1 /**
2 ******************************************************************************
3 * @file stm32wb0x_hal_radio.h
4 * @author GPM WBL Application Team
5 * @brief This file provides all the Radio Driver APIs.
6 ******************************************************************************
7 * @attention
8 *
9 * Copyright (c) 2024 STMicroelectronics.
10 * All rights reserved.
11 *
12 * This software is licensed under terms that can be found in the LICENSE file
13 * in the root directory of this software component.
14 * If no LICENSE file comes with this software, it is provided AS-IS.
15 *
16 ******************************************************************************
17 */
18
19 /* Includes ------------------------------------------------------------------*/
20 #include "stm32wb0x_hal.h"
21
22 /** @addtogroup STM32WB0x_HAL_Driver
23 * @{
24 */
25
26 /** @addtogroup RADIO
27 * @{
28 */
29
30 /** @defgroup RADIO_Private_Constants RADIO Private Constants
31 * @{
32 */
33
34 #define RSSI_OFFSET 119
35
36 /* Access address used only to sense medium with HAL_RADIO_CarrierSense() */
37 #define FAKE_NETWORK_ID 0xAAAAAAAA
38
39 #define VALIDITY_TAG 0xFCBCECCC
40 #define VALIDITY_LOCATION 0x10001EF8
41 #define MR_TRIMMING_LOCATION 0x10001EE8
42
43 #define MR_BLE_IBIAS_TRIM_Pos (8)
44 #define MR_BLE_IBIAS_TRIM_Msk (0x0F << MR_BLE_IBIAS_TRIM_Pos)
45 #define MR_BLE_IPTAT_TRIM_Pos (12)
46 #define MR_BLE_IPTAT_TRIM_Msk (0x0F << MR_BLE_IPTAT_TRIM_Pos)
47 #define MR_BLE_VBG_TRIM_Pos (16)
48 #define MR_BLE_VBG_TRIM_Msk (0x0F << MR_BLE_VBG_TRIM_Pos)
49 #define MR_BLE_RXADC_DELAY_I_TRIM_Pos (20)
50 #define MR_BLE_RXADC_DELAY_I_TRIM_Msk (0x07 << MR_BLE_RXADC_DELAY_I_TRIM_Pos)
51 #define MR_BLE_RXADC_DELAY_Q_TRIM_Pos (24)
52 #define MR_BLE_RXADC_DELAY_Q_TRIM_Msk (0x07 << MR_BLE_RXADC_DELAY_Q_TRIM_Pos)
53
54 /* AFC Configuration */
55 #define AFC_DELAY_BEFORE (0x05)
56 #define AFC_DELAY_AFTER (0x05)
57 #define CR_GAIN_BEFORE (0x06)
58 #define CR_GAIN_AFTER (0x06)
59 #define CR_LR_GAIN_BEFORE (0x05)
60 #define CR_LR_GAIN_AFTER (0x05)
61 #define LR_RSSI_THR (0x1D)
62 #define LR_PD_THR (0x59)
63 #define LR_AAC_THR (0x32)
64
65 /* Fine tuning values for antenna switching and IQ samplig */
66 #define RX_TIME_TO_SAMPLE (0x1F)
67 #define RX_TIME_TO_SWITCH (0x09)
68
69 /** @defgroup Sequencer_timeouts Sequencer Timeouts
70 * @{
71 */
72
73 /* initDelay */
74 #define INITDELAY_WAKEUP (0x40U)
75 #define INITDELAY_TIMER12_CAL (0x3FU)
76 #define INITDELAY_TIMER2_NOCAL (0x9U)
77
78 /* Init_radio_delay */
79 #if defined (STM32WB05) || defined(STM32WB09 )
80 #define DELAYCHK_TRANSMIT_CAL (0x5AU)
81 #define DELAYCHK_TRANSMIT_NOCAL (0x32U)
82 #define DELAYCHK_RECEIVE_CAL (0x5AU)
83 #define DELAYCHK_RECEIVE_NOCAL (0x32U)
84 #endif
85 #if defined (STM32WB06) || defined (STM32WB07)
86 #define DELAYCHK_TRANSMIT_CAL (0x76U)
87 #define DELAYCHK_TRANSMIT_NOCAL (0x3AU)
88 #define DELAYCHK_RECEIVE_CAL (0x74U)
89 #define DELAYCHK_RECEIVE_NOCAL (0x38U)
90 #endif
91
92 /* ConfigEndDuration */
93 #define CONFIG_END_DURATION (0x14U)
94
95 /* DataInit phase start */
96 #define CHECK_TXDATAREADY (0x5U)
97
98 /* TX parameters init */
99 #if defined (STM32WB05) || defined(STM32WB09 )
100 #define TXREADY_TIMEOUT (0x4U)
101 #endif
102 #if defined (STM32WB06) || defined(STM32WB07)
103 #define TXREADY_TIMEOUT (0x5U)
104 #endif
105 #define TXDELAY_START (0x10U)
106 #define TXDELAY_END (0x10U)
107
108 /* RX parameter init */
109 #define RCV_TIMEOUT (0x100)
110
111 /* Number of state machine used */
112 #define STATEMACHINE_COUNT (CFG_NUM_RADIO_TASKS)
113 /**
114 * @}
115 */
116
117 /**
118 * @}
119 */
120
121
122 /** @defgroup RADIO_Private_Macros RADIO Private Macros
123 * @{
124 */
125 #define IS_STATE_VALID(STATEMACHINE_NO) (STATEMACHINE_NO < STATEMACHINE_COUNT)
126 #define IS_POWERLEVEL_VALID(POWER) (POWER < 0x20)
127 #define IS_RFCHANNEL_VALID(RF_CHANNEL) (RF_CHANNEL <40)
128 #define IS_FREQOFFSET_VALID(FREQ_OFFSET) (FREQ_OFFSET >2)
129 #define IS_PHY_VALID(PHY) (PHY==PHY_1M || PHY==PHY_2M || PHY==PHY_CODED_S_2 || PHY==PHY_CODED_S_8)
130 #define IS_PREALEN_VALID(PREA) (PREA < 16)
131
132
133 #define MASK_INTERRUPTS() __disable_irq();
134 #define UNMASK_INTERRUPTS() __enable_irq();
135
136
137 #define TIME_DIFF(a, b) ((int32_t)(a - b))
138 /**
139 * @}
140 */
141
142 /** @defgroup RADIO_Private_Variables RADIO Private Variables
143 * @{
144 */
145
146 #if USE_RADIO_PROPRIETARY_DRIVER
147
148 RadioGlobalParameters_t globalParameters;
149
150 static ActionPacket aPacket[2];
151 static uint32_t networkID = 0x88DF88DF;
152
153 #endif /* USE_RADIO_PROPRIETARY_DRIVER */
154
155 /**
156 * @}
157 */
158
159 /** @defgroup RADIO_Private_Functions RADIO Private Functions
160 * @{
161 */
162
163 #if USE_RADIO_PROPRIETARY_DRIVER
164
CondRoutineTrue(ActionPacket * p)165 static uint8_t CondRoutineTrue(ActionPacket *p)
166 {
167 return TRUE;
168 }
169
DataRoutineNull(ActionPacket * current_action_packet,ActionPacket * next)170 static uint8_t DataRoutineNull(ActionPacket *current_action_packet, ActionPacket *next)
171 {
172 return TRUE;
173 }
174
CondRoutineRxTrue(ActionPacket * p)175 static uint8_t CondRoutineRxTrue(ActionPacket *p)
176 {
177 /* received a packet */
178 if ((p->status & BLUE_INTERRUPT1REG_RCVOK) != 0)
179 {
180 /* packet received without CRC error */
181 return TRUE;
182 }
183 return FALSE;
184 }
185
186 #endif /* USE_RADIO_PROPRIETARY_DRIVER */
187
188
189 /**
190 * @}
191 */
192
193 /** @defgroup RADIO_Global_Variables RADIO Global Variables
194 * @{
195 */
196
197 /* ------------------------------------------------------------------------------
198 * volatile uint32_t hot_table_radio_config_u32[]
199 *
200 * Hot table radio configuration storage.
201 * This variable is only used during the smart power management
202 * procedure
203 * ------------------------------------------------------------------------------ */
204 /* Round up HOT_TABLE_SIZE to an integer number of words then add 4 words for table management pointers */
205 volatile uint32_t hot_table_radio_config_u32[((HOT_TABLE_SIZE + 3) >> 2) + 4] = {0x00};
206
207 #if 0 /** PATCH: do not define __blue_RAM here */
208 /* BLUE RAM, reserved for radio communication. Not usable from the application */
209 __SECTION(".bss.__blue_RAM")
210 #if defined(STM32WB05) || defined(STM32WB09)
211 __REQUIRED(uint8_t __blue_RAM[CFG_NUM_RADIO_TASKS * 92 + 28]) = {0,};
212 #elif defined(STM32WB06) || defined (STM32WB07)
213 __REQUIRED(uint8_t __blue_RAM[CFG_NUM_RADIO_TASKS * 80 + 28]) = {0,};
214 #else
215 #warning "No Blue RAM allocated"
216 #endif
217 #endif /* ENDOF PATCH */
218
219 /**
220 * @}
221 */
222
223 /** @defgroup RADIO_Exported_Functions RADIO Exported Functions
224 * @{
225 */
226
227 /**
228 * @brief Initializes the radio.
229 * @retval None
230 */
HAL_RADIO_Init(RADIO_HandleTypeDef * hradio)231 void HAL_RADIO_Init(RADIO_HandleTypeDef *hradio)
232 {
233 uint32_t mr_ble_ibias;
234 uint32_t mr_ble_iptat;
235 uint32_t mr_ble_vbg;
236 uint32_t mr_ble_rxadc_delay_i;
237 uint32_t mr_ble_rxadc_delay_q;
238 uint8_t mr_ble_rxadc_delay_flag;
239 uint8_t *hot_table_radio_config = (uint8_t *)&hot_table_radio_config_u32[4];
240 uint8_t index;
241
242 /* Retrieve Trimming values from engineering flash locations */
243 if (*(volatile uint32_t *)VALIDITY_LOCATION == VALIDITY_TAG)
244 {
245 mr_ble_ibias = ((*(volatile uint32_t *)MR_TRIMMING_LOCATION) & MR_BLE_IBIAS_TRIM_Msk) >> MR_BLE_IBIAS_TRIM_Pos;
246 mr_ble_iptat = ((*(volatile uint32_t *)MR_TRIMMING_LOCATION) & MR_BLE_IPTAT_TRIM_Msk) >> MR_BLE_IPTAT_TRIM_Pos;
247 mr_ble_vbg = ((*(volatile uint32_t *)MR_TRIMMING_LOCATION) & MR_BLE_VBG_TRIM_Msk) >> MR_BLE_VBG_TRIM_Pos;
248 mr_ble_rxadc_delay_i = ((*(volatile uint32_t *)MR_TRIMMING_LOCATION) & MR_BLE_RXADC_DELAY_I_TRIM_Msk) >> MR_BLE_RXADC_DELAY_I_TRIM_Pos;
249 mr_ble_rxadc_delay_q = ((*(volatile uint32_t *)MR_TRIMMING_LOCATION) & MR_BLE_RXADC_DELAY_Q_TRIM_Msk) >> MR_BLE_RXADC_DELAY_Q_TRIM_Pos;
250 mr_ble_rxadc_delay_flag = TRUE;
251 }
252 else
253 {
254 mr_ble_ibias = 0x08;
255 mr_ble_iptat = 0x07;
256 mr_ble_vbg = 0x08;
257 mr_ble_rxadc_delay_flag = FALSE;
258 #if defined(STM32WB05) || defined(STM32WB09)
259 mr_ble_rxadc_delay_i = 3;
260 mr_ble_rxadc_delay_q = 3;
261 mr_ble_rxadc_delay_flag = TRUE;
262 #endif /* STM32WB05 or STM32WB09 */
263 }
264
265 BLUEGLOB->BYTE4 = BLUE_IDLE_0;
266 if (hradio != NULL)
267 {
268 HAL_RADIO_MspInit(hradio);
269 }
270 LL_RADIO_TIMER_DisableTimer1(BLUE);
271 LL_RADIO_TIMER_DisableTimer2(BLUE);
272 LL_RADIO_TIMER_DisableBLEWakeupTimer(WAKEUP);
273
274 /* Write Radio Trimming values in the registers: Cbias' VBG, Cbias' IPTAT, Cbias' IBIAS, RxAnaUsr Delay Trim I & Q */
275 MODIFY_REG_FIELD(RRM->CBIAS1_ANA_ENG, RRM_CBIAS1_ANA_ENG_RFD_CBIAS_VBG_TRIM, mr_ble_vbg);
276 MODIFY_REG_FIELD(RRM->CBIAS0_ANA_ENG, RRM_CBIAS0_ANA_ENG_RFD_CBIAS_IPTAT_TRIM, mr_ble_iptat);
277 MODIFY_REG_FIELD(RRM->CBIAS0_ANA_ENG, RRM_CBIAS0_ANA_ENG_RFD_CBIAS_IBIAS_TRIM, mr_ble_ibias);
278 if (mr_ble_rxadc_delay_flag)
279 {
280 MODIFY_REG_FIELD(RRM->RXADC_ANA_USR, RRM_RXADC_ANA_USR_RFD_RXADC_DELAYTRIM_I, mr_ble_rxadc_delay_i);
281 MODIFY_REG_FIELD(RRM->RXADC_ANA_USR, RRM_RXADC_ANA_USR_RFD_RXADC_DELAYTRIM_Q, mr_ble_rxadc_delay_q);
282 }
283
284 /* Radio AFC configuration */
285 MODIFY_REG(RRM->AFC1_DIG_ENG, RRM_AFC1_DIG_ENG_AFC_DELAY_AFTER | RRM_AFC1_DIG_ENG_AFC_DELAY_BEFORE,
286 ((AFC_DELAY_BEFORE << RRM_AFC1_DIG_ENG_AFC_DELAY_BEFORE_Pos) & RRM_AFC1_DIG_ENG_AFC_DELAY_BEFORE_Msk) |
287 ((AFC_DELAY_AFTER << RRM_AFC1_DIG_ENG_AFC_DELAY_AFTER_Pos) & RRM_AFC1_DIG_ENG_AFC_DELAY_AFTER_Msk));
288 MODIFY_REG(RRM->CR0_DIG_ENG, RRM_CR0_DIG_ENG_CR_GAIN_BEFORE | RRM_CR0_DIG_ENG_CR_GAIN_AFTER,
289 ((CR_GAIN_BEFORE << RRM_CR0_DIG_ENG_CR_GAIN_BEFORE_Pos) & RRM_CR0_DIG_ENG_CR_GAIN_BEFORE_Msk) |
290 ((CR_GAIN_AFTER << RRM_CR0_DIG_ENG_CR_GAIN_AFTER_Pos) & RRM_CR0_DIG_ENG_CR_GAIN_AFTER_Msk));
291 MODIFY_REG(RRM->CR0_LR, RRM_CR0_LR_CR_LR_GAIN_BEFORE | RRM_CR0_LR_CR_LR_GAIN_AFTER,
292 ((CR_LR_GAIN_BEFORE << RRM_CR0_LR_CR_LR_GAIN_BEFORE_Pos) & RRM_CR0_LR_CR_LR_GAIN_BEFORE_Msk) |
293 ((CR_LR_GAIN_AFTER << RRM_CR0_LR_CR_LR_GAIN_AFTER_Pos) & RRM_CR0_LR_CR_LR_GAIN_AFTER_Msk));
294
295 /* Radio RSSI Threshold configuration */
296 MODIFY_REG_FIELD(RRM->LR_RSSI_THR_DIG_ENG, RRM_LR_RSSI_THR_DIG_ENG_LR_RSSI_THR, LR_RSSI_THR);
297 MODIFY_REG_FIELD(RRM->LR_PD_THR_DIG_ENG, RRM_LR_PD_THR_DIG_ENG_LR_PD_THR, LR_PD_THR);
298 MODIFY_REG_FIELD(RRM->LR_AAC_THR_DIG_ENG, RRM_LR_AAC_THR_DIG_ENG_LR_AAC_THR, LR_AAC_THR);
299
300 /* Enable Viterbi */
301 SET_BIT(RRM->VIT_CONF_DIG_ENG, RRM_VIT_CONF_DIG_ENG_VIT_CONF_0);
302
303 #if defined(STM32WB05) || defined(STM32WB09)
304 MODIFY_REG_FIELD(RRM->ANTSW_DIG0_USR, RRM_ANTSW0_DIG_USR_RX_TIME_TO_SAMPLE, RX_TIME_TO_SAMPLE);
305 MODIFY_REG_FIELD(RRM->ANTSW_DIG1_USR, RRM_ANTSW1_DIG_USR_RX_TIME_TO_SWITCH, RX_TIME_TO_SWITCH);
306 #endif /* STM32WB05 or STM32WB09 */
307
308 /*Set InitDelay*/
309 LL_RADIO_SetWakeupInitDelay(INITDELAY_WAKEUP);
310 LL_RADIO_SetTimer12InitDelayCal(INITDELAY_TIMER12_CAL);
311 LL_RADIO_SetTimer12InitDelayNoCal(INITDELAY_TIMER2_NOCAL);
312
313 /*Set Init_radio_delay*/
314 LL_RADIO_SetReceivedCalDelayChk(DELAYCHK_RECEIVE_CAL);
315 LL_RADIO_SetReceivedNoCalDelayChk(DELAYCHK_RECEIVE_NOCAL);
316 LL_RADIO_SetTransmitCalDelayChk(DELAYCHK_TRANSMIT_CAL);
317 LL_RADIO_SetTransmitNoCalDelayChk(DELAYCHK_TRANSMIT_NOCAL);
318
319 /* Initial and final TX delays: control the on-air start time of the TX packet
320 * and the length of the packet "tail" after last bit is transmitted
321 */
322 LL_RADIO_SetTxDelayStart(TXDELAY_START);
323 LL_RADIO_SetTxDelayEnd(TXDELAY_END);
324
325 /* Timeout for TX ready signal from the radio FSM after the 2nd init phase
326 * has expired
327 */
328 LL_RADIO_SetTransmissionReadyTimeout(TXREADY_TIMEOUT);
329
330 /* Timing for the various programming phases of the radio, modem and memory
331 * pointers.
332 */
333 LL_RADIO_SetConfigurationEndDuration(CONFIG_END_DURATION);
334 LL_RADIO_SetTxDataReadyCheck(CHECK_TXDATAREADY);
335
336 LL_RADIO_ChkFlagAutoclearEnable_Enable();
337 LL_RADIO_NoActiveLErrorInterrupt_Enable();
338 LL_RADIO_TxRxSkipInterrupt_Enable();
339
340 #if defined(GLOBAL_WORD6_DEFAULTANTENNAID_Msk)
341 LL_RADIO_SetDefaultAntennaID(0);
342 #else
343 /* nothing to do */
344 #endif
345
346 /* The commands in the hot table start at word 4
347 * The words 0 t0 2 are used to point to the command list
348 * for the various trigger events, word 3 is a null command
349 * (see function BLEPLAT_CNTR_SetRadioConfigData)
350 */
351 index = 0;
352 hot_table_radio_config[index++] = 0x01;
353 hot_table_radio_config[index++] = RRM_CBIAS1_ANA_ENG;
354 hot_table_radio_config[index++] = RRM->CBIAS1_ANA_ENG;
355 hot_table_radio_config[index++] = 0x01;
356 hot_table_radio_config[index++] = RRM_CBIAS0_ANA_ENG;
357 hot_table_radio_config[index++] = RRM->CBIAS0_ANA_ENG;
358
359 hot_table_radio_config[index++] = 0x01;
360 hot_table_radio_config[index++] = RRM_RXADC_ANA_USR;
361 hot_table_radio_config[index++] = RRM->RXADC_ANA_USR;
362
363 hot_table_radio_config[index++] = 0x01;
364 hot_table_radio_config[index++] = RRM_AFC1_DIG_ENG;
365 hot_table_radio_config[index++] = RRM->AFC1_DIG_ENG;
366 hot_table_radio_config[index++] = 0x01;
367 hot_table_radio_config[index++] = RRM_CR0_DIG_ENG;
368 hot_table_radio_config[index++] = RRM->CR0_DIG_ENG;
369 hot_table_radio_config[index++] = 0x01;
370 hot_table_radio_config[index++] = RRM_CR0_LR;
371 hot_table_radio_config[index++] = RRM->CR0_LR;
372 hot_table_radio_config[index++] = 0x01;
373 hot_table_radio_config[index++] = RRM_LR_RSSI_THR_DIG_ENG;
374 hot_table_radio_config[index++] = RRM->LR_RSSI_THR_DIG_ENG;
375 hot_table_radio_config[index++] = 0x01;
376 hot_table_radio_config[index++] = RRM_LR_PD_THR_DIG_ENG;
377 hot_table_radio_config[index++] = RRM->LR_PD_THR_DIG_ENG;
378 hot_table_radio_config[index++] = 0x01;
379 hot_table_radio_config[index++] = RRM_LR_AAC_THR_DIG_ENG;
380 hot_table_radio_config[index++] = RRM->LR_AAC_THR_DIG_ENG;
381 hot_table_radio_config[index++] = 0x01;
382 hot_table_radio_config[index++] = RRM_VIT_CONF_DIG_ENG;
383 hot_table_radio_config[index++] = RRM->VIT_CONF_DIG_ENG;
384 #if defined(STM32WB05) || defined(STM32WB09)
385 hot_table_radio_config[index++] = 0x01;
386 hot_table_radio_config[index++] = RRM_ANTSW_DIG0_USR;
387 hot_table_radio_config[index++] = RRM->ANTSW_DIG0_USR;
388 hot_table_radio_config[index++] = 0x01;
389 hot_table_radio_config[index++] = RRM_ANTSW_DIG1_USR;
390 hot_table_radio_config[index++] = RRM->ANTSW_DIG1_USR;
391 #endif
392 hot_table_radio_config[index++] = 0x00;
393
394 hot_table_radio_config_u32[0] = (uint32_t)(&hot_table_radio_config_u32[4]); /* Point to Port 0 command list 1 executed when Wakeup timer triggers */
395 hot_table_radio_config_u32[1] = (uint32_t)(&hot_table_radio_config_u32[4]); /* Point to Port 0 command list 2 executed when Timer1 triggers */
396 hot_table_radio_config_u32[2] = (uint32_t)(&hot_table_radio_config_u32[3]); /* Point to Port 0 command list 3 executed when Timer2 triggers */
397 hot_table_radio_config_u32[3] = 0x00000000; /* Null command */
398
399 LL_RADIO_SetRadioConfigurationAddressPointer(hot_table_radio_config_u32[0]);
400 /* Reload radio config pointer */
401 *(uint32_t *)(RRM_BASE + 0x10U) = 0x01U;
402 LL_RADIO_Active2ErrorInterrupt_Enable();
403
404 #if USE_RADIO_PROPRIETARY_DRIVER
405 globalParameters.back2backTime = BACK_TO_BACK_TIME;
406 globalParameters.tone_start_stop_flag = 0;
407 #endif
408
409 /*Clear all interrupts of the BLUE Controller*/
410 uint32_t int_val_tmp = BLUE->INTERRUPT1REG;
411 BLUE->INTERRUPT1REG = int_val_tmp;
412
413 /*BLE wake up IRQ Status clearing and enable*/
414 WAKEUP->WAKEUP_BLE_IRQ_STATUS |= 1;
415 WAKEUP->WAKEUP_BLE_IRQ_ENABLE |= 1;
416
417 /* If the device is configured with
418 System clock = 64 MHz and BLE clock = 16 MHz
419 a register read is necessary to end fine
420 the clear interrupt register operation,
421 due the AHB down converter latency */
422 int_val_tmp = BLUE->INTERRUPT1REG;
423
424 return;
425 }
426
427 /**
428 * @brief Read RSSI
429 * @retval int8_t: RSSI in dBm
430 */
HAL_RADIO_ReadRSSI(void)431 int8_t HAL_RADIO_ReadRSSI(void)
432 {
433 int32_t rssi_dbm;
434 uint32_t rssi0 = RRM->RSSI0_DIG_OUT;
435 uint32_t rssi1 = RRM->RSSI1_DIG_OUT;
436
437 uint32_t rssi_int16 = ((rssi1 & 0xFF) << 8) | (rssi0 & 0xFF);
438 uint32_t reg_agc = RRM->AGC_DIG_OUT;
439
440 if ((rssi_int16 == 0U) || (reg_agc > 0xbU))
441 {
442 rssi_dbm = 127 ;
443 }
444 else
445 {
446 rssi_dbm = (int32_t)reg_agc * 6 - RSSI_OFFSET;//127 ;
447 while (rssi_int16 > 30U)
448 {
449 rssi_dbm = rssi_dbm + 6 ;
450 rssi_int16 = (rssi_int16 >> 1) ;
451 }
452 rssi_dbm = rssi_dbm + (int32_t)(uint32_t)((417U * rssi_int16 + 18080U) >> 10);
453 }
454 return (int8_t)rssi_dbm;
455 }
456
457 #if USE_RADIO_PROPRIETARY_DRIVER
458
459 /**
460 * @brief This routine is called when a RADIO event is complete.
461 * @param p: Current action packet which its transaction has been completed.
462 * @param next: Next action packet which is going to be scheduled.
463 * @retval return value: TRUE
464 */
HAL_RADIO_Callback(ActionPacket * p,ActionPacket * next)465 uint8_t HAL_RADIO_Callback(ActionPacket *p, ActionPacket *next)
466 {
467 /* Event is a reception */
468 if ((p->status & BLUE_STATUSREG_PREVTRANSMIT) == 0)
469 {
470 RxStats_t receivedStats = {0};
471 /* Reception ends with no errors */
472 if ((p->status & BLUE_INTERRUPT1REG_RCVOK) != 0)
473 {
474 if ((p->status & BLUE_INTERRUPT1REG_ENCERROR) != 0)
475 {
476 receivedStats.rssi = p->rssi;
477 receivedStats.timestamp_receive = p->timestamp_receive;
478 HAL_RADIO_CallbackRcvEncryptErr(&receivedStats);
479 }
480 else
481 {
482 receivedStats.rssi = p->rssi;
483 receivedStats.timestamp_receive = p->timestamp_receive;
484 HAL_RADIO_CallbackRcvOk(&receivedStats);
485 }
486 }
487 /* Reception ends with timeout */
488 else if ((p->status & BLUE_INTERRUPT1REG_RCVTIMEOUT) != 0)
489 {
490 receivedStats.rssi = p->rssi;
491 receivedStats.timestamp_receive = 0;
492 HAL_RADIO_CallbackRcvTimeout(&receivedStats);
493 }
494 /* Reception ends with errors */
495 else if ((p->status & BLUE_INTERRUPT1REG_RCVCRCERR) != 0)
496 {
497 receivedStats.rssi = p->rssi;
498 receivedStats.timestamp_receive = p->timestamp_receive;
499 HAL_RADIO_CallbackRcvError(&receivedStats);
500 }
501 }
502 /* Event is a transmission */
503 else if ((p->status & BLUE_INTERRUPT1REG_DONE) != 0)
504 {
505 /* RADIO TX operation done */
506 HAL_RADIO_CallbackTxDone();
507 }
508 return TRUE;
509 }
510
HAL_RADIO_CallbackRcvError(RxStats_t * rxPacketStats)511 __weak void HAL_RADIO_CallbackRcvError(RxStats_t *rxPacketStats) {}
HAL_RADIO_CallbackRcvTimeout(RxStats_t * rxPacketStats)512 __weak void HAL_RADIO_CallbackRcvTimeout(RxStats_t *rxPacketStats) {}
HAL_RADIO_CallbackRcvEncryptErr(RxStats_t * rxPacketStats)513 __weak void HAL_RADIO_CallbackRcvEncryptErr(RxStats_t *rxPacketStats) {}
HAL_RADIO_CallbackRcvOk(RxStats_t * rxPacketStats)514 __weak void HAL_RADIO_CallbackRcvOk(RxStats_t *rxPacketStats) {}
HAL_RADIO_CallbackTxDone(void)515 __weak void HAL_RADIO_CallbackTxDone(void) {}
516
517 /**
518 * @brief Radio ISR.
519 * Besides, next packet is scheduled here.
520 * @retval None
521 */
HAL_RADIO_ActionPacketIsr(uint32_t int_flags)522 static void HAL_RADIO_ActionPacketIsr(uint32_t int_flags)
523 {
524 if ((int_flags & BLUE_INTERRUPT1REG_DONE) != 0)
525 {
526
527 ActionPacket *next, *actionPacketBackup;
528 BlueTransStruct *p;
529 uint32_t time;
530
531 /* Copy status in order for callback to access it. */
532 globalParameters.current_action_packet->status = int_flags | \
533 (BLUE->STATUSREG & BLUE_STATUSREG_PREVTRANSMIT_Msk);
534
535 if ((globalParameters.current_action_packet->condRoutine(globalParameters.current_action_packet)) == TRUE)
536 {
537 next = globalParameters.current_action_packet->next_true;
538 }
539 else
540 {
541 next = globalParameters.current_action_packet->next_false;
542 }
543 /*The radio event is started. So here a check on the next packet of the event is made*/
544 if (next == NULL_0)
545 {
546 /* timer2 off */
547 LL_RADIO_TIMER_DisableTimer1(BLUE);
548 LL_RADIO_TIMER_DisableTimer2(BLUE);
549 LL_RADIO_TIMER_DisableBLEWakeupTimer(WAKEUP);
550 MODIFY_REG(BLUEGLOB->BYTE4, GLOBAL_BYTE4_ACTIVE_Msk, BLUE_IDLE_0);
551 }
552 else
553 {
554 BLUEGLOB->BYTE4 = (next->StateMachineNo | GLOBAL_BYTE4_ACTIVE_Msk);
555 p = &next->trans_packet;
556 MODIFY_REG((bluedata + next->StateMachineNo)->BYTE0, STATEMACH_BYTE0_TXMODE_Msk,
557 next->trans_config);/* Transmission or reception*/
558 (bluedata + next->StateMachineNo)->TXPOINT = BLUE_STRUCT_PTR_CAST(p);
559 (bluedata + next->StateMachineNo)->RCVPOINT = BLUE_STRUCT_PTR_CAST(p);
560 (bluedata + next->StateMachineNo)->MAXRECEIVEDLENGTH = next->MaxReceiveLength;
561
562 /* Packet will execute on time specified by WakeupTime */
563 if ((next->ActionTag & TIMER_WAKEUP) != 0)
564 {
565 /* timer1/2 off */
566 LL_RADIO_TIMER_DisableTimer1(BLUE);
567 LL_RADIO_TIMER_DisableTimer2(BLUE);
568
569 /* program timer at next->wakeuptime */
570 if ((next->ActionTag & RELATIVE) != 0)
571 {
572 time = HAL_RADIO_TIMER_GetCurrentSysTime() + HAL_RADIO_TIMER_UsToSystime(next->WakeupTime);
573 HAL_RADIO_TIMER_SetRadioTimerValue(time, (next->trans_config == STATEMACH_BYTE0_TXMODE_Msk), (next->ActionTag & PLL_TRIG));
574 }
575 else
576 {
577 HAL_RADIO_TIMER_SetRadioTimerValue(next->WakeupTime, (next->trans_config == STATEMACH_BYTE0_TXMODE_Msk), (next->ActionTag & PLL_TRIG));
578 }
579 }
580 else
581 {
582 /* back to back */
583 }
584 }
585
586 /* Accept the packet even with CRC Error */
587 if (((int_flags & BLUE_INTERRUPT1REG_RCVOK) != 0) || ((int_flags & BLUE_INTERRUPT1REG_RCVCRCERR) != 0))
588 {
589
590 uint64_t current_system_time;
591 /* read RSSI */
592 globalParameters.current_action_packet->rssi = HAL_RADIO_ReadRSSI();
593
594 /* bluedata->config = bluedata->config ^ 0x80 ; toggle NESN bit
595 bluedata->config = bluedata->config & 0x7F ; //reset NESN bit */
596
597 /* read time stamp */
598 globalParameters.current_action_packet->timestamp_receive = HAL_RADIO_TIMER_GetAnchorPoint(¤t_system_time);
599 }
600 else if ((int_flags & BLUE_INTERRUPT1REG_RCVTIMEOUT) != 0)
601 {
602 /* read RSSI even if a timeout happens */
603 globalParameters.current_action_packet->rssi = HAL_RADIO_ReadRSSI();
604 }
605
606 actionPacketBackup = globalParameters.current_action_packet;
607 globalParameters.current_action_packet = next;
608 actionPacketBackup->dataRoutine(actionPacketBackup, next);
609 }
610
611 return ;
612 }
613
614 /**
615 * @brief RADIO MSP Init
616 * @param hradio pointer to a RADIO_HandleTypeDef structure that contains
617 * the configuration information for RADIO module
618 * @retval None
619 */
HAL_RADIO_MspInit(RADIO_HandleTypeDef * hradio)620 __weak void HAL_RADIO_MspInit(RADIO_HandleTypeDef *hradio)
621 {
622 /* Prevent unused argument(s) compilation warning */
623 UNUSED(hradio);
624
625 /* NOTE : This function Should not be modified, when the callback is needed,
626 the HAL_I2S_MspInit could be implemented in the user file
627 */
628 }
629
630 /**
631 * @brief RADIO MSP DeInit
632 * @param hradio pointer to a RADIO_HandleTypeDef structure that contains
633 * the configuration information for RADIO module
634 * @retval None
635 */
HAL_RADIO_MspDeInit(RADIO_HandleTypeDef * hradio)636 __weak void HAL_RADIO_MspDeInit(RADIO_HandleTypeDef *hradio)
637 {
638 /* Prevent unused argument(s) compilation warning */
639 UNUSED(hradio);
640
641 /* NOTE : This function Should not be modified, when the callback is needed,
642 the HAL_RADIO_MspDeInit could be implemented in the user file
643 */
644 }
645
646
647 /**
648 * @brief This routine force the radio to be stopped. After calling this function,
649 * the ISR is not triggered unless, "MakeActionPacketPending" API called again.
650 * @retval 0 if the radio activity has been cleared successfully.
651 * @retval 1 if it is too late to clear the last radio activity.
652 * @retval 2 if it might not be possible to clear the last radio activity.
653 */
HAL_RADIO_StopActivity(void)654 uint8_t HAL_RADIO_StopActivity(void)
655 {
656 uint8_t retval;
657 MASK_INTERRUPTS();
658 MODIFY_REG(BLUEGLOB->BYTE4, GLOBAL_BYTE4_ACTIVE_Msk, BLUE_IDLE_0);
659 retval = HAL_RADIO_TIMER_ClearRadioTimerValue();
660 globalParameters.current_action_packet = 0;
661 UNMASK_INTERRUPTS();
662 return retval;
663 }
664
665 /**
666 * @brief This routine sets the channel map. If channel map is not in use, do not use it. The
667 * chan_remap constant is a 37-bit vector, one bit per channel from 0 to 36, with the
668 * LSB corresponding to the channel 0. If the corresponding bit is set, the channel is in use; if it is cleared,
669 * there is an automatic remap to another channel, as defined in the Bluetooth Low
670 * Energy specification.
671 * Setting all bits of the array to one, disables the channel remapping, and this is the mode
672 * that should be used if the Bluetooth channel remap is not in use.
673 * @param StateMachineNo: state machine number in multi state.
674 * @param chan_remap: a 37-bit vector, one bit per channel from 0 to 36, with the LSB corresponding to the channel 0
675 * @retval None
676 */
HAL_RADIO_SetChannelMap(uint8_t StateMachineNo,uint8_t * chan_remap)677 void HAL_RADIO_SetChannelMap(uint8_t StateMachineNo, uint8_t *chan_remap)
678 {
679 /* Check the parameters */
680 assert_param(IS_STATE_VALID(StateMachineNo));
681
682 for (uint8_t i = 0; i < 5; i++)
683 {
684 (bluedata + StateMachineNo)->USEDCHANNELFLAGS[i] = chan_remap[i];
685 }
686 (bluedata + StateMachineNo)->USEDCHANNELFLAGS[4] &= 0x1F;
687 return;
688 }
689
690 /**
691 * @brief This routine sets the channel and the channel increment. Channel and channel
692 * increment follows channel mapping corresponding to Bluetooth specification.
693 * RF channel 0: 2402 MHz -> ble channel index 37
694 * RF channel 1: 2404 MHz -> ble channel index 0
695 * RF channel 2: 2406 MHz -> ble channel index 1
696 * ...
697 * RF channel 11: 2424 MHz -> ble channel index 10
698 * RF channel 12: 2426 MHz -> ble channel index 38
699 * RF channel 13: 2428 MHz -> ble channel index 11
700 * RF channel 14: 2430 MHz -> ble channel index 12
701 * ...
702 * RF channel 38: 2478 MHz -> ble channel index 36
703 * RF channel 39: 2480 MHz -> ble channel index 39
704 *
705 * For the ble channel index 37, 38 and 39 (RF channel 0, 12, 39):
706 * - The crc_init value should always be 0x555555.
707 * - There is no encryption.
708 * - The channel increment is dedicated, the channel sequence is:
709 * 37 -> 38 -> 39 -> 37 -> ... while for the other channels is:
710 * 0 -> 1 -> ... -> 36 -> 0 -> ...
711 * There is no channel map for these three channels.
712 * Valid values for packet length for these channels are from 6 to 37.
713 * @param StateMachineNo: state machine number in multi state.
714 * @param channel: ble channel index. From 0 to 39.
715 * @param channel_increment: determines the hoping value.
716 * @retval None
717 */
HAL_RADIO_SetChannel(uint8_t StateMachineNo,uint8_t channel,uint8_t channel_increment)718 void HAL_RADIO_SetChannel(uint8_t StateMachineNo, uint8_t channel, uint8_t channel_increment)
719 {
720 /* Check the parameters */
721 assert_param(IS_STATE_VALID(StateMachineNo));
722 assert_param(IS_RFCHANNEL_VALID(channel));
723
724 MODIFY_REG((bluedata + StateMachineNo)->BYTE0, STATEMACH_BYTE0_UCHAN_Msk, channel);
725 /*if TxRxPack.incchan = 0, then remap_chan is used as physical channel*/
726 MODIFY_REG((bluedata + StateMachineNo)->BYTE1, STATEMACH_BYTE1_REMAP_CHAN_Msk, channel);
727 (bluedata + StateMachineNo)->HOPINCR = channel_increment;
728 return;
729 }
730
731 /**
732 * @brief This routine sets the NetworkID and the CRC init.
733 * @param StateMachineNo: state machine number in multi state.
734 * @param NetworkID: The NetworkID is the ID of the device.
735 * The user shall ensure that the NetworkID meets the following requirements:
736 * - It shall have no more than six consecutive zeros or ones.
737 * - It shall not have all four octets equal.
738 * - It shall have no more than 24 transitions.
739 * - It shall have a minimum of two transitions in the most significant six bits.
740 * @param crc_init: CRC initialization value.
741 * This value must be 0x555555 when channel frequency is one of these values: 37, 38, 39.
742 * @retval None
743 */
HAL_RADIO_SetTxAttributes(uint8_t StateMachineNo,uint32_t NetworkID,uint32_t crc_init)744 void HAL_RADIO_SetTxAttributes(uint8_t StateMachineNo, uint32_t NetworkID, uint32_t crc_init)
745 {
746 /* Check the parameters */
747 assert_param(IS_STATE_VALID(StateMachineNo));
748
749 (bluedata + StateMachineNo)->ACCADDR = NetworkID;
750 (bluedata + StateMachineNo)->CRCINIT[0] = crc_init;
751 (bluedata + StateMachineNo)->CRCINIT[1] = crc_init >> 8;
752 (bluedata + StateMachineNo)->CRCINIT[2] = crc_init >> 16;
753 return;
754 }
755
756 /**
757 * @brief This routine sets the 40-bit receive and transmit packet count, to be used in
758 * encryption calculation.
759 * Both are pointers to char, and set the 39-bit counter + 1-bit MSB as defined in the
760 * Bluetooth Low Energy spec. One is for transmit packets, the other is for receive packets.
761 * @param StateMachineNo: state machine number in multi state.
762 * @param count_tx: 40-bit transmit packet count, to be used in encryption nounce calculation.
763 * @param count_rcv: 40-bit receive packet count, to be used in encryption nounce calculation.
764 * @retval None
765 */
HAL_RADIO_SetEncryptionCount(uint8_t StateMachineNo,uint8_t * count_tx,uint8_t * count_rcv)766 void HAL_RADIO_SetEncryptionCount(uint8_t StateMachineNo, uint8_t *count_tx, uint8_t *count_rcv)
767 {
768 /* Check the parameters */
769 assert_param(IS_STATE_VALID(StateMachineNo));
770
771 for (uint8_t i = 0; i < 5; i++)
772 {
773 (bluedata + StateMachineNo)->PCNTRCV[i] = count_rcv[i];
774 (bluedata + StateMachineNo)->PCNTTX[i] = count_tx[i];
775 }
776 return;
777 }
778
779 /**
780 * @brief This routines sets the 8-byte encryption initial vector, and the 16-byte encryption key.
781 * The definition of the encryption key and its initial value is according the Bluetooth Low Energy spec.
782 * @param StateMachineNo: state machine number in multi state.
783 * @param enc_iv: 8-byte encryption initial vector.
784 * @param enc_key: 16-byte encryption key.
785 * @retval None
786 */
HAL_RADIO_SetEncryptionAttributes(uint8_t StateMachineNo,uint8_t * enc_iv,uint8_t * enc_key)787 void HAL_RADIO_SetEncryptionAttributes(uint8_t StateMachineNo, uint8_t *enc_iv, uint8_t *enc_key)
788 {
789 uint8_t i = 0;
790 /* Check the parameters */
791 assert_param(IS_STATE_VALID(StateMachineNo));
792
793 for (i = 0; i < 8; i++)
794 {
795 (bluedata + StateMachineNo)->ENCRYPTIV[i] = enc_iv[i];
796 (bluedata + StateMachineNo)->ENCRYPTK[i] = enc_key[i];
797 }
798 for (i = 8; i < 16; i++)
799 {
800 (bluedata + StateMachineNo)->ENCRYPTK[i] = enc_key[i];
801 }
802
803 return;
804 }
805
806 /**
807 * @brief Set the maximum length of a received packet.
808 * @param StateMachineNo: state machine number in multi state.
809 * @param MaxReceivedLength: Upper limit for the length of a received packet.
810 * From 0 to 255 bytes.
811 * @retval None
812 */
HAL_RADIO_SetMaxReceivedLength(uint8_t StateMachineNo,uint8_t MaxReceivedLength)813 void HAL_RADIO_SetMaxReceivedLength(uint8_t StateMachineNo, uint8_t MaxReceivedLength)
814 {
815 (bluedata + StateMachineNo)->MAXRECEIVEDLENGTH = MaxReceivedLength;
816 return;
817 }
818
819 /**
820 * @brief Initializes the time between back-to-back radio transmissions.
821 * @param back_to_back_time: time between two packets if wakeupTimer is not used. Resolution is 1 us.
822 * @retval None
823 */
HAL_RADIO_SetBackToBackTime(uint32_t back_to_back_time)824 void HAL_RADIO_SetBackToBackTime(uint32_t back_to_back_time)
825 {
826 globalParameters.back2backTime = back_to_back_time;
827 return;
828 }
829
830
831 /**
832 * @brief Phy selection
833 * @param StateMachineNo: state machine number in multi state.
834 * @param phy:
835 * 0x0 PHY is not coded 1Mbps
836 * 0x1 PHY is not coded 2Mbps
837 * 0x4 PHY is coded 1Mbps with S=8
838 * 0x6 PHY is coded 1Mbps with S=2
839 * @retval None
840 */
HAL_RADIO_SetPhy(uint8_t StateMachineNo,uint8_t phy)841 void HAL_RADIO_SetPhy(uint8_t StateMachineNo, uint8_t phy)
842 {
843 assert_param(IS_PHY_VALID(phy));
844
845 MODIFY_REG((bluedata + StateMachineNo)->BYTE3, STATEMACH_BYTE3_TXPHY_Msk, phy);
846 MODIFY_REG((bluedata + StateMachineNo)->BYTE3, STATEMACH_BYTE3_RXPHY_Msk, phy << 4);
847
848 return;
849 }
850
851 /**
852 * @brief This routine turns encrypt ON and OFF. When the encryption is enabled, the hardware will add 4 bytes
853 * at the end of the packet as MIC (Message Authentication Code). So the user need to add 4 byte to the
854 * length of the packet. The parameters enable the encryption for both. There are two separated parameters
855 * for this function just compliance with previous version of the driver.
856 * @param StateMachineNo: state machine number in multi state.
857 * @param EncryptFlagTx: DISABLE: encryption is turned OFF for both TX and RX operations.
858 * ENABLE: encryption is turned OFF for both TX and RX operations.
859 * This parameter can be: ENABLE or DISABLE.
860 * @param EncryptFlagRcv: encryption is turned OFF for both TX and RX operations.
861 * ENABLE: encryption is turned OFF for both TX and RX operations.
862 * This parameter can be: ENABLE or DISABLE.
863 * @retval None
864 */
HAL_RADIO_SetEncryptFlags(uint8_t StateMachineNo,FunctionalState EncryptFlagTx,FunctionalState EncryptFlagRcv)865 void HAL_RADIO_SetEncryptFlags(uint8_t StateMachineNo, FunctionalState EncryptFlagTx, FunctionalState EncryptFlagRcv)
866 {
867 /* Check the parameters */
868 assert_param(IS_STATE_VALID(StateMachineNo));
869 assert_param(IS_FUNCTIONAL_STATE(EncryptFlagTx));
870 assert_param(IS_FUNCTIONAL_STATE(EncryptFlagRcv));
871
872 if (EncryptFlagTx == ENABLE || EncryptFlagRcv == ENABLE)
873 {
874 (bluedata + StateMachineNo)->BYTE2 |= STATEMACH_BYTE2_ENCRYPTON_Msk;
875 (bluedata + StateMachineNo)->BYTE35 |= STATEMACH_BYTE35_INTENCERROR_Msk;
876 }
877 else
878 {
879 (bluedata + StateMachineNo)->BYTE2 &= (~STATEMACH_BYTE2_ENCRYPTON_Msk);
880 }
881 (bluedata + StateMachineNo)->BYTE35 |= STATEMACH_BYTE35_INTRXOVERFLOWERROR_Msk;
882 return;
883 }
884
885 /**
886 * @brief Set the receive window length.
887 * Define the maximum duration to stay in reception without any preamble
888 * and access address detection.
889 * @param ReceiveTimeout: receive window length in microseconds.
890 * @retval None
891 */
HAL_RADIO_SetGlobalReceiveTimeout(uint32_t ReceiveTimeout)892 void HAL_RADIO_SetGlobalReceiveTimeout(uint32_t ReceiveTimeout)
893 {
894 /* Set the Rx window Timeout expressed as: 4^(RCVTIMEOUT_19_18)*RCVTIMEOUT_17_0 */
895 if (ReceiveTimeout < 0x40000)
896 {
897 BLUEGLOB->RCVTIMEOUT[0] = (ReceiveTimeout) & 0x000000FF;
898 BLUEGLOB->RCVTIMEOUT[1] = (ReceiveTimeout >> 8) & 0x000000FF;
899 BLUEGLOB->RCVTIMEOUT[2] = (ReceiveTimeout >> 16) & 0x00000003;
900 }
901 else if (ReceiveTimeout < 0x100000)
902 {
903 BLUEGLOB->RCVTIMEOUT[0] = (ReceiveTimeout >> 2) & 0x000000FF;
904 BLUEGLOB->RCVTIMEOUT[1] = (ReceiveTimeout >> 10) & 0x000000FF;
905 BLUEGLOB->RCVTIMEOUT[2] = (ReceiveTimeout >> 18) & 0x00000003;
906
907 BLUEGLOB->RCVTIMEOUT[2] |= 0x04;
908 }
909 else if (ReceiveTimeout < 0x400000)
910 {
911 BLUEGLOB->RCVTIMEOUT[0] = (ReceiveTimeout >> 4) & 0x000000FF;
912 BLUEGLOB->RCVTIMEOUT[1] = (ReceiveTimeout >> 12) & 0x000000FF;
913 BLUEGLOB->RCVTIMEOUT[2] = (ReceiveTimeout >> 20) & 0x00000003;
914
915 BLUEGLOB->RCVTIMEOUT[2] |= 0x08;
916 }
917 else if (ReceiveTimeout < 0x1000000)
918 {
919 BLUEGLOB->RCVTIMEOUT[0] = (ReceiveTimeout >> 6) & 0x000000FF ;
920 BLUEGLOB->RCVTIMEOUT[1] = (ReceiveTimeout >> 14) & 0x000000FF ;
921 BLUEGLOB->RCVTIMEOUT[2] = (ReceiveTimeout >> 22) & 0x00000003 ;
922
923 BLUEGLOB->RCVTIMEOUT[2] |= 0x0C;
924 }
925 else
926 {
927 /* error */
928 }
929 }
930
931 /**
932 * @brief This routine should be called after writing/modifying an action packet, and before it
933 * is executed via either the API mechanism, or the next mechanism.
934 * @param p: pointer to action packet.
935 * @retval None
936 */
HAL_RADIO_SetReservedArea(ActionPacket * p)937 void HAL_RADIO_SetReservedArea(ActionPacket *p)
938 {
939 uint32_t relTimeout;
940 uint32_t cnt;
941
942 /*Init to 0 the TxRxPack*/
943 for (cnt = 0; cnt < sizeof(p->trans_packet); cnt++)
944 {
945 ((uint8_t *)(&(p->trans_packet)))[cnt] = 0;
946 }
947
948 /*Set the TxRxPack for the next transaction. The list cannot be empty.
949 At least,it can be composed by one only packet that points to itself*/
950 p->trans_packet.NEXTPTR = BLUE_STRUCT_PTR_CAST(&(p->trans_packet));
951
952 /* Set the buffer that contains the values to send or that stores
953 the data received */
954 p->trans_packet.DATAPTR = BLUE_DATA_PTR_CAST(p->data);
955
956 /* Compensate the radio setup time from the back2back time */
957 relTimeout = globalParameters.back2backTime - 70;
958
959 /*Check if there is some action to perform next*/
960 // if (p->next_false || p->next_true){ /* Host timer workaround */
961 /* Set the Timeout for the Timer2 */
962 p->trans_packet.TIMER2[0] = relTimeout & 0xFF;
963 p->trans_packet.TIMER2[1] = (relTimeout >> 8) & 0xFF;
964 p->trans_packet.BYTE14 = (relTimeout >> 16) & TXRXPACK_BYTE14_TIMER2_19_16_Msk;
965 /*Enable relative timer*/
966 p->trans_packet.BYTE14 |= TXRXPACK_BYTE14_TIMER2EN_Msk;
967 // }
968
969 /* TrigDone or TrigReceive */
970 if ((p->ActionTag & TIMESTAMP_POSITION) == 0)
971 {
972 p->trans_packet.BYTE14 |= TIMESTAMP_POSITION_LASTBIT;
973 }
974 else
975 {
976 p->trans_packet.BYTE14 |= TIMESTAMP_POSITION_ACCESSADDRESS;
977 }
978
979 p->trans_packet.BYTE4 |= TXRXPACK_BYTE4_KEEPSEMAREQ_Msk | \
980 (p->ActionTag & INC_CHAN) | \
981 (p->ActionTag & PLL_TRIG);
982
983 p->trans_packet.BYTE5 |= (p->ActionTag & WHITENING_DISABLE) | \
984 TXRXPACK_BYTE5_TXDATAREADY_Msk | \
985 TXRXPACK_BYTE5_ALLTABLEREADY_Msk;
986
987 /* Enable all interrupts */
988 p->trans_packet.BYTE15 = TXRXPACK_BYTE15_INT_EN_Msk;
989
990 /* By Default the next action is considered as next_true */
991 if ((p->next_true->ActionTag & TXRX) != 0)
992 {
993 /* Set the type of the next activity */
994 p->trans_packet.BYTE5 |= TXRXPACK_BYTE5_NEXTTXMODE_Msk;
995 }
996
997 p->trans_config = 0; // Rx
998 if ((p->ActionTag & TXRX) != 0)
999 {
1000 p->trans_config = STATEMACH_BYTE0_TXMODE_Msk; // Tx
1001 }
1002 return ;
1003 }
1004
1005
1006 /**
1007 * @brief This routine should be called for the first actionPacket that needs to be scheduled
1008 * on the radio. For it to work OK, the WakeupTime should be valid.
1009 * Subsequent packets can be dispatched using the same process, or by providing non-NULL pointers
1010 * to the next_true and next_false pointers of the ActionPacket.
1011 * @param p: pointer to action packet.
1012 * @retval uint8_t with following values:
1013 * - 0x00 : Success.
1014 * - 0xC4 : Radio is busy, action packet has not been executed.
1015 */
HAL_RADIO_MakeActionPacketPending(ActionPacket * p)1016 uint8_t HAL_RADIO_MakeActionPacketPending(ActionPacket *p)
1017 {
1018 uint8_t returnValue = SUCCESS_0;
1019 uint32_t time;
1020 uint32_t dummyTime;
1021 if (HAL_RADIO_GetStatus(&dummyTime) == BLUE_IDLE_0)
1022 {
1023 uint8_t statemachineNo;
1024 BlueTransStruct *p1 ;
1025
1026 /* timer1/2 off */
1027 LL_RADIO_TIMER_DisableTimer1(BLUE);
1028 LL_RADIO_TIMER_DisableTimer2(BLUE);
1029
1030 statemachineNo = 0x7F & p->StateMachineNo;
1031
1032 BLUEGLOB->BYTE4 = (p->StateMachineNo | GLOBAL_BYTE4_ACTIVE_Msk);
1033
1034 p1 = &p->trans_packet;
1035 (bluedata + statemachineNo)->RCVPOINT = BLUE_STRUCT_PTR_CAST(p1);
1036 (bluedata + statemachineNo)->TXPOINT = BLUE_STRUCT_PTR_CAST(p1);
1037 (bluedata + statemachineNo)->MAXRECEIVEDLENGTH = p->MaxReceiveLength;
1038
1039 #if defined (STM32WB05) || defined(STM32WB09 )
1040 (bluedata + statemachineNo)->BYTE3 |= 1 << 3;
1041 #endif
1042
1043 globalParameters.current_action_packet = p;
1044
1045 MODIFY_REG((bluedata + statemachineNo)->BYTE0, STATEMACH_BYTE0_TXMODE_Msk,
1046 p->trans_config); /* Transmission or reception */
1047
1048 /* program timer at next->wakeuptime */
1049 MASK_INTERRUPTS();
1050 if ((p->ActionTag & RELATIVE) != 0)
1051 {
1052 time = HAL_RADIO_TIMER_GetCurrentSysTime() + HAL_RADIO_TIMER_UsToSystime(p->WakeupTime);
1053 returnValue = HAL_RADIO_TIMER_SetRadioTimerValue(time, (p->trans_config == STATEMACH_BYTE0_TXMODE_Msk), (p->ActionTag & PLL_TRIG));
1054 }
1055 else /*absolute time*/
1056 {
1057 returnValue = HAL_RADIO_TIMER_SetRadioTimerValue(p->WakeupTime, (p->trans_config == STATEMACH_BYTE0_TXMODE_Msk), (p->ActionTag & PLL_TRIG));
1058 }
1059
1060 UNMASK_INTERRUPTS();
1061 }
1062 else
1063 {
1064 returnValue = RADIO_BUSY_C4;
1065 }
1066 return returnValue;
1067 }
1068
1069 /**
1070 * @brief Get the status of the radio and if it is active
1071 * the last programmed value in MTU.
1072 * @param time: where to store the last value programmed.
1073 * @retval 0 if the radio controller is IDLE or no timer has been programmed
1074 * @retval 1 if the radio is ACTIVE and a radio timer has been programmed
1075 */
HAL_RADIO_GetStatus(uint32_t * time)1076 uint8_t HAL_RADIO_GetStatus(uint32_t *time)
1077 {
1078 uint8_t retValue = BLUE_IDLE_0;
1079 if ((BLUEGLOB->BYTE4 & GLOBAL_BYTE4_ACTIVE_Msk) != 0)
1080 {
1081 retValue = HAL_RADIO_TIMER_GetRadioTimerValue(time);
1082 }
1083 return retValue;
1084 }
1085
1086 /**
1087 * @brief Configures the transmit power level.
1088 * @param PowerLevel: power level which should set to this value.
1089 * See the documentation inside the datasheet.
1090 * @retval None
1091 */
HAL_RADIO_SetTxPower(uint8_t PowerLevel)1092 void HAL_RADIO_SetTxPower(uint8_t PowerLevel)
1093 {
1094 /* Check the parameters */
1095 assert_param(IS_POWERLEVEL_VALID(PowerLevel));
1096
1097 for (uint8_t n = 0; n < STATEMACHINE_COUNT ; n++)
1098 {
1099 (bluedata + n)->PAPOWER = PowerLevel;
1100 }
1101 return;
1102 }
1103
1104
1105 /**
1106 * @brief Restore default preamble length to one byte.
1107 * @param StateMachineNo: state machine number in multi state.
1108 * @retval None
1109 */
HAL_RADIO_SetDefaultPreambleLen(uint8_t StateMachineNo)1110 void HAL_RADIO_SetDefaultPreambleLen(uint8_t StateMachineNo)
1111 {
1112 (bluedata + StateMachineNo)->BYTE34 &= ~(STATEMACH_BYTE34_ENAPREAMBLEREP_Msk);
1113 return;
1114 }
1115
1116 /**
1117 * @brief Set how many times repeat the preamble.
1118 * @param StateMachineNo: state machine number in multi state.
1119 * @param PreaLen: preamble length in byte for coded or uncoded phy.
1120 * @retval None
1121 */
HAL_RADIO_SetPreambleRep(uint8_t StateMachineNo,uint8_t PreaLen)1122 void HAL_RADIO_SetPreambleRep(uint8_t StateMachineNo, uint8_t PreaLen)
1123 {
1124 /* Check the parameters */
1125 assert_param(IS_PREALEN_VALID(PreaLen));
1126
1127 (bluedata + StateMachineNo)->BYTE34 |= STATEMACH_BYTE34_ENAPREAMBLEREP_Msk;
1128 (bluedata + StateMachineNo)->BYTE34 |= (PreaLen & STATEMACH_BYTE34_PREAMBLEREP_Msk);
1129 return;
1130 }
1131
1132 /**
1133 * @brief Enable or disable the CRC hardware functionality.
1134 * By default the CRC hardware feature is enabled. So, it can be enabled again
1135 * if it has been disabled.
1136 * If disabled, the CRC will be neither checked in reception nor appended in transmission.
1137 * @warning ALPHA version. In reception just ignore the CRC error and don't use this feature.
1138 * @param StateMachineNo: state machine number in multi state.
1139 * @param hwCRC:
1140 * - ENABLE: enable the CRC hardware feature.
1141 * - DISABLE: disable the CRC hardware feature.
1142 * @retval None
1143 */
HAL_RADIO_DisableCRC(uint8_t StateMachineNo,FunctionalState hwCRC)1144 void HAL_RADIO_DisableCRC(uint8_t StateMachineNo, FunctionalState hwCRC)
1145 {
1146 if (hwCRC != DISABLE)
1147 {
1148 (bluedata + StateMachineNo)->BYTE34 &= ~STATEMACH_BYTE34_DISABLECRC_Msk;
1149 }
1150 else
1151 {
1152 (bluedata + StateMachineNo)->BYTE34 |= STATEMACH_BYTE34_DISABLECRC_Msk;
1153 }
1154 return;
1155 }
1156
1157 /**
1158 * @brief Starts tone transmission on selected channel.
1159 * This API is dedicated for test and destroys context and multistate.
1160 * So, after calling this function the radio should be re-initialized.
1161 * @param RF_Channel: radio frequency channel number from 0 to 39.
1162 * Note that RF channel index is different from ble channel index due to advertising channels,
1163 * Please refer following table:
1164 * RF channel 0: 2402 MHz -> ble channel index 37
1165 * RF channel 1: 2404 MHz -> ble channel index 0
1166 * RF channel 2: 2406 MHz -> ble channel index 1
1167 * ...
1168 * RF channel 11: 2424 MHz -> ble channel index 10
1169 * RF channel 12: 2426 MHz -> ble channel index 38
1170 * RF channel 13: 2428 MHz -> ble channel index 11
1171 * RF channel 14: 2430 MHz -> ble channel index 12
1172 * ...
1173 * RF channel 38: 2478 MHz -> ble channel index 36
1174 * RF channel 39: 2480 MHz -> ble channel index 39
1175 * @param powerLevel: power level which should set.
1176 * @param freq_offset: Specify if the tone must be emitted with an offset from the channel center frequency.
1177 * If 0, the tone is emitted at the channel center frequency.
1178 * If 1 or 2, the device will continuously emit the tone at the center
1179 * frequency plus or minus 250 kHz respectively..
1180 * @retval None
1181 */
HAL_RADIO_StartTone(uint8_t RF_Channel,uint8_t powerLevel,uint8_t freq_offset)1182 uint8_t HAL_RADIO_StartTone(uint8_t RF_Channel, uint8_t powerLevel, uint8_t freq_offset)
1183 {
1184 /* Check the parameters */
1185 assert_param(IS_RFCHANNEL_VALID(RF_Channel));
1186 assert_param(IS_POWERLEVEL_VALID(powerLevel));
1187 assert_param(IS_FREQOFFSET_VALID(freq_offset)); /*TBR*/
1188
1189 uint8_t retVal;
1190 uint32_t dummyTime;
1191
1192 if (globalParameters.tone_start_stop_flag != 0U)
1193 {
1194 retVal = 1;
1195 }
1196 else
1197 {
1198 if ((RF_Channel >= 40U) || (freq_offset > 2U)) /*TBR*/
1199 {
1200 retVal = 1;
1201 }
1202 else
1203 {
1204 if (HAL_RADIO_GetStatus(&dummyTime) == BLUE_IDLE_0)
1205 {
1206 globalParameters.tone_start_stop_flag = 1;
1207 /* [EM:] Calculate the synt divide factor for 16 MHz quarts and +250 kHz offset wrt the channel center frequency
1208 * Algorithmically MAK = F_rf*(2^20)/32 = F_rf*(2^15)
1209 * With F_rf = (2402+2*RF_Channel)+0.25 MHz
1210 * K corresponds to b19-b0 of MAK
1211 * A corresponds to b22-b20 of MAK
1212 * M corresponds to b27-b23 of MAK
1213 */
1214 uint32_t kHz_250_scaled = 8192; // = 0.250*2^20/32
1215 uint32_t MAK = ((2402UL + 2UL * RF_Channel) << 15);
1216
1217 if (freq_offset == 1U)
1218 {
1219 MAK += kHz_250_scaled;
1220 }
1221 else if (freq_offset == 2U)
1222 {
1223 MAK -= kHz_250_scaled;
1224 }
1225 else
1226 {
1227 }
1228
1229 uint8_t M = ((uint8_t)(MAK >> 23) & 0x1FU);
1230 uint8_t A = ((uint8_t)(MAK >> 20) & 0x07U);
1231 uint32_t K = (MAK & 0x000FFFFFUL) + 1UL;
1232
1233 uint32_t MOD3_DIG_TEST = (M << 3) | (A & 0x7U);
1234 uint32_t MOD2_DIG_TEST = (K >> 12) & 0xFFU;
1235 uint32_t MOD1_DIG_TEST = (K >> 4) & 0xFFU;
1236 uint32_t MOD0_DIG_TEST = ((K & 0x0FU) << 4) | 0x09U;
1237 uint32_t RADIO_FSM_USR = ((powerLevel) << 3) | 0x06;
1238
1239 RRM->RADIO_FSM_USR = RADIO_FSM_USR;
1240 RRM->MOD3_DIG_TST = MOD3_DIG_TEST;
1241 RRM->MOD2_DIG_TST = MOD2_DIG_TEST;
1242 RRM->MOD1_DIG_TST = MOD1_DIG_TEST;
1243 RRM->MOD0_DIG_TST = MOD0_DIG_TEST;
1244
1245 /* Take control of the radio FSM through the test bus */
1246 RRM->DTB5_DIG_ENG = 0x09;
1247 uint32_t *rrm_udra_test = ((uint32_t *)&RRM->RRM_CTRL) + 0x01;
1248 *rrm_udra_test = 0x03;
1249 RRM->DTB5_DIG_ENG = 0x39;
1250 while (RRM->FSM_STATUS_DIG_OUT != 0x04);
1251 RRM->DTB5_DIG_ENG = 0x3B;
1252 retVal = 0;
1253 }
1254 else
1255 {
1256 retVal = 1;
1257 }
1258 }
1259 }
1260 return retVal;
1261 }
1262
1263 /**
1264 * @brief This routine stop tone transmission.
1265 * This API is dedicated for test and destroys context and multistate.
1266 * So, after calling this function the radio should be re-initialized.
1267 * @retval None
1268 */
HAL_RADIO_StopTone(void)1269 uint8_t HAL_RADIO_StopTone(void)
1270 {
1271 uint8_t retVal;
1272
1273 if (globalParameters.tone_start_stop_flag != 0U)
1274 {
1275 globalParameters.tone_start_stop_flag = 0;
1276 /* Release control of the radio FSM through the test bus */
1277 RRM->DTB5_DIG_ENG = 0x00;
1278 uint32_t *rrm_udra_test = ((uint32_t *)&RRM->RRM_CTRL) + 0x01;
1279 *rrm_udra_test = 0x00;
1280 retVal = 0;
1281 }
1282 else
1283 {
1284 retVal = 1;
1285 }
1286 return retVal;
1287 }
1288
1289
1290 /**
1291 * @brief Encrypts plain text data using AES encryption with given input key and
1292 * 128 bit block size
1293 * @param Key: encryption key to be used.
1294 * @param plainData: text data to be encrypted.
1295 * @param cypherData: contains the encrypted data.
1296 * @retval None
1297 */
HAL_RADIO_EncryptPlainData(uint8_t * Key,uint8_t * plainData,uint8_t * cypherData)1298 void HAL_RADIO_EncryptPlainData(uint8_t *Key, uint8_t *plainData, uint8_t *cypherData)
1299 {
1300 uint32_t key[4] ;
1301 uint32_t cleartext[4] ;
1302 uint32_t ciphertext[4] ;
1303 volatile uint32_t ii ;
1304
1305 for (uint8_t i = 0; i < 4; i++)
1306 {
1307 key[i] = ((uint32_t)Key[i * 4]) | ((uint32_t)Key[i * 4 + 1]) << 8 | ((uint32_t)Key[i * 4 + 2]) << 16 | ((uint32_t)Key[ i * 4 + 3]) << 24;
1308 cleartext[i] = ((uint32_t)plainData[i * 4]) | ((uint32_t)plainData[i * 4 + 1]) << 8 | ((uint32_t)plainData[i * 4 + 2]) << 16 | ((uint32_t)plainData[i * 4 + 3]) << 24;
1309 }
1310
1311 BLUE->MANAESKEY0REG = key[3];
1312 BLUE->MANAESKEY1REG = key[2];
1313 BLUE->MANAESKEY2REG = key[1];
1314 BLUE->MANAESKEY3REG = key[0];
1315
1316 BLUE->MANAESCLEARTEXT0REG = cleartext[3];
1317 BLUE->MANAESCLEARTEXT1REG = cleartext[2];
1318 BLUE->MANAESCLEARTEXT2REG = cleartext[1];
1319 BLUE->MANAESCLEARTEXT3REG = cleartext[0];
1320
1321 BLUE->MANAESCMDREG = 1;
1322
1323 ii = 0 ;
1324 while ((BLUE->MANAESSTATREG == 0) && ii < 100)
1325 {
1326 ii++;
1327 }
1328
1329 ciphertext[0] = BLUE->MANAESCIPHERTEXT3REG;
1330 ciphertext[1] = BLUE->MANAESCIPHERTEXT2REG;
1331 ciphertext[2] = BLUE->MANAESCIPHERTEXT1REG;
1332 ciphertext[3] = BLUE->MANAESCIPHERTEXT0REG;
1333
1334 for (uint8_t i = 0; i < 4; i++)
1335 {
1336 cypherData[i * 4] = ((uint8_t)ciphertext[i]);
1337 cypherData[i * 4 + 1] = (uint8_t)(ciphertext[i] >> 8);
1338 cypherData[i * 4 + 2] = (uint8_t)(ciphertext[i] >> 16);
1339 cypherData[i * 4 + 3] = (uint8_t)(ciphertext[i] >> 24);
1340 }
1341
1342 return ;
1343 }
1344
1345
1346 /**
1347 * @brief This routine sets the network ID field for packet transmission and filtering for the receiving.
1348 * Only two devices with same networkID can communicate with each other.
1349 * @param ID: network ID based on bluetooth specification:
1350 * 1. It shall have no more than six consecutive zeros or ones.
1351 * 2. It shall not have all four octets equal.
1352 * 3. It shall have no more than 24 transitions.
1353 * 4. It shall have a minimum of two transitions in the most significant six bits.
1354 *
1355 * @retval uint8_t: return value
1356 * - 0x00 : Success.
1357 * - 0xC0 : Invalid parameter.
1358 */
HAL_RADIO_SetNetworkID(uint32_t ID)1359 uint8_t HAL_RADIO_SetNetworkID(uint32_t ID)
1360 {
1361 networkID = ID;
1362 return 0;
1363 }
1364
1365
1366 /**
1367 * @brief This routine sends a packet on a specific channel and at a specific time.
1368 * @param channel: BLE channel index between 0 to 39.
1369 * @param wakeup_time: Time of transmission in us. This is relative time regarding now.
1370 * Minimum wakeup_time of 230 us. TBR
1371 * @param txBuffer: Pointer to TX data buffer. Second byte of this buffer must be the length of the data.
1372 * @param Callback: This function is being called as data routine.
1373 * First ActionPacket is current action packet and the second one is next action packet.
1374 * @retval uint8_t return value
1375 * - 0x00 : Success.
1376 * - 0xC0 : Invalid parameter.
1377 * - 0xC4 : Radio is busy, receiving has not been triggered.
1378 */
HAL_RADIO_SendPacket(uint8_t channel,uint32_t wakeup_time,uint8_t * txBuffer,uint8_t (* Callback)(ActionPacket *,ActionPacket *))1379 uint8_t HAL_RADIO_SendPacket(uint8_t channel, uint32_t wakeup_time, uint8_t *txBuffer,
1380 uint8_t (*Callback)(ActionPacket *, ActionPacket *))
1381 {
1382 uint8_t returnValue = SUCCESS_0;
1383 uint32_t dummy;
1384 uint32_t time;
1385
1386 time = (uint32_t)HAL_RADIO_TIMER_GetCurrentSysTime() + HAL_RADIO_TIMER_UsToSystime(wakeup_time);
1387
1388 if (channel > 39)
1389 {
1390 returnValue = INVALID_PARAMETER_C0;
1391 }
1392
1393 if (HAL_RADIO_GetStatus(&dummy) != BLUE_IDLE_0)
1394 {
1395 returnValue = RADIO_BUSY_C4;
1396 }
1397
1398 if (returnValue == SUCCESS_0)
1399 {
1400 uint8_t map[5] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
1401 HAL_RADIO_SetChannelMap(0, &map[0]);
1402 HAL_RADIO_SetChannel(0, channel, 0);
1403 HAL_RADIO_SetTxAttributes(0, networkID, 0x555555);
1404
1405 aPacket[0].StateMachineNo = 0;
1406 aPacket[0].ActionTag = TXRX | PLL_TRIG;
1407 aPacket[0].WakeupTime = time;
1408 aPacket[0].MaxReceiveLength = 0; /* does not affect for Tx */
1409 aPacket[0].data = txBuffer;
1410 aPacket[0].next_true = NULL_0;
1411 aPacket[0].next_false = NULL_0;
1412 aPacket[0].condRoutine = CondRoutineTrue;
1413 aPacket[0].dataRoutine = Callback;
1414
1415 HAL_RADIO_SetReservedArea(&aPacket[0]);
1416 returnValue = HAL_RADIO_MakeActionPacketPending(&aPacket[0]);
1417 }
1418
1419 return returnValue;
1420 }
1421
1422
1423 /**
1424 * @brief This routine sends a packet on a specific channel and at a certain time then wait for receiving acknowledge.
1425 * @param channel: BLE channel index between 0 to 39.
1426 * @param wakeup_time: Time of transmission based on us. This is relative time regarding now.
1427 * Minimum wakeup_time of 250 us. TBR
1428 * @param txBuffer: Pointer to TX data buffer. Second byte of this buffer must be the length of the data.
1429 * @param rxBuffer: Pointer to RX data buffer. Second byte of this buffer must be the length of the data.
1430 * @param receive_timeout: Time of RX window used to wait for the packet on us.
1431 * @param receive_length: number of bytes that the link layer accepts in reception.
1432 * @param Callback: This function is being called as data routine.
1433 * First ActionPacket is current action packet and the second one is next action packet.
1434 * @retval uint8_t return value
1435 * - 0x00 : Success.
1436 * - 0xC0 : Invalid parameter.
1437 * - 0xC4 : Radio is busy, receiving has not been triggered.
1438 */
HAL_RADIO_SendPacketWithAck(uint8_t channel,uint32_t wakeup_time,uint8_t * txBuffer,uint8_t * rxBuffer,uint32_t receive_timeout,uint8_t receive_length,uint8_t (* Callback)(ActionPacket *,ActionPacket *))1439 uint8_t HAL_RADIO_SendPacketWithAck(uint8_t channel, uint32_t wakeup_time, uint8_t *txBuffer, uint8_t *rxBuffer,
1440 uint32_t receive_timeout,
1441 uint8_t receive_length,
1442 uint8_t (*Callback)(ActionPacket *, ActionPacket *))
1443 {
1444 uint8_t returnValue = SUCCESS_0;
1445 uint32_t dummy;
1446 uint32_t time;
1447
1448 time = (uint32_t)HAL_RADIO_TIMER_GetCurrentSysTime() + HAL_RADIO_TIMER_UsToSystime(wakeup_time);
1449
1450 if (channel > 39)
1451 {
1452 returnValue = INVALID_PARAMETER_C0;
1453 }
1454
1455 if (HAL_RADIO_GetStatus(&dummy) != BLUE_IDLE_0)
1456 {
1457 returnValue = RADIO_BUSY_C4;
1458 }
1459
1460 uint8_t map[5] = {0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU};
1461 HAL_RADIO_SetChannelMap(0, &map[0]);
1462 HAL_RADIO_SetChannel(0, channel, 0);
1463 HAL_RADIO_SetTxAttributes(0, networkID, 0x555555);
1464 HAL_RADIO_SetGlobalReceiveTimeout(receive_timeout);
1465
1466 aPacket[0].StateMachineNo = 0;
1467 aPacket[0].ActionTag = TXRX | PLL_TRIG;
1468 aPacket[0].WakeupTime = time;
1469 aPacket[0].MaxReceiveLength = 0; /* does not affect for Tx */
1470 aPacket[0].data = txBuffer;
1471 aPacket[0].next_true = &aPacket[1];
1472 aPacket[0].next_false = &aPacket[1];
1473 aPacket[0].condRoutine = CondRoutineTrue;
1474 aPacket[0].dataRoutine = DataRoutineNull;
1475
1476 aPacket[1].StateMachineNo = 0;
1477 aPacket[1].ActionTag = 0;
1478 aPacket[1].WakeupTime = time;
1479 aPacket[1].MaxReceiveLength = receive_length;
1480 aPacket[1].data = rxBuffer;
1481 aPacket[1].next_true = NULL_0;
1482 aPacket[1].next_false = NULL_0;
1483 aPacket[1].condRoutine = CondRoutineTrue;
1484 aPacket[1].dataRoutine = Callback;
1485
1486 HAL_RADIO_SetReservedArea(&aPacket[0]);
1487 HAL_RADIO_SetReservedArea(&aPacket[1]);
1488 returnValue = HAL_RADIO_MakeActionPacketPending(&aPacket[0]);
1489
1490 return returnValue;
1491 }
1492
1493 #if defined (STM32WB06) || defined (STM32WB07)
1494
CarrierSenseCallback(ActionPacket * p,ActionPacket * next)1495 static uint8_t CarrierSenseCallback(ActionPacket *p, ActionPacket *next)
1496 {
1497 return TRUE;
1498 }
1499
1500 /**
1501 * @brief This function puts the radio in RX state to read the RSSI.
1502 * @note The function uses a busy loop to wait for the RSSI value and then exits
1503 * from RX state.
1504 * @param channel: BLE channel index between 0 to 39.
1505 * @param[out] rssi: the measured RSSI value on the channel
1506 * @retval uint8_t return value
1507 * - 0x00 : Success.
1508 * - 0xC0 : Invalid parameter.
1509 * - 0xC4 : Radio is busy, receiving has not been triggered.
1510 */
HAL_RADIO_CarrierSense(uint8_t channel,int8_t * rssi)1511 uint8_t HAL_RADIO_CarrierSense(uint8_t channel, int8_t *rssi)
1512 {
1513 uint8_t ret;
1514 uint16_t loop = 0;
1515 uint32_t *DEMOD_DIG_TST_p = (uint32_t *)0x60001564;
1516 uint32_t end_time;
1517 static uint8_t buffer[1];
1518
1519 *rssi = 127;
1520
1521 uint32_t networkID_tmp = networkID;
1522
1523 networkID = FAKE_NETWORK_ID;
1524
1525 ret = HAL_RADIO_ReceivePacket(channel, 300, buffer, 1000, sizeof(buffer), CarrierSenseCallback);
1526
1527 networkID = networkID_tmp;
1528
1529 if (ret)
1530 {
1531 return ret;
1532 }
1533
1534 /* loop variable just to protect from infinite loop */
1535 while ((RRM->FSM_STATUS_DIG_OUT & RRM_FSM_STATUS_DIG_OUT_STATUS) != 0x1A && loop++ < 60000);
1536 end_time = WAKEUP->ABSOLUTE_TIME + 20;
1537 while (TIME_DIFF(end_time, WAKEUP->ABSOLUTE_TIME) > 0);
1538 *DEMOD_DIG_TST_p = 0x02;
1539 /* Need to wait at least 3 BLE clocks. In worst case (sysclock = 64 MHz and blesysclk = 16 MHz)
1540 this means 12 cpu cycles. Some cycles are already used by the call to HAL_RADIO_ReadRSSI()
1541 and at the beginning of the function. */
1542 __NOP();
1543 __NOP();
1544 __NOP();
1545 __NOP();
1546 __NOP();
1547 __NOP();
1548 __NOP();
1549 __NOP();
1550 *rssi = HAL_RADIO_ReadRSSI();
1551 *DEMOD_DIG_TST_p = 0x00;
1552 BLUE->CMDREG = BLUE_CMDREG_TXRXSKIP;
1553
1554 return 0;
1555 }
1556
1557 #elif defined(STM32WB05) || defined(STM32WB09 )
1558
1559 static volatile int8_t _rssi;
1560 static volatile uint8_t _timeout;
1561
CarrierSenseCallback(ActionPacket * p,ActionPacket * next)1562 static uint8_t CarrierSenseCallback(ActionPacket *p, ActionPacket *next)
1563 {
1564 _rssi = 127;
1565
1566 if ((p->status & BLUE_INTERRUPT1REG_DONE) && (p->status & BLUE_STATUSREG_PREVTRANSMIT) == 0 &&
1567 ((p->status & BLUE_INTERRUPT1REG_RCVOK) || (p->status & BLUE_INTERRUPT1REG_RCVTIMEOUT)
1568 || (p->status & BLUE_INTERRUPT1REG_RCVCRCERR)))
1569 {
1570 _rssi = p->rssi;
1571 }
1572 _timeout = TRUE;
1573
1574 return TRUE;
1575 }
1576
1577 /**
1578 * @brief This function puts the radio in RX state to read the RSSI.
1579 * @note The function uses a busy loop to wait for the RSSI value and then exits
1580 * from RX state.
1581 * @param channel: BLE channel index between 0 to 39.
1582 * @param[out] rssi: the measured RSSI value on the channel
1583 * @retval uint8_t return value
1584 * - 0x00 : Success.
1585 * - 0xC0 : Invalid parameter.
1586 * - 0xC4 : Radio is busy, receiving has not been triggered.
1587 */
HAL_RADIO_CarrierSense(uint8_t channel,int8_t * rssi)1588 uint8_t HAL_RADIO_CarrierSense(uint8_t channel, int8_t *rssi)
1589 {
1590 uint8_t ret;
1591 uint16_t loop = 0;
1592 static uint8_t buffer[1];
1593
1594 *rssi = 127;
1595
1596 uint32_t networkID_tmp = networkID;
1597
1598 networkID = FAKE_NETWORK_ID;
1599
1600 _timeout = FALSE;
1601
1602 ret = HAL_RADIO_ReceivePacket(channel, 300, buffer, 5, sizeof(buffer), CarrierSenseCallback);
1603
1604 networkID = networkID_tmp;
1605
1606 if (ret)
1607 {
1608 return ret;
1609 }
1610
1611 /* loop variable just to protect from infinite loop */
1612 while (_timeout == FALSE && loop++ < 60000);
1613 *rssi = _rssi;
1614
1615 return 0;
1616 }
1617
1618 #endif
1619
1620 /**
1621 * @brief This routine receives a packet on a specific channel and at a certain time.
1622 * @param channel: BLE channel index between 0 to 39.
1623 * @param wakeup_time: Time of transmission based on us. This is relative time regarding now.
1624 * Minimum wakeup_time of 230 us. TBR
1625 * @param rxBuffer: Pointer to RX data buffer. Second byte of this buffer must be the length of the data.
1626 * @param receive_timeout: Time of RX window used to wait for the packet on us.
1627 * @param receive_length: number of bytes that the link layer accepts in reception.
1628 * @param Callback: This function is being called as data routine.
1629 * First ActionPacket is current action packet and the second one is next action packet.
1630 * @retval uint8_t return value
1631 * - 0x00 : Success.
1632 * - 0xC0 : Invalid parameter.
1633 * - 0xC4 : Radio is busy, receiving has not been triggered.
1634 */
HAL_RADIO_ReceivePacket(uint8_t channel,uint32_t wakeup_time,uint8_t * rxBuffer,uint32_t receive_timeout,uint8_t receive_length,uint8_t (* Callback)(ActionPacket *,ActionPacket *))1635 uint8_t HAL_RADIO_ReceivePacket(uint8_t channel, uint32_t wakeup_time, uint8_t *rxBuffer, uint32_t receive_timeout,
1636 uint8_t receive_length,
1637 uint8_t (*Callback)(ActionPacket *, ActionPacket *))
1638 {
1639 uint8_t returnValue = SUCCESS_0;
1640 uint32_t dummy;
1641 uint32_t time;
1642 time = (uint32_t)HAL_RADIO_TIMER_GetCurrentSysTime() + HAL_RADIO_TIMER_UsToSystime(wakeup_time);
1643
1644 if (channel > 39)
1645 {
1646 returnValue = INVALID_PARAMETER_C0;
1647 }
1648
1649 if (HAL_RADIO_GetStatus(&dummy) != BLUE_IDLE_0)
1650 {
1651 returnValue = RADIO_BUSY_C4;
1652 }
1653
1654 if (returnValue == SUCCESS_0)
1655 {
1656 uint8_t map[5] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
1657 HAL_RADIO_SetChannelMap(0, &map[0]);
1658 HAL_RADIO_SetChannel(0, channel, 0);
1659 HAL_RADIO_SetTxAttributes(0, networkID, 0x555555);
1660 HAL_RADIO_SetGlobalReceiveTimeout(receive_timeout);
1661
1662
1663 aPacket[0].StateMachineNo = 0;
1664 aPacket[0].ActionTag = PLL_TRIG;
1665 aPacket[0].WakeupTime = time;
1666 aPacket[0].MaxReceiveLength = receive_length;
1667 aPacket[0].data = rxBuffer;
1668 aPacket[0].next_true = NULL_0;
1669 aPacket[0].next_false = NULL_0;
1670 aPacket[0].condRoutine = CondRoutineTrue;
1671 aPacket[0].dataRoutine = Callback;
1672
1673 HAL_RADIO_SetReservedArea(&aPacket[0]);
1674 returnValue = HAL_RADIO_MakeActionPacketPending(&aPacket[0]);
1675 }
1676
1677 return returnValue;
1678 }
1679
1680 /**
1681 * @brief This routine receives a packet on a specific channel and at a certain time.
1682 * Then sends a packet as an acknowledgment.
1683 * @param channel: BLE channel index between 0 to 39.
1684 * @param wakeup_time: time of transmission based on us. This is relative time regarding now.
1685 * Minimum wakeup_time of 250 us. TBR
1686 * @param rxBuffer: points to received data buffer. second byte of this buffer determines the length of the data.
1687 * @param txBuffer: points to data buffer to send. second byte of this buffer must be the length of the buffer.
1688 * @param receive_timeout: Time of RX window used to wait for the packet on us.
1689 * @param receive_length: number of bytes that the link layer accepts in reception.
1690 * @param Callback: This function is being called as data routine.
1691 * First ActionPacket is current action packet and the second one is next action packet.
1692 * @retval uint8_t return value
1693 * - 0x00 : Success.
1694 * - 0xC0 : Invalid parameter.
1695 * - 0xC4 : Radio is busy, receiving has not been triggered.
1696 */
HAL_RADIO_ReceivePacketWithAck(uint8_t channel,uint32_t wakeup_time,uint8_t * rxBuffer,uint8_t * txBuffer,uint32_t receive_timeout,uint8_t receive_length,uint8_t (* Callback)(ActionPacket *,ActionPacket *))1697 uint8_t HAL_RADIO_ReceivePacketWithAck(uint8_t channel, uint32_t wakeup_time, uint8_t *rxBuffer, uint8_t *txBuffer,
1698 uint32_t receive_timeout,
1699 uint8_t receive_length,
1700 uint8_t (*Callback)(ActionPacket *, ActionPacket *))
1701 {
1702 uint8_t returnValue = SUCCESS_0;
1703 uint32_t dummy;
1704 uint32_t time;
1705
1706 time = (uint32_t)HAL_RADIO_TIMER_GetCurrentSysTime() + HAL_RADIO_TIMER_UsToSystime(wakeup_time);
1707
1708 if (channel > 39)
1709 {
1710 returnValue = INVALID_PARAMETER_C0;
1711 }
1712
1713 if (HAL_RADIO_GetStatus(&dummy) != BLUE_IDLE_0)
1714 {
1715 returnValue = RADIO_BUSY_C4;
1716 }
1717
1718 if (returnValue == SUCCESS_0)
1719 {
1720 uint8_t map[5] = {0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU};
1721
1722 HAL_RADIO_SetChannelMap(0, &map[0]);
1723 HAL_RADIO_SetChannel(0, channel, 0);
1724 HAL_RADIO_SetTxAttributes(0, networkID, 0x555555);
1725 HAL_RADIO_SetGlobalReceiveTimeout(receive_timeout);
1726
1727 aPacket[0].StateMachineNo = 0;
1728 aPacket[0].ActionTag = PLL_TRIG;
1729 aPacket[0].WakeupTime = time;
1730 aPacket[0].MaxReceiveLength = receive_length;
1731 aPacket[0].data = rxBuffer;
1732 aPacket[0].next_true = &aPacket[1];
1733 aPacket[0].next_false = NULL_0;
1734 aPacket[0].condRoutine = CondRoutineRxTrue;
1735 aPacket[0].dataRoutine = Callback;
1736
1737 aPacket[1].StateMachineNo = 0;
1738 aPacket[1].ActionTag = TXRX;
1739 aPacket[1].WakeupTime = time;
1740 aPacket[1].MaxReceiveLength = 0; /* does not affect for Tx */
1741 aPacket[1].data = txBuffer;
1742 aPacket[1].next_true = NULL_0;
1743 aPacket[1].next_false = NULL_0;
1744 aPacket[1].condRoutine = CondRoutineTrue;
1745 aPacket[1].dataRoutine = Callback;
1746
1747 HAL_RADIO_SetReservedArea(&aPacket[0]);
1748 HAL_RADIO_SetReservedArea(&aPacket[1]);
1749 returnValue = HAL_RADIO_MakeActionPacketPending(&aPacket[0]);
1750 }
1751
1752 return returnValue;
1753 }
1754
1755 #endif /* USE_RADIO_PROPRIETARY_DRIVER */
1756
HAL_RADIO_TxRxCallback(uint32_t flags)1757 __weak void HAL_RADIO_TxRxCallback(uint32_t flags)
1758 {
1759 }
1760
1761
HAL_RADIO_TxRxSeqCallback(void)1762 __weak void HAL_RADIO_TxRxSeqCallback(void)
1763 {
1764 }
1765
HAL_RADIO_TXRX_IRQHandler(void)1766 void HAL_RADIO_TXRX_IRQHandler(void)
1767 {
1768 uint32_t blue_status = BLUE->STATUSREG;
1769 uint32_t blue_interrupt = BLUE->INTERRUPT1REG;
1770
1771 /** clear all pending interrupts */
1772 BLUE->INTERRUPT1REG = blue_interrupt;
1773
1774 HAL_RADIO_TIMER_EndOfRadioActivityIsr();
1775
1776 #if (USE_RADIO_PROPRIETARY_DRIVER == 1)
1777 HAL_RADIO_ActionPacketIsr(blue_status | blue_interrupt);
1778 #endif
1779
1780 HAL_RADIO_TxRxCallback(blue_status | blue_interrupt);
1781
1782 HAL_RADIO_TIMER_RadioTimerIsr();
1783
1784 /* If the device is configured with
1785 System clock = 64 MHz and BLE clock = 16 MHz
1786 a register read is necessary to end fine
1787 the clear interrupt register operation,
1788 due the AHB down converter latency */
1789 blue_interrupt = BLUE->INTERRUPT1REG;
1790 }
1791
1792
HAL_RADIO_TXRX_SEQ_IRQHandler(void)1793 void HAL_RADIO_TXRX_SEQ_IRQHandler(void)
1794 {
1795 HAL_RADIO_TxRxSeqCallback();
1796 }
1797
1798 /**
1799 * @}
1800 */
1801
1802 /**
1803 * @}
1804 */
1805
1806 /**
1807 * @}
1808 */
1809