Subversion Repositories svn.mios32

Rev

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

Rev Author Line No. Line
1298 tk 1
// $Id: app.cpp 1408 2012-01-22 23:24:13Z tk $
2
/*
3
 * MIDIbox CV V2
4
 *
5
 * ==========================================================================
6
 *
7
 *  Copyright (C) 2011 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 <aout.h>
1334 tk 20
#include "tasks.h"
1298 tk 21
#include "app.h"
1334 tk 22
#include "MbCvEnvironment.h"
1298 tk 23
 
1334 tk 24
#include <file.h>
25
 
26
// include source of the SCS
27
#include <scs.h>
28
#include "scs_config.h"
29
 
30
#include <seq_bpm.h>
31
#include <seq_midi_out.h>
32
 
33
// quick&dirty to simplify re-use of C modules without changing header files
34
extern "C" {
1298 tk 35
#include "mbcv_sysex.h"
36
#include "mbcv_patch.h"
1299 tk 37
#include "mbcv_map.h"
1298 tk 38
#include "mbcv_router.h"
39
#include "mbcv_port.h"
40
 
41
#include "mbcv_file.h"
42
#include "mbcv_file_p.h"
43
 
44
#include "terminal.h"
45
#include "midimon.h"
46
 
47
#include "uip_task.h"
48
#include "osc_client.h"
1334 tk 49
}
1298 tk 50
 
51
/////////////////////////////////////////////////////////////////////////////
1334 tk 52
// for optional debugging messages via DEBUG_MSG (defined in mios32_config.h)
53
// should be at least 1 for sending error messages
1298 tk 54
/////////////////////////////////////////////////////////////////////////////
1334 tk 55
#define DEBUG_VERBOSE_LEVEL 2
1298 tk 56
 
1334 tk 57
// measure performance with the stopwatch
1394 tk 58
//#define STOPWATCH_PERFORMANCE_MEASURING 2
1401 tk 59
#define STOPWATCH_PERFORMANCE_MEASURING 0
1298 tk 60
 
61
 
62
/////////////////////////////////////////////////////////////////////////////
63
// local variables
64
/////////////////////////////////////////////////////////////////////////////
65
static u8 hw_enabled;
66
 
1334 tk 67
static u32 ms_counter;
1298 tk 68
 
1334 tk 69
static u32 stopwatch_value;
70
static u32 stopwatch_value_max;
71
static u32 stopwatch_value_accumulated;
1298 tk 72
 
1334 tk 73
static u32 cv_se_speed_factor;
1298 tk 74
 
1334 tk 75
/////////////////////////////////////////////////////////////////////////////
76
// C++ objects
77
/////////////////////////////////////////////////////////////////////////////
78
MbCvEnvironment mbCvEnvironment;
1298 tk 79
 
80
 
81
/////////////////////////////////////////////////////////////////////////////
82
// Local prototypes
83
/////////////////////////////////////////////////////////////////////////////
84
static void APP_Periodic_100uS(void);
1334 tk 85
extern void CV_TIMER_SE_Update(void);
1298 tk 86
static s32 NOTIFY_MIDI_Rx(mios32_midi_port_t port, u8 byte);
1299 tk 87
static s32 NOTIFY_MIDI_Tx(mios32_midi_port_t port, mios32_midi_package_t package);
88
static s32 NOTIFY_MIDI_TimeOut(mios32_midi_port_t port);
1298 tk 89
 
90
 
91
 
92
/////////////////////////////////////////////////////////////////////////////
1334 tk 93
// returns pointer to MbCv objects
94
/////////////////////////////////////////////////////////////////////////////
95
MbCvEnvironment *APP_GetEnv()
96
{
97
  return &mbCvEnvironment;
98
}
99
 
100
 
101
/////////////////////////////////////////////////////////////////////////////
1298 tk 102
// This hook is called after startup to initialize the application
103
/////////////////////////////////////////////////////////////////////////////
1334 tk 104
extern "C" void APP_Init(void)
1298 tk 105
{
106
  // initialize all LEDs
107
  MIOS32_BOARD_LED_Init(0xffffffff);
108
 
109
  // hardware will be enabled once configuration has been loaded from SD Card
110
  // (resp. no SD Card is available)
111
  hw_enabled = 0;
112
 
1334 tk 113
  // init Stopwatch
114
  APP_StopwatchInit();
115
 
1298 tk 116
  // initialize all J10 pins as inputs with internal Pull-Up
117
  int pin;
118
  for(pin=0; pin<8; ++pin)
119
    MIOS32_BOARD_J10_PinInit(pin, MIOS32_BOARD_PIN_MODE_INPUT_PU);
120
 
121
 
122
  // install SysEx callback
123
  MIOS32_MIDI_SysExCallback_Init(APP_SYSEX_Parser);
124
 
1299 tk 125
  // install MIDI Rx/Tx callback functions
126
  MIOS32_MIDI_DirectRxCallback_Init(&NOTIFY_MIDI_Rx);
127
  MIOS32_MIDI_DirectTxCallback_Init(&NOTIFY_MIDI_Tx);
1298 tk 128
 
1299 tk 129
  // install timeout callback function
130
  MIOS32_MIDI_TimeOutCallback_Init(&NOTIFY_MIDI_TimeOut);
1298 tk 131
 
132
  // initialize AOUT module
133
  AOUT_Init(0);
134
 
135
  // configure interface (will be changed again once config file has been loaded from SD Card, or via SCS)
136
  aout_config_t config;
137
  config = AOUT_ConfigGet();
138
  config.if_type = AOUT_IF_MAX525;
139
  config.if_option = 0;
140
  config.num_channels = 8;
141
  config.chn_inverted = 0;
142
  AOUT_ConfigSet(config);
143
  AOUT_IF_Init(0);
144
 
1299 tk 145
  // initialize code modules
146
  MBCV_PORT_Init(0);
147
  MBCV_SYSEX_Init(0);
148
  MBCV_MAP_Init(0);
149
  MBCV_ROUTER_Init(0);
150
  MBCV_PATCH_Init(0);
151
  UIP_TASK_Init(0);
152
  SCS_Init(0);
153
  SCS_CONFIG_Init(0);
154
  TERMINAL_Init(0);
155
  MIDIMON_Init(0);
156
  MBCV_FILE_Init(0);
157
  SEQ_MIDI_OUT_Init(0);
158
 
1298 tk 159
  // install timer function which is called each 100 uS
160
  MIOS32_TIMER_Init(1, 100, APP_Periodic_100uS, MIOS32_IRQ_PRIO_MID);
161
 
1334 tk 162
  // initialize MbCvEnvironment
1347 tk 163
  cv_se_speed_factor = 10;
1334 tk 164
  mbCvEnvironment.updateSpeedFactorSet(cv_se_speed_factor);
1298 tk 165
 
1334 tk 166
  // initialize tasks
167
  TASKS_Init(0);
168
 
169
  // start timer
170
  // TODO: increase  once performance has been evaluated
171
  MIOS32_TIMER_Init(2, 2000 / cv_se_speed_factor, CV_TIMER_SE_Update, MIOS32_IRQ_PRIO_MID);
1298 tk 172
}
173
 
174
 
175
/////////////////////////////////////////////////////////////////////////////
176
// This task is running endless in background
177
/////////////////////////////////////////////////////////////////////////////
1334 tk 178
extern "C" void APP_Background(void)
1298 tk 179
{
180
  // endless loop
181
  while( 1 ) {
182
    // toggle the state of all LEDs (allows to measure the execution speed with a scope)
183
    MIOS32_BOARD_LED_Set(0xffffffff, ~MIOS32_BOARD_LED_Get());
184
  }
185
}
186
 
187
 
188
/////////////////////////////////////////////////////////////////////////////
189
// This hook is called when a MIDI package has been received
190
/////////////////////////////////////////////////////////////////////////////
1334 tk 191
extern "C" void APP_MIDI_NotifyPackage(mios32_midi_port_t port, mios32_midi_package_t midi_package)
1298 tk 192
{
1299 tk 193
  // -> CV MIDI handler
1334 tk 194
  mbCvEnvironment.midiReceive(port, midi_package);
1299 tk 195
 
1298 tk 196
  // -> MIDI Router
197
  MBCV_ROUTER_Receive(port, midi_package);
198
 
1299 tk 199
  // -> MIDI Port Handler (used for MIDI monitor function)
200
  MBCV_PORT_NotifyMIDIRx(port, midi_package);
201
 
1298 tk 202
  // forward to MIDI Monitor
203
  // SysEx messages have to be filtered for USB0 and UART0 to avoid data corruption
204
  // (the SysEx stream would interfere with monitor messages)
205
  u8 filter_sysex_message = (port == USB0) || (port == UART0);
206
  MIDIMON_Receive(port, midi_package, ms_counter, filter_sysex_message);
207
}
208
 
209
/////////////////////////////////////////////////////////////////////////////
210
// This function parses an incoming sysex stream for MIOS32 commands
211
/////////////////////////////////////////////////////////////////////////////
1334 tk 212
extern "C" s32 APP_SYSEX_Parser(mios32_midi_port_t port, u8 midi_in)
1298 tk 213
{
214
  // -> MBCV
215
  MBCV_SYSEX_Parser(port, midi_in);
216
 
217
  // -> MIDI Router
218
  MBCV_ROUTER_ReceiveSysEx(port, midi_in);
219
 
220
  return 0; // no error
221
}
222
 
223
/////////////////////////////////////////////////////////////////////////////
224
// This hook is called before the shift register chain is scanned
225
/////////////////////////////////////////////////////////////////////////////
1334 tk 226
extern "C" void APP_SRIO_ServicePrepare(void)
1298 tk 227
{
228
  // pass current pin state of J10
229
  // only available for LPC17xx, all others (like STM32) default to SRIO
230
  SCS_AllPinsSet(0xff00 | MIOS32_BOARD_J10_Get());
231
 
232
  // update encoders/buttons of SCS
233
  SCS_EncButtonUpdate_Tick();
234
}
235
 
236
 
237
/////////////////////////////////////////////////////////////////////////////
238
// This hook is called after the shift register chain has been scanned
239
/////////////////////////////////////////////////////////////////////////////
1334 tk 240
extern "C" void APP_SRIO_ServiceFinish(void)
1298 tk 241
{
242
}
243
 
244
 
245
/////////////////////////////////////////////////////////////////////////////
246
// This hook is called when a button has been toggled
247
// pin_value is 1 when button released, and 0 when button pressed
248
/////////////////////////////////////////////////////////////////////////////
1334 tk 249
extern "C" void APP_DIN_NotifyToggle(u32 pin, u32 pin_value)
1298 tk 250
{
251
}
252
 
253
 
254
/////////////////////////////////////////////////////////////////////////////
255
// This hook is called when an encoder has been moved
256
// incrementer is positive when encoder has been turned clockwise, else
257
// it is negative
258
/////////////////////////////////////////////////////////////////////////////
1334 tk 259
extern "C" void APP_ENC_NotifyChange(u32 encoder, s32 incrementer)
1298 tk 260
{
261
  // pass encoder event to SCS handler
262
  if( encoder == SCS_ENC_MENU_ID )
263
    SCS_ENC_MENU_NotifyChange(incrementer);
264
}
265
 
266
 
267
/////////////////////////////////////////////////////////////////////////////
268
// This hook is called when a pot has been moved
269
/////////////////////////////////////////////////////////////////////////////
1334 tk 270
extern "C" void APP_AIN_NotifyChange(u32 pin, u32 pin_value)
1298 tk 271
{
272
}
273
 
274
 
275
 
1334 tk 276
/////////////////////////////////////////////////////////////////////////////
277
// This timer interrupt periodically calls the sound engine update
278
/////////////////////////////////////////////////////////////////////////////
279
extern void CV_TIMER_SE_Update(void)
280
{
281
  if( !hw_enabled )
282
    return;
1298 tk 283
 
1334 tk 284
#if STOPWATCH_PERFORMANCE_MEASURING >= 1
285
  APP_StopwatchReset();
286
#endif
287
 
288
  if( !mbCvEnvironment.tick() )
289
    return; // no update required
290
 
291
#if STOPWATCH_PERFORMANCE_MEASURING == 1
292
  APP_StopwatchCapture();
293
#endif
294
 
295
  // update AOUTs
296
  MBCV_MAP_Update();
297
 
298
#if STOPWATCH_PERFORMANCE_MEASURING == 2
299
  APP_StopwatchCapture();
300
#endif
301
}
302
 
303
 
304
 
305
 
1298 tk 306
/////////////////////////////////////////////////////////////////////////////
307
// This task handles the control surface
308
/////////////////////////////////////////////////////////////////////////////
1334 tk 309
void APP_TASK_Period_1mS_LP(void)
1298 tk 310
{
1334 tk 311
  static u16 performance_print_ctr = 0;
1298 tk 312
 
1334 tk 313
  // call SCS handler
314
  SCS_Tick();
1298 tk 315
 
1334 tk 316
  // MIDI In/Out monitor
317
  MBCV_PORT_Period1mS();
1298 tk 318
 
1334 tk 319
  // output and reset current stopwatch max value each second
320
  if( ++performance_print_ctr >= 1000 ) {
321
    performance_print_ctr = 0;
322
 
323
    MUTEX_MIDIOUT_TAKE;
324
    MIOS32_IRQ_Disable();
325
    u32 max_value = stopwatch_value_max;
326
    stopwatch_value_max = 0;
327
    u32 acc_value = stopwatch_value_accumulated;
328
    stopwatch_value_accumulated = 0;
329
    MIOS32_IRQ_Enable();
330
#if DEBUG_VERBOSE_LEVEL >= 2
331
    if( acc_value || max_value )
332
      DEBUG_MSG("%d uS (max: %d uS)\n", acc_value / (1000000 / (2000/cv_se_speed_factor)), max_value);
333
#endif
334
    MUTEX_MIDIOUT_GIVE;
1298 tk 335
  }
336
 
337
}
338
 
339
 
340
/////////////////////////////////////////////////////////////////////////////
341
// This task handles the SD Card
342
/////////////////////////////////////////////////////////////////////////////
1334 tk 343
void APP_TASK_Period_1mS_SD(void)
1298 tk 344
{
1334 tk 345
  static u16 sdcard_check_ctr = 0;
1298 tk 346
 
1334 tk 347
  // each second: check if SD Card (still) available
348
  if( ++sdcard_check_ctr >= 1000 ) {
349
    sdcard_check_ctr = 0;
1298 tk 350
 
1334 tk 351
    MUTEX_SDCARD_TAKE;
352
    s32 status = FILE_CheckSDCard();
1298 tk 353
 
1334 tk 354
    hw_enabled = 1; // enable hardware after first read...
1298 tk 355
 
1334 tk 356
    if( status == 1 ) {
357
      DEBUG_MSG("SD Card connected: %s\n", FILE_VolumeLabel());
358
      // load all file infos
359
      MBCV_FILE_LoadAllFiles(1); // including HW info
360
    } else if( status == 2 ) {
361
      DEBUG_MSG("SD Card disconnected\n");
362
      // invalidate all file infos
363
      MBCV_FILE_UnloadAllFiles();
1298 tk 364
 
1334 tk 365
      // change status
366
      MBCV_FILE_StatusMsgSet("No SD Card");
367
    } else if( status == 3 ) {
368
      if( !FILE_SDCardAvailable() ) {
369
    DEBUG_MSG("SD Card not found\n");
1298 tk 370
    MBCV_FILE_StatusMsgSet("No SD Card");
1334 tk 371
      } else if( !FILE_VolumeAvailable() ) {
372
    DEBUG_MSG("ERROR: SD Card contains invalid FAT!\n");
373
    MBCV_FILE_StatusMsgSet("No FAT");
374
      } else {
375
    // check if patch file exists
376
    if( !MBCV_FILE_P_Valid() ) {
377
      // create new one
378
      DEBUG_MSG("Creating initial DEFAULT.CV2 file\n");
379
 
380
      if( (status=MBCV_FILE_P_Write("DEFAULT")) < 0 ) {
381
        DEBUG_MSG("Failed to create file! (status: %d)\n", status);
1298 tk 382
      }
383
    }
384
 
1334 tk 385
    // disable status message and print patch
386
    MBCV_FILE_StatusMsgSet(NULL);
1298 tk 387
      }
388
    }
1334 tk 389
 
390
    MUTEX_SDCARD_GIVE;
1298 tk 391
  }
392
}
393
 
394
 
395
/////////////////////////////////////////////////////////////////////////////
396
// This task is called periodically each mS to handle AOUTs
397
/////////////////////////////////////////////////////////////////////////////
1334 tk 398
void APP_TASK_Period_1mS(void)
1298 tk 399
{
1334 tk 400
  if( hw_enabled ) {
401
    // nothing to do... yet
1298 tk 402
  }
403
}
404
 
405
 
406
/////////////////////////////////////////////////////////////////////////////
407
// This timer function is periodically called each 100 uS
408
/////////////////////////////////////////////////////////////////////////////
409
static void APP_Periodic_100uS(void)
410
{
411
  static u8 pre_ctr = 0;
412
 
413
  // increment the microsecond counter each 10th tick
414
  if( ++pre_ctr >= 10 ) {
415
    pre_ctr = 0;
416
    ++ms_counter;
417
  }
418
 
419
  // here we could do some additional high-prio jobs
420
  // (e.g. PWM LEDs)
421
}
422
 
423
/////////////////////////////////////////////////////////////////////////////
424
// Installed via MIOS32_MIDI_DirectRxCallback_Init
425
/////////////////////////////////////////////////////////////////////////////
426
static s32 NOTIFY_MIDI_Rx(mios32_midi_port_t port, u8 midi_byte)
427
{
1299 tk 428
  // filter MIDI In port which controls the MIDI clock
429
  if( MBCV_ROUTER_MIDIClockInGet(port) == 1 )
430
    SEQ_BPM_NotifyMIDIRx(midi_byte);
1298 tk 431
 
1408 tk 432
  // TODO: better port filtering!
433
  if( port < USB1 || port >= UART0 ) {
434
    if( midi_byte >= 0xf8 ) {
435
      mbCvEnvironment.midiReceiveRealTimeEvent(port, midi_byte);
436
    }
437
  }
438
 
1298 tk 439
  return 0; // no error, no filtering
440
}
441
 
1299 tk 442
/////////////////////////////////////////////////////////////////////////////
443
// Installed via MIOS32_MIDI_DirectTxCallback_Init
444
/////////////////////////////////////////////////////////////////////////////
445
static s32 NOTIFY_MIDI_Tx(mios32_midi_port_t port, mios32_midi_package_t package)
446
{
447
  return MBCV_PORT_NotifyMIDITx(port, package);
448
}
1298 tk 449
 
450
/////////////////////////////////////////////////////////////////////////////
1299 tk 451
// Installed via MIOS32_MIDI_TimeoutCallback_Init
452
/////////////////////////////////////////////////////////////////////////////
453
static s32 NOTIFY_MIDI_TimeOut(mios32_midi_port_t port)
454
{  
455
  // forward to SysEx parser
456
  MBCV_SYSEX_TimeOut(port);
457
 
458
  // print message on screen
459
  SCS_Msg(SCS_MSG_L, 2000, "MIDI Protocol", "TIMEOUT !!!");
460
 
461
  return 0;
462
}
463
 
464
 
465
/////////////////////////////////////////////////////////////////////////////
1334 tk 466
// For performance Measurements
1298 tk 467
/////////////////////////////////////////////////////////////////////////////
1334 tk 468
s32 APP_StopwatchInit(void)
1298 tk 469
{
1334 tk 470
  stopwatch_value = 0;
471
  stopwatch_value_max = 0;
472
  stopwatch_value_accumulated = 0;
473
  return MIOS32_STOPWATCH_Init(1); // 1 uS resolution
1298 tk 474
}
475
 
1334 tk 476
s32 APP_StopwatchReset(void)
1298 tk 477
{
1334 tk 478
  return MIOS32_STOPWATCH_Reset();
1298 tk 479
}
480
 
1334 tk 481
s32 APP_StopwatchCapture(void)
1298 tk 482
{
1334 tk 483
  u32 value = MIOS32_STOPWATCH_ValueGet();
484
  MIOS32_IRQ_Disable();
485
  stopwatch_value = value;
486
  if( value > stopwatch_value_max )
487
    stopwatch_value_max = value;
488
  stopwatch_value_accumulated += value;
489
  MIOS32_IRQ_Enable();
1298 tk 490
 
491
  return 0; // no error
492
}