/**
 * @brief       PGP Manager (Intr)
 * @author      AXELL CORPORATION
 * @description PGP Manager Layer.
 * @note        none
 * @history     2017_02_22  初版
 * @history     2017_10_26  Ver2.0
*/
/* DOM-IGNORE-BEGIN */
/*
 * This program was created by AXELL CORPORATION.
 * Copyright (C) 2017 AXELL CORPORATION, all rights reserved.
 */
/* DOM-IGNORE-END */

#include <stdio.h>
#include "pgpmgr_common.h"
#include "pgp/pgpprm.h"
#include "int/intmgr.h"
#include "AG903_intno.h"

/* 発生している割り込み要因をチェックし、Manager Layerに設定されているコールバック関数を呼び出します */
static void PgpMgrIntrCallback(int32_t id)
{
    PGPPrmParamPGPnINTSTAT intstat;
    PGPPrmParamPGPnINTCLR  intclr;
    PgpMgrContext *ctx = PgpGetContext();

    /* Primitive Layerから割り込み要因のステータスを取得します */
    AG903_PgpPrmGetPGPnINTSTAT(id, &intstat);

    if ((intstat.nd != 0) && (ctx->intr_nd_func[id] != NULL)) {
        ctx->intr_nd_func[id](id, (void *)ctx->exec_pipeline[id]);
    }
    if (((intstat.voicpl != 0) || (intstat.vooflw != 0)) && (ctx->intr_vram_error_func[id] != NULL)) {
        ctx->intr_vram_error_func[id](id, (void *)ctx->exec_pipeline[id]);
    }
    if (((intstat.ifcofs != 0) || (intstat.ifcofm != 0)) && (ctx->intr_ifc_ovf_func[id] != NULL)) {
        ctx->intr_ifc_ovf_func[id](id, (void *)ctx->exec_pipeline[id]);
    }
    if ((intstat.lblcrpt != 0) && (ctx->intr_lbl_error_func[id] != NULL)) {
        ctx->intr_lbl_error_func[id](id, (void *)ctx->exec_pipeline[id]);
    }
    if ((intstat.lblcpl != 0) && (ctx->intr_lbl_done_func[id] != NULL)) {
        ctx->intr_lbl_done_func[id](id, (void *)ctx->exec_pipeline[id]);
    }
    if ((intstat.hgmicpl != 0) && (ctx->intr_hgm_error_func[id] != NULL)) {
        ctx->intr_hgm_error_func[id](id, (void *)ctx->exec_pipeline[id]);
    }
    if ((intstat.hgmcpl != 0) && (ctx->intr_hgm_done_func[id] != NULL)) {
        ctx->intr_hgm_done_func[id](id, (void *)ctx->exec_pipeline[id]);
    }
    if ((intstat.vsynco != 0) && (ctx->intr_output_func[id] != NULL)) {
        ctx->intr_output_func[id](id, (void *)ctx->exec_pipeline[id]);
    }
    if ((intstat.vsynco != 0) && (ctx->intr_done_func[id] != NULL)) {
        ctx->intr_done_func[id](id, (void *)ctx->exec_pipeline[id]);
    }
    if ((intstat.vlineo != 0) && (ctx->intr_output_line_func[id] != NULL)) {
        ctx->intr_output_line_func[id](id, (void *)ctx->exec_pipeline[id]);
    }
    if ((intstat.vsynci != 0) && (ctx->intr_input_func[id] != NULL)) {
        ctx->intr_input_func[id](id, (void *)ctx->exec_pipeline[id]);
    }
    if ((intstat.vlinei != 0) && (ctx->intr_input_line_func[id] != NULL)) {
        ctx->intr_input_line_func[id](id, (void *)ctx->exec_pipeline[id]);
    }

    /* 割り込みをクリアします */
    intclr.nd      = intstat.nd;
    intclr.voicpl  = intstat.voicpl;
    intclr.vooflw  = intstat.vooflw;
    intclr.ifcofs  = intstat.ifcofs;
    intclr.ifcofm  = intstat.ifcofm;
    intclr.lblcrpt = intstat.lblcrpt;
    intclr.lblcpl  = intstat.lblcpl;
    intclr.hgmicpl = intstat.hgmicpl;
    intclr.hgmcpl  = intstat.hgmcpl;
    intclr.vsynco  = intstat.vsynco;
    intclr.vlineo  = intstat.vlineo;
    intclr.vsynci  = intstat.vsynci;
    intclr.vlinei  = intstat.vlinei;
    AG903_PgpPrmSetPGPnINTCLR(id, &intclr);
}

/* 演算処理パイプライン0用IRQのハンドラに登録するためのコールバック関数 */
static void PgpMgrIntrCallbackCalcPipeline0(void)
{
    PgpMgrIntrCallback(AG903_PGP_MGR_CALC_PIPELINE0);
}

/* 演算処理パイプライン1用IRQのハンドラに登録するためのコールバック関数 */
static void PgpMgrIntrCallbackCalcPipeline1(void)
{
    PgpMgrIntrCallback(AG903_PGP_MGR_CALC_PIPELINE1);
}

/* 入力画像処パイプライン0用IRQのハンドラに登録するためのコールバック関数 */
static void PgpMgrIntrCallbackInputPipeline0(void)
{
    PgpMgrIntrCallback(AG903_PGP_MGR_INPUT_PIPELINE0);
}

/* 入力画像処パイプライン1用IRQのハンドラに登録するためのコールバック関数 */
static void PgpMgrIntrCallbackInputPipeline1(void)
{
    PgpMgrIntrCallback(AG903_PGP_MGR_INPUT_PIPELINE1);
}

/* フレーム保存パイプライン0用IRQのハンドラに登録するためのコールバック関数 */
static void PgpMgrIntrCallbackFramePipeline0(void)
{
    PgpMgrIntrCallback(AG903_PGP_MGR_FRAME_PIPELINE0);
}

/* フレーム保存パイプライン1用IRQのハンドラに登録するためのコールバック関数 */
static void PgpMgrIntrCallbackFramePipeline1(void)
{
    PgpMgrIntrCallback(AG903_PGP_MGR_FRAME_PIPELINE1);
}


/**
 * @brief   割り込みハンドラに対してコールバック関数を登録します。
 * @param   none
 * @return  none
 * @note    AG903_INTMgrSetHdrを呼び出し、全てのパイプラインの割り込みコールバックを割り込みハンドラに登録します。<p>
 *          本関数はユーザー側が直接使用することはありません。
*/
void PgpMgrSetIntr(void)
{
    int32_t id;
    PgpMgrContext *ctx = PgpGetContext();
    for (id = 0; id < AG903_PGP_MGR_PIPELINE_NUM; id++) {
        ctx->intr_nd_func[id] = NULL;
        ctx->intr_vram_error_func[id] = NULL;
        ctx->intr_ifc_ovf_func[id] = NULL;
        ctx->intr_lbl_error_func[id] = NULL;
        ctx->intr_lbl_done_func[id] = NULL;
        ctx->intr_hgm_error_func[id] = NULL;
        ctx->intr_hgm_done_func[id] = NULL;
        ctx->intr_output_func[id] = NULL;
        ctx->intr_done_func[id] = NULL;
        ctx->intr_output_line_func[id] = NULL;
        ctx->intr_input_func[id] = NULL;
        ctx->intr_input_line_func[id] = NULL;
    }

    /* 割り込みハンドラの登録 */
    AG903_INTMgrHdrPrm irq0_prm = {0, NULL, AG903_IRQ32_PGP0, (void *)PgpMgrIntrCallbackCalcPipeline0};
    AG903_INTMgrHdrPrm irq1_prm = {0, NULL, AG903_IRQ33_PGP1, (void *)PgpMgrIntrCallbackCalcPipeline1};
    AG903_INTMgrHdrPrm irq2_prm = {0, NULL, AG903_IRQ34_PGP2, (void *)PgpMgrIntrCallbackInputPipeline0};
    AG903_INTMgrHdrPrm irq3_prm = {0, NULL, AG903_IRQ35_PGP3, (void *)PgpMgrIntrCallbackInputPipeline1};
    AG903_INTMgrHdrPrm irq4_prm = {0, NULL, AG903_IRQ36_PGP4, (void *)PgpMgrIntrCallbackFramePipeline0};
    AG903_INTMgrHdrPrm irq5_prm = {0, NULL, AG903_IRQ37_PGP5, (void *)PgpMgrIntrCallbackFramePipeline1};
    ctx->intr_hdr_id[0] = AG903_INTMgrSetHandler(&irq0_prm);
    ctx->intr_hdr_id[1] = AG903_INTMgrSetHandler(&irq1_prm);
    ctx->intr_hdr_id[2] = AG903_INTMgrSetHandler(&irq2_prm);
    ctx->intr_hdr_id[3] = AG903_INTMgrSetHandler(&irq3_prm);
    ctx->intr_hdr_id[4] = AG903_INTMgrSetHandler(&irq4_prm);
    ctx->intr_hdr_id[5] = AG903_INTMgrSetHandler(&irq5_prm);
    AG903_INTMgrEnableInt(AG903_IRQ32_PGP0);
    AG903_INTMgrEnableInt(AG903_IRQ33_PGP1);
    AG903_INTMgrEnableInt(AG903_IRQ34_PGP2);
    AG903_INTMgrEnableInt(AG903_IRQ35_PGP3);
    AG903_INTMgrEnableInt(AG903_IRQ36_PGP4);
    AG903_INTMgrEnableInt(AG903_IRQ37_PGP5);
}


/**
 * @brief   割り込みハンドラからコールバック関数を削除します。
 * @param   none
 * @return  none
 * @note    AG903_INTMgrDelHdrを呼び出し、全てのパイプラインの割り込みコールバックを割り込みハンドラから削除します。<p>
 *          本関数はユーザー側が直接使用することはありません。
*/
void PgpMgrResetIntr(void)
{
    int32_t id;
    PgpMgrContext *ctx = PgpGetContext();
    for (id = 0; id < AG903_PGP_MGR_PIPELINE_NUM; id++) {
        ctx->intr_nd_func[id] = NULL;
        ctx->intr_vram_error_func[id] = NULL;
        ctx->intr_ifc_ovf_func[id] = NULL;
        ctx->intr_lbl_error_func[id] = NULL;
        ctx->intr_lbl_done_func[id] = NULL;
        ctx->intr_hgm_error_func[id] = NULL;
        ctx->intr_hgm_done_func[id] = NULL;
        ctx->intr_output_func[id] = NULL;
        ctx->intr_done_func[id] = NULL;
        ctx->intr_output_line_func[id] = NULL;
        ctx->intr_input_func[id] = NULL;
        ctx->intr_input_line_func[id] = NULL;
    }

    /* 割り込みハンドルの削除 */
    AG903_INTMgrDisableInt(AG903_IRQ32_PGP0);
    AG903_INTMgrDisableInt(AG903_IRQ33_PGP1);
    AG903_INTMgrDisableInt(AG903_IRQ34_PGP2);
    AG903_INTMgrDisableInt(AG903_IRQ35_PGP3);
    AG903_INTMgrDisableInt(AG903_IRQ36_PGP4);
    AG903_INTMgrDisableInt(AG903_IRQ37_PGP5);
    AG903_INTMgrDeleteHandler(ctx->intr_hdr_id[0]);
    AG903_INTMgrDeleteHandler(ctx->intr_hdr_id[1]);
    AG903_INTMgrDeleteHandler(ctx->intr_hdr_id[2]);
    AG903_INTMgrDeleteHandler(ctx->intr_hdr_id[3]);
    AG903_INTMgrDeleteHandler(ctx->intr_hdr_id[4]);
    AG903_INTMgrDeleteHandler(ctx->intr_hdr_id[5]);
}


