11use core:: ops:: Deref ;
22
33use crate :: gpio;
4- use crate :: i2c:: { Error , NoAcknowledgeSource } ;
4+ use crate :: i2c:: { Address , Error , Hal02Operation , Hal1Operation , NoAcknowledgeSource } ;
55use crate :: pac:: fmpi2c1 as i2c1;
66use crate :: pac:: { self , rcc, RCC } ;
77use crate :: rcc:: { BusClock , Clocks , Enable , Reset } ;
88use fugit:: { HertzU32 as Hertz , RateExtU32 } ;
99use micromath:: F32Ext ;
1010
11+ #[ path = "i2c/hal_02.rs" ]
1112mod hal_02;
13+ #[ path = "i2c/hal_1.rs" ]
1214mod hal_1;
1315
1416type I2cSel = rcc:: dckcfgr2:: FMPI2C1SEL ;
@@ -364,6 +366,7 @@ impl<I2C: Instance> I2c<I2C> {
364366 self . i2c . cr1 ( ) . modify ( |_, w| w. pe ( ) . set_bit ( ) ) ;
365367 }
366368
369+ #[ inline( always) ]
367370 fn check_and_clear_error_flags ( & self , isr : & i2c1:: isr:: R ) -> Result < ( ) , Error > {
368371 // If we received a NACK, then this is an error
369372 if isr. nackf ( ) . bit_is_set ( ) {
@@ -376,6 +379,7 @@ impl<I2C: Instance> I2c<I2C> {
376379 Ok ( ( ) )
377380 }
378381
382+ #[ inline( always) ]
379383 fn end_transaction ( & self ) -> Result < ( ) , Error > {
380384 // Check and clear flags if they somehow ended up set
381385 self . check_and_clear_error_flags ( & self . i2c . isr ( ) . read ( ) )
@@ -385,11 +389,20 @@ impl<I2C: Instance> I2c<I2C> {
385389
386390 /// Sends START and Address for writing
387391 #[ inline( always) ]
388- fn prepare_write ( & self , addr : u8 , datalen : u8 ) -> Result < ( ) , Error > {
392+ fn prepare_write ( & self , addr : Address , datalen : usize ) -> Result < ( ) , Error > {
389393 // Set up current slave address for writing and disable autoending
390394 self . i2c . cr2 ( ) . modify ( |_, w| {
391- w. sadd ( ) . set ( u16:: from ( addr) << 1 ) ;
392- w. nbytes ( ) . set ( datalen) ;
395+ match addr {
396+ Address :: Seven ( addr) => {
397+ w. add10 ( ) . clear_bit ( ) ;
398+ w. sadd ( ) . set ( u16:: from ( addr) << 1 ) ;
399+ }
400+ Address :: Ten ( addr) => {
401+ w. add10 ( ) . set_bit ( ) ;
402+ w. sadd ( ) . set ( addr) ;
403+ }
404+ }
405+ w. nbytes ( ) . set ( datalen as u8 ) ;
393406 w. rd_wrn ( ) . clear_bit ( ) ;
394407 w. autoend ( ) . clear_bit ( )
395408 } ) ;
@@ -409,11 +422,26 @@ impl<I2C: Instance> I2c<I2C> {
409422 }
410423
411424 /// Sends START and Address for reading
412- fn prepare_read ( & self , addr : u8 , buflen : u8 ) -> Result < ( ) , Error > {
425+ fn prepare_read (
426+ & self ,
427+ addr : Address ,
428+ buflen : usize ,
429+ first_transaction : bool ,
430+ ) -> Result < ( ) , Error > {
413431 // Set up current address for reading
414432 self . i2c . cr2 ( ) . modify ( |_, w| {
415- w. sadd ( ) . set ( u16:: from ( addr) << 1 ) ;
416- w. nbytes ( ) . set ( buflen) ;
433+ match addr {
434+ Address :: Seven ( addr) => {
435+ w. add10 ( ) . clear_bit ( ) ;
436+ w. sadd ( ) . set ( u16:: from ( addr) << 1 ) ;
437+ }
438+ Address :: Ten ( addr) => {
439+ w. add10 ( ) . set_bit ( ) ;
440+ w. head10r ( ) . bit ( !first_transaction) ;
441+ w. sadd ( ) . set ( addr) ;
442+ }
443+ }
444+ w. nbytes ( ) . set ( buflen as u8 ) ;
417445 w. rd_wrn ( ) . set_bit ( )
418446 } ) ;
419447
@@ -474,22 +502,28 @@ impl<I2C: Instance> I2c<I2C> {
474502 Ok ( ( ) )
475503 }
476504
477- pub fn read ( & mut self , addr : u8 , buffer : & mut [ u8 ] ) -> Result < ( ) , Error > {
478- self . prepare_read ( addr, buffer. len ( ) as u8 ) ?;
505+ pub fn read ( & mut self , addr : impl Into < Address > , buffer : & mut [ u8 ] ) -> Result < ( ) , Error > {
506+ self . prepare_read ( addr. into ( ) , buffer. len ( ) , true ) ?;
479507 self . read_bytes ( buffer) ?;
480508
481509 self . end_transaction ( )
482510 }
483511
484- pub fn write ( & mut self , addr : u8 , bytes : & [ u8 ] ) -> Result < ( ) , Error > {
485- self . prepare_write ( addr, bytes. len ( ) as u8 ) ?;
512+ pub fn write ( & mut self , addr : impl Into < Address > , bytes : & [ u8 ] ) -> Result < ( ) , Error > {
513+ self . prepare_write ( addr. into ( ) , bytes. len ( ) ) ?;
486514 self . write_bytes ( bytes. iter ( ) . cloned ( ) ) ?;
487515
488516 self . end_transaction ( )
489517 }
490518
491- pub fn write_read ( & mut self , addr : u8 , bytes : & [ u8 ] , buffer : & mut [ u8 ] ) -> Result < ( ) , Error > {
492- self . prepare_write ( addr, bytes. len ( ) as u8 ) ?;
519+ pub fn write_read (
520+ & mut self ,
521+ addr : impl Into < Address > ,
522+ bytes : & [ u8 ] ,
523+ buffer : & mut [ u8 ] ,
524+ ) -> Result < ( ) , Error > {
525+ let addr = addr. into ( ) ;
526+ self . prepare_write ( addr, bytes. len ( ) ) ?;
493527 self . write_bytes ( bytes. iter ( ) . cloned ( ) ) ?;
494528
495529 // Wait until data was sent
@@ -502,7 +536,120 @@ impl<I2C: Instance> I2c<I2C> {
502536
503537 self . read ( addr, buffer)
504538 }
539+
540+ pub fn transaction < ' a > (
541+ & mut self ,
542+ addr : impl Into < Address > ,
543+ mut ops : impl Iterator < Item = Hal1Operation < ' a > > ,
544+ ) -> Result < ( ) , Error > {
545+ let addr = addr. into ( ) ;
546+ if let Some ( mut prev_op) = ops. next ( ) {
547+ // 1. Generate Start for operation
548+ match & prev_op {
549+ Hal1Operation :: Read ( buf) => self . prepare_read ( addr, buf. len ( ) , true ) ?,
550+ Hal1Operation :: Write ( data) => self . prepare_write ( addr, data. len ( ) ) ?,
551+ } ;
552+
553+ for op in ops {
554+ // 2. Execute previous operations.
555+ match & mut prev_op {
556+ Hal1Operation :: Read ( rb) => self . read_bytes ( rb) ?,
557+ Hal1Operation :: Write ( wb) => self . write_bytes ( wb. iter ( ) . cloned ( ) ) ?,
558+ } ;
559+ // 3. If operation changes type we must generate new start
560+ match ( & prev_op, & op) {
561+ ( Hal1Operation :: Read ( _) , Hal1Operation :: Write ( data) ) => {
562+ self . prepare_write ( addr, data. len ( ) ) ?
563+ }
564+ ( Hal1Operation :: Write ( _) , Hal1Operation :: Read ( buf) ) => {
565+ self . prepare_read ( addr, buf. len ( ) , false ) ?
566+ }
567+ _ => { } // No changes if operation have not changed
568+ }
569+
570+ prev_op = op;
571+ }
572+
573+ // 4. Now, prev_op is last command use methods variations that will generate stop
574+ match prev_op {
575+ Hal1Operation :: Read ( rb) => self . read_bytes ( rb) ?,
576+ Hal1Operation :: Write ( wb) => self . write_bytes ( wb. iter ( ) . cloned ( ) ) ?,
577+ } ;
578+
579+ self . end_transaction ( ) ?;
580+ }
581+
582+ // Fallthrough is success
583+ Ok ( ( ) )
584+ }
585+
586+ pub fn transaction_slice (
587+ & mut self ,
588+ addr : impl Into < Address > ,
589+ ops_slice : & mut [ Hal1Operation < ' _ > ] ,
590+ ) -> Result < ( ) , Error > {
591+ let addr = addr. into ( ) ;
592+ transaction_impl ! ( self , addr, ops_slice, Hal1Operation ) ;
593+ // Fallthrough is success
594+ Ok ( ( ) )
595+ }
596+
597+ fn transaction_slice_hal_02 (
598+ & mut self ,
599+ addr : impl Into < Address > ,
600+ ops_slice : & mut [ Hal02Operation < ' _ > ] ,
601+ ) -> Result < ( ) , Error > {
602+ let addr = addr. into ( ) ;
603+ transaction_impl ! ( self , addr, ops_slice, Hal02Operation ) ;
604+ // Fallthrough is success
605+ Ok ( ( ) )
606+ }
607+ }
608+
609+ macro_rules! transaction_impl {
610+ ( $self: ident, $addr: ident, $ops_slice: ident, $Operation: ident) => {
611+ let i2c = $self;
612+ let addr = $addr;
613+ let mut ops = $ops_slice. iter_mut( ) ;
614+
615+ if let Some ( mut prev_op) = ops. next( ) {
616+ // 1. Generate Start for operation
617+ match & prev_op {
618+ $Operation:: Read ( buf) => i2c. prepare_read( addr, buf. len( ) , true ) ?,
619+ $Operation:: Write ( data) => i2c. prepare_write( addr, data. len( ) ) ?,
620+ } ;
621+
622+ for op in ops {
623+ // 2. Execute previous operations.
624+ match & mut prev_op {
625+ $Operation:: Read ( rb) => i2c. read_bytes( rb) ?,
626+ $Operation:: Write ( wb) => i2c. write_bytes( wb. iter( ) . cloned( ) ) ?,
627+ } ;
628+ // 3. If operation changes type we must generate new start
629+ match ( & prev_op, & op) {
630+ ( $Operation:: Read ( _) , $Operation:: Write ( data) ) => {
631+ i2c. prepare_write( addr, data. len( ) ) ?
632+ }
633+ ( $Operation:: Write ( _) , $Operation:: Read ( buf) ) => {
634+ i2c. prepare_read( addr, buf. len( ) , false ) ?
635+ }
636+ _ => { } // No changes if operation have not changed
637+ }
638+
639+ prev_op = op;
640+ }
641+
642+ // 4. Now, prev_op is last command use methods variations that will generate stop
643+ match prev_op {
644+ $Operation:: Read ( rb) => i2c. read_bytes( rb) ?,
645+ $Operation:: Write ( wb) => i2c. write_bytes( wb. iter( ) . cloned( ) ) ?,
646+ } ;
647+
648+ i2c. end_transaction( ) ?;
649+ }
650+ } ;
505651}
652+ use transaction_impl;
506653
507654// Note: implementation is from f0xx-hal
508655// TODO: check error handling. See https://github.com/stm32-rs/stm32f0xx-hal/pull/95/files
0 commit comments