#ifndef __CAMERA_HAL_H
#define __CAMERA_HAL_H

#include <CAMDriver.h>
#include "camera_typedef.h"
#include <SVEDriverAPI.h>
#include <Module.h>
#include <cmthread.h>
#include "csi_s.h"
#include "CMMAPI.h"

// Macros Bitfield Redefinition from Register Raw definition
#define CAM_SCALER_START_BIT                  (BM_SCALERSTART)
#define CAM_GLOBAL_CAPTURE_ENABLE_BIT         (BM_IMGCPTEN)
#define CAM_SCALER_CAPTURE_ENABLE_BIT         (BM_IMGCPTEN_SC)

class CSI_S;

/////////////////////////////////////
// extern functions
// @class CameraHal()
// @desc    This class will handle Camera Interface IP, each method will read/write register directly.
class CameraHal : public CMiniThread
{
    public:
        CAMERA_POST_ERROR Initialize(DWORD dwCAMIFPhyAddr, DWORD dwPhyIRQ);
        void Deinitialize();
        CAMERA_POST_ERROR CameraInitialize(CAMERA_MODULE_DESC CamModuleInfo);
        void CameraDeinitialize();
        void SetID(UINT32 uCamID);
        void SetCameraSensor(MODULE_SENSOR SensorID);
        void GetModuleDesc( MODULE_DESCRIPTOR *pModDesc );
        CAMERA_POST_ERROR InitSensor();
        CAMERA_POST_ERROR DeInitSensor();            
        
        int AllocOutputDMABuffer(int dwSize, CMM_DRAM_LOCATION Loc, DWORD* dwPhy, DWORD* dwVir);
        void FreeOutputDMABuffer(int dwVir);
        void CloseCMM();
        int  OpenCMM();


        UINT32 CalculateBufferSize(UINT32 width, UINT32 height, int format);
        int SetOutputAddress(P_CAMERA_DMA_BUFFER_INFO CAM_BUFFER_INFO);
        int SetOutputAddress(BUFFER_ADDRESS *pingpong, int yoffset, int coffset);
        int GetCurrentFrameNum();
        void SetTargetRegister(UINT32 width, UINT32 height, CAM_IMG_FORMAT Format);
        
        void SetPowerOn(BOOL bOnOff);
        void SetCamIFClockOn(BOOL bOnOff);
        void SetCamIFClock();
        void SetPixelClock(DWORD dwFreq);
        
        void SetCameraSource(CAM_IMG_FORMAT Format);
        void WaitForCaptureFinish();
        void SkipFrame(int frameNum);
        
        volatile CAMIF_REG *GetCameraSFR() {return m_regCAM;}
        volatile CMU_CLK_REG *GetClockControllerSFR() {return m_regCLKCON;}
        
        void InterfaceReset(BOOL isForCam);
        void ModuleReset();
        
        void ImageEffectOn(DWORD dwImgEffect);
        void ImageEffectOff();

        void SetUsage(CAMIF_USE purpose) {m_currentContext.usefor = purpose;}
        void SetOperationMode(CAMIF_OPERATION_MODE mode) {m_CamOperationMode = mode; }
        CAMIF_OPERATION_MODE GetOperationMode(void) {return m_CamOperationMode;}
        
        int CaptureControl(BOOL on);
    
        void SetScaler(UINT32 width, UINT32 height);        
        void SetScaler(UINT32 dwCropInHSize, UINT32 dwCropInVSize, UINT32 dwResizedOutHSize, UINT32 dwResizedOutVSize);
        void SetOffsetRegister(UINT32 horOffset, UINT32 horOffset2, UINT32 verOffset, UINT32 verOffset2);        
        BOOL SetDMARegister(CAM_DMA_MODE OutputDMA);

        void SetPostEvent(HANDLE hEvent) {m_hPostDoneEvent = hEvent;}
        void ResetSkipFrameCount(void) {m_dwSkipFrameCnt = 0;}
        void ResetIDMABusy(void) {m_dwIDMABusy = 1;}
        int GetIDMABusy(){return m_dwIDMABusy;}
        void SetIDMAFree(void){m_dwIDMABusy = 0;}

        CameraHal();
        DWORD m_Size_Capture_Data;
    private:
        void SetCameraSource(MODULE_DESCRIPTOR NewModule);  //< Reserved Function
        virtual DWORD ThreadRun();   // IST
        void SetMainClockDiv();
        void SetSourceRegister(int ituxxx, int uvoffset, int order422, UINT32 hSize, UINT32 vSize);
        void CameraSourceSet(CAM_IMG_FORMAT Format);
        void InitGPIO();
        void SetInputPort(CAMIF_INPUTPORT InputPort){ m_InputPort = InputPort;}
        void SelectResetPinMux();
        BOOL GetPrescalerShiftvalue(unsigned int *MainShift, unsigned int SrcValue, unsigned int DstValue );
        void SetVideoCaptureCallbackEvent();
        void SetPreviewCaptureCallbackEvent();

protected:
        DWORD   m_CamID;
        UINT32  m_CaptureOn;
        BYTE    m_PreviewOn;    // Preview Capture On/Off control
        BYTE    m_VideoOn;   // Video Capture On/Off control
        BYTE    m_StillOn;   // Still Capture On/Off control
        
        BOOL    m_isPowerOn;        // For each CAMIF Power state control
        HANDLE  m_hPwrControl;
        DWORD   m_dwCurrentCAMIFID;   // Use HW IP PHYSICAL ADDRESS as CAMIFID

        CAMIF_INPUTPORT  m_InputPort;
        MODULE_SENSOR   m_MuduleSensor;
        CAMIF_OPERATION_MODE  m_CamOperationMode;
        UINT32  m_CamIrq;        // IRQ_FIMC0, IRQ_FIMC1, IRQ_FIMC2
        UINT32  m_CamSysIntr;
        HANDLE  m_hCaptureEvent;
        HANDLE  m_hCaptureFinishEvent;
        HANDLE  m_hPostDoneEvent;
        HANDLE  m_hCMMOpen;
        // Optional Parameter
        DWORD   m_dwISTTimeout;
        DWORD   m_dwSkipFrameCnt;   // this is for skipping first some frames, when starting capture in the middle of camera image.
                                    // the stored image can have imperfect image in the buffer. Normally Skip 1 frame
        DWORD m_CurrentFrameNum;
        CAMIF_CONTEXT        m_currentContext;
        CRITICAL_SECTION     m_csHWregister;
        MODULE_DESCRIPTOR    m_moduleDesc;

        volatile GPIO_REG    *m_regIOP;
        volatile CAMIF_REG           *m_regCAM;
        volatile CMU_CLK_REG    *m_regCLKCON;
        CSI_S   *m_oCSI_S;
        HANDLE hVideoCaptureEvent;
        HANDLE hPreviewCaptureEvent;
        BYTE    m_bWeaveMode;
        int m_dwIDMABusy;
};
#endif
