diff options
author | Daniel Friesel <derf@finalrewind.org> | 2016-02-20 20:12:33 +0100 |
---|---|---|
committer | Daniel Friesel <derf@finalrewind.org> | 2016-02-20 20:12:33 +0100 |
commit | 9e68d2ab92a2169478d6ec4b4d1f94026dfcf3dc (patch) | |
tree | 2a6616e13e4341158dcf3d8d23bbd3298a3e53a8 | |
parent | ea538b2a622c764642837e42b793f9eae7df2c2a (diff) |
Preparations for I2C error checking and handling
-rw-r--r-- | src/storage.cc | 28 | ||||
-rw-r--r-- | src/storage.h | 19 |
2 files changed, 33 insertions, 14 deletions
diff --git a/src/storage.cc b/src/storage.cc index 4afe1d8..7ee5f4c 100644 --- a/src/storage.cc +++ b/src/storage.cc @@ -55,30 +55,42 @@ void Storage::enable() * Send an I2C (re)start condition and the EEPROM address in read mode. Returns * after it has been transmitted successfully. */ -void Storage::i2c_start_read() +uint8_t Storage::i2c_start_read() { TWCR = _BV(TWINT) | _BV(TWSTA) | _BV(TWEN); while (!(TWCR & _BV(TWINT))); + if (!(TWSR & 0x18)) // 0x08 == START ok, 0x10 == RESTART ok + return I2C_START_ERR; // Note: The R byte ("... | 1") causes the TWI momodule to switch to // Master Receive mode TWDR = (I2C_EEPROM_ADDR << 1) | 1; TWCR = _BV(TWINT) | _BV(TWEN); while (!(TWCR & _BV(TWINT))); + if (TWSR != 0x40) // 0x40 == SLA+R transmitted, ACK receveid + return I2C_ADDR_ERR; + + return I2C_OK; } /* * Send an I2C (re)start condition and the EEPROM address in write mode. * Returns after it has been transmitted successfully. */ -void Storage::i2c_start_write() +uint8_t Storage::i2c_start_write() { TWCR = _BV(TWINT) | _BV(TWSTA) | _BV(TWEN); while (!(TWCR & _BV(TWINT))); + if (!(TWSR & 0x18)) // 0x08 == START ok, 0x10 == RESTART ok + return I2C_START_ERR; TWDR = (I2C_EEPROM_ADDR << 1) | 0; TWCR = _BV(TWINT) | _BV(TWEN); while (!(TWCR & _BV(TWINT))); + if (TWSR != 0x18) // 0x18 == SLA+W transmitted, ACK received + return I2C_ADDR_ERR; + + return I2C_OK; } /* @@ -93,8 +105,7 @@ void Storage::i2c_stop() * Sends len bytes to the EEPROM. Note that this method does NOT * send I2C start or stop conditions. */ -// TODO Everything[tm] (error handling and generic code) -int8_t Storage::i2c_send(uint8_t len, uint8_t *data) +uint8_t Storage::i2c_send(uint8_t len, uint8_t *data) { uint8_t pos = 0; @@ -102,6 +113,8 @@ int8_t Storage::i2c_send(uint8_t len, uint8_t *data) TWDR = data[pos]; TWCR = _BV(TWINT) | _BV(TWEN); while (!(TWCR & _BV(TWINT))); + if (TWSR != 0x28) // 0x28 == byte transmitted, ACK received + return pos; } return pos + 1; @@ -111,8 +124,7 @@ int8_t Storage::i2c_send(uint8_t len, uint8_t *data) * Receives len bytes from the EEPROM into data. Note that this method does * NOT send I2C start or stop conditions. */ -// TODO dito -int8_t Storage::i2c_receive(uint8_t len, uint8_t *data) +uint8_t Storage::i2c_receive(uint8_t len, uint8_t *data) { uint8_t pos = 0; @@ -136,7 +148,7 @@ int8_t Storage::i2c_receive(uint8_t len, uint8_t *data) * Does not check for page boundaries yet. * Includes a complete I2C transaction. */ -int8_t Storage::i2c_write(uint16_t pos, uint8_t len, uint8_t *data) +uint8_t Storage::i2c_write(uint16_t pos, uint8_t len, uint8_t *data) { uint8_t addr_buf[2]; @@ -156,7 +168,7 @@ int8_t Storage::i2c_write(uint16_t pos, uint8_t len, uint8_t *data) * Does not check for page boundaries yet. * Includes a complete I2C transaction. */ -int8_t Storage::i2c_read(uint16_t pos, uint8_t len, uint8_t *data) +uint8_t Storage::i2c_read(uint16_t pos, uint8_t len, uint8_t *data) { uint8_t addr_buf[2]; addr_buf[0] = pos >> 8; diff --git a/src/storage.h b/src/storage.h index fd7b0ad..b2a4dbf 100644 --- a/src/storage.h +++ b/src/storage.h @@ -6,13 +6,20 @@ class Storage { private: uint8_t num_anims; uint8_t first_free_page; - void i2c_start_write(void); - void i2c_start_read(void); + uint8_t i2c_start_write(void); + uint8_t i2c_start_read(void); void i2c_stop(void); - int8_t i2c_send(uint8_t len, uint8_t *data); - int8_t i2c_receive(uint8_t len, uint8_t *data); - int8_t i2c_read(uint16_t addr, uint8_t len, uint8_t *data); - int8_t i2c_write(uint16_t addr, uint8_t len, uint8_t *data); + uint8_t i2c_send(uint8_t len, uint8_t *data); + uint8_t i2c_receive(uint8_t len, uint8_t *data); + uint8_t i2c_read(uint16_t addr, uint8_t len, uint8_t *data); + uint8_t i2c_write(uint16_t addr, uint8_t len, uint8_t *data); + + enum I2CStatus : uint8_t { + I2C_OK, + I2C_START_ERR, + I2C_ADDR_ERR + }; + public: Storage() { num_anims = 0; first_free_page = 0;}; |