Add optional cyd_35r (ESP32-3248S035) with 480x320 UI; default remains 2.8.
This commit is contained in:
@@ -1,9 +1,13 @@
|
||||
# Rebuild (optional) and refresh firmware/cyd from PlatformIO build output.
|
||||
# Usage:
|
||||
# .\firmware\export_from_build.ps1
|
||||
# .\firmware\export_from_build.ps1 -SkipBuild
|
||||
# Export firmware bins from PlatformIO build.
|
||||
# Default: 2.8" (cyd -> firmware/cyd)
|
||||
# 3.5": .\firmware\export_from_build.ps1 -Env cyd_35r
|
||||
# (only after: pio run -e cyd_35r)
|
||||
|
||||
param([switch]$SkipBuild)
|
||||
param(
|
||||
[switch]$SkipBuild,
|
||||
[ValidateSet("cyd", "cyd_35r")]
|
||||
[string]$Env = "cyd"
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
$root = Split-Path -Parent (Split-Path -Parent $MyInvocation.MyCommand.Path)
|
||||
@@ -12,17 +16,26 @@ Set-Location $root
|
||||
$env:Path = "C:\Users\dsx2016\AppData\Local\Programs\Python\Python312\Scripts;" + $env:Path
|
||||
|
||||
if (-not $SkipBuild) {
|
||||
pio run -e cyd
|
||||
pio run -e $Env
|
||||
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
|
||||
}
|
||||
|
||||
$src = Join-Path $root ".pio\build\cyd"
|
||||
$dst = Join-Path $root "firmware\cyd"
|
||||
$src = Join-Path $root (".pio\build\" + $Env)
|
||||
if ($Env -eq "cyd_35r") {
|
||||
$dstName = "cyd_35r"
|
||||
$boardLine = "board: ESP32-3248S035 (ST7796)"
|
||||
$boardIdHint = "esp32-3248s035"
|
||||
} else {
|
||||
$dstName = "cyd"
|
||||
$boardLine = "board: ESP32-2432S028R (ILI9341)"
|
||||
$boardIdHint = "esp32-2432s028"
|
||||
}
|
||||
$dst = Join-Path $root ("firmware\" + $dstName)
|
||||
New-Item -ItemType Directory -Force -Path $dst | Out-Null
|
||||
|
||||
foreach ($f in @("bootloader.bin", "partitions.bin", "firmware.bin")) {
|
||||
$p = Join-Path $src $f
|
||||
if (-not (Test-Path $p)) { Write-Error "Missing build artifact: $p" }
|
||||
if (-not (Test-Path $p)) { Write-Error "Missing build artifact: $p — build with: pio run -e $Env" }
|
||||
Copy-Item $p $dst -Force
|
||||
}
|
||||
|
||||
@@ -32,17 +45,15 @@ if (-not (Test-Path $bootApp)) {
|
||||
}
|
||||
Copy-Item $bootApp (Join-Path $dst "boot_app0.bin") -Force
|
||||
|
||||
# Keep flash scripts if already present
|
||||
$git = ""
|
||||
try { $git = (git -C $root rev-parse --short HEAD).Trim() } catch { $git = "unknown" }
|
||||
$date = Get-Date -Format "yyyy-MM-dd"
|
||||
$hashes = Get-ChildItem (Join-Path $dst "*.bin") | Get-FileHash -Algorithm SHA256
|
||||
$lines = @(
|
||||
"name: CYD Pomodoro (cyd)",
|
||||
"name: CYD tftest ($dstName)",
|
||||
"git: $git",
|
||||
"date: $date",
|
||||
"board: ESP32-2432S028R (ILI9341)",
|
||||
"features: Pomodoro timer, SoftSPI touch, GPIO26 speaker, TF status",
|
||||
$boardLine,
|
||||
"flash_size: 4MB",
|
||||
"offsets:",
|
||||
" 0x1000 bootloader.bin",
|
||||
@@ -55,4 +66,22 @@ foreach ($h in $hashes) {
|
||||
$lines += (" {0,-15} {1}" -f (Split-Path $h.Path -Leaf), $h.Hash)
|
||||
}
|
||||
$lines | Set-Content -Encoding utf8 (Join-Path $dst "VERSION.txt")
|
||||
Write-Host "Exported -> $dst (git $git)"
|
||||
|
||||
# Keep / refresh meta.json boardId for catalog filtering
|
||||
$metaPath = Join-Path $dst "meta.json"
|
||||
if (Test-Path $metaPath) {
|
||||
try {
|
||||
$meta = Get-Content $metaPath -Raw | ConvertFrom-Json
|
||||
$meta.boardId = $boardIdHint
|
||||
if ($Env -eq "cyd_35r" -and $meta.name -notmatch "3\.5") {
|
||||
$meta.name = ($meta.name -replace "\s*$","") + " (3.5\")"
|
||||
}
|
||||
$meta | ConvertTo-Json -Depth 8 | Set-Content -Encoding utf8 $metaPath
|
||||
} catch {
|
||||
Write-Host "meta.json update skipped: $_"
|
||||
}
|
||||
} elseif ($Env -eq "cyd_35r") {
|
||||
Write-Host "Note: add firmware/cyd_35r/meta.json with boardId=$boardIdHint for the web catalog"
|
||||
}
|
||||
|
||||
Write-Host "Exported -> $dst (env=$Env git=$git)"
|
||||
|
||||
@@ -1,16 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
// CYD ESP32-2432S028R
|
||||
// Board pins — 2.8" default; 3.5" when CYD_BOARD_3248S035 is set (env:cyd_35r)
|
||||
|
||||
#if defined(CYD_BOARD_3248S035)
|
||||
#define TFT_BL_PIN 27
|
||||
#define SCREEN_WIDTH 320
|
||||
#define SCREEN_HEIGHT 480
|
||||
#define UI_HOR_RES 480
|
||||
#define UI_VER_RES 320
|
||||
#else
|
||||
#define TFT_BL_PIN 21
|
||||
|
||||
// TF / microSD (VSPI;触摸用 SoftSPI,不抢总线)
|
||||
#define SD_MISO 19
|
||||
#define SD_MOSI 23
|
||||
#define SD_SCK 18
|
||||
#define SD_CS 5
|
||||
|
||||
#define SPEAKER_PIN 26
|
||||
#define SCREEN_WIDTH 240
|
||||
#define SCREEN_HEIGHT 320
|
||||
#define UI_HOR_RES 320
|
||||
#define UI_VER_RES 240
|
||||
#endif
|
||||
|
||||
#define CYD_TOUCH_IRQ 36
|
||||
#define CYD_TOUCH_MOSI 32
|
||||
@@ -18,7 +22,15 @@
|
||||
#define CYD_TOUCH_CLK 25
|
||||
#define CYD_TOUCH_CS 33
|
||||
|
||||
#define SCREEN_WIDTH 240
|
||||
#define SCREEN_HEIGHT 320
|
||||
#define UI_HOR_RES 320
|
||||
#define UI_VER_RES 240
|
||||
/* Map 320x240 design coordinates onto the active UI resolution (identity on 2.8"). */
|
||||
#define UX(x) ((int)(((long)(x) * (UI_HOR_RES)) / 320))
|
||||
#define UY(y) ((int)(((long)(y) * (UI_VER_RES)) / 240))
|
||||
#define UW(w) UX(w)
|
||||
#define UH(h) UY(h)
|
||||
|
||||
|
||||
#define SD_MISO 19
|
||||
#define SD_MOSI 23
|
||||
#define SD_SCK 18
|
||||
#define SD_CS 5
|
||||
#define SPEAKER_PIN 26
|
||||
|
||||
@@ -53,3 +53,20 @@ build_flags =
|
||||
-I${PROJECT_DIR}/include
|
||||
|
||||
extra_scripts = pre:copy_lv_conf.py
|
||||
|
||||
; Optional 3.5" CYD ESP32-3248S035 (ST7796 resistive). Default remains [env:cyd].
|
||||
; Build: pio run -e cyd_35r
|
||||
[env:cyd_35r]
|
||||
extends = env:cyd
|
||||
build_flags =
|
||||
${env:cyd.build_flags}
|
||||
-UILI9341_2_DRIVER
|
||||
-DST7796_DRIVER=1
|
||||
-UTFT_WIDTH
|
||||
-UTFT_HEIGHT
|
||||
-DTFT_WIDTH=320
|
||||
-DTFT_HEIGHT=480
|
||||
-UTFT_BL
|
||||
-DTFT_BL=27
|
||||
-DCYD_BOARD_3248S035=1
|
||||
|
||||
|
||||
36
src/ui.cpp
36
src/ui.cpp
@@ -45,7 +45,7 @@ static lv_obj_t *panel_custom;
|
||||
static lv_obj_t *lbl_custom_val;
|
||||
|
||||
static char g_timer_text[8] = "05:00";
|
||||
static char g_status_text[40] = "5m · READY";
|
||||
static char g_status_text[40] = "5m - READY";
|
||||
static char g_sound_text[28] = "Alarm";
|
||||
static char g_custom_buf[4] = "";
|
||||
static char g_custom_disp[16] = "min: _";
|
||||
@@ -98,7 +98,7 @@ static void refresh_timer_labels() {
|
||||
lv_obj_set_style_text_color(lbl_timer, lv_color_hex(color), 0);
|
||||
}
|
||||
|
||||
snprintf(g_status_text, sizeof(g_status_text), "%um · %s",
|
||||
snprintf(g_status_text, sizeof(g_status_text), "%um - %s",
|
||||
(unsigned)pomo_duration_minutes(), pomo_state_name());
|
||||
if (lbl_status) {
|
||||
lv_label_set_text(lbl_status, g_status_text);
|
||||
@@ -318,7 +318,7 @@ static lv_obj_t *make_small_btn(lv_obj_t *parent, const char *txt, int x, int y,
|
||||
static void build_custom_panel(lv_obj_t *scr) {
|
||||
panel_custom = lv_obj_create(scr);
|
||||
lv_obj_set_size(panel_custom, UI_HOR_RES, UI_VER_RES);
|
||||
lv_obj_set_pos(panel_custom, 0, 0);
|
||||
lv_obj_set_pos(panel_custom, UX(0), UY(0));
|
||||
lv_obj_set_style_bg_color(panel_custom, lv_color_hex(COL_BG), 0);
|
||||
lv_obj_set_style_bg_opa(panel_custom, LV_OPA_COVER, 0);
|
||||
lv_obj_set_style_border_width(panel_custom, 0, 0);
|
||||
@@ -331,13 +331,13 @@ static void build_custom_panel(lv_obj_t *scr) {
|
||||
lv_label_set_text(title, "Custom minutes");
|
||||
lv_obj_set_style_text_font(title, &lv_font_montserrat_16, 0);
|
||||
lv_obj_set_style_text_color(title, lv_color_hex(COL_ACCENT), 0);
|
||||
lv_obj_align(title, LV_ALIGN_TOP_MID, 0, 8);
|
||||
lv_obj_align(title, LV_ALIGN_TOP_MID, UX(0), UY(8));
|
||||
|
||||
lbl_custom_val = lv_label_create(panel_custom);
|
||||
lv_label_set_text(lbl_custom_val, "min: _");
|
||||
lv_obj_set_style_text_font(lbl_custom_val, &lv_font_montserrat_28, 0);
|
||||
lv_obj_set_style_text_color(lbl_custom_val, lv_color_hex(COL_INK), 0);
|
||||
lv_obj_align(lbl_custom_val, LV_ALIGN_TOP_MID, 0, 36);
|
||||
lv_obj_align(lbl_custom_val, LV_ALIGN_TOP_MID, UX(0), UY(36));
|
||||
|
||||
// Numpad 3x4
|
||||
static const char *keys[12] = {"1", "2", "3", "4", "5", "6",
|
||||
@@ -405,13 +405,13 @@ void ui_create() {
|
||||
lv_label_set_text(lbl_title, "POMO");
|
||||
lv_obj_set_style_text_font(lbl_title, &lv_font_montserrat_20, 0);
|
||||
lv_obj_set_style_text_color(lbl_title, lv_color_hex(COL_TOMATO), 0);
|
||||
lv_obj_set_pos(lbl_title, 12, 4);
|
||||
lv_obj_set_pos(lbl_title, UX(12), UY(4));
|
||||
|
||||
lbl_chip = lv_label_create(scr);
|
||||
lv_label_set_text(lbl_chip, "-");
|
||||
lv_obj_set_style_text_font(lbl_chip, &lv_font_montserrat_14, 0);
|
||||
lv_obj_set_style_text_color(lbl_chip, lv_color_hex(COL_MUTED), 0);
|
||||
lv_obj_align(lbl_chip, LV_ALIGN_TOP_RIGHT, -12, 8);
|
||||
lv_obj_align(lbl_chip, LV_ALIGN_TOP_RIGHT, UX(-12), UY(8));
|
||||
|
||||
make_small_btn(scr, "-", 12, 32, 40, 44, on_minus_clicked, nullptr);
|
||||
|
||||
@@ -419,16 +419,16 @@ void ui_create() {
|
||||
lv_label_set_text(lbl_timer, "05:00");
|
||||
lv_obj_set_style_text_font(lbl_timer, &lv_font_montserrat_28, 0);
|
||||
lv_obj_set_style_text_color(lbl_timer, lv_color_hex(COL_ACCENT), 0);
|
||||
lv_obj_align(lbl_timer, LV_ALIGN_TOP_MID, 0, 34);
|
||||
lv_obj_align(lbl_timer, LV_ALIGN_TOP_MID, UX(0), UY(34));
|
||||
|
||||
make_small_btn(scr, "+", UI_HOR_RES - 52, 32, 40, 44, on_plus_clicked,
|
||||
nullptr);
|
||||
|
||||
lbl_status = lv_label_create(scr);
|
||||
lv_label_set_text(lbl_status, "5m · READY");
|
||||
lv_label_set_text(lbl_status, "5m - READY");
|
||||
lv_obj_set_style_text_font(lbl_status, &lv_font_montserrat_14, 0);
|
||||
lv_obj_set_style_text_color(lbl_status, lv_color_hex(COL_MUTED), 0);
|
||||
lv_obj_align(lbl_status, LV_ALIGN_TOP_MID, 0, 74);
|
||||
lv_obj_align(lbl_status, LV_ALIGN_TOP_MID, UX(0), UY(74));
|
||||
|
||||
// Presets: 1 3 5 10 + Set
|
||||
const int gap = 6;
|
||||
@@ -447,12 +447,12 @@ void ui_create() {
|
||||
lv_label_set_text(snd_cap, "SOUND");
|
||||
lv_obj_set_style_text_font(snd_cap, &lv_font_montserrat_14, 0);
|
||||
lv_obj_set_style_text_color(snd_cap, lv_color_hex(COL_MUTED), 0);
|
||||
lv_obj_set_pos(snd_cap, 12, 134);
|
||||
lv_obj_set_pos(snd_cap, UX(12), UY(134));
|
||||
|
||||
make_small_btn(scr, "<", 68, 128, 32, 28, on_sound_prev, nullptr);
|
||||
|
||||
lv_obj_t *btn_snd = lv_button_create(scr);
|
||||
lv_obj_set_pos(btn_snd, 104, 128);
|
||||
lv_obj_set_pos(btn_snd, UX(104), UY(128));
|
||||
lv_obj_set_size(btn_snd, UI_HOR_RES - 104 - 48, 28);
|
||||
lv_obj_add_flag(btn_snd, LV_OBJ_FLAG_CLICKABLE);
|
||||
lv_obj_add_event_cb(btn_snd, on_sound_preview, LV_EVENT_CLICKED, nullptr);
|
||||
@@ -472,11 +472,11 @@ void ui_create() {
|
||||
lv_label_set_text(vol_cap, "VOL");
|
||||
lv_obj_set_style_text_font(vol_cap, &lv_font_montserrat_14, 0);
|
||||
lv_obj_set_style_text_color(vol_cap, lv_color_hex(COL_MUTED), 0);
|
||||
lv_obj_set_pos(vol_cap, 12, 164);
|
||||
lv_obj_set_pos(vol_cap, UX(12), UY(164));
|
||||
|
||||
slider_vol = lv_slider_create(scr);
|
||||
lv_obj_set_size(slider_vol, UI_HOR_RES - 12 - 56 - 44, 14);
|
||||
lv_obj_set_pos(slider_vol, 52, 164);
|
||||
lv_obj_set_pos(slider_vol, UX(52), UY(164));
|
||||
lv_slider_set_range(slider_vol, 0, 100);
|
||||
lv_slider_set_value(slider_vol, audio_get_volume(), LV_ANIM_OFF);
|
||||
lv_obj_set_style_bg_color(slider_vol, lv_color_hex(COL_LINE), LV_PART_MAIN);
|
||||
@@ -493,13 +493,13 @@ void ui_create() {
|
||||
lv_label_set_text(lbl_vol, "40%");
|
||||
lv_obj_set_style_text_font(lbl_vol, &lv_font_montserrat_14, 0);
|
||||
lv_obj_set_style_text_color(lbl_vol, lv_color_hex(COL_INK), 0);
|
||||
lv_obj_align(lbl_vol, LV_ALIGN_TOP_RIGHT, -12, 164);
|
||||
lv_obj_align(lbl_vol, LV_ALIGN_TOP_RIGHT, UX(-12), UY(164));
|
||||
|
||||
lbl_audio = lv_label_create(scr);
|
||||
lv_label_set_text(lbl_audio, "Speaker OFF");
|
||||
lv_obj_set_style_text_font(lbl_audio, &lv_font_montserrat_14, 0);
|
||||
lv_obj_set_style_text_color(lbl_audio, lv_color_hex(COL_MUTED), 0);
|
||||
lv_obj_set_pos(lbl_audio, 12, 182);
|
||||
lv_obj_set_pos(lbl_audio, UX(12), UY(182));
|
||||
|
||||
const int btn_y = 200;
|
||||
const int btn_h = 36;
|
||||
@@ -518,13 +518,13 @@ void ui_create() {
|
||||
lv_label_set_text(spk_cap, "SPK");
|
||||
lv_obj_set_style_text_font(spk_cap, &lv_font_montserrat_14, 0);
|
||||
lv_obj_set_style_text_color(spk_cap, lv_color_hex(COL_MUTED), 0);
|
||||
lv_obj_align(spk_cap, LV_ALIGN_LEFT_MID, 8, 0);
|
||||
lv_obj_align(spk_cap, LV_ALIGN_LEFT_MID, UX(8), UY(0));
|
||||
|
||||
lbl_speaker = lv_label_create(btn_speaker);
|
||||
lv_label_set_text(lbl_speaker, "OFF");
|
||||
lv_obj_set_style_text_font(lbl_speaker, &lv_font_montserrat_14, 0);
|
||||
lv_obj_set_style_text_color(lbl_speaker, lv_color_hex(COL_INK), 0);
|
||||
lv_obj_align(lbl_speaker, LV_ALIGN_RIGHT_MID, -8, 0);
|
||||
lv_obj_align(lbl_speaker, LV_ALIGN_RIGHT_MID, UX(-8), UY(0));
|
||||
|
||||
btn_start = lv_button_create(scr);
|
||||
lv_obj_set_pos(btn_start, 12 + btn_w + bgap, btn_y);
|
||||
|
||||
Reference in New Issue
Block a user