arduinoprojects

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

Adafruit_BusIO_Register.cpp (9753B)


      1 #include <Adafruit_BusIO_Register.h>
      2 
      3 /*!
      4  *    @brief  Create a register we access over an I2C Device (which defines the
      5  * bus and address)
      6  *    @param  i2cdevice The I2CDevice to use for underlying I2C access
      7  *    @param  reg_addr The address pointer value for the I2C/SMBus register, can
      8  * be 8 or 16 bits
      9  *    @param  width    The width of the register data itself, defaults to 1 byte
     10  *    @param  byteorder The byte order of the register (used when width is > 1),
     11  * defaults to LSBFIRST
     12  *    @param  address_width The width of the register address itself, defaults
     13  * to 1 byte
     14  */
     15 Adafruit_BusIO_Register::Adafruit_BusIO_Register(Adafruit_I2CDevice *i2cdevice,
     16                                                  uint16_t reg_addr,
     17                                                  uint8_t width,
     18                                                  uint8_t byteorder,
     19                                                  uint8_t address_width) {
     20   _i2cdevice = i2cdevice;
     21   _spidevice = NULL;
     22   _addrwidth = address_width;
     23   _address = reg_addr;
     24   _byteorder = byteorder;
     25   _width = width;
     26 }
     27 
     28 /*!
     29  *    @brief  Create a register we access over an SPI Device (which defines the
     30  * bus and CS pin)
     31  *    @param  spidevice The SPIDevice to use for underlying SPI access
     32  *    @param  reg_addr The address pointer value for the SPI register, can
     33  * be 8 or 16 bits
     34  *    @param  type     The method we use to read/write data to SPI (which is not
     35  * as well defined as I2C)
     36  *    @param  width    The width of the register data itself, defaults to 1 byte
     37  *    @param  byteorder The byte order of the register (used when width is > 1),
     38  * defaults to LSBFIRST
     39  *    @param  address_width The width of the register address itself, defaults
     40  * to 1 byte
     41  */
     42 Adafruit_BusIO_Register::Adafruit_BusIO_Register(Adafruit_SPIDevice *spidevice,
     43                                                  uint16_t reg_addr,
     44                                                  Adafruit_BusIO_SPIRegType type,
     45                                                  uint8_t width,
     46                                                  uint8_t byteorder,
     47                                                  uint8_t address_width) {
     48   _spidevice = spidevice;
     49   _spiregtype = type;
     50   _i2cdevice = NULL;
     51   _addrwidth = address_width;
     52   _address = reg_addr;
     53   _byteorder = byteorder;
     54   _width = width;
     55 }
     56 
     57 /*!
     58  *    @brief  Create a register we access over an I2C or SPI Device. This is a
     59  * handy function because we can pass in NULL for the unused interface, allowing
     60  * libraries to mass-define all the registers
     61  *    @param  i2cdevice The I2CDevice to use for underlying I2C access, if NULL
     62  * we use SPI
     63  *    @param  spidevice The SPIDevice to use for underlying SPI access, if NULL
     64  * we use I2C
     65  *    @param  reg_addr The address pointer value for the I2C/SMBus/SPI register,
     66  * can be 8 or 16 bits
     67  *    @param  type     The method we use to read/write data to SPI (which is not
     68  * as well defined as I2C)
     69  *    @param  width    The width of the register data itself, defaults to 1 byte
     70  *    @param  byteorder The byte order of the register (used when width is > 1),
     71  * defaults to LSBFIRST
     72  *    @param  address_width The width of the register address itself, defaults
     73  * to 1 byte
     74  */
     75 Adafruit_BusIO_Register::Adafruit_BusIO_Register(
     76     Adafruit_I2CDevice *i2cdevice, Adafruit_SPIDevice *spidevice,
     77     Adafruit_BusIO_SPIRegType type, uint16_t reg_addr, uint8_t width,
     78     uint8_t byteorder, uint8_t address_width) {
     79   _spidevice = spidevice;
     80   _i2cdevice = i2cdevice;
     81   _spiregtype = type;
     82   _addrwidth = address_width;
     83   _address = reg_addr;
     84   _byteorder = byteorder;
     85   _width = width;
     86 }
     87 
     88 /*!
     89  *    @brief  Write a buffer of data to the register location
     90  *    @param  buffer Pointer to data to write
     91  *    @param  len Number of bytes to write
     92  *    @return True on successful write (only really useful for I2C as SPI is
     93  * uncheckable)
     94  */
     95 bool Adafruit_BusIO_Register::write(uint8_t *buffer, uint8_t len) {
     96 
     97   uint8_t addrbuffer[2] = {(uint8_t)(_address & 0xFF),
     98                            (uint8_t)(_address >> 8)};
     99 
    100   if (_i2cdevice) {
    101     return _i2cdevice->write(buffer, len, true, addrbuffer, _addrwidth);
    102   }
    103   if (_spidevice) {
    104     if (_spiregtype == ADDRBIT8_HIGH_TOREAD) {
    105       addrbuffer[0] &= ~0x80;
    106     }
    107     if (_spiregtype == ADDRBIT8_HIGH_TOWRITE) {
    108       addrbuffer[0] |= 0x80;
    109     }
    110     if (_spiregtype == AD8_HIGH_TOREAD_AD7_HIGH_TOINC) {
    111       addrbuffer[0] &= ~0x80;
    112       addrbuffer[0] |= 0x40;
    113     }
    114     return _spidevice->write(buffer, len, addrbuffer, _addrwidth);
    115   }
    116   return false;
    117 }
    118 
    119 /*!
    120  *    @brief  Write up to 4 bytes of data to the register location
    121  *    @param  value Data to write
    122  *    @param  numbytes How many bytes from 'value' to write
    123  *    @return True on successful write (only really useful for I2C as SPI is
    124  * uncheckable)
    125  */
    126 bool Adafruit_BusIO_Register::write(uint32_t value, uint8_t numbytes) {
    127   if (numbytes == 0) {
    128     numbytes = _width;
    129   }
    130   if (numbytes > 4) {
    131     return false;
    132   }
    133 
    134   // store a copy
    135   _cached = value;
    136 
    137   for (int i = 0; i < numbytes; i++) {
    138     if (_byteorder == LSBFIRST) {
    139       _buffer[i] = value & 0xFF;
    140     } else {
    141       _buffer[numbytes - i - 1] = value & 0xFF;
    142     }
    143     value >>= 8;
    144   }
    145   return write(_buffer, numbytes);
    146 }
    147 
    148 /*!
    149  *    @brief  Read data from the register location. This does not do any error
    150  * checking!
    151  *    @return Returns 0xFFFFFFFF on failure, value otherwise
    152  */
    153 uint32_t Adafruit_BusIO_Register::read(void) {
    154   if (!read(_buffer, _width)) {
    155     return -1;
    156   }
    157 
    158   uint32_t value = 0;
    159 
    160   for (int i = 0; i < _width; i++) {
    161     value <<= 8;
    162     if (_byteorder == LSBFIRST) {
    163       value |= _buffer[_width - i - 1];
    164     } else {
    165       value |= _buffer[i];
    166     }
    167   }
    168 
    169   return value;
    170 }
    171 
    172 /*!
    173  *    @brief  Read cached data from last time we wrote to this register
    174  *    @return Returns 0xFFFFFFFF on failure, value otherwise
    175  */
    176 uint32_t Adafruit_BusIO_Register::readCached(void) { return _cached; }
    177 
    178 /*!
    179  *    @brief  Read a buffer of data from the register location
    180  *    @param  buffer Pointer to data to read into
    181  *    @param  len Number of bytes to read
    182  *    @return True on successful write (only really useful for I2C as SPI is
    183  * uncheckable)
    184  */
    185 bool Adafruit_BusIO_Register::read(uint8_t *buffer, uint8_t len) {
    186   uint8_t addrbuffer[2] = {(uint8_t)(_address & 0xFF),
    187                            (uint8_t)(_address >> 8)};
    188 
    189   if (_i2cdevice) {
    190     return _i2cdevice->write_then_read(addrbuffer, _addrwidth, buffer, len);
    191   }
    192   if (_spidevice) {
    193     if (_spiregtype == ADDRBIT8_HIGH_TOREAD) {
    194       addrbuffer[0] |= 0x80;
    195     }
    196     if (_spiregtype == ADDRBIT8_HIGH_TOWRITE) {
    197       addrbuffer[0] &= ~0x80;
    198     }
    199     if (_spiregtype == AD8_HIGH_TOREAD_AD7_HIGH_TOINC) {
    200       addrbuffer[0] |= 0x80 | 0x40;
    201     }
    202     return _spidevice->write_then_read(addrbuffer, _addrwidth, buffer, len);
    203   }
    204   return false;
    205 }
    206 
    207 /*!
    208  *    @brief  Read 2 bytes of data from the register location
    209  *    @param  value Pointer to uint16_t variable to read into
    210  *    @return True on successful write (only really useful for I2C as SPI is
    211  * uncheckable)
    212  */
    213 bool Adafruit_BusIO_Register::read(uint16_t *value) {
    214   if (!read(_buffer, 2)) {
    215     return false;
    216   }
    217 
    218   if (_byteorder == LSBFIRST) {
    219     *value = _buffer[1];
    220     *value <<= 8;
    221     *value |= _buffer[0];
    222   } else {
    223     *value = _buffer[0];
    224     *value <<= 8;
    225     *value |= _buffer[1];
    226   }
    227   return true;
    228 }
    229 
    230 /*!
    231  *    @brief  Read 1 byte of data from the register location
    232  *    @param  value Pointer to uint8_t variable to read into
    233  *    @return True on successful write (only really useful for I2C as SPI is
    234  * uncheckable)
    235  */
    236 bool Adafruit_BusIO_Register::read(uint8_t *value) {
    237   if (!read(_buffer, 1)) {
    238     return false;
    239   }
    240 
    241   *value = _buffer[0];
    242   return true;
    243 }
    244 
    245 /*!
    246  *    @brief  Pretty printer for this register
    247  *    @param  s The Stream to print to, defaults to &Serial
    248  */
    249 void Adafruit_BusIO_Register::print(Stream *s) {
    250   uint32_t val = read();
    251   s->print("0x");
    252   s->print(val, HEX);
    253 }
    254 
    255 /*!
    256  *    @brief  Pretty printer for this register
    257  *    @param  s The Stream to print to, defaults to &Serial
    258  */
    259 void Adafruit_BusIO_Register::println(Stream *s) {
    260   print(s);
    261   s->println();
    262 }
    263 
    264 /*!
    265  *    @brief  Create a slice of the register that we can address without
    266  * touching other bits
    267  *    @param  reg The Adafruit_BusIO_Register which defines the bus/register
    268  *    @param  bits The number of bits wide we are slicing
    269  *    @param  shift The number of bits that our bit-slice is shifted from LSB
    270  */
    271 Adafruit_BusIO_RegisterBits::Adafruit_BusIO_RegisterBits(
    272     Adafruit_BusIO_Register *reg, uint8_t bits, uint8_t shift) {
    273   _register = reg;
    274   _bits = bits;
    275   _shift = shift;
    276 }
    277 
    278 /*!
    279  *    @brief  Read 4 bytes of data from the register
    280  *    @return  data The 4 bytes to read
    281  */
    282 uint32_t Adafruit_BusIO_RegisterBits::read(void) {
    283   uint32_t val = _register->read();
    284   val >>= _shift;
    285   return val & ((1 << (_bits)) - 1);
    286 }
    287 
    288 /*!
    289  *    @brief  Write 4 bytes of data to the register
    290  *    @param  data The 4 bytes to write
    291  *    @return True on successful write (only really useful for I2C as SPI is
    292  * uncheckable)
    293  */
    294 bool Adafruit_BusIO_RegisterBits::write(uint32_t data) {
    295   uint32_t val = _register->read();
    296 
    297   // mask off the data before writing
    298   uint32_t mask = (1 << (_bits)) - 1;
    299   data &= mask;
    300 
    301   mask <<= _shift;
    302   val &= ~mask;          // remove the current data at that spot
    303   val |= data << _shift; // and add in the new data
    304 
    305   return _register->write(val, _register->width());
    306 }
    307 
    308 /*!
    309  *    @brief  The width of the register data, helpful for doing calculations
    310  *    @returns The data width used when initializing the register
    311  */
    312 uint8_t Adafruit_BusIO_Register::width(void) { return _width; }