Analog Devices / mbed-drivers
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers AD7124.cpp Source File

AD7124.cpp

Go to the documentation of this file.
00001 /**
00002 *   @file     AD7124.cpp
00003 *   @brief    Source file for AD7124 ADC
00004 *   @author   Analog Devices Inc.
00005 *
00006 * For support please go to:
00007 * Github: https://github.com/analogdevicesinc/mbed-adi
00008 * Support: https://ez.analog.com/community/linux-device-drivers/microcontroller-no-os-drivers
00009 * Product: http://www.analog.com/ad7124
00010 * More: https://wiki.analog.com/resources/tools-software/mbed-drivers-all
00011 
00012 ********************************************************************************
00013 * Copyright 2016(c) Analog Devices, Inc.
00014 *
00015 * All rights reserved.
00016 *
00017 * Redistribution and use in source and binary forms, with or without
00018 * modification, are permitted provided that the following conditions are met:
00019 *  - Redistributions of source code must retain the above copyright
00020 *    notice, this list of conditions and the following disclaimer.
00021 *  - Redistributions in binary form must reproduce the above copyright
00022 *    notice, this list of conditions and the following disclaimer in
00023 *    the documentation and/or other materials provided with the
00024 *    distribution.
00025 *  - Neither the name of Analog Devices, Inc. nor the names of its
00026 *    contributors may be used to endorse or promote products derived
00027 *    from this software without specific prior written permission.
00028 *  - The use of this software may or may not infringe the patent rights
00029 *    of one or more patent holders.  This license does not release you
00030 *    from the requirement that you obtain separate licenses from these
00031 *    patent holders to use this software.
00032 *  - Use of the software either in source or binary form, must be run
00033 *    on or directly connected to an Analog Devices Inc. component.
00034 *
00035 * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
00036 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
00037 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00038 * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
00039 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00040 * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
00041 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00042 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00043 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00044 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00045 *
00046 ********************************************************************************/
00047 
00048 #include <stdint.h>
00049 #include "mbed.h"
00050 #include "AD7124.h"
00051 
00052 /**
00053  * @brief AD7790 constructor, sets CS pin and SPI format
00054  * @param CS - (optional)chip select of the AD7790
00055  * @param MOSI - (optional)pin of the SPI interface
00056  * @param MISO - (optional)pin of the SPI interface
00057  * @param SCK  - (optional)pin of the SPI interface
00058  */
00059 AD7124::AD7124(PinName CS,
00060                PinName MOSI,
00061                PinName MISO,
00062                PinName SCK) :
00063     miso(MISO), ad7124(MOSI, MISO, SCK), cs(CS)
00064 {
00065     cs = true; // cs is active low
00066     ad7124.format(8, _SPI_MODE);
00067     this->regs = ad7124_regs;
00068     this->useCRC = false;
00069 }
00070 
00071 /**
00072  * @brief Set AD7790 SPI frequency
00073  * @param hz - SPI bus frequency in hz
00074  * @return none
00075  */
00076 void AD7124::frequency(int hz)
00077 {
00078     ad7124.frequency(hz);
00079 }
00080 
00081 /**
00082  * @brief Resets the AD7790
00083  * @return none
00084  */
00085 /*void AD7124::reset()
00086 {
00087     ad7124.format(8, _SPI_MODE);
00088     cs = false;
00089     wait_us(_DELAY_TIMING);
00090     ad7124.write(_RESET);
00091     ad7124.write(_RESET);
00092     ad7124.write(_RESET);
00093     ad7124.write(_RESET);
00094     ad7124.write(_RESET);
00095     ad7124.write(_RESET);
00096     ad7124.write(_RESET);
00097     ad7124.write(_RESET);
00098     wait_us(_DELAY_TIMING);
00099     cs = true;
00100     //_continous_conversion = true;
00101 }*/
00102 /**
00103  * @brief Reads a register of the AD7790
00104  * @param  address - address of the register
00105  * @return value of the register
00106  */
00107 uint16_t AD7124::read_reg(uint8_t address)
00108 {
00109     uint16_t data = address << 8;
00110     data |= _DUMMY_BYTE;
00111     data |= _READ_FLAG;
00112     return  write_spi(data);
00113 }
00114 
00115 /**
00116  * @brief Writes a register of the AD7790
00117  * @param address - address of the register
00118  * @param reg_val - value to be written
00119  * @return none
00120  *
00121  */
00122 void AD7124::write_reg(uint8_t address, uint8_t reg_val)
00123 {
00124     uint16_t spi_data = address << 8;
00125     spi_data |= reg_val;
00126     write_spi(spi_data);
00127 }
00128 
00129 /**
00130  * @brief Writes 16bit data to the AD7790 SPI interface
00131  * @param reg_val to be written
00132  * @return data returned by the AD7790
00133  */
00134 uint16_t AD7124::write_spi(uint16_t reg_val)
00135 {
00136     uint16_t data_result;
00137     uint8_t upper_byte = (reg_val >> 8) & 0xFF;
00138     uint8_t lower_byte = reg_val & 0xFF;
00139     ad7124.format(8, _SPI_MODE);
00140     cs = false;
00141     data_result  =  (ad7124.write(upper_byte) << 8);
00142     data_result |=   ad7124.write(lower_byte);
00143     cs = true;
00144     return data_result;
00145 }
00146 
00147 
00148 
00149 /***************************************************************************//**
00150 * @brief Reads the value of the specified register without checking if the
00151 *        device is ready to accept user requests.
00152 *
00153 * @param device - The handler of the instance of the driver.
00154 * @param pReg - Pointer to the register structure holding info about the
00155 *               register to be read. The read value is stored inside the
00156 *               register structure.
00157 *
00158 * @return Returns 0 for success or negative error code.
00159 *******************************************************************************/
00160 int32_t AD7124::NoCheckReadRegister(ad7124_st_reg* pReg)
00161 {
00162     int32_t ret       = 0;
00163     uint8_t buffer[8] = {0, 0, 0, 0, 0, 0, 0, 0};
00164     uint8_t i         = 0;
00165     uint8_t check8    = 0;
00166     uint8_t msgBuf[8] = {0, 0, 0, 0, 0, 0, 0, 0};
00167 
00168 
00169     check8 = useCRC;
00170 
00171     /* Build the Command word */
00172     buffer[0] = AD7124_COMM_REG_WEN | AD7124_COMM_REG_RD |
00173                 AD7124_COMM_REG_RA(pReg->addr);
00174 
00175     /* Read data from the device */
00176     ret = SPI_Read(buffer,
00177                    ((useCRC != AD7124_DISABLE_CRC) ? pReg->size + 1
00178                     : pReg->size) + 1);
00179     if(ret < 0)
00180         return ret;
00181 
00182     /* Check the CRC */
00183     if(check8 == AD7124_USE_CRC) {
00184         msgBuf[0] = AD7124_COMM_REG_WEN | AD7124_COMM_REG_RD |
00185                     AD7124_COMM_REG_RA(pReg->addr);
00186         for(i = 1; i < pReg->size + 2; ++i) {
00187             msgBuf[i] = buffer[i];
00188         }
00189         check8 = ComputeCRC8 (msgBuf, pReg->size + 2);
00190     }
00191 
00192     if(check8 != 0) {
00193         /* ReadRegister checksum failed. */
00194         return COMM_ERR;
00195     }
00196 
00197     /* Build the result */
00198     pReg->value = 0;
00199     for(i = 1; i < pReg->size + 1; i++) {
00200         pReg->value <<= 8;
00201         pReg->value += buffer[i];
00202     }
00203 
00204     return ret;
00205 }
00206 
00207 /***************************************************************************//**
00208 * @brief Writes the value of the specified register without checking if the
00209 *        device is ready to accept user requests.
00210 *
00211 * @param device - The handler of the instance of the driver.
00212 * @param reg - Register structure holding info about the register to be written
00213 *
00214 * @return Returns 0 for success or negative error code.
00215 *******************************************************************************/
00216 int32_t AD7124::NoCheckWriteRegister(ad7124_st_reg reg)
00217 {
00218     int32_t ret      = 0;
00219     int32_t regValue = 0;
00220     uint8_t wrBuf[8] = {0, 0, 0, 0, 0, 0, 0, 0};
00221     uint8_t i        = 0;
00222     uint8_t crc8     = 0;
00223 
00224 
00225     /* Build the Command word */
00226     wrBuf[0] = AD7124_COMM_REG_WEN | AD7124_COMM_REG_WR |
00227                AD7124_COMM_REG_RA(reg.addr);
00228 
00229     /* Fill the write buffer */
00230     regValue = reg.value;
00231     for(i = 0; i < reg.size; i++) {
00232         wrBuf[reg.size - i] = regValue & 0xFF;
00233         regValue >>= 8;
00234     }
00235 
00236     /* Compute the CRC */
00237     if(useCRC != AD7124_DISABLE_CRC) {
00238         crc8 = ComputeCRC8 (wrBuf, reg.size + 1);
00239         wrBuf[reg.size + 1] = crc8;
00240     }
00241 
00242     /* Write data to the device */
00243     ret = SPI_Write(wrBuf,
00244                     (useCRC != AD7124_DISABLE_CRC) ? reg.size + 2
00245                     : reg.size + 1);
00246 
00247     return ret;
00248 }
00249 
00250 /***************************************************************************//**
00251 * @brief Reads the value of the specified register only when the device is ready
00252 *        to accept user requests. If the device ready flag is deactivated the
00253 *        read operation will be executed without checking the device state.
00254 *
00255 * @param device - The handler of the instance of the driver.
00256 * @param pReg - Pointer to the register structure holding info about the
00257 *               register to be read. The read value is stored inside the
00258 *               register structure.
00259 *
00260 * @return Returns 0 for success or negative error code.
00261 *******************************************************************************/
00262 int32_t AD7124::ReadRegister(ad7124_st_reg* pReg)
00263 {
00264     int32_t ret;
00265 
00266     if (pReg->addr != ERR_REG && check_ready) {
00267         ret = WaitForSpiReady (spi_rdy_poll_cnt);
00268         if (ret < 0)
00269             return ret;
00270     }
00271     ret = NoCheckReadRegister(pReg);
00272 
00273     return ret;
00274 }
00275 
00276 /***************************************************************************//**
00277 * @brief Writes the value of the specified register only when the device is
00278 *        ready to accept user requests. If the device ready flag is deactivated
00279 *        the write operation will be executed without checking the device state.
00280 *
00281 * @param device - The handler of the instance of the driver.
00282 * @param reg - Register structure holding info about the register to be written
00283 *
00284 * @return Returns 0 for success or negative error code.
00285 *******************************************************************************/
00286 int32_t AD7124::WriteRegister(ad7124_st_reg pReg)
00287 {
00288     int32_t ret;
00289 
00290     if (check_ready) {
00291         ret = WaitForSpiReady (spi_rdy_poll_cnt);
00292         if (ret < 0)
00293             return ret;
00294     }
00295     ret = NoCheckWriteRegister(pReg);
00296 
00297     return ret;
00298 }
00299 
00300 /***************************************************************************//**
00301 * @brief Reads and returns the value of a device register. The read value is
00302 *        also stored in software register list of the device.
00303 *
00304 * @param device - The handler of the instance of the driver.
00305 * @param reg - Which register to read from.
00306 * @param pError - Pointer to the location where to store the error code if an
00307 *                 error occurs. Stores 0 for success or negative error code.
00308 *                 Does not store anything if pErorr = NULL;
00309 *
00310 * @return Returns the value read from the specified register.
00311 *******************************************************************************/
00312 uint32_t AD7124::ReadDeviceRegister(enum ad7124_registers reg)
00313 {
00314     ReadRegister(&regs[reg]);
00315     return (regs[reg].value);
00316 }
00317 
00318 /***************************************************************************//**
00319 * @brief Writes the specified value to a device register. The value to be
00320 *        written is also stored in the software register list of the device.
00321 *
00322 * @param device - The handler of the instance of the driver.
00323 * @param reg - Which register to write to.
00324 * @param value - The value to be written to the reigster of the device.
00325 *
00326 * @return Returns 0 for success or negative error code.
00327 *******************************************************************************/
00328 int32_t AD7124::WriteDeviceRegister(enum ad7124_registers reg, uint32_t value)
00329 {
00330     regs[reg].value = value;
00331     return(WriteRegister(regs[reg]));
00332 }
00333 
00334 /***************************************************************************//**
00335 * @brief Resets the device.
00336 *
00337 * @param device - The handler of the instance of the driver.
00338 *
00339 * @return Returns 0 for success or negative error code.
00340 *******************************************************************************/
00341 int32_t AD7124::Reset()
00342 {
00343     int32_t ret = 0;
00344     uint8_t wrBuf[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
00345 
00346     ret = SPI_Write( wrBuf, 8);
00347 
00348 
00349     return ret;
00350 }
00351 
00352 /***************************************************************************//**
00353 * @brief Waits until the device can accept read and write user actions.
00354 *
00355 * @param device - The handler of the instance of the driver.
00356 * @param timeout - Count representing the number of polls to be done until the
00357 *                  function returns.
00358 *
00359 * @return Returns 0 for success or negative error code.
00360 *******************************************************************************/
00361 int32_t AD7124::WaitForSpiReady (uint32_t timeout)
00362 {
00363     ad7124_st_reg *regs;
00364     int32_t ret;
00365     int8_t ready = 0;
00366 
00367     regs = this->regs;
00368 
00369     while(!ready && --timeout) {
00370         /* Read the value of the Error Register */
00371         ret = ReadRegister(&regs[AD7124_Error]);
00372         if(ret < 0)
00373             return ret;
00374 
00375         /* Check the SPI IGNORE Error bit in the Error Register */
00376         ready = (regs[AD7124_Error].value &
00377                  AD7124_ERR_REG_SPI_IGNORE_ERR) == 0;
00378     }
00379 
00380     return timeout ? 0 : TIMEOUT;
00381 }
00382 
00383 /***************************************************************************//**
00384 * @brief Waits until a new conversion result is available.
00385 *
00386 * @param device - The handler of the instance of the driver.
00387 * @param timeout - Count representing the number of polls to be done until the
00388 *                  function returns if no new data is available.
00389 *
00390 * @return Returns 0 for success or negative error code.
00391 *******************************************************************************/
00392 int32_t AD7124::WaitForConvReady (uint32_t timeout)
00393 {
00394     ad7124_st_reg *regs;
00395     int32_t ret;
00396     int8_t ready = 0;
00397 
00398     regs = this->regs;
00399 
00400     while(!ready && --timeout) {
00401         /* Read the value of the Status Register */
00402         ret = ReadRegister(&regs[AD7124_Status]);
00403         if(ret < 0)
00404             return ret;
00405 
00406         /* Check the RDY bit in the Status Register */
00407         ready = (regs[AD7124_Status].value &
00408                  AD7124_STATUS_REG_RDY) == 0;
00409         wait_ms(1);
00410     }
00411 
00412     return timeout ? 0 : TIMEOUT;
00413 }
00414 
00415 bool AD7124::get_miso()
00416 {
00417     return miso.read();
00418 }
00419 
00420 /***************************************************************************//**
00421 * @brief Reads the conversion result from the device.
00422 *
00423 * @param device - The handler of the instance of the driver.
00424 * @param pData - Pointer to store the read data.
00425 *
00426 * @return Returns 0 for success or negative error code.
00427 *******************************************************************************/
00428 int32_t AD7124::ReadData ( int32_t* pData)
00429 {
00430     int32_t ret       = 0;
00431     uint8_t check8    = 0;
00432     uint8_t buffer[8] = {0, 0, 0, 0, 0, 0, 0, 0};
00433     uint8_t i         = 0;
00434     uint8_t msgBuf[8] = {0, 0, 0, 0, 0, 0, 0, 0};
00435     ad7124_st_reg *pReg;
00436 
00437     if( !pData)
00438         return INVALID_VAL;
00439 
00440     pReg = &regs[AD7124_Data];
00441 
00442     /* Build the Command word */
00443     buffer[0] = AD7124_COMM_REG_WEN | AD7124_COMM_REG_RD |
00444                 AD7124_COMM_REG_RA(pReg->addr);
00445 
00446 
00447     /* Read data from the device */
00448     ret = SPI_Read(buffer,
00449                    ((useCRC != AD7124_DISABLE_CRC) ? pReg->size + 1
00450                     : pReg->size) + 2);
00451 
00452     if(ret < 0)
00453         return ret;
00454 
00455     /* Check the CRC */
00456     if(check8 == AD7124_USE_CRC) {
00457         msgBuf[0] = AD7124_COMM_REG_WEN | AD7124_COMM_REG_RD |
00458                     AD7124_COMM_REG_RA(pReg->addr);
00459         for(i = 1; i < pReg->size + 2; ++i) {
00460             msgBuf[i] = buffer[i];
00461         }
00462         check8 = ComputeCRC8 (msgBuf, pReg->size + 3);
00463     }
00464 
00465     if(check8 != 0) {
00466         /* ReadRegister checksum failed. */
00467         return COMM_ERR;
00468     }
00469 
00470     /* Build the result */
00471     *pData = 0;
00472     for(i = 1; i < pReg->size + 2; i++) {
00473         *pData <<= 8;
00474         *pData += buffer[i];
00475     }
00476     wait_ms(500);
00477     return ret;
00478 }
00479 
00480 /***************************************************************************//**
00481 * @brief Computes the CRC checksum for a data buffer.
00482 *
00483 * @param pBuf - Data buffer
00484 * @param bufSize - Data buffer size in bytes
00485 *
00486 * @return Returns the computed CRC checksum.
00487 *******************************************************************************/
00488 uint8_t AD7124::ComputeCRC8 (uint8_t * pBuf, uint8_t bufSize)
00489 {
00490     uint8_t i   = 0;
00491     uint8_t crc = 0;
00492 
00493     while(bufSize) {
00494         for(i = 0x80; i != 0; i >>= 1) {
00495             if(((crc & 0x80) != 0) != ((*pBuf & i) != 0)) { /* MSB of CRC register XOR input Bit from Data */
00496                 crc <<= 1;
00497                 crc ^= AD7124_CRC8_POLYNOMIAL_REPRESENTATION;
00498             } else {
00499                 crc <<= 1;
00500             }
00501         }
00502         pBuf++;
00503         bufSize--;
00504     }
00505     return crc;
00506 }
00507 
00508 
00509 /***************************************************************************//**
00510 * @brief Updates the device SPI interface settings.
00511 *
00512 * @param device - The handler of the instance of the driver.
00513 *
00514 * @return None.
00515 *******************************************************************************/
00516 void AD7124::UpdateDevSpiSettings ()
00517 {
00518     ad7124_st_reg *regs;
00519 
00520     regs = this->regs;
00521 
00522     if (regs[AD7124_Error_En].value & AD7124_ERREN_REG_SPI_IGNORE_ERR_EN) {
00523         check_ready = 1;
00524     } else {
00525         check_ready = 0;
00526     }
00527 }
00528 
00529 /***************************************************************************//**
00530 * @brief Initializes the AD7124.
00531 *
00532 * @param device - The handler of the instance of the driver.
00533 * @param slave_select - The Slave Chip Select Id to be passed to the SPI calls.
00534 * @param regs - The list of registers of the device (initialized or not) to be
00535 *               added to the instance of the driver.
00536 *
00537 * @return Returns 0 for success or negative error code.
00538 *******************************************************************************/
00539 int32_t AD7124::Setup ()
00540 {
00541     int32_t ret;
00542     uint8_t regNr;
00543 
00544 
00545     spi_rdy_poll_cnt = 25000;
00546 
00547     /* Initialize the SPI communication. */
00548     /*ret = SPI_Init(0, 2500000, 1, 0);
00549     if (ret < 0)
00550         return ret;*/
00551 
00552     /*  Reset the device interface.*/
00553     ret = Reset();
00554     if (ret < 0)
00555         return ret;
00556 
00557     check_ready = 1;
00558 
00559     /* Initialize registers AD7124_ADC_Control through AD7124_Filter_7. */
00560     for(regNr = static_cast<uint8_t>(AD7124_Status); (regNr < static_cast<uint8_t>(AD7124_Offset_0)) && !(ret < 0);
00561             regNr++) {
00562         if (regs[regNr].rw == AD7124_RW) {
00563             ret = WriteRegister(regs[regNr]);
00564             if (ret < 0)
00565                 break;
00566         }
00567 
00568         /* Get CRC State and device SPI interface settings */
00569         if (regNr == AD7124_Error_En) {
00570             UpdateDevSpiSettings ();
00571         }
00572     }
00573 
00574     return ret;
00575 }
00576 
00577 uint8_t AD7124::SPI_Read(uint8_t *data, uint8_t bytes_number)
00578 {
00579     cs = false;
00580     for(uint8_t byte = 0; byte < bytes_number; byte++) {
00581         data[byte] = ad7124.write(data[byte]);
00582     }
00583     cs = true;
00584     return bytes_number;
00585 }
00586 
00587 uint8_t AD7124::SPI_Write(uint8_t *data, uint8_t bytes_number)
00588 {
00589     cs = false;
00590     for(uint8_t byte = 0; byte < bytes_number; byte++) {
00591         ad7124.write(data[byte]);
00592     }
00593 
00594     cs = true;
00595     return bytes_number;
00596 
00597 }