Subversion Repositories svn.mios32

Rev

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