From 86ea16a1de4cbc9ae7bd7c7587e1242d447a21f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Sarzy=C5=84ski?= Date: Wed, 5 Oct 2022 14:52:31 +0200 Subject: [PATCH] ad7779: apply a sync pulse after configuration JIRA: DTR-342 --- adc/ad7779/ad7779-driver.c | 15 +++++++++ adc/ad7779/ad7779.c | 66 +++++++++++++++++++++++++++++--------- adc/ad7779/ad7779.h | 2 ++ 3 files changed, 67 insertions(+), 16 deletions(-) diff --git a/adc/ad7779/ad7779-driver.c b/adc/ad7779/ad7779-driver.c index 6ae501479..fac91832c 100644 --- a/adc/ad7779/ad7779-driver.c +++ b/adc/ad7779/ad7779-driver.c @@ -136,6 +136,12 @@ static int dev_ctl(msg_t *msg) res = ad7779_set_enabled_channels(dev_ctl.config.enabled_ch); if (res == AD7779_ARG_ERROR) return -EINVAL; + if (res != AD7779_OK) + return -EIO; + /* NOTE: Here SYNC_IN is not required by the docs, but sometimes after + * turning on/off channels we encounter unexpected ADC hang-ups (SPI + * works but we don't get DRDY). Applying SYNC solves the issue. */ + res = ad7779_pulse_sync(); if (res != AD7779_OK) return -EIO; return EOK; @@ -175,6 +181,9 @@ static int dev_ctl(msg_t *msg) res = ad7779_set_channel_mode(dev_ctl.ch_config.channel, mode); if (res == AD7779_ARG_ERROR) return -EINVAL; + if (res != AD7779_OK) + return -EIO; + res = ad7779_pulse_sync(); if (res != AD7779_OK) return -EIO; return EOK; @@ -213,6 +222,9 @@ static int dev_ctl(msg_t *msg) res = ad7779_set_channel_gain(dev_ctl.gain.channel, dev_ctl.gain.val); if (res == AD7779_ARG_ERROR) return -EINVAL; + if (res != AD7779_OK) + return -EIO; + res = ad7779_pulse_sync(); if (res != AD7779_OK) return -EIO; return EOK; @@ -235,6 +247,9 @@ static int dev_ctl(msg_t *msg) res = ad7779_set_channel_gain_correction(dev_ctl.calib.channel, dev_ctl.calib.gain); if (res == AD7779_ARG_ERROR) return -EINVAL; + if (res != AD7779_OK) + return -EIO; + res = ad7779_pulse_sync(); if (res != AD7779_OK) return -EIO; return EOK; diff --git a/adc/ad7779/ad7779.c b/adc/ad7779/ad7779.c index 7f9fa6a12..049ffb349 100644 --- a/adc/ad7779/ad7779.c +++ b/adc/ad7779/ad7779.c @@ -76,6 +76,13 @@ #define AD7779_READ_BIT (0x80) +/* AD7779_STATUS_REG_3 */ +#define INIT_COMPLETE_BIT (1 << 4) + +/* AD7779_GEN_ERR_REG_2 */ +#define RESET_DETECTED_BIT (1 << 5) + + static int ad7779_read(uint8_t addr, uint8_t *data, uint8_t len) { uint8_t buff[len + 1]; @@ -181,6 +188,27 @@ int ad7779_get_mode(ad7779_mode_t *mode) return AD7779_OK; } +int ad7779_pulse_sync(void) +{ + int res; + + log_debug("resetting internal logic"); + res = ad7779_gpio(start, 0); + if (res != 0) { + log_error("failed to set start GPIO to 0"); + return AD7779_GPIO_IO_ERROR; + } + + usleep(2); + res = ad7779_gpio(start, 1); + if (res != 0) { + log_error("failed to set start GPIO to 1"); + return AD7779_GPIO_IO_ERROR; + } + + return AD7779_OK; +} + int ad7779_set_mode(ad7779_mode_t mode) { if (mode == ad7779_mode__high_resolution) @@ -267,13 +295,6 @@ int ad7779_set_sampling_rate(uint32_t fs) if ((res = ad7779_set_clear_bits(AD7779_SRC_UPDATE, SRC_LOAD_UPDATE_BIT, 0)) < 0) return res; - /* Reset internal logic */ - log_debug("reseting internal logic"); - if ((res = ad7779_set_clear_bits(AD7779_GENERAL_USER_CONFIG_2, 0, SPI_SYNC)) < 0) - return res; - if ((res = ad7779_set_clear_bits(AD7779_GENERAL_USER_CONFIG_2, SPI_SYNC, 0)) < 0) - return res; - return AD7779_OK; } @@ -543,25 +564,34 @@ static int ad7779_reset(int hard) } /* Software reset */ - ad7779_gpio(start, 0); - usleep(10000); ad7779_gpio(reset, 0); - usleep(200000); - ad7779_gpio(start, 1); - usleep(100000); + usleep(2); ad7779_gpio(reset, 1); + usleep(300); memset(status, 0, sizeof(status)); for (i = 0; i < 4; ++i) { - if (!ad7779_get_status(status)) { - if (status[16] & 0x10) - return AD7779_OK; + if (ad7779_get_status(status) != AD7779_OK) { + usleep(100 * 1000); + continue; } - usleep(100000); + if ((status[16] & INIT_COMPLETE_BIT) && (status[13] & RESET_DETECTED_BIT)) { + return AD7779_OK; + } + else { + if (!(status[16] & INIT_COMPLETE_BIT)) { + log_error("init bit not detected"); + } + if (!(status[13] & RESET_DETECTED_BIT)) { + log_error("reset bit not detected"); + } + break; + } } + log_error("failed to read status after the device restart"); return AD7779_CTRL_IO_ERROR; } @@ -598,6 +628,10 @@ int ad7779_init(int hard) if ((res = ad7779_set_mode(ad7779_mode__high_resolution)) < 0) return res; + /* Toggle START (to generate SYNC_IN) after mode change */ + if ((res = ad7779_pulse_sync()) < 0) + return res; + /* Use one DOUTx line; DCLK_CLK_DIV = 1 */ log_debug("setting DOUT_FORMAT"); if ((res = ad7779_write_reg(AD7779_DOUT_FORMAT, 0xe0)) < 0) diff --git a/adc/ad7779/ad7779.h b/adc/ad7779/ad7779.h index a7e931ec9..d096ee5e8 100644 --- a/adc/ad7779/ad7779.h +++ b/adc/ad7779/ad7779.h @@ -89,6 +89,8 @@ int ad7779_set_channel_gain_correction(uint8_t channel, uint32_t gain); int ad7779_get_status(uint8_t *status_buf); +int ad7779_pulse_sync(void); + /* For debugging purposes */ int ad7779_print_status(void);