diff --git a/src/button.rs b/src/button.rs new file mode 100644 index 0000000..01b8138 --- /dev/null +++ b/src/button.rs @@ -0,0 +1,99 @@ +use defmt::info; +use esp_hal::{ + Async, + analog::adc::{Adc, AdcCalLine, AdcConfig, AdcPin, Attenuation}, + peripherals::{ADC1, GPIO1, GPIO2}, +}; + +/// Measured values and rough midway points +/// Midway points: ~2850 ~2300 ~1550 ~550 +/// Recorded values: 3087, 2629, 2013, 1117, 4 +const PIN_1_RANGES: [u16; 5] = [2850, 2300, 1550, 550, 0]; + +enum Pin { + One, + Two, +} + +/// Measured values and rough midway points +/// Midway points: ~2350 ~850 +/// Recorded values: 3087, 1670, 4 +const PIN_2_RANGES: [u16; 3] = [2350, 850, 0]; +fn get_active_button(pin_value: u16, ranges: &[u16], pin: Pin) -> Option { + let number_of_buttons: u8 = match pin { + Pin::One => 4, + Pin::Two => 2, + }; + + for button_number in 0..number_of_buttons { + let start = ranges[usize::from(button_number) + 1]; + let end = ranges[usize::from(button_number)]; + // if (start..end).contains(&pin_value) { + if start < pin_value && pin_value <= end { + return Some(button_number); + } + } + + None +} + +pub(crate) struct Button<'a> { + adc: Adc<'a, ADC1<'a>, Async>, + pin: ( + AdcPin, ADC1<'a>, AdcCalLine>>, + AdcPin, ADC1<'a>, AdcCalLine>>, + ), +} + +impl<'a> Button<'a> { + pub(crate) fn new(adc: ADC1<'a>, pin_1: GPIO1<'a>, pin_2: GPIO2<'a>) -> Self { + let mut configuration = AdcConfig::new(); + let pin_1 = configuration + .enable_pin_with_cal::<_, AdcCalLine>>(pin_1, Attenuation::_11dB); + let pin_2 = configuration + .enable_pin_with_cal::<_, AdcCalLine>>(pin_2, Attenuation::_11dB); + let adc = Adc::new(adc, configuration).into_async(); + + Self { + adc, + pin: (pin_1, pin_2), + } + } + + async fn read_values(&mut self) -> (u16, u16) { + let value_1 = self.adc.read_oneshot(&mut self.pin.0).await; + let value_2 = self.adc.read_oneshot(&mut self.pin.1).await; + (value_1, value_2) + } + + pub(crate) async fn poll(&mut self) { + let values = self.read_values().await; + let button_1 = get_active_button(values.0, &PIN_1_RANGES, Pin::One); + let button_2 = get_active_button(values.1, &PIN_2_RANGES, Pin::Two); + match (button_1, button_2) { + (Some(button_1), Some(button_2)) => { + info!("Button 1: {}, Button 2: {}", button_1, button_2); + } + (Some(button_1), None) => { + info!("Button 1: {}", button_1); + } + (None, Some(button_2)) => { + info!("Button 2: {}", button_2); + } + (None, None) => { + info!("No button pressed"); + } + } + } +} + +impl<'a> Future for Button<'a> { + type Output = (); + + fn poll( + self: core::pin::Pin<&mut Self>, + context: &mut core::task::Context<'_>, + ) -> core::task::Poll { + todo!() + } +} diff --git a/src/main.rs b/src/main.rs index 7f37ca1..efdd25c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,15 +7,17 @@ )] #![deny(clippy::large_stack_frames)] +mod button; mod eink_display; mod spi; +use bt_hci::cmd::info; use defmt::{error, info}; use embassy_executor::Spawner; use embassy_time::Timer; -use esp_hal::analog::adc::{Adc, AdcCalLine, AdcConfig, Attenuation}; +use esp_hal::analog::adc::{Adc, AdcCalLine, AdcChannel, AdcConfig, Attenuation}; use esp_hal::gpio::{self, Input, InputConfig}; -use esp_hal::peripherals::{ADC1, GPIO1, GPIO2, GPIO3, LPWR}; +use esp_hal::peripherals::{ADC1, ADC2, GPIO0, GPIO1, GPIO2, GPIO3, LPWR}; use esp_hal::rtc_cntl::sleep::{RtcioWakeupSource, WakeupLevel}; use esp_hal::rtc_cntl::{reset_reason, wakeup_cause}; use esp_hal::system::Cpu; @@ -23,6 +25,7 @@ use esp_hal::timer::timg::TimerGroup; use esp_hal::{clock::CpuClock, rtc_cntl::Rtc}; use {esp_backtrace as _, esp_println as _}; +use crate::button::Button; use crate::eink_display::EinkDisplay; extern crate alloc; @@ -47,13 +50,6 @@ enum ApplicationError { as embedded_hal_async::spi::ErrorType>::Error, >, ), - #[error("Error setting entering display deep sleep")] - EnterDeepSleep( - eink_display::EnterDeepSleepError< - as embedded_hal_async::spi::ErrorType>::Error, - >, - ), - #[error("Error spawning task")] Spawn(#[from] embassy_executor::SpawnError), } @@ -112,60 +108,7 @@ async fn handle_power_button( } #[embassy_executor::task] -async fn handle_buttons(adc: ADC1<'static>, button_1: GPIO1<'static>, button_2: GPIO2<'static>) { - let mut configuration = AdcConfig::new(); - let mut pin_1 = configuration - .enable_pin_with_cal::<_, AdcCalLine>>(button_1, Attenuation::_11dB); - let mut pin_2 = configuration - .enable_pin_with_cal::<_, AdcCalLine>>(button_2, Attenuation::_11dB); - let mut adc = Adc::new(adc, configuration).into_async(); - - /// Measured values and rough midway points - /// Midway points: ~2850 ~2300 ~1550 ~550 - /// Recorded values: 3087, 2629, 2013, 1117, 4 - const PIN_1_RANGES: [u16; 5] = [2850, 2300, 1550, 550, u16::MIN]; - - enum Pin { - One, - Two, - } - - /// Measured values and rough midway points - /// Midway points: ~2350 ~850 - /// Recorded values: 3087, 1670, 4 - const PIN_2_RANGES: [u16; 3] = [2350, 850, u16::MIN]; - fn get_button_number(pin_value: u16, ranges: &[u16], pin: Pin) -> Option { - let number_of_buttons: u8 = match pin { - Pin::One => 4, - Pin::Two => 2, - }; - - for button_number in 0..number_of_buttons { - let start = ranges[usize::from(button_number) + 1]; - let end = ranges[usize::from(button_number)]; - // if (start..end).contains(&pin_value) { - if start < pin_value && pin_value <= end { - return Some(button_number); - } - } - - None - } - - loop { - let value_1 = adc.read_oneshot(&mut pin_1).await; - let button = get_button_number(value_1, &PIN_1_RANGES, Pin::One); - let value_2 = adc.read_oneshot(&mut pin_2).await; - let button_2 = get_button_number(value_2, &PIN_2_RANGES, Pin::Two); - - info!( - "Button 1: {:?} {}, Button 2: {:?} {}", - button, value_1, button_2, value_2 - ); - - Timer::after_secs(1).await; - } -} +async fn handle_battery(adc: ADC2<'static>, pin: GPIO0<'static>) {} /// Just a convenience replacement for main to be able to return errors async fn run(spawner: Spawner) -> Result<(), ApplicationError> { @@ -208,13 +151,11 @@ async fn run(spawner: Spawner) -> Result<(), ApplicationError> { // Busy let busy = peripherals.GPIO6; + // Battery + let battery_adc = peripherals.GPIO0.adc_channel(); + info!("ADC channel for battery: {:?}", battery_adc); // Buttons - - spawner.spawn(handle_buttons( - peripherals.ADC1, - peripherals.GPIO1, - peripherals.GPIO2, - ))?; + let mut button = Button::new(peripherals.ADC1, peripherals.GPIO1, peripherals.GPIO2); let direct_memory_access_channel = peripherals.DMA_CH0; let sd_card_chip_select = peripherals.GPIO12; @@ -250,6 +191,11 @@ async fn run(spawner: Spawner) -> Result<(), ApplicationError> { display, ))?; + loop { + button.poll().await; + Timer::after_secs(1).await; + } + Ok(()) }