daily update, add lora files
Dieser Commit ist enthalten in:
1 Ursprung
0ab736b338
Commit
19345c3b4b
8 Dateien geändert
+412
-80
Keine Dateien entsprechen Ihrer Suche
+6
-4
@@ -155,7 +155,7 @@ void process_command(const char* cmd) {
|
||||
if (sscanf(cmd + 5, "%lu %63[^\r\n]", &targetLine, textBuffer) == 2) {
|
||||
if (targetLine <= 7) {
|
||||
if (oled_display != nullptr) {
|
||||
oled_display->printMessage(textBuffer, static_cast<uint8_t>(targetLine));
|
||||
oled_display->printMessage(static_cast<uint8_t>(targetLine), textBuffer);
|
||||
printf("Success: Dispatched text '%s' to OLED line %lu.\r\n", textBuffer, (unsigned long)targetLine);
|
||||
} else {
|
||||
printf("Error: DisplayController handle is uninitialized.\r\n");
|
||||
@@ -237,11 +237,13 @@ static void cli_worker_task(void *pvParameters) {
|
||||
printf("\b \b");
|
||||
fflush(stdout);
|
||||
}
|
||||
// Sanitize and append plain terminal symbols into processing context
|
||||
else if (data >= 32 && data <= 126 && buffer_index < (BUF_SIZE - 1)) {
|
||||
// Sanitize and append terminal symbols (including UTF-8 multi-byte characters like German Umlaute)
|
||||
else if (((data >= 32 && data <= 126) || data >= 128) && buffer_index < (BUF_SIZE - 1)) {
|
||||
line_buffer[buffer_index++] = static_cast<char>(data);
|
||||
printf("%c", data);
|
||||
fflush(stdout);
|
||||
//fflush(stdout);
|
||||
// direct write into uart buffer, used for utf-8
|
||||
//uart_write_bytes(CLI_UART_PORT, &data, 1);
|
||||
}
|
||||
}
|
||||
// Structural task yields preventing internal stack watchdog violations
|
||||
|
||||
+31
-18
@@ -112,18 +112,30 @@ static const uint8_t font_5x7[][5] = {
|
||||
{0x44, 0x28, 0x10, 0x28, 0x44}, // 120 x
|
||||
{0x0c, 0x50, 0x50, 0x50, 0x3c}, // 121 y
|
||||
{0x44, 0x64, 0x54, 0x4c, 0x44}, // 122 z
|
||||
{0x00, 0x08, 0x36, 0x41, 0x00}, // 123 \{
|
||||
{0x00, 0x08, 0x36, 0x41, 0x00}, // 123 {
|
||||
{0x00, 0x00, 0x77, 0x00, 0x00}, // 124 |
|
||||
{0x00, 0x41, 0x36, 0x08, 0x00}, // 125 \}
|
||||
{0x00, 0x41, 0x36, 0x08, 0x00}, // 125 }
|
||||
{0x08, 0x08, 0x2a, 0x1c, 0x08}, // 126 ~
|
||||
// German Umlaute mappings
|
||||
{0x7d, 0x11, 0x11, 0x11, 0x7d}, // 127 Ä
|
||||
{0x3c, 0x41, 0x41, 0x41, 0x3c}, // 128 Ö
|
||||
{0x3d, 0x40, 0x40, 0x40, 0x3d}, // 129 Ü
|
||||
{0x20, 0x55, 0x54, 0x54, 0x78}, // 130 ä
|
||||
{0x38, 0x54, 0x54, 0x54, 0x38}, // 131 ö
|
||||
{0x3c, 0x40, 0x40, 0x20, 0x7c}, // 132 ü
|
||||
{0x7f, 0x49, 0x49, 0x36, 0x20} // 133 ß
|
||||
// {0x7d, 0x11, 0x11, 0x11, 0x7d}, // 127 Ä
|
||||
// {0x3c, 0x41, 0x41, 0x41, 0x3c}, // 128 Ö
|
||||
// {0x3d, 0x40, 0x40, 0x40, 0x3d}, // 129 Ü
|
||||
// {0x20, 0x55, 0x54, 0x54, 0x78}, // 130 ä
|
||||
// {0x38, 0x54, 0x54, 0x54, 0x38}, // 131 ö
|
||||
// {0x3c, 0x40, 0x40, 0x20, 0x7c}, // 132 ü
|
||||
// {0x7f, 0x49, 0x49, 0x36, 0x20} // 133 ß
|
||||
// new German Umlaute mapping (5x7/5x8 Font Matrix)
|
||||
{0,0,0,0,0}, //127 not allowed
|
||||
{0x7d, 0x13, 0x13, 0x13, 0x7d}, // 128 Ä
|
||||
{0x3c, 0x43, 0x43, 0x43, 0x3c}, // 129 Ö
|
||||
{0x3d, 0x42, 0x42, 0x42, 0x3d}, // 130 Ü
|
||||
{0x20, 0x55, 0x54, 0x54, 0x78}, // 131 ä
|
||||
{0x38, 0x55, 0x55, 0x55, 0x38}, // 132 ö
|
||||
{0x3c, 0x42, 0x42, 0x22, 0x7c}, // 133 ü
|
||||
{0x7f, 0x49, 0x49, 0x36, 0x00}, // 134 ß (Letzte Spalte auf 0x00 bereinigt)
|
||||
// {0x3c, 0x42, 0x51, 0x4a, 0x34} // 134 © Copyright
|
||||
// {0x3c, 0x42, 0x4d, 0x4d, 0x32} // 135
|
||||
{0x3c, 0x42, 0x95, 0x95, 0x52}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -255,7 +267,7 @@ void DisplayController::startTask(uint32_t priority) {
|
||||
* @param text Pointer to a standard null-terminated sequence of tracking information.
|
||||
* @param line Selected hardware page index mapping from 0 to 7.
|
||||
*/
|
||||
void DisplayController::printMessage(const char* text, uint8_t line) {
|
||||
void DisplayController::printMessage(uint8_t line, const char* text) {
|
||||
if (m_msgQueue == nullptr || text == nullptr) return;
|
||||
|
||||
DisplayMessage msg = {};
|
||||
@@ -321,19 +333,20 @@ void DisplayController::run() {
|
||||
uint8_t c_secondary = static_cast<uint8_t>(incoming.content[i + 1]);
|
||||
i++; // Advance the pointer to consume the compound UTF-8 token pair
|
||||
|
||||
if (c_secondary == 0x84) { fontIndex = 95; validCharacter = true; } // Ä
|
||||
if (c_secondary == 0x96) { fontIndex = 96; validCharacter = true; } // Ö
|
||||
if (c_secondary == 0x9C) { fontIndex = 97; validCharacter = true; } // Ü
|
||||
if (c_secondary == 0xA4) { fontIndex = 98; validCharacter = true; } // ä
|
||||
if (c_secondary == 0xB6) { fontIndex = 99; validCharacter = true; } // ö
|
||||
if (c_secondary == 0xBC) { fontIndex = 100; validCharacter = true; } // ü
|
||||
if (c_secondary == 0x84) { fontIndex = 96; validCharacter = true; } // Ä
|
||||
if (c_secondary == 0x96) { fontIndex = 97; validCharacter = true; } // Ö
|
||||
if (c_secondary == 0x9C) { fontIndex = 98; validCharacter = true; } // Ü
|
||||
if (c_secondary == 0xA4) { fontIndex = 99; validCharacter = true; } // ä
|
||||
if (c_secondary == 0xB6) { fontIndex = 100; validCharacter = true; } // ö
|
||||
if (c_secondary == 0xBC) { fontIndex = 101; validCharacter = true; } // ü
|
||||
}
|
||||
else if (c_primary == 0xC2 && (i + 1) < textLength) {
|
||||
uint8_t c_secondary = static_cast<uint8_t>(incoming.content[i + 1]);
|
||||
i++;
|
||||
if (c_secondary == 0x9F) { fontIndex = 101; validCharacter = true; } // ß
|
||||
if (c_secondary == 0x9F) { fontIndex = 102; validCharacter = true; } // ß
|
||||
if (c_secondary == 0xA9) { fontIndex = 103; validCharacter = true; } // ©
|
||||
}
|
||||
else if (c_primary >= 32 && c_primary <= 126) {
|
||||
else if ((c_primary >= 32 && c_primary <= 126) || (c_primary > 127 && c_primary <= 135)) {
|
||||
fontIndex = static_cast<size_t>(c_primary - 32);
|
||||
validCharacter = true;
|
||||
}
|
||||
|
||||
@@ -31,16 +31,16 @@ public:
|
||||
|
||||
/**
|
||||
* @brief Thread-safe non-blocking method to print a message to the OLED display.
|
||||
* @param text Null-terminated string message (maximum 20 characters for simple lines).
|
||||
* @param line Destination line identifier index (0 to 7 for page addressing mode).
|
||||
* @param text Null-terminated string message (maximum 20 characters for simple lines).
|
||||
*/
|
||||
void printMessage(const char* text, uint8_t line);
|
||||
void printMessage(uint8_t line, const char* text);
|
||||
|
||||
private:
|
||||
// Internal structure mapping the safe asynchronous data pipeline
|
||||
struct DisplayMessage {
|
||||
char content[24];
|
||||
uint8_t targetLine;
|
||||
char content[24];
|
||||
};
|
||||
|
||||
i2c* m_bus;
|
||||
|
||||
@@ -0,0 +1,210 @@
|
||||
/**
|
||||
* @file lora.cpp
|
||||
* @brief Thread-safe asynchronous Semtech SX1276 LoRa transceiver driver implementation
|
||||
* @author OM Tom (OE3TKT)
|
||||
*
|
||||
* @license SPDX-License-Identifier: MIT
|
||||
* @copyright Copyright (c) 2026 OM Tom (OE3TKT)
|
||||
* For the full license terms, see the LICENSE file in the project root.
|
||||
*/
|
||||
|
||||
#include "lora.hpp"
|
||||
#include "esp_log.h"
|
||||
#include "config.hpp"
|
||||
#include "display.hpp"
|
||||
#include <cstring>
|
||||
|
||||
const char* LoraController::TAG = "LORA";
|
||||
|
||||
LoraController::LoraController() {
|
||||
m_isrSemaphore = xSemaphoreCreateBinary();
|
||||
if (m_isrSemaphore == nullptr) {
|
||||
ESP_LOGE(TAG, "Fatal: Failed to allocate LoRa ISR synchronization semaphore.");
|
||||
}
|
||||
}
|
||||
|
||||
LoraController::~LoraController() {
|
||||
if (m_spiHandle != nullptr) {
|
||||
spi_bus_remove_device(m_spiHandle);
|
||||
}
|
||||
if (m_isrSemaphore != nullptr) {
|
||||
vSemaphoreDelete(m_isrSemaphore);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t LoraController::readRegister(uint8_t address) {
|
||||
if (m_spiHandle == nullptr) return 0;
|
||||
|
||||
uint8_t txData[2] = { static_cast<uint8_t>(address & 0x7FU), 0x00U };
|
||||
uint8_t rxData[2] = { 0x00U, 0x00U };
|
||||
|
||||
spi_transaction_t trans = {};
|
||||
trans.length = 16;
|
||||
trans.tx_buffer = txData;
|
||||
trans.rx_buffer = rxData;
|
||||
|
||||
if (spi_device_transmit(m_spiHandle, &trans) != ESP_OK) {
|
||||
return 0;
|
||||
}
|
||||
return rxData[1];
|
||||
}
|
||||
|
||||
void LoraController::writeRegister(uint8_t address, uint8_t value) {
|
||||
if (m_spiHandle == nullptr) return;
|
||||
|
||||
uint8_t txData[2] = { static_cast<uint8_t>(address | 0x80U), value };
|
||||
|
||||
spi_transaction_t trans = {};
|
||||
trans.length = 16;
|
||||
trans.tx_buffer = txData;
|
||||
|
||||
spi_device_transmit(m_spiHandle, &trans);
|
||||
}
|
||||
|
||||
void IRAM_ATTR LoraController::gpioIsrHandler(void* arg) {
|
||||
auto* semaphore = static_cast<SemaphoreHandle_t>(arg);
|
||||
if (semaphore != nullptr) {
|
||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||
xSemaphoreGiveFromISR(semaphore, &xHigherPriorityTaskWoken);
|
||||
if (xHigherPriorityTaskWoken == pdTRUE) {
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t LoraController::initializeHardware() {
|
||||
esp_err_t err;
|
||||
|
||||
spi_device_interface_config_t devcfg = {};
|
||||
devcfg.clock_speed_hz = 9000000;
|
||||
devcfg.mode = 0;
|
||||
devcfg.spics_io_num = Config::LORA_CS_PIN;
|
||||
devcfg.queue_size = 7;
|
||||
|
||||
err = spi_bus_add_device(SPI3_HOST, &devcfg, &m_spiHandle);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to attach device handle to SPI3 host: %s", esp_err_to_name(err));
|
||||
return err;
|
||||
}
|
||||
|
||||
gpio_reset_pin(Config::LORA_RST_PIN);
|
||||
gpio_set_direction(Config::LORA_RST_PIN, GPIO_MODE_OUTPUT);
|
||||
|
||||
gpio_reset_pin(Config::LORA_IRQ_PIN);
|
||||
gpio_set_direction(Config::LORA_IRQ_PIN, GPIO_MODE_INPUT);
|
||||
gpio_set_pull_mode(Config::LORA_IRQ_PIN, GPIO_PULLDOWN_ONLY);
|
||||
|
||||
gpio_set_level(Config::LORA_RST_PIN, 0);
|
||||
vTaskDelay(pdMS_TO_TICKS(20));
|
||||
gpio_set_level(Config::LORA_RST_PIN, 1);
|
||||
vTaskDelay(pdMS_TO_TICKS(50));
|
||||
|
||||
uint8_t version = readRegister(0x42);
|
||||
if (version != 0x12) {
|
||||
ESP_LOGE(TAG, "Transceiver handshake failed! Invalid signature: 0x%02X", version);
|
||||
return ESP_ERR_INVALID_VERSION;
|
||||
}
|
||||
ESP_LOGI(TAG, "SX1276 Handshake success. Silicon version confirmed: 0x12");
|
||||
|
||||
err = gpio_install_isr_service(0);
|
||||
if (err != ESP_OK && err != ESP_ERR_INVALID_STATE) {
|
||||
return err;
|
||||
}
|
||||
|
||||
err = gpio_set_intr_type(Config::LORA_IRQ_PIN, GPIO_INTR_POSEDGE);
|
||||
err = gpio_isr_handler_add(Config::LORA_IRQ_PIN, LoraController::gpioIsrHandler, m_isrSemaphore);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
void LoraController::setModeReceiver() {
|
||||
writeRegister(0x01, 0x80U); // Sleep + LoRa Mode
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
|
||||
// Hardwired for 868.1 MHz fallback channel
|
||||
writeRegister(0x06, 0xD9U);
|
||||
writeRegister(0x07, 0x06U);
|
||||
writeRegister(0x08, 0x66U);
|
||||
|
||||
writeRegister(0x40, 0x00U); // DIO0 map onto RxDone
|
||||
writeRegister(0x01, 0x85U); // RXCONTINUOUS
|
||||
ESP_LOGI(TAG, "Radio base configuration applied. Listening on 868.1 MHz.");
|
||||
}
|
||||
|
||||
esp_err_t LoraController::transmitFrame(const uint8_t* buffer, uint8_t length) {
|
||||
if (m_spiHandle == nullptr || buffer == nullptr || length == 0) return ESP_ERR_INVALID_STATE;
|
||||
|
||||
ESP_LOGI(TAG, "Initiating transmission sequence: Sending %u bytes.", length);
|
||||
writeRegister(0x01, 0x81U); // STDBY Mode
|
||||
writeRegister(0x0D, 0x00U); // RegFifoTxBaseAddr
|
||||
writeRegister(0x09, 0x00U); // RegFifoAddrPtr
|
||||
|
||||
for (uint8_t i = 0; i < length; i++) {
|
||||
writeRegister(0x00, buffer[i]);
|
||||
}
|
||||
|
||||
writeRegister(0x22, length); // RegPayloadLength
|
||||
writeRegister(0x01, 0x83U); // RegOpMode: TX Mode Trigger
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void LoraController::taskTrampoline(void* pvParameters) {
|
||||
auto* instance = static_cast<LoraController*>(pvParameters);
|
||||
if (instance != nullptr) {
|
||||
instance->run();
|
||||
}
|
||||
vTaskDelete(nullptr);
|
||||
}
|
||||
|
||||
void LoraController::run() {
|
||||
if (initializeHardware() != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Critical: LoRa init failed. Thread aborted.");
|
||||
return;
|
||||
}
|
||||
|
||||
setModeReceiver();
|
||||
extern DisplayController* display; // Reference the global display singleton
|
||||
|
||||
while (true) {
|
||||
if (xSemaphoreTake(m_isrSemaphore, portMAX_DELAY) == pdTRUE) {
|
||||
uint32_t irqFlags = readRegister(0x12);
|
||||
writeRegister(0x12, static_cast<uint8_t>(irqFlags));
|
||||
|
||||
if ((irqFlags & 0x40U) != 0U) { // RxDone
|
||||
LoraPacket packet = {};
|
||||
packet.length = readRegister(0x13);
|
||||
|
||||
uint32_t currentFifoAddress = readRegister(0x10);
|
||||
writeRegister(0x09, static_cast<uint8_t>(currentFifoAddress));
|
||||
|
||||
for (uint8_t i = 0; i < packet.length; i++) {
|
||||
packet.payload[i] = readRegister(0x00);
|
||||
}
|
||||
|
||||
packet.rssi = static_cast<int8_t>(static_cast<int>(readRegister(0x1A)) - 157);
|
||||
packet.snr = static_cast<int8_t>(static_cast<int>(readRegister(0x1B)) / 4);
|
||||
|
||||
ESP_LOGI(TAG, "Incoming frame packet received! Size: %u bytes, RSSI: %d dBm, SNR: %d dB",
|
||||
packet.length, packet.rssi, packet.snr);
|
||||
|
||||
// FIXED: Uses the new parameter order (line first, text second)
|
||||
if (display != nullptr) {
|
||||
display->printMessage(1, "LoRa Msg Received");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LoraController::startTask(uint32_t priority) {
|
||||
xTaskCreatePinnedToCore(
|
||||
LoraController::taskTrampoline,
|
||||
"LORA_EngineTask",
|
||||
4096,
|
||||
this,
|
||||
priority,
|
||||
&m_taskHandle,
|
||||
1
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/**
|
||||
* @file lora.hpp
|
||||
* @brief Thread-safe asynchronous Semtech SX1276 LoRa transceiver driver for FoxMesh
|
||||
* @author OM Tom (OE3TKT)
|
||||
*
|
||||
* @license SPDX-License-Identifier: MIT
|
||||
* @copyright Copyright (c) 2026 OM Tom (OE3TKT)
|
||||
* For the full license terms, see the LICENSE file in the project root.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/spi_master.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
class LoraController {
|
||||
public:
|
||||
/**
|
||||
* @brief Structure defining the localized packet buffer space.
|
||||
*/
|
||||
struct LoraPacket {
|
||||
uint8_t payload[256]; ///< Raw data payload frame matching max SX1276 FIFO allocation
|
||||
uint8_t length; ///< Total number of active bytes captured inside the frame
|
||||
int8_t rssi; ///< Received Signal Strength Indicator metric in dBm
|
||||
int8_t snr; ///< Signal-to-Noise Ratio metric in dB
|
||||
};
|
||||
|
||||
explicit LoraController();
|
||||
virtual ~LoraController();
|
||||
|
||||
// Disallow copying to prevent duplicate hardware resource assignment
|
||||
LoraController(const LoraController&) = delete;
|
||||
LoraController& operator=(const LoraController&) = delete;
|
||||
|
||||
/**
|
||||
* @brief Configures peripheral resources and registers the background worker thread on Core 1.
|
||||
* @param priority Scheduler task priority level execution metric.
|
||||
*/
|
||||
void startTask(uint32_t priority = 6);
|
||||
|
||||
/**
|
||||
* @brief Transmits a raw data frame onto the physical radio frequency layer.
|
||||
* @param buffer Pointer to the source byte array holding the packet context.
|
||||
* @param length Total number of bytes to dispatch over the air interface.
|
||||
* @return esp_err_t status indicating transaction success.
|
||||
*/
|
||||
esp_err_t transmitFrame(const uint8_t* buffer, uint8_t length);
|
||||
|
||||
private:
|
||||
spi_device_handle_t m_spiHandle = nullptr;
|
||||
TaskHandle_t m_taskHandle = nullptr;
|
||||
SemaphoreHandle_t m_isrSemaphore = nullptr;
|
||||
|
||||
static const char* TAG;
|
||||
|
||||
static void taskTrampoline(void* pvParameters);
|
||||
static void IRAM_ATTR gpioIsrHandler(void* arg);
|
||||
|
||||
void run();
|
||||
uint8_t readRegister(uint8_t address);
|
||||
void writeRegister(uint8_t address, uint8_t value);
|
||||
|
||||
esp_err_t initializeHardware();
|
||||
void setModeReceiver();
|
||||
};
|
||||
+34
-9
@@ -2,7 +2,7 @@
|
||||
* @file main.cpp
|
||||
* @brief Main application entry point for the FoxMesh tracking node
|
||||
* @author OM Tom (OE3TKT)
|
||||
*
|
||||
*
|
||||
* @license SPDX-License-Identifier: MIT
|
||||
* @copyright Copyright (c) 2026 OM Tom (OE3TKT)
|
||||
* For the full license terms, see the LICENSE file in the project root.
|
||||
@@ -20,19 +20,31 @@
|
||||
#include "i2c.hpp"
|
||||
#include "display.hpp" // FIXED: Added missing header for DisplayController
|
||||
|
||||
/**
|
||||
* @brief Global log categorization tag context for the main application loader.
|
||||
*/
|
||||
static const char *TAG = "MAIN";
|
||||
|
||||
// Global pointer to the thread-safe hardware abstraction instances
|
||||
/**
|
||||
* @brief Global pointer tracking the synchronized thread-safe I2C master bus instance.
|
||||
*/
|
||||
i2c* i2c_bus = nullptr;
|
||||
|
||||
/**
|
||||
* @brief Global pointer tracking the asynchronous isolated OLED render controller instance.
|
||||
*/
|
||||
DisplayController* display = nullptr;
|
||||
|
||||
// Global singleton instances for hardware abstraction layers
|
||||
/**
|
||||
* @brief Static singleton instance governing hardware status LED blink patterns.
|
||||
*/
|
||||
static LedController led(Config::LED_GPIO_PIN);
|
||||
|
||||
/**
|
||||
* @brief Initializes the physical SPI peripheral for the Semtech SX1276 transceiver.
|
||||
*
|
||||
* Configures VSPI (SPI3_HOST) using strict compile-time configurations from config.hpp.
|
||||
*
|
||||
* Configures the VSPI (SPI3_HOST) back-end utilizing strict compile-time layouts
|
||||
* mapped inside config.hpp and configures automatic DMA channel routing.
|
||||
*/
|
||||
void init_lora_spi(void) {
|
||||
esp_err_t ret;
|
||||
@@ -56,6 +68,12 @@ void init_lora_spi(void) {
|
||||
|
||||
// Global application anchor marked as extern "C" for the native ESP-IDF bootloader
|
||||
extern "C" {
|
||||
/**
|
||||
* @brief System core entry point executing synchronous initialization loops.
|
||||
*
|
||||
* Spawns the decoupled system worker threads, establishes thread-safe hardware
|
||||
* bus routing layers, and boots up the interactive terminal environment on Core 0.
|
||||
*/
|
||||
void app_main(void) {
|
||||
// Output system banner configuration parameters on boot
|
||||
ESP_LOGI(TAG, "=================================================");
|
||||
@@ -73,7 +91,9 @@ extern "C" {
|
||||
|
||||
// Instantiate and activate the isolated background render worker on Core 0
|
||||
display = new DisplayController(i2c_bus);
|
||||
display->startTask();
|
||||
if (display != nullptr) {
|
||||
display->startTask();
|
||||
}
|
||||
|
||||
// Pass the bus instance dependency to the interactive terminal layer
|
||||
cli_init(i2c_bus, &led, display);
|
||||
@@ -85,15 +105,20 @@ extern "C" {
|
||||
start_cli_task();
|
||||
|
||||
// Trigger synchronous welcome splash screen frame
|
||||
display->printMessage("FoxMesh Ready", 0);
|
||||
|
||||
if (display != nullptr) {
|
||||
char msg[32];
|
||||
//display->printMessage(0, "FoxMesh " Config::PROJECT_VERSION " \x86" "OE3TKT");
|
||||
snprintf(msg, sizeof(msg), "FoxMesh %s OE3TKT", Config::PROJECT_VERSION);
|
||||
display->printMessage(1, msg);
|
||||
display->printMessage(2, "Bärbel frühstückt ©");
|
||||
}
|
||||
// Main system watchdog and status monitor loop
|
||||
while (true) {
|
||||
ESP_LOGI(TAG, "[%s v%s] Operational. Free Heap: %lu bytes",
|
||||
Config::PROJECT_TITLE,
|
||||
Config::PROJECT_VERSION,
|
||||
(unsigned long)esp_get_free_heap_size());
|
||||
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(5000));
|
||||
}
|
||||
}
|
||||
|
||||
In neuem Issue referenzieren
Einen Benutzer sperren