4 ( (____ _____ ____ _| |_ _____ ____| |__
5 \____ \| ___ | (_ _) ___ |/ ___) _ \
6 _____) ) ____| | | || |_| ____( (___| | | |
7 (______/|_____)_|_|_| \__)_____)\____)_| |_|
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
20 #include "SX1280_Regs.h"
21 #include "SX1280_hal.h"
25 SX1280Hal
*SX1280Hal::instance
= NULL
;
27 SX1280Hal::SX1280Hal()
34 detachInterrupt(GPIO_PIN_DIO1
);
35 if (GPIO_PIN_DIO1_2
!= UNDEF_PIN
)
37 detachInterrupt(GPIO_PIN_DIO1_2
);
40 IsrCallback_1
= nullptr; // remove callbacks
41 IsrCallback_2
= nullptr; // remove callbacks
44 void SX1280Hal::init()
48 if (GPIO_PIN_BUSY
!= UNDEF_PIN
)
50 pinMode(GPIO_PIN_BUSY
, INPUT
);
52 if (GPIO_PIN_BUSY_2
!= UNDEF_PIN
)
54 pinMode(GPIO_PIN_BUSY_2
, INPUT
);
57 pinMode(GPIO_PIN_DIO1
, INPUT
);
58 if (GPIO_PIN_DIO1_2
!= UNDEF_PIN
)
60 pinMode(GPIO_PIN_DIO1_2
, INPUT
);
63 pinMode(GPIO_PIN_NSS
, OUTPUT
);
64 digitalWrite(GPIO_PIN_NSS
, HIGH
);
67 SPIEx
.begin(GPIO_PIN_SCK
, GPIO_PIN_MISO
, GPIO_PIN_MOSI
, GPIO_PIN_NSS
); // sck, miso, mosi, ss (ss can be any GPIO)
68 gpio_pullup_en((gpio_num_t
)GPIO_PIN_MISO
);
69 SPIEx
.setFrequency(17500000);
71 if (GPIO_PIN_NSS_2
!= UNDEF_PIN
)
73 pinMode(GPIO_PIN_NSS_2
, OUTPUT
);
74 digitalWrite(GPIO_PIN_NSS_2
, HIGH
);
75 spiAttachSS(SPIEx
.bus(), 1, GPIO_PIN_NSS_2
);
77 spiEnableSSPins(SPIEx
.bus(), SX12XX_Radio_All
);
78 #elif defined(PLATFORM_ESP8266)
79 DBGLN("PLATFORM_ESP8266");
82 SPIEx
.setBitOrder(MSBFIRST
);
83 SPIEx
.setDataMode(SPI_MODE0
);
84 SPIEx
.setFrequency(17500000);
85 #elif defined(PLATFORM_STM32)
87 SPIEx
.setBitOrder(MSBFIRST
);
88 SPIEx
.setDataMode(SPI_MODE0
);
89 SPIEx
.setMOSI(GPIO_PIN_MOSI
);
90 SPIEx
.setMISO(GPIO_PIN_MISO
);
91 SPIEx
.setSCLK(GPIO_PIN_SCK
);
93 SPIEx
.setClockDivider(SPI_CLOCK_DIV4
); // 72 / 8 = 9 MHz
96 //attachInterrupt(digitalPinToInterrupt(GPIO_PIN_BUSY), this->busyISR, CHANGE); //not used atm
97 attachInterrupt(digitalPinToInterrupt(GPIO_PIN_DIO1
), this->dioISR_1
, RISING
);
98 if (GPIO_PIN_DIO1_2
!= UNDEF_PIN
)
100 attachInterrupt(digitalPinToInterrupt(GPIO_PIN_DIO1_2
), this->dioISR_2
, RISING
);
104 void SX1280Hal::reset(void)
106 DBGLN("SX1280 Reset");
108 if (GPIO_PIN_RST
!= UNDEF_PIN
)
110 pinMode(GPIO_PIN_RST
, OUTPUT
);
111 digitalWrite(GPIO_PIN_RST
, LOW
);
112 if (GPIO_PIN_RST_2
!= UNDEF_PIN
)
114 pinMode(GPIO_PIN_RST_2
, OUTPUT
);
115 digitalWrite(GPIO_PIN_RST_2
, LOW
);
118 digitalWrite(GPIO_PIN_RST
, HIGH
);
119 if (GPIO_PIN_RST_2
!= UNDEF_PIN
)
121 digitalWrite(GPIO_PIN_RST_2
, HIGH
);
123 delay(50); // Safety buffer. Busy takes longer to go low than the 1ms timeout in WaitOnBusy().
126 BusyDelay(10000); // 10ms delay if GPIO_PIN_BUSY is undefined
127 WaitOnBusy(SX12XX_Radio_All
);
129 //this->BusyState = SX1280_NOT_BUSY;
130 DBGLN("SX1280 Ready!");
133 void ICACHE_RAM_ATTR
SX1280Hal::WriteCommand(SX1280_RadioCommands_t command
, uint8_t val
, SX12XX_Radio_Number_t radioNumber
, uint32_t busyDelay
)
135 WriteCommand(command
, &val
, 1, radioNumber
, busyDelay
);
138 void ICACHE_RAM_ATTR
SX1280Hal::WriteCommand(SX1280_RadioCommands_t command
, uint8_t *buffer
, uint8_t size
, SX12XX_Radio_Number_t radioNumber
, uint32_t busyDelay
)
140 WORD_ALIGNED_ATTR
uint8_t OutBuffer
[WORD_PADDED(size
+ 1)] = {
144 memcpy(OutBuffer
+ 1, buffer
, size
);
146 WaitOnBusy(radioNumber
);
147 SPIEx
.write(radioNumber
, OutBuffer
, size
+ 1);
149 BusyDelay(busyDelay
);
152 void ICACHE_RAM_ATTR
SX1280Hal::ReadCommand(SX1280_RadioCommands_t command
, uint8_t *buffer
, uint8_t size
, SX12XX_Radio_Number_t radioNumber
)
154 WORD_ALIGNED_ATTR
uint8_t OutBuffer
[WORD_PADDED(size
+ 2)] = {
160 WaitOnBusy(radioNumber
);
162 if (command
== SX1280_RADIO_GET_STATUS
)
164 const auto RADIO_GET_STATUS_BUF_SIZEOF
= 3; // special case for command == SX1280_RADIO_GET_STATUS, fixed 3 bytes packet size
165 SPIEx
.read(radioNumber
, OutBuffer
, RADIO_GET_STATUS_BUF_SIZEOF
);
166 buffer
[0] = OutBuffer
[0];
170 SPIEx
.read(radioNumber
, OutBuffer
, size
+ 2); // first 2 bytes returned are status!
171 memcpy(buffer
, OutBuffer
+ 2, size
);
175 void ICACHE_RAM_ATTR
SX1280Hal::WriteRegister(uint16_t address
, uint8_t *buffer
, uint8_t size
, SX12XX_Radio_Number_t radioNumber
)
177 WORD_ALIGNED_ATTR
uint8_t OutBuffer
[WORD_PADDED(size
+ 3)] = {
178 SX1280_RADIO_WRITE_REGISTER
,
179 (uint8_t)((address
& 0xFF00) >> 8),
180 (uint8_t)(address
& 0x00FF),
183 memcpy(OutBuffer
+ 3, buffer
, size
);
185 WaitOnBusy(radioNumber
);
186 SPIEx
.write(radioNumber
, OutBuffer
, size
+ 3);
191 void ICACHE_RAM_ATTR
SX1280Hal::WriteRegister(uint16_t address
, uint8_t value
, SX12XX_Radio_Number_t radioNumber
)
193 WriteRegister(address
, &value
, 1, radioNumber
);
196 void ICACHE_RAM_ATTR
SX1280Hal::ReadRegister(uint16_t address
, uint8_t *buffer
, uint8_t size
, SX12XX_Radio_Number_t radioNumber
)
198 WORD_ALIGNED_ATTR
uint8_t OutBuffer
[WORD_PADDED(size
+ 4)] = {
199 SX1280_RADIO_READ_REGISTER
,
200 (uint8_t)((address
& 0xFF00) >> 8),
201 (uint8_t)(address
& 0x00FF),
205 WaitOnBusy(radioNumber
);
207 SPIEx
.read(radioNumber
, OutBuffer
, size
+ 4);
208 memcpy(buffer
, OutBuffer
+ 4, size
);
211 uint8_t ICACHE_RAM_ATTR
SX1280Hal::ReadRegister(uint16_t address
, SX12XX_Radio_Number_t radioNumber
)
214 ReadRegister(address
, &data
, 1, radioNumber
);
218 void ICACHE_RAM_ATTR
SX1280Hal::WriteBuffer(uint8_t offset
, uint8_t *buffer
, uint8_t size
, SX12XX_Radio_Number_t radioNumber
)
220 WORD_ALIGNED_ATTR
uint8_t OutBuffer
[WORD_PADDED(size
+ 2)] = {
221 SX1280_RADIO_WRITE_BUFFER
,
225 memcpy(OutBuffer
+ 2, buffer
, size
);
227 WaitOnBusy(radioNumber
);
229 SPIEx
.write(radioNumber
, OutBuffer
, size
+ 2);
234 void ICACHE_RAM_ATTR
SX1280Hal::ReadBuffer(uint8_t offset
, uint8_t *buffer
, uint8_t size
, SX12XX_Radio_Number_t radioNumber
)
236 WORD_ALIGNED_ATTR
uint8_t OutBuffer
[WORD_PADDED(size
+ 3)] = {
237 SX1280_RADIO_READ_BUFFER
,
242 WaitOnBusy(radioNumber
);
244 SPIEx
.read(radioNumber
, OutBuffer
, size
+ 3);
246 memcpy(buffer
, OutBuffer
+ 3, size
);
249 bool ICACHE_RAM_ATTR
SX1280Hal::WaitOnBusy(SX12XX_Radio_Number_t radioNumber
)
251 if (GPIO_PIN_BUSY
!= UNDEF_PIN
)
253 constexpr uint32_t wtimeoutUS
= 1000U;
254 uint32_t startTime
= 0;
258 if (radioNumber
== SX12XX_Radio_1
)
260 if (digitalRead(GPIO_PIN_BUSY
) == LOW
) return true;
262 else if (radioNumber
== SX12XX_Radio_2
)
264 if (GPIO_PIN_BUSY_2
== UNDEF_PIN
|| digitalRead(GPIO_PIN_BUSY_2
) == LOW
) return true;
266 else if (radioNumber
== SX12XX_Radio_All
)
268 if (GPIO_PIN_BUSY_2
!= UNDEF_PIN
)
270 if (digitalRead(GPIO_PIN_BUSY
) == LOW
&& digitalRead(GPIO_PIN_BUSY_2
) == LOW
) return true;
274 if (digitalRead(GPIO_PIN_BUSY
) == LOW
) return true;
277 // Use this time to call micros().
278 uint32_t now
= micros();
279 if (startTime
== 0) startTime
= now
;
280 if ((now
- startTime
) > wtimeoutUS
) return false;
285 uint32_t now
= micros();
286 while ((now
- BusyDelayStart
) < BusyDelayDuration
)
288 BusyDelayDuration
= 0;
293 void ICACHE_RAM_ATTR
SX1280Hal::dioISR_1()
295 if (instance
->IsrCallback_1
)
296 instance
->IsrCallback_1();
299 void ICACHE_RAM_ATTR
SX1280Hal::dioISR_2()
301 if (instance
->IsrCallback_2
)
302 instance
->IsrCallback_2();