Subversion Repositories svn.mios32

Rev

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

Rev Author Line No. Line
2182 hawkeye 1
// $Id: app.c 1223 2011-06-23 21:26:52Z tk $
2
/*
3
 * Demo application for SSD1322 GLCD
4
 *
5
 * ==========================================================================
6
 *
7
 *  Copyright (C) 2008 Thorsten Klose (tk@midibox.org)
8
 *  Licensed for personal non-commercial use only.
9
 *  All other rights reserved.
10
 *
11
 * ==========================================================================
12
 */
13
 
14
/////////////////////////////////////////////////////////////////////////////
15
// Include files
16
/////////////////////////////////////////////////////////////////////////////
17
 
18
#include <mios32.h>
19
#include <msd.h>
20
#include "app.h"
21
#include "tasks.h"
22
#include "hardware.h"
23
 
24
#include <app_lcd.h>
25
 
26
#include <midi_port.h>
27
#include <midi_router.h>
28
#include <midimon.h>
29
 
30
#include "file.h"
31
 
32
#include <seq_bpm.h>
33
#include <seq_midi_out.h>
34
 
2184 hawkeye 35
#include "loopa.h"
2182 hawkeye 36
#include "terminal.h"
2571 hawkeye 37
#include "screen.h"
2182 hawkeye 38
 
39
 
2184 hawkeye 40
// #define DEBUG_MSG MIOS32_MIDI_SendDebugMessage
2182 hawkeye 41
 
2184 hawkeye 42
 
2182 hawkeye 43
// define priority level for sequencer
44
// use same priority as MIOS32 specific tasks
45
#define PRIORITY_TASK_PERIOD_1mS ( tskIDLE_PRIORITY + 3 )
46
 
47
// local prototype of the task function
48
static void TASK_Period_1mS(void *pvParameters);
49
 
50
// define priority level for control surface handler
51
// use lower priority as MIOS32 specific tasks (2), so that slow LCDs don't affect overall performance
52
#define PRIORITY_TASK_PERIOD_1mS_LP ( tskIDLE_PRIORITY + 2 )
53
 
54
// SD Card with lower priority
55
#define PRIORITY_TASK_PERIOD_1mS_SD ( tskIDLE_PRIORITY + 2 )
56
 
57
// local prototype of the task function
58
static void TASK_Period_1mS_LP(void *pvParameters);
59
static void TASK_Period_1mS_SD(void *pvParameters);
60
 
61
 
62
/////////////////////////////////////////////////////////////////////////////
63
// global variables
64
/////////////////////////////////////////////////////////////////////////////
65
u8 hw_enabled;    // After startup/config loaded, enable local hardware
66
 
67
/////////////////////////////////////////////////////////////////////////////
68
// Local types
69
/////////////////////////////////////////////////////////////////////////////
70
 
71
typedef enum {
72
  MSD_DISABLED,
73
  MSD_INIT,
74
  MSD_READY,
75
  MSD_SHUTDOWN
76
} msd_state_t;
77
 
78
 
79
/////////////////////////////////////////////////////////////////////////////
80
// local variables
81
/////////////////////////////////////////////////////////////////////////////
82
 
83
// for mutual exclusive SD Card access between different tasks
84
// The mutex is handled with MUTEX_SDCARD_TAKE and MUTEX_SDCARD_GIVE
85
// macros inside the application, which contain a different implementation
86
// for emulation
87
xSemaphoreHandle xSDCardSemaphore;
88
 
89
// Mutex for MIDI IN/OUT handler
90
xSemaphoreHandle xMIDIINSemaphore;
91
xSemaphoreHandle xMIDIOUTSemaphore;
92
 
2571 hawkeye 93
// Mutex for digital out (e.g. GP LED) updates
94
xSemaphoreHandle xDigitalOutSemaphore;
2182 hawkeye 95
 
96
static volatile msd_state_t msd_state;
97
 
98
/////////////////////////////////////////////////////////////////////////////
99
// Local prototypes
100
/////////////////////////////////////////////////////////////////////////////
101
static s32 NOTIFY_MIDI_Rx(mios32_midi_port_t port, u8 byte);
102
static s32 NOTIFY_MIDI_Tx(mios32_midi_port_t port, mios32_midi_package_t package);
103
static s32 NOTIFY_MIDI_TimeOut(mios32_midi_port_t port);
104
 
105
 
106
/////////////////////////////////////////////////////////////////////////////
107
// This hook is called after startup to initialize the application
108
/////////////////////////////////////////////////////////////////////////////
109
void APP_Init(void)
110
{
2571 hawkeye 111
   MIOS32_BOARD_LED_Init(0xffffffff); // initialize all LEDs
2182 hawkeye 112
 
2571 hawkeye 113
   MIOS32_MIDI_SendDebugMessage("=============================================================");
2593 hawkeye 114
   MIOS32_MIDI_SendDebugMessage("Starting LoopA");
2182 hawkeye 115
 
2571 hawkeye 116
   // enable MSD by default (has to be enabled in SHIFT menu)
117
   msd_state = MSD_DISABLED;
2182 hawkeye 118
 
2571 hawkeye 119
   // hardware will be enabled once configuration has been loaded from SD Card
120
   // (resp. no SD Card is available)
121
   hw_enabled = 0;
2182 hawkeye 122
 
2571 hawkeye 123
   // create semaphores
124
   xSDCardSemaphore = xSemaphoreCreateRecursiveMutex();
125
   xMIDIINSemaphore = xSemaphoreCreateRecursiveMutex();
126
   xMIDIOUTSemaphore = xSemaphoreCreateRecursiveMutex();
127
   xDigitalOutSemaphore = xSemaphoreCreateRecursiveMutex();
2182 hawkeye 128
 
2571 hawkeye 129
   // install SysEx callback
130
   MIOS32_MIDI_SysExCallback_Init(APP_SYSEX_Parser);
2182 hawkeye 131
 
2571 hawkeye 132
   // install MIDI Rx/Tx callback functions
133
   MIOS32_MIDI_DirectRxCallback_Init(&NOTIFY_MIDI_Rx);
134
   MIOS32_MIDI_DirectTxCallback_Init(&NOTIFY_MIDI_Tx);
2182 hawkeye 135
 
2571 hawkeye 136
   // install timeout callback function
137
   MIOS32_MIDI_TimeOutCallback_Init(&NOTIFY_MIDI_TimeOut);
2182 hawkeye 138
 
2571 hawkeye 139
   // initialize code modules
140
   MIDI_PORT_Init(0);
141
   MIDI_ROUTER_Init(0);
142
   TERMINAL_Init(0);
143
   MIDIMON_Init(0);
144
   FILE_Init(0);
145
   SEQ_MIDI_OUT_Init(0);
146
   seqInit(0);
2182 hawkeye 147
 
2571 hawkeye 148
   // install four encoders...
149
   mios32_enc_config_t enc_config = MIOS32_ENC_ConfigGet(enc_scene_id);
150
   enc_config.cfg.type = DETENTED3;
151
   enc_config.cfg.sr = enc_scene / 8 + 1;
152
   enc_config.cfg.pos = enc_scene % 8;
153
   enc_config.cfg.speed = NORMAL;
154
   enc_config.cfg.speed_par = 0;
155
   MIOS32_ENC_ConfigSet(enc_scene_id, enc_config);
2182 hawkeye 156
 
2571 hawkeye 157
   enc_config = MIOS32_ENC_ConfigGet(enc_track_id);
158
   enc_config.cfg.type = DETENTED3;
159
   enc_config.cfg.sr = enc_track / 8 + 1;
160
   enc_config.cfg.pos = enc_track % 8;
161
   enc_config.cfg.speed = NORMAL;
162
   enc_config.cfg.speed_par = 0;
163
   MIOS32_ENC_ConfigSet(enc_track_id, enc_config);
2182 hawkeye 164
 
2571 hawkeye 165
   enc_config = MIOS32_ENC_ConfigGet(enc_page_id);
166
   enc_config.cfg.type = DETENTED3;
167
   enc_config.cfg.sr = enc_page / 8 + 1;
168
   enc_config.cfg.pos = enc_page % 8;
169
   enc_config.cfg.speed = NORMAL;
170
   enc_config.cfg.speed_par = 0;
171
   MIOS32_ENC_ConfigSet(enc_page_id, enc_config);
2182 hawkeye 172
 
2571 hawkeye 173
   enc_config = MIOS32_ENC_ConfigGet(enc_data_id);
174
   enc_config.cfg.type = DETENTED3;
175
   enc_config.cfg.sr = enc_data / 8 + 1;
176
   enc_config.cfg.pos = enc_data % 8;
177
   enc_config.cfg.speed = NORMAL;
178
   enc_config.cfg.speed_par = 0;
179
   MIOS32_ENC_ConfigSet(enc_data_id, enc_config);
2184 hawkeye 180
 
2571 hawkeye 181
   // start tasks
2593 hawkeye 182
   xTaskCreate(TASK_Period_1mS, (const char * const)"1mS", configMINIMAL_STACK_SIZE, NULL, PRIORITY_TASK_PERIOD_1mS, NULL);
183
   xTaskCreate(TASK_Period_1mS_LP, (const char * const)"1mS_LP", 2*configMINIMAL_STACK_SIZE, NULL, PRIORITY_TASK_PERIOD_1mS_LP, NULL);
184
   xTaskCreate(TASK_Period_1mS_SD, (const char * const)"1mS_SD", 2*configMINIMAL_STACK_SIZE, NULL, PRIORITY_TASK_PERIOD_1mS_SD, NULL);
2571 hawkeye 185
 
186
   loopaStartup();
2182 hawkeye 187
}
188
 
189
 
190
/////////////////////////////////////////////////////////////////////////////
191
// This task is running endless in background
192
/////////////////////////////////////////////////////////////////////////////
193
void APP_Background(void)
194
{
195
}
196
 
197
 
198
/////////////////////////////////////////////////////////////////////////////
199
// This hook is called each mS from the MIDI task which checks for incoming
200
// MIDI events. You could add more MIDI related jobs here, but they shouldn't
201
// consume more than 300 uS to ensure the responsiveness of incoming MIDI.
202
/////////////////////////////////////////////////////////////////////////////
203
void APP_MIDI_Tick(void)
204
{
205
}
206
 
207
 
208
/////////////////////////////////////////////////////////////////////////////
209
// This hook is called when a MIDI package has been received
210
/////////////////////////////////////////////////////////////////////////////
211
void APP_MIDI_NotifyPackage(mios32_midi_port_t port, mios32_midi_package_t midi_package)
212
{
213
  // -> MIDI Router
214
  MIDI_ROUTER_Receive(port, midi_package);
215
 
216
  // -> MIDI Port Handler (used for MIDI monitor function)
217
  MIDI_PORT_NotifyMIDIRx(port, midi_package);
218
 
2571 hawkeye 219
  /// -> MIDI file recorder
220
  /// MID_FILE_Receive(port, midi_package);
2182 hawkeye 221
 
2571 hawkeye 222
  // Record midi event in loopa
223
  loopaRecord(port, midi_package);
224
 
2182 hawkeye 225
  // forward to MIDI Monitor
226
  // SysEx messages have to be filtered for USB0 and UART0 to avoid data corruption
227
  // (the SysEx stream would interfere with monitor messages)
228
  u8 filter_sysex_message = (port == USB0) || (port == UART0);
229
  MIDIMON_Receive(port, midi_package, filter_sysex_message);
230
 
2571 hawkeye 231
   /*
2182 hawkeye 232
  // Draw notes to voxel space
233
  if( midi_package.event == NoteOn && midi_package.velocity > 0)
234
     voxelNoteOn(midi_package.note, midi_package.velocity);
235
 
236
  if( midi_package.event == NoteOff || (midi_package.event == NoteOn && midi_package.velocity == 0) )
237
     voxelNoteOff(midi_package.note);
2571 hawkeye 238
     */
2182 hawkeye 239
}
240
 
241
 
242
/////////////////////////////////////////////////////////////////////////////
243
// This function parses an incoming sysex stream for MIOS32 commands
244
/////////////////////////////////////////////////////////////////////////////
245
s32 APP_SYSEX_Parser(mios32_midi_port_t port, u8 midi_in)
246
{
2571 hawkeye 247
   // -> MIDI Router
248
   MIDI_ROUTER_ReceiveSysEx(port, midi_in);
2182 hawkeye 249
 
2571 hawkeye 250
   return 0; // no error
2182 hawkeye 251
}
252
 
253
 
254
/////////////////////////////////////////////////////////////////////////////
255
// This hook is called before the shift register chain is scanned
256
/////////////////////////////////////////////////////////////////////////////
257
void APP_SRIO_ServicePrepare(void)
258
{
259
}
260
 
261
 
262
/////////////////////////////////////////////////////////////////////////////
263
// This hook is called after the shift register chain has been scanned
264
/////////////////////////////////////////////////////////////////////////////
265
void APP_SRIO_ServiceFinish(void)
266
{
267
}
268
 
269
 
270
/////////////////////////////////////////////////////////////////////////////
271
// This hook is called when a button has been toggled
272
// pin_value is 1 when button released, and 0 when button pressed
273
/////////////////////////////////////////////////////////////////////////////
274
void APP_DIN_NotifyToggle(u32 pin, u32 pin_value)
275
{
2571 hawkeye 276
   // MIOS32_MIDI_SendDebugMessage("PIN %d toggled - value %d", pin, pin_value);
2182 hawkeye 277
 
2184 hawkeye 278
   if (pin_value == 0)
279
      loopaButtonPressed(pin);
2593 hawkeye 280
   else
281
      loopaButtonReleased(pin);
2182 hawkeye 282
}
283
 
284
 
285
/////////////////////////////////////////////////////////////////////////////
286
// This hook is called when an encoder has been moved
287
// incrementer is positive when encoder has been turned clockwise, else
288
// it is negative
289
/////////////////////////////////////////////////////////////////////////////
290
void APP_ENC_NotifyChange(u32 encoder, s32 incrementer)
291
{
2571 hawkeye 292
   //MIOS32_MIDI_SendDebugMessage("Encoder %d turned - increment %d", encoder, incrementer);
2182 hawkeye 293
 
2571 hawkeye 294
   loopaEncoderTurned(encoder, incrementer);
2182 hawkeye 295
}
296
 
297
/////////////////////////////////////////////////////////////////////////////
298
// This hook is called when a pot has been moved
299
/////////////////////////////////////////////////////////////////////////////
300
void APP_AIN_NotifyChange(u32 pin, u32 pin_value)
301
{
302
}
303
 
304
/////////////////////////////////////////////////////////////////////////////
305
// This task handles the control surface
306
/////////////////////////////////////////////////////////////////////////////
307
static void TASK_Period_1mS_LP(void *pvParameters)
308
{
2571 hawkeye 309
   u16 taskCtr = 0;
2182 hawkeye 310
 
2571 hawkeye 311
   while( 1 )
312
   {
313
      vTaskDelay(1 / portTICK_RATE_MS);
314
      taskCtr++;
2182 hawkeye 315
 
2571 hawkeye 316
      // call SCS handler
317
      // SCS_Tick(); Call our own
2182 hawkeye 318
 
2571 hawkeye 319
      // MIDI In/Out monitor
320
      MIDI_PORT_Period1mS();
2182 hawkeye 321
 
2571 hawkeye 322
      if (taskCtr % 20 == 0)
323
      {
324
         display();
325
         updateGPLeds();
326
      }
327
   }
2182 hawkeye 328
}
329
 
330
/////////////////////////////////////////////////////////////////////////////
331
// This task handles the SD Card
332
/////////////////////////////////////////////////////////////////////////////
333
static void TASK_Period_1mS_SD(void *pvParameters)
334
{
335
 
336
  const u16 sdcard_check_delay = 1000;
337
  u16 sdcard_check_ctr = 0;
338
  u8 lun_available = 0;
339
 
2571 hawkeye 340
  while (1)
2182 hawkeye 341
  {
342
    vTaskDelay(1 / portTICK_RATE_MS);
343
 
344
    // each second: check if SD Card (still) available
345
 
2571 hawkeye 346
    if (msd_state == MSD_DISABLED && ++sdcard_check_ctr >= sdcard_check_delay)
2182 hawkeye 347
    {
348
       sdcard_check_ctr = 0;
349
 
350
       MUTEX_SDCARD_TAKE;
351
       s32 status = FILE_CheckSDCard();
352
 
2184 hawkeye 353
       if (status == 1)
2182 hawkeye 354
       {
355
          DEBUG_MSG("SD Card connected: %s\n", FILE_VolumeLabel());
356
 
357
          // stop sequencer
358
          SEQ_BPM_Stop();
359
 
360
          // load all file infos
361
          /// MIDIO_FILE_LoadAllFiles(1); // including HW info
362
 
363
          // immediately go to next step
364
          sdcard_check_ctr = sdcard_check_delay;
2184 hawkeye 365
       }
366
       else if (status == 2)
2182 hawkeye 367
       {
368
          DEBUG_MSG("SD Card disconnected\n");
369
          // invalidate all file infos
370
          /// MIDIO_FILE_UnloadAllFiles();
371
 
372
          // stop sequencer
373
          SEQ_BPM_Stop();
374
 
375
          // change status
376
          /// MIDIO_FILE_StatusMsgSet("No SD Card");
2184 hawkeye 377
       }
378
       else if (status == 3)
2182 hawkeye 379
       {
2184 hawkeye 380
          if (!FILE_SDCardAvailable())
2182 hawkeye 381
          {
382
             DEBUG_MSG("SD Card not found\n");
383
             /// MIDIO_FILE_StatusMsgSet("No SD Card");
2184 hawkeye 384
          }
385
          else if (!FILE_VolumeAvailable())
2182 hawkeye 386
          {
387
             DEBUG_MSG("ERROR: SD Card contains invalid FAT!\n");
388
             /// MIDIO_FILE_StatusMsgSet("No FAT");
2184 hawkeye 389
          }
390
          else
2182 hawkeye 391
          {
392
             // create the default files if they don't exist on SD Card
393
             /// MIDIO_FILE_CreateDefaultFiles();
2184 hawkeye 394
             loopaSDCardAvailable();
2182 hawkeye 395
          }
396
 
397
          hw_enabled = 1; // enable hardware after first read...
398
       }
399
 
400
       MUTEX_SDCARD_GIVE;
401
    }
402
 
403
    // MSD driver
404
    if( msd_state != MSD_DISABLED )
405
    {
406
       MUTEX_SDCARD_TAKE;
407
 
408
       switch( msd_state )
409
       {
410
       case MSD_SHUTDOWN:
411
          // switch back to USB MIDI
412
          MIOS32_USB_Init(1);
413
          msd_state = MSD_DISABLED;
414
          break;
415
 
416
       case MSD_INIT:
417
          // LUN not mounted yet
418
          lun_available = 0;
419
 
420
          // enable MSD USB driver
421
          //MUTEX_J16_TAKE;
422
          if( MSD_Init(0) >= 0 )
423
             msd_state = MSD_READY;
424
          else
425
             msd_state = MSD_SHUTDOWN;
426
          //MUTEX_J16_GIVE;
427
          break;
428
 
429
       case MSD_READY:
430
          // service MSD USB driver
431
          MSD_Periodic_mS();
432
 
433
          // this mechanism shuts down the MSD driver if SD card has been unmounted by OS
434
          if( lun_available && !MSD_LUN_AvailableGet(0) )
435
             msd_state = MSD_SHUTDOWN;
436
          else if( !lun_available && MSD_LUN_AvailableGet(0) )
437
             lun_available = 1;
438
          break;
439
       }
440
 
441
       MUTEX_SDCARD_GIVE;
442
    }
443
  }
444
}
445
 
446
 
447
/////////////////////////////////////////////////////////////////////////////
448
// This task is called periodically each mS to handle sequencer requests
449
/////////////////////////////////////////////////////////////////////////////
450
static void TASK_Period_1mS(void *pvParameters)
451
{
452
  portTickType xLastExecutionTime;
453
 
454
  // Initialise the xLastExecutionTime variable on task entry
455
  xLastExecutionTime = xTaskGetTickCount();
456
 
457
  while( 1 )
458
  {
459
     vTaskDelayUntil(&xLastExecutionTime, 1 / portTICK_RATE_MS);
460
 
461
     // skip delay gap if we had to wait for more than 5 ticks to avoid
462
     // unnecessary repeats until xLastExecutionTime reached xTaskGetTickCount() again
463
     portTickType xCurrentTickCount = xTaskGetTickCount();
2571 hawkeye 464
     if (xLastExecutionTime < xCurrentTickCount-5)
2182 hawkeye 465
        xLastExecutionTime = xCurrentTickCount;
466
 
467
     // execute sequencer handler
468
     MUTEX_SDCARD_TAKE;
2185 hawkeye 469
     seqHandler();
2182 hawkeye 470
     MUTEX_SDCARD_GIVE;
471
 
472
     // send timestamped MIDI events
473
     MUTEX_MIDIOUT_TAKE;
474
     SEQ_MIDI_OUT_Handler();
475
     MUTEX_MIDIOUT_GIVE;
476
 
477
     // Scan Matrix button handler
478
     /// MIDIO_MATRIX_ButtonHandler();
479
 
480
     // scan AINSER pins
481
     /// AINSER_Handler(APP_AINSER_NotifyChange);
482
  }
483
}
484
 
485
 
486
/////////////////////////////////////////////////////////////////////////////
487
// Installed via MIOS32_MIDI_DirectRxCallback_Init
488
/////////////////////////////////////////////////////////////////////////////
489
static s32 NOTIFY_MIDI_Rx(mios32_midi_port_t port, u8 midi_byte)
490
{
491
  // filter MIDI In port which controls the MIDI clock
2571 hawkeye 492
  if (MIDI_ROUTER_MIDIClockInGet(port) == 1)
2182 hawkeye 493
    SEQ_BPM_NotifyMIDIRx(midi_byte);
494
 
495
  return 0; // no error, no filtering
496
}
497
 
498
/////////////////////////////////////////////////////////////////////////////
499
// Installed via MIOS32_MIDI_DirectTxCallback_Init
500
/////////////////////////////////////////////////////////////////////////////
501
static s32 NOTIFY_MIDI_Tx(mios32_midi_port_t port, mios32_midi_package_t package)
502
{
503
   return MIDI_PORT_NotifyMIDITx(port, package);
504
}
505
 
506
/////////////////////////////////////////////////////////////////////////////
507
// Installed via MIOS32_MIDI_TimeoutCallback_Init
508
/////////////////////////////////////////////////////////////////////////////
509
static s32 NOTIFY_MIDI_TimeOut(mios32_midi_port_t port)
510
{
511
   // forward to SysEx parser
512
   /// MIDIO_SYSEX_TimeOut(port);
513
 
514
   // print message on screen
515
   /// SCS_Msg(SCS_MSG_L, 2000, "MIDI Protocol", "TIMEOUT !!!");
516
 
517
   return 0;
518
}
519
 
520
 
521
/////////////////////////////////////////////////////////////////////////////
522
// MSD access functions
523
/////////////////////////////////////////////////////////////////////////////
524
s32 TASK_MSD_EnableSet(u8 enable)
525
{
2184 hawkeye 526
   MIOS32_IRQ_Disable();
527
   if( msd_state == MSD_DISABLED && enable )
528
   {
529
      msd_state = MSD_INIT;
530
   } else if( msd_state == MSD_READY && !enable )
531
      msd_state = MSD_SHUTDOWN;
532
   MIOS32_IRQ_Enable();
2182 hawkeye 533
 
2184 hawkeye 534
   return 0; // no error
2182 hawkeye 535
}
536
 
537
s32 TASK_MSD_EnableGet()
538
{
2184 hawkeye 539
   return (msd_state == MSD_READY) ? 1 : 0;
2182 hawkeye 540
}
541
 
542
s32 TASK_MSD_FlagStrGet(char str[5])
543
{
2184 hawkeye 544
   str[0] = MSD_CheckAvailable() ? 'U' : '-';
545
   str[1] = MSD_LUN_AvailableGet(0) ? 'M' : '-';
546
   str[2] = MSD_RdLEDGet(250) ? 'R' : '-';
547
   str[3] = MSD_WrLEDGet(250) ? 'W' : '-';
548
   str[4] = 0;
2182 hawkeye 549
 
2184 hawkeye 550
   return 0; // no error
2182 hawkeye 551
}
552
 
553
 
554
/////////////////////////////////////////////////////////////////////////////
555
// functions to access MIDI IN/Out Mutex
556
// see also mios32_config.h
557
/////////////////////////////////////////////////////////////////////////////
558
void APP_MUTEX_MIDIOUT_Take(void) { MUTEX_MIDIOUT_TAKE; }
559
void APP_MUTEX_MIDIOUT_Give(void) { MUTEX_MIDIOUT_GIVE; }
560
void APP_MUTEX_MIDIIN_Take(void) { MUTEX_MIDIIN_TAKE; }
561
void APP_MUTEX_MIDIIN_Give(void) { MUTEX_MIDIIN_GIVE; }
562