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.
ad717x.c
00001 /***************************************************************************//** 00002 * @file AD717X.c 00003 * @brief AD717X implementation file. 00004 * Devices: AD7172-2, AD7172-4, AD7173-8, AD7175-2, AD7175-8, AD7176-2 00005 * AD7177-2, AD4111, AD4112, AD4114, AD4115 00006 * @author acozma (andrei.cozma@analog.com) 00007 * dnechita (dan.nechita@analog.com) 00008 * 00009 ******************************************************************************** 00010 * Copyright 2015(c) Analog Devices, Inc. 00011 * 00012 * All rights reserved. 00013 * 00014 * Redistribution and use in source and binary forms, with or without modification, 00015 * are permitted provided that the following conditions are met: 00016 * - Redistributions of source code must retain the above copyright 00017 * notice, this list of conditions and the following disclaimer. 00018 * - Redistributions in binary form must reproduce the above copyright 00019 * notice, this list of conditions and the following disclaimer in 00020 * the documentation and/or other materials provided with the 00021 * distribution. 00022 * - Neither the name of Analog Devices, Inc. nor the names of its 00023 * contributors may be used to endorse or promote products derived 00024 * from this software without specific prior written permission. 00025 * - The use of this software may or may not infringe the patent rights 00026 * of one or more patent holders. This license does not release you 00027 * from the requirement that you obtain separate licenses from these 00028 * patent holders to use this software. 00029 * - Use of the software either in source or binary form, must be run 00030 * on or directly connected to an Analog Devices Inc. component. 00031 * 00032 * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR IMPLIED 00033 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, MERCHANTABILITY 00034 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 00035 * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00036 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00037 * INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00038 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 00039 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00040 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00041 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00042 *******************************************************************************/ 00043 00044 /******************************************************************************/ 00045 /***************************** Include Files **********************************/ 00046 /******************************************************************************/ 00047 #include <stdlib.h> 00048 #include "ad717x.h" 00049 00050 /* Error codes */ 00051 #define INVALID_VAL -1 /* Invalid argument */ 00052 #define COMM_ERR -2 /* Communication error on receive */ 00053 #define TIMEOUT -3 /* A timeout has occured */ 00054 00055 /***************************************************************************//** 00056 * @brief Searches through the list of registers of the driver instance and 00057 * retrieves a pointer to the register that matches the given address. 00058 * 00059 * @param device - The handler of the instance of the driver. 00060 * @param reg_address - The address to be used to find the register. 00061 * 00062 * @return A pointer to the register if found or 0. 00063 *******************************************************************************/ 00064 ad717x_st_reg *AD717X_GetReg(ad717x_dev *device, 00065 uint8_t reg_address) 00066 { 00067 uint8_t i; 00068 ad717x_st_reg *reg = 0; 00069 00070 if (!device || !device->regs) 00071 return 0; 00072 00073 for (i = 0; i < device->num_regs; i++) { 00074 if (device->regs[i].addr == reg_address) { 00075 reg = &device->regs[i]; 00076 break; 00077 } 00078 } 00079 00080 return reg; 00081 } 00082 00083 /***************************************************************************//** 00084 * @brief Reads the value of the specified register. 00085 * 00086 * @param device - The handler of the instance of the driver. 00087 * @param addr - The address of the register to be read. The value will be stored 00088 * inside the register structure that holds info about this register. 00089 * 00090 * @return Returns 0 for success or negative error code. 00091 *******************************************************************************/ 00092 int32_t AD717X_ReadRegister(ad717x_dev *device, 00093 uint8_t addr) 00094 { 00095 int32_t ret = 0; 00096 uint8_t buffer[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 00097 uint8_t i = 0; 00098 uint8_t check8 = 0; 00099 uint8_t msgBuf[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 00100 ad717x_st_reg *pReg; 00101 00102 if(!device) 00103 return INVALID_VAL; 00104 00105 pReg = AD717X_GetReg(device, addr); 00106 if (!pReg) 00107 return INVALID_VAL; 00108 00109 /* Build the Command word */ 00110 buffer[0] = AD717X_COMM_REG_WEN | AD717X_COMM_REG_RD | 00111 AD717X_COMM_REG_RA(pReg->addr); 00112 00113 /* Read data from the device */ 00114 ret = spi_write_and_read(device->spi_desc, 00115 buffer, 00116 ((device->useCRC != AD717X_DISABLE) ? pReg->size + 1 00117 : pReg->size) + 1); 00118 if(ret < 0) 00119 return ret; 00120 00121 /* Check the CRC */ 00122 if(device->useCRC == AD717X_USE_CRC) { 00123 msgBuf[0] = AD717X_COMM_REG_WEN | AD717X_COMM_REG_RD | 00124 AD717X_COMM_REG_RA(pReg->addr); 00125 for(i = 1; i < pReg->size + 2; ++i) { 00126 msgBuf[i] = buffer[i]; 00127 } 00128 check8 = AD717X_ComputeCRC8(msgBuf, pReg->size + 2); 00129 } 00130 if(device->useCRC == AD717X_USE_XOR) { 00131 msgBuf[0] = AD717X_COMM_REG_WEN | AD717X_COMM_REG_RD | 00132 AD717X_COMM_REG_RA(pReg->addr); 00133 for(i = 1; i < pReg->size + 2; ++i) { 00134 msgBuf[i] = buffer[i]; 00135 } 00136 check8 = AD717X_ComputeXOR8(msgBuf, pReg->size + 2); 00137 } 00138 00139 if(check8 != 0) { 00140 /* ReadRegister checksum failed. */ 00141 return COMM_ERR; 00142 } 00143 00144 /* Build the result */ 00145 pReg->value = 0; 00146 for(i = 1; i < pReg->size + 1; i++) { 00147 pReg->value <<= 8; 00148 pReg->value += buffer[i]; 00149 } 00150 00151 return ret; 00152 } 00153 00154 /***************************************************************************//** 00155 * @brief Writes the value of the specified register. 00156 * 00157 * @param device - The handler of the instance of the driver. 00158 * @param addr - The address of the register to be written with the value stored 00159 * inside the register structure that holds info about this 00160 * register. 00161 * 00162 * @return Returns 0 for success or negative error code. 00163 *******************************************************************************/ 00164 int32_t AD717X_WriteRegister(ad717x_dev *device, 00165 uint8_t addr) 00166 { 00167 int32_t ret = 0; 00168 int32_t regValue = 0; 00169 uint8_t wrBuf[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 00170 uint8_t i = 0; 00171 uint8_t crc8 = 0; 00172 ad717x_st_reg *preg; 00173 00174 if(!device) 00175 return INVALID_VAL; 00176 00177 preg = AD717X_GetReg(device, addr); 00178 if (!preg) 00179 return INVALID_VAL; 00180 00181 /* Build the Command word */ 00182 wrBuf[0] = AD717X_COMM_REG_WEN | AD717X_COMM_REG_WR | 00183 AD717X_COMM_REG_RA(preg->addr); 00184 00185 /* Fill the write buffer */ 00186 regValue = preg->value; 00187 for(i = 0; i < preg->size; i++) { 00188 wrBuf[preg->size - i] = regValue & 0xFF; 00189 regValue >>= 8; 00190 } 00191 00192 /* Compute the CRC */ 00193 if(device->useCRC != AD717X_DISABLE) { 00194 crc8 = AD717X_ComputeCRC8(wrBuf, preg->size + 1); 00195 wrBuf[preg->size + 1] = crc8; 00196 } 00197 00198 /* Write data to the device */ 00199 ret = spi_write_and_read(device->spi_desc, 00200 wrBuf, 00201 (device->useCRC != AD717X_DISABLE) ? 00202 preg->size + 2 : preg->size + 1); 00203 00204 return ret; 00205 } 00206 00207 /***************************************************************************//** 00208 * @brief Resets the device. 00209 * 00210 * @param device - The handler of the instance of the driver. 00211 * 00212 * @return Returns 0 for success or negative error code. 00213 *******************************************************************************/ 00214 int32_t AD717X_Reset(ad717x_dev *device) 00215 { 00216 int32_t ret = 0; 00217 uint8_t wrBuf[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; 00218 00219 if(!device) 00220 return INVALID_VAL; 00221 00222 ret = spi_write_and_read(device->spi_desc, 00223 wrBuf, 00224 8); 00225 00226 return ret; 00227 } 00228 00229 /***************************************************************************//** 00230 * @brief Waits until a new conversion result is available. 00231 * 00232 * @param device - The handler of the instance of the driver. 00233 * @param timeout - Count representing the number of polls to be done until the 00234 * function returns if no new data is available. 00235 * 00236 * @return Returns 0 for success or negative error code. 00237 *******************************************************************************/ 00238 int32_t AD717X_WaitForReady(ad717x_dev *device, 00239 uint32_t timeout) 00240 { 00241 ad717x_st_reg *statusReg; 00242 int32_t ret; 00243 int8_t ready = 0; 00244 00245 if(!device || !device->regs) 00246 return INVALID_VAL; 00247 00248 statusReg = AD717X_GetReg(device, AD717X_STATUS_REG); 00249 if (!statusReg) 00250 return INVALID_VAL; 00251 00252 while(!ready && --timeout) { 00253 /* Read the value of the Status Register */ 00254 ret = AD717X_ReadRegister(device, AD717X_STATUS_REG); 00255 if(ret < 0) 00256 return ret; 00257 00258 /* Check the RDY bit in the Status Register */ 00259 ready = (statusReg->value & AD717X_STATUS_REG_RDY) == 0; 00260 } 00261 00262 return timeout ? 0 : TIMEOUT; 00263 } 00264 00265 /***************************************************************************//** 00266 * @brief Reads the conversion result from the device. 00267 * 00268 * @param device - The handler of the instance of the driver. 00269 * @param pData - Pointer to store the read data. 00270 * 00271 * @return Returns 0 for success or negative error code. 00272 *******************************************************************************/ 00273 int32_t AD717X_ReadData(ad717x_dev *device, 00274 int32_t* pData) 00275 { 00276 ad717x_st_reg *dataReg; 00277 int32_t ret; 00278 00279 if(!device || !device->regs) 00280 return INVALID_VAL; 00281 00282 dataReg = AD717X_GetReg(device, AD717X_DATA_REG); 00283 if (!dataReg) 00284 return INVALID_VAL; 00285 00286 /* Update the data register length with respect to device and options */ 00287 ret = AD717X_ComputeDataregSize(device); 00288 00289 /* Read the value of the Status Register */ 00290 ret |= AD717X_ReadRegister(device, AD717X_DATA_REG); 00291 00292 /* Get the read result */ 00293 *pData = dataReg->value; 00294 00295 return ret; 00296 } 00297 00298 /***************************************************************************//** 00299 * @brief Computes data register read size to account for bit number and status 00300 * read. 00301 * 00302 * @param device - The handler of the instance of the driver. 00303 * 00304 * @return 0in case of success or negative code in case of failure. 00305 *******************************************************************************/ 00306 int32_t AD717X_ComputeDataregSize(ad717x_dev *device) 00307 { 00308 ad717x_st_reg *reg_ptr; 00309 ad717x_st_reg *datareg_ptr; 00310 uint16_t case_var; 00311 00312 /* Get interface mode register pointer */ 00313 reg_ptr = AD717X_GetReg(device, AD717X_IFMODE_REG); 00314 /* Get data register pointer */ 00315 datareg_ptr = AD717X_GetReg(device, AD717X_DATA_REG); 00316 case_var = reg_ptr->value & (AD717X_IFMODE_REG_DATA_STAT | 00317 AD717X_IFMODE_REG_DATA_WL16); 00318 00319 /* Compute data register size */ 00320 datareg_ptr->size = 3; 00321 if ((case_var & AD717X_IFMODE_REG_DATA_WL16) == AD717X_IFMODE_REG_DATA_WL16) 00322 datareg_ptr->size--; 00323 if ((case_var & AD717X_IFMODE_REG_DATA_STAT) == AD717X_IFMODE_REG_DATA_STAT) 00324 datareg_ptr->size++; 00325 00326 /* Get ID register pointer */ 00327 reg_ptr = AD717X_GetReg(device, AD717X_ID_REG); 00328 00329 /* If the part is 32/24 bit wide add a byte to the read */ 00330 if((reg_ptr->value & AD717X_ID_REG_MASK) == AD7177_2_ID_REG_VALUE) 00331 datareg_ptr->size++; 00332 00333 return 0; 00334 } 00335 00336 /***************************************************************************//** 00337 * @brief Computes the CRC checksum for a data buffer. 00338 * 00339 * @param pBuf - Data buffer 00340 * @param bufSize - Data buffer size in bytes 00341 * 00342 * @return Returns the computed CRC checksum. 00343 *******************************************************************************/ 00344 uint8_t AD717X_ComputeCRC8(uint8_t * pBuf, 00345 uint8_t bufSize) 00346 { 00347 uint8_t i = 0; 00348 uint8_t crc = 0; 00349 00350 while(bufSize) { 00351 for(i = 0x80; i != 0; i >>= 1) { 00352 if(((crc & 0x80) != 0) != ((*pBuf & i) != 00353 0)) { /* MSB of CRC register XOR input Bit from Data */ 00354 crc <<= 1; 00355 crc ^= AD717X_CRC8_POLYNOMIAL_REPRESENTATION; 00356 } else { 00357 crc <<= 1; 00358 } 00359 } 00360 pBuf++; 00361 bufSize--; 00362 } 00363 return crc; 00364 } 00365 00366 /***************************************************************************//** 00367 * @brief Computes the XOR checksum for a data buffer. 00368 * 00369 * @param pBuf - Data buffer 00370 * @param bufSize - Data buffer size in bytes 00371 * 00372 * @return Returns the computed XOR checksum. 00373 *******************************************************************************/ 00374 uint8_t AD717X_ComputeXOR8(uint8_t * pBuf, 00375 uint8_t bufSize) 00376 { 00377 uint8_t xor = 0; 00378 00379 while(bufSize) { 00380 xor ^= *pBuf; 00381 pBuf++; 00382 bufSize--; 00383 } 00384 return xor; 00385 } 00386 00387 /***************************************************************************//** 00388 * @brief Updates the CRC settings. 00389 * 00390 * @param device - The handler of the instance of the driver. 00391 * 00392 * @return Returns 0 for success or negative error code. 00393 *******************************************************************************/ 00394 int32_t AD717X_UpdateCRCSetting(ad717x_dev *device) 00395 { 00396 ad717x_st_reg *interfaceReg; 00397 00398 if(!device || !device->regs) 00399 return INVALID_VAL; 00400 00401 interfaceReg = AD717X_GetReg(device, AD717X_IFMODE_REG); 00402 if (!interfaceReg) 00403 return INVALID_VAL; 00404 00405 /* Get CRC State. */ 00406 if(AD717X_IFMODE_REG_CRC_STAT(interfaceReg->value)) { 00407 device->useCRC = AD717X_USE_CRC; 00408 } else if(AD717X_IFMODE_REG_XOR_STAT(interfaceReg->value)) { 00409 device->useCRC = AD717X_USE_XOR; 00410 } else { 00411 device->useCRC = AD717X_DISABLE; 00412 } 00413 00414 return 0; 00415 } 00416 00417 /***************************************************************************//** 00418 * @brief Initializes the AD717X. 00419 * 00420 * @param device - The device structure. 00421 * @param init_param - The structure that contains the device initial 00422 * parameters. 00423 * 00424 * @return Returns 0 for success or negative error code. 00425 *******************************************************************************/ 00426 int32_t AD717X_Init(ad717x_dev **device, 00427 ad717x_init_param init_param) 00428 { 00429 ad717x_dev *dev; 00430 int32_t ret; 00431 ad717x_st_reg *preg; 00432 00433 dev = (ad717x_dev *)malloc(sizeof(*dev)); 00434 if (!dev) 00435 return -1; 00436 00437 dev->regs = init_param.regs; 00438 dev->num_regs = init_param.num_regs; 00439 00440 /* Initialize the SPI communication. */ 00441 ret = spi_init(&dev->spi_desc, &init_param.spi_init); 00442 if (ret < 0) 00443 return ret; 00444 00445 /* Reset the device interface.*/ 00446 ret = AD717X_Reset(dev); 00447 if (ret < 0) 00448 return ret; 00449 00450 /* Initialize ADC mode register. */ 00451 ret = AD717X_WriteRegister(dev, AD717X_ADCMODE_REG); 00452 if(ret < 0) 00453 return ret; 00454 00455 /* Initialize Interface mode register. */ 00456 ret = AD717X_WriteRegister(dev, AD717X_IFMODE_REG); 00457 if(ret < 0) 00458 return ret; 00459 00460 /* Get CRC State */ 00461 ret = AD717X_UpdateCRCSetting(dev); 00462 if(ret < 0) 00463 return ret; 00464 00465 /* Initialize registers AD717X_GPIOCON_REG through AD717X_OFFSET0_REG */ 00466 preg = AD717X_GetReg(dev, AD717X_GPIOCON_REG); 00467 if (!preg) 00468 return INVALID_VAL; 00469 00470 while (preg && preg->addr != AD717X_OFFSET0_REG) { 00471 if (preg->addr == AD717X_ID_REG) { 00472 preg ++; 00473 continue; 00474 } 00475 00476 ret = AD717X_WriteRegister(dev, preg->addr); 00477 if (ret < 0) 00478 break; 00479 preg ++; 00480 } 00481 00482 /* Read ID register to identify the part */ 00483 ret = AD717X_ReadRegister(dev, AD717X_ID_REG); 00484 if(ret < 0) 00485 return ret; 00486 00487 *device = dev; 00488 00489 return ret; 00490 } 00491 00492 /***************************************************************************//** 00493 * @brief Free the resources allocated by AD717X_Init(). 00494 * @param dev - The device structure. 00495 * @return SUCCESS in case of success, negative error code otherwise. 00496 *******************************************************************************/ 00497 int32_t AD717X_remove(ad717x_dev *dev) 00498 { 00499 int32_t ret; 00500 00501 ret = spi_remove(dev->spi_desc); 00502 00503 free(dev); 00504 00505 return ret; 00506 }
Generated on Thu Aug 11 2022 00:46:55 by
1.7.2