Subversion Repositories svn.mios32

Rev

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