|
|
|
use crate::{LayerSelect, Sequencer};
|
|
|
|
use embedded_hal::digital::v2::{InputPin, OutputPin};
|
|
|
|
use stm32f1xx_hal::gpio::{
|
|
|
|
gpioa::{PA1, PA2, PA3, PA4},
|
|
|
|
gpiob::{PB0, PB1, PB5, PB6, PB7, PB8, PB9},
|
|
|
|
Input, Output, PullDown, PushPull,
|
|
|
|
};
|
|
|
|
|
|
|
|
struct NoneOutput;
|
|
|
|
|
|
|
|
impl OutputPin for NoneOutput {
|
|
|
|
type Error = ();
|
|
|
|
|
|
|
|
fn set_low(&mut self) -> Result<(), ()> {
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
fn set_high(&mut self) -> Result<(), ()> {
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// An I/O abstraction for yesman
|
|
|
|
///
|
|
|
|
/// The main I/O of the yesman module is buttons as inputs that need
|
|
|
|
/// to be polled, and LEDs as outputs. All LED states are written at
|
|
|
|
/// the same time. An "active step" can be fed into the `Io`
|
|
|
|
/// abstraction from the `Sequencer` module.
|
|
|
|
pub struct Io {
|
|
|
|
// LED output states
|
|
|
|
pub led1: PA1<Output<PushPull>>,
|
|
|
|
pub led2: PA2<Output<PushPull>>,
|
|
|
|
pub led3: PA3<Output<PushPull>>,
|
|
|
|
pub led4: PA4<Output<PushPull>>,
|
|
|
|
|
|
|
|
// Button input states
|
|
|
|
pub btn1: PB0<Input<PullDown>>,
|
|
|
|
pub btn1_last: bool,
|
|
|
|
|
|
|
|
pub btn2: PB1<Input<PullDown>>,
|
|
|
|
pub btn2_last: bool,
|
|
|
|
|
|
|
|
pub btn3: PB5<Input<PullDown>>,
|
|
|
|
pub btn3_last: bool,
|
|
|
|
|
|
|
|
pub btn4: PB6<Input<PullDown>>,
|
|
|
|
pub btn4_last: bool,
|
|
|
|
|
|
|
|
// Eurorack signal I/O
|
|
|
|
pub clk: PB7<Input<PullDown>>,
|
|
|
|
pub clk_last: bool,
|
|
|
|
pub clk_led: PB9<Output<PushPull>>,
|
|
|
|
|
|
|
|
pub gate: PB8<Output<PushPull>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Io {
|
|
|
|
/// Check the state of each pin and update the sequencer accordingly
|
|
|
|
pub fn update_sequence(&mut self, seq: &mut Sequencer) {
|
|
|
|
// Update sequencer states based on button inputs
|
|
|
|
// btn_rising_edge(&mut self.btn1_last, &mut self.btn1, || seq.toggle(0));
|
|
|
|
// btn_rising_edge(&mut self.btn2_last, &mut self.btn2, || seq.toggle(1));
|
|
|
|
// btn_rising_edge(&mut self.btn3_last, &mut self.btn3, || seq.toggle(2));
|
|
|
|
// btn_rising_edge(&mut self.btn4_last, &mut self.btn4, || seq.toggle(3));
|
|
|
|
|
|
|
|
// // Update LED states based on sequencer
|
|
|
|
// let l = seq.layer(LayerSelect::A);
|
|
|
|
// set_output(&mut self.led1, l[0]);
|
|
|
|
// set_output(&mut self.led2, l[1]);
|
|
|
|
// set_output(&mut self.led3, l[2]);
|
|
|
|
// set_output(&mut self.led4, l[3]);
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn update_cv(&mut self, seq: &mut Sequencer) {
|
|
|
|
// Always output the current steps - if no clock is coming in this will change nothing in our output
|
|
|
|
// set_output(&mut self.gate, !seq.get().0);
|
|
|
|
|
|
|
|
// // On a rising clock edge, step the sequencer
|
|
|
|
// rising_edge(
|
|
|
|
// &mut self.clk_last,
|
|
|
|
// &mut self.clk,
|
|
|
|
// &mut self.clk_led,
|
|
|
|
// |led| {
|
|
|
|
// set_output(led, false);
|
|
|
|
// },
|
|
|
|
// );
|
|
|
|
|
|
|
|
// If the clock pin is high
|
|
|
|
if let Ok(true) = self.clk.is_high() {
|
|
|
|
// And this is the first time we run this code
|
|
|
|
if !self.clk_last {
|
|
|
|
// Just set the LED to on for now
|
|
|
|
self.clk_led.set_high().ok();
|
|
|
|
self.clk_last = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the clock pin goes low
|
|
|
|
} else if let Ok(false) = self.clk.is_high() {
|
|
|
|
// We set the `last` bool to false and reset the LED
|
|
|
|
self.clk_last = false;
|
|
|
|
self.clk_led.set_low().ok();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// If the button is pressed _and_ it was previously not pressed,
|
|
|
|
/// run the given closure and update the button state to avoid
|
|
|
|
/// running it again
|
|
|
|
#[inline]
|
|
|
|
fn btn_rising_edge<I: InputPin, F: FnMut()>(last: &mut bool, i: &mut I, mut f: F) {
|
|
|
|
rising_edge(last, i, &mut NoneOutput, |_: &mut NoneOutput| f());
|
|
|
|
}
|
|
|
|
|
|
|
|
/// If the button is pressed _and_ it was previously not pressed,
|
|
|
|
/// run the given closure and update the button state to avoid
|
|
|
|
/// running it again
|
|
|
|
#[inline]
|
|
|
|
fn rising_edge<I: InputPin, F: FnMut(&mut O), O: OutputPin>(
|
|
|
|
last: &mut bool,
|
|
|
|
i: &mut I,
|
|
|
|
o: &mut O,
|
|
|
|
mut f: F,
|
|
|
|
) {
|
|
|
|
if let Ok(true) = i.is_high() {
|
|
|
|
if !*last {
|
|
|
|
f(o);
|
|
|
|
*last = true;
|
|
|
|
}
|
|
|
|
} else if let Ok(false) = i.is_high() {
|
|
|
|
*last = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn set_output<O: OutputPin>(o: &mut O, s: bool) {
|
|
|
|
if s {
|
|
|
|
o.set_high().ok();
|
|
|
|
} else {
|
|
|
|
o.set_low().ok();
|
|
|
|
}
|
|
|
|
}
|