Merge pull request #11297 from SteveCEvans/baro_state
[betaflight.git] / src / main / drivers / rx / rx_sx1280.c
blobf0c63549680c0f8fdd896e560d5b73310a856f76
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 "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
44 static IO_t busy;
46 bool sx1280IsBusy(void)
48 return IORead(busy);
51 static bool sx1280PollBusy(void)
53 uint32_t startTime = micros();
54 while (IORead(busy)) {
55 if ((micros() - startTime) > 1000) {
56 return false;
57 } else {
58 __asm__("nop");
61 return true;
64 bool sx1280Init(IO_t resetPin, IO_t busyPin)
67 if (!rxSpiExtiConfigured()) {
68 return false;
71 rxSpiSetNormalSpeedMhz(SX1280_MAX_SPI_MHZ);
72 rxSpiNormalSpeed();
74 if (resetPin) {
75 IOInit(resetPin, OWNER_RX_SPI_EXPRESSLRS_RESET, 0);
76 IOConfigGPIO(resetPin, IOCFG_OUT_PP);
77 } else {
78 resetPin = IO_NONE;
81 if (busyPin) {
82 IOInit(busyPin, OWNER_RX_SPI_EXPRESSLRS_BUSY, 0);
83 IOConfigGPIO(busyPin, IOCFG_IPU);
84 } else {
85 busyPin = IO_NONE;
88 busy = busyPin;
90 IOLo(resetPin);
91 delay(50);
92 IOConfigGPIO(resetPin, IOCFG_IN_FLOATING); // leave floating, internal pullup on sx1280 side
93 delay(20);
95 uint16_t firmwareRev = (((sx1280ReadRegister(REG_LR_FIRMWARE_VERSION_MSB)) << 8) | (sx1280ReadRegister(REG_LR_FIRMWARE_VERSION_MSB + 1)));
97 if ((firmwareRev == 0) || (firmwareRev == 65535)) {
98 return false;
101 return true;
104 uint8_t sx1280ISR(timeUs_t *timeStamp)
106 if (rxSpiPollExti()) {
107 if (rxSpiGetLastExtiTimeUs()) {
108 *timeStamp = rxSpiGetLastExtiTimeUs();
111 uint8_t irqReason;
112 irqReason = sx1280GetIrqReason();
114 rxSpiResetExti();
116 return irqReason;
118 return 0;
121 void sx1280WriteCommand(const uint8_t address, const uint8_t data)
123 sx1280PollBusy();
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);
135 sx1280PollBusy();
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;
144 outBuffer[1] = 0x00;
146 memcpy(outBuffer + 2, data, length);
148 sx1280PollBusy();
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);
163 sx1280PollBusy();
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);
179 outBuffer[3] = 0x00;
181 sx1280PollBusy();
182 rxSpiTransferCommandMulti(&outBuffer[0], size + 4);
183 memcpy(buffer, outBuffer + 4, size);
186 uint8_t sx1280ReadRegister(const uint16_t address)
188 uint8_t data;
189 sx1280ReadRegisterBurst(address, &data, 1);
190 return data;
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);
202 sx1280PollBusy();
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;
212 outBuffer[2] = 0x00;
214 sx1280PollBusy();
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};
222 sx1280PollBusy();
223 rxSpiTransferCommandMulti(&buffer[0], 3);
224 return buffer[0];
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);
244 sx1280PollBusy();
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)
257 uint8_t buf[2];
258 buf[0] = power + 18;
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)
266 uint8_t buf[7];
268 buf[0] = preambleLength;
269 buf[1] = headerType;
270 buf[2] = payloadLength;
271 buf[3] = crc;
272 buf[4] = invertIQ;
273 buf[5] = 0x00;
274 buf[6] = 0x00;
276 sx1280WriteCommandBurst(SX1280_RADIO_SET_PACKETPARAMS, buf, 7);
279 void sx1280SetMode(const sx1280OperatingModes_e opMode)
281 uint8_t buf[3];
283 switch (opMode) {
284 case SX1280_MODE_SLEEP:
285 sx1280WriteCommand(SX1280_RADIO_SET_SLEEP, 0x01);
286 break;
287 case SX1280_MODE_CALIBRATION:
288 break;
289 case SX1280_MODE_STDBY_RC:
290 sx1280WriteCommand(SX1280_RADIO_SET_STANDBY, SX1280_STDBY_RC);
291 break;
292 case SX1280_MODE_STDBY_XOSC:
293 sx1280WriteCommand(SX1280_RADIO_SET_STANDBY, SX1280_STDBY_XOSC);
294 break;
295 case SX1280_MODE_FS:
296 sx1280WriteCommand(SX1280_RADIO_SET_FS, 0x00);
297 break;
298 case SX1280_MODE_RX:
299 buf[0] = 0x00; // periodBase = 1ms, page 71 datasheet, set to FF for cont RX
300 buf[1] = 0xFF;
301 buf[2] = 0xFF;
302 sx1280WriteCommandBurst(SX1280_RADIO_SET_RX, buf, 3);
303 break;
304 case SX1280_MODE_TX:
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);
310 break;
311 case SX1280_MODE_CAD:
312 break;
313 default:
314 break;
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);
331 switch (sf) {
332 case SX1280_LORA_SF5:
333 case SX1280_LORA_SF6:
334 sx1280WriteRegister(0x925, 0x1E); // for SF5 or SF6
335 break;
336 case SX1280_LORA_SF7:
337 case SX1280_LORA_SF8:
338 sx1280WriteRegister(0x925, 0x37); // for SF7 or SF8
339 break;
340 default:
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
371 UNUSED(offset);
372 UNUSED(freq);
375 void sx1280SetFIFOaddr(const uint8_t txBaseAddr, const uint8_t rxBaseAddr)
377 uint8_t buf[2];
379 buf[0] = txBaseAddr;
380 buf[1] = 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)
386 uint8_t buf[8];
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)
402 uint8_t status[2];
404 sx1280ReadCommandBurst(SX1280_RADIO_GET_IRQSTATUS, status, 2);
405 return status[0] << 8 | status[1];
408 void sx1280ClearIrqStatus(const uint16_t irqMask)
410 uint8_t buf[2];
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)) {
423 return 2;
424 } else if ((irqStatus & SX1280_IRQ_RX_DONE)) {
425 return 1;
427 return 0;
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);
440 return status[1];
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)
456 uint8_t status[2];
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 */