///////////////////////////////////////////////////////////////////////////// // LED update routine ///////////////////////////////////////////////////////////////////////////// s32 SEQ_TPD_LED_Update(void) { static u8 cycle_ctr = 0; if (cycle_ctr++ > 8) cycle_ctr = 0; // Power the corresponding column anode of this cycle MIOS32_DOUT_SRSet(seq_hwcfg_tpd.columns_sr - 1, (1 << cycle_ctr)); // Determine upper relative track position (tracks 1-8, "fall upward") s32 steps = SEQ_CC_Get(cycle_ctr, SEQ_CC_LENGTH); s32 curstep = seq_core_trk[cycle_ctr].step; u8 relpos_upper = 3 - (s32)(curstep << 2) / steps; // Determine lower relative track position (tracks 9-16, "fall downward") steps = SEQ_CC_Get(cycle_ctr + 8, SEQ_CC_LENGTH); curstep = seq_core_trk[cycle_ctr + 8].step; u8 relpos_lower = 4 + (s32)(curstep << 2)/ steps; // Gate the corresponding cathodes of this cycle (if the tracks are not muted) u8 setbyte = 0xFF; if (!(seq_core_trk_muted & (1 << cycle_ctr))) setbyte ^= (1 << relpos_upper); if (!(seq_core_trk_muted & (1 << (cycle_ctr + 8)))) setbyte ^= (1 << relpos_lower); MIOS32_DOUT_SRSet(seq_hwcfg_tpd.rows_sr - 1, setbyte); return 0; // no error }
s32 SEQ_TERMINAL_PrintTracks(void *_output_function) { void (*out)(char *format, ...) = _output_function; char str_buffer[128]; MUTEX_MIDIOUT_TAKE; out("Track Overview:\n"); out("===============\n"); out("| Track | Mode | Layer P/T/I | Steps P/T | Length | Port | Chn. | Muted |\n"); out("+-------+-------+-------------+-----------+--------+-------+------+-------+\n"); u8 track; for(track=0; track<SEQ_CORE_NUM_TRACKS; ++track) { seq_event_mode_t event_mode = SEQ_CC_Get(track, SEQ_CC_MIDI_EVENT_MODE); u16 num_instruments = SEQ_TRG_NumInstrumentsGet(track); u16 num_par_layers = SEQ_PAR_NumLayersGet(track); u16 num_par_steps = SEQ_PAR_NumStepsGet(track); u16 num_trg_layers = SEQ_TRG_NumLayersGet(track); u16 num_trg_steps = SEQ_TRG_NumStepsGet(track); u16 length = (u16)SEQ_CC_Get(track, SEQ_CC_LENGTH) + 1; mios32_midi_port_t midi_port = SEQ_CC_Get(track, SEQ_CC_MIDI_PORT); u8 midi_chn = SEQ_CC_Get(track, SEQ_CC_MIDI_CHANNEL) + 1; sprintf(str_buffer, "| G%dT%d | %s |", (track/4)+1, (track%4)+1, SEQ_LAYER_GetEvntModeName(event_mode)); sprintf((char *)(str_buffer + strlen(str_buffer)), " %2d/%2d/%2d | %3d/%3d | %3d | %s%c | %2d |", num_par_layers, num_trg_layers, num_instruments, num_par_steps, num_trg_steps, length, SEQ_MIDI_PORT_OutNameGet(SEQ_MIDI_PORT_OutIxGet(midi_port)), SEQ_MIDI_PORT_OutCheckAvailable(midi_port) ? ' ' : '*', midi_chn); if( seq_core_trk_muted & (1 << track) ) sprintf((char *)(str_buffer + strlen(str_buffer)), " yes |\n"); else if( seq_core_trk[track].layer_muted ) sprintf((char *)(str_buffer + strlen(str_buffer)), " layer |\n"); else sprintf((char *)(str_buffer + strlen(str_buffer)), " no |\n"); out(str_buffer); } out("+-------+-------+-------------+-----------+--------+-------+------+-------+\n"); out("done.\n"); MUTEX_MIDIOUT_GIVE; 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 }
///////////////////////////////////////////////////////////////////////////// // Search for item in quick selection list ///////////////////////////////////////////////////////////////////////////// static s32 QUICKSEL_SearchItem(u8 track) { u8 search_pattern_length = SEQ_CC_Get(track, SEQ_CC_LENGTH); u8 search_pattern_loop = SEQ_CC_Get(track, SEQ_CC_LOOP); int i; if( quicksel_mode == QUICKSEL_MODE_LENGTH ) { for(i=0; i<8; ++i) if( ui_quicksel_length[i] == search_pattern_length ) return i; } else { for(i=0; i<8; ++i) if( ui_quicksel_loop_length[i] == search_pattern_length && ui_quicksel_loop_loop[i] == search_pattern_loop ) return i; } return -1; // item not found }
///////////////////////////////////////////////////////////////////////////// // 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 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 }
///////////////////////////////////////////////////////////////////////////// // Returns the CC value for MIDI (different mapping, especially used by Loopback Feature) // see also doc/mbseqv4_cc_implementation.txt // Returns < 0 if CC value not mapped ///////////////////////////////////////////////////////////////////////////// s32 SEQ_CC_MIDI_Get(u8 track, u8 cc, u8 *mapped_cc) { if( cc >= 0x30 && cc <= 0x7f ) { *mapped_cc = cc - 0x20; u8 value = SEQ_CC_Get(track, cc); switch( cc ) { case SEQ_CC_LFO_AMPLITUDE: value /= 2; // 8bit -> 7bit break; case SEQ_CC_MIDI_PORT: case SEQ_CC_FX_MIDI_PORT: if( value >= 0xf0 ) value = 0x70 | (value & 0x0f); // map to Bus else if( value >= 0x80 ) value = 0x60 | (value & 0x0f); // map to AOUT break; } return value; } return -1; // CC not mapped }
///////////////////////////////////////////////////////////////////////////// // 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 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(); 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 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; }
///////////////////////////////////////////////////////////////////////////// // 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; }
///////////////////////////////////////////////////////////////////////////// // 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: ui_selected_item = ITEM_WAVEFORM; break; case SEQ_UI_ENCODER_GP3: ui_selected_item = ITEM_AMPLITUDE; break; case SEQ_UI_ENCODER_GP4: ui_selected_item = ITEM_PHASE; break; case SEQ_UI_ENCODER_GP5: ui_selected_item = ITEM_STEPS; break; case SEQ_UI_ENCODER_GP6: ui_selected_item = ITEM_STEPS_RST; break; case SEQ_UI_ENCODER_GP7: ui_selected_item = ITEM_ENABLE_ONE_SHOT; break; case SEQ_UI_ENCODER_GP8: return -1; // not mapped case SEQ_UI_ENCODER_GP9: ui_selected_item = ITEM_ENABLE_NOTE; break; case SEQ_UI_ENCODER_GP10: ui_selected_item = ITEM_ENABLE_VELOCITY; break; case SEQ_UI_ENCODER_GP11: ui_selected_item = ITEM_ENABLE_LENGTH; break; case SEQ_UI_ENCODER_GP12: ui_selected_item = ITEM_ENABLE_CC; break; case SEQ_UI_ENCODER_GP13: return -1; // not mapped case SEQ_UI_ENCODER_GP14: // CC number selection now has to be confirmed with GP button if( ui_selected_item != ITEM_CC ) { edit_cc_number = SEQ_CC_Get(visible_track, SEQ_CC_LFO_CC); ui_selected_item = ITEM_CC; SEQ_UI_Msg(SEQ_UI_MSG_USER, 2000, "Please confirm CC", "with GP button!"); } else if( incrementer == 0 ) { if( edit_cc_number != SEQ_CC_Get(visible_track, SEQ_CC_LFO_CC) ) { SEQ_CC_Set(visible_track, SEQ_CC_LFO_CC, edit_cc_number); SEQ_UI_Msg(SEQ_UI_MSG_USER, 2000, "CC number", "has been changed."); } // send event mios32_midi_package_t p; if( SEQ_LFO_FastCC_Event(visible_track, 0, &p, 1) >= 1 ) { MUTEX_MIDIOUT_TAKE; MIOS32_MIDI_SendPackage(SEQ_CC_Get(visible_track, SEQ_CC_MIDI_PORT), p); MUTEX_MIDIOUT_GIVE; } } break; case SEQ_UI_ENCODER_GP15: ui_selected_item = ITEM_CC_OFFSET; break; case SEQ_UI_ENCODER_GP16: ui_selected_item = ITEM_CC_PPQN; break; } // for GP encoders and Datawheel switch( ui_selected_item ) { case ITEM_GXTY: return SEQ_UI_GxTyInc(incrementer); case ITEM_WAVEFORM: return SEQ_UI_CC_Inc(SEQ_CC_LFO_WAVEFORM, 0, 22, incrementer); case ITEM_AMPLITUDE: return SEQ_UI_CC_Inc(SEQ_CC_LFO_AMPLITUDE, 0, 255, incrementer); case ITEM_PHASE: return SEQ_UI_CC_Inc(SEQ_CC_LFO_PHASE, 0, 99, incrementer); case ITEM_STEPS: return SEQ_UI_CC_Inc(SEQ_CC_LFO_STEPS, 0, 255, incrementer); case ITEM_STEPS_RST: return SEQ_UI_CC_Inc(SEQ_CC_LFO_STEPS_RST, 0, 255, incrementer); case ITEM_ENABLE_ONE_SHOT: case ITEM_ENABLE_NOTE: case ITEM_ENABLE_VELOCITY: case ITEM_ENABLE_LENGTH: case ITEM_ENABLE_CC: { u8 flag = ui_selected_item - ITEM_ENABLE_ONE_SHOT; u8 mask = 1 << flag; u8 value = SEQ_CC_Get(visible_track, SEQ_CC_LFO_ENABLE_FLAGS); if( incrementer == 0 ) // toggle SEQ_UI_CC_SetFlags(SEQ_CC_LFO_ENABLE_FLAGS, mask, value ^ mask); else if( incrementer > 0 ) SEQ_UI_CC_SetFlags(SEQ_CC_LFO_ENABLE_FLAGS, mask, mask); else SEQ_UI_CC_SetFlags(SEQ_CC_LFO_ENABLE_FLAGS, mask, 0); } break; case ITEM_CC: { // CC number selection now has to be confirmed with GP button s32 status = SEQ_UI_Var8_Inc(&edit_cc_number, 0, 127, incrementer); mios32_midi_port_t port = SEQ_CC_Get(visible_track, SEQ_CC_MIDI_PORT); u8 loopback = port == 0xf0; if( !edit_cc_number ) { SEQ_UI_Msg(SEQ_UI_MSG_USER_R, 1000, "LFO CC", "disabled"); } else { SEQ_UI_Msg(SEQ_UI_MSG_USER_R, 1000, loopback ? "Loopback CC" : "Controller:", (char *)SEQ_CC_LABELS_Get(port, edit_cc_number)); } return status; } break; case ITEM_CC_OFFSET: return SEQ_UI_CC_Inc(SEQ_CC_LFO_CC_OFFSET, 0, 127, incrementer); case ITEM_CC_PPQN: return SEQ_UI_CC_Inc(SEQ_CC_LFO_CC_PPQN, 0, 8, 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) { 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 ) {
} } 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 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 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) { 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 }
///////////////////////////////////////////////////////////////////////////// // 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) { 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 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 }
///////////////////////////////////////////////////////////////////////////// // 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. Wave Amp. Phs. Steps Rst OneShot Note Vel. Len. CC ExtraCC# Offs. PPQN // GxTy Sine 64 0% 16 16 on off off off off 001 64 384 u8 visible_track = SEQ_UI_VisibleTrackGet(); /////////////////////////////////////////////////////////////////////////// SEQ_LCD_CursorSet(0, 0); SEQ_LCD_PrintString("Trk. Wave Amp. Phs. Steps Rst OneShot Note Vel. Len. CC ExtraCC# Offs. PPQN"); /////////////////////////////////////////////////////////////////////////// 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(1); /////////////////////////////////////////////////////////////////////////// if( ui_selected_item == ITEM_WAVEFORM && ui_cursor_flash ) { SEQ_LCD_PrintSpaces(5); } else { u8 value = SEQ_CC_Get(visible_track, SEQ_CC_LFO_WAVEFORM); if( value <= 3 ) { const char waveform_str[4][6] = { " off ", "Sine ", "Tri. ", "Saw. " }; SEQ_LCD_PrintString((char *)waveform_str[value]); } else { SEQ_LCD_PrintFormattedString(" R%02d ", (value-4+1)*5); } } /////////////////////////////////////////////////////////////////////////// if( ui_selected_item == ITEM_AMPLITUDE && ui_cursor_flash ) { SEQ_LCD_PrintSpaces(5); } else { int value = (int)SEQ_CC_Get(visible_track, SEQ_CC_LFO_AMPLITUDE) - 128; SEQ_LCD_PrintFormattedString("%4d ", value); } /////////////////////////////////////////////////////////////////////////// if( ui_selected_item == ITEM_PHASE && ui_cursor_flash ) { SEQ_LCD_PrintSpaces(6); } else { SEQ_LCD_PrintFormattedString("%3d%% ", SEQ_CC_Get(visible_track, SEQ_CC_LFO_PHASE)); } /////////////////////////////////////////////////////////////////////////// if( ui_selected_item == ITEM_STEPS && ui_cursor_flash ) { SEQ_LCD_PrintSpaces(5); } else { SEQ_LCD_PrintFormattedString("%3d ", (int)SEQ_CC_Get(visible_track, SEQ_CC_LFO_STEPS)+1); } /////////////////////////////////////////////////////////////////////////// if( ui_selected_item == ITEM_STEPS_RST && ui_cursor_flash ) { SEQ_LCD_PrintSpaces(4); } else { SEQ_LCD_PrintFormattedString("%3d ", (int)SEQ_CC_Get(visible_track, SEQ_CC_LFO_STEPS_RST)+1); } /////////////////////////////////////////////////////////////////////////// if( ui_selected_item == ITEM_ENABLE_ONE_SHOT && ui_cursor_flash ) { SEQ_LCD_PrintSpaces(5); } else { SEQ_LCD_PrintString((SEQ_CC_Get(visible_track, SEQ_CC_LFO_ENABLE_FLAGS) & (1 << 0)) ? " on " : " off "); } SEQ_LCD_PrintSpaces(5); /////////////////////////////////////////////////////////////////////////// if( ui_selected_item == ITEM_ENABLE_NOTE && ui_cursor_flash ) { SEQ_LCD_PrintSpaces(5); } else { SEQ_LCD_PrintString((SEQ_CC_Get(visible_track, SEQ_CC_LFO_ENABLE_FLAGS) & (1 << 1)) ? " on " : " off "); } /////////////////////////////////////////////////////////////////////////// if( ui_selected_item == ITEM_ENABLE_VELOCITY && ui_cursor_flash ) { SEQ_LCD_PrintSpaces(5); } else { SEQ_LCD_PrintString((SEQ_CC_Get(visible_track, SEQ_CC_LFO_ENABLE_FLAGS) & (1 << 2)) ? " on " : " off "); } /////////////////////////////////////////////////////////////////////////// if( ui_selected_item == ITEM_ENABLE_LENGTH && ui_cursor_flash ) { SEQ_LCD_PrintSpaces(5); } else { SEQ_LCD_PrintString((SEQ_CC_Get(visible_track, SEQ_CC_LFO_ENABLE_FLAGS) & (1 << 3)) ? " on " : " off "); } /////////////////////////////////////////////////////////////////////////// if( ui_selected_item == ITEM_ENABLE_CC && ui_cursor_flash ) { SEQ_LCD_PrintSpaces(5); } else { SEQ_LCD_PrintString((SEQ_CC_Get(visible_track, SEQ_CC_LFO_ENABLE_FLAGS) & (1 << 4)) ? " on " : " off "); } /////////////////////////////////////////////////////////////////////////// SEQ_LCD_PrintSpaces(5); if( ui_selected_item == ITEM_CC && ui_cursor_flash ) { SEQ_LCD_PrintSpaces(5); } else { u8 current_value = SEQ_CC_Get(visible_track, SEQ_CC_LFO_CC); u8 edit_value = (ui_selected_item == ITEM_CC) ? edit_cc_number : current_value; if( edit_value ) SEQ_LCD_PrintFormattedString(" %03d", edit_value); else SEQ_LCD_PrintString(" ---"); SEQ_LCD_PrintChar((current_value != edit_value) ? '!' : ' '); } /////////////////////////////////////////////////////////////////////////// if( ui_selected_item == ITEM_CC_OFFSET && ui_cursor_flash ) { SEQ_LCD_PrintSpaces(5); } else { SEQ_LCD_PrintFormattedString(" %3d ", SEQ_CC_Get(visible_track, SEQ_CC_LFO_CC_OFFSET)); } /////////////////////////////////////////////////////////////////////////// if( ui_selected_item == ITEM_CC_PPQN && ui_cursor_flash ) { SEQ_LCD_PrintSpaces(5); } else { u8 value = SEQ_CC_Get(visible_track, SEQ_CC_LFO_CC_PPQN); int ppqn = 1; if( value ) ppqn = 3 << (value-1); SEQ_LCD_PrintFormattedString(" %3d ", ppqn); } /////////////////////////////////////////////////////////////////////////// return 0; // no error } ///////////////////////////////////////////////////////////////////////////// // Initialisation ///////////////////////////////////////////////////////////////////////////// s32 SEQ_UI_FX_LFO_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 }