From 01e6349dfb76abaf9d87d94369b17c14b678e416 Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Sun, 2 May 2021 09:42:21 +0200 Subject: Update sequencer to use timers w/ different bpms --- src/common.h | 1 + src/main.c | 156 +++++++++++++++++++++++++++++++---------------------------- 2 files changed, 82 insertions(+), 75 deletions(-) diff --git a/src/common.h b/src/common.h index 4151d18..ece94cd 100644 --- a/src/common.h +++ b/src/common.h @@ -224,6 +224,7 @@ flip_page(void) { #define TIMER_CTRL_CASCADE (1 << 2) #define TIMER_CTRL_IRQ (1 << 6) #define TIMER_CTRL_ENABLE (1 << 7) +#define TIMER_CTRL_DISABLE (0 << 7) // We use timers 2 and 3 to count the number of cycles since the profile_start // functions is called. Don't use if the code we are trying to profile make use diff --git a/src/main.c b/src/main.c index ac6bf66..b2cd2d2 100644 --- a/src/main.c +++ b/src/main.c @@ -13,6 +13,64 @@ // TODO: Cleanup OBJ/OAM memory copying and access. // +typedef struct SeqTrigger { + bool trigger; + Note note; + // TODO: ... +} SeqTrigger; + +static SeqTrigger sequence_synth_1 [] = { + {true, NOTE_D_4}, + {true, NOTE_F_4}, + {true, NOTE_A_4}, + {true, NOTE_C_5}, + + {true, NOTE_D_4}, + {false, NOTE_D_4}, + {false, NOTE_D_4}, + {false, NOTE_D_4}, + + {true, NOTE_D_4}, + {true, NOTE_F_4}, + {true, NOTE_A_4}, + {true, NOTE_C_5}, + + {true, NOTE_D_4}, + {false, NOTE_D_4}, + {true, NOTE_A_4}, + {false, NOTE_A_5}, +}; + +int step_counter = 0; +Note active_note; +void +irq_timer_0(void) { + active_note = sequence_synth_1[step_counter].note; + if (sequence_synth_1[step_counter].trigger) { + SOUND_SQUARE1_CTRL = SOUND_SQUARE_ENV_VOL(13) | SOUND_SQUARE_ENV_TIME(4) | SOUND_SQUARE_DUTY(2); + SOUND_SQUARE1_FREQ = SOUND_SQUARE_RESET | sound_rates[active_note]; + } + + step_counter = (step_counter + 1) % 16; +} + +void +set_time(int bpm) { + // TIMER_CTRL_0 = TIMER_CTRL_DISABLE; + + // The number of ticks of a 1024 cycle clock in a step based on the BPM can + // be calculated as: + // X bpm -> 60000 / 4 / bpm = Y ms = Ye-3 s + // Y ms -> Ye-3 / 59.99e-9 /1024 = Z ticks + // We have to operate on integer values, so the numbers have been + // precalculated to `n_ticks = 244181 / bmp` + int n_ticks = -244181 / bpm; + + irs_set(IRQ_TIMER_0, irq_timer_0); + TIMER_DATA_0 = n_ticks; + TIMER_CTRL_0 = TIMER_CTRL_IRQ | TIMER_CTRL_ENABLE | TIMER_CTRL_FREQ_3; +} + int main(void) { // Configure the display in mode 0 to show OBJs, where tile memory is // sequential. @@ -35,91 +93,39 @@ int main(void) { SOUND_DMG_MASTER = sound_volume(SOUND_SQUARE1 | SOUND_SQUARE2, 7); SOUND_DSOUND_MASTER = SOUND_DMG100; - Note active_note = NOTE_C_4; - int octave_diff = 0; - bool playing = false; - bool new_note = false; - u8 interval = 7; - u32 sound_sequence[16] = { - NOTE_C_4, - NOTE_A_4, - NOTE_D_5, - NOTE_D_4, - NOTE_F_4, - NOTE_G_4, - NOTE_C_4, - NOTE_A_4, - NOTE_D_5, - NOTE_D_4, - NOTE_F_4, - NOTE_G_4, - NOTE_A_4, - NOTE_G_4, - NOTE_A_4, - NOTE_F_4, - }; - int step_counter = 0; - int step_counter_2 = 0; - int frame_counter = 0; - bool trigger_1 = true; - bool trigger_2 = true; + // Initialize timer. + int bpm = 120; + while(true) { bios_vblank_wait(); poll_keys(); - - txt_position(0, 1); - - if (frame_counter >= 7 * 4) { - if ((step_counter + 1) % 4 == 0) { - step_counter_2 = (step_counter_2 + 1) % 16; - trigger_2 = true; - } - trigger_1 = true; - frame_counter = 0; - step_counter = (step_counter + 1) % 16; - } - - if (trigger_1 && playing) { - active_note = sound_sequence[step_counter]; - txt_clear_line(); - txt_printf("SYNTH 1\n\n"); - txt_clear_line(); - txt_printf("Step: %d\n", step_counter); - txt_clear_line(); - txt_printf("Playing: %s\n\n\n\n", note_names[active_note]); - SOUND_SQUARE1_CTRL = SOUND_SQUARE_ENV_VOL(13) | SOUND_SQUARE_ENV_TIME(4) | SOUND_SQUARE_DUTY(1); - SOUND_SQUARE1_FREQ = SOUND_SQUARE_RESET | sound_rates[active_note]; - trigger_1 = false; + if (key_hold(KEY_UP)) { + bpm += 1; + set_time(bpm); } - - if (trigger_2 && playing) { - active_note = sound_sequence[step_counter_2]; - txt_clear_line(); - txt_printf("SYNTH 2\n\n"); - txt_clear_line(); - txt_printf("Step: %d\n", step_counter_2); - txt_clear_line(); - txt_printf("Playing: %s\n", note_names[active_note]); - SOUND_SQUARE2_CTRL = SOUND_SQUARE_ENV_VOL(12) | SOUND_SQUARE_ENV_TIME(3) | SOUND_SQUARE_DUTY(3); - SOUND_SQUARE2_FREQ = SOUND_SQUARE_RESET | sound_rates[active_note]; - trigger_2 = false; + if (key_hold(KEY_DOWN)) { + bpm -= 1; + set_time(bpm); } - if (key_pressed(KEY_B)) { - playing = true; + if (key_pressed(KEY_START)) { step_counter = 0; - step_counter_2 = 8; - frame_counter = 0; - trigger_1 = true; - trigger_2 = true; + set_time(bpm); } - - if (key_pressed(KEY_A)) { - playing = false; + if (key_pressed(KEY_SELECT)) { + TIMER_CTRL_0 ^= TIMER_CTRL_ENABLE; } - frame_counter++; - // update_button_sprites(); + txt_position(1,6); + txt_clear_line(); + txt_printf(" BPM: %d\n\n", bpm); + + txt_clear_line(); + txt_printf(" Step: %d\n", step_counter); + txt_clear_line(); + txt_printf(" Note: %s\n", note_names[active_note]); + + update_button_sprites(); }; return 0; -- cgit v1.2.1