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; }