BV: unify ADC readout

This commit is contained in:
King Kévin 2018-02-26 14:56:23 +01:00
parent b04fcb7d3e
commit db930f645c
1 changed files with 32 additions and 47 deletions

View File

@ -85,49 +85,7 @@ void busvoodoo_setup(void)
busvoodoo_safe_state(); // also put the full version pins in safe state
}
// setup ADC to measure hardware version voltage
rcc_periph_clock_enable(RCC_ADC12_IN(BUSVOODOO_HW_VERSION_CHANNEL)); // enable clock for GPIO domain for hardware version channel
gpio_set_mode(ADC12_IN_PORT(BUSVOODOO_HW_VERSION_CHANNEL), GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, ADC12_IN_PIN(BUSVOODOO_HW_VERSION_CHANNEL)); // set hardware version channel as analogue input for the ADC
rcc_periph_clock_enable(RCC_ADC1); // enable clock for ADC domain
adc_off(ADC1); // switch off ADC while configuring it
adc_set_sample_time_on_all_channels(ADC1, ADC_SMPR_SMP_28DOT5CYC); // use 28.5 cycles to sample (long enough to be stable)
adc_enable_temperature_sensor(ADC1); // enable internal voltage reference
adc_enable_external_trigger_regular(ADC1, ADC_CR2_EXTSEL_SWSTART); // use software trigger to start conversion
uint8_t version_channels[] = {ADC_CHANNEL17, ADC_CHANNEL(BUSVOODOO_HW_VERSION_CHANNEL)}; // voltages to convert: internal, hardware version
adc_set_regular_sequence(ADC1, LENGTH(version_channels), version_channels); // set channels to convert
adc_enable_discontinuous_mode_regular(ADC1, LENGTH(version_channels)); // convert all channels
adc_power_on(ADC1); // switch on ADC
sleep_us(1); // wait t_stab for the ADC to stabilize
adc_reset_calibration(ADC1); // remove previous non-calibration
adc_calibration(ADC1); // calibrate ADC for less accuracy errors
adc_start_conversion_regular(ADC1); // start conversion to get first voltage
uint16_t channels[LENGTH(version_channels)] = {0}; // to store the values measured on the channels
for (uint8_t channel_i=0; channel_i<LENGTH(channels); channel_i++) { // get all conversions
while (!adc_eoc(ADC1)); // wait until conversion finished
channels[channel_i] = adc_read_regular(ADC1); // read voltage value (clears flag)
}
float version_voltage = channels[1]*1.2/channels[0]; // calculate voltage
// find out version of the board
gpio_set_mode(GPIO(BUSVOODOO_HW_VERSION_PORT), GPIO_MODE_INPUT, GPIO_CNF_INPUT_PULL_UPDOWN, GPIO(BUSVOODOO_HW_VERSION_PIN)); // use pull up and down to check if a voltage divider is present on the pin
gpio_set(GPIO(BUSVOODOO_HW_VERSION_PORT), GPIO(BUSVOODOO_HW_VERSION_PIN)); // pull up
bool version_up = (0!=gpio_get(GPIO(BUSVOODOO_HW_VERSION_PORT), GPIO(BUSVOODOO_HW_VERSION_PIN))); // check if the signal is still up
gpio_clear(GPIO(BUSVOODOO_HW_VERSION_PORT), GPIO(BUSVOODOO_HW_VERSION_PIN)); // pull down
bool version_down = (0==gpio_get(GPIO(BUSVOODOO_HW_VERSION_PORT), GPIO(BUSVOODOO_HW_VERSION_PIN))); // check if the signal is still down
gpio_set_mode(ADC12_IN_PORT(BUSVOODOO_HW_VERSION_CHANNEL), GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, ADC12_IN_PIN(BUSVOODOO_HW_VERSION_CHANNEL)); // put back to analog input
// get version
if (version_up && version_down) { // no voltage divider on pin
busvoodoo_version = '0'; // the pin is floating only for version 0 (= revision 18)
} else { // voltage divider on pin
for (uint8_t i=0; i<LENGTH(busvoodoo_version_voltages); i++) { // go through expected version voltages
if (version_voltage>busvoodoo_version_voltages[i]-0.2 && version_voltage<busvoodoo_version_voltages[i]+0.2) { // verify if voltage matches
busvoodoo_version = 'A'+i; // remember version name for matching voltage
break; // stop searching
}
}
}
// setup ADC to measure the 5V, 3.3V, LV, and HV power rails voltages
// setup ADC to measure the 5V, 3.3V, LV, and HV power rails voltages, and hardware version channel
rcc_periph_clock_enable(RCC_ADC12_IN(BUSVOODOO_5V_CHANNEL)); // enable clock for GPIO domain for 5V channel
gpio_set_mode(ADC12_IN_PORT(BUSVOODOO_5V_CHANNEL), GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, ADC12_IN_PIN(BUSVOODOO_5V_CHANNEL)); // set 5V channel as analogue input for the ADC
rcc_periph_clock_enable(RCC_ADC12_IN(BUSVOODOO_3V3_CHANNEL)); // enable clock for GPIO domain for 3.3V channel
@ -143,11 +101,32 @@ void busvoodoo_setup(void)
adc_set_sample_time_on_all_channels(ADC1, ADC_SMPR_SMP_28DOT5CYC); // use 28.5 cycles to sample (long enough to be stable)
adc_enable_temperature_sensor(ADC1); // enable internal voltage reference
adc_enable_external_trigger_regular(ADC1, ADC_CR2_EXTSEL_SWSTART); // use software trigger to start conversion
adc_set_single_conversion_mode(ADC1); // we only convert one channel after another
adc_power_on(ADC1); // switch on ADC
sleep_us(1); // wait t_stab for the ADC to stabilize
adc_reset_calibration(ADC1); // remove previous non-calibration
adc_calibration(ADC1); // calibrate ADC for less accuracy errors
// find out version of the board
gpio_set_mode(GPIO(BUSVOODOO_HW_VERSION_PORT), GPIO_MODE_INPUT, GPIO_CNF_INPUT_PULL_UPDOWN, GPIO(BUSVOODOO_HW_VERSION_PIN)); // use pull up and down to check if a voltage divider is present on the pin
gpio_set(GPIO(BUSVOODOO_HW_VERSION_PORT), GPIO(BUSVOODOO_HW_VERSION_PIN)); // pull up
bool version_up = (0!=gpio_get(GPIO(BUSVOODOO_HW_VERSION_PORT), GPIO(BUSVOODOO_HW_VERSION_PIN))); // check if the signal is still up
gpio_clear(GPIO(BUSVOODOO_HW_VERSION_PORT), GPIO(BUSVOODOO_HW_VERSION_PIN)); // pull down
bool version_down = (0==gpio_get(GPIO(BUSVOODOO_HW_VERSION_PORT), GPIO(BUSVOODOO_HW_VERSION_PIN))); // check if the signal is still down
gpio_set_mode(ADC12_IN_PORT(BUSVOODOO_HW_VERSION_CHANNEL), GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, ADC12_IN_PIN(BUSVOODOO_HW_VERSION_CHANNEL)); // put back to analog input
// get version
if (version_up && version_down) { // no voltage divider on pin
busvoodoo_version = '0'; // the pin is floating only for version 0 (= revision 18)
} else { // voltage divider on pin
float version_voltage = busvoodoo_vreg_get(BUSVOODOO_HW_VERSION_CHANNEL); // measure hardware version voltage
for (uint8_t i=0; i<LENGTH(busvoodoo_version_voltages); i++) { // go through expected version voltages
if (version_voltage>busvoodoo_version_voltages[i]-0.2 && version_voltage<busvoodoo_version_voltages[i]+0.2) { // verify if voltage matches
busvoodoo_version = 'A'+i; // remember version name for matching voltage
break; // stop searching
}
}
}
// setup DAC to control LV and HV voltage outputs
gpio_set_mode(GPIO(BUSVOODOO_LVCTL_PORT), GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, GPIO(BUSVOODOO_LVCTL_PIN)); // set LV pin as analog (the DAC will use it as output)
rcc_periph_clock_enable(RCC_DAC); // enable clock for DAC domain
@ -246,9 +225,10 @@ bool busvoodoo_vout_switch(bool on)
float busvoodoo_vreg_get(uint8_t channel)
{
if (channel!=BUSVOODOO_5V_CHANNEL && channel!=BUSVOODOO_3V3_CHANNEL && channel!=BUSVOODOO_LV_CHANNEL && channel!=BUSVOODOO_HV_CHANNEL) { // check channel
if (channel!=BUSVOODOO_5V_CHANNEL && channel!=BUSVOODOO_3V3_CHANNEL && channel!=BUSVOODOO_LV_CHANNEL && channel!=BUSVOODOO_HV_CHANNEL && channel!=BUSVOODOO_HW_VERSION_CHANNEL) { // check channel
return NAN;
}
uint8_t channels[2] = {ADC_CHANNEL17, ADC_CHANNEL17}; // voltages to convert: internal and internal (as fallback)
switch (channel) { // set desired channel
case BUSVOODOO_5V_CHANNEL:
@ -263,14 +243,17 @@ float busvoodoo_vreg_get(uint8_t channel)
case BUSVOODOO_HV_CHANNEL:
channels[1] = ADC_CHANNEL(BUSVOODOO_HV_CHANNEL);
break;
case BUSVOODOO_HW_VERSION_CHANNEL:
channels[1] = ADC_CHANNEL(BUSVOODOO_HW_VERSION_CHANNEL);
break;
default: // unknown channel
break;
}
adc_set_regular_sequence(ADC1, LENGTH(channels), channels); // set channels to convert
adc_enable_discontinuous_mode_regular(ADC1, LENGTH(channels)); // convert all channels
ADC_SR(ADC1) = 0; // reset flags
adc_start_conversion_regular(ADC1); // start conversion to get first voltage
uint16_t values[LENGTH(channels)] = {0}; // to store converted values
ADC_SR(ADC1) = 0; // reset flags
adc_start_conversion_regular(ADC1); // start conversion for individual channels
for (uint8_t channel_i=0; channel_i<LENGTH(channels); channel_i++) { // get all conversions
while (!adc_eoc(ADC1)); // wait until conversion finished
values[channel_i] = adc_read_regular(ADC1); // read voltage value (clears flag)
@ -289,6 +272,9 @@ float busvoodoo_vreg_get(uint8_t channel)
case BUSVOODOO_HV_CHANNEL:
to_return = values[1]/(1.5/(10.0+1.5));
break;
case BUSVOODOO_HW_VERSION_CHANNEL:
to_return = values[1];
break;
default: // unknown channel
to_return = NAN;
break;
@ -301,7 +287,6 @@ float busvoodoo_vreg_get(uint8_t channel)
float busvoodoo_lv_set(float voltage)
{
float volt = NAN; // common variable for voltages
if (voltage<=0.3) { // disable voltage regulator
gpio_clear(GPIO(BUSVOODOO_LVEN_PORT), GPIO(BUSVOODOO_LVEN_PIN)); // disable LV voltage regulator