/*
 * Copyright (c) 2022, Shenzhen CVA Innovation CO.,LTD
 * All rights reserved.
 *
 * Shenzhen CVA Innovation CO.,LTD (CVA chip) is supplying this file for use
 * exclusively with CVA's microcontroller products. This file can be freely
 * distributed within development tools that are supporting such microcontroller
 * products.
 *
 * THIS SOFTWARE IS PROVIDED "AS IS".  NO WARRANTIES, WHETHER EXPRESS, IMPLIED
 * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
 * CVA SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL,
 * OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
 */

#ifndef _LIN_SCHEDULE_H_
#define _LIN_SCHEDULE_H_

/*! \brief his file exports Lin schedule table information
 *
 */

/*******************************************************************************
 * the includes
 ******************************************************************************/

#include <stdint.h>
#include <stdbool.h>
#include "lin_type.h"
#include "lin_cfg.h"

/*! \addtogroup lin_schedule
 *  @{
 */

#ifdef __cplusplus
extern "C" {
#endif

/*******************************************************************************
 * the defines
 ******************************************************************************/
#define LINSCH_SCHEDULE_TABLE_NULL (0x00u)

#define LINSCH_FRAMEID_IDX_INVALID (0xFF)

/*******************************************************************************
 * the typedefs
 ******************************************************************************/

/* define the application communication frame schedule table type */
typedef enum
{
    LINSCH_TBL_TYPE_NULL = LINSCH_SCHEDULE_TABLE_NULL, /* Run nothing */
    LINSCH_TBL_TYPE_NORM,                              /* Normal schedule table */
    LINSCH_TBL_TYPE_DIAG,                              /* Diagnostic schedule table */
    LINSCH_TBL_TYPE_GO_TO_SLEEP,                       /* Goto sleep schedule table */
    LINSCH_TBL_TYPE_COLL_RESOLV,                       /* Collision resolving schedule table */
    LINSCH_TBL_TYPE_SPORADIC,                          /* Sporadic schedule table */

    LINSCH_TBL_TYPE_NUM
} LinSchedule_TableType;

typedef struct
{
    uint8_t           pidIdx;
    Lin_FrametypeType frameType;
    Lin_FrameCtrlType frameCtrl;
} LinSchedule_FrameAttributeType;

typedef struct
{
    uint8_t           pidIdx;
    Lin_FrametypeType frameType;
    uint16_t          frameSlotTick;
    uint8_t           linkTblIdx;
} LinSchedule_ScheduleTblInfoType;

typedef struct
{
    uint8_t                                tblIdx;
    LinSchedule_TableType                  tblType;
    const LinSchedule_ScheduleTblInfoType *pScheduleTblInfo;
    uint8_t                                frameNum;
} LinSchedule_ScheduleTblListType;

typedef struct
{
    const LinSchedule_ScheduleTblListType *pCurrentScheduleTblPtr;
    uint8_t                                defaultScheduleTblIdx;
    uint8_t                                currentScheduleTblIdx;
    uint8_t                                prevScheduleTblIdx;
    uint8_t                                targetScheduleTblIdx;
    bool                                   scheduleTblSwitchReqEn;
    uint8_t                                prevFrameIdxInScheduleTbl;
    uint8_t                                currentFrameIdxInScheduleTbl;
    uint8_t                                txFrameCnt;
    uint16_t                               frameSlotTick;

    uint16_t currentFrameSlotTickCnt;
} LinSchedule_StateType;

typedef struct
{
    const LinSchedule_FrameAttributeType *pChxFrameAttribute;
    uint8_t                               chxFrameAttributeNum;

    const LinSchedule_ScheduleTblListType *pChxScheduleTblList;
    uint8_t                                chxScheduleTblNum;

} LinSchedule_ChxTableInfoType;

typedef struct
{
    const Lin_FrameGeneralityType *pFrameGenerality;
    uint8_t                        frameGeneralityNum;

    const LinSchedule_ChxTableInfoType chxTableInfo[LINCFG_CH_NUM];

} LinSchedule_TblInfoType;

typedef struct
{
    const LinSchedule_TblInfoType *pLinSchedule_TblInfo;

    LinSchedule_StateType chxState[LINCFG_CH_NUM];
} LinSchedule_CtrlType;

/*******************************************************************************
 * the globals
 ******************************************************************************/

/*******************************************************************************
 * the function prototypes
 ******************************************************************************/

 /*! \brief Initialize the schedule table information
 *
 * This function execute to initialize the schedule table information
 *
 * \param[in] pTblInfo: table information pointer
 * \return: void
 */
extern void LinSchedule_TblInit(const LinSchedule_TblInfoType *pTblInfo);

/*! \brief Initialize the schedule table information
 *
 * This function execute to initialize the schedule table information
 *
 * \param[in] channelIdx: which physical channel is used
 * \return: void
 */
extern void LinSchedule_Init(uint8_t channelIdx);

/*! \brief Get the support frame number in the LIN BUS
 *
 * This function execute to get the frame number
 *
 * \param[in] uint8_t channelIdx: which physical channel is used
 * \return: the frame number
 */
extern uint8_t LinSchedule_GetFrameNum(uint8_t channelIdx);

/*! \brief Get the pid by the pid index
 *
 * This function execute to get the pid in the support pid list
 *
 * \param[in] pidIdx: pid index
 * \return: pid
 */
extern uint8_t LinSchedule_GetPid(uint8_t pidIdx);

/*! \brief Get the pid index by pid
 *
 * This function execute to get the pid by the pid index in the support pid list
 *
 * \param[in] pid: pid
 * \return: pid index
 */
extern uint8_t LinSchedule_GetPidIdx(uint8_t pid);

/*! \brief Get the pid index in the target schedule table
 *
 * This function execute to get the pid index in the target schedule table by frame index
 *
 * \param[in] channelIdx: which physical channel is used
 * \param[in] linkTblIdx: link schedule table index
 * \param[in] frameIdx: the frame index in schedule table
 * \return: pid index
 */
extern uint8_t LinSchedule_GetPidIdxInSchedulerTbl(uint8_t channelIdx, uint8_t linkTblIdx, uint8_t frameIdx);

/*! \brief Get the frame type
 *
 * This function execute to get the frame type by the pid index
 *
 * \param[in] channelIdx: : which physical channel is used
 * \param[in] pidIdx: pid index
 * \return: the frame type
 */
extern Lin_FrametypeType LinSchedule_GetFrameType(uint8_t channelIdx, uint8_t pidIdx);

/*! \brief Get the frame control
 *
 * This function execute to get the frame control
 *
 * \param[in] channelIdx: : which physical channel is used
 * \param[in] pidIdx: pid index
 * \return: frame control type
 */
extern Lin_FrameCtrlType LinSchedule_GetFrameCtrl(uint8_t channelIdx, uint8_t pidIdx);

/*! \brief Get the frame data length by pid index
 *
 * This function execute to get the frame data length by pid index
 *
 * \param[in] pidIdx: pid index
 * \return: the length of the frame data
 */
extern uint8_t LinSchedule_GetFrameDataLen(uint8_t pidIdx);

/*! \brief Get the checksum type
 *
 * This function execute to get the checksum type
 *
 * \param[in] pid: pid
 * \return: the type of check sum
 */
extern Lin_CheckSumType LinSchedule_GetCheckSumType(uint8_t pid);

/*! \brief Get the frame buffer pointer
 *
 * This function execute to get the frame buffer pointer, each frame has their own buffer
 *
 * \param[in] pidIdx: pid index
 * \return: the pointer of frame buffer
 */
extern Lin_FrameDataType *LinSchedule_GetFrameBufferPtr(uint8_t pidIdx);

/*! \brief Get the frame access state
 *
 * This function execute
 *
 * \param[in] uint8_t pidIdx:
 * \return: Lin_FrameAccessStateType
 */
extern Lin_FrameAccessStateType LinSchedule_GetFrameAccessState(uint8_t pidIdx);

/*! \brief Sect the frame access state
 *
 * This function execute to set the frame access state, allow or not allow to readout from the frame buffer or write data into frame buffer
 *
 * \param[in] pidIdx: pid index
 * \param[in] accessState: access state
 * \return: void
 */
extern void LinSchedule_SetFrameAccessState(uint8_t pidIdx, Lin_FrameAccessStateType accessState);

#if LINCFG_NODE_USED == LINCFG_NODE_MASTER

/*! \brief Get the schedule table index by table type
 *
 * This function execute to get the type of current operated schedule table
 *
 * \param[in] tableType: : the type of schedule table
 * \return: return the first match table index in the schedule table list
 */
extern uint8_t LinSchedule_GetScheduleTblIdxByTableType(LinSchedule_TableType tableType);

/*! \brief Set the default schedule table index
 *
 * This function execute to set the default schedule table index
 *
 * \param[in] channelIdx: which physical channel is used
 * \param[in]:  the default schedule table index
 */
extern void LinSchedule_SetDefaultScheduleTblIdx(uint8_t channelIdx, uint8_t defaultScheduleTblIdx);

/*! \brief Get the default schedule table index
 *
 * This function execute to get the default schedule table index
 *
 * \param[in] channelIdx: which physical channel is used
 * \return:  the default schedule table index
 */
extern uint8_t LinSchedule_GetDefaultScheduleTblIdx(uint8_t channelIdx);

    /*! \brief Request to switch schedule table
 *
 * This function execute to request to switch to target schedule table
 *
 * \param[in] channelIdx: which physical channel is used
 * \param[in] targetScheduleTblIdx: target schedule index
 * \return: true: switch to target schedule table successfully
 *          false: switch to target schedule table failed
 */
extern bool LinSchedule_ReqSwitchScheduleTbl(uint8_t channelIdx, uint8_t targetScheduleTblIdx);

/*! \brief The main function of schedule table process
 *
 * This function execute to process the schedule table
 *
 * \param[in] channelIdx:  which physical channel is used
 * \return: void
 */
extern void LinSchedule_MainFunction(uint8_t channelIdx);
#endif

/*! \brief Get the link schedule table index
 *
 * This function execute to get the link schedule table index by the pid index in current schedule table
 *
 * \param[in] channelIdx: which physical channel is used
 * \param[in] tblIdx: the current schedule table index
 * \param[in] pidIdx: the pid index
 * \return: the link schedule table index
 */
extern uint8_t LinSchedule_GetLinkTblIdx(uint8_t channelIdx, uint8_t tblIdx, uint8_t pidIdx);

/*! \brief Get the frame number in the current schedule table
 *
 * This function execute to get the frame number in the current schedule table
 *
 * \param[in] channelIdx: which physical channel is used
 * \param[in] linkTblIdx: which schedule table is to be check
 * \return: the frame number in the current schedule table
 */
extern uint8_t LinSchedule_GetFrameNumInScheduleTbl(uint8_t channelIdx, uint8_t linkTblIdx);

/*! \brief Get the link schedule table pointer
 *
 * This function execute to get the link schedule table pointer
 *
 * \param[in] channelIdx: which physical channel is used
 * \param[in] linkTblIdx: the link schedule table index
 * \return: the link schedule table pointer
 */
extern LinSchedule_ScheduleTblListType *LinSchedule_GetLinkScheduleTblPtr(uint8_t channelIdx, uint8_t linkTblIdx);

#ifdef __cplusplus
}
#endif /* extern "C" */

/*! @}*/

#endif /* _LIN_SCHEDULE_H_ */
