Abstracted registers for PWM and other timer modes
This commit is contained in:
@@ -44,6 +44,24 @@ enum class GPIO_Key : uint8_t {
|
||||
INVALID
|
||||
};
|
||||
|
||||
enum class GPIO_Alternate_Function_Mapping {
|
||||
A0_TIM2CH1 = 0x01,
|
||||
A1_TIM2CH2 = 0x01,
|
||||
A2_TIM2CH3 = 0x01,
|
||||
A3_TIM2CH4 = 0x01,
|
||||
A5_TIM2CH1 = 0x01,
|
||||
A6_TIM1BKIN = 0x01,
|
||||
A7_TIM1CH1N = 0x01,
|
||||
A8_TIM1CH1 = 0x01,
|
||||
A9_TIM1CH2 = 0x01,
|
||||
A10_TIM1CH3 = 0x01,
|
||||
A11_TIM1CH4 = 0x01,
|
||||
A12_TIM1ETR = 0x01,
|
||||
A15_TIM2CH1 = 0x01,
|
||||
B0_TIM2CH2N = 0x01,
|
||||
B1_TIM1CH3N = 0x01,
|
||||
};
|
||||
|
||||
static volatile GPIO_TypeDef * GPIO_TABLE[2] = { //Lookup table for ADCs
|
||||
GPIOA,
|
||||
GPIOB
|
||||
@@ -114,7 +132,7 @@ static inline SHAL_GPIO_Pullup_Pulldown_Register getGPIOPUPDRegister(const GPIO_
|
||||
|
||||
static inline SHAL_GPIO_Alternate_Function_Register getGPIOAlternateFunctionRegister(const GPIO_Key key){
|
||||
|
||||
uint32_t pinNumber = static_cast<uint8_t>(key); //Number of pin (We need 0-7 to be AFR 1 and 8-15 to be AFR 2
|
||||
uint32_t pinNumber = static_cast<uint8_t>(key); //Number of pin (We need 0-7 to be AFR 1 and 8-15 to be AFR 2)
|
||||
uint32_t afrIndex = pinNumber < 8 ? 0 : 1;
|
||||
|
||||
volatile uint32_t* reg = &GPIO_TABLE[static_cast<uint8_t>(key) / 16]->AFR[afrIndex];
|
||||
|
||||
@@ -31,6 +31,7 @@ public:
|
||||
|
||||
|
||||
void setAlternateFunction(GPIO_Alternate_Function AF) volatile;
|
||||
void setAlternateFunction(GPIO_Alternate_Function_Mapping AF) volatile;
|
||||
|
||||
void setOutputType(PinType type) volatile;
|
||||
|
||||
@@ -38,7 +39,6 @@ public:
|
||||
|
||||
void setInternalResistor(InternalResistorType type) volatile;
|
||||
|
||||
|
||||
void useAsExternalInterrupt(TriggerMode mode, EXTICallback callback);
|
||||
|
||||
SHAL_Result setPinMode(PinMode mode) volatile;
|
||||
|
||||
@@ -53,7 +53,6 @@ static IRQn_Type IRQN_TABLE[6] = {
|
||||
#define SHAL_TIM16 TimerManager::get(Timer_Key::S_TIM16)
|
||||
|
||||
|
||||
|
||||
static inline SHAL_TIM_Status_Register getTimerStatusRegister(Timer_Key key){
|
||||
|
||||
SHAL_TIM_Status_Register res = {nullptr, TIM_SR_UIF};
|
||||
@@ -66,7 +65,11 @@ static inline SHAL_TIM_Status_Register getTimerStatusRegister(Timer_Key key){
|
||||
|
||||
static inline SHAL_TIM_Control_Register_1 getTimerControlRegister1(Timer_Key key){
|
||||
|
||||
SHAL_TIM_Control_Register_1 res = {nullptr, TIM_CR1_CEN_Msk, TIM_CR1_UDIS, TIM_CR1_OPM, TIM_CR1_CMS_Pos};
|
||||
SHAL_TIM_Control_Register_1 res = {nullptr, TIM_CR1_CEN_Msk,
|
||||
TIM_CR1_UDIS,
|
||||
TIM_CR1_OPM,
|
||||
TIM_CR1_CMS_Pos,
|
||||
TIM_CR1_ARPE};
|
||||
|
||||
volatile TIM_TypeDef* tim = TIM_TABLE[static_cast<uint8_t>(key)];
|
||||
|
||||
@@ -131,6 +134,68 @@ static inline SHAL_TIM_RCC_Register getTimerRCC(Timer_Key t) {
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
static inline SHAL_TIM_Capture_Compare_Mode_Registers_Input getTimerCaptureCompareModeRegisters(Timer_Key key){
|
||||
SHAL_TIM_Capture_Compare_Mode_Registers_Input res = {{nullptr,
|
||||
nullptr},
|
||||
TIM_CCMR1_CC1S_Pos,
|
||||
TIM_CCMR1_IC1PSC_Pos,
|
||||
TIM_CCMR1_IC1F_Pos,
|
||||
TIM_CCMR1_CC2S_Pos,
|
||||
TIM_CCMR1_IC2PSC_Pos,
|
||||
TIM_CCMR1_IC2F_Pos
|
||||
};
|
||||
|
||||
volatile TIM_TypeDef* tim = TIM_TABLE[static_cast<uint8_t>(key)];
|
||||
|
||||
res.regs[0] = &tim->CCMR1;
|
||||
res.regs[1] = &tim->CCMR2;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static inline SHAL_TIM_Capture_Compare_Mode_Registers_Output
|
||||
getTimerCaptureCompareModeRegistersOutput(Timer_Key key) {
|
||||
SHAL_TIM_Capture_Compare_Mode_Registers_Output res = {
|
||||
{nullptr, nullptr},
|
||||
TIM_CCMR1_CC1S_Pos, //Channel 1 Capture/Compare selection
|
||||
TIM_CCMR1_OC1FE_Pos, //Channel 1 Fast enable
|
||||
TIM_CCMR1_OC1PE_Pos, //Channel 1 Preload enable
|
||||
TIM_CCMR1_OC1M_Pos, //Channel 1 Mode (OC1M)
|
||||
TIM_CCMR1_OC1CE_Pos, //Channel 1 Clear enable
|
||||
TIM_CCMR1_CC2S_Pos, //Channel 2 Capture/Compare selection
|
||||
TIM_CCMR1_OC2FE_Pos, //Channel 2 Fast enable
|
||||
TIM_CCMR1_OC2PE_Pos, //Channel 2 Preload enable
|
||||
TIM_CCMR1_OC2M_Pos, //Channel 2 Mode (OC2M)
|
||||
TIM_CCMR1_OC2CE_Pos //Channel 2 Clear enable
|
||||
};
|
||||
|
||||
volatile TIM_TypeDef* tim = TIM_TABLE[static_cast<uint8_t>(key)];
|
||||
res.regs[0] = &tim->CCMR1;
|
||||
res.regs[1] = &tim->CCMR2;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static inline SHAL_TIM_Break_Dead_Time_Register getBreakDeadTimeRegister(Timer_Key key){
|
||||
|
||||
SHAL_TIM_Break_Dead_Time_Register res = {nullptr, 1UL << 15};
|
||||
|
||||
volatile TIM_TypeDef* tim = TIM_TABLE[static_cast<uint8_t>(key)];
|
||||
|
||||
res.reg = &tim->BDTR;
|
||||
return res;
|
||||
}
|
||||
|
||||
static inline SHAL_TIM_Capture_Compare_Enable_Register getTimerCaptureCompareEnableRegister(Timer_Key key){
|
||||
volatile TIM_TypeDef* tim = TIM_TABLE[static_cast<uint8_t>(key)];
|
||||
return {&tim->CCER};
|
||||
}
|
||||
|
||||
static inline SHAL_TIM_Capture_Compare_Register getTimerCaptureCompareRegister(Timer_Key key){
|
||||
volatile TIM_TypeDef* tim = TIM_TABLE[static_cast<uint8_t>(key)];
|
||||
return {&tim->CCR2};
|
||||
}
|
||||
|
||||
|
||||
//Get timer IRQN from lookup table
|
||||
static inline IRQn_Type getTimerIRQn(Timer_Key t) {
|
||||
|
||||
@@ -38,6 +38,8 @@ public:
|
||||
//Enable interrupts
|
||||
void enableInterrupt();
|
||||
|
||||
void setPWMMode(SHAL_Timer_Channel channel, SHAL_Timer_Channel_Main_Output_Mode mainOutputMode, SHAL_Timer_Channel_Complimentary_Output_Mode complimentaryOutputMode);
|
||||
|
||||
//Set TIMER_KEY IRQ callback function
|
||||
void setCallbackFunc(TimerCallback callback){
|
||||
registerTimerCallback(m_key, callback);
|
||||
|
||||
@@ -18,6 +18,7 @@ struct SHAL_TIM_Control_Register_1 {
|
||||
uint32_t update_disable_mask;
|
||||
uint32_t one_pulse_mode_mask;
|
||||
uint32_t center_align_mode_offset;
|
||||
uint32_t auto_reload_preload_enable_mask;
|
||||
};
|
||||
|
||||
struct SHAL_TIM_DMA_Interrupt_Enable_Register {
|
||||
@@ -45,4 +46,81 @@ struct SHAL_TIM_Auto_Reload_Register {
|
||||
uint32_t offset;
|
||||
};
|
||||
|
||||
#endif //SHMINGO_HAL_SHAL_TIM_TYPES_H
|
||||
struct SHAL_TIM_Capture_Compare_Mode_Registers_Input {
|
||||
volatile uint32_t* regs[2];
|
||||
uint32_t input_capture_1_filter_offset;
|
||||
uint32_t input_capture_1_prescaler_offset;
|
||||
uint32_t capture_compare_1_selection_offset;
|
||||
uint32_t input_capture_2_filter_offset;
|
||||
uint32_t input_capture_2_prescaler_offset;
|
||||
uint32_t capture_compare_2_selection_offset;
|
||||
};
|
||||
|
||||
struct SHAL_TIM_Capture_Compare_Mode_Registers_Output {
|
||||
volatile uint32_t* regs[2];
|
||||
uint32_t capture_compare_1_selection_offset;
|
||||
uint32_t output_compare_1_fast_enable_offset;
|
||||
uint32_t output_compare_1_preload_enable_offset;
|
||||
uint32_t output_compare_1_mode_offset;
|
||||
uint32_t output_compare_1_clear_enable_offset;
|
||||
uint32_t capture_compare_2_selection_offset;
|
||||
uint32_t output_compare_2_fast_enable_offset;
|
||||
uint32_t output_compare_2_preload_enable_offset;
|
||||
uint32_t output_compare_2_mode_offset;
|
||||
uint32_t output_compare_2_clear_enable_offset;
|
||||
};
|
||||
|
||||
struct SHAL_TIM_Break_Dead_Time_Register {
|
||||
volatile uint32_t* reg;
|
||||
uint32_t main_output_enable_mask;
|
||||
};
|
||||
|
||||
struct SHAL_TIM_Capture_Compare_Enable_Register {
|
||||
volatile uint32_t* reg;
|
||||
};
|
||||
|
||||
struct SHAL_TIM_Capture_Compare_Register {
|
||||
volatile uint32_t* reg;
|
||||
};
|
||||
|
||||
|
||||
|
||||
enum class SHAL_TIM_Output_Compare_Mode : uint8_t {
|
||||
Frozen = 0b000, //Output compare frozen
|
||||
ActiveOnMatch = 0b001, //Set output to active level on match
|
||||
InactiveOnMatch = 0b010, //Set output to inactive level on match
|
||||
Toggle = 0b011, //Toggle output on match
|
||||
ForceInactive = 0b100, //Force output to inactive
|
||||
ForceActive = 0b101, //Force output to active
|
||||
PWMMode1 = 0b110, //PWM mode 1 (active until compare match)
|
||||
PWMMode2 = 0b111, //PWM mode 2 (inactive until compare match)
|
||||
};
|
||||
|
||||
enum class SHAL_TIM_Output_Compare_Preload : uint8_t {
|
||||
Disabled = 0b0, //CCRx register is updated immediately
|
||||
Enabled = 0b1, //CCRx register is buffered; updated on update event (UEV)
|
||||
};
|
||||
|
||||
enum class SHAL_Timer_Channel : uint8_t { //TODO change if other timers have fewer than 6 channels
|
||||
CH1 = 0,
|
||||
CH2 = 1,
|
||||
CH3 = 2,
|
||||
CH4 = 3,
|
||||
CH5 = 4,
|
||||
CH6 = 5,
|
||||
};
|
||||
|
||||
enum class SHAL_Timer_Channel_Main_Output_Mode : uint8_t {
|
||||
Disabled = 0b00,
|
||||
Polarity_Normal = 0b01,
|
||||
Polarity_Reversed = 0b11,
|
||||
};
|
||||
|
||||
enum class SHAL_Timer_Channel_Complimentary_Output_Mode : uint8_t {
|
||||
Disabled = 0b00,
|
||||
Polarity_Normal = 0b01,
|
||||
Polarity_Reversed = 0b11,
|
||||
};
|
||||
|
||||
|
||||
#endif //SHAL_TIM_TYPES_H
|
||||
|
||||
@@ -109,6 +109,12 @@ uint16_t SHAL_GPIO::analogRead(SHAL_ADC_SampleTime sampleTime) {
|
||||
return GPIOManager::getGPIOADC().singleConvertSingle(channel,sampleTime);
|
||||
}
|
||||
|
||||
void SHAL_GPIO::setAlternateFunction(GPIO_Alternate_Function_Mapping AF) volatile {
|
||||
setPinMode(PinMode::ALTERNATE_FUNCTION_MODE);
|
||||
auto alternateFunctionReg = getGPIOAlternateFunctionRegister(m_GPIO_KEY);
|
||||
SHAL_set_bits(alternateFunctionReg.reg,4,static_cast<uint8_t>(AF),alternateFunctionReg.offset);
|
||||
}
|
||||
|
||||
|
||||
SHAL_GPIO& GPIOManager::get(GPIO_Key key) {
|
||||
|
||||
|
||||
@@ -54,6 +54,21 @@ void Timer::init(uint32_t prescaler, uint32_t autoReload) {
|
||||
setARR(autoReload);
|
||||
}
|
||||
|
||||
void Timer::setPWMMode(SHAL_Timer_Channel channel, SHAL_Timer_Channel_Main_Output_Mode mainOutputMode,
|
||||
SHAL_Timer_Channel_Complimentary_Output_Mode complimentaryOutputMode) {
|
||||
|
||||
uint8_t fullModeMask = static_cast<uint8_t>(mainOutputMode) | (static_cast<uint8_t>(complimentaryOutputMode) << 2);
|
||||
uint32_t offset = static_cast<uint8_t>(channel) * 4;
|
||||
|
||||
auto ccer = getTimerCaptureCompareEnableRegister(m_key);
|
||||
|
||||
if(static_cast<uint8_t>(m_key) > 3){
|
||||
fullModeMask &= (0b0011); //Clear bits for complimentary output since channels 4,5,6 don't support it
|
||||
}
|
||||
|
||||
SHAL_set_bits(ccer.reg,4,fullModeMask,offset);
|
||||
}
|
||||
|
||||
|
||||
Timer &TimerManager::get(Timer_Key timer_key) {
|
||||
|
||||
|
||||
@@ -26,6 +26,10 @@ void timer2callback(){
|
||||
|
||||
}
|
||||
|
||||
void b0PWM(){
|
||||
PIN(B0).toggle();
|
||||
}
|
||||
|
||||
int main() {
|
||||
|
||||
SHAL_init();
|
||||
@@ -33,8 +37,6 @@ int main() {
|
||||
SHAL_UART2.init(UART_Pair_Key::Tx2A2_Rx2A3);
|
||||
SHAL_UART2.begin(115200);
|
||||
|
||||
SHAL_UART2.sendString("Begin\r\n");
|
||||
|
||||
PIN(A0).setPinMode(PinMode::ANALOG_MODE);
|
||||
PIN(A1).setPinMode(PinMode::ANALOG_MODE);
|
||||
PIN(A4).setPinMode(PinMode::ANALOG_MODE);
|
||||
@@ -42,7 +44,7 @@ int main() {
|
||||
PIN(A6).setPinMode(PinMode::ANALOG_MODE);
|
||||
PIN(A7).setPinMode(PinMode::ANALOG_MODE);
|
||||
|
||||
SHAL_UART2.sendString("Hello\r\n");
|
||||
PIN(B0).setPinMode(PinMode::OUTPUT_MODE);
|
||||
|
||||
SHAL_TIM2.init(4000000,400);
|
||||
|
||||
@@ -50,7 +52,10 @@ int main() {
|
||||
SHAL_TIM2.enableInterrupt();
|
||||
SHAL_TIM2.start();
|
||||
|
||||
SHAL_UART2.sendString("Hello\r\n");
|
||||
SHAL_TIM6.init(4000000,1);
|
||||
SHAL_TIM6.setCallbackFunc(b0PWM);
|
||||
SHAL_TIM6.enableInterrupt();
|
||||
SHAL_TIM6.start();
|
||||
|
||||
while (true) {
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user