refactor: Improve tilting code structure and organization.
Improves the code structure by reorganizing functions, minimizing the interaction with the relay channel driving API and independizing the tilting codes as much as possible from the plain channel driving API for more reliable operation. With this change the tilting API; * has its own events and event handler * does not depend on the channel's state change listener * does not interfere with channel driver API * has its own tilt command issuing logic * has its own timing management
This commit is contained in:
426
src/relay_chn.c
426
src/relay_chn.c
@@ -110,9 +110,13 @@ typedef struct relay_chn_type {
|
||||
* 100 / (RELAY_CHN_TILT_RUN_MAX_MS - RELAY_CHN_TILT_RUN_MIN_MS) )
|
||||
/// @}
|
||||
|
||||
|
||||
ESP_EVENT_DEFINE_BASE(RELAY_CHN_TILT_CMD_EVENT_BASE);
|
||||
|
||||
/// @brief Tilt commands.
|
||||
enum relay_chn_tilt_cmd_enum {
|
||||
RELAY_CHN_TILT_CMD_NONE, ///< No command.
|
||||
RELAY_CHN_TILT_CMD_STOP, ///< Tilt command stop.
|
||||
RELAY_CHN_TILT_CMD_FORWARD, ///< Tilt command for forward.
|
||||
RELAY_CHN_TILT_CMD_REVERSE ///< Tilt command for reverse.
|
||||
};
|
||||
@@ -123,7 +127,8 @@ typedef enum relay_chn_tilt_cmd_enum relay_chn_tilt_cmd_t;
|
||||
/// @brief Tilt steps.
|
||||
enum relay_chn_tilt_step_enum {
|
||||
RELAY_CHN_TILT_STEP_NONE, ///< No step.
|
||||
RELAY_CHN_TILT_STEP_RUN, ///< Run step. Tilt is either driving for forward or reverse.
|
||||
RELAY_CHN_TILT_STEP_PENDING, ///< Pending step.
|
||||
RELAY_CHN_TILT_STEP_MOVE, ///< Move step. Tilt is driving either for forward or reverse.
|
||||
RELAY_CHN_TILT_STEP_PAUSE ///< Pause step. Tilt is paused.
|
||||
};
|
||||
|
||||
@@ -132,14 +137,14 @@ typedef enum relay_chn_tilt_step_enum relay_chn_tilt_step_t;
|
||||
|
||||
/// @brief Tilt timing structure to manage tilt pattern timing.
|
||||
typedef struct relay_chn_tilt_timing_struct {
|
||||
uint8_t sensitivity; ///< Tilt sensitivity in percent value (%).
|
||||
uint32_t run_time_ms; ///< Run time in milliseconds.
|
||||
uint8_t sensitivity; ///< Tilt sensitivity in percentage (%).
|
||||
uint32_t move_time_ms; ///< Move time in milliseconds.
|
||||
uint32_t pause_time_ms; ///< Pause time in milliseconds.
|
||||
} relay_chn_tilt_timing_t;
|
||||
|
||||
/// @brief Tilt control structure to manage tilt operations.
|
||||
typedef struct relay_chn_tilt_control_struct {
|
||||
relay_chn_tilt_cmd_t cmd; ///< Current tilt command.
|
||||
relay_chn_tilt_cmd_t cmd; ///< The tilt command in process.
|
||||
relay_chn_tilt_step_t step; ///< Current tilt step.
|
||||
relay_chn_tilt_timing_t tilt_timing; ///< Tilt timing structure.
|
||||
esp_timer_handle_t tilt_timer; ///< Tilt timer handle.
|
||||
@@ -155,13 +160,11 @@ typedef struct relay_chn_type {
|
||||
relay_chn_output_t output; ///< Output configuration of the relay channel.
|
||||
relay_chn_cmd_t pending_cmd; ///< The command that is pending to be issued
|
||||
esp_timer_handle_t inertia_timer; ///< Timer to handle the opposite direction inertia time.
|
||||
relay_chn_tilt_control_t tilt_control;
|
||||
relay_chn_tilt_control_t tilt_control; ///< Tilt control block.
|
||||
} relay_chn_t;
|
||||
|
||||
static esp_err_t relay_chn_init_tilt_control(relay_chn_t *relay_chn);
|
||||
static void relay_chn_tilt_state_handler(uint8_t chn_id, relay_chn_state_t old_state, relay_chn_state_t new_state);
|
||||
|
||||
static uint32_t relay_chn_tilting_channels;
|
||||
static esp_err_t relay_chn_tilt_init(void);
|
||||
|
||||
#endif // RELAY_CHN_ENABLE_TILTING
|
||||
|
||||
@@ -338,13 +341,14 @@ esp_err_t relay_chn_create(const gpio_num_t* gpio_map, uint8_t gpio_count)
|
||||
}
|
||||
}
|
||||
|
||||
#if RELAY_CHN_ENABLE_TILTING == 1
|
||||
relay_chn_tilting_channels = 0;
|
||||
#endif
|
||||
|
||||
// Create relay channel command event loop
|
||||
ret |= relay_chn_create_event_loop();
|
||||
|
||||
#if RELAY_CHN_ENABLE_TILTING == 1
|
||||
// Must call after the event loop is initialized
|
||||
ret |= relay_chn_tilt_init(); // Initialize tilt feature
|
||||
#endif
|
||||
|
||||
// Init the state listener manager
|
||||
relay_chn_state_listener_manager.listeners = malloc(sizeof(relay_chn_state_listener_t*));
|
||||
if (relay_chn_state_listener_manager.listeners == NULL) {
|
||||
@@ -473,17 +477,6 @@ static void relay_chn_update_state(relay_chn_t *relay_chn, relay_chn_state_t new
|
||||
relay_chn_state_t old = relay_chn->state;
|
||||
relay_chn->state = new_state;
|
||||
|
||||
#if RELAY_CHN_ENABLE_TILTING == 1
|
||||
if (relay_chn->tilt_control.cmd != RELAY_CHN_TILT_CMD_NONE) {
|
||||
// The channel is tilting, pipe the internal state to the tilt state handler
|
||||
// unless the state sent from the tilt module
|
||||
if (relay_chn->state != RELAY_CHN_STATE_TILT_FORWARD && relay_chn->state != RELAY_CHN_STATE_TILT_REVERSE) {
|
||||
relay_chn_tilt_state_handler(relay_chn->id, old, new_state);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
for (uint8_t i = 0; i < relay_chn_state_listener_manager.listener_count; i++) {
|
||||
relay_chn_state_listener_t listener = relay_chn_state_listener_manager.listeners[i];
|
||||
if (listener == NULL) {
|
||||
@@ -688,47 +681,73 @@ relay_chn_direction_t relay_chn_get_direction(uint8_t chn_id)
|
||||
}
|
||||
/* relay_chn APIs */
|
||||
|
||||
static esp_err_t relay_chn_output_stop(relay_chn_t *relay_chn)
|
||||
{
|
||||
esp_err_t ret;
|
||||
ret = gpio_set_level(relay_chn->output.forward_pin, 0);
|
||||
ret |= gpio_set_level(relay_chn->output.reverse_pin, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t relay_chn_output_forward(relay_chn_t *relay_chn)
|
||||
{
|
||||
esp_err_t ret;
|
||||
ret = gpio_set_level(relay_chn->output.forward_pin, 1);
|
||||
ret |= gpio_set_level(relay_chn->output.reverse_pin, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t relay_chn_output_reverse(relay_chn_t *relay_chn)
|
||||
{
|
||||
esp_err_t ret;
|
||||
ret = gpio_set_level(relay_chn->output.forward_pin, 0);
|
||||
ret |= gpio_set_level(relay_chn->output.reverse_pin, 1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void relay_chn_execute_stop(relay_chn_t *relay_chn)
|
||||
{
|
||||
gpio_set_level(relay_chn->output.forward_pin, 0);
|
||||
gpio_set_level(relay_chn->output.reverse_pin, 0);
|
||||
if (relay_chn_output_stop(relay_chn) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "relay_chn_execute_stop: Failed to output stop for relay channel #%d!", relay_chn->id);
|
||||
}
|
||||
relay_chn_state_t previous_state = relay_chn->state;
|
||||
relay_chn_update_state(relay_chn, RELAY_CHN_STATE_STOPPED);
|
||||
|
||||
#if RELAY_CHN_ENABLE_TILTING == 1
|
||||
// Just stop and update state if tilting is active
|
||||
if (relay_chn->tilt_control.cmd != RELAY_CHN_TILT_CMD_NONE) return;
|
||||
#endif
|
||||
// If there is any pending command, cancel it since the STOP command is issued right after it
|
||||
relay_chn->pending_cmd = RELAY_CHN_CMD_NONE;
|
||||
// Invalidate the channel's timer if it is active
|
||||
esp_timer_stop(relay_chn->inertia_timer);
|
||||
|
||||
// If the channel was running, schedule a free command for the channel
|
||||
if (relay_chn->run_info.last_run_cmd != RELAY_CHN_CMD_NONE) {
|
||||
// Save the last run time only if the previous state was either STATE FORWARD
|
||||
// or STATE_REVERSE. Then schedule a free command.
|
||||
if (previous_state == RELAY_CHN_STATE_FORWARD || previous_state == RELAY_CHN_STATE_REVERSE) {
|
||||
// Record the command's last run time
|
||||
relay_chn->run_info.last_run_cmd_time_ms = esp_timer_get_time() / 1000;
|
||||
// Schedule a free command for the channel
|
||||
relay_chn->pending_cmd = RELAY_CHN_CMD_FREE;
|
||||
relay_chn_start_esp_timer_once(relay_chn->inertia_timer, RELAY_CHN_OPPOSITE_INERTIA_MS);
|
||||
} else {
|
||||
// If the channel was not running, issue a free command immediately
|
||||
// If the channel was not running one of the run or fwd, issue a free command immediately
|
||||
relay_chn_dispatch_cmd(relay_chn, RELAY_CHN_CMD_FREE);
|
||||
}
|
||||
}
|
||||
|
||||
static void relay_chn_execute_forward(relay_chn_t *relay_chn)
|
||||
{
|
||||
gpio_set_level(relay_chn->output.reverse_pin, 0);
|
||||
gpio_set_level(relay_chn->output.forward_pin, 1);
|
||||
if (relay_chn_output_forward(relay_chn) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "relay_chn_execute_forward: Failed to output forward for relay channel #%d!", relay_chn->id);
|
||||
return;
|
||||
}
|
||||
relay_chn->run_info.last_run_cmd = RELAY_CHN_CMD_FORWARD;
|
||||
relay_chn_update_state(relay_chn, RELAY_CHN_STATE_FORWARD);
|
||||
}
|
||||
|
||||
static void relay_chn_execute_reverse(relay_chn_t *relay_chn)
|
||||
{
|
||||
gpio_set_level(relay_chn->output.forward_pin, 0);
|
||||
gpio_set_level(relay_chn->output.reverse_pin, 1);
|
||||
if (relay_chn_output_reverse(relay_chn) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "relay_chn_execute_reverse: Failed to output reverse for relay channel #%d!", relay_chn->id);
|
||||
return;
|
||||
}
|
||||
relay_chn->run_info.last_run_cmd = RELAY_CHN_CMD_REVERSE;
|
||||
relay_chn_update_state(relay_chn, RELAY_CHN_STATE_REVERSE);
|
||||
}
|
||||
@@ -831,67 +850,50 @@ char *relay_chn_state_str(relay_chn_state_t state)
|
||||
|
||||
#if RELAY_CHN_ENABLE_TILTING == 1
|
||||
|
||||
// Timer callback for the relay_chn_tilt_control_t::tilt_timer
|
||||
static void relay_chn_tilt_timer_cb(void *arg)
|
||||
/**
|
||||
* @brief Dispatch a tilt command to the relay channel event loop.
|
||||
*
|
||||
* @param relay_chn The relay channel to send the command to.
|
||||
* @param cmd The tilt command.
|
||||
* @return
|
||||
* - ESP_OK on success.
|
||||
* - ESP_ERR_INVALID_ARG if the command is none.
|
||||
* - Other error codes on failure.
|
||||
*/
|
||||
static esp_err_t relay_chn_dispatch_tilt_cmd(relay_chn_t *relay_chn, relay_chn_tilt_cmd_t cmd)
|
||||
{
|
||||
uint8_t chn_id = *(uint8_t*) arg;
|
||||
if (!relay_chn_is_channel_id_valid(chn_id)) {
|
||||
ESP_LOGE(TAG, "relay_chn_tilt_timer_cb: Invalid relay channel ID!");
|
||||
return;
|
||||
}
|
||||
relay_chn_t* relay_chn = &relay_channels[chn_id];
|
||||
switch (relay_chn->tilt_control.step)
|
||||
{
|
||||
case RELAY_CHN_TILT_STEP_RUN:
|
||||
relay_chn_issue_cmd(relay_chn, RELAY_CHN_CMD_STOP);
|
||||
break;
|
||||
|
||||
case RELAY_CHN_TILT_STEP_PAUSE:
|
||||
if (relay_chn->tilt_control.cmd == RELAY_CHN_TILT_CMD_FORWARD) {
|
||||
relay_chn_issue_cmd(relay_chn, RELAY_CHN_CMD_REVERSE);
|
||||
}
|
||||
else if (relay_chn->tilt_control.cmd == RELAY_CHN_TILT_CMD_REVERSE) {
|
||||
relay_chn_issue_cmd(relay_chn, RELAY_CHN_CMD_FORWARD);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (cmd == RELAY_CHN_TILT_CMD_NONE) return ESP_ERR_INVALID_ARG;
|
||||
return esp_event_post_to(relay_chn_event_loop,
|
||||
RELAY_CHN_TILT_CMD_EVENT_BASE,
|
||||
cmd,
|
||||
&relay_chn->id,
|
||||
sizeof(relay_chn->id), portMAX_DELAY);
|
||||
}
|
||||
|
||||
// This listener is active until the relay_chn_tilt_stop() is called.
|
||||
static void relay_chn_tilt_state_handler(uint8_t chn_id, relay_chn_state_t old_state, relay_chn_state_t new_state)
|
||||
/**
|
||||
* @brief Get the required timing before tilting depending on the last run.
|
||||
*
|
||||
* @param relay_chn the relay channel.
|
||||
* @param cmd The tilt command.
|
||||
* @return The time that is required in ms.
|
||||
*/
|
||||
static uint32_t relay_chn_get_required_timing_before_tilting(relay_chn_t *relay_chn, relay_chn_tilt_cmd_t cmd)
|
||||
{
|
||||
ESP_LOGD(TAG, "relay_chn_tilt_state_listener: #%u, old_state: %s, new_state: %s",
|
||||
chn_id, relay_chn_state_str(old_state), relay_chn_state_str(new_state));
|
||||
if (cmd == RELAY_CHN_TILT_CMD_FORWARD && relay_chn->run_info.last_run_cmd == RELAY_CHN_CMD_REVERSE)
|
||||
return 0;
|
||||
else if (cmd == RELAY_CHN_TILT_CMD_REVERSE && relay_chn->run_info.last_run_cmd == RELAY_CHN_CMD_FORWARD)
|
||||
return 0;
|
||||
|
||||
relay_chn_t* relay_chn = &relay_channels[chn_id];
|
||||
// Check whether this channel is the one that's been tilting
|
||||
if (relay_chn->tilt_control.cmd == RELAY_CHN_TILT_CMD_NONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (new_state)
|
||||
{
|
||||
case RELAY_CHN_STATE_FORWARD:
|
||||
case RELAY_CHN_STATE_REVERSE:
|
||||
relay_chn->tilt_control.step = RELAY_CHN_TILT_STEP_RUN;
|
||||
// Start the tilt run timer
|
||||
esp_timer_start_once(relay_chn->tilt_control.tilt_timer,
|
||||
relay_chn->tilt_control.tilt_timing.run_time_ms * 1000);
|
||||
break;
|
||||
case RELAY_CHN_STATE_STOPPED:
|
||||
relay_chn->tilt_control.step = RELAY_CHN_TILT_STEP_PAUSE;
|
||||
esp_timer_start_once(relay_chn->tilt_control.tilt_timer,
|
||||
relay_chn->tilt_control.tilt_timing.pause_time_ms * 1000);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
uint32_t inertia_time_passed_ms = (uint32_t) (esp_timer_get_time() / 1000) - relay_chn->run_info.last_run_cmd_time_ms;
|
||||
return RELAY_CHN_OPPOSITE_INERTIA_MS - inertia_time_passed_ms;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Issue a tilt command to a specific relay channel.
|
||||
*
|
||||
* @param chn_id The channel ID.
|
||||
* @param cmd The tilt command.
|
||||
*/
|
||||
static void relay_chn_issue_tilt_cmd(uint8_t chn_id, relay_chn_tilt_cmd_t cmd)
|
||||
{
|
||||
relay_chn_t* relay_chn = &relay_channels[chn_id];
|
||||
@@ -901,36 +903,70 @@ static void relay_chn_issue_tilt_cmd(uint8_t chn_id, relay_chn_tilt_cmd_t cmd)
|
||||
ESP_LOGD(TAG, "relay_chn_issue_tilt_cmd: Tilt will not be executed since the channel hasn't been run yet");
|
||||
return;
|
||||
}
|
||||
else if (relay_chn->run_info.last_run_cmd == RELAY_CHN_CMD_REVERSE && cmd == RELAY_CHN_TILT_CMD_FORWARD) {
|
||||
ESP_LOGD(TAG, "relay_chn_issue_tilt_cmd: Invalid tilt command: TILT_FORWARD after the REVERSE command issued");
|
||||
return;
|
||||
}
|
||||
else if (relay_chn->run_info.last_run_cmd == RELAY_CHN_CMD_FORWARD && cmd == RELAY_CHN_TILT_CMD_REVERSE) {
|
||||
ESP_LOGD(TAG, "relay_chn_issue_tilt_cmd: Invalid tilt command: TILT_REVERSE after the FORWARD command issued");
|
||||
return;
|
||||
}
|
||||
|
||||
if (relay_chn->tilt_control.cmd == cmd) {
|
||||
ESP_LOGD(TAG, "relay_chn_issue_tilt_cmd: There is already a tilt command in progress!");
|
||||
return;
|
||||
}
|
||||
|
||||
// Set tilt control parameters
|
||||
// Set the command that will be processed
|
||||
relay_chn->tilt_control.cmd = cmd;
|
||||
relay_chn->tilt_control.step = RELAY_CHN_TILT_STEP_NONE;
|
||||
switch (relay_chn->state) {
|
||||
case RELAY_CHN_STATE_FREE:
|
||||
// Relay channel is free, tilt can be issued immediately
|
||||
relay_chn_dispatch_tilt_cmd(relay_chn, cmd);
|
||||
break;
|
||||
|
||||
// Set channel tilting active flag
|
||||
relay_chn_tilting_channels |= (1 << chn_id);
|
||||
|
||||
if (cmd == RELAY_CHN_TILT_CMD_FORWARD) {
|
||||
relay_chn_issue_cmd(relay_chn, RELAY_CHN_CMD_REVERSE);
|
||||
// Emit the tilt state change for the channel
|
||||
relay_chn_update_state(relay_chn, RELAY_CHN_STATE_TILT_FORWARD);
|
||||
case RELAY_CHN_STATE_FORWARD_PENDING:
|
||||
case RELAY_CHN_STATE_REVERSE_PENDING:
|
||||
// Issue a stop command first so that the timer and pending cmd get cleared
|
||||
relay_chn_dispatch_cmd(relay_chn, RELAY_CHN_CMD_STOP);
|
||||
// break not put intentionally
|
||||
case RELAY_CHN_STATE_STOPPED: {
|
||||
// Check if channel needs timing before tilting
|
||||
uint32_t req_timing_ms = relay_chn_get_required_timing_before_tilting(relay_chn, cmd);
|
||||
if (req_timing_ms == 0) {
|
||||
relay_chn_dispatch_tilt_cmd(relay_chn, cmd);
|
||||
} else {
|
||||
// Channel needs timing before running tilting action, schedule it
|
||||
relay_chn->tilt_control.step = RELAY_CHN_TILT_STEP_PENDING;
|
||||
relay_chn_start_esp_timer_once(relay_chn->tilt_control.tilt_timer, req_timing_ms);
|
||||
}
|
||||
else if (cmd == RELAY_CHN_TILT_CMD_REVERSE) {
|
||||
relay_chn_issue_cmd(relay_chn, RELAY_CHN_CMD_FORWARD);
|
||||
// Emit the tilt state change for the channel
|
||||
relay_chn_update_state(relay_chn, RELAY_CHN_STATE_TILT_REVERSE);
|
||||
break;
|
||||
}
|
||||
|
||||
case RELAY_CHN_STATE_FORWARD:
|
||||
if (cmd == RELAY_CHN_TILT_CMD_FORWARD) {
|
||||
// Stop the running channel first
|
||||
relay_chn_dispatch_cmd(relay_chn, RELAY_CHN_CMD_STOP);
|
||||
// Schedule for tilting
|
||||
relay_chn->tilt_control.step = RELAY_CHN_TILT_STEP_PENDING;
|
||||
relay_chn_start_esp_timer_once(relay_chn->tilt_control.tilt_timer, RELAY_CHN_OPPOSITE_INERTIA_MS);
|
||||
} else if (cmd == RELAY_CHN_TILT_CMD_REVERSE) {
|
||||
// Stop the running channel first
|
||||
relay_chn_dispatch_cmd(relay_chn, RELAY_CHN_CMD_STOP);
|
||||
// If the tilt cmd is TILT_REVERSE then dispatch it immediately
|
||||
relay_chn_dispatch_tilt_cmd(relay_chn, cmd);
|
||||
}
|
||||
break;
|
||||
|
||||
case RELAY_CHN_STATE_REVERSE:
|
||||
if (cmd == RELAY_CHN_TILT_CMD_REVERSE) {
|
||||
// Stop the running channel first
|
||||
relay_chn_dispatch_cmd(relay_chn, RELAY_CHN_CMD_STOP);
|
||||
// Schedule for tilting
|
||||
relay_chn->tilt_control.step = RELAY_CHN_TILT_STEP_PENDING;
|
||||
relay_chn_start_esp_timer_once(relay_chn->tilt_control.tilt_timer, RELAY_CHN_OPPOSITE_INERTIA_MS);
|
||||
} else if (cmd == RELAY_CHN_TILT_CMD_FORWARD) {
|
||||
// Stop the running channel first
|
||||
relay_chn_dispatch_cmd(relay_chn, RELAY_CHN_CMD_STOP);
|
||||
// If the tilt cmd is TILT_FORWARD then dispatch it immediately
|
||||
relay_chn_dispatch_tilt_cmd(relay_chn, cmd);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ESP_LOGD(TAG, "relay_chn_issue_tilt_cmd: Unexpected relay channel state: %s!", relay_chn_state_str(relay_chn->state));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -944,10 +980,10 @@ static void relay_chn_issue_tilt_cmd_on_all_channels(relay_chn_tilt_cmd_t cmd)
|
||||
static void relay_chn_issue_tilt_auto(uint8_t chn_id)
|
||||
{
|
||||
relay_chn_t* relay_chn = &relay_channels[chn_id];
|
||||
if (relay_chn->run_info.last_run_cmd == RELAY_CHN_CMD_FORWARD) {
|
||||
if (relay_chn->run_info.last_run_cmd == RELAY_CHN_CMD_FORWARD || relay_chn->state == RELAY_CHN_STATE_FORWARD) {
|
||||
relay_chn_issue_tilt_cmd(chn_id, RELAY_CHN_TILT_CMD_FORWARD);
|
||||
}
|
||||
else if (relay_chn->run_info.last_run_cmd == RELAY_CHN_CMD_REVERSE) {
|
||||
else if (relay_chn->run_info.last_run_cmd == RELAY_CHN_CMD_REVERSE || relay_chn->state == RELAY_CHN_STATE_REVERSE) {
|
||||
relay_chn_issue_tilt_cmd(chn_id, RELAY_CHN_TILT_CMD_REVERSE);
|
||||
}
|
||||
}
|
||||
@@ -989,19 +1025,15 @@ void relay_chn_tilt_reverse(uint8_t chn_id)
|
||||
else relay_chn_issue_tilt_cmd(chn_id, RELAY_CHN_TILT_CMD_REVERSE);
|
||||
}
|
||||
|
||||
static void relay_chn_issue_tilt_stop(uint8_t chn_id)
|
||||
static void _relay_chn_tilt_stop(uint8_t chn_id)
|
||||
{
|
||||
relay_chn_t* relay_chn = &relay_channels[chn_id];
|
||||
if (relay_chn->tilt_control.cmd != RELAY_CHN_TILT_CMD_NONE) {
|
||||
// Stop the channel's timer if active
|
||||
esp_timer_stop(relay_chn->tilt_control.tilt_timer);
|
||||
// Invalidate tilt cmd and step
|
||||
relay_chn->tilt_control.cmd = RELAY_CHN_TILT_CMD_NONE;
|
||||
relay_chn->tilt_control.step = RELAY_CHN_TILT_STEP_NONE;
|
||||
// Unset channel tilting active flag
|
||||
relay_chn_tilting_channels &= ~(1 << chn_id);
|
||||
// Stop the channel
|
||||
relay_chn_issue_cmd(relay_chn, RELAY_CHN_CMD_STOP);
|
||||
esp_event_post_to(relay_chn_event_loop,
|
||||
RELAY_CHN_TILT_CMD_EVENT_BASE,
|
||||
RELAY_CHN_TILT_CMD_STOP,
|
||||
&relay_chn->id,
|
||||
sizeof(relay_chn->id), portMAX_DELAY);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1011,20 +1043,13 @@ void relay_chn_tilt_stop(uint8_t chn_id)
|
||||
return;
|
||||
}
|
||||
|
||||
// Check whether there is an active tilting channel
|
||||
if (!relay_chn_tilting_channels) {
|
||||
// No active tilting channels, so nothing to do
|
||||
return;
|
||||
}
|
||||
|
||||
if (chn_id == RELAY_CHN_ID_ALL) {
|
||||
// Any channel executing tilt?
|
||||
for (int i = 0; i < RELAY_CHN_COUNT; i++) {
|
||||
relay_chn_issue_tilt_stop(i);
|
||||
_relay_chn_tilt_stop(i);
|
||||
}
|
||||
}
|
||||
else {
|
||||
relay_chn_issue_tilt_stop(chn_id);
|
||||
_relay_chn_tilt_stop(chn_id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1034,7 +1059,7 @@ static void relay_chn_set_tilt_timing_values(relay_chn_tilt_timing_t *tilt_timin
|
||||
uint32_t pause_time_ms)
|
||||
{
|
||||
tilt_timing->sensitivity = sensitivity;
|
||||
tilt_timing->run_time_ms = run_time_ms;
|
||||
tilt_timing->move_time_ms = run_time_ms;
|
||||
tilt_timing->pause_time_ms = pause_time_ms;
|
||||
}
|
||||
|
||||
@@ -1104,13 +1129,135 @@ esp_err_t relay_chn_tilt_sensitivity_get(uint8_t chn_id, uint8_t *sensitivity, s
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void relay_chn_tilt_execute_tilt_stop(relay_chn_t *relay_chn)
|
||||
{
|
||||
// Stop the channel's timer if active
|
||||
esp_timer_stop(relay_chn->tilt_control.tilt_timer);
|
||||
// Invalidate tilt cmd and step
|
||||
relay_chn->tilt_control.cmd = RELAY_CHN_TILT_CMD_NONE;
|
||||
relay_chn->tilt_control.step = RELAY_CHN_TILT_STEP_NONE;
|
||||
// Stop the channel
|
||||
if (relay_chn_output_stop(relay_chn) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "relay_chn_tilt_execute_tilt_stop: Failed to output stop for relay channel #%d!", relay_chn->id);
|
||||
}
|
||||
relay_chn_dispatch_cmd(relay_chn, RELAY_CHN_CMD_STOP);
|
||||
}
|
||||
|
||||
static void relay_chn_tilt_execute_tilt_forward(relay_chn_t *relay_chn)
|
||||
{
|
||||
if (relay_chn_output_reverse(relay_chn) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "relay_chn_tilt_execute_tilt_forward: Failed to output reverse for relay channel #%d!", relay_chn->id);
|
||||
// Stop tilting because of the error
|
||||
relay_chn_dispatch_tilt_cmd(relay_chn, RELAY_CHN_TILT_CMD_STOP);
|
||||
return;
|
||||
}
|
||||
// Set the move time timer
|
||||
relay_chn_start_esp_timer_once(relay_chn->tilt_control.tilt_timer,
|
||||
relay_chn->tilt_control.tilt_timing.move_time_ms);
|
||||
// Set to pause step
|
||||
relay_chn->tilt_control.step = RELAY_CHN_TILT_STEP_PAUSE;
|
||||
}
|
||||
|
||||
static void relay_chn_tilt_execute_tilt_reverse(relay_chn_t *relay_chn)
|
||||
{
|
||||
if (relay_chn_output_forward(relay_chn) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "relay_chn_tilt_execute_tilt_reverse: Failed to output forward for relay channel #%d!", relay_chn->id);
|
||||
// Stop tilting because of the error
|
||||
relay_chn_dispatch_tilt_cmd(relay_chn, RELAY_CHN_TILT_CMD_STOP);
|
||||
return;
|
||||
}
|
||||
// Set the move time timer
|
||||
relay_chn_start_esp_timer_once(relay_chn->tilt_control.tilt_timer,
|
||||
relay_chn->tilt_control.tilt_timing.move_time_ms);
|
||||
// Set to pause step
|
||||
relay_chn->tilt_control.step = RELAY_CHN_TILT_STEP_PAUSE;
|
||||
}
|
||||
|
||||
static void relay_chn_tilt_execute_tilt_pause(relay_chn_t *relay_chn)
|
||||
{
|
||||
// Pause the channel
|
||||
if (relay_chn_output_stop(relay_chn) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "relay_chn_tilt_execute_tilt_stop: Failed to output stop for relay channel #%d!", relay_chn->id);
|
||||
// Stop tilting because of the error
|
||||
relay_chn_dispatch_tilt_cmd(relay_chn, RELAY_CHN_TILT_CMD_STOP);
|
||||
return;
|
||||
}
|
||||
// Set the pause time timer
|
||||
relay_chn_start_esp_timer_once(relay_chn->tilt_control.tilt_timer,
|
||||
relay_chn->tilt_control.tilt_timing.pause_time_ms);
|
||||
// Set to move step
|
||||
relay_chn->tilt_control.step = RELAY_CHN_TILT_STEP_MOVE;
|
||||
}
|
||||
|
||||
static void relay_chn_tilt_event_handler(void *handler_arg, esp_event_base_t event_base, int32_t event_id, void *event_data)
|
||||
{
|
||||
uint8_t chn_id = *(uint8_t*) event_data;
|
||||
if (!relay_chn_is_channel_id_valid(chn_id)) {
|
||||
return;
|
||||
}
|
||||
relay_chn_t* relay_chn = &relay_channels[chn_id];
|
||||
ESP_LOGD(TAG, "relay_chn_event_handler: Channel %d, Command: %s", relay_chn->id, relay_chn_cmd_str(event_id));
|
||||
switch(event_id) {
|
||||
case RELAY_CHN_TILT_CMD_STOP:
|
||||
relay_chn_tilt_execute_tilt_stop(relay_chn);
|
||||
break;
|
||||
case RELAY_CHN_TILT_CMD_FORWARD:
|
||||
relay_chn_tilt_execute_tilt_forward(relay_chn);
|
||||
// Update channel state
|
||||
relay_chn_update_state(relay_chn, RELAY_CHN_STATE_TILT_FORWARD);
|
||||
break;
|
||||
case RELAY_CHN_TILT_CMD_REVERSE:
|
||||
relay_chn_tilt_execute_tilt_reverse(relay_chn);
|
||||
// Update channel state
|
||||
relay_chn_update_state(relay_chn, RELAY_CHN_STATE_TILT_REVERSE);
|
||||
break;
|
||||
default:
|
||||
ESP_LOGW(TAG, "Unexpected relay channel tilt command: %ld!", event_id);
|
||||
}
|
||||
}
|
||||
|
||||
// Timer callback for the relay_chn_tilt_control_t::tilt_timer
|
||||
static void relay_chn_tilt_timer_cb(void *arg)
|
||||
{
|
||||
uint8_t chn_id = *(uint8_t*) arg;
|
||||
if (!relay_chn_is_channel_id_valid(chn_id)) {
|
||||
ESP_LOGE(TAG, "relay_chn_tilt_timer_cb: Invalid relay channel ID!");
|
||||
return;
|
||||
}
|
||||
relay_chn_t* relay_chn = &relay_channels[chn_id];
|
||||
|
||||
switch (relay_chn->tilt_control.step)
|
||||
{
|
||||
case RELAY_CHN_TILT_STEP_MOVE:
|
||||
if (relay_chn->tilt_control.cmd == RELAY_CHN_TILT_CMD_FORWARD) {
|
||||
relay_chn_tilt_execute_tilt_forward(relay_chn);
|
||||
}
|
||||
else if (relay_chn->tilt_control.cmd == RELAY_CHN_TILT_CMD_REVERSE) {
|
||||
relay_chn_tilt_execute_tilt_reverse(relay_chn);
|
||||
}
|
||||
break;
|
||||
|
||||
case RELAY_CHN_TILT_STEP_PAUSE:
|
||||
relay_chn_tilt_execute_tilt_pause(relay_chn);
|
||||
break;
|
||||
|
||||
case RELAY_CHN_TILT_STEP_PENDING:
|
||||
// Just dispatch the pending tilt command
|
||||
relay_chn_dispatch_tilt_cmd(relay_chn, relay_chn->tilt_control.cmd);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static esp_err_t relay_chn_init_tilt_control(relay_chn_t *relay_chn)
|
||||
{
|
||||
relay_chn_tilt_control_t *tilt_control = &relay_chn->tilt_control;
|
||||
tilt_control->cmd = RELAY_CHN_TILT_CMD_NONE;
|
||||
tilt_control->step = RELAY_CHN_TILT_STEP_NONE;
|
||||
tilt_control->tilt_timing.sensitivity = RELAY_CHN_TILT_DEFAULT_SENSITIVITY;
|
||||
tilt_control->tilt_timing.run_time_ms = RELAY_CHN_TILT_DEFAULT_RUN_MS;
|
||||
tilt_control->tilt_timing.move_time_ms = RELAY_CHN_TILT_DEFAULT_RUN_MS;
|
||||
tilt_control->tilt_timing.pause_time_ms = RELAY_CHN_TILT_DEFAULT_PAUSE_MS;
|
||||
|
||||
// Create tilt timer for the channel
|
||||
@@ -1124,6 +1271,17 @@ static esp_err_t relay_chn_init_tilt_control(relay_chn_t *relay_chn)
|
||||
return esp_timer_create(&timer_args, &relay_chn->tilt_control.tilt_timer);
|
||||
}
|
||||
|
||||
// Should call once from relay_chn_init
|
||||
static esp_err_t relay_chn_tilt_init(void)
|
||||
{
|
||||
esp_err_t ret;
|
||||
ret = esp_event_handler_register_with(relay_chn_event_loop,
|
||||
RELAY_CHN_TILT_CMD_EVENT_BASE,
|
||||
ESP_EVENT_ANY_ID,
|
||||
relay_chn_tilt_event_handler, NULL);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif // RELAY_CHN_ENABLE_TILTING
|
||||
|
||||
/// @}
|
||||
Reference in New Issue
Block a user