Skip to content

Commit

Permalink
Make utility methods for creating raspberry PI peripherals
Browse files Browse the repository at this point in the history
  • Loading branch information
BradenEverson committed Sep 13, 2024
1 parent e5acba6 commit 51b560b
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 14 deletions.
1 change: 1 addition & 0 deletions achiever/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ authors.workspace = true
[dependencies]
rppal = { version = "0.19.0", optional = true }
slotmap = "1.0.7"
thiserror = "1.0.63"

[lib]

Expand Down
33 changes: 30 additions & 3 deletions achiever/src/body.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! The hardware controls for the agent

use std::error::Error;
use std::convert::Infallible;

use inputs::Input;
use outputs::Output;
Expand All @@ -9,6 +9,33 @@ use slotmap::{new_key_type, SlotMap};
pub mod inputs;
pub mod outputs;

#[derive(thiserror::Error, Debug)]
/// Any error that may come from a peripheral
pub enum PeripheralError {
#[cfg(feature = "rpi")]
#[error("SPI Error")]
/// A raspberry pi spi error
SpiError(#[from] rppal::spi::Error),
#[cfg(feature = "rpi")]
#[error("GPIO Error")]
/// A raspberry pi gpio error
GpioError(#[from] rppal::gpio::Error),
#[cfg(feature = "rpi")]
#[error("Uart Error")]
/// A raspberry pi uart error
UartError(#[from] rppal::uart::Error),
#[cfg(feature = "rpi")]
#[error("I2C Error")]
/// A raspberry pi i2c error
I2CError(#[from] rppal::i2c::Error),
#[error("Infallible")]
/// An error that will never be returned
Infallible(#[from] Infallible),
}

#[cfg(feature = "rpi")]
pub mod pi_peripherals;

/// Abstraction over the hardware of the device. This is still TODO because I don't exactly know
/// how we want to do this. My main idea is we can have an enum for Input/Output, and from there
/// some sort of method for reading or writing. The a body would only be a Vec<Peripheral> but we
Expand Down Expand Up @@ -55,9 +82,9 @@ impl Body {
/// An arbitrary peripheral that is either an input or output
pub enum Peripheral {
/// Input peripheral
Input(Box<dyn Input<Error = Box<dyn Error>>>),
Input(Box<dyn Input<Error = PeripheralError>>),
/// Output peripheral
Output(Box<dyn Output<Error = Box<dyn Error>>>),
Output(Box<dyn Output<Error = PeripheralError>>),
}

impl Peripheral {
Expand Down
10 changes: 5 additions & 5 deletions achiever/src/body/inputs/rpi_inputs.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
//! Input Implementations for Raspberry Pi Peripherals

use std::convert::Infallible;

use rppal::{gpio::InputPin, i2c::I2c, spi::Spi, uart::Uart};

use crate::body::PeripheralError;

use super::Input;

impl Input for InputPin {
type Error = Infallible;
type Error = PeripheralError;
fn read_input(&mut self, buffer: &mut [u8]) -> Result<(), Self::Error> {
for loc in buffer {
*loc = self.read() as u8
Expand All @@ -17,15 +17,15 @@ impl Input for InputPin {
}

impl Input for I2c {
type Error = rppal::i2c::Error;
type Error = PeripheralError;
fn read_input(&mut self, buf: &mut [u8]) -> Result<(), Self::Error> {
self.read(buf)?;
Ok(())
}
}

impl Input for Spi {
type Error = rppal::spi::Error;
type Error = PeripheralError;
fn read_input(&mut self, buf: &mut [u8]) -> Result<(), Self::Error> {
self.read(buf)?;
Ok(())
Expand Down
12 changes: 6 additions & 6 deletions achiever/src/body/outputs/rpi_outputs.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
//! Output Implementations for Raspberry Pi Output Peripherals

use std::convert::Infallible;

use rppal::{
gpio::{Level, OutputPin},
i2c::I2c,
spi::Spi,
uart::Uart,
};

use crate::body::PeripheralError;

use super::Output;

impl Output for OutputPin {
type Error = Infallible;
type Error = PeripheralError;
fn write(&mut self, bytes: &[u8]) -> Result<(), Self::Error> {
for byte in bytes {
let state = match byte {
Expand All @@ -26,23 +26,23 @@ impl Output for OutputPin {
}

impl Output for I2c {
type Error = rppal::i2c::Error;
type Error = PeripheralError;
fn write(&mut self, bytes: &[u8]) -> Result<(), Self::Error> {
self.write(bytes)?;
Ok(())
}
}

impl Output for Spi {
type Error = rppal::spi::Error;
type Error = PeripheralError;
fn write(&mut self, bytes: &[u8]) -> Result<(), Self::Error> {
self.write(bytes)?;
Ok(())
}
}

impl Output for Uart {
type Error = rppal::uart::Error;
type Error = PeripheralError;
fn write(&mut self, bytes: &[u8]) -> Result<(), Self::Error> {
self.write(bytes)?;
Ok(())
Expand Down
67 changes: 67 additions & 0 deletions achiever/src/body/pi_peripherals.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
//! Extensions of the Peripheral Enum to construct Raspberry Pi Peripherals

use rppal::{
gpio::Gpio,
i2c::I2c,
spi::{Bus, Mode, SlaveSelect, Spi},
};

use super::Peripheral;

impl Peripheral {
/// Creates a Peripheral Input Node for a Raspberry Pi GPIO pin
pub fn gpio_input(pin: u8) -> rppal::gpio::Result<Self> {
let gpio = Gpio::new()?;
let pin = gpio.get(pin)?.into_input();

Ok(Self::Input(Box::new(pin)))
}

/// Creates a Peripheral Output Node for a Raspberry Pi GPIO pin
pub fn gpio_output(pin: u8) -> rppal::gpio::Result<Self> {
let gpio = Gpio::new()?;
let pin = gpio.get(pin)?.into_output();

Ok(Self::Output(Box::new(pin)))
}

/// Creates a Peripheral Iput Node for a Raspberry Pi i2c channel
pub fn i2c_input(address: u16) -> rppal::i2c::Result<Self> {
let mut i2c = I2c::new()?;
i2c.set_slave_address(address)?;

Ok(Self::Input(Box::new(i2c)))
}

/// Creates a Peripheral Output Node for a Raspberry Pi i2c channel
pub fn i2c_output(address: u16) -> rppal::i2c::Result<Self> {
let mut i2c = I2c::new()?;
i2c.set_slave_address(address)?;

Ok(Self::Input(Box::new(i2c)))
}

/// Creates a Peripheral Input Node for a Raspberry Pi SPI Bus
pub fn spi_input(
bus: Bus,
slave_select: SlaveSelect,
clock_speed: u32,
mode: Mode,
) -> rppal::spi::Result<Self> {
let spi = Spi::new(bus, slave_select, clock_speed, mode)?;

Ok(Self::Input(Box::new(spi)))
}

/// Creates a Peripheral Output Node for a Raspberry Pi SPI Bus
pub fn spi_output(
bus: Bus,
slave_select: SlaveSelect,
clock_speed: u32,
mode: Mode,
) -> rppal::spi::Result<Self> {
let spi = Spi::new(bus, slave_select, clock_speed, mode)?;

Ok(Self::Output(Box::new(spi)))
}
}

0 comments on commit 51b560b

Please sign in to comment.