/* Bit-banged open-drain I2C master: SCL=PD3, SDA=PD2 (external pull-ups required) */ #ifndef I2C_H #define I2C_H #include #include enum { I2C_OK = 0, I2C_NACK_ADDR = 1, I2C_NACK_DATA = 2, I2C_BUS_ERR = 3 }; void i2c_init(void); void i2c_set_delay(uint8_t d); /* 0 = 400 kHz, each step adds 0.375 us per SCL period */ uint8_t i2c_lines(uint8_t pullup); /* diag: bit0=SCL, bit1=SDA level; pullup=1 enables weak internal pull-ups */ uint8_t i2c_recover(void); /* clock out stuck slave, then STOP */ /* wlen>0: write phase; rlen>0: read phase (repeated START if both); * wlen==0 && rlen==0: address probe. addr is the 7-bit address. */ uint8_t i2c_xfer(uint8_t addr, const uint8_t *w, uint8_t wlen, uint8_t *r, uint8_t rlen); /* Split-phase access. i2c_start(): START (or repeated START) + address byte * (addr_rw = addr << 1 | R/W). A non-repeated start clears the error flag and * runs bus recovery if a line is stuck. Returns I2C_OK / I2C_NACK_ADDR / I2C_BUS_ERR. */ uint8_t i2c_start(uint8_t addr_rw, bool repeated); uint8_t i2c_write(uint8_t b); /* I2C_OK / I2C_NACK_DATA / I2C_BUS_ERR */ uint8_t i2c_read(bool ack); /* ack=false on the last byte */ bool i2c_bus_error(void); /* clock-stretch timeout since last non-repeated start */ void i2c_stop(void); #endif