Bernard Escaillas
/
MidiTee
Diff: main.cpp
- 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); + } + +}