[4.4.2] Remove 15 m/s limit on estimated vario (#12788)
[betaflight.git] / src / main / drivers / rx / rx_sx1280.c
blobb3f7ba988f369ce2da093ce1ea76b69cc7fef120
1 /*
2 * This file is part of Cleanflight and Betaflight.
4 * Cleanflight and Betaflight are free software. You can redistribute
5 * this software and/or modify this software under the terms of the
6 * GNU General Public License as published by the Free Software
7 * Foundation, either version 3 of the License, or (at your option)
8 * any later version.
10 * Cleanflight and Betaflight are distributed in the hope that they
11 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 * See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this software.
18 * If not, see <http://www.gnu.org/licenses/>.
22 * Based on https://github.com/ExpressLRS/ExpressLRS
23 * Thanks to AlessandroAU, original creator of the ExpressLRS project.
26 #include <stdbool.h>
27 #include <stdint.h>
28 #include <stdlib.h>
29 #include <string.h>
31 #include "platform.h"
33 #ifdef USE_RX_SX1280
35 #include "build/atomic.h"
36 #include "build/debug.h"
38 #include "drivers/bus_spi.h"
39 #include "drivers/io.h"
40 #include "drivers/io_impl.h"
41 #include "drivers/nvic.h"
42 #include "drivers/rx/rx_sx1280.h"
43 #include "drivers/rx/rx_spi.h"
44 #include "drivers/time.h"
46 #include "rx/rx_spi.h"
47 #include "rx/expresslrs.h"
48 #include "rx/expresslrs_common.h"
49 #include "rx/expresslrs_impl.h"
51 #define SX1280_MAX_SPI_MHZ 18000000
53 // The following global variables are accessed from interrupt context to process the sequence of steps in packet processing
54 // As there is only ever one device, no need to add a device context; globals will do
55 static volatile dioReason_e irqReason; // Used to pass irq status from sx1280IrqStatusRead() to sx1280ProcessIrq()
56 static volatile uint8_t packetStats[2];
57 static volatile uint8_t FIFOaddr; // Used to pass data from sx1280GotFIFOAddr() to sx1280DoReadBuffer()
59 static IO_t busy;
61 typedef struct busyIntContext_s {
62 extiCallbackRec_t exti;
63 } busyIntContext_t;
65 static busyIntContext_t busyIntContext;
67 static volatile timeUs_t sx1280Processing;
69 static volatile bool pendingISR = false;
70 static volatile bool pendingDoFHSS = false;
72 #define SX1280_BUSY_TIMEOUT_US 1000
75 bool sx1280IsBusy(void)
77 return IORead(busy);
80 FAST_CODE static bool sx1280PollBusy(void)
82 uint32_t startTime = micros();
83 while (IORead(busy)) {
84 if ((micros() - startTime) > SX1280_BUSY_TIMEOUT_US) {
85 return false;
86 } else {
87 __asm__("nop");
90 return true;
93 FAST_CODE static bool sx1280MarkBusy(void)
95 // Check that there isn't already a sequence of accesses to the SX1280 in progress
96 ATOMIC_BLOCK(NVIC_PRIO_MAX) {
97 if (sx1280Processing) {
98 return false;
101 sx1280Processing = micros();
104 return true;
107 static void sx1280ClearBusyFn(void)
109 EXTIDisable(busy);
112 // Switch to waiting for busy interrupt
113 FAST_CODE static bool sx1280EnableBusy(void)
115 if (!sx1280MarkBusy()) {
116 return false;
119 /* Ensure BUSY EXTI is enabled
121 * This is needed because the BETAFPV F4SX1280 target defines the following resources which cannot be
122 * simultaneously used with the EXTI15_10_IRQHandler. Fortunately we can enable RX_SPI_EXTI until an
123 * interrupt is received, then enable RX_SPI_EXPRESSLRS_BUSY with the call below until data transfers
124 * are complete and then switch back with a call to sx1280EnableExti().
126 * resource RX_SPI_EXTI 1 C13
127 * resource RX_SPI_EXPRESSLRS_BUSY 1 A13
131 EXTIConfig(busy, &busyIntContext.exti, NVIC_PRIO_RX_BUSY_EXTI, IOCFG_IN_FLOATING, BETAFLIGHT_EXTI_TRIGGER_FALLING);
133 return true;
136 // waitingFn() must call sx1280ClearBusyFn() to prevent repeated calls
138 static void sx1280SetBusyFn(extiHandlerCallback *waitingFn)
140 bool sx1280Busy;
142 ATOMIC_BLOCK(NVIC_PRIO_RX_BUSY_EXTI) {
143 sx1280Busy = IORead(busy);
144 if (sx1280Busy) {
145 EXTIHandlerInit(&busyIntContext.exti, waitingFn);
146 EXTIEnable(busy);
147 } else {
148 EXTIDisable(busy);
152 if (!sx1280Busy) {
153 waitingFn(&busyIntContext.exti);
157 static void sx1280MarkFree(void)
159 // Mark that current sequence of accesses is concluded
160 sx1280Processing = (timeUs_t)0;
163 // Switch to waiting for EXTI interrupt
164 static void sx1280EnableExti(void)
166 sx1280MarkFree();
167 rxSpiEnableExti();
170 // Unlikely as it is for the code to lock up waiting on a busy SX1280, we can't afford the risk
171 // If this routine is called twice in succession whilst waiting on the same busy, force the code to advance
172 // Called from the Tick timer
173 bool sx1280HandleFromTick(void)
175 // Grab a copy to prevent a race condition
176 timeUs_t startTime = sx1280Processing;
178 if (startTime) {
179 // No operation should take SX1280_BUSY_TIMEOUT_US us
180 if (cmpTimeUs(micros(), startTime) > SX1280_BUSY_TIMEOUT_US) {
181 // Brute force abandon the current sequence of operations
182 sx1280ClearBusyFn();
183 // Renable EXTI
184 sx1280EnableExti();
186 return true;
190 return false;
193 bool sx1280Init(IO_t resetPin, IO_t busyPin)
195 if (!rxSpiExtiConfigured()) {
196 return false;
199 rxSpiSetNormalSpeedMhz(SX1280_MAX_SPI_MHZ);
200 rxSpiNormalSpeed();
202 if (resetPin) {
203 IOInit(resetPin, OWNER_RX_SPI_EXPRESSLRS_RESET, 0);
204 IOConfigGPIO(resetPin, IOCFG_OUT_PP);
205 } else {
206 resetPin = IO_NONE;
209 if (busyPin) {
210 IOInit(busyPin, OWNER_RX_SPI_EXPRESSLRS_BUSY, 0);
211 IOConfigGPIO(busyPin, IOCFG_IN_FLOATING);
212 } else {
213 busyPin = IO_NONE;
216 busy = busyPin;
218 IOLo(resetPin);
219 delay(50);
220 IOConfigGPIO(resetPin, IOCFG_IN_FLOATING); // leave floating, internal pullup on sx1280 side
221 delay(20);
223 uint16_t firmwareRev = (((sx1280ReadRegister(REG_LR_FIRMWARE_VERSION_MSB)) << 8) | (sx1280ReadRegister(REG_LR_FIRMWARE_VERSION_MSB + 1)));
225 if ((firmwareRev == 0) || (firmwareRev == 65535)) {
226 return false;
229 // Record the dev pointer for callbacks
230 extDevice_t *dev = rxSpiGetDevice();
231 dev->callbackArg = (uint32_t)dev;
233 return true;
236 void sx1280WriteCommand(const uint8_t address, const uint8_t data)
238 sx1280PollBusy();
239 rxSpiWriteCommand(address, data);
242 void sx1280WriteCommandBurst(const uint8_t address, const uint8_t *data, const uint8_t length)
244 uint8_t outBuffer[length + 1];
246 outBuffer[0] = address;
248 memcpy(outBuffer + 1, data, length);
250 sx1280PollBusy();
251 rxSpiTransferCommandMulti(&outBuffer[0], length + 1);
254 void sx1280ReadCommandBurst(const uint8_t address, uint8_t *data, const uint8_t length)
256 uint8_t outBuffer[length + 2];
258 outBuffer[0] = address;
259 outBuffer[1] = 0x00;
261 memcpy(outBuffer + 2, data, length);
263 sx1280PollBusy();
264 rxSpiTransferCommandMulti(&outBuffer[0], length + 2);
265 memcpy(data, outBuffer + 2, length);
268 void sx1280WriteRegisterBurst(const uint16_t address, const uint8_t *buffer, const uint8_t size)
270 uint8_t outBuffer[size + 3];
272 outBuffer[0] = (uint8_t) SX1280_RADIO_WRITE_REGISTER;
273 outBuffer[1] = ((address & 0xFF00) >> 8);
274 outBuffer[2] = (address & 0x00FF);
276 memcpy(outBuffer + 3, buffer, size);
278 sx1280PollBusy();
279 rxSpiTransferCommandMulti(&outBuffer[0], size + 3);
282 void sx1280WriteRegister(const uint16_t address, const uint8_t value)
284 sx1280WriteRegisterBurst(address, &value, 1);
287 void sx1280ReadRegisterBurst(const uint16_t address, uint8_t *buffer, const uint8_t size)
289 uint8_t outBuffer[size + 4];
291 outBuffer[0] = (uint8_t) SX1280_RADIO_READ_REGISTER;
292 outBuffer[1] = ((address & 0xFF00) >> 8);
293 outBuffer[2] = (address & 0x00FF);
294 outBuffer[3] = 0x00;
296 sx1280PollBusy();
297 rxSpiTransferCommandMulti(&outBuffer[0], size + 4);
298 memcpy(buffer, outBuffer + 4, size);
301 uint8_t sx1280ReadRegister(const uint16_t address)
303 uint8_t data;
304 sx1280ReadRegisterBurst(address, &data, 1);
305 return data;
308 void sx1280WriteBuffer(const uint8_t offset, const uint8_t *buffer, const uint8_t size)
310 uint8_t outBuffer[size + 2];
312 outBuffer[0] = (uint8_t) SX1280_RADIO_WRITE_BUFFER;
313 outBuffer[1] = offset;
315 memcpy(outBuffer + 2, buffer, size);
317 sx1280PollBusy();
318 rxSpiTransferCommandMulti(&outBuffer[0], size + 2);
321 void sx1280ReadBuffer(const uint8_t offset, uint8_t *buffer, const uint8_t size)
323 uint8_t outBuffer[size + 3];
325 outBuffer[0] = (uint8_t) SX1280_RADIO_READ_BUFFER;
326 outBuffer[1] = offset;
327 outBuffer[2] = 0x00;
329 sx1280PollBusy();
330 rxSpiTransferCommandMulti(&outBuffer[0], size + 3);
331 memcpy(buffer, outBuffer + 3, size);
334 uint8_t sx1280GetStatus(void)
336 uint8_t buffer[3] = {(uint8_t) SX1280_RADIO_GET_STATUS, 0, 0};
337 sx1280PollBusy();
338 rxSpiTransferCommandMulti(&buffer[0], 3);
339 return buffer[0];
342 void sx1280ConfigLoraDefaults(void)
344 sx1280SetMode(SX1280_MODE_STDBY_RC); //step 1 put in STDBY_RC mode
345 sx1280WriteCommand(SX1280_RADIO_SET_PACKETTYPE, SX1280_PACKET_TYPE_LORA); //Step 2: set packet type to LoRa
346 sx1280ConfigLoraModParams(SX1280_LORA_BW_0800, SX1280_LORA_SF6, SX1280_LORA_CR_4_7); //Step 5: Configure Modulation Params
347 sx1280WriteCommand(SX1280_RADIO_SET_AUTOFS, 0x01); //enable auto FS
348 sx1280WriteRegister(0x0891, (sx1280ReadRegister(0x0891) | 0xC0)); //default is low power mode, switch to high sensitivity instead
349 sx1280SetPacketParams(12, SX1280_LORA_PACKET_IMPLICIT, 8, SX1280_LORA_CRC_OFF, SX1280_LORA_IQ_NORMAL); //default params
350 sx1280SetFrequencyReg(fhssGetInitialFreq(0)); //Step 3: Set Freq
351 sx1280SetFifoAddr(0x00, 0x00); //Step 4: Config FIFO addr
352 sx1280SetDioIrqParams(SX1280_IRQ_RADIO_ALL, SX1280_IRQ_TX_DONE | SX1280_IRQ_RX_DONE, SX1280_IRQ_RADIO_NONE, SX1280_IRQ_RADIO_NONE); //set IRQ to both RXdone/TXdone on DIO1
355 void sx1280Config(const sx1280LoraBandwidths_e bw, const sx1280LoraSpreadingFactors_e sf, const sx1280LoraCodingRates_e cr,
356 const uint32_t freq, const uint8_t preambleLength, const bool iqInverted)
358 sx1280SetMode(SX1280_MODE_SLEEP);
359 sx1280PollBusy();
361 sx1280ConfigLoraDefaults();
362 sx1280SetOutputPower(13); //default is max power (12.5dBm for SX1280 RX)
363 sx1280SetMode(SX1280_MODE_STDBY_RC);
364 sx1280ClearIrqStatus(SX1280_IRQ_RADIO_ALL);
365 sx1280ConfigLoraModParams(bw, sf, cr);
366 sx1280SetPacketParams(preambleLength, SX1280_LORA_PACKET_IMPLICIT, 8, SX1280_LORA_CRC_OFF, (sx1280LoraIqModes_e)((uint8_t)!iqInverted << 6)); // TODO don't make static etc.
367 sx1280SetFrequencyReg(freq);
370 void sx1280SetOutputPower(const int8_t power)
372 uint8_t buf[2];
373 buf[0] = power + 18;
374 buf[1] = (uint8_t) SX1280_RADIO_RAMP_04_US;
375 sx1280WriteCommandBurst(SX1280_RADIO_SET_TXPARAMS, buf, 2);
378 void sx1280SetPacketParams(const uint8_t preambleLength, const sx1280LoraPacketLengthsModes_e headerType, const uint8_t payloadLength,
379 const sx1280LoraCrcModes_e crc, const sx1280LoraIqModes_e invertIQ)
381 uint8_t buf[7];
383 buf[0] = preambleLength;
384 buf[1] = headerType;
385 buf[2] = payloadLength;
386 buf[3] = crc;
387 buf[4] = invertIQ;
388 buf[5] = 0x00;
389 buf[6] = 0x00;
391 sx1280WriteCommandBurst(SX1280_RADIO_SET_PACKETPARAMS, buf, 7);
394 void sx1280SetMode(const sx1280OperatingModes_e opMode)
396 uint8_t buf[3];
398 switch (opMode) {
399 case SX1280_MODE_SLEEP:
400 sx1280WriteCommand(SX1280_RADIO_SET_SLEEP, 0x01);
401 break;
402 case SX1280_MODE_CALIBRATION:
403 break;
404 case SX1280_MODE_STDBY_RC:
405 sx1280WriteCommand(SX1280_RADIO_SET_STANDBY, SX1280_STDBY_RC);
406 break;
407 case SX1280_MODE_STDBY_XOSC:
408 sx1280WriteCommand(SX1280_RADIO_SET_STANDBY, SX1280_STDBY_XOSC);
409 break;
410 case SX1280_MODE_FS:
411 sx1280WriteCommand(SX1280_RADIO_SET_FS, 0x00);
412 break;
413 case SX1280_MODE_RX:
414 buf[0] = 0x00; // periodBase = 1ms, page 71 datasheet, set to FF for cont RX
415 buf[1] = 0xFF;
416 buf[2] = 0xFF;
417 sx1280WriteCommandBurst(SX1280_RADIO_SET_RX, buf, 3);
418 break;
419 case SX1280_MODE_TX:
420 //uses timeout Time-out duration = periodBase * periodBaseCount
421 buf[0] = 0x00; // periodBase = 1ms, page 71 datasheet
422 buf[1] = 0xFF; // no timeout set for now
423 buf[2] = 0xFF; // TODO dynamic timeout based on expected onairtime
424 sx1280WriteCommandBurst(SX1280_RADIO_SET_TX, buf, 3);
425 break;
426 case SX1280_MODE_CAD: // not implemented yet
427 default:
428 break;
432 void sx1280ConfigLoraModParams(const sx1280LoraBandwidths_e bw, const sx1280LoraSpreadingFactors_e sf, const sx1280LoraCodingRates_e cr)
434 // Care must therefore be taken to ensure that modulation parameters are set using the command
435 // SetModulationParam() only after defining the packet type SetPacketType() to be used
437 uint8_t rfparams[3] = {0};
439 rfparams[0] = (uint8_t)sf;
440 rfparams[1] = (uint8_t)bw;
441 rfparams[2] = (uint8_t)cr;
443 sx1280WriteCommandBurst(SX1280_RADIO_SET_MODULATIONPARAMS, rfparams, 3);
445 switch (sf) {
446 case SX1280_LORA_SF5:
447 case SX1280_LORA_SF6:
448 sx1280WriteRegister(0x925, 0x1E); // for SF5 or SF6
449 break;
450 case SX1280_LORA_SF7:
451 case SX1280_LORA_SF8:
452 sx1280WriteRegister(0x925, 0x37); // for SF7 or SF8
453 break;
454 default:
455 sx1280WriteRegister(0x925, 0x32); // for SF9, SF10, SF11, SF12
459 void sx1280SetFrequencyReg(const uint32_t freqReg)
461 uint8_t buf[3] = {0};
463 buf[0] = (uint8_t)((freqReg >> 16) & 0xFF);
464 buf[1] = (uint8_t)((freqReg >> 8) & 0xFF);
465 buf[2] = (uint8_t)(freqReg & 0xFF);
467 sx1280WriteCommandBurst(SX1280_RADIO_SET_RFFREQUENCY, buf, 3);
470 void sx1280AdjustFrequency(int32_t offset, const uint32_t freq)
472 // just a stub to show that frequency adjustment is not used on this chip as opposed to sx127x
473 UNUSED(offset);
474 UNUSED(freq);
477 void sx1280SetFifoAddr(const uint8_t txBaseAddr, const uint8_t rxBaseAddr)
479 uint8_t buf[2];
481 buf[0] = txBaseAddr;
482 buf[1] = rxBaseAddr;
483 sx1280WriteCommandBurst(SX1280_RADIO_SET_BUFFERBASEADDRESS, buf, 2);
486 void sx1280SetDioIrqParams(const uint16_t irqMask, const uint16_t dio1Mask, const uint16_t dio2Mask, const uint16_t dio3Mask)
488 uint8_t buf[8];
490 buf[0] = (uint8_t)((irqMask >> 8) & 0x00FF);
491 buf[1] = (uint8_t)(irqMask & 0x00FF);
492 buf[2] = (uint8_t)((dio1Mask >> 8) & 0x00FF);
493 buf[3] = (uint8_t)(dio1Mask & 0x00FF);
494 buf[4] = (uint8_t)((dio2Mask >> 8) & 0x00FF);
495 buf[5] = (uint8_t)(dio2Mask & 0x00FF);
496 buf[6] = (uint8_t)((dio3Mask >> 8) & 0x00FF);
497 buf[7] = (uint8_t)(dio3Mask & 0x00FF);
499 sx1280WriteCommandBurst(SX1280_RADIO_SET_DIOIRQPARAMS, buf, 8);
502 void sx1280TransmitData(const uint8_t *data, const uint8_t length)
504 sx1280WriteBuffer(0x00, data, length);
505 sx1280SetMode(SX1280_MODE_TX);
508 static uint8_t sx1280GetRxBufferAddr(void)
510 uint8_t status[2] = {0};
511 sx1280ReadCommandBurst(SX1280_RADIO_GET_RXBUFFERSTATUS, status, 2);
512 return status[1];
515 void sx1280ReceiveData(uint8_t *data, const uint8_t length)
517 uint8_t FIFOaddr = sx1280GetRxBufferAddr();
518 sx1280ReadBuffer(FIFOaddr, data, length);
521 void sx1280StartReceiving(void)
523 if (sx1280MarkBusy()) {
524 sx1280SetMode(SX1280_MODE_RX);
525 sx1280MarkFree();
529 void sx1280GetLastPacketStats(int8_t *rssi, int8_t *snr)
531 *rssi = -(int8_t)(packetStats[0] / 2);
532 *snr = (int8_t) packetStats[1];
533 int8_t negOffset = (*snr < 0) ? (*snr / 4) : 0;
534 *rssi += negOffset;
537 void sx1280DoFHSS(void)
539 return;
542 void sx1280ClearIrqStatus(const uint16_t irqMask)
544 uint8_t buf[2];
546 buf[0] = (uint8_t)(((uint16_t)irqMask >> 8) & 0x00FF);
547 buf[1] = (uint8_t)((uint16_t)irqMask & 0x00FF);
549 sx1280WriteCommandBurst(SX1280_RADIO_CLR_IRQSTATUS, buf, 2);
552 // Forward Definitions for DMA Chain //
553 static void sx1280IrqGetStatus(extiCallbackRec_t *cb);
554 static busStatus_e sx1280IrqStatusRead(uint32_t arg);
555 static void sx1280IrqClearStatus(extiCallbackRec_t *cb);
556 static busStatus_e sx1280IrqCmdComplete(uint32_t arg);
557 static void sx1280ProcessIrq(extiCallbackRec_t *cb);
558 static busStatus_e sx1280GotFIFOAddr(uint32_t arg);
559 static void sx1280DoReadBuffer(extiCallbackRec_t *cb);
560 static busStatus_e sx1280ReadBufferComplete(uint32_t arg);
561 static void sx1280GetPacketStats(extiCallbackRec_t *cb);
562 static busStatus_e sx1280GetStatsCmdComplete(uint32_t arg);
563 static busStatus_e sx1280IsFhssReq(uint32_t arg);
564 static void sx1280SetFrequency(extiCallbackRec_t *cb);
565 static busStatus_e sx1280SetFreqComplete(uint32_t arg);
566 static void sx1280StartReceivingDMA(extiCallbackRec_t *cb);
567 static busStatus_e sx1280EnableIRQs(uint32_t arg);
568 static void sx1280SendTelemetryBuffer(extiCallbackRec_t *cb);
569 static busStatus_e sx1280TelemetryComplete(uint32_t arg);
570 static void sx1280StartTransmittingDMA(extiCallbackRec_t *cb);
572 FAST_IRQ_HANDLER void sx1280ISR(void)
574 // Only attempt to access the SX1280 if it is currently idle to avoid any race condition
575 ATOMIC_BLOCK(NVIC_PRIO_RX_INT_EXTI) {
576 if (sx1280EnableBusy()) {
577 pendingISR = false;
578 sx1280SetBusyFn(sx1280IrqGetStatus);
579 } else {
580 pendingISR = true;
585 // Next, the reason for the IRQ must be read
587 FAST_IRQ_HANDLER static void sx1280IrqGetStatus(extiCallbackRec_t *cb)
589 extDevice_t *dev = rxSpiGetDevice();
591 UNUSED(cb);
593 sx1280ClearBusyFn();
595 STATIC_DMA_DATA_AUTO uint8_t irqStatusCmd[] = {SX1280_RADIO_GET_IRQSTATUS, 0, 0, 0};
596 STATIC_DMA_DATA_AUTO uint8_t irqStatus[sizeof(irqStatusCmd)];
598 static busSegment_t segments[] = {
599 {.u.buffers = {irqStatusCmd, irqStatus}, sizeof(irqStatusCmd), true, sx1280IrqStatusRead},
600 {.u.link = {NULL, NULL}, 0, false, NULL},
603 spiSequence(dev, segments);
606 // Read the IRQ status, and save it to irqStatus variable
608 FAST_IRQ_HANDLER static busStatus_e sx1280IrqStatusRead(uint32_t arg)
610 extDevice_t *dev = (extDevice_t *)arg;
612 uint16_t irqStatus = (dev->bus->curSegment->u.buffers.rxData[2] << 8) | dev->bus->curSegment->u.buffers.rxData[3];
614 if (irqStatus & SX1280_IRQ_TX_DONE) {
615 irqReason = ELRS_DIO_TX_DONE;
616 } else if (irqStatus & SX1280_IRQ_RX_DONE) {
617 irqReason = ELRS_DIO_RX_DONE;
618 } else {
619 irqReason = ELRS_DIO_UNKNOWN;
622 sx1280SetBusyFn(sx1280IrqClearStatus);
623 return BUS_READY;
626 // Clear the IRQ bit in the Radio registers
628 FAST_IRQ_HANDLER static void sx1280IrqClearStatus(extiCallbackRec_t *cb)
630 extDevice_t *dev = rxSpiGetDevice();
632 UNUSED(cb);
634 sx1280ClearBusyFn();
636 STATIC_DMA_DATA_AUTO uint8_t irqCmd[] = {SX1280_RADIO_CLR_IRQSTATUS, 0, 0};
638 irqCmd[1] = (uint8_t)(((uint16_t)SX1280_IRQ_RADIO_ALL >> 8) & 0x00FF);
639 irqCmd[2] = (uint8_t)((uint16_t)SX1280_IRQ_RADIO_ALL & 0x00FF);
641 static busSegment_t segments[] = {
642 {.u.buffers = {irqCmd, NULL}, sizeof(irqCmd), true, sx1280IrqCmdComplete},
643 {.u.link = {NULL, NULL}, 0, false, NULL},
646 spiSequence(dev, segments);
649 // Callback follow clear of IRQ status
650 FAST_IRQ_HANDLER static busStatus_e sx1280IrqCmdComplete(uint32_t arg)
652 UNUSED(arg);
654 sx1280SetBusyFn(sx1280ProcessIrq);
656 return BUS_READY;
659 // Process IRQ status
660 FAST_IRQ_HANDLER static void sx1280ProcessIrq(extiCallbackRec_t *cb)
662 extDevice_t *dev = rxSpiGetDevice();
664 UNUSED(cb);
666 sx1280ClearBusyFn();
668 if (irqReason == ELRS_DIO_RX_DONE || irqReason == ELRS_DIO_UNKNOWN) {
669 // Fire off the chain to read and decode the packet from the radio
670 // Get the buffer status to determine the FIFO address
671 STATIC_DMA_DATA_AUTO uint8_t cmdBufStatusCmd[] = {SX1280_RADIO_GET_RXBUFFERSTATUS, 0, 0, 0};
672 STATIC_DMA_DATA_AUTO uint8_t bufStatus[sizeof(cmdBufStatusCmd)];
674 static busSegment_t segments[] = {
675 {.u.buffers = {cmdBufStatusCmd, bufStatus}, sizeof(cmdBufStatusCmd), true, sx1280GotFIFOAddr},
676 {.u.link = {NULL, NULL}, 0, false, NULL},
679 spiSequence(dev, segments);
681 } else {
682 // return to RX mode immediately, the next packet will be an RX and we won't need to FHSS
683 STATIC_DMA_DATA_AUTO uint8_t irqSetRxCmd[] = {SX1280_RADIO_SET_RX, 0, 0xff, 0xff};
685 static busSegment_t segments[] = {
686 {.u.buffers = {irqSetRxCmd, NULL}, sizeof(irqSetRxCmd), true, sx1280EnableIRQs},
687 {.u.link = {NULL, NULL}, 0, false, NULL},
690 spiSequence(dev, segments);
694 // First we read from the FIFO address register to determine the FIFO address
695 static busStatus_e sx1280GotFIFOAddr(uint32_t arg)
697 extDevice_t *dev = (extDevice_t *)arg;
699 FIFOaddr = dev->bus->curSegment->u.buffers.rxData[3];
701 // Wait until no longer busy and read the buffer
702 sx1280SetBusyFn(sx1280DoReadBuffer);
704 return BUS_READY;
707 // Using the addr val stored to the global varable FIFOaddr, read the buffer
708 static void sx1280DoReadBuffer(extiCallbackRec_t *cb)
710 extDevice_t *dev = rxSpiGetDevice();
712 UNUSED(cb);
714 sx1280ClearBusyFn();
716 STATIC_DMA_DATA_AUTO uint8_t cmdReadBuf[] = {SX1280_RADIO_READ_BUFFER, 0, 0};
718 cmdReadBuf[1] = FIFOaddr;
720 static busSegment_t segments[] = {
721 {.u.buffers = {cmdReadBuf, NULL}, sizeof(cmdReadBuf), false, NULL},
722 {.u.buffers = {NULL, NULL}, ELRS_RX_TX_BUFF_SIZE, true, sx1280ReadBufferComplete},
723 {.u.link = {NULL, NULL}, 0, false, NULL},
726 segments[1].u.buffers.rxData = (uint8_t *)expressLrsGetRxBuffer();
728 spiSequence(dev, segments);
731 // Get the Packet Status and RSSI
732 static busStatus_e sx1280ReadBufferComplete(uint32_t arg)
734 UNUSED(arg);
736 sx1280SetBusyFn(sx1280GetPacketStats);
738 return BUS_READY;
741 // Save the Packet Stats to the global variables
742 static void sx1280GetPacketStats(extiCallbackRec_t *cb)
744 UNUSED(cb);
746 extDevice_t *dev = rxSpiGetDevice();
748 sx1280ClearBusyFn();
750 STATIC_DMA_DATA_AUTO uint8_t getStatsCmd[] = {SX1280_RADIO_GET_PACKETSTATUS, 0, 0, 0};
751 STATIC_DMA_DATA_AUTO uint8_t stats[sizeof(getStatsCmd)];
753 static busSegment_t segments[] = {
754 {.u.buffers = {getStatsCmd, stats}, sizeof(getStatsCmd), true, sx1280GetStatsCmdComplete},
755 {.u.link = {NULL, NULL}, 0, false, NULL},
758 spiSequence(dev, segments);
761 // Process and decode the RF packet
762 static busStatus_e sx1280GetStatsCmdComplete(uint32_t arg)
764 extDevice_t *dev = (extDevice_t *)arg;
765 volatile uint8_t *payload = expressLrsGetPayloadBuffer();
767 packetStats[0] = dev->bus->curSegment->u.buffers.rxData[2];
768 packetStats[1] = dev->bus->curSegment->u.buffers.rxData[3];
770 expressLrsSetRfPacketStatus(processRFPacket(payload, rxSpiGetLastExtiTimeUs()));
772 return sx1280IsFhssReq(arg);
775 void sx1280HandleFromTock(void)
777 ATOMIC_BLOCK(NVIC_PRIO_MAX) {
778 if (expressLrsIsFhssReq()) {
779 if (sx1280EnableBusy()) {
780 pendingDoFHSS = false;
781 sx1280SetBusyFn(sx1280SetFrequency);
782 } else {
783 pendingDoFHSS = true;
789 // Next we need to check if we need to FHSS and then do so if needed
790 static busStatus_e sx1280IsFhssReq(uint32_t arg)
792 UNUSED(arg);
794 if (expressLrsIsFhssReq()) {
795 sx1280SetBusyFn(sx1280SetFrequency);
796 } else {
797 sx1280SetFreqComplete(arg);
800 return BUS_READY;
803 // Set the frequency
804 static void sx1280SetFrequency(extiCallbackRec_t *cb)
806 UNUSED(cb);
808 extDevice_t *dev = rxSpiGetDevice();
809 uint32_t currentFreq = expressLrsGetCurrentFreq();
811 sx1280ClearBusyFn();
813 STATIC_DMA_DATA_AUTO uint8_t setFreqCmd[] = {SX1280_RADIO_SET_RFFREQUENCY, 0, 0, 0};
814 setFreqCmd[1] = (uint8_t)((currentFreq >> 16) & 0xFF);
815 setFreqCmd[2] = (uint8_t)((currentFreq >> 8) & 0xFF);
816 setFreqCmd[3] = (uint8_t)(currentFreq & 0xFF);
818 static busSegment_t segments[] = {
819 {.u.buffers = {setFreqCmd, NULL}, sizeof(setFreqCmd), true, sx1280SetFreqComplete},
820 {.u.link = {NULL, NULL}, 0, false, NULL},
823 spiSequence(dev, segments);
826 // Determine if we need to go back to RX or if we need to send TLM data
827 static busStatus_e sx1280SetFreqComplete(uint32_t arg)
829 UNUSED(arg);
831 if (expressLrsTelemRespReq()) {
832 expressLrsDoTelem();
833 // if it's time to do TLM and we have enough to do so
834 sx1280SetBusyFn(sx1280SendTelemetryBuffer);
835 } else {
836 // we don't need to send TLM and we've already FHSS so just hop back into RX mode
837 sx1280SetBusyFn(sx1280StartReceivingDMA);
840 return BUS_READY;
843 // Go back into RX mode
844 static void sx1280StartReceivingDMA(extiCallbackRec_t *cb)
846 UNUSED(cb);
847 extDevice_t *dev = rxSpiGetDevice();
849 sx1280ClearBusyFn();
851 // Issue command to start receiving
852 // periodBase = 1ms, page 71 datasheet, set to FF for cont RX
853 STATIC_DMA_DATA_AUTO uint8_t irqSetRxCmd[] = {SX1280_RADIO_SET_RX, 0, 0xff, 0xff};
855 static busSegment_t segments[] = {
856 {.u.buffers = {irqSetRxCmd, NULL}, sizeof(irqSetRxCmd), true, sx1280EnableIRQs},
857 {.u.link = {NULL, NULL}, 0, false, NULL},
860 spiSequence(dev, segments);
863 static busStatus_e sx1280EnableIRQs(uint32_t arg)
865 UNUSED(arg);
867 // Handle any queued interrupt processing
868 if (pendingISR) {
869 pendingISR = false;
870 sx1280SetBusyFn(sx1280IrqGetStatus);
871 } else if (pendingDoFHSS) {
872 pendingDoFHSS = false;
873 sx1280SetBusyFn(sx1280SetFrequency);
874 } else {
875 // Switch back to waiting for EXTI interrupt
876 sx1280EnableExti();
879 return BUS_READY;
883 // Send telemetry response
884 static void sx1280SendTelemetryBuffer(extiCallbackRec_t *cb)
886 UNUSED(cb);
887 extDevice_t *dev = rxSpiGetDevice();
889 sx1280ClearBusyFn();
891 STATIC_DMA_DATA_AUTO uint8_t writeBufferCmd[] = {SX1280_RADIO_WRITE_BUFFER, 0};
893 static busSegment_t segments[] = {
894 {.u.buffers = {writeBufferCmd, NULL}, sizeof(writeBufferCmd), false, NULL},
895 {.u.buffers = {NULL, NULL}, ELRS_RX_TX_BUFF_SIZE, true, sx1280TelemetryComplete},
896 {.u.link = {NULL, NULL}, 0, false, NULL},
899 segments[1].u.buffers.txData = (uint8_t *)expressLrsGetTelemetryBuffer();
901 spiSequence(dev, segments);
904 static busStatus_e sx1280TelemetryComplete(uint32_t arg)
906 UNUSED(arg);
908 sx1280SetBusyFn(sx1280StartTransmittingDMA);
910 return BUS_READY;
913 static void sx1280StartTransmittingDMA(extiCallbackRec_t *cb)
915 UNUSED(cb);
916 extDevice_t *dev = rxSpiGetDevice();
918 sx1280ClearBusyFn();
920 //uses timeout Time-out duration = periodBase * periodBaseCount
921 // periodBase = 1ms, page 71 datasheet
922 // no timeout set for now
923 // TODO dynamic timeout based on expected onairtime
924 STATIC_DMA_DATA_AUTO uint8_t irqSetRxCmd[] = {SX1280_RADIO_SET_TX, 0, 0xff, 0xff};
926 static busSegment_t segments[] = {
927 {.u.buffers = {irqSetRxCmd, NULL}, sizeof(irqSetRxCmd), true, sx1280EnableIRQs},
928 {.u.link = {NULL, NULL}, 0, false, NULL},
931 spiSequence(dev, segments);
933 #endif /* USE_RX_SX1280 */