mirror of
https://github.com/liquidraver/ZephCore.git
synced 2026-10-28 14:02:46 +00:00
Raw LoRa packets to and from a host over the USB/console serial port, plus upstream's SetHardware extensions (identity, crypto, radio config, stats). - app/KissModem.cpp/h: upstream text, ZephCore changes fenced: an LBT refusal returns to CSMA until the wait-clear bound; a TX times out only once the radio has concluded (as Dispatcher::loop); SetRadio outside the ZC_RADIO_* ranges is refused; msUntilNextTx() for the event loop. - src/main_kiss_modem.cpp: event-driven composition root; runs the radio maintenance the Dispatcher would. Identity in /lfs/repeater/_main.id. - adapters/transport/ZephyrUartStream: Arduino Stream over IRQ RX/TX rings. - boards/common/kiss_modem.conf: role, BT off, console driver off. - LoRaRadio::getCurrentRSSI(), Print::availableForWrite(). - UI mesh-action stubs for every non-companion role. Tested on 2x XIAO ESP32-C3 + Wio-SX1262 at 869.423 MHz SF7/62.5/CR5. Built for xiao_esp32c3, rak4631, lora_e5_mini; host tests pass. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
53 lines
1.6 KiB
C++
53 lines
1.6 KiB
C++
/*
|
|
* SPDX-License-Identifier: MIT
|
|
* Arduino Stream over an interrupt-driven Zephyr UART (CDC-ACM or plain UART),
|
|
* for code ported from upstream that talks to `Serial` (the KISS modem).
|
|
*
|
|
* RX and TX each go through a ring drained by the UART ISR. A full RX ring
|
|
* stops reading the port until the main thread has made room, so the host is
|
|
* held off instead of losing bytes. Writes take what fits (availableForWrite()).
|
|
* The callbacks run in the ISR: post events only.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <zephyr/kernel.h>
|
|
#include <zephyr/device.h>
|
|
#include <zephyr/sys/ring_buffer.h>
|
|
#include <Stream.h>
|
|
|
|
class ZephyrUartStream : public Stream {
|
|
public:
|
|
/* on_rx: bytes arrived. on_tx_idle: the TX ring has drained. */
|
|
bool begin(const struct device *dev, void (*on_rx)(void), void (*on_tx_idle)(void));
|
|
|
|
using Print::write;
|
|
size_t write(uint8_t c) override { return write(&c, 1); }
|
|
size_t write(const uint8_t *buffer, size_t size) override;
|
|
int availableForWrite() override;
|
|
|
|
int available() override;
|
|
int read() override;
|
|
int peek() override;
|
|
/* Waits for the TX ring to drain, at most FLUSH_TIMEOUT_MS. */
|
|
void flush() override;
|
|
|
|
private:
|
|
static constexpr size_t RX_BUF_SIZE = 512;
|
|
static constexpr size_t TX_BUF_SIZE = 1024;
|
|
static constexpr uint32_t FLUSH_TIMEOUT_MS = 200;
|
|
|
|
static void isr(const struct device *dev, void *user_data);
|
|
|
|
const struct device *_dev = nullptr;
|
|
void (*_on_rx)(void) = nullptr;
|
|
void (*_on_tx_idle)(void) = nullptr;
|
|
uint8_t _rx_data[RX_BUF_SIZE];
|
|
uint8_t _tx_data[TX_BUF_SIZE];
|
|
struct ring_buf _rx_ring;
|
|
struct ring_buf _tx_ring;
|
|
struct k_spinlock _tx_lock;
|
|
struct k_sem _tx_drained;
|
|
atomic_t _rx_paused = ATOMIC_INIT(0);
|
|
};
|