aboutsummaryrefslogtreecommitdiff
path: root/src/voltdisc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/voltdisc.c')
-rw-r--r--src/voltdisc.c44
1 files changed, 44 insertions, 0 deletions
diff --git a/src/voltdisc.c b/src/voltdisc.c
new file mode 100644
index 0000000..034fdf8
--- /dev/null
+++ b/src/voltdisc.c
@@ -0,0 +1,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;
+}