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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
//! [![crates.io](https://img.shields.io/crates/v/device-register)](https://crates.io/crates/device-register) [![documentation](https://docs.rs/device-register/badge.svg)](https://docs.rs/device-register)
//!
//! A `no_std`, zero cost toolkit to describe the registers of a device to ease driver development.
//! * `no_std` support
//! * Zero cost, no use of dyn
//! * No dsl, just a derive macro and impl a trait.
//! * Error passthrough
//!
//! ## Usage
//! Simply derive using `XXRegister`, where XX is the premission.
//! The following permissions are supported
//! * [`RORegister`](crate::RORegister), read only permission
//! * [`WORegister`](crate::WORegister), write only permission
//! * [`EORegister`](crate::EORegister), edit only permission, when a register need to be read-modify-write
//! * [`RERegister`](crate::RERegister), Read and edit permission
//! * [`RWRegister`](crate::RWRegister), Read, write and edit permission.
//!
//! To define a register, simply derive using the desired permission.
//!
//! Then use the `register` attribute to define it's address, type for the address and the error.
//!
//!
//! ```rust
//! # use device_register::*;
//! # pub type DeviceError = ();
//!
//! #[derive(RWRegister)]
//! #[register( addr = "42", ty = "u8")]
//! pub struct Register0(pub u16);
//! ```
//! Then, your driver only need to implement the [RegisterInterface](crate::RegisterInterface) to have access to the read/write/edit traits.
//!
//! ### Complete example
//! Here is a complete example.
//! See the `tests` folder for more, or checkout the [tmp117](https://github.com/xgroleau/tmp117-rs) driver for actual usage.
//!
//! ```rust
//! use std::collections::HashMap;
//! use device_register::*;
//!
//! // The type of the address used by the driver
//! struct Address(pub u8);
//!
//! // We define the register with Read/Write permission
//! // Then we pass the address type, value and error type of the driveer
//! #[derive(Debug, Copy, PartialEq, Eq, Clone, RWRegister)]
//! #[register( addr = "Address(1)", ty = "Address")]
//! struct Register0(pub u16);
//! # impl From<Register0> for u16 {
//! #     fn from(val: Register0) -> Self {
//! #        val.0
//! #     }
//! # }
//! # impl From<u16> for Register0 {
//! #     fn from(val: u16) -> Self {
//! #         Register0(val)
//! #     }
//! # }
//!
//! // Mock of the device driver
//! struct DeviceDriver {
//!     // Simulate reading from the device
//!     pub registers: HashMap<u8, u16>,
//! }
//!
//! // Implement a method directly, by passing the trait for specific usecases like async
//! impl DeviceDriver {
//!     pub async fn read_async<R>(&self) -> R
//!     where
//!         R: ReadableRegister<Address = Address> + From<u16>,
//!     {
//!         async {
//!             let bytes = self.registers.get(&R::ADDRESS.0).unwrap();
//!             bytes.clone().into()
//!         }.await
//!     }
//! }
//!
//!
//! // We implement the required interface
//! impl<R> RegisterInterface<R, Address> for DeviceDriver
//! where
//!     R: Register<Address = Address> + Clone + From<u16>,
//!     u16: From<R>,
//! {
//!     // The type of the error, lets have none for now,
//!     type Error = ();
//!
//!     fn read_register(&mut self) -> Result<R, Self::Error> {
//!         let bytes = self.registers.get(&R::ADDRESS.0).unwrap();
//!         Ok(bytes.clone().into())
//!     }
//!
//!     fn write_register(&mut self, register: &R) -> Result<(), Self::Error> {
//!         self.registers.insert(R::ADDRESS.0, register.clone().into());
//!         Ok(())
//!     }
//! }
//!
//! let mut device = DeviceDriver{
//!     registers:  HashMap::new(),
//! };
//! // We can the Read/Write/Edit the registers that uses the Address and DeviceError types.
//! let write = Register0(42);
//! device.write(write).unwrap();
//!
//! let read: Register0 = device.read().unwrap();
//!
//! assert_eq!(read, write);
//!
//! device.edit(|r: &mut Register0| {
//!     r.0 = 43;
//!     r
//! }).unwrap();
//!
//!
//! let read: Register0 = device.read().unwrap();
//! assert_eq!(read, Register0(43));
//!
//! // Custom implementation, async is an example of usecase for custom implements
//! tokio_test::block_on( async {
//!     let read_async: Register0 = device.read_async().await;
//!     assert_eq!(read, Register0(43));
//! } );
//!
//! ```
//!
//!
//! ## License
//! Licensed under either of
//! - Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or
//!   <http://www.apache.org/licenses/LICENSE-2.0>)
//!
//! - MIT license ([LICENSE-MIT](LICENSE-MIT) or <http://opensource.org/licenses/MIT>)
//!
//! at your option.
//!
//! ## Contribution
//! Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
//!
#![no_std]
#![deny(unsafe_code, missing_docs)]

pub use device_register_macro::*;

/// Trait of a register containing an address
pub trait Register {
    /// Type of the adress, can be used to constrain the registers accepted
    type Address;

    /// The address of the register
    const ADDRESS: Self::Address;
}

/// Trait of a read only  register
pub trait ReadableRegister: Register {}

/// Trait of a register that can only be edited.
/// Some registers require a read-edit-write operation since some bits a reserved internally
/// Editing a register allows to "safely" modify only a subset of values
pub trait EditableRegister: Register {}

/// Trait a writable register, like a register but can be written to
pub trait WritableRegister: Register {}

/// Traits that define how to read and write the registers.
/// Note that those functions should mostly just be implemented and not used since they are not bound by Read/Write/Edit permission.
pub trait RegisterInterface<R, A>
where
    R: Register<Address = A>,
{
    /// Error type returned by the interface
    type Error;

    /// Reads a register and returns it
    fn read_register(&mut self) -> Result<R, Self::Error>;

    /// Writes a register to the device
    fn write_register(&mut self, register: &R) -> Result<(), Self::Error>;
}

/// Trait to safely read a register. Only a readable register can be read.
pub trait ReadRegister<R, A>
where
    R: ReadableRegister<Address = A>,
{
    /// Error type returned by reading the register
    type Error;

    /// Read a register
    fn read(&mut self) -> Result<R, Self::Error>;
}

/// Trait to safely write a register. Only a writable register can be written to.
pub trait WriteRegister<R, A>
where
    R: WritableRegister<Address = A>,
{
    /// Error type returned by writing the register
    type Error;

    /// Write a register
    fn write(&mut self, register: R) -> Result<(), Self::Error>;
}

/// Trait to safely read-edit-write a register.
/// Usefull when a register has reserved values for internal uses.
/// Avoids writing garbage to the reserved  bits.
pub trait EditRegister<R, A>
where
    R: EditableRegister<Address = A>,
{
    /// Error type returned by editing the register
    type Error;

    /// Edit a register. The closure takes a reference to the register,
    /// the same register must be edited, then returned.
    fn edit<F>(&mut self, f: F) -> Result<(), Self::Error>
    where
        for<'w> F: FnOnce(&'w mut R) -> &'w mut R;
}

impl<I, R, A> ReadRegister<R, A> for I
where
    R: ReadableRegister<Address = A>,
    I: RegisterInterface<R, A>,
{
    type Error = I::Error;

    fn read(&mut self) -> Result<R, Self::Error> {
        self.read_register()
    }
}

impl<I, R, A> WriteRegister<R, A> for I
where
    R: WritableRegister<Address = A>,
    I: RegisterInterface<R, A>,
{
    type Error = I::Error;

    fn write(&mut self, register: R) -> Result<(), Self::Error> {
        self.write_register(&register)
    }
}

impl<I, R, A> EditRegister<R, A> for I
where
    R: EditableRegister<Address = A>,
    I: RegisterInterface<R, A>,
{
    type Error = I::Error;

    fn edit<F>(&mut self, f: F) -> Result<(), Self::Error>
    where
        for<'w> F: FnOnce(&'w mut R) -> &'w mut R,
    {
        let mut val = self.read_register()?;
        let val = f(&mut val);
        self.write_register(val)
    }
}