Files

191 lines
5.8 KiB
C

/**
* V2X-Display Driver - ST7735 SPI (T-Dongle-C5)
*
* Verwendet den ESP-IDF nativen ST7735 Treiber (aus LilyGO T-Dongle-C5 Demo)
*
* Display: ST7735, 80x160 Pixel
* GPIO: CS=10, DC=3, RST=1, BL=0, MOSI=2, SCK=6
*
* Rotation: 3 (invertiert 90°)
* Offset: x=26, y=1 (nicht-Zentriert)
*/
#include "esp_log.h"
#include "v2x_display.h"
#include "st7735.h"
#include "driver/gpio.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_timer.h"
#include <stdio.h>
static const char *TAG = "v2x-display";
static void *s_dev = NULL;
static bool s_initialized = false;
/* Globale Variablen */
bool g_disp_initialized = false;
void *g_disp_panel = NULL;
esp_err_t v2x_display_init(void)
{
esp_err_t ret;
ESP_LOGI(TAG, "Initialisiere ST7735 Display via eigenem ESP-IDF Treiber...");
ESP_LOGI(TAG, "GPIO: CS=%d, DC=%d, RST=%d, BL=%d, MOSI=%d, SCK=%d",
DISP_GPIO_CS, DISP_GPIO_DC, DISP_GPIO_RST, DISP_GPIO_BL,
DISP_GPIO_SDA, DISP_GPIO_SCK);
/* GPIO-Konfiguration mit eigenem Treiber */
st7735_gpio_config_t gpio_cfg = {
.cs_gpio = DISP_GPIO_CS,
.dc_gpio = DISP_GPIO_DC,
.rst_gpio = DISP_GPIO_RST,
.bl_gpio = DISP_GPIO_BL,
.mosi_gpio = DISP_GPIO_SDA,
.sck_gpio = DISP_GPIO_SCK,
};
/* ST7735 initialisieren - Rotation 3 (invertiert, 90° gedreht) */
ret = st7735_init(&gpio_cfg, 3, (void **)&s_dev);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "ST7735 Init fehlgeschlagen: %s", esp_err_to_name(ret));
return ret;
}
/* Display ausschalten (Backlight an, Panel aus) */
st7735_display_off((void *)s_dev);
/* Backlight an (aktiv LOW bei LilyGO) */
gpio_set_level(DISP_GPIO_BL, 0);
vTaskDelay(pdMS_TO_TICKS(50));
/* Display einschalten */
st7735_display_on((void *)s_dev);
/* Vollbild weiß */
st7735_fill_screen((void *)s_dev, DISP_COLOR_WHITE);
s_initialized = true;
g_disp_initialized = true;
g_disp_panel = (void *)s_dev;
ESP_LOGI(TAG, "ST7735 Display bereit (80x160, SPI, Rot=3)");
return ESP_OK;
}
esp_err_t v2x_display_clear(uint16_t color)
{
if (!s_initialized || !s_dev) return ESP_ERR_INVALID_STATE;
st7735_fill_screen((void *)s_dev, color);
return ESP_OK;
}
esp_err_t v2x_display_rect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color, bool filled)
{
if (!s_initialized || !s_dev) return ESP_ERR_INVALID_STATE;
if (filled) {
/* Gefülltes Rechteck zeichnen */
for (int16_t py = 0; py < h; py++) {
for (int16_t px = 0; px < w; px++) {
st7735_draw_pixel((void *)s_dev, x + px, y + py, color);
}
}
} else {
/* Nur Rahmen zeichnen */
for (int16_t px = 0; px < w; px++) {
st7735_draw_pixel((void *)s_dev, x + px, y, color);
st7735_draw_pixel((void *)s_dev, x + px, y + h - 1, color);
}
for (int16_t py = 0; py < h; py++) {
st7735_draw_pixel((void *)s_dev, x, y + py, color);
st7735_draw_pixel((void *)s_dev, x + w - 1, y + py, color);
}
}
return ESP_OK;
}
esp_err_t v2x_display_line(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color)
{
if (!s_initialized || !s_dev) return ESP_ERR_INVALID_STATE;
return st7735_draw_line((void *)s_dev, x0, y0, x1, y1, color);
}
esp_err_t v2x_display_off(void)
{
if (!s_initialized || !s_dev) return ESP_ERR_INVALID_STATE;
st7735_display_off((void *)s_dev);
gpio_set_level(DISP_GPIO_BL, 1); /* Backlight aus */
return ESP_OK;
}
esp_err_t v2x_display_progress_bar(int16_t x, int16_t y, int16_t w, int16_t h, float progress,
uint16_t fg_color, uint16_t bg_color)
{
progress = (progress < 0.0f) ? 0.0f : (progress > 1.0f) ? 1.0f : progress;
for (int16_t py = 0; py < h; py++) {
for (int16_t px = 0; px < w; px++) {
st7735_draw_pixel((void *)s_dev, x + px, y + py, bg_color);
}
}
int16_t fw = (int16_t)(w * progress);
if (fw > 0) {
for (int16_t py = 0; py < h; py++) {
for (int16_t px = 0; px < fw; px++) {
st7735_draw_pixel((void *)s_dev, x + px, y + py, fg_color);
}
}
}
for (int i = 0; i < w; i++) {
st7735_draw_pixel((void *)s_dev, x + i, y, DISP_COLOR_BLACK);
st7735_draw_pixel((void *)s_dev, x + i, y + h - 1, DISP_COLOR_BLACK);
}
for (int i = 0; i < h; i++) {
st7735_draw_pixel((void *)s_dev, x, y + i, DISP_COLOR_BLACK);
st7735_draw_pixel((void *)s_dev, x + w - 1, y + i, DISP_COLOR_BLACK);
}
return ESP_OK;
}
esp_err_t v2x_display_rssi_gauge(int8_t rssi)
{
if (rssi < -100) rssi = -100;
if (rssi > -20) rssi = -20;
float pct = (float)(rssi + 100) / 80.0f;
uint16_t color = DISP_COLOR_RED;
if (pct > 0.6f) color = DISP_COLOR_GREEN;
else if (pct > 0.3f) color = DISP_COLOR_YELLOW;
return v2x_display_progress_bar(0, 0, DISP_W, 3, pct, color, DISP_COLOR_BLACK);
}
esp_err_t v2x_display_render_frame_line(int16_t x, int16_t y, const disp_frame_info_t *info,
uint16_t bg_color)
{
for (int16_t py = 0; py < 12; py++) {
for (int16_t px = 0; px < DISP_W; px++) {
st7735_draw_pixel((void *)s_dev, x + px, y + py, bg_color);
}
}
if (info->rssi != 0) {
int8_t r = info->rssi;
if (r < -100) r = -100;
if (r > -20) r = -20;
float pct = (float)(r + 100) / 80.0f;
uint16_t bar_color = DISP_COLOR_RED;
if (pct > 0.6f) bar_color = DISP_COLOR_GREEN;
else if (pct > 0.3f) bar_color = DISP_COLOR_YELLOW;
for (int16_t py = 1; py < 11; py++) {
for (int16_t px = 0; px < 5; px++) {
st7735_draw_pixel((void *)s_dev, x + px, y + py, bar_color);
}
}
}
(void)x; (void)y;
return ESP_OK;
}