Bernard Escaillas
/
MidiTee
main.cpp
- Committer:
- Midimetric
- Date:
- 2011-06-07
- Revision:
- 0:71d791204057
File content as of revision 0:71d791204057:
#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); } }