Add single channel mode feature.
The addition of a single-channel mode implied further modularisation of the component. This commit has broken the component down into the following modules to avoid a huge single source file and to make unit testing easier. The modules: - Separation of public and private code - *types and *defs - public relay_chn API - *adapter - *output - *run_info - *core - *ctl (control) - *tilt Closes #957.
This commit is contained in:
168
src/relay_chn_output.c
Normal file
168
src/relay_chn_output.c
Normal file
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Kozmotronik Tech
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include "esp_check.h"
|
||||
#include "esp_log.h"
|
||||
#include "relay_chn_defs.h"
|
||||
#include "relay_chn_output.h"
|
||||
#include "relay_chn_core.h"
|
||||
|
||||
|
||||
static const char *TAG = "RELAY_CHN_OUTPUT";
|
||||
|
||||
#if RELAY_CHN_COUNT > 1
|
||||
static relay_chn_output_t outputs[RELAY_CHN_COUNT];
|
||||
#else
|
||||
static relay_chn_output_t output;
|
||||
#endif
|
||||
|
||||
|
||||
static esp_err_t relay_chn_output_check_gpio_capabilities(uint8_t gpio_count)
|
||||
{
|
||||
// Check if the device's GPIOs are enough for the number of channels
|
||||
if (RELAY_CHN_COUNT > (GPIO_PIN_COUNT / 2)) {
|
||||
ESP_LOGE(TAG, "Not enough GPIOs for the number of channels!");
|
||||
ESP_LOGE(TAG, "Max available num of channels: %d, requested channels: %d", GPIO_PIN_COUNT / 2, RELAY_CHN_COUNT);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
// Check if the provided GPIOs correspond to the number of channels
|
||||
if (gpio_count != RELAY_CHN_COUNT * 2) {
|
||||
ESP_LOGE(TAG, "Invalid number of GPIOs provided: %d", gpio_count);
|
||||
ESP_LOGE(TAG, "Expected number of GPIOs: %d", RELAY_CHN_COUNT * 2);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t relay_chn_output_ctl_init(relay_chn_output_t *output, gpio_num_t forward_pin, gpio_num_t reverse_pin)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(GPIO_IS_VALID_OUTPUT_GPIO(forward_pin), ESP_ERR_INVALID_ARG, TAG,
|
||||
"Invalid GPIO pin number for forward_pin: %d", forward_pin);
|
||||
ESP_RETURN_ON_FALSE(GPIO_IS_VALID_OUTPUT_GPIO(reverse_pin), ESP_ERR_INVALID_ARG, TAG,
|
||||
"Invalid GPIO pin number for reverse_pin: %d", reverse_pin);
|
||||
|
||||
// Check if the GPIOs are valid
|
||||
esp_err_t ret;
|
||||
// Initialize the GPIOs
|
||||
ret = gpio_reset_pin(forward_pin);
|
||||
ESP_RETURN_ON_ERROR(ret, TAG, "Failed to reset GPIO forward pin: %d", forward_pin);
|
||||
ret = gpio_set_direction(forward_pin, GPIO_MODE_OUTPUT);
|
||||
ESP_RETURN_ON_ERROR(ret, TAG, "Failed to set GPIO direction for forward pin: %d", forward_pin);
|
||||
|
||||
ret = gpio_reset_pin(reverse_pin);
|
||||
ESP_RETURN_ON_ERROR(ret, TAG, "Failed to reset GPIO reverse pin: %d", reverse_pin);
|
||||
ret = gpio_set_direction(reverse_pin, GPIO_MODE_OUTPUT);
|
||||
ESP_RETURN_ON_ERROR(ret, TAG, "Failed to set GPIO direction for reverse pin: %d", reverse_pin);
|
||||
// Initialize the GPIOs
|
||||
|
||||
// Initialize the relay channel output
|
||||
output->forward_pin = forward_pin;
|
||||
output->reverse_pin = reverse_pin;
|
||||
output->direction = RELAY_CHN_DIRECTION_DEFAULT;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t relay_chn_output_init(const uint8_t* gpio_map, uint8_t gpio_count)
|
||||
{
|
||||
esp_err_t ret;
|
||||
ret = relay_chn_output_check_gpio_capabilities(gpio_count);
|
||||
ESP_RETURN_ON_ERROR(ret, TAG, "Device does not support the provided GPIOs");
|
||||
|
||||
#if RELAY_CHN_COUNT > 1
|
||||
for (int i = 0; i < RELAY_CHN_COUNT; i++) {
|
||||
relay_chn_output_t* output = &outputs[i];
|
||||
int gpio_index = i << 1; // gpio_index = i * 2
|
||||
gpio_num_t forward_pin = (gpio_num_t) gpio_map[gpio_index];
|
||||
gpio_num_t reverse_pin = (gpio_num_t) gpio_map[gpio_index + 1];
|
||||
|
||||
ret = relay_chn_output_ctl_init(output, forward_pin, reverse_pin);
|
||||
ESP_RETURN_ON_ERROR(ret, TAG, "Failed to initialize relay channel %d", i);
|
||||
}
|
||||
#else
|
||||
ret = relay_chn_output_ctl_init(&output, gpio_map[0], gpio_map[1]);
|
||||
ESP_RETURN_ON_ERROR(ret, TAG, "Failed to initialize relay channel");
|
||||
#endif
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void relay_chn_output_ctl_deinit(relay_chn_output_t *output)
|
||||
{
|
||||
gpio_reset_pin(output->forward_pin);
|
||||
gpio_reset_pin(output->reverse_pin);
|
||||
}
|
||||
|
||||
void relay_chn_output_deinit()
|
||||
{
|
||||
#if RELAY_CHN_COUNT > 1
|
||||
for (int i = 0; i < RELAY_CHN_COUNT; i++) {
|
||||
relay_chn_output_ctl_deinit(&outputs[i]);
|
||||
}
|
||||
#else
|
||||
relay_chn_output_ctl_deinit(&output);
|
||||
#endif // RELAY_CHN_COUNT > 1
|
||||
}
|
||||
|
||||
#if RELAY_CHN_COUNT > 1
|
||||
relay_chn_output_t *relay_chn_output_get(uint8_t chn_id)
|
||||
{
|
||||
if (!relay_chn_is_channel_id_valid(chn_id)) {
|
||||
return NULL;
|
||||
}
|
||||
return &outputs[chn_id];
|
||||
}
|
||||
|
||||
relay_chn_output_t *relay_chn_output_get_all(void)
|
||||
{
|
||||
return outputs;
|
||||
}
|
||||
#else
|
||||
relay_chn_output_t *relay_chn_output_get(void)
|
||||
{
|
||||
return &output;
|
||||
}
|
||||
#endif // RELAY_CHN_COUNT > 1
|
||||
|
||||
esp_err_t relay_chn_output_stop(relay_chn_output_t *output)
|
||||
{
|
||||
esp_err_t ret;
|
||||
ret = gpio_set_level(output->forward_pin, 0);
|
||||
ESP_RETURN_ON_ERROR(ret, TAG, "Failed to set forward pin to LOW");
|
||||
return gpio_set_level(output->reverse_pin, 0);
|
||||
}
|
||||
|
||||
esp_err_t relay_chn_output_forward(relay_chn_output_t *output)
|
||||
{
|
||||
esp_err_t ret;
|
||||
ret = gpio_set_level(output->forward_pin, 1);
|
||||
ESP_RETURN_ON_ERROR(ret, TAG, "Failed to set forward pin to HIGH");
|
||||
return gpio_set_level(output->reverse_pin, 0);
|
||||
}
|
||||
|
||||
esp_err_t relay_chn_output_reverse(relay_chn_output_t *output)
|
||||
{
|
||||
esp_err_t ret;
|
||||
ret = gpio_set_level(output->forward_pin, 0);
|
||||
ESP_RETURN_ON_ERROR(ret, TAG, "Failed to set forward pin to LOW");
|
||||
return gpio_set_level(output->reverse_pin, 1);
|
||||
}
|
||||
|
||||
void relay_chn_output_flip(relay_chn_output_t *output)
|
||||
{
|
||||
// Flip the output GPIO pins
|
||||
gpio_num_t temp = output->forward_pin;
|
||||
output->forward_pin = output->reverse_pin;
|
||||
output->reverse_pin = temp;
|
||||
// Flip the direction
|
||||
output->direction = (output->direction == RELAY_CHN_DIRECTION_DEFAULT)
|
||||
? RELAY_CHN_DIRECTION_FLIPPED
|
||||
: RELAY_CHN_DIRECTION_DEFAULT;
|
||||
}
|
||||
|
||||
relay_chn_direction_t relay_chn_output_get_direction(relay_chn_output_t *output)
|
||||
{
|
||||
return output->direction;
|
||||
}
|
||||
Reference in New Issue
Block a user