/*
 * @file   AXHOpdDataAE.cpp
 * @brief  Source file of OPD Data for AE class.
 * @par    Programming Language
 *         C++
 */

#include "AXHOpdDataAE.hpp"
#include "AXHOpdCommon.hpp"
#include "AXHRegAddr.hpp"

AXHOpdDataAE::AXHOpdDataAE() {
}

AXHOpdDataAE::~AXHOpdDataAE() {
}

unsigned char* AXHOpdDataAE::getOpdData(int cmd) {
#ifdef CNV_BYER_TO_OPD
	// ベイヤデータ取得後OPD変換
	return cnvBayerToOpd();
#else
  if(cmd == AXH_Cmd_Get_Opd_AE1_1) {
	//  AE 長時間画像1用格納先アドレス取得
    return (unsigned char*)AXH_SPAD_OFST_IMG_AE1_1;
  }
  else if(cmd == AXH_Cmd_Get_Opd_AE1_0) {
	//  AE 長時間画像0用格納先アドレス取得
    return (unsigned char*)AXH_SPAD_OFST_IMG_AE1_0;
  }
  else if(cmd == AXH_Cmd_Get_Opd_AE0_1) {
	//  AE 短時間画像1用格納先アドレス取得
    return (unsigned char*)AXH_SPAD_OFST_IMG_AE0_1;
  }
  else {
    //  AE 短時間画像0用格納先アドレス取得
    return (unsigned char*)AXH_SPAD_OFST_IMG_AE0_0;
  }
#endif	
}

#ifdef CNV_BYER_TO_OPD
unsigned char* AXHOpdDataAE::cnvBayerToOpd(void) {
	// ベイヤーデータ取得しOPD変換し格納
	// OPDはベイヤデータ4x4の平均値を変換
	for (UInt32 yc = 0, byc= 0; yc < BAYER_ROW; yc+=4, byc++) {
		for (UInt32 xc = 0, bxc= 0; xc < BAYER_COL; xc+=4, bxc++) {
			ST_BAYER_TYPE_I Bayer = {0, 0, 0, 0};
			
			// 配列を持っても良いがRAM削減のためループを回す
			for (UInt32 yc2 = yc; yc2 < (yc + 4); yc2++) {
				for (UInt32 xc2 = xc; xc2 < (xc + 4); xc2++) {
					UInt32 bayer_gr_r = GetReg32(AXH_SPAD_OFST_IMG_AE0_0 + (xc2 * 8)  + (yc2 * BAYER_COL * 8));			// GR,R取得
					UInt32 bayer_b_gb = GetReg32(AXH_SPAD_OFST_IMG_AE0_0 + (xc2 * 8 + 4)  + (yc2 * BAYER_COL * 8));	// B,GB取得
					Bayer.gr += (unsigned short)(bayer_gr_r >> 16);			// GRを4x4範囲で加算
					Bayer.r += (unsigned short)(bayer_gr_r & 0xFFFF);		// Rを4x4範囲で加算 
					Bayer.b += (unsigned short)(bayer_b_gb >> 16);				// Bを4x4範囲で加算
					Bayer.gb += (unsigned short)(bayer_b_gb & 0xFFFF);		// GBを4x4範囲で加算
				}
			}
			
#ifdef IMX662
			// 各平均算出(1/16)　※8bit化も同時に行うため、4bit(1/16)+8bit=12bit右シフト
			Bayer.gr = (Bayer.gr + (1 << 11)) >> 12;	// GR平均値(/16)			※+(1<<11)は四捨五入
			Bayer.r = (Bayer.r + (1 << 11)) >> 12;		// R平均値(/16)	 			※+(1<<11)は四捨五入
			Bayer.b = (Bayer.b + (1 << 11)) >> 12;		// B平均値(/16)	 			※+(1<<11)は四捨五入
			Bayer.gb = (Bayer.gb + (1 << 11)) >> 12;	// GB平均値(/16)			※+(1<<11)は四捨五入
			
			// OPD算出
			ae_opd_data[byc][bxc][OPD_D_TYPE_Y] = (unsigned char)((Bayer.gr + Bayer.r + Bayer.b + Bayer.gb + (1 << 1)) >> 2);		// (GR+R+B+GB+2)/4 ※+(1<<1)は四捨五入
			ae_opd_data[byc][bxc][OPD_D_TYPE_R] = (unsigned char)Bayer.gb;
			ae_opd_data[byc][bxc][OPD_D_TYPE_G] = (unsigned char)((Bayer.r + Bayer.b + 1) >> 1);		// (GR+GB+1)/2 ※+1は四捨五入
			ae_opd_data[byc][bxc][OPD_D_TYPE_B] = (unsigned char)Bayer.gr;
#else	// IMX662
			// IMX412,IMX415用
			// 各平均算出(1/16)　※8bit化も同時に行うため、4bit(1/16)+8bit=12bit右シフトさらに412はさらに2bit右シフトのため合計14bit右シフト
			Bayer.gr = (Bayer.gr + (1 << 13)) >> 14;	// GR平均値(/16)			※+(1<<13)は四捨五入
			Bayer.r = (Bayer.r + (1 << 13)) >> 14;		// R平均値(/16)	 			※+(1<<13)は四捨五入
			Bayer.b = (Bayer.b + (1 << 13)) >> 14;		// B平均値(/16)	 			※+(1<<13)は四捨五入
			Bayer.gb = (Bayer.gb + (1 << 13)) >> 14;	// GB平均値(/16)			※+(1<<13)は四捨五入
			
			// OPD算出
			ae_opd_data[byc][bxc][OPD_D_TYPE_Y] = (unsigned char)((Bayer.gr + Bayer.r + Bayer.b + Bayer.gb + (1 << 1)) >> 2);		// (GR+R+B+GB+2)/4 ※+(1<<1)は四捨五入
			ae_opd_data[byc][bxc][OPD_D_TYPE_R] = (unsigned char)Bayer.r;
			ae_opd_data[byc][bxc][OPD_D_TYPE_G] = (unsigned char)((Bayer.gr + Bayer.gb + 1) >> 1);		// (GR+R+B+GB+1)/2 ※+1は四捨五入
			ae_opd_data[byc][bxc][OPD_D_TYPE_B] = (unsigned char)Bayer.b;
#endif	// IMX662
		}
	}
	
	return (unsigned char*)ae_opd_data;
}
#endif

