KAMUI MIDI-CV Example

Dependencies:   TextLCD mbed

midi_parser.c

Committer:
radiojunkbox
Date:
2012-05-05
Revision:
0:25a282f1141a

File content as of revision 0:25a282f1141a:

//-------------------------------------------------------------
// KAMUI MIDI-CV Exapmle
// 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;
    }
}