diff options
Diffstat (limited to 'src/storage.h')
-rw-r--r-- | src/storage.h | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/src/storage.h b/src/storage.h new file mode 100644 index 0000000..6b76190 --- /dev/null +++ b/src/storage.h @@ -0,0 +1,199 @@ +/* + * Copyright (C) 2016 by Daniel Friesel + * + * License: You may use, redistribute and/or modify this file under the terms + * of either: + * * The GNU LGPL v3 (see COPYING and COPYING.LESSER), or + * * The 3-clause BSD License (see COPYING.BSD) + * + */ + +#include <stdlib.h> + +#define I2C_EEPROM_ADDR 0x50 + +class Storage { + private: + /** + * Number of animations on the storage, AKA contents of byte 0x0000. + * A value of 0xff indicates that the EEPROM was never written to + * and therefore contains no animations. + */ + uint8_t num_anims; + + /** + * Page offset of the pattern read by the last load() call. Used to + * calculate the read address in loadChunk(). The animation this + * offset refers to starts at byte 256 + (32 * page_offset). + */ + uint8_t page_offset; + + /** + * First free page (excluding the 256 byte metadata area) on the + * EEPROM. Used by save() and append(). This value refers to the + * EEPROM bytes 256 + (32 * first_free_page) and up. + */ + uint8_t first_free_page; + + enum I2CStatus : uint8_t { + I2C_OK, + I2C_START_ERR, + I2C_ADDR_ERR, + I2C_ERR + }; + + /** + * Sends an I2C start condition and the I2C_EEPROM_ADDR with the + * write flag set. + * + * @return An I2CStatus value indicating success/failure + */ + uint8_t i2c_start_write(void); + + /** + * Sends an I2C start condition and the I2C_EEPROM_ADDR with the + * read flag set. + * + * @return An I2CStatus value indicating success/failure + */ + uint8_t i2c_start_read(void); + + /** + * Sends an I2C stop condition. Does not check for errors. + */ + void i2c_stop(void); + + /** + * Sends up to len bytes of data via I2C. i2c_start_write() must + * have been called successfully for this to work. + * + * @param len number of bytes to send + * @param data pointer to data buffer, must be at least len bytes + * @return number of bytes which were successfully sent (0 .. len) + */ + uint8_t i2c_send(uint8_t len, uint8_t *data); + + /** + * Receives up to len bytes of data via I2C. i2c_start_read() must + * have been called successfully for this to work. + * + * @param len number of bytes to receive + * @param data pointer to data buffer, must be at least len bytes + * @return number of bytes which were successfully received (0 .. len) + */ + uint8_t i2c_receive(uint8_t len, uint8_t *data); + + /** + * Reads len bytes of data stored on addrhi, addrlo from the EEPROM + * into the data buffer. Does a complete I2C transaction including + * start and stop conditions. addrlo may start at an arbitrary + * position, page boundaries are irrelevant for this function. If a + * read reaches the end of the EEPROM memory, it will wrap around to + * byte 0x0000. + * + * @param addrhi upper address byte. Must be less than 32 + * @param addrlo lower address byte + * @param len number of bytes to read + * @param data pointer to data buffer, must be at least len bytes + * @return An I2CStatus value indicating success/failure + */ + uint8_t i2c_read(uint8_t addrhi, uint8_t addrlo, uint8_t len, uint8_t *data); + + /** + * Writes len bytes of data from the data buffer into addrhi, addrlo + * on the EEPROM. Does a complete I2C transaction including start and + * stop conditions. Note that the EEPROM consists of 32 byte pages, + * so it is not possible to write more than 32 bytes in one + * operation. Also note that this function does not check for page + * boundaries. Starting a 32-byte write in the middle of a page will + * put the first 16 bytes where they belong, while the second 16 + * bytes will wrap around to the first 16 bytes of the page. + * + * @param addrhi upper address byte. Must be less than 32 + * @param addrlo lower address byte + * @param len number of bytes to write + * @param data pointer to data buffer, must be at least len bytes + * @return An I2CStatus value indicating success/failure + */ + uint8_t i2c_write(uint8_t addrhi, uint8_t addrlo, uint8_t len, uint8_t *data); + + public: + Storage() { num_anims = 0; first_free_page = 0;}; + + /** + * Enables the storage hardware: Configures the internal I2C + * module and reads num_anims from the EEPROM. + */ + void enable(); + + /** + * Prepares the storage for a complete overwrite by setting the + * number of stored animations to zero. The next save operation + * will get pattern id 0 and overwrite the first stored pattern. + * + * Note that this function does not write anything to the + * EEPROM. Use Storage::sync() for that. + */ + void reset(); + + /** + * Writes the current number of animations (as set by reset() or + * save() to the EEPROM. Required to get a consistent storage state + * after a power cycle. + */ + void sync(); + + /** + * Checks whether the EEPROM contains animathion data. + * + * @return true if the EEPROM contains valid-looking data + */ + bool hasData(); + + /** + * Accessor for the number of saved patterns on the EEPROM. + * A return value of 255 (0xff) means that there are no patterns + * on the EEPROM (and hasData() returns false in that case). + * + * @return number of patterns + */ + uint8_t numPatterns() { return num_anims; }; + + /** + * Loads pattern number idx from the EEPROM. The + * + * @param idx pattern index (starting with 0) + * @param pointer to the data structure for the pattern. Must be + * at least 132 bytes + */ + void load(uint8_t idx, uint8_t *data); + + /** + * Load partial pattern chunk (without header) from EEPROM. + * + * @param chunk 128 byte-offset inside pattern (starting with 0) + * @param data pointer to data structure for the pattern. Must be + * at least 128 bytes + */ + void loadChunk(uint8_t chunk, uint8_t *data); + + /** + * Save (possibly partial) pattern on the EEPROM. 32 bytes of + * dattern data will be read and stored, regardless of the + * pattern header. + * + * @param data pattern data. Must be at least 32 bytes + */ + void save(uint8_t *data); + + /** + * Continue saving a pattern on the EEPROM. Appends 32 bytes of + * pattern data after the most recently written block of data + * (i.e., to the pattern which is currently being saved). + * + * @param data pattern data. Must be at least 32 bytes + */ + void append(uint8_t *data); +}; + +extern Storage storage; |