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