aboutsummaryrefslogtreecommitdiff
path: root/src/voltdisc.c
blob: 034fdf8a1893f9850192f084c2b760b749bae58f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include "voltdisc.h"

#include "ch573/adc.h"
#include "gpio.h"
#include "risc-v.h"

#define ADC_I CH573_ADC__ADC_T_INTF
#define ADC ch573_adc__adc

#define VOLTAGE_DIVIDER_COEF (11)

millivolts_t get_input_voltage()
{
  // Pull down the voltage of the pin. Do this in case the MCU is in a chassis
  // which does not have the voltage divider.
  gpio_configure_pin(PIN_PA4, PIN_CFG_INPUT_PULL_DOWN);

  // Wait for the pin to discharge.
  for (int i = 0; i < 10; ++i) {
    __nop();
  }

  // Configure the pin to "floating".
  gpio_configure_pin(PIN_PA4, PIN_CFG_INPUT_FLOATING);

  // Configure the ADC for reading.
  ADC_I.cfg.adc_buf_en.set(ADC, ENABLED);
  ADC_I.cfg.adc_power_on.set(ADC, ENABLED);
  ADC_I.channel_select.set(ADC, 0);
  ADC_I.dma_interrupt_control.auto_en.set(ADC, 1);
  ADC_I.convert.adc_start.set(ADC, ON);

  uint32_t raw_value;
  // Wait until the ADC is ready for reading.
  while (!ADC_I.interrupt_flag.if_eoc.get(ADC));
  raw_value = ADC_I.data.get(ADC);

  ADC_I.convert.adc_start.set(ADC, OFF);
  ADC_I.cfg.adc_power_on.set(ADC, DISABLED);

  // Attempt to calculate the original voltage
  return (millivolts_t)(raw_value * 1.05 / 2048.0 * 1000) *
         VOLTAGE_DIVIDER_COEF;
}