/* * i2c.c * */ #include #include #include static struct { uint8_t state; long delay; uint16_t len; fifo_t fifo; unsigned char *_buf; uint16_t device; } i2c_param; char local_buf[BUFSIZ]; #define FIFO &i2c_param.fifo /* * I2Cinit: I2C initilazation as master * * Parameters: None. * * Return : None. */ void I2C_Init() { i2c_param.fifo.buf = local_buf; i2c_param.fifo.size = BUFSIZ; i2c_param.delay = 133*10L; // We can safely ignore this i2c_param.len = 0; I2C_ioctl(0,0); } void __attribute__ ((interrupt)) I2C_InterruptHandler(void) { char ch; clear_bit(MCF_I2C_I2SR,MCF_I2C_I2SR_IIF); if( MCF_I2C_I2CR & MCF_I2C_I2CR_MSTA ) { // Masters of the known universe if( MCF_I2C_I2SR & MCF_I2C_I2SR_ICF ) { switch( i2c_param.state ) { case I2C_MXRX: if( fifo_used(&i2c_param.fifo)+1 == i2c_param.len ) { clear_bit(MCF_I2C_I2CR,MCF_I2C_I2CR_MSTA); i2c_param.state = I2C_READY; } else if( fifo_used(&i2c_param.fifo)+2 == i2c_param.len ) { set_bit(MCF_I2C_I2CR,MCF_I2C_I2CR_TXAK); i2c_param.state = I2C_READY; } fifo_put(&i2c_param.fifo,MCF_I2C_I2DR); break; case I2C_ADDR: if( fifo_empty(&i2c_param.fifo) ) { i2c_param.state = I2C_MXRX; clear_bit(MCF_I2C_I2CR,MCF_I2C_I2CR_MTX); // Receive mode set_bit(MCF_I2C_I2CR,MCF_I2C_I2CR_RSTA); ch = MCF_I2C_I2DR; // Dummy read break; } case I2C_MXTX: if( fifo_empty(&i2c_param.fifo) || (MCF_I2C_I2SR&MCF_I2C_I2SR_RXAK) ) { clear_bit(MCF_I2C_I2CR,MCF_I2C_I2CR_MSTA); i2c_param.state = I2C_READY; } else MCF_I2C_I2DR = fifo_get(&i2c_param.fifo); break; } } } else { // Slave mode. int set; if( set = (MCF_I2C_I2SR & MCF_I2C_I2SR_IAL) ) clear_bit(MCF_I2C_I2SR,MCF_I2C_I2SR_IAL); if( MCF_I2C_I2SR & MCF_I2C_I2SR_IAAS ) { if( MCF_I2C_I2SR & MCF_I2C_I2SR_SRW ) { set_bit(MCF_I2C_I2CR,MCF_I2C_I2CR_MTX); fifo_put(&i2c_param.fifo,MCF_I2C_I2DR); } else { clear_bit(MCF_I2C_I2CR,MCF_I2C_I2CR_MTX); ch = MCF_I2C_I2DR; } } else if( !set ) { if( MCF_I2C_I2CR&MCF_I2C_I2CR_MTX ) { if( MCF_I2C_I2SR&MCF_I2C_I2SR_RXAK ) MCF_I2C_I2DR = fifo_get(&i2c_param.fifo); else { clear_bit(MCF_I2C_I2CR,MCF_I2C_I2CR_MTX); ch = MCF_I2C_I2DR; } } else { fifo_put(&i2c_param.fifo,MCF_I2C_I2DR); } } } } void I2C_send(unsigned short device, unsigned char *buf, unsigned short len) { if( len > i2c_param.fifo.size ) return; i2c_param.len = len; fifo_clear(&i2c_param.fifo); if( device > 127 ) // Use I2C 10 bit address { fifo_put(FIFO,0b11110|((device>>5)&6)|I2C_WRITE); fifo_put(FIFO,device&255); } else fifo_put(FIFO,((device<<1)&0xFE)|I2C_WRITE); fifo_write(FIFO,buf,len); i2c_param.state = I2C_MXTX; } void I2C_receive(unsigned short device, unsigned char *buf, unsigned short len) { if( len > i2c_param.fifo.size ) return; i2c_param.len = len; fifo_clear(FIFO); if( device > 127 ) // Use I2C 10 bit address { fifo_put(FIFO,0b11110|((device>>5)&6)|I2C_READ); fifo_put(FIFO,device&255); } else fifo_put(FIFO,((device<<1)&0xFE)|I2C_READ); i2c_param.state = I2C_ADDR; } int I2C_ioctl(unsigned int index, unsigned long val) { unsigned short len = val; uint8_t temp; // Set device as slave or switch( index ) { case I2CTLINIT: // make me master /* set the frequency near 400KHz */ MCF_I2C_I2FDR = MCF_I2C_I2FDR_IC(0x10); /* start the module */ MCF_I2C_I2CR = MCF_I2C_I2CR_IIEN | MCF_I2C_I2CR_IEN; /* if bit busy set, send a stop condition to slave module */ if(MCF_I2C_I2SR & MCF_I2C_I2SR_IBB) { MCF_I2C_I2CR = 0; /* clear control register */ MCF_I2C_I2CR = MCF_I2C_I2CR_IIEN|MCF_I2C_I2CR_IEN|MCF_I2C_I2CR_MSTA; /* enable module & send a START condition */ temp = MCF_I2C_I2DR; /* dummy read */ MCF_I2C_I2SR = 0; /* clear status register */ MCF_I2C_I2CR = 0; /* clear control register */ MCF_I2C_I2CR = MCF_I2C_I2CR_IIEN|MCF_I2C_I2CR_IEN; /* enable the module again */ } i2c_param.state = I2C_READY; i2c_param._buf = 0; break; case I2CTLSBUF: i2c_param._buf = (char *)val; break; case I2CTLDEV: i2c_param.device = val; break; case I2CTLREAD: if( i2c_param._buf == 0 || i2c_param.device == 0 ) return -1; I2C_receive(i2c_param.device,i2c_param._buf,len); break; case I2CTLWRITE: if( i2c_param._buf == 0 || i2c_param.device == 0 ) return -1; I2C_send(i2c_param.device,i2c_param._buf,len); break; } }