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)
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.
35 #include "drivers/bus_spi.h"
36 #include "drivers/io.h"
37 #include "drivers/io_impl.h"
38 #include "drivers/rx/rx_sx1280.h"
39 #include "drivers/rx/rx_spi.h"
40 #include "drivers/time.h"
42 #define SX1280_MAX_SPI_MHZ 10000000
46 bool sx1280IsBusy(void)
51 static bool sx1280PollBusy(void)
53 uint32_t startTime
= micros();
54 while (IORead(busy
)) {
55 if ((micros() - startTime
) > 1000) {
64 bool sx1280Init(IO_t resetPin
, IO_t busyPin
)
67 if (!rxSpiExtiConfigured()) {
71 rxSpiSetNormalSpeedMhz(SX1280_MAX_SPI_MHZ
);
75 IOInit(resetPin
, OWNER_RX_SPI_EXPRESSLRS_RESET
, 0);
76 IOConfigGPIO(resetPin
, IOCFG_OUT_PP
);
82 IOInit(busyPin
, OWNER_RX_SPI_EXPRESSLRS_BUSY
, 0);
83 IOConfigGPIO(busyPin
, IOCFG_IPU
);
92 IOConfigGPIO(resetPin
, IOCFG_IN_FLOATING
); // leave floating, internal pullup on sx1280 side
95 uint16_t firmwareRev
= (((sx1280ReadRegister(REG_LR_FIRMWARE_VERSION_MSB
)) << 8) | (sx1280ReadRegister(REG_LR_FIRMWARE_VERSION_MSB
+ 1)));
97 if ((firmwareRev
== 0) || (firmwareRev
== 65535)) {
104 uint8_t sx1280ISR(timeUs_t
*timeStamp
)
106 if (rxSpiPollExti()) {
107 if (rxSpiGetLastExtiTimeUs()) {
108 *timeStamp
= rxSpiGetLastExtiTimeUs();
112 irqReason
= sx1280GetIrqReason();
121 void sx1280WriteCommand(const uint8_t address
, const uint8_t data
)
124 rxSpiWriteCommand(address
, data
);
127 void sx1280WriteCommandBurst(const uint8_t address
, const uint8_t *data
, const uint8_t length
)
129 uint8_t outBuffer
[length
+ 1];
131 outBuffer
[0] = address
;
133 memcpy(outBuffer
+ 1, data
, length
);
136 rxSpiTransferCommandMulti(&outBuffer
[0], length
+ 1);
139 void sx1280ReadCommandBurst(const uint8_t address
, uint8_t *data
, const uint8_t length
)
141 uint8_t outBuffer
[length
+ 2];
143 outBuffer
[0] = address
;
146 memcpy(outBuffer
+ 2, data
, length
);
149 rxSpiTransferCommandMulti(&outBuffer
[0], length
+ 2);
150 memcpy(data
, outBuffer
+ 2, length
);
153 void sx1280WriteRegisterBurst(const uint16_t address
, const uint8_t *buffer
, const uint8_t size
)
155 uint8_t outBuffer
[size
+ 3];
157 outBuffer
[0] = (uint8_t) SX1280_RADIO_WRITE_REGISTER
;
158 outBuffer
[1] = ((address
& 0xFF00) >> 8);
159 outBuffer
[2] = (address
& 0x00FF);
161 memcpy(outBuffer
+ 3, buffer
, size
);
164 rxSpiTransferCommandMulti(&outBuffer
[0], size
+ 3);
167 void sx1280WriteRegister(const uint16_t address
, const uint8_t value
)
169 sx1280WriteRegisterBurst(address
, &value
, 1);
172 void sx1280ReadRegisterBurst(const uint16_t address
, uint8_t *buffer
, const uint8_t size
)
174 uint8_t outBuffer
[size
+ 4];
176 outBuffer
[0] = (uint8_t) SX1280_RADIO_READ_REGISTER
;
177 outBuffer
[1] = ((address
& 0xFF00) >> 8);
178 outBuffer
[2] = (address
& 0x00FF);
182 rxSpiTransferCommandMulti(&outBuffer
[0], size
+ 4);
183 memcpy(buffer
, outBuffer
+ 4, size
);
186 uint8_t sx1280ReadRegister(const uint16_t address
)
189 sx1280ReadRegisterBurst(address
, &data
, 1);
193 void sx1280WriteBuffer(const uint8_t offset
, const uint8_t *buffer
, const uint8_t size
)
195 uint8_t outBuffer
[size
+ 2];
197 outBuffer
[0] = (uint8_t) SX1280_RADIO_WRITE_BUFFER
;
198 outBuffer
[1] = offset
;
200 memcpy(outBuffer
+ 2, buffer
, size
);
203 rxSpiTransferCommandMulti(&outBuffer
[0], size
+ 2);
206 void sx1280ReadBuffer(const uint8_t offset
, uint8_t *buffer
, const uint8_t size
)
208 uint8_t outBuffer
[size
+ 3];
210 outBuffer
[0] = (uint8_t) SX1280_RADIO_READ_BUFFER
;
211 outBuffer
[1] = offset
;
215 rxSpiTransferCommandMulti(&outBuffer
[0], size
+ 3);
216 memcpy(buffer
, outBuffer
+ 3, size
);
219 uint8_t sx1280GetStatus(void)
221 uint8_t buffer
[3] = {(uint8_t) SX1280_RADIO_GET_STATUS
, 0, 0};
223 rxSpiTransferCommandMulti(&buffer
[0], 3);
227 void sx1280ConfigLoraDefaults(void)
229 sx1280SetMode(SX1280_MODE_STDBY_RC
); //step 1 put in STDBY_RC mode
230 sx1280WriteCommand(SX1280_RADIO_SET_PACKETTYPE
, SX1280_PACKET_TYPE_LORA
); //Step 2: set packet type to LoRa
231 sx1280ConfigLoraModParams(SX1280_LORA_BW_0800
, SX1280_LORA_SF6
, SX1280_LORA_CR_4_7
); //Step 5: Configure Modulation Params
232 sx1280WriteCommand(SX1280_RADIO_SET_AUTOFS
, 0x01); //enable auto FS
233 sx1280WriteRegister(0x0891, (sx1280ReadRegister(0x0891) | 0xC0)); //default is low power mode, switch to high sensitivity instead
234 sx1280SetPacketParams(12, SX1280_LORA_PACKET_IMPLICIT
, 8, SX1280_LORA_CRC_OFF
, SX1280_LORA_IQ_NORMAL
); //default params
235 sx1280SetFrequencyHZ(2400000000); //Step 3: Set Freq
236 sx1280SetFIFOaddr(0x00, 0x00); //Step 4: Config FIFO addr
237 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
240 void sx1280Config(const sx1280LoraBandwidths_e bw
, const sx1280LoraSpreadingFactors_e sf
, const sx1280LoraCodingRates_e cr
,
241 const uint32_t freq
, const uint8_t preambleLength
, const bool iqInverted
)
243 sx1280SetMode(SX1280_MODE_SLEEP
);
246 sx1280ConfigLoraDefaults();
247 sx1280SetOutputPower(13); //default is max power (12.5dBm for SX1280 RX)
248 sx1280SetMode(SX1280_MODE_STDBY_XOSC
);
249 sx1280ClearIrqStatus(SX1280_IRQ_RADIO_ALL
);
250 sx1280ConfigLoraModParams(bw
, sf
, cr
);
251 sx1280SetPacketParams(preambleLength
, SX1280_LORA_PACKET_IMPLICIT
, 8, SX1280_LORA_CRC_OFF
, (sx1280LoraIqModes_e
)((uint8_t)!iqInverted
<< 6)); // TODO don't make static etc.
252 sx1280SetFrequencyReg(freq
);
255 void sx1280SetOutputPower(const int8_t power
)
259 buf
[1] = (uint8_t) SX1280_RADIO_RAMP_04_US
;
260 sx1280WriteCommandBurst(SX1280_RADIO_SET_TXPARAMS
, buf
, 2);
263 void sx1280SetPacketParams(const uint8_t preambleLength
, const sx1280LoraPacketLengthsModes_e headerType
, const uint8_t payloadLength
,
264 const sx1280LoraCrcModes_e crc
, const sx1280LoraIqModes_e invertIQ
)
268 buf
[0] = preambleLength
;
270 buf
[2] = payloadLength
;
276 sx1280WriteCommandBurst(SX1280_RADIO_SET_PACKETPARAMS
, buf
, 7);
279 void sx1280SetMode(const sx1280OperatingModes_e opMode
)
284 case SX1280_MODE_SLEEP
:
285 sx1280WriteCommand(SX1280_RADIO_SET_SLEEP
, 0x01);
287 case SX1280_MODE_CALIBRATION
:
289 case SX1280_MODE_STDBY_RC
:
290 sx1280WriteCommand(SX1280_RADIO_SET_STANDBY
, SX1280_STDBY_RC
);
292 case SX1280_MODE_STDBY_XOSC
:
293 sx1280WriteCommand(SX1280_RADIO_SET_STANDBY
, SX1280_STDBY_XOSC
);
296 sx1280WriteCommand(SX1280_RADIO_SET_FS
, 0x00);
299 buf
[0] = 0x00; // periodBase = 1ms, page 71 datasheet, set to FF for cont RX
302 sx1280WriteCommandBurst(SX1280_RADIO_SET_RX
, buf
, 3);
305 //uses timeout Time-out duration = periodBase * periodBaseCount
306 buf
[0] = 0x00; // periodBase = 1ms, page 71 datasheet
307 buf
[1] = 0xFF; // no timeout set for now
308 buf
[2] = 0xFF; // TODO dynamic timeout based on expected onairtime
309 sx1280WriteCommandBurst(SX1280_RADIO_SET_TX
, buf
, 3);
311 case SX1280_MODE_CAD
:
318 void sx1280ConfigLoraModParams(const sx1280LoraBandwidths_e bw
, const sx1280LoraSpreadingFactors_e sf
, const sx1280LoraCodingRates_e cr
)
320 // Care must therefore be taken to ensure that modulation parameters are set using the command
321 // SetModulationParam() only after defining the packet type SetPacketType() to be used
323 uint8_t rfparams
[3] = {0};
325 rfparams
[0] = (uint8_t)sf
;
326 rfparams
[1] = (uint8_t)bw
;
327 rfparams
[2] = (uint8_t)cr
;
329 sx1280WriteCommandBurst(SX1280_RADIO_SET_MODULATIONPARAMS
, rfparams
, 3);
332 case SX1280_LORA_SF5
:
333 case SX1280_LORA_SF6
:
334 sx1280WriteRegister(0x925, 0x1E); // for SF5 or SF6
336 case SX1280_LORA_SF7
:
337 case SX1280_LORA_SF8
:
338 sx1280WriteRegister(0x925, 0x37); // for SF7 or SF8
341 sx1280WriteRegister(0x925, 0x32); // for SF9, SF10, SF11, SF12
345 void sx1280SetFrequencyHZ(const uint32_t reqFreq
)
347 uint8_t buf
[3] = {0};
349 uint32_t freq
= (uint32_t)(reqFreq
/ SX1280_FREQ_STEP
);
350 buf
[0] = (uint8_t)((freq
>> 16) & 0xFF);
351 buf
[1] = (uint8_t)((freq
>> 8) & 0xFF);
352 buf
[2] = (uint8_t)(freq
& 0xFF);
354 sx1280WriteCommandBurst(SX1280_RADIO_SET_RFFREQUENCY
, buf
, 3);
357 void sx1280SetFrequencyReg(const uint32_t freq
)
359 uint8_t buf
[3] = {0};
361 buf
[0] = (uint8_t)((freq
>> 16) & 0xFF);
362 buf
[1] = (uint8_t)((freq
>> 8) & 0xFF);
363 buf
[2] = (uint8_t)(freq
& 0xFF);
365 sx1280WriteCommandBurst(SX1280_RADIO_SET_RFFREQUENCY
, buf
, 3);
368 void sx1280AdjustFrequency(int32_t offset
, const uint32_t freq
)
370 // just a stub to show that frequency adjustment is not used on this chip as opposed to sx127x
375 void sx1280SetFIFOaddr(const uint8_t txBaseAddr
, const uint8_t rxBaseAddr
)
381 sx1280WriteCommandBurst(SX1280_RADIO_SET_BUFFERBASEADDRESS
, buf
, 2);
384 void sx1280SetDioIrqParams(const uint16_t irqMask
, const uint16_t dio1Mask
, const uint16_t dio2Mask
, const uint16_t dio3Mask
)
388 buf
[0] = (uint8_t)((irqMask
>> 8) & 0x00FF);
389 buf
[1] = (uint8_t)(irqMask
& 0x00FF);
390 buf
[2] = (uint8_t)((dio1Mask
>> 8) & 0x00FF);
391 buf
[3] = (uint8_t)(dio1Mask
& 0x00FF);
392 buf
[4] = (uint8_t)((dio2Mask
>> 8) & 0x00FF);
393 buf
[5] = (uint8_t)(dio2Mask
& 0x00FF);
394 buf
[6] = (uint8_t)((dio3Mask
>> 8) & 0x00FF);
395 buf
[7] = (uint8_t)(dio3Mask
& 0x00FF);
397 sx1280WriteCommandBurst(SX1280_RADIO_SET_DIOIRQPARAMS
, buf
, 8);
400 uint16_t sx1280GetIrqStatus(void)
404 sx1280ReadCommandBurst(SX1280_RADIO_GET_IRQSTATUS
, status
, 2);
405 return status
[0] << 8 | status
[1];
408 void sx1280ClearIrqStatus(const uint16_t irqMask
)
412 buf
[0] = (uint8_t)(((uint16_t)irqMask
>> 8) & 0x00FF);
413 buf
[1] = (uint8_t)((uint16_t)irqMask
& 0x00FF);
415 sx1280WriteCommandBurst(SX1280_RADIO_CLR_IRQSTATUS
, buf
, 2);
418 uint8_t sx1280GetIrqReason(void)
420 uint16_t irqStatus
= sx1280GetIrqStatus();
421 sx1280ClearIrqStatus(SX1280_IRQ_RADIO_ALL
);
422 if ((irqStatus
& SX1280_IRQ_TX_DONE
)) {
424 } else if ((irqStatus
& SX1280_IRQ_RX_DONE
)) {
430 void sx1280TransmitData(const uint8_t *data
, const uint8_t length
)
432 sx1280WriteBuffer(0x00, data
, length
);
433 sx1280SetMode(SX1280_MODE_TX
);
436 static uint8_t sx1280GetRxBufferAddr(void)
438 uint8_t status
[2] = {0};
439 sx1280ReadCommandBurst(SX1280_RADIO_GET_RXBUFFERSTATUS
, status
, 2);
443 void sx1280ReceiveData(uint8_t *data
, const uint8_t length
)
445 uint8_t FIFOaddr
= sx1280GetRxBufferAddr();
446 sx1280ReadBuffer(FIFOaddr
, data
, length
);
449 void sx1280StartReceiving(void)
451 sx1280SetMode(SX1280_MODE_RX
);
454 void sx1280GetLastPacketStats(int8_t *rssi
, int8_t *snr
)
458 sx1280ReadCommandBurst(SX1280_RADIO_GET_PACKETSTATUS
, status
, 2);
459 *rssi
= -(int8_t)(status
[0] / 2);
460 *snr
= ((int8_t) status
[1]) / 4;
463 #endif /* USE_RX_SX1280 */