Bernard Escaillas
/
MidiTee
main.cpp@0:71d791204057, 2011-06-07 (annotated)
- Committer:
- Midimetric
- Date:
- Tue Jun 07 13:32:20 2011 +0000
- Revision:
- 0:71d791204057
Version 1.0
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Midimetric | 0:71d791204057 | 1 | #include "mbed.h" |
Midimetric | 0:71d791204057 | 2 | #include <vector> |
Midimetric | 0:71d791204057 | 3 | #include "MODSERIAL.h" |
Midimetric | 0:71d791204057 | 4 | |
Midimetric | 0:71d791204057 | 5 | DigitalOut led[4] = { LED1, LED2, LED3, LED4 }; |
Midimetric | 0:71d791204057 | 6 | MODSERIAL SL[] = { MODSERIAL( p28, p27, 32, 256 ), |
Midimetric | 0:71d791204057 | 7 | MODSERIAL( p13, p14, 32, 256 ), |
Midimetric | 0:71d791204057 | 8 | MODSERIAL( p9, p10, 32, 256 ) |
Midimetric | 0:71d791204057 | 9 | }; |
Midimetric | 0:71d791204057 | 10 | Timer tempo; |
Midimetric | 0:71d791204057 | 11 | 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. |
Midimetric | 0:71d791204057 | 12 | |
Midimetric | 0:71d791204057 | 13 | int AvailableMemory() |
Midimetric | 0:71d791204057 | 14 | { |
Midimetric | 0:71d791204057 | 15 | register int low = 0; |
Midimetric | 0:71d791204057 | 16 | register int mid = 0; |
Midimetric | 0:71d791204057 | 17 | register int high = 8001; |
Midimetric | 0:71d791204057 | 18 | void* p = NULL; |
Midimetric | 0:71d791204057 | 19 | |
Midimetric | 0:71d791204057 | 20 | while( high - low > 1 ) |
Midimetric | 0:71d791204057 | 21 | if( ( p = malloc( mid = ( low + high ) / 2 ) ) == NULL ) |
Midimetric | 0:71d791204057 | 22 | high = mid; |
Midimetric | 0:71d791204057 | 23 | else |
Midimetric | 0:71d791204057 | 24 | { |
Midimetric | 0:71d791204057 | 25 | free( p ); |
Midimetric | 0:71d791204057 | 26 | low = mid; |
Midimetric | 0:71d791204057 | 27 | } |
Midimetric | 0:71d791204057 | 28 | return low; |
Midimetric | 0:71d791204057 | 29 | } |
Midimetric | 0:71d791204057 | 30 | |
Midimetric | 0:71d791204057 | 31 | #include "midi.h" |
Midimetric | 0:71d791204057 | 32 | #include "stack.h" |
Midimetric | 0:71d791204057 | 33 | |
Midimetric | 0:71d791204057 | 34 | #include "memory.h" |
Midimetric | 0:71d791204057 | 35 | MemList ML; |
Midimetric | 0:71d791204057 | 36 | |
Midimetric | 0:71d791204057 | 37 | #include "filter.h" |
Midimetric | 0:71d791204057 | 38 | FilterList FL; |
Midimetric | 0:71d791204057 | 39 | |
Midimetric | 0:71d791204057 | 40 | #include "parse.h" |
Midimetric | 0:71d791204057 | 41 | |
Midimetric | 0:71d791204057 | 42 | byte Last[] = {0,0,0}; // last message type for ports 1,2,3 |
Midimetric | 0:71d791204057 | 43 | MidiM* Previous[3][17] = { |
Midimetric | 0:71d791204057 | 44 | {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}, |
Midimetric | 0:71d791204057 | 45 | {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}, |
Midimetric | 0:71d791204057 | 46 | {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL} |
Midimetric | 0:71d791204057 | 47 | }; // 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. |
Midimetric | 0:71d791204057 | 48 | |
Midimetric | 0:71d791204057 | 49 | void Data_in( int port /* 0,1,2*/ ) |
Midimetric | 0:71d791204057 | 50 | { |
Midimetric | 0:71d791204057 | 51 | int v = SL[port].getc(); |
Midimetric | 0:71d791204057 | 52 | if( v == 0xFE ) return; // active sensing |
Midimetric | 0:71d791204057 | 53 | |
Midimetric | 0:71d791204057 | 54 | led[port] = 1; |
Midimetric | 0:71d791204057 | 55 | |
Midimetric | 0:71d791204057 | 56 | MidiM* current = NULL; |
Midimetric | 0:71d791204057 | 57 | int beforelast = Last[port]; // backup in case of incomplete message |
Midimetric | 0:71d791204057 | 58 | // new command |
Midimetric | 0:71d791204057 | 59 | if( v > 0x7F ) // with explicit command |
Midimetric | 0:71d791204057 | 60 | current = MidiCreateMessage( Last[port] = v ); |
Midimetric | 0:71d791204057 | 61 | else if( Last[port] ) // with implicit command (same than before) |
Midimetric | 0:71d791204057 | 62 | { |
Midimetric | 0:71d791204057 | 63 | current = MidiCreateMessage( Last[port] ); |
Midimetric | 0:71d791204057 | 64 | current->Append( v ); |
Midimetric | 0:71d791204057 | 65 | } |
Midimetric | 0:71d791204057 | 66 | else // this is junk |
Midimetric | 0:71d791204057 | 67 | { |
Midimetric | 0:71d791204057 | 68 | led[port] = 0; |
Midimetric | 0:71d791204057 | 69 | return; |
Midimetric | 0:71d791204057 | 70 | } |
Midimetric | 0:71d791204057 | 71 | int ch = current->Channel == NAKW ? 16 : current->Channel; |
Midimetric | 0:71d791204057 | 72 | |
Midimetric | 0:71d791204057 | 73 | while( current->Next != NONE ) |
Midimetric | 0:71d791204057 | 74 | { |
Midimetric | 0:71d791204057 | 75 | tempo.reset(); |
Midimetric | 0:71d791204057 | 76 | tempo.start(); |
Midimetric | 0:71d791204057 | 77 | while( SL[port].rxBufferEmpty() ) |
Midimetric | 0:71d791204057 | 78 | { |
Midimetric | 0:71d791204057 | 79 | if( tempo.read_us() > 512 ) // normal rate should 256 us beetwen bytes. If twice that, assume message end is lost. |
Midimetric | 0:71d791204057 | 80 | { |
Midimetric | 0:71d791204057 | 81 | if( current->Type==BANK || current->Type==DATA || current->Type==RPN_ || current->Type==NRPN ) // LSB may be skipped |
Midimetric | 0:71d791204057 | 82 | { |
Midimetric | 0:71d791204057 | 83 | current->Next = NONE; |
Midimetric | 0:71d791204057 | 84 | break; |
Midimetric | 0:71d791204057 | 85 | } |
Midimetric | 0:71d791204057 | 86 | // else, abort reading this message without transmission |
Midimetric | 0:71d791204057 | 87 | tempo.stop(); |
Midimetric | 0:71d791204057 | 88 | Last[port] = beforelast; // forget last received command |
Midimetric | 0:71d791204057 | 89 | delete current; |
Midimetric | 0:71d791204057 | 90 | current = NULL; |
Midimetric | 0:71d791204057 | 91 | led[port] = 0; |
Midimetric | 0:71d791204057 | 92 | return; |
Midimetric | 0:71d791204057 | 93 | } |
Midimetric | 0:71d791204057 | 94 | } |
Midimetric | 0:71d791204057 | 95 | tempo.stop(); |
Midimetric | 0:71d791204057 | 96 | |
Midimetric | 0:71d791204057 | 97 | if( current->Next != NONE ) |
Midimetric | 0:71d791204057 | 98 | { |
Midimetric | 0:71d791204057 | 99 | int b = SL[port].getcNb(); |
Midimetric | 0:71d791204057 | 100 | if( ( b > -1 ) && ( b < 0xF8 ) ) // to ignore real time messages |
Midimetric | 0:71d791204057 | 101 | { |
Midimetric | 0:71d791204057 | 102 | if( ! current->Append( b ) ) |
Midimetric | 0:71d791204057 | 103 | { |
Midimetric | 0:71d791204057 | 104 | // not a pair message (for example: NRPN lsb not followed by msb but by DATA) |
Midimetric | 0:71d791204057 | 105 | if( current->Type==RPN_ || current->Type==NRPN || current->Type==BANK ) |
Midimetric | 0:71d791204057 | 106 | { |
Midimetric | 0:71d791204057 | 107 | if( Previous[ ch ][port] != NULL ) delete Previous[ ch ][port]; |
Midimetric | 0:71d791204057 | 108 | Previous[ ch ][port] = current; |
Midimetric | 0:71d791204057 | 109 | current = MidiCreateMessage( Last[port] ); |
Midimetric | 0:71d791204057 | 110 | if( current->Next != NONE ) |
Midimetric | 0:71d791204057 | 111 | current->Append( b ); |
Midimetric | 0:71d791204057 | 112 | } |
Midimetric | 0:71d791204057 | 113 | } |
Midimetric | 0:71d791204057 | 114 | } |
Midimetric | 0:71d791204057 | 115 | } |
Midimetric | 0:71d791204057 | 116 | } |
Midimetric | 0:71d791204057 | 117 | // now message is complete (or LSB/MSB from compound message will not follow) |
Midimetric | 0:71d791204057 | 118 | led[port] = 0; |
Midimetric | 0:71d791204057 | 119 | |
Midimetric | 0:71d791204057 | 120 | 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) |
Midimetric | 0:71d791204057 | 121 | if( current->Type != DATA && current->Type != INCR && current->Type != DECR ) |
Midimetric | 0:71d791204057 | 122 | { |
Midimetric | 0:71d791204057 | 123 | if( Previous[ ch ][port] != NULL ) delete Previous[ ch ][port]; |
Midimetric | 0:71d791204057 | 124 | Previous[ ch ][port] = current; |
Midimetric | 0:71d791204057 | 125 | current = NULL; |
Midimetric | 0:71d791204057 | 126 | } |
Midimetric | 0:71d791204057 | 127 | else |
Midimetric | 0:71d791204057 | 128 | delete current; |
Midimetric | 0:71d791204057 | 129 | |
Midimetric | 0:71d791204057 | 130 | } |
Midimetric | 0:71d791204057 | 131 | |
Midimetric | 0:71d791204057 | 132 | void Blinking( int ntimes ) |
Midimetric | 0:71d791204057 | 133 | { |
Midimetric | 0:71d791204057 | 134 | if( ntimes ) |
Midimetric | 0:71d791204057 | 135 | { |
Midimetric | 0:71d791204057 | 136 | for( int i = 0 ; i < ntimes ; i++ ) |
Midimetric | 0:71d791204057 | 137 | { |
Midimetric | 0:71d791204057 | 138 | led[3] = 1; |
Midimetric | 0:71d791204057 | 139 | wait(0.2); |
Midimetric | 0:71d791204057 | 140 | led[3] = 0; |
Midimetric | 0:71d791204057 | 141 | wait(0.6); |
Midimetric | 0:71d791204057 | 142 | } |
Midimetric | 0:71d791204057 | 143 | wait(2); |
Midimetric | 0:71d791204057 | 144 | } |
Midimetric | 0:71d791204057 | 145 | } |
Midimetric | 0:71d791204057 | 146 | |
Midimetric | 0:71d791204057 | 147 | int main() |
Midimetric | 0:71d791204057 | 148 | { |
Midimetric | 0:71d791204057 | 149 | for( int i = 0 ; i < 3 ; i++ ) SL[i].baud( 31250 ); |
Midimetric | 0:71d791204057 | 150 | |
Midimetric | 0:71d791204057 | 151 | if( ! Parse() ) |
Midimetric | 0:71d791204057 | 152 | { |
Midimetric | 0:71d791204057 | 153 | Blinking(ParseError); |
Midimetric | 0:71d791204057 | 154 | return 0; |
Midimetric | 0:71d791204057 | 155 | } |
Midimetric | 0:71d791204057 | 156 | |
Midimetric | 0:71d791204057 | 157 | while(1) |
Midimetric | 0:71d791204057 | 158 | { |
Midimetric | 0:71d791204057 | 159 | for( int i = 0 ; i < 3 ; i++ ) if( SL[i].readable() ) Data_in(i); |
Midimetric | 0:71d791204057 | 160 | } |
Midimetric | 0:71d791204057 | 161 | |
Midimetric | 0:71d791204057 | 162 | } |