diff options
| author | xoviat <[email protected]> | 2021-03-05 21:19:56 -0600 |
|---|---|---|
| committer | xoviat <[email protected]> | 2021-03-05 21:19:56 -0600 |
| commit | 7a46e66298437d412eef0899ae82ab51b78cda88 (patch) | |
| tree | 0a22512cc759a73bb65ec58c795b348f1f2bd957 | |
| parent | a3a36517bd8beae30b4d9ca23b3da8db1a14de12 (diff) | |
revise i2c trait
| -rw-r--r-- | embassy-traits/src/i2c.rs | 248 |
1 files changed, 1 insertions, 247 deletions
diff --git a/embassy-traits/src/i2c.rs b/embassy-traits/src/i2c.rs index 02755b571..f9f462b50 100644 --- a/embassy-traits/src/i2c.rs +++ b/embassy-traits/src/i2c.rs | |||
| @@ -97,6 +97,7 @@ pub trait Read<A: AddressMode = SevenBitAddress> { | |||
| 97 | type Error; | 97 | type Error; |
| 98 | 98 | ||
| 99 | type ReadFuture<'a>: Future<Output = Result<(), Self::Error>> + 'a; | 99 | type ReadFuture<'a>: Future<Output = Result<(), Self::Error>> + 'a; |
| 100 | type WriteFuture<'a>: Future<Output = Result<(), Self::Error>> + 'a; | ||
| 100 | 101 | ||
| 101 | /// Reads enough bytes from slave with `address` to fill `buffer` | 102 | /// Reads enough bytes from slave with `address` to fill `buffer` |
| 102 | /// | 103 | /// |
| @@ -117,14 +118,6 @@ pub trait Read<A: AddressMode = SevenBitAddress> { | |||
| 117 | /// - `NMAK` = master no acknowledge | 118 | /// - `NMAK` = master no acknowledge |
| 118 | /// - `SP` = stop condition | 119 | /// - `SP` = stop condition |
| 119 | fn read<'a>(self: Pin<&'a mut Self>, address: A, buffer: &mut [u8]) -> Self::ReadFuture<'a>; | 120 | fn read<'a>(self: Pin<&'a mut Self>, address: A, buffer: &mut [u8]) -> Self::ReadFuture<'a>; |
| 120 | } | ||
| 121 | |||
| 122 | /// Blocking write | ||
| 123 | pub trait Write<A: AddressMode = SevenBitAddress> { | ||
| 124 | /// Error type | ||
| 125 | type Error; | ||
| 126 | |||
| 127 | type WriteFuture<'a>: Future<Output = Result<(), Self::Error>> + 'a; | ||
| 128 | 121 | ||
| 129 | /// Sends bytes to slave with address `address` | 122 | /// Sends bytes to slave with address `address` |
| 130 | /// | 123 | /// |
| @@ -144,242 +137,3 @@ pub trait Write<A: AddressMode = SevenBitAddress> { | |||
| 144 | /// - `SP` = stop condition | 137 | /// - `SP` = stop condition |
| 145 | fn write<'a>(self: Pin<&'a mut Self>, address: A, bytes: &[u8]) -> Self::WriteFuture<'a>; | 138 | fn write<'a>(self: Pin<&'a mut Self>, address: A, bytes: &[u8]) -> Self::WriteFuture<'a>; |
| 146 | } | 139 | } |
| 147 | |||
| 148 | /// Blocking write (iterator version) | ||
| 149 | pub trait WriteIter<A: AddressMode = SevenBitAddress> { | ||
| 150 | /// Error type | ||
| 151 | type Error; | ||
| 152 | |||
| 153 | type WriteIterFuture<'a>: Future<Output = Result<(), Self::Error>> + 'a; | ||
| 154 | |||
| 155 | /// Sends bytes to slave with address `address` | ||
| 156 | /// | ||
| 157 | /// # I2C Events (contract) | ||
| 158 | /// | ||
| 159 | /// Same as `Write` | ||
| 160 | fn write_iter<'a, B>( | ||
| 161 | self: Pin<&'a mut Self>, | ||
| 162 | address: A, | ||
| 163 | bytes: B, | ||
| 164 | ) -> Self::WriteIterFuture<'a> | ||
| 165 | where | ||
| 166 | B: IntoIterator<Item = u8>; | ||
| 167 | } | ||
| 168 | |||
| 169 | /// Blocking write + read | ||
| 170 | pub trait WriteRead<A: AddressMode = SevenBitAddress> { | ||
| 171 | /// Error type | ||
| 172 | type Error; | ||
| 173 | |||
| 174 | type WriteReadFuture<'a>: Future<Output = Result<(), Self::Error>> + 'a; | ||
| 175 | |||
| 176 | /// Sends bytes to slave with address `address` and then reads enough bytes to fill `buffer` *in a | ||
| 177 | /// single transaction* | ||
| 178 | /// | ||
| 179 | /// # I2C Events (contract) | ||
| 180 | /// | ||
| 181 | /// ``` text | ||
| 182 | /// Master: ST SAD+W O0 O1 ... OM SR SAD+R MAK MAK ... NMAK SP | ||
| 183 | /// Slave: SAK SAK SAK ... SAK SAK I0 I1 ... IN | ||
| 184 | /// ``` | ||
| 185 | /// | ||
| 186 | /// Where | ||
| 187 | /// | ||
| 188 | /// - `ST` = start condition | ||
| 189 | /// - `SAD+W` = slave address followed by bit 0 to indicate writing | ||
| 190 | /// - `SAK` = slave acknowledge | ||
| 191 | /// - `Oi` = ith outgoing byte of data | ||
| 192 | /// - `SR` = repeated start condition | ||
| 193 | /// - `SAD+R` = slave address followed by bit 1 to indicate reading | ||
| 194 | /// - `Ii` = ith incoming byte of data | ||
| 195 | /// - `MAK` = master acknowledge | ||
| 196 | /// - `NMAK` = master no acknowledge | ||
| 197 | /// - `SP` = stop condition | ||
| 198 | fn write_read<'a>( | ||
| 199 | self: Pin<&'a mut Self>, | ||
| 200 | address: A, | ||
| 201 | bytes: &[u8], | ||
| 202 | buffer: &mut [u8], | ||
| 203 | ) -> Self::WriteReadFuture<'a>; | ||
| 204 | } | ||
| 205 | |||
| 206 | /// Blocking write (iterator version) + read | ||
| 207 | pub trait WriteIterRead<A: AddressMode = SevenBitAddress> { | ||
| 208 | /// Error type | ||
| 209 | type Error; | ||
| 210 | |||
| 211 | type WriteIterReadFuture<'a>: Future<Output = Result<(), Self::Error>> + 'a; | ||
| 212 | |||
| 213 | /// Sends bytes to slave with address `address` and then reads enough bytes to fill `buffer` *in a | ||
| 214 | /// single transaction* | ||
| 215 | /// | ||
| 216 | /// # I2C Events (contract) | ||
| 217 | /// | ||
| 218 | /// Same as the `WriteRead` trait | ||
| 219 | fn write_iter_read<'a, B>( | ||
| 220 | self: Pin<&'a mut Self>, | ||
| 221 | address: A, | ||
| 222 | bytes: B, | ||
| 223 | buffer: &mut [u8], | ||
| 224 | ) -> Self::WriteIterReadFuture<'a> | ||
| 225 | where | ||
| 226 | B: IntoIterator<Item = u8>; | ||
| 227 | } | ||
| 228 | |||
| 229 | /// Transactional I2C operation. | ||
| 230 | /// | ||
| 231 | /// Several operations can be combined as part of a transaction. | ||
| 232 | #[derive(Debug, PartialEq)] | ||
| 233 | pub enum Operation<'a> { | ||
| 234 | /// Read data into the provided buffer | ||
| 235 | Read(&'a mut [u8]), | ||
| 236 | /// Write data from the provided buffer | ||
| 237 | Write(&'a [u8]), | ||
| 238 | } | ||
| 239 | |||
| 240 | /// Transactional I2C interface. | ||
| 241 | /// | ||
| 242 | /// This allows combining operations within an I2C transaction. | ||
| 243 | pub trait Transactional<A: AddressMode = SevenBitAddress> { | ||
| 244 | /// Error type | ||
| 245 | type Error; | ||
| 246 | |||
| 247 | type TransactionalFuture<'a>: Future<Output = Result<(), Self::Error>> + 'a; | ||
| 248 | |||
| 249 | /// Execute the provided operations on the I2C bus. | ||
| 250 | /// | ||
| 251 | /// Transaction contract: | ||
| 252 | /// - Before executing the first operation an ST is sent automatically. This is followed by SAD+R/W as appropriate. | ||
| 253 | /// - Data from adjacent operations of the same type are sent after each other without an SP or SR. | ||
| 254 | /// - Between adjacent operations of a different type an SR and SAD+R/W is sent. | ||
| 255 | /// - After executing the last operation an SP is sent automatically. | ||
| 256 | /// - If the last operation is a `Read` the master does not send an acknowledge for the last byte. | ||
| 257 | /// | ||
| 258 | /// - `ST` = start condition | ||
| 259 | /// - `SAD+R/W` = slave address followed by bit 1 to indicate reading or 0 to indicate writing | ||
| 260 | /// - `SR` = repeated start condition | ||
| 261 | /// - `SP` = stop condition | ||
| 262 | fn exec<'a>( | ||
| 263 | &mut self, | ||
| 264 | address: A, | ||
| 265 | operations: &mut [Operation<'a>], | ||
| 266 | ) -> Self::TransactionalFuture<'a>; | ||
| 267 | } | ||
| 268 | |||
| 269 | /// Transactional I2C interface (iterator version). | ||
| 270 | /// | ||
| 271 | /// This allows combining operation within an I2C transaction. | ||
| 272 | pub trait TransactionalIter<A: AddressMode = SevenBitAddress> { | ||
| 273 | /// Error type | ||
| 274 | type Error; | ||
| 275 | |||
| 276 | type TransactionalIterFuture<'a>: Future<Output = Result<(), Self::Error>> + 'a; | ||
| 277 | |||
| 278 | /// Execute the provided operations on the I2C bus (iterator version). | ||
| 279 | /// | ||
| 280 | /// Transaction contract: | ||
| 281 | /// - Before executing the first operation an ST is sent automatically. This is followed by SAD+R/W as appropriate. | ||
| 282 | /// - Data from adjacent operations of the same type are sent after each other without an SP or SR. | ||
| 283 | /// - Between adjacent operations of a different type an SR and SAD+R/W is sent. | ||
| 284 | /// - After executing the last operation an SP is sent automatically. | ||
| 285 | /// - If the last operation is a `Read` the master does not send an acknowledge for the last byte. | ||
| 286 | /// | ||
| 287 | /// - `ST` = start condition | ||
| 288 | /// - `SAD+R/W` = slave address followed by bit 1 to indicate reading or 0 to indicate writing | ||
| 289 | /// - `SR` = repeated start condition | ||
| 290 | /// - `SP` = stop condition | ||
| 291 | fn exec_iter<'a, O>(&mut self, address: A, operations: O) -> Self::TransactionalIterFuture<'a> | ||
| 292 | where | ||
| 293 | O: IntoIterator<Item = Operation<'a>>; | ||
| 294 | } | ||
| 295 | |||
| 296 | /// Default implementation of `blocking::i2c::Write`, `blocking::i2c::Read` and | ||
| 297 | /// `blocking::i2c::WriteRead` traits for `blocking::i2c::Transactional` implementers. | ||
| 298 | /// | ||
| 299 | /// If you implement `blocking::i2c::Transactional` for your I2C peripheral, | ||
| 300 | /// you can use this default implementation so that you do not need to implement | ||
| 301 | /// the `blocking::i2c::Write`, `blocking::i2c::Read` and `blocking::i2c::WriteRead` | ||
| 302 | /// traits as well. | ||
| 303 | /// ``` | ||
| 304 | /// use embedded_hal::blocking::i2c; | ||
| 305 | /// | ||
| 306 | /// struct I2c1; | ||
| 307 | /// | ||
| 308 | /// impl i2c::Transactional<i2c::SevenBitAddress> for I2c1 { | ||
| 309 | /// # type Error = (); | ||
| 310 | /// fn try_exec<'a>( | ||
| 311 | /// &mut self, | ||
| 312 | /// address: i2c::SevenBitAddress, | ||
| 313 | /// operations: &mut [i2c::Operation<'a>], | ||
| 314 | /// ) -> Result<(), Self::Error> { | ||
| 315 | /// // ... | ||
| 316 | /// # Ok(()) | ||
| 317 | /// } | ||
| 318 | /// } | ||
| 319 | /// | ||
| 320 | /// // This is all you need to do: | ||
| 321 | /// impl i2c::transactional::Default<i2c::SevenBitAddress> for I2c1 {}; | ||
| 322 | /// | ||
| 323 | /// // Then you can use `Write` and so on: | ||
| 324 | /// use i2c::Write; | ||
| 325 | /// | ||
| 326 | /// let mut i2c1 = I2c1{}; | ||
| 327 | /// i2c1.try_write(0x01, &[0xAB, 0xCD]).unwrap(); | ||
| 328 | /// ``` | ||
| 329 | pub mod transactional { | ||
| 330 | use core::future::Future; | ||
| 331 | |||
| 332 | use super::{AddressMode, Operation, Read, Transactional, Write, WriteRead}; | ||
| 333 | |||
| 334 | /// Default implementation of `blocking::i2c::Write`, `blocking::i2c::Read` and | ||
| 335 | /// `blocking::i2c::WriteRead` traits for `blocking::i2c::Transactional` implementers. | ||
| 336 | pub trait Default<A: AddressMode>: Transactional<A> {} | ||
| 337 | |||
| 338 | // impl<A, E, S> Write<A> for S | ||
| 339 | // where | ||
| 340 | // A: AddressMode + 'static, | ||
| 341 | // S: self::Default<A> + Transactional<A, Error = E> + 'static, | ||
| 342 | // E: 'static, | ||
| 343 | // { | ||
| 344 | // type Error = E; | ||
| 345 | // | ||
| 346 | // type WriteFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a; | ||
| 347 | // | ||
| 348 | // fn write<'a>(&mut self, address: A, bytes: &[u8]) -> Self::WriteFuture<'a> { | ||
| 349 | // self.exec(address, &mut [Operation::Write(bytes)]) | ||
| 350 | // } | ||
| 351 | // } | ||
| 352 | /* | ||
| 353 | impl<A, E, S> Read<A> for S | ||
| 354 | where | ||
| 355 | A: AddressMode, | ||
| 356 | S: self::Default<A> + Transactional<A, Error = E>, | ||
| 357 | { | ||
| 358 | type Error = E; | ||
| 359 | |||
| 360 | fn read(&mut self, address: A, buffer: &mut [u8]) -> Result<(), Self::Error> { | ||
| 361 | self.exec(address, &mut [Operation::Read(buffer)]) | ||
| 362 | } | ||
| 363 | } | ||
| 364 | |||
| 365 | impl<A, E, S> WriteRead<A> for S | ||
| 366 | where | ||
| 367 | A: AddressMode, | ||
| 368 | S: self::Default<A> + Transactional<A, Error = E>, | ||
| 369 | { | ||
| 370 | type Error = E; | ||
| 371 | |||
| 372 | fn write_read( | ||
| 373 | &mut self, | ||
| 374 | address: A, | ||
| 375 | bytes: &[u8], | ||
| 376 | buffer: &mut [u8], | ||
| 377 | ) -> Result<(), Self::Error> { | ||
| 378 | self.exec( | ||
| 379 | address, | ||
| 380 | &mut [Operation::Write(bytes), Operation::Read(buffer)], | ||
| 381 | ) | ||
| 382 | } | ||
| 383 | } | ||
| 384 | */ | ||
| 385 | } | ||
