| 1 | #include "Adafruit_I2CDevice.h" |
| 2 | |
| 3 | // #define DEBUG_SERIAL Serial |
| 4 | |
| 5 | /*! |
| 6 | * @brief Create an I2C device at a given address |
| 7 | * @param addr The 7-bit I2C address for the device |
| 8 | * @param theWire The I2C bus to use, defaults to &Wire |
| 9 | */ |
| 10 | Adafruit_I2CDevice::Adafruit_I2CDevice(uint8_t addr, TwoWire *theWire) { |
| 11 | _addr = addr; |
| 12 | _wire = theWire; |
| 13 | _begun = false; |
| 14 | #ifdef ARDUINO_ARCH_SAMD |
| 15 | _maxBufferSize = 250; // as defined in Wire.h's RingBuffer |
| 16 | #elif defined(ESP32) |
| 17 | _maxBufferSize = I2C_BUFFER_LENGTH; |
| 18 | #else |
| 19 | _maxBufferSize = 32; |
| 20 | #endif |
| 21 | } |
| 22 | |
| 23 | /*! |
| 24 | * @brief Initializes and does basic address detection |
| 25 | * @param addr_detect Whether we should attempt to detect the I2C address |
| 26 | * with a scan. 99% of sensors/devices don't mind, but once in a while they |
| 27 | * don't respond well to a scan! |
| 28 | * @return True if I2C initialized and a device with the addr found |
| 29 | */ |
| 30 | bool Adafruit_I2CDevice::begin(bool addr_detect) { |
| 31 | _wire->begin(); |
| 32 | _begun = true; |
| 33 | |
| 34 | if (addr_detect) { |
| 35 | return detected(); |
| 36 | } |
| 37 | return true; |
| 38 | } |
| 39 | |
| 40 | /*! |
| 41 | * @brief De-initialize device, turn off the Wire interface |
| 42 | */ |
| 43 | void Adafruit_I2CDevice::end(void) { |
| 44 | // Not all port implement Wire::end(), such as |
| 45 | // - ESP8266 |
| 46 | // - AVR core without WIRE_HAS_END |
| 47 | // - ESP32: end() is implemented since 2.0.1 which is latest at the moment. |
| 48 | // Temporarily disable for now to give time for user to update. |
| 49 | #if !(defined(ESP8266) || \ |
| 50 | (defined(ARDUINO_ARCH_AVR) && !defined(WIRE_HAS_END)) || \ |
| 51 | defined(ARDUINO_ARCH_ESP32)) |
| 52 | _wire->end(); |
| 53 | _begun = false; |
| 54 | #endif |
| 55 | } |
| 56 | |
| 57 | /*! |
| 58 | * @brief Scans I2C for the address - note will give a false-positive |
| 59 | * if there's no pullups on I2C |
| 60 | * @return True if I2C initialized and a device with the addr found |
| 61 | */ |
| 62 | bool Adafruit_I2CDevice::detected(void) { |
| 63 | // Init I2C if not done yet |
| 64 | if (!_begun && !begin()) { |
| 65 | return false; |
| 66 | } |
| 67 | |
| 68 | // A basic scanner, see if it ACK's |
| 69 | _wire->beginTransmission(_addr); |
| 70 | #ifdef DEBUG_SERIAL |
| 71 | DEBUG_SERIAL.print(F("Address 0x")); |
| 72 | DEBUG_SERIAL.print(_addr, HEX); |
| 73 | #endif |
| 74 | #ifdef ARDUINO_ARCH_MBED |
| 75 | _wire->write(0); // forces a write request instead of a read |
| 76 | #endif |
| 77 | if (_wire->endTransmission() == 0) { |
| 78 | #ifdef DEBUG_SERIAL |
| 79 | DEBUG_SERIAL.println(F(" Detected")); |
| 80 | #endif |
| 81 | return true; |
| 82 | } |
| 83 | #ifdef DEBUG_SERIAL |
| 84 | DEBUG_SERIAL.println(F(" Not detected")); |
| 85 | #endif |
| 86 | return false; |
| 87 | } |
| 88 | |
| 89 | /*! |
| 90 | * @brief Write a buffer or two to the I2C device. Cannot be more than |
| 91 | * maxBufferSize() bytes. |
| 92 | * @param buffer Pointer to buffer of data to write. This is const to |
| 93 | * ensure the content of this buffer doesn't change. |
| 94 | * @param len Number of bytes from buffer to write |
| 95 | * @param prefix_buffer Pointer to optional array of data to write before |
| 96 | * buffer. Cannot be more than maxBufferSize() bytes. This is const to |
| 97 | * ensure the content of this buffer doesn't change. |
| 98 | * @param prefix_len Number of bytes from prefix buffer to write |
| 99 | * @param stop Whether to send an I2C STOP signal on write |
| 100 | * @return True if write was successful, otherwise false. |
| 101 | */ |
| 102 | bool Adafruit_I2CDevice::write(const uint8_t *buffer, size_t len, bool stop, |
| 103 | const uint8_t *prefix_buffer, |
| 104 | size_t prefix_len) { |
| 105 | if ((len + prefix_len) > maxBufferSize()) { |
| 106 | // currently not guaranteed to work if more than 32 bytes! |
| 107 | // we will need to find out if some platforms have larger |
| 108 | // I2C buffer sizes :/ |
| 109 | #ifdef DEBUG_SERIAL |
| 110 | DEBUG_SERIAL.println(F("\tI2CDevice could not write such a large buffer")); |
| 111 | #endif |
| 112 | return false; |
| 113 | } |
| 114 | |
| 115 | _wire->beginTransmission(_addr); |
| 116 | |
| 117 | // Write the prefix data (usually an address) |
| 118 | if ((prefix_len != 0) && (prefix_buffer != nullptr)) { |
| 119 | if (_wire->write(prefix_buffer, prefix_len) != prefix_len) { |
| 120 | #ifdef DEBUG_SERIAL |
| 121 | DEBUG_SERIAL.println(F("\tI2CDevice failed to write")); |
| 122 | #endif |
| 123 | return false; |
| 124 | } |
| 125 | } |
| 126 | |
| 127 | // Write the data itself |
| 128 | if (_wire->write(buffer, len) != len) { |
| 129 | #ifdef DEBUG_SERIAL |
| 130 | DEBUG_SERIAL.println(F("\tI2CDevice failed to write")); |
| 131 | #endif |
| 132 | return false; |
| 133 | } |
| 134 | |
| 135 | #ifdef DEBUG_SERIAL |
| 136 | |
| 137 | DEBUG_SERIAL.print(F("\tI2CWRITE @ 0x")); |
| 138 | DEBUG_SERIAL.print(_addr, HEX); |
| 139 | DEBUG_SERIAL.print(F(" :: ")); |
| 140 | if ((prefix_len != 0) && (prefix_buffer != nullptr)) { |
| 141 | for (uint16_t i = 0; i < prefix_len; i++) { |
| 142 | DEBUG_SERIAL.print(F("0x")); |
| 143 | DEBUG_SERIAL.print(prefix_buffer[i], HEX); |
| 144 | DEBUG_SERIAL.print(F(", ")); |
| 145 | } |
| 146 | } |
| 147 | for (uint16_t i = 0; i < len; i++) { |
| 148 | DEBUG_SERIAL.print(F("0x")); |
| 149 | DEBUG_SERIAL.print(buffer[i], HEX); |
| 150 | DEBUG_SERIAL.print(F(", ")); |
| 151 | if (i % 32 == 31) { |
| 152 | DEBUG_SERIAL.println(); |
| 153 | } |
| 154 | } |
| 155 | |
| 156 | if (stop) { |
| 157 | DEBUG_SERIAL.print("\tSTOP"); |
| 158 | } |
| 159 | #endif |
| 160 | |
| 161 | if (_wire->endTransmission(stop) == 0) { |
| 162 | #ifdef DEBUG_SERIAL |
| 163 | DEBUG_SERIAL.println(); |
| 164 | // DEBUG_SERIAL.println("Sent!"); |
| 165 | #endif |
| 166 | return true; |
| 167 | } else { |
| 168 | #ifdef DEBUG_SERIAL |
| 169 | DEBUG_SERIAL.println("\tFailed to send!"); |
| 170 | #endif |
| 171 | return false; |
| 172 | } |
| 173 | } |
| 174 | |
| 175 | /*! |
| 176 | * @brief Read from I2C into a buffer from the I2C device. |
| 177 | * Cannot be more than maxBufferSize() bytes. |
| 178 | * @param buffer Pointer to buffer of data to read into |
| 179 | * @param len Number of bytes from buffer to read. |
| 180 | * @param stop Whether to send an I2C STOP signal on read |
| 181 | * @return True if read was successful, otherwise false. |
| 182 | */ |
| 183 | bool Adafruit_I2CDevice::read(uint8_t *buffer, size_t len, bool stop) { |
| 184 | size_t pos = 0; |
| 185 | while (pos < len) { |
| 186 | size_t read_len = |
| 187 | ((len - pos) > maxBufferSize()) ? maxBufferSize() : (len - pos); |
| 188 | bool read_stop = (pos < (len - read_len)) ? false : stop; |
| 189 | if (!_read(buffer + pos, read_len, read_stop)) |
| 190 | return false; |
| 191 | pos += read_len; |
| 192 | } |
| 193 | return true; |
| 194 | } |
| 195 | |
| 196 | bool Adafruit_I2CDevice::_read(uint8_t *buffer, size_t len, bool stop) { |
| 197 | #if defined(TinyWireM_h) |
| 198 | size_t recv = _wire->requestFrom((uint8_t)_addr, (uint8_t)len); |
| 199 | #elif defined(ARDUINO_ARCH_MEGAAVR) |
| 200 | size_t recv = _wire->requestFrom(_addr, len, stop); |
| 201 | #else |
| 202 | size_t recv = _wire->requestFrom((uint8_t)_addr, (uint8_t)len, (uint8_t)stop); |
| 203 | #endif |
| 204 | |
| 205 | if (recv != len) { |
| 206 | // Not enough data available to fulfill our obligation! |
| 207 | #ifdef DEBUG_SERIAL |
| 208 | DEBUG_SERIAL.print(F("\tI2CDevice did not receive enough data: ")); |
| 209 | DEBUG_SERIAL.println(recv); |
| 210 | #endif |
| 211 | return false; |
| 212 | } |
| 213 | |
| 214 | for (uint16_t i = 0; i < len; i++) { |
| 215 | buffer[i] = _wire->read(); |
| 216 | } |
| 217 | |
| 218 | #ifdef DEBUG_SERIAL |
| 219 | DEBUG_SERIAL.print(F("\tI2CREAD @ 0x")); |
| 220 | DEBUG_SERIAL.print(_addr, HEX); |
| 221 | DEBUG_SERIAL.print(F(" :: ")); |
| 222 | for (uint16_t i = 0; i < len; i++) { |
| 223 | DEBUG_SERIAL.print(F("0x")); |
| 224 | DEBUG_SERIAL.print(buffer[i], HEX); |
| 225 | DEBUG_SERIAL.print(F(", ")); |
| 226 | if (len % 32 == 31) { |
| 227 | DEBUG_SERIAL.println(); |
| 228 | } |
| 229 | } |
| 230 | DEBUG_SERIAL.println(); |
| 231 | #endif |
| 232 | |
| 233 | return true; |
| 234 | } |
| 235 | |
| 236 | /*! |
| 237 | * @brief Write some data, then read some data from I2C into another buffer. |
| 238 | * Cannot be more than maxBufferSize() bytes. The buffers can point to |
| 239 | * same/overlapping locations. |
| 240 | * @param write_buffer Pointer to buffer of data to write from |
| 241 | * @param write_len Number of bytes from buffer to write. |
| 242 | * @param read_buffer Pointer to buffer of data to read into. |
| 243 | * @param read_len Number of bytes from buffer to read. |
| 244 | * @param stop Whether to send an I2C STOP signal between the write and read |
| 245 | * @return True if write & read was successful, otherwise false. |
| 246 | */ |
| 247 | bool Adafruit_I2CDevice::write_then_read(const uint8_t *write_buffer, |
| 248 | size_t write_len, uint8_t *read_buffer, |
| 249 | size_t read_len, bool stop) { |
| 250 | if (!write(write_buffer, write_len, stop)) { |
| 251 | return false; |
| 252 | } |
| 253 | |
| 254 | return read(read_buffer, read_len); |
| 255 | } |
| 256 | |
| 257 | /*! |
| 258 | * @brief Returns the 7-bit address of this device |
| 259 | * @return The 7-bit address of this device |
| 260 | */ |
| 261 | uint8_t Adafruit_I2CDevice::address(void) { return _addr; } |
| 262 | |
| 263 | /*! |
| 264 | * @brief Change the I2C clock speed to desired (relies on |
| 265 | * underlying Wire support! |
| 266 | * @param desiredclk The desired I2C SCL frequency |
| 267 | * @return True if this platform supports changing I2C speed. |
| 268 | * Not necessarily that the speed was achieved! |
| 269 | */ |
| 270 | bool Adafruit_I2CDevice::setSpeed(uint32_t desiredclk) { |
| 271 | #if defined(__AVR_ATmega328__) || \ |
| 272 | defined(__AVR_ATmega328P__) // fix arduino core set clock |
| 273 | // calculate TWBR correctly |
| 274 | |
| 275 | if ((F_CPU / 18) < desiredclk) { |
| 276 | #ifdef DEBUG_SERIAL |
| 277 | Serial.println(F("I2C.setSpeed too high.")); |
| 278 | #endif |
| 279 | return false; |
| 280 | } |
| 281 | uint32_t atwbr = ((F_CPU / desiredclk) - 16) / 2; |
| 282 | if (atwbr > 16320) { |
| 283 | #ifdef DEBUG_SERIAL |
| 284 | Serial.println(F("I2C.setSpeed too low.")); |
| 285 | #endif |
| 286 | return false; |
| 287 | } |
| 288 | |
| 289 | if (atwbr <= 255) { |
| 290 | atwbr /= 1; |
| 291 | TWSR = 0x0; |
| 292 | } else if (atwbr <= 1020) { |
| 293 | atwbr /= 4; |
| 294 | TWSR = 0x1; |
| 295 | } else if (atwbr <= 4080) { |
| 296 | atwbr /= 16; |
| 297 | TWSR = 0x2; |
| 298 | } else { // if (atwbr <= 16320) |
| 299 | atwbr /= 64; |
| 300 | TWSR = 0x3; |
| 301 | } |
| 302 | TWBR = atwbr; |
| 303 | |
| 304 | #ifdef DEBUG_SERIAL |
| 305 | Serial.print(F("TWSR prescaler = ")); |
| 306 | Serial.println(pow(4, TWSR)); |
| 307 | Serial.print(F("TWBR = ")); |
| 308 | Serial.println(atwbr); |
| 309 | #endif |
| 310 | return true; |
| 311 | #elif (ARDUINO >= 157) && !defined(ARDUINO_STM32_FEATHER) && \ |
| 312 | !defined(TinyWireM_h) |
| 313 | _wire->setClock(desiredclk); |
| 314 | return true; |
| 315 | |
| 316 | #else |
| 317 | (void)desiredclk; |
| 318 | return false; |
| 319 | #endif |
| 320 | } |