1 /*******************************************************************************
2   * @file    stm32wlxx_hal_subghz.c
3   * @author  MCD Application Team
4   * @brief   SUBGHZ HAL module driver.
5   *          This file provides firmware functions to manage the following
6   *          functionalities of the SUBGHZ peripheral:
7   *           + Initialization and de-initialization functions
8   *           + IO operation functions
9   *           + Peripheral State and Errors functions
10   *
11   ******************************************************************************
12   * @attention
13   *
14   * Copyright (c) 2020 STMicroelectronics.
15   * All rights reserved.
16   *
17   * This software is licensed under terms that can be found in the LICENSE file
18   * in the root directory of this software component.
19   * If no LICENSE file comes with this software, it is provided AS-IS.
20   *
21   ******************************************************************************
22  @verbatim
23  ==============================================================================
24                        ##### How to use this driver #####
25  ==============================================================================
26  [..]
27     The SUBGHZ HAL driver can be used as follows:
28 
29     (#) Declare a SUBGHZ_HandleTypeDef handle structure, for example:
30         SUBGHZ_HandleTypeDef hUserSubghz;
31 
32     (#) Initialize the SUBGHZ low level resources by implementing the @ref HAL_SUBGHZ_MspInit() API:
33         (##) PWR configuration
34             (+++) Enable the SUBGHZSPI interface clock
35             (+++) Enable wakeup signal of the Radio peripheral
36         (##) NVIC configuration:
37             (+++) Enable the NVIC Radio IRQ ITs for CPU1 (EXTI 44)
38             (+++) Configure the Radio interrupt priority
39 
40     (#) Initialize the SUBGHZ handle and SUBGHZSPI SPI registers by calling the @ref HAL_SUBGHZ_Init(&hUserSubghz),
41         configures also the low level Hardware (GPIO, CLOCK, NVIC...etc) by calling
42         the customized @ref HAL_SUBGHZ_MspInit() API.
43 
44     (#) For SUBGHZ IO operations, polling operation modes is available within this driver :
45 
46     *** Polling mode IO operation      ***
47     =====================================
48     [..]
49       (+) Set and execute a command in blocking mode using @ref HAL_SUBGHZ_ExecSetCmd()
50       (+) Get a status blocking mode using @ref HAL_SUBGHZ_ExecGetCmd()
51       (+) Write a Data Buffer in blocking mode using @ref HAL_SUBGHZ_WriteBuffer()
52       (+) Read a Data Buffer  in blocking mode using @ref HAL_SUBGHZ_ReadBuffer()
53       (+) Write Registers (more than 1 byte) in blocking mode using @ref HAL_SUBGHZ_WriteRegisters()
54       (+) Read Registers (more than 1 byte) in blocking mode using @ref HAL_SUBGHZ_ReadRegisters()
55       (+) Write Register (1 byte) in blocking mode using @ref HAL_SUBGHZ_WriteRegister()
56       (+) Read Register (1 byte) in blocking mode using @ref HAL_SUBGHZ_ReadRegister()
57 
58     *** SUBGHZ HAL driver macros list ***
59     =====================================
60     [..]
61       (+) @ref __HAL_SUBGHZ_RESET_HANDLE_STATE: Reset the SUBGHZ handle state
62 
63 #if defined(GENERATOR_CALLBACK_REGISTERING_PRESENT)
64      *** SUBGHZ Callback registration  ***
65      =====================================
66 
67     [..]
68      The compilation flag USE_HAL_SUBGHZ_REGISTER_CALLBACKS when set to 1
69      allows the user to configure dynamically the driver callbacks.
70      Use Functions @ref HAL_SUBGHZ_RegisterCallback() or @ref HAL_SUBGHZ_RegisterAddrCallback()
71      to register an interrupt callback.
72 
73     [..]
74      Function @ref HAL_SUBGHZ_RegisterCallback() allows to register following callbacks:
75        (+) TxCpltCallback           : callback for Tx Completed.
76        (+) RxCpltCallback           : callback for Rx Completed.
77        (+) PreambleDetectedCallback : callback for Preamble detected.
78        (+) SyncWordValidCallback    : callback for Synchro word valid.
79        (+) HeaderValidCallback      : callback for Header valid.
80        (+) HeaderErrorCallback      : callback for Header error.
81        (+) CRCErrorCallback         : callback for CRC Error.
82        (+) RxTxTimeoutCallback      : callback for Rx Tx Timeout.
83        (+) MspInitCallback          : callback for Msp Init.
84        (+) MspDeInitCallback        : callback for Msp DeInit.
85        (+) LrFhssHopCallback        : callback for LoRa Frequency Hopping Spread Spectrum Hopping.
86      This function takes as parameters the HAL peripheral handle, the Callback ID
87      and a pointer to the user callback function.
88     [..]
89      For specific callback CADStatusCallback use dedicated register callbacks :
90      @ref HAL_SUBGHZ_RegisterCadStatusCallback().
91     [..]
92      Use function @ref HAL_SUBGHZ_UnRegisterCallback to reset a callback to the default
93      weak function.
94      @ref HAL_SUBGHZ_UnRegisterCallback takes as parameters the HAL peripheral handle,
95      and the Callback ID.
96      This function allows to reset following callbacks:
97        (+) TxCpltCallback           : callback for Tx Completed.
98        (+) RxCpltCallback           : callback for Rx Completed.
99        (+) PreambleDetectedCallback : callback for Preamble detected.
100        (+) SyncWordValidCallback    : callback for Synchro word valid.
101        (+) HeaderValidCallback      : callback for Header valid.
102        (+) HeaderErrorCallback      : callback for Header error.
103        (+) CRCErrorCallback         : callback for CRC Error.
104        (+) RxTxTimeoutCallback      : callback for Rx Tx Timeout.
105        (+) MspInitCallback          : callback for Msp Init.
106        (+) MspDeInitCallback        : callback for Msp DeInit.
107        (+) LrFhssHopCallback        : callback for LoRa Frequency Hopping Spread Spectrum Hopping.
108     [..]
109      For specific callback CADStatusCallback use dedicated register callbacks :
110      @ref HAL_SUBGHZ_UnRegisterCadStatusCallback().
111     [..]
112      MspInit and MspDeInit functions are reset to the legacy weak functions in the
113      @ref HAL_SUBGHZ_Init()/ @ref HAL_SUBGHZ_DeInit() only when these callbacks are null
114      (not registered beforehand).
115      If MspInit or MspDeInit are not null, the @ref HAL_SUBGHZ_Init()/ @ref HAL_SUBGHZ_DeInit()
116      keep and use the user MspInit/MspDeInit callbacks (registered beforehand) whatever the state.
117 
118     [..]
119      Callbacks for MspInit/MspDeInit functions can be registered/unregistered
120      in @ref HAL_SUBGHZ_STATE_READY or @ref HAL_SUBGHZ_STATE_RESET state,
121      thus registered (user) MspInit/DeInit callbacks can be used during the Init/DeInit.
122      Then, the user first registers the MspInit/MspDeInit user callbacks
123      using @ref HAL_SUBGHZ_RegisterCallback() before calling @ref HAL_SUBGHZ_DeInit()
124      or @ref HAL_SUBGHZ_Init() function.
125 
126     [..]
127      When the compilation flag USE_HAL_SUBGHZ_REGISTER_CALLBACKS is set to 0 or
128      not defined, the callback registration feature is not available and all callbacks
129      are set to the corresponding weak functions.
130 #endif
131   */
132 
133 /* Includes ------------------------------------------------------------------*/
134 #include "stm32wlxx_hal.h"
135 
136 /** @addtogroup STM32WLxx_HAL_Driver
137   * @{
138   */
139 
140 /** @defgroup SUBGHZ SUBGHZ
141   * @brief SUBGHZ HAL module driver
142   * @{
143   */
144 #ifdef HAL_SUBGHZ_MODULE_ENABLED
145 
146 /* Private typedef -----------------------------------------------------------*/
147 /* Private defines -----------------------------------------------------------*/
148 /** @defgroup SUBGHZ_Private_Constants SUBGHZ Private Constants
149   * @{
150   */
151 #define SUBGHZ_DEFAULT_TIMEOUT     100U    /* HAL Timeout in ms               */
152 #define SUBGHZ_DUMMY_DATA          0xFFU   /* SUBGHZSPI Dummy Data use for Tx */
153 #define SUBGHZ_DEEP_SLEEP_ENABLE   1U      /* SUBGHZ Radio in Deep Sleep      */
154 #define SUBGHZ_DEEP_SLEEP_DISABLE  0U      /* SUBGHZ Radio not in Deep Sleep  */
155 
156 /* SystemCoreClock dividers. Corresponding to time execution of while loop.   */
157 #define SUBGHZ_DEFAULT_LOOP_TIME   ((SystemCoreClock*28U)>>19U)
158 #define SUBGHZ_RFBUSY_LOOP_TIME    ((SystemCoreClock*24U)>>20U)
159 #define SUBGHZ_NSS_LOOP_TIME       ((SystemCoreClock*24U)>>16U)
160 /**
161   * @}
162   */
163 
164 /* Private macros ------------------------------------------------------------*/
165 /* Private variables ---------------------------------------------------------*/
166 /* Private function prototypes -----------------------------------------------*/
167 /** @defgroup SUBGHZ_Private_Functions SUBGHZ Private Functions
168   * @{
169   */
170 void              SUBGHZSPI_Init(uint32_t BaudratePrescaler);
171 void              SUBGHZSPI_DeInit(void);
172 HAL_StatusTypeDef SUBGHZSPI_Transmit(SUBGHZ_HandleTypeDef *hsubghz, uint8_t Data);
173 HAL_StatusTypeDef SUBGHZSPI_Receive(SUBGHZ_HandleTypeDef *hsubghz, uint8_t *pData);
174 HAL_StatusTypeDef SUBGHZ_WaitOnBusy(SUBGHZ_HandleTypeDef *hsubghz);
175 HAL_StatusTypeDef SUBGHZ_CheckDeviceReady(SUBGHZ_HandleTypeDef *hsubghz);
176 /**
177   * @}
178   */
179 
180 /* Exported functions --------------------------------------------------------*/
181 /** @defgroup SUBGHZ_Exported_Functions SUBGHZ Exported Functions
182   * @{
183   */
184 
185 /** @defgroup SUBGHZ_Exported_Functions_Group1 Initialization and de-initialization functions
186   *  @brief    Initialization and Configuration functions
187   *
188 @verbatim
189  ===============================================================================
190               ##### Initialization and de-initialization functions #####
191  ===============================================================================
192     [..]  This subsection provides a set of functions allowing to initialize and
193           de-initialize the SUBGHZ peripheral:
194 
195       (+) User must implement HAL_SUBGHZ_MspInit() function in which he configures
196           all related peripherals resources (CLOCK, GPIO, IT and NVIC ).
197 
198       (+) Call the function HAL_SUBGHZ_Init() to configure SUBGHZSPI peripheral
199           and initialize SUBGHZ Handle.
200 
201       (+) Call the function HAL_SUBGHZ_DeInit() to restore the default configuration
202           of the SUBGHZ peripheral.
203 
204 @endverbatim
205   * @{
206   */
207 
208 /**
209   * @brief  Initialize the SUBGHZ according to the specified parameters
210   *         in the SUBGHZ_HandleTypeDef and initialize the associated handle.
211   * @param  hsubghz pointer to a SUBGHZ_HandleTypeDef structure that contains
212   *         the handle information for SUBGHZ module.
213   * @note   In case of exiting from Standby mode, before calling this function,
214   *         set the state to HAL_SUBGHZ_STATE_RESET_RF_READY with __HAL_SUBGHZ_RESET_HANDLE_STATE_RF_READY
215   *         to avoid the reset of Radio peripheral.
216   * @retval HAL status
217   */
HAL_SUBGHZ_Init(SUBGHZ_HandleTypeDef * hsubghz)218 HAL_StatusTypeDef HAL_SUBGHZ_Init(SUBGHZ_HandleTypeDef *hsubghz)
219 {
220   HAL_StatusTypeDef status;
221   __IO uint32_t count;
222   HAL_SUBGHZ_StateTypeDef subghz_state;
223 
224   /* Check the hsubghz handle allocation */
225   if (hsubghz == NULL)
226   {
227     status = HAL_ERROR;
228     return status;
229   }
230   else
231   {
232     status = HAL_OK;
233   }
234 
235   assert_param(IS_SUBGHZSPI_BAUDRATE_PRESCALER(hsubghz->Init.BaudratePrescaler));
236 
237   subghz_state = hsubghz->State;
238   if ((subghz_state == HAL_SUBGHZ_STATE_RESET) ||
239       (subghz_state == HAL_SUBGHZ_STATE_RESET_RF_READY))
240   {
241     /* Allocate lock resource and initialize it */
242     hsubghz->Lock = HAL_UNLOCKED;
243 
244 #if (USE_HAL_SUBGHZ_REGISTER_CALLBACKS == 1)
245     /* Init the SUBGHZ Legacy weak Callback settings */
246     hsubghz->TxCpltCallback              = HAL_SUBGHZ_TxCpltCallback;
247     hsubghz->RxCpltCallback              = HAL_SUBGHZ_RxCpltCallback;
248     hsubghz->PreambleDetectedCallback    = HAL_SUBGHZ_PreambleDetectedCallback;
249     hsubghz->SyncWordValidCallback       = HAL_SUBGHZ_SyncWordValidCallback;
250     hsubghz->HeaderValidCallback         = HAL_SUBGHZ_HeaderValidCallback;
251     hsubghz->HeaderErrorCallback         = HAL_SUBGHZ_HeaderErrorCallback;
252     hsubghz->CRCErrorCallback            = HAL_SUBGHZ_CRCErrorCallback;
253     hsubghz->CADStatusCallback           = HAL_SUBGHZ_CADStatusCallback;
254     hsubghz->RxTxTimeoutCallback         = HAL_SUBGHZ_RxTxTimeoutCallback;
255     hsubghz->LrFhssHopCallback           = HAL_SUBGHZ_LrFhssHopCallback;
256 
257     if (hsubghz->MspInitCallback == NULL)
258     {
259       hsubghz->MspInitCallback = HAL_SUBGHZ_MspInit; /* Legacy weak MspInit  */
260     }
261 
262     /* Init the low level hardware : GPIO, CLOCK, NVIC... */
263     hsubghz->MspInitCallback(hsubghz);
264 #else
265     /* Init the low level hardware : GPIO, CLOCK, NVIC... */
266     HAL_SUBGHZ_MspInit(hsubghz);
267 #endif /* USE_HAL_ SUBGHZ_REGISTER_CALLBACKS */
268 
269 #if defined(CM0PLUS)
270     /* Enable EXTI 44 : Radio IRQ ITs for CPU2 */
271     LL_C2_EXTI_EnableIT_32_63(LL_EXTI_LINE_44);
272 #else
273     /* Enable EXTI 44 : Radio IRQ ITs for CPU1 */
274     LL_EXTI_EnableIT_32_63(LL_EXTI_LINE_44);
275 #endif /* CM0PLUS */
276   }
277 
278   if (subghz_state == HAL_SUBGHZ_STATE_RESET)
279   {
280     /* Reinitialize Radio peripheral only if SUBGHZ is in full RESET state */
281     hsubghz->State = HAL_SUBGHZ_STATE_BUSY;
282 
283     /* De-asserts the reset signal of the Radio peripheral */
284     LL_RCC_RF_DisableReset();
285 
286     /* Verify that Radio in reset status flag is set */
287     count  = SUBGHZ_DEFAULT_TIMEOUT * SUBGHZ_DEFAULT_LOOP_TIME;
288 
289     do
290     {
291       if (count == 0U)
292       {
293         status  = HAL_ERROR;
294         hsubghz->ErrorCode = HAL_SUBGHZ_ERROR_TIMEOUT;
295         break;
296       }
297       count--;
298     } while (LL_RCC_IsRFUnderReset() != 0UL);
299 
300     /* Asserts the reset signal of the Radio peripheral */
301     LL_PWR_UnselectSUBGHZSPI_NSS();
302 
303 #if defined(CM0PLUS)
304     /* Enable wakeup signal of the Radio peripheral */
305     LL_C2_PWR_SetRadioBusyTrigger(LL_PWR_RADIO_BUSY_TRIGGER_WU_IT);
306 #else
307     /* Enable wakeup signal of the Radio peripheral */
308     LL_PWR_SetRadioBusyTrigger(LL_PWR_RADIO_BUSY_TRIGGER_WU_IT);
309 #endif /* CM0PLUS */
310   }
311 
312   /* Clear Pending Flag */
313   LL_PWR_ClearFlag_RFBUSY();
314 
315   if (status == HAL_OK)
316   {
317     /* Initialize SUBGHZSPI Peripheral */
318     SUBGHZSPI_Init(hsubghz->Init.BaudratePrescaler);
319 
320     hsubghz->DeepSleep = SUBGHZ_DEEP_SLEEP_ENABLE;
321     hsubghz->ErrorCode = HAL_SUBGHZ_ERROR_NONE;
322   }
323 
324   hsubghz->State = HAL_SUBGHZ_STATE_READY;
325 
326   return status;
327 }
328 
329 /**
330   * @brief  De-Initialize the SUBGHZ peripheral.
331   * @param  hsubghz pointer to a SUBGHZ_HandleTypeDef structure that contains
332   *         the handle information for SUBGHZ module.
333   * @retval HAL status
334   */
HAL_SUBGHZ_DeInit(SUBGHZ_HandleTypeDef * hsubghz)335 HAL_StatusTypeDef HAL_SUBGHZ_DeInit(SUBGHZ_HandleTypeDef *hsubghz)
336 {
337   HAL_StatusTypeDef status;
338   __IO uint32_t count;
339 
340   /* Check the SUBGHZ handle allocation */
341   if (hsubghz == NULL)
342   {
343     status = HAL_ERROR;
344     return status;
345   }
346   else
347   {
348     status = HAL_OK;
349   }
350 
351   hsubghz->State = HAL_SUBGHZ_STATE_BUSY;
352 
353   /* DeInitialize SUBGHZSPI Peripheral */
354   SUBGHZSPI_DeInit();
355 
356 #if (USE_HAL_SUBGHZ_REGISTER_CALLBACKS == 1)
357   if (hsubghz->MspDeInitCallback == NULL)
358   {
359     hsubghz->MspDeInitCallback = HAL_SUBGHZ_MspDeInit; /* Legacy weak MspDeInit  */
360   }
361 
362   /* DeInit the low level hardware: GPIO, CLOCK, NVIC... */
363   hsubghz->MspDeInitCallback(hsubghz);
364 #else
365   /* DeInit the low level hardware: GPIO, CLOCK, NVIC... */
366   HAL_SUBGHZ_MspDeInit(hsubghz);
367 #endif /* USE_HAL_SUBGHZ_REGISTER_CALLBACKS */
368 
369 #if defined(CM0PLUS)
370   /* Disable EXTI 44 : Radio IRQ ITs for CPU2 */
371   LL_C2_EXTI_DisableIT_32_63(LL_EXTI_LINE_44);
372 
373   /* Disable wakeup signal of the Radio peripheral */
374   LL_C2_PWR_SetRadioBusyTrigger(LL_PWR_RADIO_BUSY_TRIGGER_NONE);
375 #else
376   /* Disable EXTI 44 : Radio IRQ ITs for CPU1 */
377   LL_EXTI_DisableIT_32_63(LL_EXTI_LINE_44);
378 
379   /* Disable wakeup signal of the Radio peripheral */
380   LL_PWR_SetRadioBusyTrigger(LL_PWR_RADIO_BUSY_TRIGGER_NONE);
381 #endif /* CM0PLUS */
382 
383   /* Clear Pending Flag */
384   LL_PWR_ClearFlag_RFBUSY();
385 
386   /* Re-asserts the reset signal of the Radio peripheral */
387   LL_RCC_RF_EnableReset();
388 
389   /* Verify that Radio in reset status flag is set */
390   count  = SUBGHZ_DEFAULT_TIMEOUT * SUBGHZ_DEFAULT_LOOP_TIME;
391 
392   do
393   {
394     if (count == 0U)
395     {
396       status  = HAL_ERROR;
397       hsubghz->ErrorCode = HAL_SUBGHZ_ERROR_TIMEOUT;
398       break;
399     }
400     count--;
401   } while (LL_RCC_IsRFUnderReset() != 1UL);
402 
403   hsubghz->ErrorCode = HAL_SUBGHZ_ERROR_NONE;
404   hsubghz->State     = HAL_SUBGHZ_STATE_RESET;
405 
406   /* Release Lock */
407   __HAL_UNLOCK(hsubghz);
408 
409   return status;
410 }
411 
412 /**
413   * @brief  Initialize the SUBGHZ MSP.
414   * @param  hsubghz pointer to a SUBGHZ_HandleTypeDef structure that contains
415   *         the handle information for SUBGHZ module.
416   * @retval None
417   */
HAL_SUBGHZ_MspInit(SUBGHZ_HandleTypeDef * hsubghz)418 __weak void HAL_SUBGHZ_MspInit(SUBGHZ_HandleTypeDef *hsubghz)
419 {
420   /* NOTE : This function should not be modified, when the callback is needed,
421             the HAL_SUBGHZ_MspInit should be implemented in the user file
422    */
423 
424   /* Prevent unused argument(s) compilation warning */
425   UNUSED(hsubghz);
426 }
427 
428 /**
429   * @brief  De-Initialize the SUBGHZ MSP.
430   * @param  hsubghz pointer to a SUBGHZ_HandleTypeDef structure that contains
431   *         the handle information for SUBGHZ module.
432   * @retval None
433   */
HAL_SUBGHZ_MspDeInit(SUBGHZ_HandleTypeDef * hsubghz)434 __weak void HAL_SUBGHZ_MspDeInit(SUBGHZ_HandleTypeDef *hsubghz)
435 {
436   /* NOTE : This function should not be modified, when the callback is needed,
437             the HAL_SUBGHZ_MspDeInit should be implemented in the user file
438    */
439 
440   /* Prevent unused argument(s) compilation warning */
441   UNUSED(hsubghz);
442 }
443 
444 #if (USE_HAL_SUBGHZ_REGISTER_CALLBACKS == 1)
445 /**
446   * @brief  Register a User SUBGHZ Callback
447   *         To be used instead of the weak predefined callback
448   * @param  hsubghz pointer to a SUBGHZ_HandleTypeDef structure that contains
449   *         the configuration information for the specified SUBGHZ.
450   * @param  CallbackID ID of the callback to be registered
451   * @param  pCallback pointer to the Callback function
452   * @retval HAL status
453   */
HAL_SUBGHZ_RegisterCallback(SUBGHZ_HandleTypeDef * hsubghz,HAL_SUBGHZ_CallbackIDTypeDef CallbackID,pSUBGHZ_CallbackTypeDef pCallback)454 HAL_StatusTypeDef HAL_SUBGHZ_RegisterCallback(SUBGHZ_HandleTypeDef *hsubghz,
455                                               HAL_SUBGHZ_CallbackIDTypeDef CallbackID,
456                                               pSUBGHZ_CallbackTypeDef pCallback)
457 {
458   HAL_StatusTypeDef status = HAL_OK;
459 
460   if (pCallback == NULL)
461   {
462     /* Update the error code */
463     hsubghz->ErrorCode |= HAL_SUBGHZ_ERROR_INVALID_CALLBACK;
464 
465     return HAL_ERROR;
466   }
467 
468   /* Process locked */
469   __HAL_LOCK(hsubghz);
470 
471   if (HAL_SUBGHZ_STATE_READY == hsubghz->State)
472   {
473     switch (CallbackID)
474     {
475       case HAL_SUBGHZ_TX_COMPLETE_CB_ID :
476         hsubghz->TxCpltCallback = pCallback;
477         break;
478 
479       case HAL_SUBGHZ_RX_COMPLETE_CB_ID :
480         hsubghz->RxCpltCallback = pCallback;
481         break;
482 
483       case HAL_SUBGHZ_PREAMBLE_DETECTED_CB_ID :
484         hsubghz->PreambleDetectedCallback = pCallback;
485         break;
486 
487       case HAL_SUBGHZ_SYNCWORD_VALID_CB_ID :
488         hsubghz->SyncWordValidCallback = pCallback;
489         break;
490 
491       case HAL_SUBGHZ_HEADER_VALID_CB_ID :
492         hsubghz->HeaderValidCallback = pCallback;
493         break;
494 
495       case HAL_SUBGHZ_HEADER_ERROR_CB_ID :
496         hsubghz->HeaderErrorCallback = pCallback;
497         break;
498 
499       case HAL_SUBGHZ_CRC_ERROR_CB_ID :
500         hsubghz->CRCErrorCallback = pCallback;
501         break;
502 
503       case HAL_SUBGHZ_RX_TX_TIMEOUT_CB_ID :
504         hsubghz->RxTxTimeoutCallback = pCallback;
505         break;
506 
507       case HAL_SUBGHZ_MSPINIT_CB_ID :
508         hsubghz->MspInitCallback = pCallback;
509         break;
510 
511       case HAL_SUBGHZ_MSPDEINIT_CB_ID :
512         hsubghz->MspDeInitCallback = pCallback;
513         break;
514 
515       case HAL_SUBGHZ_LR_FHSS_HOP_CB_ID :
516         hsubghz->LrFhssHopCallback = pCallback;
517         break;
518 
519       default :
520         /* Update the error code */
521         hsubghz->ErrorCode = HAL_SUBGHZ_ERROR_INVALID_CALLBACK;
522 
523         /* Return error status */
524         status =  HAL_ERROR;
525         break;
526     }
527   }
528   else if (HAL_SUBGHZ_STATE_RESET == hsubghz->State)
529   {
530     switch (CallbackID)
531     {
532       case HAL_SUBGHZ_MSPINIT_CB_ID :
533         hsubghz->MspInitCallback = pCallback;
534         break;
535 
536       case HAL_SUBGHZ_MSPDEINIT_CB_ID :
537         hsubghz->MspDeInitCallback = pCallback;
538         break;
539 
540       default :
541         /* Update the error code */
542         hsubghz->ErrorCode = HAL_SUBGHZ_ERROR_INVALID_CALLBACK;
543 
544         /* Return error status */
545         status =  HAL_ERROR;
546         break;
547     }
548   }
549   else
550   {
551     /* Update the error code */
552     hsubghz->ErrorCode = HAL_SUBGHZ_ERROR_INVALID_CALLBACK;
553 
554     /* Return error status */
555     status =  HAL_ERROR;
556   }
557 
558   /* Release Lock */
559   __HAL_UNLOCK(hsubghz);
560 
561   return status;
562 }
563 
564 /**
565   * @brief  Unregister an SUBGHZ Callback
566   *         SUBGHZ callback is redirected to the weak predefined callback
567   * @param  hsubghz pointer to a SUBGHZ_HandleTypeDef structure that contains
568   *         the configuration information for the specified SUBGHZ.
569   * @param  CallbackID ID of the callback to be unregistered
570   * @retval HAL status
571   */
HAL_SUBGHZ_UnRegisterCallback(SUBGHZ_HandleTypeDef * hsubghz,HAL_SUBGHZ_CallbackIDTypeDef CallbackID)572 HAL_StatusTypeDef HAL_SUBGHZ_UnRegisterCallback(SUBGHZ_HandleTypeDef *hsubghz,
573                                                 HAL_SUBGHZ_CallbackIDTypeDef CallbackID)
574 {
575   HAL_StatusTypeDef status = HAL_OK;
576 
577   /* Process locked */
578   __HAL_LOCK(hsubghz);
579 
580   if (HAL_SUBGHZ_STATE_READY == hsubghz->State)
581   {
582     /* call legacy weak callback function */
583     switch (CallbackID)
584     {
585       case HAL_SUBGHZ_TX_COMPLETE_CB_ID :
586         hsubghz->TxCpltCallback = HAL_SUBGHZ_TxCpltCallback;
587         break;
588 
589       case HAL_SUBGHZ_RX_COMPLETE_CB_ID :
590         hsubghz->RxCpltCallback = HAL_SUBGHZ_RxCpltCallback;
591         break;
592 
593       case HAL_SUBGHZ_PREAMBLE_DETECTED_CB_ID :
594         hsubghz->PreambleDetectedCallback = HAL_SUBGHZ_PreambleDetectedCallback;
595         break;
596 
597       case HAL_SUBGHZ_SYNCWORD_VALID_CB_ID :
598         hsubghz->SyncWordValidCallback = HAL_SUBGHZ_SyncWordValidCallback;
599         break;
600 
601       case HAL_SUBGHZ_HEADER_VALID_CB_ID :
602         hsubghz->HeaderValidCallback = HAL_SUBGHZ_HeaderValidCallback;
603         break;
604 
605       case HAL_SUBGHZ_HEADER_ERROR_CB_ID :
606         hsubghz->HeaderErrorCallback = HAL_SUBGHZ_HeaderErrorCallback;
607         break;
608 
609       case HAL_SUBGHZ_CRC_ERROR_CB_ID :
610         hsubghz->CRCErrorCallback = HAL_SUBGHZ_CRCErrorCallback;
611         break;
612 
613       case HAL_SUBGHZ_RX_TX_TIMEOUT_CB_ID :
614         hsubghz->RxTxTimeoutCallback = HAL_SUBGHZ_RxTxTimeoutCallback;
615         break;
616 
617       case HAL_SUBGHZ_MSPINIT_CB_ID :
618         hsubghz->MspInitCallback = HAL_SUBGHZ_MspInit;
619         break;
620 
621       case HAL_SUBGHZ_MSPDEINIT_CB_ID :
622         hsubghz->MspDeInitCallback = HAL_SUBGHZ_MspDeInit;
623         break;
624 
625       case HAL_SUBGHZ_LR_FHSS_HOP_CB_ID :
626         hsubghz->LrFhssHopCallback = HAL_SUBGHZ_LrFhssHopCallback;
627         break;
628 
629       default :
630         /* Update the error code */
631         hsubghz->ErrorCode = HAL_SUBGHZ_ERROR_INVALID_CALLBACK;
632 
633         /* Return error status */
634         status =  HAL_ERROR;
635         break;
636     }
637   }
638   else if (HAL_SUBGHZ_STATE_RESET == hsubghz->State)
639   {
640     switch (CallbackID)
641     {
642       case HAL_SUBGHZ_MSPINIT_CB_ID :
643         hsubghz->MspInitCallback = HAL_SUBGHZ_MspInit;
644         break;
645 
646       case HAL_SUBGHZ_MSPDEINIT_CB_ID :
647         hsubghz->MspDeInitCallback = HAL_SUBGHZ_MspDeInit;
648         break;
649 
650       default :
651         /* Update the error code */
652         hsubghz->ErrorCode = HAL_SUBGHZ_ERROR_INVALID_CALLBACK;
653 
654         /* Return error status */
655         status =  HAL_ERROR;
656         break;
657     }
658   }
659   else
660   {
661     /* Update the error code */
662     hsubghz->ErrorCode = HAL_SUBGHZ_ERROR_INVALID_CALLBACK;
663 
664     /* Return error status */
665     status =  HAL_ERROR;
666   }
667 
668   /* Release Lock */
669   __HAL_UNLOCK(hsubghz);
670 
671   return status;
672 }
673 
674 /**
675   * @brief  Register the channel activity detection status SUBGHZ Callback
676   *         To be used instead of the weak HAL_SUBGHZ_AddrCallback() predefined callback
677   * @param  hsubghz Pointer to a SUBGHZ_HandleTypeDef structure that contains
678   *                the configuration information for the specified SUBGHZ.
679   * @param  pCallback pointer to the CAD Status Callback function
680   * @retval HAL status
681   */
HAL_SUBGHZ_RegisterCadStatusCallback(SUBGHZ_HandleTypeDef * hsubghz,pSUBGHZ_CadStatusCallbackTypeDef pCallback)682 HAL_StatusTypeDef HAL_SUBGHZ_RegisterCadStatusCallback(SUBGHZ_HandleTypeDef *hsubghz,
683                                                        pSUBGHZ_CadStatusCallbackTypeDef pCallback)
684 {
685   HAL_StatusTypeDef status = HAL_OK;
686 
687   if (pCallback == NULL)
688   {
689     /* Update the error code */
690     hsubghz->ErrorCode = HAL_SUBGHZ_ERROR_INVALID_CALLBACK;
691 
692     return HAL_ERROR;
693   }
694   /* Process locked */
695   __HAL_LOCK(hsubghz);
696 
697   if (HAL_SUBGHZ_STATE_READY == hsubghz->State)
698   {
699     hsubghz->CADStatusCallback = pCallback;
700   }
701   else
702   {
703     /* Update the error code */
704     hsubghz->ErrorCode = HAL_SUBGHZ_ERROR_INVALID_CALLBACK;
705 
706     /* Return error status */
707     status =  HAL_ERROR;
708   }
709 
710   /* Release Lock */
711   __HAL_UNLOCK(hsubghz);
712   return status;
713 }
714 
715 /**
716   * @brief  UnRegister the channel activity detection status SUBGHZ Callback
717   * @param  hsubghz Pointer to a SUBGHZ_HandleTypeDef structure that contains
718   *                the configuration information for the specified SUBGHZ.
719   * @retval HAL status
720   */
HAL_SUBGHZ_UnRegisterCadStatusCallback(SUBGHZ_HandleTypeDef * hsubghz)721 HAL_StatusTypeDef HAL_SUBGHZ_UnRegisterCadStatusCallback(SUBGHZ_HandleTypeDef *hsubghz)
722 {
723   HAL_StatusTypeDef status = HAL_OK;
724 
725   /* Process locked */
726   __HAL_LOCK(hsubghz);
727 
728   if (HAL_SUBGHZ_STATE_READY == hsubghz->State)
729   {
730     hsubghz->CADStatusCallback = HAL_SUBGHZ_CADStatusCallback; /* Legacy weak AddrCallback */
731   }
732   else
733   {
734     /* Update the error code */
735     hsubghz->ErrorCode = HAL_SUBGHZ_ERROR_INVALID_CALLBACK;
736 
737     /* Return error status */
738     status =  HAL_ERROR;
739   }
740 
741   /* Release Lock */
742   __HAL_UNLOCK(hsubghz);
743   return status;
744 }
745 #endif /* USE_HAL_SUBGHZ_REGISTER_CALLBACKS */
746 /**
747   * @}
748   */
749 
750 /** @defgroup SUBGHZ_Exported_Functions_Group2 IO operation functions
751   *  @brief   Data transfers functions
752   *
753 @verbatim
754   ==============================================================================
755                       ##### IO operation functions #####
756  ===============================================================================
757  [..]
758     This subsection provides a set of functions allowing to manage the SUBGHZ
759     data transfers.
760 
761     [..] The SUBGHZ supports Read and Write operation:
762 
763     (#) There are four modes of transfer:
764        (++) Set operation: The Set Command operation is performed in polling mode.
765             The HAL status of command processing is returned by the same function
766             after finishing transfer.
767        (++) Get operation: The Get Status operation is performed using polling mode
768             These API update buffer in parameter to retrieve status of command.
769             These API return the HAL status
770        (++) Write operation: The write operation is performed in polling mode.
771             The HAL status of all data processing is returned by the same function
772             after finishing transfer.
773        (++) Read operation: The read operation is performed using polling mode
774             These APIs return the HAL status.
775 
776     (#) Blocking mode functions are :
777         (++) HAL_SUBGHZ_ExecSetCmd(
778         (++) HAL_SUBGHZ_ExecGetCmd()
779         (++) HAL_SUBGHZ_WriteBuffer()
780         (++) HAL_SUBGHZ_ReadBuffer()
781         (++) HAL_SUBGHZ_WriteRegisters()
782         (++) HAL_SUBGHZ_ReadRegisters()
783         (++) HAL_SUBGHZ_WriteRegister()
784         (++) HAL_SUBGHZ_ReadRegister()
785 
786 @endverbatim
787   * @{
788   */
789 
790 /**
791   * @brief  Write data buffer at an Address to configurate the peripheral
792   * @param  hsubghz pointer to a SUBGHZ_HandleTypeDef structure that contains
793   *         the configuration information for the specified SUBGHZ.
794   * @param  Address register to configurate
795   * @param  pBuffer pointer to a data buffer
796   * @param  Size    amount of data to be sent
797   * @retval HAL status
798   */
HAL_SUBGHZ_WriteRegisters(SUBGHZ_HandleTypeDef * hsubghz,uint16_t Address,uint8_t * pBuffer,uint16_t Size)799 HAL_StatusTypeDef HAL_SUBGHZ_WriteRegisters(SUBGHZ_HandleTypeDef *hsubghz,
800                                             uint16_t Address,
801                                             uint8_t *pBuffer,
802                                             uint16_t Size)
803 {
804   HAL_StatusTypeDef status;
805 
806   if (hsubghz->State == HAL_SUBGHZ_STATE_READY)
807   {
808     /* Process Locked */
809     __HAL_LOCK(hsubghz);
810 
811     hsubghz->State = HAL_SUBGHZ_STATE_BUSY;
812 
813     (void)SUBGHZ_CheckDeviceReady(hsubghz);
814 
815     /* NSS = 0 */
816     LL_PWR_SelectSUBGHZSPI_NSS();
817 
818     (void)SUBGHZSPI_Transmit(hsubghz, SUBGHZ_RADIO_WRITE_REGISTER);
819     (void)SUBGHZSPI_Transmit(hsubghz, (uint8_t)((Address & 0xFF00U) >> 8U));
820     (void)SUBGHZSPI_Transmit(hsubghz, (uint8_t)(Address & 0x00FFU));
821 
822     for (uint16_t i = 0U; i < Size; i++)
823     {
824       (void)SUBGHZSPI_Transmit(hsubghz, pBuffer[i]);
825     }
826 
827     /* NSS = 1 */
828     LL_PWR_UnselectSUBGHZSPI_NSS();
829 
830     (void)SUBGHZ_WaitOnBusy(hsubghz);
831 
832     if (hsubghz->ErrorCode != HAL_SUBGHZ_ERROR_NONE)
833     {
834       status = HAL_ERROR;
835     }
836     else
837     {
838       status = HAL_OK;
839     }
840 
841     hsubghz->State = HAL_SUBGHZ_STATE_READY;
842 
843     /* Process Unlocked */
844     __HAL_UNLOCK(hsubghz);
845 
846     return status;
847   }
848   else
849   {
850     return HAL_BUSY;
851   }
852 }
853 
854 /**
855   * @brief  Read data register at an Address in the peripheral
856   * @param  hsubghz pointer to a SUBGHZ_HandleTypeDef structure that contains
857   *         the configuration information for the specified SUBGHZ.
858   * @param  Address register to configurate
859   * @param  pBuffer pointer to a data buffer
860   * @param  Size    amount of data to be sent
861   * @retval HAL status
862   */
HAL_SUBGHZ_ReadRegisters(SUBGHZ_HandleTypeDef * hsubghz,uint16_t Address,uint8_t * pBuffer,uint16_t Size)863 HAL_StatusTypeDef HAL_SUBGHZ_ReadRegisters(SUBGHZ_HandleTypeDef *hsubghz,
864                                            uint16_t Address,
865                                            uint8_t *pBuffer,
866                                            uint16_t Size)
867 {
868   HAL_StatusTypeDef status;
869   uint8_t *pData = pBuffer;
870 
871   if (hsubghz->State == HAL_SUBGHZ_STATE_READY)
872   {
873     /* Process Locked */
874     __HAL_LOCK(hsubghz);
875 
876     (void)SUBGHZ_CheckDeviceReady(hsubghz);
877 
878     /* NSS = 0 */
879     LL_PWR_SelectSUBGHZSPI_NSS();
880 
881     (void)SUBGHZSPI_Transmit(hsubghz, SUBGHZ_RADIO_READ_REGISTER);
882     (void)SUBGHZSPI_Transmit(hsubghz, (uint8_t)((Address & 0xFF00U) >> 8U));
883     (void)SUBGHZSPI_Transmit(hsubghz, (uint8_t)(Address & 0x00FFU));
884     (void)SUBGHZSPI_Transmit(hsubghz, 0U);
885 
886     for (uint16_t i = 0U; i < Size; i++)
887     {
888       (void)SUBGHZSPI_Receive(hsubghz, (pData));
889       pData++;
890     }
891 
892     /* NSS = 1 */
893     LL_PWR_UnselectSUBGHZSPI_NSS();
894 
895     (void)SUBGHZ_WaitOnBusy(hsubghz);
896 
897     if (hsubghz->ErrorCode != HAL_SUBGHZ_ERROR_NONE)
898     {
899       status = HAL_ERROR;
900     }
901     else
902     {
903       status = HAL_OK;
904     }
905 
906     hsubghz->State = HAL_SUBGHZ_STATE_READY;
907 
908     /* Process Unlocked */
909     __HAL_UNLOCK(hsubghz);
910 
911     return status;
912   }
913   else
914   {
915     return HAL_BUSY;
916   }
917 }
918 
919 /**
920   * @brief  Write one data at an Address to configurate the peripheral
921   * @param  hsubghz pointer to a SUBGHZ_HandleTypeDef structure that contains
922   *         the configuration information for the specified SUBGHZ.
923   * @param  Address register to configurate
924   * @param  Value data
925   * @retval HAL status
926   */
HAL_SUBGHZ_WriteRegister(SUBGHZ_HandleTypeDef * hsubghz,uint16_t Address,uint8_t Value)927 HAL_StatusTypeDef HAL_SUBGHZ_WriteRegister(SUBGHZ_HandleTypeDef *hsubghz,
928                                            uint16_t Address,
929                                            uint8_t Value)
930 {
931   return (HAL_SUBGHZ_WriteRegisters(hsubghz, Address, &Value, 1U));
932 }
933 
934 /**
935   * @brief  Read data register at an Address in the peripheral
936   * @param  hsubghz pointer to a SUBGHZ_HandleTypeDef structure that contains
937   *         the configuration information for the specified SUBGHZ.
938   * @param  Address register to configurate
939   * @param  pValue pointer to a data
940   * @retval HAL status
941   */
HAL_SUBGHZ_ReadRegister(SUBGHZ_HandleTypeDef * hsubghz,uint16_t Address,uint8_t * pValue)942 HAL_StatusTypeDef HAL_SUBGHZ_ReadRegister(SUBGHZ_HandleTypeDef *hsubghz,
943                                           uint16_t Address,
944                                           uint8_t *pValue)
945 {
946   return (HAL_SUBGHZ_ReadRegisters(hsubghz, Address, pValue, 1U));
947 }
948 
949 /**
950   * @brief  Send a command to configure the peripheral
951   * @param  hsubghz pointer to a SUBGHZ_HandleTypeDef structure that contains
952   *         the configuration information for the specified SUBGHZ.
953   * @param  Command configuration for peripheral
954   * @param  pBuffer pointer to a data buffer
955   * @param  Size    amount of data to be sent
956   * @retval HAL status
957   */
HAL_SUBGHZ_ExecSetCmd(SUBGHZ_HandleTypeDef * hsubghz,SUBGHZ_RadioSetCmd_t Command,uint8_t * pBuffer,uint16_t Size)958 HAL_StatusTypeDef HAL_SUBGHZ_ExecSetCmd(SUBGHZ_HandleTypeDef *hsubghz,
959                                         SUBGHZ_RadioSetCmd_t Command,
960                                         uint8_t *pBuffer,
961                                         uint16_t Size)
962 {
963   HAL_StatusTypeDef status;
964 
965   /* LORA Modulation not available on STM32WLx4xx devices */
966   assert_param(IS_SUBGHZ_MODULATION_SUPPORTED(Command, pBuffer[0U]));
967 
968   if (hsubghz->State == HAL_SUBGHZ_STATE_READY)
969   {
970     /* Process Locked */
971     __HAL_LOCK(hsubghz);
972 
973     /* Need to wakeup Radio if already in Sleep at startup */
974     (void)SUBGHZ_CheckDeviceReady(hsubghz);
975 
976     if ((Command == RADIO_SET_SLEEP) || (Command == RADIO_SET_RXDUTYCYCLE))
977     {
978       hsubghz->DeepSleep = SUBGHZ_DEEP_SLEEP_ENABLE;
979     }
980     else
981     {
982       hsubghz->DeepSleep = SUBGHZ_DEEP_SLEEP_DISABLE;
983     }
984 
985     /* NSS = 0 */
986     LL_PWR_SelectSUBGHZSPI_NSS();
987 
988     (void)SUBGHZSPI_Transmit(hsubghz, (uint8_t)Command);
989 
990     for (uint16_t i = 0U; i < Size; i++)
991     {
992       (void)SUBGHZSPI_Transmit(hsubghz, pBuffer[i]);
993     }
994 
995     /* NSS = 1 */
996     LL_PWR_UnselectSUBGHZSPI_NSS();
997 
998     if (Command != RADIO_SET_SLEEP)
999     {
1000       (void)SUBGHZ_WaitOnBusy(hsubghz);
1001     }
1002 
1003     if (hsubghz->ErrorCode != HAL_SUBGHZ_ERROR_NONE)
1004     {
1005       status = HAL_ERROR;
1006     }
1007     else
1008     {
1009       status = HAL_OK;
1010     }
1011 
1012     hsubghz->State = HAL_SUBGHZ_STATE_READY;
1013 
1014     /* Process Unlocked */
1015     __HAL_UNLOCK(hsubghz);
1016 
1017     return status;
1018   }
1019   else
1020   {
1021     return HAL_BUSY;
1022   }
1023 }
1024 
1025 /**
1026   * @brief  Retrieve a status from the peripheral
1027   * @param  hsubghz pointer to a SUBGHZ_HandleTypeDef structure that contains
1028   *         the configuration information for the specified SUBGHZ.
1029   * @param  Command configuration for peripheral
1030   * @param  pBuffer pointer to a data buffer
1031   * @param  Size    amount of data to be sent
1032   * @retval HAL status
1033   */
HAL_SUBGHZ_ExecGetCmd(SUBGHZ_HandleTypeDef * hsubghz,SUBGHZ_RadioGetCmd_t Command,uint8_t * pBuffer,uint16_t Size)1034 HAL_StatusTypeDef HAL_SUBGHZ_ExecGetCmd(SUBGHZ_HandleTypeDef *hsubghz,
1035                                         SUBGHZ_RadioGetCmd_t Command,
1036                                         uint8_t *pBuffer,
1037                                         uint16_t Size)
1038 {
1039   HAL_StatusTypeDef status;
1040   uint8_t *pData = pBuffer;
1041 
1042   if (hsubghz->State == HAL_SUBGHZ_STATE_READY)
1043   {
1044     /* Process Locked */
1045     __HAL_LOCK(hsubghz);
1046 
1047     (void)SUBGHZ_CheckDeviceReady(hsubghz);
1048 
1049     /* NSS = 0 */
1050     LL_PWR_SelectSUBGHZSPI_NSS();
1051 
1052     (void)SUBGHZSPI_Transmit(hsubghz, (uint8_t)Command);
1053 
1054     /* Use to flush the Status (First byte) receive from SUBGHZ as not use */
1055     (void)SUBGHZSPI_Transmit(hsubghz, 0x00U);
1056 
1057     for (uint16_t i = 0U; i < Size; i++)
1058     {
1059       (void)SUBGHZSPI_Receive(hsubghz, (pData));
1060       pData++;
1061     }
1062 
1063     /* NSS = 1 */
1064     LL_PWR_UnselectSUBGHZSPI_NSS();
1065 
1066     (void)SUBGHZ_WaitOnBusy(hsubghz);
1067 
1068     if (hsubghz->ErrorCode != HAL_SUBGHZ_ERROR_NONE)
1069     {
1070       status = HAL_ERROR;
1071     }
1072     else
1073     {
1074       status = HAL_OK;
1075     }
1076 
1077     hsubghz->State = HAL_SUBGHZ_STATE_READY;
1078 
1079     /* Process Unlocked */
1080     __HAL_UNLOCK(hsubghz);
1081 
1082     return status;
1083   }
1084   else
1085   {
1086     return HAL_BUSY;
1087   }
1088 }
1089 
1090 /**
1091   * @brief  Write data buffer inside payload of peripheral
1092   * @param  hsubghz pointer to a SUBGHZ_HandleTypeDef structure that contains
1093   *         the configuration information for the specified SUBGHZ.
1094   * @param  Offset  Offset inside payload
1095   * @param  pBuffer pointer to a data buffer
1096   * @param  Size    amount of data to be sent
1097   * @retval HAL status
1098   */
HAL_SUBGHZ_WriteBuffer(SUBGHZ_HandleTypeDef * hsubghz,uint8_t Offset,uint8_t * pBuffer,uint16_t Size)1099 HAL_StatusTypeDef HAL_SUBGHZ_WriteBuffer(SUBGHZ_HandleTypeDef *hsubghz,
1100                                          uint8_t Offset,
1101                                          uint8_t *pBuffer,
1102                                          uint16_t Size)
1103 {
1104   HAL_StatusTypeDef status;
1105 
1106   if (hsubghz->State == HAL_SUBGHZ_STATE_READY)
1107   {
1108     /* Process Locked */
1109     __HAL_LOCK(hsubghz);
1110 
1111     (void)SUBGHZ_CheckDeviceReady(hsubghz);
1112 
1113     /* NSS = 0 */
1114     LL_PWR_SelectSUBGHZSPI_NSS();
1115 
1116     (void)SUBGHZSPI_Transmit(hsubghz, SUBGHZ_RADIO_WRITE_BUFFER);
1117     (void)SUBGHZSPI_Transmit(hsubghz, Offset);
1118 
1119     for (uint16_t i = 0U; i < Size; i++)
1120     {
1121       (void)SUBGHZSPI_Transmit(hsubghz, pBuffer[i]);
1122     }
1123     /* NSS = 1 */
1124     LL_PWR_UnselectSUBGHZSPI_NSS();
1125 
1126     (void)SUBGHZ_WaitOnBusy(hsubghz);
1127 
1128     if (hsubghz->ErrorCode != HAL_SUBGHZ_ERROR_NONE)
1129     {
1130       status = HAL_ERROR;
1131     }
1132     else
1133     {
1134       status = HAL_OK;
1135     }
1136 
1137     hsubghz->State = HAL_SUBGHZ_STATE_READY;
1138 
1139     /* Process Unlocked */
1140     __HAL_UNLOCK(hsubghz);
1141 
1142     return status;
1143   }
1144   else
1145   {
1146     return HAL_BUSY;
1147   }
1148 }
1149 
1150 /**
1151   * @brief  Read data buffer inside payload of peripheral
1152   * @param  hsubghz pointer to a SUBGHZ_HandleTypeDef structure that contains
1153   *         the configuration information for the specified SUBGHZ.
1154   * @param  Offset  Offset inside payload
1155   * @param  pBuffer pointer to a data buffer
1156   * @param  Size    amount of data to be sent
1157   * @retval HAL status
1158   */
HAL_SUBGHZ_ReadBuffer(SUBGHZ_HandleTypeDef * hsubghz,uint8_t Offset,uint8_t * pBuffer,uint16_t Size)1159 HAL_StatusTypeDef HAL_SUBGHZ_ReadBuffer(SUBGHZ_HandleTypeDef *hsubghz,
1160                                         uint8_t Offset,
1161                                         uint8_t *pBuffer,
1162                                         uint16_t Size)
1163 {
1164   HAL_StatusTypeDef status;
1165   uint8_t *pData = pBuffer;
1166 
1167   if (hsubghz->State == HAL_SUBGHZ_STATE_READY)
1168   {
1169     /* Process Locked */
1170     __HAL_LOCK(hsubghz);
1171 
1172     (void)SUBGHZ_CheckDeviceReady(hsubghz);
1173 
1174     /* NSS = 0 */
1175     LL_PWR_SelectSUBGHZSPI_NSS();
1176 
1177     (void)SUBGHZSPI_Transmit(hsubghz, SUBGHZ_RADIO_READ_BUFFER);
1178     (void)SUBGHZSPI_Transmit(hsubghz, Offset);
1179     (void)SUBGHZSPI_Transmit(hsubghz, 0x00U);
1180 
1181     for (uint16_t i = 0U; i < Size; i++)
1182     {
1183       (void)SUBGHZSPI_Receive(hsubghz, (pData));
1184       pData++;
1185     }
1186 
1187     /* NSS = 1 */
1188     LL_PWR_UnselectSUBGHZSPI_NSS();
1189 
1190     (void)SUBGHZ_WaitOnBusy(hsubghz);
1191 
1192     if (hsubghz->ErrorCode != HAL_SUBGHZ_ERROR_NONE)
1193     {
1194       status = HAL_ERROR;
1195     }
1196     else
1197     {
1198       status = HAL_OK;
1199     }
1200 
1201     hsubghz->State = HAL_SUBGHZ_STATE_READY;
1202 
1203     /* Process Unlocked */
1204     __HAL_UNLOCK(hsubghz);
1205 
1206     return status;
1207   }
1208   else
1209   {
1210     return HAL_BUSY;
1211   }
1212 }
1213 
1214 /**
1215   * @brief  Handle SUBGHZ interrupt request.
1216   * @param  hsubghz pointer to a SUBGHZ_HandleTypeDef structure that contains
1217   *               the configuration information for the specified SUBGHZ module.
1218   * @retval None
1219   */
HAL_SUBGHZ_IRQHandler(SUBGHZ_HandleTypeDef * hsubghz)1220 void HAL_SUBGHZ_IRQHandler(SUBGHZ_HandleTypeDef *hsubghz)
1221 {
1222   uint8_t tmpisr[2U] = {0U};
1223   uint16_t itsource;
1224 
1225   /* Retrieve Interrupts from SUBGHZ Irq Register */
1226   (void)HAL_SUBGHZ_ExecGetCmd(hsubghz, RADIO_GET_IRQSTATUS, tmpisr, 2U);
1227   itsource = tmpisr[0U];
1228   itsource = (itsource << 8U) | tmpisr[1U];
1229 
1230   /* Clear SUBGHZ Irq Register */
1231   (void)HAL_SUBGHZ_ExecSetCmd(hsubghz, RADIO_CLR_IRQSTATUS, tmpisr, 2U);
1232 
1233   /* Packet transmission completed Interrupt */
1234   if (SUBGHZ_CHECK_IT_SOURCE(itsource, SUBGHZ_IT_TX_CPLT) != RESET)
1235   {
1236 #if (USE_HAL_SUBGHZ_REGISTER_CALLBACKS == 1U)
1237     hsubghz->TxCpltCallback(hsubghz);
1238 #else
1239     HAL_SUBGHZ_TxCpltCallback(hsubghz);
1240 #endif /* USE_HAL_SUBGHZ_REGISTER_CALLBACKS */
1241   }
1242 
1243   /* Packet received Interrupt */
1244   if (SUBGHZ_CHECK_IT_SOURCE(itsource, SUBGHZ_IT_RX_CPLT) != RESET)
1245   {
1246 #if (USE_HAL_SUBGHZ_REGISTER_CALLBACKS == 1U)
1247     hsubghz->RxCpltCallback(hsubghz);
1248 #else
1249     HAL_SUBGHZ_RxCpltCallback(hsubghz);
1250 #endif /* USE_HAL_SUBGHZ_REGISTER_CALLBACKS */
1251   }
1252 
1253   /* Preamble Detected Interrupt */
1254   if (SUBGHZ_CHECK_IT_SOURCE(itsource, SUBGHZ_IT_PREAMBLE_DETECTED) != RESET)
1255   {
1256 #if (USE_HAL_SUBGHZ_REGISTER_CALLBACKS == 1U)
1257     hsubghz->PreambleDetectedCallback(hsubghz);
1258 #else
1259     HAL_SUBGHZ_PreambleDetectedCallback(hsubghz);
1260 #endif /* USE_HAL_SUBGHZ_REGISTER_CALLBACKS */
1261   }
1262 
1263   /*  Valid sync word detected Interrupt */
1264   if (SUBGHZ_CHECK_IT_SOURCE(itsource, SUBGHZ_IT_SYNCWORD_VALID) != RESET)
1265   {
1266 #if (USE_HAL_SUBGHZ_REGISTER_CALLBACKS == 1U)
1267     hsubghz->SyncWordValidCallback(hsubghz);
1268 #else
1269     HAL_SUBGHZ_SyncWordValidCallback(hsubghz);
1270 #endif /* USE_HAL_SUBGHZ_REGISTER_CALLBACKS */
1271   }
1272 
1273   /* Valid LoRa header received Interrupt */
1274   if (SUBGHZ_CHECK_IT_SOURCE(itsource, SUBGHZ_IT_HEADER_VALID) != RESET)
1275   {
1276 #if (USE_HAL_SUBGHZ_REGISTER_CALLBACKS == 1U)
1277     hsubghz->HeaderValidCallback(hsubghz);
1278 #else
1279     HAL_SUBGHZ_HeaderValidCallback(hsubghz);
1280 #endif /* USE_HAL_SUBGHZ_REGISTER_CALLBACKS */
1281   }
1282 
1283   /* LoRa header CRC error Interrupt */
1284   if (SUBGHZ_CHECK_IT_SOURCE(itsource, SUBGHZ_IT_HEADER_ERROR) != RESET)
1285   {
1286 #if (USE_HAL_SUBGHZ_REGISTER_CALLBACKS == 1U)
1287     hsubghz->HeaderErrorCallback(hsubghz);
1288 #else
1289     HAL_SUBGHZ_HeaderErrorCallback(hsubghz);
1290 #endif /* USE_HAL_SUBGHZ_REGISTER_CALLBACKS */
1291   }
1292 
1293   /* Wrong CRC received Interrupt */
1294   if (SUBGHZ_CHECK_IT_SOURCE(itsource, SUBGHZ_IT_CRC_ERROR) != RESET)
1295   {
1296 #if (USE_HAL_SUBGHZ_REGISTER_CALLBACKS == 1U)
1297     hsubghz->CRCErrorCallback(hsubghz);
1298 #else
1299     HAL_SUBGHZ_CRCErrorCallback(hsubghz);
1300 #endif /* USE_HAL_SUBGHZ_REGISTER_CALLBACKS */
1301   }
1302 
1303   /* Channel activity detection finished Interrupt */
1304   if (SUBGHZ_CHECK_IT_SOURCE(itsource, SUBGHZ_IT_CAD_DONE) != RESET)
1305   {
1306 #if (USE_HAL_SUBGHZ_REGISTER_CALLBACKS == 1U)
1307     /* Channel activity Detected Interrupt */
1308     if (SUBGHZ_CHECK_IT_SOURCE(itsource, SUBGHZ_IT_CAD_ACTIVITY_DETECTED) != RESET)
1309     {
1310       hsubghz->CADStatusCallback(hsubghz, HAL_SUBGHZ_CAD_DETECTED);
1311     }
1312     else
1313     {
1314       hsubghz->CADStatusCallback(hsubghz, HAL_SUBGHZ_CAD_CLEAR);
1315     }
1316 #else
1317     /* Channel activity Detected Interrupt */
1318     if (SUBGHZ_CHECK_IT_SOURCE(itsource, SUBGHZ_IT_CAD_ACTIVITY_DETECTED) != RESET)
1319     {
1320       HAL_SUBGHZ_CADStatusCallback(hsubghz, HAL_SUBGHZ_CAD_DETECTED);
1321     }
1322     else
1323     {
1324       HAL_SUBGHZ_CADStatusCallback(hsubghz, HAL_SUBGHZ_CAD_CLEAR);
1325     }
1326 #endif /* USE_HAL_SUBGHZ_REGISTER_CALLBACKS */
1327   }
1328 
1329   /* Rx or Tx Timeout Interrupt */
1330   if (SUBGHZ_CHECK_IT_SOURCE(itsource, SUBGHZ_IT_RX_TX_TIMEOUT) != RESET)
1331   {
1332 #if (USE_HAL_SUBGHZ_REGISTER_CALLBACKS == 1U)
1333     hsubghz->RxTxTimeoutCallback(hsubghz);
1334 #else
1335     HAL_SUBGHZ_RxTxTimeoutCallback(hsubghz);
1336 #endif /* USE_HAL_SUBGHZ_REGISTER_CALLBACKS */
1337   }
1338 
1339   /* LR_FHSS Hop interrupt */
1340   if (SUBGHZ_CHECK_IT_SOURCE(itsource, SUBGHZ_IT_LR_FHSS_HOP) != RESET)
1341   {
1342 #if (USE_HAL_SUBGHZ_REGISTER_CALLBACKS == 1U)
1343     hsubghz->LrFhssHopCallback(hsubghz);
1344 #else
1345     HAL_SUBGHZ_LrFhssHopCallback(hsubghz);
1346 #endif /* USE_HAL_SUBGHZ_REGISTER_CALLBACKS */
1347   }
1348 }
1349 
1350 /**
1351   * @brief  Packet transmission completed callback.
1352   * @param  hsubghz pointer to a SUBGHZ_HandleTypeDef structure that contains
1353   *               the configuration information for SUBGHZ module.
1354   * @retval None
1355   */
HAL_SUBGHZ_TxCpltCallback(SUBGHZ_HandleTypeDef * hsubghz)1356 __weak void HAL_SUBGHZ_TxCpltCallback(SUBGHZ_HandleTypeDef *hsubghz)
1357 {
1358   /* Prevent unused argument(s) compilation warning */
1359   UNUSED(hsubghz);
1360 
1361   /* NOTE : This function should not be modified, when the callback is needed,
1362             the HAL_SUBGHZ_TxCpltCallback should be implemented in the user file
1363    */
1364 }
1365 
1366 /**
1367   * @brief  Packet received callback.
1368   * @param  hsubghz pointer to a SUBGHZ_HandleTypeDef structure that contains
1369   *               the configuration information for SUBGHZ module.
1370   * @retval None
1371   */
HAL_SUBGHZ_RxCpltCallback(SUBGHZ_HandleTypeDef * hsubghz)1372 __weak void HAL_SUBGHZ_RxCpltCallback(SUBGHZ_HandleTypeDef *hsubghz)
1373 {
1374   /* Prevent unused argument(s) compilation warning */
1375   UNUSED(hsubghz);
1376 
1377   /* NOTE : This function should not be modified, when the callback is needed,
1378             the HAL_SUBGHZ_RxCpltCallback should be implemented in the user file
1379    */
1380 }
1381 
1382 /**
1383   * @brief  Preamble Detected callback.
1384   * @param  hsubghz pointer to a SUBGHZ_HandleTypeDef structure that contains
1385   *               the configuration information for SUBGHZ module.
1386   * @retval None
1387   */
HAL_SUBGHZ_PreambleDetectedCallback(SUBGHZ_HandleTypeDef * hsubghz)1388 __weak void HAL_SUBGHZ_PreambleDetectedCallback(SUBGHZ_HandleTypeDef *hsubghz)
1389 {
1390   /* Prevent unused argument(s) compilation warning */
1391   UNUSED(hsubghz);
1392 
1393   /* NOTE : This function should not be modified, when the callback is needed,
1394             the HAL_SUBGHZ_PreambleDetectedCallback should be implemented in the user file
1395    */
1396 }
1397 
1398 /**
1399   * @brief  Valid sync word detected callback.
1400   * @param  hsubghz pointer to a SUBGHZ_HandleTypeDef structure that contains
1401   *               the configuration information for SUBGHZ module.
1402   * @retval None
1403   */
HAL_SUBGHZ_SyncWordValidCallback(SUBGHZ_HandleTypeDef * hsubghz)1404 __weak void HAL_SUBGHZ_SyncWordValidCallback(SUBGHZ_HandleTypeDef *hsubghz)
1405 {
1406   /* Prevent unused argument(s) compilation warning */
1407   UNUSED(hsubghz);
1408 
1409   /* NOTE : This function should not be modified, when the callback is needed,
1410             the HAL_SUBGHZ_SyncWordValidCallback should be implemented in the user file
1411    */
1412 }
1413 
1414 /**
1415   * @brief  Valid LoRa header received callback.
1416   * @param  hsubghz pointer to a SUBGHZ_HandleTypeDef structure that contains
1417   *               the configuration information for SUBGHZ module.
1418   * @retval None
1419   */
HAL_SUBGHZ_HeaderValidCallback(SUBGHZ_HandleTypeDef * hsubghz)1420 __weak void HAL_SUBGHZ_HeaderValidCallback(SUBGHZ_HandleTypeDef *hsubghz)
1421 {
1422   /* Prevent unused argument(s) compilation warning */
1423   UNUSED(hsubghz);
1424 
1425   /* NOTE : This function should not be modified, when the callback is needed,
1426             the HAL_SUBGHZ_HeaderValidCallback should be implemented in the user file
1427    */
1428 }
1429 
1430 /**
1431   * @brief  LoRa header CRC error callback.
1432   * @param  hsubghz pointer to a SUBGHZ_HandleTypeDef structure that contains
1433   *               the configuration information for SUBGHZ module.
1434   * @retval None
1435   */
HAL_SUBGHZ_HeaderErrorCallback(SUBGHZ_HandleTypeDef * hsubghz)1436 __weak void HAL_SUBGHZ_HeaderErrorCallback(SUBGHZ_HandleTypeDef *hsubghz)
1437 {
1438   /* Prevent unused argument(s) compilation warning */
1439   UNUSED(hsubghz);
1440 
1441   /* NOTE : This function should not be modified, when the callback is needed,
1442             the HAL_SUBGHZ_HeaderErrorCallback should be implemented in the user file
1443    */
1444 }
1445 
1446 /**
1447   * @brief  Wrong CRC received callback.
1448   * @param  hsubghz pointer to a SUBGHZ_HandleTypeDef structure that contains
1449   *               the configuration information for SUBGHZ module.
1450   * @retval None
1451   */
HAL_SUBGHZ_CRCErrorCallback(SUBGHZ_HandleTypeDef * hsubghz)1452 __weak void HAL_SUBGHZ_CRCErrorCallback(SUBGHZ_HandleTypeDef *hsubghz)
1453 {
1454   /* Prevent unused argument(s) compilation warning */
1455   UNUSED(hsubghz);
1456 
1457   /* NOTE : This function should not be modified, when the callback is needed,
1458             the HAL_SUBGHZ_CRCErrorCallback should be implemented in the user file
1459    */
1460 }
1461 
1462 /**
1463   * @brief  Channel activity detection status callback.
1464   * @note   Unified callback for CAD Done and CAD activity interrupts.
1465   * @param  hsubghz pointer to a SUBGHZ_HandleTypeDef structure that contains
1466   *               the configuration information for SUBGHZ module.
1467   * @param  cadstatus reports whether activity is detected or not
1468   * @retval None
1469   */
HAL_SUBGHZ_CADStatusCallback(SUBGHZ_HandleTypeDef * hsubghz,HAL_SUBGHZ_CadStatusTypeDef cadstatus)1470 __weak void HAL_SUBGHZ_CADStatusCallback(SUBGHZ_HandleTypeDef *hsubghz,
1471                                          HAL_SUBGHZ_CadStatusTypeDef cadstatus)
1472 {
1473   /* Prevent unused argument(s) compilation warning */
1474   UNUSED(hsubghz);
1475 
1476   UNUSED(cadstatus);
1477   /* NOTE : This function should not be modified, when the callback is needed,
1478             the HAL_SUBGHZ_CADStatusCallback should be implemented in the user file
1479    */
1480 }
1481 
1482 /**
1483   * @brief  Rx or Tx Timeout callback.
1484   * @param  hsubghz pointer to a SUBGHZ_HandleTypeDef structure that contains
1485   *               the configuration information for SUBGHZ module.
1486   * @retval None
1487   */
HAL_SUBGHZ_RxTxTimeoutCallback(SUBGHZ_HandleTypeDef * hsubghz)1488 __weak void HAL_SUBGHZ_RxTxTimeoutCallback(SUBGHZ_HandleTypeDef *hsubghz)
1489 {
1490   /* Prevent unused argument(s) compilation warning */
1491   UNUSED(hsubghz);
1492 
1493   /* NOTE : This function should not be modified, when the callback is needed,
1494             the HAL_SUBGHZ_RxTxTimeoutCallback should be implemented in the user file
1495    */
1496 }
1497 
1498 /**
1499   * @brief  LR FHSS Hop callback.
1500   * @param  hsubghz pointer to a SUBGHZ_HandleTypeDef structure that contains
1501   *               the configuration information for SUBGHZ module.
1502   * @retval None
1503   */
HAL_SUBGHZ_LrFhssHopCallback(SUBGHZ_HandleTypeDef * hsubghz)1504 __weak void HAL_SUBGHZ_LrFhssHopCallback(SUBGHZ_HandleTypeDef *hsubghz)
1505 {
1506   /* Prevent unused argument(s) compilation warning */
1507   UNUSED(hsubghz);
1508 
1509   /* NOTE : This function should not be modified, when the callback is needed,
1510             the HAL_SUBGHZ_LrFhssHopCallback should be implemented in the user file
1511    */
1512 }
1513 /**
1514   * @}
1515   */
1516 
1517 /** @defgroup SUBGHZ_Exported_Functions_Group3 Peripheral State and Errors functions
1518   * @brief   SUBGHZ control functions
1519   *
1520 @verbatim
1521  ===============================================================================
1522                       ##### Peripheral State and Errors functions #####
1523  ===============================================================================
1524     [..]
1525     This subsection provides a set of functions allowing to control the SUBGHZ.
1526      (+) HAL_SUBGHZ_GetState() API can be helpful to check in run-time the state of the SUBGHZ peripheral
1527      (+) HAL_SUBGHZ_GetError() check in run-time Errors occurring during communication
1528 @endverbatim
1529   * @{
1530   */
1531 
1532 /**
1533   * @brief  Return the SUBGHZ handle state.
1534   * @param  hsubghz pointer to a SUBGHZ_HandleTypeDef structure that contains
1535   *         the handle information for SUBGHZ module.
1536   * @retval SUBGHZ state
1537   */
HAL_SUBGHZ_GetState(SUBGHZ_HandleTypeDef * hsubghz)1538 HAL_SUBGHZ_StateTypeDef HAL_SUBGHZ_GetState(SUBGHZ_HandleTypeDef *hsubghz)
1539 {
1540   /* Return SUBGHZ handle state */
1541   return hsubghz->State;
1542 }
1543 
1544 /**
1545   * @brief  Return the SUBGHZ error code.
1546   * @param  hsubghz pointer to a SUBGHZ_HandleTypeDef structure that contains
1547   *         the handle information for SUBGHZ module.
1548   * @retval SUBGHZ error code in bitmap format
1549   */
HAL_SUBGHZ_GetError(SUBGHZ_HandleTypeDef * hsubghz)1550 uint32_t HAL_SUBGHZ_GetError(SUBGHZ_HandleTypeDef *hsubghz)
1551 {
1552   /* Return SUBGHZ ErrorCode */
1553   return hsubghz->ErrorCode;
1554 }
1555 
1556 /**
1557   * @}
1558   */
1559 
1560 /**
1561   * @}
1562   */
1563 
1564 /** @addtogroup SUBGHZ_Private_Functions
1565   * @brief   Private functions
1566   * @{
1567   */
1568 
1569 /**
1570   * @brief  Initializes the SUBGHZSPI peripheral
1571   * @param  BaudratePrescaler SPI Baudrate prescaler
1572   * @retval None
1573   */
SUBGHZSPI_Init(uint32_t BaudratePrescaler)1574 void SUBGHZSPI_Init(uint32_t BaudratePrescaler)
1575 {
1576   /* Check the parameters */
1577   assert_param(IS_SUBGHZ_ALL_INSTANCE(SUBGHZSPI));
1578 
1579   /* Disable SUBGHZSPI Peripheral */
1580   CLEAR_BIT(SUBGHZSPI->CR1, SPI_CR1_SPE);
1581 
1582   /*----------------------- SPI CR1 Configuration ----------------------------*
1583    *             SPI Mode: Master                                             *
1584    *   Communication Mode: 2 lines (Full-Duplex)                              *
1585    *       Clock polarity: Low                                                *
1586    *                phase: 1st Edge                                           *
1587    *       NSS management: Internal (Done with External bit inside PWR        *
1588    *  Communication speed: BaudratePrescaler                             *
1589    *            First bit: MSB                                                *
1590    *      CRC calculation: Disable                                            *
1591    *--------------------------------------------------------------------------*/
1592   WRITE_REG(SUBGHZSPI->CR1, (SPI_CR1_MSTR | SPI_CR1_SSI | BaudratePrescaler | SPI_CR1_SSM));
1593 
1594   /*----------------------- SPI CR2 Configuration ----------------------------*
1595    *            Data Size: 8bits                                              *
1596    *              TI Mode: Disable                                            *
1597    *            NSS Pulse: Disable                                            *
1598    *    Rx FIFO Threshold: 8bits                                              *
1599    *--------------------------------------------------------------------------*/
1600   WRITE_REG(SUBGHZSPI->CR2, (SPI_CR2_FRXTH |  SPI_CR2_DS_0 | SPI_CR2_DS_1 | SPI_CR2_DS_2));
1601 
1602   /* Enable SUBGHZSPI Peripheral */
1603   SET_BIT(SUBGHZSPI->CR1, SPI_CR1_SPE);
1604 }
1605 
1606 /**
1607   * @brief  DeInitializes the SUBGHZSPI peripheral
1608   * @retval None
1609   */
SUBGHZSPI_DeInit(void)1610 void  SUBGHZSPI_DeInit(void)
1611 {
1612   /* Check the parameters */
1613   assert_param(IS_SUBGHZ_ALL_INSTANCE(SUBGHZSPI));
1614 
1615   /* Disable SUBGHZSPI Peripheral */
1616   CLEAR_BIT(SUBGHZSPI->CR1, SPI_CR1_SPE);
1617 }
1618 
1619 /**
1620   * @brief  Transmit data through SUBGHZSPI peripheral
1621   * @param  hsubghz pointer to a SUBGHZ_HandleTypeDef structure that contains
1622   *         the handle information for SUBGHZ module.
1623   * @param  Data  data to transmit
1624   * @retval HAL status
1625   */
SUBGHZSPI_Transmit(SUBGHZ_HandleTypeDef * hsubghz,uint8_t Data)1626 HAL_StatusTypeDef SUBGHZSPI_Transmit(SUBGHZ_HandleTypeDef *hsubghz,
1627                                      uint8_t Data)
1628 {
1629   HAL_StatusTypeDef status = HAL_OK;
1630   __IO uint32_t count;
1631 
1632   /* Handle Tx transmission from SUBGHZSPI peripheral to Radio ****************/
1633   /* Initialize Timeout */
1634   count = SUBGHZ_DEFAULT_TIMEOUT * SUBGHZ_DEFAULT_LOOP_TIME;
1635 
1636   /* Wait until TXE flag is set */
1637   do
1638   {
1639     if (count == 0U)
1640     {
1641       status = HAL_ERROR;
1642       hsubghz->ErrorCode = HAL_SUBGHZ_ERROR_TIMEOUT;
1643       break;
1644     }
1645     count--;
1646   } while (READ_BIT(SUBGHZSPI->SR, SPI_SR_TXE) != (SPI_SR_TXE));
1647 
1648   /* Transmit Data*/
1649 #if defined (__GNUC__)
1650   __IO uint8_t *spidr = ((__IO uint8_t *)&SUBGHZSPI->DR);
1651   *spidr = Data;
1652 #else
1653   *((__IO uint8_t *)&SUBGHZSPI->DR) = Data;
1654 #endif /* __GNUC__ */
1655 
1656   /* Handle Rx transmission from SUBGHZSPI peripheral to Radio ****************/
1657   /* Initialize Timeout */
1658   count = SUBGHZ_DEFAULT_TIMEOUT * SUBGHZ_DEFAULT_LOOP_TIME;
1659 
1660   /* Wait until RXNE flag is set */
1661   do
1662   {
1663     if (count == 0U)
1664     {
1665       status = HAL_ERROR;
1666       hsubghz->ErrorCode = HAL_SUBGHZ_ERROR_TIMEOUT;
1667       break;
1668     }
1669     count--;
1670   } while (READ_BIT(SUBGHZSPI->SR, SPI_SR_RXNE) != (SPI_SR_RXNE));
1671 
1672   /* Flush Rx data */
1673   READ_REG(SUBGHZSPI->DR);
1674 
1675   return status;
1676 }
1677 
1678 /**
1679   * @brief  Receive data through SUBGHZSPI peripheral
1680   * @param  hsubghz pointer to a SUBGHZ_HandleTypeDef structure that contains
1681   *         the handle information for SUBGHZ module.
1682   * @param  pData  pointer on data to receive
1683   * @retval HAL status
1684   */
SUBGHZSPI_Receive(SUBGHZ_HandleTypeDef * hsubghz,uint8_t * pData)1685 HAL_StatusTypeDef SUBGHZSPI_Receive(SUBGHZ_HandleTypeDef *hsubghz,
1686                                     uint8_t *pData)
1687 {
1688   HAL_StatusTypeDef status = HAL_OK;
1689   __IO uint32_t count;
1690 
1691   /* Handle Tx transmission from SUBGHZSPI peripheral to Radio ****************/
1692   /* Initialize Timeout */
1693   count = SUBGHZ_DEFAULT_TIMEOUT * SUBGHZ_DEFAULT_LOOP_TIME;
1694 
1695   /* Wait until TXE flag is set */
1696   do
1697   {
1698     if (count == 0U)
1699     {
1700       status = HAL_ERROR;
1701       hsubghz->ErrorCode = HAL_SUBGHZ_ERROR_TIMEOUT;
1702       break;
1703     }
1704     count--;
1705   } while (READ_BIT(SUBGHZSPI->SR, SPI_SR_TXE) != (SPI_SR_TXE));
1706 
1707   /* Transmit Data*/
1708 #if defined (__GNUC__)
1709   __IO uint8_t *spidr = ((__IO uint8_t *)&SUBGHZSPI->DR);
1710   *spidr = SUBGHZ_DUMMY_DATA;
1711 #else
1712   *((__IO uint8_t *)&SUBGHZSPI->DR) = SUBGHZ_DUMMY_DATA;
1713 #endif /* __GNUC__ */
1714 
1715   /* Handle Rx transmission from SUBGHZSPI peripheral to Radio ****************/
1716   /* Initialize Timeout */
1717   count = SUBGHZ_DEFAULT_TIMEOUT * SUBGHZ_DEFAULT_LOOP_TIME;
1718 
1719   /* Wait until RXNE flag is set */
1720   do
1721   {
1722     if (count == 0U)
1723     {
1724       status = HAL_ERROR;
1725       hsubghz->ErrorCode = HAL_SUBGHZ_ERROR_TIMEOUT;
1726       break;
1727     }
1728     count--;
1729   } while (READ_BIT(SUBGHZSPI->SR, SPI_SR_RXNE) != (SPI_SR_RXNE));
1730 
1731   /* Retrieve pData */
1732   *pData = (uint8_t)(READ_REG(SUBGHZSPI->DR));
1733 
1734   return status;
1735 }
1736 
1737 /**
1738   * @brief  Check if peripheral is ready
1739   * @param  hsubghz pointer to a SUBGHZ_HandleTypeDef structure that contains
1740   *         the handle information for SUBGHZ module.
1741   * @retval HAL status
1742   */
SUBGHZ_CheckDeviceReady(SUBGHZ_HandleTypeDef * hsubghz)1743 HAL_StatusTypeDef SUBGHZ_CheckDeviceReady(SUBGHZ_HandleTypeDef *hsubghz)
1744 {
1745   __IO uint32_t count;
1746 
1747   /* Wakeup radio in case of sleep mode: Select-Unselect radio */
1748   if (hsubghz->DeepSleep == SUBGHZ_DEEP_SLEEP_ENABLE)
1749   {
1750     /* Initialize NSS switch Delay */
1751     count  = SUBGHZ_NSS_LOOP_TIME;
1752 
1753     /* NSS = 0; */
1754     LL_PWR_SelectSUBGHZSPI_NSS();
1755 
1756     /* Wait Radio wakeup */
1757     do
1758     {
1759       count--;
1760     } while (count != 0UL);
1761 
1762     /* NSS = 1 */
1763     LL_PWR_UnselectSUBGHZSPI_NSS();
1764   }
1765   return (SUBGHZ_WaitOnBusy(hsubghz));
1766 }
1767 
1768 /**
1769   * @brief  Wait busy flag low from peripheral
1770   * @param  hsubghz pointer to a SUBGHZ_HandleTypeDef structure that contains
1771   *         the handle information for SUBGHZ module.
1772   * @retval HAL status
1773   */
SUBGHZ_WaitOnBusy(SUBGHZ_HandleTypeDef * hsubghz)1774 HAL_StatusTypeDef SUBGHZ_WaitOnBusy(SUBGHZ_HandleTypeDef *hsubghz)
1775 {
1776   HAL_StatusTypeDef status;
1777   __IO uint32_t count;
1778   uint32_t mask;
1779 
1780   status = HAL_OK;
1781   count  = SUBGHZ_DEFAULT_TIMEOUT * SUBGHZ_RFBUSY_LOOP_TIME;
1782 
1783   /* Wait until Busy signal is set */
1784   do
1785   {
1786     mask = LL_PWR_IsActiveFlag_RFBUSYMS();
1787 
1788     if (count == 0U)
1789     {
1790       status  = HAL_ERROR;
1791       hsubghz->ErrorCode = HAL_SUBGHZ_ERROR_RF_BUSY;
1792       break;
1793     }
1794     count--;
1795   } while ((LL_PWR_IsActiveFlag_RFBUSYS()& mask) == 1UL);
1796 
1797   return status;
1798 }
1799 /**
1800   * @}
1801   */
1802 
1803 #endif /* HAL_SUBGHZ_MODULE_ENABLED */
1804 
1805 /**
1806   * @}
1807   */
1808 
1809 /**
1810   * @}
1811   */
1812