aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2023-07-13 12:00:11 +0200
committerBad Diode <bd@badd10de.dev>2023-07-13 12:00:11 +0200
commit7f57051c51c16c88e5dcaa7bd51ccaec31469c4a (patch)
treeb484dc485d7f9718238343ffb5952428d2f52621
parentd1c68125b6825f0327a4089aa8ddca5105e78ec1 (diff)
downloadstepper-7f57051c51c16c88e5dcaa7bd51ccaec31469c4a.tar.gz
stepper-7f57051c51c16c88e5dcaa7bd51ccaec31469c4a.zip
Add working pattern chaining prototype
-rw-r--r--src/drawing.c20
-rw-r--r--src/globals.c4
-rw-r--r--src/sequencer.c76
3 files changed, 85 insertions, 15 deletions
diff --git a/src/drawing.c b/src/drawing.c
index dff5db2..4e793ea 100644
--- a/src/drawing.c
+++ b/src/drawing.c
@@ -1305,11 +1305,16 @@ draw_notif_bar() {
1305 *ptr++ = 'n'; 1305 *ptr++ = 'n';
1306 *ptr++ = ':'; 1306 *ptr++ = ':';
1307 *ptr++ = ' '; 1307 *ptr++ = ' ';
1308 for (size_t i = 0; i < chain.len; i++) { 1308 bool first = true;
1309 if (i != 0) { 1309 for (size_t i = 0; i < MAX_CHAIN; i++) {
1310 if (chain.active[i] != 1) {
1311 continue;
1312 }
1313 if (!first) {
1310 *ptr++ = '-'; 1314 *ptr++ = '-';
1311 } 1315 }
1312 *ptr++ = 'A' + chain.chain[i]; 1316 *ptr++ = 'A' + chain.chain[i];
1317 first = false;
1313 } 1318 }
1314 *ptr++ = '\0'; 1319 *ptr++ = '\0';
1315 txt_drawf_small(msg, x0 + 2, y0 + 1, color); 1320 txt_drawf_small(msg, x0 + 2, y0 + 1, color);
@@ -1338,13 +1343,8 @@ draw_pattern_chain() {
1338 if (chain.active[i]) { 1343 if (chain.active[i]) {
1339 txt_drawc('A' + chain.chain[i], x0 + 4, y0 + 3, color); 1344 txt_drawc('A' + chain.chain[i], x0 + 4, y0 + 3, color);
1340 } 1345 }
1346 if (chain.current == i && chain.len != 0) {
1347 draw_line(x0 + 5, y1 - 2, x1 - 5, y1 - 2, COL_ACC_0);
1348 }
1341 } 1349 }
1342 // draw_rect(
1343 // PARAMS_START_X,
1344 // PARAMS_START_Y + 6,
1345 // PARAMS_START_X + PARAMS_W,
1346 // PARAMS_START_Y + PARAMS_H - 6, COL_FG);
1347 // txt_drawf_small("Current pattern: %s", PARAMS_START_X + 3, PARAMS_START_Y + 8, COL_FG, "A");
1348 // txt_drawf_small("Next pattern: %s", PARAMS_START_X + 3, PARAMS_START_Y + 8 * 2, COL_FG, "A");
1349 // txt_drawf_small("Chain: %s", PARAMS_START_X + 3, PARAMS_START_Y + 8 * 3, COL_FG, "A - B - B - A - B");
1350} 1350}
diff --git a/src/globals.c b/src/globals.c
index 3a70005..1efa90c 100644
--- a/src/globals.c
+++ b/src/globals.c
@@ -144,8 +144,10 @@ typedef struct Chain {
144 u8 chain[MAX_CHAIN]; 144 u8 chain[MAX_CHAIN];
145 u8 active[MAX_CHAIN]; 145 u8 active[MAX_CHAIN];
146 u8 len; 146 u8 len;
147 u8 loop;
148 u8 current; 147 u8 current;
148 u8 playing;
149} Chain; 149} Chain;
150 150
151// DEBUG:...
152// static Chain chain = {.chain = {0, 1, 2, 3, 4, 5, 6}, .active = { 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1,1, 1,1,1,1}, .len = 14};
151static Chain chain = {0}; 153static Chain chain = {0};
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) {
47 TIMER_CTRL_3 = TIMER_CTRL_IRQ | TIMER_CTRL_ENABLE | TIMER_CTRL_FREQ_3; 47 TIMER_CTRL_3 = TIMER_CTRL_IRQ | TIMER_CTRL_ENABLE | TIMER_CTRL_FREQ_3;
48} 48}
49 49
50u8
51find_next_pattern(void) {
52 u8 idx = (chain.current + 1) % 16;
53 for (size_t i = 0; i < MAX_CHAIN; i++) {
54 if (chain.active[idx] == 1) {
55 break;
56 }
57 idx = (idx + 1) % 16;
58 }
59 return idx;
60}
61
62u8
63find_prev_pattern(void) {
64 u8 idx = chain.current == 0 ? 15 : (chain.current - 1);
65 for (size_t i = 0; i < MAX_CHAIN; i++) {
66 if (chain.active[idx] == 1) {
67 break;
68 }
69 idx = chain.current == 0 ? 15 : (chain.current - 1);
70 }
71 return idx;
72}
73
50void 74void
51play_step(void) { 75play_step(void) {
52 Pattern *pat = &patterns[current_pattern]; 76 Pattern *pat = &patterns[current_pattern];
@@ -54,6 +78,18 @@ play_step(void) {
54 current_pattern = next_pattern; 78 current_pattern = next_pattern;
55 redraw_pattern_buttons = true; 79 redraw_pattern_buttons = true;
56 update_bpm = true; 80 update_bpm = true;
81 } else if (chain.len != 0 && step_counter == 15) {
82 redraw_pattern_buttons = true;
83 update_bpm = true;
84 if (!chain.playing) {
85 next_pattern = chain.chain[chain.current];
86 current_pattern = next_pattern;
87 } else {
88 chain.current = find_next_pattern();
89 next_pattern = chain.chain[chain.current];
90 current_pattern = next_pattern;
91 }
92 chain.playing = true;
57 } 93 }
58 if (pat->ch1.active) { 94 if (pat->ch1.active) {
59 TriggerNote *trig = &pat->ch1.notes[step_counter]; 95 TriggerNote *trig = &pat->ch1.notes[step_counter];
@@ -316,6 +352,9 @@ stop_sound(void) {
316void 352void
317stop_playing(void) { 353stop_playing(void) {
318 step_counter = 0; 354 step_counter = 0;
355 chain.current = 15;
356 chain.current = find_next_pattern();
357 chain.playing = false;
319 stop_sound(); 358 stop_sound();
320} 359}
321 360
@@ -323,6 +362,15 @@ void
323toggle_playing(void) { 362toggle_playing(void) {
324 play_status ^= 1; 363 play_status ^= 1;
325 step_counter = 0; 364 step_counter = 0;
365 chain.current = 15;
366 chain.current = find_next_pattern();
367 chain.playing = false;
368 if (current_pattern == next_pattern && chain.len > 0) {
369 chain.playing = true;
370 next_pattern = chain.chain[chain.current];
371 current_pattern = next_pattern;
372 }
373 redraw_pattern_buttons = true;
326 SOUND_SQUARE1_CTRL = 0; 374 SOUND_SQUARE1_CTRL = 0;
327 SOUND_SQUARE2_CTRL = 0; 375 SOUND_SQUARE2_CTRL = 0;
328 SOUND_WAVE_CTRL = 0; 376 SOUND_WAVE_CTRL = 0;
@@ -351,6 +399,12 @@ pause_playing(void) {
351 SOUND_SQUARE2_CTRL = 0; 399 SOUND_SQUARE2_CTRL = 0;
352 SOUND_WAVE_CTRL = 0; 400 SOUND_WAVE_CTRL = 0;
353 SOUND_NOISE_CTRL = 0; 401 SOUND_NOISE_CTRL = 0;
402 chain.playing = false;
403 if (current_pattern == next_pattern && chain.len > 0) {
404 chain.playing = true;
405 next_pattern = chain.chain[chain.current];
406 current_pattern = next_pattern;
407 }
354 redraw_play_pause = true; 408 redraw_play_pause = true;
355 if (settings.sync == SYNC_IN_LINK) { 409 if (settings.sync == SYNC_IN_LINK) {
356 return; 410 return;
@@ -530,23 +584,37 @@ handle_pattern_selection(void) {
530 } 584 }
531 } 585 }
532 if (slot > -1) { 586 if (slot > -1) {
587 if (chain.len == 0) {
588 chain.current = slot;
589 }
533 chain.chain[slot] = pattern_selection_loc; 590 chain.chain[slot] = pattern_selection_loc;
534 chain.active[slot] = 1; 591 chain.active[slot] = 1;
535 chain.len++; // TODO: remove 592 chain.len++;
536 } 593 }
537 } 594 }
538 if (key_tap(KEY_L)) { 595 if (key_tap(KEY_L)) {
539 // Find last active slot. 596 // Find last active slot.
540 s16 slot = -1; 597 s16 slot = -1;
598 bool update_current = false;
541 for (size_t i = 0; i < 16; i++) { 599 for (size_t i = 0; i < 16; i++) {
542 if (chain.active[15 - i] == 1) { 600 size_t idx = 15 - i;
543 slot = 15 - i; 601 if (chain.active[idx] == 1) {
602 // If the pattern is currently playing it can't be removed.
603 if (play_status && idx == chain.current) {
604 continue;
605 } else if (idx == chain.current) {
606 update_current = true;
607 }
608 slot = idx;
544 break; 609 break;
545 } 610 }
546 } 611 }
547 if (slot > -1) { 612 if (slot > -1) {
548 chain.active[slot] = 0; 613 chain.active[slot] = 0;
549 chain.len--; // TODO: remove 614 chain.len--;
615 if (update_current) {
616 chain.current = find_prev_pattern();
617 }
550 } 618 }
551 } 619 }
552} 620}