Chuck Timber / Mbed 2 deprecated Gemphet8

Dependencies:   MIDI REnc button mbed

Revision:
1:2760654d0b44
Parent:
0:3dc89ac1495f
Child:
3:153322cb84f6
Child:
4:c18cfcad2c48
Child:
5:7d7be4c72d21
Child:
6:16aa8fc30ef8
--- a/main.cpp	Sat Aug 09 02:11:18 2014 +0000
+++ b/main.cpp	Sat Aug 09 02:17:53 2014 +0000
@@ -12,8 +12,52 @@
 //#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
-#include "midi_proc.h"
+
+/** @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,
@@ -21,10 +65,6 @@
     0,0,0,0,0,0,0,64,0,0,127,0,32,127,0,0,64,32,
 };
 
-// LED (active HIGH)
-#define dbg_led_on()        { }
-#define dbg_led_off()       { }
-
 DigitalOut myled(LED1);
 MIDI midi(dp16, dp15);
 
@@ -47,3 +87,125 @@
     }
 }
 
+/// @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;
+        }
+    }
+}