23 static constexpr uint8_t REG_FIFO = 0x00;
24 static constexpr uint8_t REG_OP_MODE = 0x01;
25 static constexpr uint8_t REG_FRF_MSB = 0x06;
26 static constexpr uint8_t REG_FRF_MID = 0x07;
27 static constexpr uint8_t REG_FRF_LSB = 0x08;
28 static constexpr uint8_t REG_PA_CONFIG = 0x09;
29 static constexpr uint8_t REG_FIFO_ADDR_PTR = 0x0D;
30 static constexpr uint8_t REG_FIFO_TX_BASE = 0x0E;
31 static constexpr uint8_t REG_FIFO_RX_BASE = 0x0F;
32 static constexpr uint8_t REG_FIFO_RX_CURRENT = 0x10;
33 static constexpr uint8_t REG_IRQ_FLAGS = 0x12;
34 static constexpr uint8_t REG_RX_NB_BYTES = 0x13;
35 static constexpr uint8_t REG_PKT_RSSI = 0x1A;
36 static constexpr uint8_t REG_MODEM_CONFIG1 = 0x1D;
37 static constexpr uint8_t REG_MODEM_CONFIG2 = 0x1E;
38 static constexpr uint8_t REG_PREAMBLE_MSB = 0x20;
39 static constexpr uint8_t REG_PREAMBLE_LSB = 0x21;
40 static constexpr uint8_t REG_PAYLOAD_LENGTH = 0x22;
41 static constexpr uint8_t REG_MODEM_CONFIG3 = 0x26;
42 static constexpr uint8_t REG_SYNC_WORD = 0x39;
43 static constexpr uint8_t REG_VERSION = 0x42;
49 static constexpr uint8_t MODE_LORA = 0x80;
50 static constexpr uint8_t MODE_SLEEP = 0x00;
51 static constexpr uint8_t MODE_STDBY = 0x01;
52 static constexpr uint8_t MODE_TX = 0x03;
53 static constexpr uint8_t MODE_RX_CONT = 0x05;
59 static constexpr uint8_t IRQ_TX_DONE = 0x08;
60 static constexpr uint8_t IRQ_PAYLOAD_CRC_ERROR = 0x20;
61 static constexpr uint8_t IRQ_RX_DONE = 0x40;
64const uint8_t SX127X_VERSION = 0x12;
66inline uint8_t rd(
const pc_lora_bus *b, uint8_t reg)
68 return b->read(reg, b->ctx);
70inline void wr(
const pc_lora_bus *b, uint8_t reg, uint8_t val)
72 b->write(reg, val, b->ctx);
76bool pc_lora_frame_parse(
const uint8_t *raw, uint16_t len, pc_lora_header *hdr,
const uint8_t **payload,
77 uint16_t *payload_len)
79 if (!raw || !hdr || len < 4)
93 *payload_len = (uint16_t)(len - 4);
98uint16_t pc_lora_frame_build(
const pc_lora_header *hdr,
const uint8_t *payload, uint16_t len, uint8_t *out,
109 for (uint16_t i = 0; i < len; i++)
111 out[4 + i] = payload[i];
113 return (uint16_t)(len + 4);
116bool pc_lora_init(
const pc_lora_bus *bus,
const pc_lora_config *cfg)
118 if (!bus || !bus->read || !bus->write || !cfg)
122 if (rd(bus, LoraReg::REG_VERSION) != SX127X_VERSION)
128 wr(bus, LoraReg::REG_OP_MODE, LoraMode::MODE_SLEEP);
129 wr(bus, LoraReg::REG_OP_MODE, LoraMode::MODE_LORA | LoraMode::MODE_SLEEP);
130 wr(bus, LoraReg::REG_OP_MODE, LoraMode::MODE_LORA | LoraMode::MODE_STDBY);
133 uint32_t frf = (uint32_t)(((uint64_t)cfg->freq_hz << 19) / 32000000UL);
134 wr(bus, LoraReg::REG_FRF_MSB, (uint8_t)(frf >> 16));
135 wr(bus, LoraReg::REG_FRF_MID, (uint8_t)(frf >> 8));
136 wr(bus, LoraReg::REG_FRF_LSB, (uint8_t)frf);
138 wr(bus, LoraReg::REG_FIFO_TX_BASE, 0x00);
139 wr(bus, LoraReg::REG_FIFO_RX_BASE, 0x00);
142 wr(bus, LoraReg::REG_MODEM_CONFIG1, (uint8_t)((cfg->bandwidth << 4) | (cfg->coding_rate << 1)));
143 wr(bus, LoraReg::REG_MODEM_CONFIG2, (uint8_t)((cfg->spreading << 4) | 0x04));
144 wr(bus, LoraReg::REG_MODEM_CONFIG3, (uint8_t)((cfg->spreading >= 11 ? 0x08 : 0x00) | 0x04));
146 wr(bus, LoraReg::REG_PREAMBLE_MSB, 0x00);
147 wr(bus, LoraReg::REG_PREAMBLE_LSB, 0x08);
148 wr(bus, LoraReg::REG_SYNC_WORD, cfg->sync_word);
149 wr(bus, LoraReg::REG_PA_CONFIG, (uint8_t)(0x80 | ((cfg->tx_power - 2) & 0x0F)));
151 wr(bus, LoraReg::REG_OP_MODE, LoraMode::MODE_LORA | LoraMode::MODE_STDBY);
155bool pc_lora_send(
const pc_lora_bus *bus,
const uint8_t *frame, uint8_t len)
161 wr(bus, LoraReg::REG_OP_MODE, LoraMode::MODE_LORA | LoraMode::MODE_STDBY);
162 wr(bus, LoraReg::REG_FIFO_ADDR_PTR, 0x00);
163 for (uint8_t i = 0; i < len; i++)
165 wr(bus, LoraReg::REG_FIFO, frame[i]);
167 wr(bus, LoraReg::REG_PAYLOAD_LENGTH, len);
168 wr(bus, LoraReg::REG_OP_MODE, LoraMode::MODE_LORA | LoraMode::MODE_TX);
172bool pc_lora_tx_done(
const pc_lora_bus *bus)
178 if (rd(bus, LoraReg::REG_IRQ_FLAGS) & LoraIrq::IRQ_TX_DONE)
180 wr(bus, LoraReg::REG_IRQ_FLAGS, 0xFF);
186void pc_lora_set_rx(
const pc_lora_bus *bus)
192 wr(bus, LoraReg::REG_FIFO_ADDR_PTR, 0x00);
193 wr(bus, LoraReg::REG_OP_MODE, LoraMode::MODE_LORA | LoraMode::MODE_RX_CONT);
196int pc_lora_recv(
const pc_lora_bus *bus, uint8_t *buf, uint8_t cap, int16_t *rssi)
202 uint8_t flags = rd(bus, LoraReg::REG_IRQ_FLAGS);
203 if (!(flags & LoraIrq::IRQ_RX_DONE))
207 if (flags & LoraIrq::IRQ_PAYLOAD_CRC_ERROR)
209 wr(bus, LoraReg::REG_IRQ_FLAGS, 0xFF);
212 uint8_t len = rd(bus, LoraReg::REG_RX_NB_BYTES);
213 wr(bus, LoraReg::REG_FIFO_ADDR_PTR, rd(bus, LoraReg::REG_FIFO_RX_CURRENT));
215 for (uint8_t i = 0; i < len; i++)
217 uint8_t b = rd(bus, LoraReg::REG_FIFO);
225 *rssi = (int16_t)(-157 + rd(bus, LoraReg::REG_PKT_RSSI));
227 wr(bus, LoraReg::REG_IRQ_FLAGS, 0xFF);
LoRa radio codec + driver (PC_ENABLE_LORA) - Semtech SX127x / RFM95-96.
#define PC_LORA_MAX_PAYLOAD
Max LoRa payload bytes (SX127x FIFO is 256; RadioHead uses 251 + 4 header).