Subversion Repositories svn.mios32

Rev

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