arduinoprojects

git clone https://git.tarina.org/arduinoprojects
Log | Files | Refs

Adafruit_I2CDevice.cpp (7193B)


      1 #include <Adafruit_I2CDevice.h>
      2 #include <Arduino.h>
      3 
      4 //#define DEBUG_SERIAL Serial
      5 
      6 /*!
      7  *    @brief  Create an I2C device at a given address
      8  *    @param  addr The 7-bit I2C address for the device
      9  *    @param  theWire The I2C bus to use, defaults to &Wire
     10  */
     11 Adafruit_I2CDevice::Adafruit_I2CDevice(uint8_t addr, TwoWire *theWire) {
     12   _addr = addr;
     13   _wire = theWire;
     14   _begun = false;
     15 #ifdef ARDUINO_ARCH_SAMD
     16   _maxBufferSize = 250; // as defined in Wire.h's RingBuffer
     17 #else
     18   _maxBufferSize = 32;
     19 #endif
     20 }
     21 
     22 /*!
     23  *    @brief  Initializes and does basic address detection
     24  *    @param  addr_detect Whether we should attempt to detect the I2C address
     25  * with a scan. 99% of sensors/devices don't mind but once in a while, they spaz
     26  * on a scan!
     27  *    @return True if I2C initialized and a device with the addr found
     28  */
     29 bool Adafruit_I2CDevice::begin(bool addr_detect) {
     30   _wire->begin();
     31   _begun = true;
     32 
     33   if (addr_detect) {
     34     return detected();
     35   }
     36   return true;
     37 }
     38 
     39 /*!
     40  *    @brief  Scans I2C for the address - note will give a false-positive
     41  *    if there's no pullups on I2C
     42  *    @return True if I2C initialized and a device with the addr found
     43  */
     44 bool Adafruit_I2CDevice::detected(void) {
     45   // Init I2C if not done yet
     46   if (!_begun && !begin()) {
     47     return false;
     48   }
     49 
     50   // A basic scanner, see if it ACK's
     51   _wire->beginTransmission(_addr);
     52   if (_wire->endTransmission() == 0) {
     53     return true;
     54   }
     55   return false;
     56 }
     57 
     58 /*!
     59  *    @brief  Write a buffer or two to the I2C device. Cannot be more than
     60  * maxBufferSize() bytes.
     61  *    @param  buffer Pointer to buffer of data to write. This is const to
     62  *            ensure the content of this buffer doesn't change.
     63  *    @param  len Number of bytes from buffer to write
     64  *    @param  prefix_buffer Pointer to optional array of data to write before
     65  * buffer. Cannot be more than maxBufferSize() bytes. This is const to
     66  *            ensure the content of this buffer doesn't change.
     67  *    @param  prefix_len Number of bytes from prefix buffer to write
     68  *    @param  stop Whether to send an I2C STOP signal on write
     69  *    @return True if write was successful, otherwise false.
     70  */
     71 bool Adafruit_I2CDevice::write(const uint8_t *buffer, size_t len, bool stop,
     72                                const uint8_t *prefix_buffer,
     73                                size_t prefix_len) {
     74   if ((len + prefix_len) > maxBufferSize()) {
     75     // currently not guaranteed to work if more than 32 bytes!
     76     // we will need to find out if some platforms have larger
     77     // I2C buffer sizes :/
     78 #ifdef DEBUG_SERIAL
     79     DEBUG_SERIAL.println(F("\tI2CDevice could not write such a large buffer"));
     80 #endif
     81     return false;
     82   }
     83 
     84   _wire->beginTransmission(_addr);
     85 
     86   // Write the prefix data (usually an address)
     87   if ((prefix_len != 0) && (prefix_buffer != NULL)) {
     88     if (_wire->write(prefix_buffer, prefix_len) != prefix_len) {
     89 #ifdef DEBUG_SERIAL
     90       DEBUG_SERIAL.println(F("\tI2CDevice failed to write"));
     91 #endif
     92       return false;
     93     }
     94   }
     95 
     96   // Write the data itself
     97   if (_wire->write(buffer, len) != len) {
     98 #ifdef DEBUG_SERIAL
     99     DEBUG_SERIAL.println(F("\tI2CDevice failed to write"));
    100 #endif
    101     return false;
    102   }
    103 
    104 #ifdef DEBUG_SERIAL
    105 
    106   DEBUG_SERIAL.print(F("\tI2CWRITE @ 0x"));
    107   DEBUG_SERIAL.print(_addr, HEX);
    108   DEBUG_SERIAL.print(F(" :: "));
    109   if ((prefix_len != 0) && (prefix_buffer != NULL)) {
    110     for (uint16_t i = 0; i < prefix_len; i++) {
    111       DEBUG_SERIAL.print(F("0x"));
    112       DEBUG_SERIAL.print(prefix_buffer[i], HEX);
    113       DEBUG_SERIAL.print(F(", "));
    114     }
    115   }
    116   for (uint16_t i = 0; i < len; i++) {
    117     DEBUG_SERIAL.print(F("0x"));
    118     DEBUG_SERIAL.print(buffer[i], HEX);
    119     DEBUG_SERIAL.print(F(", "));
    120     if (i % 32 == 31) {
    121       DEBUG_SERIAL.println();
    122     }
    123   }
    124   DEBUG_SERIAL.println();
    125 #endif
    126 
    127 #ifdef DEBUG_SERIAL
    128   // DEBUG_SERIAL.print("Stop: "); DEBUG_SERIAL.println(stop);
    129 #endif
    130 
    131   if (_wire->endTransmission(stop) == 0) {
    132 #ifdef DEBUG_SERIAL
    133     // DEBUG_SERIAL.println("Sent!");
    134 #endif
    135     return true;
    136   } else {
    137 #ifdef DEBUG_SERIAL
    138     DEBUG_SERIAL.println("Failed to send!");
    139 #endif
    140     return false;
    141   }
    142 }
    143 
    144 /*!
    145  *    @brief  Read from I2C into a buffer from the I2C device.
    146  *    Cannot be more than maxBufferSize() bytes.
    147  *    @param  buffer Pointer to buffer of data to read into
    148  *    @param  len Number of bytes from buffer to read.
    149  *    @param  stop Whether to send an I2C STOP signal on read
    150  *    @return True if read was successful, otherwise false.
    151  */
    152 bool Adafruit_I2CDevice::read(uint8_t *buffer, size_t len, bool stop) {
    153   if (len > maxBufferSize()) {
    154     // currently not guaranteed to work if more than 32 bytes!
    155     // we will need to find out if some platforms have larger
    156     // I2C buffer sizes :/
    157 #ifdef DEBUG_SERIAL
    158     DEBUG_SERIAL.println(F("\tI2CDevice could not read such a large buffer"));
    159 #endif
    160     return false;
    161   }
    162 
    163   size_t recv = _wire->requestFrom((uint8_t)_addr, (uint8_t)len, (uint8_t)stop);
    164   if (recv != len) {
    165     // Not enough data available to fulfill our obligation!
    166 #ifdef DEBUG_SERIAL
    167     DEBUG_SERIAL.print(F("\tI2CDevice did not receive enough data: "));
    168     DEBUG_SERIAL.println(recv);
    169 #endif
    170     return false;
    171   }
    172 
    173   for (uint16_t i = 0; i < len; i++) {
    174     buffer[i] = _wire->read();
    175   }
    176 
    177 #ifdef DEBUG_SERIAL
    178   DEBUG_SERIAL.print(F("\tI2CREAD  @ 0x"));
    179   DEBUG_SERIAL.print(_addr, HEX);
    180   DEBUG_SERIAL.print(F(" :: "));
    181   for (uint16_t i = 0; i < len; i++) {
    182     DEBUG_SERIAL.print(F("0x"));
    183     DEBUG_SERIAL.print(buffer[i], HEX);
    184     DEBUG_SERIAL.print(F(", "));
    185     if (len % 32 == 31) {
    186       DEBUG_SERIAL.println();
    187     }
    188   }
    189   DEBUG_SERIAL.println();
    190 #endif
    191 
    192   return true;
    193 }
    194 
    195 /*!
    196  *    @brief  Write some data, then read some data from I2C into another buffer.
    197  *    Cannot be more than maxBufferSize() bytes. The buffers can point to
    198  *    same/overlapping locations.
    199  *    @param  write_buffer Pointer to buffer of data to write from
    200  *    @param  write_len Number of bytes from buffer to write.
    201  *    @param  read_buffer Pointer to buffer of data to read into.
    202  *    @param  read_len Number of bytes from buffer to read.
    203  *    @param  stop Whether to send an I2C STOP signal between the write and read
    204  *    @return True if write & read was successful, otherwise false.
    205  */
    206 bool Adafruit_I2CDevice::write_then_read(const uint8_t *write_buffer,
    207                                          size_t write_len, uint8_t *read_buffer,
    208                                          size_t read_len, bool stop) {
    209   if (!write(write_buffer, write_len, stop)) {
    210     return false;
    211   }
    212 
    213   return read(read_buffer, read_len);
    214 }
    215 
    216 /*!
    217  *    @brief  Returns the 7-bit address of this device
    218  *    @return The 7-bit address of this device
    219  */
    220 uint8_t Adafruit_I2CDevice::address(void) { return _addr; }
    221 
    222 /*!
    223  *    @brief  Change the I2C clock speed to desired (relies on
    224  *    underlying Wire support!
    225  *    @param desiredclk The desired I2C SCL frequency
    226  *    @return True if this platform supports changing I2C speed.
    227  *    Not necessarily that the speed was achieved!
    228  */
    229 bool Adafruit_I2CDevice::setSpeed(uint32_t desiredclk) {
    230 #if (ARDUINO >= 157) && !defined(ARDUINO_STM32_FEATHER)
    231   _wire->setClock(desiredclk);
    232   return true;
    233 #else
    234   return false;
    235 #endif
    236 }