Subversion Repositories svn.mios32

Rev

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

Rev Author Line No. Line
730 tk 1
// $Id: app.c 2425 2016-11-03 00:44:22Z tk $
2
/*
3
 * MIDIbox LC V2
4
 *
5
 * ==========================================================================
6
 *
7
 *  Copyright (C) 2009 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
 
1490 tk 20
#include <eeprom.h>
21
 
730 tk 22
#include <FreeRTOS.h>
23
#include <portmacro.h>
24
#include <task.h>
25
#include <queue.h>
26
#include <semphr.h>
27
 
1490 tk 28
#include <midi_port.h>
29
#include <midi_router.h>
30
#include <midimon.h>
31
 
730 tk 32
#include "app.h"
1490 tk 33
#include "presets.h"
34
#include "terminal.h"
35
#include "tasks.h"
36
#include "uip_task.h"
37
#include "osc_client.h"
38
 
730 tk 39
#include "lc_hwcfg.h"
40
#include "lc_lcd.h"
41
#include "lc_sysex.h"
42
#include "lc_midi.h"
43
#include "lc_mf.h"
44
#include "lc_vpot.h"
45
#include "lc_dio.h"
46
#include "lc_gpc.h"
47
#include "lc_leddigits.h"
48
#include "lc_meters.h"
49
 
50
 
51
/////////////////////////////////////////////////////////////////////////////
52
// RTOS tasks
53
/////////////////////////////////////////////////////////////////////////////
54
 
1485 tk 55
// define priority level for periodic handler
56
// use same priority as MIOS32 specific tasks
57
#define PRIORITY_TASK_PERIOD_1mS ( tskIDLE_PRIORITY + 3 )
730 tk 58
 
1485 tk 59
// low-prio thread for LCD output
60
#define PRIORITY_TASK_PERIOD_1mS_LP ( tskIDLE_PRIORITY + 2 )
730 tk 61
 
1490 tk 62
 
63
/////////////////////////////////////////////////////////////////////////////
64
// Global variables
65
/////////////////////////////////////////////////////////////////////////////
66
 
67
// status of LC emulation
68
lc_flags_t lc_flags;
69
 
70
// Mutex for MIDI IN/OUT handler
71
xSemaphoreHandle xMIDIINSemaphore;
72
xSemaphoreHandle xMIDIOUTSemaphore;
73
 
74
 
75
/////////////////////////////////////////////////////////////////////////////
76
// Local prototypes
77
/////////////////////////////////////////////////////////////////////////////
78
 
1485 tk 79
// local prototype of the task functions
80
static void TASK_Period_1mS(void *pvParameters);
81
static void TASK_Period_1mS_LP(void *pvParameters);
730 tk 82
 
1490 tk 83
static s32 NOTIFY_MIDI_Rx(mios32_midi_port_t port, u8 byte);
84
static s32 NOTIFY_MIDI_Tx(mios32_midi_port_t port, mios32_midi_package_t package);
85
static s32 NOTIFY_MIDI_TimeOut(mios32_midi_port_t port);
1485 tk 86
 
1490 tk 87
 
730 tk 88
/////////////////////////////////////////////////////////////////////////////
1490 tk 89
// Default MIDI Router configuration
730 tk 90
/////////////////////////////////////////////////////////////////////////////
91
 
1490 tk 92
midi_router_node_entry_t midi_router_cfg[MIDI_ROUTER_NUM_NODES] = {
93
  // src  chn   dst  chn
94
  { USB0,  17, UART0, 17 }, // 17 == all
95
  { UART0, 17, USB0,  17 },
730 tk 96
 
1490 tk 97
  { USB1,  17, UART1, 17 },
98
  { UART1, 17, USB1,  17 },
730 tk 99
 
1490 tk 100
  { USB2,  17, UART2, 17 },
101
  { UART2, 17, USB2,  17 },
102
 
103
  { USB3,  17, UART3, 17 },
104
  { UART3, 17, USB3,  17 },
105
 
106
  { USB0,   0, UART0, 17 },
107
  { USB0,   0, UART0, 17 },
108
  { USB0,   0, UART0, 17 },
109
  { USB0,   0, UART0, 17 },
110
  { USB0,   0, UART0, 17 },
111
  { USB0,   0, UART0, 17 },
112
  { USB0,   0, UART0, 17 },
113
  { USB0,   0, UART0, 17 },
114
};
115
 
116
 
730 tk 117
/////////////////////////////////////////////////////////////////////////////
118
// This hook is called after startup to initialize the application
119
/////////////////////////////////////////////////////////////////////////////
120
void APP_Init(void)
121
{
1490 tk 122
  // create semaphores
123
  xMIDIINSemaphore = xSemaphoreCreateRecursiveMutex();
124
  xMIDIOUTSemaphore = xSemaphoreCreateRecursiveMutex();
125
 
126
  // install SysEx callback
127
  MIOS32_MIDI_SysExCallback_Init(APP_SYSEX_Parser);
128
 
129
  // install MIDI Rx/Tx callback functions
130
  MIOS32_MIDI_DirectRxCallback_Init(&NOTIFY_MIDI_Rx);
131
  MIOS32_MIDI_DirectTxCallback_Init(&NOTIFY_MIDI_Tx);
132
 
133
  // install timeout callback function
134
  MIOS32_MIDI_TimeOutCallback_Init(&NOTIFY_MIDI_TimeOut);
135
 
730 tk 136
  // initialize application specific variables
137
  LC_HWCFG_Init(0);
138
  LC_SYSEX_Init(0);
139
  LC_VPOT_Init(0);
140
  LC_MF_Init(0);
141
  LC_GPC_Init(0);
142
  LC_LEDDIGITS_Init(0);
143
  LC_DIO_SFBLEDUpdate();
144
 
145
  // initialize the shift registers
146
  //  MIOS32_SRIO_TS_SensitivitySet(TOUCHSENSOR_SENSITIVITY); // TODO
1490 tk 147
  MIOS32_SRIO_DebounceSet(20);
730 tk 148
 
1490 tk 149
  // init MIDI port/router handling
150
  MIDI_PORT_Init(0);
151
  MIDI_ROUTER_Init(0);
152
 
153
  // create default router configuration
154
  int node;
155
  midi_router_node_entry_t *ncfg = (midi_router_node_entry_t *)&midi_router_cfg[0];
156
  midi_router_node_entry_t *n = (midi_router_node_entry_t *)&midi_router_node[0];
157
  for(node=0; node<MIDI_ROUTER_NUM_NODES; ++node, ++n, ++ncfg) {
158
    n->src_port = ncfg->src_port;
159
    n->src_chn = ncfg->src_chn;
160
    n->dst_port = ncfg->dst_port;
161
    n->dst_chn = ncfg->dst_chn;
162
  }
163
 
164
  // init terminal
165
  TERMINAL_Init(0);
166
 
167
  // init MIDImon
168
  MIDIMON_Init(0);
169
 
170
  // read EEPROM content
171
  PRESETS_Init(0);
172
 
173
  // start uIP task
174
  UIP_TASK_Init(0);
175
 
176
  // print welcome message on MIOS terminal
177
  MIOS32_MIDI_SendDebugMessage("\n");
178
  MIOS32_MIDI_SendDebugMessage("=================\n");
179
  MIOS32_MIDI_SendDebugMessage("%s\n", MIOS32_LCD_BOOT_MSG_LINE1);
180
  MIOS32_MIDI_SendDebugMessage("=================\n");
181
  MIOS32_MIDI_SendDebugMessage("\n");
182
 
1485 tk 183
  // start tasks
2425 tk 184
  xTaskCreate(TASK_Period_1mS, "1mS", configMINIMAL_STACK_SIZE, NULL, PRIORITY_TASK_PERIOD_1mS, NULL);
185
  xTaskCreate(TASK_Period_1mS_LP, "1mS_LP", configMINIMAL_STACK_SIZE, NULL, PRIORITY_TASK_PERIOD_1mS_LP, NULL);
730 tk 186
}
187
 
188
/////////////////////////////////////////////////////////////////////////////
189
// This task is running endless in background
190
/////////////////////////////////////////////////////////////////////////////
191
void APP_Background(void)
192
{
193
}
194
 
195
 
196
/////////////////////////////////////////////////////////////////////////////
197
// This hook is called when a MIDI package has been received
198
/////////////////////////////////////////////////////////////////////////////
199
void APP_MIDI_NotifyPackage(mios32_midi_port_t port, mios32_midi_package_t midi_package)
200
{
1490 tk 201
  // -> MIDI Router
202
  MIDI_ROUTER_Receive(port, midi_package);
203
 
204
  // -> MIDI Port Handler (used for MIDI monitor function)
205
  MIDI_PORT_NotifyMIDIRx(port, midi_package);
206
 
207
  // forward to MIDI Monitor
208
  // SysEx messages have to be filtered for USB0 and UART0 to avoid data corruption
209
  // (the SysEx stream would interfere with monitor messages)
210
  u8 filter_sysex_message = (port == USB0) || (port == UART0);
1970 tk 211
  MIDIMON_Receive(port, midi_package, filter_sysex_message);
1490 tk 212
 
730 tk 213
  if( port == MIOS32_MIDI_DefaultPortGet() ) {
214
    // forward MIDI event to MIDI handler
215
    LC_MIDI_Received(midi_package);
216
 
217
    // forward MIDI event to GPC handler
218
    LC_GPC_Received(midi_package);
1136 tk 219
 
1485 tk 220
    // pitchbend events are also forwarded to MBHP_MF_NG module
221
    if( midi_package.type == PitchBend ) {
222
      MIOS32_MIDI_SendPackage(UART2, midi_package); // STM32 and LPC17
223
      MIOS32_MIDI_SendPackage(UART3, midi_package); // LPC17
224
    }
730 tk 225
  }
226
 
1485 tk 227
 
228
  // extra for MBHP_MF_NG: PitchBend and Note Events are also forwarded to default port
1490 tk 229
  if( port == UART2 || port == UART3 ) {
230
    if( midi_package.type == NoteOff || midi_package.type == NoteOn || midi_package.type == PitchBend ) {
231
      MIOS32_MIDI_SendPackage(USB0, midi_package);
1136 tk 232
 
1490 tk 233
      if( lc_hwcfg_verbose_level >= 2 ) {
234
    MIOS32_MIDI_SendDebugMessage("MBHP_MF_NG event forward: %02X %02X %02X",
235
                     midi_package.evnt0,
236
                     midi_package.evnt1,
237
                     midi_package.evnt2);
238
      }
239
    }
730 tk 240
  }
241
}
242
 
243
 
244
/////////////////////////////////////////////////////////////////////////////
1490 tk 245
// This function parses an incoming sysex stream for MIOS32 commands
246
/////////////////////////////////////////////////////////////////////////////
247
s32 APP_SYSEX_Parser(mios32_midi_port_t port, u8 midi_in)
248
{
249
  // -> MIDI Router
250
  MIDI_ROUTER_ReceiveSysEx(port, midi_in);
251
 
252
  // -> LC SysEx parser
253
  LC_SYSEX_Parser(port, midi_in);
254
 
255
  return 0; // no error
256
}
257
 
258
 
259
/////////////////////////////////////////////////////////////////////////////
730 tk 260
// This hook is called before the shift register chain is scanned
261
/////////////////////////////////////////////////////////////////////////////
262
void APP_SRIO_ServicePrepare(void)
263
{
264
  // sets the LEDring (and Meter) patterns
265
  LC_VPOT_LEDRing_SRHandler();
1485 tk 266
 
267
  // updates the MTC display
268
  LC_LEDDIGITS_SRHandler();
730 tk 269
}
270
 
271
 
272
/////////////////////////////////////////////////////////////////////////////
273
// This hook is called after the shift register chain has been scanned
274
/////////////////////////////////////////////////////////////////////////////
275
void APP_SRIO_ServiceFinish(void)
276
{
277
}
278
 
279
 
280
/////////////////////////////////////////////////////////////////////////////
281
// This hook is called when a button has been toggled
282
// pin_value is 1 when button released, and 0 when button pressed
283
/////////////////////////////////////////////////////////////////////////////
284
void APP_DIN_NotifyToggle(u32 pin, u32 pin_value)
285
{
1490 tk 286
  if( lc_hwcfg_verbose_level >= 2 ) {
287
    MIOS32_MIDI_SendDebugMessage("APP_DIN_NotifyToggle(%3d, %d) -> DIN SR%d.D%d %s\n",
288
                 pin, pin_value,
289
                 (pin/8)+1, pin % 8, pin_value ? "depressed" : "pressed");
290
  }
291
 
730 tk 292
  // branch to button handler
293
  LC_DIO_ButtonHandler(pin, pin_value);
294
}
295
 
296
 
297
/////////////////////////////////////////////////////////////////////////////
298
// This hook is called when an encoder has been moved
299
// incrementer is positive when encoder has been turned clockwise, else
300
// it is negative
301
/////////////////////////////////////////////////////////////////////////////
302
void APP_ENC_NotifyChange(u32 encoder, s32 incrementer)
303
{
1490 tk 304
  if( lc_hwcfg_verbose_level >= 2 ) {
305
    MIOS32_MIDI_SendDebugMessage("APP_ENC_NotifyChange(%3d, %d)\n", encoder, incrementer);
306
  }
307
 
730 tk 308
#if MBSEQ_HARDWARE_OPTION
309
 
310
  // encoder number 0: Jogwheel
311
  // encoder number 1, 3, 5, 7, 9, 11, 13, 15: VPOT
312
  // encoder number 2, 4, 6, 8, 10, 12, 14, 16: Fader replacement
313
  if( encoder == 0 )
314
    LC_VPOT_SendJogWheelEvent(incrementer);
315
  else if( encoder < 16 ) {
316
    if( !(encoder & 1) )
317
      LC_VPOT_SendFADEREvent((encoder >> 1)-1, incrementer);
318
    else
319
      LC_VPOT_SendENCEvent((encoder >> 1)-1, incrementer);
320
  }
321
  // encoder number 16: datawheel
322
  else {
323
    // here you could handle additional encoders
324
  }
325
 
326
#else
327
 
328
  // encoder number 0: Jogwheel
329
  if( encoder == 0 )
330
    LC_VPOT_SendJogWheelEvent(incrementer);
331
  // encoder number 1..8: VPOT
332
  else if( encoder < 9 )
333
    LC_VPOT_SendENCEvent(encoder-1, incrementer);
334
  else {
335
    // here you could handle additional encoders
336
  }
337
 
338
#endif
339
}
340
 
341
 
342
/////////////////////////////////////////////////////////////////////////////
343
// This hook is called when a pot has been moved
344
/////////////////////////////////////////////////////////////////////////////
345
void APP_AIN_NotifyChange(u32 pin, u32 pin_value)
346
{
347
#if MBSEQ_HARDWARE_OPTION == 0
348
  LC_MF_FaderEvent(pin, pin_value << 4); // convert 12bit to 16bit
349
#endif
350
}
351
 
352
 
353
/////////////////////////////////////////////////////////////////////////////
1485 tk 354
// This task is called periodically each mS to handle LC functions
730 tk 355
/////////////////////////////////////////////////////////////////////////////
1485 tk 356
static void TASK_Period_1mS(void *pvParameters)
730 tk 357
{
1485 tk 358
  u8 counter_20ms = 0;
1490 tk 359
  portTickType xLastExecutionTime;
730 tk 360
 
1490 tk 361
  // Initialise the xLastExecutionTime variable on task entry
362
  xLastExecutionTime = xTaskGetTickCount();
363
 
1485 tk 364
  while( 1 ) {
1490 tk 365
    vTaskDelayUntil(&xLastExecutionTime, 1 / portTICK_RATE_MS);
730 tk 366
 
1490 tk 367
    // skip delay gap if we had to wait for more than 5 ticks to avoid
368
    // unnecessary repeats until xLastExecutionTime reached xTaskGetTickCount() again
369
    portTickType xCurrentTickCount = xTaskGetTickCount();
370
    if( xLastExecutionTime < (xCurrentTickCount-5) )
371
      xLastExecutionTime = xCurrentTickCount;
372
 
1485 tk 373
    // toggle Status LED to as a sign of live
374
    MIOS32_BOARD_LED_Set(1, ~MIOS32_BOARD_LED_Get());
375
 
376
    // call the meter timer each 20 mS
377
    if( ++counter_20ms >= 20 ) {
378
      counter_20ms = 0;
379
      LC_METERS_Timer();
380
    }
381
 
382
    // handles the update requests for VPOT LEDrings
383
    LC_VPOT_LEDRing_CheckUpdates();
384
 
385
    // handles the update requests for meters
386
    LC_METERS_CheckUpdates();
387
 
388
    // handles the update requests for LEDs
389
    LC_DIO_LED_CheckUpdate();
390
  }
391
}
392
 
393
 
394
/////////////////////////////////////////////////////////////////////////////
395
// This low-prio task handles the LCD
396
/////////////////////////////////////////////////////////////////////////////
397
static void TASK_Period_1mS_LP(void *pvParameters)
398
{
399
  // init LCD
400
  LC_LCD_Init(0);
401
 
730 tk 402
  while( 1 ) {
1485 tk 403
    vTaskDelay(1 / portTICK_RATE_MS);
730 tk 404
 
1485 tk 405
    // call LCD screen handler
406
    LC_LCD_Update(0);
730 tk 407
  }
408
}
1490 tk 409
 
410
 
411
/////////////////////////////////////////////////////////////////////////////
412
// Installed via MIOS32_MIDI_DirectRxCallback_Init
413
/////////////////////////////////////////////////////////////////////////////
414
static s32 NOTIFY_MIDI_Rx(mios32_midi_port_t port, u8 midi_byte)
415
{
416
  // filter MIDI In port which controls the MIDI clock
417
  if( MIDI_ROUTER_MIDIClockInGet(port) == 1 ) {
418
   // SEQ_BPM_NotifyMIDIRx(midi_byte);
419
  }
420
 
421
  return 0; // no error, no filtering
422
}
423
 
424
/////////////////////////////////////////////////////////////////////////////
425
// Installed via MIOS32_MIDI_DirectTxCallback_Init
426
/////////////////////////////////////////////////////////////////////////////
427
static s32 NOTIFY_MIDI_Tx(mios32_midi_port_t port, mios32_midi_package_t package)
428
{
429
  return MIDI_PORT_NotifyMIDITx(port, package);
430
}
431
 
432
/////////////////////////////////////////////////////////////////////////////
433
// Installed via MIOS32_MIDI_TimeoutCallback_Init
434
/////////////////////////////////////////////////////////////////////////////
435
static s32 NOTIFY_MIDI_TimeOut(mios32_midi_port_t port)
436
{
437
  // forward to SysEx parser
438
  LC_SYSEX_TimeOut(port);
439
 
440
  // print message on screen
441
  //SCS_Msg(SCS_MSG_L, 2000, "MIDI Protocol", "TIMEOUT !!!");
442
 
443
  return 0;
444
}