/*!
 * @file        bmp561_hsc.c
 *
 * @brief       This file provides all the HSC firmware functions
 *
 * @version     V1.0.0
 *
 * @date        2025-01-01
 *
 * @attention
 *
 *  Copyright (C) 2025 Geehy Semiconductor
 *
 *  You may not use this file except in compliance with the
 *  GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
 *
 *  The program is only for reference, which is distributed in the hope
 *  that it will be useful and instructional for customers to develop
 *  their software. Unless required by applicable law or agreed to in
 *  writing, the program is distributed on an "AS IS" BASIS, WITHOUT
 *  ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
 *  and limitations under the License.
 */

#include "bmp561_hsc.h"
#include "bmp561_sysctrl.h"

/** @addtogroup Peripherals_Library Standard Peripheral Library
  @{
*/

/** @addtogroup HSC_Driver HSC Driver
  @{
*/

/** @addtogroup HSC_Functions Functions
  @{
*/

/*!
 * @brief     Resets the HSC peripheral registers to their default reset values.
 *
 * @param     None
 *
 * @retval    None
 *
 */
void HSC_Reset(void)
{
    SYSCTRL_Unlock();
    SYSCTRL_EnableAPBPeriphReset(SYSCTRL_APB_HSC);
    SYSCTRL_DisableAPBPeriphReset(SYSCTRL_APB_HSC);
    SYSCTRL_Lock();
}

/*!
 * @brief     Enables HSC.
 *
 * @param     None
 *
 * @retval    None
 *
 */
void HSC_Enable(void)
{
    HSC->CTRL_B.EN = BIT_SET;
}

/*!
 * @brief     Disables HSC.
 *
 * @param     None
 *
 * @retval    None
 *
 */
void HSC_Disable(void)
{
    HSC->CTRL_B.EN = BIT_RESET;
}

/*!
 * @brief     Start HSC transmit or restart.
 *
 * @param     None
 *
 * @retval    None
 *
 */
void HSC_Start(void)
{
    HSC->CTRL_B.START = BIT_SET;
}

/*!
 * @brief     Enables HSC break signal.
 *
 * @param     None
 *
 * @retval    None
 *
 * @note      Send break when CTRL_B.BRKEN = 0, do not send break when CTRL_B.BRKEN = 1 .
 *
 */
void HSC_EnableBreak(void)
{
    HSC->CTRL_B.BRKEN = BIT_RESET;
}

/*!
 * @brief     Disables HSC break signal.
 *
 * @param     None
 *
 * @retval    None
 *
 * @note      Send break when CTRL_B.BRKEN = 0, do not send break when CTRL_B.BRKEN = 1 .
 *
 */
void HSC_DisableBreak(void)
{
    HSC->CTRL_B.BRKEN = BIT_SET;
}

/*!
 * @brief     Configures HSC work mode.
 *
 * @param     mode: specifies HSC work mode.
 *                  This parameter can be one of the following values:
 *                  @arg HSC_MODE_SLAVE : Slave mode
 *                  @arg HSC_MODE_MASTER: Master mode
 *
 * @retval    None
 *
 */
void HSC_ConfigMode(HSC_MODE_T mode)
{
    HSC->CTRL_B.MODE = mode;
}

/*!
 * @brief     Configures HSC slave mode T(HW1) period.
 *
 * @param     threshold: specifies HSC slave mode low level threshold value.
 *                       This parameter can be one of the following values:
 *                       @arg HSC_THRETIME_1US  : 1us ~ 50us
 *                       @arg HSC_THRETIME_17US : 17us ~ 50us
 *                       @arg HSC_THRETIME_32US : 32us ~ 50us
 *                       @arg HSC_THRETIME_0P5US: 0.5us ~ 50us
 *
 * @retval    None
 *
 */
void HSC_ConfigThreshold(HSC_THRETIME_T threshold)
{
    HSC->CTRL_B.THW1 = threshold;
}

/*!
 * @brief     Configures HSC protocol data bits.
 *
 * @param     bits: specifies HSC protocol data bits.
 *                  This parameter can be one of the following values:
 *                  @arg HSC_PROTOCOL_8BIT : 8bit data
 *                  @arg HSC_PROTOCOL_16BIT: 16bit data
 *
 * @retval    None
 *
 */
void HSC_ConfigProtocolDataBits(HSC_PROTOCOL_T bits)
{
    HSC->CTRL_B.BITS = bits;
}

/*!
 * @brief     Configures HSC peripheral connect system clock.
 *
 * @param     sysClk: specifies HSC system clock.
 *                    This parameter can be one of the following values:
 *                    @arg HSC_SYSCLK_4MHZ : 4MHz system clock
 *                    @arg HSC_SYSCLK_2MHZ : 2MHz system clock
 *                    @arg HSC_SYSCLK_8MHZ : 8MHz system clock
 *                    @arg HSC_SYSCLK_16MHZ: 16MHz system clock
 *                    @arg HSC_SYSCLK_1MHZ : 1MHz system clock
 *
 * @retval    None
 *
 */
void HSC_ConfigSystemClock(HSC_SYSCLK_T sysClk)
{
    HSC->CTRL_B.CLKSEL = sysClk;
}

/*!
 * @brief     Enables HSC timeout.
 *
 * @param     None
 *
 * @retval    None
 *
 */
void HSC_EnableTimeOut(void)
{
    HSC->CTRL_B.TOEN = BIT_SET;
}

/*!
 * @brief     Disables HSC timeout.
 *
 * @param     None
 *
 * @retval    None
 *
 */
void HSC_DisableTimeOut(void)
{
    HSC->CTRL_B.TOEN = BIT_RESET;
}

/*!
 * @brief     Configures HSC address register.
 *
 * @param     Addr: 7 bit address value + 1 bit Read/write bit.
 *
 * @retval    None
 *
 */
void HSC_ConfigAddress(uint8_t Addr)
{
    HSC->HCMD = Addr;
}

/*!
 * @brief     Configures HSC read or write operation.
 *
 * @param     RWbit: specifies the HSC master mode read("0") or write("1").
 *                   This parameter can be 0x00(read) or 0x01(write).
 *
 * @retval    None
 *
 */
void HSC_ConfigReadWriteBit(uint8_t RWbit)
{
    HSC->HCMD_B.MRW = RWbit;
}

/*!
 * @brief     Write one data to Data register.
 *
 * @param     value: write value.
 *
 * @retval    None
 *
 */
void HSC_WriteData(uint16_t value)
{
    HSC->HDA = value;
}

/*!
 * @brief     Get one data from Data register.
 *
 * @param     None
 *
 * @retval    read data.
 *
 */
uint16_t HSC_ReadData(void)
{
    return (uint16_t)HSC->HDA;
}

/*!
 * @brief     Enables HSC interrupt.
 *
 * @param     interrupt: specifies the HSC interrupt.
 *                       This parameter can be one of the following values:
 *                       @arg HSC_INT_IBRK : Break finished interrupt
 *                       @arg HSC_INT_ICMD : Read/write command finished interrupt
 *                       @arg HSC_INT_IDATA: Send/Receive data finished interrupt
 *                       @arg HSC_INT_FR   : Frame error interrupt
 *                       @arg HSC_INT_TO   : Timeout interrupt
 *
 * @retval    None
 *
 */
void HSC_EnableInterrupt(HSC_INT_T interrupt)
{
    HSC->IEN |= interrupt;
}

/*!
 * @brief     Disables HSC interrupt.
 *
 * @param     interrupt: specifies the HSC interrupt.
 *                       This parameter can be one of the following values:
 *                       @arg HSC_INT_IBRK : Break completed interrupt
 *                       @arg HSC_INT_ICMD : Read/write command completed interrupt
 *                       @arg HSC_INT_IDATA: Send/Receive data completed interrupt
 *                       @arg HSC_INT_FR   : Frame error interrupt
 *                       @arg HSC_INT_TO   : Timeout interrupt
 *
 * @retval    None
 *
 */
void HSC_DisableInterrupt(HSC_INT_T interrupt)
{
    HSC->IEN &= ~interrupt;
}

/*!
 * @brief     Reads the specified HSC flag.
 *
 * @param     flag: specifies the HSC flag.
 *                  This parameter can be one of the following values:
 *                  @arg HSC_FLAG_BRK : Break flag
 *                  @arg HSC_FLAG_CMD : Read/write command flag
 *                  @arg HSC_FLAG_DATA: Send/Receive data flag
 *                  @arg HSC_FLAG_FR  : Frame error flag
 *                  @arg HSC_FLAG_TO  : Timeout flag
 *                  @arg HSC_FLAG_BUSY: Busy flag
 *
 * @retval    The new state of flag(SET or RESET).
 *
 */
uint8_t HSC_ReadFlag(HSC_FLAG_T flag)
{
    uint8_t status = RESET;

    if((HSC->SR & flag) != (uint32_t)RESET)
    {
        status = SET;
    }
    else
    {
        status = RESET;
    }
    return status;
}

/*!
 * @brief     Clears the specified HSC flag.
 *
 * @param     flag: specifies the HSC flag.
 *                  This parameter can be one of the following values:
 *                  @arg HSC_FLAG_BRK : Break flag
 *                  @arg HSC_FLAG_CMD : Read/write command flag
 *                  @arg HSC_FLAG_DATA: Send/Receive data flag
 *                  @arg HSC_FLAG_FR  : Frame error flag
 *                  @arg HSC_FLAG_TO  : Timeout flag
 *
 * @retval    None
 *
 */
void HSC_ClearFlag(HSC_FLAG_T flag)
{
    HSC->SRC |= flag;
}

/*!
 * @brief     Configures the HSC peripheral according to the specified parameters in the hscConfig.
 *
 * @param     hscConfig: pointer to a HSC_Config_T structure.
 *
 * @retval    None
 *
 * @note      Send break when CTRL_B.BRKEN = 0(hscConfig->brken = ENABLE),
 *            do not send break when CTRL_B.BRKEN = 1(hscConfig->brken = DISABLE).
 *
 */
void HSC_Config(HSC_Config_T* hscConfig)
{
    uint8_t reg = 0x00;

    if(hscConfig->brkEn == ENABLE)
    {
        reg = DISABLE;
    }
    else
    {
        reg = ENABLE;
    }

    HSC->CTRL = (uint32_t)((hscConfig->timeout << 0x0A) | \
                           (hscConfig->clock << 0x07) | \
                           (reg << 0x06) | \
                           (hscConfig->bits << 0x05)  | \
                           (hscConfig->threshold << 0x03)  | \
                           (hscConfig->mode << 0x02)  | \
                           (hscConfig->enable));

    HSC->HCMD = hscConfig->addr;
}

/*!
 * @brief     Fills each HSC_Config_T member with its default value.
 *
 * @param     hscConfig: pointer to a HSC_Config_T structure which will be initialized.
 *
 * @retval    None
 *
 */
void HSC_ConfigStructInit(HSC_Config_T* hscConfig)
{
    hscConfig->enable = DISABLE;
    hscConfig->mode = HSC_MODE_SLAVE;
    hscConfig->threshold = HSC_THRETIME_1US;
    hscConfig->bits = HSC_PROTOCOL_8BIT;
    hscConfig->brkEn = ENABLE;
    hscConfig->clock = HSC_SYSCLK_4MHZ;
    hscConfig->timeout = DISABLE;
    hscConfig->addr = 0;
}

/**@} end of group HSC_Functions*/
/**@} end of group HSC_Driver*/
/**@} end of group Peripherals_Library*/
