Added core tools, added ADC abstractions for different registers
This commit is contained in:
@@ -28,8 +28,10 @@ enum class SHAL_Result{
|
||||
};
|
||||
|
||||
|
||||
|
||||
typedef bool (*condition_fn_t)(void);
|
||||
#define SHAL_CALL(func) \
|
||||
if(func != SHAL_Result::OKAY){ \
|
||||
return SHAL_Result::ERROR; \
|
||||
}
|
||||
|
||||
#define SHAL_WAIT_FOR_CONDITION_US(cond, timeout_us) \
|
||||
SHAL_wait_for_condition_us([&](){ return (cond); }, (timeout_us))
|
||||
@@ -68,6 +70,17 @@ bool SHAL_wait_for_condition_ms(Condition cond, uint32_t timeout_ms) {
|
||||
return false; // timeout
|
||||
}
|
||||
|
||||
void SHAL_set_bits(volatile uint32_t* reg, uint32_t size, uint32_t bits, uint32_t offset){
|
||||
uint32_t mask = (1 << (size)) - 1;
|
||||
*reg &= ~(mask << offset);
|
||||
*reg |= bits << offset;
|
||||
}
|
||||
|
||||
void SHAL_apply_bitmask(volatile uint32_t* reg, uint32_t mask){
|
||||
*reg &= ~(mask);
|
||||
*reg |= mask;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
@@ -10,12 +10,84 @@
|
||||
|
||||
#define SHAL_ADC1 SHAL_ADC(1)
|
||||
|
||||
|
||||
enum class ADC_Key : uint8_t{
|
||||
S_ADC1,
|
||||
NUM_ADC,
|
||||
INVALID
|
||||
S_ADC1 = 0,
|
||||
NUM_ADC = 1,
|
||||
INVALID = 255
|
||||
};
|
||||
|
||||
enum class ADC_Clock_Source : uint8_t {
|
||||
SHAL_SYSCLK,
|
||||
SHAL_PLLSAI1,
|
||||
SHAL_PLL,
|
||||
SHAL_MSI
|
||||
};
|
||||
|
||||
static volatile ADC_TypeDef* ADC_TABLE[1] = { //Lookup table for ADCs
|
||||
ADC1,
|
||||
};
|
||||
|
||||
SHAL_ADC_Common_Control_Reg getADCCommonControl() {
|
||||
return {&ADC1_COMMON->CCR ,ADC_CCR_VREFEN,ADC_CCR_TSEN,ADC_CCR_VBATEN};
|
||||
}
|
||||
|
||||
SHAL_ADC_RCC_Enable_Reg getADCRCCEnableRegister(ADC_Key key){
|
||||
SHAL_ADC_RCC_Enable_Reg res = {nullptr, RCC_AHB2ENR_ADCEN};
|
||||
|
||||
res.reg = &(ADC_TABLE[static_cast<uint8_t>(key)]->ISR);
|
||||
return res;
|
||||
}
|
||||
|
||||
SHAL_ADC_Control_Reg getADCControlReg(ADC_Key key) {
|
||||
|
||||
SHAL_ADC_Control_Reg res = {nullptr, ADC_CR_ADEN, ADC_CR_ADDIS, ADC_CR_ADCAL, ADC_CR_ADSTART};
|
||||
|
||||
res.reg = &(ADC_TABLE[static_cast<uint8_t>(key)]->CR);
|
||||
return res;
|
||||
}
|
||||
|
||||
SHAL_ADC_Config_Reg getADCConfigReg(ADC_Key key) {
|
||||
|
||||
SHAL_ADC_Config_Reg res = {nullptr, ADC_CFGR_CONT, ADC_CFGR_RES_Pos, ADC_CFGR_ALIGN_Pos};
|
||||
|
||||
res.reg = &(ADC_TABLE[static_cast<uint8_t>(key)]->CFGR);
|
||||
return res;
|
||||
}
|
||||
|
||||
SHAL_ADC_ISR getADCISR(ADC_Key key){
|
||||
SHAL_ADC_ISR res = {nullptr, ADC_ISR_EOC};
|
||||
|
||||
res.reg = &(ADC_TABLE[static_cast<uint8_t>(key)]->ISR);
|
||||
return res;
|
||||
}
|
||||
|
||||
SHAL_ADC_Data_Reg getADCDataReg(ADC_Key key){
|
||||
SHAL_ADC_Data_Reg res = {nullptr, 0xFFFF};
|
||||
|
||||
res.reg = &(ADC_TABLE[static_cast<uint8_t>(key)]->DR);
|
||||
return res;
|
||||
}
|
||||
|
||||
SHAL_ADC_Clock_Reg getADCClockSelectRegister(ADC_Clock_Source clockSource) {
|
||||
constexpr uint32_t ADCSEL_MASK = RCC_CCIPR_ADCSEL_Msk; // covers bits 29:28
|
||||
|
||||
SHAL_ADC_Clock_Reg res = {&RCC->CCIPR, ADCSEL_MASK, 1U << RCC_CCIPR_ADCSEL_Pos}; //Default to PLLSAI1
|
||||
|
||||
switch(clockSource){
|
||||
case ADC_Clock_Source::SHAL_PLLSAI1:
|
||||
res.mask = 1U << RCC_CCIPR_ADCSEL_Pos;
|
||||
case ADC_Clock_Source::SHAL_PLL:
|
||||
res.mask = 2U << RCC_CCIPR_ADCSEL_Pos;
|
||||
case ADC_Clock_Source::SHAL_SYSCLK:
|
||||
res.mask = 3U << RCC_CCIPR_ADCSEL_Pos;
|
||||
case ADC_Clock_Source::SHAL_MSI:
|
||||
break; //TODO implement this
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
constexpr ADC_TypeDef* getADCRegister(ADC_Key key){
|
||||
switch(key){
|
||||
case ADC_Key::S_ADC1:
|
||||
|
||||
@@ -20,18 +20,22 @@ public:
|
||||
|
||||
SHAL_Result calibrate();
|
||||
|
||||
SHAL_Result configureResolution(SHAL_ADC_Resolution resolution);
|
||||
|
||||
SHAL_Result configureAlignment(SHAL_ADC_Alignment alignment);
|
||||
|
||||
/// 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);
|
||||
uint16_t singleConvertSingle(SHAL_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 multiConvertSingle(ADC_Channel* channels, const int numChannels, uint16_t* result, ADC_SampleTime time = ADC_SampleTime::C239);
|
||||
void multiConvertSingle(SHAL_ADC_Channel* channels, int numChannels, uint16_t* result, ADC_SampleTime time = ADC_SampleTime::C239);
|
||||
|
||||
|
||||
|
||||
@@ -41,6 +45,9 @@ private:
|
||||
|
||||
ADC_Key m_ADCKey = ADC_Key::INVALID;
|
||||
|
||||
bool isValid();
|
||||
SHAL_Result disable();
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -5,26 +5,75 @@
|
||||
#ifndef SHMINGO_HAL_SHAL_ADC_TYPES_H
|
||||
#define SHMINGO_HAL_SHAL_ADC_TYPES_H
|
||||
|
||||
enum class ADC_Channel : uint32_t {
|
||||
CH0 = ADC_CHSELR_CHSEL0,
|
||||
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
|
||||
|
||||
struct SHAL_ADC_Common_Control_Reg {
|
||||
|
||||
volatile uint32_t* reg;
|
||||
uint32_t VoltageRefEnable;
|
||||
uint32_t TempSensorEnable;
|
||||
uint32_t VBatteryEnable;
|
||||
|
||||
};
|
||||
|
||||
struct SHAL_ADC_RCC_Enable_Reg {
|
||||
volatile uint32_t* reg;
|
||||
uint32_t mask;
|
||||
};
|
||||
|
||||
struct SHAL_ADC_Control_Reg {
|
||||
volatile uint32_t* reg;
|
||||
uint32_t enable_mask;
|
||||
uint32_t disable_mask;
|
||||
uint32_t calibration_mask;
|
||||
uint32_t start_mask;
|
||||
};
|
||||
|
||||
struct SHAL_ADC_Config_Reg {
|
||||
volatile uint32_t* reg;
|
||||
uint32_t continue_mask;
|
||||
|
||||
uint32_t resolution_offset;
|
||||
uint32_t alignment_offset;
|
||||
};
|
||||
|
||||
struct SHAL_ADC_Data_Reg {
|
||||
volatile uint32_t* reg;
|
||||
uint32_t mask;
|
||||
};
|
||||
|
||||
struct SHAL_ADC_ISR {
|
||||
|
||||
volatile uint32_t* reg;
|
||||
uint32_t end_of_conversion_mask;
|
||||
};
|
||||
|
||||
struct SHAL_ADC_Clock_Reg {
|
||||
volatile uint32_t* reg;
|
||||
uint32_t clear;
|
||||
uint32_t mask;
|
||||
};
|
||||
|
||||
|
||||
enum class SHAL_ADC_Channel : uint32_t {
|
||||
CH0,
|
||||
CH1,
|
||||
CH2,
|
||||
CH3,
|
||||
CH4,
|
||||
CH5,
|
||||
CH6,
|
||||
CH7,
|
||||
CH8,
|
||||
CH9,
|
||||
CH10,
|
||||
CH11,
|
||||
CH12,
|
||||
CH13,
|
||||
CH14,
|
||||
CH15,
|
||||
CHTemp,
|
||||
CHRef,
|
||||
CHBat
|
||||
};
|
||||
|
||||
enum class ADC_SampleTime : uint32_t {
|
||||
@@ -38,4 +87,16 @@ enum class ADC_SampleTime : uint32_t {
|
||||
C239 = 0x07 //239.5 cycles
|
||||
};
|
||||
|
||||
enum class SHAL_ADC_Resolution : uint8_t {
|
||||
B12 = 0x00,
|
||||
B10 = 0x01,
|
||||
B8 = 0x02,
|
||||
B6 = 0x03,
|
||||
};
|
||||
|
||||
enum class SHAL_ADC_Alignment : uint8_t {
|
||||
RIGHT = 0x00,
|
||||
LEFT = 0x01,
|
||||
};
|
||||
|
||||
#endif //SHMINGO_HAL_SHAL_ADC_TYPES_H
|
||||
|
||||
@@ -275,70 +275,70 @@ constexpr SHAL_GPIO_Port_Info getGPIOPortInfo(GPIO_Key key){
|
||||
case GPIO_Key::A0:
|
||||
case GPIO_Key::B0:
|
||||
case GPIO_Key::C0:
|
||||
return {0,ADC_Channel::CH0};
|
||||
return {0, SHAL_ADC_Channel::CH0};
|
||||
case GPIO_Key::A1:
|
||||
case GPIO_Key::B1:
|
||||
case GPIO_Key::C1:
|
||||
return {1,ADC_Channel::CH1};
|
||||
return {1, SHAL_ADC_Channel::CH1};
|
||||
case GPIO_Key::A2:
|
||||
case GPIO_Key::B2:
|
||||
case GPIO_Key::C2:
|
||||
return {2,ADC_Channel::CH2};
|
||||
return {2, SHAL_ADC_Channel::CH2};
|
||||
case GPIO_Key::A3:
|
||||
case GPIO_Key::B3:
|
||||
case GPIO_Key::C3:
|
||||
return {3,ADC_Channel::CH3};
|
||||
return {3, SHAL_ADC_Channel::CH3};
|
||||
case GPIO_Key::A4:
|
||||
case GPIO_Key::B4:
|
||||
case GPIO_Key::C4:
|
||||
return {4,ADC_Channel::CH4};
|
||||
return {4, SHAL_ADC_Channel::CH4};
|
||||
case GPIO_Key::A5:
|
||||
case GPIO_Key::B5:
|
||||
case GPIO_Key::C5:
|
||||
return {5,ADC_Channel::CH5};
|
||||
return {5, SHAL_ADC_Channel::CH5};
|
||||
case GPIO_Key::A6:
|
||||
case GPIO_Key::B6:
|
||||
case GPIO_Key::C6:
|
||||
return {6,ADC_Channel::CH6};
|
||||
return {6, SHAL_ADC_Channel::CH6};
|
||||
case GPIO_Key::A7:
|
||||
case GPIO_Key::B7:
|
||||
case GPIO_Key::C7:
|
||||
return {7,ADC_Channel::CH7};
|
||||
return {7, SHAL_ADC_Channel::CH7};
|
||||
case GPIO_Key::A8:
|
||||
case GPIO_Key::B8:
|
||||
case GPIO_Key::C8:
|
||||
return {8,ADC_Channel::CH8};
|
||||
return {8, SHAL_ADC_Channel::CH8};
|
||||
case GPIO_Key::A9:
|
||||
case GPIO_Key::B9:
|
||||
case GPIO_Key::C9:
|
||||
return {9,ADC_Channel::CH9};
|
||||
return {9, SHAL_ADC_Channel::CH9};
|
||||
case GPIO_Key::A10:
|
||||
case GPIO_Key::B10:
|
||||
case GPIO_Key::C10:
|
||||
return {10,ADC_Channel::CH10};
|
||||
return {10, SHAL_ADC_Channel::CH10};
|
||||
case GPIO_Key::A11:
|
||||
case GPIO_Key::B11:
|
||||
case GPIO_Key::C11:
|
||||
return {11,ADC_Channel::CH11};
|
||||
return {11, SHAL_ADC_Channel::CH11};
|
||||
case GPIO_Key::A12:
|
||||
case GPIO_Key::B12:
|
||||
case GPIO_Key::C12:
|
||||
return {12,ADC_Channel::CH12};
|
||||
return {12, SHAL_ADC_Channel::CH12};
|
||||
case GPIO_Key::A13:
|
||||
case GPIO_Key::B13:
|
||||
case GPIO_Key::C13:
|
||||
return {13,ADC_Channel::CH13};
|
||||
return {13, SHAL_ADC_Channel::CH13};
|
||||
case GPIO_Key::A14:
|
||||
case GPIO_Key::B14:
|
||||
case GPIO_Key::C14:
|
||||
return {14,ADC_Channel::CH14};
|
||||
return {14, SHAL_ADC_Channel::CH14};
|
||||
case GPIO_Key::A15:
|
||||
case GPIO_Key::B15:
|
||||
case GPIO_Key::C15:
|
||||
return {15,ADC_Channel::CH15};
|
||||
return {15, SHAL_ADC_Channel::CH15};
|
||||
case GPIO_Key::NUM_GPIO:
|
||||
case GPIO_Key::INVALID:
|
||||
return {0,ADC_Channel::CH0};
|
||||
return {0, SHAL_ADC_Channel::CH0};
|
||||
}
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
@@ -252,70 +252,70 @@ constexpr SHAL_GPIO_Port_Info getGPIOPortInfo(GPIO_Key key){
|
||||
case GPIO_Key::A0:
|
||||
case GPIO_Key::B0:
|
||||
case GPIO_Key::C0:
|
||||
return {0,ADC_Channel::CH0};
|
||||
return {0, SHAL_ADC_Channel::CH0};
|
||||
case GPIO_Key::A1:
|
||||
case GPIO_Key::B1:
|
||||
case GPIO_Key::C1:
|
||||
return {1,ADC_Channel::CH1};
|
||||
return {1, SHAL_ADC_Channel::CH1};
|
||||
case GPIO_Key::A2:
|
||||
case GPIO_Key::B2:
|
||||
case GPIO_Key::C2:
|
||||
return {2,ADC_Channel::CH2};
|
||||
return {2, SHAL_ADC_Channel::CH2};
|
||||
case GPIO_Key::A3:
|
||||
case GPIO_Key::B3:
|
||||
case GPIO_Key::C3:
|
||||
return {3,ADC_Channel::CH3};
|
||||
return {3, SHAL_ADC_Channel::CH3};
|
||||
case GPIO_Key::A4:
|
||||
case GPIO_Key::B4:
|
||||
case GPIO_Key::C4:
|
||||
return {4,ADC_Channel::CH4};
|
||||
return {4, SHAL_ADC_Channel::CH4};
|
||||
case GPIO_Key::A5:
|
||||
case GPIO_Key::B5:
|
||||
case GPIO_Key::C5:
|
||||
return {5,ADC_Channel::CH5};
|
||||
return {5, SHAL_ADC_Channel::CH5};
|
||||
case GPIO_Key::A6:
|
||||
case GPIO_Key::B6:
|
||||
case GPIO_Key::C6:
|
||||
return {6,ADC_Channel::CH6};
|
||||
return {6, SHAL_ADC_Channel::CH6};
|
||||
case GPIO_Key::A7:
|
||||
case GPIO_Key::B7:
|
||||
case GPIO_Key::C7:
|
||||
return {7,ADC_Channel::CH7};
|
||||
return {7, SHAL_ADC_Channel::CH7};
|
||||
case GPIO_Key::A8:
|
||||
case GPIO_Key::B8:
|
||||
case GPIO_Key::C8:
|
||||
return {8,ADC_Channel::CH8};
|
||||
return {8, SHAL_ADC_Channel::CH8};
|
||||
case GPIO_Key::A9:
|
||||
case GPIO_Key::B9:
|
||||
case GPIO_Key::C9:
|
||||
return {9,ADC_Channel::CH9};
|
||||
return {9, SHAL_ADC_Channel::CH9};
|
||||
case GPIO_Key::A10:
|
||||
case GPIO_Key::B10:
|
||||
case GPIO_Key::C10:
|
||||
return {10,ADC_Channel::CH10};
|
||||
return {10, SHAL_ADC_Channel::CH10};
|
||||
case GPIO_Key::A11:
|
||||
case GPIO_Key::B11:
|
||||
case GPIO_Key::C11:
|
||||
return {11,ADC_Channel::CH11};
|
||||
return {11, SHAL_ADC_Channel::CH11};
|
||||
case GPIO_Key::A12:
|
||||
case GPIO_Key::B12:
|
||||
case GPIO_Key::C12:
|
||||
return {12,ADC_Channel::CH12};
|
||||
return {12, SHAL_ADC_Channel::CH12};
|
||||
case GPIO_Key::A13:
|
||||
case GPIO_Key::B13:
|
||||
case GPIO_Key::C13:
|
||||
return {13,ADC_Channel::CH13};
|
||||
return {13, SHAL_ADC_Channel::CH13};
|
||||
case GPIO_Key::A14:
|
||||
case GPIO_Key::B14:
|
||||
case GPIO_Key::C14:
|
||||
return {14,ADC_Channel::CH14};
|
||||
return {14, SHAL_ADC_Channel::CH14};
|
||||
case GPIO_Key::A15:
|
||||
case GPIO_Key::B15:
|
||||
case GPIO_Key::C15:
|
||||
return {15,ADC_Channel::CH15};
|
||||
return {15, SHAL_ADC_Channel::CH15};
|
||||
case GPIO_Key::NUM_GPIO:
|
||||
case GPIO_Key::INVALID:
|
||||
return {0,ADC_Channel::CH0};
|
||||
return {0, SHAL_ADC_Channel::CH0};
|
||||
}
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ struct SHAL_Peripheral_Register {
|
||||
|
||||
struct SHAL_GPIO_Port_Info{
|
||||
uint8_t number;
|
||||
ADC_Channel ADCChannel;
|
||||
SHAL_ADC_Channel ADCChannel;
|
||||
};
|
||||
|
||||
enum class PinMode : uint8_t{
|
||||
|
||||
@@ -62,6 +62,9 @@ constexpr SHAL_I2C_Reset_Reg getI2CResetReg(const I2C_Pair pair){
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
constexpr SHAL_I2C_Reset_Reg getI2CResetRe() {
|
||||
return {&RCC->APB1RSTR1,RCC_APB1RSTR1_I2C1RST};
|
||||
}
|
||||
//Gets all the bits in the I2C timer register, these values should rarely be manually set, but I wanted to support it anyway
|
||||
constexpr SHAL_I2C_Timing_Reg getI2CTimerReg(const I2C_Pair pair){
|
||||
switch(pair){
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
#elif defined(STM32L431xx)
|
||||
#include "stm32l431xx.h"
|
||||
#elif defined(STM32L432xx)
|
||||
#include "stm32l432xx.h"
|
||||
#include "SHAL_I2C_REG_L432KC.h"
|
||||
#elif defined(STM32L433xx)
|
||||
#include "stm32l433xx.h"
|
||||
#elif defined(STM32L442xx)
|
||||
|
||||
@@ -64,7 +64,7 @@ SHAL_Result SHAL_ADC::calibrate() {
|
||||
return SHAL_Result::OKAY;
|
||||
}
|
||||
|
||||
uint16_t SHAL_ADC::singleConvertSingle(ADC_Channel channel, ADC_SampleTime time) {
|
||||
uint16_t SHAL_ADC::singleConvertSingle(SHAL_ADC_Channel channel, ADC_SampleTime time) {
|
||||
|
||||
ADC_TypeDef* ADC_reg = getADCRegister(m_ADCKey);
|
||||
|
||||
@@ -81,7 +81,7 @@ uint16_t SHAL_ADC::singleConvertSingle(ADC_Channel channel, ADC_SampleTime time)
|
||||
return result;
|
||||
}
|
||||
|
||||
void SHAL_ADC::multiConvertSingle(ADC_Channel* channels, const int numChannels, uint16_t* result, ADC_SampleTime time) {
|
||||
void SHAL_ADC::multiConvertSingle(SHAL_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
|
||||
|
||||
@@ -109,7 +109,7 @@ void SHAL_GPIO::useAsExternalInterrupt(TriggerMode mode, EXTICallback callback)
|
||||
|
||||
uint16_t SHAL_GPIO::analogRead(ADC_SampleTime sampleTime) {
|
||||
|
||||
ADC_Channel channel = getGPIOPortInfo(m_GPIO_KEY).ADCChannel;
|
||||
SHAL_ADC_Channel channel = getGPIOPortInfo(m_GPIO_KEY).ADCChannel;
|
||||
|
||||
return GPIOManager::getGPIOADC().singleConvertSingle(channel,sampleTime);
|
||||
}
|
||||
|
||||
@@ -13,22 +13,19 @@ SHAL_Result SHAL_ADC::init() {
|
||||
|
||||
ADC_TypeDef* ADC_reg = getADCRegister(m_ADCKey);
|
||||
|
||||
SHAL_ADC_RCC_Enable_Reg clock_reg = getADCRCCEnableRegister(m_ADCKey); //Clock enable
|
||||
|
||||
RCC->APB2ENR |= RCC_APB2ENR_ADC1EN; //Enable clock
|
||||
RCC->CR2 |= RCC_CR2_HSI14ON; //Start peripheral oscillator
|
||||
*clock_reg.reg |= clock_reg.mask;
|
||||
|
||||
if(!SHAL_WAIT_FOR_CONDITION_US(((RCC->CR2 & RCC_CR2_HSI14RDY) != 0),50)){ //Wait for clock OKAY
|
||||
return SHAL_Result::ERROR;
|
||||
}
|
||||
SHAL_ADC_Control_Reg control_reg = getADCControlReg(m_ADCKey);
|
||||
|
||||
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 (*control_reg.reg & control_reg.enable_mask) {
|
||||
//request disable: ADEN=1 -> set ADDIS to disable
|
||||
*control_reg.reg |= control_reg.disable_mask;
|
||||
//wait until ADEN cleared (ISR.ADREADY == 0)
|
||||
if(!SHAL_WAIT_FOR_CONDITION_MS((*control_reg.reg & control_reg.enable_mask) == 0, 100)){
|
||||
return SHAL_Result::ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if(calibrate() != SHAL_Result::OKAY){ //Calibrate
|
||||
@@ -40,34 +37,26 @@ SHAL_Result SHAL_ADC::init() {
|
||||
|
||||
SHAL_Result SHAL_ADC::calibrate() {
|
||||
|
||||
if(m_ADCKey == ADC_Key::INVALID || m_ADCKey == ADC_Key::NUM_ADC){
|
||||
if(disable() != SHAL_Result::OKAY){ //Disable the ADC
|
||||
return SHAL_Result::ERROR;
|
||||
}
|
||||
|
||||
ADC_TypeDef* ADC_reg = getADCRegister(m_ADCKey);
|
||||
SHAL_ADC_Control_Reg control_reg = getADCControlReg(m_ADCKey);
|
||||
|
||||
if((ADC_reg->CR & ADC_CR_ADEN) != 0){ //Clear ADEN (enable)
|
||||
ADC_reg->CR |= ADC_CR_ADDIS;
|
||||
}
|
||||
*control_reg.reg |= control_reg.calibration_mask;
|
||||
|
||||
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
|
||||
if(!SHAL_WAIT_FOR_CONDITION_US(((*control_reg.reg & control_reg.calibration_mask) == 0),500)){ //Wait for calibration
|
||||
return SHAL_Result::ERROR;
|
||||
}
|
||||
|
||||
return SHAL_Result::OKAY;
|
||||
}
|
||||
|
||||
uint16_t SHAL_ADC::singleConvertSingle(ADC_Channel channel, ADC_SampleTime time) {
|
||||
uint16_t SHAL_ADC::singleConvertSingle(SHAL_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
|
||||
@@ -81,7 +70,7 @@ uint16_t SHAL_ADC::singleConvertSingle(ADC_Channel channel, ADC_SampleTime time)
|
||||
return result;
|
||||
}
|
||||
|
||||
void SHAL_ADC::multiConvertSingle(ADC_Channel* channels, const int numChannels, uint16_t* result, ADC_SampleTime time) {
|
||||
void SHAL_ADC::multiConvertSingle(SHAL_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
|
||||
@@ -102,6 +91,57 @@ void SHAL_ADC::multiConvertSingle(ADC_Channel* channels, const int numChannels,
|
||||
}
|
||||
}
|
||||
|
||||
SHAL_Result SHAL_ADC::disable() {
|
||||
|
||||
if(!isValid()){
|
||||
return SHAL_Result::ERROR;
|
||||
}
|
||||
|
||||
SHAL_ADC_Control_Reg control_reg = getADCControlReg(m_ADCKey);
|
||||
if (*control_reg.reg & control_reg.enable_mask) {
|
||||
//request disable: ADEN=1 -> set ADDIS to disable
|
||||
*control_reg.reg |= control_reg.disable_mask;
|
||||
//wait until ADEN cleared (ISR.ADREADY == 0)
|
||||
if(!SHAL_WAIT_FOR_CONDITION_MS((*control_reg.reg & control_reg.enable_mask) == 0, 100)){
|
||||
return SHAL_Result::ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return SHAL_Result::OKAY;
|
||||
}
|
||||
|
||||
bool SHAL_ADC::isValid() {
|
||||
if(m_ADCKey == ADC_Key::INVALID || m_ADCKey == ADC_Key::NUM_ADC){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
SHAL_Result SHAL_ADC::configureResolution(SHAL_ADC_Resolution resolution) {
|
||||
if(!isValid()){
|
||||
return SHAL_Result::ERROR;
|
||||
}
|
||||
|
||||
SHAL_ADC_Config_Reg config_reg = getADCConfigReg(m_ADCKey);
|
||||
|
||||
SHAL_set_bits(config_reg.reg,2)
|
||||
|
||||
return SHAL_Result::OKAY;
|
||||
}
|
||||
|
||||
SHAL_Result SHAL_ADC::configureAlignment(SHAL_ADC_Alignment alignment) {
|
||||
if(!isValid()){
|
||||
return SHAL_Result::ERROR;
|
||||
}
|
||||
|
||||
SHAL_ADC_Config_Reg config_reg = getADCConfigReg(m_ADCKey);
|
||||
|
||||
*config_reg.reg &= ~(0x1UL << config_reg.alignment_offset); //TODO check if this needs to be abstracted (Do other platforms have >2 resolution possibilities?
|
||||
*config_reg.reg |= static_cast<uint8_t>(alignment) << config_reg.alignment_offset;
|
||||
|
||||
return SHAL_Result::OKAY;
|
||||
}
|
||||
|
||||
SHAL_ADC &ADCManager::get(ADC_Key key) {
|
||||
return m_ADCs[static_cast<uint8_t>(key)];
|
||||
}
|
||||
|
||||
@@ -109,7 +109,7 @@ void SHAL_GPIO::useAsExternalInterrupt(TriggerMode mode, EXTICallback callback)
|
||||
|
||||
uint16_t SHAL_GPIO::analogRead(ADC_SampleTime sampleTime) {
|
||||
|
||||
ADC_Channel channel = getGPIOPortInfo(m_GPIO_KEY).ADCChannel;
|
||||
SHAL_ADC_Channel channel = getGPIOPortInfo(m_GPIO_KEY).ADCChannel;
|
||||
|
||||
return GPIOManager::getGPIOADC().singleConvertSingle(channel,sampleTime);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user