#ifndef _MODULE_H
#define _MODULE_H

#include "camera_typedef.h"
#include "iic.h"
#include "csi_s.h"


#define MODULE_MSG(x)    DBGMSG(CIF_FUNC && CIF_USR4 , x)
#define MODULE_INF(x)    DBGMSG(CIF_INFO && CIF_USR4 , x)
#define MODULE_ERR(x)    ERRMSG(x)



#define CAM_OPMODE_TO_STR(a) ((a==VIDEO_CAPTURE)?L"VIDEO":((a==STILL_CAPTURE)?L"STILL":L"PREVIEW"))

typedef enum
{
    COMMAND_SEQ_DELAY_MARK = 0xfffe,
    COMMAND_SEQ_END_MARK = 0xffff
} MODULE_I2C_COMMAND_MARKER;



typedef enum
{
    MOD_STATUS_SUCCESS = 0,
    MOD_STATUS_FAIL,
    MOD_STATUS_NOTSUPPORT,
    MOD_STATUS_INVALIDPARAM,
    MOD_STATUS_TIMEOUT,
} MODULE_STATUS;

typedef enum
{
    MOD_PWR_STATUS_ON = 0,
    MOD_PWR_STATUS_OFF,
    MOD_PWR_STATUS_STANDBY,
    MOD_PWR_STATUS_WAKEUP,
    MOD_PWR_STATUS_RESET_ACTIVE,
    MOD_PWR_STATUS_RESET_DEACTIVE,
} MODULE_PWR_STATUS;

typedef struct _MODULE_DESCRIPTOR
{
    BYTE ModuleID;          // Module Identifier
    BYTE ModuleInterlace;   // Module Interlace support
    BYTE ITUXXX;            // if ITU-601 8bit, set 1. if ITU-656 8bit, set 0
    BYTE MIPI;              // MIPI Interface: 1
    BYTE LANE;              // MIPI number of LANE : 0 = 1 lane, 1 = 2 lane
    BYTE JPEG;              // Support JPEG : 1
    BYTE UVOffset;          // Cb, Cr value offset. 1: +128 , 0: 0
    BYTE Order422;          // 0x00:YCbYCr, 0x01:YCrYCb, 0x10:CbYCrY, 0x11:CrYCbY
    BYTE Codec;             // 422: 1   , 420: 0
    BYTE HighRst;           // Reset is    Low->High: 0   High->Low: 1
    BYTE InvPCLK;           // 1: inverse the polarity of PCLK    0 : normal
    BYTE InvVSYNC;          // 1: inverse the polarity of VSYNC   0 : normal
    BYTE InvHREF;           // 1: inverse the polarity of HREF      0 : normal
    UINT32 SourceHSize;     // Horizontal size
    UINT32 SourceVSize;     // Vertical size
    UINT32 SourceHOffset;   // Horizontal Start Offset
    UINT32 SourceHOffset2;  // Horizontal End Offset
    UINT32 SourceVOffset;   // Vertical Start Offset
    UINT32 SourceVOffset2;  // Vertical End Offset
    UINT32 JpegSpoofWidth;  // fake width in jpeg mode if possible
    UINT32 JpegSpoofHeight; // fake height in jpeg mode if possible
    UINT32 Clock;           // clock
    BYTE eHSsettle;
} MODULE_DESCRIPTOR;

class ICamModule
{
public:
    virtual MODULE_STATUS Init() = 0;
    virtual MODULE_STATUS Deinit() = 0;
    virtual MODULE_STATUS InitSensor() = 0;
    virtual MODULE_STATUS Power(BOOL bOnOff) = 0;
    virtual MODULE_STATUS Standby(BOOL bActive) = 0;
    virtual MODULE_STATUS Reset(BOOL bActive) = 0;

    virtual MODULE_STATUS GetSupportFormat(MODULE_DESCRIPTOR *outModuleDesc) = 0;
    virtual MODULE_STATUS SetOperationMode(CAMIF_OPERATION_MODE mode) = 0;
    virtual MODULE_STATUS SetFormatSize(CAMIF_IMG_SIZE imageSize) = 0;

    virtual MODULE_STATUS StartCapture() = 0;
    virtual MODULE_STATUS StopCapture() = 0;
    virtual MODULE_STATUS SensorPrepare() = 0;
    virtual MODULE_STATUS SensorStart() = 0;


//MODULE_STATUS S5K6AAFX_SetBrightness(P_MODULE_CTX pModuleCtx, PCAM_PROPERTY pModuleProperty);
//MODULE_STATUS S5K6AAFX_Effect(P_MODULE_CTX pModuleCtx, PCAM_PROPERTY pModuleProperty);
//MODULE_STATUS S5K6AAFX_Whitebalance(P_MODULE_CTX pModuleCtx, PCAM_PROPERTY pModuleProperty);
//MODULE_STATUS S5K6AAFX_Flash(P_MODULE_CTX pModuleCtx, PCAM_PROPERTY pModuleProperty);
//MODULE_STATUS S5K6AAFX_Framerate(P_MODULE_CTX pModuleCtx, PCAM_PROPERTY pModuleProperty);
};

class ICamModuleExtension
{
public:
    // Feature Extension
    virtual MODULE_STATUS Flash() = 0;
    virtual MODULE_STATUS SetBrightness() = 0;
    virtual MODULE_STATUS Effect() = 0;
    virtual MODULE_STATUS Whitebalance() = 0;
    virtual MODULE_STATUS Framerate() = 0;
//MODULE_STATUS S5K6AAFX_SetBrightness(P_MODULE_CTX pModuleCtx, PCAM_PROPERTY pModuleProperty);
//MODULE_STATUS S5K6AAFX_Effect(P_MODULE_CTX pModuleCtx, PCAM_PROPERTY pModuleProperty);
//MODULE_STATUS S5K6AAFX_Whitebalance(P_MODULE_CTX pModuleCtx, PCAM_PROPERTY pModuleProperty);
//MODULE_STATUS S5K6AAFX_Flash(P_MODULE_CTX pModuleCtx, PCAM_PROPERTY pModuleProperty);
//MODULE_STATUS S5K6AAFX_Framerate(P_MODULE_CTX pModuleCtx, PCAM_PROPERTY pModuleProperty);
};

class ICamComm
{
public:
    virtual MODULE_STATUS Open(DWORD dwSlaveIdentifier, DWORD dwCommunicationSpeed) = 0;
    virtual void Close() = 0;
    virtual MODULE_STATUS WriteRegisters(PUCHAR pBuff, DWORD nRegs) = 0;
    virtual MODULE_STATUS WriteRegisters(UINT32 setFileValue) = 0;
    virtual MODULE_STATUS WriteRegisters(UINT16 *Reg) = 0;
    virtual MODULE_STATUS WriteRegisters(UINT16 RegValue, UINT16 DataValue) = 0;
   // virtual MODULE_STATUS WriteRegisterSeq(UINT16 Regs[][2]) = 0;
	virtual	MODULE_STATUS WriteRegisterSeq(UINT16 Regs[][2],INT nLen)=0;
    virtual MODULE_STATUS WriteRegisterSeq(UINT32 Regs[]) = 0;
    virtual DWORD ReadRegisters(PUCHAR pBuff, UCHAR StartReg, DWORD nRegs) = 0;
};

class CamCommI2C : public ICamComm
{
public:
    CamCommI2C();
    virtual ~CamCommI2C();
    MODULE_STATUS Open(DWORD BusSlaveAddress, DWORD dwIICClock);
    void Close();
    MODULE_STATUS WriteRegisters(PUCHAR pBuff, DWORD nRegs);
    MODULE_STATUS WriteRegisters(UINT32 setFileValue);
    MODULE_STATUS WriteRegisters(UINT16 *Reg);
    MODULE_STATUS WriteRegisters(UINT16 RegValue, UINT16 DataValue);
   // MODULE_STATUS WriteRegisterSeq(UINT16 Regs[][2]);
    MODULE_STATUS WriteRegisterSeq(UINT32 Regs[]);
	MODULE_STATUS WriteRegisterSeq(UINT16 Regs[][2],INT nLen);

    DWORD ReadRegisters(PUCHAR pBuff, UCHAR StartReg, DWORD nRegs);
private:
    HANDLE hI2CDriver;
    DWORD m_dwErr;
    DWORD m_bytes;
    DWORD m_dwIICClock;
    DWORD m_dwIICDelay;
    CHAR m_BusSlaveAddress;  // I2C Bus SlaveAddress
};

class CamModule : public ICamModule, public ICamModuleExtension
{
public:
    CamModule();
    CamModule(ICamComm *CommIF);
    virtual ~CamModule();

    virtual MODULE_STATUS SetOperationMode(CAMIF_OPERATION_MODE mode);
    virtual MODULE_STATUS StartCapture();
    virtual MODULE_STATUS StopCapture();
    // Extension
    virtual MODULE_STATUS Flash();
    virtual MODULE_STATUS SetBrightness();
    virtual MODULE_STATUS Effect();
    virtual MODULE_STATUS Whitebalance();
    virtual MODULE_STATUS Framerate();

protected:
    ICamComm *m_oCommIF;
    MODULE_PWR_STATUS PowerStatus;
    UINT32 SensorID;
    BOOL IsInitialize;
    CAMIF_OPERATION_MODE OperationMode;
    CAMIF_IMG_SIZE PreviewSize;
    CAMIF_IMG_SIZE StillSize;
    MODULE_DESCRIPTOR   ModuleDescriptor;
    volatile GPIO_REG    *m_regIOP;
//  Properties[];
};

// Functions
#ifdef __cplusplus
extern "C" {
#endif
extern int   ModuleInit();
extern void  ModuleDeinit();
extern void  ModuleGetFormat(MODULE_DESCRIPTOR *outModuleDesc);
extern int   ModuleWriteBlock();
extern int   ModuleSetImageSize(int imageSize);
extern int  ModuleSetFormatSize(CAMIF_OPERATION_MODE OPMode, CAMIF_IMG_SIZE imageSize);
extern MODULE_STATUS ModuleSetPower(MODULE_PWR_STATUS NewPower);
extern void ModuleSelectSensor(MODULE_SENSOR SensorID);
extern int   ModulePrepare();
extern int   ModuleStart();
extern int   ModuleCapturePrepare();
extern int   ModuleCaptureStart();

#ifdef __cplusplus
}
#endif

static BOOL HW_WriteRegisters(PUCHAR pBuff, DWORD nRegs);
static DWORD HW_ReadRegisters(PUCHAR pBuff, UCHAR StartReg, DWORD nRegs);
static BOOL HW_WriteRegisters16Bit(UINT32 setFileValue);
static BOOL ModuleSetHwRegMIPI(uchar ucHSubAddr, uchar ucLSubAddr, uchar ucHData, uchar ucLData);
static BOOL ModuleSetSwRegMIPI(uchar ucHSubAddr, uchar ucLSubAddr, uchar ucHData, uchar ucLData);

#endif
