@@ -53,24 +53,22 @@ type I2C struct {
53
53
// instance is declared (e.g., in the board definition). see the godoc
54
54
// comments on type muxSelect for more details.
55
55
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
65
56
}
66
57
67
- type I2CDirection bool
58
+ type i2cDirection bool
68
59
69
60
const (
70
- DirectionWrite I2CDirection = false
71
- DirectionRead I2CDirection = true
61
+ directionWrite i2cDirection = false
62
+ directionRead i2cDirection = true
72
63
)
73
64
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
+
74
72
// I2C enumerated types
75
73
type (
76
74
resultFlag uint32
@@ -156,36 +154,31 @@ const (
156
154
func (i2c * I2C ) Configure (config I2CConfig ) {
157
155
158
156
// init pins
159
- i2c . sda , i2c . scl = config .getPins ()
157
+ sda , scl : = config .getPins ()
160
158
161
159
// 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 })
164
162
165
163
// configure the mux input selector
166
164
i2c .muxSDA .connect ()
167
165
i2c .muxSCL .connect ()
168
166
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
172
170
}
173
171
174
172
// reset clock and registers, and enable LPI2C module interface
175
- i2c .reset ()
176
-
177
- i2c .configured = true
173
+ i2c .reset (freq )
178
174
}
179
175
180
176
func (i2c I2C ) Tx (addr uint16 , w , r []byte ) error {
181
177
182
- // convert address to addressable
183
- a := address7Bit (addr )
184
-
185
178
// perform transmit transfer
186
179
if nil != w {
187
180
// generate start condition on bus
188
- if result := i2c .start (a , DirectionWrite ); resultSuccess != result {
181
+ if result := i2c .start (addr , directionWrite ); resultSuccess != result {
189
182
return errI2CSignalStartTimeout
190
183
}
191
184
// ensure TX FIFO is empty
@@ -205,7 +198,7 @@ func (i2c I2C) Tx(addr uint16, w, r []byte) error {
205
198
// perform receive transfer
206
199
if nil != r {
207
200
// generate (repeated-)start condition on bus
208
- if result := i2c .start (a , DirectionRead ); resultSuccess != result {
201
+ if result := i2c .start (addr , directionRead ); resultSuccess != result {
209
202
return errI2CSignalStartTimeout
210
203
}
211
204
// read received data
@@ -230,11 +223,11 @@ func (i2c I2C) Tx(addr uint16, w, r []byte) error {
230
223
// devices with 7-bit addresses, which is the vast majority.
231
224
func (i2c I2C ) WriteRegister (address uint8 , register uint8 , data []byte ) error {
232
225
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)
238
231
}
239
232
if result := i2c .controllerTransferPoll (option , data ); resultSuccess != result {
240
233
return errI2CWriteTimeout
@@ -250,19 +243,19 @@ func (i2c I2C) WriteRegister(address uint8, register uint8, data []byte) error {
250
243
// with 7-bit addresses, which is the vast majority.
251
244
func (i2c I2C ) ReadRegister (address uint8 , register uint8 , data []byte ) error {
252
245
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)
258
251
}
259
252
if result := i2c .controllerTransferPoll (option , data ); resultSuccess != result {
260
253
return errI2CWriteTimeout
261
254
}
262
255
return nil
263
256
}
264
257
265
- func (i2c * I2C ) reset () {
258
+ func (i2c * I2C ) reset (freq uint32 ) {
266
259
// disable interface
267
260
i2c .Bus .MCR .ClearBits (nxp .LPI2C_MCR_MEN )
268
261
@@ -284,7 +277,7 @@ func (i2c *I2C) reset() {
284
277
i2c .Bus .MFCR .Set (mfcr )
285
278
286
279
// configure clock using receiver frequency
287
- i2c .setFrequency (i2c . frequency )
280
+ i2c .setFrequency (freq )
288
281
289
282
// clear reset, and enable the interface
290
283
i2c .Bus .MCR .Set (nxp .LPI2C_MCR_MEN )
@@ -392,22 +385,6 @@ func (i2c *I2C) setFrequency(freq uint32) {
392
385
}
393
386
}
394
387
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
-
411
388
// checkStatus converts the status register to a resultFlag for return, and
412
389
// clears any errors if present.
413
390
func (i2c * I2C ) checkStatus (status statusFlag ) resultFlag {
@@ -478,49 +455,14 @@ func (i2c *I2C) isBusBusy() bool {
478
455
return (0 != (status & statusBusBusy )) && (0 == (status & statusBusy ))
479
456
}
480
457
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
-
516
458
// start sends a START signal and peripheral address on the I2C bus.
517
459
//
518
460
// This function is used to initiate a new controller mode transfer. First, the
519
461
// bus state is checked to ensure that another controller is not occupying the
520
462
// bus. Then a START signal is transmitted, followed by the 7-bit peripheral
521
463
// address. Note that this function does not actually wait until the START and
522
464
// 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 {
524
466
// return an error if the bus is already in use by another controller
525
467
if i2c .isBusBusy () {
526
468
return resultBusy
@@ -535,7 +477,7 @@ func (i2c *I2C) start(address addressable, dir I2CDirection) resultFlag {
535
477
}
536
478
537
479
// issue start command
538
- i2c .Bus .MTDR .Set (uint32 (commandStart ) | address .shift (dir ))
480
+ i2c .Bus .MTDR .Set (uint32 (commandStart ) | dir .shift (address ))
539
481
return resultSuccess
540
482
}
541
483
@@ -633,33 +575,10 @@ func (i2c *I2C) controllerTransmit(txBuffer []byte) resultFlag {
633
575
return resultSuccess
634
576
}
635
577
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
-
659
578
type transferOption struct {
660
579
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
663
582
subaddress uint16 // peripheral sub-address (transferred MSB first)
664
583
subaddressSize uint16 // byte length of sub-address (maximum = 4 bytes)
665
584
}
@@ -674,45 +593,47 @@ func (i2c *I2C) controllerTransferPoll(option transferOption, data []byte) resul
674
593
// turn off auto-stop
675
594
i2c .Bus .MCFGR1 .ClearBits (nxp .LPI2C_MCFGR1_AUTOSTOP )
676
595
677
- cmd := newCommandBuffer ( 7 )
596
+ cmd := make ([] uint16 , 0 , 7 )
678
597
size := len (data )
679
598
680
599
direction := option .direction
681
600
if option .subaddressSize > 0 {
682
- direction = DirectionWrite
601
+ direction = directionWrite
683
602
}
684
603
// peripheral address
685
604
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 ))
687
607
}
688
608
// sub-address (MSB-first)
689
609
rem := option .subaddressSize
690
610
for rem > 0 {
691
611
rem --
692
- cmd . add ( (option .subaddress >> ( 8 * rem )) & 0xFF )
612
+ cmd = append ( cmd , (option .subaddress >> ( 8 * rem ))& 0xFF )
693
613
}
694
614
// 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 ))
698
619
}
699
620
}
700
621
// send command buffer
701
622
result := resultSuccess
702
- for i := uint ( 0 ); i < cmd . curr ; i ++ {
623
+ for _ , c := range cmd {
703
624
// wait until there is room in the FIFO
704
625
if result = i2c .waitForTxReady (); resultSuccess != result {
705
626
return result
706
627
}
707
628
// write byte into LPI2C controller data register
708
- i2c .Bus .MTDR .Set (uint32 (cmd . buffer [ i ] ))
629
+ i2c .Bus .MTDR .Set (uint32 (c ))
709
630
}
710
631
// send data
711
- if option .direction == DirectionWrite && size > 0 {
632
+ if option .direction == directionWrite && size > 0 {
712
633
result = i2c .controllerTransmit (data )
713
634
}
714
635
// receive data
715
- if option .direction == DirectionRead && size > 0 {
636
+ if option .direction == directionRead && size > 0 {
716
637
result = i2c .controllerReceive (data )
717
638
}
718
639
if resultSuccess != result {
0 commit comments