From a9f3b8ef3b60a394a3362bbf702ccf507a07cc26 Mon Sep 17 00:00:00 2001 From: liquidraver <504870+liquidraver@users.noreply.github.com> Date: Tue, 19 May 2026 07:00:03 +0200 Subject: [PATCH] cleanup t114, add build --- build.sh | 1 + zephcore/boards/example_board/README.md | 3 + .../heltec_t114/heltec_t114_nrf52840.dts | 10 +- zephcore/boards/supported_boards.md | 3 + zephcore/helpers/ui/display_mono_tft.c | 148 +++++++++--------- 5 files changed, 83 insertions(+), 82 deletions(-) diff --git a/build.sh b/build.sh index 6f1163c..c7ba234 100644 --- a/build.sh +++ b/build.sh @@ -19,6 +19,7 @@ nRF_boards=( xiao_nrf52840 lilygo_techo promicro_sx1262 + heltec_t114 ) ESP32_boards=( diff --git a/zephcore/boards/example_board/README.md b/zephcore/boards/example_board/README.md index f5f2844..dc6768b 100644 --- a/zephcore/boards/example_board/README.md +++ b/zephcore/boards/example_board/README.md @@ -22,6 +22,9 @@ Supported Boards | RAK WisMesh Tag | `west build -b rak_wismesh_tag zephcore` | UF2 drag-drop or `west flash` | | Ikoka Nano 30dBm | `west build -b ikoka_nano_30dbm zephcore` | UF2 drag-drop | | LilyGo T-Echo | `west build -b lilygo_techo zephcore` | UF2 drag-drop or `west flash` | +| Heltec T114 | `west build -b heltec_t114 zephcore` | UF2 drag-drop or `west flash` | + +**Heltec T114 screenless:** append `boards/nrf52840/heltec_t114/no_display.conf` to `EXTRA_CONF_FILE` for units without the TFT module. UF2 flash: Double-tap reset button, drag `build/zephyr/zephyr.uf2` to the USB drive. SWD flash: `west flash` (requires J-Link, pyocd, or nrfjprog connected). diff --git a/zephcore/boards/nrf52840/heltec_t114/heltec_t114_nrf52840.dts b/zephcore/boards/nrf52840/heltec_t114/heltec_t114_nrf52840.dts index 0a38dd6..8a44036 100644 --- a/zephcore/boards/nrf52840/heltec_t114/heltec_t114_nrf52840.dts +++ b/zephcore/boards/nrf52840/heltec_t114/heltec_t114_nrf52840.dts @@ -8,18 +8,11 @@ /dts-v1/; #include -#include #include #include #include #include "heltec_t114_nrf52840-pinctrl.dtsi" -/* Delete default partitions from nrf52840_partition.dtsi */ -/delete-node/ &boot_partition; -/delete-node/ &slot0_partition; -/delete-node/ &slot1_partition; -/delete-node/ &storage_partition; - / { model = "Heltec T114"; compatible = "heltec,t114"; @@ -217,7 +210,8 @@ #address-cells = <1>; #size-cells = <0>; - /* Battery voltage on P0.04 (AIN2) — 4.9:1 divider, 3.0V ref in Arduino */ + /* Battery voltage on P0.04 (AIN2) — 4.9:1 divider. + * ADC_GAIN_1_6 + ADC_REF_INTERNAL (0.6V) => 3600 mV full-scale. */ channel@2 { reg = <2>; zephyr,gain = "ADC_GAIN_1_6"; diff --git a/zephcore/boards/supported_boards.md b/zephcore/boards/supported_boards.md index 8f7d63a..b931cb8 100644 --- a/zephcore/boards/supported_boards.md +++ b/zephcore/boards/supported_boards.md @@ -18,9 +18,12 @@ sensecap_solar xiao_nrf52840 lilygo_techo promicro_sx1262 +heltec_t114 ``` > **RAK WisMesh Pocket** (WisBlock pocket): use `-b rak4631` — same board string and firmware as **RAK4631**. +> +> **Heltec T114** screenless build: append `boards/nrf52840/heltec_t114/no_display.conf` to `EXTRA_CONF_FILE` for units without the TFT module. ## ESP32 diff --git a/zephcore/helpers/ui/display_mono_tft.c b/zephcore/helpers/ui/display_mono_tft.c index 81f8e93..c700489 100644 --- a/zephcore/helpers/ui/display_mono_tft.c +++ b/zephcore/helpers/ui/display_mono_tft.c @@ -1,7 +1,7 @@ /* * ZephCore - Monochrome wrapper for RGB TFT displays * Copyright (c) 2026 ZephCore - * + * * SPDX-License-Identifier: Apache-2.0 * * Reports PIXEL_FORMAT_MONO01 to CFB so the framebuffer is ~4 KB @@ -24,126 +24,126 @@ LOG_MODULE_REGISTER(display_mono_tft); struct mono_tft_config { - const struct device *tft; - uint16_t width; - uint16_t height; + const struct device *tft; + uint16_t width; + uint16_t height; }; /* Hardcoded to instance 0. Only one display wrapper per board is supported. */ #define MONO_TFT_MAX_WIDTH DT_INST_PROP(0, width) struct mono_tft_data { - /* Static allocation avoids ~480 bytes of stack pressure per display_write() call. */ - uint16_t line_buf[MONO_TFT_MAX_WIDTH]; + /* Static allocation avoids ~480 bytes of stack pressure per display_write() call. */ + uint16_t line_buf[MONO_TFT_MAX_WIDTH]; }; static int mono_tft_blanking_on(const struct device *dev) { - const struct mono_tft_config *cfg = dev->config; + const struct mono_tft_config *cfg = dev->config; - return display_blanking_on(cfg->tft); + return display_blanking_on(cfg->tft); } static int mono_tft_blanking_off(const struct device *dev) { - const struct mono_tft_config *cfg = dev->config; + const struct mono_tft_config *cfg = dev->config; - return display_blanking_off(cfg->tft); + return display_blanking_off(cfg->tft); } static int mono_tft_write( - const struct device *dev, - const uint16_t x_start, const uint16_t y_start, - const struct display_buffer_descriptor *desc, - const void *buf + const struct device *dev, + const uint16_t x_start, const uint16_t y_start, + const struct display_buffer_descriptor *desc, + const void *buf ){ - const struct mono_tft_config *cfg = dev->config; - struct mono_tft_data *data = dev->data; - const uint8_t *mono_buf = buf; - /* Pitch is in pixels. Convert to bytes by rounding up to the nearest boundary. */ - uint16_t pitch_bytes = (desc->pitch + 7U) / 8U; + const struct mono_tft_config *cfg = dev->config; + struct mono_tft_data *data = dev->data; + const uint8_t *mono_buf = buf; + /* Pitch is in pixels. Convert to bytes by rounding up to the nearest boundary. */ + uint16_t pitch_bytes = (desc->pitch + 7U) / 8U; - const struct display_buffer_descriptor line_desc = { - .buf_size = (uint32_t)desc->width * 2U, - .width = desc->width, - .height = 1U, - .pitch = desc->width, - }; + const struct display_buffer_descriptor line_desc = { + .buf_size = (uint32_t)desc->width * 2U, + .width = desc->width, + .height = 1U, + .pitch = desc->width, + }; - int err = 0; + int err = 0; - for (uint16_t row = 0; row < desc->height; row++) { - const uint8_t *mono_row = mono_buf + (size_t)row * pitch_bytes; + for (uint16_t row = 0; row < desc->height; row++) { + const uint8_t *mono_row = mono_buf + (size_t)row * pitch_bytes; - for (uint16_t col = 0; col < desc->width; col++) { - /* CFB MONO01 is row major and LSB first. Pixel at col uses bit (col%8) of byte (col/8). */ - bool pixel_on = (mono_row[col / 8U] >> (col & 7U)) & 1U; - /* ST7789V expects RGB565 in big endian byte order over SPI. */ - data->line_buf[col] = pixel_on ? sys_cpu_to_be16(0xFFFFU) : 0x0000U; - } + for (uint16_t col = 0; col < desc->width; col++) { + /* CFB MONO01 is row major and LSB first. Pixel at col uses bit (col%8) of byte (col/8). */ + bool pixel_on = (mono_row[col / 8U] >> (col & 7U)) & 1U; + /* ST7789V expects RGB565 in big endian byte order over SPI. */ + data->line_buf[col] = sys_cpu_to_be16(pixel_on ? 0xFFFFU : 0x0000U); + } - err = display_write(cfg->tft, x_start, y_start + row, &line_desc, data->line_buf); - if (err) { - return err; - } - } - return 0; + err = display_write(cfg->tft, x_start, y_start + row, &line_desc, data->line_buf); + if (err) { + return err; + } + } + return 0; } static void mono_tft_get_capabilities( - const struct device *dev, - struct display_capabilities *caps + const struct device *dev, + struct display_capabilities *caps ){ - const struct mono_tft_config *cfg = dev->config; + const struct mono_tft_config *cfg = dev->config; - memset(caps, 0, sizeof(*caps)); - caps->x_resolution = cfg->width; - caps->y_resolution = cfg->height; - caps->supported_pixel_formats = PIXEL_FORMAT_MONO01; - caps->current_pixel_format = PIXEL_FORMAT_MONO01; + memset(caps, 0, sizeof(*caps)); + caps->x_resolution = cfg->width; + caps->y_resolution = cfg->height; + caps->supported_pixel_formats = PIXEL_FORMAT_MONO01; + caps->current_pixel_format = PIXEL_FORMAT_MONO01; } static int mono_tft_set_pixel_format( - const struct device *dev, - const enum display_pixel_format pixel_format + const struct device *dev, + const enum display_pixel_format pixel_format ){ - ARG_UNUSED(dev); - return (pixel_format == PIXEL_FORMAT_MONO01) ? 0 : -ENOTSUP; + ARG_UNUSED(dev); + return (pixel_format == PIXEL_FORMAT_MONO01) ? 0 : -ENOTSUP; } static int mono_tft_init(const struct device *dev) { - const struct mono_tft_config *cfg = dev->config; + const struct mono_tft_config *cfg = dev->config; - if (!device_is_ready(cfg->tft)) { - LOG_ERR("underlying TFT device not ready"); - return -ENODEV; - } - return 0; + if (!device_is_ready(cfg->tft)) { + LOG_ERR("underlying TFT device not ready"); + return -ENODEV; + } + return 0; } static const struct display_driver_api mono_tft_api = { - .blanking_on = mono_tft_blanking_on, - .blanking_off = mono_tft_blanking_off, - .write = mono_tft_write, - .get_capabilities = mono_tft_get_capabilities, - .set_pixel_format = mono_tft_set_pixel_format, + .blanking_on = mono_tft_blanking_on, + .blanking_off = mono_tft_blanking_off, + .write = mono_tft_write, + .get_capabilities = mono_tft_get_capabilities, + .set_pixel_format = mono_tft_set_pixel_format, }; static struct mono_tft_data mono_tft_data; static const struct mono_tft_config mono_tft_config = { - .tft = DEVICE_DT_GET(DT_INST_PHANDLE(0, tft_dev)), - .width = DT_INST_PROP(0, width), - .height = DT_INST_PROP(0, height), + .tft = DEVICE_DT_GET(DT_INST_PHANDLE(0, tft_dev)), + .width = DT_INST_PROP(0, width), + .height = DT_INST_PROP(0, height), }; DEVICE_DT_INST_DEFINE( - 0, - mono_tft_init, - NULL, - &mono_tft_data, - &mono_tft_config, - POST_KERNEL, - CONFIG_DISPLAY_INIT_PRIORITY, - &mono_tft_api + 0, + mono_tft_init, + NULL, + &mono_tft_data, + &mono_tft_config, + POST_KERNEL, + CONFIG_DISPLAY_INIT_PRIORITY, + &mono_tft_api );