diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/sequencer.c | 321 |
1 files changed, 220 insertions, 101 deletions
diff --git a/src/sequencer.c b/src/sequencer.c index 526680a..fa9b674 100644 --- a/src/sequencer.c +++ b/src/sequencer.c | |||
@@ -141,10 +141,12 @@ int trig_selection_loc = 0; | |||
141 | int param_selection_loc = 64; | 141 | int param_selection_loc = 64; |
142 | int channel_selection_loc = 0; | 142 | int channel_selection_loc = 0; |
143 | 143 | ||
144 | // TODO: Split into individual trigger types. | 144 | typedef struct TriggerNote { |
145 | typedef struct SeqTrigger { | 145 | bool active; |
146 | bool trigger; | ||
147 | Note note; | 146 | Note note; |
147 | } TriggerNote; | ||
148 | |||
149 | typedef struct ChannelSquareParams { | ||
148 | u8 env_volume; | 150 | u8 env_volume; |
149 | u8 env_time; | 151 | u8 env_time; |
150 | u8 env_direction; | 152 | u8 env_direction; |
@@ -152,73 +154,146 @@ typedef struct SeqTrigger { | |||
152 | u8 sweep_number; | 154 | u8 sweep_number; |
153 | u8 sweep_time; | 155 | u8 sweep_time; |
154 | u8 sweep_direction; | 156 | u8 sweep_direction; |
157 | } ChannelSquareParams; | ||
158 | |||
159 | typedef struct ChannelWaveParams { | ||
155 | u8 wave_volume; | 160 | u8 wave_volume; |
156 | u8 wave_mode; | 161 | u8 wave_mode; |
157 | u8 wave_a[16]; | 162 | u8 wave_a[16]; |
158 | u8 wave_b[16]; | 163 | u8 wave_b[16]; |
159 | } SeqTrigger; | 164 | } ChannelWaveParams; |
160 | 165 | ||
161 | static SeqTrigger sequences[3][16] = { | 166 | typedef struct ChannelSquare { |
162 | // Synth 1. | 167 | bool active; |
163 | { | 168 | TriggerNote notes[16]; |
164 | {true, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, | 169 | ChannelSquareParams params[16]; |
165 | {true, NOTE_D_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, | 170 | } ChannelSquare; |
166 | {false, NOTE_E_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, | 171 | |
167 | {false, NOTE_F_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, | 172 | typedef struct ChannelWave { |
168 | {true, NOTE_G_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, | 173 | bool active; |
169 | {true, NOTE_A_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, | 174 | TriggerNote notes[16]; |
170 | {false, NOTE_B_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, | 175 | ChannelWaveParams params[16]; |
171 | {false, NOTE_C_5, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, | 176 | } ChannelWave; |
172 | {true, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, | 177 | |
173 | {true, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, | 178 | static ChannelSquare ch1 = { |
174 | {false, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, | 179 | .notes = { |
175 | {false, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, | 180 | {true, NOTE_C_4}, |
176 | {true, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, | 181 | {true, NOTE_D_4}, |
177 | {false, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, | 182 | {true, NOTE_E_4}, |
178 | {false, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, | 183 | {true, NOTE_F_4}, |
179 | {false, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, | 184 | {true, NOTE_G_4}, |
185 | {true, NOTE_A_4}, | ||
186 | {true, NOTE_B_4}, | ||
187 | {true, NOTE_C_5}, | ||
188 | {true, NOTE_C_4}, | ||
189 | {true, NOTE_C_4}, | ||
190 | {true, NOTE_C_4}, | ||
191 | {true, NOTE_C_4}, | ||
192 | {true, NOTE_C_4}, | ||
193 | {true, NOTE_C_4}, | ||
194 | {true, NOTE_C_4}, | ||
195 | {true, NOTE_C_4}, | ||
196 | }, | ||
197 | .params = { | ||
198 | {8, 4, 0, 2, 0, 0, 0}, | ||
199 | {8, 4, 0, 2, 0, 0, 0}, | ||
200 | {8, 4, 0, 2, 0, 0, 0}, | ||
201 | {8, 4, 0, 2, 0, 0, 0}, | ||
202 | {8, 4, 0, 2, 0, 0, 0}, | ||
203 | {8, 4, 0, 2, 0, 0, 0}, | ||
204 | {8, 4, 0, 2, 0, 0, 0}, | ||
205 | {8, 4, 0, 2, 0, 0, 0}, | ||
206 | {8, 4, 0, 2, 0, 0, 0}, | ||
207 | {8, 4, 0, 2, 0, 0, 0}, | ||
208 | {8, 4, 0, 2, 0, 0, 0}, | ||
209 | {8, 4, 0, 2, 0, 0, 0}, | ||
210 | {8, 4, 0, 2, 0, 0, 0}, | ||
211 | {8, 4, 0, 2, 0, 0, 0}, | ||
212 | {8, 4, 0, 2, 0, 0, 0}, | ||
213 | {8, 4, 0, 2, 0, 0, 0}, | ||
180 | }, | 214 | }, |
181 | // Synth 2. | 215 | .active = true, |
182 | { | 216 | }; |
183 | {false, NOTE_G_5, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, | 217 | |
184 | {false, NOTE_G_5, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, | 218 | static ChannelSquare ch2 = { |
185 | {false, NOTE_G_5, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, | 219 | .notes = { |
186 | {false, NOTE_G_5, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, | 220 | {true, NOTE_C_4}, |
187 | {false, NOTE_G_5, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, | 221 | {true, NOTE_D_4}, |
188 | {false, NOTE_G_5, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, | 222 | {true, NOTE_E_4}, |
189 | {false, NOTE_G_5, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, | 223 | {true, NOTE_F_4}, |
190 | {false, NOTE_G_5, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, | 224 | {true, NOTE_G_4}, |
191 | {false, NOTE_C_5, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, | 225 | {true, NOTE_A_4}, |
192 | {false, NOTE_B_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, | 226 | {true, NOTE_B_4}, |
193 | {false, NOTE_A_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, | 227 | {true, NOTE_C_5}, |
194 | {false, NOTE_G_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, | 228 | {true, NOTE_C_4}, |
195 | {false, NOTE_F_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, | 229 | {true, NOTE_C_4}, |
196 | {false, NOTE_E_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, | 230 | {true, NOTE_C_4}, |
197 | {false, NOTE_D_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, | 231 | {true, NOTE_C_4}, |
198 | {false, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0, 0, 0, {0}, {0}}, | 232 | {true, NOTE_C_4}, |
233 | {true, NOTE_C_4}, | ||
234 | {true, NOTE_C_4}, | ||
235 | {true, NOTE_C_4}, | ||
199 | }, | 236 | }, |
200 | // Synth 3. | 237 | .params = { |
201 | { | 238 | {8, 4, 0, 2, 0, 0, 0}, |
202 | {true, NOTE_C_5, 8, 4, 0, 2, 0, 0, 0, 3, 0, {0}, {0}}, | 239 | {8, 4, 0, 2, 0, 0, 0}, |
203 | {true, NOTE_D_5, 8, 4, 0, 2, 0, 0, 0, 3, 0, {0}, {0}}, | 240 | {8, 4, 0, 2, 0, 0, 0}, |
204 | {true, NOTE_E_5, 8, 4, 0, 2, 0, 0, 0, 3, 0, {0}, {0}}, | 241 | {8, 4, 0, 2, 0, 0, 0}, |
205 | {true, NOTE_F_5, 8, 4, 0, 2, 0, 0, 0, 3, 0, {0}, {0}}, | 242 | {8, 4, 0, 2, 0, 0, 0}, |
206 | {true, NOTE_G_5, 8, 4, 0, 2, 0, 0, 0, 3, 0, {0}, {0}}, | 243 | {8, 4, 0, 2, 0, 0, 0}, |
207 | {true, NOTE_A_5, 8, 4, 0, 2, 0, 0, 0, 3, 0, {0}, {0}}, | 244 | {8, 4, 0, 2, 0, 0, 0}, |
208 | {true, NOTE_B_5, 8, 4, 0, 2, 0, 0, 0, 3, 0, {0}, {0}}, | 245 | {8, 4, 0, 2, 0, 0, 0}, |
209 | {true, NOTE_C_6, 8, 4, 0, 2, 0, 0, 0, 3, 0, {0}, {0}}, | 246 | {8, 4, 0, 2, 0, 0, 0}, |
210 | {true, NOTE_C_5, 8, 4, 0, 2, 0, 0, 0, 3, 0, {0}, {0}}, | 247 | {8, 4, 0, 2, 0, 0, 0}, |
211 | {true, NOTE_D_5, 8, 4, 0, 2, 0, 0, 0, 3, 0, {0}, {0}}, | 248 | {8, 4, 0, 2, 0, 0, 0}, |
212 | {true, NOTE_E_5, 8, 4, 0, 2, 0, 0, 0, 3, 0, {0}, {0}}, | 249 | {8, 4, 0, 2, 0, 0, 0}, |
213 | {true, NOTE_F_5, 8, 4, 0, 2, 0, 0, 0, 3, 0, {0}, {0}}, | 250 | {8, 4, 0, 2, 0, 0, 0}, |
214 | {true, NOTE_G_5, 8, 4, 0, 2, 0, 0, 0, 3, 0, {0}, {0}}, | 251 | {8, 4, 0, 2, 0, 0, 0}, |
215 | {true, NOTE_A_5, 8, 4, 0, 2, 0, 0, 0, 3, 0, {0}, {0}}, | 252 | {8, 4, 0, 2, 0, 0, 0}, |
216 | {true, NOTE_B_5, 8, 4, 0, 2, 0, 0, 0, 3, 0, {0}, {0}}, | 253 | {8, 4, 0, 2, 0, 0, 0}, |
217 | {true, NOTE_C_6, 8, 4, 0, 2, 0, 0, 0, 3, 0, {0}, {0}}, | ||
218 | }, | 254 | }, |
255 | .active = true, | ||
219 | }; | 256 | }; |
220 | 257 | ||
221 | static bool active_channels[4] = {true, true, true, true}; | 258 | static ChannelWave ch3 = { |
259 | .notes = { | ||
260 | {true, NOTE_C_4}, | ||
261 | {true, NOTE_D_4}, | ||
262 | {true, NOTE_E_4}, | ||
263 | {true, NOTE_F_4}, | ||
264 | {true, NOTE_G_4}, | ||
265 | {true, NOTE_A_4}, | ||
266 | {true, NOTE_B_4}, | ||
267 | {true, NOTE_C_5}, | ||
268 | {true, NOTE_C_4}, | ||
269 | {true, NOTE_C_4}, | ||
270 | {true, NOTE_C_4}, | ||
271 | {true, NOTE_C_4}, | ||
272 | {true, NOTE_C_4}, | ||
273 | {true, NOTE_C_4}, | ||
274 | {true, NOTE_C_4}, | ||
275 | {true, NOTE_C_4}, | ||
276 | }, | ||
277 | .params = { | ||
278 | {3, 0, {0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000},{0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000}}, | ||
279 | {3, 0, {0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000},{0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000}}, | ||
280 | {3, 0, {0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000},{0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000}}, | ||
281 | {3, 0, {0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000},{0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000}}, | ||
282 | {3, 0, {0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000},{0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000}}, | ||
283 | {3, 0, {0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000},{0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000}}, | ||
284 | {3, 0, {0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000},{0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000}}, | ||
285 | {3, 0, {0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000},{0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000}}, | ||
286 | {3, 0, {0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000},{0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000}}, | ||
287 | {3, 0, {0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000},{0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000}}, | ||
288 | {3, 0, {0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000},{0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000}}, | ||
289 | {3, 0, {0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000},{0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000}}, | ||
290 | {3, 0, {0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000},{0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000}}, | ||
291 | {3, 0, {0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000},{0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000}}, | ||
292 | {3, 0, {0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000},{0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000}}, | ||
293 | {3, 0, {0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000},{0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000}}, | ||
294 | }, | ||
295 | .active = true, | ||
296 | }; | ||
222 | 297 | ||
223 | // | 298 | // |
224 | // Trigger render functions. | 299 | // Trigger render functions. |
@@ -244,13 +319,25 @@ clear_trigger(size_t i) { | |||
244 | 319 | ||
245 | void | 320 | void |
246 | draw_trigger(size_t chan, size_t i) { | 321 | draw_trigger(size_t chan, size_t i) { |
247 | if (sequences[chan][i].trigger) { | 322 | TriggerNote trig = {0}; |
323 | switch (chan) { | ||
324 | case 0: { | ||
325 | trig = ch1.notes[i]; | ||
326 | } break; | ||
327 | case 1: { | ||
328 | trig = ch2.notes[i]; | ||
329 | } break; | ||
330 | case 2: { | ||
331 | trig = ch3.notes[i]; | ||
332 | } break; | ||
333 | } | ||
334 | if (trig.active) { | ||
248 | size_t offset_x = TRIG_OFFSET_X * (i % 8); | 335 | size_t offset_x = TRIG_OFFSET_X * (i % 8); |
249 | size_t offset_y = i < 8 ? 0 : TRIG_OFFSET_Y; | 336 | size_t offset_y = i < 8 ? 0 : TRIG_OFFSET_Y; |
250 | size_t x = TRIG_START_X + offset_x; | 337 | size_t x = TRIG_START_X + offset_x; |
251 | size_t y = TRIG_START_Y + offset_y; | 338 | size_t y = TRIG_START_Y + offset_y; |
252 | Tile *tiles = ASSETS_DATA; | 339 | Tile *tiles = ASSETS_DATA; |
253 | tiles += 2 * sequences[chan][i].note; | 340 | tiles += 2 * trig.note; |
254 | draw_tile(x, y, tiles, COL_FG, true); | 341 | draw_tile(x, y, tiles, COL_FG, true); |
255 | draw_tile(x + 8, y, tiles + 1, COL_FG, true); | 342 | draw_tile(x + 8, y, tiles + 1, COL_FG, true); |
256 | } else { | 343 | } else { |
@@ -301,7 +388,19 @@ draw_channels(void) { | |||
301 | unpack_tiles(channel_buttons, channel_tiles, 3 * 4); | 388 | unpack_tiles(channel_buttons, channel_tiles, 3 * 4); |
302 | size_t k = 0; | 389 | size_t k = 0; |
303 | for (size_t i = 0; i < 4; i++) { | 390 | for (size_t i = 0; i < 4; i++) { |
304 | u8 clr = active_channels[i] ? COL_FG : COL_GREY; | 391 | bool active; |
392 | switch (i) { | ||
393 | case 0: { | ||
394 | active = ch1.active; | ||
395 | } break; | ||
396 | case 1: { | ||
397 | active = ch2.active; | ||
398 | } break; | ||
399 | case 2: { | ||
400 | active = ch3.active; | ||
401 | } break; | ||
402 | } | ||
403 | u8 clr = active ? COL_FG : COL_GREY; | ||
305 | size_t y = CHAN_START_Y + i * CHAN_OFFSET_Y; | 404 | size_t y = CHAN_START_Y + i * CHAN_OFFSET_Y; |
306 | draw_tile(CHAN_START_X, y, channel_tiles + k++, clr, false); | 405 | draw_tile(CHAN_START_X, y, channel_tiles + k++, clr, false); |
307 | draw_tile(CHAN_START_X + 8, y, channel_tiles + k++, clr, false); | 406 | draw_tile(CHAN_START_X + 8, y, channel_tiles + k++, clr, false); |
@@ -321,55 +420,54 @@ draw_channel_cursor(size_t i, u8 clr) { | |||
321 | 420 | ||
322 | void | 421 | void |
323 | irq_timer(void) { | 422 | irq_timer(void) { |
324 | Note active_note; | 423 | if (ch1.active) { |
325 | if (active_channels[0]) { | 424 | TriggerNote *trig = &ch1.notes[step_counter]; |
326 | SeqTrigger *trig = &sequences[0][step_counter]; | 425 | ChannelSquareParams *params = &ch1.params[step_counter]; |
327 | active_note = trig->note; | 426 | if (trig->active) { |
328 | if (trig->trigger) { | 427 | SOUND_SQUARE1_SWEEP = SOUND_SWEEP_NUMBER(params->sweep_number) |
329 | SOUND_SQUARE1_SWEEP = SOUND_SWEEP_NUMBER(trig->sweep_number) | 428 | | SOUND_SWEEP_DIR(params->sweep_direction) |
330 | | SOUND_SWEEP_DIR(trig->sweep_direction) | 429 | | SOUND_SWEEP_TIME(params->sweep_time); |
331 | | SOUND_SWEEP_TIME(trig->sweep_time); | 430 | SOUND_SQUARE1_CTRL = SOUND_SQUARE_ENV_VOL(params->env_volume) |
332 | SOUND_SQUARE1_CTRL = SOUND_SQUARE_ENV_VOL(trig->env_volume) | 431 | | SOUND_SQUARE_ENV_TIME(params->env_time) |
333 | | SOUND_SQUARE_ENV_TIME(trig->env_time) | 432 | | SOUND_SQUARE_ENV_DIR(params->env_direction) |
334 | | SOUND_SQUARE_ENV_DIR(trig->env_direction) | 433 | | SOUND_SQUARE_DUTY(params->duty_cycle); |
335 | | SOUND_SQUARE_DUTY(trig->duty_cycle); | ||
336 | SOUND_SQUARE1_FREQ = SOUND_FREQ_RESET | 434 | SOUND_SQUARE1_FREQ = SOUND_FREQ_RESET |
337 | | sound_rates[active_note]; | 435 | | sound_rates[trig->note]; |
338 | } | 436 | } |
339 | } else { | 437 | } else { |
340 | SOUND_SQUARE1_CTRL = 0; | 438 | SOUND_SQUARE1_CTRL = 0; |
341 | SOUND_SQUARE1_FREQ = 0; | 439 | SOUND_SQUARE1_FREQ = 0; |
342 | } | 440 | } |
343 | if (active_channels[1]) { | 441 | if (ch2.active) { |
344 | SeqTrigger *trig = &sequences[1][step_counter]; | 442 | TriggerNote *trig = &ch2.notes[step_counter]; |
345 | active_note = trig->note; | 443 | ChannelSquareParams *params = &ch2.params[step_counter]; |
346 | if (trig->trigger) { | 444 | if (trig->active) { |
347 | SOUND_SQUARE2_CTRL = SOUND_SQUARE_ENV_VOL(trig->env_volume) | 445 | SOUND_SQUARE2_CTRL = SOUND_SQUARE_ENV_VOL(params->env_volume) |
348 | | SOUND_SQUARE_ENV_TIME(trig->env_time) | 446 | | SOUND_SQUARE_ENV_TIME(params->env_time) |
349 | | SOUND_SQUARE_ENV_DIR(trig->env_direction) | 447 | | SOUND_SQUARE_ENV_DIR(params->env_direction) |
350 | | SOUND_SQUARE_DUTY(trig->duty_cycle); | 448 | | SOUND_SQUARE_DUTY(params->duty_cycle); |
351 | SOUND_SQUARE2_FREQ = SOUND_FREQ_RESET | 449 | SOUND_SQUARE2_FREQ = SOUND_FREQ_RESET |
352 | | sound_rates[active_note]; | 450 | | sound_rates[trig->note]; |
353 | } | 451 | } |
354 | } else { | 452 | } else { |
355 | SOUND_SQUARE2_CTRL = 0; | 453 | SOUND_SQUARE2_CTRL = 0; |
356 | SOUND_SQUARE2_FREQ = 0; | 454 | SOUND_SQUARE2_FREQ = 0; |
357 | } | 455 | } |
358 | if (active_channels[2]) { | 456 | if (ch3.active) { |
359 | SeqTrigger *trig = &sequences[2][step_counter]; | 457 | TriggerNote *trig = &ch3.notes[step_counter]; |
360 | active_note = trig->note; | 458 | ChannelWaveParams *params = &ch3.params[step_counter]; |
361 | if (trig->trigger) { | 459 | if (trig->active) { |
362 | // Update both banks. | 460 | // Update both banks. |
363 | // TODO: Actually depends on which bank is selected, no need to | 461 | // TODO: Actually depends on which bank is selected, no need to |
364 | // update both if only one is playing. | 462 | // update both if only one is playing. |
365 | // TODO: Should we compare if previous and current wave are the | 463 | // TODO: Should we compare if previous and current wave are the |
366 | // same before updating? | 464 | // same before updating? |
367 | SOUND_WAVE_MODE = SOUND_WAVE_BANK_SELECT(1); | 465 | SOUND_WAVE_MODE = SOUND_WAVE_BANK_SELECT(1); |
368 | dma_copy(SOUND_WAVE_RAM, trig->wave_a, 16, 3); | 466 | dma_copy(SOUND_WAVE_RAM, params->wave_a, 16, 3); |
369 | SOUND_WAVE_MODE = SOUND_WAVE_BANK_SELECT(0); | 467 | SOUND_WAVE_MODE = SOUND_WAVE_BANK_SELECT(0); |
370 | dma_copy(SOUND_WAVE_RAM, trig->wave_b, 16, 3); | 468 | dma_copy(SOUND_WAVE_RAM, params->wave_b, 16, 3); |
371 | 469 | ||
372 | switch (trig->wave_mode) { | 470 | switch (params->wave_mode) { |
373 | case 0: { | 471 | case 0: { |
374 | SOUND_WAVE_MODE = SOUND_WAVE_BANK_MODE(0) | 472 | SOUND_WAVE_MODE = SOUND_WAVE_BANK_MODE(0) |
375 | | SOUND_WAVE_BANK_SELECT(0); | 473 | | SOUND_WAVE_BANK_SELECT(0); |
@@ -389,7 +487,7 @@ irq_timer(void) { | |||
389 | } | 487 | } |
390 | SOUND_WAVE_MODE |= SOUND_WAVE_ENABLE; | 488 | SOUND_WAVE_MODE |= SOUND_WAVE_ENABLE; |
391 | 489 | ||
392 | switch (trig->wave_volume) { | 490 | switch (params->wave_volume) { |
393 | case 0: { | 491 | case 0: { |
394 | SOUND_WAVE_CTRL = SOUND_WAVE_MUTE; | 492 | SOUND_WAVE_CTRL = SOUND_WAVE_MUTE; |
395 | } break; | 493 | } break; |
@@ -407,7 +505,7 @@ irq_timer(void) { | |||
407 | } break; | 505 | } break; |
408 | } | 506 | } |
409 | SOUND_WAVE_FREQ = SOUND_FREQ_RESET | 507 | SOUND_WAVE_FREQ = SOUND_FREQ_RESET |
410 | | sound_rates[active_note]; | 508 | | sound_rates[trig->note]; |
411 | } | 509 | } |
412 | } else { | 510 | } else { |
413 | SOUND_WAVE_CTRL = 0; | 511 | SOUND_WAVE_CTRL = 0; |
@@ -441,7 +539,17 @@ void handle_channel_cursor(void); | |||
441 | void | 539 | void |
442 | handle_channel_cursor(void) { | 540 | handle_channel_cursor(void) { |
443 | if (key_tap(KEY_B)) { | 541 | if (key_tap(KEY_B)) { |
444 | active_channels[channel_selection_loc] ^= 1; | 542 | switch (channel_selection_loc) { |
543 | case 0: { | ||
544 | ch1.active ^= 1; | ||
545 | } break; | ||
546 | case 1: { | ||
547 | ch2.active ^= 1; | ||
548 | } break; | ||
549 | case 2: { | ||
550 | ch3.active ^= 1; | ||
551 | } break; | ||
552 | } | ||
445 | draw_channels(); | 553 | draw_channels(); |
446 | } | 554 | } |
447 | if (key_tap(KEY_RIGHT)) { | 555 | if (key_tap(KEY_RIGHT)) { |
@@ -473,25 +581,36 @@ handle_channel_cursor(void) { | |||
473 | 581 | ||
474 | void | 582 | void |
475 | handle_trigger_cursor(void) { | 583 | handle_trigger_cursor(void) { |
476 | SeqTrigger *trig = &sequences[channel_selection_loc][trig_selection_loc]; | 584 | TriggerNote *trig; |
585 | switch (channel_selection_loc) { | ||
586 | case 0: { | ||
587 | trig = &ch1.notes[trig_selection_loc]; | ||
588 | } break; | ||
589 | case 1: { | ||
590 | trig = &ch2.notes[trig_selection_loc]; | ||
591 | } break; | ||
592 | case 2: { | ||
593 | trig = &ch3.notes[trig_selection_loc]; | ||
594 | } break; | ||
595 | } | ||
477 | 596 | ||
478 | if (key_tap(KEY_B)) { | 597 | if (key_tap(KEY_B)) { |
479 | // Toggle trigger. | 598 | // Toggle trigger. |
480 | trig->trigger ^= 1; | 599 | trig->active ^= 1; |
481 | draw_trigger(channel_selection_loc, trig_selection_loc); | 600 | draw_trigger(channel_selection_loc, trig_selection_loc); |
482 | } else if (key_tap(KEY_A)) { | 601 | } else if (key_tap(KEY_A)) { |
483 | // Switch to parameter selection. | 602 | // Switch to parameter selection. |
484 | // current_selection = SEQ_SELECT_PARAMETER; | 603 | // current_selection = SEQ_SELECT_PARAMETER; |
485 | } else if (key_tap(KEY_L)) { | 604 | } else if (key_tap(KEY_L)) { |
486 | // Decrease note. | 605 | // Decrease note. |
487 | if (trig->trigger) { | 606 | if (trig->active) { |
488 | trig->note = MAX(trig->note - 1, NOTE_C_2); | 607 | trig->note = MAX(trig->note - 1, NOTE_C_2); |
489 | clear_trigger(trig_selection_loc); | 608 | clear_trigger(trig_selection_loc); |
490 | draw_trigger(channel_selection_loc, trig_selection_loc); | 609 | draw_trigger(channel_selection_loc, trig_selection_loc); |
491 | } | 610 | } |
492 | } else if (key_tap(KEY_R)) { | 611 | } else if (key_tap(KEY_R)) { |
493 | // Increase note. | 612 | // Increase note. |
494 | if (trig->trigger) { | 613 | if (trig->active) { |
495 | trig->note = MIN( trig->note + 1, NOTE_C_8); | 614 | trig->note = MIN( trig->note + 1, NOTE_C_8); |
496 | clear_trigger(trig_selection_loc); | 615 | clear_trigger(trig_selection_loc); |
497 | draw_trigger(channel_selection_loc, trig_selection_loc); | 616 | draw_trigger(channel_selection_loc, trig_selection_loc); |
@@ -738,7 +857,7 @@ load_note_names(void) { | |||
738 | 857 | ||
739 | void | 858 | void |
740 | sequencer_init(void) { | 859 | sequencer_init(void) { |
741 | // TODO: Unpack non-sprite tiles directly on the VRAM. | 860 | // Unpack non-sprite tiles directly on the VRAM. |
742 | load_note_names(); | 861 | load_note_names(); |
743 | 862 | ||
744 | // Initialize background objects and sprites. | 863 | // Initialize background objects and sprites. |