summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2021-05-04 14:55:42 +0200
committerBad Diode <bd@badd10de.dev>2021-05-04 14:55:42 +0200
commit59966e7639c4ad3ffdd6dc3566e1b5aae003e3cd (patch)
tree1e6692fcc51e3fb0d1a030f3fa1279ba01c22ac5
parent0bf2a5a3f360f13d6195013a8e63b0519905202a (diff)
downloadgba-experiments-59966e7639c4ad3ffdd6dc3566e1b5aae003e3cd.tar.gz
gba-experiments-59966e7639c4ad3ffdd6dc3566e1b5aae003e3cd.zip
Enable sequencing on both square wave channels
-rw-r--r--src/sequencer.c178
1 files changed, 107 insertions, 71 deletions
diff --git a/src/sequencer.c b/src/sequencer.c
index ae06031..6837b1e 100644
--- a/src/sequencer.c
+++ b/src/sequencer.c
@@ -273,23 +273,45 @@ 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 sequence_synth[16] = { 276static SeqTrigger sequences[2][16] = {
277 {true, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0}, 277 // Synth 1
278 {false, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0}, 278 {
279 {false, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0}, 279 {true, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0},
280 {false, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0}, 280 {false, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0},
281 {true, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0}, 281 {false, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0},
282 {false, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0}, 282 {false, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0},
283 {false, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0}, 283 {true, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0},
284 {false, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0}, 284 {false, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0},
285 {true, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0}, 285 {false, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0},
286 {false, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0}, 286 {false, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0},
287 {false, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0}, 287 {true, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0},
288 {false, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0}, 288 {false, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0},
289 {true, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0}, 289 {false, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0},
290 {false, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0}, 290 {false, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0},
291 {false, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0}, 291 {true, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0},
292 {false, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0}, 292 {false, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0},
293 {false, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0},
294 {false, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0},
295 },
296 // Synth 2
297 {
298 {true, NOTE_G_5, 8, 4, 0, 2, 0, 0, 0},
299 {false, NOTE_G_5, 8, 4, 0, 2, 0, 0, 0},
300 {false, NOTE_G_5, 8, 4, 0, 2, 0, 0, 0},
301 {false, NOTE_G_5, 8, 4, 0, 2, 0, 0, 0},
302 {true, NOTE_G_5, 8, 4, 0, 2, 0, 0, 0},
303 {false, NOTE_G_5, 8, 4, 0, 2, 0, 0, 0},
304 {false, NOTE_G_5, 8, 4, 0, 2, 0, 0, 0},
305 {false, NOTE_G_5, 8, 4, 0, 2, 0, 0, 0},
306 {true, NOTE_G_5, 8, 4, 0, 2, 0, 0, 0},
307 {false, NOTE_G_5, 8, 4, 0, 2, 0, 0, 0},
308 {false, NOTE_G_5, 8, 4, 0, 2, 0, 0, 0},
309 {false, NOTE_G_5, 8, 4, 0, 2, 0, 0, 0},
310 {true, NOTE_G_5, 8, 4, 0, 2, 0, 0, 0},
311 {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},
314 },
293}; 315};
294 316
295// TODO: Support for copy paste anything, contextual. If we are on trigger 317// TODO: Support for copy paste anything, contextual. If we are on trigger
@@ -302,24 +324,38 @@ static SeqTrigger sequence_synth[16] = {
302// TODO: Allow muting and unmuting channels. Show in grey when muted. 324// TODO: Allow muting and unmuting channels. Show in grey when muted.
303// TODO: Show channel beat indicator if a note is being played. 325// TODO: Show channel beat indicator if a note is being played.
304 326
305static int bpm = 180; 327static int bpm = 115;
306static int step_counter = 0; 328static int step_counter = 0;
307static Note active_note; 329static Note active_note;
308 330
309void 331void
310irq_timer_0(void) { 332irq_timer_0(void) {
311 SeqTrigger *trig = &sequence_synth[step_counter]; 333 {
312 active_note = trig->note; 334 SeqTrigger *trig = &sequences[0][step_counter];
313 if (trig->trigger) { 335 active_note = trig->note;
314 SOUND_SQUARE1_SWEEP = SOUND_SWEEP_NUMBER(trig->sweep_number) 336 if (trig->trigger) {
315 | SOUND_SWEEP_DIR(trig->sweep_direction) 337 SOUND_SQUARE1_SWEEP = SOUND_SWEEP_NUMBER(trig->sweep_number)
316 | SOUND_SWEEP_TIME(trig->sweep_time); 338 | SOUND_SWEEP_DIR(trig->sweep_direction)
317 SOUND_SQUARE1_CTRL = SOUND_SQUARE_ENV_VOL(trig->env_volume) 339 | SOUND_SWEEP_TIME(trig->sweep_time);
318 | SOUND_SQUARE_ENV_TIME(trig->env_time) 340 SOUND_SQUARE1_CTRL = SOUND_SQUARE_ENV_VOL(trig->env_volume)
319 | SOUND_SQUARE_ENV_DIR(trig->env_direction) 341 | SOUND_SQUARE_ENV_TIME(trig->env_time)
320 | SOUND_SQUARE_DUTY(trig->duty_cycle); 342 | SOUND_SQUARE_ENV_DIR(trig->env_direction)
321 SOUND_SQUARE1_FREQ = SOUND_SQUARE_RESET 343 | SOUND_SQUARE_DUTY(trig->duty_cycle);
322 | sound_rates[active_note]; 344 SOUND_SQUARE1_FREQ = SOUND_SQUARE_RESET
345 | sound_rates[active_note];
346 }
347 }
348 SeqTrigger *trig = &sequences[1][step_counter];
349 {
350 active_note = trig->note;
351 if (trig->trigger) {
352 SOUND_SQUARE2_CTRL = SOUND_SQUARE_ENV_VOL(trig->env_volume)
353 | SOUND_SQUARE_ENV_TIME(trig->env_time)
354 | SOUND_SQUARE_ENV_DIR(trig->env_direction)
355 | SOUND_SQUARE_DUTY(trig->duty_cycle);
356 SOUND_SQUARE2_FREQ = SOUND_SQUARE_RESET
357 | sound_rates[active_note];
358 }
323 } 359 }
324 step_counter = (step_counter + 1) % 16; 360 step_counter = (step_counter + 1) % 16;
325} 361}
@@ -755,12 +791,12 @@ update_sequencer_sprites(void) {
755 // 000-015: Step note names. 791 // 000-015: Step note names.
756 for (size_t i = 0; i < 16; ++i) { 792 for (size_t i = 0; i < 16; ++i) {
757 // Each note name is made of 2 8x8 tiles (16x8). 793 // Each note name is made of 2 8x8 tiles (16x8).
758 size_t base_tile = sequence_synth[i].note * 2; 794 size_t base_tile = sequences[channel_selection_loc][i].note * 2;
759 795
760 // TODO: Show the note name if is within the duration, hide when trigger 796 // TODO: Show the note name if is within the duration, hide when trigger
761 // is off or duration of previous note was cut short. If not triggered 797 // is off or duration of previous note was cut short. If not triggered
762 // but note name appears, needs to be on a different palette bank. 798 // but note name appears, needs to be on a different palette bank.
763 if (!sequence_synth[i].trigger) { 799 if (!sequences[channel_selection_loc][i].trigger) {
764 seq_sprites[i].obj_attr_0 |= OBJ_HIDDEN; 800 seq_sprites[i].obj_attr_0 |= OBJ_HIDDEN;
765 } else { 801 } else {
766 seq_sprites[i].obj_attr_0 &= ~OBJ_HIDDEN; 802 seq_sprites[i].obj_attr_0 &= ~OBJ_HIDDEN;
@@ -808,7 +844,7 @@ update_sequencer_sprites(void) {
808 844
809 // 36: Envelope initial volume. 845 // 36: Envelope initial volume.
810 { 846 {
811 size_t tile_diff = sequence_synth[trig_selection_loc].env_volume * 4; 847 size_t tile_diff = sequences[channel_selection_loc][trig_selection_loc].env_volume * 4;
812 size_t base_tile = seq_sprites[35].base_tile; 848 size_t base_tile = seq_sprites[35].base_tile;
813 size_t tile = base_tile + tile_diff; 849 size_t tile = base_tile + tile_diff;
814 seq_sprites[35].obj_attr_2 = tile; 850 seq_sprites[35].obj_attr_2 = tile;
@@ -816,7 +852,7 @@ update_sequencer_sprites(void) {
816 852
817 // 38: Envelope time. 853 // 38: Envelope time.
818 { 854 {
819 size_t tile_diff = sequence_synth[trig_selection_loc].env_time * 4; 855 size_t tile_diff = sequences[channel_selection_loc][trig_selection_loc].env_time * 4;
820 size_t base_tile = seq_sprites[37].base_tile; 856 size_t base_tile = seq_sprites[37].base_tile;
821 size_t tile = base_tile + tile_diff; 857 size_t tile = base_tile + tile_diff;
822 seq_sprites[37].obj_attr_2 = tile; 858 seq_sprites[37].obj_attr_2 = tile;
@@ -825,7 +861,7 @@ update_sequencer_sprites(void) {
825 // 40: Envelope direction. 861 // 40: Envelope direction.
826 { 862 {
827 size_t tile_diff = 0; 863 size_t tile_diff = 0;
828 if (sequence_synth[trig_selection_loc].env_direction == 0) { 864 if (sequences[channel_selection_loc][trig_selection_loc].env_direction == 0) {
829 tile_diff = 4; 865 tile_diff = 4;
830 } 866 }
831 size_t base_tile = seq_sprites[39].base_tile; 867 size_t base_tile = seq_sprites[39].base_tile;
@@ -835,7 +871,7 @@ update_sequencer_sprites(void) {
835 871
836 // 43: Duty cycle. 872 // 43: Duty cycle.
837 { 873 {
838 size_t tile_diff = sequence_synth[trig_selection_loc].duty_cycle * 4; 874 size_t tile_diff = sequences[channel_selection_loc][trig_selection_loc].duty_cycle * 4;
839 size_t base_tile = seq_sprites[42].base_tile; 875 size_t base_tile = seq_sprites[42].base_tile;
840 size_t tile = base_tile + tile_diff; 876 size_t tile = base_tile + tile_diff;
841 seq_sprites[42].obj_attr_2 = tile; 877 seq_sprites[42].obj_attr_2 = tile;
@@ -843,7 +879,7 @@ update_sequencer_sprites(void) {
843 879
844 // 45: Sweep number. 880 // 45: Sweep number.
845 { 881 {
846 size_t tile_diff = sequence_synth[trig_selection_loc].sweep_number; 882 size_t tile_diff = sequences[channel_selection_loc][trig_selection_loc].sweep_number;
847 size_t base_tile = seq_sprites[44].base_tile; 883 size_t base_tile = seq_sprites[44].base_tile;
848 size_t tile = base_tile + tile_diff; 884 size_t tile = base_tile + tile_diff;
849 seq_sprites[44].obj_attr_2 = tile; 885 seq_sprites[44].obj_attr_2 = tile;
@@ -851,7 +887,7 @@ update_sequencer_sprites(void) {
851 887
852 // 47: Sweep time. 888 // 47: Sweep time.
853 { 889 {
854 size_t tile_diff = sequence_synth[trig_selection_loc].sweep_time; 890 size_t tile_diff = sequences[channel_selection_loc][trig_selection_loc].sweep_time;
855 size_t base_tile = seq_sprites[46].base_tile; 891 size_t base_tile = seq_sprites[46].base_tile;
856 size_t tile = base_tile + tile_diff; 892 size_t tile = base_tile + tile_diff;
857 seq_sprites[46].obj_attr_2 = tile; 893 seq_sprites[46].obj_attr_2 = tile;
@@ -859,7 +895,7 @@ update_sequencer_sprites(void) {
859 895
860 // 49: Sweep direction. 896 // 49: Sweep direction.
861 { 897 {
862 size_t tile_diff = sequence_synth[trig_selection_loc].sweep_direction * 4; 898 size_t tile_diff = sequences[channel_selection_loc][trig_selection_loc].sweep_direction * 4;
863 size_t base_tile = seq_sprites[48].base_tile; 899 size_t base_tile = seq_sprites[48].base_tile;
864 size_t tile = base_tile + tile_diff; 900 size_t tile = base_tile + tile_diff;
865 seq_sprites[48].obj_attr_2 = tile; 901 seq_sprites[48].obj_attr_2 = tile;
@@ -911,14 +947,14 @@ handle_sequencer_input(void) {
911 } else if (key_pressed(KEY_UP) || key_pressed(KEY_DOWN)) { 947 } else if (key_pressed(KEY_UP) || key_pressed(KEY_DOWN)) {
912 trig_selection_loc = (trig_selection_loc + 8) % 16; 948 trig_selection_loc = (trig_selection_loc + 8) % 16;
913 } else if (key_pressed(KEY_B)) { 949 } else if (key_pressed(KEY_B)) {
914 sequence_synth[trig_selection_loc].trigger ^= 1; 950 sequences[channel_selection_loc][trig_selection_loc].trigger ^= 1;
915 } else if (key_pressed(KEY_L)) { 951 } else if (key_pressed(KEY_L)) {
916 sequence_synth[trig_selection_loc].note = CLAMP( 952 sequences[channel_selection_loc][trig_selection_loc].note = CLAMP(
917 sequence_synth[trig_selection_loc].note - 1, 953 sequences[channel_selection_loc][trig_selection_loc].note - 1,
918 NOTE_C_2, NOTE_C_8); 954 NOTE_C_2, NOTE_C_8);
919 } else if (key_pressed(KEY_R)) { 955 } else if (key_pressed(KEY_R)) {
920 sequence_synth[trig_selection_loc].note = CLAMP( 956 sequences[channel_selection_loc][trig_selection_loc].note = CLAMP(
921 sequence_synth[trig_selection_loc].note + 1, 957 sequences[channel_selection_loc][trig_selection_loc].note + 1,
922 NOTE_C_2, NOTE_C_8); 958 NOTE_C_2, NOTE_C_8);
923 } else if (key_pressed(KEY_A)) { 959 } else if (key_pressed(KEY_A)) {
924 // Switch to parameter selection. 960 // Switch to parameter selection.
@@ -945,33 +981,33 @@ handle_sequencer_input(void) {
945 if (key_pressed(KEY_L)) { 981 if (key_pressed(KEY_L)) {
946 switch (param_selection_loc) { 982 switch (param_selection_loc) {
947 case 0: { 983 case 0: {
948 sequence_synth[trig_selection_loc].env_volume = CLAMP( 984 sequences[channel_selection_loc][trig_selection_loc].env_volume = CLAMP(
949 sequence_synth[trig_selection_loc].env_volume - 1, 0, 15); 985 sequences[channel_selection_loc][trig_selection_loc].env_volume - 1, 0, 15);
950 } break; 986 } break;
951 case 1: { 987 case 1: {
952 sequence_synth[trig_selection_loc].env_time = CLAMP( 988 sequences[channel_selection_loc][trig_selection_loc].env_time = CLAMP(
953 sequence_synth[trig_selection_loc].env_time - 1, 0, 7); 989 sequences[channel_selection_loc][trig_selection_loc].env_time - 1, 0, 7);
954 } break; 990 } break;
955 case 2: { 991 case 2: {
956 sequence_synth[trig_selection_loc].env_direction ^= 1; 992 sequences[channel_selection_loc][trig_selection_loc].env_direction ^= 1;
957 } break; 993 } break;
958 case 3: { 994 case 3: {
959 sequence_synth[trig_selection_loc].duty_cycle = CLAMP( 995 sequences[channel_selection_loc][trig_selection_loc].duty_cycle = CLAMP(
960 sequence_synth[trig_selection_loc].duty_cycle - 1, 0, 3); 996 sequences[channel_selection_loc][trig_selection_loc].duty_cycle - 1, 0, 3);
961 } break; 997 } break;
962 case 4: { 998 case 4: {
963 sequence_synth[trig_selection_loc].sweep_number = CLAMP( 999 sequences[channel_selection_loc][trig_selection_loc].sweep_number = CLAMP(
964 sequence_synth[trig_selection_loc].sweep_number - 1, 0, 7); 1000 sequences[channel_selection_loc][trig_selection_loc].sweep_number - 1, 0, 7);
965 } break; 1001 } break;
966 case 5: { 1002 case 5: {
967 sequence_synth[trig_selection_loc].sweep_time = CLAMP( 1003 sequences[channel_selection_loc][trig_selection_loc].sweep_time = CLAMP(
968 sequence_synth[trig_selection_loc].sweep_time - 1, 0, 7); 1004 sequences[channel_selection_loc][trig_selection_loc].sweep_time - 1, 0, 7);
969 } break; 1005 } break;
970 case 6: { 1006 case 6: {
971 if (sequence_synth[trig_selection_loc].sweep_direction == 0) { 1007 if (sequences[channel_selection_loc][trig_selection_loc].sweep_direction == 0) {
972 sequence_synth[trig_selection_loc].sweep_direction = 1; 1008 sequences[channel_selection_loc][trig_selection_loc].sweep_direction = 1;
973 } else { 1009 } else {
974 sequence_synth[trig_selection_loc].sweep_direction = 0; 1010 sequences[channel_selection_loc][trig_selection_loc].sweep_direction = 0;
975 } 1011 }
976 } break; 1012 } break;
977 } 1013 }
@@ -979,30 +1015,30 @@ handle_sequencer_input(void) {
979 if (key_pressed(KEY_R)) { 1015 if (key_pressed(KEY_R)) {
980 switch (param_selection_loc) { 1016 switch (param_selection_loc) {
981 case 0: { 1017 case 0: {
982 sequence_synth[trig_selection_loc].env_volume = CLAMP( 1018 sequences[channel_selection_loc][trig_selection_loc].env_volume = CLAMP(
983 sequence_synth[trig_selection_loc].env_volume + 1, 0, 15); 1019 sequences[channel_selection_loc][trig_selection_loc].env_volume + 1, 0, 15);
984 } break; 1020 } break;
985 case 1: { 1021 case 1: {
986 sequence_synth[trig_selection_loc].env_time = CLAMP( 1022 sequences[channel_selection_loc][trig_selection_loc].env_time = CLAMP(
987 sequence_synth[trig_selection_loc].env_time + 1, 0, 7); 1023 sequences[channel_selection_loc][trig_selection_loc].env_time + 1, 0, 7);
988 } break; 1024 } break;
989 case 2: { 1025 case 2: {
990 sequence_synth[trig_selection_loc].env_direction ^= 1; 1026 sequences[channel_selection_loc][trig_selection_loc].env_direction ^= 1;
991 } break; 1027 } break;
992 case 3: { 1028 case 3: {
993 sequence_synth[trig_selection_loc].duty_cycle = CLAMP( 1029 sequences[channel_selection_loc][trig_selection_loc].duty_cycle = CLAMP(
994 sequence_synth[trig_selection_loc].duty_cycle + 1, 0, 3); 1030 sequences[channel_selection_loc][trig_selection_loc].duty_cycle + 1, 0, 3);
995 } break; 1031 } break;
996 case 4: { 1032 case 4: {
997 sequence_synth[trig_selection_loc].sweep_number = CLAMP( 1033 sequences[channel_selection_loc][trig_selection_loc].sweep_number = CLAMP(
998 sequence_synth[trig_selection_loc].sweep_number + 1, 0, 7); 1034 sequences[channel_selection_loc][trig_selection_loc].sweep_number + 1, 0, 7);
999 } break; 1035 } break;
1000 case 5: { 1036 case 5: {
1001 sequence_synth[trig_selection_loc].sweep_time = CLAMP( 1037 sequences[channel_selection_loc][trig_selection_loc].sweep_time = CLAMP(
1002 sequence_synth[trig_selection_loc].sweep_time + 1, 0, 7); 1038 sequences[channel_selection_loc][trig_selection_loc].sweep_time + 1, 0, 7);
1003 } break; 1039 } break;
1004 case 6: { 1040 case 6: {
1005 sequence_synth[trig_selection_loc].sweep_direction ^= 1; 1041 sequences[channel_selection_loc][trig_selection_loc].sweep_direction ^= 1;
1006 } break; 1042 } break;
1007 } 1043 }
1008 } 1044 }
@@ -1014,7 +1050,7 @@ handle_sequencer_input(void) {
1014 1050
1015 // Enable disable trigger. 1051 // Enable disable trigger.
1016 if (key_pressed(KEY_B)) { 1052 if (key_pressed(KEY_B)) {
1017 sequence_synth[trig_selection_loc].trigger ^= 1; 1053 sequences[channel_selection_loc][trig_selection_loc].trigger ^= 1;
1018 } 1054 }
1019 } else if (current_selection == SEQ_SELECT_CHANNEL) { 1055 } else if (current_selection == SEQ_SELECT_CHANNEL) {
1020 if (key_pressed(KEY_RIGHT)) { 1056 if (key_pressed(KEY_RIGHT)) {