This repository has been archived on 2024-05-28. You can view files and clone it, but cannot push or open issues or pull requests.
2023-11-14 16:25:09 -05:00

89 lines
3.2 KiB
C++

#ifndef STM32U5XX_HAL_ADC_HPP
#define STM32U5XX_HAL_ADC_HPP
#include "global_variable.h"
#include "delay.h"
#include "prepherials.h"
#include "queue.hpp"
#include "reg_adc_gen.h"
#include "reg_nvic.h"
#include "reg_rcc.h"
#include "reg_uart.h"
#include "stm32u5xx.h"
typedef enum {
ADC_RESOLUTION_12B = 0, ADC_RESOLUTION_10B = 1, ADC_RESOLUTION_8B = 2, ADC_RESOLUTION_6B = 3
} adc_resolution_e; // todo: check with rm0456
typedef enum {
ADC_SINGLE_ENDED = 0, ADC_DIFFERENTIAL = 1
} adc_single_diff_e; // todo: check with rm0456
class Adc {
private:
ADC_TypeDef *ins = nullptr;
reg_adc_t *reg = nullptr;
ADC_Common_TypeDef *reg_common = nullptr;
queue20u32 data_queue;
public:
Adc() = default;
void setup(ADC_TypeDef *adc, ADC_Common_TypeDef *adc_common) {
reg_common = adc_common, ins = adc, reg = (reg_adc_t *) ins;
}
hal_status_e init(int channel = 0, adc_resolution_e resolution = ADC_RESOLUTION_12B,
adc_single_diff_e single_diff = ADC_SINGLE_ENDED) {
rcc_enable_adc_clock(ins); // enable adc clock
nvic_enable_adc_irq(); // enable adc irq
reg->cr.advregen = 1; // enable adc voltage regulator
delay_us(10, true); // todo: this delay may be removed, check with rm0456
{
wait_for_true(reg->cr.advregen, 1); // wait for adc voltage regulator to be ready
}
reg->cfgr1.res = resolution; // set resolution
reg->cfgr1.autdly = 0; // disable automatic delay (delay the start of conversion)
// calibration for single-end mode
// todo: add calibration for differential mode
// todo: check set sampling time with rm0456
reg->difsel.difsel = single_diff; // set single ended mode
reg->cr.adcal = 1; // start calibration
{
wait_for_true(reg->cr.adcal, 1); // wait for calibration to finish
}
reg->sqr1.l = 0; // set number of conversion
reg->sqr1.sq1 = channel; // set channel
reg->smpr1.smp1 = 0b111; // set sampling time to 640.5 adc clock cycles
reg->cfgr1.exten = 0b00; // set trigger to software
reg->cr.aden = 1; // enable adc
return HAL_OK;
}
void start_conversion(int number_conversion = 1, bool continuous_conversion = false) {
reg->cfgr1.cont = continuous_conversion;
reg->sqr1.l = number_conversion - 1; // set number of conversion
reg->cr.adstart = 1; // start conversion
}
void stop_conversion() {
reg->cr.adstp = 1; // stop conversion
}
void interrupt_handler() {
// read isr register
reg_adc_isr_t isr = const_cast<reg_adc_isr_t &>(reg->isr);
// todo: end of sequence may not need to be checked
if (isr.eoc || isr.eos) data_queue.push(reg->dr.rdata);
// clear interrupt flag
reg->isr.eoc = 0, reg->isr.eos = 0;
// TODO: continuous conversion mode
// single conversion mode and continuous conversion mode
}
hal_status_e read_last_conversion(uint32_t *data) { return data_queue.pop(data); }
};
#endif // STM32U5XX_HAL_ADC_HPP