gobot.io/x/gobot/v2@v2.1.0/platforms/digispark/digispark_i2c.go (about) 1 package digispark 2 3 import ( 4 "errors" 5 "fmt" 6 "sync" 7 ) 8 9 // digisparkI2cConnection implements the interface gobot.I2cOperations 10 type digisparkI2cConnection struct { 11 address uint8 12 adaptor *Adaptor 13 mtx sync.Mutex 14 } 15 16 // NewDigisparkI2cConnection creates an i2c connection to an i2c device at 17 // the specified address 18 func NewDigisparkI2cConnection(adaptor *Adaptor, address uint8) (connection *digisparkI2cConnection) { 19 return &digisparkI2cConnection{adaptor: adaptor, address: address} 20 } 21 22 // Init makes sure that the i2c device is already initialized 23 func (c *digisparkI2cConnection) Init() (err error) { 24 if !c.adaptor.i2c { 25 if err = c.adaptor.littleWire.i2cInit(); err != nil { 26 return 27 } 28 c.adaptor.i2c = true 29 } 30 return 31 } 32 33 // Test tests i2c connection with the given address 34 func (c *digisparkI2cConnection) Test(address uint8) error { 35 if !c.adaptor.i2c { 36 return errors.New("Digispark i2c not initialized") 37 } 38 return c.adaptor.littleWire.i2cStart(address, 0) 39 } 40 41 // UpdateDelay updates i2c signal delay amount; tune if neccessary to fit your requirements 42 func (c *digisparkI2cConnection) UpdateDelay(duration uint) error { 43 if !c.adaptor.i2c { 44 return errors.New("Digispark i2c not initialized") 45 } 46 return c.adaptor.littleWire.i2cUpdateDelay(duration) 47 } 48 49 // Read tries to read a full buffer from the i2c device. 50 // Returns an empty array if the response from the board has timed out. 51 func (c *digisparkI2cConnection) Read(b []byte) (countRead int, err error) { 52 c.mtx.Lock() 53 defer c.mtx.Unlock() 54 55 return c.readInternal(b) 56 } 57 58 // Write writes the buffer content in data to the i2c device. 59 func (c *digisparkI2cConnection) Write(data []byte) (countWritten int, err error) { 60 c.mtx.Lock() 61 defer c.mtx.Unlock() 62 63 return c.writeInternal(data, true) 64 } 65 66 // Close do nothing than return nil. 67 func (c *digisparkI2cConnection) Close() error { 68 return nil 69 } 70 71 // ReadByte reads one byte from the i2c device. 72 func (c *digisparkI2cConnection) ReadByte() (val byte, err error) { 73 c.mtx.Lock() 74 defer c.mtx.Unlock() 75 76 buf := []byte{0} 77 if err = c.readAndCheckCount(buf); err != nil { 78 return 79 } 80 val = buf[0] 81 return 82 } 83 84 // ReadByteData reads one byte of the given register address from the i2c device. 85 func (c *digisparkI2cConnection) ReadByteData(reg uint8) (val uint8, err error) { 86 c.mtx.Lock() 87 defer c.mtx.Unlock() 88 89 if err = c.writeAndCheckCount([]byte{reg}, false); err != nil { 90 return 91 } 92 93 buf := []byte{0} 94 if err = c.readAndCheckCount(buf); err != nil { 95 return 96 } 97 val = buf[0] 98 return 99 } 100 101 // ReadWordData reads two bytes of the given register address from the i2c device. 102 func (c *digisparkI2cConnection) ReadWordData(reg uint8) (val uint16, err error) { 103 c.mtx.Lock() 104 defer c.mtx.Unlock() 105 106 if err = c.writeAndCheckCount([]byte{reg}, false); err != nil { 107 return 108 } 109 110 buf := []byte{0, 0} 111 if err = c.readAndCheckCount(buf); err != nil { 112 return 113 } 114 low, high := buf[0], buf[1] 115 116 val = (uint16(high) << 8) | uint16(low) 117 return 118 } 119 120 // ReadBlockData reads a block of maximum 32 bytes from the given register address of the i2c device. 121 func (c *digisparkI2cConnection) ReadBlockData(reg uint8, data []byte) (err error) { 122 c.mtx.Lock() 123 defer c.mtx.Unlock() 124 125 if err = c.writeAndCheckCount([]byte{reg}, false); err != nil { 126 return 127 } 128 129 if len(data) > 32 { 130 data = data[:32] 131 } 132 return c.readAndCheckCount(data) 133 } 134 135 // WriteByte writes one byte to the i2c device. 136 func (c *digisparkI2cConnection) WriteByte(val byte) error { 137 c.mtx.Lock() 138 defer c.mtx.Unlock() 139 140 buf := []byte{val} 141 return c.writeAndCheckCount(buf, true) 142 } 143 144 // WriteByteData writes one byte to the given register address of the i2c device. 145 func (c *digisparkI2cConnection) WriteByteData(reg uint8, val byte) error { 146 c.mtx.Lock() 147 defer c.mtx.Unlock() 148 149 buf := []byte{reg, val} 150 return c.writeAndCheckCount(buf, true) 151 } 152 153 // WriteWordData writes two bytes to the given register address of the i2c device. 154 func (c *digisparkI2cConnection) WriteWordData(reg uint8, val uint16) error { 155 c.mtx.Lock() 156 defer c.mtx.Unlock() 157 158 low := uint8(val & 0xff) 159 high := uint8((val >> 8) & 0xff) 160 buf := []byte{reg, low, high} 161 return c.writeAndCheckCount(buf, true) 162 } 163 164 // WriteBlockData writes a block of maximum 32 bytes to the given register address of the i2c device. 165 func (c *digisparkI2cConnection) WriteBlockData(reg uint8, data []byte) error { 166 c.mtx.Lock() 167 defer c.mtx.Unlock() 168 169 if len(data) > 32 { 170 data = data[:32] 171 } 172 173 buf := make([]byte, len(data)+1) 174 copy(buf[1:], data) 175 buf[0] = reg 176 return c.writeAndCheckCount(buf, true) 177 } 178 179 // WriteBytes writes a block of maximum 32 bytes to the current register address of the i2c device. 180 func (c *digisparkI2cConnection) WriteBytes(buf []byte) error { 181 c.mtx.Lock() 182 defer c.mtx.Unlock() 183 184 if len(buf) > 32 { 185 buf = buf[:32] 186 } 187 188 return c.writeAndCheckCount(buf, true) 189 } 190 191 func (c *digisparkI2cConnection) readAndCheckCount(buf []byte) error { 192 countRead, err := c.readInternal(buf) 193 if err != nil { 194 return err 195 } 196 expectedCount := len(buf) 197 if countRead != expectedCount { 198 return fmt.Errorf("Digispark i2c read %d bytes, expected %d bytes", countRead, expectedCount) 199 } 200 return nil 201 } 202 203 func (c *digisparkI2cConnection) writeAndCheckCount(buf []byte, finalStop bool) error { 204 countWritten, err := c.writeInternal(buf, finalStop) 205 if err != nil { 206 return err 207 } 208 expectedCount := len(buf) 209 if countWritten != expectedCount { 210 return fmt.Errorf("Digispark i2c write %d bytes, expected %d bytes", countWritten, expectedCount) 211 } 212 return nil 213 } 214 215 func (c *digisparkI2cConnection) readInternal(b []byte) (countRead int, err error) { 216 if !c.adaptor.i2c { 217 err = errors.New("Digispark i2c not initialized") 218 return 219 } 220 if err = c.adaptor.littleWire.i2cStart(c.address, 1); err != nil { 221 return 222 } 223 l := 8 224 stop := uint8(0) 225 226 for stop == 0 { 227 if countRead+l >= len(b) { 228 l = len(b) - countRead 229 stop = 1 230 } 231 if err = c.adaptor.littleWire.i2cRead(b[countRead:countRead+l], l, stop); err != nil { 232 return 233 } 234 countRead += l 235 } 236 return 237 } 238 239 func (c *digisparkI2cConnection) writeInternal(data []byte, finalStop bool) (countWritten int, err error) { 240 if !c.adaptor.i2c { 241 err = errors.New("Digispark i2c not initialized") 242 return 243 } 244 if err = c.adaptor.littleWire.i2cStart(c.address, 0); err != nil { 245 return 246 } 247 l := 4 248 lastQuadruplet := false 249 stop := uint8(0) 250 251 for !lastQuadruplet { 252 if countWritten+l >= len(data) { 253 lastQuadruplet = true 254 l = len(data) - countWritten 255 if finalStop { 256 stop = 1 257 } 258 } 259 if err = c.adaptor.littleWire.i2cWrite(data[countWritten:countWritten+l], l, stop); err != nil { 260 return 261 } 262 countWritten += l 263 } 264 return 265 }