aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2023-08-25 15:42:58 +0200
committerBad Diode <bd@badd10de.dev>2023-08-25 15:42:58 +0200
commitfff06404696bb8790901cdefe016cd8d0fe856cb (patch)
treea42ac0a2afe3b15f9b90e9cc76d311c256e0ed98
parent439f5564e4a92f91a43a7f36d734f6bd96effd63 (diff)
downloadstepper-fff06404696bb8790901cdefe016cd8d0fe856cb.tar.gz
stepper-fff06404696bb8790901cdefe016cd8d0fe856cb.zip
Add pattern chain buttons behaviour (toggle/clear/random)
-rw-r--r--Makefile2
-rw-r--r--src/drawing.c75
-rw-r--r--src/globals.c11
-rw-r--r--src/main.c20
-rw-r--r--src/sequencer.c91
5 files changed, 157 insertions, 42 deletions
diff --git a/Makefile b/Makefile
index 694ba3a..0bc4bb5 100644
--- a/Makefile
+++ b/Makefile
@@ -27,7 +27,7 @@ INC_FLAGS := $(addprefix -I,$(INC_DIRS))
27INC_FLAGS += -I$(LIBGBA_SRC) 27INC_FLAGS += -I$(LIBGBA_SRC)
28 28
29# Output library names and executables. 29# Output library names and executables.
30TARGET := STEPPER-v1.7-dev 30TARGET := STEPPER-v1.7-rc1
31ELF := $(BUILD_DIR)/$(TARGET).elf 31ELF := $(BUILD_DIR)/$(TARGET).elf
32BIN := $(BUILD_DIR)/$(TARGET).gba 32BIN := $(BUILD_DIR)/$(TARGET).gba
33 33
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) {
594 draw_rect(x0, y0, x1, y1, COL_FG); 594 draw_rect(x0, y0, x1, y1, COL_FG);
595 for (size_t i = 0; i < 12 * 6; i++) { 595 for (size_t i = 0; i < 12 * 6; i++) {
596 u8 clr = COL_FG; 596 u8 clr = COL_FG;
597 s8 pos = i % 12;
598 switch (pos) {
599 case 0:
600 case 2:
601 case 4:
602 case 5:
603 case 7:
604 case 9:
605 case 11: break;
606 default: { clr = COL_BG; } break;
607 }
597 if (input_handler == handle_right_col_selection && 608 if (input_handler == handle_right_col_selection &&
598 right_col_selection_loc == R_COL_SCALE) { 609 right_col_selection_loc == R_COL_SCALE) {
599 s8 pos = i % 12;
600 if (pos == current_scale_root) { 610 if (pos == current_scale_root) {
601 clr = COL_ACC_1; 611 clr = COL_ACC_1;
602 } else { 612 } else {
@@ -1277,13 +1287,38 @@ clear_cursors(void) {
1277 1287
1278void 1288void
1279draw_pattern_chain_cursor(void) { 1289draw_pattern_chain_cursor(void) {
1280 size_t offset_x = (PAT_TRIG_H + 7) * (param_selection_loc % 8); 1290 switch (param_selection_loc) {
1281 size_t offset_y = param_selection_loc < 8 ? 0 : 0 + PAT_TRIG_OFFSET_Y; 1291 case CHAIN_BTN_ENABLE: {
1282 size_t x0 = PAT_TRIG_START_X + offset_x; 1292 size_t x0 = PAT_TRIG_START_X + 24;
1283 size_t x1 = PAT_TRIG_START_X + offset_x + PAT_TRIG_W; 1293 size_t x1 = x0 + 30;
1284 size_t y = PAT_TRIG_START_Y + offset_y + PAT_TRIG_H + 2; 1294 size_t y = PAT_TRIG_START_Y - 16 + 1 + 10;
1285 draw_line(x0, y, x1, y, COL_ACC_0); 1295 draw_line(x0, y, x1, y, COL_ACC_0);
1286 draw_line(x0, y + 1, x1, y + 1, COL_ACC_0); 1296 draw_line(x0, y + 1, x1, y + 1, COL_ACC_0);
1297 } break;
1298 case CHAIN_BTN_CLEAR: {
1299 size_t x0 = PAT_TRIG_START_X + 24 + 42;
1300 size_t x1 = x0 + 30;
1301 size_t y = PAT_TRIG_START_Y - 16 + 1 + 10;
1302 draw_line(x0, y, x1, y, COL_ACC_0);
1303 draw_line(x0, y + 1, x1, y + 1, COL_ACC_0);
1304 } break;
1305 case CHAIN_BTN_RANDOM: {
1306 size_t x0 = PAT_TRIG_START_X + 24 + 42 * 2;
1307 size_t x1 = x0 + 30;
1308 size_t y = PAT_TRIG_START_Y - 16 + 1 + 10;
1309 draw_line(x0, y, x1, y, COL_ACC_0);
1310 draw_line(x0, y + 1, x1, y + 1, COL_ACC_0);
1311 } break;
1312 default: {
1313 size_t offset_x = (PAT_TRIG_H + 7) * (param_selection_loc % 8);
1314 size_t offset_y = param_selection_loc < 8 ? 0 : 0 + PAT_TRIG_OFFSET_Y;
1315 size_t x0 = PAT_TRIG_START_X + offset_x;
1316 size_t x1 = PAT_TRIG_START_X + offset_x + PAT_TRIG_W;
1317 size_t y = PAT_TRIG_START_Y + offset_y + PAT_TRIG_H + 2;
1318 draw_line(x0, y, x1, y, COL_ACC_0);
1319 draw_line(x0, y + 1, x1, y + 1, COL_ACC_0);
1320 } break;
1321 }
1287} 1322}
1288 1323
1289void 1324void
@@ -1756,7 +1791,7 @@ draw_notif_bar() {
1756 return; 1791 return;
1757 } 1792 }
1758 1793
1759 if (chain.len != 0) { 1794 if (chain.len != 0 && chain.enabled) {
1760 u8 x = x0 + 2; 1795 u8 x = x0 + 2;
1761 u8 y = y0 + 1; 1796 u8 y = y0 + 1;
1762 txt_drawf_small("CHAIN: ", x, y, color); 1797 txt_drawf_small("CHAIN: ", x, y, color);
@@ -1789,6 +1824,7 @@ draw_notif_bar() {
1789void 1824void
1790draw_pattern_chain() { 1825draw_pattern_chain() {
1791 clear_parameters(); 1826 clear_parameters();
1827 // Pattern chain triggers.
1792 for (size_t i = 0; i < 16; i++) { 1828 for (size_t i = 0; i < 16; i++) {
1793 u8 color = COL_FG; 1829 u8 color = COL_FG;
1794 size_t offset_x = PAT_TRIG_OFFSET_X * (i % 8); 1830 size_t offset_x = PAT_TRIG_OFFSET_X * (i % 8);
@@ -1797,12 +1833,15 @@ draw_pattern_chain() {
1797 size_t x1 = PAT_TRIG_START_X + offset_x + PAT_TRIG_W; 1833 size_t x1 = PAT_TRIG_START_X + offset_x + PAT_TRIG_W;
1798 size_t y0 = PAT_TRIG_START_Y + offset_y; 1834 size_t y0 = PAT_TRIG_START_Y + offset_y;
1799 size_t y1 = PAT_TRIG_START_Y + offset_y + PAT_TRIG_H; 1835 size_t y1 = PAT_TRIG_START_Y + offset_y + PAT_TRIG_H;
1836 if (!chain.enabled) {
1837 color = COL_OFF;
1838 }
1800 draw_rect(x0, y0, x1, y1, color); 1839 draw_rect(x0, y0, x1, y1, color);
1801 if (chain.active[i]) { 1840 if (chain.active[i]) {
1802 txt_drawc('A' + chain.chain[i], x0 + 4, y0 + 3, color); 1841 txt_drawc('A' + chain.chain[i], x0 + 4, y0 + 3, color);
1803 } 1842 }
1804 color = COL_OFF; 1843 color = COL_OFF;
1805 if (chain.current == i && chain.len != 0) { 1844 if (chain.current == i && chain.len != 0 && chain.enabled) {
1806 color = COL_ACC_2; 1845 color = COL_ACC_2;
1807 if (chain.active[i]) { 1846 if (chain.active[i]) {
1808 txt_drawc('A' + chain.chain[i], x0 + 4, y0 + 3, color); 1847 txt_drawc('A' + chain.chain[i], x0 + 4, y0 + 3, color);
@@ -1811,4 +1850,20 @@ draw_pattern_chain() {
1811 } 1850 }
1812 draw_line(x0 + 5, y1 - 2, x1 - 5, y1 - 2, color); 1851 draw_line(x0 + 5, y1 - 2, x1 - 5, y1 - 2, color);
1813 } 1852 }
1853
1854 // Pattern chain buttons.
1855 size_t x0 = PAT_TRIG_START_X + 24;
1856 size_t x1 = x0 + 30;
1857 size_t y0 = PAT_TRIG_START_Y - 16 + 1;
1858 size_t y1 = y0 + 8;
1859 txt_drawf_small("toggle", x0 + 2, y0, COL_FG);
1860 draw_rect(x0, y0, x1, y1, COL_FG);
1861 x0 += 42;
1862 x1 += 42;
1863 txt_drawf_small("clear", x0 + 4, y0, COL_FG);
1864 draw_rect(x0, y0, x1, y1, COL_FG);
1865 x0 += 42;
1866 x1 += 42;
1867 txt_drawf_small("random", x0 + 2, y0, COL_FG);
1868 draw_rect(x0, y0, x1, y1, COL_FG);
1814} 1869}
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;
57#define NOTIF_START_Y 12 57#define NOTIF_START_Y 12
58 58
59#define PARAMS_W 166 59#define PARAMS_W 166
60#define PARAMS_H 52 60#define PARAMS_H 56
61#define PARAMS_START_X 29 61#define PARAMS_START_X 29
62#define PARAMS_START_Y 20 62#define PARAMS_START_Y 20
63#define PARAMS_BOX_W 30 63#define PARAMS_BOX_W 30
@@ -99,7 +99,7 @@ bool clear_screen = true;
99#define PAT_TRIG_W 14 99#define PAT_TRIG_W 14
100#define PAT_TRIG_H 14 100#define PAT_TRIG_H 14
101#define PAT_TRIG_START_X 32 101#define PAT_TRIG_START_X 32
102#define PAT_TRIG_START_Y 30 102#define PAT_TRIG_START_Y 37
103#define PAT_TRIG_OFFSET_X (PAT_TRIG_W + 7) 103#define PAT_TRIG_OFFSET_X (PAT_TRIG_W + 7)
104#define PAT_TRIG_OFFSET_Y (PAT_TRIG_H + 8) 104#define PAT_TRIG_OFFSET_Y (PAT_TRIG_H + 8)
105 105
@@ -167,8 +167,15 @@ typedef struct Chain {
167 u8 len; 167 u8 len;
168 u8 current; 168 u8 current;
169 u8 playing; 169 u8 playing;
170 u8 enabled;
170} Chain; 171} Chain;
171 172
173typedef enum ChainButtons {
174 CHAIN_BTN_ENABLE = 16,
175 CHAIN_BTN_CLEAR = 17,
176 CHAIN_BTN_RANDOM = 18,
177} ChainButtons;
178
172static Chain chain = {0}; 179static Chain chain = {0};
173 180
174typedef enum Prob { 181typedef 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.
37// - Channel params should show if there are some already on all triggers and 37// - Channel params should show if there are some already on all triggers and
38// modify only the selected parameter, not all of them. 38// modify only the selected parameter, not all of them.
39// - Should scale mode be toggleable? 39// - Should scale mode be toggleable?
40// - Improve SRAM saving to make room for longer patterns and/or more banks.
41// - Higher resolution clock to allow for microtiming and more accurate tempo.
40// 42//
41// WIP (1.7) 43// WIP (1.7)
42// + Improve "grey" cursor with dithering instead. 44// + Improve "grey" cursor with dithering instead.
@@ -55,18 +57,18 @@ WITH REGARD TO THIS SOFTWARE.
55// + Make sure bank switching is queued like patterns. 57// + Make sure bank switching is queued like patterns.
56// + If we are on sync in, BPM should display SYNC 58// + If we are on sync in, BPM should display SYNC
57// + Visual feedback for scale/root note adjustment. 59// + Visual feedback for scale/root note adjustment.
58// - Shortcut to quickly exit/enter chain mode. 60// + Settings page overhaul.
61// + Add global mutes option.
62// + Add global bpm option.
63// + Add auto-save option.
64// + Remove thin cursor option and make the fat one default, it's just better.
65// + Restore black keys when not on scale mode
66// + Enable pattern chain toggling.
67// + Enable pattern chain clearing.
68// + Enable pattern chain randomizing.
59// - Add CREDITS to the documentation for now, should probably be a menu item 69// - Add CREDITS to the documentation for now, should probably be a menu item
60// later. 70// later.
61// - Settings page overhaul.
62// - Remove thin cursor option and make the fat one default, it's just better.
63//
64// - Improve SRAM saving to make room for longer patterns and/or more banks.
65// - Higher resolution clock to allow for microtiming and more accurate tempo.
66// - Add settings for "performance mode" in which banks are not saved by
67// default while changing patterns.
68// - Make sure sync works with the same cable for in/out. 71// - Make sure sync works with the same cable for in/out.
69// - Study more improvements for a "performance mode".
70 72
71#include "gba/gba.h" 73#include "gba/gba.h"
72 74
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) {
138 } else if (current_bank != next_bank && step_counter == 15) { 138 } else if (current_bank != next_bank && step_counter == 15) {
139 select_bank(next_bank); 139 select_bank(next_bank);
140 update_bpm = true; 140 update_bpm = true;
141 } else if (chain.len != 0 && step_counter == 15) { 141 } else if (chain.len != 0 && step_counter == 15 && chain.enabled) {
142 redraw_pattern_buttons = true; 142 redraw_pattern_buttons = true;
143 update_bpm = true; 143 update_bpm = true;
144 if (!chain.playing) { 144 if (!chain.playing) {
@@ -762,6 +762,8 @@ handle_pattern_chain(void) {
762 } else if (key_tap(KEY_LEFT)) { 762 } else if (key_tap(KEY_LEFT)) {
763 if (param_selection_loc == 8) { 763 if (param_selection_loc == 8) {
764 param_selection_loc = 15; 764 param_selection_loc = 15;
765 } else if (param_selection_loc == 16) {
766 param_selection_loc = 18;
765 } else if (param_selection_loc > 0) { 767 } else if (param_selection_loc > 0) {
766 param_selection_loc--; 768 param_selection_loc--;
767 } else if (param_selection_loc == 0) { 769 } else if (param_selection_loc == 0) {
@@ -770,48 +772,97 @@ handle_pattern_chain(void) {
770 } else if (key_tap(KEY_RIGHT)) { 772 } else if (key_tap(KEY_RIGHT)) {
771 if (param_selection_loc < 15 && param_selection_loc != 7) { 773 if (param_selection_loc < 15 && param_selection_loc != 7) {
772 param_selection_loc++; 774 param_selection_loc++;
775 } else if (param_selection_loc < 18 && param_selection_loc >= 16) {
776 param_selection_loc++;
777 } else if (param_selection_loc == 18) {
778 param_selection_loc = 16;
773 } else if (param_selection_loc == 7) { 779 } else if (param_selection_loc == 7) {
774 param_selection_loc = 0; 780 param_selection_loc = 0;
775 } else if (param_selection_loc == 15) { 781 } else if (param_selection_loc == 15) {
776 param_selection_loc = 8; 782 param_selection_loc = 8;
777 } 783 }
778 } else if (key_tap(KEY_UP)) { 784 } else if (key_tap(KEY_UP)) {
779 if (param_selection_loc <= 7) { 785 if (param_selection_loc >= 1 && param_selection_loc <= 2) {
780 param_selection_loc += 8; 786 param_selection_loc = 16;
781 } else { 787 } else if (param_selection_loc >= 3 && param_selection_loc <= 4) {
788 param_selection_loc = 17;
789 } else if (param_selection_loc >= 5 && param_selection_loc <= 6) {
790 param_selection_loc = 18;
791 } else if (param_selection_loc >= 8 && param_selection_loc <= 15){
782 param_selection_loc -= 8; 792 param_selection_loc -= 8;
783 } 793 }
784 } else if (key_tap(KEY_DOWN)) { 794 } else if (key_tap(KEY_DOWN)) {
785 if (param_selection_loc <= 7) { 795 if (param_selection_loc <= 7) {
786 param_selection_loc += 8; 796 param_selection_loc += 8;
787 } else { 797 } else if (param_selection_loc == 16){
788 param_selection_loc -= 8; 798 param_selection_loc = 1;
799 } else if (param_selection_loc == 17){
800 param_selection_loc = 3;
801 } else if (param_selection_loc == 18){
802 param_selection_loc = 5;
789 } 803 }
790 } else if (key_tap(KEY_B)) { 804 } else if (key_tap(KEY_B)) {
791 if (chain.active[param_selection_loc]) { 805 switch (param_selection_loc) {
792 // Can't toggle current chain. 806 case CHAIN_BTN_ENABLE: {
793 if (!play_status 807 chain.enabled ^= 1;
794 || param_selection_loc != chain.current 808 chain.current = 15;
795 || chain.len == 1) { 809 chain.current = find_next_pattern();
796 chain.active[param_selection_loc] = 0; 810 chain.playing = false;
797 chain.len--; 811 } break;
798 } 812 case CHAIN_BTN_CLEAR: {
799 } else { 813 chain.len = 0;
800 if (chain.len == 0) { 814 chain.playing = false;
801 chain.current = param_selection_loc; 815 for (size_t i = 0; i < MAX_CHAIN; i++) {
802 } 816 chain.active[i] = false;
803 chain.active[param_selection_loc] = 1; 817 chain.chain[i] = 0;
804 chain.len++; 818 }
819 chain.current = 15;
820 chain.current = find_next_pattern();
821 } break;
822 case CHAIN_BTN_RANDOM: {
823 u8 cur = chain.current % 16;
824 for (size_t i = 0; i < MAX_CHAIN; i++) {
825 if (i == cur && chain.playing) {
826 continue;
827 }
828 if (rng16() < 32765) {
829 chain.active[i] = true;
830 } else {
831 chain.active[i] = false;
832 }
833 // NOTE: Should we also randomize the patterns or isn't it
834 // necessary?
835 }
836 } break;
837 default: {
838 if (chain.active[param_selection_loc]) {
839 // Can't toggle current chain.
840 if (!play_status
841 || param_selection_loc != chain.current
842 || chain.len == 1) {
843 chain.active[param_selection_loc] = 0;
844 chain.len--;
845 }
846 } else {
847 if (chain.len == 0) {
848 chain.current = param_selection_loc;
849 }
850 chain.active[param_selection_loc] = 1;
851 chain.len++;
852 }
853 } break;
805 } 854 }
806 } else if (key_tap(KEY_L)) { 855 } else if (key_tap(KEY_L)) {
807 if (chain.active[param_selection_loc] 856 if (chain.active[param_selection_loc]
808 && chain.chain[param_selection_loc] > 0 857 && chain.chain[param_selection_loc] > 0
858 && param_selection_loc <= 15
809 && (!play_status || param_selection_loc != chain.current)) { 859 && (!play_status || param_selection_loc != chain.current)) {
810 chain.chain[param_selection_loc]--; 860 chain.chain[param_selection_loc]--;
811 } 861 }
812 } else if (key_tap(KEY_R)) { 862 } else if (key_tap(KEY_R)) {
813 if (chain.active[param_selection_loc] 863 if (chain.active[param_selection_loc]
814 && chain.chain[param_selection_loc] < 7 864 && chain.chain[param_selection_loc] < 7
865 && param_selection_loc <= 15
815 && (!play_status || param_selection_loc != chain.current)) { 866 && (!play_status || param_selection_loc != chain.current)) {
816 chain.chain[param_selection_loc]++; 867 chain.chain[param_selection_loc]++;
817 } 868 }