//------------------------------------------------------------------------------ // Function: SendByte // Description: //------------------------------------------------------------------------------ static uint8_t I2CSendByte(uint8_t abyte) { uint8_t error = 0; uint8_t i; for (i = 0; i < 8; i++) { if (abyte & 0x80) SET_SDA(); //send each bit, MSB first else CLEAR_SDA(); if (SetSCLHigh()) //do clock cycle return IIC_SCL_TIMEOUT; CLEAR_SCL(); abyte <<= 1; //shift over to get next bit } SET_SDA(); //listen for ACK #if 1 if (SetSCLHigh()) return IIC_SCL_TIMEOUT; if (GET_SDA()) //error if no ACK { printk("IIC_NOACK\n"); error = IIC_NOACK; } #endif CLEAR_SCL(); return (error); //return 0 for no ACK, 1 for ACK received }
static uint8_t I2CGetByte(uint8_t lastbyte, uint8_t * Data) { uint8_t abyte = 0; uint8_t i; for (i = 0; i < 8; i++) //get each bit, MSB first { if (SetSCLHigh()) return IIC_SCL_TIMEOUT; abyte <<= 1; //shift result over to make room for next bit if (GET_SDA()) abyte++; //same as 'abyte |= 1', only faster CLEAR_SCL(); } if (lastbyte) SET_SDA(); //do not ACK last uint8_t read else CLEAR_SDA(); if (SetSCLHigh()) return IIC_SCL_TIMEOUT; CLEAR_SCL(); SET_SDA(); *Data = abyte; return IIC_OK; }
//------------------------------------------------------------------------------ // Function: SendStop // Description: //------------------------------------------------------------------------------ static uint8_t I2CSendStop(void) { CLEAR_SDA(); if (SetSCLHigh()) return IIC_SCL_TIMEOUT; SET_SDA(); return IIC_OK; }
void PeriodicProcessing( uint8_t inputValue, uint8_t& outputValue ) { #define SET_SDA_ACCORDING_TO_BIT_NUMBER(bitMask) \ if( (currentByte&bitMask) != 0) \ { \ SetSDAHigh(outputValue); \ } \ else \ { \ SetSDALow(outputValue); \ } //if(state != 30) DebugPrintf("%d\n",state); switch(state) { case 30: // Enter command mode. bool dataAvailable; if(numberOfBytes > 0) { SetSCLLow(outputValue); currentByte = inFIFO.NonBlockingGet(dataAvailable); if( dataAvailable == true ) { state = 2; // goto data transfer mode. } numberOfBytes--; } else { currentCmd = cmdFIFO.NonBlockingGet(dataAvailable); if( dataAvailable == true ) { if(currentCmd == 0xfe) { state = 40; // Start condtion. } else if(currentCmd == 0xff) { state = 28; // Stop condition. } else if(currentCmd == 0xfd) { state = 30; // NOP TODO: We shouldn't need this to be pumped thru. } else { numberOfBytes = currentCmd; // number of bytes to transfer. } } } break; case 40: SetSCLHigh(outputValue); // SCL is not already high from previous. SetSDAHigh(outputValue); // SDA is not already high from previous. state = 41; break; case 41: SetSDALow(outputValue); // SCL is already high from previous. Generate START condition (-ve edge on SDA while SCL high) state = 42; break; case 42: SetSCLLow(outputValue); state = 30; break; case 2: // bit 7 SET_SDA_ACCORDING_TO_BIT_NUMBER( 0x80 ); state = 3; break; case 3: SetSCLHigh(outputValue); state = 4; break; case 4: SetSCLLow(outputValue); state = 5; break; case 5: // bit 6 SET_SDA_ACCORDING_TO_BIT_NUMBER( 0x40 ); state = 6; break; case 6: SetSCLHigh(outputValue); state = 7; break; case 7: SetSCLLow(outputValue); state = 8; break; case 8: // bit 5 SET_SDA_ACCORDING_TO_BIT_NUMBER( 0x20 ); state = 9; break; case 9: SetSCLHigh(outputValue); state = 10; break; case 10: SetSCLLow(outputValue); state = 11; break; case 11: // bit 4 SET_SDA_ACCORDING_TO_BIT_NUMBER( 0x10 ); state = 12; break; case 12: SetSCLHigh(outputValue); state = 13; break; case 13: SetSCLLow(outputValue); state = 14; break; case 14: // bit 3 SET_SDA_ACCORDING_TO_BIT_NUMBER( 0x08 ); state = 15; break; case 15: SetSCLHigh(outputValue); state = 16; break; case 16: SetSCLLow(outputValue); state = 17; break; case 17: // bit 2 SET_SDA_ACCORDING_TO_BIT_NUMBER( 0x04 ); state = 18; break; case 18: SetSCLHigh(outputValue); state = 19; break; case 19: SetSCLLow(outputValue); state = 20; break; case 20: // bit 1 SET_SDA_ACCORDING_TO_BIT_NUMBER( 0x02 ); state = 21; break; case 21: SetSCLHigh(outputValue); state = 22; break; case 22: SetSCLLow(outputValue); state = 23; break; case 23: // bit 0 SET_SDA_ACCORDING_TO_BIT_NUMBER( 0x01 ); state = 24; break; case 24: SetSCLHigh(outputValue); state = 25; break; case 25: SetSCLLow(outputValue); state = 26; break; case 26: // ACK bit // stop driving SDA so we can detect ACK state in next state. SetSCLHigh(outputValue); SetSDALow(outputValue); //SetSDAHigh(outputValue); state = 27; break; case 27: SetSCLLow(outputValue); //SetSDAHigh(outputValue); ack = currentLevel; // drive SDA again now we have detected ACK. state = 30; break; case 28: // STOP condition. SDA +ve edge while SCL high. SetSCLHigh(outputValue); state = 29; break; case 29: // STOP condition. SDA +ve edge while SCL high. SetSDAHigh(outputValue); state = 30; break; case 31: break; } }