diff --git a/CMakeLists.txt b/CMakeLists.txt index 8a022b8..7bdfeea 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,4 +3,4 @@ cmake_minimum_required(VERSION 3.5) include($ENV{IDF_PATH}/tools/cmake/project.cmake) -project(hello-world) +project(irblaster) diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index 1d6c0f4..fcfeb61 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -5,6 +5,7 @@ idf_component_register(SRCS sntp_cli.c utils.c wifi_conn.c + irblast.c console/console_ioimpl.c console/console_server.c console/register_cmds.c diff --git a/main/blast.c b/main/blast.c deleted file mode 100644 index 341188f..0000000 --- a/main/blast.c +++ /dev/null @@ -1,90 +0,0 @@ -/* 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 "driver/ledc.h" - -void app_main(void) -{ - printf("Hello world!\n"); - - /* - * Prepare and set configuration of timers - * that will be used by LED Controller - */ - ledc_timer_config_t ledc_timer = { - .duty_resolution = LEDC_TIMER_8_BIT, // resolution of PWM duty - .freq_hz = 38500, // frequency of PWM signal - .speed_mode = LEDC_HIGH_SPEED_MODE, // timer mode - .timer_num = LEDC_TIMER_0, // timer index - .clk_cfg = LEDC_AUTO_CLK, // Auto select the source clock - }; - // Set configuration of timer0 for high speed channels - ledc_timer_config(&ledc_timer); - - ledc_channel_config_t chan = { - .channel = LEDC_CHANNEL_0, - .duty = 127, - .gpio_num = 17, - .speed_mode = LEDC_HIGH_SPEED_MODE, - .hpoint = 0, - .timer_sel = LEDC_TIMER_0 - }; - ledc_channel_config(&chan); - -#define PWM_ON() do { \ - ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0, 127); \ - ledc_update_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0); \ -} while(0) - -#define PWM_OFF() do { \ - ledc_stop(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0, 0); \ -} while(0) - - while (1) { - //const uint8_t bytes[4] = {0b10000000, 0b01111111, 0b00010000, 0b11101111}; // and one 1 at the end - const uint8_t bytes[4] = {0b10000000 , 0b01111111 , 0b00000000 , 0b11111111}; // and one 1 at the end - - // Preamble - PWM_ON(); - ets_delay_us(9000); - PWM_OFF(); - ets_delay_us(4500); - - for (int i = 0; i < 4; i++) { - uint8_t byte = bytes[i]; - for (int j = 0; j < 8; j++) { - bool bit = 0 != (byte & 0x80); - byte <<= 1; - if (bit==0) { - PWM_ON(); - ets_delay_us(588); - PWM_OFF(); - ets_delay_us(540); - } else { - PWM_ON(); - ets_delay_us(590); - PWM_OFF(); - ets_delay_us(1672); - } - } - } - - PWM_ON(); - ets_delay_us(600); - PWM_OFF(); - ets_delay_us(1700); - - vTaskDelay(pdMS_TO_TICKS(1000)); - } -} diff --git a/main/heap_debug.h b/main/heap_debug.h deleted file mode 100644 index 56a4de5..0000000 --- a/main/heap_debug.h +++ /dev/null @@ -1,32 +0,0 @@ -/** - * Utilities for heap usage debugging - * - * Created on 2020/10/23. - */ - -#ifndef CSPEMU_HEAP_DEBUG_H -#define CSPEMU_HEAP_DEBUG_H -#include -#include -#include - -extern uint32_t heapdebug_start; -extern const char *heapdebug_start_name; - -#define HEAP_MEASURE_START(msg) \ - heapdebug_start_name = msg; \ - ESP_LOGD(TAG, "/-- HEAP_BEGIN: %s", msg); \ - heapdebug_start = esp_get_free_heap_size(); - -#define HEAP_TRACE_START() ESP_LOGD(TAG, "--- Start heap tracing!"); \ - ESP_ERROR_CHECK( heap_trace_start(HEAP_TRACE_LEAKS) ); - -#define HEAP_MEASURE_END() \ - ESP_LOGD(TAG, "\\--- HEAP_END: %s, used %d", \ - heapdebug_start_name, (int32_t)heapdebug_start - (int32_t)esp_get_free_heap_size()); - -#define HEAP_TRACE_END() ESP_LOGD(TAG, "--- End heap tracing!"); \ - ESP_ERROR_CHECK( heap_trace_stop() ); \ - heap_trace_dump(); - -#endif //CSPEMU_HEAP_DEBUG_H diff --git a/main/irblast.c b/main/irblast.c new file mode 100644 index 0000000..a30565e --- /dev/null +++ b/main/irblast.c @@ -0,0 +1,107 @@ +/* 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 "driver/ledc.h" +#include "irblast.h" + +static portMUX_TYPE mux_irblast; + +#define CMDLEN 4 + +static const uint8_t COMMANDS[][CMDLEN] = { + [IRBLAST_ONOFF] = {0b10000000, 0b01111111, 0b00000000, 0b11111111}, + [IRBLAST_DAYNIGHT] = {0b10000000, 0b01111111, 0b10000000, 0b01111111}, + [IRBLAST_SPEED1] = {0b10000000, 0b01111111, 0b10101000, 0b01010111}, + [IRBLAST_SPEED2] = {0b10000000, 0b01111111, 0b01101000, 0b10010111}, + [IRBLAST_SPEED3] = {0b10000000, 0b01111111, 0b00101000, 0b11010111}, + [IRBLAST_MODE1] = {0b10000000, 0b01111111, 0b00011000, 0b11100111}, + [IRBLAST_MODE2] = {0b10000000, 0b01111111, 0b10011000, 0b01100111}, + [IRBLAST_MODE3] = {0b10000000, 0b01111111, 0b00001000, 0b11110111}, + [IRBLAST_MODE4] = {0b10000000, 0b01111111, 0b10001000, 0b01110111}, + [IRBLAST_HUM1] = {0b10000000, 0b01111111, 0b00010000, 0b11101111}, + [IRBLAST_HUM2] = {0b10000000, 0b01111111, 0b01010000, 0b10101111}, + [IRBLAST_HUM3] = {0b10000000, 0b01111111, 0b10010000, 0b01101111}, +}; + +void irblast_setup() { + vPortCPUInitializeMutex(&mux_irblast); + + ledc_timer_config_t ledc_timer = { + .duty_resolution = LEDC_TIMER_8_BIT, // resolution of PWM duty + .freq_hz = 38500, // frequency of PWM signal + .speed_mode = LEDC_HIGH_SPEED_MODE, // timer mode + .timer_num = LEDC_TIMER_0, // timer index + .clk_cfg = LEDC_AUTO_CLK, // Auto select the source clock + }; + // Set configuration of timer0 for high speed channels + ledc_timer_config(&ledc_timer); + + ledc_channel_config_t chan = { + .channel = LEDC_CHANNEL_0, + .duty = 127, + .gpio_num = CONFIG_PIN_IRLED, + .speed_mode = LEDC_HIGH_SPEED_MODE, + .hpoint = 0, + .timer_sel = LEDC_TIMER_0 + }; + ledc_channel_config(&chan); +} + +static inline void pwm_on() { + ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0, 127); + ledc_update_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0); +} + +static inline void pwm_off() { + ledc_stop(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0, 0); +} + +void irblast_send(enum irblast_cmd cmd) { + const uint8_t *bytes = COMMANDS[cmd]; + + portENTER_CRITICAL(&mux_irblast); + + // Preamble + pwm_on(); + ets_delay_us(9000); + pwm_off(); + ets_delay_us(4500); + + for (int i = 0; i < CMDLEN; i++) { + uint8_t byte = bytes[i]; + for (int j = 0; j < 8; j++) { + if ((byte & 0x80) == 0) { + pwm_on(); + ets_delay_us(588); + pwm_off(); + ets_delay_us(540); + } else { + pwm_on(); + ets_delay_us(590); + pwm_off(); + ets_delay_us(1672); + } + byte <<= 1; + } + } + + // one "1" at the end, for some reason + pwm_on(); + ets_delay_us(600); + pwm_off(); + + portEXIT_CRITICAL(&mux_irblast); + + vTaskDelay(pdMS_TO_TICKS(1000)); +} diff --git a/main/irblast.h b/main/irblast.h new file mode 100644 index 0000000..583acc4 --- /dev/null +++ b/main/irblast.h @@ -0,0 +1,31 @@ +/** + * IRBlaster main file + * + * Created on 2021/12/10. + */ + +#ifndef _BLAST_H +#define _BLAST_H + +#include "esp_err.h" + +enum irblast_cmd { + IRBLAST_ONOFF, + IRBLAST_DAYNIGHT, + IRBLAST_SPEED1, + IRBLAST_SPEED2, + IRBLAST_SPEED3, + IRBLAST_MODE1, + IRBLAST_MODE2, + IRBLAST_MODE3, + IRBLAST_MODE4, + IRBLAST_HUM1, + IRBLAST_HUM2, + IRBLAST_HUM3, +}; + +void irblast_setup(); + +void irblast_send(enum irblast_cmd cmd); + +#endif //_BLAST_H diff --git a/main/irblaster_main.c b/main/irblaster_main.c index 989c028..bc25ec5 100644 --- a/main/irblaster_main.c +++ b/main/irblaster_main.c @@ -2,7 +2,6 @@ #include #include -#include #include "esp_wifi.h" #include "esp_event.h" @@ -11,16 +10,7 @@ #include "nvs_flash.h" #include "driver/adc.h" -#include "esp_adc_cal.h" -#include "esp_smartconfig.h" - -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "freertos/event_groups.h" - #include "application.h" -#include "utils.h" -#include "dhcp_wd.h" #include "settings.h" #include "console/console_server.h" @@ -29,22 +19,11 @@ #include "wifi_conn.h" #include "console/register_cmds.h" - -#include "tasks.h" -#include "heap_debug.h" +#include "irblast.h" static const char *TAG = "main"; -//#define NUM_RECORDS 200 -//static heap_trace_record_t trace_record[NUM_RECORDS]; // This buffer must be in internal RAM - -uint32_t heapdebug_start; -const char *heapdebug_start_name; - void app_main(void) { -// ESP_ERROR_CHECK( heap_trace_init_standalone(trace_record, NUM_RECORDS) ); - - HEAP_MEASURE_START("NVS,settings,isr,i2c"); ESP_ERROR_CHECK(nvs_flash_init()); ESP_ERROR_CHECK(esp_register_shutdown_handler(cspemu_run_shutdown_handlers)); ESP_ERROR_CHECK(esp_event_loop_create_default()); @@ -54,26 +33,16 @@ void app_main(void) { // Start IDF service for pin change interrupts ESP_ERROR_CHECK(gpio_install_isr_service(0)); - HEAP_MEASURE_END(); - HEAP_MEASURE_START("Netif"); ESP_LOGD(TAG, "initing netif"); ESP_ERROR_CHECK(esp_netif_init()); - HEAP_MEASURE_END(); - if (g_Settings.wifi_enabled && (g_Settings.sta_enabled || g_Settings.ap_enabled)) { - HEAP_MEASURE_START("WIFI SETUP"); initialise_wifi(); - HEAP_MEASURE_END(); - HEAP_MEASURE_START("WEBSRV SETUP"); websrv_init(); - HEAP_MEASURE_END(); - g_State.wifi_inited = true; } else { // initialise the bare minimum so wifi config can be changed - ESP_LOGD(TAG, "initing wifi"); wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); ESP_ERROR_CHECK(esp_wifi_init(&cfg)); @@ -83,19 +52,14 @@ void app_main(void) { g_State.wifi_inited = true; } - HEAP_MEASURE_START("CONSOLE INIT"); + irblast_setup(); + console_init(NULL); register_console_commands(); - HEAP_MEASURE_END(); - HEAP_MEASURE_START("CONSOLE start"); console_setup_uart_stdio(); ESP_ERROR_CHECK(console_start_stdio(NULL, NULL)); - HEAP_MEASURE_END(); - HEAP_MEASURE_START("Telnet start"); telnetsrv_start(CONSOLE_TELNET_PORT); - HEAP_MEASURE_END(); - ESP_LOGI(TAG, "Startup finished, free heap = %u, cmds %"PRIu32, esp_get_free_heap_size(), console_count_commands()); } diff --git a/main/web/websrv.c b/main/web/websrv.c index 9d76f7d..d5cd730 100644 --- a/main/web/websrv.c +++ b/main/web/websrv.c @@ -8,18 +8,18 @@ #include "websrv.h" #include "esp_http_server.h" #include "utils.h" +#include "irblast.h" #include "www_files_enum.h" -static const char *TAG="websrv"; +static const char *TAG = "websrv"; static httpd_handle_t s_hServer = NULL; // Embedded files (must also be listed in CMakeLists.txt as COMPONENT_EMBED_TXTFILES) efile(index_file, "index_html"); -static struct tpl_kv_list build_index_replacements_kv(void) -{ +static struct tpl_kv_list build_index_replacements_kv(void) { //char name[TPL_KV_KEY_LEN]; struct tpl_kv_list kv = tpl_kv_init(); tpl_kv_add(&kv, "version", APP_VERSION); @@ -27,8 +27,7 @@ static struct tpl_kv_list build_index_replacements_kv(void) } /* Main page */ -static esp_err_t handler_index(httpd_req_t *req) -{ +static esp_err_t handler_index(httpd_req_t *req) { struct tpl_kv_list kv = build_index_replacements_kv(); esp_err_t suc = httpd_send_template_file(req, FILE_INDEX_HTML, tpl_kv_replacer, &kv, 0); @@ -37,8 +36,7 @@ static esp_err_t handler_index(httpd_req_t *req) } /* Update XHR for new index page data */ -static esp_err_t handler_update(httpd_req_t *req) -{ +static esp_err_t handler_update(httpd_req_t *req) { struct tpl_kv_list kv = build_index_replacements_kv(); esp_err_t suc = tpl_kv_send_as_ascii_map(req, &kv); @@ -47,15 +45,14 @@ static esp_err_t handler_update(httpd_req_t *req) } /* Set a param */ -static esp_err_t handler_set(httpd_req_t *req) -{ +static esp_err_t handler_set(httpd_req_t *req) { char buf[64]; int n = httpd_req_recv(req, buf, 63); if (n < 0) { ESP_LOGW(TAG, "rx er"); goto err; } - buf[n]=0; + buf[n] = 0; char keybuf[20]; char valbuf[20]; @@ -68,13 +65,12 @@ static esp_err_t handler_set(httpd_req_t *req) return httpd_resp_send(req, NULL, 0); -err: + err: return httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, NULL); } /* Request emulator reboot */ -static esp_err_t handler_reboot(httpd_req_t *req) -{ +static esp_err_t handler_reboot(httpd_req_t *req) { httpd_resp_send(req, "" "" "" @@ -86,9 +82,54 @@ static esp_err_t handler_reboot(httpd_req_t *req) esp_restart(); } +/* Request emulator reboot */ +static esp_err_t handler_irblast(httpd_req_t *req) { + char buf[64]; + esp_err_t err = httpd_req_get_url_query_str(req, buf, 63); + if (err != ESP_OK) { + ESP_LOGW(TAG, "param er: %s", esp_err_to_name(err)); + goto err; + } + ESP_LOGI(TAG, "querystring: %s", buf); + + char valbuf[20]; + if (ESP_OK != httpd_query_key_value(buf, "do", valbuf, 20)) { + ESP_LOGW(TAG, "fail to get \"do\" param"); + goto err; + } + valbuf[19] = 0; + + ESP_LOGI(TAG, "IR cmd to send: %s", valbuf); + + const char *cmdnames[] = { + [IRBLAST_ONOFF] = "onoff", + [IRBLAST_DAYNIGHT] = "daynight", + [IRBLAST_SPEED1] = "speed1", + [IRBLAST_SPEED2] = "speed2", + [IRBLAST_SPEED3] = "speed3", + [IRBLAST_MODE1] = "mode1", + [IRBLAST_MODE2] = "mode2", + [IRBLAST_MODE3] = "mode3", + [IRBLAST_MODE4] = "mode4", + [IRBLAST_HUM1] = "hum1", + [IRBLAST_HUM2] = "hum2", + [IRBLAST_HUM3] = "hum3", + NULL + }; + + for (int i = 0; cmdnames[i]; i++) { + if (strncasecmp(cmdnames[i], valbuf, 20) == 0) { + httpd_resp_send(req, "{\"success\":true}", -1); + irblast_send((enum irblast_cmd) i); + return ESP_OK; + } + } + err: + return httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, NULL); +} + /* An HTTP GET handler */ -static esp_err_t handler_staticfiles(httpd_req_t *r) -{ +static esp_err_t handler_staticfiles(httpd_req_t *r) { const struct embedded_file_info *file; const char *fname = r->user_ctx; enum file_access_level access = FILE_ACCESS_PROTECTED; @@ -108,8 +149,7 @@ static esp_err_t handler_staticfiles(httpd_req_t *r) if (ESP_OK != www_get_static_file(fname, access, &file)) { ESP_LOGW(TAG, "File not found: %s", fname); return httpd_resp_send_404(r); - } - else { + } else { if (streq(file->mime, "text/html")) { // using the template func to allow includes return httpd_send_template_file_struct(r, file, /*replacer*/NULL, /*ctx*/NULL, /*opts*/0); @@ -120,35 +160,39 @@ static esp_err_t handler_staticfiles(httpd_req_t *r) } static const httpd_uri_t routes[] = { - { - .uri = "/", - .method = HTTP_GET, - .handler = handler_index, - }, - { - .uri = "/data", - .method = HTTP_GET, - .handler = handler_update, - }, - { - .uri = "/set", - .method = HTTP_POST, - .handler = handler_set, - }, - { - .uri = "/reboot", - .method = HTTP_GET, - .handler = handler_reboot, - }, - { - .uri = "*", // any file except protected (e.g. not HTML, PEM etc) - .method = HTTP_GET, - .handler = handler_staticfiles, - }, + { + .uri = "/", + .method = HTTP_GET, + .handler = handler_index, + }, + { + .uri = "/data", + .method = HTTP_GET, + .handler = handler_update, + }, + { + .uri = "/set", + .method = HTTP_POST, + .handler = handler_set, + }, + { + .uri = "/reboot", + .method = HTTP_GET, + .handler = handler_reboot, + }, + { + .uri = "/irblast", + .method = HTTP_GET, + .handler = handler_irblast, + }, + { + .uri = "*", // any file except protected (e.g. not HTML, PEM etc) + .method = HTTP_GET, + .handler = handler_staticfiles, + }, }; -esp_err_t websrv_init(void) -{ +esp_err_t websrv_init(void) { httpd_config_t config = HTTPD_DEFAULT_CONFIG(); config.max_open_sockets = 3;