Subversion Repositories svn.mios32

Rev

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

Rev Author Line No. Line
1313 tk 1
// $Id: seq_ui.c 2531 2017-10-11 22:55:38Z tk $
2
/*
3
 * User Interface Routines
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
// with this switch, seq_ui.h/seq_ui_pages.inc will create local variables
19
#define SEQ_UI_PAGES_INC_LOCAL_VARS 1
20
 
21
#include <mios32.h>
22
#include <string.h>
23
#include <seq_midi_out.h>
24
#include <seq_bpm.h>
25
#include <blm_cheapo.h>
26
 
27
#include "tasks.h"
1336 tk 28
#include "seq_led.h"
2531 tk 29
#include "seq_blm8x8.h"
1313 tk 30
#include "seq_ui.h"
31
#include "seq_ui_pages.h"
32
#include "seq_hwcfg.h"
33
#include "seq_core.h"
34
#include "seq_record.h"
35
#include "seq_par.h"
36
#include "seq_layer.h"
37
#include "seq_cc.h"
38
#include "seq_midi_sysex.h"
1390 tk 39
#include "seq_blm.h"
1313 tk 40
 
41
#include "file.h"
42
#include "seq_file.h"
43
#include "seq_file_hw.h"
44
 
45
 
46
/////////////////////////////////////////////////////////////////////////////
47
// Global variables
48
/////////////////////////////////////////////////////////////////////////////
49
 
50
seq_ui_button_state_t seq_ui_button_state;
51
 
1319 tk 52
u8 ui_selected_group;
1313 tk 53
u16 ui_selected_tracks;
1319 tk 54
u8 ui_selected_par_layer;
55
u8 ui_selected_trg_layer;
56
u8 ui_selected_instrument;
1313 tk 57
u8 ui_selected_step;
58
u8 ui_selected_step_view;
1319 tk 59
u16 ui_selected_gp_buttons;
1313 tk 60
 
61
volatile u8 ui_cursor_flash;
62
volatile u8 ui_cursor_flash_overrun_ctr;
63
u16 ui_cursor_flash_ctr;
64
 
65
u8 seq_ui_display_update_req;
66
 
67
u8 ui_seq_pause;
68
 
1422 tk 69
u8 ui_song_edit_pos;
70
 
1868 tk 71
u8 seq_ui_backup_req;
72
u8 seq_ui_format_req;
73
u8 seq_ui_saveall_req;
74
 
1319 tk 75
u8 ui_quicksel_length[UI_QUICKSEL_NUM_PRESETS];
76
u8 ui_quicksel_loop_length[UI_QUICKSEL_NUM_PRESETS];
77
u8 ui_quicksel_loop_loop[UI_QUICKSEL_NUM_PRESETS];
1313 tk 78
 
1319 tk 79
seq_ui_bookmark_t seq_ui_bookmarks[SEQ_UI_BOOKMARKS_NUM];
80
 
1405 tk 81
u8 ui_controller_mode;
82
mios32_midi_port_t ui_controller_port;
83
u8 ui_controller_chn;
84
 
1976 tk 85
u16 ui_track_activity_state;
86
 
87
 
1313 tk 88
/////////////////////////////////////////////////////////////////////////////
89
// Local variables
90
/////////////////////////////////////////////////////////////////////////////
91
 
92
static u32 tap_tempo_last_timestamp;
93
#define TAP_DELAY_STORAGE_SIZE 4
94
static u16 tap_tempo_delay[TAP_DELAY_STORAGE_SIZE];
95
static u8 tap_tempo_beat_ix;
96
static u8 tap_tempo_beat_ctr;
97
 
98
 
99
/////////////////////////////////////////////////////////////////////////////
100
// Local prototypes
101
/////////////////////////////////////////////////////////////////////////////
102
static s32 resetTapTempo(void);
103
 
104
 
105
/////////////////////////////////////////////////////////////////////////////
106
// Initialisation
107
/////////////////////////////////////////////////////////////////////////////
108
s32 SEQ_UI_Init(u32 mode)
109
{
110
  seq_ui_button_state.ALL = 0;
111
 
1319 tk 112
  ui_selected_group = 0;
1313 tk 113
  ui_selected_tracks = 0x00ff;
1319 tk 114
  ui_selected_par_layer = 0;
115
  ui_selected_trg_layer = 0;
116
  ui_selected_instrument = 0;
1313 tk 117
  ui_selected_step = 0;
118
  ui_selected_step_view = 0;
119
  ui_seq_pause = 0;
1422 tk 120
  ui_song_edit_pos = 0;
1319 tk 121
  ui_selected_gp_buttons = 0;
1313 tk 122
 
123
  ui_cursor_flash_ctr = ui_cursor_flash_overrun_ctr = 0;
124
  ui_cursor_flash = 0;
125
 
126
  seq_ui_display_update_req = 1;
127
 
1868 tk 128
  // misc
129
  seq_ui_backup_req = 0;
130
  seq_ui_format_req = 0;
131
  seq_ui_saveall_req = 0;
132
 
1405 tk 133
  ui_controller_mode = UI_CONTROLLER_MODE_OFF;
134
  //ui_controller_port = 0xc0; // combined
135
  ui_controller_port = UART1; // OUT2
136
  ui_controller_chn = Chn16;
137
 
1313 tk 138
  resetTapTempo();
139
 
140
  // set initial page
141
  SEQ_UI_PAGES_Set(SEQ_UI_PAGE_TRIGGER);
142
 
1319 tk 143
  // finally init bookmarks
144
  //ui_page_before_bookmark = SEQ_UI_PAGE_EDIT;
145
  int i;
146
  for(i=0; i<SEQ_UI_BOOKMARKS_NUM; ++i) {
147
    char buffer[10];
148
    seq_ui_bookmark_t *bm = (seq_ui_bookmark_t *)&seq_ui_bookmarks[i];
149
 
150
    sprintf(buffer, "BM%2d ", i+1);
151
    memcpy((char *)bm->name, buffer, 6);
152
    bm->enable.ALL = ~0;
153
    bm->flags.LOCKED = 0;
154
    SEQ_UI_Bookmark_Store(i);
155
  }
156
 
1976 tk 157
  ui_track_activity_state = 0;
158
 
1313 tk 159
  return 0; // no error
160
}
161
 
162
 
163
// resets the tap tempo variables
164
static s32 resetTapTempo(void)
165
{
166
  tap_tempo_last_timestamp = 0;
167
  tap_tempo_beat_ix = 0;
168
  tap_tempo_beat_ctr = 0;
169
 
170
  int tap;
171
  for(tap=0; tap<TAP_DELAY_STORAGE_SIZE; ++tap)
172
    tap_tempo_delay[tap] = 0;
173
 
174
  return 0; // no error
175
}
176
 
177
 
178
/////////////////////////////////////////////////////////////////////////////
179
// Dedicated button functions
180
// Mapped to physical buttons in SEQ_UI_Button_Handler()
181
// Will also be mapped to MIDI keys later (for MIDI remote function)
182
/////////////////////////////////////////////////////////////////////////////
183
static s32 SEQ_UI_Button_GP(s32 depressed, u32 gp)
184
{
185
  s32 status;
186
 
1319 tk 187
  if( depressed )
188
    ui_selected_gp_buttons &= ~(1 << gp);
189
  else
190
    ui_selected_gp_buttons |= (1 << gp);
191
 
1313 tk 192
  if( (status=SEQ_UI_PAGES_GP_Button_Handler(gp, depressed)) >= 0 ) {
193
    ui_cursor_flash_ctr = ui_cursor_flash_overrun_ctr = 0;
194
  }
195
  return status;
196
}
197
 
198
 
199
static s32 SEQ_UI_Button_Bar(s32 depressed, u32 bar)
200
{
201
  if( depressed ) return -1; // ignore when button depressed
202
  ui_selected_step_view = bar;
203
  return 0; // no error
204
}
205
 
1981 tk 206
s32 SEQ_UI_Button_Seq(s32 depressed, u32 seq)
1313 tk 207
{
208
  static u16 seq_pressed = 0x0000;
209
 
210
  u16 selected_tracks = seq ? 0xff00 : 0x00ff;
211
 
212
  // allow multi-selections
213
  if( depressed ) {
214
    seq_pressed &= ~selected_tracks;
215
  } else {
216
    seq_pressed |= selected_tracks;
217
    ui_selected_tracks = seq_pressed;
218
  }
219
 
220
  // armed tracks handling: alternate and select all tracks depending on seq selection
221
  // can be changed in RecArm page
222
  if( seq ) {
1316 tk 223
    if( (seq_record_state.ARMED_TRACKS & 0x00ff) )
224
      seq_record_state.ARMED_TRACKS = 0xff00;
1313 tk 225
  } else {
1316 tk 226
    if( (seq_record_state.ARMED_TRACKS & 0xff00) )
227
      seq_record_state.ARMED_TRACKS = 0x00ff;
1313 tk 228
  }
229
 
1978 tk 230
  // if clear button is pressed: clear entire sequence
1981 tk 231
  if( !depressed && seq_ui_button_state.CLEAR ) {
1978 tk 232
    SEQ_UI_UTIL_Clear();
233
  }
234
 
1313 tk 235
  return 0; // no error
236
}
237
 
238
 
239
s32 SEQ_UI_Button_Stop(s32 depressed)
240
{
241
  if( depressed ) return -1; // ignore when button depressed
242
 
243
  // if sequencer running: stop it
244
  // if sequencer already stopped: reset song position
245
  if( SEQ_BPM_IsRunning() ) {
246
#if 0
247
    // TK: maybe to complicated to understand: STOP sequencer in slave mode if stop button pressed twice
248
    u8 enable_slaveclk_mute = !SEQ_BPM_IsMaster() && seq_core_slaveclk_mute != SEQ_CORE_SLAVECLK_MUTE_Enabled;
249
#else
250
    // always mute tracks, never stop sequencer (can only be done from external)
251
    u8 enable_slaveclk_mute = !SEQ_BPM_IsMaster();
252
#endif
253
    if( enable_slaveclk_mute ) {
254
      seq_core_slaveclk_mute = SEQ_CORE_SLAVECLK_MUTE_Enabled;
255
    } else {
256
      seq_core_slaveclk_mute = SEQ_CORE_SLAVECLK_MUTE_Off;
257
      SEQ_BPM_Stop();
258
    }
259
  } else {
260
    seq_core_slaveclk_mute = SEQ_CORE_SLAVECLK_MUTE_Off;
261
    SEQ_CORE_Reset(0);
262
  }
263
 
264
  return 0; // no error
265
}
266
 
267
static s32 SEQ_UI_Button_Pause(s32 depressed)
268
{
269
  if( depressed ) return -1; // ignore when button depressed
270
 
271
  // if in auto mode and BPM generator is not clocked in slave mode:
272
  // change to master mode
273
  SEQ_BPM_CheckAutoMaster();
274
 
275
  // toggle pause
276
  ui_seq_pause ^= 1;
277
 
278
  // execute stop/continue depending on new mode
279
  MIOS32_IRQ_Disable();
280
  if( ui_seq_pause ) {
281
    if( !SEQ_BPM_IsMaster() ) {
282
      seq_core_slaveclk_mute = SEQ_CORE_SLAVECLK_MUTE_Enabled;
283
    } else {
284
      SEQ_BPM_Stop();
285
    }
286
  } else {
287
    if( !SEQ_BPM_IsMaster() ) {
288
      seq_core_slaveclk_mute = SEQ_CORE_SLAVECLK_MUTE_Off;
289
    }
290
 
291
    if( !SEQ_BPM_IsRunning() )
292
      SEQ_BPM_Cont();
293
  }
294
  MIOS32_IRQ_Enable();
295
 
296
  return 0; // no error
297
}
298
 
299
s32 SEQ_UI_Button_Play(s32 depressed)
300
{
301
  if( depressed ) return -1; // ignore when button depressed
302
 
303
  // if in auto mode and BPM generator is not clocked in slave mode:
304
  // change to master mode
305
  SEQ_BPM_CheckAutoMaster();
306
 
307
  // slave mode and tracks muted: enable on next measure
308
  if( !SEQ_BPM_IsMaster() && SEQ_BPM_IsRunning() ) {
309
    if( seq_core_slaveclk_mute != SEQ_CORE_SLAVECLK_MUTE_Off )
310
      seq_core_slaveclk_mute = SEQ_CORE_SLAVECLK_MUTE_OffOnNextMeasure;
311
    // TK: note - in difference to master mode pressing PLAY twice won't reset the sequencer!
312
  } else {
313
#if 0
314
    // if sequencer running: restart it
315
    // if sequencer stopped: continue at last song position
316
    if( SEQ_BPM_IsRunning() )
317
      SEQ_BPM_Start();
318
    else
319
      SEQ_BPM_Cont();
320
#else
321
    // always restart sequencer
322
    seq_core_slaveclk_mute = SEQ_CORE_SLAVECLK_MUTE_Off;
323
    SEQ_BPM_Start();
324
#endif
325
  }
326
 
327
  return 0; // no error
328
}
329
 
330
static s32 SEQ_UI_Button_TapTempo(s32 depressed)
331
{
332
  seq_ui_button_state.TAP_TEMPO = depressed ? 0 : 1;
333
 
334
  if( depressed ) return -1; // ignore when button depressed
335
 
1422 tk 336
  // enter tempo page
337
  SEQ_UI_PAGES_Set(SEQ_UI_PAGE_TEMPO);
338
 
1313 tk 339
  // determine current timestamp
1976 tk 340
  u32 timestamp = MIOS32_TIMESTAMP_Get();
341
  u32 delay = MIOS32_TIMESTAMP_GetDelay(tap_tempo_last_timestamp);
1313 tk 342
 
343
  // if delay < 100 (mS) we assume a bouncing button - ignore this tap!
344
  if( delay < 100 )
345
    return -1;
346
 
347
  // reset counter if last timestamp zero (first tap) or difference between timestamps > 2 seconds (< 30 BPM...)
348
  if( !tap_tempo_last_timestamp || delay > 2000 ) {
349
    resetTapTempo();
350
  } else {    
351
    // store measured delay
352
    tap_tempo_delay[tap_tempo_beat_ix] = delay;
353
 
354
    // increment index, wrap at number of stored tap delays
355
    tap_tempo_beat_ix = (tap_tempo_beat_ix + 1) % TAP_DELAY_STORAGE_SIZE;
356
  }
357
 
358
  // store timestamp
359
  tap_tempo_last_timestamp = timestamp;
360
 
361
  // take over BPM and start sequencer once we reached the 5th tap
362
  if( tap_tempo_beat_ctr >= TAP_DELAY_STORAGE_SIZE ) {
363
    // hold counter at delay storage size + 1 (for display)
364
    tap_tempo_beat_ctr = TAP_DELAY_STORAGE_SIZE + 1;
365
 
366
    // determine BPM
367
    int tap;
368
    int accumulated_delay = 0;
1976 tk 369
    for(tap=0; tap<TAP_DELAY_STORAGE_SIZE; ++tap) {
1313 tk 370
      accumulated_delay += tap_tempo_delay[tap];
1976 tk 371
    }
1612 tk 372
    u32 bpm = 60000000 / (accumulated_delay / TAP_DELAY_STORAGE_SIZE);
1313 tk 373
 
374
    // set BPM
375
    float bpmF = bpm / 1000.0;
376
    seq_core_bpm_preset_tempo[seq_core_bpm_preset_num] = bpmF;
377
    SEQ_BPM_Set(bpmF);
378
 
379
    // if in auto mode and BPM generator is clocked in slave mode:
380
    // change to master mode
381
    SEQ_BPM_CheckAutoMaster();
382
 
383
    // if sequencer not running: start it!
384
    if( !SEQ_BPM_IsRunning() ) {
385
      SEQ_BPM_ModeSet(SEQ_BPM_MODE_Master); // force master mode
386
      SEQ_BPM_Start();
387
    }
388
 
389
  } else {
390
    // increment counter
391
    ++tap_tempo_beat_ctr;
392
  }
393
 
394
  return 0; // no error
395
}
396
 
397
static s32 SEQ_UI_Button_Master(s32 depressed)
398
{
399
  if( depressed ) return -1; // ignore when button depressed
400
 
401
  // note: after power-on SEQ_BPM_MODE_Auto is selected
402
  if( SEQ_BPM_ModeGet() == SEQ_BPM_MODE_Slave )
403
    SEQ_BPM_ModeSet(SEQ_BPM_MODE_Master);
404
  else
405
    SEQ_BPM_ModeSet(SEQ_BPM_MODE_Slave);
406
 
407
  return 0; // no error
408
}
409
 
410
static s32 SEQ_UI_Button_ExtRestart(s32 depressed)
411
{
412
  if( depressed ) return -1; // ignore when button depressed
413
 
414
  // should be atomic
415
  portENTER_CRITICAL();
416
  seq_core_state.EXT_RESTART_REQ = 1;
417
  portEXIT_CRITICAL();
418
 
419
  return 0; // no error
420
}
421
 
422
static s32 SEQ_UI_Button_Metronome(s32 depressed)
423
{
424
  if( depressed ) return -1; // ignore when button depressed
425
 
426
  // should be atomic
427
  portENTER_CRITICAL();
428
  seq_core_state.METRONOME ^= 1;
429
  portEXIT_CRITICAL();
430
 
431
  return 0; // no error
432
}
433
 
434
 
435
static s32 SEQ_UI_Button_Load(s32 depressed)
436
{
437
  if( depressed ) return -1; // ignore when button depressed
438
  return SEQ_UI_PAGES_Set(SEQ_UI_PAGE_LOAD);
439
}
440
 
441
static s32 SEQ_UI_Button_Save(s32 depressed)
442
{
443
  if( depressed ) return -1; // ignore when button depressed
444
  return SEQ_UI_PAGES_Set(SEQ_UI_PAGE_SAVE);
445
}
446
 
447
 
448
static s32 SEQ_UI_Button_Copy(s32 depressed)
449
{
450
  seq_ui_button_state.COPY = depressed ? 0 : 1;
451
  if( depressed ) return -1; // ignore when button depressed
452
  return SEQ_UI_UTIL_Copy();
453
}
454
 
455
 
456
static s32 SEQ_UI_Button_Paste(s32 depressed)
457
{
458
  seq_ui_button_state.PASTE = depressed ? 0 : 1;
459
  if( depressed ) return -1; // ignore when button depressed
460
  return SEQ_UI_UTIL_Paste();
461
}
462
 
463
static s32 SEQ_UI_Button_Clear(s32 depressed)
464
{
465
  seq_ui_button_state.CLEAR = depressed ? 0 : 1;
466
  if( depressed ) return -1; // ignore when button depressed
1976 tk 467
#if 0
1313 tk 468
  return SEQ_UI_UTIL_Clear();
1976 tk 469
#else
470
  // changed in V4L 1.082: press CLEAR and GP button to clear individual track
471
  return 0;
472
#endif
1313 tk 473
}
474
 
475
 
476
static s32 SEQ_UI_Button_Undo(s32 depressed)
477
{
478
  seq_ui_button_state.UNDO = depressed ? 0 : 1;
479
  if( depressed ) return -1; // ignore when button depressed
480
  return SEQ_UI_UTIL_Undo();
481
}
482
 
483
 
484
static s32 SEQ_UI_Button_TrackTrigger(s32 depressed)
485
{
486
  if( depressed ) return -1; // ignore when button depressed
487
  return SEQ_UI_PAGES_Set(SEQ_UI_PAGE_TRIGGER);
488
}
489
 
490
static s32 SEQ_UI_Button_TrackMute(s32 depressed)
491
{
1405 tk 492
  seq_ui_button_state.MUTE_PRESSED = depressed == 0;
493
 
494
  // special key combination to toggle controller mode
495
  if( seq_ui_button_state.MUTE_PRESSED && seq_ui_button_state.MIDICHN_PRESSED ) {
496
    if( ++ui_controller_mode >= UI_CONTROLLER_MODE_NUM )
497
      ui_controller_mode = 0;
498
    return 1;
499
  }
500
 
1313 tk 501
  if( depressed ) return -1; // ignore when button depressed
502
  return SEQ_UI_PAGES_Set(SEQ_UI_PAGE_MUTE);
503
}
504
 
505
 
506
static s32 SEQ_UI_Button_TrackMidiChn(s32 depressed)
507
{
1405 tk 508
  seq_ui_button_state.MIDICHN_PRESSED = depressed == 0;
509
 
510
  // special key combination to toggle controller mode
511
  if( seq_ui_button_state.MUTE_PRESSED && seq_ui_button_state.MIDICHN_PRESSED ) {
512
    if( ++ui_controller_mode >= UI_CONTROLLER_MODE_NUM )
513
      ui_controller_mode = 0;
514
    return 1;
515
  }
516
 
1313 tk 517
  if( depressed ) return -1; // ignore when button depressed
518
  return SEQ_UI_PAGES_Set(SEQ_UI_PAGE_MIDICHN);
519
}
520
 
521
 
522
static s32 SEQ_UI_Button_TrackGroove(s32 depressed)
523
{
524
  if( depressed ) return -1; // ignore when button depressed
525
  return SEQ_UI_PAGES_Set(SEQ_UI_PAGE_GROOVE);
526
}
527
 
528
static s32 SEQ_UI_Button_TrackLength(s32 depressed)
529
{
1390 tk 530
  // show loop point when length button pressed
531
  seq_ui_button_state.LENGTH_PRESSED = depressed == 0;
1313 tk 532
  if( depressed ) return -1; // ignore when button depressed
533
  return SEQ_UI_PAGES_Set(SEQ_UI_PAGE_LENGTH);
534
}
535
 
536
static s32 SEQ_UI_Button_TrackProgression(s32 depressed)
537
{
538
  if( depressed ) return -1; // ignore when button depressed
539
  return SEQ_UI_PAGES_Set(SEQ_UI_PAGE_PROGRESSION);
540
}
541
 
542
static s32 SEQ_UI_Button_TrackEcho(s32 depressed)
543
{
544
  if( depressed ) return -1; // ignore when button depressed
545
  return SEQ_UI_PAGES_Set(SEQ_UI_PAGE_ECHO);
546
}
547
 
548
 
549
static s32 SEQ_UI_Button_TrackHumanizer(s32 depressed)
550
{
551
  if( depressed ) return -1; // ignore when button depressed
552
  return SEQ_UI_PAGES_Set(SEQ_UI_PAGE_HUMANIZER);
553
}
554
 
555
static s32 SEQ_UI_Button_TrackLFO(s32 depressed)
556
{
557
  if( depressed ) return -1; // ignore when button depressed
558
  return SEQ_UI_PAGES_Set(SEQ_UI_PAGE_LFO);
559
}
560
 
561
static s32 SEQ_UI_Button_TrackScale(s32 depressed)
562
{
1390 tk 563
  // show scale selection when scale button pressed
1337 tk 564
  seq_ui_button_state.SCALE_PRESSED = depressed == 0;
1313 tk 565
  if( depressed ) return -1; // ignore when button depressed
566
  return SEQ_UI_PAGES_Set(SEQ_UI_PAGE_SCALE);
567
}
568
 
569
static s32 SEQ_UI_Button_RecArm(s32 depressed)
570
{
571
  if( depressed ) return -1; // ignore when button depressed
572
  return SEQ_UI_PAGES_Set(SEQ_UI_PAGE_REC_ARM);
573
}
574
 
575
static s32 SEQ_UI_Button_RecStep(s32 depressed)
576
{
577
  if( depressed ) return -1; // ignore when button depressed
578
  return SEQ_UI_PAGES_Set(SEQ_UI_PAGE_REC_STEP);
579
}
580
 
581
static s32 SEQ_UI_Button_RecLive(s32 depressed)
582
{
583
  if( depressed ) return -1; // ignore when button depressed
584
  return SEQ_UI_PAGES_Set(SEQ_UI_PAGE_REC_LIVE);
585
}
586
 
2452 tk 587
 
1313 tk 588
static s32 SEQ_UI_Button_RecPoly(s32 depressed)
589
{
590
  if( depressed ) return -1; // ignore when button depressed
591
 
592
  seq_record_options.POLY_RECORD ^= 1;
593
 
594
  return 0; // no error
595
}
596
 
2452 tk 597
s32 SEQ_UI_Button_Record(s32 depressed)
598
{
599
  if( depressed ) return -1; // ignore when button depressed
600
 
601
  // enable/disable recording
602
  SEQ_RECORD_Enable(seq_record_state.ENABLED ? 0 : 1, 1);
603
 
604
  return 0; // no error
605
}
606
 
1313 tk 607
static s32 SEQ_UI_Button_InOutFwd(s32 depressed)
608
{
609
  if( depressed ) return -1; // ignore when button depressed
610
 
611
  seq_record_options.FWD_MIDI ^= 1;
612
 
613
  return 0; // no error
614
}
615
 
616
static s32 SEQ_UI_Button_TrackTranspose(s32 depressed)
617
{
618
  if( depressed ) return -1; // ignore when button depressed
619
 
1322 tk 620
  seq_core_global_transpose_enabled ^= 1;
1313 tk 621
 
622
  return 0; // no error
623
}
624
 
625
 
626
 
627
 
628
/////////////////////////////////////////////////////////////////////////////
1405 tk 629
// Button handler for controller mode
1313 tk 630
/////////////////////////////////////////////////////////////////////////////
1405 tk 631
s32 SEQ_UI_Button_Handler_Controller(u32 pin, u32 pin_value)
632
{
1406 tk 633
  u8 depressed = pin_value == 1;
1405 tk 634
  mios32_midi_port_t port = ui_controller_port;
635
  u8 chn = ui_controller_chn;
636
 
1406 tk 637
  if( pin == seq_hwcfg_button.mute )
638
    seq_ui_button_state.MUTE_PRESSED = depressed == 0;
639
  if( pin == seq_hwcfg_button.midichn )
640
    seq_ui_button_state.MIDICHN_PRESSED = depressed == 0;
641
 
642
  if( pin == seq_hwcfg_button.mute || pin == seq_hwcfg_button.midichn ) {
643
    // special key combination to toggle controller mode
644
    if( seq_ui_button_state.MUTE_PRESSED && seq_ui_button_state.MIDICHN_PRESSED ) {
645
      if( ++ui_controller_mode >= UI_CONTROLLER_MODE_NUM )
646
    ui_controller_mode = 0;
647
      return 0;
648
    }
649
  }
650
 
1405 tk 651
  switch( ui_controller_mode ) {
652
  case UI_CONTROLLER_MODE_MAQ16_3:
653
    // only react on pressed buttons
1406 tk 654
    if( depressed )
1405 tk 655
      return 0;
656
 
657
    if( pin == seq_hwcfg_button.bar1 ) { MIOS32_MIDI_SendProgramChange(port, chn, 0x00); return 1; } // Select Row1
658
    if( pin == seq_hwcfg_button.bar2 ) { MIOS32_MIDI_SendProgramChange(port, chn, 0x01); return 1; } // Select Row2
659
    if( pin == seq_hwcfg_button.bar3 ) { MIOS32_MIDI_SendProgramChange(port, chn, 0x02); return 1; } // Select Row2
660
    if( pin == seq_hwcfg_button.bar4 ) { return 1; } // not assigned
661
 
1411 tk 662
    if( pin == seq_hwcfg_button.seq1  ) { return 1; } // not assigned
663
    if( pin == seq_hwcfg_button.seq2  ) { return 1; } // not assigned
1405 tk 664
    if( pin == seq_hwcfg_button.load ) { MIOS32_MIDI_SendProgramChange(port, chn, 0x05); return 1; } // Steps on
665
    if( pin == seq_hwcfg_button.save ) { MIOS32_MIDI_SendProgramChange(port, chn, 0x06); return 1; } // Steps off?
666
 
667
    if( pin == seq_hwcfg_button.copy  ) { return 1; } // not assigned
668
    if( pin == seq_hwcfg_button.paste ) { return 1; } // not assigned
669
    if( pin == seq_hwcfg_button.clear ) { return 1; } // not assigned
670
    if( pin == seq_hwcfg_button.undo  ) { return 1; } // not assigned
671
 
672
    // note: master/tempo/stop/play still working as usual
673
 
674
    // note: UI pages handled in seq_ui_pages.c
675
 
676
    if( pin == seq_hwcfg_button.rec_poly )  { return 1; } // not assigned
677
    if( pin == seq_hwcfg_button.inout_fwd ) { return 1; } // not assigned
678
    if( pin == seq_hwcfg_button.transpose ) { return 1; } // not assigned
679
 
680
    break;
681
  }
682
 
683
  return -1; // button not mapped
684
}
685
 
686
/////////////////////////////////////////////////////////////////////////////
687
// Button handler for normal mode
688
/////////////////////////////////////////////////////////////////////////////
1313 tk 689
s32 SEQ_UI_Button_Handler(u32 pin, u32 pin_value)
690
{
691
  int i;
692
 
693
  // ignore as long as hardware config hasn't been read
1868 tk 694
  if( !SEQ_FILE_HW_ConfigLocked() )
1313 tk 695
    return -1;
696
 
1868 tk 697
  // ignore during a backup or format is created
698
  if( seq_ui_backup_req || seq_ui_format_req )
699
    return -1;
700
 
1313 tk 701
  // ensure that selections are matching with track constraints
702
  SEQ_UI_CheckSelections();
703
 
704
  // update display
705
  seq_ui_display_update_req = 1;
706
 
707
  // MEMO: we could also use a jump table with references to the functions
708
  // here, but this "spagetthi code" simplifies the configuration and
709
  // the resulting ASM doesn't look that bad!
710
 
711
  if( pin != seq_hwcfg_button.tap_tempo )
712
    resetTapTempo();
713
 
1405 tk 714
  // controller mode?
715
  if( ui_controller_mode && SEQ_UI_Button_Handler_Controller(pin, pin_value) >= 0 )
716
    return 1;
1313 tk 717
 
718
  for(i=0; i<8; ++i)
719
    if( pin == (8*(seq_hwcfg_button.gp_din_l_sr-1) + i) )
720
      return SEQ_UI_Button_GP(pin_value, i + 0);
721
 
2399 tk 722
  for(i=0; i<8; ++i) {
723
    if( pin == (8*(seq_hwcfg_button.gp_din_r_sr-1) + i) ) {
724
      if( seq_hwcfg_blm8x8.dout_gp_mapping == 2 )
725
    return SEQ_UI_Button_GP(pin_value, (7-i) + 8);
726
      else
727
    return SEQ_UI_Button_GP(pin_value, i + 8);
728
    }
729
  }
1313 tk 730
 
731
  if( pin == seq_hwcfg_button.bar1 )
732
    return SEQ_UI_Button_Bar(pin_value, 0);
733
  if( pin == seq_hwcfg_button.bar2 )
734
    return SEQ_UI_Button_Bar(pin_value, 1);
735
  if( pin == seq_hwcfg_button.bar3 )
736
    return SEQ_UI_Button_Bar(pin_value, 2);
737
  if( pin == seq_hwcfg_button.bar4 )
738
    return SEQ_UI_Button_Bar(pin_value, 3);
739
 
740
  if( pin == seq_hwcfg_button.seq1 )
1981 tk 741
    return SEQ_UI_Button_Seq(pin_value, 0);
1313 tk 742
  if( pin == seq_hwcfg_button.seq2 )
1981 tk 743
    return SEQ_UI_Button_Seq(pin_value, 1);
1313 tk 744
 
745
  if( pin == seq_hwcfg_button.load )
746
    return SEQ_UI_Button_Load(pin_value);
747
  if( pin == seq_hwcfg_button.save )
748
    return SEQ_UI_Button_Save(pin_value);
749
 
750
  if( pin == seq_hwcfg_button.copy )
751
    return SEQ_UI_Button_Copy(pin_value);
752
  if( pin == seq_hwcfg_button.paste )
753
    return SEQ_UI_Button_Paste(pin_value);
754
  if( pin == seq_hwcfg_button.clear )
755
    return SEQ_UI_Button_Clear(pin_value);
756
  if( pin == seq_hwcfg_button.undo )
757
    return SEQ_UI_Button_Undo(pin_value);
758
 
759
  if( pin == seq_hwcfg_button.master )
760
    return SEQ_UI_Button_Master(pin_value);
761
  if( pin == seq_hwcfg_button.tap_tempo )
762
    return SEQ_UI_Button_TapTempo(pin_value);
763
  if( pin == seq_hwcfg_button.stop )
764
    return SEQ_UI_Button_Stop(pin_value);
765
  if( pin == seq_hwcfg_button.play )
766
    return SEQ_UI_Button_Play(pin_value);
767
 
768
  if( pin == seq_hwcfg_button.pause )
769
    return SEQ_UI_Button_Pause(pin_value);
770
  if( pin == seq_hwcfg_button.metronome )
771
    return SEQ_UI_Button_Metronome(pin_value);
772
  if( pin == seq_hwcfg_button.ext_restart )
773
    return SEQ_UI_Button_ExtRestart(pin_value);
774
 
775
  if( pin == seq_hwcfg_button.trigger )
776
    return SEQ_UI_Button_TrackTrigger(pin_value);
777
  if( pin == seq_hwcfg_button.length )
778
    return SEQ_UI_Button_TrackLength(pin_value);
779
  if( pin == seq_hwcfg_button.progression )
780
    return SEQ_UI_Button_TrackProgression(pin_value);
781
  if( pin == seq_hwcfg_button.groove )
782
    return SEQ_UI_Button_TrackGroove(pin_value);
783
  if( pin == seq_hwcfg_button.echo )
784
    return SEQ_UI_Button_TrackEcho(pin_value);
785
  if( pin == seq_hwcfg_button.humanizer )
786
    return SEQ_UI_Button_TrackHumanizer(pin_value);
787
  if( pin == seq_hwcfg_button.lfo )
788
    return SEQ_UI_Button_TrackLFO(pin_value);
789
  if( pin == seq_hwcfg_button.scale )
790
    return SEQ_UI_Button_TrackScale(pin_value);
791
 
792
  if( pin == seq_hwcfg_button.mute )
793
    return SEQ_UI_Button_TrackMute(pin_value);
794
  if( pin == seq_hwcfg_button.midichn )
795
    return SEQ_UI_Button_TrackMidiChn(pin_value);
796
 
797
  if( pin == seq_hwcfg_button.rec_arm )
798
    return SEQ_UI_Button_RecArm(pin_value);
799
  if( pin == seq_hwcfg_button.rec_step )
800
    return SEQ_UI_Button_RecStep(pin_value);
801
  if( pin == seq_hwcfg_button.rec_live )
802
    return SEQ_UI_Button_RecLive(pin_value);
803
  if( pin == seq_hwcfg_button.rec_poly )
804
    return SEQ_UI_Button_RecPoly(pin_value);
805
  if( pin == seq_hwcfg_button.inout_fwd )
806
    return SEQ_UI_Button_InOutFwd(pin_value);
807
  if( pin == seq_hwcfg_button.transpose )
808
    return SEQ_UI_Button_TrackTranspose(pin_value);
809
 
810
  // always print debugging message
811
#if 1
812
  MUTEX_MIDIOUT_TAKE;
813
  DEBUG_MSG("[SEQ_UI_Button_Handler] Button SR:%d, Pin:%d not mapped, it has been %s.\n",
814
        (pin >> 3) + 1,
815
        pin & 7,
816
        pin_value ? "depressed" : "pressed");
817
  MUTEX_MIDIOUT_GIVE;
818
#endif
819
 
820
  return -1; // button not mapped
821
}
822
 
823
 
824
/////////////////////////////////////////////////////////////////////////////
825
// MIDI Remote Keyboard Function (called from SEQ_MIDI_IN)
826
/////////////////////////////////////////////////////////////////////////////
827
s32 SEQ_UI_REMOTE_MIDI_Keyboard(u8 key, u8 depressed)
828
{
829
#if 0
830
  MIOS32_MIDI_SendDebugMessage("SEQ_UI_REMOTE_MIDI_Keyboard(%d, %d)\n", key, depressed);
831
#endif
832
 
1723 tk 833
#if 1
1313 tk 834
  switch( key ) {
835
    case 0x24: // C-2
836
      return SEQ_UI_Button_GP(depressed, 0);
837
    case 0x25: // C#2
1723 tk 838
      return SEQ_UI_Button_Bar(depressed, 0);
1313 tk 839
    case 0x26: // D-2
840
      return SEQ_UI_Button_GP(depressed, 1);
841
    case 0x27: // D#2
1723 tk 842
      return SEQ_UI_Button_Bar(depressed, 1);
1313 tk 843
    case 0x28: // E-2
844
      return SEQ_UI_Button_GP(depressed, 2);
845
    case 0x29: // F-2
846
      return SEQ_UI_Button_GP(depressed, 3);
847
    case 0x2a: // F#2
1723 tk 848
      return SEQ_UI_Button_Bar(depressed, 2);
1313 tk 849
    case 0x2b: // G-2
850
      return SEQ_UI_Button_GP(depressed, 4);
851
    case 0x2c: // G#2
1723 tk 852
      return SEQ_UI_Button_Bar(depressed, 3);
1313 tk 853
    case 0x2d: // A-2
854
      return SEQ_UI_Button_GP(depressed, 5);
855
    case 0x2e: // A#2
1981 tk 856
      return SEQ_UI_Button_Seq(depressed, 0);
1313 tk 857
    case 0x2f: // B-2
858
      return SEQ_UI_Button_GP(depressed, 6);
859
 
860
    case 0x30: // C-3
861
      return SEQ_UI_Button_GP(depressed, 7);
862
    case 0x31: // C#3
1981 tk 863
      return SEQ_UI_Button_Seq(depressed, 1);
1313 tk 864
    case 0x32: // D-3
865
      return SEQ_UI_Button_GP(depressed, 8);
866
    case 0x33: // D#3
1723 tk 867
      return 0 ; //SEQ_UI_Button_ParLayer(depressed, 2);
1313 tk 868
    case 0x34: // E-3
869
      return SEQ_UI_Button_GP(depressed, 9);
870
    case 0x35: // F-3
871
      return SEQ_UI_Button_GP(depressed, 10);
872
    case 0x36: // F#3
1723 tk 873
      return SEQ_UI_Button_RecArm(depressed);
1313 tk 874
    case 0x37: // G-3
875
      return SEQ_UI_Button_GP(depressed, 11);
876
    case 0x38: // G#3
1723 tk 877
      return SEQ_UI_Button_RecStep(depressed);
1313 tk 878
    case 0x39: // A-3
879
      return SEQ_UI_Button_GP(depressed, 12);
880
    case 0x3a: // A#3
1723 tk 881
      return SEQ_UI_Button_RecLive(depressed);
1313 tk 882
    case 0x3b: // B-3
883
      return SEQ_UI_Button_GP(depressed, 13);
884
 
885
    case 0x3c: // C-4
886
      return SEQ_UI_Button_GP(depressed, 14);
887
    case 0x3d: // C#4
1723 tk 888
      return SEQ_UI_Button_Stop(depressed);
1313 tk 889
    case 0x3e: // D-4
890
      return SEQ_UI_Button_GP(depressed, 15);
891
    case 0x3f: // D#4
1723 tk 892
      return SEQ_UI_Button_Play(depressed);
1313 tk 893
    case 0x40: // E-4
894
      return 0; // ignore
895
    case 0x41: // F-4
1723 tk 896
      return SEQ_UI_Button_TrackTrigger(depressed);
1313 tk 897
    case 0x42: // F#4
1723 tk 898
      return SEQ_UI_Button_Load(depressed);
1313 tk 899
    case 0x43: // G-4
1723 tk 900
      return SEQ_UI_Button_TrackLength(depressed); //0; // ignore
1313 tk 901
    case 0x44: // G#4
1723 tk 902
      return SEQ_UI_Button_Save(depressed);
1313 tk 903
    case 0x45: // A-4
1723 tk 904
      return SEQ_UI_Button_TrackProgression(depressed);
1313 tk 905
    case 0x46: // A#4
1723 tk 906
      return SEQ_UI_Button_Copy(depressed);
1313 tk 907
    case 0x47: // B-4
1723 tk 908
      return SEQ_UI_Button_TrackGroove(depressed);
1313 tk 909
 
910
    case 0x48: // C-5
1723 tk 911
      return SEQ_UI_Button_TrackEcho(depressed);
1313 tk 912
    case 0x49: // C#5
1723 tk 913
      return SEQ_UI_Button_Paste(depressed);
1313 tk 914
    case 0x4a: // D-5
1723 tk 915
      return SEQ_UI_Button_TrackHumanizer(depressed);
1313 tk 916
    case 0x4b: // D#5
1723 tk 917
      return SEQ_UI_Button_Clear(depressed);
1313 tk 918
    case 0x4c: // E-5
1723 tk 919
      return SEQ_UI_Button_TrackLFO(depressed);
1313 tk 920
    case 0x4d: // F-5
1723 tk 921
      return SEQ_UI_Button_TrackScale(depressed);
1313 tk 922
    case 0x4e: // F#5
1723 tk 923
      return SEQ_UI_Button_Undo(depressed);
1313 tk 924
    case 0x4f: // G-5
1723 tk 925
      return SEQ_UI_Button_TrackMute(depressed);
1313 tk 926
    case 0x50: // G#5
1723 tk 927
      return SEQ_UI_Button_Master(depressed);
1313 tk 928
    case 0x51: // A-5
1723 tk 929
      return SEQ_UI_Button_TrackMidiChn(depressed);
1313 tk 930
    case 0x52: // A#5
1723 tk 931
      return SEQ_UI_Button_TapTempo(depressed);
1313 tk 932
    case 0x53: // B-5
1723 tk 933
      return SEQ_UI_Button_RecArm(depressed);
1313 tk 934
 
935
    case 0x54: // C-6
1723 tk 936
      return SEQ_UI_Button_RecStep(depressed);
1313 tk 937
    case 0x55: // C#6
1723 tk 938
      return SEQ_UI_Button_Stop(depressed);
1313 tk 939
    case 0x56: // D-6
1723 tk 940
      return SEQ_UI_Button_RecLive(depressed);
1313 tk 941
    case 0x57: // D#6
1723 tk 942
      return SEQ_UI_Button_Play(depressed);
1313 tk 943
    case 0x58: // E-6
1723 tk 944
      return SEQ_UI_Button_RecPoly(depressed);
1313 tk 945
    case 0x59: // F-6
1723 tk 946
      return SEQ_UI_Button_InOutFwd(depressed);
1313 tk 947
    case 0x5a: // F#6
948
      return 0; // ignore
949
    case 0x5b: // G-6
1723 tk 950
      return SEQ_UI_Button_TrackTranspose(depressed);
1313 tk 951
    case 0x5c: // G#6
1723 tk 952
      return 0; //SEQ_UI_Button_Select(depressed);
1313 tk 953
    case 0x5d: // A-6
1723 tk 954
      return 0 ; //SEQ_UI_Button_Exit(depressed);
1313 tk 955
    case 0x5e: // A#6
1723 tk 956
      return 0; //SEQ_UI_Button_Down(depressed);
1313 tk 957
    case 0x5f: // B-6
1723 tk 958
      return 0 ;// SEQ_UI_Button_Up(depressed);
1313 tk 959
  }
960
#endif
961
 
962
  return 0; // no error
963
}
964
 
965
 
966
/////////////////////////////////////////////////////////////////////////////
1345 tk 967
// Encoder handler
968
/////////////////////////////////////////////////////////////////////////////
969
s32 SEQ_UI_Encoder_Handler(u32 encoder, s32 incrementer)
970
{
971
  // send MIDI event in remote mode and exit
972
  if( seq_midi_sysex_remote_active_mode == SEQ_MIDI_SYSEX_REMOTE_MODE_CLIENT )
973
    return SEQ_MIDI_SYSEX_REMOTE_Client_SendEncoder(encoder, incrementer);
974
 
975
  // ignore as long as hardware config hasn't been read
976
  if( !SEQ_FILE_HW_ConfigLocked() || seq_file_backup_notification )
977
    return -1;
978
 
979
  // ignore during a backup or format is created
980
  //if( seq_ui_backup_req || seq_ui_format_req )
981
  //return -1;
982
 
983
  if( encoder >= SEQ_HWCFG_NUM_ENCODERS )
984
    return -1; // encoder doesn't exist
985
 
986
  // ensure that selections are matching with track constraints
987
  SEQ_UI_CheckSelections();
988
 
989
  // stop current message
990
  //SEQ_UI_MsgStop();
991
 
992
  // limit incrementer
993
  if( incrementer > 3 )
994
    incrementer = 3;
995
  else if( incrementer < -3 )
996
    incrementer = -3;
997
 
998
  // encoder 0 increments BPM
999
  if( encoder == 0 ) {
1000
    u16 value = (u16)(seq_core_bpm_preset_tempo[seq_core_bpm_preset_num]*10);
1001
    if( SEQ_UI_Var16_Inc(&value, 25, 3000, incrementer) ) { // at 384ppqn, the minimum BPM rate is ca. 2.5
1002
      // set new BPM
1003
      seq_core_bpm_preset_tempo[seq_core_bpm_preset_num] = (float)value/10.0;
1004
      SEQ_CORE_BPM_Update(seq_core_bpm_preset_tempo[seq_core_bpm_preset_num], seq_core_bpm_preset_ramp[seq_core_bpm_preset_num]);
1005
      //store_file_required = 1;
1006
      seq_ui_display_update_req = 1;      
1007
    }
1008
    return 0;
1009
  }
1010
 
1011
  return -1; // not mapped
1012
}
1013
 
1014
 
1015
 
1016
/////////////////////////////////////////////////////////////////////////////
1318 tk 1017
// Receives a MIDI package from APP_NotifyReceivedEvent (-> app.c)
1018
/////////////////////////////////////////////////////////////////////////////
1019
s32 SEQ_UI_REMOTE_MIDI_Receive(mios32_midi_port_t port, mios32_midi_package_t midi_package)
1020
{
1021
  return 0; // not relevant
1022
}
1023
 
1319 tk 1024
 
1318 tk 1025
/////////////////////////////////////////////////////////////////////////////
1319 tk 1026
// Called by BLM
1027
// Replacement for MBSEQV4L
1028
/////////////////////////////////////////////////////////////////////////////
1029
s32 SEQ_UI_EDIT_Button_Handler(u8 button, u8 depressed)
1030
{
1031
  u8 prev_page = ui_page;
1032
  ui_page = SEQ_UI_PAGE_TRIGGER;
1033
  SEQ_UI_PAGES_GP_Button_Handler(button, depressed);
1034
  ui_page = prev_page;
1035
  return 0; // no error
1036
}
1037
 
1038
 
1039
/////////////////////////////////////////////////////////////////////////////
1313 tk 1040
// Update all LEDs
1041
// Usually called from background task
1042
/////////////////////////////////////////////////////////////////////////////
1043
s32 SEQ_UI_LED_Handler(void)
1044
{
1322 tk 1045
  //u8 visible_track = SEQ_UI_VisibleTrackGet();
1313 tk 1046
 
1047
  // check if update requested
1390 tk 1048
  if( !seq_ui_display_update_req ) {
1049
    // update BLM LEDs
1050
    SEQ_BLM_LED_Update();
1051
 
1313 tk 1052
    return 0;
1390 tk 1053
  }
1313 tk 1054
  seq_ui_display_update_req = 0;
1055
 
1056
  // ignore as long as hardware config hasn't been read
1345 tk 1057
  if( !SEQ_FILE_HW_ConfigLocked() || seq_file_backup_notification )
1313 tk 1058
    return -1;
1059
 
1405 tk 1060
  u8 seq_running = SEQ_BPM_IsRunning() && (!seq_core_slaveclk_mute || ((seq_core_state.ref_step & 3) == 0));
1313 tk 1061
 
1405 tk 1062
  switch( ui_controller_mode ) {
1063
  case UI_CONTROLLER_MODE_OFF:
1064
    SEQ_LED_PinSet(seq_hwcfg_led.seq1, ui_selected_tracks & (1 << 0));
1065
    SEQ_LED_PinSet(seq_hwcfg_led.seq2, ui_selected_tracks & (1 << 8));
1313 tk 1066
 
1405 tk 1067
    SEQ_LED_PinSet(seq_hwcfg_led.load, ui_page == SEQ_UI_PAGE_LOAD);
1068
    SEQ_LED_PinSet(seq_hwcfg_led.save, ui_page == SEQ_UI_PAGE_SAVE);
1313 tk 1069
 
1405 tk 1070
    SEQ_LED_PinSet(seq_hwcfg_led.copy, seq_ui_button_state.COPY);
1071
    SEQ_LED_PinSet(seq_hwcfg_led.paste, seq_ui_button_state.PASTE);
1072
    SEQ_LED_PinSet(seq_hwcfg_led.clear, seq_ui_button_state.CLEAR);
1073
    SEQ_LED_PinSet(seq_hwcfg_led.undo, seq_ui_button_state.UNDO);
1074
 
1075
    SEQ_LED_PinSet(seq_hwcfg_led.rec_poly, seq_record_options.POLY_RECORD);
1076
    SEQ_LED_PinSet(seq_hwcfg_led.inout_fwd, seq_record_options.FWD_MIDI);
1077
    SEQ_LED_PinSet(seq_hwcfg_led.transpose, seq_core_global_transpose_enabled);
1078
    break;
1079
 
1080
  case UI_CONTROLLER_MODE_MAQ16_3:
1081
    // no special LED functions...
1082
    SEQ_LED_PinSet(seq_hwcfg_led.seq1, 0);
1083
    SEQ_LED_PinSet(seq_hwcfg_led.seq2, 0);
1084
 
1085
    SEQ_LED_PinSet(seq_hwcfg_led.load, 0);
1086
    SEQ_LED_PinSet(seq_hwcfg_led.save, 0);
1087
 
1088
    SEQ_LED_PinSet(seq_hwcfg_led.copy, 0);
1089
    SEQ_LED_PinSet(seq_hwcfg_led.paste, 0);
1090
    SEQ_LED_PinSet(seq_hwcfg_led.clear, 0);
1091
    SEQ_LED_PinSet(seq_hwcfg_led.undo, 0);
1092
 
1093
    SEQ_LED_PinSet(seq_hwcfg_led.rec_poly, 0);
1094
    SEQ_LED_PinSet(seq_hwcfg_led.inout_fwd, 0);
1095
    SEQ_LED_PinSet(seq_hwcfg_led.transpose, 0);
1096
    break;
1097
  }
1098
 
1336 tk 1099
  SEQ_LED_PinSet(seq_hwcfg_led.master, SEQ_BPM_IsMaster());
1100
  // SEQ_LED_PinSet(seq_hwcfg_led.tap_tempo, 0); // handled in SEQ_UI_LED_Handler_Periodic()
1101
  SEQ_LED_PinSet(seq_hwcfg_led.stop, 0);
1313 tk 1102
  // note: no bug: we added check for ref_step&3 for flashing the LEDs to give a sign of activity in slave mode with slaveclk_muted
1336 tk 1103
  SEQ_LED_PinSet(seq_hwcfg_led.play, seq_running);
1104
  SEQ_LED_PinSet(seq_hwcfg_led.stop, !seq_running && !ui_seq_pause);
1105
  SEQ_LED_PinSet(seq_hwcfg_led.pause, ui_seq_pause && !seq_core_slaveclk_mute);
1313 tk 1106
 
1336 tk 1107
  SEQ_LED_PinSet(seq_hwcfg_led.metronome, seq_core_state.METRONOME);
1108
  SEQ_LED_PinSet(seq_hwcfg_led.ext_restart, seq_core_state.EXT_RESTART_REQ);
1313 tk 1109
 
1405 tk 1110
  {
1111
    u8 flash = ui_controller_mode && ui_cursor_flash;
1112
    SEQ_LED_PinSet(seq_hwcfg_led.trigger, (!flash && ui_page == SEQ_UI_PAGE_TRIGGER) ? 1 : 0);
1113
    SEQ_LED_PinSet(seq_hwcfg_led.length, (!flash && ui_page == SEQ_UI_PAGE_LENGTH) ? 1 : 0);
1114
    SEQ_LED_PinSet(seq_hwcfg_led.progression, (!flash && ui_page == SEQ_UI_PAGE_PROGRESSION) ? 1 : 0);
1115
    SEQ_LED_PinSet(seq_hwcfg_led.groove, (!flash && ui_page == SEQ_UI_PAGE_GROOVE) ? 1 : 0);
1116
    SEQ_LED_PinSet(seq_hwcfg_led.echo, (!flash && ui_page == SEQ_UI_PAGE_ECHO) ? 1 : 0);
1117
    SEQ_LED_PinSet(seq_hwcfg_led.humanizer, (!flash && ui_page == SEQ_UI_PAGE_HUMANIZER) ? 1 : 0);
1118
    SEQ_LED_PinSet(seq_hwcfg_led.lfo, (!flash && ui_page == SEQ_UI_PAGE_LFO) ? 1 : 0);
1119
    SEQ_LED_PinSet(seq_hwcfg_led.scale, (!flash && ui_page == SEQ_UI_PAGE_SCALE) ? 1 : 0);
1120
    SEQ_LED_PinSet(seq_hwcfg_led.mute, (!flash && ui_page == SEQ_UI_PAGE_MUTE) ? 1 : 0);
1121
    SEQ_LED_PinSet(seq_hwcfg_led.midichn, (!flash && ui_page == SEQ_UI_PAGE_MIDICHN) ? 1 : 0);
1313 tk 1122
 
1405 tk 1123
    SEQ_LED_PinSet(seq_hwcfg_led.rec_arm, (!flash && ui_page == SEQ_UI_PAGE_REC_ARM) ? 1 : 0);
1124
    SEQ_LED_PinSet(seq_hwcfg_led.rec_step, (!flash && ui_page == SEQ_UI_PAGE_REC_STEP) ? 1 : 0);
1125
    SEQ_LED_PinSet(seq_hwcfg_led.rec_live, (!flash && ui_page == SEQ_UI_PAGE_REC_LIVE) ? 1 : 0);
1126
  }
1313 tk 1127
 
1390 tk 1128
  // update BLM LEDs
1129
  SEQ_BLM_LED_Update();
1130
 
1313 tk 1131
  return 0; // no error
1132
}
1133
 
1134
 
1135
/////////////////////////////////////////////////////////////////////////////
1136
// updates high-prio LED functions (GP LEDs and Beat LED)
1137
// called each mS
1138
/////////////////////////////////////////////////////////////////////////////
1139
s32 SEQ_UI_LED_Handler_Periodic()
1140
{
1345 tk 1141
  static u16 fx_ctr = 0;
1142
 
1313 tk 1143
  // ignore as long as hardware config hasn't been read
1345 tk 1144
  if( !SEQ_FILE_HW_ConfigLocked() || seq_file_backup_notification ) {
1145
    // stupid LED FX during power on as long as HWCFG hasn't been read
1146
    // just to give the user the message that something is going on (no LCD support...)
1147
    int delay = 33;
1148
    if( ++fx_ctr >= 32*delay )
1149
      fx_ctr = 0;
1150
 
1151
    int fx_state = fx_ctr / delay;
1152
    if( seq_file_backup_notification != NULL )
1153
      fx_state = (15 * seq_file_backup_percentage) / 100;
1154
 
1155
    if( fx_state < 16 ) {
1156
      u8 step = fx_state;
1157
      u8 mask_dot = (1 << (step & 7));
1158
      u8 mask_full = (1 << ((step & 7)+1))-1;
1159
      u8 left_half = step < 8;
1160
      u8 right_half = step >= 8;
1161
 
1162
      SEQ_LED_SRSet(0, left_half  ? mask_dot : 0x00);
1163
      SEQ_LED_SRSet(4, right_half ? mask_dot : 0x00);
1164
 
1165
      SEQ_LED_SRSet(1, left_half  ? mask_full : 0xff);
1166
      SEQ_LED_SRSet(2, left_half  ? mask_full : 0xff);
2399 tk 1167
 
1345 tk 1168
      SEQ_LED_SRSet(5, right_half ? mask_full : 0x00);
1169
      SEQ_LED_SRSet(6, right_half ? mask_full : 0x00);
1170
 
1171
      SEQ_LED_SRSet(3, left_half  ? mask_dot : 0x00);
1172
      SEQ_LED_SRSet(7, right_half ? mask_dot : 0x00);
1173
    } else {
1174
      u8 step = fx_state & 0xf;
1175
      u8 mask_dot = (1 << (7-(step & 7)));
1176
      u8 mask_full = ~((1 << (((step & 7))+1))-1);
1177
      u8 left_half = step >= 8;
1178
      u8 right_half = step < 8;
1179
 
1180
      SEQ_LED_SRSet(0, left_half  ? mask_dot : 0x00);
1181
      SEQ_LED_SRSet(4, right_half ? mask_dot : 0x00);
1182
 
1183
      SEQ_LED_SRSet(1, !left_half  ? mask_full : 0x00);
1184
      SEQ_LED_SRSet(2, !left_half  ? mask_full : 0x00);
2399 tk 1185
 
1345 tk 1186
      SEQ_LED_SRSet(5, !right_half ? mask_full : 0xff);
1187
      SEQ_LED_SRSet(6, !right_half ? mask_full : 0xff);
1188
 
1189
      SEQ_LED_SRSet(3, left_half  ? mask_dot : 0x00);
1190
      SEQ_LED_SRSet(7, right_half ? mask_dot : 0x00);
1191
    }
1192
 
1313 tk 1193
    return -1;
1345 tk 1194
  }
1195
 
1976 tk 1196
  // VU meters (used in MUTE menu, could also be available as LED matrix...)
1197
  static u8 vu_meter_prediv = 0; // predivider for VU meters
1198
 
1199
  if( ++vu_meter_prediv >= 16 ) { // NOTE: in distance to V4 (without L) increased from 4 to 16 for proper track activity state
1200
    vu_meter_prediv = 0;
1201
 
1202
 
1203
    portENTER_CRITICAL();
1204
 
1205
    ui_track_activity_state = 0x0000;
1206
    u8 track;
1207
    seq_core_trk_t *t = &seq_core_trk[0];
1208
    for(track=0; track<SEQ_CORE_NUM_TRACKS; ++t, ++track) {
1978 tk 1209
      // first three tracks of a SEQ are combined for note/velocity/length
1210
      u8 seq_track = track % 8;
1211
      if( seq_track == 0 ) {
1212
    if( t->state.SUSTAINED || t->state.STRETCHED_GL || SEQ_TRG_GateGet(track, t->step, 0) ) {
1213
      ui_track_activity_state |= (7 << track);
1214
    }
1215
      }
1216
 
1976 tk 1217
      if( t->vu_meter ) {
1218
    // Special V4L handling: convert VU meter into track activity indiciators
1219
    t->vu_meter = 0;
1220
 
1978 tk 1221
    if( seq_track <= 2 ) {
1222
      if( seq_track == 0 ) {
1223
        // temporary flicker via XOR
1224
        ui_track_activity_state ^= (7 << track);
1225
      }
1976 tk 1226
    } else {
1227
      ui_track_activity_state |= (1 << track);
1228
    }
1229
      }
1230
    }
1231
 
1232
    portEXIT_CRITICAL();
1233
  }
1234
 
1235
 
1313 tk 1236
  // GP LEDs are updated when ui_page_gp_leds has changed
1237
  static u16 prev_ui_page_gp_leds = 0x0000;
1238
  u16 ui_page_gp_leds = SEQ_UI_PAGES_GP_LED_Handler();
1239
 
1240
  // beat LED
1241
  u8 sequencer_running = SEQ_BPM_IsRunning();
1242
  u8 beat_led_on = sequencer_running && ((seq_core_state.ref_step & 3) == 0);
1422 tk 1243
  SEQ_LED_PinSet(seq_hwcfg_led.tap_tempo, (ui_page == SEQ_UI_PAGE_TEMPO) ? 1 : beat_led_on);
1313 tk 1244
 
1245
  // mirror to status LED (inverted, so that LED is normaly on)
1246
  MIOS32_BOARD_LED_Set(0xffffffff, beat_led_on ? 0 : 1);
1247
 
1248
  // don't continue if no new step has been generated and GP LEDs haven't changed
1249
  if( !seq_core_step_update_req && prev_ui_page_gp_leds == ui_page_gp_leds && sequencer_running && !tap_tempo_beat_ctr ) // sequencer running check: workaround - as long as sequencer not running, we won't get an step update request!
1250
    return 0;
1251
  seq_core_step_update_req = 0; // requested from SEQ_CORE if any step has been changed
1252
  prev_ui_page_gp_leds = ui_page_gp_leds; // take over new GP pattern
1253
 
1254
  // for song position marker (supports 16 LEDs, check for selected step view)
1255
  u16 pos_marker_mask = 0x0000;
1256
  u8 visible_track = SEQ_UI_VisibleTrackGet();
1257
  u8 played_step = seq_core_trk[visible_track].step;
1258
 
1259
  if( seq_core_slaveclk_mute != SEQ_CORE_SLAVECLK_MUTE_Enabled ) { // Off and OffOnNextMeasure
1260
    if( sequencer_running && (played_step >> 4) == ui_selected_step_view )
1261
      pos_marker_mask = 1 << (played_step & 0xf);
1262
  }
1263
 
1264
 
1265
  // follow step position if enabled
1266
  if( seq_core_state.FOLLOW ) {
1267
    u8 trk_step = seq_core_trk[visible_track].step;
1268
    if( (trk_step & 0xf0) != (16*ui_selected_step_view) ) {
1269
      ui_selected_step_view = trk_step / 16;
1270
      ui_selected_step = (ui_selected_step % 16) + 16*ui_selected_step_view;
1271
    }
1272
  }
1273
 
1274
  // transfer to GP LEDs
2399 tk 1275
  if( seq_hwcfg_led.pos_dout_l_sr )
1276
    SEQ_LED_SRSet(seq_hwcfg_led.gp_dout_l_sr-1, (ui_page_gp_leds >> 0) & 0xff);
1277
  else
1278
    SEQ_LED_SRSet(seq_hwcfg_led.gp_dout_l_sr-1, ((ui_page_gp_leds ^ pos_marker_mask) >> 0) & 0xff);
1313 tk 1279
 
2399 tk 1280
  if( seq_hwcfg_led.pos_dout_r_sr )
1281
    SEQ_LED_SRSet(seq_hwcfg_led.gp_dout_r_sr-1, (ui_page_gp_leds >> 8) & 0xff);
1282
  else
1283
    SEQ_LED_SRSet(seq_hwcfg_led.gp_dout_r_sr-1, ((ui_page_gp_leds ^ pos_marker_mask) >> 8) & 0xff);
1313 tk 1284
 
1285
 
1286
  // POS LEDs tap tempo overlay
1287
  u16 pos_overlay = 0x0000;
1288
  if( tap_tempo_beat_ctr ) {
1289
    if( tap_tempo_beat_ctr == 1 )
1290
      pos_overlay = 0x000f;
1291
    else if( tap_tempo_beat_ctr == 2 )
1292
      pos_overlay = 0x00ff;
1293
    else if( tap_tempo_beat_ctr == 3 )
1294
      pos_overlay = 0x0fff;
1295
    else
1296
      pos_overlay = 0xffff;
1297
  }
1298
 
1299
  // pos LEDs
1337 tk 1300
  SEQ_LED_SRSet(seq_hwcfg_led.pos_dout_l_sr-1, ((pos_marker_mask ^ pos_overlay) >> 0) & 0xff);
1301
  SEQ_LED_SRSet(seq_hwcfg_led.pos_dout_r_sr-1, ((pos_marker_mask ^ pos_overlay) >> 8) & 0xff);
1313 tk 1302
 
1303
  u8 bar1, bar2, bar3, bar4;
1304
 
1305
  if( ui_page == SEQ_UI_PAGE_LENGTH ) {
1306
    u8 length = SEQ_CC_Get(visible_track, SEQ_CC_LENGTH);
1307
    bar1 = 1;
1308
    bar2 = length >= 16;
1309
    bar3 = length >= 32;
1310
    bar4 = length >= 48;
1311
 
1312
    if( ui_cursor_flash ) {
1313
      if( ui_selected_step_view == 0 )
1314
    bar1 ^= 1;
1315
      else if( ui_selected_step_view == 1 )
1316
    bar2 ^= 1;
1317
      else if( ui_selected_step_view == 2 )
1318
    bar3 ^= 1;
1319
      else if( ui_selected_step_view == 3 )
1320
    bar4 ^= 1;
1321
    }
1322
  } else {
1323
    bar1 = ui_selected_step_view == 0;
1324
    bar2 = ui_selected_step_view == 1;
1325
    bar3 = ui_selected_step_view == 2;
1326
    bar4 = ui_selected_step_view == 3;
1327
 
1328
    if( beat_led_on ) {
1329
      if( played_step < 16 )
1330
    bar1 ^= 1;
1331
      else if( played_step < 32 )
1332
    bar2 ^= 1;
1333
      else if( played_step < 48 )
1334
    bar3 ^= 1;
1335
      else if( played_step < 64 )
1336
    bar4 ^= 1;
1337
    }
1338
  }
1339
 
1405 tk 1340
  switch( ui_controller_mode ) {
1341
  case UI_CONTROLLER_MODE_OFF:
1342
    SEQ_LED_PinSet(seq_hwcfg_led.bar1, bar1);
1343
    SEQ_LED_PinSet(seq_hwcfg_led.bar2, bar2);
1344
    SEQ_LED_PinSet(seq_hwcfg_led.bar3, bar3);
1345
    SEQ_LED_PinSet(seq_hwcfg_led.bar4, bar4);
1346
    break;
1347
 
1348
  case UI_CONTROLLER_MODE_MAQ16_3:
1349
    // no LED function defined...
1350
    SEQ_LED_PinSet(seq_hwcfg_led.bar1, 0);
1351
    SEQ_LED_PinSet(seq_hwcfg_led.bar2, 0);
1352
    SEQ_LED_PinSet(seq_hwcfg_led.bar3, 0);
1353
    SEQ_LED_PinSet(seq_hwcfg_led.bar4, 0);
1354
    break;
1355
  }
1356
 
1313 tk 1357
  return 0; // no error
1358
}
1359
 
1360
 
1361
/////////////////////////////////////////////////////////////////////////////
1868 tk 1362
// dummy-stub for MBSEQV4L
1363
// called each mS
1364
/////////////////////////////////////////////////////////////////////////////
1365
s32 SEQ_UI_LCD_Handler(void)
1366
{
1367
  return 0; // no error
1368
}
1369
 
1370
 
1371
/////////////////////////////////////////////////////////////////////////////
1313 tk 1372
// for menu handling (e.g. flashing cursor, doubleclick counter, etc...)
1373
// called each mS
1374
/////////////////////////////////////////////////////////////////////////////
1375
s32 SEQ_UI_MENU_Handler_Periodic()
1376
{
1377
  if( ++ui_cursor_flash_ctr >= SEQ_UI_CURSOR_FLASH_CTR_MAX ) {
1378
    ui_cursor_flash_ctr = 0;
1379
    ++ui_cursor_flash_overrun_ctr;
1380
    seq_ui_display_update_req = 1;
1381
  }
1382
 
1383
  // important: flash flag has to be recalculated on each invocation of this
1384
  // handler, since counter could also be reseted outside this function
1385
  u8 old_ui_cursor_flash = ui_cursor_flash;
1386
  ui_cursor_flash = ui_cursor_flash_ctr >= SEQ_UI_CURSOR_FLASH_CTR_LED_OFF;
1387
  if( old_ui_cursor_flash != ui_cursor_flash )
1388
    seq_ui_display_update_req = 1;
1389
 
1390
  return 0;
1391
}
1392
 
1393
 
1394
/////////////////////////////////////////////////////////////////////////////
1395
// Should be regulary called to check if the layer/instrument/step selection
1396
// is valid for the current track
1397
// At least executed before button/encoder and LCD function calls
1398
/////////////////////////////////////////////////////////////////////////////
1399
s32 SEQ_UI_CheckSelections(void)
1400
{
1401
  if( !ui_selected_tracks )
1402
    ui_selected_tracks = 0x00ff;
1403
 
1404
  return 0; // no error
1405
}
1406
 
1407
 
1408
/////////////////////////////////////////////////////////////////////////////
1409
// Returns the currently visible track
1410
/////////////////////////////////////////////////////////////////////////////
1411
u8 SEQ_UI_VisibleTrackGet(void)
1412
{
1413
  u8 track;
1414
  u16 mask = 1;
1415
  for(track=0; track<SEQ_CORE_NUM_TRACKS; ++track, mask<<=1)
1416
    if( ui_selected_tracks & mask )
1417
      return track;
1418
 
1419
  return 0; // first track
1420
}
1421
 
1422
 
1423
/////////////////////////////////////////////////////////////////////////////
1424
// Returns 1 if 'track' is selected
1425
/////////////////////////////////////////////////////////////////////////////
1426
s32 SEQ_UI_IsSelectedTrack(u8 track)
1427
{
1428
  return (ui_selected_tracks & (1 << track)) ? 1 : 0;
1429
}
1430
 
1431
 
1432
/////////////////////////////////////////////////////////////////////////////
1433
// Sets a new selected step and updates the step view
1434
/////////////////////////////////////////////////////////////////////////////
1435
s32 SEQ_UI_SelectedStepSet(u8 step)
1436
{
1437
  ui_selected_step = step;
1438
  SEQ_UI_CheckSelections();
1439
 
1440
  return 0; // no error
1441
}
1442
 
1443
 
1444
/////////////////////////////////////////////////////////////////////////////
1445
// Sets a CC value on all selected tracks
1446
// OUT: 1 if value has been changed, otherwise 0
1447
/////////////////////////////////////////////////////////////////////////////
1448
s32 SEQ_UI_CC_Set(u8 cc, u8 value)
1449
{
1450
  u8 visible_track = SEQ_UI_VisibleTrackGet();
1451
  int prev_value = SEQ_CC_Get(visible_track, cc);
1452
 
1453
  if( value == prev_value )
1454
    return 0; // no change
1455
 
1456
  SEQ_CC_Set(visible_track, cc, value);
1457
 
1458
  // set same value for all selected tracks
1459
  u8 track;
1460
  for(track=0; track<SEQ_CORE_NUM_TRACKS; ++track)
1461
    if( track != visible_track && SEQ_UI_IsSelectedTrack(track) )
1462
      SEQ_CC_Set(track, cc, value);
1463
 
1464
  return 1; // value changed
1465
}
1466
 
1467
/////////////////////////////////////////////////////////////////////////////
1468
// Modifies a bitfield in a CC value to a given value
1469
// OUT: 1 if value has been changed, otherwise 0
1470
/////////////////////////////////////////////////////////////////////////////
1471
s32 SEQ_UI_CC_SetFlags(u8 cc, u8 flag_mask, u8 value)
1472
{
1473
  u8 visible_track = SEQ_UI_VisibleTrackGet();
1474
  int new_value = SEQ_CC_Get(visible_track, cc);
1475
  int prev_value = new_value;
1476
 
1477
  new_value = (new_value & ~flag_mask) | value;
1478
 
1479
  if( new_value == prev_value )
1480
    return 0; // no change
1481
 
1482
  SEQ_CC_Set(visible_track, cc, new_value);
1483
 
1484
  // do same modification for all selected tracks
1485
  u8 track;
1486
  for(track=0; track<SEQ_CORE_NUM_TRACKS; ++track)
1487
    if( track != visible_track && SEQ_UI_IsSelectedTrack(track) ) {
1488
      int new_value = SEQ_CC_Get(track, cc);
1489
      new_value = (new_value & ~flag_mask) | value;
1490
      SEQ_CC_Set(track, cc, new_value);
1491
    }
1492
 
1493
  return 1; // value changed
1494
}
1316 tk 1495
 
1496
 
1497
/////////////////////////////////////////////////////////////////////////////
1498
// Prints a temporary error messages after file operation
1499
// Expects error status number (as defined in seq_file.h)
1500
/////////////////////////////////////////////////////////////////////////////
1501
s32 SEQ_UI_SDCardErrMsg(u16 delay, s32 status)
1502
{
1503
  // send error message to MIOS terminal
1504
  MUTEX_MIDIOUT_TAKE;
1505
  FILE_SendErrorMessage(status);
1506
  MUTEX_MIDIOUT_GIVE;
1507
 
1508
#if 0
1509
  // print on LCD
1510
  char str[21];
1511
  sprintf(str, "E%3d (FatFs: D%3d)", -status, file_dfs_errno < 1000 ? file_dfs_errno : 999);
1512
  return SEQ_UI_Msg(SEQ_UI_MSG_SDCARD, delay, "!! SD Card Error !!!", str);
1513
#else
1514
  return 0;
1515
#endif
1516
}
1319 tk 1517
 
1518
 
1519
/////////////////////////////////////////////////////////////////////////////
1345 tk 1520
// Increments a 16bit variable within given min/max range
1521
// OUT: 1 if value has been changed, otherwise 0
1522
/////////////////////////////////////////////////////////////////////////////
1523
s32 SEQ_UI_Var16_Inc(u16 *value, u16 min, u16 max, s32 incrementer)
1524
{
1525
  int new_value = *value;
1526
  int prev_value = new_value;
1527
 
1528
  // extra: in fast mode increment 16bit values faster!
1529
  if( max > 0x100 && (seq_ui_button_state.FAST_ENCODERS || seq_ui_button_state.FAST2_ENCODERS) )
1530
    incrementer *= 10;
1531
 
1532
  if( incrementer >= 0 ) {
1533
    if( (new_value += incrementer) >= max )
1534
      new_value = max;
1535
  } else {
1536
    if( (new_value += incrementer) < min )
1537
      new_value = min;
1538
  }
1539
 
1540
  if( new_value == prev_value )
1541
    return 0; // no change
1542
 
1543
  *value = new_value;
1544
 
1545
  return 1; // value changed
1546
}
1547
 
1548
/////////////////////////////////////////////////////////////////////////////
1549
// Increments an 8bit variable within given min/max range
1550
// OUT: 1 if value has been changed, otherwise 0
1551
/////////////////////////////////////////////////////////////////////////////
1552
s32 SEQ_UI_Var8_Inc(u8 *value, u16 min, u16 max, s32 incrementer)
1553
{
1554
  u16 tmp = *value;
1555
  if( SEQ_UI_Var16_Inc(&tmp, min, max, incrementer) ) {
1556
    *value = tmp;
1557
    return 1; // value changed
1558
  }
1559
 
1560
  return 0; // value hasn't been changed
1561
}
1562
 
1563
/////////////////////////////////////////////////////////////////////////////
1319 tk 1564
// stores a bookmark
1565
/////////////////////////////////////////////////////////////////////////////
1566
s32 SEQ_UI_Bookmark_Store(u8 bookmark)
1567
{
1568
  if( bookmark >= SEQ_UI_BOOKMARKS_NUM )
1569
    return -1;
1570
 
1571
  //seq_ui_bookmark_t *bm = (seq_ui_bookmark_t *)&seq_ui_bookmarks[bookmark];
1572
 
1573
  return -1; // not supported by MBSEQV4L
1574
}
1575
 
1576
/////////////////////////////////////////////////////////////////////////////
1577
// restores a bookmark
1578
/////////////////////////////////////////////////////////////////////////////
1579
s32 SEQ_UI_Bookmark_Restore(u8 bookmark)
1580
{
1581
  if( bookmark >= SEQ_UI_BOOKMARKS_NUM )
1582
    return -1;
1583
 
1584
  //seq_ui_bookmark_t *bm = (seq_ui_bookmark_t *)&seq_ui_bookmarks[bookmark];
1585
 
1586
  return -1; // not supported by MBSEQV4L
1587
}