Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion urust-fw-wroom32d/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"] }
Expand Down
15 changes: 15 additions & 0 deletions urust-fw-wroom32d/src/error.rs
Original file line number Diff line number Diff line change
@@ -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<T> = Result<T, UrError>;
25 changes: 17 additions & 8 deletions urust-fw-wroom32d/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,28 @@
mod ur_context;
use anyhow::Result;

use crate::modules::gpio::{
UrGpioContext,
Esp32Wroom32dPinResolver,
};

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 = Esp32Wroom32dPinResolver::new();

fn main() -> anyhow::Result<()> {
println!("uRust: Hello from ESP32-WROOM-32D!");
let gpio = UrGpioContext::new(Box::new(resolver));

let peripherals: Peripherals = Peripherals::take().unwrap();
let mut led: UrPinsContext<Gpio2> = UrPinsContext::new(peripherals.pins.gpio2);
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));
}
Expand Down
32 changes: 32 additions & 0 deletions urust-fw-wroom32d/src/modules/gpio/allocator.rs
Original file line number Diff line number Diff line change
@@ -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<Vec<u8, MAX_GPIO>>,
}

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);
}
}
6 changes: 6 additions & 0 deletions urust-fw-wroom32d/src/modules/gpio/factory.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
use esp_idf_hal::gpio::AnyIOPin;

pub trait UrPinResolver {
fn gpio_out(&self, gpio: u8) -> Option<AnyIOPin>;
fn gpio_in(&self, gpio: u8) -> Option<AnyIOPin>;
}
35 changes: 35 additions & 0 deletions urust-fw-wroom32d/src/modules/gpio/factory_esp32_wroom.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
use esp_idf_hal::gpio::{AnyIOPin};
use super::factory::UrPinResolver;

pub struct Esp32Wroom32dPinResolver;

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; }

true
}

fn is_input_only(gpio: u8) -> bool {
(34..=39).contains(&gpio)
}
}

impl UrPinResolver for Esp32Wroom32dPinResolver {
fn gpio_out(&self, gpio: u8) -> Option<AnyIOPin> {
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<AnyIOPin> {
if !Self::is_valid_gpio(gpio) { return None; }
Some(unsafe { AnyIOPin::new(gpio as i32) })
}
}
53 changes: 53 additions & 0 deletions urust-fw-wroom32d/src/modules/gpio/handle.rs
Original file line number Diff line number Diff line change
@@ -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<Self> {
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<Self> {
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()
}
}
46 changes: 46 additions & 0 deletions urust-fw-wroom32d/src/modules/gpio/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
mod allocator;
mod factory;
pub mod factory_esp32_wroom;
mod handle;
mod types;

use allocator::GpioAllocator;
use crate::error::{UrError, UrResult};

pub use factory_esp32_wroom::Esp32Wroom32dPinResolver;

pub use handle::{UrGpioIn, UrGpioOut};
pub use types::Pull;

pub use factory::UrPinResolver;

pub struct UrGpioContext {
alloc: GpioAllocator,
factory: Box<dyn factory::UrPinResolver>,
}

impl UrGpioContext {
pub fn new(factory: Box<dyn factory::UrPinResolver>) -> Self {
Self {
alloc: GpioAllocator::new(),
factory,
}
}

pub fn out(&self, gpio: u8) -> UrResult<UrGpioOut> {
self.alloc.alloc(gpio)?;
if (34..=39).contains(&gpio) { return Err(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<UrGpioIn> {
self.alloc.alloc(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);
}
}
6 changes: 6 additions & 0 deletions urust-fw-wroom32d/src/modules/gpio/types.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#[derive(Clone, Copy)]
pub enum Pull {
None,
Up,
Down,
}
4 changes: 3 additions & 1 deletion urust-fw-wroom32d/src/modules/mod.rs
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
pub mod ur_pins_context;

pub mod ur_timer_context;
pub mod gpio;
26 changes: 0 additions & 26 deletions urust-fw-wroom32d/src/modules/ur_pins_context.rs

This file was deleted.

9 changes: 9 additions & 0 deletions urust-fw-wroom32d/src/modules/ur_timer_context.rs
Original file line number Diff line number Diff line change
@@ -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);
}
}
8 changes: 5 additions & 3 deletions urust-fw-wroom32d/src/ur_context.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use crate::modules::ur_pins_context::UrPinsContext;
use crate::modules::ur_pins_context::{UrGpioContext, UrPinsContext};
use crate::modules::ur_timer_context::UrTimerContext;
use esp_idf_hal::gpio::OutputPin;

pub struct UrContext<PIN: OutputPin> {
pub led: UrPinsContext<PIN>,
pub struct UrContext {
pub pin: UrGpioContext,
pub time: UrTimerContext,
}