bit_byte_structs/
lib.rs

1#![no_std]
2
3//! # Bit Byte Structs
4//!
5//! ## Bus Agnostic code for Register Bank style chips
6//!
7//! Many peripheral IC chips are configured by a bank of registers.
8//! Setting these registers so the chip performs as expected
9//! can take up a lot of effort and code. This library implements the
10//! required boiler plate so device specific libs don't need to.
11//!
12//! ## About this crate
13//!
14//! This create provides a convent interface trait with implementations for I2C and SPI.
15//! It then implements a set of basic structures representing numbers made up of sub, hole or multiple bytes,
16//! using this trait.
17//!
18//! There is no reason this could not be implemented for other buses. The current implementations are based around
19//! the [embedded hal traits](https://github.com/rust-embedded/embedded-hal)
20//!
21//! The provided structures are there to make it quick and easy to create drivers for peripheral chips
22//! rather than to help optimise drivers for some aspect of performance.
23//!
24//! The lib is loosely inspired by [Adafruits BusIO](https://github.com/adafruit/Adafruit_BusIO) but dose not share any IP or code.
25//!
26//! Like other users of the above lib it is assumed that a driver author may use this lib to interact with basic configuration
27//! registers with this lib but may well implement there own functions for the performance critical or less standard registers.
28//!
29//! The lib has a few key goals:
30//!    * Make it easy to make drivers
31//!    * Not to take permanent ownership of the bus
32//!    * Not to make it easy for authors to pick and chose which registers they use this lib to interact with
33//!    * Minimize the boiler plate in down stream users of this struct.
34//!
35//! ## To use in a library
36//!
37//! This lib helps remove boiler plate for the libs that use
38//!
39//! These examples are illustrative only. We are working on getting working ones.
40//!   
41//! ``` compile_fail
42//! use core::marker::PhantomData;
43//! use bitbytestructs::bus::{Interface, InterfaceError};
44//! use bitbytestructs::registers::{BitStruct, BitByteStructError};
45//!
46//! pub struct PeripheralDevice<InterfaceThing: ?Sized, E> {
47//!    phantom: PhantomData<InterfaceThing>,
48//!    low_power_bit: BitStruct<dyn Interface<Error = InterfaceError<E>>>,
49//! }
50//!
51//! impl<I2C, E> PeripheralDevice<I2C, E>
52//! where
53//!     I2C: Read<Error = E> + Write<Error = E> + WriteRead<Error = E>,
54//! {
55//!     pub fn new() -> Result<Self, BitByteStructError<InterfaceError<E>>> {
56//!
57//!        let low_power_bit =
58//!            BitStruct::<dyn Interface<Error = InterfaceError<E>>>::new(0x23, 1, 5)?;
59//!
60//!
61//!         Ok(ICMCommon::<I, E> {
62//!             phantom: PhantomData,
63//!             low_power_bit,
64//!         })
65//!     }
66//!
67//!    /// Set low power mode
68//!    pub fn set_low_power(
69//!        &mut self,
70//!        i2c_bus: &mut I2C,
71//!    ) -> Result<(), BitByteStructError<InterfaceError<E>>> {
72//!         let mut interface = bus::SPIPeripheral::<I2C, E>::new(spi_bus, cs);
73//!         
74//!         if low_power {
75//!            self.low_power_bit.write(interface, 1)?;
76//!         } else {
77//!            self.low_power_bit.write(interface, 0)?;
78//!         }
79//!         Ok(())
80//!     }
81//! }
82//! ```
83//!
84//! The lib can be used to reduce boiler plate when writing libs for peripherals that
85//! use a single bus further more they can also be used to help with peripherals that also
86//! have spi and i2c.
87//!
88//!
89//! ## Use of libs that use this lib
90//!
91//! ``` compile_fail
92//! fn main() {
93//!     let spi_mode = Mode {
94//!         polarity: Polarity::IdleLow,
95//!         phase: Phase::CaptureOnFirstTransition,
96//!     };
97//!
98//!     let mut spi = Spi::spi2(dp.SPI2, pins, spi_mode, 500.khz(), clocks, &mut rcc.apb1);
99//!
100//!     let mut delay_obj = Delay::new(cp.SYST, clocks);
101//!     let mut peripheral_A = PeripheralDevice::new(&mut spi, cs_a).unwrap();
102//!     peripheral_A.init(&mut spi, &mut delay_obj).unwrap();
103//!
104//!     let mut peripheral_B = PeripheralDevice::new(&mut spi, cs_b).unwrap();
105//!     peripheral_B.init(&mut spi, &mut delay_obj).unwrap();
106//!
107//!     loop {
108//!         let results = peripheral_A.get_values_accel_gyro(&mut spi).unwrap();
109//!         let (xa, ya, za, xg, yg, zg) =
110//!             results;
111//!         hprintln!(
112//!             "results values from chip A {:?} {:?} {:?} {:?} {:?} {:?}",
113//!             xa,
114//!             ya,
115//!             za,
116//!             xg,
117//!             yg,
118//!             zg
119//!         )
120//!         .unwrap();
121//!         let results = peripheral_B.get_values_accel_gyro(&mut spi).unwrap();
122//!         let (xa, ya, za, xg, yg, zg) =
123//!             results;
124//!         hprintln!(
125//!             "results values from chip B{:?} {:?} {:?} {:?} {:?} {:?}",
126//!             xa,
127//!             ya,
128//!             za,
129//!             xg,
130//!             yg,
131//!             zg
132//!         )
133//!         .unwrap();
134//!         delay_obj.delay_ms(500 as u16);
135//!     }
136//! }
137//! ```
138//!
139//! By borrowing the bus per operation we use the type system to make sure that the bus is not
140//! accessed when being used by a different peripheral.
141//!
142//! The peripheral struct could have a functions that creates a sub struct that keeps the buss for a
143//! life time until ist time to give the bus back and let a different peripheral use it.
144
145pub mod bus;
146pub mod registers;