From 901ba917a3b4812f7eacf93d55389978a907a44d Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Thu, 25 Apr 2024 16:29:44 +0200 Subject: Staging some testing samples for backup --- Makefile | 2 +- src/main.c | 2 +- src/sequencer.c | 253 ++++++++++++++++++++++++++++++++++++++++++++++++-------- 3 files changed, 219 insertions(+), 38 deletions(-) diff --git a/Makefile b/Makefile index e464b75..abaa008 100644 --- a/Makefile +++ b/Makefile @@ -27,7 +27,7 @@ INC_FLAGS := $(addprefix -I,$(INC_DIRS)) INC_FLAGS += -I$(LIBGBA_SRC) # Output library names and executables. -TARGET := STEPPER-v1.8 +TARGET := STEPPER-v1.8-dev-lsdj ELF := $(BUILD_DIR)/$(TARGET).elf BIN := $(BUILD_DIR)/$(TARGET).gba diff --git a/src/main.c b/src/main.c index 170e0e0..81e47a1 100644 --- a/src/main.c +++ b/src/main.c @@ -255,7 +255,7 @@ main(void) { // Register interrupts. irq_init(); - irs_set(IRQ_VBLANK, sound_vsync); + irs_set(IRQ_VBLANK, irs_stub); // Initialize sequencer. sequencer_init(); diff --git a/src/sequencer.c b/src/sequencer.c index 9efd506..d2a0054 100644 --- a/src/sequencer.c +++ b/src/sequencer.c @@ -25,32 +25,185 @@ clear_pattern(size_t idx) { void gate_off(void) { - SIO_MODE = SIO_MODE_GP - | SIO_SC_OUT(1) - | SIO_SD_OUT(1) - | SIO_SI_OUT(0) - | SIO_SO_OUT(1) - | SIO_SC(0) - | SIO_SD(0) - | SIO_SO(0); - TIMER_CTRL_3 = 0; + // SIO_MODE = SIO_MODE_GP + // | SIO_SC_OUT(1) + // | SIO_SD_OUT(0) + // | SIO_SI_OUT(0) + // | SIO_SO_OUT(0) + // | SIO_SI(0) + // | SIO_SC(0) + // | SIO_SD(0) + // | SIO_SO(0); + // TIMER_CTRL_3 = 0; +} + +int pulses_sent = 0; +int gate_status = 0; + +void +gate_lsdj(void) { + gate_status ^= 1; + if (pulses_sent >= 7) { + gate_off(); + return; + } + if (gate_status == 1) { + gate_off(); + } else { + pulses_sent++; + SIO_MODE = SIO_MODE_GP + | SIO_SC_OUT(1) + | SIO_SD_OUT(0) + | SIO_SI_OUT(0) + | SIO_SO_OUT(0) + | SIO_SI(0) + | SIO_SC(1) + | SIO_SD(0) + | SIO_SO(0); + } + int n_ticks = -80 / 8 / 2; // 5ms + irs_set(IRQ_TIMER_3, gate_lsdj); + TIMER_DATA_3 = n_ticks; + TIMER_CTRL_3 = TIMER_CTRL_IRQ | TIMER_CTRL_ENABLE | TIMER_CTRL_FREQ_3; } +// TODO: LSDJ sync pulse? + void gate_on(void) { - gate_off(); + // SYNC24 NOTES + // (from https://e-rm.de/data/E-RM_report_HowToDinSync_10_14_EN.pdf) + // + // "Moreover, a duty cycle of 50% doesn’t seem to be nescessary, all tested + // machines were able to sync properly to clock ticks with a positive width + // of 5 ms to up to 300 BPM" @ 24bpq + // + // int bpm = 100; + // if (settings.global_bpm) { + // bpm = settings.bpm; + // } else { + // bpm patterns[current_pattern].bpm; + // } + // gate_off(); + // pulses_sent = 0; + // gate_status = 0; + // SIO_MODE = SIO_MODE_GP + // | SIO_SC_OUT(1) + // | SIO_SD_OUT(0) + // | SIO_SI_OUT(0) + // | SIO_SO_OUT(0) + // | SIO_SI(0) + // | SIO_SC(1) + // | SIO_SD(0) + // | SIO_SO(0); + // // int n_ticks = -80; // 5ms + // // irs_set(IRQ_TIMER_3, gate_off); + // // TIMER_DATA_3 = n_ticks; + // // TIMER_CTRL_3 = TIMER_CTRL_IRQ | TIMER_CTRL_ENABLE | TIMER_CTRL_FREQ_3; + // int n_ticks = -80 / 8 / 2; // 5ms + // irs_set(IRQ_TIMER_3, gate_lsdj); + // TIMER_DATA_3 = n_ticks; + // TIMER_CTRL_3 = TIMER_CTRL_IRQ | TIMER_CTRL_ENABLE | TIMER_CTRL_FREQ_3; + // int n_ticks = -79; // 5ms + // TIMER_DATA_3 = n_ticks; + // TIMER_CTRL_3 = TIMER_CTRL_ENABLE | TIMER_CTRL_FREQ_3; + // while (1) { + // int cnt = TIMER_DATA_3; + // if (cnt >= 80) { + // gate_off(); + // break; + // } + // } +} + +bool first_pulse = true; +int so_status = 1; + +void +lsdj_toggle(void) { + gate_status ^= 1; + if (pulses_sent >= 7) { + TIMER_CTRL_3 = 0; + SIO_MODE = SIO_MODE_GP + | SIO_SI_OUT(0) + | SIO_SC_OUT(1) + | SIO_SD_OUT(0) + | SIO_SO_OUT(1) + | SIO_SI(0) + | SIO_SC(1) + | SIO_SD(0) + | SIO_SO(so_status); + return; + } + if (gate_status == 1) { + SIO_MODE = SIO_MODE_GP + | SIO_SI_OUT(0) + | SIO_SC_OUT(1) + | SIO_SD_OUT(0) + | SIO_SO_OUT(1) + | SIO_SI(0) + | SIO_SC(1) + | SIO_SD(0) + | SIO_SO(so_status); + } else { + pulses_sent++; + SIO_MODE = SIO_MODE_GP + | SIO_SI_OUT(0) + | SIO_SC_OUT(1) + | SIO_SD_OUT(0) + | SIO_SO_OUT(1) + | SIO_SI(0) + | SIO_SC(0) + | SIO_SD(0) + | SIO_SO(so_status); + } + TIMER_CTRL_3 = 0; + // int n_ticks = -80 / 8 / 2; // 5ms + // irs_set(IRQ_TIMER_3, lsdj_toggle); + // TIMER_DATA_3 = n_ticks; + // TIMER_CTRL_3 = TIMER_CTRL_IRQ | TIMER_CTRL_ENABLE | TIMER_CTRL_FREQ_3; + int n_ticks = -9; // 122/2 = 61us; 61 / 3.8 = 16 + irs_set(IRQ_TIMER_3, lsdj_toggle); + TIMER_DATA_3 = n_ticks; + TIMER_CTRL_3 = TIMER_CTRL_IRQ | TIMER_CTRL_ENABLE | TIMER_CTRL_FREQ_1; +} + +void +lsdj_pulse(void) { + // LSDJ expects a pulse train on the SC pin (active low?). For the song + // start, the first pulse and until the start of the second one it should + // set SO to low as follows: + // + // CLK (SC) --_-_-_-_-_-_-_-_----------------_-_-_-_-_-_-_-_---------------- + // OUT (SO) --_______________________________------------------------------- + // + // Additionally, in LSDJ sync mode, SO will go low at the start of each bar. + // + // The width of the pulse is approximately 915-916us (122us per pulse at 50% + // duty cycle of 61us). This sync method is based on sync24, so it should + // receive 6 pulses each 1/16th step (96 pulses in a 16 step sequence). + if (first_pulse) { + first_pulse = false; + so_status = 0; + } else { + so_status = 1; + } + TIMER_DATA_3 = 0; + pulses_sent = 0; + gate_status = 0; SIO_MODE = SIO_MODE_GP | SIO_SC_OUT(1) - | SIO_SD_OUT(1) + | SIO_SD_OUT(0) | SIO_SI_OUT(0) | SIO_SO_OUT(1) - | SIO_SC(1) + | SIO_SI(0) + | SIO_SC(0) | SIO_SD(0) - | SIO_SO(1); - int n_ticks = -244181 / 600; - irs_set(IRQ_TIMER_3, gate_off); + | SIO_SO(so_status); + int n_ticks = -9; // 122/2 = 61us; 61 / 3.8 = 16 + irs_set(IRQ_TIMER_3, lsdj_toggle); TIMER_DATA_3 = n_ticks; - TIMER_CTRL_3 = TIMER_CTRL_IRQ | TIMER_CTRL_ENABLE | TIMER_CTRL_FREQ_3; + TIMER_CTRL_3 = TIMER_CTRL_IRQ | TIMER_CTRL_ENABLE | TIMER_CTRL_FREQ_1; } u8 @@ -475,31 +628,36 @@ env_start: void sequencer_tick(void) { - switch (settings.sync) { - case SYNC_OUT_LINK_96BPQ: { gate_on(); } break; - case SYNC_OUT_LINK_48BPQ: { if (sync_ticks++ % 2 == 0) { gate_on(); } } break; - case SYNC_OUT_LINK_24BPQ: { if (sync_ticks++ % 4 == 0) { gate_on(); } } break; - case SYNC_OUT_LINK_12BPQ: { if (sync_ticks++ % 8 == 0) { gate_on(); } } break; - case SYNC_OUT_LINK_6BPQ: { if (sync_ticks++ % 16 == 0) { gate_on(); } } break; - case SYNC_OUT_LINK_4BPQ: { if (sync_ticks++ % 24 == 0) { gate_on(); } } break; - case SYNC_OUT_LINK_2BPQ: { if (sync_ticks++ % 48 == 0) { gate_on(); } } break; - case SYNC_OUT_AUDIO_12BPQ: { if (sync_ticks++ % 8 == 0) { audio_sync_click = true; } } break; - case SYNC_OUT_AUDIO_6BPQ: { if (sync_ticks++ % 16 == 0) { audio_sync_click = true; } } break; - case SYNC_OUT_AUDIO_4BPQ: { if (sync_ticks++ % 24 == 0) { audio_sync_click = true; } } break; - case SYNC_OUT_AUDIO_2BPQ: { if (sync_ticks++ % 48 == 0) { audio_sync_click = true; } } break; - case SYNC_OUT_LINK_AUDIO_12BPQ: { if (sync_ticks++ % 8 == 0) { gate_on(); audio_sync_click = true; } } break; - case SYNC_OUT_LINK_AUDIO_6BPQ: { if (sync_ticks++ % 16 == 0) { gate_on(); audio_sync_click = true; } } break; - case SYNC_OUT_LINK_AUDIO_4BPQ: { if (sync_ticks++ % 24 == 0) { gate_on(); audio_sync_click = true; } } break; - case SYNC_OUT_LINK_AUDIO_2BPQ: { if (sync_ticks++ % 48 == 0) { gate_on(); audio_sync_click = true; } } break; - default: break; - } + // switch (settings.sync) { + // case SYNC_OUT_LINK_96BPQ: { gate_on(); } break; + // case SYNC_OUT_LINK_48BPQ: { if (sync_ticks++ % 2 == 0) { gate_on(); } } break; + // case SYNC_OUT_LINK_24BPQ: { if (sync_ticks++ % 4 == 0) { gate_on(); } } break; + // case SYNC_OUT_LINK_12BPQ: { if (sync_ticks++ % 8 == 0) { gate_on(); } } break; + // case SYNC_OUT_LINK_6BPQ: { if (sync_ticks++ % 16 == 0) { gate_on(); } } break; + // case SYNC_OUT_LINK_4BPQ: { if (sync_ticks++ % 24 == 0) { gate_on(); } } break; + // case SYNC_OUT_LINK_2BPQ: { if (sync_ticks++ % 48 == 0) { gate_on(); } } break; + // case SYNC_OUT_AUDIO_12BPQ: { if (sync_ticks++ % 8 == 0) { audio_sync_click = true; } } break; + // case SYNC_OUT_AUDIO_6BPQ: { if (sync_ticks++ % 16 == 0) { audio_sync_click = true; } } break; + // case SYNC_OUT_AUDIO_4BPQ: { if (sync_ticks++ % 24 == 0) { audio_sync_click = true; } } break; + // case SYNC_OUT_AUDIO_2BPQ: { if (sync_ticks++ % 48 == 0) { audio_sync_click = true; } } break; + // case SYNC_OUT_LINK_AUDIO_12BPQ: { if (sync_ticks++ % 8 == 0) { gate_on(); audio_sync_click = true; } } break; + // case SYNC_OUT_LINK_AUDIO_6BPQ: { if (sync_ticks++ % 16 == 0) { gate_on(); audio_sync_click = true; } } break; + // case SYNC_OUT_LINK_AUDIO_4BPQ: { if (sync_ticks++ % 24 == 0) { gate_on(); audio_sync_click = true; } } break; + // case SYNC_OUT_LINK_AUDIO_2BPQ: { if (sync_ticks++ % 48 == 0) { gate_on(); audio_sync_click = true; } } break; + // default: break; + // } if (nseq_ticks++ == 0) { - play_step(); + if (step_counter % 16 == 0) { + // first_pulse = true; + } + step_counter = (step_counter + 1) % 16; + // play_step(); } + if (sync_ticks++ % 4 == 0) { lsdj_pulse(); } if (nseq_ticks == 24) { nseq_ticks = 0; } - wave_ad_tick(); + // wave_ad_tick(); } void @@ -680,10 +838,23 @@ stop_sound(void) { SOUND_NOISE_CTRL = 0; redraw_play_pause = true; redraw_pattern_buttons = true; + SIO_MODE = SIO_MODE_GP + | SIO_SI_OUT(0) + | SIO_SC_OUT(1) + | SIO_SD_OUT(0) + | SIO_SO_OUT(1) + | SIO_SI(0) + | SIO_SC(1) + | SIO_SD(0) + | SIO_SO(1); } void reset_sequencer(void) { + first_pulse = true; + so_status = 1; + gate_status = 0; + pulses_sent = 0; step_counter = 0; nseq_ticks = 0; sync_ticks = 0; @@ -1984,4 +2155,14 @@ sequencer_init(void) { SOUND_STATUS = SOUND_ENABLE; init_dsound(); set_audio_settings(); + // gate_off(); + SIO_MODE = SIO_MODE_GP + | SIO_SC_OUT(1) + | SIO_SD_OUT(0) + | SIO_SI_OUT(0) + | SIO_SO_OUT(1) + | SIO_SI(0) + | SIO_SC(1) + | SIO_SD(0) + | SIO_SO(1); } -- cgit v1.2.1