/*
 * AXMPixcessorInt.cpp
 */

#include "AXMPixcessorInt.hpp"
#include "AXFEvent.hpp"
#include "AXFStage.hpp"
#include "AXFIrqSignal.hpp"
#include "AXMIsp/AXMIsp.hpp"
#include "../../project/refkit/AXMIspConfig.hpp"		// project/refkit/
#include "AXHWhiteBalanceGain.hpp"


WbgRegCtrl wbg_reg_ctrl;
WbgRegCtrl *p_wbg_reg_ctrl;

AXMPixcessorInt *p_AXMPixcessorInt;



static int           GduBankno = 0;
static unsigned char ImageIFOpeMode = 0;       //  ImageIF 動作モード通知用[0:Linearモード以外/1:Linearモード]
static unsigned char ImageIFOpeModeUpd = 0;    //  ImageIF 動作モード変更通知[0:動作モード変更なし/1:あり]
static unsigned char SclEnabled[] = { 0, 0, 0 };

AXMPixcessorInt::AXMPixcessorInt(AXFObjectName& name)
    : AXModelActor(name),
      m_log(name),
      m_name(name),
      m_timerID(NULL),
      m_irqSignal(NULL),
      //m_irqFrameGen(NULL),//　ホストCPUへの通知なしのため不要
      m_isUseTimer(false),
      m_genWCount(0),
      m_genRCount(0),
      m_isrcount(0) {
  m_log.write(AXFLOG_DEBUG, "PixcessorInt Constractor");
	creFlg = false;		// 生成フラグ初期化

  for(int i=0; i < AXM_GENPARAM_MAX; i++){
    m_genParam[i].cmd   = 0;
    m_genParam[i].bankno     = 0;
  }
  imageSensorParam.st_change_sts = 0;
  imageSensorParam.st_time = 0;
  imageSensorParam.st_gain = 0;
  imageSensorParam.st_frm  = 1125;
}

AXMPixcessorInt::~AXMPixcessorInt() {
  m_log.write(AXFLOG_DEBUG, "PixcessorInt Destractor");
}

ax::actorFuncStatus AXMPixcessorInt::onCreate() {
  m_log.write(AXFLOG_DEBUG, "PixcessorInt onCreate()");
  // タイマーの生成
#ifndef PARASOFT_CPPTEST
  if (AXFActor::TIMER_SUCCESS != createTimer()) {
    m_log.write(AXFLOG_ERR, "fail stopTimer");
    return ax::AXFACTOR_ERROR;
  }
#endif  //  PARASOFT_CPPTEST

  // irqSignal(フレーム割り込み用)の生成
  m_irqSignal = new (std::nothrow) AXFIrqSignal(nameIsp,
                                                AXFEVENT_DEVICE_FRAME_ISR);
#ifndef PARASOFT_CPPTEST
  if (NULL == m_irqSignal) {
    m_log.write(AXFLOG_ERR, "fail new AXFIrqSignal");
    return ax::AXFACTOR_ERROR;
  }

  if (false == m_irqSignal->create()) {
    m_log.write(AXFLOG_ERR, "fail create AXFIrqSignal");
    return ax::AXFACTOR_ERROR;
  }
#endif  //  PARASOFT_CPPTEST

	//　ホストCPUへの通知なしのため不要
	/*
  // irqSignal(フレーム生成完了通知用)の生成
  m_irqFrameGen = new (std::nothrow) AXFIrqSignal(nameIsp,
                                                AXMIsp::EVENT_IRQ_FRAMEGEN);
#ifndef PARASOFT_CPPTEST
  if (NULL == m_irqFrameGen) {
    m_log.write(AXFLOG_ERR, "fail new AXFIrqFrameGen");
    return ax::AXFACTOR_ERROR;
  }

  if (false == m_irqFrameGen->create()) {
    m_log.write(AXFLOG_ERR, "fail create AXFIrqFrameGen");
    return ax::AXFACTOR_ERROR;
  }
#endif  //  PARASOFT_CPPTEST
	*/

  // StateMachine に必要な情報を登録する
  //      自オブジェクト,
  //      初期状態,
  //      状態の最大数
#ifndef PARASOFT_CPPTEST
  if (0 > setStateInfo(this, STATUS_RUNNING, STATSU_MAX)) {
    m_log.write(AXFLOG_ERR, "fail registHandle");
    return ax::AXFACTOR_ERROR;
  }

  // STATE_0状態の状態テーブルを登録する
  //      状態テーブルで登録する状態,
  //      状態テーブルのポインタ,
  setStateTable(STATUS_RUNNING, state_running);
#endif  //  PARASOFT_CPPTEST

  //p_AXMPixcessorInt = AXMPixcessorInt;
  p_AXMPixcessorInt = this;
  
  p_wbg_reg_ctrl = &wbg_reg_ctrl;

	creFlg = true;		// 生成フラグON
  return ax::AXFACTOR_SUCCESS;
}

ax::actorFuncStatus AXMPixcessorInt::onStart() {
  m_log.write(AXFLOG_DEBUG, "PixcessorInt onStart()");

  PixcessorInit();

  return ax::AXFACTOR_SUCCESS;
}

ax::actorFuncStatus AXMPixcessorInt::onStop() {
  m_log.write(AXFLOG_DEBUG, "PixcessorInt onStop()");

  return ax::AXFACTOR_SUCCESS;
}

ax::actorFuncStatus AXMPixcessorInt::onDestroy() {
  m_log.write(AXFLOG_DEBUG, "PixcessorInt onDestroy()");
  // タイマーの削除
#ifndef PARASOFT_CPPTEST
  deleteTimer();
#endif  //  PARASOFT_CPPTEST

  // irqSignalの削除
  delete m_irqSignal;
  m_irqSignal = NULL;

	//　ホストCPUへの通知なしのため不要
	/*
  // m_irqFrameGenの削除
  delete m_irqFrameGen;
  m_irqFrameGen = NULL;
	*/

  return ax::AXFACTOR_SUCCESS;
}

#if 0
ax::actorFuncStatus AXMPixcessorInt::onPause() {
  m_log.write(AXFLOG_DEBUG, "PixcessorInt onPause()");
  return ax::AXFACTOR_SUCCESS;
}

ax::actorFuncStatus AXMPixcessorInt::onResume() {
  m_log.write(AXFLOG_DEBUG, "PixcessorInt onResume()");
  return ax::AXFACTOR_SUCCESS;
}

ax::actorFuncStatus AXMPixcessorInt::onRestart() {
  m_log.write(AXFLOG_DEBUG, "PixcessorInt onRestart()");
  return ax::AXFACTOR_SUCCESS;
}
#endif

/* フレーム完了通知IRQハンドラ(実機では型を調整してください) */
void AXMPixcessorInt::frameIsrHandler() {
  // 実機において、IRQハンドラから C++メソッドが呼び出せない場合は、
  // C関数ポインタにキャストするなど、工夫が必要
  m_irqSignal->signal();
}

//　ホストCPUへの通知なしのため不要
///* フレーム生成完了通知(DSP->ARM)ハンドラ */
//void AXMPixcessorInt::frameGenHandler(int cmd, int bankno, int complex) {
//  setGenParam(cmd, bankno, complex);
//  m_irqFrameGen->signal();
//}

/* フレーム生成用パラメータ設定 */
void AXMPixcessorInt::setGenParam(int cmd, int bankno, int complex) {
  m_genParam[m_genWCount].cmd = cmd;
  m_genParam[m_genWCount].bankno = bankno;
  m_genParam[m_genWCount].complex = complex;
  m_genWCount = ((m_genWCount + 1) % AXM_GENPARAM_MAX);
}

/* フレーム生成用パラメータ取得 */
void* AXMPixcessorInt::getGenParam() {
  int count = m_genRCount;
  if(count == m_genWCount){
    return NULL;
  }
  m_genRCount = ((m_genRCount + 1) % AXM_GENPARAM_MAX);
  return (void*)&m_genParam[count];
}

/* AF評価値取得 */
void AXMPixcessorInt::getAfEval() {
	static int count = 0;

	// 今回AFは非対応のため不要
	/*
	afEval[0]  = GetReg32( RegAFH_DTH0 );
	afEval[1]  = GetReg32( RegAFH_DTH1 );
	afEval[2]  = GetReg32( RegAFH_DTH2 );
	afEval[3]  = GetReg32( RegAFH_DTH3 );
	afEval[4]  = GetReg32( RegAFH_DTH4 );
	afEval[5]  = GetReg32( RegAFH_DTH5 );
	afEval[6]  = GetReg32( RegAFH_DTH6 );
	afEval[7]  = GetReg32( RegAFH_DTH7 );
	afEval[8]  = GetReg32( RegAFH_DTH8 );
	afEval[9]  = GetReg32( RegAFH_DTL0 );
	afEval[10] = GetReg32( RegAFH_DTL1 );
	afEval[11] = GetReg32( RegAFH_DTL2 );
	afEval[12] = GetReg32( RegAFH_DTL3 );
	afEval[13] = GetReg32( RegAFH_DTL4 );
	afEval[14] = GetReg32( RegAFH_DTL5 );
	afEval[15] = GetReg32( RegAFH_DTL6 );
	afEval[16] = GetReg32( RegAFH_DTL7 );
	afEval[17] = GetReg32( RegAFH_DTL8 );
	*/

//	for(int i = 0; i < 18 ; i++) {
//		afEval[i] = GetReg32(c_regAFH_DTtbl[i]);
//	}
	afEval[18] = ++count;
}

void AXMPixcessorInt::startIsp() {
	if (0 <= GduBankno) {
		m_pixInt.set_isp_start(SclEnabled[0], SclEnabled[1], SclEnabled[2]);
	}
}

void AXMPixcessorInt::startGdu() {
	m_pixInt.set_gdu_start();
}

void AXMPixcessorInt::switchGduBankNo() {
	// 複雑度
	unsigned int satd = getScalerSatd();

	if (0 <= GduBankno) {
		m_pixInt.switch_gdu_bank_no((unsigned int)GduBankno, satd);
	}
}

unsigned char AXMPixcessorInt::setImageIFOpeMode(unsigned char opemode) {
	// 0:Linearモード以外/1:Linearモード
	// 0,1であれば更新
	if (opemode <= 1) {
		ImageIFOpeMode = opemode;
		ImageIFOpeModeUpd = 1;
	}
	return ImageIFOpeMode;
}

void AXMPixcessorInt::setScalerEnabled(unsigned char ch0_enabled, unsigned char ch1_enabled, unsigned char ch2_enabled) {
	SclEnabled[0] = ch0_enabled;
	SclEnabled[1] = ch1_enabled;
	SclEnabled[2] = ch2_enabled;
}

unsigned int AXMPixcessorInt::getScalerSatd() {
	unsigned int satd = 0;
	m_scl.get_scaler_satd(&satd);
#ifdef PARASOFT_CPPTEST
    satd = 0x03FFFFFF;
#endif  //  PARASOFT_CPPTEST

	return satd;
}

void AXMPixcessorInt::setGduBankno(int bankno) {
	GduBankno = bankno;
}

int AXMPixcessorInt::getGduBankno() {
	return GduBankno;
}

unsigned char AXMPixcessorInt::getImageIFOpeModeUpd() {
	// 値取得で、動作モード変更通知を落とす
	unsigned char ret = ImageIFOpeModeUpd;
	ImageIFOpeModeUpd = 0;
	return ret;
}

unsigned char AXMPixcessorInt::getImageIFOpeMode() {
	return ImageIFOpeMode;
}

extern "C" {

//#include "../../AXMIspTest/DSPCommon.h"
//#include "../../AXMIspTest/reg_isp.h"
//#include "../../AXMIspTest/dram_map.h"
//#include "../../AXMIspTest/adrs_base.h"
//#include "../../AXMIspTest/reg_imageif.h"
//#include "../../AXMIspTest/proc_def_cmos_eval.h"
//#include "../../AXMIspTest/reg_ckg_clk.h"
//#include "../../AXMIspTest/reg_gpio.h"
//#include "../../AXMIspTest/reg_sio.h"
//#include "../../AXMIspTest/reg_audio.h"
//#include "../../AXMIspTest/audio_dsp_com.h"
//#include "../../AXMIspTest/proc_def_imageif_eval.h"
//#include "../../AXMIspTest/proc_def_isp_eval.h"
//#include "../../AXMIspTest/proc_def_intc.h"
#ifdef AX_MAIN
#include "../ExtInter.h"
#endif
}

void AXMPixcessorInt::PixcessorInit() {

#ifndef PARASOFT_CPPTEST
    
#if 0
    //sPrID = xthal_get_prid();
    _xtos_ints_off(0xffffffff); // all interrupt disable
#endif	//	#if 0
    
    //xthal_dcache_all_invalidate();
    //xthal_icache_all_invalidate();
    //xthal_icacheattr(0x22222222);
    //xthal_set_dcacheattr(0x22222122);//ugoku
    //xthal_set_dcacheattr(0x22222112); //ugoku
#if 0
    xthal_set_cacheattr(0x22222222); //all chache oFF !!
#else
#ifndef BB_TMP_PASS	/* 一旦コンパイルを通す用 */
    unsigned int dat = xthal_get_cacheattr();
    xthal_set_cacheattr((dat & 0xFFFFFF0Ful) | 0x00000020);
#endif	//  BB_TMP_PASS
#endif
    
    //xthal_set_dcacheattr(0x11111121);
    //===========================================
    // 512Byte separtate 2 is chache off
    //===========================================
    
    // Register the interrupt handler
    //_xtos_set_interrupt_handler(TIMER0_INT_NUM, timer0Isr);
    //_xtos_set_interrupt_handler(TIMER1_INT_NUM, timer1Isr);
#if 0
    //_xtos_set_interrupt_handler(EXLEVEL_INT_NUM, (void*)exIsr);
    _xtos_set_interrupt_handler(EXLEVEL_INT_NUM, audio_dsp_int_proc);
    _xtos_ints_on(EXLEVEL_INT_MASK);

#ifndef BB_TMP_PASS	/* 一旦コンパイルを通す用 */
    proc_def_int();
#endif	// BB_TMP_PASS
#endif	//	#if 0

#ifndef BB_TMP_PASS	/* 一旦コンパイルを通す用 */
    audio_init_isp_mode();
#endif	// BB_TMP_PASS
#if 0
    audio_dsp_int_enable(AUDIODSP_HOST_INT_BIT        | 
                         AUDIODSP_ISP_SCL_INT_BIT     | 
                         AUDIODSP_IMAGEIF_ISI_INT_BIT | 
                         AUDIODSP_IMAGEIF_MIX_INT_BIT |
			 AUDIODSP_APCKT_INT_BIT);
#endif	//	#if 0

#endif  //  PARASOFT_CPPTEST
}


#ifndef BB_TMP_PASS	/* 一旦コンパイルを通す用 */
// start proc_def_int
// T-Kernel起動時にハンドラ登録を実施（Cソースからのコール）
#ifdef __cplusplus
extern "C" {
#endif
void proc_def_int()
{
// vect0 CPU間通信は、libxt_xtensa内で別途制御する
// vect1
	DRVAPI(drvXInt_addHandler , AUDIODSP_IMAGEIF_ISI_INT_BIT , (DRVXINT_FP_t)recv_imageif_isi_int );
	DRVAPI(drvXInt_setMask , AUDIODSP_IMAGEIF_ISI_INT_BIT );
// vect2
//	DRVAPI(drvXInt_addHandler , AUDIODSP_IMAGEIF_SPU_INT_BIT , (DRVXINT_FP_t)recv_imageif_spu_int );
//	DRVAPI(drvXInt_setMask , AUDIODSP_IMAGEIF_SPU_INT_BIT );
// vect3
	DRVAPI(drvXInt_addHandler , AUDIODSP_IMAGEIF_MIX_INT_BIT , (DRVXINT_FP_t)recv_imageif_mix_int );
	DRVAPI(drvXInt_setMask , AUDIODSP_IMAGEIF_MIX_INT_BIT );
// vect4
//	DRVAPI(drvXInt_addHandler , AUDIODSP_IMAGEIF_DMAW_INT_BIT , (DRVXINT_FP_t)recv_imageif_dmaw_int );
//	DRVAPI(drvXInt_setMask , AUDIODSP_IMAGEIF_DMAW_INT_BIT );
// vect5
//	DRVAPI(drvXInt_addHandler , AUDIODSP_IMAGEIF_DMAR_INT_BIT , (DRVXINT_FP_t)recv_imageif_dmar_int );
//	DRVAPI(drvXInt_setMask , AUDIODSP_IMAGEIF_DMAR_INT_BIT );
// vect6
//	DRVAPI(drvXInt_addHandler , AUDIODSP_ISP_RPU_INT_BIT , (DRVXINT_FP_t)recv_isp_rpu_int );
//	DRVAPI(drvXInt_setMask , AUDIODSP_ISP_RPU_INT_BIT );
// vect7
	DRVAPI(drvXInt_addHandler , AUDIODSP_ISP_SCL_INT_BIT , (DRVXINT_FP_t)recv_isp_scl_int );
	DRVAPI(drvXInt_setMask , AUDIODSP_ISP_SCL_INT_BIT );
// vect8
//	DRVAPI(drvXInt_addHandler , AUDIODSP_ISP_DMAW_INT_BIT , (DRVXINT_FP_t)recv_isp_dmaw_int );
//	DRVAPI(drvXInt_setMask , AUDIODSP_ISP_DMAW_INT_BIT );
// vect9
//	DRVAPI(drvXInt_addHandler , AUDIODSP_ISP_DMAR_INT_BIT , (DRVXINT_FP_t)recv_isp_dmar_int );
//	DRVAPI(drvXInt_setMask , AUDIODSP_ISP_DMAR_INT_BIT );
// vect10
//	DRVAPI(drvXInt_addHandler , AUDIODSP_APCKT_INT_BIT , (DRVXINT_FP_t)recv_gdu_core_int );
//	DRVAPI(drvXInt_setMask , AUDIODSP_APCKT_INT_BIT );
// vect11
//	DRVAPI(drvXInt_addHandler , AUDIODSP_I2C0_INT_BIT , (DRVXINT_FP_t)recv_i2c0_int );
//	DRVAPI(drvXInt_setMask , AUDIODSP_I2C0_INT_BIT );
// vect12
//	DRVAPI(drvXInt_addHandler , AUDIODSP_I2C1_INT_BIT , (DRVXINT_FP_t)recv_i2c1_int );
//	DRVAPI(drvXInt_setMask , AUDIODSP_I2C1_INT_BIT );
}

#ifdef __cplusplus
}
#endif
// end proc_def_int
#endif	// BB_TMP_PASS

