Dieser Commit ist enthalten in:
1 Ursprung
04a13bc154
Commit
63b77838a2
4 Dateien geändert
+161
-13
Keine Dateien entsprechen Ihrer Suche
+56
-2
@@ -18,11 +18,13 @@
|
|||||||
#include "driver/uart.h"
|
#include "driver/uart.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "config.hpp"
|
#include "config.hpp"
|
||||||
|
#include "lora.hpp"
|
||||||
|
|
||||||
static const char* TAG = "CLI";
|
static const char* TAG = "CLI";
|
||||||
static i2c* i2c_bus = nullptr;
|
static i2c* i2c_bus = nullptr;
|
||||||
static LedController* led_system = nullptr;
|
static LedController* led_system = nullptr;
|
||||||
static DisplayController* oled_display = nullptr;
|
static DisplayController* oled_display = nullptr;
|
||||||
|
static LoraController* lora_system = nullptr;
|
||||||
|
|
||||||
#define CLI_UART_PORT UART_NUM_0
|
#define CLI_UART_PORT UART_NUM_0
|
||||||
#define BUF_SIZE 1024
|
#define BUF_SIZE 1024
|
||||||
@@ -49,6 +51,10 @@ void cli_init(i2c* bus_pointer, LedController* led_pointer, DisplayController* d
|
|||||||
oled_display = display_pointer;
|
oled_display = display_pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void cli_init_lora(LoraController* lora_pointer) {
|
||||||
|
lora_system = lora_pointer;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* @brief Software timer callback task executed once terminal interaction has gone stale.
|
* @brief Software timer callback task executed once terminal interaction has gone stale.
|
||||||
* @param xTimer Handle tracking the specific FreeRTOS timing token instance.
|
* @param xTimer Handle tracking the specific FreeRTOS timing token instance.
|
||||||
@@ -82,6 +88,8 @@ void process_command(const char* cmd) {
|
|||||||
printf(" mute <sec> - Set custom logging timeout (Current: %lus)\r\n", (unsigned long)current_mute_time_sec);
|
printf(" mute <sec> - Set custom logging timeout (Current: %lus)\r\n", (unsigned long)current_mute_time_sec);
|
||||||
printf(" blink <int> <puls> - Set LED profile in ms (e.g. blink 1000 50)\r\n");
|
printf(" blink <int> <puls> - Set LED profile in ms (e.g. blink 1000 50)\r\n");
|
||||||
printf(" oled <line> <txt> - Print text to OLED line 0-7 (e.g. oled 0 Test)\r\n");
|
printf(" oled <line> <txt> - Print text to OLED line 0-7 (e.g. oled 0 Test)\r\n");
|
||||||
|
printf(" freq <hz> - Set dynamic radio frequency (433 / 868 MHz bounds)\r\n");
|
||||||
|
printf(" bw <62|125|250|500>- Set dynamic LoRa bandwidth in kHz\r\n");
|
||||||
printf(" i2c - Scan the configured I2C bus infrastructure\r\n");
|
printf(" i2c - Scan the configured I2C bus infrastructure\r\n");
|
||||||
}
|
}
|
||||||
else if (strcmp(cmd, "version") == 0) {
|
else if (strcmp(cmd, "version") == 0) {
|
||||||
@@ -107,8 +115,7 @@ void process_command(const char* cmd) {
|
|||||||
xTimerStop(silence_timer, pdMS_TO_TICKS(10));
|
xTimerStop(silence_timer, pdMS_TO_TICKS(10));
|
||||||
}
|
}
|
||||||
printf("Success: Infinite mute activated. Debug logs are permanently suppressed.\r\n");
|
printf("Success: Infinite mute activated. Debug logs are permanently suppressed.\r\n");
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
// DYNAMIC TIMEOUT: Extracted multiplication step to decouple constant values from structural macros
|
// DYNAMIC TIMEOUT: Extracted multiplication step to decouple constant values from structural macros
|
||||||
uint32_t timeout_ms = current_mute_time_sec * 1000;
|
uint32_t timeout_ms = current_mute_time_sec * 1000;
|
||||||
|
|
||||||
@@ -147,6 +154,53 @@ void process_command(const char* cmd) {
|
|||||||
printf("Usage error: Please specify parameters as 'blink <interval_ms> <pulse_width_ms>'\r\n");
|
printf("Usage error: Please specify parameters as 'blink <interval_ms> <pulse_width_ms>'\r\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (strncmp(cmd, "freq ", 5) == 0) {
|
||||||
|
uint32_t target_freq_hz = 0;
|
||||||
|
if (sscanf(cmd + 5, "%lu", &target_freq_hz) == 1) {
|
||||||
|
// Validate limits to protect the SX1276 front-end (e.g., 410 MHz to 525 MHz)
|
||||||
|
bool valid_433 = (target_freq_hz >= 430000000 && target_freq_hz <= 440000000);
|
||||||
|
bool valid_868 = (target_freq_hz >= 863000000 && target_freq_hz <= 870000000);
|
||||||
|
|
||||||
|
if (valid_433 || valid_868) {
|
||||||
|
if (lora_system != nullptr) {
|
||||||
|
// SX1276 formula: Frf = Ffreq * 2^19 / 32000000
|
||||||
|
// Using double to prevent truncation during division before bit masking
|
||||||
|
double fraction = (static_cast<double>(target_freq_hz) * 524288.0) / 32000000.0;
|
||||||
|
uint32_t frf = static_cast<uint32_t>(fraction);
|
||||||
|
|
||||||
|
uint8_t msb = static_cast<uint8_t>((frf >> 16) & 0xFFU);
|
||||||
|
uint8_t mid = static_cast<uint8_t>((frf >> 8) & 0xFFU);
|
||||||
|
uint8_t lsb = static_cast<uint8_t>(frf & 0xFFU);
|
||||||
|
|
||||||
|
lora_system->setFrequency(msb, mid, lsb);
|
||||||
|
printf("Success: Frequency shifted to %lu Hz.\r\n", (unsigned long)target_freq_hz);
|
||||||
|
} else {
|
||||||
|
printf("Error: LoraController handle is uninitialized.\r\n");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
printf("Error: Frequency out of boundaries 430-440 / 863-870 MHz band limits.\r\n");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
printf("Usage error: Please specify parameters as 'freq <frequency_in_hz>'\r\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (strncmp(cmd, "bw ", 3) == 0) {
|
||||||
|
uint32_t target_bw = 0;
|
||||||
|
if (sscanf(cmd + 3, "%lu", &target_bw) == 1) {
|
||||||
|
if (target_bw == 62 || target_bw == 125 || target_bw == 250 || target_bw == 500) {
|
||||||
|
if (lora_system != nullptr) {
|
||||||
|
lora_system->setBandwidth(target_bw);
|
||||||
|
printf("Success: Dispatched bandwidth configuration update to %lu kHz.\r\n", (unsigned long)target_bw);
|
||||||
|
} else {
|
||||||
|
printf("Error: LoraController handle is uninitialized.\r\n");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
printf("Error: Invalid choice. Supported bandwidth options are: 62, 125, 250, 500.\r\n");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
printf("Usage error: Please specify parameter as 'bw <62|125|250|500>'\r\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (strncmp(cmd, "oled ", 5) == 0) {
|
else if (strncmp(cmd, "oled ", 5) == 0) {
|
||||||
uint32_t targetLine = 0;
|
uint32_t targetLine = 0;
|
||||||
char textBuffer[64];
|
char textBuffer[64];
|
||||||
|
|||||||
+14
-2
@@ -3,7 +3,7 @@
|
|||||||
* @file config.hpp
|
* @file config.hpp
|
||||||
* @brief Global compile-time configuration profile and pin mapping for FoxMesh
|
* @brief Global compile-time configuration profile and pin mapping for FoxMesh
|
||||||
* @author OM Tom (OE3TKT)
|
* @author OM Tom (OE3TKT)
|
||||||
*
|
*
|
||||||
* @license SPDX-License-Identifier: MIT
|
* @license SPDX-License-Identifier: MIT
|
||||||
* @copyright Copyright (c) 2026 OM Tom (OE3TKT)
|
* @copyright Copyright (c) 2026 OM Tom (OE3TKT)
|
||||||
* For the full license terms, see the LICENSE file in the project root.
|
* For the full license terms, see the LICENSE file in the project root.
|
||||||
@@ -31,7 +31,7 @@ namespace Config {
|
|||||||
// Hardware Configuration
|
// Hardware Configuration
|
||||||
constexpr gpio_num_t LED_GPIO_PIN = GPIO_NUM_25;
|
constexpr gpio_num_t LED_GPIO_PIN = GPIO_NUM_25;
|
||||||
constexpr int BLINK_INTERVAL_MS = 5000;
|
constexpr int BLINK_INTERVAL_MS = 5000;
|
||||||
|
|
||||||
// OLED Display I2C Bus Configuration
|
// OLED Display I2C Bus Configuration
|
||||||
constexpr gpio_num_t OLED_SDA_PIN = GPIO_NUM_21;
|
constexpr gpio_num_t OLED_SDA_PIN = GPIO_NUM_21;
|
||||||
constexpr gpio_num_t OLED_SCL_PIN = GPIO_NUM_22;
|
constexpr gpio_num_t OLED_SCL_PIN = GPIO_NUM_22;
|
||||||
@@ -45,4 +45,16 @@ namespace Config {
|
|||||||
constexpr gpio_num_t LORA_CS_PIN = GPIO_NUM_18;
|
constexpr gpio_num_t LORA_CS_PIN = GPIO_NUM_18;
|
||||||
constexpr gpio_num_t LORA_RST_PIN = GPIO_NUM_23; // Adjusted configuration for T3_V1.6 hardware revision
|
constexpr gpio_num_t LORA_RST_PIN = GPIO_NUM_23; // Adjusted configuration for T3_V1.6 hardware revision
|
||||||
constexpr gpio_num_t LORA_IRQ_PIN = GPIO_NUM_26;
|
constexpr gpio_num_t LORA_IRQ_PIN = GPIO_NUM_26;
|
||||||
|
|
||||||
|
// Semtech SX1276 LoRa Configuration Parameters
|
||||||
|
// 433.175 MHz is calculated by: 433175000 / (32000000 / 2^19) = 7096525 = 0x06C4CD
|
||||||
|
constexpr uint8_t LORA_FRF_MSB = 0x06;
|
||||||
|
constexpr uint8_t LORA_FRF_MID = 0xC4;
|
||||||
|
constexpr uint8_t LORA_FRF_LSB = 0xCD;
|
||||||
|
|
||||||
|
// Modem Config 1: BW 250kHz (0x80), CR 4/6 (0x04), Explicit Header (0x00) -> 0x84
|
||||||
|
constexpr uint8_t LORA_MODEM_CONFIG_1 = 0x84;
|
||||||
|
|
||||||
|
// Modem Config 2: SF11 (0xB0), TX Continuous off (0x00), CRC On (0x04) -> 0xB4
|
||||||
|
constexpr uint8_t LORA_MODEM_CONFIG_2 = 0xB4;
|
||||||
}
|
}
|
||||||
+77
-9
@@ -61,6 +61,9 @@ void LoraController::writeRegister(uint8_t address, uint8_t value) {
|
|||||||
spi_device_transmit(m_spiHandle, &trans);
|
spi_device_transmit(m_spiHandle, &trans);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Suppress the ISO C++ braced-groups macro expansion warning for the FreeRTOS portYIELD macro
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wpedantic"
|
||||||
void IRAM_ATTR LoraController::gpioIsrHandler(void* arg) {
|
void IRAM_ATTR LoraController::gpioIsrHandler(void* arg) {
|
||||||
auto* semaphore = static_cast<SemaphoreHandle_t>(arg);
|
auto* semaphore = static_cast<SemaphoreHandle_t>(arg);
|
||||||
if (semaphore != nullptr) {
|
if (semaphore != nullptr) {
|
||||||
@@ -71,6 +74,7 @@ void IRAM_ATTR LoraController::gpioIsrHandler(void* arg) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
|
||||||
esp_err_t LoraController::initializeHardware() {
|
esp_err_t LoraController::initializeHardware() {
|
||||||
esp_err_t err;
|
esp_err_t err;
|
||||||
@@ -121,14 +125,57 @@ void LoraController::setModeReceiver() {
|
|||||||
writeRegister(0x01, 0x80U); // Sleep + LoRa Mode
|
writeRegister(0x01, 0x80U); // Sleep + LoRa Mode
|
||||||
vTaskDelay(pdMS_TO_TICKS(10));
|
vTaskDelay(pdMS_TO_TICKS(10));
|
||||||
|
|
||||||
// Hardwired for 868.1 MHz fallback channel
|
// Apply MeshCom network profile: 433.175 MHz, BW 250kHz, SF11, CR 4/6
|
||||||
writeRegister(0x06, 0xD9U);
|
writeRegister(0x06, Config::LORA_FRF_MSB);
|
||||||
writeRegister(0x07, 0x06U);
|
writeRegister(0x07, Config::LORA_FRF_MID);
|
||||||
writeRegister(0x08, 0x66U);
|
writeRegister(0x08, Config::LORA_FRF_LSB);
|
||||||
|
|
||||||
|
writeRegister(0x1D, Config::LORA_MODEM_CONFIG_1); // RegModemConfig1
|
||||||
|
writeRegister(0x1E, Config::LORA_MODEM_CONFIG_2); // RegModemConfig2
|
||||||
|
|
||||||
writeRegister(0x40, 0x00U); // DIO0 map onto RxDone
|
writeRegister(0x40, 0x00U); // DIO0 map onto RxDone
|
||||||
writeRegister(0x01, 0x85U); // RXCONTINUOUS
|
writeRegister(0x01, 0x85U); // RXCONTINUOUS
|
||||||
ESP_LOGI(TAG, "Radio base configuration applied. Listening on 868.1 MHz.");
|
ESP_LOGI(TAG, "Radio configured: 433.175 MHz | BW 250kHz | SF11 | CR 4/6");
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoraController::setFrequency(uint8_t msb, uint8_t mid, uint8_t lsb) {
|
||||||
|
if (m_spiHandle == nullptr) return;
|
||||||
|
|
||||||
|
// Safely force transceiver to Standby to update hardware registers safely
|
||||||
|
writeRegister(0x01, 0x81U);
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(5));
|
||||||
|
|
||||||
|
writeRegister(0x06, msb);
|
||||||
|
writeRegister(0x07, mid);
|
||||||
|
writeRegister(0x08, lsb);
|
||||||
|
|
||||||
|
// Re-engage Continous Reception Mode
|
||||||
|
writeRegister(0x01, 0x85U);
|
||||||
|
ESP_LOGI(TAG, "Frequency dynamically shifted to: 0x%02X%02X%02X", msb, mid, lsb);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoraController::setBandwidth(uint32_t bw_khz) {
|
||||||
|
if (m_spiHandle == nullptr) return;
|
||||||
|
uint8_t bw_setting = 0x00U;
|
||||||
|
bool valid = false;
|
||||||
|
|
||||||
|
if (bw_khz == 62) { bw_setting = 0x60U; valid = true; }
|
||||||
|
if (bw_khz == 125) { bw_setting = 0x70U; valid = true; }
|
||||||
|
if (bw_khz == 250) { bw_setting = 0x80U; valid = true; }
|
||||||
|
if (bw_khz == 500) { bw_setting = 0x90U; valid = true; }
|
||||||
|
|
||||||
|
if (!valid) return;
|
||||||
|
|
||||||
|
writeRegister(0x01, 0x81U);
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(5));
|
||||||
|
|
||||||
|
uint8_t current_config = readRegister(0x1D);
|
||||||
|
current_config = static_cast<uint8_t>(current_config & 0x0FU);
|
||||||
|
current_config = static_cast<uint8_t>(current_config | bw_setting);
|
||||||
|
|
||||||
|
writeRegister(0x1D, current_config);
|
||||||
|
writeRegister(0x01, 0x85U);
|
||||||
|
ESP_LOGI(TAG, "Modem bandwidth dynamically shifted to %lu kHz.", (unsigned long)bw_khz);
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t LoraController::transmitFrame(const uint8_t* buffer, uint8_t length) {
|
esp_err_t LoraController::transmitFrame(const uint8_t* buffer, uint8_t length) {
|
||||||
@@ -171,7 +218,7 @@ void LoraController::run() {
|
|||||||
uint32_t irqFlags = readRegister(0x12);
|
uint32_t irqFlags = readRegister(0x12);
|
||||||
writeRegister(0x12, static_cast<uint8_t>(irqFlags));
|
writeRegister(0x12, static_cast<uint8_t>(irqFlags));
|
||||||
|
|
||||||
if ((irqFlags & 0x40U) != 0U) { // RxDone
|
if ((irqFlags & 0x40U) != 0U) { // RxDone Flag
|
||||||
LoraPacket packet = {};
|
LoraPacket packet = {};
|
||||||
packet.length = readRegister(0x13);
|
packet.length = readRegister(0x13);
|
||||||
|
|
||||||
@@ -181,12 +228,33 @@ void LoraController::run() {
|
|||||||
for (uint8_t i = 0; i < packet.length; i++) {
|
for (uint8_t i = 0; i < packet.length; i++) {
|
||||||
packet.payload[i] = readRegister(0x00);
|
packet.payload[i] = readRegister(0x00);
|
||||||
}
|
}
|
||||||
|
// Calculate the telemetry data
|
||||||
packet.rssi = static_cast<int8_t>(static_cast<int>(readRegister(0x1A)) - 157);
|
packet.rssi = static_cast<int8_t>(static_cast<int>(readRegister(0x1A)) - 157);
|
||||||
packet.snr = static_cast<int8_t>(static_cast<int>(readRegister(0x1B)) / 4);
|
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",
|
// LIVE-AUSGABE DIREKT AUF DIE CONSOLE (Garantiert un-gemutet!)
|
||||||
packet.length, packet.rssi, packet.snr);
|
printf("\r\n--------------------------------------------------\r\n");
|
||||||
|
printf("[LoRa RX] Paket erfolgreich empfangen!\r\n");
|
||||||
|
printf(" Laenge: %u Bytes\r\n", packet.length);
|
||||||
|
printf(" RSSI : %d dBm (Signalstaerke)\r\n", packet.rssi);
|
||||||
|
printf(" SNR : %d dB (Rauschabstand)\r\n", packet.snr);
|
||||||
|
//ESP_LOGI(TAG, "Incoming frame packet received! Size: %u bytes, RSSI: %d dBm, SNR: %d dB",
|
||||||
|
// packet.length, packet.rssi, packet.snr);
|
||||||
|
|
||||||
|
// ASCII-Klartext-Ausgabe für das Terminal formatiert
|
||||||
|
printf(" Inhalt: \"");
|
||||||
|
for (uint8_t i = 0; i < packet.length; i++) {
|
||||||
|
char c = static_cast<char>(packet.payload[i]);
|
||||||
|
// Nur druckbare Zeichen ausgeben, um das Terminal nicht zu verwirren
|
||||||
|
if (c >= 32 && c <= 126) {
|
||||||
|
printf("%c", c);
|
||||||
|
} else {
|
||||||
|
printf("."); // Punkt für nicht-druckbare Binärbytes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("\"\r\n--------------------------------------------------\r\n");
|
||||||
|
printf("%s # ", Config::PROJECT_TITLE); // CLI-Prompt wiederherstellen
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
// FIXED: Uses the new parameter order (line first, text second)
|
// FIXED: Uses the new parameter order (line first, text second)
|
||||||
if (display != nullptr) {
|
if (display != nullptr) {
|
||||||
|
|||||||
@@ -49,6 +49,20 @@ public:
|
|||||||
*/
|
*/
|
||||||
esp_err_t transmitFrame(const uint8_t* buffer, uint8_t length);
|
esp_err_t transmitFrame(const uint8_t* buffer, uint8_t length);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Dynamically updates the transceiver operating frequency at runtime.
|
||||||
|
* @param msb Most Significant Byte of the frequency fraction.
|
||||||
|
* @param mid Middle Significant Byte of the frequency fraction.
|
||||||
|
* @param lsb Least Significant Byte of the frequency fraction.
|
||||||
|
*/
|
||||||
|
void setFrequency(uint8_t msb, uint8_t mid, uint8_t lsb);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Dynamically updates the LoRa signal bandwidth at runtime.
|
||||||
|
* @param bw_khz Target bandwidth in kHz (e.g., 62, 125, 250, 500).
|
||||||
|
*/
|
||||||
|
void setBandwidth(uint32_t bw_khz);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
spi_device_handle_t m_spiHandle = nullptr;
|
spi_device_handle_t m_spiHandle = nullptr;
|
||||||
TaskHandle_t m_taskHandle = nullptr;
|
TaskHandle_t m_taskHandle = nullptr;
|
||||||
|
|||||||
In neuem Issue referenzieren
Einen Benutzer sperren