/**
 * @file       	AXMIspAeAlgorithm.hpp
 * @brief      	AEアルゴリズム演算処理クラス群ヘッダ
 *
 * @par			言語
 *              C++
 */

#ifndef AXMISPAEALGORITHM_HPP_
#define AXMISPAEALGORITHM_HPP_
#include <string>
#include <iostream>
#include <iomanip>
#include "AXMISPtype.hpp"
#include "AXMIspAeValue.hpp"
#include "AXMIspAeSetting.hpp"
#include "AXHSpec.hpp"

   /**
   * @enum  CNTOBJ
   * @brief AE制御対象選択
   */
  enum CNTOBJ {
    CNTOBJ_SHUTSPED = 0,		//!< シャッター制御		※コンパイラ都合によりenumから数値に変更（_ZERO -> 0）
    CNTOBJ_GAIN ,					//!< ゲイン制御
    CNTOBJ_SLOWSHUT ,				//!< スローシャッター制御
    CNTOBJ_IRIS						//!< IRISシャッター制御
   };

   /**
   * @enum  YLVLDISPL
   * @brief Yレベルの変化状況
   */
    enum YLVLDISPL {
      YLVL_UPPER = 0,			//!< 上昇		※コンパイラ都合によりenumから数値に変更（_ZERO -> 0）
      YLVL_UNCHANGE ,				//!< 変化なし
      YLVL_LOWER ,					//!< 下降
     };

   /**
   * @enum  IRIS_THRESHOLD
   * @brief IRIS制御定数
   */
    enum IRIS_THRESHOLD {
    	IRIS_THR_TH1F_OUT =  20,		//!< Th1f 0.002 × 10000
    	IRIS_THR_TH1F_IN  = 200,		//!< Th1f 0.02  × 10000
    	IRIS_THR_TH2F = 1000,		//!< Th2f 0.1  × 10000
		IRIS_THR_CDIF = 1000,		//!< Cdif 0.1  × 10000
    };

   /**
   * @enum  IRIS_CONTVALUE
   * @brief DC-IRIS制御電圧定数
   */
    enum IRIS_CONTVALUE {
    	IRIS_CONT_STOP_UPPER      = 0x88,		//!< 停止範囲上限電圧
    	IRIS_CONT_STOP_LOWER      = 0x78,		//!< 停止範囲下限電圧
		IRIS_CONT_CLOSE_SLOW      = 0xB0,		//!< アイリス閉低速電圧
    	IRIS_CONT_CLOSE_FAST      = 0xFF,		//!< アイリス閉高速電圧
    	IRIS_CONT_OPEN_SLOW       = 0x50,		//!< アイリス開低速電圧
    	IRIS_CONT_OPEN_FAST       = 0x00,		//!< アイリス開高速電圧
    	IRIS_CONT_STOP            = (IRIS_CONT_STOP_UPPER+IRIS_CONT_STOP_LOWER) >> 1,		//!< 停止電圧
    };

   /**
   * @enum  AEBANK
   * @brief AutoWDRでAeDiffログを切り替えるために追加
   */
	enum AEBANK {
		AE_USUAL_BANK = 0,	// AE通常およびAutoWDR短時間露光時に使用
		AE_EXTEND_BANK,		// AutoWDR長時間露光時に使用
		AE_BANK_MAX
	};

#ifdef IMX662
  const static USHORT ExposureTimeLine = 1125;  //!< 露光時間ライン基準数
#elif IMX415
  // IMX415用
  //const static USHORT ExposureTimeLine = 1125;  //!< 露光時間ライン基準数
	const static USHORT ExposureTimeLine = 2250;  //!< 露光時間ライン基準数
#else	// IMX662
  // IMX412
  const static USHORT ExposureTimeLine = 2250;  //!< 露光時間ライン基準数
#endif	// IMX662
  const static LONG  AECONTROLCLIP = 2500L;  	//!< 制御量クリップ
  const static UCHAR IRIS_NO_CHANGE_TIMES = 5;	//!< IRIS 変化なし判定用の規定時間
  const static UCHAR IRIS_NO_CHANGE_TIMES_WDR = 15;	//!< IRIS 変化なし判定用の規定時間(WDR)
  const static int cnvGainLinear[11] = {
										1 , // gain  0.0dB 〜  2.9dB	 0dB
										2 , // gain  3.0dB 〜  8.9dB	 6dB
										4 , // gain  9.0dB 〜 14.9dB	12dB
										8 , // gain 15.0dB 〜 20.9dB	18dB
									   16 , // gain 21.0dB 〜 26.9dB	24dB
									   32 , // gain 27.0dB 〜 32.9dB	30dB
									   64 , // gain 34.0dB 〜 38.9dB	36dB
									  128 , // gain 40.0dB 〜 44.9dB	42dB
									  256 , // gain 46.0dB 〜 50.9dB	48dB
									  512 , // gain 52.0dB 〜 56.9dB	54dB
									 1024   // gain 58.0dB 〜 62.9dB	60dB
  };

/**
 * @class  AXMIspAeBase
 * @brief  AEアルゴリズム基本クラス
 *
 * @n
 */
#if 1	// doc err
class AXMIspAeBase {
#ifdef AXM_ISP_CT_AE
  friend class AXMIspCTAe;
#endif
 public:
#if 1	// doc err
  /**
   * @brief  オブジェクトを初期化する
   *
   * @n
   */
  AXMIspAeBase();
  /**
   * @brief  オブジェクトを開放する
   *
   * @n
   */
  virtual ~AXMIspAeBase();
  /**
   * @brief       AE設定情報通知
   *
   * @n *ptrAeSettingRef	AE設定情報クラスへのポインタを記憶
   * @param      [in]    obj	AE設定情報クラスへのポインタ
   */
  void notifyAeAlgorithm(AXMIspAeSetting *obj);
  /**
   * @brief       偏差計算
   *
   * @n			
   * @param [in]    aeBank	AutoWDR時は短時間露光と長時間露光で偏差を別に持つのでバンクを指定する。通常は１バンクのみ
   */
  void CalcAeDiff(AEBANK aeBank);  // note 2014/08/28「不感帯の処理」と「安定化処理」の順番が逆になっていたので修正
  /**
   * @brief       AE制御量計算
   *
   * @n			
   */
  void CalcAeControlValue(void);
  /**
   * @brief       AE制御対象選択
   *
   * @n
   * @n プログラム線図判定
   * @n 制御対象(シャッタースピード/ゲイン/低速シャッタースピード/アイリス)選択
   */
  void SelectControlObject(void);
  /**
   * @brief       AE制御量決定
   *
   * @n			
   * @param      [in,out]    controlExposure	デバイスドライバに渡す制御情報
   */
  void DecideControlValue(AXMIspAeControlExposure *controlExposure);
  /**
   * @brief       明るさ計算
   *
   * @n			
   * @param      [in,out]    controlExposure	デバイスドライバに渡す制御情報
   * @param      [in,out]    execFromAeToIsp	ISPに渡す情報（WDR、明るさ）
   */
  void CalcLuminanceValue(AXMIspAeControlExposure *controlExposure , ST_FROM_AE_TO_ISP *execFromAeToIsp);
  /**
   * @brief       露光時間計算
   *
   * @n			
   * @param       [in,out]    controlExposure	デバイスドライバに渡す制御情報
   */
  void CalcExposureTime(AXMIspAeControlExposure *controlExposure);
  /**
   * @brief       イメージセンサーゲイン計算
   *
   * @n			
   * @param       [in,out]    controlExposure	デバイスドライバに渡す制御情報
   */
  void CalcImageSensorGain(AXMIspAeControlExposure *controlExposure);
  /**
   * @brief       ISPゲイン計算
   *
   * @n			
   */
  void CalcISPGain(void);
  /**
   * @brief       概略アイリス値管理
   *
   * @n			
   * @param  [in,out]    controlExposure	デバイスドライバに渡す制御情報
   */
  void ManageRoughIrisValue(AXMIspAeControlExposure *controlExposure);
  /**
   * @brief       アイリス作動領域内外判定
   *
   * @n			
   * @param  [in,out]    controlExposure	デバイスドライバに渡す制御情報
   * @param  [in]    isWdrMode	false: Lineaモード true: WDRモード
   */
#ifdef MECHA_IRIS
  void JudgeIrisRegion(AXMIspAeControlExposure *controlExposure, bool isWdrMode);
#endif
	/**
   * @brief   10000除算
   *
   * @n
   * @param   [in]    dividend 被除数
   * @return  被除数/10000の結果
   */
  ULONG divBy10000(ULONG dividend);

  /**
   * @brief 	Ｙレベル変位方向
   *
   * @retval YLVL_UPPER	  上方向
   * @retval YLVL_UNCHANGE 変位なし
   * @retval YLVL_LOWER    下方向
   */
  YLVLDISPL getYLevelChangeDirection(void);
#endif	// doc err
#if 1	// doc err

  /**
   * @brief 	シャッタースピード下限判定
   *
   * @n			
   * @retval  true 下限超えた
   * @retval  false 範囲内
   */
  bool isShutterLowerLimit(void);
  /**
   * @brief 	シャッタースピード上限判定
   *
   * @n			
   * @retval   true 上限超えた
   * @retval   false 範囲内
   */
  bool isShutterUpperLimit(void);
  /**
   * @brief 	ゲイン下限判定
   *
   * @n			
   * @retval   true 下限超えた
   * @retval   false 範囲内
   */
  bool isGainLowerLimit(void);
  /**
   * @brief 	ゲイン上限判定
   *
   * @n			
   * @retval   true 上限超えた
   * @retval   false 範囲内
   */
  bool isGainUpperLimit(void);
  /**
   * @brief 	スローシャッター下限判定
   *
   * @n			
   * @retval    true 下限超えた
   * @retval    false 範囲内
   */
  bool isSlowShutterLowerLimit(void);
  /**
   * @brief 	スローシャッター上限判定
   *
   * @n			
   * @retval    true 上限超えた
   * @retval    false 範囲内
   */
  bool isSlowShutterUpperLimit(void);
  /**
   * @brief 	アイリス下限判定
   *
   * @n			
   * @retval    true 下限超えた
   * @retval    false 範囲内
   */
  bool isIrisUpperLimit(void);
  /**
   * @brief 	アイリス上限判定
   *
   * @n			
   * @retval    true 上限超えた
   * @retval    false 範囲内
   */
  bool isIrisLowerLimit(void);
  /**
   * @brief 	アイリス強制オープン
   *
   * @param   [in,out]    controlExposure	デバイスドライバに渡す制御情報
   */
  void forceIrisOpen(AXMIspAeControlExposure *controlExposure);
  /**
   * @brief 	AE制御対象選択サブルーチン
   *
   * @n			
   * @param   [in]    currobj  現在の選択中のオブジェクト
   * @param   [in]    dir   現在の変移方向
   * @param   [in]    slowshut   スローシャッター有効/無効
   * @param   [in]    irisflag   アイリス有効/無効
   * @param   [in]    priSlowGain	スローシャッター/ゲインの優先度
   * @param   [in]    ssOnly	シャッター制御のみ
   * @retval  CNTOBJ	  次に選択するオブジェクト\n
   * @n (irisflag == true) && (slowshut == true) && (priSlowGain == true)\n
   * @n 1)アイリス制御→シャッタースピード制御→低速シャッタースピード→ゲイン制御\n
   * @n (irisflag == true) && (slowshut == true) && (priSlowGain == false)\n
   * @n 2)アイリス制御→シャッタースピード制御→ゲイン制御→低速シャッタースピード\n
   * @n (irisflag == false) && (slowshut == true) && (priSlowGain == true)\n
   * @n 3)シャッタースピード制御→低速シャッタースピード→ゲイン制御\n
   * @n (irisflag == false) && (slowshut == true) && (priSlowGain == false)\n
   * @n 4)シャッタースピード制御→ゲイン制御→低速シャッタースピード\n
   * @n (irisflag == false) && (slowshut == false)\n
   * @n 5)シャッタースピード制御→ゲイン制御\n
   * @n Y level lower ←  dir ⇒ Y level upper
   */
   CNTOBJ selectSubr(CNTOBJ currobj , YLVLDISPL dir , bool slowshut , bool irisflag , bool priSlowGain , bool ssOnly);
  /**
   * @brief 	シャッタースピード制御
   *
   * @n			
   * @param   [in]	currobj	現在制御情報
   * @param   [in]	dir	増減情報
   * @param   [in]	slowshut	スローシャッター情報
   * @param   [in]	irisflag	アイリス情報
   * @param   [in]	priSlowGain	ゲイン/スローシャッター優先度
   * @param   [in]	ssOnly	シャッター制御のみ
   * @retval  CNTOBJ	  次に選択するオブジェクト
   */
   CNTOBJ selectSubr_Shutter(CNTOBJ currobj, YLVLDISPL dir, bool slowshut, bool irisflag, bool priSlowGain, bool ssOnly);
  /**
   * @brief 	ゲイン制御
   *
   * @n			
   * @param   [in]	currobj	現在制御情報
   * @param   [in]	dir	増減情報
   * @param   [in]	slowshut	スローシャッター情報
   * @param   [in]	irisflag	アイリス情報
   * @param   [in]	priSlowGain	ゲイン/スローシャッター優先度
   * @param   [in]	ssOnly	シャッター制御のみ
   * @retval  CNTOBJ	  次に選択するオブジェクト
   */
   CNTOBJ selectSubr_Gain(CNTOBJ currobj, YLVLDISPL dir, bool slowshut, bool irisflag, bool priSlowGain, bool ssOnly);
  /**
   * @brief 	スローシャッター制御
   *
   * @n			
   * @param   [in]	currobj	現在制御情報
   * @param   [in]	dir	増減情報
   * @param   [in]	slowshut	スローシャッター情報
   * @param   [in]	irisflag	アイリス情報
   * @param   [in]	priSlowGain	ゲイン/スローシャッター優先度
   * @param   [in]	ssOnly	シャッター制御のみ
   * @retval  CNTOBJ	  次に選択するオブジェクト
   */
   CNTOBJ selectSubr_SlowShutter(CNTOBJ currobj, YLVLDISPL dir, bool slowshut, bool irisflag, bool priSlowGain, bool ssOnly);
  /**
   * @brief 	アイリス制御
   *
   * @n			
   * @param   [in]	currobj	現在制御情報
   * @param   [in]	dir	増減情報
   * @param   [in]	slowshut	スローシャッター情報
   * @param   [in]	irisflag	アイリス情報
   * @param   [in]	priSlowGain	ゲイン/スローシャッター優先度
   * @param   [in]	ssOnly	シャッター制御のみ
   * @retval  CNTOBJ	  次に選択するオブジェクト
   */
   CNTOBJ selectSubr_Iris(CNTOBJ currobj, YLVLDISPL dir, bool slowshut, bool irisflag, bool priSlowGain, bool ssOnly);

#if 1	// doc err

 protected:
  AXMIspAeValue AeDiff;
  struct _aeDiffLog_ {
	  AXMIspAeValue AeDiffLog[4];
	  UCHAR AeDiffLogFlag;
	  UCHAR AeDiffFrameNo;
  } st_AeDiff[AE_BANK_MAX];
  AXMIspAeValue DeadZoneThreshold;
  ULONG ControlValueExposureTime;
  ULONG ControlValueGain;
#ifdef MECHA_IRIS
  ULONG ControlValueIris;
#endif
  ULONG AbsoluteLuminanceValue;
  ULONG ExposureTime;
  ULONG GainSensor;
  ULONG GainISP;
#ifdef MECHA_IRIS
  ULONG RoughIrisValue;
  ULONG FlagIrisRegion;
  UCHAR	irisNoChangeFrameCnt;
#endif

    unsigned int shutterSpeed;
    unsigned int gain;
    unsigned int irisCntl;
    unsigned int slowShutter;
    bool noChangeControl	;
    bool outOfLimit;
	
	CNTOBJ ControlObject;
#endif	// doc err

 public:
  AXMIspAeSetting *ptrAeSettingRef;
  LONG AeControlValue;	// AeDiff / AeSpeed
  std::string TAG;
  AXMIspAeValue OpdYAve;			// AE評価データ　12bit(整数部8bit,小数1桁4bit)
	
 public:
  const static ULONG GAINMAX = 255;   // イメージセンサのgainレジスタ8bitの最大値
  const static ULONG ExposureMax = 0x0001FFFF;   // イメージセンサのshutレジスタ8bitの最大値

  ULONG beforeExposureTime;				// 露光時間
  ULONG beforeExposureGain;      // 前回のGain

    ULONG shutterSpeedLower;
    ULONG shutterSpeedUpper;
    ULONG gainLower;
    ULONG gainUpper;
    ULONG slowShutterLower;
    ULONG slowShutterUpper;
    ULONG irisUpper;
    ULONG irisLower;
// WDR実装時に追加
	AXMIspAeValue AeTarget;
	ULONG ExposureRatio;
	USHORT forceIrisOpenCnt;
	UCHAR dayNightMode;
	USHORT dayNightCount;

#ifdef PARASOFT_CPPTEST
 public:
  /**
   * @brief       アイリス制御量計算C++テスト用スタブ
   *
   * @n
   * @param       [in]   currentAeDiffFrameNo	現在の差分格納位置
   * @param       [in]   beforeAeDiffFrameNo	前回の差分格納位置
   */
  void setIrisValueFrame(SHORT currentAeDiffFrameNo , SHORT beforeAeDiffFrameNo);
  /**
   * @brief       アイリス制御量計算C++テスト用スタブ
   *
   * @n
   * @param       [in]    currentAeDiff    現在の差分
   * @param       [in]    beforeAeDiff     前回の差分
   */
  void setIrisValueDiff(LONG currentAeDiff , LONG beforeAeDiff);
  /**
   * @brief       アイリス制御量計算C++テスト用スタブ
   *
   * @n
   * @param       [in]    absIdif	差の時間変化
   */
  void setIrisValueAbsDiff(LONG absIdif);
  /**
   * @brief       アイリス制御量計算C++テスト用スタブ
   *
   * @n
   * @param       [in]    absTh1	停止と低速動作の閾値
   * @param       [in]    absTh2	低速動作と高速動作の閾値
   */
  void setIrisValue(LONG absTh1 , LONG absTh2 );
	LONG	result[8];
	LONG absTh1;
	LONG absTh2;
	SHORT currentAeDiffFrameNo;
	SHORT beforeAeDiffFrameNo;
	LONG currentAeDiff;
	LONG beforeAeDiff;
	LONG absIdif;
#endif	// PARASOFT_CPPTEST
#endif	// doc err

};
#endif	// doc err

/**
 * @var          PhotometPre1
 * @brief        AE測光パターンプリセットデータ
 *
 * @n			
 */

// 今回OPDサイズが変更されるため各重点の配列内容も変更する
/* 中央重点 */
const static UCHAR PhotometPre1[PHOTOMET_MAX] = {
/*  1   2   3   4   5   6   7   8   9  10 */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*  1 */
1, 1, 2, 2, 2, 2, 2, 2, 1, 1, /*  2 */
1, 1, 2, 3, 3, 3, 3, 2, 1, 1, /*  3 */
1, 1, 2, 2, 2, 2, 2, 2, 1, 1, /*  4 */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*  5 */
};

/* 中央下重点 */
const static UCHAR PhotometPre2[PHOTOMET_MAX] = {
/*  1   2   3   4   5   6   7   8   9  10 */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*  1 */
1, 1, 2, 2, 2, 2, 2, 2, 1, 1, /*  2 */
1, 1, 2, 3, 3, 3, 3, 2, 1, 1, /*  3 */
1, 1, 2, 3, 3, 3, 3, 2, 1, 1, /*  4 */
1, 1, 2, 3, 3, 3, 3, 2, 1, 1, /*  5 */
};

/* 右重点 */
const static UCHAR PhotometPre3[PHOTOMET_MAX] = {
/*  1   2   3   4   5   6   7   8   9  10 */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*  1 */
1, 1, 1, 1, 2, 2, 2, 2, 2, 2, /*  2 */
1, 1, 1, 1, 2, 3, 3, 3, 3, 2, /*  3 */
1, 1, 1, 1, 2, 2, 2, 2, 2, 2, /*  4 */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*  5 */
};

/* 左重点 */
const static UCHAR PhotometPre4[PHOTOMET_MAX] = {
/*  1   2   3   4   5   6   7   8   9  10 */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*  1 */
2, 2, 2, 2, 2, 2, 1, 1, 1, 1, /*  2 */
2, 3, 3, 3, 3, 2, 1, 1, 1, 1, /*  3 */
2, 2, 2, 2, 2, 2, 1, 1, 1, 1, /*  4 */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*  5 */
};

/**
 * @class  AXMispAeWeightOPD
 * @brief  AE通常処理OPD重み付けクラス
 *
 * @n			
 */
class AXMispAeWeightOPD : public AXMIspAeBase {
 private:

 public:
  /**
   * @brief  オブジェクトを初期化する
   *
   * @n
   */
  AXMispAeWeightOPD();
  /**
   * @brief  オブジェクトを開放する
   *
   * @n
   */
  virtual ~AXMispAeWeightOPD();
  /**
   * @brief 	OPD重み付け
   *
   * @n			
   * @param   [in]    array[]			OPDデータ
   */
  void WeightOPD(const UCHAR array[]);
  /**
   * @brief    OPD平均計算
   *
   * @n			
   */
  void CalcAverageOPD(void);
 public:
  USHORT OpdYWeighted[PHOTOMET_MAX];	//< OPDデータのYデータに測光パターンで重み付けしたデータを格納する(12bit)
  USHORT addCounter;					//< 重み付け後の積算用カウント値(4bit)
  UCHAR OpdY[PHOTOMET_MAX];				//< OPDデータからYデータを取り出して格納する(8bit)

};

#define HISTMAX 18
/**
 * @struct  ST_HISTSECT
 * @brief   ヒストグラム区間設定用構造体定義
 */
typedef struct _histogramSection_ {
	SHORT bin ;			// bin
	SHORT center;		// 中心
	SHORT lower;		// 下限
	SHORT upper;		// 上限
	SHORT width;		// 幅
	SHORT weight;		// 重み付け
} ST_HISTSECT;

/**
 * @enum   HIST_PEAK_VALLEY
 * @brief  ヒストグラムの山谷識別用構定義
 */
enum HIST_PEAK_VALLEY {
	HIST_PV_OTHER = 0,
	HIST_PEAK,
	HIST_VALLEY
};

/**
 * @enum   HIST_PEAK_VALLEY
 * @brief  ヒストグラムの山谷走査用定義
 */
enum EVAL_PEAK_VALLEY {
	EVAL_FLAT = 0,				// 初期値は平ら
	EVAL_UPPER ,				// 上昇
	EVAL_FLAT_AFTER_UPPER , 	// 上昇の後の平ら
	EVAL_LOWER ,				// 下降
	EVAL_FLAT_AFTER_LOWER 		// 下降の後の平ら
};

/**
 * @struct  ST_HISTOGRAM
 *
 * @brief   ヒストグラム計算用構造体定義
 */
typedef struct _histogram_ {
	SHORT bin ;			// bin
	SHORT frequency;	// 度数
	LONG weighted;		// 重み付け後
	HIST_PEAK_VALLEY pv_flag;	// 山 or 谷
	EVAL_PEAK_VALLEY eval;
} ST_HISTOGRAM;

static const ST_HISTOGRAM initHistStruct = { 0 };

/**
 * @var   histSect
 * @brief ヒストグラム区間設定定数定義
 *
 * @n     重み付けは少数第２位まで表すため100倍した整数を設定する
 */
static const ST_HISTSECT histSect[HISTMAX] = {	
	{  1,	224,	192,	255,	64,	250	} ,		// 重み付け 2.5  × 100 ＝ 250
	{  2,	192,	160,	223,	64,	200	} ,		// 重み付け 2    × 100 ＝ 200
	{  3,	160,	128,	191,	64,	150	} ,		// 重み付け 1.5  × 100 ＝ 150
	{  4,	128,	112,	143,	32,	275	} ,		// 重み付け 2.75 × 100 ＝ 275
	{  5,	112,	 96,	127,	32,	250	} ,		// 重み付け 2.5  × 100 ＝ 250
	{  6,	 96,	 80,	111,	32,	225	} ,		// 重み付け 2.25 × 100 ＝ 225
	{  7,	 80,	 64,	 95,	32,	175	} ,		// 重み付け 1.75 × 100 ＝ 175
	{  8,	 64,	 56,	 71,	16,	300	} ,		// 重み付け 3    × 100 ＝ 300
	{  9,	 56,	 48,	 63,	16,	250	} ,		// 重み付け 2.5  × 100 ＝ 250
	{ 10,	 48,	 40,	 55,	16,	225	} ,		// 重み付け 2.25 × 100 ＝ 225
	{ 11,	 40,	 32,	 47,	16,	175	} ,		// 重み付け 1.75 × 100 ＝ 175
	{ 12,	 32,	 24,	 39,	16,	150	} ,		// 重み付け 1.5  × 100 ＝ 150
	{ 13,	 24,	 20,	 27,	 8,	225	} ,		// 重み付け 2.25 × 100 ＝ 225
	{ 14,	 20,	 16,	 23,	 8,	200	} ,		// 重み付け 2    × 100 ＝ 200
	{ 15,	 16,	 12,	 19,	 8,	150	} ,		// 重み付け 1.5  × 100 ＝ 150
	{ 16,	 12,	  8,	 15,	 8,	100	} ,		// 重み付け 1    × 100 ＝ 100
	{ 17,	  8,	  4,	 11,	 8,	 75	} ,		// 重み付け 0.75 × 100 ＝  75
	{ 18,	  4,	  1,	  7,	 8,	 50	} ,		// 重み付け 0.5  × 100 ＝  50
};

#define HIST_SUIT_THRESH 90				//90は実質無効//!< ヒストグラム補正に相応しい最低度数の閾値定義 7〜10
#define HIST_DIV_POINT_START (7-1)		//!< 分割ポイントを探すbinの開始点
#define HIST_DIV_POINT_END  (18-1)			//!< 分割ポイントを探すbinの終了点
#define HIST_CORRECT_STRENGTH 5			// 補正強度　（デフォルト5 最大10）
#define HIST_DIV_LOG_MAX 4
#define W_AVE_LOG_MAX 4
#if 1	// doc err

/**
 * @class AXMIspAeHistogramBase
 * @brief AEヒストグラム分割基本クラス
 *
 * @n			
 */
class AXMIspAeHistogramBase : public AXMIspAeBase {
 public:
  /**
   * @brief  オブジェクトを初期化する
   *
   * @n
   */
  AXMIspAeHistogramBase();
  /**
   * @brief  オブジェクトを開放する
   *
   * @n
   */
  virtual ~AXMIspAeHistogramBase();
  /**
   * @brief ヒストグラム計算
   *
   * @n			
   * @param [in]    array[]  OPDデータ
   */
  void CalcHistogram(const UCHAR array[]);
  /**
   * @brief ヒストグラム分割処理
   *
   * @n			
   */
  void DivHistogram(void);
  /**
   * @brief 低輝度エリアOPD平均
   *
   * @n			
   * @param [in]    array[]  OPDデータ
   */
  void CalcAverageLowLumiAreaOPD(const UCHAR array[]);
  /**
   * @brief 高輝度エリアOPD平均
   *
   * @n			
   * @param [in]    array[]  OPDデータ
   */
  void CalcAverageHighLumiAreaOPD(const UCHAR array[]);

 protected:
  void initHistogram(void);
  void setHistogramSect(UCHAR Ylevel);
  SHORT getHistogramValue(UCHAR Ylevel);

  ST_HISTOGRAM Histogram[HISTMAX];
  LONG OpdYLowLumiAreaAve;
  LONG OpdYHighLumiAreaAve;
  LONG NonMainObjectAreaWeight;
  LONG histDivPoint;					// 分割ポイント
  LONG histDivFrequency;
  LONG OpdYAllTotal;
  LONG OpdYAllCount;
  SHORT histDivLogNo;
  CHAR histDivLogFlag;
  CHAR histDivLog[HIST_DIV_LOG_MAX];
  SHORT w_aveLogNo;
  CHAR w_aveLogFlag;
  LONG w_aveLog[W_AVE_LOG_MAX];

};
#endif	// doc err

#if 1	// doc err

/**
 * @class AXMIspAeAutoBLFLCHistogram
 * @brief AEヒストグラム分割逆光補正/過順光補正処理クラス
 *
 * @n			
 */
class AXMIspAeAutoBLFLCHistogram : public AXMIspAeHistogramBase {
 public:
  /**
   * @brief  オブジェクトを初期化する
   *
   * @n
   */
  AXMIspAeAutoBLFLCHistogram();
  /**
   * @brief  オブジェクトを開放する
   *
   * @n
   */
  virtual ~AXMIspAeAutoBLFLCHistogram();
  /**
   * @brief 全体平均計算
   *
   * @n			
   */
  void CalcAverageALLHist(void);

 private:
  UCHAR SelectBL_CorFLC;

};
#endif	// doc err
#if 1	// doc err
/**
 * @class AXMIspAEAutoBLFLCMainObject
 * @brief AE主要被写体指定逆光/過順光補正処理クラス
 *
 * @n			
 */
class AXMIspAEAutoBLFLCMainObject : public AXMIspAeBase {
 public:
  /**
   * @brief  オブジェクトを初期化する
   *
   * @n
   */
  AXMIspAEAutoBLFLCMainObject();
  /**
   * @brief  オブジェクトを開放する
   *
   * @n
   */
  virtual ~AXMIspAEAutoBLFLCMainObject();
  /**
   * @brief 	主要被写体エリアOPD平均
   *
   * @n			
   * @param   [in]    array[]			OPDデータ
   */
  void CalcAverageMainObjectOPD(const UCHAR array[]);
  /**
   * @brief 	非主要被写体エリアOPD平均
   *
   * @n			
   * @param   [in]    array[]			OPDデータ
   */
  void CalcAverageNonMainObjectOPD(const UCHAR array[]);
  /**
   * @brief 	非主要被写体重み付け
   *
   * @n			
   */
  void WeightNonMainObjectArea(void);
  /**
   * @brief 	全体平均計算
   *
   * @n			
   */
  void CalcAverageALL(void);

  static const ULONG MAIN_OBJECT_GAIN   =  5;	// 0.5 を10倍した値
  static const ULONG MAIN_OBJECT_OFFSET = 20;	// 2 を10倍した値
 public:
  ULONG OpdYNonMainObjectAve;		// OtherLv
  ULONG OpdYMainObjectAve;			// MainLv
  ULONG NonMainObjectAreaWeight;	// Weight

};
#endif	// doc err
#if 1	// doc err
/**
 * @class AXMIspAeExposureRatioWDRMode
 * @brief 親クラス AE通常処理OPD重み付けクラス
 *
 * @n			
 */
#ifdef WDR
class AXMIspAeExposureRatioWDRMode : public AXMispAeWeightOPD {
private:
	unsigned int wdrShutterSpeed;

 public:
  /**
   * @brief  オブジェクトを初期化する
   *
   * @n
   */
  AXMIspAeExposureRatioWDRMode();
  /**
   * @brief  オブジェクトを開放する
   *
   * @n
   */
  virtual ~AXMIspAeExposureRatioWDRMode();
  /**
   * @brief      AE設定情報通知
   *
   * @n *ptrAeSettingRef	AE設定情報クラスへのポインタを記憶
   * @param      [in]    obj	AE設定情報クラスへのポインタ
   */
  void notifyAeAlgorithm(AXMIspAeSetting *obj);
  /**
   * @brief      WDR露光時間計算
   *
   * @n	制御量から(1/32000s×露光比率)1/32000sの範囲でWDR短時間露光のシャッタースピードを計算する
   * @param      [in,out]    controlExposure	デバイスドライバに渡す制御情報
   */
  void CalcWDRShortExposureTime(AXMIspAeControlExposure *controlExposure);
  /**
   * @brief      WDR短時間露光制御量決定
   *
   * @n			
   * @param      [in,out]    controlExposure	デバイスドライバに渡す制御情報
   */
  void DecideWDRShortControlValue(AXMIspAeControlExposure *controlExposure);
  /**
   * @brief      WDR長時間露光制御量決定
   *
   * @n			
   * @param      [in,out]    controlExposure	デバイスドライバに渡す制御情報
   */
  void DecideWDRLongControlValue(AXMIspAeControlExposure *controlExposure);
  /**
   * @brief      WDR明るさ計算
   *
   * @n			
   * @param      [in,out]    controlExposure	デバイスドライバに渡す制御情報
   * @param      [out]       execFromAeToIsp	ISPに渡す制御情報
   */
  void WDRCalcLuminanceValue(AXMIspAeControlExposure *controlExposure , ST_FROM_AE_TO_ISP *execFromAeToIsp);
};
#endif
#endif	// doc err
#if 1	// doc err

/**
 * @class AXMIspAeAutoWDR
 * @brief 親クラス  AEヒストグラム分割基本クラス
 *
 * @n			
 */
#ifdef WDR
class AXMIspAeAutoWDR : public AXMIspAeHistogramBase {
 public:
  /**
   * @brief  オブジェクトを初期化する
   *
   * @n
   */
  AXMIspAeAutoWDR();
  /**
   * @brief  オブジェクトを開放する
   *
   * @n
   */
  virtual ~AXMIspAeAutoWDR();
  /**
   * @brief      AE設定情報通知
   *
   * @n *ptrAeSettingRef	AE設定情報クラスへのポインタを記憶
   * @param      [in]    obj	AE設定情報クラスへのポインタ
   */
  void notifyAeAlgorithm(AXMIspAeSetting *obj);
  /**
   * @brief      AutoWDR短時間露光の目標値設定
   *
   * @n
   */
  void SetAutoWDRShortTarget(void);
  /**
   * @brief      AutoWDR長時間露光の目標値設定
   *
   * @n
   */
  void SetAutoWDRLongTarget(void);
  /**
   * @brief      AutoWDR短時間露光の平均計算
   *
   * @n
   * @param      [in,out]    controlExposure	デバイスドライバに渡す制御情報
   */
  void CalcAutoWDRShortAverage(AXMIspAeControlExposure *controlExposure);
  /**
   * @brief      AutoWDR長時間露光の平均計算
   *
   * @n
   * @param      [in,out]    controlExposure	デバイスドライバに渡す制御情報
   */
  void CalcAutoWDRLongAverage(AXMIspAeControlExposure *controlExposure);
  /**
   * @brief       AutoWDR露光時間計算
   *
   * @n
   * @param      [in,out]   controlExposure     デバイスドライバに渡す制御情報
   * @param      [in,out]   beforeExposureTime  前回露光時間
   */
  void CalcAutoWDRExposureTime(AXMIspAeControlExposure *controlExposure , ULONG *beforeExposureTime);
  /**
   * @brief      AutoWDR短時間露光制御量決定
   *
   * @n
   * @param      [in,out]   controlExposure	デバイスドライバに渡す制御情報
   */
  void DecideAutoWDRShortControlValue(AXMIspAeControlExposure *controlExposure);
  /**
   * @brief      AutoWDR長時間露光制御量決定
   *
   * @n
   * @param      [in,out]   controlExposure	デバイスドライバに渡す制御情報
   */
  void DecideAutoWDRLongControlValue(AXMIspAeControlExposure *controlExposure);

 private:
	unsigned int wdrShutterSpeed;

  UCHAR SelectBL_CorFLC;
	unsigned int wdrShortShutterSpeed;
	unsigned int wdrLongShutterSpeed;
	ULONG beforeShortExposureTime;				// 露光時間
    ULONG beforeLongExposureTime;				// 露光時間
	USHORT newRatio;

};
#endif
#endif // doc err
#endif /* AXMISPAEALGORITHM_HPP_ */
