unsigned char I2C_ReadBit_Wait() { SDAINPUT; I2C_CLOCK_HI(); unsigned int i = 0; unsigned char c = READSDA; while(c>0 && i<=35) { I2CDELAY(1); c = READSDA; i++; } if(c) I2C_DATA_HI(); else I2C_DATA_LO(); SDAOUTPUT; I2CDELAY(1); I2C_CLOCK_LO(); I2CDELAY(1); return c?0:1; // return true on ACK (0) }
//! Send a START Condition void I2C_Start() { I2C_Take(); // XXX Should probably check to see if someone else is using the bus before we do this I2CDELAY(3); I2C_DATA_LO(); I2CDELAY(3); I2C_CLOCK_LO(); I2CDELAY(1); }
//! Send a STOP Condition void I2C_Stop() { I2C_DATA_LO(); I2CDELAY(3); I2C_CLOCK_HI(); I2CDELAY(3); I2C_DATA_HI(); I2CDELAY(1); I2C_Release(); }
//! Write an I2C bit. void I2C_WriteBit( unsigned char c ) { if(c>0) I2C_DATA_HI(); else I2C_DATA_LO(); I2C_CLOCK_HI(); I2CDELAY(1); I2C_CLOCK_LO(); I2CDELAY(1); }
static void stop_cond(void) { /* Pull SDA down */ CLRSDA(); I2CDELAY(I2CSPEED/2); /* Clock stretching - wait for slave to raise it*/ while (READSCL() == 0); /* SCL is high, set SDA from 0 to 1 */ if (READSDA() == 0) { ARBITRATION_LOST(); } I2CDELAY(I2CSPEED/2); start = 0; }
static unsigned char read_bit(void) { unsigned char bit; // Let the slave drive data READSDA(); I2CDELAY(I2CSPEED/2); /* Clock stretching */ while (READSCL() == 0); /* SCL is high, now data is valid */ bit = READSDA(); I2CDELAY(I2CSPEED/2); CLRSCL(); return bit; }
bool stop_cond(void) { /* set SDA to 0 */ CLRSDA(); I2CDELAY(I2CSPEED/2); /* Clock stretching */ while (READSCL() == 0); /* SCL is high, set SDA from 0 to 1 */ if (READSDA() == 0) return false; //arbitration lost I2CDELAY(I2CSPEED/2); start = 0; return true; }
bool read_bit(void) { bool bit; //Let slave drive data signal. READSDA(); I2CDELAY(I2CSPEED/2); /* Clock stretching */ while (READSCL() == 0); /* SCL is high, now data is valid */ bit = READSDA(); I2CDELAY(I2CSPEED/2); CLRSCL(); return bit; }
void i2c_stop_cond(void) { /* set SDA to 0 */ CLRSDA(); I2CDELAY(); /* Clock stretching */ while (READSCL() == 0) ; /* You should add timeout to this loop */ /* SCL is high. Respect I2C spec's minimum stop setup time of 4ms. */ I2CDELAY(); /* set SDA from 0 to 1 */ if (READSDA() == 0) ARBITRATION_LOST(); I2CDELAY(); started = false; }
/* Read a bit from I2C bus */ static int i2c_read_bit(void) { int bit; /* Let the slave drive data */ READSDA(); I2CDELAY(); /* Clock stretching */ while (READSCL() == 0) ; /* You should add timeout to this loop */ /* SCL is high, now data is valid */ bit = READSDA(); I2CDELAY(); CLRSCL(); return bit; }
bool write_bit(bool bit) { if(bit) READSDA(); else CLRSDA(); I2CDELAY(I2CSPEED/2); /* Clock stretching */ while (READSCL() == 0); /* SCL is high, now data is valid */ /* check that nobody is driving SDA */ if (bit && READSDA() == 0) return false; //arbitration lost I2CDELAY(I2CSPEED/2); CLRSCL(); return true; }
/* Write a bit to I2C bus */ static void i2c_write_bit(int bit) { if (bit) READSDA(); else CLRSDA(); I2CDELAY(); /* Clock stretching */ while (READSCL() == 0) ; /* You should add timeout to this loop */ /* SCL is high, now data is valid */ /* If SDA is high, check that nobody else is driving SDA */ if (bit && READSDA() == 0) ARBITRATION_LOST(); I2CDELAY(); CLRSCL(); }
//! Read an I2C bit. unsigned char I2C_ReadBit() { SDAINPUT; I2C_CLOCK_HI(); unsigned char c = READSDA; if(c) I2C_DATA_HI(); else I2C_DATA_LO(); SDAOUTPUT; I2CDELAY(1); I2C_CLOCK_LO(); I2CDELAY(1); return c; }
static void start_cond(void) { if (start) { /* Let SDA rise */ READSDA(); I2CDELAY(I2CSPEED/2); /* Clock stretching */ while (READSCL() == 0); } if (READSDA() == 0) { ARBITRATION_LOST(); } /* SCL is high, we waited for slave to raise it, so pull SDA down */ CLRSDA(); I2CDELAY(I2CSPEED/2); // Now pull SCL down CLRSCL(); start = 1; }
static void write_bit(unsigned char bit) { //Put the bit on SDA by either letting it rise or pulling it down if (bit) { READSDA(); } else { CLRSDA(); } I2CDELAY(I2CSPEED/2); /* Clock stretching - Let SCL rise and wait for slave to let it rise */ while (READSCL() == 0); /* SCL is high, now data is being read */ /* If SDA is high, check that nobody else is driving SDA */ if (bit) { if (READSDA() == 0) { //Oops, someone else pulled SDA down ARBITRATION_LOST(); } } I2CDELAY(I2CSPEED/2); CLRSCL(); }
void i2c_start_cond(void) { if (started) { // if started, do a restart cond // set SDA to 1 READSDA(); I2CDELAY(); // Clock stretching while (READSCL() == 0) ; // You can add a timeout to this loop to // recover from SCL being stuck low. // Repeated start setup time, minimum 4.7us I2CDELAY(); } if (READSDA() == 0) ARBITRATION_LOST(); // SCL is high, set SDA from 1 to 0 CLRSDA(); I2CDELAY(); CLRSCL(); started = true; }
//! read a byte from the I2C slave device unsigned char I2C_Read( unsigned char ack ) { unsigned char res = 0; char i; for (i=0;i<8;i++){ res <<= 1; res |= I2C_ReadBit(); } if( ack > 0) I2C_WriteBit(0); else I2C_WriteBit(1); I2CDELAY(1); return res; }
//! Inits bitbanging port, must be called before using the functions below void I2C_Init() { I2C_Take(); //PULLON; I2CDELAY(1); }
//! Handles an i2c command. void i2c_handle_fn( uint8_t const app, uint8_t const verb, uint32_t const len) { unsigned char i; unsigned long l; switch(verb) { case READ: l = len; if(l > 0) //optional parameter of length l=cmddata[0]; if(!l) //default value of 1 l=1; I2C_Start(); for(i=0; i < l; i++) cmddata[i]=I2C_Read(i<l?1:0); I2C_Stop(); txdata(app,verb,l); break; case WRITE: I2C_Start(); cmddata[0] = cmddata[0] << 1; for(i=0; i<len; i++) { if (!I2C_Write(cmddata[i])) //if NACK break; } I2C_Stop(); cmddata[0] = i; txdata(app,verb,1); break; case PEEK: l = cmddata[0]; I2C_Start(); unsigned char address = cmddata[1] << 1; I2C_Write(address); for(i=2; i < len; i++){ I2C_Write(cmddata[i]); } I2C_Start(); I2C_Write(address|1); // spit out the target address again and flip the read bit I2CDELAY(1); // XXX We should wait for clock to go high here XXX for(i=0; i < l; i++) cmddata[i]=I2C_Read(i+1<l?1:0); // If the next i is still less than l, then ACK I2C_Stop(); txdata(app,verb,l); break; case POKE: break; case START: I2C_Start(); txdata(app,verb,0); break; case STOP: I2C_Stop(); txdata(app,verb,0); break; case SETUP: I2C_Init(); txdata(app,verb,0); break; } }