Layer: Foundation ยท Build flags: PROTOCORE_ENABLE_LORA, PROTOCORE_ENABLE_GATEWAY
What this example teaches
The radio-plugin half of RadioGateway: instead of a simulated feed, this drives an actual Semtech SX127x / RFM95-96 over SPI and bridges its frames to the gateway.
RFM95 RX --SPI--> protocore_lora_recv() --> protocore_lora_frame_parse() --> protocore_gateway_uplink()
|
envelope + topic lora/0/<from>
|
northbound publish (MQTT/HTTP/WS)
The services/lora module has two layers, and only the first is hardware-specific:
- Driver - the SX127x register protocol over a
protocore_lora_bus (two callbacks that read / write a chip register). Here they are a few SPI transfers; that is the only code tied to your board.
- Codec -
protocore_lora_frame_parse / protocore_lora_frame_build handle the RadioHead 4-byte header (to / from / id / flags) that sits on top of the header-less LoRa PHY.
proto_bool protocore_gateway_uplink(uint8_t *work, uint8_t port_id, uint16_t src_addr, const uint8_t *payload, uint16_t len, int16_t rssi)
Bridge a received southbound frame northbound: envelope it and .
int protocore_lora_recv(uint8_t *work, const protocore_lora_bus *bus, uint8_t *buf, uint8_t cap, int16_t *rssi)
If a frame has been received, copy it into buf and report its RSSI.
void protocore_lora_set_rx(uint8_t *work, const protocore_lora_bus *bus)
Put the radio in continuous-receive mode (call once, then poll .
proto_bool protocore_lora_init(uint8_t *work, const protocore_lora_bus *bus, const protocore_lora_config *cfg)
Initialize the SX127x: verify the chip, switch to LoRa mode, and .
proto_bool protocore_lora_frame_parse(uint8_t *work, const uint8_t *raw, uint16_t len, protocore_lora_header *hdr, const uint8_t **payload, uint16_t *payload_len)
Split a received frame into its header and payload.
Radio configuration applied by protocore_lora_init().
uint32_t freq_hz
carrier frequency in Hz (e.g. 868100000 / 915000000).
uint8_t bandwidth
bandwidth code 0..9 (7 = 125 kHz - the common default).
uint8_t sync_word
0x12 private / 0x34 LoRaWAN.
uint8_t spreading
spreading factor 6..12 (SF7 default is a good start).
uint8_t tx_power
PA_BOOST power 2..17 dBm.
uint8_t coding_rate
coding rate 1..4 (1 = 4/5).
A downlink (a northbound command) is the mirror: protocore_lora_frame_build() then protocore_lora_send(), driven by the gateway port's transmit callback.
Wiring (ESP32 <-> RFM95)
| RFM95 | ESP32 |
| SCK | GPIO 18 |
| MISO | GPIO 19 |
| MOSI | GPIO 23 |
| NSS | GPIO 5 |
| RST | GPIO 14 |
| DIO0 | GPIO 26 |
| VCC | 3V3 |
| GND | GND |
Change the PIN_* constants for your board. A production build triggers RX off the DIO0 interrupt and rides the DMA + FORWARD-lane path (RadioGateway); this sketch polls to stay simple. It needs the module wired to actually receive - the codec and the register protocol are host-tested in test/test_lora.
Build-flag note
The flags must reach the library build, so pass them as build flags:
pio ci --board=esp32dev --project-option="framework=arduino" \
--project-option="build_flags=-DPROTOCORE_ENABLE_LORA=1 -DPROTOCORE_ENABLE_GATEWAY=1" \
--lib="." examples/Drivers/LoRaGateway/LoRaGateway.ino