Subversion Repositories svn.mios32

Rev

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