⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 camera.cpp

📁 camera driver for wince s3c2440 .SAMSUNG s S3C2440A 16/32-bit RISC microprocessor. SAMSUNG鈥檚 S3C2440
💻 CPP
📖 第 1 页 / 共 4 页
字号:

#include <windows.h>

#include <nkintr.h>
//#include <oalintr.h>
#include <pm.h>
#include "pmplatform.h"
#include <ceddk.h>

#include <s3c2440a.h>
#include <bsp.h>
#include "camif.h"
#include "camera.h"
#include "s5x532.h"

#define PM_MSG 		0
#define I2C_MSG		0
#define MSG_EN_1	0
#define MSG_EN_2	0

#define CAPTURE_TIME		30

#define CAM_CLOCK_OFF_ON_IDLE 1

#if (CAM_CLOCK_OFF_ON_IDLE == 1)
#define DISPLAY_THREAD_TIMEOUT	3000
#else
#define DISPLAY_THREAD_TIMEOUT	INFINITE
#endif

#define U8	unsigned char
#define U16	unsigned short
#define U32	unsigned int

#define	PORT_A 1
#define	PORT_B 0

#define	YCbCrtoR(Y,Cb,Cr)	(1000*Y + 1540*(Cr-128))/1000
#define	YCbCrtoG(Y,Cb,Cr)	(1000*Y - 459*(Cb-128) - 183*(Cr-128))/1000
#define	YCbCrtoB(Y,Cb,Cr)	(1000*Y + 1856*(Cb-128))/1000

volatile S3C2440A_IOPORT_REG *s2440IOP = NULL;
volatile S3C2440A_CAM_REG    *s2440CAM = NULL;
volatile S3C2440A_INTR_REG	*s2440INT = NULL;
volatile S3C2440A_CLKPWR_REG *s2440PWR = NULL;

unsigned int dwDisplayTimeout = DISPLAY_THREAD_TIMEOUT;

BOOL bIdlePwrDown = FALSE;

unsigned char buffer_num=0xff;		// ping pong buffer

//unsigned char image_size = 2;				// 1: QCIF, 2:CIF (default)
unsigned char image_size = 1;				// 1: QCIF, 2:CIF (default)

//#define DRIVER_PREVIEW_ENABLE		2	// 0: onTimeTek, 1: Preview, 2:Samsung Camcorder
unsigned char DRIVER_PREVIEW_ENABLE = 1;	// 0: onTimeTek, 1: Preview, 2:Samsung Camcorder	

unsigned int frame_count=0;			// for MPEG4
DWORD Tick_GET_FRAME_CUR;
DWORD Tick_GET_FRAME_PREV;
DWORD Tick_COPY_FRAME;

CAMINFO sCAMINFO;

UINT32 g_CamIrq = IRQ_CAM;	// Determined by SMDK2440 board layout.
UINT32 g_CamSysIntr = SYSINTR_UNDEFINED;

HANDLE CameraThread;
HANDLE CameraEvent;
static BOOL mInitialized = FALSE;

unsigned char codec_flag=0;
unsigned char rgb_flag=0;
unsigned int y_address,cb_address,cr_address;
unsigned int rgb_address;

// PingPong Memory Physical Address 
PHYSICAL_ADDRESS g_PhysPreviewAddr;
PHYSICAL_ADDRESS g_PhysCodecAddr;


void CAM_WriteBlock(void);

void Virtual_Alloc();						// Virtual allocation
void Camera_Clock(unsigned char divide);	// set default value
void Camif_Capture(int cap_a, int cap_b);	// A port, B port
void Display_Cam_Image(U32 pos_x, U32 pos_y, U32 size_x, U32 size_y, U8 port);
void Display_Cam_Image2(U32 size_x, U32 size_y, U8 port);
void Copy_Cam_Image(U8 * pBufOut, U32 size_x, U32 size_y, U8 port);
void Samsung_camcoder(U8 *pBufOut);
void Samsung_camcoder_pr(U8 *pBufOut);
void Buffer_codec_info_update();
void Buffer_preview_info_update();
BOOL Cam_Init();
BOOL CamClockOn(BOOL bOnOff);

void CamInit(U32 CoDstWidth, U32 CoDstHeight, U32 PrDstWidth, U32 PrDstHeight, 
			U32 WinHorOffset, U32 WinVerOffset,  U32 CoFrameBuffer, U32 PrFrameBuffer);

DWORD CameraCaptureThread(void);
BOOL InitInterruptThread();

CEDEVICE_POWER_STATE m_Dx;

#ifdef DEBUG
DBGPARAM dpCurSettings = {
    TEXT("CAMERA"), {
        TEXT("0"),TEXT("1"),TEXT("2"),TEXT("3"),
        TEXT("4"),TEXT("5"),TEXT("6"),TEXT("7"),
        TEXT("8"),TEXT("9"),TEXT("10"),TEXT("11"),
        TEXT("12"),TEXT("Function"),TEXT("Init"),TEXT("Error")},
    0x8000  // Errors only, by default
}; 
#endif


PCIS_CONTEXT pCIS;

CRITICAL_SECTION m_Lock;

void Lock()   {EnterCriticalSection(&m_Lock);}
void Unlock() {LeaveCriticalSection(&m_Lock);}


static void Delay(USHORT count)
{
	volatile int i, j = 0;
	volatile static int loop = S3C2440A_FCLK/100000;
	
	for(;count > 0;count--)
		for(i=0;i < loop; i++) { j++; }
}


// 
// Read PCF50606 registers directly into our cache
//
DWORD
HW_ReadRegisters(
    PCIS_CONTEXT pCIS,
    PUCHAR pBuff,       // Optional buffer
    UCHAR StartReg,     // Start Register
    DWORD nRegs         // Number of Registers
    )
{
    DWORD dwErr;


    EnterCriticalSection(&pCIS->RegCS);

    // use the driver-to-driver call
    dwErr = pCIS->fc.I2CRead(pCIS->fc.Context,
                             CAMERA_READ, 	// SlaveAddress
                             StartReg,      // WordAddress
                             !pBuff ? (PUCHAR)&pCIS->Reg[StartReg] : pBuff,
                             nRegs);
    
    if ( !dwErr ) {


    } else {        
        RETAILMSG(1,(TEXT("I2CRead ERROR: %u \r\n"), dwErr));
        //DEBUGMSG(ZONE_ERR,(TEXT("I2CRead ERROR: %u \r\n"), dwErr));
    }            

    LeaveCriticalSection(&pCIS->RegCS);
    
    return dwErr;
}


// 
// Write PCF50606 registers directly from our cache
//
DWORD
HW_WriteRegisters(
    PCIS_CONTEXT pCIS,
    PUCHAR pBuff,   // Optional buffer
    UCHAR StartReg, // start register
    DWORD nRegs     // number of registers
    )
{
    DWORD dwErr;


    EnterCriticalSection(&pCIS->RegCS);

    // use the driver-to-driver call
    dwErr = pCIS->fc.I2CWrite(pCIS->fc.Context,
                              CAMERA_WRITE,   	// SlaveAddress
                              StartReg,         // WordAddress
                              !pBuff ? (PUCHAR)&pCIS->Reg[StartReg] : pBuff,
                              nRegs);

    if ( dwErr ) {
        RETAILMSG(1, (TEXT("I2CWrite ERROR: %u \r\n"), dwErr));
        //DEBUGMSG(ZONE_ERR, (TEXT("I2CWrite ERROR: %u \r\n"), dwErr));
    }            

    LeaveCriticalSection(&pCIS->RegCS);
    
    return dwErr;
}

void CAM_WriteBlock(void)
{
    int i;
    unsigned char rdata[256] = { 0, }; 
    //int err = 0;
#if (CIS_TYPE == CIS_S5X3A1)
	for(i=0; i<(sizeof(S5X3A1_YCbCr8bit)/2); i++)
	{
		//HW_WriteRegisters(&S5X3A1_YCbCr8bit[i][1], S5X3A1_YCbCr8bit[i][0], 1);
		HW_WriteRegisters(pCIS, &S5X3A1_YCbCr8bit[i][1], S5X3A1_YCbCr8bit[i][0], 1);
	}
#elif (CIS_TYPE == CIS_S5X3AA) 
	for(i=0; i<(sizeof(S5X3AA_YCbCr8bit)/2); i++)
	{
		//HW_WriteRegisters(&S5X3AA_YCbCr8bit[i][1], S5X3AA_YCbCr8bit[i][0], 1);
		HW_WriteRegisters(pCIS, &S5X3AA_YCbCr8bit[i][1], S5X3AA_YCbCr8bit[i][0], 1);
	}
#endif
 	/*
    for(i=0; i<(sizeof(S5X532_YCbCr8bit_TV)/2); i++){
    	RETAILMSG(I2C_MSG,(TEXT("num:%d "),i));	
		//Wr_CamIIC(SlaveID, S5X532_YCbCr8bit_TV[i][0], S5X532_YCbCr8bit_TV[i][1]);
		HW_WriteRegisters(pCIS, &S5X532_YCbCr8bit_TV[i][1], S5X532_YCbCr8bit_TV[i][0], 1);
		//Sleep(1);
	}
	*/
#if 0
	i = 0;
	HW_WriteRegisters(pCIS, &S5X532_YCbCr8bit_TV[i][1], S5X532_YCbCr8bit_TV[i][0], 1);
	do 
	{
		i++;
		HW_ReadRegisters(pCIS, &rdata[i], S5X532_YCbCr8bit_TV[i][0], 1);
		RETAILMSG(1,(_T("rdata[%d] = 0x%X\r\n"), i, rdata[i]));
		Sleep(1);
	} while (i < 10);

#endif
	
    RETAILMSG(1,(TEXT("Camera::Block TX Ended...\r\n")));	
}

/********************************************************
 CalculateBurstSize - Calculate the busrt lengths
 
 Description:	
 - dstHSize: the number of the byte of H Size.
 
*/
void CalculateBurstSize(unsigned int hSize,unsigned int *mainBurstSize,unsigned int *remainedBurstSize)
{
	unsigned int tmp;	
	tmp=(hSize/4)%16;
	switch(tmp) {
		case 0:
			*mainBurstSize=16;
			*remainedBurstSize=16;
			break;
		case 4:
			*mainBurstSize=16;
			*remainedBurstSize=4;
			break;
		case 8:
			*mainBurstSize=16;
			*remainedBurstSize=8;
			break;
		default: 
			tmp=(hSize/4)%8;
			switch(tmp) {
				case 0:
					*mainBurstSize=8;
					*remainedBurstSize=8;
					break;
				case 4:
					*mainBurstSize=8;
					*remainedBurstSize=4;
				default:
					*mainBurstSize=4;
					tmp=(hSize/4)%4;
					*remainedBurstSize= (tmp) ? tmp: 4;
					break;
			}
			break;
	}		    	    		
}

/********************************************************
 CalculatePrescalerRatioShift - none
 
 Description:	
 - none
 
*/
void CalculatePrescalerRatioShift(unsigned int SrcSize, unsigned int DstSize, unsigned int *ratio,unsigned int *shift)
{
	if(SrcSize>=64*DstSize) {
//		Uart_Printf("ERROR: out of the prescaler range: SrcSize/DstSize = %d(< 64)\r\n",SrcSize/DstSize);
		while(1);
	}
	else if(SrcSize>=32*DstSize) {
		*ratio=32;
		*shift=5;
	}
	else if(SrcSize>=16*DstSize) {
		*ratio=16;
		*shift=4;
	}
	else if(SrcSize>=8*DstSize) {
		*ratio=8;
		*shift=3;
	}
	else if(SrcSize>=4*DstSize) {
		*ratio=4;
		*shift=2;
	}
	else if(SrcSize>=2*DstSize) {
		*ratio=2;
		*shift=1;
	}
	else {
		*ratio=1;
		*shift=0;
	}    	
}

void Camera_Clock(unsigned char divide)
{
	unsigned int camclk;
	
	// Set camera clock for camera processor
	s2440PWR->CAMDIVN = (s2440PWR->CAMDIVN & ~(0x1f)) | (1<<4) | (divide & 0xf); // CAMCLK is divided..
	camclk = 48000000/(((s2440PWR->CAMDIVN&0xf) + 1)*2);

	//RETAILMSG(1,(TEXT("CAM clock:%d\r\n"),camclk));
}


void Camif_Capture(int cap_a, int cap_b)
{
	//RETAILMSG(1,(_T("Camif_Capture(%d, %d)\r\n"), cap_a, cap_b));
	// S3C2440A

	s2440CAM->CIIMGCPT &= ~(CAM_CAMIF_GLOBAL_CAPTURE_ENABLE_BIT);

	if(cap_b == CAPTURE_ON) 
	{
		//Codec capture start
		s2440CAM->CICOSCCTRL |=(CAM_CODEC_SACLER_START_BIT);
		s2440CAM->CIIMGCPT |=(CAM_CAMIF_GLOBAL_CAPTURE_ENABLE_BIT)|(CAM_CODEC_SCALER_CAPTURE_ENABLE_BIT);
	} 
	else if (cap_b == CAPTURE_OFF)
	{
		s2440CAM->CICOSCCTRL &= ~(CAM_CODEC_SACLER_START_BIT);
		s2440CAM->CIIMGCPT &= ~(CAM_CODEC_SCALER_CAPTURE_ENABLE_BIT);
	}

	if(cap_a == CAPTURE_ON) 
	{  
		// Preview capture Start
		s2440CAM->CIPRSCCTRL |=(CAM_PVIEW_SACLER_START_BIT);
		s2440CAM->CIIMGCPT |=(CAM_CAMIF_GLOBAL_CAPTURE_ENABLE_BIT)|(CAM_PVIEW_SCALER_CAPTURE_ENABLE_BIT);
	}
	else if (cap_a == CAPTURE_OFF)
	{
		s2440CAM->CIPRSCCTRL &= ~(CAM_PVIEW_SACLER_START_BIT);
		s2440CAM->CIIMGCPT &= ~(CAM_PVIEW_SCALER_CAPTURE_ENABLE_BIT);
	}
	
	if ((cap_a == CAPTURE_ON) || (cap_b == CAPTURE_ON))
	{
		s2440CAM->CIIMGCPT |= (CAM_CAMIF_GLOBAL_CAPTURE_ENABLE_BIT);
	}
	
}



void CamInterface_PowerDown(void)
{
	RETAILMSG(PM_MSG, (_T("CamInterface_PowerDown()\r\n")));

	// Camera clock off
	CamClockOn(FALSE);

	// GPIO control
	// for power down mode, gpio goes to input mode
	s2440IOP->GPJCON = (s2440IOP->GPJCON & ~(0xffffff)) | 0x555555; // CAM IO setup except CAMRESET
	s2440IOP->GPJDAT = s2440IOP->GPJDAT & ~(0xfff); 	// CAM IO DATA pin setup except CAMRESET
	s2440IOP->GPJUP = (s2440IOP->GPJUP | 0xfff); 		// CAM IO PullUp setup except CAMRESET
	//s2440IOP->GPJCON = (s2440IOP->GPJCON & ~(0x3<<22)) | (0x0<<22); // CAMCLKOUT -> input
	
}

void CamInterface_PowerUp(void)
{
	RETAILMSG(PM_MSG, (_T("CamInterface_PowerUp()\r\n")));

	// GPIO control
	s2440IOP->GPJCON = (s2440IOP->GPJCON & ~(0xffffff)) | 0xaaaaaa; // CAM IO setup except CAMRESET
	s2440IOP->GPJDAT = s2440IOP->GPJDAT & ~(0xfff); 	// CAM IO DATA pin setup except CAMRESET
	s2440IOP->GPJUP = (s2440IOP->GPJUP | 0xfff); 		// CAM IO PullUp setup except CAMRESET
	//s2440IOP->GPJCON = (s2440IOP->GPJCON & ~(0x3<<22)) | (0x2<<22); // CAMCLKOUT -> input

	Delay(10);

	// Camera clock on
	CamClockOn(TRUE);
	
	Delay(100);
}


DWORD CameraCaptureThread(void)
{
	unsigned char tmp=0;
	static unsigned int time,old_time;
	static unsigned int cam_intr;
	
	DWORD	dwCause;					// LJY PWR040613

	//dwDisplayTimeout = INFINITE;

	SetProcPermissions((DWORD)-1);
	
	while(TRUE)
	{
		RETAILMSG(0,(TEXT("[CAM_HW] InterruptThread : Waiting For a Single Object\n\r")));
		
		dwCause = WaitForSingleObject(CameraEvent, dwDisplayTimeout);
		
		RETAILMSG(MSG_EN_1,(_T("CameraCaptureThread(%d)++\r\n"), frame_count));

#if 0
		if (frame_count <= 2) {
			//frame_count++;
			// Enable camera interrupt
			s2440INT->INTSUBMSK &= ~(( 1 << IRQ_SUB_CAM_P )|( 1 << IRQ_SUB_CAM_C ));
			s2440INT->INTMSK &= ~( 1 << IRQ_CAM );
			
			continue;
		}
#endif
		
		if (dwCause == WAIT_OBJECT_0) // LJY PWR
		{
			Lock();

			__try
			{

				if (s2440INT->INTSUBMSK & ( 1 << IRQ_SUB_CAM_C ))
				{
					frame_count++;
					cam_intr |= ( 1 << IRQ_SUB_CAM_C );
				    
				    s2440INT->SUBSRCPND  =  (1<<IRQ_SUB_CAM_C);
		            s2440INT->INTSUBMSK &= ~(1<<IRQ_SUB_CAM_C);
					//RETAILMSG(1,(_T("CAM_C, ts %d\r\n"), GetTickCount()));
				}

				if (s2440INT->INTSUBMSK & ( 1 << IRQ_SUB_CAM_P ))
				{
					cam_intr |= ( 1 << IRQ_SUB_CAM_P );
					
					s2440INT->SUBSRCPND  =  (1<<IRQ_SUB_CAM_P);
		            s2440INT->INTSUBMSK &= ~(1<<IRQ_SUB_CAM_P);
					//RETAILMSG(1,(_T("CAM_P, ts %d\r\n"), GetTickCount()));
				}

				if (((s2440INT->INTSUBMSK & ( 1 << IRQ_SUB_CAM_C )) == 0) && ((s2440INT->INTSUBMSK & ( 1 << IRQ_SUB_CAM_P )) == 0))
				{
					RETAILMSG(MSG_EN_1,(_T("[CAM]NOP\r\n")));					
				}
				
				
				InterruptDone(g_CamSysIntr);				
			
				//time = GetTickCount();
				//RETAILMSG(1,(TEXT("+time:%d\r\n"),(time - old_time)));
	
				// Handle any interrupts on the input source
				if (cam_intr & ( 1 << IRQ_SUB_CAM_P ))
				{
					// display the image	
					if (DRIVER_PREVIEW_ENABLE == 1)
					Display_Cam_Image(0,54,PREVIEW_X, PREVIEW_Y, PORT_A);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -