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.
Dependencies: platform_drivers
ad469x.c
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, ®_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 }
Generated on Thu Jul 21 2022 03:20:48 by
1.7.2