/*
 * AXMIspAdjsut.cpp
 */
#include "../AXMCommon/AXMCommonConfig.hpp"
#include "../AXMCommon/AXMCommonParam.hpp"
#include "../../project/refkit/AXMIspConfig.hpp"
#include "../AXMPixcessor/AXMPixcessor.hpp"
#include "AXHSpec.hpp"
#include "AXMIspAdjust.hpp"
#include "AXMIspAdjustDef.hpp"

#ifndef DISABLE_GAMMA_PROC
#include "AXMIspGamma.hpp"
#include "AXHGamma.hpp"
#include <cstring>
#endif
#ifndef DISABLE_APERTURE_PROC
#include "AXMIspAperture.hpp"
#include "AXHAperture.hpp"
//#include <stdio.h>
#endif

AXMIspAdjust::AXMIspAdjust(AXFObjectName& name) :
	  AXModelActor(name)
	, m_log(name)
	, state(STATE_RUNNING)
	, p_adjustspec(0)
{
	// TODO 自動生成されたコンストラクター・スタブ
    //  設定値保存先アドレスの取得のタイミングの変更のため、
    //  GammaとApertureの初期値は、funcSpecAddr()へ移動

    RGBMatrixInit();                    //  RGBマトリックス設定値保持用変数初期化
    DefectInit();                       //  画素欠陥補正設定値保持用変数初期化
	//  レンズシェーディング補正設定値保持用変数初期化
	LensShadeSettings.regCorrectStart = 0;
	LensShadeSettings.Enabled = 0;
	LensShadeSettings.Pitch = 0;
	LensShadeSettings.Shift = 0;
	//  IRIDIX設定値保持用変数初期化
	IridixSettings.Strength = 0;
	IridixSettings.MinSlope = 0;
	IridixSettings.MaxSlope = 0;
	//  NR設定値保持用変数初期化
	NRSettings.Mode = 0;
	for(UINT i = 0; i < AXH_NR_Main_Max; i++) {
		NRSettings.Main.YTH[i] = 0;
		NRSettings.Main.YIN[i] = 0;
		NRSettings.Main.YLV[i] = 0;
		NRSettings.Main.CTH[i] = 0;
		NRSettings.Main.CIN[i] = 0;
		NRSettings.Main.CLV[i] = 0;
	}
	for(UINT i = 0; i < AXH_NR_Sub_Max; i++) {
		NRSettings.Sub.YTH[i] = 0;
		NRSettings.Sub.YIN[i] = 0;
		NRSettings.Sub.YLV[i] = 0;
		NRSettings.Sub.CTH[i] = 0;
		NRSettings.Sub.CIN[i] = 0;
		NRSettings.Sub.CLV[i] = 0;
	}
	m_scalerSettings.scaling.InImgSize.Width  = 0;
	m_scalerSettings.scaling.InImgSize.Height = 0;
	for(int i = 0; i < SCL_SCALING_CH_CNT; i++) {
		m_scalerSettings.scaling.enabled[i] = 0;
		m_scalerSettings.scaling.OutImgSize[i].Width  = 0;
		m_scalerSettings.scaling.OutImgSize[i].Height = 0;
	}
	for(int i = 0; i < SCL_NEG_FLIP_CH_CNT; i++) {
		m_scalerSettings.flip[i].vFlip = 0;
		m_scalerSettings.flip[i].hFlip = 0;
		m_scalerSettings.neg[i] = 0;
	}
}

AXMIspAdjust::~AXMIspAdjust() {
	// TODO Auto-generated destructor stub
}

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

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

	return ax::AXFACTOR_SUCCESS;
}

ax::actorFuncStatus AXMIspAdjust::onStart() {
    //  設定値保存先アドレスの取得タイミング変更のため、
	//  各種機能の初期化処理は、funcSpecAddr()へ移動

	return ax::AXFACTOR_SUCCESS;
}

ax::actorFuncStatus AXMIspAdjust::onStop() {
	return ax::AXFACTOR_SUCCESS;
}

void AXMIspAdjust::RGBMatrixInit() {
  for(unsigned int i = 0; i < AXH_RGBMatrixSetOut_Max; i++) {
    for(unsigned int j = 0; j < AXH_RGBMatrixSetIn_Max; j++) {
      RGBMatrixSettings.Coef[i][j] = 0x0000u;
    }
    RGBMatrixSettings.Offset[i] = 0x0000u;
  }
}

void AXMIspAdjust::DefectInit() {
  DefectSettings.Mode.External = 0;
  DefectSettings.Mode.AutoCorrect = 0;
  for(unsigned int i = 0; i < AXH_Defect_IntAddr_Max; i++) {
    DefectSettings.Address[i].H = 0;
    DefectSettings.Address[i].V = 0;
    DefectSettings.Address[i].CLS = 0;
  }
  DefectSettings.AutoCorrect.CLS = 0;
  DefectSettings.AutoCorrect.Ave = 0;
  DefectSettings.AutoCorrect.TH_H = 0;
  DefectSettings.AutoCorrect.TH_L = 0;
  for(unsigned int i = 0; i < AXH_Defect_IntAddr_Max; i++) {
    DefectSettings.AutoCorrect.OFST[i] = 0;
  }
  DefectSettings.DetectSet.regStart = 0;
  DefectSettings.DetectSet.AE.ShutterSpeed = 0;
  DefectSettings.DetectSet.AE.Gain = 0;
  DefectSettings.DetectSet.AE.IrisCloseMode = 0;
  DefectSettings.DetectSet.TH = 0;
  DefectSettings.DetectSet.CLS = 0;
  DefectSettings.DetectSet.Priority = 0;
}

void AXMIspAdjust::GammaTableInit() {
#ifndef DISABLE_GAMMA_PROC
	m_gammaCalc.NotifySettings(&m_gammaSettings);
	m_gammaCalc.CreateDefGammaCurve();

	ST_MSG msg;
	msg.data = &m_gammaSettings.setGammaCurvePoint[0];
#ifndef PARASOFT_CPPTEST
	// ガンマ補正カーブ設定
	if (send(namePixessor, AXFEVENT_MODEL(AXMPixcessor::ISP_EVENT_GAMMA_TABLE_SET), &msg, sizeof(ST_MSG)) < 0) {
		SIM_LOG_OUT(AXFLOG_ERR, "fail send Pixcessor ISP_EVENT_GAMMA_TABLE_SET");
	}
#endif  //  PARASOFT_CPPTEST
#endif
//	char str[1000];
//	snprintf(str, sizeof(str), "GammaTableInit %d, %d, %d,... %d\n"
//			, gammaSettings.setGammaCurvePoint[0]
//			, gammaSettings.setGammaCurvePoint[1]
//			, gammaSettings.setGammaCurvePoint[2]
//			, gammaSettings.setGammaCurvePoint[64]
//			);
//	m_log.write(AXFLOG_DEBUG, str);
}

void AXMIspAdjust::ApertureInit() {
#ifndef DISABLE_APERTURE_PROC
	// アパーチャ補正後変調ゲインLUT初期値
	apertureDefaultLutTblSet();
	// 高域・中域ゲイン比率の設定
	apertureOverMidRangeGainRatioSet(m_apertureSettings.midRangeRatio);
	// 正側・負側リミット値の設定
	apertureLimitSet(m_apertureSettings.limitPositive, m_apertureSettings.limitNegative);
	// トータルゲイン調整の設定
	apertureTotalGainSet(m_apertureSettings.totalGain);
	// コアリングしきい値の設定
	apertureCoringSet(m_apertureSettings.coringTh);
#endif
}

void AXMIspAdjust::ChromaInit() {
#ifndef DISABLE_CHROMA_PROC
	// クロマサプレス色ゲイン変調LUT初期値
	chromaLutTblSet();
	//chromaDefaultLutTblSet();

	// エッジクロマサプレス色ゲイン変調LUT初期値
	chromaEdgeLutTblSet();
#endif
}


void AXMIspAdjust::SetLensShade(USHORT cmd)
{
  //  パラメータの演算がないので、
  //   設定値をそのままAXMPixsessorにイベント送信して、レジスタに設定する
  LensShadeSettings = p_adjustspec->LensShade;
  static ST_MSG msg;
  msg.cmd = cmd;
  msg.data = (void *)&LensShadeSettings;
#ifndef PARASOFT_CPPTEST
  if (send(namePixessor, AXFEVENT_MODEL(AXMPixcessor::PIXCESSOR_EVENT_LENS_SHADE_SET), &msg, sizeof(msg)) < 0) {
    m_log.write(AXFLOG_ERR, "fail send Pixcessor PIXCESSOR_EVENT_LENS_SHADE_SET");
  }
#else   //  PARASOFT_CPPTEST
  m_log.write(AXFLOG_ERR, "send Pixcessor PIXCESSOR_EVENT_LENS_SHADE_SET");
#endif  //  PARASOFT_CPPTEST
}


void AXMIspAdjust::SetIridix(USHORT cmd)
{
  //  パラメータの演算がないので、
  //   設定値をそのままAXMPixsessorにイベント送信して、レジスタに設定する
  IridixSettings = p_adjustspec->Iridix;
  static ST_MSG msg;
  msg.cmd = cmd;
  msg.data = (void *)&IridixSettings;
#ifndef PARASOFT_CPPTEST
  if (send(namePixessor, AXFEVENT_MODEL(AXMPixcessor::PIXCESSOR_EVENT_IRIDIX_SET), &msg, sizeof(msg)) < 0) {
    m_log.write(AXFLOG_ERR, "fail send Pixcessor PIXCESSOR_EVENT_IRIDIX_SET");
  }
#else   //  PARASOFT_CPPTEST
  m_log.write(AXFLOG_ERR, "send Pixcessor PIXCESSOR_EVENT_IRIDIX_SET");
#endif  //  PARASOFT_CPPTEST
}

//  NRのON/OFFを行う
void AXMIspAdjust::SetNR(USHORT mode)
{
  //  パラメータの演算がないので、
  //   設定値をそのままAXMPixsessorにイベント送信して、レジスタに設定する
  NRSettings = p_adjustspec->NR;
  static ST_MSG msg;
  msg.cmd = 0;
  msg.data = (void *)&NRSettings;
  if (mode == PTN_NR_ALL) {
    //  一括設定
    msg.cmd |= PTN_NR_ALL;
#ifndef PARASOFT_CPPTEST
    if (send(namePixessor, AXFEVENT_MODEL(AXMPixcessor::PIXCESSOR_EVENT_NR_SET), &msg, sizeof(msg)) < 0) {
      m_log.write(AXFLOG_ERR, "fail send Pixcessor PIXCESSOR_EVENT_NR_SET");
    }
#else   //  PARASOFT_CPPTEST
    m_log.write(AXFLOG_ERR, "send Pixcessor PIXCESSOR_EVENT_NR_SET");
#endif  //  PARASOFT_CPPTEST
  }
  else {
    if(mode & PTN_NR_MODE) {
      //  モードのみ設定
      msg.cmd |= PTN_NR_MODE;
#ifndef PARASOFT_CPPTEST
      if (send(namePixessor, AXFEVENT_MODEL(AXMPixcessor::PIXCESSOR_EVENT_NR_MODE_SET), &msg, sizeof(msg)) < 0) {
        m_log.write(AXFLOG_ERR, "fail send Pixcessor PIXCESSOR_EVENT_NR_MODE_SET");
      }
#else   //  PARASOFT_CPPTEST
      m_log.write(AXFLOG_ERR, "send Pixcessor PIXCESSOR_EVENT_NR_MODE_SET");
#endif  //  PARASOFT_CPPTEST
    }
    if(mode & PTN_NR_MainY) {
      //  MainYのみ設定
       msg.cmd |= PTN_NR_MainY;
#ifndef PARASOFT_CPPTEST
      if (send(namePixessor, AXFEVENT_MODEL(AXMPixcessor::PIXCESSOR_EVENT_NR_MAINY_SET), &msg, sizeof(msg)) < 0) {
        m_log.write(AXFLOG_ERR, "fail send Pixcessor PIXCESSOR_EVENT_NR_MAINY_SET");
      }
#else   //  PARASOFT_CPPTEST
      m_log.write(AXFLOG_ERR, "send Pixcessor PIXCESSOR_EVENT_NR_MAINY_SET");
#endif  //  PARASOFT_CPPTEST
    }
    if(mode & PTN_NR_MainC) {
      //  MainCのみ設定
       msg.cmd |= PTN_NR_MainC;
#ifndef PARASOFT_CPPTEST
      if (send(namePixessor, AXFEVENT_MODEL(AXMPixcessor::PIXCESSOR_EVENT_NR_MAINC_SET), &msg, sizeof(msg)) < 0) {
        m_log.write(AXFLOG_ERR, "fail send Pixcessor PIXCESSOR_EVENT_NR_MAINC_SET");
      }
#else   //  PARASOFT_CPPTEST
      m_log.write(AXFLOG_ERR, "send Pixcessor PIXCESSOR_EVENT_NR_MAINC_SET");
#endif  //  PARASOFT_CPPTEST
    }
    if(mode & PTN_NR_SubY) {
      //  SubYのみ設定
       msg.cmd |= PTN_NR_SubY;
#ifndef PARASOFT_CPPTEST
      if (send(namePixessor, AXFEVENT_MODEL(AXMPixcessor::PIXCESSOR_EVENT_NR_SUBY_SET), &msg, sizeof(msg)) < 0) {
        m_log.write(AXFLOG_ERR, "fail send Pixcessor PIXCESSOR_EVENT_NR_SUBY_SET");
      }
#else   //  PARASOFT_CPPTEST
      m_log.write(AXFLOG_ERR, "send Pixcessor PIXCESSOR_EVENT_NR_SUBY_SET");
#endif  //  PARASOFT_CPPTEST
    }
    if(mode & PTN_NR_SubC) {
      //  SubCのみ設定
       msg.cmd |= PTN_NR_SubC;
#ifndef PARASOFT_CPPTEST
      if (send(namePixessor, AXFEVENT_MODEL(AXMPixcessor::PIXCESSOR_EVENT_NR_SUBC_SET), &msg, sizeof(msg)) < 0) {
        m_log.write(AXFLOG_ERR, "fail send Pixcessor PIXCESSOR_EVENT_NR_SUBC_SET");
      }
#else   //  PARASOFT_CPPTEST
      m_log.write(AXFLOG_ERR, "send Pixcessor PIXCESSOR_EVENT_NR_SUBC_SET");
#endif  //  PARASOFT_CPPTEST
    }
  }
}

//  画素欠陥補正の設定を行う
void AXMIspAdjust::SetDefect(USHORT mode)
{
  //  パラメータの演算がないので、
  //   設定値をそのままAXMPixsessorにイベント送信して、レジスタに設定する
  DefectSettings = p_adjustspec->Defect;
  static ST_MSG msg;
  msg.cmd = 0;
  msg.data = (void *)&DefectSettings;
  if (mode == PTN_DEFECT_ALL) {
    //  一括設定
    msg.cmd |= PTN_DEFECT_ALL;
#ifndef PARASOFT_CPPTEST
    if (send(namePixessor, AXFEVENT_MODEL(AXMPixcessor::PIXCESSOR_EVENT_DEFECT_SET), &msg, sizeof(msg)) < 0) {
      m_log.write(AXFLOG_ERR, "fail send Pixcessor PIXCESSOR_EVENT_DEFECT_SET");
    }
#else   //  PARASOFT_CPPTEST
    m_log.write(AXFLOG_ERR, "send Pixcessor PIXCESSOR_EVENT_DEFECT_SET");
#endif  //  PARASOFT_CPPTEST
  }
  else {
    if(mode & PTN_DEFECT_Mode) {
      //  モードのみ設定
      msg.cmd |= PTN_DEFECT_Mode;
#ifndef PARASOFT_CPPTEST
      if (send(namePixessor, AXFEVENT_MODEL(AXMPixcessor::PIXCESSOR_EVENT_DEFECT_MODE_SET), &msg, sizeof(msg)) < 0) {
        m_log.write(AXFLOG_ERR, "fail send Pixcessor PIXCESSOR_EVENT_DEFECT_MODE_SET");
      }
#else   //  PARASOFT_CPPTEST
      m_log.write(AXFLOG_ERR, "send Pixcessor PIXCESSOR_EVENT_DEFECT_MODE_SET");
#endif  //  PARASOFT_CPPTEST
    }
    if(mode & PTN_DEFECT_Address) {
      //  アドレス設定のみ設定
       msg.cmd |= PTN_DEFECT_Address;
#ifndef PARASOFT_CPPTEST
      if (send(namePixessor, AXFEVENT_MODEL(AXMPixcessor::PIXCESSOR_EVENT_DEFECT_ADDRESS_SET), &msg, sizeof(msg)) < 0) {
        m_log.write(AXFLOG_ERR, "fail send Pixcessor PIXCESSOR_EVENT_DEFECT_ADDRESS_SET");
      }
#else   //  PARASOFT_CPPTEST
      m_log.write(AXFLOG_ERR, "send Pixcessor PIXCESSOR_EVENT_DEFECT_ADDRESS_SET");
#endif  //  PARASOFT_CPPTEST
    }
    if(mode & PTN_DEFECT_AutoSettings) {
      //  自動補正設定のみ設定
       msg.cmd |= PTN_DEFECT_AutoSettings;
#ifndef PARASOFT_CPPTEST
      if (send(namePixessor, AXFEVENT_MODEL(AXMPixcessor::PIXCESSOR_EVENT_DEFECT_AUTO_SET), &msg, sizeof(msg)) < 0) {
        m_log.write(AXFLOG_ERR, "fail send Pixcessor PIXCESSOR_EVENT_DEFECT_AUTO_SET");
      }
#else   //  PARASOFT_CPPTEST
      m_log.write(AXFLOG_ERR, "send Pixcessor PIXCESSOR_EVENT_DEFECT_AUTO_SET");
#endif  //  PARASOFT_CPPTEST
    }
    if(mode & PTN_DEFECT_AutoLevel) {
      //  輝度信号レベルのみ設定
       msg.cmd |= PTN_DEFECT_AutoLevel;
#ifndef PARASOFT_CPPTEST
      if (send(namePixessor, AXFEVENT_MODEL(AXMPixcessor::PIXCESSOR_EVENT_DEFECT_LEVEL_SET), &msg, sizeof(msg)) < 0) {
        m_log.write(AXFLOG_ERR, "fail send Pixcessor PIXCESSOR_EVENT_DEFECT_LEVEL_SET");
      }
#else   //  PARASOFT_CPPTEST
      m_log.write(AXFLOG_ERR, "send Pixcessor PIXCESSOR_EVENT_DEFECT_LEVEL_SET");
#endif  //  PARASOFT_CPPTEST
    }
  }
}

void AXMIspAdjust::SetRGBMatrix()
{
  //  パラメータの演算がないので、
  //   設定値をそのままAXMPixsessorにイベント送信して、レジスタに設定する
  RGBMatrixSettings = p_adjustspec->RGBMatrix;
  static ST_MSG msg;
  msg.data = (void *)&RGBMatrixSettings;
#ifndef PARASOFT_CPPTEST
  if (send(namePixessor, AXFEVENT_MODEL(AXMPixcessor::PIXCESSOR_EVENT_RGB_MATRIX_SET), &msg, sizeof(msg)) < 0) {
    m_log.write(AXFLOG_ERR, "fail send Pixcessor PIXCESSOR_EVENT_RGB_MATRIX_SET");
  }
#else   //  PARASOFT_CPPTEST
  m_log.write(AXFLOG_ERR, "send Pixcessor PIXCESSOR_EVENT_RGB_MATRIX_SET");
#endif  //  PARASOFT_CPPTEST
}
