Subversion Repositories svn.mios32

Rev

Rev 1319 | Rev 1341 | 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 1336 2011-09-28 19:11:58Z 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>
690 tk 23
#include <blm.h>
464 tk 24
#include <blm_x.h>
190 tk 25
#include <seq_midi_out.h>
26
#include <seq_bpm.h>
134 tk 27
 
290 tk 28
#include "tasks.h"
134 tk 29
#include "seq_ui.h"
728 tk 30
#include "seq_lcd.h"
31
#include "seq_lcd_logo.h"
492 tk 32
#include "seq_hwcfg.h"
134 tk 33
#include "seq_lcd.h"
34
#include "seq_led.h"
186 tk 35
#include "seq_midply.h"
134 tk 36
#include "seq_core.h"
399 tk 37
#include "seq_song.h"
333 tk 38
#include "seq_par.h"
178 tk 39
#include "seq_layer.h"
184 tk 40
#include "seq_cc.h"
1313 tk 41
#include "seq_record.h"
785 tk 42
#include "seq_midi_sysex.h"
1336 tk 43
#include "seq_midi_port.h"
1020 tk 44
#include "seq_blm.h"
1261 tk 45
 
46
#include "file.h"
299 tk 47
#include "seq_file.h"
1281 tk 48
#include "seq_file_t.h"
690 tk 49
#include "seq_file_hw.h"
134 tk 50
 
51
 
52
/////////////////////////////////////////////////////////////////////////////
53
// Global variables
54
/////////////////////////////////////////////////////////////////////////////
55
 
159 tk 56
u8 seq_ui_display_update_req;
57
u8 seq_ui_display_init_req;
134 tk 58
 
167 tk 59
seq_ui_button_state_t seq_ui_button_state;
60
 
134 tk 61
u8 ui_selected_group;
484 tk 62
u16 ui_selected_tracks;
134 tk 63
u8 ui_selected_par_layer;
64
u8 ui_selected_trg_layer;
328 tk 65
u8 ui_selected_instrument;
134 tk 66
u8 ui_selected_step_view;
67
u8 ui_selected_step;
168 tk 68
u8 ui_selected_item;
1319 tk 69
u16 ui_selected_gp_buttons;
134 tk 70
 
168 tk 71
u8 ui_selected_item;
134 tk 72
 
240 tk 73
u16 ui_hold_msg_ctr;
74
 
206 tk 75
seq_ui_page_t ui_page;
272 tk 76
seq_ui_page_t ui_selected_page;
600 tk 77
seq_ui_page_t ui_stepview_prev_page;
78
seq_ui_page_t ui_trglayer_prev_page;
79
seq_ui_page_t ui_parlayer_prev_page;
206 tk 80
 
173 tk 81
volatile u8 ui_cursor_flash;
740 tk 82
volatile u8 ui_cursor_flash_overrun_ctr;
173 tk 83
u16 ui_cursor_flash_ctr;
134 tk 84
 
316 tk 85
u8 ui_edit_name_cursor;
86
u8 ui_edit_preset_num_category;
87
u8 ui_edit_preset_num_label;
729 tk 88
u8 ui_edit_preset_num_drum;
316 tk 89
 
193 tk 90
u8 ui_seq_pause;
91
 
634 tk 92
u8 seq_ui_backup_req;
740 tk 93
u8 seq_ui_format_req;
974 tk 94
u8 seq_ui_saveall_req;
625 tk 95
 
744 tk 96
// to display directories via SEQ_UI_SelectListItem() and SEQ_LCD_PrintList() -- see seq_ui_sysex.c as example
746 tk 97
char ui_global_dir_list[80];
634 tk 98
 
1203 tk 99
seq_ui_bookmark_t seq_ui_bookmarks[SEQ_UI_BOOKMARKS_NUM];
744 tk 100
 
134 tk 101
/////////////////////////////////////////////////////////////////////////////
102
// Local variables
103
/////////////////////////////////////////////////////////////////////////////
104
 
168 tk 105
static s32 (*ui_button_callback)(seq_ui_button_t button, s32 depressed);
106
static s32 (*ui_encoder_callback)(seq_ui_encoder_t encoder, s32 incrementer);
173 tk 107
static s32 (*ui_led_callback)(u16 *gp_leds);
167 tk 108
static s32 (*ui_lcd_callback)(u8 high_prio);
352 tk 109
static s32 (*ui_exit_callback)(void);
752 tk 110
static s32 (*ui_delayed_action_callback)(u32 parameter);
111
static u32 ui_delayed_action_parameter;
167 tk 112
 
168 tk 113
static u16 ui_gp_leds;
167 tk 114
 
1040 tk 115
#define UI_MSG_MAX_CHAR 31
596 tk 116
static char ui_msg[2][UI_MSG_MAX_CHAR];
117
static u16 ui_msg_ctr;
118
static seq_ui_msg_type_t ui_msg_type;
299 tk 119
 
740 tk 120
static u16 ui_delayed_action_ctr;
299 tk 121
 
1203 tk 122
static seq_ui_page_t ui_page_before_bookmark;
752 tk 123
 
124
 
134 tk 125
/////////////////////////////////////////////////////////////////////////////
126
// Initialisation
127
/////////////////////////////////////////////////////////////////////////////
128
s32 SEQ_UI_Init(u32 mode)
129
{
626 tk 130
  int i;
131
  // clear all LEDs
132
  for(i=0; i<SEQ_LED_NUM_SR; ++i)
133
    SEQ_LED_SRSet(i, 0x00);
134
 
134 tk 135
  // init selection variables
136
  ui_selected_group = 0;
137
  ui_selected_tracks = (1 << 0);
138
  ui_selected_par_layer = 0;
139
  ui_selected_trg_layer = 0;
328 tk 140
  ui_selected_instrument = 0;
134 tk 141
  ui_selected_step_view = 0;
142
  ui_selected_step = 0;
168 tk 143
  ui_selected_item = 0;
1319 tk 144
  ui_selected_gp_buttons = 0;
134 tk 145
 
240 tk 146
  ui_hold_msg_ctr = 0;
596 tk 147
  ui_msg_ctr = 0;
740 tk 148
  ui_delayed_action_ctr = 0;
240 tk 149
 
740 tk 150
  ui_cursor_flash_ctr = ui_cursor_flash_overrun_ctr = 0;
173 tk 151
  ui_cursor_flash = 0;
168 tk 152
 
167 tk 153
  seq_ui_button_state.ALL = 0;
154
 
193 tk 155
  ui_seq_pause = 0;
156
 
134 tk 157
  // visible GP pattern
158
  ui_gp_leds = 0x0000;
159
 
634 tk 160
  // misc
161
  seq_ui_backup_req = 0;
740 tk 162
  seq_ui_format_req = 0;
974 tk 163
  seq_ui_saveall_req = 0;
634 tk 164
 
167 tk 165
  // change to edit page
166
  ui_page = SEQ_UI_PAGE_NONE;
167
  SEQ_UI_PageSet(SEQ_UI_PAGE_EDIT);
134 tk 168
 
1203 tk 169
  // finally init bookmarks
170
  ui_page_before_bookmark = SEQ_UI_PAGE_EDIT;
171
  for(i=0; i<SEQ_UI_BOOKMARKS_NUM; ++i) {
172
    char buffer[10];
173
    seq_ui_bookmark_t *bm = (seq_ui_bookmark_t *)&seq_ui_bookmarks[i];
596 tk 174
 
1203 tk 175
    sprintf(buffer, "BM%2d ", i+1);
176
    memcpy((char *)bm->name, buffer, 6);
177
    bm->enable.ALL = ~0;
178
    bm->flags.LOCKED = 0;
179
    SEQ_UI_Bookmark_Store(i);
180
  }
181
 
134 tk 182
  return 0; // no error
183
}
184
 
185
 
186
/////////////////////////////////////////////////////////////////////////////
178 tk 187
// Inits the speed mode of all encoders
188
// Auto mode should be used whenever:
189
//    - the edit screen is entered
190
//    - the group is changed
191
//    - a track is changed
192
//    - a layer is changed
193
/////////////////////////////////////////////////////////////////////////////
194
s32 SEQ_UI_InitEncSpeed(u32 auto_config)
195
{
196
  mios32_enc_config_t enc_config;
197
 
198
  if( auto_config ) {
513 tk 199
 
200
    if( !seq_hwcfg_enc.auto_fast )
201
      return 0; // auto mode not enabled - ignore auto reconfiguration request
202
 
333 tk 203
    switch( SEQ_PAR_AssignmentGet(SEQ_UI_VisibleTrackGet(), ui_selected_par_layer) ) {
204
      case SEQ_PAR_Type_Velocity:
205
      case SEQ_PAR_Type_Length:
206
      case SEQ_PAR_Type_CC:
207
      case SEQ_PAR_Type_PitchBend:
208
      case SEQ_PAR_Type_Probability:
209
      case SEQ_PAR_Type_Delay:
178 tk 210
    seq_ui_button_state.FAST_ENCODERS = 1;
211
    break;
212
 
213
      default:
214
    seq_ui_button_state.FAST_ENCODERS = 0;
215
    }
216
  }
217
 
218
  // change for datawheel and GP encoders
219
  int enc;
220
  for(enc=0; enc<17; ++enc) {
221
    enc_config = MIOS32_ENC_ConfigGet(enc);
1121 tk 222
    enc_config.cfg.speed = (seq_ui_button_state.FAST_ENCODERS || seq_ui_button_state.FAST2_ENCODERS) ? FAST : NORMAL;
513 tk 223
    enc_config.cfg.speed_par = (enc == 0) ? seq_hwcfg_enc.datawheel_fast_speed : seq_hwcfg_enc.gp_fast_speed;
178 tk 224
    MIOS32_ENC_ConfigSet(enc, enc_config);
225
  }
226
 
227
  return 0; // no error
228
}
229
 
230
 
231
/////////////////////////////////////////////////////////////////////////////
167 tk 232
// Various installation routines for menu page LCD handlers
233
/////////////////////////////////////////////////////////////////////////////
168 tk 234
s32 SEQ_UI_InstallButtonCallback(void *callback)
167 tk 235
{
168 tk 236
  ui_button_callback = callback;
167 tk 237
  return 0; // no error
238
}
239
 
168 tk 240
s32 SEQ_UI_InstallEncoderCallback(void *callback)
167 tk 241
{
168 tk 242
  ui_encoder_callback = callback;
167 tk 243
  return 0; // no error
244
}
245
 
168 tk 246
s32 SEQ_UI_InstallLEDCallback(void *callback)
167 tk 247
{
168 tk 248
  ui_led_callback = callback;
167 tk 249
  return 0; // no error
250
}
251
 
168 tk 252
s32 SEQ_UI_InstallLCDCallback(void *callback)
167 tk 253
{
254
  ui_lcd_callback = callback;
255
  return 0; // no error
256
}
257
 
352 tk 258
s32 SEQ_UI_InstallExitCallback(void *callback)
259
{
260
  ui_exit_callback = callback;
261
  return 0; // no error
262
}
167 tk 263
 
352 tk 264
 
752 tk 265
s32 SEQ_UI_InstallDelayedActionCallback(void *callback, u16 delay_mS, u32 parameter)
740 tk 266
{
752 tk 267
  // must be atomic
268
  MIOS32_IRQ_Disable();
269
  ui_delayed_action_parameter = parameter;
740 tk 270
  ui_delayed_action_callback = callback;
752 tk 271
  ui_delayed_action_ctr = delay_mS;
272
  MIOS32_IRQ_Enable();
740 tk 273
 
274
  return 0; // no error
275
}
276
 
277
s32 SEQ_UI_UnInstallDelayedActionCallback(void *callback)
278
{
752 tk 279
  // must be atomic
280
  MIOS32_IRQ_Disable();
740 tk 281
  if( ui_delayed_action_callback == callback )
282
    ui_delayed_action_callback = 0;
752 tk 283
  MIOS32_IRQ_Enable();
284
 
740 tk 285
  return 0; // no error
286
}
287
 
288
 
167 tk 289
/////////////////////////////////////////////////////////////////////////////
290
// Change the menu page
291
/////////////////////////////////////////////////////////////////////////////
292
s32 SEQ_UI_PageSet(seq_ui_page_t page)
293
{
294
  if( page != ui_page ) {
352 tk 295
 
296
    // call page exit callback
297
    if( ui_exit_callback != NULL )
298
      ui_exit_callback();
299
 
167 tk 300
    // disable hooks of previous page and request re-initialisation
318 tk 301
    portENTER_CRITICAL();
167 tk 302
    ui_page = page;
168 tk 303
    ui_button_callback = NULL;
304
    ui_encoder_callback = NULL;
305
    ui_led_callback = NULL;
167 tk 306
    ui_lcd_callback = NULL;
352 tk 307
    ui_exit_callback = NULL;
740 tk 308
    ui_delayed_action_callback = NULL;
318 tk 309
    portEXIT_CRITICAL();
167 tk 310
 
311
    // request display initialisation
312
    seq_ui_display_init_req = 1;
313
  }
173 tk 314
 
306 tk 315
  // for MENU button:
1024 tk 316
  if( seq_hwcfg_button_beh.menu )
317
    seq_ui_button_state.MENU_PRESSED = 0; // MENU page selection finished
306 tk 318
  // first page has been selected - display new screen
319
  seq_ui_button_state.MENU_FIRST_PAGE_SELECTED = 1;
320
 
272 tk 321
  // for SEQ_UI_MENU which is accessible with EXIT button
322
  // remember the current selectable page
323
  if( ui_page >= SEQ_UI_FIRST_MENU_SELECTION_PAGE )
324
    ui_selected_page = ui_page;
325
 
184 tk 326
  return 0; // no error
167 tk 327
}
328
 
329
 
330
/////////////////////////////////////////////////////////////////////////////
272 tk 331
// Returns name of menu page (18 characters)
332
/////////////////////////////////////////////////////////////////////////////
333
char *SEQ_UI_PageNameGet(seq_ui_page_t page)
334
{
690 tk 335
  return (char *)ui_menu_pages[page].name;
272 tk 336
}
337
 
338
 
339
/////////////////////////////////////////////////////////////////////////////
134 tk 340
// Dedicated button functions
341
// Mapped to physical buttons in SEQ_UI_Button_Handler()
342
// Will also be mapped to MIDI keys later (for MIDI remote function)
343
/////////////////////////////////////////////////////////////////////////////
344
static s32 SEQ_UI_Button_GP(s32 depressed, u32 gp)
345
{
1044 tk 346
  // in MENU page: overrule GP buttons as long as MENU button is pressed/active
306 tk 347
  if( seq_ui_button_state.MENU_PRESSED ) {
348
    if( depressed ) return -1;
349
    SEQ_UI_PageSet(ui_shortcut_menu_pages[gp]);
350
  } else {
1319 tk 351
    if( depressed )
352
      ui_selected_gp_buttons &= ~(1 << gp);
353
    else
354
      ui_selected_gp_buttons |= (1 << gp);
355
 
306 tk 356
    // forward to menu page
740 tk 357
    if( ui_button_callback != NULL ) {
306 tk 358
      ui_button_callback(gp, depressed);
740 tk 359
      ui_cursor_flash_ctr = ui_cursor_flash_overrun_ctr = 0;
360
    }
306 tk 361
  }
134 tk 362
 
363
  return 0; // no error
364
}
365
 
366
static s32 SEQ_UI_Button_Left(s32 depressed)
367
{
168 tk 368
  // forward to menu page
740 tk 369
  if( !seq_ui_button_state.MENU_PRESSED && ui_button_callback != NULL ) {
168 tk 370
    ui_button_callback(SEQ_UI_BUTTON_Left, depressed);
740 tk 371
    ui_cursor_flash_ctr = ui_cursor_flash_overrun_ctr = 0;
372
  }
134 tk 373
 
374
  return 0; // no error
375
}
376
 
377
static s32 SEQ_UI_Button_Right(s32 depressed)
378
{
168 tk 379
  // forward to menu page
740 tk 380
  if( !seq_ui_button_state.MENU_PRESSED && ui_button_callback != NULL ) {
168 tk 381
    ui_button_callback(SEQ_UI_BUTTON_Right, depressed);
740 tk 382
    ui_cursor_flash_ctr = ui_cursor_flash_overrun_ctr = 0;
383
  }
134 tk 384
 
385
  return 0; // no error
386
}
387
 
168 tk 388
static s32 SEQ_UI_Button_Down(s32 depressed)
389
{
240 tk 390
  seq_ui_button_state.DOWN = depressed ? 0 : 1;
391
 
168 tk 392
  // forward to menu page
740 tk 393
  if( !seq_ui_button_state.MENU_PRESSED && ui_button_callback != NULL ) {
168 tk 394
    ui_button_callback(SEQ_UI_BUTTON_Down, depressed);
740 tk 395
    ui_cursor_flash_ctr = ui_cursor_flash_overrun_ctr = 0;
396
  }
168 tk 397
 
398
  return 0; // no error
399
}
400
 
401
static s32 SEQ_UI_Button_Up(s32 depressed)
402
{
240 tk 403
  seq_ui_button_state.UP = depressed ? 0 : 1;
404
 
168 tk 405
  // forward to menu page
740 tk 406
  if( !seq_ui_button_state.MENU_PRESSED && ui_button_callback != NULL ) {
168 tk 407
    ui_button_callback(SEQ_UI_BUTTON_Up, depressed);
740 tk 408
    ui_cursor_flash_ctr = ui_cursor_flash_overrun_ctr = 0;
409
  }
168 tk 410
 
411
  return 0; // no error
412
}
413
 
1068 tk 414
s32 SEQ_UI_Button_Stop(s32 depressed)
134 tk 415
{
416
  if( depressed ) return -1; // ignore when button depressed
417
 
159 tk 418
  // if sequencer running: stop it
419
  // if sequencer already stopped: reset song position
1206 tk 420
  if( SEQ_BPM_IsRunning() ) {
421
#if 0
422
    // TK: maybe to complicated to understand: STOP sequencer in slave mode if stop button pressed twice
423
    u8 enable_slaveclk_mute = !SEQ_BPM_IsMaster() && seq_core_slaveclk_mute != SEQ_CORE_SLAVECLK_MUTE_Enabled;
424
#else
425
    // always mute tracks, never stop sequencer (can only be done from external)
426
    u8 enable_slaveclk_mute = !SEQ_BPM_IsMaster();
427
#endif
428
    if( enable_slaveclk_mute ) {
429
      seq_core_slaveclk_mute = SEQ_CORE_SLAVECLK_MUTE_Enabled;
430
    } else {
431
      seq_core_slaveclk_mute = SEQ_CORE_SLAVECLK_MUTE_Off;
432
      SEQ_BPM_Stop();
433
    }
434
  } else {
435
    seq_core_slaveclk_mute = SEQ_CORE_SLAVECLK_MUTE_Off;
1145 tk 436
    SEQ_SONG_Reset(0);
437
    SEQ_CORE_Reset(0);
759 tk 438
    SEQ_MIDPLY_Reset();
439
  }
159 tk 440
 
134 tk 441
  return 0; // no error
442
}
443
 
444
static s32 SEQ_UI_Button_Pause(s32 depressed)
445
{
446
  if( depressed ) return -1; // ignore when button depressed
447
 
1206 tk 448
  // if in auto mode and BPM generator is not clocked in slave mode:
193 tk 449
  // change to master mode
450
  SEQ_BPM_CheckAutoMaster();
159 tk 451
 
1206 tk 452
  // toggle pause
193 tk 453
  ui_seq_pause ^= 1;
454
 
455
  // execute stop/continue depending on new mode
1206 tk 456
  MIOS32_IRQ_Disable();
457
  if( ui_seq_pause ) {
458
    if( !SEQ_BPM_IsMaster() ) {
459
      seq_core_slaveclk_mute = SEQ_CORE_SLAVECLK_MUTE_Enabled;
460
    } else {
461
      SEQ_BPM_Stop();
462
    }
463
  } else {
464
    if( !SEQ_BPM_IsMaster() ) {
465
      seq_core_slaveclk_mute = SEQ_CORE_SLAVECLK_MUTE_Off;
466
    }
193 tk 467
 
1206 tk 468
    if( !SEQ_BPM_IsRunning() )
469
      SEQ_BPM_Cont();
470
  }
471
  MIOS32_IRQ_Enable();
472
 
134 tk 473
  return 0; // no error
474
}
475
 
1068 tk 476
s32 SEQ_UI_Button_Play(s32 depressed)
134 tk 477
{
478
  if( depressed ) return -1; // ignore when button depressed
479
 
1090 tk 480
  // if MENU button pressed -> tap tempo
481
  if( seq_ui_button_state.MENU_PRESSED )
482
    return SEQ_UI_BPM_TapTempo();
483
 
1206 tk 484
  // if in auto mode and BPM generator is not clocked in slave mode:
186 tk 485
  // change to master mode
486
  SEQ_BPM_CheckAutoMaster();
487
 
1206 tk 488
  // slave mode and tracks muted: enable on next measure
489
  if( !SEQ_BPM_IsMaster() && SEQ_BPM_IsRunning() ) {
490
    if( seq_core_slaveclk_mute != SEQ_CORE_SLAVECLK_MUTE_Off )
491
      seq_core_slaveclk_mute = SEQ_CORE_SLAVECLK_MUTE_OffOnNextMeasure;
492
    // TK: note - in difference to master mode pressing PLAY twice won't reset the sequencer!
493
  } else {
193 tk 494
#if 0
1206 tk 495
    // if sequencer running: restart it
496
    // if sequencer stopped: continue at last song position
497
    if( SEQ_BPM_IsRunning() )
498
      SEQ_BPM_Start();
499
    else
500
      SEQ_BPM_Cont();
501
#else
502
    // always restart sequencer
503
    seq_core_slaveclk_mute = SEQ_CORE_SLAVECLK_MUTE_Off;
193 tk 504
    SEQ_BPM_Start();
186 tk 505
#endif
1206 tk 506
  }
159 tk 507
 
134 tk 508
  return 0; // no error
509
}
510
 
511
static s32 SEQ_UI_Button_Rew(s32 depressed)
512
{
240 tk 513
  seq_ui_button_state.REW = depressed ? 0 : 1;
514
 
134 tk 515
  if( depressed ) return -1; // ignore when button depressed
516
 
607 tk 517
  if( SEQ_SONG_ActiveGet() ) {
518
    portENTER_CRITICAL();
519
    SEQ_SONG_Rew();
520
    portEXIT_CRITICAL();
521
  } else
522
    SEQ_UI_Msg(SEQ_UI_MSG_USER, 1000, "We are not", "in Song Mode!");
523
 
134 tk 524
  return 0; // no error
525
}
526
 
527
static s32 SEQ_UI_Button_Fwd(s32 depressed)
528
{
240 tk 529
  seq_ui_button_state.FWD = depressed ? 0 : 1;
530
 
134 tk 531
  if( depressed ) return -1; // ignore when button depressed
532
 
607 tk 533
  if( SEQ_SONG_ActiveGet() ) {
534
    portENTER_CRITICAL();
535
    SEQ_SONG_Fwd();
536
    portEXIT_CRITICAL();
537
  } else
538
    SEQ_UI_Msg(SEQ_UI_MSG_USER, 1000, "We are not", "in Song Mode!");
539
 
134 tk 540
  return 0; // no error
541
}
542
 
596 tk 543
static s32 SEQ_UI_Button_Loop(s32 depressed)
544
{
545
  if( seq_hwcfg_button_beh.loop ) {
546
    // toggle mode
547
    if( depressed ) return -1; // ignore when button depressed
548
    // should be atomic
549
    portENTER_CRITICAL();
550
    seq_core_state.LOOP ^= 1;
551
  } else {
552
    // should be atomic
553
    portENTER_CRITICAL();
554
    // set mode
555
    seq_core_state.LOOP = depressed ? 0 : 1;
556
  }
557
  portEXIT_CRITICAL();
558
 
559
  SEQ_UI_Msg(SEQ_UI_MSG_USER, 1000, "Loop Mode", seq_core_state.LOOP ? "    on" : "   off");
560
 
561
  return 0; // no error
562
}
563
 
951 tk 564
static s32 SEQ_UI_Button_Follow(s32 depressed)
565
{
566
  if( seq_hwcfg_button_beh.follow ) {
567
    // toggle mode
568
    if( depressed ) return -1; // ignore when button depressed
569
    // should be atomic
570
    portENTER_CRITICAL();
571
    seq_core_state.FOLLOW ^= 1;
572
  } else {
573
    // should be atomic
574
    portENTER_CRITICAL();
575
    // set mode
576
    seq_core_state.FOLLOW = depressed ? 0 : 1;
577
  }
578
  portEXIT_CRITICAL();
579
 
580
  SEQ_UI_Msg(SEQ_UI_MSG_USER, 1000, "Follow Mode", seq_core_state.FOLLOW ? "    on" : "   off");
581
 
582
  return 0; // no error
583
}
584
 
596 tk 585
static s32 SEQ_UI_Button_Scrub(s32 depressed)
586
{
587
  // double function: -> Loop if menu button pressed
588
  if( seq_ui_button_state.MENU_PRESSED )
589
    return SEQ_UI_Button_Loop(depressed);
590
 
591
  if( seq_hwcfg_button_beh.scrub ) {
592
    // toggle mode
593
    if( depressed ) return -1; // ignore when button depressed
594
    seq_ui_button_state.SCRUB ^= 1;
595
  } else {
596
    // set mode
597
    seq_ui_button_state.SCRUB = depressed ? 0 : 1;
598
  }
599
 
600
  SEQ_UI_Msg(SEQ_UI_MSG_USER, 1000, "Scrub Mode", seq_ui_button_state.SCRUB ? "    on" : "   off");
601
 
602
  return 0; // no error
603
}
604
 
513 tk 605
static s32 SEQ_UI_Button_TempoPreset(s32 depressed)
134 tk 606
{
513 tk 607
  static seq_ui_page_t prev_page = SEQ_UI_PAGE_NONE;
240 tk 608
 
513 tk 609
  if( seq_hwcfg_button_beh.tempo_preset ) {
610
    if( depressed ) return -1; // ignore when button depressed
678 tk 611
    if( !seq_ui_button_state.TEMPO_PRESET ) // due to page change: button going to be set, clear other toggle buttons
612
      seq_ui_button_state.PAGE_CHANGE_BUTTON_FLAGS = 0;
513 tk 613
    seq_ui_button_state.TEMPO_PRESET ^= 1; // toggle TEMPO_PRESET pressed (will also be released once GP button has been pressed)
614
  } else {
615
    // set mode
616
    seq_ui_button_state.TEMPO_PRESET = depressed ? 0 : 1;
617
  }
134 tk 618
 
513 tk 619
  if( seq_ui_button_state.TEMPO_PRESET ) {
620
    prev_page = ui_page;
621
    SEQ_UI_PageSet(SEQ_UI_PAGE_BPM_PRESETS);
622
  } else {
524 tk 623
    if( ui_page == SEQ_UI_PAGE_BPM_PRESETS )
624
      SEQ_UI_PageSet(prev_page);
513 tk 625
  }
240 tk 626
 
134 tk 627
  return 0; // no error
628
}
629
 
513 tk 630
static s32 SEQ_UI_Button_TapTempo(s32 depressed)
134 tk 631
{
513 tk 632
  seq_ui_button_state.TAP_TEMPO = depressed ? 0 : 1;
240 tk 633
 
134 tk 634
  if( depressed ) return -1; // ignore when button depressed
635
 
1142 tk 636
  return SEQ_UI_BPM_TapTempo();
134 tk 637
}
638
 
524 tk 639
static s32 SEQ_UI_Button_ExtRestart(s32 depressed)
134 tk 640
{
641
  if( depressed ) return -1; // ignore when button depressed
642
 
596 tk 643
  // should be atomic
524 tk 644
  portENTER_CRITICAL();
645
  seq_core_state.EXT_RESTART_REQ = 1;
646
  portEXIT_CRITICAL();
647
 
596 tk 648
  SEQ_UI_Msg(SEQ_UI_MSG_USER, 1000, "External Restart", "requested");
649
 
134 tk 650
  return 0; // no error
651
}
652
 
596 tk 653
static s32 SEQ_UI_Button_Metronome(s32 depressed)
654
{
655
  // double function: -> ExtRestart if menu button pressed
656
  if( seq_ui_button_state.MENU_PRESSED )
657
    return SEQ_UI_Button_ExtRestart(depressed);
658
 
659
  if( seq_hwcfg_button_beh.metronome ) {
660
    // toggle mode
661
    if( depressed ) return -1; // ignore when button depressed
662
    // should be atomic
663
    portENTER_CRITICAL();
664
    seq_core_state.METRONOME ^= 1;
665
  } else {
666
    // should be atomic
667
    portENTER_CRITICAL();
668
    // set mode
669
    seq_core_state.METRONOME = depressed ? 0 : 1;
670
  }
671
  portEXIT_CRITICAL();
672
 
673
  SEQ_UI_Msg(SEQ_UI_MSG_USER, 1000, "Metronome", seq_core_state.METRONOME ? "    on" : "   off");
674
 
599 tk 675
#if 0
676
  // metronome button can be used to trigger pattern file fixes
677
  if( !depressed )
678
    SEQ_PATTERN_FixAll();
679
#endif
680
 
596 tk 681
  return 0; // no error
682
}
683
 
630 tk 684
static s32 SEQ_UI_Button_Record(s32 depressed)
685
{
686
  if( depressed ) return -1; // ignore when button depressed
687
 
1219 tk 688
  // change to record page
630 tk 689
  SEQ_UI_PageSet(SEQ_UI_PAGE_TRKREC);
690
 
691
  return 0; // no error
692
}
693
 
1219 tk 694
static s32 SEQ_UI_Button_Live(s32 depressed)
695
{
696
  if( depressed ) return -1; // ignore when button depressed
697
 
698
  // change to live page
699
  SEQ_UI_PageSet(SEQ_UI_PAGE_TRKLIVE);
700
 
701
  return 0; // no error
702
}
703
 
134 tk 704
static s32 SEQ_UI_Button_Utility(s32 depressed)
705
{
706
  if( depressed ) return -1; // ignore when button depressed
707
 
240 tk 708
  // change to utility page
709
  SEQ_UI_PageSet(SEQ_UI_PAGE_UTIL);
710
 
134 tk 711
  return 0; // no error
712
}
713
 
1281 tk 714
static s32 SEQ_UI_Button_MultiCopy(s32 depressed)
715
{
716
  if( depressed ) return 1;
717
 
718
  s32 status = 0;
719
  char path[30];
720
 
721
  // create directory if it doesn't exist
722
  strcpy(path, "/PRESETS");
723
  MUTEX_SDCARD_TAKE;
724
  status = FILE_MakeDir(path);
725
  status = FILE_DirExists(path);
726
  MUTEX_SDCARD_GIVE;
727
 
728
  if( status < 0 ) {
729
    SEQ_UI_SDCardErrMsg(2000, status);
730
    return -3;
731
  }
732
 
733
  if( status == 0 ) {
734
    SEQ_UI_Msg(SEQ_UI_MSG_USER, 2000, "/PRESETS directory", "cannot be created!");
735
    return -4;
736
  }
737
 
738
  // copy all selected patterns to preset directory
739
  u8 track, track_id;
740
  for(track=0, track_id=0; track<SEQ_CORE_NUM_TRACKS; ++track) {
741
    if( ui_selected_tracks & (1 << track) ) {
742
      ++track_id;
743
      sprintf(path, "/PRESETS/COPY%d.v4t", track_id);
744
 
745
      char str[30];
746
      sprintf(str, "Exporting G%dT%d to:", (track/4)+1, (track%4)+1);
747
      SEQ_UI_Msg(SEQ_UI_MSG_USER, 2000, str, path);
748
 
749
      MUTEX_SDCARD_TAKE;
1282 tk 750
      status=SEQ_FILE_T_Write(path, track);
1281 tk 751
      MUTEX_SDCARD_GIVE;
752
 
753
      if( status < 0 ) {
754
    SEQ_UI_Msg(SEQ_UI_MSG_USER, 2000, "Error during Export!", "see MIOS Terminal!");
755
    return -6;
756
      }
757
    }
758
  }
759
 
760
  if( !track_id ) {
761
    SEQ_UI_Msg(SEQ_UI_MSG_USER, 2000, "No Track selected", "for Multi-Copy!");
762
  }
763
 
764
  return 0; // no error
765
}
766
 
134 tk 767
static s32 SEQ_UI_Button_Copy(s32 depressed)
768
{
240 tk 769
  static seq_ui_page_t prev_page = SEQ_UI_PAGE_NONE;
134 tk 770
 
240 tk 771
  seq_ui_button_state.COPY = depressed ? 0 : 1;
772
 
1281 tk 773
  if( seq_ui_button_state.MENU_PRESSED ) {
774
    return SEQ_UI_Button_MultiCopy(depressed);
775
  }
776
 
280 tk 777
  if( ui_page == SEQ_UI_PAGE_MIXER ) {
778
    if( depressed ) return -1;
779
    SEQ_UI_MIXER_Copy();
729 tk 780
    SEQ_UI_Msg(SEQ_UI_MSG_USER, 1000, "Mixer Map", "copied");
280 tk 781
    return 1;
729 tk 782
  } else if( ui_page == SEQ_UI_PAGE_SONG ) {
783
    if( depressed ) return -1;
784
    SEQ_UI_SONG_Copy();
785
    SEQ_UI_Msg(SEQ_UI_MSG_USER, 1000, "Song Position", "copied");
786
    return 1;
280 tk 787
  } else {
788
    if( !depressed ) {
789
      prev_page = ui_page;
790
      SEQ_UI_PageSet(SEQ_UI_PAGE_UTIL);
791
    }
240 tk 792
 
280 tk 793
    s32 status = SEQ_UI_UTIL_CopyButton(depressed);
240 tk 794
 
596 tk 795
    if( depressed ) {
796
      if( prev_page != SEQ_UI_PAGE_UTIL )
797
    SEQ_UI_PageSet(prev_page);
240 tk 798
 
596 tk 799
      SEQ_UI_Msg(SEQ_UI_MSG_USER, 1000, "Track", "copied");
800
    }
801
 
280 tk 802
    return status;
803
  }
134 tk 804
}
805
 
1281 tk 806
static s32 SEQ_UI_Button_MultiPaste(s32 depressed)
807
{
808
  if( depressed ) return 1;
809
 
810
  s32 status = 0;
811
  char path[30];
812
 
813
  // paste multi copy presets into selected tracks
814
  u8 track, track_id;
815
  for(track=0, track_id=0; track<SEQ_CORE_NUM_TRACKS; ++track) {
816
    if( ui_selected_tracks & (1 << track) ) {
817
      ++track_id;
818
      sprintf(path, "/PRESETS/COPY%d.v4t", track_id);
819
 
820
      char str[30];
821
      sprintf(str, "Importing to G%dT%d:", (track/4)+1, (track%4)+1);
822
      SEQ_UI_Msg(SEQ_UI_MSG_USER, 2000, str, path);
823
 
824
      // mute track to avoid random effects while loading the file
825
      MIOS32_IRQ_Disable(); // this operation should be atomic!
826
      u8 muted = seq_core_trk_muted & (1 << track);
827
      if( !muted )
828
    seq_core_trk_muted |= (1 << track);
829
      MIOS32_IRQ_Enable();
830
 
831
      static seq_file_t_import_flags_t import_flags;
832
      import_flags.ALL = 0xff;
833
 
834
      // read file
835
      MUTEX_SDCARD_TAKE;
836
      status = SEQ_FILE_T_Read(path, track, import_flags);
837
      MUTEX_SDCARD_GIVE;
838
 
839
      // unmute track if it wasn't muted before
840
      MIOS32_IRQ_Disable(); // this operation should be atomic!
841
      if( !muted )
842
    seq_core_trk_muted &= ~(1 << track);
843
      MIOS32_IRQ_Enable();
844
 
845
      if( status == FILE_ERR_OPEN_READ ) {
846
    char str[30];
847
    sprintf(str, "File for G%dT%d missing:", (track/4)+1, (track%4)+1);
848
    SEQ_UI_Msg(SEQ_UI_MSG_USER, 2000, str, path);
849
      } else if( status < 0 ) {
850
    SEQ_UI_SDCardErrMsg(2000, status);
851
      } else {
852
    sprintf(str, "Imported to G%dT%d:", (track/4)+1, (track%4)+1);
853
    SEQ_UI_Msg(SEQ_UI_MSG_USER, 2000, str, path);
854
      }
855
    }
856
  }
857
 
858
  if( !track_id ) {
859
    SEQ_UI_Msg(SEQ_UI_MSG_USER, 2000, "No Track selected", "for Multi-Paste!");
860
  }
861
 
862
  return 0; // no error
863
}
864
 
134 tk 865
static s32 SEQ_UI_Button_Paste(s32 depressed)
866
{
240 tk 867
  static seq_ui_page_t prev_page = SEQ_UI_PAGE_NONE;
134 tk 868
 
240 tk 869
  seq_ui_button_state.PASTE = depressed ? 0 : 1;
870
 
1281 tk 871
  if( seq_ui_button_state.MENU_PRESSED ) {
872
    return SEQ_UI_Button_MultiPaste(depressed);
873
  }
874
 
280 tk 875
  if( ui_page == SEQ_UI_PAGE_MIXER ) {
876
    if( depressed ) return -1;
877
    SEQ_UI_MIXER_Paste();
729 tk 878
    SEQ_UI_Msg(SEQ_UI_MSG_USER, 1000, "Mixer Map", "pasted");
280 tk 879
    return 1;
729 tk 880
  } else if( ui_page == SEQ_UI_PAGE_SONG ) {
881
    if( depressed ) return -1;
882
    SEQ_UI_SONG_Paste();
883
    SEQ_UI_Msg(SEQ_UI_MSG_USER, 1000, "Song Position", "pasted");
884
    return 1;
280 tk 885
  } else {
886
    if( !depressed ) {
887
      prev_page = ui_page;
888
      SEQ_UI_PageSet(SEQ_UI_PAGE_UTIL);
889
    }
240 tk 890
 
280 tk 891
    s32 status = SEQ_UI_UTIL_PasteButton(depressed);
240 tk 892
 
596 tk 893
    if( depressed ) {
894
      if( prev_page != SEQ_UI_PAGE_UTIL )
895
    SEQ_UI_PageSet(prev_page);
240 tk 896
 
596 tk 897
      SEQ_UI_Msg(SEQ_UI_MSG_USER, 1000, "Track", "pasted");
898
    }
899
 
280 tk 900
    return status;
901
  }
134 tk 902
}
903
 
740 tk 904
 
905
// callback function for delayed Clear Mixer function
752 tk 906
static void SEQ_UI_Button_Clear_Mixer(u32 dummy)
740 tk 907
{
908
  SEQ_UI_MIXER_Clear();
909
  SEQ_UI_Msg(SEQ_UI_MSG_USER, 1000, "Mixer Map", "cleared");
910
}
911
 
912
// callback function for delayed Clear SongPos function
752 tk 913
static void SEQ_UI_Button_Clear_SongPos(u32 dummy)
740 tk 914
{
915
  SEQ_UI_SONG_Clear();
916
  SEQ_UI_Msg(SEQ_UI_MSG_USER, 1000, "Song Position", "cleared");
917
}
918
 
919
// callback function for clear track
752 tk 920
static void SEQ_UI_Button_Clear_Track(u32 dummy)
740 tk 921
{
922
  SEQ_UI_UTIL_ClearButton(0); // button pressed
923
  SEQ_UI_UTIL_ClearButton(1); // button depressed
924
  SEQ_UI_Msg(SEQ_UI_MSG_USER, 1000, "Track", "cleared");
925
}
926
 
134 tk 927
static s32 SEQ_UI_Button_Clear(s32 depressed)
928
{
240 tk 929
  seq_ui_button_state.CLEAR = depressed ? 0 : 1;
280 tk 930
 
931
  if( ui_page == SEQ_UI_PAGE_MIXER ) {
740 tk 932
    if( depressed )
933
      SEQ_UI_UnInstallDelayedActionCallback(SEQ_UI_Button_Clear_Mixer);
752 tk 934
    else {
935
      SEQ_UI_InstallDelayedActionCallback(SEQ_UI_Button_Clear_Mixer, 2000, 0);
936
      SEQ_UI_Msg(SEQ_UI_MSG_DELAYED_ACTION, 2001, "", "to clear Mixer Map");
937
    }
729 tk 938
    return 1;
939
  } else if( ui_page == SEQ_UI_PAGE_SONG ) {
740 tk 940
    if( depressed )
941
      SEQ_UI_UnInstallDelayedActionCallback(SEQ_UI_Button_Clear_SongPos);
752 tk 942
    else {
943
      SEQ_UI_InstallDelayedActionCallback(SEQ_UI_Button_Clear_SongPos, 2000, 0);
944
      SEQ_UI_Msg(SEQ_UI_MSG_DELAYED_ACTION, 2001, "", "to clear SongPos");
945
    }
729 tk 946
    return 1;
947
  } else {
740 tk 948
    if( depressed )
949
      SEQ_UI_UnInstallDelayedActionCallback(SEQ_UI_Button_Clear_Track);
752 tk 950
    else {
951
      SEQ_UI_InstallDelayedActionCallback(SEQ_UI_Button_Clear_Track, 2000, 0);
952
      SEQ_UI_Msg(SEQ_UI_MSG_DELAYED_ACTION, 2001, "", "to clear Track");
953
    }
280 tk 954
    return 1;
955
  }
134 tk 956
}
957
 
1014 tk 958
 
959
static s32 SEQ_UI_Button_Undo(s32 depressed)
960
{
961
  static seq_ui_page_t prev_page = SEQ_UI_PAGE_NONE;
962
 
963
  seq_ui_button_state.UNDO = depressed ? 0 : 1;
964
 
965
  if( ui_page == SEQ_UI_PAGE_MIXER ) {
966
    if( depressed ) return -1;
967
    SEQ_UI_MIXER_Undo();
968
    SEQ_UI_Msg(SEQ_UI_MSG_USER, 1000, "Mixer Map", "Undo applied");
969
    return 1;
970
  } else {
971
    if( !depressed ) {
972
      prev_page = ui_page;
973
      SEQ_UI_PageSet(SEQ_UI_PAGE_UTIL);
974
    }
975
 
976
    s32 status = SEQ_UI_UTIL_UndoButton(depressed);
977
 
978
    if( depressed ) {
979
      if( prev_page != SEQ_UI_PAGE_UTIL )
980
    SEQ_UI_PageSet(prev_page);
981
 
982
      SEQ_UI_Msg(SEQ_UI_MSG_USER, 1000, "Track", "Undo applied");
983
    }
984
 
985
    return status;
986
  }
987
}
988
 
989
 
134 tk 990
static s32 SEQ_UI_Button_Menu(s32 depressed)
991
{
513 tk 992
  if( seq_hwcfg_button_beh.menu ) {
993
    // toggle mode
994
    if( depressed ) return -1; // ignore when button depressed
995
    seq_ui_button_state.MENU_FIRST_PAGE_SELECTED = 0;
678 tk 996
    if( !seq_ui_button_state.MENU_PRESSED ) // due to page change: button going to be set, clear other toggle buttons
997
      seq_ui_button_state.PAGE_CHANGE_BUTTON_FLAGS = 0;
513 tk 998
    seq_ui_button_state.MENU_PRESSED ^= 1; // toggle MENU pressed (will also be released once GP button has been pressed)
999
  } else {
1000
    // set mode
1001
    seq_ui_button_state.MENU_FIRST_PAGE_SELECTED = 0;
1002
    seq_ui_button_state.MENU_PRESSED = depressed ? 0 : 1;
1003
  }
134 tk 1004
 
1005
  return 0; // no error
1006
}
1007
 
1203 tk 1008
 
1009
static s32 SEQ_UI_Button_Bookmark(s32 depressed)
1010
{
1011
  if( seq_hwcfg_button_beh.bookmark ) {
1012
    if( depressed ) return -1; // ignore when button depressed
1013
    if( !seq_ui_button_state.BOOKMARK ) // due to page change: button going to be set, clear other toggle buttons
1014
      seq_ui_button_state.PAGE_CHANGE_BUTTON_FLAGS = 0;
1015
#if 0
1016
    seq_ui_button_state.BOOKMARK ^= 1; // toggle BOOKMARK pressed (will also be released once GP button has been pressed)
1017
#else
1018
    seq_ui_button_state.BOOKMARK = 1; // seems that it's better *not* to toggle!
1019
#endif
1020
  } else {
1021
    // set mode
1022
    seq_ui_button_state.BOOKMARK = depressed ? 0 : 1;
1023
  }
1024
 
1025
  if( seq_ui_button_state.BOOKMARK ) {
1026
    if( ui_page != SEQ_UI_PAGE_BOOKMARKS )
1027
      ui_page_before_bookmark = ui_page;
1028
    SEQ_UI_PageSet(SEQ_UI_PAGE_BOOKMARKS);
1029
  } else {
1030
    if( ui_page == SEQ_UI_PAGE_BOOKMARKS )
1031
      SEQ_UI_PageSet(ui_page_before_bookmark);
1032
  }
1033
 
1034
  return 0; // no error
1035
}
1036
 
1037
 
1205 tk 1038
static s32 SEQ_UI_Button_DirectBookmark(s32 depressed, u32 bookmark_button)
1039
{
1040
  if( !depressed )
1041
    ui_page_before_bookmark = ui_page;
1042
 
1043
  return SEQ_UI_BOOKMARKS_Button_Handler(bookmark_button, depressed);
1044
}
1045
 
1046
 
134 tk 1047
static s32 SEQ_UI_Button_Select(s32 depressed)
1048
{
1203 tk 1049
  // double function: -> Bookmark if menu button pressed
1050
  if( seq_ui_button_state.MENU_PRESSED )
1051
    return SEQ_UI_Button_Bookmark(depressed);
1052
 
168 tk 1053
  // forward to menu page
591 tk 1054
  if( !seq_ui_button_state.MENU_PRESSED ) {
1055
    seq_ui_button_state.SELECT_PRESSED = depressed ? 0 : 1;
740 tk 1056
    if( ui_button_callback != NULL ) {
591 tk 1057
      ui_button_callback(SEQ_UI_BUTTON_Select, depressed);
740 tk 1058
      ui_cursor_flash_ctr = ui_cursor_flash_overrun_ctr = 0;
1059
    }
591 tk 1060
  }
134 tk 1061
 
1062
  return 0; // no error
1063
}
1064
 
1065
static s32 SEQ_UI_Button_Exit(s32 depressed)
1066
{
951 tk 1067
  // double function: -> Follow if menu button pressed
1068
  if( seq_ui_button_state.MENU_PRESSED )
1069
    return SEQ_UI_Button_Follow(depressed);
1070
 
272 tk 1071
  if( depressed ) return -1; // ignore when button depressed
1072
 
1073
  u8 prev_ui_page = ui_page;
1074
 
168 tk 1075
  // forward to menu page
1123 tk 1076
  if( ui_button_callback != NULL ) {
1077
    if( ui_button_callback(SEQ_UI_BUTTON_Exit, depressed) >= 1 )
1078
      return 1; // page has already handled exit button
740 tk 1079
    ui_cursor_flash_ctr = ui_cursor_flash_overrun_ctr = 0;
1080
  }
134 tk 1081
 
167 tk 1082
  // release all button states
984 tk 1083
  // seq_ui_button_state.ALL = 0;
1084
  // clashes with SOLO/ALL/etc.
167 tk 1085
 
272 tk 1086
  // enter menu page if we were not there before
1087
  if( prev_ui_page != SEQ_UI_PAGE_MENU )
1088
    SEQ_UI_PageSet(SEQ_UI_PAGE_MENU);
1089
 
134 tk 1090
  return 0; // no error
1091
}
1092
 
1093
static s32 SEQ_UI_Button_Edit(s32 depressed)
1094
{
741 tk 1095
  seq_ui_button_state.EDIT_PRESSED = depressed ? 0 : 1;
591 tk 1096
 
134 tk 1097
  if( depressed ) return -1; // ignore when button depressed
1098
 
167 tk 1099
  // change to edit page
1100
  SEQ_UI_PageSet(SEQ_UI_PAGE_EDIT);
1101
 
178 tk 1102
  // set/clear encoder fast function if required
1103
  SEQ_UI_InitEncSpeed(1); // auto config
1104
 
134 tk 1105
  return 0; // no error
1106
}
1107
 
1108
static s32 SEQ_UI_Button_Mute(s32 depressed)
1109
{
591 tk 1110
  seq_ui_button_state.MUTE_PRESSED = depressed ? 0 : 1;
1111
 
134 tk 1112
  if( depressed ) return -1; // ignore when button depressed
1113
 
184 tk 1114
  SEQ_UI_PageSet(SEQ_UI_PAGE_MUTE);
1115
 
134 tk 1116
  return 0; // no error
1117
}
1118
 
1119
static s32 SEQ_UI_Button_Pattern(s32 depressed)
1120
{
591 tk 1121
  seq_ui_button_state.PATTERN_PRESSED = depressed ? 0 : 1;
1122
 
134 tk 1123
  if( depressed ) return -1; // ignore when button depressed
1124
 
184 tk 1125
  SEQ_UI_PageSet(SEQ_UI_PAGE_PATTERN);
1126
 
134 tk 1127
  return 0; // no error
1128
}
1129
 
1130
static s32 SEQ_UI_Button_Song(s32 depressed)
1131
{
591 tk 1132
  seq_ui_button_state.SONG_PRESSED = depressed ? 0 : 1;
1133
 
134 tk 1134
  if( depressed ) return -1; // ignore when button depressed
1135
 
399 tk 1136
  SEQ_UI_PageSet(SEQ_UI_PAGE_SONG);
1137
 
134 tk 1138
  return 0; // no error
1139
}
1140
 
1141
static s32 SEQ_UI_Button_Solo(s32 depressed)
1142
{
513 tk 1143
  if( seq_hwcfg_button_beh.solo ) {
1144
    // toggle mode
1145
    if( depressed ) return -1; // ignore when button depressed
1146
    seq_ui_button_state.SOLO ^= 1;
1147
  } else {
1148
    // set mode
1149
    seq_ui_button_state.SOLO = depressed ? 0 : 1;
1150
  }
134 tk 1151
 
1152
  return 0; // no error
1153
}
1154
 
1155
static s32 SEQ_UI_Button_Fast(s32 depressed)
1156
{
513 tk 1157
  if( seq_hwcfg_button_beh.fast ) {
1158
    // toggle mode
1159
    if( depressed ) return -1; // ignore when button depressed
1160
    seq_ui_button_state.FAST_ENCODERS ^= 1;
1161
  } else {
1162
    // set mode
1163
    seq_ui_button_state.FAST_ENCODERS = depressed ? 0 : 1;
1164
  }
134 tk 1165
 
178 tk 1166
  SEQ_UI_InitEncSpeed(0); // no auto config
1167
 
134 tk 1168
  return 0; // no error
1169
}
1170
 
1121 tk 1171
static s32 SEQ_UI_Button_Fast2(s32 depressed)
1172
{
1173
  if( seq_hwcfg_button_beh.fast2 ) {
1174
    // toggle mode
1175
    if( depressed ) return -1; // ignore when button depressed
1176
    seq_ui_button_state.FAST2_ENCODERS ^= 1;
1177
  } else {
1178
    // set mode
1179
    seq_ui_button_state.FAST2_ENCODERS = depressed ? 0 : 1;
1180
  }
1181
 
1182
  SEQ_UI_InitEncSpeed(0); // no auto config
1183
 
1184
  return 0; // no error
1185
}
1186
 
134 tk 1187
static s32 SEQ_UI_Button_All(s32 depressed)
1188
{
178 tk 1189
  seq_ui_button_state.CHANGE_ALL_STEPS_SAME_VALUE = depressed ? 0 : 1;
134 tk 1190
 
513 tk 1191
  if( seq_hwcfg_button_beh.all ) {
1192
    // toggle mode
1193
    if( depressed ) return -1;
1194
    seq_ui_button_state.CHANGE_ALL_STEPS ^= 1;
1195
  } else {
1196
    // set mode
1197
    seq_ui_button_state.CHANGE_ALL_STEPS = depressed ? 0 : 1;
1198
  }
178 tk 1199
 
134 tk 1200
  return 0; // no error
1201
}
1202
 
1203
static s32 SEQ_UI_Button_StepView(s32 depressed)
1204
{
600 tk 1205
  //  static seq_ui_page_t prev_page = SEQ_UI_PAGE_NONE;
1206
  // also used by seq_ui_stepsel
1207
 
513 tk 1208
  if( seq_hwcfg_button_beh.step_view ) {
1209
    if( depressed ) return -1; // ignore when button depressed
678 tk 1210
    if( !seq_ui_button_state.STEP_VIEW ) // due to page change: button going to be set, clear other toggle buttons
1211
      seq_ui_button_state.PAGE_CHANGE_BUTTON_FLAGS = 0;
513 tk 1212
    seq_ui_button_state.STEP_VIEW ^= 1; // toggle STEP_VIEW pressed (will also be released once GP button has been pressed)
1213
  } else {
1214
    // set mode
1215
    seq_ui_button_state.STEP_VIEW = depressed ? 0 : 1;
1216
  }
134 tk 1217
 
513 tk 1218
  if( seq_ui_button_state.STEP_VIEW ) {
600 tk 1219
    ui_stepview_prev_page = ui_page;
303 tk 1220
    SEQ_UI_PageSet(SEQ_UI_PAGE_STEPSEL);
1221
  } else {
524 tk 1222
    if( ui_page == SEQ_UI_PAGE_STEPSEL )
600 tk 1223
      SEQ_UI_PageSet(ui_stepview_prev_page);
303 tk 1224
  }
134 tk 1225
 
1226
  return 0; // no error
1227
}
1228
 
513 tk 1229
static s32 SEQ_UI_Button_TrackSel(s32 depressed)
134 tk 1230
{
513 tk 1231
  static seq_ui_page_t prev_page = SEQ_UI_PAGE_NONE;
134 tk 1232
 
513 tk 1233
  if( seq_hwcfg_button_beh.track_sel ) {
1234
    if( depressed ) return -1; // ignore when button depressed
678 tk 1235
    if( !seq_ui_button_state.TRACK_SEL ) // due to page change: button going to be set, clear other toggle buttons
1236
      seq_ui_button_state.PAGE_CHANGE_BUTTON_FLAGS = 0;
513 tk 1237
    seq_ui_button_state.TRACK_SEL ^= 1; // toggle TRACKSEL status (will also be released once GP button has been pressed)
1238
  } else {
1239
    seq_ui_button_state.TRACK_SEL = depressed ? 0 : 1;
1240
  }
1241
 
1242
  if( seq_ui_button_state.TRACK_SEL ) {
1243
    prev_page = ui_page;
1244
    SEQ_UI_PageSet(SEQ_UI_PAGE_TRACKSEL);
1245
  } else {
524 tk 1246
    if( ui_page == SEQ_UI_PAGE_TRACKSEL )
1247
      SEQ_UI_PageSet(prev_page);
513 tk 1248
  }
1249
 
134 tk 1250
  return 0; // no error
1251
}
1252
 
987 tk 1253
static s32 SEQ_UI_Button_Group(s32 depressed, u32 group)
1254
{
1255
  if( depressed ) return -1; // ignore when button depressed
1256
 
1257
  if( group >= 4 ) return -2; // max. 4 group buttons
1258
 
1259
  // in song page: track and group buttons are used to select the cursor position
1260
  if( ui_page == SEQ_UI_PAGE_SONG ) {
1261
    ui_selected_item = 3 + group;
1262
    return 0;
1263
  }
1264
 
1265
  // if group has changed:
1266
  if( group != ui_selected_group ) {
1267
    // get current track selection
1268
    u16 old_tracks = ui_selected_tracks >> (4*ui_selected_group);
1269
 
1270
    // select new group
1271
    ui_selected_group = group;
1272
 
1273
    // take over old track selection
1274
    ui_selected_tracks = old_tracks << (4*ui_selected_group);
1275
  }
1276
 
1277
  // set/clear encoder fast function if required
1278
  SEQ_UI_InitEncSpeed(1); // auto config
1279
 
1280
  return 0; // no error
1281
}
1282
 
484 tk 1283
static s32 SEQ_UI_Button_Track(s32 depressed, u32 track_button)
134 tk 1284
{
484 tk 1285
  static u8 button_state = 0x0f; // all 4 buttons depressed
134 tk 1286
 
484 tk 1287
  if( track_button >= 4 ) return -2; // max. 4 track buttons
134 tk 1288
 
484 tk 1289
  if( depressed ) {
1290
    button_state |= (1 << track_button);
1291
    return 0; // no error
1292
  }
134 tk 1293
 
484 tk 1294
  button_state &= ~(1 << track_button);
1295
 
987 tk 1296
  // in pattern and song page: use track buttons as group buttons
1297
  if( ui_page == SEQ_UI_PAGE_PATTERN || ui_page == SEQ_UI_PAGE_SONG ) {
1298
    return SEQ_UI_Button_Group(depressed, track_button);
1299
  }
1300
 
484 tk 1301
  if( button_state == (~(1 << track_button) & 0xf) ) {
1302
    // if only one select button pressed: radio-button function (1 of 4)
1303
    ui_selected_tracks = 1 << (track_button + 4*ui_selected_group);
1304
  } else {
1305
    // if more than one select button pressed: toggle function (4 of 4)
1306
    ui_selected_tracks ^= 1 << (track_button + 4*ui_selected_group);
1307
  }
1308
 
178 tk 1309
  // set/clear encoder fast function if required
1310
  SEQ_UI_InitEncSpeed(1); // auto config
1311
 
134 tk 1312
  return 0; // no error
1313
}
1314
 
1146 tk 1315
static s32 SEQ_UI_Button_DirectTrack(s32 depressed, u32 track_button)
1316
{
1317
  static u16 button_state = 0xffff; // all 16 buttons depressed
1318
 
1319
  if( track_button >= 16 ) return -2; // max. 16 direct track buttons
1320
 
1321
  if( depressed ) {
1322
    button_state |= (1 << track_button);
1323
    return 0; // no error
1324
  }
1325
 
1326
  button_state &= ~(1 << track_button);
1327
 
1328
  if( button_state == (~(1 << track_button) & 0xffff) ) {
1329
    // if only one select button pressed: radio-button function (1 of 16)
1330
    ui_selected_tracks = 1 << track_button;
1331
  } else {
1332
    // if more than one select button pressed: toggle function (16 of 16)
1333
    ui_selected_tracks ^= 1 << track_button;
1334
  }
1335
 
1336
  // set/clear encoder fast function if required
1337
  SEQ_UI_InitEncSpeed(1); // auto config
1338
 
1339
  return 0; // no error
1340
}
1341
 
513 tk 1342
static s32 SEQ_UI_Button_ParLayerSel(s32 depressed)
1343
{
600 tk 1344
  // static seq_ui_page_t prev_page = SEQ_UI_PAGE_NONE;
1345
  // also used by seq_ui_parsel.c
513 tk 1346
 
1347
  if( seq_hwcfg_button_beh.par_layer ) {
1348
    if( depressed ) return -1; // ignore when button depressed
678 tk 1349
    if( !seq_ui_button_state.PAR_LAYER_SEL ) // due to page change: button going to be set, clear other toggle buttons
1350
      seq_ui_button_state.PAGE_CHANGE_BUTTON_FLAGS = 0;
513 tk 1351
    seq_ui_button_state.PAR_LAYER_SEL ^= 1; // toggle PARSEL status (will also be released once GP button has been pressed)
1352
  } else {
1353
    seq_ui_button_state.PAR_LAYER_SEL = depressed ? 0 : 1;
1354
  }
1355
 
1356
  if( seq_ui_button_state.PAR_LAYER_SEL ) {
600 tk 1357
    ui_parlayer_prev_page = ui_page;
513 tk 1358
    SEQ_UI_PageSet(SEQ_UI_PAGE_PARSEL);
1359
  } else {
524 tk 1360
    if( ui_page == SEQ_UI_PAGE_PARSEL )
600 tk 1361
      SEQ_UI_PageSet(ui_parlayer_prev_page);
513 tk 1362
  }
1363
 
1364
  // set/clear encoder fast function if required
1365
  SEQ_UI_InitEncSpeed(1); // auto config
1366
 
1367
  return 0; // no error
1368
}
1369
 
134 tk 1370
static s32 SEQ_UI_Button_ParLayer(s32 depressed, u32 par_layer)
1371
{
1117 tk 1372
  static u8 layer_c_pressed = 0;
784 tk 1373
 
134 tk 1374
  if( par_layer >= 3 ) return -2; // max. 3 parlayer buttons
1375
 
1205 tk 1376
  u8 visible_track = SEQ_UI_VisibleTrackGet();
1377
  u8 num_p_layers = SEQ_PAR_NumLayersGet(visible_track);
1378
 
987 tk 1379
  // in song page: parameter layer buttons are used to select the cursor position
1380
  if( ui_page == SEQ_UI_PAGE_SONG ) {
1381
    ui_selected_item = par_layer;
1382
    return 0;
1383
  }
1384
 
1205 tk 1385
  // drum mode in edit page: print parameter layer as long as button is pressed
1386
  if( ui_page == SEQ_UI_PAGE_EDIT ) {
1387
    u8 event_mode = SEQ_CC_Get(visible_track, SEQ_CC_MIDI_EVENT_MODE);
1388
    if( event_mode == SEQ_EVENT_MODE_Drum ) {
1389
      ui_hold_msg_ctr = depressed ? 0 : ~0; // show value for at least 65 seconds... enough?
1390
    }
1391
  }
134 tk 1392
 
784 tk 1393
  // holding Layer C button allows to increment/decrement layer with A/B button
1394
  if( par_layer == 2 )
1395
    layer_c_pressed = !depressed;
1396
 
1397
  if( layer_c_pressed && par_layer == 0 ) {
333 tk 1398
    if( depressed ) return -1; // ignore when button depressed
784 tk 1399
    // increment layer
1400
    if( ++ui_selected_par_layer >= num_p_layers )
1401
      ui_selected_par_layer = 0;
1402
  } else if( layer_c_pressed && par_layer == 1 ) {
333 tk 1403
    if( depressed ) return -1; // ignore when button depressed
784 tk 1404
    // decrement layer
1405
    if( ui_selected_par_layer == 0 )
1406
      ui_selected_par_layer = num_p_layers - 1;
333 tk 1407
    else
784 tk 1408
      --ui_selected_par_layer;
333 tk 1409
  } else {
784 tk 1410
    if( num_p_layers <= 3 ) {
1411
      // 3 layers: direct selection with LayerA/B/C button
333 tk 1412
      if( depressed ) return -1; // ignore when button depressed
784 tk 1413
      if( par_layer >= num_p_layers ) {
1414
    char str1[21];
1415
    sprintf(str1, "Parameter Layer %c", 'A'+par_layer);
1416
    SEQ_UI_Msg(SEQ_UI_MSG_USER, 1000, str1, "not available!");
1417
      } else {
1418
    seq_ui_button_state.PAR_LAYER_SEL = 0;
1419
    ui_selected_par_layer = par_layer;
1420
      }
1421
    } else if( num_p_layers <= 4 ) {
1422
      // 4 layers: LayerC Button toggles between C and D
1423
      if( depressed ) return -1; // ignore when button depressed
333 tk 1424
      seq_ui_button_state.PAR_LAYER_SEL = 0;
784 tk 1425
      if( par_layer == 2 )
1426
    ui_selected_par_layer = (ui_selected_par_layer == 2) ? 3 : 2;
1427
      else
1428
    ui_selected_par_layer = par_layer;
333 tk 1429
    } else {
784 tk 1430
      // >4 layers: LayerA/B button selects directly, Layer C button enters layer selection page
1431
      if( par_layer <= 1 ) {
1432
    if( depressed ) return -1; // ignore when button depressed
1433
    seq_ui_button_state.PAR_LAYER_SEL = 0;
1434
    ui_selected_par_layer = par_layer;
1435
      } else {
1436
    return SEQ_UI_Button_ParLayerSel(depressed);
1437
      }
333 tk 1438
    }
1439
  }
1440
 
178 tk 1441
  // set/clear encoder fast function if required
1442
  SEQ_UI_InitEncSpeed(1); // auto config
1443
 
134 tk 1444
  return 0; // no error
1445
}
1446
 
513 tk 1447
static s32 SEQ_UI_Button_TrgLayerSel(s32 depressed)
1448
{
600 tk 1449
  // static seq_ui_page_t prev_page = SEQ_UI_PAGE_NONE;
1450
  // also used by seq_ui_trgsel.c
513 tk 1451
 
1452
  if( seq_hwcfg_button_beh.trg_layer ) {
1453
    if( depressed ) return -1; // ignore when button depressed
678 tk 1454
    if( !seq_ui_button_state.TRG_LAYER_SEL ) // due to page change: button going to be set, clear other toggle buttons
1455
      seq_ui_button_state.PAGE_CHANGE_BUTTON_FLAGS = 0;
513 tk 1456
    seq_ui_button_state.TRG_LAYER_SEL ^= 1; // toggle TRGSEL status (will also be released once GP button has been pressed)
1457
  } else {
1458
    seq_ui_button_state.TRG_LAYER_SEL = depressed ? 0 : 1;
1459
  }
1460
 
1461
  if( seq_ui_button_state.TRG_LAYER_SEL ) {
600 tk 1462
    ui_trglayer_prev_page = ui_page;
513 tk 1463
    SEQ_UI_PageSet(SEQ_UI_PAGE_TRGSEL);
1464
  } else {
524 tk 1465
    if( ui_page == SEQ_UI_PAGE_TRGSEL )
600 tk 1466
      SEQ_UI_PageSet(ui_trglayer_prev_page);
513 tk 1467
  }
1468
 
1469
  return 0; // no error
1470
}
1471
 
134 tk 1472
static s32 SEQ_UI_Button_TrgLayer(s32 depressed, u32 trg_layer)
1473
{
1117 tk 1474
  static u8 layer_c_pressed = 0;
784 tk 1475
 
134 tk 1476
  if( trg_layer >= 3 ) return -2; // max. 3 trglayer buttons
1477
 
326 tk 1478
  u8 visible_track = SEQ_UI_VisibleTrackGet();
1479
  u8 event_mode = SEQ_CC_Get(visible_track, SEQ_CC_MIDI_EVENT_MODE);
1480
  u8 num_t_layers = SEQ_TRG_NumLayersGet(visible_track);
134 tk 1481
 
1205 tk 1482
  // drum mode in edit page: ensure that trigger layer is print again
1483
  if( ui_page == SEQ_UI_PAGE_EDIT ) {
1484
    u8 event_mode = SEQ_CC_Get(visible_track, SEQ_CC_MIDI_EVENT_MODE);
1485
    if( event_mode == SEQ_EVENT_MODE_Drum ) {
1486
      if( !depressed )
1487
    ui_hold_msg_ctr = 0;
1488
    }
1489
  }
1490
 
784 tk 1491
  // holding Layer C button allows to increment/decrement layer with A/B button
1492
  if( trg_layer == 2 )
1493
    layer_c_pressed = !depressed;
1494
 
1495
  if( layer_c_pressed && trg_layer == 0 ) {
326 tk 1496
    if( depressed ) return -1; // ignore when button depressed
784 tk 1497
    // increment layer
1498
    if( ++ui_selected_trg_layer >= num_t_layers )
1499
      ui_selected_trg_layer = 0;
1500
  } else if( layer_c_pressed && trg_layer == 1 ) {
326 tk 1501
    if( depressed ) return -1; // ignore when button depressed
784 tk 1502
    // decrement layer
1503
    if( ui_selected_trg_layer == 0 )
1504
      ui_selected_trg_layer = num_t_layers - 1;
326 tk 1505
    else
784 tk 1506
      --ui_selected_trg_layer;
326 tk 1507
  } else {
784 tk 1508
    if( event_mode != SEQ_EVENT_MODE_Drum && num_t_layers <= 3 ) {
1509
      // 3 layers: direct selection with LayerA/B/C button
326 tk 1510
      if( depressed ) return -1; // ignore when button depressed
784 tk 1511
      if( trg_layer >= num_t_layers ) {
1512
    char str1[21];
1513
    sprintf(str1, "Trigger Layer %c", 'A'+trg_layer);
1514
    SEQ_UI_Msg(SEQ_UI_MSG_USER, 1000, str1, "not available!");
1515
      } else {
1516
    seq_ui_button_state.TRG_LAYER_SEL = 0;
1517
    ui_selected_trg_layer = trg_layer;
1518
      }
1519
    } else if( event_mode != SEQ_EVENT_MODE_Drum && num_t_layers <= 4 ) {
1520
      // 4 layers: LayerC Button toggles between C and D
1521
      if( depressed ) return -1; // ignore when button depressed
328 tk 1522
      seq_ui_button_state.TRG_LAYER_SEL = 0;
784 tk 1523
      if( trg_layer == 2 )
1524
    ui_selected_trg_layer = (ui_selected_trg_layer == 2) ? 3 : 2;
1525
      else
1526
    ui_selected_trg_layer = trg_layer;
326 tk 1527
    } else {
784 tk 1528
      // >4 layers or drum mode: LayerA/B button selects directly, Layer C button enters trigger selection page
1529
      // also used for drum tracks
1530
      if( trg_layer <= 1 ) {
1531
    if( depressed ) return -1; // ignore when button depressed
1532
    seq_ui_button_state.TRG_LAYER_SEL = 0;
1533
    ui_selected_trg_layer = trg_layer;
1534
      } else {
1535
    return SEQ_UI_Button_TrgLayerSel(depressed);
1536
      }
326 tk 1537
    }
1538
  }
1539
 
134 tk 1540
  return 0; // no error
1541
}
1542
 
1543
 
1119 tk 1544
static s32 SEQ_UI_Button_Mixer(s32 depressed)
544 tk 1545
{
1546
  if( depressed ) return -1; // ignore when button depressed
134 tk 1547
 
1119 tk 1548
  SEQ_UI_PageSet(SEQ_UI_PAGE_MIXER);
544 tk 1549
 
1550
  return 0; // no error
1551
}
1552
 
1119 tk 1553
static s32 SEQ_UI_Button_TrackMode(s32 depressed)
544 tk 1554
{
1555
  if( depressed ) return -1; // ignore when button depressed
1556
 
1119 tk 1557
  SEQ_UI_PageSet(SEQ_UI_PAGE_TRKMODE);
544 tk 1558
 
1559
  return 0; // no error
1560
}
1561
 
1119 tk 1562
static s32 SEQ_UI_Button_TrackGroove(s32 depressed)
544 tk 1563
{
1564
  if( depressed ) return -1; // ignore when button depressed
1565
 
1119 tk 1566
  SEQ_UI_PageSet(SEQ_UI_PAGE_TRKGRV);
1567
 
1568
  return 0; // no error
1569
}
1570
 
1571
static s32 SEQ_UI_Button_TrackLength(s32 depressed)
1572
{
1573
  if( depressed ) return -1; // ignore when button depressed
1574
 
1575
  SEQ_UI_PageSet(SEQ_UI_PAGE_TRKLEN);
1576
 
1577
  return 0; // no error
1578
}
1579
 
1580
static s32 SEQ_UI_Button_TrackDirection(s32 depressed)
1581
{
1582
  if( depressed ) return -1; // ignore when button depressed
1583
 
1584
  SEQ_UI_PageSet(SEQ_UI_PAGE_TRKDIR);
1585
 
1586
  return 0; // no error
1587
}
1588
 
1589
static s32 SEQ_UI_Button_TrackMorph(s32 depressed)
1590
{
1591
  if( depressed ) return -1; // ignore when button depressed
1592
 
1593
  SEQ_UI_PageSet(SEQ_UI_PAGE_TRKMORPH);
1594
 
1595
  return 0; // no error
1596
}
1597
 
1598
static s32 SEQ_UI_Button_TrackTranspose(s32 depressed)
1599
{
1600
  if( depressed ) return -1; // ignore when button depressed
1601
 
544 tk 1602
  SEQ_UI_PageSet(SEQ_UI_PAGE_TRKTRAN);
1603
 
1604
  return 0; // no error
1605
}
1606
 
1607
 
742 tk 1608
// only used by keyboard remote function
1609
static s32 SEQ_UI_Button_ToggleGate(s32 depressed)
1610
{
1611
  if( depressed ) return -1; // ignore when button depressed
544 tk 1612
 
742 tk 1613
  u8 visible_track = SEQ_UI_VisibleTrackGet();
1614
  u8 gate = SEQ_TRG_GateGet(visible_track, ui_selected_step, ui_selected_instrument) ? 0 : 1;
1615
  SEQ_TRG_GateSet(visible_track, ui_selected_step, ui_selected_instrument, gate);
544 tk 1616
 
742 tk 1617
  return 0; // no error
1618
}
1619
 
1620
 
1621
 
134 tk 1622
/////////////////////////////////////////////////////////////////////////////
1623
// Button handler
1624
/////////////////////////////////////////////////////////////////////////////
1625
s32 SEQ_UI_Button_Handler(u32 pin, u32 pin_value)
1626
{
492 tk 1627
  int i;
1628
 
625 tk 1629
  // send MIDI event in remote mode and exit
1316 tk 1630
  if( seq_midi_sysex_remote_active_mode == SEQ_MIDI_SYSEX_REMOTE_MODE_CLIENT )
625 tk 1631
    return SEQ_MIDI_SYSEX_REMOTE_Client_SendButton(pin, pin_value);
1632
 
1044 tk 1633
  // ignore as long as hardware config hasn't been read
496 tk 1634
  if( !SEQ_FILE_HW_ConfigLocked() )
1635
    return -1;
1636
 
740 tk 1637
  // ignore during a backup or format is created
1638
  if( seq_ui_backup_req || seq_ui_format_req )
634 tk 1639
    return -1;
1640
 
328 tk 1641
  // ensure that selections are matching with track constraints
1642
  SEQ_UI_CheckSelections();
1643
 
492 tk 1644
  // request display update
1645
  seq_ui_display_update_req = 1;
134 tk 1646
 
596 tk 1647
  // stop current message if (new) button has been pressed
1648
  if( pin_value == 0 )
1649
    SEQ_UI_MsgStop();
134 tk 1650
 
596 tk 1651
 
492 tk 1652
  // MEMO: we could also use a jump table with references to the functions
1653
  // here, but this "spagetthi code" simplifies the configuration and
1654
  // the resulting ASM doesn't look that bad!
168 tk 1655
 
492 tk 1656
  for(i=0; i<SEQ_HWCFG_NUM_GP; ++i)
1657
    if( pin == seq_hwcfg_button.gp[i] )
1658
      return SEQ_UI_Button_GP(pin_value, i);
134 tk 1659
 
492 tk 1660
  for(i=0; i<SEQ_HWCFG_NUM_TRACK; ++i)
1661
    if( pin == seq_hwcfg_button.track[i] )
1662
      return SEQ_UI_Button_Track(pin_value, i);
1146 tk 1663
 
1664
  for(i=0; i<SEQ_HWCFG_NUM_DIRECT_TRACK; ++i)
1665
    if( pin == seq_hwcfg_button.direct_track[i] )
1666
      return SEQ_UI_Button_DirectTrack(pin_value, i);
1667
 
1205 tk 1668
  for(i=0; i<SEQ_HWCFG_NUM_DIRECT_BOOKMARK; ++i)
1669
    if( pin == seq_hwcfg_button.direct_bookmark[i] )
1670
      return SEQ_UI_Button_DirectBookmark(pin_value, i);
1671
 
513 tk 1672
  if( pin == seq_hwcfg_button.track_sel )
1673
    return SEQ_UI_Button_TrackSel(pin_value);
134 tk 1674
 
492 tk 1675
  for(i=0; i<SEQ_HWCFG_NUM_GROUP; ++i)
1676
    if( pin == seq_hwcfg_button.group[i] )
1677
      return SEQ_UI_Button_Group(pin_value, i);
134 tk 1678
 
492 tk 1679
  for(i=0; i<SEQ_HWCFG_NUM_PAR_LAYER; ++i)
1680
    if( pin == seq_hwcfg_button.par_layer[i] )
1681
      return SEQ_UI_Button_ParLayer(pin_value, i);
513 tk 1682
  if( pin == seq_hwcfg_button.par_layer_sel )
1683
    return SEQ_UI_Button_ParLayerSel(pin_value);
134 tk 1684
 
492 tk 1685
  for(i=0; i<SEQ_HWCFG_NUM_TRG_LAYER; ++i)
1686
    if( pin == seq_hwcfg_button.trg_layer[i] )
1687
      return SEQ_UI_Button_TrgLayer(pin_value, i);
513 tk 1688
  if( pin == seq_hwcfg_button.trg_layer_sel )
1689
    return SEQ_UI_Button_TrgLayerSel(pin_value);
134 tk 1690
 
492 tk 1691
  if( pin == seq_hwcfg_button.left )
1692
    return SEQ_UI_Button_Left(pin_value);
1693
  if( pin == seq_hwcfg_button.right )
1694
    return SEQ_UI_Button_Right(pin_value);
1695
  if( pin == seq_hwcfg_button.down )
1696
    return SEQ_UI_Button_Down(pin_value);
1697
  if( pin == seq_hwcfg_button.up )
1698
    return SEQ_UI_Button_Up(pin_value);
134 tk 1699
 
492 tk 1700
  if( pin == seq_hwcfg_button.scrub )
1701
    return SEQ_UI_Button_Scrub(pin_value);
1702
  if( pin == seq_hwcfg_button.metronome )
1703
    return SEQ_UI_Button_Metronome(pin_value);
134 tk 1704
 
630 tk 1705
  if( pin == seq_hwcfg_button.record )
1706
    return SEQ_UI_Button_Record(pin_value);
1219 tk 1707
  if( pin == seq_hwcfg_button.live )
1708
    return SEQ_UI_Button_Live(pin_value);
630 tk 1709
 
492 tk 1710
  if( pin == seq_hwcfg_button.stop )
1711
    return SEQ_UI_Button_Stop(pin_value);
1712
  if( pin == seq_hwcfg_button.pause )
1713
    return SEQ_UI_Button_Pause(pin_value);
1714
  if( pin == seq_hwcfg_button.play )
1715
    return SEQ_UI_Button_Play(pin_value);
1716
  if( pin == seq_hwcfg_button.rew )
1717
    return SEQ_UI_Button_Rew(pin_value);
1718
  if( pin == seq_hwcfg_button.fwd )
1719
    return SEQ_UI_Button_Fwd(pin_value);
596 tk 1720
  if( pin == seq_hwcfg_button.loop )
1721
    return SEQ_UI_Button_Loop(pin_value);
973 tk 1722
  if( pin == seq_hwcfg_button.follow )
1723
    return SEQ_UI_Button_Follow(pin_value);
134 tk 1724
 
492 tk 1725
  if( pin == seq_hwcfg_button.utility )
1726
    return SEQ_UI_Button_Utility(pin_value);
1727
  if( pin == seq_hwcfg_button.copy )
1728
    return SEQ_UI_Button_Copy(pin_value);
1729
  if( pin == seq_hwcfg_button.paste )
1730
    return SEQ_UI_Button_Paste(pin_value);
1731
  if( pin == seq_hwcfg_button.clear )
1732
    return SEQ_UI_Button_Clear(pin_value);
1014 tk 1733
  if( pin == seq_hwcfg_button.undo )
1734
    return SEQ_UI_Button_Undo(pin_value);
134 tk 1735
 
492 tk 1736
  if( pin == seq_hwcfg_button.menu )
1737
    return SEQ_UI_Button_Menu(pin_value);
1203 tk 1738
  if( pin == seq_hwcfg_button.bookmark )
1739
    return SEQ_UI_Button_Bookmark(pin_value);
492 tk 1740
  if( pin == seq_hwcfg_button.select )
1741
    return SEQ_UI_Button_Select(pin_value);
1742
  if( pin == seq_hwcfg_button.exit )
1743
    return SEQ_UI_Button_Exit(pin_value);
134 tk 1744
 
513 tk 1745
  if( pin == seq_hwcfg_button.tap_tempo )
1746
    return SEQ_UI_Button_TapTempo(pin_value);
1747
  if( pin == seq_hwcfg_button.tempo_preset )
1748
    return SEQ_UI_Button_TempoPreset(pin_value);
524 tk 1749
  if( pin == seq_hwcfg_button.ext_restart )
1750
    return SEQ_UI_Button_ExtRestart(pin_value);
134 tk 1751
 
492 tk 1752
  if( pin == seq_hwcfg_button.edit )
1753
    return SEQ_UI_Button_Edit(pin_value);
1754
  if( pin == seq_hwcfg_button.mute )
1755
    return SEQ_UI_Button_Mute(pin_value);
1756
  if( pin == seq_hwcfg_button.pattern )
1757
    return SEQ_UI_Button_Pattern(pin_value);
1758
  if( pin == seq_hwcfg_button.song )
1759
    return SEQ_UI_Button_Song(pin_value);
134 tk 1760
 
492 tk 1761
  if( pin == seq_hwcfg_button.solo )
1762
    return SEQ_UI_Button_Solo(pin_value);
1763
  if( pin == seq_hwcfg_button.fast )
1764
    return SEQ_UI_Button_Fast(pin_value);
1121 tk 1765
  if( pin == seq_hwcfg_button.fast2 )
1766
    return SEQ_UI_Button_Fast2(pin_value);
492 tk 1767
  if( pin == seq_hwcfg_button.all )
1768
    return SEQ_UI_Button_All(pin_value);
134 tk 1769
 
492 tk 1770
  if( pin == seq_hwcfg_button.step_view )
1771
    return SEQ_UI_Button_StepView(pin_value);
134 tk 1772
 
544 tk 1773
  if( pin == seq_hwcfg_button.mixer )
1774
    return SEQ_UI_Button_Mixer(pin_value);
1775
 
1119 tk 1776
  if( pin == seq_hwcfg_button.track_mode )
1777
    return SEQ_UI_Button_TrackMode(pin_value);
1778
  if( pin == seq_hwcfg_button.track_groove )
1779
    return SEQ_UI_Button_TrackGroove(pin_value);
1780
  if( pin == seq_hwcfg_button.track_length )
1781
    return SEQ_UI_Button_TrackLength(pin_value);
1782
  if( pin == seq_hwcfg_button.track_direction )
1783
    return SEQ_UI_Button_TrackDirection(pin_value);
1784
  if( pin == seq_hwcfg_button.track_morph )
1785
    return SEQ_UI_Button_TrackMorph(pin_value);
1786
  if( pin == seq_hwcfg_button.track_transpose )
1787
    return SEQ_UI_Button_TrackTranspose(pin_value);
1788
 
625 tk 1789
  // always print debugging message
1790
#if 1
1081 tk 1791
  MUTEX_MIDIOUT_TAKE;
1792
  DEBUG_MSG("[SEQ_UI_Button_Handler] Button SR:%d, Pin:%d not mapped, it has been %s.\n",
1793
        (pin >> 3) + 1,
1794
        pin & 7,
1795
        pin_value ? "depressed" : "pressed");
1796
  MUTEX_MIDIOUT_GIVE;
625 tk 1797
#endif
1798
 
492 tk 1799
  return -1; // button not mapped
134 tk 1800
}
1801
 
1802
 
1803
/////////////////////////////////////////////////////////////////////////////
524 tk 1804
// BLM Button handler
1805
/////////////////////////////////////////////////////////////////////////////
1806
s32 SEQ_UI_BLM_Button_Handler(u32 row, u32 pin, u32 pin_value)
1807
{
625 tk 1808
  // send MIDI event in remote mode and exit
1316 tk 1809
  if( seq_midi_sysex_remote_active_mode == SEQ_MIDI_SYSEX_REMOTE_MODE_CLIENT )
625 tk 1810
    return SEQ_MIDI_SYSEX_REMOTE_Client_Send_BLM_Button(row, pin, pin_value);
1811
 
1044 tk 1812
  // ignore as long as hardware config hasn't been read
524 tk 1813
  if( !SEQ_FILE_HW_ConfigLocked() )
1814
    return -1;
1815
 
740 tk 1816
  // ignore during a backup or format is created
1817
  if( seq_ui_backup_req || seq_ui_format_req )
634 tk 1818
    return -1;
1819
 
524 tk 1820
  if( row >= SEQ_CORE_NUM_TRACKS_PER_GROUP )
1821
    return -1; // more than 4 tracks not supported (yet) - could be done in this function w/o much effort
1822
 
1823
  if( pin >= 16 )
1824
    return -1; // more than 16 step buttons not supported (yet) - could be done by selecting the step view
1825
 
1826
  // select track depending on row
1827
  ui_selected_tracks = 1 << (row + 4*ui_selected_group);
1828
 
1829
  // ensure that selections are matching with track constraints
1830
  SEQ_UI_CheckSelections();
1831
 
1832
  // request display update
1833
  seq_ui_display_update_req = 1;
1834
 
1835
  // emulate general purpose button
758 tk 1836
  if( seq_hwcfg_blm.buttons_no_ui ) {
763 tk 1837
    s32 status = SEQ_UI_EDIT_Button_Handler(pin, pin_value);
758 tk 1838
    ui_cursor_flash_ctr = ui_cursor_flash_overrun_ctr = 0;
1839
    return status;
763 tk 1840
  }
1841
 
1842
  return SEQ_UI_Button_GP(pin_value, pin); // no error, pin_value and pin are swapped for this function due to consistency reasons
524 tk 1843
}
1844
 
1845
 
1846
/////////////////////////////////////////////////////////////////////////////
134 tk 1847
// Encoder handler
1848
/////////////////////////////////////////////////////////////////////////////
1849
s32 SEQ_UI_Encoder_Handler(u32 encoder, s32 incrementer)
1850
{
625 tk 1851
  // send MIDI event in remote mode and exit
1316 tk 1852
  if( seq_midi_sysex_remote_active_mode == SEQ_MIDI_SYSEX_REMOTE_MODE_CLIENT )
625 tk 1853
    return SEQ_MIDI_SYSEX_REMOTE_Client_SendEncoder(encoder, incrementer);
1854
 
1044 tk 1855
  // ignore as long as hardware config hasn't been read
496 tk 1856
  if( !SEQ_FILE_HW_ConfigLocked() )
1857
    return -1;
1858
 
740 tk 1859
  // ignore during a backup or format is created
1860
  if( seq_ui_backup_req || seq_ui_format_req )
634 tk 1861
    return -1;
1862
 
134 tk 1863
  if( encoder > 16 )
1864
    return -1; // encoder doesn't exist
1865
 
328 tk 1866
  // ensure that selections are matching with track constraints
1867
  SEQ_UI_CheckSelections();
1868
 
596 tk 1869
  // stop current message
1870
  SEQ_UI_MsgStop();
1871
 
134 tk 1872
  // limit incrementer
1873
  if( incrementer > 3 )
1874
    incrementer = 3;
1875
  else if( incrementer < -3 )
1876
    incrementer = -3;
1877
 
607 tk 1878
  if( seq_ui_button_state.SCRUB && encoder == 0 ) {
1879
    // if sequencer isn't already running, continue it (don't restart)
1880
    if( !SEQ_BPM_IsRunning() )
1881
      SEQ_BPM_Cont();
1882
    ui_seq_pause = 0; // clear pause mode
1278 tk 1883
 
607 tk 1884
    // Scrub sequence back or forth
1885
    portENTER_CRITICAL(); // should be atomic
1886
    SEQ_CORE_Scrub(incrementer);
1887
    portEXIT_CRITICAL();
1888
  } else if( !seq_ui_button_state.MENU_PRESSED && ui_encoder_callback != NULL ) {
173 tk 1889
    ui_encoder_callback((encoder == 0) ? SEQ_UI_ENCODER_Datawheel : (encoder-1), incrementer);
740 tk 1890
    ui_cursor_flash_ctr = ui_cursor_flash_overrun_ctr = 0; // ensure that value is visible when it has been changed
134 tk 1891
  }
1892
 
1893
  // request display update
159 tk 1894
  seq_ui_display_update_req = 1;
134 tk 1895
 
1896
  return 0; // no error
1897
}
1898
 
1899
 
353 tk 1900
 
134 tk 1901
/////////////////////////////////////////////////////////////////////////////
626 tk 1902
// Receives a MIDI package from APP_NotifyReceivedEvent (-> app.c)
1903
/////////////////////////////////////////////////////////////////////////////
1904
s32 SEQ_UI_REMOTE_MIDI_Receive(mios32_midi_port_t port, mios32_midi_package_t midi_package)
1905
{
1906
#if 1
1907
  // check for active remote mode
1316 tk 1908
  if( seq_midi_sysex_remote_active_mode != SEQ_MIDI_SYSEX_REMOTE_MODE_SERVER )
626 tk 1909
    return 0; // no error
1910
#endif
1911
 
1316 tk 1912
  if( (seq_midi_sysex_remote_port == DEFAULT && seq_midi_sysex_remote_active_port != port) ||
1913
      (seq_midi_sysex_remote_port != DEFAULT && port != seq_midi_sysex_remote_port) )
626 tk 1914
    return 0; // wrong port
1915
 
1916
  // for easier parsing: convert Note Off -> Note On with velocity 0
1917
  if( midi_package.event == NoteOff ) {
1918
    midi_package.event = NoteOn;
1919
    midi_package.velocity = 0;
1920
  }
1921
 
1922
  switch( midi_package.event ) {
1923
    case NoteOn: {
1924
      switch( midi_package.chn ) {
1925
        case Chn1:
1926
      SEQ_UI_Button_Handler(midi_package.note + 0x00, midi_package.velocity ? 0 : 1);
1927
      break;
1928
        case Chn2:
1929
      SEQ_UI_Button_Handler(midi_package.note + 0x80, midi_package.velocity ? 0 : 1);
1930
      break;
1931
        case Chn3:
1932
      SEQ_UI_BLM_Button_Handler(midi_package.note >> 5, midi_package.note & 0x1f, midi_package.velocity ? 0 : 1);
1933
      break;
1934
      }
1935
    } break;
1936
 
1937
    case CC: {
1938
      if( midi_package.cc_number >= 15 && midi_package.cc_number <= 31 )
1939
    SEQ_UI_Encoder_Handler(midi_package.cc_number-15, (int)midi_package.value - 0x40);
1940
    } break;
1941
  }
1942
 
632 tk 1943
  return 1; // MIDI event has been taken for remote function -> don't forward to router/MIDI event parser
626 tk 1944
}
1945
 
1946
 
1947
/////////////////////////////////////////////////////////////////////////////
741 tk 1948
// MIDI Remote Keyboard Function (called from SEQ_MIDI_IN)
1949
/////////////////////////////////////////////////////////////////////////////
742 tk 1950
s32 SEQ_UI_REMOTE_MIDI_Keyboard(u8 key, u8 depressed)
741 tk 1951
{
742 tk 1952
#if 0
1316 tk 1953
  MIOS32_MIDI_SendDebugMessage("SEQ_MIDI_SYSEX_REMOTE_MIDI_Keyboard(%d, %d)\n", key, depressed);
741 tk 1954
#endif
742 tk 1955
 
1956
  switch( key ) {
1957
    case 0x24: // C-2
1958
      return SEQ_UI_Button_GP(depressed, 0);
1959
    case 0x25: // C#2
1960
      return SEQ_UI_Button_Track(depressed, 0);
1961
    case 0x26: // D-2
1962
      return SEQ_UI_Button_GP(depressed, 1);
1963
    case 0x27: // D#2
1964
      return SEQ_UI_Button_Track(depressed, 1);
1965
    case 0x28: // E-2
1966
      return SEQ_UI_Button_GP(depressed, 2);
1967
    case 0x29: // F-2
1968
      return SEQ_UI_Button_GP(depressed, 3);
1969
    case 0x2a: // F#2
1970
      return SEQ_UI_Button_Track(depressed, 2);
1971
    case 0x2b: // G-2
1972
      return SEQ_UI_Button_GP(depressed, 4);
1973
    case 0x2c: // G#2
1974
      return SEQ_UI_Button_Track(depressed, 3);
1975
    case 0x2d: // A-2
1976
      return SEQ_UI_Button_GP(depressed, 5);
1977
    case 0x2e: // A#2
1978
      return SEQ_UI_Button_ParLayer(depressed, 0);
1979
    case 0x2f: // B-2
1980
      return SEQ_UI_Button_GP(depressed, 6);
1981
 
1982
    case 0x30: // C-3
1983
      return SEQ_UI_Button_GP(depressed, 7);
1984
    case 0x31: // C#3
1985
      return SEQ_UI_Button_ParLayer(depressed, 1);
1986
    case 0x32: // D-3
1987
      return SEQ_UI_Button_GP(depressed, 8);
1988
    case 0x33: // D#3
1989
      return SEQ_UI_Button_ParLayer(depressed, 2);
1990
    case 0x34: // E-3
1991
      return SEQ_UI_Button_GP(depressed, 9);
1992
    case 0x35: // F-3
1993
      return SEQ_UI_Button_GP(depressed, 10);
1994
    case 0x36: // F#3
1995
      return SEQ_UI_Button_TrgLayer(depressed, 0);
1996
    case 0x37: // G-3
1997
      return SEQ_UI_Button_GP(depressed, 11);
1998
    case 0x38: // G#3
1999
      return SEQ_UI_Button_TrgLayer(depressed, 1);
2000
    case 0x39: // A-3
2001
      return SEQ_UI_Button_GP(depressed, 12);
2002
    case 0x3a: // A#3
2003
      return SEQ_UI_Button_TrgLayer(depressed, 2);
2004
    case 0x3b: // B-3
2005
      return SEQ_UI_Button_GP(depressed, 13);
2006
 
2007
    case 0x3c: // C-4
2008
      return SEQ_UI_Button_GP(depressed, 14);
2009
    case 0x3d: // C#4
2010
      return SEQ_UI_Button_Group(depressed, 0);
2011
    case 0x3e: // D-4
2012
      return SEQ_UI_Button_GP(depressed, 15);
2013
    case 0x3f: // D#4
2014
      return SEQ_UI_Button_Group(depressed, 1);
2015
    case 0x40: // E-4
2016
      return 0; // ignore
2017
    case 0x41: // F-4
2018
      return SEQ_UI_Button_StepView(depressed);
2019
    case 0x42: // F#4
2020
      return SEQ_UI_Button_Group(depressed, 1);
2021
    case 0x43: // G-4
2022
      return 0; // ignore
2023
    case 0x44: // G#4
2024
      return SEQ_UI_Button_Group(depressed, 2);
2025
    case 0x45: // A-4
2026
      return SEQ_UI_Button_Left(depressed);
2027
    case 0x46: // A#4
2028
      return SEQ_UI_Button_ToggleGate(depressed);
2029
    case 0x47: // B-4
2030
      return SEQ_UI_Button_Right(depressed);
2031
 
2032
    case 0x48: // C-5
2033
      return SEQ_UI_Button_Edit(depressed);
2034
    case 0x49: // C#5
2035
      return SEQ_UI_Button_Solo(depressed);
2036
    case 0x4a: // D-5
2037
      return SEQ_UI_Button_Mute(depressed);
2038
    case 0x4b: // D#5
2039
      return SEQ_UI_Button_All(depressed);
2040
    case 0x4c: // E-5
2041
      return SEQ_UI_Button_Pattern(depressed);
2042
    case 0x4d: // F-5
2043
      return SEQ_UI_Button_Song(depressed);
2044
    case 0x4e: // F#5
2045
      return SEQ_UI_Button_Fast(depressed);
2046
    case 0x4f: // G-5
2047
      return SEQ_UI_Button_Metronome(depressed);
2048
    case 0x50: // G#5
2049
      return SEQ_UI_Button_ExtRestart(depressed);
2050
    case 0x51: // A-5
2051
      return SEQ_UI_Button_ParLayerSel(depressed);
2052
    case 0x52: // A#5
2053
      return SEQ_UI_Button_TrackSel(depressed);
2054
    case 0x53: // B-5
2055
      return SEQ_UI_Button_Stop(depressed);
2056
 
2057
    case 0x54: // C-6
2058
      return SEQ_UI_Button_Play(depressed);
2059
    case 0x55: // C#6
2060
      return SEQ_UI_Button_Pause(depressed);
2061
    case 0x56: // D-6
2062
      return SEQ_UI_Button_Rew(depressed);
2063
    case 0x57: // D#6
2064
      return SEQ_UI_Button_Fwd(depressed);
2065
    case 0x58: // E-6
2066
      return SEQ_UI_Button_Utility(depressed);
2067
    case 0x59: // F-6
2068
      return SEQ_UI_Button_TempoPreset(depressed);
2069
    case 0x5a: // F#6
2070
      return 0; // ignore
2071
    case 0x5b: // G-6
2072
      return SEQ_UI_Button_Menu(depressed);
2073
    case 0x5c: // G#6
2074
      return SEQ_UI_Button_Select(depressed);
2075
    case 0x5d: // A-6
2076
      return SEQ_UI_Button_Exit(depressed);
2077
    case 0x5e: // A#6
2078
      return SEQ_UI_Button_Down(depressed);
2079
    case 0x5f: // B-6
2080
      return SEQ_UI_Button_Up(depressed);
2081
  }
2082
 
741 tk 2083
  return 0; // no error
2084
}
2085
 
2086
 
2087
/////////////////////////////////////////////////////////////////////////////
134 tk 2088
// Update LCD messages
2089
// Usually called from background task
2090
/////////////////////////////////////////////////////////////////////////////
2091
s32 SEQ_UI_LCD_Handler(void)
2092
{
728 tk 2093
  static u8 boot_animation_wait_ctr = 0;
2094
  static u8 boot_animation_lcd_pos = 0;
2095
 
625 tk 2096
  // special handling in remote client mode
1316 tk 2097
  if( seq_midi_sysex_remote_active_mode == SEQ_MIDI_SYSEX_REMOTE_MODE_CLIENT )
625 tk 2098
    return SEQ_UI_LCD_Update();
2099
 
159 tk 2100
  if( seq_ui_display_init_req ) {
2101
    seq_ui_display_init_req = 0; // clear request
134 tk 2102
 
278 tk 2103
    // clear force update of LCD
2104
    SEQ_LCD_Clear();
2105
    SEQ_LCD_Update(1);
134 tk 2106
 
168 tk 2107
    // select first menu item
2108
    ui_selected_item = 0;
2109
 
167 tk 2110
    // call init function of current page
272 tk 2111
    if( ui_menu_pages[ui_page].init_callback != NULL )
2112
      ui_menu_pages[ui_page].init_callback(0); // mode
134 tk 2113
 
2114
    // request display update
159 tk 2115
    seq_ui_display_update_req = 1;
134 tk 2116
  }
2117
 
1044 tk 2118
  // print boot screen as long as hardware config hasn't been read
496 tk 2119
  if( !SEQ_FILE_HW_ConfigLocked() ) {
728 tk 2120
    if( boot_animation_lcd_pos < (40-3) ) {
2121
      if( ++boot_animation_wait_ctr >= 75 ) {
2122
    boot_animation_wait_ctr = 0;
637 tk 2123
 
728 tk 2124
    if( boot_animation_lcd_pos == 0 ) {
2125
      SEQ_LCD_Clear();
2126
      SEQ_LCD_CursorSet(0, 0);
2127
      SEQ_LCD_PrintString(MIOS32_LCD_BOOT_MSG_LINE1 " " MIOS32_LCD_BOOT_MSG_LINE2);
2128
      SEQ_LCD_CursorSet(0, 1);
2129
      SEQ_LCD_PrintString("Searching for SD Card...");
2130
    }
2131
 
2132
    // logo is print on second LCD
2133
    SEQ_LCD_LOGO_Print(boot_animation_lcd_pos++);
2134
      }
2135
    }
740 tk 2136
  } else if( seq_ui_backup_req || seq_ui_format_req ) {
634 tk 2137
    SEQ_LCD_Clear();
2138
    SEQ_LCD_CursorSet(0, 0);
740 tk 2139
    //                     <-------------------------------------->
2140
    //                     0123456789012345678901234567890123456789
2141
    if( seq_ui_backup_req )
959 tk 2142
      SEQ_LCD_PrintString("Copy Files - be patient!!!");
740 tk 2143
    else if( seq_ui_format_req )
959 tk 2144
      SEQ_LCD_PrintString("Creating Files - be patient!!!");
740 tk 2145
    else
2146
      SEQ_LCD_PrintString("Don't know what I'm doing! :-/");
637 tk 2147
 
2148
    if( seq_file_backup_notification != NULL ) {
2149
      int i;
2150
 
2151
      SEQ_LCD_CursorSet(0, 1);
959 tk 2152
      SEQ_LCD_PrintFormattedString("Creating %s", seq_file_backup_notification);
637 tk 2153
 
2154
      SEQ_LCD_CursorSet(40+3, 0);
2155
      SEQ_LCD_PrintString("Total: [");
2156
      for(i=0; i<20; ++i)
2157
    SEQ_LCD_PrintChar((i>(seq_file_backup_percentage/5)) ? ' ' : '#');
2158
      SEQ_LCD_PrintFormattedString("] %3d%%", seq_file_backup_percentage);
2159
 
2160
      SEQ_LCD_CursorSet(40+3, 1);
2161
      SEQ_LCD_PrintString("File:  [");
2162
      for(i=0; i<20; ++i)
1261 tk 2163
    SEQ_LCD_PrintChar((i>(file_copy_percentage/5)) ? ' ' : '#');
2164
      SEQ_LCD_PrintFormattedString("] %3d%%", file_copy_percentage);
637 tk 2165
    }
2166
 
496 tk 2167
  } else if( seq_ui_button_state.MENU_PRESSED && !seq_ui_button_state.MENU_FIRST_PAGE_SELECTED ) {
2168
    SEQ_LCD_CursorSet(0, 0);
2169
    //                   <-------------------------------------->
2170
    //                   0123456789012345678901234567890123456789
306 tk 2171
    SEQ_LCD_PrintString("Menu Shortcuts:");
2172
    SEQ_LCD_PrintSpaces(25 + 40);
2173
    SEQ_LCD_CursorSet(0, 1);
2174
    SEQ_LCD_PrintString(UI_SHORTCUT_STR); // defined in seq_ui_pages.inc
2175
  } else {
2176
    // perform high priority LCD update request
2177
    if( ui_lcd_callback != NULL )
2178
      ui_lcd_callback(1); // high_prio
167 tk 2179
 
306 tk 2180
    // perform low priority LCD update request if requested
2181
    if( seq_ui_display_update_req ) {
2182
      seq_ui_display_update_req = 0; // clear request
328 tk 2183
 
2184
      // ensure that selections are matching with track constraints
2185
      SEQ_UI_CheckSelections();
2186
 
306 tk 2187
      if( ui_lcd_callback != NULL )
2188
    ui_lcd_callback(0); // no high_prio
2189
    }
134 tk 2190
  }
2191
 
353 tk 2192
  // transfer all changed characters to LCD
2193
  SEQ_UI_LCD_Update();
2194
 
2195
  return 0; // no error
2196
}
2197
 
2198
 
2199
/////////////////////////////////////////////////////////////////////////////
2200
// Called from SEQ_UI_LCD_Handler(), but optionally also from other tasks
2201
// to update the LCD screen immediately
2202
/////////////////////////////////////////////////////////////////////////////
1117 tk 2203
// for newer GCC versions it's important to declare constant arrays outside a function
2204
//                                             00112233
2205
static const char animation_l_arrows[2*4+1] = "   >>>> ";
2206
//                                             00112233
2207
static const char animation_r_arrows[2*4+1] = "  < << <";
2208
//                                               00112233
2209
static const char animation_l_brackets[2*4+1] = "   )))) ";
2210
//                                               00112233
2211
static const char animation_r_brackets[2*4+1] = "  ( (( (";
2212
//                                            00112233
2213
static const char animation_l_stars[2*4+1] = "   **** ";
2214
//                                            00112233
2215
static const char animation_r_stars[2*4+1] = "  * ** *";
353 tk 2216
s32 SEQ_UI_LCD_Update(void)
2217
{
625 tk 2218
  // special handling in remote client mode
1316 tk 2219
  if( seq_midi_sysex_remote_active_mode == SEQ_MIDI_SYSEX_REMOTE_MODE_CLIENT ) {
626 tk 2220
    MIOS32_IRQ_Disable();
1316 tk 2221
    u8 force = seq_midi_sysex_remote_force_lcd_update;
2222
    seq_midi_sysex_remote_force_lcd_update = 0;
626 tk 2223
    MIOS32_IRQ_Enable();
2224
    return SEQ_LCD_Update(force);
625 tk 2225
  }
2226
 
596 tk 2227
  // if UI message active: copy over the text
2228
  if( ui_msg_ctr ) {
774 tk 2229
    char *animation_l_ptr;
2230
    char *animation_r_ptr;
596 tk 2231
    u8 msg_x = 0;
2232
    u8 right_aligned = 0;
740 tk 2233
    u8 disable_message = 0;
299 tk 2234
 
596 tk 2235
    switch( ui_msg_type ) {
2236
      case SEQ_UI_MSG_SDCARD: {
1117 tk 2237
    animation_l_ptr = (char *)animation_l_arrows;
2238
    animation_r_ptr = (char *)animation_r_arrows;
596 tk 2239
    msg_x = 0; // MEMO: print such important information at first LCD for the case the user hasn't connected the second LCD yet
2240
    right_aligned = 0;
2241
      } break;
2242
 
756 tk 2243
      case SEQ_UI_MSG_DELAYED_ACTION:
2244
      case SEQ_UI_MSG_DELAYED_ACTION_R: {
1117 tk 2245
    animation_l_ptr = (char *)animation_l_brackets;
2246
    animation_r_ptr = (char *)animation_r_brackets;
756 tk 2247
    if( ui_msg_type == SEQ_UI_MSG_DELAYED_ACTION_R ) {
2248
      msg_x = 40; // right LCD
2249
      right_aligned = 0;
2250
    } else {
2251
      msg_x = 39; // left LCD
2252
      right_aligned = 1;
2253
    }
740 tk 2254
 
2255
    if( ui_delayed_action_callback == NULL ) {
2256
      disable_message = 1; // button has been depressed before delay
2257
    } else {
2258
      int seconds = (ui_delayed_action_ctr / 1000) + 1;
2259
      if( seconds == 1 )
2260
        sprintf(ui_msg[0], "Hold for 1 second ");
2261
      else
2262
        sprintf(ui_msg[0], "Hold for %d seconds", seconds);
2263
    }
2264
      } break;
2265
 
741 tk 2266
      case SEQ_UI_MSG_USER_R: {
1117 tk 2267
    animation_l_ptr = (char *)animation_l_stars;
2268
    animation_r_ptr = (char *)animation_r_stars;
741 tk 2269
    msg_x = 40; // right display
2270
    right_aligned = 0;
2271
      } break;
2272
 
596 tk 2273
      default: {
1117 tk 2274
    animation_l_ptr = (char *)animation_l_stars;
2275
    animation_r_ptr = (char *)animation_r_stars;
596 tk 2276
    msg_x = 39;
2277
    right_aligned = 1;
2278
      } break;
2279
 
2280
    }
2281
 
740 tk 2282
    if( !disable_message ) {
2283
      int anum = (ui_msg_ctr % 1000) / 250;
596 tk 2284
 
740 tk 2285
      int len[2];
2286
      len[0] = strlen((char *)ui_msg[0]);
2287
      len[1] = strlen((char *)ui_msg[1]);
2288
      int len_max = len[0];
2289
      if( len[1] > len_max )
2290
    len_max = len[1];
596 tk 2291
 
740 tk 2292
      if( right_aligned )
2293
    msg_x -= (9 + len_max);
596 tk 2294
 
740 tk 2295
      int line;
2296
      for(line=0; line<2; ++line) {
2297
    SEQ_LCD_CursorSet(msg_x, line);
596 tk 2298
 
740 tk 2299
    // ensure that both lines are padded with same number of spaces
2300
    int end_pos = len[line];
2301
    while( end_pos < len_max )
2302
      ui_msg[line][end_pos++] = ' ';
2303
    ui_msg[line][end_pos] = 0;
2304
 
2305
    SEQ_LCD_PrintFormattedString(" %c%c| %s |%c%c ",
2306
                     *(animation_l_ptr + 2*anum + 0), *(animation_l_ptr + 2*anum + 1),
2307
                     (char *)ui_msg[line],
2308
                     *(animation_r_ptr + 2*anum + 0), *(animation_r_ptr + 2*anum + 1));
2309
      }
299 tk 2310
    }
2311
  }
2312
 
637 tk 2313
  // MSD USB notification at right corner if not in Disk page
2314
  // to warn user that USB MIDI is disabled and seq performance is bad now!
638 tk 2315
  if( (TASK_MSD_EnableGet() > 0) && ui_page != SEQ_UI_PAGE_DISK ) {
637 tk 2316
    SEQ_LCD_CursorSet(80-11, 0);
2317
    if( ui_cursor_flash ) SEQ_LCD_PrintSpaces(13); else SEQ_LCD_PrintString(" [MSD USB] ");
2318
    SEQ_LCD_CursorSet(80-11, 1);
2319
    char str[5];
2320
    TASK_MSD_FlagStrGet(str);
2321
    if( ui_cursor_flash ) SEQ_LCD_PrintSpaces(13); else SEQ_LCD_PrintFormattedString(" [ %s  ] ", str);
2322
  }
596 tk 2323
 
278 tk 2324
  // transfer all changed characters to LCD
353 tk 2325
  // SEQ_LCD_Update provides a MUTEX handling to allow updates from different tasks
2326
  return SEQ_LCD_Update(0);
134 tk 2327
}
2328
 
2329
 
2330
/////////////////////////////////////////////////////////////////////////////
2331
// Update all LEDs
2332
// Usually called from background task
2333
/////////////////////////////////////////////////////////////////////////////
2334
s32 SEQ_UI_LED_Handler(void)
2335
{
626 tk 2336
  static u8 remote_led_sr[SEQ_LED_NUM_SR];
2337
 
625 tk 2338
  // ignore in remote client mode
1316 tk 2339
  if( seq_midi_sysex_remote_active_mode == SEQ_MIDI_SYSEX_REMOTE_MODE_CLIENT )
625 tk 2340
    return 0; // no error
2341
 
1044 tk 2342
  // ignore as long as hardware config hasn't been read
496 tk 2343
  if( !SEQ_FILE_HW_ConfigLocked() )
2344
    return -1;
2345
 
134 tk 2346
  // track LEDs
987 tk 2347
  // in pattern page: track buttons are used as group buttons
2348
  if( ui_page == SEQ_UI_PAGE_PATTERN ) {
2349
    SEQ_LED_PinSet(seq_hwcfg_led.track[0], (ui_selected_group == 0));
2350
    SEQ_LED_PinSet(seq_hwcfg_led.track[1], (ui_selected_group == 1));
2351
    SEQ_LED_PinSet(seq_hwcfg_led.track[2], (ui_selected_group == 2));
2352
    SEQ_LED_PinSet(seq_hwcfg_led.track[3], (ui_selected_group == 3));
2353
  } else if( ui_page == SEQ_UI_PAGE_SONG ) {
2354
    // in song page: track and group buttons are used to select the cursor position
2355
    SEQ_LED_PinSet(seq_hwcfg_led.track[0], (ui_selected_item == 3));
2356
    SEQ_LED_PinSet(seq_hwcfg_led.track[1], (ui_selected_item == 4));
2357
    SEQ_LED_PinSet(seq_hwcfg_led.track[2], (ui_selected_item == 5));
2358
    SEQ_LED_PinSet(seq_hwcfg_led.track[3], (ui_selected_item == 6));
2359
  } else {
2360
    u8 selected_tracks = ui_selected_tracks >> (4*ui_selected_group);
2361
    SEQ_LED_PinSet(seq_hwcfg_led.track[0], (selected_tracks & (1 << 0)));
2362
    SEQ_LED_PinSet(seq_hwcfg_led.track[1], (selected_tracks & (1 << 1)));
2363
    SEQ_LED_PinSet(seq_hwcfg_led.track[2], (selected_tracks & (1 << 2)));
2364
    SEQ_LED_PinSet(seq_hwcfg_led.track[3], (selected_tracks & (1 << 3)));
2365
  }
2366
 
678 tk 2367
  SEQ_LED_PinSet(seq_hwcfg_led.track_sel, ui_page == SEQ_UI_PAGE_TRACKSEL);
134 tk 2368
 
2369
  // parameter layer LEDs
987 tk 2370
  // in song page: layer buttons are used to select the cursor position
2371
  if( ui_page == SEQ_UI_PAGE_SONG ) {
2372
    SEQ_LED_PinSet(seq_hwcfg_led.par_layer[0], ui_selected_item == 0);
2373
    SEQ_LED_PinSet(seq_hwcfg_led.par_layer[1], ui_selected_item == 1);
2374
    SEQ_LED_PinSet(seq_hwcfg_led.par_layer[2], ui_selected_item == 2);
2375
  } else {
2376
    SEQ_LED_PinSet(seq_hwcfg_led.par_layer[0], (ui_selected_par_layer == 0));
2377
    SEQ_LED_PinSet(seq_hwcfg_led.par_layer[1], (ui_selected_par_layer == 1));
2378
    SEQ_LED_PinSet(seq_hwcfg_led.par_layer[2], (ui_selected_par_layer >= 2) || seq_ui_button_state.PAR_LAYER_SEL);
2379
  }
678 tk 2380
  SEQ_LED_PinSet(seq_hwcfg_led.par_layer_sel, ui_page == SEQ_UI_PAGE_PARSEL);
134 tk 2381
 
2382
  // group LEDs
987 tk 2383
  // in song page: track and group buttons are used to select the cursor position
2384
  if( ui_page == SEQ_UI_PAGE_SONG ) {
2385
    SEQ_LED_PinSet(seq_hwcfg_led.group[0], (ui_selected_item == 3));
2386
    SEQ_LED_PinSet(seq_hwcfg_led.group[1], (ui_selected_item == 4));
2387
    SEQ_LED_PinSet(seq_hwcfg_led.group[2], (ui_selected_item == 5));
2388
    SEQ_LED_PinSet(seq_hwcfg_led.group[3], (ui_selected_item == 6));
2389
  } else {
2390
    SEQ_LED_PinSet(seq_hwcfg_led.group[0], (ui_selected_group == 0));
2391
    SEQ_LED_PinSet(seq_hwcfg_led.group[1], (ui_selected_group == 1));
2392
    SEQ_LED_PinSet(seq_hwcfg_led.group[2], (ui_selected_group == 2));
2393
    SEQ_LED_PinSet(seq_hwcfg_led.group[3], (ui_selected_group == 3));
2394
  }
134 tk 2395
 
2396
  // trigger layer LEDs
492 tk 2397
  SEQ_LED_PinSet(seq_hwcfg_led.trg_layer[0], (ui_selected_trg_layer == 0));
2398
  SEQ_LED_PinSet(seq_hwcfg_led.trg_layer[1], (ui_selected_trg_layer == 1));
2399
  SEQ_LED_PinSet(seq_hwcfg_led.trg_layer[2], (ui_selected_trg_layer >= 2) || seq_ui_button_state.TRG_LAYER_SEL);
678 tk 2400
  SEQ_LED_PinSet(seq_hwcfg_led.trg_layer_sel, ui_page == SEQ_UI_PAGE_TRGSEL);
134 tk 2401
 
2402
  // remaining LEDs
492 tk 2403
  SEQ_LED_PinSet(seq_hwcfg_led.edit, ui_page == SEQ_UI_PAGE_EDIT);
2404
  SEQ_LED_PinSet(seq_hwcfg_led.mute, ui_page == SEQ_UI_PAGE_MUTE);
2405
  SEQ_LED_PinSet(seq_hwcfg_led.pattern, ui_page == SEQ_UI_PAGE_PATTERN);
399 tk 2406
  if( SEQ_SONG_ActiveGet() )
492 tk 2407
    SEQ_LED_PinSet(seq_hwcfg_led.song, 1);
399 tk 2408
  else
492 tk 2409
    SEQ_LED_PinSet(seq_hwcfg_led.song, ui_cursor_flash ? 0 : (ui_page == SEQ_UI_PAGE_SONG));
743 tk 2410
  SEQ_LED_PinSet(seq_hwcfg_led.mixer, ui_page == SEQ_UI_PAGE_MIXER);
1119 tk 2411
 
2412
  SEQ_LED_PinSet(seq_hwcfg_led.track_mode, ui_page == SEQ_UI_PAGE_TRKMODE);
2413
  SEQ_LED_PinSet(seq_hwcfg_led.track_groove, ui_page == SEQ_UI_PAGE_TRKGRV);
2414
  SEQ_LED_PinSet(seq_hwcfg_led.track_length, ui_page == SEQ_UI_PAGE_TRKLEN);
2415
  SEQ_LED_PinSet(seq_hwcfg_led.track_direction, ui_page == SEQ_UI_PAGE_TRKDIR);
2416
  SEQ_LED_PinSet(seq_hwcfg_led.track_morph, ui_page == SEQ_UI_PAGE_TRKMORPH);
2417
  SEQ_LED_PinSet(seq_hwcfg_led.track_transpose, ui_page == SEQ_UI_PAGE_TRKTRAN);
134 tk 2418
 
492 tk 2419
  SEQ_LED_PinSet(seq_hwcfg_led.solo, seq_ui_button_state.SOLO);
2420
  SEQ_LED_PinSet(seq_hwcfg_led.fast, seq_ui_button_state.FAST_ENCODERS);
1121 tk 2421
  SEQ_LED_PinSet(seq_hwcfg_led.fast2, seq_ui_button_state.FAST2_ENCODERS);
492 tk 2422
  SEQ_LED_PinSet(seq_hwcfg_led.all, seq_ui_button_state.CHANGE_ALL_STEPS);
134 tk 2423
 
1206 tk 2424
  u8 seq_running = SEQ_BPM_IsRunning() && (!seq_core_slaveclk_mute || ((seq_core_state.ref_step & 3) == 0));
2425
  // note: no bug: we added check for ref_step&3 for flashing the LEDs to give a sign of activity in slave mode with slaveclk_muted
2426
  SEQ_LED_PinSet(seq_hwcfg_led.play, seq_running);
2427
  SEQ_LED_PinSet(seq_hwcfg_led.stop, !seq_running && !ui_seq_pause);
2428
  SEQ_LED_PinSet(seq_hwcfg_led.pause, ui_seq_pause && (!seq_core_slaveclk_mute || ui_cursor_flash));
240 tk 2429
 
492 tk 2430
  SEQ_LED_PinSet(seq_hwcfg_led.rew, seq_ui_button_state.REW);
2431
  SEQ_LED_PinSet(seq_hwcfg_led.fwd, seq_ui_button_state.FWD);
596 tk 2432
 
2433
  SEQ_LED_PinSet(seq_hwcfg_led.loop, seq_core_state.LOOP);
951 tk 2434
  SEQ_LED_PinSet(seq_hwcfg_led.follow, seq_core_state.FOLLOW);
134 tk 2435
 
678 tk 2436
  SEQ_LED_PinSet(seq_hwcfg_led.step_view, ui_page == SEQ_UI_PAGE_STEPSEL);
134 tk 2437
 
591 tk 2438
  SEQ_LED_PinSet(seq_hwcfg_led.select, seq_ui_button_state.SELECT_PRESSED);
492 tk 2439
  SEQ_LED_PinSet(seq_hwcfg_led.menu, seq_ui_button_state.MENU_PRESSED);
1203 tk 2440
  SEQ_LED_PinSet(seq_hwcfg_led.bookmark, ui_page == SEQ_UI_PAGE_BOOKMARKS);
134 tk 2441
 
596 tk 2442
  // handle double functions
2443
  if( seq_ui_button_state.MENU_PRESSED ) {
2444
    SEQ_LED_PinSet(seq_hwcfg_led.scrub, seq_core_state.LOOP);
951 tk 2445
    SEQ_LED_PinSet(seq_hwcfg_led.exit, seq_core_state.FOLLOW);
596 tk 2446
    SEQ_LED_PinSet(seq_hwcfg_led.metronome, seq_core_state.EXT_RESTART_REQ);
2447
  } else {
2448
    SEQ_LED_PinSet(seq_hwcfg_led.scrub, seq_ui_button_state.SCRUB);
951 tk 2449
    SEQ_LED_PinSet(seq_hwcfg_led.exit, ui_page == SEQ_UI_PAGE_MENU);
596 tk 2450
    SEQ_LED_PinSet(seq_hwcfg_led.metronome, seq_core_state.METRONOME);
2451
  }
2452
 
1313 tk 2453
  SEQ_LED_PinSet(seq_hwcfg_led.record, seq_record_state.ENABLED);
1219 tk 2454
  SEQ_LED_PinSet(seq_hwcfg_led.live, ui_page == SEQ_UI_PAGE_TRKLIVE);
630 tk 2455
 
492 tk 2456
  SEQ_LED_PinSet(seq_hwcfg_led.utility, ui_page == SEQ_UI_PAGE_UTIL);
2457
  SEQ_LED_PinSet(seq_hwcfg_led.copy, seq_ui_button_state.COPY);
2458
  SEQ_LED_PinSet(seq_hwcfg_led.paste, seq_ui_button_state.PASTE);
1014 tk 2459
  SEQ_LED_PinSet(seq_hwcfg_led.undo, seq_ui_button_state.UNDO);
492 tk 2460
  SEQ_LED_PinSet(seq_hwcfg_led.clear, seq_ui_button_state.CLEAR);
240 tk 2461
 
513 tk 2462
  SEQ_LED_PinSet(seq_hwcfg_led.tap_tempo, seq_ui_button_state.TAP_TEMPO);
678 tk 2463
  SEQ_LED_PinSet(seq_hwcfg_led.tempo_preset, ui_page == SEQ_UI_PAGE_BPM_PRESETS);
524 tk 2464
  SEQ_LED_PinSet(seq_hwcfg_led.ext_restart, seq_core_state.EXT_RESTART_REQ);
240 tk 2465
 
492 tk 2466
  SEQ_LED_PinSet(seq_hwcfg_led.down, seq_ui_button_state.DOWN);
2467
  SEQ_LED_PinSet(seq_hwcfg_led.up, seq_ui_button_state.UP);
240 tk 2468
 
167 tk 2469
 
1044 tk 2470
  // in MENU page: overrule GP LEDs as long as MENU button is pressed/active
306 tk 2471
  if( seq_ui_button_state.MENU_PRESSED ) {
2472
    if( ui_cursor_flash ) // if flashing flag active: no LED flag set
2473
      ui_gp_leds = 0x0000;
2474
    else {
2475
      int i;
2476
      u16 new_ui_gp_leds = 0x0000;
2477
      for(i=0; i<16; ++i)
2478
    if( ui_page == ui_shortcut_menu_pages[i] )
2479
      new_ui_gp_leds |= (1 << i);
2480
      ui_gp_leds = new_ui_gp_leds;
2481
    }
2482
  } else {
2483
    // note: the background function is permanently interrupted - therefore we write the GP pattern
2484
    // into a temporary variable, and take it over once completed
2485
    u16 new_ui_gp_leds = 0x0000;
2486
    // request GP LED values from current menu page
2487
    // will be transfered to DOUT registers in SEQ_UI_LED_Handler_Periodic
2488
    new_ui_gp_leds = 0x0000;
206 tk 2489
 
306 tk 2490
    if( ui_led_callback != NULL )
2491
      ui_led_callback(&new_ui_gp_leds);
167 tk 2492
 
306 tk 2493
    ui_gp_leds = new_ui_gp_leds;
2494
  }
2495
 
1020 tk 2496
  // update BLM LEDs
2497
  SEQ_BLM_LED_Update();
524 tk 2498
 
626 tk 2499
  // send LED changes in remote server mode
1316 tk 2500
  if( seq_midi_sysex_remote_mode == SEQ_MIDI_SYSEX_REMOTE_MODE_SERVER || seq_midi_sysex_remote_active_mode == SEQ_MIDI_SYSEX_REMOTE_MODE_SERVER ) {
626 tk 2501
    int first_sr = -1;
2502
    int last_sr = -1;
2503
    int sr;
2504
    for(sr=0; sr<SEQ_LED_NUM_SR; ++sr) {
2505
      u8 value = SEQ_LED_SRGet(sr);
2506
      if( value != remote_led_sr[sr] ) {
2507
    if( first_sr == -1 )
2508
      first_sr = sr;
2509
    last_sr = sr;
2510
    remote_led_sr[sr] = value;
2511
      }
2512
    }
2513
 
2514
    MIOS32_IRQ_Disable();
1316 tk 2515
    if( seq_midi_sysex_remote_force_led_update ) {
626 tk 2516
      first_sr = 0;
2517
      last_sr = SEQ_LED_NUM_SR-1;
2518
    }
1316 tk 2519
    seq_midi_sysex_remote_force_led_update = 0;
626 tk 2520
    MIOS32_IRQ_Enable();
2521
 
2522
    if( first_sr >= 0 )
2523
      SEQ_MIDI_SYSEX_REMOTE_Server_SendLED(first_sr, (u8 *)&remote_led_sr[first_sr], last_sr-first_sr+1);
2524
  }
2525
 
2526
 
134 tk 2527
  return 0; // no error
2528
}
2529
 
2530
 
2531
/////////////////////////////////////////////////////////////////////////////
2532
// updates high-prio LED functions (GP LEDs and Beat LED)
168 tk 2533
// called each mS
134 tk 2534
/////////////////////////////////////////////////////////////////////////////
2535
s32 SEQ_UI_LED_Handler_Periodic()
2536
{
625 tk 2537
  // ignore in remote client mode
1316 tk 2538
  if( seq_midi_sysex_remote_active_mode == SEQ_MIDI_SYSEX_REMOTE_MODE_CLIENT )
625 tk 2539
    return 0; // no error
2540
 
1044 tk 2541
  // ignore as long as hardware config hasn't been read
496 tk 2542
  if( !SEQ_FILE_HW_ConfigLocked() )
2543
    return -1;
2544
 
752 tk 2545
  // GP LEDs are updated when ui_gp_leds has changed
134 tk 2546
  static u16 prev_ui_gp_leds = 0x0000;
2547
 
755 tk 2548
  // beat LED
193 tk 2549
  u8 sequencer_running = SEQ_BPM_IsRunning();
1068 tk 2550
  u8 beat_led_on = sequencer_running && ((seq_core_state.ref_step & 3) == 0);
2551
  SEQ_LED_PinSet(seq_hwcfg_led.beat, beat_led_on);
134 tk 2552
 
1068 tk 2553
  // mirror to status LED (inverted, so that LED is normaly on)
2554
  MIOS32_BOARD_LED_Set(0xffffffff, beat_led_on ? 0 : 1);
755 tk 2555
 
1336 tk 2556
  // MIDI IN/OUT LEDs
2557
  SEQ_LED_PinSet(seq_hwcfg_led.midi_in_combined, seq_midi_port_in_combined_ctr);
2558
  SEQ_LED_PinSet(seq_hwcfg_led.midi_out_combined, seq_midi_port_out_combined_ctr);  
1068 tk 2559
 
755 tk 2560
  // don't continue if no new step has been generated and GP LEDs haven't changed
1044 tk 2561
  if( !seq_core_step_update_req && prev_ui_gp_leds == ui_gp_leds && sequencer_running ) // sequencer running check: workaround - as long as sequencer not running, we won't get an step update request!
755 tk 2562
    return 0;
2563
  seq_core_step_update_req = 0; // requested from SEQ_CORE if any step has been changed
2564
  prev_ui_gp_leds = ui_gp_leds; // take over new GP pattern
2565
 
134 tk 2566
  // for song position marker (supports 16 LEDs, check for selected step view)
2567
  u16 pos_marker_mask = 0x0000;
325 tk 2568
  u8 visible_track = SEQ_UI_VisibleTrackGet();
2569
  u8 played_step = seq_core_trk[visible_track].step;
754 tk 2570
 
1206 tk 2571
  if( seq_core_slaveclk_mute != SEQ_CORE_SLAVECLK_MUTE_Enabled ) { // Off and OffOnNextMeasure
2572
    if( seq_ui_button_state.STEP_VIEW ) {
2573
      // if STEP_VIEW button pressed: pos marker correlated to zoom ratio
2574
      if( sequencer_running )
2575
    pos_marker_mask = 1 << (played_step / (SEQ_TRG_NumStepsGet(visible_track)/16));
2576
    } else {
2577
      if( sequencer_running && (played_step >> 4) == ui_selected_step_view )
2578
    pos_marker_mask = 1 << (played_step & 0xf);
2579
    }
325 tk 2580
  }
134 tk 2581
 
752 tk 2582
 
2583
  // follow step position if enabled
951 tk 2584
  if( seq_core_state.FOLLOW ) {
752 tk 2585
    u8 trk_step = seq_core_trk[visible_track].step;
2586
    if( (trk_step & 0xf0) != (16*ui_selected_step_view) ) {
2587
      ui_selected_step_view = trk_step / 16;
2588
      ui_selected_step = (ui_selected_step % 16) + 16*ui_selected_step_view;
2589
      seq_ui_display_update_req = 1;
2590
    }
2591
  }
134 tk 2592
 
2593
  // transfer to GP LEDs
514 tk 2594
  if( seq_hwcfg_led.gp_dout_l_sr ) {
2595
    if( seq_hwcfg_led.gp_dout_l2_sr )
2596
      SEQ_LED_SRSet(seq_hwcfg_led.gp_dout_l_sr-1, (ui_gp_leds >> 0) & 0xff);
496 tk 2597
    else
514 tk 2598
      SEQ_LED_SRSet(seq_hwcfg_led.gp_dout_l_sr-1, ((ui_gp_leds ^ pos_marker_mask) >> 0) & 0xff);
496 tk 2599
  }
134 tk 2600
 
514 tk 2601
  if( seq_hwcfg_led.gp_dout_r_sr ) {
2602
    if( seq_hwcfg_led.gp_dout_r2_sr )
2603
      SEQ_LED_SRSet(seq_hwcfg_led.gp_dout_r_sr-1, (ui_gp_leds >> 8) & 0xff);
496 tk 2604
    else
514 tk 2605
      SEQ_LED_SRSet(seq_hwcfg_led.gp_dout_r_sr-1, ((ui_gp_leds ^ pos_marker_mask) >> 8) & 0xff);
496 tk 2606
  }
134 tk 2607
 
514 tk 2608
  if( seq_hwcfg_led.gp_dout_l2_sr )
2609
    SEQ_LED_SRSet(seq_hwcfg_led.gp_dout_l2_sr-1, (pos_marker_mask >> 0) & 0xff);
2610
  if( seq_hwcfg_led.gp_dout_r2_sr )
2611
    SEQ_LED_SRSet(seq_hwcfg_led.gp_dout_r2_sr-1, (pos_marker_mask >> 8) & 0xff);
496 tk 2612
 
1146 tk 2613
  // transfer to optional track LEDs
2614
  if( seq_hwcfg_led.tracks_dout_l_sr )
2615
    SEQ_LED_SRSet(seq_hwcfg_led.tracks_dout_l_sr-1, (ui_selected_tracks >> 0) & 0xff);
2616
  if( seq_hwcfg_led.tracks_dout_r_sr )
2617
    SEQ_LED_SRSet(seq_hwcfg_led.tracks_dout_r_sr-1, (ui_selected_tracks >> 8) & 0xff);
524 tk 2618
 
2619
  if( seq_hwcfg_blm.enabled ) {
2620
    // Red LEDs (position marker)
2621
    int track_ix;
784 tk 2622
    for(track_ix=0; track_ix<4; ++track_ix) {
2623
      u8 track = 4*ui_selected_group + track_ix;
1020 tk 2624
 
2625
      // determine position marker
524 tk 2626
      u16 pos_marker_mask = 0x0000;
2627
      if( sequencer_running )