Pratyush Mallick / Mbed OS EVAL-AD4696

Dependencies:   platform_drivers

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ad469x.c Source File

ad469x.c

Go to the documentation of this file.
00001 /***************************************************************************//**
00002  *   @file   ad469x.c
00003  *   @brief  Implementation of ad469x Driver.
00004  *   @author Cristian Pop (cristian.pop@analog.com)
00005 ********************************************************************************
00006  * Copyright 2021(c) Analog Devices, Inc.
00007  *
00008  * All rights reserved.
00009  *
00010  * Redistribution and use in source and binary forms, with or without
00011  * modification, are permitted provided that the following conditions are met:
00012  *  - Redistributions of source code must retain the above copyright
00013  *    notice, this list of conditions and the following disclaimer.
00014  *  - Redistributions in binary form must reproduce the above copyright
00015  *    notice, this list of conditions and the following disclaimer in
00016  *    the documentation and/or other materials provided with the
00017  *    distribution.
00018  *  - Neither the name of Analog Devices, Inc. nor the names of its
00019  *    contributors may be used to endorse or promote products derived
00020  *    from this software without specific prior written permission.
00021  *  - The use of this software may or may not infringe the patent rights
00022  *    of one or more patent holders.  This license does not release you
00023  *    from the requirement that you obtain separate licenses from these
00024  *    patent holders to use this software.
00025  *  - Use of the software either in source or binary form, must be run
00026  *    on or directly connected to an Analog Devices Inc. component.
00027  *
00028  * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
00029  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
00030  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00031  * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
00032  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00033  * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
00034  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00035  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00036  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00037  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00038 *******************************************************************************/
00039 
00040 /******************************************************************************/
00041 /***************************** Include Files **********************************/
00042 /******************************************************************************/
00043 #include <string.h>
00044 #include <stdio.h>
00045 #include <stdlib.h>
00046 #include "ad469x.h"
00047 #include "delay.h"
00048 #include "error.h"
00049 #include "util.h"
00050 #include "gpio.h"
00051 
00052 #define AD469x_TEST_DATA 0xEA
00053 /******************************************************************************/
00054 /********************** Macros and Constants Definitions **********************/
00055 /******************************************************************************/
00056 
00057 /**
00058  * @brief Device resolution
00059  */
00060 const uint8_t ad469x_device_resol[] = {
00061     [AD469x_OSR_1] = 16,
00062     [AD469x_OSR_4] = 17,
00063     [AD469x_OSR_16] = 18,
00064     [AD469x_OSR_64] = 19
00065 };
00066 
00067 /******************************************************************************/
00068 /************************** Functions Implementation **************************/
00069 /******************************************************************************/
00070 
00071 /**
00072  * Read from device.
00073  * @param dev - The device structure.
00074  * @param reg_addr - The register address.
00075  * @param reg_data - The register data.
00076  * @return SUCCESS in case of success, negative error code otherwise.
00077  */
00078 int32_t ad469x_spi_reg_read(struct ad469x_dev *dev,
00079     uint16_t reg_addr,
00080     uint8_t *reg_data)
00081 {
00082     int32_t ret;
00083     uint8_t buf[3];
00084 
00085 #if defined (ENABLE_SPI_ENGINE)
00086     ret = spi_engine_set_transfer_width(dev->spi_desc, dev->reg_data_width);
00087     if (ret != SUCCESS)
00088         return ret;
00089 
00090     spi_engine_set_speed(dev->spi_desc, dev->reg_access_speed);
00091 #endif
00092 
00093     buf[0] = (1 << 7) | ((reg_addr >> 8) & 0x7F);
00094     buf[1] = 0xFF & reg_addr;
00095     buf[2] = 0xFF;
00096 
00097     ret = spi_write_and_read(dev->spi_desc, buf, 3);
00098     *reg_data = buf[2];
00099 
00100 #if defined (ENABLE_SPI_ENGINE)  
00101     ret = spi_engine_set_transfer_width(dev->spi_desc, dev->capture_data_width);
00102     if (ret != SUCCESS)
00103         return ret;
00104 
00105     spi_engine_set_speed(dev->spi_desc, dev->spi_desc->max_speed_hz);
00106 #endif
00107 
00108     return ret;
00109 }
00110 
00111 /**
00112  * Write to device.
00113  * @param dev - The device structure.
00114  * @param reg_addr - The register address.
00115  * @param reg_data - The register data.
00116  * @@eturn SUCCESS in case of success, negative error code otherwise.
00117  */
00118 int32_t ad469x_spi_reg_write(struct ad469x_dev *dev,
00119     uint16_t reg_addr,
00120     uint8_t reg_data)
00121 {
00122     int32_t ret;
00123     uint8_t buf[3];
00124 
00125 #if defined (ENABLE_SPI_ENGINE) 
00126     ret = spi_engine_set_transfer_width(dev->spi_desc, dev->reg_data_width);
00127     if (ret != SUCCESS)
00128         return ret;
00129 
00130     spi_engine_set_speed(dev->spi_desc, dev->reg_access_speed);
00131 #endif
00132 
00133     buf[0] = ((reg_addr >> 8) & 0x7F);
00134     buf[1] = 0xFF & reg_addr;
00135     buf[2] = reg_data;
00136 
00137     ret = spi_write_and_read(dev->spi_desc, buf, 3);
00138 
00139 #if defined (ENABLE_SPI_ENGINE)
00140     ret = spi_engine_set_transfer_width(dev->spi_desc,
00141         dev->capture_data_width);
00142     if (ret != SUCCESS)
00143         return ret;
00144 
00145     spi_engine_set_speed(dev->spi_desc, dev->spi_desc->max_speed_hz);
00146 #endif
00147 
00148     return ret;
00149 }
00150 
00151 /**
00152  * SPI read from device using a mask.
00153  * @param dev - The device structure.
00154  * @param reg_addr - The register address.
00155  * @param mask - The mask.
00156  * @param data - The register data.
00157  * @return SUCCESS in case of success, negative error code otherwise.
00158  */
00159 int32_t ad469x_spi_read_mask(struct ad469x_dev *dev,
00160     uint16_t reg_addr,
00161     uint8_t mask,
00162     uint8_t *data)
00163 {
00164     uint8_t reg_data[3];
00165     int32_t ret;
00166 
00167     ret = ad469x_spi_reg_read(dev, reg_addr, reg_data);
00168     if (ret != SUCCESS)
00169         return ret;
00170 
00171     *data = (reg_data[0] & mask);
00172 
00173     return ret;
00174 }
00175 
00176 /**
00177  * SPI write to device using a mask.
00178  * @param dev - The device structure.
00179  * @param reg_addr - The register address.
00180  * @param mask - The mask.
00181  * @param data - The register data.
00182  * @return SUCCESS in case of success, negative error code otherwise.
00183  */
00184 int32_t ad469x_spi_write_mask(struct ad469x_dev *dev,
00185     uint16_t reg_addr,
00186     uint8_t mask,
00187     uint8_t data)
00188 {
00189     uint8_t reg_data;
00190     int32_t ret;
00191 
00192     ret = ad469x_spi_reg_read(dev, reg_addr, &reg_data);
00193     if (ret != SUCCESS)
00194         return ret;
00195 
00196     reg_data &= ~mask;
00197     reg_data |= data;
00198 
00199     return ad469x_spi_reg_write(dev, reg_addr, reg_data);
00200 }
00201 
00202 /**
00203  * @brief Configure register access mode
00204  * @param [in] dev - ad469x_dev device handler.
00205  * @param [in] access - Access mode
00206  * @return \ref SUCCESS in case of success, \ref FAILURE otherwise.
00207  */
00208 int32_t ad469x_set_reg_access_mode(struct ad469x_dev *dev,
00209     enum ad469x_reg_access access)
00210 {
00211     return ad469x_spi_write_mask(dev,
00212         AD469x_REG_IF_CONFIG_C,
00213         AD469x_REG_IF_CONFIG_C_MB_STRICT_MASK,
00214         AD469x_REG_IF_CONFIG_C_MB_STRICT(access));
00215 }
00216 
00217 /**
00218  * @brief Initialize GPIO driver handlers for the GPIOs in the system.
00219  *        ad469x_init() helper function.
00220  * @param [out] dev - ad469x_dev device handler.
00221  * @param [in] init_param - Pointer to the initialization structure.
00222  * @return \ref SUCCESS in case of success, \ref FAILURE otherwise.
00223  */
00224 static int32_t ad469x_init_gpio(struct ad469x_dev *dev,
00225     struct ad469x_init_param *init_param)
00226 {
00227     int32_t ret;
00228 
00229     do 
00230     {
00231         ret = gpio_get_optional(&dev->gpio_resetn, init_param->gpio_resetn);
00232         if (ret != SUCCESS)
00233             break;
00234 
00235         /** Reset to configure pins */
00236         if (init_param->gpio_resetn) {
00237             ret = gpio_direction_output(dev->gpio_resetn, GPIO_LOW);
00238             if (ret != SUCCESS)
00239                 break;
00240 
00241             mdelay(100);
00242             ret = gpio_set_value(dev->gpio_resetn, GPIO_HIGH);
00243             if (ret != SUCCESS)
00244                 break;
00245 
00246             mdelay(100);
00247         }
00248     
00249         /** Initialize the BUSY GPIO descriptor **/
00250         ret = gpio_get_optional(&dev->gpio_busy, init_param->gpio_busy);
00251         if (ret != SUCCESS)
00252             break;
00253         
00254         if (init_param->gpio_busy) {
00255             if (gpio_direction_input(dev->gpio_busy) != SUCCESS)
00256                 break;
00257         }
00258         
00259         return SUCCESS;
00260     } while (0);
00261 
00262     return FAILURE;
00263 }
00264 
00265 /**
00266  * @brief Configure over sampling ratio in advanced sequencer mode
00267  * @param [in] dev - ad469x_dev device handler.
00268  * @param [in] ch - Channel to configure.
00269  * @param [in] ratio - OSR ratio.
00270  * @return \ref SUCCESS in case of success, \ref FAILURE otherwise.
00271  */
00272 int32_t ad469x_adv_seq_osr(struct ad469x_dev *dev,
00273     uint16_t ch,
00274     enum ad469x_osr_ratios ratio)
00275 {
00276     int32_t ret;
00277 
00278     if (dev->ch_sequence == AD469x_single_cycle ||
00279         dev->ch_sequence == AD469x_two_cycle)
00280         return FAILURE;
00281 
00282     if (ch >= AD469x_CHANNEL_NO)
00283         return FAILURE;
00284 
00285     ret = ad469x_spi_write_mask(dev,
00286         AD469x_REG_CONFIG_IN(ch),
00287         AD469x_REG_CONFIG_IN_OSR_MASK,
00288         AD469x_REG_CONFIG_IN_OSR(ratio));
00289     if (ret != SUCCESS)
00290         return ret;
00291 
00292     dev->adv_seq_osr_resol[ch] = ad469x_device_resol[ratio];
00293     /* Set storage to maximum data width */
00294     dev->capture_data_width = ad469x_device_resol[AD469x_OSR_64];
00295 
00296     return SUCCESS;
00297 }
00298 
00299 /**
00300  * @brief Configure over sampling ratio to 1 in single and two cycle modes.
00301  * @param [in] dev - ad469x_dev device handler.
00302  * @return \ref SUCCESS in case of success, \ref FAILURE otherwise.
00303  */
00304 static int32_t ad469x_seq_osr_clear(struct ad469x_dev *dev)
00305 {
00306     int32_t ret;
00307     uint8_t i = 0;
00308 
00309     for (i = 0; i < AD469x_CHANNEL_NO; i++) {
00310         ret = ad469x_spi_write_mask(dev,
00311             AD469x_REG_CONFIG_IN(i),
00312             AD469x_REG_CONFIG_IN_OSR_MASK,
00313             AD469x_REG_CONFIG_IN_OSR(AD469x_OSR_1));
00314         if (ret != SUCCESS)
00315             return ret;
00316         dev->adv_seq_osr_resol[i] = ad469x_device_resol[AD469x_OSR_1];
00317     }
00318     /* Set storage to minimum data width */
00319     dev->capture_data_width = ad469x_device_resol[AD469x_OSR_1];
00320 
00321     return SUCCESS;
00322 }
00323 
00324 /**
00325  * @brief Configure over sampling ratio in standard sequencer mode
00326  * @param [in] dev - ad469x_dev device handler.
00327  * @param [in] ratio - OSR ratio.
00328  * @return \ref SUCCESS in case of success, \ref FAILURE otherwise.
00329  */
00330 int32_t ad469x_std_seq_osr(struct ad469x_dev *dev, enum ad469x_osr_ratios ratio)
00331 {
00332     int ret;
00333 
00334     if (dev->ch_sequence == AD469x_single_cycle ||
00335         dev->ch_sequence == AD469x_two_cycle)
00336         return FAILURE;
00337 
00338     ret = ad469x_spi_write_mask(dev,
00339         AD469x_REG_CONFIG_IN(0),
00340         AD469x_REG_CONFIG_IN_OSR_MASK,
00341         AD469x_REG_CONFIG_IN_OSR(ratio));
00342     if (ret != SUCCESS)
00343         return ret;
00344 
00345     dev->capture_data_width = ad469x_device_resol[ratio];
00346 
00347     return ret;
00348 }
00349 
00350 /**
00351  * @brief Set channel sequence.
00352  * @param [in] dev - ad469x_dev device handler.
00353  * @param [in] seq - Channel sequence.
00354  * @return \ref SUCCESS in case of success, \ref FAILURE otherwise.
00355  */
00356 int32_t ad469x_set_channel_sequence(struct ad469x_dev *dev,
00357     enum ad469x_channel_sequencing seq)
00358 {
00359     int32_t ret;
00360 
00361     switch (seq) {
00362     case AD469x_single_cycle:
00363         ret = ad469x_spi_write_mask(dev,
00364             AD469x_REG_SEQ_CTRL,
00365             AD469x_SEQ_CTRL_STD_SEQ_EN_MASK,
00366             AD469x_SEQ_CTRL_STD_SEQ_EN(0));
00367         if (ret != SUCCESS)
00368             return ret;
00369 
00370         ret = ad469x_spi_write_mask(dev,
00371             AD469x_REG_SEQ_CTRL,
00372             AD469x_SEQ_CTRL_NUM_SLOTS_AS_MASK,
00373             AD469x_SEQ_CTRL_NUM_SLOTS_AS(0));
00374         if (ret != SUCCESS)
00375             return ret;
00376 
00377         ret = ad469x_spi_write_mask(dev,
00378             AD469x_REG_SETUP,
00379             AD469x_SETUP_CYC_CTRL_MASK,
00380             AD469x_SETUP_CYC_CTRL_SINGLE(0));
00381         if (ret != SUCCESS)
00382             return ret;
00383 
00384         ret = ad469x_seq_osr_clear(dev);
00385         if (ret != SUCCESS)
00386             return ret;
00387 
00388         break;
00389 
00390     case AD469x_two_cycle:
00391         ret = ad469x_spi_write_mask(dev,
00392             AD469x_REG_SEQ_CTRL,
00393             AD469x_SEQ_CTRL_STD_SEQ_EN_MASK,
00394             AD469x_SEQ_CTRL_STD_SEQ_EN(0));
00395         if (ret != SUCCESS)
00396             return ret;
00397 
00398         ret = ad469x_spi_write_mask(dev,
00399             AD469x_REG_SEQ_CTRL,
00400             AD469x_SEQ_CTRL_NUM_SLOTS_AS_MASK,
00401             AD469x_SEQ_CTRL_NUM_SLOTS_AS(0));
00402         if (ret != SUCCESS)
00403             return ret;
00404 
00405         ret = ad469x_spi_write_mask(dev,
00406             AD469x_REG_SETUP,
00407             AD469x_SETUP_CYC_CTRL_MASK,
00408             AD469x_SETUP_CYC_CTRL_SINGLE(1));
00409         if (ret != SUCCESS)
00410             return ret;
00411 
00412         ret = ad469x_seq_osr_clear(dev);
00413         if (ret != SUCCESS)
00414             return ret;
00415 
00416         break;
00417 
00418     case AD469x_standard_seq:
00419         ret = ad469x_spi_write_mask(dev,
00420             AD469x_REG_SEQ_CTRL,
00421             AD469x_SEQ_CTRL_STD_SEQ_EN_MASK,
00422             AD469x_SEQ_CTRL_STD_SEQ_EN(1));
00423         if (ret != SUCCESS)
00424             return ret;
00425 
00426         break;
00427 
00428     case AD469x_advanced_seq:
00429         ret = ad469x_spi_write_mask(dev,
00430             AD469x_REG_SEQ_CTRL,
00431             AD469x_SEQ_CTRL_STD_SEQ_EN_MASK,
00432             AD469x_SEQ_CTRL_STD_SEQ_EN(0));
00433         if (ret != SUCCESS)
00434             return ret;
00435 
00436         break;
00437 
00438     default:
00439         return FAILURE;
00440         break;
00441     }
00442 
00443     dev->ch_sequence = seq;
00444 
00445     return ret;
00446 }
00447 
00448 /**
00449  * @brief Configure advanced sequencer number of slots, temp channel not
00450  * included
00451  * @param [in] dev - ad469x_dev device handler.
00452  * @param [in] num_slots - Number of slots, max value = 0x7f
00453  * @return \ref SUCCESS in case of success, \ref FAILURE otherwise.
00454  */
00455 int32_t ad469x_adv_sequence_set_num_slots(struct ad469x_dev *dev,
00456     uint8_t num_slots)
00457 {
00458     int32_t ret;
00459     uint8_t write_num_slots = 0;
00460 
00461     if (num_slots)
00462         write_num_slots = num_slots - 1;
00463 
00464     ret = ad469x_spi_write_mask(dev,
00465         AD469x_REG_SEQ_CTRL,
00466         AD469x_SEQ_CTRL_NUM_SLOTS_AS_MASK,
00467         AD469x_SEQ_CTRL_NUM_SLOTS_AS(write_num_slots));
00468     if (ret != SUCCESS)
00469         return ret;
00470 
00471     dev->num_slots = num_slots;
00472 
00473     return SUCCESS;
00474 }
00475 
00476 /**
00477  * @brief Advanced sequencer, assign channel to a slot
00478  * @param [in] dev - ad469x_dev device handler.
00479  * @param [in] slot - Slot number [0x00, 0x7f]
00480  * @param [in] channel - Assigned channel [0x00, 0x0f].
00481  * @return \ref SUCCESS in case of success, \ref FAILURE otherwise.
00482  */
00483 int32_t ad469x_adv_sequence_set_slot(struct ad469x_dev *dev,
00484     uint8_t slot,
00485     uint8_t channel)
00486 {
00487     int32_t ret;
00488     ret = ad469x_spi_reg_write(dev,
00489         AD469x_REG_AS_SLOT(slot),
00490         AD469x_REG_AS_SLOT_INX(channel));
00491     if (ret != SUCCESS)
00492         return ret;
00493 
00494     dev->ch_slots[slot] = channel;
00495 
00496     return SUCCESS;
00497 }
00498 
00499 /**
00500  * @brief Configure standard sequencer channels
00501  * @param [in] dev - ad469x_dev device handler.
00502  * @param [in] ch_mask - Extra channels to activate.
00503  * @return \ref SUCCESS in case of success, \ref FAILURE otherwise.
00504  */
00505 int32_t ad469x_std_sequence_ch(struct ad469x_dev *dev, uint32_t ch_mask)
00506 {
00507     int32_t ret;
00508 
00509     ret = ad469x_spi_reg_write(dev,
00510         AD469x_REG_STD_SEQ_CONFIG,
00511         0xff & ch_mask);
00512     if (ret != SUCCESS)
00513         return ret;
00514 
00515     ret = ad469x_spi_reg_write(dev,
00516         AD469x_REG_STD_SEQ_CONFIG + 1,
00517         ch_mask >> 8);
00518     if (ret != SUCCESS)
00519         return ret;
00520 
00521     dev->num_slots = hweight8(ch_mask);
00522 
00523     return ret;
00524 }
00525 
00526 /**
00527  * @brief Enable temperature read at the end of the sequence, for standard and
00528  * advanced sequencer
00529  * @param [in] dev - ad469x_dev device handler.
00530  * @return \ref SUCCESS in case of success, \ref FAILURE otherwise.
00531  */
00532 int32_t ad469x_sequence_enable_temp(struct ad469x_dev *dev)
00533 {
00534     int32_t ret;
00535 
00536     ret = ad469x_spi_write_mask(dev,
00537         AD469x_REG_TEMP_CTRL,
00538         AD469x_REG_TEMP_CTRL_TEMP_EN_MASK,
00539         AD469x_REG_TEMP_CTRL_TEMP_EN(1));
00540     if (ret != SUCCESS)
00541         return ret;
00542 
00543     dev->temp_enabled = true;
00544 
00545     return ret;
00546 }
00547 
00548 /**
00549  * @brief Disable temperature read at the end of the sequence, for standard and
00550  * advanced sequencer
00551  * @param [in] dev - ad469x_dev device handler.
00552  * @return \ref SUCCESS in case of success, \ref FAILURE otherwise.
00553  */
00554 int32_t ad469x_sequence_disable_temp(struct ad469x_dev *dev)
00555 {
00556     int32_t ret;
00557 
00558     ret = ad469x_spi_write_mask(dev,
00559         AD469x_REG_TEMP_CTRL,
00560         AD469x_REG_TEMP_CTRL_TEMP_EN_MASK,
00561         AD469x_REG_TEMP_CTRL_TEMP_EN(0));
00562     if (ret != SUCCESS)
00563         return ret;
00564 
00565     dev->temp_enabled = false;
00566 
00567     return ret;
00568 }
00569 
00570 /**
00571  * @brief Configure converter busy indicator to the output of the specified port
00572  * @param [in] dev - ad469x_dev device handler.
00573  * @param [in] gp_sel - Port.
00574  * @return \ref SUCCESS in case of success, \ref FAILURE otherwise.
00575  */
00576 int32_t ad469x_set_busy(struct ad469x_dev *dev,
00577     enum ad469x_busy_gp_sel gp_sel)
00578 {
00579     int32_t ret;
00580 
00581     ret = ad469x_spi_write_mask(dev,
00582         AD469x_REG_GP_MODE,
00583         AD469x_GP_MODE_BUSY_GP_EN_MASK,
00584         AD469x_GP_MODE_BUSY_GP_EN(1));
00585     if (ret != SUCCESS)
00586         return ret;
00587 
00588 
00589     ret = ad469x_spi_write_mask(dev,
00590         AD469x_REG_GP_MODE,
00591         AD469x_GP_MODE_BUSY_GP_SEL_MASK,
00592         AD469x_GP_MODE_BUSY_GP_SEL(gp_sel));
00593     if (ret != SUCCESS)
00594         return ret;
00595 
00596 
00597     return ret;
00598 }
00599 
00600 /**
00601  * @brief Enter conversion mode.
00602  *        To exit conversion mode send a 5 bit conversion mode command
00603  *        AD469x_CMD_REG_CONFIG_MODE
00604  * @param [in] dev - ad469x_dev device handler.
00605  * @return \ref SUCCESS in case of success, \ref FAILURE otherwise.
00606  */
00607 int32_t ad469x_enter_conversion_mode(struct ad469x_dev *dev)
00608 {
00609     return ad469x_spi_write_mask(dev,
00610                      AD469x_REG_SETUP,
00611                      AD469x_SETUP_IF_MODE_MASK,
00612                      AD469x_SETUP_IF_MODE_CONV);
00613 }
00614 
00615 /**
00616  * @brief Exit conversion mode.
00617  *        Enter register mode to read/write registers
00618  * @param [in] dev - ad469x_dev device handler.
00619  * @return \ref SUCCESS in case of success, \ref FAILURE otherwise.
00620  */
00621 int32_t ad469x_exit_conversion_mode(struct ad469x_dev *dev)
00622 {
00623     int32_t ret ; 
00624     
00625 #if defined(ENABLE_SPI_ENGINE)
00626     uint32_t commands_data[1], buf;
00627     struct spi_engine_offload_message msg;
00628     uint32_t spi_eng_msg_cmds[3] = {
00629         CS_LOW,
00630         WRITE_READ(1),
00631         CS_HIGH
00632     };
00633 
00634     pwm_enable(dev->trigger_pwm_desc);
00635 
00636     commands_data[0] = AD469x_CMD_REG_CONFIG_MODE << 8;
00637 
00638     ret = spi_engine_offload_init(dev->spi_desc, dev->offload_init_param);
00639     if (ret != SUCCESS)
00640         return ret;
00641 
00642     msg.commands = spi_eng_msg_cmds;
00643     msg.no_commands = ARRAY_SIZE(spi_eng_msg_cmds);
00644     msg.rx_addr = (uint32_t)&buf;
00645     msg.commands_data = commands_data;
00646 
00647     ret = spi_engine_offload_transfer(dev->spi_desc, msg, 1);
00648     if (ret != SUCCESS)
00649         return ret;
00650 
00651     pwm_disable(dev->trigger_pwm_desc);
00652     if (ret != SUCCESS)
00653         return ret;
00654 #else
00655     uint8_t cmd = AD469x_CMD_REG_CONFIG_MODE; 
00656     
00657     ret = spi_write_and_read(dev->spi_desc, &cmd, 1);
00658     if (ret != SUCCESS)
00659         return ret;
00660 #endif
00661 
00662     return SUCCESS;
00663 }
00664 
00665 /**
00666  * @brief Advanced sequencer, get util data bits in a sample
00667  * @param [in] dev - ad469x_dev device handler.
00668  * @param [in] cur_sample - Current sample number
00669  * @param [in] sample - Sample data
00670  * @return \ref SUCCESS in case of success, \ref FAILURE otherwise.
00671  */
00672 static int32_t ad469x_adv_seq_osr_get_util_data(struct ad469x_dev *dev,
00673     uint16_t cur_sample,
00674     uint32_t *sample)
00675 {
00676     uint8_t cur_slot, cur_ch;
00677 
00678     cur_slot = cur_sample % (dev->num_slots + dev->temp_enabled);
00679     cur_ch = dev->ch_slots[cur_slot];
00680 
00681     /* Temperature channel sample */
00682     if (dev->temp_enabled && cur_slot == dev->num_slots)
00683         return SUCCESS;
00684 
00685     *sample = (*sample) >> (dev->capture_data_width -
00686                 dev->adv_seq_osr_resol[cur_ch]);
00687 
00688     return SUCCESS;
00689 }
00690 
00691 /**
00692  * @brief Read from device when converter has the channel sequencer activated.
00693  *        Enter register mode to read/write registers
00694  * @param [in] dev - ad469x_dev device handler.
00695  * @param [out] buf - data buffer.
00696  * @param [in] samples - Number of samples per channel. For example, if  with
00697  * ad469x_std_sequence_ch 2 channel where activated, buf will be filled with
00698  * 10 samples for each of them. If temp is enable, the there will be an other 10
00699  * samples for temperature
00700  * @return \ref SUCCESS in case of success, \ref FAILURE otherwise.
00701  */
00702 int32_t ad469x_seq_read_data(struct ad469x_dev *dev,
00703     uint32_t *buf,
00704     uint16_t samples)
00705 {
00706     int32_t ret;
00707     uint16_t i;
00708     uint32_t total_samples;
00709 
00710     total_samples = samples * (dev->num_slots + dev->temp_enabled);
00711     ret = ad469x_read_data(dev, 0, buf, total_samples);
00712     if (ret != SUCCESS)
00713         return ret;
00714 
00715     if (dev->ch_sequence != AD469x_advanced_seq)
00716         return SUCCESS;
00717 
00718     for (i = 0; i < total_samples; i++) {
00719         ret = ad469x_adv_seq_osr_get_util_data(dev, i, &buf[i]);
00720         if (ret != SUCCESS)
00721             return ret;
00722     }
00723 
00724     return SUCCESS;
00725 }
00726 
00727 /**
00728  * @brief Read from device.
00729  *        Enter register mode to read/write registers
00730  * @param [in] dev - ad469x_dev device handler.
00731  * @param [in] channel - ad469x selected channel.
00732  * @param [out] buf - data buffer.
00733  * @param [in] samples - sample number.
00734  * @return \ref SUCCESS in case of success, \ref FAILURE otherwise.
00735  */
00736 int32_t ad469x_read_data(struct ad469x_dev *dev,
00737     uint8_t channel,
00738     uint32_t *buf,
00739     uint16_t samples)
00740 {
00741     int32_t ret;
00742 
00743 #if defined(ENABLE_SPI_ENGINE)
00744     uint32_t commands_data[1];
00745     struct spi_engine_offload_message msg;
00746     uint32_t spi_eng_msg_cmds[3] = {
00747         CS_LOW,
00748         WRITE_READ(1),
00749         CS_HIGH
00750     };
00751     if (channel < AD469x_CHANNEL_NO)
00752         commands_data[0] = AD469x_CMD_CONFIG_CH_SEL(channel) << 8;
00753     else if (channel == AD469x_CHANNEL_TEMP)
00754         commands_data[0] = AD469x_CMD_SEL_TEMP_SNSOR_CH << 8;
00755     else
00756         return FAILURE;
00757 
00758     pwm_enable(dev->trigger_pwm_desc);
00759 
00760     ret = spi_engine_offload_init(dev->spi_desc, dev->offload_init_param);
00761     if (ret != SUCCESS)
00762         return ret;
00763     
00764     msg.commands = spi_eng_msg_cmds;
00765     msg.no_commands = ARRAY_SIZE(spi_eng_msg_cmds);
00766     msg.rx_addr = (uint32_t)buf;
00767     msg.commands_data = commands_data;
00768 
00769     ret = spi_engine_offload_transfer(dev->spi_desc, msg, samples * 2);
00770     if (ret != SUCCESS)
00771         return ret;
00772 
00773     if (dev->dcache_invalidate_range)
00774         dev->dcache_invalidate_range(msg.rx_addr, samples * 4);
00775 #else 
00776     // Dummy Data
00777     dev->data[0] = 0x0;
00778     dev->data[1] = 0x0;
00779     ret = spi_write_and_read(dev->spi_desc, dev->data, (samples * 2));
00780     if (ret != SUCCESS)
00781         return FAILURE;
00782         
00783     *buf = (uint16_t)(dev->data[0] << 8) | dev->data[1];
00784     
00785 #endif
00786     
00787     return ret;
00788 }
00789 
00790 /**
00791  * Initialize the device.
00792  * @param [out] device - The device structure.
00793  * @param [in] init_param - The structure that contains the device initial
00794  *      parameters.
00795  * @return \ref SUCCESS in case of success, \ref FAILURE otherwise.
00796  */
00797 int32_t ad469x_init(struct ad469x_dev **device,
00798     struct ad469x_init_param *init_param)
00799 {
00800     struct ad469x_dev *dev;
00801     int32_t ret;
00802     uint8_t data = 0;
00803 
00804     dev = (struct ad469x_dev *)malloc(sizeof(*dev));
00805     if (!dev)
00806         return FAILURE;
00807 
00808 #if defined(SPI_ENGINE)
00809     ret = axi_clkgen_init(&dev->clkgen, init_param->clkgen_init);
00810     if (ret != SUCCESS) {
00811         printf("error: %s: axi_clkgen_init() failed\n",
00812             init_param->clkgen_init->name);
00813         goto error_dev;
00814     }
00815 
00816     ret = axi_clkgen_set_rate(dev->clkgen, init_param->axi_clkgen_rate);
00817     if (ret != SUCCESS) {
00818         printf("error: %s: axi_clkgen_set_rate() failed\n",
00819             init_param->clkgen_init->name);
00820         goto error_clkgen;
00821     }
00822     
00823 #endif
00824 
00825     ret = ad469x_init_gpio(dev, init_param);
00826     if (ret != SUCCESS)
00827         goto error_gpio;
00828     
00829     ret = spi_init(&dev->spi_desc, init_param->spi_init);
00830     if (ret != SUCCESS)
00831         goto error_gpio;
00832 
00833     dev->offload_init_param = init_param->offload_init_param;
00834 
00835     dev->reg_access_speed = init_param->reg_access_speed;
00836     dev->reg_data_width = init_param->reg_data_width;
00837     dev->capture_data_width = init_param->capture_data_width;
00838     dev->dev_id = init_param->dev_id;
00839     dev->dcache_invalidate_range = init_param->dcache_invalidate_range;
00840     dev->ch_sequence = AD469x_standard_seq;
00841     dev->num_slots = 0;
00842     dev->temp_enabled = false;
00843     memset(dev->ch_slots, 0, sizeof(dev->ch_slots));
00844     
00845     ret = ad469x_spi_reg_write(dev, AD469x_REG_SCRATCH_PAD, AD469x_TEST_DATA);
00846     if (ret != SUCCESS)
00847         goto error_spi;
00848     
00849     ret = ad469x_spi_reg_read(dev, AD469x_REG_SCRATCH_PAD, &data);
00850     if (ret != SUCCESS)
00851         goto error_spi;
00852 
00853     if (data != AD469x_TEST_DATA)
00854         goto error_spi;
00855 
00856     ret = ad469x_set_reg_access_mode(dev, AD469x_BYTE_ACCESS);
00857     if (ret != SUCCESS)
00858         goto error_spi;
00859 
00860     ret = ad469x_set_busy(dev, AD469x_busy_gp0);
00861     if (ret != SUCCESS)
00862         goto error_spi;
00863 
00864     ret = ad469x_seq_osr_clear(dev);
00865     if (ret != SUCCESS)
00866         goto error_spi;
00867 
00868 #if defined(SPI_ENGINE)
00869     ret = pwm_init(&dev->trigger_pwm_desc, init_param->trigger_pwm_init);
00870     if (ret != SUCCESS)
00871         goto error_spi;
00872 #endif
00873 
00874 
00875     *device = dev;
00876 
00877     return ret;
00878 
00879 error_spi:
00880     spi_remove(dev->spi_desc);
00881 error_gpio:
00882     gpio_remove(dev->gpio_resetn);
00883     
00884 #if defined(SPI_ENGINE)
00885 error_clkgen:
00886     axi_clkgen_remove(dev->clkgen);
00887 error_dev:
00888 #endif
00889     
00890     free(dev);
00891 
00892     return FAILURE;
00893     
00894 }
00895 
00896 /**
00897  * @brief Free the memory allocated by ad469x_init().
00898  * @param [in] dev - Pointer to the device handler.
00899  * @return \ref SUCCESS in case of success, \ref FAILURE otherwise
00900  */
00901 int32_t ad469x_remove(struct ad469x_dev *dev)
00902 {
00903     int32_t ret;
00904 
00905     if (!dev)
00906         return FAILURE;
00907     
00908     ret = spi_remove(dev->spi_desc);
00909     if (ret != SUCCESS)
00910         return ret;
00911 
00912     ret = gpio_remove(dev->gpio_resetn);
00913     if (ret != SUCCESS)
00914         return ret;
00915     
00916     ret = gpio_remove(dev->gpio_convst);
00917     if (ret != SUCCESS)
00918         return ret;
00919     
00920     ret = gpio_remove(dev->gpio_busy);
00921     if (ret != SUCCESS)
00922         return ret;
00923 
00924 #if defined(SPI_ENGINE)
00925     ret = pwm_remove(dev->trigger_pwm_desc);
00926     if (ret != SUCCESS)
00927         return ret;
00928     
00929     ret = axi_clkgen_remove(dev->clkgen);
00930     if (ret != SUCCESS)
00931         return ret;
00932 #endif
00933 
00934     free(dev);
00935 
00936     return ret;
00937 }