makes GPIO_PIN_RST optional for the sx1276
[ExpressLRS.git] / src / lib / SX1280Driver / SX1280.cpp
blob0789caf49cf285dc89f6f75c1e3164a8c4571664
1 #include "SX1280_Regs.h"
2 #include "SX1280_hal.h"
3 #include "SX1280.h"
4 #include "logging.h"
6 SX1280Hal hal;
7 SX1280Driver *SX1280Driver::instance = NULL;
9 //DEBUG_SX1280_OTA_TIMING
11 /* Steps for startup
13 1. If not in STDBY_RC mode, then go to this mode by sending the command:
14 SetStandby(STDBY_RC)
16 2. Define the LoRa® packet type by sending the command:
17 SetPacketType(PACKET_TYPE_LORA)
19 3. Define the RF frequency by sending the command:
20 SetRfFrequency(rfFrequency)
21 The LSB of rfFrequency is equal to the PLL step i.e. 52e6/2^18 Hz. SetRfFrequency() defines the Tx frequency.
23 4. Indicate the addresses where the packet handler will read (txBaseAddress in Tx) or write (rxBaseAddress in Rx) the first
24 byte of the data payload by sending the command:
25 SetBufferBaseAddress(txBaseAddress, rxBaseAddress)
26 Note:
27 txBaseAddress and rxBaseAddress are offset relative to the beginning of the data memory map.
29 5. Define the modulation parameter signal BW SF CR
32 #if defined(DEBUG_SX1280_OTA_TIMING)
33 static uint32_t beginTX;
34 static uint32_t endTX;
35 #endif
37 void ICACHE_RAM_ATTR SX1280Driver::nullCallback(void) {}
39 SX1280Driver::SX1280Driver()
41 instance = this;
44 void SX1280Driver::End()
46 SetMode(SX1280_MODE_SLEEP);
47 hal.end();
48 TXdoneCallback = &nullCallback; // remove callbacks
49 RXdoneCallback = &nullCallback;
52 bool SX1280Driver::Begin()
54 hal.init();
55 hal.IsrCallback = &SX1280Driver::IsrCallback;
57 hal.reset();
58 DBGLN("SX1280 Begin");
59 delay(100);
60 uint16_t firmwareRev = (((hal.ReadRegister(REG_LR_FIRMWARE_VERSION_MSB)) << 8) | (hal.ReadRegister(REG_LR_FIRMWARE_VERSION_MSB + 1)));
61 DBGLN("Read Vers: %d", firmwareRev);
62 if ((firmwareRev == 0) || (firmwareRev == 65535))
64 // SPI communication failed, just return without configuration
65 return false;
68 SetMode(SX1280_MODE_STDBY_RC); //Put in STDBY_RC mode
69 hal.WriteCommand(SX1280_RADIO_SET_PACKETTYPE, SX1280_PACKET_TYPE_LORA); //Set packet type to LoRa
70 ConfigLoRaModParams(currBW, currSF, currCR); //Configure Modulation Params
71 hal.WriteCommand(SX1280_RADIO_SET_AUTOFS, 0x01); //Enable auto FS
72 hal.WriteRegister(0x0891, (hal.ReadRegister(0x0891) | 0xC0)); //default is low power mode, switch to high sensitivity instead
73 SetPacketParams(12, SX1280_LORA_PACKET_IMPLICIT, 8, SX1280_LORA_CRC_OFF, SX1280_LORA_IQ_NORMAL); //default params
74 SetFrequencyReg(currFreq); //Set Freq
75 SetFIFOaddr(0x00, 0x00); //Config FIFO addr
76 SetDioIrqParams(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
77 #if defined(USE_SX1280_DCDC)
78 hal.WriteCommand(SX1280_RADIO_SET_REGULATORMODE, 0x01); // Enable DCDC converter instead of LDO
79 #endif
80 return true;
83 void SX1280Driver::Config(SX1280_RadioLoRaBandwidths_t bw, SX1280_RadioLoRaSpreadingFactors_t sf, SX1280_RadioLoRaCodingRates_t cr, uint32_t freq, uint8_t PreambleLength, bool InvertIQ, uint8_t PayloadLength)
85 PayloadLength = PayloadLength;
86 IQinverted = InvertIQ;
87 SetMode(SX1280_MODE_STDBY_XOSC);
88 ConfigLoRaModParams(bw, sf, cr);
89 SetPacketParams(PreambleLength, SX1280_LORA_PACKET_IMPLICIT, PayloadLength, SX1280_LORA_CRC_OFF, (SX1280_RadioLoRaIQModes_t)((uint8_t)!IQinverted << 6)); // TODO don't make static etc. LORA_IQ_STD = 0x40, LORA_IQ_INVERTED = 0x00
90 SetFrequencyReg(freq);
93 void SX1280Driver::SetOutputPower(int8_t power)
95 if (power < -18) power = -18;
96 else if (13 < power) power = 13;
97 uint8_t buf[2] = {(uint8_t)(power + 18), (uint8_t)SX1280_RADIO_RAMP_04_US};
98 hal.WriteCommand(SX1280_RADIO_SET_TXPARAMS, buf, sizeof(buf));
99 DBGLN("SetPower: %d", buf[0]);
100 return;
103 void SX1280Driver::SetPacketParams(uint8_t PreambleLength, SX1280_RadioLoRaPacketLengthsModes_t HeaderType, uint8_t PayloadLength, SX1280_RadioLoRaCrcModes_t crc, SX1280_RadioLoRaIQModes_t InvertIQ)
105 uint8_t buf[7];
107 buf[0] = PreambleLength;
108 buf[1] = HeaderType;
109 buf[2] = PayloadLength;
110 buf[3] = crc;
111 buf[4] = InvertIQ;
112 buf[5] = 0x00;
113 buf[6] = 0x00;
115 hal.WriteCommand(SX1280_RADIO_SET_PACKETPARAMS, buf, sizeof(buf));
118 void SX1280Driver::SetMode(SX1280_RadioOperatingModes_t OPmode)
121 if (OPmode == currOpmode)
123 return;
126 WORD_ALIGNED_ATTR uint8_t buf[3];
127 uint32_t switchDelay = 0;
129 switch (OPmode)
132 case SX1280_MODE_SLEEP:
133 hal.WriteCommand(SX1280_RADIO_SET_SLEEP, 0x01);
134 break;
136 case SX1280_MODE_CALIBRATION:
137 break;
139 case SX1280_MODE_STDBY_RC:
140 hal.WriteCommand(SX1280_RADIO_SET_STANDBY, SX1280_STDBY_RC);
141 switchDelay = 1500;
142 break;
144 case SX1280_MODE_STDBY_XOSC:
145 hal.WriteCommand(SX1280_RADIO_SET_STANDBY, SX1280_STDBY_XOSC);
146 switchDelay = 50;
147 break;
149 case SX1280_MODE_FS:
150 hal.WriteCommand(SX1280_RADIO_SET_FS, 0x00);
151 switchDelay = 70;
152 break;
154 case SX1280_MODE_RX:
155 buf[0] = 0x00; // periodBase = 1ms, page 71 datasheet, set to FF for cont RX
156 buf[1] = 0xFF;
157 buf[2] = 0xFF;
158 hal.WriteCommand(SX1280_RADIO_SET_RX, buf, sizeof(buf));
159 switchDelay = 100;
160 break;
162 case SX1280_MODE_TX:
163 //uses timeout Time-out duration = periodBase * periodBaseCount
164 buf[0] = 0x00; // periodBase = 1ms, page 71 datasheet
165 buf[1] = 0xFF; // no timeout set for now
166 buf[2] = 0xFF; // TODO dynamic timeout based on expected onairtime
167 hal.WriteCommand(SX1280_RADIO_SET_TX, buf, sizeof(buf));
168 switchDelay = 100;
169 break;
171 case SX1280_MODE_CAD:
172 break;
174 default:
175 break;
177 hal.BusyDelay(switchDelay);
179 currOpmode = OPmode;
182 void SX1280Driver::ConfigLoRaModParams(SX1280_RadioLoRaBandwidths_t bw, SX1280_RadioLoRaSpreadingFactors_t sf, SX1280_RadioLoRaCodingRates_t cr)
184 // Care must therefore be taken to ensure that modulation parameters are set using the command
185 // SetModulationParam() only after defining the packet type SetPacketType() to be used
187 WORD_ALIGNED_ATTR uint8_t rfparams[3] = {0};
189 rfparams[0] = (uint8_t)sf;
190 rfparams[1] = (uint8_t)bw;
191 rfparams[2] = (uint8_t)cr;
193 hal.WriteCommand(SX1280_RADIO_SET_MODULATIONPARAMS, rfparams, sizeof(rfparams));
195 switch (sf)
197 case SX1280_LORA_SF5:
198 case SX1280_LORA_SF6:
199 hal.WriteRegister(0x925, 0x1E); // for SF5 or SF6
200 break;
201 case SX1280_LORA_SF7:
202 case SX1280_LORA_SF8:
203 hal.WriteRegister(0x925, 0x37); // for SF7 or SF8
204 break;
205 default:
206 hal.WriteRegister(0x925, 0x32); // for SF9, SF10, SF11, SF12
210 void ICACHE_RAM_ATTR SX1280Driver::SetFrequencyHz(uint32_t Reqfreq)
212 WORD_ALIGNED_ATTR uint8_t buf[3] = {0};
214 uint32_t freq = (uint32_t)((double)Reqfreq / (double)FREQ_STEP);
215 buf[0] = (uint8_t)((freq >> 16) & 0xFF);
216 buf[1] = (uint8_t)((freq >> 8) & 0xFF);
217 buf[2] = (uint8_t)(freq & 0xFF);
219 hal.WriteCommand(SX1280_RADIO_SET_RFFREQUENCY, buf, sizeof(buf));
220 currFreq = Reqfreq;
223 void ICACHE_RAM_ATTR SX1280Driver::SetFrequencyReg(uint32_t freq)
225 WORD_ALIGNED_ATTR uint8_t buf[3] = {0};
227 buf[0] = (uint8_t)((freq >> 16) & 0xFF);
228 buf[1] = (uint8_t)((freq >> 8) & 0xFF);
229 buf[2] = (uint8_t)(freq & 0xFF);
231 hal.WriteCommand(SX1280_RADIO_SET_RFFREQUENCY, buf, sizeof(buf));
232 currFreq = freq;
235 int32_t ICACHE_RAM_ATTR SX1280Driver::GetFrequencyError()
237 WORD_ALIGNED_ATTR uint8_t efeRaw[3] = {0};
238 uint32_t efe = 0;
239 double efeHz = 0.0;
241 efeRaw[0] = hal.ReadRegister(SX1280_REG_LR_ESTIMATED_FREQUENCY_ERROR_MSB);
242 efeRaw[1] = hal.ReadRegister(SX1280_REG_LR_ESTIMATED_FREQUENCY_ERROR_MSB + 1);
243 efeRaw[2] = hal.ReadRegister(SX1280_REG_LR_ESTIMATED_FREQUENCY_ERROR_MSB + 2);
244 efe = (efeRaw[0] << 16) | (efeRaw[1] << 8) | efeRaw[2];
246 efe &= SX1280_REG_LR_ESTIMATED_FREQUENCY_ERROR_MASK;
248 //efeHz = 1.55 * (double)complement2(efe, 20) / (1600.0 / (double)GetLoRaBandwidth() * 1000.0);
249 return efeHz;
252 void SX1280Driver::SetFIFOaddr(uint8_t txBaseAddr, uint8_t rxBaseAddr)
254 uint8_t buf[2];
256 buf[0] = txBaseAddr;
257 buf[1] = rxBaseAddr;
258 hal.WriteCommand(SX1280_RADIO_SET_BUFFERBASEADDRESS, buf, sizeof(buf));
261 void SX1280Driver::SetDioIrqParams(uint16_t irqMask, uint16_t dio1Mask, uint16_t dio2Mask, uint16_t dio3Mask)
263 uint8_t buf[8];
265 buf[0] = (uint8_t)((irqMask >> 8) & 0x00FF);
266 buf[1] = (uint8_t)(irqMask & 0x00FF);
267 buf[2] = (uint8_t)((dio1Mask >> 8) & 0x00FF);
268 buf[3] = (uint8_t)(dio1Mask & 0x00FF);
269 buf[4] = (uint8_t)((dio2Mask >> 8) & 0x00FF);
270 buf[5] = (uint8_t)(dio2Mask & 0x00FF);
271 buf[6] = (uint8_t)((dio3Mask >> 8) & 0x00FF);
272 buf[7] = (uint8_t)(dio3Mask & 0x00FF);
274 hal.WriteCommand(SX1280_RADIO_SET_DIOIRQPARAMS, buf, sizeof(buf));
277 uint16_t ICACHE_RAM_ATTR SX1280Driver::GetIrqStatus()
279 uint8_t status[2];
281 hal.ReadCommand(SX1280_RADIO_GET_IRQSTATUS, status, 2);
282 return status[0] << 8 | status[1];
285 void ICACHE_RAM_ATTR SX1280Driver::ClearIrqStatus(uint16_t irqMask)
287 uint8_t buf[2];
289 buf[0] = (uint8_t)(((uint16_t)irqMask >> 8) & 0x00FF);
290 buf[1] = (uint8_t)((uint16_t)irqMask & 0x00FF);
292 hal.WriteCommand(SX1280_RADIO_CLR_IRQSTATUS, buf, sizeof(buf));
295 void ICACHE_RAM_ATTR SX1280Driver::TXnbISR()
297 currOpmode = SX1280_MODE_FS; // radio goes to FS after TX
298 #ifdef DEBUG_SX1280_OTA_TIMING
299 endTX = micros();
300 DBGLN("TOA: %d", endTX - beginTX);
301 #endif
302 TXdoneCallback();
305 uint8_t FIFOaddr = 0;
307 void ICACHE_RAM_ATTR SX1280Driver::TXnb()
309 if (currOpmode == SX1280_MODE_TX) //catch TX timeout
311 //DBGLN("Timeout!");
312 SetMode(SX1280_MODE_FS);
313 TXnbISR();
314 return;
316 hal.TXenable(); // do first to allow PA stablise
317 hal.WriteBuffer(0x00, TXdataBuffer, PayloadLength); //todo fix offset to equal fifo addr
318 instance->SetMode(SX1280_MODE_TX);
319 #ifdef DEBUG_SX1280_OTA_TIMING
320 beginTX = micros();
321 #endif
324 void ICACHE_RAM_ATTR SX1280Driver::RXnbISR()
326 // In continuous receive mode, the device stays in Rx mode
327 //currOpmode = SX1280_MODE_FS;
328 uint8_t FIFOaddr = GetRxBufferAddr();
329 hal.ReadBuffer(FIFOaddr, RXdataBuffer, PayloadLength);
330 GetLastPacketStats();
331 RXdoneCallback();
334 void ICACHE_RAM_ATTR SX1280Driver::RXnb()
336 hal.RXenable();
337 SetMode(SX1280_MODE_RX);
340 uint8_t ICACHE_RAM_ATTR SX1280Driver::GetRxBufferAddr()
342 WORD_ALIGNED_ATTR uint8_t status[2] = {0};
343 hal.ReadCommand(SX1280_RADIO_GET_RXBUFFERSTATUS, status, 2);
344 return status[1];
347 void ICACHE_RAM_ATTR SX1280Driver::GetStatus()
349 uint8_t status = 0;
350 hal.ReadCommand(SX1280_RADIO_GET_STATUS, (uint8_t *)&status, 1);
351 DBGLN("Status: %x, %x, %x", (0b11100000 & status) >> 5, (0b00011100 & status) >> 2, 0b00000001 & status);
354 bool ICACHE_RAM_ATTR SX1280Driver::GetFrequencyErrorbool()
356 uint8_t regEFI[3];
358 hal.ReadRegister(SX1280_REG_LR_ESTIMATED_FREQUENCY_ERROR_MSB, regEFI, sizeof(regEFI));
360 DBGLN("%d %d %d", regEFI[0], regEFI[1], regEFI[2]);
362 //bool result = (val & 0b00001000) >> 3;
363 //return result; // returns true if pos freq error, neg if false
364 return 0;
367 void ICACHE_RAM_ATTR SX1280Driver::GetLastPacketStats()
369 uint8_t status[2];
371 hal.ReadCommand(SX1280_RADIO_GET_PACKETSTATUS, status, 2);
372 LastPacketRSSI = -(int8_t)(status[0] / 2);
373 LastPacketSNR = (int8_t)status[1] / 4;
376 void ICACHE_RAM_ATTR SX1280Driver::IsrCallback()
378 uint16_t irqStatus = instance->GetIrqStatus();
379 instance->ClearIrqStatus(SX1280_IRQ_RADIO_ALL);
380 if ((irqStatus & SX1280_IRQ_TX_DONE))
381 instance->TXnbISR();
382 else if ((irqStatus & SX1280_IRQ_RX_DONE))
383 instance->RXnbISR();