From f980e62407607a22ef42793056a4ff1d80b34d40 Mon Sep 17 00:00:00 2001 From: Ea-r-th <39779954+Ea-r-th@users.noreply.github.com> Date: Mon, 22 Sep 2025 19:36:19 -0700 Subject: [PATCH] Finished ADC methods --- SHAL/Include/Core/SHAL_CORE.h | 8 +- .../Include/Peripheral/ADC/Reg/SHAL_ADC_REG.h | 8 -- .../Peripheral/ADC/Reg/SHAL_ADC_REG_F072xB.h | 14 ++- .../Peripheral/ADC/Reg/SHAL_ADC_TYPES.h | 8 -- SHAL/Include/Peripheral/ADC/SHAL_ADC.h | 32 ++++++ SHAL/Include/Peripheral/ADC/SHAL_ADC_REG.h | 44 ++++++++ SHAL/Include/Peripheral/ADC/SHAL_ADC_TYPES.h | 40 +++++++ .../Peripheral/GPIO/{Reg => }/SHAL_GPIO_REG.h | 0 .../GPIO/{Reg => }/SHAL_GPIO_TYPES.h | 0 .../Peripheral/I2C/{Reg => }/SHAL_I2C_REG.h | 0 .../Peripheral/I2C/{Reg => }/SHAL_I2C_TYPES.h | 0 .../Peripheral/Timer/{Reg => }/SHAL_TIM_REG.h | 0 .../Timer/{Reg => }/SHAL_TIM_TYPES.h | 0 .../Peripheral/UART/{Reg => }/SHAL_UART_REG.h | 0 .../UART/{Reg => }/SHAL_UART_TYPES.h | 0 SHAL/Src/Peripheral/ADC/SHAL_ADC.cpp | 100 ++++++++++++++++++ 16 files changed, 235 insertions(+), 19 deletions(-) delete mode 100644 SHAL/Include/Peripheral/ADC/Reg/SHAL_ADC_REG.h delete mode 100644 SHAL/Include/Peripheral/ADC/Reg/SHAL_ADC_TYPES.h create mode 100644 SHAL/Include/Peripheral/ADC/SHAL_ADC_REG.h create mode 100644 SHAL/Include/Peripheral/ADC/SHAL_ADC_TYPES.h rename SHAL/Include/Peripheral/GPIO/{Reg => }/SHAL_GPIO_REG.h (100%) rename SHAL/Include/Peripheral/GPIO/{Reg => }/SHAL_GPIO_TYPES.h (100%) rename SHAL/Include/Peripheral/I2C/{Reg => }/SHAL_I2C_REG.h (100%) rename SHAL/Include/Peripheral/I2C/{Reg => }/SHAL_I2C_TYPES.h (100%) rename SHAL/Include/Peripheral/Timer/{Reg => }/SHAL_TIM_REG.h (100%) rename SHAL/Include/Peripheral/Timer/{Reg => }/SHAL_TIM_TYPES.h (100%) rename SHAL/Include/Peripheral/UART/{Reg => }/SHAL_UART_REG.h (100%) rename SHAL/Include/Peripheral/UART/{Reg => }/SHAL_UART_TYPES.h (100%) diff --git a/SHAL/Include/Core/SHAL_CORE.h b/SHAL/Include/Core/SHAL_CORE.h index c891dda..e6b0bf1 100644 --- a/SHAL/Include/Core/SHAL_CORE.h +++ b/SHAL/Include/Core/SHAL_CORE.h @@ -22,6 +22,13 @@ void SHAL_init(); //Universal structs and defines --------------------------- +enum class SHAL_Result{ + OKAY, + ERROR +}; + + + typedef bool (*condition_fn_t)(void); #define SHAL_WAIT_FOR_CONDITION_US(cond, timeout_us) \ @@ -31,7 +38,6 @@ typedef bool (*condition_fn_t)(void); SHAL_wait_for_condition_ms([&](){ return (cond); }, (timeout_ms)) - //Currently configures systick to count down in microseconds void systick_init(); diff --git a/SHAL/Include/Peripheral/ADC/Reg/SHAL_ADC_REG.h b/SHAL/Include/Peripheral/ADC/Reg/SHAL_ADC_REG.h deleted file mode 100644 index 8a38e5a..0000000 --- a/SHAL/Include/Peripheral/ADC/Reg/SHAL_ADC_REG.h +++ /dev/null @@ -1,8 +0,0 @@ -// -// Created by Luca on 9/21/2025. -// - -#ifndef SHMINGO_HAL_SHAL_ADC_REG_H -#define SHMINGO_HAL_SHAL_ADC_REG_H - -#endif //SHMINGO_HAL_SHAL_ADC_REG_H diff --git a/SHAL/Include/Peripheral/ADC/Reg/SHAL_ADC_REG_F072xB.h b/SHAL/Include/Peripheral/ADC/Reg/SHAL_ADC_REG_F072xB.h index 276d0ec..3b1046d 100644 --- a/SHAL/Include/Peripheral/ADC/Reg/SHAL_ADC_REG_F072xB.h +++ b/SHAL/Include/Peripheral/ADC/Reg/SHAL_ADC_REG_F072xB.h @@ -9,12 +9,22 @@ #include "SHAL_ADC_TYPES.h" -enum class ADC_Key{ - +enum class ADC_Key : uint8_t{ S_ADC1, NUM_ADC, INVALID }; +ADC_TypeDef* getADCRegister(ADC_Key key){ + switch(key){ + case ADC_Key::S_ADC1: + return ADC1; + + case ADC_Key::NUM_ADC: + case ADC_Key::INVALID: + return nullptr; + } + __builtin_unreachable(); +} #endif //SHMINGO_HAL_SHAL_ADC_REG_F072XB_H diff --git a/SHAL/Include/Peripheral/ADC/Reg/SHAL_ADC_TYPES.h b/SHAL/Include/Peripheral/ADC/Reg/SHAL_ADC_TYPES.h deleted file mode 100644 index 2cdfe1f..0000000 --- a/SHAL/Include/Peripheral/ADC/Reg/SHAL_ADC_TYPES.h +++ /dev/null @@ -1,8 +0,0 @@ -// -// Created by Luca on 9/21/2025. -// - -#ifndef SHMINGO_HAL_SHAL_ADC_TYPES_H -#define SHMINGO_HAL_SHAL_ADC_TYPES_H - -#endif //SHMINGO_HAL_SHAL_ADC_TYPES_H diff --git a/SHAL/Include/Peripheral/ADC/SHAL_ADC.h b/SHAL/Include/Peripheral/ADC/SHAL_ADC.h index 7cc1a42..55cb95f 100644 --- a/SHAL/Include/Peripheral/ADC/SHAL_ADC.h +++ b/SHAL/Include/Peripheral/ADC/SHAL_ADC.h @@ -5,13 +5,41 @@ #ifndef SHMINGO_HAL_SHAL_ADC_H #define SHMINGO_HAL_SHAL_ADC_H +#include + +#include "SHAL_CORE.h" +#include "SHAL_ADC_REG.h" + class SHAL_ADC { + friend class ADCManager; + public: + SHAL_Result init(); + + SHAL_Result calibrate(); + + /// Performs analog to digital conversion on a single channel, one time + /// \param channel Channel to be converted + /// \param time ADC_SampleTime - amount of clock cycles per conversion + /// \return resulting value + uint16_t singleConvertSingle(ADC_Channel channel, ADC_SampleTime time = ADC_SampleTime::C239); + + /// Performs analog to digital conversion on multiple channels, one time + /// \param channels Pointer to an array of channels to convert + /// \param numChannels Number of channels to convert + /// \param result Pointer to store converted channel results in + /// \param time ADC_SampleTime - amount of clock cycles per conversion + void singleConvertSingle(ADC_Channel* channels, const int numChannels, uint16_t* result, ADC_SampleTime time = ADC_SampleTime::C239); + + private: + SHAL_ADC() = default; + + ADC_Key m_ADCKey = ADC_Key::INVALID; }; @@ -23,9 +51,13 @@ class ADCManager{ public: + static SHAL_ADC& get(ADC_Key key); + + ADCManager() = delete; private: + inline static SHAL_ADC m_ADCs[static_cast(ADC_Key::NUM_ADC)] = {}; }; diff --git a/SHAL/Include/Peripheral/ADC/SHAL_ADC_REG.h b/SHAL/Include/Peripheral/ADC/SHAL_ADC_REG.h new file mode 100644 index 0000000..6996576 --- /dev/null +++ b/SHAL/Include/Peripheral/ADC/SHAL_ADC_REG.h @@ -0,0 +1,44 @@ +// +// Created by Luca on 9/21/2025. +// + +#ifndef SHMINGO_HAL_SHAL_ADC_REG_H +#define SHMINGO_HAL_SHAL_ADC_REG_H + +#if defined(STM32F030x6) +#include "stm32f030x6.h" +#elif defined(STM32F030x8) +#include "stm32f030x8.h" +#elif defined(STM32F031x6) +#include "stm32f031x6.h" +#elif defined(STM32F038xx) +#include "stm32f038xx.h" +#elif defined(STM32F042x6) +#include "stm32f042x6.h" +#elif defined(STM32F048xx) +#include "stm32f048xx.h" +#elif defined(STM32F051x8) +#include "stm32f051x8.h" +#elif defined(STM32F058xx) +#include "stm32f058xx.h" +#elif defined(STM32F070x6) +#include "stm32f070x6.h" +#elif defined(STM32F070xB) +#include "stm32f070xb.h" +#elif defined(STM32F071xB) +#include "stm32f071xb.h" +#elif defined(STM32F072xB) +#include "SHAL_ADC_REG_F072xB.h" +#elif defined(STM32F078xx) +#include "stm32f078xx.h" +#elif defined(STM32F091xC) + #include "stm32f091xc.h" +#elif defined(STM32F098xx) + #include "stm32f098xx.h" +#elif defined(STM32F030xC) + #include "stm32f030xc.h" +#else + #error "Please select first the target STM32F0xx device used in your application (in stm32f0xx.h file)" +#endif + +#endif //SHMINGO_HAL_SHAL_ADC_REG_H diff --git a/SHAL/Include/Peripheral/ADC/SHAL_ADC_TYPES.h b/SHAL/Include/Peripheral/ADC/SHAL_ADC_TYPES.h new file mode 100644 index 0000000..b69f571 --- /dev/null +++ b/SHAL/Include/Peripheral/ADC/SHAL_ADC_TYPES.h @@ -0,0 +1,40 @@ +// +// Created by Luca on 9/21/2025. +// + +#ifndef SHMINGO_HAL_SHAL_ADC_TYPES_H +#define SHMINGO_HAL_SHAL_ADC_TYPES_H + +enum class ADC_Channel : uint32_t { + CH1 = ADC_CHSELR_CHSEL1, + CH2 = ADC_CHSELR_CHSEL2, + CH3 = ADC_CHSELR_CHSEL3, + CH4 = ADC_CHSELR_CHSEL4, + CH5 = ADC_CHSELR_CHSEL5, + CH6 = ADC_CHSELR_CHSEL6, + CH7 = ADC_CHSELR_CHSEL7, + CH8 = ADC_CHSELR_CHSEL8, + CH9 = ADC_CHSELR_CHSEL9, + CH10 = ADC_CHSELR_CHSEL10, + CH11 = ADC_CHSELR_CHSEL11, + CH12 = ADC_CHSELR_CHSEL12, + CH13 = ADC_CHSELR_CHSEL13, + CH14 = ADC_CHSELR_CHSEL14, + CH15 = ADC_CHSELR_CHSEL15, + CHTemp = ADC_CHSELR_CHSEL16, + CHRef = ADC_CHSELR_CHSEL17, + CHBat = ADC_CHSELR_CHSEL18 +}; + +enum class ADC_SampleTime : uint32_t { + C2 = 0x00, //1.5 cycles per sample + C7 = 0x01, //7.5 cycles + C13 = 0x02, //13.5 cycles + C28 = 0x03, //28.5 cycles + C41 = 0x04, //41.5 cycles + C55 = 0x05, //55.5 cycles + C71 = 0x06, //71.5 cycles + C239 = 0x07 //239.5 cycles +}; + +#endif //SHMINGO_HAL_SHAL_ADC_TYPES_H diff --git a/SHAL/Include/Peripheral/GPIO/Reg/SHAL_GPIO_REG.h b/SHAL/Include/Peripheral/GPIO/SHAL_GPIO_REG.h similarity index 100% rename from SHAL/Include/Peripheral/GPIO/Reg/SHAL_GPIO_REG.h rename to SHAL/Include/Peripheral/GPIO/SHAL_GPIO_REG.h diff --git a/SHAL/Include/Peripheral/GPIO/Reg/SHAL_GPIO_TYPES.h b/SHAL/Include/Peripheral/GPIO/SHAL_GPIO_TYPES.h similarity index 100% rename from SHAL/Include/Peripheral/GPIO/Reg/SHAL_GPIO_TYPES.h rename to SHAL/Include/Peripheral/GPIO/SHAL_GPIO_TYPES.h diff --git a/SHAL/Include/Peripheral/I2C/Reg/SHAL_I2C_REG.h b/SHAL/Include/Peripheral/I2C/SHAL_I2C_REG.h similarity index 100% rename from SHAL/Include/Peripheral/I2C/Reg/SHAL_I2C_REG.h rename to SHAL/Include/Peripheral/I2C/SHAL_I2C_REG.h diff --git a/SHAL/Include/Peripheral/I2C/Reg/SHAL_I2C_TYPES.h b/SHAL/Include/Peripheral/I2C/SHAL_I2C_TYPES.h similarity index 100% rename from SHAL/Include/Peripheral/I2C/Reg/SHAL_I2C_TYPES.h rename to SHAL/Include/Peripheral/I2C/SHAL_I2C_TYPES.h diff --git a/SHAL/Include/Peripheral/Timer/Reg/SHAL_TIM_REG.h b/SHAL/Include/Peripheral/Timer/SHAL_TIM_REG.h similarity index 100% rename from SHAL/Include/Peripheral/Timer/Reg/SHAL_TIM_REG.h rename to SHAL/Include/Peripheral/Timer/SHAL_TIM_REG.h diff --git a/SHAL/Include/Peripheral/Timer/Reg/SHAL_TIM_TYPES.h b/SHAL/Include/Peripheral/Timer/SHAL_TIM_TYPES.h similarity index 100% rename from SHAL/Include/Peripheral/Timer/Reg/SHAL_TIM_TYPES.h rename to SHAL/Include/Peripheral/Timer/SHAL_TIM_TYPES.h diff --git a/SHAL/Include/Peripheral/UART/Reg/SHAL_UART_REG.h b/SHAL/Include/Peripheral/UART/SHAL_UART_REG.h similarity index 100% rename from SHAL/Include/Peripheral/UART/Reg/SHAL_UART_REG.h rename to SHAL/Include/Peripheral/UART/SHAL_UART_REG.h diff --git a/SHAL/Include/Peripheral/UART/Reg/SHAL_UART_TYPES.h b/SHAL/Include/Peripheral/UART/SHAL_UART_TYPES.h similarity index 100% rename from SHAL/Include/Peripheral/UART/Reg/SHAL_UART_TYPES.h rename to SHAL/Include/Peripheral/UART/SHAL_UART_TYPES.h diff --git a/SHAL/Src/Peripheral/ADC/SHAL_ADC.cpp b/SHAL/Src/Peripheral/ADC/SHAL_ADC.cpp index 9c33b97..7cb499e 100644 --- a/SHAL/Src/Peripheral/ADC/SHAL_ADC.cpp +++ b/SHAL/Src/Peripheral/ADC/SHAL_ADC.cpp @@ -1,3 +1,103 @@ // // 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(channel); //Enable channel for conversion + ADC_reg->SMPR |= static_cast(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(channels[i]); + } + + ADC_reg->SMPR |= static_cast(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; + } +} \ No newline at end of file