/*
 *  Copyright 2020-2022 Yuntu Microelectronics co.,ltd
 *  All rights reserved.
 * 
 *  YUNTU Confidential. This software is owned or controlled by YUNTU and may only be
 *  used strictly in accordance with the applicable license terms. By expressly
 *  accepting such terms or by downloading, installing, activating and/or otherwise
 *  using the software, you are agreeing that you have read, and that you agree to
 *  comply with and are bound by, such license terms. If you do not agree to be
 *  bound by the applicable license terms, then you may not retain, install,
 *  activate or otherwise use the software. The production use license in
 *  Section 2.3 is expressly granted for this software.
 * 
 * @file osire_driver.h
 * @brief 
 * 
 */

#ifndef _OSIRE_DRIVER_H
#define _OSIRE_DRIVER_H
#include <stdint.h>
#include <stdbool.h>

/*******************************************************************************
 * Definition
 ******************************************************************************/
#define OSIRE_SPI_0     (0U) 
#define OSIRE_SPI_1     (1U) 
#define OSIRE_SPI_2     (2U) 
#define OSIRE_SPI_3     (3U) 
#define OSIRE_SPI_4     (4U) 
#define OSIRE_SPI_5     (5U) 

/*******************************************************************************
 * Union
 ******************************************************************************/
/*! @brief PWM data type
 * Implements : OSIRE_PwmDataType_Class
 */
typedef union
{
    uint8_t pwmData[6]; /*!< PWM data buffer */
    struct
    {
        uint16_t blue_pwm :15;  /*!< blue PWM value */
        uint16_t blue_curr :1;  /*!< day or night mode */
        uint16_t green_pwm :15; /*!< green PWM value */
        uint16_t green_curr :1; /*!< day or night mode */
        uint16_t red_pwm :15;   /*!< red PWM value */
        uint16_t red_curr :1;   /*!< day or night mode */
    } bit;
} OSIRE_PwmDataType;

/*! @brief Frame type
 * Implements : OSIRE_FrameType_Class
 */
typedef union
{
    uint8_t buf[12]; /*!< Frame data buffer */
    struct
    {
        uint8_t  data[8];     /*!< Exact data include crc */
        uint32_t reserve :8;  /*!< May ignore */
        uint32_t command :7;  /*!< OSP or OSP_OSIRE command */
        uint32_t psi :3;      /*!< payload in bytes */
        uint32_t address :10; /*!< device address */
        uint32_t preamble :4; /*!< OSP_PROTOCOL_PREAMBLE 0x0A */
    } bit;
} OSIRE_FrameType;

/*******************************************************************************
 * Enumerate
 ******************************************************************************/
/*! @brief Return type
 * Implements : OSIRE_ReturnType_Class
 */
typedef enum
{
    OSIRE_OK = 0x00, /**< no error */
    OSIRE_ERROR_STRIP,  /**< invalid strip*/
    OSIRE_ERROR_ADDRESS, /**< invalid device address*/
    OSIRE_ERROR_INITIALIZATION, /**< error while initializing */
    OSIRE_ERROR_CRC, /**< incorrect CRC of OSP command */
    OSIRE_ERROR_SPI /**< SPI interface error */
} OSIRE_ReturnType;

/*! @brief Communication Event type
 * Implements : OSIRE_CommEventType_Class
 */
typedef enum
{
    TRANSMISSION_COMPLETE = 0x01U,      /*!< Downstream completed event */
    RECEPTION_COMPLETE = 0x02U,         /*!< Upstream completed event */
    RECEPTION_TIMEOUT = 0x03U,          /*!< Upstream timeout event */
    CRC_ERROR = 0x04U,                  /*!< Upstream CRC error */
    CHAINLENGTH_ERROR = 0x05U,          /*!< Length of chain out of range */
    IDLE = 0x06U                        /*!< Idle */
} OSIRE_CommEventType;

/*! @brief Transfer type
 * Implements : OSIRE_TransferType_Class
 */
typedef enum
{
    OSIRE_USING_DMA = 0x00U,           /*!< OSIRE uses DMA to transfer */
    OSIRE_USING_INTERRUPTS = 0x01U,    /*!< OSIRE uses interrupt to transfer */
}OSIRE_TransferType;

/*! @brief Interface selection
 * Implements : OSIRE_InterfaceType_Class
 */
typedef enum
{
    OSIRE_INTERFACE_SPI    = 0x01U     /*!< Interface of OSIRE is SPI */
}OSIRE_InterfaceType;

/*******************************************************************************
 * Structure
 ******************************************************************************/
/*! @brief Pin Mux for a pin
 * Implements : OSIRE_PinMuxConfigType_Class
 */
typedef struct
{
    uint32_t * pctrlPtr;                /*!< Memory base of PCTRL */
    uint8_t pinMux;                     /*!< Pin mux selection */
}OSIRE_PinMuxConfigType;

/*! @brief Pin config for a LED strip
 * Implements : OSIRE_PinConfigType_Class
 */
typedef struct
{
    uint8_t stripNr;                     /*!< Strip number */
    uint8_t instanceNr;                  /*!< The instance number of SPI */
    OSIRE_PinMuxConfigType * pcsPinMux;  /*!< The pinMux of SPI_PCS */
    OSIRE_PinMuxConfigType * clkPinMux;  /*!< The pinMux of SPI_SCK */
}OSIRE_PinConfigType;

/*! @brief Timeout configuration for a LED strip
 * Implements : OSIRE_TimeoutType_Class
 */
typedef struct
{
    uint8_t stripNr;                     /*!< Strip number */
    uint32_t timeoutDuration;            /*!< Timeout of strip */
}OSIRE_TimeoutType;

/*! @brief Configuration structure
 * Implements : OSIRE_ConfigType_Class
 */
typedef struct
{
    uint8_t                 nrOfStrips;     /*!< Number of strips */
    void                    (*callback)(OSIRE_CommEventType event, uint8_t strip);
    OSIRE_InterfaceType     interfaceType;  /*!< Interface selection */
    OSIRE_PinConfigType     *pinConfig;     /*!< Pin config for a LED strip */
    OSIRE_TimeoutType       *timeoutConfig; /*!< Timeout configuration for a LED strip */
    OSIRE_TransferType      transferType;   /*!< Transfer type */
    uint8_t                 dmaChanTx;      /*!< TX channel of DMA */
    uint8_t                 dmaChanRx;      /*!< RX channel of DMA */
} OSIRE_ConfigType;

/*!
 * @brief Initializes the OSIRE interface or interfaces
 *
 * This function initializes the OSIRE driver
 *
 * @param NrOfInterfaces          Number of hardware interfaces used for OSIRE communication (SPI)
 * @param ConfigPtr               Pointer to the configuration structure
 * @return
 *         - OSIRE_OK: Interface configured successfully.
 *         - OSIRE_ERROR_SPI: Error due to invalid parameters
 */
OSIRE_ReturnType OSIRE_InitInterface(uint8_t NrOfInterfaces, OSIRE_ConfigType *ConfigPtr);

/*!
 * @brief Triggers the software reset
 *
 * This function resets the internal state of the LEDs. When sent as a first command, OSIRE_Reset is always sent with CRC.
 *
 * @param StripNr                 Number of the strip on which the commands will be sent
 * @param address                 0-1000: Address of the target LED. 0 addresses all LEDs of the chain.
 * @return
 *         - OSIRE_OK: Function returned successfully.
 *         - OSIRE_ERROR_STRIP: Interface not initialized or
 *                              StripNr bigger than maximum supported number of strips.
 *
 */
OSIRE_ReturnType OSIRE_Reset(uint8_t StripNr, uint16_t address);

/*!
 * @brief Clears all error flags in one or all devices
 *
 * This function resets clears all error flags in one or all devices. 
 * If an error condition still persists, the error flag is automatically set again.
 *
 * @param StripNr                 Number of the strip on which the commands will be sent
 * @param address                 0-1000: Address of the target LED. 0 addresses all LEDs of the chain.
 * @return
 *         - OSIRE_OK: Function returned successfully.
 *         - OSIRE_ERROR_STRIP: Interface not initialized or
 *                              StripNr bigger than maximum supported number of strips.
 *
 */
OSIRE_ReturnType OSIRE_ClearError(uint8_t StripNr, uint16_t address);

/*!
 * @brief Initiates the automatic addressing of the chain
 *
 * This function initiates the automatic addressing of the chain and 
 * sets the communication direction to bidirectional.
 *
 * @param StripNr                 Number of the strip on which the commands will be sent
 * @param rspFrame                Pointer to structure containing result of initialization
 * @return
 *         - OSIRE_OK: Function returned successfully.
 *         - OSIRE_ERROR_STRIP: Interface not initialized or
 *                              StripNr bigger than maximum supported number of strips.
 *
 */
OSIRE_ReturnType OSIRE_InitBidir(uint8_t StripNr, OSIRE_FrameType *rspFrame);

/*!
 * @brief Initiates the automatic addressing of the chain
 *
 * Same as InitBidir but sets the communication mode to loop-back. 
 * The response to the master is sent in the forward direction.
 *
 * @param StripNr                 Number of the strip on which the commands will be sent
 * @param rspFrame                Pointer to structure containing result of initialization
 * @return
 *         - OSIRE_OK: Function returned successfully.
 *         - OSIRE_ERROR_STRIP: Interface not initialized or
 *                              StripNr bigger than maximum supported number of strips.
 *
 */
OSIRE_ReturnType OSIRE_InitLoop(uint8_t StripNr, OSIRE_FrameType *rspFrame);

/*!
 * @brief Sends one or all devices into SLEEP state.
 *
 * This function sends one or all devices into SLEEP state.
 *
 * @param StripNr                 Number of the strip on which the commands will be sent
 * @param address                 0-1000: Address of the target LED. 0 addresses all LEDs of the chain.
 * @return
 *         - OSIRE_OK: Function returned successfully.
 *         - OSIRE_ERROR_STRIP: Interface not initialized or
 *                              StripNr bigger than maximum supported number of strips.
 *
 */
OSIRE_ReturnType OSIRE_GoSleep(uint8_t StripNr, uint16_t address);

/*!
 * @brief Sends one or all devices into ACTIVE state.
 *
 * This function sends one or all devices into ACTIVE state.
 *
 * @param StripNr                 Number of the strip on which the commands will be sent
 * @param address                 0-1000: Address of the target LED. 0 addresses all LEDs of the chain.
 * @return
 *         - OSIRE_OK: Function returned successfully.
 *         - OSIRE_ERROR_STRIP: Interface not initialized or
 *                              StripNr bigger than maximum supported number of strips.
 *
 */
OSIRE_ReturnType OSIRE_GoActive(uint8_t StripNr, uint16_t address);

/*!
 * @brief Sends one or all devices into DEEPSLEEP state.
 *
 * This function sends one or all devices into DEEPSLEEP state.
 *
 * @param StripNr                 Number of the strip on which the commands will be sent
 * @param address                 0-1000: Address of the target LED. 0 addresses all LEDs of the chain.
 * @return
 *         - OSIRE_OK: Function returned successfully.
 *         - OSIRE_ERROR_STRIP: Interface not initialized or
 *                              StripNr bigger than maximum supported number of strips.
 *
 */
OSIRE_ReturnType OSIRE_GoDeepSleep(uint8_t StripNr, uint16_t address);

/*!
 * @brief Returns the STATUS register
 *
 * This function returns the STATUS register, and the definition of each bit refers to Start_Up_Guide.
 *
 * @param StripNr                 Number of the strip on which the commands will be sent
 * @param rspFrame                Pointer to structure containing result of initialization
 * @return
 *         - OSIRE_OK: Function returned successfully.
 *         - OSIRE_ERROR_STRIP: Interface not initialized or
 *                              StripNr bigger than maximum supported number of strips.
 *
 */
OSIRE_ReturnType OSIRE_ReadStatus(uint8_t StripNr, OSIRE_FrameType *rspFrame);

/*!
 * @brief Returns the TEMP + STATUS register
 *
 * This function returns the TEMP + STATUS register, and the definition of each bit refers to Start_Up_Guide.
 *
 * @param StripNr                 Number of the strip on which the commands will be sent
 * @param rspFrame                Pointer to structure containing result of initialization
 * @return
 *         - OSIRE_OK: Function returned successfully.
 *         - OSIRE_ERROR_STRIP: Interface not initialized or
 *                              StripNr bigger than maximum supported number of strips.
 *
 */
OSIRE_ReturnType OSIRE_ReadTempStatus(uint8_t StripNr, OSIRE_FrameType *rspFrame);

/*!
 * @brief Returns the COM STATUS register
 *
 * This function returns the COM STATUS register, and the definition of each bit refers to Start_Up_Guide.
 *
 * @param StripNr                 Number of the strip on which the commands will be sent
 * @param rspFrame                Pointer to structure containing result of initialization
 * @return
 *         - OSIRE_OK: Function returned successfully.
 *         - OSIRE_ERROR_STRIP: Interface not initialized or
 *                              StripNr bigger than maximum supported number of strips.
 *
 */
OSIRE_ReturnType OSIRE_ReadComStatus(uint8_t StripNr, OSIRE_FrameType *rspFrame);

/*!
 * @brief Returns the LED STATUS register
 *
 * This function returns the LED STATUS register, and the definition of each bit refers to Start_Up_Guide.
 *
 * @param StripNr                 Number of the strip on which the commands will be sent
 * @param rspFrame                Pointer to structure containing result of initialization
 * @return
 *         - OSIRE_OK: Function returned successfully.
 *         - OSIRE_ERROR_STRIP: Interface not initialized or
 *                              StripNr bigger than maximum supported number of strips.
 *
 */
OSIRE_ReturnType OSIRE_ReadLedStatus(uint8_t StripNr, OSIRE_FrameType *rspFrame);

/*!
 * @brief Returns the TEMP register
 *
 * This function returns the TEMP register, and the definition of each bit refers to Start_Up_Guide.
 *
 * @param StripNr                 Number of the strip on which the commands will be sent
 * @param rspFrame                Pointer to structure containing result of initialization
 * @return
 *         - OSIRE_OK: Function returned successfully.
 *         - OSIRE_ERROR_STRIP: Interface not initialized or
 *                              StripNr bigger than maximum supported number of strips.
 *
 */
OSIRE_ReturnType OSIRE_ReadTemp(uint8_t StripNr, OSIRE_FrameType *rspFrame);

/*!
 * @brief Writes the SETUP register.
 *
 * This function writes the SETUP register, and the definition of each bit refers to Start_Up_Guide.
 *
 * @param StripNr                 Number of the strip on which the commands will be sent
 * @param address                 0-1000: Address of the target LED. 0 addresses all LEDs of the chain.
 * @param config                  The SETUP register value needs to write.
 * @return
 *         - OSIRE_OK: Function returned successfully.
 *         - OSIRE_ERROR_STRIP: Interface not initialized or
 *                              StripNr bigger than maximum supported number of strips.
 *
 */
OSIRE_ReturnType OSIRE_SetSetup(uint8_t StripNr, uint16_t address, uint8_t config);

/*!
 * @brief Returns the SETUP register
 *
 * This function returns the SETUP register, and the definition of each bit refers to Start_Up_Guide.
 *
 * @param StripNr                 Number of the strip on which the commands will be sent
 * @param rspFrame                Pointer to structure containing result of initialization
 * @return
 *         - OSIRE_OK: Function returned successfully.
 *         - OSIRE_ERROR_STRIP: Interface not initialized or
 *                              StripNr bigger than maximum supported number of strips.
 *
 */
OSIRE_ReturnType OSIRE_ReadSetup(uint8_t StripNr, OSIRE_FrameType *rspFrame);

/*!
 * @brief Writes the PWM register.
 *
 * This function writes the PWM register, and the definition of each bit refers to Start_Up_Guide.
 *
 * @param StripNr                 Number of the strip on which the commands will be sent
 * @param address                 0-1000: Address of the target LED. 0 addresses all LEDs of the chain.
 * @param pwmData                 The PWM register value needs to write.
 * @return
 *         - OSIRE_OK: Function returned successfully.
 *         - OSIRE_ERROR_STRIP: Interface not initialized or
 *                              StripNr bigger than maximum supported number of strips.
 *
 */
OSIRE_ReturnType OSIRE_SetPwm(uint8_t StripNr, uint16_t address, OSIRE_PwmDataType pwmData);

/*!
 * @brief Returns the PWM register
 *
 * This function returns the SETUP register, and the definition of each bit refers to Start_Up_Guide.
 *
 * @param StripNr                 Number of the strip on which the commands will be sent
 * @param rspFrame                Pointer to structure containing result of initialization
 * @return
 *         - OSIRE_OK: Function returned successfully.
 *         - OSIRE_ERROR_STRIP: Interface not initialized or
 *                              StripNr bigger than maximum supported number of strips.
 *
 */
OSIRE_ReturnType OSIRE_ReadPwm(uint8_t StripNr, OSIRE_FrameType *rspFrame);

/*!
 * @brief Reads OTP values from address OTP ADDR
 *
 * This function reads OTP values from address OTP ADDR, and the definition of each bit refers to Start_Up_Guide.
 * If any of the 8 bytes exceeds the range of valid addresses, these bytes contain random data and should be ignored.
 *
 * @param StripNr                 Number of the strip on which the commands will be sent
 * @param otpAddress              The response contains 8 bytes starting from otpAddress.
 * @param rspFrame                Pointer to structure containing result of initialization
 * @return
 *         - OSIRE_OK: Function returned successfully.
 *         - OSIRE_ERROR_STRIP: Interface not initialized or
 *                              StripNr bigger than maximum supported number of strips.
 *
 */
OSIRE_ReturnType OSIRE_ReadOtp(uint8_t StripNr, uint8_t otpAddress, OSIRE_FrameType *rspFrame);

/*!
 * @brief Sets the timeout duration for a strip
 *
 * This function sets the timeout duration for a given strip
 *
 * @param Duration                Timeout duration in engineering units
 * @param StripNr                 Number of the strip on which the timeout will be set
 * @return
 *         - OSIRE_OK: Timeout set successfully.
 *         - OSIRE_ERROR_STRIP: Error due to invalid parameters
 */
OSIRE_ReturnType OSIRE_Set_Timeout(uint32_t Duration, uint8_t StripNr);

/*!
 * @brief Check if timeout.
 * 
 * This function is call back in timer IRQn handler and checking if timeout.
 * 
 * @param StripNr                 Number of the strip which need to check timeout.
 * @return
 *         - OSIRE_OK: Function returned successfully.
 *         - OSIRE_ERROR_STRIP: Error due to invalid parameters or
 *                              Interface not initialized or
 *                              Strip not initialized or
 *                              StripNr bigger than maximum supported number of strips or
 *                              chainLength is 0.
 *
 */
OSIRE_ReturnType OSIRE_Timeout_Service(uint8_t StripNr);

/*! @}*/
#endif /* _OSIRE_DRIVER_H */