diff --git a/CMakeLists.txt b/CMakeLists.txt index 1fbc887..8fec4a8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,6 +26,7 @@ idf_component_register( "src/CronTimers.c" "src/SerialPort.c" src/PPPoS.c + src/ShiftRegisterSPI.c src/sdcard.c src/FileBlockHandler.c src/OTA.c diff --git a/Kconfig b/Kconfig index bde6b9a..d7c4cc4 100644 --- a/Kconfig +++ b/Kconfig @@ -818,6 +818,42 @@ menu "WebGUIApp" default n endmenu + menu "SR IO extender configuration" + config WEBGUIAPP_SR_ENABLE + bool "Enabled SR IO extender" + default n + + config WEBGUIAPP_SR_CLOCK_MHZ + int "SR extender clock speed (MHz)" + range 1 20 + default 10 if IDF_TARGET_ESP32 || IDF_TARGET_ESP32C3 + default 30 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 + help + Set the clock speed (MHz) of SPI interface. + + config WEBGUIAPP_SR_CS + int "SR SC signal GPIO" + range GPIO_RANGE_MIN GPIO_RANGE_MAX + default 12 + help + Set GPIO for chip select signal. + + config WEBGUIAPP_SR_OUTPUTS + int "SR outputs number" + range 0 64 + default 8 + help + Set the number of outputs (must be a multiple of 8). + + config WEBGUIAPP_SR_INPUTS + int "SR inputs number" + range 0 64 + default 8 + help + Set the number of inputs (must be a multiple of 8). + + endmenu + menu "Serial port configuration" config WEBGUIAPP_UART_TRANSPORT_ENABLE diff --git a/include/ShiftRegisterSPI.h b/include/ShiftRegisterSPI.h new file mode 100644 index 0000000..36e9cba --- /dev/null +++ b/include/ShiftRegisterSPI.h @@ -0,0 +1,51 @@ +/* + * ShiftRegisterSPI.h + * + * Created on: Apr 18, 2025 + * Author: bogd + */ + +#ifndef COMPONENTS_WEBGUIAPP_INCLUDE_SHIFTREGISTERSPI_H_ +#define COMPONENTS_WEBGUIAPP_INCLUDE_SHIFTREGISTERSPI_H_ + +#include "esp_err.h" + +typedef enum { + VGPIO_NUM_NC = -1, + VGPIO_NUM_0 = 0, + VGPIO_NUM_1 = 1, + VGPIO_NUM_2 = 2, + VGPIO_NUM_3 = 3, + VGPIO_NUM_4 = 4, + VGPIO_NUM_5 = 5, + VGPIO_NUM_6 = 6, + VGPIO_NUM_7 = 7, + VGPIO_NUM_MAX, +/** @endcond */ +} virtual_gpio_num_t; + +typedef enum { + VGPIO_MOTOR_IN1 = 0, + VGPIO_MOTOR_IN2, + VGPIO_PILOT_RELAY, + VGPIO_RELAY1, + VGPIO_RELAY2, + VGPIO_TRIAC1, + VGPIO_TRIAC2, + VGPIO_TRIAC3 + +} virtual_gpio_funct_t; + +esp_err_t ShiftRegInit(void); +esp_err_t vgpio_set_level(virtual_gpio_num_t gpio_num, uint8_t *gpio_level); +esp_err_t vgpio_get_level(virtual_gpio_num_t gpio_num, uint8_t *gpio_level); +esp_err_t vgpi_get_level(int gpio_num, uint8_t *gpio_level); +esp_err_t vgpio_set_reg(uint8_t reg); + +void GPIOExtenderTxRx(uint8_t *tx, uint8_t *rx, int bt); +void GPIOInputRead(int num, int *val); +void GPIOInputWrite(int num, int *val); + + + +#endif /* COMPONENTS_WEBGUIAPP_INCLUDE_SHIFTREGISTERSPI_H_ */ diff --git a/include/webguiapp.h b/include/webguiapp.h index 6717c47..4bec57d 100644 --- a/include/webguiapp.h +++ b/include/webguiapp.h @@ -35,6 +35,7 @@ #include "SystemApplication.h" #include "UserCallbacks.h" #include "CommandProcSys.h" +#include "ShiftRegisterSPI.h" esp_err_t spi_device_polling_transmit_synchronized(spi_device_handle_t handle, spi_transaction_t *trans_desc); diff --git a/src/GSMTransport.c b/src/GSMTransport.c index 1e816bf..74c5841 100644 --- a/src/GSMTransport.c +++ b/src/GSMTransport.c @@ -309,7 +309,7 @@ static void GSMRunTask(void *pvParameter) { void PPPModemStart(void) { xTaskCreatePinnedToCore(GSMRunTask, "GSMRunTask", 1024 * 4, &ResetType, 3, - NULL, 1); + NULL, 0); } int PPPModemGetRSSI(void) { diff --git a/src/ShiftRegisterSPI.c b/src/ShiftRegisterSPI.c new file mode 100644 index 0000000..5dbdb4b --- /dev/null +++ b/src/ShiftRegisterSPI.c @@ -0,0 +1,123 @@ +/* + * ShiftRegisterSPI.c + * + * Created on: Apr 18, 2025 + * Author: bogd + */ + +#include "SysConfiguration.h" +#include "webguiapp.h" +#include "sdkconfig.h" +#include "esp_timer.h" + +#ifdef CONFIG_WEBGUIAPP_SR_ENABLE + + +#define TAG "ShiftRegDriver" + +#define CONFIG_SHIFTREG_SPI_HOST (1) +#define CONFIG_SHIFTREG_SPI_CLOCK_HZ (10000000) +#define CONFIG_SHIFTREG_SPI_CS_GPIO (12) + +#define CONFIG_SHIFTREG_SAMPLES_MS (10) + +static spi_device_handle_t spi_shift_handle; +static spi_transaction_t spi_shift_transaction; +static uint8_t inputs[] = { 0, 0 }, outputs[] = { 0, 0 }; + +static const int SHIFTREG_SAMPLE_START_BIT = BIT0; + +static EventGroupHandle_t digio_event_group = NULL; +static SemaphoreHandle_t xSemaphoreShiftRegHandle = NULL; +static StaticSemaphore_t xSemaphoreShiftRegBuf; + +esp_timer_handle_t shiftreg_timer, inputs_periodical_timer; + +void ShiftRegSampleStart(void *arg); + +const esp_timer_create_args_t shiftreg_timer_args = { .callback = &ShiftRegSampleStart, .name = "shiftregTimer" }; + +void ShiftRegSampleStart(void *arg) +{ + xEventGroupSetBits(digio_event_group, SHIFTREG_SAMPLE_START_BIT); +} + +static esp_err_t shiftreg_txrx_transaction(uint8_t *tx, uint8_t *rx, int bits) +{ + memset(&spi_shift_transaction, 0, sizeof(spi_shift_transaction)); + spi_shift_transaction.cmd = 0; + spi_shift_transaction.addr = 0; + spi_shift_transaction.length = bits; + spi_shift_transaction.tx_buffer = tx; + spi_shift_transaction.rx_buffer = rx; + spi_shift_transaction.rxlength = 0; + esp_err_t err = spi_device_polling_transmit(spi_shift_handle, &spi_shift_transaction); + ESP_ERROR_CHECK(err); + return err; +} + +static void shift_reg_task(void *pvParameter) +{ + while (1) + { + xEventGroupWaitBits(digio_event_group, SHIFTREG_SAMPLE_START_BIT, pdTRUE, pdTRUE, portMAX_DELAY); + xSemaphoreTake(xSemaphoreShiftRegHandle, portMAX_DELAY); + shiftreg_txrx_transaction(outputs, inputs, 8); + xSemaphoreGive(xSemaphoreShiftRegHandle); + } +} + +esp_err_t ShiftRegInit(void) +{ + spi_device_interface_config_t devcfg = { .command_bits = 0, .address_bits = 0, .mode = 0, .clock_speed_hz = CONFIG_SHIFTREG_SPI_CLOCK_HZ, .queue_size = 10, .spics_io_num = 12 }; + esp_err_t ret = spi_bus_add_device(CONFIG_SHIFTREG_SPI_HOST, &devcfg, &spi_shift_handle); + ESP_ERROR_CHECK(ret); + outputs[0] = 0b00110000; + digio_event_group = xEventGroupCreate(); + xSemaphoreShiftRegHandle = xSemaphoreCreateBinaryStatic(&xSemaphoreShiftRegBuf); + xSemaphoreGive(xSemaphoreShiftRegHandle); + ESP_ERROR_CHECK(esp_timer_create(&shiftreg_timer_args, &shiftreg_timer)); + ESP_ERROR_CHECK(esp_timer_start_periodic(shiftreg_timer, CONFIG_SHIFTREG_SAMPLES_MS * 1000)); + ESP_LOGI(TAG, "HC595 SPI device init OK"); + return ESP_OK; +} + +esp_err_t vgpio_set_level(virtual_gpio_num_t gpio_num, uint8_t *gpio_level) +{ + if (gpio_num < 0 || gpio_num >= VGPIO_NUM_MAX) + return ESP_ERR_INVALID_ARG; + uint8_t lv = *gpio_level & 1; + xSemaphoreTake(xSemaphoreShiftRegHandle, portMAX_DELAY); + outputs[0] = (outputs[0] & ~(1 << gpio_num)) | (lv << gpio_num); + shiftreg_txrx_transaction(outputs, inputs, 8); + xSemaphoreGive(xSemaphoreShiftRegHandle); + return ESP_OK; +} + +esp_err_t vgpio_get_level(virtual_gpio_num_t gpio_num, uint8_t *gpio_level) +{ + if (gpio_num < 0 || gpio_num >= VGPIO_NUM_MAX) + return ESP_ERR_INVALID_ARG; + *gpio_level = (outputs[0] & (1 << gpio_num)) ? 1 : 0; + return ESP_OK; +} + +esp_err_t vgpio_set_reg(uint8_t reg) +{ + if (xSemaphoreTake(xSemaphoreShiftRegHandle, pdMS_TO_TICKS(50)) == pdTRUE) + { + outputs[0] = (outputs[0] & 0b11110001) | (reg << 1); + shiftreg_txrx_transaction(outputs, inputs, 8); + xSemaphoreGive(xSemaphoreShiftRegHandle); + return ESP_OK; + } + else + { + ESP_LOGW(TAG, "Can't obtain SPI bus"); + return ESP_ERR_NOT_FINISHED; + } +} + + + +#endif \ No newline at end of file diff --git a/src/SysConfiguration.c b/src/SysConfiguration.c index c1a50fc..215651d 100644 --- a/src/SysConfiguration.c +++ b/src/SysConfiguration.c @@ -23,6 +23,7 @@ #include "../include/SysConfiguration.h" +#include "ShiftRegisterSPI.h" #include "SystemApplication.h" #include #include "stdlib.h" @@ -98,6 +99,11 @@ esp_err_t WebGuiAppInit(void) #if CONFIG_WEBGUIAPP_SPI_ENABLE InitSysSPI(); #endif + +#ifdef CONFIG_WEBGUIAPP_SR_ENABLE + ShiftRegInit(); +#endif + #if CONFIG_WEBGUIAPP_I2C_ENABLE InitSysI2C(); #endif