Files
Shmingo-HAL/SHAL/Src/Peripheral/ADC/SHAL_ADC.cpp
2025-09-22 19:36:19 -07:00

103 lines
3.0 KiB
C++

//
// Created by Luca on 9/21/2025.
//
#include "SHAL_ADC.h"
//Can hard code registers on F0 because all F0 devices have only one ADC, and use only one clock
SHAL_Result SHAL_ADC::init() {
if(m_ADCKey == ADC_Key::INVALID || m_ADCKey == ADC_Key::NUM_ADC){
return SHAL_Result::ERROR;
}
ADC_TypeDef* ADC_reg = getADCRegister(m_ADCKey);
RCC->APB2ENR |= RCC_APB2ENR_ADC1EN; //Enable clock
RCC->CR2 |= RCC_CR2_HSI14ON; //Start peripheral oscillator
if(!SHAL_WAIT_FOR_CONDITION_US(((RCC->CR2 & RCC_CR2_HSI14RDY) != 0),50)){ //Wait for clock OKAY
return SHAL_Result::ERROR;
}
if((ADC_reg->ISR & ADC_ISR_ADRDY) != 0){ //Set ADRDY to 0
ADC_reg->ISR |= ADC_ISR_ADRDY;
}
ADC_reg->CR |= ADC_CR_ADEN; //Enable
if(!SHAL_WAIT_FOR_CONDITION_US(((ADC_reg->ISR & ADC_ISR_ADRDY) != 0),50)){ //Wait for disable
return SHAL_Result::ERROR;
}
if(calibrate() != SHAL_Result::OKAY){ //Calibrate
return SHAL_Result::ERROR;
}
return SHAL_Result::OKAY;
}
SHAL_Result SHAL_ADC::calibrate() {
if(m_ADCKey == ADC_Key::INVALID || m_ADCKey == ADC_Key::NUM_ADC){
return SHAL_Result::ERROR;
}
ADC_TypeDef* ADC_reg = getADCRegister(m_ADCKey);
if((ADC_reg->CR & ADC_CR_ADEN) != 0){ //Clear ADEN (enable)
ADC_reg->CR |= ADC_CR_ADDIS;
}
if(!SHAL_WAIT_FOR_CONDITION_US(((ADC_reg->CR & ADC_CR_ADEN) == 0),50)){ //Wait for disable
return SHAL_Result::ERROR;
}
ADC_reg->CFGR1 &= ~ADC_CFGR1_DMAEN; //Clear DMAEN
ADC_reg->CR |= ADC_CR_ADCAL; //Launch calibration by setting ADCAL
if(!SHAL_WAIT_FOR_CONDITION_US(((ADC_reg->CR & ADC_CR_ADCAL) == 0),50)){ //Wait for calibration
return SHAL_Result::ERROR;
}
return SHAL_Result::OKAY;
}
uint16_t SHAL_ADC::singleConvertSingle(ADC_Channel channel, ADC_SampleTime time) {
ADC_TypeDef* ADC_reg = getADCRegister(m_ADCKey);
ADC->CCR |= ADC_CCR_VREFEN | ADC_CCR_TSEN; //Enable VREFINT and Temp sensor in global ADC struct
ADC_reg->CHSELR = static_cast<uint32_t>(channel); //Enable channel for conversion
ADC_reg->SMPR |= static_cast<uint32_t>(time); //Set sampling time
if(!SHAL_WAIT_FOR_CONDITION_US(((ADC_reg->ISR & ADC_ISR_EOC) != 0),500)){ //Wait for conversion
return 0; //Failed
}
uint16_t result = ADC_reg->DR;
return result;
}
void SHAL_ADC::singleConvertSingle(ADC_Channel* channels, const int numChannels, uint16_t* result, ADC_SampleTime time) {
ADC_TypeDef* ADC_reg = getADCRegister(m_ADCKey);
ADC->CCR |= ADC_CCR_VREFEN | ADC_CCR_TSEN; //Enable VREFINT and Temp sensor in global ADC struct
for(int i = 0; i < numChannels; i++){ //Enable all channels
ADC_reg->CHSELR = static_cast<uint32_t>(channels[i]);
}
ADC_reg->SMPR |= static_cast<uint32_t>(time); //Set sampling time
for(int i = 0; i < numChannels; i++){
if(!SHAL_WAIT_FOR_CONDITION_US(((ADC_reg->ISR & ADC_ISR_EOC) != 0),500)){ //Wait for conversion
continue; //Failed
}
result[i] = ADC_reg->DR;
}
}