From f2a20887b57ccad5286ee22d0fe6f8342df1750a Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Fri, 10 May 2024 22:32:21 +0200 Subject: Add a more accurate LSDJ sync method, including SO out --- src/sequencer.c | 116 +++++++++++++++++++++++--------------------------------- src/settings.h | 2 + 2 files changed, 50 insertions(+), 68 deletions(-) (limited to 'src') diff --git a/src/sequencer.c b/src/sequencer.c index 9e39cc7..4f57ec8 100644 --- a/src/sequencer.c +++ b/src/sequencer.c @@ -35,30 +35,6 @@ gate_set(u8 sc, u8 so) { | SIO_SI(0); } -int pulses_sent = 0; -int gate_status = 0; - -void -gate_lsdj(void) { - gate_status ^= 1; - if (pulses_sent >= 7) { - gate_set(0, 0); - return; - } - if (gate_status == 1) { - gate_set(0, 0); - } else { - pulses_sent++; - gate_set(1, 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) { // // SYNC24 NOTES @@ -106,60 +82,56 @@ gate_lsdj(void) { // // } //} -bool first_pulse = true; -int so_status = 1; - -void -lsdj_toggle(void) { - gate_status ^= 1; - if (pulses_sent >= 7) { - TIMER_CTRL_3 = 0; - gate_set(1, so_status); - return; - } - if (gate_status == 1) { - gate_set(1, so_status); - } else { - pulses_sent++; - gate_set(0, 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; -} +int pulse_count = 0; +int pulse_value = 0; +int gate_status = 0; 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: +send_pulse(void) { + // LSDJ expects a pulse train on the SC pin (active low). For the song + // start, the first pulse indicates the starting row, for example, for row + // 0x06: // // CLK (SC) --_-_-_-_-_-_-_-_----------------_-_-_-_-_-_-_-_---------------- - // OUT (SO) --_______________________________------------------------------- + // OUT (SO) --__________----_________________------------------------------- + // + // Additionally, in LSDJ sync mode, at the start of each bar, SO should send + // the 0x01 byte (active low). // - // Additionally, in LSDJ sync mode, SO will go low at the start of each bar. + // CLK (SC) --_-_-_-_-_-_-_-_----------------_-_-_-_-_-_-_-_---------------- + // OUT (SO) --____________--_________________------------------------------- // // 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; + TIMER_CTRL_3 = 0; + gate_set(gate_status, (pulse_value >> (7 - pulse_count)) & 0x1); + gate_status ^= 1; + if (gate_status == 0) { + pulse_count++; + } + if (pulse_count <= 7) { + int n_ticks = -9; // 122/2 = 61us; 61 / 3.8 = 16 + irs_set(IRQ_TIMER_3, send_pulse); + TIMER_DATA_3 = n_ticks; + TIMER_CTRL_3 = TIMER_CTRL_IRQ | TIMER_CTRL_ENABLE | TIMER_CTRL_FREQ_1; } else { - so_status = 1; + pulse_value = 0; + pulse_count = 0; } +} + +void +send_lsdj_pulse(u8 out_byte) { + pulse_value = out_byte; + + // Reset timer. TIMER_DATA_3 = 0; - pulses_sent = 0; + pulse_value = out_byte; + pulse_count = 0; gate_status = 0; - gate_set(0, so_status); int n_ticks = -9; // 122/2 = 61us; 61 / 3.8 = 16 - irs_set(IRQ_TIMER_3, lsdj_toggle); + irs_set(IRQ_TIMER_3, send_pulse); TIMER_DATA_3 = n_ticks; TIMER_CTRL_3 = TIMER_CTRL_IRQ | TIMER_CTRL_ENABLE | TIMER_CTRL_FREQ_1; } @@ -607,10 +579,19 @@ sequencer_tick(void) { // case SYNC_OUT_LINK_AUDIO_2BPQ: { if (sync_ticks++ % 48 == 0) { gate_on(); audio_sync_click = true; } } break; // default: break; // } + // TODO: case sync_out_lsdj + if (sync_ticks++ % 4 == 0) { + u8 val = 0xff; + if ((sync_ticks - 1) == 0) { + val = 7; // DEBUG: Depends on pattern + bank. + } else if ((sync_ticks - 1) % 384 == 0) { + val = 253; + } + send_lsdj_pulse(val); + } if (nseq_ticks++ == 0) { play_step(); } - if (sync_ticks++ % 4 == 0) { lsdj_pulse(); } if (nseq_ticks == 24) { nseq_ticks = 0; } @@ -800,10 +781,9 @@ stop_sound(void) { void reset_sequencer(void) { - first_pulse = true; - so_status = 1; + TIMER_CTRL_3 = 0; + gate_set(1, 1); gate_status = 0; - pulses_sent = 0; step_counter = 0; nseq_ticks = 0; sync_ticks = 0; diff --git a/src/settings.h b/src/settings.h index bbfdfd2..73da88f 100644 --- a/src/settings.h +++ b/src/settings.h @@ -28,6 +28,7 @@ typedef enum SyncSetting { SYNC_OUT_LINK_AUDIO_6BPQ, SYNC_OUT_LINK_AUDIO_4BPQ, SYNC_OUT_LINK_AUDIO_2BPQ, + SYNC_OUT_LSDJ, SYNC_IN_LINK_96BPQ, SYNC_IN_LINK_48BPQ, SYNC_IN_LINK_24BPQ, @@ -54,6 +55,7 @@ char * sync_setting_str[] = { "LINK+AUDIO OUT (6BPQ)", "LINK+AUDIO OUT (4BPQ)", "LINK+AUDIO OUT (2BPQ)", + "LSDJ OUT", "LINK IN (96BPQ)", "LINK IN (48BPQ)", "LINK IN (24BPQ)", -- cgit v1.2.1