You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by ma...@apache.org on 2019/04/30 11:16:20 UTC
[mynewt-core] branch master updated: gpadc_da1469x;
add knob to run through ADC calibration sequence when device is
opened.
This is an automated email from the ASF dual-hosted git repository.
marko pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git
The following commit(s) were added to refs/heads/master by this push:
new 04e88c1 gpadc_da1469x; add knob to run through ADC calibration sequence when device is opened.
new a998f40 Merge pull request #1786 from mkiiskila/da1469x_gpadc_calibrate
04e88c1 is described below
commit 04e88c1121289571c690bf1deeb17baf1fcdaed9
Author: Marko Kiiskila <ma...@apache.org>
AuthorDate: Mon Apr 29 19:24:21 2019 +0300
gpadc_da1469x; add knob to run through ADC calibration sequence
when device is opened.
---
.../include/gpadc_da1469x/gpadc_da1469x.h | 15 +--
hw/drivers/adc/gpadc_da1469x/src/gpadc_da1469x.c | 118 ++++++++++++++++++++-
2 files changed, 122 insertions(+), 11 deletions(-)
diff --git a/hw/drivers/adc/gpadc_da1469x/include/gpadc_da1469x/gpadc_da1469x.h b/hw/drivers/adc/gpadc_da1469x/include/gpadc_da1469x/gpadc_da1469x.h
index 387cf82..c8bf3e3 100644
--- a/hw/drivers/adc/gpadc_da1469x/include/gpadc_da1469x/gpadc_da1469x.h
+++ b/hw/drivers/adc/gpadc_da1469x/include/gpadc_da1469x/gpadc_da1469x.h
@@ -43,13 +43,14 @@ struct da1469x_gpadc_init_cfg {
};
struct da1469x_gpadc_dev_cfg {
- uint32_t dgdc_gpadc_ctrl;
- uint32_t dgdc_gpadc_ctrl2;
- uint32_t dgdc_gpadc_ctrl3;
- uint8_t dgdc_gpadc_set_offp:1;
- uint8_t dgdc_gpadc_set_offn:1;
- uint32_t dgdc_gpadc_offp;
- uint32_t dgdc_gpadc_offn;
+ uint32_t dgdc_gpadc_ctrl; /* GP_ADC_CTRL_REG */
+ uint32_t dgdc_gpadc_ctrl2; /* GP_ADC_CTRL2_REG */
+ uint32_t dgdc_gpadc_ctrl3; /* GP_ADC_CTRL3_REG */
+ uint8_t dgdc_gpadc_set_offp:1; /* Set GP_ADC_OFFP explicitly */
+ uint8_t dgdc_gpadc_set_offn:1; /* Set GP_ADC_OFFN explicitly */
+ uint8_t dgdc_gpadc_autocalibrate:1; /* Set offp/offn automatically */
+ uint32_t dgdc_gpadc_offp; /* GP_ADC_OFFP (when _set_offp set) */
+ uint32_t dgdc_gpadc_offn; /* GP_ADC_OFFN (when _set_offn set) */
};
struct da1469x_gpadc_chan_cfg {
diff --git a/hw/drivers/adc/gpadc_da1469x/src/gpadc_da1469x.c b/hw/drivers/adc/gpadc_da1469x/src/gpadc_da1469x.c
index a913f72..28b5031 100644
--- a/hw/drivers/adc/gpadc_da1469x/src/gpadc_da1469x.c
+++ b/hw/drivers/adc/gpadc_da1469x/src/gpadc_da1469x.c
@@ -171,7 +171,7 @@ da1469x_gpadc_configure_channel(struct adc_dev *adev, uint8_t cnum,
* Blocking read of an ADC channel, returns result as an integer.
*/
static int
-da1469x_gpadc_read_channel(struct adc_dev *adev, uint8_t cnum, int *result)
+da1469x_gpadc_read(uint32_t *val)
{
uint32_t reg;
@@ -199,17 +199,39 @@ da1469x_gpadc_read_channel(struct adc_dev *adev, uint8_t cnum, int *result)
reg = GPADC->GP_ADC_CTRL_REG;
} while ((reg & GPADC_GP_ADC_CTRL_REG_GP_ADC_INT_Msk) == 0);
+ *val = GPADC->GP_ADC_RESULT_REG;
+
+ return 0;
+}
+
+static int
+da1469x_gpadc_read_scaled(uint32_t *val)
+{
+ if (da1469x_gpadc_read(val)) {
+ return -1;
+ }
+ *val = *val >> 6;
+ return 0;
+}
+
+static int
+da1469x_gpadc_read_channel(struct adc_dev *adev, uint8_t cnum, int *result)
+{
+ uint32_t val;
+
+ da1469x_gpadc_read(&val);
+
/*
* Read results. # of valid bits depends on settings.
*/
- if (reg & GPADC_GP_ADC_CTRL_REG_GP_ADC_SE_Msk) {
- *result = GPADC->GP_ADC_RESULT_REG;
+ if (GPADC->GP_ADC_CTRL_REG & GPADC_GP_ADC_CTRL_REG_GP_ADC_SE_Msk) {
+ *result = val;
} else {
/*
* Differential mode.
* 0x8000 is 0V. Move that point to be 0.
*/
- *result = GPADC->GP_ADC_RESULT_REG - 0x8000;
+ *result = val - 0x8000;
}
return 0;
}
@@ -378,6 +400,90 @@ static const struct adc_driver_funcs da1469x_gpadc_funcs = {
.af_size_buffer = da1469x_gpadc_size_buffer
};
+/*
+ * Run through calibration sequence as described in datasheet.
+ */
+static int
+da1469x_gpadc_calibrate(struct da1469x_gpadc_dev *dev)
+{
+ uint32_t adc_off_p;
+ uint32_t adc_off_n;
+ uint32_t orig_ctrl;
+ int i;
+
+ orig_ctrl = GPADC->GP_ADC_CTRL_REG;
+
+ /*
+ * Only attempt this few times. If calibration fails, still go ahead.
+ */
+ for (i = 0; i < 5; i++) {
+ /*
+ * Step 1. Set up registers.
+ */
+ GPADC->GP_ADC_OFFP_REG = 0x200;
+ GPADC->GP_ADC_OFFN_REG = 0x200;
+
+ GPADC->GP_ADC_CTRL_REG =
+ (orig_ctrl & ~GPADC_GP_ADC_CTRL_REG_GP_ADC_SIGN_Msk) |
+ GPADC_GP_ADC_CTRL_REG_GP_ADC_MUTE_Msk;
+
+ /*
+ * Step 2. Run conversion.
+ */
+ if (da1469x_gpadc_read_scaled(&adc_off_p)) {
+ return -1;
+ }
+
+ /*
+ * Step 3.
+ */
+ adc_off_p -= 0x200;
+
+ /*
+ * Step 4; reconfigure register.
+ */
+ GPADC->GP_ADC_CTRL_REG |= GPADC_GP_ADC_CTRL_REG_GP_ADC_SIGN_Msk;
+
+ /*
+ * Step 5. Run conversion.
+ */
+ if (da1469x_gpadc_read_scaled(&adc_off_n)) {
+ return -1;
+ }
+
+ /*
+ * Step 6.
+ */
+ adc_off_n -= 0x200;
+
+ /*
+ * Step 7.
+ */
+ if (GPADC->GP_ADC_CTRL_REG & GPADC_GP_ADC_CTRL_REG_GP_ADC_SE_Msk) {
+ GPADC->GP_ADC_OFFP_REG = 0x200 - (adc_off_p * 2);
+ GPADC->GP_ADC_OFFN_REG = 0x200 - (adc_off_n * 2);
+ } else {
+ GPADC->GP_ADC_OFFP_REG = 0x200 - adc_off_p;
+ GPADC->GP_ADC_OFFN_REG = 0x200 - adc_off_n;
+ }
+
+ /*
+ * Step 8. Verify results.
+ */
+ GPADC->GP_ADC_CTRL_REG &= ~GPADC_GP_ADC_CTRL_REG_GP_ADC_SIGN_Msk;
+ if (da1469x_gpadc_read_scaled(&adc_off_p)) {
+ return -1;
+ }
+ adc_off_p = abs(0x200 - adc_off_p);
+ if (adc_off_p < 0x8) {
+ break;
+ }
+ }
+ assert(i != 5);
+ GPADC->GP_ADC_CTRL_REG = orig_ctrl;
+ return 0;
+}
+
static int
da1469x_gpadc_hwinit(struct da1469x_gpadc_dev *dev,
struct da1469x_gpadc_dev_cfg *dgdc)
@@ -449,6 +555,10 @@ da1469x_gpadc_hwinit(struct da1469x_gpadc_dev *dev,
GPADC->GP_ADC_OFFN_REG = reg;
}
+ if (dgdc->dgdc_gpadc_autocalibrate) {
+ return da1469x_gpadc_calibrate(dev);
+ }
+
return 0;
}