Adafruit_BusIO_Register.cpp 9.3 KB

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