Subversion Repositories svn.mios32

Rev

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