Compare commits
17
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d70df219f8 | ||
|
|
7e854e10f0 | ||
|
|
b6c385e09c | ||
|
|
a9f76ea058 | ||
|
|
c40c714028 | ||
|
|
f87ab0c65f | ||
|
|
b4230b2a0e | ||
|
|
04e1ed0f16 | ||
|
|
a33b4b0c74 | ||
|
|
73f3158b27 | ||
|
|
a3fe809359 | ||
|
|
637ea8cb6e | ||
|
|
84b60155dd | ||
|
|
7406114368 | ||
|
|
0b0a713098 | ||
|
|
9ea89ac467 | ||
|
|
5f1727da7d |
+22
-16
@@ -16,19 +16,15 @@ jobs:
|
||||
- name: Install host toolchain
|
||||
if: hashFiles('tests/host/CMakeLists.txt') != ''
|
||||
run: |
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
if command -v sudo >/dev/null 2>&1 && [ "$(id -u)" -ne 0 ]; then
|
||||
SUDO=sudo
|
||||
else
|
||||
SUDO=
|
||||
fi
|
||||
$SUDO apt-get update
|
||||
$SUDO apt-get install -y --no-install-recommends cmake gcc g++ make
|
||||
export DEBIAN_FRONTEND=noninteractive && \
|
||||
if command -v sudo >/dev/null 2>&1 && [ "$(id -u)" -ne 0 ]; then SUDO=sudo; else SUDO=; fi && \
|
||||
$SUDO apt-get update && \
|
||||
$SUDO apt-get install -y -q --no-install-recommends cmake gcc g++ make
|
||||
- name: Host unit tests
|
||||
if: hashFiles('tests/host/CMakeLists.txt') != ''
|
||||
run: |
|
||||
cmake -S tests/host -B build/host
|
||||
cmake --build build/host
|
||||
cmake -S tests/host -B build/host && \
|
||||
cmake --build build/host && \
|
||||
ctest --test-dir build/host --output-on-failure
|
||||
|
||||
firmware:
|
||||
@@ -47,21 +43,30 @@ jobs:
|
||||
target: esp32s3
|
||||
sdkconfig: sdkconfig.s3
|
||||
steps:
|
||||
- name: Install Node.js
|
||||
run: |
|
||||
export DEBIAN_FRONTEND=noninteractive && \
|
||||
export NEEDRESTART_MODE=a && \
|
||||
if command -v sudo >/dev/null 2>&1 && [ "$(id -u)" -ne 0 ]; then SUDO=sudo; else SUDO=; fi && \
|
||||
$SUDO apt-get update && \
|
||||
$SUDO apt-get install -y -q --no-install-recommends nodejs
|
||||
- uses: actions/checkout@v4
|
||||
- name: Build
|
||||
if: hashFiles('CMakeLists.txt') != ''
|
||||
run: |
|
||||
git config --global --add safe.directory '*'
|
||||
idf.py -B build/${{ matrix.board }} set-target ${{ matrix.target }}
|
||||
. $IDF_PATH/export.sh && \
|
||||
git config --global --add safe.directory '*' && \
|
||||
idf.py -B build/${{ matrix.board }} set-target ${{ matrix.target }} && \
|
||||
idf.py -B build/${{ matrix.board }} \
|
||||
-D SDKCONFIG_DEFAULTS="sdkconfig.defaults;${{ matrix.sdkconfig }}" \
|
||||
-D AUTOFILM_BOARD=${{ matrix.board }} \
|
||||
build
|
||||
idf.py -B build/${{ matrix.board }} size | tee size-${{ matrix.board }}.txt
|
||||
build && \
|
||||
idf.py -B build/${{ matrix.board }} size | tee size-${{ matrix.board }}.txt && \
|
||||
cd build/${{ matrix.board }} && \
|
||||
python $IDF_PATH/components/esptool_py/esptool/esptool.py \
|
||||
--chip ${{ matrix.target }} merge_bin \
|
||||
-o autofilm-${{ matrix.board }}-${{ gitea.sha }}.bin \
|
||||
@build/${{ matrix.board }}/flash_args
|
||||
-o ../../autofilm-${{ matrix.board }}-${{ gitea.sha }}.bin \
|
||||
@flash_args
|
||||
- uses: actions/upload-artifact@v3
|
||||
if: hashFiles('CMakeLists.txt') != ''
|
||||
with:
|
||||
@@ -74,3 +79,4 @@ jobs:
|
||||
build/${{ matrix.board }}/flasher_args.json
|
||||
build/${{ matrix.board }}/sdkconfig
|
||||
size-${{ matrix.board }}.txt
|
||||
|
||||
@@ -56,7 +56,7 @@ static void draw_program_select(void)
|
||||
|
||||
static void draw_step_select(const ui_evt_t *ev)
|
||||
{
|
||||
char line[21];
|
||||
char line[32];
|
||||
char mm[8];
|
||||
uint16_t ts = ev->time_s;
|
||||
fmt_mmss(mm, sizeof(mm), ts);
|
||||
@@ -71,7 +71,7 @@ static void draw_step_select(const ui_evt_t *ev)
|
||||
|
||||
static void draw_armed(const ui_evt_t *ev)
|
||||
{
|
||||
char line[21];
|
||||
char line[32];
|
||||
char mm[8];
|
||||
fmt_mmss(mm, sizeof(mm), ev->time_s);
|
||||
int pref = (int)(ev->temp_pref_c + (ev->temp_pref_c >= 0 ? 0.5f : -0.5f));
|
||||
@@ -84,7 +84,7 @@ static void draw_armed(const ui_evt_t *ev)
|
||||
|
||||
static void draw_running(const ui_evt_t *ev)
|
||||
{
|
||||
char line[21];
|
||||
char line[32];
|
||||
char mm[8];
|
||||
uint32_t rem_s = (ev->remaining_ms + 999u) / 1000u;
|
||||
fmt_mmss(mm, sizeof(mm), rem_s);
|
||||
@@ -98,7 +98,7 @@ static void draw_running(const ui_evt_t *ev)
|
||||
|
||||
static void draw_stopped(const ui_evt_t *ev)
|
||||
{
|
||||
char line[21];
|
||||
char line[32];
|
||||
char mm[8];
|
||||
uint32_t rem_s = (ev->remaining_ms + 999u) / 1000u;
|
||||
fmt_mmss(mm, sizeof(mm), rem_s);
|
||||
@@ -111,7 +111,7 @@ static void draw_stopped(const ui_evt_t *ev)
|
||||
|
||||
static void draw_complete(const ui_evt_t *ev)
|
||||
{
|
||||
char line[21];
|
||||
char line[32];
|
||||
hal_display_clear();
|
||||
snprintf(line, sizeof(line), "%-10.10s Done", step_name(ev->process_id, ev->step_index));
|
||||
hal_display_text(0, 0, line);
|
||||
|
||||
@@ -19,10 +19,17 @@
|
||||
* RST 38
|
||||
* addr 0x5D
|
||||
*
|
||||
* Motor:
|
||||
* EN GPIO_NUM_NC — no spare header pin documented for EN.
|
||||
* STEP/DIR not assigned. Do not steal QSPI or GT911 pins.
|
||||
* Agitation may remain on WROOM until a spare is proven.
|
||||
* Motor (P3 header IO6/7/15/16):
|
||||
* EN 7 active LOW (disable level 1)
|
||||
* STEP 16
|
||||
* DIR 15
|
||||
*
|
||||
* DS18B20 temp: 17 (P4 header GND/3V3/17/18, UART1 unused)
|
||||
*
|
||||
* Speaker I2S (onboard amp, P7 Speak connector):
|
||||
* BCLK 42
|
||||
* LRCLK 2
|
||||
* DIN 41
|
||||
*/
|
||||
|
||||
const char *board_name(void)
|
||||
@@ -32,7 +39,7 @@ const char *board_name(void)
|
||||
|
||||
gpio_num_t board_pin_motor_en(void)
|
||||
{
|
||||
return GPIO_NUM_NC;
|
||||
return (gpio_num_t)7;
|
||||
}
|
||||
|
||||
int board_motor_en_disable_level(void)
|
||||
@@ -40,6 +47,14 @@ int board_motor_en_disable_level(void)
|
||||
return 1;
|
||||
}
|
||||
|
||||
gpio_num_t board_pin_motor_step(void) { return (gpio_num_t)16; }
|
||||
gpio_num_t board_pin_motor_dir(void) { return (gpio_num_t)15; }
|
||||
gpio_num_t board_pin_temp(void) { return (gpio_num_t)17; }
|
||||
|
||||
gpio_num_t board_pin_spk_bclk(void) { return (gpio_num_t)42; }
|
||||
gpio_num_t board_pin_spk_lrclk(void) { return (gpio_num_t)2; }
|
||||
gpio_num_t board_pin_spk_din(void) { return (gpio_num_t)41; }
|
||||
|
||||
gpio_num_t board_pin_lcd_cs(void) { return (gpio_num_t)45; }
|
||||
gpio_num_t board_pin_lcd_sck(void) { return (gpio_num_t)47; }
|
||||
gpio_num_t board_pin_lcd_d0(void) { return (gpio_num_t)21; }
|
||||
|
||||
@@ -4,6 +4,12 @@
|
||||
const char *board_name(void);
|
||||
gpio_num_t board_pin_motor_en(void);
|
||||
int board_motor_en_disable_level(void);
|
||||
gpio_num_t board_pin_motor_step(void);
|
||||
gpio_num_t board_pin_motor_dir(void);
|
||||
gpio_num_t board_pin_temp(void);
|
||||
gpio_num_t board_pin_spk_bclk(void);
|
||||
gpio_num_t board_pin_spk_lrclk(void);
|
||||
gpio_num_t board_pin_spk_din(void);
|
||||
|
||||
gpio_num_t board_pin_lcd_cs(void);
|
||||
gpio_num_t board_pin_lcd_sck(void);
|
||||
|
||||
@@ -14,3 +14,7 @@ int board_motor_en_disable_level(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
gpio_num_t board_pin_motor_step(void) { return (gpio_num_t)12; }
|
||||
gpio_num_t board_pin_motor_dir(void) { return (gpio_num_t)14; }
|
||||
gpio_num_t board_pin_temp(void) { return (gpio_num_t)13; }
|
||||
|
||||
@@ -3,3 +3,6 @@
|
||||
const char *board_name(void);
|
||||
gpio_num_t board_pin_motor_en(void);
|
||||
int board_motor_en_disable_level(void);
|
||||
gpio_num_t board_pin_motor_step(void);
|
||||
gpio_num_t board_pin_motor_dir(void);
|
||||
gpio_num_t board_pin_temp(void);
|
||||
|
||||
@@ -4,6 +4,9 @@ set(priv_req driver)
|
||||
if(IDF_TARGET STREQUAL "esp32")
|
||||
list(APPEND srcs wroom/hal_audio.c)
|
||||
list(APPEND priv_req board_wroom)
|
||||
elseif(IDF_TARGET STREQUAL "esp32s3")
|
||||
list(APPEND srcs s3/hal_audio.c)
|
||||
list(APPEND priv_req board_jc4827w543)
|
||||
else()
|
||||
list(APPEND srcs stub/hal_audio.c)
|
||||
endif()
|
||||
|
||||
@@ -0,0 +1,212 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
#include "driver/i2s_std.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/queue.h"
|
||||
|
||||
#include "board.h"
|
||||
|
||||
#define SPK_SAMPLE_RATE 48000
|
||||
#define TONE_HZ 2000
|
||||
#define TONE_PERIOD_SMP (SPK_SAMPLE_RATE / TONE_HZ) /* 24 samples */
|
||||
#define CHUNK_MS 10
|
||||
#define CHUNK_FRAMES (SPK_SAMPLE_RATE / 1000 * CHUNK_MS) /* 480, multiple of period */
|
||||
#define TONE_AMPLITUDE 12000
|
||||
#define DMA_DESC_NUM 4
|
||||
#define DMA_FRAME_NUM 240
|
||||
|
||||
static const char *TAG = "audio";
|
||||
|
||||
enum {
|
||||
AUDIO_SHORT = 1,
|
||||
AUDIO_ALARM,
|
||||
AUDIO_CANCEL,
|
||||
};
|
||||
|
||||
static QueueHandle_t s_q;
|
||||
static TaskHandle_t s_task;
|
||||
static i2s_chan_handle_t s_tx;
|
||||
static bool s_chan_on;
|
||||
static bool s_inited;
|
||||
|
||||
static int16_t s_tone[CHUNK_FRAMES * 2];
|
||||
static int16_t s_silence[CHUNK_FRAMES * 2];
|
||||
|
||||
static void chan_on(void)
|
||||
{
|
||||
if (!s_chan_on && s_tx != NULL) {
|
||||
i2s_channel_enable(s_tx);
|
||||
s_chan_on = true;
|
||||
}
|
||||
}
|
||||
|
||||
static void chan_off(void)
|
||||
{
|
||||
if (s_chan_on && s_tx != NULL) {
|
||||
size_t w = 0;
|
||||
i2s_channel_write(s_tx, s_silence, sizeof(s_silence), &w, 50);
|
||||
i2s_channel_disable(s_tx);
|
||||
s_chan_on = false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool drain_cancel(void)
|
||||
{
|
||||
int msg;
|
||||
while (xQueueReceive(s_q, &msg, 0) == pdTRUE) {
|
||||
if (msg == AUDIO_CANCEL) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Write buf for ~ms wall time. DMA pacing makes each 10 ms write block
|
||||
* in this task only; the UI path never touches I2S. */
|
||||
static bool play_buf_ms(const int16_t *buf, size_t len, uint32_t ms)
|
||||
{
|
||||
TickType_t t0 = xTaskGetTickCount();
|
||||
while ((xTaskGetTickCount() - t0) < pdMS_TO_TICKS(ms)) {
|
||||
if (drain_cancel()) {
|
||||
return false;
|
||||
}
|
||||
size_t w = 0;
|
||||
if (i2s_channel_write(s_tx, buf, len, &w, portMAX_DELAY) != ESP_OK) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void play_short(void)
|
||||
{
|
||||
chan_on();
|
||||
play_buf_ms(s_tone, sizeof(s_tone), 100);
|
||||
chan_off();
|
||||
}
|
||||
|
||||
static void play_alarm(void)
|
||||
{
|
||||
chan_on();
|
||||
for (int i = 0; i < 10; i++) {
|
||||
if (!play_buf_ms(s_tone, sizeof(s_tone), 500)) {
|
||||
break;
|
||||
}
|
||||
if (!play_buf_ms(s_silence, sizeof(s_silence), 250)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
chan_off();
|
||||
}
|
||||
|
||||
static void audio_task(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
int msg;
|
||||
for (;;) {
|
||||
if (xQueueReceive(s_q, &msg, portMAX_DELAY) != pdTRUE) {
|
||||
continue;
|
||||
}
|
||||
if (msg == AUDIO_SHORT) {
|
||||
play_short();
|
||||
} else if (msg == AUDIO_ALARM) {
|
||||
play_alarm();
|
||||
} else if (msg == AUDIO_CANCEL) {
|
||||
chan_off();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void post(int msg)
|
||||
{
|
||||
if (s_q == NULL) {
|
||||
return;
|
||||
}
|
||||
xQueueSend(s_q, &msg, 0);
|
||||
}
|
||||
|
||||
void autofilm_audio_task(void *arg)
|
||||
{
|
||||
audio_task(arg);
|
||||
}
|
||||
|
||||
void hal_audio_init(void)
|
||||
{
|
||||
if (s_inited) {
|
||||
return;
|
||||
}
|
||||
gpio_num_t bclk = board_pin_spk_bclk();
|
||||
gpio_num_t lrclk = board_pin_spk_lrclk();
|
||||
gpio_num_t din = board_pin_spk_din();
|
||||
if (bclk == GPIO_NUM_NC || lrclk == GPIO_NUM_NC || din == GPIO_NUM_NC) {
|
||||
ESP_LOGW(TAG, "no speaker pins on this board");
|
||||
s_inited = true;
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < CHUNK_FRAMES; i++) {
|
||||
int16_t v = ((i % TONE_PERIOD_SMP) < (TONE_PERIOD_SMP / 2))
|
||||
? TONE_AMPLITUDE : -TONE_AMPLITUDE;
|
||||
s_tone[i * 2] = v;
|
||||
s_tone[i * 2 + 1] = v;
|
||||
}
|
||||
|
||||
i2s_chan_config_t chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_AUTO, I2S_ROLE_MASTER);
|
||||
chan_cfg.dma_desc_num = DMA_DESC_NUM;
|
||||
chan_cfg.dma_frame_num = DMA_FRAME_NUM;
|
||||
if (i2s_new_channel(&chan_cfg, &s_tx, NULL) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "i2s_new_channel failed");
|
||||
s_inited = true;
|
||||
return;
|
||||
}
|
||||
i2s_std_config_t std_cfg = {
|
||||
.clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(SPK_SAMPLE_RATE),
|
||||
.slot_cfg = I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT,
|
||||
I2S_SLOT_MODE_STEREO),
|
||||
.gpio_cfg = {
|
||||
.mclk = I2S_GPIO_UNUSED,
|
||||
.bclk = bclk,
|
||||
.ws = lrclk,
|
||||
.dout = din,
|
||||
.din = I2S_GPIO_UNUSED,
|
||||
.invert_flags = {
|
||||
.mclk_inv = false,
|
||||
.bclk_inv = false,
|
||||
.ws_inv = false,
|
||||
},
|
||||
},
|
||||
};
|
||||
if (i2s_channel_init_std_mode(s_tx, &std_cfg) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "i2s_channel_init_std_mode failed");
|
||||
i2s_del_channel(s_tx);
|
||||
s_tx = NULL;
|
||||
s_inited = true;
|
||||
return;
|
||||
}
|
||||
s_q = xQueueCreate(8, sizeof(int));
|
||||
if (s_task == NULL) {
|
||||
xTaskCreate(audio_task, "audio", 3072, NULL, 2, &s_task);
|
||||
}
|
||||
s_inited = true;
|
||||
ESP_LOGI(TAG, "init i2s bclk=%d ws=%d dout=%d", bclk, lrclk, din);
|
||||
}
|
||||
|
||||
void hal_audio_beep_short(void)
|
||||
{
|
||||
post(AUDIO_SHORT);
|
||||
}
|
||||
|
||||
void hal_audio_alarm_complete(void)
|
||||
{
|
||||
post(AUDIO_ALARM);
|
||||
}
|
||||
|
||||
void hal_audio_alarm_cancel(void)
|
||||
{
|
||||
post(AUDIO_CANCEL);
|
||||
}
|
||||
@@ -3,8 +3,11 @@ set(priv_inc)
|
||||
set(priv_req driver)
|
||||
|
||||
if(IDF_TARGET STREQUAL "esp32")
|
||||
list(APPEND srcs wroom/hal_motor.c)
|
||||
list(APPEND srcs hal_motor.c)
|
||||
list(APPEND priv_req board_wroom)
|
||||
elseif(IDF_TARGET STREQUAL "esp32s3")
|
||||
list(APPEND srcs hal_motor.c)
|
||||
list(APPEND priv_req board_jc4827w543)
|
||||
else()
|
||||
list(APPEND srcs stub/hal_motor.c)
|
||||
endif()
|
||||
|
||||
@@ -10,9 +10,9 @@
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
#define PIN_STEP 12
|
||||
#define PIN_DIR 14
|
||||
#define PIN_EN 27
|
||||
#include "board.h"
|
||||
#include "hal_motor.h"
|
||||
|
||||
#define STEPS_PER_REV 4800
|
||||
#define DEFAULT_RPM 60
|
||||
#define ACCEL 9600
|
||||
@@ -23,6 +23,10 @@
|
||||
|
||||
static const char *TAG = "motor";
|
||||
|
||||
static gpio_num_t s_pin_en = GPIO_NUM_NC;
|
||||
static gpio_num_t s_pin_dir = GPIO_NUM_NC;
|
||||
static gpio_num_t s_pin_step = GPIO_NUM_NC;
|
||||
static int s_en_disable_level = 1;
|
||||
static TaskHandle_t s_task;
|
||||
static atomic_uint s_stop_req;
|
||||
static float s_cw;
|
||||
@@ -35,13 +39,17 @@ static rmt_encoder_handle_t s_enc;
|
||||
|
||||
static void en_disable(void)
|
||||
{
|
||||
gpio_set_level((gpio_num_t)PIN_EN, 1);
|
||||
if (s_pin_en != GPIO_NUM_NC) {
|
||||
gpio_set_level(s_pin_en, s_en_disable_level);
|
||||
}
|
||||
s_enabled = false;
|
||||
}
|
||||
|
||||
static void en_enable(void)
|
||||
{
|
||||
gpio_set_level((gpio_num_t)PIN_EN, 0);
|
||||
if (s_pin_en != GPIO_NUM_NC) {
|
||||
gpio_set_level(s_pin_en, !s_en_disable_level);
|
||||
}
|
||||
s_enabled = true;
|
||||
}
|
||||
|
||||
@@ -111,7 +119,7 @@ static bool run_move(long steps)
|
||||
if (steps < 0) {
|
||||
steps = -steps;
|
||||
}
|
||||
gpio_set_level((gpio_num_t)PIN_DIR, dir);
|
||||
gpio_set_level(s_pin_dir, dir);
|
||||
|
||||
uint32_t cruise = (s_rpm * STEPS_PER_REV) / 60;
|
||||
if (cruise == 0) {
|
||||
@@ -189,22 +197,31 @@ void hal_motor_init(void)
|
||||
if (s_inited) {
|
||||
return;
|
||||
}
|
||||
s_pin_en = board_pin_motor_en();
|
||||
s_pin_dir = board_pin_motor_dir();
|
||||
s_pin_step = board_pin_motor_step();
|
||||
s_en_disable_level = board_motor_en_disable_level();
|
||||
if (s_pin_en == GPIO_NUM_NC || s_pin_dir == GPIO_NUM_NC || s_pin_step == GPIO_NUM_NC) {
|
||||
ESP_LOGW(TAG, "no motor pins on this board");
|
||||
s_inited = true;
|
||||
return;
|
||||
}
|
||||
gpio_config_t io = {
|
||||
.pin_bit_mask = (1ULL << PIN_EN) | (1ULL << PIN_DIR),
|
||||
.pin_bit_mask = (1ULL << s_pin_en) | (1ULL << s_pin_dir),
|
||||
.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((gpio_num_t)PIN_EN, 1);
|
||||
gpio_set_level((gpio_num_t)PIN_DIR, 0);
|
||||
gpio_set_level(s_pin_en, s_en_disable_level);
|
||||
gpio_set_level(s_pin_dir, 0);
|
||||
s_enabled = false;
|
||||
atomic_store(&s_stop_req, 0);
|
||||
|
||||
rmt_tx_channel_config_t txcfg = {
|
||||
.clk_src = RMT_CLK_SRC_DEFAULT,
|
||||
.gpio_num = PIN_STEP,
|
||||
.gpio_num = s_pin_step,
|
||||
.mem_block_symbols = 64,
|
||||
.resolution_hz = RMT_RES_HZ,
|
||||
.trans_queue_depth = 4,
|
||||
@@ -219,7 +236,8 @@ void hal_motor_init(void)
|
||||
configMAX_PRIORITIES - 2, &s_task, 0);
|
||||
}
|
||||
s_inited = true;
|
||||
ESP_LOGI(TAG, "init EN=HIGH RMT step=%d dir=%d", PIN_STEP, PIN_DIR);
|
||||
ESP_LOGI(TAG, "init en=%d step=%d dir=%d dis_lvl=%d",
|
||||
s_pin_en, s_pin_step, s_pin_dir, s_en_disable_level);
|
||||
}
|
||||
|
||||
void hal_motor_enable(bool on)
|
||||
@@ -234,8 +252,7 @@ void hal_motor_enable(bool on)
|
||||
void hal_motor_request_stop(void)
|
||||
{
|
||||
atomic_store(&s_stop_req, 1);
|
||||
gpio_set_level((gpio_num_t)PIN_EN, 1);
|
||||
s_enabled = false;
|
||||
en_disable();
|
||||
rmt_abort();
|
||||
if (s_task != NULL) {
|
||||
xTaskNotifyGive(s_task);
|
||||
@@ -3,8 +3,11 @@ set(priv_inc)
|
||||
set(priv_req driver)
|
||||
|
||||
if(IDF_TARGET STREQUAL "esp32")
|
||||
list(APPEND srcs wroom/hal_temp.c)
|
||||
list(APPEND srcs hal_temp.c)
|
||||
list(APPEND priv_req board_wroom onewire_bus)
|
||||
elseif(IDF_TARGET STREQUAL "esp32s3")
|
||||
list(APPEND srcs hal_temp.c)
|
||||
list(APPEND priv_req board_jc4827w543 onewire_bus)
|
||||
else()
|
||||
list(APPEND srcs stub/hal_temp.c)
|
||||
endif()
|
||||
|
||||
@@ -8,8 +8,9 @@
|
||||
#include "freertos/task.h"
|
||||
|
||||
#include "onewire_bus.h"
|
||||
#include "board.h"
|
||||
#include "hal_temp.h"
|
||||
|
||||
#define PIN_DS 13
|
||||
#define TEMP_OFFSET 0.4f
|
||||
#define CMD_SKIP_ROM 0xCC
|
||||
#define CMD_CONVERT_T 0x44
|
||||
@@ -40,7 +41,7 @@ static bool scratch_valid(const uint8_t *sp)
|
||||
return crc == sp[8];
|
||||
}
|
||||
|
||||
void autofilm_temp_tick(void)
|
||||
void hal_temp_tick(void)
|
||||
{
|
||||
if (s_bus == NULL) {
|
||||
s_last_ok = false;
|
||||
@@ -84,21 +85,19 @@ void autofilm_temp_tick(void)
|
||||
s_last_ok = true;
|
||||
}
|
||||
|
||||
void autofilm_temp_task(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
for (;;) {
|
||||
autofilm_temp_tick();
|
||||
}
|
||||
}
|
||||
|
||||
void hal_temp_init(void)
|
||||
{
|
||||
if (s_inited) {
|
||||
return;
|
||||
}
|
||||
gpio_num_t pin = board_pin_temp();
|
||||
if (pin == GPIO_NUM_NC) {
|
||||
ESP_LOGW(TAG, "no temp pin on this board");
|
||||
s_inited = true;
|
||||
return;
|
||||
}
|
||||
onewire_bus_config_t bus_config = {
|
||||
.bus_gpio_num = PIN_DS,
|
||||
.bus_gpio_num = pin,
|
||||
.flags = {
|
||||
.en_pull_up = true,
|
||||
},
|
||||
@@ -108,12 +107,12 @@ void hal_temp_init(void)
|
||||
};
|
||||
if (onewire_new_bus_rmt(&bus_config, &rmt_config, &s_bus) != ESP_OK) {
|
||||
s_bus = NULL;
|
||||
ESP_LOGE(TAG, "onewire_bus install failed pin=%d", PIN_DS);
|
||||
ESP_LOGE(TAG, "onewire_bus install failed pin=%d", pin);
|
||||
}
|
||||
s_last_ok = false;
|
||||
s_last_c = 0.0f;
|
||||
s_inited = true;
|
||||
ESP_LOGI(TAG, "init onewire_bus pin=%d offset=%.1f", PIN_DS, (double)TEMP_OFFSET);
|
||||
ESP_LOGI(TAG, "init onewire_bus pin=%d offset=%.1f", pin, (double)TEMP_OFFSET);
|
||||
}
|
||||
|
||||
esp_err_t hal_temp_read_c(float *out)
|
||||
@@ -7,4 +7,5 @@
|
||||
#endif
|
||||
|
||||
void hal_temp_init(void);
|
||||
void hal_temp_tick(void); /* blocking conversion poll; blocks >=750 ms */
|
||||
esp_err_t hal_temp_read_c(float *out); /* ESP_FAIL → disconnected */
|
||||
|
||||
@@ -1,9 +1,17 @@
|
||||
#include "hal_temp.h"
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
void hal_temp_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
void hal_temp_tick(void)
|
||||
{
|
||||
vTaskDelay(pdMS_TO_TICKS(750));
|
||||
}
|
||||
|
||||
esp_err_t hal_temp_read_c(float *out)
|
||||
{
|
||||
(void)out;
|
||||
|
||||
@@ -44,6 +44,8 @@ From `include/config.h` and `src/config.cpp`:
|
||||
|
||||
Motor constants: `STEPS_PER_REV = 4800`, `RPM = 60`, acceleration `9600`. Enable is driven HIGH at boot (disabled).
|
||||
|
||||
Note — S3 panel (JC4827W543C) pin lock via `board_jc4827w543` accessors: motor EN 7 / STEP 16 / DIR 15 on header P3 (IO6/7/15/16), DS18B20 on 17 on header P4 (GND/3V3/17/18, UART1 unused), speaker amp I2S BCLK 42 / LRCLK 2 / DIN 41 (P7 Speak). Header P2 carries IO46/9/14/5 and is left unused (IO46 is input-only).
|
||||
|
||||
Keypad map (5×4):
|
||||
|
||||
```
|
||||
|
||||
@@ -0,0 +1,174 @@
|
||||
# JC4827W543 pin audit
|
||||
|
||||
Comparison of the GPIO assignments in this tree against the vendor
|
||||
documentation at <https://github.com/lsdlsd88/JC4827W543> (GUITION
|
||||
factory docs: spec PDF, IO pin distribution xlsx, Arduino demos).
|
||||
|
||||
Board variants: `JC4827W543N` (no touch), `...R` (resistive XPT2046),
|
||||
`...C` (capacitive GT911). Ours is the **C** model.
|
||||
|
||||
## 1. Vendor-documented pin allocation (authoritative)
|
||||
|
||||
From `5-IO pin distribution/4.3 inches IO pin distribution.xlsx`,
|
||||
cross-checked against the demo sketches
|
||||
(`1-Demo/Demo_Arduino/3_3-*` and `4_*`):
|
||||
|
||||
| GPIO | Vendor function | Notes |
|
||||
| --- | --- | --- |
|
||||
| 0 | BOOT button | also wired to `LCD_TE` |
|
||||
| 1 | `BL_CTRL` | LCD backlight |
|
||||
| 2 | `SPECK_LRCLK` | onboard speaker amp I2S WS |
|
||||
| 3 | `CTP_INT` / `RTP_IRQ` | touch interrupt (both models) |
|
||||
| 4 | `CTP_SCL` | GT911 I2C SCL |
|
||||
| 5 | free | |
|
||||
| 6 | free | |
|
||||
| 7 | free | |
|
||||
| 8 | `CTP_SDA` | GT911 I2C SDA |
|
||||
| 9 | free | |
|
||||
| 10 | `TF_CS` | microSD slot |
|
||||
| 11 | `RTP_DIN` / `TF_MISO` | shared SPI: resistive touch / SD |
|
||||
| 12 | `RTP_CLK` / `TF_CLK` | shared SPI |
|
||||
| 13 | `RTP_DIO` / `TF_MOSI` | shared SPI |
|
||||
| 14 | free | |
|
||||
| 15 | free | exposed on header (P2/P3 area) |
|
||||
| 16 | free | exposed on header; used by vendor LED demo |
|
||||
| 17 | `U1TXD` | UART1 header (P5), usable if UART1 unused |
|
||||
| 18 | `U1RXD` | UART1 header (P5), usable if UART1 unused |
|
||||
| 19 | `USB+` | USB D+ |
|
||||
| 20 | `USB-` | USB D- |
|
||||
| 21 | `LCD_A0` | QSPI data 0 |
|
||||
| 22–25 | — | do not exist on ESP32-S3 |
|
||||
| 26–34 | — | flash/PSRAM or non-existent |
|
||||
| 35 | not available | octal PSRAM (xlsx marks explicitly) |
|
||||
| 36, 37 | free per xlsx | **but** consumed by octal PSRAM on N8R8/R8 modules — treat as unavailable until module variant confirmed |
|
||||
| 38 | `RTP_CS` (resistive model) | on the **C** model this is the GT911 reset line — see §3 |
|
||||
| 39 | `LCD_A3` | QSPI data 3 |
|
||||
| 40 | `LCD_A2` | QSPI data 2 |
|
||||
| 41 | `SPECK_DIN` | speaker amp I2S data in |
|
||||
| 42 | `SPECK_BCLK` | speaker amp I2S BCLK |
|
||||
| 43 | `U0TXD` | console |
|
||||
| 44 | `U0RXD` | console |
|
||||
| 45 | `LCD_CS` | QSPI chip select |
|
||||
| 46 | free per xlsx | strapping pin (`LOG`); output-only-ish, use with care |
|
||||
| 47 | `LCD_CLK` | QSPI clock |
|
||||
| 48 | `LCD_A1` | QSPI data 1 |
|
||||
|
||||
The board carries an onboard I2S speaker amplifier (datasheets for
|
||||
NS4168 / AX9835 ship in `4-Driver_IC_Data_Sheet`), a `Speak` connector
|
||||
(P7), `BAT` connector (P6), TF slot, UART0 console, UART1 header and a
|
||||
scattering of free-IO headers (P2–P5: GPIO 15, 16, 17, 18 visible on
|
||||
the structure diagram). Vendor demos drive LEDs on GPIO 16/17 and a
|
||||
DHT11 on GPIO 27 — note GPIO 27 is **not** in the vendor pin table,
|
||||
so that demo value is suspect/generic.
|
||||
|
||||
## 2. What the code assigns today
|
||||
|
||||
### `board_jc4827w543` (`components/board_jc4827w543/board.c`)
|
||||
|
||||
| Signal | Code GPIO | Vendor | Match |
|
||||
| --- | --- | --- | --- |
|
||||
| LCD CS | 45 | 45 `LCD_CS` | yes |
|
||||
| LCD SCK | 47 | 47 `LCD_CLK` | yes |
|
||||
| LCD D0 | 21 | 21 `LCD_A0` | yes |
|
||||
| LCD D1 | 48 | 48 `LCD_A1` | yes |
|
||||
| LCD D2 | 40 | 40 `LCD_A2` | yes |
|
||||
| LCD D3 | 39 | 39 `LCD_A3` | yes |
|
||||
| LCD BL | 1 | 1 `BL_CTRL` | yes |
|
||||
| TP SDA | 8 | 8 `CTP_SDA` | yes |
|
||||
| TP SCL | 4 | 4 `CTP_SCL` | yes |
|
||||
| TP INT | 3 | 3 `CTP_INT` | yes |
|
||||
| TP RST | 38 | 38 (demo: `TOUCH_RES 38`) | yes — see §3 |
|
||||
| Motor EN | `GPIO_NUM_NC` | n/a | deliberately unassigned |
|
||||
|
||||
### `hal_display_nv3041a.c`
|
||||
|
||||
Driver **NV3041A** over QSPI via `esp_lcd` SPI host, 480×272, quad
|
||||
mode, 40 MHz. Matches the vendor demo
|
||||
(`Arduino_ESP32QSPI(45,47,21,48,40,39)` + `Arduino_NV3041A`,
|
||||
`Arduino_Canvas(480,272)`).
|
||||
|
||||
Caveat: the spec sheet PDF lists the driver chip as "ST3401A" — that
|
||||
string appears nowhere else; every demo and the burn files use
|
||||
NV3041A. Treat the PDF label as a typo.
|
||||
|
||||
### `hal_input_gt911.c`
|
||||
|
||||
GT911 at I2C addr `0x5D` (`GT911_SLAVE_ADDRESS1` in the vendor
|
||||
`touch.h`), I2C_NUM_0 @ 400 kHz on SDA 8 / SCL 4. Reset sequence
|
||||
(drive INT low, pulse RST, release INT to input) selects the 0x5D
|
||||
address per the GT911 datasheet — matches the vendor demo's
|
||||
`TOUCH_RES 38` / `TOUCH_INT 3` wiring.
|
||||
|
||||
### `board_wroom` + `hal_*` (classic ESP32, unchanged)
|
||||
|
||||
| Signal | GPIO | Source |
|
||||
| --- | --- | --- |
|
||||
| Stepper STEP | 12 | `config.h`, `hal_motor.c` |
|
||||
| Stepper DIR | 14 | `config.h`, `hal_motor.c` |
|
||||
| Stepper EN (active LOW) | 27 | `config.h`, `hal_motor.c`, `board_wroom` |
|
||||
| DS18B20 | 13 | `config.h`, `hal_temp.c` |
|
||||
| Beeper | 25 | `config.cpp`, `hal_audio.c` |
|
||||
| LCD 2004 I2C | SDA 21 / SCL 22, addr 0x27 | `config.cpp`, `hal_display_lcd2004.c` |
|
||||
| Keypad rows | 19, 18, 5, 17, 16 | `config.cpp`, `hal_input_keypad.c` |
|
||||
| Keypad cols | 15, 2, 0, 4 | `config.cpp`, `hal_input_keypad.c` |
|
||||
|
||||
Self-consistent with `docs/CURRENT_STATE.md`. Not related to the S3
|
||||
panel.
|
||||
|
||||
## 3. Findings / discrepancies
|
||||
|
||||
1. **Display and touch pins are all correct.** Every QSPI, backlight
|
||||
and GT911 pin in `board_jc4827w543/board.c` matches both the
|
||||
vendor xlsx and the vendor Arduino demos. No changes needed.
|
||||
|
||||
2. **TP_RST on GPIO 38 is undocumented for the C model.** The xlsx
|
||||
labels IO38 `RTP_CS` (its resistive-touch function). The capacitive
|
||||
demos (`LvglWidgets/touch.h`) set `TOUCH_RES 38`, so on the C
|
||||
variant IO38 is clearly the GT911 reset. Our code is right, but the
|
||||
vendor table alone would not tell you that — the demo code is the
|
||||
authority here.
|
||||
|
||||
3. **Motor EN/STEP/DIR are unassigned on the S3 board** (`GPIO_NUM_NC`
|
||||
in `board.c`). Correct call — but usable free pins do exist.
|
||||
Candidates from the vendor table + headers:
|
||||
- Safest (plain free, on headers): **15, 16** and UART1 header
|
||||
**17, 18** if UART1 is unused.
|
||||
- Free in xlsx but not obviously headered: **5, 6, 7, 9, 14**.
|
||||
- **Avoid**: 0 (BOOT/LCD_TE), 1–4/8 (LCD+touch+speaker), 10–13
|
||||
(TF/RTP SPI), 19/20 (USB), 21 (LCD D0), 35–37 (octal PSRAM),
|
||||
38–48 (used/strapping), 43/44 (console).
|
||||
- GPIO 46 is xlsx-free but is a strapping pin — last resort only.
|
||||
- Octal PSRAM (`sdkconfig.s3`: `CONFIG_SPIRAM_MODE_OCT=y`) means
|
||||
33–37 are off-limits even though the xlsx only flags 35.
|
||||
|
||||
4. **Audio on S3 should use I2S, not a beeper GPIO.** The board has a
|
||||
speaker amp on IO2 (LRCLK), IO41 (DIN), IO42 (BCLK) — P7 `Speak`
|
||||
connector. `hal_audio` currently builds the LEDC buzzer only for
|
||||
esp32 and a stub elsewhere; an S3 implementation should drive
|
||||
I2S on those pins rather than allocating a GPIO.
|
||||
|
||||
5. **DS18B20 on S3 needs one free GPIO** (any of §3's candidates; it
|
||||
only needs input+open-drain drive). Hal currently stubs temp on
|
||||
non-esp32.
|
||||
|
||||
6. **Reserved/bus-shared notes**: GPIO 0 carries `LCD_TE` in addition
|
||||
to BOOT — do not use it for anything else. TF card SPI (10–13) is
|
||||
shared with resistive-touch signals on R models; on our C model
|
||||
it's purely the SD slot.
|
||||
|
||||
7. **No conflicts found** between the code's S3 selections and the
|
||||
vendor map — every consumed pin is one the vendor assigns to that
|
||||
same function.
|
||||
|
||||
## Suggested motor wiring (for when S3 motor support lands)
|
||||
|
||||
| Signal | Suggested GPIO | Rationale |
|
||||
| --- | --- | --- |
|
||||
| STEP | 16 | free, on header, no boot function |
|
||||
| DIR | 15 | free, on header |
|
||||
| EN (active LOW) | 17 or 18 | UART1 header; free if UART1 unused |
|
||||
| DS18B20 | 9 or 14 | free, any GPIO works |
|
||||
|
||||
If UART1 is wanted for something else, use 5/6/7 for EN/temp instead.
|
||||
Keep motor EN's disable-first behaviour (drive inactive at boot before
|
||||
enabling output mode) whatever pins are chosen.
|
||||
@@ -0,0 +1,14 @@
|
||||
# JC4827W543 pin audit - ERRATA
|
||||
|
||||
*Based on verification against the official vendor repository at <https://github.com/lsdlsd88/JC4827W543>.*
|
||||
|
||||
**No errors were found in the original `JC4827W543_PIN_AUDIT.md` document.**
|
||||
|
||||
### Verification Notes:
|
||||
- **Vendor IO pin distribution:** The `4.3 inches IO pin distribution.xlsx` file perfectly matches the pinout matrix in the audit document (e.g., IO45 for LCD_CS, IO47 for LCD_CLK, etc., and SPECK_LRCLK / SPECK_DIN / SPECK_BCLK correctly documented as I2S lines).
|
||||
- **Display Configuration:** `Arduino_ESP32QSPI` code in `LvglWidgets.ino` verifies the QSPI display pins as `CS:45, SCK:47, D0:21, D1:48, D2:40, D3:39` matching the audit exactly.
|
||||
- **Touch Controller:** Capacitive GT911 configuration uses `TOUCH_SDA = 8`, `TOUCH_SCL = 4`, `TOUCH_RES = 38`, `TOUCH_INT = 3` which aligns with the undocumented `RTP_CS (38)` being effectively co-opted for capacitive reset, confirming the finding in the original document.
|
||||
- **Demos:** The DHT11 demo at `1-Demo/Demo_Arduino/4_9_WIFI Web Servers DHT11` indeed uses `GPIO 27`, and the `4_7_WIFI Web Servers LED` demo uses `GPIO 16/17`. These assignments are generic demo choices as noted in the original document and correctly do not conflict with the board specifications.
|
||||
- **Proposed GPIOs:** The suggested GPIOs for motor control (`16`, `15`, `17`, `18`, `9`, `14`, `5`, `6`, `7`) are correctly identified as free based on the schematic and code.
|
||||
|
||||
The original document is factually sound and can be completely trusted as the authoritative reference for this project.
|
||||
@@ -0,0 +1,184 @@
|
||||
# JC4827W543 pin audit
|
||||
|
||||
Comparison of the GPIO assignments in this tree against the vendor
|
||||
documentation at <https://github.com/lsdlsd88/JC4827W543> (GUITION
|
||||
factory docs: spec PDF, IO pin distribution xlsx, Arduino demos).
|
||||
|
||||
Board variants: `JC4827W543N` (no touch), `...R` (resistive XPT2046),
|
||||
`...C` (capacitive GT911). Ours is the **C** model.
|
||||
|
||||
## 1. Vendor-documented pin allocation (authoritative)
|
||||
|
||||
From `5-IO pin distribution/4.3 inches IO pin distribution.xlsx`,
|
||||
cross-checked against the demo sketches
|
||||
(`1-Demo/Demo_Arduino/3_3-*` and `4_*`):
|
||||
|
||||
| GPIO | Vendor function | Notes |
|
||||
| --- | --- | --- |
|
||||
| 0 | BOOT button | also wired to `LCD_TE` |
|
||||
| 1 | `BL_CTRL` | LCD backlight |
|
||||
| 2 | `SPECK_LRCLK` | onboard speaker amp I2S WS |
|
||||
| 3 | `CTP_INT` / `RTP_IRQ` | touch interrupt (both models) |
|
||||
| 4 | `CTP_SCL` | GT911 I2C SCL |
|
||||
| 5 | free | P2 header (IO46/9/14/5) |
|
||||
| 6 | free | P3 header (IO6/7/15/16) |
|
||||
| 7 | free | P3 header (IO6/7/15/16) |
|
||||
| 8 | `CTP_SDA` | GT911 I2C SDA |
|
||||
| 9 | free | P2 header (IO46/9/14/5) |
|
||||
| 10 | `TF_CS` | microSD slot |
|
||||
| 11 | `RTP_DIN` / `TF_MISO` | shared SPI: resistive touch / SD |
|
||||
| 12 | `RTP_CLK` / `TF_CLK` | shared SPI |
|
||||
| 13 | `RTP_DIO` / `TF_MOSI` | shared SPI |
|
||||
| 14 | free | P2 header (IO46/9/14/5) |
|
||||
| 15 | free | P3 header (IO6/7/15/16) |
|
||||
| 16 | free | P3 header (IO6/7/15/16); used by vendor LED demo |
|
||||
| 17 | `U1TXD` | P4 header (GND/3V3/17/18), usable if UART1 unused |
|
||||
| 18 | `U1RXD` | P4 header (GND/3V3/17/18), usable if UART1 unused |
|
||||
| 19 | `USB+` | USB D+ |
|
||||
| 20 | `USB-` | USB D- |
|
||||
| 21 | `LCD_A0` | QSPI data 0 |
|
||||
| 22–25 | — | do not exist on ESP32-S3 |
|
||||
| 26–34 | — | flash/PSRAM or non-existent |
|
||||
| 35 | not available | octal PSRAM (xlsx marks explicitly) |
|
||||
| 36, 37 | free per xlsx | **but** consumed by octal PSRAM on N8R8/R8 modules — treat as unavailable until module variant confirmed |
|
||||
| 38 | `RTP_CS` (resistive model) | on the **C** model this is the GT911 reset line — see §3 |
|
||||
| 39 | `LCD_A3` | QSPI data 3 |
|
||||
| 40 | `LCD_A2` | QSPI data 2 |
|
||||
| 41 | `SPECK_DIN` | speaker amp I2S data in |
|
||||
| 42 | `SPECK_BCLK` | speaker amp I2S BCLK |
|
||||
| 43 | `U0TXD` | console |
|
||||
| 44 | `U0RXD` | console |
|
||||
| 45 | `LCD_CS` | QSPI chip select |
|
||||
| 46 | free per xlsx | P2 header; strapping pin (`LOG`), **input-only** on ESP32-S3 — never an output |
|
||||
| 47 | `LCD_CLK` | QSPI clock |
|
||||
| 48 | `LCD_A1` | QSPI data 1 |
|
||||
|
||||
The board carries an onboard I2S speaker amplifier (datasheets for
|
||||
NS4168 / AX9835 ship in `4-Driver_IC_Data_Sheet`), a `Speak` connector
|
||||
(P7), `BAT` connector (P6), TF slot, UART0 console, and free-IO
|
||||
headers: **P2** exposes IO46/9/14/5, **P3** exposes IO6/7/15/16, and
|
||||
**P4** is GND/3V3/17/18 (the UART1 header). Vendor demos drive LEDs on GPIO 16/17 and a
|
||||
DHT11 on GPIO 27 — note GPIO 27 is **not** in the vendor pin table,
|
||||
so that demo value is suspect/generic.
|
||||
|
||||
## 2. What the code assigns today
|
||||
|
||||
### `board_jc4827w543` (`components/board_jc4827w543/board.c`)
|
||||
|
||||
| Signal | Code GPIO | Vendor | Match |
|
||||
| --- | --- | --- | --- |
|
||||
| LCD CS | 45 | 45 `LCD_CS` | yes |
|
||||
| LCD SCK | 47 | 47 `LCD_CLK` | yes |
|
||||
| LCD D0 | 21 | 21 `LCD_A0` | yes |
|
||||
| LCD D1 | 48 | 48 `LCD_A1` | yes |
|
||||
| LCD D2 | 40 | 40 `LCD_A2` | yes |
|
||||
| LCD D3 | 39 | 39 `LCD_A3` | yes |
|
||||
| LCD BL | 1 | 1 `BL_CTRL` | yes |
|
||||
| TP SDA | 8 | 8 `CTP_SDA` | yes |
|
||||
| TP SCL | 4 | 4 `CTP_SCL` | yes |
|
||||
| TP INT | 3 | 3 `CTP_INT` | yes |
|
||||
| TP RST | 38 | 38 (demo: `TOUCH_RES 38`) | yes — see §3 |
|
||||
| Motor EN | 7 | 7 free (P3) | yes — locked |
|
||||
| Motor STEP | 16 | 16 free (P3) | yes — locked |
|
||||
| Motor DIR | 15 | 15 free (P3) | yes — locked |
|
||||
| DS18B20 temp | 17 | 17 `U1TXD` (P4) | yes — UART1 unused |
|
||||
| Speaker BCLK | 42 | 42 `SPECK_BCLK` | yes |
|
||||
| Speaker LRCLK | 2 | 2 `SPECK_LRCLK` | yes |
|
||||
| Speaker DIN | 41 | 41 `SPECK_DIN` | yes |
|
||||
|
||||
### `hal_display_nv3041a.c`
|
||||
|
||||
Driver **NV3041A** over QSPI via `esp_lcd` SPI host, 480×272, quad
|
||||
mode, 40 MHz. Matches the vendor demo
|
||||
(`Arduino_ESP32QSPI(45,47,21,48,40,39)` + `Arduino_NV3041A`,
|
||||
`Arduino_Canvas(480,272)`).
|
||||
|
||||
Caveat: the spec sheet PDF lists the driver chip as "ST3401A" — that
|
||||
string appears nowhere else; every demo and the burn files use
|
||||
NV3041A. Treat the PDF label as a typo.
|
||||
|
||||
### `hal_input_gt911.c`
|
||||
|
||||
GT911 at I2C addr `0x5D` (`GT911_SLAVE_ADDRESS1` in the vendor
|
||||
`touch.h`), I2C_NUM_0 @ 400 kHz on SDA 8 / SCL 4. Reset sequence
|
||||
(drive INT low, pulse RST, release INT to input) selects the 0x5D
|
||||
address per the GT911 datasheet — matches the vendor demo's
|
||||
`TOUCH_RES 38` / `TOUCH_INT 3` wiring.
|
||||
|
||||
### `board_wroom` + `hal_*` (classic ESP32, unchanged)
|
||||
|
||||
| Signal | GPIO | Source |
|
||||
| --- | --- | --- |
|
||||
| Stepper STEP | 12 | `config.h`, `hal_motor.c` |
|
||||
| Stepper DIR | 14 | `config.h`, `hal_motor.c` |
|
||||
| Stepper EN (active LOW) | 27 | `config.h`, `hal_motor.c`, `board_wroom` |
|
||||
| DS18B20 | 13 | `config.h`, `hal_temp.c` |
|
||||
| Beeper | 25 | `config.cpp`, `hal_audio.c` |
|
||||
| LCD 2004 I2C | SDA 21 / SCL 22, addr 0x27 | `config.cpp`, `hal_display_lcd2004.c` |
|
||||
| Keypad rows | 19, 18, 5, 17, 16 | `config.cpp`, `hal_input_keypad.c` |
|
||||
| Keypad cols | 15, 2, 0, 4 | `config.cpp`, `hal_input_keypad.c` |
|
||||
|
||||
Self-consistent with `docs/CURRENT_STATE.md`. Not related to the S3
|
||||
panel.
|
||||
|
||||
## 3. Findings / discrepancies
|
||||
|
||||
1. **Display and touch pins are all correct.** Every QSPI, backlight
|
||||
and GT911 pin in `board_jc4827w543/board.c` matches both the
|
||||
vendor xlsx and the vendor Arduino demos. No changes needed.
|
||||
|
||||
2. **TP_RST on GPIO 38 is undocumented for the C model.** The xlsx
|
||||
labels IO38 `RTP_CS` (its resistive-touch function). The capacitive
|
||||
demos (`LvglWidgets/touch.h`) set `TOUCH_RES 38`, so on the C
|
||||
variant IO38 is clearly the GT911 reset. Our code is right, but the
|
||||
vendor table alone would not tell you that — the demo code is the
|
||||
authority here.
|
||||
|
||||
3. **Motor EN/STEP/DIR and DS18B20 are now locked on the S3 board.**
|
||||
Header labels confirmed: P2 exposes IO46/9/14/5, P3 exposes
|
||||
IO6/7/15/16, P4 is GND/3V3/17/18 (the UART1 header).
|
||||
- Motor STEP **16**, DIR **15**, EN **7** (active LOW) — all on P3;
|
||||
IO6 stays spare.
|
||||
- DS18B20 on **17** — P4 puts GND, 3V3 and data on one header;
|
||||
UART1 is unused.
|
||||
- Speaker amp I2S stays on the vendor pins: BCLK **42**,
|
||||
LRCLK **2**, DIN **41** (P7 `Speak`).
|
||||
- **Avoid**: 0 (BOOT/LCD_TE), 1–4/8 (LCD+touch+speaker), 10–13
|
||||
(TF/RTP SPI), 19/20 (USB), 21 (LCD D0), 35–37 (octal PSRAM),
|
||||
38–48 (used/strapping), 43/44 (console).
|
||||
- GPIO 46 is xlsx-free and on P2 but is **input-only** on the
|
||||
ESP32-S3 — never use it for outputs.
|
||||
- Octal PSRAM (`sdkconfig.s3`: `CONFIG_SPIRAM_MODE_OCT=y`) means
|
||||
33–37 are off-limits even though the xlsx only flags 35.
|
||||
|
||||
4. **Audio on S3 should use I2S, not a beeper GPIO.** The board has a
|
||||
speaker amp on IO2 (LRCLK), IO41 (DIN), IO42 (BCLK) — P7 `Speak`
|
||||
connector. `hal_audio` currently builds the LEDC buzzer only for
|
||||
esp32 and a stub elsewhere; an S3 implementation should drive
|
||||
I2S on those pins rather than allocating a GPIO.
|
||||
|
||||
5. **DS18B20 on S3 needs one free GPIO** (any of §3's candidates; it
|
||||
only needs input+open-drain drive). Hal currently stubs temp on
|
||||
non-esp32.
|
||||
|
||||
6. **Reserved/bus-shared notes**: GPIO 0 carries `LCD_TE` in addition
|
||||
to BOOT — do not use it for anything else. TF card SPI (10–13) is
|
||||
shared with resistive-touch signals on R models; on our C model
|
||||
it's purely the SD slot.
|
||||
|
||||
7. **No conflicts found** between the code's S3 selections and the
|
||||
vendor map — every consumed pin is one the vendor assigns to that
|
||||
same function.
|
||||
|
||||
## Motor / temp / speaker wiring as locked (phase I01)
|
||||
|
||||
| Signal | GPIO | Rationale |
|
||||
| --- | --- | --- |
|
||||
| STEP | 16 | free, P3 header, no boot function |
|
||||
| DIR | 15 | free, P3 header |
|
||||
| EN (active LOW) | 7 | free, P3 header |
|
||||
| DS18B20 | 17 | P4 header carries GND/3V3/17/18 — one connector for the sensor |
|
||||
| Speaker BCLK / LRCLK / DIN | 42 / 2 / 41 | onboard amp wired to P7 `Speak` |
|
||||
|
||||
Keep motor EN's disable-first behaviour (drive inactive at boot before
|
||||
enabling output mode).
|
||||
@@ -0,0 +1,41 @@
|
||||
# INTEGRATION MEGAPLAN — AutoFilm-ESP32 S3 Hardware Integration
|
||||
|
||||
Audience: coding agent. One phase = one session. Do not start the next phase in the same session.
|
||||
|
||||
## Summary
|
||||
|
||||
This megaplan drives the hardware integration for the ESP32-S3 (JC4827W543) board, activating the stepper motor, DS18B20 temperature sensor, and I2S speaker using conflict-free, header-available GPIOs. To ensure success, these changes have been broken down from a single monolithic phase into a sequence of safe, isolated phases.
|
||||
|
||||
## Protocol (every session)
|
||||
|
||||
1. Ensure you are on the appropriate integration branch off `develop`.
|
||||
2. Read only: `AGENTS.md`, this file (status table), **the assigned phase file**. Open other docs only if the phase `READ:` list says so.
|
||||
3. Execute `IN` only. Honour `OUT` and `FORBIDDEN`.
|
||||
4. Run `VERIFY` exactly. Do not push if any verify item fails.
|
||||
5. Commits: messages listed in the phase. Imperative. No secret tokens.
|
||||
6. Push to origin. PR target is `develop`, not `main`.
|
||||
7. Set phase `STATUS:` to `DONE` in the phase file **and** this table. One-line `Notes` if you diverged (API name only — do not silently change behaviour).
|
||||
|
||||
If blocked: stop, commit nothing broken, write `BLOCKED:` at top of the phase file with the exact error.
|
||||
|
||||
## Frozen constraints (never reinterpret)
|
||||
|
||||
- The motor EN/STEP/DIR, DS18B20, and I2S audio pins for the JC4827W543 are strictly defined in this plan and the pin audit doc.
|
||||
- **Constraints that eliminate S3 pins:**
|
||||
- QSPI display: 45, 47, 21, 48, 40, 39 + BL 1 — consumed
|
||||
- GT911: SDA 8, SCL 4, INT 3, RST 38 — consumed
|
||||
- Speaker I2S: 2 (LRCLK), 41 (DIN), 42 (BCLK) — consumed by onboard amp
|
||||
- TF slot: 10–13; USB: 19/20; UART0: 43/44; BOOT+LCD_TE: 0
|
||||
- Octal PSRAM: 33–37 off-limits
|
||||
- GPIO46 is INPUT-ONLY on ESP32-S3 — excluded from outputs entirely
|
||||
- UI never blocks on hardware operations (motor, OneWire, I2S).
|
||||
- Watchdog stays **on**. No `vTaskDelete` of long-lived workers.
|
||||
|
||||
## Status
|
||||
|
||||
| ID | File | Session goal | STATUS |
|
||||
| --- | --- | --- | --- |
|
||||
| I01 | `integration/I01-board-configs.md` | Board pin allocations & accessors | DONE |
|
||||
| I02 | `integration/I02-temp-fix.md` | Temp HAL shared & starvation fix | DONE |
|
||||
| I03 | `integration/I03-motor-hal.md` | Motor HAL shared across boards | DONE |
|
||||
| I04 | `integration/I04-audio-i2s.md` | I2S audio implementation for S3 | DONE |
|
||||
@@ -0,0 +1,23 @@
|
||||
STATUS: DONE
|
||||
DEPENDS: none
|
||||
|
||||
**READ:** `docs/megaplans/INTEGRATION-MEGAPLAN.md`, `docs/JC4827W543_PIN_AUDIT_VERIFIED.md`, `components/board_jc4827w543/board.c`, `components/board_wroom/board.c`
|
||||
|
||||
**IN:**
|
||||
1. `board_jc4827w543`: add `board_pin_motor_step()` → 16, `board_pin_motor_dir()` → 15, `board_pin_temp()` → 17, `board_pin_spk_bclk()`, `board_pin_spk_lrclk()`, `board_pin_spk_din()` → 42, 2, 41; change `board_pin_motor_en()` → 7 (keep disable level 1 = active-LOW EN).
|
||||
2. `board_wroom`: add matching `board_pin_motor_step()` → 12, `board_pin_motor_dir()` → 14, `board_pin_temp()` → 13 so HAL impls can be shared.
|
||||
3. Update `docs/CURRENT_STATE.md` pin table note and `JC4827W543_PIN_AUDIT_VERIFIED.md` header section with the corrected labels if not already updated (P2: IO46/9/14/5, P3: IO6/7/15/16, P4: GND/3V3/17/18).
|
||||
|
||||
**OUT:** HAL implementations, business logic, NVS profiles.
|
||||
**FORBIDDEN:** GPIO46 for any output; stealing TF, QSPI, GT911, USB, or UART0 pins.
|
||||
|
||||
**VERIFY:** `idf.py build` succeeds for both `esp32` and `esp32s3` targets.
|
||||
|
||||
**COMMITS:**
|
||||
1. `Lock S3 header pins and introduce shared board pin accessors`
|
||||
2. `Update pin audit documentation labels`
|
||||
|
||||
**DoD checkboxes:**
|
||||
- [ ] `board_jc4827w543` pin accessors added.
|
||||
- [ ] `board_wroom` pin accessors added.
|
||||
- [ ] Build succeeds on both targets.
|
||||
@@ -0,0 +1,23 @@
|
||||
STATUS: DONE
|
||||
DEPENDS: I01
|
||||
Notes: Poll API named `hal_temp_tick` (declared in hal_temp.h). `idf.py build` for both targets verified via CI run 38616 (no local IDF). S3 flash watchdog check not run — no device attached to this machine.
|
||||
|
||||
**READ:** `docs/megaplans/INTEGRATION-MEGAPLAN.md`, `main/main.c`, `components/hal_temp/*`
|
||||
|
||||
**IN:**
|
||||
1. `hal_temp`: Generalize `hal_temp.c` to use `board_pin_temp()` instead of hardcoded macros. Compile for both targets via CMake (`IDF_TARGET esp32|esp32s3` → shared source, `PRIV_REQUIRES board_wroom|board_jc4827w543`).
|
||||
2. `main.c` **bug fix**: `temp_task` currently calls `autofilm_temp_tick()` only `#ifdef AUTOFILM_BOARD_WROOM` and has **no `vTaskDelay`** — on S3 it spins at priority 2 and starves the idle task (task-WDT risk). Move the tick loop into a `hal_temp`-level poll (e.g. `hal_temp_tick()` weak per-board) or add `vTaskDelay(pdMS_TO_TICKS(750))` on the non-WROOM path so the task always blocks.
|
||||
|
||||
**OUT:** Motor logic, audio logic.
|
||||
**FORBIDDEN:** Removing the watchdog, deleting the temp task.
|
||||
|
||||
**VERIFY:** `idf.py build` succeeds for both `esp32` and `esp32s3`. Flash to S3 and verify no task watchdog panics occur in the console.
|
||||
|
||||
**COMMITS:**
|
||||
1. `Share onewire temp HAL across both boards`
|
||||
2. `Fix temp_task starvation bug on non-WROOM`
|
||||
|
||||
**DoD checkboxes:**
|
||||
- [x] `hal_temp` generalized to use board accessors.
|
||||
- [x] `temp_task` starvation bug fixed.
|
||||
- [x] Build succeeds on both targets.
|
||||
@@ -0,0 +1,21 @@
|
||||
STATUS: DONE
|
||||
DEPENDS: I01
|
||||
|
||||
**READ:** `docs/megaplans/INTEGRATION-MEGAPLAN.md`, `components/hal_motor/*`
|
||||
|
||||
**IN:**
|
||||
1. `hal_motor`: Generalize `wroom/hal_motor.c` (already pure-IDF RMT) to read pins from `board.h`; compile for both targets via CMake (`IDF_TARGET esp32|esp32s3` → shared source, `PRIV_REQUIRES board_wroom|board_jc4827w543`).
|
||||
2. Preserve: EN HIGH at init + on stop, `stop_req` sampled inside step loop, immortal task, `hal_motor_request_stop` ISR-safe.
|
||||
|
||||
**OUT:** Temp logic, audio logic.
|
||||
**FORBIDDEN:** Blocking UI on motor operations.
|
||||
|
||||
**VERIFY:** `idf.py build` succeeds for both targets. Run host ctests if any apply to motor logic.
|
||||
|
||||
**COMMITS:**
|
||||
1. `Share RMT motor HAL across both boards`
|
||||
|
||||
**DoD checkboxes:**
|
||||
- [ ] `hal_motor` generalized to use board accessors.
|
||||
- [ ] EN HIGH initialization preserved.
|
||||
- [ ] Build succeeds on both targets.
|
||||
@@ -0,0 +1,23 @@
|
||||
STATUS: DONE
|
||||
DEPENDS: I01
|
||||
Notes: `idf.py build` for both targets verified via CI run 38684 (no local IDF).
|
||||
|
||||
**READ:** `docs/megaplans/INTEGRATION-MEGAPLAN.md`, `components/hal_audio/*`
|
||||
|
||||
**IN:**
|
||||
1. `hal_audio` S3: Implement new `s3/hal_audio.c` using `i2s_std` TX on pins 41/42/2 (via `board_pin_spk_*`) to the NS4168 amp.
|
||||
2. Generate 2 kHz square-wave bursts into a small DMA buffer.
|
||||
3. Ensure identical queue protocol (SHORT / 10×ALARM 500ms-on/250ms-off / CANCEL) and non-blocking semantics as the WROOM LEDC version.
|
||||
|
||||
**OUT:** Motor logic, Temp logic.
|
||||
**FORBIDDEN:** Blocking the UI on I2S writes.
|
||||
|
||||
**VERIFY:** `idf.py build` succeeds for both targets.
|
||||
|
||||
**COMMITS:**
|
||||
1. `Add I2S speaker audio for S3`
|
||||
|
||||
**DoD checkboxes:**
|
||||
- [x] `hal_audio` I2S implementation added for S3.
|
||||
- [x] Queue protocol and non-blocking semantics maintained.
|
||||
- [x] Build succeeds.
|
||||
+2
-1
@@ -12,7 +12,8 @@ endif()
|
||||
idf_component_register(SRCS "main.c"
|
||||
INCLUDE_DIRS "."
|
||||
REQUIRES ${BOARD_COMP} driver app_process app_machine app_ui
|
||||
hal_motor hal_temp hal_audio hal_display hal_input)
|
||||
hal_motor hal_temp hal_audio hal_display hal_input
|
||||
PRIV_REQUIRES esp_timer)
|
||||
|
||||
if(IDF_TARGET STREQUAL "esp32")
|
||||
target_compile_definitions(${COMPONENT_LIB} PRIVATE AUTOFILM_BOARD_WROOM=1)
|
||||
|
||||
+1
-5
@@ -28,8 +28,6 @@ static const char *TAG = "app";
|
||||
#if defined(AUTOFILM_BOARD_WROOM) || defined(AUTOFILM_BOARD_S3)
|
||||
static QueueHandle_t s_cmdq;
|
||||
|
||||
extern void autofilm_temp_tick(void);
|
||||
|
||||
static void map_and_post_key(char key)
|
||||
{
|
||||
ui_cmd_t cmd;
|
||||
@@ -168,9 +166,7 @@ static void temp_task(void *arg)
|
||||
(void)arg;
|
||||
esp_task_wdt_add(NULL);
|
||||
for (;;) {
|
||||
#ifdef AUTOFILM_BOARD_WROOM
|
||||
autofilm_temp_tick();
|
||||
#endif
|
||||
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);
|
||||
|
||||
@@ -10,6 +10,10 @@ void hal_temp_init(void)
|
||||
stub_temp_c = 20.0f;
|
||||
}
|
||||
|
||||
void hal_temp_tick(void)
|
||||
{
|
||||
}
|
||||
|
||||
esp_err_t hal_temp_read_c(float *out)
|
||||
{
|
||||
if (stub_temp_fail) {
|
||||
|
||||
Reference in New Issue
Block a user