12-polyphonic "chiptune" MIDI synthesizer for LPC1768 (Standalone version)
Dependencies: ClockControl PowerControl mbed
parser.cpp
- Committer:
- kayekss
- Date:
- 2014-12-09
- Revision:
- 5:7bc917d03bd6
- Parent:
- 1:5f0c89bffec1
File content as of revision 5:7bc917d03bd6:
#include <stdarg.h> #include "mbed.h" #include "defs.h" #include "RingBuffer.h" #include "debug.h" #include "events.h" #include "parser.h" extern Serial console; extern bool serSource; extern dumpmode_t dumpMode; char const sysExGmSystemOn[6] = { 0xf0, 0x7e, 0x7f, 0x09, 0x01, 0xf7 }; char const sysExGsReset[11] = { 0xf0, 0x41, 0x10, 0x42, 0x12, 0x40, 0x00, 0x7f, 0x00, 0x41, 0xf7 }; char const sysExXgSystemOn[9] = { 0xf0, 0x43, 0x10, 0x4c, 0x00, 0x00, 0x7e, 0x00, 0xf7 }; void parseMessage(RingBuffer<char>& buffer) { static char lastStatusByte; char c; char messageBytes[3]; char sysExBuffer[SYSEX_BUFFER_LENGTH]; bool runningStatus = false; c = *buffer.peek(); // Running status if (!(c & 0x80)) { runningStatus = true; // Restore previous status byte c = lastStatusByte; } switch (c & 0xf0) { case 0x80: // Note off if (buffer.getItemCount() >= 3 - runningStatus) { messageBytes[0] = runningStatus ? c : *buffer.read(); for (uint8_t i = 1; i < 3; i++) { messageBytes[i] = *buffer.read(); } if (dumpMode == DUMP_EVENTS) { console.printf("%-19s %c%02X %02X %02Xh\r\n", "Note off", runningStatus ? '*' : ' ', messageBytes[0], messageBytes[1], messageBytes[2]); } dispatchNoteOff(messageBytes); lastStatusByte = c; } break; case 0x90: // Note on if (buffer.getItemCount() >= 3 - runningStatus) { messageBytes[0] = runningStatus ? c : *buffer.read(); for (uint8_t i = 1; i < 3; i++) { messageBytes[i] = *buffer.read(); } if (dumpMode == DUMP_EVENTS) { console.printf("%-19s %c%02X %02X %02Xh\r\n", "Note on", runningStatus ? '*' : ' ', messageBytes[0], messageBytes[1], messageBytes[2]); } if (messageBytes[2] == 0x00) { dispatchNoteOff(messageBytes); } else { dispatchNoteOn(messageBytes); } lastStatusByte = c; } break; case 0xa0: // Polyphonic pressure // Not supported if (buffer.getItemCount() >= 3 - runningStatus) { messageBytes[0] = runningStatus ? c : *buffer.read(); for (uint8_t i = 1; i < 3; i++) { messageBytes[i] = *buffer.read(); } if (dumpMode == DUMP_EVENTS) { console.printf("%-19s %c%02X %02X %02Xh\r\n", "Poly pressure", runningStatus ? '*' : ' ', messageBytes[0], messageBytes[1], messageBytes[2]); } lastStatusByte = c; } break; case 0xb0: // Control change if (buffer.getItemCount() >= 3 - runningStatus) { messageBytes[0] = runningStatus ? c : *buffer.read(); for (uint8_t i = 1; i < 3; i++) { messageBytes[i] = *buffer.read(); } if (dumpMode == DUMP_EVENTS) { console.printf("%-19s %c%02X %02X %02Xh\r\n", "Control change", runningStatus ? '*' : ' ', messageBytes[0], messageBytes[1], messageBytes[2]); } switch (messageBytes[1]) { case 0x78: // All sound off case 0x7b: // All note off allNoteOff(messageBytes); break; case 0x79: // Reset all controllers resetAllControllers(messageBytes); break; default: sendControlChange(messageBytes); break; } lastStatusByte = c; } break; case 0xc0: // Program change if (buffer.getItemCount() >= 2 - runningStatus) { messageBytes[0] = runningStatus ? c : *buffer.read(); for (uint8_t i = 1; i < 2; i++) { messageBytes[i] = *buffer.read(); } if (dumpMode == DUMP_EVENTS) { console.printf("%-19s %c%02X %02X __h\r\n", "Program change", runningStatus ? '*' : ' ', messageBytes[0], messageBytes[1]); } sendProgramChange(messageBytes); lastStatusByte = c; } break; case 0xd0: // Channel pressure // Not supported if (buffer.getItemCount() >= 2 - runningStatus) { messageBytes[0] = runningStatus ? c : *buffer.read(); for (uint8_t i = 1; i < 2; i++) { messageBytes[i] = *buffer.read(); } if (dumpMode == DUMP_EVENTS) { console.printf("%-19s %c%02X %02X __h\r\n", "Ch pressure", runningStatus ? '*' : ' ', messageBytes[0], messageBytes[1]); } lastStatusByte = c; } break; case 0xe0: // Pitch bend if (buffer.getItemCount() >= 3 - runningStatus) { messageBytes[0] = runningStatus ? c : *buffer.read(); for (uint8_t i = 1; i < 3; i++) { messageBytes[i] = *buffer.read(); } if (dumpMode == DUMP_EVENTS) { console.printf("%-19s %c%02X %02X %02Xh\r\n", "Pitch bend", runningStatus ? '*' : ' ', messageBytes[0], messageBytes[1], messageBytes[2]); } sendPitchBend(messageBytes); lastStatusByte = c; } break; case 0xf0: switch (c) { case 0xf0: // SysEx message if (buffer.find(0xf7) == -1) { break; } // Extract "F0 ** F7h" message block from buffer extractSysExMessage(buffer, sysExBuffer); if (strncmp(sysExBuffer, sysExGmSystemOn, 6) == 0) { // Matches "GM System On" SysEx message if (dumpMode == DUMP_EVENTS) { console.printf("SysEx message: GM System On\r\n"); } sendSystemReset(); } else if (strncmp(sysExBuffer, sysExGsReset, 11) == 0) { // Matches "GS Reset" SysEx message if (dumpMode == DUMP_EVENTS) { console.printf("SysEx message: GS Reset\r\n"); } sendSystemReset(); } else if (strncmp(sysExBuffer, sysExXgSystemOn, 9) == 0) { // Matches "XG System On" SysEx message if (dumpMode == DUMP_EVENTS) { console.printf("SysEx message: XG System On\r\n"); } sendSystemReset(); } else { if (dumpMode == DUMP_EVENTS) { console.printf("Unsupported SysEx message\r\n"); } } break; case 0xf1: // MTC quarter frame case 0xf3: // Song select // Not supported buffer.read(); buffer.read(); break; case 0xf2: // Song position // Not supported buffer.read(); buffer.read(); buffer.read(); break; case 0xf4: case 0xf5: case 0xf9: case 0xfd: // Undefined case 0xf6: // Tune request case 0xfa: // Start case 0xfb: // Continue case 0xfc: // Stop buffer.read(); break; case 0xfe: // Active sensing buffer.read(); break; case 0xff: // System reset // Discard message buffer.read(); sendSystemReset(); } } } uint32_t extractSysExMessage(RingBuffer<char>& buffer, char* msg) { uint32_t extractedLength; char* c = NULL; // Check if the first byte matches SysEx start byte (0xf0) c = buffer.read(); if (!c) return 0; if (*c != 0xf0) { return 0; } else { msg[0] = *c; } // Read buffer until reaching SysEx end byte (0xf7) extractedLength = 1; while (extractedLength < SYSEX_BUFFER_LENGTH) { c = buffer.read(); if (!c) break; msg[extractedLength++] = *c; if (*c == 0xf7) return extractedLength; } return 0; }