257 lines
6.7 KiB
C
257 lines
6.7 KiB
C
#include "board.h"
|
|
#include "app_process.h"
|
|
#include "app_machine.h"
|
|
#include "app_ui.h"
|
|
#include "hal_motor.h"
|
|
#include "hal_temp.h"
|
|
#include "hal_audio.h"
|
|
#include "hal_display.h"
|
|
#include "hal_input.h"
|
|
#include "ui_cmd.h"
|
|
|
|
#include <string.h>
|
|
#include <stdbool.h>
|
|
|
|
#include "esp_log.h"
|
|
#include "esp_timer.h"
|
|
#include "esp_task_wdt.h"
|
|
#include "freertos/FreeRTOS.h"
|
|
#include "freertos/task.h"
|
|
#include "freertos/queue.h"
|
|
|
|
#ifndef AUTOFILM_GIT_DESC
|
|
#define AUTOFILM_GIT_DESC "dev"
|
|
#endif
|
|
|
|
static const char *TAG = "app";
|
|
|
|
#if defined(AUTOFILM_BOARD_WROOM) || defined(AUTOFILM_BOARD_S3)
|
|
static QueueHandle_t s_cmdq;
|
|
|
|
static void map_and_post_key(char key)
|
|
{
|
|
ui_cmd_t cmd;
|
|
memset(&cmd, 0, sizeof(cmd));
|
|
machine_state_t st = app_machine_state();
|
|
|
|
if (key >= '1' && key <= '6') {
|
|
cmd.id = CMD_SELECT_PROCESS;
|
|
cmd.process_id = (uint8_t)(key - '1');
|
|
xQueueSend(s_cmdq, &cmd, 0);
|
|
return;
|
|
}
|
|
|
|
switch (key) {
|
|
case 'U':
|
|
cmd.id = CMD_BROWSE_STEP;
|
|
cmd.step_delta = -1;
|
|
break;
|
|
case 'D':
|
|
cmd.id = CMD_BROWSE_STEP;
|
|
cmd.step_delta = 1;
|
|
break;
|
|
case 'L':
|
|
cmd.id = CMD_ADJUST_STEP_TIME;
|
|
cmd.time_delta_s = -5;
|
|
break;
|
|
case 'R':
|
|
cmd.id = CMD_ADJUST_STEP_TIME;
|
|
cmd.time_delta_s = 5;
|
|
break;
|
|
case 'E':
|
|
if (st == ST_STEP_SELECT) {
|
|
cmd.id = CMD_ARM_STEP;
|
|
cmd.step_index = app_machine_step_index();
|
|
} else if (st == ST_ARMED) {
|
|
cmd.id = CMD_START_STEP;
|
|
} else if (st == ST_STOPPED) {
|
|
cmd.id = CMD_RESUME;
|
|
} else if (st == ST_COMPLETE) {
|
|
cmd.id = CMD_ARM_STEP;
|
|
cmd.step_index = app_machine_step_index();
|
|
} else {
|
|
return;
|
|
}
|
|
break;
|
|
case 'X':
|
|
if (st == ST_ARMED) {
|
|
cmd.id = CMD_CANCEL_ARMED;
|
|
} else if (st == ST_RUNNING) {
|
|
/* Dual-path stop: EN-off in this task, then CMD_STOP. */
|
|
hal_motor_request_stop();
|
|
cmd.id = CMD_STOP;
|
|
} else if (st == ST_COMPLETE) {
|
|
cmd.id = CMD_STOP;
|
|
} else if (st == ST_STOPPED) {
|
|
cmd.id = CMD_RETURN_TO_STEP_SELECT;
|
|
} else {
|
|
return; /* ignore IDLE */
|
|
}
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
xQueueSend(s_cmdq, &cmd, 0);
|
|
}
|
|
|
|
static void input_task(void *arg)
|
|
{
|
|
(void)arg;
|
|
esp_err_t werr = esp_task_wdt_add(NULL);
|
|
if (werr != ESP_OK) {
|
|
ESP_LOGW(TAG, "input wdt add failed: %s", esp_err_to_name(werr));
|
|
}
|
|
const TickType_t period = pdMS_TO_TICKS(40); /* 25 Hz */
|
|
for (;;) {
|
|
ui_raw_key_t raw;
|
|
while (hal_input_pop_key(&raw)) {
|
|
map_and_post_key(raw.key);
|
|
}
|
|
ui_raw_touch_t touch;
|
|
while (hal_input_pop_touch(&touch)) {
|
|
char key;
|
|
if (app_ui_touch_to_key(touch.x, touch.y, &key)) {
|
|
map_and_post_key(key);
|
|
}
|
|
}
|
|
esp_task_wdt_reset();
|
|
vTaskDelay(period);
|
|
}
|
|
}
|
|
|
|
static void machine_task(void *arg)
|
|
{
|
|
(void)arg;
|
|
esp_err_t werr = esp_task_wdt_add(NULL);
|
|
if (werr != ESP_OK) {
|
|
ESP_LOGW(TAG, "machine wdt add failed: %s", esp_err_to_name(werr));
|
|
}
|
|
const TickType_t period = pdMS_TO_TICKS(20); /* 50 Hz */
|
|
for (;;) {
|
|
ui_cmd_t cmd;
|
|
while (xQueueReceive(s_cmdq, &cmd, 0) == pdTRUE) {
|
|
app_machine_handle_cmd(&cmd);
|
|
}
|
|
uint32_t now_ms = (uint32_t)(esp_timer_get_time() / 1000ULL);
|
|
app_machine_tick(now_ms);
|
|
esp_task_wdt_reset();
|
|
vTaskDelay(period);
|
|
}
|
|
}
|
|
|
|
static void ui_task(void *arg)
|
|
{
|
|
(void)arg;
|
|
esp_err_t werr = esp_task_wdt_add(NULL);
|
|
if (werr != ESP_OK) {
|
|
ESP_LOGW(TAG, "ui wdt add failed: %s", esp_err_to_name(werr));
|
|
}
|
|
|
|
hal_display_clear();
|
|
hal_display_text(0, 0, "AUTOFILM");
|
|
hal_display_text(0, 1, AUTOFILM_GIT_DESC);
|
|
vTaskDelay(pdMS_TO_TICKS(1000));
|
|
|
|
app_ui_init();
|
|
app_ui_draw();
|
|
|
|
const TickType_t period = pdMS_TO_TICKS(25);
|
|
for (;;) {
|
|
ui_evt_t ev;
|
|
while (app_machine_last_event(&ev) == 1) {
|
|
app_ui_on_event(&ev);
|
|
}
|
|
/* Running remaining is read from the machine on each draw (>=4 Hz). */
|
|
if (app_ui_is_dirty() || app_machine_state() == ST_RUNNING) {
|
|
app_ui_draw();
|
|
}
|
|
esp_task_wdt_reset();
|
|
vTaskDelay(period);
|
|
}
|
|
}
|
|
|
|
static void temp_task(void *arg)
|
|
{
|
|
(void)arg;
|
|
esp_err_t werr = esp_task_wdt_add(NULL);
|
|
if (werr != ESP_OK) {
|
|
ESP_LOGW(TAG, "temp wdt add failed: %s", esp_err_to_name(werr));
|
|
}
|
|
for (;;) {
|
|
hal_temp_tick();
|
|
float c = 0.0f;
|
|
bool ok = (hal_temp_read_c(&c) == ESP_OK);
|
|
app_machine_on_temp(ok ? c : 0.0f, ok);
|
|
esp_task_wdt_reset();
|
|
vTaskDelay(pdMS_TO_TICKS(100));
|
|
}
|
|
}
|
|
#endif
|
|
|
|
void app_main(void)
|
|
{
|
|
ESP_LOGI(TAG, "board=%s desc=%s", board_name(), AUTOFILM_GIT_DESC);
|
|
|
|
gpio_num_t en_pin = board_pin_motor_en();
|
|
if (en_pin != GPIO_NUM_NC) {
|
|
gpio_config_t io = {
|
|
.pin_bit_mask = 1ULL << en_pin,
|
|
.mode = GPIO_MODE_OUTPUT,
|
|
.pull_up_en = GPIO_PULLUP_DISABLE,
|
|
.pull_down_en = GPIO_PULLDOWN_DISABLE,
|
|
.intr_type = GPIO_INTR_DISABLE,
|
|
};
|
|
gpio_config(&io);
|
|
gpio_set_level(en_pin, board_motor_en_disable_level());
|
|
}
|
|
|
|
app_process_init();
|
|
hal_motor_init();
|
|
hal_temp_init();
|
|
hal_audio_init();
|
|
app_machine_init();
|
|
|
|
#if defined(AUTOFILM_BOARD_WROOM) || defined(AUTOFILM_BOARD_S3)
|
|
hal_display_init();
|
|
hal_input_init();
|
|
app_ui_init();
|
|
|
|
s_cmdq = xQueueCreate(UI_CMD_QUEUE_LEN, sizeof(ui_cmd_t));
|
|
|
|
#if CONFIG_ESP_TASK_WDT_EN
|
|
esp_task_wdt_config_t wdt_cfg = {
|
|
.timeout_ms = CONFIG_ESP_TASK_WDT_TIMEOUT_S * 1000,
|
|
.idle_core_mask =
|
|
#if CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0
|
|
(1u << 0)
|
|
#else
|
|
0
|
|
#endif
|
|
#if CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1
|
|
| (1u << 1)
|
|
#endif
|
|
,
|
|
#if CONFIG_ESP_TASK_WDT_PANIC
|
|
.trigger_panic = true,
|
|
#else
|
|
.trigger_panic = false,
|
|
#endif
|
|
};
|
|
esp_err_t wdt_err = esp_task_wdt_init(&wdt_cfg);
|
|
if (wdt_err == ESP_ERR_INVALID_STATE) {
|
|
wdt_err = esp_task_wdt_reconfigure(&wdt_cfg); /* already auto-initialised */
|
|
}
|
|
if (wdt_err != ESP_OK) {
|
|
ESP_LOGW(TAG, "task wdt setup: %s", esp_err_to_name(wdt_err));
|
|
}
|
|
#endif
|
|
|
|
xTaskCreate(temp_task, "temp", 4096, NULL, 2, NULL);
|
|
xTaskCreate(input_task, "input", 3072, NULL, 8, NULL);
|
|
xTaskCreate(machine_task, "machine", 4096, NULL, 6, NULL);
|
|
xTaskCreate(ui_task, "ui", 4096, NULL, 4, NULL);
|
|
#endif
|
|
|
|
/* app_main returns; scheduler keeps product tasks. No legacy startingMenu. */
|
|
}
|