Chuck Timber / Mbed 2 deprecated Gemphet8

Dependencies:   MIDI REnc button mbed

main.cpp

Committer:
ChuckTimber
Date:
2014-08-09
Revision:
1:2760654d0b44
Parent:
0:3dc89ac1495f
Child:
3:153322cb84f6
Child:
4:c18cfcad2c48
Child:
5:7d7be4c72d21
Child:
6:16aa8fc30ef8

File content as of revision 1:2760654d0b44:

/**
 *  @file       main.cpp
 *  Project     Gem8 - handles 8-gembox synth project application
 *  @brief      Gem8 project application
 *  @version    1.0
 *  @author     Chuck Timber
 *  @date       08/08/2014
 */
 
#include "mbed.h"
//#include "button.h"
//#include "REnc.h"
#include "MIDI.h"


// LED (active HIGH)
#define dbg_led_on()        { }
#define dbg_led_off()       { }


/** MIDI System message */
#define MIDI_ALL_NOTE_OFF             0x7B
#define MIDI_RESET_ALL_CONTROLLERS    0x79

#define POLYPHONICE_NOTES 8

/** @structure MIDI Note management structure
 *
 */
struct _MidiNote {
    /// MIDI Note number
    uint8_t Note;
    /// MIDI Note velocity
    uint8_t Velocity;
    /// MIDI Note channel
    uint8_t Channel;
    /// pointer to the next _MidiNote object
    struct _MidiNote *next;
};

struct _MidiNote NoteEnd = { 255, 255, 15, 0 };
struct _MidiNote NoteStart = { 0, 0, 0, &NoteEnd };
struct _MidiNote MidiNotes[POLYPHONICE_NOTES];
static uint16_t MidiNotesTag;

volatile static uint8_t NumOfNotes = POLYPHONICE_NOTES;

/** @brief Prototypes related to MIDI
 *
 */
struct _MidiNote *allocN(void);
void freeN(struct _MidiNote *addr);
void midi_allnoteoff(void);
void midi_resetcontrol(void);
void midi_sysreset(void);
void midi_noteoff(byte channel, byte note, byte velocity);
void midi_noteon(byte channel, byte note, byte velocity);
void midi_cc(byte channel, byte number, byte value);
void midi_pc(byte channel, byte number);
void midi_pbend(byte channel, int bend);

uint8_t midi_params[]={
    0,0,0,0,0,0,0,100,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,64,0,0,127,0,32,127,0,0,64,32,
};

DigitalOut myled(LED1);
MIDI midi(dp16, dp15);


int main() {
    
    midi.setHandleNoteOff(&midi_noteoff);
    midi.setHandleNoteOn(&midi_noteon);
    midi.setHandleControlChange(&midi_cc);
    midi.setHandleProgramChange(&midi_pc);
    midi.setHandlePitchBend(&midi_pbend);
    midi.setHandleSystemReset(&midi_sysreset);
    
    
    while(1) {
        myled = 1;
        wait(0.2);
        myled = 0;
        wait(0.2);
    }
}

/// @brief  Reset all MIDI controller
static void midi_allnoteoff(void)
{
    int i;
    uint16_t msk;

    for (i = 0, msk = 0x01; i < NumOfNotes; i++, msk<<=1) {
        if (MidiNotesTag & msk) {
            midi.sendNoteOff(MidiNotes[i].Note, MidiNotes[i].Velocity, MidiNotes[i].Channel);
            MidiNotesTag &= ~msk;           
        }
    }

    MidiNotesTag = 0x0000;
    NoteEnd.next = NULL;
    NoteStart.next = &NoteEnd;
}

/// @brief  Reset MIDI controller
static void midi_resetcontrol(void)
{
}

/// @brief  Reset all MIDI controller
void midi_sysreset(void)
{
    midi_allnoteoff();
    midi_resetcontrol();
}

/// @brief  MIDI note structure allocate function
static struct _MidiNote *allocN(void)
{
    int i;
    uint16_t msk;

    for (i = 0, msk = 0x01; i < NumOfNotes; i++, msk<<=1) {
        if (!(MidiNotesTag & msk)) {
            MidiNotesTag |= msk;
            MidiNotes[i].Channel = i;
            return (&MidiNotes[i]);
        }
    }
    return NULL;
}

/// @brief  MIDI note structure free function
static void freeN(struct _MidiNote *addr)
{
    int i;
    uint16_t msk;

    for (i = 0, msk = 0x01; i < NumOfNotes; i++, msk<<=1) {
        if (addr == &MidiNotes[i]) 
            MidiNotesTag &= ~msk;
    }
}

/// @brief  MIDI Control Change callback funcion
void midi_cc(byte channel, byte number, byte value)
{
    if (number == MIDI_ALL_NOTE_OFF) {
        midi_allnoteoff();
    }
    if (number == MIDI_RESET_ALL_CONTROLLERS) {
        midi_resetcontrol();
    }
    midi.sendControlChange(number, value, channel);
}

/// @brief  MIDI Program Change callback funcion
void midi_pc(byte channel, byte number)
{
    midi.sendProgramChange(number, channel);
}

/// @brief  MIDI Pitch Bend callback funcion
void midi_pbend(byte channel, int bend)
{
    midi.sendPitchBend(bend, channel);
}

/// @brief  MIDI Note On callback funcion
void midi_noteon(byte channel, byte note, byte velocity)
{
    struct _MidiNote *ptr, *newnote;

    if ((newnote = allocN()) == NULL) { // if table full, release oldest note
        ptr = NoteStart.next;
        midi.sendNoteOff(ptr->Note, ptr->Velocity, ptr->Channel);
        NoteStart.next = ptr->next;
        freeN(ptr);
        newnote = allocN();
    }
    newnote->Note = note;
    newnote->Velocity = velocity;
    // newnote->Channel // do not set channel
    midi.sendNoteOn(note, velocity, newnote->Channel);
    for (ptr = &NoteStart; ptr->next; ptr = ptr->next) {    // put newnote on the tail
        if (ptr->next == &NoteEnd) {
            newnote->next = ptr->next;
            ptr->next = newnote;
            break;
        }
    }
}

/// @brief  MIDI Note Off callback funcion
void midi_noteoff(byte channel, byte note, byte velocity)
{
    struct _MidiNote *ptr, *lastptr;

    for (ptr = &NoteStart; ptr->next; ptr = ptr->next) {
        if (note == ptr->next->Note) {
            lastptr = ptr->next;
            midi.sendNoteOff(lastptr->Note, lastptr->Velocity, lastptr->Channel);
            ptr->next = lastptr->next;
            freeN(lastptr);
            break;
        }
    }
}