MIDI interpreter using mbed
Dependencies: MIDI TextLCD mbed
parser.cpp
- Committer:
- kayekss
- Date:
- 2013-06-14
- Revision:
- 1:af9dd50ffbc2
- Parent:
- 0:93868ff6d1b1
File content as of revision 1:af9dd50ffbc2:
#include "mbed.h" #include "define.h" #include "RingBuffer.h" #include "events.h" #include "parser.h" extern BusOut obLeds; #ifdef USE_PC_SERIAL extern Serial pc; #endif 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 dataBytes[2]; 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.items() >= 3 - runningStatus) { if (!runningStatus) buffer.read(); for (uint8_t i = 0; i < 2; i++) { dataBytes[i] = *buffer.read(); } #ifdef USE_PC_SERIAL pc.printf("%-19s %c%02X %02X %02Xh\r\n", "Note off", runningStatus ? '*' : ' ', c, dataBytes[0], dataBytes[1]); #endif dispatchNoteOff(c, dataBytes[0]); lastStatusByte = c; } break; case 0x90: /* Note on */ if (buffer.items() >= 3 - runningStatus) { if (!runningStatus) buffer.read(); for (uint8_t i = 0; i < 2; i++) { dataBytes[i] = *buffer.read(); } #ifdef USE_PC_SERIAL pc.printf("%-19s %c%02X %02X %02Xh\r\n", "Note on", runningStatus ? '*' : ' ', c, dataBytes[0], dataBytes[1]); #endif if (dataBytes[1] == 0x00) { dispatchNoteOff(c, dataBytes[0]); } else { dispatchNoteOn(c, dataBytes[0], dataBytes[1]); } lastStatusByte = c; } break; case 0xa0: /* Polyphonic pressure */ // Not supported if (buffer.items() >= 3 - runningStatus) { if (!runningStatus) buffer.read(); for (uint8_t i = 0; i < 2; i++) { dataBytes[i] = *buffer.read(); } #ifdef USE_PC_SERIAL pc.printf("%-19s %c%02X %02X %02Xh\r\n", "Poly pressure", runningStatus ? '*' : ' ', c, dataBytes[0], dataBytes[1]); #endif lastStatusByte = c; } break; case 0xb0: /* Control change */ if (buffer.items() >= 3 - runningStatus) { if (!runningStatus) buffer.read(); for (uint8_t i = 0; i < 2; i++) { dataBytes[i] = *buffer.read(); } #ifdef USE_PC_SERIAL pc.printf("%-19s %c%02X %02X %02Xh\r\n", "Control change", runningStatus ? '*' : ' ', c, dataBytes[0], dataBytes[1]); #endif setControlChange(c, dataBytes[0], dataBytes[1]); lastStatusByte = c; } break; case 0xc0: /* Program change */ if (buffer.items() >= 3 - runningStatus) { if (!runningStatus) buffer.read(); for (uint8_t i = 0; i < 2; i++) { dataBytes[i] = *buffer.read(); } #ifdef USE_PC_SERIAL pc.printf("%-19s %c%02X %02X __h\r\n", "Program change", runningStatus ? '*' : ' ', c, dataBytes[0]); #endif setProgramChange(c, dataBytes[0]); lastStatusByte = c; } break; case 0xd0: /* Channel pressure */ // Not supported if (buffer.items() >= 3 - runningStatus) { if (!runningStatus) buffer.read(); for (uint8_t i = 0; i < 2; i++) { dataBytes[i] = *buffer.read(); } #ifdef USE_PC_SERIAL pc.printf("%-19s %c%02X %02X __h\r\n", "Ch pressure", runningStatus ? '*' : ' ', c, dataBytes[0]); #endif lastStatusByte = c; } break; case 0xe0: /* Pitch bend */ if (buffer.items() >= 3 - runningStatus) { if (!runningStatus) buffer.read(); for (uint8_t i = 0; i < 2; i++) { dataBytes[i] = *buffer.read(); } #ifdef USE_PC_SERIAL pc.printf("%-19s %c%02X %02X %02Xh\r\n", "Pitch bend", runningStatus ? '*' : ' ', c, dataBytes[0], dataBytes[1]); #endif setPitchBend(c, dataBytes[1] << 7 | dataBytes[0]); lastStatusByte = c; } break; case 0xf0: switch (c) { case 0xf0: /* SysEx message */ if (buffer.find(0xf7) == -1) { break; } extractSysExMessage(buffer, sysExBuffer); if (strncmp(sysExBuffer, sysExGmSystemOn, 6) == 0) { // Matches "GM System On" SysEx message #ifdef USE_PC_SERIAL pc.printf("SysEx message: GM System On\r\n"); #endif obLeds = 0x1; } else if (strncmp(sysExBuffer, sysExGsReset, 11) == 0) { // Matches "GS Reset" SysEx message #ifdef USE_PC_SERIAL pc.printf("SysEx message: GS Reset\r\n"); #endif obLeds = 0x2; } else if (strncmp(sysExBuffer, sysExXgSystemOn, 9) == 0) { // Matches "XG System On" SysEx message #ifdef USE_PC_SERIAL pc.printf("SysEx message: XG System On\r\n"); #endif obLeds = 0x2; } else { #ifdef USE_PC_SERIAL pc.printf("Unsupported SysEx message\r\n"); #endif } break; case 0xf1: /* MTC quarter frame */ case 0xf3: /* Song select */ // Not supported buffer.read(); buffer.read(); obLeds = 0x0; break; case 0xf2: /* Song position */ // Not supported buffer.read(); buffer.read(); buffer.read(); obLeds = 0x0; 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(); obLeds = 0x0; break; case 0xfe: /* Active sensing */ break; case 0xff: /* System reset */ // Discard message (@todo) buffer.read(); obLeds = 0x0; } } } 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; }