big refactoring: J1939, log output, state machine bug fixes
This commit is contained in:
+194
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user