From 20a7f238fefdcaabd846584543600c51197d074b Mon Sep 17 00:00:00 2001 From: dweg0 Date: Fri, 12 Dec 2025 11:22:34 -0300 Subject: [PATCH 1/3] feat: UrTimerContext has been created to set timer in a std env --- urust-fw-wroom32d/src/main.rs | 6 +++--- urust-fw-wroom32d/src/modules/mod.rs | 3 ++- urust-fw-wroom32d/src/modules/ur_timer_context.rs | 9 +++++++++ urust-fw-wroom32d/src/ur_context.rs | 4 +++- 4 files changed, 17 insertions(+), 5 deletions(-) create mode 100644 urust-fw-wroom32d/src/modules/ur_timer_context.rs diff --git a/urust-fw-wroom32d/src/main.rs b/urust-fw-wroom32d/src/main.rs index a1cf4ba..3a8aaf8 100644 --- a/urust-fw-wroom32d/src/main.rs +++ b/urust-fw-wroom32d/src/main.rs @@ -10,11 +10,11 @@ fn main() -> anyhow::Result<()> { let peripherals: Peripherals = Peripherals::take().unwrap(); let mut led: UrPinsContext = UrPinsContext::new(peripherals.pins.gpio2); - + let _timer = modules::ur_timer_context::UrTimerContext; loop { led.set(true); - std::thread::sleep(std::time::Duration::from_millis(500)); + _timer.sleep_ms(500); led.set(false); - std::thread::sleep(std::time::Duration::from_millis(500)); + _timer.sleep_ms(500); } } diff --git a/urust-fw-wroom32d/src/modules/mod.rs b/urust-fw-wroom32d/src/modules/mod.rs index f8a812c..9c7807b 100644 --- a/urust-fw-wroom32d/src/modules/mod.rs +++ b/urust-fw-wroom32d/src/modules/mod.rs @@ -1 +1,2 @@ -pub mod ur_pins_context; \ No newline at end of file +pub mod ur_pins_context; +pub mod ur_timer_context; \ No newline at end of file diff --git a/urust-fw-wroom32d/src/modules/ur_timer_context.rs b/urust-fw-wroom32d/src/modules/ur_timer_context.rs new file mode 100644 index 0000000..dc7c7f7 --- /dev/null +++ b/urust-fw-wroom32d/src/modules/ur_timer_context.rs @@ -0,0 +1,9 @@ +use esp_idf_hal::delay::FreeRtos; + +pub struct UrTimerContext; + +impl UrTimerContext { + pub fn sleep_ms(&self, time_ms: u32) { + FreeRtos::delay_ms(time_ms); + } +} \ No newline at end of file diff --git a/urust-fw-wroom32d/src/ur_context.rs b/urust-fw-wroom32d/src/ur_context.rs index b7f1050..19b89b3 100644 --- a/urust-fw-wroom32d/src/ur_context.rs +++ b/urust-fw-wroom32d/src/ur_context.rs @@ -1,6 +1,8 @@ use crate::modules::ur_pins_context::UrPinsContext; use esp_idf_hal::gpio::OutputPin; +use crate::modules::ur_timer_context::UrTimerContext; pub struct UrContext { - pub led: UrPinsContext, + pub pin: UrPinsContext, + pub timer: UrTimerContext, } From f86b8b50f42e257f4abdaa00bc25ea4a3338184e Mon Sep 17 00:00:00 2001 From: dweg0 Date: Mon, 15 Dec 2025 10:36:47 -0300 Subject: [PATCH 2/3] feat: new gpio logic implemented --- urust-fw-wroom32d/Cargo.toml | 4 +- urust-fw-wroom32d/src/error.rs | 15 ++++++ urust-fw-wroom32d/src/main.rs | 27 ++++++---- .../src/modules/gpio/allocator.rs | 32 +++++++++++ urust-fw-wroom32d/src/modules/gpio/factory.rs | 5 ++ .../src/modules/gpio/factory_esp32_wroom.rs | 21 ++++++++ urust-fw-wroom32d/src/modules/gpio/handle.rs | 53 +++++++++++++++++++ urust-fw-wroom32d/src/modules/gpio/mod.rs | 47 ++++++++++++++++ urust-fw-wroom32d/src/modules/gpio/types.rs | 6 +++ urust-fw-wroom32d/src/modules/mod.rs | 5 +- .../src/modules/ur_pins_context.rs | 26 --------- urust-fw-wroom32d/src/ur_context.rs | 10 ++-- 12 files changed, 206 insertions(+), 45 deletions(-) create mode 100644 urust-fw-wroom32d/src/error.rs create mode 100644 urust-fw-wroom32d/src/modules/gpio/allocator.rs create mode 100644 urust-fw-wroom32d/src/modules/gpio/factory.rs create mode 100644 urust-fw-wroom32d/src/modules/gpio/factory_esp32_wroom.rs create mode 100644 urust-fw-wroom32d/src/modules/gpio/handle.rs create mode 100644 urust-fw-wroom32d/src/modules/gpio/mod.rs create mode 100644 urust-fw-wroom32d/src/modules/gpio/types.rs delete mode 100644 urust-fw-wroom32d/src/modules/ur_pins_context.rs diff --git a/urust-fw-wroom32d/Cargo.toml b/urust-fw-wroom32d/Cargo.toml index 32ff6a3..cb86009 100644 --- a/urust-fw-wroom32d/Cargo.toml +++ b/urust-fw-wroom32d/Cargo.toml @@ -27,7 +27,9 @@ log = "0.4" esp-idf-svc = "0.51" esp-idf-hal = "0.45.2" esp-idf-sys = "0.36.1" -anyhow = "1.0.100" +anyhow = "1" +thiserror = "1" +heapless = "0.8.0" # --- Optional Embassy Integration --- # esp-idf-svc = { version = "0.51", features = ["critical-section", "embassy-time-driver", "embassy-sync"] } diff --git a/urust-fw-wroom32d/src/error.rs b/urust-fw-wroom32d/src/error.rs new file mode 100644 index 0000000..ad3bfe6 --- /dev/null +++ b/urust-fw-wroom32d/src/error.rs @@ -0,0 +1,15 @@ +use thiserror::Error; + +#[derive(Debug, Error)] +pub enum UrError { + #[error("invalid gpio: {0}")] + InvalidGpio(u8), + + #[error("gpio already allocated: {0}")] + GpioAlreadyAllocated(u8), + + #[error("hal error")] + HalError, +} + +pub type UrResult = Result; diff --git a/urust-fw-wroom32d/src/main.rs b/urust-fw-wroom32d/src/main.rs index 3a8aaf8..a0d7fdc 100644 --- a/urust-fw-wroom32d/src/main.rs +++ b/urust-fw-wroom32d/src/main.rs @@ -1,20 +1,25 @@ -mod ur_context; +use anyhow::Result; + +use crate::modules::gpio::{ + UrGpioContext, + Esp32WroomPinResolver, +}; + mod modules; +mod error; -use esp_idf_hal::prelude::*; -use esp_idf_hal::gpio::{Gpio2}; -use crate::modules::ur_pins_context::{UrPinsContext}; +fn main() -> Result<()> { + let resolver = Esp32WroomPinResolver::new(); -fn main() -> anyhow::Result<()> { - println!("uRust: Hello from ESP32-WROOM-32D!"); + let gpio = UrGpioContext::new(Box::new(resolver)); + + let mut led = gpio.out(2)?; - let peripherals: Peripherals = Peripherals::take().unwrap(); - let mut led: UrPinsContext = UrPinsContext::new(peripherals.pins.gpio2); - let _timer = modules::ur_timer_context::UrTimerContext; loop { led.set(true); - _timer.sleep_ms(500); + std::thread::sleep(std::time::Duration::from_millis(500)); + led.set(false); - _timer.sleep_ms(500); + std::thread::sleep(std::time::Duration::from_millis(500)); } } diff --git a/urust-fw-wroom32d/src/modules/gpio/allocator.rs b/urust-fw-wroom32d/src/modules/gpio/allocator.rs new file mode 100644 index 0000000..ed92c6b --- /dev/null +++ b/urust-fw-wroom32d/src/modules/gpio/allocator.rs @@ -0,0 +1,32 @@ +use core::cell::RefCell; +use heapless::Vec; + +use crate::error::{UrError, UrResult}; + +const MAX_GPIO: usize = 40; + +pub struct GpioAllocator { + used: RefCell>, +} + +impl GpioAllocator { + pub fn new() -> Self { + Self { + used: RefCell::new(Vec::new()), + } + } + + pub fn alloc(&self, gpio: u8) -> UrResult<()> { + let mut used = self.used.borrow_mut(); + if used.iter().any(|&g| g == gpio) { + return Err(UrError::GpioAlreadyAllocated(gpio)); + } + used.push(gpio).map_err(|_| UrError::HalError)?; + Ok(()) + } + + pub fn free(&self, gpio: u8) { + let mut used = self.used.borrow_mut(); + used.retain(|&g| g != gpio); + } +} diff --git a/urust-fw-wroom32d/src/modules/gpio/factory.rs b/urust-fw-wroom32d/src/modules/gpio/factory.rs new file mode 100644 index 0000000..028a174 --- /dev/null +++ b/urust-fw-wroom32d/src/modules/gpio/factory.rs @@ -0,0 +1,5 @@ +use esp_idf_hal::gpio::AnyIOPin; + +pub trait UrPinResolver { + fn any_io(&self, gpio: u8) -> Option; +} diff --git a/urust-fw-wroom32d/src/modules/gpio/factory_esp32_wroom.rs b/urust-fw-wroom32d/src/modules/gpio/factory_esp32_wroom.rs new file mode 100644 index 0000000..14765e9 --- /dev/null +++ b/urust-fw-wroom32d/src/modules/gpio/factory_esp32_wroom.rs @@ -0,0 +1,21 @@ +use esp_idf_hal::gpio::AnyIOPin; +use super::factory::UrPinResolver; + +pub struct Esp32WroomPinResolver; + +impl Esp32WroomPinResolver { + pub fn new() -> Self { Self } + + fn is_valid_gpio(gpio: u8) -> bool { + if gpio > 39 { return false; } + if (6..=11).contains(&gpio) { return false; } // flash + true + } +} + +impl UrPinResolver for Esp32WroomPinResolver { + fn any_io(&self, gpio: u8) -> Option { + if !Self::is_valid_gpio(gpio) { return None; } + Some(unsafe { AnyIOPin::new(gpio as i32) }) + } +} diff --git a/urust-fw-wroom32d/src/modules/gpio/handle.rs b/urust-fw-wroom32d/src/modules/gpio/handle.rs new file mode 100644 index 0000000..633d939 --- /dev/null +++ b/urust-fw-wroom32d/src/modules/gpio/handle.rs @@ -0,0 +1,53 @@ +use esp_idf_hal::gpio::{ + AnyIOPin, + Input, + Output, + PinDriver, + Pull as HalPull, +}; + +use crate::error::{UrError, UrResult}; +use super::types::Pull; + +pub struct UrGpioOut { + pin: PinDriver<'static, AnyIOPin, Output>, +} + +pub struct UrGpioIn { + pin: PinDriver<'static, AnyIOPin, Input>, +} + +impl UrGpioOut { + pub fn new(pin: AnyIOPin) -> UrResult { + let driver = PinDriver::output(pin).map_err(|_| UrError::HalError)?; + Ok(Self { pin: driver }) + } + + pub fn set(&mut self, high: bool) { + if high { let _ = self.pin.set_high(); } + else { let _ = self.pin.set_low(); } + } + + pub fn toggle(&mut self) { + let _ = self.pin.toggle(); + } +} + +impl UrGpioIn { + pub fn new(pin: AnyIOPin, pull: Pull) -> UrResult { + let mut driver = PinDriver::input(pin).map_err(|_| UrError::HalError)?; + + let hal_pull = match pull { + Pull::None => HalPull::Floating, + Pull::Up => HalPull::Up, + Pull::Down => HalPull::Down, + }; + + driver.set_pull(hal_pull).map_err(|_| UrError::HalError)?; + Ok(Self { pin: driver }) + } + + pub fn is_high(&self) -> bool { + self.pin.is_high() + } +} diff --git a/urust-fw-wroom32d/src/modules/gpio/mod.rs b/urust-fw-wroom32d/src/modules/gpio/mod.rs new file mode 100644 index 0000000..170649a --- /dev/null +++ b/urust-fw-wroom32d/src/modules/gpio/mod.rs @@ -0,0 +1,47 @@ +mod allocator; +mod factory; +pub mod factory_esp32_wroom; +mod handle; +mod types; + +pub use factory_esp32_wroom::Esp32WroomPinResolver; + +use allocator::GpioAllocator; +use crate::error::{UrError, UrResult}; + +pub use handle::{UrGpioIn, UrGpioOut}; +pub use types::Pull; + +pub use factory::UrPinResolver; + +pub struct UrGpioContext { + alloc: GpioAllocator, + factory: Box, +} + +impl UrGpioContext { + pub fn new(factory: Box) -> Self { + Self { + alloc: GpioAllocator::new(), + factory, + } + } + + pub fn out(&self, gpio: u8) -> UrResult { + self.alloc.alloc(gpio)?; + if (34..=39).contains(&gpio) { return Err(UrError::InvalidGpio(gpio)); } + let pin = self.factory.any_io(gpio).ok_or(UrError::InvalidGpio(gpio))?; + UrGpioOut::new(pin) + } + + pub fn input(&self, gpio: u8, pull: Pull) -> UrResult { + self.alloc.alloc(gpio)?; + let pin = self.factory.any_io(gpio).ok_or(UrError::InvalidGpio(gpio))?; + UrGpioIn::new(pin, pull) + } + + + pub fn free(&self, gpio: u8) { + self.alloc.free(gpio); + } +} diff --git a/urust-fw-wroom32d/src/modules/gpio/types.rs b/urust-fw-wroom32d/src/modules/gpio/types.rs new file mode 100644 index 0000000..1b79e9d --- /dev/null +++ b/urust-fw-wroom32d/src/modules/gpio/types.rs @@ -0,0 +1,6 @@ +#[derive(Clone, Copy)] +pub enum Pull { + None, + Up, + Down, +} diff --git a/urust-fw-wroom32d/src/modules/mod.rs b/urust-fw-wroom32d/src/modules/mod.rs index 9c7807b..be320e8 100644 --- a/urust-fw-wroom32d/src/modules/mod.rs +++ b/urust-fw-wroom32d/src/modules/mod.rs @@ -1,2 +1,3 @@ -pub mod ur_pins_context; -pub mod ur_timer_context; \ No newline at end of file + +pub mod ur_timer_context; +pub(crate) mod gpio; \ No newline at end of file diff --git a/urust-fw-wroom32d/src/modules/ur_pins_context.rs b/urust-fw-wroom32d/src/modules/ur_pins_context.rs deleted file mode 100644 index 3cd2697..0000000 --- a/urust-fw-wroom32d/src/modules/ur_pins_context.rs +++ /dev/null @@ -1,26 +0,0 @@ -use esp_idf_hal::gpio::{Output, OutputPin, PinDriver}; - -pub struct UrPinsContext { - pin: PinDriver<'static, PIN, Output>, - is_on: bool, -} - -impl UrPinsContext { - pub fn new(pin: PIN) -> Self { - let driver = PinDriver::output(pin).unwrap(); - Self { pin: driver, is_on: false } - } - - pub fn set(&mut self, is_on: bool) { - self.is_on = is_on; - self.apply(); - } - - fn apply(&mut self) { - if self.is_on { - self.pin.set_high().unwrap(); - } else { - self.pin.set_low().unwrap(); - } - } -} diff --git a/urust-fw-wroom32d/src/ur_context.rs b/urust-fw-wroom32d/src/ur_context.rs index 19b89b3..ae6bfa5 100644 --- a/urust-fw-wroom32d/src/ur_context.rs +++ b/urust-fw-wroom32d/src/ur_context.rs @@ -1,8 +1,8 @@ -use crate::modules::ur_pins_context::UrPinsContext; -use esp_idf_hal::gpio::OutputPin; +use crate::modules::ur_pins_context::{UrGpioContext, UrPinsContext}; use crate::modules::ur_timer_context::UrTimerContext; +use esp_idf_hal::gpio::OutputPin; -pub struct UrContext { - pub pin: UrPinsContext, - pub timer: UrTimerContext, +pub struct UrContext { + pub pin: UrGpioContext, + pub time: UrTimerContext, } From b82e405be255c00be0ad2d43c8aa05d95b00f220 Mon Sep 17 00:00:00 2001 From: dweg0 Date: Mon, 15 Dec 2025 11:19:22 -0300 Subject: [PATCH 3/3] refactor: gpio code has been refactored --- urust-fw-wroom32d/src/main.rs | 8 ++++-- urust-fw-wroom32d/src/modules/gpio/factory.rs | 5 ++-- .../src/modules/gpio/factory_esp32_wroom.rs | 28 ++++++++++++++----- urust-fw-wroom32d/src/modules/gpio/mod.rs | 9 +++--- urust-fw-wroom32d/src/modules/mod.rs | 2 +- 5 files changed, 35 insertions(+), 17 deletions(-) diff --git a/urust-fw-wroom32d/src/main.rs b/urust-fw-wroom32d/src/main.rs index a0d7fdc..d1eac6f 100644 --- a/urust-fw-wroom32d/src/main.rs +++ b/urust-fw-wroom32d/src/main.rs @@ -2,23 +2,27 @@ use anyhow::Result; use crate::modules::gpio::{ UrGpioContext, - Esp32WroomPinResolver, + Esp32Wroom32dPinResolver, }; mod modules; mod error; fn main() -> Result<()> { - let resolver = Esp32WroomPinResolver::new(); + let resolver = Esp32Wroom32dPinResolver::new(); let gpio = UrGpioContext::new(Box::new(resolver)); let mut led = gpio.out(2)?; + let mut led2 = gpio.out(13)?; loop { led.set(true); + led2.set(false); std::thread::sleep(std::time::Duration::from_millis(500)); + + led2.set(true); led.set(false); std::thread::sleep(std::time::Duration::from_millis(500)); } diff --git a/urust-fw-wroom32d/src/modules/gpio/factory.rs b/urust-fw-wroom32d/src/modules/gpio/factory.rs index 028a174..c0b269e 100644 --- a/urust-fw-wroom32d/src/modules/gpio/factory.rs +++ b/urust-fw-wroom32d/src/modules/gpio/factory.rs @@ -1,5 +1,6 @@ use esp_idf_hal::gpio::AnyIOPin; pub trait UrPinResolver { - fn any_io(&self, gpio: u8) -> Option; -} + fn gpio_out(&self, gpio: u8) -> Option; + fn gpio_in(&self, gpio: u8) -> Option; +} \ No newline at end of file diff --git a/urust-fw-wroom32d/src/modules/gpio/factory_esp32_wroom.rs b/urust-fw-wroom32d/src/modules/gpio/factory_esp32_wroom.rs index 14765e9..8328c1d 100644 --- a/urust-fw-wroom32d/src/modules/gpio/factory_esp32_wroom.rs +++ b/urust-fw-wroom32d/src/modules/gpio/factory_esp32_wroom.rs @@ -1,20 +1,34 @@ -use esp_idf_hal::gpio::AnyIOPin; +use esp_idf_hal::gpio::{AnyIOPin}; use super::factory::UrPinResolver; -pub struct Esp32WroomPinResolver; +pub struct Esp32Wroom32dPinResolver; -impl Esp32WroomPinResolver { - pub fn new() -> Self { Self } +impl Esp32Wroom32dPinResolver { + pub fn new() -> Self { + Self + } fn is_valid_gpio(gpio: u8) -> bool { if gpio > 39 { return false; } - if (6..=11).contains(&gpio) { return false; } // flash + + if (6..=11).contains(&gpio) { return false; } + true } + + fn is_input_only(gpio: u8) -> bool { + (34..=39).contains(&gpio) + } } -impl UrPinResolver for Esp32WroomPinResolver { - fn any_io(&self, gpio: u8) -> Option { +impl UrPinResolver for Esp32Wroom32dPinResolver { + fn gpio_out(&self, gpio: u8) -> Option { + if !Self::is_valid_gpio(gpio) { return None; } + if Self::is_input_only(gpio) { return None; } + Some(unsafe { AnyIOPin::new(gpio as i32) }) + } + + fn gpio_in(&self, gpio: u8) -> Option { if !Self::is_valid_gpio(gpio) { return None; } Some(unsafe { AnyIOPin::new(gpio as i32) }) } diff --git a/urust-fw-wroom32d/src/modules/gpio/mod.rs b/urust-fw-wroom32d/src/modules/gpio/mod.rs index 170649a..2dacd2f 100644 --- a/urust-fw-wroom32d/src/modules/gpio/mod.rs +++ b/urust-fw-wroom32d/src/modules/gpio/mod.rs @@ -4,11 +4,11 @@ pub mod factory_esp32_wroom; mod handle; mod types; -pub use factory_esp32_wroom::Esp32WroomPinResolver; - use allocator::GpioAllocator; use crate::error::{UrError, UrResult}; +pub use factory_esp32_wroom::Esp32Wroom32dPinResolver; + pub use handle::{UrGpioIn, UrGpioOut}; pub use types::Pull; @@ -30,17 +30,16 @@ impl UrGpioContext { pub fn out(&self, gpio: u8) -> UrResult { self.alloc.alloc(gpio)?; if (34..=39).contains(&gpio) { return Err(UrError::InvalidGpio(gpio)); } - let pin = self.factory.any_io(gpio).ok_or(UrError::InvalidGpio(gpio))?; + let pin = self.factory.gpio_out(gpio).ok_or(UrError::InvalidGpio(gpio))?; UrGpioOut::new(pin) } pub fn input(&self, gpio: u8, pull: Pull) -> UrResult { self.alloc.alloc(gpio)?; - let pin = self.factory.any_io(gpio).ok_or(UrError::InvalidGpio(gpio))?; + let pin = self.factory.gpio_in(gpio).ok_or(UrError::InvalidGpio(gpio))?; UrGpioIn::new(pin, pull) } - pub fn free(&self, gpio: u8) { self.alloc.free(gpio); } diff --git a/urust-fw-wroom32d/src/modules/mod.rs b/urust-fw-wroom32d/src/modules/mod.rs index be320e8..7e3815e 100644 --- a/urust-fw-wroom32d/src/modules/mod.rs +++ b/urust-fw-wroom32d/src/modules/mod.rs @@ -1,3 +1,3 @@ pub mod ur_timer_context; -pub(crate) mod gpio; \ No newline at end of file +pub mod gpio; \ No newline at end of file