From be37f274be067e92f9240112b7a047b8ef9e09b0 Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Mon, 8 Jan 2024 15:32:13 +0100 Subject: Add input retriggering with configurable rate and offset --- src/gba/gba.h | 111 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.c | 3 +- src/sequencer.c | 80 ++++++++++++++++++++-------------------- src/settings.c | 8 ++-- 4 files changed, 157 insertions(+), 45 deletions(-) (limited to 'src') diff --git a/src/gba/gba.h b/src/gba/gba.h index 8ba3de5..b5868f0 100644 --- a/src/gba/gba.h +++ b/src/gba/gba.h @@ -327,6 +327,117 @@ key_hold(u32 key) { return key_curr & key_prev & key; } +// Stores number of frames since a keay was pressed. +typedef struct Controller { + int key_up; + int key_down; + int key_left; + int key_right; + int key_select; + int key_start; + int key_b; + int key_a; + int key_l; + int key_r; +} Controller; + +static Controller ctrl = {0}; + +#define RETRIG_OFFSET 16 +#define RETRIG_FRAMES 3 + +static inline +bool +_key_retrig(int key, int offset, int frames) { + if (key_tap(key)) { + return true; + } + switch (key) { + case KEY_L: { + if (key_hold(key)) { + if (ctrl.key_l < offset) { return false; } + if (ctrl.key_l % frames == 0) { return true; } + } + } break; + case KEY_R: { + if (key_hold(key)) { + if (ctrl.key_r < offset) { return false; } + if (ctrl.key_r % frames == 0) { return true; } + } + } break; + case KEY_A: { + if (key_hold(key)) { + if (ctrl.key_a < offset) { return false; } + if (ctrl.key_a % frames == 0) { return true; } + } + } break; + case KEY_B: { + if (key_hold(key)) { + if (ctrl.key_b < offset) { return false; } + if (ctrl.key_b % frames == 0) { return true; } + } + } break; + case KEY_SELECT: { + if (key_hold(key)) { + if (ctrl.key_select < offset) { return false; } + if (ctrl.key_select % frames == 0) { return true; } + } + } break; + case KEY_START: { + if (key_hold(key)) { + if (ctrl.key_start < offset) { return false; } + if (ctrl.key_start % frames == 0) { return true; } + } + } break; + case KEY_UP: { + if (key_hold(key)) { + if (ctrl.key_up < offset) { return false; } + if (ctrl.key_up % frames == 0) { return true; } + } + } break; + case KEY_DOWN: { + if (key_hold(key)) { + if (ctrl.key_down < offset) { return false; } + if (ctrl.key_down % frames == 0) { return true; } + } + } break; + case KEY_LEFT: { + if (key_hold(key)) { + if (ctrl.key_left < offset) { return false; } + if (ctrl.key_left % frames == 0) { return true; } + } + } break; + case KEY_RIGHT: { + if (key_hold(key)) { + if (ctrl.key_right < offset) { return false; } + if (ctrl.key_right % frames == 0) { return true; } + } + } break; + } + return false; +} + +static inline +bool +key_retrig(int key) { + return _key_retrig(key, RETRIG_OFFSET, RETRIG_FRAMES); +} + +static inline +void +update_controller(void) { + if (key_pressed(KEY_UP)) { ctrl.key_up++; } else if (key_released(KEY_UP)) { ctrl.key_up = 0; } + if (key_pressed(KEY_DOWN)) { ctrl.key_down++; } else if (key_released(KEY_DOWN)) { ctrl.key_down = 0; } + if (key_pressed(KEY_LEFT)) { ctrl.key_left++; } else if (key_released(KEY_LEFT)) { ctrl.key_left = 0; } + if (key_pressed(KEY_RIGHT)) { ctrl.key_right++; } else if (key_released(KEY_RIGHT)) { ctrl.key_right = 0; } + if (key_pressed(KEY_L)) { ctrl.key_l++; } else if (key_released(KEY_L)) { ctrl.key_l = 0; } + if (key_pressed(KEY_R)) { ctrl.key_r++; } else if (key_released(KEY_R)) { ctrl.key_r = 0; } + if (key_pressed(KEY_A)) { ctrl.key_a++; } else if (key_released(KEY_A)) { ctrl.key_a = 0; } + if (key_pressed(KEY_B)) { ctrl.key_b++; } else if (key_released(KEY_B)) { ctrl.key_b = 0; } + if (key_pressed(KEY_SELECT)) { ctrl.key_select++; } else if (key_released(KEY_SELECT)) { ctrl.key_select = 0; } + if (key_pressed(KEY_START)) { ctrl.key_start++; } else if (key_released(KEY_START)) { ctrl.key_start = 0; } +} + // // Direct Memory Access (DMA) // diff --git a/src/main.c b/src/main.c index 1562565..6b7619f 100644 --- a/src/main.c +++ b/src/main.c @@ -24,7 +24,7 @@ WITH REGARD TO THIS SOFTWARE. // + Fix scale being active for noise channel (makes no sense) // + Save scale on metadata // + Allow using B + dpad to nudge trigs. This will potentially mean switching -// - Hold L/R retriggers at short intervals? +// + Hold L/R retriggers at short intervals? // to key release to enable trigs. // - Fix any bugs we currently have // - Add an envelope to ch3, would need to work with a timer in order to make @@ -192,6 +192,7 @@ handle_input(void) { void update(void) { + update_controller(); if (next_scene != scene) { scene = next_scene; clear_screen = true; diff --git a/src/sequencer.c b/src/sequencer.c index a032481..3433da1 100644 --- a/src/sequencer.c +++ b/src/sequencer.c @@ -442,7 +442,7 @@ handle_channel_selection(void) { } } redraw_params = true; - } else if (key_tap(KEY_L)) { + } else if (key_retrig(KEY_L)) { s32 inc = -1; if (key_hold(KEY_SELECT)) { inc = -12; @@ -466,7 +466,7 @@ handle_channel_selection(void) { } } redraw_trigs = true; - } else if (key_tap(KEY_R)) { + } else if (key_retrig(KEY_R)) { s32 inc = 1; if (key_hold(KEY_SELECT)) { inc = 12; @@ -491,16 +491,16 @@ handle_channel_selection(void) { } redraw_trigs = true; } - if (key_tap(KEY_RIGHT)) { + if (key_retrig(KEY_RIGHT)) { trig_selection_loc = 0; param_selection_loc = 0; input_handler = handle_trigger_selection; redraw_params = true; - } else if (key_tap(KEY_LEFT)) { + } else if (key_retrig(KEY_LEFT)) { input_handler = handle_pattern_selection; param_selection_loc = 0; redraw_params = true; - } else if (key_tap(KEY_UP)) { + } else if (key_retrig(KEY_UP)) { if (channel_selection_loc == 0) { channel_selection_loc = SEQ_N_CHANNELS - 1; } else { @@ -509,7 +509,7 @@ handle_channel_selection(void) { param_selection_loc = 0; redraw_trigs = true; redraw_params = true; - } else if (key_tap(KEY_DOWN)) { + } else if (key_retrig(KEY_DOWN)) { if (channel_selection_loc == SEQ_N_CHANNELS - 1) { channel_selection_loc = 0; } else { @@ -601,7 +601,7 @@ toggle_playing(void) { void handle_right_col_selection(void) { - if (key_tap(KEY_LEFT)) { + if (key_retrig(KEY_LEFT)) { switch (right_col_selection_loc) { case R_COL_STOP: case R_COL_BANK_B: @@ -624,7 +624,7 @@ handle_right_col_selection(void) { } else { trig_selection_loc = 7; } - } else if (key_tap(KEY_RIGHT)) { + } else if (key_retrig(KEY_RIGHT)) { switch (right_col_selection_loc) { case R_COL_PLAY: case R_COL_BANK_A: @@ -638,7 +638,7 @@ handle_right_col_selection(void) { case R_COL_SETTINGS: case R_COL_STOP: { input_handler = handle_pattern_selection; } break; } - } else if (key_tap(KEY_UP)) { + } else if (key_retrig(KEY_UP)) { switch (right_col_selection_loc) { case R_COL_BANK_A: { right_col_selection_loc = R_COL_PLAY; } break; case R_COL_BANK_B: { right_col_selection_loc = R_COL_STOP; } break; @@ -650,7 +650,7 @@ handle_right_col_selection(void) { case R_COL_SCALE: { right_col_selection_loc -= 2; } break; default: { right_col_selection_loc--; } break; } - } else if (key_tap(KEY_DOWN)) { + } else if (key_retrig(KEY_DOWN)) { switch (right_col_selection_loc) { case R_COL_BANK_A: case R_COL_BANK_B: @@ -661,7 +661,7 @@ handle_right_col_selection(void) { case R_COL_STOP: { right_col_selection_loc = R_COL_BANK_B; } break; default: { right_col_selection_loc++; } break; } - } else if (key_tap(KEY_L)) { + } else if (key_retrig(KEY_L)) { switch (right_col_selection_loc) { case R_COL_BPM: { s32 bpm_inc = -1; @@ -701,7 +701,7 @@ handle_right_col_selection(void) { } } break; } - } else if (key_tap(KEY_R)) { + } else if (key_retrig(KEY_R)) { switch (right_col_selection_loc) { case R_COL_BPM: { s32 bpm_inc = 1; @@ -759,7 +759,7 @@ handle_pattern_chain(void) { static int previous_loc = 0; if (key_tap(KEY_A)) { input_handler = handle_pattern_selection; - } else if (key_tap(KEY_LEFT)) { + } else if (key_retrig(KEY_LEFT)) { if (param_selection_loc == 8) { param_selection_loc = 15; } else if (param_selection_loc == 16) { @@ -769,7 +769,7 @@ handle_pattern_chain(void) { } else if (param_selection_loc == 0) { param_selection_loc = 7; } - } else if (key_tap(KEY_RIGHT)) { + } else if (key_retrig(KEY_RIGHT)) { if (param_selection_loc < 15 && param_selection_loc != 7) { param_selection_loc++; } else if (param_selection_loc < 18 && param_selection_loc >= 16) { @@ -885,14 +885,14 @@ handle_pattern_chain(void) { } } break; } - } else if (key_tap(KEY_L)) { + } else if (key_retrig(KEY_L)) { if (chain.active[param_selection_loc] && chain.chain[param_selection_loc] > 0 && param_selection_loc <= 15 && (!play_status || param_selection_loc != chain.current)) { chain.chain[param_selection_loc]--; } - } else if (key_tap(KEY_R)) { + } else if (key_retrig(KEY_R)) { if (chain.active[param_selection_loc] && chain.chain[param_selection_loc] < 7 && param_selection_loc <= 15 @@ -934,11 +934,11 @@ handle_pattern_selection(void) { if (key_tap(KEY_A)) { input_handler = handle_pattern_chain; } - if (key_tap(KEY_RIGHT)) { + if (key_retrig(KEY_RIGHT)) { param_selection_loc = 0; input_handler = handle_channel_selection; redraw_params = true; - } else if (key_tap(KEY_UP)) { + } else if (key_retrig(KEY_UP)) { if (pattern_selection_loc > 0) { pattern_selection_loc = pattern_selection_loc - 1; } else { @@ -947,7 +947,7 @@ handle_pattern_selection(void) { redraw_channels = true; redraw_trigs = true; redraw_bpm = true; - } else if (key_tap(KEY_DOWN)) { + } else if (key_retrig(KEY_DOWN)) { if (pattern_selection_loc < 7) { pattern_selection_loc = pattern_selection_loc + 1; } else { @@ -957,7 +957,7 @@ handle_pattern_selection(void) { redraw_trigs = true; redraw_bpm = true; } - if (key_tap(KEY_LEFT)) { + if (key_retrig(KEY_LEFT)) { redraw_params = true; input_handler = handle_right_col_selection; param_selection_loc = 0; @@ -1032,8 +1032,8 @@ set_param_selection_sq1(ChannelSquareParams *params, InputHandler return_handler } // Cursor movement. - if (key_tap(KEY_LEFT) || key_tap(KEY_RIGHT)) { - if (key_tap(KEY_RIGHT)) { + if (key_retrig(KEY_LEFT) || key_retrig(KEY_RIGHT)) { + if (key_retrig(KEY_RIGHT)) { if (param_selection_loc == 4) { param_selection_loc = 0; } else if (param_selection_loc == 9) { @@ -1073,9 +1073,9 @@ set_param_selection_sq1(ChannelSquareParams *params, InputHandler return_handler } // Adjust parameter. - if (key_tap(KEY_R) || key_tap(KEY_L)) { + if (key_retrig(KEY_R) || key_retrig(KEY_L)) { int inc; - if (key_tap(KEY_L)) { + if (key_retrig(KEY_L)) { inc = -1; } else { inc = 1; @@ -1116,8 +1116,8 @@ set_param_selection_sq2(ChannelSquareParams *params, InputHandler return_handler } // Cursor movement. - if (key_tap(KEY_LEFT) || key_tap(KEY_RIGHT)) { - if (key_tap(KEY_RIGHT)) { + if (key_retrig(KEY_LEFT) || key_retrig(KEY_RIGHT)) { + if (key_retrig(KEY_RIGHT)) { if (param_selection_loc == 4) { param_selection_loc = 0; } else if (param_selection_loc == 7) { @@ -1149,9 +1149,9 @@ set_param_selection_sq2(ChannelSquareParams *params, InputHandler return_handler } // Adjust parameter. - if (key_tap(KEY_R) || key_tap(KEY_L)) { + if (key_retrig(KEY_R) || key_retrig(KEY_L)) { int inc; - if (key_tap(KEY_L)) { + if (key_retrig(KEY_L)) { inc = -1; } else { inc = 1; @@ -1189,8 +1189,8 @@ set_param_selection_wave(ChannelWaveParams *params, InputHandler return_handler) } // Cursor movement. - if (key_tap(KEY_LEFT) || key_tap(KEY_RIGHT)) { - if (key_tap(KEY_RIGHT)) { + if (key_retrig(KEY_LEFT) || key_retrig(KEY_RIGHT)) { + if (key_retrig(KEY_RIGHT)) { if (param_selection_loc == 4) { param_selection_loc = 0; } else if (param_selection_loc == 6) { @@ -1230,9 +1230,9 @@ set_param_selection_wave(ChannelWaveParams *params, InputHandler return_handler) } // Adjust parameter. - if (key_tap(KEY_R) || key_tap(KEY_L)) { + if (key_retrig(KEY_R) || key_retrig(KEY_L)) { int inc; - if (key_tap(KEY_L)) { + if (key_retrig(KEY_L)) { inc = -1; } else { inc = 1; @@ -1264,8 +1264,8 @@ set_param_selection_noise(ChannelNoiseParams *params, InputHandler return_handle } // Cursor movement. - if (key_tap(KEY_LEFT) || key_tap(KEY_RIGHT)) { - if (key_tap(KEY_RIGHT)) { + if (key_retrig(KEY_LEFT) || key_retrig(KEY_RIGHT)) { + if (key_retrig(KEY_RIGHT)) { if (param_selection_loc == 4) { param_selection_loc = 0; } else if (param_selection_loc == 7) { @@ -1297,9 +1297,9 @@ set_param_selection_noise(ChannelNoiseParams *params, InputHandler return_handle } // Adjust parameter. - if (key_tap(KEY_R) || key_tap(KEY_L)) { + if (key_retrig(KEY_R) || key_retrig(KEY_L)) { int inc; - if (key_tap(KEY_L)) { + if (key_retrig(KEY_L)) { inc = -1; } else { inc = 1; @@ -1547,7 +1547,7 @@ handle_trigger_selection(void) { } } redraw_trigs = true; - } else if (key_tap(KEY_L)) { + } else if (key_retrig(KEY_L)) { s32 inc = -1; if (key_hold(KEY_SELECT)) { inc = -12; @@ -1564,7 +1564,7 @@ handle_trigger_selection(void) { } } redraw_trigs = true; - } else if (key_tap(KEY_R)) { + } else if (key_retrig(KEY_R)) { s32 inc = 1; if (key_hold(KEY_SELECT)) { inc = 12; @@ -1584,7 +1584,7 @@ handle_trigger_selection(void) { } // Move trigger cursor. - if (key_tap(KEY_LEFT)) { + if (key_retrig(KEY_LEFT)) { if (key_hold(KEY_B)) { if (trig_selection_loc != 0 && trig_selection_loc != 8) { int next_selection_loc = MAX(trig_selection_loc - 1, 0); @@ -1602,7 +1602,7 @@ handle_trigger_selection(void) { } } redraw_params = true; - } else if (key_tap(KEY_RIGHT)) { + } else if (key_retrig(KEY_RIGHT)) { if (key_hold(KEY_B)) { if (trig_selection_loc != 7 && trig_selection_loc != 15) { int next_selection_loc = MIN(trig_selection_loc + 1, 15); diff --git a/src/settings.c b/src/settings.c index 7e86be7..9fc2f3d 100644 --- a/src/settings.c +++ b/src/settings.c @@ -70,7 +70,7 @@ set_audio_settings(void) { void handle_settings_input(void) { - if (key_tap(KEY_DOWN)) { + if (key_retrig(KEY_DOWN)) { if (settings_cursor_loc == (SETTINGS_NUM - 1)) { settings_cursor_loc = 0; } else { @@ -78,7 +78,7 @@ handle_settings_input(void) { } clear_screen = true; } - if (key_tap(KEY_UP)) { + if (key_retrig(KEY_UP)) { if (settings_cursor_loc == 0) { settings_cursor_loc = SETTINGS_NUM - 1; } else { @@ -86,7 +86,7 @@ handle_settings_input(void) { } clear_screen = true; } - if (key_tap(KEY_R)) { + if (key_retrig(KEY_R)) { switch (settings_cursor_loc) { case SETTINGS_SYNC: { if ((settings.sync + 1) >= SYNC_NUM) { @@ -142,7 +142,7 @@ handle_settings_input(void) { save_metadata(); clear_screen = true; } - if (key_tap(KEY_L)) { + if (key_retrig(KEY_L)) { switch (settings_cursor_loc) { case SETTINGS_SYNC: { if (settings.sync == 0) { -- cgit v1.2.1