diff --git a/main/APP/app_task_hello/app_task_hello.c b/main/APP/app_task_hello/app_task_hello.c new file mode 100644 index 0000000..c819087 --- /dev/null +++ b/main/APP/app_task_hello/app_task_hello.c @@ -0,0 +1,43 @@ +/** + * @file app_task_hello.c + * @author impressionyang (impressionyang@outlook.com) + * @brief + * @version 0.1 + * @date 2022-09-28 + * _ _ + * (_)_ _ ___ _______ ___ ___ (_)__ ___ __ _____ ____ ___ _ + * / / ' \/ _ \/ __/ -_|_-<(_- + * Date Version Author Description + * 2022-09-28 v1.0 impressionyang 内容 + * + */ +#include "app_task_hello.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +static void _app_hello_task_run(void *param) +{ + uint16_t idx = 0; + while(1) { + printf("hello %d\r\n", idx++); + vTaskDelay(100); + } +} + +uint8_t app_hello_task_start() +{ + vTaskDelay(10); + xTaskCreatePinnedToCore(_app_hello_task_run, "hello task", 4096, NULL, 5, NULL, tskNO_AFFINITY); + return 0; +} + +uint8_t app_hello_task_stop() +{ + return 0; +} diff --git a/main/APP/app_task_hello/app_task_hello.h b/main/APP/app_task_hello/app_task_hello.h new file mode 100644 index 0000000..8825e45 --- /dev/null +++ b/main/APP/app_task_hello/app_task_hello.h @@ -0,0 +1,52 @@ +/** + * @file app_hello_task.h + * @author impressionyang (impressionyang@outlook.com) + * @brief + * @version 0.1 + * @date 2022-09-28 + * _ _ + * (_)_ _ ___ _______ ___ ___ (_)__ ___ __ _____ ____ ___ _ + * / / ' \/ _ \/ __/ -_|_-<(_- + * Date Version Author Description + * 2022-09-28 v1.0 impressionyang 内容 + * + */ +#ifndef __APP_HELLO_TASK_H__ +#define __APP_HELLO_TASK_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * + * @brief + * @author impressionyang (impressionyang@outlook.com) + * @return uint8_t + * + * @details + */ +uint8_t app_hello_task_start(); + +/** + * + * @brief + * @author impressionyang (impressionyang@outlook.com) + * @return uint8_t + * + * @details + */ +uint8_t app_hello_task_stop(); + +#ifdef __cplusplus +} +#endif +#endif//__APP_HELLO_TASK_H__ \ No newline at end of file diff --git a/main/APP/app_task_mqtt/app_task_mqtt.c b/main/APP/app_task_mqtt/app_task_mqtt.c new file mode 100644 index 0000000..682bad4 --- /dev/null +++ b/main/APP/app_task_mqtt/app_task_mqtt.c @@ -0,0 +1,177 @@ +/** + * @file app_task_mqtt.c + * @author impressionyang (impressionyang@outlook.com) + * @brief + * @version 0.1 + * @date 2022-09-29 + * _ _ + * (_)_ _ ___ _______ ___ ___ (_)__ ___ __ _____ ____ ___ _ + * / / ' \/ _ \/ __/ -_|_-<(_- + * Date Version Author Description + * 2022-09-29 v1.0 impressionyang 内容 + * + */ +#include "app_task_mqtt.h" +#include "app_main.h" + +#include +#include +#include +#include +#include "esp_wifi.h" +#include "esp_system.h" +#include "nvs_flash.h" +#include "esp_event_loop.h" + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#include "freertos/queue.h" +#include "freertos/event_groups.h" + +#include "lwip/sockets.h" +#include "lwip/dns.h" +#include "lwip/netdb.h" + +#include "esp_log.h" +#include "mqtt_client.h" + +static const char *TAG = "MQTT_EXAMPLE"; +//mqtt连上事件 +static EventGroupHandle_t mqtt_event_group; +const static int CONNECTED_BIT = BIT0; +esp_mqtt_client_handle_t client; + +static esp_err_t mqtt_event_handler(esp_mqtt_event_handle_t event) +{ + esp_mqtt_client_handle_t client = event->client; + int msg_id; + // your_context_t *context = event->context; + switch (event->event_id) { + case MQTT_EVENT_CONNECTED://MQTT连上事件 + ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED"); + xEventGroupSetBits(mqtt_event_group, CONNECTED_BIT); + //发布主题 + // msg_id = esp_mqtt_client_publish(client, "/topic/qos1", "data_3", 0, 1, 0); + // ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id); + //发送订阅 + // msg_id = esp_mqtt_client_subscribe(client, "/topic/qos0", 0); + // ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id); + //发送订阅 + msg_id = esp_mqtt_client_subscribe(client, "/topic/qos1", 1); + ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id); + //取消订阅 + // msg_id = esp_mqtt_client_unsubscribe(client, "/topic/qos1"); + // ESP_LOGI(TAG, "sent unsubscribe successful, msg_id=%d", msg_id); + break; + case MQTT_EVENT_DISCONNECTED://MQTT断开连接事件 + ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED"); + //mqtt连上事件 + xEventGroupClearBits(mqtt_event_group, CONNECTED_BIT); + break; + + case MQTT_EVENT_SUBSCRIBED://MQTT发送订阅事件 + ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id); + msg_id = esp_mqtt_client_publish(client, "/topic/qos0", "订阅成功", 0, 0, 0); + ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id); + break; + case MQTT_EVENT_UNSUBSCRIBED://MQTT取消订阅事件 + ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id); + break; + case MQTT_EVENT_PUBLISHED://MQTT发布事件 + ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id); + break; + case MQTT_EVENT_DATA://MQTT接受数据事件 + ESP_LOGI(TAG, "MQTT_EVENT_DATA"); + printf("TOPIC=%.*s\r\n", event->topic_len, event->topic); //主题 + printf("DATA=%.*s\r\n", event->data_len, event->data); //内容 + break; + case MQTT_EVENT_ERROR://MQTT错误事件 + ESP_LOGI(TAG, "MQTT_EVENT_ERROR"); + xEventGroupClearBits(mqtt_event_group, CONNECTED_BIT); + break; + default: + break; + } + return ESP_OK; +} + +//mqtt初始化 +static void mqtt_app_start(void) +{ + mqtt_event_group = xEventGroupCreate(); + esp_mqtt_client_config_t mqtt_cfg = { + .host = "117.50.172.12", //MQTT服务器IP + .event_handle = mqtt_event_handler, //MQTT事件 + .port=21883, //端口 + .username = "admin", //用户名 + .password = "public", //密码 + // .user_context = (void *)your_context + }; + +#if CONFIG_BROKER_URL_FROM_STDIN + char line[128]; + + if (strcmp(mqtt_cfg.uri, "FROM_STDIN") == 0) { + int count = 0; + printf("Please enter url of mqtt broker\n"); + while (count < 128) { + int c = fgetc(stdin); + if (c == '\n') { + line[count] = '\0'; + break; + } else if (c > 0 && c < 127) { + line[count] = c; + ++count; + } + vTaskDelay(10 / portTICK_PERIOD_MS); + } + mqtt_cfg.uri = line; + printf("Broker url: %s\n", line); + } else { + ESP_LOGE(TAG, "Configuration mismatch: wrong broker url"); + abort(); + } +#endif /* CONFIG_BROKER_URL_FROM_STDIN */ + + client = esp_mqtt_client_init(&mqtt_cfg); + esp_mqtt_client_start(client); + //等mqtt连上 + xEventGroupWaitBits(mqtt_event_group, CONNECTED_BIT, false, true, portMAX_DELAY); +} + +extern double g_temp; +extern double g_pres; + +static void _app_task_mqtt_run(void* param) +{ + while (!app_main_handle_get_nework_state()) { + vTaskDelay(10); + } + ESP_ERROR_CHECK(esp_netif_init()); + mqtt_app_start(); + char buf[50] = {0}; + while (1) { + vTaskDelay(1000); + sprintf(buf, "temp = %.4lf, presure = %.4lf\r\n", g_temp, g_pres); + esp_mqtt_client_publish(client, "/topic/bmp280", buf, 0, 0, 0); + } +} + +uint8_t app_task_mqtt_start() +{ + vTaskDelay(10); + xTaskCreatePinnedToCore(_app_task_mqtt_run, "mqtt app task", 4096, NULL, 5, NULL, tskNO_AFFINITY); + return 0; +} + +uint8_t app_task_mqtt_stop() +{ + return 0; +} diff --git a/main/APP/app_task_mqtt/app_task_mqtt.h b/main/APP/app_task_mqtt/app_task_mqtt.h new file mode 100644 index 0000000..25b60a0 --- /dev/null +++ b/main/APP/app_task_mqtt/app_task_mqtt.h @@ -0,0 +1,52 @@ +/** + * @file app_task_mqtt.h + * @author impressionyang (impressionyang@outlook.com) + * @brief + * @version 0.1 + * @date 2022-09-29 + * _ _ + * (_)_ _ ___ _______ ___ ___ (_)__ ___ __ _____ ____ ___ _ + * / / ' \/ _ \/ __/ -_|_-<(_- + * Date Version Author Description + * 2022-09-29 v1.0 impressionyang 内容 + * + */ +#ifndef __APP_TASK_MQTT_H__ +#define __APP_TASK_MQTT_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * + * @brief + * @author impressionyang (impressionyang@outlook.com) + * @return uint8_t + * + * @details + */ +uint8_t app_task_mqtt_stop(); + +/** + * + * @brief + * @author impressionyang (impressionyang@outlook.com) + * @return uint8_t + * + * @details + */ +uint8_t app_task_mqtt_start(); + +#ifdef __cplusplus +} +#endif +#endif//__APP_TASK_MQTT_H__ \ No newline at end of file diff --git a/main/APP/app_task_sensors/app_task_sensors.c b/main/APP/app_task_sensors/app_task_sensors.c new file mode 100644 index 0000000..fa1b22c --- /dev/null +++ b/main/APP/app_task_sensors/app_task_sensors.c @@ -0,0 +1,152 @@ +#include "app_task_sensors.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "driver/i2c.h" + +#include "drv_bmp280_3v3.h" +#include +#include +#include + +#include "shell_port.h" +#include "msg_queue.h" + +#define SENSOR_DRV_I2C_MASTER_SCL_IO 33 +#define SENSOR_DRV_I2C_MASTER_SDA_IO 34 +#define SENSOR_DRV_I2C_MASTER_FREQ_HZ 100000 +#define SENSOR_DRV_I2C_CONTROLLER_PORT 0 +#define SENSOR_DRV_I2C_MASTER_TIMEOUT_MS 1000 +#define SENSOR_DRV_I2C_MASTER_RX_BUF_DISABLE 0 +#define SENSOR_DRV_I2C_MASTER_TX_BUF_DISABLE 0 + +static i2c_config_t sg_drv_sensor_i2c_conf = { + .mode = I2C_MODE_MASTER, + .sda_io_num = SENSOR_DRV_I2C_MASTER_SDA_IO, + .scl_io_num = SENSOR_DRV_I2C_MASTER_SCL_IO, + .sda_pullup_en = GPIO_PULLUP_ENABLE, + .scl_pullup_en = GPIO_PULLUP_ENABLE, + .master.clk_speed = SENSOR_DRV_I2C_MASTER_FREQ_HZ, +}; + +static drv_bmp280_3v3_t* sg_drv_bmp280_handle = NULL; +double g_temp = 0; +double g_pres = 0; + +static int8_t drv_i2c_read(uint8_t reg_addr, uint8_t *data, uint32_t data_len, void *chip_addr) +{ + int ret = i2c_master_write_read_device(SENSOR_DRV_I2C_CONTROLLER_PORT, *((uint8_t*)chip_addr) , ®_addr, 1, data, data_len, SENSOR_DRV_I2C_MASTER_TIMEOUT_MS / portTICK_RATE_MS); + + if (ret) { + printf("I2C read error = %d, chip addr = %02x\r\n", ret, *((uint8_t*)chip_addr)); + } + return 0; +} + +static int8_t drv_i2c_write(uint8_t reg_addr, const uint8_t *data, uint32_t data_len, void *chip_addr) +{ + int ret, i; + uint8_t write_buf[51] = {0}; //{reg_addr, *data}; + + if (data_len > 50 || data_len == 0) { + return 1; + } + write_buf[0] = reg_addr; + for (i = 0 ; i < data_len; i++) { + write_buf[i+1] = data[i]; + } + + ret = i2c_master_write_to_device(SENSOR_DRV_I2C_CONTROLLER_PORT, *((uint8_t*)chip_addr), write_buf, data_len + 1, SENSOR_DRV_I2C_MASTER_TIMEOUT_MS / portTICK_RATE_MS); + + if (ret) { + printf("I2C write error = %d\r\n", ret); + } + return 0; +} + +static void drv_delay_ms_fptr_t(uint32_t period, void *intf_ptr) +{ + vTaskDelay(1); +} + +static uint8_t _app_task_sensors_drv_init() +{ + sg_drv_bmp280_handle = malloc(sizeof(drv_bmp280_3v3_t)); + memset(sg_drv_bmp280_handle, 0, sizeof(drv_bmp280_3v3_t)); + sg_drv_bmp280_handle->drv_i2c_read = drv_i2c_read; + sg_drv_bmp280_handle->drv_i2c_write = drv_i2c_write; + sg_drv_bmp280_handle->delay_10ms = drv_delay_ms_fptr_t; + drv_bmp280_3v3_init(sg_drv_bmp280_handle); + return 0; +} + +static uint8_t _app_task_sensors_drv_deinit() +{ + + return 0; +} + +static esp_err_t _app_task_sensors_esp_i2c_init() +{ + i2c_param_config(SENSOR_DRV_I2C_CONTROLLER_PORT, &sg_drv_sensor_i2c_conf); + + return i2c_driver_install(SENSOR_DRV_I2C_CONTROLLER_PORT, sg_drv_sensor_i2c_conf.mode, SENSOR_DRV_I2C_MASTER_RX_BUF_DISABLE, SENSOR_DRV_I2C_MASTER_TX_BUF_DISABLE, 0); +} + +static void _app_task_sensors_run() +{ + int ret = 0; + uint32_t presure = 0; + msg_data_t msg_data = {0}; + ret = _app_task_sensors_esp_i2c_init(); + if (ret) { + printf("sensor i2c init faild = %d\r\n", ret); + return; + } + + _app_task_sensors_drv_init(); + + while(1) { + + ret = drv_bmp280_3v3_refresh_data(sg_drv_bmp280_handle); + if (!ret) { + ret = drv_bmp280_3v3_get_tempreture(sg_drv_bmp280_handle, &g_temp); + // printf("temp = %.4lf\r\n", temp); + ret = drv_bmp280_3v3_get_pressure(sg_drv_bmp280_handle, &g_pres); + // printf("pres = %.4lf\r\n", pres); + }else { + printf("bmp280 is mesuring\r\n"); + } + msg_data.msg_type = 1; + msg_data.msg_id = 0; + msg_data.msg_value = (uint16_t)g_temp; + msg_queue_send_msg("mqtt_task", &msg_data); + + vTaskDelay(100); + } +} + +uint8_t app_task_sensors_start() +{ + vTaskDelay(10); + xTaskCreatePinnedToCore(_app_task_sensors_run, "sensor task", 4096, NULL, 4, NULL, tskNO_AFFINITY); + return 0; +} + +uint8_t app_task_sensors_stop() +{ + return 0; +} + +static void _show_bmp280(int argc, char **argv) +{ + int ret = 0; + ret = drv_bmp280_3v3_get_tempreture(sg_drv_bmp280_handle, &g_temp); + ret = drv_bmp280_3v3_get_pressure(sg_drv_bmp280_handle, &g_pres); + printf("temp = %.4lf\r\n", g_temp); + printf("pres = %.4lf\r\n", g_pres); + +} + +SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN), show_bmp280, _show_bmp280, show bmp280 pressure and tempreture); + + diff --git a/main/APP/app_task_sensors/app_task_sensors.h b/main/APP/app_task_sensors/app_task_sensors.h new file mode 100644 index 0000000..dcef346 --- /dev/null +++ b/main/APP/app_task_sensors/app_task_sensors.h @@ -0,0 +1,17 @@ +#ifndef __APP_TASK_SENSORS_H__ +#define __APP_TASK_SENSORS_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +uint8_t app_task_sensors_start(); + +uint8_t app_task_sensors_stop(); + +#ifdef __cplusplus +} +#endif +#endif//__APP_TASK_SENSORS_H__ \ No newline at end of file diff --git a/main/APP/app_task_wifi/app_task_wifi.c b/main/APP/app_task_wifi/app_task_wifi.c new file mode 100644 index 0000000..b2144ac --- /dev/null +++ b/main/APP/app_task_wifi/app_task_wifi.c @@ -0,0 +1,148 @@ +/** + * @file app_task_wifi.c + * @author impressionyang (impressionyang@outlook.com) + * @brief + * @version 0.1 + * @date 2022-09-29 + * _ _ + * (_)_ _ ___ _______ ___ ___ (_)__ ___ __ _____ ____ ___ _ + * / / ' \/ _ \/ __/ -_|_-<(_- + * Date Version Author Description + * 2022-09-29 v1.0 impressionyang 内容 + * + */ +#include "app_task_wifi.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/event_groups.h" +#include "esp_wifi.h" +#include "esp_log.h" +#include "esp_event.h" +#include + +/* Set the SSID and Password via project configuration, or can set directly here */ +#define DEFAULT_SSID "1022" +#define DEFAULT_PWD "w15077040648" + +#if CONFIG_EXAMPLE_WIFI_ALL_CHANNEL_SCAN +#define DEFAULT_SCAN_METHOD WIFI_ALL_CHANNEL_SCAN +#elif CONFIG_EXAMPLE_WIFI_FAST_SCAN +#define DEFAULT_SCAN_METHOD WIFI_FAST_SCAN +#else +#define DEFAULT_SCAN_METHOD WIFI_FAST_SCAN +#endif /*CONFIG_EXAMPLE_SCAN_METHOD*/ + +#if CONFIG_EXAMPLE_WIFI_CONNECT_AP_BY_SIGNAL +#define DEFAULT_SORT_METHOD WIFI_CONNECT_AP_BY_SIGNAL +#elif CONFIG_EXAMPLE_WIFI_CONNECT_AP_BY_SECURITY +#define DEFAULT_SORT_METHOD WIFI_CONNECT_AP_BY_SECURITY +#else +#define DEFAULT_SORT_METHOD WIFI_CONNECT_AP_BY_SIGNAL +#endif /*CONFIG_EXAMPLE_SORT_METHOD*/ + +#if CONFIG_EXAMPLE_FAST_SCAN_THRESHOLD +#define DEFAULT_RSSI CONFIG_EXAMPLE_FAST_SCAN_MINIMUM_SIGNAL +#if CONFIG_EXAMPLE_FAST_SCAN_WEAKEST_AUTHMODE_OPEN +#define DEFAULT_AUTHMODE WIFI_AUTH_OPEN +#elif CONFIG_EXAMPLE_FAST_SCAN_WEAKEST_AUTHMODE_WEP +#define DEFAULT_AUTHMODE WIFI_AUTH_WEP +#elif CONFIG_EXAMPLE_FAST_SCAN_WEAKEST_AUTHMODE_WPA +#define DEFAULT_AUTHMODE WIFI_AUTH_WPA_PSK +#elif CONFIG_EXAMPLE_FAST_SCAN_WEAKEST_AUTHMODE_WPA2 +#define DEFAULT_AUTHMODE WIFI_AUTH_WPA2_PSK +#else +#define DEFAULT_AUTHMODE WIFI_AUTH_OPEN +#endif +#else +#define DEFAULT_RSSI -127 +#define DEFAULT_AUTHMODE WIFI_AUTH_OPEN +#endif /*CONFIG_EXAMPLE_FAST_SCAN_THRESHOLD*/ + +static const char *TAG = "scan"; +static app_task_wifi_t sg_wifi_app_handle = {0}; + +static void event_handler(void* arg, esp_event_base_t event_base, + int32_t event_id, void* event_data) +{ + if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) { + esp_wifi_connect(); + } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) { + esp_wifi_connect(); + } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) { + ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data; + ESP_LOGI(TAG, "got ip:" IPSTR, IP2STR(&event->ip_info.ip)); + } +} + + +/* Initialize Wi-Fi as sta and set scan method */ +static void fast_scan(void) +{ + tcpip_adapter_init(); + ESP_ERROR_CHECK(esp_netif_init()); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + ESP_ERROR_CHECK(esp_wifi_init(&cfg)); + + ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL, NULL)); + ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL, NULL)); + + // Initialize default station as network interface instance (esp-netif) + esp_netif_t *sta_netif = esp_netif_create_default_wifi_sta(); + assert(sta_netif); + + // Initialize and start WiFi + wifi_config_t wifi_config = { + .sta = { + .ssid = DEFAULT_SSID, + .password = DEFAULT_PWD, + .scan_method = DEFAULT_SCAN_METHOD, + .sort_method = DEFAULT_SORT_METHOD, + .threshold.rssi = DEFAULT_RSSI, + .threshold.authmode = DEFAULT_AUTHMODE, + }, + }; + ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); + ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config)); + ESP_ERROR_CHECK(esp_wifi_start()); +} + +static void _app_wifi_task_run(void *param) +{ + fast_scan(); + while(sg_wifi_app_handle.is_wifi_app_running) { + // printf("wifi info:\r\n"); + // printf("is wifi conneted : %d\r\n", sg_wifi_app_handle.is_wifi_conneted); + vTaskDelay(100); + sg_wifi_app_handle.is_wifi_conneted = 1; + } +} + +uint8_t app_task_wifi_start() +{ + vTaskDelay(10); + sg_wifi_app_handle.is_wifi_app_start = 1; + sg_wifi_app_handle.is_wifi_app_running = 1; + + xTaskCreatePinnedToCore(_app_wifi_task_run, "wifi app task", 4096, NULL, 5, NULL, tskNO_AFFINITY); + return 0; +} + +uint8_t app_task_wifi_stop() +{ + sg_wifi_app_handle.is_wifi_app_running = 0; + return 0; +} + +uint8_t app_task_wifi_get_info(app_task_wifi_t *info_ptr) +{ + memcpy(info_ptr, &sg_wifi_app_handle, sizeof(app_task_wifi_t)); + return 0; +} \ No newline at end of file diff --git a/main/APP/app_task_wifi/app_task_wifi.h b/main/APP/app_task_wifi/app_task_wifi.h new file mode 100644 index 0000000..ac2098b --- /dev/null +++ b/main/APP/app_task_wifi/app_task_wifi.h @@ -0,0 +1,74 @@ +/** + * @file app_task_wifi.h + * @author impressionyang (impressionyang@outlook.com) + * @brief + * @version 0.1 + * @date 2022-09-29 + * _ _ + * (_)_ _ ___ _______ ___ ___ (_)__ ___ __ _____ ____ ___ _ + * / / ' \/ _ \/ __/ -_|_-<(_- + * Date Version Author Description + * 2022-09-29 v1.0 impressionyang 内容 + * + */ +#ifndef __APP_TASK_WIFI_H__ +#define __APP_TASK_WIFI_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/// @brief wifi 控制句柄 +typedef struct _app_task_wifi_t_ +{ + /// @brief wifi APP是否启动:0-》未启动 | 1-》已经启动 + uint8_t is_wifi_app_start; + /// @brief wifi是否连接:0-》未连接 | 1-》已连接 + uint8_t is_wifi_conneted; + /// @brief wifi APP线程是否运行:0-》未运行 | 1-》正在运行 + uint8_t is_wifi_app_running; +} app_task_wifi_t; + +/** + * app_task_wifi_start + * @brief wifi APP启动 + * @author impressionyang (impressionyang@outlook.com) + * @return uint8_t + * + * @details + */ +uint8_t app_task_wifi_start(); + +/** + * app_task_wifi_stop + * @brief wifi APP关闭 + * @author impressionyang (impressionyang@outlook.com) + * @return uint8_t + * + * @details + */ +uint8_t app_task_wifi_stop(); + +/** + * app_task_wifi_get_info + * @brief wifi APP信息获取 + * @author impressionyang (impressionyang@outlook.com) + * @param [in] info_ptr + * @return uint8_t + * + * @details + */ +uint8_t app_task_wifi_get_info(app_task_wifi_t *info_ptr); + +#ifdef __cplusplus +} +#endif +#endif//__APP_TASK_WIFI_H__ \ No newline at end of file diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index 0488bd1..985efda 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -1,2 +1,36 @@ -idf_component_register(SRCS "real_time_stats_example_main.c" - INCLUDE_DIRS ".") +# (utilities/letter_shell/port/esp-idf) + + + +idf_component_register( + SRC_DIRS + "." + "APP/app_task_hello" + # "APP/app_task_wifi" + # "APP/app_task_mqtt" + # "APP/app_task_sensors" + # "drivers/drv_bmp280_3v3" + # "drivers/msg_queue" + # "drivers/drv_bmp280_3v3/bmp2" + "drivers/st7789" + "drivers/cst816" + "utilities/letter_shell/src" + "utilities/letter_shell/port/esp-idf" + # "utilities/link_list" + INCLUDE_DIRS + "." + "APP/app_task_hello" + # "APP/app_task_wifi" + # "APP/app_task_mqtt" + # "APP/app_task_sensors" + # "drivers/drv_bmp280_3v3" + # "drivers/msg_queue" + # "drivers/drv_bmp280_3v3/bmp2" + "drivers/st7789" + "drivers/cst816" + "utilities/letter_shell/src" + "utilities/letter_shell/port/esp-idf" + # "utilities/link_list" + LDFRAGMENTS + "utilities/letter_shell/port/esp-idf/shell.lf" +) diff --git a/main/Kconfig.projbuild b/main/Kconfig.projbuild new file mode 100644 index 0000000..fd0c10e --- /dev/null +++ b/main/Kconfig.projbuild @@ -0,0 +1,139 @@ +menu "ST7789 Configuration" + + config GPIO_RANGE_MAX + int + default 33 if IDF_TARGET_ESP32 + default 46 if IDF_TARGET_ESP32S2 + default 19 if IDF_TARGET_ESP32C3 + default 48 if IDF_TARGET_ESP32S3 + + config WIDTH + int "SCREEN WIDTH" + range 0 999 + default 240 + help + The width resolution of the screen. + + config HEIGHT + int "SCREEN HEIGHT" + range 0 999 + default 240 + help + The height resolution of the screen. + + config OFFSETX + int "GRAM X OFFSET" + range 0 99 + default 0 + help + When your TFT have offset(X), set it. + + config OFFSETY + int "GRAM Y OFFSET" + range 0 99 + default 0 + help + When your TFT have offset(Y), set it. + + config MOSI_GPIO + int "MOSI GPIO number" + range 0 GPIO_RANGE_MAX + default 23 if IDF_TARGET_ESP32 + default 35 if IDF_TARGET_ESP32S2 + default 35 if IDF_TARGET_ESP32S3 + default 0 if IDF_TARGET_ESP32C3 + help + GPIO number (IOxx) to SPI MOSI. + Some GPIOs are used for other purposes (flash connections, etc.) and cannot be used to MOSI. + On the ESP32, GPIOs 35-39 are input-only so cannot be used as outputs. + On the ESP32-S2, GPIO 46 is input-only so cannot be used as outputs. + + config SCLK_GPIO + int "SCLK GPIO number" + range 0 GPIO_RANGE_MAX + default 18 if IDF_TARGET_ESP32 + default 36 if IDF_TARGET_ESP32S2 + default 36 if IDF_TARGET_ESP32S3 + default 1 if IDF_TARGET_ESP32C3 + help + GPIO number (IOxx) to SPI SCLK. + Some GPIOs are used for other purposes (flash connections, etc.) and cannot be used to SCLK. + On the ESP32, GPIOs 35-39 are input-only so cannot be used as outputs. + On the ESP32-S2, GPIO 46 is input-only so cannot be used as outputs. + + config CS_GPIO + int "CS GPIO number" + range -1 GPIO_RANGE_MAX + default -1 if IDF_TARGET_ESP32 + default -1 if IDF_TARGET_ESP32S2 + default -1 if IDF_TARGET_ESP32S3 + default -1 if IDF_TARGET_ESP32C3 + help + GPIO number (IOxx) to SPI CS. + When it is -1, CS isn't performed. + Some GPIOs are used for other purposes (flash connections, etc.) and cannot be used to CS. + On the ESP32, GPIOs 35-39 are input-only so cannot be used as outputs. + On the ESP32-S2, GPIO 46 is input-only so cannot be used as outputs. + + config DC_GPIO + int "DC GPIO number" + range 0 GPIO_RANGE_MAX + default 27 if IDF_TARGET_ESP32 + default 37 if IDF_TARGET_ESP32S2 + default 40 if IDF_TARGET_ESP32S3 + default 2 if IDF_TARGET_ESP32C3 + help + GPIO number (IOxx) to SPI DC. + Some GPIOs are used for other purposes (flash connections, etc.) and cannot be used to DC. + On the ESP32, GPIOs 35-39 are input-only so cannot be used as outputs. + On the ESP32-S2, GPIO 46 is input-only so cannot be used as outputs. + + config RESET_GPIO + int "RESET GPIO number" + range 0 GPIO_RANGE_MAX + default 33 if IDF_TARGET_ESP32 + default 38 if IDF_TARGET_ESP32S2 + default 41 if IDF_TARGET_ESP32S3 + default 3 if IDF_TARGET_ESP32C3 + help + GPIO number (IOxx) to RESET. + Some GPIOs are used for other purposes (flash connections, etc.) and cannot be used to RESET. + On the ESP32, GPIOs 35-39 are input-only so cannot be used as outputs. + On the ESP32-S2, GPIO 46 is input-only so cannot be used as outputs. + + config BL_GPIO + int "BACKLIGHT GPIO number" + range -1 GPIO_RANGE_MAX + default 32 if IDF_TARGET_ESP32 + default 33 if IDF_TARGET_ESP32S2 + default 33 if IDF_TARGET_ESP32S3 + default 4 if IDF_TARGET_ESP32C3 + help + GPIO number (IOxx) to BACKLIGHT. + When it is -1, BACKLIGHT isn't performed. + Some GPIOs are used for other purposes (flash connections, etc.) and cannot be used to BACKLIGHT. + On the ESP32, GPIOs 35-39 are input-only so cannot be used as outputs. + On the ESP32-S2, GPIO 46 is input-only so cannot be used as outputs. + + config INVERSION + bool "Enable Display Inversion" + default false + help + Enable Display Inversion. + + choice SPI_HOST + prompt "SPI peripheral that controls this bus" + default SPI2_HOST + help + Select SPI peripheral that controls this bus. + config SPI2_HOST + bool "SPI2_HOST" + help + Use SPI2_HOST. This is also called HSPI_HOST. + config SPI3_HOST + bool "SPI3_HOST" + help + USE SPI3_HOST. This is also called VSPI_HOST + endchoice + +endmenu diff --git a/main/app_main.c b/main/app_main.c new file mode 100644 index 0000000..4d9114b --- /dev/null +++ b/main/app_main.c @@ -0,0 +1,192 @@ +/* Hello World Example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ +#include +#include "sdkconfig.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_system.h" +#include "esp_spi_flash.h" +#include "nvs_flash.h" +#include "esp_err.h" +#include "esp_log.h" + +#include "app_task_hello.h" +// #include "app_task_wifi.h" +// #include "app_task_mqtt.h" +// #include "app_task_sensors.h" +#include "st7789.h" +#include "CST816T.h" +#include "app_main.h" +#include "shell_port.h" +// #include "msg_queue.h" + +static app_main_handle_t sg_app_main_handle = {0}; + +static void _init_esp() +{ + // Initialize NVS + esp_err_t ret = nvs_flash_init(); + if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { + ESP_ERROR_CHECK(nvs_flash_erase()); + ret = nvs_flash_init(); + } + ESP_ERROR_CHECK( ret ); +} + +TickType_t FillTest(TFT_t * dev, int width, int height) { + TickType_t startTick, endTick, diffTick; + startTick = xTaskGetTickCount(); + + lcdFillScreen(dev, RED); + vTaskDelay(50); + lcdFillScreen(dev, GREEN); + vTaskDelay(50); + lcdFillScreen(dev, BLUE); + vTaskDelay(50); + + endTick = xTaskGetTickCount(); + diffTick = endTick - startTick; + ESP_LOGI(__FUNCTION__, "elapsed time[ms]:%d",diffTick*portTICK_PERIOD_MS); + return diffTick; +} + +void cst_scan_gesture() +{ + while (1) + { + vTaskDelay(1); + if (cst816t_available()) + { + /*printf("gesture.id %u \n", data.gestureID); + printf("points %u \n", data.points); + printf("event %u \n", data.event);*/ + printf("x %i \n", data.x); + printf("y %i \n", data.y); + + switch (data.gestureID) + { + case NONE: + // printf("NONE"); + break; + case SWIPE_DOWN: + printf("SWIPE DOWN \n"); + break; + case SWIPE_UP: + printf("SWIPE UP \n"); + break; + case SWIPE_LEFT: + printf("SWIPE LEFT \n"); + break; + case SWIPE_RIGHT: + printf("SWIPE RIGHT \n"); + break; + case SINGLE_CLICK: + printf("SINGLE CLICK \n"); + break; + case DOUBLE_CLICK: + printf("DOUBLE CLICK \n"); + break; + case LONG_PRESS: + printf("LONG PRESS \n"); + break; + default: + printf("UNKNOWN \n"); + break; + } + } + } +} + +void app_main(void) +{ + // app_task_wifi_t wifi_info = {0}; + // msg_queue_init(); + printf("Hello world!\n"); + + vTaskDelay(10); + + _init_esp(); + // app_hello_task_start(); + // app_task_wifi_start(); + // app_task_mqtt_start(); + // app_task_sensors_start(); + + userShellInit(); + + cst816t_begin(34, 33, 35, 36); + + xTaskCreatePinnedToCore(cst_scan_gesture, "sct test", 4096, NULL, 4, NULL, tskNO_AFFINITY); + + + TFT_t dev; + spi_master_init(&dev, CONFIG_MOSI_GPIO, CONFIG_SCLK_GPIO, CONFIG_CS_GPIO, CONFIG_DC_GPIO, CONFIG_RESET_GPIO, CONFIG_BL_GPIO); + // lcdBacklightOn(&dev); + // vTaskDelay(1000); + lcdInit(&dev, CONFIG_WIDTH, CONFIG_HEIGHT, CONFIG_OFFSETX, CONFIG_OFFSETY); + // lcdBacklightOn(&dev); + +#if CONFIG_INVERSION + // ESP_LOGI(TAG, "Enable Display Inversion"); + lcdInversionOn(&dev); +#endif + + /* Print chip information */ + esp_chip_info_t chip_info; + esp_chip_info(&chip_info); + printf("This is %s chip with %d CPU core(s), WiFi%s%s, ", + CONFIG_IDF_TARGET, + chip_info.cores, + (chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "", + (chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : ""); + + printf("silicon revision %d, ", chip_info.revision); + + printf("%dMB %s flash\n", spi_flash_get_chip_size() / (1024 * 1024), + (chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded" : "external"); + + printf("Minimum free heap size: %d bytes\n", esp_get_minimum_free_heap_size()); + + // uint8_t ret = msg_queue_create("mqtt_task"); + // printf("ret = %d\r\n", ret); + + // msg_data_t msg_data = {0}; + for (int i = 10; ; ) { + // printf("Restarting in %d seconds...\n", i); + // app_task_wifi_get_info(&wifi_info); + // sg_app_main_handle.have_network = wifi_info.is_wifi_conneted; + FillTest(&dev, CONFIG_WIDTH, CONFIG_HEIGHT); + vTaskDelay(5000 / portTICK_PERIOD_MS); + // if (!msg_queue_recive_msg("mqtt_task", &msg_data, 100)) { + // printf("msg queue get data = %d\r\n", msg_data.msg_type); + // } + } + printf("Restarting now.\n"); + fflush(stdout); + esp_restart(); +} + +uint8_t app_main_handle_get_nework_state() +{ + return sg_app_main_handle.have_network; +} + +static void _show_build_time(int argc, char **argv) +{ + printf("build at %s %s\n", __DATE__, __TIME__); +} + +SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN), show_build_time, _show_build_time, show the build time); + +static void _reboot(int argc, char **argv) +{ + esp_restart(); +} + +SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN), reboot, _reboot, reboot system); + diff --git a/main/app_main.h b/main/app_main.h new file mode 100644 index 0000000..aff189e --- /dev/null +++ b/main/app_main.h @@ -0,0 +1,48 @@ +/** + * @file app_main.h + * @author impressionyang (impressionyang@outlook.com) + * @brief + * @version 0.1 + * @date 2022-09-29 + * _ _ + * (_)_ _ ___ _______ ___ ___ (_)__ ___ __ _____ ____ ___ _ + * / / ' \/ _ \/ __/ -_|_-<(_- + * Date Version Author Description + * 2022-09-29 v1.0 impressionyang 内容 + * + */ +#ifndef __APP_MAIN_H__ +#define __APP_MAIN_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _app_main_handle_ +{ + uint8_t have_network; +} app_main_handle_t; + + +/** + * + * @brief 获取网络连接状态 + * @author impressionyang (impressionyang@outlook.com) + * @return uint8_t + * + * @details + */ +uint8_t app_main_handle_get_nework_state(); + +#ifdef __cplusplus +} +#endif +#endif//__APP_MAIN_H__ \ No newline at end of file diff --git a/main/drivers/cst816/CST816T.c b/main/drivers/cst816/CST816T.c new file mode 100644 index 0000000..8ce43e9 --- /dev/null +++ b/main/drivers/cst816/CST816T.c @@ -0,0 +1,113 @@ +#include +#include +#include +#include +#include +#include + +#include +#include "esp_log.h" +#include "esp_system.h" +#include "driver/i2c.h" +#include "driver/gpio.h" +#include "CST816T.h" + +static const char *TAG = "CST816T "; + +static int i2c_master_port = I2C_MASTER_NUM; + +esp_err_t i2c_master_init(void) +{ + + i2c_config_t conf = { + .mode = I2C_MODE_MASTER, + .sda_io_num = _sda, + .scl_io_num = _scl, + .sda_pullup_en = GPIO_PULLUP_ENABLE, + .scl_pullup_en = GPIO_PULLUP_ENABLE, + .master.clk_speed = I2C_MASTER_FREQ_HZ, + }; + i2c_param_config(i2c_master_port, &conf); + return i2c_driver_install(i2c_master_port, conf.mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0); +} + +void cst816t_read_touch() +{ + uint8_t rx_data[6]; + uint8_t tx_data[5]; + tx_data[0] = 0x01; + i2c_master_write_to_device(i2c_master_port, CST816T_ADDRESS, tx_data, 1, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS); + vTaskDelay(50 / portTICK_RATE_MS); + i2c_master_read_from_device(i2c_master_port, CST816T_ADDRESS, rx_data, 6, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS); + // ESP_LOG_BUFFER_HEX(TAG, rx_data, 6); + vTaskDelay(50 / portTICK_RATE_MS); + data.gestureID = rx_data[0]; + data.points = rx_data[1]; + data.event = rx_data[2] >> 6; + data.x = rx_data[3]; + data.y = rx_data[5]; +} + +void IRAM_ATTR gpioHandler(void *arg) +{ + _event_available = true; +} + +void cst816t_begin(int sda, int scl, int rst, int irq) +{ + _sda = sda; + _scl = scl; + _rst = rst; + _irq = irq; + ESP_ERROR_CHECK(i2c_master_init()); + gpio_pad_select_gpio(_rst); + gpio_set_direction(_rst, GPIO_MODE_OUTPUT); + gpio_pad_select_gpio(_irq); + gpio_set_direction(_irq, GPIO_MODE_INPUT); + + gpio_set_level(_rst, 1); + vTaskDelay(50 / portTICK_RATE_MS); + gpio_set_level(_rst, 0); + vTaskDelay(5 / portTICK_RATE_MS); + gpio_set_level(_rst, 1); + vTaskDelay(50 / portTICK_RATE_MS); + + uint8_t rx_data[5]; + uint8_t tx_data[5]; + // 芯片性能检查 + tx_data[0] = 0x15; + ESP_LOGE(TAG, "tx_data = 0x15"); + i2c_master_write_to_device(i2c_master_port, CST816T_ADDRESS, tx_data, 1, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS); + vTaskDelay(50 / portTICK_RATE_MS); + i2c_master_read_from_device(i2c_master_port, CST816T_ADDRESS, rx_data, 1, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS); + ESP_LOG_BUFFER_HEX(TAG, rx_data, 1); + vTaskDelay(50 / portTICK_RATE_MS); + //验证芯片版本 + tx_data[0] = 0xA7; + ESP_LOGE(TAG, "tx_data = 0xA7"); + i2c_master_write_to_device(i2c_master_port, CST816T_ADDRESS, tx_data, 1, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS); + vTaskDelay(50 / portTICK_RATE_MS); + i2c_master_read_from_device(i2c_master_port, CST816T_ADDRESS, rx_data, 3, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS); + ESP_LOG_BUFFER_HEX(TAG, rx_data, 3); + vTaskDelay(50 / portTICK_RATE_MS); + //设置和初始化中断 + gpio_install_isr_service(0); + gpio_set_intr_type(_irq, GPIO_INTR_NEGEDGE); + gpio_isr_handler_add(_irq, gpioHandler, (void *)_irq); + gpio_intr_enable(_irq); +} + +bool cst816t_available() +{ + if (_event_available) + { + cst816t_read_touch(); + _event_available = false; + return true; + } + else + { + vTaskDelay(1); + } + return false; +} \ No newline at end of file diff --git a/main/drivers/cst816/CST816T.h b/main/drivers/cst816/CST816T.h new file mode 100644 index 0000000..5940ce3 --- /dev/null +++ b/main/drivers/cst816/CST816T.h @@ -0,0 +1,50 @@ +#ifndef __CST816T_H__ +#define __CST816T_H__ +#define I2C_MASTER_NUM 1 /*!< I2C master i2c port number, the number of i2c peripheral interfaces available will depend on the chip */ +#define I2C_MASTER_FREQ_HZ 400000 /*!< I2C master clock frequency */ +#define I2C_MASTER_TX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */ +#define I2C_MASTER_RX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */ +#define I2C_MASTER_TIMEOUT_MS 1000 +#define CST816T_ADDRESS 0x15 +#define CST816T_RESET_BIT 8 +#define CST816T_RAW_DATA_SIZE 8 + +typedef struct data_struct +{ + uint8_t gestureID; // Gesture ID + uint8_t points; // Number of touch points + uint8_t event; // Event (0 = Down, 1 = Up, 2 = Contact) + int x; + int y; + uint8_t version; + uint8_t versionInfo[3]; +} data_struct_t; + +typedef enum GESTURE +{ + NONE = 0x00, + SWIPE_UP = 0x01, + SWIPE_DOWN = 0x02, + SWIPE_LEFT = 0x04, + SWIPE_RIGHT = 0x03, + SINGLE_CLICK = 0x05, + DOUBLE_CLICK = 0x0B, + LONG_PRESS = 0x0C + +} gesture_t; + +int _sda; +int _scl; +int _rst; +int _irq; + +void cst816t_begin(int sda, int scl, int rst, int irq); +bool cst816t_available(); +void cst816t_read_touch(); +bool _event_available; +void IRAM_ATTR gpioHandler(void *arg); +esp_err_t i2c_master_init(void); +data_struct_t data; +// String gesture(); + +#endif \ No newline at end of file diff --git a/main/drivers/drv_bmp280_3v3/bmp2/bmp2.c b/main/drivers/drv_bmp280_3v3/bmp2/bmp2.c new file mode 100644 index 0000000..e9917fd --- /dev/null +++ b/main/drivers/drv_bmp280_3v3/bmp2/bmp2.c @@ -0,0 +1,1032 @@ +/** +* Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. +* +* BSD-3-Clause +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* 3. Neither the name of the copyright holder nor the names of its +* contributors may be used to endorse or promote products derived from +* this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +* +* @file bmp2.c +* @date 2021-05-21 +* @version v1.0.1 +* +*/ + +/*! @file bmp2.c + * @brief Sensor driver for BMP2 sensor + */ + +#include "bmp2.h" + +/********************** Static function declarations ************************/ + +/*! + * @brief This internal API is used to check for null-pointers in the device + * structure. + * + * @param[in] dev : Structure instance of bmp2_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval <0 -> Fail + */ +static int8_t null_ptr_check(const struct bmp2_dev *dev); + +/*! + * @brief This internal API interleaves the register addresses and respective + * register data for a burst write + * + * @param[in] reg_addr : Register address array + * @param[out] temp_buff : Interleaved register address and data array + * @param[in] reg_data : Register data array + * @param[in] len : Length of the reg_addr and reg_data arrays + * + */ +static void interleave_data(const uint8_t *reg_addr, uint8_t *temp_buff, const uint8_t *reg_data, uint32_t len); + +/*! + * @brief This API is used to read the calibration parameters used + * for calculating the compensated data. + * + * @param[in] dev : Structure instance of bmp2_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval <0 -> Fail + */ +static int8_t get_calib_param(struct bmp2_dev *dev); + +/*! + * @brief This internal API to reset the sensor, restore/set conf, restore/set mode + * + * @param[in] mode : Desired mode + * @param[in] conf : Desired configuration to the bmp2 + * + * conf->os_mode = BMP2_OS_MODE_ULTRA_LOW_POWER, BMP2_OS_MODE_LOW_POWER, BMP2_OS_MODE_STANDARD_RESOLUTION, + * BMP2_OS_MODE_HIGH_RESOLUTION, BMP2_OS_MODE_ULTRA_HIGH_RESOLUTION + * + * conf->mode = BMP2_POWERMODE_SLEEP, BMP2_POWERMODE_FORCED, BMP2_POWERMODE_NORMAL + * + * conf->odr = BMP2_ODR_0_5_MS, BMP2_ODR_62_5_MS, BMP2_ODR_125_MS, + * BMP2_ODR_250_MS, BMP2_ODR_500_MS, BMP2_ODR_1000_MS, + * BMP2_ODR_2000_MS, BMP2_ODR_4000_MS + * + * conf->filter = BMP2_FILTER_OFF, BMP2_FILTER_COEFF_2, + * BMP2_FILTER_COEFF_4, BMP2_FILTER_COEFF_8, BMP2_FILTER_COEFF_16 + * + * @param[in] dev : Structure instance of bmp2_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval <0 -> Fail + */ +static int8_t conf_sensor(uint8_t mode, const struct bmp2_config *conf, struct bmp2_dev *dev); + +/*! + * @brief This API is used to set the over-sampling rate of temperature and pressure + * based on the over-sampling mode. + * + * @param[in] reg_data : Contains register data + * @param[out] conf : Desired configuration to the bmp2 + * + */ +static void set_os_mode(uint8_t *reg_data, const struct bmp2_config *conf); + +/*! + * @brief This API is used to parse the pressure and temperature + * data and store it in the bmp2_uncomp_data structure instance. + * + * @param[in] reg_data : Contains register data which needs to be parsed + * @param[out] uncomp_data : Contains the uncompensated pressure, temperature + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval <0 -> Fail + */ +static int8_t parse_sensor_data(const uint8_t *reg_data, struct bmp2_uncomp_data *uncomp_data); + +#ifdef BMP2_DOUBLE_COMPENSATION + +/*! + * @brief This internal API is used to get the compensated temperature from + * uncompensated temperature. This API uses double floating precision. + * + * @param[out] comp_temperature : Compensated temperature data in double. + * @param[in] uncomp_data : Contains the uncompensated temperature data. + * @param[in] dev : Structure instance of bmp2_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval >0 -> Warning + * @retval <0 -> Fail + */ +static int8_t compensate_temperature(double *comp_temperature, + const struct bmp2_uncomp_data *uncomp_data, + struct bmp2_dev *dev); + +/*! + * @brief This internal API is used to get the compensated pressure from + * uncompensated pressure. This API uses double floating precision. + * + * @param[out] comp_pressure : Compensated pressure data in double. + * @param[in] uncomp_data : Contains the uncompensated pressure data. + * @param[in] dev : Structure instance of bmp2_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval >0 -> Warning + * @retval <0 -> Fail + */ +static int8_t compensate_pressure(double *comp_pressure, + const struct bmp2_uncomp_data *uncomp_data, + const struct bmp2_dev *dev); + +#else + +/*! + * @brief This internal API is used to get the compensated temperature from + * uncompensated temperature. This API uses 32bit integer data type. + * + * @param[out] comp_temperature : Compensated temperature data in integer. + * @param[in] uncomp_data : Contains the uncompensated temperature data. + * @param[in] dev : Structure instance of bmp2_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval >0 -> Warning + * @retval <0 -> Fail + */ +static int8_t compensate_temperature(int32_t *comp_temperature, + const struct bmp2_uncomp_data *uncomp_data, + struct bmp2_dev *dev); + +/*! + * @brief This internal API is used to get the compensated pressure from + * uncompensated pressure. This API uses 64bit integer data type. + * + * @param[out] comp_pressure : Compensated pressure data in integer. + * @param[in] uncomp_data : Contains the uncompensated pressure data. + * @param[in] dev : Structure instance of bmp2_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval >0 -> Warning + * @retval <0 -> Fail + */ +static int8_t compensate_pressure(uint32_t *comp_pressure, + const struct bmp2_uncomp_data *uncomp_data, + const struct bmp2_dev *dev); + +#endif + +/*! + * @This internal API checks whether the uncompensated temperature and pressure are within the range + * + * @param[in] utemperature : Uncompensated temperature + * @param[in] upressure : Uncompensated pressure + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval <0 -> Fail + */ +static int8_t st_check_boundaries(int32_t utemperature, int32_t upressure); + +/****************** User Function Definitions *******************************/ + +/*! + * @brief This API is the entry point. + * It reads the chip-id and calibration data from the sensor. + */ +int8_t bmp2_init(struct bmp2_dev *dev) +{ + int8_t rslt; + + rslt = null_ptr_check(dev); + + if (rslt == BMP2_OK) + { + rslt = bmp2_get_regs(BMP2_REG_CHIP_ID, &dev->chip_id, 1, dev); + + /* Check for chip id validity */ + if (rslt == BMP2_OK) + { + if (dev->chip_id == BMP2_CHIP_ID) + { + rslt = get_calib_param(dev); + } + else + { + rslt = BMP2_E_DEV_NOT_FOUND; + } + } + } + + return rslt; +} + +/*! + * @brief This API reads the data from the given register address of the + * sensor. + */ +int8_t bmp2_get_regs(uint8_t reg_addr, uint8_t *reg_data, uint32_t len, struct bmp2_dev *dev) +{ + int8_t rslt; + + rslt = null_ptr_check(dev); + + if ((rslt == BMP2_OK) && (reg_data != NULL)) + { + /* Mask the register address' MSB if interface selected is SPI */ + if (dev->intf == BMP2_SPI_INTF) + { + reg_addr = reg_addr | BMP2_SPI_RD_MASK; + } + + dev->intf_rslt = dev->read(reg_addr, reg_data, len, dev->intf_ptr); + + /* Check for communication error and mask with an internal error code */ + if (dev->intf_rslt != BMP2_INTF_RET_SUCCESS) + { + rslt = BMP2_E_COM_FAIL; + } + } + else + { + rslt = BMP2_E_NULL_PTR; + } + + return rslt; +} + +/*! + * @brief This API writes the given data to the register addresses + * of the sensor. + */ +int8_t bmp2_set_regs(uint8_t *reg_addr, const uint8_t *reg_data, uint32_t len, struct bmp2_dev *dev) +{ + int8_t rslt; + uint8_t temp_buff[8]; /* Typically not to write more than 4 registers */ + uint32_t temp_len; + uint8_t reg_addr_cnt; + + if (len > BMP2_MAX_LEN) + { + len = BMP2_MAX_LEN; + } + + rslt = null_ptr_check(dev); + + if ((rslt == BMP2_OK) && (reg_addr != NULL) && (reg_data != NULL)) + { + if (len > 0) + { + temp_buff[0] = reg_data[0]; + + /* Mask the register address' MSB if interface selected is SPI */ + if (dev->intf == BMP2_SPI_INTF) + { + /* Converting all the reg address into proper SPI write address + * i.e making MSB(R/`W) bit 0 + */ + for (reg_addr_cnt = 0; reg_addr_cnt < len; reg_addr_cnt++) + { + reg_addr[reg_addr_cnt] = reg_addr[reg_addr_cnt] & BMP2_SPI_WR_MASK; + } + } + + /* Burst write mode */ + if (len > 1) + { + /* Interleave register address w.r.t data for burst write */ + interleave_data(reg_addr, temp_buff, reg_data, len); + temp_len = ((len * 2) - 1); + } + else + { + temp_len = len; + } + + dev->intf_rslt = dev->write(reg_addr[0], temp_buff, temp_len, dev->intf_ptr); + + /* Check for communication error and mask with an internal error code */ + if (dev->intf_rslt != BMP2_INTF_RET_SUCCESS) + { + rslt = BMP2_E_COM_FAIL; + } + } + else + { + rslt = BMP2_E_INVALID_LEN; + } + } + else + { + rslt = BMP2_E_NULL_PTR; + } + + return rslt; +} + +/*! + * @brief This API triggers the soft-reset of the sensor. + */ +int8_t bmp2_soft_reset(struct bmp2_dev *dev) +{ + int8_t rslt; + uint8_t reg_addr = BMP2_REG_SOFT_RESET; + uint8_t soft_rst_cmd = BMP2_SOFT_RESET_CMD; + + rslt = bmp2_set_regs(®_addr, &soft_rst_cmd, 1, dev); + + return rslt; +} + +/*! + * @brief This API reads the data from the ctrl_meas register and config + * register. It gives the currently set temperature and pressure over-sampling + * configuration, power mode configuration, sleep duration and + * IIR filter coefficient. + */ +int8_t bmp2_get_config(struct bmp2_config *conf, struct bmp2_dev *dev) +{ + int8_t rslt; + uint8_t temp[2] = { 0, 0 }; + + if (conf != NULL) + { + rslt = bmp2_get_regs(BMP2_REG_CTRL_MEAS, temp, 2, dev); + + if (rslt == BMP2_OK) + { + conf->os_temp = BMP2_GET_BITS(temp[0], BMP2_OS_TEMP); + conf->os_pres = BMP2_GET_BITS(temp[0], BMP2_OS_PRES); + conf->odr = BMP2_GET_BITS(temp[1], BMP2_STANDBY_DURN); + conf->filter = BMP2_GET_BITS(temp[1], BMP2_FILTER); + conf->spi3w_en = BMP2_GET_BITS_POS_0(temp[1], BMP2_SPI3_ENABLE); + } + } + else + { + rslt = BMP2_E_NULL_PTR; + } + + return rslt; +} + +/*! + * @brief This API writes the data to the ctrl_meas register and config register. + * It sets the over-sampling mode, power mode configuration, + * sleep duration and IIR filter coefficient. + */ +int8_t bmp2_set_config(const struct bmp2_config *conf, struct bmp2_dev *dev) +{ + return conf_sensor(BMP2_POWERMODE_SLEEP, conf, dev); +} + +/*! + * @brief This API reads the status register + */ +int8_t bmp2_get_status(struct bmp2_status *status, struct bmp2_dev *dev) +{ + int8_t rslt; + uint8_t temp; + + if (status != NULL) + { + rslt = bmp2_get_regs(BMP2_REG_STATUS, &temp, 1, dev); + + if (rslt == BMP2_OK) + { + status->measuring = BMP2_GET_BITS(temp, BMP2_STATUS_MEAS); + status->im_update = BMP2_GET_BITS_POS_0(temp, BMP2_STATUS_IM_UPDATE); + } + } + else + { + rslt = BMP2_E_NULL_PTR; + } + + return rslt; +} + +/*! + * @brief This API reads the power mode. + */ +int8_t bmp2_get_power_mode(uint8_t *mode, struct bmp2_dev *dev) +{ + int8_t rslt; + uint8_t temp; + + if (mode != NULL) + { + rslt = bmp2_get_regs(BMP2_REG_CTRL_MEAS, &temp, 1, dev); + + *mode = BMP2_GET_BITS_POS_0(temp, BMP2_POWERMODE); + dev->power_mode = *mode; + } + else + { + rslt = BMP2_E_NULL_PTR; + } + + return rslt; +} + +/*! + * @brief This API writes the power mode. + */ +int8_t bmp2_set_power_mode(uint8_t mode, const struct bmp2_config *conf, struct bmp2_dev *dev) +{ + int8_t rslt; + + rslt = conf_sensor(mode, conf, dev); + + return rslt; +} + +/*! + * @brief This API reads the pressure and temperature data from the + * sensor, compensates the data and store it in the bmp2_data structure + * instance passed by the user. + */ +int8_t bmp2_get_sensor_data(struct bmp2_data *comp_data, struct bmp2_dev *dev) +{ + int8_t rslt; + uint8_t temp[BMP2_P_T_LEN] = { 0 }; + struct bmp2_uncomp_data uncomp_data = { 0 }; + + if (comp_data != NULL) + { + rslt = bmp2_get_regs(BMP2_REG_PRES_MSB, temp, BMP2_P_T_LEN, dev); + + if (rslt == BMP2_OK) + { + /* Parse the read data from the sensor */ + rslt = parse_sensor_data(temp, &uncomp_data); + + if (rslt == BMP2_OK) + { + /* Compensate the pressure and/or temperature + * data from the sensor + */ + rslt = bmp2_compensate_data(&uncomp_data, comp_data, dev); + } + } + } + else + { + rslt = BMP2_E_NULL_PTR; + } + + return rslt; +} + +/*! + * @brief This API is used to compensate the pressure and + * temperature data. + */ +int8_t bmp2_compensate_data(const struct bmp2_uncomp_data *uncomp_data, + struct bmp2_data *comp_data, + struct bmp2_dev *dev) +{ + int8_t rslt; + + rslt = null_ptr_check(dev); + + if ((rslt == BMP2_OK) && (uncomp_data != NULL) && (comp_data != NULL)) + { + /* Initialize to zero */ + comp_data->temperature = 0; + comp_data->pressure = 0; + + rslt = compensate_temperature(&comp_data->temperature, uncomp_data, dev); + + if (rslt == BMP2_OK) + { + rslt = compensate_pressure(&comp_data->pressure, uncomp_data, dev); + } + } + else + { + rslt = BMP2_E_NULL_PTR; + } + + return rslt; +} + +/*! + * @brief This API computes the measurement time in microseconds for the + * active configuration based on standbytime(conf->odr) and over-sampling mode(conf->os_mode) + */ +int8_t bmp2_compute_meas_time(uint32_t *sampling_time, const struct bmp2_config *conf, const struct bmp2_dev *dev) +{ + int8_t rslt; + + /* Array contains measurement time in microseconds */ + uint32_t measurement_time[] = { 5500, 7500, 11500, 19500, 37500 }; + uint32_t standby_time[] = { 500, 62500, 125000, 250000, 500000, 1000000, 2000000, 4000000 }; + + rslt = null_ptr_check(dev); + + if ((rslt == BMP2_OK) && (conf != NULL)) + { + if (dev->power_mode == BMP2_POWERMODE_NORMAL) + { + /* Time in microseconds */ + (*sampling_time) = measurement_time[conf->os_mode] + standby_time[conf->odr]; + } + else + { + /* Time in microseconds */ + (*sampling_time) = measurement_time[conf->os_mode]; + } + } + else + { + rslt = BMP2_E_NULL_PTR; + } + + return rslt; +} + +/****************** Static Function Definitions *******************************/ + +/*! + * @brief This internal API is used to check for null-pointers in the device + * structure. + */ +static int8_t null_ptr_check(const struct bmp2_dev *dev) +{ + int8_t rslt; + + if ((dev == NULL) || (dev->read == NULL) || (dev->write == NULL) || (dev->delay_us == NULL)) + { + /* Null-pointer found */ + rslt = BMP2_E_NULL_PTR; + } + else + { + rslt = BMP2_OK; + } + + return rslt; +} + +/*! + * @brief This internal API interleaves the register addresses and respective + * register data for a burst write + */ +static void interleave_data(const uint8_t *reg_addr, uint8_t *temp_buff, const uint8_t *reg_data, uint32_t len) +{ + uint32_t index; + + for (index = 1; index < len; index++) + { + temp_buff[(index * 2) - 1] = reg_addr[index]; + temp_buff[index * 2] = reg_data[index]; + } +} + +/*! + * @brief This API is used to read the calibration parameters used + * for calculating the compensated data. + */ +static int8_t get_calib_param(struct bmp2_dev *dev) +{ + int8_t rslt; + uint8_t temp[BMP2_CALIB_DATA_SIZE] = { 0 }; + + rslt = bmp2_get_regs(BMP2_REG_DIG_T1_LSB, temp, BMP2_CALIB_DATA_SIZE, dev); + + if (rslt == BMP2_OK) + { + dev->calib_param.dig_t1 = (uint16_t) (BMP2_MSBLSB_TO_U16(temp[BMP2_DIG_T1_MSB_POS], temp[BMP2_DIG_T1_LSB_POS])); + dev->calib_param.dig_t2 = (int16_t) (BMP2_MSBLSB_TO_U16(temp[BMP2_DIG_T2_MSB_POS], temp[BMP2_DIG_T2_LSB_POS])); + dev->calib_param.dig_t3 = (int16_t) (BMP2_MSBLSB_TO_U16(temp[BMP2_DIG_T3_MSB_POS], temp[BMP2_DIG_T3_LSB_POS])); + dev->calib_param.dig_p1 = (uint16_t) (BMP2_MSBLSB_TO_U16(temp[BMP2_DIG_P1_MSB_POS], temp[BMP2_DIG_P1_LSB_POS])); + dev->calib_param.dig_p2 = (int16_t) (BMP2_MSBLSB_TO_U16(temp[BMP2_DIG_P2_MSB_POS], temp[BMP2_DIG_P2_LSB_POS])); + dev->calib_param.dig_p3 = (int16_t) (BMP2_MSBLSB_TO_U16(temp[BMP2_DIG_P3_MSB_POS], temp[BMP2_DIG_P3_LSB_POS])); + dev->calib_param.dig_p4 = (int16_t) (BMP2_MSBLSB_TO_U16(temp[BMP2_DIG_P4_MSB_POS], temp[BMP2_DIG_P4_LSB_POS])); + dev->calib_param.dig_p5 = (int16_t) (BMP2_MSBLSB_TO_U16(temp[BMP2_DIG_P5_MSB_POS], temp[BMP2_DIG_P5_LSB_POS])); + dev->calib_param.dig_p6 = (int16_t) (BMP2_MSBLSB_TO_U16(temp[BMP2_DIG_P6_MSB_POS], temp[BMP2_DIG_P6_LSB_POS])); + dev->calib_param.dig_p7 = (int16_t) (BMP2_MSBLSB_TO_U16(temp[BMP2_DIG_P7_MSB_POS], temp[BMP2_DIG_P7_LSB_POS])); + dev->calib_param.dig_p8 = (int16_t) (BMP2_MSBLSB_TO_U16(temp[BMP2_DIG_P8_MSB_POS], temp[BMP2_DIG_P8_LSB_POS])); + dev->calib_param.dig_p9 = (int16_t) (BMP2_MSBLSB_TO_U16(temp[BMP2_DIG_P9_MSB_POS], temp[BMP2_DIG_P9_LSB_POS])); + dev->calib_param.dig_p10 = (int8_t) ((uint8_t)(temp[BMP2_DIG_P10_POS])); + } + + return rslt; +} + +/*! + * @brief This internal API to reset the sensor, restore/set conf, restore/set mode + */ +static int8_t conf_sensor(uint8_t mode, const struct bmp2_config *conf, struct bmp2_dev *dev) +{ + int8_t rslt; + uint8_t temp[2] = { 0, 0 }; + uint8_t reg_addr[2] = { BMP2_REG_CTRL_MEAS, BMP2_REG_CONFIG }; + + if (conf != NULL) + { + rslt = bmp2_get_regs(BMP2_REG_CTRL_MEAS, temp, 2, dev); + + if (rslt == BMP2_OK) + { + /* Here the intention is to put the device to sleep + * within the shortest period of time + */ + rslt = bmp2_soft_reset(dev); + + if (rslt == BMP2_OK) + { + set_os_mode(temp, conf); + temp[1] = BMP2_SET_BITS(temp[1], BMP2_STANDBY_DURN, conf->odr); + temp[1] = BMP2_SET_BITS(temp[1], BMP2_FILTER, conf->filter); + temp[1] = BMP2_SET_BITS_POS_0(temp[1], BMP2_SPI3_ENABLE, conf->spi3w_en); + + rslt = bmp2_set_regs(reg_addr, temp, 2, dev); + + if ((rslt == BMP2_OK) && (mode != BMP2_POWERMODE_SLEEP)) + { + dev->power_mode = mode; + + /* Write only the power mode register in a separate write */ + temp[0] = BMP2_SET_BITS_POS_0(temp[0], BMP2_POWERMODE, mode); + rslt = bmp2_set_regs(reg_addr, temp, 1, dev); + } + } + } + } + else + { + rslt = BMP2_E_NULL_PTR; + } + + return rslt; +} + +/*! + * @brief This internal API is used to set the over-sampling rate of temperature and pressure + * based on the over-sampling mode. + */ +static void set_os_mode(uint8_t *reg_data, const struct bmp2_config *conf) +{ + switch (conf->os_mode) + { + case BMP2_OS_MODE_ULTRA_LOW_POWER: + reg_data[0] = BMP2_SET_BITS(reg_data[0], BMP2_OS_TEMP, BMP2_OS_1X); + reg_data[0] = BMP2_SET_BITS(reg_data[0], BMP2_OS_PRES, BMP2_OS_1X); + break; + case BMP2_OS_MODE_LOW_POWER: + reg_data[0] = BMP2_SET_BITS(reg_data[0], BMP2_OS_TEMP, BMP2_OS_1X); + reg_data[0] = BMP2_SET_BITS(reg_data[0], BMP2_OS_PRES, BMP2_OS_2X); + break; + case BMP2_OS_MODE_STANDARD_RESOLUTION: + reg_data[0] = BMP2_SET_BITS(reg_data[0], BMP2_OS_TEMP, BMP2_OS_1X); + reg_data[0] = BMP2_SET_BITS(reg_data[0], BMP2_OS_PRES, BMP2_OS_4X); + break; + case BMP2_OS_MODE_HIGH_RESOLUTION: + reg_data[0] = BMP2_SET_BITS(reg_data[0], BMP2_OS_TEMP, BMP2_OS_1X); + reg_data[0] = BMP2_SET_BITS(reg_data[0], BMP2_OS_PRES, BMP2_OS_8X); + break; + case BMP2_OS_MODE_ULTRA_HIGH_RESOLUTION: + reg_data[0] = BMP2_SET_BITS(reg_data[0], BMP2_OS_TEMP, BMP2_OS_2X); + reg_data[0] = BMP2_SET_BITS(reg_data[0], BMP2_OS_PRES, BMP2_OS_16X); + break; + default: + break; + } +} + +/*! + * @brief This internal API is used to parse the pressure and temperature + * data and store it in the bmp2_uncomp_data structure instance. + */ +static int8_t parse_sensor_data(const uint8_t *reg_data, struct bmp2_uncomp_data *uncomp_data) +{ + int8_t rslt; + + /* Variables to store the sensor data */ + uint32_t data_xlsb; + uint32_t data_lsb; + uint32_t data_msb; + + /* Store the parsed register values for pressure data */ + data_msb = (uint32_t)reg_data[0] << 12; + data_lsb = (uint32_t)reg_data[1] << 4; + data_xlsb = (uint32_t)reg_data[2] >> 4; + uncomp_data->pressure = data_msb | data_lsb | data_xlsb; + + /* Store the parsed register values for temperature data */ + data_msb = (int32_t)reg_data[3] << 12; + data_lsb = (int32_t)reg_data[4] << 4; + data_xlsb = (int32_t)reg_data[5] >> 4; + uncomp_data->temperature = (int32_t)(data_msb | data_lsb | data_xlsb); + + rslt = st_check_boundaries((int32_t)uncomp_data->temperature, (int32_t)uncomp_data->pressure); + + return rslt; +} + +#ifdef BMP2_DOUBLE_COMPENSATION + +/*! + * @brief This internal API is used to get the compensated temperature from + * uncompensated temperature. This API uses double floating precision. + */ +static int8_t compensate_temperature(double *comp_temperature, + const struct bmp2_uncomp_data *uncomp_data, + struct bmp2_dev *dev) +{ + int8_t rslt = BMP2_OK; + double var1, var2; + double temperature; + + var1 = (((double) uncomp_data->temperature) / 16384.0 - ((double) dev->calib_param.dig_t1) / 1024.0) * + ((double) dev->calib_param.dig_t2); + var2 = + ((((double) uncomp_data->temperature) / 131072.0 - ((double) dev->calib_param.dig_t1) / 8192.0) * + (((double) uncomp_data->temperature) / 131072.0 - ((double) dev->calib_param.dig_t1) / 8192.0)) * + ((double) dev->calib_param.dig_t3); + + dev->calib_param.t_fine = (int32_t) (var1 + var2); + temperature = (var1 + var2) / 5120.0; + + if (temperature < BMP2_MIN_TEMP_DOUBLE) + { + temperature = BMP2_MIN_TEMP_DOUBLE; + rslt = BMP2_W_MIN_TEMP; + } + + if (temperature > BMP2_MAX_TEMP_DOUBLE) + { + temperature = BMP2_MAX_TEMP_DOUBLE; + rslt = BMP2_W_MAX_TEMP; + } + + (*comp_temperature) = temperature; + + return rslt; +} + +/*! + * @brief This internal API is used to get the compensated pressure from + * uncompensated pressure. This API uses double floating precision. + */ +static int8_t compensate_pressure(double *comp_pressure, + const struct bmp2_uncomp_data *uncomp_data, + const struct bmp2_dev *dev) +{ + int8_t rslt = BMP2_OK; + double var1, var2; + double pressure = 0.0; + + var1 = ((double) dev->calib_param.t_fine / 2.0) - 64000.0; + var2 = var1 * var1 * ((double) dev->calib_param.dig_p6) / 32768.0; + var2 = var2 + var1 * ((double) dev->calib_param.dig_p5) * 2.0; + var2 = (var2 / 4.0) + (((double) dev->calib_param.dig_p4) * 65536.0); + var1 = (((double)dev->calib_param.dig_p3) * var1 * var1 / 524288.0 + ((double)dev->calib_param.dig_p2) * var1) / + 524288.0; + var1 = (1.0 + var1 / 32768.0) * ((double) dev->calib_param.dig_p1); + + if (var1 < 0 || var1 > 0) + { + pressure = 1048576.0 - (double)uncomp_data->pressure; + pressure = (pressure - (var2 / 4096.0)) * 6250.0 / var1; + var1 = ((double)dev->calib_param.dig_p9) * pressure * pressure / 2147483648.0; + var2 = pressure * ((double)dev->calib_param.dig_p8) / 32768.0; + + pressure = pressure + (var1 + var2 + ((double)dev->calib_param.dig_p7)) / 16.0; + + if (pressure < BMP2_MIN_PRES_DOUBLE) + { + pressure = BMP2_MIN_PRES_DOUBLE; + rslt = BMP2_W_MIN_PRES; + } + + if (pressure > BMP2_MAX_PRES_DOUBLE) + { + pressure = BMP2_MAX_PRES_DOUBLE; + rslt = BMP2_W_MAX_PRES; + } + + (*comp_pressure) = pressure; + } + + return rslt; +} + +#else + +/*! + * @brief This internal API is used to get the compensated temperature from + * uncompensated temperature. This API uses 32bit integer data type. + */ +static int8_t compensate_temperature(int32_t *comp_temperature, + const struct bmp2_uncomp_data *uncomp_data, + struct bmp2_dev *dev) +{ + int8_t rslt = BMP2_OK; + int32_t var1, var2; + int32_t temperature; + + var1 = + ((((uncomp_data->temperature / 8) - ((int32_t) dev->calib_param.dig_t1 * 2))) * + ((int32_t) dev->calib_param.dig_t2)) / 2048; + var2 = + (((((uncomp_data->temperature / 16) - ((int32_t) dev->calib_param.dig_t1)) * + ((uncomp_data->temperature / 16) - ((int32_t) dev->calib_param.dig_t1))) / 4096) * + ((int32_t) dev->calib_param.dig_t3)) / 16384; + + dev->calib_param.t_fine = var1 + var2; + + temperature = (dev->calib_param.t_fine * 5 + 128) / 256; + + if (temperature < BMP2_MIN_TEMP_INT) + { + temperature = BMP2_MIN_TEMP_INT; + rslt = BMP2_W_MIN_TEMP; + } + + if (temperature > BMP2_MAX_TEMP_INT) + { + temperature = BMP2_MAX_TEMP_INT; + rslt = BMP2_W_MAX_TEMP; + } + + (*comp_temperature) = temperature; + + return rslt; +} + +#ifndef BMP2_32BIT_COMPENSATION + +/*! + * @brief This internal API is used to get the compensated pressure from + * uncompensated pressure. This API uses 64bit integer data type. + */ +static int8_t compensate_pressure(uint32_t *comp_pressure, + const struct bmp2_uncomp_data *uncomp_data, + const struct bmp2_dev *dev) +{ + int8_t rslt = BMP2_OK; + int64_t var1, var2, p; + uint32_t pressure = 0; + + var1 = ((int64_t) dev->calib_param.t_fine) - 128000; + var2 = var1 * var1 * (int64_t) dev->calib_param.dig_p6; + var2 = var2 + ((var1 * (int64_t) dev->calib_param.dig_p5) * 131072); + var2 = var2 + (((int64_t) dev->calib_param.dig_p4) * 34359738368); + var1 = ((var1 * var1 * (int64_t) dev->calib_param.dig_p3) / 256) + + ((var1 * (int64_t) dev->calib_param.dig_p2) * 4096); + var1 = (((((int64_t)1) * 140737488355328) + var1)) * ((int64_t)dev->calib_param.dig_p1) / 8589934592; + + if (var1 != 0) + { + p = 1048576 - uncomp_data->pressure; + p = (((p * 2147483648) - var2) * 3125) / var1; + var1 = (((int64_t) dev->calib_param.dig_p9) * (p / 8192) * (p / 8192)) / 33554432; + var2 = (((int64_t) dev->calib_param.dig_p8) * p) / 524288; + + p = ((p + var1 + var2) / 256) + (((int64_t)dev->calib_param.dig_p7) * 16); + pressure = (uint32_t)p; + + if (pressure < BMP2_MIN_PRES_64INT) + { + pressure = BMP2_MIN_PRES_64INT; + rslt = BMP2_W_MIN_PRES; + } + + if (pressure > BMP2_MAX_PRES_64INT) + { + pressure = BMP2_MAX_PRES_64INT; + rslt = BMP2_W_MAX_PRES; + } + + (*comp_pressure) = pressure; + } + + return rslt; +} + +#else + +/*! + * @brief This internal API is used to get the compensated pressure from + * uncompensated pressure. This API uses 32bit integer data type. + */ +static int8_t compensate_pressure(uint32_t *comp_pressure, + const struct bmp2_uncomp_data *uncomp_data, + const struct bmp2_dev *dev) +{ + int8_t rslt = BMP2_OK; + int32_t var1, var2; + uint32_t pressure = 0; + + var1 = (((int32_t) dev->calib_param.t_fine) / 2) - (int32_t) 64000; + var2 = (((var1 / 4) * (var1 / 4)) / 2048) * ((int32_t) dev->calib_param.dig_p6); + var2 = var2 + ((var1 * ((int32_t) dev->calib_param.dig_p5)) * 2); + var2 = (var2 / 4) + (((int32_t) dev->calib_param.dig_p4) * 65536); + var1 = + (((dev->calib_param.dig_p3 * (((var1 / 4) * (var1 / 4)) / 8192)) / 8) + + ((((int32_t) dev->calib_param.dig_p2) * var1) / 2)) / 262144; + var1 = ((((32768 + var1)) * ((int32_t) dev->calib_param.dig_p1)) / 32768); + + /* Avoid exception caused by division with zero */ + if (var1 != 0) + { + pressure = (((uint32_t)(((int32_t)1048576) - uncomp_data->pressure) - (var2 / 4096))) * 3125; + + /* Check for overflows against UINT32_MAX/2; if pressure is left-shifted by 1 */ + if (pressure < 0x80000000) + { + pressure = (pressure * 2) / ((uint32_t) var1); + } + else + { + pressure = (pressure / (uint32_t) var1) * 2; + } + + var1 = (((int32_t) dev->calib_param.dig_p9) * ((int32_t) (((pressure / 8) * (pressure / 8)) / 8192))) / 4096; + var2 = (((int32_t) (pressure / 4)) * ((int32_t) dev->calib_param.dig_p8)) / 8192; + pressure = (uint32_t) ((int32_t) pressure + ((var1 + var2 + dev->calib_param.dig_p7) / 16)); + + if (pressure < BMP2_MIN_PRES_32INT) + { + pressure = BMP2_MIN_PRES_32INT; + rslt = BMP2_W_MIN_PRES; + } + + if (pressure > BMP2_MAX_PRES_32INT) + { + pressure = BMP2_MAX_PRES_32INT; + rslt = BMP2_W_MAX_PRES; + } + + (*comp_pressure) = pressure; + } + + return rslt; +} + +#endif +#endif + +/*! + * @This internal API checks whether the uncompensated temperature and + * uncompensated pressure are within the range + */ +static int8_t st_check_boundaries(int32_t utemperature, int32_t upressure) +{ + int8_t rslt = 0; + + /* Check Uncompensated pressure in not valid range AND uncompensated temperature in valid range */ + if ((upressure < BMP2_ST_ADC_P_MIN || upressure > BMP2_ST_ADC_P_MAX) && + (utemperature >= BMP2_ST_ADC_T_MIN && utemperature <= BMP2_ST_ADC_T_MAX)) + { + rslt = BMP2_E_UNCOMP_PRESS_RANGE; + } + /* Check Uncompensated temperature in not valid range AND uncompensated pressure in valid range */ + else if ((utemperature < BMP2_ST_ADC_T_MIN || utemperature > BMP2_ST_ADC_T_MAX) && + (upressure >= BMP2_ST_ADC_P_MIN && upressure <= BMP2_ST_ADC_P_MAX)) + { + rslt = BMP2_E_UNCOMP_TEMP_RANGE; + } + /* Check Uncompensated pressure in not valid range AND uncompensated temperature in not valid range */ + else if ((upressure < BMP2_ST_ADC_P_MIN || upressure > BMP2_ST_ADC_P_MAX) && + (utemperature < BMP2_ST_ADC_T_MIN || utemperature > BMP2_ST_ADC_T_MAX)) + { + rslt = BMP2_E_UNCOMP_TEMP_AND_PRESS_RANGE; + } + else + { + rslt = BMP2_OK; + } + + return rslt; +} diff --git a/main/drivers/drv_bmp280_3v3/bmp2/bmp2.h b/main/drivers/drv_bmp280_3v3/bmp2/bmp2.h new file mode 100644 index 0000000..c5ba31a --- /dev/null +++ b/main/drivers/drv_bmp280_3v3/bmp2/bmp2.h @@ -0,0 +1,393 @@ +/** +* Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. +* +* BSD-3-Clause +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* 3. Neither the name of the copyright holder nor the names of its +* contributors may be used to endorse or promote products derived from +* this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +* +* @file bmp2.h +* @date 2021-05-21 +* @version v1.0.1 +* +*/ + +/*! @file bmp2.h + * @brief Sensor driver for BMP2 sensor + */ + +/*! + * @defgroup bmp2 BMP2 + */ + +#ifndef _BMP2_H +#define _BMP2_H + +/*! CPP guard */ +#ifdef __cplusplus +extern "C" { +#endif + +/****************************************************************************/ + +/*! Header files + ****************************************************************************/ +#include "bmp2_defs.h" + +/***************************************************************************/ + +/*! BMP2 User Interface function prototypes + ****************************************************************************/ + +/** + * \ingroup bmp2 + * \defgroup bmp2ApiInit Initialization + * @brief Perform initialization of sensor + */ + +/*! + * \ingroup bmp2ApiInit + * \page bmp2_api_bmp2_init bmp2_init + * \code + * int8_t bmp2_init(struct bmp2_dev *dev); + * \endcode + * @details This API is the entry point. + * It reads the chip-id and calibration data from the sensor. + * + * @param[in,out] dev : Structure instance of bmp2_dev + * + * @return Result of API execution status. + * + * @retval 0 -> Success. + * @retval < 0 -> Fail. + */ +int8_t bmp2_init(struct bmp2_dev *dev); + +/** + * \ingroup bmp2 + * \defgroup bmp2ApiRegs Registers + * @brief Initialize the sensor and device structure + */ + +/*! + * \ingroup bmp2ApiRegs + * \page bmp2_api_bmp2_get_regs bmp2_get_regs + * \code + * int8_t bmp2_get_regs(uint8_t reg_addr, uint8_t *reg_data, uint32_t len, struct bmp2_dev *dev); + * \endcode + * @details This API reads the data from the given register address of the + * sensor. + * + * @param[in] reg_addr : Register address from where the data to be read + * @param[out] reg_data : Pointer to data buffer to store the read data. + * @param[in] len : No of bytes of data to be read. + * @param[in] dev : Structure instance of bmp2_dev. + * + * @return Result of API execution status. + * + * @retval 0 -> Success. + * @retval < 0 -> Fail. + */ +int8_t bmp2_get_regs(uint8_t reg_addr, uint8_t *reg_data, uint32_t len, struct bmp2_dev *dev); + +/*! + * \ingroup bmp2ApiRegs + * \page bmp2_api_bmp2_set_regs bmp2_set_regs + * \code + * int8_t bmp2_set_regs(uint8_t *reg_addr, const uint8_t *reg_data, uint32_t len, struct bmp2_dev *dev); + * \endcode + * @details This API writes the given data to the register addresses + * of the sensor. + * + * @param[in] reg_addr : Register address from where the data to be written. + * @param[in] reg_data : Pointer to data buffer which is to be written + * in the sensor. + * @param[in] len : No of bytes of data to write.. + * @param[in] dev : Structure instance of bmp2_dev. + * + * @return Result of API execution status. + * + * @retval 0 -> Success. + * @retval < 0 -> Fail. + */ +int8_t bmp2_set_regs(uint8_t *reg_addr, const uint8_t *reg_data, uint32_t len, struct bmp2_dev *dev); + +/** + * \ingroup bmp2 + * \defgroup bmp2ApiSoftreset Soft reset + * @brief Perform self test + */ + +/*! + * \ingroup bmp2ApiSoftreset + * \page bmp2_api_bmp2_soft_reset bmp2_soft_reset + * \code + * int8_t bmp2_soft_reset(struct bmp2_dev *dev); + * \endcode + * @details This API triggers the soft reset of the sensor. + * + * @param[in] dev : Structure instance of bmp2_dev. + * + * @return Result of API execution status. + * + * @retval 0 -> Success. + * @retval < 0 -> Fail. + */ +int8_t bmp2_soft_reset(struct bmp2_dev *dev); + +/** + * \ingroup bmp2 + * \defgroup bmp2ApiPowermode Power mode + * @brief Set / Get power mode of the sensor + */ + +/*! + * \ingroup bmp2ApiPowermode + * \page bmp2_api_bmp2_get_power_mode bmp2_get_power_mode + * \code + * int8_t bmp2_get_power_mode(uint8_t *mode, struct bmp2_dev *dev); + * \endcode + * @details This API reads the power mode. + * + * @param[out] mode : BMP2_POWERMODE_SLEEP, BMP2_POWERMODE_NORMAL, + * BMP2_POWERMODE_FORCED + * @param[in] dev : Structure instance of bmp2_dev + * + * @return Result of API execution status. + * + * @retval 0 -> Success. + * @retval < 0 -> Fail. + */ +int8_t bmp2_get_power_mode(uint8_t *mode, struct bmp2_dev *dev); + +/*! + * \ingroup bmp2ApiPowermode + * \page bmp2_api_bmp2_set_power_mode bmp2_set_power_mode + * \code + * int8_t bmp2_set_power_mode(uint8_t mode, const struct bmp2_config *conf, struct bmp2_dev *dev); + * \endcode + * @details This API writes the power mode. + * + * @param[in] mode : BMP2_POWERMODE_SLEEP, BMP2_POWERMODE_NORMAL, + * BMP2_POWERMODE_FORCED + * @param[in] conf : Structure instance of bmp2_config + * @param[in] dev : Structure instance of bmp2_dev + * + * @return Result of API execution status. + * + * @retval 0 -> Success. + * @retval < 0 -> Fail. + */ +int8_t bmp2_set_power_mode(uint8_t mode, const struct bmp2_config *conf, struct bmp2_dev *dev); + +/** + * \ingroup bmp2 + * \defgroup bmp2ApiConfig Configuration + * @brief Set / Get configurations of the sensor + */ + +/*! + * \ingroup bmp2ApiConfig + * \page bmp2_api_bmp2_get_config bmp2_get_config + * \code + * int8_t bmp2_get_config(struct bmp2_config *conf, struct bmp2_dev *dev); + * \endcode + * @details This API reads the data from the ctrl_meas register and config + * register. It gives the currently set temperature and pressure over-sampling + * configuration, power mode configuration, sleep duration and + * IIR filter coefficient. + * + * @param[out] conf : Current configuration of the bmp2 + * conf->osrs_t, conf->osrs_p = BMP2_OS_NONE, BMP2_OS_1X, + * BMP2_OS_2X, BMP2_OS_4X, BMP2_OS_8X, BMP2_OS_16X + * + * conf->odr = BMP2_ODR_0_5_MS, BMP2_ODR_62_5_MS, BMP2_ODR_125_MS, + * BMP2_ODR_250_MS, BMP2_ODR_500_MS, BMP2_ODR_1000_MS, + * BMP2_ODR_2000_MS, BMP2_ODR_4000_MS + * + * conf->filter = BMP2_FILTER_OFF, BMP2_FILTER_COEFF_2, + * BMP2_FILTER_COEFF_4, BMP2_FILTER_COEFF_8, BMP2_FILTER_COEFF_16 + * + * conf->spi3w_en = BMP2_SPI3_WIRE_ENABLE, BMP2_SPI3_WIRE_DISABLE + * + * @param[in] dev : Structure instance of bmp2_dev + * + * @return Result of API execution status. + * + * @retval 0 -> Success. + * @retval < 0 -> Fail. + */ +int8_t bmp2_get_config(struct bmp2_config *conf, struct bmp2_dev *dev); + +/*! + * \ingroup bmp2ApiConfig + * \page bmp2_api_bmp2_set_config bmp2_set_config + * \code + * int8_t bmp2_set_config(const struct bmp2_config *conf, struct bmp2_dev *dev); + * \endcode + * @details This API writes the data to the ctrl_meas register and config register. + * It sets the over-sampling mode, power mode configuration, + * sleep duration and IIR filter coefficient. + * + * @param[in] conf : Desired configuration to the bmp2 + * conf->osrs_t, conf->osrs_p = BMP2_OS_NONE, BMP2_OS_1X, + * BMP2_OS_2X, BMP2_OS_4X, BMP2_OS_8X, BMP2_OS_16X + * + * conf->odr = BMP2_ODR_0_5_MS, BMP2_ODR_62_5_MS, BMP2_ODR_125_MS, + * BMP2_ODR_250_MS, BMP2_ODR_500_MS, BMP2_ODR_1000_MS, + * BMP2_ODR_2000_MS, BMP2_ODR_4000_MS + * + * conf->filter = BMP2_FILTER_OFF, BMP2_FILTER_COEFF_2, + * BMP2_FILTER_COEFF_4, BMP2_FILTER_COEFF_8, BMP2_FILTER_COEFF_16 + * + * conf->spi3w_en = BMP2_SPI3_WIRE_ENABLE, BMP2_SPI3_WIRE_DISABLE + * + * Over-sampling settings | conf->os_pres | conf->os_temp + *--------------------------|-------------------|--------------------------- + * Ultra low power | 1 | 1 + * Low power | 2 | 1 + * Standard resolution | 4 | 1 + * High resolution | 8 | 1 + * Ultra high resolution | 16 | 2 + * + * @param[in] dev : Structure instance of bmp2_dev + * + * @return Result of API execution status. + * + * @retval 0 -> Success. + * @retval < 0 -> Fail. + */ +int8_t bmp2_set_config(const struct bmp2_config *conf, struct bmp2_dev *dev); + +/** + * \ingroup bmp2 + * \defgroup bmp2ApiStatus Status register + * @brief Read status register + */ + +/*! + * \ingroup bmp2ApiStatus + * \page bmp2_api_bmp2_get_status bmp2_get_status + * \code + * int8_t bmp2_get_status(struct bmp2_status *status, struct bmp2_dev *dev); + * \endcode + * @details This API reads the status register + * + * @param[in,out] status : Structure instance of bmp2_status. + * @param[in] dev : Structure instance of bmp2_dev + * + * @return Result of API execution status. + * + * @retval 0 -> Success. + * @retval < 0 -> Fail. + */ +int8_t bmp2_get_status(struct bmp2_status *status, struct bmp2_dev *dev); + +/** + * \ingroup bmp2 + * \defgroup bmp2ApiSensorData Sensor Data + * @brief Data processing of sensor + */ + +/*! + * \ingroup bmp2ApiSensorData + * \page bmp2_api_bmp2_get_sensor_data bmp2_get_sensor_data + * \code + * int8_t bmp2_get_sensor_data(struct bmp2_data *comp_data, struct bmp2_dev *dev); + * \endcode + * @details This API reads the pressure and temperature data from the + * sensor, compensates the data and store it in the bmp2_data structure + * instance passed by the user. + * + * @param[in] comp_data : Structure instance of bmp2_data + * @param[in] dev : Structure instance of bmp2_dev + * + * @return Result of API execution status. + * + * @retval 0 -> Success. + * @retval < 0 -> Fail. + */ +int8_t bmp2_get_sensor_data(struct bmp2_data *comp_data, struct bmp2_dev *dev); + +/*! + * \ingroup bmp2ApiSensorData + * \page bmp2_api_bmp2_compensate_data bmp2_compensate_data + * \code + * int8_t bmp2_compensate_data(const struct bmp2_uncomp_data *uncomp_data, + * struct bmp2_data *comp_data, + * struct bmp2_dev *dev); + * \endcode + * @details This API is used to compensate the pressure and + * temperature data. + * + * @param[in] uncomp_data : Contains the uncompensated pressure, temperature data. + * @param[out] comp_data : Contains the compensated pressure and/or temperature data. + * @param[in] dev : Structure instance of bmp2_dev. + * + * @return Result of API execution status. + * + * @retval 0 -> Success. + * @retval > 0 -> Warning. + * @retval < 0 -> Fail. + * + */ +int8_t bmp2_compensate_data(const struct bmp2_uncomp_data *uncomp_data, + struct bmp2_data *comp_data, + struct bmp2_dev *dev); + +/** + * \ingroup bmp2 + * \defgroup bmp2ApiMeasTime Compute measurement time + * @brief Computes measurement time (in microseconds) + */ + +/*! + * \ingroup bmp2ApiMeasTime + * \page bmp2_api_bmp2_compute_meas_time bmp2_compute_meas_time + * \code + * int8_t bmp2_compute_meas_time(uint32_t *sampling_time, const struct bmp2_config *conf, const struct bmp2_dev *dev); + * \endcode + * @details This API computes the measurement time in microseconds for the + * active configuration based on standbytime(conf->odr) and over-sampling mode(conf->os_mode) + * + * @param[out] sampling_time : Measurement time for the active configuration in microseconds + * @param[in] conf : Structure instance of bmp2_config + * @param[in] dev : Structure instance of bmp2_dev + * + * @return Result of API execution status. + * + * @retval 0 -> Success. + * @retval < 0 -> Fail. + * + */ +int8_t bmp2_compute_meas_time(uint32_t *sampling_time, const struct bmp2_config *conf, const struct bmp2_dev *dev); + +#ifdef __cplusplus +} +#endif /* End of CPP guard */ + +#endif /* _BMP2_H */ diff --git a/main/drivers/drv_bmp280_3v3/bmp2/bmp2_defs.h b/main/drivers/drv_bmp280_3v3/bmp2/bmp2_defs.h new file mode 100644 index 0000000..8ac811c --- /dev/null +++ b/main/drivers/drv_bmp280_3v3/bmp2/bmp2_defs.h @@ -0,0 +1,602 @@ +/** +* Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. +* +* BSD-3-Clause +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* 3. Neither the name of the copyright holder nor the names of its +* contributors may be used to endorse or promote products derived from +* this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +* +* @file bmp2_defs.h +* @date 2021-05-21 +* @version v1.0.1 +* +*/ + +/*! @file bmp2_defs.h + * @brief Sensor driver for BMP2 sensor + */ + +#ifndef _BMP2_DEFS_H +#define _BMP2_DEFS_H + +/*! CPP guard */ +#ifdef __cplusplus +extern "C" { +#endif + +/****************************************************************/ +/*! @name Header includes */ +/****************************************************************/ +#ifdef __KERNEL__ +#include +#include +#else +#include +#include +#endif + +/****************************************************************/ +/*! @name Common macros */ +/****************************************************************/ +#ifdef __KERNEL__ +#if !defined(UINT8_C) && !defined(INT8_C) +#define INT8_C(x) S8_C(x) +#define UINT8_C(x) U8_C(x) +#endif + +#if !defined(UINT16_C) && !defined(INT16_C) +#define INT16_C(x) S16_C(x) +#define UINT16_C(x) U16_C(x) +#endif + +#if !defined(INT32_C) && !defined(UINT32_C) +#define INT32_C(x) S32_C(x) +#define UINT32_C(x) U32_C(x) +#endif + +#if !defined(INT64_C) && !defined(UINT64_C) +#define INT64_C(x) S64_C(x) +#define UINT64_C(x) U64_C(x) +#endif +#endif + +/*! @name C standard macros */ +#ifndef NULL +#ifdef __cplusplus +#define NULL 0 +#else +#define NULL ((void *) 0) +#endif +#endif + +/******************************************************************************/ +/*! @name Compiler switch macros Definitions */ +/******************************************************************************/ +#ifndef BMP2_64BIT_COMPENSATION /*< Check if 64bit (using BMP2_64BIT_COMPENSATION) is enabled */ +#ifndef BMP2_32BIT_COMPENSATION /*< Check if 32bit (using BMP2_32BIT_COMPENSATION) is enabled */ +#ifndef BMP2_DOUBLE_COMPENSATION /*< If any of the integer data types not enabled then enable + * BMP2_DOUBLE_COMPENSATION */ +#define BMP2_DOUBLE_COMPENSATION +#endif +#endif +#endif + +/******************************************************************************/ +/*! @name General Macro Definitions */ +/******************************************************************************/ + +/*! @name Maximum write length to registers */ +#define BMP2_MAX_LEN UINT8_C(4) + +/*! @name Return codes */ +/*! @name Success code*/ +#define BMP2_OK INT8_C(0) + +/*! @name Error codes */ +#define BMP2_E_NULL_PTR INT8_C(-1) +#define BMP2_E_COM_FAIL INT8_C(-2) +#define BMP2_E_INVALID_LEN INT8_C(-3) +#define BMP2_E_DEV_NOT_FOUND INT8_C(-4) +#define BMP2_E_UNCOMP_TEMP_RANGE INT8_C(-5) +#define BMP2_E_UNCOMP_PRESS_RANGE INT8_C(-6) +#define BMP2_E_UNCOMP_TEMP_AND_PRESS_RANGE INT8_C(-7) + +/*! @name Warning codes */ +#define BMP2_W_MIN_TEMP INT8_C(1) +#define BMP2_W_MAX_TEMP INT8_C(2) +#define BMP2_W_MIN_PRES INT8_C(3) +#define BMP2_W_MAX_PRES INT8_C(4) + +/*! @name Chip ID */ +#define BMP2_CHIP_ID UINT8_C(0x58) + +/*! @name I2C addresses */ +#define BMP2_I2C_ADDR_PRIM UINT8_C(0x76) +#define BMP2_I2C_ADDR_SEC UINT8_C(0x77) + +/*! @name Register addresses */ +#define BMP2_REG_CHIP_ID UINT8_C(0xD0) +#define BMP2_REG_SOFT_RESET UINT8_C(0xE0) +#define BMP2_REG_STATUS UINT8_C(0xF3) +#define BMP2_REG_CTRL_MEAS UINT8_C(0xF4) +#define BMP2_REG_CONFIG UINT8_C(0xF5) +#define BMP2_REG_PRES_MSB UINT8_C(0xF7) +#define BMP2_REG_PRES_LSB UINT8_C(0xF8) +#define BMP2_REG_PRES_XLSB UINT8_C(0xF9) +#define BMP2_REG_TEMP_MSB UINT8_C(0xFA) +#define BMP2_REG_TEMP_LSB UINT8_C(0xFB) +#define BMP2_REG_TEMP_XLSB UINT8_C(0xFC) + +/* Calibration parameter register addresses */ +#define BMP2_REG_DIG_T1_LSB UINT8_C(0x88) +#define BMP2_REG_DIG_T1_MSB UINT8_C(0x89) +#define BMP2_REG_DIG_T2_LSB UINT8_C(0x8A) +#define BMP2_REG_DIG_T2_MSB UINT8_C(0x8B) +#define BMP2_REG_DIG_T3_LSB UINT8_C(0x8C) +#define BMP2_REG_DIG_T3_MSB UINT8_C(0x8D) +#define BMP2_REG_DIG_P1_LSB UINT8_C(0x8E) +#define BMP2_REG_DIG_P1_MSB UINT8_C(0x8F) +#define BMP2_REG_DIG_P2_LSB UINT8_C(0x90) +#define BMP2_REG_DIG_P2_MSB UINT8_C(0x91) +#define BMP2_REG_DIG_P3_LSB UINT8_C(0x92) +#define BMP2_REG_DIG_P3_MSB UINT8_C(0x93) +#define BMP2_REG_DIG_P4_LSB UINT8_C(0x94) +#define BMP2_REG_DIG_P4_MSB UINT8_C(0x95) +#define BMP2_REG_DIG_P5_LSB UINT8_C(0x96) +#define BMP2_REG_DIG_P5_MSB UINT8_C(0x97) +#define BMP2_REG_DIG_P6_LSB UINT8_C(0x98) +#define BMP2_REG_DIG_P6_MSB UINT8_C(0x99) +#define BMP2_REG_DIG_P7_LSB UINT8_C(0x9A) +#define BMP2_REG_DIG_P7_MSB UINT8_C(0x9B) +#define BMP2_REG_DIG_P8_LSB UINT8_C(0x9C) +#define BMP2_REG_DIG_P8_MSB UINT8_C(0x9D) +#define BMP2_REG_DIG_P9_LSB UINT8_C(0x9E) +#define BMP2_REG_DIG_P9_MSB UINT8_C(0x9F) + +/*! @name Interface settings */ +#define BMP2_SPI_RD_MASK UINT8_C(0x80) +#define BMP2_SPI_WR_MASK UINT8_C(0x7F) + +/*! @name Delay definition */ +#define BMP2_DELAY_US_STARTUP_TIME UINT8_C(2000) + +/*! @name Power modes */ +#define BMP2_POWERMODE_SLEEP UINT8_C(0x00) +#define BMP2_POWERMODE_FORCED UINT8_C(0x01) +#define BMP2_POWERMODE_NORMAL UINT8_C(0x03) + +#define BMP2_POWERMODE_POS UINT8_C(0x00) +#define BMP2_POWERMODE_MSK UINT8_C(0x03) + +/*! @name Soft reset command */ +#define BMP2_SOFT_RESET_CMD UINT8_C(0xB6) + +/*! @name Data length */ +#define BMP2_P_T_LEN UINT8_C(0X06) + +/*! @name Temperature range values in integer(32bit, 64bit) and float */ +#define BMP2_MIN_TEMP_INT INT32_C(-4000) +#define BMP2_MAX_TEMP_INT INT32_C(8500) +#define BMP2_MIN_TEMP_DOUBLE -40.0f +#define BMP2_MAX_TEMP_DOUBLE 85.0f + +/*! @name Pressure range values in integer and float */ +#define BMP2_MIN_PRES_32INT UINT32_C(30000) +#define BMP2_MAX_PRES_32INT UINT32_C(110000) +#define BMP2_MIN_PRES_64INT UINT32_C(30000 * 256) +#define BMP2_MAX_PRES_64INT UINT32_C(110000 * 256) +#define BMP2_MIN_PRES_DOUBLE 30000.0f +#define BMP2_MAX_PRES_DOUBLE 110000.0f + +/*! @name ODR options */ +#define BMP2_ODR_0_5_MS UINT8_C(0x00) +#define BMP2_ODR_62_5_MS UINT8_C(0x01) +#define BMP2_ODR_125_MS UINT8_C(0x02) +#define BMP2_ODR_250_MS UINT8_C(0x03) +#define BMP2_ODR_500_MS UINT8_C(0x04) +#define BMP2_ODR_1000_MS UINT8_C(0x05) +#define BMP2_ODR_2000_MS UINT8_C(0x06) +#define BMP2_ODR_4000_MS UINT8_C(0x07) + +/*! @name Over-sampling macros */ +#define BMP2_OS_NONE UINT8_C(0x00) +#define BMP2_OS_1X UINT8_C(0x01) +#define BMP2_OS_2X UINT8_C(0x02) +#define BMP2_OS_4X UINT8_C(0x03) +#define BMP2_OS_8X UINT8_C(0x04) +#define BMP2_OS_16X UINT8_C(0x05) +#define BMP2_OS_TEMP_POS UINT8_C(0x05) +#define BMP2_OS_TEMP_MSK UINT8_C(0xE0) +#define BMP2_OS_PRES_POS UINT8_C(0x02) +#define BMP2_OS_PRES_MSK UINT8_C(0x1C) + +/*! @name Over-sampling mode */ +#define BMP2_OS_MODE_ULTRA_LOW_POWER UINT8_C(0x00) +#define BMP2_OS_MODE_LOW_POWER UINT8_C(0x01) +#define BMP2_OS_MODE_STANDARD_RESOLUTION UINT8_C(0x02) +#define BMP2_OS_MODE_HIGH_RESOLUTION UINT8_C(0x03) +#define BMP2_OS_MODE_ULTRA_HIGH_RESOLUTION UINT8_C(0x04) + +/*! @name Filter coefficient macros */ +#define BMP2_FILTER_OFF UINT8_C(0x00) +#define BMP2_FILTER_COEFF_2 UINT8_C(0x01) +#define BMP2_FILTER_COEFF_4 UINT8_C(0x02) +#define BMP2_FILTER_COEFF_8 UINT8_C(0x03) +#define BMP2_FILTER_COEFF_16 UINT8_C(0x04) + +#define BMP2_FILTER_POS UINT8_C(0x02) +#define BMP2_FILTER_MSK UINT8_C(0x1C) + +/*! @name SPI 3-Wire macros */ +#define BMP2_SPI3_WIRE_ENABLE UINT8_C(0x01) +#define BMP2_SPI3_WIRE_DISABLE UINT8_C(0x00) + +#define BMP2_SPI3_ENABLE_POS UINT8_C(0x00) +#define BMP2_SPI3_ENABLE_MSK UINT8_C(0x01) + +/*! @name Measurement status macros */ +#define BMP2_MEAS_DONE UINT8_C(0x00) +#define BMP2_MEAS_ONGOING UINT8_C(0x01) + +#define BMP2_STATUS_MEAS_POS UINT8_C(0x03) +#define BMP2_STATUS_MEAS_MSK UINT8_C(0x08) + +/*! @name Image update status macros */ +#define BMP2_IM_UPDATE_DONE UINT8_C(0x00) +#define BMP2_IM_UPDATE_ONGOING UINT8_C(0x01) + +#define BMP2_STATUS_IM_UPDATE_POS UINT8_C(0x00) +#define BMP2_STATUS_IM_UPDATE_MSK UINT8_C(0x01) + +/*! @name Standby duration macros */ +#define BMP2_STANDBY_DURN_POS UINT8_C(0x05) +#define BMP2_STANDBY_DURN_MSK UINT8_C(0xE0) + +/*! @name Calibration parameters' relative position */ +#define BMP2_DIG_T1_LSB_POS UINT8_C(0) +#define BMP2_DIG_T1_MSB_POS UINT8_C(1) +#define BMP2_DIG_T2_LSB_POS UINT8_C(2) +#define BMP2_DIG_T2_MSB_POS UINT8_C(3) +#define BMP2_DIG_T3_LSB_POS UINT8_C(4) +#define BMP2_DIG_T3_MSB_POS UINT8_C(5) +#define BMP2_DIG_P1_LSB_POS UINT8_C(6) +#define BMP2_DIG_P1_MSB_POS UINT8_C(7) +#define BMP2_DIG_P2_LSB_POS UINT8_C(8) +#define BMP2_DIG_P2_MSB_POS UINT8_C(9) +#define BMP2_DIG_P3_LSB_POS UINT8_C(10) +#define BMP2_DIG_P3_MSB_POS UINT8_C(11) +#define BMP2_DIG_P4_LSB_POS UINT8_C(12) +#define BMP2_DIG_P4_MSB_POS UINT8_C(13) +#define BMP2_DIG_P5_LSB_POS UINT8_C(14) +#define BMP2_DIG_P5_MSB_POS UINT8_C(15) +#define BMP2_DIG_P6_LSB_POS UINT8_C(16) +#define BMP2_DIG_P6_MSB_POS UINT8_C(17) +#define BMP2_DIG_P7_LSB_POS UINT8_C(18) +#define BMP2_DIG_P7_MSB_POS UINT8_C(19) +#define BMP2_DIG_P8_LSB_POS UINT8_C(20) +#define BMP2_DIG_P8_MSB_POS UINT8_C(21) +#define BMP2_DIG_P9_LSB_POS UINT8_C(22) +#define BMP2_DIG_P9_MSB_POS UINT8_C(23) +#define BMP2_DIG_P10_POS UINT8_C(24) +#define BMP2_CALIB_DATA_SIZE UINT8_C(25) + +/*! @brief Macros holding the minimum and maximum for trimming values */ +#define BMP2_ST_DIG_T1_MIN UINT16_C(19000) +#define BMP2_ST_DIG_T1_MAX UINT16_C(35000) +#define BMP2_ST_DIG_T2_MIN UINT16_C(22000) +#define BMP2_ST_DIG_T2_MAX UINT16_C(30000) +#define BMP2_ST_DIG_T3_MIN INT16_C(-3000) +#define BMP2_ST_DIG_T3_MAX INT16_C(-1000) +#define BMP2_ST_DIG_P1_MIN UINT16_C(30000) +#define BMP2_ST_DIG_P1_MAX UINT16_C(42000) +#define BMP2_ST_DIG_P2_MIN INT16_C(-12970) +#define BMP2_ST_DIG_P2_MAX INT16_C(-8000) +#define BMP2_ST_DIG_P3_MIN INT16_C(-5000) +#define BMP2_ST_DIG_P3_MAX UINT16_C(8000) +#define BMP2_ST_DIG_P4_MIN INT16_C(-10000) +#define BMP2_ST_DIG_P4_MAX UINT16_C(18000) +#define BMP2_ST_DIG_P5_MIN INT16_C(-500) +#define BMP2_ST_DIG_P5_MAX UINT16_C(1100) +#define BMP2_ST_DIG_P6_MIN INT16_C(-1000) +#define BMP2_ST_DIG_P6_MAX UINT16_C(1000) +#define BMP2_ST_DIG_P7_MIN INT16_C(-32768) +#define BMP2_ST_DIG_P7_MAX UINT16_C(32767) +#define BMP2_ST_DIG_P8_MIN INT16_C(-30000) +#define BMP2_ST_DIG_P8_MAX UINT16_C(10000) +#define BMP2_ST_DIG_P9_MIN INT16_C(-10000) +#define BMP2_ST_DIG_P9_MAX UINT16_C(30000) + +/*! @brief Macros holding the minimum and maximum for trimming values */ +/* 0x00000 is minimum output value */ +#define BMP2_ST_ADC_T_MIN INT32_C(0x00000) + +/* 0xFFFF0 is maximum 20-bit output value without over sampling */ +#define BMP2_ST_ADC_T_MAX INT32_C(0xFFFF0) + +/* 0x00000 is minimum output value */ +#define BMP2_ST_ADC_P_MIN INT32_C(0x00000) + +/* 0xFFFF0 is maximum 20-bit output value without over sampling */ +#define BMP2_ST_ADC_P_MAX INT32_C(0xFFFF0) + +/*! @brief Macros to read out API revision number */ +/* Register holding custom trimming values */ +#define BMP2_ST_TRIMCUSTOM_REG UINT8_C(0x87) +#define BMP2_ST_TRIMCUSTOM_REG_APIREV_POS UINT8_C(1) +#define BMP2_ST_TRIMCUSTOM_REG_APIREV_MSK UINT8_C(0x06) +#define BMP2_ST_TRIMCUSTOM_REG_APIREV_LEN UINT8_C(2) +#define BMP2_ST_TRIMCUSTOM_REG_APIREV_REG BMP2_ST_TRIMCUSTOM_REG + +/* Highest API revision supported is revision 0. */ +#define BMP2_ST_MAX_APIREVISION UINT8_C(0x00) + +#define BMP2_MSBLSB_TO_U16(msb, lsb) (((uint16_t)msb << 8) | ((uint16_t)lsb)) + +/*! @name Bit-slicing macros */ +#define BMP2_GET_BITS(reg_data, bitname) ((reg_data & bitname##_MSK) \ + >> bitname##_POS) +#define BMP2_SET_BITS(reg_data, bitname, val) ((reg_data & \ + ~bitname##_MSK) | ((val << bitname##_POS) & bitname##_MSK)) +#define BMP2_SET_BITS_POS_0(reg_data, bitname, data) ((reg_data & \ + ~(bitname##_MSK)) | (data & bitname##_MSK)) +#define BMP2_GET_BITS_POS_0(reg_data, bitname) (reg_data & \ + (bitname##_MSK)) + +/******************************************************************************/ +/*! @name Function Pointers */ +/******************************************************************************/ +#ifndef BMP2_INTF_RET_TYPE +#define BMP2_INTF_RET_TYPE int8_t +#endif + +#ifndef BMP2_INTF_RET_SUCCESS +#define BMP2_INTF_RET_SUCCESS INT8_C(0) +#endif + +/*! + * @brief Bus communication function pointer which should be mapped to + * the platform specific read functions of the user + * + * @param[in] reg_addr : 8bit register address of the sensor + * @param[out] reg_data : Data from the specified address + * @param[in] length : Length of the reg_data array + * @param[in,out] intf_ptr : Void pointer that can enable the linking of descriptors + * for interface related callbacks + * @retval 0 for Success + * @retval Non-zero for Failure + */ +typedef BMP2_INTF_RET_TYPE (*bmp2_read_fptr_t)(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr); + +/*! + * @brief Bus communication function pointer which should be mapped to + * the platform specific read functions of the user + * + * @param[in] reg_addr : 8bit register address of the sensor + * @param[out] reg_data : Data from the specified address + * @param[in] length : Length of the reg_data array + * @param[in,out] intf_ptr : Void pointer that can enable the linking of descriptors + * for interface related callbacks + * @retval 0 for Success + * @retval Non-zero for Failure + */ +typedef BMP2_INTF_RET_TYPE (*bmp2_write_fptr_t)(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, + void *intf_ptr); + +/*! + * @brief Delay function pointer which should be mapped to + * delay function of the user + * + * @param period - The time period in microseconds + * @param[in,out] intf_ptr : Void pointer that can enable the linking of descriptors + * for interface related callbacks + */ +typedef void (*bmp2_delay_us_fptr_t)(uint32_t period, void *intf_ptr); + +/******************************************************************************/ +/*! @name Enum Declarations */ +/******************************************************************************/ + +/*! + * @brief Enum to define BMP2 sensor interfaces + */ +enum bmp2_intf { + /*! SPI interface */ + BMP2_SPI_INTF, + /*! I2C interface */ + BMP2_I2C_INTF +}; + +/******************************************************************************/ +/*! @name Structure Declarations */ +/******************************************************************************/ + +/*! + * @brief Calibration parameters' structure + */ +struct bmp2_calib_param +{ + /*! Calibration parameter of temperature data */ + + /*! Calibration t1 data */ + uint16_t dig_t1; + + /*! Calibration t2 data */ + int16_t dig_t2; + + /*! Calibration t3 data */ + int16_t dig_t3; + + /*! Calibration parameter of pressure data */ + + /*! Calibration p1 data */ + uint16_t dig_p1; + + /*! Calibration p2 data */ + int16_t dig_p2; + + /*! Calibration p3 data */ + int16_t dig_p3; + + /*! Calibration p4 data */ + int16_t dig_p4; + + /*! Calibration p5 data */ + int16_t dig_p5; + + /*! Calibration p6 data */ + int16_t dig_p6; + + /*! Calibration p7 data */ + int16_t dig_p7; + + /*! Calibration p8 data */ + int16_t dig_p8; + + /*! Calibration p9 data */ + int16_t dig_p9; + + /*! Calibration p10 data */ + int8_t dig_p10; + + /*! Fine resolution temperature value */ + int32_t t_fine; +}; + +/*! + * @brief Sensor configuration structure + */ +struct bmp2_config +{ + /*! Over-sampling of temperature data */ + uint8_t os_temp; + + /*! Over-sampling of pressure data */ + uint8_t os_pres; + + /*! Odr set by setting standby duration */ + uint8_t odr; + + /*! Over-sampling mode */ + uint8_t os_mode; + + /*! Time constant of IIR filter */ + uint8_t filter; + + /*! Enable 3-wire SPI interface */ + uint8_t spi3w_en; +}; + +/*! + * @brief Sensor status structure + */ +struct bmp2_status +{ + /*! Data registers' status */ + uint8_t measuring; + + /*! Image register status */ + uint8_t im_update; +}; + +/*! + * @brief Uncompensated data structure + */ +struct bmp2_uncomp_data +{ + /*! Uncompensated temperature data */ + int32_t temperature; + + /*! Uncompensated pressure data */ + uint32_t pressure; +}; + +/*! + * @brief bmp2 sensor structure which comprises of temperature and pressure + */ +#ifdef BMP2_DOUBLE_COMPENSATION +struct bmp2_data +{ + /*! Compensated pressure */ + double pressure; + + /*! Compensated temperature */ + double temperature; +}; +#else +struct bmp2_data +{ + /*! Compensated pressure */ + uint32_t pressure; + + /*! Compensated temperature */ + int32_t temperature; +}; +#endif + +/*! + * @brief API device structure + */ +struct bmp2_dev +{ + /*! Chip Id */ + uint8_t chip_id; + + /*! SPI/I2C Interface selection */ + enum bmp2_intf intf; + + /*! + * The interface pointer is used to enable the user + * to link their interface descriptors for reference during the + * implementation of the read and write interfaces to the + * hardware. + */ + void *intf_ptr; + + /*! Variable that holds result of read/write function */ + BMP2_INTF_RET_TYPE intf_rslt; + + /*! Bus read function pointer */ + bmp2_read_fptr_t read; + + /*! Bus write function pointer */ + bmp2_write_fptr_t write; + + /*! Delay(in us) function pointer */ + bmp2_delay_us_fptr_t delay_us; + + /*! Powermode of the sensor */ + uint8_t power_mode; + + /*! Structure of calibration parameters' */ + struct bmp2_calib_param calib_param; +}; + +#ifdef __cplusplus +} +#endif /* End of CPP guard */ + +#endif /* _BMP2_DEFS_H */ diff --git a/main/drivers/drv_bmp280_3v3/drv_bmp280_3v3.c b/main/drivers/drv_bmp280_3v3/drv_bmp280_3v3.c new file mode 100644 index 0000000..12e69f3 --- /dev/null +++ b/main/drivers/drv_bmp280_3v3/drv_bmp280_3v3.c @@ -0,0 +1,170 @@ +/** + * @file drv_bmp280_3v3.c + * @author impressionyang (impressionyang@outlook.com) + * @brief + * @version 0.1 + * @date 2022-10-09 + * _ _ + * (_)_ _ ___ _______ ___ ___ (_)__ ___ __ _____ ____ ___ _ + * / / ' \/ _ \/ __/ -_|_-<(_- + * Date Version Author Description + * 2022-10-09 v1.0 impressionyang 内容 + * + */ +#include "drv_bmp280_3v3.h" +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +static struct bmp2_status status = {0}; +static struct bmp2_data comp_data = {0}; +static struct bmp2_dev dev = {0}; +static struct bmp2_config conf = {0}; +static uint8_t dev_addr = BMP2_I2C_ADDR_PRIM; + +static void bmp2_error_codes_print_result(const char api_name[], int8_t rslt) +{ + if (rslt != BMP2_OK) + { + printf("%s\t", api_name); + + switch (rslt) + { + case BMP2_E_NULL_PTR: + printf("Error [%d] : Null pointer error.", rslt); + printf( + "It occurs when the user tries to assign value (not address) to a pointer, which has been initialized to NULL.\r\n"); + break; + case BMP2_E_COM_FAIL: + printf("Error [%d] : Communication failure error.", rslt); + printf( + "It occurs due to read/write operation failure and also due to power failure during communication\r\n"); + break; + case BMP2_E_INVALID_LEN: + printf("Error [%d] : Invalid length error.", rslt); + printf("Occurs when length of data to be written is zero\n"); + break; + case BMP2_E_DEV_NOT_FOUND: + printf("Error [%d] : Device not found error. It occurs when the device chip id is incorrectly read\r\n", + rslt); + break; + case BMP2_E_UNCOMP_TEMP_RANGE: + printf("Error [%d] : Uncompensated temperature data not in valid range error.", rslt); + break; + case BMP2_E_UNCOMP_PRESS_RANGE: + printf("Error [%d] : Uncompensated pressure data not in valid range error.", rslt); + break; + case BMP2_E_UNCOMP_TEMP_AND_PRESS_RANGE: + printf( + "Error [%d] : Uncompensated pressure data and uncompensated temperature data are not in valid range error.", + rslt); + break; + default: + printf("Error [%d] : Unknown error code\r\n", rslt); + break; + } + } +} + +uint8_t drv_bmp280_3v3_init(drv_bmp280_3v3_t *handle) +{ + if (!handle || !handle->drv_i2c_read || !handle->drv_i2c_write) { + return 1; + } + + int8_t rslt; + uint32_t meas_time; + + dev.read = handle->drv_i2c_read; + dev.write = handle->drv_i2c_write; + dev.delay_us = handle->delay_10ms; + dev.intf = BMP2_I2C_INTF; + dev.intf_ptr = &dev_addr; + + handle->chip_addr = BMP2_I2C_ADDR_PRIM; + handle->is_drv_init = 1; + handle->drv_state = 1; + printf("1 addr of handle dev = %08x\r\n", (unsigned int)handle->dev); + + handle->dev = &dev; + + printf("2 addr of handle dev = %08x\r\n", (unsigned int)handle->dev); + + rslt = bmp2_init(handle->dev); + bmp2_error_codes_print_result("bmp2_init", rslt); + + rslt = bmp2_get_config(&conf, handle->dev); + bmp2_error_codes_print_result("bmp2_get_config", rslt); + + conf.filter = BMP2_FILTER_OFF; + conf.os_mode = BMP2_OS_MODE_HIGH_RESOLUTION; + conf.odr = BMP2_ODR_250_MS; + + rslt = bmp2_set_config(&conf, handle->dev); + bmp2_error_codes_print_result("bmp2_set_config", rslt); + + rslt = bmp2_set_power_mode(BMP2_POWERMODE_NORMAL, &conf, handle->dev); + bmp2_error_codes_print_result("bmp2_set_power_mode", rslt); + rslt = bmp2_compute_meas_time(&meas_time, &conf, handle->dev); + bmp2_error_codes_print_result("bmp2_compute_meas_time", rslt); + + drv_bmp280_3v3_refresh_data(handle); + + return 0; +} + +uint8_t drv_bmp280_3v3_refresh_data(drv_bmp280_3v3_t *handle) +{ + if (!handle) { + return 1; + } + + int8_t rslt = BMP2_E_NULL_PTR; + + rslt = bmp2_get_status(&status, handle->dev); + bmp2_error_codes_print_result("bmp2_get_status", rslt); + + if (status.measuring == BMP2_MEAS_DONE) + { + rslt = bmp2_get_sensor_data(&comp_data, handle->dev); + bmp2_error_codes_print_result("bmp2_get_sensor_data", rslt); + + }else { + return 1; + } + + return 0; +} + +uint8_t drv_bmp280_3v3_get_pressure(drv_bmp280_3v3_t *handle, double *presure) +{ + if (!handle) { + return 1; + } + + *presure = comp_data.pressure; + + return 0; +} + +uint8_t drv_bmp280_3v3_get_tempreture(drv_bmp280_3v3_t *handle, double *temperature) +{ + if (!handle) { + return 1; + } + + *temperature = comp_data.temperature; + return 0; +} + +uint8_t drv_bmp280_3v3_deinit(drv_bmp280_3v3_t *handle) +{ + handle->is_drv_init = 0; + return 0; +} diff --git a/main/drivers/drv_bmp280_3v3/drv_bmp280_3v3.h b/main/drivers/drv_bmp280_3v3/drv_bmp280_3v3.h new file mode 100644 index 0000000..ea4d62b --- /dev/null +++ b/main/drivers/drv_bmp280_3v3/drv_bmp280_3v3.h @@ -0,0 +1,51 @@ +/** + * @file drv_bmp280_3v3.h + * @author impressionyang (impressionyang@outlook.com) + * @brief + * @version 0.1 + * @date 2022-10-09 + * _ _ + * (_)_ _ ___ _______ ___ ___ (_)__ ___ __ _____ ____ ___ _ + * / / ' \/ _ \/ __/ -_|_-<(_- + * Date Version Author Description + * 2022-10-09 v1.0 impressionyang 内容 + * + */ +#ifndef __DRV_BMP280_3V3_H__ +#define __DRV_BMP280_3V3_H__ + +#include +#include "bmp2.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef struct _drv_bmp280_3v3_t_ +{ + uint8_t is_drv_init; + uint8_t drv_state; + uint8_t chip_addr; + int8_t (*drv_i2c_read)(uint8_t reg_addr, uint8_t *data, uint32_t data_len, void *chip_addr); + int8_t (*drv_i2c_write)(uint8_t reg_addr, const uint8_t *data, uint32_t data_len, void *chip_addr); + uint8_t (*delay_10ms)(uint32_t period, void *intf_ptr); + struct bmp2_dev *dev; +} drv_bmp280_3v3_t; + +uint8_t drv_bmp280_3v3_init(drv_bmp280_3v3_t *handle); +uint8_t drv_bmp280_3v3_refresh_data(drv_bmp280_3v3_t *handle); +uint8_t drv_bmp280_3v3_get_pressure(drv_bmp280_3v3_t *handle, double *presure); +uint8_t drv_bmp280_3v3_get_tempreture(drv_bmp280_3v3_t *handle, double *temperature); +uint8_t drv_bmp280_3v3_deinit(drv_bmp280_3v3_t *handle); + +#ifdef __cplusplus +} +#endif +#endif//__DRV_BMP280_3V3_H__ \ No newline at end of file diff --git a/main/drivers/msg_queue/msg_queue.c b/main/drivers/msg_queue/msg_queue.c new file mode 100644 index 0000000..f4b4577 --- /dev/null +++ b/main/drivers/msg_queue/msg_queue.c @@ -0,0 +1,211 @@ +/** + * @file msg_queue.c + * @author impressionyang (impressionyang@outlook.com) + * @brief + * @version 0.1 + * @date 2022-10-09 + * _ _ + * (_)_ _ ___ _______ ___ ___ (_)__ ___ __ _____ ____ ___ _ + * / / ' \/ _ \/ __/ -_|_-<(_- + * Date Version Author Description + * 2022-10-09 v1.0 impressionyang 内容 + * + */ +#include "msg_queue.h" +#include "link_list.h" +#include +#include + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/queue.h" + +typedef struct _msg_queue_list_node_t_ +{ + char *msg_queue_name; + QueueHandle_t xQueue_handle; +} msg_queue_list_node_t; + +link_list_handle_t *sg_msg_list = NULL; + +/** + * + * @brief 检查是否存在 + * @author impressionyang (impressionyang@outlook.com) + * @param [in] msg_queue_name + * @return uint8_t 0:存在 | 非0:不存在 + * + * @details + */ +static uint8_t _msg_queue_check_msg_q_is_exist(char *msg_queue_name) +{ + uint8_t result = 1; + link_list_node_t *node = sg_msg_list->link_list_header; + msg_queue_list_node_t *msg_node = NULL; + + if (NULL == msg_queue_name) { + // pointer is null + return 2; + } + + if (NULL == node) { + return 3; + } + + for (; node->next != NULL; node = node->next) { + msg_node = node->node_data_ptr; + if (strcmp(msg_queue_name, msg_node->msg_queue_name) == 0) { + result = 0; + break; + } + } + return result; +} + +static uint8_t _msg_queue_get_msg_q_node(char *msg_queue_name, msg_queue_list_node_t *node_need, uint16_t *node_id) +{ + uint8_t result = 1; + link_list_node_t *node = sg_msg_list->link_list_header; + msg_queue_list_node_t *msg_node = NULL; + + if (NULL == msg_queue_name) { + // pointer is null + return 2; + } + + printf("_msg_queue_get_msg_q_node %s\r\n", msg_queue_name); + + if (node != NULL && node->next == NULL) { + msg_node = node->node_data_ptr; + printf("%s : %s\r\n", msg_queue_name, msg_node->msg_queue_name); + if (strcmp(msg_queue_name, msg_node->msg_queue_name) == 0) { + result = 0; + memcpy(node_need, msg_node, sizeof(msg_queue_list_node_t)); + return 0; + } + } + + for (; node != NULL && node->next != NULL; node = node->next) { + msg_node = node->node_data_ptr; + printf("%s : %s\r\n", msg_queue_name, msg_node->msg_queue_name); + if (strcmp(msg_queue_name, msg_node->msg_queue_name) == 0) { + result = 0; + memcpy(node_need, msg_node, sizeof(msg_queue_list_node_t)); + break; + } + } + return result; +} + +uint8_t msg_queue_init() +{ + sg_msg_list = link_list_init(); + return 0; +} + +uint8_t msg_queue_create(char *msg_queue_name) +{ + printf("msg_queue_create: line %d\r\n", __LINE__); + uint8_t ret = 0, msg_node_id; + + if (NULL == msg_queue_name) { + return 1; + } + printf("msg_queue_create: line %d\r\n", __LINE__); + + ret = _msg_queue_check_msg_q_is_exist(msg_queue_name); + if (!ret) { + return 2; + } + printf("msg_queue_create: line %d\r\n", __LINE__); + + msg_queue_list_node_t *msg_node = malloc(sizeof(msg_queue_list_node_t)); + printf("msg_queue_create: line %d\r\n", __LINE__); + msg_node->msg_queue_name = msg_queue_name; + msg_node->xQueue_handle = xQueueCreate(20, sizeof(msg_data_t)); + printf("msg_queue_create: line %d\r\n", __LINE__); + link_list_append_node_to_tail(sg_msg_list, msg_node, &msg_node_id); + printf("msg_queue_create: line %d\r\n", __LINE__); + + return 0; +} + +uint8_t msg_queue_send_msg(char *receiver, msg_data_t *msg) +{ + uint8_t ret = 0; + uint16_t node_id = 0; + msg_queue_list_node_t msg_node = {0}; + ret = _msg_queue_get_msg_q_node(receiver, &msg_node, &node_id); + printf("msg_queue_send_msg _msg_queue_get_msg_q_node ret = %d\r\n", ret); + if (ret) { + return 1; + } + + if(xQueueSend(msg_node.xQueue_handle, (void *)msg, (TickType_t)10) != pdPASS) + { + // Failed to post the message, even after 10 ticks. + return 2; + } + + return 0; +} + +uint8_t msg_queue_recive_msg(char *msg_queue_name, msg_data_t *msg_data_ptr, uint16_t timeout) +{ + uint8_t ret = 0; + uint16_t node_id = 0; + msg_queue_list_node_t msg_node = {0}; + msg_data_t *msg_data_ptr_in_queue = NULL; + ret = _msg_queue_get_msg_q_node(msg_queue_name, &msg_node, &node_id); + printf("msg_queue_recive_msg _msg_queue_get_msg_q_node ret = %d\r\n", ret); + + if (ret) { + return 1; + } + + if (xQueueReceive(msg_node.xQueue_handle, &msg_data_ptr_in_queue, (TickType_t)timeout)) + { + // msg_data_ptr now points to the struct AMessage variable posted + // by vATask. + memcpy(msg_data_ptr, msg_data_ptr_in_queue, sizeof(msg_data_t)); + return 0; + } + return 1; +} + +uint8_t msg_queue_destroy(char *msg_queue_name) +{ + uint8_t ret = 0; + uint16_t node_id = 0; + msg_queue_list_node_t msg_node = {0}; + ret = _msg_queue_get_msg_q_node(msg_queue_name, &msg_node, &node_id); + + if (ret) { + return 1; + } + + vQueueDelete(msg_node.xQueue_handle); + link_list_delete_node_by_id(sg_msg_list, node_id); + + return 0; +} + +uint8_t msg_queue_deinit() +{ + link_list_node_t *node = sg_msg_list->link_list_header; + msg_queue_list_node_t *msg_node = NULL; + + for (; node->next != NULL;) { + msg_node = node->node_data_ptr; + node = node->next; + msg_queue_destroy(msg_node->msg_queue_name); + } + return 0; +} + diff --git a/main/drivers/msg_queue/msg_queue.h b/main/drivers/msg_queue/msg_queue.h new file mode 100644 index 0000000..45f5c4f --- /dev/null +++ b/main/drivers/msg_queue/msg_queue.h @@ -0,0 +1,112 @@ +/** + * @file msg_queue.h + * @author impressionyang (impressionyang@outlook.com) + * @brief 消息队列的驱动,用来进行动态创建、获取、删除消息队列句柄的 + * @version 0.1 + * @date 2022-10-09 + * _ _ + * (_)_ _ ___ _______ ___ ___ (_)__ ___ __ _____ ____ ___ _ + * / / ' \/ _ \/ __/ -_|_-<(_- + * Date Version Author Description + * 2022-10-09 v1.0 impressionyang 内容 + * + */ +#ifndef __MSG_QUEUE_H__ +#define __MSG_QUEUE_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _msg_data_t_ +{ + uint16_t msg_id; + uint16_t msg_reserve; + uint16_t msg_type; + uint16_t msg_value; + union + { + uint32_t msg_data; + void* msg_ptr; + }; +} msg_data_t; + +/** + * + * @brief 初始化消息队列链表 + * @author impressionyang (impressionyang@outlook.com) + * @return uint8_t + * + * @details + */ +uint8_t msg_queue_init(); + +/** + * + * @brief 创建一个消息队列 + * @author impressionyang (impressionyang@outlook.com) + * @param [in] msg_queue_name + * @return uint8_t + * + * @details + */ +uint8_t msg_queue_create(char *msg_queue_name); + +/** + * + * @brief 给指定的消息队列发送消息 + * @author impressionyang (impressionyang@outlook.com) + * @param [in] receiver + * @param [in] msg + * @return uint8_t + * + * @details + */ +uint8_t msg_queue_send_msg(char *receiver, msg_data_t *msg); + +/** + * + * @brief 从消息队列收取消息 + * @author impressionyang (impressionyang@outlook.com) + * @param [in] msg_queue_name + * @param [in] msg_data_ptr + * @param [in] timeout + * @return uint8_t + * + * @details + */ +uint8_t msg_queue_recive_msg(char *msg_queue_name, msg_data_t *msg_data_ptr, uint16_t timeout); + +/** + * + * @brief 销毁一个存在的消息队列 + * @author impressionyang (impressionyang@outlook.com) + * @param [in] msg_queue_name + * @return uint8_t + * + * @details + */ +uint8_t msg_queue_destroy(char *msg_queue_name); + +/** + * + * @brief 去初始化消息队列 + * @author impressionyang (impressionyang@outlook.com) + * @return uint8_t + * + * @details + */ +uint8_t msg_queue_deinit(); + +#ifdef __cplusplus +} +#endif +#endif//__MSG_QUEUE_H__ \ No newline at end of file diff --git a/main/drivers/st7789/bmpfile.h b/main/drivers/st7789/bmpfile.h new file mode 100644 index 0000000..95f70e3 --- /dev/null +++ b/main/drivers/st7789/bmpfile.h @@ -0,0 +1,51 @@ +#ifndef __bmpfile_h__ +#define __bmpfile_h__ + +typedef struct { + uint8_t magic[2]; /* the magic number used to identify the BMP file: + 0x42 0x4D (Hex code points for B and M). + The following entries are possible: + BM - Windows 3.1x, 95, NT, ... etc + BA - OS/2 Bitmap Array + CI - OS/2 Color Icon + CP - OS/2 Color Pointer + IC - OS/2 Icon + PT - OS/2 Pointer. */ + uint32_t filesz; /* the size of the BMP file in bytes */ + uint16_t creator1; /* reserved. */ + uint16_t creator2; /* reserved. */ + uint32_t offset; /* the offset, i.e. starting address, + of the byte where the bitmap data can be found. */ +} bmp_header_t; + +typedef struct { + uint32_t header_sz; /* the size of this header (40 bytes) */ + uint32_t width; /* the bitmap width in pixels */ + uint32_t height; /* the bitmap height in pixels */ + uint16_t nplanes; /* the number of color planes being used. + Must be set to 1. */ + uint16_t depth; /* the number of bits per pixel, + which is the color depth of the image. + Typical values are 1, 4, 8, 16, 24 and 32. */ + uint32_t compress_type; /* the compression method being used. + See also bmp_compression_method_t. */ + uint32_t bmp_bytesz; /* the image size. This is the size of the raw bitmap + data (see below), and should not be confused + with the file size. */ + uint32_t hres; /* the horizontal resolution of the image. + (pixel per meter) */ + uint32_t vres; /* the vertical resolution of the image. + (pixel per meter) */ + uint32_t ncolors; /* the number of colors in the color palette, + or 0 to default to 2n. */ + uint32_t nimpcolors; /* the number of important colors used, + or 0 when every color is important; + generally ignored. */ +} bmp_dib_v3_header_t; + +typedef struct { + bmp_header_t header; + bmp_dib_v3_header_t dib; +} bmpfile_t; + +#endif /* __bmpfile_h__ */ diff --git a/main/drivers/st7789/decode_jpeg.c b/main/drivers/st7789/decode_jpeg.c new file mode 100644 index 0000000..06fdae7 --- /dev/null +++ b/main/drivers/st7789/decode_jpeg.c @@ -0,0 +1,186 @@ +#include +#include "decode_jpeg.h" +#include "esp32/rom/tjpgd.h" +#include "esp_log.h" + +//Data that is passed from the decoder function to the infunc/outfunc functions. +typedef struct { + pixel_jpeg **outData; // Array of IMAGE_H pointers to arrays of 16-bit pixel values + int screenWidth; // Width of the screen + int screenHeight; // Height of the screen + FILE* fp; // File pointer of jpeg file +} JpegDev; + + +//Input function for jpeg decoder. Just returns bytes from the inData field of the JpegDev structure. +static UINT infunc(JDEC *decoder, BYTE *buf, UINT len) { + JpegDev *jd = (JpegDev *) decoder->device; + ESP_LOGD(__FUNCTION__, "infunc len=%d fp=%p", len, jd->fp); + int rlen; + if (buf != NULL) { /* Read nd bytes from the input strem */ + rlen = fread(buf, 1, len, jd->fp); + ESP_LOGD(__FUNCTION__, "rlen=%d",rlen); + } else { /* Skip nd bytes on the input stream */ + ESP_LOGD(__FUNCTION__, "buff is NULL"); + fseek(jd->fp, len, SEEK_CUR); + rlen = len; + } + return rlen; +} + +#define rgb565(r, g, b) (((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3)) + +//Output function. Re-encodes the RGB888 data from the decoder as big-endian RGB565 and +//stores it in the outData array of the JpegDev structure. +static UINT outfunc(JDEC *decoder, void *bitmap, JRECT *rect) { + JpegDev *jd = (JpegDev *) decoder->device; + uint8_t *in = (uint8_t *) bitmap; + ESP_LOGD(__FUNCTION__, "rect->top=%d rect->bottom=%d", rect->top, rect->bottom); + ESP_LOGD(__FUNCTION__, "rect->left=%d rect->right=%d", rect->left, rect->right); + ESP_LOGD(__FUNCTION__, "jd->screenWidth=%d jd->screenHeight=%d", jd->screenWidth, jd->screenHeight); + + for (int y = rect->top; y <= rect->bottom; y++) { + for (int x = rect->left; x <= rect->right; x++) { + + if (y < jd->screenHeight && x < jd->screenWidth) { +#if 0 + jd->outData[y][x].red = in[0]; + jd->outData[y][x].green = in[1]; + jd->outData[y][x].blue = in[2]; +#endif + jd->outData[y][x] = rgb565(in[0], in[1], in[2]); + } + + in += 3; + } + } + return 1; +} + +// Specifies scaling factor N for output. The output image is descaled to 1 / 2 ^ N (N = 0 to 3). +// When scaling feature is disabled (JD_USE_SCALE == 0), it must be 0. +uint8_t getScale(uint16_t screenWidth, uint16_t screenHeight, uint16_t imageWidth, uint16_t imageHeight) { + if (screenWidth >= imageWidth && screenHeight >= imageHeight) return 0; + + double scaleWidth = (double)imageWidth / (double)screenWidth; + double scaleHeight = (double)imageHeight / (double)screenHeight; + ESP_LOGD(__FUNCTION__, "scaleWidth=%f scaleHeight=%f", scaleWidth, scaleHeight); + double scale = scaleWidth; + if (scaleWidth < scaleHeight) scale = scaleHeight; + ESP_LOGD(__FUNCTION__, "scale=%f", scale); + if (scale <= 2.0) return 1; + if (scale <= 4.0) return 2; + return 3; + +} + +//Size of the work space for the jpeg decoder. +#define WORKSZ 3100 + +//Decode the embedded image into pixel lines that can be used with the rest of the logic. +esp_err_t decode_jpeg(pixel_jpeg ***pixels, char * file, uint16_t width, uint16_t height, uint16_t * imageWidth, uint16_t * imageHeight) { + char *work = NULL; + int r; + JDEC decoder; + JpegDev jd; + *pixels = NULL; + esp_err_t ret = ESP_OK; + + + //Alocate pixel memory. Each line is an array of IMAGE_W 16-bit pixels; the `*pixels` array itself contains pointers to these lines. + *pixels = calloc(height, sizeof(pixel_jpeg *)); + if (*pixels == NULL) { + ESP_LOGE(__FUNCTION__, "Error allocating memory for lines"); + ret = ESP_ERR_NO_MEM; + goto err; + } + for (int i = 0; i < height; i++) { + (*pixels)[i] = malloc(width * sizeof(pixel_jpeg)); + if ((*pixels)[i] == NULL) { + ESP_LOGE(__FUNCTION__, "Error allocating memory for line %d", i); + ret = ESP_ERR_NO_MEM; + goto err; + } + } + + //Allocate the work space for the jpeg decoder. + work = calloc(WORKSZ, 1); + if (work == NULL) { + ESP_LOGE(__FUNCTION__, "Cannot allocate workspace"); + ret = ESP_ERR_NO_MEM; + goto err; + } + + + //Populate fields of the JpegDev struct. + jd.outData = *pixels; + jd.screenWidth = width; + jd.screenHeight = height; + jd.fp = fopen(file, "rb"); + if (jd.fp == NULL) { + ESP_LOGW(__FUNCTION__, "Image file not found [%s]", file); + ret = ESP_ERR_NOT_FOUND; + goto err; + } + ESP_LOGD(__FUNCTION__, "jd.fp=%p", jd.fp); + + //Prepare and decode the jpeg. + r = jd_prepare(&decoder, infunc, work, WORKSZ, (void *) &jd); + if (r != JDR_OK) { + ESP_LOGE(__FUNCTION__, "Image decoder: jd_prepare failed (%d)", r); + ret = ESP_ERR_NOT_SUPPORTED; + goto err; + } + ESP_LOGD(__FUNCTION__, "decoder.width=%d decoder.height=%d", decoder.width, decoder.height); + + //Calculate Scaling factor + uint8_t scale = getScale(width, height, decoder.width, decoder.height); + ESP_LOGD(__FUNCTION__, "scale=%d", scale); + + //Calculate image size + double factor = 1.0; + if (scale == 1) factor = 0.5; + if (scale == 2) factor = 0.25; + if (scale == 3) factor = 0.125; + ESP_LOGD(__FUNCTION__, "factor=%f",factor); + *imageWidth = (double)decoder.width * factor; + *imageHeight = (double)decoder.height * factor; + ESP_LOGD(__FUNCTION__, "imageWidth=%d imageHeight=%d", *imageWidth, *imageHeight); + + + r = jd_decomp(&decoder, outfunc, scale); + if (r != JDR_OK) { + ESP_LOGE(__FUNCTION__, "Image decoder: jd_decode failed (%d)", r); + ret = ESP_ERR_NOT_SUPPORTED; + goto err; + } + + //All done! Free the work area (as we don't need it anymore) and return victoriously. + free(work); + fclose(jd.fp); + return ret; + + //Something went wrong! Exit cleanly, de-allocating everything we allocated. + err: + fclose(jd.fp); + if (*pixels != NULL) { + for (int i = 0; i < height; i++) { + free((*pixels)[i]); + } + free(*pixels); + } + free(work); + return ret; +} + + +esp_err_t release_image(pixel_jpeg ***pixels, uint16_t width, uint16_t height) { + if (*pixels != NULL) { + for (int i = 0; i < height; i++) { + free((*pixels)[i]); + } + free(*pixels); + } + return ESP_OK; +} + diff --git a/main/drivers/st7789/decode_jpeg.h b/main/drivers/st7789/decode_jpeg.h new file mode 100644 index 0000000..e69a722 --- /dev/null +++ b/main/drivers/st7789/decode_jpeg.h @@ -0,0 +1,34 @@ +#pragma once +#include +#include "esp_err.h" + +#if 0 +typedef struct __attribute__((__packed__)) { + uint8_t red; + uint8_t green; + uint8_t blue; +} pixel_jpeg; +#endif + +//rgb565 format +typedef uint16_t pixel_jpeg; + +/** + * @brief Decode the jpeg ``image.jpg`` embedded into the program file into pixel data. + * + * @param pixels A pointer to a pointer for an array of rows, which themselves are an array of pixels. + * Effectively, you can get the pixel data by doing ``decode_jpeg(&myPixels); pixelval=myPixels[ypos][xpos];`` + * @return - ESP_ERR_NOT_SUPPORTED if image is malformed or a progressive jpeg file + * - ESP_ERR_NO_MEM if out of memory + * - ESP_OK on succesful decode + */ + +esp_err_t decode_jpeg(pixel_jpeg ***pixels, char * file, uint16_t width, uint16_t height, uint16_t * imageWidth, uint16_t * imageHeight); + +/** + * @brief Release image memory. + * + */ + +esp_err_t release_image(pixel_jpeg ***pixels, uint16_t width, uint16_t height); + diff --git a/main/drivers/st7789/decode_png.c b/main/drivers/st7789/decode_png.c new file mode 100644 index 0000000..9e80f63 --- /dev/null +++ b/main/drivers/st7789/decode_png.c @@ -0,0 +1,61 @@ +#include +#include "decode_png.h" +#include "pngle.h" +#include "esp_log.h" + +void png_init(pngle_t *pngle, uint32_t w, uint32_t h) +{ + ESP_LOGD(__FUNCTION__, "png_init w=%d h=%d", w, h); + ESP_LOGD(__FUNCTION__, "screenWidth=%d screenHeight=%d", pngle->screenWidth, pngle->screenHeight); + pngle->imageWidth = w; + pngle->imageHeight = h; + pngle->reduction = false; + pngle->scale_factor = 1.0; + + // Calculate Reduction + if (pngle->screenWidth < pngle->imageWidth || pngle->screenHeight < pngle->imageHeight) { + pngle->reduction = true; + double factorWidth = (double)pngle->screenWidth / (double)pngle->imageWidth; + double factorHeight = (double)pngle->screenHeight / (double)pngle->imageHeight; + pngle->scale_factor = factorWidth; + if (factorHeight < factorWidth) pngle->scale_factor = factorHeight; + pngle->imageWidth = pngle->imageWidth * pngle->scale_factor; + pngle->imageHeight = pngle->imageHeight * pngle->scale_factor; + } + ESP_LOGD(__FUNCTION__, "reduction=%d scale_factor=%f", pngle->reduction, pngle->scale_factor); + ESP_LOGD(__FUNCTION__, "imageWidth=%d imageHeight=%d", pngle->imageWidth, pngle->imageHeight); + +} + +#define rgb565(r, g, b) (((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3)) + +void png_draw(pngle_t *pngle, uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint8_t rgba[4]) +{ + ESP_LOGD(__FUNCTION__, "png_draw x=%d y=%d w=%d h=%d", x,y,w,h); +#if 0 + uint8_t r = rgba[0]; + uint8_t g = rgba[1]; + uint8_t b = rgba[2]; +#endif + + // image reduction + uint32_t _x = x; + uint32_t _y = y; + if (pngle->reduction) { + _x = x * pngle->scale_factor; + _y = y * pngle->scale_factor; + } + if (_y < pngle->screenHeight && _x < pngle->screenWidth) { +#if 0 + pngle->pixels[_y][_x].red = rgba[0]; + pngle->pixels[_y][_x].green = rgba[1]; + pngle->pixels[_y][_x].blue = rgba[2]; +#endif + pngle->pixels[_y][_x] = rgb565(rgba[0], rgba[1], rgba[2]); + } + +} + +void png_finish(pngle_t *pngle) { + ESP_LOGD(__FUNCTION__, "png_finish"); +} diff --git a/main/drivers/st7789/decode_png.h b/main/drivers/st7789/decode_png.h new file mode 100644 index 0000000..66365c6 --- /dev/null +++ b/main/drivers/st7789/decode_png.h @@ -0,0 +1,9 @@ +#pragma once +#include +#include +#include "pngle.h" + +void png_init(pngle_t *pngle, uint32_t w, uint32_t h); +void png_draw(pngle_t *pngle, uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint8_t rgba[4]); +void png_finish(pngle_t *pngle); + diff --git a/main/drivers/st7789/fontx.c b/main/drivers/st7789/fontx.c new file mode 100644 index 0000000..c332535 --- /dev/null +++ b/main/drivers/st7789/fontx.c @@ -0,0 +1,582 @@ +#include +#include +#include +#include +#include "esp_err.h" +#include "esp_log.h" +#include "esp_spiffs.h" + +#include "fontx.h" + +#define FontxDebug 0 // for Debug + +// フォントファイルパスを構造体に保存 +void AddFontx(FontxFile *fx, const char *path) +{ + memset(fx, 0, sizeof(FontxFile)); + fx->path = path; + fx->opened = false; +} + +// フォント構造体を初期化 +void InitFontx(FontxFile *fxs, const char *f0, const char *f1) +{ + AddFontx(&fxs[0], f0); + AddFontx(&fxs[1], f1); +} + +// フォントファイルをOPEN +bool OpenFontx(FontxFile *fx) +{ + FILE *f; + if(!fx->opened){ + if(FontxDebug)printf("[openFont]fx->path=[%s]\n",fx->path); + f = fopen(fx->path, "r"); + if(FontxDebug)printf("[openFont]fopen=%p\n",f); + if (f == NULL) { + fx->valid = false; + printf("Fontx:%s not found.\n",fx->path); + return fx->valid ; + } + fx->opened = true; + fx->file = f; + char buf[18]; + if (fread(buf, 1, sizeof(buf), fx->file) != sizeof(buf)) { + fx->valid = false; + printf("Fontx:%s not FONTX format.\n",fx->path); + fclose(fx->file); + return fx->valid ; + } + + if(FontxDebug) { + for(int i=0;ifxname, &buf[6], 8); + fx->w = buf[14]; + fx->h = buf[15]; + fx->is_ank = (buf[16] == 0); + fx->bc = buf[17]; + fx->fsz = (fx->w + 7)/8 * fx->h; + if(fx->fsz > FontxGlyphBufSize){ + printf("Fontx:%s is too big font size.\n",fx->path); + fx->valid = false; + fclose(fx->file); + return fx->valid ; + } + fx->valid = true; + } + return fx->valid; +} + +// フォントファイルをCLOSE +void CloseFontx(FontxFile *fx) +{ + if(fx->opened){ + fclose(fx->file); + fx->opened = false; + } +} + +// フォント構造体の表示 +void DumpFontx(FontxFile *fxs) +{ + for(int i=0;i<2;i++) { + printf("fxs[%d]->path=%s\n",i,fxs[i].path); + printf("fxs[%d]->opened=%d\n",i,fxs[i].opened); + printf("fxs[%d]->fxname=%s\n",i,fxs[i].fxname); + printf("fxs[%d]->valid=%d\n",i,fxs[i].valid); + printf("fxs[%d]->is_ank=%d\n",i,fxs[i].is_ank); + printf("fxs[%d]->w=%d\n",i,fxs[i].w); + printf("fxs[%d]->h=%d\n",i,fxs[i].h); + printf("fxs[%d]->fsz=%d\n",i,fxs[i].fsz); + printf("fxs[%d]->bc=%d\n",i,fxs[i].bc); + } +} + +uint8_t getFortWidth(FontxFile *fx) { + printf("fx->w=%d\n",fx->w); + return(fx->w); +} + +uint8_t getFortHeight(FontxFile *fx) { + printf("fx->h=%d\n",fx->h); + return(fx->h); +} + + +/* + フォントファイルからフォントパターンを取り出す + + フォントの並び(16X16ドット) + 00000000 01111111 + 12345678 90123456 + 01 pGlyph[000] pGlyph[001] + 02 pGlyph[002] pGlyph[003] + 03 pGlyph[004] pGlyph[005] + 04 pGlyph[006] pGlyph[007] + 05 pGlyph[008] pGlyph[009] + 06 pGlyph[010] pGlyph[011] + 07 pGlyph[012] pGlyph[013] + 08 pGlyph[014] pGlyph[015] + 09 pGlyph[016] pGlyph[017] + 10 pGlyph[018] pGlyph[019] + 11 pGlyph[020] pGlyph[021] + 12 pGlyph[022] pGlyph[023] + 13 pGlyph[024] pGlyph[025] + 14 pGlyph[026] pGlyph[027] + 15 pGlyph[028] pGlyph[029] + 16 pGlyph[030] pGlyph[031] + + フォントの並び(24X24ドット) + 00000000 01111111 11122222 + 12345678 90123456 78901234 + 01 pGlyph[000] pGlyph[001] pGlyph[002] + 02 pGlyph[003] pGlyph[004] pGlyph[005] + 03 pGlyph[006] pGlyph[007] pGlyph[008] + 04 pGlyph[009] pGlyph[010] pGlyph[011] + 05 pGlyph[012] pGlyph[013] pGlyph[014] + 06 pGlyph[015] pGlyph[016] pGlyph[017] + 07 pGlyph[018] pGlyph[019] pGlyph[020] + 08 pGlyph[021] pGlyph[022] pGlyph[023] + 09 pGlyph[024] pGlyph[025] pGlyph[026] + 10 pGlyph[027] pGlyph[028] pGlyph[029] + 11 pGlyph[030] pGlyph[031] pGlyph[032] + 12 pGlyph[033] pGlyph[034] pGlyph[035] + 13 pGlyph[036] pGlyph[037] pGlyph[038] + 14 pGlyph[039] pGlyph[040] pGlyph[041] + 15 pGlyph[042] pGlyph[043] pGlyph[044] + 16 pGlyph[045] pGlyph[046] pGlyph[047] + 17 pGlyph[048] pGlyph[049] pGlyph[050] + 18 pGlyph[051] pGlyph[052] pGlyph[053] + 19 pGlyph[054] pGlyph[055] pGlyph[056] + 20 pGlyph[057] pGlyph[058] pGlyph[059] + 21 pGlyph[060] pGlyph[061] pGlyph[062] + 22 pGlyph[063] pGlyph[064] pGlyph[065] + 23 pGlyph[066] pGlyph[067] pGlyph[068] + 24 pGlyph[069] pGlyph[070] pGlyph[071] + + フォントの並び(32X32ドット) + 00000000 01111111 11122222 22222333 + 12345678 90123456 78901234 56789012 + 01 pGlyph[000] pGlyph[001] pGlyph[002] pGlyph[003] + 02 pGlyph[004] pGlyph[005] pGlyph[006] pGlyph[007] + 03 pGlyph[008] pGlyph[009] pGlyph[010] pGlyph[011] + 04 pGlyph[012] pGlyph[013] pGlyph[014] pGlyph[015] + 05 pGlyph[016] pGlyph[017] pGlyph[018] pGlyph[019] + 06 pGlyph[020] pGlyph[021] pGlyph[022] pGlyph[023] + 07 pGlyph[024] pGlyph[025] pGlyph[026] pGlyph[027] + 08 pGlyph[028] pGlyph[029] pGlyph[030] pGlyph[031] + 09 pGlyph[032] pGlyph[033] pGlyph[034] pGlyph[035] + 10 pGlyph[036] pGlyph[037] pGlyph[038] pGlyph[039] + 11 pGlyph[040] pGlyph[041] pGlyph[042] pGlyph[043] + 12 pGlyph[044] pGlyph[045] pGlyph[046] pGlyph[047] + 13 pGlyph[048] pGlyph[049] pGlyph[050] pGlyph[051] + 14 pGlyph[052] pGlyph[053] pGlyph[054] pGlyph[055] + 15 pGlyph[056] pGlyph[057] pGlyph[058] pGlyph[059] + 16 pGlyph[060] pGlyph[061] pGlyph[062] pGlyph[063] + 17 pGlyph[064] pGlyph[065] pGlyph[066] pGlyph[067] + 18 pGlyph[068] pGlyph[069] pGlyph[070] pGlyph[071] + 19 pGlyph[072] pGlyph[073] pGlyph[074] pGlyph[075] + 20 pGlyph[076] pGlyph[077] pGlyph[078] pGlyph[079] + 21 pGlyph[080] pGlyph[081] pGlyph[082] pGlyph[083] + 22 pGlyph[084] pGlyph[085] pGlyph[086] pGlyph[087] + 23 pGlyph[088] pGlyph[089] pGlyph[090] pGlyph[091] + 24 pGlyph[092] pGlyph[093] pGlyph[094] pGlyph[095] + 25 pGlyph[096] pGlyph[097] pGlyph[098] pGlyph[099] + 26 pGlyph[100] pGlyph[101] pGlyph[102] pGlyph[103] + 27 pGlyph[104] pGlyph[105] pGlyph[106] pGlyph[107] + 28 pGlyph[108] pGlyph[109] pGlyph[110] pGlyph[111] + 29 pGlyph[112] pGlyph[113] pGlyph[114] pGlyph[115] + 30 pGlyph[116] pGlyph[117] pGlyph[118] pGlyph[119] + 31 pGlyph[120] pGlyph[121] pGlyph[122] pGlyph[123] + 32 pGlyph[124] pGlyph[125] pGlyph[127] pGlyph[128] + +*/ + +bool GetFontx(FontxFile *fxs, uint8_t ascii , uint8_t *pGlyph, uint8_t *pw, uint8_t *ph) +{ + + int i; + uint32_t offset; + + if(FontxDebug)printf("[GetFontx]ascii=0x%x\n",ascii); + for(i=0; i<2; i++){ + //for(i=0; i<1; i++){ + if(!OpenFontx(&fxs[i])) continue; + if(FontxDebug)printf("[GetFontx]openFontxFile[%d] ok\n",i); + + //if(ascii < 0xFF){ + if(fxs[i].is_ank){ + if(FontxDebug)printf("[GetFontx]fxs.is_ank fxs.fsz=%d\n",fxs[i].fsz); + offset = 17 + ascii * fxs[i].fsz; + if(FontxDebug)printf("[GetFontx]offset=%d\n",offset); + if(fseek(fxs[i].file, offset, SEEK_SET)) { + printf("Fontx:seek(%u) failed.\n",offset); + return false; + } + if(fread(pGlyph, 1, fxs[i].fsz, fxs[i].file) != fxs[i].fsz) { + printf("Fontx:fread failed.\n"); + return false; + } + if(pw) *pw = fxs[i].w; + if(ph) *ph = fxs[i].h; + return true; + } + //} + } + return false; +} + + +/* + フォントパターンをビットマップイメージに変換する + + fonts(16X16ドット) + 00000000 01111111 + 12345678 90123456 + 01 pGlyph[000] pGlyph[001] + 02 pGlyph[002] pGlyph[003] + 03 pGlyph[004] pGlyph[005] + 04 pGlyph[006] pGlyph[007] + 05 pGlyph[008] pGlyph[009] + 06 pGlyph[010] pGlyph[011] + 07 pGlyph[012] pGlyph[013] + 08 pGlyph[014] pGlyph[015] + 09 pGlyph[016] pGlyph[017] + 10 pGlyph[018] pGlyph[019] + 11 pGlyph[020] pGlyph[021] + 12 pGlyph[022] pGlyph[023] + 13 pGlyph[024] pGlyph[025] + 14 pGlyph[026] pGlyph[027] + 15 pGlyph[028] pGlyph[029] + 16 pGlyph[030] pGlyph[031] + + line[32*4] + 01 line[000] line[001] line[002] .... line[014] line[015] line[016-031](Not use) + | + 07 line[000] line[001] line[002] .... line[014] line[015] line[016-031](Not use) + + 08 line[032] line[033] line[034] .... line[046] line[047] line[048-063](Not use) + | + 16 line[032] line[033] line[034] .... line[046] line[047] line[048-063](Not use) + + + + fonts(24X24ドット) + 00000000 01111111 11122222 + 12345678 90123456 78901234 + 01 pGlyph[000] pGlyph[001] pGlyph[002] + 02 pGlyph[003] pGlyph[004] pGlyph[005] + 03 pGlyph[006] pGlyph[007] pGlyph[008] + 04 pGlyph[009] pGlyph[010] pGlyph[011] + 05 pGlyph[012] pGlyph[013] pGlyph[014] + 06 pGlyph[015] pGlyph[016] pGlyph[017] + 07 pGlyph[018] pGlyph[019] pGlyph[020] + 08 pGlyph[021] pGlyph[022] pGlyph[023] + 09 pGlyph[024] pGlyph[025] pGlyph[026] + 10 pGlyph[027] pGlyph[028] pGlyph[029] + 11 pGlyph[030] pGlyph[031] pGlyph[032] + 12 pGlyph[033] pGlyph[034] pGlyph[035] + 13 pGlyph[036] pGlyph[037] pGlyph[038] + 14 pGlyph[039] pGlyph[040] pGlyph[041] + 15 pGlyph[042] pGlyph[043] pGlyph[044] + 16 pGlyph[045] pGlyph[046] pGlyph[047] + 17 pGlyph[048] pGlyph[049] pGlyph[050] + 18 pGlyph[051] pGlyph[052] pGlyph[053] + 19 pGlyph[054] pGlyph[055] pGlyph[056] + 20 pGlyph[057] pGlyph[058] pGlyph[059] + 21 pGlyph[060] pGlyph[061] pGlyph[062] + 22 pGlyph[063] pGlyph[064] pGlyph[065] + 23 pGlyph[066] pGlyph[067] pGlyph[068] + 24 pGlyph[069] pGlyph[070] pGlyph[071] + + line[32*4] + 01 line[000] line[001] line[002] .... line[022] line[023] line[024-031](Not use) + | + 08 line[000] line[001] line[002] .... line[022] line[023] line[024-031](Not use) + + 09 line[032] line[033] line[034] .... line[054] line[055] line[056-063](Not use) + | + 16 line[032] line[033] line[034] .... line[054] line[055] line[056-063](Not use) + + 17 line[064] line[065] line[066] .... line[086] line[087] line[088-095](Not use) + | + 24 line[064] line[065] line[066] .... line[086] line[087] line[088-095](Not use) + + + fonts(32X32ドット) + 00000000 01111111 11122222 22222333 + 12345678 90123456 78901234 56789012 + 01 pGlyph[000] pGlyph[001] pGlyph[002] pGlyph[003] + 02 pGlyph[004] pGlyph[005] pGlyph[006] pGlyph[007] + 03 pGlyph[008] pGlyph[009] pGlyph[010] pGlyph[011] + 04 pGlyph[012] pGlyph[013] pGlyph[014] pGlyph[015] + 05 pGlyph[016] pGlyph[017] pGlyph[018] pGlyph[019] + 06 pGlyph[020] pGlyph[021] pGlyph[022] pGlyph[023] + 07 pGlyph[024] pGlyph[025] pGlyph[026] pGlyph[027] + 08 pGlyph[028] pGlyph[029] pGlyph[030] pGlyph[031] + 09 pGlyph[032] pGlyph[033] pGlyph[034] pGlyph[035] + 10 pGlyph[036] pGlyph[037] pGlyph[038] pGlyph[039] + 11 pGlyph[040] pGlyph[041] pGlyph[042] pGlyph[043] + 12 pGlyph[044] pGlyph[045] pGlyph[046] pGlyph[047] + 13 pGlyph[048] pGlyph[049] pGlyph[050] pGlyph[051] + 14 pGlyph[052] pGlyph[053] pGlyph[054] pGlyph[055] + 15 pGlyph[056] pGlyph[057] pGlyph[058] pGlyph[059] + 16 pGlyph[060] pGlyph[061] pGlyph[062] pGlyph[063] + 17 pGlyph[064] pGlyph[065] pGlyph[066] pGlyph[067] + 18 pGlyph[068] pGlyph[069] pGlyph[070] pGlyph[071] + 19 pGlyph[072] pGlyph[073] pGlyph[074] pGlyph[075] + 20 pGlyph[076] pGlyph[077] pGlyph[078] pGlyph[079] + 21 pGlyph[080] pGlyph[081] pGlyph[082] pGlyph[083] + 22 pGlyph[084] pGlyph[085] pGlyph[086] pGlyph[087] + 23 pGlyph[088] pGlyph[089] pGlyph[090] pGlyph[091] + 24 pGlyph[092] pGlyph[093] pGlyph[094] pGlyph[095] + 25 pGlyph[096] pGlyph[097] pGlyph[098] pGlyph[099] + 26 pGlyph[100] pGlyph[101] pGlyph[102] pGlyph[103] + 27 pGlyph[104] pGlyph[105] pGlyph[106] pGlyph[107] + 28 pGlyph[108] pGlyph[109] pGlyph[110] pGlyph[111] + 29 pGlyph[112] pGlyph[113] pGlyph[114] pGlyph[115] + 30 pGlyph[116] pGlyph[117] pGlyph[118] pGlyph[119] + 31 pGlyph[120] pGlyph[121] pGlyph[122] pGlyph[123] + 32 pGlyph[124] pGlyph[125] pGlyph[127] pGlyph[128] + + line[32*4] + 01 line[000] line[001] line[002] .... line[030] line[031] + | + 08 line[000] line[001] line[002] .... line[030] line[031] + + 09 line[032] line[033] line[034] .... line[062] line[063] + | + 16 line[032] line[033] line[034] .... line[062] line[063] + + 17 line[064] line[065] line[066] .... line[094] line[095] + | + 24 line[064] line[065] line[066] .... line[094] line[095] + + 25 line[096] line[097] line[098] .... line[126] line[127] + | + 32 line[096] line[097] line[098] .... line[126] line[127] + +*/ +void Font2Bitmap(uint8_t *fonts, uint8_t *line, uint8_t w, uint8_t h, uint8_t inverse) { + int x,y; + for(y=0; y<(h/8); y++){ + for(x=0; x> (x % 8))) line[linep] = line[linep] + (1 << mask); + } + mask--; + if (mask < 0) mask = 7; + fontp += (w + 7)/8; + } + + if (inverse) { + for(y=0; y<(h/8); y++){ + for(x=0; x> (x % 8))) { + printf("*"); + } else { + printf("."); + } + } + printf("\n"); + fpos=fpos+(pw+7)/8; + } + printf("\n"); +} + +// Bitmapの表示 +void ShowBitmap(uint8_t *bitmap, uint8_t pw, uint8_t ph) { + int x,y,fpos; + printf("[ShowBitmap pw=%d ph=%d]\n",pw,ph); +#if 0 + for (y=0;y<(ph+7)/8;y++) { + for (x=0;x> fpos); + if (bitmap[x+(y/8)*32] & (0x80 >> fpos)) { + printf("*"); + } else { + printf("."); + } + } + printf("\n"); + fpos++; + if (fpos > 7) fpos = 0; + } + printf("\n"); +} + + +// 8ビットデータを反転 +uint8_t RotateByte(uint8_t ch1) { + uint8_t ch2 = 0; + int j; + for (j=0;j<8;j++) { + ch2 = (ch2 << 1) + (ch1 & 0x01); + ch1 = ch1 >> 1; + } + return ch2; +} + + +#if 0 +// UTF code(3Byte) を SJIS Code(2 Byte) に変換 +// https://www.mgo-tec.com/blog-entry-utf8sjis01.html +uint16_t UTF2SJIS(spiffs_file fd, uint8_t *utf8) { + + uint32_t offset = 0; + uint32_t ret; + uint32_t UTF8uint = utf8[0]*256*256 + utf8[1]*256 + utf8[2]; + + if(utf8[0]>=0xC2 && utf8[0]<=0xD1){ //0xB0からS_JISコード実データ。0x00-0xAFまではライセンス文ヘッダなのでそれをカット。 + offset = ((utf8[0]*256 + utf8[1])-0xC2A2)*2 + 0xB0; //文字"¢" UTF8コード C2A2~、S_jisコード8191 + }else if(utf8[0]==0xE2 && utf8[1]>=0x80){ + offset = (UTF8uint-0xE28090)*2 + 0x1EEC; //文字"‐" UTF8コード E28090~、S_jisコード815D + }else if(utf8[0]==0xE3 && utf8[1]>=0x80){ + offset = (UTF8uint-0xE38080)*2 + 0x9DCC; //スペース UTF8コード E38080~、S_jisコード8140 + }else if(utf8[0]==0xE4 && utf8[1]>=0x80){ + offset = (UTF8uint-0xE4B880)*2 + 0x11CCC; //文字"一" UTF8コード E4B880~、S_jisコード88EA + }else if(utf8[0]==0xE5 && utf8[1]>=0x80){ + offset = (UTF8uint-0xE58085)*2 + 0x12BCC; //文字"倅" UTF8コード E58085~、S_jisコード98E4 + }else if(utf8[0]==0xE6 && utf8[1]>=0x80){ + offset = (UTF8uint-0xE6808E)*2 + 0x1AAC2; //文字"怎" UTF8コード E6808E~、S_jisコード9C83 + }else if(utf8[0]==0xE7 && utf8[1]>=0x80){ + offset = (UTF8uint-0xE78081)*2 + 0x229A6; //文字"瀁" UTF8コード E78081~、S_jisコードE066 + }else if(utf8[0]==0xE8 && utf8[1]>=0x80){ + offset = (UTF8uint-0xE88080)*2 + 0x2A8A4; //文字"耀" UTF8コード E88080~、S_jisコード9773 + }else if(utf8[0]==0xE9 && utf8[1]>=0x80){ + offset = (UTF8uint-0xE98080)*2 + 0x327A4; //文字"退" UTF8コード E98080~、S_jisコード91DE + }else if(utf8[0]>=0xEF && utf8[1]>=0xBC){ + offset = (UTF8uint-0xEFBC81)*2 + 0x3A6A4; //文字"!" UTF8コード EFBC81~、S_jisコード8149 + if(utf8[0]==0xEF && utf8[1]==0xBD && utf8[2]==0x9E){ + offset = 0x3A8DE; // "~" UTF8コード EFBD9E、S_jisコード8160 + } + } + +if(FontxDebug)printf("[UTF2SJIS] offset=%d\n",offset); + char buf[2]; + ret = SPIFFS_lseek(&fs, fd, offset, SPIFFS_SEEK_SET); +if(FontxDebug)printf("[UTF2SJIS] lseek ret=%d\n",ret); + if (ret != offset) { + printf("UTF2SJIS:seek(%u) failed.\n",offset); + return 0; + } + if (SPIFFS_read(&fs, fd, buf, sizeof(buf)) != sizeof(buf)) { + printf("UTF2SJIS:read failed.\n"); + return 0; + } +if(FontxDebug)printf("[UTF2SJIS] sjis=0x%x%x\n",buf[0],buf[1]); + return buf[0]*256+buf[1]; +} + + +// UTFを含む文字列をSJISに変換 +int String2SJIS(spiffs_file fd, unsigned char *str_in, size_t stlen, + uint16_t *sjis, size_t ssize) { + int i; + uint8_t sp; + uint8_t c1 = 0; + uint8_t c2 = 0; + uint8_t utf8[3]; + uint16_t sjis2; + int spos = 0; + + for(i=0;i +#include +#include +#include +#include + +#include "esp_log.h" +//#include "miniz.h" +#include "esp32/rom/miniz.h" +#include "pngle.h" + +#define PNGLE_ERROR(s) (pngle->error = (s), pngle->state = PNGLE_STATE_ERROR, -1) +#define PNGLE_CALLOC(a, b, name) (debug_printf("[pngle] Allocating %zu bytes for %s\n", (size_t)(a) * (size_t)(b), (name)), calloc((size_t)(a), (size_t)(b))) + +#define PNGLE_UNUSED(x) (void)(x) + +// magic +static const uint8_t png_sig[] = { 137, 80, 78, 71, 13, 10, 26, 10 }; +static uint32_t interlace_off_x[8] = { 0, 0, 4, 0, 2, 0, 1, 0 }; +static uint32_t interlace_off_y[8] = { 0, 0, 0, 4, 0, 2, 0, 1 }; +static uint32_t interlace_div_x[8] = { 1, 8, 8, 4, 4, 2, 2, 1 }; +static uint32_t interlace_div_y[8] = { 1, 8, 8, 8, 4, 4, 2, 2 }; + + +static inline uint8_t read_uint8(const uint8_t *p) +{ + return *p; +} + +static inline uint32_t read_uint32(const uint8_t *p) +{ + return (p[0] << 24) + | (p[1] << 16) + | (p[2] << 8) + | (p[3] << 0) + ; +} + +static inline uint32_t U32_CLAMP_ADD(uint32_t a, uint32_t b, uint32_t top) +{ + uint32_t v = a + b; + if (v < a) return top; // uint32 overflow + if (v > top) return top; // clamp + return v; +} + + +void pngle_reset(pngle_t *pngle) +{ + if (!pngle) return ; + + pngle->state = PNGLE_STATE_INITIAL; + pngle->error = "No error"; + + if (pngle->scanline_ringbuf) free(pngle->scanline_ringbuf); + if (pngle->palette) free(pngle->palette); + if (pngle->trans_palette) free(pngle->trans_palette); +#ifndef PNGLE_NO_GAMMA_CORRECTION + if (pngle->gamma_table) free(pngle->gamma_table); +#endif + + pngle->scanline_ringbuf = NULL; + pngle->palette = NULL; + pngle->trans_palette = NULL; +#ifndef PNGLE_NO_GAMMA_CORRECTION + pngle->gamma_table = NULL; +#endif + + pngle->channels = 0; // indicates IHDR hasn't been processed yet + pngle->next_out = NULL; // indicates IDAT hasn't been processed yet + + // clear them just in case... + memset(&pngle->hdr, 0, sizeof(pngle->hdr)); + pngle->n_palettes = 0; + pngle->n_trans_palettes = 0; + + tinfl_init(&pngle->inflator); +} + +pngle_t *pngle_new(uint16_t width, uint16_t height) +{ + pngle_t *pngle = (pngle_t *)PNGLE_CALLOC(1, sizeof(pngle_t), "pngle_t"); + if (!pngle) return NULL; + + pngle_reset(pngle); + + pngle->pixels = NULL; + + //Alocate pixel memory. Each line is an array of IMAGE_W 16-bit pixels; the `*pixels` array itself contains pointers to these lines. + ESP_LOGD(__FUNCTION__, "height=%d sizeof(pixel_png *)=%d", height, sizeof(pixel_png *)); + pngle->pixels = calloc(height, sizeof(pixel_png *)); + if (pngle->pixels == NULL) { + ESP_LOGE(__FUNCTION__, "Error allocating memory for lines"); + //ret = ESP_ERR_NO_MEM; + goto err; + } + ESP_LOGD(__FUNCTION__, "width=%d sizeof(pixel_png)=%d", width, sizeof(pixel_png)); + for (int i = 0; i < height; i++) { + (pngle->pixels)[i] = malloc(width * sizeof(pixel_png)); + if ((pngle->pixels)[i] == NULL) { + ESP_LOGE(__FUNCTION__, "Error allocating memory for line %d", i); + //ret = ESP_ERR_NO_MEM; + goto err; + } + } + + pngle->screenWidth = width; + pngle->screenHeight = height; + return pngle; + + err: + //Something went wrong! Exit cleanly, de-allocating everything we allocated. + if (pngle->pixels != NULL) { + for (int i = 0; i < height; i++) { + free((pngle->pixels)[i]); + } + free(pngle->pixels); + } + return NULL; +} + +void pngle_destroy(pngle_t *pngle, uint16_t width, uint16_t height) +{ + if (pngle) { + if (pngle->pixels != NULL) { + for (int i = 0; i < height; i++) { + free((pngle->pixels)[i]); + } + free(pngle->pixels); + } + pngle_reset(pngle); + free(pngle); + } +} + +const char *pngle_error(pngle_t *pngle) +{ + if (!pngle) return "Uninitialized"; + return pngle->error; +} + +uint32_t pngle_get_width(pngle_t *pngle) +{ + if (!pngle) return 0; + return pngle->hdr.width; +} + +uint32_t pngle_get_height(pngle_t *pngle) +{ + if (!pngle) return 0; + return pngle->hdr.height; +} + +pngle_ihdr_t *pngle_get_ihdr(pngle_t *pngle) +{ + if (!pngle) return NULL; + if (pngle->channels == 0) return NULL; + return &pngle->hdr; +} + + +static int is_trans_color(pngle_t *pngle, uint16_t *value, size_t n) +{ + if (pngle->n_trans_palettes != 1) return 0; // false (none or indexed) + + for (size_t i = 0; i < n; i++) { + if (value[i] != (pngle->trans_palette[i * 2 + 0] * 0x100 + pngle->trans_palette[i * 2 + 1])) return 0; // false + } + return 1; // true +} + +static inline void scanline_ringbuf_push(pngle_t *pngle, uint8_t value) +{ + pngle->scanline_ringbuf[pngle->scanline_ringbuf_cidx] = value; + pngle->scanline_ringbuf_cidx = (pngle->scanline_ringbuf_cidx + 1) % pngle->scanline_ringbuf_size; +} + +static inline uint16_t get_value(pngle_t *pngle, size_t *ridx, int *bitcount, int depth) +{ + uint16_t v; + + switch (depth) { + case 1: + case 2: + case 4: + if (*bitcount >= 8) { + *bitcount = 0; + *ridx = (*ridx + 1) % pngle->scanline_ringbuf_size; + } + *bitcount += depth; + uint8_t mask = ((1UL << depth) - 1); + uint8_t shift = (8 - *bitcount); + return (pngle->scanline_ringbuf[*ridx] >> shift) & mask; + + case 8: + v = pngle->scanline_ringbuf[*ridx]; + *ridx = (*ridx + 1) % pngle->scanline_ringbuf_size; + return v; + + case 16: + v = pngle->scanline_ringbuf[*ridx]; + *ridx = (*ridx + 1) % pngle->scanline_ringbuf_size; + + v = v * 0x100 + pngle->scanline_ringbuf[*ridx]; + *ridx = (*ridx + 1) % pngle->scanline_ringbuf_size; + return v; + } + + return 0; +} + +static int pngle_draw_pixels(pngle_t *pngle, size_t scanline_ringbuf_xidx) +{ + uint16_t v[4]; // MAX_CHANNELS + int bitcount = 0; + uint8_t pixel_depth = (pngle->hdr.color_type & 1) ? 8 : pngle->hdr.depth; + uint16_t maxval = (1UL << pixel_depth) - 1; + + int n_pixels = pngle->hdr.depth == 16 ? 1 : (8 / pngle->hdr.depth); + + for (; n_pixels-- > 0 && pngle->drawing_x < pngle->hdr.width; pngle->drawing_x = U32_CLAMP_ADD(pngle->drawing_x, interlace_div_x[pngle->interlace_pass], pngle->hdr.width)) { + for (uint_fast8_t c = 0; c < pngle->channels; c++) { + v[c] = get_value(pngle, &scanline_ringbuf_xidx, &bitcount, pngle->hdr.depth); + } + + // color type: 0000 0111 + // ^-- indexed color (palette) + // ^--- Color + // ^---- Alpha channel + + if (pngle->hdr.color_type & 2) { + // color + if (pngle->hdr.color_type & 1) { + // indexed color: type 3 + + // lookup palette info + uint16_t pidx = v[0]; + if (pidx >= pngle->n_palettes) return PNGLE_ERROR("Color index is out of range"); + + v[0] = pngle->palette[pidx * 3 + 0]; + v[1] = pngle->palette[pidx * 3 + 1]; + v[2] = pngle->palette[pidx * 3 + 2]; + + // tRNS as an indexed alpha value table (for color type 3) + v[3] = pidx < pngle->n_trans_palettes ? pngle->trans_palette[pidx] : maxval; + } else { + // true color: 2, and 6 + v[3] = (pngle->hdr.color_type & 4) ? v[3] : is_trans_color(pngle, v, 3) ? 0 : maxval; + } + } else { + // alpha, tRNS, or opaque + v[3] = (pngle->hdr.color_type & 4) ? v[1] : is_trans_color(pngle, v, 1) ? 0 : maxval; + + // monochrome + v[1] = v[2] = v[0]; + } + + if (pngle->draw_callback) { + uint8_t rgba[4] = { + (v[0] * 255 + maxval / 2) / maxval, + (v[1] * 255 + maxval / 2) / maxval, + (v[2] * 255 + maxval / 2) / maxval, + (v[3] * 255 + maxval / 2) / maxval + }; + +#ifndef PNGLE_NO_GAMMA_CORRECTION + if (pngle->gamma_table) { + for (int i = 0; i < 3; i++) { + rgba[i] = pngle->gamma_table[v[i]]; + } + } +#endif + + pngle->draw_callback(pngle, pngle->drawing_x, pngle->drawing_y + , MIN(interlace_div_x[pngle->interlace_pass] - interlace_off_x[pngle->interlace_pass], pngle->hdr.width - pngle->drawing_x) + , MIN(interlace_div_y[pngle->interlace_pass] - interlace_off_y[pngle->interlace_pass], pngle->hdr.height - pngle->drawing_y) + , rgba + ); + } + } + + return 0; +} + +static inline int paeth(int a, int b, int c) +{ + int p = a + b - c; + int pa = abs(p - a); + int pb = abs(p - b); + int pc = abs(p - c); + + if (pa <= pb && pa <= pc) return a; + if (pb <= pc) return b; + return c; +} + +static int set_interlace_pass(pngle_t *pngle, uint_fast8_t pass) +{ + pngle->interlace_pass = pass; + + uint_fast8_t bytes_per_pixel = (pngle->channels * pngle->hdr.depth + 7) / 8; // 1 if depth <= 8 + size_t scanline_pixels = (pngle->hdr.width - interlace_off_x[pngle->interlace_pass] + interlace_div_x[pngle->interlace_pass] - 1) / interlace_div_x[pngle->interlace_pass]; + size_t scanline_stride = (scanline_pixels * pngle->channels * pngle->hdr.depth + 7) / 8; + + pngle->scanline_ringbuf_size = scanline_stride + bytes_per_pixel * 2; // 2 rooms for c/x and a + + if (pngle->scanline_ringbuf) free(pngle->scanline_ringbuf); + if ((pngle->scanline_ringbuf = PNGLE_CALLOC(pngle->scanline_ringbuf_size, 1, "scanline ringbuf")) == NULL) return PNGLE_ERROR("Insufficient memory"); + + pngle->drawing_x = interlace_off_x[pngle->interlace_pass]; + pngle->drawing_y = interlace_off_y[pngle->interlace_pass]; + pngle->filter_type = -1; + + pngle->scanline_ringbuf_cidx = 0; + pngle->scanline_remain_bytes_to_render = -1; + + return 0; +} + +static int setup_gamma_table(pngle_t *pngle, uint32_t png_gamma) +{ +#ifndef PNGLE_NO_GAMMA_CORRECTION + if (pngle->gamma_table) free(pngle->gamma_table); + + if (pngle->display_gamma <= 0) return 0; // disable gamma correction + if (png_gamma == 0) return 0; + + uint8_t pixel_depth = (pngle->hdr.color_type & 1) ? 8 : pngle->hdr.depth; + uint16_t maxval = (1UL << pixel_depth) - 1; + + pngle->gamma_table = PNGLE_CALLOC(1, maxval + 1, "gamma table"); + if (!pngle->gamma_table) return PNGLE_ERROR("Insufficient memory"); + + for (int i = 0; i < maxval + 1; i++) { + pngle->gamma_table[i] = (uint8_t)floor(pow(i / (double)maxval, 100000.0 / png_gamma / pngle->display_gamma) * 255.0 + 0.5); + } + debug_printf("[pngle] gamma value = %d\n", png_gamma); +#else + PNGLE_UNUSED(pngle); + PNGLE_UNUSED(png_gamma); +#endif + return 0; +} + + +static int pngle_on_data(pngle_t *pngle, const uint8_t *p, int len) +{ + const uint8_t *ep = p + len; + + uint_fast8_t bytes_per_pixel = (pngle->channels * pngle->hdr.depth + 7) / 8; // 1 if depth <= 8 + + while (p < ep) { + if (pngle->drawing_x >= pngle->hdr.width) { + // New row + pngle->drawing_x = interlace_off_x[pngle->interlace_pass]; + pngle->drawing_y = U32_CLAMP_ADD(pngle->drawing_y, interlace_div_y[pngle->interlace_pass], pngle->hdr.height); + pngle->filter_type = -1; // Indicate new line + } + + if (pngle->drawing_x >= pngle->hdr.width || pngle->drawing_y >= pngle->hdr.height) { + if (pngle->interlace_pass == 0 || pngle->interlace_pass >= 7) return len; // Do nothing further + + // Interlace: Next pass + if (set_interlace_pass(pngle, pngle->interlace_pass + 1) < 0) return -1; + debug_printf("[pngle] interlace pass changed to: %d\n", pngle->interlace_pass); + + continue; // This is required because "No filter type bytes are present in an empty pass". + } + + if (pngle->filter_type < 0) { + if (*p > 4) { + debug_printf("[pngle] Invalid filter type is found; 0x%02x\n", *p); + return PNGLE_ERROR("Invalid filter type is found"); + } + + pngle->filter_type = (int_fast8_t)*p++; // 0 - 4 + + // push sentinel bytes for new line + for (uint_fast8_t i = 0; i < bytes_per_pixel; i++) { + scanline_ringbuf_push(pngle, 0); + } + + continue; + } + + size_t cidx = pngle->scanline_ringbuf_cidx; + size_t bidx = (pngle->scanline_ringbuf_cidx + bytes_per_pixel) % pngle->scanline_ringbuf_size; + size_t aidx = (pngle->scanline_ringbuf_cidx + pngle->scanline_ringbuf_size - bytes_per_pixel) % pngle->scanline_ringbuf_size; + // debug_printf("[pngle] cidx = %zd, bidx = %zd, aidx = %zd\n", cidx, bidx, aidx); + + uint8_t c = pngle->scanline_ringbuf[cidx]; // left-up + uint8_t b = pngle->scanline_ringbuf[bidx]; // up + uint8_t a = pngle->scanline_ringbuf[aidx]; // left + uint8_t x = *p++; // target + // debug_printf("[pngle] c = 0x%02x, b = 0x%02x, a = 0x%02x, x = 0x%02x\n", c, b, a, x); + + // Reverse the filter + switch (pngle->filter_type) { + case 0: break; // None + case 1: x += a; break; // Sub + case 2: x += b; break; // Up + case 3: x += (a + b) / 2; break; // Average + case 4: x += paeth(a, b, c); break; // Paeth + } + + scanline_ringbuf_push(pngle, x); // updates scanline_ringbuf_cidx + + if (pngle->scanline_remain_bytes_to_render < 0) pngle->scanline_remain_bytes_to_render = bytes_per_pixel; + if (--pngle->scanline_remain_bytes_to_render == 0) { + size_t xidx = (pngle->scanline_ringbuf_cidx + pngle->scanline_ringbuf_size - bytes_per_pixel) % pngle->scanline_ringbuf_size; + + if (pngle_draw_pixels(pngle, xidx) < 0) return -1; + + pngle->scanline_remain_bytes_to_render = -1; // reset + } + } + + return len; +} + + +static int pngle_handle_chunk(pngle_t *pngle, const uint8_t *buf, size_t len) +{ + size_t consume = 0; + + switch (pngle->chunk_type) { + case PNGLE_CHUNK_IHDR: + // parse IHDR + consume = 13; + if (len < consume) return 0; + + debug_printf("[pngle] Parse IHDR\n"); + + pngle->hdr.width = read_uint32(buf + 0); + pngle->hdr.height = read_uint32(buf + 4); + pngle->hdr.depth = read_uint8 (buf + 8); + pngle->hdr.color_type = read_uint8 (buf + 9); + pngle->hdr.compression = read_uint8 (buf + 10); + pngle->hdr.filter = read_uint8 (buf + 11); + pngle->hdr.interlace = read_uint8 (buf + 12); + + + debug_printf("[pngle] width : %d\n", pngle->hdr.width ); + debug_printf("[pngle] height : %d\n", pngle->hdr.height ); + debug_printf("[pngle] depth : %d\n", pngle->hdr.depth ); + debug_printf("[pngle] color_type : %d\n", pngle->hdr.color_type ); + debug_printf("[pngle] compression: %d\n", pngle->hdr.compression); + debug_printf("[pngle] filter : %d\n", pngle->hdr.filter ); + debug_printf("[pngle] interlace : %d\n", pngle->hdr.interlace ); + + /* + Color Allowed Interpretation channels + Type Bit Depths + + 0 1,2,4,8,16 Each pixel is a grayscale sample. 1 channels (Brightness) + + 2 8,16 Each pixel is an R,G,B triple. 3 channels (R, G, B) + + 3 1,2,4,8 Each pixel is a palette index; 1 channels (palette info) + a PLTE chunk must appear. + + 4 8,16 Each pixel is a grayscale sample, 2 channels (Brightness, Alpha) + followed by an alpha sample. + + 6 8,16 Each pixel is an R,G,B triple, 4 channels (R, G, B, Alpha) + followed by an alpha sample. + */ + // 111 + // ^-- indexed color (palette) + // ^--- Color + // ^---- Alpha channel + + switch (pngle->hdr.color_type) { + case 0: pngle->channels = 1; if (pngle->hdr.depth != 1 && pngle->hdr.depth != 2 && pngle->hdr.depth != 4 && pngle->hdr.depth != 8 && pngle->hdr.depth != 16) return PNGLE_ERROR("Invalid bit depth"); break; // grayscale + case 2: pngle->channels = 3; if ( pngle->hdr.depth != 8 && pngle->hdr.depth != 16) return PNGLE_ERROR("Invalid bit depth"); break; // truecolor + case 3: pngle->channels = 1; if (pngle->hdr.depth != 1 && pngle->hdr.depth != 2 && pngle->hdr.depth != 4 && pngle->hdr.depth != 8 ) return PNGLE_ERROR("Invalid bit depth"); break; // indexed color + case 4: pngle->channels = 2; if ( pngle->hdr.depth != 8 && pngle->hdr.depth != 16) return PNGLE_ERROR("Invalid bit depth"); break; // grayscale + alpha + case 6: pngle->channels = 4; if ( pngle->hdr.depth != 8 && pngle->hdr.depth != 16) return PNGLE_ERROR("Invalid bit depth"); break; // truecolor + alpha + default: + return PNGLE_ERROR("Incorrect IHDR info"); + } + + if (pngle->hdr.compression != 0) return PNGLE_ERROR("Unsupported compression type in IHDR"); + if (pngle->hdr.filter != 0) return PNGLE_ERROR("Unsupported filter type in IHDR"); + + // interlace + if (set_interlace_pass(pngle, pngle->hdr.interlace ? 1 : 0) < 0) return -1; + + // callback + if (pngle->init_callback) pngle->init_callback(pngle, pngle->hdr.width, pngle->hdr.height); + + break; + + case PNGLE_CHUNK_IDAT: + // parse & decode IDAT chunk + if (len < 1) return 0; + + debug_printf("[pngle] Reading IDAT (len %zd / chunk remain %u)\n", len, pngle->chunk_remain); + + size_t in_bytes = len; + size_t out_bytes = pngle->avail_out; + + //debug_printf("[pngle] in_bytes %zd, out_bytes %zd, next_out %p\n", in_bytes, out_bytes, pngle->next_out); + + // XXX: tinfl_decompress always requires (next_out - lz_buf + avail_out) == TINFL_LZ_DICT_SIZE + tinfl_status status = tinfl_decompress(&pngle->inflator, (const mz_uint8 *)buf, &in_bytes, pngle->lz_buf, (mz_uint8 *)pngle->next_out, &out_bytes, TINFL_FLAG_HAS_MORE_INPUT | TINFL_FLAG_PARSE_ZLIB_HEADER); + + //debug_printf("[pngle] tinfl_decompress\n"); + //debug_printf("[pngle] => in_bytes %zd, out_bytes %zd, next_out %p, status %d\n", in_bytes, out_bytes, pngle->next_out, status); + + if (status < TINFL_STATUS_DONE) { + // Decompression failed. + debug_printf("[pngle] tinfl_decompress() failed with status %d!\n", status); + return PNGLE_ERROR("Failed to decompress the IDAT stream"); + } + + pngle->next_out += out_bytes; + pngle->avail_out -= out_bytes; + + // debug_printf("[pngle] => avail_out %zd, next_out %p\n", pngle->avail_out, pngle->next_out); + + if (status == TINFL_STATUS_DONE || pngle->avail_out == 0) { + // Output buffer is full, or decompression is done, so write buffer to output file. + // XXX: This is the only chance to process the buffer. + uint8_t *read_ptr = pngle->lz_buf; + size_t n = TINFL_LZ_DICT_SIZE - (size_t)pngle->avail_out; + + // pngle_on_data() usually returns n, otherwise -1 on error + if (pngle_on_data(pngle, read_ptr, n) < 0) return -1; + + // XXX: tinfl_decompress always requires (next_out - lz_buf + avail_out) == TINFL_LZ_DICT_SIZE + pngle->next_out = pngle->lz_buf; + pngle->avail_out = TINFL_LZ_DICT_SIZE; + } + + consume = in_bytes; + break; + + case PNGLE_CHUNK_PLTE: + consume = 3; + if (len < consume) return 0; + + memcpy(pngle->palette + pngle->n_palettes * 3, buf, 3); + + debug_printf("[pngle] PLTE[%zd]: (%d, %d, %d)\n" + , pngle->n_palettes + , pngle->palette[pngle->n_palettes * 3 + 0] + , pngle->palette[pngle->n_palettes * 3 + 1] + , pngle->palette[pngle->n_palettes * 3 + 2] + ); + + pngle->n_palettes++; + + break; + + case PNGLE_CHUNK_IEND: + consume = 0; + break; + + case PNGLE_CHUNK_tRNS: + switch (pngle->hdr.color_type) { + case 3: consume = 1; break; + case 0: consume = 2 * 1; break; + case 2: consume = 2 * 3; break; + default: + return PNGLE_ERROR("tRNS chunk is prohibited on the color type"); + } + if (len < consume) return 0; + + memcpy(pngle->trans_palette + pngle->n_trans_palettes, buf, consume); + + pngle->n_trans_palettes++; + + break; + + case PNGLE_CHUNK_gAMA: + consume = 4; + if (len < consume) return 0; + + if (setup_gamma_table(pngle, read_uint32(buf)) < 0) return -1; + + break; + + default: + // unknown chunk + consume = len; + + debug_printf("[pngle] Unknown chunk; %zd bytes discarded\n", consume); + break; + } + + return consume; +} + +static int pngle_feed_internal(pngle_t *pngle, const uint8_t *buf, size_t len) +{ + if (!pngle) return -1; + + switch (pngle->state) { + case PNGLE_STATE_ERROR: + return -1; + + case PNGLE_STATE_EOF: + return len; + + case PNGLE_STATE_INITIAL: + // find PNG header + if (len < sizeof(png_sig)) return 0; + + if (memcmp(png_sig, buf, sizeof(png_sig))) return PNGLE_ERROR("Incorrect PNG signature"); + + debug_printf("[pngle] PNG signature found\n"); + + pngle->state = PNGLE_STATE_FIND_CHUNK_HEADER; + return sizeof(png_sig); + + case PNGLE_STATE_FIND_CHUNK_HEADER: + if (len < 8) return 0; + + pngle->chunk_remain = read_uint32(buf); + pngle->chunk_type = read_uint32(buf + 4); + + pngle->crc32 = mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)(buf + 4), 4); + + debug_printf("[pngle] Chunk '%.4s' len %u\n", buf + 4, pngle->chunk_remain); + + pngle->state = PNGLE_STATE_HANDLE_CHUNK; + + // initialize & sanity check + switch (pngle->chunk_type) { + case PNGLE_CHUNK_IHDR: + if (pngle->chunk_remain != 13) return PNGLE_ERROR("Invalid IHDR chunk size"); + if (pngle->channels != 0) return PNGLE_ERROR("Multiple IHDR chunks are not allowed"); + break; + + case PNGLE_CHUNK_IDAT: + if (pngle->chunk_remain <= 0) return PNGLE_ERROR("Invalid IDAT chunk size"); + if (pngle->channels == 0) return PNGLE_ERROR("No IHDR chunk is found"); + if (pngle->hdr.color_type == 3 && pngle->palette == NULL) return PNGLE_ERROR("No PLTE chunk is found"); + + if (pngle->next_out == NULL) { + // Very first IDAT + pngle->next_out = pngle->lz_buf; + pngle->avail_out = TINFL_LZ_DICT_SIZE; + } + break; + + case PNGLE_CHUNK_PLTE: + if (pngle->chunk_remain <= 0) return PNGLE_ERROR("Invalid PLTE chunk size"); + if (pngle->channels == 0) return PNGLE_ERROR("No IHDR chunk is found"); + if (pngle->palette) return PNGLE_ERROR("Too many PLTE chunk"); + + switch (pngle->hdr.color_type) { + case 3: // indexed color + break; + case 2: // truecolor + case 6: // truecolor + alpha + // suggested palettes + break; + default: + return PNGLE_ERROR("PLTE chunk is prohibited on the color type"); + } + + if (pngle->chunk_remain % 3) return PNGLE_ERROR("Invalid PLTE chunk size"); + if (pngle->chunk_remain / 3 > MIN(256, (1UL << pngle->hdr.depth))) return PNGLE_ERROR("Too many palettes in PLTE"); + if ((pngle->palette = PNGLE_CALLOC(pngle->chunk_remain / 3, 3, "palette")) == NULL) return PNGLE_ERROR("Insufficient memory"); + pngle->n_palettes = 0; + break; + + case PNGLE_CHUNK_IEND: + if (pngle->next_out == NULL) return PNGLE_ERROR("No IDAT chunk is found"); + if (pngle->chunk_remain > 0) return PNGLE_ERROR("Invalid IEND chunk size"); + break; + + case PNGLE_CHUNK_tRNS: + if (pngle->chunk_remain <= 0) return PNGLE_ERROR("Invalid tRNS chunk size"); + if (pngle->channels == 0) return PNGLE_ERROR("No IHDR chunk is found"); + if (pngle->trans_palette) return PNGLE_ERROR("Too many tRNS chunk"); + + switch (pngle->hdr.color_type) { + case 3: // indexed color + if (pngle->chunk_remain > (1UL << pngle->hdr.depth)) return PNGLE_ERROR("Too many palettes in tRNS"); + break; + case 0: // grayscale + if (pngle->chunk_remain != 2) return PNGLE_ERROR("Invalid tRNS chunk size"); + break; + case 2: // truecolor + if (pngle->chunk_remain != 6) return PNGLE_ERROR("Invalid tRNS chunk size"); + break; + + default: + return PNGLE_ERROR("tRNS chunk is prohibited on the color type"); + } + if ((pngle->trans_palette = PNGLE_CALLOC(pngle->chunk_remain, 1, "trans palette")) == NULL) return PNGLE_ERROR("Insufficient memory"); + pngle->n_trans_palettes = 0; + break; + + default: + break; + } + + return 8; + + case PNGLE_STATE_HANDLE_CHUNK: + len = MIN(len, pngle->chunk_remain); + + int consumed = pngle_handle_chunk(pngle, buf, len); + + if (consumed > 0) { + if (pngle->chunk_remain < (uint32_t)consumed) return PNGLE_ERROR("Chunk data has been consumed too much"); + + pngle->chunk_remain -= consumed; + pngle->crc32 = mz_crc32(pngle->crc32, (const mz_uint8 *)buf, consumed); + } + if (pngle->chunk_remain <= 0) pngle->state = PNGLE_STATE_CRC; + + return consumed; + + case PNGLE_STATE_CRC: + if (len < 4) return 0; + + uint32_t crc32 = read_uint32(buf); + + if (crc32 != pngle->crc32) { + debug_printf("[pngle] CRC: %08x vs %08x => NG\n", crc32, (uint32_t)pngle->crc32); + return PNGLE_ERROR("CRC mismatch"); + } + + debug_printf("[pngle] CRC: %08x vs %08x => OK\n", crc32, (uint32_t)pngle->crc32); + pngle->state = PNGLE_STATE_FIND_CHUNK_HEADER; + + // XXX: + if (pngle->chunk_type == PNGLE_CHUNK_IEND) { + pngle->state = PNGLE_STATE_EOF; + if (pngle->done_callback) pngle->done_callback(pngle); + debug_printf("[pngle] DONE\n"); + } + + return 4; + + default: + break; + } + + return PNGLE_ERROR("Invalid state"); +} + +int pngle_feed(pngle_t *pngle, const void *buf, size_t len) +{ + size_t pos = 0; + pngle_state_t last_state = pngle->state; + + while (pos < len) { + int r = pngle_feed_internal(pngle, (const uint8_t *)buf + pos, len - pos); + if (r < 0) return r; // error + + if (r == 0 && last_state == pngle->state) break; + last_state = pngle->state; + + pos += r; + } + + return pos; +} + +void pngle_set_display_gamma(pngle_t *pngle, double display_gamma) +{ + if (!pngle) return ; +#ifndef PNGLE_NO_GAMMA_CORRECTION + pngle->display_gamma = display_gamma; +#else + PNGLE_UNUSED(display_gamma); +#endif +} + +void pngle_set_init_callback(pngle_t *pngle, pngle_init_callback_t callback) +{ + if (!pngle) return ; + pngle->init_callback = callback; +} + +void pngle_set_draw_callback(pngle_t *pngle, pngle_draw_callback_t callback) +{ + if (!pngle) return ; + pngle->draw_callback = callback; +} + +void pngle_set_done_callback(pngle_t *pngle, pngle_done_callback_t callback) +{ + if (!pngle) return ; + pngle->done_callback = callback; +} + +void pngle_set_user_data(pngle_t *pngle, void *user_data) +{ + if (!pngle) return ; + pngle->user_data = user_data; +} + +void *pngle_get_user_data(pngle_t *pngle) +{ + if (!pngle) return NULL; + return pngle->user_data; +} + +/* vim: set ts=4 sw=4 noexpandtab: */ diff --git a/main/drivers/st7789/pngle.h b/main/drivers/st7789/pngle.h new file mode 100644 index 0000000..6bbd776 --- /dev/null +++ b/main/drivers/st7789/pngle.h @@ -0,0 +1,189 @@ +/*- + * MIT License + * + * Copyright (c) 2019 kikuchan + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __PNGLE_H__ +#define __PNGLE_H__ + +#include +#include +#include "esp32/rom/miniz.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef MIN +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#endif + +#ifdef PNGLE_DEBUG +#define debug_printf(...) fprintf(stderr, __VA_ARGS__) +#else +#define debug_printf(...) ((void)0) +#endif + +//#define PNGLE_NO_GAMMA_CORRECTION + +#if 0 +typedef struct __attribute__((__packed__)) { + uint8_t red; + uint8_t green; + uint8_t blue; +} pixel_png; +#endif + +//rgb565 format +typedef uint16_t pixel_png; + +typedef enum { + PNGLE_STATE_ERROR = -2, + PNGLE_STATE_EOF = -1, + PNGLE_STATE_INITIAL = 0, + + PNGLE_STATE_FIND_CHUNK_HEADER, + PNGLE_STATE_HANDLE_CHUNK, + PNGLE_STATE_CRC, +} pngle_state_t; + + +typedef enum { +// Supported chunks +// Filter chunk names by following command to (re)generate hex constants; +// % perl -ne 'chomp; s/.*\s*\/\/\s*//; print "\tPNGLE_CHUNK_$_ = 0x" . unpack("H*") . "UL, // $_\n";' + PNGLE_CHUNK_IHDR = 0x49484452UL, // IHDR + PNGLE_CHUNK_PLTE = 0x504c5445UL, // PLTE + PNGLE_CHUNK_IDAT = 0x49444154UL, // IDAT + PNGLE_CHUNK_IEND = 0x49454e44UL, // IEND + PNGLE_CHUNK_tRNS = 0x74524e53UL, // tRNS + PNGLE_CHUNK_gAMA = 0x67414d41UL, // gAMA +} pngle_chunk_t; + +typedef struct _pngle_ihdr_t { + uint32_t width; + uint32_t height; + uint8_t depth; + uint8_t color_type; + uint8_t compression; + uint8_t filter; + uint8_t interlace; +} pngle_ihdr_t; + +typedef unsigned int UINT; + +typedef struct pngle pngle_t; + +typedef void (*pngle_init_callback_t)(pngle_t *pngle, uint32_t w, uint32_t h); +typedef void (*pngle_draw_callback_t)(pngle_t *pngle, uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint8_t rgba[4]); +typedef void (*pngle_done_callback_t)(pngle_t *pngle); + +struct pngle { + pngle_ihdr_t hdr; + + uint_fast8_t channels; // 0 indicates IHDR hasn't been processed yet + + // PLTE chunk + size_t n_palettes; + uint8_t *palette; + + // tRNS chunk + size_t n_trans_palettes; + uint8_t *trans_palette; + + // parser state (reset on every chunk header) + pngle_state_t state; + uint32_t chunk_type; + uint32_t chunk_remain; + mz_ulong crc32; + + // decompression state (reset on IHDR) + tinfl_decompressor inflator; // 11000 bytes + uint8_t lz_buf[TINFL_LZ_DICT_SIZE]; // 32768 bytes + uint8_t *next_out; // NULL indicates IDAT hasn't been processed yet + size_t avail_out; + + // scanline decoder (reset on every set_interlace_pass() call) + uint8_t *scanline_ringbuf; + size_t scanline_ringbuf_size; + size_t scanline_ringbuf_cidx; + int_fast8_t scanline_remain_bytes_to_render; + int_fast8_t filter_type; + uint32_t drawing_x; + uint32_t drawing_y; + + // interlace + uint_fast8_t interlace_pass; + + const char *error; + +#ifndef PNGLE_NO_GAMMA_CORRECTION + uint8_t *gamma_table; + double display_gamma; +#endif + + pngle_init_callback_t init_callback; + pngle_draw_callback_t draw_callback; + pngle_done_callback_t done_callback; + + void *user_data; + uint16_t screenWidth; + uint16_t screenHeight; + uint16_t imageWidth; + uint16_t imageHeight; + pixel_png **pixels; + bool reduction; + double scale_factor; +}; + + +// ---------------- +// Basic interfaces +// ---------------- +pngle_t *pngle_new(uint16_t width, uint16_t height); +void pngle_destroy(pngle_t *pngle, uint16_t width, uint16_t height); +void pngle_reset(pngle_t *pngle); // clear its internal state (not applied to pngle_set_* functions) +const char *pngle_error(pngle_t *pngle); +int pngle_feed(pngle_t *pngle, const void *buf, size_t len); // returns -1: On error, 0: Need more data, n: n bytes eaten + +uint32_t pngle_get_width(pngle_t *pngle); +uint32_t pngle_get_height(pngle_t *pngle); + +void pngle_set_init_callback(pngle_t *png, pngle_init_callback_t callback); +void pngle_set_draw_callback(pngle_t *png, pngle_draw_callback_t callback); +void pngle_set_done_callback(pngle_t *png, pngle_done_callback_t callback); + +void pngle_set_display_gamma(pngle_t *pngle, double display_gamma); // enables gamma correction by specifying display gamma, typically 2.2. No effect when gAMA chunk is missing + +void pngle_set_user_data(pngle_t *pngle, void *user_data); +void *pngle_get_user_data(pngle_t *pngle); + + +// Get IHDR information +pngle_ihdr_t *pngle_get_ihdr(pngle_t *pngle); + + +#ifdef __cplusplus +} +#endif + +#endif /* __PNGLE_H__ */ diff --git a/main/drivers/st7789/st7789.c b/main/drivers/st7789/st7789.c new file mode 100644 index 0000000..c5cad27 --- /dev/null +++ b/main/drivers/st7789/st7789.c @@ -0,0 +1,1111 @@ +#include +#include + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +#include +#include +#include "esp_log.h" + +#include "st7789.h" + +#define TAG "ST7789" +#define _DEBUG_ 0 + +#if 0 +#ifdef CONFIG_IDF_TARGET_ESP32 +#define LCD_HOST HSPI_HOST +#elif defined CONFIG_IDF_TARGET_ESP32S2 +#define LCD_HOST SPI2_HOST +#elif defined CONFIG_IDF_TARGET_ESP32S3 +#define LCD_HOST SPI2_HOST +#elif defined CONFIG_IDF_TARGET_ESP32C3 +#define LCD_HOST SPI2_HOST +#endif +#endif + +#if CONFIG_SPI2_HOST +#define HOST_ID SPI2_HOST +#elif CONFIG_SPI3_HOST +#define HOST_ID SPI3_HOST +#endif + +static const int SPI_Command_Mode = 0; +static const int SPI_Data_Mode = 1; +// static const int SPI_Frequency = SPI_MASTER_FREQ_8M; +//static const int SPI_Frequency = SPI_MASTER_FREQ_26M; +// static const int SPI_Frequency = SPI_MASTER_FREQ_40M; +static const int SPI_Frequency = SPI_MASTER_FREQ_80M; + + +void spi_master_init(TFT_t * dev, int16_t GPIO_MOSI, int16_t GPIO_SCLK, int16_t GPIO_CS, int16_t GPIO_DC, int16_t GPIO_RESET, int16_t GPIO_BL) +{ + esp_err_t ret; + gpio_config_t io_conf = {}; + + ESP_LOGI(TAG, "GPIO_CS=%d",GPIO_CS); + if ( GPIO_CS >= 0 ) { + //gpio_pad_select_gpio( GPIO_CS ); + // gpio_reset_pin( GPIO_CS ); + // gpio_set_direction( GPIO_CS, GPIO_MODE_OUTPUT ); + // gpio_set_level( GPIO_CS, 0 ); + + //disable interrupt + io_conf.intr_type = GPIO_INTR_DISABLE; + //set as output mode + io_conf.mode = GPIO_MODE_OUTPUT; + //bit mask of the pins that you want to set,e.g.GPIO18/19 + io_conf.pin_bit_mask = (1ULL<= 0 ) { + //gpio_pad_select_gpio( GPIO_RESET ); + gpio_reset_pin( GPIO_RESET ); + gpio_set_direction( GPIO_RESET, GPIO_MODE_OUTPUT ); + gpio_set_level( GPIO_RESET, 1 ); + delayMS(50); + gpio_set_level( GPIO_RESET, 0 ); + delayMS(50); + gpio_set_level( GPIO_RESET, 1 ); + delayMS(50); + } + + ESP_LOGI(TAG, "GPIO_BL=%d",GPIO_BL); + if ( GPIO_BL >= 0 ) { + //gpio_pad_select_gpio(GPIO_BL); + // gpio_reset_pin(GPIO_BL); + // gpio_set_direction( GPIO_BL, GPIO_MODE_OUTPUT ); + // gpio_set_level( GPIO_BL, 0 ); + //disable interrupt + io_conf.intr_type = GPIO_INTR_DISABLE; + //set as output mode + io_conf.mode = GPIO_MODE_OUTPUT; + //bit mask of the pins that you want to set,e.g.GPIO18/19 + io_conf.pin_bit_mask = (1ULL<= 0 ) { + devcfg.spics_io_num = GPIO_CS; + } else { + devcfg.spics_io_num = -1; + } + + static spi_device_handle_t handle; + ret = spi_bus_add_device( HOST_ID, &devcfg, &handle); + printf("spi_bus_add_device = %d\r\n", ret); + ESP_LOGD(TAG, "spi_bus_add_device=%d",ret); + assert(ret==ESP_OK); + dev->_dc = GPIO_DC; + dev->_bl = GPIO_BL; + dev->_SPIHandle = handle; +} + + +bool spi_master_write_byte(spi_device_handle_t SPIHandle, const uint8_t* Data, size_t DataLength) +{ + spi_transaction_t SPITransaction; + esp_err_t ret; + + if ( DataLength > 0 ) { + memset( &SPITransaction, 0, sizeof( spi_transaction_t ) ); + SPITransaction.length = DataLength * 8; + SPITransaction.tx_buffer = Data; +#if 1 + ret = spi_device_transmit( SPIHandle, &SPITransaction ); +#else + ret = spi_device_polling_transmit( SPIHandle, &SPITransaction ); +#endif + assert(ret==ESP_OK); + } + + return true; +} + +bool spi_master_write_command(TFT_t * dev, uint8_t cmd) +{ + static uint8_t Byte = 0; + Byte = cmd; + gpio_set_level( dev->_dc, SPI_Command_Mode ); + return spi_master_write_byte( dev->_SPIHandle, &Byte, 1 ); +} + +bool spi_master_write_data_byte(TFT_t * dev, uint8_t data) +{ + static uint8_t Byte = 0; + Byte = data; + gpio_set_level( dev->_dc, SPI_Data_Mode ); + return spi_master_write_byte( dev->_SPIHandle, &Byte, 1 ); +} + + +bool spi_master_write_data_word(TFT_t * dev, uint16_t data) +{ + static uint8_t Byte[2]; + Byte[0] = (data >> 8) & 0xFF; + Byte[1] = data & 0xFF; + gpio_set_level( dev->_dc, SPI_Data_Mode ); + return spi_master_write_byte( dev->_SPIHandle, Byte, 2); +} + +bool spi_master_write_addr(TFT_t * dev, uint16_t addr1, uint16_t addr2) +{ + static uint8_t Byte[4]; + Byte[0] = (addr1 >> 8) & 0xFF; + Byte[1] = addr1 & 0xFF; + Byte[2] = (addr2 >> 8) & 0xFF; + Byte[3] = addr2 & 0xFF; + gpio_set_level( dev->_dc, SPI_Data_Mode ); + return spi_master_write_byte( dev->_SPIHandle, Byte, 4); +} + +bool spi_master_write_color(TFT_t * dev, uint16_t color, uint16_t size) +{ + static uint8_t Byte[1024]; + int index = 0; + for(int i=0;i> 8) & 0xFF; + Byte[index++] = color & 0xFF; + } + gpio_set_level( dev->_dc, SPI_Data_Mode ); + return spi_master_write_byte( dev->_SPIHandle, Byte, size*2); +} + +// Add 202001 +bool spi_master_write_colors(TFT_t * dev, uint16_t * colors, uint16_t size) +{ + static uint8_t Byte[1024]; + int index = 0; + for(int i=0;i> 8) & 0xFF; + Byte[index++] = colors[i] & 0xFF; + } + gpio_set_level( dev->_dc, SPI_Data_Mode ); + return spi_master_write_byte( dev->_SPIHandle, Byte, size*2); +} + +void delayMS(int ms) { + int _ms = ms + (portTICK_PERIOD_MS - 1); + TickType_t xTicksToDelay = _ms / portTICK_PERIOD_MS; + ESP_LOGD(TAG, "ms=%d _ms=%d portTICK_PERIOD_MS=%d xTicksToDelay=%d",ms,_ms,portTICK_PERIOD_MS,xTicksToDelay); + vTaskDelay(xTicksToDelay); +} + + +void lcdInit(TFT_t * dev, int width, int height, int offsetx, int offsety) +{ + dev->_width = width; + dev->_height = height; + dev->_offsetx = offsetx; + dev->_offsety = offsety; + dev->_font_direction = DIRECTION0; + dev->_font_fill = false; + dev->_font_underline = false; + +#if 1 + spi_master_write_command(dev, 0x01); //Software Reset + delayMS(150); + + spi_master_write_command(dev, 0x11); //Sleep Out + delayMS(255); + + spi_master_write_command(dev, 0x3A); //Interface Pixel Format + spi_master_write_data_byte(dev, 0x55); + delayMS(10); + + spi_master_write_command(dev, 0x36); //Memory Data Access Control + spi_master_write_data_byte(dev, 0x00); + + // spi_master_write_command(dev, 0x2A); //Column Address Set + // spi_master_write_data_byte(dev, 0x00); + // spi_master_write_data_byte(dev, 0x00); + // spi_master_write_data_byte(dev, 0x00); + // spi_master_write_data_byte(dev, 0xF0); + + // spi_master_write_command(dev, 0x2B); //Row Address Set + // spi_master_write_data_byte(dev, 0x00); + // spi_master_write_data_byte(dev, 0x00); + // spi_master_write_data_byte(dev, 0x00); + // spi_master_write_data_byte(dev, 0xF0); + + spi_master_write_command(dev, 0x2A); //Column Address Set + spi_master_write_data_byte(dev, 0x00); + spi_master_write_data_byte(dev, 0x00); //0 + spi_master_write_data_byte(dev, 0x00); + spi_master_write_data_byte(dev, 0xEF); //239 + + spi_master_write_command(dev, 0x2B); //Row Address Set + spi_master_write_data_byte(dev, 0x00); + spi_master_write_data_byte(dev, 0x14); //0 + spi_master_write_data_byte(dev, 0x01); + spi_master_write_data_byte(dev, 0x2B); + + spi_master_write_command(dev, 0x21); //Display Inversion On + delayMS(10); + + spi_master_write_command(dev, 0x13); //Normal Display Mode On + delayMS(10); + + spi_master_write_command(dev, 0x29); //Display ON + delayMS(255); + + +#else + spi_master_write_command(dev, 0x01); + + delayMS(120); + + spi_master_write_command(dev, 0x11); + + delayMS(120); + + spi_master_write_command(dev, 0x36); + spi_master_write_data_byte(dev, 0x00); + + spi_master_write_command(dev, 0x3A); + spi_master_write_data_byte(dev, 0x06); + + spi_master_write_command(dev, 0xB2); + spi_master_write_data_byte(dev, 0x0B); + spi_master_write_data_byte(dev, 0x0B); + spi_master_write_data_byte(dev, 0x00); + spi_master_write_data_byte(dev, 0x33); + spi_master_write_data_byte(dev, 0x33); + + spi_master_write_command(dev, 0xB7); + spi_master_write_data_byte(dev, 0x11); + + spi_master_write_command(dev, 0xBB); + spi_master_write_data_byte(dev, 0x2F); + + spi_master_write_command(dev, 0xC0); + spi_master_write_data_byte(dev, 0x2C); + + spi_master_write_command(dev, 0xC2); + spi_master_write_data_byte(dev, 0x01); + + spi_master_write_command(dev, 0xC3); + spi_master_write_data_byte(dev, 0x0D); + + spi_master_write_command(dev, 0xC4); + spi_master_write_data_byte(dev, 0x20); //VDV, 0x20:0v + + spi_master_write_command(dev, 0xC6); + spi_master_write_data_byte(dev, 0x13); //0x13:60Hz + + spi_master_write_command(dev, 0xD0); + spi_master_write_data_byte(dev, 0xA4); + spi_master_write_data_byte(dev, 0xA1); + + spi_master_write_command(dev, 0xD6); + spi_master_write_data_byte(dev, 0xA1); //sleep in后,gate输出为GND + + spi_master_write_command(dev, 0xE0); + spi_master_write_data_byte(dev, 0xF0); + spi_master_write_data_byte(dev, 0x04); + spi_master_write_data_byte(dev, 0x07); + spi_master_write_data_byte(dev, 0x09); + spi_master_write_data_byte(dev, 0x07); + spi_master_write_data_byte(dev, 0x13); + spi_master_write_data_byte(dev, 0x25); + spi_master_write_data_byte(dev, 0x33); + spi_master_write_data_byte(dev, 0x3C); + spi_master_write_data_byte(dev, 0x34); + spi_master_write_data_byte(dev, 0x10); + spi_master_write_data_byte(dev, 0x10); + spi_master_write_data_byte(dev, 0x29); + spi_master_write_data_byte(dev, 0x32); + + spi_master_write_command(dev, 0xE1); + spi_master_write_data_byte(dev, 0xF0); + spi_master_write_data_byte(dev, 0x05); + spi_master_write_data_byte(dev, 0x08); + spi_master_write_data_byte(dev, 0x0A); + spi_master_write_data_byte(dev, 0x09); + spi_master_write_data_byte(dev, 0x05); + spi_master_write_data_byte(dev, 0x25); + spi_master_write_data_byte(dev, 0x32); + spi_master_write_data_byte(dev, 0x3B); + spi_master_write_data_byte(dev, 0x3B); + spi_master_write_data_byte(dev, 0x17); + spi_master_write_data_byte(dev, 0x18); + spi_master_write_data_byte(dev, 0x2E); + spi_master_write_data_byte(dev, 0x37); + + spi_master_write_command(dev, 0xE4); + spi_master_write_data_byte(dev, 0x25); //使用240根gate (N+1)*8 + spi_master_write_data_byte(dev, 0x00); //设定gate起点位置 + spi_master_write_data_byte(dev, 0x00); //当gate没有用完时,bit4(TMG)设为0 + + // spi_master_write_command(dev, 0x21); + + spi_master_write_command(dev, 0x29); + + spi_master_write_command(dev, 0x2A); //Column Address Set + spi_master_write_data_byte(dev, 0x00); + spi_master_write_data_byte(dev, 0x00); //0 + spi_master_write_data_byte(dev, 0x00); + spi_master_write_data_byte(dev, 0xEF); //239 + + spi_master_write_command(dev, 0x2B); //Row Address Set + spi_master_write_data_byte(dev, 0x00); + spi_master_write_data_byte(dev, 0x14); //0 + spi_master_write_data_byte(dev, 0x01); + spi_master_write_data_byte(dev, 0x2B); + + spi_master_write_command(dev, 0x2C); +#endif + + if(dev->_bl >= 0) { + gpio_set_level( dev->_bl, 0 ); + } +} + + +// Draw pixel +// x:X coordinate +// y:Y coordinate +// color:color +void lcdDrawPixel(TFT_t * dev, uint16_t x, uint16_t y, uint16_t color){ + if (x >= dev->_width) return; + if (y >= dev->_height) return; + + uint16_t _x = x + dev->_offsetx; + uint16_t _y = y + dev->_offsety; + + spi_master_write_command(dev, 0x2A); // set column(x) address + spi_master_write_addr(dev, _x, _x); + spi_master_write_command(dev, 0x2B); // set Page(y) address + spi_master_write_addr(dev, _y, _y); + spi_master_write_command(dev, 0x2C); // Memory Write + spi_master_write_data_word(dev, color); +} + + +// Draw multi pixel +// x:X coordinate +// y:Y coordinate +// size:Number of colors +// colors:colors +void lcdDrawMultiPixels(TFT_t * dev, uint16_t x, uint16_t y, uint16_t size, uint16_t * colors) { + if (x+size > dev->_width) return; + if (y >= dev->_height) return; + + uint16_t _x1 = x + dev->_offsetx; + uint16_t _x2 = _x1 + size; + uint16_t _y1 = y + dev->_offsety; + uint16_t _y2 = _y1; + + spi_master_write_command(dev, 0x2A); // set column(x) address + spi_master_write_addr(dev, _x1, _x2); + spi_master_write_command(dev, 0x2B); // set Page(y) address + spi_master_write_addr(dev, _y1, _y2); + spi_master_write_command(dev, 0x2C); // Memory Write + spi_master_write_colors(dev, colors, size); +} + +// Draw rectangle of filling +// x1:Start X coordinate +// y1:Start Y coordinate +// x2:End X coordinate +// y2:End Y coordinate +// color:color +void lcdDrawFillRect(TFT_t * dev, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color) { + if (x1 >= dev->_width) return; + if (x2 >= dev->_width) x2=dev->_width-1; + if (y1 >= dev->_height) return; + if (y2 >= dev->_height) y2=dev->_height-1; + + ESP_LOGD(TAG,"offset(x)=%d offset(y)=%d",dev->_offsetx,dev->_offsety); + uint16_t _x1 = x1 + dev->_offsetx; + uint16_t _x2 = x2 + dev->_offsetx; + uint16_t _y1 = y1 + dev->_offsety; + uint16_t _y2 = y2 + dev->_offsety; + + bool ret = spi_master_write_command(dev, 0x2A); // set column(x) address + printf("ret = %d\r\n", ret); + spi_master_write_addr(dev, _x1, _x2); + spi_master_write_command(dev, 0x2B); // set Page(y) address + spi_master_write_addr(dev, _y1, _y2); + spi_master_write_command(dev, 0x2C); // Memory Write + for(int i=_x1;i<=_x2;i++){ + uint16_t size = _y2-_y1+1; + spi_master_write_color(dev, color, size); +#if 0 + for(j=y1;j<=y2;j++){ + //ESP_LOGD(TAG,"i=%d j=%d",i,j); + spi_master_write_data_word(dev, color); + } +#endif + } +} + +// Display OFF +void lcdDisplayOff(TFT_t * dev) { + spi_master_write_command(dev, 0x28); //Display off +} + +// Display ON +void lcdDisplayOn(TFT_t * dev) { + spi_master_write_command(dev, 0x29); //Display on +} + +// Fill screen +// color:color +void lcdFillScreen(TFT_t * dev, uint16_t color) { + lcdDrawFillRect(dev, 0, 0, dev->_width-1, dev->_height-1, color); +} + +// Draw line +// x1:Start X coordinate +// y1:Start Y coordinate +// x2:End X coordinate +// y2:End Y coordinate +// color:color +void lcdDrawLine(TFT_t * dev, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color) { + int i; + int dx,dy; + int sx,sy; + int E; + + /* distance between two points */ + dx = ( x2 > x1 ) ? x2 - x1 : x1 - x2; + dy = ( y2 > y1 ) ? y2 - y1 : y1 - y2; + + /* direction of two point */ + sx = ( x2 > x1 ) ? 1 : -1; + sy = ( y2 > y1 ) ? 1 : -1; + + /* inclination < 1 */ + if ( dx > dy ) { + E = -dx; + for ( i = 0 ; i <= dx ; i++ ) { + lcdDrawPixel(dev, x1, y1, color); + x1 += sx; + E += 2 * dy; + if ( E >= 0 ) { + y1 += sy; + E -= 2 * dx; + } + } + + /* inclination >= 1 */ + } else { + E = -dy; + for ( i = 0 ; i <= dy ; i++ ) { + lcdDrawPixel(dev, x1, y1, color); + y1 += sy; + E += 2 * dx; + if ( E >= 0 ) { + x1 += sx; + E -= 2 * dy; + } + } + } +} + +// Draw rectangle +// x1:Start X coordinate +// y1:Start Y coordinate +// x2:End X coordinate +// y2:End Y coordinate +// color:color +void lcdDrawRect(TFT_t * dev, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color) { + lcdDrawLine(dev, x1, y1, x2, y1, color); + lcdDrawLine(dev, x2, y1, x2, y2, color); + lcdDrawLine(dev, x2, y2, x1, y2, color); + lcdDrawLine(dev, x1, y2, x1, y1, color); +} + +// Draw rectangle with angle +// xc:Center X coordinate +// yc:Center Y coordinate +// w:Width of rectangle +// h:Height of rectangle +// angle :Angle of rectangle +// color :color + +//When the origin is (0, 0), the point (x1, y1) after rotating the point (x, y) by the angle is obtained by the following calculation. +// x1 = x * cos(angle) - y * sin(angle) +// y1 = x * sin(angle) + y * cos(angle) +void lcdDrawRectAngle(TFT_t * dev, uint16_t xc, uint16_t yc, uint16_t w, uint16_t h, uint16_t angle, uint16_t color) { + double xd,yd,rd; + int x1,y1; + int x2,y2; + int x3,y3; + int x4,y4; + rd = -angle * M_PI / 180.0; + xd = 0.0 - w/2; + yd = h/2; + x1 = (int)(xd * cos(rd) - yd * sin(rd) + xc); + y1 = (int)(xd * sin(rd) + yd * cos(rd) + yc); + + yd = 0.0 - yd; + x2 = (int)(xd * cos(rd) - yd * sin(rd) + xc); + y2 = (int)(xd * sin(rd) + yd * cos(rd) + yc); + + xd = w/2; + yd = h/2; + x3 = (int)(xd * cos(rd) - yd * sin(rd) + xc); + y3 = (int)(xd * sin(rd) + yd * cos(rd) + yc); + + yd = 0.0 - yd; + x4 = (int)(xd * cos(rd) - yd * sin(rd) + xc); + y4 = (int)(xd * sin(rd) + yd * cos(rd) + yc); + + lcdDrawLine(dev, x1, y1, x2, y2, color); + lcdDrawLine(dev, x1, y1, x3, y3, color); + lcdDrawLine(dev, x2, y2, x4, y4, color); + lcdDrawLine(dev, x3, y3, x4, y4, color); +} + +// Draw triangle +// xc:Center X coordinate +// yc:Center Y coordinate +// w:Width of triangle +// h:Height of triangle +// angle :Angle of triangle +// color :color + +//When the origin is (0, 0), the point (x1, y1) after rotating the point (x, y) by the angle is obtained by the following calculation. +// x1 = x * cos(angle) - y * sin(angle) +// y1 = x * sin(angle) + y * cos(angle) +void lcdDrawTriangle(TFT_t * dev, uint16_t xc, uint16_t yc, uint16_t w, uint16_t h, uint16_t angle, uint16_t color) { + double xd,yd,rd; + int x1,y1; + int x2,y2; + int x3,y3; + rd = -angle * M_PI / 180.0; + xd = 0.0; + yd = h/2; + x1 = (int)(xd * cos(rd) - yd * sin(rd) + xc); + y1 = (int)(xd * sin(rd) + yd * cos(rd) + yc); + + xd = w/2; + yd = 0.0 - yd; + x2 = (int)(xd * cos(rd) - yd * sin(rd) + xc); + y2 = (int)(xd * sin(rd) + yd * cos(rd) + yc); + + xd = 0.0 - w/2; + x3 = (int)(xd * cos(rd) - yd * sin(rd) + xc); + y3 = (int)(xd * sin(rd) + yd * cos(rd) + yc); + + lcdDrawLine(dev, x1, y1, x2, y2, color); + lcdDrawLine(dev, x1, y1, x3, y3, color); + lcdDrawLine(dev, x2, y2, x3, y3, color); +} + +// Draw circle +// x0:Central X coordinate +// y0:Central Y coordinate +// r:radius +// color:color +void lcdDrawCircle(TFT_t * dev, uint16_t x0, uint16_t y0, uint16_t r, uint16_t color) { + int x; + int y; + int err; + int old_err; + + x=0; + y=-r; + err=2-2*r; + do{ + lcdDrawPixel(dev, x0-x, y0+y, color); + lcdDrawPixel(dev, x0-y, y0-x, color); + lcdDrawPixel(dev, x0+x, y0-y, color); + lcdDrawPixel(dev, x0+y, y0+x, color); + if ((old_err=err)<=x) err+=++x*2+1; + if (old_err>y || err>x) err+=++y*2+1; + } while(y<0); +} + +// Draw circle of filling +// x0:Central X coordinate +// y0:Central Y coordinate +// r:radius +// color:color +void lcdDrawFillCircle(TFT_t * dev, uint16_t x0, uint16_t y0, uint16_t r, uint16_t color) { + int x; + int y; + int err; + int old_err; + int ChangeX; + + x=0; + y=-r; + err=2-2*r; + ChangeX=1; + do{ + if(ChangeX) { + lcdDrawLine(dev, x0-x, y0-y, x0-x, y0+y, color); + lcdDrawLine(dev, x0+x, y0-y, x0+x, y0+y, color); + } // endif + ChangeX=(old_err=err)<=x; + if (ChangeX) err+=++x*2+1; + if (old_err>y || err>x) err+=++y*2+1; + } while(y<=0); +} + +// Draw rectangle with round corner +// x1:Start X coordinate +// y1:Start Y coordinate +// x2:End X coordinate +// y2:End Y coordinate +// r:radius +// color:color +void lcdDrawRoundRect(TFT_t * dev, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t r, uint16_t color) { + int x; + int y; + int err; + int old_err; + unsigned char temp; + + if(x1>x2) { + temp=x1; x1=x2; x2=temp; + } // endif + + if(y1>y2) { + temp=y1; y1=y2; y2=temp; + } // endif + + ESP_LOGD(TAG, "x1=%d x2=%d delta=%d r=%d",x1, x2, x2-x1, r); + ESP_LOGD(TAG, "y1=%d y2=%d delta=%d r=%d",y1, y2, y2-y1, r); + if (x2-x1 < r) return; // Add 20190517 + if (y2-y1 < r) return; // Add 20190517 + + x=0; + y=-r; + err=2-2*r; + + do{ + if(x) { + lcdDrawPixel(dev, x1+r-x, y1+r+y, color); + lcdDrawPixel(dev, x2-r+x, y1+r+y, color); + lcdDrawPixel(dev, x1+r-x, y2-r-y, color); + lcdDrawPixel(dev, x2-r+x, y2-r-y, color); + } // endif + if ((old_err=err)<=x) err+=++x*2+1; + if (old_err>y || err>x) err+=++y*2+1; + } while(y<0); + + ESP_LOGD(TAG, "x1+r=%d x2-r=%d",x1+r, x2-r); + lcdDrawLine(dev, x1+r,y1 ,x2-r,y1 ,color); + lcdDrawLine(dev, x1+r,y2 ,x2-r,y2 ,color); + ESP_LOGD(TAG, "y1+r=%d y2-r=%d",y1+r, y2-r); + lcdDrawLine(dev, x1 ,y1+r,x1 ,y2-r,color); + lcdDrawLine(dev, x2 ,y1+r,x2 ,y2-r,color); +} + +// Draw arrow +// x1:Start X coordinate +// y1:Start Y coordinate +// x2:End X coordinate +// y2:End Y coordinate +// w:Width of the botom +// color:color +// Thanks http://k-hiura.cocolog-nifty.com/blog/2010/11/post-2a62.html +void lcdDrawArrow(TFT_t * dev, uint16_t x0,uint16_t y0,uint16_t x1,uint16_t y1,uint16_t w,uint16_t color) { + double Vx= x1 - x0; + double Vy= y1 - y0; + double v = sqrt(Vx*Vx+Vy*Vy); + // printf("v=%f\n",v); + double Ux= Vx/v; + double Uy= Vy/v; + + uint16_t L[2],R[2]; + L[0]= x1 - Uy*w - Ux*v; + L[1]= y1 + Ux*w - Uy*v; + R[0]= x1 + Uy*w - Ux*v; + R[1]= y1 - Ux*w - Uy*v; + //printf("L=%d-%d R=%d-%d\n",L[0],L[1],R[0],R[1]); + + //lcdDrawLine(x0,y0,x1,y1,color); + lcdDrawLine(dev, x1, y1, L[0], L[1], color); + lcdDrawLine(dev, x1, y1, R[0], R[1], color); + lcdDrawLine(dev, L[0], L[1], R[0], R[1], color); +} + + +// Draw arrow of filling +// x1:Start X coordinate +// y1:Start Y coordinate +// x2:End X coordinate +// y2:End Y coordinate +// w:Width of the botom +// color:color +void lcdDrawFillArrow(TFT_t * dev, uint16_t x0,uint16_t y0,uint16_t x1,uint16_t y1,uint16_t w,uint16_t color) { + double Vx= x1 - x0; + double Vy= y1 - y0; + double v = sqrt(Vx*Vx+Vy*Vy); + //printf("v=%f\n",v); + double Ux= Vx/v; + double Uy= Vy/v; + + uint16_t L[2],R[2]; + L[0]= x1 - Uy*w - Ux*v; + L[1]= y1 + Ux*w - Uy*v; + R[0]= x1 + Uy*w - Ux*v; + R[1]= y1 - Ux*w - Uy*v; + //printf("L=%d-%d R=%d-%d\n",L[0],L[1],R[0],R[1]); + + lcdDrawLine(dev, x0, y0, x1, y1, color); + lcdDrawLine(dev, x1, y1, L[0], L[1], color); + lcdDrawLine(dev, x1, y1, R[0], R[1], color); + lcdDrawLine(dev, L[0], L[1], R[0], R[1], color); + + int ww; + for(ww=w-1;ww>0;ww--) { + L[0]= x1 - Uy*ww - Ux*v; + L[1]= y1 + Ux*ww - Uy*v; + R[0]= x1 + Uy*ww - Ux*v; + R[1]= y1 - Ux*ww - Uy*v; + //printf("Fill>L=%d-%d R=%d-%d\n",L[0],L[1],R[0],R[1]); + lcdDrawLine(dev, x1, y1, L[0], L[1], color); + lcdDrawLine(dev, x1, y1, R[0], R[1], color); + } +} + + +// RGB565 conversion +// RGB565 is R(5)+G(6)+B(5)=16bit color format. +// Bit image "RRRRRGGGGGGBBBBB" +uint16_t rgb565_conv(uint16_t r,uint16_t g,uint16_t b) { + return (((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3)); +} + +// Draw ASCII character +// x:X coordinate +// y:Y coordinate +// ascii: ascii code +// color:color +int lcdDrawChar(TFT_t * dev, FontxFile *fxs, uint16_t x, uint16_t y, uint8_t ascii, uint16_t color) { + uint16_t xx,yy,bit,ofs; + unsigned char fonts[128]; // font pattern + unsigned char pw, ph; + int h,w; + uint16_t mask; + bool rc; + + if(_DEBUG_)printf("_font_direction=%d\n",dev->_font_direction); + rc = GetFontx(fxs, ascii, fonts, &pw, &ph); + if(_DEBUG_)printf("GetFontx rc=%d pw=%d ph=%d\n",rc,pw,ph); + if (!rc) return 0; + + int16_t xd1 = 0; + int16_t yd1 = 0; + int16_t xd2 = 0; + int16_t yd2 = 0; + uint16_t xss = 0; + uint16_t yss = 0; + int16_t xsd = 0; + int16_t ysd = 0; + int16_t next = 0; + uint16_t x0 = 0; + uint16_t x1 = 0; + uint16_t y0 = 0; + uint16_t y1 = 0; + if (dev->_font_direction == 0) { + xd1 = +1; + yd1 = +1; //-1; + xd2 = 0; + yd2 = 0; + xss = x; + yss = y - (ph - 1); + xsd = 1; + ysd = 0; + next = x + pw; + + x0 = x; + y0 = y - (ph-1); + x1 = x + (pw-1); + y1 = y; + } else if (dev->_font_direction == 2) { + xd1 = -1; + yd1 = -1; //+1; + xd2 = 0; + yd2 = 0; + xss = x; + yss = y + ph + 1; + xsd = 1; + ysd = 0; + next = x - pw; + + x0 = x - (pw-1); + y0 = y; + x1 = x; + y1 = y + (ph-1); + } else if (dev->_font_direction == 1) { + xd1 = 0; + yd1 = 0; + xd2 = -1; + yd2 = +1; //-1; + xss = x + ph; + yss = y; + xsd = 0; + ysd = 1; + next = y + pw; //y - pw; + + x0 = x; + y0 = y; + x1 = x + (ph-1); + y1 = y + (pw-1); + } else if (dev->_font_direction == 3) { + xd1 = 0; + yd1 = 0; + xd2 = +1; + yd2 = -1; //+1; + xss = x - (ph - 1); + yss = y; + xsd = 0; + ysd = 1; + next = y - pw; //y + pw; + + x0 = x - (ph-1); + y0 = y - (pw-1); + x1 = x; + y1 = y; + } + + if (dev->_font_fill) lcdDrawFillRect(dev, x0, y0, x1, y1, dev->_font_fill_color); + + int bits; + if(_DEBUG_)printf("xss=%d yss=%d\n",xss,yss); + ofs = 0; + yy = yss; + xx = xss; + for(h=0;h_font_fill) lcdDrawPixel(dev, xx, yy, dev->_font_fill_color); + } + if (h == (ph-2) && dev->_font_underline) + lcdDrawPixel(dev, xx, yy, dev->_font_underline_color); + if (h == (ph-1) && dev->_font_underline) + lcdDrawPixel(dev, xx, yy, dev->_font_underline_color); + xx = xx + xd1; + yy = yy + yd2; + mask = mask >> 1; + } + ofs++; + } + yy = yy + yd1; + xx = xx + xd2; + } + + if (next < 0) next = 0; + return next; +} + +int lcdDrawString(TFT_t * dev, FontxFile *fx, uint16_t x, uint16_t y, uint8_t * ascii, uint16_t color) { + int length = strlen((char *)ascii); + if(_DEBUG_)printf("lcdDrawString length=%d\n",length); + for(int i=0;i_font_direction == 0) + x = lcdDrawChar(dev, fx, x, y, ascii[i], color); + if (dev->_font_direction == 1) + y = lcdDrawChar(dev, fx, x, y, ascii[i], color); + if (dev->_font_direction == 2) + x = lcdDrawChar(dev, fx, x, y, ascii[i], color); + if (dev->_font_direction == 3) + y = lcdDrawChar(dev, fx, x, y, ascii[i], color); + } + if (dev->_font_direction == 0) return x; + if (dev->_font_direction == 2) return x; + if (dev->_font_direction == 1) return y; + if (dev->_font_direction == 3) return y; + return 0; +} + + +// Draw Non-Alphanumeric character +// x:X coordinate +// y:Y coordinate +// code: charcter code +// color:color +int lcdDrawCode(TFT_t * dev, FontxFile *fx, uint16_t x,uint16_t y,uint8_t code,uint16_t color) { + if(_DEBUG_)printf("code=%x x=%d y=%d\n",code,x,y); + if (dev->_font_direction == 0) + x = lcdDrawChar(dev, fx, x, y, code, color); + if (dev->_font_direction == 1) + y = lcdDrawChar(dev, fx, x, y, code, color); + if (dev->_font_direction == 2) + x = lcdDrawChar(dev, fx, x, y, code, color); + if (dev->_font_direction == 3) + y = lcdDrawChar(dev, fx, x, y, code, color); + if (dev->_font_direction == 0) return x; + if (dev->_font_direction == 2) return x; + if (dev->_font_direction == 1) return y; + if (dev->_font_direction == 3) return y; + return 0; +} + +#if 0 +// Draw UTF8 character +// x:X coordinate +// y:Y coordinate +// utf8: UTF8 code +// color:color +int lcdDrawUTF8Char(TFT_t * dev, FontxFile *fx, uint16_t x,uint16_t y,uint8_t *utf8,uint16_t color) { + uint16_t sjis[1]; + + sjis[0] = UTF2SJIS(utf8); + if(_DEBUG_)printf("sjis=%04x\n",sjis[0]); + return lcdDrawSJISChar(dev, fx, x, y, sjis[0], color); +} + +// Draw UTF8 string +// x:X coordinate +// y:Y coordinate +// utfs: UTF8 string +// color:color +int lcdDrawUTF8String(TFT_t * dev, FontxFile *fx, uint16_t x, uint16_t y, unsigned char *utfs, uint16_t color) { + + int i; + int spos; + uint16_t sjis[64]; + spos = String2SJIS(utfs, strlen((char *)utfs), sjis, 64); + if(_DEBUG_)printf("spos=%d\n",spos); + for(i=0;i_font_direction == 0) + x = lcdDrawSJISChar(dev, fx, x, y, sjis[i], color); + if (dev->_font_direction == 1) + y = lcdDrawSJISChar(dev, fx, x, y, sjis[i], color); + if (dev->_font_direction == 2) + x = lcdDrawSJISChar(dev, fx, x, y, sjis[i], color); + if (dev->_font_direction == 3) + y = lcdDrawSJISChar(dev, fx, x, y, sjis[i], color); + } + if (dev->_font_direction == 0) return x; + if (dev->_font_direction == 2) return x; + if (dev->_font_direction == 1) return y; + if (dev->_font_direction == 3) return y; + return 0; +} +#endif + +// Set font direction +// dir:Direction +void lcdSetFontDirection(TFT_t * dev, uint16_t dir) { + dev->_font_direction = dir; +} + +// Set font filling +// color:fill color +void lcdSetFontFill(TFT_t * dev, uint16_t color) { + dev->_font_fill = true; + dev->_font_fill_color = color; +} + +// UnSet font filling +void lcdUnsetFontFill(TFT_t * dev) { + dev->_font_fill = false; +} + +// Set font underline +// color:frame color +void lcdSetFontUnderLine(TFT_t * dev, uint16_t color) { + dev->_font_underline = true; + dev->_font_underline_color = color; +} + +// UnSet font underline +void lcdUnsetFontUnderLine(TFT_t * dev) { + dev->_font_underline = false; +} + +// Backlight OFF +void lcdBacklightOff(TFT_t * dev) { + if(dev->_bl >= 0) { + gpio_set_level( dev->_bl, 0 ); + } +} + +// Backlight ON +void lcdBacklightOn(TFT_t * dev) { + if(dev->_bl >= 0) { + gpio_set_level( dev->_bl, 1 ); + } +} + +// Display Inversion Off +void lcdInversionOff(TFT_t * dev) { + spi_master_write_command(dev, 0x20); //Display Inversion Off +} + +// Display Inversion On +void lcdInversionOn(TFT_t * dev) { + spi_master_write_command(dev, 0x21); //Display Inversion On +} diff --git a/main/drivers/st7789/st7789.h b/main/drivers/st7789/st7789.h new file mode 100644 index 0000000..c2c5c1a --- /dev/null +++ b/main/drivers/st7789/st7789.h @@ -0,0 +1,81 @@ +#ifndef MAIN_ST7789_H_ +#define MAIN_ST7789_H_ + +#include "driver/spi_master.h" +#include "fontx.h" + +#define RED 0xf800 +#define GREEN 0x07e0 +#define BLUE 0x001f +#define BLACK 0x0000 +#define WHITE 0xffff +#define GRAY 0x8c51 +#define YELLOW 0xFFE0 +#define CYAN 0x07FF +#define PURPLE 0xF81F + + +#define DIRECTION0 0 +#define DIRECTION90 1 +#define DIRECTION180 2 +#define DIRECTION270 3 + + +typedef struct { + uint16_t _width; + uint16_t _height; + uint16_t _offsetx; + uint16_t _offsety; + uint16_t _font_direction; + uint16_t _font_fill; + uint16_t _font_fill_color; + uint16_t _font_underline; + uint16_t _font_underline_color; + int16_t _dc; + int16_t _bl; + spi_device_handle_t _SPIHandle; +} TFT_t; + +void spi_master_init(TFT_t * dev, int16_t GPIO_MOSI, int16_t GPIO_SCLK, int16_t GPIO_CS, int16_t GPIO_DC, int16_t GPIO_RESET, int16_t GPIO_BL); +bool spi_master_write_byte(spi_device_handle_t SPIHandle, const uint8_t* Data, size_t DataLength); +bool spi_master_write_command(TFT_t * dev, uint8_t cmd); +bool spi_master_write_data_byte(TFT_t * dev, uint8_t data); +bool spi_master_write_data_word(TFT_t * dev, uint16_t data); +bool spi_master_write_addr(TFT_t * dev, uint16_t addr1, uint16_t addr2); +bool spi_master_write_color(TFT_t * dev, uint16_t color, uint16_t size); +bool spi_master_write_colors(TFT_t * dev, uint16_t * colors, uint16_t size); + +void delayMS(int ms); +void lcdInit(TFT_t * dev, int width, int height, int offsetx, int offsety); +void lcdDrawPixel(TFT_t * dev, uint16_t x, uint16_t y, uint16_t color); +void lcdDrawMultiPixels(TFT_t * dev, uint16_t x, uint16_t y, uint16_t size, uint16_t * colors); +void lcdDrawFillRect(TFT_t * dev, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color); +void lcdDisplayOff(TFT_t * dev); +void lcdDisplayOn(TFT_t * dev); +void lcdFillScreen(TFT_t * dev, uint16_t color); +void lcdDrawLine(TFT_t * dev, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color); +void lcdDrawRect(TFT_t * dev, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color); +void lcdDrawRectAngle(TFT_t * dev, uint16_t xc, uint16_t yc, uint16_t w, uint16_t h, uint16_t angle, uint16_t color); +void lcdDrawTriangle(TFT_t * dev, uint16_t xc, uint16_t yc, uint16_t w, uint16_t h, uint16_t angle, uint16_t color); +void lcdDrawCircle(TFT_t * dev, uint16_t x0, uint16_t y0, uint16_t r, uint16_t color); +void lcdDrawFillCircle(TFT_t * dev, uint16_t x0, uint16_t y0, uint16_t r, uint16_t color); +void lcdDrawRoundRect(TFT_t * dev, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t r, uint16_t color); +void lcdDrawArrow(TFT_t * dev, uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t w, uint16_t color); +void lcdDrawFillArrow(TFT_t * dev, uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t w, uint16_t color); +uint16_t rgb565_conv(uint16_t r, uint16_t g, uint16_t b); +int lcdDrawChar(TFT_t * dev, FontxFile *fx, uint16_t x, uint16_t y, uint8_t ascii, uint16_t color); +int lcdDrawString(TFT_t * dev, FontxFile *fx, uint16_t x, uint16_t y, uint8_t * ascii, uint16_t color); +int lcdDrawCode(TFT_t * dev, FontxFile *fx, uint16_t x,uint16_t y,uint8_t code,uint16_t color); +//int lcdDrawUTF8Char(TFT_t * dev, FontxFile *fx, uint16_t x, uint16_t y, uint8_t *utf8, uint16_t color); +//int lcdDrawUTF8String(TFT_t * dev, FontxFile *fx, uint16_t x, uint16_t y, unsigned char *utfs, uint16_t color); +void lcdSetFontDirection(TFT_t * dev, uint16_t); +void lcdSetFontFill(TFT_t * dev, uint16_t color); +void lcdUnsetFontFill(TFT_t * dev); +void lcdSetFontUnderLine(TFT_t * dev, uint16_t color); +void lcdUnsetFontUnderLine(TFT_t * dev); +void lcdBacklightOff(TFT_t * dev); +void lcdBacklightOn(TFT_t * dev); +void lcdInversionOff(TFT_t * dev); +void lcdInversionOn(TFT_t * dev); +#endif /* MAIN_ST7789_H_ */ + diff --git a/main/utilities/letter_shell/port/esp-idf/CMakeLists.txt b/main/utilities/letter_shell/port/esp-idf/CMakeLists.txt new file mode 100644 index 0000000..aad99df --- /dev/null +++ b/main/utilities/letter_shell/port/esp-idf/CMakeLists.txt @@ -0,0 +1,8 @@ +idf_component_register( + SRCS "src/shell.c" + "src/shell_ext.c" + "shell_port.c" + INCLUDE_DIRS "./" + "./src" + LDFRAGMENTS "shell.lf" +) \ No newline at end of file diff --git a/main/utilities/letter_shell/port/esp-idf/readme.md b/main/utilities/letter_shell/port/esp-idf/readme.md new file mode 100644 index 0000000..d7dcf1e --- /dev/null +++ b/main/utilities/letter_shell/port/esp-idf/readme.md @@ -0,0 +1,13 @@ +# esp-idf demo + +此目录文件用于在 `esp-idf` 中使用 `letter-shell` 做参考 + +## 使用 + +此 demo 已经包含 `CMakeLists.txt`, 可直接作为 `esp-idf` 的模块编译 + +## 注意 + +- `esp-idf` 编译系统会忽略 `__attribute__((used))` 声明,所以仅仅作为命令定义的函数不会被包含在编译出来的固件里面,只有被代码引用的函数会被编译进去 + +- 此 demo 包含链接使用的 `.lf` 文件,在使用这个文件的情况下不需要修改 `esp-idf` 中的 `ld` 文件 diff --git a/main/utilities/letter_shell/port/esp-idf/shell.lf b/main/utilities/letter_shell/port/esp-idf/shell.lf new file mode 100644 index 0000000..bd7f89c --- /dev/null +++ b/main/utilities/letter_shell/port/esp-idf/shell.lf @@ -0,0 +1,13 @@ +[sections:shellCommand] +entries: + shellCommand+ + +[scheme:shell_command] +entries: + shellCommand -> flash_rodata + +[mapping:shell] +archive: * +entries: + * (shell_command); + shellCommand -> flash_rodata KEEP() ALIGN(4, pre, post) SURROUND(shell_command) \ No newline at end of file diff --git a/main/utilities/letter_shell/port/esp-idf/shell_cfg.h b/main/utilities/letter_shell/port/esp-idf/shell_cfg.h new file mode 100644 index 0000000..05b0446 --- /dev/null +++ b/main/utilities/letter_shell/port/esp-idf/shell_cfg.h @@ -0,0 +1,190 @@ +/** + * @file shell_cfg.h + * @author Letter (nevermindzzt@gmail.com) + * @brief shell config + * @version 3.0.0 + * @date 2019-12-31 + * + * @copyright (c) 2019 Letter + * + */ + +#ifndef __SHELL_CFG_H__ +#define __SHELL_CFG_H__ + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +/** + * @brief 是否使用默认shell任务while循环,使能宏`SHELL_USING_TASK`后此宏有意义 + * 使能此宏,则`shellTask()`函数会一直循环读取输入,一般使用操作系统建立shell + * 任务时使能此宏,关闭此宏的情况下,一般适用于无操作系统,在主循环中调用`shellTask()` + */ +#define SHELL_TASK_WHILE 1 + +/** + * @brief 是否使用命令导出方式 + * 使能此宏后,可以使用`SHELL_EXPORT_CMD()`等导出命令 + * 定义shell命令,关闭此宏的情况下,需要使用命令表的方式 + */ +#define SHELL_USING_CMD_EXPORT 1 + +/** + * @brief 是否使用shell伴生对象 + * 一些扩展的组件(文件系统支持,日志工具等)需要使用伴生对象 + */ +#define SHELL_USING_COMPANION 0 + +/** + * @brief 支持shell尾行模式 + */ +#define SHELL_SUPPORT_END_LINE 0 + +/** + * @brief 是否在输出命令列表中列出用户 + */ +#define SHELL_HELP_LIST_USER 0 + +/** + * @brief 是否在输出命令列表中列出变量 + */ +#define SHELL_HELP_LIST_VAR 0 + +/** + * @brief 是否在输出命令列表中列出按键 + */ +#define SHELL_HELP_LIST_KEY 0 + +/** + * @brief 是否在输出命令列表中展示命令权限 + */ +#define SHELL_HELP_SHOW_PERMISSION 1 + +/** + * @brief 使用LF作为命令行回车触发 + * 可以和SHELL_ENTER_CR同时开启 + */ +#define SHELL_ENTER_LF 1 + +/** + * @brief 使用CR作为命令行回车触发 + * 可以和SHELL_ENTER_LF同时开启 + */ +#define SHELL_ENTER_CR 1 + +/** + * @brief 使用CRLF作为命令行回车触发 + * 不可以和SHELL_ENTER_LF或SHELL_ENTER_CR同时开启 + */ +#define SHELL_ENTER_CRLF 0 + +/** + * @brief 使用执行未导出函数的功能 + * 启用后,可以通过`exec [addr] [args]`直接执行对应地址的函数 + * @attention 如果地址错误,可能会直接引起程序崩溃 + */ +#define SHELL_EXEC_UNDEF_FUNC 0 + +/** + * @brief shell命令参数最大数量 + * 包含命令名在内,超过16个参数并且使用了参数自动转换的情况下,需要修改源码 + */ +#define SHELL_PARAMETER_MAX_NUMBER 8 + +/** + * @brief 历史命令记录数量 + */ +#define SHELL_HISTORY_MAX_NUMBER 5 + +/** + * @brief 双击间隔(ms) + * 使能宏`SHELL_LONG_HELP`后此宏生效,定义双击tab补全help的时间间隔 + */ +#define SHELL_DOUBLE_CLICK_TIME 200 + +/** + * @brief 快速帮助 + * 作用于双击tab的场景,当使能此宏时,双击tab不会对命令进行help补全,而是直接显示对应命令的帮助信息 + */ +#define SHELL_QUICK_HELP 1 + +/** + * @brief 保存命令返回值 + * 开启后会默认定义一个`RETVAL`变量,会保存上一次命令执行的返回值,可以在随后的命令中进行调用 + * 如果命令的`SHELL_CMD_DISABLE_RETURN`标志被设置,则该命令不会更新`RETVAL` + */ +#define SHELL_KEEP_RETURN_VALUE 0 + +/** + * @brief 管理的最大shell数量 + */ +#define SHELL_MAX_NUMBER 5 + +/** + * @brief shell格式化输出的缓冲大小 + * 为0时不使用shell格式化输出 + */ +#define SHELL_PRINT_BUFFER 128 + +/** + * @brief shell格式化输入的缓冲大小 + * 为0时不使用shell格式化输入 + * @note shell格式化输入会阻塞shellTask, 仅适用于在有操作系统的情况下使用 + */ +#define SHELL_SCAN_BUFFER 0 + +/** + * @brief 获取系统时间(ms) + * 定义此宏为获取系统Tick,如`HAL_GetTick()` + * @note 此宏不定义时无法使用双击tab补全命令help,无法使用shell超时锁定 + */ +#define SHELL_GET_TICK() xTaskGetTickCount() + +/** + * @brief 使用锁 + * @note 使用shell锁时,需要对加锁和解锁进行实现 + */ +#define SHELL_USING_LOCK 0 + +/** + * @brief shell内存分配 + * shell本身不需要此接口,若使用shell伴生对象,需要进行定义 + */ +#define SHELL_MALLOC(size) 0 + +/** + * @brief shell内存释放 + * shell本身不需要此接口,若使用shell伴生对象,需要进行定义 + */ +#define SHELL_FREE(obj) 0 + +/** + * @brief 是否显示shell信息 + */ +#define SHELL_SHOW_INFO 1 + +/** + * @brief 是否在登录后清除命令行 + */ +#define SHELL_CLS_WHEN_LOGIN 1 + +/** + * @brief shell默认用户 + */ +#define SHELL_DEFAULT_USER "letter" + +/** + * @brief shell默认用户密码 + * 若默认用户不需要密码,设为"" + */ +#define SHELL_DEFAULT_USER_PASSWORD "" + +/** + * @brief shell自动锁定超时 + * shell当前用户密码有效的时候生效,超时后会自动重新锁定shell + * 设置为0时关闭自动锁定功能,时间单位为`SHELL_GET_TICK()`单位 + * @note 使用超时锁定必须保证`SHELL_GET_TICK()`有效 + */ +#define SHELL_LOCK_TIMEOUT 0 * 60 * 1000 + +#endif diff --git a/main/utilities/letter_shell/port/esp-idf/shell_port.c b/main/utilities/letter_shell/port/esp-idf/shell_port.c new file mode 100644 index 0000000..d08b4f6 --- /dev/null +++ b/main/utilities/letter_shell/port/esp-idf/shell_port.c @@ -0,0 +1,70 @@ +/** + * @file shell_port.c + * @author Letter (NevermindZZT@gmail.com) + * @brief + * @version 0.1 + * @date 2019-02-22 + * + * @copyright (c) 2019 Letter + * + */ + +#include "shell.h" +#include "freertos/FreeRTOS.h" +#include "driver/uart.h" + + +#define SHELL_UART UART_NUM_0 + +Shell shell; +char shellBuffer[512]; + +/** + * @brief 用户shell写 + * + * @param data 数据 + * @param len 数据长度 + * + * @return unsigned short 写入实际长度 + */ +unsigned short userShellWrite(char *data, unsigned short len) +{ + return uart_write_bytes(SHELL_UART, (const char *)data, len); +} + + +/** + * @brief 用户shell读 + * + * @param data 数据 + * @param len 数据长度 + * + * @return unsigned short 读取实际长度 + */ +signed char userShellRead(char *data, unsigned short len) +{ + return uart_read_bytes(SHELL_UART, (uint8_t *)data, len, portMAX_DELAY); +} + + +/** + * @brief 用户shell初始化 + * + */ +void userShellInit(void) +{ + uart_config_t uartConfig = { + .baud_rate = 115200, + .data_bits = UART_DATA_8_BITS, + .parity = UART_PARITY_DISABLE, + .stop_bits = UART_STOP_BITS_1, + .flow_ctrl = UART_HW_FLOWCTRL_DISABLE + }; + uart_param_config(SHELL_UART, &uartConfig); + uart_driver_install(SHELL_UART, 256 * 2, 0, 0, NULL, 0); + shell.write = userShellWrite; + shell.read = userShellRead; + shellInit(&shell, shellBuffer, 512); + + xTaskCreate(shellTask, "shell", 2048, &shell, 10, NULL); +} diff --git a/main/utilities/letter_shell/port/esp-idf/shell_port.h b/main/utilities/letter_shell/port/esp-idf/shell_port.h new file mode 100644 index 0000000..0fd47ce --- /dev/null +++ b/main/utilities/letter_shell/port/esp-idf/shell_port.h @@ -0,0 +1,20 @@ +/** + * @file shell_port.h + * @author Letter (NevermindZZT@gmail.com) + * @brief + * @version 0.1 + * @date 2019-02-22 + * + * @copyright (c) 2019 Letter + * + */ + +#ifndef __SHELL_PORT_H__ +#define __SHELL_PORT_H__ + +#include "shell.h" + +extern Shell shell; + +void userShellInit(void); +#endif diff --git a/main/utilities/letter_shell/src/shell.c b/main/utilities/letter_shell/src/shell.c new file mode 100644 index 0000000..cc6ee33 --- /dev/null +++ b/main/utilities/letter_shell/src/shell.c @@ -0,0 +1,2011 @@ +/** + * @file shell.c + * @author Letter (NevermindZZT@gmail.com) + * @version 3.0.0 + * @date 2019-12-30 + * + * @copyright (c) 2020 Letter + * + */ + +#include "shell.h" +#include "string.h" +#include "stdio.h" +#include "stdarg.h" +#include "shell_ext.h" + + +#if SHELL_USING_CMD_EXPORT == 1 +/** + * @brief 默认用户 + */ +const char shellCmdDefaultUser[] = SHELL_DEFAULT_USER; +const char shellPasswordDefaultUser[] = SHELL_DEFAULT_USER_PASSWORD; +const char shellDesDefaultUser[] = "default user"; +SHELL_USED const ShellCommand shellUserDefault SHELL_SECTION("shellCommand") = +{ + .attr.value = SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_USER), + .data.user.name = shellCmdDefaultUser, + .data.user.password = shellPasswordDefaultUser, + .data.user.desc = shellDesDefaultUser +}; +#endif + +#if SHELL_USING_CMD_EXPORT == 1 + #if defined(__CC_ARM) || (defined(__ARMCC_VERSION) && __ARMCC_VERSION >= 6000000) + extern const unsigned int shellCommand$$Base; + extern const unsigned int shellCommand$$Limit; + #elif defined(__ICCARM__) || defined(__ICCRX__) + #pragma section="shellCommand" + #elif defined(__GNUC__) + extern const unsigned int _shell_command_start; + extern const unsigned int _shell_command_end; + #endif +#else + extern const ShellCommand shellCommandList[]; + extern const unsigned short shellCommandCount; +#endif + + +/** + * @brief shell 常量文本索引 + */ +enum +{ +#if SHELL_SHOW_INFO == 1 + SHELL_TEXT_INFO, /**< shell信息 */ +#endif + SHELL_TEXT_CMD_TOO_LONG, /**< 命令过长 */ + SHELL_TEXT_CMD_LIST, /**< 可执行命令列表标题 */ + SHELL_TEXT_VAR_LIST, /**< 变量列表标题 */ + SHELL_TEXT_USER_LIST, /**< 用户列表标题 */ + SHELL_TEXT_KEY_LIST, /**< 按键列表标题 */ + SHELL_TEXT_CMD_NOT_FOUND, /**< 命令未找到 */ + SHELL_TEXT_POINT_CANNOT_MODIFY, /**< 指针变量不允许修改 */ + SHELL_TEXT_VAR_READ_ONLY_CANNOT_MODIFY, /**< 只读变量不允许修改 */ + SHELL_TEXT_NOT_VAR, /**< 命令不是变量 */ + SHELL_TEXT_VAR_NOT_FOUND, /**< 变量未找到 */ + SHELL_TEXT_HELP_HEADER, /**< help头 */ + SHELL_TEXT_PASSWORD_HINT, /**< 密码输入提示 */ + SHELL_TEXT_PASSWORD_ERROR, /**< 密码错误 */ + SHELL_TEXT_CLEAR_CONSOLE, /**< 清空控制台 */ + SHELL_TEXT_CLEAR_LINE, /**< 清空当前行 */ + SHELL_TEXT_TYPE_CMD, /**< 命令类型 */ + SHELL_TEXT_TYPE_VAR, /**< 变量类型 */ + SHELL_TEXT_TYPE_USER, /**< 用户类型 */ + SHELL_TEXT_TYPE_KEY, /**< 按键类型 */ + SHELL_TEXT_TYPE_NONE, /**< 非法类型 */ +#if SHELL_EXEC_UNDEF_FUNC == 1 + SHELL_TEXT_PARAM_ERROR, /**< 参数错误 */ +#endif +}; + + +static const char *shellText[] = +{ +#if SHELL_SHOW_INFO == 1 + [SHELL_TEXT_INFO] = + "\r\n" + " _ _ _ _ _ _ \r\n" + "| | ___| |_| |_ ___ _ __ ___| |__ ___| | |\r\n" + "| | / _ \\ __| __/ _ \\ '__| / __| '_ \\ / _ \\ | |\r\n" + "| |__| __/ |_| || __/ | \\__ \\ | | | __/ | |\r\n" + "|_____\\___|\\__|\\__\\___|_| |___/_| |_|\\___|_|_|\r\n" + "\r\n" + "Build: "__DATE__" "__TIME__"\r\n" + "Version: "SHELL_VERSION"\r\n" + "Copyright: (c) 2020 Letter\r\n", +#endif + [SHELL_TEXT_CMD_TOO_LONG] = + "\r\nWarning: Command is too long\r\n", + [SHELL_TEXT_CMD_LIST] = + "\r\nCommand List:\r\n", + [SHELL_TEXT_VAR_LIST] = + "\r\nVar List:\r\n", + [SHELL_TEXT_USER_LIST] = + "\r\nUser List:\r\n", + [SHELL_TEXT_KEY_LIST] = + "\r\nKey List:\r\n", + [SHELL_TEXT_CMD_NOT_FOUND] = + "Command not Found\r\n", + [SHELL_TEXT_POINT_CANNOT_MODIFY] = + "can't set pointer\r\n", + [SHELL_TEXT_VAR_READ_ONLY_CANNOT_MODIFY] = + "can't set read only var\r\n", + [SHELL_TEXT_NOT_VAR] = + " is not a var\r\n", + [SHELL_TEXT_VAR_NOT_FOUND] = + "Var not Fount\r\n", + [SHELL_TEXT_HELP_HEADER] = + "command help of ", + [SHELL_TEXT_PASSWORD_HINT] = + "Please input password:", + [SHELL_TEXT_PASSWORD_ERROR] = + "\r\npassword error\r\n", + [SHELL_TEXT_CLEAR_CONSOLE] = + "\033[2J\033[1H", + [SHELL_TEXT_CLEAR_LINE] = + "\033[2K\r", + [SHELL_TEXT_TYPE_CMD] = + "CMD ", + [SHELL_TEXT_TYPE_VAR] = + "VAR ", + [SHELL_TEXT_TYPE_USER] = + "USER", + [SHELL_TEXT_TYPE_KEY] = + "KEY ", + [SHELL_TEXT_TYPE_NONE] = + "NONE", +#if SHELL_EXEC_UNDEF_FUNC == 1 + [SHELL_TEXT_PARAM_ERROR] = + "Parameter error\r\n", +#endif +}; + + +/** + * @brief shell对象表 + */ +static Shell *shellList[SHELL_MAX_NUMBER] = {NULL}; + + +static void shellAdd(Shell *shell); +static void shellWritePrompt(Shell *shell, unsigned char newline); +static void shellWriteReturnValue(Shell *shell, int value); +static int shellShowVar(Shell *shell, ShellCommand *command); +void shellSetUser(Shell *shell, const ShellCommand *user); +ShellCommand* shellSeekCommand(Shell *shell, + const char *cmd, + ShellCommand *base, + unsigned short compareLength); +static void shellWriteCommandHelp(Shell *shell, char *cmd); + +/** + * @brief shell 初始化 + * + * @param shell shell对象 + */ +void shellInit(Shell *shell, char *buffer, unsigned short size) +{ + shell->parser.length = 0; + shell->parser.cursor = 0; + shell->info.user = NULL; + shell->status.isChecked = 1; + + shell->parser.buffer = buffer; + shell->parser.bufferSize = size / (SHELL_HISTORY_MAX_NUMBER + 1); + +#if SHELL_HISTORY_MAX_NUMBER > 0 + shell->history.offset = 0; + shell->history.number = 0; + shell->history.record = 0; + for (short i = 0; i < SHELL_HISTORY_MAX_NUMBER; i++) + { + shell->history.item[i] = buffer + shell->parser.bufferSize * (i + 1); + } +#endif /** SHELL_HISTORY_MAX_NUMBER > 0 */ + +#if SHELL_USING_CMD_EXPORT == 1 + #if defined(__CC_ARM) || (defined(__ARMCC_VERSION) && __ARMCC_VERSION >= 6000000) + shell->commandList.base = (ShellCommand *)(&shellCommand$$Base); + shell->commandList.count = ((unsigned int)(&shellCommand$$Limit) + - (unsigned int)(&shellCommand$$Base)) + / sizeof(ShellCommand); + + #elif defined(__ICCARM__) || defined(__ICCRX__) + shell->commandList.base = (ShellCommand *)(__section_begin("shellCommand")); + shell->commandList.count = ((unsigned int)(__section_end("shellCommand")) + - (unsigned int)(__section_begin("shellCommand"))) + / sizeof(ShellCommand); + #elif defined(__GNUC__) + shell->commandList.base = (ShellCommand *)(&_shell_command_start); + shell->commandList.count = ((unsigned int)(&_shell_command_end) + - (unsigned int)(&_shell_command_start)) + / sizeof(ShellCommand); + #else + #error not supported compiler, please use command table mode + #endif +#else + shell->commandList.base = (ShellCommand *)shellCommandList; + shell->commandList.count = shellCommandCount; +#endif + + shellAdd(shell); + + shellSetUser(shell, shellSeekCommand(shell, + SHELL_DEFAULT_USER, + shell->commandList.base, + 0)); + shellWritePrompt(shell, 1); +} + + +/** + * @brief 添加shell + * + * @param shell shell对象 + */ +static void shellAdd(Shell *shell) +{ + for (short i = 0; i < SHELL_MAX_NUMBER; i++) + { + if (shellList[i] == NULL) + { + shellList[i] = shell; + return; + } + } +} + +/** + * @brief 移除shell + * + * @param shell shell对象 + * + */ +void shellRemove(Shell *shell) +{ + for (short i = 0; i < SHELL_MAX_NUMBER; i++) + { + if (shellList[i] == shell) + { + shellList[i] = NULL; + return; + } + } +} + +/** + * @brief 获取当前活动shell + * + * @return Shell* 当前活动shell对象 + */ +Shell* shellGetCurrent(void) +{ + for (short i = 0; i < SHELL_MAX_NUMBER; i++) + { + if (shellList[i] && shellList[i]->status.isActive) + { + return shellList[i]; + } + } + return NULL; +} + + +/** + * @brief shell写字符 + * + * @param shell shell对象 + * @param data 字符数据 + */ +static void shellWriteByte(Shell *shell, char data) +{ + shell->write(&data, 1); +} + + +/** + * @brief shell 写字符串 + * + * @param shell shell对象 + * @param string 字符串数据 + * + * @return unsigned short 写入字符的数量 + */ +unsigned short shellWriteString(Shell *shell, const char *string) +{ + unsigned short count = 0; + const char *p = string; + SHELL_ASSERT(shell->write, return 0); + while(*p++) + { + count ++; + } + return shell->write((char *)string, count); +} + + +/** + * @brief shell 写命令描述字符串 + * + * @param shell shell对象 + * @param string 字符串数据 + * + * @return unsigned short 写入字符的数量 + */ +static unsigned short shellWriteCommandDesc(Shell *shell, const char *string) +{ + unsigned short count = 0; + const char *p = string; + SHELL_ASSERT(shell->write, return 0); + while (*p && *p != '\r' && *p != '\n') + { + p++; + count++; + } + + if (count > 36) + { + shell->write((char *)string, 36); + shell->write("...", 3); + } + else + { + shell->write((char *)string, count); + } + return count > 36 ? 36 : 39; +} + + +/** + * @brief shell写命令提示符 + * + * @param shell shell对象 + * @param newline 新行 + * + */ +static void shellWritePrompt(Shell *shell, unsigned char newline) +{ + if (shell->status.isChecked) + { + if (newline) + { + shellWriteString(shell, "\r\n"); + } + shellWriteString(shell, shell->info.user->data.user.name); + shellWriteString(shell, ":"); + shellWriteString(shell, shell->info.path ? shell->info.path : "/"); + shellWriteString(shell, "$ "); + } + else + { + shellWriteString(shell, shellText[SHELL_TEXT_PASSWORD_HINT]); + } +} + + +#if SHELL_PRINT_BUFFER > 0 +/** + * @brief shell格式化输出 + * + * @param shell shell对象 + * @param fmt 格式化字符串 + * @param ... 参数 + */ +void shellPrint(Shell *shell, const char *fmt, ...) +{ + char buffer[SHELL_PRINT_BUFFER]; + va_list vargs; + + SHELL_ASSERT(shell, return); + + va_start(vargs, fmt); + vsnprintf(buffer, SHELL_PRINT_BUFFER - 1, fmt, vargs); + va_end(vargs); + + shellWriteString(shell, buffer); +} +#endif + + +#if SHELL_SCAN_BUFFER > 0 +/** + * @brief shell格式化输入 + * + * @param shell shell对象 + * @param fmt 格式化字符串 + * @param ... 参数 + */ +void shellScan(Shell *shell, char *fmt, ...) +{ + char buffer[SHELL_SCAN_BUFFER]; + va_list vargs; + short index = 0; + + SHELL_ASSERT(shell, return); + + if (shell->read) + { + do { + if (shell->read(&buffer[index], 1) == 1) + { + shell->write(&buffer[index], 1); + index++; + } + } while (buffer[index -1] != '\r' && buffer[index -1] != '\n' && index < SHELL_SCAN_BUFFER); + shellWriteString(shell, "\r\n"); + buffer[index] = '\0'; + } + + va_start(vargs, fmt); + vsscanf(buffer, fmt, vargs); + va_end(vargs); +} +#endif + + +/** + * @brief shell 检查命令权限 + * + * @param shell shell对象 + * @param command ShellCommand + * + * @return signed char 0 当前用户具有该命令权限 + * @return signec char -1 当前用户不具有该命令权限 + */ +signed char shellCheckPermission(Shell *shell, ShellCommand *command) +{ + return ((!command->attr.attrs.permission + || command->attr.attrs.type == SHELL_TYPE_USER + || (shell->info.user + && (command->attr.attrs.permission + & shell->info.user->attr.attrs.permission))) + && (shell->status.isChecked + || command->attr.attrs.enableUnchecked)) + ? 0 : -1; +} + + +/** + * @brief int转16进制字符串 + * + * @param value 数值 + * @param buffer 缓冲 + * + * @return signed char 转换后有效数据长度 + */ +signed char shellToHex(unsigned int value, char *buffer) +{ + char byte; + unsigned char i = 8; + buffer[8] = 0; + while (value) + { + byte = value & 0x0000000F; + buffer[--i] = (byte > 9) ? (byte + 87) : (byte + 48); + value >>= 4; + } + return 8 - i; +} + + +/** +* @brief int转10进制字符串 + * + * @param value 数值 + * @param buffer 缓冲 + * + * @return signed char 转换后有效数据长度 + */ +signed char shellToDec(int value, char *buffer) +{ + unsigned char i = 11; + int v = value; + if (value < 0) + { + v = -value; + } + buffer[11] = 0; + while (v) + { + buffer[--i] = v % 10 + 48; + v /= 10; + } + if (value < 0) + { + buffer[--i] = '-'; + } + if (value == 0) { + buffer[--i] = '0'; + } + return 11 - i; +} + + +/** + * @brief shell字符串复制 + * + * @param dest 目标字符串 + * @param src 源字符串 + * @return unsigned short 字符串长度 + */ +static unsigned short shellStringCopy(char *dest, char* src) +{ + unsigned short count = 0; + while (*(src + count)) + { + *(dest + count) = *(src + count); + count++; + } + *(dest + count) = 0; + return count; +} + + +/** + * @brief shell字符串比较 + * + * @param dest 目标字符串 + * @param src 源字符串 + * @return unsigned short 匹配长度 + */ +static unsigned short shellStringCompare(char* dest, char *src) +{ + unsigned short match = 0; + unsigned short i = 0; + + while (*(dest +i) && *(src + i)) + { + if (*(dest + i) != *(src +i)) + { + break; + } + match ++; + i++; + } + return match; +} + + +/** + * @brief shell获取命令名 + * + * @param command 命令 + * @return const char* 命令名 + */ +static const char* shellGetCommandName(ShellCommand *command) +{ + static char buffer[9]; + for (unsigned char i = 0; i < 9; i++) + { + buffer[i] = '0'; + } + if (command->attr.attrs.type <= SHELL_TYPE_CMD_FUNC) + { + return command->data.cmd.name; + } + else if (command->attr.attrs.type <= SHELL_TYPE_VAR_NODE) + { + return command->data.var.name; + } + else if (command->attr.attrs.type <= SHELL_TYPE_USER) + { + return command->data.user.name; + } + else + { + shellToHex(command->data.key.value, buffer); + return buffer; + } +} + + +/** + * @brief shell获取命令描述 + * + * @param command 命令 + * @return const char* 命令描述 + */ +static const char* shellGetCommandDesc(ShellCommand *command) +{ + if (command->attr.attrs.type <= SHELL_TYPE_CMD_FUNC) + { + return command->data.cmd.desc; + } + else if (command->attr.attrs.type <= SHELL_TYPE_VAR_NODE) + { + return command->data.var.desc; + } + else if (command->attr.attrs.type <= SHELL_TYPE_USER) + { + return command->data.user.desc; + } + else + { + return command->data.key.desc; + } +} + +/** + * @brief shell 列出命令条目 + * + * @param shell shell对象 + * @param item 命令条目 + */ +void shellListItem(Shell *shell, ShellCommand *item) +{ + short spaceLength; + + spaceLength = 22 - shellWriteString(shell, shellGetCommandName(item)); + spaceLength = (spaceLength > 0) ? spaceLength : 4; + do { + shellWriteByte(shell, ' '); + } while (--spaceLength); + if (item->attr.attrs.type <= SHELL_TYPE_CMD_FUNC) + { + shellWriteString(shell, shellText[SHELL_TEXT_TYPE_CMD]); + } + else if (item->attr.attrs.type <= SHELL_TYPE_VAR_NODE) + { + shellWriteString(shell, shellText[SHELL_TEXT_TYPE_VAR]); + } + else if (item->attr.attrs.type <= SHELL_TYPE_USER) + { + shellWriteString(shell, shellText[SHELL_TEXT_TYPE_USER]); + } + else if (item->attr.attrs.type <= SHELL_TYPE_KEY) + { + shellWriteString(shell, shellText[SHELL_TEXT_TYPE_KEY]); + } + else + { + shellWriteString(shell, shellText[SHELL_TEXT_TYPE_NONE]); + } +#if SHELL_HELP_SHOW_PERMISSION == 1 + shellWriteString(shell, " "); + for (signed char i = 7; i >= 0; i--) + { + shellWriteByte(shell, item->attr.attrs.permission & (1 << i) ? 'x' : '-'); + } +#endif + shellWriteString(shell, " "); + shellWriteCommandDesc(shell, shellGetCommandDesc(item)); + shellWriteString(shell, "\r\n"); +} + + +/** + * @brief shell列出可执行命令 + * + * @param shell shell对象 + */ +void shellListCommand(Shell *shell) +{ + ShellCommand *base = (ShellCommand *)shell->commandList.base; + shellWriteString(shell, shellText[SHELL_TEXT_CMD_LIST]); + for (short i = 0; i < shell->commandList.count; i++) + { + if (base[i].attr.attrs.type <= SHELL_TYPE_CMD_FUNC + && shellCheckPermission(shell, &base[i]) == 0) + { + shellListItem(shell, &base[i]); + } + } +} + + +/** + * @brief shell列出变量 + * + * @param shell shell对象 + */ +void shellListVar(Shell *shell) +{ + ShellCommand *base = (ShellCommand *)shell->commandList.base; + shellWriteString(shell, shellText[SHELL_TEXT_VAR_LIST]); + for (short i = 0; i < shell->commandList.count; i++) + { + if (base[i].attr.attrs.type > SHELL_TYPE_CMD_FUNC + && base[i].attr.attrs.type <= SHELL_TYPE_VAR_NODE + && shellCheckPermission(shell, &base[i]) == 0) + { + shellListItem(shell, &base[i]); + } + } +} + + +/** + * @brief shell列出用户 + * + * @param shell shell对象 + */ +void shellListUser(Shell *shell) +{ + ShellCommand *base = (ShellCommand *)shell->commandList.base; + shellWriteString(shell, shellText[SHELL_TEXT_USER_LIST]); + for (short i = 0; i < shell->commandList.count; i++) + { + if (base[i].attr.attrs.type > SHELL_TYPE_VAR_NODE + && base[i].attr.attrs.type <= SHELL_TYPE_USER + && shellCheckPermission(shell, &base[i]) == 0) + { + shellListItem(shell, &base[i]); + } + } +} + + +/** + * @brief shell列出按键 + * + * @param shell shell对象 + */ +void shellListKey(Shell *shell) +{ + ShellCommand *base = (ShellCommand *)shell->commandList.base; + shellWriteString(shell, shellText[SHELL_TEXT_KEY_LIST]); + for (short i = 0; i < shell->commandList.count; i++) + { + if (base[i].attr.attrs.type > SHELL_TYPE_USER + && base[i].attr.attrs.type <= SHELL_TYPE_KEY + && shellCheckPermission(shell, &base[i]) == 0) + { + shellListItem(shell, &base[i]); + } + } +} + + +/** + * @brief shell列出所有命令 + * + * @param shell shell对象 + */ +void shellListAll(Shell *shell) +{ +#if SHELL_HELP_LIST_USER == 1 + shellListUser(shell); +#endif + shellListCommand(shell); +#if SHELL_HELP_LIST_VAR == 1 + shellListVar(shell); +#endif +#if SHELL_HELP_LIST_KEY == 1 + shellListKey(shell); +#endif +} + + +/** + * @brief shell删除命令行数据 + * + * @param shell shell对象 + * @param length 删除长度 + */ +void shellDeleteCommandLine(Shell *shell, unsigned char length) +{ + while (length--) + { + shellWriteString(shell, "\b \b"); + } +} + + +/** + * @brief shell 清空命令行输入 + * + * @param shell shell对象 + */ +void shellClearCommandLine(Shell *shell) +{ + for (short i = shell->parser.length - shell->parser.cursor; i > 0; i--) + { + shellWriteByte(shell, ' '); + } + shellDeleteCommandLine(shell, shell->parser.length); +} + + +/** + * @brief shell插入一个字符到光标位置 + * + * @param shell shell对象 + * @param data 字符数据 + */ +void shellInsertByte(Shell *shell, char data) +{ + /* 判断输入数据是否过长 */ + if (shell->parser.length >= shell->parser.bufferSize - 1) + { + shellWriteString(shell, shellText[SHELL_TEXT_CMD_TOO_LONG]); + shellWritePrompt(shell, 1); + shellWriteString(shell, shell->parser.buffer); + return; + } + + /* 插入数据 */ + if (shell->parser.cursor == shell->parser.length) + { + shell->parser.buffer[shell->parser.length++] = data; + shell->parser.buffer[shell->parser.length] = 0; + shell->parser.cursor++; + shellWriteByte(shell, data); + } + else if (shell->parser.cursor < shell->parser.length) + { + for (short i = shell->parser.length - shell->parser.cursor; i > 0; i--) + { + shell->parser.buffer[shell->parser.cursor + i] = + shell->parser.buffer[shell->parser.cursor + i - 1]; + } + shell->parser.buffer[shell->parser.cursor++] = data; + shell->parser.buffer[++shell->parser.length] = 0; + for (short i = shell->parser.cursor - 1; i < shell->parser.length; i++) + { + shellWriteByte(shell, shell->parser.buffer[i]); + } + for (short i = shell->parser.length - shell->parser.cursor; i > 0; i--) + { + shellWriteByte(shell, '\b'); + } + } +} + + +/** + * @brief shell 删除字节 + * + * @param shell shell对象 + * @param direction 删除方向 {@code 1}删除光标前字符 {@code -1}删除光标处字符 + */ +void shellDeleteByte(Shell *shell, signed char direction) +{ + char offset = (direction == -1) ? 1 : 0; + + if ((shell->parser.cursor == 0 && direction == 1) + || (shell->parser.cursor == shell->parser.length && direction == -1)) + { + return; + } + if (shell->parser.cursor == shell->parser.length && direction == 1) + { + shell->parser.cursor--; + shell->parser.length--; + shell->parser.buffer[shell->parser.length] = 0; + shellDeleteCommandLine(shell, 1); + } + else + { + for (short i = offset; i < shell->parser.length - shell->parser.cursor; i++) + { + shell->parser.buffer[shell->parser.cursor + i - 1] = + shell->parser.buffer[shell->parser.cursor + i]; + } + shell->parser.length--; + if (!offset) + { + shell->parser.cursor--; + shellWriteByte(shell, '\b'); + } + shell->parser.buffer[shell->parser.length] = 0; + for (short i = shell->parser.cursor; i < shell->parser.length; i++) + { + shellWriteByte(shell, shell->parser.buffer[i]); + } + shellWriteByte(shell, ' '); + for (short i = shell->parser.length - shell->parser.cursor + 1; i > 0; i--) + { + shellWriteByte(shell, '\b'); + } + } +} + + +/** + * @brief shell 解析参数 + * + * @param shell shell对象 + */ +static void shellParserParam(Shell *shell) +{ + unsigned char quotes = 0; + unsigned char record = 1; + + for (short i = 0; i < SHELL_PARAMETER_MAX_NUMBER; i++) + { + shell->parser.param[i] = NULL; + } + + shell->parser.paramCount = 0; + for (unsigned short i = 0; i < shell->parser.length; i++) + { + if (quotes != 0 + || (shell->parser.buffer[i] != ' ' + && shell->parser.buffer[i] != 0)) + { + if (shell->parser.buffer[i] == '\"') + { + quotes = quotes ? 0 : 1; + } + if (record == 1) + { + if (shell->parser.paramCount < SHELL_PARAMETER_MAX_NUMBER) + { + shell->parser.param[shell->parser.paramCount++] = + &(shell->parser.buffer[i]); + } + record = 0; + } + if (shell->parser.buffer[i] == '\\' + && shell->parser.buffer[i + 1] != 0) + { + i++; + } + } + else + { + shell->parser.buffer[i] = 0; + record = 1; + } + } +} + + +/** + * @brief shell去除字符串参数头尾的双引号 + * + * @param shell shell对象 + */ +static void shellRemoveParamQuotes(Shell *shell) +{ + unsigned short paramLength; + for (unsigned short i = 0; i < shell->parser.paramCount; i++) + { + if (shell->parser.param[i][0] == '\"') + { + shell->parser.param[i][0] = 0; + shell->parser.param[i] = &shell->parser.param[i][1]; + } + paramLength = strlen(shell->parser.param[i]); + if (shell->parser.param[i][paramLength - 1] == '\"') + { + shell->parser.param[i][paramLength - 1] = 0; + } + } +} + + +/** + * @brief shell匹配命令 + * + * @param shell shell对象 + * @param cmd 命令 + * @param base 匹配命令表基址 + * @param compareLength 匹配字符串长度 + * @return ShellCommand* 匹配到的命令 + */ +ShellCommand* shellSeekCommand(Shell *shell, + const char *cmd, + ShellCommand *base, + unsigned short compareLength) +{ + const char *name; + unsigned short count = shell->commandList.count - + ((int)base - (int)shell->commandList.base) / sizeof(ShellCommand); + for (unsigned short i = 0; i < count; i++) + { + if (base[i].attr.attrs.type == SHELL_TYPE_KEY + || shellCheckPermission(shell, &base[i]) != 0) + { + continue; + } + name = shellGetCommandName(&base[i]); + if (!compareLength) + { + if (strcmp(cmd, name) == 0) + { + return &base[i]; + } + } + else + { + if (strncmp(cmd, name, compareLength) == 0) + { + return &base[i]; + } + } + } + return NULL; +} + + +/** + * @brief shell 获取变量值 + * + * @param shell shell对象 + * @param command 命令 + * @return int 变量值 + */ +int shellGetVarValue(Shell *shell, ShellCommand *command) +{ + int value = 0; + switch (command->attr.attrs.type) + { + case SHELL_TYPE_VAR_INT: + value = *((int *)(command->data.var.value)); + break; + case SHELL_TYPE_VAR_SHORT: + value = *((short *)(command->data.var.value)); + break; + case SHELL_TYPE_VAR_CHAR: + value = *((char *)(command->data.var.value)); + break; + case SHELL_TYPE_VAR_STRING: + case SHELL_TYPE_VAR_POINT: + value = (int)(command->data.var.value); + break; + case SHELL_TYPE_VAR_NODE: + value = ((ShellNodeVarAttr *)command->data.var.value)->get ? + ((ShellNodeVarAttr *)command->data.var.value) + ->get(((ShellNodeVarAttr *)command->data.var.value)->var) : 0; + break; + default: + break; + } + return value; +} + + +/** + * @brief shell设置变量值 + * + * @param shell shell对象 + * @param command 命令 + * @param value 值 + * @return int 返回变量值 + */ +int shellSetVarValue(Shell *shell, ShellCommand *command, int value) +{ + if (command->attr.attrs.readOnly) + { + shellWriteString(shell, shellText[SHELL_TEXT_VAR_READ_ONLY_CANNOT_MODIFY]); + } + else + { + switch (command->attr.attrs.type) + { + case SHELL_TYPE_VAR_INT: + *((int *)(command->data.var.value)) = value; + break; + case SHELL_TYPE_VAR_SHORT: + *((short *)(command->data.var.value)) = value; + break; + case SHELL_TYPE_VAR_CHAR: + *((char *)(command->data.var.value)) = value; + break; + case SHELL_TYPE_VAR_STRING: + shellStringCopy(((char *)(command->data.var.value)), (char *)value); + break; + case SHELL_TYPE_VAR_POINT: + shellWriteString(shell, shellText[SHELL_TEXT_POINT_CANNOT_MODIFY]); + break; + case SHELL_TYPE_VAR_NODE: + if (((ShellNodeVarAttr *)command->data.var.value)->set) + { + if (((ShellNodeVarAttr *)command->data.var.value)->var) + { + ((ShellNodeVarAttr *)command->data.var.value) + ->set(((ShellNodeVarAttr *)command->data.var.value)->var, value); + } + else + { + ((ShellNodeVarAttr *)command->data.var.value)->set(value); + } + } + break; + default: + break; + } + } + return shellShowVar(shell, command); +} + + +/** + * @brief shell变量输出 + * + * @param shell shell对象 + * @param command 命令 + * @return int 返回变量值 + */ +static int shellShowVar(Shell *shell, ShellCommand *command) +{ + char buffer[12] = "00000000000"; + int value = shellGetVarValue(shell, command); + + shellWriteString(shell, command->data.var.name); + shellWriteString(shell, " = "); + + switch (command->attr.attrs.type) + { + case SHELL_TYPE_VAR_STRING: + shellWriteString(shell, "\""); + shellWriteString(shell, (char *)value); + shellWriteString(shell, "\""); + break; + // case SHELL_TYPE_VAR_INT: + // case SHELL_TYPE_VAR_SHORT: + // case SHELL_TYPE_VAR_CHAR: + // case SHELL_TYPE_VAR_POINT: + default: + shellWriteString(shell, &buffer[11 - shellToDec(value, buffer)]); + shellWriteString(shell, ", 0x"); + for (short i = 0; i < 11; i++) + { + buffer[i] = '0'; + } + shellToHex(value, buffer); + shellWriteString(shell, buffer); + break; + } + + shellWriteString(shell, "\r\n"); + return value; +} + + +/** + * @brief shell设置变量 + * + * @param name 变量名 + * @param value 变量值 + * @return int 返回变量值 + */ +int shellSetVar(char *name, int value) +{ + Shell *shell = shellGetCurrent(); + if (shell == NULL) + { + return 0; + } + ShellCommand *command = shellSeekCommand(shell, + name, + shell->commandList.base, + 0); + if (!command) + { + shellWriteString(shell, shellText[SHELL_TEXT_VAR_NOT_FOUND]); + return 0; + } + if (command->attr.attrs.type < SHELL_TYPE_VAR_INT + || command->attr.attrs.type > SHELL_TYPE_VAR_NODE) + { + shellWriteString(shell, name); + shellWriteString(shell, shellText[SHELL_TEXT_NOT_VAR]); + return 0; + } + return shellSetVarValue(shell, command, value); +} +SHELL_EXPORT_CMD( +SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)|SHELL_CMD_DISABLE_RETURN, +setVar, shellSetVar, set var); + + +/** + * @brief shell运行命令 + * + * @param shell shell对象 + * @param command 命令 + * + * @return unsigned int 命令返回值 + */ +unsigned int shellRunCommand(Shell *shell, ShellCommand *command) +{ + int returnValue = 0; + shell->status.isActive = 1; + if (command->attr.attrs.type == SHELL_TYPE_CMD_MAIN) + { + shellRemoveParamQuotes(shell); + returnValue = command->data.cmd.function(shell->parser.paramCount, + shell->parser.param); + if (!command->attr.attrs.disableReturn) + { + shellWriteReturnValue(shell, returnValue); + } + } + else if (command->attr.attrs.type == SHELL_TYPE_CMD_FUNC) + { + returnValue = shellExtRun(shell, + command, + shell->parser.paramCount, + shell->parser.param); + if (!command->attr.attrs.disableReturn) + { + shellWriteReturnValue(shell, returnValue); + } + } + else if (command->attr.attrs.type >= SHELL_TYPE_VAR_INT + && command->attr.attrs.type <= SHELL_TYPE_VAR_NODE) + { + shellShowVar(shell, command); + } + else if (command->attr.attrs.type == SHELL_TYPE_USER) + { + shellSetUser(shell, command); + } + shell->status.isActive = 0; + + return returnValue; +} + + +/** + * @brief shell校验密码 + * + * @param shell shell对象 + */ +static void shellCheckPassword(Shell *shell) +{ + if (strcmp(shell->parser.buffer, shell->info.user->data.user.password) == 0) + { + shell->status.isChecked = 1; + #if SHELL_SHOW_INFO == 1 + shellWriteString(shell, shellText[SHELL_TEXT_INFO]); + #endif + } + else + { + shellWriteString(shell, shellText[SHELL_TEXT_PASSWORD_ERROR]); + } + shell->parser.length = 0; + shell->parser.cursor = 0; +} + + +/** + * @brief shell设置用户 + * + * @param shell shell对象 + * @param user 用户 + */ +void shellSetUser(Shell *shell, const ShellCommand *user) +{ + shell->info.user = user; + shell->status.isChecked = + ((user->data.user.password && strlen(user->data.user.password) != 0) + && (shell->parser.paramCount < 2 + || strcmp(user->data.user.password, shell->parser.param[1]) != 0)) + ? 0 : 1; + +#if SHELL_CLS_WHEN_LOGIN == 1 + shellWriteString(shell, shellText[SHELL_TEXT_CLEAR_CONSOLE]); +#endif +#if SHELL_SHOW_INFO == 1 + if (shell->status.isChecked) + { + shellWriteString(shell, shellText[SHELL_TEXT_INFO]); + } +#endif +} + + +/** + * @brief shell写返回值 + * + * @param shell shell对象 + * @param value 返回值 + */ +static void shellWriteReturnValue(Shell *shell, int value) +{ + char buffer[12] = "00000000000"; + shellWriteString(shell, "Return: "); + shellWriteString(shell, &buffer[11 - shellToDec(value, buffer)]); + shellWriteString(shell, ", 0x"); + for (short i = 0; i < 11; i++) + { + buffer[i] = '0'; + } + shellToHex(value, buffer); + shellWriteString(shell, buffer); + shellWriteString(shell, "\r\n"); +#if SHELL_KEEP_RETURN_VALUE == 1 + shell->info.retVal = value; +#endif +} + + +#if SHELL_HISTORY_MAX_NUMBER > 0 +/** + * @brief shell历史记录添加 + * + * @param shell shell对象 + */ +static void shellHistoryAdd(Shell *shell) +{ + shell->history.offset = 0; + if (shell->history.number > 0 + && strcmp(shell->history.item[(shell->history.record == 0 ? + SHELL_HISTORY_MAX_NUMBER : shell->history.record) - 1], + shell->parser.buffer) == 0) + { + return; + } + if (shellStringCopy(shell->history.item[shell->history.record], + shell->parser.buffer) != 0) + { + shell->history.record++; + } + if (++shell->history.number > SHELL_HISTORY_MAX_NUMBER) + { + shell->history.number = SHELL_HISTORY_MAX_NUMBER; + } + if (shell->history.record >= SHELL_HISTORY_MAX_NUMBER) + { + shell->history.record = 0; + } +} + + +/** + * @brief shell历史记录查找 + * + * @param shell shell对象 + * @param dir 方向 {@code <0}往上查找 {@code >0}往下查找 + */ +static void shellHistory(Shell *shell, signed char dir) +{ + if (dir > 0) + { + if (shell->history.offset-- <= + -((shell->history.number > shell->history.record) ? + shell->history.number : shell->history.record)) + { + shell->history.offset = -((shell->history.number > shell->history.record) + ? shell->history.number : shell->history.record); + } + } + else if (dir < 0) + { + if (++shell->history.offset > 0) + { + shell->history.offset = 0; + return; + } + } + else + { + return; + } + shellClearCommandLine(shell); + if (shell->history.offset == 0) + { + shell->parser.cursor = shell->parser.length = 0; + } + else + { + if ((shell->parser.length = shellStringCopy(shell->parser.buffer, + shell->history.item[(shell->history.record + SHELL_HISTORY_MAX_NUMBER + + shell->history.offset) % SHELL_HISTORY_MAX_NUMBER])) == 0) + { + return; + } + shell->parser.cursor = shell->parser.length; + shellWriteString(shell, shell->parser.buffer); + } + +} +#endif /** SHELL_HISTORY_MAX_NUMBER > 0 */ + + +/** + * @brief shell 常规输入 + * + * @param shell shell 对象 + * @param data 输入字符 + */ +void shellNormalInput(Shell *shell, char data) +{ + shell->status.tabFlag = 0; + shellInsertByte(shell, data); +} + + +/** + * @brief shell运行命令 + * + * @param shell shell对象 + */ +void shellExec(Shell *shell) +{ + + if (shell->parser.length == 0) + { + return; + } + + shell->parser.buffer[shell->parser.length] = 0; + + if (shell->status.isChecked) + { + #if SHELL_HISTORY_MAX_NUMBER > 0 + shellHistoryAdd(shell); + #endif /** SHELL_HISTORY_MAX_NUMBER > 0 */ + shellParserParam(shell); + shell->parser.length = shell->parser.cursor = 0; + if (shell->parser.paramCount == 0) + { + return; + } + shellWriteString(shell, "\r\n"); + + ShellCommand *command = shellSeekCommand(shell, + shell->parser.param[0], + shell->commandList.base, + 0); + if (command != NULL) + { + shellRunCommand(shell, command); + } + else + { + shellWriteString(shell, shellText[SHELL_TEXT_CMD_NOT_FOUND]); + } + } + else + { + shellCheckPassword(shell); + } +} + + +#if SHELL_HISTORY_MAX_NUMBER > 0 +/** + * @brief shell上方向键输入 + * + * @param shell shell对象 + */ +void shellUp(Shell *shell) +{ + shellHistory(shell, 1); +} +SHELL_EXPORT_KEY(SHELL_CMD_PERMISSION(0), 0x1B5B4100, shellUp, up); + + +/** + * @brief shell下方向键输入 + * + * @param shell shell对象 + */ +void shellDown(Shell *shell) +{ + shellHistory(shell, -1); +} +SHELL_EXPORT_KEY(SHELL_CMD_PERMISSION(0), 0x1B5B4200, shellDown, down); +#endif /** SHELL_HISTORY_MAX_NUMBER > 0 */ + + +/** + * @brief shell右方向键输入 + * + * @param shell shell对象 + */ +void shellRight(Shell *shell) +{ + if (shell->parser.cursor < shell->parser.length) + { + shellWriteByte(shell, shell->parser.buffer[shell->parser.cursor++]); + } +} +SHELL_EXPORT_KEY(SHELL_CMD_PERMISSION(0)|SHELL_CMD_ENABLE_UNCHECKED, +0x1B5B4300, shellRight, right); + + +/** + * @brief shell左方向键输入 + * + * @param shell shell对象 + */ +void shellLeft(Shell *shell) +{ + if (shell->parser.cursor > 0) + { + shellWriteByte(shell, '\b'); + shell->parser.cursor--; + } +} +SHELL_EXPORT_KEY(SHELL_CMD_PERMISSION(0)|SHELL_CMD_ENABLE_UNCHECKED, +0x1B5B4400, shellLeft, left); + + +/** + * @brief shell Tab按键处理 + * + * @param shell shell对象 + */ +void shellTab(Shell *shell) +{ + unsigned short maxMatch = shell->parser.bufferSize; + unsigned short lastMatchIndex = 0; + unsigned short matchNum = 0; + unsigned short length; + + if (shell->parser.length == 0) + { + shellListAll(shell); + shellWritePrompt(shell, 1); + } + else if (shell->parser.length > 0) + { + shell->parser.buffer[shell->parser.length] = 0; + ShellCommand *base = (ShellCommand *)shell->commandList.base; + for (short i = 0; i < shell->commandList.count; i++) + { + if (shellCheckPermission(shell, &base[i]) == 0 + && shellStringCompare(shell->parser.buffer, + (char *)shellGetCommandName(&base[i])) + == shell->parser.length) + { + if (matchNum != 0) + { + if (matchNum == 1) + { + shellWriteString(shell, "\r\n"); + } + shellListItem(shell, &base[lastMatchIndex]); + length = + shellStringCompare((char *)shellGetCommandName(&base[lastMatchIndex]), + (char *)shellGetCommandName(&base[i])); + maxMatch = (maxMatch > length) ? length : maxMatch; + } + lastMatchIndex = i; + matchNum++; + } + } + if (matchNum == 0) + { + return; + } + if (matchNum == 1) + { + shellClearCommandLine(shell); + } + if (matchNum != 0) + { + shell->parser.length = + shellStringCopy(shell->parser.buffer, + (char *)shellGetCommandName(&base[lastMatchIndex])); + } + if (matchNum > 1) + { + shellListItem(shell, &base[lastMatchIndex]); + shellWritePrompt(shell, 1); + shell->parser.length = maxMatch; + } + shell->parser.buffer[shell->parser.length] = 0; + shell->parser.cursor = shell->parser.length; + shellWriteString(shell, shell->parser.buffer); + } + + if (SHELL_GET_TICK()) + { + if (matchNum == 1 + && shell->status.tabFlag + && SHELL_GET_TICK() - shell->info.activeTime < SHELL_DOUBLE_CLICK_TIME) + { + #if SHELL_QUICK_HELP == 1 + shellWriteString(shell, "\r\n"); + shellWriteCommandHelp(shell, shell->parser.buffer); + shellWritePrompt(shell, 1); + shellWriteString(shell, shell->parser.buffer); + #else + shellClearCommandLine(shell); + for (short i = shell->parser.length; i >= 0; i--) + { + shell->parser.buffer[i + 5] = shell->parser.buffer[i]; + } + shellStringCopy(shell->parser.buffer, "help"); + shell->parser.buffer[4] = ' '; + shell->parser.length += 5; + shell->parser.cursor = shell->parser.length; + shellWriteString(shell, shell->parser.buffer); + #endif + } + else + { + shell->status.tabFlag = 1; + } + } +} +SHELL_EXPORT_KEY(SHELL_CMD_PERMISSION(0), 0x09000000, shellTab, tab); + + +/** + * @brief shell 退格 + * + * @param shell shell对象 + */ +void shellBackspace(Shell *shell) +{ + shellDeleteByte(shell, 1); +} +SHELL_EXPORT_KEY(SHELL_CMD_PERMISSION(0)|SHELL_CMD_ENABLE_UNCHECKED, +0x08000000, shellBackspace, backspace); +SHELL_EXPORT_KEY(SHELL_CMD_PERMISSION(0)|SHELL_CMD_ENABLE_UNCHECKED, +0x7F000000, shellBackspace, backspace); + + +/** + * @brief shell 删除 + * + * @param shell shell对象 + */ +void shellDelete(Shell *shell) +{ + shellDeleteByte(shell, -1); +} +SHELL_EXPORT_KEY(SHELL_CMD_PERMISSION(0)|SHELL_CMD_ENABLE_UNCHECKED, +0x1B5B337E, shellDelete, delete); + + +/** + * @brief shell 回车处理 + * + * @param shell shell对象 + */ +void shellEnter(Shell *shell) +{ + shellExec(shell); + shellWritePrompt(shell, 1); +} +#if SHELL_ENTER_LF == 1 +SHELL_EXPORT_KEY(SHELL_CMD_PERMISSION(0)|SHELL_CMD_ENABLE_UNCHECKED, +0x0A000000, shellEnter, enter); +#endif +#if SHELL_ENTER_CR == 1 +SHELL_EXPORT_KEY(SHELL_CMD_PERMISSION(0)|SHELL_CMD_ENABLE_UNCHECKED, +0x0D000000, shellEnter, enter); +#endif +#if SHELL_ENTER_CRLF == 1 +SHELL_EXPORT_KEY(SHELL_CMD_PERMISSION(0)|SHELL_CMD_ENABLE_UNCHECKED, +0x0D0A0000, shellEnter, enter); +#endif + +/** + * @brief shell 写命令帮助信息 + * + * @param shell shell对象 + * @param cmd 命令字符串 + */ +static void shellWriteCommandHelp(Shell *shell, char *cmd) +{ + ShellCommand *command = shellSeekCommand(shell, + cmd, + shell->commandList.base, + 0); + if (command) + { + shellWriteString(shell, shellText[SHELL_TEXT_HELP_HEADER]); + shellWriteString(shell, shellGetCommandName(command)); + shellWriteString(shell, "\r\n"); + shellWriteString(shell, shellGetCommandDesc(command)); + shellWriteString(shell, "\r\n"); + } + else + { + shellWriteString(shell, shellText[SHELL_TEXT_CMD_NOT_FOUND]); + } +} + +/** + * @brief shell help + * + * @param argc 参数个数 + * @param argv 参数 + */ +void shellHelp(int argc, char *argv[]) +{ + Shell *shell = shellGetCurrent(); + SHELL_ASSERT(shell, return); + if (argc == 1) + { + shellListAll(shell); + } + else if (argc > 1) + { + shellWriteCommandHelp(shell, argv[1]); + } +} +SHELL_EXPORT_CMD( +SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN)|SHELL_CMD_DISABLE_RETURN, +help, shellHelp, show command info\r\nhelp [cmd]); + +/** + * @brief shell 输入处理 + * + * @param shell shell对象 + * @param data 输入数据 + */ +void shellHandler(Shell *shell, char data) +{ + SHELL_ASSERT(data, return); + SHELL_LOCK(shell); + +#if SHELL_LOCK_TIMEOUT > 0 + if (shell->info.user->data.user.password + && strlen(shell->info.user->data.user.password) != 0 + && SHELL_GET_TICK()) + { + if (SHELL_GET_TICK() - shell->info.activeTime > SHELL_LOCK_TIMEOUT) + { + shell->status.isChecked = 0; + } + } +#endif + + /* 根据记录的按键键值计算当前字节在按键键值中的偏移 */ + char keyByteOffset = 24; + int keyFilter = 0x00000000; + if ((shell->parser.keyValue & 0x0000FF00) != 0x00000000) + { + keyByteOffset = 0; + keyFilter = 0xFFFFFF00; + } + else if ((shell->parser.keyValue & 0x00FF0000) != 0x00000000) + { + keyByteOffset = 8; + keyFilter = 0xFFFF0000; + } + else if ((shell->parser.keyValue & 0xFF000000) != 0x00000000) + { + keyByteOffset = 16; + keyFilter = 0xFF000000; + } + + /* 遍历ShellCommand列表,尝试进行按键键值匹配 */ + ShellCommand *base = (ShellCommand *)shell->commandList.base; + for (short i = 0; i < shell->commandList.count; i++) + { + /* 判断是否是按键定义并验证权限 */ + if (base[i].attr.attrs.type == SHELL_TYPE_KEY + && shellCheckPermission(shell, &(base[i])) == 0) + { + /* 对输入的字节同按键键值进行匹配 */ + if ((base[i].data.key.value & keyFilter) == shell->parser.keyValue + && (base[i].data.key.value & (0xFF << keyByteOffset)) + == (data << keyByteOffset)) + { + shell->parser.keyValue |= data << keyByteOffset; + data = 0x00; + if (keyByteOffset == 0 + || (base[i].data.key.value & (0xFF << (keyByteOffset - 8))) + == 0x00000000) + { + if (base[i].data.key.function) + { + base[i].data.key.function(shell); + } + shell->parser.keyValue = 0x00000000; + break; + } + } + } + } + + if (data != 0x00) + { + shell->parser.keyValue = 0x00000000; + shellNormalInput(shell, data); + } + + if (SHELL_GET_TICK()) + { + shell->info.activeTime = SHELL_GET_TICK(); + } + SHELL_UNLOCK(shell); +} + + +#if SHELL_SUPPORT_END_LINE == 1 +void shellWriteEndLine(Shell *shell, char *buffer, int len) +{ + SHELL_LOCK(shell); + if (!shell->status.isActive) + { + shellWriteString(shell, shellText[SHELL_TEXT_CLEAR_LINE]); + } + shell->write(buffer, len); + + if (!shell->status.isActive) + { + shellWritePrompt(shell, 0); + if (shell->parser.length > 0) + { + shellWriteString(shell, shell->parser.buffer); + for (short i = 0; i < shell->parser.length - shell->parser.cursor; i++) + { + shellWriteByte(shell, '\b'); + } + } + } + SHELL_UNLOCK(shell); +} +#endif /** SHELL_SUPPORT_END_LINE == 1 */ + + +/** + * @brief shell 任务 + * + * @param param 参数(shell对象) + * + */ +void shellTask(void *param) +{ + Shell *shell = (Shell *)param; + char data; +#if SHELL_TASK_WHILE == 1 + while(1) + { +#endif + if (shell->read && shell->read(&data, 1) == 1) + { + shellHandler(shell, data); + } +#if SHELL_TASK_WHILE == 1 + } +#endif +} + + +/** + * @brief shell 输出用户列表(shell调用) + */ +void shellUsers(void) +{ + Shell *shell = shellGetCurrent(); + if (shell) + { + shellListUser(shell); + } +} +SHELL_EXPORT_CMD( +SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)|SHELL_CMD_DISABLE_RETURN, +users, shellUsers, list all user); + + +/** + * @brief shell 输出命令列表(shell调用) + */ +void shellCmds(void) +{ + Shell *shell = shellGetCurrent(); + if (shell) + { + shellListCommand(shell); + } +} +SHELL_EXPORT_CMD( +SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)|SHELL_CMD_DISABLE_RETURN, +cmds, shellCmds, list all cmd); + + +/** + * @brief shell 输出变量列表(shell调用) + */ +void shellVars(void) +{ + Shell *shell = shellGetCurrent(); + if (shell) + { + shellListVar(shell); + } +} +SHELL_EXPORT_CMD( +SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)|SHELL_CMD_DISABLE_RETURN, +vars, shellVars, list all var); + + +/** + * @brief shell 输出按键列表(shell调用) + */ +void shellKeys(void) +{ + Shell *shell = shellGetCurrent(); + if (shell) + { + shellListKey(shell); + } +} +SHELL_EXPORT_CMD( +SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)|SHELL_CMD_DISABLE_RETURN, +keys, shellKeys, list all key); + + +/** + * @brief shell 清空控制台(shell调用) + */ +void shellClear(void) +{ + Shell *shell = shellGetCurrent(); + if (shell) + { + shellWriteString(shell, shellText[SHELL_TEXT_CLEAR_CONSOLE]); + } +} +SHELL_EXPORT_CMD( +SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)|SHELL_CMD_DISABLE_RETURN, +clear, shellClear, clear console); + + +/** + * @brief shell执行命令 + * + * @param shell shell对象 + * @param cmd 命令字符串 + * @return int 返回值 + */ +int shellRun(Shell *shell, const char *cmd) +{ + SHELL_ASSERT(shell && cmd, return -1); + char active = shell->status.isActive; + if (strlen(cmd) > shell->parser.bufferSize - 1) + { + shellWriteString(shell, shellText[SHELL_TEXT_CMD_TOO_LONG]); + return -1; + } + else + { + shell->parser.length = shellStringCopy(shell->parser.buffer, (char *)cmd); + shellExec(shell); + shell->status.isActive = active; + return 0; + } +} + + +#if SHELL_EXEC_UNDEF_FUNC == 1 +/** + * @brief shell执行未定义函数 + * + * @param argc 参数个数 + * @param argv 参数 + * @return int 返回值 + */ +int shellExecute(int argc, char *argv[]) +{ + Shell *shell = shellGetCurrent(); + if (shell && argc >= 2) + { + int (*func)() = (int (*)())shellExtParsePara(shell, argv[1]); + ShellCommand command = { + .attr.value = SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC) + |SHELL_CMD_DISABLE_RETURN, + .data.cmd.function = func, + }; + return shellExtRun(shell, &command, argc - 1, &argv[1]); + } + else + { + shellWriteString(shell, shellText[SHELL_TEXT_PARAM_ERROR]); + return -1; + } +} +SHELL_EXPORT_CMD( +SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN)|SHELL_CMD_DISABLE_RETURN, +exec, shellExecute, execute function undefined); +#endif + +#if SHELL_KEEP_RETURN_VALUE == 1 +/** + * @brief shell返回值获取 + * 获取上一次执行的命令的返回值 + * + * @return int 返回值 + */ +static int shellRetValGet() +{ + Shell *shell = shellGetCurrent(); + return shell ? shell->info.retVal : 0; +} +static ShellNodeVarAttr shellRetVal = { + .get = shellRetValGet +}; +SHELL_EXPORT_VAR(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_VAR_NODE)|SHELL_CMD_READ_ONLY, +RETVAL, &shellRetVal, return value of last command); +#endif /** SHELL_KEEP_RETURN_VALUE == 1 */ + +static void _prompt(int argc, char **argv) +{ + for (short i = 0; i < SHELL_MAX_NUMBER; i++) + { + if (shellList[i] != NULL) + { + shellWriteString(shellList[i], shellText[SHELL_TEXT_INFO]); + return; + } + } + +} + +SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN), prompt, _prompt, show prompt info); diff --git a/main/utilities/letter_shell/src/shell.h b/main/utilities/letter_shell/src/shell.h new file mode 100644 index 0000000..c08bcc2 --- /dev/null +++ b/main/utilities/letter_shell/src/shell.h @@ -0,0 +1,472 @@ +/** + * @file shell.h + * @author Letter (NevermindZZT@gmail.com) + * @brief letter shell + * @version 3.0.0 + * @date 2019-12-30 + * + * @copyright (c) 2020 Letter + * + */ + +#ifndef __SHELL_H__ +#define __SHELL_H__ + +#include "shell_cfg.h" + +#define SHELL_VERSION "3.1.2" /**< 版本号 */ + + +/** + * @brief shell 断言 + * + * @param expr 表达式 + * @param action 断言失败操作 + */ +#define SHELL_ASSERT(expr, action) \ + if (!(expr)) { \ + action; \ + } + +#if SHELL_USING_LOCK == 1 +#define SHELL_LOCK(shell) shell->lock(shell) +#define SHELL_UNLOCK(shell) shell->unlock(shell) +#else +#define SHELL_LOCK(shell) +#define SHELL_UNLOCK(shell) +#endif /** SHELL_USING_LOCK == 1 */ +/** + * @brief shell 命令权限 + * + * @param permission 权限级别 + */ +#define SHELL_CMD_PERMISSION(permission) \ + (permission & 0x000000FF) + +/** + * @brief shell 命令类型 + * + * @param type 类型 + */ +#define SHELL_CMD_TYPE(type) \ + ((type & 0x0000000F) << 8) + +/** + * @brief 使能命令在未校验密码的情况下使用 + */ +#define SHELL_CMD_ENABLE_UNCHECKED \ + (1 << 12) + +/** + * @brief 禁用返回值打印 + */ +#define SHELL_CMD_DISABLE_RETURN \ + (1 << 13) + +/** + * @brief 只读属性(仅对变量生效) + */ +#define SHELL_CMD_READ_ONLY \ + (1 << 14) + +/** + * @brief 命令参数数量 + */ +#define SHELL_CMD_PARAM_NUM(num) \ + ((num & 0x0000000F)) << 16 + +#ifndef SHELL_SECTION + #if defined(__CC_ARM) || defined(__CLANG_ARM) + #define SHELL_SECTION(x) __attribute__((section(x))) + #elif defined (__IAR_SYSTEMS_ICC__) + #define SHELL_SECTION(x) @ x + #elif defined(__GNUC__) + #define SHELL_SECTION(x) __attribute__((section(x))) + #else + #define SHELL_SECTION(x) + #endif +#endif + +#ifndef SHELL_USED + #if defined(__CC_ARM) || defined(__CLANG_ARM) + #define SHELL_USED __attribute__((used)) + #elif defined (__IAR_SYSTEMS_ICC__) + #define SHELL_USED __root + #elif defined(__GNUC__) + #define SHELL_USED __attribute__((used)) + #else + #define SHELL_USED + #endif +#endif + +/** + * @brief shell float型参数转换 + */ +#define SHELL_PARAM_FLOAT(x) (*(float *)(&x)) + +/** + * @brief shell 代理函数名 + */ +#define SHELL_AGENCY_FUNC_NAME(_func) agency##_func + +/** + * @brief shell代理函数定义 + * + * @param _func 被代理的函数 + * @param ... 代理参数 + */ +#define SHELL_AGENCY_FUNC(_func, ...) \ + void SHELL_AGENCY_FUNC_NAME(_func)(int p1, int p2, int p3, int p4, int p5, int p6, int p7) \ + { _func(__VA_ARGS__); } + +#if SHELL_USING_CMD_EXPORT == 1 + + /** + * @brief shell 命令定义 + * + * @param _attr 命令属性 + * @param _name 命令名 + * @param _func 命令函数 + * @param _desc 命令描述 + */ + #define SHELL_EXPORT_CMD(_attr, _name, _func, _desc) \ + const char shellCmd##_name[] = #_name; \ + const char shellDesc##_name[] = #_desc; \ + SHELL_USED const ShellCommand \ + shellCommand##_name SHELL_SECTION("shellCommand") = \ + { \ + .attr.value = _attr, \ + .data.cmd.name = shellCmd##_name, \ + .data.cmd.function = (int (*)())_func, \ + .data.cmd.desc = shellDesc##_name \ + } + + /** + * @brief shell 代理命令定义 + * + * @param _attr 命令属性 + * @param _name 命令名 + * @param _func 命令函数 + * @param _desc 命令描述 + * @param ... 代理参数 + */ + #define SHELL_EXPORT_CMD_AGENCY(_attr, _name, _func, _desc, ...) \ + SHELL_AGENCY_FUNC(_func, ##__VA_ARGS__) \ + SHELL_EXPORT_CMD(_attr, _name, SHELL_AGENCY_FUNC_NAME(_func), _desc) + + /** + * @brief shell 变量定义 + * + * @param _attr 变量属性 + * @param _name 变量名 + * @param _value 变量值 + * @param _desc 变量描述 + */ + #define SHELL_EXPORT_VAR(_attr, _name, _value, _desc) \ + const char shellCmd##_name[] = #_name; \ + const char shellDesc##_name[] = #_desc; \ + SHELL_USED const ShellCommand \ + shellVar##_name SHELL_SECTION("shellCommand") = \ + { \ + .attr.value = _attr, \ + .data.var.name = shellCmd##_name, \ + .data.var.value = (void *)_value, \ + .data.var.desc = shellDesc##_name \ + } + + /** + * @brief shell 用户定义 + * + * @param _attr 用户属性 + * @param _name 用户名 + * @param _password 用户密码 + * @param _desc 用户描述 + */ + #define SHELL_EXPORT_USER(_attr, _name, _password, _desc) \ + const char shellCmd##_name[] = #_name; \ + const char shellPassword##_name[] = #_password; \ + const char shellDesc##_name[] = #_desc; \ + SHELL_USED const ShellCommand \ + shellUser##_name SHELL_SECTION("shellCommand") = \ + { \ + .attr.value = _attr|SHELL_CMD_TYPE(SHELL_TYPE_USER), \ + .data.user.name = shellCmd##_name, \ + .data.user.password = shellPassword##_name, \ + .data.user.desc = shellDesc##_name \ + } + + /** + * @brief shell 按键定义 + * + * @param _attr 按键属性 + * @param _value 按键键值 + * @param _func 按键函数 + * @param _desc 按键描述 + */ + #define SHELL_EXPORT_KEY(_attr, _value, _func, _desc) \ + const char shellDesc##_value[] = #_desc; \ + SHELL_USED const ShellCommand \ + shellKey##_value SHELL_SECTION("shellCommand") = \ + { \ + .attr.value = _attr|SHELL_CMD_TYPE(SHELL_TYPE_KEY), \ + .data.key.value = _value, \ + .data.key.function = (void (*)(Shell *))_func, \ + .data.key.desc = shellDesc##_value \ + } + + /** + * @brief shell 代理按键定义 + * + * @param _attr 按键属性 + * @param _value 按键键值 + * @param _func 按键函数 + * @param _desc 按键描述 + * @param ... 代理参数 + */ + #define SHELL_EXPORT_KEY_AGENCY(_attr, _value, _func, _desc, ...) \ + SHELL_AGENCY_FUNC(_func, ##__VA_ARGS__) \ + SHELL_EXPORT_KEY(_attr, _value, SHELL_AGENCY_FUNC_NAME(_func), _desc) +#else + /** + * @brief shell 命令item定义 + * + * @param _attr 命令属性 + * @param _name 命令名 + * @param _func 命令函数 + * @param _desc 命令描述 + */ + #define SHELL_CMD_ITEM(_attr, _name, _func, _desc) \ + { \ + .attr.value = _attr, \ + .data.cmd.name = #_name, \ + .data.cmd.function = (int (*)())_func, \ + .data.cmd.desc = #_desc \ + } + + /** + * @brief shell 变量item定义 + * + * @param _attr 变量属性 + * @param _name 变量名 + * @param _value 变量值 + * @param _desc 变量描述 + */ + #define SHELL_VAR_ITEM(_attr, _name, _value, _desc) \ + { \ + .attr.value = _attr, \ + .data.var.name = #_name, \ + .data.var.value = (void *)_value, \ + .data.var.desc = #_desc \ + } + + /** + * @brief shell 用户item定义 + * + * @param _attr 用户属性 + * @param _name 用户名 + * @param _password 用户密码 + * @param _desc 用户描述 + */ + #define SHELL_USER_ITEM(_attr, _name, _password, _desc) \ + { \ + .attr.value = _attr|SHELL_CMD_TYPE(SHELL_TYPE_USER), \ + .data.user.name = #_name, \ + .data.user.password = #_password, \ + .data.user.desc = #_desc \ + } + + /** + * @brief shell 按键item定义 + * + * @param _attr 按键属性 + * @param _value 按键键值 + * @param _func 按键函数 + * @param _desc 按键描述 + */ + #define SHELL_KEY_ITEM(_attr, _value, _func, _desc) \ + { \ + .attr.value = _attr|SHELL_CMD_TYPE(SHELL_TYPE_KEY), \ + .data.key.value = _value, \ + .data.key.function = (void (*)(Shell *))_func, \ + .data.key.desc = #_desc \ + } + + #define SHELL_EXPORT_CMD(_attr, _name, _func, _desc) + #define SHELL_EXPORT_CMD_AGENCY(_attr, _name, _func, _desc, ...) + #define SHELL_EXPORT_VAR(_attr, _name, _value, _desc) + #define SHELL_EXPORT_USER(_attr, _name, _password, _desc) + #define SHELL_EXPORT_KEY(_attr, _value, _func, _desc) + #define SHELL_EXPORT_KEY_AGENCY(_attr, _name, _func, _desc, ...) +#endif /** SHELL_USING_CMD_EXPORT == 1 */ + +/** + * @brief shell command类型 + */ +typedef enum +{ + SHELL_TYPE_CMD_MAIN = 0, /**< main形式命令 */ + SHELL_TYPE_CMD_FUNC, /**< C函数形式命令 */ + SHELL_TYPE_VAR_INT, /**< int型变量 */ + SHELL_TYPE_VAR_SHORT, /**< short型变量 */ + SHELL_TYPE_VAR_CHAR, /**< char型变量 */ + SHELL_TYPE_VAR_STRING, /**< string型变量 */ + SHELL_TYPE_VAR_POINT, /**< 指针型变量 */ + SHELL_TYPE_VAR_NODE, /**< 节点变量 */ + SHELL_TYPE_USER, /**< 用户 */ + SHELL_TYPE_KEY, /**< 按键 */ +} ShellCommandType; + + +/** + * @brief Shell定义 + */ +typedef struct shell_def +{ + struct + { + const struct shell_command *user; /**< 当前用户 */ + int activeTime; /**< shell激活时间 */ + char *path; /**< 当前shell路径 */ + #if SHELL_USING_COMPANION == 1 + struct shell_companion_object *companions; /**< 伴生对象 */ + #endif + #if SHELL_KEEP_RETURN_VALUE == 1 + int retVal; /**< 返回值 */ + #endif + } info; + struct + { + unsigned short length; /**< 输入数据长度 */ + unsigned short cursor; /**< 当前光标位置 */ + char *buffer; /**< 输入缓冲 */ + char *param[SHELL_PARAMETER_MAX_NUMBER]; /**< 参数 */ + unsigned short bufferSize; /**< 输入缓冲大小 */ + unsigned short paramCount; /**< 参数数量 */ + int keyValue; /**< 输入按键键值 */ + } parser; +#if SHELL_HISTORY_MAX_NUMBER > 0 + struct + { + char *item[SHELL_HISTORY_MAX_NUMBER]; /**< 历史记录 */ + unsigned short number; /**< 历史记录数 */ + unsigned short record; /**< 当前记录位置 */ + signed short offset; /**< 当前历史记录偏移 */ + } history; +#endif /** SHELL_HISTORY_MAX_NUMBER > 0 */ + struct + { + void *base; /**< 命令表基址 */ + unsigned short count; /**< 命令数量 */ + } commandList; + struct + { + unsigned char isChecked : 1; /**< 密码校验通过 */ + unsigned char isActive : 1; /**< 当前活动Shell */ + unsigned char tabFlag : 1; /**< tab标志 */ + } status; + signed short (*read)(char *, unsigned short); /**< shell读函数 */ + signed short (*write)(char *, unsigned short); /**< shell写函数 */ +#if SHELL_USING_LOCK == 1 + int (*lock)(struct shell_def *); /**< shell 加锁 */ + int (*unlock)(struct shell_def *); /**< shell 解锁 */ +#endif +} Shell; + + +/** + * @brief shell command定义 + */ +typedef struct shell_command +{ + union + { + struct + { + unsigned char permission : 8; /**< command权限 */ + ShellCommandType type : 4; /**< command类型 */ + unsigned char enableUnchecked : 1; /**< 在未校验密码的情况下可用 */ + unsigned char disableReturn : 1; /**< 禁用返回值输出 */ + unsigned char readOnly : 1; /**< 只读 */ + unsigned char reserve : 1; /**< 保留 */ + unsigned char paramNum : 4; /**< 参数数量 */ + } attrs; + int value; + } attr; /**< 属性 */ + union + { + struct + { + const char *name; /**< 命令名 */ + int (*function)(); /**< 命令执行函数 */ + const char *desc; /**< 命令描述 */ + } cmd; /**< 命令定义 */ + struct + { + const char *name; /**< 变量名 */ + void *value; /**< 变量值 */ + const char *desc; /**< 变量描述 */ + } var; /**< 变量定义 */ + struct + { + const char *name; /**< 用户名 */ + const char *password; /**< 用户密码 */ + const char *desc; /**< 用户描述 */ + } user; /**< 用户定义 */ + struct + { + int value; /**< 按键键值 */ + void (*function)(Shell *); /**< 按键执行函数 */ + const char *desc; /**< 按键描述 */ + } key; /**< 按键定义 */ + } data; +} ShellCommand; + +/** + * @brief shell节点变量属性 + */ +typedef struct +{ + void *var; /**< 变量引用 */ + int (*get)(); /**< 变量get方法 */ + int (*set)(); /**< 变量set方法 */ +} ShellNodeVarAttr; + + +#define shellSetPath(_shell, _path) (_shell)->info.path = _path +#define shellGetPath(_shell) ((_shell)->info.path) + +#define shellDeInit(shell) shellRemove(shell) + +void shellInit(Shell *shell, char *buffer, unsigned short size); +void shellRemove(Shell *shell); +unsigned short shellWriteString(Shell *shell, const char *string); +void shellPrint(Shell *shell, const char *fmt, ...); +void shellScan(Shell *shell, char *fmt, ...); +Shell* shellGetCurrent(void); +void shellHandler(Shell *shell, char data); +void shellWriteEndLine(Shell *shell, char *buffer, int len); +void shellTask(void *param); +int shellRun(Shell *shell, const char *cmd); + + + +#if SHELL_USING_COMPANION == 1 +/** + * @brief shell伴生对象定义 + */ +typedef struct shell_companion_object +{ + int id; /**< 伴生对象ID */ + void *obj; /**< 伴生对象 */ + struct shell_companion_object *next; /**< 下一个伴生对象 */ +} ShellCompanionObj; + + +signed char shellCompanionAdd(Shell *shell, int id, void *object); +signed char shellCompanionDel(Shell *shell, int id); +void *shellCompanionGet(Shell *shell, int id); +#endif + +#endif + + diff --git a/main/utilities/letter_shell/src/shell_cfg.h b/main/utilities/letter_shell/src/shell_cfg.h new file mode 100644 index 0000000..874043d --- /dev/null +++ b/main/utilities/letter_shell/src/shell_cfg.h @@ -0,0 +1,188 @@ +/** + * @file shell_cfg.h + * @author Letter (nevermindzzt@gmail.com) + * @brief shell config + * @version 3.0.0 + * @date 2019-12-31 + * + * @copyright (c) 2019 Letter + * + */ + +#ifndef __SHELL_CFG_H__ +#define __SHELL_CFG_H__ + + +/** + * @brief 是否使用默认shell任务while循环,使能宏`SHELL_USING_TASK`后此宏有意义 + * 使能此宏,则`shellTask()`函数会一直循环读取输入,一般使用操作系统建立shell + * 任务时使能此宏,关闭此宏的情况下,一般适用于无操作系统,在主循环中调用`shellTask()` + */ +#define SHELL_TASK_WHILE 1 + +/** + * @brief 是否使用命令导出方式 + * 使能此宏后,可以使用`SHELL_EXPORT_CMD()`等导出命令 + * 定义shell命令,关闭此宏的情况下,需要使用命令表的方式 + */ +#define SHELL_USING_CMD_EXPORT 1 + +/** + * @brief 是否使用shell伴生对象 + * 一些扩展的组件(文件系统支持,日志工具等)需要使用伴生对象 + */ +#define SHELL_USING_COMPANION 0 + +/** + * @brief 支持shell尾行模式 + */ +#define SHELL_SUPPORT_END_LINE 0 + +/** + * @brief 是否在输出命令列表中列出用户 + */ +#define SHELL_HELP_LIST_USER 0 + +/** + * @brief 是否在输出命令列表中列出变量 + */ +#define SHELL_HELP_LIST_VAR 0 + +/** + * @brief 是否在输出命令列表中列出按键 + */ +#define SHELL_HELP_LIST_KEY 0 + +/** + * @brief 是否在输出命令列表中展示命令权限 + */ +#define SHELL_HELP_SHOW_PERMISSION 1 + +/** + * @brief 使用LF作为命令行回车触发 + * 可以和SHELL_ENTER_CR同时开启 + */ +#define SHELL_ENTER_LF 1 + +/** + * @brief 使用CR作为命令行回车触发 + * 可以和SHELL_ENTER_LF同时开启 + */ +#define SHELL_ENTER_CR 1 + +/** + * @brief 使用CRLF作为命令行回车触发 + * 不可以和SHELL_ENTER_LF或SHELL_ENTER_CR同时开启 + */ +#define SHELL_ENTER_CRLF 0 + +/** + * @brief 使用执行未导出函数的功能 + * 启用后,可以通过`exec [addr] [args]`直接执行对应地址的函数 + * @attention 如果地址错误,可能会直接引起程序崩溃 + */ +#define SHELL_EXEC_UNDEF_FUNC 0 + +/** + * @brief shell命令参数最大数量 + * 包含命令名在内,超过16个参数并且使用了参数自动转换的情况下,需要修改源码 + */ +#define SHELL_PARAMETER_MAX_NUMBER 8 + +/** + * @brief 历史命令记录数量 + */ +#define SHELL_HISTORY_MAX_NUMBER 5 + +/** + * @brief 双击间隔(ms) + * 使能宏`SHELL_LONG_HELP`后此宏生效,定义双击tab补全help的时间间隔 + */ +#define SHELL_DOUBLE_CLICK_TIME 200 + +/** + * @brief 快速帮助 + * 作用于双击tab的场景,当使能此宏时,双击tab不会对命令进行help补全,而是直接显示对应命令的帮助信息 + */ +#define SHELL_QUICK_HELP 1 + +/** + * @brief 保存命令返回值 + * 开启后会默认定义一个`RETVAL`变量,会保存上一次命令执行的返回值,可以在随后的命令中进行调用 + * 如果命令的`SHELL_CMD_DISABLE_RETURN`标志被设置,则该命令不会更新`RETVAL` + */ +#define SHELL_KEEP_RETURN_VALUE 0 + +/** + * @brief 管理的最大shell数量 + */ +#define SHELL_MAX_NUMBER 5 + +/** + * @brief shell格式化输出的缓冲大小 + * 为0时不使用shell格式化输出 + */ +#define SHELL_PRINT_BUFFER 128 + +/** + * @brief shell格式化输入的缓冲大小 + * 为0时不使用shell格式化输入 + * @note shell格式化输入会阻塞shellTask, 仅适用于在有操作系统的情况下使用 + */ +#define SHELL_SCAN_BUFFER 0 + +/** + * @brief 获取系统时间(ms) + * 定义此宏为获取系统Tick,如`HAL_GetTick()` + * @note 此宏不定义时无法使用双击tab补全命令help,无法使用shell超时锁定 + */ +#define SHELL_GET_TICK() 0 + +/** + * @brief 使用锁 + * @note 使用shell锁时,需要对加锁和解锁进行实现 + */ +#define SHELL_USING_LOCK 0 + +/** + * @brief shell内存分配 + * shell本身不需要此接口,若使用shell伴生对象,需要进行定义 + */ +#define SHELL_MALLOC(size) 0 + +/** + * @brief shell内存释放 + * shell本身不需要此接口,若使用shell伴生对象,需要进行定义 + */ +#define SHELL_FREE(obj) 0 + +/** + * @brief 是否显示shell信息 + */ +#define SHELL_SHOW_INFO 1 + +/** + * @brief 是否在登录后清除命令行 + */ +#define SHELL_CLS_WHEN_LOGIN 1 + +/** + * @brief shell默认用户 + */ +#define SHELL_DEFAULT_USER "letter" + +/** + * @brief shell默认用户密码 + * 若默认用户不需要密码,设为"" + */ +#define SHELL_DEFAULT_USER_PASSWORD "" + +/** + * @brief shell自动锁定超时 + * shell当前用户密码有效的时候生效,超时后会自动重新锁定shell + * 设置为0时关闭自动锁定功能,时间单位为`SHELL_GET_TICK()`单位 + * @note 使用超时锁定必须保证`SHELL_GET_TICK()`有效 + */ +#define SHELL_LOCK_TIMEOUT 0 * 60 * 1000 + +#endif diff --git a/main/utilities/letter_shell/src/shell_cmd_list.c b/main/utilities/letter_shell/src/shell_cmd_list.c new file mode 100644 index 0000000..139a531 --- /dev/null +++ b/main/utilities/letter_shell/src/shell_cmd_list.c @@ -0,0 +1,103 @@ +/** + * @file shell_cmd_list.c + * @author Letter (NevermindZZT@gmail.com) + * @brief shell cmd list + * @version 3.0.0 + * @date 2020-01-17 + * + * @copyright (c) 2020 Letter + * + */ + +#include "shell.h" + +#if SHELL_USING_CMD_EXPORT != 1 + +extern int shellSetVar(char *name, int value); +extern void shellUp(Shell *shell); +extern void shellDown(Shell *shell); +extern void shellRight(Shell *shell); +extern void shellLeft(Shell *shell); +extern void shellTab(Shell *shell); +extern void shellBackspace(Shell *shell); +extern void shellDelete(Shell *shell); +extern void shellEnter(Shell *shell); +extern void shellHelp(int argc, char *argv[]); +extern void shellUsers(void); +extern void shellCmds(void); +extern void shellVars(void); +extern void shellKeys(void); +extern void shellClear(void); +#if SHELL_EXEC_UNDEF_FUNC == 1 +extern int shellExecute(int argc, char *argv[]); +#endif + +SHELL_AGENCY_FUNC(shellRun, shellGetCurrent(), (const char *)p1); + + +/** + * @brief shell命令表 + * + */ +const ShellCommand shellCommandList[] = +{ + {.attr.value=SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_USER), + .data.user.name = SHELL_DEFAULT_USER, + .data.user.password = SHELL_DEFAULT_USER_PASSWORD, + .data.user.desc = "default user"}, + SHELL_CMD_ITEM(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC), + setVar, shellSetVar, set var), + SHELL_KEY_ITEM(SHELL_CMD_PERMISSION(0), 0x1B5B4100, shellUp, up), + SHELL_KEY_ITEM(SHELL_CMD_PERMISSION(0), 0x1B5B4200, shellDown, down), + SHELL_KEY_ITEM(SHELL_CMD_PERMISSION(0)|SHELL_CMD_ENABLE_UNCHECKED, + 0x1B5B4300, shellRight, right), + SHELL_KEY_ITEM(SHELL_CMD_PERMISSION(0)|SHELL_CMD_ENABLE_UNCHECKED, + 0x1B5B4400, shellLeft, left), + SHELL_KEY_ITEM(SHELL_CMD_PERMISSION(0), 0x09000000, shellTab, tab), + SHELL_KEY_ITEM(SHELL_CMD_PERMISSION(0)|SHELL_CMD_ENABLE_UNCHECKED, + 0x08000000, shellBackspace, backspace), + SHELL_KEY_ITEM(SHELL_CMD_PERMISSION(0)|SHELL_CMD_ENABLE_UNCHECKED, + 0x7F000000, shellDelete, delete), + SHELL_KEY_ITEM(SHELL_CMD_PERMISSION(0)|SHELL_CMD_ENABLE_UNCHECKED, + 0x1B5B337E, shellDelete, delete), +#if SHELL_ENTER_LF == 1 + SHELL_KEY_ITEM(SHELL_CMD_PERMISSION(0)|SHELL_CMD_ENABLE_UNCHECKED, + 0x0A000000, shellEnter, enter), +#endif +#if SHELL_ENTER_CR == 1 + SHELL_KEY_ITEM(SHELL_CMD_PERMISSION(0)|SHELL_CMD_ENABLE_UNCHECKED, + 0x0D000000, shellEnter, enter), +#endif +#if SHELL_ENTER_CRLF == 1 + SHELL_KEY_ITEM(SHELL_CMD_PERMISSION(0)|SHELL_CMD_ENABLE_UNCHECKED, + 0x0D0A0000, shellEnter, enter), +#endif + SHELL_CMD_ITEM(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN)|SHELL_CMD_DISABLE_RETURN, + help, shellHelp, show command info\r\nhelp [cmd]), + SHELL_CMD_ITEM(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)|SHELL_CMD_DISABLE_RETURN, + users, shellUsers, list all user), + SHELL_CMD_ITEM(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)|SHELL_CMD_DISABLE_RETURN, + cmds, shellCmds, list all cmd), + SHELL_CMD_ITEM(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)|SHELL_CMD_DISABLE_RETURN, + vars, shellVars, list all var), + SHELL_CMD_ITEM(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)|SHELL_CMD_DISABLE_RETURN, + keys, shellKeys, list all key), + SHELL_CMD_ITEM(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)|SHELL_CMD_DISABLE_RETURN, + clear, shellClear, clear console), + SHELL_CMD_ITEM(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)|SHELL_CMD_DISABLE_RETURN, + sh, SHELL_AGENCY_FUNC_NAME(shellRun), run command directly), +#if SHELL_EXEC_UNDEF_FUNC == 1 + SHELL_CMD_ITEM(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN)|SHELL_CMD_DISABLE_RETURN, + exec, shellExecute, execute function undefined), +#endif +}; + + +/** + * @brief shell命令表大小 + * + */ +const unsigned short shellCommandCount + = sizeof(shellCommandList) / sizeof(ShellCommand); + +#endif diff --git a/main/utilities/letter_shell/src/shell_companion.c b/main/utilities/letter_shell/src/shell_companion.c new file mode 100644 index 0000000..eb494c7 --- /dev/null +++ b/main/utilities/letter_shell/src/shell_companion.c @@ -0,0 +1,87 @@ +/** + * @file shell_companion.c + * @author Letter (nevermindzzt@gmail.com) + * @brief shell companion object support + * @version 3.0.3 + * @date 2020-07-22 + * + * @copyright (c) 2020 Letter + * + */ + #include "shell.h" + +#if SHELL_USING_COMPANION == 1 +/** + * @brief shell添加伴生对象 + * + * @param shell shell对象 + * @param id 伴生对象ID + * @param object 伴生对象 + * @return signed char 0 添加成功 -1 添加失败 + */ +signed char shellCompanionAdd(Shell *shell, int id, void *object) +{ + ShellCompanionObj *companions = shell->info.companions; + ShellCompanionObj *node = SHELL_MALLOC(sizeof(ShellCompanionObj)); + SHELL_ASSERT(node, return -1); + node->id = id; + node->obj = object; + node->next = companions; + shell->info.companions = node; + return 0; +} + +/** + * @brief shell删除伴生对象 + * + * @param shell shell对象 + * @param id 伴生对象ID + * @return signed char 0 删除成功 -1 无匹配对象 + */ +signed char shellCompanionDel(Shell *shell, int id) +{ + ShellCompanionObj *companions = shell->info.companions; + ShellCompanionObj *front = companions; + while (companions) + { + if (companions->id == id) + { + if (companions == shell->info.companions && !(companions->next)) + { + shell->info.companions = (void *)0; + } + else + { + front->next = companions->next; + } + SHELL_FREE(companions); + return 0; + } + front = companions; + companions = companions->next; + } + return -1; +} + +/** + * @brief shell获取伴生对象 + * + * @param shell shell对象 + * @param id 伴生对象ID + * @return void* 伴生对象,无匹配对象时返回NULL + */ +void *shellCompanionGet(Shell *shell, int id) +{ + SHELL_ASSERT(shell, return (void *)0); + ShellCompanionObj *companions = shell->info.companions; + while (companions) + { + if (companions->id == id) + { + return companions->obj; + } + companions = companions->next; + } + return (void *)0; +} +#endif /** SHELL_USING_COMPANION == 1 */ diff --git a/main/utilities/letter_shell/src/shell_ext.c b/main/utilities/letter_shell/src/shell_ext.c new file mode 100644 index 0000000..7fbbc61 --- /dev/null +++ b/main/utilities/letter_shell/src/shell_ext.c @@ -0,0 +1,447 @@ +/** + * @file shell_ext.c + * @author Letter (NevermindZZT@gmail.com) + * @brief shell extensions + * @version 3.0.0 + * @date 2019-12-31 + * + * @copyright (c) 2019 Letter + * + */ + +#include "shell_cfg.h" +#include "shell.h" +#include "shell_ext.h" + + +extern ShellCommand* shellSeekCommand(Shell *shell, + const char *cmd, + ShellCommand *base, + unsigned short compareLength); +extern int shellGetVarValue(Shell *shell, ShellCommand *command); + +/** + * @brief 判断数字进制 + * + * @param string 参数字符串 + * @return ShellNumType 进制 + */ +static ShellNumType shellExtNumType(char *string) +{ + char *p = string; + ShellNumType type = NUM_TYPE_DEC; + + if ((*p == '0') && ((*(p + 1) == 'x') || (*(p + 1) == 'X'))) + { + type = NUM_TYPE_HEX; + } + else if ((*p == '0') && ((*(p + 1) == 'b') || (*(p + 1) == 'B'))) + { + type = NUM_TYPE_BIN; + } + else if (*p == '0') + { + type = NUM_TYPE_OCT; + } + + while (*p++) + { + if (*p == '.' && *(p + 1) != 0) + { + type = NUM_TYPE_FLOAT; + break; + } + } + + return type; +} + + +/** + * @brief 字符转数字 + * + * @param code 字符 + * @return char 数字 + */ +static char shellExtToNum(char code) +{ + if ((code >= '0') && (code <= '9')) + { + return code -'0'; + } + else if ((code >= 'a') && (code <= 'f')) + { + return code - 'a' + 10; + } + else if ((code >= 'A') && (code <= 'F')) + { + return code - 'A' + 10; + } + else + { + return 0; + } +} + + +/** + * @brief 解析字符参数 + * + * @param string 字符串参数 + * @return char 解析出的字符 + */ +static char shellExtParseChar(char *string) +{ + char *p = string + 1; + char value = 0; + + if (*p == '\\') + { + switch (*(p + 1)) + { + case 'b': + value = '\b'; + break; + case 'r': + value = '\r'; + break; + case 'n': + value = '\n'; + break; + case 't': + value = '\t'; + break; + case '0': + value = 0; + break; + default: + value = *(p + 1); + break; + } + } + else + { + value = *p; + } + return value; +} + + +/** + * @brief 解析字符串参数 + * + * @param string 字符串参数 + * @return char* 解析出的字符串 + */ +static char* shellExtParseString(char *string) +{ + char *p = string; + unsigned short index = 0; + + if (*string == '\"') + { + p = ++string; + } + + while (*p) + { + if (*p == '\\') + { + *(string + index) = shellExtParseChar(p - 1); + p++; + } + else if (*p == '\"') + { + *(string + index) = 0; + } + else + { + *(string + index) = *p; + } + p++; + index ++; + } + *(string + index) = 0; + return string; +} + + +/** + * @brief 解析数字参数 + * + * @param string 字符串参数 + * @return unsigned int 解析出的数字 + */ +static unsigned int shellExtParseNumber(char *string) +{ + ShellNumType type = NUM_TYPE_DEC; + char radix = 10; + char *p = string; + char offset = 0; + signed char sign = 1; + unsigned int valueInt = 0; + float valueFloat = 0.0; + unsigned int devide = 0; + + if (*string == '-') + { + sign = -1; + } + + type = shellExtNumType(string + ((sign == -1) ? 1 : 0)); + + switch ((char)type) + { + case NUM_TYPE_HEX: + radix = 16; + offset = 2; + break; + + case NUM_TYPE_OCT: + radix = 8; + offset = 1; + break; + + case NUM_TYPE_BIN: + radix = 2; + offset = 2; + break; + + default: + break; + } + + p = string + offset + ((sign == -1) ? 1 : 0); + + while (*p) + { + if (*p == '.') + { + devide = 1; + p++; + continue; + } + valueInt = valueInt * radix + shellExtToNum(*p); + devide *= 10; + p++; + } + if (type == NUM_TYPE_FLOAT && devide != 0) + { + valueFloat = (float)valueInt / devide * sign; + return *(unsigned int *)(&valueFloat); + } + else + { + return valueInt * sign; + } +} + + +/** + * @brief 解析变量参数 + * + * @param shell shell对象 + * @param var 变量 + * @return unsigned int 变量值 + */ +static unsigned int shellExtParseVar(Shell *shell, char *var) +{ + ShellCommand *command = shellSeekCommand(shell, + var + 1, + shell->commandList.base, + 0); + if (command) + { + return shellGetVarValue(shell, command); + } + else + { + return 0; + } +} + + +/** + * @brief 解析参数 + * + * @param shell shell对象 + * @param string 参数 + * @return unsigned int 解析结果 + */ +unsigned int shellExtParsePara(Shell *shell, char *string) +{ + if (*string == '\'' && *(string + 1)) + { + return (unsigned int)shellExtParseChar(string); + } + else if (*string == '-' || (*string >= '0' && *string <= '9')) + { + return (unsigned int)shellExtParseNumber(string); + } + else if (*string == '$' && *(string + 1)) + { + return shellExtParseVar(shell, string); + } + else if (*string) + { + return (unsigned int)shellExtParseString(string); + } + return 0; +} + + +/** + * @brief 执行命令 + * + * @param shell shell对象 + * @param command 命令 + * @param argc 参数个数 + * @param argv 参数 + * @return int 返回值 + */ +int shellExtRun(Shell *shell, ShellCommand *command, int argc, char *argv[]) +{ + unsigned int params[SHELL_PARAMETER_MAX_NUMBER] = {0}; + int paramNum = command->attr.attrs.paramNum > (argc - 1) ? + command->attr.attrs.paramNum : (argc - 1); + for (int i = 0; i < argc - 1; i++) + { + params[i] = shellExtParsePara(shell, argv[i + 1]); + } + switch (paramNum) + { +#if SHELL_PARAMETER_MAX_NUMBER >= 1 + case 0: + return command->data.cmd.function(); + // break; +#endif /** SHELL_PARAMETER_MAX_NUMBER >= 1 */ +#if SHELL_PARAMETER_MAX_NUMBER >= 2 + case 1: + return command->data.cmd.function(params[0]); + // break; +#endif /** SHELL_PARAMETER_MAX_NUMBER >= 2 */ +#if SHELL_PARAMETER_MAX_NUMBER >= 3 + case 2: + return command->data.cmd.function(params[0], params[1]); + // break; +#endif /** SHELL_PARAMETER_MAX_NUMBER >= 3 */ +#if SHELL_PARAMETER_MAX_NUMBER >= 4 + case 3: + return command->data.cmd.function(params[0], params[1], + params[2]); + // break; +#endif /** SHELL_PARAMETER_MAX_NUMBER >= 4 */ +#if SHELL_PARAMETER_MAX_NUMBER >= 5 + case 4: + return command->data.cmd.function(params[0], params[1], + params[2], params[3]); + // break; +#endif /** SHELL_PARAMETER_MAX_NUMBER >= 5 */ +#if SHELL_PARAMETER_MAX_NUMBER >= 6 + case 5: + return command->data.cmd.function(params[0], params[1], + params[2], params[3], + params[4]); + // break; +#endif /** SHELL_PARAMETER_MAX_NUMBER >= 6 */ +#if SHELL_PARAMETER_MAX_NUMBER >= 7 + case 6: + return command->data.cmd.function(params[0], params[1], + params[2], params[3], + params[4], params[5]); + // break; +#endif /** SHELL_PARAMETER_MAX_NUMBER >= 7 */ +#if SHELL_PARAMETER_MAX_NUMBER >= 8 + case 7: + return command->data.cmd.function(params[0], params[1], + params[2], params[3], + params[4], params[5], + params[6]); + // break; +#endif /** SHELL_PARAMETER_MAX_NUMBER >= 8 */ +#if SHELL_PARAMETER_MAX_NUMBER >= 9 + case 8: + return command->data.cmd.function(params[0], params[1], + params[2], params[3], + params[4], params[5], + params[6], params[7]); + // break; +#endif /** SHELL_PARAMETER_MAX_NUMBER >= 9 */ +#if SHELL_PARAMETER_MAX_NUMBER >= 10 + case 9: + return command->data.cmd.function(params[0], params[1], + params[2], params[3], + params[4], params[5], + params[6], params[7], + params[8]); + // break; +#endif /** SHELL_PARAMETER_MAX_NUMBER >= 10 */ +#if SHELL_PARAMETER_MAX_NUMBER >= 11 + case 10: + return command->data.cmd.function(params[0], params[1], + params[2], params[3], + params[4], params[5], + params[6], params[7], + params[8], params[9]); + // break; +#endif /** SHELL_PARAMETER_MAX_NUMBER >= 11 */ +#if SHELL_PARAMETER_MAX_NUMBER >= 12 + case 11: + return command->data.cmd.function(params[0], params[1], + params[2], params[3], + params[4], params[5], + params[6], params[7], + params[8], params[9], + params[10]); + // break; +#endif /** SHELL_PARAMETER_MAX_NUMBER >= 12 */ +#if SHELL_PARAMETER_MAX_NUMBER >= 13 + case 12: + return command->data.cmd.function(params[0], params[1], + params[2], params[3], + params[4], params[5], + params[6], params[7], + params[8], params[9], + params[10], params[11]); + // break; +#endif /** SHELL_PARAMETER_MAX_NUMBER >= 13 */ +#if SHELL_PARAMETER_MAX_NUMBER >= 14 + case 13: + return command->data.cmd.function(params[0], params[1], + params[2], params[3], + params[4], params[5], + params[6], params[7], + params[8], params[9], + params[10], params[11], + params[12]); + // break; +#endif /** SHELL_PARAMETER_MAX_NUMBER >= 14 */ +#if SHELL_PARAMETER_MAX_NUMBER >= 15 + case 14: + return command->data.cmd.function(params[0], params[1], + params[2], params[3], + params[4], params[5], + params[6], params[7], + params[8], params[9], + params[10], params[11], + params[12], params[13]); + // break; +#endif /** SHELL_PARAMETER_MAX_NUMBER >= 15 */ +#if SHELL_PARAMETER_MAX_NUMBER >= 16 + case 15: + return command->data.cmd.function(params[0], params[1], + params[2], params[3], + params[4], params[5], + params[6], params[7], + params[8], params[9], + params[10], params[11], + params[12], params[13], + params[14]); + // break; +#endif /** SHELL_PARAMETER_MAX_NUMBER >= 16 */ + default: + return -1; + // break; + } +} + diff --git a/main/utilities/letter_shell/src/shell_ext.h b/main/utilities/letter_shell/src/shell_ext.h new file mode 100644 index 0000000..2e6158c --- /dev/null +++ b/main/utilities/letter_shell/src/shell_ext.h @@ -0,0 +1,33 @@ +/** + * @file shell_ext.h + * @author Letter (NevermindZZT@gmail.com) + * @brief shell extensions + * @version 3.0.0 + * @date 2019-12-31 + * + * @copyright (c) 2019 Letter + * + */ + +#ifndef __SHELL_EXT_H__ +#define __SHELL_EXT_H__ + +#include "shell.h" + +/** + * @brief 数字类型 + * + */ +typedef enum +{ + NUM_TYPE_DEC, /**< 十进制整型 */ + NUM_TYPE_BIN, /**< 二进制整型 */ + NUM_TYPE_OCT, /**< 八进制整型 */ + NUM_TYPE_HEX, /**< 十六进制整型 */ + NUM_TYPE_FLOAT /**< 浮点型 */ +} ShellNumType; + +unsigned int shellExtParsePara(Shell *shell, char *string); +int shellExtRun(Shell *shell, ShellCommand *command, int argc, char *argv[]); + +#endif diff --git a/main/utilities/link_list/link_list.c b/main/utilities/link_list/link_list.c new file mode 100644 index 0000000..22f1afa --- /dev/null +++ b/main/utilities/link_list/link_list.c @@ -0,0 +1,144 @@ +/** + * @file link_list.c + * @author impressionyang (impressionyang@outlook.com) + * @brief + * @version 0.1 + * @date 2022-10-12 + * _ _ + * (_)_ _ ___ _______ ___ ___ (_)__ ___ __ _____ ____ ___ _ + * / / ' \/ _ \/ __/ -_|_-<(_- + * Date Version Author Description + * 2022-10-12 v1.0 impressionyang 内容 + * + */ +#include "link_list.h" +#include +#include + +static uint8_t sg_link_list_node_id = 0; + +link_list_handle_t* link_list_init() +{ + link_list_handle_t *ptr = (link_list_handle_t *)malloc(sizeof(link_list_handle_t)); + + ptr->link_list_length = 0; + ptr->link_list_header = NULL; + ptr->link_list_tail = NULL; + + return ptr; +} +uint8_t link_list_append_node_to_tail(link_list_handle_t *link_list, void *node_data_ptr, uint8_t *node_id) +{ + link_list_node_t *node = (link_list_node_t *)malloc(sizeof(link_list_node_t)); + + if (!link_list || !node_data_ptr || !node_id) { + // null pointer error + return 1; + } + + node->node_id = sg_link_list_node_id++; + node->node_data_ptr = node_data_ptr; + node->next = NULL; + + if (NULL == link_list->link_list_header) { + link_list->link_list_header = node; + link_list->link_list_tail = node; + }else { + link_list->link_list_tail->next = node; + link_list->link_list_tail = node; + } + + return 0; +} + +link_list_node_t *link_list_get_next_node(link_list_handle_t *link_list, link_list_node_t *node, void *node_data_ptr) +{ + if (!link_list || !node_data_ptr || !node) { + // null pointer error + return NULL; + } + + return node->next; +} + +uint8_t link_list_get_node_by_id(link_list_handle_t *link_list, void *node_data_ptr, uint8_t node_id) +{ + link_list_node_t *head = link_list->link_list_header; + link_list_node_t *p, *q; + + if (!link_list || !node_data_ptr ) { + // null pointer error + return 1; + } + + if (node_id > link_list->link_list_length) { + // id error + return 2; + } + + for (p = head; p->next != NULL; p = p->next) { + if (p->node_id == node_id) { + node_data_ptr = p->node_data_ptr; + break; + } + } + + return 0; +} + +uint8_t link_list_delete_node_by_id(link_list_handle_t *link_list, uint8_t node_id) +{ + link_list_node_t *head = link_list->link_list_header; + link_list_node_t *p, *q; + + if (!link_list ) { + // null pointer error + return 1; + } + + if (node_id > link_list->link_list_length) { + // id error + return 2; + } + + q = head; + for (p = head; p->next != NULL; p = p->next) { + if (p->node_id == node_id) { + q->next = p->next; + if (p == link_list->link_list_tail) { + link_list->link_list_tail = q; + } + free(p); + break; + } + q = p; + } + + return 0; +} + +uint8_t link_list_deinit(link_list_handle_t* link_list) +{ + if (!link_list) { + // null pointer + return 1; + } + + link_list_node_t *head = link_list->link_list_header; + link_list_node_t *p, *q; + + for (p = head; p->next != NULL; p = q) { + q = p->next; + free(p); + } + + free (link_list); + + return 0; +} \ No newline at end of file diff --git a/main/utilities/link_list/link_list.h b/main/utilities/link_list/link_list.h new file mode 100644 index 0000000..2c4816d --- /dev/null +++ b/main/utilities/link_list/link_list.h @@ -0,0 +1,128 @@ +/** + * @file link_list.h + * @author impressionyang (impressionyang@outlook.com) + * @brief 链表的数据结构 + * @version 0.1 + * @date 2022-10-12 + * _ _ + * (_)_ _ ___ _______ ___ ___ (_)__ ___ __ _____ ____ ___ _ + * / / ' \/ _ \/ __/ -_|_-<(_- + * Date Version Author Description + * 2022-10-12 v1.0 impressionyang 内容 + * + */ +#ifndef __LINK_LIST_H__ +#define __LINK_LIST_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/// @brief 链表节点结构 +typedef struct _link_list_node_t_ +{ + /// @brief 链表节点的位置,如果有删除事件,需要 + uint8_t node_id; + /// @brief 链表数据的指针,所有的链表节点内的数据都是一个指针,方便存放如结构体等数据 + void *node_data_ptr; + /// @brief 下一个元素节点的指针 + struct _link_list_node_t_ *next; +}link_list_node_t; + +/// @brief 链表控制句柄,用来确认链表的元素和链表头的 +typedef struct _link_list_handle_t_ +{ + /// @brief 链表节点个数 + uint8_t link_list_length; + /// @brief 链表头 + link_list_node_t *link_list_header; + /// @brief 链表尾 + link_list_node_t *link_list_tail; +}link_list_handle_t; + +/** + * + * @brief 初始化链表 + * 1. 申请内存空间 + * 2. 返回一个链表句柄 + * @author impressionyang (impressionyang@outlook.com) + * @return link_list_handle_t* 链表控制句柄 + * + * @details + */ +link_list_handle_t* link_list_init(); + +/** + * + * @brief 将node_data_ptr创建一个链表的节点插入到尾部中 + * @author impressionyang (impressionyang@outlook.com) + * @param [in] link_list 链表控制句柄 + * @param [in] node_data_ptr 链表节点的数据的指针 + * @param [out] node_id 返回的该节点在链表中的当前的位置 + * @return uint8_t 插入结果 0 -》成功 | 非0 -》 失败 + * + * @details + */ +uint8_t link_list_append_node_to_tail(link_list_handle_t *link_list, void *node_data_ptr, uint8_t *node_id); + +/** + * + * @brief 通过一个节点指针获取该节点的下一个链表节点的内容 + * @author impressionyang (impressionyang@outlook.com) + * @param [in] link_list 链表控制句柄 + * @param [in] node 当前节点(一般开始为头节点) + * @param [in] node_data_ptr 节点的数据的指针 + * @return link_list_node_t* 下一个节点的指针 + * + * @details + */ +link_list_node_t *link_list_get_next_node(link_list_handle_t *link_list, link_list_node_t *node, void *node_data_ptr); + +/** + * + * @brief 通过位置获取节点的数值 + * @author impressionyang (impressionyang@outlook.com) + * @param [in] link_list 链表控制句柄 + * @param [in] node_data_ptr 节点数据保存的指针 + * @param [in] node_id 位置 + * @return uint8_t 结果 0 -》成功 | 非0 -》 失败 + * + * @details + */ +uint8_t link_list_get_node_by_id(link_list_handle_t *link_list, void *node_data_ptr, uint8_t node_id); + +/** + * + * @brief 通过位置删除节点 + * @author impressionyang (impressionyang@outlook.com) + * @param [in] link_list 链表控制句柄 + * @param [in] node_id 位置 + * @return uint8_t 结果 0 -》成功 | 非0 -》 失败 + * + * @details + */ +uint8_t link_list_delete_node_by_id(link_list_handle_t *link_list, uint8_t node_id); + +/** + * + * @brief 去初始化链表,删除所有元素 + * @author impressionyang (impressionyang@outlook.com) + * @param [in] link_list 链表控制句柄 + * @return uint8_t 结果 0 -》成功 | 非0 -》 失败 + * + * @details + */ +uint8_t link_list_deinit(link_list_handle_t* link_list); + +#ifdef __cplusplus +} +#endif +#endif//__LINK_LIST_H__ \ No newline at end of file diff --git a/sdkconfig b/sdkconfig new file mode 100644 index 0000000..d676400 --- /dev/null +++ b/sdkconfig @@ -0,0 +1,1376 @@ +# +# Automatically generated file. DO NOT EDIT. +# Espressif IoT Development Framework (ESP-IDF) Project Configuration +# +CONFIG_IDF_CMAKE=y +CONFIG_IDF_TARGET_ARCH_XTENSA=y +CONFIG_IDF_TARGET="esp32s2" +CONFIG_IDF_TARGET_ESP32S2=y +CONFIG_IDF_FIRMWARE_CHIP_ID=0x0002 + +# +# SDK tool configuration +# +CONFIG_SDK_TOOLPREFIX="xtensa-esp32s2-elf-" +# CONFIG_SDK_TOOLCHAIN_SUPPORTS_TIME_WIDE_64_BITS is not set +# end of SDK tool configuration + +# +# Build type +# +CONFIG_APP_BUILD_TYPE_APP_2NDBOOT=y +# CONFIG_APP_BUILD_TYPE_ELF_RAM is not set +CONFIG_APP_BUILD_GENERATE_BINARIES=y +CONFIG_APP_BUILD_BOOTLOADER=y +CONFIG_APP_BUILD_USE_FLASH_SECTIONS=y +# end of Build type + +# +# Application manager +# +CONFIG_APP_COMPILE_TIME_DATE=y +# CONFIG_APP_EXCLUDE_PROJECT_VER_VAR is not set +# CONFIG_APP_EXCLUDE_PROJECT_NAME_VAR is not set +# CONFIG_APP_PROJECT_VER_FROM_CONFIG is not set +CONFIG_APP_RETRIEVE_LEN_ELF_SHA=16 +# end of Application manager + +# +# Bootloader config +# +CONFIG_BOOTLOADER_OFFSET_IN_FLASH=0x1000 +CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y +# CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_DEBUG is not set +# CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_PERF is not set +# CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_NONE is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_NONE is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_ERROR is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_WARN is not set +CONFIG_BOOTLOADER_LOG_LEVEL_INFO=y +# CONFIG_BOOTLOADER_LOG_LEVEL_DEBUG is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_VERBOSE is not set +CONFIG_BOOTLOADER_LOG_LEVEL=3 +CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V=y +# CONFIG_BOOTLOADER_FACTORY_RESET is not set +# CONFIG_BOOTLOADER_APP_TEST is not set +CONFIG_BOOTLOADER_REGION_PROTECTION_ENABLE=y +CONFIG_BOOTLOADER_WDT_ENABLE=y +# CONFIG_BOOTLOADER_WDT_DISABLE_IN_USER_CODE is not set +CONFIG_BOOTLOADER_WDT_TIME_MS=9000 +# CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE is not set +# CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP is not set +# CONFIG_BOOTLOADER_SKIP_VALIDATE_ON_POWER_ON is not set +# CONFIG_BOOTLOADER_SKIP_VALIDATE_ALWAYS is not set +CONFIG_BOOTLOADER_RESERVE_RTC_SIZE=0 +# CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC is not set +CONFIG_BOOTLOADER_FLASH_XMC_SUPPORT=y +# end of Bootloader config + +# +# Security features +# +CONFIG_SECURE_BOOT_SUPPORTS_RSA=y +CONFIG_SECURE_TARGET_HAS_SECURE_ROM_DL_MODE=y +# CONFIG_SECURE_SIGNED_APPS_NO_SECURE_BOOT is not set +# CONFIG_SECURE_BOOT is not set +# CONFIG_SECURE_FLASH_ENC_ENABLED is not set +# end of Security features + +# +# Boot ROM Behavior +# +CONFIG_BOOT_ROM_LOG_ALWAYS_ON=y +# CONFIG_BOOT_ROM_LOG_ALWAYS_OFF is not set +# CONFIG_BOOT_ROM_LOG_ON_GPIO_HIGH is not set +# CONFIG_BOOT_ROM_LOG_ON_GPIO_LOW is not set +# end of Boot ROM Behavior + +# +# Serial flasher config +# +CONFIG_ESPTOOLPY_BAUD_OTHER_VAL=115200 +# CONFIG_ESPTOOLPY_NO_STUB is not set +# CONFIG_ESPTOOLPY_FLASHMODE_QIO is not set +# CONFIG_ESPTOOLPY_FLASHMODE_QOUT is not set +CONFIG_ESPTOOLPY_FLASHMODE_DIO=y +# CONFIG_ESPTOOLPY_FLASHMODE_DOUT is not set +CONFIG_ESPTOOLPY_FLASH_SAMPLE_MODE_STR=y +CONFIG_ESPTOOLPY_FLASHMODE="dio" +CONFIG_ESPTOOLPY_FLASHFREQ_80M=y +# CONFIG_ESPTOOLPY_FLASHFREQ_40M is not set +# CONFIG_ESPTOOLPY_FLASHFREQ_26M is not set +# CONFIG_ESPTOOLPY_FLASHFREQ_20M is not set +CONFIG_ESPTOOLPY_FLASHFREQ="80m" +# CONFIG_ESPTOOLPY_FLASHSIZE_1MB is not set +CONFIG_ESPTOOLPY_FLASHSIZE_2MB=y +# CONFIG_ESPTOOLPY_FLASHSIZE_4MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_8MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_16MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_32MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_64MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_128MB is not set +CONFIG_ESPTOOLPY_FLASHSIZE="2MB" +CONFIG_ESPTOOLPY_FLASHSIZE_DETECT=y +CONFIG_ESPTOOLPY_BEFORE_RESET=y +# CONFIG_ESPTOOLPY_BEFORE_NORESET is not set +CONFIG_ESPTOOLPY_BEFORE="default_reset" +CONFIG_ESPTOOLPY_AFTER_RESET=y +# CONFIG_ESPTOOLPY_AFTER_NORESET is not set +CONFIG_ESPTOOLPY_AFTER="hard_reset" +# CONFIG_ESPTOOLPY_MONITOR_BAUD_CONSOLE is not set +# CONFIG_ESPTOOLPY_MONITOR_BAUD_9600B is not set +# CONFIG_ESPTOOLPY_MONITOR_BAUD_57600B is not set +CONFIG_ESPTOOLPY_MONITOR_BAUD_115200B=y +# CONFIG_ESPTOOLPY_MONITOR_BAUD_230400B is not set +# CONFIG_ESPTOOLPY_MONITOR_BAUD_921600B is not set +# CONFIG_ESPTOOLPY_MONITOR_BAUD_2MB is not set +# CONFIG_ESPTOOLPY_MONITOR_BAUD_OTHER is not set +CONFIG_ESPTOOLPY_MONITOR_BAUD_OTHER_VAL=115200 +CONFIG_ESPTOOLPY_MONITOR_BAUD=115200 +# end of Serial flasher config + +# +# Partition Table +# +CONFIG_PARTITION_TABLE_SINGLE_APP=y +# CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE is not set +# CONFIG_PARTITION_TABLE_TWO_OTA is not set +# CONFIG_PARTITION_TABLE_CUSTOM is not set +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" +CONFIG_PARTITION_TABLE_FILENAME="partitions_singleapp.csv" +CONFIG_PARTITION_TABLE_OFFSET=0x8000 +CONFIG_PARTITION_TABLE_MD5=y +# end of Partition Table + +# +# ST7789 Configuration +# +CONFIG_GPIO_RANGE_MAX=46 +CONFIG_WIDTH=240 +CONFIG_HEIGHT=280 +CONFIG_OFFSETX=0 +CONFIG_OFFSETY=20 +CONFIG_MOSI_GPIO=11 +CONFIG_SCLK_GPIO=12 +CONFIG_CS_GPIO=-1 +CONFIG_DC_GPIO=13 +CONFIG_RESET_GPIO=10 +CONFIG_BL_GPIO=14 +# CONFIG_INVERSION is not set +# CONFIG_SPI2_HOST is not set +CONFIG_SPI3_HOST=y +# end of ST7789 Configuration + +# +# Compiler options +# +CONFIG_COMPILER_OPTIMIZATION_DEFAULT=y +# CONFIG_COMPILER_OPTIMIZATION_SIZE is not set +# CONFIG_COMPILER_OPTIMIZATION_PERF is not set +# CONFIG_COMPILER_OPTIMIZATION_NONE is not set +CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE=y +# CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT is not set +# CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE is not set +CONFIG_COMPILER_OPTIMIZATION_ASSERTION_LEVEL=2 +# CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT is not set +CONFIG_COMPILER_HIDE_PATHS_MACROS=y +# CONFIG_COMPILER_CXX_EXCEPTIONS is not set +# CONFIG_COMPILER_CXX_RTTI is not set +CONFIG_COMPILER_STACK_CHECK_MODE_NONE=y +# CONFIG_COMPILER_STACK_CHECK_MODE_NORM is not set +# CONFIG_COMPILER_STACK_CHECK_MODE_STRONG is not set +# CONFIG_COMPILER_STACK_CHECK_MODE_ALL is not set +# CONFIG_COMPILER_WARN_WRITE_STRINGS is not set +# CONFIG_COMPILER_DISABLE_GCC8_WARNINGS is not set +# CONFIG_COMPILER_DUMP_RTL_FILES is not set +# end of Compiler options + +# +# Component config +# + +# +# Application Level Tracing +# +# CONFIG_APPTRACE_DEST_JTAG is not set +CONFIG_APPTRACE_DEST_NONE=y +CONFIG_APPTRACE_LOCK_ENABLE=y +# end of Application Level Tracing + +# +# ESP-ASIO +# +# CONFIG_ASIO_SSL_SUPPORT is not set +# end of ESP-ASIO + +# +# CoAP Configuration +# +CONFIG_COAP_MBEDTLS_PSK=y +# CONFIG_COAP_MBEDTLS_PKI is not set +# CONFIG_COAP_MBEDTLS_DEBUG is not set +CONFIG_COAP_LOG_DEFAULT_LEVEL=0 +# end of CoAP Configuration + +# +# Driver configurations +# + +# +# ADC configuration +# +# CONFIG_ADC_FORCE_XPD_FSM is not set +CONFIG_ADC_DISABLE_DAC=y +# end of ADC configuration + +# +# MCPWM configuration +# +# CONFIG_MCPWM_ISR_IN_IRAM is not set +# end of MCPWM configuration + +# +# SPI configuration +# +# CONFIG_SPI_MASTER_IN_IRAM is not set +CONFIG_SPI_MASTER_ISR_IN_IRAM=y +# CONFIG_SPI_SLAVE_IN_IRAM is not set +CONFIG_SPI_SLAVE_ISR_IN_IRAM=y +# end of SPI configuration + +# +# TWAI configuration +# +# CONFIG_TWAI_ISR_IN_IRAM is not set +# end of TWAI configuration + +# +# UART configuration +# +# CONFIG_UART_ISR_IN_IRAM is not set +# end of UART configuration + +# +# GDMA Configuration +# +# CONFIG_GDMA_CTRL_FUNC_IN_IRAM is not set +# CONFIG_GDMA_ISR_IRAM_SAFE is not set +# end of GDMA Configuration +# end of Driver configurations + +# +# eFuse Bit Manager +# +# CONFIG_EFUSE_CUSTOM_TABLE is not set +# CONFIG_EFUSE_VIRTUAL is not set +CONFIG_EFUSE_MAX_BLK_LEN=256 +# end of eFuse Bit Manager + +# +# ESP-TLS +# +CONFIG_ESP_TLS_USING_MBEDTLS=y +CONFIG_ESP_TLS_USE_DS_PERIPHERAL=y +# CONFIG_ESP_TLS_CLIENT_SESSION_TICKETS is not set +# CONFIG_ESP_TLS_SERVER is not set +# CONFIG_ESP_TLS_PSK_VERIFICATION is not set +# CONFIG_ESP_TLS_INSECURE is not set +# end of ESP-TLS + +# +# ESP32S2-specific +# +# CONFIG_ESP32S2_DEFAULT_CPU_FREQ_80 is not set +CONFIG_ESP32S2_DEFAULT_CPU_FREQ_160=y +# CONFIG_ESP32S2_DEFAULT_CPU_FREQ_240 is not set +CONFIG_ESP32S2_DEFAULT_CPU_FREQ_MHZ=160 + +# +# Cache config +# +CONFIG_ESP32S2_INSTRUCTION_CACHE_8KB=y +# CONFIG_ESP32S2_INSTRUCTION_CACHE_16KB is not set +# CONFIG_ESP32S2_INSTRUCTION_CACHE_LINE_16B is not set +CONFIG_ESP32S2_INSTRUCTION_CACHE_LINE_32B=y +CONFIG_ESP32S2_DATA_CACHE_0KB=y +# CONFIG_ESP32S2_DATA_CACHE_8KB is not set +# CONFIG_ESP32S2_DATA_CACHE_16KB is not set +# CONFIG_ESP32S2_DATA_CACHE_LINE_16B is not set +CONFIG_ESP32S2_DATA_CACHE_LINE_32B=y +# CONFIG_ESP32S2_INSTRUCTION_CACHE_WRAP is not set +# CONFIG_ESP32S2_DATA_CACHE_WRAP is not set +# end of Cache config + +# CONFIG_ESP32S2_SPIRAM_SUPPORT is not set +# CONFIG_ESP32S2_TRAX is not set +CONFIG_ESP32S2_TRACEMEM_RESERVE_DRAM=0x0 +# CONFIG_ESP32S2_ULP_COPROC_ENABLED is not set +CONFIG_ESP32S2_ULP_COPROC_RESERVE_MEM=0 +CONFIG_ESP32S2_DEBUG_OCDAWARE=y +CONFIG_ESP32S2_BROWNOUT_DET=y +CONFIG_ESP32S2_BROWNOUT_DET_LVL_SEL_7=y +# CONFIG_ESP32S2_BROWNOUT_DET_LVL_SEL_6 is not set +# CONFIG_ESP32S2_BROWNOUT_DET_LVL_SEL_5 is not set +# CONFIG_ESP32S2_BROWNOUT_DET_LVL_SEL_4 is not set +# CONFIG_ESP32S2_BROWNOUT_DET_LVL_SEL_3 is not set +# CONFIG_ESP32S2_BROWNOUT_DET_LVL_SEL_2 is not set +# CONFIG_ESP32S2_BROWNOUT_DET_LVL_SEL_1 is not set +CONFIG_ESP32S2_BROWNOUT_DET_LVL=7 +CONFIG_ESP32S2_TIME_SYSCALL_USE_RTC_FRC1=y +# CONFIG_ESP32S2_TIME_SYSCALL_USE_RTC is not set +# CONFIG_ESP32S2_TIME_SYSCALL_USE_FRC1 is not set +# CONFIG_ESP32S2_TIME_SYSCALL_USE_NONE is not set +CONFIG_ESP32S2_RTC_CLK_SRC_INT_RC=y +# CONFIG_ESP32S2_RTC_CLK_SRC_EXT_CRYS is not set +# CONFIG_ESP32S2_RTC_CLK_SRC_EXT_OSC is not set +# CONFIG_ESP32S2_RTC_CLK_SRC_INT_8MD256 is not set +CONFIG_ESP32S2_RTC_CLK_CAL_CYCLES=576 +# CONFIG_ESP32S2_NO_BLOBS is not set +# CONFIG_ESP32S2_KEEP_USB_ALIVE is not set +# CONFIG_ESP32S2_RTCDATA_IN_FAST_MEM is not set +# CONFIG_ESP32S2_USE_FIXED_STATIC_RAM_SIZE is not set +# end of ESP32S2-specific + +# +# ADC-Calibration +# +# end of ADC-Calibration + +# +# Common ESP-related +# +CONFIG_ESP_ERR_TO_NAME_LOOKUP=y +# end of Common ESP-related + +# +# Ethernet +# +CONFIG_ETH_ENABLED=y +CONFIG_ETH_USE_SPI_ETHERNET=y +# CONFIG_ETH_SPI_ETHERNET_DM9051 is not set +# CONFIG_ETH_SPI_ETHERNET_W5500 is not set +# CONFIG_ETH_SPI_ETHERNET_KSZ8851SNL is not set +# CONFIG_ETH_USE_OPENETH is not set +# end of Ethernet + +# +# Event Loop Library +# +# CONFIG_ESP_EVENT_LOOP_PROFILING is not set +CONFIG_ESP_EVENT_POST_FROM_ISR=y +CONFIG_ESP_EVENT_POST_FROM_IRAM_ISR=y +# end of Event Loop Library + +# +# GDB Stub +# +# end of GDB Stub + +# +# ESP HTTP client +# +CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS=y +# CONFIG_ESP_HTTP_CLIENT_ENABLE_BASIC_AUTH is not set +CONFIG_ESP_HTTP_CLIENT_ENABLE_DIGEST_AUTH=y +# end of ESP HTTP client + +# +# HTTP Server +# +CONFIG_HTTPD_MAX_REQ_HDR_LEN=512 +CONFIG_HTTPD_MAX_URI_LEN=512 +CONFIG_HTTPD_ERR_RESP_NO_DELAY=y +CONFIG_HTTPD_PURGE_BUF_LEN=32 +# CONFIG_HTTPD_LOG_PURGE_DATA is not set +# CONFIG_HTTPD_WS_SUPPORT is not set +# end of HTTP Server + +# +# ESP HTTPS OTA +# +# CONFIG_OTA_ALLOW_HTTP is not set +# end of ESP HTTPS OTA + +# +# ESP HTTPS server +# +# CONFIG_ESP_HTTPS_SERVER_ENABLE is not set +# end of ESP HTTPS server + +# +# Hardware Settings +# + +# +# MAC Config +# +CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_STA=y +CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_AP=y +# CONFIG_ESP32S2_UNIVERSAL_MAC_ADDRESSES_ONE is not set +CONFIG_ESP32S2_UNIVERSAL_MAC_ADDRESSES_TWO=y +CONFIG_ESP32S2_UNIVERSAL_MAC_ADDRESSES=2 +# end of MAC Config + +# +# Sleep Config +# +CONFIG_ESP_SLEEP_POWER_DOWN_FLASH=y +CONFIG_ESP_SLEEP_RTC_BUS_ISO_WORKAROUND=y +# CONFIG_ESP_SLEEP_GPIO_RESET_WORKAROUND is not set +# CONFIG_ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND is not set +# end of Sleep Config + +# +# RTC Clock Config +# +# end of RTC Clock Config +# end of Hardware Settings + +# +# IPC (Inter-Processor Call) +# +CONFIG_ESP_IPC_TASK_STACK_SIZE=1536 +# end of IPC (Inter-Processor Call) + +# +# LCD and Touch Panel +# + +# +# LCD Peripheral Configuration +# +CONFIG_LCD_PANEL_IO_FORMAT_BUF_SIZE=32 +# end of LCD Peripheral Configuration +# end of LCD and Touch Panel + +# +# ESP NETIF Adapter +# +CONFIG_ESP_NETIF_IP_LOST_TIMER_INTERVAL=120 +CONFIG_ESP_NETIF_TCPIP_LWIP=y +# CONFIG_ESP_NETIF_LOOPBACK is not set +CONFIG_ESP_NETIF_TCPIP_ADAPTER_COMPATIBLE_LAYER=y +# end of ESP NETIF Adapter + +# +# PHY +# +CONFIG_ESP_PHY_CALIBRATION_AND_DATA_STORAGE=y +# CONFIG_ESP_PHY_INIT_DATA_IN_PARTITION is not set +CONFIG_ESP_PHY_MAX_WIFI_TX_POWER=20 +CONFIG_ESP_PHY_MAX_TX_POWER=20 +# CONFIG_ESP_PHY_ENABLE_USB is not set +# end of PHY + +# +# Power Management +# +# CONFIG_PM_ENABLE is not set +# end of Power Management + +# +# ESP System Settings +# +# CONFIG_ESP_SYSTEM_PANIC_PRINT_HALT is not set +CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT=y +# CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT is not set +# CONFIG_ESP_SYSTEM_PANIC_GDBSTUB is not set +# CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME is not set +CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE=y +CONFIG_ESP_SYSTEM_RTC_FAST_MEM_AS_HEAP_DEPCHECK=y +CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP=y + +# +# Memory protection +# +CONFIG_ESP_SYSTEM_MEMPROT_DEPCHECK=y +CONFIG_ESP_SYSTEM_MEMPROT_FEATURE=y +CONFIG_ESP_SYSTEM_MEMPROT_FEATURE_LOCK=y +CONFIG_ESP_SYSTEM_MEMPROT_CPU_PREFETCH_PAD_SIZE=16 +CONFIG_ESP_SYSTEM_MEMPROT_MEM_ALIGN_SIZE=4 +# end of Memory protection + +CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE=32 +CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=2304 +CONFIG_ESP_MAIN_TASK_STACK_SIZE=3584 +CONFIG_ESP_MAIN_TASK_AFFINITY_CPU0=y +# CONFIG_ESP_MAIN_TASK_AFFINITY_NO_AFFINITY is not set +CONFIG_ESP_MAIN_TASK_AFFINITY=0x0 +CONFIG_ESP_MINIMAL_SHARED_STACK_SIZE=2048 +CONFIG_ESP_CONSOLE_UART_DEFAULT=y +# CONFIG_ESP_CONSOLE_USB_CDC is not set +# CONFIG_ESP_CONSOLE_UART_CUSTOM is not set +# CONFIG_ESP_CONSOLE_NONE is not set +CONFIG_ESP_CONSOLE_UART=y +CONFIG_ESP_CONSOLE_MULTIPLE_UART=y +CONFIG_ESP_CONSOLE_UART_NUM=0 +CONFIG_ESP_CONSOLE_UART_BAUDRATE=115200 +CONFIG_ESP_INT_WDT=y +CONFIG_ESP_INT_WDT_TIMEOUT_MS=300 +CONFIG_ESP_TASK_WDT=y +# CONFIG_ESP_TASK_WDT_PANIC is not set +CONFIG_ESP_TASK_WDT_TIMEOUT_S=5 +CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0=y +# CONFIG_ESP_PANIC_HANDLER_IRAM is not set +# CONFIG_ESP_DEBUG_STUBS_ENABLE is not set +CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL_4=y +# end of ESP System Settings + +# +# High resolution timer (esp_timer) +# +# CONFIG_ESP_TIMER_PROFILING is not set +CONFIG_ESP_TIME_FUNCS_USE_RTC_TIMER=y +CONFIG_ESP_TIME_FUNCS_USE_ESP_TIMER=y +CONFIG_ESP_TIMER_TASK_STACK_SIZE=3584 +CONFIG_ESP_TIMER_INTERRUPT_LEVEL=1 +# CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD is not set +CONFIG_ESP_TIMER_IMPL_SYSTIMER=y +# end of High resolution timer (esp_timer) + +# +# Wi-Fi +# +CONFIG_ESP32_WIFI_ENABLED=y +CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=10 +CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=32 +# CONFIG_ESP32_WIFI_STATIC_TX_BUFFER is not set +CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER=y +CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=1 +CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=32 +# CONFIG_ESP32_WIFI_CSI_ENABLED is not set +CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=y +CONFIG_ESP32_WIFI_TX_BA_WIN=6 +CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y +CONFIG_ESP32_WIFI_RX_BA_WIN=6 +CONFIG_ESP32_WIFI_NVS_ENABLED=y +CONFIG_ESP32_WIFI_SOFTAP_BEACON_MAX_LEN=752 +CONFIG_ESP32_WIFI_MGMT_SBUF_NUM=32 +CONFIG_ESP32_WIFI_IRAM_OPT=y +CONFIG_ESP32_WIFI_RX_IRAM_OPT=y +CONFIG_ESP32_WIFI_ENABLE_WPA3_SAE=y +# CONFIG_ESP_WIFI_SLP_IRAM_OPT is not set +# CONFIG_ESP_WIFI_FTM_ENABLE is not set +# CONFIG_ESP_WIFI_STA_DISCONNECTED_PM_ENABLE is not set +# CONFIG_ESP_WIFI_EXTERNAL_COEXIST_ENABLE is not set +# CONFIG_ESP_WIFI_GMAC_SUPPORT is not set +CONFIG_ESP_WIFI_SOFTAP_SUPPORT=y +# end of Wi-Fi + +# +# Core dump +# +# CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH is not set +# CONFIG_ESP_COREDUMP_ENABLE_TO_UART is not set +CONFIG_ESP_COREDUMP_ENABLE_TO_NONE=y +# end of Core dump + +# +# FAT Filesystem support +# +# CONFIG_FATFS_CODEPAGE_DYNAMIC is not set +CONFIG_FATFS_CODEPAGE_437=y +# CONFIG_FATFS_CODEPAGE_720 is not set +# CONFIG_FATFS_CODEPAGE_737 is not set +# CONFIG_FATFS_CODEPAGE_771 is not set +# CONFIG_FATFS_CODEPAGE_775 is not set +# CONFIG_FATFS_CODEPAGE_850 is not set +# CONFIG_FATFS_CODEPAGE_852 is not set +# CONFIG_FATFS_CODEPAGE_855 is not set +# CONFIG_FATFS_CODEPAGE_857 is not set +# CONFIG_FATFS_CODEPAGE_860 is not set +# CONFIG_FATFS_CODEPAGE_861 is not set +# CONFIG_FATFS_CODEPAGE_862 is not set +# CONFIG_FATFS_CODEPAGE_863 is not set +# CONFIG_FATFS_CODEPAGE_864 is not set +# CONFIG_FATFS_CODEPAGE_865 is not set +# CONFIG_FATFS_CODEPAGE_866 is not set +# CONFIG_FATFS_CODEPAGE_869 is not set +# CONFIG_FATFS_CODEPAGE_932 is not set +# CONFIG_FATFS_CODEPAGE_936 is not set +# CONFIG_FATFS_CODEPAGE_949 is not set +# CONFIG_FATFS_CODEPAGE_950 is not set +CONFIG_FATFS_CODEPAGE=437 +CONFIG_FATFS_LFN_NONE=y +# CONFIG_FATFS_LFN_HEAP is not set +# CONFIG_FATFS_LFN_STACK is not set +CONFIG_FATFS_FS_LOCK=0 +CONFIG_FATFS_TIMEOUT_MS=10000 +CONFIG_FATFS_PER_FILE_CACHE=y +# CONFIG_FATFS_USE_FASTSEEK is not set +# end of FAT Filesystem support + +# +# Modbus configuration +# +CONFIG_FMB_COMM_MODE_TCP_EN=y +CONFIG_FMB_TCP_PORT_DEFAULT=502 +CONFIG_FMB_TCP_PORT_MAX_CONN=5 +CONFIG_FMB_TCP_CONNECTION_TOUT_SEC=20 +CONFIG_FMB_COMM_MODE_RTU_EN=y +CONFIG_FMB_COMM_MODE_ASCII_EN=y +CONFIG_FMB_MASTER_TIMEOUT_MS_RESPOND=150 +CONFIG_FMB_MASTER_DELAY_MS_CONVERT=200 +CONFIG_FMB_QUEUE_LENGTH=20 +CONFIG_FMB_PORT_TASK_STACK_SIZE=4096 +CONFIG_FMB_SERIAL_BUF_SIZE=256 +CONFIG_FMB_SERIAL_ASCII_BITS_PER_SYMB=8 +CONFIG_FMB_SERIAL_ASCII_TIMEOUT_RESPOND_MS=1000 +CONFIG_FMB_PORT_TASK_PRIO=10 +CONFIG_FMB_PORT_TASK_AFFINITY=0x7FFFFFFF +CONFIG_FMB_CONTROLLER_SLAVE_ID_SUPPORT=y +CONFIG_FMB_CONTROLLER_SLAVE_ID=0x00112233 +CONFIG_FMB_CONTROLLER_NOTIFY_TIMEOUT=20 +CONFIG_FMB_CONTROLLER_NOTIFY_QUEUE_SIZE=20 +CONFIG_FMB_CONTROLLER_STACK_SIZE=4096 +CONFIG_FMB_EVENT_QUEUE_TIMEOUT=20 +# CONFIG_FMB_TIMER_PORT_ENABLED is not set +CONFIG_FMB_TIMER_GROUP=0 +CONFIG_FMB_TIMER_INDEX=0 +CONFIG_FMB_MASTER_TIMER_GROUP=0 +CONFIG_FMB_MASTER_TIMER_INDEX=0 +# CONFIG_FMB_TIMER_ISR_IN_IRAM is not set +# end of Modbus configuration + +# +# FreeRTOS +# +CONFIG_FREERTOS_UNICORE=y +CONFIG_FREERTOS_NO_AFFINITY=0x7FFFFFFF +CONFIG_FREERTOS_TICK_SUPPORT_CORETIMER=y +CONFIG_FREERTOS_CORETIMER_0=y +# CONFIG_FREERTOS_CORETIMER_1 is not set +CONFIG_FREERTOS_SYSTICK_USES_CCOUNT=y +CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y +CONFIG_FREERTOS_HZ=100 +CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION=y +# CONFIG_FREERTOS_CHECK_STACKOVERFLOW_NONE is not set +# CONFIG_FREERTOS_CHECK_STACKOVERFLOW_PTRVAL is not set +CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY=y +# CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK is not set +CONFIG_FREERTOS_INTERRUPT_BACKTRACE=y +CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=1 +CONFIG_FREERTOS_ASSERT_FAIL_ABORT=y +# CONFIG_FREERTOS_ASSERT_FAIL_PRINT_CONTINUE is not set +# CONFIG_FREERTOS_ASSERT_DISABLE is not set +CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=1536 +CONFIG_FREERTOS_ISR_STACKSIZE=1536 +# CONFIG_FREERTOS_LEGACY_HOOKS is not set +CONFIG_FREERTOS_MAX_TASK_NAME_LEN=16 +CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION=y +# CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP is not set +CONFIG_FREERTOS_TIMER_TASK_PRIORITY=1 +CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=2048 +CONFIG_FREERTOS_TIMER_QUEUE_LENGTH=10 +CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE=0 +CONFIG_FREERTOS_USE_TRACE_FACILITY=y +CONFIG_FREERTOS_USE_STATS_FORMATTING_FUNCTIONS=y +# CONFIG_FREERTOS_VTASKLIST_INCLUDE_COREID is not set +CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS=y +CONFIG_FREERTOS_RUN_TIME_STATS_USING_ESP_TIMER=y +# CONFIG_FREERTOS_RUN_TIME_STATS_USING_CPU_CLK is not set +CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER=y +CONFIG_FREERTOS_CHECK_MUTEX_GIVEN_BY_OWNER=y +# CONFIG_FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE is not set +# CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH is not set +CONFIG_FREERTOS_DEBUG_OCDAWARE=y +CONFIG_FREERTOS_ENABLE_TASK_SNAPSHOT=y +# CONFIG_FREERTOS_PLACE_SNAPSHOT_FUNS_INTO_FLASH is not set +# end of FreeRTOS + +# +# Hardware Abstraction Layer (HAL) and Low Level (LL) +# +CONFIG_HAL_ASSERTION_EQUALS_SYSTEM=y +# CONFIG_HAL_ASSERTION_DISABLE is not set +# CONFIG_HAL_ASSERTION_SILIENT is not set +# CONFIG_HAL_ASSERTION_ENABLE is not set +CONFIG_HAL_DEFAULT_ASSERTION_LEVEL=2 +# end of Hardware Abstraction Layer (HAL) and Low Level (LL) + +# +# Heap memory debugging +# +CONFIG_HEAP_POISONING_DISABLED=y +# CONFIG_HEAP_POISONING_LIGHT is not set +# CONFIG_HEAP_POISONING_COMPREHENSIVE is not set +CONFIG_HEAP_TRACING_OFF=y +# CONFIG_HEAP_TRACING_STANDALONE is not set +# CONFIG_HEAP_TRACING_TOHOST is not set +# CONFIG_HEAP_ABORT_WHEN_ALLOCATION_FAILS is not set +# end of Heap memory debugging + +# +# jsmn +# +# CONFIG_JSMN_PARENT_LINKS is not set +# CONFIG_JSMN_STRICT is not set +# end of jsmn + +# +# libsodium +# +# end of libsodium + +# +# Log output +# +# CONFIG_LOG_DEFAULT_LEVEL_NONE is not set +# CONFIG_LOG_DEFAULT_LEVEL_ERROR is not set +# CONFIG_LOG_DEFAULT_LEVEL_WARN is not set +CONFIG_LOG_DEFAULT_LEVEL_INFO=y +# CONFIG_LOG_DEFAULT_LEVEL_DEBUG is not set +# CONFIG_LOG_DEFAULT_LEVEL_VERBOSE is not set +CONFIG_LOG_DEFAULT_LEVEL=3 +CONFIG_LOG_MAXIMUM_EQUALS_DEFAULT=y +# CONFIG_LOG_MAXIMUM_LEVEL_DEBUG is not set +# CONFIG_LOG_MAXIMUM_LEVEL_VERBOSE is not set +CONFIG_LOG_MAXIMUM_LEVEL=3 +CONFIG_LOG_COLORS=y +CONFIG_LOG_TIMESTAMP_SOURCE_RTOS=y +# CONFIG_LOG_TIMESTAMP_SOURCE_SYSTEM is not set +# end of Log output + +# +# LWIP +# +CONFIG_LWIP_LOCAL_HOSTNAME="espressif" +# CONFIG_LWIP_NETIF_API is not set +# CONFIG_LWIP_TCPIP_CORE_LOCKING is not set +CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES=y +# CONFIG_LWIP_L2_TO_L3_COPY is not set +# CONFIG_LWIP_IRAM_OPTIMIZATION is not set +CONFIG_LWIP_TIMERS_ONDEMAND=y +CONFIG_LWIP_MAX_SOCKETS=10 +# CONFIG_LWIP_USE_ONLY_LWIP_SELECT is not set +# CONFIG_LWIP_SO_LINGER is not set +CONFIG_LWIP_SO_REUSE=y +CONFIG_LWIP_SO_REUSE_RXTOALL=y +# CONFIG_LWIP_SO_RCVBUF is not set +# CONFIG_LWIP_NETBUF_RECVINFO is not set +CONFIG_LWIP_IP4_FRAG=y +CONFIG_LWIP_IP6_FRAG=y +# CONFIG_LWIP_IP4_REASSEMBLY is not set +# CONFIG_LWIP_IP6_REASSEMBLY is not set +# CONFIG_LWIP_IP_FORWARD is not set +# CONFIG_LWIP_STATS is not set +# CONFIG_LWIP_ETHARP_TRUST_IP_MAC is not set +CONFIG_LWIP_ESP_GRATUITOUS_ARP=y +CONFIG_LWIP_GARP_TMR_INTERVAL=60 +CONFIG_LWIP_TCPIP_RECVMBOX_SIZE=32 +CONFIG_LWIP_DHCP_DOES_ARP_CHECK=y +# CONFIG_LWIP_DHCP_DISABLE_CLIENT_ID is not set +CONFIG_LWIP_DHCP_DISABLE_VENDOR_CLASS_ID=y +# CONFIG_LWIP_DHCP_RESTORE_LAST_IP is not set +CONFIG_LWIP_DHCP_OPTIONS_LEN=68 + +# +# DHCP server +# +CONFIG_LWIP_DHCPS=y +CONFIG_LWIP_DHCPS_LEASE_UNIT=60 +CONFIG_LWIP_DHCPS_MAX_STATION_NUM=8 +# end of DHCP server + +# CONFIG_LWIP_AUTOIP is not set +CONFIG_LWIP_IPV6=y +# CONFIG_LWIP_IPV6_AUTOCONFIG is not set +CONFIG_LWIP_IPV6_NUM_ADDRESSES=3 +# CONFIG_LWIP_IPV6_FORWARD is not set +# CONFIG_LWIP_NETIF_STATUS_CALLBACK is not set +CONFIG_LWIP_NETIF_LOOPBACK=y +CONFIG_LWIP_LOOPBACK_MAX_PBUFS=8 + +# +# TCP +# +CONFIG_LWIP_MAX_ACTIVE_TCP=16 +CONFIG_LWIP_MAX_LISTENING_TCP=16 +CONFIG_LWIP_TCP_HIGH_SPEED_RETRANSMISSION=y +CONFIG_LWIP_TCP_MAXRTX=12 +CONFIG_LWIP_TCP_SYNMAXRTX=12 +CONFIG_LWIP_TCP_MSS=1440 +CONFIG_LWIP_TCP_TMR_INTERVAL=250 +CONFIG_LWIP_TCP_MSL=60000 +CONFIG_LWIP_TCP_SND_BUF_DEFAULT=5744 +CONFIG_LWIP_TCP_WND_DEFAULT=5744 +CONFIG_LWIP_TCP_RECVMBOX_SIZE=6 +CONFIG_LWIP_TCP_QUEUE_OOSEQ=y +# CONFIG_LWIP_TCP_SACK_OUT is not set +# CONFIG_LWIP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES is not set +CONFIG_LWIP_TCP_OVERSIZE_MSS=y +# CONFIG_LWIP_TCP_OVERSIZE_QUARTER_MSS is not set +# CONFIG_LWIP_TCP_OVERSIZE_DISABLE is not set +CONFIG_LWIP_TCP_RTO_TIME=1500 +# end of TCP + +# +# UDP +# +CONFIG_LWIP_MAX_UDP_PCBS=16 +CONFIG_LWIP_UDP_RECVMBOX_SIZE=6 +# end of UDP + +# +# Checksums +# +# CONFIG_LWIP_CHECKSUM_CHECK_IP is not set +# CONFIG_LWIP_CHECKSUM_CHECK_UDP is not set +CONFIG_LWIP_CHECKSUM_CHECK_ICMP=y +# end of Checksums + +CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=3072 +CONFIG_LWIP_TCPIP_TASK_AFFINITY_NO_AFFINITY=y +# CONFIG_LWIP_TCPIP_TASK_AFFINITY_CPU0 is not set +CONFIG_LWIP_TCPIP_TASK_AFFINITY=0x7FFFFFFF +# CONFIG_LWIP_PPP_SUPPORT is not set +CONFIG_LWIP_IPV6_MEMP_NUM_ND6_QUEUE=3 +CONFIG_LWIP_IPV6_ND6_NUM_NEIGHBORS=5 +# CONFIG_LWIP_SLIP_SUPPORT is not set + +# +# ICMP +# +CONFIG_LWIP_ICMP=y +# CONFIG_LWIP_MULTICAST_PING is not set +# CONFIG_LWIP_BROADCAST_PING is not set +# end of ICMP + +# +# LWIP RAW API +# +CONFIG_LWIP_MAX_RAW_PCBS=16 +# end of LWIP RAW API + +# +# SNTP +# +CONFIG_LWIP_SNTP_MAX_SERVERS=1 +# CONFIG_LWIP_DHCP_GET_NTP_SRV is not set +CONFIG_LWIP_SNTP_UPDATE_DELAY=3600000 +# end of SNTP + +CONFIG_LWIP_ESP_LWIP_ASSERT=y + +# +# Hooks +# +# CONFIG_LWIP_HOOK_TCP_ISN_NONE is not set +CONFIG_LWIP_HOOK_TCP_ISN_DEFAULT=y +# CONFIG_LWIP_HOOK_TCP_ISN_CUSTOM is not set +CONFIG_LWIP_HOOK_IP6_ROUTE_NONE=y +# CONFIG_LWIP_HOOK_IP6_ROUTE_DEFAULT is not set +# CONFIG_LWIP_HOOK_IP6_ROUTE_CUSTOM is not set +CONFIG_LWIP_HOOK_ND6_GET_GW_NONE=y +# CONFIG_LWIP_HOOK_ND6_GET_GW_DEFAULT is not set +# CONFIG_LWIP_HOOK_ND6_GET_GW_CUSTOM is not set +CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_NONE=y +# CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_DEFAULT is not set +# CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_CUSTOM is not set +# end of Hooks + +# CONFIG_LWIP_DEBUG is not set +# end of LWIP + +# +# mbedTLS +# +CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y +# CONFIG_MBEDTLS_DEFAULT_MEM_ALLOC is not set +# CONFIG_MBEDTLS_CUSTOM_MEM_ALLOC is not set +CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN=y +CONFIG_MBEDTLS_SSL_IN_CONTENT_LEN=16384 +CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN=4096 +# CONFIG_MBEDTLS_DYNAMIC_BUFFER is not set +# CONFIG_MBEDTLS_DEBUG is not set + +# +# mbedTLS v2.28.x related +# +# CONFIG_MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH is not set +# CONFIG_MBEDTLS_X509_TRUSTED_CERT_CALLBACK is not set +# CONFIG_MBEDTLS_SSL_CONTEXT_SERIALIZATION is not set +CONFIG_MBEDTLS_SSL_KEEP_PEER_CERTIFICATE=y +# end of mbedTLS v2.28.x related + +# +# Certificate Bundle +# +CONFIG_MBEDTLS_CERTIFICATE_BUNDLE=y +CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL=y +# CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_CMN is not set +# CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_NONE is not set +# CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE is not set +CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_MAX_CERTS=200 +# end of Certificate Bundle + +# CONFIG_MBEDTLS_ECP_RESTARTABLE is not set +# CONFIG_MBEDTLS_CMAC_C is not set +CONFIG_MBEDTLS_HARDWARE_AES=y +CONFIG_MBEDTLS_AES_USE_INTERRUPT=y +CONFIG_MBEDTLS_HARDWARE_GCM=y +CONFIG_MBEDTLS_HARDWARE_MPI=y +CONFIG_MBEDTLS_HARDWARE_SHA=y +CONFIG_MBEDTLS_ROM_MD5=y +# CONFIG_MBEDTLS_ATCA_HW_ECDSA_SIGN is not set +# CONFIG_MBEDTLS_ATCA_HW_ECDSA_VERIFY is not set +CONFIG_MBEDTLS_HAVE_TIME=y +# CONFIG_MBEDTLS_HAVE_TIME_DATE is not set +CONFIG_MBEDTLS_ECDSA_DETERMINISTIC=y +CONFIG_MBEDTLS_SHA512_C=y +CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT=y +# CONFIG_MBEDTLS_TLS_SERVER_ONLY is not set +# CONFIG_MBEDTLS_TLS_CLIENT_ONLY is not set +# CONFIG_MBEDTLS_TLS_DISABLED is not set +CONFIG_MBEDTLS_TLS_SERVER=y +CONFIG_MBEDTLS_TLS_CLIENT=y +CONFIG_MBEDTLS_TLS_ENABLED=y + +# +# TLS Key Exchange Methods +# +# CONFIG_MBEDTLS_PSK_MODES is not set +CONFIG_MBEDTLS_KEY_EXCHANGE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_RSA=y +# end of TLS Key Exchange Methods + +CONFIG_MBEDTLS_SSL_RENEGOTIATION=y +# CONFIG_MBEDTLS_SSL_PROTO_SSL3 is not set +CONFIG_MBEDTLS_SSL_PROTO_TLS1=y +CONFIG_MBEDTLS_SSL_PROTO_TLS1_1=y +CONFIG_MBEDTLS_SSL_PROTO_TLS1_2=y +# CONFIG_MBEDTLS_SSL_PROTO_GMTSSL1_1 is not set +# CONFIG_MBEDTLS_SSL_PROTO_DTLS is not set +CONFIG_MBEDTLS_SSL_ALPN=y +CONFIG_MBEDTLS_CLIENT_SSL_SESSION_TICKETS=y +CONFIG_MBEDTLS_X509_CHECK_KEY_USAGE=y +CONFIG_MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE=y +CONFIG_MBEDTLS_SERVER_SSL_SESSION_TICKETS=y + +# +# Symmetric Ciphers +# +CONFIG_MBEDTLS_AES_C=y +# CONFIG_MBEDTLS_CAMELLIA_C is not set +# CONFIG_MBEDTLS_DES_C is not set +CONFIG_MBEDTLS_RC4_DISABLED=y +# CONFIG_MBEDTLS_RC4_ENABLED_NO_DEFAULT is not set +# CONFIG_MBEDTLS_RC4_ENABLED is not set +# CONFIG_MBEDTLS_BLOWFISH_C is not set +# CONFIG_MBEDTLS_XTEA_C is not set +CONFIG_MBEDTLS_CCM_C=y +CONFIG_MBEDTLS_GCM_C=y +# CONFIG_MBEDTLS_NIST_KW_C is not set +# end of Symmetric Ciphers + +# CONFIG_MBEDTLS_RIPEMD160_C is not set + +# +# Certificates +# +CONFIG_MBEDTLS_PEM_PARSE_C=y +CONFIG_MBEDTLS_PEM_WRITE_C=y +CONFIG_MBEDTLS_X509_CRL_PARSE_C=y +CONFIG_MBEDTLS_X509_CSR_PARSE_C=y +# end of Certificates + +CONFIG_MBEDTLS_ECP_C=y +CONFIG_MBEDTLS_ECDH_C=y +CONFIG_MBEDTLS_ECDSA_C=y +# CONFIG_MBEDTLS_ECJPAKE_C is not set +CONFIG_MBEDTLS_ECP_DP_SECP192R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP224R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP384R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP521R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP192K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP224K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP256K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP256R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP512R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_CURVE25519_ENABLED=y +CONFIG_MBEDTLS_ECP_NIST_OPTIM=y +# CONFIG_MBEDTLS_POLY1305_C is not set +# CONFIG_MBEDTLS_CHACHA20_C is not set +# CONFIG_MBEDTLS_HKDF_C is not set +# CONFIG_MBEDTLS_THREADING_C is not set +# CONFIG_MBEDTLS_LARGE_KEY_SOFTWARE_MPI is not set +# CONFIG_MBEDTLS_SECURITY_RISKS is not set +# end of mbedTLS + +# +# mDNS +# +CONFIG_MDNS_MAX_SERVICES=10 +CONFIG_MDNS_TASK_PRIORITY=1 +CONFIG_MDNS_TASK_STACK_SIZE=4096 +# CONFIG_MDNS_TASK_AFFINITY_NO_AFFINITY is not set +CONFIG_MDNS_TASK_AFFINITY_CPU0=y +CONFIG_MDNS_TASK_AFFINITY=0x0 +CONFIG_MDNS_SERVICE_ADD_TIMEOUT_MS=2000 +# CONFIG_MDNS_STRICT_MODE is not set +CONFIG_MDNS_TIMER_PERIOD_MS=100 +# CONFIG_MDNS_NETWORKING_SOCKET is not set +CONFIG_MDNS_MULTIPLE_INSTANCE=y +# end of mDNS + +# +# ESP-MQTT Configurations +# +CONFIG_MQTT_PROTOCOL_311=y +CONFIG_MQTT_TRANSPORT_SSL=y +CONFIG_MQTT_TRANSPORT_WEBSOCKET=y +CONFIG_MQTT_TRANSPORT_WEBSOCKET_SECURE=y +# CONFIG_MQTT_MSG_ID_INCREMENTAL is not set +# CONFIG_MQTT_SKIP_PUBLISH_IF_DISCONNECTED is not set +# CONFIG_MQTT_REPORT_DELETED_MESSAGES is not set +# CONFIG_MQTT_USE_CUSTOM_CONFIG is not set +# CONFIG_MQTT_TASK_CORE_SELECTION_ENABLED is not set +# CONFIG_MQTT_CUSTOM_OUTBOX is not set +# end of ESP-MQTT Configurations + +# +# Newlib +# +CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF=y +# CONFIG_NEWLIB_STDOUT_LINE_ENDING_LF is not set +# CONFIG_NEWLIB_STDOUT_LINE_ENDING_CR is not set +# CONFIG_NEWLIB_STDIN_LINE_ENDING_CRLF is not set +# CONFIG_NEWLIB_STDIN_LINE_ENDING_LF is not set +CONFIG_NEWLIB_STDIN_LINE_ENDING_CR=y +# CONFIG_NEWLIB_NANO_FORMAT is not set +# end of Newlib + +# +# NVS +# +# CONFIG_NVS_ASSERT_ERROR_CHECK is not set +# end of NVS + +# +# OpenSSL +# +# CONFIG_OPENSSL_DEBUG is not set +CONFIG_OPENSSL_ERROR_STACK=y +# CONFIG_OPENSSL_ASSERT_DO_NOTHING is not set +CONFIG_OPENSSL_ASSERT_EXIT=y +# end of OpenSSL + +# +# OpenThread +# +# CONFIG_OPENTHREAD_ENABLED is not set +# end of OpenThread + +# +# PThreads +# +CONFIG_PTHREAD_TASK_PRIO_DEFAULT=5 +CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072 +CONFIG_PTHREAD_STACK_MIN=768 +CONFIG_PTHREAD_TASK_CORE_DEFAULT=-1 +CONFIG_PTHREAD_TASK_NAME_DEFAULT="pthread" +# end of PThreads + +# +# SPI Flash driver +# +# CONFIG_SPI_FLASH_VERIFY_WRITE is not set +# CONFIG_SPI_FLASH_ENABLE_COUNTERS is not set +CONFIG_SPI_FLASH_ROM_DRIVER_PATCH=y +CONFIG_SPI_FLASH_DANGEROUS_WRITE_ABORTS=y +# CONFIG_SPI_FLASH_DANGEROUS_WRITE_FAILS is not set +# CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED is not set +# CONFIG_SPI_FLASH_USE_LEGACY_IMPL is not set +# CONFIG_SPI_FLASH_BYPASS_BLOCK_ERASE is not set +CONFIG_SPI_FLASH_YIELD_DURING_ERASE=y +CONFIG_SPI_FLASH_ERASE_YIELD_DURATION_MS=20 +CONFIG_SPI_FLASH_ERASE_YIELD_TICKS=1 +CONFIG_SPI_FLASH_WRITE_CHUNK_SIZE=8192 +# CONFIG_SPI_FLASH_SIZE_OVERRIDE is not set +# CONFIG_SPI_FLASH_CHECK_ERASE_TIMEOUT_DISABLED is not set +# CONFIG_SPI_FLASH_OVERRIDE_CHIP_DRIVER_LIST is not set + +# +# Auto-detect flash chips +# +CONFIG_SPI_FLASH_SUPPORT_ISSI_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_MXIC_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_GD_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_WINBOND_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_BOYA_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_TH_CHIP=y +# end of Auto-detect flash chips + +CONFIG_SPI_FLASH_ENABLE_ENCRYPTED_READ_WRITE=y +# end of SPI Flash driver + +# +# SPIFFS Configuration +# +CONFIG_SPIFFS_MAX_PARTITIONS=3 + +# +# SPIFFS Cache Configuration +# +CONFIG_SPIFFS_CACHE=y +CONFIG_SPIFFS_CACHE_WR=y +# CONFIG_SPIFFS_CACHE_STATS is not set +# end of SPIFFS Cache Configuration + +CONFIG_SPIFFS_PAGE_CHECK=y +CONFIG_SPIFFS_GC_MAX_RUNS=10 +# CONFIG_SPIFFS_GC_STATS is not set +CONFIG_SPIFFS_PAGE_SIZE=256 +CONFIG_SPIFFS_OBJ_NAME_LEN=32 +# CONFIG_SPIFFS_FOLLOW_SYMLINKS is not set +CONFIG_SPIFFS_USE_MAGIC=y +CONFIG_SPIFFS_USE_MAGIC_LENGTH=y +CONFIG_SPIFFS_META_LENGTH=4 +CONFIG_SPIFFS_USE_MTIME=y + +# +# Debug Configuration +# +# CONFIG_SPIFFS_DBG is not set +# CONFIG_SPIFFS_API_DBG is not set +# CONFIG_SPIFFS_GC_DBG is not set +# CONFIG_SPIFFS_CACHE_DBG is not set +# CONFIG_SPIFFS_CHECK_DBG is not set +# CONFIG_SPIFFS_TEST_VISUALISATION is not set +# end of Debug Configuration +# end of SPIFFS Configuration + +# +# TCP Transport +# + +# +# Websocket +# +CONFIG_WS_TRANSPORT=y +CONFIG_WS_BUFFER_SIZE=1024 +# end of Websocket +# end of TCP Transport + +# +# TinyUSB Stack +# +# CONFIG_TINYUSB is not set +# end of TinyUSB Stack + +# +# Unity unit testing library +# +CONFIG_UNITY_ENABLE_FLOAT=y +CONFIG_UNITY_ENABLE_DOUBLE=y +# CONFIG_UNITY_ENABLE_64BIT is not set +# CONFIG_UNITY_ENABLE_COLOR is not set +CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y +# CONFIG_UNITY_ENABLE_FIXTURE is not set +# CONFIG_UNITY_ENABLE_BACKTRACE_ON_FAIL is not set +# end of Unity unit testing library + +# +# USB-OTG +# +CONFIG_USB_OTG_SUPPORTED=y +CONFIG_USB_HOST_CONTROL_TRANSFER_MAX_SIZE=256 +CONFIG_USB_HOST_HW_BUFFER_BIAS_BALANCED=y +# CONFIG_USB_HOST_HW_BUFFER_BIAS_IN is not set +# CONFIG_USB_HOST_HW_BUFFER_BIAS_PERIODIC_OUT is not set +# end of USB-OTG + +# +# Virtual file system +# +CONFIG_VFS_SUPPORT_IO=y +CONFIG_VFS_SUPPORT_DIR=y +CONFIG_VFS_SUPPORT_SELECT=y +CONFIG_VFS_SUPPRESS_SELECT_DEBUG_OUTPUT=y +CONFIG_VFS_SUPPORT_TERMIOS=y + +# +# Host File System I/O (Semihosting) +# +CONFIG_VFS_SEMIHOSTFS_MAX_MOUNT_POINTS=1 +# end of Host File System I/O (Semihosting) +# end of Virtual file system + +# +# Wear Levelling +# +# CONFIG_WL_SECTOR_SIZE_512 is not set +CONFIG_WL_SECTOR_SIZE_4096=y +CONFIG_WL_SECTOR_SIZE=4096 +# end of Wear Levelling + +# +# Wi-Fi Provisioning Manager +# +CONFIG_WIFI_PROV_SCAN_MAX_ENTRIES=16 +CONFIG_WIFI_PROV_AUTOSTOP_TIMEOUT=30 +CONFIG_WIFI_PROV_BLE_FORCE_ENCRYPTION=y +# end of Wi-Fi Provisioning Manager + +# +# Supplicant +# +CONFIG_WPA_MBEDTLS_CRYPTO=y +# CONFIG_WPA_WAPI_PSK is not set +# CONFIG_WPA_SUITE_B_192 is not set +# CONFIG_WPA_DEBUG_PRINT is not set +# CONFIG_WPA_TESTING_OPTIONS is not set +# CONFIG_WPA_WPS_STRICT is not set +# CONFIG_WPA_11KV_SUPPORT is not set +# CONFIG_WPA_MBO_SUPPORT is not set +# CONFIG_WPA_DPP_SUPPORT is not set +# end of Supplicant +# end of Component config + +# +# Compatibility options +# +# CONFIG_LEGACY_INCLUDE_COMMON_HEADERS is not set +# end of Compatibility options + +# Deprecated options for backward compatibility +CONFIG_TOOLPREFIX="xtensa-esp32s2-elf-" +# CONFIG_LOG_BOOTLOADER_LEVEL_NONE is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_ERROR is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_WARN is not set +CONFIG_LOG_BOOTLOADER_LEVEL_INFO=y +# CONFIG_LOG_BOOTLOADER_LEVEL_DEBUG is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_VERBOSE is not set +CONFIG_LOG_BOOTLOADER_LEVEL=3 +# CONFIG_APP_ROLLBACK_ENABLE is not set +# CONFIG_FLASH_ENCRYPTION_ENABLED is not set +# CONFIG_FLASHMODE_QIO is not set +# CONFIG_FLASHMODE_QOUT is not set +CONFIG_FLASHMODE_DIO=y +# CONFIG_FLASHMODE_DOUT is not set +# CONFIG_MONITOR_BAUD_9600B is not set +# CONFIG_MONITOR_BAUD_57600B is not set +CONFIG_MONITOR_BAUD_115200B=y +# CONFIG_MONITOR_BAUD_230400B is not set +# CONFIG_MONITOR_BAUD_921600B is not set +# CONFIG_MONITOR_BAUD_2MB is not set +# CONFIG_MONITOR_BAUD_OTHER is not set +CONFIG_MONITOR_BAUD_OTHER_VAL=115200 +CONFIG_MONITOR_BAUD=115200 +CONFIG_COMPILER_OPTIMIZATION_LEVEL_DEBUG=y +# CONFIG_COMPILER_OPTIMIZATION_LEVEL_RELEASE is not set +CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED=y +# CONFIG_OPTIMIZATION_ASSERTIONS_SILENT is not set +# CONFIG_OPTIMIZATION_ASSERTIONS_DISABLED is not set +CONFIG_OPTIMIZATION_ASSERTION_LEVEL=2 +# CONFIG_CXX_EXCEPTIONS is not set +CONFIG_STACK_CHECK_NONE=y +# CONFIG_STACK_CHECK_NORM is not set +# CONFIG_STACK_CHECK_STRONG is not set +# CONFIG_STACK_CHECK_ALL is not set +# CONFIG_WARN_WRITE_STRINGS is not set +# CONFIG_DISABLE_GCC8_WARNINGS is not set +# CONFIG_ESP32_APPTRACE_DEST_TRAX is not set +CONFIG_ESP32_APPTRACE_DEST_NONE=y +CONFIG_ESP32_APPTRACE_LOCK_ENABLE=y +CONFIG_ADC2_DISABLE_DAC=y +# CONFIG_EVENT_LOOP_PROFILING is not set +CONFIG_POST_EVENTS_FROM_ISR=y +CONFIG_POST_EVENTS_FROM_IRAM_ISR=y +CONFIG_ESP_SYSTEM_PD_FLASH=y +# CONFIG_ESP32C3_LIGHTSLEEP_GPIO_RESET_WORKAROUND is not set +CONFIG_IPC_TASK_STACK_SIZE=1536 +CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE=y +# CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION is not set +CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER=20 +CONFIG_ESP32_PHY_MAX_TX_POWER=20 +# CONFIG_ESP32S2_PANIC_PRINT_HALT is not set +CONFIG_ESP32S2_PANIC_PRINT_REBOOT=y +# CONFIG_ESP32S2_PANIC_SILENT_REBOOT is not set +# CONFIG_ESP32S2_PANIC_GDBSTUB is not set +CONFIG_ESP32S2_ALLOW_RTC_FAST_MEM_AS_HEAP=y +CONFIG_ESP32H2_MEMPROT_FEATURE=y +CONFIG_ESP32H2_MEMPROT_FEATURE_LOCK=y +CONFIG_SYSTEM_EVENT_QUEUE_SIZE=32 +CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=2304 +CONFIG_MAIN_TASK_STACK_SIZE=3584 +CONFIG_CONSOLE_UART_DEFAULT=y +# CONFIG_CONSOLE_UART_CUSTOM is not set +# CONFIG_ESP_CONSOLE_UART_NONE is not set +CONFIG_CONSOLE_UART=y +CONFIG_CONSOLE_UART_NUM=0 +CONFIG_CONSOLE_UART_BAUDRATE=115200 +CONFIG_INT_WDT=y +CONFIG_INT_WDT_TIMEOUT_MS=300 +CONFIG_TASK_WDT=y +# CONFIG_TASK_WDT_PANIC is not set +CONFIG_TASK_WDT_TIMEOUT_S=5 +CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0=y +# CONFIG_ESP32_DEBUG_STUBS_ENABLE is not set +CONFIG_TIMER_TASK_STACK_SIZE=3584 +# CONFIG_EXTERNAL_COEX_ENABLE is not set +# CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH is not set +# CONFIG_ESP32_ENABLE_COREDUMP_TO_UART is not set +CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE=y +CONFIG_MB_MASTER_TIMEOUT_MS_RESPOND=150 +CONFIG_MB_MASTER_DELAY_MS_CONVERT=200 +CONFIG_MB_QUEUE_LENGTH=20 +CONFIG_MB_SERIAL_TASK_STACK_SIZE=4096 +CONFIG_MB_SERIAL_BUF_SIZE=256 +CONFIG_MB_SERIAL_TASK_PRIO=10 +CONFIG_MB_CONTROLLER_SLAVE_ID_SUPPORT=y +CONFIG_MB_CONTROLLER_SLAVE_ID=0x00112233 +CONFIG_MB_CONTROLLER_NOTIFY_TIMEOUT=20 +CONFIG_MB_CONTROLLER_NOTIFY_QUEUE_SIZE=20 +CONFIG_MB_CONTROLLER_STACK_SIZE=4096 +CONFIG_MB_EVENT_QUEUE_TIMEOUT=20 +# CONFIG_MB_TIMER_PORT_ENABLED is not set +CONFIG_MB_TIMER_GROUP=0 +CONFIG_MB_TIMER_INDEX=0 +# CONFIG_ENABLE_STATIC_TASK_CLEAN_UP_HOOK is not set +CONFIG_TIMER_TASK_PRIORITY=1 +CONFIG_TIMER_TASK_STACK_DEPTH=2048 +CONFIG_TIMER_QUEUE_LENGTH=10 +# CONFIG_L2_TO_L3_COPY is not set +# CONFIG_USE_ONLY_LWIP_SELECT is not set +CONFIG_ESP_GRATUITOUS_ARP=y +CONFIG_GARP_TMR_INTERVAL=60 +CONFIG_TCPIP_RECVMBOX_SIZE=32 +CONFIG_TCP_MAXRTX=12 +CONFIG_TCP_SYNMAXRTX=12 +CONFIG_TCP_MSS=1440 +CONFIG_TCP_MSL=60000 +CONFIG_TCP_SND_BUF_DEFAULT=5744 +CONFIG_TCP_WND_DEFAULT=5744 +CONFIG_TCP_RECVMBOX_SIZE=6 +CONFIG_TCP_QUEUE_OOSEQ=y +# CONFIG_ESP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES is not set +CONFIG_TCP_OVERSIZE_MSS=y +# CONFIG_TCP_OVERSIZE_QUARTER_MSS is not set +# CONFIG_TCP_OVERSIZE_DISABLE is not set +CONFIG_UDP_RECVMBOX_SIZE=6 +CONFIG_TCPIP_TASK_STACK_SIZE=3072 +CONFIG_TCPIP_TASK_AFFINITY_NO_AFFINITY=y +# CONFIG_TCPIP_TASK_AFFINITY_CPU0 is not set +CONFIG_TCPIP_TASK_AFFINITY=0x7FFFFFFF +# CONFIG_PPP_SUPPORT is not set +CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT=5 +CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072 +CONFIG_ESP32_PTHREAD_STACK_MIN=768 +CONFIG_ESP32_PTHREAD_TASK_CORE_DEFAULT=-1 +CONFIG_ESP32_PTHREAD_TASK_NAME_DEFAULT="pthread" +CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ABORTS=y +# CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_FAILS is not set +# CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ALLOWED is not set +# CONFIG_USB_ENABLED is not set +CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT=y +CONFIG_SUPPORT_TERMIOS=y +CONFIG_SEMIHOSTFS_MAX_MOUNT_POINTS=1 +# End of deprecated options diff --git a/sdkconfig.old b/sdkconfig.old new file mode 100644 index 0000000..ba31434 --- /dev/null +++ b/sdkconfig.old @@ -0,0 +1,1376 @@ +# +# Automatically generated file. DO NOT EDIT. +# Espressif IoT Development Framework (ESP-IDF) Project Configuration +# +CONFIG_IDF_CMAKE=y +CONFIG_IDF_TARGET_ARCH_XTENSA=y +CONFIG_IDF_TARGET="esp32s2" +CONFIG_IDF_TARGET_ESP32S2=y +CONFIG_IDF_FIRMWARE_CHIP_ID=0x0002 + +# +# SDK tool configuration +# +CONFIG_SDK_TOOLPREFIX="xtensa-esp32s2-elf-" +# CONFIG_SDK_TOOLCHAIN_SUPPORTS_TIME_WIDE_64_BITS is not set +# end of SDK tool configuration + +# +# Build type +# +CONFIG_APP_BUILD_TYPE_APP_2NDBOOT=y +# CONFIG_APP_BUILD_TYPE_ELF_RAM is not set +CONFIG_APP_BUILD_GENERATE_BINARIES=y +CONFIG_APP_BUILD_BOOTLOADER=y +CONFIG_APP_BUILD_USE_FLASH_SECTIONS=y +# end of Build type + +# +# Application manager +# +CONFIG_APP_COMPILE_TIME_DATE=y +# CONFIG_APP_EXCLUDE_PROJECT_VER_VAR is not set +# CONFIG_APP_EXCLUDE_PROJECT_NAME_VAR is not set +# CONFIG_APP_PROJECT_VER_FROM_CONFIG is not set +CONFIG_APP_RETRIEVE_LEN_ELF_SHA=16 +# end of Application manager + +# +# Bootloader config +# +CONFIG_BOOTLOADER_OFFSET_IN_FLASH=0x1000 +CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y +# CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_DEBUG is not set +# CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_PERF is not set +# CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_NONE is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_NONE is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_ERROR is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_WARN is not set +CONFIG_BOOTLOADER_LOG_LEVEL_INFO=y +# CONFIG_BOOTLOADER_LOG_LEVEL_DEBUG is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_VERBOSE is not set +CONFIG_BOOTLOADER_LOG_LEVEL=3 +CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V=y +# CONFIG_BOOTLOADER_FACTORY_RESET is not set +# CONFIG_BOOTLOADER_APP_TEST is not set +CONFIG_BOOTLOADER_REGION_PROTECTION_ENABLE=y +CONFIG_BOOTLOADER_WDT_ENABLE=y +# CONFIG_BOOTLOADER_WDT_DISABLE_IN_USER_CODE is not set +CONFIG_BOOTLOADER_WDT_TIME_MS=9000 +# CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE is not set +# CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP is not set +# CONFIG_BOOTLOADER_SKIP_VALIDATE_ON_POWER_ON is not set +# CONFIG_BOOTLOADER_SKIP_VALIDATE_ALWAYS is not set +CONFIG_BOOTLOADER_RESERVE_RTC_SIZE=0 +# CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC is not set +CONFIG_BOOTLOADER_FLASH_XMC_SUPPORT=y +# end of Bootloader config + +# +# Security features +# +CONFIG_SECURE_BOOT_SUPPORTS_RSA=y +CONFIG_SECURE_TARGET_HAS_SECURE_ROM_DL_MODE=y +# CONFIG_SECURE_SIGNED_APPS_NO_SECURE_BOOT is not set +# CONFIG_SECURE_BOOT is not set +# CONFIG_SECURE_FLASH_ENC_ENABLED is not set +# end of Security features + +# +# Boot ROM Behavior +# +CONFIG_BOOT_ROM_LOG_ALWAYS_ON=y +# CONFIG_BOOT_ROM_LOG_ALWAYS_OFF is not set +# CONFIG_BOOT_ROM_LOG_ON_GPIO_HIGH is not set +# CONFIG_BOOT_ROM_LOG_ON_GPIO_LOW is not set +# end of Boot ROM Behavior + +# +# Serial flasher config +# +CONFIG_ESPTOOLPY_BAUD_OTHER_VAL=115200 +# CONFIG_ESPTOOLPY_NO_STUB is not set +# CONFIG_ESPTOOLPY_FLASHMODE_QIO is not set +# CONFIG_ESPTOOLPY_FLASHMODE_QOUT is not set +CONFIG_ESPTOOLPY_FLASHMODE_DIO=y +# CONFIG_ESPTOOLPY_FLASHMODE_DOUT is not set +CONFIG_ESPTOOLPY_FLASH_SAMPLE_MODE_STR=y +CONFIG_ESPTOOLPY_FLASHMODE="dio" +CONFIG_ESPTOOLPY_FLASHFREQ_80M=y +# CONFIG_ESPTOOLPY_FLASHFREQ_40M is not set +# CONFIG_ESPTOOLPY_FLASHFREQ_26M is not set +# CONFIG_ESPTOOLPY_FLASHFREQ_20M is not set +CONFIG_ESPTOOLPY_FLASHFREQ="80m" +# CONFIG_ESPTOOLPY_FLASHSIZE_1MB is not set +CONFIG_ESPTOOLPY_FLASHSIZE_2MB=y +# CONFIG_ESPTOOLPY_FLASHSIZE_4MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_8MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_16MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_32MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_64MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_128MB is not set +CONFIG_ESPTOOLPY_FLASHSIZE="2MB" +CONFIG_ESPTOOLPY_FLASHSIZE_DETECT=y +CONFIG_ESPTOOLPY_BEFORE_RESET=y +# CONFIG_ESPTOOLPY_BEFORE_NORESET is not set +CONFIG_ESPTOOLPY_BEFORE="default_reset" +CONFIG_ESPTOOLPY_AFTER_RESET=y +# CONFIG_ESPTOOLPY_AFTER_NORESET is not set +CONFIG_ESPTOOLPY_AFTER="hard_reset" +# CONFIG_ESPTOOLPY_MONITOR_BAUD_CONSOLE is not set +# CONFIG_ESPTOOLPY_MONITOR_BAUD_9600B is not set +# CONFIG_ESPTOOLPY_MONITOR_BAUD_57600B is not set +CONFIG_ESPTOOLPY_MONITOR_BAUD_115200B=y +# CONFIG_ESPTOOLPY_MONITOR_BAUD_230400B is not set +# CONFIG_ESPTOOLPY_MONITOR_BAUD_921600B is not set +# CONFIG_ESPTOOLPY_MONITOR_BAUD_2MB is not set +# CONFIG_ESPTOOLPY_MONITOR_BAUD_OTHER is not set +CONFIG_ESPTOOLPY_MONITOR_BAUD_OTHER_VAL=115200 +CONFIG_ESPTOOLPY_MONITOR_BAUD=115200 +# end of Serial flasher config + +# +# Partition Table +# +CONFIG_PARTITION_TABLE_SINGLE_APP=y +# CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE is not set +# CONFIG_PARTITION_TABLE_TWO_OTA is not set +# CONFIG_PARTITION_TABLE_CUSTOM is not set +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" +CONFIG_PARTITION_TABLE_FILENAME="partitions_singleapp.csv" +CONFIG_PARTITION_TABLE_OFFSET=0x8000 +CONFIG_PARTITION_TABLE_MD5=y +# end of Partition Table + +# +# ST7789 Configuration +# +CONFIG_GPIO_RANGE_MAX=46 +CONFIG_WIDTH=240 +CONFIG_HEIGHT=280 +CONFIG_OFFSETX=0 +CONFIG_OFFSETY=0 +CONFIG_MOSI_GPIO=11 +CONFIG_SCLK_GPIO=12 +CONFIG_CS_GPIO=-1 +CONFIG_DC_GPIO=13 +CONFIG_RESET_GPIO=10 +CONFIG_BL_GPIO=14 +# CONFIG_INVERSION is not set +# CONFIG_SPI2_HOST is not set +CONFIG_SPI3_HOST=y +# end of ST7789 Configuration + +# +# Compiler options +# +CONFIG_COMPILER_OPTIMIZATION_DEFAULT=y +# CONFIG_COMPILER_OPTIMIZATION_SIZE is not set +# CONFIG_COMPILER_OPTIMIZATION_PERF is not set +# CONFIG_COMPILER_OPTIMIZATION_NONE is not set +CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE=y +# CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT is not set +# CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE is not set +CONFIG_COMPILER_OPTIMIZATION_ASSERTION_LEVEL=2 +# CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT is not set +CONFIG_COMPILER_HIDE_PATHS_MACROS=y +# CONFIG_COMPILER_CXX_EXCEPTIONS is not set +# CONFIG_COMPILER_CXX_RTTI is not set +CONFIG_COMPILER_STACK_CHECK_MODE_NONE=y +# CONFIG_COMPILER_STACK_CHECK_MODE_NORM is not set +# CONFIG_COMPILER_STACK_CHECK_MODE_STRONG is not set +# CONFIG_COMPILER_STACK_CHECK_MODE_ALL is not set +# CONFIG_COMPILER_WARN_WRITE_STRINGS is not set +# CONFIG_COMPILER_DISABLE_GCC8_WARNINGS is not set +# CONFIG_COMPILER_DUMP_RTL_FILES is not set +# end of Compiler options + +# +# Component config +# + +# +# Application Level Tracing +# +# CONFIG_APPTRACE_DEST_JTAG is not set +CONFIG_APPTRACE_DEST_NONE=y +CONFIG_APPTRACE_LOCK_ENABLE=y +# end of Application Level Tracing + +# +# ESP-ASIO +# +# CONFIG_ASIO_SSL_SUPPORT is not set +# end of ESP-ASIO + +# +# CoAP Configuration +# +CONFIG_COAP_MBEDTLS_PSK=y +# CONFIG_COAP_MBEDTLS_PKI is not set +# CONFIG_COAP_MBEDTLS_DEBUG is not set +CONFIG_COAP_LOG_DEFAULT_LEVEL=0 +# end of CoAP Configuration + +# +# Driver configurations +# + +# +# ADC configuration +# +# CONFIG_ADC_FORCE_XPD_FSM is not set +CONFIG_ADC_DISABLE_DAC=y +# end of ADC configuration + +# +# MCPWM configuration +# +# CONFIG_MCPWM_ISR_IN_IRAM is not set +# end of MCPWM configuration + +# +# SPI configuration +# +# CONFIG_SPI_MASTER_IN_IRAM is not set +CONFIG_SPI_MASTER_ISR_IN_IRAM=y +# CONFIG_SPI_SLAVE_IN_IRAM is not set +CONFIG_SPI_SLAVE_ISR_IN_IRAM=y +# end of SPI configuration + +# +# TWAI configuration +# +# CONFIG_TWAI_ISR_IN_IRAM is not set +# end of TWAI configuration + +# +# UART configuration +# +# CONFIG_UART_ISR_IN_IRAM is not set +# end of UART configuration + +# +# GDMA Configuration +# +# CONFIG_GDMA_CTRL_FUNC_IN_IRAM is not set +# CONFIG_GDMA_ISR_IRAM_SAFE is not set +# end of GDMA Configuration +# end of Driver configurations + +# +# eFuse Bit Manager +# +# CONFIG_EFUSE_CUSTOM_TABLE is not set +# CONFIG_EFUSE_VIRTUAL is not set +CONFIG_EFUSE_MAX_BLK_LEN=256 +# end of eFuse Bit Manager + +# +# ESP-TLS +# +CONFIG_ESP_TLS_USING_MBEDTLS=y +CONFIG_ESP_TLS_USE_DS_PERIPHERAL=y +# CONFIG_ESP_TLS_CLIENT_SESSION_TICKETS is not set +# CONFIG_ESP_TLS_SERVER is not set +# CONFIG_ESP_TLS_PSK_VERIFICATION is not set +# CONFIG_ESP_TLS_INSECURE is not set +# end of ESP-TLS + +# +# ESP32S2-specific +# +# CONFIG_ESP32S2_DEFAULT_CPU_FREQ_80 is not set +CONFIG_ESP32S2_DEFAULT_CPU_FREQ_160=y +# CONFIG_ESP32S2_DEFAULT_CPU_FREQ_240 is not set +CONFIG_ESP32S2_DEFAULT_CPU_FREQ_MHZ=160 + +# +# Cache config +# +CONFIG_ESP32S2_INSTRUCTION_CACHE_8KB=y +# CONFIG_ESP32S2_INSTRUCTION_CACHE_16KB is not set +# CONFIG_ESP32S2_INSTRUCTION_CACHE_LINE_16B is not set +CONFIG_ESP32S2_INSTRUCTION_CACHE_LINE_32B=y +CONFIG_ESP32S2_DATA_CACHE_0KB=y +# CONFIG_ESP32S2_DATA_CACHE_8KB is not set +# CONFIG_ESP32S2_DATA_CACHE_16KB is not set +# CONFIG_ESP32S2_DATA_CACHE_LINE_16B is not set +CONFIG_ESP32S2_DATA_CACHE_LINE_32B=y +# CONFIG_ESP32S2_INSTRUCTION_CACHE_WRAP is not set +# CONFIG_ESP32S2_DATA_CACHE_WRAP is not set +# end of Cache config + +# CONFIG_ESP32S2_SPIRAM_SUPPORT is not set +# CONFIG_ESP32S2_TRAX is not set +CONFIG_ESP32S2_TRACEMEM_RESERVE_DRAM=0x0 +# CONFIG_ESP32S2_ULP_COPROC_ENABLED is not set +CONFIG_ESP32S2_ULP_COPROC_RESERVE_MEM=0 +CONFIG_ESP32S2_DEBUG_OCDAWARE=y +CONFIG_ESP32S2_BROWNOUT_DET=y +CONFIG_ESP32S2_BROWNOUT_DET_LVL_SEL_7=y +# CONFIG_ESP32S2_BROWNOUT_DET_LVL_SEL_6 is not set +# CONFIG_ESP32S2_BROWNOUT_DET_LVL_SEL_5 is not set +# CONFIG_ESP32S2_BROWNOUT_DET_LVL_SEL_4 is not set +# CONFIG_ESP32S2_BROWNOUT_DET_LVL_SEL_3 is not set +# CONFIG_ESP32S2_BROWNOUT_DET_LVL_SEL_2 is not set +# CONFIG_ESP32S2_BROWNOUT_DET_LVL_SEL_1 is not set +CONFIG_ESP32S2_BROWNOUT_DET_LVL=7 +CONFIG_ESP32S2_TIME_SYSCALL_USE_RTC_FRC1=y +# CONFIG_ESP32S2_TIME_SYSCALL_USE_RTC is not set +# CONFIG_ESP32S2_TIME_SYSCALL_USE_FRC1 is not set +# CONFIG_ESP32S2_TIME_SYSCALL_USE_NONE is not set +CONFIG_ESP32S2_RTC_CLK_SRC_INT_RC=y +# CONFIG_ESP32S2_RTC_CLK_SRC_EXT_CRYS is not set +# CONFIG_ESP32S2_RTC_CLK_SRC_EXT_OSC is not set +# CONFIG_ESP32S2_RTC_CLK_SRC_INT_8MD256 is not set +CONFIG_ESP32S2_RTC_CLK_CAL_CYCLES=576 +# CONFIG_ESP32S2_NO_BLOBS is not set +# CONFIG_ESP32S2_KEEP_USB_ALIVE is not set +# CONFIG_ESP32S2_RTCDATA_IN_FAST_MEM is not set +# CONFIG_ESP32S2_USE_FIXED_STATIC_RAM_SIZE is not set +# end of ESP32S2-specific + +# +# ADC-Calibration +# +# end of ADC-Calibration + +# +# Common ESP-related +# +CONFIG_ESP_ERR_TO_NAME_LOOKUP=y +# end of Common ESP-related + +# +# Ethernet +# +CONFIG_ETH_ENABLED=y +CONFIG_ETH_USE_SPI_ETHERNET=y +# CONFIG_ETH_SPI_ETHERNET_DM9051 is not set +# CONFIG_ETH_SPI_ETHERNET_W5500 is not set +# CONFIG_ETH_SPI_ETHERNET_KSZ8851SNL is not set +# CONFIG_ETH_USE_OPENETH is not set +# end of Ethernet + +# +# Event Loop Library +# +# CONFIG_ESP_EVENT_LOOP_PROFILING is not set +CONFIG_ESP_EVENT_POST_FROM_ISR=y +CONFIG_ESP_EVENT_POST_FROM_IRAM_ISR=y +# end of Event Loop Library + +# +# GDB Stub +# +# end of GDB Stub + +# +# ESP HTTP client +# +CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS=y +# CONFIG_ESP_HTTP_CLIENT_ENABLE_BASIC_AUTH is not set +CONFIG_ESP_HTTP_CLIENT_ENABLE_DIGEST_AUTH=y +# end of ESP HTTP client + +# +# HTTP Server +# +CONFIG_HTTPD_MAX_REQ_HDR_LEN=512 +CONFIG_HTTPD_MAX_URI_LEN=512 +CONFIG_HTTPD_ERR_RESP_NO_DELAY=y +CONFIG_HTTPD_PURGE_BUF_LEN=32 +# CONFIG_HTTPD_LOG_PURGE_DATA is not set +# CONFIG_HTTPD_WS_SUPPORT is not set +# end of HTTP Server + +# +# ESP HTTPS OTA +# +# CONFIG_OTA_ALLOW_HTTP is not set +# end of ESP HTTPS OTA + +# +# ESP HTTPS server +# +# CONFIG_ESP_HTTPS_SERVER_ENABLE is not set +# end of ESP HTTPS server + +# +# Hardware Settings +# + +# +# MAC Config +# +CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_STA=y +CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_AP=y +# CONFIG_ESP32S2_UNIVERSAL_MAC_ADDRESSES_ONE is not set +CONFIG_ESP32S2_UNIVERSAL_MAC_ADDRESSES_TWO=y +CONFIG_ESP32S2_UNIVERSAL_MAC_ADDRESSES=2 +# end of MAC Config + +# +# Sleep Config +# +CONFIG_ESP_SLEEP_POWER_DOWN_FLASH=y +CONFIG_ESP_SLEEP_RTC_BUS_ISO_WORKAROUND=y +# CONFIG_ESP_SLEEP_GPIO_RESET_WORKAROUND is not set +# CONFIG_ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND is not set +# end of Sleep Config + +# +# RTC Clock Config +# +# end of RTC Clock Config +# end of Hardware Settings + +# +# IPC (Inter-Processor Call) +# +CONFIG_ESP_IPC_TASK_STACK_SIZE=1536 +# end of IPC (Inter-Processor Call) + +# +# LCD and Touch Panel +# + +# +# LCD Peripheral Configuration +# +CONFIG_LCD_PANEL_IO_FORMAT_BUF_SIZE=32 +# end of LCD Peripheral Configuration +# end of LCD and Touch Panel + +# +# ESP NETIF Adapter +# +CONFIG_ESP_NETIF_IP_LOST_TIMER_INTERVAL=120 +CONFIG_ESP_NETIF_TCPIP_LWIP=y +# CONFIG_ESP_NETIF_LOOPBACK is not set +CONFIG_ESP_NETIF_TCPIP_ADAPTER_COMPATIBLE_LAYER=y +# end of ESP NETIF Adapter + +# +# PHY +# +CONFIG_ESP_PHY_CALIBRATION_AND_DATA_STORAGE=y +# CONFIG_ESP_PHY_INIT_DATA_IN_PARTITION is not set +CONFIG_ESP_PHY_MAX_WIFI_TX_POWER=20 +CONFIG_ESP_PHY_MAX_TX_POWER=20 +# CONFIG_ESP_PHY_ENABLE_USB is not set +# end of PHY + +# +# Power Management +# +# CONFIG_PM_ENABLE is not set +# end of Power Management + +# +# ESP System Settings +# +# CONFIG_ESP_SYSTEM_PANIC_PRINT_HALT is not set +CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT=y +# CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT is not set +# CONFIG_ESP_SYSTEM_PANIC_GDBSTUB is not set +# CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME is not set +CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE=y +CONFIG_ESP_SYSTEM_RTC_FAST_MEM_AS_HEAP_DEPCHECK=y +CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP=y + +# +# Memory protection +# +CONFIG_ESP_SYSTEM_MEMPROT_DEPCHECK=y +CONFIG_ESP_SYSTEM_MEMPROT_FEATURE=y +CONFIG_ESP_SYSTEM_MEMPROT_FEATURE_LOCK=y +CONFIG_ESP_SYSTEM_MEMPROT_CPU_PREFETCH_PAD_SIZE=16 +CONFIG_ESP_SYSTEM_MEMPROT_MEM_ALIGN_SIZE=4 +# end of Memory protection + +CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE=32 +CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=2304 +CONFIG_ESP_MAIN_TASK_STACK_SIZE=3584 +CONFIG_ESP_MAIN_TASK_AFFINITY_CPU0=y +# CONFIG_ESP_MAIN_TASK_AFFINITY_NO_AFFINITY is not set +CONFIG_ESP_MAIN_TASK_AFFINITY=0x0 +CONFIG_ESP_MINIMAL_SHARED_STACK_SIZE=2048 +CONFIG_ESP_CONSOLE_UART_DEFAULT=y +# CONFIG_ESP_CONSOLE_USB_CDC is not set +# CONFIG_ESP_CONSOLE_UART_CUSTOM is not set +# CONFIG_ESP_CONSOLE_NONE is not set +CONFIG_ESP_CONSOLE_UART=y +CONFIG_ESP_CONSOLE_MULTIPLE_UART=y +CONFIG_ESP_CONSOLE_UART_NUM=0 +CONFIG_ESP_CONSOLE_UART_BAUDRATE=115200 +CONFIG_ESP_INT_WDT=y +CONFIG_ESP_INT_WDT_TIMEOUT_MS=300 +CONFIG_ESP_TASK_WDT=y +# CONFIG_ESP_TASK_WDT_PANIC is not set +CONFIG_ESP_TASK_WDT_TIMEOUT_S=5 +CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0=y +# CONFIG_ESP_PANIC_HANDLER_IRAM is not set +# CONFIG_ESP_DEBUG_STUBS_ENABLE is not set +CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL_4=y +# end of ESP System Settings + +# +# High resolution timer (esp_timer) +# +# CONFIG_ESP_TIMER_PROFILING is not set +CONFIG_ESP_TIME_FUNCS_USE_RTC_TIMER=y +CONFIG_ESP_TIME_FUNCS_USE_ESP_TIMER=y +CONFIG_ESP_TIMER_TASK_STACK_SIZE=3584 +CONFIG_ESP_TIMER_INTERRUPT_LEVEL=1 +# CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD is not set +CONFIG_ESP_TIMER_IMPL_SYSTIMER=y +# end of High resolution timer (esp_timer) + +# +# Wi-Fi +# +CONFIG_ESP32_WIFI_ENABLED=y +CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=10 +CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=32 +# CONFIG_ESP32_WIFI_STATIC_TX_BUFFER is not set +CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER=y +CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=1 +CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=32 +# CONFIG_ESP32_WIFI_CSI_ENABLED is not set +CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=y +CONFIG_ESP32_WIFI_TX_BA_WIN=6 +CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y +CONFIG_ESP32_WIFI_RX_BA_WIN=6 +CONFIG_ESP32_WIFI_NVS_ENABLED=y +CONFIG_ESP32_WIFI_SOFTAP_BEACON_MAX_LEN=752 +CONFIG_ESP32_WIFI_MGMT_SBUF_NUM=32 +CONFIG_ESP32_WIFI_IRAM_OPT=y +CONFIG_ESP32_WIFI_RX_IRAM_OPT=y +CONFIG_ESP32_WIFI_ENABLE_WPA3_SAE=y +# CONFIG_ESP_WIFI_SLP_IRAM_OPT is not set +# CONFIG_ESP_WIFI_FTM_ENABLE is not set +# CONFIG_ESP_WIFI_STA_DISCONNECTED_PM_ENABLE is not set +# CONFIG_ESP_WIFI_EXTERNAL_COEXIST_ENABLE is not set +# CONFIG_ESP_WIFI_GMAC_SUPPORT is not set +CONFIG_ESP_WIFI_SOFTAP_SUPPORT=y +# end of Wi-Fi + +# +# Core dump +# +# CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH is not set +# CONFIG_ESP_COREDUMP_ENABLE_TO_UART is not set +CONFIG_ESP_COREDUMP_ENABLE_TO_NONE=y +# end of Core dump + +# +# FAT Filesystem support +# +# CONFIG_FATFS_CODEPAGE_DYNAMIC is not set +CONFIG_FATFS_CODEPAGE_437=y +# CONFIG_FATFS_CODEPAGE_720 is not set +# CONFIG_FATFS_CODEPAGE_737 is not set +# CONFIG_FATFS_CODEPAGE_771 is not set +# CONFIG_FATFS_CODEPAGE_775 is not set +# CONFIG_FATFS_CODEPAGE_850 is not set +# CONFIG_FATFS_CODEPAGE_852 is not set +# CONFIG_FATFS_CODEPAGE_855 is not set +# CONFIG_FATFS_CODEPAGE_857 is not set +# CONFIG_FATFS_CODEPAGE_860 is not set +# CONFIG_FATFS_CODEPAGE_861 is not set +# CONFIG_FATFS_CODEPAGE_862 is not set +# CONFIG_FATFS_CODEPAGE_863 is not set +# CONFIG_FATFS_CODEPAGE_864 is not set +# CONFIG_FATFS_CODEPAGE_865 is not set +# CONFIG_FATFS_CODEPAGE_866 is not set +# CONFIG_FATFS_CODEPAGE_869 is not set +# CONFIG_FATFS_CODEPAGE_932 is not set +# CONFIG_FATFS_CODEPAGE_936 is not set +# CONFIG_FATFS_CODEPAGE_949 is not set +# CONFIG_FATFS_CODEPAGE_950 is not set +CONFIG_FATFS_CODEPAGE=437 +CONFIG_FATFS_LFN_NONE=y +# CONFIG_FATFS_LFN_HEAP is not set +# CONFIG_FATFS_LFN_STACK is not set +CONFIG_FATFS_FS_LOCK=0 +CONFIG_FATFS_TIMEOUT_MS=10000 +CONFIG_FATFS_PER_FILE_CACHE=y +# CONFIG_FATFS_USE_FASTSEEK is not set +# end of FAT Filesystem support + +# +# Modbus configuration +# +CONFIG_FMB_COMM_MODE_TCP_EN=y +CONFIG_FMB_TCP_PORT_DEFAULT=502 +CONFIG_FMB_TCP_PORT_MAX_CONN=5 +CONFIG_FMB_TCP_CONNECTION_TOUT_SEC=20 +CONFIG_FMB_COMM_MODE_RTU_EN=y +CONFIG_FMB_COMM_MODE_ASCII_EN=y +CONFIG_FMB_MASTER_TIMEOUT_MS_RESPOND=150 +CONFIG_FMB_MASTER_DELAY_MS_CONVERT=200 +CONFIG_FMB_QUEUE_LENGTH=20 +CONFIG_FMB_PORT_TASK_STACK_SIZE=4096 +CONFIG_FMB_SERIAL_BUF_SIZE=256 +CONFIG_FMB_SERIAL_ASCII_BITS_PER_SYMB=8 +CONFIG_FMB_SERIAL_ASCII_TIMEOUT_RESPOND_MS=1000 +CONFIG_FMB_PORT_TASK_PRIO=10 +CONFIG_FMB_PORT_TASK_AFFINITY=0x7FFFFFFF +CONFIG_FMB_CONTROLLER_SLAVE_ID_SUPPORT=y +CONFIG_FMB_CONTROLLER_SLAVE_ID=0x00112233 +CONFIG_FMB_CONTROLLER_NOTIFY_TIMEOUT=20 +CONFIG_FMB_CONTROLLER_NOTIFY_QUEUE_SIZE=20 +CONFIG_FMB_CONTROLLER_STACK_SIZE=4096 +CONFIG_FMB_EVENT_QUEUE_TIMEOUT=20 +# CONFIG_FMB_TIMER_PORT_ENABLED is not set +CONFIG_FMB_TIMER_GROUP=0 +CONFIG_FMB_TIMER_INDEX=0 +CONFIG_FMB_MASTER_TIMER_GROUP=0 +CONFIG_FMB_MASTER_TIMER_INDEX=0 +# CONFIG_FMB_TIMER_ISR_IN_IRAM is not set +# end of Modbus configuration + +# +# FreeRTOS +# +CONFIG_FREERTOS_UNICORE=y +CONFIG_FREERTOS_NO_AFFINITY=0x7FFFFFFF +CONFIG_FREERTOS_TICK_SUPPORT_CORETIMER=y +CONFIG_FREERTOS_CORETIMER_0=y +# CONFIG_FREERTOS_CORETIMER_1 is not set +CONFIG_FREERTOS_SYSTICK_USES_CCOUNT=y +CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y +CONFIG_FREERTOS_HZ=100 +CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION=y +# CONFIG_FREERTOS_CHECK_STACKOVERFLOW_NONE is not set +# CONFIG_FREERTOS_CHECK_STACKOVERFLOW_PTRVAL is not set +CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY=y +# CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK is not set +CONFIG_FREERTOS_INTERRUPT_BACKTRACE=y +CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=1 +CONFIG_FREERTOS_ASSERT_FAIL_ABORT=y +# CONFIG_FREERTOS_ASSERT_FAIL_PRINT_CONTINUE is not set +# CONFIG_FREERTOS_ASSERT_DISABLE is not set +CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=1536 +CONFIG_FREERTOS_ISR_STACKSIZE=1536 +# CONFIG_FREERTOS_LEGACY_HOOKS is not set +CONFIG_FREERTOS_MAX_TASK_NAME_LEN=16 +CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION=y +# CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP is not set +CONFIG_FREERTOS_TIMER_TASK_PRIORITY=1 +CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=2048 +CONFIG_FREERTOS_TIMER_QUEUE_LENGTH=10 +CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE=0 +CONFIG_FREERTOS_USE_TRACE_FACILITY=y +CONFIG_FREERTOS_USE_STATS_FORMATTING_FUNCTIONS=y +# CONFIG_FREERTOS_VTASKLIST_INCLUDE_COREID is not set +CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS=y +CONFIG_FREERTOS_RUN_TIME_STATS_USING_ESP_TIMER=y +# CONFIG_FREERTOS_RUN_TIME_STATS_USING_CPU_CLK is not set +CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER=y +CONFIG_FREERTOS_CHECK_MUTEX_GIVEN_BY_OWNER=y +# CONFIG_FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE is not set +# CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH is not set +CONFIG_FREERTOS_DEBUG_OCDAWARE=y +CONFIG_FREERTOS_ENABLE_TASK_SNAPSHOT=y +# CONFIG_FREERTOS_PLACE_SNAPSHOT_FUNS_INTO_FLASH is not set +# end of FreeRTOS + +# +# Hardware Abstraction Layer (HAL) and Low Level (LL) +# +CONFIG_HAL_ASSERTION_EQUALS_SYSTEM=y +# CONFIG_HAL_ASSERTION_DISABLE is not set +# CONFIG_HAL_ASSERTION_SILIENT is not set +# CONFIG_HAL_ASSERTION_ENABLE is not set +CONFIG_HAL_DEFAULT_ASSERTION_LEVEL=2 +# end of Hardware Abstraction Layer (HAL) and Low Level (LL) + +# +# Heap memory debugging +# +CONFIG_HEAP_POISONING_DISABLED=y +# CONFIG_HEAP_POISONING_LIGHT is not set +# CONFIG_HEAP_POISONING_COMPREHENSIVE is not set +CONFIG_HEAP_TRACING_OFF=y +# CONFIG_HEAP_TRACING_STANDALONE is not set +# CONFIG_HEAP_TRACING_TOHOST is not set +# CONFIG_HEAP_ABORT_WHEN_ALLOCATION_FAILS is not set +# end of Heap memory debugging + +# +# jsmn +# +# CONFIG_JSMN_PARENT_LINKS is not set +# CONFIG_JSMN_STRICT is not set +# end of jsmn + +# +# libsodium +# +# end of libsodium + +# +# Log output +# +# CONFIG_LOG_DEFAULT_LEVEL_NONE is not set +# CONFIG_LOG_DEFAULT_LEVEL_ERROR is not set +# CONFIG_LOG_DEFAULT_LEVEL_WARN is not set +CONFIG_LOG_DEFAULT_LEVEL_INFO=y +# CONFIG_LOG_DEFAULT_LEVEL_DEBUG is not set +# CONFIG_LOG_DEFAULT_LEVEL_VERBOSE is not set +CONFIG_LOG_DEFAULT_LEVEL=3 +CONFIG_LOG_MAXIMUM_EQUALS_DEFAULT=y +# CONFIG_LOG_MAXIMUM_LEVEL_DEBUG is not set +# CONFIG_LOG_MAXIMUM_LEVEL_VERBOSE is not set +CONFIG_LOG_MAXIMUM_LEVEL=3 +CONFIG_LOG_COLORS=y +CONFIG_LOG_TIMESTAMP_SOURCE_RTOS=y +# CONFIG_LOG_TIMESTAMP_SOURCE_SYSTEM is not set +# end of Log output + +# +# LWIP +# +CONFIG_LWIP_LOCAL_HOSTNAME="espressif" +# CONFIG_LWIP_NETIF_API is not set +# CONFIG_LWIP_TCPIP_CORE_LOCKING is not set +CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES=y +# CONFIG_LWIP_L2_TO_L3_COPY is not set +# CONFIG_LWIP_IRAM_OPTIMIZATION is not set +CONFIG_LWIP_TIMERS_ONDEMAND=y +CONFIG_LWIP_MAX_SOCKETS=10 +# CONFIG_LWIP_USE_ONLY_LWIP_SELECT is not set +# CONFIG_LWIP_SO_LINGER is not set +CONFIG_LWIP_SO_REUSE=y +CONFIG_LWIP_SO_REUSE_RXTOALL=y +# CONFIG_LWIP_SO_RCVBUF is not set +# CONFIG_LWIP_NETBUF_RECVINFO is not set +CONFIG_LWIP_IP4_FRAG=y +CONFIG_LWIP_IP6_FRAG=y +# CONFIG_LWIP_IP4_REASSEMBLY is not set +# CONFIG_LWIP_IP6_REASSEMBLY is not set +# CONFIG_LWIP_IP_FORWARD is not set +# CONFIG_LWIP_STATS is not set +# CONFIG_LWIP_ETHARP_TRUST_IP_MAC is not set +CONFIG_LWIP_ESP_GRATUITOUS_ARP=y +CONFIG_LWIP_GARP_TMR_INTERVAL=60 +CONFIG_LWIP_TCPIP_RECVMBOX_SIZE=32 +CONFIG_LWIP_DHCP_DOES_ARP_CHECK=y +# CONFIG_LWIP_DHCP_DISABLE_CLIENT_ID is not set +CONFIG_LWIP_DHCP_DISABLE_VENDOR_CLASS_ID=y +# CONFIG_LWIP_DHCP_RESTORE_LAST_IP is not set +CONFIG_LWIP_DHCP_OPTIONS_LEN=68 + +# +# DHCP server +# +CONFIG_LWIP_DHCPS=y +CONFIG_LWIP_DHCPS_LEASE_UNIT=60 +CONFIG_LWIP_DHCPS_MAX_STATION_NUM=8 +# end of DHCP server + +# CONFIG_LWIP_AUTOIP is not set +CONFIG_LWIP_IPV6=y +# CONFIG_LWIP_IPV6_AUTOCONFIG is not set +CONFIG_LWIP_IPV6_NUM_ADDRESSES=3 +# CONFIG_LWIP_IPV6_FORWARD is not set +# CONFIG_LWIP_NETIF_STATUS_CALLBACK is not set +CONFIG_LWIP_NETIF_LOOPBACK=y +CONFIG_LWIP_LOOPBACK_MAX_PBUFS=8 + +# +# TCP +# +CONFIG_LWIP_MAX_ACTIVE_TCP=16 +CONFIG_LWIP_MAX_LISTENING_TCP=16 +CONFIG_LWIP_TCP_HIGH_SPEED_RETRANSMISSION=y +CONFIG_LWIP_TCP_MAXRTX=12 +CONFIG_LWIP_TCP_SYNMAXRTX=12 +CONFIG_LWIP_TCP_MSS=1440 +CONFIG_LWIP_TCP_TMR_INTERVAL=250 +CONFIG_LWIP_TCP_MSL=60000 +CONFIG_LWIP_TCP_SND_BUF_DEFAULT=5744 +CONFIG_LWIP_TCP_WND_DEFAULT=5744 +CONFIG_LWIP_TCP_RECVMBOX_SIZE=6 +CONFIG_LWIP_TCP_QUEUE_OOSEQ=y +# CONFIG_LWIP_TCP_SACK_OUT is not set +# CONFIG_LWIP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES is not set +CONFIG_LWIP_TCP_OVERSIZE_MSS=y +# CONFIG_LWIP_TCP_OVERSIZE_QUARTER_MSS is not set +# CONFIG_LWIP_TCP_OVERSIZE_DISABLE is not set +CONFIG_LWIP_TCP_RTO_TIME=1500 +# end of TCP + +# +# UDP +# +CONFIG_LWIP_MAX_UDP_PCBS=16 +CONFIG_LWIP_UDP_RECVMBOX_SIZE=6 +# end of UDP + +# +# Checksums +# +# CONFIG_LWIP_CHECKSUM_CHECK_IP is not set +# CONFIG_LWIP_CHECKSUM_CHECK_UDP is not set +CONFIG_LWIP_CHECKSUM_CHECK_ICMP=y +# end of Checksums + +CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=3072 +CONFIG_LWIP_TCPIP_TASK_AFFINITY_NO_AFFINITY=y +# CONFIG_LWIP_TCPIP_TASK_AFFINITY_CPU0 is not set +CONFIG_LWIP_TCPIP_TASK_AFFINITY=0x7FFFFFFF +# CONFIG_LWIP_PPP_SUPPORT is not set +CONFIG_LWIP_IPV6_MEMP_NUM_ND6_QUEUE=3 +CONFIG_LWIP_IPV6_ND6_NUM_NEIGHBORS=5 +# CONFIG_LWIP_SLIP_SUPPORT is not set + +# +# ICMP +# +CONFIG_LWIP_ICMP=y +# CONFIG_LWIP_MULTICAST_PING is not set +# CONFIG_LWIP_BROADCAST_PING is not set +# end of ICMP + +# +# LWIP RAW API +# +CONFIG_LWIP_MAX_RAW_PCBS=16 +# end of LWIP RAW API + +# +# SNTP +# +CONFIG_LWIP_SNTP_MAX_SERVERS=1 +# CONFIG_LWIP_DHCP_GET_NTP_SRV is not set +CONFIG_LWIP_SNTP_UPDATE_DELAY=3600000 +# end of SNTP + +CONFIG_LWIP_ESP_LWIP_ASSERT=y + +# +# Hooks +# +# CONFIG_LWIP_HOOK_TCP_ISN_NONE is not set +CONFIG_LWIP_HOOK_TCP_ISN_DEFAULT=y +# CONFIG_LWIP_HOOK_TCP_ISN_CUSTOM is not set +CONFIG_LWIP_HOOK_IP6_ROUTE_NONE=y +# CONFIG_LWIP_HOOK_IP6_ROUTE_DEFAULT is not set +# CONFIG_LWIP_HOOK_IP6_ROUTE_CUSTOM is not set +CONFIG_LWIP_HOOK_ND6_GET_GW_NONE=y +# CONFIG_LWIP_HOOK_ND6_GET_GW_DEFAULT is not set +# CONFIG_LWIP_HOOK_ND6_GET_GW_CUSTOM is not set +CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_NONE=y +# CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_DEFAULT is not set +# CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_CUSTOM is not set +# end of Hooks + +# CONFIG_LWIP_DEBUG is not set +# end of LWIP + +# +# mbedTLS +# +CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y +# CONFIG_MBEDTLS_DEFAULT_MEM_ALLOC is not set +# CONFIG_MBEDTLS_CUSTOM_MEM_ALLOC is not set +CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN=y +CONFIG_MBEDTLS_SSL_IN_CONTENT_LEN=16384 +CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN=4096 +# CONFIG_MBEDTLS_DYNAMIC_BUFFER is not set +# CONFIG_MBEDTLS_DEBUG is not set + +# +# mbedTLS v2.28.x related +# +# CONFIG_MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH is not set +# CONFIG_MBEDTLS_X509_TRUSTED_CERT_CALLBACK is not set +# CONFIG_MBEDTLS_SSL_CONTEXT_SERIALIZATION is not set +CONFIG_MBEDTLS_SSL_KEEP_PEER_CERTIFICATE=y +# end of mbedTLS v2.28.x related + +# +# Certificate Bundle +# +CONFIG_MBEDTLS_CERTIFICATE_BUNDLE=y +CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL=y +# CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_CMN is not set +# CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_NONE is not set +# CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE is not set +CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_MAX_CERTS=200 +# end of Certificate Bundle + +# CONFIG_MBEDTLS_ECP_RESTARTABLE is not set +# CONFIG_MBEDTLS_CMAC_C is not set +CONFIG_MBEDTLS_HARDWARE_AES=y +CONFIG_MBEDTLS_AES_USE_INTERRUPT=y +CONFIG_MBEDTLS_HARDWARE_GCM=y +CONFIG_MBEDTLS_HARDWARE_MPI=y +CONFIG_MBEDTLS_HARDWARE_SHA=y +CONFIG_MBEDTLS_ROM_MD5=y +# CONFIG_MBEDTLS_ATCA_HW_ECDSA_SIGN is not set +# CONFIG_MBEDTLS_ATCA_HW_ECDSA_VERIFY is not set +CONFIG_MBEDTLS_HAVE_TIME=y +# CONFIG_MBEDTLS_HAVE_TIME_DATE is not set +CONFIG_MBEDTLS_ECDSA_DETERMINISTIC=y +CONFIG_MBEDTLS_SHA512_C=y +CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT=y +# CONFIG_MBEDTLS_TLS_SERVER_ONLY is not set +# CONFIG_MBEDTLS_TLS_CLIENT_ONLY is not set +# CONFIG_MBEDTLS_TLS_DISABLED is not set +CONFIG_MBEDTLS_TLS_SERVER=y +CONFIG_MBEDTLS_TLS_CLIENT=y +CONFIG_MBEDTLS_TLS_ENABLED=y + +# +# TLS Key Exchange Methods +# +# CONFIG_MBEDTLS_PSK_MODES is not set +CONFIG_MBEDTLS_KEY_EXCHANGE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_RSA=y +# end of TLS Key Exchange Methods + +CONFIG_MBEDTLS_SSL_RENEGOTIATION=y +# CONFIG_MBEDTLS_SSL_PROTO_SSL3 is not set +CONFIG_MBEDTLS_SSL_PROTO_TLS1=y +CONFIG_MBEDTLS_SSL_PROTO_TLS1_1=y +CONFIG_MBEDTLS_SSL_PROTO_TLS1_2=y +# CONFIG_MBEDTLS_SSL_PROTO_GMTSSL1_1 is not set +# CONFIG_MBEDTLS_SSL_PROTO_DTLS is not set +CONFIG_MBEDTLS_SSL_ALPN=y +CONFIG_MBEDTLS_CLIENT_SSL_SESSION_TICKETS=y +CONFIG_MBEDTLS_X509_CHECK_KEY_USAGE=y +CONFIG_MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE=y +CONFIG_MBEDTLS_SERVER_SSL_SESSION_TICKETS=y + +# +# Symmetric Ciphers +# +CONFIG_MBEDTLS_AES_C=y +# CONFIG_MBEDTLS_CAMELLIA_C is not set +# CONFIG_MBEDTLS_DES_C is not set +CONFIG_MBEDTLS_RC4_DISABLED=y +# CONFIG_MBEDTLS_RC4_ENABLED_NO_DEFAULT is not set +# CONFIG_MBEDTLS_RC4_ENABLED is not set +# CONFIG_MBEDTLS_BLOWFISH_C is not set +# CONFIG_MBEDTLS_XTEA_C is not set +CONFIG_MBEDTLS_CCM_C=y +CONFIG_MBEDTLS_GCM_C=y +# CONFIG_MBEDTLS_NIST_KW_C is not set +# end of Symmetric Ciphers + +# CONFIG_MBEDTLS_RIPEMD160_C is not set + +# +# Certificates +# +CONFIG_MBEDTLS_PEM_PARSE_C=y +CONFIG_MBEDTLS_PEM_WRITE_C=y +CONFIG_MBEDTLS_X509_CRL_PARSE_C=y +CONFIG_MBEDTLS_X509_CSR_PARSE_C=y +# end of Certificates + +CONFIG_MBEDTLS_ECP_C=y +CONFIG_MBEDTLS_ECDH_C=y +CONFIG_MBEDTLS_ECDSA_C=y +# CONFIG_MBEDTLS_ECJPAKE_C is not set +CONFIG_MBEDTLS_ECP_DP_SECP192R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP224R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP384R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP521R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP192K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP224K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP256K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP256R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP512R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_CURVE25519_ENABLED=y +CONFIG_MBEDTLS_ECP_NIST_OPTIM=y +# CONFIG_MBEDTLS_POLY1305_C is not set +# CONFIG_MBEDTLS_CHACHA20_C is not set +# CONFIG_MBEDTLS_HKDF_C is not set +# CONFIG_MBEDTLS_THREADING_C is not set +# CONFIG_MBEDTLS_LARGE_KEY_SOFTWARE_MPI is not set +# CONFIG_MBEDTLS_SECURITY_RISKS is not set +# end of mbedTLS + +# +# mDNS +# +CONFIG_MDNS_MAX_SERVICES=10 +CONFIG_MDNS_TASK_PRIORITY=1 +CONFIG_MDNS_TASK_STACK_SIZE=4096 +# CONFIG_MDNS_TASK_AFFINITY_NO_AFFINITY is not set +CONFIG_MDNS_TASK_AFFINITY_CPU0=y +CONFIG_MDNS_TASK_AFFINITY=0x0 +CONFIG_MDNS_SERVICE_ADD_TIMEOUT_MS=2000 +# CONFIG_MDNS_STRICT_MODE is not set +CONFIG_MDNS_TIMER_PERIOD_MS=100 +# CONFIG_MDNS_NETWORKING_SOCKET is not set +CONFIG_MDNS_MULTIPLE_INSTANCE=y +# end of mDNS + +# +# ESP-MQTT Configurations +# +CONFIG_MQTT_PROTOCOL_311=y +CONFIG_MQTT_TRANSPORT_SSL=y +CONFIG_MQTT_TRANSPORT_WEBSOCKET=y +CONFIG_MQTT_TRANSPORT_WEBSOCKET_SECURE=y +# CONFIG_MQTT_MSG_ID_INCREMENTAL is not set +# CONFIG_MQTT_SKIP_PUBLISH_IF_DISCONNECTED is not set +# CONFIG_MQTT_REPORT_DELETED_MESSAGES is not set +# CONFIG_MQTT_USE_CUSTOM_CONFIG is not set +# CONFIG_MQTT_TASK_CORE_SELECTION_ENABLED is not set +# CONFIG_MQTT_CUSTOM_OUTBOX is not set +# end of ESP-MQTT Configurations + +# +# Newlib +# +CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF=y +# CONFIG_NEWLIB_STDOUT_LINE_ENDING_LF is not set +# CONFIG_NEWLIB_STDOUT_LINE_ENDING_CR is not set +# CONFIG_NEWLIB_STDIN_LINE_ENDING_CRLF is not set +# CONFIG_NEWLIB_STDIN_LINE_ENDING_LF is not set +CONFIG_NEWLIB_STDIN_LINE_ENDING_CR=y +# CONFIG_NEWLIB_NANO_FORMAT is not set +# end of Newlib + +# +# NVS +# +# CONFIG_NVS_ASSERT_ERROR_CHECK is not set +# end of NVS + +# +# OpenSSL +# +# CONFIG_OPENSSL_DEBUG is not set +CONFIG_OPENSSL_ERROR_STACK=y +# CONFIG_OPENSSL_ASSERT_DO_NOTHING is not set +CONFIG_OPENSSL_ASSERT_EXIT=y +# end of OpenSSL + +# +# OpenThread +# +# CONFIG_OPENTHREAD_ENABLED is not set +# end of OpenThread + +# +# PThreads +# +CONFIG_PTHREAD_TASK_PRIO_DEFAULT=5 +CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072 +CONFIG_PTHREAD_STACK_MIN=768 +CONFIG_PTHREAD_TASK_CORE_DEFAULT=-1 +CONFIG_PTHREAD_TASK_NAME_DEFAULT="pthread" +# end of PThreads + +# +# SPI Flash driver +# +# CONFIG_SPI_FLASH_VERIFY_WRITE is not set +# CONFIG_SPI_FLASH_ENABLE_COUNTERS is not set +CONFIG_SPI_FLASH_ROM_DRIVER_PATCH=y +CONFIG_SPI_FLASH_DANGEROUS_WRITE_ABORTS=y +# CONFIG_SPI_FLASH_DANGEROUS_WRITE_FAILS is not set +# CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED is not set +# CONFIG_SPI_FLASH_USE_LEGACY_IMPL is not set +# CONFIG_SPI_FLASH_BYPASS_BLOCK_ERASE is not set +CONFIG_SPI_FLASH_YIELD_DURING_ERASE=y +CONFIG_SPI_FLASH_ERASE_YIELD_DURATION_MS=20 +CONFIG_SPI_FLASH_ERASE_YIELD_TICKS=1 +CONFIG_SPI_FLASH_WRITE_CHUNK_SIZE=8192 +# CONFIG_SPI_FLASH_SIZE_OVERRIDE is not set +# CONFIG_SPI_FLASH_CHECK_ERASE_TIMEOUT_DISABLED is not set +# CONFIG_SPI_FLASH_OVERRIDE_CHIP_DRIVER_LIST is not set + +# +# Auto-detect flash chips +# +CONFIG_SPI_FLASH_SUPPORT_ISSI_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_MXIC_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_GD_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_WINBOND_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_BOYA_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_TH_CHIP=y +# end of Auto-detect flash chips + +CONFIG_SPI_FLASH_ENABLE_ENCRYPTED_READ_WRITE=y +# end of SPI Flash driver + +# +# SPIFFS Configuration +# +CONFIG_SPIFFS_MAX_PARTITIONS=3 + +# +# SPIFFS Cache Configuration +# +CONFIG_SPIFFS_CACHE=y +CONFIG_SPIFFS_CACHE_WR=y +# CONFIG_SPIFFS_CACHE_STATS is not set +# end of SPIFFS Cache Configuration + +CONFIG_SPIFFS_PAGE_CHECK=y +CONFIG_SPIFFS_GC_MAX_RUNS=10 +# CONFIG_SPIFFS_GC_STATS is not set +CONFIG_SPIFFS_PAGE_SIZE=256 +CONFIG_SPIFFS_OBJ_NAME_LEN=32 +# CONFIG_SPIFFS_FOLLOW_SYMLINKS is not set +CONFIG_SPIFFS_USE_MAGIC=y +CONFIG_SPIFFS_USE_MAGIC_LENGTH=y +CONFIG_SPIFFS_META_LENGTH=4 +CONFIG_SPIFFS_USE_MTIME=y + +# +# Debug Configuration +# +# CONFIG_SPIFFS_DBG is not set +# CONFIG_SPIFFS_API_DBG is not set +# CONFIG_SPIFFS_GC_DBG is not set +# CONFIG_SPIFFS_CACHE_DBG is not set +# CONFIG_SPIFFS_CHECK_DBG is not set +# CONFIG_SPIFFS_TEST_VISUALISATION is not set +# end of Debug Configuration +# end of SPIFFS Configuration + +# +# TCP Transport +# + +# +# Websocket +# +CONFIG_WS_TRANSPORT=y +CONFIG_WS_BUFFER_SIZE=1024 +# end of Websocket +# end of TCP Transport + +# +# TinyUSB Stack +# +# CONFIG_TINYUSB is not set +# end of TinyUSB Stack + +# +# Unity unit testing library +# +CONFIG_UNITY_ENABLE_FLOAT=y +CONFIG_UNITY_ENABLE_DOUBLE=y +# CONFIG_UNITY_ENABLE_64BIT is not set +# CONFIG_UNITY_ENABLE_COLOR is not set +CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y +# CONFIG_UNITY_ENABLE_FIXTURE is not set +# CONFIG_UNITY_ENABLE_BACKTRACE_ON_FAIL is not set +# end of Unity unit testing library + +# +# USB-OTG +# +CONFIG_USB_OTG_SUPPORTED=y +CONFIG_USB_HOST_CONTROL_TRANSFER_MAX_SIZE=256 +CONFIG_USB_HOST_HW_BUFFER_BIAS_BALANCED=y +# CONFIG_USB_HOST_HW_BUFFER_BIAS_IN is not set +# CONFIG_USB_HOST_HW_BUFFER_BIAS_PERIODIC_OUT is not set +# end of USB-OTG + +# +# Virtual file system +# +CONFIG_VFS_SUPPORT_IO=y +CONFIG_VFS_SUPPORT_DIR=y +CONFIG_VFS_SUPPORT_SELECT=y +CONFIG_VFS_SUPPRESS_SELECT_DEBUG_OUTPUT=y +CONFIG_VFS_SUPPORT_TERMIOS=y + +# +# Host File System I/O (Semihosting) +# +CONFIG_VFS_SEMIHOSTFS_MAX_MOUNT_POINTS=1 +# end of Host File System I/O (Semihosting) +# end of Virtual file system + +# +# Wear Levelling +# +# CONFIG_WL_SECTOR_SIZE_512 is not set +CONFIG_WL_SECTOR_SIZE_4096=y +CONFIG_WL_SECTOR_SIZE=4096 +# end of Wear Levelling + +# +# Wi-Fi Provisioning Manager +# +CONFIG_WIFI_PROV_SCAN_MAX_ENTRIES=16 +CONFIG_WIFI_PROV_AUTOSTOP_TIMEOUT=30 +CONFIG_WIFI_PROV_BLE_FORCE_ENCRYPTION=y +# end of Wi-Fi Provisioning Manager + +# +# Supplicant +# +CONFIG_WPA_MBEDTLS_CRYPTO=y +# CONFIG_WPA_WAPI_PSK is not set +# CONFIG_WPA_SUITE_B_192 is not set +# CONFIG_WPA_DEBUG_PRINT is not set +# CONFIG_WPA_TESTING_OPTIONS is not set +# CONFIG_WPA_WPS_STRICT is not set +# CONFIG_WPA_11KV_SUPPORT is not set +# CONFIG_WPA_MBO_SUPPORT is not set +# CONFIG_WPA_DPP_SUPPORT is not set +# end of Supplicant +# end of Component config + +# +# Compatibility options +# +# CONFIG_LEGACY_INCLUDE_COMMON_HEADERS is not set +# end of Compatibility options + +# Deprecated options for backward compatibility +CONFIG_TOOLPREFIX="xtensa-esp32s2-elf-" +# CONFIG_LOG_BOOTLOADER_LEVEL_NONE is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_ERROR is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_WARN is not set +CONFIG_LOG_BOOTLOADER_LEVEL_INFO=y +# CONFIG_LOG_BOOTLOADER_LEVEL_DEBUG is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_VERBOSE is not set +CONFIG_LOG_BOOTLOADER_LEVEL=3 +# CONFIG_APP_ROLLBACK_ENABLE is not set +# CONFIG_FLASH_ENCRYPTION_ENABLED is not set +# CONFIG_FLASHMODE_QIO is not set +# CONFIG_FLASHMODE_QOUT is not set +CONFIG_FLASHMODE_DIO=y +# CONFIG_FLASHMODE_DOUT is not set +# CONFIG_MONITOR_BAUD_9600B is not set +# CONFIG_MONITOR_BAUD_57600B is not set +CONFIG_MONITOR_BAUD_115200B=y +# CONFIG_MONITOR_BAUD_230400B is not set +# CONFIG_MONITOR_BAUD_921600B is not set +# CONFIG_MONITOR_BAUD_2MB is not set +# CONFIG_MONITOR_BAUD_OTHER is not set +CONFIG_MONITOR_BAUD_OTHER_VAL=115200 +CONFIG_MONITOR_BAUD=115200 +CONFIG_COMPILER_OPTIMIZATION_LEVEL_DEBUG=y +# CONFIG_COMPILER_OPTIMIZATION_LEVEL_RELEASE is not set +CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED=y +# CONFIG_OPTIMIZATION_ASSERTIONS_SILENT is not set +# CONFIG_OPTIMIZATION_ASSERTIONS_DISABLED is not set +CONFIG_OPTIMIZATION_ASSERTION_LEVEL=2 +# CONFIG_CXX_EXCEPTIONS is not set +CONFIG_STACK_CHECK_NONE=y +# CONFIG_STACK_CHECK_NORM is not set +# CONFIG_STACK_CHECK_STRONG is not set +# CONFIG_STACK_CHECK_ALL is not set +# CONFIG_WARN_WRITE_STRINGS is not set +# CONFIG_DISABLE_GCC8_WARNINGS is not set +# CONFIG_ESP32_APPTRACE_DEST_TRAX is not set +CONFIG_ESP32_APPTRACE_DEST_NONE=y +CONFIG_ESP32_APPTRACE_LOCK_ENABLE=y +CONFIG_ADC2_DISABLE_DAC=y +# CONFIG_EVENT_LOOP_PROFILING is not set +CONFIG_POST_EVENTS_FROM_ISR=y +CONFIG_POST_EVENTS_FROM_IRAM_ISR=y +CONFIG_ESP_SYSTEM_PD_FLASH=y +# CONFIG_ESP32C3_LIGHTSLEEP_GPIO_RESET_WORKAROUND is not set +CONFIG_IPC_TASK_STACK_SIZE=1536 +CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE=y +# CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION is not set +CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER=20 +CONFIG_ESP32_PHY_MAX_TX_POWER=20 +# CONFIG_ESP32S2_PANIC_PRINT_HALT is not set +CONFIG_ESP32S2_PANIC_PRINT_REBOOT=y +# CONFIG_ESP32S2_PANIC_SILENT_REBOOT is not set +# CONFIG_ESP32S2_PANIC_GDBSTUB is not set +CONFIG_ESP32S2_ALLOW_RTC_FAST_MEM_AS_HEAP=y +CONFIG_ESP32H2_MEMPROT_FEATURE=y +CONFIG_ESP32H2_MEMPROT_FEATURE_LOCK=y +CONFIG_SYSTEM_EVENT_QUEUE_SIZE=32 +CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=2304 +CONFIG_MAIN_TASK_STACK_SIZE=3584 +CONFIG_CONSOLE_UART_DEFAULT=y +# CONFIG_CONSOLE_UART_CUSTOM is not set +# CONFIG_ESP_CONSOLE_UART_NONE is not set +CONFIG_CONSOLE_UART=y +CONFIG_CONSOLE_UART_NUM=0 +CONFIG_CONSOLE_UART_BAUDRATE=115200 +CONFIG_INT_WDT=y +CONFIG_INT_WDT_TIMEOUT_MS=300 +CONFIG_TASK_WDT=y +# CONFIG_TASK_WDT_PANIC is not set +CONFIG_TASK_WDT_TIMEOUT_S=5 +CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0=y +# CONFIG_ESP32_DEBUG_STUBS_ENABLE is not set +CONFIG_TIMER_TASK_STACK_SIZE=3584 +# CONFIG_EXTERNAL_COEX_ENABLE is not set +# CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH is not set +# CONFIG_ESP32_ENABLE_COREDUMP_TO_UART is not set +CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE=y +CONFIG_MB_MASTER_TIMEOUT_MS_RESPOND=150 +CONFIG_MB_MASTER_DELAY_MS_CONVERT=200 +CONFIG_MB_QUEUE_LENGTH=20 +CONFIG_MB_SERIAL_TASK_STACK_SIZE=4096 +CONFIG_MB_SERIAL_BUF_SIZE=256 +CONFIG_MB_SERIAL_TASK_PRIO=10 +CONFIG_MB_CONTROLLER_SLAVE_ID_SUPPORT=y +CONFIG_MB_CONTROLLER_SLAVE_ID=0x00112233 +CONFIG_MB_CONTROLLER_NOTIFY_TIMEOUT=20 +CONFIG_MB_CONTROLLER_NOTIFY_QUEUE_SIZE=20 +CONFIG_MB_CONTROLLER_STACK_SIZE=4096 +CONFIG_MB_EVENT_QUEUE_TIMEOUT=20 +# CONFIG_MB_TIMER_PORT_ENABLED is not set +CONFIG_MB_TIMER_GROUP=0 +CONFIG_MB_TIMER_INDEX=0 +# CONFIG_ENABLE_STATIC_TASK_CLEAN_UP_HOOK is not set +CONFIG_TIMER_TASK_PRIORITY=1 +CONFIG_TIMER_TASK_STACK_DEPTH=2048 +CONFIG_TIMER_QUEUE_LENGTH=10 +# CONFIG_L2_TO_L3_COPY is not set +# CONFIG_USE_ONLY_LWIP_SELECT is not set +CONFIG_ESP_GRATUITOUS_ARP=y +CONFIG_GARP_TMR_INTERVAL=60 +CONFIG_TCPIP_RECVMBOX_SIZE=32 +CONFIG_TCP_MAXRTX=12 +CONFIG_TCP_SYNMAXRTX=12 +CONFIG_TCP_MSS=1440 +CONFIG_TCP_MSL=60000 +CONFIG_TCP_SND_BUF_DEFAULT=5744 +CONFIG_TCP_WND_DEFAULT=5744 +CONFIG_TCP_RECVMBOX_SIZE=6 +CONFIG_TCP_QUEUE_OOSEQ=y +# CONFIG_ESP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES is not set +CONFIG_TCP_OVERSIZE_MSS=y +# CONFIG_TCP_OVERSIZE_QUARTER_MSS is not set +# CONFIG_TCP_OVERSIZE_DISABLE is not set +CONFIG_UDP_RECVMBOX_SIZE=6 +CONFIG_TCPIP_TASK_STACK_SIZE=3072 +CONFIG_TCPIP_TASK_AFFINITY_NO_AFFINITY=y +# CONFIG_TCPIP_TASK_AFFINITY_CPU0 is not set +CONFIG_TCPIP_TASK_AFFINITY=0x7FFFFFFF +# CONFIG_PPP_SUPPORT is not set +CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT=5 +CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072 +CONFIG_ESP32_PTHREAD_STACK_MIN=768 +CONFIG_ESP32_PTHREAD_TASK_CORE_DEFAULT=-1 +CONFIG_ESP32_PTHREAD_TASK_NAME_DEFAULT="pthread" +CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ABORTS=y +# CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_FAILS is not set +# CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ALLOWED is not set +# CONFIG_USB_ENABLED is not set +CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT=y +CONFIG_SUPPORT_TERMIOS=y +CONFIG_SEMIHOSTFS_MAX_MOUNT_POINTS=1 +# End of deprecated options