1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
//! ## Overview
//!
//! This crate provides a handful of utility types for writing abstractions for interfacing with
//! register based devices. Most commonly, this would be utilized when writing drivers for
//! external peripherals within an embedded environment. As such, some utility functions
//! are provided for reading and writing registers on devices across I2C or SPI buses.
//!
//! This crate provides two core traits:
//! - [`Register`] for types that represent a value stored within an addressable register
//! - [`Command`] for types that represent an invokable command with parameters and response
//!
//! ### Readable Registers
//!
//! A register in which values can be retrieved from, or read from, is represented as any type that
//! implements the [`ReadableRegister`] trait. This trait is very little more than just a marker trait,
//! but it represents a type that is both a [`Register`] and that can be created from a byte array through
//! the [`FromByteArray`] trait. The bulk of the work in writing a type that can be read from a register
//! will be in implementing the [`FromByteArray`] trait.
//!
//! A type that implements the [`ReadableRegister`] trait can then be used with provided utility methods
//! such as those provided by the [`i2c`] or [`spi`] modules.
//!
//! #### Register Implementation Example
//!
//! ```
//! use regiface::{register, ReadableRegister, FromByteArray};
//!
//! #[register(42u8)]
//! #[derive(ReadableRegister, Debug)]
//! pub struct MyRegister {
//! value: u8
//! }
//!
//! impl FromByteArray for MyRegister {
//! type Error = core::convert::Infallible;
//! type Array = [u8; 1];
//!
//! fn from_bytes(bytes: Self::Array) -> Result<Self, Self::Error> {
//! Ok(Self {
//! value: bytes[0]
//! })
//! }
//! }
//! ```
//!
//! ### Writable Registers
//!
//! A register in which values can be written to is represented as any type that
//! implements the [`WritableRegister`] trait. This trait is very little more than just a marker trait,
//! but it represents a type that is both a [`Register`] and that can be serialized into a byte array through
//! the [`ToByteArray`] trait. The bulk of the work in writing a type that can be written to a register
//! will be in implementing the [`ToByteArray`] trait.
//!
//! A type that implements the [`WritableRegister`] trait can then be used with provided utility methods
//! such as those provided by the [`i2c`] or [`spi`] modules.
//!
//! #### Register Implementation Example
//!
//! ```
//! use regiface::{register, WritableRegister, ToByteArray};
//!
//! #[register(42u8)]
//! #[derive(WritableRegister, Debug)]
//! pub struct MyRegister {
//! value: u8
//! }
//!
//! impl ToByteArray for MyRegister {
//! type Error = core::convert::Infallible;
//! type Array = [u8; 1];
//!
//! fn to_bytes(self) -> Result<Self::Array, Self::Error> {
//! Ok([self.value])
//! }
//! }
//! ```
//!
//! ### Commands
//!
//! A command represents an invokable action with optional parameters and response. Commands are
//! implemented using the [`Command`] trait, which specifies both the command parameters and expected
//! response type. For commands or responses without parameters, the [`NoParameters`] type can be used.
//!
//! #### Command Implementation Example
//!
//! ```rust
//! use regiface::{Command, ToByteArray, FromByteArray, NoParameters};
//!
//! struct GetTemperature;
//!
//! impl Command for GetTemperature {
//! type IdType = u8;
//! type CommandParameters = NoParameters;
//! type ResponseParameters = Temperature;
//!
//! fn id() -> Self::IdType {
//! 0x42
//! }
//!
//! fn invoking_parameters(self) -> Self::CommandParameters {
//! NoParameters::default()
//! }
//! }
//!
//! struct Temperature {
//! celsius: f32
//! }
//!
//! impl FromByteArray for Temperature {
//! type Error = core::convert::Infallible;
//! type Array = [u8; 4];
//!
//! fn from_bytes(bytes: Self::Array) -> Result<Self, Self::Error> {
//! let celsius = f32::from_be_bytes(bytes);
//! Ok(Self { celsius })
//! }
//! }
//! ```
pub use *;
pub use *;
pub use *;
pub use *;