Subversion Repositories svn.mios32

Rev

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