From 09966d01d5d2a8e33ea2484629e56bc36437ae60 Mon Sep 17 00:00:00 2001 From: oganigl Date: Mon, 4 May 2026 13:01:22 +0200 Subject: [PATCH 01/11] add init --- Inc/HALAL/Services/Encoder/Encoder.hpp | 29 +++++++++++++------------- Inc/HALAL/Services/PWM/DualPWM.hpp | 20 +++++++++++++----- 2 files changed, 30 insertions(+), 19 deletions(-) diff --git a/Inc/HALAL/Services/Encoder/Encoder.hpp b/Inc/HALAL/Services/Encoder/Encoder.hpp index 8e1ddd1b9..631773e77 100644 --- a/Inc/HALAL/Services/Encoder/Encoder.hpp +++ b/Inc/HALAL/Services/Encoder/Encoder.hpp @@ -27,15 +27,13 @@ template class Encoder { inline static TimerWrapper* timer; inline static bool is_on = false; + inline static bool is_initialized = false; - Encoder(TimerWrapper* tim) { - if (timer == nullptr) { - init(tim); + Encoder(TimerWrapper* tim) { timer = tim; } + static void init() { + if (timer == nullptr || timer->instance == nullptr) { + PANIC("Timer instance is not set for encoder"); } - } - -public: - static void init(TimerWrapper* tim) { TIM_Encoder_InitTypeDef sConfig = {0}; TIM_MasterConfigTypeDef sMasterConfig = {0}; @@ -49,32 +47,35 @@ template class Encoder { sConfig.IC2Prescaler = TIM_ICPSC_DIV1; sConfig.IC2Filter = 0; - if (HAL_TIM_Encoder_Init(tim->instance->hal_tim, &sConfig) != HAL_OK) { + if (HAL_TIM_Encoder_Init(timer->instance->hal_tim, &sConfig) != HAL_OK) { ErrorHandler("Unable to init encoder"); return; } sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; - if (HAL_TIMEx_MasterConfigSynchronization(tim->instance->hal_tim, &sMasterConfig) != + if (HAL_TIMEx_MasterConfigSynchronization(timer->instance->hal_tim, &sMasterConfig) != HAL_OK) { ErrorHandler("Unable to config master synchronization in encoder"); return; } - tim->instance->tim->PSC = 5; + timer->instance->tim->PSC = 5; if constexpr (TimerWrapper::is_32bit_instance) { - tim->instance->tim->ARR = UINT32_MAX; + timer->instance->tim->ARR = UINT32_MAX; } else { - tim->instance->tim->ARR = UINT16_MAX; + timer->instance->tim->ARR = UINT16_MAX; } - timer = tim; } +public: static void turn_on() { + if (!is_initialized) { + init(); + is_initialized = true; + } if (is_on) return; - if (HAL_TIM_Encoder_GetState(timer->instance->hal_tim) == HAL_TIM_STATE_RESET) { ErrorHandler("Unable to get state from encoder"); return; diff --git a/Inc/HALAL/Services/PWM/DualPWM.hpp b/Inc/HALAL/Services/PWM/DualPWM.hpp index b0121ec3c..0c4c2369b 100644 --- a/Inc/HALAL/Services/PWM/DualPWM.hpp +++ b/Inc/HALAL/Services/PWM/DualPWM.hpp @@ -22,10 +22,13 @@ class DualPWM { friend TimerWrapper; TimerWrapper* timer; - uint32_t* frequency; float* duty_cycle = nullptr; + uint32_t* frequency; + uint32_t polarity; + uint32_t negated_polarity; bool is_on_positive = false; bool is_on_negative = false; + bool is_initialized = false; /* This constructor is private for a reason. Use TimerWrapper::get_dual_pwm */ DualPWM( @@ -35,10 +38,16 @@ class DualPWM { float* duty_ptr, uint32_t* frequency_ptr ) - : timer(tim) { - duty_cycle = duty_ptr; - frequency = frequency_ptr; + : timer(tim), duty_cycle(duty_ptr), frequency(frequency_ptr), polarity(polarity), + negated_polarity(negated_polarity) {} + + inline void initialize() { + if (is_initialized) + return; + if (timer == nullptr || timer->instance == nullptr || timer->instance->hal_tim == nullptr) { + PANIC(" DUALPWM requested before timer init"); + } TIM_OC_InitTypeDef sConfigOC = { .OCMode = TIM_OCMODE_PWM1, .Pulse = 0, @@ -53,10 +62,12 @@ class DualPWM { timer->template config_output_compare_channel(&sConfigOC); timer->template set_output_compare_preload_enable(); + is_initialized = true; } public: inline void turn_on() { + initialize(); turn_on_positive(); turn_on_negative(); } @@ -65,7 +76,6 @@ class DualPWM { turn_off_positive(); turn_off_negative(); } - void turn_on_positive() { if (this->is_on_positive) return; From a63ded98d0dd18c29378eed71b06fe564cd9e89a Mon Sep 17 00:00:00 2001 From: oganigl Date: Mon, 4 May 2026 21:10:38 +0200 Subject: [PATCH 02/11] use error handler --- Inc/HALAL/Services/Encoder/Encoder.hpp | 2 +- Inc/HALAL/Services/PWM/DualPWM.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Inc/HALAL/Services/Encoder/Encoder.hpp b/Inc/HALAL/Services/Encoder/Encoder.hpp index 631773e77..800b6a319 100644 --- a/Inc/HALAL/Services/Encoder/Encoder.hpp +++ b/Inc/HALAL/Services/Encoder/Encoder.hpp @@ -32,7 +32,7 @@ template class Encoder { Encoder(TimerWrapper* tim) { timer = tim; } static void init() { if (timer == nullptr || timer->instance == nullptr) { - PANIC("Timer instance is not set for encoder"); + ErrorHandler("Timer instance is not set for encoder"); } TIM_Encoder_InitTypeDef sConfig = {0}; TIM_MasterConfigTypeDef sMasterConfig = {0}; diff --git a/Inc/HALAL/Services/PWM/DualPWM.hpp b/Inc/HALAL/Services/PWM/DualPWM.hpp index 0c4c2369b..8de543538 100644 --- a/Inc/HALAL/Services/PWM/DualPWM.hpp +++ b/Inc/HALAL/Services/PWM/DualPWM.hpp @@ -46,7 +46,7 @@ class DualPWM { return; if (timer == nullptr || timer->instance == nullptr || timer->instance->hal_tim == nullptr) { - PANIC(" DUALPWM requested before timer init"); + ErrorHandler(" DUALPWM requested before timer init"); } TIM_OC_InitTypeDef sConfigOC = { .OCMode = TIM_OCMODE_PWM1, From 70694f340a7eee05b4bf8f3fb5d2bd8f31e47a9c Mon Sep 17 00:00:00 2001 From: oganigl Date: Mon, 4 May 2026 21:13:33 +0200 Subject: [PATCH 03/11] added changeset --- .changesets/init_timer.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .changesets/init_timer.md diff --git a/.changesets/init_timer.md b/.changesets/init_timer.md new file mode 100644 index 000000000..4af02d5f3 --- /dev/null +++ b/.changesets/init_timer.md @@ -0,0 +1,2 @@ +release: minor +summary: move initialization outside constructor From c5e2936b82c2715ff524f94876766bfe948840ec Mon Sep 17 00:00:00 2001 From: oganigl Date: Mon, 4 May 2026 21:27:00 +0200 Subject: [PATCH 04/11] modify encoder turn on and go back to init encoder --- Inc/HALAL/Services/Encoder/Encoder.hpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Inc/HALAL/Services/Encoder/Encoder.hpp b/Inc/HALAL/Services/Encoder/Encoder.hpp index 800b6a319..3a8e741bd 100644 --- a/Inc/HALAL/Services/Encoder/Encoder.hpp +++ b/Inc/HALAL/Services/Encoder/Encoder.hpp @@ -30,8 +30,10 @@ template class Encoder { inline static bool is_initialized = false; Encoder(TimerWrapper* tim) { timer = tim; } - static void init() { - if (timer == nullptr || timer->instance == nullptr) { + +public: +static void init(TimerWrapper* tim){ + if (tim == nullptr || tim->instance == nullptr) { ErrorHandler("Timer instance is not set for encoder"); } TIM_Encoder_InitTypeDef sConfig = {0}; @@ -47,31 +49,29 @@ template class Encoder { sConfig.IC2Prescaler = TIM_ICPSC_DIV1; sConfig.IC2Filter = 0; - if (HAL_TIM_Encoder_Init(timer->instance->hal_tim, &sConfig) != HAL_OK) { + if (HAL_TIM_Encoder_Init(tim->instance->hal_tim, &sConfig) != HAL_OK) { ErrorHandler("Unable to init encoder"); return; } sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; - if (HAL_TIMEx_MasterConfigSynchronization(timer->instance->hal_tim, &sMasterConfig) != + if (HAL_TIMEx_MasterConfigSynchronization(tim->instance->hal_tim, &sMasterConfig) != HAL_OK) { ErrorHandler("Unable to config master synchronization in encoder"); return; } - timer->instance->tim->PSC = 5; + tim->instance->tim->PSC = 5; if constexpr (TimerWrapper::is_32bit_instance) { - timer->instance->tim->ARR = UINT32_MAX; + tim->instance->tim->ARR = UINT32_MAX; } else { - timer->instance->tim->ARR = UINT16_MAX; + tim->instance->tim->ARR = UINT16_MAX; } } - -public: static void turn_on() { if (!is_initialized) { - init(); + init(timer); is_initialized = true; } if (is_on) From 0a29dded2e420241b1b15e8e5fda51772b0f4e49 Mon Sep 17 00:00:00 2001 From: oganigl Date: Mon, 4 May 2026 21:29:30 +0200 Subject: [PATCH 05/11] indentation --- Inc/HALAL/Services/Encoder/Encoder.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Inc/HALAL/Services/Encoder/Encoder.hpp b/Inc/HALAL/Services/Encoder/Encoder.hpp index 3a8e741bd..3a6f3a023 100644 --- a/Inc/HALAL/Services/Encoder/Encoder.hpp +++ b/Inc/HALAL/Services/Encoder/Encoder.hpp @@ -30,9 +30,9 @@ template class Encoder { inline static bool is_initialized = false; Encoder(TimerWrapper* tim) { timer = tim; } - + public: -static void init(TimerWrapper* tim){ + static void init(TimerWrapper* tim) { if (tim == nullptr || tim->instance == nullptr) { ErrorHandler("Timer instance is not set for encoder"); } From 6ebbdb0c2a58127a58157f9eb50936c46e1d726b Mon Sep 17 00:00:00 2001 From: oganigl Date: Tue, 5 May 2026 13:05:28 +0200 Subject: [PATCH 06/11] let see if this works --- Inc/HALAL/Services/Encoder/Encoder.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Inc/HALAL/Services/Encoder/Encoder.hpp b/Inc/HALAL/Services/Encoder/Encoder.hpp index 3a6f3a023..0202df3a7 100644 --- a/Inc/HALAL/Services/Encoder/Encoder.hpp +++ b/Inc/HALAL/Services/Encoder/Encoder.hpp @@ -68,6 +68,7 @@ template class Encoder { } else { tim->instance->tim->ARR = UINT16_MAX; } + timer = tim; } static void turn_on() { if (!is_initialized) { From 9d7ee17f0319d20d10fc22bf520a31ebeca0a2a6 Mon Sep 17 00:00:00 2001 From: oganigl Date: Tue, 5 May 2026 13:53:18 +0200 Subject: [PATCH 07/11] I hope Victor likes it --- .../Services/InputCapture/InputCapture.hpp | 21 ++++++++++++++----- Inc/HALAL/Services/PWM/DualPWM.hpp | 2 +- Inc/HALAL/Services/PWM/PWM.hpp | 18 +++++++++++----- 3 files changed, 30 insertions(+), 11 deletions(-) diff --git a/Inc/HALAL/Services/InputCapture/InputCapture.hpp b/Inc/HALAL/Services/InputCapture/InputCapture.hpp index d031c9c87..6de8c1f63 100644 --- a/Inc/HALAL/Services/InputCapture/InputCapture.hpp +++ b/Inc/HALAL/Services/InputCapture/InputCapture.hpp @@ -28,10 +28,17 @@ class InputCapture { TimerWrapper* timer = nullptr; TimerDomain::InputCaptureInfo* info = nullptr; bool is_on = false; - - InputCapture(TimerWrapper* tim) { - timer = tim; - + bool is_initialized = false; + InputCapture(TimerWrapper* tim): timer(tim){ + + + } + void init(){ + if (is_initialized) return; + if (timer == nullptr || timer->instance == nullptr || timer->instance->hal_tim == nullptr) { + ErrorHandler("Timer instance is not set for input capture"); + return; + } // Setup TimerDomain uint8_t ch_rising = static_cast(pin_rising.channel) - 1; uint8_t ch_falling = static_cast(channel_falling) - 1; @@ -61,10 +68,14 @@ class InputCapture { sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_FALLING; sConfigIC.ICSelection = TIM_ICSELECTION_INDIRECTTI; timer->template config_input_compare_channel(&sConfigIC); + is_initialized = true; } - public: void turn_on(void) { + if(is_initialized == false){ + init(); + return; + } if (is_on) return; diff --git a/Inc/HALAL/Services/PWM/DualPWM.hpp b/Inc/HALAL/Services/PWM/DualPWM.hpp index 8de543538..e04e2c21d 100644 --- a/Inc/HALAL/Services/PWM/DualPWM.hpp +++ b/Inc/HALAL/Services/PWM/DualPWM.hpp @@ -46,7 +46,7 @@ class DualPWM { return; if (timer == nullptr || timer->instance == nullptr || timer->instance->hal_tim == nullptr) { - ErrorHandler(" DUALPWM requested before timer init"); + ErrorHandler("Timer instance is not set for DualPWM"); } TIM_OC_InitTypeDef sConfigOC = { .OCMode = TIM_OCMODE_PWM1, diff --git a/Inc/HALAL/Services/PWM/PWM.hpp b/Inc/HALAL/Services/PWM/PWM.hpp index 305e4251c..3f654894c 100644 --- a/Inc/HALAL/Services/PWM/PWM.hpp +++ b/Inc/HALAL/Services/PWM/PWM.hpp @@ -21,6 +21,9 @@ template class PWM { uint32_t* frequency; float* duty_cycle = nullptr; bool is_on = false; + bool is_initialized = false; + uint32_t polarity; + uint32_t negated_polarity; /* This constructor is private for a reason. Use TimerWrapper::get_pwm */ PWM(TimerWrapper* tim, @@ -28,10 +31,12 @@ template class PWM { uint32_t negated_polarity, float* duty_ptr, uint32_t* frequency_ptr) - : timer(tim) { - duty_cycle = duty_ptr; - frequency = frequency_ptr; - + : timer(tim), polarity(polarity), negated_polarity(negated_polarity), duty_cycle(duty_ptr), frequency(frequency_ptr) { + + } + void init(){ + if(is_initialized) + return; TIM_OC_InitTypeDef sConfigOC = { .OCMode = TIM_OCMODE_PWM1, .Pulse = 0, @@ -45,10 +50,13 @@ template class PWM { }; timer->template config_output_compare_channel(&sConfigOC); timer->template set_output_compare_preload_enable(); + is_initialized = true; } - public: void turn_on() { + if(this->is_initialized == false){ + init(); + } if (this->is_on) return; From 012696876bdff9030496b6f498f4976863f5df65 Mon Sep 17 00:00:00 2001 From: oganigl Date: Tue, 5 May 2026 13:54:11 +0200 Subject: [PATCH 08/11] Someone promise me that if I commit using the terminal the indentation works, not true --- Inc/HALAL/Services/InputCapture/InputCapture.hpp | 13 ++++++------- Inc/HALAL/Services/PWM/PWM.hpp | 12 ++++++------ 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/Inc/HALAL/Services/InputCapture/InputCapture.hpp b/Inc/HALAL/Services/InputCapture/InputCapture.hpp index 6de8c1f63..fe9dac1cb 100644 --- a/Inc/HALAL/Services/InputCapture/InputCapture.hpp +++ b/Inc/HALAL/Services/InputCapture/InputCapture.hpp @@ -29,12 +29,10 @@ class InputCapture { TimerDomain::InputCaptureInfo* info = nullptr; bool is_on = false; bool is_initialized = false; - InputCapture(TimerWrapper* tim): timer(tim){ - - - } - void init(){ - if (is_initialized) return; + InputCapture(TimerWrapper* tim) : timer(tim) {} + void init() { + if (is_initialized) + return; if (timer == nullptr || timer->instance == nullptr || timer->instance->hal_tim == nullptr) { ErrorHandler("Timer instance is not set for input capture"); return; @@ -70,9 +68,10 @@ class InputCapture { timer->template config_input_compare_channel(&sConfigIC); is_initialized = true; } + public: void turn_on(void) { - if(is_initialized == false){ + if (is_initialized == false) { init(); return; } diff --git a/Inc/HALAL/Services/PWM/PWM.hpp b/Inc/HALAL/Services/PWM/PWM.hpp index 3f654894c..5f155891d 100644 --- a/Inc/HALAL/Services/PWM/PWM.hpp +++ b/Inc/HALAL/Services/PWM/PWM.hpp @@ -31,11 +31,10 @@ template class PWM { uint32_t negated_polarity, float* duty_ptr, uint32_t* frequency_ptr) - : timer(tim), polarity(polarity), negated_polarity(negated_polarity), duty_cycle(duty_ptr), frequency(frequency_ptr) { - - } - void init(){ - if(is_initialized) + : timer(tim), polarity(polarity), negated_polarity(negated_polarity), duty_cycle(duty_ptr), + frequency(frequency_ptr) {} + void init() { + if (is_initialized) return; TIM_OC_InitTypeDef sConfigOC = { .OCMode = TIM_OCMODE_PWM1, @@ -52,9 +51,10 @@ template class PWM { timer->template set_output_compare_preload_enable(); is_initialized = true; } + public: void turn_on() { - if(this->is_initialized == false){ + if (this->is_initialized == false) { init(); } if (this->is_on) From 439fa0e31928bde4996f65912700dfa187454ba1 Mon Sep 17 00:00:00 2001 From: oganigl Date: Tue, 5 May 2026 13:55:04 +0200 Subject: [PATCH 09/11] better explanation of my changes --- .changesets/init_timer.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changesets/init_timer.md b/.changesets/init_timer.md index 4af02d5f3..860ffdde4 100644 --- a/.changesets/init_timer.md +++ b/.changesets/init_timer.md @@ -1,2 +1,2 @@ release: minor -summary: move initialization outside constructor +summary: move initialization outside constructor in PWM, DualPWM, Encoder and InputCapture From bfd4cdaa1ed3916ae8fe341949797b8a1c81d7ae Mon Sep 17 00:00:00 2001 From: oganigl Date: Tue, 5 May 2026 13:58:39 +0200 Subject: [PATCH 10/11] next time I build before commiting Co-authored-by: Copilot --- Inc/HALAL/Services/InputCapture/InputCapture.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Inc/HALAL/Services/InputCapture/InputCapture.hpp b/Inc/HALAL/Services/InputCapture/InputCapture.hpp index fe9dac1cb..7a5f6af61 100644 --- a/Inc/HALAL/Services/InputCapture/InputCapture.hpp +++ b/Inc/HALAL/Services/InputCapture/InputCapture.hpp @@ -40,9 +40,9 @@ class InputCapture { // Setup TimerDomain uint8_t ch_rising = static_cast(pin_rising.channel) - 1; uint8_t ch_falling = static_cast(channel_falling) - 1; - info = &TimerDomain::input_capture_info_backing[tim->instance->timer_idx][ch_rising]; - TimerDomain::input_capture_info[tim->instance->timer_idx][ch_rising] = info; - TimerDomain::input_capture_info[tim->instance->timer_idx][ch_falling] = info; + info = &TimerDomain::input_capture_info_backing[timer->instance->timer_idx][ch_rising]; + TimerDomain::input_capture_info[timer->instance->timer_idx][ch_rising] = info; + TimerDomain::input_capture_info[timer->instance->timer_idx][ch_falling] = info; info->channel_rising = ch_rising; info->channel_falling = ch_falling; From da8054c8c5f910e2754ed3d6a6cc0f91a0a432ee Mon Sep 17 00:00:00 2001 From: oganigl Date: Tue, 5 May 2026 14:04:45 +0200 Subject: [PATCH 11/11] Okay I hope Victor is Happy now, xd Co-authored-by: Copilot --- Inc/HALAL/Services/PWM/PWM.hpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Inc/HALAL/Services/PWM/PWM.hpp b/Inc/HALAL/Services/PWM/PWM.hpp index 5f155891d..396d25427 100644 --- a/Inc/HALAL/Services/PWM/PWM.hpp +++ b/Inc/HALAL/Services/PWM/PWM.hpp @@ -36,6 +36,9 @@ template class PWM { void init() { if (is_initialized) return; + if (timer == nullptr || timer->instance == nullptr || timer->instance->hal_tim == nullptr) { + ErrorHandler("Timer instance is not set for PWM"); + } TIM_OC_InitTypeDef sConfigOC = { .OCMode = TIM_OCMODE_PWM1, .Pulse = 0,