diff options
author | Bad Diode <bd@badd10de.dev> | 2023-04-04 09:38:55 +0200 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2023-04-04 09:38:55 +0200 |
commit | 3f3968e15776104c5420a0442364cda5a76d3f77 (patch) | |
tree | 9c8920344c62fe39983544227ebe95e6de26cb3b | |
parent | 47e1e8a63d466ab540e39eaf0f87326e33f38c67 (diff) | |
download | stepper-3f3968e15776104c5420a0442364cda5a76d3f77.tar.gz stepper-3f3968e15776104c5420a0442364cda5a76d3f77.zip |
Add bpm and play/pause buttons control
-rw-r--r-- | src/sequencer.c | 241 |
1 files changed, 187 insertions, 54 deletions
diff --git a/src/sequencer.c b/src/sequencer.c index d0705a7..855bbe5 100644 --- a/src/sequencer.c +++ b/src/sequencer.c | |||
@@ -2,12 +2,11 @@ | |||
2 | #include "text.h" | 2 | #include "text.h" |
3 | 3 | ||
4 | // TODO | 4 | // TODO |
5 | // - Preview sound keys | 5 | // - Preview sound keys? |
6 | // - Copy paste trigs/notes/params | 6 | // - Copy paste trigs/notes/params |
7 | // - Different banks for storing patterns | 7 | // - Different banks for storing patterns |
8 | // - Buttons on the left side for selecting different patterns | 8 | // - Finish noise channel (parameter editing) |
9 | // - Allow control BPM | 9 | |
10 | // - Finish noise channel | ||
11 | 10 | ||
12 | // | 11 | // |
13 | // Color indexes. | 12 | // Color indexes. |
@@ -59,6 +58,17 @@ | |||
59 | #define PAT_H 12 | 58 | #define PAT_H 12 |
60 | #define PAT_OFFSET_Y 17 | 59 | #define PAT_OFFSET_Y 17 |
61 | 60 | ||
61 | #define R_COL_W 24 | ||
62 | #define BPM_START_X (R_SIDEBAR_X) | ||
63 | #define BPM_START_Y (TRIG_START_Y + TRIG_H + 9) | ||
64 | #define BPM_H 22 | ||
65 | |||
66 | #define PLAY_START_X (R_SIDEBAR_X) | ||
67 | #define PLAY_START_Y (TRIG_START_Y) | ||
68 | #define STOP_START_X (R_SIDEBAR_X) | ||
69 | #define STOP_START_Y (TRIG_START_Y + 14) | ||
70 | #define PLAY_STOP_H (10) | ||
71 | |||
62 | #define SEQ_N_CHANNELS 4 | 72 | #define SEQ_N_CHANNELS 4 |
63 | 73 | ||
64 | // | 74 | // |
@@ -193,10 +203,17 @@ int trig_selection_loc = 0; | |||
193 | int param_selection_loc = 0; | 203 | int param_selection_loc = 0; |
194 | int channel_selection_loc = 0; | 204 | int channel_selection_loc = 0; |
195 | int pattern_selection_loc = 0; | 205 | int pattern_selection_loc = 0; |
206 | int right_col_selection_loc = 0; | ||
196 | int play_status = 0; | 207 | int play_status = 0; |
197 | static int current_pattern = 0; | 208 | static int current_pattern = 0; |
198 | static int next_pattern = 0; | 209 | static int next_pattern = 0; |
199 | 210 | ||
211 | enum RIGHT_COL_LOC { | ||
212 | R_COL_BPM = 0, | ||
213 | R_COL_STOP = 1, | ||
214 | R_COL_PLAY = 2, | ||
215 | }; | ||
216 | |||
200 | typedef struct TriggerNote { | 217 | typedef struct TriggerNote { |
201 | bool active; | 218 | bool active; |
202 | Note note; | 219 | Note note; |
@@ -524,6 +541,31 @@ draw_trig_cursor(size_t i, u8 clr) { | |||
524 | } | 541 | } |
525 | 542 | ||
526 | void | 543 | void |
544 | draw_right_col_cursor(u8 clr) { | ||
545 | size_t x0 = 0; | ||
546 | size_t x1 = 0; | ||
547 | size_t y = 0; | ||
548 | switch (right_col_selection_loc) { | ||
549 | case R_COL_BPM: { | ||
550 | x0 = BPM_START_X; | ||
551 | x1 = x0 + R_COL_W; | ||
552 | y = BPM_START_Y + BPM_H + 2; | ||
553 | } break; | ||
554 | case R_COL_STOP: { | ||
555 | x0 = STOP_START_X; | ||
556 | x1 = x0 + R_COL_W; | ||
557 | y = STOP_START_Y + PLAY_STOP_H + 2; | ||
558 | } break; | ||
559 | case R_COL_PLAY: { | ||
560 | x0 = PLAY_START_X; | ||
561 | x1 = x0 + R_COL_W; | ||
562 | y = PLAY_START_Y + PLAY_STOP_H + 2; | ||
563 | } break; | ||
564 | } | ||
565 | draw_line(x0, y, x1, y, clr); | ||
566 | } | ||
567 | |||
568 | void | ||
527 | draw_current_step(u8 col) { | 569 | draw_current_step(u8 col) { |
528 | size_t offset_x = TRIG_OFFSET_X * (step_counter % 8); | 570 | size_t offset_x = TRIG_OFFSET_X * (step_counter % 8); |
529 | size_t offset_y = step_counter < 8 ? 2 : 2 + TRIG_OFFSET_Y; | 571 | size_t offset_y = step_counter < 8 ? 2 : 2 + TRIG_OFFSET_Y; |
@@ -534,26 +576,6 @@ draw_current_step(u8 col) { | |||
534 | } | 576 | } |
535 | 577 | ||
536 | void | 578 | void |
537 | draw_play() { | ||
538 | size_t x = R_SIDEBAR_X; | ||
539 | size_t y = TRIG_START_Y; | ||
540 | draw_filled_rect(x, y, x + 24, y + 10, COL_BG); | ||
541 | draw_rect(x, y, x + 24, y + 10, COL_CYAN); | ||
542 | if (play_status == 1) { | ||
543 | // Pause button | ||
544 | draw_filled_rect(x + 10, y + 3, x + 11, y + 7, COL_CYAN); | ||
545 | draw_filled_rect(x + 13, y + 3, x + 14, y + 7, COL_CYAN); | ||
546 | } else { | ||
547 | // Play button | ||
548 | x += 1; | ||
549 | draw_line(x + 10, y + 2, x + 10, y + 8, COL_CYAN); | ||
550 | draw_line(x + 11, y + 3, x + 11, y + 7, COL_CYAN); | ||
551 | draw_line(x + 12, y + 4, x + 12, y + 6, COL_CYAN); | ||
552 | draw_line(x + 13, y + 5, x + 13, y + 5, COL_CYAN); | ||
553 | } | ||
554 | } | ||
555 | |||
556 | void | ||
557 | draw_pattern_buttons() { | 579 | draw_pattern_buttons() { |
558 | size_t x = PAT_START_X; | 580 | size_t x = PAT_START_X; |
559 | size_t y = PAT_START_Y; | 581 | size_t y = PAT_START_Y; |
@@ -588,20 +610,41 @@ draw_pattern_cursor(size_t i, u8 clr) { | |||
588 | } | 610 | } |
589 | 611 | ||
590 | void | 612 | void |
613 | draw_play() { | ||
614 | size_t x = PLAY_START_X; | ||
615 | size_t y = PLAY_START_Y; | ||
616 | draw_filled_rect(x, y, x + R_COL_W, y + PLAY_STOP_H, COL_BG); | ||
617 | draw_rect(x, y, x + R_COL_W, y + PLAY_STOP_H, COL_CYAN); | ||
618 | if (play_status == 1) { | ||
619 | // Pause button | ||
620 | draw_filled_rect(x + 10, y + 3, x + 11, y + 7, COL_CYAN); | ||
621 | draw_filled_rect(x + 13, y + 3, x + 14, y + 7, COL_CYAN); | ||
622 | } else { | ||
623 | // Play button | ||
624 | x += 1; | ||
625 | draw_line(x + 10, y + 2, x + 10, y + 8, COL_CYAN); | ||
626 | draw_line(x + 11, y + 3, x + 11, y + 7, COL_CYAN); | ||
627 | draw_line(x + 12, y + 4, x + 12, y + 6, COL_CYAN); | ||
628 | draw_line(x + 13, y + 5, x + 13, y + 5, COL_CYAN); | ||
629 | } | ||
630 | } | ||
631 | |||
632 | void | ||
591 | draw_stop() { | 633 | draw_stop() { |
592 | size_t x = R_SIDEBAR_X; | 634 | size_t x = STOP_START_X; |
593 | size_t y = TRIG_START_Y + 14; | 635 | size_t y = STOP_START_Y; |
594 | draw_rect(x, y, x + 24, y + 10, COL_RED); | 636 | draw_rect(x, y, x + R_COL_W, y + PLAY_STOP_H, COL_RED); |
595 | draw_filled_rect(x + 10, y + 3, x + 14, y + 7, COL_RED); | 637 | draw_filled_rect(x + 10, y + 3, x + 14, y + 7, COL_RED); |
596 | } | 638 | } |
597 | 639 | ||
598 | void | 640 | void |
599 | draw_bpm() { | 641 | draw_bpm() { |
600 | size_t x = R_SIDEBAR_X; | 642 | size_t x = BPM_START_X; |
601 | size_t y = TRIG_START_Y + TRIG_H + 9; | 643 | size_t y = BPM_START_Y; |
602 | 644 | ||
603 | // Draw bounding box. | 645 | // Draw bounding box. |
604 | draw_rect(x, y, x + 24, y + 22, COL_FG); | 646 | draw_filled_rect(x, y, x + R_COL_W, y + BPM_H, COL_BG); |
647 | draw_rect(x, y, x + R_COL_W, y + BPM_H, COL_FG); | ||
605 | draw_line(x + 5, y, x + 19, y, COL_BG); | 648 | draw_line(x + 5, y, x + 19, y, COL_BG); |
606 | txt_drawf_small("BPM", x + 5, y - 4, 4, COL_FG); | 649 | txt_drawf_small("BPM", x + 5, y - 4, 4, COL_FG); |
607 | 650 | ||
@@ -820,6 +863,9 @@ draw_params_cursor_wave(size_t i, u8 clr) { | |||
820 | 863 | ||
821 | void | 864 | void |
822 | draw_params_cursor_noise(size_t i, u8 clr) { | 865 | draw_params_cursor_noise(size_t i, u8 clr) { |
866 | // TODO: Handle this. | ||
867 | (void)i; | ||
868 | (void)clr; | ||
823 | // u8 x_positions[] = { | 869 | // u8 x_positions[] = { |
824 | // // 32 half bytes (Wave A). | 870 | // // 32 half bytes (Wave A). |
825 | // 0, 4, 8, 12, 16, 20, 24, 28, | 871 | // 0, 4, 8, 12, 16, 20, 24, 28, |
@@ -1611,6 +1657,7 @@ void handle_param_selection_sq1(void); | |||
1611 | void handle_param_selection_sq2(void); | 1657 | void handle_param_selection_sq2(void); |
1612 | void handle_param_selection_wave(void); | 1658 | void handle_param_selection_wave(void); |
1613 | void handle_param_selection_noise(void); | 1659 | void handle_param_selection_noise(void); |
1660 | void handle_right_col_selection(void); | ||
1614 | 1661 | ||
1615 | void | 1662 | void |
1616 | handle_channel_selection(void) { | 1663 | handle_channel_selection(void) { |
@@ -1666,6 +1713,101 @@ handle_channel_selection(void) { | |||
1666 | } | 1713 | } |
1667 | 1714 | ||
1668 | void | 1715 | void |
1716 | stop_playing(void) { | ||
1717 | play_status ^= 1; | ||
1718 | if (step_counter != 0) { | ||
1719 | draw_current_step(COL_BG); | ||
1720 | } | ||
1721 | step_counter = 0; | ||
1722 | if ((TIMER_CTRL_0 & TIMER_CTRL_ENABLE) == 0) { | ||
1723 | set_time(patterns[current_pattern].bpm); | ||
1724 | } else { | ||
1725 | TIMER_CTRL_0 ^= TIMER_CTRL_ENABLE; | ||
1726 | SOUND_SQUARE1_CTRL = 0; | ||
1727 | SOUND_SQUARE2_CTRL = 0; | ||
1728 | SOUND_WAVE_CTRL = 0; | ||
1729 | SOUND_NOISE_CTRL = 0; | ||
1730 | } | ||
1731 | draw_current_step(COL_RED); | ||
1732 | draw_play(); | ||
1733 | } | ||
1734 | |||
1735 | void | ||
1736 | pause_playing(void) { | ||
1737 | play_status ^= 1; | ||
1738 | if ((TIMER_CTRL_0 & TIMER_CTRL_ENABLE) == 0) { | ||
1739 | set_time(patterns[current_pattern].bpm); | ||
1740 | } else { | ||
1741 | TIMER_CTRL_0 ^= TIMER_CTRL_ENABLE; | ||
1742 | SOUND_SQUARE1_CTRL = 0; | ||
1743 | SOUND_SQUARE2_CTRL = 0; | ||
1744 | SOUND_WAVE_CTRL = 0; | ||
1745 | SOUND_NOISE_CTRL = 0; | ||
1746 | } | ||
1747 | draw_play(); | ||
1748 | } | ||
1749 | |||
1750 | void | ||
1751 | handle_right_col_selection(void) { | ||
1752 | if (key_tap(KEY_LEFT)) { | ||
1753 | input_handler = handle_trigger_selection; | ||
1754 | switch (right_col_selection_loc) { | ||
1755 | case R_COL_BPM: { | ||
1756 | trig_selection_loc = 15; | ||
1757 | } break; | ||
1758 | case R_COL_PLAY : | ||
1759 | case R_COL_STOP: { | ||
1760 | trig_selection_loc = 7; | ||
1761 | } break; | ||
1762 | } | ||
1763 | draw_right_col_cursor(COL_BG); | ||
1764 | draw_trig_cursor(trig_selection_loc, COL_CURSOR); | ||
1765 | TriggerNote *trig = get_current_trig(); | ||
1766 | draw_note(trig->note, COL_NOTE_PRESSED); | ||
1767 | draw_parameters(); | ||
1768 | } else if (key_tap(KEY_UP)) { | ||
1769 | if (right_col_selection_loc < 2) { | ||
1770 | draw_right_col_cursor(COL_BG); | ||
1771 | right_col_selection_loc++; | ||
1772 | draw_right_col_cursor(COL_CURSOR); | ||
1773 | } | ||
1774 | } else if (key_tap(KEY_DOWN)) { | ||
1775 | if (right_col_selection_loc > 0) { | ||
1776 | draw_right_col_cursor(COL_BG); | ||
1777 | right_col_selection_loc--; | ||
1778 | draw_right_col_cursor(COL_CURSOR); | ||
1779 | } | ||
1780 | } else if (key_tap(KEY_L)) { | ||
1781 | switch (right_col_selection_loc) { | ||
1782 | case R_COL_BPM: { | ||
1783 | if (patterns[pattern_selection_loc].bpm > 10) { | ||
1784 | set_time(--patterns[pattern_selection_loc].bpm); | ||
1785 | draw_bpm(); | ||
1786 | } | ||
1787 | } break; | ||
1788 | } | ||
1789 | } else if (key_tap(KEY_R)) { | ||
1790 | switch (right_col_selection_loc) { | ||
1791 | case R_COL_BPM: { | ||
1792 | if (patterns[pattern_selection_loc].bpm < 300) { | ||
1793 | set_time(++patterns[pattern_selection_loc].bpm); | ||
1794 | draw_bpm(); | ||
1795 | } | ||
1796 | } break; | ||
1797 | } | ||
1798 | } else if (key_tap(KEY_B)) { | ||
1799 | switch (right_col_selection_loc) { | ||
1800 | case R_COL_STOP: { | ||
1801 | stop_playing(); | ||
1802 | } break; | ||
1803 | case R_COL_PLAY: { | ||
1804 | pause_playing(); | ||
1805 | } break; | ||
1806 | } | ||
1807 | } | ||
1808 | } | ||
1809 | |||
1810 | void | ||
1669 | handle_pattern_selection(void) { | 1811 | handle_pattern_selection(void) { |
1670 | if (key_tap(KEY_B)) { | 1812 | if (key_tap(KEY_B)) { |
1671 | next_pattern = pattern_selection_loc; | 1813 | next_pattern = pattern_selection_loc; |
@@ -2236,7 +2378,7 @@ handle_trigger_selection(void) { | |||
2236 | draw_parameters(); | 2378 | draw_parameters(); |
2237 | } | 2379 | } |
2238 | } else if (key_tap(KEY_RIGHT)) { | 2380 | } else if (key_tap(KEY_RIGHT)) { |
2239 | if (trig_selection_loc != 7) { | 2381 | if (trig_selection_loc != 7 && trig_selection_loc != 15) { |
2240 | draw_trig_cursor(trig_selection_loc, COL_BG); | 2382 | draw_trig_cursor(trig_selection_loc, COL_BG); |
2241 | draw_note(trig->note, COL_FG); | 2383 | draw_note(trig->note, COL_FG); |
2242 | trig_selection_loc = MIN(trig_selection_loc + 1, 15); | 2384 | trig_selection_loc = MIN(trig_selection_loc + 1, 15); |
@@ -2244,6 +2386,18 @@ handle_trigger_selection(void) { | |||
2244 | draw_trig_cursor(trig_selection_loc, COL_CURSOR); | 2386 | draw_trig_cursor(trig_selection_loc, COL_CURSOR); |
2245 | draw_note(trig->note, COL_NOTE_PRESSED); | 2387 | draw_note(trig->note, COL_NOTE_PRESSED); |
2246 | draw_parameters(); | 2388 | draw_parameters(); |
2389 | } else if (trig_selection_loc == 7) { | ||
2390 | input_handler = handle_right_col_selection; | ||
2391 | right_col_selection_loc = R_COL_STOP; | ||
2392 | draw_trig_cursor(trig_selection_loc, COL_BG); | ||
2393 | draw_note(trig->note, COL_FG); | ||
2394 | draw_right_col_cursor(COL_CURSOR); | ||
2395 | } else if (trig_selection_loc == 15) { | ||
2396 | right_col_selection_loc = R_COL_BPM; | ||
2397 | input_handler = handle_right_col_selection; | ||
2398 | draw_trig_cursor(trig_selection_loc, COL_BG); | ||
2399 | draw_note(trig->note, COL_FG); | ||
2400 | draw_right_col_cursor(COL_CURSOR); | ||
2247 | } | 2401 | } |
2248 | } else if (key_tap(KEY_UP) || key_tap(KEY_DOWN)) { | 2402 | } else if (key_tap(KEY_UP) || key_tap(KEY_DOWN)) { |
2249 | draw_trig_cursor(trig_selection_loc, COL_BG); | 2403 | draw_trig_cursor(trig_selection_loc, COL_BG); |
@@ -2281,31 +2435,10 @@ handle_sequencer_input(void) { | |||
2281 | 2435 | ||
2282 | if (key_tap(KEY_START)) { | 2436 | if (key_tap(KEY_START)) { |
2283 | // Stop the sequencer or start playing from the beginning. | 2437 | // Stop the sequencer or start playing from the beginning. |
2284 | play_status ^= 1; | 2438 | stop_playing(); |
2285 | if (step_counter != 0) { | ||
2286 | draw_current_step(COL_BG); | ||
2287 | } | ||
2288 | step_counter = 0; | ||
2289 | if ((TIMER_CTRL_0 & TIMER_CTRL_ENABLE) == 0) { | ||
2290 | set_time(patterns[current_pattern].bpm); | ||
2291 | } else { | ||
2292 | draw_current_step(COL_RED); | ||
2293 | TIMER_CTRL_0 ^= TIMER_CTRL_ENABLE; | ||
2294 | SOUND_SQUARE1_CTRL = 0; | ||
2295 | SOUND_SQUARE2_CTRL = 0; | ||
2296 | SOUND_WAVE_CTRL = 0; | ||
2297 | SOUND_NOISE_CTRL = 0; | ||
2298 | } | ||
2299 | draw_play(); | ||
2300 | } else if (key_tap(KEY_SELECT)) { | 2439 | } else if (key_tap(KEY_SELECT)) { |
2301 | // Play/pause. | 2440 | // Play/pause. |
2302 | play_status ^= 1; | 2441 | pause_playing(); |
2303 | TIMER_CTRL_0 ^= TIMER_CTRL_ENABLE; | ||
2304 | SOUND_SQUARE1_CTRL = 0; | ||
2305 | SOUND_SQUARE2_CTRL = 0; | ||
2306 | SOUND_WAVE_CTRL = 0; | ||
2307 | SOUND_NOISE_CTRL = 0; | ||
2308 | draw_play(); | ||
2309 | } | 2442 | } |
2310 | } | 2443 | } |
2311 | 2444 | ||