Subversion Repositories svn.mios32

Rev

Rev 303 | Rev 316 | 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 306 2009-01-15 23:33:04Z tk $
2
/*
3
 * User Interface Routines
4
 *
5
 * ==========================================================================
6
 *
7
 *  Copyright (C) 2008 Thorsten Klose (tk@midibox.org)
8
 *  Licensed for personal non-commercial use only.
9
 *  All other rights reserved.
10
 *
11
 * ==========================================================================
12
 */
13
 
14
/////////////////////////////////////////////////////////////////////////////
15
// Include files
16
/////////////////////////////////////////////////////////////////////////////
17
 
272 tk 18
// with this switch, seq_ui.h/seq_ui_pages.inc will create local variables
19
#define SEQ_UI_PAGES_INC_LOCAL_VARS 1
20
 
134 tk 21
#include <mios32.h>
299 tk 22
#include <string.h>
134 tk 23
#include <blm8x8.h>
190 tk 24
#include <seq_midi_out.h>
25
#include <seq_bpm.h>
134 tk 26
 
290 tk 27
#include "tasks.h"
134 tk 28
#include "seq_ui.h"
29
#include "seq_lcd.h"
30
#include "seq_led.h"
186 tk 31
#include "seq_midply.h"
134 tk 32
#include "seq_core.h"
178 tk 33
#include "seq_layer.h"
184 tk 34
#include "seq_cc.h"
299 tk 35
#include "seq_file.h"
248 tk 36
#include "seq_file_b.h"
280 tk 37
#include "seq_file_m.h"
134 tk 38
 
39
 
40
/////////////////////////////////////////////////////////////////////////////
41
// Local types
42
/////////////////////////////////////////////////////////////////////////////
43
 
44
 
45
/////////////////////////////////////////////////////////////////////////////
46
// Local prototypes
47
/////////////////////////////////////////////////////////////////////////////
48
 
49
 
50
/////////////////////////////////////////////////////////////////////////////
51
// Global variables
52
/////////////////////////////////////////////////////////////////////////////
53
 
159 tk 54
u8 seq_ui_display_update_req;
55
u8 seq_ui_display_init_req;
134 tk 56
 
167 tk 57
seq_ui_button_state_t seq_ui_button_state;
58
 
134 tk 59
u8 ui_selected_group;
60
u8 ui_selected_tracks;
61
u8 ui_selected_par_layer;
62
u8 ui_selected_trg_layer;
63
u8 ui_selected_step_view;
64
u8 ui_selected_step;
168 tk 65
u8 ui_selected_item;
134 tk 66
 
168 tk 67
u8 ui_selected_item;
134 tk 68
 
240 tk 69
u16 ui_hold_msg_ctr;
70
 
206 tk 71
seq_ui_page_t ui_page;
272 tk 72
seq_ui_page_t ui_selected_page;
303 tk 73
seq_ui_page_t ui_stepview_prev_page;
206 tk 74
 
173 tk 75
volatile u8 ui_cursor_flash;
76
u16 ui_cursor_flash_ctr;
134 tk 77
 
193 tk 78
u8 ui_seq_pause;
79
 
80
 
134 tk 81
/////////////////////////////////////////////////////////////////////////////
82
// Local variables
83
/////////////////////////////////////////////////////////////////////////////
84
 
168 tk 85
static s32 (*ui_button_callback)(seq_ui_button_t button, s32 depressed);
86
static s32 (*ui_encoder_callback)(seq_ui_encoder_t encoder, s32 incrementer);
173 tk 87
static s32 (*ui_led_callback)(u16 *gp_leds);
167 tk 88
static s32 (*ui_lcd_callback)(u8 high_prio);
89
 
168 tk 90
static u16 ui_gp_leds;
167 tk 91
 
168 tk 92
 
299 tk 93
#define SDCARD_MSG_MAX_CHAR 21
94
static char sdcard_msg[2][SDCARD_MSG_MAX_CHAR];
95
static u16 sdcard_msg_ctr;
96
 
97
 
98
 
134 tk 99
/////////////////////////////////////////////////////////////////////////////
100
// Initialisation
101
/////////////////////////////////////////////////////////////////////////////
102
s32 SEQ_UI_Init(u32 mode)
103
{
104
  // init selection variables
105
  ui_selected_group = 0;
106
  ui_selected_tracks = (1 << 0);
107
  ui_selected_par_layer = 0;
108
  ui_selected_trg_layer = 0;
109
  ui_selected_step_view = 0;
110
  ui_selected_step = 0;
168 tk 111
  ui_selected_item = 0;
134 tk 112
 
240 tk 113
  ui_hold_msg_ctr = 0;
299 tk 114
  sdcard_msg_ctr = 0;
240 tk 115
 
168 tk 116
  ui_cursor_flash_ctr = 0;
173 tk 117
  ui_cursor_flash = 0;
168 tk 118
 
167 tk 119
  seq_ui_button_state.ALL = 0;
120
 
193 tk 121
  ui_seq_pause = 0;
122
 
134 tk 123
  // visible GP pattern
124
  ui_gp_leds = 0x0000;
125
 
167 tk 126
  // change to edit page
127
  ui_page = SEQ_UI_PAGE_NONE;
128
  SEQ_UI_PageSet(SEQ_UI_PAGE_EDIT);
134 tk 129
 
130
  return 0; // no error
131
}
132
 
133
 
134
/////////////////////////////////////////////////////////////////////////////
178 tk 135
// Inits the speed mode of all encoders
136
// Auto mode should be used whenever:
137
//    - the edit screen is entered
138
//    - the group is changed
139
//    - a track is changed
140
//    - a layer is changed
141
/////////////////////////////////////////////////////////////////////////////
142
s32 SEQ_UI_InitEncSpeed(u32 auto_config)
143
{
144
  mios32_enc_config_t enc_config;
145
 
146
  if( auto_config ) {
147
#if DEFAULT_AUTO_FAST_BUTTON
148
    switch( SEQ_LAYER_GetVControlType(SEQ_UI_VisibleTrackGet(), ui_selected_par_layer) ) {
149
      case SEQ_LAYER_ControlType_Velocity:
150
      case SEQ_LAYER_ControlType_Chord1_Velocity:
151
      case SEQ_LAYER_ControlType_Chord2_Velocity:
152
      case SEQ_LAYER_ControlType_CC:
153
    seq_ui_button_state.FAST_ENCODERS = 1;
154
    break;
155
 
156
      default:
157
    seq_ui_button_state.FAST_ENCODERS = 0;
158
    }
159
#else
160
    // auto mode not enabled - ignore auto reconfiguration request
161
    return 0;
162
#endif
163
  }
164
 
165
  // change for datawheel and GP encoders
166
  int enc;
167
  for(enc=0; enc<17; ++enc) {
168
    enc_config = MIOS32_ENC_ConfigGet(enc);
169
    enc_config.cfg.speed = seq_ui_button_state.FAST_ENCODERS ? FAST : NORMAL;
170
    enc_config.cfg.speed_par = (enc == 0) ? DEFAULT_DATAWHEEL_SPEED_VALUE : DEFAULT_ENC_SPEED_VALUE;
171
    MIOS32_ENC_ConfigSet(enc, enc_config);
172
  }
173
 
174
  return 0; // no error
175
}
176
 
177
 
178
/////////////////////////////////////////////////////////////////////////////
167 tk 179
// Various installation routines for menu page LCD handlers
180
/////////////////////////////////////////////////////////////////////////////
168 tk 181
s32 SEQ_UI_InstallButtonCallback(void *callback)
167 tk 182
{
168 tk 183
  ui_button_callback = callback;
167 tk 184
  return 0; // no error
185
}
186
 
168 tk 187
s32 SEQ_UI_InstallEncoderCallback(void *callback)
167 tk 188
{
168 tk 189
  ui_encoder_callback = callback;
167 tk 190
  return 0; // no error
191
}
192
 
168 tk 193
s32 SEQ_UI_InstallLEDCallback(void *callback)
167 tk 194
{
168 tk 195
  ui_led_callback = callback;
167 tk 196
  return 0; // no error
197
}
198
 
168 tk 199
s32 SEQ_UI_InstallLCDCallback(void *callback)
167 tk 200
{
201
  ui_lcd_callback = callback;
202
  return 0; // no error
203
}
204
 
205
 
206
/////////////////////////////////////////////////////////////////////////////
207
// Change the menu page
208
/////////////////////////////////////////////////////////////////////////////
209
s32 SEQ_UI_PageSet(seq_ui_page_t page)
210
{
211
  if( page != ui_page ) {
212
    // disable hooks of previous page and request re-initialisation
213
    MIOS32_IRQ_Disable();
214
    ui_page = page;
168 tk 215
    ui_button_callback = NULL;
216
    ui_encoder_callback = NULL;
217
    ui_led_callback = NULL;
167 tk 218
    ui_lcd_callback = NULL;
219
    MIOS32_IRQ_Enable();
220
 
178 tk 221
#if DEFAULT_BEHAVIOUR_BUTTON_MENU
168 tk 222
    seq_ui_button_state.MENU_PRESSED = 0; // MENU page selection finished
167 tk 223
#endif
224
 
225
    // request display initialisation
226
    seq_ui_display_init_req = 1;
227
  }
173 tk 228
 
306 tk 229
  // for MENU button:
230
  // first page has been selected - display new screen
231
  seq_ui_button_state.MENU_FIRST_PAGE_SELECTED = 1;
232
 
272 tk 233
  // for SEQ_UI_MENU which is accessible with EXIT button
234
  // remember the current selectable page
235
  if( ui_page >= SEQ_UI_FIRST_MENU_SELECTION_PAGE )
236
    ui_selected_page = ui_page;
237
 
184 tk 238
  return 0; // no error
167 tk 239
}
240
 
241
 
242
/////////////////////////////////////////////////////////////////////////////
272 tk 243
// Returns name of menu page (18 characters)
244
/////////////////////////////////////////////////////////////////////////////
245
char *SEQ_UI_PageNameGet(seq_ui_page_t page)
246
{
247
  return ui_menu_pages[page].name;
248
}
249
 
250
 
251
/////////////////////////////////////////////////////////////////////////////
134 tk 252
// Dedicated button functions
253
// Mapped to physical buttons in SEQ_UI_Button_Handler()
254
// Will also be mapped to MIDI keys later (for MIDI remote function)
255
/////////////////////////////////////////////////////////////////////////////
256
static s32 SEQ_UI_Button_GP(s32 depressed, u32 gp)
257
{
306 tk 258
  // in MENU page: overrule GP buttons so long MENU button is pressed/active
259
  if( seq_ui_button_state.MENU_PRESSED ) {
260
    if( depressed ) return -1;
261
    SEQ_UI_PageSet(ui_shortcut_menu_pages[gp]);
262
  } else {
263
    // forward to menu page
264
    if( ui_button_callback != NULL )
265
      ui_button_callback(gp, depressed);
266
    ui_cursor_flash_ctr = 0;
267
  }
134 tk 268
 
269
  return 0; // no error
270
}
271
 
272
static s32 SEQ_UI_Button_Left(s32 depressed)
273
{
168 tk 274
  // forward to menu page
306 tk 275
  if( !seq_ui_button_state.MENU_PRESSED && ui_button_callback != NULL )
168 tk 276
    ui_button_callback(SEQ_UI_BUTTON_Left, depressed);
173 tk 277
  ui_cursor_flash_ctr = 0;
134 tk 278
 
279
  return 0; // no error
280
}
281
 
282
static s32 SEQ_UI_Button_Right(s32 depressed)
283
{
168 tk 284
  // forward to menu page
306 tk 285
  if( !seq_ui_button_state.MENU_PRESSED && ui_button_callback != NULL )
168 tk 286
    ui_button_callback(SEQ_UI_BUTTON_Right, depressed);
173 tk 287
  ui_cursor_flash_ctr = 0;
134 tk 288
 
289
  return 0; // no error
290
}
291
 
168 tk 292
static s32 SEQ_UI_Button_Down(s32 depressed)
293
{
240 tk 294
  seq_ui_button_state.DOWN = depressed ? 0 : 1;
295
 
168 tk 296
  // forward to menu page
306 tk 297
  if( !seq_ui_button_state.MENU_PRESSED && ui_button_callback != NULL )
168 tk 298
    ui_button_callback(SEQ_UI_BUTTON_Down, depressed);
173 tk 299
  ui_cursor_flash_ctr = 0;
168 tk 300
 
301
  return 0; // no error
302
}
303
 
304
static s32 SEQ_UI_Button_Up(s32 depressed)
305
{
240 tk 306
  seq_ui_button_state.UP = depressed ? 0 : 1;
307
 
168 tk 308
  // forward to menu page
306 tk 309
  if( !seq_ui_button_state.MENU_PRESSED && ui_button_callback != NULL )
168 tk 310
    ui_button_callback(SEQ_UI_BUTTON_Up, depressed);
173 tk 311
  ui_cursor_flash_ctr = 0;
168 tk 312
 
313
  return 0; // no error
314
}
315
 
134 tk 316
static s32 SEQ_UI_Button_Scrub(s32 depressed)
317
{
178 tk 318
#if DEFAULT_BEHAVIOUR_BUTTON_SCRUB
319
  // toggle mode
134 tk 320
  if( depressed ) return -1; // ignore when button depressed
178 tk 321
  seq_ui_button_state.SCRUB ^= 1;
137 tk 322
#else
178 tk 323
  // set mode
324
  seq_ui_button_state.SCRUB = depressed ? 0 : 1;
137 tk 325
#endif
326
 
134 tk 327
  return 0; // no error
328
}
329
 
330
static s32 SEQ_UI_Button_Metronome(s32 depressed)
331
{
178 tk 332
#if DEFAULT_BEHAVIOUR_BUTTON_METRON
333
  // toggle mode
134 tk 334
  if( depressed ) return -1; // ignore when button depressed
178 tk 335
  seq_ui_button_state.METRONOME ^= 1;
290 tk 336
 
248 tk 337
#if 1
290 tk 338
  MUTEX_SDCARD_TAKE;
280 tk 339
 
340
#if 0
249 tk 341
  u8 bank;
342
  for(bank=0; bank<SEQ_FILE_B_NUM_BANKS; ++bank) {
343
    SEQ_FILE_B_Create(bank);
344
    SEQ_FILE_B_Open(bank);
345
  }
280 tk 346
#else
347
    SEQ_FILE_M_Create();
348
    SEQ_FILE_M_Open();
349
#endif
350
 
290 tk 351
  MUTEX_SDCARD_GIVE;
248 tk 352
#endif
353
 
137 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
 
639
  return 0; // no error
640
}
641
 
642
static s32 SEQ_UI_Button_Solo(s32 depressed)
643
{
178 tk 644
#if DEFAULT_BEHAVIOUR_BUTTON_ALL
645
  // toggle mode
134 tk 646
  if( depressed ) return -1; // ignore when button depressed
178 tk 647
  seq_ui_button_state.SOLO ^= 1;
648
#else
649
  // set mode
650
  seq_ui_button_state.SOLO = depressed ? 0 : 1;
651
#endif
134 tk 652
 
653
  return 0; // no error
654
}
655
 
656
static s32 SEQ_UI_Button_Fast(s32 depressed)
657
{
178 tk 658
#if DEFAULT_BEHAVIOUR_BUTTON_FAST
659
  // toggle mode
134 tk 660
  if( depressed ) return -1; // ignore when button depressed
178 tk 661
  seq_ui_button_state.FAST_ENCODERS ^= 1;
662
#else
663
  // set mode
664
  seq_ui_button_state.FAST_ENCODERS = depressed ? 0 : 1;
665
#endif
134 tk 666
 
178 tk 667
  SEQ_UI_InitEncSpeed(0); // no auto config
668
 
134 tk 669
  return 0; // no error
670
}
671
 
672
static s32 SEQ_UI_Button_All(s32 depressed)
673
{
178 tk 674
  seq_ui_button_state.CHANGE_ALL_STEPS_SAME_VALUE = depressed ? 0 : 1;
134 tk 675
 
178 tk 676
#if DEFAULT_BEHAVIOUR_BUTTON_ALL
677
  // toggle mode
678
  if( depressed ) return -1;
679
  seq_ui_button_state.CHANGE_ALL_STEPS ^= 1;
680
#else
681
  // set mode
682
  seq_ui_button_state.CHANGE_ALL_STEPS = depressed ? 0 : 1;
683
#endif
684
 
134 tk 685
  return 0; // no error
686
}
687
 
688
static s32 SEQ_UI_Button_StepView(s32 depressed)
689
{
303 tk 690
#if DEFAULT_BEHAVIOUR_BUTTON_STEPVIEW
134 tk 691
  if( depressed ) return -1; // ignore when button depressed
303 tk 692
  seq_ui_button_state.STEPVIEW ^= 1; // toggle STEPVIEW pressed (will also be released once GP button has been pressed)
693
#else
694
  // set mode
695
  seq_ui_button_state.STEPVIEW = depressed ? 0 : 1;
696
#endif
134 tk 697
 
303 tk 698
  if( seq_ui_button_state.STEPVIEW ) {
699
    ui_stepview_prev_page = ui_page;
700
    SEQ_UI_PageSet(SEQ_UI_PAGE_STEPSEL);
701
  } else {
702
    SEQ_UI_PageSet(ui_stepview_prev_page);
703
  }
134 tk 704
 
705
  return 0; // no error
706
}
707
 
708
static s32 SEQ_UI_Button_TapTempo(s32 depressed)
709
{
710
  if( depressed ) return -1; // ignore when button depressed
711
 
712
  return 0; // no error
713
}
714
 
715
static s32 SEQ_UI_Button_Track(s32 depressed, u32 track)
716
{
717
  if( depressed ) return -1; // ignore when button depressed
718
 
719
  if( track >= 4 ) return -2; // max. 4 track buttons
720
 
721
  ui_selected_tracks = (1 << track); // TODO: multi-selections!
722
 
178 tk 723
  // set/clear encoder fast function if required
724
  SEQ_UI_InitEncSpeed(1); // auto config
725
 
134 tk 726
  return 0; // no error
727
}
728
 
729
static s32 SEQ_UI_Button_Group(s32 depressed, u32 group)
730
{
731
  if( depressed ) return -1; // ignore when button depressed
732
 
733
  if( group >= 4 ) return -2; // max. 4 group buttons
734
 
735
  ui_selected_group = group;
736
 
178 tk 737
  // set/clear encoder fast function if required
738
  SEQ_UI_InitEncSpeed(1); // auto config
739
 
134 tk 740
  return 0; // no error
741
}
742
 
743
static s32 SEQ_UI_Button_ParLayer(s32 depressed, u32 par_layer)
744
{
745
  if( depressed ) return -1; // ignore when button depressed
746
 
747
  if( par_layer >= 3 ) return -2; // max. 3 parlayer buttons
748
 
749
  ui_selected_par_layer = par_layer;
750
 
178 tk 751
  // set/clear encoder fast function if required
752
  SEQ_UI_InitEncSpeed(1); // auto config
753
 
134 tk 754
  return 0; // no error
755
}
756
 
757
static s32 SEQ_UI_Button_TrgLayer(s32 depressed, u32 trg_layer)
758
{
759
  if( depressed ) return -1; // ignore when button depressed
760
 
761
  if( trg_layer >= 3 ) return -2; // max. 3 trglayer buttons
762
 
763
  ui_selected_trg_layer = trg_layer;
764
 
765
  return 0; // no error
766
}
767
 
768
 
769
 
770
/////////////////////////////////////////////////////////////////////////////
771
// Button handler
772
/////////////////////////////////////////////////////////////////////////////
773
s32 SEQ_UI_Button_Handler(u32 pin, u32 pin_value)
774
{
775
  switch( pin ) {
168 tk 776
#if BUTTON_GP1 != BUTTON_DISABLED
134 tk 777
    case BUTTON_GP1:   SEQ_UI_Button_GP(pin_value, 0); break;
778
#endif
168 tk 779
#if BUTTON_GP2 != BUTTON_DISABLED
134 tk 780
    case BUTTON_GP2:   SEQ_UI_Button_GP(pin_value, 1); break;
781
#endif
168 tk 782
#if BUTTON_GP3 != BUTTON_DISABLED
134 tk 783
    case BUTTON_GP3:   SEQ_UI_Button_GP(pin_value, 2); break;
784
#endif
168 tk 785
#if BUTTON_GP4 != BUTTON_DISABLED
134 tk 786
    case BUTTON_GP4:   SEQ_UI_Button_GP(pin_value, 3); break;
787
#endif
168 tk 788
#if BUTTON_GP5 != BUTTON_DISABLED
134 tk 789
    case BUTTON_GP5:   SEQ_UI_Button_GP(pin_value, 4); break;
790
#endif
168 tk 791
#if BUTTON_GP6 != BUTTON_DISABLED
134 tk 792
    case BUTTON_GP6:   SEQ_UI_Button_GP(pin_value, 5); break;
793
#endif
168 tk 794
#if BUTTON_GP7 != BUTTON_DISABLED
134 tk 795
    case BUTTON_GP7:   SEQ_UI_Button_GP(pin_value, 6); break;
796
#endif
168 tk 797
#if BUTTON_GP8 != BUTTON_DISABLED
134 tk 798
    case BUTTON_GP8:   SEQ_UI_Button_GP(pin_value, 7); break;
799
#endif
168 tk 800
#if BUTTON_GP9 != BUTTON_DISABLED
134 tk 801
    case BUTTON_GP9:   SEQ_UI_Button_GP(pin_value, 8); break;
802
#endif
168 tk 803
#if BUTTON_GP10 != BUTTON_DISABLED
134 tk 804
    case BUTTON_GP10:  SEQ_UI_Button_GP(pin_value, 9); break;
805
#endif
168 tk 806
#if BUTTON_GP11 != BUTTON_DISABLED
134 tk 807
    case BUTTON_GP11:  SEQ_UI_Button_GP(pin_value, 10); break;
808
#endif
168 tk 809
#if BUTTON_GP12 != BUTTON_DISABLED
134 tk 810
    case BUTTON_GP12:  SEQ_UI_Button_GP(pin_value, 11); break;
811
#endif
168 tk 812
#if BUTTON_GP13 != BUTTON_DISABLED
134 tk 813
    case BUTTON_GP13:  SEQ_UI_Button_GP(pin_value, 12); break;
814
#endif
168 tk 815
#if BUTTON_GP14 != BUTTON_DISABLED
134 tk 816
    case BUTTON_GP14:  SEQ_UI_Button_GP(pin_value, 13); break;
817
#endif
168 tk 818
#if BUTTON_GP15 != BUTTON_DISABLED
134 tk 819
    case BUTTON_GP15:  SEQ_UI_Button_GP(pin_value, 14); break;
820
#endif
168 tk 821
#if BUTTON_GP16 != BUTTON_DISABLED
134 tk 822
    case BUTTON_GP16:  SEQ_UI_Button_GP(pin_value, 15); break;
823
#endif
824
 
168 tk 825
#if BUTTON_LEFT != BUTTON_DISABLED
134 tk 826
    case BUTTON_LEFT:  SEQ_UI_Button_Left(pin_value); break;
827
#endif
168 tk 828
#if BUTTON_RIGHT != BUTTON_DISABLED
134 tk 829
    case BUTTON_RIGHT: SEQ_UI_Button_Right(pin_value); break;
830
#endif
831
 
168 tk 832
#if BUTTON_DOWN != BUTTON_DISABLED
833
    case BUTTON_DOWN:  SEQ_UI_Button_Down(pin_value); break;
834
#endif
835
#if BUTTON_UP != BUTTON_DISABLED
836
    case BUTTON_UP:    SEQ_UI_Button_Up(pin_value); break;
837
#endif
838
 
839
#if BUTTON_SCRUB != BUTTON_DISABLED
134 tk 840
    case BUTTON_SCRUB: SEQ_UI_Button_Scrub(pin_value); break;
841
#endif
168 tk 842
#if BUTTON_METRONOME != BUTTON_DISABLED
134 tk 843
    case BUTTON_METRONOME: SEQ_UI_Button_Metronome(pin_value); break;
844
#endif
845
 
168 tk 846
#if BUTTON_STOP != BUTTON_DISABLED
134 tk 847
    case BUTTON_STOP:  SEQ_UI_Button_Stop(pin_value); break;
848
#endif
168 tk 849
#if BUTTON_PAUSE != BUTTON_DISABLED
134 tk 850
    case BUTTON_PAUSE: SEQ_UI_Button_Pause(pin_value); break;
851
#endif
168 tk 852
#if BUTTON_PLAY != BUTTON_DISABLED
134 tk 853
    case BUTTON_PLAY:  SEQ_UI_Button_Play(pin_value); break;
854
#endif
168 tk 855
#if BUTTON_REW != BUTTON_DISABLED
134 tk 856
    case BUTTON_REW:   SEQ_UI_Button_Rew(pin_value); break;
857
#endif
168 tk 858
#if BUTTON_FWD != BUTTON_DISABLED
134 tk 859
    case BUTTON_FWD:   SEQ_UI_Button_Fwd(pin_value); break;
860
#endif
861
 
168 tk 862
#if BUTTON_F1 != BUTTON_DISABLED
134 tk 863
    case BUTTON_F1:    SEQ_UI_Button_F1(pin_value); break;
864
#endif
168 tk 865
#if BUTTON_F2 != BUTTON_DISABLED
134 tk 866
    case BUTTON_F2:    SEQ_UI_Button_F2(pin_value); break;
867
#endif
168 tk 868
#if BUTTON_F3 != BUTTON_DISABLED
134 tk 869
    case BUTTON_F3:    SEQ_UI_Button_F3(pin_value); break;
870
#endif
168 tk 871
#if BUTTON_F4 != BUTTON_DISABLED
134 tk 872
    case BUTTON_F4:    SEQ_UI_Button_F4(pin_value); break;
873
#endif
874
 
168 tk 875
#if BUTTON_UTILITY != BUTTON_DISABLED
134 tk 876
    case BUTTON_UTILITY: SEQ_UI_Button_Utility(pin_value); break;
877
#endif
168 tk 878
#if BUTTON_COPY != BUTTON_DISABLED
134 tk 879
    case BUTTON_COPY:  SEQ_UI_Button_Copy(pin_value); break;
880
#endif
168 tk 881
#if BUTTON_PASTE != BUTTON_DISABLED
134 tk 882
    case BUTTON_PASTE: SEQ_UI_Button_Paste(pin_value); break;
883
#endif
168 tk 884
#if BUTTON_CLEAR != BUTTON_DISABLED
134 tk 885
    case BUTTON_CLEAR: SEQ_UI_Button_Clear(pin_value); break;
886
#endif
887
 
168 tk 888
#if BUTTON_MENU != BUTTON_DISABLED
134 tk 889
    case BUTTON_MENU:  SEQ_UI_Button_Menu(pin_value); break;
890
#endif
168 tk 891
#if BUTTON_SELECT != BUTTON_DISABLED
134 tk 892
    case BUTTON_SELECT:SEQ_UI_Button_Select(pin_value); break;
893
#endif
168 tk 894
#if BUTTON_EXIT != BUTTON_DISABLED
134 tk 895
    case BUTTON_EXIT:  SEQ_UI_Button_Exit(pin_value); break;
896
#endif
897
 
168 tk 898
#if BUTTON_TRACK1 != BUTTON_DISABLED
134 tk 899
    case BUTTON_TRACK1: SEQ_UI_Button_Track(pin_value, 0); break;
900
#endif
168 tk 901
#if BUTTON_TRACK2 != BUTTON_DISABLED
134 tk 902
    case BUTTON_TRACK2: SEQ_UI_Button_Track(pin_value, 1); break;
903
#endif
168 tk 904
#if BUTTON_TRACK3 != BUTTON_DISABLED
134 tk 905
    case BUTTON_TRACK3: SEQ_UI_Button_Track(pin_value, 2); break;
906
#endif
168 tk 907
#if BUTTON_TRACK4 != BUTTON_DISABLED
134 tk 908
    case BUTTON_TRACK4: SEQ_UI_Button_Track(pin_value, 3); break;
909
#endif
910
 
168 tk 911
#if BUTTON_PAR_LAYER_A != BUTTON_DISABLED
134 tk 912
    case BUTTON_PAR_LAYER_A: SEQ_UI_Button_ParLayer(pin_value, 0); break;
913
#endif
168 tk 914
#if BUTTON_PAR_LAYER_B != BUTTON_DISABLED
134 tk 915
    case BUTTON_PAR_LAYER_B: SEQ_UI_Button_ParLayer(pin_value, 1); break;
916
#endif
168 tk 917
#if BUTTON_PAR_LAYER_C != BUTTON_DISABLED
134 tk 918
    case BUTTON_PAR_LAYER_C: SEQ_UI_Button_ParLayer(pin_value, 2); break;
919
#endif
920
 
168 tk 921
#if BUTTON_EDIT != BUTTON_DISABLED
134 tk 922
    case BUTTON_EDIT:   SEQ_UI_Button_Edit(pin_value); break;
923
#endif
168 tk 924
#if BUTTON_MUTE != BUTTON_DISABLED
134 tk 925
    case BUTTON_MUTE:   SEQ_UI_Button_Mute(pin_value); break;
926
#endif
168 tk 927
#if BUTTON_PATTERN != BUTTON_DISABLED
134 tk 928
    case BUTTON_PATTERN:SEQ_UI_Button_Pattern(pin_value); break;
929
#endif
168 tk 930
#if BUTTON_SONG != BUTTON_DISABLED
134 tk 931
    case BUTTON_SONG:   SEQ_UI_Button_Song(pin_value); break;
932
#endif
933
 
168 tk 934
#if BUTTON_SOLO != BUTTON_DISABLED
134 tk 935
    case BUTTON_SOLO:   SEQ_UI_Button_Solo(pin_value); break;
936
#endif
168 tk 937
#if BUTTON_FAST != BUTTON_DISABLED
134 tk 938
    case BUTTON_FAST:   SEQ_UI_Button_Fast(pin_value); break;
939
#endif
168 tk 940
#if BUTTON_ALL != BUTTON_DISABLED
134 tk 941
    case BUTTON_ALL:    SEQ_UI_Button_All(pin_value); break;
942
#endif
943
 
168 tk 944
#if BUTTON_GROUP1 != BUTTON_DISABLED
134 tk 945
    case BUTTON_GROUP1: SEQ_UI_Button_Group(pin_value, 0); break;
946
#endif
168 tk 947
#if BUTTON_GROUP2 != BUTTON_DISABLED
134 tk 948
    case BUTTON_GROUP2: SEQ_UI_Button_Group(pin_value, 1); break;
949
#endif
168 tk 950
#if BUTTON_GROUP3 != BUTTON_DISABLED
134 tk 951
    case BUTTON_GROUP3: SEQ_UI_Button_Group(pin_value, 2); break;
952
#endif
168 tk 953
#if BUTTON_GROUP4 != BUTTON_DISABLED
134 tk 954
    case BUTTON_GROUP4: SEQ_UI_Button_Group(pin_value, 3); break;
955
#endif
956
 
168 tk 957
#if BUTTON_TRG_LAYER_A != BUTTON_DISABLED
134 tk 958
    case BUTTON_TRG_LAYER_A: SEQ_UI_Button_TrgLayer(pin_value, 0); break;
959
#endif
168 tk 960
#if BUTTON_TRG_LAYER_B != BUTTON_DISABLED
134 tk 961
    case BUTTON_TRG_LAYER_B: SEQ_UI_Button_TrgLayer(pin_value, 1); break;
962
#endif
168 tk 963
#if BUTTON_TRG_LAYER_C != BUTTON_DISABLED
134 tk 964
    case BUTTON_TRG_LAYER_C: SEQ_UI_Button_TrgLayer(pin_value, 2); break;
965
#endif
966
 
168 tk 967
#if BUTTON_STEP_VIEW != BUTTON_DISABLED
134 tk 968
    case BUTTON_STEP_VIEW: SEQ_UI_Button_StepView(pin_value); break;
969
#endif
970
 
168 tk 971
#if BUTTON_TAP_TEMPO != BUTTON_DISABLED
134 tk 972
    case BUTTON_TAP_TEMPO:   SEQ_UI_Button_TapTempo(pin_value); break;
973
#endif
974
 
975
    default:
976
      return -1; // button function not mapped to physical button
977
  }
978
 
979
  // request display update
159 tk 980
  seq_ui_display_update_req = 1;
134 tk 981
 
982
  return 0; // no error
983
}
984
 
985
 
986
/////////////////////////////////////////////////////////////////////////////
987
// Encoder handler
988
/////////////////////////////////////////////////////////////////////////////
989
s32 SEQ_UI_Encoder_Handler(u32 encoder, s32 incrementer)
990
{
991
  if( encoder > 16 )
992
    return -1; // encoder doesn't exist
993
 
994
  // limit incrementer
995
  if( incrementer > 3 )
996
    incrementer = 3;
997
  else if( incrementer < -3 )
998
    incrementer = -3;
999
 
306 tk 1000
  if( !seq_ui_button_state.MENU_PRESSED && ui_encoder_callback != NULL ) {
173 tk 1001
    ui_encoder_callback((encoder == 0) ? SEQ_UI_ENCODER_Datawheel : (encoder-1), incrementer);
1002
    ui_cursor_flash_ctr = 0; // ensure that value is visible when it has been changed
134 tk 1003
  }
1004
 
1005
  // request display update
159 tk 1006
  seq_ui_display_update_req = 1;
134 tk 1007
 
1008
  return 0; // no error
1009
}
1010
 
1011
 
1012
/////////////////////////////////////////////////////////////////////////////
1013
// Update LCD messages
1014
// Usually called from background task
1015
/////////////////////////////////////////////////////////////////////////////
1016
s32 SEQ_UI_LCD_Handler(void)
1017
{
159 tk 1018
  if( seq_ui_display_init_req ) {
1019
    seq_ui_display_init_req = 0; // clear request
134 tk 1020
 
278 tk 1021
    // clear force update of LCD
1022
    SEQ_LCD_Clear();
1023
    SEQ_LCD_Update(1);
134 tk 1024
 
168 tk 1025
    // select first menu item
1026
    ui_selected_item = 0;
1027
 
167 tk 1028
    // call init function of current page
272 tk 1029
    if( ui_menu_pages[ui_page].init_callback != NULL )
1030
      ui_menu_pages[ui_page].init_callback(0); // mode
134 tk 1031
 
1032
    // request display update
159 tk 1033
    seq_ui_display_update_req = 1;
134 tk 1034
  }
1035
 
306 tk 1036
  // in MENU page: overrule LCD output so long MENU button is pressed/active
1037
  if( seq_ui_button_state.MENU_PRESSED && !seq_ui_button_state.MENU_FIRST_PAGE_SELECTED ) {
1038
    SEQ_LCD_CursorSet(0, 0);
1039
    //                      <-------------------------------------->
1040
    //                      0123456789012345678901234567890123456789
1041
    SEQ_LCD_PrintString("Menu Shortcuts:");
1042
    SEQ_LCD_PrintSpaces(25 + 40);
1043
    SEQ_LCD_CursorSet(0, 1);
1044
    SEQ_LCD_PrintString(UI_SHORTCUT_STR); // defined in seq_ui_pages.inc
1045
  } else {
1046
    // perform high priority LCD update request
1047
    if( ui_lcd_callback != NULL )
1048
      ui_lcd_callback(1); // high_prio
167 tk 1049
 
306 tk 1050
    // perform low priority LCD update request if requested
1051
    if( seq_ui_display_update_req ) {
1052
      seq_ui_display_update_req = 0; // clear request
1053
 
1054
      if( ui_lcd_callback != NULL )
1055
    ui_lcd_callback(0); // no high_prio
1056
    }
134 tk 1057
  }
1058
 
299 tk 1059
  // if SD card message active: copy over the text
1060
  if( sdcard_msg_ctr ) {
1061
    const char animation_l[4][3] = {
1062
      "  ", " >", ">>", "> " };
1063
    const char animation_r[4][3] = {
1064
      "  ", "< ", "<<", " <" };
1065
    int anum = (sdcard_msg_ctr % 1000) / 250;
1066
 
1067
    int line;
1068
    for(line=0; line<2; ++line) {
1069
      SEQ_LCD_CursorSet(40, line);
1070
      SEQ_LCD_PrintFormattedString(" %s| %-20s |%s ",
1071
                   (char *)animation_l[anum],
1072
                   (char *)sdcard_msg[line],
1073
                   (char *)animation_r[anum]);
1074
    }
1075
  }
1076
 
278 tk 1077
  // transfer all changed characters to LCD
1078
  SEQ_LCD_Update(0);
159 tk 1079
 
134 tk 1080
  return 0; // no error
1081
}
1082
 
1083
 
1084
 
1085
/////////////////////////////////////////////////////////////////////////////
1086
// Update all LEDs
1087
// Usually called from background task
1088
/////////////////////////////////////////////////////////////////////////////
1089
s32 SEQ_UI_LED_Handler(void)
1090
{
1091
  // track LEDs
167 tk 1092
  SEQ_LED_PinSet(LED_TRACK1, (ui_selected_tracks & (1 << 0)));
1093
  SEQ_LED_PinSet(LED_TRACK2, (ui_selected_tracks & (1 << 1)));
1094
  SEQ_LED_PinSet(LED_TRACK3, (ui_selected_tracks & (1 << 2)));
1095
  SEQ_LED_PinSet(LED_TRACK4, (ui_selected_tracks & (1 << 3)));
134 tk 1096
 
1097
  // parameter layer LEDs
167 tk 1098
  SEQ_LED_PinSet(LED_PAR_LAYER_A, (ui_selected_par_layer == 0));
1099
  SEQ_LED_PinSet(LED_PAR_LAYER_B, (ui_selected_par_layer == 1));
1100
  SEQ_LED_PinSet(LED_PAR_LAYER_C, (ui_selected_par_layer == 2));
134 tk 1101
 
1102
  // group LEDs
167 tk 1103
  SEQ_LED_PinSet(LED_GROUP1, (ui_selected_group == 0));
1104
  SEQ_LED_PinSet(LED_GROUP2, (ui_selected_group == 1));
1105
  SEQ_LED_PinSet(LED_GROUP3, (ui_selected_group == 2));
1106
  SEQ_LED_PinSet(LED_GROUP4, (ui_selected_group == 3));
134 tk 1107
 
1108
  // trigger layer LEDs
167 tk 1109
  SEQ_LED_PinSet(LED_TRG_LAYER_A, (ui_selected_trg_layer == 0));
1110
  SEQ_LED_PinSet(LED_TRG_LAYER_B, (ui_selected_trg_layer == 1));
1111
  SEQ_LED_PinSet(LED_TRG_LAYER_C, (ui_selected_trg_layer == 2));
134 tk 1112
 
1113
  // remaining LEDs
167 tk 1114
  SEQ_LED_PinSet(LED_EDIT, ui_page == SEQ_UI_PAGE_EDIT);
184 tk 1115
  SEQ_LED_PinSet(LED_MUTE, ui_page == SEQ_UI_PAGE_MUTE);
1116
  SEQ_LED_PinSet(LED_PATTERN, ui_page == SEQ_UI_PAGE_PATTERN);
134 tk 1117
  SEQ_LED_PinSet(LED_SONG, 0);
1118
 
178 tk 1119
  SEQ_LED_PinSet(LED_SOLO, seq_ui_button_state.SOLO);
1120
  SEQ_LED_PinSet(LED_FAST, seq_ui_button_state.FAST_ENCODERS);
1121
  SEQ_LED_PinSet(LED_ALL, seq_ui_button_state.CHANGE_ALL_STEPS);
134 tk 1122
 
193 tk 1123
  SEQ_LED_PinSet(LED_PLAY, SEQ_BPM_IsRunning());
1124
  SEQ_LED_PinSet(LED_STOP, !SEQ_BPM_IsRunning() && !ui_seq_pause);
1125
  SEQ_LED_PinSet(LED_PAUSE, ui_seq_pause);
240 tk 1126
 
1127
  SEQ_LED_PinSet(LED_REW, seq_ui_button_state.REW);
1128
  SEQ_LED_PinSet(LED_FWD, seq_ui_button_state.FWD);
134 tk 1129
 
303 tk 1130
  SEQ_LED_PinSet(LED_STEPVIEW, seq_ui_button_state.STEPVIEW);
134 tk 1131
 
167 tk 1132
  SEQ_LED_PinSet(LED_MENU, seq_ui_button_state.MENU_PRESSED);
178 tk 1133
  SEQ_LED_PinSet(LED_SCRUB, seq_ui_button_state.SCRUB);
1134
  SEQ_LED_PinSet(LED_METRONOME, seq_ui_button_state.METRONOME);
134 tk 1135
 
240 tk 1136
  SEQ_LED_PinSet(LED_UTILITY, ui_page == SEQ_UI_PAGE_UTIL);
1137
  SEQ_LED_PinSet(LED_COPY, seq_ui_button_state.COPY);
1138
  SEQ_LED_PinSet(LED_PASTE, seq_ui_button_state.PASTE);
1139
  SEQ_LED_PinSet(LED_CLEAR, seq_ui_button_state.CLEAR);
1140
 
1141
  SEQ_LED_PinSet(LED_F1, seq_ui_button_state.F1);
1142
  SEQ_LED_PinSet(LED_F2, seq_ui_button_state.F2);
1143
  SEQ_LED_PinSet(LED_F3, seq_ui_button_state.F3);
1144
  SEQ_LED_PinSet(LED_F4, seq_ui_button_state.F4);
1145
 
1146
  SEQ_LED_PinSet(LED_DOWN, seq_ui_button_state.DOWN);
1147
  SEQ_LED_PinSet(LED_UP, seq_ui_button_state.UP);
1148
 
167 tk 1149
 
306 tk 1150
  // in MENU page: overrule GP LEDs so long MENU button is pressed/active
1151
  if( seq_ui_button_state.MENU_PRESSED ) {
1152
    if( ui_cursor_flash ) // if flashing flag active: no LED flag set
1153
      ui_gp_leds = 0x0000;
1154
    else {
1155
      int i;
1156
      u16 new_ui_gp_leds = 0x0000;
1157
      for(i=0; i<16; ++i)
1158
    if( ui_page == ui_shortcut_menu_pages[i] )
1159
      new_ui_gp_leds |= (1 << i);
1160
      ui_gp_leds = new_ui_gp_leds;
1161
    }
1162
  } else {
1163
    // note: the background function is permanently interrupted - therefore we write the GP pattern
1164
    // into a temporary variable, and take it over once completed
1165
    u16 new_ui_gp_leds = 0x0000;
1166
    // request GP LED values from current menu page
1167
    // will be transfered to DOUT registers in SEQ_UI_LED_Handler_Periodic
1168
    new_ui_gp_leds = 0x0000;
206 tk 1169
 
306 tk 1170
    if( ui_led_callback != NULL )
1171
      ui_led_callback(&new_ui_gp_leds);
167 tk 1172
 
306 tk 1173
    ui_gp_leds = new_ui_gp_leds;
1174
  }
1175
 
134 tk 1176
  return 0; // no error
1177
}
1178
 
1179
 
1180
/////////////////////////////////////////////////////////////////////////////
1181
// updates high-prio LED functions (GP LEDs and Beat LED)
168 tk 1182
// called each mS
134 tk 1183
/////////////////////////////////////////////////////////////////////////////
1184
s32 SEQ_UI_LED_Handler_Periodic()
1185
{
1186
  // GP LEDs are only updated when ui_gp_leds or pos_marker_mask has changed
1187
  static u16 prev_ui_gp_leds = 0x0000;
1188
  static u16 prev_pos_marker_mask = 0x0000;
1189
 
1190
  // beat LED: tmp. for demo w/o real sequencer
193 tk 1191
  u8 sequencer_running = SEQ_BPM_IsRunning();
1192
  SEQ_LED_PinSet(LED_BEAT, (sequencer_running && (seq_core_state.ref_step & 3) == 0));
134 tk 1193
 
1194
  // for song position marker (supports 16 LEDs, check for selected step view)
1195
  u16 pos_marker_mask = 0x0000;
166 tk 1196
  u8 played_step = seq_core_trk[SEQ_UI_VisibleTrackGet()].step;
193 tk 1197
  if( sequencer_running && (played_step >> 4) == ui_selected_step_view )
134 tk 1198
    pos_marker_mask = 1 << (played_step & 0xf);
1199
 
1200
  // exit of pattern hasn't changed
173 tk 1201
  if( prev_ui_gp_leds == ui_gp_leds && prev_pos_marker_mask == pos_marker_mask )
134 tk 1202
    return 0;
173 tk 1203
  prev_ui_gp_leds = ui_gp_leds;
134 tk 1204
  prev_pos_marker_mask = pos_marker_mask;
1205
 
1206
  // transfer to GP LEDs
1207
 
1208
#ifdef DEFAULT_GP_DOUT_SR_L
1209
# ifdef DEFAULT_GP_DOUT_SR_L2
173 tk 1210
  SEQ_LED_SRSet(DEFAULT_GP_DOUT_SR_L-1, (ui_gp_leds >> 0) & 0xff);
134 tk 1211
# else
173 tk 1212
  SEQ_LED_SRSet(DEFAULT_GP_DOUT_SR_L-1, ((ui_gp_leds ^ pos_marker_mask) >> 0) & 0xff);
134 tk 1213
# endif
1214
#endif
1215
#ifdef DEFAULT_GP_DOUT_SR_R
1216
# ifdef DEFAULT_GP_DOUT_SR_R2
173 tk 1217
  SEQ_LED_SRSet(DEFAULT_GP_DOUT_SR_R-1, (ui_gp_leds >> 8) & 0xff);
134 tk 1218
#else
173 tk 1219
  SEQ_LED_SRSet(DEFAULT_GP_DOUT_SR_R-1, ((ui_gp_leds ^ pos_marker_mask) >> 8) & 0xff);
134 tk 1220
#endif
1221
#endif
1222
 
1223
#ifdef DEFAULT_GP_DOUT_SR_L2
1224
  SEQ_LED_SRSet(DEFAULT_GP_DOUT_SR_L2-1, (pos_marker_mask >> 0) & 0xff);
1225
#endif
1226
#ifdef DEFAULT_GP_DOUT_SR_R2
1227
  SEQ_LED_SRSet(DEFAULT_GP_DOUT_SR_R2-1, (pos_marker_mask >> 8) & 0xff);
1228
#endif
1229
 
1230
#if DEFAULT_SRM_ENABLED && DEFAULT_SRM_DOUT_M_MAPPING == 1
1231
  // for wilba's frontpanel
1232
 
1233
  // BLM8X8 DOUT -> GP LED mapping
1234
  // 0 = 15,16  1 = 13,14   2 = 11,12   3 = 9,10
1235
  // 4 = 1,2    5 = 3,4     6 = 5,6     7 = 7,8
1236
 
1237
  // bit 7: first green (i.e. GP1-G)
1238
  // bit 6: first red (i.e. GP1-R)
1239
  // bit 5: second green (i.e. GP2-G)
1240
  // bit 4: second red (i.e. GP2-R)
1241
 
1242
  // this mapping routine takes ca. 5 uS
173 tk 1243
  // since it's only executed when ui_gp_leds or gp_mask has changed, it doesn't really hurt
134 tk 1244
 
173 tk 1245
  u16 modified_gp_leds = ui_gp_leds;
134 tk 1246
#if 1
1247
  // extra: red LED is lit exclusively for higher contrast
1248
  modified_gp_leds &= ~pos_marker_mask;
1249
#endif
1250
 
1251
  int sr;
1252
  const u8 blm8x8_sr_map[8] = {4, 5, 6, 7, 3, 2, 1, 0};
1253
  u16 gp_mask = 1 << 0;
1254
  for(sr=0; sr<8; ++sr) {
1255
    u8 pattern = 0;
1256
 
1257
    if( modified_gp_leds & gp_mask )
1258
      pattern |= 0x80;
1259
    if( pos_marker_mask & gp_mask )
1260
      pattern |= 0x40;
1261
    gp_mask <<= 1;
1262
    if( modified_gp_leds & gp_mask )
1263
      pattern |= 0x20;
1264
    if( pos_marker_mask & gp_mask )
1265
      pattern |= 0x10;
1266
    gp_mask <<= 1;
1267
 
1268
    u8 mapped_sr = blm8x8_sr_map[sr];
1269
    blm8x8_led_row[mapped_sr] = (blm8x8_led_row[mapped_sr] & 0x0f) | pattern;
1270
  }
1271
#endif
1272
 
184 tk 1273
  return 0; // no error
134 tk 1274
}
1275
 
1276
 
1277
/////////////////////////////////////////////////////////////////////////////
168 tk 1278
// for menu handling (e.g. flashing cursor, doubleclick counter, etc...)
1279
// called each mS
1280
/////////////////////////////////////////////////////////////////////////////
1281
s32 SEQ_UI_MENU_Handler_Periodic()
1282
{
1283
  if( ++ui_cursor_flash_ctr >= SEQ_UI_CURSOR_FLASH_CTR_MAX ) {
1284
    ui_cursor_flash_ctr = 0;
1285
    seq_ui_display_update_req = 1;
173 tk 1286
  } else if( ui_cursor_flash_ctr == SEQ_UI_CURSOR_FLASH_CTR_LED_OFF ) {
168 tk 1287
    seq_ui_display_update_req = 1;
173 tk 1288
  }
1289
  // important: flash flag has to be recalculated on each invocation of this
1290
  // handler, since counter could also be reseted outside this function
1291
  ui_cursor_flash = ui_cursor_flash_ctr >= SEQ_UI_CURSOR_FLASH_CTR_LED_OFF;
168 tk 1292
 
184 tk 1293
 
240 tk 1294
  // used in some pages for temporary messages
1295
  if( ui_hold_msg_ctr )
1296
    --ui_hold_msg_ctr;
1297
 
299 tk 1298
  // used for temporary SD Card messages
1299
  if( sdcard_msg_ctr )
1300
    --sdcard_msg_ctr;
1301
 
184 tk 1302
  // VU meters (used in MUTE menu, could also be available as LED matrix...)
1303
  static u8 vu_meter_prediv = 0; // predivider for VU meters
1304
 
1305
  if( ++vu_meter_prediv >= 4 ) {
1306
    vu_meter_prediv = 0;
1307
 
1308
    u8 track;
1309
    seq_core_trk_t *t = &seq_core_trk[0];
1310
    MIOS32_IRQ_Disable();
1311
    for(track=0; track<SEQ_CORE_NUM_TRACKS; ++t, ++track)
1312
      if( t->vu_meter )
1313
    --t->vu_meter;
1314
    MIOS32_IRQ_Enable();
1315
  }
1316
 
168 tk 1317
  return 0;
1318
}
1319
 
1320
 
1321
/////////////////////////////////////////////////////////////////////////////
134 tk 1322
// Returns the currently visible track
1323
/////////////////////////////////////////////////////////////////////////////
1324
u8 SEQ_UI_VisibleTrackGet(void)
1325
{
1326
  u8 offset = 0;
1327
 
1328
  if( ui_selected_tracks & (1 << 3) )
1329
    offset = 3;
1330
  if( ui_selected_tracks & (1 << 2) )
1331
    offset = 2;
1332
  if( ui_selected_tracks & (1 << 1) )
1333
    offset = 1;
1334
  if( ui_selected_tracks & (1 << 0) )
1335
    offset = 0;
1336
 
1337
  return 4*ui_selected_group + offset;
1338
}
1339
 
168 tk 1340
 
1341
/////////////////////////////////////////////////////////////////////////////
178 tk 1342
// Returns 1 if 'track' is selected
1343
/////////////////////////////////////////////////////////////////////////////
1344
s32 SEQ_UI_IsSelectedTrack(u8 track)
1345
{
1346
  if( (track>>2) != ui_selected_group )
1347
    return 0;
1348
  return (ui_selected_tracks & (1 << (track&3))) ? 1 : 0;
1349
}
1350
 
1351
 
1352
/////////////////////////////////////////////////////////////////////////////
240 tk 1353
// Sets a new selected step and updates the step view
1354
/////////////////////////////////////////////////////////////////////////////
1355
s32 SEQ_UI_SelectedStepSet(u8 step)
1356
{
1357
  ui_selected_step = step;
1358
  ui_selected_step_view = (ui_selected_step >= 16) ? 1 : 0;
1359
  return 0; // no error
1360
}
1361
 
1362
 
1363
/////////////////////////////////////////////////////////////////////////////
168 tk 1364
// Increments the selected tracks/groups
1365
// OUT: 1 if value has been changed, otherwise 0
1366
/////////////////////////////////////////////////////////////////////////////
1367
s32 SEQ_UI_GxTyInc(s32 incrementer)
1368
{
1369
  int gxty = SEQ_UI_VisibleTrackGet();
1370
  int prev_gxty = gxty;
1371
 
1372
  if( incrementer >= 0 ) {
1373
    if( (gxty += incrementer) >= SEQ_CORE_NUM_TRACKS )
1374
      gxty = SEQ_CORE_NUM_TRACKS-1;
1375
  } else {
1376
    if( (gxty += incrementer) < 0 )
1377
      gxty = 0;
1378
  }
1379
 
1380
  if( gxty == prev_gxty )
1381
    return 0; // no change
1382
 
1383
  ui_selected_tracks = 1 << (gxty % 4);
1384
  ui_selected_group = gxty / 4;
1385
 
1386
  return 1; // value changed
1387
}
1388
 
1389
 
1390
/////////////////////////////////////////////////////////////////////////////
236 tk 1391
// Increments a 16bit variable within given min/max range
1392
// OUT: 1 if value has been changed, otherwise 0
1393
/////////////////////////////////////////////////////////////////////////////
240 tk 1394
s32 SEQ_UI_Var16_Inc(u16 *value, u16 min, u16 max, s32 incrementer)
236 tk 1395
{
1396
  int new_value = *value;
1397
  int prev_value = new_value;
1398
 
1399
  if( incrementer >= 0 ) {
1400
    if( (new_value += incrementer) >= max )
1401
      new_value = max;
1402
  } else {
1403
    if( (new_value += incrementer) < min )
1404
      new_value = min;
1405
  }
1406
 
1407
  if( new_value == prev_value )
1408
    return 0; // no change
1409
 
1410
  *value = new_value;
1411
 
1412
  return 1; // value changed
1413
}
1414
 
240 tk 1415
/////////////////////////////////////////////////////////////////////////////
1416
// Increments an 8bit variable within given min/max range
1417
// OUT: 1 if value has been changed, otherwise 0
1418
/////////////////////////////////////////////////////////////////////////////
1419
s32 SEQ_UI_Var8_Inc(u8 *value, u16 min, u16 max, s32 incrementer)
1420
{
1421
  u16 tmp = *value;
1422
  if( SEQ_UI_Var16_Inc(&tmp, min, max, incrementer) ) {
1423
    *value = tmp;
1424
    return 1; // value changed
1425
  }
236 tk 1426
 
240 tk 1427
  return 0; // value hasn't been changed
1428
}
1429
 
1430
 
236 tk 1431
/////////////////////////////////////////////////////////////////////////////
168 tk 1432
// Increments a CC within given min/max range
1433
// OUT: 1 if value has been changed, otherwise 0
1434
/////////////////////////////////////////////////////////////////////////////
248 tk 1435
s32 SEQ_UI_CC_Inc(u8 cc, u8 min, u8 max, s32 incrementer)
168 tk 1436
{
1437
  u8 visible_track = SEQ_UI_VisibleTrackGet();
173 tk 1438
  int new_value = SEQ_CC_Get(visible_track, cc);
1439
  int prev_value = new_value;
168 tk 1440
 
1441
  if( incrementer >= 0 ) {
173 tk 1442
    if( (new_value += incrementer) >= max )
1443
      new_value = max;
168 tk 1444
  } else {
173 tk 1445
    if( (new_value += incrementer) < min )
1446
      new_value = min;
168 tk 1447
  }
1448
 
173 tk 1449
  if( new_value == prev_value )
168 tk 1450
    return 0; // no change
1451
 
173 tk 1452
  SEQ_CC_Set(visible_track, cc, new_value);
168 tk 1453
 
179 tk 1454
  // set same value for all selected tracks
1455
  u8 track;
1456
  for(track=0; track<SEQ_CORE_NUM_TRACKS; ++track)
1457
    if( track != visible_track && SEQ_UI_IsSelectedTrack(track) )
1458
      SEQ_CC_Set(track, cc, new_value);
1459
 
168 tk 1460
  return 1; // value changed
1461
}
1462
 
173 tk 1463
 
1464
/////////////////////////////////////////////////////////////////////////////
179 tk 1465
// Sets a CC value on all selected tracks
1466
// OUT: 1 if value has been changed, otherwise 0
1467
/////////////////////////////////////////////////////////////////////////////
248 tk 1468
s32 SEQ_UI_CC_Set(u8 cc, u8 value)
179 tk 1469
{
1470
  u8 visible_track = SEQ_UI_VisibleTrackGet();
1471
  int prev_value = SEQ_CC_Get(visible_track, cc);
1472
 
1473
  if( value == prev_value )
1474
    return 0; // no change
1475
 
1476
  SEQ_CC_Set(visible_track, cc, value);
1477
 
1478
  // set same value for all selected tracks
1479
  u8 track;
1480
  for(track=0; track<SEQ_CORE_NUM_TRACKS; ++track)
1481
    if( track != visible_track && SEQ_UI_IsSelectedTrack(track) )
1482
      SEQ_CC_Set(track, cc, value);
1483
 
1484
  return 1; // value changed
1485
}
1486
 
1487
/////////////////////////////////////////////////////////////////////////////
173 tk 1488
// Modifies a bitfield in a CC value to a given value
1489
// OUT: 1 if value has been changed, otherwise 0
1490
/////////////////////////////////////////////////////////////////////////////
248 tk 1491
s32 SEQ_UI_CC_SetFlags(u8 cc, u8 flag_mask, u8 value)
173 tk 1492
{
1493
  u8 visible_track = SEQ_UI_VisibleTrackGet();
1494
  int new_value = SEQ_CC_Get(visible_track, cc);
1495
  int prev_value = new_value;
1496
 
1497
  new_value = (new_value & ~flag_mask) | value;
1498
 
1499
  if( new_value == prev_value )
1500
    return 0; // no change
1501
 
1502
  SEQ_CC_Set(visible_track, cc, new_value);
1503
 
179 tk 1504
  // do same modification for all selected tracks
1505
  u8 track;
1506
  for(track=0; track<SEQ_CORE_NUM_TRACKS; ++track)
1507
    if( track != visible_track && SEQ_UI_IsSelectedTrack(track) ) {
1508
      int new_value = SEQ_CC_Get(track, cc);
1509
      new_value = (new_value & ~flag_mask) | value;
1510
      SEQ_CC_Set(track, cc, new_value);
1511
    }
1512
 
173 tk 1513
  return 1; // value changed
1514
}
1515
 
1516
 
299 tk 1517
/////////////////////////////////////////////////////////////////////////////
1518
// Print temporary messages after file operations
1519
// expects mS delay and two lines, each up to 20 characters
1520
/////////////////////////////////////////////////////////////////////////////
1521
s32 SEQ_UI_SDCardMsg(u16 delay, char *line1, char *line2)
1522
{
1523
  sdcard_msg_ctr = delay;
1524
  strncpy((char *)sdcard_msg[0], line1, SDCARD_MSG_MAX_CHAR);
1525
  strncpy((char *)sdcard_msg[1], line2, SDCARD_MSG_MAX_CHAR);
1526
 
1527
  return 0; // no error
1528
}
1529
 
1530
/////////////////////////////////////////////////////////////////////////////
1531
// Prints a temporary error messages after file operation
1532
// Expects error status number (as defined in seq_file.h)
1533
/////////////////////////////////////////////////////////////////////////////
1534
s32 SEQ_UI_SDCardErrMsg(u16 delay, s32 status)
1535
{
1536
  // TODO: add more verbose error messages, they are clearly defined in seq_file.h)
1537
  char str[21];
1538
  sprintf(str, "E%3d (DOSFS: D%3d)", -status, seq_file_dfs_errno < 1000 ? seq_file_dfs_errno : 999);
1539
  return SEQ_UI_SDCardMsg(delay, "!! SD Card Error !!!", str);
1540
}