From e5d61a87ec41443a2e32cd8be1ecc62b8c590251 Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Tue, 22 Aug 2023 12:28:10 +0200 Subject: Add pattern clearing with SEL+L+R on pattern view --- src/drawing.c | 40 ++++++++++++++++++++++------- src/main.c | 10 ++++---- src/patterns.c | 17 ++++++------ src/sequencer.c | 80 +++++++++++++++++++++++++++++++++++++++++++++------------ 4 files changed, 109 insertions(+), 38 deletions(-) (limited to 'src') diff --git a/src/drawing.c b/src/drawing.c index d24307b..253a961 100644 --- a/src/drawing.c +++ b/src/drawing.c @@ -3,7 +3,7 @@ // void -draw_param_stub(size_t idx, u8 color) { +draw_param_stub(size_t idx, u8 clr) { if (idx >= 10) { return; } @@ -15,12 +15,12 @@ draw_param_stub(size_t idx, u8 color) { } u8 y1 = y0 + PARAMS_BOX_H; for (size_t i = 0; i < PARAMS_BOX_W; i += 2) { - draw_pixel(x0 + i + 1, y0, color); - draw_pixel(x0 + i + 1, y1, color); + draw_pixel(x0 + i + 1, y0, clr); + draw_pixel(x0 + i + 1, y1, clr); } for (size_t i = 0; i < PARAMS_BOX_H; i += 2) { - draw_pixel(x0, y0 + i + 1, color); - draw_pixel(x1, y0 + i + 1, color); + draw_pixel(x0, y0 + i + 1, clr); + draw_pixel(x1, y0 + i + 1, clr); } } @@ -79,6 +79,9 @@ draw_channels(void) { case 2: { active = patterns[pattern_selection_loc].ch3.active; } break; case 3: { active = patterns[pattern_selection_loc].ch4.active; } break; } + if (patterns[pattern_selection_loc].empty) { + active = true; + } u8 clr = active ? colors[i] : COL_OFF; size_t y = CHAN_START_Y + i * CHAN_OFFSET_Y; draw_channel_sprite(CHAN_START_X, y, clr, i); @@ -273,14 +276,26 @@ draw_bank_buttons() { } } +void +draw_dotted_rect(size_t x0, size_t y0, size_t x1, size_t y1, u8 clr) { + size_t w = x1 - x0; + size_t h = y1 - y0; + for (size_t i = 0; i <= w; i += 2) { + draw_pixel(x0 + i, y0, clr); + draw_pixel(x0 + i, y1, clr); + } + for (size_t i = 0; i <= h; i += 2) { + draw_pixel(x0, y0 + i, clr); + draw_pixel(x1, y0 + i, clr); + } +} + void draw_pattern_buttons() { // Clear patterns. size_t x = PAT_START_X; size_t y = PAT_START_Y; - draw_filled_rect(x, y, x + PAT_W, y + PAT_H * 8, COL_BG); - txt_drawf_small("PAT", x, y - 10, COL_FG); char pat_names[] = { 'A', 'B', 'C', 'D', @@ -294,7 +309,12 @@ draw_pattern_buttons() { if (i == next_pattern && current_pattern != next_pattern) { color = COL_ACC_0; } - draw_rect(x, y, x + PAT_W, y + PAT_H, color); + draw_filled_rect(x, y, x + PAT_W, y + PAT_H, COL_BG); + if (patterns[i].empty) { + draw_dotted_rect(x, y, x + PAT_W, y + PAT_H, color); + } else { + draw_rect(x, y, x + PAT_W, y + PAT_H, color); + } txt_drawc(pat_names[i], x + 4, y + 1, color); y += PAT_OFFSET_Y; } @@ -404,7 +424,9 @@ draw_triggers(void) { size_t y1 = TRIG_START_Y + offset_y + TRIG_H; draw_rect(x0, y0, x1, y1, COL_FG); clear_trigger(i); - draw_trigger(channel_selection_loc, i); + if (!patterns[pattern_selection_loc].empty) { + draw_trigger(channel_selection_loc, i); + } } } diff --git a/src/main.c b/src/main.c index 3ddfaac..cff3afa 100644 --- a/src/main.c +++ b/src/main.c @@ -40,11 +40,14 @@ WITH REGARD TO THIS SOFTWARE. // + Improve "grey" cursor with dithering instead. // + New channel icons. // + Update rcol UI and cursor management. +// + Fix bug: Copy/paste don't update the BMP drawing. +// + Blank patterns could show up as empty on the pattern view for better +// separation and section organization. +// + Pattern can be cleared on pattern view with (SEL + L + R). This is +// reversible with the same combination unless the pattern is modified. // - Improve SRAM saving to make room for longer patterns and/or more banks. // - Make sure there is an ALL notification when modifying channel params so // that it's clear it's affecting all triggers. -// - Blank patterns could show up as empty on the pattern view for better -// separation and section organization. // - Scale mode for entering notes. // - Add CLEAR ALL to the settings menu. // - Higher resolution clock to allow for microtiming and more accurate tempo. @@ -60,9 +63,6 @@ WITH REGARD TO THIS SOFTWARE. // - Add CREDITS to the documentation for now, should probably be a menu item // later. // -// BUGS -// -// - Copy/paste don't update the BMP drawing. // NOTE: (by catbeats) // diff --git a/src/patterns.c b/src/patterns.c index 621eb14..a1f8f24 100644 --- a/src/patterns.c +++ b/src/patterns.c @@ -64,6 +64,7 @@ typedef struct Pattern { ChannelNoise ch4; int bpm; u8 bank; + bool empty; } Pattern; // @@ -233,14 +234,14 @@ const ChannelNoise default_ch4 = { const int default_bpm = 90; static Pattern patterns[8] = { - {default_ch1, default_ch2, default_ch3, default_ch4, default_bpm, 0}, - {default_ch1, default_ch2, default_ch3, default_ch4, default_bpm, 0}, - {default_ch1, default_ch2, default_ch3, default_ch4, default_bpm, 0}, - {default_ch1, default_ch2, default_ch3, default_ch4, default_bpm, 0}, - {default_ch1, default_ch2, default_ch3, default_ch4, default_bpm, 0}, - {default_ch1, default_ch2, default_ch3, default_ch4, default_bpm, 0}, - {default_ch1, default_ch2, default_ch3, default_ch4, default_bpm, 0}, - {default_ch1, default_ch2, default_ch3, default_ch4, default_bpm, 0}, + {default_ch1, default_ch2, default_ch3, default_ch4, default_bpm, 0, true}, + {default_ch1, default_ch2, default_ch3, default_ch4, default_bpm, 0, true}, + {default_ch1, default_ch2, default_ch3, default_ch4, default_bpm, 0, true}, + {default_ch1, default_ch2, default_ch3, default_ch4, default_bpm, 0, true}, + {default_ch1, default_ch2, default_ch3, default_ch4, default_bpm, 0, true}, + {default_ch1, default_ch2, default_ch3, default_ch4, default_bpm, 0, true}, + {default_ch1, default_ch2, default_ch3, default_ch4, default_bpm, 0, true}, + {default_ch1, default_ch2, default_ch3, default_ch4, default_bpm, 0, true}, }; static ChannelSquareParams ch1_params = {8, 4, 0, 2, 0, 0, 0, PROB_100, 0}; diff --git a/src/sequencer.c b/src/sequencer.c index 4e3802f..3110c74 100644 --- a/src/sequencer.c +++ b/src/sequencer.c @@ -19,6 +19,22 @@ bool redraw_piano_note = true; bool update_bpm = false; u8 bar_counter = 0; +void +clear_pattern(size_t idx) { + Pattern *pat = &patterns[idx]; + *pat = (Pattern){default_ch1, default_ch2, default_ch3, default_ch4, default_bpm, 0, false}; + for (size_t i = 0; i < 16; i++) { + pat->ch1.notes[i] = (TriggerNote){false, NOTE_C_4}; + pat->ch2.notes[i] = (TriggerNote){false, NOTE_C_4}; + pat->ch3.notes[i] = (TriggerNote){false, NOTE_C_4}; + pat->ch4.notes[i] = (TriggerNote){false, NOTE_C_4}; + } + redraw_pattern_buttons = true; + redraw_channels = true; + redraw_trigs = true; + redraw_bpm = true; +} + void gate_off(void) { SIO_MODE = SIO_MODE_GP @@ -117,7 +133,7 @@ play_step(void) { } chain.playing = true; } - if (pat->ch1.active) { + if (pat->ch1.active && !pat->empty) { TriggerNote *trig = &pat->ch1.notes[step_counter]; ChannelSquareParams *params = &pat->ch1.params[step_counter]; if (trig->active && should_play(params->prob)) { @@ -162,7 +178,7 @@ play_step(void) { SOUND_SQUARE1_FREQ = SOUND_FREQ_RESET; SOUND_SQUARE1_CTRL = 0; } - if (pat->ch2.active) { + if (pat->ch2.active && !pat->empty) { TriggerNote *trig = &pat->ch2.notes[step_counter]; ChannelSquareParams *params = &pat->ch2.params[step_counter]; if (trig->active && should_play(params->prob)) { @@ -188,7 +204,7 @@ play_step(void) { SOUND_SQUARE2_FREQ = SOUND_FREQ_RESET; SOUND_SQUARE2_CTRL = 0; } - if (pat->ch3.active) { + if (pat->ch3.active && !pat->empty) { TriggerNote *trig = &pat->ch3.notes[step_counter]; ChannelWaveParams *params = &pat->ch3.params[step_counter]; if (trig->active && should_play(params->prob)) { @@ -237,7 +253,7 @@ play_step(void) { SOUND_WAVE_FREQ = SOUND_FREQ_RESET; SOUND_WAVE_CTRL = SOUND_WAVE_MUTE; } - if (pat->ch4.active) { + if (pat->ch4.active && !pat->empty) { TriggerNote *trig = &pat->ch4.notes[step_counter]; ChannelNoiseParams *params = &pat->ch4.params[step_counter]; if (trig->active && should_play(params->prob)) { @@ -347,6 +363,9 @@ handle_channel_selection(void) { if (key_hold(KEY_SELECT)) { clipboard_copy(); } else { + if (patterns[pattern_selection_loc].empty) { + clear_pattern(pattern_selection_loc); + } switch (channel_selection_loc) { case 0: { pat->ch1.active ^= 1; } break; case 1: { pat->ch2.active ^= 1; } break; @@ -358,6 +377,10 @@ handle_channel_selection(void) { } else if (key_tap(KEY_A)) { if (key_hold(KEY_SELECT)) { clipboard_paste(); + redraw_bpm = true; + redraw_trigs = true; + redraw_channels = true; + redraw_pattern_buttons = true; } else { switch (channel_selection_loc) { case 0: { input_handler = handle_param_selection_ch1; } break; @@ -645,6 +668,9 @@ handle_right_col_selection(void) { set_time(patterns[current_pattern].bpm); } redraw_bpm = true; + if (patterns[pattern_selection_loc].empty) { + clear_pattern(pattern_selection_loc); + } } break; // TODO: Scale. } @@ -664,6 +690,9 @@ handle_right_col_selection(void) { set_time(patterns[current_pattern].bpm); } redraw_bpm = true; + if (patterns[pattern_selection_loc].empty) { + clear_pattern(pattern_selection_loc); + } } break; // TODO: Scale. } @@ -748,20 +777,32 @@ handle_pattern_chain(void) { void handle_pattern_selection(void) { - if (key_tap(KEY_B)) { - if (key_hold(KEY_SELECT)) { + if (key_hold(KEY_SELECT)) { + if ((key_pressed(KEY_L) && key_tap(KEY_R)) + || (key_pressed(KEY_R) && key_tap(KEY_L))) { + patterns[pattern_selection_loc].empty ^= 1; + redraw_pattern_buttons = true; + redraw_channels = true; + redraw_trigs = true; + } + if (key_tap(KEY_B)) { clipboard_copy(); - } else { - next_pattern = pattern_selection_loc; + } + if (key_tap(KEY_A)) { + clipboard_paste(); + redraw_bpm = true; + redraw_trigs = true; + redraw_channels = true; redraw_pattern_buttons = true; } + return; + } + if (key_tap(KEY_B)) { + next_pattern = pattern_selection_loc; + redraw_pattern_buttons = true; } if (key_tap(KEY_A)) { - if (key_hold(KEY_SELECT)) { - clipboard_paste(); - } else { - input_handler = handle_pattern_chain; - } + input_handler = handle_pattern_chain; } if (key_tap(KEY_RIGHT)) { input_handler = handle_channel_selection; @@ -1214,11 +1255,14 @@ void handle_trigger_selection(void) { TriggerNote *trig = get_current_trig(); + bool empty = patterns[pattern_selection_loc].empty; if (key_tap(KEY_B)) { if (key_hold(KEY_SELECT)) { clipboard_copy(); } else { - // Toggle trigger. + if (empty) { + clear_pattern(pattern_selection_loc); + } trig->active ^= 1; redraw_trigs = true; } @@ -1228,7 +1272,7 @@ handle_trigger_selection(void) { inc = -12; } // Decrease note. - if (trig->active) { + if (trig->active && !empty) { trig->note = MAX((s32)trig->note + inc, (s32)NOTE_C_2); } redraw_trigs = true; @@ -1239,7 +1283,7 @@ handle_trigger_selection(void) { inc = 12; } // Increase note. - if (trig->active) { + if (trig->active && !empty) { trig->note = MIN((s32)trig->note + inc, (s32)NOTE_C_8 - 1); } redraw_trigs = true; @@ -1275,6 +1319,10 @@ handle_trigger_selection(void) { } else if (key_tap(KEY_A)) { if (key_hold(KEY_SELECT)) { clipboard_paste(); + redraw_bpm = true; + redraw_trigs = true; + redraw_channels = true; + redraw_pattern_buttons = true; } else { // Switch to parameter selection. switch (channel_selection_loc) { -- cgit v1.2.1