Revision 0:71d791204057, committed 2011-06-07
- Comitter:
- Midimetric
- Date:
- Tue Jun 07 13:32:20 2011 +0000
- Commit message:
- Version 1.0
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/MODSERIAL.lib Tue Jun 07 13:32:20 2011 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/AjK/code/MODSERIAL/#af2af4c61c2f
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/filter.h Tue Jun 07 13:32:20 2011 +0000
@@ -0,0 +1,471 @@
+#include <vector>
+#include "midi.h"
+#include "stack.h"
+#include "memory.h"
+
+#define TO_OUT1 1
+#define TO_OUT2 2
+#define TO_OUT3 4
+
+#define BitSet( flag, bit ) ( ( flag >> bit ) & 1 )
+#define BitPut( flag, bit ) ( flag | ( 1 << bit ) )
+#define BitDel( flag, bit ) ( flag & ~( 1 << bit ) )
+
+// literals are either 8 bits ( 0 to 255 ) or 14 bits ( 0 to 16383 / -8192 to 8191 )
+// commands are coded with bit 14 set (above 16383 ) but not with bit 15 to leave negative down to -8192 to literals and to avoid ambiguity
+
+#define ISCOMMAND(x) ( (x & 0xF000) == 0x4000 )
+
+// sequence delimiter
+#define SEQ 0x4000 // escape; introducing a sequence in a Chain:
+#define E7_ 0x4001 // return 7 bits byte from computation
+#define E8_ 0x4002 // return 8 bits byte from computation
+#define E14 0x4003 // return 14 bits word from computation (msb then lsb)
+#define NOP 0x4004 // nul terminator in sequence array
+#define RAW 0x4005 // output is raw input (no change)
+// VALUES
+#define VMC 0x4010 // =%mc Full midi command (base command + channel), can be used in sequence or alone
+#define VM_ 0x4011 // =%m Base midi command (4 msb of VMC ), can be used in sequence or alone
+#define VC_ 0x4012 // =%c Value of Channel (4 lsb of VMC )
+#define VA_ 0x4013 // Value A, can be used in sequence or alone
+#define VB_ 0x4014 // Value B
+#define VN_ 0x4015 // RPN or NRPN 14bits number
+#define VD_ 0x4016 // RPN or NRPN 14bits data
+#define VK_ 0x4017 // Bank 14bits data
+
+// FUNCTIONS
+#define ADD 0x4020
+#define SUB 0x4021 // Add 14 bits value as signed integer, bound to 0 - 0xFFFF
+#define MUL 0x4022
+#define DIV 0x4023
+#define MOD 0x4024
+#define BIT 0x4125 // folowing int is index value then bit shift then bits count
+#define BOR 0x4026 // bynary OR
+#define BAN 0x4027 // bynary AND
+#define BNO 0x4028 // bynary NOT
+#define BSL 0x4029 // bynary shift left (<<)
+#define BSR 0x402A // bynary shift right (>>)
+#define MAP 0x402B // discrete value mapping
+#define RPN 0x402C // RPN type formated output
+#define NPN 0x402D // NRPN type formated output
+#define BNK 0x402E // Bank type formated output
+#define MSB 0x402F // msb part of value
+#define LSB 0x4030 // lsb part of value
+#define NP8 0x4031 // 8 bit value NRPN (sends only CC6 not CC38)
+
+// checkSUm
+// - compute checksum from value after 'SUB' to value before 'SUE'
+#define CSB 0x4040 // checkSUm Begin
+#define CSE 0x4041 // checkSUm End
+#define CS1 0x4042 // insert 8 bit checksum at position (careful:may appear before SUB-SUE range)
+#define CS2 0x4043 // 32 bits checksum
+// Checksum Type1 (Roland) : -( sum( SUB -> SUE ) & 127 ) & 127
+// Checksum Type2 (Alesis) : -( sum( SUB -> SUE ) & 0xFFFF ) & 0xFFFF
+
+// custom identifiers
+#define CID 0x4100 // end of Custom IDentifier
+// 0x41cc // cc = ascii char index
+#define CUL 0x4200 // Custom identifier character set Upper Limit
+
+#if _DEBUGFILTER
+#include "filter_debug.h"
+#endif
+
+// error codes returned by Compute
+#define CHAIN_SKIPROUTE -1
+#define CHAIN_NOERROR 0
+#define CHAIN_STACK_FAILURE 1
+#define CHAIN_MISSING_SUB 2
+#define CHAIN_MISSING_SUE 3
+#define CHAIN_SUB_AFTER_SUE 4
+#define CHAIN_NOT_A_BYTE 5
+#define CHAIN_UNKNOWN_OP 6
+#define CHAIN_SYNTAXE_ERROR 7
+#define CHAIN_DIVIDE_BY_ZERO 8
+
+#define NEXT i++; break;
+#define PUSH(x) Out.push_back(x)
+
+short bitmasking[] = {0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383};
+
+//_____________________________________________________________________________
+class Chain
+{//""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+// a chain defines for each port a message composed of fixed bytes or symbols
+public:
+ vector<short> Msg[3];
+ vector<byte> Out;
+
+ Chain() { }
+ Chain( vector<short> &msg1, vector<short> &msg2, vector<short> &msg3 ) { Msg[0] = msg1; Msg[1] = msg2; Msg[2] = msg3; }
+ ~Chain() { }
+
+ void Done() // clear output vector until next compute to avoid keeping computation for all filters in memory
+ {
+ Out.clear();
+ }
+ short Compute( byte port, MidiM &cur, MidiM &prev ) // 0=ok, else return error code
+ {
+ short max = Msg[port].size();
+ if( max == 0 ) return -1;
+
+ Stack<long> k;
+ long a,b,c,d; // temp
+ short i = 0; // next position in Msg
+ bool s = false; // true when "in sequence"
+ short csb = -1; // position of check sum begin
+ short cse = -1; // position of check sum end
+ short csu = 0; // position where to insert check sum
+ short cst = 0; // check sum type
+
+ Out.clear();
+
+ while( i < max )
+ {
+ short n = Msg[port][i];
+ if( ! s ) // out of sequence, expect a byte value or a custom identifier or SEQ
+ {
+ if( n < 256 ) { PUSH( (byte)n ); i++; } // just copy fixed message byte
+ else if( ! ISCOMMAND( n ) ) return CHAIN_NOT_A_BYTE; // short values are not allowed outside of sequence
+ else switch( n ) {
+ case SEQ : s = true; NEXT
+ case VMC : PUSH( cur.Command | ( cur.Channel == NAKN ? 0 : cur.Channel ) ); NEXT
+ case VM_ : PUSH( cur.Command ); NEXT
+ case VC_ : PUSH( cur.Channel == NAKN ? 0 : cur.Channel ); NEXT
+ case VA_ : PUSH( cur.ValA ); NEXT
+ case VB_ : PUSH( cur.ValB ); NEXT
+ case VN_ : PUSH( prev.ValA ); PUSH( prev.ValB ); NEXT
+ case VD_ : PUSH( cur.ValA ); PUSH( cur.ValB ); NEXT
+ case VK_ : PUSH( cur.ValA ); PUSH( cur.ValB ); NEXT
+
+ case RAW : if( ( cur.Type == DATA || cur.Type == INCR || cur.Type == DECR )
+ && ( prev.Type == NRPN || prev.Type == RPN_ ) )
+ {
+ Out = prev.Raw; Out.insert( Out.end(), cur.Raw.begin(), cur.Raw.end() );
+ }
+ else Out = cur.Raw;
+ return 0;
+
+ default : {char id[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; short idi = 0;
+ while( n > CID && n < CUL ) { id[idi++] = (char)(n - CID); n = Msg[port][++i]; }
+ PUSH( (byte)ML.Get( id ) ); } NEXT
+ }
+ }
+ else if( ! ISCOMMAND( n ) ) // 14 bit literal inside a sequence, push on stack
+ {
+ k.Push( n ); i++;
+ }
+ else switch( n )
+ {
+ case NOP : NEXT
+ case E7_ : k.Pull(a); if(a < 0) a=0; else if(a > 127) a=127; PUSH(a); s = false; NEXT
+ case E8_ : k.Pull(a); if(a < 0) a=0; else if(a > 255) a=255; PUSH(a); s = false; NEXT
+ case E14 : k.Pull(a); PUSH( (byte)(a >> 7) & 127 ); PUSH(a & 127); s = false; NEXT
+ case VMC : k.Push( cur.Command|( cur.Channel == NAKN ? 0 : cur.Channel ) ); NEXT
+ case VM_ : k.Push( cur.Command ); NEXT
+ case VC_ : k.Push( ( cur.Channel == NAKN ? 0 : cur.Channel ) ); NEXT
+ case VA_ : k.Push( cur.ValA ); NEXT
+ case VB_ : k.Push( cur.ValB ); NEXT
+ case VN_ : k.Push( prev.Get14() ); NEXT
+ case VD_ : k.Push( cur.Get14() ); NEXT
+ case VK_ : k.Push( cur.Get14() ); NEXT
+ case ADD : k.Pull( b, a ); k.Push( a + b ); NEXT
+ case SUB : k.Pull( b, a ); k.Push( a - b ); NEXT
+ case MUL : k.Pull( b, a ); k.Push( a * b ); NEXT
+ case DIV : k.Pull( b, a ); if(b==0) return CHAIN_DIVIDE_BY_ZERO; k.Push( a / b ); NEXT
+ case MOD : k.Pull( b, a ); if(b==0) return CHAIN_DIVIDE_BY_ZERO; k.Push( a % b ); NEXT
+ case BIT : k.Pull( c,b,a); k.Push(cur.Raw[a] >> b & bitmasking[c]); NEXT
+ case BOR : k.Pull( b, a ); k.Push( a | b ); NEXT
+ case BAN : k.Pull( b, a ); k.Push( a & b ); NEXT
+ case BNO : k.Pull( a ); k.Push( ~a ); NEXT
+ case BSL : k.Pull( b, a ); k.Push( a << b ); NEXT
+ case BSR : k.Pull( b, a ); k.Push( a >> b ); NEXT
+ case MSB : k.Pull( a ); k.Push( a >> 7 ); NEXT
+ case LSB : k.Pull( a ); k.Push( a & 127 ); NEXT
+ case CSB : csb=Out.size(); s = false; /*quit sequence not waiting for END*/ NEXT
+ case CSE : cse=Out.size(); s = false; NEXT
+ case CS1 : csu=Out.size(); cst=1; PUSH(0); NEXT
+ case CS2 : csu=Out.size(); cst=2; PUSH(0); PUSH(0); PUSH(0); PUSH(0); NEXT
+ case MAP : k.Pull( d, a, c, b ); d--;
+ while( a != b )
+ if( ( d -= 2 ) == 0 ) return CHAIN_SKIPROUTE;
+ else k.Pull( c, b );
+ while( d -= 2 ) k.Pull(a,b); /* unstack unused values */ k.Push( c ); NEXT
+ case NPN : k.Pull( c,b,a); a &= 15;
+ if( b > 127 ) { PUSH( 0xB0 + a ); PUSH( 99 ); PUSH( ( b >> 7 ) & 127 ); }
+ PUSH( 0xB0 + a ); PUSH( 98 ); PUSH( b & 127 );
+ PUSH( 0xB0 + a ); PUSH( 6 ); PUSH( ( c >> 7 ) & 127 );
+ PUSH( 0xB0 + a ); PUSH( 38 ); PUSH( c & 127 ); NEXT
+
+ case NP8 : k.Pull( c,b,a); a &= 15;
+ if( b > 127 ) { PUSH( 0xB0 + a ); PUSH( 99 ); PUSH( ( b >> 7 ) & 127 ); }
+ PUSH( 0xB0 + a ); PUSH( 98 ); PUSH( b & 127 );
+ PUSH( 0xB0 + a ); PUSH( 6 ); PUSH( c & 127 ); NEXT
+
+ case RPN : k.Pull( c,b,a); a &= 15;
+ if( b > 127 ) { PUSH( 0xB0 + a ); PUSH(101 ); PUSH( ( b >> 7 ) & 127 ); }
+ PUSH( 0xB0 + a ); PUSH(100 ); PUSH( b & 127 );
+ PUSH( 0xB0 + a ); PUSH( 6 ); PUSH( ( c >> 7 ) & 127 );
+ PUSH( 0xB0 + a ); PUSH( 38 ); PUSH( c & 127 ); NEXT
+
+ case BNK : k.Pull( b, a ); a &= 15;
+ if( b > 127 ) { PUSH( 0xB0 + a ); PUSH( 0 ); PUSH( ( b >> 7 ) & 127 ); }
+ PUSH( 0xB0 + a ); PUSH( 32 ); PUSH( b & 127 ); NEXT
+ default:
+ if( n <= CID && n > CID + 0xFF )return CHAIN_UNKNOWN_OP;
+ {char id[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; short idi = 0;
+ while( n > CID && n < CUL ) { id[idi++] = (char)(n - CID);
+ n = Msg[port][++i]; } k.Push( (byte)ML.Get( id ) ); } NEXT
+ }
+ }
+ c = 0;
+ if( cst )
+ {
+ if( csb == -1 ) return CHAIN_MISSING_SUB;
+ if( cse == -1 ) return CHAIN_MISSING_SUE;
+ if( csb >= cse ) return CHAIN_SUB_AFTER_SUE;
+ }
+ if( cst == 1 )
+ {
+ for( i = csb ; i < cse ; i++ )
+ c -= Out[i];
+ Out[csu]= (byte)( c & 127 );
+ }
+ if( cst == 2 )
+ {
+ for( i = csb ; i < cse ; i += 4 )
+ c -= Out[i] + ( Out[i+1] << 8 ) + ( Out[i+2] << 16 ) + ( Out[i+3] << 24 );
+ Out[csu++]= (byte)( c );
+ Out[csu++]= (byte)( c >> 8 );
+ Out[csu++]= (byte)( c >> 16 );
+ Out[csu ]= (byte)( c >> 24 );
+ }
+
+ return 0;
+ }
+};
+//_____________________________________________________________________________
+class Assignment
+{//""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+public:
+ char Name[17];
+ vector<short> Msg;
+ short Value;
+
+ Assignment() { Name[0] = 0; Value = NOP; }
+ Assignment( char* name, vector<short> &msg ) { strncpy( Name, name, 17 ); Msg = msg; Value = NOP; }
+ ~Assignment() { }
+
+ short Compute( MidiM &cur, MidiM &prev ) // 0=ok, else return error code
+ {
+ Stack<long> k;
+ long a,b,c,d; // temp
+ short i = 0; // next position in Msg
+ bool s = false; // true when "in sequence"
+
+ while( i < Msg.size() )
+ {
+ short n = Msg[i];
+ if( ! s ) // out of sequence, expect a byte value or a custom identifier or SEQ
+ {
+ if( n < 256 ) { Value = n; return 0; } // just copy fixed message byte
+ else if( ! ISCOMMAND( n ) ) return CHAIN_NOT_A_BYTE; // short values are not allowed outside of sequence
+ else switch( n ) {
+ case SEQ : s = true; NEXT
+ case VMC : Value = cur.Command | ( cur.Channel == NAKN ? 0 : cur.Channel ); return 0;
+ case VM_ : Value = cur.Command; return 0;
+ case VC_ : Value = ( cur.Channel == NAKN ? 0 : cur.Channel ); return 0;
+ case VA_ : Value = cur.ValA; return 0;
+ case VN_ : Value = prev.Get14(); return 0;
+ case VB_ : Value = cur.ValB; return 0;
+ case VD_ :
+ case VK_ : Value = cur.Get14(); return 0;
+ default : char id[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; short idi = 0;
+ while( n > CID && n < CUL ) { id[idi++] = (char)(n - CID);
+ n = Msg[i++]; } Value = ML.Get( id ); return 0;
+ }
+ }
+ else if( ! ISCOMMAND( n ) ) // 14 bit literal inside a sequence, push on stack
+ {
+ k.Push( n ); i++;
+ }
+ else switch( n )
+ {
+ case E7_ :
+ case E8_ :
+ case E14 : Value = (short)k.Pull(); return 0;
+
+ case VMC : k.Push( cur.Command|( cur.Channel == NAKN ? 0 : cur.Channel ) ); NEXT
+ case VM_ : k.Push( cur.Command ); NEXT
+ case VC_ : k.Push( ( cur.Channel == NAKN ? 0 : cur.Channel ) ); NEXT
+ case VA_ : k.Push( cur.ValA ); NEXT
+ case VB_ : k.Push( cur.ValB ); NEXT
+ case VN_ : k.Push( prev.Get14() ); NEXT
+ case VD_ :
+ case VK_ : k.Push( cur.Get14() ); NEXT
+ case ADD : k.Pull( b, a ); k.Push( a + b ); NEXT
+ case SUB : k.Pull( b, a ); k.Push( a - b ); NEXT
+ case MUL : k.Pull( b, a ); k.Push( a * b ); NEXT
+ case DIV : k.Pull( b, a ); k.Push( a / b ); NEXT
+ case MOD : k.Pull( b, a ); k.Push( a % b ); NEXT
+ case BIT : k.Pull( c,b,a); k.Push( cur.Raw[a] >> b & bitmasking[c] ); NEXT
+ case BOR : k.Pull( b, a ); k.Push( a | b ); NEXT
+ case BAN : k.Pull( b, a ); k.Push( a & b ); NEXT
+ case BNO : k.Pull( a ); k.Push( ~a ); NEXT
+ case BSL : k.Pull( b, a ); k.Push( a << b ); NEXT
+ case BSR : k.Pull( b, a ); k.Push( a >> b ); NEXT
+ case MSB : k.Pull( a ); k.Push( a >> 7 ); NEXT
+ case LSB : k.Pull( a ); k.Push( a & 127 ); NEXT
+ case MAP : k.Pull( d, a, c, b ); d--;
+ while( a != b )
+ if( ( d -= 2 ) == 0 ) { k.Push( NAKN ); NEXT }
+ else k.Pull( c, b );
+ while( d -= 2 ) k.Pull(a,b); /* unstack unused values */ k.Push( c ); NEXT
+ default:
+ if( n <= CID && n > CID + 0xFF )return CHAIN_UNKNOWN_OP;
+ {char id[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; short idi = 0;
+ while( n > CID && n < CUL ) { id[idi++] = (char)(n - CID);
+ n = Msg[++i]; } k.Push( (byte)ML.Get( id ) ); } NEXT
+ }
+ }
+ return CHAIN_SYNTAXE_ERROR;
+ }
+};
+//_____________________________________________________________________________
+class Filter
+{//""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+public:
+ byte Port; // use constants TO_OUT1...3
+ byte Type; // use constants NOTE, POLA, ... from midi.h
+ short Channel;
+ short Amin; // may be a 14 bits value for RPN, NRPN identifier
+ short Amax;
+ short Bmin; // may be a 14 bits value for RPN, NRPN value
+ short Bmax;
+ vector<byte> Head;
+ Chain Out;
+ vector<Assignment*> Assigns;
+
+ Filter() : Port(0), Type(0), Channel(NAKW), Amin(NAKN), Amax(NAKN), Bmin(NAKN), Bmax(NAKN), Head( 1, (short)0xF0 ) { }
+ ~Filter() { }
+
+ Filter( Filter & f )
+ : Port(f.Port),Type(f.Type),Channel(f.Channel),Amin(f.Amin),Amax(f.Amax),Bmin(f.Bmin),Bmax(f.Bmax)
+ {
+ Head = f.Head; Out.Msg[0] = f.Out.Msg[0]; Out.Msg[1] = f.Out.Msg[1]; Out.Msg[2] = f.Out.Msg[2]; Assigns = f.Assigns;
+ }
+
+ Filter( byte p, byte t, short c, short ai, short ax, short bi, short bx, vector<byte> &head, vector<short> &o1, vector<short> &o2, vector<short> &o3, vector<Assignment*> &assigns )
+ : Port(p), Type(t), Channel(c), Amin(ai), Amax(ax), Bmin(bi), Bmax(bx)
+ {
+ Head = head; Out.Msg[0] = o1; Out.Msg[1] = o2; Out.Msg[2] = o3; Assigns = assigns;
+ }
+};
+
+//_____________________________________________________________________________
+class FilterList
+{//""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+public:
+ vector<Filter*> List;
+
+ void Add( byte inport, byte message, short channels, short mina, short maxa, short minb, short maxb, vector<byte> &head, vector<short> &sequence1, vector<short> &sequence2, vector<short> &sequence3, vector<Assignment*> &assigns )
+ {
+ List.push_back( new Filter( inport, message, channels, mina, maxa, minb, maxb, head, sequence1, sequence2, sequence3, assigns ) );
+ HasBank |= message == BANK;
+ HasData |= ( message >= DATA ) && ( message <= NRPN );
+ HasSysx |= message == SYSX;
+ }
+ Filter* operator[] ( short index )
+ {
+ return List[index];
+ }
+ void Route( byte from, MidiM &cur, MidiM &prev )
+ {
+ for( short i = 0 ; i < List.size() ; i++ )
+ {
+ Filter* f = List[i];
+ if( f->Port != from ) continue;
+
+ if( HasSysx && ( f->Type == SYSX ) && ( cur.Type == SYSX ) )
+ {
+ bool ok = f->Head.size() > 0;
+ if( ok )
+ if( f->Head[0] != RAW )
+ for( int j = 0 ; j < f->Head.size() ; j++ )
+ if( j == cur.Raw.size() || f->Head[j] != cur.Raw[j] )
+ ok=false;
+ if( ok )
+ {
+ for( int assign = 0 ; assign < f->Assigns.size() ; assign++ )
+ if( f->Assigns[assign]->Compute( cur, prev ) == 0 )
+ ML.Add( f->Assigns[assign]->Name, f->Assigns[assign]->Value );
+
+ for( int port = 0 ; port < 3 ; port++ )
+ if( f->Out.Compute( port, cur, prev ) == 0 )
+ {
+ led[3] = 1;
+ for( short j = 0 ; j < f->Out.Out.size() ; j++ )
+ SL[port].putc( f->Out.Out[j] );
+ led[3] = 0;
+ }
+ f->Out.Done();
+ return;
+ }
+ }
+ else if( HasData && ( f->Type == DATA || f->Type == INCR || f->Type == DECR ) && ( cur.Type == f->Type ) && ( prev.Type == NRPN || prev.Type == RPN_ ) )
+ {
+ short number = prev.Get14(), data = cur.Get14();
+ if( f->Channel == NAKW || ( f->Channel & ( 1 << cur.Channel ) & ( 1 << prev.Channel ) ) )
+ if( f->Amin==NAKW || ( f->Amax==NAKW && number==f->Amin ) || ( f->Amax!=NAKW && number>=f->Amin && number<=f->Amax ) )
+ if( f->Bmin==NAKW || ( f->Bmax==NAKW && data==f->Bmin ) || ( f->Bmax!=NAKW && data>=f->Bmin && data<=f->Bmax ) )
+ {
+ for( int assign = 0 ; assign < f->Assigns.size() ; assign++ )
+ if( f->Assigns[assign]->Compute( cur, prev ) == 0 )
+ ML.Add( f->Assigns[assign]->Name, f->Assigns[assign]->Value );
+ for( int port = 0 ; port < 3 ; port++ )
+ if( f->Out.Compute( port, cur, prev ) == 0 )
+ {
+ for( short j = 0 ; j < f->Out.Out.size() ; j++ ) // check for unrountable message
+ {
+ short n = f->Out.Out[j];
+ if( f->Out.Out[j] == NAKN ) return;
+ }
+ led[3] = 1;
+ for( short j = 0 ; j < f->Out.Out.size() ; j++ )
+ SL[port].putc( f->Out.Out[j] );
+ led[3] = 0;
+ }
+ f->Out.Done();
+ return;
+ }
+ }
+ else if( f->Type == cur.Type )
+ if( ( f->Channel == NAKW ) || ( f->Channel & ( 1 << cur.Channel ) ) )
+ if( cur.ValCount()==0 || f->Amin==NAKN || ( f->Amax==NAKN && cur.ValA==f->Amin ) || ( f->Amax!=NAKN && cur.ValA>=f->Amin && cur.ValA<=f->Amax ) )
+ if( cur.ValCount()==1 || f->Bmin==NAKN || ( f->Bmax==NAKN && cur.ValB==f->Bmin ) || ( f->Bmax!=NAKN && cur.ValB>=f->Bmin && cur.ValB<=f->Bmax ) )
+ {
+ for( int assign = 0 ; assign < f->Assigns.size() ; assign++ )
+ if( f->Assigns[assign]->Compute( cur, prev ) == 0 )
+ ML.Add( f->Assigns[assign]->Name, f->Assigns[assign]->Value );
+
+ for( int port = 0 ; port < 3 ; port++ )
+ if( f->Out.Compute( port, cur, prev ) == 0 )
+ {
+ for( short j = 0 ; j < f->Out.Out.size() ; j++ ) // check for unrountable message
+ if( f->Out.Out[j] == NAKN ) return;
+ led[3] = 1;
+ for( short j = 0 ; j < f->Out.Out.size() ; j++ )
+ SL[port].putc( f->Out.Out[j] );
+ led[3] = 0;
+ }
+ f->Out.Done();
+ return;
+ }
+
+ }
+ }
+};
+
+#undef NEXT
+#undef PUSH
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/filter_debug.h Tue Jun 07 13:32:20 2011 +0000
@@ -0,0 +1,66 @@
+#ifndef FILTER_DEBUG_H
+#define FILTER_DEBUG_H
+
+int PrintFilterSymbol( short* p )
+{
+ int shift = 0;
+
+ if( *p > 0 && *p < 128 )
+ {
+ printf( "%d ", *p ); return 0;
+ }
+ if( *p > 0 && *p < 256 )
+ {
+ printf( "0x%02.2X ", *p ); return 0;
+ }
+ if( *p < SEQ || *p > NAKW )
+ {
+ printf( "0x%04.4X ", *p ); return 0;
+ }
+ switch( *p )
+ {
+ case SEQ: printf( "SEQ " ); return 0;
+ case E7_: printf( "E7_ " ); return 0;
+ case E8_: printf( "E8_ " ); return 0;
+ case E14: printf( "E14 " ); return 0;
+ case NOP: printf( "NOP " ); return 0;
+ case VMC: printf( "VMC " ); return 0;
+ case VM_: printf( "VM_ " ); return 0;
+ case VC_: printf( "VC_ " ); return 0;
+ case VA_: printf( "VA_ " ); return 0;
+ case VB_: printf( "VB_ " ); return 0;
+ case VD_: printf( "VD_ " ); return 0;
+ case VN_: printf( "VN_ " ); return 0;
+ case ADD: printf( "ADD " ); return 0;
+ case SUB: printf( "SUB " ); return 0;
+ case MUL: printf( "MUL " ); return 0;
+ case DIV: printf( "DIV " ); return 0;
+ case MOD: printf( "MOD " ); return 0;
+ case BIT: printf( "BIT " ); return 0;
+ case BOR: printf( "BOR " ); return 0;
+ case BAN: printf( "BAN " ); return 0;
+ case BNO: printf( "BNO " ); return 0;
+ case BSL: printf( "BSL " ); return 0;
+ case BSR: printf( "BSR " ); return 0;
+ case MAP: printf( "MAP " ); return 0;
+ case RPN: printf( "RPN " ); return 0;
+ case NPN: printf( "NPN " ); return 0;
+ case CSB: printf( "CSB " ); return 0;
+ case CSE: printf( "CSE " ); return 0;
+ case CS1: printf( "CS1 " ); return 0;
+ case CS2: printf( "CS2 " ); return 0;
+ case NAKW:printf( "NAKW "); return 0;
+ case RAW: printf( "* " ); return 0;
+ }
+ if( *p > CID && *p < CUL )
+ {
+ char buffer[17];
+ while( *p != CID ) buffer[shift++]= (char)( *p++ - CID );
+ buffer[shift] = 0;
+ printf( "%s ", buffer );
+ return shift;
+ }
+ return 0;
+}
+
+#endif
\ No newline at end of file
--- /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);
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld Tue Jun 07 13:32:20 2011 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/63bcd7ba4912
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/memory.h Tue Jun 07 13:32:20 2011 +0000
@@ -0,0 +1,78 @@
+#ifndef MEMORY_H
+#define MEMORY_H
+
+//_____________________________________________________________________________
+class Memory
+{//""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+private:
+public:
+ char Name[16];
+ short Value;
+ Memory() { Name[0] = 0; Value = 0; }
+ Memory( char* n, short v ) { strncpy( Name, n, 16 ); Value = v; }
+ ~Memory() {}
+};
+//_____________________________________________________________________________
+class MemList
+{//""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+private:
+ short allocated_; // size of allocated list
+public:
+ short Count; // size of initialized list
+ Memory* List; // list of names
+
+ MemList() : Count(0), List(NULL) {}
+
+ ~MemList()
+ {
+ if( List != NULL ) free( List );
+ Count = allocated_ = 0;
+ }
+ void Add( Memory &m )
+ {
+ int n = Find( m.Name );
+ if( n == -1 )
+ {
+ if( Count == allocated_ ) List = (Memory*)realloc( List, ( allocated_ += 5 ) * sizeof( Memory ) );
+ List[ Count++ ] = m;
+ }
+ else
+ List[n].Value = m.Value;
+ }
+ void Add( char* name, short value )
+ {
+ int n = Find( name );
+ if( n == -1 )
+ {
+ if( Count == allocated_ ) List = (Memory*)realloc( List, ( allocated_ += 5 ) * sizeof( Memory ) );
+ List[ Count++ ] = Memory( name, value );
+ }
+ else
+ List[n].Value = value;
+ }
+ short Find( char* name )
+ {
+ for( short i = 0 ; i < Count ; i++ )
+ if( strcmp( List[i].Name, name ) == 0 )
+ return i;
+ return -1;
+ }
+ short Get( char* name )
+ {
+ for( short i = 0 ; i < Count ; i++ )
+ if( strcmp( List[i].Name, name ) == 0 )
+ return List[i].Value;
+ return 0;
+ }
+ void Set( char* name, short value )
+ {
+ for( short i = 0 ; i < Count ; i++ )
+ if( strcmp( List[i].Name, name ) == 0 )
+ {
+ List[i].Value = value;
+ break;
+ }
+ }
+};
+
+#endif
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/midi.h Tue Jun 07 13:32:20 2011 +0000
@@ -0,0 +1,435 @@
+#ifndef MIDI_H
+#define MIDI_H
+
+#include <vector>
+
+#ifndef BYTE
+ #define BYTE
+ typedef unsigned char byte;
+#endif
+
+#ifndef WORD
+ #define WORD
+ typedef unsigned short word;
+#endif
+
+ // unused midi code serves as defining 'Not A Known Value':
+#define NAKN 253
+
+// out of 14bit range value serves as defining 'Not A Known Word':
+#define NAKW 0x5000
+
+// generic:
+#define NONE 0
+
+// values for member 'next':
+#define VALA 1
+#define VALB 2
+#define MSB 3
+#define LSB 4
+#define PAIR 5
+#define ITEM 6
+#define MSB2 7
+#define LSB2 8
+
+// values for member 'type':
+// channel message:
+#define NOTE 1
+#define POLA 2
+#define CTRL 3
+#define PROG 4
+#define BANK 5
+#define DATA 6
+#define INCR 7
+#define DECR 8
+#define RPN_ 9
+#define NRPN 10
+#define MONA 11
+#define BEND 12
+// no channel message:
+#define SYSX 13
+#define TCOD 14
+#define SPOS 15
+#define SSEL 16
+#define TUNE 17
+#define CLOK 18
+#define STAR 19
+#define CONT 20
+#define STOP 21
+#define SENS 22
+#define RSET 23
+
+///////////////////////////////////////////////////////////////////////////////
+ // base class for all Messages
+//_____________________________________________________________________________
+class MidiM
+{//""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+public:
+ byte Command;
+ byte Type;
+ byte Channel;
+ byte Next; // expected type of next inconming byte
+ byte ValA; // data
+ byte ValB; // data
+ vector<byte> Raw;
+
+ MidiM( byte type ) : Command(0), Type( type ), Channel( NAKN ), Next(NONE), ValA(NAKN), ValB(NAKN) {}
+ MidiM( byte type, byte ch ) : Command(0), Type( type ), Channel( ch ), Next(NONE), ValA(NAKN), ValB(NAKN) {}
+ virtual ~MidiM(){}
+
+ virtual bool Append( byte b) { Raw.push_back(b); return true; }
+
+ virtual byte ValCount() { return 0; }
+
+ short Get14()
+ {
+ return ( ValA == NAKN ? 0 : ValA << 7 ) + ( ValB == NAKN ? 0 : ValB );
+ }
+ void Set14( short v )
+ {
+ ValA = ( v >> 7 ) & 127;
+ ValB = v & 127;
+ Next = NONE;
+ }
+};
+//_____________________________________________________________________________
+class MidiTune : public MidiM
+{//""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+public:
+ MidiTune() : MidiM( TUNE ) { Raw.push_back( Command = 0xF6 ); }
+ virtual ~MidiTune(){}
+// virtual void Send( Serial &s ) { s.putc( 0xF6 ); }
+};
+//_____________________________________________________________________________
+class MidiClock : public MidiM
+{//""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+public:
+ MidiClock() : MidiM( CLOK ) { Raw.push_back( Command = 0xF8 ); }
+ virtual ~MidiClock(){}
+// virtual void Send( Serial &s ) { s.putc( 0xF8 ); }
+};
+//_____________________________________________________________________________
+class MidiStart : public MidiM
+{//""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+public:
+ MidiStart() : MidiM( STAR ) { Raw.push_back( Command = 0xFA ); }
+ virtual ~MidiStart(){}
+// virtual void Send( Serial &s ) { s.putc( 0xFA ); }
+};
+//_____________________________________________________________________________
+class MidiContinue : public MidiM
+{//""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+public:
+ MidiContinue() : MidiM( CONT ) { Raw.push_back( Command = 0xFB ); }
+ virtual ~MidiContinue(){}
+// virtual void Send( Serial &s ) { s.putc( 0xFB ); }
+};
+//_____________________________________________________________________________
+class MidiStop : public MidiM
+{//""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+public:
+ MidiStop() : MidiM( STOP ) { Raw.push_back( Command = 0xFC ); }
+ virtual ~MidiStop(){}
+// virtual void Send( Serial &s ) { s.putc( 0xFC ); }
+};
+//_____________________________________________________________________________
+class MidiSensing : public MidiM
+{//""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+public:
+ MidiSensing() : MidiM( SENS ) { Raw.push_back( Command = 0xFE ); }
+ virtual ~MidiSensing(){}
+// virtual void Send( Serial &s ) { s.putc( 0xFE ); }
+};
+//_____________________________________________________________________________
+class MidiReset : public MidiM
+{//""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+public:
+ MidiReset() : MidiM( RSET ) { Raw.push_back( Command = 0xFF ); }
+ virtual ~MidiReset(){}
+// virtual void Send( Serial &s ) { s.putc( 0xFF ); }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// base class & derived classes for all Messages having 1 byte of data
+//_____________________________________________________________________________
+class MidiM1 : public MidiM
+{//""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+public:
+ MidiM1( byte type, byte ch ) : MidiM( type, ch ) { Next = VALA; }
+ MidiM1( byte type, byte ch, byte v ) : MidiM( type, ch ) { Next = NONE; ValA = v; }
+ virtual ~MidiM1(){}
+ virtual bool Append( byte b )
+ {
+ Raw.push_back(b);
+ if( b > 127 || Next == NONE ) return false;
+ Next = NONE; ValA = b; return true;
+ }
+ virtual byte ValCount() { return 1; }
+};
+//_____________________________________________________________________________
+class MidiSelect : public MidiM1
+{//""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+public:
+ MidiSelect() : MidiM1( SSEL, NAKN ) { Raw.push_back( Command = 0xF3 ); }
+ MidiSelect( byte v ) : MidiM1( SSEL, NAKN, v ) { Raw.push_back( Command = 0xF3 ); }
+ virtual ~MidiSelect(){}
+// virtual void Send( Serial &s ) { s.putc( 0xF3 ); s.putc( ValA ); }
+};
+//_____________________________________________________________________________
+class MidiTimeCode : public MidiM1
+{//""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+public:
+ MidiTimeCode() : MidiM1( TCOD, NAKN ) { Raw.push_back( Command = 0xF1 ); }
+ MidiTimeCode( byte v ) : MidiM1( TCOD, NAKN, v ) { Raw.push_back( Command = 0xF1 ); }
+ virtual ~MidiTimeCode(){}
+// virtual void Send( Serial &s ) { s.putc( 0xF1 ); s.putc( ValA ); }
+};
+//_____________________________________________________________________________
+class MidiProgram : public MidiM1
+{//""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+public:
+ MidiProgram( byte ch ) : MidiM1( PROG, ch ) { Raw.push_back( ( Command = 0xC0 ) + ch ); }
+ MidiProgram( byte ch, byte v ) : MidiM1( PROG, ch, v ){ Raw.push_back( ( Command = 0xC0 ) + ch ); }
+ virtual ~MidiProgram(){}
+// virtual void Send( Serial &s ){ s.putc( 0xC0 + Channel ); s.putc( ValA ); }
+};
+//_____________________________________________________________________________
+class MidiMonoAft : public MidiM1
+{//""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+public:
+ MidiMonoAft( byte ch ) : MidiM1( MONA, ch ) { Raw.push_back( ( Command = 0xD0 ) + ch ); }
+ MidiMonoAft( byte ch, byte v ) : MidiM1( MONA, ch, v ){ Raw.push_back( ( Command = 0xD0 ) + ch ); }
+ virtual ~MidiMonoAft(){}
+// virtual void Send( Serial &s ){ s.putc( 0xD0 + Channel ); s.putc( ValA ); }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// base class & derived classes for all Messages having 2 byte of data
+//_____________________________________________________________________________
+class MidiM2 : public MidiM
+{//""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+public:
+ MidiM2(byte type,byte ch) : MidiM(type,ch){ Next = VALA; }
+ MidiM2(byte type,byte ch,byte v) : MidiM(type,ch){Next=VALB;ValA=v;}
+ MidiM2(byte type,byte ch,byte v,byte w): MidiM(type,ch){Next=NONE;ValA=v;ValB=w;}
+ virtual ~MidiM2(){}
+ virtual byte ValCount() { return 2; }
+
+ virtual bool Append( byte b )
+ {
+ Raw.push_back(b);
+ if( b > 127 || Next == NONE ) return false;
+ if( Next == VALA ) { ValA = b; Next = VALB; }
+ else { ValB = b; Next = NONE; }
+ return true;
+ }
+};
+//_____________________________________________________________________________
+class MidiPosition : public MidiM2
+{//""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+public:
+ MidiPosition() : MidiM2( SPOS, NAKN ) { Raw.push_back( Command = 0xF3 ); }
+ MidiPosition( byte v ) : MidiM2( SPOS, NAKN, v ) { Raw.push_back( Command = 0xF3 ); }
+ MidiPosition( byte v, byte w ) : MidiM2( SPOS, NAKN, v, w ) { Command = 0xF3; }
+ virtual ~MidiPosition(){}
+// virtual void Send( Serial &s ){ s.putc(0xF3); s.putc(ValA); s.putc(ValB); }
+};
+//_____________________________________________________________________________
+class MidiNoteOn : public MidiM2
+{//""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+public:
+ MidiNoteOn( byte ch ) : MidiM2( NOTE, ch ) { Raw.push_back( ( Command = 0x90 ) + ch ); }
+ MidiNoteOn( byte ch, byte v ): MidiM2( NOTE, ch, v ) { Raw.push_back( ( Command = 0x90 ) + ch ); }
+ MidiNoteOn( byte ch, byte v, byte w ) : MidiM2( NOTE, ch, v, w ) { Command = 0x90; }
+ virtual ~MidiNoteOn(){}
+/* virtual void Send( Serial &s )
+ {
+ s.putc( 0x90 + Channel ); s.putc( ValA ); s.putc( ValB );
+ }*/
+};
+//_____________________________________________________________________________
+class MidiNoteOff : public MidiM2
+{//""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+public:
+ MidiNoteOff( byte ch ) : MidiM2( NOTE, ch ) { Raw.push_back( ( Command = 0x80 ) + ch ); }
+ MidiNoteOff( byte ch, byte v ): MidiM2( NOTE, ch, v ) { Raw.push_back( ( Command = 0x80 ) + ch ); }
+ MidiNoteOff( byte ch, byte v, byte w ): MidiM2( NOTE, ch, v, w ) { Command = 0x80; }
+ virtual ~MidiNoteOff(){}
+/* virtual void Send( Serial &s )
+ {
+ s.putc( 0x80 + Channel ); s.putc( ValA ); s.putc( ValB );
+ }*/
+};
+//_____________________________________________________________________________
+class MidiPolyAft : public MidiM2
+{//""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+public:
+ MidiPolyAft( byte ch ) : MidiM2( POLA, ch ) { Raw.push_back( ( Command = 0xA0 ) + ch ); }
+ MidiPolyAft( byte ch, byte v ): MidiM2( POLA, ch, v ) { Raw.push_back( ( Command = 0xA0 ) + ch ); }
+ MidiPolyAft( byte ch, byte v, byte w ): MidiM2( POLA, ch, v, w ) { Command = 0xA0; }
+ virtual ~MidiPolyAft(){}
+/* virtual void Send( Serial &s )
+ {
+ s.putc( 0xA0 + Channel ); s.putc( ValA ); s.putc( ValB );
+ }*/
+};
+//_____________________________________________________________________________
+class MidiBend : public MidiM2
+{//""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+public:
+ MidiBend( byte ch ) : MidiM2( BEND, ch ) { Raw.push_back( ( Command = 0xE0 ) + ch ); }
+ MidiBend( byte ch, byte v ) : MidiM2( BEND, ch, v ) { Raw.push_back( ( Command = 0xE0 ) + ch ); }
+ MidiBend( byte ch, byte v, byte w ): MidiM2( BEND, ch, v, w ) { Command = 0xE0; }
+ virtual ~MidiBend(){}
+/* virtual void Send( Serial &s )
+ {
+ s.putc( 0xE0 + Channel ); s.putc( ValA ); s.putc( ValB );
+ }*/
+};
+//_____________________________________________________________________________
+class MidiControl : public MidiM2
+{//""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+public:
+ MidiControl( byte ch ) : MidiM2( CTRL, ch ) { Raw.push_back( ( Command = 0xB0 ) + ch ); }
+ MidiControl( byte ch, byte v ): MidiM2( CTRL, ch, v ) { Raw.push_back( ( Command = 0xB0 ) + ch ); }
+ MidiControl( byte ch, byte v, byte w ): MidiM2( CTRL, ch, v, w ) { Command = 0xB0; }
+ virtual ~MidiControl(){}
+/* virtual void Send( Serial &s )
+ {
+ byte c = 0xB0 + Channel;
+ switch( Type ) {
+ case CTRL : s.putc( c ); s.putc(ValA ); s.putc( ValB ); break;
+ case BANK : if( ValA != NAKN ) s.putc( c ); s.putc( 0 ); s.putc( ValA );
+ if( ValB != NAKN ) s.putc( c ); s.putc( 32 ); s.putc( ValB ); break;
+ case DATA : if( ValA != NAKN ) s.putc( c ); s.putc( 6 ); s.putc( ValA );
+ if( ValB != NAKN ) s.putc( c ); s.putc( 38 ); s.putc( ValB ); break;
+ case INCR : s.putc( c ); s.putc( 96 ); break;
+ case DECR : s.putc( c ); s.putc( 97 ); break;
+ case NRPN : if( ValA != NAKN ) s.putc( c ); s.putc( 99 ); s.putc( ValA );
+ if( ValB != NAKN ) s.putc( c ); s.putc( 98 ); s.putc( ValB ); break;
+ case RPN_ : if( ValA != NAKN ) s.putc( c ); s.putc( 101 ); s.putc( ValA );
+ if( ValB != NAKN ) s.putc( c ); s.putc( 100 ); s.putc( ValB ); break;
+ }
+ }*/
+ virtual bool Append( byte b )
+ {
+ Raw.push_back(b);
+ switch( Next ) {
+ case VALA:
+ if( HasBank || HasData )
+ switch( b ) {
+ case 0: if( HasBank ) { Next=MSB; Type=BANK; }
+ else { Next=VALB; ValA=b; } return true;
+
+ case 32: if( HasBank ) { Next=LSB; Type=BANK; }
+ else { Next=VALB; ValA=b; } return true;
+
+ case 6: if( HasData ) { Next=MSB; Type=DATA; }
+ else { Next=VALB; ValA=b; } return true;
+
+ case 38: if( HasData ) { Next=LSB; Type=DATA; }
+ else { Next=VALB; ValA=b; } return true;
+
+ case 96: if( HasData ) { Next=NONE; Type=INCR; }
+ else { Next=VALB; ValA=b; } return true;
+
+ case 97: if( HasData ) { Next=NONE; Type=DECR; }
+ else { Next=VALB; ValA=b; } return true;
+
+ case 98: if( HasData ) { Next=LSB; Type=NRPN; }
+ else { Next=VALB; ValA=b; } return true;
+
+ case 99: if( HasData ) { Next=MSB; Type=NRPN; }
+ else { Next=VALB; ValA=b; } return true;
+
+ case 100: if( HasData ) { Next=LSB; Type=NRPN; }
+ else { Next=VALB; ValA=b; } return true;
+
+ case 101: if( HasData ) { Next=MSB; Type=NRPN; }
+ else { Next=VALB; ValA=b; } return true;
+
+ default: Next = VALB; ValA = b; return true;
+ }
+ else{
+ Next = VALB;
+ ValA = b;
+ return true;
+ }
+ case VALB: Next = NONE; ValB = b; return true;
+ case MSB: Next = PAIR; ValA = b; return true; // wait for 0xB*
+ case LSB: Next = PAIR; ValB = b; return true; // wait for 0xB*
+ case MSB2: Next = NONE; ValA = b; return true;
+ case LSB2: Next = NONE; ValB = b; return true;
+ case PAIR: Next = ITEM; return true; // 0xB*
+ case ITEM:
+ switch( Type ) {
+ case BANK: if( b!= 0 && b!= 32 ){ Next = NONE; return false; }
+ Next = b == 0 ? MSB2 : LSB2; return true;
+ case DATA: if( b!= 6 && b!= 38 ){ Next = NONE; return false; }
+ Next = b == 6 ? MSB2 : LSB2; return true;
+ case NRPN: if( b!= 98 && b!= 99 ){ Next = NONE; return false; }
+ Next = b == 99 ? MSB2 : LSB2; return true;
+ case RPN_: if( b!=100 && b!=101 ){ Next = NONE; return false; }
+ Next = b ==101 ? MSB2 : LSB2; return true;
+ }
+ }
+ return false;
+ }
+
+};
+
+//_____________________________________________________________________________
+class MidiX : public MidiM2 // class for SysEx message
+{//""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+public:
+ MidiX() : MidiM2( SYSX, NAKN ){ Raw.push_back( Command = 0xF0 ); }
+ virtual ~MidiX(){}
+ virtual bool Append( byte b )
+ {
+ Raw.push_back(b);
+ if( b==0xF7 )
+ Next = NONE;
+ return true;
+ }
+};
+
+//_____________________________________________________________________________
+MidiM* MidiCreateMessage( byte command )
+{//""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+ if( command >= 0xF0 )
+ switch( command ) {
+ case 0xF0: return new MidiX();
+ case 0xF1: return new MidiTimeCode();
+ case 0xF2: return new MidiPosition();
+ case 0xF3: return new MidiSelect();
+ case 0xF6: return new MidiTune();
+ case 0xF8: return new MidiClock();
+ case 0xFA: return new MidiStart();
+ case 0xFB: return new MidiContinue();
+ case 0xFC: return new MidiStop();
+ case 0xFE: return new MidiSensing();
+ case 0xFF: return new MidiReset();
+ }
+ else switch( command >> 4 ) {
+ case 0x8: return new MidiNoteOff( command & 15 );
+ case 0x9: return new MidiNoteOn ( command & 15 );
+ case 0xA: return new MidiPolyAft( command & 15 );
+ case 0xB: return new MidiControl( command & 15 );
+ case 0xC: return new MidiProgram( command & 15 );
+ case 0xD: return new MidiMonoAft( command & 15 );
+ case 0xE: return new MidiBend ( command & 15 );
+
+ }
+ return new MidiM( NONE );
+}
+
+#undef VALA
+#undef VALB
+#undef MSB
+#undef LSB
+#undef PAIR
+#undef ITEM
+#undef MSB2
+#undef LSB2
+
+#endif
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/parse.h Tue Jun 07 13:32:20 2011 +0000
@@ -0,0 +1,448 @@
+#ifndef PARSE_H
+#define PARSE_H
+
+#include <string.h>
+#include <vector>
+
+void ParseCleanUp( char* s1, char* s2 )
+{
+ // copy all non blank till ; or 0
+ for( int i = 0, j = 0 ; i < 256 ; i++ )
+ if( s1[i] != 32 && s1[i] != 13 && s1[i] != 10 && s1[i] != 9 )
+ switch( s2[j++] = s1[i] ) {
+ case ';': s2[j-1] = 0; return;
+ case 0: return;
+ }
+}
+int GetOPIDfromFunction( char * f )
+{
+ if( strcmp( f, "add" ) == 0 ) return ADD;
+ if( strcmp( f, "mul" ) == 0 ) return MUL;
+ if( strcmp( f, "sub" ) == 0 ) return SUB;
+ if( strcmp( f, "div" ) == 0 ) return DIV;
+ if( strcmp( f, "i8" ) == 0 ) return E8_;
+ if( strcmp( f, "i14" ) == 0 ) return E14;
+ if( strcmp( f, "mod" ) == 0 ) return MOD;
+ if( strcmp( f, "bit" ) == 0 ) return BIT;
+ if( strcmp( f, "bor" ) == 0 ) return BOR;
+ if( strcmp( f, "ban" ) == 0 ) return BAN;
+ if( strcmp( f, "bno" ) == 0 ) return BNO;
+ if( strcmp( f, "bsl" ) == 0 ) return BSL;
+ if( strcmp( f, "bsr" ) == 0 ) return BSR;
+ if( strcmp( f, "msb" ) == 0 ) return MSB;
+ if( strcmp( f, "lsb" ) == 0 ) return LSB;
+ if( strcmp( f, "map" ) == 0 ) return MAP;
+ if( strcmp( f, "nrpn") == 0 ) return NPN;
+ if( strcmp( f, "rpn" ) == 0 ) return RPN;
+ if( strcmp( f, "bank") == 0 ) return BNK;
+ if( strcmp( f, "nrp8") == 0 ) return NP8;
+ return 0;
+}
+
+int ParseError = 0;
+int ParseLine = 0;
+#define abort(x) { ParseError = x; return false; }
+
+#define PARSE_NOERROR 0
+#define PARSE_NO_FILE 1
+#define PARSE_BAD_NUMBER_DEFINITION 2
+#define PARSE_BAD_MESSAGE_DEFINITION 3
+#define PARSE_BAD_SEQ_SYNTAXE 4
+#define PARSE_BAD_SEQ_HEXA_SIGN 5
+#define PARSE_BAD_SEQ_NUMBER 6
+#define PARSE_BAD_SEQ_IDENTIFIER 7
+#define PARSE_BAD_SEQ_BYTE 8
+#define PARSE_BAD_SEQ_FUNCTION 9
+#define PARSE_BAD_SEQ_TOOLONG 10
+#define PARSE_UNKNWON_ENTRY 11
+#define PARSE_MIN_GREATER_THAN_MAX 12
+
+#define TOKEN_END *p == 0 || *p == ',' || *p == ')'
+#define TOKEN_NUM *p >= '0' && *p <= '9'
+#define TOKEN_LOW *p >= 'a' && *p <= 'z'
+#define TOKEN_UPP *p >= 'A' && *p <= 'Z'
+#define TOKEN_LOX *p >= 'a' && *p <= 'f'
+#define TOKEN_UPX *p >= 'A' && *p <= 'F'
+
+class ParseEntry
+{
+public:
+ char Name[17];
+ ParseEntry( char* name )
+ {
+ short i = 0;
+ for( i = 0 ; i < 16 && name[i] ; i++ )
+ {
+ if( name[i] >= 'A' && name[i]<='Z' ) Name[i] = name[i] + 32; else Name[i] = name[i];
+ }
+ Name[i] = 0;
+ }
+ virtual ~ParseEntry() {}
+
+ virtual bool Parse( char* data ){ return true; }
+};
+class ParseFlag : public ParseEntry
+{
+public:
+ int Flag;
+ ParseFlag( char* name ) : ParseEntry( name ), Flag(0) {}
+ virtual ~ParseFlag(){}
+ virtual bool Parse( char* data )
+ {
+ if( *data == '*' )
+ {
+ Flag = NAKW;
+ return true;
+ }
+ Flag = 0;
+ for( int i = 0 ; i < 16 ; i++ )
+ if( data[i] == 0 ) break;
+ else if( data[i] != '-' ) Flag |= 1 << i;
+ return true;
+ }
+};
+class ParseByte : public ParseEntry
+{
+public:
+ byte Mini;
+ byte Maxi;
+ ParseByte( char* name ) : ParseEntry( name ),Mini(NAKN), Maxi(NAKN) {}
+ virtual ~ParseByte(){}
+ virtual bool Parse( char* data )
+ {
+ if( *data == '*' )
+ {
+ Mini = NAKN;
+ Maxi = NAKN;
+ return true;
+ }
+
+ int base = 10;
+ bool start = true;
+ int dot = 0;
+ char set[] = "0123456789ABCDEF$.";
+ char* p;
+ bool ok = false;
+
+ Mini = 0;
+
+ while( *data )
+ {
+ ok = false;
+ p = strchr( set, *data++ );
+ if( p )
+ {
+ int index = p - set;
+
+ if( index==16 && start==true ) { start=false; base=16, ok=true; }
+ else if( index == 17 && dot < 3 ) { dot++; if( dot==3) { start=true; base=10; Maxi = 0; ok=true; } }
+ else if( index < base ) { if( dot==3 ) { start=false; Maxi = Maxi * base + index; ok=true; }
+ else { start=false; Mini = Mini * base + index; ok=true; } }
+ else break;
+ }
+ else break;
+ }
+ if( ! ok ) abort( PARSE_BAD_NUMBER_DEFINITION )
+ if( Maxi != NAKN && Mini > Maxi ) abort( PARSE_MIN_GREATER_THAN_MAX )
+ return true;
+ }
+};
+class ParseShort : public ParseEntry
+{
+public:
+ short Mini;
+ short Maxi;
+ ParseShort( char* name ) : ParseEntry( name ),Mini(NAKW), Maxi(NAKW) {}
+ virtual ~ParseShort(){}
+ virtual bool Parse( char* data )
+ {
+ if( *data == '*' )
+ {
+ Mini = NAKW;
+ Maxi = NAKW;
+ return true;
+ }
+ int base = 10;
+ bool start = true;
+ int dot = 0;
+ char set[] = "0123456789ABCDEF$.";
+ char* p;
+ bool ok = false;
+
+ Mini = 0;
+
+ while( *data )
+ {
+ ok = false;
+ p = strchr( set, *data++ );
+ if( p )
+ {
+ int index = p - set;
+
+ if( index==16 && start==true ) { start=false; base=16, ok=true; }
+ else if( index == 17 && dot < 3 ) { dot++; if( dot==3) { start=true; base=10; Maxi = 0; ok=true; } }
+ else if( index < base ) { if( dot==3 ) { start=false; Maxi = Maxi * base + index; ok=true; }
+ else { start=false; Mini = Mini * base + index; ok=true; } }
+ else break;
+ }
+ else break;
+ }
+ if( ! ok ) abort( PARSE_BAD_NUMBER_DEFINITION )
+ if( Maxi != NAKW && Mini>Maxi ) abort( PARSE_MIN_GREATER_THAN_MAX )
+ return true;
+ }
+};
+class ParseMessage : public ParseEntry
+{
+public:
+ byte Code;
+ ParseMessage( char* name ) : ParseEntry( name ),Code(NAKN) {}
+ virtual ~ParseMessage(){}
+ virtual bool Parse( char* data )
+ {
+ static char keywords[] = "NOTE;POLA;CTRL;PROG;BANK;DATA;INCR;DECR;RPN_;NRPN;MONA;BEND;SYSX;TCOD;SPOS;SSEL;TUNE;CLOK;STAR;CONT;STOP;SENS;RSET";
+
+ char* p = strstr( keywords, data );
+ if( p == NULL ) abort( PARSE_BAD_MESSAGE_DEFINITION )
+
+ Code = ( p - keywords ) / 5 + 1;
+ return true;
+ }
+};
+
+#define PUSH(x) Sequence.push_back(x)
+
+class ParseSequence : public ParseEntry
+{
+public:
+ vector<short> Sequence;
+ ParseSequence( char* name ) : ParseEntry(name) {}
+ virtual ~ParseSequence() { }
+
+ virtual bool Parse( char* data )
+ {
+ if( *data == '*' )
+ {
+ Sequence = vector<short>( 1, RAW );
+ return true;
+ }
+ char* p = data;
+ if( SubParse( p ) )
+ {
+ Sequence.push_back(NOP);
+ return true;
+ }
+ return false;
+ }
+ short SubParse( char* &p ) // returns the number of arguments in the sub-sequence
+ {
+ static int level = 0;
+ level++;
+
+ int args = 0;
+
+ while( *p )
+ {
+ int num = 0;
+
+ switch( *p )
+ {
+ case '=':
+ case ',': p++; break;
+ case ')': p++; level--; return args;
+
+ case '$': while( 1 ) {
+ p++; if( TOKEN_END ) { PUSH( num ); break; }
+ else if( TOKEN_NUM ) num = num * 16 + (*p - 48 );
+ else if( TOKEN_UPX ) num = num * 16 + (*p - 55 );
+ else if( TOKEN_LOX ) num = num * 16 + (*p - 87 );
+ else abort( PARSE_BAD_SEQ_HEXA_SIGN )
+ } args++; break;
+
+ case '%': { char fn[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; int i = 0;
+ while( 1 ) {
+ p++; if( TOKEN_END ) break;
+ else if( TOKEN_NUM ) fn[i++] = *p;
+ else if( TOKEN_UPP ) fn[i++] = *p + 32;
+ else if( TOKEN_LOW ) fn[i++] = *p;
+ else abort( PARSE_BAD_SEQ_IDENTIFIER )
+ if( i == 16 ) abort( PARSE_BAD_SEQ_TOOLONG )
+ }
+ if( strcmp( fn, "mc") == 0 ) PUSH( VMC );
+ else if( strcmp( fn, "m" ) == 0 ) PUSH( VM_ );
+ else if( strcmp( fn, "c" ) == 0 ) PUSH( VC_ );
+ else if( strcmp( fn, "a" ) == 0 ) PUSH( VA_ );
+ else if( strcmp( fn, "b" ) == 0 ) PUSH( VB_ );
+ else if( strcmp( fn, "n" ) == 0 ) PUSH( VN_ );
+ else if( strcmp( fn, "d" ) == 0 ) PUSH( VD_ );
+ else if( strcmp( fn, "k" ) == 0 ) PUSH( VK_ );
+ else {
+ for( int j = 0 ; j < i ; j++ )
+ PUSH( CID + fn[j] );
+ PUSH( CID );
+ }
+ } args++; break;
+
+ default: if( TOKEN_UPP ) *p += 32;
+
+ if( TOKEN_LOW ) { char fn[] = {*p,0,0,0,0,0,0,0,0,0}; int i = 1;
+ while( 1 ) {
+ p++; if( *p == '(' ) break;
+ else if( TOKEN_UPP ) fn[i++] = *p + 32;
+ else if( TOKEN_LOW ) fn[i++] = *p;
+ else if( TOKEN_NUM ) fn[i++] = *p;
+ else abort(PARSE_BAD_SEQ_FUNCTION)
+ }
+ p++; // skip (
+ if( level == 1 ) PUSH( SEQ );
+ short a = SubParse( p );
+ if( a == 0 ) return 0;
+ int n = GetOPIDfromFunction( fn );
+ if( n == 0 ) abort(PARSE_BAD_SEQ_FUNCTION)
+ if( n == MAP ) PUSH( a );
+ PUSH( n );
+ if( level==1 && n!=E8_ && n!=E14 && n!=RPN && n!=NPN && n!=BNK && n!=NP8 ) PUSH( E7_ );
+ args++;
+ break;
+ }
+ if( TOKEN_NUM ) {
+ num = *p - 48;
+ while( 1 ) {
+ p++; if( TOKEN_END ) { PUSH( num ); break; }
+ else if( TOKEN_NUM ) num = num * 10 + (*p - 48 );
+ else abort( PARSE_BAD_SEQ_NUMBER )
+ } args++; break;
+ }
+ abort( PARSE_BAD_SEQ_SYNTAXE )
+ }
+ }
+ level--;
+ return args;
+ }
+};
+
+class ParseRoute
+{
+public :
+ byte Inport;
+ byte Message;
+ short Channels;
+ short minA;
+ short maxA;
+ short minB;
+ short maxB;
+ vector<byte> Head;
+ vector<short> Sequence1;
+ vector<short> Sequence2;
+ vector<short> Sequence3;
+ vector<Assignment*> Assigns;
+
+ ParseRoute() : Inport(0), Message(NAKN), Channels(NAKW), minA(NAKN), maxA(NAKN), minB(NAKN), maxB(NAKN) {}
+ ~ParseRoute()
+ {
+ }
+ bool Add( ParseEntry* entry )
+ {
+ ParseMessage* m = (ParseMessage*)entry;
+ ParseFlag* f = (ParseFlag*)entry;
+ ParseByte* b = (ParseByte*)entry;
+ ParseShort* s = (ParseShort*)entry;
+ ParseSequence* q = (ParseSequence*)entry;
+
+ if( strcmp( entry->Name, "input1" ) == 0 ) { Inport = 0; Message = m->Code; return true; }
+ else if( strcmp( entry->Name, "input2" ) == 0 ) { Inport = 1; Message = m->Code; return true; }
+ else if( strcmp( entry->Name, "input3" ) == 0 ) { Inport = 2; Message = m->Code; return true; }
+ else if( strcmp( entry->Name, "channels" ) == 0 ) { Channels = f->Flag; return true; }
+ else if( strcmp( entry->Name, "program" ) == 0 ) { minA = b->Mini; maxA = b->Maxi; return true; }
+ else if( strcmp( entry->Name, "valuea" ) == 0 ) { minA = b->Mini; maxA = b->Maxi; return true; }
+ else if( strcmp( entry->Name, "valueb" ) == 0 ) { minB = b->Mini; maxB = b->Maxi; return true; }
+ else if( strcmp( entry->Name, "parameter") == 0 ) { minA = s->Mini; maxA = s->Maxi; return true; }
+ else if( strcmp( entry->Name, "data" ) == 0 ) { minB = s->Mini; maxB = s->Maxi; return true; }
+ else if( strcmp( entry->Name, "bank" ) == 0 ) { minA = s->Mini; maxA = s->Maxi; return true; }
+ else if( strcmp( entry->Name, "output1" ) == 0 ) { Sequence1.insert( Sequence1.end(), q->Sequence.begin(), q->Sequence.end() ); return true; }
+ else if( strcmp( entry->Name, "output2" ) == 0 ) { Sequence2.insert( Sequence2.end(), q->Sequence.begin(), q->Sequence.end() ); return true; }
+ else if( strcmp( entry->Name, "output3" ) == 0 ) { Sequence3.insert( Sequence3.end(), q->Sequence.begin(), q->Sequence.end() ); return true; }
+ else if( strcmp( entry->Name, "header" ) == 0 ) { Head.insert( Head.end(), q->Sequence.begin(), q->Sequence.end() ); return true; }
+ else if( entry->Name[0] == '%' ) { Assigns.push_back( new Assignment( entry->Name + 1 /* skip the %*/, q->Sequence ) ); return true; }
+ ParseError = PARSE_UNKNWON_ENTRY;
+ return false;
+ }
+ bool Done()
+ {
+ FL.Add( Inport, Message, Channels, minA, maxA, minB, maxB, Head, Sequence1, Sequence2, Sequence3, Assigns );
+ return true;
+ }
+};
+
+const char keywords_flag[] = "channels";
+const char keywords_nums[] = "valueA valueB program";
+const char keywords_nu14[] = "parameter data bank";
+const char keywords_mess[] = "input1 input2 input3";
+const char keywords_sequ[] = "output1 output2 output3 header";
+
+bool Parse()
+{
+ char Line1[256];
+ char Line2[256];
+ LocalFileSystem local("local");
+ FILE* f = fopen( "/local/filter.txt", "r" );
+ if( f == NULL )
+ {
+ ParseError = PARSE_NO_FILE;
+ return false;
+ }
+ ParseRoute* pr = NULL;
+ ParseLine = 0;
+ while( /* ( ParseLine < 200 ) && */ fgets( Line1, 256, f ) )
+ {
+ ParseLine++;
+ ParseEntry* sp = NULL;
+
+ ParseCleanUp( Line1, Line2 );
+ strtok( Line2, ":" );
+
+ if( Line2[0] == 0 || Line2[0] == 10 ) continue;
+
+ if( strcmp( Line2, "ROUTE" ) == 0 ) {
+ if( pr ) if( ! pr->Done() ) goto Bad;
+ delete pr;
+ pr = NULL;
+ int mem = AvailableMemory();
+ if( mem < 512 ) { printf("Only %d bytes left for program.\nFilter definitions reading stopped at line %d\n", mem, ParseLine ); break; }
+ pr = new ParseRoute();
+ }
+ else if( strstr( keywords_flag, Line2 ) ) sp = new ParseFlag( Line2 );
+ else if( strstr( keywords_nums, Line2 ) ) sp = new ParseByte( Line2 );
+ else if( strstr( keywords_nu14, Line2 ) ) sp = new ParseShort( Line2 );
+ else if( strstr( keywords_mess, Line2 ) ) sp = new ParseMessage( Line2 );
+ else if( strstr( keywords_sequ, Line2 ) ) sp = new ParseSequence(Line2 );
+ else if( Line2[0] == '%' ) sp = new ParseSequence(Line2 );
+ else { ParseError = PARSE_UNKNWON_ENTRY; goto Bad; }
+
+ if( sp != NULL )
+ {
+ if( pr == NULL ) goto Bad;
+ if( ! sp->Parse( strtok( NULL, "\n" ) ) ) goto Bad;
+ if( ! pr->Add( sp ) ) goto Bad;
+ delete sp;
+ }
+ }
+
+ if( pr ) if( ! pr->Done() ) goto Bad;
+
+ fclose( f );
+ return true;
+Bad:
+ if( f != NULL ) fclose(f);
+ return false;
+}
+
+#undef abort
+#undef TOKEN_END
+#undef TOKEN_NUM
+#undef TOKEN_LOW
+#undef TOKEN_UPP
+#undef TOKEN_LOX
+#undef TOKEN_UPX
+
+#endif
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/stack.h Tue Jun 07 13:32:20 2011 +0000
@@ -0,0 +1,49 @@
+#ifndef STACK_H
+#define STACK_H
+
+template<class T>
+class Stack
+{
+public:
+ T Data[50];
+ short Position;
+
+ Stack() : Position(0) {}
+
+ inline void Push( T v ) { if( Position < 50 ) Data[Position++] = v; }
+ inline T Pull() { if( Position ) return Data[--Position]; else return (T)NAKN; }
+
+ void Pull( T &a )
+ {
+ if( Position ) a = Data[--Position];
+ else a = (T)NAKN;
+ }
+ void Pull( T &b, T &a )
+ {
+ if( Position ) b = Data[--Position];
+ else b = (T)NAKN;
+ if( Position ) a = Data[--Position];
+ else a = (T)NAKN;
+ }
+ void Pull( T &c, T &b, T &a )
+ {
+ if( Position ) c = Data[--Position];
+ else c = (T)NAKN;
+ if( Position ) b = Data[--Position];
+ else b = (T)NAKN;
+ if( Position ) a = Data[--Position];
+ else a = (T)NAKN;
+ }
+ void Pull( T &d, T &c, T &b, T &a )
+ {
+ if( Position ) d = Data[--Position];
+ else d = (T)NAKN;
+ if( Position ) c = Data[--Position];
+ else c = (T)NAKN;
+ if( Position ) b = Data[--Position];
+ else b = (T)NAKN;
+ if( Position ) a = Data[--Position];
+ else a = (T)NAKN;
+ }
+};
+#endif
\ No newline at end of file