Subversion Repositories svn.mios32

Rev

Rev 225 | Rev 231 | 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 230 2009-01-01 16:47:08Z tk $
211 tk 2
//! \defgroup MIOS32_MIDI
3
//!
4
//! MIDI layer functions for MIOS32
5
//!
6
//! the mios32_midi_package_t format complies with USB MIDI spec (details see there)
7
//! and is used for transfers between other MIDI ports as well.
8
//!
9
//! \{
10
/* ==========================================================================
32 tk 11
 *
12
 *  Copyright (C) 2008 Thorsten Klose (tk@midibox.org)
13
 *  Licensed for personal non-commercial use only.
14
 *  All other rights reserved.
15
 *
16
 * ==========================================================================
17
 */
18
 
19
/////////////////////////////////////////////////////////////////////////////
20
// Include files
21
/////////////////////////////////////////////////////////////////////////////
22
 
23
#include <mios32.h>
24
 
25
// this module can be optionally disabled in a local mios32_config.h file (included from mios32.h)
26
#if !defined(MIOS32_DONT_USE_MIDI)
27
 
28
 
29
/////////////////////////////////////////////////////////////////////////////
30
// Global variables
31
/////////////////////////////////////////////////////////////////////////////
32
 
211 tk 33
//! this global array is read from MIOS32_IIC_MIDI and MIOS32_UART_MIDI to
34
//! determine the number of MIDI bytes which are part of a package
80 tk 35
const u8 mios32_midi_pcktype_num_bytes[16] = {
36
  0, // 0: invalid/reserved event
37
  0, // 1: invalid/reserved event
38
  2, // 2: two-byte system common messages like MTC, Song Select, etc.
39
  3, // 3: three-byte system common messages like SPP, etc.
40
  3, // 4: SysEx starts or continues
41
  1, // 5: Single-byte system common message or sysex sends with following single byte
42
  2, // 6: SysEx sends with following two bytes
43
  3, // 7: SysEx sends with following three bytes
44
  3, // 8: Note Off
45
  3, // 9: Note On
46
  3, // a: Poly-Key Press
47
  3, // b: Control Change
48
  2, // c: Program Change
49
  2, // d: Channel Pressure
50
  3, // e: PitchBend Change
51
  1  // f: single byte
52
};
32 tk 53
 
211 tk 54
//! Number if expected bytes for a common MIDI event - 1
89 tk 55
const u8 mios32_midi_expected_bytes_common[8] = {
56
  2, // Note On
57
  2, // Note Off
58
  2, // Poly Preasure
59
  2, // Controller
60
  1, // Program Change
61
  1, // Channel Preasure
62
  2, // Pitch Bender
63
  0, // System Message - must be zero, so that mios32_midi_expected_bytes_system[] will be used
64
};
80 tk 65
 
211 tk 66
//! Number if expected bytes for a system MIDI event - 1
89 tk 67
const u8 mios32_midi_expected_bytes_system[16] = {
68
  1, // SysEx Begin (endless until SysEx End F7)
69
  1, // MTC Data frame
70
  2, // Song Position
71
  1, // Song Select
72
  0, // Reserved
73
  0, // Reserved
74
  0, // Request Tuning Calibration
75
  0, // SysEx End
76
 
77
  // Note: just only for documentation, Realtime Messages don't change the running status
78
  0, // MIDI Clock
79
  0, // MIDI Tick
80
  0, // MIDI Start
81
  0, // MIDI Continue
82
  0, // MIDI Stop
83
  0, // Reserved
84
  0, // Active Sense
85
  0, // Reset
86
};
87
 
225 tk 88
//! should only be used by MIOS32 internally and by the Bootloader!
89
const u8 mios32_midi_sysex_header[5] = { 0xf0, 0x00, 0x00, 0x7e, 0x32 };
89 tk 90
 
225 tk 91
 
32 tk 92
/////////////////////////////////////////////////////////////////////////////
225 tk 93
// Local types
94
/////////////////////////////////////////////////////////////////////////////
95
 
96
typedef union {
97
  struct {
98
    unsigned ALL:8;
99
  };
100
 
101
  struct {
102
    unsigned CTR:3;
103
    unsigned CMD:1;
104
    unsigned MY_SYSEX:1;
105
  };
106
} sysex_state_t;
107
 
108
 
109
/////////////////////////////////////////////////////////////////////////////
32 tk 110
// Local variables
111
/////////////////////////////////////////////////////////////////////////////
112
 
225 tk 113
static mios32_midi_port_t default_port = MIOS32_MIDI_DEFAULT_PORT;
114
 
155 tk 115
static void (*direct_rx_callback_func)(mios32_midi_port_t port, u8 midi_byte);
116
static void (*direct_tx_callback_func)(mios32_midi_port_t port, u8 midi_byte);
32 tk 117
 
225 tk 118
static sysex_state_t sysex_state;
119
static u8 sysex_device_id;
120
static u8 sysex_cmd;
121
static mios32_midi_port_t last_sysex_port = DEFAULT;
155 tk 122
 
225 tk 123
 
32 tk 124
/////////////////////////////////////////////////////////////////////////////
225 tk 125
// Local prototypes
126
/////////////////////////////////////////////////////////////////////////////
127
 
128
static s32 MIOS32_MIDI_SYSEX_Parser(mios32_midi_port_t port, u8 midi_in);
129
static s32 MIOS32_MIDI_SYSEX_CmdFinished(void);
130
static s32 MIOS32_MIDI_SYSEX_Cmd(mios32_midi_port_t port, mios32_midi_sysex_cmd_state_t cmd_state, u8 midi_in);
230 tk 131
static s32 MIOS32_MIDI_SYSEX_Cmd_Query(mios32_midi_port_t port, mios32_midi_sysex_cmd_state_t cmd_state, u8 midi_in);
225 tk 132
static s32 MIOS32_MIDI_SYSEX_Cmd_Ping(mios32_midi_port_t port, mios32_midi_sysex_cmd_state_t cmd_state, u8 midi_in);
133
static s32 MIOS32_MIDI_SYSEX_SendAck(mios32_midi_port_t port, u8 ack_code, u8 ack_arg);
230 tk 134
static s32 MIOS32_MIDI_SYSEX_SendAckStr(mios32_midi_port_t port, char *str);
225 tk 135
 
136
 
137
/////////////////////////////////////////////////////////////////////////////
211 tk 138
//! Initializes MIDI layer
139
//! \param[in] mode currently only mode 0 supported
140
//! \return < 0 if initialisation failed
32 tk 141
/////////////////////////////////////////////////////////////////////////////
142
s32 MIOS32_MIDI_Init(u32 mode)
143
{
144
  s32 ret = 0;
145
 
110 tk 146
  // currently only mode 0 supported
147
  if( mode != 0 )
32 tk 148
    return -1; // unsupported mode
149
 
225 tk 150
  // set default port as defined in mios32.h/mios32_config.h
151
  default_port = MIOS32_MIDI_DEFAULT_PORT;
152
 
155 tk 153
  // disable Rx/Tx callback functions
154
  direct_rx_callback_func = NULL;
155
  direct_tx_callback_func = NULL;
156
 
157
  // initialize interfaces
101 tk 158
#if !defined(MIOS32_DONT_USE_USB) && !defined(MIOS32_DONT_USE_USB_MIDI)
110 tk 159
  if( MIOS32_USB_MIDI_Init(0) < 0 )
32 tk 160
    ret |= (1 << 0);
161
#endif
162
 
80 tk 163
#if !defined(MIOS32_DONT_USE_UART) && !defined(MIOS32_DONT_USE_UART_MIDI)
110 tk 164
  if( MIOS32_UART_MIDI_Init(0) < 0 )
80 tk 165
    ret |= (1 << 1);
166
#endif
167
 
78 tk 168
#if !defined(MIOS32_DONT_USE_IIC) && !defined(MIOS32_DONT_USE_IIC_MIDI)
110 tk 169
  if( MIOS32_IIC_MIDI_Init(0) < 0 )
80 tk 170
    ret |= (1 << 2);
78 tk 171
#endif
172
 
225 tk 173
  last_sysex_port = DEFAULT;
174
  sysex_state.ALL = 0;
175
 
176
  // TODO: allow to change device ID (read from flash, resp. BSL based EEPROM emulation)
177
  sysex_device_id = 0x00;
178
 
32 tk 179
  return -ret;
180
}
181
 
182
 
183
/////////////////////////////////////////////////////////////////////////////
211 tk 184
//! This function checks the availability of a MIDI port
185
//! \param[in] port MIDI port (DEFAULT, USB0..USB7, UART0..UART1, IIC0..IIC7)
186
//! \return 1: port available
187
//! \return 0: port not available
78 tk 188
/////////////////////////////////////////////////////////////////////////////
189
s32 MIOS32_MIDI_CheckAvailable(mios32_midi_port_t port)
190
{
191
  // if default port: select mapped port
192
  if( !(port & 0xf0) ) {
225 tk 193
    port = default_port;
78 tk 194
  }
195
 
196
  // branch depending on selected port
197
  switch( port >> 4 ) {
198
    case 1:
199
#if !defined(MIOS32_DONT_USE_USB) && !defined(MIOS32_DONT_USE_USB_MIDI)
200
      return MIOS32_USB_MIDI_CheckAvailable();
201
#else
202
      return 0; // USB has been disabled
203
#endif
204
 
205
    case 2:
80 tk 206
#if !defined(MIOS32_DONT_USE_UART) && !defined(MIOS32_DONT_USE_UART_MIDI)
207
      return MIOS32_UART_MIDI_CheckAvailable(port & 0xf);
208
#else
209
      return 0; // UART_MIDI has been disabled
210
#endif
78 tk 211
 
212
    case 3:
213
#if !defined(MIOS32_DONT_USE_IIC) && !defined(MIOS32_DONT_USE_IIC_MIDI)
214
      return MIOS32_IIC_MIDI_CheckAvailable(port & 0xf);
215
#else
216
      return 0; // IIC_MIDI has been disabled
217
#endif
218
 
219
    case 4:
220
      return 0; // Ethernet not implemented yet
221
 
222
    default:
223
      // invalid port
224
      return 0;
225
  }
226
}
227
 
228
 
229
/////////////////////////////////////////////////////////////////////////////
211 tk 230
//! Sends a package over given port
231
//! This is a low level function. In difference to other MIOS32_MIDI_Send* functions,
232
//! It allows to send packages in non-blocking mode (caller has to retry if -2 is returned)
233
//! \param[in] port MIDI port (DEFAULT, USB0..USB7, UART0..UART1, IIC0..IIC7)
234
//! \param[in] package MIDI package
235
//! \return -1 if port not available
236
//! \return -2 buffer is full
237
//!         caller should retry until buffer is free again
238
//! \return 0 on success
110 tk 239
/////////////////////////////////////////////////////////////////////////////
240
s32 MIOS32_MIDI_SendPackage_NonBlocking(mios32_midi_port_t port, mios32_midi_package_t package)
241
{
242
  // if default port: select mapped port
243
  if( !(port & 0xf0) ) {
225 tk 244
    port = default_port;
110 tk 245
  }
246
 
247
  // insert subport number into package
248
  package.cable = port & 0xf;
249
 
250
  // branch depending on selected port
251
  switch( port >> 4 ) {
252
    case 1:
253
#if !defined(MIOS32_DONT_USE_USB) && !defined(MIOS32_DONT_USE_USB_MIDI)
191 tk 254
      return MIOS32_USB_MIDI_PackageSend_NonBlocking(package);
110 tk 255
#else
256
      return -1; // USB has been disabled
257
#endif
258
 
259
    case 2:
260
#if !defined(MIOS32_DONT_USE_UART) && !defined(MIOS32_DONT_USE_UART_MIDI)
261
      return MIOS32_UART_MIDI_PackageSend_NonBlocking(package.cable, package);
262
#else
263
      return -1; // UART_MIDI has been disabled
264
#endif
265
 
266
    case 3:
267
#if !defined(MIOS32_DONT_USE_IIC) && !defined(MIOS32_DONT_USE_IIC_MIDI)
268
      return MIOS32_IIC_MIDI_PackageSend_NonBlocking(package.cable, package);
269
#else
270
      return -1; // IIC_MIDI has been disabled
271
#endif
272
 
273
    case 4:
274
      return -1; // Ethernet not implemented yet
275
 
276
    default:
277
      // invalid port
278
      return -1;
279
  }
280
}
281
 
282
 
283
/////////////////////////////////////////////////////////////////////////////
211 tk 284
//! Sends a package over given port
285
//! This is a low level function - use the remaining MIOS32_MIDI_Send* functions
286
//! to send specific MIDI events
287
//! (blocking function)
288
//! \param[in] port MIDI port (DEFAULT, USB0..USB7, UART0..UART1, IIC0..IIC7)
289
//! \param[in] package MIDI package
290
//! \return -1 if port not available
291
//! \return 0 on success
32 tk 292
/////////////////////////////////////////////////////////////////////////////
69 tk 293
s32 MIOS32_MIDI_SendPackage(mios32_midi_port_t port, mios32_midi_package_t package)
32 tk 294
{
80 tk 295
  // if default port: select mapped port
296
  if( !(port & 0xf0) ) {
225 tk 297
    port = default_port;
80 tk 298
  }
299
 
32 tk 300
  // insert subport number into package
89 tk 301
  package.cable = port & 0xf;
32 tk 302
 
303
  // branch depending on selected port
304
  switch( port >> 4 ) {
80 tk 305
    case 1:
78 tk 306
#if !defined(MIOS32_DONT_USE_USB) && !defined(MIOS32_DONT_USE_USB_MIDI)
191 tk 307
      return MIOS32_USB_MIDI_PackageSend(package);
32 tk 308
#else
309
      return -1; // USB has been disabled
310
#endif
311
 
80 tk 312
    case 2:
313
#if !defined(MIOS32_DONT_USE_UART) && !defined(MIOS32_DONT_USE_UART_MIDI)
314
      return MIOS32_UART_MIDI_PackageSend(package.cable, package);
315
#else
316
      return -1; // UART_MIDI has been disabled
317
#endif
32 tk 318
 
80 tk 319
    case 3:
78 tk 320
#if !defined(MIOS32_DONT_USE_IIC) && !defined(MIOS32_DONT_USE_IIC_MIDI)
321
      return MIOS32_IIC_MIDI_PackageSend(package.cable, package);
322
#else
323
      return -1; // IIC_MIDI has been disabled
324
#endif
32 tk 325
 
80 tk 326
    case 4:
32 tk 327
      return -1; // Ethernet not implemented yet
328
 
329
    default:
330
      // invalid port
331
      return -1;
332
  }
333
}
334
 
335
 
336
/////////////////////////////////////////////////////////////////////////////
211 tk 337
//! Sends a MIDI Event
338
//! This function is provided for a more comfortable use model
339
//!    o MIOS32_MIDI_SendNoteOff(port, chn, note, vel)
340
//!    o MIOS32_MIDI_SendNoteOn(port, chn, note, vel)
341
//!    o MIOS32_MIDI_SendPolyAftertouch(port, chn, note, val)
342
//!    o MIOS32_MIDI_SendCC(port, chn, cc, val)
343
//!    o MIOS32_MIDI_SendProgramChange(port, chn, prg)
344
//!    o MIOS32_MIDI_ChannelAftertouch(port, chn, val)
345
//!    o MIOS32_MIDI_PitchBend(port, chn, val)
346
//!
347
//! \param[in] port MIDI port (DEFAULT, USB0..USB7, UART0..UART1, IIC0..IIC7)
348
//! \param[in] evnt0 first MIDI byte
225 tk 349
//! \param[in] evnt1 second MIDI byte
350
//! \param[in] evnt2 third MIDI byte
211 tk 351
//! \return -1 if port not available
352
//! \return 0 on success
32 tk 353
/////////////////////////////////////////////////////////////////////////////
69 tk 354
s32 MIOS32_MIDI_SendEvent(mios32_midi_port_t port, u8 evnt0, u8 evnt1, u8 evnt2)
32 tk 355
{
33 tk 356
  mios32_midi_package_t package;
357
 
358
  // MEMO: don't optimize this function by calling MIOS32_MIDI_SendSpecialEvent
359
  // from here, because the 4 * u8 parameter list of this function leads
360
  // to best compile results (4*u8 combined to a single u32)
361
 
362
  package.type  = evnt0 >> 4;
363
  package.evnt0 = evnt0;
364
  package.evnt1 = evnt1;
365
  package.evnt2 = evnt2;
366
  return MIOS32_MIDI_SendPackage(port, package);
32 tk 367
}
368
 
69 tk 369
s32 MIOS32_MIDI_SendNoteOff(mios32_midi_port_t port, mios32_midi_chn_t chn, u8 note, u8 vel)
136 tk 370
{ return MIOS32_MIDI_SendEvent(port, 0x80 | chn, note, vel); }
32 tk 371
 
69 tk 372
s32 MIOS32_MIDI_SendNoteOn(mios32_midi_port_t port, mios32_midi_chn_t chn, u8 note, u8 vel)
136 tk 373
{ return MIOS32_MIDI_SendEvent(port, 0x90 | chn, note, vel); }
69 tk 374
 
375
s32 MIOS32_MIDI_SendPolyPressure(mios32_midi_port_t port, mios32_midi_chn_t chn, u8 note, u8 val)
136 tk 376
{ return MIOS32_MIDI_SendEvent(port, 0xa0 | chn, note, val); }
69 tk 377
 
378
s32 MIOS32_MIDI_SendCC(mios32_midi_port_t port, mios32_midi_chn_t chn, u8 cc, u8 val)
136 tk 379
{ return MIOS32_MIDI_SendEvent(port, 0xb0 | chn, cc,   val); }
69 tk 380
 
381
s32 MIOS32_MIDI_SendProgramChange(mios32_midi_port_t port, mios32_midi_chn_t chn, u8 prg)
136 tk 382
{ return MIOS32_MIDI_SendEvent(port, 0xc0 | chn, prg,  0x00); }
69 tk 383
 
384
s32 MIOS32_MIDI_SendAftertouch(mios32_midi_port_t port, mios32_midi_chn_t chn, u8 val)
136 tk 385
{ return MIOS32_MIDI_SendEvent(port, 0xd0 | chn, val,  0x00); }
69 tk 386
 
387
s32 MIOS32_MIDI_SendPitchBend(mios32_midi_port_t port, mios32_midi_chn_t chn, u16 val)
136 tk 388
{ return MIOS32_MIDI_SendEvent(port, 0xe0 | chn, val & 0x7f, val >> 7); }
69 tk 389
 
390
 
33 tk 391
/////////////////////////////////////////////////////////////////////////////
211 tk 392
//! Sends a special type MIDI Event
393
//! This function is provided for a more comfortable use model
394
//! It is aliased to following functions
395
//!    o MIOS32_MIDI_SendMTC(port, val)
396
//!    o MIOS32_MIDI_SendSongPosition(port, val)
397
//!    o MIOS32_MIDI_SendSongSelect(port, val)
398
//!    o MIOS32_MIDI_SendTuneRequest()
399
//!    o MIOS32_MIDI_SendClock()
400
//!    o MIOS32_MIDI_SendTick()
401
//!    o MIOS32_MIDI_SendStart()
402
//!    o MIOS32_MIDI_SendStop()
403
//!    o MIOS32_MIDI_SendContinue()
404
//!    o MIOS32_MIDI_SendActiveSense()
405
//!    o MIOS32_MIDI_SendReset()
406
//!
407
//! \param[in] port MIDI port (DEFAULT, USB0..USB7, UART0..UART1, IIC0..IIC7)
408
//! \param[in] type the event type
409
//! \param[in] evnt0 first MIDI byte
225 tk 410
//! \param[in] evnt1 second MIDI byte
411
//! \param[in] evnt2 third MIDI byte
211 tk 412
//! \return -1 if port not available
413
//! \return 0 on success
33 tk 414
/////////////////////////////////////////////////////////////////////////////
69 tk 415
s32 MIOS32_MIDI_SendSpecialEvent(mios32_midi_port_t port, u8 type, u8 evnt0, u8 evnt1, u8 evnt2)
33 tk 416
{
417
  mios32_midi_package_t package;
418
 
419
  package.type  = type;
420
  package.evnt0 = evnt0;
421
  package.evnt1 = evnt1;
422
  package.evnt2 = evnt2;
423
  return MIOS32_MIDI_SendPackage(port, package);
424
}
425
 
426
 
69 tk 427
s32 MIOS32_MIDI_SendMTC(mios32_midi_port_t port, u8 val)
136 tk 428
{ return MIOS32_MIDI_SendSpecialEvent(port, 0x2, 0xf1, val, 0x00); }
69 tk 429
 
430
s32 MIOS32_MIDI_SendSongPosition(mios32_midi_port_t port, u16 val)
136 tk 431
{ return MIOS32_MIDI_SendSpecialEvent(port, 0x3, 0xf2, val & 0x7f, val >> 7); }
69 tk 432
 
433
s32 MIOS32_MIDI_SendSongSelect(mios32_midi_port_t port, u8 val)
136 tk 434
{ return MIOS32_MIDI_SendSpecialEvent(port, 0x2, 0xf3, val, 0x00); }
69 tk 435
 
436
s32 MIOS32_MIDI_SendTuneRequest(mios32_midi_port_t port)
136 tk 437
{ return MIOS32_MIDI_SendSpecialEvent(port, 0x5, 0xf6, 0x00, 0x00); }
69 tk 438
 
439
s32 MIOS32_MIDI_SendClock(mios32_midi_port_t port)
136 tk 440
{ return MIOS32_MIDI_SendSpecialEvent(port, 0x5, 0xf8, 0x00, 0x00); }
69 tk 441
 
442
s32 MIOS32_MIDI_SendTick(mios32_midi_port_t port)
136 tk 443
{ return MIOS32_MIDI_SendSpecialEvent(port, 0x5, 0xf9, 0x00, 0x00); }
69 tk 444
 
445
s32 MIOS32_MIDI_SendStart(mios32_midi_port_t port)
136 tk 446
{ return MIOS32_MIDI_SendSpecialEvent(port, 0x5, 0xfa, 0x00, 0x00); }
69 tk 447
 
448
s32 MIOS32_MIDI_SendStop(mios32_midi_port_t port)
136 tk 449
{ return MIOS32_MIDI_SendSpecialEvent(port, 0x5, 0xfb, 0x00, 0x00); }
69 tk 450
 
451
s32 MIOS32_MIDI_SendContinue(mios32_midi_port_t port)
136 tk 452
{ return MIOS32_MIDI_SendSpecialEvent(port, 0x5, 0xfc, 0x00, 0x00); }
69 tk 453
 
454
s32 MIOS32_MIDI_SendActiveSense(mios32_midi_port_t port)
136 tk 455
{ return MIOS32_MIDI_SendSpecialEvent(port, 0x5, 0xfe, 0x00, 0x00); }
69 tk 456
 
457
s32 MIOS32_MIDI_SendReset(mios32_midi_port_t port)
136 tk 458
{ return MIOS32_MIDI_SendSpecialEvent(port, 0x5, 0xff, 0x00, 0x00); }
69 tk 459
 
460
 
33 tk 461
/////////////////////////////////////////////////////////////////////////////
211 tk 462
//! Sends a SysEx Stream
463
//! This function is provided for a more comfortable use model
464
//! \param[in] port MIDI port (DEFAULT, USB0..USB7, UART0..UART1, IIC0..IIC7)
465
//! \param[in] stream pointer to SysEx stream
466
//! \param[in] count number of bytes
467
//! \return -1 if port not available
468
//! \return 0 on success
33 tk 469
/////////////////////////////////////////////////////////////////////////////
69 tk 470
s32 MIOS32_MIDI_SendSysEx(mios32_midi_port_t port, u8 *stream, u32 count)
33 tk 471
{
472
  s32 res;
473
  u32 offset;
474
  mios32_midi_package_t package;
475
 
476
  // MEMO: have a look into the project.lss file - gcc optimizes this code pretty well :)
477
 
478
  for(offset=0; offset<count;) {
479
    // package type depends on number of remaining bytes
480
    switch( count-offset ) {
481
      case 1:
482
    package.type = 0x5; // SysEx ends with following single byte. 
483
    package.evnt0 = stream[offset++];
484
    package.evnt1 = 0x00;
485
    package.evnt2 = 0x00;
486
    break;
487
      case 2:
488
    package.type = 0x6; // SysEx ends with following two bytes.
489
    package.evnt0 = stream[offset++];
490
    package.evnt1 = stream[offset++];
491
    package.evnt2 = 0x00;
492
    break;
493
      case 3:
494
    package.type = 0x7; // SysEx ends with following three bytes. 
495
    package.evnt0 = stream[offset++];
496
    package.evnt1 = stream[offset++];
497
    package.evnt2 = stream[offset++];
498
    break;
499
      default:
500
    package.type = 0x4; // SysEx starts or continues
501
    package.evnt0 = stream[offset++];
502
    package.evnt1 = stream[offset++];
503
    package.evnt2 = stream[offset++];
504
    }
505
 
110 tk 506
    res=MIOS32_MIDI_SendPackage(port, package);
33 tk 507
 
110 tk 508
    // expection? (e.g., port not available)
33 tk 509
    if( res < 0 )
510
      return res;
511
  }
512
 
513
  return 0;
514
}
515
 
516
 
517
/////////////////////////////////////////////////////////////////////////////
211 tk 518
//! Checks for incoming MIDI messages, calls either the callback_event or
519
//! callback_sysex function with following parameters:
520
//! \code
521
//!    callback_event(mios32_midi_port_t port, mios32_midi_package_t midi_package)
522
//!    callback_sysex(mios32_midi_port_t port, u8 sysex_byte)
523
//! \endcode
524
//! \return < 0 on errors
33 tk 525
/////////////////////////////////////////////////////////////////////////////
526
s32 MIOS32_MIDI_Receive_Handler(void *_callback_event, void *_callback_sysex)
527
{
528
  u8 port;
529
  mios32_midi_package_t package;
530
 
69 tk 531
  void (*callback_event)(mios32_midi_port_t port, mios32_midi_package_t midi_package) = _callback_event;
532
  void (*callback_sysex)(mios32_midi_port_t port, u8 sysex_byte) = _callback_sysex;
33 tk 533
 
78 tk 534
  u8 intf = 0; // interface to be checked
535
  u8 total_packages_forwarded = 0; // number of forwards - stop after 10 forwards to yield some CPU time for other tasks
536
  u8 packages_forwarded = 0;
537
  u8 again = 1;
33 tk 538
  do {
78 tk 539
    // Round Robin
540
    // TODO: maybe a list based approach would be better
541
    // it would allow to add/remove interfaces dynamically
542
    // this would also allow to give certain ports a higher priority (to add them multiple times to the list)
543
    // it would also improve this spagetthi code ;)
544
    s32 error = -1;
545
    switch( intf++ ) {
546
#if !defined(MIOS32_DONT_USE_USB) && !defined(MIOS32_DONT_USE_USB_MIDI)
191 tk 547
      case 0: error = MIOS32_USB_MIDI_PackageReceive(&package); port = USB0 + package.cable; break;
78 tk 548
#else
549
      case 0: error = -1; break;
550
#endif
126 tk 551
#if !defined(MIOS32_DONT_USE_UART) && !defined(MIOS32_DONT_USE_UART_MIDI) && MIOS32_UART0_ASSIGNMENT == 1
80 tk 552
      case 1: error = MIOS32_UART_MIDI_PackageReceive(0, &package); port = UART0; break;
78 tk 553
#else
554
      case 1: error = -1; break;
555
#endif
126 tk 556
#if !defined(MIOS32_DONT_USE_UART) && !defined(MIOS32_DONT_USE_UART_MIDI) && MIOS32_UART1_ASSIGNMENT == 1
80 tk 557
      case 2: error = MIOS32_UART_MIDI_PackageReceive(1, &package); port = UART1; break;
78 tk 558
#else
559
      case 2: error = -1; break;
560
#endif
561
#if !defined(MIOS32_DONT_USE_IIC) && !defined(MIOS32_DONT_USE_IIC_MIDI)
80 tk 562
      case 3: error = MIOS32_IIC_MIDI_PackageReceive(0, &package); port = IIC0; break;
78 tk 563
#else
564
      case 3: error = -1; break;
565
#endif
566
#if !defined(MIOS32_DONT_USE_IIC) && !defined(MIOS32_DONT_USE_IIC_MIDI)
80 tk 567
      case 4: error = MIOS32_IIC_MIDI_PackageReceive(1, &package); port = IIC1; break;
78 tk 568
#else
569
      case 4: error = -1; break;
570
#endif
571
#if !defined(MIOS32_DONT_USE_IIC) && !defined(MIOS32_DONT_USE_IIC_MIDI)
80 tk 572
      case 5: error = MIOS32_IIC_MIDI_PackageReceive(2, &package); port = IIC2; break;
78 tk 573
#else
574
      case 5: error = -1; break;
575
#endif
576
#if !defined(MIOS32_DONT_USE_IIC) && !defined(MIOS32_DONT_USE_IIC_MIDI)
80 tk 577
      case 6: error = MIOS32_IIC_MIDI_PackageReceive(3, &package); port = IIC3; break;
78 tk 578
#else
579
      case 6: error = -1; break;
580
#endif
581
#if !defined(MIOS32_DONT_USE_IIC) && !defined(MIOS32_DONT_USE_IIC_MIDI)
80 tk 582
      case 7: error = MIOS32_IIC_MIDI_PackageReceive(4, &package); port = IIC4; break;
78 tk 583
#else
584
      case 7: error = -1; break;
585
#endif
586
#if !defined(MIOS32_DONT_USE_IIC) && !defined(MIOS32_DONT_USE_IIC_MIDI)
80 tk 587
      case 8: error = MIOS32_IIC_MIDI_PackageReceive(5, &package); port = IIC5; break;
78 tk 588
#else
589
      case 8: error = -1; break;
590
#endif
80 tk 591
#if !defined(MIOS32_DONT_USE_IIC) && !defined(MIOS32_DONT_USE_IIC_MIDI)
592
      case 9: error = MIOS32_IIC_MIDI_PackageReceive(6, &package); port = IIC6; break;
593
#else
594
      case 9: error = -1; break;
595
#endif
596
#if !defined(MIOS32_DONT_USE_IIC) && !defined(MIOS32_DONT_USE_IIC_MIDI)
597
      case 10: error = MIOS32_IIC_MIDI_PackageReceive(7, &package); port = IIC7; break;
598
#else
599
      case 10: error = -1; break;
600
#endif
78 tk 601
      default:
602
    // allow 10 forwards maximum to yield some CPU time for other tasks
603
    if( packages_forwarded && total_packages_forwarded < 10 ) {
604
      intf = 0; // restart with USB
605
      packages_forwarded = 0; // for checking, if packages still have been forwarded in next round
606
    } else {
607
      again = 0; // no more interfaces to be processed
608
    }
609
    error = -1; // empty round - no message
610
    }
33 tk 611
 
78 tk 612
    // message received?
613
    if( error >= 0 ) {
614
      // notify that a package has been forwarded
615
      ++packages_forwarded;
616
      ++total_packages_forwarded;
33 tk 617
 
78 tk 618
      // remove cable number from package (MIOS32_MIDI passes it's own port number)
69 tk 619
      package.cable = 0;
33 tk 620
 
78 tk 621
      // branch depending on package type
33 tk 622
      if( package.type >= 0x8 ) {
217 tk 623
    if( callback_event != NULL )
624
      callback_event(port, package);
33 tk 625
      } else {
626
    switch( package.type ) {
627
    case 0x0: // reserved, ignore
628
    case 0x1: // cable events, ignore
629
      break;
630
 
631
    case 0x2: // Two-byte System Common messages like MTC, SongSelect, etc. 
632
    case 0x3: // Three-byte System Common messages like SPP, etc. 
217 tk 633
      if( callback_event != NULL )
634
        callback_event(port, package); // -> forwarded as event
33 tk 635
      break;
636
    case 0x4: // SysEx starts or continues (3 bytes)
217 tk 637
      if( callback_sysex != NULL ) {
638
        callback_sysex(port, package.evnt0); // -> forwarded as SysEx
639
        callback_sysex(port, package.evnt1); // -> forwarded as SysEx
640
        callback_sysex(port, package.evnt2); // -> forwarded as SysEx
641
      }
225 tk 642
      MIOS32_MIDI_SYSEX_Parser(port, package.evnt0); // -> forward to MIOS32 SysEx Parser
643
      MIOS32_MIDI_SYSEX_Parser(port, package.evnt1); // -> forward to MIOS32 SysEx Parser
644
      MIOS32_MIDI_SYSEX_Parser(port, package.evnt2); // -> forward to MIOS32 SysEx Parser
33 tk 645
      break;
646
    case 0x5: // Single-byte System Common Message or SysEx ends with following single byte. 
217 tk 647
      if( package.evnt0 >= 0xf8 ) {
648
        if( callback_event != NULL )
649
          callback_event(port, package); // -> forwarded as event
650
      } else {
651
        if( callback_sysex != NULL )
652
          callback_sysex(port, package.evnt0); // -> forwarded as SysEx
225 tk 653
        MIOS32_MIDI_SYSEX_Parser(port, package.evnt0); // -> forward to MIOS32 SysEx Parser
217 tk 654
      }
33 tk 655
      break;
656
    case 0x6: // SysEx ends with following two bytes.
217 tk 657
      if( callback_sysex != NULL ) {
658
        callback_sysex(port, package.evnt0); // -> forwarded as SysEx
659
        callback_sysex(port, package.evnt1); // -> forwarded as SysEx
660
      }
225 tk 661
      MIOS32_MIDI_SYSEX_Parser(port, package.evnt0); // -> forward to MIOS32 SysEx Parser
662
      MIOS32_MIDI_SYSEX_Parser(port, package.evnt1); // -> forward to MIOS32 SysEx Parser
33 tk 663
      break;
664
    case 0x7: // SysEx ends with following three bytes.
217 tk 665
      if( callback_sysex != NULL ) {
666
        callback_sysex(port, package.evnt0); // -> forwarded as SysEx
667
        callback_sysex(port, package.evnt1); // -> forwarded as SysEx
668
        callback_sysex(port, package.evnt2); // -> forwarded as SysEx
669
      }
225 tk 670
      MIOS32_MIDI_SYSEX_Parser(port, package.evnt0); // -> forward to MIOS32 SysEx Parser
671
      MIOS32_MIDI_SYSEX_Parser(port, package.evnt1); // -> forward to MIOS32 SysEx Parser
672
      MIOS32_MIDI_SYSEX_Parser(port, package.evnt2); // -> forward to MIOS32 SysEx Parser
33 tk 673
      break;
674
    }
675
      }
676
    }
677
  } while( again );
678
 
679
  return 0;
680
}
681
 
682
 
155 tk 683
/////////////////////////////////////////////////////////////////////////////
211 tk 684
//! Installs Rx/Tx callback functions which are executed immediately on each
685
//! incoming/outgoing MIDI byte, partly from interrupt handlers with following
686
//! parameters:
687
//! \code
688
//!    callback_rx(mios32_midi_port_t port, u8 midi_byte);
689
//!    callback_tx(mios32_midi_port_t port, u8 midi_byte);
690
//! \endcode
691
//!
692
//! These functions should be executed so fast as possible. They can be used
693
//! to trigger MIDI Rx/Tx LEDs or to trigger on MIDI clock events. In order to
694
//! avoid MIDI buffer overruns, the max. recommented execution time is 100 uS!
695
//! \return < 0 on errors
155 tk 696
/////////////////////////////////////////////////////////////////////////////
697
s32 MIOS32_MIDI_DirectRxTxCallback_Init(void *callback_rx, void *callback_tx)
698
{
699
  direct_rx_callback_func = callback_rx;
700
  direct_tx_callback_func = callback_tx;
157 tk 701
 
702
  return 0; // no error
155 tk 703
}
704
 
705
 
706
/////////////////////////////////////////////////////////////////////////////
211 tk 707
//! This function is used by MIOS32 internal functions to forward received
708
//! MIDI bytes to the Rx Callback routine
155 tk 709
/////////////////////////////////////////////////////////////////////////////
710
s32 MIOS32_MIDI_SendByteToRxCallback(mios32_midi_port_t port, u8 midi_byte)
711
{
712
  // note: here we could filter the user hook execution on special situations
713
  if( direct_rx_callback_func != NULL )
714
    direct_rx_callback_func(port, midi_byte);
157 tk 715
  return 0; // no error
155 tk 716
}
717
 
718
/////////////////////////////////////////////////////////////////////////////
211 tk 719
//! This function is used by MIOS32 internal functions to forward received
720
//! MIDI packages to the Rx Callback routine (byte by byte)
721
//! \param[in] port MIDI port (DEFAULT, USB0..USB7, UART0..UART1, IIC0..IIC7)
212 tk 722
//! \param[in] midi_package MIDI package
211 tk 723
//! \return < 0 on errors
155 tk 724
/////////////////////////////////////////////////////////////////////////////
725
s32 MIOS32_MIDI_SendPackageToRxCallback(mios32_midi_port_t port, mios32_midi_package_t midi_package)
726
{
727
  // note: here we could filter the user hook execution on special situations
728
  if( direct_rx_callback_func != NULL ) {
729
    u8 buffer[3] = {midi_package.evnt0, midi_package.evnt1, midi_package.evnt2};
730
    int len = mios32_midi_pcktype_num_bytes[midi_package.cin];
731
    int i;
732
    for(i=0; i<len; ++i)
733
      direct_rx_callback_func(port, buffer[i]);
734
  }
157 tk 735
  return 0; // no error
155 tk 736
}
737
 
738
/////////////////////////////////////////////////////////////////////////////
211 tk 739
//! This function is used by MIOS32 internal functions to forward received
740
//! MIDI bytes to the Tx Callback routine
741
//! \param[in] port MIDI port (DEFAULT, USB0..USB7, UART0..UART1, IIC0..IIC7)
742
//! \param[in] midi_byte MIDI byte
743
//! \return < 0 on errors
155 tk 744
/////////////////////////////////////////////////////////////////////////////
745
s32 MIOS32_MIDI_SendByteToTxCallback(mios32_midi_port_t port, u8 midi_byte)
746
{
747
  // note: here we could filter the user hook execution on special situations
748
  if( direct_tx_callback_func != NULL )
749
    direct_tx_callback_func(port, midi_byte);
157 tk 750
  return 0; // no error
155 tk 751
}
752
 
753
/////////////////////////////////////////////////////////////////////////////
211 tk 754
//! This function is used by MIOS32 internal functions to forward received
755
//! MIDI packages to the Tx Callback routine (byte by byte)
756
//! \param[in] port MIDI port (DEFAULT, USB0..USB7, UART0..UART1, IIC0..IIC7)
212 tk 757
//! \param[in] midi_package MIDI package
211 tk 758
//! \return < 0 on errors
155 tk 759
/////////////////////////////////////////////////////////////////////////////
760
s32 MIOS32_MIDI_SendPackageToTxCallback(mios32_midi_port_t port, mios32_midi_package_t midi_package)
761
{
762
  // note: here we could filter the user hook execution on special situations
763
  if( direct_tx_callback_func != NULL ) {
764
    u8 buffer[3] = {midi_package.evnt0, midi_package.evnt1, midi_package.evnt2};
765
    int len = mios32_midi_pcktype_num_bytes[midi_package.cin];
766
    int i;
767
    for(i=0; i<len; ++i)
768
      direct_tx_callback_func(port, buffer[i]);
769
  }
157 tk 770
  return 0; // no error
155 tk 771
}
772
 
225 tk 773
 
774
/////////////////////////////////////////////////////////////////////////////
775
//! This function allows to change the DEFAULT port.<BR>
776
//! The preset which will be used after application reset can be set in
777
//! mios32_config.h via "#define MIOS32_MIDI_DEFAULT_PORT <port>".<BR>
778
//! It's set to USB0 so long not overruled in mios32_config.h
779
//! \param[in] port MIDI port (USB0..USB7, UART0..UART1, IIC0..IIC7)
780
//! \return < 0 on errors
781
/////////////////////////////////////////////////////////////////////////////
782
s32 MIOS32_MIDI_DefaultPortSet(mios32_midi_port_t port)
783
{
784
  if( port == DEFAULT ) // avoid recursion
785
    return -1;
786
 
787
  default_port = port;
788
 
789
  return 0; // no error
790
}
791
 
792
/////////////////////////////////////////////////////////////////////////////
793
//! This function returns the DEFAULT port
794
//! \return the default port
795
/////////////////////////////////////////////////////////////////////////////
796
mios32_midi_port_t MIOS32_MIDI_DefaultPortGet(void)
797
{
798
  return default_port;
799
}
800
 
801
 
802
/////////////////////////////////////////////////////////////////////////////
803
//! This function sets the SysEx Device ID, which is used during parsing
804
//! incoming SysEx Requests to MIOS32<BR>
805
//! It can also be used by an application for additional parsing with the same ID.<BR>
806
//! ID changes will get lost after reset. It can be changed permanently by the
807
//! user via Bootloader Command 0x0c
808
//! \param[in] device_id a new (temporary) device ID (0x00..0x7f)
809
//! \return < 0 on errors
810
/////////////////////////////////////////////////////////////////////////////
811
s32 MIOS32_MIDI_DeviceIDSet(u8 device_id)
812
{
813
  sysex_device_id = device_id & 0x7f;
814
  return 0; // no error
815
}
816
 
817
/////////////////////////////////////////////////////////////////////////////
818
//! This function returns the SysEx Device ID, which is used during parsing
819
//! incoming SysEx Requests to MIOS32<BR>
820
//! It can also be used by an application for additional parsing with the same ID.<BR>
821
//! The initial ID is stored inside the BSL range and will be recovered after
822
//! reset. It can be changed by the user via Bootloader Command 0x0c
823
//! \return SysEx device ID (0x00..0x7f)
824
//! \todo store device ID via BSL based EEPROM emulation
825
/////////////////////////////////////////////////////////////////////////////
826
u8 MIOS32_MIDI_DeviceIDGet(void)
827
{
828
  return sysex_device_id;
829
}
830
 
831
 
832
/////////////////////////////////////////////////////////////////////////////
833
// This function parses an incoming sysex stream for MIOS32 commands
834
/////////////////////////////////////////////////////////////////////////////
835
static s32 MIOS32_MIDI_SYSEX_Parser(mios32_midi_port_t port, u8 midi_in)
836
{
837
  // ignore realtime messages (see MIDI spec - realtime messages can
838
  // always be injected into events/streams, and don't change the running status)
839
  if( midi_in >= 0xf8 )
840
    return 0;
841
 
842
  // TODO: here we could send an error notification, that multiple devices are trying to access the device
843
  if( sysex_state.MY_SYSEX && port != last_sysex_port )
844
    return -1;
845
 
846
  last_sysex_port = port;
847
 
848
  // branch depending on state
849
  if( !sysex_state.MY_SYSEX ) {
850
    if( (sysex_state.CTR < sizeof(mios32_midi_sysex_header) && midi_in != mios32_midi_sysex_header[sysex_state.CTR]) ||
851
    (sysex_state.CTR == sizeof(mios32_midi_sysex_header) && midi_in != sysex_device_id) ) {
852
      // incoming byte doesn't match
853
      MIOS32_MIDI_SYSEX_CmdFinished();
854
    } else {
855
      if( ++sysex_state.CTR > sizeof(mios32_midi_sysex_header) ) {
856
    // complete header received, waiting for data
857
    sysex_state.MY_SYSEX = 1;
858
      }
859
    }
860
  } else {
861
    // check for end of SysEx message or invalid status byte
862
    if( midi_in >= 0x80 ) {
863
      if( midi_in == 0xf7 && sysex_state.CMD ) {
864
        MIOS32_MIDI_SYSEX_Cmd(port, MIOS32_MIDI_SYSEX_CMD_STATE_END, midi_in);
865
      }
866
      MIOS32_MIDI_SYSEX_CmdFinished();
867
    } else {
868
      // check if command byte has been received
869
      if( !sysex_state.CMD ) {
870
    sysex_state.CMD = 1;
871
    sysex_cmd = midi_in;
872
    MIOS32_MIDI_SYSEX_Cmd(port, MIOS32_MIDI_SYSEX_CMD_STATE_BEGIN, midi_in);
873
      }
874
      else
875
    MIOS32_MIDI_SYSEX_Cmd(port, MIOS32_MIDI_SYSEX_CMD_STATE_CONT, midi_in);
876
    }
877
  }
878
 
879
  return 0; // no error
880
}
881
 
882
 
883
/////////////////////////////////////////////////////////////////////////////
884
// This function is called at the end of a sysex command or on 
885
// an invalid message
886
/////////////////////////////////////////////////////////////////////////////
887
static s32 MIOS32_MIDI_SYSEX_CmdFinished(void)
888
{
889
  // clear all status variables
890
  sysex_state.ALL = 0;
891
  sysex_cmd = 0;
892
 
893
  return 0; // no error
894
}
895
 
896
/////////////////////////////////////////////////////////////////////////////
897
// This function handles the sysex commands
898
/////////////////////////////////////////////////////////////////////////////
899
static s32 MIOS32_MIDI_SYSEX_Cmd(mios32_midi_port_t port, mios32_midi_sysex_cmd_state_t cmd_state, u8 midi_in)
900
{
901
  // enter the commands here
902
  switch( sysex_cmd ) {
903
    case 0x00:
230 tk 904
      MIOS32_MIDI_SYSEX_Cmd_Query(port, cmd_state, midi_in);
225 tk 905
      break;
906
    case 0x0f:
907
      MIOS32_MIDI_SYSEX_Cmd_Ping(port, cmd_state, midi_in);
908
      break;
909
    default:
910
#if MIOS32_MIDI_BSL_ENHANCEMENTS
911
      // this compile switch should only be activated for the bootloader!
912
      if( BSL_SYSEX_Cmd(port, cmd_state, midi_in, sysex_cmd) >= 0 )
913
    return 0; // BSL has serviced this command - no error
914
#endif
915
      // unknown command
916
      // TODO: send 0xf7 if merger enabled
917
      MIOS32_MIDI_SYSEX_SendAck(port, MIOS32_MIDI_SYSEX_DISACK, MIOS32_MIDI_SYSEX_DISACK_INVALID_COMMAND);
918
      MIOS32_MIDI_SYSEX_CmdFinished();      
919
  }
920
 
921
  return 0; // no error
922
}
923
 
924
 
925
 
926
/////////////////////////////////////////////////////////////////////////////
230 tk 927
// Command 00: Query core informations and request BSL entry
225 tk 928
/////////////////////////////////////////////////////////////////////////////
230 tk 929
static s32 MIOS32_MIDI_SYSEX_Cmd_Query(mios32_midi_port_t port, mios32_midi_sysex_cmd_state_t cmd_state, u8 midi_in)
225 tk 930
{
230 tk 931
  static u8 query_req = 0;
932
  char str_buffer[40];
225 tk 933
 
934
  switch( cmd_state ) {
935
 
936
    case MIOS32_MIDI_SYSEX_CMD_STATE_BEGIN:
230 tk 937
      query_req = 0;
225 tk 938
      break;
939
 
940
    case MIOS32_MIDI_SYSEX_CMD_STATE_CONT:
230 tk 941
      query_req = midi_in;
942
      break;
943
 
944
    default: // MIOS32_MIDI_SYSEX_CMD_STATE_END
945
      switch( query_req ) {
946
        case 0x01: // operating system
947
      MIOS32_MIDI_SYSEX_SendAckStr(port, "MIOS32");
225 tk 948
      break;
230 tk 949
        case 0x02: // MBHP Board
950
      MIOS32_MIDI_SYSEX_SendAckStr(port, MIOS32_BOARD_STR);
225 tk 951
      break;
230 tk 952
        case 0x03: // Core Family
953
      MIOS32_MIDI_SYSEX_SendAckStr(port, MIOS32_FAMILY_STR);
225 tk 954
      break;
230 tk 955
        case 0x04: // Chip ID
956
      sprintf(str_buffer, "%08x", MIOS32_SYS_ChipIDGet());
957
      MIOS32_MIDI_SYSEX_SendAckStr(port, (char *)str_buffer);
958
      break;
959
        case 0x05: // Serial Number
960
      if( MIOS32_SYS_SerialNumberGet((char *)str_buffer) >= 0 )
961
        MIOS32_MIDI_SYSEX_SendAckStr(port, str_buffer);
962
      else
963
        MIOS32_MIDI_SYSEX_SendAckStr(port, "?");
964
      break;
965
        case 0x06: // Flash Memory Size
966
      sprintf(str_buffer, "%d", MIOS32_SYS_FlashSizeGet());
967
      MIOS32_MIDI_SYSEX_SendAckStr(port, str_buffer);
968
      break;
969
        case 0x07: // RAM Memory Size
970
      sprintf(str_buffer, "%d", MIOS32_SYS_RAMSizeGet());
971
      MIOS32_MIDI_SYSEX_SendAckStr(port, str_buffer);
972
      break;
973
        case 0x08: // Application Name Line #1
974
      MIOS32_MIDI_SYSEX_SendAckStr(port, MIOS32_LCD_BOOT_MSG_LINE1);
975
      break;
976
        case 0x09: // Application Name Line #2
977
      MIOS32_MIDI_SYSEX_SendAckStr(port, MIOS32_LCD_BOOT_MSG_LINE2);
978
      break;
979
        case 0x7f:
980
      // reset core (this will send an upload request)
981
      MIOS32_SYS_Reset();
982
      // at least on STM32 we will never reach this point
983
      // but other core families could contain an empty stumb!
984
      break;
985
        default:
986
      // unknown query
987
      MIOS32_MIDI_SYSEX_SendAck(port, MIOS32_MIDI_SYSEX_DISACK, MIOS32_MIDI_SYSEX_DISACK_UNKNOWN_QUERY);
225 tk 988
      }
989
  }
990
 
991
  return 0; // no error
992
}
993
 
994
/////////////////////////////////////////////////////////////////////////////
995
// Command 0F: Ping (just send back acknowledge)
996
/////////////////////////////////////////////////////////////////////////////
997
static s32 MIOS32_MIDI_SYSEX_Cmd_Ping(mios32_midi_port_t port, mios32_midi_sysex_cmd_state_t cmd_state, u8 midi_in)
998
{
999
  switch( cmd_state ) {
1000
 
1001
    case MIOS32_MIDI_SYSEX_CMD_STATE_BEGIN:
1002
      // nothing to do
1003
      break;
1004
 
1005
    case MIOS32_MIDI_SYSEX_CMD_STATE_CONT:
1006
      // nothing to do
1007
      break;
1008
 
1009
    default: // MIOS32_MIDI_SYSEX_CMD_STATE_END
1010
      // TODO: send 0xf7 if merger enabled
1011
 
1012
      // send acknowledge
1013
      MIOS32_MIDI_SYSEX_SendAck(port, MIOS32_MIDI_SYSEX_ACK, 0x00);
1014
 
1015
      break;
1016
  }
1017
 
1018
  return 0; // no error
1019
}
1020
 
1021
/////////////////////////////////////////////////////////////////////////////
1022
// This function sends a SysEx acknowledge to notify the user about the received command
1023
// expects acknowledge code (e.g. 0x0f for good, 0x0e for error) and additional argument
1024
/////////////////////////////////////////////////////////////////////////////
1025
static s32 MIOS32_MIDI_SYSEX_SendAck(mios32_midi_port_t port, u8 ack_code, u8 ack_arg)
1026
{
1027
  u8 sysex_buffer[32]; // should be enough?
1028
  u8 *sysex_buffer_ptr = &sysex_buffer[0];
1029
  int i;
1030
 
1031
  for(i=0; i<sizeof(mios32_midi_sysex_header); ++i)
1032
    *sysex_buffer_ptr++ = mios32_midi_sysex_header[i];
1033
 
1034
  // device ID
1035
  *sysex_buffer_ptr++ = MIOS32_MIDI_DeviceIDGet();
1036
 
1037
  // send ack code and argument
1038
  *sysex_buffer_ptr++ = ack_code;
1039
  *sysex_buffer_ptr++ = ack_arg;
1040
 
1041
  // send footer
1042
  *sysex_buffer_ptr++ = 0xf7;
1043
 
1044
  // finally send SysEx stream
1045
  return MIOS32_MIDI_SendSysEx(port, (u8 *)sysex_buffer, (u32)sysex_buffer_ptr - ((u32)&sysex_buffer[0]));
1046
}
1047
 
230 tk 1048
/////////////////////////////////////////////////////////////////////////////
1049
// This function sends an SysEx acknowledge with a string (used on queries)
1050
/////////////////////////////////////////////////////////////////////////////
1051
static s32 MIOS32_MIDI_SYSEX_SendAckStr(mios32_midi_port_t port, char *str)
1052
{
1053
  u8 sysex_buffer[128]; // should be enough?
1054
  u8 *sysex_buffer_ptr = &sysex_buffer[0];
1055
  int i;
225 tk 1056
 
230 tk 1057
  for(i=0; i<sizeof(mios32_midi_sysex_header); ++i)
1058
    *sysex_buffer_ptr++ = mios32_midi_sysex_header[i];
155 tk 1059
 
230 tk 1060
  // device ID
1061
  *sysex_buffer_ptr++ = MIOS32_MIDI_DeviceIDGet();
1062
 
1063
  // send ack code
1064
  *sysex_buffer_ptr++ = MIOS32_MIDI_SYSEX_ACK;
1065
 
1066
  // send string
1067
  for(i=0; i<100 && str[i] != 0; ++i)
1068
    *sysex_buffer_ptr++ = str[i];
1069
 
1070
  // send footer
1071
  *sysex_buffer_ptr++ = 0xf7;
1072
 
1073
  // finally send SysEx stream
1074
  return MIOS32_MIDI_SendSysEx(port, (u8 *)sysex_buffer, (u32)sysex_buffer_ptr - ((u32)&sysex_buffer[0]));
1075
}
1076
 
32 tk 1077
#endif /* MIOS32_DONT_USE_MIDI */