Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
ad7124.cpp
00001 /***************************************************************************//** 00002 * @file AD7124.c 00003 * @brief AD7124 implementation file. 00004 * @devices AD7124-4, AD7124-8 00005 * 00006 ******************************************************************************** 00007 * Copyright 2015(c) Analog Devices, Inc. 00008 * 00009 * All rights reserved. 00010 * 00011 * Redistribution and use in source and binary forms, with or without modification, 00012 * are permitted provided that the following conditions are met: 00013 * - Redistributions of source code must retain the above copyright 00014 * notice, this list of conditions and the following disclaimer. 00015 * - Redistributions in binary form must reproduce the above copyright 00016 * notice, this list of conditions and the following disclaimer in 00017 * the documentation and/or other materials provided with the 00018 * distribution. 00019 * - Neither the name of Analog Devices, Inc. nor the names of its 00020 * contributors may be used to endorse or promote products derived 00021 * from this software without specific prior written permission. 00022 * - The use of this software may or may not infringe the patent rights 00023 * of one or more patent holders. This license does not release you 00024 * from the requirement that you obtain separate licenses from these 00025 * patent holders to use this software. 00026 * - Use of the software either in source or binary form, must be run 00027 * on or directly connected to an Analog Devices Inc. component. 00028 * 00029 * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR IMPLIED 00030 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, MERCHANTABILITY 00031 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 00032 * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00033 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00034 * INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00035 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 00036 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00037 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00038 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00039 *******************************************************************************/ 00040 00041 /******************************************************************************/ 00042 /***************************** Include Files **********************************/ 00043 /******************************************************************************/ 00044 #include <stdlib.h> 00045 #include "ad7124.h" 00046 00047 /* Error codes */ 00048 #define INVALID_VAL -1 /* Invalid argument */ 00049 #define COMM_ERR -2 /* Communication error on receive */ 00050 #define TIMEOUT -3 /* A timeout has occured */ 00051 00052 /***************************************************************************//** 00053 * @brief Reads the value of the specified register without checking if the 00054 * device is ready to accept user requests. 00055 * 00056 * @param dev - The handler of the instance of the driver. 00057 * @param p_reg - Pointer to the register structure holding info about the 00058 * register to be read. The read value is stored inside the 00059 * register structure. 00060 * 00061 * @return Returns 0 for success or negative error code. 00062 *******************************************************************************/ 00063 int32_t ad7124_no_check_read_register(struct ad7124_dev *dev, 00064 struct ad7124_st_reg * p_reg) 00065 { 00066 int32_t ret = 0; 00067 uint8_t buffer[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 00068 uint8_t i = 0; 00069 uint8_t check8 = 0; 00070 uint8_t msg_buf[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 00071 00072 if(!dev || !p_reg) 00073 return INVALID_VAL; 00074 00075 /* Build the Command word */ 00076 buffer[0] = AD7124_COMM_REG_WEN | AD7124_COMM_REG_RD | 00077 AD7124_COMM_REG_RA(p_reg->addr); 00078 00079 /* Read data from the device */ 00080 ret = spi_write_and_read(dev->spi_desc, 00081 buffer, 00082 ((dev->use_crc != AD7124_DISABLE_CRC) ? p_reg->size + 1 00083 : p_reg->size) + 1); 00084 if(ret < 0) 00085 return ret; 00086 00087 /* Check the CRC */ 00088 if(dev->use_crc == AD7124_USE_CRC) { 00089 msg_buf[0] = AD7124_COMM_REG_WEN | AD7124_COMM_REG_RD | 00090 AD7124_COMM_REG_RA(p_reg->addr); 00091 for(i = 1; i < p_reg->size + 2; ++i) { 00092 msg_buf[i] = buffer[i]; 00093 } 00094 check8 = ad7124_compute_crc8(msg_buf, p_reg->size + 2); 00095 } 00096 00097 if(check8 != 0) { 00098 /* ReadRegister checksum failed. */ 00099 return COMM_ERR; 00100 } 00101 00102 /* Build the result */ 00103 p_reg->value = 0; 00104 for(i = 1; i < p_reg->size + 1; i++) { 00105 p_reg->value <<= 8; 00106 p_reg->value += buffer[i]; 00107 } 00108 00109 return ret; 00110 } 00111 00112 /***************************************************************************//** 00113 * @brief Writes the value of the specified register without checking if the 00114 * device is ready to accept user requests. 00115 * 00116 * @param dev - The handler of the instance of the driver. 00117 * @param reg - Register structure holding info about the register to be written 00118 * 00119 * @return Returns 0 for success or negative error code. 00120 *******************************************************************************/ 00121 int32_t ad7124_no_check_write_register(struct ad7124_dev *dev, 00122 struct ad7124_st_reg reg) 00123 { 00124 int32_t ret = 0; 00125 int32_t reg_value = 0; 00126 uint8_t wr_buf[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 00127 uint8_t i = 0; 00128 uint8_t crc8 = 0; 00129 00130 if(!dev) 00131 return INVALID_VAL; 00132 00133 /* Build the Command word */ 00134 wr_buf[0] = AD7124_COMM_REG_WEN | AD7124_COMM_REG_WR | 00135 AD7124_COMM_REG_RA(reg.addr); 00136 00137 /* Fill the write buffer */ 00138 reg_value = reg.value; 00139 for(i = 0; i < reg.size; i++) { 00140 wr_buf[reg.size - i] = reg_value & 0xFF; 00141 reg_value >>= 8; 00142 } 00143 00144 /* Compute the CRC */ 00145 if(dev->use_crc != AD7124_DISABLE_CRC) { 00146 crc8 = ad7124_compute_crc8(wr_buf, reg.size + 1); 00147 wr_buf[reg.size + 1] = crc8; 00148 } 00149 00150 /* Write data to the device */ 00151 ret = spi_write_and_read(dev->spi_desc, 00152 wr_buf, 00153 (dev->use_crc != AD7124_DISABLE_CRC) ? reg.size + 2 00154 : reg.size + 1); 00155 00156 return ret; 00157 } 00158 00159 /***************************************************************************//** 00160 * @brief Reads the value of the specified register only when the device is ready 00161 * to accept user requests. If the device ready flag is deactivated the 00162 * read operation will be executed without checking the device state. 00163 * 00164 * @param dev - The handler of the instance of the driver. 00165 * @param p_reg - Pointer to the register structure holding info about the 00166 * register to be read. The read value is stored inside the 00167 * register structure. 00168 * 00169 * @return Returns 0 for success or negative error code. 00170 *******************************************************************************/ 00171 int32_t ad7124_read_register(struct ad7124_dev *dev, 00172 struct ad7124_st_reg * p_reg) 00173 { 00174 int32_t ret; 00175 00176 if (p_reg->addr != AD7124_ERR_REG && dev->check_ready) { 00177 ret = ad7124_wait_for_spi_ready(dev, 00178 dev->spi_rdy_poll_cnt); 00179 if (ret < 0) 00180 return ret; 00181 } 00182 ret = ad7124_no_check_read_register(dev, 00183 p_reg); 00184 00185 return ret; 00186 } 00187 00188 /***************************************************************************//** 00189 * @brief Writes the value of the specified register only when the device is 00190 * ready to accept user requests. If the device ready flag is deactivated 00191 * the write operation will be executed without checking the device state. 00192 * 00193 * @param dev - The handler of the instance of the driver. 00194 * @param reg - Register structure holding info about the register to be written 00195 * 00196 * @return Returns 0 for success or negative error code. 00197 *******************************************************************************/ 00198 int32_t ad7124_write_register(struct ad7124_dev *dev, 00199 struct ad7124_st_reg p_reg) 00200 { 00201 int32_t ret; 00202 00203 if (dev->check_ready) { 00204 ret = ad7124_wait_for_spi_ready(dev, 00205 dev->spi_rdy_poll_cnt); 00206 if (ret < 0) 00207 return ret; 00208 } 00209 ret = ad7124_no_check_write_register(dev, 00210 p_reg); 00211 00212 return ret; 00213 } 00214 00215 /***************************************************************************//** 00216 * @brief Resets the device. 00217 * 00218 * @param dev - The handler of the instance of the driver. 00219 * 00220 * @return Returns 0 for success or negative error code. 00221 *******************************************************************************/ 00222 int32_t ad7124_reset(struct ad7124_dev *dev) 00223 { 00224 int32_t ret = 0; 00225 uint8_t wr_buf[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; 00226 00227 if(!dev) 00228 return INVALID_VAL; 00229 00230 ret = spi_write_and_read(dev->spi_desc, 00231 wr_buf, 00232 8); 00233 00234 /* Wait for the reset to complete */ 00235 ret = ad7124_wait_to_power_on(dev, 00236 dev->spi_rdy_poll_cnt); 00237 00238 return ret; 00239 } 00240 00241 /***************************************************************************//** 00242 * @brief Waits until the device can accept read and write user actions. 00243 * 00244 * @param dev - The handler of the instance of the driver. 00245 * @param timeout - Count representing the number of polls to be done until the 00246 * function returns. 00247 * 00248 * @return Returns 0 for success or negative error code. 00249 *******************************************************************************/ 00250 int32_t ad7124_wait_for_spi_ready(struct ad7124_dev *dev, 00251 uint32_t timeout) 00252 { 00253 struct ad7124_st_reg *regs; 00254 int32_t ret; 00255 int8_t ready = 0; 00256 00257 if(!dev) 00258 return INVALID_VAL; 00259 00260 regs = dev->regs; 00261 00262 while(!ready && --timeout) { 00263 /* Read the value of the Error Register */ 00264 ret = ad7124_read_register(dev, ®s[AD7124_Error]); 00265 if(ret < 0) 00266 return ret; 00267 00268 /* Check the SPI IGNORE Error bit in the Error Register */ 00269 ready = (regs[AD7124_Error].value & 00270 AD7124_ERR_REG_SPI_IGNORE_ERR) == 0; 00271 } 00272 00273 return timeout ? 0 : TIMEOUT; 00274 } 00275 00276 /***************************************************************************//** 00277 * @brief Waits until the device finishes the power-on reset operation. 00278 * 00279 * @param dev - The handler of the instance of the driver. 00280 * @param timeout - Count representing the number of polls to be done until the 00281 * function returns. 00282 * 00283 * @return Returns 0 for success or negative error code. 00284 *******************************************************************************/ 00285 int32_t ad7124_wait_to_power_on(struct ad7124_dev *dev, 00286 uint32_t timeout) 00287 { 00288 struct ad7124_st_reg *regs; 00289 int32_t ret; 00290 int8_t powered_on = 0; 00291 00292 if(!dev) 00293 return INVALID_VAL; 00294 00295 regs = dev->regs; 00296 00297 while(!powered_on && timeout--) { 00298 ret = ad7124_read_register(dev, 00299 ®s[AD7124_Status]); 00300 if(ret < 0) 00301 return ret; 00302 00303 /* Check the POR_FLAG bit in the Status Register */ 00304 powered_on = (regs[AD7124_Status].value & 00305 AD7124_STATUS_REG_POR_FLAG) == 0; 00306 } 00307 00308 return (timeout || powered_on) ? 0 : TIMEOUT; 00309 } 00310 00311 /***************************************************************************//** 00312 * @brief Waits until a new conversion result is available. 00313 * 00314 * @param dev - The handler of the instance of the driver. 00315 * @param timeout - Count representing the number of polls to be done until the 00316 * function returns if no new data is available. 00317 * 00318 * @return Returns 0 for success or negative error code. 00319 *******************************************************************************/ 00320 int32_t ad7124_wait_for_conv_ready(struct ad7124_dev *dev, 00321 uint32_t timeout) 00322 { 00323 struct ad7124_st_reg *regs; 00324 int32_t ret; 00325 int8_t ready = 0; 00326 00327 if(!dev) 00328 return INVALID_VAL; 00329 00330 regs = dev->regs; 00331 00332 while(!ready && --timeout) { 00333 /* Read the value of the Status Register */ 00334 ret = ad7124_read_register(dev, ®s[AD7124_Status]); 00335 if(ret < 0) 00336 return ret; 00337 00338 /* Check the RDY bit in the Status Register */ 00339 ready = (regs[AD7124_Status].value & 00340 AD7124_STATUS_REG_RDY) == 0; 00341 } 00342 00343 return timeout ? 0 : TIMEOUT; 00344 } 00345 00346 /***************************************************************************//** 00347 * @brief Reads the conversion result from the device. 00348 * 00349 * @param dev - The handler of the instance of the driver. 00350 * @param p_data - Pointer to store the read data. 00351 * 00352 * @return Returns 0 for success or negative error code. 00353 *******************************************************************************/ 00354 int32_t ad7124_read_data(struct ad7124_dev *dev, 00355 int32_t* p_data) 00356 { 00357 struct ad7124_st_reg *regs; 00358 int32_t ret; 00359 00360 if(!dev) 00361 return INVALID_VAL; 00362 00363 regs = dev->regs; 00364 00365 /* Read the value of the Status Register */ 00366 ret = ad7124_read_register(dev, ®s[AD7124_Data]); 00367 00368 /* Get the read result */ 00369 *p_data = regs[AD7124_Data].value; 00370 00371 return ret; 00372 } 00373 00374 /***************************************************************************//** 00375 * @brief Computes the CRC checksum for a data buffer. 00376 * 00377 * @param p_buf - Data buffer 00378 * @param buf_size - Data buffer size in bytes 00379 * 00380 * @return Returns the computed CRC checksum. 00381 *******************************************************************************/ 00382 uint8_t ad7124_compute_crc8(uint8_t * p_buf, uint8_t buf_size) 00383 { 00384 uint8_t i = 0; 00385 uint8_t crc = 0; 00386 00387 while(buf_size) { 00388 for(i = 0x80; i != 0; i >>= 1) { 00389 bool cmp1 = (crc & 0x80) != 0; 00390 bool cmp2 = (*p_buf & i) != 0; 00391 if(cmp1 != cmp2) { /* MSB of CRC register XOR input Bit from Data */ 00392 crc <<= 1; 00393 crc ^= AD7124_CRC8_POLYNOMIAL_REPRESENTATION; 00394 } else { 00395 crc <<= 1; 00396 } 00397 } 00398 p_buf++; 00399 buf_size--; 00400 } 00401 return crc; 00402 } 00403 00404 /***************************************************************************//** 00405 * @brief Updates the CRC settings. 00406 * 00407 * @param dev - The handler of the instance of the driver. 00408 * 00409 * @return None. 00410 *******************************************************************************/ 00411 void ad7124_update_crcsetting(struct ad7124_dev *dev) 00412 { 00413 struct ad7124_st_reg *regs; 00414 00415 if(!dev) 00416 return; 00417 00418 regs = dev->regs; 00419 00420 /* Get CRC State. */ 00421 if (regs[AD7124_Error_En].value & AD7124_ERREN_REG_SPI_CRC_ERR_EN) { 00422 dev->use_crc = AD7124_USE_CRC; 00423 } else { 00424 dev->use_crc = AD7124_DISABLE_CRC; 00425 } 00426 } 00427 00428 /***************************************************************************//** 00429 * @brief Updates the device SPI interface settings. 00430 * 00431 * @param dev - The handler of the instance of the driver. 00432 * 00433 * @return None. 00434 *******************************************************************************/ 00435 void ad7124_update_dev_spi_settings(struct ad7124_dev *dev) 00436 { 00437 struct ad7124_st_reg *regs; 00438 00439 if(!dev) 00440 return; 00441 00442 regs = dev->regs; 00443 00444 if (regs[AD7124_Error_En].value & AD7124_ERREN_REG_SPI_IGNORE_ERR_EN) { 00445 dev->check_ready = 1; 00446 } else { 00447 dev->check_ready = 0; 00448 } 00449 } 00450 00451 /***************************************************************************//** 00452 * @brief Initializes the AD7124. 00453 * 00454 * @param device - The device structure. 00455 * @param init_param - The structure that contains the device initial 00456 * parameters. 00457 * 00458 * @return Returns 0 for success or negative error code. 00459 *******************************************************************************/ 00460 int32_t ad7124_setup(struct ad7124_dev **device, 00461 struct ad7124_init_param init_param) 00462 { 00463 int32_t ret; 00464 int reg_nr; 00465 struct ad7124_dev *dev; 00466 00467 dev = (struct ad7124_dev *)malloc(sizeof(*dev)); 00468 if (!dev) 00469 return INVALID_VAL; 00470 00471 dev->regs = init_param.regs; 00472 dev->spi_rdy_poll_cnt = init_param.spi_rdy_poll_cnt; 00473 00474 /* Initialize the SPI communication. */ 00475 ret = spi_init(&dev->spi_desc, &init_param.spi_init); 00476 if (ret < 0) 00477 return ret; 00478 00479 /* Reset the device interface.*/ 00480 ret = ad7124_reset(dev); 00481 if (ret < 0) 00482 return ret; 00483 00484 /* Update the device structure with power-on/reset settings */ 00485 dev->check_ready = 1; 00486 00487 /* Initialize registers AD7124_ADC_Control through AD7124_Filter_7. */ 00488 for(reg_nr = AD7124_Status; (reg_nr < AD7124_Offset_0) && !(ret < 0); 00489 reg_nr++) { 00490 if (dev->regs[reg_nr].rw == AD7124_RW) { 00491 ret = ad7124_write_register(dev, dev->regs[reg_nr]); 00492 if (ret < 0) 00493 break; 00494 } 00495 00496 /* Get CRC State and device SPI interface settings */ 00497 if (reg_nr == AD7124_Error_En) { 00498 ad7124_update_crcsetting(dev); 00499 ad7124_update_dev_spi_settings(dev); 00500 } 00501 } 00502 00503 *device = dev; 00504 00505 return ret; 00506 } 00507 00508 /***************************************************************************//** 00509 * @brief Free the resources allocated by AD7124_Setup(). 00510 * 00511 * @param dev - The device structure. 00512 * 00513 * @return SUCCESS in case of success, negative error code otherwise. 00514 *******************************************************************************/ 00515 int32_t ad7124_remove(struct ad7124_dev *dev) 00516 { 00517 int32_t ret; 00518 00519 ret = spi_remove(dev->spi_desc); 00520 00521 free(dev); 00522 00523 return ret; 00524 }
Generated on Thu Jul 21 2022 07:59:18 by
1.7.2