#include <avr/io.h>
#ifndef F_CPU
#define F_CPU 16000000UL
#endif
#include <util/delay.h>
#define I2C_SDA_DDR DDRB
#define I2C_SCL_DDR DDRB
#define I2C_TEST_DDR DDRB
#define I2C_SDA_PORT PORTB
#define I2C_SCL_PORT PORTB
#define I2C_TEST_PORT PORTB
#define I2C_SDA_PIN PB1
#define I2C_SCL_PIN PB2
#define I2C_TEST_PIN PB5
#define STARTB 0x00 //star bit
#define STOPB 0x01 //stop bit
#define setPin(pport, ppin, pbit) \
(pport = pbit \
? pport | (0x01 << ppin) \
: pport & (~(0x01 << ppin)))
uint8_t ack;
void setStaSto(const uint8_t pStaSto){
//reset SCL and SDA
pStaSto \
? setPin(I2C_SDA_PORT, I2C_SDA_PIN, 0x01) \
: setPin(I2C_SDA_PORT, I2C_SDA_PIN, 0x00);
setPin(I2C_SCL_PORT, I2C_SCL_PIN, 0x00);
//SDA HIGH for StartBit, SDA LOW, for StopBit
pStaSto
? setPin(I2C_SDA_PORT, I2C_SDA_PIN, 0x00) //begin stop bit
: setPin(I2C_SDA_PORT, I2C_SDA_PIN, 0x01); //begin start bit
setPin(I2C_SCL_PORT, I2C_SCL_PIN, 0x01);
_delay_us(0x01); //7 - tSU:sTA > 600nS
//SDA LOW for StartBit, SDA HIGH for StopBit
pStaSto
? setPin(I2C_SDA_PORT, I2C_SDA_PIN, 0x01) //end stop bit
: setPin(I2C_SDA_PORT, I2C_SDA_PIN, 0x00); //end start bit
_delay_us(0x01); //6 - tHD:sTA > 600nS
//set SCL LOW, end of Start or Stop Conditions
setPin(I2C_SCL_PORT, I2C_SCL_PIN, 0x00);
_delay_us(0x02); //3 - tLOW > 1.3uS - maybe it's not needed
}
void sendByte(uint8_t pByte){
uint8_t tmppByte = pByte;
for(uint8_t i = 0x00; i < 0x08; i++){
//set SCL to LOW to allow Data change
setPin(I2C_SCL_PORT, I2C_SCL_PIN, 0x00);
_delay_us(0x01); // 3 - tLOW > 1.3uS - not sure if needed - I set it to the 1sthalf of waht is needed
setPin(I2C_SDA_PORT, I2C_SDA_PIN, tmppByte >> 0x07); //Get MSB of pByte
tmppByte <<= 0x01; //Get next bit
_delay_us(0x01); //3 - tLOW > 1.3 uS - not sure if needed - I set it to the 2nd half of what is needed
//set SCL to HIGH
setPin(I2C_SCL_PORT, I2C_SCL_PIN, 0x01);
_delay_us(0x01); //2 - tHIGH > 600nS
setPin(I2C_SCL_PORT, I2C_SCL_PIN, 0x00);
//8 - tHD:DAT > 0 - therefore, not needed
}
ack = checkACK();
}
uint8_t checkACK(void){
//set SDA as input to allow SDA reading
setPin(I2C_SDA_DDR, I2C_SDA_PIN, 0x00);
//set SDA pin to tri-state mode, disable internal pull-up
setPin(I2C_SDA_PORT, I2C_SDA_PIN, 0x00);
//read ACK value
ack = ( I2C_SDA_PORT & (0x01 << I2C_SDA_PIN) ) \
? 0x01 \
: 0x00;
//set SDA as output back again
setPin(I2C_SDA_DDR, I2C_SDA_PIN, 0x01);
return ack;
}
void writeByte(uint8_t pByte){
setStaSto(STARTB);
sendByte(0xA0);
checkACK();
sendByte(pByte);
checkACK();
setStaSto(STOPB);
checkACK();
}
int main(void){
//one time run code goes here
//set DDR SDA and SCL pins as output
setPin(I2C_SDA_DDR, I2C_SDA_PIN, 0x01);
setPin(I2C_SCL_DDR, I2C_SCL_PIN, 0x01);
setPin(I2C_TEST_DDR, I2C_TEST_PIN, 0x01);
//loop code goes here
while(0x01){
setPin(I2C_TEST_PORT, I2C_TEST_PIN, 0x01);
_delay_ms(50);
setPin(I2C_TEST_PORT, I2C_TEST_PIN, 0x00);
_delay_ms(100);
}
return 0;
}
I2luY2x1ZGUgPGF2ci9pby5oPgoKI2lmbmRlZiBGX0NQVQojZGVmaW5lIEZfQ1BVIDE2MDAwMDAwVUwKI2VuZGlmCgojaW5jbHVkZSA8dXRpbC9kZWxheS5oPgoKI2RlZmluZSBJMkNfU0RBX0REUiAgRERSQgojZGVmaW5lIEkyQ19TQ0xfRERSICBERFJCCiNkZWZpbmUgSTJDX1RFU1RfRERSIEREUkIKCiNkZWZpbmUgSTJDX1NEQV9QT1JUICBQT1JUQgojZGVmaW5lIEkyQ19TQ0xfUE9SVCAgUE9SVEIKI2RlZmluZSBJMkNfVEVTVF9QT1JUIFBPUlRCCgojZGVmaW5lIEkyQ19TREFfUElOICBQQjEKI2RlZmluZSBJMkNfU0NMX1BJTiAgUEIyCiNkZWZpbmUgSTJDX1RFU1RfUElOIFBCNQoKI2RlZmluZSBTVEFSVEIgMHgwMCAvL3N0YXIgYml0CiNkZWZpbmUgU1RPUEIgIDB4MDEgLy9zdG9wIGJpdAoKI2RlZmluZSBzZXRQaW4ocHBvcnQsIHBwaW4sIHBiaXQpICAgICAgICAgXAogICAgICAocHBvcnQgPSBwYml0ICAgICAgICAgICAgICAgICAgICAgICBcCiAgICAgICAgICAgICAgID8gcHBvcnQgfCAgKDB4MDEgPDwgcHBpbikgIFwKICAgICAgICAgICAgICAgOiBwcG9ydCAmICh+KDB4MDEgPDwgcHBpbikpKQoKdWludDhfdCBhY2s7Cgp2b2lkIHNldFN0YVN0byhjb25zdCB1aW50OF90IHBTdGFTdG8pewogICAvL3Jlc2V0IFNDTCBhbmQgU0RBCiAgIHBTdGFTdG8gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwKICAgICAgICAgPyBzZXRQaW4oSTJDX1NEQV9QT1JULCBJMkNfU0RBX1BJTiwgMHgwMSkgXAogICAgICAgICA6IHNldFBpbihJMkNfU0RBX1BPUlQsIEkyQ19TREFfUElOLCAweDAwKTsKICAgc2V0UGluKEkyQ19TQ0xfUE9SVCwgSTJDX1NDTF9QSU4sIDB4MDApOwoKICAgLy9TREEgSElHSCBmb3IgU3RhcnRCaXQsIFNEQSBMT1csIGZvciBTdG9wQml0CiAgIHBTdGFTdG8KICAgICAgICAgPyBzZXRQaW4oSTJDX1NEQV9QT1JULCBJMkNfU0RBX1BJTiwgMHgwMCkgIC8vYmVnaW4gc3RvcCBiaXQKICAgICAgICAgOiBzZXRQaW4oSTJDX1NEQV9QT1JULCBJMkNfU0RBX1BJTiwgMHgwMSk7IC8vYmVnaW4gc3RhcnQgYml0CiAgIHNldFBpbihJMkNfU0NMX1BPUlQsIEkyQ19TQ0xfUElOLCAweDAxKTsKICAgX2RlbGF5X3VzKDB4MDEpOyAvLzcgLSB0U1U6c1RBID4gNjAwblMKCiAgIC8vU0RBIExPVyBmb3IgU3RhcnRCaXQsIFNEQSBISUdIIGZvciBTdG9wQml0CiAgIHBTdGFTdG8KICAgICAgICAgPyBzZXRQaW4oSTJDX1NEQV9QT1JULCBJMkNfU0RBX1BJTiwgMHgwMSkgIC8vZW5kIHN0b3AgYml0CiAgICAgICAgIDogc2V0UGluKEkyQ19TREFfUE9SVCwgSTJDX1NEQV9QSU4sIDB4MDApOyAvL2VuZCBzdGFydCBiaXQKICAgX2RlbGF5X3VzKDB4MDEpOyAvLzYgLSB0SEQ6c1RBID4gNjAwblMKCiAgIC8vc2V0IFNDTCBMT1csIGVuZCBvZiBTdGFydCBvciBTdG9wIENvbmRpdGlvbnMKICAgc2V0UGluKEkyQ19TQ0xfUE9SVCwgSTJDX1NDTF9QSU4sIDB4MDApOwogICBfZGVsYXlfdXMoMHgwMik7IC8vMyAtIHRMT1cgPiAxLjN1UyAtIG1heWJlIGl0J3Mgbm90IG5lZWRlZAp9Cgp2b2lkIHNlbmRCeXRlKHVpbnQ4X3QgcEJ5dGUpewogICB1aW50OF90IHRtcHBCeXRlID0gcEJ5dGU7CgogICBmb3IodWludDhfdCBpID0gMHgwMDsgaSA8IDB4MDg7IGkrKyl7CiAgICAgIC8vc2V0IFNDTCB0byBMT1cgdG8gYWxsb3cgRGF0YSBjaGFuZ2UKICAgICAgc2V0UGluKEkyQ19TQ0xfUE9SVCwgSTJDX1NDTF9QSU4sIDB4MDApOwogICAgICBfZGVsYXlfdXMoMHgwMSk7IC8vIDMgLSB0TE9XID4gMS4zdVMgLSBub3Qgc3VyZSBpZiBuZWVkZWQgLSBJIHNldCBpdCB0byB0aGUgMXN0aGFsZiBvZiB3YWh0IGlzIG5lZWRlZAogICAgICBzZXRQaW4oSTJDX1NEQV9QT1JULCBJMkNfU0RBX1BJTiwgdG1wcEJ5dGUgPj4gMHgwNyk7IC8vR2V0IE1TQiBvZiBwQnl0ZQogICAgICB0bXBwQnl0ZSA8PD0gMHgwMTsgLy9HZXQgbmV4dCBiaXQKICAgICAgX2RlbGF5X3VzKDB4MDEpOyAvLzMgLSB0TE9XID4gMS4zIHVTIC0gbm90IHN1cmUgaWYgbmVlZGVkIC0gSSBzZXQgaXQgdG8gdGhlIDJuZCBoYWxmIG9mIHdoYXQgaXMgbmVlZGVkCiAgICAgIC8vc2V0IFNDTCB0byBISUdICiAgICAgIHNldFBpbihJMkNfU0NMX1BPUlQsIEkyQ19TQ0xfUElOLCAweDAxKTsKICAgICAgX2RlbGF5X3VzKDB4MDEpOyAvLzIgLSB0SElHSCA+IDYwMG5TCiAgICAgIHNldFBpbihJMkNfU0NMX1BPUlQsIEkyQ19TQ0xfUElOLCAweDAwKTsKICAgICAgLy84IC0gdEhEOkRBVCA+IDAgLSB0aGVyZWZvcmUsIG5vdCBuZWVkZWQKICAgfQogICBhY2sgPSBjaGVja0FDSygpOwp9Cgp1aW50OF90IGNoZWNrQUNLKHZvaWQpewogICAvL3NldCBTREEgYXMgaW5wdXQgdG8gYWxsb3cgU0RBIHJlYWRpbmcKICAgc2V0UGluKEkyQ19TREFfRERSLCBJMkNfU0RBX1BJTiwgMHgwMCk7CiAgIC8vc2V0IFNEQSBwaW4gdG8gdHJpLXN0YXRlIG1vZGUsIGRpc2FibGUgaW50ZXJuYWwgcHVsbC11cAogICBzZXRQaW4oSTJDX1NEQV9QT1JULCBJMkNfU0RBX1BJTiwgMHgwMCk7CiAgIC8vcmVhZCBBQ0sgdmFsdWUKICAgYWNrID0gKCBJMkNfU0RBX1BPUlQgJiAoMHgwMSA8PCBJMkNfU0RBX1BJTikgKSBcCiAgICAgICAgICAgICAgICAgID8gMHgwMSAgICAgICAgICAgICAgICAgICAgICAgICAgXAogICAgICAgICAgICAgICAgICA6IDB4MDA7CiAgIC8vc2V0IFNEQSBhcyBvdXRwdXQgYmFjayBhZ2FpbgogICBzZXRQaW4oSTJDX1NEQV9ERFIsIEkyQ19TREFfUElOLCAweDAxKTsKICAgcmV0dXJuIGFjazsKfQoKdm9pZCB3cml0ZUJ5dGUodWludDhfdCBwQnl0ZSl7CiAgIHNldFN0YVN0byhTVEFSVEIpOwogICBzZW5kQnl0ZSgweEEwKTsKICAgY2hlY2tBQ0soKTsKICAgc2VuZEJ5dGUocEJ5dGUpOwogICBjaGVja0FDSygpOwogICBzZXRTdGFTdG8oU1RPUEIpOwogICBjaGVja0FDSygpOwp9CgppbnQgbWFpbih2b2lkKXsKICAgLy9vbmUgdGltZSBydW4gY29kZSBnb2VzIGhlcmUKICAgLy9zZXQgRERSIFNEQSBhbmQgU0NMIHBpbnMgYXMgb3V0cHV0CiAgIHNldFBpbihJMkNfU0RBX0REUiwgSTJDX1NEQV9QSU4sIDB4MDEpOwogICBzZXRQaW4oSTJDX1NDTF9ERFIsIEkyQ19TQ0xfUElOLCAweDAxKTsKICAgc2V0UGluKEkyQ19URVNUX0REUiwgSTJDX1RFU1RfUElOLCAweDAxKTsKCiAgIC8vbG9vcCBjb2RlIGdvZXMgaGVyZQogICB3aGlsZSgweDAxKXsKICAgICAgc2V0UGluKEkyQ19URVNUX1BPUlQsIEkyQ19URVNUX1BJTiwgMHgwMSk7CiAgICAgICBfZGVsYXlfbXMoNTApOwogICAgICBzZXRQaW4oSTJDX1RFU1RfUE9SVCwgSTJDX1RFU1RfUElOLCAweDAwKTsKICAgICAgX2RlbGF5X21zKDEwMCk7CiAgIH0KICAgcmV0dXJuIDA7Cn0=