diff --git a/tiny84/master/i2c_master.c b/tiny84/master/i2c_master.c new file mode 100644 index 0000000..3744f6f --- /dev/null +++ b/tiny84/master/i2c_master.c @@ -0,0 +1,131 @@ +#include "i2c_master.h" +#include + +uint8_t i2c_clock(uint8_t type); + +void i2c_init(void) +{ + // Define SCL and SDA as Output + DDRA |= (1 << 4) | (1 << 6); + + // Preload dataregister with "released level" data + USIDR = 0xFF; + + // Use SCL and SDA pins + // Select clock sources + USICR = (1 << USIWM1) | (1 << USICS1) | (1 << USICLK); + + // Clear flags and reset counter + USISR = (1 << USISIF) | (1 << USIOIF) | (1 << USIPF) | (1 << USIDC); +} + +uint8_t i2c_start(uint8_t address) +{ + // FOR REPEATED START + // Release SCL + PORTA |= (1 << 4); + // Verify that SCL becomes high + while (!( PINA & (1 << 4) )); + + // GENERATE START CONDITION + // Force SDA LOW + PORTA &= ~(1 << 6); + + // Pull SCL LOW + PORTA &= ~(1 << 4); + // Release SDA + PORTA |= (1 << 6); + + return i2c_write(address); +} + +uint8_t i2c_write(uint8_t data) +{ + // Pull SCL LOW + PORTA &= ~(1 << 4); + // Setup data + USIDR = data; + + // Send 8 bits on bus + i2c_clock(8); + + // Enable SDA as input + DDRA &= ~(1 << 6); + + // Receive 1 bit on bus & Check for NACK + if (i2c_clock(1) & (1 << 0)) + { + return 1; + } + return 0; +} + +uint8_t i2c_read(uint8_t nack) +{ + // Enable SDA as input. + DDRA &= ~(1 << 6); + // Read 8 bits + uint8_t result = i2c_clock(8); + + if (nack) + { + // Load NACK + USIDR = 0xFF; + } + else + { + // Load ACK + USIDR = 0x00; + } + + i2c_clock(1); + return result; +} + +void i2c_stop(void) +{ + // Pull SDA low + PORTA &= ~(1 << 6); + // Release SCL + PORTA |= (1 << 4); + // Wait for SCL to go high + while (!( PINA & (1 << 4) )); + + // Release SDA + PORTA |= (1 << 6); +} + +uint8_t i2c_clock(uint8_t count) +{ + uint8_t reg_temp = (1 << USISIF) | (1 << USIOIF) | (1 << USIPF) | (1 << USIDC); + // Counter counts number of edges + // Overflow signals end of transmission + reg_temp |= 16 - (count * 2); + + USISR = reg_temp; + + // Set clock source & toggle clock prepare + reg_temp = (1 << USIWM1) | (1 << USICS1) | (1 << USICLK) | (1 << USITC); + do + { + // Generate positve SCL edge. + USICR = reg_temp; + + // Wait for SCL to go high + while (!( PINA & (1 << 4))); + + // Generate negative SCL edge + USICR = reg_temp; + } + // Wait for counter overflow (all edges are completed) + while (!( USISR & (1 << USIOIF))); + + // Read data + reg_temp = USIDR; + // Load dataregister with "released level" data + USIDR = 0xFF; + + // Enable SDA as output + DDRA |= (1 << 6); + return reg_temp; +} diff --git a/tiny/master/i2c_master.h b/tiny84/master/i2c_master.h similarity index 100% rename from tiny/master/i2c_master.h rename to tiny84/master/i2c_master.h diff --git a/tiny/master/i2c_master.c b/tiny85/master/i2c_master.c similarity index 100% rename from tiny/master/i2c_master.c rename to tiny85/master/i2c_master.c diff --git a/tiny85/master/i2c_master.h b/tiny85/master/i2c_master.h new file mode 100644 index 0000000..42bba16 --- /dev/null +++ b/tiny85/master/i2c_master.h @@ -0,0 +1,15 @@ +#include + +#ifndef I2C_MASTER_H +#define I2C_MASTER_H + +#define I2C_READ 0x01 +#define I2C_WRITE 0x00 + +void i2c_init(void); +uint8_t i2c_start(uint8_t address); +uint8_t i2c_write(uint8_t data); +uint8_t i2c_read(uint8_t nack); +void i2c_stop(void); + +#endif // I2C_MASTER_H