
#include "platform.h"
#include "hal_headfile.h"
#include "npu.h"
#include "debug.h"
/************************************************static 函数列表***************************************************/
//! 打开npu电源
//__IRAM static void openNpuPower(void);

/************************************************static 变量列表***************************************************/
/*
 * npu监听结构体,用于监听npu的实时动态方便调度器及时了解npu的相关状态
 * */
static  npuListener_s            *gNpuListener          = NULL;

/**!
 * npu 运行状态开关
 * */
static volatile uint8_t           gNpuIsRunning         = 0;

// static uint64_t  gTime;

#define TABLE_IE                           (1  << 1)
#define TAB_PD                             (1  << 1)
#define RES_IE                             (1  << 0)
#define RES_PD                             (1  << 0)
#define SKIPIN                             (1  << 14)
#define DEFAULT_BASSPAN                    (18 << 24)
#define DEFAULT_BSID                       (0  << 16)
#define DEFAULT_SEL0_CHOOSE                (0xF0000000)
#define DEFAULT_SEL1_CHOOSE                (0xFFFFFFFF)

extern uint64_t read_mcycle2(void);

//打开npu电源
//static void openNpuPower(void)
//{
//
//}

/*!
* \brief npu done 中断回调函数,配合底层的API，在npu done中断触发后调用此接口
*/
void npu_res_irq_handler(void)
{
//  uint64_t  tTime;
//  tTime = read_mcycle2() - gTime;
    DEV_NPU->PD |= RES_PD;
    gNpuIsRunning = 0;

    if ((gNpuListener != NULL) && (gNpuListener->npuDoneListener != NULL))
    {
        // DEV_GPIO->CTL[23] = 0x210;
        gNpuListener->npuDoneListener();
    }

    DEV_RMU->RSTEN0 &= ~DEV_RMU_RSTEN0_NPU;
    DEV_CMU->CLKEN0 &= ~DEV_CMU_CLKEN0_NPU;
}


/*!
* \brief npu table 中断回调函数,配合底层的API，在npu table中断触发后调用此接口
*/
void npu_tab_irq_handler(void)
{
    DEV_NPU->PD |= TAB_PD;

    if ((gNpuListener != NULL) && (gNpuListener->npuTableListener != NULL))
    {
        gNpuListener->npuTableListener();
    }
}


/*!
* \brief npu初始化函数,外界可调,主要功能
*        a. 变量初始化
*        b. 为调度器下探指针提供接口
*/
void npuInit(npuListener_s *npuListener)
{
    //将调度器下探的钩子储存
    gNpuListener = npuListener;
}


/*!
* \brief 在上层准备好之后，重新启动npu
*/
void reStartNpu(void)
{
    // DEV_GPIO->CTL[23] = 0x10;
    DEV_NPU->PPRDY = 1;
}


/*!
* \brief 根据申请单中传来的参数配置npu,并启动npu
* \param
*        startParam       : npu的配置参数
*/
uint8_t startNpu(npuStartParam_s *startParam)
{
    // if(gNpuIsRunning)
    // {
    //  return 0;
    // }
    // gTime = read_mcycle2();
    DEV_RMU->RSTEN0 &= ~DEV_RMU_RSTEN0_NPU;
    DEV_CMU->CLKEN0 |= DEV_CMU_CLKEN0_NPU;
    DEV_RMU->RSTEN0 |= DEV_RMU_RSTEN0_NPU;
    gNpuIsRunning = 1;
    DEV_MEMC->RAM_SEL0  = DEFAULT_SEL0_CHOOSE;
    DEV_MEMC->RAM_SEL1  = DEFAULT_SEL1_CHOOSE;

    //! 打开npu
    if (startParam->bottom == startParam->top)
    {
        DEV_NPU->MBK        = SKIPIN | DEFAULT_BASSPAN | DEFAULT_BSID;
    }
    else
    {
        DEV_NPU->MBK        = DEFAULT_BASSPAN | DEFAULT_BSID;
        DEV_NPU->PKL_ADR    = startParam->bottom;
        DEV_NPU->PKC_ADR    = startParam->current;
        DEV_NPU->PKU_ADR    = startParam->top;
    }

    DEV_NPU->MDL_ADR    = startParam->cfg;
    DEV_NPU->BIA_ADR    = startParam->bias;
    DEV_NPU->PONG_ADR   = startParam->pong;
    DEV_NPU->PING_ADR   = startParam->ping;
    DEV_NPU->PPLEN      = startParam->tableLen;
    DEV_NPU->RES_ADR    = startParam->output;
    DEV_NPU->PPRDY      = 1;
    // DEV_GPIO->CTL[23] = 0x10;
    DEV_NPU->IE         = TABLE_IE | RES_IE;
    DEV_NPU->EN         = 1;
    return 1;
}



