Subversion Repositories svn.mios32

Rev

Rev 481 | Rev 492 | 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 484 2009-05-04 20:16:40Z 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
 * TODO: chained tracks are obsolete, but we could combine 4 tracks to much larger track w/o much effort
10
 *
134 tk 11
 * ==========================================================================
12
 *
13
 *  Copyright (C) 2008 Thorsten Klose (tk@midibox.org)
14
 *  Licensed for personal non-commercial use only.
15
 *  All other rights reserved.
16
 *
17
 * ==========================================================================
18
 */
19
 
20
/////////////////////////////////////////////////////////////////////////////
21
// Include files
22
/////////////////////////////////////////////////////////////////////////////
23
 
272 tk 24
// with this switch, seq_ui.h/seq_ui_pages.inc will create local variables
25
#define SEQ_UI_PAGES_INC_LOCAL_VARS 1
26
 
134 tk 27
#include <mios32.h>
299 tk 28
#include <string.h>
464 tk 29
#include <blm_x.h>
190 tk 30
#include <seq_midi_out.h>
31
#include <seq_bpm.h>
134 tk 32
 
290 tk 33
#include "tasks.h"
134 tk 34
#include "seq_ui.h"
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
{
328 tk 880
  // ensure that selections are matching with track constraints
881
  SEQ_UI_CheckSelections();
882
 
134 tk 883
  switch( pin ) {
168 tk 884
#if BUTTON_GP1 != BUTTON_DISABLED
134 tk 885
    case BUTTON_GP1:   SEQ_UI_Button_GP(pin_value, 0); break;
886
#endif
168 tk 887
#if BUTTON_GP2 != BUTTON_DISABLED
134 tk 888
    case BUTTON_GP2:   SEQ_UI_Button_GP(pin_value, 1); break;
889
#endif
168 tk 890
#if BUTTON_GP3 != BUTTON_DISABLED
134 tk 891
    case BUTTON_GP3:   SEQ_UI_Button_GP(pin_value, 2); break;
892
#endif
168 tk 893
#if BUTTON_GP4 != BUTTON_DISABLED
134 tk 894
    case BUTTON_GP4:   SEQ_UI_Button_GP(pin_value, 3); break;
895
#endif
168 tk 896
#if BUTTON_GP5 != BUTTON_DISABLED
134 tk 897
    case BUTTON_GP5:   SEQ_UI_Button_GP(pin_value, 4); break;
898
#endif
168 tk 899
#if BUTTON_GP6 != BUTTON_DISABLED
134 tk 900
    case BUTTON_GP6:   SEQ_UI_Button_GP(pin_value, 5); break;
901
#endif
168 tk 902
#if BUTTON_GP7 != BUTTON_DISABLED
134 tk 903
    case BUTTON_GP7:   SEQ_UI_Button_GP(pin_value, 6); break;
904
#endif
168 tk 905
#if BUTTON_GP8 != BUTTON_DISABLED
134 tk 906
    case BUTTON_GP8:   SEQ_UI_Button_GP(pin_value, 7); break;
907
#endif
168 tk 908
#if BUTTON_GP9 != BUTTON_DISABLED
134 tk 909
    case BUTTON_GP9:   SEQ_UI_Button_GP(pin_value, 8); break;
910
#endif
168 tk 911
#if BUTTON_GP10 != BUTTON_DISABLED
134 tk 912
    case BUTTON_GP10:  SEQ_UI_Button_GP(pin_value, 9); break;
913
#endif
168 tk 914
#if BUTTON_GP11 != BUTTON_DISABLED
134 tk 915
    case BUTTON_GP11:  SEQ_UI_Button_GP(pin_value, 10); break;
916
#endif
168 tk 917
#if BUTTON_GP12 != BUTTON_DISABLED
134 tk 918
    case BUTTON_GP12:  SEQ_UI_Button_GP(pin_value, 11); break;
919
#endif
168 tk 920
#if BUTTON_GP13 != BUTTON_DISABLED
134 tk 921
    case BUTTON_GP13:  SEQ_UI_Button_GP(pin_value, 12); break;
922
#endif
168 tk 923
#if BUTTON_GP14 != BUTTON_DISABLED
134 tk 924
    case BUTTON_GP14:  SEQ_UI_Button_GP(pin_value, 13); break;
925
#endif
168 tk 926
#if BUTTON_GP15 != BUTTON_DISABLED
134 tk 927
    case BUTTON_GP15:  SEQ_UI_Button_GP(pin_value, 14); break;
928
#endif
168 tk 929
#if BUTTON_GP16 != BUTTON_DISABLED
134 tk 930
    case BUTTON_GP16:  SEQ_UI_Button_GP(pin_value, 15); break;
931
#endif
932
 
168 tk 933
#if BUTTON_LEFT != BUTTON_DISABLED
134 tk 934
    case BUTTON_LEFT:  SEQ_UI_Button_Left(pin_value); break;
935
#endif
168 tk 936
#if BUTTON_RIGHT != BUTTON_DISABLED
134 tk 937
    case BUTTON_RIGHT: SEQ_UI_Button_Right(pin_value); break;
938
#endif
939
 
168 tk 940
#if BUTTON_DOWN != BUTTON_DISABLED
941
    case BUTTON_DOWN:  SEQ_UI_Button_Down(pin_value); break;
942
#endif
943
#if BUTTON_UP != BUTTON_DISABLED
944
    case BUTTON_UP:    SEQ_UI_Button_Up(pin_value); break;
945
#endif
946
 
947
#if BUTTON_SCRUB != BUTTON_DISABLED
134 tk 948
    case BUTTON_SCRUB: SEQ_UI_Button_Scrub(pin_value); break;
949
#endif
168 tk 950
#if BUTTON_METRONOME != BUTTON_DISABLED
134 tk 951
    case BUTTON_METRONOME: SEQ_UI_Button_Metronome(pin_value); break;
952
#endif
953
 
168 tk 954
#if BUTTON_STOP != BUTTON_DISABLED
134 tk 955
    case BUTTON_STOP:  SEQ_UI_Button_Stop(pin_value); break;
956
#endif
168 tk 957
#if BUTTON_PAUSE != BUTTON_DISABLED
134 tk 958
    case BUTTON_PAUSE: SEQ_UI_Button_Pause(pin_value); break;
959
#endif
168 tk 960
#if BUTTON_PLAY != BUTTON_DISABLED
134 tk 961
    case BUTTON_PLAY:  SEQ_UI_Button_Play(pin_value); break;
962
#endif
168 tk 963
#if BUTTON_REW != BUTTON_DISABLED
134 tk 964
    case BUTTON_REW:   SEQ_UI_Button_Rew(pin_value); break;
965
#endif
168 tk 966
#if BUTTON_FWD != BUTTON_DISABLED
134 tk 967
    case BUTTON_FWD:   SEQ_UI_Button_Fwd(pin_value); break;
968
#endif
969
 
168 tk 970
#if BUTTON_F1 != BUTTON_DISABLED
134 tk 971
    case BUTTON_F1:    SEQ_UI_Button_F1(pin_value); break;
972
#endif
168 tk 973
#if BUTTON_F2 != BUTTON_DISABLED
134 tk 974
    case BUTTON_F2:    SEQ_UI_Button_F2(pin_value); break;
975
#endif
168 tk 976
#if BUTTON_F3 != BUTTON_DISABLED
134 tk 977
    case BUTTON_F3:    SEQ_UI_Button_F3(pin_value); break;
978
#endif
168 tk 979
#if BUTTON_F4 != BUTTON_DISABLED
134 tk 980
    case BUTTON_F4:    SEQ_UI_Button_F4(pin_value); break;
981
#endif
982
 
168 tk 983
#if BUTTON_UTILITY != BUTTON_DISABLED
134 tk 984
    case BUTTON_UTILITY: SEQ_UI_Button_Utility(pin_value); break;
985
#endif
168 tk 986
#if BUTTON_COPY != BUTTON_DISABLED
134 tk 987
    case BUTTON_COPY:  SEQ_UI_Button_Copy(pin_value); break;
988
#endif
168 tk 989
#if BUTTON_PASTE != BUTTON_DISABLED
134 tk 990
    case BUTTON_PASTE: SEQ_UI_Button_Paste(pin_value); break;
991
#endif
168 tk 992
#if BUTTON_CLEAR != BUTTON_DISABLED
134 tk 993
    case BUTTON_CLEAR: SEQ_UI_Button_Clear(pin_value); break;
994
#endif
995
 
168 tk 996
#if BUTTON_MENU != BUTTON_DISABLED
134 tk 997
    case BUTTON_MENU:  SEQ_UI_Button_Menu(pin_value); break;
998
#endif
168 tk 999
#if BUTTON_SELECT != BUTTON_DISABLED
134 tk 1000
    case BUTTON_SELECT:SEQ_UI_Button_Select(pin_value); break;
1001
#endif
168 tk 1002
#if BUTTON_EXIT != BUTTON_DISABLED
134 tk 1003
    case BUTTON_EXIT:  SEQ_UI_Button_Exit(pin_value); break;
1004
#endif
1005
 
168 tk 1006
#if BUTTON_TRACK1 != BUTTON_DISABLED
134 tk 1007
    case BUTTON_TRACK1: SEQ_UI_Button_Track(pin_value, 0); break;
1008
#endif
168 tk 1009
#if BUTTON_TRACK2 != BUTTON_DISABLED
134 tk 1010
    case BUTTON_TRACK2: SEQ_UI_Button_Track(pin_value, 1); break;
1011
#endif
168 tk 1012
#if BUTTON_TRACK3 != BUTTON_DISABLED
134 tk 1013
    case BUTTON_TRACK3: SEQ_UI_Button_Track(pin_value, 2); break;
1014
#endif
168 tk 1015
#if BUTTON_TRACK4 != BUTTON_DISABLED
134 tk 1016
    case BUTTON_TRACK4: SEQ_UI_Button_Track(pin_value, 3); break;
1017
#endif
1018
 
168 tk 1019
#if BUTTON_PAR_LAYER_A != BUTTON_DISABLED
134 tk 1020
    case BUTTON_PAR_LAYER_A: SEQ_UI_Button_ParLayer(pin_value, 0); break;
1021
#endif
168 tk 1022
#if BUTTON_PAR_LAYER_B != BUTTON_DISABLED
134 tk 1023
    case BUTTON_PAR_LAYER_B: SEQ_UI_Button_ParLayer(pin_value, 1); break;
1024
#endif
168 tk 1025
#if BUTTON_PAR_LAYER_C != BUTTON_DISABLED
134 tk 1026
    case BUTTON_PAR_LAYER_C: SEQ_UI_Button_ParLayer(pin_value, 2); break;
1027
#endif
1028
 
168 tk 1029
#if BUTTON_EDIT != BUTTON_DISABLED
134 tk 1030
    case BUTTON_EDIT:   SEQ_UI_Button_Edit(pin_value); break;
1031
#endif
168 tk 1032
#if BUTTON_MUTE != BUTTON_DISABLED
134 tk 1033
    case BUTTON_MUTE:   SEQ_UI_Button_Mute(pin_value); break;
1034
#endif
168 tk 1035
#if BUTTON_PATTERN != BUTTON_DISABLED
134 tk 1036
    case BUTTON_PATTERN:SEQ_UI_Button_Pattern(pin_value); break;
1037
#endif
168 tk 1038
#if BUTTON_SONG != BUTTON_DISABLED
134 tk 1039
    case BUTTON_SONG:   SEQ_UI_Button_Song(pin_value); break;
1040
#endif
1041
 
168 tk 1042
#if BUTTON_SOLO != BUTTON_DISABLED
134 tk 1043
    case BUTTON_SOLO:   SEQ_UI_Button_Solo(pin_value); break;
1044
#endif
168 tk 1045
#if BUTTON_FAST != BUTTON_DISABLED
134 tk 1046
    case BUTTON_FAST:   SEQ_UI_Button_Fast(pin_value); break;
1047
#endif
168 tk 1048
#if BUTTON_ALL != BUTTON_DISABLED
134 tk 1049
    case BUTTON_ALL:    SEQ_UI_Button_All(pin_value); break;
1050
#endif
1051
 
168 tk 1052
#if BUTTON_GROUP1 != BUTTON_DISABLED
134 tk 1053
    case BUTTON_GROUP1: SEQ_UI_Button_Group(pin_value, 0); break;
1054
#endif
168 tk 1055
#if BUTTON_GROUP2 != BUTTON_DISABLED
134 tk 1056
    case BUTTON_GROUP2: SEQ_UI_Button_Group(pin_value, 1); break;
1057
#endif
168 tk 1058
#if BUTTON_GROUP3 != BUTTON_DISABLED
134 tk 1059
    case BUTTON_GROUP3: SEQ_UI_Button_Group(pin_value, 2); break;
1060
#endif
168 tk 1061
#if BUTTON_GROUP4 != BUTTON_DISABLED
134 tk 1062
    case BUTTON_GROUP4: SEQ_UI_Button_Group(pin_value, 3); break;
1063
#endif
1064
 
168 tk 1065
#if BUTTON_TRG_LAYER_A != BUTTON_DISABLED
134 tk 1066
    case BUTTON_TRG_LAYER_A: SEQ_UI_Button_TrgLayer(pin_value, 0); break;
1067
#endif
168 tk 1068
#if BUTTON_TRG_LAYER_B != BUTTON_DISABLED
134 tk 1069
    case BUTTON_TRG_LAYER_B: SEQ_UI_Button_TrgLayer(pin_value, 1); break;
1070
#endif
168 tk 1071
#if BUTTON_TRG_LAYER_C != BUTTON_DISABLED
134 tk 1072
    case BUTTON_TRG_LAYER_C: SEQ_UI_Button_TrgLayer(pin_value, 2); break;
1073
#endif
1074
 
168 tk 1075
#if BUTTON_STEP_VIEW != BUTTON_DISABLED
134 tk 1076
    case BUTTON_STEP_VIEW: SEQ_UI_Button_StepView(pin_value); break;
1077
#endif
1078
 
168 tk 1079
#if BUTTON_TAP_TEMPO != BUTTON_DISABLED
134 tk 1080
    case BUTTON_TAP_TEMPO:   SEQ_UI_Button_TapTempo(pin_value); break;
1081
#endif
1082
 
1083
    default:
1084
      return -1; // button function not mapped to physical button
1085
  }
1086
 
1087
  // request display update
159 tk 1088
  seq_ui_display_update_req = 1;
134 tk 1089
 
1090
  return 0; // no error
1091
}
1092
 
1093
 
1094
/////////////////////////////////////////////////////////////////////////////
1095
// Encoder handler
1096
/////////////////////////////////////////////////////////////////////////////
1097
s32 SEQ_UI_Encoder_Handler(u32 encoder, s32 incrementer)
1098
{
1099
  if( encoder > 16 )
1100
    return -1; // encoder doesn't exist
1101
 
328 tk 1102
  // ensure that selections are matching with track constraints
1103
  SEQ_UI_CheckSelections();
1104
 
134 tk 1105
  // limit incrementer
1106
  if( incrementer > 3 )
1107
    incrementer = 3;
1108
  else if( incrementer < -3 )
1109
    incrementer = -3;
1110
 
306 tk 1111
  if( !seq_ui_button_state.MENU_PRESSED && ui_encoder_callback != NULL ) {
173 tk 1112
    ui_encoder_callback((encoder == 0) ? SEQ_UI_ENCODER_Datawheel : (encoder-1), incrementer);
1113
    ui_cursor_flash_ctr = 0; // ensure that value is visible when it has been changed
134 tk 1114
  }
1115
 
1116
  // request display update
159 tk 1117
  seq_ui_display_update_req = 1;
134 tk 1118
 
1119
  return 0; // no error
1120
}
1121
 
1122
 
353 tk 1123
 
134 tk 1124
/////////////////////////////////////////////////////////////////////////////
1125
// Update LCD messages
1126
// Usually called from background task
1127
/////////////////////////////////////////////////////////////////////////////
1128
s32 SEQ_UI_LCD_Handler(void)
1129
{
159 tk 1130
  if( seq_ui_display_init_req ) {
1131
    seq_ui_display_init_req = 0; // clear request
134 tk 1132
 
278 tk 1133
    // clear force update of LCD
1134
    SEQ_LCD_Clear();
1135
    SEQ_LCD_Update(1);
134 tk 1136
 
168 tk 1137
    // select first menu item
1138
    ui_selected_item = 0;
1139
 
167 tk 1140
    // call init function of current page
272 tk 1141
    if( ui_menu_pages[ui_page].init_callback != NULL )
1142
      ui_menu_pages[ui_page].init_callback(0); // mode
134 tk 1143
 
1144
    // request display update
159 tk 1145
    seq_ui_display_update_req = 1;
134 tk 1146
  }
1147
 
306 tk 1148
  // in MENU page: overrule LCD output so long MENU button is pressed/active
1149
  if( seq_ui_button_state.MENU_PRESSED && !seq_ui_button_state.MENU_FIRST_PAGE_SELECTED ) {
1150
    SEQ_LCD_CursorSet(0, 0);
1151
    //                      <-------------------------------------->
1152
    //                      0123456789012345678901234567890123456789
1153
    SEQ_LCD_PrintString("Menu Shortcuts:");
1154
    SEQ_LCD_PrintSpaces(25 + 40);
1155
    SEQ_LCD_CursorSet(0, 1);
1156
    SEQ_LCD_PrintString(UI_SHORTCUT_STR); // defined in seq_ui_pages.inc
1157
  } else {
1158
    // perform high priority LCD update request
1159
    if( ui_lcd_callback != NULL )
1160
      ui_lcd_callback(1); // high_prio
167 tk 1161
 
306 tk 1162
    // perform low priority LCD update request if requested
1163
    if( seq_ui_display_update_req ) {
1164
      seq_ui_display_update_req = 0; // clear request
328 tk 1165
 
1166
      // ensure that selections are matching with track constraints
1167
      SEQ_UI_CheckSelections();
1168
 
306 tk 1169
      if( ui_lcd_callback != NULL )
1170
    ui_lcd_callback(0); // no high_prio
1171
    }
134 tk 1172
  }
1173
 
353 tk 1174
  // transfer all changed characters to LCD
1175
  SEQ_UI_LCD_Update();
1176
 
1177
  return 0; // no error
1178
}
1179
 
1180
 
1181
/////////////////////////////////////////////////////////////////////////////
1182
// Called from SEQ_UI_LCD_Handler(), but optionally also from other tasks
1183
// to update the LCD screen immediately
1184
/////////////////////////////////////////////////////////////////////////////
1185
s32 SEQ_UI_LCD_Update(void)
1186
{
299 tk 1187
  // if SD card message active: copy over the text
1188
  if( sdcard_msg_ctr ) {
1189
    const char animation_l[4][3] = {
1190
      "  ", " >", ">>", "> " };
1191
    const char animation_r[4][3] = {
1192
      "  ", "< ", "<<", " <" };
1193
    int anum = (sdcard_msg_ctr % 1000) / 250;
1194
 
1195
    int line;
1196
    for(line=0; line<2; ++line) {
353 tk 1197
      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 1198
      SEQ_LCD_PrintFormattedString(" %s| %-20s |%s ",
1199
                   (char *)animation_l[anum],
1200
                   (char *)sdcard_msg[line],
1201
                   (char *)animation_r[anum]);
1202
    }
1203
  }
1204
 
278 tk 1205
  // transfer all changed characters to LCD
353 tk 1206
  // SEQ_LCD_Update provides a MUTEX handling to allow updates from different tasks
1207
  return SEQ_LCD_Update(0);
134 tk 1208
}
1209
 
1210
 
1211
/////////////////////////////////////////////////////////////////////////////
1212
// Update all LEDs
1213
// Usually called from background task
1214
/////////////////////////////////////////////////////////////////////////////
1215
s32 SEQ_UI_LED_Handler(void)
1216
{
326 tk 1217
  u8 visible_track = SEQ_UI_VisibleTrackGet();
1218
  u8 event_mode = SEQ_CC_Get(visible_track, SEQ_CC_MIDI_EVENT_MODE);
1219
 
134 tk 1220
  // track LEDs
484 tk 1221
  u8 selected_tracks = ui_selected_tracks >> (4*ui_selected_group);
1222
  SEQ_LED_PinSet(LED_TRACK1, (selected_tracks & (1 << 0)));
1223
  SEQ_LED_PinSet(LED_TRACK2, (selected_tracks & (1 << 1)));
1224
  SEQ_LED_PinSet(LED_TRACK3, (selected_tracks & (1 << 2)));
1225
  SEQ_LED_PinSet(LED_TRACK4, (selected_tracks & (1 << 3)));
134 tk 1226
 
1227
  // parameter layer LEDs
167 tk 1228
  SEQ_LED_PinSet(LED_PAR_LAYER_A, (ui_selected_par_layer == 0));
1229
  SEQ_LED_PinSet(LED_PAR_LAYER_B, (ui_selected_par_layer == 1));
326 tk 1230
  SEQ_LED_PinSet(LED_PAR_LAYER_C, (ui_selected_par_layer >= 2) || seq_ui_button_state.PAR_LAYER_SEL);
134 tk 1231
 
1232
  // group LEDs
167 tk 1233
  SEQ_LED_PinSet(LED_GROUP1, (ui_selected_group == 0));
1234
  SEQ_LED_PinSet(LED_GROUP2, (ui_selected_group == 1));
1235
  SEQ_LED_PinSet(LED_GROUP3, (ui_selected_group == 2));
1236
  SEQ_LED_PinSet(LED_GROUP4, (ui_selected_group == 3));
134 tk 1237
 
1238
  // trigger layer LEDs
328 tk 1239
  SEQ_LED_PinSet(LED_TRG_LAYER_A, (ui_selected_trg_layer == 0));
1240
  SEQ_LED_PinSet(LED_TRG_LAYER_B, (ui_selected_trg_layer == 1));
1241
  SEQ_LED_PinSet(LED_TRG_LAYER_C, (ui_selected_trg_layer >= 2) || seq_ui_button_state.TRG_LAYER_SEL);
134 tk 1242
 
1243
  // remaining LEDs
167 tk 1244
  SEQ_LED_PinSet(LED_EDIT, ui_page == SEQ_UI_PAGE_EDIT);
184 tk 1245
  SEQ_LED_PinSet(LED_MUTE, ui_page == SEQ_UI_PAGE_MUTE);
1246
  SEQ_LED_PinSet(LED_PATTERN, ui_page == SEQ_UI_PAGE_PATTERN);
399 tk 1247
  if( SEQ_SONG_ActiveGet() )
1248
    SEQ_LED_PinSet(LED_SONG, 1);
1249
  else
1250
    SEQ_LED_PinSet(LED_SONG, ui_cursor_flash ? 0 : (ui_page == SEQ_UI_PAGE_SONG));
134 tk 1251
 
178 tk 1252
  SEQ_LED_PinSet(LED_SOLO, seq_ui_button_state.SOLO);
1253
  SEQ_LED_PinSet(LED_FAST, seq_ui_button_state.FAST_ENCODERS);
1254
  SEQ_LED_PinSet(LED_ALL, seq_ui_button_state.CHANGE_ALL_STEPS);
134 tk 1255
 
193 tk 1256
  SEQ_LED_PinSet(LED_PLAY, SEQ_BPM_IsRunning());
1257
  SEQ_LED_PinSet(LED_STOP, !SEQ_BPM_IsRunning() && !ui_seq_pause);
1258
  SEQ_LED_PinSet(LED_PAUSE, ui_seq_pause);
240 tk 1259
 
1260
  SEQ_LED_PinSet(LED_REW, seq_ui_button_state.REW);
1261
  SEQ_LED_PinSet(LED_FWD, seq_ui_button_state.FWD);
134 tk 1262
 
303 tk 1263
  SEQ_LED_PinSet(LED_STEPVIEW, seq_ui_button_state.STEPVIEW);
134 tk 1264
 
167 tk 1265
  SEQ_LED_PinSet(LED_MENU, seq_ui_button_state.MENU_PRESSED);
178 tk 1266
  SEQ_LED_PinSet(LED_SCRUB, seq_ui_button_state.SCRUB);
1267
  SEQ_LED_PinSet(LED_METRONOME, seq_ui_button_state.METRONOME);
134 tk 1268
 
240 tk 1269
  SEQ_LED_PinSet(LED_UTILITY, ui_page == SEQ_UI_PAGE_UTIL);
1270
  SEQ_LED_PinSet(LED_COPY, seq_ui_button_state.COPY);
1271
  SEQ_LED_PinSet(LED_PASTE, seq_ui_button_state.PASTE);
1272
  SEQ_LED_PinSet(LED_CLEAR, seq_ui_button_state.CLEAR);
1273
 
1274
  SEQ_LED_PinSet(LED_F1, seq_ui_button_state.F1);
1275
  SEQ_LED_PinSet(LED_F2, seq_ui_button_state.F2);
1276
  SEQ_LED_PinSet(LED_F3, seq_ui_button_state.F3);
1277
  SEQ_LED_PinSet(LED_F4, seq_ui_button_state.F4);
1278
 
1279
  SEQ_LED_PinSet(LED_DOWN, seq_ui_button_state.DOWN);
1280
  SEQ_LED_PinSet(LED_UP, seq_ui_button_state.UP);
1281
 
167 tk 1282
 
306 tk 1283
  // in MENU page: overrule GP LEDs so long MENU button is pressed/active
1284
  if( seq_ui_button_state.MENU_PRESSED ) {
1285
    if( ui_cursor_flash ) // if flashing flag active: no LED flag set
1286
      ui_gp_leds = 0x0000;
1287
    else {
1288
      int i;
1289
      u16 new_ui_gp_leds = 0x0000;
1290
      for(i=0; i<16; ++i)
1291
    if( ui_page == ui_shortcut_menu_pages[i] )
1292
      new_ui_gp_leds |= (1 << i);
1293
      ui_gp_leds = new_ui_gp_leds;
1294
    }
1295
  } else {
1296
    // note: the background function is permanently interrupted - therefore we write the GP pattern
1297
    // into a temporary variable, and take it over once completed
1298
    u16 new_ui_gp_leds = 0x0000;
1299
    // request GP LED values from current menu page
1300
    // will be transfered to DOUT registers in SEQ_UI_LED_Handler_Periodic
1301
    new_ui_gp_leds = 0x0000;
206 tk 1302
 
306 tk 1303
    if( ui_led_callback != NULL )
1304
      ui_led_callback(&new_ui_gp_leds);
167 tk 1305
 
306 tk 1306
    ui_gp_leds = new_ui_gp_leds;
1307
  }
1308
 
134 tk 1309
  return 0; // no error
1310
}
1311
 
1312
 
1313
/////////////////////////////////////////////////////////////////////////////
1314
// updates high-prio LED functions (GP LEDs and Beat LED)
168 tk 1315
// called each mS
134 tk 1316
/////////////////////////////////////////////////////////////////////////////
1317
s32 SEQ_UI_LED_Handler_Periodic()
1318
{
1319
  // GP LEDs are only updated when ui_gp_leds or pos_marker_mask has changed
1320
  static u16 prev_ui_gp_leds = 0x0000;
1321
  static u16 prev_pos_marker_mask = 0x0000;
1322
 
1323
  // beat LED: tmp. for demo w/o real sequencer
193 tk 1324
  u8 sequencer_running = SEQ_BPM_IsRunning();
325 tk 1325
  SEQ_LED_PinSet(LED_BEAT, sequencer_running && ((seq_core_state.ref_step & 3) == 0));
134 tk 1326
 
1327
  // for song position marker (supports 16 LEDs, check for selected step view)
1328
  u16 pos_marker_mask = 0x0000;
325 tk 1329
  u8 visible_track = SEQ_UI_VisibleTrackGet();
1330
  u8 played_step = seq_core_trk[visible_track].step;
1331
  if( seq_ui_button_state.STEPVIEW ) {
1332
    // if STEPVIEW button pressed: pos marker correlated to zoom ratio
1333
    if( sequencer_running )
1334
      pos_marker_mask = 1 << (played_step / (SEQ_TRG_NumStepsGet(visible_track)/16));
1335
  } else {
1336
    if( sequencer_running && (played_step >> 4) == ui_selected_step_view )
1337
      pos_marker_mask = 1 << (played_step & 0xf);
1338
  }
134 tk 1339
 
1340
  // exit of pattern hasn't changed
173 tk 1341
  if( prev_ui_gp_leds == ui_gp_leds && prev_pos_marker_mask == pos_marker_mask )
134 tk 1342
    return 0;
173 tk 1343
  prev_ui_gp_leds = ui_gp_leds;
134 tk 1344
  prev_pos_marker_mask = pos_marker_mask;
1345
 
1346
  // transfer to GP LEDs
1347
 
1348
#ifdef DEFAULT_GP_DOUT_SR_L
1349
# ifdef DEFAULT_GP_DOUT_SR_L2
173 tk 1350
  SEQ_LED_SRSet(DEFAULT_GP_DOUT_SR_L-1, (ui_gp_leds >> 0) & 0xff);
134 tk 1351
# else
173 tk 1352
  SEQ_LED_SRSet(DEFAULT_GP_DOUT_SR_L-1, ((ui_gp_leds ^ pos_marker_mask) >> 0) & 0xff);
134 tk 1353
# endif
1354
#endif
1355
#ifdef DEFAULT_GP_DOUT_SR_R
1356
# ifdef DEFAULT_GP_DOUT_SR_R2
173 tk 1357
  SEQ_LED_SRSet(DEFAULT_GP_DOUT_SR_R-1, (ui_gp_leds >> 8) & 0xff);
134 tk 1358
#else
173 tk 1359
  SEQ_LED_SRSet(DEFAULT_GP_DOUT_SR_R-1, ((ui_gp_leds ^ pos_marker_mask) >> 8) & 0xff);
134 tk 1360
#endif
1361
#endif
1362
 
1363
#ifdef DEFAULT_GP_DOUT_SR_L2
1364
  SEQ_LED_SRSet(DEFAULT_GP_DOUT_SR_L2-1, (pos_marker_mask >> 0) & 0xff);
1365
#endif
1366
#ifdef DEFAULT_GP_DOUT_SR_R2
1367
  SEQ_LED_SRSet(DEFAULT_GP_DOUT_SR_R2-1, (pos_marker_mask >> 8) & 0xff);
1368
#endif
1369
 
1370
#if DEFAULT_SRM_ENABLED && DEFAULT_SRM_DOUT_M_MAPPING == 1
1371
  // for wilba's frontpanel
1372
 
464 tk 1373
  // BLM_X DOUT -> GP LED mapping
134 tk 1374
  // 0 = 15,16  1 = 13,14   2 = 11,12   3 = 9,10
1375
  // 4 = 1,2    5 = 3,4     6 = 5,6     7 = 7,8
1376
 
1377
  // bit 7: first green (i.e. GP1-G)
1378
  // bit 6: first red (i.e. GP1-R)
1379
  // bit 5: second green (i.e. GP2-G)
1380
  // bit 4: second red (i.e. GP2-R)
1381
 
1382
  // this mapping routine takes ca. 5 uS
173 tk 1383
  // since it's only executed when ui_gp_leds or gp_mask has changed, it doesn't really hurt
134 tk 1384
 
173 tk 1385
  u16 modified_gp_leds = ui_gp_leds;
134 tk 1386
#if 1
1387
  // extra: red LED is lit exclusively for higher contrast
1388
  modified_gp_leds &= ~pos_marker_mask;
1389
#endif
1390
 
1391
  int sr;
464 tk 1392
  const u8 blm_x_sr_map[8] = {4, 5, 6, 7, 3, 2, 1, 0};
134 tk 1393
  u16 gp_mask = 1 << 0;
1394
  for(sr=0; sr<8; ++sr) {
1395
    u8 pattern = 0;
1396
 
1397
    if( modified_gp_leds & gp_mask )
1398
      pattern |= 0x80;
1399
    if( pos_marker_mask & gp_mask )
1400
      pattern |= 0x40;
1401
    gp_mask <<= 1;
1402
    if( modified_gp_leds & gp_mask )
1403
      pattern |= 0x20;
1404
    if( pos_marker_mask & gp_mask )
1405
      pattern |= 0x10;
1406
    gp_mask <<= 1;
1407
 
464 tk 1408
    u8 mapped_sr = blm_x_sr_map[sr];
1409
    BLM_X_LED_rows[mapped_sr][0] = (BLM_X_LED_rows[mapped_sr][0] & 0x0f) | pattern;
134 tk 1410
  }
1411
#endif
1412
 
184 tk 1413
  return 0; // no error
134 tk 1414
}
1415
 
1416
 
1417
/////////////////////////////////////////////////////////////////////////////
168 tk 1418
// for menu handling (e.g. flashing cursor, doubleclick counter, etc...)
1419
// called each mS
1420
/////////////////////////////////////////////////////////////////////////////
1421
s32 SEQ_UI_MENU_Handler_Periodic()
1422
{
1423
  if( ++ui_cursor_flash_ctr >= SEQ_UI_CURSOR_FLASH_CTR_MAX ) {
1424
    ui_cursor_flash_ctr = 0;
1425
    seq_ui_display_update_req = 1;
173 tk 1426
  } else if( ui_cursor_flash_ctr == SEQ_UI_CURSOR_FLASH_CTR_LED_OFF ) {
168 tk 1427
    seq_ui_display_update_req = 1;
173 tk 1428
  }
1429
  // important: flash flag has to be recalculated on each invocation of this
1430
  // handler, since counter could also be reseted outside this function
1431
  ui_cursor_flash = ui_cursor_flash_ctr >= SEQ_UI_CURSOR_FLASH_CTR_LED_OFF;
168 tk 1432
 
184 tk 1433
 
240 tk 1434
  // used in some pages for temporary messages
416 tk 1435
  if( ui_hold_msg_ctr ) {
240 tk 1436
    --ui_hold_msg_ctr;
1437
 
416 tk 1438
    if( !ui_hold_msg_ctr )
1439
      seq_ui_display_update_req = 1;
1440
  }
1441
 
299 tk 1442
  // used for temporary SD Card messages
1443
  if( sdcard_msg_ctr )
1444
    --sdcard_msg_ctr;
1445
 
184 tk 1446
  // VU meters (used in MUTE menu, could also be available as LED matrix...)
1447
  static u8 vu_meter_prediv = 0; // predivider for VU meters
1448
 
1449
  if( ++vu_meter_prediv >= 4 ) {
1450
    vu_meter_prediv = 0;
1451
 
333 tk 1452
 
1453
    portENTER_CRITICAL();
1454
 
184 tk 1455
    u8 track;
1456
    seq_core_trk_t *t = &seq_core_trk[0];
1457
    for(track=0; track<SEQ_CORE_NUM_TRACKS; ++t, ++track)
1458
      if( t->vu_meter )
1459
    --t->vu_meter;
333 tk 1460
 
1461
    int i;
1462
    u8 *vu_meter = (u8 *)&seq_layer_vu_meter[0];
1463
    for(i=0; i<sizeof(seq_layer_vu_meter); ++i, ++vu_meter) {
1464
      if( *vu_meter && !(*vu_meter & 0x80) ) // if bit 7 set: static value
1465
    *vu_meter -= 1;
1466
    }
1467
 
318 tk 1468
    portEXIT_CRITICAL();
184 tk 1469
  }
1470
 
168 tk 1471
  return 0;
1472
}
1473
 
1474
 
1475
/////////////////////////////////////////////////////////////////////////////
328 tk 1476
// Should be regulary called to check if the layer/instrument/step selection
1477
// is valid for the current track
1478
// At least executed before button/encoder and LCD function calls
1479
/////////////////////////////////////////////////////////////////////////////
1480
s32 SEQ_UI_CheckSelections(void)
1481
{
1482
  u8 visible_track = SEQ_UI_VisibleTrackGet();
1483
 
1484
  if( ui_selected_instrument >= SEQ_PAR_NumInstrumentsGet(visible_track) )
1485
    ui_selected_instrument = 0;
1486
 
1487
  if( ui_selected_par_layer >= SEQ_PAR_NumLayersGet(visible_track) )
1488
    ui_selected_par_layer = 0;
1489
 
1490
  if( ui_selected_trg_layer >= SEQ_TRG_NumLayersGet(visible_track) )
1491
    ui_selected_trg_layer = 0;
1492
 
1493
  if( ui_selected_step >= SEQ_TRG_NumStepsGet(visible_track) )
1494
    ui_selected_step = 0;
1495
 
1496
  if( ui_selected_step_view >= (SEQ_TRG_NumStepsGet(visible_track)/16) ) {
1497
    ui_selected_step_view = 0;
1498
    ui_selected_step %= 16;
1499
  }
1500
 
336 tk 1501
  if( ui_selected_step < (16*ui_selected_step_view) ||
1502
      ui_selected_step >= (16*(ui_selected_step_view+1)) )
328 tk 1503
    ui_selected_step_view = ui_selected_step / 16;
1504
 
1505
  return 0; // no error
1506
}
1507
 
1508
 
1509
/////////////////////////////////////////////////////////////////////////////
134 tk 1510
// Returns the currently visible track
1511
/////////////////////////////////////////////////////////////////////////////
1512
u8 SEQ_UI_VisibleTrackGet(void)
1513
{
1514
  u8 offset = 0;
1515
 
484 tk 1516
  u8 selected_tracks = ui_selected_tracks >> (4*ui_selected_group);
1517
  if( selected_tracks & (1 << 3) )
134 tk 1518
    offset = 3;
484 tk 1519
  if( selected_tracks & (1 << 2) )
134 tk 1520
    offset = 2;
484 tk 1521
  if( selected_tracks & (1 << 1) )
134 tk 1522
    offset = 1;
484 tk 1523
  if( selected_tracks & (1 << 0) )
134 tk 1524
    offset = 0;
1525
 
1526
  return 4*ui_selected_group + offset;
1527
}
1528
 
168 tk 1529
 
1530
/////////////////////////////////////////////////////////////////////////////
178 tk 1531
// Returns 1 if 'track' is selected
1532
/////////////////////////////////////////////////////////////////////////////
1533
s32 SEQ_UI_IsSelectedTrack(u8 track)
1534
{
484 tk 1535
  return (ui_selected_tracks & (1 << track)) ? 1 : 0;
178 tk 1536
}
1537
 
1538
 
1539
/////////////////////////////////////////////////////////////////////////////
240 tk 1540
// Sets a new selected step and updates the step view
1541
/////////////////////////////////////////////////////////////////////////////
1542
s32 SEQ_UI_SelectedStepSet(u8 step)
1543
{
1544
  ui_selected_step = step;
328 tk 1545
  SEQ_UI_CheckSelections();
1546
 
240 tk 1547
  return 0; // no error
1548
}
1549
 
1550
 
1551
/////////////////////////////////////////////////////////////////////////////
168 tk 1552
// Increments the selected tracks/groups
1553
// OUT: 1 if value has been changed, otherwise 0
1554
/////////////////////////////////////////////////////////////////////////////
1555
s32 SEQ_UI_GxTyInc(s32 incrementer)
1556
{
1557
  int gxty = SEQ_UI_VisibleTrackGet();
1558
  int prev_gxty = gxty;
1559
 
1560
  if( incrementer >= 0 ) {
1561
    if( (gxty += incrementer) >= SEQ_CORE_NUM_TRACKS )
1562
      gxty = SEQ_CORE_NUM_TRACKS-1;
1563
  } else {
1564
    if( (gxty += incrementer) < 0 )
1565
      gxty = 0;
1566
  }
1567
 
1568
  if( gxty == prev_gxty )
1569
    return 0; // no change
1570
 
484 tk 1571
  ui_selected_tracks = 1 << gxty;
168 tk 1572
  ui_selected_group = gxty / 4;
1573
 
1574
  return 1; // value changed
1575
}
1576
 
1577
 
1578
/////////////////////////////////////////////////////////////////////////////
236 tk 1579
// Increments a 16bit variable within given min/max range
1580
// OUT: 1 if value has been changed, otherwise 0
1581
/////////////////////////////////////////////////////////////////////////////
240 tk 1582
s32 SEQ_UI_Var16_Inc(u16 *value, u16 min, u16 max, s32 incrementer)
236 tk 1583
{
1584
  int new_value = *value;
1585
  int prev_value = new_value;
1586
 
1587
  if( incrementer >= 0 ) {
1588
    if( (new_value += incrementer) >= max )
1589
      new_value = max;
1590
  } else {
1591
    if( (new_value += incrementer) < min )
1592
      new_value = min;
1593
  }
1594
 
1595
  if( new_value == prev_value )
1596
    return 0; // no change
1597
 
1598
  *value = new_value;
1599
 
1600
  return 1; // value changed
1601
}
1602
 
240 tk 1603
/////////////////////////////////////////////////////////////////////////////
1604
// Increments an 8bit variable within given min/max range
1605
// OUT: 1 if value has been changed, otherwise 0
1606
/////////////////////////////////////////////////////////////////////////////
1607
s32 SEQ_UI_Var8_Inc(u8 *value, u16 min, u16 max, s32 incrementer)
1608
{
1609
  u16 tmp = *value;
1610
  if( SEQ_UI_Var16_Inc(&tmp, min, max, incrementer) ) {
1611
    *value = tmp;
1612
    return 1; // value changed
1613
  }
236 tk 1614
 
240 tk 1615
  return 0; // value hasn't been changed
1616
}
1617
 
1618
 
236 tk 1619
/////////////////////////////////////////////////////////////////////////////
168 tk 1620
// Increments a CC within given min/max range
1621
// OUT: 1 if value has been changed, otherwise 0
1622
/////////////////////////////////////////////////////////////////////////////
248 tk 1623
s32 SEQ_UI_CC_Inc(u8 cc, u8 min, u8 max, s32 incrementer)
168 tk 1624
{
1625
  u8 visible_track = SEQ_UI_VisibleTrackGet();
173 tk 1626
  int new_value = SEQ_CC_Get(visible_track, cc);
1627
  int prev_value = new_value;
168 tk 1628
 
1629
  if( incrementer >= 0 ) {
173 tk 1630
    if( (new_value += incrementer) >= max )
1631
      new_value = max;
168 tk 1632
  } else {
173 tk 1633
    if( (new_value += incrementer) < min )
1634
      new_value = min;
168 tk 1635
  }
1636
 
173 tk 1637
  if( new_value == prev_value )
168 tk 1638
    return 0; // no change
1639
 
173 tk 1640
  SEQ_CC_Set(visible_track, cc, new_value);
168 tk 1641
 
179 tk 1642
  // set same value for all selected tracks
1643
  u8 track;
1644
  for(track=0; track<SEQ_CORE_NUM_TRACKS; ++track)
1645
    if( track != visible_track && SEQ_UI_IsSelectedTrack(track) )
1646
      SEQ_CC_Set(track, cc, new_value);
1647
 
168 tk 1648
  return 1; // value changed
1649
}
1650
 
173 tk 1651
 
1652
/////////////////////////////////////////////////////////////////////////////
179 tk 1653
// Sets a CC value on all selected tracks
1654
// OUT: 1 if value has been changed, otherwise 0
1655
/////////////////////////////////////////////////////////////////////////////
248 tk 1656
s32 SEQ_UI_CC_Set(u8 cc, u8 value)
179 tk 1657
{
1658
  u8 visible_track = SEQ_UI_VisibleTrackGet();
1659
  int prev_value = SEQ_CC_Get(visible_track, cc);
1660
 
1661
  if( value == prev_value )
1662
    return 0; // no change
1663
 
1664
  SEQ_CC_Set(visible_track, cc, value);
1665
 
1666
  // set same value for all selected tracks
1667
  u8 track;
1668
  for(track=0; track<SEQ_CORE_NUM_TRACKS; ++track)
1669
    if( track != visible_track && SEQ_UI_IsSelectedTrack(track) )
1670
      SEQ_CC_Set(track, cc, value);
1671
 
1672
  return 1; // value changed
1673
}
1674
 
1675
/////////////////////////////////////////////////////////////////////////////
173 tk 1676
// Modifies a bitfield in a CC value to a given value
1677
// OUT: 1 if value has been changed, otherwise 0
1678
/////////////////////////////////////////////////////////////////////////////
248 tk 1679
s32 SEQ_UI_CC_SetFlags(u8 cc, u8 flag_mask, u8 value)
173 tk 1680
{
1681
  u8 visible_track = SEQ_UI_VisibleTrackGet();
1682
  int new_value = SEQ_CC_Get(visible_track, cc);
1683
  int prev_value = new_value;
1684
 
1685
  new_value = (new_value & ~flag_mask) | value;
1686
 
1687
  if( new_value == prev_value )
1688
    return 0; // no change
1689
 
1690
  SEQ_CC_Set(visible_track, cc, new_value);
1691
 
179 tk 1692
  // do same modification for all selected tracks
1693
  u8 track;
1694
  for(track=0; track<SEQ_CORE_NUM_TRACKS; ++track)
1695
    if( track != visible_track && SEQ_UI_IsSelectedTrack(track) ) {
1696
      int new_value = SEQ_CC_Get(track, cc);
1697
      new_value = (new_value & ~flag_mask) | value;
1698
      SEQ_CC_Set(track, cc, new_value);
1699
    }
1700
 
173 tk 1701
  return 1; // value changed
1702
}
1703
 
1704
 
299 tk 1705
/////////////////////////////////////////////////////////////////////////////
1706
// Print temporary messages after file operations
1707
// expects mS delay and two lines, each up to 20 characters
1708
/////////////////////////////////////////////////////////////////////////////
1709
s32 SEQ_UI_SDCardMsg(u16 delay, char *line1, char *line2)
1710
{
1711
  sdcard_msg_ctr = delay;
1712
  strncpy((char *)sdcard_msg[0], line1, SDCARD_MSG_MAX_CHAR);
1713
  strncpy((char *)sdcard_msg[1], line2, SDCARD_MSG_MAX_CHAR);
1714
 
1715
  return 0; // no error
1716
}
1717
 
1718
/////////////////////////////////////////////////////////////////////////////
1719
// Prints a temporary error messages after file operation
1720
// Expects error status number (as defined in seq_file.h)
1721
/////////////////////////////////////////////////////////////////////////////
1722
s32 SEQ_UI_SDCardErrMsg(u16 delay, s32 status)
1723
{
1724
  // TODO: add more verbose error messages, they are clearly defined in seq_file.h)
1725
  char str[21];
1726
  sprintf(str, "E%3d (DOSFS: D%3d)", -status, seq_file_dfs_errno < 1000 ? seq_file_dfs_errno : 999);
1727
  return SEQ_UI_SDCardMsg(delay, "!! SD Card Error !!!", str);
1728
}