Subversion Repositories svn.mios32

Rev

Rev 155 | Rev 191 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
32 tk 1
// $Id: mios32_midi.c 157 2008-12-06 01:32:12Z tk $
2
/*
3
 * MIDI layer functions for MIOS32
4
 *
33 tk 5
 * the mios32_midi_package_t format complies with USB MIDI spec (details see there)
6
 * and is used for transfers between other MIDI ports as well.
7
 *
32 tk 8
 * ==========================================================================
9
 *
10
 *  Copyright (C) 2008 Thorsten Klose (tk@midibox.org)
11
 *  Licensed for personal non-commercial use only.
12
 *  All other rights reserved.
13
 *
14
 * ==========================================================================
15
 */
16
 
17
/////////////////////////////////////////////////////////////////////////////
18
// Include files
19
/////////////////////////////////////////////////////////////////////////////
20
 
21
#include <mios32.h>
22
 
23
// this module can be optionally disabled in a local mios32_config.h file (included from mios32.h)
24
#if !defined(MIOS32_DONT_USE_MIDI)
25
 
26
 
27
/////////////////////////////////////////////////////////////////////////////
28
// Global variables
29
/////////////////////////////////////////////////////////////////////////////
30
 
80 tk 31
// this global array is read from MIOS32_IIC_MIDI and MIOS32_UART_MIDI to
32
// determine the number of MIDI bytes which are part of a package
33
const u8 mios32_midi_pcktype_num_bytes[16] = {
34
  0, // 0: invalid/reserved event
35
  0, // 1: invalid/reserved event
36
  2, // 2: two-byte system common messages like MTC, Song Select, etc.
37
  3, // 3: three-byte system common messages like SPP, etc.
38
  3, // 4: SysEx starts or continues
39
  1, // 5: Single-byte system common message or sysex sends with following single byte
40
  2, // 6: SysEx sends with following two bytes
41
  3, // 7: SysEx sends with following three bytes
42
  3, // 8: Note Off
43
  3, // 9: Note On
44
  3, // a: Poly-Key Press
45
  3, // b: Control Change
46
  2, // c: Program Change
47
  2, // d: Channel Pressure
48
  3, // e: PitchBend Change
49
  1  // f: single byte
50
};
32 tk 51
 
89 tk 52
// Number if expected bytes for a common MIDI event - 1
53
const u8 mios32_midi_expected_bytes_common[8] = {
54
  2, // Note On
55
  2, // Note Off
56
  2, // Poly Preasure
57
  2, // Controller
58
  1, // Program Change
59
  1, // Channel Preasure
60
  2, // Pitch Bender
61
  0, // System Message - must be zero, so that mios32_midi_expected_bytes_system[] will be used
62
};
80 tk 63
 
89 tk 64
// // Number if expected bytes for a system MIDI event - 1
65
const u8 mios32_midi_expected_bytes_system[16] = {
66
  1, // SysEx Begin (endless until SysEx End F7)
67
  1, // MTC Data frame
68
  2, // Song Position
69
  1, // Song Select
70
  0, // Reserved
71
  0, // Reserved
72
  0, // Request Tuning Calibration
73
  0, // SysEx End
74
 
75
  // Note: just only for documentation, Realtime Messages don't change the running status
76
  0, // MIDI Clock
77
  0, // MIDI Tick
78
  0, // MIDI Start
79
  0, // MIDI Continue
80
  0, // MIDI Stop
81
  0, // Reserved
82
  0, // Active Sense
83
  0, // Reset
84
};
85
 
86
 
32 tk 87
/////////////////////////////////////////////////////////////////////////////
88
// Local variables
89
/////////////////////////////////////////////////////////////////////////////
90
 
155 tk 91
static void (*direct_rx_callback_func)(mios32_midi_port_t port, u8 midi_byte);
92
static void (*direct_tx_callback_func)(mios32_midi_port_t port, u8 midi_byte);
32 tk 93
 
155 tk 94
 
32 tk 95
/////////////////////////////////////////////////////////////////////////////
96
// Initializes MIDI layer
110 tk 97
// IN: <mode>: currently only mode 0 supported
32 tk 98
// OUT: returns < 0 if initialisation failed
99
/////////////////////////////////////////////////////////////////////////////
100
s32 MIOS32_MIDI_Init(u32 mode)
101
{
102
  s32 ret = 0;
103
 
110 tk 104
  // currently only mode 0 supported
105
  if( mode != 0 )
32 tk 106
    return -1; // unsupported mode
107
 
155 tk 108
  // disable Rx/Tx callback functions
109
  direct_rx_callback_func = NULL;
110
  direct_tx_callback_func = NULL;
111
 
112
  // initialize interfaces
101 tk 113
#if !defined(MIOS32_DONT_USE_USB) && !defined(MIOS32_DONT_USE_USB_MIDI)
110 tk 114
  if( MIOS32_USB_MIDI_Init(0) < 0 )
32 tk 115
    ret |= (1 << 0);
116
#endif
117
 
80 tk 118
#if !defined(MIOS32_DONT_USE_UART) && !defined(MIOS32_DONT_USE_UART_MIDI)
110 tk 119
  if( MIOS32_UART_MIDI_Init(0) < 0 )
80 tk 120
    ret |= (1 << 1);
121
#endif
122
 
78 tk 123
#if !defined(MIOS32_DONT_USE_IIC) && !defined(MIOS32_DONT_USE_IIC_MIDI)
110 tk 124
  if( MIOS32_IIC_MIDI_Init(0) < 0 )
80 tk 125
    ret |= (1 << 2);
78 tk 126
#endif
127
 
32 tk 128
  return -ret;
129
}
130
 
131
 
132
/////////////////////////////////////////////////////////////////////////////
78 tk 133
// This function checks the availability of a MIDI port
134
// IN: <port>: MIDI port 
135
//             DEFAULT, USB0..USB7, UART0..UART1, IIC0..IIC7
136
// OUT: 1: port available
137
//      0: port not available
138
/////////////////////////////////////////////////////////////////////////////
139
s32 MIOS32_MIDI_CheckAvailable(mios32_midi_port_t port)
140
{
141
  // if default port: select mapped port
142
  if( !(port & 0xf0) ) {
143
    port = MIOS32_MIDI_DEFAULT_PORT;
144
  }
145
 
146
  // branch depending on selected port
147
  switch( port >> 4 ) {
148
    case 1:
149
#if !defined(MIOS32_DONT_USE_USB) && !defined(MIOS32_DONT_USE_USB_MIDI)
150
      return MIOS32_USB_MIDI_CheckAvailable();
151
#else
152
      return 0; // USB has been disabled
153
#endif
154
 
155
    case 2:
80 tk 156
#if !defined(MIOS32_DONT_USE_UART) && !defined(MIOS32_DONT_USE_UART_MIDI)
157
      return MIOS32_UART_MIDI_CheckAvailable(port & 0xf);
158
#else
159
      return 0; // UART_MIDI has been disabled
160
#endif
78 tk 161
 
162
    case 3:
163
#if !defined(MIOS32_DONT_USE_IIC) && !defined(MIOS32_DONT_USE_IIC_MIDI)
164
      return MIOS32_IIC_MIDI_CheckAvailable(port & 0xf);
165
#else
166
      return 0; // IIC_MIDI has been disabled
167
#endif
168
 
169
    case 4:
170
      return 0; // Ethernet not implemented yet
171
 
172
    default:
173
      // invalid port
174
      return 0;
175
  }
176
}
177
 
178
 
179
/////////////////////////////////////////////////////////////////////////////
32 tk 180
// Sends a package over given port
110 tk 181
// This is a low level function. In difference to other MIOS32_MIDI_Send* functions,
182
// It allows to send packages in non-blocking mode (caller has to retry if -2 is returned)
183
// IN: <port>: MIDI port 
184
//             DEFAULT, USB0..USB7, UART0..UART1, IIC0..IIC7
185
//     <package>: MIDI package (see definition in mios32_midi.h)
186
// OUT: returns -1 if port not available
187
//      returns -2 buffer is full
188
//                 caller should retry until buffer is free again
189
//      returns 0 on success
190
/////////////////////////////////////////////////////////////////////////////
191
s32 MIOS32_MIDI_SendPackage_NonBlocking(mios32_midi_port_t port, mios32_midi_package_t package)
192
{
193
  // if default port: select mapped port
194
  if( !(port & 0xf0) ) {
195
    port = MIOS32_MIDI_DEFAULT_PORT;
196
  }
197
 
198
  // insert subport number into package
199
  package.cable = port & 0xf;
200
 
201
  // branch depending on selected port
202
  switch( port >> 4 ) {
203
    case 1:
204
#if !defined(MIOS32_DONT_USE_USB) && !defined(MIOS32_DONT_USE_USB_MIDI)
205
      return MIOS32_USB_MIDI_MIDIPackageSend_NonBlocking(package);
206
#else
207
      return -1; // USB has been disabled
208
#endif
209
 
210
    case 2:
211
#if !defined(MIOS32_DONT_USE_UART) && !defined(MIOS32_DONT_USE_UART_MIDI)
212
      return MIOS32_UART_MIDI_PackageSend_NonBlocking(package.cable, package);
213
#else
214
      return -1; // UART_MIDI has been disabled
215
#endif
216
 
217
    case 3:
218
#if !defined(MIOS32_DONT_USE_IIC) && !defined(MIOS32_DONT_USE_IIC_MIDI)
219
      return MIOS32_IIC_MIDI_PackageSend_NonBlocking(package.cable, package);
220
#else
221
      return -1; // IIC_MIDI has been disabled
222
#endif
223
 
224
    case 4:
225
      return -1; // Ethernet not implemented yet
226
 
227
    default:
228
      // invalid port
229
      return -1;
230
  }
231
}
232
 
233
 
234
/////////////////////////////////////////////////////////////////////////////
235
// Sends a package over given port
33 tk 236
// This is a low level function - use the remaining MIOS32_MIDI_Send* functions
237
// to send specific MIDI events
110 tk 238
// (blocking function)
32 tk 239
// IN: <port>: MIDI port 
78 tk 240
//             DEFAULT, USB0..USB7, UART0..UART1, IIC0..IIC7
32 tk 241
//     <package>: MIDI package (see definition in mios32_midi.h)
242
// OUT: returns -1 if port not available
243
//      returns 0 on success
244
/////////////////////////////////////////////////////////////////////////////
69 tk 245
s32 MIOS32_MIDI_SendPackage(mios32_midi_port_t port, mios32_midi_package_t package)
32 tk 246
{
80 tk 247
  // if default port: select mapped port
248
  if( !(port & 0xf0) ) {
249
    port = MIOS32_MIDI_DEFAULT_PORT;
250
  }
251
 
32 tk 252
  // insert subport number into package
89 tk 253
  package.cable = port & 0xf;
32 tk 254
 
255
  // branch depending on selected port
256
  switch( port >> 4 ) {
80 tk 257
    case 1:
78 tk 258
#if !defined(MIOS32_DONT_USE_USB) && !defined(MIOS32_DONT_USE_USB_MIDI)
259
      return MIOS32_USB_MIDI_MIDIPackageSend(package);
32 tk 260
#else
261
      return -1; // USB has been disabled
262
#endif
263
 
80 tk 264
    case 2:
265
#if !defined(MIOS32_DONT_USE_UART) && !defined(MIOS32_DONT_USE_UART_MIDI)
266
      return MIOS32_UART_MIDI_PackageSend(package.cable, package);
267
#else
268
      return -1; // UART_MIDI has been disabled
269
#endif
32 tk 270
 
80 tk 271
    case 3:
78 tk 272
#if !defined(MIOS32_DONT_USE_IIC) && !defined(MIOS32_DONT_USE_IIC_MIDI)
273
      return MIOS32_IIC_MIDI_PackageSend(package.cable, package);
274
#else
275
      return -1; // IIC_MIDI has been disabled
276
#endif
32 tk 277
 
80 tk 278
    case 4:
32 tk 279
      return -1; // Ethernet not implemented yet
280
 
281
    default:
282
      // invalid port
283
      return -1;
284
  }
285
}
286
 
287
 
288
/////////////////////////////////////////////////////////////////////////////
33 tk 289
// Sends a MIDI Event
290
// This function is provided for a more comfortable use model
291
//    o MIOS32_MIDI_SendNoteOff(port, chn, note, vel)
292
//    o MIOS32_MIDI_SendNoteOn(port, chn, note, vel)
293
//    o MIOS32_MIDI_SendPolyAftertouch(port, chn, note, val)
294
//    o MIOS32_MIDI_SendCC(port, chn, cc, val)
295
//    o MIOS32_MIDI_SendProgramChange(port, chn, prg)
296
//    o MIOS32_MIDI_ChannelAftertouch(port, chn, val)
297
//    o MIOS32_MIDI_PitchBend(port, chn, val)
298
//
299
// IN: <port>: MIDI port 
300
//     <evnt0> <evnt1> <evnt2> up to 3 bytes
301
// OUT: returns -1 if port not available
302
//      returns 0 on success
32 tk 303
/////////////////////////////////////////////////////////////////////////////
69 tk 304
s32 MIOS32_MIDI_SendEvent(mios32_midi_port_t port, u8 evnt0, u8 evnt1, u8 evnt2)
32 tk 305
{
33 tk 306
  mios32_midi_package_t package;
307
 
308
  // MEMO: don't optimize this function by calling MIOS32_MIDI_SendSpecialEvent
309
  // from here, because the 4 * u8 parameter list of this function leads
310
  // to best compile results (4*u8 combined to a single u32)
311
 
312
  package.type  = evnt0 >> 4;
313
  package.evnt0 = evnt0;
314
  package.evnt1 = evnt1;
315
  package.evnt2 = evnt2;
316
  return MIOS32_MIDI_SendPackage(port, package);
32 tk 317
}
318
 
69 tk 319
s32 MIOS32_MIDI_SendNoteOff(mios32_midi_port_t port, mios32_midi_chn_t chn, u8 note, u8 vel)
136 tk 320
{ return MIOS32_MIDI_SendEvent(port, 0x80 | chn, note, vel); }
32 tk 321
 
69 tk 322
s32 MIOS32_MIDI_SendNoteOn(mios32_midi_port_t port, mios32_midi_chn_t chn, u8 note, u8 vel)
136 tk 323
{ return MIOS32_MIDI_SendEvent(port, 0x90 | chn, note, vel); }
69 tk 324
 
325
s32 MIOS32_MIDI_SendPolyPressure(mios32_midi_port_t port, mios32_midi_chn_t chn, u8 note, u8 val)
136 tk 326
{ return MIOS32_MIDI_SendEvent(port, 0xa0 | chn, note, val); }
69 tk 327
 
328
s32 MIOS32_MIDI_SendCC(mios32_midi_port_t port, mios32_midi_chn_t chn, u8 cc, u8 val)
136 tk 329
{ return MIOS32_MIDI_SendEvent(port, 0xb0 | chn, cc,   val); }
69 tk 330
 
331
s32 MIOS32_MIDI_SendProgramChange(mios32_midi_port_t port, mios32_midi_chn_t chn, u8 prg)
136 tk 332
{ return MIOS32_MIDI_SendEvent(port, 0xc0 | chn, prg,  0x00); }
69 tk 333
 
334
s32 MIOS32_MIDI_SendAftertouch(mios32_midi_port_t port, mios32_midi_chn_t chn, u8 val)
136 tk 335
{ return MIOS32_MIDI_SendEvent(port, 0xd0 | chn, val,  0x00); }
69 tk 336
 
337
s32 MIOS32_MIDI_SendPitchBend(mios32_midi_port_t port, mios32_midi_chn_t chn, u16 val)
136 tk 338
{ return MIOS32_MIDI_SendEvent(port, 0xe0 | chn, val & 0x7f, val >> 7); }
69 tk 339
 
340
 
33 tk 341
/////////////////////////////////////////////////////////////////////////////
342
// Sends a special type MIDI Event
343
// This function is provided for a more comfortable use model
69 tk 344
// It is aliased to following functions
33 tk 345
//    o MIOS32_MIDI_SendMTC(port, val)
346
//    o MIOS32_MIDI_SendSongPosition(port, val)
347
//    o MIOS32_MIDI_SendSongSelect(port, val)
348
//    o MIOS32_MIDI_SendTuneRequest()
349
//    o MIOS32_MIDI_SendClock()
350
//    o MIOS32_MIDI_SendTick()
351
//    o MIOS32_MIDI_SendStart()
352
//    o MIOS32_MIDI_SendStop()
353
//    o MIOS32_MIDI_SendContinue()
354
//    o MIOS32_MIDI_SendActiveSense()
355
//    o MIOS32_MIDI_SendReset()
356
//
357
// IN: <port>: MIDI port 
358
//     <type>: the event type
359
//     <evnt0> <evnt1> <evnt2> up to 3 bytes
360
// OUT: returns -1 if port not available
361
//      returns 0 on success
362
/////////////////////////////////////////////////////////////////////////////
69 tk 363
s32 MIOS32_MIDI_SendSpecialEvent(mios32_midi_port_t port, u8 type, u8 evnt0, u8 evnt1, u8 evnt2)
33 tk 364
{
365
  mios32_midi_package_t package;
366
 
367
  package.type  = type;
368
  package.evnt0 = evnt0;
369
  package.evnt1 = evnt1;
370
  package.evnt2 = evnt2;
371
  return MIOS32_MIDI_SendPackage(port, package);
372
}
373
 
374
 
69 tk 375
s32 MIOS32_MIDI_SendMTC(mios32_midi_port_t port, u8 val)
136 tk 376
{ return MIOS32_MIDI_SendSpecialEvent(port, 0x2, 0xf1, val, 0x00); }
69 tk 377
 
378
s32 MIOS32_MIDI_SendSongPosition(mios32_midi_port_t port, u16 val)
136 tk 379
{ return MIOS32_MIDI_SendSpecialEvent(port, 0x3, 0xf2, val & 0x7f, val >> 7); }
69 tk 380
 
381
s32 MIOS32_MIDI_SendSongSelect(mios32_midi_port_t port, u8 val)
136 tk 382
{ return MIOS32_MIDI_SendSpecialEvent(port, 0x2, 0xf3, val, 0x00); }
69 tk 383
 
384
s32 MIOS32_MIDI_SendTuneRequest(mios32_midi_port_t port)
136 tk 385
{ return MIOS32_MIDI_SendSpecialEvent(port, 0x5, 0xf6, 0x00, 0x00); }
69 tk 386
 
387
s32 MIOS32_MIDI_SendClock(mios32_midi_port_t port)
136 tk 388
{ return MIOS32_MIDI_SendSpecialEvent(port, 0x5, 0xf8, 0x00, 0x00); }
69 tk 389
 
390
s32 MIOS32_MIDI_SendTick(mios32_midi_port_t port)
136 tk 391
{ return MIOS32_MIDI_SendSpecialEvent(port, 0x5, 0xf9, 0x00, 0x00); }
69 tk 392
 
393
s32 MIOS32_MIDI_SendStart(mios32_midi_port_t port)
136 tk 394
{ return MIOS32_MIDI_SendSpecialEvent(port, 0x5, 0xfa, 0x00, 0x00); }
69 tk 395
 
396
s32 MIOS32_MIDI_SendStop(mios32_midi_port_t port)
136 tk 397
{ return MIOS32_MIDI_SendSpecialEvent(port, 0x5, 0xfb, 0x00, 0x00); }
69 tk 398
 
399
s32 MIOS32_MIDI_SendContinue(mios32_midi_port_t port)
136 tk 400
{ return MIOS32_MIDI_SendSpecialEvent(port, 0x5, 0xfc, 0x00, 0x00); }
69 tk 401
 
402
s32 MIOS32_MIDI_SendActiveSense(mios32_midi_port_t port)
136 tk 403
{ return MIOS32_MIDI_SendSpecialEvent(port, 0x5, 0xfe, 0x00, 0x00); }
69 tk 404
 
405
s32 MIOS32_MIDI_SendReset(mios32_midi_port_t port)
136 tk 406
{ return MIOS32_MIDI_SendSpecialEvent(port, 0x5, 0xff, 0x00, 0x00); }
69 tk 407
 
408
 
33 tk 409
/////////////////////////////////////////////////////////////////////////////
410
// Sends a SysEx Stream
411
// This function is provided for a more comfortable use model
412
// IN: <port>: MIDI port 
413
//     <stream>: pointer to SysEx stream
414
//     <count>: number of bytes
415
// OUT: returns -1 if port not available
416
//      returns 0 on success
417
/////////////////////////////////////////////////////////////////////////////
69 tk 418
s32 MIOS32_MIDI_SendSysEx(mios32_midi_port_t port, u8 *stream, u32 count)
33 tk 419
{
420
  s32 res;
421
  u32 offset;
422
  mios32_midi_package_t package;
423
 
424
  // MEMO: have a look into the project.lss file - gcc optimizes this code pretty well :)
425
 
426
  for(offset=0; offset<count;) {
427
    // package type depends on number of remaining bytes
428
    switch( count-offset ) {
429
      case 1:
430
    package.type = 0x5; // SysEx ends with following single byte. 
431
    package.evnt0 = stream[offset++];
432
    package.evnt1 = 0x00;
433
    package.evnt2 = 0x00;
434
    break;
435
      case 2:
436
    package.type = 0x6; // SysEx ends with following two bytes.
437
    package.evnt0 = stream[offset++];
438
    package.evnt1 = stream[offset++];
439
    package.evnt2 = 0x00;
440
    break;
441
      case 3:
442
    package.type = 0x7; // SysEx ends with following three bytes. 
443
    package.evnt0 = stream[offset++];
444
    package.evnt1 = stream[offset++];
445
    package.evnt2 = stream[offset++];
446
    break;
447
      default:
448
    package.type = 0x4; // SysEx starts or continues
449
    package.evnt0 = stream[offset++];
450
    package.evnt1 = stream[offset++];
451
    package.evnt2 = stream[offset++];
452
    }
453
 
110 tk 454
    res=MIOS32_MIDI_SendPackage(port, package);
33 tk 455
 
110 tk 456
    // expection? (e.g., port not available)
33 tk 457
    if( res < 0 )
458
      return res;
459
  }
460
 
461
  return 0;
462
}
463
 
464
 
465
/////////////////////////////////////////////////////////////////////////////
466
// Checks for incoming MIDI messages, calls either the callback_event or
467
// callback_sysex function with following parameters:
69 tk 468
//    callback_event(mios32_midi_port_t port, mios32_midi_package_t midi_package)
469
//    callback_sysex(mios32_midi_port_t port, u8 sysex_byte)
33 tk 470
// OUT: returns < 0 on errors
471
/////////////////////////////////////////////////////////////////////////////
472
s32 MIOS32_MIDI_Receive_Handler(void *_callback_event, void *_callback_sysex)
473
{
474
  u8 port;
475
  mios32_midi_package_t package;
476
 
69 tk 477
  void (*callback_event)(mios32_midi_port_t port, mios32_midi_package_t midi_package) = _callback_event;
478
  void (*callback_sysex)(mios32_midi_port_t port, u8 sysex_byte) = _callback_sysex;
33 tk 479
 
78 tk 480
  u8 intf = 0; // interface to be checked
481
  u8 total_packages_forwarded = 0; // number of forwards - stop after 10 forwards to yield some CPU time for other tasks
482
  u8 packages_forwarded = 0;
483
  u8 again = 1;
33 tk 484
  do {
78 tk 485
    // Round Robin
486
    // TODO: maybe a list based approach would be better
487
    // it would allow to add/remove interfaces dynamically
488
    // this would also allow to give certain ports a higher priority (to add them multiple times to the list)
489
    // it would also improve this spagetthi code ;)
490
    s32 error = -1;
491
    switch( intf++ ) {
492
#if !defined(MIOS32_DONT_USE_USB) && !defined(MIOS32_DONT_USE_USB_MIDI)
105 tk 493
      case 0: error = MIOS32_USB_MIDI_MIDIPackageReceive(&package); port = USB0 + package.cable; break;
78 tk 494
#else
495
      case 0: error = -1; break;
496
#endif
126 tk 497
#if !defined(MIOS32_DONT_USE_UART) && !defined(MIOS32_DONT_USE_UART_MIDI) && MIOS32_UART0_ASSIGNMENT == 1
80 tk 498
      case 1: error = MIOS32_UART_MIDI_PackageReceive(0, &package); port = UART0; break;
78 tk 499
#else
500
      case 1: error = -1; break;
501
#endif
126 tk 502
#if !defined(MIOS32_DONT_USE_UART) && !defined(MIOS32_DONT_USE_UART_MIDI) && MIOS32_UART1_ASSIGNMENT == 1
80 tk 503
      case 2: error = MIOS32_UART_MIDI_PackageReceive(1, &package); port = UART1; break;
78 tk 504
#else
505
      case 2: error = -1; break;
506
#endif
507
#if !defined(MIOS32_DONT_USE_IIC) && !defined(MIOS32_DONT_USE_IIC_MIDI)
80 tk 508
      case 3: error = MIOS32_IIC_MIDI_PackageReceive(0, &package); port = IIC0; break;
78 tk 509
#else
510
      case 3: error = -1; break;
511
#endif
512
#if !defined(MIOS32_DONT_USE_IIC) && !defined(MIOS32_DONT_USE_IIC_MIDI)
80 tk 513
      case 4: error = MIOS32_IIC_MIDI_PackageReceive(1, &package); port = IIC1; break;
78 tk 514
#else
515
      case 4: error = -1; break;
516
#endif
517
#if !defined(MIOS32_DONT_USE_IIC) && !defined(MIOS32_DONT_USE_IIC_MIDI)
80 tk 518
      case 5: error = MIOS32_IIC_MIDI_PackageReceive(2, &package); port = IIC2; break;
78 tk 519
#else
520
      case 5: error = -1; break;
521
#endif
522
#if !defined(MIOS32_DONT_USE_IIC) && !defined(MIOS32_DONT_USE_IIC_MIDI)
80 tk 523
      case 6: error = MIOS32_IIC_MIDI_PackageReceive(3, &package); port = IIC3; break;
78 tk 524
#else
525
      case 6: error = -1; break;
526
#endif
527
#if !defined(MIOS32_DONT_USE_IIC) && !defined(MIOS32_DONT_USE_IIC_MIDI)
80 tk 528
      case 7: error = MIOS32_IIC_MIDI_PackageReceive(4, &package); port = IIC4; break;
78 tk 529
#else
530
      case 7: error = -1; break;
531
#endif
532
#if !defined(MIOS32_DONT_USE_IIC) && !defined(MIOS32_DONT_USE_IIC_MIDI)
80 tk 533
      case 8: error = MIOS32_IIC_MIDI_PackageReceive(5, &package); port = IIC5; break;
78 tk 534
#else
535
      case 8: error = -1; break;
536
#endif
80 tk 537
#if !defined(MIOS32_DONT_USE_IIC) && !defined(MIOS32_DONT_USE_IIC_MIDI)
538
      case 9: error = MIOS32_IIC_MIDI_PackageReceive(6, &package); port = IIC6; break;
539
#else
540
      case 9: error = -1; break;
541
#endif
542
#if !defined(MIOS32_DONT_USE_IIC) && !defined(MIOS32_DONT_USE_IIC_MIDI)
543
      case 10: error = MIOS32_IIC_MIDI_PackageReceive(7, &package); port = IIC7; break;
544
#else
545
      case 10: error = -1; break;
546
#endif
78 tk 547
      default:
548
    // allow 10 forwards maximum to yield some CPU time for other tasks
549
    if( packages_forwarded && total_packages_forwarded < 10 ) {
550
      intf = 0; // restart with USB
551
      packages_forwarded = 0; // for checking, if packages still have been forwarded in next round
552
    } else {
553
      again = 0; // no more interfaces to be processed
554
    }
555
    error = -1; // empty round - no message
556
    }
33 tk 557
 
78 tk 558
    // message received?
559
    if( error >= 0 ) {
560
      // notify that a package has been forwarded
561
      ++packages_forwarded;
562
      ++total_packages_forwarded;
33 tk 563
 
78 tk 564
      // remove cable number from package (MIOS32_MIDI passes it's own port number)
69 tk 565
      package.cable = 0;
33 tk 566
 
78 tk 567
      // branch depending on package type
33 tk 568
      if( package.type >= 0x8 ) {
569
    callback_event(port, package);
570
      } else {
571
    switch( package.type ) {
572
    case 0x0: // reserved, ignore
573
    case 0x1: // cable events, ignore
574
      break;
575
 
576
    case 0x2: // Two-byte System Common messages like MTC, SongSelect, etc. 
577
    case 0x3: // Three-byte System Common messages like SPP, etc. 
578
      callback_event(port, package); // -> forwarded as event
579
      break;
580
    case 0x4: // SysEx starts or continues (3 bytes)
581
      callback_sysex(port, package.evnt0); // -> forwarded as SysEx
582
      callback_sysex(port, package.evnt1); // -> forwarded as SysEx
583
      callback_sysex(port, package.evnt2); // -> forwarded as SysEx
584
      break;
585
    case 0x5: // Single-byte System Common Message or SysEx ends with following single byte. 
586
      if( package.evnt0 >= 0xf8 )
587
        callback_event(port, package); // -> forwarded as event
588
      else
589
        callback_sysex(port, package.evnt0); // -> forwarded as SysEx
590
      break;
591
    case 0x6: // SysEx ends with following two bytes.
592
      callback_sysex(port, package.evnt0); // -> forwarded as SysEx
593
      callback_sysex(port, package.evnt1); // -> forwarded as SysEx
594
      break;
595
    case 0x7: // SysEx ends with following three bytes.
596
      callback_sysex(port, package.evnt0); // -> forwarded as SysEx
597
      callback_sysex(port, package.evnt1); // -> forwarded as SysEx
598
      callback_sysex(port, package.evnt2); // -> forwarded as SysEx
599
      break;
600
    }
601
      }
602
    }
603
  } while( again );
604
 
605
  return 0;
606
}
607
 
608
 
155 tk 609
/////////////////////////////////////////////////////////////////////////////
610
// Installs Rx/Tx callback functions which are executed immediately on each
611
// incoming/outgoing MIDI byte, partly from interrupt handlers with following
612
// parameters:
613
//    callback_rx(mios32_midi_port_t port, u8 midi_byte);
614
//    callback_tx(mios32_midi_port_t port, u8 midi_byte);
615
//
616
// These functions should be executed so fast as possible. They can be used
617
// to trigger MIDI Rx/Tx LEDs or to trigger on MIDI clock events. In order to
618
// avoid MIDI buffer overruns, the max. recommented execution time is 100 uS!
619
// OUT: returns < 0 on errors
620
/////////////////////////////////////////////////////////////////////////////
621
s32 MIOS32_MIDI_DirectRxTxCallback_Init(void *callback_rx, void *callback_tx)
622
{
623
  direct_rx_callback_func = callback_rx;
624
  direct_tx_callback_func = callback_tx;
157 tk 625
 
626
  return 0; // no error
155 tk 627
}
628
 
629
 
630
/////////////////////////////////////////////////////////////////////////////
631
// This function is used by MIOS32 internal functions to forward received
632
// MIDI bytes to the Rx Callback routine
633
/////////////////////////////////////////////////////////////////////////////
634
s32 MIOS32_MIDI_SendByteToRxCallback(mios32_midi_port_t port, u8 midi_byte)
635
{
636
  // note: here we could filter the user hook execution on special situations
637
  if( direct_rx_callback_func != NULL )
638
    direct_rx_callback_func(port, midi_byte);
157 tk 639
  return 0; // no error
155 tk 640
}
641
 
642
/////////////////////////////////////////////////////////////////////////////
643
// This function is used by MIOS32 internal functions to forward received
644
// MIDI packages to the Rx Callback routine (byte by byte)
645
/////////////////////////////////////////////////////////////////////////////
646
s32 MIOS32_MIDI_SendPackageToRxCallback(mios32_midi_port_t port, mios32_midi_package_t midi_package)
647
{
648
  // note: here we could filter the user hook execution on special situations
649
  if( direct_rx_callback_func != NULL ) {
650
    u8 buffer[3] = {midi_package.evnt0, midi_package.evnt1, midi_package.evnt2};
651
    int len = mios32_midi_pcktype_num_bytes[midi_package.cin];
652
    int i;
653
    for(i=0; i<len; ++i)
654
      direct_rx_callback_func(port, buffer[i]);
655
  }
157 tk 656
  return 0; // no error
155 tk 657
}
658
 
659
/////////////////////////////////////////////////////////////////////////////
660
// This function is used by MIOS32 internal functions to forward received
661
// MIDI bytes to the Tx Callback routine
662
/////////////////////////////////////////////////////////////////////////////
663
s32 MIOS32_MIDI_SendByteToTxCallback(mios32_midi_port_t port, u8 midi_byte)
664
{
665
  // note: here we could filter the user hook execution on special situations
666
  if( direct_tx_callback_func != NULL )
667
    direct_tx_callback_func(port, midi_byte);
157 tk 668
  return 0; // no error
155 tk 669
}
670
 
671
/////////////////////////////////////////////////////////////////////////////
672
// This function is used by MIOS32 internal functions to forward received
673
// MIDI packages to the Tx Callback routine (byte by byte)
674
/////////////////////////////////////////////////////////////////////////////
675
s32 MIOS32_MIDI_SendPackageToTxCallback(mios32_midi_port_t port, mios32_midi_package_t midi_package)
676
{
677
  // note: here we could filter the user hook execution on special situations
678
  if( direct_tx_callback_func != NULL ) {
679
    u8 buffer[3] = {midi_package.evnt0, midi_package.evnt1, midi_package.evnt2};
680
    int len = mios32_midi_pcktype_num_bytes[midi_package.cin];
681
    int i;
682
    for(i=0; i<len; ++i)
683
      direct_tx_callback_func(port, buffer[i]);
684
  }
157 tk 685
  return 0; // no error
155 tk 686
}
687
 
688
 
32 tk 689
#endif /* MIOS32_DONT_USE_MIDI */