/*
 * Copyright 2018 NXP
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * o Redistributions of source code must retain the above copyright notice, this list
 *   of conditions and the following disclaimer.
 *
 * o Redistributions in binary form must reproduce the above copyright notice, this
 *   list of conditions and the following disclaimer in the documentation and/or
 *   other materials provided with the distribution.
 *
 * o Neither the name of the copyright holder nor the names of its
 *   contributors may be used to endorse or promote products derived from this
 *   software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/*****************************************************************************
*
* \file nxp_sja1124.h
*
* \author NXP
*
* \brief Functions for the SJA1124
*
*****************************************************************************/

#ifndef NXP_SJA1124_H
#define NXP_SJA1124_H

/*****************************************************************************
* INCLUDES
*****************************************************************************/

#include <SJA1124_Drv/nxp_sja1124_defines.h>
#include <SJA1124_Drv/nxp_sja1124_registers.h>

/*****************************************************************************
* DEFINES
*****************************************************************************/

/*****************************************************************************
* TYPE DEFINITIONS
*****************************************************************************/

/*
* \brief Device operational mode.
* \details The device is put to sleep (low power) mode by SPI command and could
*          woken up remotely via LIN bus or by SPI.
*/
typedef enum
{
  SJA1124_MODE_NORMAL = 0u, /* Normal device mode. */
  SJA1124_MODE_SLEEP = 1u   /* Low power device mode. */
} SJA1124_OperationalModeType;

/*
* \brief Device wake-up reason.
* \details This specifies if the device was woken up remotely via LIN bus
*          or by SPI command.
*/
typedef enum
{
  SJA1124_WAKEUP_BUS = 0u, /* The LIN bus caused the wake up. */
  SJA1124_WAKEUP_SPI = 1u  /* The device was woken up by request to NORMAL mode. */
} SJA1124_WakeupReasonType;

/*
* \brief Wake-up mode.
* \details Enable/disable interrupts when LIN bus wake-up occurs
*          or clear wake-up status.
*/
typedef enum
{
  SJA1124_WUMODE_ENABLE = 0u,  /* Enable wake-up interrupts of the device. */
  SJA1124_WUMODE_DISABLE = 1u, /* Disable wake-up interrupts of the device. */
  SJA1124_WUMODE_CLEAR = 2u    /* Clear wake-up status. */
} SJA1124_WakeupModeType;

/*
* \brief Chip-select configuration.
* \details This structure specifies the port and number of pin used as SPI chip-select.
           Values of members depend on definition of GPIO handling function GPIO_WritePin.
*/
typedef struct
{
  uint8_t pinPort;
  uint8_t pinNumber;
} SJA1124_SpiChipSelectType;

/*
* \brief Device configuration.
* \details Configuration registers:
*          MODE:    | RST   | reserved                                              | LPMODE |
*          PLLCFG:  | reserved                        | PLLMULT                              |
*          INT1EN:  | reserved                        | L4WUIE  | L3WUIE   | L2WUIE | L1WUIE |
*          INT2EN:  | reserved      | OTWIE | PLLOLIE | PLLILIE | PLLIFFIE | SPIEIE | res.   |
*          INT3EN:  | L4EIE | L3EIE | L2EIE | L1EIE   | L4SIE   | L3SIE    | L2SIE  | L1SIE  |
*/
typedef struct
{
  uint8_t modeRegister;   /* Mode register.*/
  uint8_t pllCfgRegister; /* PLL configuration register. */
  uint8_t int1EnRegister; /* Interrupt 1 enable register. */
  uint8_t int2EnRegister; /* Interrupt 2 enable register. */
  uint8_t int3EnRegister; /* Interrupt 3 enable register. */
} SJA1124_DeviceConfigType;

/*
* \brief Driver configuration.
* \details Specifies the SPI device used, chip-select pins and configuration
*          of all (up to 4) devices connected to shared SPI interface.
*/
typedef struct
{
  uint8_t spiDevice;                                               /* Instance of SPI device. */
  SJA1124_SpiChipSelectType spiChipSelect[SJA1124_NUM_OF_DEVICES]; /* SCSN pin configurations. */
  SJA1124_DeviceConfigType deviceConfig[SJA1124_NUM_OF_DEVICES];   /* Device configurations. */
} SJA1124_ConfigType;

/*
* \brief Device status information.
* \details Status registers (read only):
*          INT1:    | INITI | reserved               | L4WUI  | L3WUI   | L2WUI | L1WUI |
*          INT2:    | reserved     | OTWI | PLLOLI   | PLLILI | PLLIFFI | SPIEI | LPRFI |
*          INT3:    | L4EI  | L3EI | L2EI | L1EI     | L4SI   | L3SI    | L2SI  | L1SI  |
*          STATUS:  | reserved     | OTW  | reserved | PLLIL  | PLLIFF  | reserved      |
*/
typedef struct
{
  uint8_t int1Register;   /* Interrupt 1 register. */
  uint8_t int2Register;   /* Interrupt 2 register. */
  uint8_t int3Register;   /* Interrupt 3 register. */
  uint8_t statusRegister; /* Status register. */
} SJA1124_StatusType;

/*****************************************************************************
* FUNCTIONS
*****************************************************************************/

/*
* \brief The function Init initializes configuration registers of the device.
*
* \param[in] uint8_t device             - Device number (0..3 in case of 4 devices).
* \param[in] SJA1124_ConfigType* config - Pointer to SJA1124 configuration set.
* \return Std_ReturnType                - E_OK: Send command has been accepted.
*                                         E_NOT_OK: Send command has not been accepted.
*/
Std_ReturnType SJA1124_Init(uint8_t device, const SJA1124_ConfigType* config);

/*
* \brief The function RWRegister creates command to send using SPI driver send/receive function.
*        1st byte (address)   2nd byte (setting)    3rd byte etc.
*        Addr7..0             RW 0 0 0 DLC3..0      Data
*
* \param[in] uint8_t device       - Device number (0..3 in case of 4 devices).
* \param[in] bool rwRead          - true: Read register.
*                                   false: Write register.
* \param[in] uint8_t regAddress   - Number of first register to write.
* \param[in] uint8_t numOfBytes   - Number of data bytes to read or write.
* \param[in] uint8_t* sendDataPtr - Pointer to buffer with data to send.
*                                   If this pointer is NULL, data bytes with 0x00 value are sent.
* \param[out] uint8_t* rcvDataPtr - Pointer to buffer where received data are stored.
*                                   If this pointer is NULL, received data are ignored.
* \return Std_ReturnType          - E_OK: Send command has been accepted.
*                                   E_NOT_OK: Send command has not been accepted.
*/
Std_ReturnType SJA1124_RWRegister(uint8_t device, bool rwRead, uint8_t regAddress, uint8_t numOfBytes, uint8_t* sendDataPtr, uint8_t* rcvDataPtr);

/*
* \brief The function SetOperationalMode sets operational mode of the device to normal or sleep
*        (low power) mode. In low power mode all LIN master controllers and the PLL are disabled,
*        the power consumption is reduced, but the device can still detect remote wake-up via LIN
*        or wake-up by SPI command.
*
* \param[in] uint8_t device                     - Device number (0..3 in case of 4 devices).
* \param[in] SJA1124_OperationalModeType opMode - Operational mode of the device, use
*                                                 SJA1124_MODE_NORMAL for normal device mode
*                                                 and SJA1124_MODE_SLEEP for low power mode.
* \return Std_ReturnType                        - E_OK: Send command has been accepted.
*                                                 E_NOT_OK: Send command has not been accepted.
*/
Std_ReturnType SJA1124_SetOperationalMode(uint8_t device, SJA1124_OperationalModeType opMode);

/*
* \brief The function GetOperationalMode gets last set operational mode.
*
* \param[in] uint8_t device                       - Device number (0..3 in case of 4 devices).
* \param[out] SJA1124_OperationalModeType* opMode - Operational mode of the device, value is
*                                                   SJA1124_MODE_NORMAL for normal device mode
*                                                   and SJA1124_MODE_SLEEP for low power mode.
* \return Std_ReturnType                          - E_OK: Send command has been accepted.
*                                                   E_NOT_OK: Send command has not been accepted.
*/
Std_ReturnType SJA1124_GetOperationalMode(uint8_t device, SJA1124_OperationalModeType* opMode);

/*
* \brief The function SetWakeupMode enables/disables interrupts when wake-up is detected.
*        It can also be used to clear wake-up status bits in INT1 register.
*
* \param[in] uint8_t device                - Device number (0..3 in case of 4 devices).
* \param[in] SJA1124_WakeupModeType wuMode - Enable or disable all wake-up interrupts
*                                            (SJA1124_WAKEUP_ENABLE, SJA1124_WAKEUP_DISABLE)
*                                            or clear wake-up interrupt register in case of
*                                            an interrupt occurred (SJA1124_WAKEUP_CLEAR).
* \return Std_ReturnType                   - E_OK: Send command has been accepted.
*                                            E_NOT_OK: Send command has not been accepted.
*/
Std_ReturnType SJA1124_SetWakeupMode(uint8_t device, SJA1124_WakeupModeType wuMode);

/*
* \brief The function GetWakeupReason reads if the device was woken up remotely by another device
*        on the LIN bus. The device is woken up either remotely via LIN bus or by 1-0 transition
*        on SCSN pin. Use SetWakeupMode function to enable interrupts when wake-up is detected.
*
* \param[in] uint8_t device                      - Device number (0..3 in case of 4 devices).
* \param[out] SJA1124_WakeupReasonType* wuReason - Wake-up reason of the device, either
*                                                  SJA1124_WAKEUP_BUS when it's woken up by other
*                                                  device on the bus, or SJA1124_WAKEUP_SPI when
*                                                  it's woken up by SPI command.
* \return Std_ReturnType                         - E_OK: Send command has been accepted.
*                                                  E_NOT_OK: Send command has not been accepted.
*/
Std_ReturnType SJA1124_GetWakeupReason(uint8_t device, SJA1124_WakeupReasonType* wuReason);

/*
* \brief The function GetStatus reads the status registers of the device.
*
* \param[in] uint8_t device              - Device number (0..3 in case of 4 devices).
* \param[out] SJA1124_StatusType* status - Pointer to structure where status data are stored.
* \return Std_ReturnType                 - E_OK: Send command has been accepted.
*                                          E_NOT_OK: Send command has not been accepted.
*/
Std_ReturnType SJA1124_GetStatus(uint8_t device, SJA1124_StatusType* status);

#endif  /* NXP_SJA1124_H */
