summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2021-05-03 15:53:48 +0200
committerBad Diode <bd@badd10de.dev>2021-05-03 15:53:48 +0200
commit400b50baed8125a482895fa7534526c40cfd97af (patch)
treee27b811dfe29a4758ea968861a86fb4652bee039
parent60953849bb18c1719f6c90de5e48084efae71592 (diff)
downloadgba-experiments-400b50baed8125a482895fa7534526c40cfd97af.tar.gz
gba-experiments-400b50baed8125a482895fa7534526c40cfd97af.zip
Add sweep in UI and parameter controls
-rw-r--r--src/common.h9
-rw-r--r--src/main.c5
-rw-r--r--src/sequencer.c440
3 files changed, 376 insertions, 78 deletions
diff --git a/src/common.h b/src/common.h
index b688711..d78f11a 100644
--- a/src/common.h
+++ b/src/common.h
@@ -105,7 +105,7 @@ rgb15(u32 red, u32 green, u32 blue ) {
105#define COLOR_RED rgb15(31, 0, 12) 105#define COLOR_RED rgb15(31, 0, 12)
106#define COLOR_BLUE rgb15(2, 15, 30) 106#define COLOR_BLUE rgb15(2, 15, 30)
107#define COLOR_CYAN rgb15(0, 30, 30) 107#define COLOR_CYAN rgb15(0, 30, 30)
108#define COLOR_GREY rgb15(4, 4, 4) 108#define COLOR_GREY rgb15(12, 12, 12)
109#define COLOR_BLACK rgb15(0, 0, 0) 109#define COLOR_BLACK rgb15(0, 0, 0)
110#define COLOR_WHITE rgb15(28, 28, 28) 110#define COLOR_WHITE rgb15(28, 28, 28)
111 111
@@ -594,9 +594,14 @@ sound_volume(SoundChannel channels, u8 volume) {
594#define SOUND_SQUARE_LEN(N) (N) 594#define SOUND_SQUARE_LEN(N) (N)
595#define SOUND_SQUARE_DUTY(N) ((N) << 0x6) 595#define SOUND_SQUARE_DUTY(N) ((N) << 0x6)
596#define SOUND_SQUARE_ENV_TIME(N) ((N) << 0x8) 596#define SOUND_SQUARE_ENV_TIME(N) ((N) << 0x8)
597#define SOUND_SQUARE_ENV_INC(N) ((N) << 0xB) 597#define SOUND_SQUARE_ENV_DIR(N) ((N) << 0xB)
598#define SOUND_SQUARE_ENV_VOL(N) ((N) << 0xC) 598#define SOUND_SQUARE_ENV_VOL(N) ((N) << 0xC)
599 599
600// DMG square 1 sweep control bits.
601#define SOUND_SWEEP_NUMBER(N) (N)
602#define SOUND_SWEEP_DIR(N) ((N) << 0x3)
603#define SOUND_SWEEP_TIME(N) ((N) << 0x4)
604
600// DMG square frequency bits. 605// DMG square frequency bits.
601#define SOUND_SQUARE_TIMED (1 << 0xE) 606#define SOUND_SQUARE_TIMED (1 << 0xE)
602#define SOUND_SQUARE_RESET (1 << 0xF) 607#define SOUND_SQUARE_RESET (1 << 0xF)
diff --git a/src/main.c b/src/main.c
index d64208e..b93abe6 100644
--- a/src/main.c
+++ b/src/main.c
@@ -20,11 +20,6 @@ int main(void) {
20 // sequential. 20 // sequential.
21 DISP_CTRL = DISP_ENABLE_SPRITES | DISP_MODE_0 | DISP_BG_0; 21 DISP_CTRL = DISP_ENABLE_SPRITES | DISP_MODE_0 | DISP_BG_0;
22 22
23 // Initialize sprite button overlay.
24 init_sprite_pal(0, COLOR_WHITE);
25 init_sprite_pal(16, COLOR_CYAN);
26 init_sprite_pal(32, COLOR_RED);
27 init_sprites(0);
28 init_sequencer_sprites(); 23 init_sequencer_sprites();
29 24
30 // Initialize text engine. 25 // Initialize text engine.
diff --git a/src/sequencer.c b/src/sequencer.c
index 5db1b5d..b55ceca 100644
--- a/src/sequencer.c
+++ b/src/sequencer.c
@@ -101,7 +101,7 @@ u32 sprite_env_label_volume[] = {
101 0xaaeaaaaa, 0xae000000, 0x0e020602, 0x0e000000, 101 0xaaeaaaaa, 0xae000000, 0x0e020602, 0x0e000000,
102}; 102};
103 103
104u32 sprite_env_label_time[] = { 104u32 sprite_env_sweep_label_time[] = {
105 0x00000000, 0x00000000, 0xee444444, 0xe4000000, 105 0x00000000, 0x00000000, 0xee444444, 0xe4000000,
106 0xea2e6a2a, 0xea000000, 0x00000000, 0x00000000, 106 0xea2e6a2a, 0xea000000, 0x00000000, 0x00000000,
107}; 107};
@@ -116,6 +116,16 @@ u32 sprite_env_label_env[] = {
116 0x62a2a2a2, 0xee000000, 0xee2a6e22, 0xe2000000, 116 0x62a2a2a2, 0xee000000, 0xee2a6e22, 0xe2000000,
117}; 117};
118 118
119u32 sprite_sweep_number_label[] = {
120 0x60a0a0a0, 0xa0000000, 0xaaeaaaaa, 0xae000000,
121 0xee2a662a, 0xee000000, 0x0e0a060a, 0x0a000000,
122};
123
124u32 sprite_sweep_label[] = {
125 0x8040c000, 0xc0000000, 0xa5a4a5b5, 0xa8000000,
126 0xbb889988, 0xbb000000, 0x03020300, 0x00000000,
127};
128
119u32 sprite_duty_cycle_label[] = { 129u32 sprite_duty_cycle_label[] = {
120 0x00000000, 0x00000080, 0xa6aaaaaa, 0xe60000ab, 130 0x00000000, 0x00000080, 0xa6aaaaaa, 0xe60000ab,
121 0xaea4e444, 0x4400008b, 0x00000000, 0x00000003, 131 0xaea4e444, 0x4400008b, 0x00000000, 0x00000003,
@@ -195,6 +205,25 @@ u32 sprite_env_sweep_direction[] = {
195 0xb2b2b2b2, 0xb2ba9400, 0x0d0f0e0c, 0x0c0c0c00, 205 0xb2b2b2b2, 0xb2ba9400, 0x0d0f0e0c, 0x0c0c0c00,
196}; 206};
197 207
208u32 sprite_sweep_time_number[] = {
209 0x7c646464, 0x64647c00, 0x18181818, 0x18181800,
210 0x7c60607c, 0x0c0c7c00, 0x7c606078, 0x60607c00,
211 0x60706864, 0x7c606000, 0x7c0c0c7c, 0x60607c00,
212 0x7c0c0c7c, 0x4c4c7c00, 0x7c606030, 0x180c0c00,
213};
214
215u32 sprite_synth_param_selector[] = {
216 0x07010100, 0x00000000, 0x00000000, 0x00000000,
217 0x00000000, 0x00000000, 0xe0808000, 0x00000000,
218 0x00000000, 0x00000000, 0x00000000, 0x00000000,
219 0x00000000, 0x00000000, 0x00000000, 0x00000000,
220 0x00000101, 0x07000000, 0x00000000, 0x00000000,
221 0x00000000, 0x00000000, 0x00008080, 0xe0000000,
222 0x00000000, 0x00000000, 0x00000000, 0x00000000,
223 0x00000000, 0x00000000, 0x00000000, 0x00000000,
224};
225
226
198typedef struct SeqTrigger { 227typedef struct SeqTrigger {
199 bool trigger; 228 bool trigger;
200 Note note; 229 Note note;
@@ -202,29 +231,32 @@ typedef struct SeqTrigger {
202 u8 env_time; 231 u8 env_time;
203 u8 env_direction; 232 u8 env_direction;
204 u8 duty_cycle; 233 u8 duty_cycle;
234 u8 sweep_number;
235 u8 sweep_time;
236 u8 sweep_direction;
205 // TODO: ... 237 // TODO: ...
206} SeqTrigger; 238} SeqTrigger;
207 239
208static SeqTrigger sequence_synth[] = { 240static SeqTrigger sequence_synth[] = {
209 {true , NOTE_D_4 , 0, 0, 0, 0}, 241 {true , NOTE_D_4 , 0, 0, 0, 0, 0, 0, 0},
210 {true , NOTE_F_4 , 1, 1, 0, 0}, 242 {true , NOTE_F_4 , 1, 1, 0, 0, 1, 1, 0},
211 {true , NOTE_A_4 , 2, 2, 0, 1}, 243 {true , NOTE_A_4 , 2, 2, 0, 1, 2, 2, 1},
212 {true , NOTE_C_5 , 3, 3, 0, 1}, 244 {true , NOTE_C_5 , 3, 3, 0, 1, 3, 3, 1},
213 245
214 {true , NOTE_D_4 , 4, 4, 1, 2}, 246 {true , NOTE_D_4 , 4, 4, 1, 2, 4, 4, 0},
215 {false , NOTE_C_SHARP_4 , 5, 5, 1, 2}, 247 {false , NOTE_C_SHARP_4 , 5, 5, 1, 2, 5, 5, 0},
216 {false , NOTE_D_4 , 6, 6, 1, 3}, 248 {false , NOTE_D_4 , 6, 6, 1, 3, 6, 6, 1},
217 {false , NOTE_D_4 , 7, 7, 1, 3}, 249 {false , NOTE_D_4 , 7, 7, 1, 3, 7, 7, 1},
218 250
219 {true , NOTE_D_4 , 8, 0, 0, 0}, 251 {true , NOTE_D_4 , 8, 0, 0, 0, 7, 0, 0},
220 {true , NOTE_F_4 , 9, 1, 0, 0}, 252 {true , NOTE_F_4 , 9, 1, 0, 0, 6, 1, 0},
221 {true , NOTE_A_4 , 10, 2, 0, 1}, 253 {true , NOTE_A_4 , 10, 2, 0, 1, 5, 2, 1},
222 {true , NOTE_C_5 , 11, 3, 0, 1}, 254 {true , NOTE_C_5 , 11, 3, 0, 1, 4, 3, 1},
223 255
224 {true , NOTE_D_4 , 12, 4, 1, 2}, 256 {true , NOTE_D_4 , 12, 4, 1, 2, 3, 4, 0},
225 {false , NOTE_D_4 , 13, 5, 1, 2}, 257 {false , NOTE_D_4 , 13, 5, 1, 2, 2, 5, 0},
226 {true , NOTE_A_4 , 14, 6, 1, 3}, 258 {true , NOTE_A_4 , 14, 6, 1, 3, 1, 6, 1},
227 {false , NOTE_A_5 , 15, 7, 1, 3}, 259 {false , NOTE_A_5 , 15, 7, 1, 3, 0, 7, 1},
228}; 260};
229 261
230static int bpm = 120; 262static int bpm = 120;
@@ -236,11 +268,15 @@ irq_timer_0(void) {
236 SeqTrigger *trig = &sequence_synth[step_counter]; 268 SeqTrigger *trig = &sequence_synth[step_counter];
237 active_note = trig->note; 269 active_note = trig->note;
238 if (trig->trigger) { 270 if (trig->trigger) {
271 SOUND_SQUARE1_SWEEP = SOUND_SWEEP_NUMBER(trig->sweep_number)
272 | SOUND_SWEEP_DIR(trig->sweep_direction)
273 | SOUND_SWEEP_TIME(trig->sweep_time);
239 SOUND_SQUARE1_CTRL = SOUND_SQUARE_ENV_VOL(trig->env_volume) 274 SOUND_SQUARE1_CTRL = SOUND_SQUARE_ENV_VOL(trig->env_volume)
240 | SOUND_SQUARE_ENV_TIME(trig->env_time) 275 | SOUND_SQUARE_ENV_TIME(trig->env_time)
241 | SOUND_SQUARE_ENV_INC(trig->env_direction) 276 | SOUND_SQUARE_ENV_DIR(trig->env_direction)
242 | SOUND_SQUARE_DUTY(trig->duty_cycle); 277 | SOUND_SQUARE_DUTY(trig->duty_cycle);
243 SOUND_SQUARE1_FREQ = SOUND_SQUARE_RESET | sound_rates[active_note]; 278 SOUND_SQUARE1_FREQ = SOUND_SQUARE_RESET
279 | sound_rates[active_note];
244 } 280 }
245 step_counter = (step_counter + 1) % 16; 281 step_counter = (step_counter + 1) % 16;
246} 282}
@@ -250,7 +286,7 @@ set_time(int bpm) {
250 // The number of ticks of a 1024 cycle clock in a step based on the BPM can 286 // The number of ticks of a 1024 cycle clock in a step based on the BPM can
251 // be calculated as: 287 // be calculated as:
252 // X bpm -> 60000 / 4 / bpm = Y ms = Ye-3 s 288 // X bpm -> 60000 / 4 / bpm = Y ms = Ye-3 s
253 // Y ms -> Ye-3 / 59.99e-9 /1024 = Z ticks 289 // Y ms -> Ye-3 / 59.99e-9 / 1024 = Z ticks
254 // We have to operate on integer values, so the numbers have been 290 // We have to operate on integer values, so the numbers have been
255 // precalculated to `n_ticks = 244181 / bmp` 291 // precalculated to `n_ticks = 244181 / bmp`
256 int n_ticks = -244181 / bpm; 292 int n_ticks = -244181 / bpm;
@@ -291,6 +327,14 @@ set_time(int bpm) {
291// - 040-040 envelope: envelope label. 327// - 040-040 envelope: envelope label.
292// - 041-041 duty-cycle label. 328// - 041-041 duty-cycle label.
293// - 042-042 duty-cycle indicator. 329// - 042-042 duty-cycle indicator.
330// - 043-043 sweep: number label.
331// - 044-044 sweep: number indicator.
332// - 045-045 sweep: time label.
333// - 046-046 sweep: time indicator.
334// - 047-047 sweep: direction label.
335// - 048-048 sweep: direction indicator.
336// - 049-049 sweep: sweep label.
337// - 050-050 synth parameter selector.
294// 338//
295 339
296 340
@@ -300,9 +344,11 @@ set_time(int bpm) {
300#define SEQ_TRIG_DIST 20 344#define SEQ_TRIG_DIST 20
301#define SEQ_ENV_POS_X 10 345#define SEQ_ENV_POS_X 10
302#define SEQ_ENV_POS_Y 10 346#define SEQ_ENV_POS_Y 10
303#define SEQ_ENV_DIST 34 347#define SEQ_ENV_DIST 32
304#define SEQ_DUTYCYCLE_POS_X SEQ_ENV_POS_X + SEQ_ENV_DIST * 3 348#define SEQ_DUTYCYCLE_POS_X SEQ_ENV_POS_X + SEQ_ENV_DIST * 3
305#define SEQ_DUTYCYCLE_POS_Y 10 - 8 349#define SEQ_DUTYCYCLE_POS_Y 10 - 8
350#define SEQ_SWEEP_POS_X SEQ_DUTYCYCLE_POS_X + SEQ_ENV_DIST
351#define SEQ_SWEEP_POS_Y SEQ_ENV_POS_Y
306 352
307size_t obj_counter = 0; 353size_t obj_counter = 0;
308 354
@@ -316,12 +362,27 @@ typedef struct SeqSprite {
316 u16 obj_attr_2; 362 u16 obj_attr_2;
317} SeqSprite; 363} SeqSprite;
318 364
319int trig_selection_loc = 1;
320 365
321SeqSprite seq_sprites[43] = {0}; 366typedef enum {
367 SEQ_SELECT_TRIGGER,
368 SEQ_SELECT_PARAMETER,
369} SeqSelect;
370
371int trig_selection_loc = 0;
372int param_selection_loc = 0;
373SeqSelect current_selection = SEQ_SELECT_TRIGGER;
374
375SeqSprite seq_sprites[51] = {0};
322 376
323void 377void
324init_sequencer_sprites(void) { 378init_sequencer_sprites(void) {
379 // Load palette.
380 init_sprite_pal(0, COLOR_WHITE);
381 init_sprite_pal(16, COLOR_CYAN);
382 init_sprite_pal(32, COLOR_RED);
383 init_sprite_pal(48, COLOR_GREY);
384 init_sprites(0);
385
325 // Sprite note names. 386 // Sprite note names.
326 size_t sprite_id = load_packed_sprite_data(&sprite_note_names, 2, 73); 387 size_t sprite_id = load_packed_sprite_data(&sprite_note_names, 2, 73);
327 for (size_t i = 0; i < 16; ++i) { 388 for (size_t i = 0; i < 16; ++i) {
@@ -396,7 +457,7 @@ init_sequencer_sprites(void) {
396 seq_sprites[34].base_tile = base_tile; 457 seq_sprites[34].base_tile = base_tile;
397 seq_sprites[34].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y); 458 seq_sprites[34].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y);
398 seq_sprites[34].obj_attr_1 = OBJ_SIZE_MID | OBJ_X_COORD(x); 459 seq_sprites[34].obj_attr_1 = OBJ_SIZE_MID | OBJ_X_COORD(x);
399 seq_sprites[34].obj_attr_2 = base_tile | OBJ_PAL_BANK(2); 460 seq_sprites[34].obj_attr_2 = base_tile;
400 } 461 }
401 462
402 sprite_id = load_packed_sprite_data(&sprite_env_volume, 4, 16); 463 sprite_id = load_packed_sprite_data(&sprite_env_volume, 4, 16);
@@ -408,10 +469,10 @@ init_sequencer_sprites(void) {
408 seq_sprites[35].base_tile = base_tile; 469 seq_sprites[35].base_tile = base_tile;
409 seq_sprites[35].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y); 470 seq_sprites[35].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y);
410 seq_sprites[35].obj_attr_1 = OBJ_SIZE_MID | OBJ_X_COORD(x); 471 seq_sprites[35].obj_attr_1 = OBJ_SIZE_MID | OBJ_X_COORD(x);
411 seq_sprites[35].obj_attr_2 = base_tile | OBJ_PAL_BANK(2); 472 seq_sprites[35].obj_attr_2 = base_tile;
412 } 473 }
413 474
414 sprite_id = load_packed_sprite_data(&sprite_env_label_time, 4, 1); 475 sprite_id = load_packed_sprite_data(&sprite_env_sweep_label_time, 4, 1);
415 { 476 {
416 int x = SEQ_ENV_POS_X + SEQ_ENV_DIST; 477 int x = SEQ_ENV_POS_X + SEQ_ENV_DIST;
417 int y = SEQ_ENV_POS_Y; 478 int y = SEQ_ENV_POS_Y;
@@ -420,7 +481,17 @@ init_sequencer_sprites(void) {
420 seq_sprites[36].base_tile = base_tile; 481 seq_sprites[36].base_tile = base_tile;
421 seq_sprites[36].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y); 482 seq_sprites[36].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y);
422 seq_sprites[36].obj_attr_1 = OBJ_SIZE_MID | OBJ_X_COORD(x); 483 seq_sprites[36].obj_attr_1 = OBJ_SIZE_MID | OBJ_X_COORD(x);
423 seq_sprites[36].obj_attr_2 = base_tile | OBJ_PAL_BANK(2); 484 seq_sprites[36].obj_attr_2 = base_tile;
485 }
486 {
487 int x = SEQ_SWEEP_POS_X + SEQ_ENV_DIST;
488 int y = SEQ_SWEEP_POS_Y;
489 int base_tile = sprites[sprite_id].tile_start;
490 seq_sprites[45].id = obj_counter++;
491 seq_sprites[45].base_tile = base_tile;
492 seq_sprites[45].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y);
493 seq_sprites[45].obj_attr_1 = OBJ_SIZE_MID | OBJ_X_COORD(x);
494 seq_sprites[45].obj_attr_2 = base_tile;
424 } 495 }
425 496
426 sprite_id = load_packed_sprite_data(&sprite_env_time, 4, 8); 497 sprite_id = load_packed_sprite_data(&sprite_env_time, 4, 8);
@@ -432,7 +503,7 @@ init_sequencer_sprites(void) {
432 seq_sprites[37].base_tile = base_tile; 503 seq_sprites[37].base_tile = base_tile;
433 seq_sprites[37].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y); 504 seq_sprites[37].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y);
434 seq_sprites[37].obj_attr_1 = OBJ_SIZE_MID | OBJ_X_COORD(x); 505 seq_sprites[37].obj_attr_1 = OBJ_SIZE_MID | OBJ_X_COORD(x);
435 seq_sprites[37].obj_attr_2 = base_tile | OBJ_PAL_BANK(2); 506 seq_sprites[37].obj_attr_2 = base_tile;
436 } 507 }
437 508
438 sprite_id = load_packed_sprite_data(&sprite_env_label_direction, 4, 1); 509 sprite_id = load_packed_sprite_data(&sprite_env_label_direction, 4, 1);
@@ -444,7 +515,17 @@ init_sequencer_sprites(void) {
444 seq_sprites[38].base_tile = base_tile; 515 seq_sprites[38].base_tile = base_tile;
445 seq_sprites[38].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y); 516 seq_sprites[38].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y);
446 seq_sprites[38].obj_attr_1 = OBJ_SIZE_MID | OBJ_X_COORD(x); 517 seq_sprites[38].obj_attr_1 = OBJ_SIZE_MID | OBJ_X_COORD(x);
447 seq_sprites[38].obj_attr_2 = base_tile | OBJ_PAL_BANK(2); 518 seq_sprites[38].obj_attr_2 = base_tile;
519 }
520 {
521 int x = SEQ_SWEEP_POS_X + SEQ_ENV_DIST * 2;
522 int y = SEQ_SWEEP_POS_Y;
523 int base_tile = sprites[sprite_id].tile_start;
524 seq_sprites[47].id = obj_counter++;
525 seq_sprites[47].base_tile = base_tile;
526 seq_sprites[47].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y);
527 seq_sprites[47].obj_attr_1 = OBJ_SIZE_MID | OBJ_X_COORD(x);
528 seq_sprites[47].obj_attr_2 = base_tile;
448 } 529 }
449 530
450 sprite_id = load_packed_sprite_data(&sprite_env_sweep_direction, 4, 2); 531 sprite_id = load_packed_sprite_data(&sprite_env_sweep_direction, 4, 2);
@@ -456,19 +537,29 @@ init_sequencer_sprites(void) {
456 seq_sprites[39].base_tile = base_tile; 537 seq_sprites[39].base_tile = base_tile;
457 seq_sprites[39].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y); 538 seq_sprites[39].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y);
458 seq_sprites[39].obj_attr_1 = OBJ_SIZE_MID | OBJ_X_COORD(x); 539 seq_sprites[39].obj_attr_1 = OBJ_SIZE_MID | OBJ_X_COORD(x);
459 seq_sprites[39].obj_attr_2 = base_tile | OBJ_PAL_BANK(2); 540 seq_sprites[39].obj_attr_2 = base_tile;
541 }
542 {
543 int x = SEQ_SWEEP_POS_X + SEQ_ENV_DIST * 2;
544 int y = SEQ_SWEEP_POS_Y + 8;
545 int base_tile = sprites[sprite_id].tile_start;
546 seq_sprites[48].id = obj_counter++;
547 seq_sprites[48].base_tile = base_tile;
548 seq_sprites[48].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y);
549 seq_sprites[48].obj_attr_1 = OBJ_SIZE_MID | OBJ_X_COORD(x);
550 seq_sprites[48].obj_attr_2 = base_tile;
460 } 551 }
461 552
462 sprite_id = load_packed_sprite_data(&sprite_env_label_env, 4, 1); 553 sprite_id = load_packed_sprite_data(&sprite_env_label_env, 4, 1);
463 { 554 {
464 int x = SEQ_ENV_POS_X + SEQ_ENV_DIST; 555 int x = SEQ_ENV_POS_X + SEQ_ENV_DIST;
465 int y = SEQ_ENV_POS_Y - 8; 556 int y = SEQ_ENV_POS_Y - 10;
466 int base_tile = sprites[sprite_id].tile_start; 557 int base_tile = sprites[sprite_id].tile_start;
467 seq_sprites[40].id = obj_counter++; 558 seq_sprites[40].id = obj_counter++;
468 seq_sprites[40].base_tile = base_tile; 559 seq_sprites[40].base_tile = base_tile;
469 seq_sprites[40].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y); 560 seq_sprites[40].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y);
470 seq_sprites[40].obj_attr_1 = OBJ_SIZE_MID | OBJ_X_COORD(x); 561 seq_sprites[40].obj_attr_1 = OBJ_SIZE_MID | OBJ_X_COORD(x);
471 seq_sprites[40].obj_attr_2 = base_tile | OBJ_PAL_BANK(2); 562 seq_sprites[40].obj_attr_2 = base_tile;
472 } 563 }
473 564
474 sprite_id = load_packed_sprite_data(&sprite_duty_cycle_label, 8, 1); 565 sprite_id = load_packed_sprite_data(&sprite_duty_cycle_label, 8, 1);
@@ -480,8 +571,9 @@ init_sequencer_sprites(void) {
480 seq_sprites[41].base_tile = base_tile; 571 seq_sprites[41].base_tile = base_tile;
481 seq_sprites[41].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y); 572 seq_sprites[41].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y);
482 seq_sprites[41].obj_attr_1 = OBJ_SIZE_BIG | OBJ_X_COORD(x); 573 seq_sprites[41].obj_attr_1 = OBJ_SIZE_BIG | OBJ_X_COORD(x);
483 seq_sprites[41].obj_attr_2 = base_tile | OBJ_PAL_BANK(2); 574 seq_sprites[41].obj_attr_2 = base_tile;
484 } 575 }
576
485 sprite_id = load_packed_sprite_data(&sprite_duty_cycle, 4, 4); 577 sprite_id = load_packed_sprite_data(&sprite_duty_cycle, 4, 4);
486 { 578 {
487 int x = SEQ_DUTYCYCLE_POS_X; 579 int x = SEQ_DUTYCYCLE_POS_X;
@@ -491,7 +583,65 @@ init_sequencer_sprites(void) {
491 seq_sprites[42].base_tile = base_tile; 583 seq_sprites[42].base_tile = base_tile;
492 seq_sprites[42].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y); 584 seq_sprites[42].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y);
493 seq_sprites[42].obj_attr_1 = OBJ_SIZE_MID | OBJ_X_COORD(x); 585 seq_sprites[42].obj_attr_1 = OBJ_SIZE_MID | OBJ_X_COORD(x);
494 seq_sprites[42].obj_attr_2 = base_tile | OBJ_PAL_BANK(2); 586 seq_sprites[42].obj_attr_2 = base_tile;
587 }
588
589 sprite_id = load_packed_sprite_data(&sprite_sweep_number_label, 4, 1);
590 {
591 int x = SEQ_SWEEP_POS_X;
592 int y = SEQ_SWEEP_POS_Y;
593 int base_tile = sprites[sprite_id].tile_start;
594 seq_sprites[43].id = obj_counter++;
595 seq_sprites[43].base_tile = base_tile;
596 seq_sprites[43].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y);
597 seq_sprites[43].obj_attr_1 = OBJ_SIZE_MID | OBJ_X_COORD(x);
598 seq_sprites[43].obj_attr_2 = base_tile;
599 }
600
601 sprite_id = load_packed_sprite_data(&sprite_sweep_time_number, 1, 8);
602 {
603 int x = SEQ_SWEEP_POS_X + 12;
604 int y = SEQ_SWEEP_POS_Y + 8;
605 int base_tile = sprites[sprite_id].tile_start;
606 seq_sprites[44].id = obj_counter++;
607 seq_sprites[44].base_tile = base_tile;
608 seq_sprites[44].obj_attr_0 = OBJ_SHAPE_SQUARE | OBJ_Y_COORD(y);
609 seq_sprites[44].obj_attr_1 = OBJ_SIZE_SMALL | OBJ_X_COORD(x);
610 seq_sprites[44].obj_attr_2 = base_tile;
611 }
612 {
613 int x = SEQ_SWEEP_POS_X + 12 + SEQ_ENV_DIST;
614 int y = SEQ_SWEEP_POS_Y + 8;
615 int base_tile = sprites[sprite_id].tile_start;
616 seq_sprites[46].id = obj_counter++;
617 seq_sprites[46].base_tile = base_tile;
618 seq_sprites[46].obj_attr_0 = OBJ_SHAPE_SQUARE | OBJ_Y_COORD(y);
619 seq_sprites[46].obj_attr_1 = OBJ_SIZE_SMALL | OBJ_X_COORD(x);
620 seq_sprites[46].obj_attr_2 = base_tile;
621 }
622
623 sprite_id = load_packed_sprite_data(&sprite_sweep_label, 4, 1);
624 {
625 int x = SEQ_SWEEP_POS_X + SEQ_ENV_DIST;
626 int y = SEQ_SWEEP_POS_Y - 10;
627 int base_tile = sprites[sprite_id].tile_start;
628 seq_sprites[49].id = obj_counter++;
629 seq_sprites[49].base_tile = base_tile;
630 seq_sprites[49].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y);
631 seq_sprites[49].obj_attr_1 = OBJ_SIZE_MID | OBJ_X_COORD(x);
632 seq_sprites[49].obj_attr_2 = base_tile;
633 }
634
635 sprite_id = load_packed_sprite_data(&sprite_synth_param_selector, 16, 1);
636 {
637 int x = SEQ_ENV_POS_X + 1;
638 int y = SEQ_ENV_POS_Y - 3;
639 int base_tile = sprites[sprite_id].tile_start;
640 seq_sprites[50].id = obj_counter++;
641 seq_sprites[50].base_tile = base_tile;
642 seq_sprites[50].obj_attr_0 = OBJ_SHAPE_SQUARE | OBJ_Y_COORD(y);
643 seq_sprites[50].obj_attr_1 = OBJ_SIZE_BIG | OBJ_X_COORD(x);
644 seq_sprites[50].obj_attr_2 = base_tile | OBJ_PAL_BANK(2);
495 } 645 }
496} 646}
497 647
@@ -534,79 +684,227 @@ update_sequencer_sprites(void) {
534 y += 32; 684 y += 32;
535 x -= 8 * SEQ_TRIG_DIST; 685 x -= 8 * SEQ_TRIG_DIST;
536 } 686 }
537 // TODO: Mask and update instead.
538 seq_sprites[33].obj_attr_0 = OBJ_SHAPE_SQUARE | OBJ_Y_COORD(y); 687 seq_sprites[33].obj_attr_0 = OBJ_SHAPE_SQUARE | OBJ_Y_COORD(y);
539 seq_sprites[33].obj_attr_1 = OBJ_SIZE_BIG | OBJ_X_COORD(x); 688 seq_sprites[33].obj_attr_1 = OBJ_SIZE_BIG | OBJ_X_COORD(x);
689 int base_tile = seq_sprites[33].base_tile;
690 if (current_selection == SEQ_SELECT_TRIGGER) {
691 seq_sprites[33].obj_attr_2 = base_tile | OBJ_PAL_BANK(2);
692 } else {
693 seq_sprites[33].obj_attr_2 = base_tile | OBJ_PAL_BANK(3);
694 }
540 } 695 }
541 696
542 // 36: Envelope initial volume 697 // 36: Envelope initial volume.
543 { 698 {
544 size_t tile_diff = sequence_synth[trig_selection_loc].env_volume * 4; 699 size_t tile_diff = sequence_synth[trig_selection_loc].env_volume * 4;
545 size_t base_tile = seq_sprites[35].base_tile; 700 size_t base_tile = seq_sprites[35].base_tile;
546 size_t tile = base_tile + tile_diff; 701 size_t tile = base_tile + tile_diff;
547 seq_sprites[35].obj_attr_2 = tile | OBJ_PAL_BANK(2); 702 seq_sprites[35].obj_attr_2 = tile;
548 } 703 }
549 704
550 // 38: Envelope initial volume 705 // 38: Envelope time.
551 { 706 {
552 size_t tile_diff = sequence_synth[trig_selection_loc].env_time * 4; 707 size_t tile_diff = sequence_synth[trig_selection_loc].env_time * 4;
553 size_t base_tile = seq_sprites[37].base_tile; 708 size_t base_tile = seq_sprites[37].base_tile;
554 size_t tile = base_tile + tile_diff; 709 size_t tile = base_tile + tile_diff;
555 seq_sprites[37].obj_attr_2 = tile | OBJ_PAL_BANK(2); 710 seq_sprites[37].obj_attr_2 = tile;
556 } 711 }
557 712
558 // 40: Envelope initial volume 713 // 40: Envelope direction.
559 { 714 {
560 size_t tile_diff = sequence_synth[trig_selection_loc].env_direction * 4; 715 size_t tile_diff = 0;
716 if (sequence_synth[trig_selection_loc].env_direction == 0) {
717 tile_diff = 4;
718 }
561 size_t base_tile = seq_sprites[39].base_tile; 719 size_t base_tile = seq_sprites[39].base_tile;
562 size_t tile = base_tile + tile_diff; 720 size_t tile = base_tile + tile_diff;
563 seq_sprites[39].obj_attr_2 = tile | OBJ_PAL_BANK(2); 721 seq_sprites[39].obj_attr_2 = tile;
564 } 722 }
565 723
566 // 43: Envelope initial volume 724 // 43: Duty cycle.
567 { 725 {
568 size_t tile_diff = sequence_synth[trig_selection_loc].duty_cycle * 4; 726 size_t tile_diff = sequence_synth[trig_selection_loc].duty_cycle * 4;
569 size_t base_tile = seq_sprites[42].base_tile; 727 size_t base_tile = seq_sprites[42].base_tile;
570 size_t tile = base_tile + tile_diff; 728 size_t tile = base_tile + tile_diff;
571 seq_sprites[42].obj_attr_2 = tile | OBJ_PAL_BANK(2); 729 seq_sprites[42].obj_attr_2 = tile;
730 }
731
732 // 45: Sweep number.
733 {
734 size_t tile_diff = sequence_synth[trig_selection_loc].sweep_number;
735 size_t base_tile = seq_sprites[44].base_tile;
736 size_t tile = base_tile + tile_diff;
737 seq_sprites[44].obj_attr_2 = tile;
738 }
739
740 // 47: Sweep time.
741 {
742 size_t tile_diff = sequence_synth[trig_selection_loc].sweep_time;
743 size_t base_tile = seq_sprites[46].base_tile;
744 size_t tile = base_tile + tile_diff;
745 seq_sprites[46].obj_attr_2 = tile;
746 }
747
748 // 49: Sweep direction.
749 {
750 size_t tile_diff = sequence_synth[trig_selection_loc].sweep_direction * 4;
751 size_t base_tile = seq_sprites[48].base_tile;
752 size_t tile = base_tile + tile_diff;
753 seq_sprites[48].obj_attr_2 = tile;
754 }
755
756 // 51: Parameter selector.
757 {
758 int x = SEQ_ENV_POS_X + 1 + (param_selection_loc % 7) * SEQ_ENV_DIST;
759 int y = SEQ_ENV_POS_Y - 2;
760 if (param_selection_loc >= 8) {
761 y += 32;
762 x -= 8 * SEQ_TRIG_DIST;
763 }
764 int hidden = 0;
765 if (current_selection != SEQ_SELECT_PARAMETER) {
766 hidden = OBJ_HIDDEN;
767 }
768 seq_sprites[50].obj_attr_0 = OBJ_SHAPE_SQUARE | OBJ_Y_COORD(y) | hidden;
769 seq_sprites[50].obj_attr_1 = OBJ_SIZE_BIG | OBJ_X_COORD(x);
572 } 770 }
573} 771}
574 772
575void 773void
576handle_sequencer_input(void) { 774handle_sequencer_input(void) {
577 if (key_pressed(KEY_LEFT)) { 775 if (current_selection == SEQ_SELECT_TRIGGER) {
578 if (trig_selection_loc == 0) { 776 if (key_pressed(KEY_LEFT)) {
579 trig_selection_loc = 15; 777 if (trig_selection_loc == 0) {
580 } else { 778 trig_selection_loc = 15;
581 trig_selection_loc = CLAMP(trig_selection_loc - 1, 0, 15); 779 } else {
780 trig_selection_loc = CLAMP(trig_selection_loc - 1, 0, 15);
781 }
582 } 782 }
583 } 783 if (key_pressed(KEY_RIGHT)) {
584 if (key_pressed(KEY_RIGHT)) { 784 if (trig_selection_loc == 15) {
585 if (trig_selection_loc == 15) { 785 trig_selection_loc = 0;
586 trig_selection_loc = 0; 786 } else {
587 } else { 787 trig_selection_loc = CLAMP(trig_selection_loc + 1, 0, 15);
588 trig_selection_loc = CLAMP(trig_selection_loc + 1, 0, 15); 788 }
789 }
790 if (key_pressed(KEY_UP) || key_pressed(KEY_DOWN)) {
791 trig_selection_loc = (trig_selection_loc + 8) % 16;
792 }
793 if (key_pressed(KEY_B)) {
794 sequence_synth[trig_selection_loc].trigger ^= 1;
795 }
796 if (key_pressed(KEY_L)) {
797 sequence_synth[trig_selection_loc].note = CLAMP(sequence_synth[trig_selection_loc].note - 1, NOTE_C_2, NOTE_C_8);
798 }
799 if (key_pressed(KEY_R)) {
800 sequence_synth[trig_selection_loc].note = CLAMP(sequence_synth[trig_selection_loc].note + 1, NOTE_C_2, NOTE_C_8);
801 }
802
803 // Switch to parameter selection.
804 if (key_pressed(KEY_A)) {
805 current_selection = SEQ_SELECT_PARAMETER;
806 }
807 } else if (current_selection == SEQ_SELECT_PARAMETER) {
808 // Move through the selected synth parameters.
809 if (key_pressed(KEY_LEFT)) {
810 if (param_selection_loc == 0) {
811 param_selection_loc = 6;
812 } else {
813 param_selection_loc = CLAMP(param_selection_loc - 1, 0, 6);
814 }
815 }
816 if (key_pressed(KEY_RIGHT)) {
817 if (param_selection_loc == 6) {
818 param_selection_loc = 0;
819 } else {
820 param_selection_loc = CLAMP(param_selection_loc + 1, 0, 6);
821 }
822 }
823
824 // Adjust the parameters up or down.
825 if (key_pressed(KEY_L)) {
826 switch (param_selection_loc) {
827 case 0: {
828 sequence_synth[trig_selection_loc].env_volume = CLAMP(
829 sequence_synth[trig_selection_loc].env_volume - 1, 0, 15);
830 } break;
831 case 1: {
832 sequence_synth[trig_selection_loc].env_time = CLAMP(
833 sequence_synth[trig_selection_loc].env_time - 1, 0, 7);
834 } break;
835 case 2: {
836 sequence_synth[trig_selection_loc].env_direction ^= 1;
837 } break;
838 case 3: {
839 sequence_synth[trig_selection_loc].duty_cycle = CLAMP(
840 sequence_synth[trig_selection_loc].duty_cycle - 1, 0, 3);
841 } break;
842 case 4: {
843 sequence_synth[trig_selection_loc].sweep_number = CLAMP(
844 sequence_synth[trig_selection_loc].sweep_number - 1, 0, 7);
845 } break;
846 case 5: {
847 sequence_synth[trig_selection_loc].sweep_time = CLAMP(
848 sequence_synth[trig_selection_loc].sweep_time - 1, 0, 7);
849 } break;
850 case 6: {
851 if (sequence_synth[trig_selection_loc].sweep_direction == 0) {
852 sequence_synth[trig_selection_loc].sweep_direction = 1;
853 } else {
854 sequence_synth[trig_selection_loc].sweep_direction = 0;
855 }
856 } break;
857 }
858 }
859 if (key_pressed(KEY_R)) {
860 switch (param_selection_loc) {
861 case 0: {
862 sequence_synth[trig_selection_loc].env_volume = CLAMP(
863 sequence_synth[trig_selection_loc].env_volume + 1, 0, 15);
864 } break;
865 case 1: {
866 sequence_synth[trig_selection_loc].env_time = CLAMP(
867 sequence_synth[trig_selection_loc].env_time + 1, 0, 7);
868 } break;
869 case 2: {
870 sequence_synth[trig_selection_loc].env_direction ^= 1;
871 } break;
872 case 3: {
873 sequence_synth[trig_selection_loc].duty_cycle = CLAMP(
874 sequence_synth[trig_selection_loc].duty_cycle + 1, 0, 3);
875 } break;
876 case 4: {
877 sequence_synth[trig_selection_loc].sweep_number = CLAMP(
878 sequence_synth[trig_selection_loc].sweep_number + 1, 0, 7);
879 } break;
880 case 5: {
881 sequence_synth[trig_selection_loc].sweep_time = CLAMP(
882 sequence_synth[trig_selection_loc].sweep_time + 1, 0, 7);
883 } break;
884 case 6: {
885 sequence_synth[trig_selection_loc].sweep_direction ^= 1;
886 } break;
887 }
888 }
889
890 // Go back to trigger selection.
891 if (key_pressed(KEY_A)) {
892 current_selection = SEQ_SELECT_TRIGGER;
589 } 893 }
590 }
591 if (key_pressed(KEY_UP) || key_pressed(KEY_DOWN)) {
592 trig_selection_loc = (trig_selection_loc + 8) % 16;
593 }
594 if (key_pressed(KEY_B)) {
595 sequence_synth[trig_selection_loc].trigger ^= 1;
596 }
597 if (key_pressed(KEY_L)) {
598 sequence_synth[trig_selection_loc].note = CLAMP(sequence_synth[trig_selection_loc].note - 1, NOTE_C_2, NOTE_C_8);
599 }
600 if (key_pressed(KEY_R)) {
601 sequence_synth[trig_selection_loc].note = CLAMP(sequence_synth[trig_selection_loc].note + 1, NOTE_C_2, NOTE_C_8);
602 } 894 }
603 895
604 if (key_pressed(KEY_START)) { 896 if (key_pressed(KEY_START)) {
605 step_counter = 0; 897 step_counter = 0;
606 set_time(bpm); 898 if ((TIMER_CTRL_0 & TIMER_CTRL_ENABLE) == 0) {
899 set_time(bpm);
900 } else {
901 TIMER_CTRL_0 ^= TIMER_CTRL_ENABLE;
902 SOUND_SQUARE1_CTRL = 0;
903 }
607 } 904 }
608 if (key_pressed(KEY_SELECT)) { 905 if (key_pressed(KEY_SELECT)) {
609 TIMER_CTRL_0 ^= TIMER_CTRL_ENABLE; 906 TIMER_CTRL_0 ^= TIMER_CTRL_ENABLE;
907 SOUND_SQUARE1_CTRL = 0;
610 } 908 }
611} 909}
612 910