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

📄 cci2c.c

📁 linux平台上的开放源代码的网络摄像机程序.实现视频捕捉,传输以及云台控制等.非常具有参考价值.
💻 C
字号:
/*!****************************************************************************! 05.03.2002 splitted huge cmoscam.c*! removed all sensor specifics (shadow registers, invalidate window)*! FILE NAME  : cci2c.c*!*! DESCRIPTION: TBD*! used i2.c v2.2 by Axis* removed all "CLI-s" they could be needed for delay counter ?*//****************** INCLUDE FILES SECTION ***********************************/#include <linux/module.h>#include <linux/sched.h>#include <linux/slab.h>#include <linux/errno.h>#include <linux/kernel.h>#include <linux/fs.h>#include <linux/string.h>#include <linux/init.h>#include <linux/config.h>#include <asm/system.h>#include <asm/svinto.h>#include <asm/io.h>#include <asm/irq.h>#include <asm/delay.h>#include <asm/uaccess.h>#include <asm/cmoscama.h>#include "cc303.h"#include "cci2c.h"#define D(x)/****************** I2C DEFINITION SECTION *************************/#define CLOCK_LOW_TIME            8#define CLOCK_HIGH_TIME           8#define START_CONDITION_HOLD_TIME 8#define STOP_CONDITION_HOLD_TIME  8#define ENABLE_OUTPUT 0x01#define ENABLE_INPUT 0x00#define I2C_CLOCK_HIGH 1#define I2C_CLOCK_LOW 0#define I2C_DATA_HIGH 1#define I2C_DATA_LOW 0/* use the kernels delay routine */#define i2c_delay(usecs) udelay(usecs)void i2c_disable(int n);void i2c_dir_out(int n);void i2c_dir_in (int n);void i2c_scl_0  (int n);void i2c_scl_1  (int n);void i2c_sda    (int n, int d);	/* d is checked against zero only, it does not need to be "1" */ int i2c_getbit	(int n);int i2c_getscl(int n);			/* just for i2c testing */int i2c_diagnose(int n);int	i2c_start(int n);void i2c_stop(int n);int i2c_outbyte(int n, unsigned char d);unsigned char i2c_inbyte(int n);void i2c_sendack(int n);/* I2C functions */void i2c_disable(int n) { //first disable, then set high if (n) {   ccamCRAnd(~CCAM_BITS(SCL1_EN,1) & ~CCAM_BITS(SDA1_EN,1));   ccamCROr (CCAM_BITS(SCL1,1) | CCAM_BITS(SDA1,1)); } else {   ccamCRAnd(~CCAM_BITS(SCL0_EN,1) & ~CCAM_BITS(SDA0_EN,1));   ccamCROr (CCAM_BITS(SCL0,1) | CCAM_BITS(SDA0,1)); }}void i2c_dir_out(int n) { //first  set high, then enable  D(printk("i2c_dir_out bus= %x, was port= %x\n\r",n,ccam_cr_shadow)); if (n) {   ccamCROr  (CCAM_BITS(SCL1,1) | CCAM_BITS(SDA1,1));   ccamCROr  (CCAM_BITS(SCL1_EN,1) | CCAM_BITS(SDA1_EN,1)); } else {   ccamCROr  (CCAM_BITS(SCL0,1) | CCAM_BITS(SDA0,1));   ccamCROr  (CCAM_BITS(SCL0_EN,1) | CCAM_BITS(SDA0_EN,1)); }  D(printk("i2c_dir_out new port= %x\n\r",ccam_cr_shadow));}void i2c_dir_in(int n) {  // should be called after i2c_dir_out if (n)	{   ccamCROr  (CCAM_BITS(SDA1,1));   ccamCRAnd (~CCAM_BITS(SDA1_EN,1)); } else {   ccamCROr  (CCAM_BITS(SDA0,1));   ccamCRAnd (~CCAM_BITS(SDA0_EN,1)); }}void i2c_scl_0(int n) { if (n)  ccamCRAnd (~CCAM_BITS(SCL1,1)); else    ccamCRAnd (~CCAM_BITS(SCL0,1)); }void i2c_scl_1(int n) { if (n)  ccamCROr (CCAM_BITS(SCL1,1)); else    ccamCROr (CCAM_BITS(SCL0,1)); }void i2c_sda (int n, int d) {	// will also force sda enable if (n) { 	if (d) ccamCROr  ( CCAM_BITS(SDA1,1));	else   ccamCRAnd (~CCAM_BITS(SDA1,1));        ccamCROr (CCAM_BITS(SDA1_EN,1)); } else { 	if (d) ccamCROr  ( CCAM_BITS(SDA0,1));	else   ccamCRAnd (~CCAM_BITS(SDA0,1));        ccamCROr (CCAM_BITS(SDA0_EN,1)); }}// #define CCAM_SR(x) ((port_csp0_addr[CCAM__RA__SR] >> CCAM_SR__##x ) & 1)int i2c_getbit(int n) {  return n? CCAM_SR(SDA1) : CCAM_SR(SDA0);}int i2c_getscl(int n) {  return n? CCAM_SR(SCL1) : CCAM_SR(SCL0);}/* diagnose i2c bus problems. Will always return non-zeroNormally is called from i2c_start, if it detects problem  */int i2c_diagnose(int n) {	int error=0;  D(printk("i2c_diagnose:  bus=%x\r\n", n));	while (!error) {		i2c_dir_out(n);	// will force high SCL, SDA		i2c_delay(CLOCK_HIGH_TIME);		if (!i2c_getbit(n)) error |= ERR_I2C_SDA_ST0;		if (!i2c_getscl(n)) error |= ERR_I2C_SCL_ST0;		if (error) break;		i2c_scl_0(n);		i2c_sda  (n,0);		i2c_delay(CLOCK_LOW_TIME);		if (!i2c_getbit(n)) error |= ERR_I2C_SDA_ST0;		if (!i2c_getscl(n)) error |= ERR_I2C_SCL_ST0;		if (error) break;		i2c_disable(n); // first diseble, then sets high		i2c_delay(CLOCK_HIGH_TIME*2);		if (!i2c_getbit(n)) error |= ERR_I2C_SDA_NOPULLUP;		if (!i2c_getscl(n)) error |= ERR_I2C_SCL_NOPULLUP;		if (error) break;		i2c_sda(n,0);	// scl will be left disabled (high)		if (!i2c_getscl(n)) error |= ERR_I2C_SHORT;		break;	}	if (!error) error =	 ERR_I2C_NOTDETECTED;	/* try start-stop to reset effects of playing with sda/scl lines */	i2c_dir_out(n);	// will force high SCL, SDA	i2c_sda (n,0);	i2c_delay(START_CONDITION_HOLD_TIME);	i2c_scl_0(n);	i2c_delay(CLOCK_LOW_TIME*2);	i2c_scl_1(n);	i2c_delay(CLOCK_HIGH_TIME*2);	i2c_sda (n,1);	i2c_delay(STOP_CONDITION_HOLD_TIME);	i2c_disable(n);	return error;}/* generate i2c start condition and test bus */int	i2c_start(int n) {//	int error=0;	int i;  D(printk("i2c_start:  bus=%x\r\n", n));	/* SCL=1 SDA=1 */	i2c_dir_out(n);	// will set high SCL, SDA	i2c_delay(CLOCK_HIGH_TIME/2);	/* if the periferial (?) driving sda low (after being interrupted)? - try to recover */	i2c_dir_in(n);	i2c_delay(CLOCK_HIGH_TIME/2);	if (!i2c_getbit(n)) {		for (i=0;(i<9) && !i2c_getbit(n);i++) {			i2c_scl_0(n);			i2c_delay(CLOCK_LOW_TIME);			i2c_scl_1(n);			i2c_delay(CLOCK_HIGH_TIME);		}		if (!i2c_getbit(n)) return  i2c_diagnose(n); // did not help - really stuck		/* it is breathing - try "START"-"STOP" */		i2c_sda (n,0);		i2c_delay(START_CONDITION_HOLD_TIME);		i2c_scl_0(n);		i2c_delay(CLOCK_LOW_TIME*2);		i2c_scl_1(n);		i2c_delay(CLOCK_HIGH_TIME*2);		i2c_sda (n,1);		i2c_delay(STOP_CONDITION_HOLD_TIME);	}	/* SCL=1 SDA=1 */	i2c_dir_out(n);	// will set high SCL, SDA	i2c_delay(CLOCK_HIGH_TIME/2);	if ((!i2c_getbit(n)) || (!i2c_getscl(n))) return  i2c_diagnose(n);	/* SCL=1 SDA=0 */	i2c_sda (n,0);	i2c_delay(START_CONDITION_HOLD_TIME);	if (( i2c_getbit(n)) || (!i2c_getscl(n))) return  i2c_diagnose(n);	/* SCL=0 SDA=0 */	i2c_scl_0(n);	i2c_delay(CLOCK_LOW_TIME);	if (( i2c_getbit(n)) || ( i2c_getscl(n))) return  i2c_diagnose(n);	return 0;}/* generate i2c stop condition */void i2c_stop(int n) {	// assumed to be enabled	/* SCL=0 SDA=0  */  D(printk("i2c_stop:  bus=%x\r\n", n));	i2c_scl_0(n);	i2c_sda (n,0);	i2c_delay(CLOCK_LOW_TIME*2);	/* SCL=1 SDA=0 */	i2c_scl_1(n);	i2c_delay(CLOCK_HIGH_TIME*2);	/* SCL=1 SDA=1 */	i2c_sda (n,1);	i2c_delay(STOP_CONDITION_HOLD_TIME);	i2c_disable(n);	// both high with resistor pull-up}/* write a byte to the i2c interface , return acknowledge */int i2c_outbyte(int n, unsigned char d) { 	int i;	unsigned char x=d;	// make it non-destructive  D(printk("i2c_outbyte:  bus=%x byte=%x\r\n", n, x));	for (i = 0; i < 8; i++) { // assumed to be with SCL=0;		i2c_sda (n,(x & 0x80));	// checks only on non-zero, so no need to '>>'		i2c_delay(CLOCK_LOW_TIME/2);		i2c_scl_1(n);		i2c_delay(CLOCK_HIGH_TIME);		i2c_scl_0(n);		i2c_delay(CLOCK_LOW_TIME/2);		x <<= 1;	}	/* enable input	 */	i2c_dir_in(n);	i2c_delay(CLOCK_LOW_TIME/2);	i2c_scl_1(n);	i2c_delay(CLOCK_HIGH_TIME);	i= (1-i2c_getbit(n));	i2c_scl_0(n);	i2c_delay(CLOCK_LOW_TIME/2);  D(printk("i2c_outbyte:  ACK=%x\r\n", i));	return i;}/* read a byte from the i2c interface */unsigned char i2c_inbyte(int n) { // assumed SCL=0, SDA=X	unsigned char aBitByte = 0;	int i;	/* enable input */  D(printk("i2c_inbyte:  bus=%x\r\n", n));	i2c_dir_in(n);	/* get bits	 */	for (i = 0; i < 8; i++) {		i2c_delay(CLOCK_LOW_TIME/2);		/* low clock period	 */		i2c_scl_1(n);		i2c_delay(CLOCK_HIGH_TIME);		aBitByte = (aBitByte << 1) | i2c_getbit(n);		i2c_scl_0(n);		i2c_delay(CLOCK_LOW_TIME/2);	}  D(printk("i2c_inbyte:  data=%x\r\n", aBitByte));	return aBitByte;	// returns with SCL=0, SDA - OFF}/*#---------------------------------------------------------------------------*#*# FUNCTION NAME: I2C::sendAck*#*# DESCRIPTION  : Send ACK on received data*#*#--------------------------------------------------------------------------*/void i2c_sendack(int n) {	 D(printk("i2c_sendack:  bus=%x\r\n", n));		i2c_sda (n,0);		i2c_delay(CLOCK_LOW_TIME/2);		i2c_scl_1(n);		i2c_delay(CLOCK_HIGH_TIME);		i2c_scl_0(n);		i2c_delay(CLOCK_LOW_TIME/2);}/*#---------------------------------------------------------------------------*#*# FUNCTION NAME: i2c_writeData*#*# DESCRIPTION  : Writes a sequence of bytes to an I2C device*# removed retries, will add test-ready later as a separate function*# removed all "dummy stuff" - I never needed that*#*#--------------------------------------------------------------------------*/int i2c_writeData(int n, unsigned char theSlave, unsigned char *theData, int size) {	int i,error=0;	/* we don't like to be interrupted	*** WHY??? *** 	 */   D(printk("i2c_writeData:  bus=%x theSlave=%x data=%x %x size=%x\r\n", n, theSlave, theData[0], theData[1], size));	/* generate start condition, test bus */	if ((error=i2c_start(n))) return error;	/* send slave address, wait for ack */	if(!i2c_outbyte(n,theSlave)) {		 i2c_stop(n);		 return ERR_I2C_BSY;	// device does not exist or not ready	}// OK, now send theData verifying ACK goes after each byte	for (i=0;i<size;i++) {		if(!i2c_outbyte(n,theData[i])) {			i2c_stop(n);		 	return ERR_I2C_NACK;	// device failure		}	}	i2c_stop(n);	return 0;}/*#---------------------------------------------------------------------------*#*# FUNCTION NAME: i2c_readData*#*# DESCRIPTION  : Reads a data from the i2c device, returns 0- OK, else - error code*#*#--------------------------------------------------------------------------*/int i2c_readData(int n, unsigned char theSlave, unsigned char *theData, int size) {	int i, error=0;	if ((error=i2c_start(n))) return error;	/* send slave address, wait for ack */   D(printk("i2c_readData:  bus=%x theSlave=%x size=%x\r\n", n, theSlave, size));	if(!i2c_outbyte(n,theSlave)) {		 i2c_stop(n);		 return ERR_I2C_BSY;	// device does not exist or not ready	}	for (i=0;i<size;i++) {		theData[i]=i2c_inbyte(n);		i2c_sendack(n);	}	 i2c_stop(n);	 return 0; 	}/* Main device API. ioctl's to write or read to/from i2c registers.  */// for now - single register read/write onlyint i2c_ioctl(struct inode *inode, struct file *file,	  unsigned int cmd, unsigned long arg) {	  unsigned char data[2];	  int error=0;   D(printk("i2c_ioctl cmd= %x, arg= %x\n\r",cmd,arg));   D(printk("i2c_ioctl:  ((int *)file->private_data)[0]= %x\n\r",((int *)file->private_data)[0]));	if(_IOC_TYPE(cmd) != CMOSCAM_IOCTYPE) {		return -EINVAL;	}//int i2c_writeData(int n, unsigned char theSlave, unsigned char *theData, int size) {	switch (_IOC_NR(cmd)) {		case I2C_WRITEREG:/*			if ( (( I2C_ARGBUS(arg)) == 0) &&	// copy zr32112 parameters			     ((I2C_ARGSLAVE(arg)) == sensor_i2c_addr) //&& // was 0x60                            ) {				set_imageParamsR   (P_DMA_VALID, 0);				sensor_i2c_regs[ I2C_ARGREG(arg) ] = ( I2C_ARGVALUE(arg) );			      }*/			/* write to an i2c slave */			D(printk("i2cw bus=%d, slave=%d, reg=%d, value=%d\n", 				 I2C_ARGBUS(arg),				 I2C_ARGSLAVE(arg),				 I2C_ARGREG(arg),				 I2C_ARGVALUE(arg)));			data[0]=I2C_ARGREG(arg);			data[1]=I2C_ARGVALUE(arg);			return -i2c_writeData(I2C_ARGBUS(arg), I2C_ARGSLAVE(arg) & 0xfe, &data[0], 2);		case I2C_READREG:		{			/* read from an i2c slave */			D(printk("i2cr bus=%d, slave=%d, reg=%d ", 				 I2C_ARGBUS(arg),				 I2C_ARGSLAVE(arg),				 I2C_ARGREG(arg)));			data[0]=I2C_ARGREG(arg);			error=i2c_writeData(I2C_ARGBUS(arg), I2C_ARGSLAVE(arg) & 0xfe, &data[0], 1);			if (error) return -error;			error=i2c_readData(I2C_ARGBUS(arg), I2C_ARGSLAVE(arg) | 0x01, &data[1], 1);			if (error) return -error;			D(printk("returned %d\n", data[1]));/*			if ( (( I2C_ARGBUS(arg)) == 0) &&	// copy zr32112 parameters			     ((I2C_ARGSLAVE(arg)) == sensor_i2c_addr) // &&  // was 0x60                           ) sensor_i2c_regs[ I2C_ARGREG(arg) ] = data[1];*/			return data[1];		}					    		default:			return -EINVAL;	}		return 0;}

⌨️ 快捷键说明

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