diff options
author | Bad Diode <bd@badd10de.dev> | 2024-01-04 14:19:05 +0100 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2024-01-04 14:19:05 +0100 |
commit | 2d397003e2acbfd04019425bef00d0834191cd92 (patch) | |
tree | da37380fc954fa656686645d5bc1f58d1897a200 | |
parent | e1680f8c586dfd111b794c0e6f7cc9ed81a76b0b (diff) | |
download | stepper-2d397003e2acbfd04019425bef00d0834191cd92.tar.gz stepper-2d397003e2acbfd04019425bef00d0834191cd92.zip |
Add new 96ppq sequencer tick timer
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | src/main.c | 38 | ||||
-rw-r--r-- | src/sequencer.c | 43 |
3 files changed, 57 insertions, 28 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.7 | 30 | TARGET := STEPPER-v1.8-dev-01 |
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 | ||
@@ -82,7 +82,7 @@ run: main | |||
82 | mgba-qt $(BIN) | 82 | mgba-qt $(BIN) |
83 | 83 | ||
84 | deploy: | 84 | deploy: |
85 | mount /dev/sdg1 /mnt | 85 | mount /dev/sdf1 /mnt |
86 | cp $(BIN) /mnt | 86 | cp $(BIN) /mnt |
87 | umount /mnt | 87 | umount /mnt |
88 | 88 | ||
@@ -11,11 +11,30 @@ WITH REGARD TO THIS SOFTWARE. | |||
11 | 11 | ||
12 | // TODO: A list of features I would like to get to implement in the near future. | 12 | // TODO: A list of features I would like to get to implement in the near future. |
13 | // | 13 | // |
14 | // High priority: | ||
15 | // + Higher resolution clock to allow for microtiming and more accurate tempo. | ||
16 | // - Look back again at the emulator issues... | ||
17 | // - Fix any bugs we currently have | ||
18 | // - Possible that when we switched banks there is some weird ui behaviour. | ||
19 | // - Add an envelope to ch3, would need to work with a timer in order to make | ||
20 | // it work I think. | ||
21 | // - Hold L/R retriggers at short intervals? | ||
22 | // - Sync via MIDI with the Analogue cables. | ||
23 | // - Channel params should show if there are some already on all triggers and | ||
24 | // modify only the selected parameter, not all of them. | ||
25 | // - Should scale mode be toggleable? | ||
26 | // - Add clipboard sharing between banks. | ||
27 | // - Allow using B + dpad to nudge trigs. This will potentially mean switching | ||
28 | // to key release to enable trigs. | ||
29 | // - Make sure transposing a sequence past the keyboard limit doesn't affect | ||
30 | // the sequence and can be reversed. | ||
31 | // - Study saving overhauls for bootleg cartridges. | ||
32 | // | ||
33 | // Low priority: | ||
34 | // | ||
14 | // UI tweaks. | 35 | // UI tweaks. |
15 | // - Add custom user themes | 36 | // - Add custom user themes |
16 | // - Animations for cursor movement/current step highlight. (A fade out maybe?) | 37 | // - Animations for cursor movement/current step highlight. (A fade out maybe?) |
17 | // - Should the channel parameters reset after leaving them? Is it more or | ||
18 | // less confusing this way? | ||
19 | // | 38 | // |
20 | // Quality of life improvements. | 39 | // Quality of life improvements. |
21 | // - When not on play mode, adjusting a note or a parameter triggers the sound. | 40 | // - When not on play mode, adjusting a note or a parameter triggers the sound. |
@@ -27,24 +46,9 @@ WITH REGARD TO THIS SOFTWARE. | |||
27 | // - Add tap tempo for BPM. | 46 | // - Add tap tempo for BPM. |
28 | // - Allow "marking" several trigs to be able to copy/paste them and/or adjust | 47 | // - Allow "marking" several trigs to be able to copy/paste them and/or adjust |
29 | // their parameters. | 48 | // their parameters. |
30 | // - Add an envelope to ch3, would need to work with a timer in order to make | ||
31 | // it work I think. | ||
32 | // - Sync via MIDI via arduinoboy or something similar. | ||
33 | // - Per trig LFO? How would we go about this? There is at least one empty slot | 49 | // - Per trig LFO? How would we go about this? There is at least one empty slot |
34 | // in all channels. LFO amount? LFO speed? Would need a dedicated page for | 50 | // in all channels. LFO amount? LFO speed? Would need a dedicated page for |
35 | // configuring LFOs | 51 | // configuring LFOs |
36 | // - Per-channel N steps to create polymeters? | ||
37 | // - Channel params should show if there are some already on all triggers and | ||
38 | // modify only the selected parameter, not all of them. | ||
39 | // - Should scale mode be toggleable? | ||
40 | // - Improve SRAM saving to make room for longer patterns and/or more banks. | ||
41 | // - Higher resolution clock to allow for microtiming and more accurate tempo. | ||
42 | // - Add clipboard sharing between banks. | ||
43 | // - Allow using B + dpad to nudge trigs. This will potentially mean switching | ||
44 | // to key release to enable trigs. | ||
45 | // - Channel parameters should only modify the parameter being edited, not all | ||
46 | // of them. | ||
47 | // - Make sure sync works with the same cable for in/out. | ||
48 | 52 | ||
49 | 53 | ||
50 | #include "gba/gba.h" | 54 | #include "gba/gba.h" |
diff --git a/src/sequencer.c b/src/sequencer.c index 632a777..11c0f5a 100644 --- a/src/sequencer.c +++ b/src/sequencer.c | |||
@@ -346,21 +346,46 @@ play_step(void) { | |||
346 | step_counter = (step_counter + 1) % 16; | 346 | step_counter = (step_counter + 1) % 16; |
347 | } | 347 | } |
348 | 348 | ||
349 | static nseq_ticks = 0; | ||
350 | void | ||
351 | sequencer_tick(void) { | ||
352 | if (nseq_ticks++ < 24) { | ||
353 | return; | ||
354 | } | ||
355 | nseq_ticks = 0; | ||
356 | |||
357 | // NOTE: ACK interrupt before play_step??? | ||
358 | play_step(); | ||
359 | } | ||
360 | |||
349 | void | 361 | void |
350 | set_time(int bpm) { | 362 | set_time(int bpm) { |
351 | if (settings.sync == SYNC_IN_LINK) { | 363 | if (settings.sync == SYNC_IN_LINK) { |
352 | return; | 364 | return; |
353 | } | 365 | } |
354 | // The number of ticks of a 1024 cycle clock in a step based on the BPM can | 366 | // We use a high resolution 96 PPQ clock for sequencing. With the following |
355 | // be calculated as: | 367 | // formula we can calculate the time (in seconds) based on the PPQ and BPM: |
356 | // X bpm -> 60000 / 4 / bpm = Y ms = Ye-3 s | 368 | // |
357 | // Y ms -> Ye-3 / 59.99e-9 / 1024 = Z ticks | 369 | // t = 60 / (PPQ * BPM) |
358 | // We have to operate on integer values, so the numbers have been | 370 | // |
359 | // precalculated to `n_ticks = 244181 / bmp` | 371 | // To translate this timer to a GBA timer running at 64 CPU cycles per tick |
360 | int n_ticks = -244181 / bpm; | 372 | // we need to divide this by the constant Q = 3.97329943e-06. In theory, the |
361 | irs_set(IRQ_TIMER_2, play_step); | 373 | // period of this timer running a a frequency of 262.21kHz should be |
374 | // Q = 3.815us, but using this number resulted in a less accurate sequencer | ||
375 | // compared to the metronome of a DAW (Bitwig). Tuning Q using a japanese | ||
376 | // GBA-SP and an Analogue Pocket resulted in the previously mentioned value. | ||
377 | // | ||
378 | // If we factor out the BPM we can obtain a fixed constant: | ||
379 | // | ||
380 | // C = 60 / (96 * 3.97329943e-06) = 157300 | ||
381 | // | ||
382 | // Allowing us to calculate the clock timer as -C/BPM. Note that this is | ||
383 | // integer division and we will be losing the fractional part, resulting in | ||
384 | // some minor precision differences, but it seems to work well in practice. | ||
385 | int n_ticks = -157300 / bpm; | ||
386 | irs_set(IRQ_TIMER_2, sequencer_tick); | ||
362 | TIMER_DATA_2 = n_ticks; | 387 | TIMER_DATA_2 = n_ticks; |
363 | TIMER_CTRL_2 = TIMER_CTRL_IRQ | TIMER_CTRL_ENABLE | TIMER_CTRL_FREQ_3; | 388 | TIMER_CTRL_2 = TIMER_CTRL_IRQ | TIMER_CTRL_ENABLE | TIMER_CTRL_FREQ_1; |
364 | } | 389 | } |
365 | 390 | ||
366 | TriggerNote * | 391 | TriggerNote * |