// CH7026_VGA800600.cpp : Defines the entry point for the console application.
//

//#include "stdafx.h"
#include <windows.h>
#include <commctrl.h>

#include "stdio.h"
#include "iic.h"
#include "winioctl.h"
#include "ceddk.h"

#include <i2c_wave.h>


#define RETRY_COUNT     3
#define I2C_CODEC_GROUP_NAME    L"I2C2:"
#define DEVICE_ID	0xec//0x76  //0x76<<1  ==0xec
#define I2C_CLOCK      100


#define CVBS_OUTPUT 0




HANDLE OpenI2C(LPWSTR lpGroupName);
BOOL InitI2C(HANDLE hI2C, WORD wSlaveAddr, DWORD dwSpead);

BOOL WriteI2C_SlaveName(HANDLE hI2C, PBYTE pWData, DWORD dwWDatas);

BOOL ReadI2C_SlaveName(HANDLE hI2C, PBYTE pWData, DWORD dwWDatas, BOOL bStop, PBYTE pRData, DWORD dwRDatas);

BOOL ReadRegisters(HANDLE hI2CDriver,
    PUCHAR pBuff,       // Optional buffer
    UCHAR StartReg,     // Start Register
    DWORD nRegs         // Number of Registers
    );
BOOL WriteRegisterSeq(UINT16 Regs[][2],INT nLen);

HANDLE hI2C = NULL;


//CVBS NTSC_M OutPut
unsigned short CH7026_Init_CVBS[][2] = {
{ 0x02, 0x01 },
{ 0x02, 0x03 },
{ 0x03, 0x00 },
{ 0x04, 0x39 },
{ 0x0F, 0x23 },
{ 0x10, 0x20 },
{ 0x11, 0x22 },
{ 0x12, 0x40 },
{ 0x13, 0xDC },
{ 0x14, 0x0A },
{ 0x15, 0x11 },
{ 0x16, 0xE0 },
{ 0x17, 0x0F },
{ 0x19, 0x1E },
{ 0x1A, 0x07 },
{ 0x1C, 0x1E },
{ 0x22, 0xBD },
{ 0x36, 0xC8 },
{ 0x41, 0xA2 },
{ 0x4D, 0x04 },
{ 0x4E, 0x27 },
{ 0x4F, 0x62 },
{ 0x50, 0x76 },
{ 0x51, 0x51 },
{ 0x52, 0x12 },
{ 0x53, 0x1B },
{ 0x55, 0xE5 },
{ 0x5E, 0x80 },
{ 0x69, 0x64 },
{ 0x7D, 0x62 },
{ 0x04, 0x38 },
{ 0x06, 0x71 },

/*
NOTE: The following five repeated sentences are used here to wait memory initial complete, please don't remove...(you could refer to Appendix A of programming guide document (CH7025(26)B Programming Guide Rev2.03.pdf or later version) for detailed information about memory initialization! 
*/
{ 0x03, 0x00 },
{ 0x03, 0x00 },
{ 0x03, 0x00 },
{ 0x03, 0x00 },
{ 0x03, 0x00 },

{ 0x06, 0x70 },
{ 0x02, 0x02 },
{ 0x02, 0x03 },
{ 0x04, 0x00 },
};


//VGA 800*600
unsigned short CH7026_Init_VAG800600[][2] = {
{ 0x02, 0x01 },
{ 0x02, 0x03 },
{ 0x03, 0x00 },
{ 0x04, 0x39 },
{ 0x08, 0x08 },
{ 0x09, 0x80 },

{ 0x0D, 0x08 },
{ 0x0F, 0x23 },
{ 0x10, 0x20 },
{ 0x11, 0x22 },
{ 0x12, 0x40 },//{ 0x12, 0x40 },
{ 0x13, 0xe6 },//{ 0x13, 0xa6 },//{ 0x13, 0x26 },//increase add h size,or inc size
{ 0x14, 0x0A },
{ 0x15, 0x11 },
{ 0x16, 0xf0 },//{ 0x16, 0xE0 },//increase add v size,or inc size
{ 0x17, 0x0F },
{ 0x19, 0x12 },
{ 0x1A, 0x07 },
{ 0x1B, 0x23 },
{ 0x1C, 0x20 },
{ 0x1D, 0x20 },
{ 0x1F, 0x28 },
{ 0x20, 0x80 },
{ 0x21, 0x12 },
{ 0x22, 0x58 },
{ 0x23, 0x74 },
{ 0x25, 0x01 },
{ 0x26, 0x04 },
{ 0x37, 0x20 },
{ 0x39, 0x20 },
{ 0x3B, 0x20 },
{ 0x41, 0xA2 },
{ 0x4D, 0x03 },
{ 0x4E, 0x0F },
{ 0x4F, 0x8E },
{ 0x50, 0x92 },
{ 0x51, 0x51 },
{ 0x52, 0x12 },
{ 0x53, 0x13 },
{ 0x55, 0xE5 },
{ 0x5E, 0x80 },
{ 0x69, 0x64 },
{ 0x77, 0x03 },
{ 0x7D, 0x62 },
{ 0x04, 0x38 },
{ 0x06, 0x71 },
{ 0x36, 0x18 },//{ 0x36, 0x28 },//increase to move right,or move left
{ 0x34, 0x08 },//{ 0x36, 0x48 },//increase to move up,or move down

/*
NOTE: The following five repeated sentences are used here to wait memory initial complete, please don't remove...(you could refer to Appendix A of programming guide document (CH7025(26)B Programming Guide Rev2.03.pdf or later version) for detailed information about memory initialization! 
*/
{ 0x03, 0x00 },
{ 0x03, 0x00 },
{ 0x03, 0x00 },
{ 0x03, 0x00 },
{ 0x03, 0x00 },

{ 0x06, 0x70 },
{ 0x02, 0x02 },
{ 0x02, 0x03 },
{ 0x04, 0x00 },
//{0xffff, 0xfffe}
};


BOOL
WriteI2C_SlaveName(HANDLE hI2C, PBYTE pWData, DWORD dwWDatas)
{
    BOOL bWrite = TRUE;
    DWORD dwTry;
    I2C_WRITE_DESC I2CWriteDesc;
    
	I2CWriteDesc.IO_pbtData = pWData;
	I2CWriteDesc.IN_dwData  = dwWDatas;
	I2CWriteDesc.IN_bStop   = TRUE;

    for(dwTry=0; dwTry<RETRY_COUNT; ++dwTry)
    {

    	if(!DeviceIoControl(hI2C,
    	                    IOCTL_I2C_GENERAL_WRITE, 
    	                    &I2CWriteDesc, sizeof(I2C_WRITE_DESC), 
    	                    NULL, 0,
    	                    NULL, NULL)) 

        {
          //  ERRMSG((L"[XXX] IOCTL_I2C_GENERAL_WRITE ERROR: %u \r\n", GetLastError()));
            if(dwTry == (RETRY_COUNT-1)) bWrite = FALSE;
            continue;
        }

        break;
    }


	return bWrite;
}

BOOL
ReadI2C_SlaveName(HANDLE hI2C, PBYTE pWData, DWORD dwWDatas, BOOL bStop, PBYTE pRData, DWORD dwRDatas)
{
	BOOL bRead = TRUE;
    DWORD dwTry;
	I2C_WRITE_DESC I2CWriteDesc;
    I2C_READ_DESC I2CReadDesc;

	I2CWriteDesc.IO_pbtData = pWData;
	I2CWriteDesc.IN_dwData  = dwWDatas;
	I2CWriteDesc.IN_bStop   = bStop;

    for(dwTry=0; dwTry<RETRY_COUNT; ++dwTry)
    {

    	if (!DeviceIoControl(hI2C,
    	                     IOCTL_I2C_GENERAL_WRITE, 
    	                     &I2CWriteDesc, sizeof(I2C_WRITE_DESC), 
    	                     NULL, 0,
    	                     NULL, NULL)) 

    	{
    		//ERRMSG((L"[XXX] IOCTL_I2C_GENERAL_WRITE ERROR: %u \r\n", GetLastError()));
    		if(dwTry == (RETRY_COUNT-1)) bRead = FALSE;
            continue;
    	} 
    	else
    	{
    		I2CReadDesc.IO_pbtData 		= pRData;
    		I2CReadDesc.IN_dwData 		= dwRDatas;
    		I2CReadDesc.IN_bStop		= TRUE;

    		if (!DeviceIoControl(hI2C,
    		                     IOCTL_I2C_GENERAL_READ, 
    		                     &I2CReadDesc, sizeof(I2C_READ_DESC), 
    		                     NULL, 0,
    		                     NULL, NULL))

    		{
    			//ERRMSG((L"[XXX] IOCTL_I2C_GENERAL_READ ERROR: %u \r\n", GetLastError()));
    			if(dwTry == (RETRY_COUNT-1)) bRead = FALSE;
                continue;
    		} 		
    	}

        break;
    }
    
	return bRead;
}


BOOL ReadRegisters(HANDLE hI2CDriver,
    PUCHAR pBuff,       // Optional buffer
    UCHAR StartReg,     // Start Register
    DWORD nRegs         // Number of Registers
    )
{
    return  ReadI2C_SlaveName(hI2CDriver, &StartReg, 1 , FALSE, pBuff, nRegs);     
}

BOOL WriteRegisters(
    PUCHAR pBuff,   // Optional buffer
    DWORD nRegs     // number of registers
    )
{  
    return WriteI2C_SlaveName(hI2C, pBuff, nRegs );
}


BOOL WriteRegisters_CH7026(UINT16 RegValue, UINT16 DataValue)
{
    DMA_ADAPTER_OBJECT Adapter;
    PBYTE pCommandBuf = NULL;
    PHYSICAL_ADDRESS pPhyCommandBuf;
    bool bRet = true;

	UINT8 *u8Array = (UINT8*)&RegValue;
	u8Array[1]=   (0xff & DataValue);

    unsigned char value = 0;

	//bRet = WriteRegisters(u8Array, 2);

    bRet = WriteI2C_SlaveName(hI2C, u8Array, 2 );



    return bRet;
}


//MODULE_STATUS CamCommI2C::WriteRegisterSeq(UINT16 Regs[][2])
BOOL WriteRegisterSeq(UINT16 Regs[][2],INT nLen)
{
    int i = 0;

    if(nLen<0)
        return false;

    // Do iteration when the END Mark appears
    for ( i=0; i<nLen; i++ )
    {
            if(WriteRegisters_CH7026(Regs[i][0],Regs[i][1]) != TRUE )
            {
               // MODULE_ERR((TEXT("111%s : No. %d command failed\r\n"),  _T(__FUNCTION__),i));
                return false;
            }
			Sleep(10);
    }
    return true;
}

bool CH7026_Init(void)
{
	BOOL  bRet = FALSE;
	UCHAR ReadVal[5] = {0};
	DWORD dwlen = 1;


	if(CVBS_OUTPUT) 	
	{	
		/********************************************************************************/
		// CVBS
		/********************************************************************************/

		//printf("[APP]....CVBS OUTPUT............\r\n");


		dwlen = sizeof(CH7026_Init_CVBS)/sizeof(CH7026_Init_CVBS[0]);
		bRet =WriteRegisterSeq(CH7026_Init_CVBS,dwlen);
	}
	else
	{			
		/********************************************************************************/
		// VGA 800*600		
		/********************************************************************************/
		dwlen = sizeof(CH7026_Init_VAG800600)/sizeof(CH7026_Init_VAG800600[0]);
		bRet =WriteRegisterSeq(CH7026_Init_VAG800600,dwlen);

		if(bRet)
			RETAILMSG(1,(TEXT(".VGA800*600 OUTPUT............\r\n")));
		
		//printf("[APP]....VGA800*600 OUTPUT............\r\n");

	}

		//if(!bRet)
		//printf("error....write reg............\r\n");
	return bRet;


}



#if 0
int _tmain(int argc, _TCHAR* argv[])
{

	BOOL  bRet = FALSE;
	UCHAR ReadVal[5] = {0};
	DWORD dwlen = 1;

 //  printf("[APP]....1............\r\n");

	// TODO: Add extra initialization here
	hI2C = OpenI2C(I2C_CODEC_GROUP_NAME);


	   printf("[APP]....2............\r\n");
	if(hI2C!=NULL)
	{	
		if(InitI2C(hI2C,DEVICE_ID,I2C_CLOCK))
		{
			   printf("[APP]....3............\r\n");

			bRet = ReadRegisters(hI2C,ReadVal,0x00,1); //ch7026  device id:0x54
			if(bRet)
				printf("ch7026 device id [0x%xc]..\r\n",ReadVal);

			if(CVBS_OUTPUT)		
			{	
				/********************************************************************************/
				// CVBS
				/********************************************************************************/
				
				printf("[APP]....CVBS OUTPUT............\r\n");


				dwlen = sizeof(CH7026_Init_CVBS)/sizeof(CH7026_Init_CVBS[0]);
				bRet =WriteRegisterSeq(CH7026_Init_CVBS,dwlen);
			}
			else
			{			
				/********************************************************************************/
				// VGA 800*600		
				/********************************************************************************/
				dwlen = sizeof(CH7026_Init_VAG800600)/sizeof(CH7026_Init_VAG800600[0]);
				bRet =WriteRegisterSeq(CH7026_Init_VAG800600,dwlen);

				printf("[APP]....VGA800*600 OUTPUT............\r\n");

			}

			if(!bRet)
				printf("error....write reg............\r\n");

		}
	}
	return 0;
}
#endif
