Subversion Repositories svn.mios32

Rev

Rev 2649 | Details | Compare with Previous | Last modification | View Log | RSS feed

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