///////////////////////////////////////////////////////////////////////////// // Local LED handler function ///////////////////////////////////////////////////////////////////////////// static s32 LED_Handler(u16 *gp_leds) { u8 track; if( seq_ui_button_state.CHANGE_ALL_STEPS ) { u8 visible_track = SEQ_UI_VisibleTrackGet(); *gp_leds = 0; u16 all_layers_muted_mask = 0; int track; for(track=0; track<SEQ_CORE_NUM_TRACKS; ++track) all_layers_muted_mask |= seq_core_trk[track].layer_muted; #if 1 if( seq_core_trk_muted == 0xffff ) *gp_leds |= 0x0003; if( seq_core_trk[visible_track].layer_muted == 0xffff ) *gp_leds |= 0x001c; if( seq_core_trk_muted == 0xffff && all_layers_muted_mask == 0xffff ) *gp_leds |= 0x00e0; if( seq_core_trk_muted == 0x0000 ) *gp_leds |= 0x0300; if( seq_core_trk[visible_track].layer_muted == 0x0000 ) *gp_leds |= 0x1c00; if( seq_core_trk_muted == 0x0000 && all_layers_muted_mask == 0x0000 ) *gp_leds |= 0xe000; #else // Better? Mayber to difficult to understand for users, therefore disabled by default // e.g. all tracks muted: activate LEDs of the "all tracks unmuted" button. // it should signal: something will happen when you push here... if( seq_core_trk_muted == 0xffff ) *gp_leds |= 0x0300; if( seq_core_trk[visible_track].layer_muted == 0xffff ) *gp_leds |= 0x1c00; if( seq_core_trk_muted == 0xffff && all_layers_muted_mask == 0xffff ) *gp_leds |= 0xe000; if( seq_core_trk_muted == 0x0000 ) *gp_leds |= 0x0003; if( seq_core_trk[visible_track].layer_muted == 0x0000 ) *gp_leds |= 0x001c; if( seq_core_trk_muted == 0x0000 && all_layers_muted_mask == 0x0000 ) *gp_leds |= 0x00e0; #endif } else if( !ui_cursor_flash && seq_ui_button_state.SELECT_PRESSED ) { *gp_leds = latched_mute; } else { if( seq_ui_button_state.MUTE_PRESSED ) { track = SEQ_UI_VisibleTrackGet(); *gp_leds = seq_core_trk[track].layer_muted | seq_core_trk[track].layer_muted_from_midi; } else { *gp_leds = seq_core_trk_muted; } } return 0; // no error }
///////////////////////////////////////////////////////////////////////////// // Local LED handler function ///////////////////////////////////////////////////////////////////////////// static s32 LED_Handler(u16 *gp_leds) { if( ui_cursor_flash ) // if flashing flag active: no LED flag set return 0; switch( ui_selected_item ) { case ITEM_GXTY: *gp_leds = 0x0001; break; case ITEM_WAVEFORM: *gp_leds = 0x0002; break; case ITEM_AMPLITUDE: *gp_leds = 0x0004; break; case ITEM_PHASE: *gp_leds = 0x0008; break; case ITEM_STEPS: *gp_leds = 0x0010; break; case ITEM_STEPS_RST: *gp_leds = 0x0020; break; case ITEM_ENABLE_ONE_SHOT: *gp_leds = 0x0040; break; case ITEM_ENABLE_NOTE: *gp_leds = 0x0100; break; case ITEM_ENABLE_VELOCITY: *gp_leds = 0x0200; break; case ITEM_ENABLE_LENGTH: *gp_leds = 0x0400; break; case ITEM_ENABLE_CC: *gp_leds = 0x0800; break; case ITEM_CC: *gp_leds = 0x2000; break; case ITEM_CC_OFFSET: *gp_leds = 0x2000; break; case ITEM_CC_PPQN: *gp_leds = 0x8000; break; } #if 0 // inconsistent and doesn't look so nice u8 visible_track = SEQ_UI_VisibleTrackGet(); u8 flags = SEQ_CC_Get(visible_track, SEQ_CC_LFO_ENABLE_FLAGS); *gp_leds |= (((u16)(flags & 0x1e)) << 7) | (((u16)(flags & 0x01)) << 6); #endif return 0; // no error }
///////////////////////////////////////////////////////////////////////////// // Local button callback function // Should return: // 1 if value has been changed // 0 if value hasn't been changed // -1 if invalid or unsupported button ///////////////////////////////////////////////////////////////////////////// static s32 Button_Handler(seq_ui_button_t button, s32 depressed) { if( button <= SEQ_UI_BUTTON_GP16 ) { if( !seq_midi_in_options[selected_bus].MODE_PLAY ) return -1; u8 visible_track = SEQ_UI_VisibleTrackGet(); mios32_midi_package_t p; if( depressed ) gp_button_pressed &= ~(1 << button); else gp_button_pressed |= (1 << button); p.type = NoteOn; p.event = NoteOn; p.chn = Chn1; // will be overruled anyhow by SEQ_LIVE_PlayEvent() p.note = 0x30 + (u8)button; p.velocity = depressed ? 0x00 : seq_live_options.VELOCITY; SEQ_LIVE_PlayEvent(visible_track, p); return 0; } // exit if button depressed if( depressed ) return -1; // remaining buttons: switch( button ) { case SEQ_UI_BUTTON_Select: case SEQ_UI_BUTTON_Right: if( ++ui_selected_item >= NUM_OF_ITEMS ) ui_selected_item = 0; return 1; // value always changed case SEQ_UI_BUTTON_Left: if( ui_selected_item == 0 ) ui_selected_item = NUM_OF_ITEMS-1; else --ui_selected_item; return 1; // value always changed case SEQ_UI_BUTTON_Up: return Encoder_Handler(SEQ_UI_ENCODER_Datawheel, 1); case SEQ_UI_BUTTON_Down: return Encoder_Handler(SEQ_UI_ENCODER_Datawheel, -1); } return -1; // invalid or unsupported button }
///////////////////////////////////////////////////////////////////////////// // Local LED handler function ///////////////////////////////////////////////////////////////////////////// static s32 LED_Handler(u16 *gp_leds) { if( ui_cursor_flash ) // if flashing flag active: no LED flag set return 0; u8 visible_track = SEQ_UI_VisibleTrackGet(); u8 event_mode = SEQ_CC_Get(visible_track, SEQ_CC_MIDI_EVENT_MODE); if( event_mode == SEQ_EVENT_MODE_Drum ) *gp_leds = 1 << ui_selected_instrument; else *gp_leds = 1 << ui_selected_trg_layer; return 0; // no error }
///////////////////////////////////////////////////////////////////////////// // Local LED handler function ///////////////////////////////////////////////////////////////////////////// static s32 LED_Handler(u16 *gp_leds) { if( ui_cursor_flash ) // if flashing flag active: no LED flag set return 0; u8 visible_track = SEQ_UI_VisibleTrackGet(); int num_steps = SEQ_TRG_NumStepsGet(visible_track); if( num_steps > 128 ) *gp_leds = 1 << ui_selected_step_view; else if( num_steps > 64 ) *gp_leds = 3 << (2*ui_selected_step_view); else *gp_leds = 15 << (4*ui_selected_step_view); return 0; // no error }
///////////////////////////////////////////////////////////////////////////// // Local LED handler function ///////////////////////////////////////////////////////////////////////////// static s32 LED_Handler(u16 *gp_leds) { u8 track; if( !ui_cursor_flash && seq_ui_button_state.SELECT_PRESSED ) { *gp_leds = latched_mute; } else { if( seq_ui_button_state.MUTE_PRESSED ) { track = SEQ_UI_VisibleTrackGet(); *gp_leds = seq_core_trk[track].layer_muted; } else { *gp_leds = seq_core_trk_muted; } } return 0; // no error }
///////////////////////////////////////////////////////////////////////////// // Local LED handler function ///////////////////////////////////////////////////////////////////////////// static s32 LED_Handler(u16 *gp_leds) { if( ui_cursor_flash ) // if flashing flag active: no LED flag set return 0; switch( ui_selected_item ) { case ITEM_GXTY: *gp_leds = 0x0001; break; case ITEM_LENGTH: *gp_leds = 0x0006; break; case ITEM_LOOP: *gp_leds = 0x0018; break; case ITEM_QUICKSEL_MODE: *gp_leds = 0x00c0; break; } s32 quicksel_item = QUICKSEL_SearchItem(SEQ_UI_VisibleTrackGet()); if( quicksel_item >= 0 ) *gp_leds |= 1 << (quicksel_item+8); return 0; // no error }
///////////////////////////////////////////////////////////////////////////// // Local encoder callback function // Should return: // 1 if value has been changed // 0 if value hasn't been changed // -1 if invalid or unsupported encoder ///////////////////////////////////////////////////////////////////////////// static s32 Encoder_Handler(seq_ui_encoder_t encoder, s32 incrementer) { u8 visible_track = SEQ_UI_VisibleTrackGet(); u8 event_mode = SEQ_CC_Get(visible_track, SEQ_CC_MIDI_EVENT_MODE); if( encoder <= SEQ_UI_ENCODER_GP16 ) { // select new layer/instrument if( event_mode == SEQ_EVENT_MODE_Drum ) { if( encoder >= SEQ_TRG_NumInstrumentsGet(visible_track) ) return -1; ui_selected_instrument = encoder; } else { if( encoder >= SEQ_TRG_NumLayersGet(visible_track) ) return -1; ui_selected_trg_layer = encoder; } if( seq_hwcfg_button_beh.par_layer ) { // if toggle function active: jump back to previous menu // this is especially useful for the emulated MBSEQ, where we can only click on a single button // (trigger gets deactivated when clicking on GP button or moving encoder) seq_ui_button_state.TRG_LAYER_SEL = 0; SEQ_UI_PageSet(ui_trglayer_prev_page); } return 1; // value changed } else if( encoder == SEQ_UI_ENCODER_Datawheel ) { if( event_mode == SEQ_EVENT_MODE_Drum ) { return SEQ_UI_Var8_Inc(&ui_selected_instrument, 0, SEQ_TRG_NumInstrumentsGet(visible_track)-1, incrementer); } else { return SEQ_UI_Var8_Inc(&ui_selected_trg_layer, 0, SEQ_TRG_NumLayersGet(visible_track)-1, incrementer); } } return -1; // invalid or unsupported encoder }
///////////////////////////////////////////////////////////////////////////// // Local LED handler function ///////////////////////////////////////////////////////////////////////////// static s32 LED_Handler(u16 *gp_leds) { if( ui_cursor_flash ) // if flashing flag active: no LED flag set return 0; switch( ui_selected_item ) { case ITEM_GXTY: *gp_leds = 0x0001; break; case ITEM_MODE: { int selected_mode = SEQ_CC_Get(SEQ_UI_VisibleTrackGet(), SEQ_CC_MODE); *gp_leds = (1 << (selected_mode+1)); } break; case ITEM_BUS: *gp_leds = 0x0080; break; case ITEM_HOLD: *gp_leds = 0x0100; break; case ITEM_SORT: *gp_leds = 0x0200; break; case ITEM_RESTART: *gp_leds = 0x0c00; break; case ITEM_FORCE_SCALE: *gp_leds = 0x3000; break; case ITEM_SUSTAIN: *gp_leds = 0xc000; break; } return 0; // no error }
///////////////////////////////////////////////////////////////////////////// // Local button callback function // Should return: // 1 if value has been changed // 0 if value hasn't been changed // -1 if invalid or unsupported button ///////////////////////////////////////////////////////////////////////////// static s32 Button_Handler(seq_ui_button_t button, s32 depressed) { if( depressed ) return 0; // ignore when button depressed if( button <= SEQ_UI_BUTTON_GP8 || button == SEQ_UI_BUTTON_Select ) { if( button != SEQ_UI_BUTTON_Select ) ui_selected_item = button / 2; SEQ_UI_Msg(SEQ_UI_MSG_USER_R, 10000, "Sending Informations", "to MIOS Terminal!"); switch( ui_selected_item + list_view_offset ) { ////////////////////////////////////////////////////////////////////////////////////////////// case LIST_ITEM_SYSTEM: SEQ_TERMINAL_PrintSystem(DEBUG_MSG); break; ////////////////////////////////////////////////////////////////////////////////////////////// case LIST_ITEM_GLOBALS: SEQ_TERMINAL_PrintGlobalConfig(DEBUG_MSG); break; ////////////////////////////////////////////////////////////////////////////////////////////// case LIST_ITEM_CONFIG: SEQ_TERMINAL_PrintSessionConfig(DEBUG_MSG); break; ////////////////////////////////////////////////////////////////////////////////////////////// case LIST_ITEM_TRACKS: SEQ_TERMINAL_PrintTracks(DEBUG_MSG); break; ////////////////////////////////////////////////////////////////////////////////////////////// case LIST_ITEM_TRACK_INFO: SEQ_TERMINAL_PrintTrack(DEBUG_MSG, SEQ_UI_VisibleTrackGet()); break; ////////////////////////////////////////////////////////////////////////////////////////////// case LIST_ITEM_MIXER_MAP: SEQ_TERMINAL_PrintCurrentMixerMap(DEBUG_MSG); break; ////////////////////////////////////////////////////////////////////////////////////////////// case LIST_ITEM_SONG: SEQ_TERMINAL_PrintCurrentSong(DEBUG_MSG); break; ////////////////////////////////////////////////////////////////////////////////////////////// case LIST_ITEM_GROOVES: SEQ_TERMINAL_PrintGrooveTemplates(DEBUG_MSG); break; ////////////////////////////////////////////////////////////////////////////////////////////// case LIST_ITEM_BOOKMARKS: SEQ_TERMINAL_PrintBookmarks(DEBUG_MSG); break; ////////////////////////////////////////////////////////////////////////////////////////////// case LIST_ITEM_SD_CARD: SEQ_TERMINAL_PrintSdCardInfo(DEBUG_MSG); break; ////////////////////////////////////////////////////////////////////////////////////////////// case LIST_ITEM_NETWORK: #if !defined(MIOS32_FAMILY_EMULATION) UIP_TERMINAL_PrintNetwork(DEBUG_MSG); #endif break; ////////////////////////////////////////////////////////////////////////////////////////////// default: DEBUG_MSG("No informations available."); } SEQ_UI_Msg(SEQ_UI_MSG_USER_R, 1000, "Sent Informations", "to MIOS Terminal!"); return 1; } if( button >= SEQ_UI_BUTTON_GP9 && button <= SEQ_UI_BUTTON_GP16 ) { // re-using encoder handler return Encoder_Handler(button, 0); } switch( button ) { case SEQ_UI_BUTTON_Right: case SEQ_UI_BUTTON_Up: return Encoder_Handler(SEQ_UI_ENCODER_Datawheel, 1); case SEQ_UI_BUTTON_Left: case SEQ_UI_BUTTON_Down: return Encoder_Handler(SEQ_UI_ENCODER_Datawheel, -1); } return -1; // invalid or unsupported button }
///////////////////////////////////////////////////////////////////////////// // Local encoder callback function // Should return: // 1 if value has been changed // 0 if value hasn't been changed // -1 if invalid or unsupported encoder ///////////////////////////////////////////////////////////////////////////// static s32 Encoder_Handler(seq_ui_encoder_t encoder, s32 incrementer) { #if 0 // leads to: comparison is always true due to limited range of data type if( (encoder >= SEQ_UI_ENCODER_GP1 && encoder <= SEQ_UI_ENCODER_GP16) ) { #else if( encoder <= SEQ_UI_ENCODER_GP16 ) { #endif if( seq_ui_button_state.SELECT_PRESSED && !seq_ui_button_state.CHANGE_ALL_STEPS ) { // select button pressed: indirect MUTED flag modification (taken over when select button depressed) u16 mask = 1 << encoder; if( incrementer < 0 || (incrementer == 0 && !(latched_mute & mask)) ) latched_mute |= mask; else latched_mute &= ~mask; } else { // select button not pressed: direct MUTED flag modification // access to seq_core_trk[] must be atomic! portENTER_CRITICAL(); u8 visible_track = SEQ_UI_VisibleTrackGet(); u16 mask = 1 << encoder; u16 *muted = (u16 *)&seq_core_trk_muted; if( seq_ui_button_state.CHANGE_ALL_STEPS ) { switch( encoder ) { case SEQ_UI_ENCODER_GP1: case SEQ_UI_ENCODER_GP2: *muted = 0xffff; SEQ_UI_Msg(SEQ_UI_MSG_USER, 1000, "All Tracks", "muted"); break; case SEQ_UI_ENCODER_GP3: case SEQ_UI_ENCODER_GP4: case SEQ_UI_ENCODER_GP5: muted = (u16 *)&seq_core_trk[visible_track].layer_muted; *muted = 0xffff; SEQ_UI_Msg(SEQ_UI_MSG_USER, 1000, "All Layers", "of current Track muted"); break; case SEQ_UI_ENCODER_GP6: case SEQ_UI_ENCODER_GP7: case SEQ_UI_ENCODER_GP8: { *muted = 0xffff; int track; for(track=0; track<SEQ_CORE_NUM_TRACKS; ++track) { seq_core_trk[track].layer_muted = 0xffff; } SEQ_UI_Msg(SEQ_UI_MSG_USER, 1000, "All Layers", "and Tracks muted"); } break; case SEQ_UI_ENCODER_GP9: case SEQ_UI_ENCODER_GP10: *muted = 0x0000; SEQ_UI_Msg(SEQ_UI_MSG_USER_R, 1000, "All Tracks", "unmuted"); break; case SEQ_UI_ENCODER_GP11: case SEQ_UI_ENCODER_GP12: case SEQ_UI_ENCODER_GP13: muted = (u16 *)&seq_core_trk[visible_track].layer_muted; *muted = 0x0000; SEQ_UI_Msg(SEQ_UI_MSG_USER_R, 1000, "All Layers", "of current Track unmuted"); break; case SEQ_UI_ENCODER_GP14: case SEQ_UI_ENCODER_GP15: case SEQ_UI_ENCODER_GP16: { *muted = 0x0000; int track; for(track=0; track<SEQ_CORE_NUM_TRACKS; ++track) { seq_core_trk[track].layer_muted = 0x0000; } SEQ_UI_Msg(SEQ_UI_MSG_USER_R, 1000, "All Layers", "and Tracks unmuted"); } break; } } else { if( seq_ui_button_state.MUTE_PRESSED ) muted = (u16 *)&seq_core_trk[visible_track].layer_muted; else if( SEQ_BPM_IsRunning() ) { // Synched Mutes only when sequencer is running if( !(*muted & mask) && seq_core_options.SYNCHED_MUTE && !seq_ui_button_state.FAST_ENCODERS ) { // Fast button will disable synched mute muted = (u16 *)&seq_core_trk_synched_mute; } else if( (*muted & mask) && seq_core_options.SYNCHED_UNMUTE && !seq_ui_button_state.FAST_ENCODERS ) { // Fast button will disable synched unmute muted = (u16 *)&seq_core_trk_synched_unmute; } } else { // clear synched mutes/unmutes if sequencer not running seq_core_trk_synched_mute = 0; seq_core_trk_synched_unmute = 0; } if( incrementer < 0 ) *muted |= mask; else if( incrementer > 0 ) *muted &= ~mask; else *muted ^= mask; } portEXIT_CRITICAL(); if( muted == ((u16 *)&seq_core_trk_muted) ) { // send to external SEQ_MIDI_IN_ExtCtrlSend(SEQ_MIDI_IN_EXT_CTRL_MUTES, (*muted & mask) ? 127 : 0, encoder); } } return 1; // value changed } return -1; // invalid or unsupported encoder } ///////////////////////////////////////////////////////////////////////////// // Local button callback function // Should return: // 1 if value has been changed // 0 if value hasn't been changed // -1 if invalid or unsupported button ///////////////////////////////////////////////////////////////////////////// static s32 Button_Handler(seq_ui_button_t button, s32 depressed) { #if 0 // leads to: comparison is always true due to limited range of data type if( button >= SEQ_UI_BUTTON_GP1 && button <= SEQ_UI_BUTTON_GP16 ) { #else if( button <= SEQ_UI_BUTTON_GP16 ) { #endif if( depressed ) return 0; // ignore when button depressed // re-using encoder routine return Encoder_Handler(button, 0); } switch( button ) { case SEQ_UI_BUTTON_Select: portENTER_CRITICAL(); if( depressed ) { // select button released: take over latched mutes if( seq_ui_button_state.MUTE_PRESSED ) { u8 visible_track = SEQ_UI_VisibleTrackGet(); seq_core_trk[visible_track].layer_muted = latched_mute; } else { u16 new_mutes = latched_mute & ~seq_core_trk_muted; if( SEQ_BPM_IsRunning() && seq_core_options.SYNCHED_MUTE && !seq_ui_button_state.FAST_ENCODERS ) // Fast button will disable synched mute seq_core_trk_synched_mute |= new_mutes; else seq_core_trk_muted |= new_mutes; u16 new_unmutes = ~latched_mute & seq_core_trk_muted; if( SEQ_BPM_IsRunning() && seq_core_options.SYNCHED_UNMUTE && !seq_ui_button_state.FAST_ENCODERS ) // Fast button will disable synched unmute seq_core_trk_synched_unmute |= new_unmutes; else seq_core_trk_muted &= ~new_unmutes; } } else { // select pressed: init latched mutes which will be taken over once SELECT button released if( seq_ui_button_state.MUTE_PRESSED ) { u8 visible_track = SEQ_UI_VisibleTrackGet(); latched_mute = seq_core_trk[visible_track].layer_muted; } else { latched_mute = seq_core_trk_muted; } } portEXIT_CRITICAL(); return 1; } return -1; // invalid or unsupported button } ///////////////////////////////////////////////////////////////////////////// // Local Display Handler function // IN: <high_prio>: if set, a high-priority LCD update is requested ///////////////////////////////////////////////////////////////////////////// static s32 LCD_Handler(u8 high_prio) { // layout: // 00000000001111111111222222222233333333330000000000111111111122222222223333333333 // 01234567890123456789012345678901234567890123456789012345678901234567890123456789 // <--------------------------------------><--------------------------------------> // > 1< 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 // ...horizontal VU meters... // Mute All screen: // 00000000001111111111222222222233333333330000000000111111111122222222223333333333 // 01234567890123456789012345678901234567890123456789012345678901234567890123456789 // <--------------------------------------><--------------------------------------> // Mute Mute Mute all Tracks Unmute Unmute Unmute all Tracks // all Tracks G1T1 Layers and all Layersall Tracks G1T1 Layers and all Layers if( seq_ui_button_state.CHANGE_ALL_STEPS ) { if( high_prio ) return 0; SEQ_LCD_CursorSet(0, 0); SEQ_LCD_PrintString(" Mute Mute Mute all Tracks Unmute Unmute Unmute all Tracks"); SEQ_LCD_CursorSet(0, 1); SEQ_LCD_PrintString("all Tracks "); SEQ_LCD_PrintGxTy(ui_selected_group, ui_selected_tracks); SEQ_LCD_PrintString(" Layers and all Layersall Tracks "); SEQ_LCD_PrintGxTy(ui_selected_group, ui_selected_tracks); SEQ_LCD_PrintString(" Layers and all Layers"); return 0; } if( high_prio ) { /////////////////////////////////////////////////////////////////////////// // frequently update VU meters SEQ_LCD_CursorSet(0, 1); u8 track; u16 mute_flags = 0; u16 mute_flags_from_midi = 0; if( !ui_cursor_flash && seq_ui_button_state.SELECT_PRESSED ) { mute_flags = latched_mute; } else { if( seq_ui_button_state.MUTE_PRESSED ) { u8 visible_track = SEQ_UI_VisibleTrackGet(); mute_flags = seq_core_trk[visible_track].layer_muted; mute_flags_from_midi = seq_core_trk[visible_track].layer_muted_from_midi; } else { mute_flags = seq_core_trk_muted; } } if( seq_ui_button_state.MUTE_PRESSED ) { u8 layer; u16 mask = (1 << 0); for(layer=0; layer<16; ++layer, mask <<= 1) if( mute_flags_from_midi & mask ) { SEQ_LCD_PrintString("MIDI "); } else if( mute_flags & mask ) { SEQ_LCD_PrintString("Mute "); } else { SEQ_LCD_PrintHBar((seq_layer_vu_meter[layer] >> 3) & 0xf); } } else { int remaining_steps = (seq_core_steps_per_measure - seq_core_state.ref_step) + 1; seq_core_trk_t *t = &seq_core_trk[0]; u16 mask = (1 << 0); for(track=0; track<16; ++t, ++track, mask <<= 1) if( mute_flags & mask ) { if( !seq_ui_button_state.SELECT_PRESSED && (seq_core_trk_synched_unmute & mask) ) { SEQ_LCD_PrintFormattedString("U%3d ", remaining_steps); } else { SEQ_LCD_PrintString("Mute "); } } else { if( !seq_ui_button_state.SELECT_PRESSED && (seq_core_trk_synched_mute & mask) ) { SEQ_LCD_PrintFormattedString("M%3d ", remaining_steps); } else { SEQ_LCD_PrintHBar(t->vu_meter >> 3); } } } } else {
SEQ_LCD_PrintString("Mute "); } } else { if( !seq_ui_button_state.SELECT_PRESSED && (seq_core_trk_synched_mute & mask) ) { SEQ_LCD_PrintFormattedString("M%3d ", remaining_steps); } else { SEQ_LCD_PrintHBar(t->vu_meter >> 3); } } } } else { /////////////////////////////////////////////////////////////////////////// SEQ_LCD_CursorSet(0, 0); u8 track; u8 visible_track = SEQ_UI_VisibleTrackGet(); u8 event_mode = SEQ_CC_Get(visible_track, SEQ_CC_MIDI_EVENT_MODE); u8 num_layers = (event_mode == SEQ_EVENT_MODE_Drum) ? SEQ_TRG_NumInstrumentsGet(visible_track) : SEQ_PAR_NumLayersGet(visible_track); for(track=0; track<16; ++track) { if( ui_cursor_flash && seq_ui_button_state.SELECT_PRESSED ) SEQ_LCD_PrintSpaces(5); else { if( seq_ui_button_state.MUTE_PRESSED ) { if( track >= num_layers ) SEQ_LCD_PrintSpaces(5); else { if( event_mode == SEQ_EVENT_MODE_Drum ) SEQ_LCD_PrintTrackDrum(visible_track, track, (char *)seq_core_trk[visible_track].name); else SEQ_LCD_PrintString(SEQ_PAR_AssignedTypeStr(visible_track, track));
///////////////////////////////////////////////////////////////////////////// // Local encoder callback function // Should return: // 1 if value has been changed // 0 if value hasn't been changed // -1 if invalid or unsupported encoder ///////////////////////////////////////////////////////////////////////////// static s32 Encoder_Handler(seq_ui_encoder_t encoder, s32 incrementer) { u8 visible_track = SEQ_UI_VisibleTrackGet(); int num_steps = SEQ_TRG_NumStepsGet(visible_track); int track_length = (int)SEQ_CC_Get(visible_track, SEQ_CC_LENGTH) + 1; #if 0 // leads to: comparison is always true due to limited range of data type if( (encoder >= SEQ_UI_ENCODER_GP1 && encoder <= SEQ_UI_ENCODER_GP16) ) { #else if( encoder <= SEQ_UI_ENCODER_GP16 ) { #endif if( seq_ui_button_state.SELECT_PRESSED ) { int section; if( num_steps > 128 ) section = encoder / (track_length / 16); else if( num_steps > 64 ) section = encoder / ((2 * track_length) / 16); else section = encoder / ((4 * track_length) / 16); // operation should be atomic (change all selected tracks) u8 track; seq_core_trk_t *t = &seq_core_trk[0]; MIOS32_IRQ_Disable(); for(track=0; track<SEQ_CORE_NUM_TRACKS; ++track, ++t) if( ui_selected_tracks & (1 << track) ) t->play_section = section; MIOS32_IRQ_Enable(); } else { // won't work if Follow function active! if( seq_core_state.FOLLOW ) { // print message and exit SEQ_UI_Msg((encoder <= SEQ_UI_ENCODER_GP8) ? SEQ_UI_MSG_USER : SEQ_UI_MSG_USER_R, 2000, "\"Follow\" active!", "Please deactivate!"); return 1; } } // select new step view ui_selected_step_view = (encoder * (num_steps/16)) / 16; // select step within view if( !seq_ui_button_state.CHANGE_ALL_STEPS ) { // don't change the selected step if ALL function is active, otherwise the ramp can't be changed over multiple views ui_selected_step = (ui_selected_step_view << 4) | (ui_selected_step & 0xf); } if( seq_hwcfg_button_beh.step_view ) { // if toggle function active: jump back to previous menu // this is especially useful for the emulated MBSEQ, where we can only click on a single button // (stepview gets deactivated when clicking on GP button) if( seq_ui_button_state.STEP_VIEW ) { seq_ui_button_state.STEP_VIEW = 0; SEQ_UI_PageSet(ui_stepview_prev_page); } } return 1; // value changed } else if( encoder == SEQ_UI_ENCODER_Datawheel ) { if( SEQ_UI_Var8_Inc(&ui_selected_step_view, 0, (num_steps-1)/16, incrementer) >= 1 ) { // select step within view if( !seq_ui_button_state.CHANGE_ALL_STEPS ) { // don't change the selected step if ALL function is active, otherwise the ramp can't be changed over multiple views ui_selected_step = (ui_selected_step_view << 4) | (ui_selected_step & 0xf); } } else { return 0; } } return -1; // invalid or unsupported encoder } ///////////////////////////////////////////////////////////////////////////// // Local button callback function // Should return: // 1 if value has been changed // 0 if value hasn't been changed // -1 if invalid or unsupported button ///////////////////////////////////////////////////////////////////////////// static s32 Button_Handler(seq_ui_button_t button, s32 depressed) { if( depressed ) return 0; // ignore when button depressed #if 0 // leads to: comparison is always true due to limited range of data type if( button >= SEQ_UI_BUTTON_GP1 && button <= SEQ_UI_BUTTON_GP16 ) { #else if( button <= SEQ_UI_BUTTON_GP16 ) { #endif // -> same handling like for encoders return Encoder_Handler(button, 0); } switch( button ) { case SEQ_UI_BUTTON_Select: return 1; // selects section mode, checked via seq_ui_button_state.SELECT_PRESSED case SEQ_UI_BUTTON_Right: case SEQ_UI_BUTTON_Up: if( depressed ) return 0; // ignore when button depressed return Encoder_Handler(SEQ_UI_ENCODER_Datawheel, 1); case SEQ_UI_BUTTON_Left: case SEQ_UI_BUTTON_Down: if( depressed ) return 0; // ignore when button depressed return Encoder_Handler(SEQ_UI_ENCODER_Datawheel, -1); } return -1; // invalid or unsupported button } ///////////////////////////////////////////////////////////////////////////// // Local Display Handler function // IN: <high_prio>: if set, a high-priority LCD update is requested ///////////////////////////////////////////////////////////////////////////// static s32 LCD_Handler(u8 high_prio) { // layout: // 00000000001111111111222222222233333333330000000000111111111122222222223333333333 // 01234567890123456789012345678901234567890123456789012345678901234567890123456789 // <--------------------------------------><--------------------------------------> // 1 17 33 49 // *... *... *... *... *... *... *... *... *... *... *... *... *... *... *... *... // 5 character usage in 256 step view (5 chars have to display 16 steps, 8 special chars available, // due to this limitation, we only display 15 steps (shouldn't really hurt)) // 43210 43210 43210 43210 43210 // * * * * . . . * . . . * . . . (Small charset) // 5 character usage in 128 step view (5 chars have to display 8 steps): // 43210 43210 43210 43210 43210 // * * . * * . . . (Medium charset) // 5 character usage in 64 step view (5 chars have to display 4 steps): // 43210 43210 43210 43210 43210 // * * * * * (Big charset) u8 visible_track = SEQ_UI_VisibleTrackGet(); u8 event_mode = SEQ_CC_Get(visible_track, SEQ_CC_MIDI_EVENT_MODE); int num_steps = SEQ_TRG_NumStepsGet(visible_track); int steps_per_item = num_steps / 16; int played_step = SEQ_BPM_IsRunning() ? seq_core_trk[visible_track].step : -1; int i; if( !high_prio ) { SEQ_LCD_CursorSet(0, 0); for(i=0; i<16; ++i) if( ((i*steps_per_item) % 16) || ((((i*steps_per_item)/16) == ui_selected_step_view) && ui_cursor_flash) ) SEQ_LCD_PrintSpaces(5); else SEQ_LCD_PrintFormattedString("%-3d ", i*steps_per_item+1); // print flashing *LOOPED* at right corner if loop mode activated to remind that steps will be played differntly if( (ui_cursor_flash_overrun_ctr & 1) && seq_core_state.LOOP ) { SEQ_LCD_CursorSet(71, 0); SEQ_LCD_PrintString(" *LOOPED*"); } else if( (ui_cursor_flash_overrun_ctr & 1) && seq_core_trk[visible_track].play_section > 0 ) { SEQ_LCD_CursorSet(71, 0); SEQ_LCD_PrintFormattedString(" *Sect.%c*", 'A'+seq_core_trk[visible_track].play_section); } else { if( event_mode == SEQ_EVENT_MODE_Drum ) { // print drum name at the rightmost side SEQ_LCD_CursorSet(75, 0); SEQ_LCD_PrintTrackDrum(visible_track, ui_selected_instrument, (char *)seq_core_trk[visible_track].name); } else { // print trigger layer and name at the rightmost side SEQ_LCD_CursorSet(73, 0); SEQ_LCD_PrintFormattedString("%c:%s", 'A' + ui_selected_trg_layer, SEQ_TRG_AssignedTypeStr(visible_track, ui_selected_trg_layer)); } } } SEQ_LCD_CursorSet(0, 1); if( steps_per_item > 8 ) { SEQ_LCD_InitSpecialChars(SEQ_LCD_CHARSET_DrumSymbolsSmall); for(i=0; i<16; ++i) { u16 step = i*steps_per_item; u8 step8 = step / 8; u8 layer = (event_mode == SEQ_EVENT_MODE_Drum) ? 0 : ui_selected_trg_layer; u16 steps = (SEQ_TRG_Get8(visible_track, step8+1, layer, ui_selected_instrument) << 8) | (SEQ_TRG_Get8(visible_track, step8+0, layer, ui_selected_instrument) << 0); if( played_step >= step && played_step < (step+16) ) steps ^= (1 << (played_step % 16)); int j; for(j=0; j<5; ++j) { SEQ_LCD_PrintChar(steps & 0x7); steps >>= 3; } } } else if( steps_per_item > 4 ) {
///////////////////////////////////////////////////////////////////////////// // Receives a MIDI package from APP_NotifyReceivedEvent (-> app.c) ///////////////////////////////////////////////////////////////////////////// s32 SEQ_MIDI_IN_Receive(mios32_midi_port_t port, mios32_midi_package_t midi_package) { s32 status = 0; // check if we should record this event u8 should_be_recorded = ui_page == SEQ_UI_PAGE_TRKREC && ((!seq_midi_in_rec_port || port == seq_midi_in_rec_port) && midi_package.chn == (seq_midi_in_rec_channel-1)); // search for matching ports // status[0] set if at least one port matched // status[1] set if remote function active int bus; for(bus=0; bus<SEQ_MIDI_IN_NUM_BUSSES; ++bus) { // filter MIDI port (if 0: no filter, listen to all ports) if( (!seq_midi_in_port[bus] || port == seq_midi_in_port[bus]) && midi_package.chn == (seq_midi_in_channel[bus]-1) ) { switch( midi_package.event ) { case NoteOff: if( remote_active ) { if( seq_hwcfg_midi_remote.key && midi_package.note == seq_hwcfg_midi_remote.key ) { remote_active = 0; // send "button depressed" state to all remote functions int i; for(i=0; i<128; ++i) SEQ_UI_REMOTE_MIDI_Keyboard(i, 1); // depressed } else { SEQ_UI_REMOTE_MIDI_Keyboard(midi_package.note, 1); // depressed } status |= 2; } else { if( !should_be_recorded && midi_package.note >= seq_midi_in_lower[bus] && (!seq_midi_in_upper[bus] || midi_package.note <= seq_midi_in_upper[bus]) ) { if( seq_midi_in_options[bus].MODE_PLAY ) { MUTEX_MIDIOUT_TAKE; SEQ_CORE_PlayLive(SEQ_UI_VisibleTrackGet(), midi_package); MUTEX_MIDIOUT_GIVE; } else { #if 0 // octave normalisation - too complicated for normal users... mios32_midi_package_t p = midi_package; if( seq_midi_in_lower[bus] ) { // normalize to first octave int normalized_note = 0x30 + p.note - ((int)seq_midi_in_lower[bus]/12)*12; while( normalized_note > 127 ) normalized_note -= 12; while( normalized_note < 0 ) normalized_note += 12; p.note = normalized_note; } SEQ_MIDI_IN_BusReceive(0xf0+bus, p, 0); #else SEQ_MIDI_IN_BusReceive(0xf0+bus, midi_package, 0); #endif } status |= 1; } } break; case NoteOn: if( remote_active ) SEQ_UI_REMOTE_MIDI_Keyboard(midi_package.note, midi_package.velocity ? 0 : 1); // depressed else { if( seq_hwcfg_midi_remote.key && midi_package.note == seq_hwcfg_midi_remote.key ) { remote_active = 1; status |= 2; } else { if( !should_be_recorded && midi_package.note >= seq_midi_in_lower[bus] && (!seq_midi_in_upper[bus] || midi_package.note <= seq_midi_in_upper[bus]) ) { if( seq_midi_in_options[bus].MODE_PLAY ) { MUTEX_MIDIOUT_TAKE; SEQ_CORE_PlayLive(SEQ_UI_VisibleTrackGet(), midi_package); MUTEX_MIDIOUT_GIVE; } else { #if 0 // octave normalisation - too complicated for normal users... mios32_midi_package_t p = midi_package; if( seq_midi_in_lower[bus] ) { // normalize to first octave int normalized_note = 0x30 + p.note - ((int)seq_midi_in_lower[bus]/12)*12; while( normalized_note > 127 ) normalized_note -= 12; while( normalized_note < 0 ) normalized_note += 12; p.note = normalized_note; } SEQ_MIDI_IN_BusReceive(0xf0+bus, p, 0); #else SEQ_MIDI_IN_BusReceive(0xf0+bus, midi_package, 0); #endif } status |= 1; } } } break; case CC: if( !should_be_recorded ) { if( seq_midi_in_options[bus].MODE_PLAY ) { MUTEX_MIDIOUT_TAKE; SEQ_CORE_PlayLive(SEQ_UI_VisibleTrackGet(), midi_package); MUTEX_MIDIOUT_GIVE; } else { SEQ_MIDI_IN_BusReceive(0xf0+bus, midi_package, 0); } } status |= 1; break; default: if( seq_midi_in_options[bus].MODE_PLAY ) { MUTEX_MIDIOUT_TAKE; SEQ_CORE_PlayLive(SEQ_UI_VisibleTrackGet(), midi_package); MUTEX_MIDIOUT_GIVE; } } } } // record function if( !(status & 2) && should_be_recorded ) { SEQ_RECORD_Receive(midi_package, SEQ_UI_VisibleTrackGet()); } // Section Changer if( !(status & 2) && (seq_midi_in_sect_port && port == seq_midi_in_sect_port && midi_package.chn == (seq_midi_in_sect_channel-1)) ) { u8 forward_event = 1; switch( midi_package.event ) { case NoteOff: MUTEX_MIDIIN_TAKE; if( (status = SEQ_MIDI_IN_Receive_NoteSC(midi_package.note, 0x00)) >= 1 ) forward_event = 0; MUTEX_MIDIIN_GIVE; break; case NoteOn: MUTEX_MIDIIN_TAKE; if( (status = SEQ_MIDI_IN_Receive_NoteSC(midi_package.note, midi_package.velocity)) >= 1 ) forward_event = 0; MUTEX_MIDIIN_GIVE; break; } if( seq_midi_in_sect_fwd_port && forward_event ) { // octave hasn't been taken, optionally forward to forwarding port MUTEX_MIDIOUT_TAKE; MIOS32_MIDI_SendPackage(seq_midi_in_sect_fwd_port, midi_package); MUTEX_MIDIOUT_GIVE; } } #if PATCH_CHANGER_ENABLED // Patch Changer (currently assigned to channel+1) if( !(status & 2) && (seq_midi_in_sect_port && port == seq_midi_in_sect_port && midi_package.chn == (seq_midi_in_sect_channel)) ) { u8 forward_event = 1; switch( midi_package.event ) { case NoteOff: MUTEX_MIDIIN_TAKE; if( (status = SEQ_MIDI_IN_Receive_NotePC(midi_package.note, 0x00)) >= 1 ) forward_event = 0; MUTEX_MIDIIN_GIVE; break; case NoteOn: MUTEX_MIDIIN_TAKE; if( (status = SEQ_MIDI_IN_Receive_NotePC(midi_package.note, midi_package.velocity)) >= 1 ) forward_event = 0; MUTEX_MIDIIN_GIVE; break; } if( seq_midi_in_sect_fwd_port && forward_event ) { // octave hasn't been taken, optionally forward to forwarding port MUTEX_MIDIOUT_TAKE; MIOS32_MIDI_SendPackage(seq_midi_in_sect_fwd_port, midi_package); MUTEX_MIDIOUT_GIVE; } } #endif return status; }
///////////////////////////////////////////////////////////////////////////// // Local button callback function // Should return: // 1 if value has been changed // 0 if value hasn't been changed // -1 if invalid or unsupported button ///////////////////////////////////////////////////////////////////////////// static s32 Button_Handler(seq_ui_button_t button, s32 depressed) { if( SEQ_FILE_FormattingRequired() ) return 0; // no button action as long as files not available u8 group; s32 status; switch( button ) { case SEQ_UI_BUTTON_Edit: { if ( depressed && (selected_page == PAGE_REMIX) ) { // we want to show vertical VU meters normal mode SEQ_LCD_InitSpecialChars(SEQ_LCD_CHARSET_VBars); selected_page = PAGE_MAIN; // // here we run the commands for remix states // u16 remix_map_tmp; // if we are in no preview_mode them call the demix procedment in case we got some request if ( (seq_pattern_remix_map != seq_pattern_demix_map) && ( remix_mode ) ) { remix_map_tmp = seq_pattern_remix_map; seq_pattern_remix_map = ~(seq_pattern_remix_map ^ seq_pattern_demix_map); if (ableton_api) { // TODO: implements a ableton remotescript to the clip control functionality u8 track; for(track=0; track<SEQ_CORE_NUM_TRACKS; ++track) { // if we got the track bit setup inside our remix_map, them do not send mixer data for that track channel, let it be mixed down if ( ((1 << track) | seq_pattern_remix_map) == seq_pattern_remix_map ) { // do nothing... } else { // delay our task for ableton get a breath before change the pattern line vTaskDelay(50); // send slot play envet to ableton: cc (111 + track) with value 127 to channel 16 MIOS32_MIDI_SendCC(ableton_port, 15, (111 + track), 127); } } } // if we are in remix mode lets start the process if (remix_map_tmp == 0) { //pattern_name = pattern_name_remix; preview_mode = 0; remix_mode = 0; // set the pattern_remix_timer reference pattern_remix_timer = MIOS32_SYS_TimeGet(); } // Change Pattern u8 group; for(group=0; group<SEQ_CORE_NUM_GROUPS; ++group) { // change pattern SEQ_PATTERN_Change(group, seq_pattern[group], 0); } // copy the pattern name for future reference sprintf(pattern_name, seq_pattern_name[0]); // getting back seq_pattern_remix_map = remix_map_tmp; seq_pattern_demix_map = seq_pattern_remix_map; } } else if ( !depressed ) { // we want to show horizontal VU meters in remix mode SEQ_LCD_InitSpecialChars(SEQ_LCD_CHARSET_HBars); selected_page = PAGE_REMIX; } return 1; } break; case SEQ_UI_BUTTON_Select: { if(!depressed) { selected_page = PAGE_OPTION; return 1; } if( (depressed) && (selected_page == PAGE_OPTION) ) { selected_page = PAGE_MAIN; } } break; default: break; } if( depressed ) return 0; // ignore when button depressed if its not SEQ_UI_BUTTON_Select or SEQ_UI_BUTTON_Edit switch( selected_page ) { /////////////////////////////////////////////////////////////////////////// // REMIX PAGE case PAGE_REMIX: { if( button <= SEQ_UI_BUTTON_GP16 ) { // re-using encoder routine return Encoder_Handler(button, 0); } } break; /////////////////////////////////////////////////////////////////////////// // OPTION PAGE case PAGE_OPTION: { switch( button ) { case SEQ_UI_BUTTON_GP1: // Save Pattern(all 4 groups at once) for(group=0; group<SEQ_CORE_NUM_GROUPS; ++group) { if( (status=SEQ_PATTERN_Save(group, seq_pattern[group])) < 0 ) { SEQ_UI_SDCardErrMsg(2000, status); return 0; } } // Save the pattern mixer SEQ_MIXER_Save(SEQ_MIXER_NumGet()); break; case SEQ_UI_BUTTON_GP2: // Edit Pattern Name //SEQ_LCD_Clear(); selected_page = PAGE_NAME_EDIT; break; case SEQ_UI_BUTTON_GP3: // Copy Pattern // We are going to use the multicopy procedure SEQ_UI_PATTERN_Copy(); // coping mixer SEQ_UI_MIXER_Copy(); break; case SEQ_UI_BUTTON_GP4: // Paste Pattern // We are going to use the multicopy procedure SEQ_UI_PATTERN_Paste(); // paste mixer SEQ_UI_MIXER_Paste(); break; case SEQ_UI_BUTTON_GP5: case SEQ_UI_BUTTON_GP6: return -1; // not mapped case SEQ_UI_BUTTON_GP7: case SEQ_UI_BUTTON_GP8: // Track Delay Page //SEQ_LCD_Clear(); //selected_page = PAGE_TRK_DELAY; //break; return -1; // not mapped case SEQ_UI_BUTTON_GP9: case SEQ_UI_BUTTON_GP10: return -1; // not mapped case SEQ_UI_BUTTON_GP11: case SEQ_UI_BUTTON_GP12: return -1; // not mapped case SEQ_UI_BUTTON_GP13: case SEQ_UI_BUTTON_GP14: // Auto Save switch auto_save ^= 1; break; break; case SEQ_UI_BUTTON_GP15: case SEQ_UI_BUTTON_GP16: // Ableton API switch ableton_api ^= 1; return -1; // not mapped } return 0; } break; /////////////////////////////////////////////////////////////////////////// // PATTERN NAME EDIT PAGE case PAGE_NAME_EDIT: { return Encoder_Handler((seq_ui_encoder_t)button, 0); } break; /////////////////////////////////////////////////////////////////////////// // TRACK DELAY PAGE case PAGE_TRK_DELAY: { } break; /////////////////////////////////////////////////////////////////////////// // MAIN PAGE case PAGE_MAIN: { // Pattern Change Group Requests if( button <= SEQ_UI_BUTTON_GP8 ) { u8 group; for(group=0; group<SEQ_CORE_NUM_GROUPS; ++group) { if( selected_pattern[group].group == button ) { if( SEQ_FILE_B_NumPatterns(selected_pattern[group].bank) > 64 ) { selected_pattern[group].lower ^= 1; } else { selected_pattern[group].lower = 0; // toggling not required } } else { selected_pattern[group].group = button; preview_bank = button; //preview_mode = 0; } } SEQ_PATTERN_PeekName(selected_pattern[0], preview_name); preview_mode = 1; return 1; // value always changed } // Pattern Change Request if( button >= SEQ_UI_BUTTON_GP9 && button <= SEQ_UI_BUTTON_GP16 ) { //u8 group; s32 status = 0; // setting save patterns for later autosave procedure //for(group=0; group<SEQ_CORE_NUM_GROUPS; ++group) // save_pattern[group] = seq_pattern[group]; // change preview pattern selected_pattern[0].num = button-8; selected_pattern[1].num = button-8; selected_pattern[2].num = button-8; selected_pattern[3].num = button-8; if ( !preview_mode ) { preview_num = button-8; SEQ_PATTERN_PeekName(selected_pattern[0], preview_name); preview_mode = 1; // for security reasons in live environment, we can not accept rapid 2x press of pattern button. // if the buttons are not good quality they can send a 2x rapid signal os pressing in just one physical pressing // the time we need is bassicly the human time to read the name of patterns requested // start time in count pc_time_control = seq_core_timestamp_ms + 200; // vTaksDelay(200); } else { // if ( remix_mode == 0 ) { //char str[30]; //sprintf(str, "%d = %d %d = %d", selected_pattern[0].num, preview_num, selected_pattern[0].group, preview_bank); //SEQ_UI_Msg(SEQ_UI_MSG_USER, 2000, str, "debug"); // Check for remix state if ( (selected_pattern[0].num == preview_num) && (selected_pattern[0].group == preview_bank) ) { //if ( pc_time_control >= seq_core_timestamp_ms ) // return 0; // do nothing, just to be shure we are not handle acidental double clicks, it happens! // if we got some remix bit setup, enter in remix mode if (seq_pattern_remix_map != 0) { // set the remix mode remix_mode = 1; } } } // Change Pattern if ( (selected_pattern[0].num == preview_num) && (selected_pattern[0].group == preview_bank) ) { if ( pc_time_control >= seq_core_timestamp_ms ) return 0; // do nothing, just to be shure we are not handle acidental double clicks if (ableton_api) { u8 ableton_pattern_number = 0; // // ABLETON API PATTERN CHANGE HANDLE // // send ableton event to change the line clips if (selected_pattern[0].lower) { ableton_pattern_number = ((selected_pattern[0].group - 1) * 8) + button; } else { ableton_pattern_number = (((selected_pattern[0].group - 1) + 8) * 8) + button; } // midi_cc to send = 110 // midi_chn = 16 // midi_port = ableton_port // here we need to send a clip line change request MIOS32_MIDI_SendCC(ableton_port, 15, 110, ableton_pattern_number); // delay our task for ableton get a breath before change the pattern line vTaskDelay(50); // clip triggering u8 track; for(track=0; track<SEQ_CORE_NUM_TRACKS; ++track) { // if we got the track bit setup inside our remix_map, them do not send mixer data for that track channel, let it be mixed down if ( ((1 << track) | seq_pattern_remix_map) == seq_pattern_remix_map ) { // do nothing... } else { // delay our task for ableton get a breath before change the pattern line vTaskDelay(50); // send clip slot play envet to ableton cc (111 + track) with value 127 to channel 16 MIOS32_MIDI_SendCC(ableton_port, 15, (111 + track), 127); } } // send a global clip change(all clips in the clip line) // send play envet to ableton cc 20 with value 127 to channel 16 //MIOS32_MIDI_SendCC(ableton_port, 15, 20, 127); } // // Autosave Pattern // if (auto_save) { // Autosave all 4 group of patterns for(group=0; group<SEQ_CORE_NUM_GROUPS; ++group) { // Save to SD Card if( (status=SEQ_PATTERN_Save(group, seq_pattern[group])) < 0 ) { SEQ_UI_SDCardErrMsg(2000, status); } } // Autosave Mixer Map SEQ_MIXER_Save(SEQ_MIXER_NumGet()); } // if we are not in remix mode if (seq_pattern_remix_map == 0) { // keep the name of old pattern(because we still got 1 or more tracks belongs to this pattern) //pattern_name = seq_pattern_name; // set timer for mixed pattern pattern_remix_timer = MIOS32_SYS_TimeGet(); } // // Pattern change request // for(group=0; group<SEQ_CORE_NUM_GROUPS; ++group) { // change pattern //selected_pattern[group].num = button-8; SEQ_PATTERN_Change(group, selected_pattern[group], 0); //if ( remix_mode ) { // keep the pattern name... //sprintf(seq_pattern_name[group], pattern_name); //} } if ( !remix_mode ) { // copy the pattern name for future reference //sprintf(pattern_name, seq_pattern_name[0]); SEQ_PATTERN_PeekName(selected_pattern[0], pattern_name); // TODO: sync this with the pattern change handled by SEQ_PATTERN_Handler() //pattern_timer.seconds = 0; preview_mode = 0; } // support for demix seq_pattern_demix_map = seq_pattern_remix_map; //preview_mode = 0; // Request a Pattern Preview } else { preview_num = button-8; SEQ_PATTERN_PeekName(selected_pattern[0], preview_name); // for security reasons in live environment, we can not accept 2x rapid press of pattern button. // if the buttons are not good quality they can send a 2x rapid signal os pressing in just one physical pressing // the time we need is bassicly the human time to read the name of patterns requested // start time in count pc_time_control = seq_core_timestamp_ms + 200; } } return 1; // value always changed } u8 visible_track = SEQ_UI_VisibleTrackGet(); switch( button ) { case SEQ_UI_BUTTON_Right: // switch to next track if( visible_track < (SEQ_CORE_NUM_TRACKS - 1) ) visible_track++; ui_selected_tracks = (1 << visible_track); ui_selected_group = visible_track / 4; return 1; // value always changed case SEQ_UI_BUTTON_Left: // switch to previous track if( visible_track >= 1 ) visible_track--; ui_selected_tracks = (1 << visible_track); ui_selected_group = visible_track / 4; return 1; // value always changed case SEQ_UI_BUTTON_Up: return Encoder_Handler(SEQ_UI_ENCODER_Datawheel, 1); case SEQ_UI_BUTTON_Down: return Encoder_Handler(SEQ_UI_ENCODER_Datawheel, -1); } return -1; // invalid or unsupported button } break; /////////////////////////////////////////////////////////////////////////// // Page do not exist default: break; } return 0; }
///////////////////////////////////////////////////////////////////////////// // Local button callback function // Should return: // 1 if value has been changed // 0 if value hasn't been changed // -1 if invalid or unsupported button ///////////////////////////////////////////////////////////////////////////// static s32 Button_Handler(seq_ui_button_t button, s32 depressed) { if( depressed ) return 0; // ignore when button depressed #if 0 // leads to: comparison is always true due to limited range of data type if( button >= SEQ_UI_BUTTON_GP1 && button <= SEQ_UI_BUTTON_GP16 ) { #else if( button <= SEQ_UI_BUTTON_GP16 ) { #endif // re-use encoder handler - only select UI item, don't increment return Encoder_Handler((int)button, 0); } // remaining buttons: switch( button ) { case SEQ_UI_BUTTON_Select: case SEQ_UI_BUTTON_Right: if( ++ui_selected_item >= NUM_OF_ITEMS ) ui_selected_item = 0; return 1; // value always changed case SEQ_UI_BUTTON_Left: if( ui_selected_item == 0 ) ui_selected_item = NUM_OF_ITEMS-1; else --ui_selected_item; return 1; // value always changed case SEQ_UI_BUTTON_Up: return Encoder_Handler(SEQ_UI_ENCODER_Datawheel, 1); case SEQ_UI_BUTTON_Down: return Encoder_Handler(SEQ_UI_ENCODER_Datawheel, -1); } return -1; // invalid or unsupported button } ///////////////////////////////////////////////////////////////////////////// // Local Display Handler function // IN: <high_prio>: if set, a high-priority LCD update is requested ///////////////////////////////////////////////////////////////////////////// static s32 LCD_Handler(u8 high_prio) { if( high_prio ) return 0; // there are no high-priority updates // layout: // 00000000001111111111222222222233333333330000000000111111111122222222223333333333 // 01234567890123456789012345678901234567890123456789012345678901234567890123456789 // <--------------------------------------><--------------------------------------> // Trk. Repeats Delay Vel.Level FB Velocity Note Gatelen. Ticks // GxTy 3 1/16 75% 120% + 0 100% 100% u8 visible_track = SEQ_UI_VisibleTrackGet(); /////////////////////////////////////////////////////////////////////////// SEQ_LCD_CursorSet(0, 0); SEQ_LCD_PrintString("Trk. Repeats Delay Vel.Level FB Velocity Note Gatelen. Ticks "); /////////////////////////////////////////////////////////////////////////// SEQ_LCD_CursorSet(0, 1); if( ui_selected_item == ITEM_GXTY && ui_cursor_flash ) { SEQ_LCD_PrintSpaces(4); } else { SEQ_LCD_PrintGxTy(ui_selected_group, ui_selected_tracks); } SEQ_LCD_PrintSpaces(10); /////////////////////////////////////////////////////////////////////////// if( ui_selected_item == ITEM_REPEATS && ui_cursor_flash ) { SEQ_LCD_PrintSpaces(2); } else { SEQ_LCD_PrintFormattedString("%2d", SEQ_CC_Get(visible_track, SEQ_CC_ECHO_REPEATS)); } SEQ_LCD_PrintSpaces(7); /////////////////////////////////////////////////////////////////////////// if( ui_selected_item == ITEM_DELAY && ui_cursor_flash ) { SEQ_LCD_PrintSpaces(4); } else { SEQ_LCD_PrintString((char *)SEQ_CORE_Echo_GetDelayModeName(SEQ_CC_Get(visible_track, SEQ_CC_ECHO_DELAY))); } SEQ_LCD_PrintSpaces(6); /////////////////////////////////////////////////////////////////////////// if( ui_selected_item == ITEM_VELOCITY && ui_cursor_flash ) { SEQ_LCD_PrintSpaces(4); } else { SEQ_LCD_PrintFormattedString("%3d%%", 5*SEQ_CC_Get(visible_track, SEQ_CC_ECHO_VELOCITY)); } SEQ_LCD_PrintSpaces(2); /////////////////////////////////////////////////////////////////////////// SEQ_LCD_CursorSet(40, 1); SEQ_LCD_PrintSpaces(4); if( ui_selected_item == ITEM_FB_VELOCITY && ui_cursor_flash ) { SEQ_LCD_PrintSpaces(4); } else { SEQ_LCD_PrintFormattedString("%3d%%", 5*SEQ_CC_Get(visible_track, SEQ_CC_ECHO_FB_VELOCITY)); } SEQ_LCD_PrintSpaces(7); /////////////////////////////////////////////////////////////////////////// if( ui_selected_item == ITEM_FB_NOTE && ui_cursor_flash ) { SEQ_LCD_PrintSpaces(3); } else { u8 note_delta = SEQ_CC_Get(visible_track, SEQ_CC_ECHO_FB_NOTE); if( note_delta < 24 ) SEQ_LCD_PrintFormattedString("-%2d", 24-note_delta); else if( note_delta < 49 ) SEQ_LCD_PrintFormattedString("+%2d", note_delta-24); else SEQ_LCD_PrintString("Rnd"); } SEQ_LCD_PrintSpaces(5); /////////////////////////////////////////////////////////////////////////// if( ui_selected_item == ITEM_FB_GATELENGTH && ui_cursor_flash ) { SEQ_LCD_PrintSpaces(4); } else { SEQ_LCD_PrintFormattedString("%3d%%", 5*SEQ_CC_Get(visible_track, SEQ_CC_ECHO_FB_GATELENGTH)); } SEQ_LCD_PrintSpaces(7); /////////////////////////////////////////////////////////////////////////// if( ui_selected_item == ITEM_FB_TICKS && ui_cursor_flash ) { SEQ_LCD_PrintSpaces(4); } else { SEQ_LCD_PrintFormattedString("%3d%%", 5*SEQ_CC_Get(visible_track, SEQ_CC_ECHO_FB_TICKS)); } SEQ_LCD_PrintSpaces(2); return 0; // no error } ///////////////////////////////////////////////////////////////////////////// // Initialisation ///////////////////////////////////////////////////////////////////////////// s32 SEQ_UI_FX_ECHO_Init(u32 mode) { // install callback routines SEQ_UI_InstallButtonCallback(Button_Handler); SEQ_UI_InstallEncoderCallback(Encoder_Handler); SEQ_UI_InstallLEDCallback(LED_Handler); SEQ_UI_InstallLCDCallback(LCD_Handler); return 0; // no error }
///////////////////////////////////////////////////////////////////////////// // Local button callback function // Should return: // 1 if value has been changed // 0 if value hasn't been changed // -1 if invalid or unsupported button ///////////////////////////////////////////////////////////////////////////// static s32 Button_Handler(seq_ui_button_t button, s32 depressed) { if( depressed ) return 0; // ignore when button depressed u8 visible_track = SEQ_UI_VisibleTrackGet(); #if 0 // leads to: comparison is always true due to limited range of data type if( button >= SEQ_UI_BUTTON_GP1 && button <= SEQ_UI_BUTTON_GP16 ) { #else if( button <= SEQ_UI_BUTTON_GP15 ) { #endif // re-use encoder handler - only select UI item, don't increment return Encoder_Handler((int)button, 0); } // remaining buttons: switch( button ) { case SEQ_UI_BUTTON_GP16: { if( SEQ_GROOVE_Clear(SEQ_CC_Get(visible_track, SEQ_CC_GROOVE_STYLE)) < 0 ) SEQ_UI_Msg(SEQ_UI_MSG_USER, 1000, "Preset", "not editable!"); else SEQ_UI_Msg(SEQ_UI_MSG_USER, 1000, "Groove", "cleared!"); } break; case SEQ_UI_BUTTON_Select: case SEQ_UI_BUTTON_Right: if( ++ui_selected_item >= NUM_OF_ITEMS ) ui_selected_item = 0; return 1; // value always changed case SEQ_UI_BUTTON_Left: if( ui_selected_item == 0 ) ui_selected_item = NUM_OF_ITEMS-1; else --ui_selected_item; return 1; // value always changed case SEQ_UI_BUTTON_Up: return Encoder_Handler(SEQ_UI_ENCODER_Datawheel, 1); case SEQ_UI_BUTTON_Down: return Encoder_Handler(SEQ_UI_ENCODER_Datawheel, -1); } return -1; // invalid or unsupported button } ///////////////////////////////////////////////////////////////////////////// // Local Display Handler function // IN: <high_prio>: if set, a high-priority LCD update is requested ///////////////////////////////////////////////////////////////////////////// static s32 LCD_Handler(u8 high_prio) { if( high_prio ) return 0; // there are no high-priority updates // layout: // 00000000001111111111222222222233333333330000000000111111111122222222223333333333 // 01234567890123456789012345678901234567890123456789012345678901234567890123456789 // <--------------------------------------><--------------------------------------> // Trk. Groove Style Intensity Change forStep Dly. Len. Vel. NumSteps Clr // G1T1 Inv. Shuffle 15 all Tracks 1 0 0 0 Preset not editable! u8 visible_track = SEQ_UI_VisibleTrackGet(); u8 selected_groove = SEQ_CC_Get(visible_track, SEQ_CC_GROOVE_STYLE); seq_groove_entry_t *g; if( selected_groove >= SEQ_GROOVE_NUM_PRESETS ) g = (seq_groove_entry_t *)&seq_groove_templates[selected_groove-SEQ_GROOVE_NUM_PRESETS]; else g = (seq_groove_entry_t *)&seq_groove_presets[selected_groove]; /////////////////////////////////////////////////////////////////////////// SEQ_LCD_CursorSet(0, 0); SEQ_LCD_PrintString("Trk. Groove Style Intensity "); if( ui_selected_item == ITEM_GROOVE_VALUE_GLB && ui_cursor_flash ) { SEQ_LCD_PrintSpaces(10); } else { SEQ_LCD_PrintString("Change for"); } SEQ_LCD_PrintString("Step Dly. Len. Vel. NumSteps Clr "); /////////////////////////////////////////////////////////////////////////// SEQ_LCD_CursorSet(0, 1); if( ui_selected_item == ITEM_GXTY && ui_cursor_flash ) { SEQ_LCD_PrintSpaces(4); } else { SEQ_LCD_PrintGxTy(ui_selected_group, ui_selected_tracks); } SEQ_LCD_PrintSpaces(2); /////////////////////////////////////////////////////////////////////////// if( ui_selected_item == ITEM_GROOVE_STYLE && ui_cursor_flash ) { SEQ_LCD_PrintSpaces(12); } else { SEQ_LCD_PrintString(SEQ_GROOVE_NameGet(selected_groove)); } SEQ_LCD_PrintSpaces(5); /////////////////////////////////////////////////////////////////////////// if( ui_selected_item == ITEM_GROOVE_VALUE && ui_cursor_flash ) { SEQ_LCD_PrintSpaces(3); } else { SEQ_LCD_PrintFormattedString("%3d", SEQ_CC_Get(visible_track, SEQ_CC_GROOVE_VALUE)); } SEQ_LCD_PrintSpaces(4); /////////////////////////////////////////////////////////////////////////// if( ui_selected_item == ITEM_GROOVE_VALUE_GLB && ui_cursor_flash ) { SEQ_LCD_PrintSpaces(10); } else { SEQ_LCD_PrintString("all Tracks"); } /////////////////////////////////////////////////////////////////////////// if( ui_selected_item == ITEM_GROOVE_STEP && ui_cursor_flash ) { SEQ_LCD_PrintSpaces(4); } else { SEQ_LCD_PrintFormattedString(" %2d ", edit_step+1); } /////////////////////////////////////////////////////////////////////////// if( ui_selected_item == ITEM_GROOVE_DELAY && ui_cursor_flash ) { SEQ_LCD_PrintSpaces(5); } else { int value = g->add_step_delay[edit_step]; if( value <= -128 ) SEQ_LCD_PrintString("VNEG "); else if( value >= 127 ) SEQ_LCD_PrintString("VPOS "); else SEQ_LCD_PrintFormattedString("%4d ", value); } /////////////////////////////////////////////////////////////////////////// if( ui_selected_item == ITEM_GROOVE_LENGTH && ui_cursor_flash ) { SEQ_LCD_PrintSpaces(5); } else { int value = g->add_step_length[edit_step]; if( value <= -128 ) SEQ_LCD_PrintString("VNEG "); else if( value >= 127 ) SEQ_LCD_PrintString("VPOS "); else SEQ_LCD_PrintFormattedString("%4d ", value); } /////////////////////////////////////////////////////////////////////////// if( ui_selected_item == ITEM_GROOVE_VELOCITY && ui_cursor_flash ) { SEQ_LCD_PrintSpaces(5); } else { int value = g->add_step_velocity[edit_step]; if( value <= -128 ) SEQ_LCD_PrintString("VNEG "); else if( value >= 127 ) SEQ_LCD_PrintString("VPOS "); else SEQ_LCD_PrintFormattedString("%4d ", value); } /////////////////////////////////////////////////////////////////////////// if( selected_groove >= SEQ_GROOVE_NUM_PRESETS ) { if( ui_selected_item == ITEM_GROOVE_NUM_STEPS && ui_cursor_flash ) { SEQ_LCD_PrintSpaces(6); } else { SEQ_LCD_PrintFormattedString(" %2d ", g->num_steps); } SEQ_LCD_PrintSpaces(15); } else { if( ui_cursor_flash && ui_selected_item >= ITEM_GROOVE_LENGTH && ui_selected_item <= ITEM_GROOVE_DELAY ) SEQ_LCD_PrintSpaces(21); else SEQ_LCD_PrintString(" Preset not editable!"); } return 0; // no error } ///////////////////////////////////////////////////////////////////////////// // Local exit function ///////////////////////////////////////////////////////////////////////////// static s32 EXIT_Handler(void) { s32 status = 0; if( ui_store_file_required ) { // write config file MUTEX_SDCARD_TAKE; if( (status=SEQ_FILE_G_Write(seq_file_session_name)) < 0 ) SEQ_UI_SDCardErrMsg(2000, status); MUTEX_SDCARD_GIVE; ui_store_file_required = 0; } return status; }
///////////////////////////////////////////////////////////////////////////// // Local Display Handler function // IN: <high_prio>: if set, a high-priority LCD update is requested ///////////////////////////////////////////////////////////////////////////// static s32 LCD_Handler(u8 high_prio) { if( high_prio ) return 0; // there are no high-priority updates // layout: // 00000000001111111111222222222233333333330000000000111111111122222222223333333333 // 01234567890123456789012345678901234567890123456789012345678901234567890123456789 // <--------------------------------------><--------------------------------------> // Trk. Length Loop QuickSel Quick Selection: Length // G1T1 256/256 1 Length 4 8 16 24 32 64 128 256 // Trk. Length Loop QuickSel 1 5 9 13 1 1 17 25 // G1T1 256/256 1 Loops 4 8 12 16 16 32 32 32 u8 visible_track = SEQ_UI_VisibleTrackGet(); s32 quicksel_item = QUICKSEL_SearchItem(SEQ_UI_VisibleTrackGet()); /////////////////////////////////////////////////////////////////////////// SEQ_LCD_CursorSet(0, 0); SEQ_LCD_PrintString("Trk. Length Loop "); SEQ_LCD_CursorSet(0, 2); SEQ_LCD_PrintString("QuickSel: "); SEQ_LCD_CursorSet(0, 3); SEQ_LCD_PrintSpaces(21); SEQ_LCD_CursorSet(0, 4); if( quicksel_mode == QUICKSEL_MODE_LENGTH ) { //SEQ_LCD_PrintString("Quick Selection: Length "); SEQ_LCD_PrintSpaces(21); } else { int i; for(i=0; i<8; ++i) { switch( i ) { case 0: SEQ_LCD_CursorSet(0, 4); break; case 4: SEQ_LCD_CursorSet(0, 6); break; } if( quicksel_item == i && ui_cursor_flash ) { SEQ_LCD_PrintSpaces(5); } else { int loop = (int)ui_quicksel_loop_loop[i] + 1; PrintLengthOrLoop(loop); } } } /////////////////////////////////////////////////////////////////////////// SEQ_LCD_CursorSet(0, 1); if( ui_selected_item == ITEM_GXTY && ui_cursor_flash ) { SEQ_LCD_PrintSpaces(7); } else { SEQ_LCD_PrintGxTy(ui_selected_group, ui_selected_tracks); SEQ_LCD_PrintSpaces(3); } /////////////////////////////////////////////////////////////////////////// SEQ_LCD_PrintSpaces(8); if( ui_selected_item == ITEM_LENGTH && ui_cursor_flash ) { } else { SEQ_LCD_CursorSet(7, 1); u16 num_steps = SEQ_TRG_NumStepsGet(visible_track); u16 len = SEQ_CC_Get(visible_track, SEQ_CC_LENGTH)+1; if( len > num_steps ) SEQ_LCD_PrintFormattedString("!!!/%d", num_steps); else SEQ_LCD_PrintFormattedString("%d/%d", len, num_steps); } // to allow variable string lengths... SEQ_LCD_CursorSet(15, 1); /////////////////////////////////////////////////////////////////////////// if( ui_selected_item == ITEM_LOOP && ui_cursor_flash ) { SEQ_LCD_PrintSpaces(4); } else { u16 num_steps = SEQ_TRG_NumStepsGet(visible_track); u16 loop = SEQ_CC_Get(visible_track, SEQ_CC_LOOP)+1; if( loop > num_steps ) SEQ_LCD_PrintString("!!! "); else SEQ_LCD_PrintFormattedString("%3d ", loop); } /////////////////////////////////////////////////////////////////////////// //SEQ_LCD_PrintSpaces(14); SEQ_LCD_CursorSet(11, 2); // free for sale /////////////////////////////////////////////////////////////////////////// if( ui_selected_item == ITEM_QUICKSEL_MODE && ui_cursor_flash ) { SEQ_LCD_PrintSpaces(7); } else { if( quicksel_mode == QUICKSEL_MODE_LENGTH ) { SEQ_LCD_PrintString("Length "); } else { SEQ_LCD_PrintString("Loops "); } } /////////////////////////////////////////////////////////////////////////// int i; for(i=0; i<8; ++i) { switch( i ) { case 0: SEQ_LCD_CursorSet(0, 5); break; case 4: SEQ_LCD_CursorSet(0, 7); break; } if( quicksel_item == i && ui_cursor_flash ) { SEQ_LCD_PrintSpaces(5); } else { int length = (int)((quicksel_mode == QUICKSEL_MODE_LENGTH) ? ui_quicksel_length[i] : ui_quicksel_loop_length[i]) + 1; if( length > SEQ_TRG_NumStepsGet(visible_track) ) SEQ_LCD_PrintString(" --- "); else { PrintLengthOrLoop(length); } } } return 0; // no error }
///////////////////////////////////////////////////////////////////////////// // Local button callback function // Should return: // 1 if value has been changed // 0 if value hasn't been changed // -1 if invalid or unsupported button ///////////////////////////////////////////////////////////////////////////// static s32 Button_Handler(seq_ui_button_t button, s32 depressed) { if( depressed ) return 0; // ignore when button depressed #if 0 // leads to: comparison is always true due to limited range of data type if( button >= SEQ_UI_BUTTON_GP1 && button <= SEQ_UI_BUTTON_GP16 ) { #else if( button <= SEQ_UI_BUTTON_GP16 ) { #endif // -> same handling like for encoders return Encoder_Handler(button, 0); } switch( button ) { case SEQ_UI_BUTTON_Select: return -1; // unsupported (yet) case SEQ_UI_BUTTON_Right: case SEQ_UI_BUTTON_Up: if( depressed ) return 0; // ignore when button depressed return Encoder_Handler(SEQ_UI_ENCODER_Datawheel, 1); case SEQ_UI_BUTTON_Left: case SEQ_UI_BUTTON_Down: if( depressed ) return 0; // ignore when button depressed return Encoder_Handler(SEQ_UI_ENCODER_Datawheel, -1); } return -1; // invalid or unsupported button } ///////////////////////////////////////////////////////////////////////////// // Local Display Handler function // IN: <high_prio>: if set, a high-priority LCD update is requested ///////////////////////////////////////////////////////////////////////////// static s32 LCD_Handler(u8 high_prio) { // layout normal mode: // 00000000001111111111222222222233333333330000000000111111111122222222223333333333 // 01234567890123456789012345678901234567890123456789012345678901234567890123456789 // <--------------------------------------><--------------------------------------> // Gate Acc. Roll Glide Skip R.G R.V No Fx // A B C D E F G H // layout drum mode (lower line shows drum labels): // 00000000001111111111222222222233333333330000000000111111111122222222223333333333 // 01234567890123456789012345678901234567890123456789012345678901234567890123456789 // <--------------------------------------><--------------------------------------> // Select Drum Instrument: // BD SD LT MT HT CP MA RS CB CY OH CH Smp1 Smp2 Smp3 Smp4 // ...horizontal VU meters... u8 visible_track = SEQ_UI_VisibleTrackGet(); u8 event_mode = SEQ_CC_Get(visible_track, SEQ_CC_MIDI_EVENT_MODE); if( high_prio && event_mode == SEQ_EVENT_MODE_Drum ) { /////////////////////////////////////////////////////////////////////////// // frequently update VU meters SEQ_LCD_CursorSet(0, 1); u8 drum; u8 num_instruments = SEQ_TRG_NumInstrumentsGet(visible_track); for(drum=0; drum<num_instruments; ++drum) { if( seq_core_trk[visible_track].layer_muted & (1 << drum) ) SEQ_LCD_PrintString("Mute "); else SEQ_LCD_PrintHBar((seq_layer_vu_meter[drum] >> 3) & 0xf); } return 0; // no error }
///////////////////////////////////////////////////////////////////////////// // Local encoder callback function // Should return: // 1 if value has been changed // 0 if value hasn't been changed // -1 if invalid or unsupported encoder ///////////////////////////////////////////////////////////////////////////// static s32 Encoder_Handler(seq_ui_encoder_t encoder, s32 incrementer) { u8 visible_track = SEQ_UI_VisibleTrackGet(); u16 num_steps = SEQ_TRG_NumStepsGet(visible_track); switch( encoder ) { case SEQ_UI_ENCODER_GP1: SEQ_UI_Var8_Inc(&ui_selected_item, 0, NUM_OF_ITEMS, incrementer); //ui_selected_item = ITEM_GXTY; break; case SEQ_UI_ENCODER_GP2: case SEQ_UI_ENCODER_GP3: ui_selected_item = ITEM_LENGTH; break; case SEQ_UI_ENCODER_GP4: case SEQ_UI_ENCODER_GP5: ui_selected_item = ITEM_LOOP; break; case SEQ_UI_ENCODER_GP6: return 0; // not mapped case SEQ_UI_ENCODER_GP7: case SEQ_UI_ENCODER_GP8: ui_selected_item = ITEM_QUICKSEL_MODE; break; case SEQ_UI_ENCODER_GP9: case SEQ_UI_ENCODER_GP10: case SEQ_UI_ENCODER_GP11: case SEQ_UI_ENCODER_GP12: case SEQ_UI_ENCODER_GP13: case SEQ_UI_ENCODER_GP14: case SEQ_UI_ENCODER_GP15: case SEQ_UI_ENCODER_GP16: { int quicksel = encoder - 8; int len = (quicksel_mode == QUICKSEL_MODE_LENGTH) ? ui_quicksel_length[quicksel] : ui_quicksel_loop_length[quicksel]; if( (len+1) > num_steps ) { len = num_steps-1; char buffer[20]; sprintf(buffer, "for %d steps", num_steps); SEQ_UI_Msg(SEQ_UI_MSG_USER_R, 1000, "Track only prepared", buffer); } else if( seq_cc_trk[visible_track].clkdiv.SYNCH_TO_MEASURE && ((int)len > (int)seq_core_steps_per_measure) ) { char buffer[20]; sprintf(buffer, "active for %d steps", (int)seq_core_steps_per_measure+1); SEQ_UI_Msg(SEQ_UI_MSG_USER, 1000, "Synch-to-Measure is", buffer); } SEQ_UI_CC_Set(SEQ_CC_LENGTH, len); if( quicksel_mode == QUICKSEL_MODE_LOOP ) { SEQ_UI_CC_Set(SEQ_CC_LOOP, ui_quicksel_loop_loop[quicksel]); } return 1; // value has been changed } break; } // for GP encoders and Datawheel if (encoder == SEQ_UI_ENCODER_Datawheel) { switch( ui_selected_item ) { case ITEM_GXTY: return SEQ_UI_GxTyInc(incrementer); case ITEM_LENGTH: { if( SEQ_UI_CC_Inc(SEQ_CC_LENGTH, 0, num_steps-1, incrementer) >= 1 ) { if( seq_cc_trk[visible_track].clkdiv.SYNCH_TO_MEASURE && (int)SEQ_CC_Get(visible_track, SEQ_CC_LENGTH) > (int)seq_core_steps_per_measure ) { char buffer[20]; sprintf(buffer, "active for %d steps", (int)seq_core_steps_per_measure+1); SEQ_UI_Msg(SEQ_UI_MSG_USER, 1000, "Synch-to-Measure is", buffer); } return 1; } return 0; } case ITEM_LOOP: return SEQ_UI_CC_Inc(SEQ_CC_LOOP, 0, num_steps-1, incrementer); case ITEM_QUICKSEL_MODE: return SEQ_UI_Var8_Inc(&quicksel_mode, 0, 1, incrementer); } } return -1; // invalid or unsupported encoder }
///////////////////////////////////////////////////////////////////////////// // Called from SEQ_MIDI_IN_Receive() if MIDI event has been received on // matching IN port and channel ///////////////////////////////////////////////////////////////////////////// s32 SEQ_RECORD_Receive(mios32_midi_package_t midi_package, u8 track) { // step recording mode? // Note: if sequencer is not running, "Live Recording" will be handled like "Step Recording" u8 step_record_mode = seq_record_options.STEP_RECORD || !SEQ_BPM_IsRunning(); #if MBSEQV4L // extra for MBSEQ V4L: seq_record_state.ARMED_TRACKS and auto-assignment if( !seq_record_state.ARMED_TRACKS ) return 0; // no track armed track = 0; if( seq_record_state.ARMED_TRACKS & 0xff00) track = 8; // search for free track/layer if( (midi_package.event == NoteOn) || (midi_package.event == NoteOff) ) { // fine, we will record Note in selected track } else if( midi_package.event == PitchBend ) { track += 3; // G1T4 resp. G3T4 } else if( midi_package.event == CC ) { const u8 track_layer_cc_table[19][2] = { { 4, 0 }, { 5, 0 }, { 6, 0 }, { 7, 0 }, { 7, 1 }, { 7, 2 }, { 7, 3 }, { 6, 1 }, { 6, 2 }, { 6, 3 }, { 5, 1 }, { 5, 2 }, { 5, 3 }, { 4, 1 }, { 4, 2 }, { 4, 3 }, { 3, 1 }, { 3, 2 }, { 3, 3 }, }; // search for same (or free) CC entry // new track/layer search algorithm since V4L.082 u8 seq_track_offset = track; // depends on sequence int par_layer = 0; int i; u8 free_layer_found = 0; for(i=0; i<19 && !free_layer_found; ++i) { track = seq_track_offset + track_layer_cc_table[i][0]; par_layer = track_layer_cc_table[i][1]; seq_cc_trk_t *tcc = &seq_cc_trk[track]; u8 *layer_type_ptr = (u8 *)&tcc->lay_const[0*16 + par_layer]; u8 *layer_cc_ptr = (u8 *)&tcc->lay_const[1*16 + par_layer]; if( *layer_type_ptr == SEQ_PAR_Type_CC && (*layer_cc_ptr >= 0x80 || *layer_cc_ptr == midi_package.cc_number) && (seq_record_state.ARMED_TRACKS & (1 << track)) ) { if( *layer_cc_ptr >= 0x80 ) { *layer_cc_ptr = midi_package.cc_number; // assing CC number to free track // initialize whole layer with invalid value 0xc0 (indicates: not recorded) int num_p_steps = SEQ_PAR_NumStepsGet(track); int instrument = 0; int step; for(step=0; step<num_p_steps; ++step) SEQ_PAR_Set(track, step, par_layer, instrument, 0xc0); #if DEBUG_VERBOSE_LEVEL >= 2 DEBUG_MSG("[SEQ_RECORD_Receive] free CC layer found for CC#%d in track #%d.%c\n", midi_package.cc_number, track+1, 'A'+par_layer); #endif } free_layer_found = 1; } } if( !free_layer_found ) { #if DEBUG_VERBOSE_LEVEL >= 2 DEBUG_MSG("[SEQ_RECORD_Receive] no free CC layer found for CC#%d\n", midi_package.cc_number); #endif return 0; // no free layer } } else { return 0; // event not relevant } // exit if track not armed if( !(seq_record_state.ARMED_TRACKS & (1 << track)) ) return 0; #else // MBSEQV4 (without L) if( midi_package.event == CC && track == SEQ_UI_VisibleTrackGet() ) { // search for same (or free) CC entry seq_cc_trk_t *tcc = &seq_cc_trk[track]; u8 free_layer_found = 0; { u8 num_p_layers = SEQ_PAR_NumLayersGet(track); u8 *layer_type_ptr = (u8 *)&tcc->lay_const[0*16]; u8 *layer_cc_ptr = (u8 *)&tcc->lay_const[1*16]; int par_layer; for(par_layer=0; par_layer<num_p_layers && !free_layer_found; ++par_layer, ++layer_type_ptr, ++layer_cc_ptr) { if( *layer_type_ptr == SEQ_PAR_Type_CC && (*layer_cc_ptr >= 0x80 || *layer_cc_ptr == midi_package.cc_number) ) { if( *layer_cc_ptr >= 0x80 ) { *layer_cc_ptr = midi_package.cc_number; // assing CC number to free track // initialize whole layer with invalid value 0xc0 (indicates: not recorded) int num_p_steps = SEQ_PAR_NumStepsGet(track); int instrument = 0; int step; for(step=0; step<num_p_steps; ++step) SEQ_PAR_Set(track, step, par_layer, instrument, 0xc0); #if DEBUG_VERBOSE_LEVEL >= 2 DEBUG_MSG("[SEQ_RECORD_Receive] free CC layer found for CC#%d in track #%d.%c\n", midi_package.cc_number, track+1, 'A'+par_layer); #endif } free_layer_found = 1; break; } } } if( !free_layer_found ) { #if DEBUG_VERBOSE_LEVEL >= 2 DEBUG_MSG("[SEQ_RECORD_Receive] no free CC layer found for CC#%d\n", midi_package.cc_number); #endif return 0; // no free layer } } #endif #if DEBUG_VERBOSE_LEVEL >= 2 DEBUG_MSG("[SEQ_RECORD_Receive] %02x %02x %02x -> track #%d\n", midi_package.evnt0, midi_package.evnt1, midi_package.evnt2, track+1); #endif // exit if track number too high if( track >= SEQ_CORE_NUM_TRACKS ) return -1; // unsupported track seq_core_trk_t *t = &seq_core_trk[track]; seq_cc_trk_t *tcc = &seq_cc_trk[track]; // branch depending on event u8 rec_event = 0; u8 send_note_off = 0; switch( midi_package.event ) { case NoteOff: case NoteOn: { midi_package.note &= 0x7f; // to avoid array overwrites u32 note_mask = 1 << (midi_package.note & 0x1f); // if Note Off and new note number matches with recorded note number if( midi_package.event == NoteOff || midi_package.velocity == 0 ) { if( seq_record_played_notes[midi_package.note>>5] & note_mask ) { MIOS32_IRQ_Disable(); // note not active anymore seq_record_played_notes[midi_package.note>>5] &= ~note_mask; // determine duration in mS (for step recording function) u16 duration_ms = MIOS32_TIMESTAMP_Get() - seq_record_note_timestamp_ms[midi_package.note]; // map to BPM int duration = (int)((float)duration_ms / ((1000.0*60.0) / SEQ_BPM_EffectiveGet() / (float)SEQ_BPM_PPQN_Get())); #if DEBUG_VERBOSE_LEVEL >= 3 DEBUG_MSG("[SEQ_RECORD_Receive] duration of note 0x%02x was %d mS (%d ticks)\n", midi_package.note, duration_ms, duration); #endif // insert length into current step u8 instrument = 0; int len; if( step_record_mode ) { len = 71; // 75% if( tcc->event_mode != SEQ_EVENT_MODE_Drum ) len = (duration <= 96) ? duration : 96; // for duration >= 96 the length will be stretched after record } else { len = SEQ_BPM_TickGet() - t->rec_timestamp; if( len < 1 ) len = 1; else if( len > 95 ) len = 95; } int len_step = step_record_mode ? ui_selected_step : t->step; u8 num_p_layers = SEQ_PAR_NumLayersGet(track); while( 1 ) { if( tcc->event_mode == SEQ_EVENT_MODE_Combined ) { // extra for MBSEQ V4L: // search for note in track 1/8, insert length into track 3/10 int par_layer; for(par_layer=0; par_layer<num_p_layers; ++par_layer) { if( SEQ_PAR_Get(track, len_step, par_layer, instrument) == midi_package.note ) { SEQ_PAR_Set(track+2, len_step, par_layer, instrument, len); break; } } } else { if( tcc->link_par_layer_length >= 0 ) SEQ_PAR_Set(track, len_step, tcc->link_par_layer_length, instrument, len); } if( !step_record_mode ) break; if( tcc->event_mode == SEQ_EVENT_MODE_Drum ) break; if( duration <= 0 ) break; duration -= 96; // insert length into all following steps until a gate is set if( ++len_step > tcc->length ) // TODO: handle this correctly if track is played backwards len_step = tcc->loop; if( SEQ_TRG_GateGet(track, len_step, instrument) ) break; len = (duration > 0) ? 96 : -duration; // copy notes u8 *layer_type_ptr = (u8 *)&tcc->lay_const[0*16]; int par_layer; for(par_layer=0; par_layer<num_p_layers; ++par_layer, ++layer_type_ptr) { if( *layer_type_ptr == SEQ_PAR_Type_Note || *layer_type_ptr == SEQ_PAR_Type_Chord ) { u8 note = SEQ_PAR_Get(track, ui_selected_step, par_layer, instrument); SEQ_PAR_Set(track, len_step, par_layer, instrument, note); } } } MIOS32_IRQ_Enable(); } if( step_record_mode && seq_record_options.FWD_MIDI ) { // send Note Off events of current track if no key is played anymore u8 any_note_played = seq_record_played_notes[0] || seq_record_played_notes[1] || seq_record_played_notes[2] || seq_record_played_notes[3]; if( !any_note_played ) send_note_off = 1; } } else { MIOS32_IRQ_Disable(); if( step_record_mode && tcc->event_mode != SEQ_EVENT_MODE_Drum ) { // check if another note is already played u8 any_note_played = seq_record_played_notes[0] || seq_record_played_notes[1] || seq_record_played_notes[2] || seq_record_played_notes[3]; // if not: clear poly counter and all notes (so that new chord can be entered if all keys were released) if( !any_note_played ) { t->rec_poly_ctr = 0; u8 num_p_layers = SEQ_PAR_NumLayersGet(track); u8 *layer_type_ptr = (u8 *)&tcc->lay_const[0*16]; int par_layer; u8 instrument = 0; for(par_layer=0; par_layer<num_p_layers; ++par_layer, ++layer_type_ptr) { if( *layer_type_ptr == SEQ_PAR_Type_Note || *layer_type_ptr == SEQ_PAR_Type_Chord ) SEQ_PAR_Set(track, ui_selected_step, par_layer, instrument, 0x00); } } } // note is active seq_record_played_notes[midi_package.note>>5] |= note_mask; // start measuring length t->rec_timestamp = SEQ_BPM_TickGet(); // for step record function: independent from BPM seq_record_note_timestamp_ms[midi_package.note & 0x7f] = MIOS32_TIMESTAMP_Get(); // note: 16bit only MIOS32_IRQ_Enable(); // record event rec_event = 1; } } break; case CC: case PitchBend: { rec_event = 1; } break; default: { #if DEBUG_VERBOSE_LEVEL >= 2 DEBUG_MSG("[SEQ_RECORD_Receive] event %x not supported.\n", midi_package.event); #endif return -2; // unsupported event } }
///////////////////////////////////////////////////////////////////////////// // Local encoder callback function // Should return: // 1 if value has been changed // 0 if value hasn't been changed // -1 if invalid or unsupported encoder ///////////////////////////////////////////////////////////////////////////// static s32 Encoder_Handler(seq_ui_encoder_t encoder, s32 incrementer) { u8 visible_track = SEQ_UI_VisibleTrackGet(); switch( encoder ) { case SEQ_UI_ENCODER_GP1: case SEQ_UI_ENCODER_GP2: ui_selected_item = ITEM_GXTY; break; case SEQ_UI_ENCODER_GP3: case SEQ_UI_ENCODER_GP4: ui_selected_item = ITEM_REPEATS; break; case SEQ_UI_ENCODER_GP5: case SEQ_UI_ENCODER_GP6: ui_selected_item = ITEM_DELAY; break; case SEQ_UI_ENCODER_GP7: case SEQ_UI_ENCODER_GP8: ui_selected_item = ITEM_VELOCITY; break; case SEQ_UI_ENCODER_GP9: case SEQ_UI_ENCODER_GP10: ui_selected_item = ITEM_FB_VELOCITY; break; case SEQ_UI_ENCODER_GP11: case SEQ_UI_ENCODER_GP12: ui_selected_item = ITEM_FB_NOTE; break; case SEQ_UI_ENCODER_GP13: case SEQ_UI_ENCODER_GP14: ui_selected_item = ITEM_FB_GATELENGTH; break; case SEQ_UI_ENCODER_GP15: case SEQ_UI_ENCODER_GP16: ui_selected_item = ITEM_FB_TICKS; break; } // for GP encoders and Datawheel switch( ui_selected_item ) { case ITEM_GXTY: return SEQ_UI_GxTyInc(incrementer); case ITEM_REPEATS: return SEQ_UI_CC_Inc(SEQ_CC_ECHO_REPEATS, 0, 15, incrementer); case ITEM_DELAY: { // for compatibility with older patches pre Beta30 u8 value = SEQ_CC_Get(visible_track, SEQ_CC_ECHO_DELAY); value = SEQ_CORE_Echo_MapInternalToUser(value); if( SEQ_UI_Var8_Inc(&value, 0, 21, incrementer) ) { value = SEQ_CORE_Echo_MapUserToInternal(value); SEQ_CC_Set(visible_track, SEQ_CC_ECHO_DELAY, value); return 1; } return 0; } break; case ITEM_VELOCITY: return SEQ_UI_CC_Inc(SEQ_CC_ECHO_VELOCITY, 0, 40, incrementer); case ITEM_FB_VELOCITY: return SEQ_UI_CC_Inc(SEQ_CC_ECHO_FB_VELOCITY, 0, 40, incrementer); case ITEM_FB_NOTE: return SEQ_UI_CC_Inc(SEQ_CC_ECHO_FB_NOTE, 0, 49, incrementer); case ITEM_FB_GATELENGTH: return SEQ_UI_CC_Inc(SEQ_CC_ECHO_FB_GATELENGTH, 0, 40, incrementer); case ITEM_FB_TICKS: return SEQ_UI_CC_Inc(SEQ_CC_ECHO_FB_TICKS, 0, 40, incrementer); } return -1; // invalid or unsupported encoder }
///////////////////////////////////////////////////////////////////////////// // Local encoder callback function // Should return: // 1 if value has been changed // 0 if value hasn't been changed // -1 if invalid or unsupported encoder ///////////////////////////////////////////////////////////////////////////// static s32 Encoder_Handler(seq_ui_encoder_t encoder, s32 incrementer) { #if 0 // leads to: comparison is always true due to limited range of data type if( (encoder >= SEQ_UI_ENCODER_GP1 && encoder <= SEQ_UI_ENCODER_GP16) ) { #else if( encoder <= SEQ_UI_ENCODER_GP16 ) { #endif if( seq_ui_button_state.SELECT_PRESSED ) { // select button pressed: indirect MUTED flag modification (taken over when select button depressed) u16 mask = 1 << encoder; if( incrementer < 0 || (incrementer == 0 && !(latched_mute & mask)) ) latched_mute |= mask; else latched_mute &= ~mask; } else { // select button not pressed: direct MUTED flag modification // access to seq_core_trk[] must be atomic! portENTER_CRITICAL(); u8 visible_track = SEQ_UI_VisibleTrackGet(); u16 mask = 1 << encoder; u16 *muted = seq_ui_button_state.MUTE_PRESSED ? (u16 *)&seq_core_trk[visible_track].layer_muted : (u16 *)&seq_core_trk_muted; if( incrementer < 0 ) *muted |= mask; else if( incrementer > 0 ) *muted &= ~mask; else *muted ^= mask; portEXIT_CRITICAL(); } return 1; // value changed } return -1; // invalid or unsupported encoder } ///////////////////////////////////////////////////////////////////////////// // Local button callback function // Should return: // 1 if value has been changed // 0 if value hasn't been changed // -1 if invalid or unsupported button ///////////////////////////////////////////////////////////////////////////// static s32 Button_Handler(seq_ui_button_t button, s32 depressed) { #if 0 // leads to: comparison is always true due to limited range of data type if( button >= SEQ_UI_BUTTON_GP1 && button <= SEQ_UI_BUTTON_GP16 ) { #else if( button <= SEQ_UI_BUTTON_GP16 ) { #endif if( depressed ) return 0; // ignore when button depressed // re-using encoder routine return Encoder_Handler(button, 0); } switch( button ) { case SEQ_UI_BUTTON_Select: portENTER_CRITICAL(); if( depressed ) { // select button released: take over latched mutes if( seq_ui_button_state.MUTE_PRESSED ) { u8 visible_track = SEQ_UI_VisibleTrackGet(); seq_core_trk[visible_track].layer_muted = latched_mute; } else { seq_core_trk_muted = latched_mute; } } else { // select pressed: init latched mutes which will be taken over once SELECT button released if( seq_ui_button_state.MUTE_PRESSED ) { u8 visible_track = SEQ_UI_VisibleTrackGet(); latched_mute = seq_core_trk[visible_track].layer_muted; } else { latched_mute = seq_core_trk_muted; } } portEXIT_CRITICAL(); return 1; } return -1; // invalid or unsupported button } ///////////////////////////////////////////////////////////////////////////// // Local Display Handler function // IN: <high_prio>: if set, a high-priority LCD update is requested ///////////////////////////////////////////////////////////////////////////// static s32 LCD_Handler(u8 high_prio) { // layout: // 00000000001111111111222222222233333333330000000000111111111122222222223333333333 // 01234567890123456789012345678901234567890123456789012345678901234567890123456789 // <--------------------------------------><--------------------------------------> // > 1< 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 // ...horizontal VU meters... if( high_prio ) { /////////////////////////////////////////////////////////////////////////// // frequently update VU meters SEQ_LCD_CursorSet(0, 1); u8 track; u16 mute_flags = 0; if( !ui_cursor_flash && seq_ui_button_state.SELECT_PRESSED ) { mute_flags = latched_mute; } else { if( seq_ui_button_state.MUTE_PRESSED ) { u8 visible_track = SEQ_UI_VisibleTrackGet(); mute_flags = seq_core_trk[visible_track].layer_muted; } else { mute_flags = seq_core_trk_muted; } } if( seq_ui_button_state.MUTE_PRESSED ) { u8 layer; for(layer=0; layer<16; ++layer) if( mute_flags & (1 << layer) ) SEQ_LCD_PrintString("Mute "); else SEQ_LCD_PrintHBar((seq_layer_vu_meter[layer] >> 3) & 0xf); } else { seq_core_trk_t *t = &seq_core_trk[0]; for(track=0; track<16; ++t, ++track) if( mute_flags & (1 << track) ) SEQ_LCD_PrintString("Mute "); else SEQ_LCD_PrintHBar(t->vu_meter >> 3); } } else {
///////////////////////////////////////////////////////////////////////////// // Local encoder callback function // Should return: // 1 if value has been changed // 0 if value hasn't been changed // -1 if invalid or unsupported encoder ///////////////////////////////////////////////////////////////////////////// static s32 Encoder_Handler(seq_ui_encoder_t encoder, s32 incrementer) { // ensure that original record screen will be print immediately ui_hold_msg_ctr = 0; switch( encoder ) { case SEQ_UI_ENCODER_GP1: ui_selected_item = ITEM_GXTY; break; case SEQ_UI_ENCODER_GP2: ui_selected_item = ITEM_MUTE; break; case SEQ_UI_ENCODER_GP3: ui_selected_item = ITEM_OCT_TRANSPOSE; break; case SEQ_UI_ENCODER_GP4: ui_selected_item = ITEM_LIVE_VELOCITY; break; case SEQ_UI_ENCODER_GP5: ui_selected_item = ITEM_LIVE_FORCE_SCALE; break; case SEQ_UI_ENCODER_GP6: ui_selected_item = ITEM_LIVE_FX; break; case SEQ_UI_ENCODER_GP7: case SEQ_UI_ENCODER_GP8: return 0; // not mapped (yet) break; case SEQ_UI_ENCODER_GP9: ui_selected_item = ITEM_IN_BUS; break; case SEQ_UI_ENCODER_GP10: ui_selected_item = ITEM_IN_PORT; break; case SEQ_UI_ENCODER_GP11: ui_selected_item = ITEM_IN_CHN; break; case SEQ_UI_ENCODER_GP12: ui_selected_item = ITEM_IN_LOWER; break; case SEQ_UI_ENCODER_GP13: ui_selected_item = ITEM_IN_UPPER; break; case SEQ_UI_ENCODER_GP14: ui_selected_item = ITEM_IN_MODE; break; case SEQ_UI_ENCODER_GP15: return -1; // not mapped case SEQ_UI_ENCODER_GP16: ui_selected_item = ITEM_RESET_STACKS; break; } // for GP encoders and Datawheel switch( ui_selected_item ) { case ITEM_GXTY: { if( !seq_midi_in_options[selected_bus].MODE_PLAY ) return -1; return SEQ_UI_GxTyInc(incrementer); } case ITEM_MUTE: { if( !seq_midi_in_options[selected_bus].MODE_PLAY ) return -1; u8 visible_track = SEQ_UI_VisibleTrackGet(); u16 mask = 1 << visible_track; if( incrementer < 0 ) seq_core_trk_muted |= mask; else seq_core_trk_muted &= ~mask; return 1; // value changed } break; case ITEM_OCT_TRANSPOSE: { if( !seq_midi_in_options[selected_bus].MODE_PLAY ) return -1; u8 tmp = seq_live_options.OCT_TRANSPOSE + 5; if( SEQ_UI_Var8_Inc(&tmp, 0, 10, incrementer) >= 0 ) { seq_live_options.OCT_TRANSPOSE = (s8)tmp - 5; store_file_required = 1; return 1; // value changed } return 0; // no change } break; case ITEM_LIVE_VELOCITY: { if( !seq_midi_in_options[selected_bus].MODE_PLAY ) return -1; if( SEQ_UI_Var8_Inc(&seq_live_options.VELOCITY, 1, 127, incrementer) >= 0 ) { store_file_required = 1; return 1; // value changed } return 0; // no change } case ITEM_LIVE_FORCE_SCALE: { if( !seq_midi_in_options[selected_bus].MODE_PLAY ) return -1; u8 tmp = seq_live_options.FORCE_SCALE; if( SEQ_UI_Var8_Inc(&tmp, 0, 1, incrementer) >= 0 ) { seq_live_options.FORCE_SCALE = tmp; store_file_required = 1; return 1; // value changed } return 0; // no change } case ITEM_LIVE_FX: { if( !seq_midi_in_options[selected_bus].MODE_PLAY ) return -1; u8 tmp = seq_live_options.FX; if( SEQ_UI_Var8_Inc(&tmp, 0, 1, incrementer) >= 0 ) { seq_live_options.FX = tmp; store_file_required = 1; return 1; // value changed } return 0; // no change } case ITEM_IN_BUS: { if( SEQ_UI_Var8_Inc(&selected_bus, 0, SEQ_MIDI_IN_NUM_BUSSES-1, incrementer) >= 0 ) { return 1; // value changed } return 0; // no change } break; case ITEM_IN_PORT: { u8 port_ix = SEQ_MIDI_PORT_InIxGet(seq_midi_in_port[selected_bus]); if( SEQ_UI_Var8_Inc(&port_ix, 0, SEQ_MIDI_PORT_InNumGet()-1-4, incrementer) >= 0 ) { // don't allow selection of Bus1..Bus4 seq_midi_in_port[selected_bus] = SEQ_MIDI_PORT_InPortGet(port_ix); store_file_required = 1; return 1; // value changed } return 0; // no change } break; case ITEM_IN_CHN: if( SEQ_UI_Var8_Inc(&seq_midi_in_channel[selected_bus], 0, 16, incrementer) >= 0 ) { store_file_required = 1; return 1; // value changed } return 0; // no change case ITEM_IN_LOWER: if( SEQ_UI_Var8_Inc(&seq_midi_in_lower[selected_bus], 0, 127, incrementer) >= 0 ) { store_file_required = 1; return 1; // value changed } return 0; // no change case ITEM_IN_UPPER: if( SEQ_UI_Var8_Inc(&seq_midi_in_upper[selected_bus], 0, 127, incrementer) >= 0 ) { store_file_required = 1; return 1; // value changed } return 0; // no change case ITEM_IN_MODE: { u8 fwd = seq_midi_in_options[selected_bus].MODE_PLAY; if( SEQ_UI_Var8_Inc(&fwd, 0, 1, incrementer) >= 0 ) { seq_midi_in_options[selected_bus].MODE_PLAY = fwd; store_file_required = 1; return 1; // value changed } return 0; // no change } break; case ITEM_RESET_STACKS: { SEQ_MIDI_IN_ResetTransArpStacks(); SEQ_UI_Msg(SEQ_UI_MSG_USER_R, 2000, "Transposer/Arp.", "Stacks cleared!"); return 1; } break; } return -1; // invalid or unsupported encoder }
///////////////////////////////////////////////////////////////////////////// // This hook is called before the shift register chain is scanned ///////////////////////////////////////////////////////////////////////////// void APP_SRIO_ServicePrepare(void) { static u8 led_digit_ctr = 0; if( ++led_digit_ctr >= 7 ) led_digit_ctr = 0; #ifndef MBSEQV4L if( seq_hwcfg_blm.enabled ) { // prepare DOUT registers of BLM to drive the column BLM_PrepareCol(); } #else BLM_CHEAPO_PrepareCol(); #endif if( seq_hwcfg_blm8x8.enabled ) { // prepare DOUT registers of 8x8 BLM to drive the row BLM_X_PrepareRow(); } // TK: using MIOS32_DOUT_SRSet/PinSet instead of SEQ_LED_SRSet/PinSet to ensure compatibility with MBSEQV4L if( seq_hwcfg_bpm_digits.enabled ) { // invert for common anodes u8 inversion_mask = (seq_hwcfg_bpm_digits.enabled == 2) ? 0xff : 0x00; u8 common_enable = (seq_hwcfg_bpm_digits.enabled == 2) ? 1 : 0; float bpm = SEQ_BPM_EffectiveGet(); if( led_digit_ctr == 0 ) { u8 sr_value = SEQ_LED_DigitPatternGet(((int)(bpm*10)) % 10); MIOS32_DOUT_SRSet(seq_hwcfg_bpm_digits.segments_sr - 1, sr_value ^ inversion_mask); MIOS32_DOUT_PinSet(seq_hwcfg_bpm_digits.common1_pin, common_enable); MIOS32_DOUT_PinSet(seq_hwcfg_bpm_digits.common2_pin, !common_enable); MIOS32_DOUT_PinSet(seq_hwcfg_bpm_digits.common3_pin, !common_enable); MIOS32_DOUT_PinSet(seq_hwcfg_bpm_digits.common4_pin, !common_enable); } else if( led_digit_ctr == 1 ) { u8 sr_value = SEQ_LED_DigitPatternGet((int)bpm % 10) | 0x80; // +dot MIOS32_DOUT_SRSet(seq_hwcfg_bpm_digits.segments_sr - 1, sr_value ^ inversion_mask); MIOS32_DOUT_PinSet(seq_hwcfg_bpm_digits.common1_pin, !common_enable); MIOS32_DOUT_PinSet(seq_hwcfg_bpm_digits.common2_pin, common_enable); MIOS32_DOUT_PinSet(seq_hwcfg_bpm_digits.common3_pin, !common_enable); MIOS32_DOUT_PinSet(seq_hwcfg_bpm_digits.common4_pin, !common_enable); } else if( led_digit_ctr == 2 ) { u8 sr_value = SEQ_LED_DigitPatternGet(((int)bpm / 10) % 10); MIOS32_DOUT_SRSet(seq_hwcfg_bpm_digits.segments_sr - 1, sr_value ^ inversion_mask); MIOS32_DOUT_PinSet(seq_hwcfg_bpm_digits.common1_pin, !common_enable); MIOS32_DOUT_PinSet(seq_hwcfg_bpm_digits.common2_pin, !common_enable); MIOS32_DOUT_PinSet(seq_hwcfg_bpm_digits.common3_pin, common_enable); MIOS32_DOUT_PinSet(seq_hwcfg_bpm_digits.common4_pin, !common_enable); } else if( led_digit_ctr == 3 ) { u8 sr_value = SEQ_LED_DigitPatternGet(((int)bpm / 100) % 10); MIOS32_DOUT_SRSet(seq_hwcfg_bpm_digits.segments_sr - 1, sr_value ^ inversion_mask); MIOS32_DOUT_PinSet(seq_hwcfg_bpm_digits.common1_pin, !common_enable); MIOS32_DOUT_PinSet(seq_hwcfg_bpm_digits.common2_pin, !common_enable); MIOS32_DOUT_PinSet(seq_hwcfg_bpm_digits.common3_pin, !common_enable); MIOS32_DOUT_PinSet(seq_hwcfg_bpm_digits.common4_pin, common_enable); } else { // not displaying bpm digit in this cycle, disable common pins MIOS32_DOUT_PinSet(seq_hwcfg_bpm_digits.common1_pin, !common_enable); MIOS32_DOUT_PinSet(seq_hwcfg_bpm_digits.common2_pin, !common_enable); MIOS32_DOUT_PinSet(seq_hwcfg_bpm_digits.common3_pin, !common_enable); MIOS32_DOUT_PinSet(seq_hwcfg_bpm_digits.common4_pin, !common_enable); } } if( seq_hwcfg_step_digits.enabled ) { // invert for common anodes u8 inversion_mask = (seq_hwcfg_step_digits.enabled == 2) ? 0xff : 0x00; u8 common_enable = (seq_hwcfg_step_digits.enabled == 2) ? 1 : 0; int step = (int)(SEQ_BPM_IsRunning() ? seq_core_trk[SEQ_UI_VisibleTrackGet()].step : ui_selected_step) + 1; if( led_digit_ctr == 4 ) { u8 sr_value = SEQ_LED_DigitPatternGet(step % 10); MIOS32_DOUT_SRSet(seq_hwcfg_step_digits.segments_sr - 1, sr_value ^ inversion_mask); MIOS32_DOUT_PinSet(seq_hwcfg_step_digits.common1_pin, common_enable); MIOS32_DOUT_PinSet(seq_hwcfg_step_digits.common2_pin, !common_enable); MIOS32_DOUT_PinSet(seq_hwcfg_step_digits.common3_pin, !common_enable); } else if( led_digit_ctr == 5 ) { u8 sr_value = SEQ_LED_DigitPatternGet((step / 10) % 10); MIOS32_DOUT_SRSet(seq_hwcfg_step_digits.segments_sr - 1, sr_value ^ inversion_mask); MIOS32_DOUT_PinSet(seq_hwcfg_step_digits.common1_pin, !common_enable); MIOS32_DOUT_PinSet(seq_hwcfg_step_digits.common2_pin, common_enable); MIOS32_DOUT_PinSet(seq_hwcfg_step_digits.common3_pin, !common_enable); } else if( led_digit_ctr == 6 ) { u8 sr_value = SEQ_LED_DigitPatternGet((step / 100) % 10); MIOS32_DOUT_SRSet(seq_hwcfg_step_digits.segments_sr - 1, sr_value ^ inversion_mask); MIOS32_DOUT_PinSet(seq_hwcfg_step_digits.common1_pin, !common_enable); MIOS32_DOUT_PinSet(seq_hwcfg_step_digits.common2_pin, !common_enable); MIOS32_DOUT_PinSet(seq_hwcfg_step_digits.common3_pin, common_enable); } else { // not displaying step digit in this cycle, disable common pins MIOS32_DOUT_PinSet(seq_hwcfg_step_digits.common1_pin, !common_enable); MIOS32_DOUT_PinSet(seq_hwcfg_step_digits.common2_pin, !common_enable); MIOS32_DOUT_PinSet(seq_hwcfg_step_digits.common3_pin, !common_enable); } } SEQ_TPD_LED_Update(); }
///////////////////////////////////////////////////////////////////////////// // Local encoder callback function // Should return: // 1 if value has been changed // 0 if value hasn't been changed // -1 if invalid or unsupported encoder ///////////////////////////////////////////////////////////////////////////// static s32 Encoder_Handler(seq_ui_encoder_t encoder, s32 incrementer) { u8 visible_track = SEQ_UI_VisibleTrackGet(); switch( encoder ) { case SEQ_UI_ENCODER_GP1: ui_selected_item = ITEM_GXTY; break; case SEQ_UI_ENCODER_GP2: case SEQ_UI_ENCODER_GP3: case SEQ_UI_ENCODER_GP4: ui_selected_item = ITEM_GROOVE_STYLE; break; case SEQ_UI_ENCODER_GP5: case SEQ_UI_ENCODER_GP6: ui_selected_item = ITEM_GROOVE_VALUE; break; case SEQ_UI_ENCODER_GP7: case SEQ_UI_ENCODER_GP8: ui_selected_item = ITEM_GROOVE_VALUE_GLB; break; case SEQ_UI_ENCODER_GP9: ui_selected_item = ITEM_GROOVE_STEP; break; case SEQ_UI_ENCODER_GP10: ui_selected_item = ITEM_GROOVE_DELAY; break; case SEQ_UI_ENCODER_GP11: ui_selected_item = ITEM_GROOVE_LENGTH; break; case SEQ_UI_ENCODER_GP12: ui_selected_item = ITEM_GROOVE_VELOCITY; break; case SEQ_UI_ENCODER_GP13: ui_selected_item = ITEM_GROOVE_NUM_STEPS; break; case SEQ_UI_ENCODER_GP14: case SEQ_UI_ENCODER_GP15: case SEQ_UI_ENCODER_GP16: return -1; // not mapped yet } // for GP encoders and Datawheel u8 grooves_total = SEQ_GROOVE_NUM_PRESETS+SEQ_GROOVE_NUM_TEMPLATES; u8 selected_groove = SEQ_CC_Get(visible_track, SEQ_CC_GROOVE_STYLE); s32 groove_template = selected_groove - SEQ_GROOVE_NUM_PRESETS; // negative if not a custom template seq_groove_entry_t *g; if( selected_groove >= SEQ_GROOVE_NUM_PRESETS ) g = (seq_groove_entry_t *)&seq_groove_templates[selected_groove-SEQ_GROOVE_NUM_PRESETS]; else g = (seq_groove_entry_t *)&seq_groove_presets[selected_groove]; switch( ui_selected_item ) { case ITEM_GXTY: return SEQ_UI_GxTyInc(incrementer); case ITEM_GROOVE_STYLE: return SEQ_UI_CC_Inc(SEQ_CC_GROOVE_STYLE, 0, grooves_total-1, incrementer); case ITEM_GROOVE_VALUE: return SEQ_UI_CC_Inc(SEQ_CC_GROOVE_VALUE, 0, 127, incrementer); case ITEM_GROOVE_STEP: return SEQ_UI_Var8_Inc(&edit_step, 0, g->num_steps-1, incrementer); case ITEM_GROOVE_VALUE_GLB: { if( SEQ_UI_CC_Inc(SEQ_CC_GROOVE_VALUE, 0, 127, incrementer) > 0 ) { // change value for all tracks u8 value = SEQ_CC_Get(visible_track, SEQ_CC_GROOVE_VALUE); u8 track; for(track=0; track<SEQ_CORE_NUM_TRACKS; ++track) { SEQ_CC_Set(track, SEQ_CC_GROOVE_VALUE, value); } return 1; } return 0; } case ITEM_GROOVE_DELAY: { if( groove_template < 0 || groove_template >= SEQ_GROOVE_NUM_TEMPLATES ) return 0; u8 value = (u8)seq_groove_templates[groove_template].add_step_delay[edit_step] + 128; if( SEQ_UI_Var8_Inc(&value, 0, 255, incrementer) > 0 ) { seq_groove_templates[groove_template].add_step_delay[edit_step] = (s8)(value - 128); ui_store_file_required = 1; return 1; } return 0; } case ITEM_GROOVE_LENGTH: { if( groove_template < 0 || groove_template >= SEQ_GROOVE_NUM_TEMPLATES ) return 0; u8 value = (u8)seq_groove_templates[groove_template].add_step_length[edit_step] + 128; if( SEQ_UI_Var8_Inc(&value, 0, 255, incrementer) > 0 ) { seq_groove_templates[groove_template].add_step_length[edit_step] = (s8)(value - 128); ui_store_file_required = 1; return 1; } return 0; } case ITEM_GROOVE_VELOCITY: { if( groove_template < 0 || groove_template >= SEQ_GROOVE_NUM_TEMPLATES ) return 0; u8 value = (u8)seq_groove_templates[groove_template].add_step_velocity[edit_step] + 128; if( SEQ_UI_Var8_Inc(&value, 0, 255, incrementer) > 0 ) { seq_groove_templates[groove_template].add_step_velocity[edit_step] = (s8)(value - 128); ui_store_file_required = 1; return 1; } return 0; } case ITEM_GROOVE_NUM_STEPS: { if( groove_template < 0 || groove_template >= SEQ_GROOVE_NUM_TEMPLATES ) return 0; u8 value = (u8)seq_groove_templates[groove_template].num_steps; if( SEQ_UI_Var8_Inc(&value, 1, 16, incrementer) > 0 ) { seq_groove_templates[groove_template].num_steps = value; ui_store_file_required = 1; return 1; } return 0; } } return -1; // invalid or unsupported encoder }
///////////////////////////////////////////////////////////////////////////// // Local Display Handler function // IN: <high_prio>: if set, a high-priority LCD update is requested ///////////////////////////////////////////////////////////////////////////// static s32 LCD_Handler(u8 high_prio) { if( high_prio ) return 0; // there are no high-priority updates // layout: // 00000000001111111111222222222233333333330000000000111111111122222222223333333333 // 01234567890123456789012345678901234567890123456789012345678901234567890123456789 // <--------------------------------------><--------------------------------------> // Trk. off Transpose Bus Hold Sort Restart ForceScale Sustain // G1T1 >Normal< Arpeggiator 1 on on on on on u8 visible_track = SEQ_UI_VisibleTrackGet(); /////////////////////////////////////////////////////////////////////////// SEQ_LCD_CursorSet(0, 0); SEQ_LCD_PrintString("Trk."); SEQ_LCD_CursorSet(0, 1); if( ui_selected_item == ITEM_GXTY && ui_cursor_flash ) { SEQ_LCD_PrintSpaces(9); } else { SEQ_LCD_PrintGxTy(ui_selected_group, ui_selected_tracks); SEQ_LCD_PrintSpaces(5); } /////////////////////////////////////////////////////////////////////////// const char mode_names[7][14] = { ">off< ", ">Normal< ", ">Transpose< ", ">Arpeggiator<" }; int i; int selected_mode = SEQ_CC_Get(visible_track, SEQ_CC_MODE); for(i=0; i<4; ++i) { u8 x = 4 + 5*i; SEQ_LCD_CursorSet(x, i%2); // print unmodified name if item selected // replace '>' and '<' by space if item not selected // flash item (print only '>'/'<' and spaces) if cursor position == 1 and flash flag set by timer int j; for(j=0; j<13; ++j) { u8 c = mode_names[i][j]; if( ++x > 35 ) // don't print more than 35 characters per line break; if( c == '>' || c == '<' ) { SEQ_LCD_PrintChar((i == selected_mode) ? c : ' '); } else { if( ui_selected_item == ITEM_MODE && i == selected_mode && ui_cursor_flash ) SEQ_LCD_PrintChar(' '); else SEQ_LCD_PrintChar(c); } } } // additional spaces to fill LCD (avoids artefacts on page switches) SEQ_LCD_CursorSet(25, 0); SEQ_LCD_PrintSpaces(15); SEQ_LCD_CursorSet(32, 1); SEQ_LCD_PrintSpaces(8); /////////////////////////////////////////////////////////////////////////// SEQ_LCD_CursorSet(35, 0); SEQ_LCD_PrintString(" Bus Hold Sort Restart ForceScale Sustain "); SEQ_LCD_CursorSet(35, 1); /////////////////////////////////////////////////////////////////////////// if( ui_selected_item == ITEM_BUS && ui_cursor_flash ) { SEQ_LCD_PrintSpaces(3); } else { SEQ_LCD_PrintFormattedString(" %d", SEQ_CC_Get(visible_track, SEQ_CC_BUSASG) + 1); } SEQ_LCD_PrintSpaces(3); /////////////////////////////////////////////////////////////////////////// if( ui_selected_item == ITEM_HOLD && ui_cursor_flash ) { SEQ_LCD_PrintSpaces(3); } else { SEQ_LCD_PrintString((SEQ_CC_Get(visible_track, SEQ_CC_MODE_FLAGS) & (1 << 1)) ? "on " : "off"); } SEQ_LCD_PrintSpaces(2); /////////////////////////////////////////////////////////////////////////// if( ui_selected_item == ITEM_SORT && ui_cursor_flash ) { SEQ_LCD_PrintSpaces(3); } else { SEQ_LCD_PrintString((SEQ_CC_Get(visible_track, SEQ_CC_MODE_FLAGS) & (1 << 0)) ? "off" : "on "); // SORT is inverted! } SEQ_LCD_PrintSpaces(4); /////////////////////////////////////////////////////////////////////////// if( ui_selected_item == ITEM_RESTART && ui_cursor_flash ) { SEQ_LCD_PrintSpaces(3); } else { SEQ_LCD_PrintString((SEQ_CC_Get(visible_track, SEQ_CC_MODE_FLAGS) & (1 << 2)) ? "on " : "off"); } SEQ_LCD_PrintSpaces(7); /////////////////////////////////////////////////////////////////////////// if( ui_selected_item == ITEM_FORCE_SCALE && ui_cursor_flash ) { SEQ_LCD_PrintSpaces(3); } else { SEQ_LCD_PrintString((SEQ_CC_Get(visible_track, SEQ_CC_MODE_FLAGS) & (1 << 3)) ? "on " : "off"); } SEQ_LCD_PrintSpaces(8); /////////////////////////////////////////////////////////////////////////// if( ui_selected_item == ITEM_SUSTAIN && ui_cursor_flash ) { SEQ_LCD_PrintSpaces(3); } else { SEQ_LCD_PrintString((SEQ_CC_Get(visible_track, SEQ_CC_MODE_FLAGS) & (1 << 4)) ? "on " : "off"); } SEQ_LCD_PrintSpaces(3); return 0; // no error }
///////////////////////////////////////////////////////////////////////////// // Local Display Handler function // IN: <high_prio>: if set, a high-priority LCD update is requested ///////////////////////////////////////////////////////////////////////////// static s32 LCD_Handler(u8 high_prio) { u8 visible_track = SEQ_UI_VisibleTrackGet(); if( high_prio ) return 0; // there are no high-priority updates // layout: // 00000000001111111111222222222233333333330000000000111111111122222222223333333333 // 01234567890123456789012345678901234567890123456789012345678901234567890123456789 // <--------------------------------------><--------------------------------------> // Trk. Mute Oct. Vel. FTS Fx Bus Port Chn. Lower/Upper Mode Reset // G1T1 +0 100 on on 1 IN1 #16 --- --- T&A Stacks // The selected Bus1 is not configured Bus Port Chn. Lower/Upper Mode Reset // for Play mode (but for Transposer&Arp.) 1 IN1 #16 --- --- T&A Stacks /////////////////////////////////////////////////////////////////////////// SEQ_LCD_CursorSet(0, 0); if( !seq_midi_in_options[selected_bus].MODE_PLAY ) { SEQ_LCD_PrintFormattedString("The selected Bus%d is not configured ", selected_bus+1); } else { SEQ_LCD_PrintString("Trk. Mute Oct. Vel. FTS Fx "); } SEQ_LCD_CursorSet(40, 0); SEQ_LCD_PrintString(" Bus Port Chn. Lower/Upper Mode Reset "); /////////////////////////////////////////////////////////////////////////// SEQ_LCD_CursorSet(0, 1); if( !seq_midi_in_options[selected_bus].MODE_PLAY ) { SEQ_LCD_PrintString("for Play mode (but for Transposer&Arp.) "); } else { if( ui_selected_item == ITEM_GXTY && ui_cursor_flash ) { SEQ_LCD_PrintSpaces(4); } else { SEQ_LCD_PrintGxTy(ui_selected_group, ui_selected_tracks); } SEQ_LCD_PrintSpaces(1); /////////////////////////////////////////////////////////////////////////// if( ui_selected_item == ITEM_MUTE && ui_cursor_flash ) { SEQ_LCD_PrintSpaces(5); } else { SEQ_LCD_PrintSpaces(2); SEQ_LCD_PrintChar((seq_core_trk_muted & (1 << visible_track)) ? '*' : 'o'); SEQ_LCD_PrintSpaces(2); } /////////////////////////////////////////////////////////////////////////// if( ui_selected_item == ITEM_OCT_TRANSPOSE && ui_cursor_flash ) { SEQ_LCD_PrintSpaces(4); } else { u8 event_mode = SEQ_CC_Get(visible_track, SEQ_CC_MIDI_EVENT_MODE); if( event_mode == SEQ_EVENT_MODE_Drum ) { SEQ_LCD_PrintString("Drum"); } else { SEQ_LCD_PrintFormattedString(" %c%d ", (seq_live_options.OCT_TRANSPOSE < 0) ? '-' : '+', abs(seq_live_options.OCT_TRANSPOSE)); } } SEQ_LCD_PrintSpaces(1); /////////////////////////////////////////////////////////////////////////// if( ui_selected_item == ITEM_LIVE_VELOCITY && ui_cursor_flash ) { SEQ_LCD_PrintSpaces(3); } else { SEQ_LCD_PrintFormattedString("%3d", seq_live_options.VELOCITY); } SEQ_LCD_PrintSpaces(2); /////////////////////////////////////////////////////////////////////////// if( ui_selected_item == ITEM_LIVE_FORCE_SCALE && ui_cursor_flash ) { SEQ_LCD_PrintSpaces(3); } else { SEQ_LCD_PrintString(seq_live_options.FORCE_SCALE ? " on" : "off"); } SEQ_LCD_PrintSpaces(2); /////////////////////////////////////////////////////////////////////////// if( ui_selected_item == ITEM_LIVE_FX && ui_cursor_flash ) { SEQ_LCD_PrintSpaces(3); } else { SEQ_LCD_PrintString(seq_live_options.FX ? " on" : "off"); } SEQ_LCD_PrintSpaces(2 + 10); } /////////////////////////////////////////////////////////////////////// if( ui_selected_item == ITEM_IN_BUS && ui_cursor_flash ) { SEQ_LCD_PrintSpaces(5); } else { SEQ_LCD_PrintFormattedString(" %d ", selected_bus+1); } /////////////////////////////////////////////////////////////////////// if( ui_selected_item == ITEM_IN_PORT && ui_cursor_flash ) { SEQ_LCD_PrintSpaces(4); } else { if( seq_midi_in_port[selected_bus] ) SEQ_LCD_PrintString(SEQ_MIDI_PORT_InNameGet(SEQ_MIDI_PORT_InIxGet(seq_midi_in_port[selected_bus]))); else SEQ_LCD_PrintString(" All"); } SEQ_LCD_PrintSpaces(1); /////////////////////////////////////////////////////////////////////// if( ui_selected_item == ITEM_IN_CHN && ui_cursor_flash ) { SEQ_LCD_PrintSpaces(3); } else { if( seq_midi_in_channel[selected_bus] ) SEQ_LCD_PrintFormattedString("#%2d", seq_midi_in_channel[selected_bus]); else SEQ_LCD_PrintString("---"); } SEQ_LCD_PrintSpaces(3); /////////////////////////////////////////////////////////////////////// if( ui_selected_item == ITEM_IN_LOWER && ui_cursor_flash ) { SEQ_LCD_PrintSpaces(3); } else { SEQ_LCD_PrintNote(seq_midi_in_lower[selected_bus]); } SEQ_LCD_PrintSpaces(3); /////////////////////////////////////////////////////////////////////// if( ui_selected_item == ITEM_IN_UPPER && ui_cursor_flash ) { SEQ_LCD_PrintSpaces(3); } else { SEQ_LCD_PrintNote(seq_midi_in_upper[selected_bus]); } SEQ_LCD_PrintSpaces(2); /////////////////////////////////////////////////////////////////////// if( ui_selected_item == ITEM_IN_MODE && ui_cursor_flash ) { SEQ_LCD_PrintSpaces(4); } else { SEQ_LCD_PrintString(seq_midi_in_options[selected_bus].MODE_PLAY ? "Play" : "T&A "); } SEQ_LCD_PrintSpaces(3); SEQ_LCD_PrintString("Stacks"); return 0; // no error }
///////////////////////////////////////////////////////////////////////////// // Local encoder callback function // Should return: // 1 if value has been changed // 0 if value hasn't been changed // -1 if invalid or unsupported encoder ///////////////////////////////////////////////////////////////////////////// static s32 Encoder_Handler(seq_ui_encoder_t encoder, s32 incrementer) { u8 visible_track = SEQ_UI_VisibleTrackGet(); switch( encoder ) { case SEQ_UI_ENCODER_GP1: ui_selected_item = ITEM_GXTY; break; case SEQ_UI_ENCODER_GP2: case SEQ_UI_ENCODER_GP3: case SEQ_UI_ENCODER_GP4: case SEQ_UI_ENCODER_GP5: ui_selected_item = ITEM_MODE; SEQ_UI_CC_Set(SEQ_CC_MODE, encoder-1); return 1; case SEQ_UI_ENCODER_GP6: case SEQ_UI_ENCODER_GP7: return -1; // not mapped case SEQ_UI_ENCODER_GP8: ui_selected_item = ITEM_BUS; break; case SEQ_UI_ENCODER_GP9: ui_selected_item = ITEM_HOLD; break; case SEQ_UI_ENCODER_GP10: ui_selected_item = ITEM_SORT; break; case SEQ_UI_ENCODER_GP11: case SEQ_UI_ENCODER_GP12: ui_selected_item = ITEM_RESTART; break; case SEQ_UI_ENCODER_GP13: case SEQ_UI_ENCODER_GP14: ui_selected_item = ITEM_FORCE_SCALE; break; case SEQ_UI_ENCODER_GP15: case SEQ_UI_ENCODER_GP16: ui_selected_item = ITEM_SUSTAIN; break; } // for GP encoders and Datawheel switch( ui_selected_item ) { case ITEM_GXTY: return SEQ_UI_GxTyInc(incrementer); case ITEM_MODE: return SEQ_UI_CC_Inc(SEQ_CC_MODE, 0, 3, incrementer); case ITEM_BUS: return SEQ_UI_CC_Inc(SEQ_CC_BUSASG, 0, 3, incrementer); case ITEM_HOLD: if( !incrementer ) // toggle flag incrementer = (SEQ_CC_Get(visible_track, SEQ_CC_MODE_FLAGS) & (1<<1)) ? -1 : 1; return SEQ_UI_CC_SetFlags(SEQ_CC_MODE_FLAGS, (1<<1), (incrementer >= 0) ? (1<<1) : 0); case ITEM_SORT: if( !incrementer ) // toggle flag - SORT is inverted! incrementer = (SEQ_CC_Get(visible_track, SEQ_CC_MODE_FLAGS) & (1<<0)) ? 1 : -1; return SEQ_UI_CC_SetFlags(SEQ_CC_MODE_FLAGS, (1<<0), (incrementer >= 0) ? 0 : (1<<0)); // SORT is inverted! case ITEM_RESTART: if( !incrementer ) // toggle flag incrementer = (SEQ_CC_Get(visible_track, SEQ_CC_MODE_FLAGS) & (1<<2)) ? -1 : 1; return SEQ_UI_CC_SetFlags(SEQ_CC_MODE_FLAGS, (1<<2), (incrementer >= 0) ? (1<<2) : 0); case ITEM_FORCE_SCALE: if( !incrementer ) // toggle flag incrementer = (SEQ_CC_Get(visible_track, SEQ_CC_MODE_FLAGS) & (1<<3)) ? -1 : 1; return SEQ_UI_CC_SetFlags(SEQ_CC_MODE_FLAGS, (1<<3), (incrementer >= 0) ? (1<<3) : 0); case ITEM_SUSTAIN: if( !incrementer ) // toggle flag incrementer = (SEQ_CC_Get(visible_track, SEQ_CC_MODE_FLAGS) & (1<<4)) ? -1 : 1; return SEQ_UI_CC_SetFlags(SEQ_CC_MODE_FLAGS, (1<<4), (incrementer >= 0) ? (1<<4) : 0); } return -1; // invalid or unsupported encoder }
///////////////////////////////////////////////////////////////////////////// // Frequently called to return the status of GP LEDs ///////////////////////////////////////////////////////////////////////////// u16 SEQ_UI_PAGES_GP_LED_Handler(void) { if( ui_controller_mode ) return SEQ_UI_PAGES_GP_LED_Handler_Controller(); static u16 check_100mS_ctr = 0; if( load_save_notifier_ctr ) --load_save_notifier_ctr; u8 visible_track = SEQ_UI_VisibleTrackGet(); // for periodic checks (e.g. of selections derived from patches) if( ++check_100mS_ctr >= 100 ) check_100mS_ctr = 0; // clear button pressed: print track activity if( seq_ui_button_state.CLEAR ) { return ui_track_activity_state; } switch( ui_page ) { /////////////////////////////////////////////////////////////////////////// case SEQ_UI_PAGE_LOAD: case SEQ_UI_PAGE_SAVE: { u8 group = 0; u16 leds = (1 << ui_selected_pattern[group].group) | (1 << (ui_selected_pattern[group].num+8)); if( ui_selected_pattern_changing && ui_cursor_flash ) leds &= 0x00ff; // invert LEDs each 50 mS if load/save notifier active if( load_save_notifier_ctr && (load_save_notifier_ctr % 100) >= 50 ) leds ^= 0xffff; return leds; } break; /////////////////////////////////////////////////////////////////////////// case SEQ_UI_PAGE_TRIGGER: { u8 *trg_ptr = (u8 *)&seq_trg_layer_value[visible_track][2*ui_selected_step_view]; u16 leds = *trg_ptr; ++trg_ptr; leds |= (*trg_ptr << 8); return leds; } break; /////////////////////////////////////////////////////////////////////////// case SEQ_UI_PAGE_REC_STEP: case SEQ_UI_PAGE_REC_LIVE: { u8 record_track = 8; if( seq_record_state.ARMED_TRACKS & (1 << 0) ) record_track = 0; u8 *trg_ptr = (u8 *)&seq_trg_layer_value[record_track][2*ui_selected_step_view]; u16 leds = *trg_ptr; ++trg_ptr; leds |= (*trg_ptr << 8); u16 record_step_mask = (1 << (seq_record_step % 16)); if( ui_cursor_flash && ((seq_record_step >> 4) == ui_selected_step_view) ) { leds ^= record_step_mask; } // button of selected step always active as long as GP button is pressed if( ui_selected_gp_buttons & record_step_mask ) leds |= record_step_mask; return leds; } break; /////////////////////////////////////////////////////////////////////////// case SEQ_UI_PAGE_LENGTH: { u16 leds = 0x0000; u8 length = SEQ_CC_Get(visible_track, SEQ_CC_LENGTH); u8 loop = SEQ_CC_Get(visible_track, SEQ_CC_LOOP); if( length >= 16*(ui_selected_step_view+1) ) leds = 0xffff; else if( (length >> 4) == ui_selected_step_view ) leds = (1 << ((length % 16)+1))-1; if( ui_cursor_flash ) { if( (loop/16) == ui_selected_step_view ) leds &= ~(1 << loop % 16); if( (length/16) == ui_selected_step_view ) leds &= ~(1 << length % 16); } return leds; } break; /////////////////////////////////////////////////////////////////////////// case SEQ_UI_PAGE_PROGRESSION: { // check if selection still valid if( check_100mS_ctr == 0 ) { seq_cc_trk_t *tcc = &seq_cc_trk[visible_track]; seq_ui_pages_progression_presets_t *preset = (seq_ui_pages_progression_presets_t *)&seq_ui_pages_progression_presets[0]; int i; for(i=0; i<16; ++i, ++preset) { if( ((u8)tcc->steps_forward+1) == preset->steps_forward && tcc->steps_jump_back == preset->steps_jump_back && tcc->steps_replay == preset->steps_replay && tcc->steps_repeat == preset->steps_repeat && tcc->steps_skip == preset->steps_skip && tcc->steps_rs_interval == preset->steps_rs_interval ) { ui_selected_progression_preset = i; break; } } } return (1 << ui_selected_progression_preset); } break; /////////////////////////////////////////////////////////////////////////// case SEQ_UI_PAGE_GROOVE: { u8 groove_style = SEQ_CC_Get(visible_track, SEQ_CC_GROOVE_STYLE); if( groove_style < 8 || groove_style > 22 ) return 0x0001; // off resp. non-selectable value else // note: starting at second custom groove, the first groove is always "off" return (1 << (groove_style-8+1)); } break; /////////////////////////////////////////////////////////////////////////// case SEQ_UI_PAGE_ECHO: { // check if selection still valid if( check_100mS_ctr == 0 ) { seq_cc_trk_t *tcc = &seq_cc_trk[visible_track]; seq_ui_pages_echo_presets_t *preset = (seq_ui_pages_echo_presets_t *)&seq_ui_pages_echo_presets[0]; int i; for(i=0; i<16; ++i, ++preset) { if( tcc->echo_repeats == preset->repeats && tcc->echo_delay == preset->delay && tcc->echo_velocity == preset->velocity && tcc->echo_fb_velocity == preset->fb_velocity && tcc->echo_fb_note == preset->fb_note && tcc->echo_fb_gatelength == preset->fb_gatelength && tcc->echo_fb_ticks == preset->fb_ticks ) { ui_selected_echo_preset = i; break; } } } return (1 << ui_selected_echo_preset); } break; /////////////////////////////////////////////////////////////////////////// case SEQ_UI_PAGE_HUMANIZER: { // check if selection still valid if( check_100mS_ctr == 0 ) { seq_cc_trk_t *tcc = &seq_cc_trk[visible_track]; seq_ui_pages_humanizer_presets_t *preset = (seq_ui_pages_humanizer_presets_t *)&seq_ui_pages_humanizer_presets[0]; int i; for(i=0; i<16; ++i, ++preset) { if( tcc->humanize_mode == preset->mode && tcc->humanize_value == preset->value ) { ui_selected_humanizer_preset = i; break; } } } return (1 << ui_selected_humanizer_preset); } break; /////////////////////////////////////////////////////////////////////////// case SEQ_UI_PAGE_LFO: { // check if selection still valid if( check_100mS_ctr == 0 ) { seq_cc_trk_t *tcc = &seq_cc_trk[visible_track]; seq_ui_pages_lfo_presets_t *preset = (seq_ui_pages_lfo_presets_t *)&seq_ui_pages_lfo_presets[0]; int i; for(i=0; i<16; ++i, ++preset) { if( tcc->lfo_waveform == preset->waveform && tcc->lfo_amplitude == preset->amplitude && tcc->lfo_phase == preset->phase && tcc->lfo_steps == preset->steps && tcc->lfo_steps_rst == preset->steps_rst && tcc->lfo_enable_flags.ALL == preset->enable_flags && tcc->lfo_cc == preset->cc && tcc->lfo_cc_offset == preset->cc_offset && tcc->lfo_cc_ppqn == preset->cc_ppqn ) { ui_selected_lfo_preset = i; break; } } } return (1 << ui_selected_lfo_preset); } break; /////////////////////////////////////////////////////////////////////////// case SEQ_UI_PAGE_SCALE: { // check if selection still valid if( check_100mS_ctr == 0 ) { u8 note_track = 8; if( ui_selected_tracks & (1 << 0) ) note_track = 0; if( !seq_cc_trk[note_track].mode.FORCE_SCALE ) ui_selected_scale = 0; else { u8 *preset = (u8 *)&seq_ui_pages_scale_presets[1]; int i; for(i=1; i<16; ++i, ++preset) if( seq_core_global_scale == *preset ) break; ui_selected_scale = (i > 15) ? 15 : i; // if no preset scale, show last LED } } if( seq_ui_button_state.SCALE_PRESSED ) return (1 << ui_selected_scale); if( seq_core_global_scale_root_selection ) return (1 << (seq_core_global_scale_root_selection-1)); // selected scale else return 0xf000 | (1 << seq_core_keyb_scale_root); // scale via keyboard } break; /////////////////////////////////////////////////////////////////////////// case SEQ_UI_PAGE_MUTE: { u16 muted = seq_core_trk_muted; if( ui_cursor_flash && seq_ui_button_state.SOLO ) { //muted |= !ui_selected_tracks; // doesn't work with gcc version 4.2.1 ?!? muted |= ui_selected_tracks ^ 0xffff; } return muted; } break; /////////////////////////////////////////////////////////////////////////// case SEQ_UI_PAGE_MIDICHN: { u8 chn = SEQ_CC_Get(visible_track, SEQ_CC_MIDI_CHANNEL); return (1 << chn); } break; /////////////////////////////////////////////////////////////////////////// case SEQ_UI_PAGE_REC_ARM: { return seq_record_state.ARMED_TRACKS; } break; /////////////////////////////////////////////////////////////////////////// case SEQ_UI_PAGE_TEMPO: { // check if selection still valid if( check_100mS_ctr == 0 ) { seq_cc_trk_t *tcc = &seq_cc_trk[visible_track]; seq_ui_pages_tempo_presets_t *preset = (seq_ui_pages_tempo_presets_t *)&seq_ui_pages_tempo_presets[0]; int i; for(i=0; i<16; ++i, ++preset) { if( tcc->clkdiv.value == preset->clkdiv && tcc->clkdiv.TRIPLETS == preset->triplets ) { ui_selected_tempo_preset = i; break; } } } return (1 << ui_selected_tempo_preset); } break; } return 0x0000; }