aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2023-04-24 11:39:58 +0200
committerBad Diode <bd@badd10de.dev>2023-04-24 11:39:58 +0200
commit0fa40db0a578cc2dc3952fe108a332a1e3182452 (patch)
tree3a336e243482525c29eceea1fc7032a68224d2ec
parentfa26d1a58d629c151edab565080e19102a99bfc7 (diff)
downloadstepper-0fa40db0a578cc2dc3952fe108a332a1e3182452.tar.gz
stepper-0fa40db0a578cc2dc3952fe108a332a1e3182452.zip
Add quick BPM adjustment with SEL+L/R
-rw-r--r--src/main.c26
-rw-r--r--src/sequencer.c61
2 files changed, 68 insertions, 19 deletions
diff --git a/src/main.c b/src/main.c
index 0fb018f..3cc5345 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,5 +1,5 @@
1/* 1/*
2Copyright (c) 2021 Bad Diode 2Copyright (c) 2023 Bad Diode
3 3
4Permission to use, copy, modify, and distribute this software for any 4Permission to use, copy, modify, and distribute this software for any
5purpose with or without fee is hereby granted, provided that the above 5purpose with or without fee is hereby granted, provided that the above
@@ -9,6 +9,30 @@ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9WITH REGARD TO THIS SOFTWARE. 9WITH REGARD TO THIS SOFTWARE.
10*/ 10*/
11 11
12// TODO: A list of features I would like to get to implement in the near future.
13//
14// UI tweaks.
15// - Notification support for feedback when doing some operations
16// (copying/pasting)
17// - Animations for cursor movement/current step highlight. (A fade out maybe?)
18// - Display played notes on all tonal channels when a trig or channel is not
19// selected. If a channel is selected show active note in that channel, if
20// a trig is selected behaved as usual. These could be highlighted in
21// different colors to make it easier on the eyes. If a pattern is selected,
22// show the notes it would play on that pattern?
23// - Theming support, with a number of pre-configured themes and custom colors.
24//
25// Quality of life improvements.
26// - Per channel sound adjustments that modify the sound in all trigs.
27// - Per-octave note adjustment with Select + L/R on a trig.
28// - Pattern chaining for more than 1 queue and/or song mode.
29// - Undo/Redo.
30// - Add a settings page to change some configuration parameters.
31//
32// Advanced
33// - Sync via MIDI via arduinoboy or something similar.
34// - Sync via CV by using the link cable.
35
12#include "gba/gba.h" 36#include "gba/gba.h"
13 37
14#include "filesystem.c" 38#include "filesystem.c"
diff --git a/src/sequencer.c b/src/sequencer.c
index 784d132..2940b25 100644
--- a/src/sequencer.c
+++ b/src/sequencer.c
@@ -19,13 +19,15 @@ bool redraw_bpm = true;
19bool redraw_piano_note = true; 19bool redraw_piano_note = true;
20 20
21void 21void
22irq_timer(void) { 22play_step(void) {
23 if (current_pattern != next_pattern && step_counter == 0) { 23 if (current_pattern != next_pattern && step_counter == 15) {
24 current_pattern = next_pattern; 24 current_pattern = next_pattern;
25 redraw_pattern_buttons = true; 25 redraw_pattern_buttons = true;
26 set_time(patterns[current_pattern].bpm);
27 play_step();
28 return;
26 } 29 }
27 Pattern *pat = &patterns[current_pattern]; 30 Pattern *pat = &patterns[current_pattern];
28 set_time(pat->bpm);
29 if (pat->ch1.active) { 31 if (pat->ch1.active) {
30 TriggerNote *trig = &pat->ch1.notes[step_counter]; 32 TriggerNote *trig = &pat->ch1.notes[step_counter];
31 ChannelSquareParams *params = &pat->ch1.params[step_counter]; 33 ChannelSquareParams *params = &pat->ch1.params[step_counter];
@@ -156,7 +158,7 @@ set_time(int bpm) {
156 // We have to operate on integer values, so the numbers have been 158 // We have to operate on integer values, so the numbers have been
157 // precalculated to `n_ticks = 244181 / bmp` 159 // precalculated to `n_ticks = 244181 / bmp`
158 int n_ticks = -244181 / bpm; 160 int n_ticks = -244181 / bpm;
159 irs_set(IRQ_TIMER_0, irq_timer); 161 irs_set(IRQ_TIMER_0, play_step);
160 TIMER_DATA_0 = n_ticks; 162 TIMER_DATA_0 = n_ticks;
161 TIMER_CTRL_0 = TIMER_CTRL_IRQ | TIMER_CTRL_ENABLE | TIMER_CTRL_FREQ_3; 163 TIMER_CTRL_0 = TIMER_CTRL_IRQ | TIMER_CTRL_ENABLE | TIMER_CTRL_FREQ_3;
162} 164}
@@ -242,7 +244,12 @@ toggle_playing(void) {
242 play_status ^= 1; 244 play_status ^= 1;
243 step_counter = 0; 245 step_counter = 0;
244 if ((TIMER_CTRL_0 & TIMER_CTRL_ENABLE) == 0) { 246 if ((TIMER_CTRL_0 & TIMER_CTRL_ENABLE) == 0) {
247 if (current_pattern != next_pattern) {
248 current_pattern = next_pattern;
249 redraw_pattern_buttons = true;
250 }
245 set_time(patterns[current_pattern].bpm); 251 set_time(patterns[current_pattern].bpm);
252 play_step();
246 } else { 253 } else {
247 TIMER_CTRL_0 ^= TIMER_CTRL_ENABLE; 254 TIMER_CTRL_0 ^= TIMER_CTRL_ENABLE;
248 SOUND_SQUARE1_CTRL = 0; 255 SOUND_SQUARE1_CTRL = 0;
@@ -257,7 +264,12 @@ void
257pause_playing(void) { 264pause_playing(void) {
258 play_status ^= 1; 265 play_status ^= 1;
259 if ((TIMER_CTRL_0 & TIMER_CTRL_ENABLE) == 0) { 266 if ((TIMER_CTRL_0 & TIMER_CTRL_ENABLE) == 0) {
267 if (current_pattern != next_pattern && step_counter == 0) {
268 current_pattern = next_pattern;
269 redraw_pattern_buttons = true;
270 }
260 set_time(patterns[current_pattern].bpm); 271 set_time(patterns[current_pattern].bpm);
272 play_step();
261 } else { 273 } else {
262 TIMER_CTRL_0 ^= TIMER_CTRL_ENABLE; 274 TIMER_CTRL_0 ^= TIMER_CTRL_ENABLE;
263 SOUND_SQUARE1_CTRL = 0; 275 SOUND_SQUARE1_CTRL = 0;
@@ -312,27 +324,37 @@ handle_right_col_selection(void) {
312 } else if (key_tap(KEY_L)) { 324 } else if (key_tap(KEY_L)) {
313 switch (right_col_selection_loc) { 325 switch (right_col_selection_loc) {
314 case R_COL_BPM: { 326 case R_COL_BPM: {
315 if (patterns[pattern_selection_loc].bpm > 10) { 327 s32 bpm_inc = -1;
316 patterns[pattern_selection_loc].bpm--; 328 if (key_pressed(KEY_SELECT)) {
317 if ((TIMER_CTRL_0 & TIMER_CTRL_ENABLE) != 0 329 bpm_inc = -10;
318 && current_pattern == pattern_selection_loc) {
319 set_time(patterns[current_pattern].bpm);
320 }
321 redraw_bpm = true;
322 } 330 }
331 patterns[pattern_selection_loc].bpm = CLAMP(
332 patterns[pattern_selection_loc].bpm + bpm_inc,
333 10,
334 300);
335 if ((TIMER_CTRL_0 & TIMER_CTRL_ENABLE) != 0
336 && current_pattern == pattern_selection_loc) {
337 set_time(patterns[current_pattern].bpm);
338 }
339 redraw_bpm = true;
323 } break; 340 } break;
324 } 341 }
325 } else if (key_tap(KEY_R)) { 342 } else if (key_tap(KEY_R)) {
326 switch (right_col_selection_loc) { 343 switch (right_col_selection_loc) {
327 case R_COL_BPM: { 344 case R_COL_BPM: {
328 if (patterns[pattern_selection_loc].bpm < 300) { 345 s32 bpm_inc = 1;
329 patterns[pattern_selection_loc].bpm++; 346 if (key_pressed(KEY_SELECT)) {
330 if ((TIMER_CTRL_0 & TIMER_CTRL_ENABLE) != 0 347 bpm_inc = 10;
331 && current_pattern == pattern_selection_loc) { 348 }
332 set_time(patterns[current_pattern].bpm); 349 patterns[pattern_selection_loc].bpm = CLAMP(
333 } 350 patterns[pattern_selection_loc].bpm + bpm_inc,
334 redraw_bpm = true; 351 10,
352 300);
353 if ((TIMER_CTRL_0 & TIMER_CTRL_ENABLE) != 0
354 && current_pattern == pattern_selection_loc) {
355 set_time(patterns[current_pattern].bpm);
335 } 356 }
357 redraw_bpm = true;
336 } break; 358 } break;
337 } 359 }
338 } else if (key_tap(KEY_B)) { 360 } else if (key_tap(KEY_B)) {
@@ -830,6 +852,9 @@ handle_sequencer_input(void) {
830 clipboard_copy(); 852 clipboard_copy();
831 input_handler(); 853 input_handler();
832 } 854 }
855 if (input_handler == handle_right_col_selection) {
856 input_handler();
857 }
833 // Clipboard combo. 858 // Clipboard combo.
834 else if (key_tap(KEY_A)) { 859 else if (key_tap(KEY_A)) {
835 clipboard_paste(); 860 clipboard_paste();