aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2024-01-04 14:19:05 +0100
committerBad Diode <bd@badd10de.dev>2024-01-04 14:19:05 +0100
commit2d397003e2acbfd04019425bef00d0834191cd92 (patch)
treeda37380fc954fa656686645d5bc1f58d1897a200
parente1680f8c586dfd111b794c0e6f7cc9ed81a76b0b (diff)
downloadstepper-2d397003e2acbfd04019425bef00d0834191cd92.tar.gz
stepper-2d397003e2acbfd04019425bef00d0834191cd92.zip
Add new 96ppq sequencer tick timer
-rw-r--r--Makefile4
-rw-r--r--src/main.c38
-rw-r--r--src/sequencer.c43
3 files changed, 57 insertions, 28 deletions
diff --git a/Makefile b/Makefile
index 00e643d..960a8a6 100644
--- a/Makefile
+++ b/Makefile
@@ -27,7 +27,7 @@ INC_FLAGS := $(addprefix -I,$(INC_DIRS))
27INC_FLAGS += -I$(LIBGBA_SRC) 27INC_FLAGS += -I$(LIBGBA_SRC)
28 28
29# Output library names and executables. 29# Output library names and executables.
30TARGET := STEPPER-v1.7 30TARGET := STEPPER-v1.8-dev-01
31ELF := $(BUILD_DIR)/$(TARGET).elf 31ELF := $(BUILD_DIR)/$(TARGET).elf
32BIN := $(BUILD_DIR)/$(TARGET).gba 32BIN := $(BUILD_DIR)/$(TARGET).gba
33 33
@@ -82,7 +82,7 @@ run: main
82 mgba-qt $(BIN) 82 mgba-qt $(BIN)
83 83
84deploy: 84deploy:
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
diff --git a/src/main.c b/src/main.c
index 4502dbd..2e64275 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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
349static nseq_ticks = 0;
350void
351sequencer_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
349void 361void
350set_time(int bpm) { 362set_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
366TriggerNote * 391TriggerNote *