xref: /btstack/chipset/sx128x/SMTC_Drivers/sx1280-driver-c/sx1280-hal.c (revision cd5f23a3250874824c01a2b3326a9522fea3f99f)
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 
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 
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 
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 
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 
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
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  */
252 void SX1280HalWaitOnBusy( void )
253 {
254     while( HAL_GPIO_ReadPin( RADIO_BUSY_PORT, RADIO_BUSY_PIN ) == 1 );
255 }
256 
257 void SX1280HalInit( DioIrqHandler **irqHandlers )
258 {
259     SX1280HalReset( );
260     SX1280HalIoIrqInit( irqHandlers );
261 }
262 
263 void HAL_GPIO_EXTI_Callback( uint16_t GPIO_Pin )
264 {
265     dioIrqHandlers[0]();
266 }
267 
268 void SX1280HalIoIrqInit( DioIrqHandler **irqHandlers )
269 {
270     dioIrqHandlers = irqHandlers;
271 }
272 
273 void SX1280HalReset( void )
274 {
275     HAL_Delay( 20 );
276     HAL_GPIO_WritePin( RADIO_nRESET_PORT, RADIO_nRESET_PIN, 0 );
277     HAL_Delay( 50 );
278     HAL_GPIO_WritePin( RADIO_nRESET_PORT, RADIO_nRESET_PIN, 1 );
279     HAL_Delay( 20 );
280 }
281 
282 #if 0
283 // commented out as (3+IRAM_SIZE) > sizeof(halTxBuffer)
284 void SX1280HalClearInstructionRam( void )
285 {
286     // Clearing the instruction RAM is writing 0x00s on every bytes of the
287     // instruction RAM
288     uint16_t halSize = 3 + IRAM_SIZE;
289     halTxBuffer[0] = RADIO_WRITE_REGISTER;
290     halTxBuffer[1] = ( IRAM_START_ADDRESS >> 8 ) & 0x00FF;
291     halTxBuffer[2] = IRAM_START_ADDRESS & 0x00FF;
292     for( uint16_t index = 0; index < IRAM_SIZE; index++ )
293     {
294         halTxBuffer[3+index] = 0x00;
295     }
296 
297     SX1280HalWaitOnBusy( );
298 
299     HAL_GPIO_WritePin( RADIO_NSS_PORT, RADIO_NSS_PIN, 0 );
300 
301 	SX1280HalSpiTxThenRx( halTxBuffer, halSize, NULL, 0);
302 
303     HAL_GPIO_WritePin( RADIO_NSS_PORT, RADIO_NSS_PIN, 1 );
304 
305     SX1280HalWaitOnBusy( );
306 }
307 #endif
308 
309 void SX1280HalWakeup( void )
310 {
311     __disable_irq( );
312 
313     HAL_GPIO_WritePin( RADIO_NSS_PORT, RADIO_NSS_PIN, 0 );
314 
315     uint16_t halSize = 2;
316     halTxBuffer[0] = RADIO_GET_STATUS;
317     halTxBuffer[1] = 0x00;
318 
319 	SX1280HalSpiTxThenRx( halSize, NULL, 0);
320 
321     HAL_GPIO_WritePin( RADIO_NSS_PORT, RADIO_NSS_PIN, 1 );
322 
323     // Wait for chip to be ready.
324     SX1280HalWaitOnBusy( );
325 
326     __enable_irq( );
327 }
328 
329 void SX1280HalWriteCommand( RadioCommands_t command, uint8_t *buffer, uint16_t size )
330 {
331     uint16_t halSize  = size + 1;
332     SX1280HalWaitOnBusy( );
333 
334     HAL_GPIO_WritePin( RADIO_NSS_PORT, RADIO_NSS_PIN, 0 );
335 
336     halTxBuffer[0] = command;
337     memcpy( halTxBuffer + 1, ( uint8_t * )buffer, size * sizeof( uint8_t ) );
338 
339 	SX1280HalSpiTxThenRx( halSize, NULL, 0);
340 
341     HAL_GPIO_WritePin( RADIO_NSS_PORT, RADIO_NSS_PIN, 1 );
342 
343     if( command != RADIO_SET_SLEEP )
344     {
345         SX1280HalWaitOnBusy( );
346     }
347 }
348 
349 void SX1280HalReadCommand( RadioCommands_t command, uint8_t *buffer, uint16_t size )
350 {
351     halTxBuffer[0] = command;
352     halTxBuffer[1] = 0x00;
353 
354     SX1280HalWaitOnBusy( );
355 
356     HAL_GPIO_WritePin( RADIO_NSS_PORT, RADIO_NSS_PIN, 0 );
357 
358 	SX1280HalSpiTxThenRx( 2, buffer, size);
359 
360     HAL_GPIO_WritePin( RADIO_NSS_PORT, RADIO_NSS_PIN, 1 );
361 
362     SX1280HalWaitOnBusy( );
363 }
364 
365 void SX1280HalWriteRegisters( uint16_t address, uint8_t *buffer, uint16_t size )
366 {
367     uint16_t halSize = size + 3;
368     halTxBuffer[0] = RADIO_WRITE_REGISTER;
369     halTxBuffer[1] = ( address & 0xFF00 ) >> 8;
370     halTxBuffer[2] = address & 0x00FF;
371     memcpy( halTxBuffer + 3, buffer, size );
372 
373     SX1280HalWaitOnBusy( );
374 
375     HAL_GPIO_WritePin( RADIO_NSS_PORT, RADIO_NSS_PIN, 0 );
376 
377 	SX1280HalSpiTxThenRx( halSize, NULL, 0);
378 
379     HAL_GPIO_WritePin( RADIO_NSS_PORT, RADIO_NSS_PIN, 1 );
380 
381     SX1280HalWaitOnBusy( );
382 }
383 
384 void SX1280HalWriteRegister( uint16_t address, uint8_t value )
385 {
386     SX1280HalWriteRegisters( address, &value, 1 );
387 }
388 
389 void SX1280HalReadRegisters( uint16_t address, uint8_t *buffer, uint16_t size )
390 {
391     halTxBuffer[0] = RADIO_READ_REGISTER;
392     halTxBuffer[1] = ( address & 0xFF00 ) >> 8;
393     halTxBuffer[2] = address & 0x00FF;
394     halTxBuffer[3] = 0x00;
395 
396     SX1280HalWaitOnBusy( );
397 
398     HAL_GPIO_WritePin( RADIO_NSS_PORT, RADIO_NSS_PIN, 0 );
399 
400 	SX1280HalSpiTxThenRx( 4, buffer, size);
401 
402     HAL_GPIO_WritePin( RADIO_NSS_PORT, RADIO_NSS_PIN, 1 );
403 
404     SX1280HalWaitOnBusy( );
405 }
406 
407 uint8_t SX1280HalReadRegister( uint16_t address )
408 {
409     uint8_t data;
410 
411     SX1280HalReadRegisters( address, &data, 1 );
412 
413     return data;
414 }
415 
416 void SX1280HalWriteBuffer( uint8_t offset, uint8_t *buffer, uint8_t size )
417 {
418     uint16_t halSize = size + 2;
419     halTxBuffer[0] = RADIO_WRITE_BUFFER;
420     halTxBuffer[1] = offset;
421     memcpy( halTxBuffer + 2, buffer, size );
422 
423     SX1280HalWaitOnBusy( );
424 
425     HAL_GPIO_WritePin( RADIO_NSS_PORT, RADIO_NSS_PIN, 0 );
426 
427 	SX1280HalSpiTxThenRx( halSize, NULL, 0);
428 
429     HAL_GPIO_WritePin( RADIO_NSS_PORT, RADIO_NSS_PIN, 1 );
430 
431     SX1280HalWaitOnBusy( );
432 }
433 
434 void SX1280HalReadBuffer( uint8_t offset, uint8_t *buffer, uint8_t size )
435 {
436     halTxBuffer[0] = RADIO_READ_BUFFER;
437     halTxBuffer[1] = offset;
438     halTxBuffer[2] = 0x00;
439 
440     SX1280HalWaitOnBusy( );
441 
442     HAL_GPIO_WritePin( RADIO_NSS_PORT, RADIO_NSS_PIN, 0 );
443 
444 	SX1280HalSpiTxThenRx( 3, buffer, size);
445 
446     HAL_GPIO_WritePin( RADIO_NSS_PORT, RADIO_NSS_PIN, 1 );
447 
448     SX1280HalWaitOnBusy( );
449 }
450 
451 uint8_t SX1280HalGetDioStatus( void )
452 {
453 	uint8_t Status = HAL_GPIO_ReadPin( RADIO_BUSY_PORT, RADIO_BUSY_PIN );
454 
455 #if( RADIO_DIO1_ENABLE )
456 	Status |= (HAL_GPIO_ReadPin( RADIO_DIO1_GPIO_Port, RADIO_DIO1_Pin ) << 1);
457 #endif
458 #if( RADIO_DIO2_ENABLE )
459 	Status |= (HAL_GPIO_ReadPin( RADIO_DIO2_GPIO_Port, RADIO_DIO2_Pin ) << 2);
460 #endif
461 #if( RADIO_DIO3_ENABLE )
462 	Status |= (HAL_GPIO_ReadPin( RADIO_DIO3_GPIO_Port, RADIO_DIO3_Pin ) << 3);
463 #endif
464 #if( !RADIO_DIO1_ENABLE && !RADIO_DIO2_ENABLE && !RADIO_DIO3_ENABLE )
465 #error "Please define a DIO"
466 #endif
467 
468 	return Status;
469 }
470