Subversion Repositories svn.mios32

Rev

Rev 1547 | Rev 1562 | 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 1560 2012-12-01 12:26:11Z 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>
307 tk 24
#include <string.h>
25
#include <stdarg.h>
32 tk 26
 
27
// this module can be optionally disabled in a local mios32_config.h file (included from mios32.h)
28
#if !defined(MIOS32_DONT_USE_MIDI)
29
 
30
 
31
/////////////////////////////////////////////////////////////////////////////
32
// Global variables
33
/////////////////////////////////////////////////////////////////////////////
34
 
211 tk 35
//! this global array is read from MIOS32_IIC_MIDI and MIOS32_UART_MIDI to
36
//! determine the number of MIDI bytes which are part of a package
80 tk 37
const u8 mios32_midi_pcktype_num_bytes[16] = {
38
  0, // 0: invalid/reserved event
39
  0, // 1: invalid/reserved event
40
  2, // 2: two-byte system common messages like MTC, Song Select, etc.
41
  3, // 3: three-byte system common messages like SPP, etc.
42
  3, // 4: SysEx starts or continues
43
  1, // 5: Single-byte system common message or sysex sends with following single byte
44
  2, // 6: SysEx sends with following two bytes
45
  3, // 7: SysEx sends with following three bytes
46
  3, // 8: Note Off
47
  3, // 9: Note On
48
  3, // a: Poly-Key Press
49
  3, // b: Control Change
50
  2, // c: Program Change
51
  2, // d: Channel Pressure
52
  3, // e: PitchBend Change
53
  1  // f: single byte
54
};
32 tk 55
 
211 tk 56
//! Number if expected bytes for a common MIDI event - 1
89 tk 57
const u8 mios32_midi_expected_bytes_common[8] = {
58
  2, // Note On
59
  2, // Note Off
60
  2, // Poly Preasure
61
  2, // Controller
62
  1, // Program Change
63
  1, // Channel Preasure
64
  2, // Pitch Bender
65
  0, // System Message - must be zero, so that mios32_midi_expected_bytes_system[] will be used
66
};
80 tk 67
 
211 tk 68
//! Number if expected bytes for a system MIDI event - 1
89 tk 69
const u8 mios32_midi_expected_bytes_system[16] = {
70
  1, // SysEx Begin (endless until SysEx End F7)
71
  1, // MTC Data frame
72
  2, // Song Position
73
  1, // Song Select
74
  0, // Reserved
75
  0, // Reserved
76
  0, // Request Tuning Calibration
77
  0, // SysEx End
78
 
79
  // Note: just only for documentation, Realtime Messages don't change the running status
80
  0, // MIDI Clock
81
  0, // MIDI Tick
82
  0, // MIDI Start
83
  0, // MIDI Continue
84
  0, // MIDI Stop
85
  0, // Reserved
86
  0, // Active Sense
87
  0, // Reset
88
};
89
 
225 tk 90
//! should only be used by MIOS32 internally and by the Bootloader!
91
const u8 mios32_midi_sysex_header[5] = { 0xf0, 0x00, 0x00, 0x7e, 0x32 };
89 tk 92
 
225 tk 93
 
32 tk 94
/////////////////////////////////////////////////////////////////////////////
225 tk 95
// Local types
96
/////////////////////////////////////////////////////////////////////////////
97
 
98
typedef union {
99
  struct {
100
    unsigned ALL:8;
101
  };
102
 
103
  struct {
104
    unsigned CTR:3;
624 tk 105
    unsigned MY_SYSEX:1;
225 tk 106
    unsigned CMD:1;
107
  };
623 tk 108
 
109
  struct {
110
    unsigned CTR:3;
624 tk 111
    unsigned MY_SYSEX:1;
623 tk 112
    unsigned CMD:1;
113
    unsigned PING_BYTE_RECEIVED;
114
  };
225 tk 115
} sysex_state_t;
116
 
117
 
550 tk 118
typedef union {
119
  struct {
120
    unsigned ALL:32;
121
  };
122
 
123
  struct {
124
    unsigned usb_receives:16;
125
    unsigned iic_receives:16;
126
  };
127
} sysex_timeout_ctr_flags_t;
128
 
129
 
225 tk 130
/////////////////////////////////////////////////////////////////////////////
32 tk 131
// Local variables
132
/////////////////////////////////////////////////////////////////////////////
133
 
225 tk 134
static mios32_midi_port_t default_port = MIOS32_MIDI_DEFAULT_PORT;
307 tk 135
static mios32_midi_port_t debug_port   = MIOS32_MIDI_DEBUG_PORT;
225 tk 136
 
281 tk 137
static s32 (*direct_rx_callback_func)(mios32_midi_port_t port, u8 midi_byte);
138
static s32 (*direct_tx_callback_func)(mios32_midi_port_t port, mios32_midi_package_t package);
674 tk 139
static s32 (*sysex_callback_func)(mios32_midi_port_t port, u8 sysex_byte);
529 tk 140
static s32 (*timeout_callback_func)(mios32_midi_port_t port);
582 tk 141
static s32 (*debug_command_callback_func)(mios32_midi_port_t port, char c);
1541 tk 142
static s32 (*filebrowser_command_callback_func)(mios32_midi_port_t port, char c);
32 tk 143
 
225 tk 144
static sysex_state_t sysex_state;
145
static u8 sysex_device_id;
146
static u8 sysex_cmd;
147
static mios32_midi_port_t last_sysex_port = DEFAULT;
155 tk 148
 
225 tk 149
 
550 tk 150
// SysEx timeout counter: in order to save memory and execution time, we only
151
// protect a single SysEx stream for packet oriented interfaces.
152
// Serial interfaces (UART) are protected separately -> see MIOS32_UART_MIDI_PackageReceive
153
// Approach: the first interface which sends F0 resets the timeout counter.
154
// The flag is reset with F7
155
// Once one second has passed, and the flag is still set, MIOS32_MIDI_TimeOut() will
156
// be called to notify the failure.
157
// Drawback: if another interface starts a SysEx transfer at the same time, the stream
158
// will be ignored, and a timeout won't be detected.
159
// It's unlikely that this is an issue in practice, especially if SysEx parsers only
160
// take streams of the first interface which sends F0 like MIOS32_MIDI_SYSEX_Parser()...
161
//
162
// If a stronger protection is desired (SysEx parser handles streams of multiple interfaces),
163
// it's recommented to implement a separate timeout mechanism at application side.
164
static u16 sysex_timeout_ctr;
165
static sysex_timeout_ctr_flags_t sysex_timeout_ctr_flags;
166
 
167
 
32 tk 168
/////////////////////////////////////////////////////////////////////////////
225 tk 169
// Local prototypes
170
/////////////////////////////////////////////////////////////////////////////
171
 
172
static s32 MIOS32_MIDI_SYSEX_Parser(mios32_midi_port_t port, u8 midi_in);
173
static s32 MIOS32_MIDI_SYSEX_CmdFinished(void);
174
static s32 MIOS32_MIDI_SYSEX_Cmd(mios32_midi_port_t port, mios32_midi_sysex_cmd_state_t cmd_state, u8 midi_in);
230 tk 175
static s32 MIOS32_MIDI_SYSEX_Cmd_Query(mios32_midi_port_t port, mios32_midi_sysex_cmd_state_t cmd_state, u8 midi_in);
582 tk 176
static s32 MIOS32_MIDI_SYSEX_Cmd_Debug(mios32_midi_port_t port, mios32_midi_sysex_cmd_state_t cmd_state, u8 midi_in);
225 tk 177
static s32 MIOS32_MIDI_SYSEX_Cmd_Ping(mios32_midi_port_t port, mios32_midi_sysex_cmd_state_t cmd_state, u8 midi_in);
178
static s32 MIOS32_MIDI_SYSEX_SendAck(mios32_midi_port_t port, u8 ack_code, u8 ack_arg);
230 tk 179
static s32 MIOS32_MIDI_SYSEX_SendAckStr(mios32_midi_port_t port, char *str);
529 tk 180
static s32 MIOS32_MIDI_TimeOut(mios32_midi_port_t port);
225 tk 181
 
182
 
183
/////////////////////////////////////////////////////////////////////////////
211 tk 184
//! Initializes MIDI layer
185
//! \param[in] mode currently only mode 0 supported
186
//! \return < 0 if initialisation failed
32 tk 187
/////////////////////////////////////////////////////////////////////////////
188
s32 MIOS32_MIDI_Init(u32 mode)
189
{
190
  s32 ret = 0;
191
 
110 tk 192
  // currently only mode 0 supported
193
  if( mode != 0 )
32 tk 194
    return -1; // unsupported mode
195
 
307 tk 196
  // set default/debug port as defined in mios32.h/mios32_config.h
225 tk 197
  default_port = MIOS32_MIDI_DEFAULT_PORT;
307 tk 198
  debug_port = MIOS32_MIDI_DEBUG_PORT;
225 tk 199
 
582 tk 200
  // disable callback functions
155 tk 201
  direct_rx_callback_func = NULL;
202
  direct_tx_callback_func = NULL;
674 tk 203
  sysex_callback_func = NULL;
204
  timeout_callback_func = NULL;
582 tk 205
  debug_command_callback_func = NULL;
1541 tk 206
  filebrowser_command_callback_func = NULL;
529 tk 207
 
155 tk 208
  // initialize interfaces
101 tk 209
#if !defined(MIOS32_DONT_USE_USB) && !defined(MIOS32_DONT_USE_USB_MIDI)
110 tk 210
  if( MIOS32_USB_MIDI_Init(0) < 0 )
32 tk 211
    ret |= (1 << 0);
212
#endif
213
 
80 tk 214
#if !defined(MIOS32_DONT_USE_UART) && !defined(MIOS32_DONT_USE_UART_MIDI)
110 tk 215
  if( MIOS32_UART_MIDI_Init(0) < 0 )
80 tk 216
    ret |= (1 << 1);
217
#endif
218
 
78 tk 219
#if !defined(MIOS32_DONT_USE_IIC) && !defined(MIOS32_DONT_USE_IIC_MIDI)
110 tk 220
  if( MIOS32_IIC_MIDI_Init(0) < 0 )
80 tk 221
    ret |= (1 << 2);
78 tk 222
#endif
223
 
225 tk 224
  last_sysex_port = DEFAULT;
225
  sysex_state.ALL = 0;
226
 
227
  sysex_device_id = 0x00;
1307 tk 228
#ifdef MIOS32_SYS_ADDR_BSL_INFO_BEGIN
229
  // read from bootloader info range
230
  u8 *device_id_confirm = (u8 *)MIOS32_SYS_ADDR_DEVICE_ID_CONFIRM;
231
  u8 *device_id = (u8 *)MIOS32_SYS_ADDR_DEVICE_ID;
232
  if( *device_id_confirm == 0x42 && *device_id < 0x80 )
1300 tk 233
    sysex_device_id = *device_id;
234
#endif
225 tk 235
 
550 tk 236
  // SysEx timeout mechanism
237
  sysex_timeout_ctr = 0;
238
  sysex_timeout_ctr_flags.ALL = 0;
239
 
32 tk 240
  return -ret;
241
}
242
 
243
 
244
/////////////////////////////////////////////////////////////////////////////
211 tk 245
//! This function checks the availability of a MIDI port
1328 tk 246
//! \param[in] port MIDI port (DEFAULT, USB0..USB7, UART0..UART3, IIC0..IIC7)
211 tk 247
//! \return 1: port available
248
//! \return 0: port not available
78 tk 249
/////////////////////////////////////////////////////////////////////////////
250
s32 MIOS32_MIDI_CheckAvailable(mios32_midi_port_t port)
251
{
307 tk 252
  // if default/debug port: select mapped port
78 tk 253
  if( !(port & 0xf0) ) {
307 tk 254
    port = (port == MIDI_DEBUG) ? debug_port : default_port;
78 tk 255
  }
256
 
257
  // branch depending on selected port
550 tk 258
  switch( port & 0xf0 ) {
259
    case USB0://..15
78 tk 260
#if !defined(MIOS32_DONT_USE_USB) && !defined(MIOS32_DONT_USE_USB_MIDI)
1259 tk 261
      return MIOS32_USB_MIDI_CheckAvailable(port & 0xf);
78 tk 262
#else
263
      return 0; // USB has been disabled
264
#endif
265
 
550 tk 266
    case UART0://..15
80 tk 267
#if !defined(MIOS32_DONT_USE_UART) && !defined(MIOS32_DONT_USE_UART_MIDI)
268
      return MIOS32_UART_MIDI_CheckAvailable(port & 0xf);
269
#else
270
      return 0; // UART_MIDI has been disabled
271
#endif
78 tk 272
 
550 tk 273
    case IIC0://..15
78 tk 274
#if !defined(MIOS32_DONT_USE_IIC) && !defined(MIOS32_DONT_USE_IIC_MIDI)
275
      return MIOS32_IIC_MIDI_CheckAvailable(port & 0xf);
276
#else
277
      return 0; // IIC_MIDI has been disabled
278
#endif
279
  }
528 tk 280
 
281
  return 0; // invalid port
78 tk 282
}
283
 
284
 
285
/////////////////////////////////////////////////////////////////////////////
528 tk 286
//! This function enables/disables running status optimisation for a given
287
//! MIDI OUT port to improve bandwidth if MIDI events with the same
288
//! status byte are sent back-to-back.<BR>
289
//! The optimisation is currently only used for UART based port (enabled by
290
//! default), IIC: TODO, USB: not required).
1328 tk 291
//! \param[in] port MIDI port (DEFAULT, USB0..USB7, UART0..UART3, IIC0..IIC7)
528 tk 292
//! \param[in] enable 0=optimisation disabled, 1=optimisation enabled
293
//! \return -1 if port not available or if it doesn't support running status
294
//! \return 0 on success
295
/////////////////////////////////////////////////////////////////////////////
296
s32 MIOS32_MIDI_RS_OptimisationSet(mios32_midi_port_t port, u8 enable)
297
{
298
  // if default/debug port: select mapped port
299
  if( !(port & 0xf0) ) {
300
    port = (port == MIDI_DEBUG) ? debug_port : default_port;
301
  }
302
 
303
  // branch depending on selected port
550 tk 304
  switch( port & 0xf0 ) {
305
    case USB0://..15
528 tk 306
      return -1; // not required for USB
307
 
550 tk 308
    case UART0://..15
528 tk 309
#if !defined(MIOS32_DONT_USE_UART) && !defined(MIOS32_DONT_USE_UART_MIDI)
310
      return MIOS32_UART_MIDI_RS_OptimisationSet(port & 0xf, enable);
311
#else
312
      return -1; // UART_MIDI has been disabled
313
#endif
314
 
550 tk 315
    case IIC0://..15
528 tk 316
#if !defined(MIOS32_DONT_USE_IIC) && !defined(MIOS32_DONT_USE_IIC_MIDI)
317
      return MIOS32_IIC_MIDI_RS_OptimisationSet(port & 0xf, enable);
318
#else
319
      return -1; // IIC_MIDI has been disabled
320
#endif
321
  }
322
 
323
  return -1; // invalid port
324
}
325
 
326
 
327
/////////////////////////////////////////////////////////////////////////////
328
//! This function returns the running status optimisation enable/disable flag
329
//! for the given MIDI OUT port.
1328 tk 330
//! \param[in] port MIDI port (DEFAULT, USB0..USB7, UART0..UART3, IIC0..IIC7)
528 tk 331
//! \return -1 if port not available or if it doesn't support running status
332
//! \return 0 if optimisation disabled
333
//! \return 1 if optimisation enabled
334
/////////////////////////////////////////////////////////////////////////////
335
s32 MIOS32_MIDI_RS_OptimisationGet(mios32_midi_port_t port)
336
{
337
  // if default/debug port: select mapped port
338
  if( !(port & 0xf0) ) {
339
    port = (port == MIDI_DEBUG) ? debug_port : default_port;
340
  }
341
 
342
  // branch depending on selected port
550 tk 343
  switch( port & 0xf0 ) {
344
    case USB0://..15
528 tk 345
      return -1; // not required for USB
346
 
550 tk 347
    case UART0://..15
528 tk 348
#if !defined(MIOS32_DONT_USE_UART) && !defined(MIOS32_DONT_USE_UART_MIDI)
349
      return MIOS32_UART_MIDI_RS_OptimisationGet(port & 0xf);
350
#else
351
      return -1; // UART_MIDI has been disabled
352
#endif
353
 
550 tk 354
    case IIC0://..15
528 tk 355
#if !defined(MIOS32_DONT_USE_IIC) && !defined(MIOS32_DONT_USE_IIC_MIDI)
356
      return MIOS32_IIC_MIDI_RS_OptimisationGet(port & 0xf);
357
#else
358
      return -1; // IIC_MIDI has been disabled
359
#endif
360
  }
361
 
362
  return -1; // invalid port
363
}
364
 
365
 
366
/////////////////////////////////////////////////////////////////////////////
367
//! This function resets the current running status, so that it will be sent
368
//! again with the next MIDI Out package.
1328 tk 369
//! \param[in] port MIDI port (DEFAULT, USB0..USB7, UART0..UART3, IIC0..IIC7)
528 tk 370
//! \return -1 if port not available or if it doesn't support running status
371
//! \return 0 if optimisation disabled
372
//! \return 1 if optimisation enabled
373
/////////////////////////////////////////////////////////////////////////////
374
s32 MIOS32_MIDI_RS_Reset(mios32_midi_port_t port)
375
{
376
  // if default/debug port: select mapped port
377
  if( !(port & 0xf0) ) {
378
    port = (port == MIDI_DEBUG) ? debug_port : default_port;
379
  }
380
 
381
  // branch depending on selected port
550 tk 382
  switch( port & 0xf0 ) {
383
    case USB0://..15
528 tk 384
      return -1; // not required for USB
385
 
550 tk 386
    case UART0://..15
528 tk 387
#if !defined(MIOS32_DONT_USE_UART) && !defined(MIOS32_DONT_USE_UART_MIDI)
388
      return MIOS32_UART_MIDI_RS_Reset(port & 0xf);
389
#else
390
      return -1; // UART_MIDI has been disabled
391
#endif
392
 
550 tk 393
    case IIC0://..15
528 tk 394
#if !defined(MIOS32_DONT_USE_IIC) && !defined(MIOS32_DONT_USE_IIC_MIDI)
395
      return MIOS32_IIC_MIDI_RS_Reset(port & 0xf);
396
#else
397
      return -1; // IIC_MIDI has been disabled
398
#endif
399
  }
400
 
401
  return -1; // invalid port
402
}
403
 
404
 
405
/////////////////////////////////////////////////////////////////////////////
211 tk 406
//! Sends a package over given port
281 tk 407
//!
211 tk 408
//! This is a low level function. In difference to other MIOS32_MIDI_Send* functions,
409
//! It allows to send packages in non-blocking mode (caller has to retry if -2 is returned)
281 tk 410
//!
411
//! Before the package is forwarded, an optional Tx Callback function will be called
412
//! which allows to filter/monitor/route the package, or extend the MIDI transmitter
413
//! by custom MIDI Output ports (e.g. for internal busses, OSC, AOUT, etc.)
1328 tk 414
//! \param[in] port MIDI port (DEFAULT, USB0..USB7, UART0..UART3, IIC0..IIC7)
211 tk 415
//! \param[in] package MIDI package
416
//! \return -1 if port not available
417
//! \return -2 buffer is full
418
//!         caller should retry until buffer is free again
281 tk 419
//! \return -3 Tx Callback reported an error
420
//! \return 1 if package has been filtered by Tx callback
211 tk 421
//! \return 0 on success
110 tk 422
/////////////////////////////////////////////////////////////////////////////
423
s32 MIOS32_MIDI_SendPackage_NonBlocking(mios32_midi_port_t port, mios32_midi_package_t package)
424
{
307 tk 425
  // if default/debug port: select mapped port
110 tk 426
  if( !(port & 0xf0) ) {
307 tk 427
    port = (port == MIDI_DEBUG) ? debug_port : default_port;
110 tk 428
  }
429
 
430
  // insert subport number into package
431
  package.cable = port & 0xf;
432
 
281 tk 433
  // forward to Tx callback function and break if package has been filtered
434
  if( direct_tx_callback_func != NULL ) {
435
    s32 status;
425 tk 436
    if( (status=direct_tx_callback_func(port, package)) )
281 tk 437
      return status;
438
  }
439
 
110 tk 440
  // branch depending on selected port
550 tk 441
  switch( port & 0xf0 ) {
442
    case USB0://..15
110 tk 443
#if !defined(MIOS32_DONT_USE_USB) && !defined(MIOS32_DONT_USE_USB_MIDI)
191 tk 444
      return MIOS32_USB_MIDI_PackageSend_NonBlocking(package);
110 tk 445
#else
446
      return -1; // USB has been disabled
447
#endif
448
 
550 tk 449
    case UART0://..15
110 tk 450
#if !defined(MIOS32_DONT_USE_UART) && !defined(MIOS32_DONT_USE_UART_MIDI)
451
      return MIOS32_UART_MIDI_PackageSend_NonBlocking(package.cable, package);
452
#else
453
      return -1; // UART_MIDI has been disabled
454
#endif
455
 
550 tk 456
    case IIC0://..15
110 tk 457
#if !defined(MIOS32_DONT_USE_IIC) && !defined(MIOS32_DONT_USE_IIC_MIDI)
458
      return MIOS32_IIC_MIDI_PackageSend_NonBlocking(package.cable, package);
459
#else
460
      return -1; // IIC_MIDI has been disabled
461
#endif
462
 
463
    default:
464
      // invalid port
465
      return -1;
466
  }
467
}
468
 
469
 
470
/////////////////////////////////////////////////////////////////////////////
211 tk 471
//! Sends a package over given port
472
//! This is a low level function - use the remaining MIOS32_MIDI_Send* functions
473
//! to send specific MIDI events
474
//! (blocking function)
1328 tk 475
//! \param[in] port MIDI port (DEFAULT, USB0..USB7, UART0..UART3, IIC0..IIC7)
211 tk 476
//! \param[in] package MIDI package
477
//! \return -1 if port not available
478
//! \return 0 on success
32 tk 479
/////////////////////////////////////////////////////////////////////////////
69 tk 480
s32 MIOS32_MIDI_SendPackage(mios32_midi_port_t port, mios32_midi_package_t package)
32 tk 481
{
307 tk 482
  // if default/debug port: select mapped port
80 tk 483
  if( !(port & 0xf0) ) {
307 tk 484
    port = (port == MIDI_DEBUG) ? debug_port : default_port;
80 tk 485
  }
486
 
32 tk 487
  // insert subport number into package
89 tk 488
  package.cable = port & 0xf;
32 tk 489
 
301 tk 490
  // forward to Tx callback function and break if package has been filtered
491
  if( direct_tx_callback_func != NULL ) {
492
    s32 status;
425 tk 493
    if( (status=direct_tx_callback_func(port, package)) )
301 tk 494
      return status;
495
  }
496
 
32 tk 497
  // branch depending on selected port
550 tk 498
  switch( port & 0xf0 ) {
499
    case USB0://..15
78 tk 500
#if !defined(MIOS32_DONT_USE_USB) && !defined(MIOS32_DONT_USE_USB_MIDI)
191 tk 501
      return MIOS32_USB_MIDI_PackageSend(package);
32 tk 502
#else
503
      return -1; // USB has been disabled
504
#endif
505
 
550 tk 506
    case UART0://..15
80 tk 507
#if !defined(MIOS32_DONT_USE_UART) && !defined(MIOS32_DONT_USE_UART_MIDI)
508
      return MIOS32_UART_MIDI_PackageSend(package.cable, package);
509
#else
510
      return -1; // UART_MIDI has been disabled
511
#endif
32 tk 512
 
550 tk 513
    case IIC0://..15
78 tk 514
#if !defined(MIOS32_DONT_USE_IIC) && !defined(MIOS32_DONT_USE_IIC_MIDI)
515
      return MIOS32_IIC_MIDI_PackageSend(package.cable, package);
516
#else
517
      return -1; // IIC_MIDI has been disabled
518
#endif
32 tk 519
 
520
    default:
521
      // invalid port
522
      return -1;
523
  }
524
}
525
 
526
 
527
/////////////////////////////////////////////////////////////////////////////
211 tk 528
//! Sends a MIDI Event
529
//! This function is provided for a more comfortable use model
530
//!    o MIOS32_MIDI_SendNoteOff(port, chn, note, vel)
531
//!    o MIOS32_MIDI_SendNoteOn(port, chn, note, vel)
532
//!    o MIOS32_MIDI_SendPolyAftertouch(port, chn, note, val)
533
//!    o MIOS32_MIDI_SendCC(port, chn, cc, val)
534
//!    o MIOS32_MIDI_SendProgramChange(port, chn, prg)
535
//!    o MIOS32_MIDI_ChannelAftertouch(port, chn, val)
536
//!    o MIOS32_MIDI_PitchBend(port, chn, val)
537
//!
1328 tk 538
//! \param[in] port MIDI port (DEFAULT, USB0..USB7, UART0..UART3, IIC0..IIC7)
211 tk 539
//! \param[in] evnt0 first MIDI byte
225 tk 540
//! \param[in] evnt1 second MIDI byte
541
//! \param[in] evnt2 third MIDI byte
211 tk 542
//! \return -1 if port not available
543
//! \return 0 on success
32 tk 544
/////////////////////////////////////////////////////////////////////////////
69 tk 545
s32 MIOS32_MIDI_SendEvent(mios32_midi_port_t port, u8 evnt0, u8 evnt1, u8 evnt2)
32 tk 546
{
33 tk 547
  mios32_midi_package_t package;
548
 
549
  // MEMO: don't optimize this function by calling MIOS32_MIDI_SendSpecialEvent
550
  // from here, because the 4 * u8 parameter list of this function leads
551
  // to best compile results (4*u8 combined to a single u32)
552
 
553
  package.type  = evnt0 >> 4;
554
  package.evnt0 = evnt0;
555
  package.evnt1 = evnt1;
556
  package.evnt2 = evnt2;
557
  return MIOS32_MIDI_SendPackage(port, package);
32 tk 558
}
559
 
69 tk 560
s32 MIOS32_MIDI_SendNoteOff(mios32_midi_port_t port, mios32_midi_chn_t chn, u8 note, u8 vel)
136 tk 561
{ return MIOS32_MIDI_SendEvent(port, 0x80 | chn, note, vel); }
32 tk 562
 
69 tk 563
s32 MIOS32_MIDI_SendNoteOn(mios32_midi_port_t port, mios32_midi_chn_t chn, u8 note, u8 vel)
136 tk 564
{ return MIOS32_MIDI_SendEvent(port, 0x90 | chn, note, vel); }
69 tk 565
 
566
s32 MIOS32_MIDI_SendPolyPressure(mios32_midi_port_t port, mios32_midi_chn_t chn, u8 note, u8 val)
136 tk 567
{ return MIOS32_MIDI_SendEvent(port, 0xa0 | chn, note, val); }
69 tk 568
 
681 tk 569
s32 MIOS32_MIDI_SendCC(mios32_midi_port_t port, mios32_midi_chn_t chn, u8 cc_number, u8 val)
570
{ return MIOS32_MIDI_SendEvent(port, 0xb0 | chn, cc_number,   val); }
69 tk 571
 
572
s32 MIOS32_MIDI_SendProgramChange(mios32_midi_port_t port, mios32_midi_chn_t chn, u8 prg)
136 tk 573
{ return MIOS32_MIDI_SendEvent(port, 0xc0 | chn, prg,  0x00); }
69 tk 574
 
575
s32 MIOS32_MIDI_SendAftertouch(mios32_midi_port_t port, mios32_midi_chn_t chn, u8 val)
136 tk 576
{ return MIOS32_MIDI_SendEvent(port, 0xd0 | chn, val,  0x00); }
69 tk 577
 
578
s32 MIOS32_MIDI_SendPitchBend(mios32_midi_port_t port, mios32_midi_chn_t chn, u16 val)
136 tk 579
{ return MIOS32_MIDI_SendEvent(port, 0xe0 | chn, val & 0x7f, val >> 7); }
69 tk 580
 
581
 
33 tk 582
/////////////////////////////////////////////////////////////////////////////
211 tk 583
//! Sends a special type MIDI Event
584
//! This function is provided for a more comfortable use model
585
//! It is aliased to following functions
586
//!    o MIOS32_MIDI_SendMTC(port, val)
587
//!    o MIOS32_MIDI_SendSongPosition(port, val)
588
//!    o MIOS32_MIDI_SendSongSelect(port, val)
589
//!    o MIOS32_MIDI_SendTuneRequest()
590
//!    o MIOS32_MIDI_SendClock()
591
//!    o MIOS32_MIDI_SendTick()
592
//!    o MIOS32_MIDI_SendStart()
593
//!    o MIOS32_MIDI_SendStop()
594
//!    o MIOS32_MIDI_SendContinue()
595
//!    o MIOS32_MIDI_SendActiveSense()
596
//!    o MIOS32_MIDI_SendReset()
597
//!
1328 tk 598
//! \param[in] port MIDI port (DEFAULT, USB0..USB7, UART0..UART3, IIC0..IIC7)
211 tk 599
//! \param[in] type the event type
600
//! \param[in] evnt0 first MIDI byte
225 tk 601
//! \param[in] evnt1 second MIDI byte
602
//! \param[in] evnt2 third MIDI byte
211 tk 603
//! \return -1 if port not available
604
//! \return 0 on success
33 tk 605
/////////////////////////////////////////////////////////////////////////////
69 tk 606
s32 MIOS32_MIDI_SendSpecialEvent(mios32_midi_port_t port, u8 type, u8 evnt0, u8 evnt1, u8 evnt2)
33 tk 607
{
608
  mios32_midi_package_t package;
609
 
610
  package.type  = type;
611
  package.evnt0 = evnt0;
612
  package.evnt1 = evnt1;
613
  package.evnt2 = evnt2;
614
  return MIOS32_MIDI_SendPackage(port, package);
615
}
616
 
617
 
69 tk 618
s32 MIOS32_MIDI_SendMTC(mios32_midi_port_t port, u8 val)
136 tk 619
{ return MIOS32_MIDI_SendSpecialEvent(port, 0x2, 0xf1, val, 0x00); }
69 tk 620
 
621
s32 MIOS32_MIDI_SendSongPosition(mios32_midi_port_t port, u16 val)
136 tk 622
{ return MIOS32_MIDI_SendSpecialEvent(port, 0x3, 0xf2, val & 0x7f, val >> 7); }
69 tk 623
 
624
s32 MIOS32_MIDI_SendSongSelect(mios32_midi_port_t port, u8 val)
136 tk 625
{ return MIOS32_MIDI_SendSpecialEvent(port, 0x2, 0xf3, val, 0x00); }
69 tk 626
 
627
s32 MIOS32_MIDI_SendTuneRequest(mios32_midi_port_t port)
136 tk 628
{ return MIOS32_MIDI_SendSpecialEvent(port, 0x5, 0xf6, 0x00, 0x00); }
69 tk 629
 
630
s32 MIOS32_MIDI_SendClock(mios32_midi_port_t port)
136 tk 631
{ return MIOS32_MIDI_SendSpecialEvent(port, 0x5, 0xf8, 0x00, 0x00); }
69 tk 632
 
633
s32 MIOS32_MIDI_SendTick(mios32_midi_port_t port)
136 tk 634
{ return MIOS32_MIDI_SendSpecialEvent(port, 0x5, 0xf9, 0x00, 0x00); }
69 tk 635
 
636
s32 MIOS32_MIDI_SendStart(mios32_midi_port_t port)
136 tk 637
{ return MIOS32_MIDI_SendSpecialEvent(port, 0x5, 0xfa, 0x00, 0x00); }
69 tk 638
 
397 stryd_one 639
s32 MIOS32_MIDI_SendContinue(mios32_midi_port_t port)
136 tk 640
{ return MIOS32_MIDI_SendSpecialEvent(port, 0x5, 0xfb, 0x00, 0x00); }
69 tk 641
 
397 stryd_one 642
s32 MIOS32_MIDI_SendStop(mios32_midi_port_t port)
136 tk 643
{ return MIOS32_MIDI_SendSpecialEvent(port, 0x5, 0xfc, 0x00, 0x00); }
69 tk 644
 
645
s32 MIOS32_MIDI_SendActiveSense(mios32_midi_port_t port)
136 tk 646
{ return MIOS32_MIDI_SendSpecialEvent(port, 0x5, 0xfe, 0x00, 0x00); }
69 tk 647
 
648
s32 MIOS32_MIDI_SendReset(mios32_midi_port_t port)
136 tk 649
{ return MIOS32_MIDI_SendSpecialEvent(port, 0x5, 0xff, 0x00, 0x00); }
69 tk 650
 
651
 
33 tk 652
/////////////////////////////////////////////////////////////////////////////
211 tk 653
//! Sends a SysEx Stream
307 tk 654
//!
211 tk 655
//! This function is provided for a more comfortable use model
1328 tk 656
//! \param[in] port MIDI port (DEFAULT, USB0..USB7, UART0..UART3, IIC0..IIC7)
211 tk 657
//! \param[in] stream pointer to SysEx stream
658
//! \param[in] count number of bytes
659
//! \return -1 if port not available
660
//! \return 0 on success
33 tk 661
/////////////////////////////////////////////////////////////////////////////
69 tk 662
s32 MIOS32_MIDI_SendSysEx(mios32_midi_port_t port, u8 *stream, u32 count)
33 tk 663
{
664
  s32 res;
665
  u32 offset;
666
  mios32_midi_package_t package;
667
 
668
  // MEMO: have a look into the project.lss file - gcc optimizes this code pretty well :)
669
 
670
  for(offset=0; offset<count;) {
671
    // package type depends on number of remaining bytes
672
    switch( count-offset ) {
673
      case 1:
674
    package.type = 0x5; // SysEx ends with following single byte. 
675
    package.evnt0 = stream[offset++];
676
    package.evnt1 = 0x00;
677
    package.evnt2 = 0x00;
678
    break;
679
      case 2:
680
    package.type = 0x6; // SysEx ends with following two bytes.
681
    package.evnt0 = stream[offset++];
682
    package.evnt1 = stream[offset++];
683
    package.evnt2 = 0x00;
684
    break;
685
      case 3:
686
    package.type = 0x7; // SysEx ends with following three bytes. 
687
    package.evnt0 = stream[offset++];
688
    package.evnt1 = stream[offset++];
689
    package.evnt2 = stream[offset++];
690
    break;
691
      default:
692
    package.type = 0x4; // SysEx starts or continues
693
    package.evnt0 = stream[offset++];
694
    package.evnt1 = stream[offset++];
695
    package.evnt2 = stream[offset++];
696
    }
697
 
110 tk 698
    res=MIOS32_MIDI_SendPackage(port, package);
33 tk 699
 
110 tk 700
    // expection? (e.g., port not available)
33 tk 701
    if( res < 0 )
702
      return res;
703
  }
704
 
705
  return 0;
706
}
707
 
708
 
709
/////////////////////////////////////////////////////////////////////////////
1541 tk 710
//! Sends the header of a debug string
307 tk 711
//!
1541 tk 712
//! Example (implementation of MIOS32_MIDI_SendDebugString)
307 tk 713
//! \code
1541 tk 714
//!   u32 len = strlen(str);
715
//!  
716
//!   MIOS32_MIDI_SendDebugStringHeader(port, 0x40, str[0]);
717
//!   if( len >= 2 )
718
//!     MIOS32_MIDI_SendDebugStringBody(port, (char *)&str[1], len-1);
719
//!   MIOS32_MIDI_SendDebugStringFooter(port);
307 tk 720
//! \endcode
721
//!
722
//! \return < 0 on errors
723
/////////////////////////////////////////////////////////////////////////////
1541 tk 724
s32 MIOS32_MIDI_SendDebugStringHeader(mios32_midi_port_t port, char command, char first_byte)
307 tk 725
{
1275 tk 726
#ifdef MIOS32_MIDI_DISABLE_DEBUG_MESSAGE
727
  // for bootloader to save memory
728
  return -1;
729
#else
1541 tk 730
  s32 status = 0;
731
  mios32_midi_package_t package;
307 tk 732
 
1541 tk 733
// unfortunately doesn't work, and runtime check would be unnecessary costly
734
//#if sizeof(mios32_midi_sysex_header) != 5
735
//# error "Please adapt MIOS32_MIDI_SendDebugString"
736
//#endif
307 tk 737
 
1541 tk 738
  package.type = 0x4; // SysEx starts or continues
739
  package.evnt0 = mios32_midi_sysex_header[0];
740
  package.evnt1 = mios32_midi_sysex_header[1];
741
  package.evnt2 = mios32_midi_sysex_header[2];
742
  status |= MIOS32_MIDI_SendPackage(port, package);
307 tk 743
 
1541 tk 744
  package.type = 0x4; // SysEx starts or continues
745
  package.evnt0 = mios32_midi_sysex_header[3];
746
  package.evnt1 = mios32_midi_sysex_header[4];
747
  package.evnt2 = MIOS32_MIDI_DeviceIDGet();
748
  status |= MIOS32_MIDI_SendPackage(port, package);
307 tk 749
 
1541 tk 750
  package.type = 0x4; // SysEx starts or continues
751
  package.evnt0 = MIOS32_MIDI_SYSEX_DEBUG;
752
  package.evnt1 = command; // output string, usually 0x40
753
  package.evnt2 = first_byte; // will be 0x00 if string already ends (""), thats ok, MIOS Studio can handle this
754
  status |= MIOS32_MIDI_SendPackage(port, package);
307 tk 755
 
1541 tk 756
  return status;
1275 tk 757
#endif
307 tk 758
}
759
 
760
 
761
/////////////////////////////////////////////////////////////////////////////
1541 tk 762
//! Sends the body of a debug string
1477 tk 763
//!
1541 tk 764
//! Example: see MIOS32_MIDI_SendDebugStringHeader
1477 tk 765
//!
766
//! The string size isn't limited.
767
//!
768
//! \return < 0 on errors
769
/////////////////////////////////////////////////////////////////////////////
1541 tk 770
s32 MIOS32_MIDI_SendDebugStringBody(mios32_midi_port_t port, char *str, u32 len)
1477 tk 771
{
772
#ifdef MIOS32_MIDI_DISABLE_DEBUG_MESSAGE
773
  // for bootloader to save memory
774
  return -1;
775
#else
776
  s32 status = 0;
777
  mios32_midi_package_t package;
778
 
779
  if( len > 0 ) {
1541 tk 780
    int i = 0;
781
    for(i=0; i<len; i+=3) {
1477 tk 782
      u8 b;
783
      u8 terminated = 0;
784
 
785
      package.type = 0x4; // SysEx starts or continues
786
      if( (b=str[i+0]) ) {
787
    package.evnt0 = b & 0x7f;
788
      } else {
789
    package.evnt0 = 0x00;
790
    terminated = 1;
791
      }
792
 
793
      if( !terminated && (b=str[i+1]) ) {
794
    package.evnt1 = b & 0x7f;
795
      } else {
796
    package.evnt1 = 0x00;
797
    terminated = 1;
798
      }
799
 
800
      if( !terminated && (b=str[i+2]) ) {
801
    package.evnt2 = b & 0x7f;
802
      } else {
803
    package.evnt2 = 0x00;
804
    terminated = 1;
805
      }
806
 
1541 tk 807
      status |= MIOS32_MIDI_SendPackage(port, package);
1477 tk 808
    }
809
  }
810
 
1541 tk 811
  return status;
812
#endif
813
}
814
 
815
 
816
/////////////////////////////////////////////////////////////////////////////
817
//! Sends the footer of a debug string
818
//!
819
//! Example: see MIOS32_MIDI_SendDebugStringHeader
820
//!
821
//! \return < 0 on errors
822
/////////////////////////////////////////////////////////////////////////////
823
s32 MIOS32_MIDI_SendDebugStringFooter(mios32_midi_port_t port)
824
{
825
#ifdef MIOS32_MIDI_DISABLE_DEBUG_MESSAGE
826
  // for bootloader to save memory
827
  return -1;
828
#else
829
  s32 status = 0;
830
  mios32_midi_package_t package;
831
 
1477 tk 832
  package.type = 0x5; // SysEx ends with following single byte. 
833
  package.evnt0 = 0xf7;
834
  package.evnt1 = 0x00;
835
  package.evnt2 = 0x00;
1541 tk 836
  status |= MIOS32_MIDI_SendPackage(port, package);
1477 tk 837
 
838
  return status;
839
#endif
840
}
841
 
842
 
843
/////////////////////////////////////////////////////////////////////////////
1541 tk 844
//! Sends a string to the MIOS Terminal in MIOS Studio.
845
//!
846
//! In distance to MIOS32_MIDI_SendDebugMessage this version is less costly (it
847
//! doesn't consume so much stack space), but the string must already be prepared.
848
//!
849
//! Example:
850
//! \code
851
//!   MIOS32_MIDI_SendDebugString("ERROR: something strange happened in myFunction()!");
852
//! \endcode
853
//!
854
//! The string size isn't limited.
855
//!
856
//! \return < 0 on errors
857
/////////////////////////////////////////////////////////////////////////////
858
s32 MIOS32_MIDI_SendDebugString(char *str)
859
{
860
#ifdef MIOS32_MIDI_DISABLE_DEBUG_MESSAGE
861
  // for bootloader to save memory
862
  return -1;
863
#else
864
  s32 status = 0;
865
  u32 len = strlen(str);
866
 
867
  status |= MIOS32_MIDI_SendDebugStringHeader(debug_port, 0x40, str[0]);
868
  if( len >= 2 )
869
    status |= MIOS32_MIDI_SendDebugStringBody(debug_port, (char *)&str[1], len-1);
870
  status |= MIOS32_MIDI_SendDebugStringFooter(debug_port);
871
 
872
  return status;
873
#endif
874
}
875
 
876
 
877
/////////////////////////////////////////////////////////////////////////////
878
//! Sends a formatted Debug Message to the MIOS Terminal in MIOS Studio.
879
//!
880
//! Formatting parameters are like known from printf, e.g.
881
//! \code
882
//!   MIOS32_MIDI_SendDebugMessage("Button %d %s\n", button, value ? "depressed" : "pressed");
883
//! \endcode
884
//!
885
//! The MIDI port used for debugging (MIDI_DEBUG) can be declared in mios32_config.h:
886
//! \code
887
//!   #define MIOS32_MIDI_DEBUG_PORT USB0
888
//! \endcode
889
//! (USB0 is the default value)
890
//!
891
//! Optionally, the port can be changed during runtime with MIOS32_MIDI_DebugPortSet
892
//!
893
//! Please note that the resulting string shouldn't be longer than 128 characters!<BR>
894
//! If the *format string is already longer than 100 characters an error message will
895
//! be sent to notify about the programming error.<BR>
896
//! The limit is set to save allocated stack memory! Just reduce the formated string to
897
//! print out the intended message.
898
//! \param[in] *format zero-terminated format string - 128 characters supported maximum!
899
//! \param ... additional arguments
900
//! \return < 0 on errors
901
/////////////////////////////////////////////////////////////////////////////
902
s32 MIOS32_MIDI_SendDebugMessage(char *format, ...)
903
{
904
#ifdef MIOS32_MIDI_DISABLE_DEBUG_MESSAGE
905
  // for bootloader to save memory
906
  return -1;
907
#else
908
  char str[128]; // 128 chars allowed
909
  va_list args;
910
 
911
  // failsave: if format string is longer than 100 chars, break here
912
  // note that this is a weak protection: if %s is used, or a lot of other format tokens,
913
  // the resulting string could still lead to a buffer overflow
914
  // other the other hand we don't want to allocate too many byte for buffer[] to save stack
915
  if( strlen(format) > 100 ) {
916
    // exit with less costly message
917
    return MIOS32_MIDI_SendDebugString("(ERROR: string passed to MIOS32_MIDI_SendDebugMessage() is longer than 100 chars!\n");
918
  } else {
919
    // transform formatted string into string
920
    va_start(args, format);
921
    vsprintf(str, format, args);
922
  }
923
 
924
  u32 len = strlen(str);
925
  u8 *str_ptr = (u8 *)str;
926
  int i;
927
  for(i=0; i<len; ++i) {
928
    *str_ptr++ &= 0x7f; // ensure that MIDI protocol won't be violated
929
  }
930
 
931
  return MIOS32_MIDI_SendDebugString(str);
932
#endif
933
}
934
 
935
 
936
/////////////////////////////////////////////////////////////////////////////
369 tk 937
//! Sends an hex dump (formatted representation of memory content) to the 
938
//! MIOS Terminal in MIOS Studio.
939
//!
940
//! The MIDI port used for debugging (MIDI_DEBUG) can be declared in mios32_config.h:
941
//! \code
942
//!   #define MIOS32_MIDI_DEBUG_PORT USB0
943
//! \endcode
944
//! (USB0 is the default value)
945
//!
946
//! Optionally, the port can be changed during runtime with MIOS32_MIDI_DebugPortSet
947
//! \param[in] *src pointer to memory location which should be dumped
948
//! \param[in] len number of bytes which should be sent
949
//! \return < 0 on errors
950
/////////////////////////////////////////////////////////////////////////////
951
s32 MIOS32_MIDI_SendDebugHexDump(u8 *src, u32 len)
952
{
1541 tk 953
  s32 status = 0;
954
 
369 tk 955
  // check if any byte has to be sent
956
  if( !len )
957
    return 0;
958
 
959
  // send hex dump line by line
370 tk 960
  u8 *src_begin = src;
369 tk 961
  u8 *src_end;
962
  for(src_end=(u8 *)((size_t)src + len - 1); src < src_end;) {
1541 tk 963
    char str[80];
964
    char* str_ptr = (char *)str;
369 tk 965
    int i;
966
 
967
    // build line:
968
    // add source address
1541 tk 969
    sprintf((char *)str_ptr, "%08X ", (u32)(src-src_begin));
970
    str_ptr += 9;
369 tk 971
 
972
    // add up to 16 bytes
973
    u8 *src_chars = src; // for later
974
    for(i=0; i<16; ++i) {
1541 tk 975
      sprintf((char *)str_ptr, (src <= src_end) ? " %02X" : "   ", *src);
976
      str_ptr += 3;
369 tk 977
 
978
      ++src;
979
    }
980
 
981
    // add two spaces
374 tk 982
    for(i=0; i<2; ++i)
1541 tk 983
      *str_ptr++ = ' ';
369 tk 984
 
985
    // add characters
986
    for(i=0; i<16; ++i) {
987
      if( *src_chars < 32 || *src_chars >= 128 )
1541 tk 988
    *str_ptr++ = '.';
369 tk 989
      else
1541 tk 990
    *str_ptr++ = *src_chars;
369 tk 991
 
992
      if( src_chars == src_end )
993
    break;
994
 
995
      ++src_chars;
996
    }
997
 
376 tk 998
    // linebreak
1541 tk 999
    *str_ptr++ = '\n';
376 tk 1000
 
1541 tk 1001
    // terminator
1002
    *str_ptr++ = 0;
369 tk 1003
 
1541 tk 1004
    status |= MIOS32_MIDI_SendDebugString(str);
369 tk 1005
  }
1006
 
1541 tk 1007
  return status;
369 tk 1008
}
1009
 
1010
 
1011
/////////////////////////////////////////////////////////////////////////////
674 tk 1012
//! Checks for incoming MIDI messages amd calls callback_package function
1013
//! with following parameters:
211 tk 1014
//! \code
674 tk 1015
//!    callback_package(mios32_midi_port_t port, mios32_midi_package_t midi_package)
211 tk 1016
//! \endcode
528 tk 1017
//!
1018
//! Not for use in an application - this function is called by
674 tk 1019
//! by a task in the programming model, callback_package is APP_MIDI_NotifyPackage()
1020
//!
1021
//! SysEx streams can be optionally redirected to a separate callback function 
1022
//! which can be installed via MIOS32_MIDI_SysExCallback_Init()
1023
//!
211 tk 1024
//! \return < 0 on errors
33 tk 1025
/////////////////////////////////////////////////////////////////////////////
674 tk 1026
s32 MIOS32_MIDI_Receive_Handler(void *_callback_package)
33 tk 1027
{
1028
  u8 port;
1029
  mios32_midi_package_t package;
1030
 
674 tk 1031
  void (*callback_package)(mios32_midi_port_t port, mios32_midi_package_t midi_package) = _callback_package;
33 tk 1032
 
78 tk 1033
  u8 intf = 0; // interface to be checked
1034
  u8 total_packages_forwarded = 0; // number of forwards - stop after 10 forwards to yield some CPU time for other tasks
1035
  u8 packages_forwarded = 0;
1036
  u8 again = 1;
33 tk 1037
  do {
78 tk 1038
    // Round Robin
1039
    // TODO: maybe a list based approach would be better
1040
    // it would allow to add/remove interfaces dynamically
1041
    // this would also allow to give certain ports a higher priority (to add them multiple times to the list)
1042
    // it would also improve this spagetthi code ;)
529 tk 1043
    s32 status = -1;
78 tk 1044
    switch( intf++ ) {
1045
#if !defined(MIOS32_DONT_USE_USB) && !defined(MIOS32_DONT_USE_USB_MIDI)
529 tk 1046
      case 0: status = MIOS32_USB_MIDI_PackageReceive(&package); port = USB0 + package.cable; break;
78 tk 1047
#else
529 tk 1048
      case 0: status = -1; break;
78 tk 1049
#endif
126 tk 1050
#if !defined(MIOS32_DONT_USE_UART) && !defined(MIOS32_DONT_USE_UART_MIDI) && MIOS32_UART0_ASSIGNMENT == 1
529 tk 1051
      case 1: status = MIOS32_UART_MIDI_PackageReceive(0, &package); port = UART0; break;
78 tk 1052
#else
529 tk 1053
      case 1: status = -1; break;
78 tk 1054
#endif
126 tk 1055
#if !defined(MIOS32_DONT_USE_UART) && !defined(MIOS32_DONT_USE_UART_MIDI) && MIOS32_UART1_ASSIGNMENT == 1
529 tk 1056
      case 2: status = MIOS32_UART_MIDI_PackageReceive(1, &package); port = UART1; break;
78 tk 1057
#else
529 tk 1058
      case 2: status = -1; break;
78 tk 1059
#endif
1071 tk 1060
#if !defined(MIOS32_DONT_USE_UART) && !defined(MIOS32_DONT_USE_UART_MIDI) && MIOS32_UART2_ASSIGNMENT == 1
1061
      case 3: status = MIOS32_UART_MIDI_PackageReceive(2, &package); port = UART2; break;
78 tk 1062
#else
529 tk 1063
      case 3: status = -1; break;
78 tk 1064
#endif
1328 tk 1065
#if !defined(MIOS32_DONT_USE_UART) && !defined(MIOS32_DONT_USE_UART_MIDI) && MIOS32_UART3_ASSIGNMENT == 1
1066
      case 4: status = MIOS32_UART_MIDI_PackageReceive(3, &package); port = UART3; break;
78 tk 1067
#else
529 tk 1068
      case 4: status = -1; break;
78 tk 1069
#endif
1070
#if !defined(MIOS32_DONT_USE_IIC) && !defined(MIOS32_DONT_USE_IIC_MIDI)
1328 tk 1071
      case 5: status = MIOS32_IIC_MIDI_PackageReceive(0, &package); port = IIC0; break;
78 tk 1072
#else
529 tk 1073
      case 5: status = -1; break;
78 tk 1074
#endif
1075
#if !defined(MIOS32_DONT_USE_IIC) && !defined(MIOS32_DONT_USE_IIC_MIDI)
1328 tk 1076
      case 6: status = MIOS32_IIC_MIDI_PackageReceive(1, &package); port = IIC1; break;
78 tk 1077
#else
529 tk 1078
      case 6: status = -1; break;
78 tk 1079
#endif
1080
#if !defined(MIOS32_DONT_USE_IIC) && !defined(MIOS32_DONT_USE_IIC_MIDI)
1328 tk 1081
      case 7: status = MIOS32_IIC_MIDI_PackageReceive(2, &package); port = IIC2; break;
78 tk 1082
#else
529 tk 1083
      case 7: status = -1; break;
78 tk 1084
#endif
1085
#if !defined(MIOS32_DONT_USE_IIC) && !defined(MIOS32_DONT_USE_IIC_MIDI)
1328 tk 1086
      case 8: status = MIOS32_IIC_MIDI_PackageReceive(3, &package); port = IIC3; break;
78 tk 1087
#else
529 tk 1088
      case 8: status = -1; break;
78 tk 1089
#endif
80 tk 1090
#if !defined(MIOS32_DONT_USE_IIC) && !defined(MIOS32_DONT_USE_IIC_MIDI)
1328 tk 1091
      case 9: status = MIOS32_IIC_MIDI_PackageReceive(4, &package); port = IIC4; break;
80 tk 1092
#else
529 tk 1093
      case 9: status = -1; break;
80 tk 1094
#endif
1095
#if !defined(MIOS32_DONT_USE_IIC) && !defined(MIOS32_DONT_USE_IIC_MIDI)
1328 tk 1096
      case 10: status = MIOS32_IIC_MIDI_PackageReceive(5, &package); port = IIC5; break;
80 tk 1097
#else
529 tk 1098
      case 10: status = -1; break;
80 tk 1099
#endif
1071 tk 1100
#if !defined(MIOS32_DONT_USE_IIC) && !defined(MIOS32_DONT_USE_IIC_MIDI)
1328 tk 1101
      case 11: status = MIOS32_IIC_MIDI_PackageReceive(6, &package); port = IIC6; break;
1071 tk 1102
#else
1103
      case 11: status = -1; break;
1104
#endif
1328 tk 1105
#if !defined(MIOS32_DONT_USE_IIC) && !defined(MIOS32_DONT_USE_IIC_MIDI)
1106
      case 12: status = MIOS32_IIC_MIDI_PackageReceive(7, &package); port = IIC7; break;
1107
#else
1108
      case 12: status = -1; break;
1109
#endif
78 tk 1110
      default:
1111
    // allow 10 forwards maximum to yield some CPU time for other tasks
1112
    if( packages_forwarded && total_packages_forwarded < 10 ) {
1113
      intf = 0; // restart with USB
1114
      packages_forwarded = 0; // for checking, if packages still have been forwarded in next round
1115
    } else {
1116
      again = 0; // no more interfaces to be processed
1117
    }
529 tk 1118
    status = -1; // empty round - no message
78 tk 1119
    }
33 tk 1120
 
550 tk 1121
    // timeout detected by interface?
529 tk 1122
    if( status == -10 ) {
1123
      MIOS32_MIDI_TimeOut(port);
1124
      again = 0;
1125
    } else if( status >= 0 ) { // message received?
78 tk 1126
      // notify that a package has been forwarded
1127
      ++packages_forwarded;
1128
      ++total_packages_forwarded;
33 tk 1129
 
78 tk 1130
      // remove cable number from package (MIOS32_MIDI passes it's own port number)
69 tk 1131
      package.cable = 0;
33 tk 1132
 
78 tk 1133
      // branch depending on package type
582 tk 1134
      if( package.type >= 0x8 && package.type < 0xf ) {
674 tk 1135
    if( callback_package != NULL )
1136
      callback_package(port, package);
33 tk 1137
      } else {
675 tk 1138
    u8 filter_sysex = 0;
1139
 
33 tk 1140
    switch( package.type ) {
550 tk 1141
      case 0x0: // reserved, ignore
1142
      case 0x1: // cable events, ignore
1143
        break;
33 tk 1144
 
550 tk 1145
      case 0x2: // Two-byte System Common messages like MTC, SongSelect, etc. 
1146
      case 0x3: // Three-byte System Common messages like SPP, etc. 
674 tk 1147
        if( callback_package != NULL )
1148
          callback_package(port, package); // -> forwarded as event
550 tk 1149
        break;
1150
 
1151
      case 0x4: // SysEx starts or continues (3 bytes)
582 tk 1152
      case 0xf: // Single byte is interpreted as SysEx as well (I noticed that portmidi sometimes sends single bytes!)
674 tk 1153
 
1154
        if( package.evnt0 >= 0xf8 ) { // relevant for package type 0xf
1155
          if( callback_package != NULL )
1156
        callback_package(port, package); // -> realtime event is forwarded as event
1157
          break;
1158
        }
1159
 
550 tk 1160
        if( package.evnt0 == 0xf0 ) {
1161
          // cheap timeout mechanism - see comments above the sysex_timeout_ctr declaration
1162
          if( !sysex_timeout_ctr_flags.ALL ) {
1163
        switch( port & 0xf0 ) {
1164
          case USB0://..15
1165
            sysex_timeout_ctr = 0;
1166
            sysex_timeout_ctr_flags.usb_receives = (1 << (port & 0xf));
1167
            break;
1168
          case UART0://..15
1169
            // already done in MIOS32_UART_MIDI_PackageReceive()
1170
            break;
1171
          case IIC0://..15
1172
            sysex_timeout_ctr = 0;
1173
            sysex_timeout_ctr_flags.iic_receives = (1 << (port & 0xf));
1174
            break;
1175
            // no timeout protection for remaining interfaces (yet)
1176
        }
1177
          }
1178
        }
1179
 
1180
        MIOS32_MIDI_SYSEX_Parser(port, package.evnt0); // -> forward to MIOS32 SysEx Parser
582 tk 1181
        if( package.type != 0x0f ) {
1182
          MIOS32_MIDI_SYSEX_Parser(port, package.evnt1); // -> forward to MIOS32 SysEx Parser
1183
          MIOS32_MIDI_SYSEX_Parser(port, package.evnt2); // -> forward to MIOS32 SysEx Parser
1184
        }
1185
 
1560 tk 1186
#if !MIOS32_MIDI_BSL_ENHANCEMENTS // to save some memory
1547 tk 1187
        if( !sysex_state.MY_SYSEX ) { // don't forward to application if we receive a MIOS32 command
1188
          if( sysex_callback_func != NULL ) {
1189
        filter_sysex |= sysex_callback_func(port, package.evnt0); // -> forwarded as SysEx
1190
        if( package.type != 0x0f ) {
1191
          filter_sysex |= sysex_callback_func(port, package.evnt1); // -> forwarded as SysEx
1192
          filter_sysex |= sysex_callback_func(port, package.evnt2); // -> forwarded as SysEx
1193
        }
582 tk 1194
          }
1547 tk 1195
 
1196
          if( callback_package != NULL && !filter_sysex )
1197
        callback_package(port, package);
675 tk 1198
        }
1560 tk 1199
#endif
550 tk 1200
        break;
1201
 
1202
      case 0x5:   // Single-byte System Common Message or SysEx ends with following single byte. 
1203
        if( package.evnt0 >= 0xf8 ) {
674 tk 1204
          if( callback_package != NULL )
1205
        callback_package(port, package); // -> forwarded as event
550 tk 1206
          break;
1207
        }
1208
        // no >= 0xf8 event: continue!
1209
 
1210
      case 0x6:   // SysEx ends with following two bytes.
1211
      case 0x7: { // SysEx ends with following three bytes.
1212
        u8 num_bytes = package.type - 0x5 + 1;
1213
        u8 current_byte = 0;
1214
 
1215
        if( num_bytes >= 1 ) {
1216
          current_byte = package.evnt0;
1217
          MIOS32_MIDI_SYSEX_Parser(port, current_byte); // -> forward to MIOS32 SysEx Parser
1547 tk 1218
 
1560 tk 1219
#if !MIOS32_MIDI_BSL_ENHANCEMENTS // to save some memory
1547 tk 1220
          if( !sysex_state.MY_SYSEX ) { // don't forward to application if we receive a MIOS32 command
1221
        if( sysex_callback_func != NULL )
1222
          filter_sysex |= sysex_callback_func(port, current_byte); // -> forwarded as SysEx
1223
          }
1560 tk 1224
#endif
550 tk 1225
        }
1226
 
1227
        if( num_bytes >= 2 ) {
1228
          current_byte = package.evnt1;
1229
          MIOS32_MIDI_SYSEX_Parser(port, current_byte); // -> forward to MIOS32 SysEx Parser
1547 tk 1230
 
1560 tk 1231
#if !MIOS32_MIDI_BSL_ENHANCEMENTS // to save some memory
1547 tk 1232
          if( !sysex_state.MY_SYSEX ) { // don't forward to application if we receive a MIOS32 command
1233
        if( sysex_callback_func != NULL )
1234
          filter_sysex |= sysex_callback_func(port, current_byte); // -> forwarded as SysEx
1235
          }
1560 tk 1236
#endif
550 tk 1237
        }
1238
 
1239
        if( num_bytes >= 3 ) {
1240
          current_byte = package.evnt2;
1241
          MIOS32_MIDI_SYSEX_Parser(port, current_byte); // -> forward to MIOS32 SysEx Parser
1547 tk 1242
 
1560 tk 1243
#if !MIOS32_MIDI_BSL_ENHANCEMENTS // to save some memory
1547 tk 1244
          if( !sysex_state.MY_SYSEX ) { // don't forward to application if we receive a MIOS32 command
1245
        if( sysex_callback_func != NULL )
1246
          filter_sysex |= sysex_callback_func(port, current_byte); // -> forwarded as SysEx
1247
          }
1560 tk 1248
#endif
550 tk 1249
        }
1250
 
1251
        // reset timeout protection if required
1252
        if( current_byte == 0xf7 )
1253
          sysex_timeout_ctr_flags.ALL = 0;
674 tk 1254
 
1560 tk 1255
#if !MIOS32_MIDI_BSL_ENHANCEMENTS // to save some memory
1547 tk 1256
        if( !sysex_state.MY_SYSEX ) { // don't forward to application if we receive a MIOS32 command
1257
          // forward as package if not filtered
1258
          if( callback_package != NULL && !filter_sysex )
1259
        callback_package(port, package);
1560 tk 1260
        }    
1261
#endif  
550 tk 1262
      } break;
1263
    }    
33 tk 1264
      }
1265
    }
550 tk 1266
 
1267
    // timeout detected by this handler?
1268
    if( sysex_timeout_ctr_flags.ALL && sysex_timeout_ctr > 1000 ) {
1269
      u8 timeout_port = 0;
1270
 
1271
      // determine port
1272
      if( sysex_timeout_ctr_flags.usb_receives ) {
1273
    int i; // i'm missing a prio instruction in C!
1274
    for(i=0; i<16; ++i)
1275
      if( sysex_timeout_ctr_flags.usb_receives & (1 << i) )
1276
        break;
1277
    if( i >= 16 ) // failsafe
1278
      i = 0;
1279
    timeout_port = USB0 + i;
1280
      } else if( sysex_timeout_ctr_flags.iic_receives ) {
1281
    int i; // i'm missing a prio instruction in C!
1282
    for(i=0; i<16; ++i)
1283
      if( sysex_timeout_ctr_flags.iic_receives & (1 << i) )
1284
        break;
1285
    if( i >= 16 ) // failsafe
1286
      i = 0;
1287
    timeout_port = IIC0 + i;
1288
      }
1289
 
1290
      MIOS32_MIDI_TimeOut(timeout_port);
1291
      sysex_timeout_ctr_flags.ALL = 0;
1292
      again = 0;
1293
    }
33 tk 1294
  } while( again );
1295
 
1296
  return 0;
1297
}
1298
 
1299
 
155 tk 1300
/////////////////////////////////////////////////////////////////////////////
528 tk 1301
//! This function should be called periodically each mS to handle timeout
1302
//! and expire counters.
1303
//!
1304
//! Not for use in an application - this function is called by
1305
//! by a task in the programming model!
1306
//! 
1307
//! \return < 0 on errors
1308
/////////////////////////////////////////////////////////////////////////////
1309
s32 MIOS32_MIDI_Periodic_mS(void)
1310
{
1311
  s32 status = 0;
1312
 
1313
#ifndef MIOS32_DONT_USE_USB_MIDI
1314
  status |= MIOS32_USB_MIDI_Periodic_mS();
1315
#endif
1316
 
1317
#ifndef MIOS32_DONT_USE_UART_MIDI
1318
  status |= MIOS32_UART_MIDI_Periodic_mS();
1319
#endif
1320
 
1321
#ifndef MIOS32_DONT_USE_IIC_MIDI
1322
  status |= MIOS32_IIC_MIDI_Periodic_mS();
1323
#endif
1324
 
550 tk 1325
  // increment timeout counter for incoming packages
1326
  // an incomplete event will be timed out after 1000 ticks (1 second)
1327
  if( sysex_timeout_ctr < 65535 )
1328
    ++sysex_timeout_ctr;
1329
 
528 tk 1330
  return status;
1331
}
1332
 
1333
 
1334
/////////////////////////////////////////////////////////////////////////////
281 tk 1335
//! Installs the Tx callback function which is executed by
1336
//! MIOS32_MIDI_SendPackage_NonBlocking() before the MIDI package will be
1337
//! forwarded to the physical interface.
1338
//!
1339
//! The callback allows following usecases:
1340
//! <UL>
282 tk 1341
//!   <LI>package filter
281 tk 1342
//!   <LI>duplicating/routing packages
1343
//!   <LI>monitoring packages (sniffer)
1344
//!   <LI>create virtual busses; loopbacks
282 tk 1345
//!   <LI>extend available ports (e.g. by an OSC or AOUT port)<BR>
1346
//!       It is recommented to give port extensions a port number >= 0x80 to
1347
//!       avoid incompatibility with future MIOS32 port extensions.
281 tk 1348
//! </UL>
1349
//! \param[in] *callback_tx pointer to callback function:<BR>
211 tk 1350
//! \code
674 tk 1351
//!    s32 callback_tx(mios32_midi_port_t port, mios32_midi_package_t package)
1352
//!    {
1353
//!    }
211 tk 1354
//! \endcode
281 tk 1355
//! The package will be forwarded to the physical interface if the function 
1356
//! returns 0.<BR>
1357
//! Should return 1 to filter a package.
1358
//! Should return -2 to initiate a retry (function will be called again)
1359
//! Should return -3 to report any other error.
1360
//! These error codes comply with MIOS32_MIDI_SendPackage_NonBlocking()
211 tk 1361
//! \return < 0 on errors
281 tk 1362
//! \note Please use the filtering capabilities with special care - if a port
1363
//! is filtered which is also used for code upload, you won't be able to exchange
1364
//! the erroneous code w/o starting the bootloader in hold mode after power-on.
155 tk 1365
/////////////////////////////////////////////////////////////////////////////
1327 tk 1366
s32 MIOS32_MIDI_DirectTxCallback_Init(s32 (*callback_tx)(mios32_midi_port_t port, mios32_midi_package_t package))
155 tk 1367
{
1368
  direct_tx_callback_func = callback_tx;
157 tk 1369
 
1370
  return 0; // no error
155 tk 1371
}
1372
 
1373
 
1374
/////////////////////////////////////////////////////////////////////////////
281 tk 1375
//! Installs the Rx callback function which is executed immediately on each
1376
//! incoming/outgoing MIDI byte, partly from interrupt handlers.
1377
//!
1378
//! This function should be executed so fast as possible. It can be used
1379
//! to trigger MIDI Rx LEDs or to trigger on MIDI clock events. In order to
1380
//! avoid MIDI buffer overruns, the max. recommented execution time is 100 uS!
1381
//!
1382
//! It is possible to filter incoming MIDI bytes with the return value of the
1383
//! callback function.<BR>
1384
//! \param[in] *callback_rx pointer to callback function:<BR>
1385
//! \code
674 tk 1386
//!    s32 callback_rx(mios32_midi_port_t port, u8 midi_byte)
1387
//!    {
1388
//!    }
281 tk 1389
//! \endcode
1390
//! The byte will be forwarded into the MIDI Rx queue if the function returns 0.<BR>
1391
//! It will be filtered out if the callback returns != 0 (e.g. 1 for "filter", 
1392
//! or -1 for "error").
1393
//! \return < 0 on errors
1394
//! \note Please use the filtering capabilities with special care - if a port
1395
//! is filtered which is also used for code upload, you won't be able to exchange
1396
//! the erroneous code w/o starting the bootloader in hold mode after power-on.
155 tk 1397
/////////////////////////////////////////////////////////////////////////////
1327 tk 1398
s32 MIOS32_MIDI_DirectRxCallback_Init(s32 (*callback_rx)(mios32_midi_port_t port, u8 midi_byte))
155 tk 1399
{
281 tk 1400
  direct_rx_callback_func = callback_rx;
155 tk 1401
 
157 tk 1402
  return 0; // no error
155 tk 1403
}
1404
 
281 tk 1405
 
155 tk 1406
/////////////////////////////////////////////////////////////////////////////
211 tk 1407
//! This function is used by MIOS32 internal functions to forward received
281 tk 1408
//! MIDI bytes to the Rx Callback routine.
1409
//!
1410
//! It shouldn't be used by applications.
1328 tk 1411
//! \param[in] port MIDI port (DEFAULT, USB0..USB7, UART0..UART3, IIC0..IIC7)
281 tk 1412
//! \param[in] midi_byte received MIDI byte
211 tk 1413
//! \return < 0 on errors
155 tk 1414
/////////////////////////////////////////////////////////////////////////////
281 tk 1415
s32 MIOS32_MIDI_SendByteToRxCallback(mios32_midi_port_t port, u8 midi_byte)
155 tk 1416
{
1417
  // note: here we could filter the user hook execution on special situations
281 tk 1418
  if( direct_rx_callback_func != NULL )
1419
    return direct_rx_callback_func(port, midi_byte);
157 tk 1420
  return 0; // no error
155 tk 1421
}
1422
 
1423
/////////////////////////////////////////////////////////////////////////////
211 tk 1424
//! This function is used by MIOS32 internal functions to forward received
281 tk 1425
//! MIDI packages to the Rx Callback routine (byte by byte)
1426
//!
1427
//! It shouldn't be used by applications.
1328 tk 1428
//! \param[in] port MIDI port (DEFAULT, USB0..USB7, UART0..UART3, IIC0..IIC7)
281 tk 1429
//! \param[in] midi_package received MIDI package
211 tk 1430
//! \return < 0 on errors
155 tk 1431
/////////////////////////////////////////////////////////////////////////////
281 tk 1432
s32 MIOS32_MIDI_SendPackageToRxCallback(mios32_midi_port_t port, mios32_midi_package_t midi_package)
155 tk 1433
{
1434
  // note: here we could filter the user hook execution on special situations
281 tk 1435
  if( direct_rx_callback_func != NULL ) {
155 tk 1436
    u8 buffer[3] = {midi_package.evnt0, midi_package.evnt1, midi_package.evnt2};
1437
    int len = mios32_midi_pcktype_num_bytes[midi_package.cin];
1438
    int i;
283 tk 1439
    s32 status = 0;
155 tk 1440
    for(i=0; i<len; ++i)
281 tk 1441
      status |= direct_rx_callback_func(port, buffer[i]);
1442
    return status;
155 tk 1443
  }
157 tk 1444
  return 0; // no error
155 tk 1445
}
1446
 
225 tk 1447
/////////////////////////////////////////////////////////////////////////////
1448
//! This function allows to change the DEFAULT port.<BR>
1449
//! The preset which will be used after application reset can be set in
1450
//! mios32_config.h via "#define MIOS32_MIDI_DEFAULT_PORT <port>".<BR>
1127 tk 1451
//! It's set to USB0 as long as not overruled in mios32_config.h
1328 tk 1452
//! \param[in] port MIDI port (USB0..USB7, UART0..UART3, IIC0..IIC7)
225 tk 1453
//! \return < 0 on errors
1454
/////////////////////////////////////////////////////////////////////////////
1455
s32 MIOS32_MIDI_DefaultPortSet(mios32_midi_port_t port)
1456
{
1457
  if( port == DEFAULT ) // avoid recursion
1458
    return -1;
1459
 
1460
  default_port = port;
1461
 
1462
  return 0; // no error
1463
}
1464
 
1465
/////////////////////////////////////////////////////////////////////////////
1466
//! This function returns the DEFAULT port
1467
//! \return the default port
1468
/////////////////////////////////////////////////////////////////////////////
1469
mios32_midi_port_t MIOS32_MIDI_DefaultPortGet(void)
1470
{
1471
  return default_port;
1472
}
1473
 
1474
 
1475
/////////////////////////////////////////////////////////////////////////////
307 tk 1476
//! This function allows to change the MIDI_DEBUG port.<BR>
1477
//! The preset which will be used after application reset can be set in
1478
//! mios32_config.h via "#define MIOS32_MIDI_DEBUG_PORT <port>".<BR>
1127 tk 1479
//! It's set to USB0 as long as not overruled in mios32_config.h
1328 tk 1480
//! \param[in] port MIDI port (USB0..USB7, UART0..UART3, IIC0..IIC7)
307 tk 1481
//! \return < 0 on errors
1482
/////////////////////////////////////////////////////////////////////////////
1483
s32 MIOS32_MIDI_DebugPortSet(mios32_midi_port_t port)
1484
{
1485
  if( port == MIDI_DEBUG ) // avoid recursion
1486
    return -1;
1487
 
1488
  debug_port = port;
1275 tk 1489
 
307 tk 1490
  return 0; // no error
1491
}
1492
 
1493
/////////////////////////////////////////////////////////////////////////////
1494
//! This function returns the MIDI_DEBUG port
1495
//! \return the debug port
1496
/////////////////////////////////////////////////////////////////////////////
1497
mios32_midi_port_t MIOS32_MIDI_DebugPortGet(void)
1498
{
1499
  return debug_port;
1500
}
1501
 
1502
 
1503
/////////////////////////////////////////////////////////////////////////////
225 tk 1504
//! This function sets the SysEx Device ID, which is used during parsing
1505
//! incoming SysEx Requests to MIOS32<BR>
1506
//! It can also be used by an application for additional parsing with the same ID.<BR>
1507
//! ID changes will get lost after reset. It can be changed permanently by the
1300 tk 1508
//! user via the bootloader update tool
225 tk 1509
//! \param[in] device_id a new (temporary) device ID (0x00..0x7f)
1510
//! \return < 0 on errors
1511
/////////////////////////////////////////////////////////////////////////////
1512
s32 MIOS32_MIDI_DeviceIDSet(u8 device_id)
1513
{
1514
  sysex_device_id = device_id & 0x7f;
1515
  return 0; // no error
1516
}
1517
 
1518
/////////////////////////////////////////////////////////////////////////////
1519
//! This function returns the SysEx Device ID, which is used during parsing
1520
//! incoming SysEx Requests to MIOS32<BR>
1521
//! It can also be used by an application for additional parsing with the same ID.<BR>
1522
//! The initial ID is stored inside the BSL range and will be recovered after
1300 tk 1523
//! reset. It can be changed by the user with the bootloader update tool
225 tk 1524
//! \return SysEx device ID (0x00..0x7f)
1525
/////////////////////////////////////////////////////////////////////////////
1526
u8 MIOS32_MIDI_DeviceIDGet(void)
1527
{
1528
  return sysex_device_id;
1529
}
1530
 
1531
 
1532
/////////////////////////////////////////////////////////////////////////////
674 tk 1533
//! Installs an optional SysEx callback which is called by 
676 tk 1534
//! MIOS32_MIDI_Receive_Handler() to simplify the parsing of SysEx streams.
674 tk 1535
//!
1536
//! Without this callback (or with MIOS32_MIDI_SysExCallback_Init(NULL)),
676 tk 1537
//! SysEx messages are only forwarded to APP_MIDI_NotifyPackage() in chunks of 
674 tk 1538
//! 1, 2 or 3 bytes, tagged with midi_package.type == 0x4..0x7 or 0xf
1539
//! 
1540
//! In this case, the application has to take care for different transmission
1541
//! approaches which are under control of the package sender. E.g., while Windows
1542
//! uses Package Type 4..7 to transmit a SysEx stream, PortMIDI under MacOS sends 
1543
//! a mix of 0xf (single byte) and 0x4 (continued 3-byte) packages instead.
1544
//! 
677 tk 1545
//! By using the SysEx callback, the type of package doesn't play a role anymore,
674 tk 1546
//! instead the application can parse a serial stream.
1547
//!
1548
//! MIOS32 ensures, that realtime events (0xf8..0xff) are still forwarded to
1549
//! APP_MIDI_NotifyPackage(), regardless if they are transmitted in a package
1550
//! type 0x5 or 0xf, so that the SysEx parser doesn't need to filter out such
1551
//! events, which could otherwise appear inside a SysEx stream.
1552
//! 
1553
//! \param[in] *callback_sysex pointer to callback function:<BR>
1554
//! \code
1555
//!    s32 callback_sysex(mios32_midi_port_t port, u8 sysex_byte)
1556
//!    {
675 tk 1557
//!       //
674 tk 1558
//!       // .. parse stream
675 tk 1559
//!       //
1560
//!     
1561
//!       return 1; // don't forward package to APP_MIDI_NotifyPackage()
674 tk 1562
//!    }
1563
//! \endcode
675 tk 1564
//! If the function returns 0, SysEx bytes will be forwarded to APP_MIDI_NotifyPackage() as well.
1565
//! With return value != 0, APP_MIDI_NotifyPackage() won't get the already processed package.
674 tk 1566
//! \return < 0 on errors
1567
/////////////////////////////////////////////////////////////////////////////
1327 tk 1568
s32 MIOS32_MIDI_SysExCallback_Init(s32 (*callback_sysex)(mios32_midi_port_t port, u8 midi_in))
674 tk 1569
{
1570
  sysex_callback_func = callback_sysex;
1571
 
1572
  return 0; // no error
1573
}
1574
 
1575
/////////////////////////////////////////////////////////////////////////////
225 tk 1576
// This function parses an incoming sysex stream for MIOS32 commands
1577
/////////////////////////////////////////////////////////////////////////////
1578
static s32 MIOS32_MIDI_SYSEX_Parser(mios32_midi_port_t port, u8 midi_in)
1579
{
1580
  // ignore realtime messages (see MIDI spec - realtime messages can
1581
  // always be injected into events/streams, and don't change the running status)
1582
  if( midi_in >= 0xf8 )
1583
    return 0;
1584
 
1585
  // TODO: here we could send an error notification, that multiple devices are trying to access the device
1586
  if( sysex_state.MY_SYSEX && port != last_sysex_port )
1587
    return -1;
1588
 
1135 tk 1589
  // USB upload is only allowed via USB0
1590
  // this covers the scenario where other USB1..7 ports are used for MIDI Port forwarding, and a MIOS8 core
1591
  // is connected to one of these ports
1592
  // MIOS Studio reports "Detected MIOS8 and MIOS32 response - selection not supported yet!" in this case
1593
  // By ignoring >= USB1 <= USB7 we have at least a workaround which works (for example) for MIDIbox LC
1594
  if( port >= USB1 && port <= USB7 )
1595
    return -1;
1596
 
225 tk 1597
  last_sysex_port = port;
1598
 
1599
  // branch depending on state
1600
  if( !sysex_state.MY_SYSEX ) {
1601
    if( (sysex_state.CTR < sizeof(mios32_midi_sysex_header) && midi_in != mios32_midi_sysex_header[sysex_state.CTR]) ||
1602
    (sysex_state.CTR == sizeof(mios32_midi_sysex_header) && midi_in != sysex_device_id) ) {
1603
      // incoming byte doesn't match
1604
      MIOS32_MIDI_SYSEX_CmdFinished();
1605
    } else {
1606
      if( ++sysex_state.CTR > sizeof(mios32_midi_sysex_header) ) {
1607
    // complete header received, waiting for data
1608
    sysex_state.MY_SYSEX = 1;
1609
      }
1610
    }
1611
  } else {
1612
    // check for end of SysEx message or invalid status byte
1613
    if( midi_in >= 0x80 ) {
1614
      if( midi_in == 0xf7 && sysex_state.CMD ) {
1615
        MIOS32_MIDI_SYSEX_Cmd(port, MIOS32_MIDI_SYSEX_CMD_STATE_END, midi_in);
1616
      }
1617
      MIOS32_MIDI_SYSEX_CmdFinished();
1618
    } else {
1619
      // check if command byte has been received
1620
      if( !sysex_state.CMD ) {
1621
    sysex_state.CMD = 1;
1622
    sysex_cmd = midi_in;
1623
    MIOS32_MIDI_SYSEX_Cmd(port, MIOS32_MIDI_SYSEX_CMD_STATE_BEGIN, midi_in);
1624
      }
1625
      else
1626
    MIOS32_MIDI_SYSEX_Cmd(port, MIOS32_MIDI_SYSEX_CMD_STATE_CONT, midi_in);
1627
    }
1628
  }
1629
 
1630
  return 0; // no error
1631
}
1632
 
1633
 
1634
/////////////////////////////////////////////////////////////////////////////
1635
// This function is called at the end of a sysex command or on 
1636
// an invalid message
1637
/////////////////////////////////////////////////////////////////////////////
1638
static s32 MIOS32_MIDI_SYSEX_CmdFinished(void)
1639
{
1640
  // clear all status variables
1641
  sysex_state.ALL = 0;
1642
  sysex_cmd = 0;
1643
 
1644
  return 0; // no error
1645
}
1646
 
1647
/////////////////////////////////////////////////////////////////////////////
1648
// This function handles the sysex commands
1649
/////////////////////////////////////////////////////////////////////////////
1650
static s32 MIOS32_MIDI_SYSEX_Cmd(mios32_midi_port_t port, mios32_midi_sysex_cmd_state_t cmd_state, u8 midi_in)
1651
{
238 tk 1652
#if MIOS32_MIDI_BSL_ENHANCEMENTS
1653
  // this compile switch should only be activated for the bootloader!
1654
  if( BSL_SYSEX_Cmd(port, cmd_state, midi_in, sysex_cmd) >= 0 )
1655
    return 0; // BSL has serviced this command - no error
1656
#endif
225 tk 1657
  switch( sysex_cmd ) {
1658
    case 0x00:
230 tk 1659
      MIOS32_MIDI_SYSEX_Cmd_Query(port, cmd_state, midi_in);
225 tk 1660
      break;
582 tk 1661
    case 0x0d:
1662
      MIOS32_MIDI_SYSEX_Cmd_Debug(port, cmd_state, midi_in);
1663
      break;
626 tk 1664
    case 0x0e: // ignore to avoid loopbacks
1665
      break;
225 tk 1666
    case 0x0f:
1667
      MIOS32_MIDI_SYSEX_Cmd_Ping(port, cmd_state, midi_in);
1668
      break;
1669
    default:
1670
      // unknown command
1671
      // TODO: send 0xf7 if merger enabled
1672
      MIOS32_MIDI_SYSEX_SendAck(port, MIOS32_MIDI_SYSEX_DISACK, MIOS32_MIDI_SYSEX_DISACK_INVALID_COMMAND);
1673
      MIOS32_MIDI_SYSEX_CmdFinished();      
1674
  }
1675
 
1676
  return 0; // no error
1677
}
1678
 
1679
 
1680
 
1681
/////////////////////////////////////////////////////////////////////////////
230 tk 1682
// Command 00: Query core informations and request BSL entry
225 tk 1683
/////////////////////////////////////////////////////////////////////////////
230 tk 1684
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 1685
{
230 tk 1686
  static u8 query_req = 0;
1687
  char str_buffer[40];
225 tk 1688
 
1689
  switch( cmd_state ) {
1690
 
1691
    case MIOS32_MIDI_SYSEX_CMD_STATE_BEGIN:
230 tk 1692
      query_req = 0;
225 tk 1693
      break;
1694
 
1695
    case MIOS32_MIDI_SYSEX_CMD_STATE_CONT:
230 tk 1696
      query_req = midi_in;
1697
      break;
1698
 
1699
    default: // MIOS32_MIDI_SYSEX_CMD_STATE_END
1700
      switch( query_req ) {
1701
        case 0x01: // operating system
1702
      MIOS32_MIDI_SYSEX_SendAckStr(port, "MIOS32");
225 tk 1703
      break;
237 tk 1704
        case 0x02: // Board
230 tk 1705
      MIOS32_MIDI_SYSEX_SendAckStr(port, MIOS32_BOARD_STR);
225 tk 1706
      break;
230 tk 1707
        case 0x03: // Core Family
1708
      MIOS32_MIDI_SYSEX_SendAckStr(port, MIOS32_FAMILY_STR);
225 tk 1709
      break;
230 tk 1710
        case 0x04: // Chip ID
1711
      sprintf(str_buffer, "%08x", MIOS32_SYS_ChipIDGet());
1712
      MIOS32_MIDI_SYSEX_SendAckStr(port, (char *)str_buffer);
1713
      break;
1714
        case 0x05: // Serial Number
1715
      if( MIOS32_SYS_SerialNumberGet((char *)str_buffer) >= 0 )
1716
        MIOS32_MIDI_SYSEX_SendAckStr(port, str_buffer);
1717
      else
1718
        MIOS32_MIDI_SYSEX_SendAckStr(port, "?");
1719
      break;
1720
        case 0x06: // Flash Memory Size
1721
      sprintf(str_buffer, "%d", MIOS32_SYS_FlashSizeGet());
1722
      MIOS32_MIDI_SYSEX_SendAckStr(port, str_buffer);
1723
      break;
1724
        case 0x07: // RAM Memory Size
1725
      sprintf(str_buffer, "%d", MIOS32_SYS_RAMSizeGet());
1726
      MIOS32_MIDI_SYSEX_SendAckStr(port, str_buffer);
1727
      break;
1728
        case 0x08: // Application Name Line #1
1729
      MIOS32_MIDI_SYSEX_SendAckStr(port, MIOS32_LCD_BOOT_MSG_LINE1);
1730
      break;
1731
        case 0x09: // Application Name Line #2
1732
      MIOS32_MIDI_SYSEX_SendAckStr(port, MIOS32_LCD_BOOT_MSG_LINE2);
1733
      break;
1734
        case 0x7f:
231 tk 1735
#if MIOS32_MIDI_BSL_ENHANCEMENTS
1736
      // release halt state (or sending upload request) instead of reseting the core
1737
      BSL_SYSEX_ReleaseHaltState();
1738
#else
230 tk 1739
      // reset core (this will send an upload request)
1740
      MIOS32_SYS_Reset();
1741
      // at least on STM32 we will never reach this point
1742
      // but other core families could contain an empty stumb!
231 tk 1743
#endif
230 tk 1744
      break;
1745
        default:
1746
      // unknown query
1747
      MIOS32_MIDI_SYSEX_SendAck(port, MIOS32_MIDI_SYSEX_DISACK, MIOS32_MIDI_SYSEX_DISACK_UNKNOWN_QUERY);
225 tk 1748
      }
1749
  }
1750
 
1751
  return 0; // no error
1752
}
1753
 
582 tk 1754
 
225 tk 1755
/////////////////////////////////////////////////////////////////////////////
582 tk 1756
// Command 0D: Debug Input/Output
1757
/////////////////////////////////////////////////////////////////////////////
1758
static s32 MIOS32_MIDI_SYSEX_Cmd_Debug(mios32_midi_port_t port, mios32_midi_sysex_cmd_state_t cmd_state, u8 midi_in)
1759
{
1760
  static u8 debug_req = 0xff;
1761
 
1762
  switch( cmd_state ) {
1763
 
1764
    case MIOS32_MIDI_SYSEX_CMD_STATE_BEGIN:
1765
      debug_req = 0xff;
1766
      break;
1767
 
1768
    case MIOS32_MIDI_SYSEX_CMD_STATE_CONT:
1769
      if( debug_req == 0xff ) {
1770
    debug_req = midi_in;
1771
      } else {
1772
    switch( debug_req ) {
1773
      case 0x00: // input string
1774
        if( debug_command_callback_func != NULL )
1775
          debug_command_callback_func(last_sysex_port, (char)midi_in);
1776
        break;
1777
 
1541 tk 1778
      case 0x01: // input string to filebrowser
1779
        if( filebrowser_command_callback_func != NULL )
1780
          filebrowser_command_callback_func(last_sysex_port, (char)midi_in);
1781
        break;
1782
 
582 tk 1783
      case 0x40: // output string
1541 tk 1784
      case 0x41: // output string for filebrowser
582 tk 1785
        // not supported - DisAck will be sent
1786
        break;
1787
 
1788
      default: // others
1789
        // not supported - DisAck will be sent
1790
        break;
1791
    }
1792
      }
1793
      break;
1794
 
1795
    default: // MIOS32_MIDI_SYSEX_CMD_STATE_END
1796
      if( debug_req == 0x00 ) {
1797
    // send acknowledge
1798
    MIOS32_MIDI_SYSEX_SendAck(port, MIOS32_MIDI_SYSEX_ACK, 0x00);
944 tk 1799
 
959 tk 1800
    if( debug_req == 0 && debug_command_callback_func == NULL ) {
1801
      mios32_midi_port_t prev_debug_port = MIOS32_MIDI_DebugPortGet();
1802
      MIOS32_MIDI_DebugPortSet(port);
1477 tk 1803
      MIOS32_MIDI_SendDebugString("[MIOS32_MIDI_SYSEX_Cmd_Debug] command handler not implemented by application\n");
959 tk 1804
      MIOS32_MIDI_DebugPortSet(prev_debug_port);
1805
    }
944 tk 1806
 
1541 tk 1807
      } else if( debug_req == 0x01 && filebrowser_command_callback_func != NULL ) {
1808
    // we expect that the filebrowser handler sends back a string
582 tk 1809
      } else {
1810
    // send disacknowledge
1811
    MIOS32_MIDI_SYSEX_SendAck(port, MIOS32_MIDI_SYSEX_DISACK, MIOS32_MIDI_SYSEX_DISACK_UNSUPPORTED_DEBUG);
1812
      }
1813
  }
1814
 
1815
  return 0; // no error
1816
}
1817
 
1818
/////////////////////////////////////////////////////////////////////////////
623 tk 1819
// Command 0F: Ping (just send back acknowledge if no additional byte has been received)
225 tk 1820
/////////////////////////////////////////////////////////////////////////////
1821
static s32 MIOS32_MIDI_SYSEX_Cmd_Ping(mios32_midi_port_t port, mios32_midi_sysex_cmd_state_t cmd_state, u8 midi_in)
1822
{
1823
  switch( cmd_state ) {
1824
 
1825
    case MIOS32_MIDI_SYSEX_CMD_STATE_BEGIN:
623 tk 1826
      sysex_state.PING_BYTE_RECEIVED = 0;
225 tk 1827
      break;
1828
 
1829
    case MIOS32_MIDI_SYSEX_CMD_STATE_CONT:
623 tk 1830
      sysex_state.PING_BYTE_RECEIVED = 1;
225 tk 1831
      break;
1832
 
1833
    default: // MIOS32_MIDI_SYSEX_CMD_STATE_END
1834
      // TODO: send 0xf7 if merger enabled
1835
 
623 tk 1836
      // send acknowledge if no additional byte has been received
1837
      // to avoid feedback loop if two cores are directly connected
1838
      if( !sysex_state.PING_BYTE_RECEIVED )
1839
    MIOS32_MIDI_SYSEX_SendAck(port, MIOS32_MIDI_SYSEX_ACK, 0x00);
225 tk 1840
 
1841
      break;
1842
  }
1843
 
1844
  return 0; // no error
1845
}
1846
 
1847
/////////////////////////////////////////////////////////////////////////////
1848
// This function sends a SysEx acknowledge to notify the user about the received command
1849
// expects acknowledge code (e.g. 0x0f for good, 0x0e for error) and additional argument
1850
/////////////////////////////////////////////////////////////////////////////
1851
static s32 MIOS32_MIDI_SYSEX_SendAck(mios32_midi_port_t port, u8 ack_code, u8 ack_arg)
1852
{
1853
  u8 sysex_buffer[32]; // should be enough?
1854
  u8 *sysex_buffer_ptr = &sysex_buffer[0];
1855
  int i;
1856
 
1857
  for(i=0; i<sizeof(mios32_midi_sysex_header); ++i)
1858
    *sysex_buffer_ptr++ = mios32_midi_sysex_header[i];
1859
 
1860
  // device ID
1861
  *sysex_buffer_ptr++ = MIOS32_MIDI_DeviceIDGet();
1862
 
1863
  // send ack code and argument
1864
  *sysex_buffer_ptr++ = ack_code;
1865
  *sysex_buffer_ptr++ = ack_arg;
1866
 
1867
  // send footer
1868
  *sysex_buffer_ptr++ = 0xf7;
1869
 
1870
  // finally send SysEx stream
1871
  return MIOS32_MIDI_SendSysEx(port, (u8 *)sysex_buffer, (u32)sysex_buffer_ptr - ((u32)&sysex_buffer[0]));
1872
}
1873
 
230 tk 1874
/////////////////////////////////////////////////////////////////////////////
1875
// This function sends an SysEx acknowledge with a string (used on queries)
1876
/////////////////////////////////////////////////////////////////////////////
1877
static s32 MIOS32_MIDI_SYSEX_SendAckStr(mios32_midi_port_t port, char *str)
1878
{
1560 tk 1879
  s32 status = 0;
1880
  mios32_midi_package_t package;
225 tk 1881
 
1560 tk 1882
  package.type = 0x4; // SysEx starts or continues
1883
  package.evnt0 = mios32_midi_sysex_header[0];
1884
  package.evnt1 = mios32_midi_sysex_header[1];
1885
  package.evnt2 = mios32_midi_sysex_header[2];
1886
  status |= MIOS32_MIDI_SendPackage(port, package);
155 tk 1887
 
1560 tk 1888
  package.type = 0x4; // SysEx starts or continues
1889
  package.evnt0 = mios32_midi_sysex_header[3];
1890
  package.evnt1 = mios32_midi_sysex_header[4];
1891
  package.evnt2 = MIOS32_MIDI_DeviceIDGet();
1892
  status |= MIOS32_MIDI_SendPackage(port, package);
230 tk 1893
 
1560 tk 1894
  package.type = 0x4; // SysEx starts or continues
1895
  package.evnt0 = MIOS32_MIDI_SYSEX_ACK;
1896
  package.evnt1 = str[0]; // first char or string terminator 0
1897
  package.evnt2 = str[1]; // second char, string terminator 0 or irrelevant char
1898
  status |= MIOS32_MIDI_SendPackage(port, package);
230 tk 1899
 
1560 tk 1900
  // more chars?
1901
  u32 len = strlen(str);
1902
  if( len >= 2 ) {
1903
    status |= MIOS32_MIDI_SendDebugStringBody(port, (char *)&str[2], len-2);
1904
  }
230 tk 1905
 
1560 tk 1906
  // footer
1907
  status |= MIOS32_MIDI_SendDebugStringFooter(port);
230 tk 1908
 
1560 tk 1909
  return status;
230 tk 1910
}
1911
 
529 tk 1912
 
1913
/////////////////////////////////////////////////////////////////////////////
582 tk 1914
//! Installs the debug command callback function which is executed on incoming
1915
//! characters from a MIOS Terminal
1916
//!
1917
//! Example:
1918
//! \code
1919
//! s32 CONSOLE_Parse(mios32_midi_port_t port, char c)
1920
//! {
1921
//!   // see $MIOS32_PATH/apps/examples/midi_console/
1922
//!   
1923
//!   return 0; // no error
1924
//! }
1925
//! \endcode
1926
//!
1927
//! The callback function has been installed in an Init() function with:
1928
//! \code
1929
//!   MIOS32_MIDI_DebugCommandCallback_Init(CONSOLE_Parse);
1930
//! \endcode
1931
//! \param[in] callback_debug_command the callback function (NULL disables the callback)
1932
//! \return < 0 on errors
1933
/////////////////////////////////////////////////////////////////////////////
1327 tk 1934
s32 MIOS32_MIDI_DebugCommandCallback_Init(s32 (*callback_debug_command)(mios32_midi_port_t port, char c))
582 tk 1935
{
1936
  debug_command_callback_func = callback_debug_command;
1937
 
1938
  return 0; // no error
1939
}
1940
 
1941
 
1942
/////////////////////////////////////////////////////////////////////////////
1541 tk 1943
//! Installs the filebrowser command callback function which is executed on incoming
1944
//! characters from aMIOS  Filebrowser
1945
//!
1946
//! Usage example: see terminal.c of $MIOS32_PATH/apps/controllers/midio128
1947
//!
1948
//! The callback function has been installed in an Init() function with:
1949
//! \code
1950
//!   MIOS32_MIDI_FilebrowserCommandCallback_Init(CONSOLE_Parse);
1951
//! \endcode
1952
//! \param[in] callback_debug_command the callback function (NULL disables the callback)
1953
//! \return < 0 on errors
1954
/////////////////////////////////////////////////////////////////////////////
1955
s32 MIOS32_MIDI_FilebrowserCommandCallback_Init(s32 (*filebrowser_debug_command)(mios32_midi_port_t port, char c))
1956
{
1957
  filebrowser_command_callback_func = filebrowser_debug_command;
1958
 
1959
  return 0; // no error
1960
}
1961
 
1962
 
1963
/////////////////////////////////////////////////////////////////////////////
529 tk 1964
//! Installs the Timeout callback function which is executed on incomplete
1965
//! MIDI packages received via UART, or on incomplete SysEx streams.
1966
//!
1967
//! A timeout is detected after 1 second.
1968
//!
1969
//! On a timeout, it is recommented to reset MIDI parsing relevant variables,
1970
//! e.g. the state of a SysEx parser.
1971
//!
1972
//! Example:
1973
//! \code
1974
//! s32 NOTIFY_MIDI_TimeOut(mios32_midi_port_t port)
1975
//! {
1976
//!   // if my SysEx parser receives a command (MY_SYSEX flag set), abort parser if port matches
1977
//!   if( sysex_state.MY_SYSEX && port == last_sysex_port )
1978
//!     MySYSEX_CmdFinished();
1979
//!
1980
//!   return 0; // no error
1981
//! }
1982
//! \endcode
1983
//!
1984
//! The callback function has been installed in an Init() function with:
1985
//! \code
674 tk 1986
//!   MIOS32_MIDI_TimeOutCallback_Init(NOTIFY_MIDI_TimeOut)
1987
//!   {
1988
//!   }
529 tk 1989
//! \endcode
1990
//! \param[in] callback_timeout the callback function (NULL disables the callback)
1991
//! \return < 0 on errors
1992
/////////////////////////////////////////////////////////////////////////////
1327 tk 1993
s32 MIOS32_MIDI_TimeOutCallback_Init(s32 (*callback_timeout)(mios32_midi_port_t port))
529 tk 1994
{
1995
  timeout_callback_func = callback_timeout;
1996
 
1997
  return 0; // no error
1998
}
1999
 
2000
 
2001
/////////////////////////////////////////////////////////////////////////////
2002
// This function is called if a MIDI parser runs into timeout
2003
/////////////////////////////////////////////////////////////////////////////
2004
static s32 MIOS32_MIDI_TimeOut(mios32_midi_port_t port)
2005
{
2006
  // if MIOS32 receives a SysEx command (MY_SYSEX flag set), abort parser if port matches
2007
  if( sysex_state.MY_SYSEX && port == last_sysex_port )
2008
    MIOS32_MIDI_SYSEX_CmdFinished();
2009
 
2010
  // optional hook to application
2011
  if( timeout_callback_func != NULL )
2012
    timeout_callback_func(port);
2013
 
2014
#if 1
2015
  // this debug message should always be active, so that common users are informed about the exception
2016
  MIOS32_MIDI_SendDebugMessage("[MIOS32_MIDI_Receive_Handler] Timeout on port 0x%02x\n", port);
2017
#endif
2018
 
2019
  return 0; // no error
2020
}
2021
 
32 tk 2022
#endif /* MIOS32_DONT_USE_MIDI */