xref: /btstack/chipset/sx128x/SMTC_Drivers/sx1280-driver-c/sx1280-hal.c (revision 90825e06ef7db74092a42a40bc9e7171996f0f42)
1 /*
2   ______                              _
3  / _____)             _              | |
4 ( (____  _____ ____ _| |_ _____  ____| |__
5  \____ \| ___ |    (_   _) ___ |/ ___)  _ \
6  _____) ) ____| | | || |_| ____( (___| | | |
7 (______/|_____)_|_|_| \__)_____)\____)_| |_|
8     (C)2016 Semtech
9 
10 Description: Handling of the node configuration protocol
11 
12 License: Revised BSD License, see LICENSE.TXT file include in the project
13 
14 Maintainer: Miguel Luis, Matthieu Verdy and Benjamin Boulet
15 */
16 #include "hw.h"
17 #include "sx1280-hal.h"
18 #include "radio.h"
19 #include <string.h>
20 
21 // logging on
22 #include "SEGGER_RTT.h"
23 #define printf(format, ...) SEGGER_RTT_printf(0, format,  ## __VA_ARGS__)
24 
25 // make CubeMX defines usable
26 #ifndef RADIO_BUSY_PORT
27 #define RADIO_BUSY_PORT RADIO_BUSY_GPIO_Port
28 #endif
29 #ifndef RADIO_BUSY_PIN
30 #define RADIO_BUSY_PIN RADIO_BUSY_Pin
31 #endif
32 #ifndef RADIO_nRESET_PORT
33 #define RADIO_nRESET_PORT RADIO_nRESET_GPIO_Port
34 #endif
35 #ifndef RADIO_nRESET_PIN
36 #define RADIO_nRESET_PIN RADIO_nRESET_Pin
37 #endif
38 #ifndef RADIO_NSS_PORT
39 #define RADIO_NSS_PORT RADIO_NSS_GPIO_Port
40 #endif
41 #ifndef RADIO_NSS_PIN
42 #define RADIO_NSS_PIN RADIO_NSS_Pin
43 #endif
44 /*!
45  * \brief Define the size of tx and rx hal buffers
46  *
47  * The Tx and Rx hal buffers are used for SPI communication to
48  * store data to be sent/receive to/from the chip.
49  *
50  * \warning The application must ensure the maximal useful size to be much lower
51  *          than the MAX_HAL_BUFFER_SIZE
52  */
53 #define MAX_HAL_BUFFER_SIZE   0xFFF
54 
55 #define IRQ_HIGH_PRIORITY  0
56 
57 /*!
58  * Radio driver structure initialization
59  */
60 const struct Radio_s Radio =
61 {
62     SX1280Init,
63     SX1280HalReset,
64     SX1280GetStatus,
65     SX1280HalWriteCommand,
66     SX1280HalReadCommand,
67     SX1280HalWriteRegisters,
68     SX1280HalWriteRegister,
69     SX1280HalReadRegisters,
70     SX1280HalReadRegister,
71     SX1280HalWriteBuffer,
72     SX1280HalReadBuffer,
73     SX1280HalGetDioStatus,
74     SX1280GetFirmwareVersion,
75     SX1280SetRegulatorMode,
76     SX1280SetStandby,
77     SX1280SetPacketType,
78     SX1280SetModulationParams,
79     SX1280SetPacketParams,
80     SX1280SetRfFrequency,
81     SX1280SetBufferBaseAddresses,
82     SX1280SetTxParams,
83     SX1280SetDioIrqParams,
84     SX1280SetSyncWord,
85     SX1280SetRx,
86     SX1280GetPayload,
87     SX1280SendPayload,
88     SX1280SetRangingRole,
89     SX1280SetPollingMode,
90     SX1280SetInterruptMode,
91     SX1280SetRegistersDefault,
92     SX1280GetOpMode,
93     SX1280SetSleep,
94     SX1280SetFs,
95     SX1280SetTx,
96     SX1280SetRxDutyCycle,
97     SX1280SetCad,
98     SX1280SetTxContinuousWave,
99     SX1280SetTxContinuousPreamble,
100     SX1280GetPacketType,
101     SX1280SetCadParams,
102     SX1280GetRxBufferStatus,
103     SX1280GetPacketStatus,
104     SX1280GetRssiInst,
105     SX1280GetIrqStatus,
106     SX1280ClearIrqStatus,
107     SX1280Calibrate,
108     SX1280SetSaveContext,
109     SX1280SetAutoTx,
110     SX1280StopAutoTx,
111     SX1280SetAutoFS,
112     SX1280SetLongPreamble,
113     SX1280SetPayload,
114     SX1280SetSyncWordErrorTolerance,
115     SX1280SetCrcSeed,
116     SX1280SetBleAccessAddress,
117     SX1280SetBleAdvertizerAccessAddress,
118     SX1280SetCrcPolynomial,
119     SX1280SetWhiteningSeed,
120     SX1280EnableManualGain,
121     SX1280DisableManualGain,
122     SX1280SetManualGainValue,
123     SX1280SetLNAGainSetting,
124     SX1280SetRangingIdLength,
125     SX1280SetDeviceRangingAddress,
126     SX1280SetRangingRequestAddress,
127     SX1280GetRangingResult,
128     SX1280SetRangingCalibration,
129     SX1280GetRangingPowerDeltaThresholdIndicator,
130     SX1280RangingClearFilterResult,
131     SX1280RangingSetFilterNumSamples,
132     SX1280GetFrequencyError,
133 };
134 
135 // static uint8_t halRxBuffer[MAX_HAL_BUFFER_SIZE];
136 static uint8_t halTxBuffer[MAX_HAL_BUFFER_SIZE];
137 const static uint8_t halZeroBuffer[MAX_HAL_BUFFER_SIZE];
138 static DioIrqHandler **dioIrqHandlers;
139 
140 extern SPI_HandleTypeDef RADIO_SPI_HANDLE;
141 extern DMA_HandleTypeDef RADIO_SPI_DMA_RX;
142 extern DMA_HandleTypeDef RADIO_SPI_DMA_TX;
143 
144 
145 #ifdef USE_BK_SPI
146 
spi_enable(SPI_HandleTypeDef * hspi)147 static void spi_enable(SPI_HandleTypeDef *hspi){
148 	/* Set fiforxthreshold according the reception data length: 8bit */
149 	SET_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
150 
151 	/* Check if the SPI is already enabled */
152 	if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
153 	{
154 		/* Enable SPI peripheral */
155 		__HAL_SPI_ENABLE(hspi);
156 	}
157 }
158 
spi_tx(SPI_HandleTypeDef * hspi,const uint8_t * tx_data,uint16_t tx_len)159 static void spi_tx(SPI_HandleTypeDef *hspi, const uint8_t * tx_data, uint16_t tx_len){
160     // send tx / ignore rx
161     uint8_t tx_byte = *tx_data++;
162     while (tx_len > 0){
163         tx_len--;
164         // while (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE) == 0);
165         *(__IO uint8_t *)&hspi->Instance->DR = tx_byte;
166         tx_byte = *tx_data++;
167         while (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_RXNE) == 0);
168         uint8_t rx_byte = *(__IO uint8_t *)&hspi->Instance->DR;
169         (void) rx_byte;
170     }
171 }
172 
spi_rx(SPI_HandleTypeDef * hspi,uint8_t * rx_buffer,uint16_t rx_len)173 static void spi_rx(SPI_HandleTypeDef *hspi,  uint8_t * rx_buffer, uint16_t rx_len){
174     // send NOP / store rx
175     while (rx_len > 0){
176         rx_len--;
177         // while (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE) == 0);
178         *(__IO uint8_t *)&hspi->Instance->DR = 0;
179         while (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_RXNE) == 0);
180         *rx_buffer++ = *(__IO uint8_t *)&hspi->Instance->DR;
181     }
182 }
183 
spi_tx_only_dma(const uint8_t * tx_data,uint16_t tx_len)184 static void spi_tx_only_dma(const uint8_t * tx_data, uint16_t tx_len) {
185 
186 	HAL_DMA_Start(&RADIO_SPI_DMA_TX, (uintptr_t) tx_data, (uintptr_t) &RADIO_SPI_HANDLE.Instance->DR, tx_len);
187 
188 	/* Enable Tx DMA Request */
189 	SET_BIT(RADIO_SPI_HANDLE.Instance->CR2, SPI_CR2_TXDMAEN);
190 
191 	HAL_DMA_PollForTransfer(&RADIO_SPI_DMA_TX, HAL_DMA_FULL_TRANSFER, HAL_MAX_DELAY);
192 
193 	/* Discard received byte */
194 	(void) RADIO_SPI_HANDLE.Instance->DR;
195 }
196 
spi_tx_rx_dma(const uint8_t * tx_data,uint8_t * rx_buffer,uint16_t size)197 static void spi_tx_rx_dma(const uint8_t * tx_data, uint8_t * rx_buffer, uint16_t size) {
198 
199 	/* Enable Rx DMA Request */
200 	SET_BIT(RADIO_SPI_HANDLE.Instance->CR2, SPI_CR2_RXDMAEN);
201 
202 	HAL_DMA_Start(&RADIO_SPI_DMA_RX, (uintptr_t) &RADIO_SPI_HANDLE.Instance->DR, (uintptr_t) rx_buffer, size);
203 	HAL_DMA_Start(&RADIO_SPI_DMA_TX, (uintptr_t) tx_data, (uintptr_t) &RADIO_SPI_HANDLE.Instance->DR, size);
204 
205 	/* Enable Tx DMA Request */
206 	SET_BIT(RADIO_SPI_HANDLE.Instance->CR2, SPI_CR2_TXDMAEN);
207 
208 	HAL_DMA_PollForTransfer(&RADIO_SPI_DMA_TX, HAL_DMA_FULL_TRANSFER, HAL_MAX_DELAY);
209 	HAL_DMA_PollForTransfer(&RADIO_SPI_DMA_RX, HAL_DMA_FULL_TRANSFER, HAL_MAX_DELAY);
210 }
211 
212 #endif
213 
214 // assert: tx_data == tx_buffer (local call), tx_len > 0
215 // DMA is disabled as one extra byte is read
SX1280HalSpiTxThenRx(uint16_t tx_len,uint8_t * rx_buffer,uint16_t rx_len)216 void SX1280HalSpiTxThenRx(uint16_t tx_len, uint8_t * rx_buffer, uint16_t rx_len){
217 
218 	spi_enable(&RADIO_SPI_HANDLE);
219 
220 	// min size for dma to be faster
221 	const uint16_t dma_min_size_tx = 100;
222 
223 	if (tx_len < dma_min_size_tx) {
224 		// Custom Polling
225 		spi_tx(&RADIO_SPI_HANDLE, halTxBuffer, tx_len);
226 	} else {
227 		// Custom DMA
228 		spi_tx_only_dma( halTxBuffer, tx_len );
229 	}
230 
231 	// 'Flush' Fifo by reading until marked empty
232 	HAL_SPIEx_FlushRxFifo(&RADIO_SPI_HANDLE);
233 
234 	if (rx_len == 0) return;
235 
236 	// min size for dma to be faster
237 	const uint16_t dma_min_size_rx = 100;
238 
239 	if (rx_len < dma_min_size_rx){
240 		// Custom Polling
241 		spi_rx(&RADIO_SPI_HANDLE, rx_buffer, rx_len);
242 	} else {
243 		// Custom DMA
244 		spi_tx_rx_dma( halZeroBuffer, rx_buffer, rx_len);
245 	}
246 }
247 
248 /*!
249  * \brief Used to block execution waiting for low state on radio busy pin.
250  *        Essentially used in SPI communications
251  */
SX1280HalWaitOnBusy(void)252 void SX1280HalWaitOnBusy( void )
253 {
254     while( HAL_GPIO_ReadPin( RADIO_BUSY_PORT, RADIO_BUSY_PIN ) == 1 );
255 }
256 
SX1280HalInit(DioIrqHandler ** irqHandlers)257 void SX1280HalInit( DioIrqHandler **irqHandlers )
258 {
259     SX1280HalReset( );
260     SX1280HalWakeup();
261     SX1280HalIoIrqInit( irqHandlers );
262 }
263 
HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)264 void HAL_GPIO_EXTI_Callback( uint16_t GPIO_Pin )
265 {
266     dioIrqHandlers[0]();
267 }
268 
SX1280HalIoIrqInit(DioIrqHandler ** irqHandlers)269 void SX1280HalIoIrqInit( DioIrqHandler **irqHandlers )
270 {
271     dioIrqHandlers = irqHandlers;
272 }
273 
SX1280HalReset(void)274 void SX1280HalReset( void )
275 {
276     HAL_Delay( 20 );
277     HAL_GPIO_WritePin( RADIO_nRESET_PORT, RADIO_nRESET_PIN, 0 );
278     HAL_Delay( 50 );
279     HAL_GPIO_WritePin( RADIO_nRESET_PORT, RADIO_nRESET_PIN, 1 );
280     HAL_Delay( 20 );
281 }
282 
283 #if 0
284 // commented out as (3+IRAM_SIZE) > sizeof(halTxBuffer)
285 void SX1280HalClearInstructionRam( void )
286 {
287     // Clearing the instruction RAM is writing 0x00s on every bytes of the
288     // instruction RAM
289     uint16_t halSize = 3 + IRAM_SIZE;
290     halTxBuffer[0] = RADIO_WRITE_REGISTER;
291     halTxBuffer[1] = ( IRAM_START_ADDRESS >> 8 ) & 0x00FF;
292     halTxBuffer[2] = IRAM_START_ADDRESS & 0x00FF;
293     for( uint16_t index = 0; index < IRAM_SIZE; index++ )
294     {
295         halTxBuffer[3+index] = 0x00;
296     }
297 
298     SX1280HalWaitOnBusy( );
299 
300     HAL_GPIO_WritePin( RADIO_NSS_PORT, RADIO_NSS_PIN, 0 );
301 
302 	SX1280HalSpiTxThenRx( halTxBuffer, halSize, NULL, 0);
303 
304     HAL_GPIO_WritePin( RADIO_NSS_PORT, RADIO_NSS_PIN, 1 );
305 
306     SX1280HalWaitOnBusy( );
307 }
308 #endif
309 
SX1280HalWakeup(void)310 void SX1280HalWakeup( void )
311 {
312     __disable_irq( );
313 
314     HAL_GPIO_WritePin( RADIO_NSS_PORT, RADIO_NSS_PIN, 0 );
315 
316     uint16_t halSize = 2;
317     halTxBuffer[0] = RADIO_GET_STATUS;
318     halTxBuffer[1] = 0x00;
319 
320 	SX1280HalSpiTxThenRx( halSize, NULL, 0);
321 
322     HAL_GPIO_WritePin( RADIO_NSS_PORT, RADIO_NSS_PIN, 1 );
323 
324     // Wait for chip to be ready.
325     SX1280HalWaitOnBusy( );
326 
327     __enable_irq( );
328 }
329 
SX1280HalWriteCommand(RadioCommands_t command,uint8_t * buffer,uint16_t size)330 void SX1280HalWriteCommand( RadioCommands_t command, uint8_t *buffer, uint16_t size )
331 {
332     uint16_t halSize  = size + 1;
333     SX1280HalWaitOnBusy( );
334 
335     HAL_GPIO_WritePin( RADIO_NSS_PORT, RADIO_NSS_PIN, 0 );
336 
337     halTxBuffer[0] = command;
338     memcpy( halTxBuffer + 1, ( uint8_t * )buffer, size * sizeof( uint8_t ) );
339 
340 	SX1280HalSpiTxThenRx( halSize, NULL, 0);
341 
342     HAL_GPIO_WritePin( RADIO_NSS_PORT, RADIO_NSS_PIN, 1 );
343 
344     if( command != RADIO_SET_SLEEP )
345     {
346         SX1280HalWaitOnBusy( );
347     }
348 }
349 
SX1280HalReadCommand(RadioCommands_t command,uint8_t * buffer,uint16_t size)350 void SX1280HalReadCommand( RadioCommands_t command, uint8_t *buffer, uint16_t size )
351 {
352     halTxBuffer[0] = command;
353     halTxBuffer[1] = 0x00;
354 
355     SX1280HalWaitOnBusy( );
356 
357     HAL_GPIO_WritePin( RADIO_NSS_PORT, RADIO_NSS_PIN, 0 );
358 
359 	SX1280HalSpiTxThenRx( 2, buffer, size);
360 
361     HAL_GPIO_WritePin( RADIO_NSS_PORT, RADIO_NSS_PIN, 1 );
362 
363     SX1280HalWaitOnBusy( );
364 }
365 
SX1280HalWriteRegisters(uint16_t address,uint8_t * buffer,uint16_t size)366 void SX1280HalWriteRegisters( uint16_t address, uint8_t *buffer, uint16_t size )
367 {
368     uint16_t halSize = size + 3;
369     halTxBuffer[0] = RADIO_WRITE_REGISTER;
370     halTxBuffer[1] = ( address & 0xFF00 ) >> 8;
371     halTxBuffer[2] = address & 0x00FF;
372     memcpy( halTxBuffer + 3, buffer, size );
373 
374     SX1280HalWaitOnBusy( );
375 
376     HAL_GPIO_WritePin( RADIO_NSS_PORT, RADIO_NSS_PIN, 0 );
377 
378 	SX1280HalSpiTxThenRx( halSize, NULL, 0);
379 
380     HAL_GPIO_WritePin( RADIO_NSS_PORT, RADIO_NSS_PIN, 1 );
381 
382     SX1280HalWaitOnBusy( );
383 }
384 
SX1280HalWriteRegister(uint16_t address,uint8_t value)385 void SX1280HalWriteRegister( uint16_t address, uint8_t value )
386 {
387     SX1280HalWriteRegisters( address, &value, 1 );
388 }
389 
SX1280HalReadRegisters(uint16_t address,uint8_t * buffer,uint16_t size)390 void SX1280HalReadRegisters( uint16_t address, uint8_t *buffer, uint16_t size )
391 {
392     halTxBuffer[0] = RADIO_READ_REGISTER;
393     halTxBuffer[1] = ( address & 0xFF00 ) >> 8;
394     halTxBuffer[2] = address & 0x00FF;
395     halTxBuffer[3] = 0x00;
396 
397     SX1280HalWaitOnBusy( );
398 
399     HAL_GPIO_WritePin( RADIO_NSS_PORT, RADIO_NSS_PIN, 0 );
400 
401 	SX1280HalSpiTxThenRx( 4, buffer, size);
402 
403     HAL_GPIO_WritePin( RADIO_NSS_PORT, RADIO_NSS_PIN, 1 );
404 
405     SX1280HalWaitOnBusy( );
406 }
407 
SX1280HalReadRegister(uint16_t address)408 uint8_t SX1280HalReadRegister( uint16_t address )
409 {
410     uint8_t data;
411 
412     SX1280HalReadRegisters( address, &data, 1 );
413 
414     return data;
415 }
416 
SX1280HalWriteBuffer(uint8_t offset,uint8_t * buffer,uint8_t size)417 void SX1280HalWriteBuffer( uint8_t offset, uint8_t *buffer, uint8_t size )
418 {
419     uint16_t halSize = size + 2;
420     halTxBuffer[0] = RADIO_WRITE_BUFFER;
421     halTxBuffer[1] = offset;
422     memcpy( halTxBuffer + 2, buffer, size );
423 
424     SX1280HalWaitOnBusy( );
425 
426     HAL_GPIO_WritePin( RADIO_NSS_PORT, RADIO_NSS_PIN, 0 );
427 
428 	SX1280HalSpiTxThenRx( halSize, NULL, 0);
429 
430     HAL_GPIO_WritePin( RADIO_NSS_PORT, RADIO_NSS_PIN, 1 );
431 
432     SX1280HalWaitOnBusy( );
433 }
434 
SX1280HalReadBuffer(uint8_t offset,uint8_t * buffer,uint8_t size)435 void SX1280HalReadBuffer( uint8_t offset, uint8_t *buffer, uint8_t size )
436 {
437     halTxBuffer[0] = RADIO_READ_BUFFER;
438     halTxBuffer[1] = offset;
439     halTxBuffer[2] = 0x00;
440 
441     SX1280HalWaitOnBusy( );
442 
443     HAL_GPIO_WritePin( RADIO_NSS_PORT, RADIO_NSS_PIN, 0 );
444 
445 	SX1280HalSpiTxThenRx( 3, buffer, size);
446 
447     HAL_GPIO_WritePin( RADIO_NSS_PORT, RADIO_NSS_PIN, 1 );
448 
449     SX1280HalWaitOnBusy( );
450 }
451 
SX1280HalGetDioStatus(void)452 uint8_t SX1280HalGetDioStatus( void )
453 {
454 	uint8_t Status = HAL_GPIO_ReadPin( RADIO_BUSY_PORT, RADIO_BUSY_PIN );
455 
456 #if( RADIO_DIO1_ENABLE )
457 	Status |= (HAL_GPIO_ReadPin( RADIO_DIO1_GPIO_Port, RADIO_DIO1_Pin ) << 1);
458 #endif
459 #if( RADIO_DIO2_ENABLE )
460 	Status |= (HAL_GPIO_ReadPin( RADIO_DIO2_GPIO_Port, RADIO_DIO2_Pin ) << 2);
461 #endif
462 #if( RADIO_DIO3_ENABLE )
463 	Status |= (HAL_GPIO_ReadPin( RADIO_DIO3_GPIO_Port, RADIO_DIO3_Pin ) << 3);
464 #endif
465 #if( !RADIO_DIO1_ENABLE && !RADIO_DIO2_ENABLE && !RADIO_DIO3_ENABLE )
466 #error "Please define a DIO"
467 #endif
468 
469 	return Status;
470 }
471