summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2021-06-08 13:36:20 +0200
committerBad Diode <bd@badd10de.dev>2021-06-08 13:36:20 +0200
commit436b4a1d28f5939e1c0f8792317a639b091b0f29 (patch)
treeadaa35f0de608ee6890e4431805c0850f199d8ce
parent5b160c23330663e38d1c7fa387d64e83a372638d (diff)
downloadgba-sequencer-436b4a1d28f5939e1c0f8792317a639b091b0f29.tar.gz
gba-sequencer-436b4a1d28f5939e1c0f8792317a639b091b0f29.zip
Start FSM based input handling
-rw-r--r--src/sequencer.c778
1 files changed, 473 insertions, 305 deletions
diff --git a/src/sequencer.c b/src/sequencer.c
index 43e6ffc..46e57ef 100644
--- a/src/sequencer.c
+++ b/src/sequencer.c
@@ -1,4 +1,98 @@
1#include "rng.c" 1#include "rng.c"
2#include "text.h"
3
4//
5// Assets.
6//
7
8#define ASSETS_DATA ((u32*)(MEM_VRAM + KB(32)))
9
10static const u32 note_names[] = {
11 0x000000e0, 0x202020e0, 0x0000000e, 0x080e020e,
12 0x00000098, 0xa8a8a898, 0x00000038, 0x203b0a39,
13 0x00000060, 0xa0a0a060, 0x0000000e, 0x080e020e,
14 0x000000b8, 0x889888b8, 0x00000038, 0x203b0a39,
15 0x000000e0, 0x206020e0, 0x0000000e, 0x080e020e,
16 0x000000e0, 0x20602020, 0x0000000e, 0x080e020e,
17 0x000000b8, 0x8888a8b8, 0x00000038, 0x203b0a39,
18 0x000000e0, 0x2020a0e0, 0x0000000e, 0x080e020e,
19 0x000000b8, 0xa8a8b8a8, 0x00000038, 0x203b0a39,
20 0x000000e0, 0xa0a0e0a0, 0x0000000e, 0x080e020e,
21 0x000000b8, 0xa898a8b8, 0x00000038, 0x203b0a39,
22 0x000000e0, 0xa060a0e0, 0x0000000e, 0x080e020e,
23 0x000000e0, 0x202020e0, 0x0000000e, 0x080c080e,
24 0x00000098, 0xa8a8a898, 0x00000038, 0x20332239,
25 0x00000060, 0xa0a0a060, 0x0000000e, 0x080c080e,
26 0x000000b8, 0x889888b8, 0x00000038, 0x20332239,
27 0x000000e0, 0x206020e0, 0x0000000e, 0x080c080e,
28 0x000000e0, 0x20602020, 0x0000000e, 0x080c080e,
29 0x000000b8, 0x8888a8b8, 0x00000038, 0x20332239,
30 0x000000e0, 0x2020a0e0, 0x0000000e, 0x080c080e,
31 0x000000b8, 0xa8a8b8a8, 0x00000038, 0x20332239,
32 0x000000e0, 0xa0a0e0a0, 0x0000000e, 0x080c080e,
33 0x000000b8, 0xa898a8b8, 0x00000038, 0x20332239,
34 0x000000e0, 0xa060a0e0, 0x0000000e, 0x080c080e,
35 0x000000e0, 0x202020e0, 0x0000000a, 0x0a0e0808,
36 0x00000098, 0xa8a8a898, 0x00000028, 0x283b2221,
37 0x00000060, 0xa0a0a060, 0x0000000a, 0x0a0e0808,
38 0x000000b8, 0x889888b8, 0x00000028, 0x283b2221,
39 0x000000e0, 0x206020e0, 0x0000000a, 0x0a0e0808,
40 0x000000e0, 0x20602020, 0x0000000a, 0x0a0e0808,
41 0x000000b8, 0x8888a8b8, 0x00000028, 0x283b2221,
42 0x000000e0, 0x2020a0e0, 0x0000000a, 0x0a0e0808,
43 0x000000b8, 0xa8a8b8a8, 0x00000028, 0x283b2221,
44 0x000000e0, 0xa0a0e0a0, 0x0000000a, 0x0a0e0808,
45 0x000000b8, 0xa898a8b8, 0x00000028, 0x283b2221,
46 0x000000e0, 0xa060a0e0, 0x0000000a, 0x0a0e0808,
47 0x000000e0, 0x202020e0, 0x0000000e, 0x020e080e,
48 0x00000098, 0xa8a8a898, 0x00000038, 0x083b2239,
49 0x00000060, 0xa0a0a060, 0x0000000e, 0x020e080e,
50 0x000000b8, 0x889888b8, 0x00000038, 0x083b2239,
51 0x000000e0, 0x206020e0, 0x0000000e, 0x020e080e,
52 0x000000e0, 0x20602020, 0x0000000e, 0x020e080e,
53 0x000000b8, 0x8888a8b8, 0x00000038, 0x083b2239,
54 0x000000e0, 0x2020a0e0, 0x0000000e, 0x020e080e,
55 0x000000b8, 0xa8a8b8a8, 0x00000038, 0x083b2239,
56 0x000000e0, 0xa0a0e0a0, 0x0000000e, 0x020e080e,
57 0x000000b8, 0xa898a8b8, 0x00000038, 0x083b2239,
58 0x000000e0, 0xa060a0e0, 0x0000000e, 0x020e080e,
59 0x000000e0, 0x202020e0, 0x0000000e, 0x020e0a0e,
60 0x00000098, 0xa8a8a898, 0x00000038, 0x083b2a39,
61 0x00000060, 0xa0a0a060, 0x0000000e, 0x020e0a0e,
62 0x000000b8, 0x889888b8, 0x00000038, 0x083b2a39,
63 0x000000e0, 0x206020e0, 0x0000000e, 0x020e0a0e,
64 0x000000e0, 0x20602020, 0x0000000e, 0x020e0a0e,
65 0x000000b8, 0x8888a8b8, 0x00000038, 0x083b2a39,
66 0x000000e0, 0x2020a0e0, 0x0000000e, 0x020e0a0e,
67 0x000000b8, 0xa8a8b8a8, 0x00000038, 0x083b2a39,
68 0x000000e0, 0xa0a0e0a0, 0x0000000e, 0x020e0a0e,
69 0x000000b8, 0xa898a8b8, 0x00000038, 0x083b2a39,
70 0x000000e0, 0xa060a0e0, 0x0000000e, 0x020e0a0e,
71 0x000000e0, 0x202020e0, 0x0000000e, 0x08040202,
72 0x00000098, 0xa8a8a898, 0x00000038, 0x20130a09,
73 0x00000060, 0xa0a0a060, 0x0000000e, 0x08040202,
74 0x000000b8, 0x889888b8, 0x00000038, 0x20130a09,
75 0x000000e0, 0x206020e0, 0x0000000e, 0x08040202,
76 0x000000e0, 0x20602020, 0x0000000e, 0x08040202,
77 0x000000b8, 0x8888a8b8, 0x00000038, 0x20130a09,
78 0x000000e0, 0x2020a0e0, 0x0000000e, 0x08040202,
79 0x000000b8, 0xa8a8b8a8, 0x00000038, 0x20130a09,
80 0x000000e0, 0xa0a0e0a0, 0x0000000e, 0x08040202,
81 0x000000b8, 0xa898a8b8, 0x00000038, 0x20130a09,
82 0x000000e0, 0xa060a0e0, 0x0000000e, 0x08040202,
83 0x000000e0, 0x202020e0, 0x0000000e, 0x0a0e0a0e,
84};
85
86static const u32 channel_buttons[] = {
87 0xff017111, 0x117101ff, 0xff008585, 0x879500ff,
88 0x0f080808, 0x0808080f, 0xff01b989, 0x89b901ff,
89 0xff004242, 0x434a00ff, 0x0f080909, 0x0909080f,
90 0xff015d45, 0xc55d01ff, 0xff00a1a1, 0xa1a500ff,
91 0x0f080a0a, 0x0a0a080f, 0xff015d45, 0xc55d01ff,
92 0xff00a1a1, 0xa12500ff, 0x0f080a0a, 0x0a0b080f,
93 0xff01c141, 0xc14101ff, 0xff00151c, 0x141400ff,
94 0x0f080808, 0x0808080f,
95};
2 96
3// 97//
4// Globals. 98// Globals.
@@ -12,7 +106,7 @@ static int bpm = 115;
12static int step_counter = 0; 106static int step_counter = 0;
13int trig_selection_loc = 0; 107int trig_selection_loc = 0;
14int param_selection_loc = 64; 108int param_selection_loc = 64;
15int channel_selection_loc = 2; 109int channel_selection_loc = 0;
16SeqSelect current_selection = SEQ_SELECT_TRIGGER; 110SeqSelect current_selection = SEQ_SELECT_TRIGGER;
17 111
18// 112//
@@ -61,19 +155,19 @@ typedef struct SeqTrigger {
61static SeqTrigger sequences[3][16] = { 155static SeqTrigger sequences[3][16] = {
62 // Synth 1. 156 // Synth 1.
63 { 157 {
64 {false, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, 158 {true, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}},
65 {false, NOTE_D_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, 159 {true, NOTE_D_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}},
66 {false, NOTE_E_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, 160 {false, NOTE_E_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}},
67 {false, NOTE_F_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, 161 {false, NOTE_F_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}},
68 {false, NOTE_G_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, 162 {true, NOTE_G_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}},
69 {false, NOTE_A_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, 163 {true, NOTE_A_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}},
70 {false, NOTE_B_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, 164 {false, NOTE_B_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}},
71 {false, NOTE_C_5, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, 165 {false, NOTE_C_5, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}},
166 {true, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}},
167 {true, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}},
72 {false, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, 168 {false, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}},
73 {false, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, 169 {false, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}},
74 {false, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, 170 {true, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}},
75 {false, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}},
76 {false, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}},
77 {false, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, 171 {false, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}},
78 {false, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, 172 {false, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}},
79 {false, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, 173 {false, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}},
@@ -99,22 +193,22 @@ static SeqTrigger sequences[3][16] = {
99 }, 193 },
100 // Synth 3. 194 // Synth 3.
101 { 195 {
102 {true, NOTE_C_5, 8, 4, 0, 2, 0, 0, 0, 3, 0, {0xffffffff, 0x00000000, 0xffffffff, 0x00000000}, {0}}, 196 {true, NOTE_C_5, 8, 4, 0, 2, 0, 0, 0, 3, 0, {0}, {0}},
103 {true, NOTE_D_5, 8, 4, 0, 2, 0, 0, 0, 3, 0, {0xffffffff, 0x00000000, 0xffffffff, 0x00000000}, {0}}, 197 {true, NOTE_D_5, 8, 4, 0, 2, 0, 0, 0, 3, 0, {0}, {0}},
104 {true, NOTE_E_5, 8, 4, 0, 2, 0, 0, 0, 3, 0, {0xffffffff, 0x00000000, 0xffffffff, 0x00000000}, {0}}, 198 {true, NOTE_E_5, 8, 4, 0, 2, 0, 0, 0, 3, 0, {0}, {0}},
105 {true, NOTE_F_5, 8, 4, 0, 2, 0, 0, 0, 3, 0, {0xffffffff, 0x00000000, 0xffffffff, 0x00000000}, {0}}, 199 {true, NOTE_F_5, 8, 4, 0, 2, 0, 0, 0, 3, 0, {0}, {0}},
106 {true, NOTE_G_5, 8, 4, 0, 2, 0, 0, 0, 3, 0, {0xffffffff, 0x00000000, 0xffffffff, 0x00000000}, {0}}, 200 {true, NOTE_G_5, 8, 4, 0, 2, 0, 0, 0, 3, 0, {0}, {0}},
107 {true, NOTE_A_5, 8, 4, 0, 2, 0, 0, 0, 3, 0, {0xffffffff, 0x00000000, 0xffffffff, 0x00000000}, {0}}, 201 {true, NOTE_A_5, 8, 4, 0, 2, 0, 0, 0, 3, 0, {0}, {0}},
108 {true, NOTE_B_5, 8, 4, 0, 2, 0, 0, 0, 3, 0, {0xffffffff, 0x00000000, 0xffffffff, 0x00000000}, {0}}, 202 {true, NOTE_B_5, 8, 4, 0, 2, 0, 0, 0, 3, 0, {0}, {0}},
109 {true, NOTE_C_6, 8, 4, 0, 2, 0, 0, 0, 3, 0, {0xffffffff, 0x00000000, 0xffffffff, 0x00000000}, {0}}, 203 {true, NOTE_C_6, 8, 4, 0, 2, 0, 0, 0, 3, 0, {0}, {0}},
110 {true, NOTE_C_5, 8, 4, 0, 2, 0, 0, 0, 3, 0, {0xffffffff, 0x00000000, 0xffffffff, 0x00000000}, {0}}, 204 {true, NOTE_C_5, 8, 4, 0, 2, 0, 0, 0, 3, 0, {0}, {0}},
111 {true, NOTE_D_5, 8, 4, 0, 2, 0, 0, 0, 3, 0, {0xffffffff, 0x00000000, 0xffffffff, 0x00000000}, {0}}, 205 {true, NOTE_D_5, 8, 4, 0, 2, 0, 0, 0, 3, 0, {0}, {0}},
112 {true, NOTE_E_5, 8, 4, 0, 2, 0, 0, 0, 3, 0, {0xffffffff, 0x00000000, 0xffffffff, 0x00000000}, {0}}, 206 {true, NOTE_E_5, 8, 4, 0, 2, 0, 0, 0, 3, 0, {0}, {0}},
113 {true, NOTE_F_5, 8, 4, 0, 2, 0, 0, 0, 3, 0, {0xffffffff, 0x00000000, 0xffffffff, 0x00000000}, {0}}, 207 {true, NOTE_F_5, 8, 4, 0, 2, 0, 0, 0, 3, 0, {0}, {0}},
114 {true, NOTE_G_5, 8, 4, 0, 2, 0, 0, 0, 3, 0, {0xffffffff, 0x00000000, 0xffffffff, 0x00000000}, {0}}, 208 {true, NOTE_G_5, 8, 4, 0, 2, 0, 0, 0, 3, 0, {0}, {0}},
115 {true, NOTE_A_5, 8, 4, 0, 2, 0, 0, 0, 3, 0, {0xffffffff, 0x00000000, 0xffffffff, 0x00000000}, {0}}, 209 {true, NOTE_A_5, 8, 4, 0, 2, 0, 0, 0, 3, 0, {0}, {0}},
116 {true, NOTE_B_5, 8, 4, 0, 2, 0, 0, 0, 3, 0, {0xffffffff, 0x00000000, 0xffffffff, 0x00000000}, {0}}, 210 {true, NOTE_B_5, 8, 4, 0, 2, 0, 0, 0, 3, 0, {0}, {0}},
117 {true, NOTE_C_6, 8, 4, 0, 2, 0, 0, 0, 3, 0, {0xffffffff, 0x00000000, 0xffffffff, 0x00000000}, {0}}, 211 {true, NOTE_C_6, 8, 4, 0, 2, 0, 0, 0, 3, 0, {0}, {0}},
118 }, 212 },
119}; 213};
120 214
@@ -127,20 +221,53 @@ static SeqTrigger sequences[3][16] = {
127#define TRIG_OFFSET_Y (TRIG_H + 7) 221#define TRIG_OFFSET_Y (TRIG_H + 7)
128 222
129void 223void
130draw_triggers(void) { 224clear_trigger(size_t i) {
131 for (size_t i = 0; i < 8; i++) { 225 size_t offset_x = TRIG_OFFSET_X * (i % 8);
132 size_t x0 = TRIG_START_X + TRIG_OFFSET_X * i; 226 size_t offset_y = i < 8 ? 0 : TRIG_OFFSET_Y;
133 size_t x1 = TRIG_START_X + TRIG_W + TRIG_OFFSET_X * i; 227 size_t x0 = TRIG_START_X + offset_x + 1;
134 size_t y0 = TRIG_START_Y; 228 size_t x1 = TRIG_START_X + offset_x + TRIG_W - 1;
135 size_t y1 = TRIG_START_Y + TRIG_H; 229 size_t y0 = TRIG_START_Y + offset_y + 1;
136 draw_rect(x0, y0, x1, y1, 1); 230 size_t y1 = TRIG_START_Y + offset_y + TRIG_H - 1;
231 draw_filled_rect(x0, y0, x1, y1, 0);
232}
233
234void
235draw_trigger(size_t chan, size_t i) {
236 if (sequences[chan][i].trigger) {
237 size_t offset_x = TRIG_OFFSET_X * (i % 8);
238 size_t offset_y = i < 8 ? 0 : TRIG_OFFSET_Y;
239 size_t x = TRIG_START_X + offset_x;
240 size_t y = TRIG_START_Y + offset_y;
241 Tile *tiles = ASSETS_DATA;
242 tiles += 2 * sequences[chan][i].note;
243 draw_tile(x, y, tiles, true);
244 draw_tile(x + 8, y, tiles + 1, true);
245 } else {
246 clear_trigger(i);
137 } 247 }
138 for (size_t i = 0; i < 8; i++) { 248}
139 size_t x0 = TRIG_START_X + TRIG_OFFSET_X * i; 249
140 size_t x1 = TRIG_START_X + TRIG_W + TRIG_OFFSET_X * i; 250void
141 size_t y0 = TRIG_START_Y + TRIG_OFFSET_Y; 251draw_trig_cursor(size_t i, u8 clr) {
142 size_t y1 = TRIG_START_Y + TRIG_H + TRIG_OFFSET_Y; 252 size_t offset_x = TRIG_OFFSET_X * (i % 8);
253 size_t offset_y = i < 8 ? 1 : 1 + TRIG_OFFSET_Y;
254 size_t x0 = TRIG_START_X + offset_x;
255 size_t x1 = TRIG_START_X + TRIG_W + offset_x;
256 size_t y = TRIG_START_Y + TRIG_H + offset_y;
257 draw_line(x0, y, x1, y, clr);
258}
259
260void
261draw_triggers(void) {
262 for (size_t i = 0; i < 16; i++) {
263 size_t offset_x = TRIG_OFFSET_X * (i % 8);
264 size_t offset_y = i < 8 ? 0 : 0 + TRIG_OFFSET_Y;
265 size_t x0 = TRIG_START_X + offset_x;
266 size_t x1 = TRIG_START_X + offset_x + TRIG_W;
267 size_t y0 = TRIG_START_Y + offset_y;
268 size_t y1 = TRIG_START_Y + offset_y + TRIG_H;
143 draw_rect(x0, y0, x1, y1, 1); 269 draw_rect(x0, y0, x1, y1, 1);
270 draw_trigger(channel_selection_loc, i);
144 } 271 }
145} 272}
146 273
@@ -152,16 +279,6 @@ void
152draw_channels(void) { 279draw_channels(void) {
153 // Contains 5 channel buttons: Ch. 1-4 + FM. We are only drawing the DMG 280 // Contains 5 channel buttons: Ch. 1-4 + FM. We are only drawing the DMG
154 // channels for now, since FM may take some time to develop. 281 // channels for now, since FM may take some time to develop.
155 u32 channel_buttons[] = {
156 0xff017111, 0x117101ff, 0xff008585, 0x879500ff,
157 0x0f080808, 0x0808080f, 0xff01b989, 0x89b901ff,
158 0xff004242, 0x434a00ff, 0x0f080909, 0x0909080f,
159 0xff015d45, 0xc55d01ff, 0xff00a1a1, 0xa1a500ff,
160 0x0f080a0a, 0x0a0a080f, 0xff015d45, 0xc55d01ff,
161 0xff00a1a1, 0xa12500ff, 0x0f080a0a, 0x0a0b080f,
162 0xff01c141, 0xc14101ff, 0xff00151c, 0x141400ff,
163 0x0f080808, 0x0808080f,
164 };
165 Tile channel_tiles[3 * 4] = {0}; 282 Tile channel_tiles[3 * 4] = {0};
166 unpack_tiles(channel_buttons, channel_tiles, 3 * 4); 283 unpack_tiles(channel_buttons, channel_tiles, 3 * 4);
167 size_t k = 0; 284 size_t k = 0;
@@ -213,9 +330,9 @@ irq_timer_0(void) {
213 // TODO: Should we compare if previous and current wave are the 330 // TODO: Should we compare if previous and current wave are the
214 // same before updating? 331 // same before updating?
215 SOUND_WAVE_MODE = SOUND_WAVE_BANK_SELECT(1); 332 SOUND_WAVE_MODE = SOUND_WAVE_BANK_SELECT(1);
216 memcpy(SOUND_WAVE_RAM, trig->wave_a, 16); 333 dma_copy(SOUND_WAVE_RAM, trig->wave_a, 16, 3);
217 SOUND_WAVE_MODE = SOUND_WAVE_BANK_SELECT(0); 334 SOUND_WAVE_MODE = SOUND_WAVE_BANK_SELECT(0);
218 memcpy(SOUND_WAVE_RAM, trig->wave_b, 16); 335 dma_copy(SOUND_WAVE_RAM, trig->wave_b, 16, 3);
219 336
220 switch (trig->wave_mode) { 337 switch (trig->wave_mode) {
221 case 0: { 338 case 0: {
@@ -261,252 +378,306 @@ irq_timer_0(void) {
261 step_counter = (step_counter + 1) % 16; 378 step_counter = (step_counter + 1) % 16;
262} 379}
263 380
381void
382set_time(int bpm) {
383 // The number of ticks of a 1024 cycle clock in a step based on the BPM can
384 // be calculated as:
385 // X bpm -> 60000 / 4 / bpm = Y ms = Ye-3 s
386 // Y ms -> Ye-3 / 59.99e-9 / 1024 = Z ticks
387 // We have to operate on integer values, so the numbers have been
388 // precalculated to `n_ticks = 244181 / bmp`
389 int n_ticks = -244181 / bpm;
390 irs_set(IRQ_TIMER_0, irq_timer_0);
391 TIMER_DATA_0 = n_ticks;
392 TIMER_CTRL_0 = TIMER_CTRL_IRQ | TIMER_CTRL_ENABLE | TIMER_CTRL_FREQ_3;
393}
394
264#define SEQ_N_CHANNELS 3 395#define SEQ_N_CHANNELS 3
265 396
266void 397void
267handle_sequencer_input(void) { 398trigger_cursor(void) {
268 poll_keys();
269 SeqTrigger *trig = &sequences[channel_selection_loc][trig_selection_loc]; 399 SeqTrigger *trig = &sequences[channel_selection_loc][trig_selection_loc];
270 if (current_selection == SEQ_SELECT_TRIGGER) { 400 if (key_tap(KEY_LEFT)) {
271 if (key_tap(KEY_LEFT)) { 401 if (trig_selection_loc == 0 || trig_selection_loc == 8) {
272 if (trig_selection_loc == 0 || trig_selection_loc == 8) { 402 // current_selection = SEQ_SELECT_CHANNEL;
273 current_selection = SEQ_SELECT_CHANNEL; 403 } else {
274 } else { 404 draw_trig_cursor(trig_selection_loc, 0);
275 trig_selection_loc = MAX(trig_selection_loc - 1, 0); 405 trig_selection_loc = MAX(trig_selection_loc - 1, 0);
276 } 406 draw_trig_cursor(trig_selection_loc, 3);
277 } else if (key_tap(KEY_RIGHT)) {
278 if (trig_selection_loc != 7) {
279 trig_selection_loc = MIN(trig_selection_loc + 1, 15);
280 }
281 } else if (key_tap(KEY_UP) || key_tap(KEY_DOWN)) {
282 trig_selection_loc = (trig_selection_loc + 8) % 16;
283 } else if (key_tap(KEY_B)) {
284 trig->trigger ^= 1;
285 } else if (key_tap(KEY_L)) {
286 if (trig->trigger) {
287 trig->note = MAX(trig->note - 1, NOTE_C_2);
288 }
289 } else if (key_tap(KEY_R)) {
290 if (trig->trigger) {
291 trig->note = MIN( trig->note + 1, NOTE_C_8);
292 }
293 } else if (key_tap(KEY_A)) {
294 // Switch to parameter selection.
295 current_selection = SEQ_SELECT_PARAMETER;
296 }
297 } else if (current_selection == SEQ_SELECT_PARAMETER) {
298 if (channel_selection_loc < 2) {
299 // Move through the selected synth parameters.
300 if (key_tap(KEY_LEFT)) {
301 int max_param = 6;
302 if (channel_selection_loc == 1) {
303 max_param = 3;
304 }
305 if (param_selection_loc == 0) {
306 param_selection_loc = max_param;
307 } else {
308 param_selection_loc = MAX(param_selection_loc - 1, 0);
309 }
310 }
311 if (key_tap(KEY_RIGHT)) {
312 int max_param = 6;
313 if (channel_selection_loc == 1) {
314 max_param = 3;
315 }
316 if (param_selection_loc == max_param) {
317 param_selection_loc = 0;
318 } else {
319 param_selection_loc = MIN(param_selection_loc + 1, max_param);
320 }
321 }
322
323 // Adjust the parameters up or down.
324 if (key_tap(KEY_L) || key_tap(KEY_R)) {
325 int inc;
326 if (key_tap(KEY_L)) {
327 inc = -1;
328 } else {
329 inc = 1;
330 }
331 switch (param_selection_loc) {
332 case 0: {
333 trig->env_volume = CLAMP(trig->env_volume + inc, 0, 15);
334 } break;
335 case 1: {
336 trig->env_time = CLAMP(trig->env_time + inc, 0, 7);
337 } break;
338 case 2: {
339 trig->env_direction ^= 1;
340 } break;
341 case 3: {
342 trig->duty_cycle = CLAMP(trig->duty_cycle + inc, 0, 3);
343 } break;
344 case 4: {
345 trig->sweep_number = CLAMP(trig->sweep_number + inc, 0, 7);
346 } break;
347 case 5: {
348 trig->sweep_time = CLAMP(trig->sweep_time + inc, 0, 7);
349 } break;
350 case 6: {
351 if (trig->sweep_direction == 0) {
352 trig->sweep_direction = 1;
353 } else {
354 trig->sweep_direction = 0;
355 }
356 } break;
357 }
358 }
359 } else if (channel_selection_loc == 2) {
360 if (key_tap(KEY_LEFT) || key_tap(KEY_RIGHT)) {
361 int inc = 0;
362 int loc = param_selection_loc;
363 if (key_tap(KEY_RIGHT)) {
364 if (loc == 15 || loc == 31) {
365 inc = 17;
366 } else if (loc != 47 && loc != 63){
367 inc = 1;
368 }
369 } else {
370 if (loc == 32 || loc == 48) {
371 inc = -17;
372 } else if (loc != 16 && loc != 64){
373 inc = -1;
374 }
375 }
376 param_selection_loc = CLAMP(loc + inc, 0, 71);
377 }
378 if (key_tap(KEY_UP) || key_tap(KEY_DOWN)) {
379 int inc = 0;
380 int loc = param_selection_loc;
381 if (key_tap(KEY_UP)) {
382 if ((loc >= 16 && loc < 32) || (loc >= 48 && loc < 64)) {
383 inc = -16;
384 } else if (loc == 64) {
385 inc = -48;
386 } else if (loc == 65) {
387 inc = -45;
388 } else if (loc == 66) {
389 inc = -42;
390 } else if (loc == 67) {
391 inc = -39;
392 } else if (loc == 68) {
393 inc = -20;
394 } else if (loc == 69) {
395 inc = -17;
396 } else if (loc == 70) {
397 inc = -14;
398 } else if (loc == 71) {
399 inc = -11;
400 }
401 } else {
402 if (loc < 16 || (loc >= 32 && loc < 48)) {
403 inc = 16;
404 } else if (loc >= 16 && loc <= 19){
405 inc = 48 - (loc - 16);
406 } else if (loc >= 20 && loc <= 23){
407 inc = 45 - (loc - 20);
408 } else if (loc >= 24 && loc <= 27){
409 inc = 42 - (loc - 24);
410 } else if (loc >= 28 && loc <= 31){
411 inc = 39 - (loc - 28);
412 } else if (loc >= 48 && loc <= 51){
413 inc = 20 - (loc - 48);
414 } else if (loc >= 52 && loc <= 55){
415 inc = 17 - (loc - 52);
416 } else if (loc >= 56 && loc <= 59){
417 inc = 14 - (loc - 56);
418 } else if (loc >= 60 && loc <= 63){
419 inc = 11 - (loc - 60);
420 }
421 }
422 param_selection_loc = CLAMP(loc + inc, 0, 71);
423 }
424 if (key_tap(KEY_R) || key_tap(KEY_L)) {
425 int odd = param_selection_loc & 0x1;
426 int inc;
427 if (key_tap(KEY_R)) {
428 inc = 1;
429 } else {
430 inc = -1;
431 }
432 // Wave: AA BB CC DD ...
433 // ^^
434 // |`- odd
435 // `-- even
436 if (param_selection_loc < 32) {
437 u8 byte_number = param_selection_loc >> 1;
438 u8 byte = sequences[2][trig_selection_loc].wave_a[byte_number];
439 if (odd) {
440 byte = (~0xF & byte) | ((byte + inc) & 0xF);
441 } else {
442 byte = (0xF & byte) | (((byte >> 4) + inc) & 0xF) << 4;
443 }
444 sequences[2][trig_selection_loc].wave_a[byte_number] = byte;
445 } else if (param_selection_loc < 64){
446 u8 byte_number = (param_selection_loc - 32) >> 1;
447 u8 byte = sequences[2][trig_selection_loc].wave_b[byte_number];
448 if (odd) {
449 byte = (~0xF & byte) | (byte + inc);
450 } else {
451 byte = (0xF & byte) | ((byte >> 4) + inc) << 4;
452 }
453 sequences[2][trig_selection_loc].wave_b[byte_number] = byte;
454 } else if (param_selection_loc == 64){
455 memcpy(&trig->wave_a, &sine_wave, 16);
456 } else if (param_selection_loc == 65){
457 memcpy(&trig->wave_a, &saw_wave, 16);
458 } else if (param_selection_loc == 66){
459 memcpy(&trig->wave_a, &square_wave, 16);
460 } else if (param_selection_loc == 67){
461 u32 rand_wave[4] = {
462 rng32(), rng32(), rng32(), rng32(),
463 };
464 memcpy(&trig->wave_a, &rand_wave, 16);
465 } else if (param_selection_loc == 68){
466 memcpy(&trig->wave_b, &sine_wave, 16);
467 } else if (param_selection_loc == 69){
468 memcpy(&trig->wave_b, &saw_wave, 16);
469 } else if (param_selection_loc == 70){
470 memcpy(&trig->wave_b, &square_wave, 16);
471 } else if (param_selection_loc == 71){
472 u32 rand_wave[4] = {
473 rng32(), rng32(), rng32(), rng32(),
474 };
475 memcpy(&trig->wave_b, &rand_wave, 16);
476 }
477 }
478 }
479
480 // Go back to trigger selection.
481 if (key_tap(KEY_A)) {
482 current_selection = SEQ_SELECT_TRIGGER;
483 }
484
485 // Enable disable trigger.
486 if (key_tap(KEY_B)) {
487 trig->trigger ^= 1;
488 } 407 }
489 } else if (current_selection == SEQ_SELECT_CHANNEL) { 408 } else if (key_tap(KEY_RIGHT)) {
490 if (key_tap(KEY_RIGHT)) { 409 if (trig_selection_loc != 7) {
491 current_selection = SEQ_SELECT_TRIGGER; 410 draw_trig_cursor(trig_selection_loc, 0);
492 trig_selection_loc = 0; 411 trig_selection_loc = MIN(trig_selection_loc + 1, 15);
493 param_selection_loc = 0; 412 draw_trig_cursor(trig_selection_loc, 3);
494 } 413 }
495 if (key_tap(KEY_UP)) { 414 } else if (key_tap(KEY_UP) || key_tap(KEY_DOWN)) {
496 if (channel_selection_loc == 0) { 415 draw_trig_cursor(trig_selection_loc, 0);
497 channel_selection_loc = SEQ_N_CHANNELS - 1; 416 trig_selection_loc = (trig_selection_loc + 8) % 16;
498 } else { 417 draw_trig_cursor(trig_selection_loc, 3);
499 channel_selection_loc = MAX(channel_selection_loc - 1, 0); 418 } else if (key_tap(KEY_B)) {
500 } 419 trig->trigger ^= 1;
420 } else if (key_tap(KEY_L)) {
421 if (trig->trigger) {
422 trig->note = MAX(trig->note - 1, NOTE_C_2);
501 } 423 }
502 if (key_tap(KEY_DOWN)) { 424 } else if (key_tap(KEY_R)) {
503 if (channel_selection_loc == SEQ_N_CHANNELS - 1) { 425 if (trig->trigger) {
504 channel_selection_loc = 0; 426 trig->note = MIN( trig->note + 1, NOTE_C_8);
505 } else {
506 channel_selection_loc = MIN(channel_selection_loc + 1, SEQ_N_CHANNELS);
507 }
508 } 427 }
428 } else if (key_tap(KEY_A)) {
429 // Switch to parameter selection.
430 // current_selection = SEQ_SELECT_PARAMETER;
509 } 431 }
432}
433
434void (*input_handler)(void);
435
436void
437handle_sequencer_input(void) {
438 poll_keys();
439 input_handler();
440 // SeqTrigger *trig = &sequences[channel_selection_loc][trig_selection_loc];
441 // if (current_selection == SEQ_SELECT_TRIGGER) {
442 // if (key_tap(KEY_LEFT)) {
443 // if (trig_selection_loc == 0 || trig_selection_loc == 8) {
444 // current_selection = SEQ_SELECT_CHANNEL;
445 // } else {
446 // trig_selection_loc = MAX(trig_selection_loc - 1, 0);
447 // }
448 // } else if (key_tap(KEY_RIGHT)) {
449 // if (trig_selection_loc != 7) {
450 // trig_selection_loc = MIN(trig_selection_loc + 1, 15);
451 // }
452 // } else if (key_tap(KEY_UP) || key_tap(KEY_DOWN)) {
453 // trig_selection_loc = (trig_selection_loc + 8) % 16;
454 // } else if (key_tap(KEY_B)) {
455 // trig->trigger ^= 1;
456 // } else if (key_tap(KEY_L)) {
457 // if (trig->trigger) {
458 // trig->note = MAX(trig->note - 1, NOTE_C_2);
459 // }
460 // } else if (key_tap(KEY_R)) {
461 // if (trig->trigger) {
462 // trig->note = MIN( trig->note + 1, NOTE_C_8);
463 // }
464 // } else if (key_tap(KEY_A)) {
465 // // Switch to parameter selection.
466 // current_selection = SEQ_SELECT_PARAMETER;
467 // }
468 // } else if (current_selection == SEQ_SELECT_PARAMETER) {
469 // if (channel_selection_loc < 2) {
470 // // Move through the selected synth parameters.
471 // if (key_tap(KEY_LEFT)) {
472 // int max_param = 6;
473 // if (channel_selection_loc == 1) {
474 // max_param = 3;
475 // }
476 // if (param_selection_loc == 0) {
477 // param_selection_loc = max_param;
478 // } else {
479 // param_selection_loc = MAX(param_selection_loc - 1, 0);
480 // }
481 // }
482 // if (key_tap(KEY_RIGHT)) {
483 // int max_param = 6;
484 // if (channel_selection_loc == 1) {
485 // max_param = 3;
486 // }
487 // if (param_selection_loc == max_param) {
488 // param_selection_loc = 0;
489 // } else {
490 // param_selection_loc = MIN(param_selection_loc + 1, max_param);
491 // }
492 // }
493
494 // // Adjust the parameters up or down.
495 // if (key_tap(KEY_L) || key_tap(KEY_R)) {
496 // int inc;
497 // if (key_tap(KEY_L)) {
498 // inc = -1;
499 // } else {
500 // inc = 1;
501 // }
502 // switch (param_selection_loc) {
503 // case 0: {
504 // trig->env_volume = CLAMP(trig->env_volume + inc, 0, 15);
505 // } break;
506 // case 1: {
507 // trig->env_time = CLAMP(trig->env_time + inc, 0, 7);
508 // } break;
509 // case 2: {
510 // trig->env_direction ^= 1;
511 // } break;
512 // case 3: {
513 // trig->duty_cycle = CLAMP(trig->duty_cycle + inc, 0, 3);
514 // } break;
515 // case 4: {
516 // trig->sweep_number = CLAMP(trig->sweep_number + inc, 0, 7);
517 // } break;
518 // case 5: {
519 // trig->sweep_time = CLAMP(trig->sweep_time + inc, 0, 7);
520 // } break;
521 // case 6: {
522 // if (trig->sweep_direction == 0) {
523 // trig->sweep_direction = 1;
524 // } else {
525 // trig->sweep_direction = 0;
526 // }
527 // } break;
528 // }
529 // }
530 // } else if (channel_selection_loc == 2) {
531 // if (key_tap(KEY_LEFT) || key_tap(KEY_RIGHT)) {
532 // int inc = 0;
533 // int loc = param_selection_loc;
534 // if (key_tap(KEY_RIGHT)) {
535 // if (loc == 15 || loc == 31) {
536 // inc = 17;
537 // } else if (loc != 47 && loc != 63){
538 // inc = 1;
539 // }
540 // } else {
541 // if (loc == 32 || loc == 48) {
542 // inc = -17;
543 // } else if (loc != 16 && loc != 64){
544 // inc = -1;
545 // }
546 // }
547 // param_selection_loc = CLAMP(loc + inc, 0, 71);
548 // }
549 // if (key_tap(KEY_UP) || key_tap(KEY_DOWN)) {
550 // int inc = 0;
551 // int loc = param_selection_loc;
552 // if (key_tap(KEY_UP)) {
553 // if ((loc >= 16 && loc < 32) || (loc >= 48 && loc < 64)) {
554 // inc = -16;
555 // } else if (loc == 64) {
556 // inc = -48;
557 // } else if (loc == 65) {
558 // inc = -45;
559 // } else if (loc == 66) {
560 // inc = -42;
561 // } else if (loc == 67) {
562 // inc = -39;
563 // } else if (loc == 68) {
564 // inc = -20;
565 // } else if (loc == 69) {
566 // inc = -17;
567 // } else if (loc == 70) {
568 // inc = -14;
569 // } else if (loc == 71) {
570 // inc = -11;
571 // }
572 // } else {
573 // if (loc < 16 || (loc >= 32 && loc < 48)) {
574 // inc = 16;
575 // } else if (loc >= 16 && loc <= 19){
576 // inc = 48 - (loc - 16);
577 // } else if (loc >= 20 && loc <= 23){
578 // inc = 45 - (loc - 20);
579 // } else if (loc >= 24 && loc <= 27){
580 // inc = 42 - (loc - 24);
581 // } else if (loc >= 28 && loc <= 31){
582 // inc = 39 - (loc - 28);
583 // } else if (loc >= 48 && loc <= 51){
584 // inc = 20 - (loc - 48);
585 // } else if (loc >= 52 && loc <= 55){
586 // inc = 17 - (loc - 52);
587 // } else if (loc >= 56 && loc <= 59){
588 // inc = 14 - (loc - 56);
589 // } else if (loc >= 60 && loc <= 63){
590 // inc = 11 - (loc - 60);
591 // }
592 // }
593 // param_selection_loc = CLAMP(loc + inc, 0, 71);
594 // }
595 // if (key_tap(KEY_R) || key_tap(KEY_L)) {
596 // int odd = param_selection_loc & 0x1;
597 // int inc;
598 // if (key_tap(KEY_R)) {
599 // inc = 1;
600 // } else {
601 // inc = -1;
602 // }
603 // // Wave: AA BB CC DD ...
604 // // ^^
605 // // |`- odd
606 // // `-- even
607 // if (param_selection_loc < 32) {
608 // u8 byte_number = param_selection_loc >> 1;
609 // u8 byte = sequences[2][trig_selection_loc].wave_a[byte_number];
610 // if (odd) {
611 // byte = (~0xF & byte) | ((byte + inc) & 0xF);
612 // } else {
613 // byte = (0xF & byte) | (((byte >> 4) + inc) & 0xF) << 4;
614 // }
615 // sequences[2][trig_selection_loc].wave_a[byte_number] = byte;
616 // } else if (param_selection_loc < 64){
617 // u8 byte_number = (param_selection_loc - 32) >> 1;
618 // u8 byte = sequences[2][trig_selection_loc].wave_b[byte_number];
619 // if (odd) {
620 // byte = (~0xF & byte) | (byte + inc);
621 // } else {
622 // byte = (0xF & byte) | ((byte >> 4) + inc) << 4;
623 // }
624 // sequences[2][trig_selection_loc].wave_b[byte_number] = byte;
625 // } else if (param_selection_loc == 64){
626 // dma_copy(&trig->wave_a, &sine_wave, 16);
627 // } else if (param_selection_loc == 65){
628 // dma_copy(&trig->wave_a, &saw_wave, 16);
629 // } else if (param_selection_loc == 66){
630 // dma_copy(&trig->wave_a, &square_wave, 16);
631 // } else if (param_selection_loc == 67){
632 // u32 rand_wave[4] = {
633 // rng32(), rng32(), rng32(), rng32(),
634 // };
635 // dma_copy(&trig->wave_a, &rand_wave, 16);
636 // } else if (param_selection_loc == 68){
637 // dma_copy(&trig->wave_b, &sine_wave, 16);
638 // } else if (param_selection_loc == 69){
639 // dma_copy(&trig->wave_b, &saw_wave, 16);
640 // } else if (param_selection_loc == 70){
641 // dma_copy(&trig->wave_b, &square_wave, 16);
642 // } else if (param_selection_loc == 71){
643 // u32 rand_wave[4] = {
644 // rng32(), rng32(), rng32(), rng32(),
645 // };
646 // dma_copy(&trig->wave_b, &rand_wave, 16);
647 // }
648 // }
649 // }
650
651 // // Go back to trigger selection.
652 // if (key_tap(KEY_A)) {
653 // current_selection = SEQ_SELECT_TRIGGER;
654 // }
655
656 // // Enable disable trigger.
657 // if (key_tap(KEY_B)) {
658 // trig->trigger ^= 1;
659 // }
660 // } else if (current_selection == SEQ_SELECT_CHANNEL) {
661 // if (key_tap(KEY_RIGHT)) {
662 // current_selection = SEQ_SELECT_TRIGGER;
663 // trig_selection_loc = 0;
664 // param_selection_loc = 0;
665 // }
666 // if (key_tap(KEY_UP)) {
667 // if (channel_selection_loc == 0) {
668 // channel_selection_loc = SEQ_N_CHANNELS - 1;
669 // } else {
670 // channel_selection_loc = MAX(channel_selection_loc - 1, 0);
671 // }
672 // }
673 // if (key_tap(KEY_DOWN)) {
674 // if (channel_selection_loc == SEQ_N_CHANNELS - 1) {
675 // channel_selection_loc = 0;
676 // } else {
677 // channel_selection_loc = MIN(channel_selection_loc + 1, SEQ_N_CHANNELS);
678 // }
679 // }
680 // }
510 681
511 if (key_tap(KEY_START)) { 682 if (key_tap(KEY_START)) {
512 step_counter = 0; 683 step_counter = 0;
@@ -526,41 +697,38 @@ handle_sequencer_input(void) {
526 SOUND_WAVE_CTRL = 0; 697 SOUND_WAVE_CTRL = 0;
527 } 698 }
528 699
529 if (key_tap(KEY_LEFT) 700 // if (key_tap(KEY_LEFT)
530 || key_tap(KEY_RIGHT) 701 // || key_tap(KEY_RIGHT)
531 || key_tap(KEY_UP) 702 // || key_tap(KEY_UP)
532 || key_tap(KEY_DOWN) 703 // || key_tap(KEY_DOWN)
533 || key_tap(KEY_L) 704 // || key_tap(KEY_L)
534 || key_tap(KEY_R) 705 // || key_tap(KEY_R)
535 ) { 706 // ) {
536 } 707 // }
537} 708}
538 709
539void 710void
540set_time(int bpm) { 711load_note_names(void) {
541 // The number of ticks of a 1024 cycle clock in a step based on the BPM can 712 unpack_tiles(note_names, ASSETS_DATA, 2 * 73);
542 // be calculated as:
543 // X bpm -> 60000 / 4 / bpm = Y ms = Ye-3 s
544 // Y ms -> Ye-3 / 59.99e-9 / 1024 = Z ticks
545 // We have to operate on integer values, so the numbers have been
546 // precalculated to `n_ticks = 244181 / bmp`
547 int n_ticks = -244181 / bpm;
548 irs_set(IRQ_TIMER_0, irq_timer_0);
549 TIMER_DATA_0 = n_ticks;
550 TIMER_CTRL_0 = TIMER_CTRL_IRQ | TIMER_CTRL_ENABLE | TIMER_CTRL_FREQ_3;
551} 713}
552 714
553void 715void
554sequencer_init(void) { 716sequencer_init(void) {
717 // TODO: Unpack non-sprite tiles directly on the VRAM.
718 load_note_names();
719
555 // Initialize background objects and sprites. 720 // Initialize background objects and sprites.
556 draw_triggers(); 721 draw_triggers();
557 draw_channels(); 722 draw_channels();
558 723
724 // Initialize input handler.
725 input_handler = trigger_cursor;
726 draw_trig_cursor(trig_selection_loc, 3);
727
559 // Initialize sound system. 728 // Initialize sound system.
560 SOUND_STATUS = SOUND_ENABLE; 729 SOUND_STATUS = SOUND_ENABLE;
561 SOUND_DMG_MASTER = sound_volume(SOUND_SQUARE1 730 SOUND_DMG_MASTER = sound_volume(SOUND_SQUARE1
562 | SOUND_SQUARE2 731 | SOUND_SQUARE2
563 | SOUND_WAVE, 3); 732 | SOUND_WAVE, 3);
564 SOUND_DSOUND_MASTER = SOUND_DMG25; 733 SOUND_DSOUND_MASTER = SOUND_DMG25;
565 set_time(bpm);
566} 734}