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