blaster working now

master
Ondřej Hruška 3 years ago
parent c8ec93722e
commit 05f372efaa
  1. 2
      CMakeLists.txt
  2. 1
      main/CMakeLists.txt
  3. 90
      main/blast.c
  4. 32
      main/heap_debug.h
  5. 107
      main/irblast.c
  6. 31
      main/irblast.h
  7. 42
      main/irblaster_main.c
  8. 76
      main/web/websrv.c

@ -3,4 +3,4 @@
cmake_minimum_required(VERSION 3.5)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(hello-world)
project(irblaster)

@ -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

@ -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 <stdio.h>
#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));
}
}

@ -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 <stdint.h>
#include <esp_heap_trace.h>
#include <esp_log.h>
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

@ -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 <stdio.h>
#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));
}

@ -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

@ -2,7 +2,6 @@
#include <console/console.h>
#include <console/console_ioimpl.h>
#include <esp_heap_trace.h>
#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());
}

@ -8,6 +8,7 @@
#include "websrv.h"
#include "esp_http_server.h"
#include "utils.h"
#include "irblast.h"
#include "www_files_enum.h"
@ -18,8 +19,7 @@ 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,8 +45,7 @@ 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) {
@ -73,8 +70,7 @@ err:
}
/* 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, "<!DOCTYPE html><html><head>"
"<meta http-equiv=\"refresh\" content=\"10; url=/\">"
"</head>"
@ -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);
@ -140,6 +180,11 @@ static const httpd_uri_t routes[] = {
.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,
@ -147,8 +192,7 @@ static const httpd_uri_t routes[] = {
},
};
esp_err_t websrv_init(void)
{
esp_err_t websrv_init(void) {
httpd_config_t config = HTTPD_DEFAULT_CONFIG();
config.max_open_sockets = 3;

Loading…
Cancel
Save