big refactoring: J1939, log output, state machine bug fixes

This commit is contained in:
2026-05-07 22:12:13 +03:00
parent 137c9d3c8d
commit 7a74ef1367
49 changed files with 2574 additions and 684 deletions
+194
View File
@@ -0,0 +1,194 @@
#include "cp.h"
#include "tim.h"
#define CP_CAPTURE_TARGET_CLK_HZ 1000000U
#define CP_INPUT_SIGNAL_INVERTED 1U
typedef enum {
CP_WAIT_RISING_1 = 0,
CP_WAIT_FALLING,
CP_WAIT_RISING_2
} CP_CaptureState_t;
static volatile CP_CaptureState_t cp_capture_state = CP_WAIT_RISING_1;
static volatile uint32_t cp_rise_1 = 0;
static volatile uint32_t cp_fall = 0;
static volatile uint32_t cp_rise_2 = 0;
static volatile uint32_t cp_last_update_ms = 0;
static volatile CP_Measurement_t cp_measurement = {0, 0, 0};
static uint32_t CP_TicksDiff(uint32_t now, uint32_t prev, uint32_t arr);
static uint32_t CP_GetTimerClockHz(void);
static void CP_ApplyStateOutputs(void);
static uint32_t CP_GetTim3InputClockHz(void);
void CP_Init(void) {
TIM_IC_InitTypeDef sConfigIC = {0};
uint32_t tim3_input_clk = CP_GetTim3InputClockHz();
uint32_t target_prescaler = 0U;
if (tim3_input_clk > CP_CAPTURE_TARGET_CLK_HZ) {
target_prescaler = (tim3_input_clk / CP_CAPTURE_TARGET_CLK_HZ) - 1U;
}
if (target_prescaler > 0xFFFFU) {
target_prescaler = 0xFFFFU;
}
__HAL_TIM_SET_PRESCALER(&htim3, (uint16_t)target_prescaler);
__HAL_TIM_SET_COUNTER(&htim3, 0U);
sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING;
sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;
sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;
sConfigIC.ICFilter = 2;
HAL_TIM_IC_ConfigChannel(&htim3, &sConfigIC, TIM_CHANNEL_2);
cp_capture_state = CP_WAIT_RISING_1;
cp_measurement.valid = 0;
cp_last_update_ms = HAL_GetTick();
CP_ApplyStateOutputs();
HAL_TIM_IC_Start_IT(&htim3, TIM_CHANNEL_2);
}
void CP_Task(void) {
CP_ApplyStateOutputs();
if ((HAL_GetTick() - cp_last_update_ms) > 200U) {
cp_measurement.valid = 0;
cp_measurement.frequency_hz = 0;
cp_measurement.duty_percent = 0;
}
}
CP_Measurement_t CP_GetMeasurement(void) {
CP_Measurement_t snapshot;
__disable_irq();
snapshot = cp_measurement;
__enable_irq();
return snapshot;
}
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) {
if ((htim->Instance != TIM3) || (htim->Channel != HAL_TIM_ACTIVE_CHANNEL_2)) {
return;
}
uint32_t captured = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2);
uint32_t arr = __HAL_TIM_GET_AUTORELOAD(htim);
TIM_RESET_CAPTUREPOLARITY(htim, TIM_CHANNEL_2);
if (cp_capture_state == CP_WAIT_RISING_1) {
cp_rise_1 = captured;
cp_capture_state = CP_WAIT_FALLING;
TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_2, TIM_INPUTCHANNELPOLARITY_FALLING);
return;
}
if (cp_capture_state == CP_WAIT_FALLING) {
cp_fall = captured;
cp_capture_state = CP_WAIT_RISING_2;
TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_2, TIM_INPUTCHANNELPOLARITY_RISING);
return;
}
cp_rise_2 = captured;
cp_capture_state = CP_WAIT_RISING_1;
TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_2, TIM_INPUTCHANNELPOLARITY_RISING);
uint32_t period_ticks = CP_TicksDiff(cp_rise_2, cp_rise_1, arr);
uint32_t high_ticks = CP_TicksDiff(cp_fall, cp_rise_1, arr);
uint32_t timer_clk = CP_GetTimerClockHz();
if ((period_ticks == 0U) || (high_ticks > period_ticks) || (timer_clk == 0U)) {
cp_measurement.valid = 0;
return;
}
cp_measurement.frequency_hz = timer_clk / period_ticks;
uint32_t duty_high = (high_ticks * 100U + (period_ticks / 2U)) / period_ticks; /* rounded */
if (duty_high > 100U) {
duty_high = 100U;
}
uint32_t duty = duty_high;
#if CP_INPUT_SIGNAL_INVERTED
duty = 100U - duty_high;
#endif
cp_measurement.duty_percent = (uint8_t)duty;
cp_measurement.valid = 1;
cp_last_update_ms = HAL_GetTick();
}
static uint32_t CP_TicksDiff(uint32_t now, uint32_t prev, uint32_t arr) {
if (now >= prev) {
return now - prev;
}
return (arr - prev + 1U) + now;
}
static uint32_t CP_GetTimerClockHz(void) {
uint32_t timclk = CP_GetTim3InputClockHz();
uint32_t prescaler = htim3.Instance->PSC;
return timclk / (prescaler + 1U);
}
static uint32_t CP_GetTim3InputClockHz(void) {
RCC_ClkInitTypeDef clk_init = {0};
uint32_t flash_latency = 0U;
uint32_t pclk1 = HAL_RCC_GetPCLK1Freq();
HAL_RCC_GetClockConfig(&clk_init, &flash_latency);
if (clk_init.APB1CLKDivider == RCC_HCLK_DIV1) {
return pclk1;
}
return pclk1 * 2U;
}
static void CP_ApplyStateOutputs(void) {
static CP_State_t last_state = (CP_State_t)0xFF;
if (last_state == cp_state) {
return;
}
switch (cp_state) {
case EV_STATE_A_IDLE:
HAL_GPIO_WritePin(CP_RELAY_GPIO_Port, CP_RELAY_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(CP_STATE_C_GPIO_Port, CP_STATE_C_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(CP_STATE_F_GPIO_Port, CP_STATE_F_Pin, GPIO_PIN_RESET);
break;
case EV_STATE_B_CONN_PREP:
HAL_GPIO_WritePin(CP_RELAY_GPIO_Port, CP_RELAY_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(CP_STATE_C_GPIO_Port, CP_STATE_C_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(CP_STATE_F_GPIO_Port, CP_STATE_F_Pin, GPIO_PIN_RESET);
break;
case EV_STATE_C_CONN_ACTIVE:
HAL_GPIO_WritePin(CP_RELAY_GPIO_Port, CP_RELAY_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(CP_STATE_C_GPIO_Port, CP_STATE_C_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(CP_STATE_F_GPIO_Port, CP_STATE_F_Pin, GPIO_PIN_RESET);
break;
case EV_STATE_F_ERROR:
HAL_GPIO_WritePin(CP_RELAY_GPIO_Port, CP_RELAY_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(CP_STATE_C_GPIO_Port, CP_STATE_C_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(CP_STATE_F_GPIO_Port, CP_STATE_F_Pin, GPIO_PIN_SET);
break;
case EV_STATE_D_CONN_ACT_VENT:
HAL_GPIO_WritePin(CP_RELAY_GPIO_Port, CP_RELAY_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(CP_STATE_C_GPIO_Port, CP_STATE_C_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(CP_STATE_F_GPIO_Port, CP_STATE_F_Pin, GPIO_PIN_RESET);
break;
case EV_STATE_E_NO_POWER:
HAL_GPIO_WritePin(CP_RELAY_GPIO_Port, CP_RELAY_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(CP_STATE_C_GPIO_Port, CP_STATE_C_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(CP_STATE_F_GPIO_Port, CP_STATE_F_Pin, GPIO_PIN_SET);
break;
case EV_STATE_ACQUIRING:
default:
HAL_GPIO_WritePin(CP_RELAY_GPIO_Port, CP_RELAY_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(CP_STATE_F_GPIO_Port, CP_STATE_F_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(CP_STATE_C_GPIO_Port, CP_STATE_C_Pin, GPIO_PIN_RESET);
break;
}
last_state = cp_state;
}