From fff06404696bb8790901cdefe016cd8d0fe856cb Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Fri, 25 Aug 2023 15:42:58 +0200 Subject: Add pattern chain buttons behaviour (toggle/clear/random) --- src/drawing.c | 75 ++++++++++++++++++++++++++++++++++++++++------- src/globals.c | 11 +++++-- src/main.c | 20 +++++++------ src/sequencer.c | 91 ++++++++++++++++++++++++++++++++++++++++++++------------- 4 files changed, 156 insertions(+), 41 deletions(-) (limited to 'src') diff --git a/src/drawing.c b/src/drawing.c index 50f3de3..e94d0ff 100644 --- a/src/drawing.c +++ b/src/drawing.c @@ -594,9 +594,19 @@ draw_piano(void) { draw_rect(x0, y0, x1, y1, COL_FG); for (size_t i = 0; i < 12 * 6; i++) { u8 clr = COL_FG; + s8 pos = i % 12; + switch (pos) { + case 0: + case 2: + case 4: + case 5: + case 7: + case 9: + case 11: break; + default: { clr = COL_BG; } break; + } if (input_handler == handle_right_col_selection && right_col_selection_loc == R_COL_SCALE) { - s8 pos = i % 12; if (pos == current_scale_root) { clr = COL_ACC_1; } else { @@ -1277,13 +1287,38 @@ clear_cursors(void) { void draw_pattern_chain_cursor(void) { - size_t offset_x = (PAT_TRIG_H + 7) * (param_selection_loc % 8); - size_t offset_y = param_selection_loc < 8 ? 0 : 0 + PAT_TRIG_OFFSET_Y; - size_t x0 = PAT_TRIG_START_X + offset_x; - size_t x1 = PAT_TRIG_START_X + offset_x + PAT_TRIG_W; - size_t y = PAT_TRIG_START_Y + offset_y + PAT_TRIG_H + 2; - draw_line(x0, y, x1, y, COL_ACC_0); - draw_line(x0, y + 1, x1, y + 1, COL_ACC_0); + switch (param_selection_loc) { + case CHAIN_BTN_ENABLE: { + size_t x0 = PAT_TRIG_START_X + 24; + size_t x1 = x0 + 30; + size_t y = PAT_TRIG_START_Y - 16 + 1 + 10; + draw_line(x0, y, x1, y, COL_ACC_0); + draw_line(x0, y + 1, x1, y + 1, COL_ACC_0); + } break; + case CHAIN_BTN_CLEAR: { + size_t x0 = PAT_TRIG_START_X + 24 + 42; + size_t x1 = x0 + 30; + size_t y = PAT_TRIG_START_Y - 16 + 1 + 10; + draw_line(x0, y, x1, y, COL_ACC_0); + draw_line(x0, y + 1, x1, y + 1, COL_ACC_0); + } break; + case CHAIN_BTN_RANDOM: { + size_t x0 = PAT_TRIG_START_X + 24 + 42 * 2; + size_t x1 = x0 + 30; + size_t y = PAT_TRIG_START_Y - 16 + 1 + 10; + draw_line(x0, y, x1, y, COL_ACC_0); + draw_line(x0, y + 1, x1, y + 1, COL_ACC_0); + } break; + default: { + size_t offset_x = (PAT_TRIG_H + 7) * (param_selection_loc % 8); + size_t offset_y = param_selection_loc < 8 ? 0 : 0 + PAT_TRIG_OFFSET_Y; + size_t x0 = PAT_TRIG_START_X + offset_x; + size_t x1 = PAT_TRIG_START_X + offset_x + PAT_TRIG_W; + size_t y = PAT_TRIG_START_Y + offset_y + PAT_TRIG_H + 2; + draw_line(x0, y, x1, y, COL_ACC_0); + draw_line(x0, y + 1, x1, y + 1, COL_ACC_0); + } break; + } } void @@ -1756,7 +1791,7 @@ draw_notif_bar() { return; } - if (chain.len != 0) { + if (chain.len != 0 && chain.enabled) { u8 x = x0 + 2; u8 y = y0 + 1; txt_drawf_small("CHAIN: ", x, y, color); @@ -1789,6 +1824,7 @@ draw_notif_bar() { void draw_pattern_chain() { clear_parameters(); + // Pattern chain triggers. for (size_t i = 0; i < 16; i++) { u8 color = COL_FG; size_t offset_x = PAT_TRIG_OFFSET_X * (i % 8); @@ -1797,12 +1833,15 @@ draw_pattern_chain() { size_t x1 = PAT_TRIG_START_X + offset_x + PAT_TRIG_W; size_t y0 = PAT_TRIG_START_Y + offset_y; size_t y1 = PAT_TRIG_START_Y + offset_y + PAT_TRIG_H; + if (!chain.enabled) { + color = COL_OFF; + } draw_rect(x0, y0, x1, y1, color); if (chain.active[i]) { txt_drawc('A' + chain.chain[i], x0 + 4, y0 + 3, color); } color = COL_OFF; - if (chain.current == i && chain.len != 0) { + if (chain.current == i && chain.len != 0 && chain.enabled) { color = COL_ACC_2; if (chain.active[i]) { txt_drawc('A' + chain.chain[i], x0 + 4, y0 + 3, color); @@ -1811,4 +1850,20 @@ draw_pattern_chain() { } draw_line(x0 + 5, y1 - 2, x1 - 5, y1 - 2, color); } + + // Pattern chain buttons. + size_t x0 = PAT_TRIG_START_X + 24; + size_t x1 = x0 + 30; + size_t y0 = PAT_TRIG_START_Y - 16 + 1; + size_t y1 = y0 + 8; + txt_drawf_small("toggle", x0 + 2, y0, COL_FG); + draw_rect(x0, y0, x1, y1, COL_FG); + x0 += 42; + x1 += 42; + txt_drawf_small("clear", x0 + 4, y0, COL_FG); + draw_rect(x0, y0, x1, y1, COL_FG); + x0 += 42; + x1 += 42; + txt_drawf_small("random", x0 + 2, y0, COL_FG); + draw_rect(x0, y0, x1, y1, COL_FG); } diff --git a/src/globals.c b/src/globals.c index 7361129..05c964a 100644 --- a/src/globals.c +++ b/src/globals.c @@ -57,7 +57,7 @@ bool clear_screen = true; #define NOTIF_START_Y 12 #define PARAMS_W 166 -#define PARAMS_H 52 +#define PARAMS_H 56 #define PARAMS_START_X 29 #define PARAMS_START_Y 20 #define PARAMS_BOX_W 30 @@ -99,7 +99,7 @@ bool clear_screen = true; #define PAT_TRIG_W 14 #define PAT_TRIG_H 14 #define PAT_TRIG_START_X 32 -#define PAT_TRIG_START_Y 30 +#define PAT_TRIG_START_Y 37 #define PAT_TRIG_OFFSET_X (PAT_TRIG_W + 7) #define PAT_TRIG_OFFSET_Y (PAT_TRIG_H + 8) @@ -167,8 +167,15 @@ typedef struct Chain { u8 len; u8 current; u8 playing; + u8 enabled; } Chain; +typedef enum ChainButtons { + CHAIN_BTN_ENABLE = 16, + CHAIN_BTN_CLEAR = 17, + CHAIN_BTN_RANDOM = 18, +} ChainButtons; + static Chain chain = {0}; typedef enum Prob { diff --git a/src/main.c b/src/main.c index 68049ee..6f34d27 100644 --- a/src/main.c +++ b/src/main.c @@ -37,6 +37,8 @@ WITH REGARD TO THIS SOFTWARE. // - Channel params should show if there are some already on all triggers and // modify only the selected parameter, not all of them. // - Should scale mode be toggleable? +// - Improve SRAM saving to make room for longer patterns and/or more banks. +// - Higher resolution clock to allow for microtiming and more accurate tempo. // // WIP (1.7) // + Improve "grey" cursor with dithering instead. @@ -55,18 +57,18 @@ WITH REGARD TO THIS SOFTWARE. // + Make sure bank switching is queued like patterns. // + If we are on sync in, BPM should display SYNC // + Visual feedback for scale/root note adjustment. -// - Shortcut to quickly exit/enter chain mode. +// + Settings page overhaul. +// + Add global mutes option. +// + Add global bpm option. +// + Add auto-save option. +// + Remove thin cursor option and make the fat one default, it's just better. +// + Restore black keys when not on scale mode +// + Enable pattern chain toggling. +// + Enable pattern chain clearing. +// + Enable pattern chain randomizing. // - Add CREDITS to the documentation for now, should probably be a menu item // later. -// - Settings page overhaul. -// - Remove thin cursor option and make the fat one default, it's just better. -// -// - Improve SRAM saving to make room for longer patterns and/or more banks. -// - Higher resolution clock to allow for microtiming and more accurate tempo. -// - Add settings for "performance mode" in which banks are not saved by -// default while changing patterns. // - Make sure sync works with the same cable for in/out. -// - Study more improvements for a "performance mode". #include "gba/gba.h" diff --git a/src/sequencer.c b/src/sequencer.c index 58714cb..266db94 100644 --- a/src/sequencer.c +++ b/src/sequencer.c @@ -138,7 +138,7 @@ play_step(void) { } else if (current_bank != next_bank && step_counter == 15) { select_bank(next_bank); update_bpm = true; - } else if (chain.len != 0 && step_counter == 15) { + } else if (chain.len != 0 && step_counter == 15 && chain.enabled) { redraw_pattern_buttons = true; update_bpm = true; if (!chain.playing) { @@ -762,6 +762,8 @@ handle_pattern_chain(void) { } else if (key_tap(KEY_LEFT)) { if (param_selection_loc == 8) { param_selection_loc = 15; + } else if (param_selection_loc == 16) { + param_selection_loc = 18; } else if (param_selection_loc > 0) { param_selection_loc--; } else if (param_selection_loc == 0) { @@ -770,48 +772,97 @@ handle_pattern_chain(void) { } else if (key_tap(KEY_RIGHT)) { if (param_selection_loc < 15 && param_selection_loc != 7) { param_selection_loc++; + } else if (param_selection_loc < 18 && param_selection_loc >= 16) { + param_selection_loc++; + } else if (param_selection_loc == 18) { + param_selection_loc = 16; } else if (param_selection_loc == 7) { param_selection_loc = 0; } else if (param_selection_loc == 15) { param_selection_loc = 8; } } else if (key_tap(KEY_UP)) { - if (param_selection_loc <= 7) { - param_selection_loc += 8; - } else { + if (param_selection_loc >= 1 && param_selection_loc <= 2) { + param_selection_loc = 16; + } else if (param_selection_loc >= 3 && param_selection_loc <= 4) { + param_selection_loc = 17; + } else if (param_selection_loc >= 5 && param_selection_loc <= 6) { + param_selection_loc = 18; + } else if (param_selection_loc >= 8 && param_selection_loc <= 15){ param_selection_loc -= 8; } } else if (key_tap(KEY_DOWN)) { if (param_selection_loc <= 7) { param_selection_loc += 8; - } else { - param_selection_loc -= 8; + } else if (param_selection_loc == 16){ + param_selection_loc = 1; + } else if (param_selection_loc == 17){ + param_selection_loc = 3; + } else if (param_selection_loc == 18){ + param_selection_loc = 5; } } else if (key_tap(KEY_B)) { - if (chain.active[param_selection_loc]) { - // Can't toggle current chain. - if (!play_status - || param_selection_loc != chain.current - || chain.len == 1) { - chain.active[param_selection_loc] = 0; - chain.len--; - } - } else { - if (chain.len == 0) { - chain.current = param_selection_loc; - } - chain.active[param_selection_loc] = 1; - chain.len++; + switch (param_selection_loc) { + case CHAIN_BTN_ENABLE: { + chain.enabled ^= 1; + chain.current = 15; + chain.current = find_next_pattern(); + chain.playing = false; + } break; + case CHAIN_BTN_CLEAR: { + chain.len = 0; + chain.playing = false; + for (size_t i = 0; i < MAX_CHAIN; i++) { + chain.active[i] = false; + chain.chain[i] = 0; + } + chain.current = 15; + chain.current = find_next_pattern(); + } break; + case CHAIN_BTN_RANDOM: { + u8 cur = chain.current % 16; + for (size_t i = 0; i < MAX_CHAIN; i++) { + if (i == cur && chain.playing) { + continue; + } + if (rng16() < 32765) { + chain.active[i] = true; + } else { + chain.active[i] = false; + } + // NOTE: Should we also randomize the patterns or isn't it + // necessary? + } + } break; + default: { + if (chain.active[param_selection_loc]) { + // Can't toggle current chain. + if (!play_status + || param_selection_loc != chain.current + || chain.len == 1) { + chain.active[param_selection_loc] = 0; + chain.len--; + } + } else { + if (chain.len == 0) { + chain.current = param_selection_loc; + } + chain.active[param_selection_loc] = 1; + chain.len++; + } + } break; } } else if (key_tap(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)) { if (chain.active[param_selection_loc] && chain.chain[param_selection_loc] < 7 + && param_selection_loc <= 15 && (!play_status || param_selection_loc != chain.current)) { chain.chain[param_selection_loc]++; } -- cgit v1.2.1