Subversion Repositories svn.mios32

Rev

Rev 167 | Rev 173 | 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 168 2008-12-07 18:32:25Z 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
 
18
#include <mios32.h>
19
 
20
#if DEFAULT_SRM_ENABLED
21
#include <blm8x8.h>
22
#endif
23
 
24
#include "seq_ui.h"
25
#include "seq_lcd.h"
26
#include "seq_led.h"
27
#include "seq_midi.h"
159 tk 28
#include "seq_bpm.h"
134 tk 29
#include "seq_core.h"
30
#include "seq_par.h"
31
#include "seq_trg.h"
32
 
33
 
34
/////////////////////////////////////////////////////////////////////////////
35
// Local types
36
/////////////////////////////////////////////////////////////////////////////
37
 
38
 
39
/////////////////////////////////////////////////////////////////////////////
40
// Local prototypes
41
/////////////////////////////////////////////////////////////////////////////
42
 
43
 
44
/////////////////////////////////////////////////////////////////////////////
45
// Global variables
46
/////////////////////////////////////////////////////////////////////////////
47
 
159 tk 48
u8 seq_ui_display_update_req;
49
u8 seq_ui_display_init_req;
134 tk 50
 
167 tk 51
seq_ui_button_state_t seq_ui_button_state;
52
 
134 tk 53
u8 ui_selected_group;
54
u8 ui_selected_tracks;
55
u8 ui_selected_par_layer;
56
u8 ui_selected_trg_layer;
57
u8 ui_selected_step_view;
58
u8 ui_selected_step;
168 tk 59
u8 ui_selected_item;
134 tk 60
 
168 tk 61
u8 ui_selected_item;
134 tk 62
 
168 tk 63
volatile u16 ui_cursor_flash_ctr;
134 tk 64
 
168 tk 65
 
134 tk 66
/////////////////////////////////////////////////////////////////////////////
67
// Local variables
68
/////////////////////////////////////////////////////////////////////////////
69
 
167 tk 70
// Note: must be kept in sync with SEQ_UI_PAGE_xxx definitions in seq_ui.h!
71
static const s32 (*ui_init_callback[SEQ_UI_PAGES])(u32 mode) = {
72
  (void *)&SEQ_UI_TODO_Init,    // 0
73
  (void *)&SEQ_UI_EDIT_Init,    // 1
74
  (void *)&SEQ_UI_TRKDIR_Init   // 2
75
};
134 tk 76
 
168 tk 77
static s32 (*ui_button_callback)(seq_ui_button_t button, s32 depressed);
78
static s32 (*ui_encoder_callback)(seq_ui_encoder_t encoder, s32 incrementer);
79
static s32 (*ui_led_callback)(u16 *gp_leds, u16 *gp_leds_flashing);
167 tk 80
static s32 (*ui_lcd_callback)(u8 high_prio);
81
 
82
static seq_ui_page_t ui_page;
83
 
84
 
85
// following pages are directly accessible with the GP buttons when MENU button is pressed
86
static const seq_ui_page_t ui_direct_access_menu_pages[16] = {
87
  SEQ_UI_PAGE_NONE,        // GP1
88
  SEQ_UI_PAGE_NONE,        // GP2
89
  SEQ_UI_PAGE_NONE,        // GP3
90
  SEQ_UI_PAGE_TRKDIR,      // GP4
91
  SEQ_UI_PAGE_NONE,        // GP5
92
  SEQ_UI_PAGE_NONE,        // GP6
93
  SEQ_UI_PAGE_NONE,        // GP7
94
  SEQ_UI_PAGE_NONE,        // GP8
95
  SEQ_UI_PAGE_NONE,        // GP9
96
  SEQ_UI_PAGE_NONE,        // GP10
97
  SEQ_UI_PAGE_NONE,        // GP11
98
  SEQ_UI_PAGE_NONE,        // GP12
99
  SEQ_UI_PAGE_NONE,        // GP13
100
  SEQ_UI_PAGE_NONE,        // GP14
101
  SEQ_UI_PAGE_NONE,        // GP15
102
  SEQ_UI_PAGE_NONE         // GP16
103
};
104
 
168 tk 105
static u16 ui_gp_leds;
106
static u16 ui_gp_leds_flashing;
167 tk 107
 
168 tk 108
 
134 tk 109
/////////////////////////////////////////////////////////////////////////////
110
// Initialisation
111
/////////////////////////////////////////////////////////////////////////////
112
s32 SEQ_UI_Init(u32 mode)
113
{
114
  // init selection variables
115
  ui_selected_group = 0;
116
  ui_selected_tracks = (1 << 0);
117
  ui_selected_par_layer = 0;
118
  ui_selected_trg_layer = 0;
119
  ui_selected_step_view = 0;
120
  ui_selected_step = 0;
168 tk 121
  ui_selected_item = 0;
134 tk 122
 
168 tk 123
  ui_cursor_flash_ctr = 0;
124
 
167 tk 125
  seq_ui_button_state.ALL = 0;
126
 
134 tk 127
  // visible GP pattern
128
  ui_gp_leds = 0x0000;
167 tk 129
  ui_gp_leds_flashing = 0x0000;
134 tk 130
 
167 tk 131
  // change to edit page
132
  ui_page = SEQ_UI_PAGE_NONE;
133
  SEQ_UI_PageSet(SEQ_UI_PAGE_EDIT);
134 tk 134
 
135
  return 0; // no error
136
}
137
 
138
 
139
/////////////////////////////////////////////////////////////////////////////
167 tk 140
// Various installation routines for menu page LCD handlers
141
/////////////////////////////////////////////////////////////////////////////
168 tk 142
s32 SEQ_UI_InstallButtonCallback(void *callback)
167 tk 143
{
168 tk 144
  ui_button_callback = callback;
167 tk 145
  return 0; // no error
146
}
147
 
168 tk 148
s32 SEQ_UI_InstallEncoderCallback(void *callback)
167 tk 149
{
168 tk 150
  ui_encoder_callback = callback;
167 tk 151
  return 0; // no error
152
}
153
 
168 tk 154
s32 SEQ_UI_InstallLEDCallback(void *callback)
167 tk 155
{
168 tk 156
  ui_led_callback = callback;
167 tk 157
  return 0; // no error
158
}
159
 
168 tk 160
s32 SEQ_UI_InstallLCDCallback(void *callback)
167 tk 161
{
162
  ui_lcd_callback = callback;
163
  return 0; // no error
164
}
165
 
166
 
167
/////////////////////////////////////////////////////////////////////////////
168
// Change the menu page
169
/////////////////////////////////////////////////////////////////////////////
170
s32 SEQ_UI_PageSet(seq_ui_page_t page)
171
{
172
  if( page != ui_page ) {
173
    // disable hooks of previous page and request re-initialisation
174
    MIOS32_IRQ_Disable();
175
    ui_page = page;
168 tk 176
    ui_button_callback = NULL;
177
    ui_encoder_callback = NULL;
178
    ui_led_callback = NULL;
167 tk 179
    ui_lcd_callback = NULL;
180
    MIOS32_IRQ_Enable();
181
 
182
  // TODO: define generic #define for this button behaviour
183
#if defined(MIOS32_FAMILY_EMULATION)
168 tk 184
    seq_ui_button_state.MENU_PRESSED = 0; // MENU page selection finished
167 tk 185
#endif
186
 
168 tk 187
    // don't display menu page anymore (only first time when menu button has been pressed)
188
    seq_ui_button_state.MENU_PAGE_DISPLAYED = 0;
189
 
167 tk 190
    // request display initialisation
191
    seq_ui_display_init_req = 1;
192
  }
193
}
194
 
195
 
196
/////////////////////////////////////////////////////////////////////////////
134 tk 197
// Dedicated button functions
198
// Mapped to physical buttons in SEQ_UI_Button_Handler()
199
// Will also be mapped to MIDI keys later (for MIDI remote function)
200
/////////////////////////////////////////////////////////////////////////////
201
static s32 SEQ_UI_Button_GP(s32 depressed, u32 gp)
202
{
203
  if( depressed ) return -1; // ignore when button depressed
204
 
167 tk 205
  if( seq_ui_button_state.MENU_PRESSED ) {
206
    // MENU button overruling - select menu page
207
    SEQ_UI_PageSet(ui_direct_access_menu_pages[gp]);
208
  } else {
209
    // forward to menu page
168 tk 210
    if( ui_button_callback != NULL )
211
      ui_button_callback(gp, depressed);
167 tk 212
  }
134 tk 213
 
214
  return 0; // no error
215
}
216
 
217
static s32 SEQ_UI_Button_Left(s32 depressed)
218
{
168 tk 219
  // forward to menu page
220
  if( ui_button_callback != NULL )
221
    ui_button_callback(SEQ_UI_BUTTON_Left, depressed);
134 tk 222
 
223
  return 0; // no error
224
}
225
 
226
static s32 SEQ_UI_Button_Right(s32 depressed)
227
{
168 tk 228
  // forward to menu page
229
  if( ui_button_callback != NULL )
230
    ui_button_callback(SEQ_UI_BUTTON_Right, depressed);
134 tk 231
 
232
  return 0; // no error
233
}
234
 
168 tk 235
static s32 SEQ_UI_Button_Down(s32 depressed)
236
{
237
  // forward to menu page
238
  if( ui_button_callback != NULL )
239
    ui_button_callback(SEQ_UI_BUTTON_Down, depressed);
240
 
241
  return 0; // no error
242
}
243
 
244
static s32 SEQ_UI_Button_Up(s32 depressed)
245
{
246
  // forward to menu page
247
  if( ui_button_callback != NULL )
248
    ui_button_callback(SEQ_UI_BUTTON_Up, depressed);
249
 
250
  return 0; // no error
251
}
252
 
134 tk 253
static s32 SEQ_UI_Button_Scrub(s32 depressed)
254
{
137 tk 255
#if 0
134 tk 256
  if( depressed ) return -1; // ignore when button depressed
137 tk 257
#else
258
  // Sending SysEx Stream test
259
  u8 buffer[7] = { 0xf0, 0x11, 0x22, 0x33, 0x44, depressed ? 0x00 : 0x55, 0xf7 };
134 tk 260
 
137 tk 261
  MIOS32_MIDI_SendSysEx(DEFAULT, buffer, 7);
262
#endif
263
 
134 tk 264
  return 0; // no error
265
}
266
 
267
static s32 SEQ_UI_Button_Metronome(s32 depressed)
268
{
137 tk 269
#if 0
134 tk 270
  if( depressed ) return -1; // ignore when button depressed
137 tk 271
#else
272
  // Sending MIDI Note test
273
  if( depressed )
274
    MIOS32_MIDI_SendNoteOff(DEFAULT, 0x90, 0x3c, 0x00);
275
  else
276
    MIOS32_MIDI_SendNoteOn(DEFAULT, 0x90, 0x3c, 0x7f);
277
#endif
134 tk 278
 
279
  return 0; // no error
280
}
281
 
282
static s32 SEQ_UI_Button_Stop(s32 depressed)
283
{
284
  if( depressed ) return -1; // ignore when button depressed
285
 
159 tk 286
  // if sequencer running: stop it
287
  // if sequencer already stopped: reset song position
166 tk 288
  if( seq_core_state.RUN )
159 tk 289
    SEQ_CORE_Stop(0);
290
  else
291
    SEQ_CORE_Reset();
292
 
134 tk 293
  return 0; // no error
294
}
295
 
296
static s32 SEQ_UI_Button_Pause(s32 depressed)
297
{
298
  if( depressed ) return -1; // ignore when button depressed
299
 
159 tk 300
  // pause sequencer
301
  SEQ_CORE_Pause(0);
302
 
134 tk 303
  return 0; // no error
304
}
305
 
306
static s32 SEQ_UI_Button_Play(s32 depressed)
307
{
308
  if( depressed ) return -1; // ignore when button depressed
309
 
159 tk 310
  // start sequencer
311
  SEQ_CORE_Start(0);
312
 
134 tk 313
  return 0; // no error
314
}
315
 
316
static s32 SEQ_UI_Button_Rew(s32 depressed)
317
{
318
  if( depressed ) return -1; // ignore when button depressed
319
 
320
  return 0; // no error
321
}
322
 
323
static s32 SEQ_UI_Button_Fwd(s32 depressed)
324
{
325
  if( depressed ) return -1; // ignore when button depressed
326
 
327
  return 0; // no error
328
}
329
 
330
static s32 SEQ_UI_Button_F1(s32 depressed)
331
{
332
  if( depressed ) return -1; // ignore when button depressed
333
 
334
  return 0; // no error
335
}
336
 
337
static s32 SEQ_UI_Button_F2(s32 depressed)
338
{
339
  if( depressed ) return -1; // ignore when button depressed
340
 
341
  return 0; // no error
342
}
343
 
344
static s32 SEQ_UI_Button_F3(s32 depressed)
345
{
346
  if( depressed ) return -1; // ignore when button depressed
347
 
348
  return 0; // no error
349
}
350
 
351
static s32 SEQ_UI_Button_F4(s32 depressed)
352
{
353
  if( depressed ) return -1; // ignore when button depressed
354
 
355
  return 0; // no error
356
}
357
 
358
static s32 SEQ_UI_Button_Utility(s32 depressed)
359
{
360
  if( depressed ) return -1; // ignore when button depressed
361
 
362
  return 0; // no error
363
}
364
 
365
static s32 SEQ_UI_Button_Copy(s32 depressed)
366
{
367
  if( depressed ) return -1; // ignore when button depressed
368
 
369
  return 0; // no error
370
}
371
 
372
static s32 SEQ_UI_Button_Paste(s32 depressed)
373
{
374
  if( depressed ) return -1; // ignore when button depressed
375
 
376
  return 0; // no error
377
}
378
 
379
static s32 SEQ_UI_Button_Clear(s32 depressed)
380
{
381
  if( depressed ) return -1; // ignore when button depressed
382
 
383
  return 0; // no error
384
}
385
 
386
static s32 SEQ_UI_Button_Menu(s32 depressed)
387
{
167 tk 388
  // TODO: define generic #define for this button behaviour
389
#if defined(MIOS32_FAMILY_EMULATION)
134 tk 390
  if( depressed ) return -1; // ignore when button depressed
167 tk 391
  seq_ui_button_state.MENU_PRESSED ^= 1; // toggle MENU pressed (will also be released once GP button has been pressed)
392
#else
393
  seq_ui_button_state.MENU_PRESSED = depressed ? 0 : 1;
394
#endif
134 tk 395
 
168 tk 396
  seq_ui_button_state.MENU_PAGE_DISPLAYED = seq_ui_button_state.MENU_PRESSED;
397
 
134 tk 398
  return 0; // no error
399
}
400
 
401
static s32 SEQ_UI_Button_Select(s32 depressed)
402
{
168 tk 403
  // forward to menu page
404
  if( ui_button_callback != NULL )
405
    ui_button_callback(SEQ_UI_BUTTON_Select, depressed);
134 tk 406
 
407
  return 0; // no error
408
}
409
 
410
static s32 SEQ_UI_Button_Exit(s32 depressed)
411
{
168 tk 412
  // forward to menu page
413
  if( ui_button_callback != NULL )
414
    ui_button_callback(SEQ_UI_BUTTON_Exit, depressed);
134 tk 415
 
167 tk 416
  // release all button states
417
  seq_ui_button_state.ALL = 0;
418
 
134 tk 419
  return 0; // no error
420
}
421
 
422
static s32 SEQ_UI_Button_Edit(s32 depressed)
423
{
424
  if( depressed ) return -1; // ignore when button depressed
425
 
167 tk 426
  // change to edit page
427
  SEQ_UI_PageSet(SEQ_UI_PAGE_EDIT);
428
 
134 tk 429
  return 0; // no error
430
}
431
 
432
static s32 SEQ_UI_Button_Mute(s32 depressed)
433
{
434
  if( depressed ) return -1; // ignore when button depressed
435
 
436
  return 0; // no error
437
}
438
 
439
static s32 SEQ_UI_Button_Pattern(s32 depressed)
440
{
441
  if( depressed ) return -1; // ignore when button depressed
442
 
443
  return 0; // no error
444
}
445
 
446
static s32 SEQ_UI_Button_Song(s32 depressed)
447
{
448
  if( depressed ) return -1; // ignore when button depressed
449
 
450
  return 0; // no error
451
}
452
 
453
static s32 SEQ_UI_Button_Solo(s32 depressed)
454
{
455
  if( depressed ) return -1; // ignore when button depressed
456
 
457
  return 0; // no error
458
}
459
 
460
static s32 SEQ_UI_Button_Fast(s32 depressed)
461
{
462
  if( depressed ) return -1; // ignore when button depressed
463
 
464
  return 0; // no error
465
}
466
 
467
static s32 SEQ_UI_Button_All(s32 depressed)
468
{
469
  if( depressed ) return -1; // ignore when button depressed
470
 
471
  return 0; // no error
472
}
473
 
474
static s32 SEQ_UI_Button_StepView(s32 depressed)
475
{
476
  if( depressed ) return -1; // ignore when button depressed
477
 
478
  ui_selected_step_view = ui_selected_step_view ? 0 : 1;
479
 
480
  return 0; // no error
481
}
482
 
483
static s32 SEQ_UI_Button_TapTempo(s32 depressed)
484
{
485
  if( depressed ) return -1; // ignore when button depressed
486
 
487
  return 0; // no error
488
}
489
 
490
static s32 SEQ_UI_Button_Track(s32 depressed, u32 track)
491
{
492
  if( depressed ) return -1; // ignore when button depressed
493
 
494
  if( track >= 4 ) return -2; // max. 4 track buttons
495
 
496
  ui_selected_tracks = (1 << track); // TODO: multi-selections!
497
 
498
  return 0; // no error
499
}
500
 
501
static s32 SEQ_UI_Button_Group(s32 depressed, u32 group)
502
{
503
  if( depressed ) return -1; // ignore when button depressed
504
 
505
  if( group >= 4 ) return -2; // max. 4 group buttons
506
 
507
  ui_selected_group = group;
508
 
509
  return 0; // no error
510
}
511
 
512
static s32 SEQ_UI_Button_ParLayer(s32 depressed, u32 par_layer)
513
{
514
  if( depressed ) return -1; // ignore when button depressed
515
 
516
  if( par_layer >= 3 ) return -2; // max. 3 parlayer buttons
517
 
518
  ui_selected_par_layer = par_layer;
519
 
520
  return 0; // no error
521
}
522
 
523
static s32 SEQ_UI_Button_TrgLayer(s32 depressed, u32 trg_layer)
524
{
525
  if( depressed ) return -1; // ignore when button depressed
526
 
527
  if( trg_layer >= 3 ) return -2; // max. 3 trglayer buttons
528
 
529
  ui_selected_trg_layer = trg_layer;
530
 
531
  return 0; // no error
532
}
533
 
534
 
535
 
536
/////////////////////////////////////////////////////////////////////////////
537
// Button handler
538
/////////////////////////////////////////////////////////////////////////////
539
s32 SEQ_UI_Button_Handler(u32 pin, u32 pin_value)
540
{
541
  switch( pin ) {
168 tk 542
#if BUTTON_GP1 != BUTTON_DISABLED
134 tk 543
    case BUTTON_GP1:   SEQ_UI_Button_GP(pin_value, 0); break;
544
#endif
168 tk 545
#if BUTTON_GP2 != BUTTON_DISABLED
134 tk 546
    case BUTTON_GP2:   SEQ_UI_Button_GP(pin_value, 1); break;
547
#endif
168 tk 548
#if BUTTON_GP3 != BUTTON_DISABLED
134 tk 549
    case BUTTON_GP3:   SEQ_UI_Button_GP(pin_value, 2); break;
550
#endif
168 tk 551
#if BUTTON_GP4 != BUTTON_DISABLED
134 tk 552
    case BUTTON_GP4:   SEQ_UI_Button_GP(pin_value, 3); break;
553
#endif
168 tk 554
#if BUTTON_GP5 != BUTTON_DISABLED
134 tk 555
    case BUTTON_GP5:   SEQ_UI_Button_GP(pin_value, 4); break;
556
#endif
168 tk 557
#if BUTTON_GP6 != BUTTON_DISABLED
134 tk 558
    case BUTTON_GP6:   SEQ_UI_Button_GP(pin_value, 5); break;
559
#endif
168 tk 560
#if BUTTON_GP7 != BUTTON_DISABLED
134 tk 561
    case BUTTON_GP7:   SEQ_UI_Button_GP(pin_value, 6); break;
562
#endif
168 tk 563
#if BUTTON_GP8 != BUTTON_DISABLED
134 tk 564
    case BUTTON_GP8:   SEQ_UI_Button_GP(pin_value, 7); break;
565
#endif
168 tk 566
#if BUTTON_GP9 != BUTTON_DISABLED
134 tk 567
    case BUTTON_GP9:   SEQ_UI_Button_GP(pin_value, 8); break;
568
#endif
168 tk 569
#if BUTTON_GP10 != BUTTON_DISABLED
134 tk 570
    case BUTTON_GP10:  SEQ_UI_Button_GP(pin_value, 9); break;
571
#endif
168 tk 572
#if BUTTON_GP11 != BUTTON_DISABLED
134 tk 573
    case BUTTON_GP11:  SEQ_UI_Button_GP(pin_value, 10); break;
574
#endif
168 tk 575
#if BUTTON_GP12 != BUTTON_DISABLED
134 tk 576
    case BUTTON_GP12:  SEQ_UI_Button_GP(pin_value, 11); break;
577
#endif
168 tk 578
#if BUTTON_GP13 != BUTTON_DISABLED
134 tk 579
    case BUTTON_GP13:  SEQ_UI_Button_GP(pin_value, 12); break;
580
#endif
168 tk 581
#if BUTTON_GP14 != BUTTON_DISABLED
134 tk 582
    case BUTTON_GP14:  SEQ_UI_Button_GP(pin_value, 13); break;
583
#endif
168 tk 584
#if BUTTON_GP15 != BUTTON_DISABLED
134 tk 585
    case BUTTON_GP15:  SEQ_UI_Button_GP(pin_value, 14); break;
586
#endif
168 tk 587
#if BUTTON_GP16 != BUTTON_DISABLED
134 tk 588
    case BUTTON_GP16:  SEQ_UI_Button_GP(pin_value, 15); break;
589
#endif
590
 
168 tk 591
#if BUTTON_LEFT != BUTTON_DISABLED
134 tk 592
    case BUTTON_LEFT:  SEQ_UI_Button_Left(pin_value); break;
593
#endif
168 tk 594
#if BUTTON_RIGHT != BUTTON_DISABLED
134 tk 595
    case BUTTON_RIGHT: SEQ_UI_Button_Right(pin_value); break;
596
#endif
597
 
168 tk 598
#if BUTTON_DOWN != BUTTON_DISABLED
599
    case BUTTON_DOWN:  SEQ_UI_Button_Down(pin_value); break;
600
#endif
601
#if BUTTON_UP != BUTTON_DISABLED
602
    case BUTTON_UP:    SEQ_UI_Button_Up(pin_value); break;
603
#endif
604
 
605
#if BUTTON_SCRUB != BUTTON_DISABLED
134 tk 606
    case BUTTON_SCRUB: SEQ_UI_Button_Scrub(pin_value); break;
607
#endif
168 tk 608
#if BUTTON_METRONOME != BUTTON_DISABLED
134 tk 609
    case BUTTON_METRONOME: SEQ_UI_Button_Metronome(pin_value); break;
610
#endif
611
 
168 tk 612
#if BUTTON_STOP != BUTTON_DISABLED
134 tk 613
    case BUTTON_STOP:  SEQ_UI_Button_Stop(pin_value); break;
614
#endif
168 tk 615
#if BUTTON_PAUSE != BUTTON_DISABLED
134 tk 616
    case BUTTON_PAUSE: SEQ_UI_Button_Pause(pin_value); break;
617
#endif
168 tk 618
#if BUTTON_PLAY != BUTTON_DISABLED
134 tk 619
    case BUTTON_PLAY:  SEQ_UI_Button_Play(pin_value); break;
620
#endif
168 tk 621
#if BUTTON_REW != BUTTON_DISABLED
134 tk 622
    case BUTTON_REW:   SEQ_UI_Button_Rew(pin_value); break;
623
#endif
168 tk 624
#if BUTTON_FWD != BUTTON_DISABLED
134 tk 625
    case BUTTON_FWD:   SEQ_UI_Button_Fwd(pin_value); break;
626
#endif
627
 
168 tk 628
#if BUTTON_F1 != BUTTON_DISABLED
134 tk 629
    case BUTTON_F1:    SEQ_UI_Button_F1(pin_value); break;
630
#endif
168 tk 631
#if BUTTON_F2 != BUTTON_DISABLED
134 tk 632
    case BUTTON_F2:    SEQ_UI_Button_F2(pin_value); break;
633
#endif
168 tk 634
#if BUTTON_F3 != BUTTON_DISABLED
134 tk 635
    case BUTTON_F3:    SEQ_UI_Button_F3(pin_value); break;
636
#endif
168 tk 637
#if BUTTON_F4 != BUTTON_DISABLED
134 tk 638
    case BUTTON_F4:    SEQ_UI_Button_F4(pin_value); break;
639
#endif
640
 
168 tk 641
#if BUTTON_UTILITY != BUTTON_DISABLED
134 tk 642
    case BUTTON_UTILITY: SEQ_UI_Button_Utility(pin_value); break;
643
#endif
168 tk 644
#if BUTTON_COPY != BUTTON_DISABLED
134 tk 645
    case BUTTON_COPY:  SEQ_UI_Button_Copy(pin_value); break;
646
#endif
168 tk 647
#if BUTTON_PASTE != BUTTON_DISABLED
134 tk 648
    case BUTTON_PASTE: SEQ_UI_Button_Paste(pin_value); break;
649
#endif
168 tk 650
#if BUTTON_CLEAR != BUTTON_DISABLED
134 tk 651
    case BUTTON_CLEAR: SEQ_UI_Button_Clear(pin_value); break;
652
#endif
653
 
168 tk 654
#if BUTTON_MENU != BUTTON_DISABLED
134 tk 655
    case BUTTON_MENU:  SEQ_UI_Button_Menu(pin_value); break;
656
#endif
168 tk 657
#if BUTTON_SELECT != BUTTON_DISABLED
134 tk 658
    case BUTTON_SELECT:SEQ_UI_Button_Select(pin_value); break;
659
#endif
168 tk 660
#if BUTTON_EXIT != BUTTON_DISABLED
134 tk 661
    case BUTTON_EXIT:  SEQ_UI_Button_Exit(pin_value); break;
662
#endif
663
 
168 tk 664
#if BUTTON_TRACK1 != BUTTON_DISABLED
134 tk 665
    case BUTTON_TRACK1: SEQ_UI_Button_Track(pin_value, 0); break;
666
#endif
168 tk 667
#if BUTTON_TRACK2 != BUTTON_DISABLED
134 tk 668
    case BUTTON_TRACK2: SEQ_UI_Button_Track(pin_value, 1); break;
669
#endif
168 tk 670
#if BUTTON_TRACK3 != BUTTON_DISABLED
134 tk 671
    case BUTTON_TRACK3: SEQ_UI_Button_Track(pin_value, 2); break;
672
#endif
168 tk 673
#if BUTTON_TRACK4 != BUTTON_DISABLED
134 tk 674
    case BUTTON_TRACK4: SEQ_UI_Button_Track(pin_value, 3); break;
675
#endif
676
 
168 tk 677
#if BUTTON_PAR_LAYER_A != BUTTON_DISABLED
134 tk 678
    case BUTTON_PAR_LAYER_A: SEQ_UI_Button_ParLayer(pin_value, 0); break;
679
#endif
168 tk 680
#if BUTTON_PAR_LAYER_B != BUTTON_DISABLED
134 tk 681
    case BUTTON_PAR_LAYER_B: SEQ_UI_Button_ParLayer(pin_value, 1); break;
682
#endif
168 tk 683
#if BUTTON_PAR_LAYER_C != BUTTON_DISABLED
134 tk 684
    case BUTTON_PAR_LAYER_C: SEQ_UI_Button_ParLayer(pin_value, 2); break;
685
#endif
686
 
168 tk 687
#if BUTTON_EDIT != BUTTON_DISABLED
134 tk 688
    case BUTTON_EDIT:   SEQ_UI_Button_Edit(pin_value); break;
689
#endif
168 tk 690
#if BUTTON_MUTE != BUTTON_DISABLED
134 tk 691
    case BUTTON_MUTE:   SEQ_UI_Button_Mute(pin_value); break;
692
#endif
168 tk 693
#if BUTTON_PATTERN != BUTTON_DISABLED
134 tk 694
    case BUTTON_PATTERN:SEQ_UI_Button_Pattern(pin_value); break;
695
#endif
168 tk 696
#if BUTTON_SONG != BUTTON_DISABLED
134 tk 697
    case BUTTON_SONG:   SEQ_UI_Button_Song(pin_value); break;
698
#endif
699
 
168 tk 700
#if BUTTON_SOLO != BUTTON_DISABLED
134 tk 701
    case BUTTON_SOLO:   SEQ_UI_Button_Solo(pin_value); break;
702
#endif
168 tk 703
#if BUTTON_FAST != BUTTON_DISABLED
134 tk 704
    case BUTTON_FAST:   SEQ_UI_Button_Fast(pin_value); break;
705
#endif
168 tk 706
#if BUTTON_ALL != BUTTON_DISABLED
134 tk 707
    case BUTTON_ALL:    SEQ_UI_Button_All(pin_value); break;
708
#endif
709
 
168 tk 710
#if BUTTON_GROUP1 != BUTTON_DISABLED
134 tk 711
    case BUTTON_GROUP1: SEQ_UI_Button_Group(pin_value, 0); break;
712
#endif
168 tk 713
#if BUTTON_GROUP2 != BUTTON_DISABLED
134 tk 714
    case BUTTON_GROUP2: SEQ_UI_Button_Group(pin_value, 1); break;
715
#endif
168 tk 716
#if BUTTON_GROUP3 != BUTTON_DISABLED
134 tk 717
    case BUTTON_GROUP3: SEQ_UI_Button_Group(pin_value, 2); break;
718
#endif
168 tk 719
#if BUTTON_GROUP4 != BUTTON_DISABLED
134 tk 720
    case BUTTON_GROUP4: SEQ_UI_Button_Group(pin_value, 3); break;
721
#endif
722
 
168 tk 723
#if BUTTON_TRG_LAYER_A != BUTTON_DISABLED
134 tk 724
    case BUTTON_TRG_LAYER_A: SEQ_UI_Button_TrgLayer(pin_value, 0); break;
725
#endif
168 tk 726
#if BUTTON_TRG_LAYER_B != BUTTON_DISABLED
134 tk 727
    case BUTTON_TRG_LAYER_B: SEQ_UI_Button_TrgLayer(pin_value, 1); break;
728
#endif
168 tk 729
#if BUTTON_TRG_LAYER_C != BUTTON_DISABLED
134 tk 730
    case BUTTON_TRG_LAYER_C: SEQ_UI_Button_TrgLayer(pin_value, 2); break;
731
#endif
732
 
168 tk 733
#if BUTTON_STEP_VIEW != BUTTON_DISABLED
134 tk 734
    case BUTTON_STEP_VIEW: SEQ_UI_Button_StepView(pin_value); break;
735
#endif
736
 
168 tk 737
#if BUTTON_TAP_TEMPO != BUTTON_DISABLED
134 tk 738
    case BUTTON_TAP_TEMPO:   SEQ_UI_Button_TapTempo(pin_value); break;
739
#endif
740
 
741
    default:
742
      return -1; // button function not mapped to physical button
743
  }
744
 
745
  // request display update
159 tk 746
  seq_ui_display_update_req = 1;
134 tk 747
 
748
  return 0; // no error
749
}
750
 
751
 
752
/////////////////////////////////////////////////////////////////////////////
753
// Encoder handler
754
/////////////////////////////////////////////////////////////////////////////
755
s32 SEQ_UI_Encoder_Handler(u32 encoder, s32 incrementer)
756
{
757
  if( encoder > 16 )
758
    return -1; // encoder doesn't exist
759
 
760
  // limit incrementer
761
  if( incrementer > 3 )
762
    incrementer = 3;
763
  else if( incrementer < -3 )
764
    incrementer = -3;
765
 
766
  if( encoder == 0 ) {
168 tk 767
    // forward to menu page
768
    if( ui_encoder_callback != NULL )
769
      ui_encoder_callback(SEQ_UI_ENCODER_Datawheel, incrementer);
134 tk 770
  } else {
167 tk 771
    // forward to menu page
168 tk 772
    if( ui_encoder_callback != NULL )
773
      ui_encoder_callback(encoder-1, incrementer);
134 tk 774
  }
775
 
776
  // request display update
159 tk 777
  seq_ui_display_update_req = 1;
134 tk 778
 
779
  return 0; // no error
780
}
781
 
782
 
783
/////////////////////////////////////////////////////////////////////////////
784
// Update LCD messages
785
// Usually called from background task
786
/////////////////////////////////////////////////////////////////////////////
787
s32 SEQ_UI_LCD_Handler(void)
788
{
159 tk 789
  if( seq_ui_display_init_req ) {
790
    seq_ui_display_init_req = 0; // clear request
134 tk 791
 
792
    // clear both LCDs
793
    int i;
794
    for(i=0; i<2; ++i) {
795
      MIOS32_LCD_DeviceSet(i);
796
      SEQ_LCD_Clear();
797
    }
798
 
168 tk 799
    // select first menu item
800
    ui_selected_item = 0;
801
 
167 tk 802
    // call init function of current page
803
    if( ui_init_callback[ui_page] != NULL )
804
      ui_init_callback[ui_page](0); // mode
134 tk 805
 
806
    // request display update
159 tk 807
    seq_ui_display_update_req = 1;
134 tk 808
  }
809
 
167 tk 810
  // perform high priority LCD update request
168 tk 811
  if( ui_lcd_callback != NULL && !seq_ui_button_state.MENU_PAGE_DISPLAYED )
167 tk 812
    ui_lcd_callback(1); // high_prio
813
 
814
  // perform low priority LCD update request if requested
159 tk 815
  if( seq_ui_display_update_req ) {
816
    seq_ui_display_update_req = 0; // clear request
134 tk 817
 
168 tk 818
    // menu page is visible until MENU button has been released, or first page has been selected
819
    if( seq_ui_button_state.MENU_PAGE_DISPLAYED ) {
820
      // print available menu pages
821
      MIOS32_LCD_DeviceSet(0);
822
      MIOS32_LCD_CursorSet(0, 0);
823
      //                      <-------------------------------------->
824
      //                      0123456789012345678901234567890123456789
825
      MIOS32_LCD_PrintString("                                        ");
826
      MIOS32_LCD_CursorSet(0, 1);
827
      MIOS32_LCD_PrintString("Mix  Evnt Mode Dir. Div. Len. Trn. Grv. ");
828
 
829
      MIOS32_LCD_DeviceSet(1);
830
      MIOS32_LCD_CursorSet(0, 0);
831
      //                      <-------------------------------------->
832
      //                      0123456789012345678901234567890123456789
833
      MIOS32_LCD_PrintString("                                        ");
834
      MIOS32_LCD_CursorSet(0, 1);
835
      MIOS32_LCD_PrintString("Trg.  Fx  Man. Mrp. BPM  Save MIDI SysEx");
836
    } else {
837
      if( ui_lcd_callback != NULL )
838
    ui_lcd_callback(0); // no high_prio
839
    }
134 tk 840
  }
841
 
159 tk 842
  // for debugging
843
#if 0
844
  MIOS32_LCD_DeviceSet(0);
845
  MIOS32_LCD_CursorSet(0, 0);
846
  MIOS32_LCD_PrintFormattedString("%5d  ", seq_midi_queue_size);
847
#endif
848
 
167 tk 849
#if 0
166 tk 850
  u32 bpm_tick = SEQ_BPM_TickGet();
851
  u32 bpm_sub = bpm_tick % SEQ_BPM_RESOLUTION_PPQN;
852
  u32 bpm_16th = (bpm_tick / (SEQ_BPM_RESOLUTION_PPQN/4)) % 16;
853
  u32 bpm_qn = (bpm_tick / SEQ_BPM_RESOLUTION_PPQN) % 4;
854
  u32 bpm_n = bpm_tick / (4*SEQ_BPM_RESOLUTION_PPQN);
855
  MIOS32_LCD_DeviceSet(0);
856
  MIOS32_LCD_CursorSet(0, 0);
857
  MIOS32_LCD_PrintFormattedString("%3d.%2d.%2d.%3d  ", bpm_n, bpm_qn, bpm_16th, bpm_sub);
858
#endif
859
 
134 tk 860
  return 0; // no error
861
}
862
 
863
 
864
 
865
/////////////////////////////////////////////////////////////////////////////
866
// Update all LEDs
867
// Usually called from background task
868
/////////////////////////////////////////////////////////////////////////////
869
s32 SEQ_UI_LED_Handler(void)
870
{
871
  u8 visible_track = SEQ_UI_VisibleTrackGet();
872
 
873
  // track LEDs
167 tk 874
  SEQ_LED_PinSet(LED_TRACK1, (ui_selected_tracks & (1 << 0)));
875
  SEQ_LED_PinSet(LED_TRACK2, (ui_selected_tracks & (1 << 1)));
876
  SEQ_LED_PinSet(LED_TRACK3, (ui_selected_tracks & (1 << 2)));
877
  SEQ_LED_PinSet(LED_TRACK4, (ui_selected_tracks & (1 << 3)));
134 tk 878
 
879
  // parameter layer LEDs
167 tk 880
  SEQ_LED_PinSet(LED_PAR_LAYER_A, (ui_selected_par_layer == 0));
881
  SEQ_LED_PinSet(LED_PAR_LAYER_B, (ui_selected_par_layer == 1));
882
  SEQ_LED_PinSet(LED_PAR_LAYER_C, (ui_selected_par_layer == 2));
134 tk 883
 
884
  // group LEDs
167 tk 885
  SEQ_LED_PinSet(LED_GROUP1, (ui_selected_group == 0));
886
  SEQ_LED_PinSet(LED_GROUP2, (ui_selected_group == 1));
887
  SEQ_LED_PinSet(LED_GROUP3, (ui_selected_group == 2));
888
  SEQ_LED_PinSet(LED_GROUP4, (ui_selected_group == 3));
134 tk 889
 
890
  // trigger layer LEDs
167 tk 891
  SEQ_LED_PinSet(LED_TRG_LAYER_A, (ui_selected_trg_layer == 0));
892
  SEQ_LED_PinSet(LED_TRG_LAYER_B, (ui_selected_trg_layer == 1));
893
  SEQ_LED_PinSet(LED_TRG_LAYER_C, (ui_selected_trg_layer == 2));
134 tk 894
 
895
  // remaining LEDs
167 tk 896
  SEQ_LED_PinSet(LED_EDIT, ui_page == SEQ_UI_PAGE_EDIT);
134 tk 897
  SEQ_LED_PinSet(LED_MUTE, 0);
898
  SEQ_LED_PinSet(LED_PATTERN, 0);
899
  SEQ_LED_PinSet(LED_SONG, 0);
900
 
901
  SEQ_LED_PinSet(LED_SOLO, 0);
902
  SEQ_LED_PinSet(LED_FAST, 0);
903
  SEQ_LED_PinSet(LED_ALL, 0);
904
 
166 tk 905
  SEQ_LED_PinSet(LED_PLAY, seq_core_state.RUN);
906
  SEQ_LED_PinSet(LED_STOP, !seq_core_state.RUN);
907
  SEQ_LED_PinSet(LED_PAUSE, seq_core_state.PAUSE);
134 tk 908
 
167 tk 909
  SEQ_LED_PinSet(LED_STEP_1_16, (ui_selected_step_view == 0));
910
  SEQ_LED_PinSet(LED_STEP_17_32, (ui_selected_step_view == 1)); // will be obsolete in MBSEQ V4
134 tk 911
 
167 tk 912
  SEQ_LED_PinSet(LED_MENU, seq_ui_button_state.MENU_PRESSED);
913
  SEQ_LED_PinSet(LED_SCRUB, 0);
914
  SEQ_LED_PinSet(LED_METRONOME, 0);
134 tk 915
 
167 tk 916
  // note: the background function is permanently interrupted - therefore we write the GP pattern
917
  // into a temporary variable, and take it over once completed
918
  u16 new_ui_gp_leds = 0x0000;
919
  u16 new_ui_gp_leds_flashing = 0x0000;  
920
  if( seq_ui_button_state.MENU_PRESSED ) {
921
    // MENU button overruling - find out the selected menu (if accessible via MENU button)
922
    int i;
923
    for(i=0; i<16; ++i)
924
      if(ui_page == ui_direct_access_menu_pages[i])
925
    new_ui_gp_leds |= (1 << i);
926
  } else {
927
    // request GP LED values from current menu page
928
    // will be transfered to DOUT registers in SEQ_UI_LED_Handler_Periodic
929
    new_ui_gp_leds = 0x0000;
930
    new_ui_gp_leds_flashing = 0x0000;
931
 
168 tk 932
    if( ui_led_callback != NULL )
933
      ui_led_callback(&new_ui_gp_leds, &new_ui_gp_leds_flashing);
167 tk 934
  }
935
  ui_gp_leds = new_ui_gp_leds;
936
  ui_gp_leds_flashing = new_ui_gp_leds_flashing;
937
 
134 tk 938
  return 0; // no error
939
}
940
 
941
 
942
/////////////////////////////////////////////////////////////////////////////
943
// updates high-prio LED functions (GP LEDs and Beat LED)
168 tk 944
// called each mS
134 tk 945
/////////////////////////////////////////////////////////////////////////////
946
s32 SEQ_UI_LED_Handler_Periodic()
947
{
948
  // GP LEDs are only updated when ui_gp_leds or pos_marker_mask has changed
949
  static u16 prev_ui_gp_leds = 0x0000;
950
  static u16 prev_pos_marker_mask = 0x0000;
951
 
952
  // beat LED: tmp. for demo w/o real sequencer
167 tk 953
  SEQ_LED_PinSet(LED_BEAT, (seq_core_state.RUN && (seq_core_state.ref_step & 3) == 0));
134 tk 954
 
955
  // for song position marker (supports 16 LEDs, check for selected step view)
956
  u16 pos_marker_mask = 0x0000;
166 tk 957
  u8 played_step = seq_core_trk[SEQ_UI_VisibleTrackGet()].step;
958
  if( seq_core_state.RUN && (played_step >> 4) == ui_selected_step_view )
134 tk 959
    pos_marker_mask = 1 << (played_step & 0xf);
960
 
168 tk 961
  // apply flash mask
962
  u16 ui_gp_leds_flashed = ui_gp_leds;
963
  if( ui_cursor_flash_ctr >= SEQ_UI_CURSOR_FLASH_CTR_LED_OFF )
964
    ui_gp_leds_flashed &= ~ui_gp_leds_flashing;
965
 
134 tk 966
  // exit of pattern hasn't changed
168 tk 967
  if( prev_ui_gp_leds == ui_gp_leds_flashed && prev_pos_marker_mask == pos_marker_mask )
134 tk 968
    return 0;
168 tk 969
  prev_ui_gp_leds = ui_gp_leds_flashed;
134 tk 970
  prev_pos_marker_mask = pos_marker_mask;
971
 
972
  // transfer to GP LEDs
973
 
974
#ifdef DEFAULT_GP_DOUT_SR_L
975
# ifdef DEFAULT_GP_DOUT_SR_L2
168 tk 976
  SEQ_LED_SRSet(DEFAULT_GP_DOUT_SR_L-1, (ui_gp_leds_flashed >> 0) & 0xff);
134 tk 977
# else
168 tk 978
  SEQ_LED_SRSet(DEFAULT_GP_DOUT_SR_L-1, ((ui_gp_leds_flashed ^ pos_marker_mask) >> 0) & 0xff);
134 tk 979
# endif
980
#endif
981
#ifdef DEFAULT_GP_DOUT_SR_R
982
# ifdef DEFAULT_GP_DOUT_SR_R2
168 tk 983
  SEQ_LED_SRSet(DEFAULT_GP_DOUT_SR_R-1, (ui_gp_leds_flashed >> 8) & 0xff);
134 tk 984
#else
168 tk 985
  SEQ_LED_SRSet(DEFAULT_GP_DOUT_SR_R-1, ((ui_gp_leds_flashed ^ pos_marker_mask) >> 8) & 0xff);
134 tk 986
#endif
987
#endif
988
 
989
#ifdef DEFAULT_GP_DOUT_SR_L2
990
  SEQ_LED_SRSet(DEFAULT_GP_DOUT_SR_L2-1, (pos_marker_mask >> 0) & 0xff);
991
#endif
992
#ifdef DEFAULT_GP_DOUT_SR_R2
993
  SEQ_LED_SRSet(DEFAULT_GP_DOUT_SR_R2-1, (pos_marker_mask >> 8) & 0xff);
994
#endif
995
 
996
#if DEFAULT_SRM_ENABLED && DEFAULT_SRM_DOUT_M_MAPPING == 1
997
  // for wilba's frontpanel
998
 
999
  // BLM8X8 DOUT -> GP LED mapping
1000
  // 0 = 15,16  1 = 13,14   2 = 11,12   3 = 9,10
1001
  // 4 = 1,2    5 = 3,4     6 = 5,6     7 = 7,8
1002
 
1003
  // bit 7: first green (i.e. GP1-G)
1004
  // bit 6: first red (i.e. GP1-R)
1005
  // bit 5: second green (i.e. GP2-G)
1006
  // bit 4: second red (i.e. GP2-R)
1007
 
1008
  // this mapping routine takes ca. 5 uS
168 tk 1009
  // since it's only executed when ui_gp_leds_flashed or gp_mask has changed, it doesn't really hurt
134 tk 1010
 
168 tk 1011
  u16 modified_gp_leds = ui_gp_leds_flashed;
134 tk 1012
#if 1
1013
  // extra: red LED is lit exclusively for higher contrast
1014
  modified_gp_leds &= ~pos_marker_mask;
1015
#endif
1016
 
1017
  int sr;
1018
  const u8 blm8x8_sr_map[8] = {4, 5, 6, 7, 3, 2, 1, 0};
1019
  u16 gp_mask = 1 << 0;
1020
  for(sr=0; sr<8; ++sr) {
1021
    u8 pattern = 0;
1022
 
1023
    if( modified_gp_leds & gp_mask )
1024
      pattern |= 0x80;
1025
    if( pos_marker_mask & gp_mask )
1026
      pattern |= 0x40;
1027
    gp_mask <<= 1;
1028
    if( modified_gp_leds & gp_mask )
1029
      pattern |= 0x20;
1030
    if( pos_marker_mask & gp_mask )
1031
      pattern |= 0x10;
1032
    gp_mask <<= 1;
1033
 
1034
    u8 mapped_sr = blm8x8_sr_map[sr];
1035
    blm8x8_led_row[mapped_sr] = (blm8x8_led_row[mapped_sr] & 0x0f) | pattern;
1036
  }
1037
#endif
1038
 
1039
}
1040
 
1041
 
1042
/////////////////////////////////////////////////////////////////////////////
168 tk 1043
// for menu handling (e.g. flashing cursor, doubleclick counter, etc...)
1044
// called each mS
1045
/////////////////////////////////////////////////////////////////////////////
1046
s32 SEQ_UI_MENU_Handler_Periodic()
1047
{
1048
  if( ++ui_cursor_flash_ctr >= SEQ_UI_CURSOR_FLASH_CTR_MAX ) {
1049
    ui_cursor_flash_ctr = 0;
1050
    seq_ui_display_update_req = 1;
1051
  } else if( ui_cursor_flash_ctr == SEQ_UI_CURSOR_FLASH_CTR_LED_OFF )
1052
    seq_ui_display_update_req = 1;
1053
 
1054
  return 0;
1055
}
1056
 
1057
 
1058
/////////////////////////////////////////////////////////////////////////////
134 tk 1059
// Returns the currently visible track
1060
/////////////////////////////////////////////////////////////////////////////
1061
u8 SEQ_UI_VisibleTrackGet(void)
1062
{
1063
  u8 offset = 0;
1064
 
1065
  if( ui_selected_tracks & (1 << 3) )
1066
    offset = 3;
1067
  if( ui_selected_tracks & (1 << 2) )
1068
    offset = 2;
1069
  if( ui_selected_tracks & (1 << 1) )
1070
    offset = 1;
1071
  if( ui_selected_tracks & (1 << 0) )
1072
    offset = 0;
1073
 
1074
  return 4*ui_selected_group + offset;
1075
}
1076
 
168 tk 1077
 
1078
/////////////////////////////////////////////////////////////////////////////
1079
// Increments the selected tracks/groups
1080
// OUT: 1 if value has been changed, otherwise 0
1081
/////////////////////////////////////////////////////////////////////////////
1082
s32 SEQ_UI_GxTyInc(s32 incrementer)
1083
{
1084
  int gxty = SEQ_UI_VisibleTrackGet();
1085
  int prev_gxty = gxty;
1086
 
1087
  if( incrementer >= 0 ) {
1088
    if( (gxty += incrementer) >= SEQ_CORE_NUM_TRACKS )
1089
      gxty = SEQ_CORE_NUM_TRACKS-1;
1090
  } else {
1091
    if( (gxty += incrementer) < 0 )
1092
      gxty = 0;
1093
  }
1094
 
1095
  if( gxty == prev_gxty )
1096
    return 0; // no change
1097
 
1098
  ui_selected_tracks = 1 << (gxty % 4);
1099
  ui_selected_group = gxty / 4;
1100
 
1101
  return 1; // value changed
1102
}
1103
 
1104
 
1105
/////////////////////////////////////////////////////////////////////////////
1106
// Increments a CC within given min/max range
1107
// OUT: 1 if value has been changed, otherwise 0
1108
/////////////////////////////////////////////////////////////////////////////
1109
s32 SEQ_UI_CCInc(u8 cc, u16 min, u16 max, s32 incrementer)
1110
{
1111
  u8 visible_track = SEQ_UI_VisibleTrackGet();
1112
  int value = SEQ_CC_Get(visible_track, cc);
1113
  int prev_value = value;
1114
 
1115
  if( incrementer >= 0 ) {
1116
    if( (value += incrementer) >= max )
1117
      value = max;
1118
  } else {
1119
    if( (value += incrementer) < min )
1120
      value = min;
1121
  }
1122
 
1123
  if( value == prev_value )
1124
    return 0; // no change
1125
 
1126
  SEQ_CC_Set(visible_track, cc, value);
1127
 
1128
  return 1; // value changed
1129
}
1130