tangled
alpha
login
or
join now
ericwood.org
/
macropad-sequencer
1
fork
atom
A step sequencer for Adafruit's RP2040-based macropad
1
fork
atom
overview
issues
pulls
pipelines
hold keys to limit steps
ericwood.org
2 months ago
f802729c
ea61030c
+19
-19
3 changed files
expand all
collapse all
unified
split
src
main.rs
tasks
controls.rs
sequencer.rs
+3
-4
src/main.rs
···
1
1
#![no_std]
2
2
#![no_main]
3
3
4
4
-
use core::sync::atomic::{AtomicBool, AtomicU8, AtomicU32};
5
5
-
6
4
use embassy_executor::Spawner;
7
5
use embassy_rp::{
8
6
Peri, bind_interrupts,
···
40
38
PIO0_IRQ_0 => PioInterruptHandler<PIO0>;
41
39
});
42
40
43
43
-
const COLS: usize = 3;
44
44
-
const ROWS: usize = 4;
41
41
+
static COLS: usize = 3;
42
42
+
static ROWS: usize = 4;
43
43
+
static NUM_KEYS: usize = ROWS * COLS;
45
44
type KeyGrid<T> = [[T; COLS]; ROWS];
46
45
47
46
#[embassy_executor::main]
+15
-5
src/tasks/controls.rs
···
2
2
use smart_leds::RGB;
3
3
4
4
use crate::{
5
5
-
COLS, KeyGrid, ROWS,
5
5
+
COLS, KeyGrid, NUM_KEYS, ROWS,
6
6
key_leds::Coord,
7
7
menus::{SEQUENCER_MENU, SequencerMenuValue, StepMenuValue},
8
8
tasks::{
···
16
16
pub enum ControlEvent {
17
17
Key { pressed: bool, coord: Coord },
18
18
RotaryButton { pressed: bool },
19
19
-
SequencerStep { coord: Coord },
19
19
+
SequencerStep,
20
20
RotaryEncoder { increment: i32 },
21
21
SequencerMenuChange { value: SequencerMenuValue },
22
22
StepMenuChange { value: StepMenuValue },
···
39
39
40
40
let mut num_keys_pressed = 0;
41
41
let mut selected_step: Option<Coord> = None;
42
42
+
let mut step_index: usize = 0;
42
43
let mut step: Coord = (0, 0);
43
44
44
45
loop {
···
78
79
rotary_press().await;
79
80
}
80
81
ControlEvent::RotaryEncoder { increment } => rotary_change(increment).await,
81
81
-
ControlEvent::SequencerStep { coord } => {
82
82
+
ControlEvent::SequencerStep => {
82
83
let prev_color = if step_state[step.1 as usize][step.0 as usize].active {
83
84
active
84
85
} else {
85
86
off
86
87
};
87
88
89
89
+
step_index = (step_index + 1).rem_euclid(NUM_KEYS);
90
90
+
let mut next_step = ((step_index % COLS) as u8, (step_index / COLS) as u8);
91
91
+
if num_keys_pressed > 0 {
92
92
+
while !step_state[next_step.1 as usize][next_step.0 as usize].pressed {
93
93
+
step_index = (step_index + 1).rem_euclid(NUM_KEYS);
94
94
+
next_step = ((step_index % COLS) as u8, (step_index / COLS) as u8);
95
95
+
}
96
96
+
}
97
97
+
88
98
update_key_light(step, prev_color).await;
89
89
-
update_key_light(coord, current).await;
90
90
-
step = coord;
99
99
+
update_key_light(next_step, current).await;
100
100
+
step = next_step;
91
101
}
92
102
ControlEvent::SequencerMenuChange { value } => unsafe {
93
103
SEQUENCER_MENU.lock_mut(|inner| *inner = Some(value));
+1
-10
src/tasks/sequencer.rs
···
1
1
use crate::{
2
2
-
COLS,
3
2
menus::{SEQUENCER_MENU, SequencerMenuValue},
4
3
sequencer_timer::{SequencerConfig, SequencerTimer},
5
4
tasks::{CONTROLS_CHANNEL, controls::ControlEvent},
···
7
6
8
7
#[embassy_executor::task]
9
8
pub async fn sequencer() {
10
10
-
let mut step: u8 = 0;
11
11
-
let cols = COLS as u8;
12
12
-
13
9
let mut timer = SequencerTimer::new();
14
10
let mut play = false;
15
11
loop {
···
25
21
});
26
22
27
23
if play {
28
28
-
let coord = (step % cols, step / cols);
29
29
-
CONTROLS_CHANNEL
30
30
-
.send(ControlEvent::SequencerStep { coord })
31
31
-
.await;
32
32
-
33
33
-
step = (step + 1).rem_euclid(12);
24
24
+
CONTROLS_CHANNEL.send(ControlEvent::SequencerStep).await;
34
25
}
35
26
36
27
timer.next_step().await;