Subversion Repositories svn.mios32

Rev

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

Rev Author Line No. Line
61 tk 1
// $Id: app.c 1421 2012-02-11 23:44:23Z tk $
2
/*
3
 * MIDIbox SEQ V4
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>
1320 tk 19
#include <string.h>
61 tk 20
 
190 tk 21
#include <seq_midi_out.h>
22
#include <seq_bpm.h>
1318 tk 23
 
24
#ifndef MBSEQV4L
524 tk 25
#include <blm.h>
1318 tk 26
#else
27
#include <blm_cheapo.h>
28
#endif
507 tk 29
#include <blm_x.h>
190 tk 30
 
141 tk 31
#include "tasks.h"
32
 
61 tk 33
#include "app.h"
868 tk 34
#include "seq_lcd.h"
61 tk 35
 
492 tk 36
#include "seq_hwcfg.h"
37
 
141 tk 38
#include "seq_core.h"
184 tk 39
#include "seq_led.h"
1345 tk 40
#include "seq_tpd.h"
141 tk 41
#include "seq_ui.h"
184 tk 42
#include "seq_pattern.h"
690 tk 43
#include "seq_mixer.h"
44
#include "seq_song.h"
45
#include "seq_label.h"
868 tk 46
#include "seq_cc_labels.h"
186 tk 47
#include "seq_midply.h"
48
 
1318 tk 49
 
1083 tk 50
#include "seq_cv.h"
285 tk 51
#include "seq_midi_port.h"
182 tk 52
#include "seq_midi_in.h"
690 tk 53
#include "seq_midi_router.h"
625 tk 54
#include "seq_midi_sysex.h"
1020 tk 55
#include "seq_blm.h"
944 tk 56
#include "seq_terminal.h"
57
#include "seq_statistics.h"
134 tk 58
 
1261 tk 59
#include "file.h"
248 tk 60
#include "seq_file.h"
61
#include "seq_file_b.h"
599 tk 62
#include "seq_file_g.h"
352 tk 63
#include "seq_file_c.h"
1052 tk 64
#include "seq_file_gc.h"
492 tk 65
#include "seq_file_hw.h"
1318 tk 66
#include "seq_file_m.h"
67
#include "seq_file_s.h"
68
#include "seq_file_bm.h"
186 tk 69
 
1318 tk 70
 
61 tk 71
/////////////////////////////////////////////////////////////////////////////
343 tk 72
// for optional debugging messages via DEBUG_MSG (defined in mios32_config.h)
308 tk 73
/////////////////////////////////////////////////////////////////////////////
327 tk 74
#define DEBUG_VERBOSE_LEVEL 0
308 tk 75
 
76
 
77
/////////////////////////////////////////////////////////////////////////////
159 tk 78
// Local prototypes
79
/////////////////////////////////////////////////////////////////////////////
281 tk 80
static s32 NOTIFY_MIDI_Rx(mios32_midi_port_t port, u8 byte);
81
static s32 NOTIFY_MIDI_Tx(mios32_midi_port_t port, mios32_midi_package_t package);
529 tk 82
static s32 NOTIFY_MIDI_TimeOut(mios32_midi_port_t port);
159 tk 83
 
84
 
85
/////////////////////////////////////////////////////////////////////////////
61 tk 86
// This hook is called after startup to initialize the application
87
/////////////////////////////////////////////////////////////////////////////
88
void APP_Init(void)
89
{
90
  // initialize all LEDs
91
  MIOS32_BOARD_LED_Init(0xffffffff);
92
 
1323 tk 93
#ifdef MBSEQV4L
94
  // MBSEQV4L: set default port to 0xc0: multiple outputs
95
  MIOS32_MIDI_DefaultPortSet(0xc0);
96
#endif
97
 
492 tk 98
  // initialize hardware soft-config
99
  SEQ_HWCFG_Init(0);
61 tk 100
 
1318 tk 101
#ifndef MBSEQV4L
821 tk 102
  // initialize CLCDs
103
  SEQ_LCD_Init(0);
1318 tk 104
#endif
134 tk 105
 
524 tk 106
  // init BLMs
1318 tk 107
#ifndef MBSEQV4L
524 tk 108
  BLM_Init(0);
1318 tk 109
#else
110
  BLM_CHEAPO_Init(0);
111
#endif
464 tk 112
  BLM_X_Init();
134 tk 113
 
1083 tk 114
  // initialize CV
115
  SEQ_CV_Init(0);
507 tk 116
 
182 tk 117
  // initialize MIDI handlers
285 tk 118
  SEQ_MIDI_PORT_Init(0);
182 tk 119
  SEQ_MIDI_IN_Init(0);
625 tk 120
  SEQ_MIDI_SYSEX_Init(0);
1020 tk 121
  SEQ_BLM_Init(0);
190 tk 122
  SEQ_MIDI_OUT_Init(0);
406 tk 123
  SEQ_MIDI_ROUTER_Init(0);
944 tk 124
  SEQ_TERMINAL_Init(0);
182 tk 125
 
280 tk 126
  // init mixer page
127
  SEQ_MIXER_Init(0);
128
 
141 tk 129
  // init sequencer core
130
  SEQ_CORE_Init(0);
131
 
132
  // init user interface
1318 tk 133
#ifndef MBSEQV4L
472 tk 134
  SEQ_LABEL_Init(0);
718 tk 135
  SEQ_CC_LABELS_Init(0);
1336 tk 136
#endif
141 tk 137
  SEQ_LED_Init(0);
138
  SEQ_UI_Init(0);
139
 
248 tk 140
  // initial load of filesystem
352 tk 141
  SEQ_FILE_Init(0);
248 tk 142
 
141 tk 143
  // start tasks (differs between MIOS32 and MacOS)
144
  TASKS_Init(0);
159 tk 145
 
146
  // install MIDI Rx/Tx callback functions
868 tk 147
  MIOS32_MIDI_DirectRxCallback_Init(&NOTIFY_MIDI_Rx);
148
  MIOS32_MIDI_DirectTxCallback_Init(&NOTIFY_MIDI_Tx);
529 tk 149
 
1311 tk 150
  // install SysEx callback
151
  MIOS32_MIDI_SysExCallback_Init(APP_SYSEX_Parser);
152
 
529 tk 153
  // install timeout callback function
868 tk 154
  MIOS32_MIDI_TimeOutCallback_Init(&NOTIFY_MIDI_TimeOut);
61 tk 155
}
156
 
157
 
158
/////////////////////////////////////////////////////////////////////////////
159
// This task is running endless in background
160
/////////////////////////////////////////////////////////////////////////////
141 tk 161
void APP_Background(void)
162
{
163
  // toggle the state of all LEDs (allows to measure the execution speed with a scope)
184 tk 164
#if 0
141 tk 165
  MIOS32_BOARD_LED_Set(0xffffffff, ~MIOS32_BOARD_LED_Get());
159 tk 166
#endif
702 tk 167
 
168
  // for idle time measurements
944 tk 169
  SEQ_STATISTICS_Idle();
141 tk 170
}
171
 
172
 
61 tk 173
/////////////////////////////////////////////////////////////////////////////
674 tk 174
// This hook is called when a MIDI package has been received
61 tk 175
/////////////////////////////////////////////////////////////////////////////
674 tk 176
void APP_MIDI_NotifyPackage(mios32_midi_port_t port, mios32_midi_package_t midi_package)
141 tk 177
{
674 tk 178
  if( midi_package.evnt0 >= 0xf8 ) {
653 tk 179
    // disabled: MIDI Clock always sent from sequencer, even in slave mode
180
#if 0
652 tk 181
    // forward to router
182
    mios32_midi_package_t p;
183
    p.ALL = 0;
184
    p.type = 0x5; // Single-byte system common message
185
    p.evnt0 = sysex_byte;
186
    SEQ_MIDI_ROUTER_Receive(port, p);
653 tk 187
#endif
652 tk 188
  } else {
1020 tk 189
    if( port == seq_blm_port ) {
190
      SEQ_BLM_MIDI_Receive(port, midi_package);
1319 tk 191
    } else {
784 tk 192
      // returns > 0 if byte has been used for remote function
193
      if( SEQ_UI_REMOTE_MIDI_Receive(port, midi_package) < 1 ) {
194
    // forward to router
195
    SEQ_MIDI_ROUTER_Receive(port, midi_package);
196
    // forward to transposer/arpeggiator/CC parser/etc...
197
    SEQ_MIDI_IN_Receive(port, midi_package);
198
      }
674 tk 199
    }
652 tk 200
  }
759 tk 201
 
202
  // forward to port handler (used for MIDI monitor function)
203
  SEQ_MIDI_PORT_NotifyMIDIRx(port, midi_package);
141 tk 204
}
61 tk 205
 
206
 
207
/////////////////////////////////////////////////////////////////////////////
1311 tk 208
// This function parses an incoming sysex stream for MIOS32 commands
209
/////////////////////////////////////////////////////////////////////////////
210
s32 APP_SYSEX_Parser(mios32_midi_port_t port, u8 midi_in)
211
{
212
  // forward event to MIDI router
213
  SEQ_MIDI_ROUTER_ReceiveSysEx(port, midi_in);
214
 
215
  // forward event to BLM as well
216
  SEQ_BLM_SYSEX_Parser(port, midi_in);
217
 
218
  // forward to common SysEx handler
219
  SEQ_MIDI_SYSEX_Parser(port, midi_in);
220
 
221
  return 0; // no error
222
}
223
 
224
 
225
 
226
/////////////////////////////////////////////////////////////////////////////
61 tk 227
// This hook is called before the shift register chain is scanned
228
/////////////////////////////////////////////////////////////////////////////
141 tk 229
void APP_SRIO_ServicePrepare(void)
230
{
1341 tk 231
  static u8 led_digit_ctr = 0;
1345 tk 232
  if( ++led_digit_ctr >= 7 )
1341 tk 233
    led_digit_ctr = 0;
1336 tk 234
 
1318 tk 235
#ifndef MBSEQV4L
524 tk 236
  if( seq_hwcfg_blm.enabled ) {
237
    // prepare DOUT registers of BLM to drive the column
238
    BLM_PrepareCol();
239
  }
1318 tk 240
#else
241
  BLM_CHEAPO_PrepareCol();
242
#endif
524 tk 243
 
514 tk 244
  if( seq_hwcfg_blm8x8.enabled ) {
513 tk 245
    // prepare DOUT registers of 8x8 BLM to drive the row
246
    BLM_X_PrepareRow();
247
  }
1336 tk 248
 
1403 tk 249
  // TK: using MIOS32_DOUT_SRSet/PinSet instead of SEQ_LED_SRSet/PinSet to ensure compatibility with MBSEQV4L
1336 tk 250
  if( seq_hwcfg_bpm_digits.enabled ) {
251
    // invert for common anodes
252
    u8 inversion_mask = (seq_hwcfg_bpm_digits.enabled == 2) ? 0xff : 0x00;
1345 tk 253
    u8 common_enable = (seq_hwcfg_bpm_digits.enabled == 2) ? 1 : 0;
1336 tk 254
 
1421 tk 255
    float bpm = SEQ_BPM_EffectiveGet();
1341 tk 256
    if( led_digit_ctr == 0 ) {
1345 tk 257
      u8 sr_value = SEQ_LED_DigitPatternGet(((int)(bpm*10)) % 10);
1403 tk 258
      MIOS32_DOUT_SRSet(seq_hwcfg_bpm_digits.segments_sr - 1, sr_value ^ inversion_mask);
259
      MIOS32_DOUT_PinSet(seq_hwcfg_bpm_digits.common1_pin, common_enable);
260
      MIOS32_DOUT_PinSet(seq_hwcfg_bpm_digits.common2_pin, !common_enable);
261
      MIOS32_DOUT_PinSet(seq_hwcfg_bpm_digits.common3_pin, !common_enable);
262
      MIOS32_DOUT_PinSet(seq_hwcfg_bpm_digits.common4_pin, !common_enable);
1341 tk 263
    } else if( led_digit_ctr == 1 ) {
1345 tk 264
      u8 sr_value = SEQ_LED_DigitPatternGet((int)bpm % 10) | 0x80; // +dot
1403 tk 265
      MIOS32_DOUT_SRSet(seq_hwcfg_bpm_digits.segments_sr - 1, sr_value ^ inversion_mask);
266
      MIOS32_DOUT_PinSet(seq_hwcfg_bpm_digits.common1_pin, !common_enable);
267
      MIOS32_DOUT_PinSet(seq_hwcfg_bpm_digits.common2_pin, common_enable);
268
      MIOS32_DOUT_PinSet(seq_hwcfg_bpm_digits.common3_pin, !common_enable);
269
      MIOS32_DOUT_PinSet(seq_hwcfg_bpm_digits.common4_pin, !common_enable);
1341 tk 270
    } else if( led_digit_ctr == 2 ) {
1345 tk 271
      u8 sr_value = SEQ_LED_DigitPatternGet(((int)bpm / 10) % 10);
1403 tk 272
      MIOS32_DOUT_SRSet(seq_hwcfg_bpm_digits.segments_sr - 1, sr_value ^ inversion_mask);
273
      MIOS32_DOUT_PinSet(seq_hwcfg_bpm_digits.common1_pin, !common_enable);
274
      MIOS32_DOUT_PinSet(seq_hwcfg_bpm_digits.common2_pin, !common_enable);
275
      MIOS32_DOUT_PinSet(seq_hwcfg_bpm_digits.common3_pin, common_enable);
276
      MIOS32_DOUT_PinSet(seq_hwcfg_bpm_digits.common4_pin, !common_enable);
1341 tk 277
    } else if( led_digit_ctr == 3 ) {
1345 tk 278
      u8 sr_value = SEQ_LED_DigitPatternGet(((int)bpm / 100) % 10);
1403 tk 279
      MIOS32_DOUT_SRSet(seq_hwcfg_bpm_digits.segments_sr - 1, sr_value ^ inversion_mask);
280
      MIOS32_DOUT_PinSet(seq_hwcfg_bpm_digits.common1_pin, !common_enable);
281
      MIOS32_DOUT_PinSet(seq_hwcfg_bpm_digits.common2_pin, !common_enable);
282
      MIOS32_DOUT_PinSet(seq_hwcfg_bpm_digits.common3_pin, !common_enable);
283
      MIOS32_DOUT_PinSet(seq_hwcfg_bpm_digits.common4_pin, common_enable);
1336 tk 284
    }
1345 tk 285
    else { // not displaying bpm digit in this cycle, disable common pins
1403 tk 286
      MIOS32_DOUT_PinSet(seq_hwcfg_bpm_digits.common1_pin, !common_enable);
287
      MIOS32_DOUT_PinSet(seq_hwcfg_bpm_digits.common2_pin, !common_enable);
288
      MIOS32_DOUT_PinSet(seq_hwcfg_bpm_digits.common3_pin, !common_enable);
289
      MIOS32_DOUT_PinSet(seq_hwcfg_bpm_digits.common4_pin, !common_enable);
1345 tk 290
    }
1336 tk 291
  }
1341 tk 292
 
293
  if( seq_hwcfg_step_digits.enabled ) {
294
    // invert for common anodes
295
    u8 inversion_mask = (seq_hwcfg_step_digits.enabled == 2) ? 0xff : 0x00;
1345 tk 296
    u8 common_enable = (seq_hwcfg_step_digits.enabled == 2) ? 1 : 0;
297
 
298
    int step = (int)(SEQ_BPM_IsRunning() ? seq_core_trk[SEQ_UI_VisibleTrackGet()].step : ui_selected_step) + 1;
299
    if( led_digit_ctr == 4 ) {
1341 tk 300
      u8 sr_value = SEQ_LED_DigitPatternGet(step % 10);
1403 tk 301
      MIOS32_DOUT_SRSet(seq_hwcfg_step_digits.segments_sr - 1, sr_value ^ inversion_mask);
302
      MIOS32_DOUT_PinSet(seq_hwcfg_step_digits.common1_pin, common_enable);
303
      MIOS32_DOUT_PinSet(seq_hwcfg_step_digits.common2_pin, !common_enable);
304
      MIOS32_DOUT_PinSet(seq_hwcfg_step_digits.common3_pin, !common_enable);
1345 tk 305
    } else if( led_digit_ctr == 5 ) {
1341 tk 306
      u8 sr_value = SEQ_LED_DigitPatternGet((step / 10) % 10);
1403 tk 307
      MIOS32_DOUT_SRSet(seq_hwcfg_step_digits.segments_sr - 1, sr_value ^ inversion_mask);
308
      MIOS32_DOUT_PinSet(seq_hwcfg_step_digits.common1_pin, !common_enable);
309
      MIOS32_DOUT_PinSet(seq_hwcfg_step_digits.common2_pin, common_enable);
310
      MIOS32_DOUT_PinSet(seq_hwcfg_step_digits.common3_pin, !common_enable);
1345 tk 311
    } else if( led_digit_ctr == 6 ) {
1341 tk 312
      u8 sr_value = SEQ_LED_DigitPatternGet((step / 100) % 10);
1403 tk 313
      MIOS32_DOUT_SRSet(seq_hwcfg_step_digits.segments_sr - 1, sr_value ^ inversion_mask);
314
      MIOS32_DOUT_PinSet(seq_hwcfg_step_digits.common1_pin, !common_enable);
315
      MIOS32_DOUT_PinSet(seq_hwcfg_step_digits.common2_pin, !common_enable);
316
      MIOS32_DOUT_PinSet(seq_hwcfg_step_digits.common3_pin, common_enable);
1341 tk 317
    }
1345 tk 318
    else { // not displaying step digit in this cycle, disable common pins
1403 tk 319
      MIOS32_DOUT_PinSet(seq_hwcfg_step_digits.common1_pin, !common_enable);
320
      MIOS32_DOUT_PinSet(seq_hwcfg_step_digits.common2_pin, !common_enable);
321
      MIOS32_DOUT_PinSet(seq_hwcfg_step_digits.common3_pin, !common_enable);
1345 tk 322
    }    
1341 tk 323
  }
1345 tk 324
 
325
  if( seq_hwcfg_tpd.enabled ) {
326
     SEQ_TPD_LED_Update();    
327
  }
141 tk 328
}
61 tk 329
 
330
 
331
/////////////////////////////////////////////////////////////////////////////
332
// This hook is called after the shift register chain has been scanned
333
/////////////////////////////////////////////////////////////////////////////
141 tk 334
void APP_SRIO_ServiceFinish(void)
335
{
1318 tk 336
#ifndef MBSEQV4L
524 tk 337
  if( seq_hwcfg_blm.enabled ) {
338
    // call the BL_GetRow function after scan is finished to capture the read DIN values
339
    BLM_GetRow();
340
  }
1318 tk 341
#else
342
  BLM_CHEAPO_GetRow();
343
#endif
524 tk 344
 
514 tk 345
  if( seq_hwcfg_blm8x8.enabled ) {
513 tk 346
    // call the BL_X_GetRow function after scan is finished to capture the read DIN values
347
    BLM_X_GetRow();
348
  }
141 tk 349
}
61 tk 350
 
351
 
352
/////////////////////////////////////////////////////////////////////////////
353
// This hook is called when a button has been toggled
354
// pin_value is 1 when button released, and 0 when button pressed
355
/////////////////////////////////////////////////////////////////////////////
141 tk 356
void APP_DIN_NotifyToggle(u32 pin, u32 pin_value)
357
{
308 tk 358
#if DEBUG_VERBOSE_LEVEL >= 1
359
  DEBUG_MSG("Pin %3d (SR%d:D%d) = %d\n", pin, (pin>>3)+1, pin&7, pin_value);
141 tk 360
#endif
61 tk 361
 
141 tk 362
  // forward to UI button handler
363
  SEQ_UI_Button_Handler(pin, pin_value);
364
}
61 tk 365
 
141 tk 366
 
61 tk 367
/////////////////////////////////////////////////////////////////////////////
524 tk 368
// This hook is called when a BLM button has been toggled
369
// (see also SEQ_TASK_Period1mS)
370
// pin_value is 1 when button released, and 0 when button pressed
371
/////////////////////////////////////////////////////////////////////////////
372
void APP_BLM_NotifyToggle(u32 pin, u32 pin_value)
373
{
1318 tk 374
#ifndef MBSEQV4L
524 tk 375
  u8 row = pin / 16;
376
  u8 pin_of_row = pin % 16;
377
#if DEBUG_VERBOSE_LEVEL >= 1
378
  DEBUG_MSG("BLM Pin %3d (Row%d:D%d) = %d\n", pin, row, pin_of_row, pin_value);
379
#endif
380
 
381
  // forward to UI BLM button handler
382
  SEQ_UI_BLM_Button_Handler(row, pin_of_row, pin_value);
1318 tk 383
#else
384
#if 0
385
  MIOS32_MIDI_SendDebugMessage("SR: %d  Pin:%d  Value:%d\n", (pin>>3)+1, pin & 7, pin_value);
386
#endif
387
 
388
  // forward to UI button handler
389
  SEQ_UI_Button_Handler(pin, pin_value);
390
#endif
524 tk 391
}
392
 
393
 
394
/////////////////////////////////////////////////////////////////////////////
464 tk 395
// This hook is called when a BLM_X button has been toggled
141 tk 396
// (see also SEQ_TASK_Period1mS)
397
// pin_value is 1 when button released, and 0 when button pressed
398
/////////////////////////////////////////////////////////////////////////////
464 tk 399
void APP_BLM_X_NotifyToggle(u32 pin, u32 pin_value)
141 tk 400
{
308 tk 401
#if DEBUG_VERBOSE_LEVEL >= 1
524 tk 402
  DEBUG_MSG("BLM8x8 Pin %3d (SR%d:D%d) = %d\n", pin, (pin>>3)+1, pin&7, pin_value);
141 tk 403
#endif
404
 
405
  // forward to UI button handler
406
  SEQ_UI_Button_Handler(pin + 128, pin_value);
407
}
408
 
409
 
410
/////////////////////////////////////////////////////////////////////////////
61 tk 411
// This hook is called when an encoder has been moved
412
// incrementer is positive when encoder has been turned clockwise, else
413
// it is negative
414
/////////////////////////////////////////////////////////////////////////////
141 tk 415
void APP_ENC_NotifyChange(u32 encoder, s32 incrementer)
416
{
308 tk 417
#if DEBUG_VERBOSE_LEVEL >= 1
418
  DEBUG_MSG("Enc %2d = %d\n", encoder, incrementer);
141 tk 419
#endif
61 tk 420
 
141 tk 421
  // forward to UI encoder handler
422
  SEQ_UI_Encoder_Handler(encoder, incrementer);
423
}
61 tk 424
 
141 tk 425
 
61 tk 426
/////////////////////////////////////////////////////////////////////////////
427
// This hook is called when a pot has been moved
428
/////////////////////////////////////////////////////////////////////////////
429
void APP_AIN_NotifyChange(u32 pin, u32 pin_value)
430
{
431
}
134 tk 432
 
433
/////////////////////////////////////////////////////////////////////////////
434
// This task is called periodically each mS
435
/////////////////////////////////////////////////////////////////////////////
141 tk 436
void SEQ_TASK_Period1mS(void)
134 tk 437
{
141 tk 438
  // update high-prio LED functions
439
  SEQ_UI_LED_Handler_Periodic();
134 tk 440
 
168 tk 441
  // for menu handling (e.g. flashing cursor, doubleclick counter, etc...)
442
  SEQ_UI_MENU_Handler_Periodic();
443
 
761 tk 444
  // update BPM
445
  SEQ_CORE_BPM_SweepHandler();
446
 
1318 tk 447
#ifndef MBSEQV4L
761 tk 448
  // Button handlers
524 tk 449
  if( seq_hwcfg_blm.enabled ) {
450
    // check for BLM pin changes, call button handler of sequencer on each toggled pin
451
    BLM_ButtonHandler(APP_BLM_NotifyToggle);
452
  }
1318 tk 453
#else
454
  // -> BLM_CHEAPO driver
455
  BLM_CHEAPO_ButtonHandler(APP_BLM_NotifyToggle);
456
#endif
524 tk 457
 
514 tk 458
  if( seq_hwcfg_blm8x8.enabled ) {
513 tk 459
    // check for BLM_X pin changes, call button handler of sequencer on each toggled pin
460
    BLM_X_BtnHandler(APP_BLM_X_NotifyToggle);
461
  }
141 tk 462
}
134 tk 463
 
159 tk 464
 
465
/////////////////////////////////////////////////////////////////////////////
625 tk 466
// This task is called each mS with lowest priority
467
/////////////////////////////////////////////////////////////////////////////
468
void SEQ_TASK_Period1mS_LowPrio(void)
469
{
1318 tk 470
#ifndef MBSEQV4L
625 tk 471
  // call LCD Handler
472
  SEQ_UI_LCD_Handler();
1318 tk 473
#endif
625 tk 474
 
475
  // update LEDs
476
  SEQ_UI_LED_Handler();
626 tk 477
 
759 tk 478
  // MIDI In/Out monitor
479
  SEQ_MIDI_PORT_Period1mS();
480
 
626 tk 481
  // if remote client active: timeout handling
1316 tk 482
  if( seq_midi_sysex_remote_active_mode == SEQ_MIDI_SYSEX_REMOTE_MODE_CLIENT ) {
483
    ++seq_midi_sysex_remote_client_timeout_ctr;
626 tk 484
 
485
    // request refresh from server each second
1316 tk 486
    if( (seq_midi_sysex_remote_client_timeout_ctr % 1000) == 999 ) {
626 tk 487
      SEQ_MIDI_SYSEX_REMOTE_SendRefresh();
1316 tk 488
    } else if( seq_midi_sysex_remote_client_timeout_ctr >= 5000 ) {
626 tk 489
      // no reply from server after 5 seconds: leave client mode
1316 tk 490
      seq_midi_sysex_remote_active_mode = SEQ_MIDI_SYSEX_REMOTE_MODE_AUTO;
1318 tk 491
#ifndef MBSEQV4L
626 tk 492
      SEQ_UI_Msg(SEQ_UI_MSG_USER, 1000, "No response from", "Remote Server!");
1318 tk 493
#endif
626 tk 494
    }
495
  }
496
 
625 tk 497
}
498
 
499
/////////////////////////////////////////////////////////////////////////////
290 tk 500
// This task is called periodically each second
501
/////////////////////////////////////////////////////////////////////////////
502
void SEQ_TASK_Period1S(void)
503
{
1318 tk 504
#ifndef MBSEQV4L
728 tk 505
  static u8 wait_boot_ctr = 2; // wait 2 seconds before loading from SD Card - this is to increase the time where the boot screen is print!
401 tk 506
  u8 load_sd_content = 0;
507
 
637 tk 508
  // don't check for SD Card if MSD enabled
638 tk 509
  if( TASK_MSD_EnableGet() > 0 )
637 tk 510
    return;
511
 
1044 tk 512
  // poll for IIC modules as long as HW config hasn't been locked (read from SD card)
652 tk 513
  // TODO: use proper mutex handling here
514
#ifndef MIOS32_FAMILY_EMULATION
515
  if( !SEQ_FILE_HW_ConfigLocked() ) {
516
    MIOS32_IIC_MIDI_ScanInterfaces();
517
  }
518
#endif  
519
 
728 tk 520
  // boot phase of 2 seconds finished?
521
  if( wait_boot_ctr ) {
522
    --wait_boot_ctr;
523
    return;
524
  }
525
 
1020 tk 526
  // BLM timeout counter
1021 tk 527
  MIOS32_IRQ_Disable();
1020 tk 528
  if( blm_timeout_ctr )
529
    --blm_timeout_ctr;
1021 tk 530
  MIOS32_IRQ_Enable();
1020 tk 531
 
290 tk 532
  // check if SD Card connected
533
  MUTEX_SDCARD_TAKE;
299 tk 534
 
1261 tk 535
  s32 status = FILE_CheckSDCard();
299 tk 536
 
537
  if( status == 1 ) {
538
    char str[21];
1261 tk 539
    sprintf(str, "Label: %s", FILE_VolumeLabel());
596 tk 540
    SEQ_UI_Msg(SEQ_UI_MSG_SDCARD, 2000, " SD Card connected", "        :-D");
1265 tk 541
    SEQ_FILE_LoadSessionName();
1261 tk 542
    SEQ_FILE_LoadAllFiles(1);
299 tk 543
  } else if( status == 2 ) {
596 tk 544
    SEQ_UI_Msg(SEQ_UI_MSG_SDCARD, 2000, "SD Card disconnected", "        :-/");
1261 tk 545
    SEQ_FILE_UnloadAllFiles();
299 tk 546
  } else if( status == 3 ) {
1261 tk 547
    if( !FILE_SDCardAvailable() ) {
596 tk 548
      SEQ_UI_Msg(SEQ_UI_MSG_SDCARD, 2000, "  No SD Card found  ", "        :-(");
496 tk 549
      SEQ_FILE_HW_LockConfig(); // lock configuration
1261 tk 550
    } else if( !FILE_VolumeAvailable() ) {
596 tk 551
      SEQ_UI_Msg(SEQ_UI_MSG_SDCARD, 2000, "!! SD Card Error !!!", "!! Invalid FAT !!!!!");
496 tk 552
      SEQ_FILE_HW_LockConfig(); // lock configuration
299 tk 553
    } else {
1052 tk 554
      char str1[30];
740 tk 555
      sprintf(str1, "Banks: ........");
299 tk 556
      u8 bank;
557
      for(bank=0; bank<8; ++bank)
740 tk 558
    str1[7+bank] = SEQ_FILE_B_NumPatterns(bank) ? ('1'+bank) : '-';
1052 tk 559
      char str2[30];
740 tk 560
      sprintf(str2,
1052 tk 561
          "M:%c S:%c G:%c C:%c%c HW:%c",
562
          SEQ_FILE_M_NumMaps() ? '*':'-',
563
          SEQ_FILE_S_NumSongs() ? '*':'-',
564
          SEQ_FILE_G_Valid() ? '*':'-',
565
          SEQ_FILE_C_Valid() ? 'S':'-',
566
          SEQ_FILE_GC_Valid() ? 'G':'-',
567
          SEQ_FILE_HW_Valid() ? '*':'-');
740 tk 568
      SEQ_UI_Msg(SEQ_UI_MSG_SDCARD, 2000, str1, str2);
353 tk 569
 
740 tk 570
      // request to load content of SD card
571
      load_sd_content = 1;
299 tk 572
    }
573
  } else if( status < 0 ) {
574
    SEQ_UI_SDCardErrMsg(2000, status);
575
  }
576
 
740 tk 577
  // check for format request
578
  // this is running with low priority, so that LCD is updated in parallel!
579
  if( seq_ui_format_req ) {
580
    // note: request should be cleared at the end of this process to avoid double-triggers!
581
    if( (status = SEQ_FILE_Format()) < 0 )
582
      SEQ_UI_SDCardErrMsg(2000, status);
961 tk 583
    else {
959 tk 584
      SEQ_UI_Msg(SEQ_UI_MSG_USER, 1000, "Files created", "successfully!");
740 tk 585
 
961 tk 586
      // store session name
587
      status |= SEQ_FILE_StoreSessionName();
588
    }
589
 
740 tk 590
    // request to load content of SD card
591
    load_sd_content = 1;
592
 
593
    // finally clear request
594
    seq_ui_format_req = 0;
595
  }
596
 
634 tk 597
  // check for backup request
598
  // this is running with low priority, so that LCD is updated in parallel!
599
  if( seq_ui_backup_req ) {
600
    // note: request should be cleared at the end of this process to avoid double-triggers!
601
    status = SEQ_FILE_CreateBackup();
602
 
603
    if( status < 0 ) {
1261 tk 604
      if( status == FILE_ERR_COPY )
959 tk 605
    SEQ_UI_Msg(SEQ_UI_MSG_USER, 2000, "COPY FAILED!", "ERROR :-(");
606
      else
607
    SEQ_UI_SDCardErrMsg(2000, status);
634 tk 608
    }
961 tk 609
    else {
959 tk 610
      SEQ_UI_Msg(SEQ_UI_MSG_USER, 1000, "Files copied", "successfully!");
634 tk 611
 
961 tk 612
      // store session name
613
      status |= SEQ_FILE_StoreSessionName();
614
    }
615
 
634 tk 616
    // finally clear request
617
    seq_ui_backup_req = 0;
618
  }
619
 
974 tk 620
  // check for save all request
621
  // this is running with low priority, so that LCD is updated in parallel!
622
  if( seq_ui_saveall_req ) {
1389 tk 623
    s32 status = 0;
974 tk 624
 
1389 tk 625
    // store all patterns
626
    int group;
627
    for(group=0; group<SEQ_CORE_NUM_GROUPS; ++group)
628
      status |= SEQ_FILE_B_PatternWrite(seq_file_session_name, seq_pattern[group].bank, seq_pattern[group].pattern, group, 1);
629
 
630
    // store config (e.g. to store current song/mixermap/pattern numbers
631
    SEQ_FILE_C_Write(seq_file_session_name);
632
 
974 tk 633
    // store session name
634
    if( status >= 0 )
635
      status |= SEQ_FILE_StoreSessionName();
636
 
637
    if( status < 0 )
638
      SEQ_UI_SDCardErrMsg(2000, status);
639
 
640
    // finally clear request
641
    seq_ui_saveall_req = 0;
642
  }
643
 
290 tk 644
  MUTEX_SDCARD_GIVE;
401 tk 645
 
646
  // load content of SD card if requested ((re-)connection detected)
740 tk 647
  if( load_sd_content && !SEQ_FILE_FormattingRequired() ) {
785 tk 648
    // send layout request to MBHP_BLM_SCALAR
649
    MUTEX_MIDIOUT_TAKE;
1020 tk 650
    SEQ_BLM_SYSEX_SendRequest(0x00);
785 tk 651
    MUTEX_MIDIOUT_GIVE;
652
 
401 tk 653
    // TODO: should we load the patterns when SD Card has been detected?
785 tk 654
    // disadvantage: current edit patterns are destroyed - this could be fatal during a live session if there is a bad contact!
401 tk 655
 
1020 tk 656
    SEQ_MIXER_Load(SEQ_MIXER_NumGet());
657
    SEQ_SONG_Load(SEQ_SONG_NumGet());
401 tk 658
  }
1318 tk 659
#else
660
  // MBSEQV4L handling (could be combined with code above later)
661
 
662
  // don't check for SD Card if MSD enabled
663
  if( TASK_MSD_EnableGet() > 0 )
664
    return;
665
 
666
  MUTEX_SDCARD_TAKE;
667
  s32 status = FILE_CheckSDCard();
668
 
669
  if( status == 1 ) {
670
    DEBUG_MSG("SD Card connected: %s\n", FILE_VolumeLabel());
671
    // load all file infos
1320 tk 672
    SEQ_FILE_LoadSessionName();
673
    DEBUG_MSG("Loading session %s\n", seq_file_session_name);
1318 tk 674
    SEQ_FILE_LoadAllFiles(1); // including HW info
675
  } else if( status == 2 ) {
676
    DEBUG_MSG("SD Card disconnected\n");
677
    // invalidate all file infos
678
    SEQ_FILE_UnloadAllFiles();
679
  } else if( status == 3 ) {
680
    if( !FILE_SDCardAvailable() ) {
681
      DEBUG_MSG("SD Card not found\n");
682
      SEQ_FILE_HW_LockConfig(); // lock configuration
683
    } else if( !FILE_VolumeAvailable() ) {
684
      DEBUG_MSG("ERROR: SD Card contains invalid FAT!\n");
685
      SEQ_FILE_HW_LockConfig(); // lock configuration
686
    } else {
1320 tk 687
      // check if formatting is required
688
      if( SEQ_FILE_FormattingRequired() ) {
689
    strcpy(seq_file_new_session_name, "DEF_V4L");
690
    DEBUG_MSG("Creating initial session '%s'... this can take some seconds!\n", seq_file_new_session_name);
691
 
692
    if( (status=SEQ_FILE_Format()) < 0 ) {
693
      DEBUG_MSG("Failed to create session! (status: %d)\n", status);
694
    } else {
695
      SEQ_FILE_StoreSessionName();
696
      DEBUG_MSG("Done!\n");
1318 tk 697
    }
698
      }
699
    }
700
  }
701
 
702
  MUTEX_SDCARD_GIVE;
703
#endif
290 tk 704
}
705
 
706
 
707
/////////////////////////////////////////////////////////////////////////////
159 tk 708
// This task is called periodically each mS as well
709
// it handles sequencer and MIDI events
710
/////////////////////////////////////////////////////////////////////////////
711
void SEQ_TASK_MIDI(void)
712
{
419 tk 713
  MUTEX_MIDIOUT_TAKE;
714
 
159 tk 715
  // execute sequencer handler
716
  SEQ_CORE_Handler();
717
 
718
  // send timestamped MIDI events
190 tk 719
  SEQ_MIDI_OUT_Handler();
419 tk 720
 
1083 tk 721
  // update CV and gates
722
  SEQ_CV_Update();
718 tk 723
 
419 tk 724
  MUTEX_MIDIOUT_GIVE;
159 tk 725
}
726
 
727
 
728
/////////////////////////////////////////////////////////////////////////////
184 tk 729
// This task is triggered whenever a pattern has to be loaded
730
/////////////////////////////////////////////////////////////////////////////
731
void SEQ_TASK_Pattern(void)
732
{
733
  SEQ_PATTERN_Handler();
734
}
735
 
736
 
737
/////////////////////////////////////////////////////////////////////////////
281 tk 738
// Installed via MIOS32_MIDI_DirectRxCallback_Init
159 tk 739
/////////////////////////////////////////////////////////////////////////////
281 tk 740
static s32 NOTIFY_MIDI_Rx(mios32_midi_port_t port, u8 midi_byte)
159 tk 741
{
653 tk 742
  // filter MIDI In port which controls the MIDI clock
743
  if( SEQ_MIDI_ROUTER_MIDIClockInGet(port) == 1 )
457 tk 744
    SEQ_BPM_NotifyMIDIRx(midi_byte);
281 tk 745
 
746
  return 0; // no error, no filtering
159 tk 747
}
748
 
281 tk 749
 
750
/////////////////////////////////////////////////////////////////////////////
751
// Installed via MIOS32_MIDI_DirectTxCallback_Init
752
/////////////////////////////////////////////////////////////////////////////
753
static s32 NOTIFY_MIDI_Tx(mios32_midi_port_t port, mios32_midi_package_t package)
159 tk 754
{
718 tk 755
  return SEQ_MIDI_PORT_NotifyMIDITx(port, package);
159 tk 756
}
529 tk 757
 
758
 
759
/////////////////////////////////////////////////////////////////////////////
760
// Installed via MIOS32_MIDI_TimeoutCallback_Init
761
/////////////////////////////////////////////////////////////////////////////
762
static s32 NOTIFY_MIDI_TimeOut(mios32_midi_port_t port)
763
{  
625 tk 764
  // forward to SysEx parser
765
  SEQ_MIDI_SYSEX_TimeOut(port);
529 tk 766
 
1318 tk 767
#ifndef MBSEQV4L
625 tk 768
  // print message on screen
769
  SEQ_UI_Msg(SEQ_UI_MSG_USER, 2000, "MIDI Protocol", "TIMEOUT !!!");
1318 tk 770
#endif
625 tk 771
 
529 tk 772
  return 0;
773
}