1 | use embedded_hal_02::blocking; |
2 | |
3 | /// Wrapper that implements async traits using blocking implementations. |
4 | /// |
5 | /// This allows driver writers to depend on the async traits while still supporting embedded-hal peripheral implementations. |
6 | /// |
7 | /// BlockingAsync will implement any async trait that maps to embedded-hal traits implemented for the wrapped driver. |
8 | /// |
9 | /// Driver users are then free to choose which implementation that is available to them. |
10 | pub struct BlockingAsync<T> { |
11 | wrapped: T, |
12 | } |
13 | |
14 | impl<T> BlockingAsync<T> { |
15 | /// Create a new instance of a wrapper for a given peripheral. |
16 | pub fn new(wrapped: T) -> Self { |
17 | Self { wrapped } |
18 | } |
19 | } |
20 | |
21 | // |
22 | // I2C implementations |
23 | // |
24 | impl<T, E> embedded_hal_1::i2c::ErrorType for BlockingAsync<T> |
25 | where |
26 | E: embedded_hal_1::i2c::Error + 'static, |
27 | T: blocking::i2c::WriteRead<Error = E> + blocking::i2c::Read<Error = E> + blocking::i2c::Write<Error = E>, |
28 | { |
29 | type Error = E; |
30 | } |
31 | |
32 | impl<T, E> embedded_hal_async::i2c::I2c for BlockingAsync<T> |
33 | where |
34 | E: embedded_hal_1::i2c::Error + 'static, |
35 | T: blocking::i2c::WriteRead<Error = E> + blocking::i2c::Read<Error = E> + blocking::i2c::Write<Error = E>, |
36 | { |
37 | async fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> { |
38 | self.wrapped.read(address, buffer:read) |
39 | } |
40 | |
41 | async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Self::Error> { |
42 | self.wrapped.write(address, bytes:write) |
43 | } |
44 | |
45 | async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> { |
46 | self.wrapped.write_read(address, bytes:write, buffer:read) |
47 | } |
48 | |
49 | async fn transaction( |
50 | &mut self, |
51 | address: u8, |
52 | operations: &mut [embedded_hal_1::i2c::Operation<'_>], |
53 | ) -> Result<(), Self::Error> { |
54 | let _ = address; |
55 | let _ = operations; |
56 | todo!() |
57 | } |
58 | } |
59 | |
60 | // |
61 | // SPI implementatinos |
62 | // |
63 | |
64 | impl<T, E> embedded_hal_async::spi::ErrorType for BlockingAsync<T> |
65 | where |
66 | E: embedded_hal_1::spi::Error, |
67 | T: blocking::spi::Transfer<u8, Error = E> + blocking::spi::Write<u8, Error = E>, |
68 | { |
69 | type Error = E; |
70 | } |
71 | |
72 | impl<T, E> embedded_hal_async::spi::SpiBus<u8> for BlockingAsync<T> |
73 | where |
74 | E: embedded_hal_1::spi::Error + 'static, |
75 | T: blocking::spi::Transfer<u8, Error = E> + blocking::spi::Write<u8, Error = E>, |
76 | { |
77 | async fn flush(&mut self) -> Result<(), Self::Error> { |
78 | Ok(()) |
79 | } |
80 | |
81 | async fn write(&mut self, data: &[u8]) -> Result<(), Self::Error> { |
82 | self.wrapped.write(data)?; |
83 | Ok(()) |
84 | } |
85 | |
86 | async fn read(&mut self, data: &mut [u8]) -> Result<(), Self::Error> { |
87 | self.wrapped.transfer(data)?; |
88 | Ok(()) |
89 | } |
90 | |
91 | async fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> { |
92 | // Ensure we write the expected bytes |
93 | for i in 0..core::cmp::min(read.len(), write.len()) { |
94 | read[i] = write[i].clone(); |
95 | } |
96 | self.wrapped.transfer(read)?; |
97 | Ok(()) |
98 | } |
99 | |
100 | async fn transfer_in_place(&mut self, data: &mut [u8]) -> Result<(), Self::Error> { |
101 | self.wrapped.transfer(data)?; |
102 | Ok(()) |
103 | } |
104 | } |
105 | |
106 | /// NOR flash wrapper |
107 | use embedded_storage::nor_flash::{ErrorType, MultiwriteNorFlash, NorFlash, ReadNorFlash}; |
108 | use embedded_storage_async::nor_flash::{ |
109 | MultiwriteNorFlash as AsyncMultiwriteNorFlash, NorFlash as AsyncNorFlash, ReadNorFlash as AsyncReadNorFlash, |
110 | }; |
111 | |
112 | impl<T> ErrorType for BlockingAsync<T> |
113 | where |
114 | T: ErrorType, |
115 | { |
116 | type Error = T::Error; |
117 | } |
118 | |
119 | impl<T> AsyncNorFlash for BlockingAsync<T> |
120 | where |
121 | T: NorFlash, |
122 | { |
123 | const WRITE_SIZE: usize = <T as NorFlash>::WRITE_SIZE; |
124 | const ERASE_SIZE: usize = <T as NorFlash>::ERASE_SIZE; |
125 | |
126 | async fn write(&mut self, offset: u32, data: &[u8]) -> Result<(), Self::Error> { |
127 | self.wrapped.write(offset, bytes:data) |
128 | } |
129 | |
130 | async fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> { |
131 | self.wrapped.erase(from, to) |
132 | } |
133 | } |
134 | |
135 | impl<T> AsyncReadNorFlash for BlockingAsync<T> |
136 | where |
137 | T: ReadNorFlash, |
138 | { |
139 | const READ_SIZE: usize = <T as ReadNorFlash>::READ_SIZE; |
140 | async fn read(&mut self, address: u32, data: &mut [u8]) -> Result<(), Self::Error> { |
141 | self.wrapped.read(offset:address, bytes:data) |
142 | } |
143 | |
144 | fn capacity(&self) -> usize { |
145 | self.wrapped.capacity() |
146 | } |
147 | } |
148 | |
149 | impl<T> AsyncMultiwriteNorFlash for BlockingAsync<T> where T: MultiwriteNorFlash {} |
150 | |