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>, pub led2: PA2>, pub led3: PA3>, pub led4: PA4>, // Button input states pub btn1: PB0>, pub btn1_last: bool, pub btn2: PB1>, pub btn2_last: bool, pub btn3: PB5>, pub btn3_last: bool, pub btn4: PB6>, pub btn4_last: bool, // Eurorack signal I/O pub clk: PB7>, pub clk_last: bool, pub clk_led: PB9>, pub gate: PB8>, } 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(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( 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: &mut O, s: bool) { if s { o.set_high().ok(); } else { o.set_low().ok(); } }