ad7124.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555
  1. /***************************************************************************//**
  2. * @file ad7124.c
  3. * @brief AD7124 implementation file.
  4. * Devices: AD7124-4, AD7124-8
  5. *
  6. ********************************************************************************
  7. * Copyright 2015-2019(c) Analog Devices, Inc.
  8. *
  9. * All rights reserved.
  10. *
  11. * Redistribution and use in source and binary forms, with or without modification,
  12. * are permitted provided that the following conditions are met:
  13. * - Redistributions of source code must retain the above copyright
  14. * notice, this list of conditions and the following disclaimer.
  15. * - Redistributions in binary form must reproduce the above copyright
  16. * notice, this list of conditions and the following disclaimer in
  17. * the documentation and/or other materials provided with the
  18. * distribution.
  19. * - Neither the name of Analog Devices, Inc. nor the names of its
  20. * contributors may be used to endorse or promote products derived
  21. * from this software without specific prior written permission.
  22. * - The use of this software may or may not infringe the patent rights
  23. * of one or more patent holders. This license does not release you
  24. * from the requirement that you obtain separate licenses from these
  25. * patent holders to use this software.
  26. * - Use of the software either in source or binary form, must be run
  27. * on or directly connected to an Analog Devices Inc. component.
  28. *
  29. * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR IMPLIED
  30. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, MERCHANTABILITY
  31. * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  32. * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  33. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  34. * INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  35. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  36. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  37. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  38. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  39. *******************************************************************************/
  40. /******************************************************************************/
  41. /***************************** Include Files **********************************/
  42. /******************************************************************************/
  43. #include <stdlib.h>
  44. #include <stdbool.h>
  45. #include "ad7124.h"
  46. /* Error codes */
  47. #define INVALID_VAL -1 /* Invalid argument */
  48. #define COMM_ERR -2 /* Communication error on receive */
  49. #define TIMEOUT -3 /* A timeout has occured */
  50. /*
  51. * Post reset delay required to ensure all internal config done
  52. * A time of 2ms should be enough based on the data sheet, but 4ms
  53. * chosen to provide enough margin, in case mdelay is not accurate.
  54. */
  55. #define AD7124_POST_RESET_DELAY 4
  56. /***************************************************************************//**
  57. * @brief Reads the value of the specified register without checking if the
  58. * device is ready to accept user requests.
  59. *
  60. * @param dev - The handler of the instance of the driver.
  61. * @param p_reg - Pointer to the register structure holding info about the
  62. * register to be read. The read value is stored inside the
  63. * register structure.
  64. *
  65. * @return Returns 0 for success or negative error code.
  66. *******************************************************************************/
  67. int32_t ad7124_no_check_read_register(struct ad7124_dev *dev,
  68. struct ad7124_st_reg* p_reg)
  69. {
  70. int32_t ret = 0;
  71. uint8_t buffer[8] = {0, 0, 0, 0, 0, 0, 0, 0};
  72. uint8_t i = 0;
  73. uint8_t check8 = 0, add_status_length = 0;
  74. uint8_t msg_buf[8] = {0, 0, 0, 0, 0, 0, 0, 0};
  75. if(!dev || !p_reg)
  76. return INVALID_VAL;
  77. /* Build the Command word */
  78. buffer[0] = AD7124_COMM_REG_WEN | AD7124_COMM_REG_RD |
  79. AD7124_COMM_REG_RA(p_reg->addr);
  80. /*
  81. * If this is an AD7124_DATA register read, and the DATA_STATUS bit is set
  82. * in ADC_CONTROL, need to read 4, not 3 bytes for DATA with STATUS
  83. */
  84. if ((p_reg->addr == AD7124_DATA_REG) &&
  85. (dev->regs[AD7124_ADC_Control].value & AD7124_ADC_CTRL_REG_DATA_STATUS)) {
  86. add_status_length = 1;
  87. }
  88. /* Read data from the device */
  89. ret = spi_write_and_read(dev->spi_desc,
  90. buffer,
  91. ((dev->use_crc != AD7124_DISABLE_CRC) ? p_reg->size + 1
  92. : p_reg->size) + 1 + add_status_length);
  93. if(ret < 0)
  94. return ret;
  95. /* Check the CRC */
  96. if(dev->use_crc == AD7124_USE_CRC) {
  97. msg_buf[0] = AD7124_COMM_REG_WEN | AD7124_COMM_REG_RD |
  98. AD7124_COMM_REG_RA(p_reg->addr);
  99. for(i = 1; i < p_reg->size + 2 + add_status_length; ++i) {
  100. msg_buf[i] = buffer[i];
  101. }
  102. check8 = ad7124_compute_crc8(msg_buf, p_reg->size + 2 + add_status_length);
  103. }
  104. if(check8 != 0) {
  105. /* ReadRegister checksum failed. */
  106. return COMM_ERR;
  107. }
  108. /*
  109. * if reading Data with 4 bytes, need to copy the status byte to the STATUS
  110. * register struct value member
  111. */
  112. if (add_status_length) {
  113. dev->regs[AD7124_Status].value = buffer[p_reg->size + 1];
  114. }
  115. /* Build the result */
  116. p_reg->value = 0;
  117. for(i = 1; i < p_reg->size + 1; i++) {
  118. p_reg->value <<= 8;
  119. p_reg->value += buffer[i];
  120. }
  121. return ret;
  122. }
  123. /***************************************************************************//**
  124. * @brief Writes the value of the specified register without checking if the
  125. * device is ready to accept user requests.
  126. *
  127. * @param dev - The handler of the instance of the driver.
  128. * @param reg - Register structure holding info about the register to be written
  129. *
  130. * @return Returns 0 for success or negative error code.
  131. *******************************************************************************/
  132. int32_t ad7124_no_check_write_register(struct ad7124_dev *dev,
  133. struct ad7124_st_reg reg)
  134. {
  135. int32_t ret = 0;
  136. int32_t reg_value = 0;
  137. uint8_t wr_buf[8] = {0, 0, 0, 0, 0, 0, 0, 0};
  138. uint8_t i = 0;
  139. uint8_t crc8 = 0;
  140. if(!dev)
  141. return INVALID_VAL;
  142. /* Build the Command word */
  143. wr_buf[0] = AD7124_COMM_REG_WEN | AD7124_COMM_REG_WR |
  144. AD7124_COMM_REG_RA(reg.addr);
  145. /* Fill the write buffer */
  146. reg_value = reg.value;
  147. for(i = 0; i < reg.size; i++) {
  148. wr_buf[reg.size - i] = reg_value & 0xFF;
  149. reg_value >>= 8;
  150. }
  151. /* Compute the CRC */
  152. if(dev->use_crc != AD7124_DISABLE_CRC) {
  153. crc8 = ad7124_compute_crc8(wr_buf, reg.size + 1);
  154. wr_buf[reg.size + 1] = crc8;
  155. }
  156. /* Write data to the device */
  157. ret = spi_write_and_read(dev->spi_desc,
  158. wr_buf,
  159. (dev->use_crc != AD7124_DISABLE_CRC) ? reg.size + 2
  160. : reg.size + 1);
  161. return ret;
  162. }
  163. /***************************************************************************//**
  164. * @brief Reads the value of the specified register only when the device is ready
  165. * to accept user requests. If the device ready flag is deactivated the
  166. * read operation will be executed without checking the device state.
  167. *
  168. * @param dev - The handler of the instance of the driver.
  169. * @param p_reg - Pointer to the register structure holding info about the
  170. * register to be read. The read value is stored inside the
  171. * register structure.
  172. *
  173. * @return Returns 0 for success or negative error code.
  174. *******************************************************************************/
  175. int32_t ad7124_read_register(struct ad7124_dev *dev,
  176. struct ad7124_st_reg* p_reg)
  177. {
  178. int32_t ret;
  179. if (p_reg->addr != AD7124_ERR_REG && dev->check_ready) {
  180. ret = ad7124_wait_for_spi_ready(dev,
  181. dev->spi_rdy_poll_cnt);
  182. if (ret < 0)
  183. return ret;
  184. }
  185. ret = ad7124_no_check_read_register(dev,
  186. p_reg);
  187. return ret;
  188. }
  189. /***************************************************************************//**
  190. * @brief Writes the value of the specified register only when the device is
  191. * ready to accept user requests. If the device ready flag is deactivated
  192. * the write operation will be executed without checking the device state.
  193. *
  194. * @param dev - The handler of the instance of the driver.
  195. * @param p_reg - Register structure holding info about the register to be written
  196. *
  197. * @return Returns 0 for success or negative error code.
  198. *******************************************************************************/
  199. int32_t ad7124_write_register(struct ad7124_dev *dev,
  200. struct ad7124_st_reg p_reg)
  201. {
  202. int32_t ret;
  203. if (dev->check_ready) {
  204. ret = ad7124_wait_for_spi_ready(dev,
  205. dev->spi_rdy_poll_cnt);
  206. if (ret < 0)
  207. return ret;
  208. }
  209. ret = ad7124_no_check_write_register(dev,
  210. p_reg);
  211. return ret;
  212. }
  213. /***************************************************************************//**
  214. * @brief Resets the device.
  215. *
  216. * @param dev - The handler of the instance of the driver.
  217. *
  218. * @return Returns 0 for success or negative error code.
  219. *******************************************************************************/
  220. int32_t ad7124_reset(struct ad7124_dev *dev)
  221. {
  222. int32_t ret = 0;
  223. uint8_t wr_buf[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
  224. if(!dev)
  225. return INVALID_VAL;
  226. ret = spi_write_and_read(dev->spi_desc,
  227. wr_buf,
  228. 8);
  229. /* CRC is disabled after reset */
  230. dev->use_crc = AD7124_DISABLE_CRC;
  231. /* Read POR bit to clear */
  232. ret = ad7124_wait_to_power_on(dev,
  233. dev->spi_rdy_poll_cnt);
  234. mdelay(AD7124_POST_RESET_DELAY);
  235. return ret;
  236. }
  237. /***************************************************************************//**
  238. * @brief Waits until the device can accept read and write user actions.
  239. *
  240. * @param dev - The handler of the instance of the driver.
  241. * @param timeout - Count representing the number of polls to be done until the
  242. * function returns.
  243. *
  244. * @return Returns 0 for success or negative error code.
  245. *******************************************************************************/
  246. int32_t ad7124_wait_for_spi_ready(struct ad7124_dev *dev,
  247. uint32_t timeout)
  248. {
  249. struct ad7124_st_reg *regs;
  250. int32_t ret;
  251. int8_t ready = 0;
  252. if(!dev)
  253. return INVALID_VAL;
  254. regs = dev->regs;
  255. while(!ready && --timeout) {
  256. /* Read the value of the Error Register */
  257. ret = ad7124_read_register(dev, &regs[AD7124_Error]);
  258. if(ret < 0)
  259. return ret;
  260. /* Check the SPI IGNORE Error bit in the Error Register */
  261. ready = (regs[AD7124_Error].value &
  262. AD7124_ERR_REG_SPI_IGNORE_ERR) == 0;
  263. }
  264. return timeout ? 0 : TIMEOUT;
  265. }
  266. /***************************************************************************//**
  267. * @brief Waits until the device finishes the power-on reset operation.
  268. *
  269. * @param dev - The handler of the instance of the driver.
  270. * @param timeout - Count representing the number of polls to be done until the
  271. * function returns.
  272. *
  273. * @return Returns 0 for success or negative error code.
  274. *******************************************************************************/
  275. int32_t ad7124_wait_to_power_on(struct ad7124_dev *dev,
  276. uint32_t timeout)
  277. {
  278. struct ad7124_st_reg *regs;
  279. int32_t ret;
  280. int8_t powered_on = 0;
  281. if(!dev)
  282. return INVALID_VAL;
  283. regs = dev->regs;
  284. while(!powered_on && timeout--) {
  285. ret = ad7124_read_register(dev,
  286. &regs[AD7124_Status]);
  287. if(ret < 0)
  288. return ret;
  289. /* Check the POR_FLAG bit in the Status Register */
  290. powered_on = (regs[AD7124_Status].value &
  291. AD7124_STATUS_REG_POR_FLAG) == 0;
  292. }
  293. return (timeout || powered_on) ? 0 : TIMEOUT;
  294. }
  295. /***************************************************************************//**
  296. * @brief Waits until a new conversion result is available.
  297. *
  298. * @param dev - The handler of the instance of the driver.
  299. * @param timeout - Count representing the number of polls to be done until the
  300. * function returns if no new data is available.
  301. *
  302. * @return Returns 0 for success or negative error code.
  303. *******************************************************************************/
  304. int32_t ad7124_wait_for_conv_ready(struct ad7124_dev *dev,
  305. uint32_t timeout)
  306. {
  307. struct ad7124_st_reg *regs;
  308. int32_t ret;
  309. int8_t ready = 0;
  310. if(!dev)
  311. return INVALID_VAL;
  312. regs = dev->regs;
  313. while(!ready && --timeout) {
  314. /* Read the value of the Status Register */
  315. ret = ad7124_read_register(dev, &regs[AD7124_Status]);
  316. if(ret < 0)
  317. return ret;
  318. /* Check the RDY bit in the Status Register */
  319. ready = (regs[AD7124_Status].value &
  320. AD7124_STATUS_REG_RDY) == 0;
  321. }
  322. return timeout ? 0 : TIMEOUT;
  323. }
  324. /***************************************************************************//**
  325. * @brief Reads the conversion result from the device.
  326. *
  327. * @param dev - The handler of the instance of the driver.
  328. * @param p_data - Pointer to store the read data.
  329. *
  330. * @return Returns 0 for success or negative error code.
  331. *******************************************************************************/
  332. int32_t ad7124_read_data(struct ad7124_dev *dev,
  333. int32_t* p_data)
  334. {
  335. struct ad7124_st_reg *regs;
  336. int32_t ret;
  337. if(!dev)
  338. return INVALID_VAL;
  339. regs = dev->regs;
  340. /* Read the value of the Status Register */
  341. ret = ad7124_read_register(dev, &regs[AD7124_Data]);
  342. /* Get the read result */
  343. *p_data = regs[AD7124_Data].value;
  344. return ret;
  345. }
  346. /***************************************************************************//**
  347. * @brief Computes the CRC checksum for a data buffer.
  348. *
  349. * @param p_buf - Data buffer
  350. * @param buf_size - Data buffer size in bytes
  351. *
  352. * @return Returns the computed CRC checksum.
  353. *******************************************************************************/
  354. uint8_t ad7124_compute_crc8(uint8_t * p_buf, uint8_t buf_size)
  355. {
  356. uint8_t i = 0;
  357. uint8_t crc = 0;
  358. while(buf_size) {
  359. for(i = 0x80; i != 0; i >>= 1) {
  360. bool cmp1 = (crc & 0x80) != 0;
  361. bool cmp2 = (*p_buf & i) != 0;
  362. if(cmp1 != cmp2) { /* MSB of CRC register XOR input Bit from Data */
  363. crc <<= 1;
  364. crc ^= AD7124_CRC8_POLYNOMIAL_REPRESENTATION;
  365. } else {
  366. crc <<= 1;
  367. }
  368. }
  369. p_buf++;
  370. buf_size--;
  371. }
  372. return crc;
  373. }
  374. /***************************************************************************//**
  375. * @brief Updates the CRC settings.
  376. *
  377. * @param dev - The handler of the instance of the driver.
  378. *
  379. * @return None.
  380. *******************************************************************************/
  381. void ad7124_update_crcsetting(struct ad7124_dev *dev)
  382. {
  383. struct ad7124_st_reg *regs;
  384. if(!dev)
  385. return;
  386. regs = dev->regs;
  387. /* Get CRC State. */
  388. if (regs[AD7124_Error_En].value & AD7124_ERREN_REG_SPI_CRC_ERR_EN) {
  389. dev->use_crc = AD7124_USE_CRC;
  390. } else {
  391. dev->use_crc = AD7124_DISABLE_CRC;
  392. }
  393. }
  394. /***************************************************************************//**
  395. * @brief Updates the device SPI interface settings.
  396. *
  397. * @param dev - The handler of the instance of the driver.
  398. *
  399. * @return None.
  400. *******************************************************************************/
  401. void ad7124_update_dev_spi_settings(struct ad7124_dev *dev)
  402. {
  403. struct ad7124_st_reg *regs;
  404. if(!dev)
  405. return;
  406. regs = dev->regs;
  407. if (regs[AD7124_Error_En].value & AD7124_ERREN_REG_SPI_IGNORE_ERR_EN) {
  408. dev->check_ready = 1;
  409. } else {
  410. dev->check_ready = 0;
  411. }
  412. }
  413. /***************************************************************************//**
  414. * @brief Initializes the AD7124.
  415. *
  416. * @param device - The device structure.
  417. * @param init_param - The structure that contains the device initial
  418. * parameters.
  419. *
  420. * @return Returns 0 for success or negative error code.
  421. *******************************************************************************/
  422. int32_t ad7124_setup(struct ad7124_dev **device,
  423. struct ad7124_init_param init_param)
  424. {
  425. int32_t ret;
  426. enum ad7124_registers reg_nr;
  427. struct ad7124_dev *dev;
  428. dev = (struct ad7124_dev *)malloc(sizeof(*dev));
  429. if (!dev)
  430. return INVALID_VAL;
  431. dev->regs = init_param.regs;
  432. dev->spi_rdy_poll_cnt = init_param.spi_rdy_poll_cnt;
  433. /* Initialize the SPI communication. */
  434. ret = spi_init(&dev->spi_desc, &init_param.spi_init);
  435. if (ret < 0)
  436. return ret;
  437. /* Reset the device interface.*/
  438. ret = ad7124_reset(dev);
  439. if (ret < 0)
  440. return ret;
  441. /* Update the device structure with power-on/reset settings */
  442. dev->check_ready = 1;
  443. /* Initialize registers AD7124_ADC_Control through AD7124_Filter_7. */
  444. for(reg_nr = AD7124_Status; (reg_nr < AD7124_Offset_0) && !(ret < 0);
  445. reg_nr++) {
  446. if (dev->regs[reg_nr].rw == AD7124_RW) {
  447. ret = ad7124_write_register(dev, dev->regs[reg_nr]);
  448. if (ret < 0)
  449. break;
  450. }
  451. /* Get CRC State and device SPI interface settings */
  452. if (reg_nr == AD7124_Error_En) {
  453. ad7124_update_crcsetting(dev);
  454. ad7124_update_dev_spi_settings(dev);
  455. }
  456. }
  457. *device = dev;
  458. return ret;
  459. }
  460. /***************************************************************************//**
  461. * @brief Free the resources allocated by AD7124_Setup().
  462. *
  463. * @param dev - The device structure.
  464. *
  465. * @return SUCCESS in case of success, negative error code otherwise.
  466. *******************************************************************************/
  467. int32_t ad7124_remove(struct ad7124_dev *dev)
  468. {
  469. int32_t ret;
  470. ret = spi_remove(dev->spi_desc);
  471. free(dev);
  472. return ret;
  473. }