KAMUI USB HOST MIDI-CV Example based on Peter Barrett's BlueUSB

Dependencies:   TextLCD mbed

Revision:
0:3b4e3e2ec6a5
diff -r 000000000000 -r 3b4e3e2ec6a5 midi_parser.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/midi_parser.c	Fri May 11 15:31:59 2012 +0000
@@ -0,0 +1,258 @@
+//-------------------------------------------------------------
+// file : midi_parser.c
+// Copyright (C) 2012 RJB RadioJunkBox
+// Released under the MIT License: http://mbed.org/license/mit
+//-------------------------------------------------------------
+
+#include "mbed.h"
+#include "midi_parser.h"
+
+//-------------------------------------------------------------
+// MIDI Parser
+
+void MIDI_Parser(unsigned char mididata)
+{
+    RxByte = mididata;
+
+    if(MIDI_SystemMessage()) {
+        MIDI_ChannelMessage();
+    }
+}
+
+//-------------------------------------------------------------
+// MIDI System Meassage
+
+int MIDI_SystemMessage(void)
+{
+    if(SysEx){
+        if(RxByte == MIDI_EndSysEx){
+            SysEx = FALSE;
+        }
+    }
+    else{
+        if(RxByte < 0xF8){
+            if(RxByte > 0x7F){
+                if(RxByte == MIDI_StartSysEx){
+                    SysEx = TRUE;
+                }
+                else{
+                    MidiCh = RxByte & 0x0F;
+                }
+                PC = 0;
+             }
+            else{
+                MByte[PC & 0x01] = RxByte;
+            }
+            return TRUE;
+        }
+        else {
+            MIDI_SystemRealtimeMessage();
+        }
+    }
+    return FALSE;
+}
+
+//-------------------------------------------------------------
+// MIDI System Realtime Message
+
+void MIDI_SystemRealtimeMessage(void)
+{
+    switch(RxByte) {
+        case MIDI_TimingClock:
+            gMIDISYNC_CLK |= 0x01;
+            break;
+        case MIDI_Start:
+            gMIDISYNC_RUN = 0x01;
+            break;
+        case MIDI_Continue:
+            gMIDISYNC_RUN = 0x01;
+            break;
+        case MIDI_Stop:
+            gMIDISYNC_RUN = 0x00;
+            break;
+        case MIDI_ActiveSensing:
+            break;
+        case MIDI_SystemReset:
+            break;
+    }
+}
+
+//-------------------------------------------------------------
+// MIDI Channel Message
+
+void MIDI_ChannelMessage(void)
+{
+    switch(PC){
+        case 0:
+            switch(RxByte & 0xF0){
+            case MIDI_NoteOff:
+                PC = 2;
+                break;
+            case MIDI_NoteOn:
+                PC = 4;
+                break;
+            case MIDI_PolykeyPressure:
+                PC = 6;
+                break;
+            case MIDI_ProgramChange:
+                PC = 8;
+                break;
+            case MIDI_ControlChange:
+                PC = 10;
+                break;
+            case MIDI_ChannelPressure:
+                PC = 12;
+                break;
+            case MIDI_PitchBend:
+                PC = 14;
+                break;
+            } break;
+
+        // Note OFF
+        case 2:
+            PC = 3;
+            break;
+        case 3:
+            PC = 2;
+            NoteOFF();
+            break;
+
+        // Note ON
+        case 4:
+            PC = 5;
+            break;
+        case 5:
+            PC = 4;
+            if( MByte[1] == 0){
+                NoteOFF();
+            }
+            else{
+                NoteON();
+            }
+            break;
+
+        // Polyphonic Key Pressure
+        case 6:
+            PC = 7;
+            break;
+        case 7:
+            PC = 6;
+            break;
+
+        // Program Change
+        case 8:
+            break;
+
+        // Control Change
+        case 10: PC = 11; break;
+        case 11:
+            switch(MByte[0]) {
+                case MIDI_CC_Moduration:
+                    gModWheelBuf[MidiCh] = MByte[1] >> 2;
+                    break;
+                case MIDI_CC_DataEntry:
+                    break;
+                case MIDI_CC_RPN_LSB:
+                    break;
+                case MIDI_CC_RPN_MSB:
+                    break;
+                case MIDI_MM_AllSoundOff:
+                    break;
+                case MIDI_MM_ResetAllControl:
+                    break;
+                case MIDI_MM_AllNoteOff:
+                    break;
+            }
+            break;
+
+        // Channel Pressure
+        case 12:
+            break;
+
+        // Pitch Bend
+        case 14:
+            PC = 15;
+            break;
+            
+        case 15:
+            PC = 14;
+            gPitchBendBuf[MidiCh] = (MByte[1] << 1) | (MByte[0] >> 6);
+            break;
+
+        default:
+            break;
+    }
+}
+
+//-------------------------------------------------------------
+// Note ON Message Processing
+
+void NoteON(void)
+{
+    unsigned char i;
+    unsigned char h = 0; // higheest note
+
+    // ignore note if registed buffer
+    for(i = 0; i < NoteCnt[MidiCh]; i++) {
+        if(NoteBuf[MidiCh][i] == MByte[0]) {
+            return;
+        }
+    }
+
+    // full note buffer?
+    if(NoteCnt[MidiCh] == MAX_NOTE_CNT) {
+        for(i = 0; i < (MAX_NOTE_CNT - 1); i++) {
+            NoteBuf[MidiCh][i] = NoteBuf[MidiCh][i+1];
+        }
+        NoteBuf[MidiCh][MAX_NOTE_CNT - 1] = MByte[0];
+    }
+    else {
+        NoteBuf[MidiCh][NoteCnt[MidiCh]] = MByte[0];
+        NoteCnt[MidiCh]++;
+    }
+
+    // set highest note
+    for(i = 0; i < NoteCnt[MidiCh]; i++) {
+        if(h < NoteBuf[MidiCh][i]) {
+            h = NoteBuf[MidiCh][i];
+        }
+    }
+    gPlayNoteBuf[MidiCh] = h;
+    gGateBuf[MidiCh] = ON;
+}
+
+//-------------------------------------------------------------
+// Note OFF Message Processing
+
+void NoteOFF(void)
+{
+    unsigned char i;
+    unsigned char h = 0; // highest note
+    int flg = FALSE;
+
+    // Delete Note If Registed Buffer
+    for(i = 0; i < NoteCnt[MidiCh]; i++) {
+        if(flg) {
+            NoteBuf[MidiCh][i-1] = NoteBuf[MidiCh][i];
+        }
+        if(NoteBuf[MidiCh][i] == MByte[0]) {
+            flg = TRUE;
+        }
+    }
+    if(flg) NoteCnt[MidiCh]--;
+
+    if(NoteCnt[MidiCh] == 0) {
+        // Empty Buffer then Gate OFF
+        gGateBuf[MidiCh] = OFF;
+    }
+    else {
+        // Highest Note
+        for(i = 0; i < NoteCnt[MidiCh]; i++) {
+            if( h < NoteBuf[MidiCh][i]) {
+                h = NoteBuf[MidiCh][i];
+            }
+        }
+        gPlayNoteBuf[MidiCh] = h;
+    }
+}
+