Loading...
Searching...
No Matches
sx1272.c
1/**************************************************************************************************
2 * @file sx1272.c *
3 * @author Matt Ricci *
4 * @addtogroup LoRa *
5 * @brief Brief description of the file's purpose. *
6 * *
7 * @todo Implement adjustable packet size *
8 * @{ *
9 **************************************************************************************************/
10
11#include "sx1272.h"
12
13#include "stddef.h"
14#include "math.h"
15
16static void _SX1272_init(SX1272_t *, SX1272_Config *);
17static void SX1272_writeRegister(SX1272_t *, uint8_t, uint8_t);
18
19/* ============================================================================================== */
30bool SX1272_init(SX1272_t *lora, SPI_t *spi, GPIOpin_t cs, SX1272_Config *config) {
31 lora->spi = spi;
32 lora->cs = cs;
33 lora->standby = SX1272_standby;
39
40 return SX1272_updateConfig(lora, config);
41}
42
43// ALLOW FORMATTING
44#ifndef __DOXYGEN__
45
46/**************************************** PRIVATE METHODS *****************************************/
47
48/* ============================================================================================== */
57static void _SX1272_init(SX1272_t *lora, SX1272_Config *config) {
58 // Set mode to sleep
59 _SX1272_setMode(lora, SX1272_MODE_SLEEP);
60
61 /* clang-format off */
62 uint8_t opMode = SX1272_readRegister(lora, SX1272_REG_OP_MODE);
63 SX1272_writeRegister(lora, SX1272_REG_OP_MODE, opMode | SX1272_OP_MODE_LONG_RANGE);
64
65 _SX1272_setMode(lora, SX1272_MODE_STDBY);
66
67 uint32_t frf = (config->freq * (0x01 << 19)) / 32.0f;
68 SX1272_writeRegister(lora, SX1272_REG_FR_LSB, frf >> 0);
69 SX1272_writeRegister(lora, SX1272_REG_FR_MIB, frf >> 8);
70 SX1272_writeRegister(lora, SX1272_REG_FR_MSB, frf >> 16);
71
72
73 // Set bandwidth, coding rate, toggle implicit header mode, crc enable
74 SX1272_writeRegister(lora, SX1272_REG_MODEM_CONFIG1,
75 config->bw << SX1272_MODEM_CONFIG1_BW_Pos // Set bandwidth
76 | config->cr << SX1272_MODEM_CONFIG1_CR_Pos // Set coding rate
77 | (config->implicitHeader ? SX1272_MODEM_CONFIG1_IMPLICIT_HEADER : 0) // Set header mode
78 | (config->crc ? SX1272_MODEM_CONFIG1_CRC : 0) // Set CRC
79 );
80
81 // Set spreading factor
82 SX1272_writeRegister(lora, SX1272_REG_MODEM_CONFIG2,
83 (config->sf << SX1272_MODEM_CONFIG2_SF_Pos) | SX1272_MODEM_CONFIG2_AGC_AUTO_ON
84 );
85
86 // Set maximum payload length
87 SX1272_writeRegister(lora, SX1272_REG_MAX_PAYLOAD_LENGTH, config->maxPayloadLength);
88
89 // Set FIFO base addresses
90 SX1272_writeRegister(lora, SX1272_REG_FIFO_TX_BASE_ADDR, config->txFifoBaseAddr);
91 SX1272_writeRegister(lora, SX1272_REG_FIFO_RX_BASE_ADDR, config->rxFifoBaseAddr);
92
93 // Set over current protection configuration
94 SX1272_writeRegister(lora, SX1272_REG_OCP,
95 (config->ocp ? SX1272_OCP_ON : 0) // Enable/disable over current protection
96 | config->ocpTrim // Set overcurrent protection trim
97 );
98
99 // Set power amplifier configuration
100 SX1272_writeRegister(lora, SX1272_REG_PA_CONFIG,
101 (config->paSelect ? SX1272_PA_SELECT : 0) // Select power amplifier output pin
102 | config->outputPower // Set power amplifier output power
103 );
104 /* clang-format on */
105
106 SX1272_writeRegister(lora, SX1272_REG_PA_DAC, 0x87);
107
108 uint8_t RegPll = SX1272_readRegister(lora, 0x5C);
109 RegPll &= 0xC0;
110 RegPll |= 0x40;
111 SX1272_writeRegister(lora, 0x5C, RegPll);
112
113 uint8_t RegTcxo = SX1272_readRegister(lora, 0x58);
114 RegTcxo |= 0x10;
115 SX1272_writeRegister(lora, 0x58, RegTcxo);
116
117 SX1272_writeRegister(lora, 0x0A, 0x09);
118
119 // Set mode to standby
120 //_SX1272_setMode(lora, SX1272_MODE_STDBY);
121}
122
123/* ============================================================================================== */
132void _SX1272_setMode(SX1272_t *lora, SX1272_Mode mode) {
133 uint8_t regOpMode = SX1272_readRegister(lora, SX1272_REG_OP_MODE);
134 regOpMode &= ~0x07; // Mask to mode bits
135 regOpMode |= mode; // Set mode
136 lora->currentMode = mode; // Set driver mode
137
138 switch (mode) {
139 case SX1272_MODE_TX:
140 lora->base.currentMode = LORA_MODE_TX;
141 break;
142 case SX1272_MODE_RXCONTINUOUS:
143 lora->base.currentMode = LORA_MODE_RX;
144 break;
145 default:
146 lora->base.currentMode = LORA_MODE_OTHER;
147 break;
148 }
149
150 // Update device mode
151 SX1272_writeRegister(lora, SX1272_REG_OP_MODE, regOpMode);
152}
153
154#endif
155
156/***************************************** PUBLIC METHODS *****************************************/
157
158/* ============================================================================================== */
168 _SX1272_setMode(lora, SX1272_MODE_STDBY);
169}
170
171/* ============================================================================================== */
179void SX1272_transmit(LoRa_t *lora, uint8_t *pointerdata, uint8_t length) {
180 SX1272_t *driver = (SX1272_t *)lora;
181
182 // Set device to standby
183 _SX1272_setMode(driver, SX1272_MODE_STDBY);
184
185 // Set payload length
186 SX1272_writeRegister(driver, SX1272_REG_PAYLOAD_LENGTH, length);
187
188 // TODO: add in proper read-mask-write operation for setting DIO mapping
189 //
190 // Set DIO interrupt pin to TxDone
191 SX1272_writeRegister(driver, SX1272_REG_DIO_MAPPING1, SX1272_LORA_DIO_TXDONE);
192
193 // Since the device will only ever be transmitting or receiving at any given time
194 // and each packet should be handled immediately by the implementation (no waiting
195 // on buffering), we don't need to be concerned about the buffer being overwritten.
196 //
197 // ...for now.
198
199 // TODO:
200 // Think of a more elegant solution for applications that might use this
201 // driver that want buffered data
202 //
203 // Clear IRQ flags and set FIFO address pointer.
204
205 SX1272_writeRegister(driver, SX1272_REG_IRQ_FLAGS, SX1272_LORA_IRQ_TXDONE); // clears the IRQ flag
206 SX1272_writeRegister(driver, SX1272_REG_FIFO_ADDR_PTR, 0x00); // set pointer adddress to start
207 // Load data into transmit FIFO
208 for (int i = 0; i < length; i++) {
209 SX1272_writeRegister(driver, SX1272_REG_FIFO, pointerdata[i]);
210 }
211
212 // Update the current operating mode
213 _SX1272_setMode(driver, SX1272_MODE_TX); // Start transmitting
214}
215
216/* ============================================================================================== */
224 SX1272_t *driver = (SX1272_t *)lora;
225
226 // Set device to standby
227 _SX1272_setMode(driver, SX1272_MODE_STDBY);
228
229 // TODO: add in proper read-mask-write operation for setting DIO mapping
230 //
231 // Set DIO interrupt pin to RxDone
232 SX1272_writeRegister(driver, SX1272_REG_DIO_MAPPING1, SX1272_LORA_DIO_RXDONE);
233
234 // Since the device will only ever be transmitting or receiving at any given time
235 // and each packet should be handled immediately by the implementation (no waiting
236 // on buffering), we don't need to be concerned about the buffer being overwritten.
237 //
238 // ...for now.
239
240 // TODO:
241 // Think of a more elegant solution for applications that might use this
242 // driver that want buffered data
243 //
244 // Clear IRQ flags and set FIFO address pointer.
245 // SX1272_writeRegister(driver, SX1272_REG_IRQ_FLAGS, SX1272_LORA_IRQ_RXDONE); // Clear the IRQ flag
246 SX1272_writeRegister(driver, SX1272_REG_FIFO_ADDR_PTR, 0x00); // Set pointer adddress to start
247
248 // Update the current operating mode
249 _SX1272_setMode(driver, SX1272_MODE_RXCONTINUOUS); // Start receiving
250}
251
252/* ============================================================================================== */
264uint8_t SX1272_readReceive(LoRa_t *lora, uint8_t *buffer, uint8_t buffSize) {
265 SX1272_t *driver = (SX1272_t *)lora;
266
267 // TODO: Error handling for IRQ flags
268 //
269 // Currently the readReceive() method clears the SX1272 RxDone IRQ flag before
270 // starting the read. This is fine for cases where the user code carefully
271 // manages the DIO interrupts, however ideally the method should check for
272 // errors in the IRQ register and appropriately discard received packets.
273
274 // Clear the IRQ flag
275 SX1272_writeRegister(driver, SX1272_REG_IRQ_FLAGS, SX1272_LORA_IRQ_RXDONE);
276
277 // Read address and packet width information of received data
278 uint8_t bytesReceived = SX1272_readRegister(driver, SX1272_REG_RX_BYTES); // Number of bytes received
279 uint8_t rxCurrentAddr = SX1272_readRegister(driver, SX1272_REG_FIFO_RX_CURR_ADDR); // Address of last packet
280
281 // Return error if buffer is smaller than the received data
282 if (bytesReceived > buffSize)
283 return false;
284
285 // Otherwise, set the address pointer and read each byte into buffer
286 SX1272_writeRegister(driver, SX1272_REG_FIFO_ADDR_PTR, rxCurrentAddr);
287 for (int i = 0; i < bytesReceived; i++) {
288 buffer[i] = SX1272_readRegister(driver, SX1272_REG_FIFO);
289 }
290
291 return bytesReceived;
292}
293
294/* ============================================================================================== */
305void SX1272_clearIRQ(LoRa_t *lora, uint8_t flags) {
306 SX1272_writeRegister((SX1272_t *)lora, SX1272_REG_IRQ_FLAGS, flags);
307}
308
309/* ============================================================================================== */
320 // Initialise config with default values if passed NULL.
321 if (config == NULL) {
322 config = &SX1272_CONFIG_DEFAULT;
323 }
324
325 // Validate max values
326 if (config->outputPower > 0x1F || config->ocpTrim > 0x1F)
327 return false;
328
329 // Update peripheral with new config
330 lora->config = *config;
331
332 // Initialise SPI registers and enable peripheral
333 _SX1272_init(lora, config);
334
335 return true;
336}
337
338/*************************************** INTERFACE METHODS ****************************************/
339
340// NOTE: This function is left exposed to public imports for debug purposes
341uint8_t SX1272_readRegister(SX1272_t *lora, uint8_t address) {
342 uint8_t response = 0;
343 SPI_t *spi = lora->spi;
344 GPIOpin_t cs = lora->cs;
345
346 // Pull CS low
347 cs.reset(&cs);
348
349 // Send write data and address
350 uint8_t payload = address & 0x7F; // Load payload with address and read command
351 response = spi->transmit(spi, payload); // Transmit payload
352 response = spi->transmit(spi, 0xFF); // Transmit dummy data and reasd response
353
354 // Set CS high
355 cs.set(&cs);
356
357 return response;
358}
359
360void SX1272_writeRegister(SX1272_t *lora, uint8_t address, uint8_t data) {
361 SPI_t *spi = lora->spi;
362 GPIOpin_t cs = lora->cs;
363
364 // Pull CS low
365 cs.reset(&cs);
366
367 // Send write data and address
368 uint8_t payload = address | 0x80; // Load payload with address and write command
369 spi->transmit(spi, payload); // Transmit payload
370 spi->transmit(spi, data); // Transmit write data
371
372 // Set CS high
373 cs.set(&cs);
374}
375
Definition lora.h:30
void(* transmit)(struct LoRa *, uint8_t *, uint8_t)
LoRa transmit method.
Definition lora.h:32
LoRa_Mode currentMode
Current operating mode.
Definition lora.h:31
uint8_t(* readReceive)(struct LoRa *, uint8_t *, uint8_t)
LoRa receive buffer read method.
Definition lora.h:34
void(* startReceive)(struct LoRa *)
LoRa continuous receive method.
Definition lora.h:33
void(* clearIRQ)(struct LoRa *, uint8_t)
LoRa IRQ clear method.
Definition lora.h:35
void(* set)(struct GPIOpin *)
Definition gpiopin.h:155
void(* reset)(struct GPIOpin *)
Definition gpiopin.h:156
Struct definition for a GPIO pin.
Definition gpiopin.h:151
SX1272_CodingRate cr
SX1272 LoRa modem coding rate.
Definition sx1272.h:166
uint8_t ocpTrim
SX1272 LoRa modem overcurrent protection trim.
Definition sx1272.h:176
SX1272_Config config
Configuration parameters for the SX1272 driver.
Definition sx1272.h:191
void(* standby)(struct SX1272 *)
SX1272 standby method.
Definition sx1272.h:195
float freq
SX1272 LoRa carrier frequency.
Definition sx1272.h:160
SX1272_SpreadingFactor sf
SX1272 LoRa modem spreading factor.
Definition sx1272.h:164
GPIOpin_t cs
Chip select GPIO.
Definition sx1272.h:193
LoRa_t base
Base LoRa API.
Definition sx1272.h:190
uint8_t rxFifoBaseAddr
Base address for RX fifo.
Definition sx1272.h:179
bool ocp
SX1272 LoRa modem overcurrent protection enable.
Definition sx1272.h:175
bool(* updateConfig)(struct SX1272 *, SX1272_Config *)
SX1272 configuration update method.
Definition sx1272.h:196
bool paSelect
SX1272 LoRa modem power amp output select.
Definition sx1272.h:171
uint8_t outputPower
SX1272 LoRa modem power amp output power.
Definition sx1272.h:172
bool implicitHeader
SX1272 LoRa modem implicit header enable.
Definition sx1272.h:167
uint8_t txFifoBaseAddr
Base address for TX fifo.
Definition sx1272.h:180
SX1272_Mode currentMode
Current operating mode.
Definition sx1272.h:194
SX1272_Bandwidth bw
SX1272 LoRa modem bandwidth.
Definition sx1272.h:165
SPI_t * spi
Parent SPI interface.
Definition sx1272.h:192
bool crc
SX1272 LoRa modem CRC enable.
Definition sx1272.h:168
uint8_t maxPayloadLength
Maximum allowed length of payload.
Definition sx1272.h:181
uint16_t(* transmit)(struct SPI *, uint16_t)
SPI transmit method.
Definition spi.h:139
Struct definition for SPI interface. Provides the interface for API consumers to interact with the SP...
Definition spi.h:134
void SX1272_startReceive(LoRa_t *lora)
Begins continuous receive on the SX1272.
Definition sx1272.c:223
uint8_t SX1272_readReceive(LoRa_t *lora, uint8_t *data, uint8_t byffSize)
Reads contents of received packet to local buffer from the SX1272.
Definition sx1272.c:264
void SX1272_transmit(LoRa_t *lora, uint8_t *data, uint8_t length)
Transmits data using the SX1272.
Definition sx1272.c:179
bool SX1272_updateConfig(SX1272_t *lora, SX1272_Config *config)
Update SX1272 configuration.
Definition sx1272.c:319
SX1272_Mode
SX1272 operating mode enum.
Definition sx1272.h:144
void SX1272_standby(SX1272_t *)
Sets the operational mode of the LoRa module to standby.
Definition sx1272.c:167
bool SX1272_init(SX1272_t *lora, SPI_t *spi, GPIOpin_t cs, SX1272_Config *config)
Initializes the LoRa module with specified configuration parameters.
Definition sx1272.c:30
void SX1272_clearIRQ(LoRa_t *, uint8_t)
Sets the value of RegIrqFlags in the SX1272 to the provided argument value. Writing a 1 to a bit in t...
Definition sx1272.c:305
SX1272 LoRa configuration struct.
Definition sx1272.h:159
Struct definition for SX1272. Provides the interface for API consumers to interact with the SX1272 Lo...
Definition sx1272.h:189