From 7f57051c51c16c88e5dcaa7bd51ccaec31469c4a Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Thu, 13 Jul 2023 12:00:11 +0200 Subject: Add working pattern chaining prototype --- src/sequencer.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 72 insertions(+), 4 deletions(-) (limited to 'src/sequencer.c') diff --git a/src/sequencer.c b/src/sequencer.c index 44ff90e..8d79c65 100644 --- a/src/sequencer.c +++ b/src/sequencer.c @@ -47,6 +47,30 @@ gate_on(void) { TIMER_CTRL_3 = TIMER_CTRL_IRQ | TIMER_CTRL_ENABLE | TIMER_CTRL_FREQ_3; } +u8 +find_next_pattern(void) { + u8 idx = (chain.current + 1) % 16; + for (size_t i = 0; i < MAX_CHAIN; i++) { + if (chain.active[idx] == 1) { + break; + } + idx = (idx + 1) % 16; + } + return idx; +} + +u8 +find_prev_pattern(void) { + u8 idx = chain.current == 0 ? 15 : (chain.current - 1); + for (size_t i = 0; i < MAX_CHAIN; i++) { + if (chain.active[idx] == 1) { + break; + } + idx = chain.current == 0 ? 15 : (chain.current - 1); + } + return idx; +} + void play_step(void) { Pattern *pat = &patterns[current_pattern]; @@ -54,6 +78,18 @@ play_step(void) { current_pattern = next_pattern; redraw_pattern_buttons = true; update_bpm = true; + } else if (chain.len != 0 && step_counter == 15) { + redraw_pattern_buttons = true; + update_bpm = true; + if (!chain.playing) { + next_pattern = chain.chain[chain.current]; + current_pattern = next_pattern; + } else { + chain.current = find_next_pattern(); + next_pattern = chain.chain[chain.current]; + current_pattern = next_pattern; + } + chain.playing = true; } if (pat->ch1.active) { TriggerNote *trig = &pat->ch1.notes[step_counter]; @@ -316,6 +352,9 @@ stop_sound(void) { void stop_playing(void) { step_counter = 0; + chain.current = 15; + chain.current = find_next_pattern(); + chain.playing = false; stop_sound(); } @@ -323,6 +362,15 @@ void toggle_playing(void) { play_status ^= 1; step_counter = 0; + chain.current = 15; + chain.current = find_next_pattern(); + chain.playing = false; + if (current_pattern == next_pattern && chain.len > 0) { + chain.playing = true; + next_pattern = chain.chain[chain.current]; + current_pattern = next_pattern; + } + redraw_pattern_buttons = true; SOUND_SQUARE1_CTRL = 0; SOUND_SQUARE2_CTRL = 0; SOUND_WAVE_CTRL = 0; @@ -351,6 +399,12 @@ pause_playing(void) { SOUND_SQUARE2_CTRL = 0; SOUND_WAVE_CTRL = 0; SOUND_NOISE_CTRL = 0; + chain.playing = false; + if (current_pattern == next_pattern && chain.len > 0) { + chain.playing = true; + next_pattern = chain.chain[chain.current]; + current_pattern = next_pattern; + } redraw_play_pause = true; if (settings.sync == SYNC_IN_LINK) { return; @@ -530,23 +584,37 @@ handle_pattern_selection(void) { } } if (slot > -1) { + if (chain.len == 0) { + chain.current = slot; + } chain.chain[slot] = pattern_selection_loc; chain.active[slot] = 1; - chain.len++; // TODO: remove + chain.len++; } } if (key_tap(KEY_L)) { // Find last active slot. s16 slot = -1; + bool update_current = false; for (size_t i = 0; i < 16; i++) { - if (chain.active[15 - i] == 1) { - slot = 15 - i; + size_t idx = 15 - i; + if (chain.active[idx] == 1) { + // If the pattern is currently playing it can't be removed. + if (play_status && idx == chain.current) { + continue; + } else if (idx == chain.current) { + update_current = true; + } + slot = idx; break; } } if (slot > -1) { chain.active[slot] = 0; - chain.len--; // TODO: remove + chain.len--; + if (update_current) { + chain.current = find_prev_pattern(); + } } } } -- cgit v1.2.1