From cab3be97e645aa4f00936c2cbd5d79254b12ceca Mon Sep 17 00:00:00 2001 From: Jacek Fedorynski Date: Tue, 8 Oct 2024 02:17:33 +0200 Subject: [PATCH] Use TIM2 Output Compare to autotrigger GPIO pin Makes it so that triggering the GPIO pin is uniformly spread over a span of 1ms by using the timer output compare function. Because the pin toggling is done in hardware, the timing is not affected by interrupt handlers and higher prority threads. Changes the GPIO pin used from PB15 (Arduino D11) to PA15 (Arduino D9). Doesn't take the "Auto-trigger Level" setting into consideration. --- src/gfx_main.c | 4 ++++ src/hardware_config.c | 18 ++++++++++++++++++ src/stm32f7xx_hal_msp.c | 2 +- src/xlat.c | 13 +++++-------- 4 files changed, 28 insertions(+), 9 deletions(-) diff --git a/src/gfx_main.c b/src/gfx_main.c index db79318..d24b85c 100644 --- a/src/gfx_main.c +++ b/src/gfx_main.c @@ -24,6 +24,7 @@ #include "gfx_settings.h" #include "stdio_glue.h" #include "usb_host.h" +#include "hardware_config.h" #define Y_CHART_SIZE_X 410 #define Y_CHART_SIZE_Y 130 @@ -144,6 +145,7 @@ void auto_trigger_callback(lv_timer_t * timer) lv_timer_set_period(timer, AUTO_TRIGGER_PERIOD_MS + (rand() % 10)); } else { auto_trigger_clear_timer(); + hw_exti_interrupts_enable(); } } @@ -158,7 +160,9 @@ static void btn_trigger_event_cb(lv_event_t * e) // Already running count = 0; auto_trigger_clear_timer(); + hw_exti_interrupts_enable(); } else { + hw_exti_interrupts_disable(); // Trigger a new series of measurements printf("AutoTrigger activated\n"); count = 1000; diff --git a/src/hardware_config.c b/src/hardware_config.c index 55b6c2d..d190025 100644 --- a/src/hardware_config.c +++ b/src/hardware_config.c @@ -351,6 +351,7 @@ static void MX_TIM1_Init(void) static void MX_TIM2_Init(void) { TIM_ClockConfigTypeDef sClockSourceConfig = {0}; + TIM_OC_InitTypeDef sConfigOC = {0}; TIM_MasterConfigTypeDef sMasterConfig = {0}; htim2.Instance = TIM2; @@ -368,6 +369,18 @@ static void MX_TIM2_Init(void) { Error_Handler(); } + if (HAL_TIM_OC_Init(&htim2) != HAL_OK) + { + Error_Handler(); + } + + sConfigOC.OCMode = TIM_OCMODE_TOGGLE; + sConfigOC.Pulse = 0; + sConfigOC.OCPolarity = TIM_OCPOLARITY_LOW; + if (HAL_TIM_OC_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1) != HAL_OK) + { + Error_Handler(); + } sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK) @@ -377,6 +390,11 @@ static void MX_TIM2_Init(void) // Start as free-running timer right away HAL_TIM_Base_Start(&htim2); + if (HAL_TIM_OC_Start(&htim2, TIM_CHANNEL_1) != HAL_OK) + { + Error_Handler(); + } + HAL_TIM_MspPostInit(&htim2); } /** diff --git a/src/stm32f7xx_hal_msp.c b/src/stm32f7xx_hal_msp.c index 41e93be..bdd1945 100644 --- a/src/stm32f7xx_hal_msp.c +++ b/src/stm32f7xx_hal_msp.c @@ -519,7 +519,7 @@ void HAL_TIM_MspPostInit(TIM_HandleTypeDef* htim) PA15 ------> TIM2_CH1 */ GPIO_InitStruct.Pin = ARDUINO_PWM_D9_Pin; - GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Alternate = GPIO_AF1_TIM2; diff --git a/src/xlat.c b/src/xlat.c index 90eeb98..33d1a8d 100644 --- a/src/xlat.c +++ b/src/xlat.c @@ -602,18 +602,15 @@ enum xlat_mode xlat_get_mode(void) void xlat_auto_trigger_action(void) { - // random delay, such that we do not always perfectly align with USB timing - srand(xTaskGetTickCount()); - int val = rand() & 0xFFF; - for (volatile int i = 0; i < val; i++) { - __NOP(); - } - HAL_GPIO_WritePin(ARDUINO_D11_GPIO_Port, ARDUINO_D11_Pin, auto_trigger_level_high ? GPIO_PIN_SET : GPIO_PIN_RESET); + uint32_t delay = rand() % 1000 + 100; + last_btn_gpio_timestamp = xlat_counter_1mhz_get() + delay; + htim2.Instance->CCR1 = last_btn_gpio_timestamp; + gpio_irq_producer++; } void xlat_auto_trigger_turn_off_action(void) { - HAL_GPIO_WritePin(ARDUINO_D11_GPIO_Port, ARDUINO_D11_Pin, auto_trigger_level_high ? GPIO_PIN_RESET : GPIO_PIN_SET); + htim2.Instance->CCR1 = xlat_counter_1mhz_get() + 100; } void xlat_auto_trigger_level_set(bool high)