diff --git a/firmware/src/bus.rs b/firmware/src/bus.rs new file mode 100755 index 0000000..65a774f --- /dev/null +++ b/firmware/src/bus.rs @@ -0,0 +1,80 @@ +use hal::prelude::*; +use panic_halt as _; +use stm32f0xx_hal as hal; + +pub struct Bus { + latch_en: hal::gpio::gpioa::PA0>, + select_en: hal::gpio::gpiob::PB8>, + pb0: hal::gpio::gpiob::PB0>, + pb1: hal::gpio::gpiob::PB1>, + pb2: hal::gpio::gpiob::PB2>, + pb3: hal::gpio::gpiob::PB3>, + pb4: hal::gpio::gpiob::PB4>, + pb5: hal::gpio::gpiob::PB5>, + pb6: hal::gpio::gpiob::PB6>, + pb7: hal::gpio::gpiob::PB7>, +} + +impl Bus { + pub fn new( + latch_en: hal::gpio::gpioa::PA0>, + select_en: hal::gpio::gpiob::PB8>, + pb0: hal::gpio::gpiob::PB0>, + pb1: hal::gpio::gpiob::PB1>, + pb2: hal::gpio::gpiob::PB2>, + pb3: hal::gpio::gpiob::PB3>, + pb4: hal::gpio::gpiob::PB4>, + pb5: hal::gpio::gpiob::PB5>, + pb6: hal::gpio::gpiob::PB6>, + pb7: hal::gpio::gpiob::PB7>, + ) -> Self { + cortex_m::interrupt::free(|cs| { + Self { + latch_en: latch_en.into_push_pull_output(cs), + select_en: select_en.into_open_drain_output(cs), + pb0: pb0.into_push_pull_output(cs), + pb1: pb1.into_push_pull_output(cs), + pb2: pb2.into_push_pull_output(cs), + pb3: pb3.into_push_pull_output(cs), + pb4: pb4.into_push_pull_output(cs), + pb5: pb5.into_push_pull_output(cs), + pb6: pb6.into_push_pull_output(cs), + pb7: pb7.into_push_pull_output(cs), + } + }) + } + + pub fn output(&mut self, ic: u8, data: u8) { + match ic { + 0 | 3 => self.select(1), + 1 | 10 => self.select(0), + 2 | 11 => self.select(5), + + _ => self.select(2), + } + self.select_en(true); + self.write(data); + self.select_en(false); + } + + fn write(&mut self, data: u8) { + self.pb0.set_state((data & 0b_0000_0001 != 0).into()).ok(); + self.pb1.set_state((data & 0b_0000_0010 != 0).into()).ok(); + self.pb2.set_state((data & 0b_0000_0100 != 0).into()).ok(); + self.pb3.set_state((data & 0b_0000_1000 != 0).into()).ok(); + self.pb4.set_state((data & 0b_0001_0000 != 0).into()).ok(); + self.pb5.set_state((data & 0b_0010_0000 != 0).into()).ok(); + self.pb6.set_state((data & 0b_0100_0000 != 0).into()).ok(); + self.pb7.set_state((data & 0b_1000_0000 != 0).into()).ok(); + } + + fn select_en(&mut self, enable: bool) { + self.select_en.set_state(enable.into()).ok(); + } + + fn select(&mut self, line: u8) { + self.write(line); + self.latch_en.set_high().ok(); + self.latch_en.set_low().ok(); + } +} diff --git a/firmware/src/led_state.rs b/firmware/src/led_state.rs new file mode 100644 index 0000000..acb226a --- /dev/null +++ b/firmware/src/led_state.rs @@ -0,0 +1,171 @@ +#[derive(Default, Clone)] +pub struct LedState { + pub switch_1: bool, + pub switch_2: bool, + pub switches: bool, + pub select: bool, + pub number: bool, + pub value_1: bool, + pub value_2: bool, + pub direct_select: bool, + pub midi_function: bool, + pub midi_chan: bool, + pub config: bool, + pub expression_1: bool, + pub expression_2: bool, + pub buttons: [bool; 10], + pub digit_0: SevenSegmentDisplay, + pub digit_1: SevenSegmentDisplay, + pub digit_2: SevenSegmentDisplay, +} + +#[derive(Default, Clone)] +pub struct SevenSegmentDisplay { + pub a: bool, + pub b: bool, + pub c: bool, + pub d: bool, + pub e: bool, + pub f: bool, + pub g: bool, + pub dp: bool, +} + +impl LedState { + pub fn boot_sequence(i: usize) -> Option { + let mut led_state = LedState::default(); + match i { + 0 => led_state.switch_1 = true, + 1 => led_state.switch_2 = true, + 2 => led_state.switches = true, + 3 => led_state.select = true, + 4 => led_state.number = true, + 5 => led_state.value_1 = true, + 6 => led_state.value_2 = true, + 7 => led_state.direct_select = true, + 8 => led_state.midi_function = true, + 9 => led_state.midi_chan = true, + 10 => led_state.config = true, + 11 => led_state.digit_0.a = true, + 12 => led_state.digit_0.b = true, + 13 => led_state.digit_0.c = true, + 14 => led_state.digit_0.g = true, + 15 => led_state.digit_0.dp = true, + 16 => led_state.digit_1.a = true, + 17 => led_state.digit_1.b = true, + 18 => led_state.digit_1.c = true, + 19 => led_state.digit_1.d = true, + 20 => led_state.digit_1.e = true, + 21 => led_state.digit_1.f = true, + 22 => led_state.digit_1.g = true, + 23 => led_state.digit_1.dp = true, + 24 => led_state.digit_2.a = true, + 25 => led_state.digit_2.b = true, + 26 => led_state.digit_2.c = true, + 27 => led_state.digit_2.d = true, + 28 => led_state.digit_2.e = true, + 29 => led_state.digit_2.f = true, + 30 => led_state.digit_2.g = true, + 31 => led_state.digit_2.dp = true, + 32 => led_state.expression_1 = true, + 33 => led_state.expression_2 = true, + 34 => led_state.buttons[0] = true, + 35 => led_state.buttons[1] = true, + 36 => led_state.buttons[2] = true, + 37 => led_state.buttons[3] = true, + 38 => led_state.buttons[4] = true, + 39 => led_state.buttons[5] = true, + 40 => led_state.buttons[6] = true, + 41 => led_state.buttons[7] = true, + 42 => led_state.buttons[8] = true, + 43 => led_state.buttons[9] = true, + _ => return None, + } + Some(led_state) + } + + pub fn ic_3_value(&self, index: usize) -> u8 { + let bits = match index { + 0 => { + [ + self.digit_2.dp, + self.digit_2.g, + self.digit_2.f, + self.digit_2.e, + self.digit_2.d, + self.digit_2.c, + self.digit_2.b, + self.digit_2.a, + ] + } + 1 => { + [ + self.digit_1.dp, + self.digit_1.g, + self.digit_1.f, + self.digit_1.e, + self.digit_1.d, + self.digit_1.c, + self.digit_1.b, + self.digit_1.a, + ] + } + 2 => { + [ + self.digit_0.dp, + self.digit_0.g, + self.digit_0.f, + self.digit_0.e, + self.digit_0.d, + self.digit_0.c, + self.digit_0.b, + self.digit_0.a, + ] + } + 3 => { + [ + self.midi_function, + self.midi_chan, + self.expression_2, + self.expression_1, + self.switch_1, + self.switch_2, + self.buttons[4], + self.buttons[3], + ] + } + 4 => { + [ + self.buttons[2], + self.buttons[1], + self.buttons[0], + self.buttons[9], + self.buttons[8], + self.buttons[7], + self.buttons[6], + self.buttons[5], + ] + } + 5 => { + [ + self.direct_select, + self.value_2, + self.value_1, + self.number, + self.select, + self.switches, + self.config, + false, + ] + } + _ => return 0xFF, + }; + let mut value = 0; + for (i, bit) in bits.iter().enumerate() { + if !*bit { + value |= 1 << i; + } + } + value + } +} \ No newline at end of file diff --git a/firmware/src/main.rs b/firmware/src/main.rs index 0043f39..c3553f5 100755 --- a/firmware/src/main.rs +++ b/firmware/src/main.rs @@ -1,6 +1,9 @@ #![no_std] #![no_main] +mod led_state; +mod bus; + use cortex_m_rt::entry; use defmt::warn; use hal::prelude::*; @@ -21,19 +24,6 @@ defmt::timestamp!("{=u32}", { } }); -struct Bus { - latch_en: hal::gpio::gpioa::PA0>, - select_en: hal::gpio::gpiob::PB8>, - pb0: hal::gpio::gpiob::PB0>, - pb1: hal::gpio::gpiob::PB1>, - pb2: hal::gpio::gpiob::PB2>, - pb3: hal::gpio::gpiob::PB3>, - pb4: hal::gpio::gpiob::PB4>, - pb5: hal::gpio::gpiob::PB5>, - pb6: hal::gpio::gpiob::PB6>, - pb7: hal::gpio::gpiob::PB7>, -} - #[entry] fn main() -> ! { // Get device peripherals @@ -60,18 +50,7 @@ fn main() -> ! { let button_1_5 = cortex_m::interrupt::free(|cs| gpiob.pb13.into_floating_input(cs)); let button_6_10 = cortex_m::interrupt::free(|cs| gpiob.pb11.into_floating_input(cs)); - let mut bus = cortex_m::interrupt::free(|cs| Bus { - latch_en: gpioa.pa0.into_push_pull_output(cs), - select_en: gpiob.pb8.into_open_drain_output(cs), - pb0: gpiob.pb0.into_push_pull_output(cs), - pb1: gpiob.pb1.into_push_pull_output(cs), - pb2: gpiob.pb2.into_push_pull_output(cs), - pb3: gpiob.pb3.into_push_pull_output(cs), - pb4: gpiob.pb4.into_push_pull_output(cs), - pb5: gpiob.pb5.into_push_pull_output(cs), - pb6: gpiob.pb6.into_push_pull_output(cs), - pb7: gpiob.pb7.into_push_pull_output(cs), - }); + let mut bus = bus::Bus::new(gpioa.pa0, gpiob.pb8, gpiob.pb0, gpiob.pb1, gpiob.pb2, gpiob.pb3, gpiob.pb4, gpiob.pb5, gpiob.pb6, gpiob.pb7); // Configure serial port let serial = cortex_m::interrupt::free(|cs| { @@ -80,80 +59,190 @@ fn main() -> ! { Serial::usart1(dp.USART1, (tx, rx), 31_250.bps(), &mut rcc) }); - let (tx, _rx) = serial.split(); - let mut midi = embedded_midi::MidiOut::new(tx); + let (tx, rx) = serial.split(); + let mut midi_tx = embedded_midi::MidiOut::new(tx); + let mut midi_rx = embedded_midi::MidiIn::new(rx); - bus.output(3, 0xFF, &mut delay); - bus.output(10, 0xFF, &mut delay); - bus.output(11, 0xFF, &mut delay); + // Startup sequence + let mut boot_sequence_index = 0; + while let Some(led_state) = led_state::LedState::boot_sequence(boot_sequence_index) { + for _ in 0..20 { + for i in 0_u8..6_u8 { + let ic_3_value = led_state.ic_3_value(i as _); + bus.output(10, 1_u8 << i); + bus.output(3, ic_3_value); + delay.delay_us(1000u16); + bus.output(3, 0xFF); + + bus.output(11, 4_u8 << i); + } + } + boot_sequence_index += 1; + } // Main loop let mut button_states = [false; 12]; + let mut led_state = led_state::LedState::default(); loop { - for i in 0_u8..6_u8 { - bus.output(11, 4_u8 << i, &mut delay); - delay.delay_us(1u16); - let previous_state = &mut button_states[i as usize]; - let new_state = button_1_5.is_high().unwrap_or(false); - if new_state != *previous_state { - *previous_state = new_state; - let control = control_from_button(i); - if new_state { - info!("Button {} pressed", i); - if midi - .write(&embedded_midi::MidiMessage::ControlChange( - embedded_midi::Channel::C1, - control, - midi_types::Value7::new(127), - )) - .is_err() - { - warn!("Failed to send MIDI message"); - } - } else { - info!("Button {} released", i); - if midi - .write(&embedded_midi::MidiMessage::ControlChange( - embedded_midi::Channel::C1, - control, - midi_types::Value7::new(0), - )) - .is_err() - { - warn!("Failed to send MIDI message"); + for _ in 0..20 { + for i in 0_u8..6_u8 { + let ic_3_value = led_state.ic_3_value(i as _); + + bus.output(10, 1_u8 << i); + bus.output(3, ic_3_value); + delay.delay_us(20u16); + bus.output(3, 0xFF); + + bus.output(11, 4_u8 << i); + + let previous_state = &mut button_states[i as usize]; + let new_state = button_1_5.is_high().unwrap_or(false); + if new_state != *previous_state { + *previous_state = new_state; + let control = control_from_button(i); + if new_state { + info!("Button {} pressed", i); + if midi_tx + .write(&embedded_midi::MidiMessage::ControlChange( + embedded_midi::Channel::C1, + control, + midi_types::Value7::new(127), + )) + .is_err() + { + warn!("Failed to send MIDI message"); + } + } else { + info!("Button {} released", i); + if midi_tx + .write(&embedded_midi::MidiMessage::ControlChange( + embedded_midi::Channel::C1, + control, + midi_types::Value7::new(0), + )) + .is_err() + { + warn!("Failed to send MIDI message"); + } } } - } - let i = i + 6; - let previous_state = &mut button_states[i as usize]; - let new_state = button_6_10.is_high().unwrap_or(false); - if new_state != *previous_state { - *previous_state = new_state; - let control = control_from_button(i); - if new_state { - info!("Button {} pressed", i); - if midi - .write(&embedded_midi::MidiMessage::ControlChange( - embedded_midi::Channel::C1, - control, - midi_types::Value7::new(127), - )) - .is_err() - { - warn!("Failed to send MIDI message"); + let i = i + 6; + let previous_state = &mut button_states[i as usize]; + let new_state = button_6_10.is_high().unwrap_or(false); + if new_state != *previous_state { + *previous_state = new_state; + let control = control_from_button(i); + if new_state { + info!("Button {} pressed", i); + if midi_tx + .write(&embedded_midi::MidiMessage::ControlChange( + embedded_midi::Channel::C1, + control, + midi_types::Value7::new(127), + )) + .is_err() + { + warn!("Failed to send MIDI message"); + } + } else { + info!("Button {} released", i); + if midi_tx + .write(&embedded_midi::MidiMessage::ControlChange( + embedded_midi::Channel::C1, + control, + midi_types::Value7::new(0), + )) + .is_err() + { + warn!("Failed to send MIDI message"); + } } - } else { - info!("Button {} released", i); - if midi - .write(&embedded_midi::MidiMessage::ControlChange( - embedded_midi::Channel::C1, - control, - midi_types::Value7::new(0), - )) - .is_err() + } + match midi_rx.read() { + Ok(embedded_midi::MidiMessage::ControlChange(channel, control, value)) + if channel == embedded_midi::Channel::C1 => { - warn!("Failed to send MIDI message"); + if control == embedded_midi::Control::new(31) { + let value: u8 = value.into(); + led_state.switch_1 = value & 0b0000_0001 != 0; + led_state.switch_2 = value & 0b0000_0010 != 0; + led_state.expression_1 = value & 0b0000_0100 != 0; + led_state.expression_2 = value & 0b0000_1000 != 0; + } else if control == embedded_midi::Control::new(32) { + let value: u8 = value.into(); + led_state.switches = value & 0b0000_0001 != 0; + led_state.select = value & 0b0000_0010 != 0; + led_state.number = value & 0b0000_0100 != 0; + led_state.value_1 = value & 0b0000_1000 != 0; + led_state.value_2 = value & 0b0001_0000 != 0; + } else if control == embedded_midi::Control::new(33) { + let value: u8 = value.into(); + led_state.direct_select = value & 0b0000_0001 != 0; + led_state.midi_function = value & 0b0000_0010 != 0; + led_state.midi_chan = value & 0b0000_0100 != 0; + led_state.config = value & 0b0000_1000 != 0; + } else if control == embedded_midi::Control::new(34) { + let value: u8 = value.into(); + led_state.digit_0.a = value & 0b0000_0001 != 0; + led_state.digit_0.b = value & 0b0000_0010 != 0; + led_state.digit_0.c = value & 0b0000_0100 != 0; + led_state.digit_0.d = value & 0b0000_1000 != 0; + led_state.digit_0.e = value & 0b0001_0000 != 0; + led_state.digit_0.f = value & 0b0010_0000 != 0; + led_state.digit_0.g = value & 0b0100_0000 != 0; + } else if control == embedded_midi::Control::new(35) { + let value: u8 = value.into(); + led_state.digit_1.a = value & 0b0000_0001 != 0; + led_state.digit_1.b = value & 0b0000_0010 != 0; + led_state.digit_1.c = value & 0b0000_0100 != 0; + led_state.digit_1.d = value & 0b0000_1000 != 0; + led_state.digit_1.e = value & 0b0001_0000 != 0; + led_state.digit_1.f = value & 0b0010_0000 != 0; + led_state.digit_1.g = value & 0b0100_0000 != 0; + } else if control == embedded_midi::Control::new(36) { + let value: u8 = value.into(); + led_state.digit_2.a = value & 0b0000_0001 != 0; + led_state.digit_2.b = value & 0b0000_0010 != 0; + led_state.digit_2.c = value & 0b0000_0100 != 0; + led_state.digit_2.d = value & 0b0000_1000 != 0; + led_state.digit_2.e = value & 0b0001_0000 != 0; + led_state.digit_2.f = value & 0b0010_0000 != 0; + led_state.digit_2.g = value & 0b0100_0000 != 0; + } else if control == embedded_midi::Control::new(37) { + let value: u8 = value.into(); + led_state.buttons[0] = value & 0b0000_0001 != 0; + led_state.buttons[1] = value & 0b0000_0010 != 0; + led_state.buttons[2] = value & 0b0000_0100 != 0; + led_state.buttons[3] = value & 0b0000_1000 != 0; + led_state.buttons[4] = value & 0b0001_0000 != 0; + } else if control == embedded_midi::Control::new(38) { + let value: u8 = value.into(); + led_state.buttons[0] = value & 0b0000_0001 != 0; + led_state.buttons[1] = value & 0b0000_0010 != 0; + led_state.buttons[2] = value & 0b0000_0100 != 0; + led_state.buttons[3] = value & 0b0000_1000 != 0; + led_state.buttons[4] = value & 0b0001_0000 != 0; + } + } + Ok(_) => { + info!("unhandled midi message"); + } + Err(nb::Error::WouldBlock) => {} + Err(nb::Error::Other(hal::serial::Error::Framing)) => { + info!("Error::Framing"); + } + Err(nb::Error::Other(hal::serial::Error::Noise)) => { + info!("Error::Noise"); + } + Err(nb::Error::Other(hal::serial::Error::Overrun)) => { + info!("Error::Overrun"); + } + Err(nb::Error::Other(hal::serial::Error::Parity)) => { + info!("Error::Parity"); + } + Err(nb::Error::Other(_)) => { + info!("Error::Other"); } } } @@ -177,45 +266,4 @@ fn control_from_button(button: u8) -> embedded_midi::Control { 11 => embedded_midi::Control::new(30), _ => embedded_midi::Control::new(0), } -} - -impl Bus { - fn output(&mut self, ic: u8, data: u8, delay: &mut Delay) { - match ic { - 0 | 3 => self.select(1, delay), - 1 | 10 => self.select(0, delay), - 2 | 11 => self.select(5, delay), - - _ => self.select(2, delay), - } - delay.delay_us(1u16); - self.select_en(true); - delay.delay_us(1u16); - self.write(data); - delay.delay_us(1u16); - self.select_en(false); - } - - fn write(&mut self, data: u8) { - self.pb0.set_state((data & 0b_0000_0001 != 0).into()).ok(); - self.pb1.set_state((data & 0b_0000_0010 != 0).into()).ok(); - self.pb2.set_state((data & 0b_0000_0100 != 0).into()).ok(); - self.pb3.set_state((data & 0b_0000_1000 != 0).into()).ok(); - self.pb4.set_state((data & 0b_0001_0000 != 0).into()).ok(); - self.pb5.set_state((data & 0b_0010_0000 != 0).into()).ok(); - self.pb6.set_state((data & 0b_0100_0000 != 0).into()).ok(); - self.pb7.set_state((data & 0b_1000_0000 != 0).into()).ok(); - } - - fn select_en(&mut self, enable: bool) { - self.select_en.set_state(enable.into()).ok(); - } - - fn select(&mut self, line: u8, delay: &mut Delay) { - self.write(line); - delay.delay_us(1u16); - self.latch_en.set_high().ok(); - delay.delay_us(1u16); - self.latch_en.set_low().ok(); - } -} +} \ No newline at end of file