/******************************************************************************* * @file stm32wlxx_hal_subghz.c * @author MCD Application Team * @brief SUBGHZ HAL module driver. * This file provides firmware functions to manage the following * functionalities of the SUBGHZ peripheral: * + Initialization and de-initialization functions * + IO operation functions * + Peripheral State and Errors functions * ****************************************************************************** * @attention * * Copyright (c) 2020 STMicroelectronics. * All rights reserved. * * This software is licensed under terms that can be found in the LICENSE file * in the root directory of this software component. * If no LICENSE file comes with this software, it is provided AS-IS. * ****************************************************************************** @verbatim ============================================================================== ##### How to use this driver ##### ============================================================================== [..] The SUBGHZ HAL driver can be used as follows: (#) Declare a SUBGHZ_HandleTypeDef handle structure, for example: SUBGHZ_HandleTypeDef hUserSubghz; (#) Initialize the SUBGHZ low level resources by implementing the @ref HAL_SUBGHZ_MspInit() API: (##) PWR configuration (+++) Enable the SUBGHZSPI interface clock (+++) Enable wakeup signal of the Radio peripheral (##) NVIC configuration: (+++) Enable the NVIC Radio IRQ ITs for CPU1 (EXTI 44) (+++) Configure the Radio interrupt priority (#) Initialize the SUBGHZ handle and SUBGHZSPI SPI registers by calling the @ref HAL_SUBGHZ_Init(&hUserSubghz), configures also the low level Hardware (GPIO, CLOCK, NVIC...etc) by calling the customized @ref HAL_SUBGHZ_MspInit() API. (#) For SUBGHZ IO operations, polling operation modes is available within this driver : *** Polling mode IO operation *** ===================================== [..] (+) Set and execute a command in blocking mode using @ref HAL_SUBGHZ_ExecSetCmd() (+) Get a status blocking mode using @ref HAL_SUBGHZ_ExecGetCmd() (+) Write a Data Buffer in blocking mode using @ref HAL_SUBGHZ_WriteBuffer() (+) Read a Data Buffer in blocking mode using @ref HAL_SUBGHZ_ReadBuffer() (+) Write Registers (more than 1 byte) in blocking mode using @ref HAL_SUBGHZ_WriteRegisters() (+) Read Registers (more than 1 byte) in blocking mode using @ref HAL_SUBGHZ_ReadRegisters() (+) Write Register (1 byte) in blocking mode using @ref HAL_SUBGHZ_WriteRegister() (+) Read Register (1 byte) in blocking mode using @ref HAL_SUBGHZ_ReadRegister() *** SUBGHZ HAL driver macros list *** ===================================== [..] (+) @ref __HAL_SUBGHZ_RESET_HANDLE_STATE: Reset the SUBGHZ handle state #if defined(GENERATOR_CALLBACK_REGISTERING_PRESENT) *** SUBGHZ Callback registration *** ===================================== [..] The compilation flag USE_HAL_SUBGHZ_REGISTER_CALLBACKS when set to 1 allows the user to configure dynamically the driver callbacks. Use Functions @ref HAL_SUBGHZ_RegisterCallback() or @ref HAL_SUBGHZ_RegisterAddrCallback() to register an interrupt callback. [..] Function @ref HAL_SUBGHZ_RegisterCallback() allows to register following callbacks: (+) TxCpltCallback : callback for Tx Completed. (+) RxCpltCallback : callback for Rx Completed. (+) PreambleDetectedCallback : callback for Preamble detected. (+) SyncWordValidCallback : callback for Synchro word valid. (+) HeaderValidCallback : callback for Header valid. (+) HeaderErrorCallback : callback for Header error. (+) CRCErrorCallback : callback for CRC Error. (+) RxTxTimeoutCallback : callback for Rx Tx Timeout. (+) MspInitCallback : callback for Msp Init. (+) MspDeInitCallback : callback for Msp DeInit. (+) LrFhssHopCallback : callback for LoRa Frequency Hopping Spread Spectrum Hopping. This function takes as parameters the HAL peripheral handle, the Callback ID and a pointer to the user callback function. [..] For specific callback CADStatusCallback use dedicated register callbacks : @ref HAL_SUBGHZ_RegisterCadStatusCallback(). [..] Use function @ref HAL_SUBGHZ_UnRegisterCallback to reset a callback to the default weak function. @ref HAL_SUBGHZ_UnRegisterCallback takes as parameters the HAL peripheral handle, and the Callback ID. This function allows to reset following callbacks: (+) TxCpltCallback : callback for Tx Completed. (+) RxCpltCallback : callback for Rx Completed. (+) PreambleDetectedCallback : callback for Preamble detected. (+) SyncWordValidCallback : callback for Synchro word valid. (+) HeaderValidCallback : callback for Header valid. (+) HeaderErrorCallback : callback for Header error. (+) CRCErrorCallback : callback for CRC Error. (+) RxTxTimeoutCallback : callback for Rx Tx Timeout. (+) MspInitCallback : callback for Msp Init. (+) MspDeInitCallback : callback for Msp DeInit. (+) LrFhssHopCallback : callback for LoRa Frequency Hopping Spread Spectrum Hopping. [..] For specific callback CADStatusCallback use dedicated register callbacks : @ref HAL_SUBGHZ_UnRegisterCadStatusCallback(). [..] MspInit and MspDeInit functions are reset to the legacy weak functions in the @ref HAL_SUBGHZ_Init()/ @ref HAL_SUBGHZ_DeInit() only when these callbacks are null (not registered beforehand). If MspInit or MspDeInit are not null, the @ref HAL_SUBGHZ_Init()/ @ref HAL_SUBGHZ_DeInit() keep and use the user MspInit/MspDeInit callbacks (registered beforehand) whatever the state. [..] Callbacks for MspInit/MspDeInit functions can be registered/unregistered in @ref HAL_SUBGHZ_STATE_READY or @ref HAL_SUBGHZ_STATE_RESET state, thus registered (user) MspInit/DeInit callbacks can be used during the Init/DeInit. Then, the user first registers the MspInit/MspDeInit user callbacks using @ref HAL_SUBGHZ_RegisterCallback() before calling @ref HAL_SUBGHZ_DeInit() or @ref HAL_SUBGHZ_Init() function. [..] When the compilation flag USE_HAL_SUBGHZ_REGISTER_CALLBACKS is set to 0 or not defined, the callback registration feature is not available and all callbacks are set to the corresponding weak functions. #endif */ /* Includes ------------------------------------------------------------------*/ #include "stm32wlxx_hal.h" /** @addtogroup STM32WLxx_HAL_Driver * @{ */ /** @defgroup SUBGHZ SUBGHZ * @brief SUBGHZ HAL module driver * @{ */ #ifdef HAL_SUBGHZ_MODULE_ENABLED /* Private typedef -----------------------------------------------------------*/ /* Private defines -----------------------------------------------------------*/ /** @defgroup SUBGHZ_Private_Constants SUBGHZ Private Constants * @{ */ #define SUBGHZ_DEFAULT_TIMEOUT 100U /* HAL Timeout in ms */ #define SUBGHZ_DUMMY_DATA 0xFFU /* SUBGHZSPI Dummy Data use for Tx */ #define SUBGHZ_DEEP_SLEEP_ENABLE 1U /* SUBGHZ Radio in Deep Sleep */ #define SUBGHZ_DEEP_SLEEP_DISABLE 0U /* SUBGHZ Radio not in Deep Sleep */ /* SystemCoreClock dividers. Corresponding to time execution of while loop. */ #define SUBGHZ_DEFAULT_LOOP_TIME ((SystemCoreClock*28U)>>19U) #define SUBGHZ_RFBUSY_LOOP_TIME ((SystemCoreClock*24U)>>20U) #define SUBGHZ_NSS_LOOP_TIME ((SystemCoreClock*24U)>>16U) /** * @} */ /* Private macros ------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ /* Private function prototypes -----------------------------------------------*/ /** @defgroup SUBGHZ_Private_Functions SUBGHZ Private Functions * @{ */ void SUBGHZSPI_Init(uint32_t BaudratePrescaler); void SUBGHZSPI_DeInit(void); HAL_StatusTypeDef SUBGHZSPI_Transmit(SUBGHZ_HandleTypeDef *hsubghz, uint8_t Data); HAL_StatusTypeDef SUBGHZSPI_Receive(SUBGHZ_HandleTypeDef *hsubghz, uint8_t *pData); HAL_StatusTypeDef SUBGHZ_WaitOnBusy(SUBGHZ_HandleTypeDef *hsubghz); HAL_StatusTypeDef SUBGHZ_CheckDeviceReady(SUBGHZ_HandleTypeDef *hsubghz); /** * @} */ /* Exported functions --------------------------------------------------------*/ /** @defgroup SUBGHZ_Exported_Functions SUBGHZ Exported Functions * @{ */ /** @defgroup SUBGHZ_Exported_Functions_Group1 Initialization and de-initialization functions * @brief Initialization and Configuration functions * @verbatim =============================================================================== ##### Initialization and de-initialization functions ##### =============================================================================== [..] This subsection provides a set of functions allowing to initialize and de-initialize the SUBGHZ peripheral: (+) User must implement HAL_SUBGHZ_MspInit() function in which he configures all related peripherals resources (CLOCK, GPIO, IT and NVIC ). (+) Call the function HAL_SUBGHZ_Init() to configure SUBGHZSPI peripheral and initialize SUBGHZ Handle. (+) Call the function HAL_SUBGHZ_DeInit() to restore the default configuration of the SUBGHZ peripheral. @endverbatim * @{ */ /** * @brief Initialize the SUBGHZ according to the specified parameters * in the SUBGHZ_HandleTypeDef and initialize the associated handle. * @param hsubghz pointer to a SUBGHZ_HandleTypeDef structure that contains * the handle information for SUBGHZ module. * @note In case of exiting from Standby mode, before calling this function, * set the state to HAL_SUBGHZ_STATE_RESET_RF_READY with __HAL_SUBGHZ_RESET_HANDLE_STATE_RF_READY * to avoid the reset of Radio peripheral. * @retval HAL status */ HAL_StatusTypeDef HAL_SUBGHZ_Init(SUBGHZ_HandleTypeDef *hsubghz) { HAL_StatusTypeDef status; __IO uint32_t count; HAL_SUBGHZ_StateTypeDef subghz_state; /* Check the hsubghz handle allocation */ if (hsubghz == NULL) { status = HAL_ERROR; return status; } else { status = HAL_OK; } assert_param(IS_SUBGHZSPI_BAUDRATE_PRESCALER(hsubghz->Init.BaudratePrescaler)); subghz_state = hsubghz->State; if ((subghz_state == HAL_SUBGHZ_STATE_RESET) || (subghz_state == HAL_SUBGHZ_STATE_RESET_RF_READY)) { /* Allocate lock resource and initialize it */ hsubghz->Lock = HAL_UNLOCKED; #if (USE_HAL_SUBGHZ_REGISTER_CALLBACKS == 1) /* Init the SUBGHZ Legacy weak Callback settings */ hsubghz->TxCpltCallback = HAL_SUBGHZ_TxCpltCallback; hsubghz->RxCpltCallback = HAL_SUBGHZ_RxCpltCallback; hsubghz->PreambleDetectedCallback = HAL_SUBGHZ_PreambleDetectedCallback; hsubghz->SyncWordValidCallback = HAL_SUBGHZ_SyncWordValidCallback; hsubghz->HeaderValidCallback = HAL_SUBGHZ_HeaderValidCallback; hsubghz->HeaderErrorCallback = HAL_SUBGHZ_HeaderErrorCallback; hsubghz->CRCErrorCallback = HAL_SUBGHZ_CRCErrorCallback; hsubghz->CADStatusCallback = HAL_SUBGHZ_CADStatusCallback; hsubghz->RxTxTimeoutCallback = HAL_SUBGHZ_RxTxTimeoutCallback; hsubghz->LrFhssHopCallback = HAL_SUBGHZ_LrFhssHopCallback; if (hsubghz->MspInitCallback == NULL) { hsubghz->MspInitCallback = HAL_SUBGHZ_MspInit; /* Legacy weak MspInit */ } /* Init the low level hardware : GPIO, CLOCK, NVIC... */ hsubghz->MspInitCallback(hsubghz); #else /* Init the low level hardware : GPIO, CLOCK, NVIC... */ HAL_SUBGHZ_MspInit(hsubghz); #endif /* USE_HAL_ SUBGHZ_REGISTER_CALLBACKS */ #if defined(CM0PLUS) /* Enable EXTI 44 : Radio IRQ ITs for CPU2 */ LL_C2_EXTI_EnableIT_32_63(LL_EXTI_LINE_44); #else /* Enable EXTI 44 : Radio IRQ ITs for CPU1 */ LL_EXTI_EnableIT_32_63(LL_EXTI_LINE_44); #endif /* CM0PLUS */ } if (subghz_state == HAL_SUBGHZ_STATE_RESET) { /* Reinitialize Radio peripheral only if SUBGHZ is in full RESET state */ hsubghz->State = HAL_SUBGHZ_STATE_BUSY; /* De-asserts the reset signal of the Radio peripheral */ LL_RCC_RF_DisableReset(); /* Verify that Radio in reset status flag is set */ count = SUBGHZ_DEFAULT_TIMEOUT * SUBGHZ_DEFAULT_LOOP_TIME; do { if (count == 0U) { status = HAL_ERROR; hsubghz->ErrorCode = HAL_SUBGHZ_ERROR_TIMEOUT; break; } count--; } while (LL_RCC_IsRFUnderReset() != 0UL); /* Asserts the reset signal of the Radio peripheral */ LL_PWR_UnselectSUBGHZSPI_NSS(); #if defined(CM0PLUS) /* Enable wakeup signal of the Radio peripheral */ LL_C2_PWR_SetRadioBusyTrigger(LL_PWR_RADIO_BUSY_TRIGGER_WU_IT); #else /* Enable wakeup signal of the Radio peripheral */ LL_PWR_SetRadioBusyTrigger(LL_PWR_RADIO_BUSY_TRIGGER_WU_IT); #endif /* CM0PLUS */ } /* Clear Pending Flag */ LL_PWR_ClearFlag_RFBUSY(); if (status == HAL_OK) { /* Initialize SUBGHZSPI Peripheral */ SUBGHZSPI_Init(hsubghz->Init.BaudratePrescaler); hsubghz->DeepSleep = SUBGHZ_DEEP_SLEEP_ENABLE; hsubghz->ErrorCode = HAL_SUBGHZ_ERROR_NONE; } hsubghz->State = HAL_SUBGHZ_STATE_READY; return status; } /** * @brief De-Initialize the SUBGHZ peripheral. * @param hsubghz pointer to a SUBGHZ_HandleTypeDef structure that contains * the handle information for SUBGHZ module. * @retval HAL status */ HAL_StatusTypeDef HAL_SUBGHZ_DeInit(SUBGHZ_HandleTypeDef *hsubghz) { HAL_StatusTypeDef status; __IO uint32_t count; /* Check the SUBGHZ handle allocation */ if (hsubghz == NULL) { status = HAL_ERROR; return status; } else { status = HAL_OK; } hsubghz->State = HAL_SUBGHZ_STATE_BUSY; /* DeInitialize SUBGHZSPI Peripheral */ SUBGHZSPI_DeInit(); #if (USE_HAL_SUBGHZ_REGISTER_CALLBACKS == 1) if (hsubghz->MspDeInitCallback == NULL) { hsubghz->MspDeInitCallback = HAL_SUBGHZ_MspDeInit; /* Legacy weak MspDeInit */ } /* DeInit the low level hardware: GPIO, CLOCK, NVIC... */ hsubghz->MspDeInitCallback(hsubghz); #else /* DeInit the low level hardware: GPIO, CLOCK, NVIC... */ HAL_SUBGHZ_MspDeInit(hsubghz); #endif /* USE_HAL_SUBGHZ_REGISTER_CALLBACKS */ #if defined(CM0PLUS) /* Disable EXTI 44 : Radio IRQ ITs for CPU2 */ LL_C2_EXTI_DisableIT_32_63(LL_EXTI_LINE_44); /* Disable wakeup signal of the Radio peripheral */ LL_C2_PWR_SetRadioBusyTrigger(LL_PWR_RADIO_BUSY_TRIGGER_NONE); #else /* Disable EXTI 44 : Radio IRQ ITs for CPU1 */ LL_EXTI_DisableIT_32_63(LL_EXTI_LINE_44); /* Disable wakeup signal of the Radio peripheral */ LL_PWR_SetRadioBusyTrigger(LL_PWR_RADIO_BUSY_TRIGGER_NONE); #endif /* CM0PLUS */ /* Clear Pending Flag */ LL_PWR_ClearFlag_RFBUSY(); /* Re-asserts the reset signal of the Radio peripheral */ LL_RCC_RF_EnableReset(); /* Verify that Radio in reset status flag is set */ count = SUBGHZ_DEFAULT_TIMEOUT * SUBGHZ_DEFAULT_LOOP_TIME; do { if (count == 0U) { status = HAL_ERROR; hsubghz->ErrorCode = HAL_SUBGHZ_ERROR_TIMEOUT; break; } count--; } while (LL_RCC_IsRFUnderReset() != 1UL); hsubghz->ErrorCode = HAL_SUBGHZ_ERROR_NONE; hsubghz->State = HAL_SUBGHZ_STATE_RESET; /* Release Lock */ __HAL_UNLOCK(hsubghz); return status; } /** * @brief Initialize the SUBGHZ MSP. * @param hsubghz pointer to a SUBGHZ_HandleTypeDef structure that contains * the handle information for SUBGHZ module. * @retval None */ __weak void HAL_SUBGHZ_MspInit(SUBGHZ_HandleTypeDef *hsubghz) { /* NOTE : This function should not be modified, when the callback is needed, the HAL_SUBGHZ_MspInit should be implemented in the user file */ /* Prevent unused argument(s) compilation warning */ UNUSED(hsubghz); } /** * @brief De-Initialize the SUBGHZ MSP. * @param hsubghz pointer to a SUBGHZ_HandleTypeDef structure that contains * the handle information for SUBGHZ module. * @retval None */ __weak void HAL_SUBGHZ_MspDeInit(SUBGHZ_HandleTypeDef *hsubghz) { /* NOTE : This function should not be modified, when the callback is needed, the HAL_SUBGHZ_MspDeInit should be implemented in the user file */ /* Prevent unused argument(s) compilation warning */ UNUSED(hsubghz); } #if (USE_HAL_SUBGHZ_REGISTER_CALLBACKS == 1) /** * @brief Register a User SUBGHZ Callback * To be used instead of the weak predefined callback * @param hsubghz pointer to a SUBGHZ_HandleTypeDef structure that contains * the configuration information for the specified SUBGHZ. * @param CallbackID ID of the callback to be registered * @param pCallback pointer to the Callback function * @retval HAL status */ HAL_StatusTypeDef HAL_SUBGHZ_RegisterCallback(SUBGHZ_HandleTypeDef *hsubghz, HAL_SUBGHZ_CallbackIDTypeDef CallbackID, pSUBGHZ_CallbackTypeDef pCallback) { HAL_StatusTypeDef status = HAL_OK; if (pCallback == NULL) { /* Update the error code */ hsubghz->ErrorCode |= HAL_SUBGHZ_ERROR_INVALID_CALLBACK; return HAL_ERROR; } /* Process locked */ __HAL_LOCK(hsubghz); if (HAL_SUBGHZ_STATE_READY == hsubghz->State) { switch (CallbackID) { case HAL_SUBGHZ_TX_COMPLETE_CB_ID : hsubghz->TxCpltCallback = pCallback; break; case HAL_SUBGHZ_RX_COMPLETE_CB_ID : hsubghz->RxCpltCallback = pCallback; break; case HAL_SUBGHZ_PREAMBLE_DETECTED_CB_ID : hsubghz->PreambleDetectedCallback = pCallback; break; case HAL_SUBGHZ_SYNCWORD_VALID_CB_ID : hsubghz->SyncWordValidCallback = pCallback; break; case HAL_SUBGHZ_HEADER_VALID_CB_ID : hsubghz->HeaderValidCallback = pCallback; break; case HAL_SUBGHZ_HEADER_ERROR_CB_ID : hsubghz->HeaderErrorCallback = pCallback; break; case HAL_SUBGHZ_CRC_ERROR_CB_ID : hsubghz->CRCErrorCallback = pCallback; break; case HAL_SUBGHZ_RX_TX_TIMEOUT_CB_ID : hsubghz->RxTxTimeoutCallback = pCallback; break; case HAL_SUBGHZ_MSPINIT_CB_ID : hsubghz->MspInitCallback = pCallback; break; case HAL_SUBGHZ_MSPDEINIT_CB_ID : hsubghz->MspDeInitCallback = pCallback; break; case HAL_SUBGHZ_LR_FHSS_HOP_CB_ID : hsubghz->LrFhssHopCallback = pCallback; break; default : /* Update the error code */ hsubghz->ErrorCode = HAL_SUBGHZ_ERROR_INVALID_CALLBACK; /* Return error status */ status = HAL_ERROR; break; } } else if (HAL_SUBGHZ_STATE_RESET == hsubghz->State) { switch (CallbackID) { case HAL_SUBGHZ_MSPINIT_CB_ID : hsubghz->MspInitCallback = pCallback; break; case HAL_SUBGHZ_MSPDEINIT_CB_ID : hsubghz->MspDeInitCallback = pCallback; break; default : /* Update the error code */ hsubghz->ErrorCode = HAL_SUBGHZ_ERROR_INVALID_CALLBACK; /* Return error status */ status = HAL_ERROR; break; } } else { /* Update the error code */ hsubghz->ErrorCode = HAL_SUBGHZ_ERROR_INVALID_CALLBACK; /* Return error status */ status = HAL_ERROR; } /* Release Lock */ __HAL_UNLOCK(hsubghz); return status; } /** * @brief Unregister an SUBGHZ Callback * SUBGHZ callback is redirected to the weak predefined callback * @param hsubghz pointer to a SUBGHZ_HandleTypeDef structure that contains * the configuration information for the specified SUBGHZ. * @param CallbackID ID of the callback to be unregistered * @retval HAL status */ HAL_StatusTypeDef HAL_SUBGHZ_UnRegisterCallback(SUBGHZ_HandleTypeDef *hsubghz, HAL_SUBGHZ_CallbackIDTypeDef CallbackID) { HAL_StatusTypeDef status = HAL_OK; /* Process locked */ __HAL_LOCK(hsubghz); if (HAL_SUBGHZ_STATE_READY == hsubghz->State) { /* call legacy weak callback function */ switch (CallbackID) { case HAL_SUBGHZ_TX_COMPLETE_CB_ID : hsubghz->TxCpltCallback = HAL_SUBGHZ_TxCpltCallback; break; case HAL_SUBGHZ_RX_COMPLETE_CB_ID : hsubghz->RxCpltCallback = HAL_SUBGHZ_RxCpltCallback; break; case HAL_SUBGHZ_PREAMBLE_DETECTED_CB_ID : hsubghz->PreambleDetectedCallback = HAL_SUBGHZ_PreambleDetectedCallback; break; case HAL_SUBGHZ_SYNCWORD_VALID_CB_ID : hsubghz->SyncWordValidCallback = HAL_SUBGHZ_SyncWordValidCallback; break; case HAL_SUBGHZ_HEADER_VALID_CB_ID : hsubghz->HeaderValidCallback = HAL_SUBGHZ_HeaderValidCallback; break; case HAL_SUBGHZ_HEADER_ERROR_CB_ID : hsubghz->HeaderErrorCallback = HAL_SUBGHZ_HeaderErrorCallback; break; case HAL_SUBGHZ_CRC_ERROR_CB_ID : hsubghz->CRCErrorCallback = HAL_SUBGHZ_CRCErrorCallback; break; case HAL_SUBGHZ_RX_TX_TIMEOUT_CB_ID : hsubghz->RxTxTimeoutCallback = HAL_SUBGHZ_RxTxTimeoutCallback; break; case HAL_SUBGHZ_MSPINIT_CB_ID : hsubghz->MspInitCallback = HAL_SUBGHZ_MspInit; break; case HAL_SUBGHZ_MSPDEINIT_CB_ID : hsubghz->MspDeInitCallback = HAL_SUBGHZ_MspDeInit; break; case HAL_SUBGHZ_LR_FHSS_HOP_CB_ID : hsubghz->LrFhssHopCallback = HAL_SUBGHZ_LrFhssHopCallback; break; default : /* Update the error code */ hsubghz->ErrorCode = HAL_SUBGHZ_ERROR_INVALID_CALLBACK; /* Return error status */ status = HAL_ERROR; break; } } else if (HAL_SUBGHZ_STATE_RESET == hsubghz->State) { switch (CallbackID) { case HAL_SUBGHZ_MSPINIT_CB_ID : hsubghz->MspInitCallback = HAL_SUBGHZ_MspInit; break; case HAL_SUBGHZ_MSPDEINIT_CB_ID : hsubghz->MspDeInitCallback = HAL_SUBGHZ_MspDeInit; break; default : /* Update the error code */ hsubghz->ErrorCode = HAL_SUBGHZ_ERROR_INVALID_CALLBACK; /* Return error status */ status = HAL_ERROR; break; } } else { /* Update the error code */ hsubghz->ErrorCode = HAL_SUBGHZ_ERROR_INVALID_CALLBACK; /* Return error status */ status = HAL_ERROR; } /* Release Lock */ __HAL_UNLOCK(hsubghz); return status; } /** * @brief Register the channel activity detection status SUBGHZ Callback * To be used instead of the weak HAL_SUBGHZ_AddrCallback() predefined callback * @param hsubghz Pointer to a SUBGHZ_HandleTypeDef structure that contains * the configuration information for the specified SUBGHZ. * @param pCallback pointer to the CAD Status Callback function * @retval HAL status */ HAL_StatusTypeDef HAL_SUBGHZ_RegisterCadStatusCallback(SUBGHZ_HandleTypeDef *hsubghz, pSUBGHZ_CadStatusCallbackTypeDef pCallback) { HAL_StatusTypeDef status = HAL_OK; if (pCallback == NULL) { /* Update the error code */ hsubghz->ErrorCode = HAL_SUBGHZ_ERROR_INVALID_CALLBACK; return HAL_ERROR; } /* Process locked */ __HAL_LOCK(hsubghz); if (HAL_SUBGHZ_STATE_READY == hsubghz->State) { hsubghz->CADStatusCallback = pCallback; } else { /* Update the error code */ hsubghz->ErrorCode = HAL_SUBGHZ_ERROR_INVALID_CALLBACK; /* Return error status */ status = HAL_ERROR; } /* Release Lock */ __HAL_UNLOCK(hsubghz); return status; } /** * @brief UnRegister the channel activity detection status SUBGHZ Callback * @param hsubghz Pointer to a SUBGHZ_HandleTypeDef structure that contains * the configuration information for the specified SUBGHZ. * @retval HAL status */ HAL_StatusTypeDef HAL_SUBGHZ_UnRegisterCadStatusCallback(SUBGHZ_HandleTypeDef *hsubghz) { HAL_StatusTypeDef status = HAL_OK; /* Process locked */ __HAL_LOCK(hsubghz); if (HAL_SUBGHZ_STATE_READY == hsubghz->State) { hsubghz->CADStatusCallback = HAL_SUBGHZ_CADStatusCallback; /* Legacy weak AddrCallback */ } else { /* Update the error code */ hsubghz->ErrorCode = HAL_SUBGHZ_ERROR_INVALID_CALLBACK; /* Return error status */ status = HAL_ERROR; } /* Release Lock */ __HAL_UNLOCK(hsubghz); return status; } #endif /* USE_HAL_SUBGHZ_REGISTER_CALLBACKS */ /** * @} */ /** @defgroup SUBGHZ_Exported_Functions_Group2 IO operation functions * @brief Data transfers functions * @verbatim ============================================================================== ##### IO operation functions ##### =============================================================================== [..] This subsection provides a set of functions allowing to manage the SUBGHZ data transfers. [..] The SUBGHZ supports Read and Write operation: (#) There are four modes of transfer: (++) Set operation: The Set Command operation is performed in polling mode. The HAL status of command processing is returned by the same function after finishing transfer. (++) Get operation: The Get Status operation is performed using polling mode These API update buffer in parameter to retrieve status of command. These API return the HAL status (++) Write operation: The write operation is performed in polling mode. The HAL status of all data processing is returned by the same function after finishing transfer. (++) Read operation: The read operation is performed using polling mode These APIs return the HAL status. (#) Blocking mode functions are : (++) HAL_SUBGHZ_ExecSetCmd( (++) HAL_SUBGHZ_ExecGetCmd() (++) HAL_SUBGHZ_WriteBuffer() (++) HAL_SUBGHZ_ReadBuffer() (++) HAL_SUBGHZ_WriteRegisters() (++) HAL_SUBGHZ_ReadRegisters() (++) HAL_SUBGHZ_WriteRegister() (++) HAL_SUBGHZ_ReadRegister() @endverbatim * @{ */ /** * @brief Write data buffer at an Address to configurate the peripheral * @param hsubghz pointer to a SUBGHZ_HandleTypeDef structure that contains * the configuration information for the specified SUBGHZ. * @param Address register to configurate * @param pBuffer pointer to a data buffer * @param Size amount of data to be sent * @retval HAL status */ HAL_StatusTypeDef HAL_SUBGHZ_WriteRegisters(SUBGHZ_HandleTypeDef *hsubghz, uint16_t Address, uint8_t *pBuffer, uint16_t Size) { HAL_StatusTypeDef status; if (hsubghz->State == HAL_SUBGHZ_STATE_READY) { /* Process Locked */ __HAL_LOCK(hsubghz); hsubghz->State = HAL_SUBGHZ_STATE_BUSY; (void)SUBGHZ_CheckDeviceReady(hsubghz); /* NSS = 0 */ LL_PWR_SelectSUBGHZSPI_NSS(); (void)SUBGHZSPI_Transmit(hsubghz, SUBGHZ_RADIO_WRITE_REGISTER); (void)SUBGHZSPI_Transmit(hsubghz, (uint8_t)((Address & 0xFF00U) >> 8U)); (void)SUBGHZSPI_Transmit(hsubghz, (uint8_t)(Address & 0x00FFU)); for (uint16_t i = 0U; i < Size; i++) { (void)SUBGHZSPI_Transmit(hsubghz, pBuffer[i]); } /* NSS = 1 */ LL_PWR_UnselectSUBGHZSPI_NSS(); (void)SUBGHZ_WaitOnBusy(hsubghz); if (hsubghz->ErrorCode != HAL_SUBGHZ_ERROR_NONE) { status = HAL_ERROR; } else { status = HAL_OK; } hsubghz->State = HAL_SUBGHZ_STATE_READY; /* Process Unlocked */ __HAL_UNLOCK(hsubghz); return status; } else { return HAL_BUSY; } } /** * @brief Read data register at an Address in the peripheral * @param hsubghz pointer to a SUBGHZ_HandleTypeDef structure that contains * the configuration information for the specified SUBGHZ. * @param Address register to configurate * @param pBuffer pointer to a data buffer * @param Size amount of data to be sent * @retval HAL status */ HAL_StatusTypeDef HAL_SUBGHZ_ReadRegisters(SUBGHZ_HandleTypeDef *hsubghz, uint16_t Address, uint8_t *pBuffer, uint16_t Size) { HAL_StatusTypeDef status; uint8_t *pData = pBuffer; if (hsubghz->State == HAL_SUBGHZ_STATE_READY) { /* Process Locked */ __HAL_LOCK(hsubghz); (void)SUBGHZ_CheckDeviceReady(hsubghz); /* NSS = 0 */ LL_PWR_SelectSUBGHZSPI_NSS(); (void)SUBGHZSPI_Transmit(hsubghz, SUBGHZ_RADIO_READ_REGISTER); (void)SUBGHZSPI_Transmit(hsubghz, (uint8_t)((Address & 0xFF00U) >> 8U)); (void)SUBGHZSPI_Transmit(hsubghz, (uint8_t)(Address & 0x00FFU)); (void)SUBGHZSPI_Transmit(hsubghz, 0U); for (uint16_t i = 0U; i < Size; i++) { (void)SUBGHZSPI_Receive(hsubghz, (pData)); pData++; } /* NSS = 1 */ LL_PWR_UnselectSUBGHZSPI_NSS(); (void)SUBGHZ_WaitOnBusy(hsubghz); if (hsubghz->ErrorCode != HAL_SUBGHZ_ERROR_NONE) { status = HAL_ERROR; } else { status = HAL_OK; } hsubghz->State = HAL_SUBGHZ_STATE_READY; /* Process Unlocked */ __HAL_UNLOCK(hsubghz); return status; } else { return HAL_BUSY; } } /** * @brief Write one data at an Address to configurate the peripheral * @param hsubghz pointer to a SUBGHZ_HandleTypeDef structure that contains * the configuration information for the specified SUBGHZ. * @param Address register to configurate * @param Value data * @retval HAL status */ HAL_StatusTypeDef HAL_SUBGHZ_WriteRegister(SUBGHZ_HandleTypeDef *hsubghz, uint16_t Address, uint8_t Value) { return (HAL_SUBGHZ_WriteRegisters(hsubghz, Address, &Value, 1U)); } /** * @brief Read data register at an Address in the peripheral * @param hsubghz pointer to a SUBGHZ_HandleTypeDef structure that contains * the configuration information for the specified SUBGHZ. * @param Address register to configurate * @param pValue pointer to a data * @retval HAL status */ HAL_StatusTypeDef HAL_SUBGHZ_ReadRegister(SUBGHZ_HandleTypeDef *hsubghz, uint16_t Address, uint8_t *pValue) { return (HAL_SUBGHZ_ReadRegisters(hsubghz, Address, pValue, 1U)); } /** * @brief Send a command to configure the peripheral * @param hsubghz pointer to a SUBGHZ_HandleTypeDef structure that contains * the configuration information for the specified SUBGHZ. * @param Command configuration for peripheral * @param pBuffer pointer to a data buffer * @param Size amount of data to be sent * @retval HAL status */ HAL_StatusTypeDef HAL_SUBGHZ_ExecSetCmd(SUBGHZ_HandleTypeDef *hsubghz, SUBGHZ_RadioSetCmd_t Command, uint8_t *pBuffer, uint16_t Size) { HAL_StatusTypeDef status; /* LORA Modulation not available on STM32WLx4xx devices */ assert_param(IS_SUBGHZ_MODULATION_SUPPORTED(Command, pBuffer[0U])); if (hsubghz->State == HAL_SUBGHZ_STATE_READY) { /* Process Locked */ __HAL_LOCK(hsubghz); /* Need to wakeup Radio if already in Sleep at startup */ (void)SUBGHZ_CheckDeviceReady(hsubghz); if ((Command == RADIO_SET_SLEEP) || (Command == RADIO_SET_RXDUTYCYCLE)) { hsubghz->DeepSleep = SUBGHZ_DEEP_SLEEP_ENABLE; } else { hsubghz->DeepSleep = SUBGHZ_DEEP_SLEEP_DISABLE; } /* NSS = 0 */ LL_PWR_SelectSUBGHZSPI_NSS(); (void)SUBGHZSPI_Transmit(hsubghz, (uint8_t)Command); for (uint16_t i = 0U; i < Size; i++) { (void)SUBGHZSPI_Transmit(hsubghz, pBuffer[i]); } /* NSS = 1 */ LL_PWR_UnselectSUBGHZSPI_NSS(); if (Command != RADIO_SET_SLEEP) { (void)SUBGHZ_WaitOnBusy(hsubghz); } if (hsubghz->ErrorCode != HAL_SUBGHZ_ERROR_NONE) { status = HAL_ERROR; } else { status = HAL_OK; } hsubghz->State = HAL_SUBGHZ_STATE_READY; /* Process Unlocked */ __HAL_UNLOCK(hsubghz); return status; } else { return HAL_BUSY; } } /** * @brief Retrieve a status from the peripheral * @param hsubghz pointer to a SUBGHZ_HandleTypeDef structure that contains * the configuration information for the specified SUBGHZ. * @param Command configuration for peripheral * @param pBuffer pointer to a data buffer * @param Size amount of data to be sent * @retval HAL status */ HAL_StatusTypeDef HAL_SUBGHZ_ExecGetCmd(SUBGHZ_HandleTypeDef *hsubghz, SUBGHZ_RadioGetCmd_t Command, uint8_t *pBuffer, uint16_t Size) { HAL_StatusTypeDef status; uint8_t *pData = pBuffer; if (hsubghz->State == HAL_SUBGHZ_STATE_READY) { /* Process Locked */ __HAL_LOCK(hsubghz); (void)SUBGHZ_CheckDeviceReady(hsubghz); /* NSS = 0 */ LL_PWR_SelectSUBGHZSPI_NSS(); (void)SUBGHZSPI_Transmit(hsubghz, (uint8_t)Command); /* Use to flush the Status (First byte) receive from SUBGHZ as not use */ (void)SUBGHZSPI_Transmit(hsubghz, 0x00U); for (uint16_t i = 0U; i < Size; i++) { (void)SUBGHZSPI_Receive(hsubghz, (pData)); pData++; } /* NSS = 1 */ LL_PWR_UnselectSUBGHZSPI_NSS(); (void)SUBGHZ_WaitOnBusy(hsubghz); if (hsubghz->ErrorCode != HAL_SUBGHZ_ERROR_NONE) { status = HAL_ERROR; } else { status = HAL_OK; } hsubghz->State = HAL_SUBGHZ_STATE_READY; /* Process Unlocked */ __HAL_UNLOCK(hsubghz); return status; } else { return HAL_BUSY; } } /** * @brief Write data buffer inside payload of peripheral * @param hsubghz pointer to a SUBGHZ_HandleTypeDef structure that contains * the configuration information for the specified SUBGHZ. * @param Offset Offset inside payload * @param pBuffer pointer to a data buffer * @param Size amount of data to be sent * @retval HAL status */ HAL_StatusTypeDef HAL_SUBGHZ_WriteBuffer(SUBGHZ_HandleTypeDef *hsubghz, uint8_t Offset, uint8_t *pBuffer, uint16_t Size) { HAL_StatusTypeDef status; if (hsubghz->State == HAL_SUBGHZ_STATE_READY) { /* Process Locked */ __HAL_LOCK(hsubghz); (void)SUBGHZ_CheckDeviceReady(hsubghz); /* NSS = 0 */ LL_PWR_SelectSUBGHZSPI_NSS(); (void)SUBGHZSPI_Transmit(hsubghz, SUBGHZ_RADIO_WRITE_BUFFER); (void)SUBGHZSPI_Transmit(hsubghz, Offset); for (uint16_t i = 0U; i < Size; i++) { (void)SUBGHZSPI_Transmit(hsubghz, pBuffer[i]); } /* NSS = 1 */ LL_PWR_UnselectSUBGHZSPI_NSS(); (void)SUBGHZ_WaitOnBusy(hsubghz); if (hsubghz->ErrorCode != HAL_SUBGHZ_ERROR_NONE) { status = HAL_ERROR; } else { status = HAL_OK; } hsubghz->State = HAL_SUBGHZ_STATE_READY; /* Process Unlocked */ __HAL_UNLOCK(hsubghz); return status; } else { return HAL_BUSY; } } /** * @brief Read data buffer inside payload of peripheral * @param hsubghz pointer to a SUBGHZ_HandleTypeDef structure that contains * the configuration information for the specified SUBGHZ. * @param Offset Offset inside payload * @param pBuffer pointer to a data buffer * @param Size amount of data to be sent * @retval HAL status */ HAL_StatusTypeDef HAL_SUBGHZ_ReadBuffer(SUBGHZ_HandleTypeDef *hsubghz, uint8_t Offset, uint8_t *pBuffer, uint16_t Size) { HAL_StatusTypeDef status; uint8_t *pData = pBuffer; if (hsubghz->State == HAL_SUBGHZ_STATE_READY) { /* Process Locked */ __HAL_LOCK(hsubghz); (void)SUBGHZ_CheckDeviceReady(hsubghz); /* NSS = 0 */ LL_PWR_SelectSUBGHZSPI_NSS(); (void)SUBGHZSPI_Transmit(hsubghz, SUBGHZ_RADIO_READ_BUFFER); (void)SUBGHZSPI_Transmit(hsubghz, Offset); (void)SUBGHZSPI_Transmit(hsubghz, 0x00U); for (uint16_t i = 0U; i < Size; i++) { (void)SUBGHZSPI_Receive(hsubghz, (pData)); pData++; } /* NSS = 1 */ LL_PWR_UnselectSUBGHZSPI_NSS(); (void)SUBGHZ_WaitOnBusy(hsubghz); if (hsubghz->ErrorCode != HAL_SUBGHZ_ERROR_NONE) { status = HAL_ERROR; } else { status = HAL_OK; } hsubghz->State = HAL_SUBGHZ_STATE_READY; /* Process Unlocked */ __HAL_UNLOCK(hsubghz); return status; } else { return HAL_BUSY; } } /** * @brief Handle SUBGHZ interrupt request. * @param hsubghz pointer to a SUBGHZ_HandleTypeDef structure that contains * the configuration information for the specified SUBGHZ module. * @retval None */ void HAL_SUBGHZ_IRQHandler(SUBGHZ_HandleTypeDef *hsubghz) { uint8_t tmpisr[2U] = {0U}; uint16_t itsource; /* Retrieve Interrupts from SUBGHZ Irq Register */ (void)HAL_SUBGHZ_ExecGetCmd(hsubghz, RADIO_GET_IRQSTATUS, tmpisr, 2U); itsource = tmpisr[0U]; itsource = (itsource << 8U) | tmpisr[1U]; /* Clear SUBGHZ Irq Register */ (void)HAL_SUBGHZ_ExecSetCmd(hsubghz, RADIO_CLR_IRQSTATUS, tmpisr, 2U); /* Packet transmission completed Interrupt */ if (SUBGHZ_CHECK_IT_SOURCE(itsource, SUBGHZ_IT_TX_CPLT) != RESET) { #if (USE_HAL_SUBGHZ_REGISTER_CALLBACKS == 1U) hsubghz->TxCpltCallback(hsubghz); #else HAL_SUBGHZ_TxCpltCallback(hsubghz); #endif /* USE_HAL_SUBGHZ_REGISTER_CALLBACKS */ } /* Packet received Interrupt */ if (SUBGHZ_CHECK_IT_SOURCE(itsource, SUBGHZ_IT_RX_CPLT) != RESET) { #if (USE_HAL_SUBGHZ_REGISTER_CALLBACKS == 1U) hsubghz->RxCpltCallback(hsubghz); #else HAL_SUBGHZ_RxCpltCallback(hsubghz); #endif /* USE_HAL_SUBGHZ_REGISTER_CALLBACKS */ } /* Preamble Detected Interrupt */ if (SUBGHZ_CHECK_IT_SOURCE(itsource, SUBGHZ_IT_PREAMBLE_DETECTED) != RESET) { #if (USE_HAL_SUBGHZ_REGISTER_CALLBACKS == 1U) hsubghz->PreambleDetectedCallback(hsubghz); #else HAL_SUBGHZ_PreambleDetectedCallback(hsubghz); #endif /* USE_HAL_SUBGHZ_REGISTER_CALLBACKS */ } /* Valid sync word detected Interrupt */ if (SUBGHZ_CHECK_IT_SOURCE(itsource, SUBGHZ_IT_SYNCWORD_VALID) != RESET) { #if (USE_HAL_SUBGHZ_REGISTER_CALLBACKS == 1U) hsubghz->SyncWordValidCallback(hsubghz); #else HAL_SUBGHZ_SyncWordValidCallback(hsubghz); #endif /* USE_HAL_SUBGHZ_REGISTER_CALLBACKS */ } /* Valid LoRa header received Interrupt */ if (SUBGHZ_CHECK_IT_SOURCE(itsource, SUBGHZ_IT_HEADER_VALID) != RESET) { #if (USE_HAL_SUBGHZ_REGISTER_CALLBACKS == 1U) hsubghz->HeaderValidCallback(hsubghz); #else HAL_SUBGHZ_HeaderValidCallback(hsubghz); #endif /* USE_HAL_SUBGHZ_REGISTER_CALLBACKS */ } /* LoRa header CRC error Interrupt */ if (SUBGHZ_CHECK_IT_SOURCE(itsource, SUBGHZ_IT_HEADER_ERROR) != RESET) { #if (USE_HAL_SUBGHZ_REGISTER_CALLBACKS == 1U) hsubghz->HeaderErrorCallback(hsubghz); #else HAL_SUBGHZ_HeaderErrorCallback(hsubghz); #endif /* USE_HAL_SUBGHZ_REGISTER_CALLBACKS */ } /* Wrong CRC received Interrupt */ if (SUBGHZ_CHECK_IT_SOURCE(itsource, SUBGHZ_IT_CRC_ERROR) != RESET) { #if (USE_HAL_SUBGHZ_REGISTER_CALLBACKS == 1U) hsubghz->CRCErrorCallback(hsubghz); #else HAL_SUBGHZ_CRCErrorCallback(hsubghz); #endif /* USE_HAL_SUBGHZ_REGISTER_CALLBACKS */ } /* Channel activity detection finished Interrupt */ if (SUBGHZ_CHECK_IT_SOURCE(itsource, SUBGHZ_IT_CAD_DONE) != RESET) { #if (USE_HAL_SUBGHZ_REGISTER_CALLBACKS == 1U) /* Channel activity Detected Interrupt */ if (SUBGHZ_CHECK_IT_SOURCE(itsource, SUBGHZ_IT_CAD_ACTIVITY_DETECTED) != RESET) { hsubghz->CADStatusCallback(hsubghz, HAL_SUBGHZ_CAD_DETECTED); } else { hsubghz->CADStatusCallback(hsubghz, HAL_SUBGHZ_CAD_CLEAR); } #else /* Channel activity Detected Interrupt */ if (SUBGHZ_CHECK_IT_SOURCE(itsource, SUBGHZ_IT_CAD_ACTIVITY_DETECTED) != RESET) { HAL_SUBGHZ_CADStatusCallback(hsubghz, HAL_SUBGHZ_CAD_DETECTED); } else { HAL_SUBGHZ_CADStatusCallback(hsubghz, HAL_SUBGHZ_CAD_CLEAR); } #endif /* USE_HAL_SUBGHZ_REGISTER_CALLBACKS */ } /* Rx or Tx Timeout Interrupt */ if (SUBGHZ_CHECK_IT_SOURCE(itsource, SUBGHZ_IT_RX_TX_TIMEOUT) != RESET) { #if (USE_HAL_SUBGHZ_REGISTER_CALLBACKS == 1U) hsubghz->RxTxTimeoutCallback(hsubghz); #else HAL_SUBGHZ_RxTxTimeoutCallback(hsubghz); #endif /* USE_HAL_SUBGHZ_REGISTER_CALLBACKS */ } /* LR_FHSS Hop interrupt */ if (SUBGHZ_CHECK_IT_SOURCE(itsource, SUBGHZ_IT_LR_FHSS_HOP) != RESET) { #if (USE_HAL_SUBGHZ_REGISTER_CALLBACKS == 1U) hsubghz->LrFhssHopCallback(hsubghz); #else HAL_SUBGHZ_LrFhssHopCallback(hsubghz); #endif /* USE_HAL_SUBGHZ_REGISTER_CALLBACKS */ } } /** * @brief Packet transmission completed callback. * @param hsubghz pointer to a SUBGHZ_HandleTypeDef structure that contains * the configuration information for SUBGHZ module. * @retval None */ __weak void HAL_SUBGHZ_TxCpltCallback(SUBGHZ_HandleTypeDef *hsubghz) { /* Prevent unused argument(s) compilation warning */ UNUSED(hsubghz); /* NOTE : This function should not be modified, when the callback is needed, the HAL_SUBGHZ_TxCpltCallback should be implemented in the user file */ } /** * @brief Packet received callback. * @param hsubghz pointer to a SUBGHZ_HandleTypeDef structure that contains * the configuration information for SUBGHZ module. * @retval None */ __weak void HAL_SUBGHZ_RxCpltCallback(SUBGHZ_HandleTypeDef *hsubghz) { /* Prevent unused argument(s) compilation warning */ UNUSED(hsubghz); /* NOTE : This function should not be modified, when the callback is needed, the HAL_SUBGHZ_RxCpltCallback should be implemented in the user file */ } /** * @brief Preamble Detected callback. * @param hsubghz pointer to a SUBGHZ_HandleTypeDef structure that contains * the configuration information for SUBGHZ module. * @retval None */ __weak void HAL_SUBGHZ_PreambleDetectedCallback(SUBGHZ_HandleTypeDef *hsubghz) { /* Prevent unused argument(s) compilation warning */ UNUSED(hsubghz); /* NOTE : This function should not be modified, when the callback is needed, the HAL_SUBGHZ_PreambleDetectedCallback should be implemented in the user file */ } /** * @brief Valid sync word detected callback. * @param hsubghz pointer to a SUBGHZ_HandleTypeDef structure that contains * the configuration information for SUBGHZ module. * @retval None */ __weak void HAL_SUBGHZ_SyncWordValidCallback(SUBGHZ_HandleTypeDef *hsubghz) { /* Prevent unused argument(s) compilation warning */ UNUSED(hsubghz); /* NOTE : This function should not be modified, when the callback is needed, the HAL_SUBGHZ_SyncWordValidCallback should be implemented in the user file */ } /** * @brief Valid LoRa header received callback. * @param hsubghz pointer to a SUBGHZ_HandleTypeDef structure that contains * the configuration information for SUBGHZ module. * @retval None */ __weak void HAL_SUBGHZ_HeaderValidCallback(SUBGHZ_HandleTypeDef *hsubghz) { /* Prevent unused argument(s) compilation warning */ UNUSED(hsubghz); /* NOTE : This function should not be modified, when the callback is needed, the HAL_SUBGHZ_HeaderValidCallback should be implemented in the user file */ } /** * @brief LoRa header CRC error callback. * @param hsubghz pointer to a SUBGHZ_HandleTypeDef structure that contains * the configuration information for SUBGHZ module. * @retval None */ __weak void HAL_SUBGHZ_HeaderErrorCallback(SUBGHZ_HandleTypeDef *hsubghz) { /* Prevent unused argument(s) compilation warning */ UNUSED(hsubghz); /* NOTE : This function should not be modified, when the callback is needed, the HAL_SUBGHZ_HeaderErrorCallback should be implemented in the user file */ } /** * @brief Wrong CRC received callback. * @param hsubghz pointer to a SUBGHZ_HandleTypeDef structure that contains * the configuration information for SUBGHZ module. * @retval None */ __weak void HAL_SUBGHZ_CRCErrorCallback(SUBGHZ_HandleTypeDef *hsubghz) { /* Prevent unused argument(s) compilation warning */ UNUSED(hsubghz); /* NOTE : This function should not be modified, when the callback is needed, the HAL_SUBGHZ_CRCErrorCallback should be implemented in the user file */ } /** * @brief Channel activity detection status callback. * @note Unified callback for CAD Done and CAD activity interrupts. * @param hsubghz pointer to a SUBGHZ_HandleTypeDef structure that contains * the configuration information for SUBGHZ module. * @param cadstatus reports whether activity is detected or not * @retval None */ __weak void HAL_SUBGHZ_CADStatusCallback(SUBGHZ_HandleTypeDef *hsubghz, HAL_SUBGHZ_CadStatusTypeDef cadstatus) { /* Prevent unused argument(s) compilation warning */ UNUSED(hsubghz); UNUSED(cadstatus); /* NOTE : This function should not be modified, when the callback is needed, the HAL_SUBGHZ_CADStatusCallback should be implemented in the user file */ } /** * @brief Rx or Tx Timeout callback. * @param hsubghz pointer to a SUBGHZ_HandleTypeDef structure that contains * the configuration information for SUBGHZ module. * @retval None */ __weak void HAL_SUBGHZ_RxTxTimeoutCallback(SUBGHZ_HandleTypeDef *hsubghz) { /* Prevent unused argument(s) compilation warning */ UNUSED(hsubghz); /* NOTE : This function should not be modified, when the callback is needed, the HAL_SUBGHZ_RxTxTimeoutCallback should be implemented in the user file */ } /** * @brief LR FHSS Hop callback. * @param hsubghz pointer to a SUBGHZ_HandleTypeDef structure that contains * the configuration information for SUBGHZ module. * @retval None */ __weak void HAL_SUBGHZ_LrFhssHopCallback(SUBGHZ_HandleTypeDef *hsubghz) { /* Prevent unused argument(s) compilation warning */ UNUSED(hsubghz); /* NOTE : This function should not be modified, when the callback is needed, the HAL_SUBGHZ_LrFhssHopCallback should be implemented in the user file */ } /** * @} */ /** @defgroup SUBGHZ_Exported_Functions_Group3 Peripheral State and Errors functions * @brief SUBGHZ control functions * @verbatim =============================================================================== ##### Peripheral State and Errors functions ##### =============================================================================== [..] This subsection provides a set of functions allowing to control the SUBGHZ. (+) HAL_SUBGHZ_GetState() API can be helpful to check in run-time the state of the SUBGHZ peripheral (+) HAL_SUBGHZ_GetError() check in run-time Errors occurring during communication @endverbatim * @{ */ /** * @brief Return the SUBGHZ handle state. * @param hsubghz pointer to a SUBGHZ_HandleTypeDef structure that contains * the handle information for SUBGHZ module. * @retval SUBGHZ state */ HAL_SUBGHZ_StateTypeDef HAL_SUBGHZ_GetState(SUBGHZ_HandleTypeDef *hsubghz) { /* Return SUBGHZ handle state */ return hsubghz->State; } /** * @brief Return the SUBGHZ error code. * @param hsubghz pointer to a SUBGHZ_HandleTypeDef structure that contains * the handle information for SUBGHZ module. * @retval SUBGHZ error code in bitmap format */ uint32_t HAL_SUBGHZ_GetError(SUBGHZ_HandleTypeDef *hsubghz) { /* Return SUBGHZ ErrorCode */ return hsubghz->ErrorCode; } /** * @} */ /** * @} */ /** @addtogroup SUBGHZ_Private_Functions * @brief Private functions * @{ */ /** * @brief Initializes the SUBGHZSPI peripheral * @param BaudratePrescaler SPI Baudrate prescaler * @retval None */ void SUBGHZSPI_Init(uint32_t BaudratePrescaler) { /* Check the parameters */ assert_param(IS_SUBGHZ_ALL_INSTANCE(SUBGHZSPI)); /* Disable SUBGHZSPI Peripheral */ CLEAR_BIT(SUBGHZSPI->CR1, SPI_CR1_SPE); /*----------------------- SPI CR1 Configuration ----------------------------* * SPI Mode: Master * * Communication Mode: 2 lines (Full-Duplex) * * Clock polarity: Low * * phase: 1st Edge * * NSS management: Internal (Done with External bit inside PWR * * Communication speed: BaudratePrescaler * * First bit: MSB * * CRC calculation: Disable * *--------------------------------------------------------------------------*/ WRITE_REG(SUBGHZSPI->CR1, (SPI_CR1_MSTR | SPI_CR1_SSI | BaudratePrescaler | SPI_CR1_SSM)); /*----------------------- SPI CR2 Configuration ----------------------------* * Data Size: 8bits * * TI Mode: Disable * * NSS Pulse: Disable * * Rx FIFO Threshold: 8bits * *--------------------------------------------------------------------------*/ WRITE_REG(SUBGHZSPI->CR2, (SPI_CR2_FRXTH | SPI_CR2_DS_0 | SPI_CR2_DS_1 | SPI_CR2_DS_2)); /* Enable SUBGHZSPI Peripheral */ SET_BIT(SUBGHZSPI->CR1, SPI_CR1_SPE); } /** * @brief DeInitializes the SUBGHZSPI peripheral * @retval None */ void SUBGHZSPI_DeInit(void) { /* Check the parameters */ assert_param(IS_SUBGHZ_ALL_INSTANCE(SUBGHZSPI)); /* Disable SUBGHZSPI Peripheral */ CLEAR_BIT(SUBGHZSPI->CR1, SPI_CR1_SPE); } /** * @brief Transmit data through SUBGHZSPI peripheral * @param hsubghz pointer to a SUBGHZ_HandleTypeDef structure that contains * the handle information for SUBGHZ module. * @param Data data to transmit * @retval HAL status */ HAL_StatusTypeDef SUBGHZSPI_Transmit(SUBGHZ_HandleTypeDef *hsubghz, uint8_t Data) { HAL_StatusTypeDef status = HAL_OK; __IO uint32_t count; /* Handle Tx transmission from SUBGHZSPI peripheral to Radio ****************/ /* Initialize Timeout */ count = SUBGHZ_DEFAULT_TIMEOUT * SUBGHZ_DEFAULT_LOOP_TIME; /* Wait until TXE flag is set */ do { if (count == 0U) { status = HAL_ERROR; hsubghz->ErrorCode = HAL_SUBGHZ_ERROR_TIMEOUT; break; } count--; } while (READ_BIT(SUBGHZSPI->SR, SPI_SR_TXE) != (SPI_SR_TXE)); /* Transmit Data*/ #if defined (__GNUC__) __IO uint8_t *spidr = ((__IO uint8_t *)&SUBGHZSPI->DR); *spidr = Data; #else *((__IO uint8_t *)&SUBGHZSPI->DR) = Data; #endif /* __GNUC__ */ /* Handle Rx transmission from SUBGHZSPI peripheral to Radio ****************/ /* Initialize Timeout */ count = SUBGHZ_DEFAULT_TIMEOUT * SUBGHZ_DEFAULT_LOOP_TIME; /* Wait until RXNE flag is set */ do { if (count == 0U) { status = HAL_ERROR; hsubghz->ErrorCode = HAL_SUBGHZ_ERROR_TIMEOUT; break; } count--; } while (READ_BIT(SUBGHZSPI->SR, SPI_SR_RXNE) != (SPI_SR_RXNE)); /* Flush Rx data */ READ_REG(SUBGHZSPI->DR); return status; } /** * @brief Receive data through SUBGHZSPI peripheral * @param hsubghz pointer to a SUBGHZ_HandleTypeDef structure that contains * the handle information for SUBGHZ module. * @param pData pointer on data to receive * @retval HAL status */ HAL_StatusTypeDef SUBGHZSPI_Receive(SUBGHZ_HandleTypeDef *hsubghz, uint8_t *pData) { HAL_StatusTypeDef status = HAL_OK; __IO uint32_t count; /* Handle Tx transmission from SUBGHZSPI peripheral to Radio ****************/ /* Initialize Timeout */ count = SUBGHZ_DEFAULT_TIMEOUT * SUBGHZ_DEFAULT_LOOP_TIME; /* Wait until TXE flag is set */ do { if (count == 0U) { status = HAL_ERROR; hsubghz->ErrorCode = HAL_SUBGHZ_ERROR_TIMEOUT; break; } count--; } while (READ_BIT(SUBGHZSPI->SR, SPI_SR_TXE) != (SPI_SR_TXE)); /* Transmit Data*/ #if defined (__GNUC__) __IO uint8_t *spidr = ((__IO uint8_t *)&SUBGHZSPI->DR); *spidr = SUBGHZ_DUMMY_DATA; #else *((__IO uint8_t *)&SUBGHZSPI->DR) = SUBGHZ_DUMMY_DATA; #endif /* __GNUC__ */ /* Handle Rx transmission from SUBGHZSPI peripheral to Radio ****************/ /* Initialize Timeout */ count = SUBGHZ_DEFAULT_TIMEOUT * SUBGHZ_DEFAULT_LOOP_TIME; /* Wait until RXNE flag is set */ do { if (count == 0U) { status = HAL_ERROR; hsubghz->ErrorCode = HAL_SUBGHZ_ERROR_TIMEOUT; break; } count--; } while (READ_BIT(SUBGHZSPI->SR, SPI_SR_RXNE) != (SPI_SR_RXNE)); /* Retrieve pData */ *pData = (uint8_t)(READ_REG(SUBGHZSPI->DR)); return status; } /** * @brief Check if peripheral is ready * @param hsubghz pointer to a SUBGHZ_HandleTypeDef structure that contains * the handle information for SUBGHZ module. * @retval HAL status */ HAL_StatusTypeDef SUBGHZ_CheckDeviceReady(SUBGHZ_HandleTypeDef *hsubghz) { __IO uint32_t count; /* Wakeup radio in case of sleep mode: Select-Unselect radio */ if (hsubghz->DeepSleep == SUBGHZ_DEEP_SLEEP_ENABLE) { /* Initialize NSS switch Delay */ count = SUBGHZ_NSS_LOOP_TIME; /* NSS = 0; */ LL_PWR_SelectSUBGHZSPI_NSS(); /* Wait Radio wakeup */ do { count--; } while (count != 0UL); /* NSS = 1 */ LL_PWR_UnselectSUBGHZSPI_NSS(); } return (SUBGHZ_WaitOnBusy(hsubghz)); } /** * @brief Wait busy flag low from peripheral * @param hsubghz pointer to a SUBGHZ_HandleTypeDef structure that contains * the handle information for SUBGHZ module. * @retval HAL status */ HAL_StatusTypeDef SUBGHZ_WaitOnBusy(SUBGHZ_HandleTypeDef *hsubghz) { HAL_StatusTypeDef status; __IO uint32_t count; uint32_t mask; status = HAL_OK; count = SUBGHZ_DEFAULT_TIMEOUT * SUBGHZ_RFBUSY_LOOP_TIME; /* Wait until Busy signal is set */ do { mask = LL_PWR_IsActiveFlag_RFBUSYMS(); if (count == 0U) { status = HAL_ERROR; hsubghz->ErrorCode = HAL_SUBGHZ_ERROR_RF_BUSY; break; } count--; } while ((LL_PWR_IsActiveFlag_RFBUSYS()& mask) == 1UL); return status; } /** * @} */ #endif /* HAL_SUBGHZ_MODULE_ENABLED */ /** * @} */ /** * @} */