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
|
}
|