Subversion Repositories svn.mios32

Rev

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

Rev Author Line No. Line
134 tk 1
// $Id: seq_ui.c 496 2009-05-07 21:31:48Z tk $
2
/*
3
 * User Interface Routines
4
 *
336 tk 5
 * TODO: allow to loop the selected view while editing a track
6
 * TODO: add loop fx page for setting loop point interactively
7
 * TODO: scroll function should use this loop point
8
 * TODO: utility page in drum mode: allow to handle only selected instrument
9
 *
134 tk 10
 * ==========================================================================
11
 *
12
 *  Copyright (C) 2008 Thorsten Klose (tk@midibox.org)
13
 *  Licensed for personal non-commercial use only.
14
 *  All other rights reserved.
15
 *
16
 * ==========================================================================
17
 */
18
 
19
/////////////////////////////////////////////////////////////////////////////
20
// Include files
21
/////////////////////////////////////////////////////////////////////////////
22
 
272 tk 23
// with this switch, seq_ui.h/seq_ui_pages.inc will create local variables
24
#define SEQ_UI_PAGES_INC_LOCAL_VARS 1
25
 
134 tk 26
#include <mios32.h>
299 tk 27
#include <string.h>
464 tk 28
#include <blm_x.h>
190 tk 29
#include <seq_midi_out.h>
30
#include <seq_bpm.h>
134 tk 31
 
290 tk 32
#include "tasks.h"
134 tk 33
#include "seq_ui.h"
492 tk 34
#include "seq_hwcfg.h"
134 tk 35
#include "seq_lcd.h"
36
#include "seq_led.h"
186 tk 37
#include "seq_midply.h"
134 tk 38
#include "seq_core.h"
399 tk 39
#include "seq_song.h"
333 tk 40
#include "seq_par.h"
178 tk 41
#include "seq_layer.h"
184 tk 42
#include "seq_cc.h"
299 tk 43
#include "seq_file.h"
134 tk 44
 
45
 
46
/////////////////////////////////////////////////////////////////////////////
47
// Global variables
48
/////////////////////////////////////////////////////////////////////////////
49
 
159 tk 50
u8 seq_ui_display_update_req;
51
u8 seq_ui_display_init_req;
134 tk 52
 
167 tk 53
seq_ui_button_state_t seq_ui_button_state;
54
 
134 tk 55
u8 ui_selected_group;
484 tk 56
u16 ui_selected_tracks;
134 tk 57
u8 ui_selected_par_layer;
58
u8 ui_selected_trg_layer;
328 tk 59
u8 ui_selected_instrument;
134 tk 60
u8 ui_selected_step_view;
61
u8 ui_selected_step;
168 tk 62
u8 ui_selected_item;
134 tk 63
 
168 tk 64
u8 ui_selected_item;
134 tk 65
 
240 tk 66
u16 ui_hold_msg_ctr;
67
 
206 tk 68
seq_ui_page_t ui_page;
272 tk 69
seq_ui_page_t ui_selected_page;
303 tk 70
seq_ui_page_t ui_stepview_prev_page;
326 tk 71
seq_ui_page_t ui_trglayer_prev_page;
72
seq_ui_page_t ui_parlayer_prev_page;
206 tk 73
 
173 tk 74
volatile u8 ui_cursor_flash;
75
u16 ui_cursor_flash_ctr;
134 tk 76
 
316 tk 77
u8 ui_edit_name_cursor;
78
u8 ui_edit_preset_num_category;
79
u8 ui_edit_preset_num_label;
80
 
193 tk 81
u8 ui_seq_pause;
82
 
83
 
134 tk 84
/////////////////////////////////////////////////////////////////////////////
85
// Local variables
86
/////////////////////////////////////////////////////////////////////////////
87
 
168 tk 88
static s32 (*ui_button_callback)(seq_ui_button_t button, s32 depressed);
89
static s32 (*ui_encoder_callback)(seq_ui_encoder_t encoder, s32 incrementer);
173 tk 90
static s32 (*ui_led_callback)(u16 *gp_leds);
167 tk 91
static s32 (*ui_lcd_callback)(u8 high_prio);
352 tk 92
static s32 (*ui_exit_callback)(void);
167 tk 93
 
168 tk 94
static u16 ui_gp_leds;
167 tk 95
 
299 tk 96
#define SDCARD_MSG_MAX_CHAR 21
97
static char sdcard_msg[2][SDCARD_MSG_MAX_CHAR];
98
static u16 sdcard_msg_ctr;
99
 
100
 
134 tk 101
/////////////////////////////////////////////////////////////////////////////
102
// Initialisation
103
/////////////////////////////////////////////////////////////////////////////
104
s32 SEQ_UI_Init(u32 mode)
105
{
106
  // init selection variables
107
  ui_selected_group = 0;
108
  ui_selected_tracks = (1 << 0);
109
  ui_selected_par_layer = 0;
110
  ui_selected_trg_layer = 0;
328 tk 111
  ui_selected_instrument = 0;
134 tk 112
  ui_selected_step_view = 0;
113
  ui_selected_step = 0;
168 tk 114
  ui_selected_item = 0;
134 tk 115
 
240 tk 116
  ui_hold_msg_ctr = 0;
299 tk 117
  sdcard_msg_ctr = 0;
240 tk 118
 
168 tk 119
  ui_cursor_flash_ctr = 0;
173 tk 120
  ui_cursor_flash = 0;
168 tk 121
 
167 tk 122
  seq_ui_button_state.ALL = 0;
123
 
193 tk 124
  ui_seq_pause = 0;
125
 
134 tk 126
  // visible GP pattern
127
  ui_gp_leds = 0x0000;
128
 
167 tk 129
  // change to edit page
130
  ui_page = SEQ_UI_PAGE_NONE;
131
  SEQ_UI_PageSet(SEQ_UI_PAGE_EDIT);
134 tk 132
 
133
  return 0; // no error
134
}
135
 
136
 
137
/////////////////////////////////////////////////////////////////////////////
178 tk 138
// Inits the speed mode of all encoders
139
// Auto mode should be used whenever:
140
//    - the edit screen is entered
141
//    - the group is changed
142
//    - a track is changed
143
//    - a layer is changed
144
/////////////////////////////////////////////////////////////////////////////
145
s32 SEQ_UI_InitEncSpeed(u32 auto_config)
146
{
147
  mios32_enc_config_t enc_config;
148
 
149
  if( auto_config ) {
150
#if DEFAULT_AUTO_FAST_BUTTON
333 tk 151
    switch( SEQ_PAR_AssignmentGet(SEQ_UI_VisibleTrackGet(), ui_selected_par_layer) ) {
152
      case SEQ_PAR_Type_Velocity:
153
      case SEQ_PAR_Type_Length:
154
      case SEQ_PAR_Type_CC:
155
      case SEQ_PAR_Type_PitchBend:
156
      case SEQ_PAR_Type_Probability:
157
      case SEQ_PAR_Type_Delay:
158
      case SEQ_PAR_Type_Loopback:
178 tk 159
    seq_ui_button_state.FAST_ENCODERS = 1;
160
    break;
161
 
162
      default:
163
    seq_ui_button_state.FAST_ENCODERS = 0;
164
    }
165
#else
166
    // auto mode not enabled - ignore auto reconfiguration request
167
    return 0;
168
#endif
169
  }
170
 
171
  // change for datawheel and GP encoders
172
  int enc;
173
  for(enc=0; enc<17; ++enc) {
174
    enc_config = MIOS32_ENC_ConfigGet(enc);
175
    enc_config.cfg.speed = seq_ui_button_state.FAST_ENCODERS ? FAST : NORMAL;
176
    enc_config.cfg.speed_par = (enc == 0) ? DEFAULT_DATAWHEEL_SPEED_VALUE : DEFAULT_ENC_SPEED_VALUE;
177
    MIOS32_ENC_ConfigSet(enc, enc_config);
178
  }
179
 
180
  return 0; // no error
181
}
182
 
183
 
184
/////////////////////////////////////////////////////////////////////////////
167 tk 185
// Various installation routines for menu page LCD handlers
186
/////////////////////////////////////////////////////////////////////////////
168 tk 187
s32 SEQ_UI_InstallButtonCallback(void *callback)
167 tk 188
{
168 tk 189
  ui_button_callback = callback;
167 tk 190
  return 0; // no error
191
}
192
 
168 tk 193
s32 SEQ_UI_InstallEncoderCallback(void *callback)
167 tk 194
{
168 tk 195
  ui_encoder_callback = callback;
167 tk 196
  return 0; // no error
197
}
198
 
168 tk 199
s32 SEQ_UI_InstallLEDCallback(void *callback)
167 tk 200
{
168 tk 201
  ui_led_callback = callback;
167 tk 202
  return 0; // no error
203
}
204
 
168 tk 205
s32 SEQ_UI_InstallLCDCallback(void *callback)
167 tk 206
{
207
  ui_lcd_callback = callback;
208
  return 0; // no error
209
}
210
 
352 tk 211
s32 SEQ_UI_InstallExitCallback(void *callback)
212
{
213
  ui_exit_callback = callback;
214
  return 0; // no error
215
}
167 tk 216
 
352 tk 217
 
167 tk 218
/////////////////////////////////////////////////////////////////////////////
219
// Change the menu page
220
/////////////////////////////////////////////////////////////////////////////
221
s32 SEQ_UI_PageSet(seq_ui_page_t page)
222
{
223
  if( page != ui_page ) {
352 tk 224
 
225
    // call page exit callback
226
    if( ui_exit_callback != NULL )
227
      ui_exit_callback();
228
 
167 tk 229
    // disable hooks of previous page and request re-initialisation
318 tk 230
    portENTER_CRITICAL();
167 tk 231
    ui_page = page;
168 tk 232
    ui_button_callback = NULL;
233
    ui_encoder_callback = NULL;
234
    ui_led_callback = NULL;
167 tk 235
    ui_lcd_callback = NULL;
352 tk 236
    ui_exit_callback = NULL;
318 tk 237
    portEXIT_CRITICAL();
167 tk 238
 
178 tk 239
#if DEFAULT_BEHAVIOUR_BUTTON_MENU
168 tk 240
    seq_ui_button_state.MENU_PRESSED = 0; // MENU page selection finished
167 tk 241
#endif
242
 
243
    // request display initialisation
244
    seq_ui_display_init_req = 1;
245
  }
173 tk 246
 
306 tk 247
  // for MENU button:
248
  // first page has been selected - display new screen
249
  seq_ui_button_state.MENU_FIRST_PAGE_SELECTED = 1;
250
 
272 tk 251
  // for SEQ_UI_MENU which is accessible with EXIT button
252
  // remember the current selectable page
253
  if( ui_page >= SEQ_UI_FIRST_MENU_SELECTION_PAGE )
254
    ui_selected_page = ui_page;
255
 
184 tk 256
  return 0; // no error
167 tk 257
}
258
 
259
 
260
/////////////////////////////////////////////////////////////////////////////
272 tk 261
// Returns name of menu page (18 characters)
262
/////////////////////////////////////////////////////////////////////////////
263
char *SEQ_UI_PageNameGet(seq_ui_page_t page)
264
{
265
  return ui_menu_pages[page].name;
266
}
267
 
268
 
269
/////////////////////////////////////////////////////////////////////////////
134 tk 270
// Dedicated button functions
271
// Mapped to physical buttons in SEQ_UI_Button_Handler()
272
// Will also be mapped to MIDI keys later (for MIDI remote function)
273
/////////////////////////////////////////////////////////////////////////////
274
static s32 SEQ_UI_Button_GP(s32 depressed, u32 gp)
275
{
306 tk 276
  // in MENU page: overrule GP buttons so long MENU button is pressed/active
277
  if( seq_ui_button_state.MENU_PRESSED ) {
278
    if( depressed ) return -1;
279
    SEQ_UI_PageSet(ui_shortcut_menu_pages[gp]);
280
  } else {
281
    // forward to menu page
282
    if( ui_button_callback != NULL )
283
      ui_button_callback(gp, depressed);
284
    ui_cursor_flash_ctr = 0;
285
  }
134 tk 286
 
287
  return 0; // no error
288
}
289
 
290
static s32 SEQ_UI_Button_Left(s32 depressed)
291
{
168 tk 292
  // forward to menu page
306 tk 293
  if( !seq_ui_button_state.MENU_PRESSED && ui_button_callback != NULL )
168 tk 294
    ui_button_callback(SEQ_UI_BUTTON_Left, depressed);
173 tk 295
  ui_cursor_flash_ctr = 0;
134 tk 296
 
297
  return 0; // no error
298
}
299
 
300
static s32 SEQ_UI_Button_Right(s32 depressed)
301
{
168 tk 302
  // forward to menu page
306 tk 303
  if( !seq_ui_button_state.MENU_PRESSED && ui_button_callback != NULL )
168 tk 304
    ui_button_callback(SEQ_UI_BUTTON_Right, depressed);
173 tk 305
  ui_cursor_flash_ctr = 0;
134 tk 306
 
307
  return 0; // no error
308
}
309
 
168 tk 310
static s32 SEQ_UI_Button_Down(s32 depressed)
311
{
240 tk 312
  seq_ui_button_state.DOWN = depressed ? 0 : 1;
313
 
168 tk 314
  // forward to menu page
306 tk 315
  if( !seq_ui_button_state.MENU_PRESSED && ui_button_callback != NULL )
168 tk 316
    ui_button_callback(SEQ_UI_BUTTON_Down, depressed);
173 tk 317
  ui_cursor_flash_ctr = 0;
168 tk 318
 
319
  return 0; // no error
320
}
321
 
322
static s32 SEQ_UI_Button_Up(s32 depressed)
323
{
240 tk 324
  seq_ui_button_state.UP = depressed ? 0 : 1;
325
 
168 tk 326
  // forward to menu page
306 tk 327
  if( !seq_ui_button_state.MENU_PRESSED && ui_button_callback != NULL )
168 tk 328
    ui_button_callback(SEQ_UI_BUTTON_Up, depressed);
173 tk 329
  ui_cursor_flash_ctr = 0;
168 tk 330
 
331
  return 0; // no error
332
}
333
 
134 tk 334
static s32 SEQ_UI_Button_Scrub(s32 depressed)
335
{
178 tk 336
#if DEFAULT_BEHAVIOUR_BUTTON_SCRUB
337
  // toggle mode
134 tk 338
  if( depressed ) return -1; // ignore when button depressed
178 tk 339
  seq_ui_button_state.SCRUB ^= 1;
137 tk 340
#else
178 tk 341
  // set mode
342
  seq_ui_button_state.SCRUB = depressed ? 0 : 1;
137 tk 343
#endif
344
 
134 tk 345
  return 0; // no error
346
}
347
 
348
static s32 SEQ_UI_Button_Metronome(s32 depressed)
349
{
178 tk 350
#if DEFAULT_BEHAVIOUR_BUTTON_METRON
351
  // toggle mode
134 tk 352
  if( depressed ) return -1; // ignore when button depressed
178 tk 353
  seq_ui_button_state.METRONOME ^= 1;
338 tk 354
#else
178 tk 355
  // set mode
356
  seq_ui_button_state.METRONOME = depressed ? 0 : 1;
137 tk 357
#endif
134 tk 358
 
359
  return 0; // no error
360
}
361
 
362
static s32 SEQ_UI_Button_Stop(s32 depressed)
363
{
364
  if( depressed ) return -1; // ignore when button depressed
365
 
159 tk 366
  // if sequencer running: stop it
367
  // if sequencer already stopped: reset song position
186 tk 368
#if MID_PLAYER_TEST
193 tk 369
  if( SEQ_BPM_IsRunning() )
370
    SEQ_BPM_Stop();
186 tk 371
  else
372
    SEQ_MIDPLY_Reset();
373
#else
193 tk 374
  if( SEQ_BPM_IsRunning() )
375
    SEQ_BPM_Stop();
159 tk 376
  else
377
    SEQ_CORE_Reset();
186 tk 378
#endif
159 tk 379
 
134 tk 380
  return 0; // no error
381
}
382
 
383
static s32 SEQ_UI_Button_Pause(s32 depressed)
384
{
385
  if( depressed ) return -1; // ignore when button depressed
386
 
193 tk 387
  // if in auto mode and BPM generator is clocked in slave mode:
388
  // change to master mode
389
  SEQ_BPM_CheckAutoMaster();
159 tk 390
 
193 tk 391
  // toggle pause mode
392
  ui_seq_pause ^= 1;
393
 
394
  // execute stop/continue depending on new mode
395
  if( ui_seq_pause )
396
    SEQ_BPM_Stop();
397
  else
398
    SEQ_BPM_Cont();
399
 
134 tk 400
  return 0; // no error
401
}
402
 
403
static s32 SEQ_UI_Button_Play(s32 depressed)
404
{
405
  if( depressed ) return -1; // ignore when button depressed
406
 
186 tk 407
  // if in auto mode and BPM generator is clocked in slave mode:
408
  // change to master mode
409
  SEQ_BPM_CheckAutoMaster();
410
 
193 tk 411
#if 0
412
  // if sequencer running: restart it
413
  // if sequencer stopped: continue at last song position
414
  if( SEQ_BPM_IsRunning() )
415
    SEQ_BPM_Start();
416
  else
417
    SEQ_BPM_Cont();
186 tk 418
#else
193 tk 419
  // always restart sequencer
420
  SEQ_BPM_Start();
186 tk 421
#endif
159 tk 422
 
134 tk 423
  return 0; // no error
424
}
425
 
426
static s32 SEQ_UI_Button_Rew(s32 depressed)
427
{
240 tk 428
  seq_ui_button_state.REW = depressed ? 0 : 1;
429
 
134 tk 430
  if( depressed ) return -1; // ignore when button depressed
431
 
432
  return 0; // no error
433
}
434
 
435
static s32 SEQ_UI_Button_Fwd(s32 depressed)
436
{
240 tk 437
  seq_ui_button_state.FWD = depressed ? 0 : 1;
438
 
134 tk 439
  if( depressed ) return -1; // ignore when button depressed
440
 
441
  return 0; // no error
442
}
443
 
444
static s32 SEQ_UI_Button_F1(s32 depressed)
445
{
240 tk 446
  seq_ui_button_state.F1 = depressed ? 0 : 1;
447
 
134 tk 448
  if( depressed ) return -1; // ignore when button depressed
449
 
240 tk 450
  // change to utility page
451
  SEQ_UI_PageSet(SEQ_UI_PAGE_UTIL);
452
 
134 tk 453
  return 0; // no error
454
}
455
 
456
static s32 SEQ_UI_Button_F2(s32 depressed)
457
{
240 tk 458
  seq_ui_button_state.F2 = depressed ? 0 : 1;
459
 
134 tk 460
  if( depressed ) return -1; // ignore when button depressed
461
 
462
  return 0; // no error
463
}
464
 
465
static s32 SEQ_UI_Button_F3(s32 depressed)
466
{
240 tk 467
  seq_ui_button_state.F3 = depressed ? 0 : 1;
468
 
134 tk 469
  if( depressed ) return -1; // ignore when button depressed
470
 
471
  return 0; // no error
472
}
473
 
474
static s32 SEQ_UI_Button_F4(s32 depressed)
475
{
240 tk 476
  seq_ui_button_state.F4 = depressed ? 0 : 1;
477
 
134 tk 478
  if( depressed ) return -1; // ignore when button depressed
479
 
480
  return 0; // no error
481
}
482
 
483
static s32 SEQ_UI_Button_Utility(s32 depressed)
484
{
485
  if( depressed ) return -1; // ignore when button depressed
486
 
240 tk 487
  // change to utility page
488
  SEQ_UI_PageSet(SEQ_UI_PAGE_UTIL);
489
 
134 tk 490
  return 0; // no error
491
}
492
 
493
static s32 SEQ_UI_Button_Copy(s32 depressed)
494
{
240 tk 495
  static seq_ui_page_t prev_page = SEQ_UI_PAGE_NONE;
134 tk 496
 
240 tk 497
  seq_ui_button_state.COPY = depressed ? 0 : 1;
498
 
280 tk 499
  if( ui_page == SEQ_UI_PAGE_MIXER ) {
500
    if( depressed ) return -1;
501
    SEQ_UI_MIXER_Copy();
502
    return 1;
503
  } else {
504
    if( !depressed ) {
505
      prev_page = ui_page;
506
      SEQ_UI_PageSet(SEQ_UI_PAGE_UTIL);
507
    }
240 tk 508
 
280 tk 509
    s32 status = SEQ_UI_UTIL_CopyButton(depressed);
240 tk 510
 
280 tk 511
    if( depressed )
512
      SEQ_UI_PageSet(prev_page);
240 tk 513
 
280 tk 514
    return status;
515
  }
134 tk 516
}
517
 
518
static s32 SEQ_UI_Button_Paste(s32 depressed)
519
{
240 tk 520
  static seq_ui_page_t prev_page = SEQ_UI_PAGE_NONE;
134 tk 521
 
240 tk 522
  seq_ui_button_state.PASTE = depressed ? 0 : 1;
523
 
280 tk 524
  if( ui_page == SEQ_UI_PAGE_MIXER ) {
525
    if( depressed ) return -1;
526
    SEQ_UI_MIXER_Paste();
527
    return 1;
528
  } else {
529
    if( !depressed ) {
530
      prev_page = ui_page;
531
      SEQ_UI_PageSet(SEQ_UI_PAGE_UTIL);
532
    }
240 tk 533
 
280 tk 534
    s32 status = SEQ_UI_UTIL_PasteButton(depressed);
240 tk 535
 
280 tk 536
    if( depressed )
537
      SEQ_UI_PageSet(prev_page);
240 tk 538
 
280 tk 539
    return status;
540
  }
134 tk 541
}
542
 
543
static s32 SEQ_UI_Button_Clear(s32 depressed)
544
{
240 tk 545
  seq_ui_button_state.CLEAR = depressed ? 0 : 1;
280 tk 546
 
547
  if( ui_page == SEQ_UI_PAGE_MIXER ) {
548
    if( depressed ) return -1;
549
    SEQ_UI_MIXER_Clear();
550
    return 1;
551
  } else {
552
    return SEQ_UI_UTIL_ClearButton(depressed);
553
  }
134 tk 554
}
555
 
556
static s32 SEQ_UI_Button_Menu(s32 depressed)
557
{
167 tk 558
  // TODO: define generic #define for this button behaviour
178 tk 559
#if DEFAULT_BEHAVIOUR_BUTTON_MENU
560
  // toggle mode
134 tk 561
  if( depressed ) return -1; // ignore when button depressed
306 tk 562
  seq_ui_button_state.MENU_FIRST_PAGE_SELECTED = 0;
167 tk 563
  seq_ui_button_state.MENU_PRESSED ^= 1; // toggle MENU pressed (will also be released once GP button has been pressed)
564
#else
178 tk 565
  // set mode
306 tk 566
  seq_ui_button_state.MENU_FIRST_PAGE_SELECTED = 0;
167 tk 567
  seq_ui_button_state.MENU_PRESSED = depressed ? 0 : 1;
568
#endif
134 tk 569
 
570
  return 0; // no error
571
}
572
 
573
static s32 SEQ_UI_Button_Select(s32 depressed)
574
{
168 tk 575
  // forward to menu page
306 tk 576
  if( !seq_ui_button_state.MENU_PRESSED && ui_button_callback != NULL )
168 tk 577
    ui_button_callback(SEQ_UI_BUTTON_Select, depressed);
173 tk 578
  ui_cursor_flash_ctr = 0;
134 tk 579
 
580
  return 0; // no error
581
}
582
 
583
static s32 SEQ_UI_Button_Exit(s32 depressed)
584
{
272 tk 585
  if( depressed ) return -1; // ignore when button depressed
586
 
587
  u8 prev_ui_page = ui_page;
588
 
168 tk 589
  // forward to menu page
306 tk 590
  if( !seq_ui_button_state.MENU_PRESSED && ui_button_callback != NULL )
168 tk 591
    ui_button_callback(SEQ_UI_BUTTON_Exit, depressed);
173 tk 592
  ui_cursor_flash_ctr = 0;
134 tk 593
 
167 tk 594
  // release all button states
595
  seq_ui_button_state.ALL = 0;
596
 
272 tk 597
  // enter menu page if we were not there before
598
  if( prev_ui_page != SEQ_UI_PAGE_MENU )
599
    SEQ_UI_PageSet(SEQ_UI_PAGE_MENU);
600
 
134 tk 601
  return 0; // no error
602
}
603
 
604
static s32 SEQ_UI_Button_Edit(s32 depressed)
605
{
606
  if( depressed ) return -1; // ignore when button depressed
607
 
167 tk 608
  // change to edit page
609
  SEQ_UI_PageSet(SEQ_UI_PAGE_EDIT);
610
 
178 tk 611
  // set/clear encoder fast function if required
612
  SEQ_UI_InitEncSpeed(1); // auto config
613
 
134 tk 614
  return 0; // no error
615
}
616
 
617
static s32 SEQ_UI_Button_Mute(s32 depressed)
618
{
619
  if( depressed ) return -1; // ignore when button depressed
620
 
184 tk 621
  SEQ_UI_PageSet(SEQ_UI_PAGE_MUTE);
622
 
134 tk 623
  return 0; // no error
624
}
625
 
626
static s32 SEQ_UI_Button_Pattern(s32 depressed)
627
{
628
  if( depressed ) return -1; // ignore when button depressed
629
 
184 tk 630
  SEQ_UI_PageSet(SEQ_UI_PAGE_PATTERN);
631
 
134 tk 632
  return 0; // no error
633
}
634
 
635
static s32 SEQ_UI_Button_Song(s32 depressed)
636
{
637
  if( depressed ) return -1; // ignore when button depressed
638
 
399 tk 639
  // toggle active mode if already in song page
640
  if( ui_page == SEQ_UI_PAGE_SONG ) {
641
    SEQ_SONG_ActiveSet(SEQ_SONG_ActiveGet() ? 0 : 1);
642
  }
643
 
644
  SEQ_UI_PageSet(SEQ_UI_PAGE_SONG);
645
 
134 tk 646
  return 0; // no error
647
}
648
 
649
static s32 SEQ_UI_Button_Solo(s32 depressed)
650
{
178 tk 651
#if DEFAULT_BEHAVIOUR_BUTTON_ALL
652
  // toggle mode
134 tk 653
  if( depressed ) return -1; // ignore when button depressed
178 tk 654
  seq_ui_button_state.SOLO ^= 1;
655
#else
656
  // set mode
657
  seq_ui_button_state.SOLO = depressed ? 0 : 1;
658
#endif
134 tk 659
 
660
  return 0; // no error
661
}
662
 
663
static s32 SEQ_UI_Button_Fast(s32 depressed)
664
{
178 tk 665
#if DEFAULT_BEHAVIOUR_BUTTON_FAST
666
  // toggle mode
134 tk 667
  if( depressed ) return -1; // ignore when button depressed
178 tk 668
  seq_ui_button_state.FAST_ENCODERS ^= 1;
669
#else
670
  // set mode
671
  seq_ui_button_state.FAST_ENCODERS = depressed ? 0 : 1;
672
#endif
134 tk 673
 
178 tk 674
  SEQ_UI_InitEncSpeed(0); // no auto config
675
 
134 tk 676
  return 0; // no error
677
}
678
 
679
static s32 SEQ_UI_Button_All(s32 depressed)
680
{
178 tk 681
  seq_ui_button_state.CHANGE_ALL_STEPS_SAME_VALUE = depressed ? 0 : 1;
134 tk 682
 
178 tk 683
#if DEFAULT_BEHAVIOUR_BUTTON_ALL
684
  // toggle mode
685
  if( depressed ) return -1;
686
  seq_ui_button_state.CHANGE_ALL_STEPS ^= 1;
687
#else
688
  // set mode
689
  seq_ui_button_state.CHANGE_ALL_STEPS = depressed ? 0 : 1;
690
#endif
691
 
134 tk 692
  return 0; // no error
693
}
694
 
695
static s32 SEQ_UI_Button_StepView(s32 depressed)
696
{
326 tk 697
 
303 tk 698
#if DEFAULT_BEHAVIOUR_BUTTON_STEPVIEW
134 tk 699
  if( depressed ) return -1; // ignore when button depressed
303 tk 700
  seq_ui_button_state.STEPVIEW ^= 1; // toggle STEPVIEW pressed (will also be released once GP button has been pressed)
701
#else
702
  // set mode
703
  seq_ui_button_state.STEPVIEW = depressed ? 0 : 1;
704
#endif
134 tk 705
 
303 tk 706
  if( seq_ui_button_state.STEPVIEW ) {
707
    ui_stepview_prev_page = ui_page;
708
    SEQ_UI_PageSet(SEQ_UI_PAGE_STEPSEL);
709
  } else {
710
    SEQ_UI_PageSet(ui_stepview_prev_page);
711
  }
134 tk 712
 
713
  return 0; // no error
714
}
715
 
716
static s32 SEQ_UI_Button_TapTempo(s32 depressed)
717
{
718
  if( depressed ) return -1; // ignore when button depressed
719
 
720
  return 0; // no error
721
}
722
 
484 tk 723
static s32 SEQ_UI_Button_Track(s32 depressed, u32 track_button)
134 tk 724
{
484 tk 725
  static u8 button_state = 0x0f; // all 4 buttons depressed
134 tk 726
 
484 tk 727
  if( track_button >= 4 ) return -2; // max. 4 track buttons
134 tk 728
 
484 tk 729
  if( depressed ) {
730
    button_state |= (1 << track_button);
731
    return 0; // no error
732
  }
134 tk 733
 
484 tk 734
  button_state &= ~(1 << track_button);
735
 
736
  if( button_state == (~(1 << track_button) & 0xf) ) {
737
    // if only one select button pressed: radio-button function (1 of 4)
738
    ui_selected_tracks = 1 << (track_button + 4*ui_selected_group);
739
  } else {
740
    // if more than one select button pressed: toggle function (4 of 4)
741
    ui_selected_tracks ^= 1 << (track_button + 4*ui_selected_group);
742
  }
743
 
178 tk 744
  // set/clear encoder fast function if required
745
  SEQ_UI_InitEncSpeed(1); // auto config
746
 
134 tk 747
  return 0; // no error
748
}
749
 
750
static s32 SEQ_UI_Button_Group(s32 depressed, u32 group)
751
{
752
  if( depressed ) return -1; // ignore when button depressed
753
 
754
  if( group >= 4 ) return -2; // max. 4 group buttons
755
 
484 tk 756
  // if group has changed:
757
  if( group != ui_selected_group ) {
758
    // get current track selection
759
    u16 old_tracks = ui_selected_tracks >> (4*ui_selected_group);
134 tk 760
 
484 tk 761
    // select new group
762
    ui_selected_group = group;
763
 
764
    // take over old track selection
765
    ui_selected_tracks = old_tracks << (4*ui_selected_group);
766
  }
767
 
178 tk 768
  // set/clear encoder fast function if required
769
  SEQ_UI_InitEncSpeed(1); // auto config
770
 
134 tk 771
  return 0; // no error
772
}
773
 
774
static s32 SEQ_UI_Button_ParLayer(s32 depressed, u32 par_layer)
775
{
776
  if( par_layer >= 3 ) return -2; // max. 3 parlayer buttons
777
 
333 tk 778
  u8 visible_track = SEQ_UI_VisibleTrackGet();
779
  u8 num_p_layers = SEQ_PAR_NumLayersGet(visible_track);
134 tk 780
 
333 tk 781
  if( num_p_layers <= 3 ) {
782
    // 3 layers: direct selection with LayerA/B/C button
783
    if( depressed ) return -1; // ignore when button depressed
784
    seq_ui_button_state.PAR_LAYER_SEL = 0;
785
    ui_selected_par_layer = par_layer;
786
  } else if( num_p_layers <= 4 ) {
787
    // 4 layers: LayerC Button toggles between C and D
788
    if( depressed ) return -1; // ignore when button depressed
789
    seq_ui_button_state.PAR_LAYER_SEL = 0;
336 tk 790
    if( par_layer == 2 )
791
      ui_selected_par_layer = (ui_selected_par_layer == 2) ? 3 : 2;
333 tk 792
    else
793
      ui_selected_par_layer = par_layer;
794
  } else {
795
    // >4 layers: LayerA/B button selects directly, Layer C button enters layer selection page
796
    if( par_layer <= 1 ) {
797
      if( depressed ) return -1; // ignore when button depressed
798
      seq_ui_button_state.PAR_LAYER_SEL = 0;
799
      ui_selected_par_layer = par_layer;
800
    } else {
801
#if DEFAULT_BEHAVIOUR_BUTTON_PAR_LAYER
802
      if( depressed ) return -1; // ignore when button depressed
803
      seq_ui_button_state.PAR_LAYER_SEL ^= 1; // toggle PARSEL status (will also be released once GP button has been pressed)
804
#else
805
      // set mode
806
      seq_ui_button_state.PAR_LAYER_SEL = depressed ? 0 : 1;
807
#endif
808
 
809
      if( seq_ui_button_state.PAR_LAYER_SEL ) {
810
    ui_parlayer_prev_page = ui_page;
811
    SEQ_UI_PageSet(SEQ_UI_PAGE_PARSEL);
812
      } else {
813
    SEQ_UI_PageSet(ui_parlayer_prev_page);
814
      }
815
    }
816
  }
817
 
178 tk 818
  // set/clear encoder fast function if required
819
  SEQ_UI_InitEncSpeed(1); // auto config
820
 
134 tk 821
  return 0; // no error
822
}
823
 
824
static s32 SEQ_UI_Button_TrgLayer(s32 depressed, u32 trg_layer)
825
{
826
  if( trg_layer >= 3 ) return -2; // max. 3 trglayer buttons
827
 
326 tk 828
  u8 visible_track = SEQ_UI_VisibleTrackGet();
829
  u8 event_mode = SEQ_CC_Get(visible_track, SEQ_CC_MIDI_EVENT_MODE);
830
  u8 num_t_layers = SEQ_TRG_NumLayersGet(visible_track);
134 tk 831
 
328 tk 832
  if( event_mode != SEQ_EVENT_MODE_Drum && num_t_layers <= 3 ) {
326 tk 833
    // 3 layers: direct selection with LayerA/B/C button
834
    if( depressed ) return -1; // ignore when button depressed
835
    seq_ui_button_state.TRG_LAYER_SEL = 0;
836
    ui_selected_trg_layer = trg_layer;
328 tk 837
  } else if( event_mode != SEQ_EVENT_MODE_Drum && num_t_layers <= 4 ) {
326 tk 838
    // 4 layers: LayerC Button toggles between C and D
839
    if( depressed ) return -1; // ignore when button depressed
840
    seq_ui_button_state.TRG_LAYER_SEL = 0;
336 tk 841
    if( trg_layer == 2 )
842
      ui_selected_trg_layer = (ui_selected_trg_layer == 2) ? 3 : 2;
326 tk 843
    else
844
      ui_selected_trg_layer = trg_layer;
845
  } else {
333 tk 846
    // >4 layers or drum mode: LayerA/B button selects directly, Layer C button enters trigger selection page
326 tk 847
    // also used for drum tracks
848
    if( trg_layer <= 1 ) {
849
      if( depressed ) return -1; // ignore when button depressed
328 tk 850
      seq_ui_button_state.TRG_LAYER_SEL = 0;
851
      ui_selected_trg_layer = trg_layer;
326 tk 852
    } else {
853
#if DEFAULT_BEHAVIOUR_BUTTON_TRG_LAYER
854
      if( depressed ) return -1; // ignore when button depressed
855
      seq_ui_button_state.TRG_LAYER_SEL ^= 1; // toggle TRGSEL status (will also be released once GP button has been pressed)
856
#else
857
      // set mode
858
      seq_ui_button_state.TRG_LAYER_SEL = depressed ? 0 : 1;
859
#endif
860
 
861
      if( seq_ui_button_state.TRG_LAYER_SEL ) {
862
    ui_trglayer_prev_page = ui_page;
863
    SEQ_UI_PageSet(SEQ_UI_PAGE_TRGSEL);
864
      } else {
865
    SEQ_UI_PageSet(ui_trglayer_prev_page);
866
      }
867
    }
868
  }
869
 
134 tk 870
  return 0; // no error
871
}
872
 
873
 
874
 
875
/////////////////////////////////////////////////////////////////////////////
876
// Button handler
877
/////////////////////////////////////////////////////////////////////////////
878
s32 SEQ_UI_Button_Handler(u32 pin, u32 pin_value)
879
{
492 tk 880
  int i;
881
 
496 tk 882
  // ignore so long hardware config hasn't been read
883
  if( !SEQ_FILE_HW_ConfigLocked() )
884
    return -1;
885
 
328 tk 886
  // ensure that selections are matching with track constraints
887
  SEQ_UI_CheckSelections();
888
 
492 tk 889
  // request display update
890
  seq_ui_display_update_req = 1;
134 tk 891
 
892
 
492 tk 893
  // MEMO: we could also use a jump table with references to the functions
894
  // here, but this "spagetthi code" simplifies the configuration and
895
  // the resulting ASM doesn't look that bad!
168 tk 896
 
492 tk 897
  for(i=0; i<SEQ_HWCFG_NUM_GP; ++i)
898
    if( pin == seq_hwcfg_button.gp[i] )
899
      return SEQ_UI_Button_GP(pin_value, i);
134 tk 900
 
492 tk 901
  for(i=0; i<SEQ_HWCFG_NUM_TRACK; ++i)
902
    if( pin == seq_hwcfg_button.track[i] )
903
      return SEQ_UI_Button_Track(pin_value, i);
134 tk 904
 
492 tk 905
  for(i=0; i<SEQ_HWCFG_NUM_GROUP; ++i)
906
    if( pin == seq_hwcfg_button.group[i] )
907
      return SEQ_UI_Button_Group(pin_value, i);
134 tk 908
 
492 tk 909
  for(i=0; i<SEQ_HWCFG_NUM_PAR_LAYER; ++i)
910
    if( pin == seq_hwcfg_button.par_layer[i] )
911
      return SEQ_UI_Button_ParLayer(pin_value, i);
134 tk 912
 
492 tk 913
  for(i=0; i<SEQ_HWCFG_NUM_TRG_LAYER; ++i)
914
    if( pin == seq_hwcfg_button.trg_layer[i] )
915
      return SEQ_UI_Button_TrgLayer(pin_value, i);
134 tk 916
 
492 tk 917
  if( pin == seq_hwcfg_button.left )
918
    return SEQ_UI_Button_Left(pin_value);
919
  if( pin == seq_hwcfg_button.right )
920
    return SEQ_UI_Button_Right(pin_value);
921
  if( pin == seq_hwcfg_button.down )
922
    return SEQ_UI_Button_Down(pin_value);
923
  if( pin == seq_hwcfg_button.up )
924
    return SEQ_UI_Button_Up(pin_value);
134 tk 925
 
492 tk 926
  if( pin == seq_hwcfg_button.scrub )
927
    return SEQ_UI_Button_Scrub(pin_value);
928
  if( pin == seq_hwcfg_button.metronome )
929
    return SEQ_UI_Button_Metronome(pin_value);
134 tk 930
 
492 tk 931
  if( pin == seq_hwcfg_button.stop )
932
    return SEQ_UI_Button_Stop(pin_value);
933
  if( pin == seq_hwcfg_button.pause )
934
    return SEQ_UI_Button_Pause(pin_value);
935
  if( pin == seq_hwcfg_button.play )
936
    return SEQ_UI_Button_Play(pin_value);
937
  if( pin == seq_hwcfg_button.rew )
938
    return SEQ_UI_Button_Rew(pin_value);
939
  if( pin == seq_hwcfg_button.fwd )
940
    return SEQ_UI_Button_Fwd(pin_value);
134 tk 941
 
492 tk 942
  if( pin == seq_hwcfg_button.utility )
943
    return SEQ_UI_Button_Utility(pin_value);
944
  if( pin == seq_hwcfg_button.copy )
945
    return SEQ_UI_Button_Copy(pin_value);
946
  if( pin == seq_hwcfg_button.paste )
947
    return SEQ_UI_Button_Paste(pin_value);
948
  if( pin == seq_hwcfg_button.clear )
949
    return SEQ_UI_Button_Clear(pin_value);
134 tk 950
 
492 tk 951
  if( pin == seq_hwcfg_button.menu )
952
    return SEQ_UI_Button_Menu(pin_value);
953
  if( pin == seq_hwcfg_button.select )
954
    return SEQ_UI_Button_Select(pin_value);
955
  if( pin == seq_hwcfg_button.exit )
956
    return SEQ_UI_Button_Exit(pin_value);
134 tk 957
 
492 tk 958
  if( pin == seq_hwcfg_button.f1 )
959
    return SEQ_UI_Button_F1(pin_value);
960
  if( pin == seq_hwcfg_button.f2 )
961
    return SEQ_UI_Button_F2(pin_value);
962
  if( pin == seq_hwcfg_button.f3 )
963
    return SEQ_UI_Button_F3(pin_value);
964
  if( pin == seq_hwcfg_button.f4 )
965
    return SEQ_UI_Button_F4(pin_value);
134 tk 966
 
492 tk 967
  if( pin == seq_hwcfg_button.edit )
968
    return SEQ_UI_Button_Edit(pin_value);
969
  if( pin == seq_hwcfg_button.mute )
970
    return SEQ_UI_Button_Mute(pin_value);
971
  if( pin == seq_hwcfg_button.pattern )
972
    return SEQ_UI_Button_Pattern(pin_value);
973
  if( pin == seq_hwcfg_button.song )
974
    return SEQ_UI_Button_Song(pin_value);
134 tk 975
 
492 tk 976
  if( pin == seq_hwcfg_button.solo )
977
    return SEQ_UI_Button_Solo(pin_value);
978
  if( pin == seq_hwcfg_button.fast )
979
    return SEQ_UI_Button_Fast(pin_value);
980
  if( pin == seq_hwcfg_button.all )
981
    return SEQ_UI_Button_All(pin_value);
134 tk 982
 
492 tk 983
  if( pin == seq_hwcfg_button.step_view )
984
    return SEQ_UI_Button_StepView(pin_value);
985
  if( pin == seq_hwcfg_button.tap_tempo )
986
    return SEQ_UI_Button_TapTempo(pin_value);
134 tk 987
 
492 tk 988
  return -1; // button not mapped
134 tk 989
}
990
 
991
 
992
/////////////////////////////////////////////////////////////////////////////
993
// Encoder handler
994
/////////////////////////////////////////////////////////////////////////////
995
s32 SEQ_UI_Encoder_Handler(u32 encoder, s32 incrementer)
996
{
496 tk 997
  // ignore so long hardware config hasn't been read
998
  if( !SEQ_FILE_HW_ConfigLocked() )
999
    return -1;
1000
 
134 tk 1001
  if( encoder > 16 )
1002
    return -1; // encoder doesn't exist
1003
 
328 tk 1004
  // ensure that selections are matching with track constraints
1005
  SEQ_UI_CheckSelections();
1006
 
134 tk 1007
  // limit incrementer
1008
  if( incrementer > 3 )
1009
    incrementer = 3;
1010
  else if( incrementer < -3 )
1011
    incrementer = -3;
1012
 
306 tk 1013
  if( !seq_ui_button_state.MENU_PRESSED && ui_encoder_callback != NULL ) {
173 tk 1014
    ui_encoder_callback((encoder == 0) ? SEQ_UI_ENCODER_Datawheel : (encoder-1), incrementer);
1015
    ui_cursor_flash_ctr = 0; // ensure that value is visible when it has been changed
134 tk 1016
  }
1017
 
1018
  // request display update
159 tk 1019
  seq_ui_display_update_req = 1;
134 tk 1020
 
1021
  return 0; // no error
1022
}
1023
 
1024
 
353 tk 1025
 
134 tk 1026
/////////////////////////////////////////////////////////////////////////////
1027
// Update LCD messages
1028
// Usually called from background task
1029
/////////////////////////////////////////////////////////////////////////////
1030
s32 SEQ_UI_LCD_Handler(void)
1031
{
159 tk 1032
  if( seq_ui_display_init_req ) {
1033
    seq_ui_display_init_req = 0; // clear request
134 tk 1034
 
278 tk 1035
    // clear force update of LCD
1036
    SEQ_LCD_Clear();
1037
    SEQ_LCD_Update(1);
134 tk 1038
 
168 tk 1039
    // select first menu item
1040
    ui_selected_item = 0;
1041
 
167 tk 1042
    // call init function of current page
272 tk 1043
    if( ui_menu_pages[ui_page].init_callback != NULL )
1044
      ui_menu_pages[ui_page].init_callback(0); // mode
134 tk 1045
 
1046
    // request display update
159 tk 1047
    seq_ui_display_update_req = 1;
134 tk 1048
  }
1049
 
496 tk 1050
  // print boot screen so long hardware config hasn't been read
1051
  if( !SEQ_FILE_HW_ConfigLocked() ) {
1052
    SEQ_LCD_Clear();
306 tk 1053
    SEQ_LCD_CursorSet(0, 0);
496 tk 1054
    //                   <-------------------------------------->
1055
    //                   0123456789012345678901234567890123456789
1056
    SEQ_LCD_PrintString(MIOS32_LCD_BOOT_MSG_LINE1);
1057
    SEQ_LCD_CursorSet(40, 0);
1058
    SEQ_LCD_PrintString("Searching for SD Card...");
1059
    SEQ_LCD_CursorSet(0, 1);
1060
    SEQ_LCD_PrintString(MIOS32_LCD_BOOT_MSG_LINE2);
1061
    // TODO: print nice animation
1062
  } else if( seq_ui_button_state.MENU_PRESSED && !seq_ui_button_state.MENU_FIRST_PAGE_SELECTED ) {
1063
    SEQ_LCD_CursorSet(0, 0);
1064
    //                   <-------------------------------------->
1065
    //                   0123456789012345678901234567890123456789
306 tk 1066
    SEQ_LCD_PrintString("Menu Shortcuts:");
1067
    SEQ_LCD_PrintSpaces(25 + 40);
1068
    SEQ_LCD_CursorSet(0, 1);
1069
    SEQ_LCD_PrintString(UI_SHORTCUT_STR); // defined in seq_ui_pages.inc
1070
  } else {
1071
    // perform high priority LCD update request
1072
    if( ui_lcd_callback != NULL )
1073
      ui_lcd_callback(1); // high_prio
167 tk 1074
 
306 tk 1075
    // perform low priority LCD update request if requested
1076
    if( seq_ui_display_update_req ) {
1077
      seq_ui_display_update_req = 0; // clear request
328 tk 1078
 
1079
      // ensure that selections are matching with track constraints
1080
      SEQ_UI_CheckSelections();
1081
 
306 tk 1082
      if( ui_lcd_callback != NULL )
1083
    ui_lcd_callback(0); // no high_prio
1084
    }
134 tk 1085
  }
1086
 
353 tk 1087
  // transfer all changed characters to LCD
1088
  SEQ_UI_LCD_Update();
1089
 
1090
  return 0; // no error
1091
}
1092
 
1093
 
1094
/////////////////////////////////////////////////////////////////////////////
1095
// Called from SEQ_UI_LCD_Handler(), but optionally also from other tasks
1096
// to update the LCD screen immediately
1097
/////////////////////////////////////////////////////////////////////////////
1098
s32 SEQ_UI_LCD_Update(void)
1099
{
299 tk 1100
  // if SD card message active: copy over the text
1101
  if( sdcard_msg_ctr ) {
1102
    const char animation_l[4][3] = {
1103
      "  ", " >", ">>", "> " };
1104
    const char animation_r[4][3] = {
1105
      "  ", "< ", "<<", " <" };
1106
    int anum = (sdcard_msg_ctr % 1000) / 250;
1107
 
1108
    int line;
1109
    for(line=0; line<2; ++line) {
353 tk 1110
      SEQ_LCD_CursorSet(0, line); // MEMO: print such important information at first LCD for the case the user hasn't connected the second LCD yet
299 tk 1111
      SEQ_LCD_PrintFormattedString(" %s| %-20s |%s ",
1112
                   (char *)animation_l[anum],
1113
                   (char *)sdcard_msg[line],
1114
                   (char *)animation_r[anum]);
1115
    }
1116
  }
1117
 
278 tk 1118
  // transfer all changed characters to LCD
353 tk 1119
  // SEQ_LCD_Update provides a MUTEX handling to allow updates from different tasks
1120
  return SEQ_LCD_Update(0);
134 tk 1121
}
1122
 
1123
 
1124
/////////////////////////////////////////////////////////////////////////////
1125
// Update all LEDs
1126
// Usually called from background task
1127
/////////////////////////////////////////////////////////////////////////////
1128
s32 SEQ_UI_LED_Handler(void)
1129
{
496 tk 1130
  // ignore so long hardware config hasn't been read
1131
  if( !SEQ_FILE_HW_ConfigLocked() )
1132
    return -1;
1133
 
326 tk 1134
  u8 visible_track = SEQ_UI_VisibleTrackGet();
1135
  u8 event_mode = SEQ_CC_Get(visible_track, SEQ_CC_MIDI_EVENT_MODE);
1136
 
134 tk 1137
  // track LEDs
484 tk 1138
  u8 selected_tracks = ui_selected_tracks >> (4*ui_selected_group);
492 tk 1139
  SEQ_LED_PinSet(seq_hwcfg_led.track[0], (selected_tracks & (1 << 0)));
1140
  SEQ_LED_PinSet(seq_hwcfg_led.track[1], (selected_tracks & (1 << 1)));
1141
  SEQ_LED_PinSet(seq_hwcfg_led.track[2], (selected_tracks & (1 << 2)));
1142
  SEQ_LED_PinSet(seq_hwcfg_led.track[3], (selected_tracks & (1 << 3)));
134 tk 1143
 
1144
  // parameter layer LEDs
492 tk 1145
  SEQ_LED_PinSet(seq_hwcfg_led.par_layer[0], (ui_selected_par_layer == 0));
1146
  SEQ_LED_PinSet(seq_hwcfg_led.par_layer[1], (ui_selected_par_layer == 1));
1147
  SEQ_LED_PinSet(seq_hwcfg_led.par_layer[2], (ui_selected_par_layer >= 2) || seq_ui_button_state.PAR_LAYER_SEL);
134 tk 1148
 
1149
  // group LEDs
492 tk 1150
  SEQ_LED_PinSet(seq_hwcfg_led.group[0], (ui_selected_group == 0));
1151
  SEQ_LED_PinSet(seq_hwcfg_led.group[1], (ui_selected_group == 1));
1152
  SEQ_LED_PinSet(seq_hwcfg_led.group[2], (ui_selected_group == 2));
1153
  SEQ_LED_PinSet(seq_hwcfg_led.group[3], (ui_selected_group == 3));
134 tk 1154
 
1155
  // trigger layer LEDs
492 tk 1156
  SEQ_LED_PinSet(seq_hwcfg_led.trg_layer[0], (ui_selected_trg_layer == 0));
1157
  SEQ_LED_PinSet(seq_hwcfg_led.trg_layer[1], (ui_selected_trg_layer == 1));
1158
  SEQ_LED_PinSet(seq_hwcfg_led.trg_layer[2], (ui_selected_trg_layer >= 2) || seq_ui_button_state.TRG_LAYER_SEL);
134 tk 1159
 
1160
  // remaining LEDs
492 tk 1161
  SEQ_LED_PinSet(seq_hwcfg_led.edit, ui_page == SEQ_UI_PAGE_EDIT);
1162
  SEQ_LED_PinSet(seq_hwcfg_led.mute, ui_page == SEQ_UI_PAGE_MUTE);
1163
  SEQ_LED_PinSet(seq_hwcfg_led.pattern, ui_page == SEQ_UI_PAGE_PATTERN);
399 tk 1164
  if( SEQ_SONG_ActiveGet() )
492 tk 1165
    SEQ_LED_PinSet(seq_hwcfg_led.song, 1);
399 tk 1166
  else
492 tk 1167
    SEQ_LED_PinSet(seq_hwcfg_led.song, ui_cursor_flash ? 0 : (ui_page == SEQ_UI_PAGE_SONG));
134 tk 1168
 
492 tk 1169
  SEQ_LED_PinSet(seq_hwcfg_led.solo, seq_ui_button_state.SOLO);
1170
  SEQ_LED_PinSet(seq_hwcfg_led.fast, seq_ui_button_state.FAST_ENCODERS);
1171
  SEQ_LED_PinSet(seq_hwcfg_led.all, seq_ui_button_state.CHANGE_ALL_STEPS);
134 tk 1172
 
492 tk 1173
  SEQ_LED_PinSet(seq_hwcfg_led.play, SEQ_BPM_IsRunning());
1174
  SEQ_LED_PinSet(seq_hwcfg_led.stop, !SEQ_BPM_IsRunning() && !ui_seq_pause);
1175
  SEQ_LED_PinSet(seq_hwcfg_led.pause, ui_seq_pause);
240 tk 1176
 
492 tk 1177
  SEQ_LED_PinSet(seq_hwcfg_led.rew, seq_ui_button_state.REW);
1178
  SEQ_LED_PinSet(seq_hwcfg_led.fwd, seq_ui_button_state.FWD);
134 tk 1179
 
492 tk 1180
  SEQ_LED_PinSet(seq_hwcfg_led.step_view, seq_ui_button_state.STEPVIEW);
134 tk 1181
 
492 tk 1182
  SEQ_LED_PinSet(seq_hwcfg_led.menu, seq_ui_button_state.MENU_PRESSED);
1183
  SEQ_LED_PinSet(seq_hwcfg_led.scrub, seq_ui_button_state.SCRUB);
1184
  SEQ_LED_PinSet(seq_hwcfg_led.metronome, seq_ui_button_state.METRONOME);
134 tk 1185
 
492 tk 1186
  SEQ_LED_PinSet(seq_hwcfg_led.utility, ui_page == SEQ_UI_PAGE_UTIL);
1187
  SEQ_LED_PinSet(seq_hwcfg_led.copy, seq_ui_button_state.COPY);
1188
  SEQ_LED_PinSet(seq_hwcfg_led.paste, seq_ui_button_state.PASTE);
1189
  SEQ_LED_PinSet(seq_hwcfg_led.clear, seq_ui_button_state.CLEAR);
240 tk 1190
 
492 tk 1191
  SEQ_LED_PinSet(seq_hwcfg_led.f1, seq_ui_button_state.F1);
1192
  SEQ_LED_PinSet(seq_hwcfg_led.f2, seq_ui_button_state.F2);
1193
  SEQ_LED_PinSet(seq_hwcfg_led.f3, seq_ui_button_state.F3);
1194
  SEQ_LED_PinSet(seq_hwcfg_led.f4, seq_ui_button_state.F4);
240 tk 1195
 
492 tk 1196
  SEQ_LED_PinSet(seq_hwcfg_led.down, seq_ui_button_state.DOWN);
1197
  SEQ_LED_PinSet(seq_hwcfg_led.up, seq_ui_button_state.UP);
240 tk 1198
 
167 tk 1199
 
306 tk 1200
  // in MENU page: overrule GP LEDs so long MENU button is pressed/active
1201
  if( seq_ui_button_state.MENU_PRESSED ) {
1202
    if( ui_cursor_flash ) // if flashing flag active: no LED flag set
1203
      ui_gp_leds = 0x0000;
1204
    else {
1205
      int i;
1206
      u16 new_ui_gp_leds = 0x0000;
1207
      for(i=0; i<16; ++i)
1208
    if( ui_page == ui_shortcut_menu_pages[i] )
1209
      new_ui_gp_leds |= (1 << i);
1210
      ui_gp_leds = new_ui_gp_leds;
1211
    }
1212
  } else {
1213
    // note: the background function is permanently interrupted - therefore we write the GP pattern
1214
    // into a temporary variable, and take it over once completed
1215
    u16 new_ui_gp_leds = 0x0000;
1216
    // request GP LED values from current menu page
1217
    // will be transfered to DOUT registers in SEQ_UI_LED_Handler_Periodic
1218
    new_ui_gp_leds = 0x0000;
206 tk 1219
 
306 tk 1220
    if( ui_led_callback != NULL )
1221
      ui_led_callback(&new_ui_gp_leds);
167 tk 1222
 
306 tk 1223
    ui_gp_leds = new_ui_gp_leds;
1224
  }
1225
 
134 tk 1226
  return 0; // no error
1227
}
1228
 
1229
 
1230
/////////////////////////////////////////////////////////////////////////////
1231
// updates high-prio LED functions (GP LEDs and Beat LED)
168 tk 1232
// called each mS
134 tk 1233
/////////////////////////////////////////////////////////////////////////////
1234
s32 SEQ_UI_LED_Handler_Periodic()
1235
{
496 tk 1236
  // ignore so long hardware config hasn't been read
1237
  if( !SEQ_FILE_HW_ConfigLocked() )
1238
    return -1;
1239
 
134 tk 1240
  // GP LEDs are only updated when ui_gp_leds or pos_marker_mask has changed
1241
  static u16 prev_ui_gp_leds = 0x0000;
1242
  static u16 prev_pos_marker_mask = 0x0000;
1243
 
1244
  // beat LED: tmp. for demo w/o real sequencer
193 tk 1245
  u8 sequencer_running = SEQ_BPM_IsRunning();
492 tk 1246
  SEQ_LED_PinSet(seq_hwcfg_led.beat, sequencer_running && ((seq_core_state.ref_step & 3) == 0));
134 tk 1247
 
1248
  // for song position marker (supports 16 LEDs, check for selected step view)
1249
  u16 pos_marker_mask = 0x0000;
325 tk 1250
  u8 visible_track = SEQ_UI_VisibleTrackGet();
1251
  u8 played_step = seq_core_trk[visible_track].step;
1252
  if( seq_ui_button_state.STEPVIEW ) {
1253
    // if STEPVIEW button pressed: pos marker correlated to zoom ratio
1254
    if( sequencer_running )
1255
      pos_marker_mask = 1 << (played_step / (SEQ_TRG_NumStepsGet(visible_track)/16));
1256
  } else {
1257
    if( sequencer_running && (played_step >> 4) == ui_selected_step_view )
1258
      pos_marker_mask = 1 << (played_step & 0xf);
1259
  }
134 tk 1260
 
1261
  // exit of pattern hasn't changed
173 tk 1262
  if( prev_ui_gp_leds == ui_gp_leds && prev_pos_marker_mask == pos_marker_mask )
134 tk 1263
    return 0;
173 tk 1264
  prev_ui_gp_leds = ui_gp_leds;
134 tk 1265
  prev_pos_marker_mask = pos_marker_mask;
1266
 
1267
  // transfer to GP LEDs
1268
 
496 tk 1269
  if( seq_hwcfg_led.gp_dout_sr_l ) {
1270
    if( seq_hwcfg_led.gp_dout_sr_l2 )
1271
      SEQ_LED_SRSet(seq_hwcfg_led.gp_dout_sr_l-1, (ui_gp_leds >> 0) & 0xff);
1272
    else
1273
      SEQ_LED_SRSet(seq_hwcfg_led.gp_dout_sr_l-1, ((ui_gp_leds ^ pos_marker_mask) >> 0) & 0xff);
1274
  }
134 tk 1275
 
496 tk 1276
  if( seq_hwcfg_led.gp_dout_sr_r ) {
1277
    if( seq_hwcfg_led.gp_dout_sr_r2 )
1278
      SEQ_LED_SRSet(seq_hwcfg_led.gp_dout_sr_r-1, (ui_gp_leds >> 8) & 0xff);
1279
    else
1280
      SEQ_LED_SRSet(seq_hwcfg_led.gp_dout_sr_r-1, ((ui_gp_leds ^ pos_marker_mask) >> 8) & 0xff);
1281
  }
134 tk 1282
 
496 tk 1283
  if( seq_hwcfg_led.gp_dout_sr_l2 )
1284
    SEQ_LED_SRSet(seq_hwcfg_led.gp_dout_sr_l2-1, (pos_marker_mask >> 0) & 0xff);
1285
  if( seq_hwcfg_led.gp_dout_sr_r2 )
1286
    SEQ_LED_SRSet(seq_hwcfg_led.gp_dout_sr_r2-1, (pos_marker_mask >> 8) & 0xff);
1287
 
134 tk 1288
#if DEFAULT_SRM_ENABLED && DEFAULT_SRM_DOUT_M_MAPPING == 1
1289
  // for wilba's frontpanel
1290
 
464 tk 1291
  // BLM_X DOUT -> GP LED mapping
134 tk 1292
  // 0 = 15,16  1 = 13,14   2 = 11,12   3 = 9,10
1293
  // 4 = 1,2    5 = 3,4     6 = 5,6     7 = 7,8
1294
 
1295
  // bit 7: first green (i.e. GP1-G)
1296
  // bit 6: first red (i.e. GP1-R)
1297
  // bit 5: second green (i.e. GP2-G)
1298
  // bit 4: second red (i.e. GP2-R)
1299
 
1300
  // this mapping routine takes ca. 5 uS
173 tk 1301
  // since it's only executed when ui_gp_leds or gp_mask has changed, it doesn't really hurt
134 tk 1302
 
173 tk 1303
  u16 modified_gp_leds = ui_gp_leds;
134 tk 1304
#if 1
1305
  // extra: red LED is lit exclusively for higher contrast
1306
  modified_gp_leds &= ~pos_marker_mask;
1307
#endif
1308
 
1309
  int sr;
464 tk 1310
  const u8 blm_x_sr_map[8] = {4, 5, 6, 7, 3, 2, 1, 0};
134 tk 1311
  u16 gp_mask = 1 << 0;
1312
  for(sr=0; sr<8; ++sr) {
1313
    u8 pattern = 0;
1314
 
1315
    if( modified_gp_leds & gp_mask )
1316
      pattern |= 0x80;
1317
    if( pos_marker_mask & gp_mask )
1318
      pattern |= 0x40;
1319
    gp_mask <<= 1;
1320
    if( modified_gp_leds & gp_mask )
1321
      pattern |= 0x20;
1322
    if( pos_marker_mask & gp_mask )
1323
      pattern |= 0x10;
1324
    gp_mask <<= 1;
1325
 
464 tk 1326
    u8 mapped_sr = blm_x_sr_map[sr];
1327
    BLM_X_LED_rows[mapped_sr][0] = (BLM_X_LED_rows[mapped_sr][0] & 0x0f) | pattern;
134 tk 1328
  }
1329
#endif
1330
 
184 tk 1331
  return 0; // no error
134 tk 1332
}
1333
 
1334
 
1335
/////////////////////////////////////////////////////////////////////////////
168 tk 1336
// for menu handling (e.g. flashing cursor, doubleclick counter, etc...)
1337
// called each mS
1338
/////////////////////////////////////////////////////////////////////////////
1339
s32 SEQ_UI_MENU_Handler_Periodic()
1340
{
1341
  if( ++ui_cursor_flash_ctr >= SEQ_UI_CURSOR_FLASH_CTR_MAX ) {
1342
    ui_cursor_flash_ctr = 0;
1343
    seq_ui_display_update_req = 1;
173 tk 1344
  } else if( ui_cursor_flash_ctr == SEQ_UI_CURSOR_FLASH_CTR_LED_OFF ) {
168 tk 1345
    seq_ui_display_update_req = 1;
173 tk 1346
  }
1347
  // important: flash flag has to be recalculated on each invocation of this
1348
  // handler, since counter could also be reseted outside this function
1349
  ui_cursor_flash = ui_cursor_flash_ctr >= SEQ_UI_CURSOR_FLASH_CTR_LED_OFF;
168 tk 1350
 
184 tk 1351
 
240 tk 1352
  // used in some pages for temporary messages
416 tk 1353
  if( ui_hold_msg_ctr ) {
240 tk 1354
    --ui_hold_msg_ctr;
1355
 
416 tk 1356
    if( !ui_hold_msg_ctr )
1357
      seq_ui_display_update_req = 1;
1358
  }
1359
 
299 tk 1360
  // used for temporary SD Card messages
1361
  if( sdcard_msg_ctr )
1362
    --sdcard_msg_ctr;
1363
 
184 tk 1364
  // VU meters (used in MUTE menu, could also be available as LED matrix...)
1365
  static u8 vu_meter_prediv = 0; // predivider for VU meters
1366
 
1367
  if( ++vu_meter_prediv >= 4 ) {
1368
    vu_meter_prediv = 0;
1369
 
333 tk 1370
 
1371
    portENTER_CRITICAL();
1372
 
184 tk 1373
    u8 track;
1374
    seq_core_trk_t *t = &seq_core_trk[0];
1375
    for(track=0; track<SEQ_CORE_NUM_TRACKS; ++t, ++track)
1376
      if( t->vu_meter )
1377
    --t->vu_meter;
333 tk 1378
 
1379
    int i;
1380
    u8 *vu_meter = (u8 *)&seq_layer_vu_meter[0];
1381
    for(i=0; i<sizeof(seq_layer_vu_meter); ++i, ++vu_meter) {
1382
      if( *vu_meter && !(*vu_meter & 0x80) ) // if bit 7 set: static value
1383
    *vu_meter -= 1;
1384
    }
1385
 
318 tk 1386
    portEXIT_CRITICAL();
184 tk 1387
  }
1388
 
168 tk 1389
  return 0;
1390
}
1391
 
1392
 
1393
/////////////////////////////////////////////////////////////////////////////
328 tk 1394
// Should be regulary called to check if the layer/instrument/step selection
1395
// is valid for the current track
1396
// At least executed before button/encoder and LCD function calls
1397
/////////////////////////////////////////////////////////////////////////////
1398
s32 SEQ_UI_CheckSelections(void)
1399
{
492 tk 1400
  if( (ui_selected_tracks >> (4*ui_selected_group)) == 0 )
1401
    ui_selected_tracks = 1 << (4*ui_selected_group);
1402
 
328 tk 1403
  u8 visible_track = SEQ_UI_VisibleTrackGet();
1404
 
1405
  if( ui_selected_instrument >= SEQ_PAR_NumInstrumentsGet(visible_track) )
1406
    ui_selected_instrument = 0;
1407
 
1408
  if( ui_selected_par_layer >= SEQ_PAR_NumLayersGet(visible_track) )
1409
    ui_selected_par_layer = 0;
1410
 
1411
  if( ui_selected_trg_layer >= SEQ_TRG_NumLayersGet(visible_track) )
1412
    ui_selected_trg_layer = 0;
1413
 
1414
  if( ui_selected_step >= SEQ_TRG_NumStepsGet(visible_track) )
1415
    ui_selected_step = 0;
1416
 
1417
  if( ui_selected_step_view >= (SEQ_TRG_NumStepsGet(visible_track)/16) ) {
1418
    ui_selected_step_view = 0;
1419
    ui_selected_step %= 16;
1420
  }
1421
 
336 tk 1422
  if( ui_selected_step < (16*ui_selected_step_view) ||
1423
      ui_selected_step >= (16*(ui_selected_step_view+1)) )
328 tk 1424
    ui_selected_step_view = ui_selected_step / 16;
1425
 
1426
  return 0; // no error
1427
}
1428
 
1429
 
1430
/////////////////////////////////////////////////////////////////////////////
134 tk 1431
// Returns the currently visible track
1432
/////////////////////////////////////////////////////////////////////////////
1433
u8 SEQ_UI_VisibleTrackGet(void)
1434
{
1435
  u8 offset = 0;
1436
 
484 tk 1437
  u8 selected_tracks = ui_selected_tracks >> (4*ui_selected_group);
1438
  if( selected_tracks & (1 << 3) )
134 tk 1439
    offset = 3;
484 tk 1440
  if( selected_tracks & (1 << 2) )
134 tk 1441
    offset = 2;
484 tk 1442
  if( selected_tracks & (1 << 1) )
134 tk 1443
    offset = 1;
484 tk 1444
  if( selected_tracks & (1 << 0) )
134 tk 1445
    offset = 0;
1446
 
1447
  return 4*ui_selected_group + offset;
1448
}
1449
 
168 tk 1450
 
1451
/////////////////////////////////////////////////////////////////////////////
178 tk 1452
// Returns 1 if 'track' is selected
1453
/////////////////////////////////////////////////////////////////////////////
1454
s32 SEQ_UI_IsSelectedTrack(u8 track)
1455
{
484 tk 1456
  return (ui_selected_tracks & (1 << track)) ? 1 : 0;
178 tk 1457
}
1458
 
1459
 
1460
/////////////////////////////////////////////////////////////////////////////
240 tk 1461
// Sets a new selected step and updates the step view
1462
/////////////////////////////////////////////////////////////////////////////
1463
s32 SEQ_UI_SelectedStepSet(u8 step)
1464
{
1465
  ui_selected_step = step;
328 tk 1466
  SEQ_UI_CheckSelections();
1467
 
240 tk 1468
  return 0; // no error
1469
}
1470
 
1471
 
1472
/////////////////////////////////////////////////////////////////////////////
168 tk 1473
// Increments the selected tracks/groups
1474
// OUT: 1 if value has been changed, otherwise 0
1475
/////////////////////////////////////////////////////////////////////////////
1476
s32 SEQ_UI_GxTyInc(s32 incrementer)
1477
{
1478
  int gxty = SEQ_UI_VisibleTrackGet();
1479
  int prev_gxty = gxty;
1480
 
1481
  if( incrementer >= 0 ) {
1482
    if( (gxty += incrementer) >= SEQ_CORE_NUM_TRACKS )
1483
      gxty = SEQ_CORE_NUM_TRACKS-1;
1484
  } else {
1485
    if( (gxty += incrementer) < 0 )
1486
      gxty = 0;
1487
  }
1488
 
1489
  if( gxty == prev_gxty )
1490
    return 0; // no change
1491
 
484 tk 1492
  ui_selected_tracks = 1 << gxty;
168 tk 1493
  ui_selected_group = gxty / 4;
1494
 
1495
  return 1; // value changed
1496
}
1497
 
1498
 
1499
/////////////////////////////////////////////////////////////////////////////
236 tk 1500
// Increments a 16bit variable within given min/max range
1501
// OUT: 1 if value has been changed, otherwise 0
1502
/////////////////////////////////////////////////////////////////////////////
240 tk 1503
s32 SEQ_UI_Var16_Inc(u16 *value, u16 min, u16 max, s32 incrementer)
236 tk 1504
{
1505
  int new_value = *value;
1506
  int prev_value = new_value;
1507
 
1508
  if( incrementer >= 0 ) {
1509
    if( (new_value += incrementer) >= max )
1510
      new_value = max;
1511
  } else {
1512
    if( (new_value += incrementer) < min )
1513
      new_value = min;
1514
  }
1515
 
1516
  if( new_value == prev_value )
1517
    return 0; // no change
1518
 
1519
  *value = new_value;
1520
 
1521
  return 1; // value changed
1522
}
1523
 
240 tk 1524
/////////////////////////////////////////////////////////////////////////////
1525
// Increments an 8bit variable within given min/max range
1526
// OUT: 1 if value has been changed, otherwise 0
1527
/////////////////////////////////////////////////////////////////////////////
1528
s32 SEQ_UI_Var8_Inc(u8 *value, u16 min, u16 max, s32 incrementer)
1529
{
1530
  u16 tmp = *value;
1531
  if( SEQ_UI_Var16_Inc(&tmp, min, max, incrementer) ) {
1532
    *value = tmp;
1533
    return 1; // value changed
1534
  }
236 tk 1535
 
240 tk 1536
  return 0; // value hasn't been changed
1537
}
1538
 
1539
 
236 tk 1540
/////////////////////////////////////////////////////////////////////////////
168 tk 1541
// Increments a CC within given min/max range
1542
// OUT: 1 if value has been changed, otherwise 0
1543
/////////////////////////////////////////////////////////////////////////////
248 tk 1544
s32 SEQ_UI_CC_Inc(u8 cc, u8 min, u8 max, s32 incrementer)
168 tk 1545
{
1546
  u8 visible_track = SEQ_UI_VisibleTrackGet();
173 tk 1547
  int new_value = SEQ_CC_Get(visible_track, cc);
1548
  int prev_value = new_value;
168 tk 1549
 
1550
  if( incrementer >= 0 ) {
173 tk 1551
    if( (new_value += incrementer) >= max )
1552
      new_value = max;
168 tk 1553
  } else {
173 tk 1554
    if( (new_value += incrementer) < min )
1555
      new_value = min;
168 tk 1556
  }
1557
 
173 tk 1558
  if( new_value == prev_value )
168 tk 1559
    return 0; // no change
1560
 
173 tk 1561
  SEQ_CC_Set(visible_track, cc, new_value);
168 tk 1562
 
179 tk 1563
  // set same value for all selected tracks
1564
  u8 track;
1565
  for(track=0; track<SEQ_CORE_NUM_TRACKS; ++track)
1566
    if( track != visible_track && SEQ_UI_IsSelectedTrack(track) )
1567
      SEQ_CC_Set(track, cc, new_value);
1568
 
168 tk 1569
  return 1; // value changed
1570
}
1571
 
173 tk 1572
 
1573
/////////////////////////////////////////////////////////////////////////////
179 tk 1574
// Sets a CC value on all selected tracks
1575
// OUT: 1 if value has been changed, otherwise 0
1576
/////////////////////////////////////////////////////////////////////////////
248 tk 1577
s32 SEQ_UI_CC_Set(u8 cc, u8 value)
179 tk 1578
{
1579
  u8 visible_track = SEQ_UI_VisibleTrackGet();
1580
  int prev_value = SEQ_CC_Get(visible_track, cc);
1581
 
1582
  if( value == prev_value )
1583
    return 0; // no change
1584
 
1585
  SEQ_CC_Set(visible_track, cc, value);
1586
 
1587
  // set same value for all selected tracks
1588
  u8 track;
1589
  for(track=0; track<SEQ_CORE_NUM_TRACKS; ++track)
1590
    if( track != visible_track && SEQ_UI_IsSelectedTrack(track) )
1591
      SEQ_CC_Set(track, cc, value);
1592
 
1593
  return 1; // value changed
1594
}
1595
 
1596
/////////////////////////////////////////////////////////////////////////////
173 tk 1597
// Modifies a bitfield in a CC value to a given value
1598
// OUT: 1 if value has been changed, otherwise 0
1599
/////////////////////////////////////////////////////////////////////////////
248 tk 1600
s32 SEQ_UI_CC_SetFlags(u8 cc, u8 flag_mask, u8 value)
173 tk 1601
{
1602
  u8 visible_track = SEQ_UI_VisibleTrackGet();
1603
  int new_value = SEQ_CC_Get(visible_track, cc);
1604
  int prev_value = new_value;
1605
 
1606
  new_value = (new_value & ~flag_mask) | value;
1607
 
1608
  if( new_value == prev_value )
1609
    return 0; // no change
1610
 
1611
  SEQ_CC_Set(visible_track, cc, new_value);
1612
 
179 tk 1613
  // do same modification for all selected tracks
1614
  u8 track;
1615
  for(track=0; track<SEQ_CORE_NUM_TRACKS; ++track)
1616
    if( track != visible_track && SEQ_UI_IsSelectedTrack(track) ) {
1617
      int new_value = SEQ_CC_Get(track, cc);
1618
      new_value = (new_value & ~flag_mask) | value;
1619
      SEQ_CC_Set(track, cc, new_value);
1620
    }
1621
 
173 tk 1622
  return 1; // value changed
1623
}
1624
 
1625
 
299 tk 1626
/////////////////////////////////////////////////////////////////////////////
1627
// Print temporary messages after file operations
1628
// expects mS delay and two lines, each up to 20 characters
1629
/////////////////////////////////////////////////////////////////////////////
1630
s32 SEQ_UI_SDCardMsg(u16 delay, char *line1, char *line2)
1631
{
1632
  sdcard_msg_ctr = delay;
1633
  strncpy((char *)sdcard_msg[0], line1, SDCARD_MSG_MAX_CHAR);
1634
  strncpy((char *)sdcard_msg[1], line2, SDCARD_MSG_MAX_CHAR);
1635
 
1636
  return 0; // no error
1637
}
1638
 
1639
/////////////////////////////////////////////////////////////////////////////
1640
// Prints a temporary error messages after file operation
1641
// Expects error status number (as defined in seq_file.h)
1642
/////////////////////////////////////////////////////////////////////////////
1643
s32 SEQ_UI_SDCardErrMsg(u16 delay, s32 status)
1644
{
1645
  // TODO: add more verbose error messages, they are clearly defined in seq_file.h)
1646
  char str[21];
1647
  sprintf(str, "E%3d (DOSFS: D%3d)", -status, seq_file_dfs_errno < 1000 ? seq_file_dfs_errno : 999);
1648
  return SEQ_UI_SDCardMsg(delay, "!! SD Card Error !!!", str);
1649
}