first commit

This commit is contained in:
matt committed 2026-08-03 20:31:28 -07:00
commit 0ef2017d18
28 files changed
+1882

No files matched your search

+135
View File
@@ -0,0 +1,135 @@
#include <stdio.h>
#include <string.h>
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "ambient_weather.h"
#include "app_config.h"
#include "backlight.h"
#include "display_rgb.h"
#include "i2c_bus.h"
#include "lvgl_port.h"
#include "touch_gt911.h"
#include "ui_manager.h"
#include "wifi_manager.h"
static const char *TAG = "main";
#define WEATHER_TASK_STACK 6144
#define WEATHER_TASK_PRIO 3
#define WEATHER_FIRST_DELAY_MS 3000
static void weather_update_task(void *arg)
{
weather_data_t weather;
char line[96];
vTaskDelay(pdMS_TO_TICKS(WEATHER_FIRST_DELAY_MS));
while (1) {
if (!wifi_is_connected()) {
ui_set_status("WiFi: reconnecting...");
vTaskDelay(pdMS_TO_TICKS(WEATHER_UPDATE_INTERVAL_MS));
continue;
}
/*
* Freeze rendering for the duration of the fetch. The TLS session,
* the LVGL redraw and the flush into the PSRAM framebuffer all
* compete with the LCD's own DMA out of that same PSRAM; letting them
* overlap is what produces visible artefacts. The panel keeps
* scanning the last completed frame, so the screen simply holds still.
*/
lvgl_port_pause();
const esp_err_t err = weather_update(&weather);
lvgl_port_resume();
if (err == ESP_OK) {
weather_get_string(&weather, line, sizeof(line));
ESP_LOGI(TAG, "Weather: %s", line);
char detail[64];
snprintf(detail, sizeof(detail), "%.0f%% humidity",
weather.has_humidity ? weather.humidity : 0.0f);
ui_update_weather((int16_t)(weather.temp_f + 0.5f),
weather.has_humidity ? detail : "Outdoor");
wifi_get_status(line, sizeof(line));
ui_set_status(line);
} else {
ESP_LOGW(TAG, "Weather update failed");
ui_set_status("Weather update failed");
}
vTaskDelay(pdMS_TO_TICKS(WEATHER_UPDATE_INTERVAL_MS));
}
}
void app_main(void)
{
ESP_LOGI(TAG, "Thermostat HMI -- CrowPanel 7.0\" ESP32-S3 (800x480)");
/*
* WiFi comes up FIRST, before the RGB panel exists.
*
* The panel's bounce-buffer ISR reads the framebuffer out of PSRAM, and
* PSRAM shares the cache with flash on the ESP32-S3. Bringing up NVS and
* the WiFi PHY writes calibration data to flash, which disables the cache
* and faults that ISR. Doing it here means every flash write is finished
* before the panel starts scanning.
*/
const esp_err_t wifi_err = wifi_init_sta();
if (wifi_err != ESP_OK) {
ESP_LOGE(TAG, "WiFi failed -- continuing, weather will be disabled");
}
/* LVGL core must exist before the display and touch drivers register
* themselves with it. */
ESP_ERROR_CHECK(lvgl_port_init());
/* Shared bus: STC8H1K28 board controller and GT911 both live on it. */
ESP_ERROR_CHECK(i2c_bus_init());
/* Must precede touch_init(): the STC8H1K28 holds the GT911 in reset
* until its init sequence runs. */
if (backlight_init() != ESP_OK) {
ESP_LOGE(TAG, "STC8H1K28 init failed -- backlight and touch will not work");
}
i2c_bus_scan(TAG);
ESP_ERROR_CHECK(display_init());
if (touch_init() != ESP_OK) {
/* A dead touch panel should not stop the display from working. */
ESP_LOGW(TAG, "Touch unavailable -- continuing without input");
}
ui_init();
ESP_ERROR_CHECK(lvgl_port_start());
/* First frame is rendered by now, so it is safe to light the panel. */
vTaskDelay(pdMS_TO_TICKS(100));
ESP_ERROR_CHECK(backlight_set(255));
if (wifi_err != ESP_OK) {
ui_set_status("WiFi: failed");
return;
}
char status[96];
wifi_get_status(status, sizeof(status));
ui_set_status(status);
if (weather_init() != ESP_OK) {
ui_set_status("Weather: no API credentials");
return;
}
xTaskCreate(weather_update_task, "weather", WEATHER_TASK_STACK, NULL,
WEATHER_TASK_PRIO, NULL);
ESP_LOGI(TAG, "System ready");
}