Merge pull request #1269 from pkendall64/crsf-max-output
[ExpressLRS.git] / src / lib / SX1280Driver / SX1280_hal.cpp
blob4d540604b16100e7c087015311f30900579996ff
1 /*
2 ______ _
3 / _____) _ | |
4 ( (____ _____ ____ _| |_ _____ ____| |__
5 \____ \| ___ | (_ _) ___ |/ ___) _ \
6 _____) ) ____| | | || |_| ____( (___| | | |
7 (______/|_____)_|_|_| \__)_____)\____)_| |_|
8 (C)2016 Semtech
10 Description: Handling of the node configuration protocol
12 License: Revised BSD License, see LICENSE.TXT file include in the project
14 Maintainer: Miguel Luis, Gregory Cristian and Matthieu Verdy
16 Modified and adapted by Alessandro Carcione for ELRS project
19 #ifndef UNIT_TEST
20 #include "SX1280_Regs.h"
21 #include "SX1280_hal.h"
22 #include <SPI.h>
23 #include "logging.h"
25 SX1280Hal *SX1280Hal::instance = NULL;
27 SX1280Hal::SX1280Hal()
29 instance = this;
32 void SX1280Hal::end()
34 RXenable(); // make sure the TX amp pin is disabled
35 detachInterrupt(GPIO_PIN_DIO1);
36 SPI.end();
37 IsrCallback = nullptr; // remove callbacks
40 void SX1280Hal::init()
42 DBGLN("Hal Init");
43 #if defined(GPIO_PIN_BUSY) && (GPIO_PIN_BUSY != UNDEF_PIN)
44 pinMode(GPIO_PIN_BUSY, INPUT);
45 #endif
46 pinMode(GPIO_PIN_DIO1, INPUT);
47 pinMode(GPIO_PIN_NSS, OUTPUT);
48 digitalWrite(GPIO_PIN_NSS, HIGH);
50 #if defined(GPIO_PIN_PA_ENABLE) && (GPIO_PIN_PA_ENABLE != UNDEF_PIN)
51 DBGLN("Use PA ctrl pin: %d", GPIO_PIN_PA_ENABLE);
52 pinMode(GPIO_PIN_PA_ENABLE, OUTPUT);
53 digitalWrite(GPIO_PIN_PA_ENABLE, LOW);
54 #endif
56 #if defined(GPIO_PIN_PA_SE2622L_ENABLE) && (GPIO_PIN_PA_SE2622L_ENABLE != UNDEF_PIN)
57 DBGLN("Use PA ctrl pin: %d", GPIO_PIN_PA_SE2622L_ENABLE);
58 pinMode(GPIO_PIN_PA_SE2622L_ENABLE, OUTPUT);
59 digitalWrite(GPIO_PIN_PA_SE2622L_ENABLE, LOW);
60 #endif
62 #if defined(GPIO_PIN_TX_ENABLE) && (GPIO_PIN_TX_ENABLE != UNDEF_PIN)
63 DBGLN("Use TX pin: %d", GPIO_PIN_TX_ENABLE);
64 pinMode(GPIO_PIN_TX_ENABLE, OUTPUT);
65 digitalWrite(GPIO_PIN_TX_ENABLE, LOW);
66 #endif
68 #if defined(GPIO_PIN_RX_ENABLE) && (GPIO_PIN_RX_ENABLE != UNDEF_PIN)
69 DBGLN("Use RX pin: %d", GPIO_PIN_RX_ENABLE);
70 pinMode(GPIO_PIN_RX_ENABLE, OUTPUT);
71 digitalWrite(GPIO_PIN_RX_ENABLE, LOW);
72 #endif
74 #if defined(GPIO_PIN_ANT_CTRL_1) && (GPIO_PIN_ANT_CTRL_1 != UNDEF_PIN)
75 pinMode(GPIO_PIN_ANT_CTRL_1, OUTPUT);
76 digitalWrite(GPIO_PIN_ANT_CTRL_1, HIGH);
77 #endif
79 #if defined(GPIO_PIN_ANT_CTRL_2) && (GPIO_PIN_ANT_CTRL_2 != UNDEF_PIN)
80 pinMode(GPIO_PIN_ANT_CTRL_2, OUTPUT);
81 digitalWrite(GPIO_PIN_ANT_CTRL_2, LOW);
82 #endif
84 #ifdef PLATFORM_ESP32
85 SPI.begin(GPIO_PIN_SCK, GPIO_PIN_MISO, GPIO_PIN_MOSI, -1); // sck, miso, mosi, ss (ss can be any GPIO)
86 gpio_pullup_en((gpio_num_t)GPIO_PIN_MISO);
87 SPI.setFrequency(10000000);
88 #endif
90 #ifdef PLATFORM_ESP8266
91 DBGLN("PLATFORM_ESP8266");
92 SPI.begin();
93 SPI.setBitOrder(MSBFIRST);
94 SPI.setDataMode(SPI_MODE0);
95 SPI.setFrequency(10000000);
96 #endif
98 #ifdef PLATFORM_STM32
99 DBGLN("Config SPI");
100 SPI.setMOSI(GPIO_PIN_MOSI);
101 SPI.setMISO(GPIO_PIN_MISO);
102 SPI.setSCLK(GPIO_PIN_SCK);
103 SPI.setBitOrder(MSBFIRST);
104 SPI.setDataMode(SPI_MODE0);
105 SPI.begin();
106 SPI.setClockDivider(SPI_CLOCK_DIV4); // 72 / 8 = 9 MHz
107 #endif
109 //attachInterrupt(digitalPinToInterrupt(GPIO_PIN_BUSY), this->busyISR, CHANGE); //not used atm
110 attachInterrupt(digitalPinToInterrupt(GPIO_PIN_DIO1), this->dioISR, RISING);
113 void SX1280Hal::reset(void)
115 DBGLN("SX1280 Reset");
117 #if defined(GPIO_PIN_RST)
118 pinMode(GPIO_PIN_RST, OUTPUT);
120 delay(50);
121 digitalWrite(GPIO_PIN_RST, LOW);
122 delay(50);
123 digitalWrite(GPIO_PIN_RST, HIGH);
124 #endif
126 #if defined(GPIO_PIN_BUSY) && (GPIO_PIN_BUSY != UNDEF_PIN)
127 while (digitalRead(GPIO_PIN_BUSY) == HIGH) // wait for busy
129 #ifdef PLATFORM_STM32
130 __NOP();
131 #elif PLATFORM_ESP32
132 _NOP();
133 #elif PLATFORM_ESP8266
134 _NOP();
135 #endif
137 #else
138 delay(10); // typically 2ms observed
139 #endif
141 //this->BusyState = SX1280_NOT_BUSY;
142 DBGLN("SX1280 Ready!");
145 void ICACHE_RAM_ATTR SX1280Hal::WriteCommand(SX1280_RadioCommands_t command, uint8_t val)
147 WaitOnBusy();
148 digitalWrite(GPIO_PIN_NSS, LOW);
150 SPI.transfer((uint8_t)command);
151 SPI.transfer(val);
153 digitalWrite(GPIO_PIN_NSS, HIGH);
155 BusyDelay(12);
158 void ICACHE_RAM_ATTR SX1280Hal::WriteCommand(SX1280_RadioCommands_t command, uint8_t *buffer, uint8_t size)
160 WORD_ALIGNED_ATTR uint8_t OutBuffer[size + 1];
162 OutBuffer[0] = (uint8_t)command;
163 memcpy(OutBuffer + 1, buffer, size);
165 WaitOnBusy();
166 digitalWrite(GPIO_PIN_NSS, LOW);
167 SPI.transfer(OutBuffer, (uint8_t)sizeof(OutBuffer));
168 digitalWrite(GPIO_PIN_NSS, HIGH);
170 BusyDelay(12);
173 void ICACHE_RAM_ATTR SX1280Hal::ReadCommand(SX1280_RadioCommands_t command, uint8_t *buffer, uint8_t size)
175 WORD_ALIGNED_ATTR uint8_t OutBuffer[size + 2];
176 #define RADIO_GET_STATUS_BUF_SIZEOF 3 // special case for command == SX1280_RADIO_GET_STATUS, fixed 3 bytes packet size
178 WaitOnBusy();
179 digitalWrite(GPIO_PIN_NSS, LOW);
181 if (command == SX1280_RADIO_GET_STATUS)
183 OutBuffer[0] = (uint8_t)command;
184 OutBuffer[1] = 0x00;
185 OutBuffer[2] = 0x00;
186 SPI.transfer(OutBuffer, RADIO_GET_STATUS_BUF_SIZEOF);
187 buffer[0] = OutBuffer[0];
189 else
191 OutBuffer[0] = (uint8_t)command;
192 OutBuffer[1] = 0x00;
193 memcpy(OutBuffer + 2, buffer, size);
194 SPI.transfer(OutBuffer, sizeof(OutBuffer));
195 memcpy(buffer, OutBuffer + 2, size);
197 digitalWrite(GPIO_PIN_NSS, HIGH);
200 void ICACHE_RAM_ATTR SX1280Hal::WriteRegister(uint16_t address, uint8_t *buffer, uint8_t size)
202 WORD_ALIGNED_ATTR uint8_t OutBuffer[size + 3];
204 OutBuffer[0] = (SX1280_RADIO_WRITE_REGISTER);
205 OutBuffer[1] = ((address & 0xFF00) >> 8);
206 OutBuffer[2] = (address & 0x00FF);
208 memcpy(OutBuffer + 3, buffer, size);
210 WaitOnBusy();
211 digitalWrite(GPIO_PIN_NSS, LOW);
212 SPI.transfer(OutBuffer, (uint8_t)sizeof(OutBuffer));
213 digitalWrite(GPIO_PIN_NSS, HIGH);
215 BusyDelay(12);
218 void ICACHE_RAM_ATTR SX1280Hal::WriteRegister(uint16_t address, uint8_t value)
220 WriteRegister(address, &value, 1);
223 void ICACHE_RAM_ATTR SX1280Hal::ReadRegister(uint16_t address, uint8_t *buffer, uint8_t size)
225 WORD_ALIGNED_ATTR uint8_t OutBuffer[size + 4];
227 OutBuffer[0] = (SX1280_RADIO_READ_REGISTER);
228 OutBuffer[1] = ((address & 0xFF00) >> 8);
229 OutBuffer[2] = (address & 0x00FF);
230 OutBuffer[3] = 0x00;
232 WaitOnBusy();
233 digitalWrite(GPIO_PIN_NSS, LOW);
235 SPI.transfer(OutBuffer, uint8_t(sizeof(OutBuffer)));
236 memcpy(buffer, OutBuffer + 4, size);
238 digitalWrite(GPIO_PIN_NSS, HIGH);
241 uint8_t ICACHE_RAM_ATTR SX1280Hal::ReadRegister(uint16_t address)
243 uint8_t data;
244 ReadRegister(address, &data, 1);
245 return data;
248 void ICACHE_RAM_ATTR SX1280Hal::WriteBuffer(uint8_t offset, volatile uint8_t *buffer, uint8_t size)
250 uint8_t localbuf[size];
252 for (int i = 0; i < size; i++) // todo check if this is the right want to handle volatiles
254 localbuf[i] = buffer[i];
257 WORD_ALIGNED_ATTR uint8_t OutBuffer[size + 2];
259 OutBuffer[0] = SX1280_RADIO_WRITE_BUFFER;
260 OutBuffer[1] = offset;
262 memcpy(OutBuffer + 2, localbuf, size);
264 WaitOnBusy();
266 digitalWrite(GPIO_PIN_NSS, LOW);
267 SPI.transfer(OutBuffer, (uint8_t)sizeof(OutBuffer));
268 digitalWrite(GPIO_PIN_NSS, HIGH);
270 BusyDelay(12);
273 void ICACHE_RAM_ATTR SX1280Hal::ReadBuffer(uint8_t offset, volatile uint8_t *buffer, uint8_t size)
275 WORD_ALIGNED_ATTR uint8_t OutBuffer[size + 3];
276 uint8_t localbuf[size];
278 OutBuffer[0] = SX1280_RADIO_READ_BUFFER;
279 OutBuffer[1] = offset;
280 OutBuffer[2] = 0x00;
282 WaitOnBusy();
283 digitalWrite(GPIO_PIN_NSS, LOW);
285 SPI.transfer(OutBuffer, uint8_t(sizeof(OutBuffer)));
286 digitalWrite(GPIO_PIN_NSS, HIGH);
288 memcpy(localbuf, OutBuffer + 3, size);
290 for (int i = 0; i < size; i++) // todo check if this is the right wany to handle volatiles
292 buffer[i] = localbuf[i];
296 bool ICACHE_RAM_ATTR SX1280Hal::WaitOnBusy()
298 #if defined(GPIO_PIN_BUSY) && (GPIO_PIN_BUSY != UNDEF_PIN)
299 #define wtimeoutUS 1000
300 uint32_t startTime = micros();
302 while (digitalRead(GPIO_PIN_BUSY) == HIGH) // wait untill not busy or until wtimeoutUS
304 if ((micros() - startTime) > wtimeoutUS)
306 //DBGLN("TO");
307 return false;
309 else
311 #ifdef PLATFORM_STM32
312 __NOP();
313 #elif PLATFORM_ESP32
314 _NOP();
315 #elif PLATFORM_ESP8266
316 _NOP();
317 #endif
320 #else
321 // observed BUSY time for Write* calls are 12-20uS after NSS de-assert
322 // and state transitions require extra time depending on prior state
323 if (BusyDelayDuration)
325 while ((micros() - BusyDelayStart) < BusyDelayDuration)
326 #ifdef PLATFORM_STM32
327 __NOP();
328 #elif PLATFORM_ESP32
329 _NOP();
330 #elif PLATFORM_ESP8266
331 _NOP();
332 #endif
333 BusyDelayDuration = 0;
335 // delayMicroseconds(80);
336 #endif
337 return true;
340 void ICACHE_RAM_ATTR SX1280Hal::dioISR()
342 if (instance->IsrCallback)
343 instance->IsrCallback();
346 void ICACHE_RAM_ATTR SX1280Hal::TXenable()
348 #if defined(GPIO_PIN_PA_ENABLE) && (GPIO_PIN_PA_ENABLE != UNDEF_PIN)
349 digitalWrite(GPIO_PIN_PA_ENABLE, HIGH);
350 #endif
351 #if defined(GPIO_PIN_RX_ENABLE) && (GPIO_PIN_RX_ENABLE != UNDEF_PIN)
352 digitalWrite(GPIO_PIN_RX_ENABLE, LOW);
353 #endif
354 #if defined(GPIO_PIN_TX_ENABLE) && (GPIO_PIN_TX_ENABLE != UNDEF_PIN)
355 digitalWrite(GPIO_PIN_TX_ENABLE, HIGH);
356 #endif
357 #if defined(GPIO_PIN_ANT_CTRL_1) && (GPIO_PIN_ANT_CTRL_1 != UNDEF_PIN)
358 digitalWrite(GPIO_PIN_ANT_CTRL_1, HIGH);
359 #endif
360 #if defined(GPIO_PIN_ANT_CTRL_2) && (GPIO_PIN_ANT_CTRL_2 != UNDEF_PIN)
361 digitalWrite(GPIO_PIN_ANT_CTRL_2, LOW);
362 #endif
365 void ICACHE_RAM_ATTR SX1280Hal::RXenable()
367 #if defined(GPIO_PIN_PA_ENABLE) && (GPIO_PIN_PA_ENABLE != UNDEF_PIN)
368 digitalWrite(GPIO_PIN_PA_ENABLE, HIGH);
369 #endif
370 #if defined(GPIO_PIN_RX_ENABLE) && (GPIO_PIN_RX_ENABLE != UNDEF_PIN)
371 digitalWrite(GPIO_PIN_RX_ENABLE, HIGH);
372 #endif
373 #if defined(GPIO_PIN_TX_ENABLE) && (GPIO_PIN_TX_ENABLE != UNDEF_PIN)
374 digitalWrite(GPIO_PIN_TX_ENABLE, LOW);
375 #endif
376 #if defined(GPIO_PIN_ANT_CTRL_1) && (GPIO_PIN_ANT_CTRL_1 != UNDEF_PIN)
377 digitalWrite(GPIO_PIN_ANT_CTRL_1, LOW);
378 #endif
379 #if defined(GPIO_PIN_ANT_CTRL_2) && (GPIO_PIN_ANT_CTRL_2 != UNDEF_PIN)
380 digitalWrite(GPIO_PIN_ANT_CTRL_2, HIGH);
381 #endif
384 void ICACHE_RAM_ATTR SX1280Hal::TXRXdisable()
386 #if defined(GPIO_PIN_RX_ENABLE) && (GPIO_PIN_RX_ENABLE != UNDEF_PIN)
387 digitalWrite(GPIO_PIN_RX_ENABLE, LOW);
388 #endif
389 #if defined(GPIO_PIN_TX_ENABLE) && (GPIO_PIN_TX_ENABLE != UNDEF_PIN)
390 digitalWrite(GPIO_PIN_TX_ENABLE, LOW);
391 #endif
392 #if defined(GPIO_PIN_PA_ENABLE) && (GPIO_PIN_PA_ENABLE != UNDEF_PIN)
393 digitalWrite(GPIO_PIN_PA_ENABLE, LOW);
394 #endif
397 #endif // UNIT_TEST