Skip to content

Commit

Permalink
Board docs (#105)
Browse files Browse the repository at this point in the history
  • Loading branch information
mattjperez authored Nov 20, 2023
1 parent 4d56373 commit c2c0555
Show file tree
Hide file tree
Showing 7 changed files with 209 additions and 136 deletions.
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ format:
doc:
cargo doc --no-default-features --features esp32 --target=xtensa-esp32-espidf -Zbuild-std=std,panic_abort

doc-open:
cargo doc --no-default-features --features esp32 --target=xtensa-esp32-espidf -Zbuild-std=std,panic_abort --open

size:
find . -name "esp-build.map" -exec ${IDF_PATH}/tools/idf_size.py {} \;

Expand Down
88 changes: 63 additions & 25 deletions src/common/board.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,22 @@
//! Abstraction of a general-purpose compute board
#![allow(dead_code)]
use crate::common::analog::AnalogReader;
use crate::common::status::Status;
use crate::google;
use crate::proto::common;
use crate::proto::component;
use crate::{
common::{analog::AnalogReader, status::Status},
google,
proto::{common, component},
};

use core::cell::RefCell;
use log::*;
use std::collections::HashMap;
use std::rc::Rc;
use std::sync::Arc;
use std::sync::Mutex;
use std::time::Duration;

use super::analog::FakeAnalogReader;
use super::config::ConfigType;
use super::i2c::FakeI2CHandle;
use super::i2c::FakeI2cConfig;
use super::i2c::I2CHandle;
use super::i2c::I2cHandleType;
use super::registry::ComponentRegistry;
use std::{collections::HashMap, rc::Rc, sync::Arc, sync::Mutex, time::Duration};

use super::{
analog::FakeAnalogReader,
config::ConfigType,
i2c::{FakeI2CHandle, FakeI2cConfig, I2CHandle, I2cHandleType},
registry::ComponentRegistry,
};

pub static COMPONENT_NAME: &str = "board";

Expand All @@ -31,39 +29,66 @@ pub(crate) fn register_models(registry: &mut ComponentRegistry) {
}
}

pub struct FakeBoard {
analogs: Vec<Rc<RefCell<dyn AnalogReader<u16, Error = anyhow::Error>>>>,
i2cs: HashMap<String, Arc<Mutex<FakeI2CHandle>>>,
pin_pwms: HashMap<i32, f64>,
pin_pwm_freq: HashMap<i32, u64>,
}
/// Represents the functionality of a general purpose compute board that contains various components such as analog readers and digital interrupts.
pub trait Board: Status {
/// Set a pin to high or low
fn set_gpio_pin_level(&mut self, pin: i32, is_high: bool) -> anyhow::Result<()>;

/// Return the current [BoardStatus](common::v1::BoardStatus) of the board
fn get_board_status(&self) -> anyhow::Result<common::v1::BoardStatus>;

/// Get the state of a pin, high(`true`) or low(`false`)
fn get_gpio_level(&self, pin: i32) -> anyhow::Result<bool>;

/// Get an [AnalogReader] by name
fn get_analog_reader_by_name(
&self,
name: String,
) -> anyhow::Result<Rc<RefCell<dyn AnalogReader<u16, Error = anyhow::Error>>>>;

/// Set the board to the indicated [PowerMode](component::board::v1::PowerMode)
fn set_power_mode(
&self,
mode: component::board::v1::PowerMode,
duration: Option<Duration>,
) -> anyhow::Result<()>;

/// Get a wrapped [I2CHandle] by name.
fn get_i2c_by_name(&self, name: String) -> anyhow::Result<I2cHandleType>;

/// Return the amount of detected interrupt events on a pin. Should error if the
/// pin has not been configured as an interrupt
fn get_digital_interrupt_value(&self, _pin: i32) -> anyhow::Result<u32> {
anyhow::bail!("this board does not support digital interrupts")
}

/// Get the pin's given duty cycle, returns percentage as float between 0.0 and 1.0
fn get_pwm_duty(&self, pin: i32) -> f64;

/// Set the pin to the given duty cycle , `duty_cycle_pct` is a float between 0.0 and 1.0.
fn set_pwm_duty(&mut self, pin: i32, duty_cycle_pct: f64) -> anyhow::Result<()>;

/// Get the PWM frequency of the pin
fn get_pwm_frequency(&self, pin: i32) -> anyhow::Result<u64>;

/// Set the pin to the given PWM frequency (in Hz).
/// When frequency is 0, the board will unregister the pin and PWM channel from
/// the timer and removes the PWM signal.
fn set_pwm_frequency(&mut self, pin: i32, frequency_hz: u64) -> anyhow::Result<()>;
}

/// An alias for a thread-safe handle to a struct that implements the [Board] trait
pub type BoardType = Arc<Mutex<dyn Board>>;

#[doc(hidden)]
/// A test implementation of a generic compute board
pub struct FakeBoard {
analogs: Vec<Rc<RefCell<dyn AnalogReader<u16, Error = anyhow::Error>>>>,
i2cs: HashMap<String, Arc<Mutex<FakeI2CHandle>>>,
pin_pwms: HashMap<i32, f64>,
pin_pwm_freq: HashMap<i32, u64>,
}

impl FakeBoard {
pub fn new(analogs: Vec<Rc<RefCell<dyn AnalogReader<u16, Error = anyhow::Error>>>>) -> Self {
let mut i2cs: HashMap<String, Arc<Mutex<FakeI2CHandle>>> = HashMap::new();
Expand All @@ -78,6 +103,7 @@ impl FakeBoard {
pin_pwm_freq: HashMap::new(),
}
}

pub(crate) fn from_config(cfg: ConfigType) -> anyhow::Result<BoardType> {
let analogs = if let Ok(analog_confs) = cfg.get_attribute::<HashMap<&str, f64>>("analogs") {
analog_confs
Expand Down Expand Up @@ -121,6 +147,7 @@ impl Board for FakeBoard {
info!("set pin {} to {}", pin, is_high);
Ok(())
}

fn get_board_status(&self) -> anyhow::Result<common::v1::BoardStatus> {
let mut b = common::v1::BoardStatus {
analogs: HashMap::new(),
Expand All @@ -135,12 +162,14 @@ impl Board for FakeBoard {
},
);
});
Ok(b) //component::board::v1::StatusResponse { status: Some(b) }
Ok(b)
}

fn get_gpio_level(&self, pin: i32) -> anyhow::Result<bool> {
info!("get pin {}", pin);
Ok(true)
}

fn get_analog_reader_by_name(
&self,
name: String,
Expand All @@ -150,6 +179,7 @@ impl Board for FakeBoard {
None => Err(anyhow::anyhow!("couldn't find analog reader {}", name)),
}
}

fn set_power_mode(
&self,
mode: component::board::v1::PowerMode,
Expand All @@ -165,23 +195,28 @@ impl Board for FakeBoard {
);
Ok(())
}

fn get_i2c_by_name(&self, name: String) -> anyhow::Result<I2cHandleType> {
if let Some(i2c_handle) = self.i2cs.get(&name) {
Ok((*i2c_handle).clone())
} else {
anyhow::bail!("could not find I2C with name {}", name)
}
}

fn get_pwm_duty(&self, pin: i32) -> f64 {
*self.pin_pwms.get(&pin).unwrap_or(&0.0)
}

fn set_pwm_duty(&mut self, pin: i32, duty_cycle_pct: f64) -> anyhow::Result<()> {
self.pin_pwms.insert(pin, duty_cycle_pct);
Ok(())
}

fn get_pwm_frequency(&self, pin: i32) -> anyhow::Result<u64> {
Ok(*self.pin_pwm_freq.get(&pin).unwrap_or(&0))
}

fn set_pwm_frequency(&mut self, pin: i32, frequency_hz: u64) -> anyhow::Result<()> {
self.pin_pwm_freq.insert(pin, frequency_hz);
Ok(())
Expand Down Expand Up @@ -233,12 +268,15 @@ where
fn get_board_status(&self) -> anyhow::Result<common::v1::BoardStatus> {
self.lock().unwrap().get_board_status()
}

fn get_gpio_level(&self, pin: i32) -> anyhow::Result<bool> {
self.lock().unwrap().get_gpio_level(pin)
}

fn set_gpio_pin_level(&mut self, pin: i32, is_high: bool) -> anyhow::Result<()> {
self.lock().unwrap().set_gpio_pin_level(pin, is_high)
}

fn get_analog_reader_by_name(
&self,
name: String,
Expand Down
73 changes: 73 additions & 0 deletions src/common/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
//! Structs, traits, and utils to develop [component](https://docs.viam.com/components/)
//! drivers.
//!
//! # Components
//! - [actuator]
//! - [base]
//! - [board]
//! - [camera]
//! - [encoder]
//! - [motor]
//! - [movement_sensor]
//! - [sensor]
//! - [servo]
//!
//! # Utils
//! - [grpc]
//! - [grpc_client]
//! - [i2c]
//! - [webrtc]
//! - [conn]
//!
//!
//! General Purpose Drivers
//! - [gpio_motor]
//! - [adxl345]
//! - [mpu6050]
pub mod actuator;
pub mod adxl345;
pub mod analog;
pub mod app_client;
pub mod base;
pub mod board;
pub mod camera;
pub mod config;
pub mod digital_interrupt;
pub mod encoder;
pub mod entry;
pub mod generic;
pub mod gpio_motor;
pub mod gpio_servo;
pub mod grpc;
pub mod grpc_client;
pub mod i2c;
pub mod log;
pub mod math_utils;
pub mod moisture_sensor;
pub mod motor;
pub mod movement_sensor;
pub mod mpu6050;
pub mod power_sensor;
pub mod registry;
pub mod robot;
pub mod sensor;
pub mod servo;
pub mod status;
pub mod webrtc {
pub mod api;
pub mod candidates;
pub mod certificate;
pub mod dtls;
pub mod exec;
pub mod grpc;
pub mod ice;
pub mod io;
pub mod sctp;
}
pub mod conn {
pub mod errors;
pub mod mdns;
pub mod server;
mod utils;
}
58 changes: 31 additions & 27 deletions src/esp32/board.rs
Original file line number Diff line number Diff line change
@@ -1,35 +1,38 @@
#![allow(dead_code)]
use crate::common::analog::AnalogReader;
use crate::common::analog::AnalogReaderConfig;
use crate::common::board::Board;
use crate::common::board::BoardType;
use crate::common::config::ConfigType;
use crate::common::digital_interrupt::DigitalInterruptConfig;
use crate::common::i2c::I2cHandleType;
use crate::common::registry::ComponentRegistry;
use crate::common::status::Status;
use crate::google;
use crate::proto::common;
use crate::proto::component;

use anyhow::Context;
use core::cell::RefCell;
use esp_idf_hal::adc::config::Config;
use esp_idf_hal::adc::AdcChannelDriver;
use esp_idf_hal::adc::AdcDriver;
use esp_idf_hal::adc::Atten11dB;
use esp_idf_hal::adc::ADC1;
use esp_idf_hal::gpio::InterruptType;

use log::*;
use std::collections::HashMap;
use std::rc::Rc;
use std::sync::{Arc, Mutex};
use std::time::Duration;
use std::{
collections::HashMap,
rc::Rc,
sync::{Arc, Mutex},
time::Duration,
};

use crate::{
common::{
analog::{AnalogReader, AnalogReaderConfig},
board::{Board, BoardType},
config::ConfigType,
digital_interrupt::DigitalInterruptConfig,
i2c::I2cHandleType,
registry::ComponentRegistry,
status::Status,
},
google,
proto::{common, component},
};

use super::{
analog::Esp32AnalogReader,
i2c::{Esp32I2C, Esp32I2cConfig},
pin::Esp32GPIOPin,
};

use super::analog::Esp32AnalogReader;
use super::i2c::{Esp32I2C, Esp32I2cConfig};
use super::pin::Esp32GPIOPin;
use esp_idf_hal::{
adc::{config::Config, AdcChannelDriver, AdcDriver, Atten11dB, ADC1},
gpio::InterruptType,
};

pub(crate) fn register_models(registry: &mut ComponentRegistry) {
if registry
Expand All @@ -40,6 +43,7 @@ pub(crate) fn register_models(registry: &mut ComponentRegistry) {
}
}

/// An ESP32 implementation that wraps esp-idf functionality
pub struct EspBoard {
pins: Vec<Esp32GPIOPin>,
analogs: Vec<Rc<RefCell<dyn AnalogReader<u16, Error = anyhow::Error>>>>,
Expand Down
25 changes: 25 additions & 0 deletions src/esp32/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//! ESP32-specific implementations of components and tools
pub mod analog;
pub mod base;
pub mod board;
#[cfg(feature = "camera")]
pub mod camera;
pub mod certificate;
pub mod dtls;
pub mod encoder;
pub mod entry;
pub mod exec;
pub mod i2c;
pub mod pin;
pub mod pulse_counter;
pub mod pwm;
pub mod single_encoded_motor;
pub mod single_encoder;
pub mod tcp;
pub mod tls;
pub mod utils;
pub mod webhook;
pub mod conn {
pub mod mdns;
}
Loading

0 comments on commit c2c0555

Please sign in to comment.