/**
  ******************************************************************************
  * @file    stm32wlxx_hal_ipcc.c
  * @author  MCD Application Team
  * @brief   IPCC HAL module driver.
  *          This file provides firmware functions to manage the following
  *          functionalities of the Inter-Processor communication controller
  *          peripherals (IPCC).
  *           + Initialization and de-initialization functions
  *           + Configuration, notification and interrupts handling
  *           + Peripheral State and Error functions
  @verbatim
  ==============================================================================
                        ##### How to use this driver #####
  ==============================================================================
    [..]
      The IPCC HAL driver can be used as follows:

      (#) Declare a IPCC_HandleTypeDef handle structure, for example: IPCC_HandleTypeDef hipcc;
      (#) Initialize the IPCC low level resources by implementing the HAL_IPCC_MspInit() API:
        (##) Enable the IPCC interface clock
        (##) NVIC configuration if you need to use interrupt process
            (+++) Configure the IPCC interrupt priority
            (+++) Enable the NVIC IPCC IRQ

      (#) Initialize the IPCC registers by calling the HAL_IPCC_Init() API which trig
          HAL_IPCC_MspInit().

      (#) Implement the interrupt callbacks for transmission and reception to use the driver in interrupt mode

      (#) Associate those callback to the corresponding channel and direction using HAL_IPCC_ConfigChannel().
          This is the interrupt mode.
          If no callback are configured for a given channel and direction, it is up to the user to poll the
          status of the communication (polling mode).

      (#) Notify the other MCU when a message is available in a chosen channel
          or when a message has been retrieved from a chosen channel by calling
          the HAL_IPCC_NotifyCPU() API.

@endverbatim
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under BSD 3-Clause license,
  * the "License"; You may not use this file except in compliance with the
  * License. You may obtain a copy of the License at:
  *                        opensource.org/licenses/BSD-3-Clause
  *
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "stm32wlxx_hal.h"

#if defined(IPCC)
/** @addtogroup STM32WLxx_HAL_Driver
  * @{
  */

/** @addtogroup IPCC
  * @{
  */

#ifdef HAL_IPCC_MODULE_ENABLED

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/** @defgroup IPCC_Private_Constants IPCC Private Constants
  * @{
  */
#define IPCC_ALL_RX_BUF 0x0000003FU /*!< Mask for all RX buffers. */
#define IPCC_ALL_TX_BUF 0x003F0000U /*!< Mask for all TX buffers. */
#define CHANNEL_INDEX_Msk 0x0000000FU /*!< Mask the channel index to avoid overflow */
/**
  * @}
  */

/* Private macros ------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/** @defgroup IPCC_Private_Functions IPCC Private Functions
  * @{
  */
void IPCC_MaskInterrupt(uint32_t ChannelIndex, IPCC_CHANNELDirTypeDef ChannelDir);
void IPCC_UnmaskInterrupt(uint32_t ChannelIndex, IPCC_CHANNELDirTypeDef ChannelDir);
void IPCC_SetDefaultCallbacks(IPCC_HandleTypeDef *hipcc);
void IPCC_Reset_Register(IPCC_CommonTypeDef *Instance);
/**
  * @}
  */

/** @addtogroup IPCC_Exported_Functions
  * @{
  */

/** @addtogroup IPCC_Exported_Functions_Group1
 *  @brief    Initialization and de-initialization functions
 *
@verbatim
 ===============================================================================
             ##### Initialization and de-initialization functions  #####
 ===============================================================================
    [..]  This subsection provides a set of functions allowing to initialize and
          deinitialize the IPCC peripheral:

      (+) User must Implement HAL_IPCC_MspInit() function in which he configures
          all related peripherals resources (CLOCK and NVIC ).

      (+) Call the function HAL_IPCC_Init() to configure the IPCC register.

      (+) Call the function HAL_PKA_DeInit() to restore the default configuration
          of the selected IPCC peripheral.

@endverbatim
  * @{
  */

/**
  * @brief  Initialize the IPCC peripheral.
  * @param  hipcc IPCC handle
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_IPCC_Init(IPCC_HandleTypeDef *hipcc)
{
  HAL_StatusTypeDef err = HAL_OK;

  /* Check the IPCC handle allocation */
  if (hipcc != NULL)
  {
    /* Check the parameters */
    assert_param(IS_IPCC_ALL_INSTANCE(hipcc->Instance));

#if defined(CORE_CM0PLUS)
    IPCC_CommonTypeDef *currentInstance = IPCC_C2;
#else
    IPCC_CommonTypeDef *currentInstance = IPCC_C1;
#endif

    if (hipcc->State == HAL_IPCC_STATE_RESET)
    {
      /* Init the low level hardware : CLOCK, NVIC */
      HAL_IPCC_MspInit(hipcc);
    }

    /* Reset all registers of the current cpu to default state */
    IPCC_Reset_Register(currentInstance);

    /* Activate the interrupts */
    currentInstance->CR |= (IPCC_CR_RXOIE | IPCC_CR_TXFIE);

    /* Clear callback pointers */
    IPCC_SetDefaultCallbacks(hipcc);

    /* Reset all callback notification request */
    hipcc->callbackRequest = 0;

    hipcc->State = HAL_IPCC_STATE_READY;
  }
  else
  {
    err = HAL_ERROR;
  }

  return err;
}

/**
  * @brief  DeInitialize the IPCC peripheral.
  * @param  hipcc IPCC handle
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_IPCC_DeInit(IPCC_HandleTypeDef *hipcc)
{
  HAL_StatusTypeDef err = HAL_OK;

  /* Check the IPCC handle allocation */
  if (hipcc != NULL)
  {
    assert_param(IS_IPCC_ALL_INSTANCE(hipcc->Instance));
#if defined(CORE_CM0PLUS)
    IPCC_CommonTypeDef *currentInstance = IPCC_C2;
#else
    IPCC_CommonTypeDef *currentInstance = IPCC_C1;
#endif

    /* Set the state to busy */
    hipcc->State = HAL_IPCC_STATE_BUSY;

    /* Reset all registers of the current cpu to default state */
    IPCC_Reset_Register(currentInstance);

    /* Clear callback pointers */
    IPCC_SetDefaultCallbacks(hipcc);

    /* Reset all callback notification request */
    hipcc->callbackRequest = 0;

    /* DeInit the low level hardware : CLOCK, NVIC */
    HAL_IPCC_MspDeInit(hipcc);

    hipcc->State = HAL_IPCC_STATE_RESET;
  }
  else
  {
    err = HAL_ERROR;
  }

  return err;
}

/**
  * @brief Initialize the IPCC MSP.
  * @param  hipcc IPCC handle
  * @retval None
  */
__weak void HAL_IPCC_MspInit(IPCC_HandleTypeDef *hipcc)
{
  /* Prevent unused argument(s) compilation warning */
  UNUSED(hipcc);

  /* NOTE : This function should not be modified. When the callback is needed
            the HAL_IPCC_MspInit should be implemented in the user file
   */
}

/**
  * @brief IPCC MSP DeInit
  * @param  hipcc IPCC handle
  * @retval None
  */
__weak void HAL_IPCC_MspDeInit(IPCC_HandleTypeDef *hipcc)
{
  /* Prevent unused argument(s) compilation warning */
  UNUSED(hipcc);

  /* NOTE : This function should not be modified. When the callback is needed
            the HAL_IPCC_MspDeInit should be implemented in the user file
   */
}

/**
  * @}
  */


/** @addtogroup IPCC_Exported_Functions_Group2
 *  @brief    Configuration, notification and Irq handling functions.
 *
@verbatim
 ===============================================================================
              ##### IO operation functions #####
 ===============================================================================
    [..]  This section provides functions to allow two MCU to communicate.

    (#) For a given channel (from 0 to IPCC_CHANNEL_NUMBER), for a given direction
        IPCC_CHANNEL_DIR_TX or IPCC_CHANNEL_DIR_RX, you can choose to communicate
        in polling mode or in interrupt mode using IPCC.
        By default, the IPCC HAL driver handle the communication in polling mode.
        By setting a callback for a channel/direction, this communication use
        the interrupt mode.

    (#) Polling mode:
       (++) To transmit information, use HAL_IPCC_NotifyCPU() with
            IPCC_CHANNEL_DIR_TX. To know when the other processor has handled
            the notification, poll the communication using HAL_IPCC_NotifyCPU
            with IPCC_CHANNEL_DIR_TX.

       (++) To receive information, poll the status of the communication with
            HAL_IPCC_GetChannelStatus with IPCC_CHANNEL_DIR_RX. To notify the other
            processor that the information has been received, use HAL_IPCC_NotifyCPU
            with IPCC_CHANNEL_DIR_RX.

    (#) Interrupt mode:
       (++) Configure a callback for the channel and the direction using HAL_IPCC_ConfigChannel().
            This callback will be triggered under interrupt.

       (++) To transmit information, use HAL_IPCC_NotifyCPU() with
            IPCC_CHANNEL_DIR_TX. The callback configured with HAL_IPCC_ConfigChannel() and
            IPCC_CHANNEL_DIR_TX will be triggered once the communication has been handled by the
            other processor.

       (++) To receive information, the callback configured with HAL_IPCC_ConfigChannel() and
            IPCC_CHANNEL_DIR_RX will be triggered on reception of a communication.To notify the other
            processor that the information has been received, use HAL_IPCC_NotifyCPU
            with IPCC_CHANNEL_DIR_RX.

       (++) HAL_IPCC_TX_IRQHandler must be added to the IPCC TX IRQHandler

       (++) HAL_IPCC_RX_IRQHandler must be added to the IPCC RX IRQHandler
@endverbatim
  * @{
  */

/**
  * @brief  Activate the callback notification on receive/transmit interrupt
  * @param  hipcc IPCC handle
  * @param  ChannelIndex Channel number
  *          This parameter can be one of the following values:
  *            @arg IPCC_CHANNEL_1: IPCC Channel 1
  *            @arg IPCC_CHANNEL_2: IPCC Channel 2
  *            @arg IPCC_CHANNEL_3: IPCC Channel 3
  *            @arg IPCC_CHANNEL_4: IPCC Channel 4
  *            @arg IPCC_CHANNEL_5: IPCC Channel 5
  *            @arg IPCC_CHANNEL_6: IPCC Channel 6
  * @param  ChannelDir Channel direction
  * @param  cb Interrupt callback
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_IPCC_ActivateNotification(IPCC_HandleTypeDef *hipcc, uint32_t ChannelIndex, IPCC_CHANNELDirTypeDef ChannelDir, ChannelCb cb)
{
  HAL_StatusTypeDef err = HAL_OK;

  /* Check the IPCC handle allocation */
  if (hipcc != NULL)
  {
    /* Check the parameters */
    assert_param(IS_IPCC_ALL_INSTANCE(hipcc->Instance));

    /* Check IPCC state */
    if (hipcc->State == HAL_IPCC_STATE_READY)
    {
      /* Set callback and register masking information */
      if (ChannelDir == IPCC_CHANNEL_DIR_TX)
      {
        hipcc->ChannelCallbackTx[ChannelIndex] = cb;
        hipcc->callbackRequest |= (IPCC_MR_CH1FM_Msk << (ChannelIndex & CHANNEL_INDEX_Msk));
      }
      else
      {
        hipcc->ChannelCallbackRx[ChannelIndex] = cb;
        hipcc->callbackRequest |= (IPCC_MR_CH1OM_Msk << (ChannelIndex & CHANNEL_INDEX_Msk));
      }

      /* Unmask only the channels in reception (Transmission channel mask/unmask is done in HAL_IPCC_NotifyCPU) */
      if (ChannelDir == IPCC_CHANNEL_DIR_RX)
      {
        IPCC_UnmaskInterrupt(ChannelIndex, ChannelDir);
      }
    }
    else
    {
      err = HAL_ERROR;
    }
  }
  else
  {
    err = HAL_ERROR;
  }
  return err;
}

/**
  * @brief  Remove the callback notification on receive/transmit interrupt
  * @param  hipcc IPCC handle
  * @param  ChannelIndex Channel number
  *          This parameter can be one of the following values:
  *            @arg IPCC_CHANNEL_1: IPCC Channel 1
  *            @arg IPCC_CHANNEL_2: IPCC Channel 2
  *            @arg IPCC_CHANNEL_3: IPCC Channel 3
  *            @arg IPCC_CHANNEL_4: IPCC Channel 4
  *            @arg IPCC_CHANNEL_5: IPCC Channel 5
  *            @arg IPCC_CHANNEL_6: IPCC Channel 6
  * @param  ChannelDir Channel direction
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_IPCC_DeActivateNotification(IPCC_HandleTypeDef *hipcc, uint32_t ChannelIndex, IPCC_CHANNELDirTypeDef ChannelDir)
{
  HAL_StatusTypeDef err = HAL_OK;

  /* Check the IPCC handle allocation */
  if (hipcc != NULL)
  {
    /* Check the parameters */
    assert_param(IS_IPCC_ALL_INSTANCE(hipcc->Instance));

    /* Check IPCC state */
    if (hipcc->State == HAL_IPCC_STATE_READY)
    {
      /* Set default callback and register masking information */
      if (ChannelDir == IPCC_CHANNEL_DIR_TX)
      {
        hipcc->ChannelCallbackTx[ChannelIndex] = HAL_IPCC_TxCallback;
        hipcc->callbackRequest &= ~(IPCC_MR_CH1FM_Msk << (ChannelIndex & CHANNEL_INDEX_Msk));
      }
      else
      {
        hipcc->ChannelCallbackRx[ChannelIndex] = HAL_IPCC_RxCallback;
        hipcc->callbackRequest &= ~(IPCC_MR_CH1OM_Msk << (ChannelIndex & CHANNEL_INDEX_Msk));
      }

      /* Mask the interrupt */
      IPCC_MaskInterrupt(ChannelIndex, ChannelDir);
    }
    else
    {
      err = HAL_ERROR;
    }
  }
  else
  {
    err = HAL_ERROR;
  }
  return err;
}

/**
  * @brief  Get state of IPCC channel
  * @param  hipcc IPCC handle
  * @param  ChannelIndex Channel number
  *          This parameter can be one of the following values:
  *            @arg IPCC_CHANNEL_1: IPCC Channel 1
  *            @arg IPCC_CHANNEL_2: IPCC Channel 2
  *            @arg IPCC_CHANNEL_3: IPCC Channel 3
  *            @arg IPCC_CHANNEL_4: IPCC Channel 4
  *            @arg IPCC_CHANNEL_5: IPCC Channel 5
  *            @arg IPCC_CHANNEL_6: IPCC Channel 6
  * @param  ChannelDir Channel direction
  * @retval Channel status
  */
IPCC_CHANNELStatusTypeDef HAL_IPCC_GetChannelStatus(IPCC_HandleTypeDef const *const hipcc, uint32_t ChannelIndex, IPCC_CHANNELDirTypeDef ChannelDir)
{
  uint32_t channel_state;
#if defined(CORE_CM0PLUS)
  IPCC_CommonTypeDef *currentInstance = IPCC_C2;
  IPCC_CommonTypeDef *otherInstance = IPCC_C1;
#else
  IPCC_CommonTypeDef *currentInstance = IPCC_C1;
  IPCC_CommonTypeDef *otherInstance = IPCC_C2;
#endif

  /* Check the parameters */
  assert_param(IS_IPCC_ALL_INSTANCE(hipcc->Instance));

  /* Read corresponding channel depending of the MCU and the direction */
  if (ChannelDir == IPCC_CHANNEL_DIR_TX)
  {
    channel_state = (currentInstance->SR) & (IPCC_SR_CH1F_Msk << (ChannelIndex & CHANNEL_INDEX_Msk));
  }
  else
  {
    channel_state = (otherInstance->SR) & (IPCC_SR_CH1F_Msk << (ChannelIndex & CHANNEL_INDEX_Msk));
  }

  return (channel_state == 0UL) ? IPCC_CHANNEL_STATUS_FREE : IPCC_CHANNEL_STATUS_OCCUPIED ;
}

/**
  * @brief  Notify remote processor
  * @param  hipcc IPCC handle
  * @param  ChannelIndex Channel number
  *          This parameter can be one of the following values:
  *            @arg IPCC_CHANNEL_1: IPCC Channel 1
  *            @arg IPCC_CHANNEL_2: IPCC Channel 2
  *            @arg IPCC_CHANNEL_3: IPCC Channel 3
  *            @arg IPCC_CHANNEL_4: IPCC Channel 4
  *            @arg IPCC_CHANNEL_5: IPCC Channel 5
  *            @arg IPCC_CHANNEL_6: IPCC Channel 6
  * @param  ChannelDir Channel direction
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_IPCC_NotifyCPU(IPCC_HandleTypeDef const *const hipcc, uint32_t ChannelIndex, IPCC_CHANNELDirTypeDef ChannelDir)
{
  HAL_StatusTypeDef err = HAL_OK;
  uint32_t mask;
#if defined(CORE_CM0PLUS)
  IPCC_CommonTypeDef *currentInstance = IPCC_C2;
#else
  IPCC_CommonTypeDef *currentInstance = IPCC_C1;
#endif

  /* Check the parameters */
  assert_param(IS_IPCC_ALL_INSTANCE(hipcc->Instance));

  /* Check if IPCC is initialized */
  if (hipcc->State == HAL_IPCC_STATE_READY)
  {
    /* For IPCC_CHANNEL_DIR_TX, set the status. For IPCC_CHANNEL_DIR_RX, clear the status */
    currentInstance->SCR |= ((ChannelDir == IPCC_CHANNEL_DIR_TX) ? IPCC_SCR_CH1S : IPCC_SCR_CH1C) << (ChannelIndex & CHANNEL_INDEX_Msk) ;

    /* Unmask interrupt if the callback is requested */
    mask = ((ChannelDir == IPCC_CHANNEL_DIR_TX) ? IPCC_MR_CH1FM_Msk : IPCC_MR_CH1OM_Msk) << (ChannelIndex & CHANNEL_INDEX_Msk) ;
    if ((hipcc->callbackRequest & mask) == mask)
    {
      IPCC_UnmaskInterrupt(ChannelIndex, ChannelDir);
    }
  }
  else
  {
    err = HAL_ERROR;
  }

  return err;
}

/**
  * @}
  */

/** @addtogroup IPCC_IRQ_Handler_and_Callbacks
 * @{
 */

/**
  * @brief  This function handles IPCC Tx Free interrupt request.
  * @param  hipcc IPCC handle
  * @retval None
  */
void HAL_IPCC_TX_IRQHandler(IPCC_HandleTypeDef *const hipcc)
{
  uint32_t irqmask;
  uint32_t bit_pos;
  uint32_t ch_count = 0U;
#if defined(CORE_CM0PLUS)
  IPCC_CommonTypeDef *currentInstance = IPCC_C2;
#else
  IPCC_CommonTypeDef *currentInstance = IPCC_C1;
#endif

  /* check the Tx free channels which are not masked */
  irqmask = ~(currentInstance->MR) & IPCC_ALL_TX_BUF;
  irqmask = irqmask & ~(currentInstance->SR << IPCC_MR_CH1FM_Pos);

  while (irqmask != 0UL)  /* if several bits are set, it loops to serve all of them */
  {
    bit_pos = 1UL << (IPCC_MR_CH1FM_Pos + (ch_count & CHANNEL_INDEX_Msk));

    if ((irqmask & bit_pos) != 0U)
    {
      /* mask the channel Free interrupt  */
      currentInstance->MR |= bit_pos;
      if (hipcc->ChannelCallbackTx[ch_count] != NULL)
      {
        hipcc->ChannelCallbackTx[ch_count](hipcc, ch_count, IPCC_CHANNEL_DIR_TX);
      }
      irqmask =  irqmask & ~(bit_pos);
    }
    ch_count++;
  }
}

/**
  * @brief  This function handles IPCC Rx Occupied interrupt request.
  * @param  hipcc : IPCC handle
  * @retval None
  */
void HAL_IPCC_RX_IRQHandler(IPCC_HandleTypeDef *const hipcc)
{
  uint32_t irqmask;
  uint32_t bit_pos;
  uint32_t ch_count = 0U;
#if defined(CORE_CM0PLUS)
  IPCC_CommonTypeDef *currentInstance = IPCC_C2;
  IPCC_CommonTypeDef *otherInstance = IPCC_C1;
#else
  IPCC_CommonTypeDef *currentInstance = IPCC_C1;
  IPCC_CommonTypeDef *otherInstance = IPCC_C2;
#endif

  /* check the Rx occupied channels which are not masked */
  irqmask = ~(currentInstance->MR) & IPCC_ALL_RX_BUF;
  irqmask = irqmask & otherInstance->SR;

  while (irqmask != 0UL)  /* if several bits are set, it loops to serve all of them */
  {
    bit_pos = 1UL << (ch_count & CHANNEL_INDEX_Msk);

    if ((irqmask & bit_pos) != 0U)
    {
      /* mask the channel occupied interrupt */
      currentInstance->MR |= bit_pos;
      if (hipcc->ChannelCallbackRx[ch_count] != NULL)
      {
        hipcc->ChannelCallbackRx[ch_count](hipcc, ch_count, IPCC_CHANNEL_DIR_RX);
      }
      irqmask = irqmask & ~(bit_pos);
    }
    ch_count++;
  }
}

/**
  * @brief Rx occupied callback
  * @param hipcc IPCC handle
  * @param ChannelIndex Channel number
  *          This parameter can be one of the following values:
  *            @arg IPCC_CHANNEL_1: IPCC Channel 1
  *            @arg IPCC_CHANNEL_2: IPCC Channel 2
  *            @arg IPCC_CHANNEL_3: IPCC Channel 3
  *            @arg IPCC_CHANNEL_4: IPCC Channel 4
  *            @arg IPCC_CHANNEL_5: IPCC Channel 5
  *            @arg IPCC_CHANNEL_6: IPCC Channel 6
  * @param ChannelDir Channel direction
  */
__weak void HAL_IPCC_RxCallback(IPCC_HandleTypeDef *hipcc, uint32_t ChannelIndex, IPCC_CHANNELDirTypeDef ChannelDir)
{
  /* Prevent unused argument(s) compilation warning */
  UNUSED(hipcc);
  UNUSED(ChannelIndex);
  UNUSED(ChannelDir);

  /* NOTE : This function should not be modified, when the callback is needed,
            the HAL_IPCC_RxCallback can be implemented in the user file
   */
}

/**
  * @brief Tx free callback
  * @param hipcc IPCC handle
  * @param ChannelIndex Channel number
  *          This parameter can be one of the following values:
  *            @arg IPCC_CHANNEL_1: IPCC Channel 1
  *            @arg IPCC_CHANNEL_2: IPCC Channel 2
  *            @arg IPCC_CHANNEL_3: IPCC Channel 3
  *            @arg IPCC_CHANNEL_4: IPCC Channel 4
  *            @arg IPCC_CHANNEL_5: IPCC Channel 5
  *            @arg IPCC_CHANNEL_6: IPCC Channel 6
  * @param ChannelDir Channel direction
  */
__weak void HAL_IPCC_TxCallback(IPCC_HandleTypeDef *hipcc, uint32_t ChannelIndex, IPCC_CHANNELDirTypeDef ChannelDir)
{
  /* Prevent unused argument(s) compilation warning */
  UNUSED(hipcc);
  UNUSED(ChannelIndex);
  UNUSED(ChannelDir);

  /* NOTE : This function should not be modified, when the callback is needed,
            the HAL_IPCC_TxCallback can be implemented in the user file
   */
}

/**
  * @}
  */

/** @addtogroup IPCC_Exported_Functions_Group3
 *  @brief   IPCC Peripheral State and Error functions
 *
@verbatim
  ==============================================================================
            ##### Peripheral State and Error functions #####
  ==============================================================================
    [..]
    This subsection permit to get in run-time the status of the peripheral
    and the data flow.

@endverbatim
  * @{
  */

/**
  * @brief Return the IPCC handle state.
  * @param  hipcc IPCC handle
  * @retval IPCC handle state
  */
HAL_IPCC_StateTypeDef HAL_IPCC_GetState(IPCC_HandleTypeDef const *const hipcc)
{
  return hipcc->State;
}

/**
  * @}
  */

/**
  * @}
  */

/** @addtogroup IPCC_Private_Functions
  * @{
  */

/**
  * @brief  Mask IPCC interrupts.
  * @param  ChannelIndex Channel number
  *          This parameter can be one of the following values:
  *            @arg IPCC_CHANNEL_1: IPCC Channel 1
  *            @arg IPCC_CHANNEL_2: IPCC Channel 2
  *            @arg IPCC_CHANNEL_3: IPCC Channel 3
  *            @arg IPCC_CHANNEL_4: IPCC Channel 4
  *            @arg IPCC_CHANNEL_5: IPCC Channel 5
  *            @arg IPCC_CHANNEL_6: IPCC Channel 6
  * @param  ChannelDir Channel direction
  */
void IPCC_MaskInterrupt(uint32_t ChannelIndex, IPCC_CHANNELDirTypeDef ChannelDir)
{
#if defined(CORE_CM0PLUS)
  IPCC_CommonTypeDef *currentInstance = IPCC_C2;
#else
  IPCC_CommonTypeDef *currentInstance = IPCC_C1;
#endif
  if (ChannelDir == IPCC_CHANNEL_DIR_TX)
  {
    /* Mask interrupt */
    currentInstance->MR |= (IPCC_MR_CH1FM_Msk << (ChannelIndex & CHANNEL_INDEX_Msk));
  }
  else
  {
    /* Mask interrupt */
    currentInstance->MR |= (IPCC_MR_CH1OM_Msk << (ChannelIndex & CHANNEL_INDEX_Msk));
  }
}
/**
  * @brief  Unmask IPCC interrupts.
  * @param  ChannelIndex Channel number
  *          This parameter can be one of the following values:
  *            @arg IPCC_CHANNEL_1: IPCC Channel 1
  *            @arg IPCC_CHANNEL_2: IPCC Channel 2
  *            @arg IPCC_CHANNEL_3: IPCC Channel 3
  *            @arg IPCC_CHANNEL_4: IPCC Channel 4
  *            @arg IPCC_CHANNEL_5: IPCC Channel 5
  *            @arg IPCC_CHANNEL_6: IPCC Channel 6
  * @param  ChannelDir Channel direction
  */
void IPCC_UnmaskInterrupt(uint32_t ChannelIndex, IPCC_CHANNELDirTypeDef ChannelDir)
{
#if defined(CORE_CM0PLUS)
  IPCC_CommonTypeDef *currentInstance = IPCC_C2;
#else
  IPCC_CommonTypeDef *currentInstance = IPCC_C1;
#endif
  if (ChannelDir == IPCC_CHANNEL_DIR_TX)
  {
    /* Unmask interrupt */
    currentInstance->MR &= ~(IPCC_MR_CH1FM_Msk << (ChannelIndex & CHANNEL_INDEX_Msk));
  }
  else
  {
    /* Unmask interrupt */
    currentInstance->MR &= ~(IPCC_MR_CH1OM_Msk << (ChannelIndex & CHANNEL_INDEX_Msk));
  }
}

/**
  * @brief Reset all callbacks of the handle to NULL.
  * @param  hipcc IPCC handle
  */
void IPCC_SetDefaultCallbacks(IPCC_HandleTypeDef *hipcc)
{
  uint32_t i;
  /* Set all callbacks to default */
  for (i = 0; i < IPCC_CHANNEL_NUMBER; i++)
  {
    hipcc->ChannelCallbackRx[i] = HAL_IPCC_RxCallback;
    hipcc->ChannelCallbackTx[i] = HAL_IPCC_TxCallback;
  }
}

/**
  * @brief Reset IPCC register to default value for the concerned instance.
  * @param  Instance pointer to register
  */
void IPCC_Reset_Register(IPCC_CommonTypeDef *Instance)
{
  /* Disable RX and TX interrupts */
  Instance->CR  = 0x00000000U;

  /* Mask RX and TX interrupts */
  Instance->MR  = (IPCC_ALL_TX_BUF | IPCC_ALL_RX_BUF);

  /* Clear RX status */
  Instance->SCR = IPCC_ALL_RX_BUF;
}

/**
  * @}
  */

#endif /* HAL_IPCC_MODULE_ENABLED */

/**
  * @}
  */
#endif /* IPCC */
/**
  * @}
  */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/