diff options
author | Bad Diode <bd@badd10de.dev> | 2024-04-25 16:29:44 +0200 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2024-04-25 16:29:44 +0200 |
commit | 901ba917a3b4812f7eacf93d55389978a907a44d (patch) | |
tree | 40848dc90600f928ae981636190ce19498ba3516 | |
parent | c9a48c8cbea8718181632c461a7ed9abae9988e3 (diff) | |
download | stepper-lsdjsync.tar.gz stepper-lsdjsync.zip |
Staging some testing samples for backuplsdjsync
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | src/main.c | 2 | ||||
-rw-r--r-- | src/sequencer.c | 253 |
3 files changed, 219 insertions, 38 deletions
@@ -27,7 +27,7 @@ INC_FLAGS := $(addprefix -I,$(INC_DIRS)) | |||
27 | INC_FLAGS += -I$(LIBGBA_SRC) | 27 | INC_FLAGS += -I$(LIBGBA_SRC) |
28 | 28 | ||
29 | # Output library names and executables. | 29 | # Output library names and executables. |
30 | TARGET := STEPPER-v1.8 | 30 | TARGET := STEPPER-v1.8-dev-lsdj |
31 | ELF := $(BUILD_DIR)/$(TARGET).elf | 31 | ELF := $(BUILD_DIR)/$(TARGET).elf |
32 | BIN := $(BUILD_DIR)/$(TARGET).gba | 32 | BIN := $(BUILD_DIR)/$(TARGET).gba |
33 | 33 | ||
@@ -255,7 +255,7 @@ main(void) { | |||
255 | 255 | ||
256 | // Register interrupts. | 256 | // Register interrupts. |
257 | irq_init(); | 257 | irq_init(); |
258 | irs_set(IRQ_VBLANK, sound_vsync); | 258 | irs_set(IRQ_VBLANK, irs_stub); |
259 | 259 | ||
260 | // Initialize sequencer. | 260 | // Initialize sequencer. |
261 | sequencer_init(); | 261 | 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) { | |||
25 | 25 | ||
26 | void | 26 | void |
27 | gate_off(void) { | 27 | gate_off(void) { |
28 | SIO_MODE = SIO_MODE_GP | 28 | // SIO_MODE = SIO_MODE_GP |
29 | | SIO_SC_OUT(1) | 29 | // | SIO_SC_OUT(1) |
30 | | SIO_SD_OUT(1) | 30 | // | SIO_SD_OUT(0) |
31 | | SIO_SI_OUT(0) | 31 | // | SIO_SI_OUT(0) |
32 | | SIO_SO_OUT(1) | 32 | // | SIO_SO_OUT(0) |
33 | | SIO_SC(0) | 33 | // | SIO_SI(0) |
34 | | SIO_SD(0) | 34 | // | SIO_SC(0) |
35 | | SIO_SO(0); | 35 | // | SIO_SD(0) |
36 | TIMER_CTRL_3 = 0; | 36 | // | SIO_SO(0); |
37 | // TIMER_CTRL_3 = 0; | ||
38 | } | ||
39 | |||
40 | int pulses_sent = 0; | ||
41 | int gate_status = 0; | ||
42 | |||
43 | void | ||
44 | gate_lsdj(void) { | ||
45 | gate_status ^= 1; | ||
46 | if (pulses_sent >= 7) { | ||
47 | gate_off(); | ||
48 | return; | ||
49 | } | ||
50 | if (gate_status == 1) { | ||
51 | gate_off(); | ||
52 | } else { | ||
53 | pulses_sent++; | ||
54 | SIO_MODE = SIO_MODE_GP | ||
55 | | SIO_SC_OUT(1) | ||
56 | | SIO_SD_OUT(0) | ||
57 | | SIO_SI_OUT(0) | ||
58 | | SIO_SO_OUT(0) | ||
59 | | SIO_SI(0) | ||
60 | | SIO_SC(1) | ||
61 | | SIO_SD(0) | ||
62 | | SIO_SO(0); | ||
63 | } | ||
64 | int n_ticks = -80 / 8 / 2; // 5ms | ||
65 | irs_set(IRQ_TIMER_3, gate_lsdj); | ||
66 | TIMER_DATA_3 = n_ticks; | ||
67 | TIMER_CTRL_3 = TIMER_CTRL_IRQ | TIMER_CTRL_ENABLE | TIMER_CTRL_FREQ_3; | ||
37 | } | 68 | } |
38 | 69 | ||
70 | // TODO: LSDJ sync pulse? | ||
71 | |||
39 | void | 72 | void |
40 | gate_on(void) { | 73 | gate_on(void) { |
41 | gate_off(); | 74 | // SYNC24 NOTES |
75 | // (from https://e-rm.de/data/E-RM_report_HowToDinSync_10_14_EN.pdf) | ||
76 | // | ||
77 | // "Moreover, a duty cycle of 50% doesn’t seem to be nescessary, all tested | ||
78 | // machines were able to sync properly to clock ticks with a positive width | ||
79 | // of 5 ms to up to 300 BPM" @ 24bpq | ||
80 | // | ||
81 | // int bpm = 100; | ||
82 | // if (settings.global_bpm) { | ||
83 | // bpm = settings.bpm; | ||
84 | // } else { | ||
85 | // bpm patterns[current_pattern].bpm; | ||
86 | // } | ||
87 | // gate_off(); | ||
88 | // pulses_sent = 0; | ||
89 | // gate_status = 0; | ||
90 | // SIO_MODE = SIO_MODE_GP | ||
91 | // | SIO_SC_OUT(1) | ||
92 | // | SIO_SD_OUT(0) | ||
93 | // | SIO_SI_OUT(0) | ||
94 | // | SIO_SO_OUT(0) | ||
95 | // | SIO_SI(0) | ||
96 | // | SIO_SC(1) | ||
97 | // | SIO_SD(0) | ||
98 | // | SIO_SO(0); | ||
99 | // // int n_ticks = -80; // 5ms | ||
100 | // // irs_set(IRQ_TIMER_3, gate_off); | ||
101 | // // TIMER_DATA_3 = n_ticks; | ||
102 | // // TIMER_CTRL_3 = TIMER_CTRL_IRQ | TIMER_CTRL_ENABLE | TIMER_CTRL_FREQ_3; | ||
103 | // int n_ticks = -80 / 8 / 2; // 5ms | ||
104 | // irs_set(IRQ_TIMER_3, gate_lsdj); | ||
105 | // TIMER_DATA_3 = n_ticks; | ||
106 | // TIMER_CTRL_3 = TIMER_CTRL_IRQ | TIMER_CTRL_ENABLE | TIMER_CTRL_FREQ_3; | ||
107 | // int n_ticks = -79; // 5ms | ||
108 | // TIMER_DATA_3 = n_ticks; | ||
109 | // TIMER_CTRL_3 = TIMER_CTRL_ENABLE | TIMER_CTRL_FREQ_3; | ||
110 | // while (1) { | ||
111 | // int cnt = TIMER_DATA_3; | ||
112 | // if (cnt >= 80) { | ||
113 | // gate_off(); | ||
114 | // break; | ||
115 | // } | ||
116 | // } | ||
117 | } | ||
118 | |||
119 | bool first_pulse = true; | ||
120 | int so_status = 1; | ||
121 | |||
122 | void | ||
123 | lsdj_toggle(void) { | ||
124 | gate_status ^= 1; | ||
125 | if (pulses_sent >= 7) { | ||
126 | TIMER_CTRL_3 = 0; | ||
127 | SIO_MODE = SIO_MODE_GP | ||
128 | | SIO_SI_OUT(0) | ||
129 | | SIO_SC_OUT(1) | ||
130 | | SIO_SD_OUT(0) | ||
131 | | SIO_SO_OUT(1) | ||
132 | | SIO_SI(0) | ||
133 | | SIO_SC(1) | ||
134 | | SIO_SD(0) | ||
135 | | SIO_SO(so_status); | ||
136 | return; | ||
137 | } | ||
138 | if (gate_status == 1) { | ||
139 | SIO_MODE = SIO_MODE_GP | ||
140 | | SIO_SI_OUT(0) | ||
141 | | SIO_SC_OUT(1) | ||
142 | | SIO_SD_OUT(0) | ||
143 | | SIO_SO_OUT(1) | ||
144 | | SIO_SI(0) | ||
145 | | SIO_SC(1) | ||
146 | | SIO_SD(0) | ||
147 | | SIO_SO(so_status); | ||
148 | } else { | ||
149 | pulses_sent++; | ||
150 | SIO_MODE = SIO_MODE_GP | ||
151 | | SIO_SI_OUT(0) | ||
152 | | SIO_SC_OUT(1) | ||
153 | | SIO_SD_OUT(0) | ||
154 | | SIO_SO_OUT(1) | ||
155 | | SIO_SI(0) | ||
156 | | SIO_SC(0) | ||
157 | | SIO_SD(0) | ||
158 | | SIO_SO(so_status); | ||
159 | } | ||
160 | TIMER_CTRL_3 = 0; | ||
161 | // int n_ticks = -80 / 8 / 2; // 5ms | ||
162 | // irs_set(IRQ_TIMER_3, lsdj_toggle); | ||
163 | // TIMER_DATA_3 = n_ticks; | ||
164 | // TIMER_CTRL_3 = TIMER_CTRL_IRQ | TIMER_CTRL_ENABLE | TIMER_CTRL_FREQ_3; | ||
165 | int n_ticks = -9; // 122/2 = 61us; 61 / 3.8 = 16 | ||
166 | irs_set(IRQ_TIMER_3, lsdj_toggle); | ||
167 | TIMER_DATA_3 = n_ticks; | ||
168 | TIMER_CTRL_3 = TIMER_CTRL_IRQ | TIMER_CTRL_ENABLE | TIMER_CTRL_FREQ_1; | ||
169 | } | ||
170 | |||
171 | void | ||
172 | lsdj_pulse(void) { | ||
173 | // LSDJ expects a pulse train on the SC pin (active low?). For the song | ||
174 | // start, the first pulse and until the start of the second one it should | ||
175 | // set SO to low as follows: | ||
176 | // | ||
177 | // CLK (SC) --_-_-_-_-_-_-_-_----------------_-_-_-_-_-_-_-_---------------- | ||
178 | // OUT (SO) --_______________________________------------------------------- | ||
179 | // | ||
180 | // Additionally, in LSDJ sync mode, SO will go low at the start of each bar. | ||
181 | // | ||
182 | // The width of the pulse is approximately 915-916us (122us per pulse at 50% | ||
183 | // duty cycle of 61us). This sync method is based on sync24, so it should | ||
184 | // receive 6 pulses each 1/16th step (96 pulses in a 16 step sequence). | ||
185 | if (first_pulse) { | ||
186 | first_pulse = false; | ||
187 | so_status = 0; | ||
188 | } else { | ||
189 | so_status = 1; | ||
190 | } | ||
191 | TIMER_DATA_3 = 0; | ||
192 | pulses_sent = 0; | ||
193 | gate_status = 0; | ||
42 | SIO_MODE = SIO_MODE_GP | 194 | SIO_MODE = SIO_MODE_GP |
43 | | SIO_SC_OUT(1) | 195 | | SIO_SC_OUT(1) |
44 | | SIO_SD_OUT(1) | 196 | | SIO_SD_OUT(0) |
45 | | SIO_SI_OUT(0) | 197 | | SIO_SI_OUT(0) |
46 | | SIO_SO_OUT(1) | 198 | | SIO_SO_OUT(1) |
47 | | SIO_SC(1) | 199 | | SIO_SI(0) |
200 | | SIO_SC(0) | ||
48 | | SIO_SD(0) | 201 | | SIO_SD(0) |
49 | | SIO_SO(1); | 202 | | SIO_SO(so_status); |
50 | int n_ticks = -244181 / 600; | 203 | int n_ticks = -9; // 122/2 = 61us; 61 / 3.8 = 16 |
51 | irs_set(IRQ_TIMER_3, gate_off); | 204 | irs_set(IRQ_TIMER_3, lsdj_toggle); |
52 | TIMER_DATA_3 = n_ticks; | 205 | TIMER_DATA_3 = n_ticks; |
53 | TIMER_CTRL_3 = TIMER_CTRL_IRQ | TIMER_CTRL_ENABLE | TIMER_CTRL_FREQ_3; | 206 | TIMER_CTRL_3 = TIMER_CTRL_IRQ | TIMER_CTRL_ENABLE | TIMER_CTRL_FREQ_1; |
54 | } | 207 | } |
55 | 208 | ||
56 | u8 | 209 | u8 |
@@ -475,31 +628,36 @@ env_start: | |||
475 | 628 | ||
476 | void | 629 | void |
477 | sequencer_tick(void) { | 630 | sequencer_tick(void) { |
478 | switch (settings.sync) { | 631 | // switch (settings.sync) { |
479 | case SYNC_OUT_LINK_96BPQ: { gate_on(); } break; | 632 | // case SYNC_OUT_LINK_96BPQ: { gate_on(); } break; |
480 | case SYNC_OUT_LINK_48BPQ: { if (sync_ticks++ % 2 == 0) { gate_on(); } } break; | 633 | // case SYNC_OUT_LINK_48BPQ: { if (sync_ticks++ % 2 == 0) { gate_on(); } } break; |
481 | case SYNC_OUT_LINK_24BPQ: { if (sync_ticks++ % 4 == 0) { gate_on(); } } break; | 634 | // case SYNC_OUT_LINK_24BPQ: { if (sync_ticks++ % 4 == 0) { gate_on(); } } break; |
482 | case SYNC_OUT_LINK_12BPQ: { if (sync_ticks++ % 8 == 0) { gate_on(); } } break; | 635 | // case SYNC_OUT_LINK_12BPQ: { if (sync_ticks++ % 8 == 0) { gate_on(); } } break; |
483 | case SYNC_OUT_LINK_6BPQ: { if (sync_ticks++ % 16 == 0) { gate_on(); } } break; | 636 | // case SYNC_OUT_LINK_6BPQ: { if (sync_ticks++ % 16 == 0) { gate_on(); } } break; |
484 | case SYNC_OUT_LINK_4BPQ: { if (sync_ticks++ % 24 == 0) { gate_on(); } } break; | 637 | // case SYNC_OUT_LINK_4BPQ: { if (sync_ticks++ % 24 == 0) { gate_on(); } } break; |
485 | case SYNC_OUT_LINK_2BPQ: { if (sync_ticks++ % 48 == 0) { gate_on(); } } break; | 638 | // case SYNC_OUT_LINK_2BPQ: { if (sync_ticks++ % 48 == 0) { gate_on(); } } break; |
486 | case SYNC_OUT_AUDIO_12BPQ: { if (sync_ticks++ % 8 == 0) { audio_sync_click = true; } } break; | 639 | // case SYNC_OUT_AUDIO_12BPQ: { if (sync_ticks++ % 8 == 0) { audio_sync_click = true; } } break; |
487 | case SYNC_OUT_AUDIO_6BPQ: { if (sync_ticks++ % 16 == 0) { audio_sync_click = true; } } break; | 640 | // case SYNC_OUT_AUDIO_6BPQ: { if (sync_ticks++ % 16 == 0) { audio_sync_click = true; } } break; |
488 | case SYNC_OUT_AUDIO_4BPQ: { if (sync_ticks++ % 24 == 0) { audio_sync_click = true; } } break; | 641 | // case SYNC_OUT_AUDIO_4BPQ: { if (sync_ticks++ % 24 == 0) { audio_sync_click = true; } } break; |
489 | case SYNC_OUT_AUDIO_2BPQ: { if (sync_ticks++ % 48 == 0) { audio_sync_click = true; } } break; | 642 | // case SYNC_OUT_AUDIO_2BPQ: { if (sync_ticks++ % 48 == 0) { audio_sync_click = true; } } break; |
490 | case SYNC_OUT_LINK_AUDIO_12BPQ: { if (sync_ticks++ % 8 == 0) { gate_on(); audio_sync_click = true; } } break; | 643 | // case SYNC_OUT_LINK_AUDIO_12BPQ: { if (sync_ticks++ % 8 == 0) { gate_on(); audio_sync_click = true; } } break; |
491 | case SYNC_OUT_LINK_AUDIO_6BPQ: { if (sync_ticks++ % 16 == 0) { gate_on(); audio_sync_click = true; } } break; | 644 | // case SYNC_OUT_LINK_AUDIO_6BPQ: { if (sync_ticks++ % 16 == 0) { gate_on(); audio_sync_click = true; } } break; |
492 | case SYNC_OUT_LINK_AUDIO_4BPQ: { if (sync_ticks++ % 24 == 0) { gate_on(); audio_sync_click = true; } } break; | 645 | // case SYNC_OUT_LINK_AUDIO_4BPQ: { if (sync_ticks++ % 24 == 0) { gate_on(); audio_sync_click = true; } } break; |
493 | case SYNC_OUT_LINK_AUDIO_2BPQ: { if (sync_ticks++ % 48 == 0) { gate_on(); audio_sync_click = true; } } break; | 646 | // case SYNC_OUT_LINK_AUDIO_2BPQ: { if (sync_ticks++ % 48 == 0) { gate_on(); audio_sync_click = true; } } break; |
494 | default: break; | 647 | // default: break; |
495 | } | 648 | // } |
496 | if (nseq_ticks++ == 0) { | 649 | if (nseq_ticks++ == 0) { |
497 | play_step(); | 650 | if (step_counter % 16 == 0) { |
651 | // first_pulse = true; | ||
652 | } | ||
653 | step_counter = (step_counter + 1) % 16; | ||
654 | // play_step(); | ||
498 | } | 655 | } |
656 | if (sync_ticks++ % 4 == 0) { lsdj_pulse(); } | ||
499 | if (nseq_ticks == 24) { | 657 | if (nseq_ticks == 24) { |
500 | nseq_ticks = 0; | 658 | nseq_ticks = 0; |
501 | } | 659 | } |
502 | wave_ad_tick(); | 660 | // wave_ad_tick(); |
503 | } | 661 | } |
504 | 662 | ||
505 | void | 663 | void |
@@ -680,10 +838,23 @@ stop_sound(void) { | |||
680 | SOUND_NOISE_CTRL = 0; | 838 | SOUND_NOISE_CTRL = 0; |
681 | redraw_play_pause = true; | 839 | redraw_play_pause = true; |
682 | redraw_pattern_buttons = true; | 840 | redraw_pattern_buttons = true; |
841 | SIO_MODE = SIO_MODE_GP | ||
842 | | SIO_SI_OUT(0) | ||
843 | | SIO_SC_OUT(1) | ||
844 | | SIO_SD_OUT(0) | ||
845 | | SIO_SO_OUT(1) | ||
846 | | SIO_SI(0) | ||
847 | | SIO_SC(1) | ||
848 | | SIO_SD(0) | ||
849 | | SIO_SO(1); | ||
683 | } | 850 | } |
684 | 851 | ||
685 | void | 852 | void |
686 | reset_sequencer(void) { | 853 | reset_sequencer(void) { |
854 | first_pulse = true; | ||
855 | so_status = 1; | ||
856 | gate_status = 0; | ||
857 | pulses_sent = 0; | ||
687 | step_counter = 0; | 858 | step_counter = 0; |
688 | nseq_ticks = 0; | 859 | nseq_ticks = 0; |
689 | sync_ticks = 0; | 860 | sync_ticks = 0; |
@@ -1984,4 +2155,14 @@ sequencer_init(void) { | |||
1984 | SOUND_STATUS = SOUND_ENABLE; | 2155 | SOUND_STATUS = SOUND_ENABLE; |
1985 | init_dsound(); | 2156 | init_dsound(); |
1986 | set_audio_settings(); | 2157 | set_audio_settings(); |
2158 | // gate_off(); | ||
2159 | SIO_MODE = SIO_MODE_GP | ||
2160 | | SIO_SC_OUT(1) | ||
2161 | | SIO_SD_OUT(0) | ||
2162 | | SIO_SI_OUT(0) | ||
2163 | | SIO_SO_OUT(1) | ||
2164 | | SIO_SI(0) | ||
2165 | | SIO_SC(1) | ||
2166 | | SIO_SD(0) | ||
2167 | | SIO_SO(1); | ||
1987 | } | 2168 | } |