blob: c66c8dbea83d12ea9c8aa4bb7cdd17e875857dc8 [file] [log] [blame]
/*******************************************************************************
* @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 */
/**
* @}
*/
/**
* @}
*/