Dependencies:   mbed

Revision:
0:71d791204057
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Tue Jun 07 13:32:20 2011 +0000
@@ -0,0 +1,162 @@
+#include "mbed.h"
+#include <vector>
+#include "MODSERIAL.h"
+
+DigitalOut  led[4] = { LED1, LED2, LED3, LED4 };
+MODSERIAL   SL[] = { MODSERIAL( p28, p27, 32, 256 ),
+                     MODSERIAL( p13, p14, 32, 256 ),
+                     MODSERIAL(  p9, p10, 32, 256 )
+                   };
+Timer       tempo;
+bool        HasBank, HasData, HasSysx; // flags to know if special type messages have a route defined. If not, these will be treated as plain cc or not stored.
+
+int AvailableMemory()
+{
+    register int low = 0;
+    register int mid = 0;
+    register int high = 8001;
+    void* p = NULL;
+    
+    while( high - low > 1 ) 
+        if( ( p = malloc( mid = ( low + high ) / 2 ) ) == NULL )
+            high = mid;
+        else 
+        {
+            free( p );
+            low = mid;
+        }
+    return low;
+}
+
+#include "midi.h"
+#include "stack.h"
+
+#include "memory.h"
+MemList     ML;
+
+#include "filter.h"
+FilterList  FL;
+
+#include "parse.h"
+
+byte        Last[] = {0,0,0}; // last message type for ports 1,2,3
+MidiM*      Previous[3][17] = {
+                {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL},
+                {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL},
+                {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}
+            }; // keep previous per channel 0-15 or not channeled 16, and per port. Call to Route must use Previous from same channel & port than Current.
+
+void Data_in( int port /* 0,1,2*/ ) 
+{ 
+    int     v           = SL[port].getc();
+    if( v == 0xFE ) return; // active sensing
+    
+    led[port] = 1;
+
+    MidiM*  current     = NULL;
+    int     beforelast  = Last[port]; // backup in case of incomplete message
+    // new command
+    if( v > 0x7F ) // with explicit command
+        current = MidiCreateMessage( Last[port] = v );
+    else if( Last[port] ) // with implicit command (same than before)
+    {
+        current = MidiCreateMessage( Last[port]  );
+        current->Append( v );
+    }
+    else // this is junk
+    {
+        led[port] = 0;
+        return;
+    }
+    int ch = current->Channel == NAKW ? 16 : current->Channel;
+
+    while( current->Next != NONE )
+    {
+        tempo.reset();
+        tempo.start();
+        while( SL[port].rxBufferEmpty() )
+        {
+            if( tempo.read_us() > 512 ) // normal rate should 256 us beetwen bytes. If twice that,  assume message end is lost.
+            {
+                if( current->Type==BANK || current->Type==DATA || current->Type==RPN_ || current->Type==NRPN ) // LSB may be skipped
+                { 
+                    current->Next = NONE;
+                    break; 
+                }
+                // else, abort reading this message without transmission
+                tempo.stop();
+                Last[port] = beforelast; // forget last received command
+                delete current;
+                current = NULL;
+                led[port] = 0;
+                return;
+            }
+        }
+        tempo.stop();
+        
+        if( current->Next != NONE ) 
+        {
+            int b = SL[port].getcNb();
+            if( ( b > -1 )  &&  ( b < 0xF8 ) ) // to ignore real time messages
+            {
+                if( ! current->Append( b ) )
+                {
+                // not a pair message (for example: NRPN lsb not followed by msb but by DATA)
+                    if( current->Type==RPN_ || current->Type==NRPN || current->Type==BANK )
+                    {
+                        if( Previous[ ch ][port] != NULL ) delete Previous[ ch ][port];
+                        Previous[ ch ][port] = current;
+                        current = MidiCreateMessage( Last[port]  );
+                        if( current->Next != NONE ) 
+                            current->Append( b );
+                    }
+                }
+            }
+        }
+    }
+    // now message is complete (or LSB/MSB from compound message will not follow)
+    led[port] = 0;
+    
+    FL.Route( port, *current, *(Previous[ current->Channel == NAKN ? 16 : current->Channel ][port]) ); // pass also 'previous' in case of multipart messages (RPN|NRP)+(DATA|INC|DEC)
+    if( current->Type != DATA && current->Type != INCR && current->Type != DECR )
+    {
+        if( Previous[ ch ][port] != NULL ) delete Previous[ ch ][port];
+        Previous[ ch ][port] = current;
+        current = NULL;
+    }
+    else
+        delete current;
+
+}
+
+void Blinking( int ntimes )
+{
+    if( ntimes )
+    {
+        for( int i = 0 ; i < ntimes ; i++ )
+        {
+            led[3] = 1;
+            wait(0.2);
+            led[3] = 0;
+            wait(0.6);
+        }
+        wait(2);
+    }
+}
+
+int main()
+{
+    for( int i = 0 ; i < 3 ; i++ ) SL[i].baud( 31250 );
+    
+    if( ! Parse() )
+    {
+        Blinking(ParseError);
+        return 0;
+    }
+
+    while(1)
+    {
+        for( int i = 0 ; i < 3 ; i++ ) if( SL[i].readable() ) Data_in(i);
+    }
+
+}