/*********************************************************************************************************************
 * Copyright (c) 2021, Infineon Technologies AG
 *
 * 
 * Distributed under the Boost Software License, Version 1.0.
 * 
 * 
 * Boost Software License - Version 1.0 - August 17th, 2003
 * 
 * Permission is hereby granted, free of charge, to any person or organization
 * obtaining a copy of the software and accompanying documentation covered by
 * this license (the "Software") to use, reproduce, display, distribute,
 * execute, and transmit the Software, and to prepare derivative works of the
 * Software, and to permit third-parties to whom the Software is furnished to
 * do so, all subject to the following:
 * 
 * The copyright notices in the Software and this entire statement, including
 * the above license grant, this restriction and the following disclaimer,
 * must be included in all copies of the Software, in whole or in part, and
 * all derivative works of the Software, unless such copies or derivative
 * works are solely in the form of machine-executable object code generated by
 * a source language processor.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
 * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
 * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 * 
 *********************************************************************************************************************/


/********************************************************************************************************
 * @file        TLE926x.h
 *
 * @brief       Main header declaration file for TLE926x SBC family device
 *
 * @version     V1.0.0
 * @date        
 * @author      Fedy Farhat
 * @author      Michael Schaffarczyk
 ********************************************************************************************************/
 
#ifndef TLE926x_H
#define TLE926x_H

/* ================================================================================ */
/* ============================   HEADER FILES     ================================ */
/* ================================================================================ */ 

#include "TLE926x_DEFINES.h"
#include "TLE926x_ISR.h"
#include "TLE926x_SPI.h"
#include <stdint.h>

#ifdef __cplusplus
extern "C" {
#endif

/* ================================================================================ */
/* ================================   MACROS     ================================== */
/* ================================================================================ */ 


/**
 * \def             SBC_WRITE_BIT
 * 
 * \brief           This bit has to be set in order to write to a register.
 */
#define SBC_WRITE_BIT   (0x80U)

/**
 * \def             SBC_READ_MASK
 * 
 * \brief           A mask to prevent the user from accidentally writing to a register.
 */
#define SBC_READ_MASK   (0x7FU)





/* ================================================================================ */
/* ===========================   Library Functions    ============================ */
/* ================================================================================ */ 



/**
 * @def SBC_ErrorCode

 * @brief  A structure for simple error readout.
 * 
 * @param       flippedBitsMask is greater than 0 if the value read from the register at SBC_Register differs from expectedValue.
 *                              !< Masks the bits that differ from the expected value. Is 0 if readout is as expected.
 * @param       SBC_Register is The register where an error occurred.
 * @param       expectedValue !<Expected readout of the register.
 */

typedef struct __SBC_ErrorCode {
    uint8_t SBC_Register;      
    uint8_t flippedBitsMask;   
    uint8_t expectedValue;      
} SBC_ErrorCode;



/**
 * \def     *SBC_Func_Callback
 * \brief   Typedef for interrupt callbacks.
 */
typedef void (*SBC_Func_Callback)(uint8_t callbackHandler);




/**
 * @def       sbc_read_reg

 * @brief   This method will proceed a readout of a register.
 * 
 * @param   sbc_register     Address of the register to be read out. See sbc_register_t for definitions
 * @retval  A 16 bit value will be returned.
 *          Bit[15:8] is the Status-Information-Field, Bit [7:0] is the read register-value.
 *          For furhter information of the Status-Information-Field see chapter 13.3 in the datasheet.
 */
uint16_t      sbc_read_reg(sbc_register_t sbc_register);


/**
 * @def      sbc_read_reg_field
 * 
 * @brief   This method will proceed a readout of a dedicated bitfield within a register
 * 
 * @param   sbc_register   Address of the register to be readout. See sbc_register_t for definitions
 * @param   bit_mask    Bit mask of the field to be readout. See sbc_bit_mask_t for definitions
 * 
 * 
 * @retval  A 8 bit value will be returned and includes the data of the bitfield to be read out 
 */
uint8_t       sbc_read_reg_field(sbc_register_t sbc_register, sbc_bit_mask_t bit_mask);


/**
 * @def     sbc_write_reg
 * @brief   Writes a whole byte to a register and verifies it.
 * 
 * @param   sbc_register    Address of the register to be manipulated. See sbc_register_t for definitions
 * @param   SBC_Val         Byte to write to SBC_Reg -- new value to be written in register
 * @param   *returnval      A 16 bit value will be returned.
 *                          Bit[15:8] is the Status-Information-Field, Bit [7:0] is the value of the manipulated register before write
 *                          For furhter information of the Status-Information-Field see chapter 16.3 in the datasheet.
 * 
 * @retval  See description of SBC_ErrorCode.
 */
SBC_ErrorCode sbc_write_reg(sbc_register_t sbc_register, uint8_t SBC_Val, uint16_t * returnval);


/**
 * @def     sbc_write_reg_field
 * @brief   This method can be used for manipulating a single bit-field in a control-register.
 *
 *          It will readout the old value of the registers, manipulate the desired bit-field and keep
 *          the other bit-configuration as it was.
 *          For usage examples have a look at the implementations of different API calls below.
 * 
 * @param   sbc_register    Address of the register to be manipulated. See sbc_register_t for definitions
 * @param   bit_mask        Bit mask of the field to manipulate. See sbc_bit_mask_t for definitions
 * @param   val             New value, which will be written to the bit-field. 
 * @param   *returnval      A 16 bit value will be returned.
 *                          Bit[15:8] is the Status-Information-Field, Bit [7:0] is the value of the manipulated register before write
 *                          For furhter information of the Status-Information-Field see chapter 16.3 in the datasheet.
 * 
 * 
 * @retval  SBC_ErrorCode   See description of SBC_ErrorCode.
 *
 */
SBC_ErrorCode sbc_write_reg_field(sbc_register_t sbc_register, sbc_bit_mask_t bit_mask, uint8_t val, uint16_t * returnval);


/**
 * @def            sbc_configure_watchdog
 * @brief          this function will configure the watchdog. 
 * 
 *                 it will manipulate the desired bit_fields by setting the new configuration that will be used later
                   by the function sbc_wd_trigger
 * @param  wd_type select the the type of watchdog functions, whci can be  timeout or  window
 *                 For further information see chapter 15.2 in datasheet
 * 
 * @param  wd_enable_after_busWake   depnding on user desires, watchdog can be enabled or disabled after a buswake    
 *                                   See sbc_wd_en_wk_bus_t for definition
 * @param  wd_timer       select watchdog timer period.
                           See sbc_wd_timer_t for definition and 15.3 in datasheet for further inforamtion. 


*  @retval  SBC_ErrorCode   See description of SBC_ErrorCode.             
 */
SBC_ErrorCode sbc_configure_watchdog(sbc_wd_win_t wd_type, sbc_wd_en_wk_bus_t wd_enable_after_busWake, sbc_wd_timer_t wd_timer);


/**
 * @def     sbc_wd_trigger
 * @brief   This method will trigger the watchdog.
 * 
 *          The function must be called periodically according to the configured watchdog-time.
 *          See sbc_configure_watchdog for further information of the configurations.
 * 
 * 
 * @retval  SBC_ErrorCode   See description of SBC_ErrorCode.
 */
SBC_ErrorCode sbc_wd_trigger(void);




/**
 * @brief   This method must be called one time at startup of the microcontroller.
 *
 *          This method will initialize all registers of the SBC with the configuration-data.
 *          After this, the SBC can be used as normal.
 * 
 * @retval  SBC_ErrorCode    See description of SBC_ErrorCode.
 */
SBC_ErrorCode sbc_init(void);




/* --------------------------------  ISR Functions -------------------------------- */

/**
 * @brief   This function can register a self-defined function to a specific interrupt-event of the SBC.
 * 
 *          Everytime the SBC_ISR() method is called and the associated status-bit is set, it will consider to
 *          proceed a callback to this function later.
 *          See all the possible ISR_Vectors in the TLE926x.h
 *
 * 
 * @param   vector_isr   Definition of the interrupt event. See all possible events in TLE926x.h
 * 
 * @param   *Callback_Handler Pointer to the function which will be called back.
 *          The function must accept a uint8_t as first argument.
 */
void          sbc_register_callback(uint32_t vector_isr, void (*Callback_Handler)(uint8_t callback_handler));


/**
 * @brief   Interrupt Service Routine for handling interrupts.
 * 
 *          This method must be called automatically everytime a rising-edge on the INTN pin is recognized.
 *          In case, the INTN pin is not connected, this method can also be called periodically by the user during runtime.
 *          The ISR will proceed a readout of all registered interrupts. If a status-bit of a registered interrupt is set,
 *          it will initiate a callback to the registered function and give the registered function the status-register value
 *          as a parameter.
 * 
 * @retval  SBC_ErrorCode   See description of SBC_ErrorCode.
 */
SBC_ErrorCode SBC_ISR(void);


/* --------------------------------  API Calls  ----------------------------------- */

/**
 * @def     sbc_sys_stat_read
 * @brief   Reads System Status Control. See page 168 in datasheet.
 * 
 * @retval   8 bit are read from register SBC_SYS_STATUS_CTRL
 */
uint8_t       sbc_sys_stat_read(void);





/**
 * @def     sbc_sys_stat_write
 * @brief   Writes System Status Control. See page 168 in datasheet.
 * 
 * @retval  SBC_ErrorCode   See description of SBC_ErrorCode.
 */
SBC_ErrorCode sbc_sys_stat_write(uint8_t status); 



/**
 * @def     sbc_hsx_config
 * @brief   select the desired high side and set its configuration  in register SBC_HS_CTRL_1 or SBC_HS_CTRL_2.
 *          This function can enable or disable hsx, and set each hsx to be controlled either by PWMx or TIMERx.
 * 
 * @param   hsx  select the desired highside. See sbc_hsx_t for definition
 * 
 * @param   hs_config   set the configuration of each HSx. See  sbc_hs_config_t for definition
 * 
 * @retval  SBC_ErrorCode   See description of SBC_ErrorCode.
 */
SBC_ErrorCode sbc_hsx_config(sbc_hsx_t hsx, sbc_hs_config_t hs_config);



/**
 * @def     sbc_cyclicsense
 * @brief   This function can assign HSx to a Wake input. A TIMERx will control the HSx with a specific ontime an period.
 *          See 5.2 for morfe information
 * 
 * @param   timer  select the timer, which will control the HSx. See sbc_timer_t for definition
 * @param   timerPeriod   configure the timer period. See  sbc_timer_per_t for definition
 * @param   timerOnTime   set the On_duration of timer. See sbc_timer_on_t for defintion.
 * @param   hsX           select the desired high side. See sbc_hsx_t for definition
 * @param   wk            select the wake input for the chosen HSx. See sbc_wk_t for defintion. 
 * @param   pupdConfig    select the switching type of the wake input. See sbc_wk_pupd_t for definition
 * 
 * 
 * @retval  SBC_ErrorCode   See description of SBC_ErrorCode.
 */
SBC_ErrorCode sbc_cyclicsense (sbc_timer_t timer, sbc_timer_per_t timerPeriod, sbc_timer_on_t timerOnTime, sbc_hsx_t hsX, sbc_wk_t wk, sbc_wk_pupd_t pupdConfig);



/**
 * @def     sbc_cyclicwake
 * @brief   This function set a timer for a periodic wake. 
 *          See 5.2 for morfe information
 * 
 * @param   timer  select the timer that will enable the wake signal.
 * @param   timer_period   configure the timer period. See  sbc_timer_per_t for definition
 * @param   timer_on_time   set the On_duration of timer. See sbc_timer_on_t for defintion.
 
 * 
 * @retval  SBC_ErrorCode   See description of SBC_ErrorCode.
 */
SBC_ErrorCode sbc_cyclicwake(sbc_timer_t timer, sbc_timer_per_t timer_period, sbc_timer_on_t timer_on_time);




SBC_ErrorCode sbc_can_swk(uint_least32_t id, uint_least32_t id_mask, uint64_t data, sbc_mode_t low_power_mode); // TODO not implemented



/**
 * @def     sbc_mode_normal
 * @brief   Enters SBC normal mode
 * 
 * @retval  SBC_ErrorCode   See description of SBC_ErrorCode.
 */
SBC_ErrorCode sbc_mode_normal(void);



/**
 * @def       sbc_mode_stop
 * @brief   Enters SBC stop mode
 * 
 * @retval  SBC_ErrorCode   See description of SBC_ErrorCode.
 */
SBC_ErrorCode sbc_mode_stop(void);




/**
 * @def     sbc_mode_sleep
 * 
 * @brief   Clears all wake status registers and enter SBC sleep mode. Depending on configuration also the selective-wake feature will be initialized
 *          before entering sleep mode. In case, the SWK option is enabled and the internal CAN protocol handler is not in sync when calling this function,
 *          the sleep mode will be not entered.
 * 
 * @retval  SBC_ErrorCode   See description of SBC_ErrorCode.
 */
SBC_ErrorCode sbc_mode_sleep(void);




/**
 * @def     sbc_can_mode
 * 
 * @brief   This function enters the selected CAN Mode. See chapter 5.4.4 for further information
 * 
 * @param   CANmode the CAN mode to be entered. See  sbc_can_t for definition
 * 
 * 
 * @retval  SBC_ErrorCode   See description of SBC_ErrorCode.
 */
SBC_ErrorCode sbc_can_mode(sbc_can_t CANmode ) ;



/**
 * @def     sbc_lin_mode
 * 
 * @brief   enable or disable the selected LIN module. 
 *          This function assign the desired LIN mode to the selected LIN module.
 *           See chapter 5.4.4 for further information
 * 
 * 
 * @param   lin_module which LIN module to be selected. See sbc_lin_module_t for definition.
 * @param   lin_mode   the LIN mode to be entered. See  sbc_lin_mode_t for definition.
 * 
 * 
 * @retval  SBC_ErrorCode   See description of SBC_ErrorCode.
 */
SBC_ErrorCode sbc_lin_mode(sbc_lin_module_t lin_module, sbc_lin_mode_t lin_mode);


/**
 * @def     sbc_mode_stop_without_watchdog
 * 
 * @brief  entering stop mode without Watchdog. 
 *         This function disables Watchdog befor the Sbc enters in Stop mode. 
 *         For further information See 15.2.4.
 * 
 * 
 * @retval  SBC_ErrorCode   See description of SBC_ErrorCode.
 */
SBC_ErrorCode sbc_mode_stop_without_watchdog(void);



/**
 * @def     sbc_configure_pwm
 * 
 * @brief  select the desired PWM and set its frequency and dutycycle. For further information see 9.2
 * 
 * @param pwm  selcet the desired PWMx. See sbc_pwm_t for defintion.
 * @param frequency  set the frequency of the PWM. See sbc_pwm_freq_t  for defintion.
 * @param duty_cycle  set the duty cycle of the PWM.
 * 
 *        
 * @retval  SBC_ErrorCode   See description of SBC_ErrorCode.
 */
SBC_ErrorCode sbc_configure_pwm(sbc_pwm_t pwm, sbc_pwm_freq_t frequency, uint8_t duty_cycle);



/**
 * @def     sbc_configure_pwm_percentage
 * 
 * @brief  select the desired PWM and set its frequency and dutycycle. The dutycycle is given here in percentage For further information see 9.2
 * 
 * @param pwm  selcet the desired PWMx. See sbc_pwm_t for defintion.
 * @param frequency  set the frequency of the PWM. See sbc_pwm_freq_t  for defintion.
 * @param duty_cycle  set the duty cycle of the PWM. The duty cycle is entred in percentage
 * 
 *        
 * @retval  SBC_ErrorCode   See description of SBC_ErrorCode.
 */
SBC_ErrorCode sbc_configure_pwm_percentage(sbc_pwm_t pwm, sbc_pwm_freq_t frequency, double duty_cycle);


/**
 * @def     sbc_switch_vcc2
 * 
 * @brief   This function enables or disables VCC2. For further information See 7.1
 * 
 * @param vcc2_value   is the value that should be entered to enable or disable VCC2.
 *                     See sbc_vcc2_on_t for information
 *        
 * @retval  SBC_ErrorCode   See description of SBC_ErrorCode.
 */
SBC_ErrorCode sbc_switch_vcc2(sbc_vcc2_on_t vcc2_value);



/**
 * @def     sbc_switch_vcc3
 * 
 * @brief   This function enables or disables VCC3. For further information See 8.1
 * 
 * @param vcc3_value   is the value that should be entered to enable or disable VCC3.
 *                     See sbc_vcc3_on_t for information
 * 
 *        
 * @retval  SBC_ErrorCode   See description of SBC_ErrorCode.
 */
SBC_ErrorCode sbc_switch_vcc3(sbc_vcc3_on_t vcc3_value);



/**
 *  @def sbc_configure_gpio
 *  @brief  select the GPIOx to be manipulated and set the desired configuration.
 *          For further information see page 166.
 * 
 * @param gpio  select the GPIO. See sbc_gpiox_t for definition
 * @param gpio_config  set the configuration for the selected GPIO. See sbc_gpio_t for definition
 * 
 * @return SBC_ErrorCode  See description of SBC_ErrorCode.
 */
SBC_ErrorCode sbc_configure_gpio(sbc_gpiox_t gpio, sbc_gpio_t gpio_config);



/**
 * @def sbc_fo_x
 * 
 * @brief  activate or deactivate the Failure outut bit. See 14.1 for further information
 * 
 * @param on  set the configuration to enable or disable FO. 0 = off, 1 = on
 * 
 * @return SBC_ErrorCode  See description of SBC_ErrorCode.
 */
SBC_ErrorCode sbc_fo_x(uint8_t on);

#ifdef __cplusplus
}
#endif

#endif
