| 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 | |