www.pudn.com > ADS_s3c2440a.rar > camproset.c


/******************************************************************************

 Filename:	camproset.c

 Descriptions		
 - Camera Processor Initialization code using SCCB.
 - SCCB(Serial Camera Contol Bus) H/W dependent code.
 - Camera Processor Initialization code using IIC.

 History
  - July 23, 2003. Draft Version 0.0 by purnnamu
  - Janualy 15, 2004. Modifed by Boaz
  - Feb. 10, 2004. Modified by junon for S3C2440A

 
 Copyright (c) 2003 SAMSUNG Electronics.
 # However, Anybody can use this code without our permission.  

 ******************************************************************************/


#include 
#include 
#include 

#include "def.h"
#include "2440addr.h"
#include "2440lib.h"
#include "camproset.h"
#include "camdef.h"
#include "camdata.h"


#define CAMWRDATA      (1)
#define CAMRDDATA      (3)
#define CAMSETRDADDR   (4)

#define CAMIICBUFSIZE 0x20


#if USED_CAM_TYPE==CAM_OV7620
#define CAM_ID		(0x42)
#define CAM_NAME  "OV7620"
#elif USED_CAM_TYPE==CAM_S5X433
#define CAM_ID		(0x42)
#define CAM_NAME  "S5X433"
#elif USED_CAM_TYPE==CAM_S5X532
#define CAM_ID		(0x5a)
#define CAM_NAME  "S5X532"
#elif USED_CAM_TYPE==CAM_S5X3A1
#define CAM_ID		(0x5a)
#define CAM_NAME  "S5X3A1"
#elif USED_CAM_TYPE==CAM_AU70H
#define CAM_ID		(0x22)
#define CAM_NAME  "AU70H"
#endif


static U8 _CAMiicData[CAMIICBUFSIZE];
static volatile int _CAMiicDataCount;
static volatile int _CAMiicStatus;
static volatile int _CAMiicMode;
static int _CAMiicPt;

volatile U32 save_GPECON;


void * func_cammodule_test[][2]=
{								   
	//IIC 	
	(void *)Camera_WriteByte, 	"Write 1 byte data into Camera module register",
	(void *)Camera_ReadByte,  	"Read 1 byte data from Camera module register",
	(void *)Camera_WriteBlock,  	"Write a block of byte data into Camera module register",
	(void *)Camera_ReadBlock,  	"Read a block of byte data from Camera module register",
	0,0
};


void Camera_Iic_Test(void)
{
	int i, camclk;

	CameraModuleSetting();

	Uart_Printf("\n***** IIC Master Tx/Rx Test Program with %s Camera Module *****\n", CAM_NAME);

	while(1) 	{
		i=0;
		Uart_Printf("\n\n");

		while(1) {   //display menu
			Uart_Printf("%2d:%s\n", i, func_cammodule_test[i][1]);
			i++;
			if((int)(func_cammodule_test[i][0])==0) {
				Uart_Printf("\n");
				break;
			}
			if((i%4)==0)
			Uart_Printf("\n");
		}

		Uart_Printf("\nPress Enter key to exit : ");
		i = Uart_GetIntNum();

		if(i==-1) break;		// return.
		if(i>=0 && (i<((sizeof(func_cammodule_test)-1)/8)) )	// select and execute...
			( (void (*)(void)) (func_cammodule_test[i][0]) )();
	}

	Uart_Printf("\n");
   	rINTMSK |= BIT_IIC;
}


void IicPortSet(void)
{
	save_GPECON = rGPECON;
	rGPECON = rGPECON & ~(0xf<<28) | (0xa<<28);	//GPE15:IICSDA , GPE14:IICSCL 	 
}

void IicPortReturn(void)
{
	rGPECON = save_GPECON;
}

void Wr_CamIIC(U32 slvAddr, U32 addr, U8 data)
{
	_CAMiicMode      = CAMWRDATA;
	_CAMiicPt        = 0;
	_CAMiicData[0]   = (U8)addr;
	_CAMiicData[1]   = data;
	_CAMiicDataCount = 2;
    
	rIICDS        = slvAddr;            //0x5a: S5X532 Slave ID 
	rIICSTAT      = 0xf0; //Start Master TX Condition    
	rIICCON &= ~(1<<4);   //Clearing the pending bit isn't needed because the pending bit has been cleared.

	while(_CAMiicDataCount!=-1);
}

void Rd_CamIIC(U32 slvAddr,U32 addr,U8 *data)
{

	/*IIC Slave Addr Write + IIC Reg Addr Write */	
	_CAMiicMode      = CAMSETRDADDR;
	_CAMiicPt        = 0;
	_CAMiicData[0]   = (U8)addr;
	_CAMiicDataCount = 1;

	rIICDS   = slvAddr;
	rIICSTAT = 0xf0;   //Master Tx, Start
	rIICCON &= ~(1<<4);                    //Resumes IIC operation.  
	//Clearing the pending bit isn't needed because the pending bit has been cleared.
	while(_CAMiicDataCount!=-1);
    
	_CAMiicMode      = CAMRDDATA;
	_CAMiicPt        = 0;
	_CAMiicDataCount = 1;
    
	rIICDS   = slvAddr;
	rIICSTAT = 0xb0;                    //Master Rx,Start
	rIICCON &= ~(1<<4);                   //Resumes IIC operation.   
    
	while(_CAMiicDataCount!=-1);

	*data = _CAMiicData[1];
}


void __irq Cam_IICInt(void)
{
	U32 iicSt,i;

	ClearPending(BIT_IIC);
	iicSt   = rIICSTAT; 
	rINTMSK |= BIT_IIC;

	if(iicSt & 0x8){}           //When bus arbitration is failed.
	if(iicSt & 0x4){}           //When a slave address is matched with IICADD
	if(iicSt & 0x2){}           //When a slave address is 0000000b
	if(iicSt & 0x1){}           //When ACK isn't received

	switch(_CAMiicMode) {
		case CAMRDDATA:
			if((_CAMiicDataCount--)==0) {
				_CAMiicData[_CAMiicPt++] = rIICDS;
            
				rIICSTAT = 0x90;      //Stop MasRx condition 
				rIICCON  &= ~(1<<4);      //Resumes IIC operation.
				Delay(1);                 //Wait until stop condtion is in effect., Too long time...  # need the time 2440:Delay(1), 24A0: Delay(2)
								//The pending bit will not be set after issuing stop condition.
				break;    
			}      
			_CAMiicData[_CAMiicPt++] = rIICDS;     //The last data has to be read with no ack.

			if((_CAMiicDataCount)==0)
				rIICCON &= ~((1<<7)|(1<<4));      //Resumes IIC operation with NOACK in case of S5X532 Cameara  
//				rIICCON = 0x6f;			//Resumes IIC operation with NOACK in case of S5X532 Cameara	
			else 
				rIICCON &= ~(1<<4);      //Resumes IIC operation with ACK
			break;
		case CAMWRDATA:
			if((_CAMiicDataCount--)==0) {
				rIICSTAT = 0xd0;                //stop MasTx condition 
				rIICCON  &= ~(1<<4);                //resumes IIC operation.
				Delay(1);                       //wait until stop condtion is in effect. # need the time 2440:Delay(1), 24A0: Delay(2)
					//The pending bit will not be set after issuing stop condition.
				break;    
			}
			rIICDS = _CAMiicData[_CAMiicPt++];        //_iicData[0] has dummy.
			for(i=0;i<10;i++);                  //for setup time until rising edge of IICSCL
				rIICCON &= ~(1<<4);                     //resumes IIC operation.
			break;
		case CAMSETRDADDR: //Uart_Printf("[S%d]",_iicDataCount);
			if((_CAMiicDataCount--)==0) {
				rIICSTAT = 0xd0;                //stop MasTx condition 
				rIICCON  &= ~(1<<4);                //resumes IIC operation.
				Delay(1);      //wait until stop condtion is in effect.

				break;                  //IIC operation is stopped because of IICCON[4]    
			}
			rIICDS = _CAMiicData[_CAMiicPt++];
			for(i=0;i<10;i++);          //for setup time until rising edge of IICSCL
				rIICCON &= ~(1<<4);             //resumes IIC operation.
			break;
		default:
			break;      
	}

	rINTMSK &= ~BIT_IIC;
}


void Camera_WriteByte(void)
{
	unsigned int i, j, save_E, save_PE, RegAddr, RegData, pageNo;
      	
#if (USED_CAM_TYPE==CAM_S5X532)||(USED_CAM_TYPE==CAM_S5X3A1)
	Uart_Printf("Input Write Page No of %s\n=>", CAM_NAME);
	pageNo = (U8)Uart_GetIntNum();
#endif

	Uart_Printf("Input Write Register Address of %s\n=>", CAM_NAME);
	RegAddr = (U8)Uart_GetIntNum();
    
	Uart_Printf("Input Write Transfer Data into %s\n=>", CAM_NAME);
	RegData = (U8)Uart_GetIntNum();

#if (USED_CAM_TYPE==CAM_S5X532)||(USED_CAM_TYPE==CAM_S5X3A1)
	Wr_CamIIC(CAM_ID, (U8)0xec, pageNo);  // set Page no
#endif
	Wr_CamIIC(CAM_ID, (U8)RegAddr, RegData); // set register after setting page number
}


void Camera_ReadByte(void)
{
	unsigned int i, j, save_E, save_PE, RegAddr, RegData, pageNo;
	static U8 rdata[8];
      	
#if (USED_CAM_TYPE==CAM_S5X532)||(USED_CAM_TYPE==CAM_S5X3A1)
	Uart_Printf("Input Write Page No of %s\n=>", CAM_NAME);
	pageNo = (U8)Uart_GetIntNum();
	Wr_CamIIC(CAM_ID, (U8)0xec, pageNo);  // set Page no
#endif

	Uart_Printf("Input Read Register Address of %s\n=>", CAM_NAME);
	RegAddr = (U8)Uart_GetIntNum();
	Rd_CamIIC(CAM_ID, RegAddr, &rdata[0]); 
	Uart_Printf("Register Addr: 0x%2x, data: 0x%2x\n", RegAddr,rdata[0]);
}


void Camera_WriteBlock(void)
{
	unsigned int i, j, save_E, save_PE, RegAddr, RegData;
	static U8 rdata[256]; 

#if USED_CAM_TYPE==CAM_OV7620
	for(i=0; i<(sizeof(Ov7620_YCbCr8bit)/2); i++)
		Wr_CamIIC(CAM_ID, Ov7620_YCbCr8bit[i][0], Ov7620_YCbCr8bit[i][1]);
#elif USED_CAM_TYPE==CAM_S5X532
	for(i=0; i<(sizeof(S5X532_YCbCr8bit)/2); i++)
		Wr_CamIIC(CAM_ID, S5X532_YCbCr8bit[i][0], S5X532_YCbCr8bit[i][1]);
#elif USED_CAM_TYPE==CAM_S5X3A1
		for(i=0; i<(sizeof(S5X3A1_YCbCr8bit)/2); i++)
			Wr_CamIIC(CAM_ID, S5X3A1_YCbCr8bit[i][0], S5X3A1_YCbCr8bit[i][1]);
#elif USED_CAM_TYPE==CAM_AU70H
	for(i=0; i<(sizeof(Au70h)/2); i++)
		Wr_CamIIC(CAM_ID, Au70h[i][0], Au70h[i][1]);
#endif
	
   Uart_Printf("\nBlock TX Ended...\n");	
}


void Camera_ReadBlock(void)
{
	unsigned int i, j, save_E, save_PE, RegAddr, RegData;
	static U8 rdata[256]; 

#if USED_CAM_TYPE==CAM_OV7620
	for(i=0; i<(sizeof(Ov7620_YCbCr8bit)/2);i++)
		Rd_CamIIC(CAM_ID, Ov7620_YCbCr8bit[i][0], &rdata[i]); 
	for(i=0; i<(sizeof(Ov7620_YCbCr8bit)/2);i++)
		Uart_Printf("Addr: 0x%2x, W: 0x%2x, R: 0x%2x\n", Ov7620_YCbCr8bit[i][0], Ov7620_YCbCr8bit[i][1], rdata[i]);
#elif USED_CAM_TYPE==CAM_S5X532
    for(i=0; i<(sizeof(S5X532_YCbCr8bit)/2);i++)
   	{     
		if(S5X532_YCbCr8bit[i][0] == 0xec)
			Wr_CamIIC(CAM_ID, S5X532_YCbCr8bit[i][0], S5X532_YCbCr8bit[i][1]);
		else
			Rd_CamIIC(CAM_ID, S5X532_YCbCr8bit[i][0], &rdata[i]); 
    }
  	for(i=0; i<(sizeof(S5X532_YCbCr8bit)/2);i++)
	{
	  	if(S5X532_YCbCr8bit[i][0] == 0xec)
	       Uart_Printf("Page: 0x%2x\n",  S5X532_YCbCr8bit[i][1]);
		else
	  		Uart_Printf("Addr: 0x%2x, W: 0x%2x, R: 0x%2x\n", S5X532_YCbCr8bit[i][0], S5X532_YCbCr8bit[i][1], rdata[i]);
  	}      
#elif USED_CAM_TYPE==CAM_S5X3A1
	for(i=0; i<(sizeof(S5X3A1_YCbCr8bit)/2);i++)
	{ 		
	if(S5X3A1_YCbCr8bit[i][0] == 0xec)
		Wr_CamIIC(CAM_ID, S5X3A1_YCbCr8bit[i][0], S5X3A1_YCbCr8bit[i][1]);
	else
		Rd_CamIIC(CAM_ID, S5X3A1_YCbCr8bit[i][0], &rdata[i]); 
	}
	for(i=0; i<(sizeof(S5X3A1_YCbCr8bit)/2);i++)
{
		if(S5X3A1_YCbCr8bit[i][0] == 0xec)
			 Uart_Printf("Page: 0x%2x\n",  S5X3A1_YCbCr8bit[i][1]);
	else
			Uart_Printf("Addr: 0x%2x, W: 0x%2x, R: 0x%2x\n", S5X3A1_YCbCr8bit[i][0], S5X3A1_YCbCr8bit[i][1], rdata[i]);
	} 		 
#elif USED_CAM_TYPE==CAM_AU70H
	for(i=0; i<(sizeof(Au70h)/2);i++)
		Rd_CamIIC(CAM_ID, Au70h[i][0], &rdata[i]); 
	for(i=0; i<(sizeof(Au70h)/2);i++)
		Uart_Printf("Addr: 0x%2x, W: 0x%2x, R: 0x%2x\n", Au70h[i][0], Au70h[i][1], rdata[i]);
#endif

}


int CameraModuleSetting(void)
{
	unsigned int i, j, save_E, save_PE, RegAddr, RegData;
	static U8 rdata[256]; 
	int donestatus;
      	
	IicPortSet();

	// for camera init, added by junon
	pISR_IIC = (unsigned)Cam_IICInt; 
	rINTMSK &= ~(BIT_IIC);

	//Enable ACK, Prescaler IICCLK=PCLK/512, Enable interrupt, Transmit clock value Tx clock=IICCLK/16
	rIICCON  = (1<<7) | (1<<6) | (1<<5) | (0x3);

	rIICADD  = 0x10;                    //24A0 slave address = [7:1]
	rIICSTAT = 0x10;                    //IIC bus data output enable(Rx/Tx)
	rIICLC = (1<<2)|(3);   			// SDAOUT has 5clock cycle delay

	donestatus=1;

	Camera_WriteBlock();
//	Camera_ReadBlock();
	
	return donestatus;
}