summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2021-05-05 15:25:04 +0200
committerBad Diode <bd@badd10de.dev>2021-05-05 15:25:04 +0200
commit089f9ec86e90368c391c1c89e45301310cc7725a (patch)
tree5e99a6c7550433d403cb9c57d8fb496b2a541219
parente1c4894a016682aed8a0fbd3837711c6f2781876 (diff)
downloadgba-experiments-089f9ec86e90368c391c1c89e45301310cc7725a.tar.gz
gba-experiments-089f9ec86e90368c391c1c89e45301310cc7725a.zip
Add control for wave synth (channel 3)
-rw-r--r--src/common.h34
-rw-r--r--src/main.c7
-rw-r--r--src/sequencer.c73
3 files changed, 97 insertions, 17 deletions
diff --git a/src/common.h b/src/common.h
index d78f11a..f0c0886 100644
--- a/src/common.h
+++ b/src/common.h
@@ -561,8 +561,8 @@ int bios_div(int num, int denom);
561typedef enum { 561typedef enum {
562 SOUND_SQUARE1 = (0x1 << 0), 562 SOUND_SQUARE1 = (0x1 << 0),
563 SOUND_SQUARE2 = (0x1 << 1), 563 SOUND_SQUARE2 = (0x1 << 1),
564 SOUND_WAVE = (0x4 << 2), 564 SOUND_WAVE = (0x1 << 2),
565 SOUND_NOISE = (0x8 << 3), 565 SOUND_NOISE = (0x1 << 3),
566} SoundChannel; 566} SoundChannel;
567 567
568u16 568u16
@@ -602,9 +602,33 @@ sound_volume(SoundChannel channels, u8 volume) {
602#define SOUND_SWEEP_DIR(N) ((N) << 0x3) 602#define SOUND_SWEEP_DIR(N) ((N) << 0x3)
603#define SOUND_SWEEP_TIME(N) ((N) << 0x4) 603#define SOUND_SWEEP_TIME(N) ((N) << 0x4)
604 604
605// DMG square frequency bits. 605// DMG frequency bits (Square/Wave).
606#define SOUND_SQUARE_TIMED (1 << 0xE) 606#define SOUND_FREQ_TIMED (1 << 0xE)
607#define SOUND_SQUARE_RESET (1 << 0xF) 607#define SOUND_FREQ_RESET (1 << 0xF)
608
609// DMG wave ram.
610#define SOUND_WAVE_RAM_0 *((vu32*)(MEM_IO + 0x90))
611#define SOUND_WAVE_RAM_1 *((vu32*)(MEM_IO + 0x94))
612#define SOUND_WAVE_RAM_2 *((vu32*)(MEM_IO + 0x98))
613#define SOUND_WAVE_RAM_3 *((vu32*)(MEM_IO + 0x9C))
614
615// DMG wave control bits.
616#define SOUND_WAVE_LENGTH(N) (N)
617#define SOUND_WAVE_MUTE 0x0
618#define SOUND_WAVE_VOL_100 (0x1 << 0xD)
619#define SOUND_WAVE_VOL_75 (0x4 << 0xD)
620#define SOUND_WAVE_VOL_50 (0x2 << 0xD)
621#define SOUND_WAVE_VOL_25 (0x3 << 0xD)
622
623// DMG wave mode bits.
624#define SOUND_WAVE_BANK_MODE(N) ((N) << 0x5)
625#define SOUND_WAVE_BANK_SELECT(N) ((N) << 0x6)
626#define SOUND_WAVE_ENABLE (1 << 0x7)
627
628typedef u8 WaveBank[32];
629
630// typedef u32 WaveBank[4];
631#define SOUND_WAVE_RAM ((WaveBank*)(MEM_IO + 0x90))
608 632
609typedef enum { 633typedef enum {
610 NOTE_C_2 , NOTE_C_SHARP_2 , NOTE_D_2 , NOTE_D_SHARP_2 , 634 NOTE_C_2 , NOTE_C_SHARP_2 , NOTE_D_2 , NOTE_D_SHARP_2 ,
diff --git a/src/main.c b/src/main.c
index b93abe6..48538fb 100644
--- a/src/main.c
+++ b/src/main.c
@@ -20,8 +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 init_sequencer_sprites();
24
25 // Initialize text engine. 23 // Initialize text engine.
26 // txt_init(0, COLOR_RED, 0); 24 // txt_init(0, COLOR_RED, 0);
27 25
@@ -29,10 +27,7 @@ int main(void) {
29 irq_init(); 27 irq_init();
30 irs_set(IRQ_VBLANK, irs_stub); 28 irs_set(IRQ_VBLANK, irs_stub);
31 29
32 // turn sound on 30 init_sequencer();
33 SOUND_STATUS = SOUND_ENABLE;
34 SOUND_DMG_MASTER = sound_volume(SOUND_SQUARE1 | SOUND_SQUARE2, 3);
35 SOUND_DSOUND_MASTER = SOUND_DMG100;
36 31
37 // Initialize timer. 32 // Initialize timer.
38 while(true) { 33 while(true) {
diff --git a/src/sequencer.c b/src/sequencer.c
index f4006c4..1447056 100644
--- a/src/sequencer.c
+++ b/src/sequencer.c
@@ -13,7 +13,7 @@
13#define SEQ_DUTYCYCLE_POS_Y 10 - 8 13#define SEQ_DUTYCYCLE_POS_Y 10 - 8
14#define SEQ_SWEEP_POS_X SEQ_DUTYCYCLE_POS_X + SEQ_ENV_DIST 14#define SEQ_SWEEP_POS_X SEQ_DUTYCYCLE_POS_X + SEQ_ENV_DIST
15#define SEQ_SWEEP_POS_Y SEQ_ENV_POS_Y 15#define SEQ_SWEEP_POS_Y SEQ_ENV_POS_Y
16#define SEQ_N_CHANNELS 2 16#define SEQ_N_CHANNELS 3
17 17
18u32 sprite_note_names[] = { 18u32 sprite_note_names[] = {
19 0x000000e0, 0x202020e0, 0x0000000e, 0x080e020e, 19 0x000000e0, 0x202020e0, 0x0000000e, 0x080e020e,
@@ -273,7 +273,7 @@ typedef struct SeqTrigger {
273 // TODO: Do we need other fields? 273 // TODO: Do we need other fields?
274} SeqTrigger; 274} SeqTrigger;
275 275
276static SeqTrigger sequences[2][16] = { 276static SeqTrigger sequences[3][16] = {
277 // Synth 1 277 // Synth 1
278 { 278 {
279 {true, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0}, 279 {true, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0},
@@ -312,6 +312,25 @@ static SeqTrigger sequences[2][16] = {
312 {false, NOTE_G_5, 8, 4, 0, 2, 0, 0, 0}, 312 {false, NOTE_G_5, 8, 4, 0, 2, 0, 0, 0},
313 {false, NOTE_G_5, 8, 4, 0, 2, 0, 0, 0}, 313 {false, NOTE_G_5, 8, 4, 0, 2, 0, 0, 0},
314 }, 314 },
315 // Synth 3
316 {
317 {true, NOTE_G_5, 8, 4, 0, 2, 0, 0, 0},
318 {false, NOTE_G_5, 8, 4, 0, 2, 0, 0, 0},
319 {false, NOTE_G_5, 8, 4, 0, 2, 0, 0, 0},
320 {true, NOTE_C_5, 8, 4, 0, 2, 0, 0, 0},
321 {true, NOTE_D_5, 8, 4, 0, 2, 0, 0, 0},
322 {false, NOTE_G_5, 8, 4, 0, 2, 0, 0, 0},
323 {false, NOTE_G_5, 8, 4, 0, 2, 0, 0, 0},
324 {false, NOTE_G_5, 8, 4, 0, 2, 0, 0, 0},
325 {true, NOTE_G_5, 8, 4, 0, 2, 0, 0, 0},
326 {false, NOTE_G_5, 8, 4, 0, 2, 0, 0, 0},
327 {false, NOTE_G_5, 8, 4, 0, 2, 0, 0, 0},
328 {false, NOTE_G_5, 8, 4, 0, 2, 0, 0, 0},
329 {true, NOTE_D_5, 8, 4, 0, 2, 0, 0, 0},
330 {false, NOTE_G_5, 8, 4, 0, 2, 0, 0, 0},
331 {false, NOTE_G_5, 8, 4, 0, 2, 0, 0, 0},
332 {false, NOTE_G_5, 8, 4, 0, 2, 0, 0, 0},
333 },
315}; 334};
316 335
317// TODO: Support for copy paste anything, contextual. If we are on trigger 336// TODO: Support for copy paste anything, contextual. If we are on trigger
@@ -346,19 +365,31 @@ irq_timer_0(void) {
346 | SOUND_SQUARE_ENV_TIME(trig->env_time) 365 | SOUND_SQUARE_ENV_TIME(trig->env_time)
347 | SOUND_SQUARE_ENV_DIR(trig->env_direction) 366 | SOUND_SQUARE_ENV_DIR(trig->env_direction)
348 | SOUND_SQUARE_DUTY(trig->duty_cycle); 367 | SOUND_SQUARE_DUTY(trig->duty_cycle);
349 SOUND_SQUARE1_FREQ = SOUND_SQUARE_RESET 368 SOUND_SQUARE1_FREQ = SOUND_FREQ_RESET
350 | sound_rates[active_note]; 369 | sound_rates[active_note];
351 } 370 }
352 } 371 }
353 SeqTrigger *trig = &sequences[1][step_counter];
354 { 372 {
373 SeqTrigger *trig = &sequences[1][step_counter];
355 active_note = trig->note; 374 active_note = trig->note;
356 if (trig->trigger) { 375 if (trig->trigger) {
357 SOUND_SQUARE2_CTRL = SOUND_SQUARE_ENV_VOL(trig->env_volume) 376 SOUND_SQUARE2_CTRL = SOUND_SQUARE_ENV_VOL(trig->env_volume)
358 | SOUND_SQUARE_ENV_TIME(trig->env_time) 377 | SOUND_SQUARE_ENV_TIME(trig->env_time)
359 | SOUND_SQUARE_ENV_DIR(trig->env_direction) 378 | SOUND_SQUARE_ENV_DIR(trig->env_direction)
360 | SOUND_SQUARE_DUTY(trig->duty_cycle); 379 | SOUND_SQUARE_DUTY(trig->duty_cycle);
361 SOUND_SQUARE2_FREQ = SOUND_SQUARE_RESET 380 SOUND_SQUARE2_FREQ = SOUND_FREQ_RESET
381 | sound_rates[active_note];
382 }
383 }
384 {
385 SeqTrigger *trig = &sequences[2][step_counter];
386 active_note = trig->note;
387 if (trig->trigger) {
388 SOUND_WAVE_MODE = SOUND_WAVE_BANK_MODE(0)
389 | SOUND_WAVE_BANK_SELECT(0)
390 | SOUND_WAVE_ENABLE;
391 SOUND_WAVE_CTRL = SOUND_WAVE_VOL_100;
392 SOUND_WAVE_FREQ = SOUND_FREQ_RESET
362 | sound_rates[active_note]; 393 | sound_rates[active_note];
363 } 394 }
364 } 395 }
@@ -752,7 +783,7 @@ init_sequencer_sprites(void) {
752 int base_tile = sprites[sprite_id].tile_start + 8; 783 int base_tile = sprites[sprite_id].tile_start + 8;
753 seq_sprites[53].id = obj_counter++; 784 seq_sprites[53].id = obj_counter++;
754 seq_sprites[53].base_tile = base_tile; 785 seq_sprites[53].base_tile = base_tile;
755 seq_sprites[53].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y) | OBJ_HIDDEN; 786 seq_sprites[53].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y);
756 seq_sprites[53].obj_attr_1 = OBJ_SIZE_MID | OBJ_X_COORD(x); 787 seq_sprites[53].obj_attr_1 = OBJ_SIZE_MID | OBJ_X_COORD(x);
757 seq_sprites[53].obj_attr_2 = base_tile | OBJ_PAL_BANK(0); 788 seq_sprites[53].obj_attr_2 = base_tile | OBJ_PAL_BANK(0);
758 } 789 }
@@ -1084,11 +1115,15 @@ handle_sequencer_input(void) {
1084 } else { 1115 } else {
1085 TIMER_CTRL_0 ^= TIMER_CTRL_ENABLE; 1116 TIMER_CTRL_0 ^= TIMER_CTRL_ENABLE;
1086 SOUND_SQUARE1_CTRL = 0; 1117 SOUND_SQUARE1_CTRL = 0;
1118 SOUND_SQUARE2_CTRL = 0;
1119 SOUND_WAVE_CTRL = 0;
1087 } 1120 }
1088 } 1121 }
1089 if (key_pressed(KEY_SELECT)) { 1122 if (key_pressed(KEY_SELECT)) {
1090 TIMER_CTRL_0 ^= TIMER_CTRL_ENABLE; 1123 TIMER_CTRL_0 ^= TIMER_CTRL_ENABLE;
1091 SOUND_SQUARE1_CTRL = 0; 1124 SOUND_SQUARE1_CTRL = 0;
1125 SOUND_SQUARE2_CTRL = 0;
1126 SOUND_WAVE_CTRL = 0;
1092 } 1127 }
1093} 1128}
1094 1129
@@ -1102,3 +1137,29 @@ render_sequencer_sprites(void) {
1102 OBJ_ATTR_2(id) = seq_sprites[i].obj_attr_2; 1137 OBJ_ATTR_2(id) = seq_sprites[i].obj_attr_2;
1103 } 1138 }
1104} 1139}
1140
1141void init_sequencer() {
1142 init_sequencer_sprites();
1143 SOUND_STATUS = SOUND_ENABLE;
1144 SOUND_DMG_MASTER = sound_volume(SOUND_SQUARE1 | SOUND_SQUARE2 | SOUND_WAVE, 3);
1145 SOUND_DSOUND_MASTER = SOUND_DMG100;
1146
1147 // TODO: Currently static, need to figure out a way of controlling these
1148 // parameters.
1149 // Select bank 0 for writing (bank 1 playing).
1150 SOUND_WAVE_RAM_0 = 0xEFDEBC89;
1151 SOUND_WAVE_RAM_1 = 0x98CBEDFE;
1152 SOUND_WAVE_RAM_2 = 0x10214376;
1153 SOUND_WAVE_RAM_3 = 0x67341201;
1154 SOUND_WAVE_MODE = SOUND_WAVE_BANK_MODE(1) | SOUND_WAVE_BANK_SELECT(1);
1155
1156 // SINE WAVE
1157 SOUND_WAVE_RAM_0 = 0xEFDEBC89;
1158 SOUND_WAVE_RAM_1 = 0x98CBEDFE;
1159 SOUND_WAVE_RAM_2 = 0x10214376;
1160 SOUND_WAVE_RAM_3 = 0x67341201;
1161
1162 // Select bank 0 for playing.
1163 SOUND_WAVE_MODE = SOUND_WAVE_BANK_MODE(0) | SOUND_WAVE_BANK_SELECT(0);
1164 SOUND_WAVE_MODE |= SOUND_WAVE_ENABLE;
1165}