@@ -53,24 +53,22 @@ type I2C struct {
5353 // instance is declared (e.g., in the board definition). see the godoc
5454 // comments on type muxSelect for more details.
5555 muxSDA , muxSCL muxSelect
56-
57- // these are copied from I2CConfig, during (*I2C).Configure(I2CConfig), and
58- // should be considered read-only for internal reference (i.e., modifying them
59- // will have no desirable effect).
60- sda , scl Pin
61- frequency uint32
62-
63- // auxiliary state data used internally
64- configured bool
6556}
6657
67- type I2CDirection bool
58+ type i2cDirection bool
6859
6960const (
70- DirectionWrite I2CDirection = false
71- DirectionRead I2CDirection = true
61+ directionWrite i2cDirection = false
62+ directionRead i2cDirection = true
7263)
7364
65+ func (dir i2cDirection ) shift (addr uint16 ) uint32 {
66+ if addr <<= 1 ; dir == directionRead {
67+ addr |= 1
68+ }
69+ return uint32 (addr ) & 0xFF
70+ }
71+
7472// I2C enumerated types
7573type (
7674 resultFlag uint32
@@ -156,36 +154,31 @@ const (
156154func (i2c * I2C ) Configure (config I2CConfig ) {
157155
158156 // init pins
159- i2c . sda , i2c . scl = config .getPins ()
157+ sda , scl : = config .getPins ()
160158
161159 // configure the mux and pad control registers
162- i2c . sda .Configure (PinConfig {Mode : PinModeI2CSDA })
163- i2c . scl .Configure (PinConfig {Mode : PinModeI2CSCL })
160+ sda .Configure (PinConfig {Mode : PinModeI2CSDA })
161+ scl .Configure (PinConfig {Mode : PinModeI2CSCL })
164162
165163 // configure the mux input selector
166164 i2c .muxSDA .connect ()
167165 i2c .muxSCL .connect ()
168166
169- i2c . frequency = config .Frequency
170- if 0 == i2c . frequency {
171- i2c . frequency = TWI_FREQ_DEFAULT
167+ freq : = config .Frequency
168+ if 0 == freq {
169+ freq = TWI_FREQ_DEFAULT
172170 }
173171
174172 // reset clock and registers, and enable LPI2C module interface
175- i2c .reset ()
176-
177- i2c .configured = true
173+ i2c .reset (freq )
178174}
179175
180176func (i2c I2C ) Tx (addr uint16 , w , r []byte ) error {
181177
182- // convert address to addressable
183- a := address7Bit (addr )
184-
185178 // perform transmit transfer
186179 if nil != w {
187180 // generate start condition on bus
188- if result := i2c .start (a , DirectionWrite ); resultSuccess != result {
181+ if result := i2c .start (addr , directionWrite ); resultSuccess != result {
189182 return errI2CSignalStartTimeout
190183 }
191184 // ensure TX FIFO is empty
@@ -205,7 +198,7 @@ func (i2c I2C) Tx(addr uint16, w, r []byte) error {
205198 // perform receive transfer
206199 if nil != r {
207200 // generate (repeated-)start condition on bus
208- if result := i2c .start (a , DirectionRead ); resultSuccess != result {
201+ if result := i2c .start (addr , directionRead ); resultSuccess != result {
209202 return errI2CSignalStartTimeout
210203 }
211204 // read received data
@@ -230,11 +223,11 @@ func (i2c I2C) Tx(addr uint16, w, r []byte) error {
230223// devices with 7-bit addresses, which is the vast majority.
231224func (i2c I2C ) WriteRegister (address uint8 , register uint8 , data []byte ) error {
232225 option := transferOption {
233- flags : transferDefault , // transfer options bit mask (0 = normal transfer)
234- peripheral : address7Bit (address ), // 7-bit peripheral address
235- direction : DirectionWrite , // DirectionRead or DirectionWrite
236- subaddress : uint16 (register ), // peripheral sub-address (transferred MSB first)
237- subaddressSize : 1 , // byte length of sub-address (maximum = 4 bytes)
226+ flags : transferDefault , // transfer options bit mask (0 = normal transfer)
227+ peripheral : uint16 (address ), // 7-bit peripheral address
228+ direction : directionWrite , // directionRead or directionWrite
229+ subaddress : uint16 (register ), // peripheral sub-address (transferred MSB first)
230+ subaddressSize : 1 , // byte length of sub-address (maximum = 4 bytes)
238231 }
239232 if result := i2c .controllerTransferPoll (option , data ); resultSuccess != result {
240233 return errI2CWriteTimeout
@@ -250,19 +243,19 @@ func (i2c I2C) WriteRegister(address uint8, register uint8, data []byte) error {
250243// with 7-bit addresses, which is the vast majority.
251244func (i2c I2C ) ReadRegister (address uint8 , register uint8 , data []byte ) error {
252245 option := transferOption {
253- flags : transferDefault , // transfer options bit mask (0 = normal transfer)
254- peripheral : address7Bit (address ), // 7-bit peripheral address
255- direction : DirectionRead , // DirectionRead or DirectionWrite
256- subaddress : uint16 (register ), // peripheral sub-address (transferred MSB first)
257- subaddressSize : 1 , // byte length of sub-address (maximum = 4 bytes)
246+ flags : transferDefault , // transfer options bit mask (0 = normal transfer)
247+ peripheral : uint16 (address ), // 7-bit peripheral address
248+ direction : directionRead , // directionRead or directionWrite
249+ subaddress : uint16 (register ), // peripheral sub-address (transferred MSB first)
250+ subaddressSize : 1 , // byte length of sub-address (maximum = 4 bytes)
258251 }
259252 if result := i2c .controllerTransferPoll (option , data ); resultSuccess != result {
260253 return errI2CWriteTimeout
261254 }
262255 return nil
263256}
264257
265- func (i2c * I2C ) reset () {
258+ func (i2c * I2C ) reset (freq uint32 ) {
266259 // disable interface
267260 i2c .Bus .MCR .ClearBits (nxp .LPI2C_MCR_MEN )
268261
@@ -284,7 +277,7 @@ func (i2c *I2C) reset() {
284277 i2c .Bus .MFCR .Set (mfcr )
285278
286279 // configure clock using receiver frequency
287- i2c .setFrequency (i2c . frequency )
280+ i2c .setFrequency (freq )
288281
289282 // clear reset, and enable the interface
290283 i2c .Bus .MCR .Set (nxp .LPI2C_MCR_MEN )
@@ -392,22 +385,6 @@ func (i2c *I2C) setFrequency(freq uint32) {
392385 }
393386}
394387
395- // cycles computes a cycle count for a given time in nanoseconds.
396- func (i2c * I2C ) cycles (width , maxCycles , prescalar uint32 ) uint32 {
397- busCycles := 1000000 / (TWI_FREQ_BUS / prescalar / 1000 )
398- cycles := uint32 (0 )
399- // search for the cycle count just below the desired glitch width
400- for (((cycles + 1 ) * busCycles ) < width ) && (cycles + 1 < maxCycles ) {
401- cycles ++
402- }
403- // if we end up with zero cycles, then set the filter to a single cycle unless
404- // the bus clock is greater than 10x the desired glitch width
405- if (cycles == 0 ) && (busCycles <= (width * 10 )) {
406- cycles = 1
407- }
408- return cycles
409- }
410-
411388// checkStatus converts the status register to a resultFlag for return, and
412389// clears any errors if present.
413390func (i2c * I2C ) checkStatus (status statusFlag ) resultFlag {
@@ -478,49 +455,14 @@ func (i2c *I2C) isBusBusy() bool {
478455 return (0 != (status & statusBusBusy )) && (0 == (status & statusBusy ))
479456}
480457
481- // addressable represents a type that can provide fully-formatted I2C peripheral
482- // addresses for both read operations and write operations.
483- type addressable interface {
484- toRead () uint32
485- toWrite () uint32
486- bitSize () uint8
487- shift (I2CDirection ) uint32
488- }
489-
490- // address7Bit and address10Bit stores the unshifted original I2C peripheral
491- // address in an unsigned integral data type and implements the addressable
492- // interface to reformat addresses as required for read/write operations.
493- // TODO:
494- // add 10-bit address support
495- type (
496- address7Bit uint8
497- //address10Bit uint16
498- )
499-
500- func (a address7Bit ) toRead () uint32 { return uint32 (((uint8 (a ) << 1 ) | 0x01 ) & 0xFF ) }
501- func (a address7Bit ) toWrite () uint32 { return uint32 (((uint8 (a ) << 1 ) & 0xFE ) & 0xFF ) }
502- func (a address7Bit ) bitSize () uint8 { return 7 } // 7-bit addresses
503- func (a address7Bit ) shift (dir I2CDirection ) uint32 {
504- if DirectionWrite == dir {
505- return a .toWrite ()
506- }
507- return a .toRead ()
508- }
509-
510- //func (a address10Bit) toRead() uint32 {}
511- //func (a address10Bit) toWrite() uint32 {}
512- //func (a address10Bit) bitSize() uint8 { return 10 } // 10-bit addresses
513- //func (a address10Bit) shift(dir I2CDirection) uint32 {
514- //}
515-
516458// start sends a START signal and peripheral address on the I2C bus.
517459//
518460// This function is used to initiate a new controller mode transfer. First, the
519461// bus state is checked to ensure that another controller is not occupying the
520462// bus. Then a START signal is transmitted, followed by the 7-bit peripheral
521463// address. Note that this function does not actually wait until the START and
522464// address are successfully sent on the bus before returning.
523- func (i2c * I2C ) start (address addressable , dir I2CDirection ) resultFlag {
465+ func (i2c * I2C ) start (address uint16 , dir i2cDirection ) resultFlag {
524466 // return an error if the bus is already in use by another controller
525467 if i2c .isBusBusy () {
526468 return resultBusy
@@ -535,7 +477,7 @@ func (i2c *I2C) start(address addressable, dir I2CDirection) resultFlag {
535477 }
536478
537479 // issue start command
538- i2c .Bus .MTDR .Set (uint32 (commandStart ) | address .shift (dir ))
480+ i2c .Bus .MTDR .Set (uint32 (commandStart ) | dir .shift (address ))
539481 return resultSuccess
540482}
541483
@@ -633,33 +575,10 @@ func (i2c *I2C) controllerTransmit(txBuffer []byte) resultFlag {
633575 return resultSuccess
634576}
635577
636- type commandBuffer struct {
637- buffer []uint16
638- curr uint
639- size uint
640- }
641-
642- func newCommandBuffer (size uint ) * commandBuffer {
643- return & commandBuffer {
644- buffer : make ([]uint16 , size ),
645- curr : 0 ,
646- size : size ,
647- }
648- }
649-
650- func (cb * commandBuffer ) add (cmd uint16 ) bool {
651- if cb .curr < cb .size {
652- cb .buffer [cb .curr ] = cmd
653- cb .curr ++
654- return true
655- }
656- return false
657- }
658-
659578type transferOption struct {
660579 flags transferFlag // transfer options bit mask (0 = normal transfer)
661- peripheral addressable // 7-bit peripheral address
662- direction I2CDirection // DirectionRead or DirectionWrite
580+ peripheral uint16 // 7-bit peripheral address
581+ direction i2cDirection // directionRead or directionWrite
663582 subaddress uint16 // peripheral sub-address (transferred MSB first)
664583 subaddressSize uint16 // byte length of sub-address (maximum = 4 bytes)
665584}
@@ -674,45 +593,47 @@ func (i2c *I2C) controllerTransferPoll(option transferOption, data []byte) resul
674593 // turn off auto-stop
675594 i2c .Bus .MCFGR1 .ClearBits (nxp .LPI2C_MCFGR1_AUTOSTOP )
676595
677- cmd := newCommandBuffer ( 7 )
596+ cmd := make ([] uint16 , 0 , 7 )
678597 size := len (data )
679598
680599 direction := option .direction
681600 if option .subaddressSize > 0 {
682- direction = DirectionWrite
601+ direction = directionWrite
683602 }
684603 // peripheral address
685604 if 0 == (option .flags & transferNoStart ) {
686- cmd .add (uint16 (uint32 (commandStart ) | option .peripheral .shift (direction )))
605+ addr := direction .shift (option .peripheral )
606+ cmd = append (cmd , uint16 (uint32 (commandStart )| addr ))
687607 }
688608 // sub-address (MSB-first)
689609 rem := option .subaddressSize
690610 for rem > 0 {
691611 rem --
692- cmd . add ( (option .subaddress >> ( 8 * rem )) & 0xFF )
612+ cmd = append ( cmd , (option .subaddress >> ( 8 * rem ))& 0xFF )
693613 }
694614 // need to send repeated start if switching directions to read
695- if (0 != size ) && (DirectionRead == option .direction ) {
696- if DirectionWrite == direction {
697- cmd .add (uint16 (uint32 (commandStart ) | option .peripheral .toRead ()))
615+ if (0 != size ) && (directionRead == option .direction ) {
616+ if directionWrite == direction {
617+ addr := directionRead .shift (option .peripheral )
618+ cmd = append (cmd , uint16 (uint32 (commandStart )| addr ))
698619 }
699620 }
700621 // send command buffer
701622 result := resultSuccess
702- for i := uint ( 0 ); i < cmd . curr ; i ++ {
623+ for _ , c := range cmd {
703624 // wait until there is room in the FIFO
704625 if result = i2c .waitForTxReady (); resultSuccess != result {
705626 return result
706627 }
707628 // write byte into LPI2C controller data register
708- i2c .Bus .MTDR .Set (uint32 (cmd . buffer [ i ] ))
629+ i2c .Bus .MTDR .Set (uint32 (c ))
709630 }
710631 // send data
711- if option .direction == DirectionWrite && size > 0 {
632+ if option .direction == directionWrite && size > 0 {
712633 result = i2c .controllerTransmit (data )
713634 }
714635 // receive data
715- if option .direction == DirectionRead && size > 0 {
636+ if option .direction == directionRead && size > 0 {
716637 result = i2c .controllerReceive (data )
717638 }
718639 if resultSuccess != result {
0 commit comments