diff --git a/src/demo_tasks.rs b/src/demo_tasks.rs index f900b5a374b5dd6a20173ba0097852e03c861202..329cb1a70ade964de2295bfbbb6d097deebcc43a 100644 --- a/src/demo_tasks.rs +++ b/src/demo_tasks.rs @@ -9,14 +9,13 @@ use embedded_graphics::{ primitives::{PrimitiveStyle, Rectangle, StyledDrawable}, text::Text, }; -use embedded_hal_async::digital::Wait; use esp_backtrace as _; use esp_println::println; use tinybmp::Bmp; use smart_leds::SmartLedsWrite; -use crate::flow3r::input::{FlowerInputEventSource, InputHandler}; +use crate::flow3r::input::InputHandler; #[embassy_executor::task] pub async fn leds_fade(mut leds: crate::flow3r::leds::Leds) -> ! { diff --git a/src/flow3r/badgelink/mod.rs b/src/flow3r/badgelink/mod.rs index b3cab2b21b16361305d218c0c93069d3336a4739..eb46d3e0df6ebcde8425daae69c8922414e0da26 100644 --- a/src/flow3r/badgelink/mod.rs +++ b/src/flow3r/badgelink/mod.rs @@ -1,19 +1,17 @@ use hal::{i2c::I2C, peripherals::I2C0}; -use port_expander::{Max7321, dev::max7321::Driver}; -use shared_bus::{I2cProxy, XtensaMutex, NullMutex}; +use port_expander::{dev::max7321::Driver, Max7321}; +use shared_bus::{I2cProxy, NullMutex, XtensaMutex}; pub mod badgenet; pub struct BadgeLink { - port_expander: Max7321<NullMutex<Driver<I2cProxy<'static, XtensaMutex<I2C<'static, I2C0>>>>>> + port_expander: Max7321<NullMutex<Driver<I2cProxy<'static, XtensaMutex<I2C<'static, I2C0>>>>>>, } impl BadgeLink { pub fn new(i2c: I2cProxy<'static, XtensaMutex<I2C<'static, I2C0>>>) -> Self { - let mut port_expander = port_expander::Max7321::new(i2c, true, true, true, false); - Self { - port_expander - } + let port_expander = port_expander::Max7321::new(i2c, true, true, true, false); + Self { port_expander } } pub fn left_audio(&mut self) -> Result<(), hal::i2c::Error> { diff --git a/src/flow3r/captouch.rs b/src/flow3r/captouch.rs index ac57e163f240cd41e08f5f2899e5f5242896320a..e6c724c77849137923b4aae75b2b1d579fed370b 100644 --- a/src/flow3r/captouch.rs +++ b/src/flow3r/captouch.rs @@ -3,64 +3,317 @@ use ad7147::{ stage::{CapInput, CdcInput, InputConnection}, Ad7147, DeviceConfiguration, Initialized, StageConfiguration, }; +use embassy_futures::select::select; use embassy_time::{Delay, Duration, Timer}; use embedded_hal_async::digital::Wait; use esp_println::println; use hal::{ - gpio::{Gpio16, Unknown}, + gpio::{Gpio15, Gpio16, Unknown}, i2c::I2C, - peripherals::I2C0, prelude::_esp_hal_gpio_InputPin, + peripherals::I2C0, }; use shared_bus::{I2cProxy, XtensaMutex}; pub struct CapTouchHandler; fn init_captouch( - i2c: I2cProxy<'static, XtensaMutex<I2C<'static, I2C0>>>, + i2c_bot: I2cProxy<'static, XtensaMutex<I2C<'static, I2C0>>>, + i2c_top: I2cProxy<'static, XtensaMutex<I2C<'static, I2C0>>>, ) -> Result< - Ad7147<I2cProxy<'static, XtensaMutex<I2C<'static, I2C0>>>, Initialized, 1>, + ( + Ad7147<I2cProxy<'static, XtensaMutex<I2C<'static, I2C0>>>, Initialized, 12>, + Ad7147<I2cProxy<'static, XtensaMutex<I2C<'static, I2C0>>>, Initialized, 12>, + ), hal::i2c::Error, > { - let ad7147 = Ad7147::new(i2c, 0b00101100); - let config = DeviceConfiguration::builder() + let ad7147_bot = Ad7147::new(i2c_bot, 0b00101101); + let config_bot = DeviceConfiguration::builder() .decimation(DecimationFactor::Factor64) - .stages([StageConfiguration::builder() - .calibration_enabled(true) - .conversion_complete_interrupt_enabled(true) - .add_input_connection(InputConnection { - cin: CapInput::CIN0, - cdc: CdcInput::Positive, - }) - .build()]) + .stages([ + StageConfiguration::builder() + .calibration_enabled(true) + .conversion_complete_interrupt_enabled(true) + .pos_afe_offset(2) + .add_input_connection(InputConnection { + cin: CapInput::CIN0, + cdc: CdcInput::Positive, + }) + .build(), + StageConfiguration::builder() + .calibration_enabled(true) + .conversion_complete_interrupt_enabled(true) + .pos_afe_offset(2) + .add_input_connection(InputConnection { + cin: CapInput::CIN1, + cdc: CdcInput::Positive, + }) + .build(), + StageConfiguration::builder() + .calibration_enabled(true) + .conversion_complete_interrupt_enabled(true) + .pos_afe_offset(2) + .add_input_connection(InputConnection { + cin: CapInput::CIN2, + cdc: CdcInput::Positive, + }) + .build(), + StageConfiguration::builder() + .calibration_enabled(true) + .conversion_complete_interrupt_enabled(true) + .pos_afe_offset(2) + .add_input_connection(InputConnection { + cin: CapInput::CIN3, + cdc: CdcInput::Positive, + }) + .build(), + StageConfiguration::builder() + .calibration_enabled(true) + .conversion_complete_interrupt_enabled(true) + .pos_afe_offset(2) + .add_input_connection(InputConnection { + cin: CapInput::CIN4, + cdc: CdcInput::Positive, + }) + .build(), + StageConfiguration::builder() + .calibration_enabled(true) + .conversion_complete_interrupt_enabled(true) + .pos_afe_offset(2) + .add_input_connection(InputConnection { + cin: CapInput::CIN5, + cdc: CdcInput::Positive, + }) + .build(), + StageConfiguration::builder() + .calibration_enabled(true) + .conversion_complete_interrupt_enabled(true) + .pos_afe_offset(2) + .add_input_connection(InputConnection { + cin: CapInput::CIN6, + cdc: CdcInput::Positive, + }) + .build(), + StageConfiguration::builder() + .calibration_enabled(true) + .conversion_complete_interrupt_enabled(true) + .pos_afe_offset(2) + .add_input_connection(InputConnection { + cin: CapInput::CIN7, + cdc: CdcInput::Positive, + }) + .build(), + StageConfiguration::builder() + .calibration_enabled(true) + .conversion_complete_interrupt_enabled(true) + .pos_afe_offset(2) + .add_input_connection(InputConnection { + cin: CapInput::CIN8, + cdc: CdcInput::Positive, + }) + .build(), + StageConfiguration::builder() + .calibration_enabled(true) + .conversion_complete_interrupt_enabled(true) + .pos_afe_offset(2) + .add_input_connection(InputConnection { + cin: CapInput::CIN9, + cdc: CdcInput::Positive, + }) + .build(), + StageConfiguration::builder() + .calibration_enabled(true) + .conversion_complete_interrupt_enabled(true) + .pos_afe_offset(30) + .add_input_connection(InputConnection { + cin: CapInput::CIN10, + cdc: CdcInput::Positive, + }) + .build(), + StageConfiguration::builder() + .calibration_enabled(true) + .conversion_complete_interrupt_enabled(true) + .pos_afe_offset(26) + .add_input_connection(InputConnection { + cin: CapInput::CIN11, + cdc: CdcInput::Positive, + }) + .build(), + ]) .build(); - println!("device config: {:x?}", config.0.to_reg_value_for_init()); - ad7147.init(config, &mut Delay) + let ad7147_top = Ad7147::new(i2c_top, 0b00101100); + let config_top = DeviceConfiguration::builder() + .decimation(DecimationFactor::Factor64) + .stages([ + StageConfiguration::builder() + .calibration_enabled(true) + .conversion_complete_interrupt_enabled(true) + .pos_afe_offset(30) + .add_input_connection(InputConnection { + cin: CapInput::CIN0, + cdc: CdcInput::Positive, + }) + .build(), + StageConfiguration::builder() + .calibration_enabled(true) + .conversion_complete_interrupt_enabled(true) + .pos_afe_offset(30) + .add_input_connection(InputConnection { + cin: CapInput::CIN1, + cdc: CdcInput::Positive, + }) + .build(), + StageConfiguration::builder() + .calibration_enabled(true) + .conversion_complete_interrupt_enabled(true) + .pos_afe_offset(28) + .add_input_connection(InputConnection { + cin: CapInput::CIN2, + cdc: CdcInput::Positive, + }) + .build(), + StageConfiguration::builder() + .calibration_enabled(true) + .conversion_complete_interrupt_enabled(true) + .pos_afe_offset(28) + .add_input_connection(InputConnection { + cin: CapInput::CIN3, + cdc: CdcInput::Positive, + }) + .build(), + StageConfiguration::builder() + .calibration_enabled(true) + .conversion_complete_interrupt_enabled(true) + .pos_afe_offset(28) + .add_input_connection(InputConnection { + cin: CapInput::CIN4, + cdc: CdcInput::Positive, + }) + .build(), + StageConfiguration::builder() + .calibration_enabled(true) + .conversion_complete_interrupt_enabled(true) + .pos_afe_offset(28) + .add_input_connection(InputConnection { + cin: CapInput::CIN5, + cdc: CdcInput::Positive, + }) + .build(), + StageConfiguration::builder() + .calibration_enabled(true) + .conversion_complete_interrupt_enabled(true) + .pos_afe_offset(28) + .add_input_connection(InputConnection { + cin: CapInput::CIN6, + cdc: CdcInput::Positive, + }) + .build(), + StageConfiguration::builder() + .calibration_enabled(true) + .conversion_complete_interrupt_enabled(true) + .pos_afe_offset(10) + .add_input_connection(InputConnection { + cin: CapInput::CIN7, + cdc: CdcInput::Positive, + }) + .build(), + StageConfiguration::builder() + .calibration_enabled(true) + .conversion_complete_interrupt_enabled(true) + .pos_afe_offset(20) + .add_input_connection(InputConnection { + cin: CapInput::CIN8, + cdc: CdcInput::Positive, + }) + .build(), + StageConfiguration::builder() + .calibration_enabled(true) + .conversion_complete_interrupt_enabled(true) + .pos_afe_offset(20) + .add_input_connection(InputConnection { + cin: CapInput::CIN9, + cdc: CdcInput::Positive, + }) + .build(), + StageConfiguration::builder() + .calibration_enabled(true) + .conversion_complete_interrupt_enabled(true) + .pos_afe_offset(8) + .add_input_connection(InputConnection { + cin: CapInput::CIN10, + cdc: CdcInput::Positive, + }) + .build(), + StageConfiguration::builder() + .calibration_enabled(true) + .conversion_complete_interrupt_enabled(true) + .pos_afe_offset(20) + .add_input_connection(InputConnection { + cin: CapInput::CIN11, + cdc: CdcInput::Positive, + }) + .build(), + ]) + .build(); + Ok(( + ad7147_bot.init(config_bot, &mut Delay)?, + ad7147_top.init(config_top, &mut Delay)?, + )) } #[embassy_executor::task] pub async fn captouch_controller( - i2c: I2cProxy<'static, XtensaMutex<I2C<'static, I2C0>>>, - cap_b_int: Gpio16<Unknown>, + i2c_bot: I2cProxy<'static, XtensaMutex<I2C<'static, I2C0>>>, + i2c_top: I2cProxy<'static, XtensaMutex<I2C<'static, I2C0>>>, + cap_bot_int: Gpio16<Unknown>, + cap_top_int: Gpio15<Unknown>, ) -> ! { - let mut cap_b_int = cap_b_int.into_pull_up_input(); - let mut ad7147 = init_captouch(i2c).unwrap(); - - let device_id = ad7147.read_device_id().unwrap(); - println!("captouch device id: {:016b}", device_id); - - let ints = ad7147.read_interrupt_registers().unwrap(); - println!("ints: {:?}", ints); + let mut cap_bot_int = cap_bot_int.into_pull_up_input(); + let mut cap_top_int = cap_top_int.into_pull_up_input(); + let (mut ad7147_bot, mut ad7147_top) = init_captouch(i2c_bot, i2c_top).unwrap(); - println!("int pin: {}", cap_b_int.is_input_high()); + let device_id = ad7147_bot.read_device_id().unwrap(); + println!("captouch bot device id: {:016b}", device_id); + let device_id = ad7147_top.read_device_id().unwrap(); + println!("captouch top device id: {:016b}", device_id); println!("initialized captouch"); loop { - println!("int pin: {}", cap_b_int.is_input_high()); - // cap_b_int.wait_for_low().await.unwrap(); - println!("captouch interrupt"); - let ints = ad7147.read_interrupt_registers().unwrap(); - println!("ints: {:?}", ints); - let measurement = ad7147.read_all_stages().unwrap(); - println!("{}", measurement[0]); - Timer::after(Duration::from_secs(10)).await; + //println!("int pin: {}", cap_b_int.is_input_high()); + select(cap_bot_int.wait_for_low(), cap_top_int.wait_for_low()); + let _ = ad7147_bot.read_interrupt_registers().unwrap(); + let _ = ad7147_top.read_interrupt_registers().unwrap(); + //println!("ints: {:?}", ints); + let measurement = ad7147_bot.read_all_stages().unwrap(); + println!( + "{} {} {} {} {} {} {} {} {} {} {} {}", + measurement[0], + measurement[1], + measurement[2], + measurement[3], + measurement[4], + measurement[5], + measurement[6], + measurement[7], + measurement[8], + measurement[9], + measurement[10], + measurement[11] + ); + let measurement = ad7147_top.read_all_stages().unwrap(); + println!( + "{} {} {} {} {} {} {} {} {} {} {} {}", + measurement[0], + measurement[1], + measurement[2], + measurement[3], + measurement[4], + measurement[5], + measurement[6], + measurement[7], + measurement[8], + measurement[9], + measurement[10], + measurement[11] + ); + Timer::after(Duration::from_millis(1000)).await; } } diff --git a/src/flow3r/imu.rs b/src/flow3r/imu.rs index 5038b55408a7c062db9fc9beb57331245d9ee287..b1ed43a13b6fca9e47462516896c4cd5490c2c08 100644 --- a/src/flow3r/imu.rs +++ b/src/flow3r/imu.rs @@ -1,4 +1,4 @@ -use bmi270::{interface::I2cInterface, Bmi270, PwrCtrl}; +use bmi270::{interface::I2cInterface, AuxData, AxisData, Bmi270, Error, PwrCtrl}; use embassy_time::{Duration, Timer}; use esp_println::println; use hal::{i2c::I2C, peripherals::I2C0}; @@ -8,30 +8,34 @@ pub struct ImuHandler { imu: Bmi270<I2cInterface<I2cProxy<'static, XtensaMutex<I2C<'static, I2C0>>>>>, } -impl ImuHandler {} +impl ImuHandler { + pub fn new(i2c: I2cProxy<'static, XtensaMutex<I2C<'static, I2C0>>>) -> Self { + let mut bmi270 = Bmi270::new_i2c(i2c, bmi270::I2cAddr::Default, bmi270::Burst::Max); -#[embassy_executor::task] -pub async fn imu_manager(i2c: I2cProxy<'static, XtensaMutex<I2C<'static, I2C0>>>) -> ! { - let mut bmi270 = Bmi270::new_i2c(i2c, bmi270::I2cAddr::Default, bmi270::Burst::Max); + let chip_id = bmi270.get_chip_id().unwrap(); + println!("imu chip id: {}", chip_id); - let chip_id = bmi270.get_chip_id().unwrap(); - println!("imu chip id: {}", chip_id); + bmi270.init().unwrap(); - bmi270.init().unwrap(); - - let pwr_ctrl = PwrCtrl { - aux_en: false, - gyr_en: true, - acc_en: true, - temp_en: false, - }; - bmi270.set_pwr_ctrl(pwr_ctrl).unwrap(); + let pwr_ctrl = PwrCtrl { + aux_en: false, + gyr_en: true, + acc_en: true, + temp_en: false, + }; + bmi270.set_pwr_ctrl(pwr_ctrl).unwrap(); + Self { imu: bmi270 } + } - let data = bmi270.get_data().unwrap(); + pub fn acceleration(&mut self) -> Result<AxisData, Error<hal::i2c::Error, ()>> { + self.imu.get_acc_data() + } - println!("imu data: {:?}", data); + pub fn rotation(&mut self) -> Result<AxisData, Error<hal::i2c::Error, ()>> { + self.imu.get_gyr_data() + } - loop { - Timer::after(Duration::from_secs(10)).await; + pub fn atmospheric_pressure(&mut self) -> Result<AuxData, Error<hal::i2c::Error, ()>> { + todo!() } } diff --git a/src/flow3r/input.rs b/src/flow3r/input.rs index 3546bf0b0be9db8faf03130e1137b9b23705cf37..ae557b14860b5eafa4d02ba83975efd217faadff 100644 --- a/src/flow3r/input.rs +++ b/src/flow3r/input.rs @@ -70,13 +70,11 @@ pub struct Flow3rInput(FlowerInputEventSource); impl Flow3rInput { pub async fn wait_for_release(&mut self) -> Result<(), embassy_sync::pubsub::Error> { - wait_for_event(self.0, Flow3rInputEventType::Press) - .await + wait_for_event(self.0, Flow3rInputEventType::Press).await } pub async fn wait_for_press(&mut self) -> Result<(), embassy_sync::pubsub::Error> { - wait_for_event(self.0, Flow3rInputEventType::Press) - .await + wait_for_event(self.0, Flow3rInputEventType::Press).await } pub async fn wait_for_any(&mut self) -> Result<(), embassy_sync::pubsub::Error> { diff --git a/src/flow3r/mod.rs b/src/flow3r/mod.rs index a252d08e1a834b9cf509ed7530686ce16df4c25e..6551c92f820776ad4f768543843040f26c6fbbcf 100644 --- a/src/flow3r/mod.rs +++ b/src/flow3r/mod.rs @@ -1,5 +1,8 @@ use self::badgelink::BadgeLink; +use self::captouch::CapTouchHandler; use self::display::Display; +use self::imu::ImuHandler; +use self::input::InputHandler; use self::leds::Leds; pub mod badgelink; @@ -11,13 +14,30 @@ pub mod leds; pub mod sdcard; pub struct Flow3r { + pub badgelink: BadgeLink, + pub captouch: CapTouchHandler, pub display: Display, + pub imu: ImuHandler, + pub inputs: InputHandler, pub leds: Leds, - pub badgelink: BadgeLink, } impl Flow3r { - pub fn new(display: Display, leds: Leds, badgelink: BadgeLink) -> Self { - Self { display, leds, badgelink } + pub fn new( + badgelink: BadgeLink, + captouch: CapTouchHandler, + display: Display, + imu: ImuHandler, + inputs: InputHandler, + leds: Leds, + ) -> Self { + Self { + badgelink, + captouch, + display, + imu, + inputs, + leds, + } } } diff --git a/src/runtime.rs b/src/runtime.rs index bc802f1d50e15ea576fd5eda3333d2c1cf5688fd..7834e7f0331c48b2e0cda0a3ffeb350aa6085b67 100644 --- a/src/runtime.rs +++ b/src/runtime.rs @@ -2,7 +2,7 @@ use embassy_executor::{Executor, Spawner}; use embassy_time::{Duration, Timer}; use hal::{ clock::{ClockControl, Clocks}, - cpu_control::{self, AppCoreGuard, CpuControl}, + cpu_control::CpuControl, embassy, gdma::Gdma, i2c::I2C, @@ -17,11 +17,13 @@ use hal::{ use static_cell::StaticCell; use crate::flow3r::{ - captouch::captouch_controller, + badgelink::BadgeLink, + captouch::{captouch_controller, CapTouchHandler}, display::{display_refresh, Display}, - input::input_controller, + imu::ImuHandler, + input::{input_controller, InputHandler}, leds::init_leds, - Flow3r, badgelink::BadgeLink, + Flow3r, }; use crate::main; @@ -82,7 +84,7 @@ async fn init_runtime() { embassy::init(&clocks, SystemTimer::new(peripherals.SYSTIMER)); - let cpu_control = CpuControl::new(system.cpu_control); + let _cpu_control = CpuControl::new(system.cpu_control); // Async requires the GPIO interrupt to wake futures hal::interrupt::enable( @@ -101,7 +103,8 @@ async fn init_runtime() { 0, ) .unwrap(); - let leds = init_leds(pulse.channel0, io.pins.gpio14); + + // Init I2C let sda = io.pins.gpio2; let scl = io.pins.gpio1; @@ -115,8 +118,12 @@ async fn init_runtime() { &clocks, ); + // Create shared I2C Bus + let i2c_busmanager = shared_bus::new_xtensa!(I2C<'static, I2C0> = i2c).unwrap(); + // Init SPI + DMA + let sck = io.pins.gpio41; let mosi = io.pins.gpio42; let spi = Spi::new_no_cs_no_miso( @@ -132,13 +139,16 @@ async fn init_runtime() { let dma = Gdma::new(peripherals.DMA, &mut system.peripheral_clock_control); let dma_channel = dma.channel0; - // Display backlight control + // Init Display backlight control + let ledc = LEDC::new( peripherals.LEDC, clocks, &mut system.peripheral_clock_control, ); + // Init display early to clear pixel mash from screen + let mut display = Display::new( spi, dma_channel, @@ -150,6 +160,8 @@ async fn init_runtime() { .await; display.clear().await.unwrap(); + // Init uart + let mut uart0 = Uart::new(peripherals.UART0, &mut system.peripheral_clock_control); uart0.set_rx_fifo_full_threshold(READ_BUF_SIZE as u16); @@ -159,11 +171,19 @@ async fn init_runtime() { ) .unwrap(); - let rng = RNG.init(Rng::new(peripherals.RNG)); + let _rng = RNG.init(Rng::new(peripherals.RNG)); + + // Init Flow3r components let badgelink = BadgeLink::new(i2c_busmanager.acquire_i2c()); + let imu = ImuHandler::new(i2c_busmanager.acquire_i2c()); + let inputs = InputHandler; + let captouch = CapTouchHandler; + let leds = init_leds(pulse.channel0, io.pins.gpio14); - let flow3r = Flow3r::new(display, leds, badgelink); + let flow3r = Flow3r::new(badgelink, captouch, display, imu, inputs, leds); + + // Spawn background tasks let spawner = Spawner::for_current_executor().await; spawner @@ -176,9 +196,13 @@ async fn init_runtime() { .ok(); spawner .spawn(captouch_controller( + i2c_busmanager.acquire_i2c(), i2c_busmanager.acquire_i2c(), io.pins.gpio16, + io.pins.gpio15, )) .ok(); + + // Hand over to main task spawner.spawn(main(flow3r)).ok(); }