#include #include "eeprom.hpp" #include "util.hpp" using namespace eeprom; constexpr uint8_t WRITE_MS = 3; constexpr uint8_t ADDR = 0x50; static uint32_t at = 0; static uint32_t last_block_end = 0; static bool is_responsive(uint8_t i2c_addr) { bool s = mem.start_write(i2c_addr); return s; } static void wait_for_responsive(uint8_t i2c_addr) { while(!is_responsive(i2c_addr)) { delay(1); } } static uint8_t get_i2c_addr(uint32_t at) { return ADDR ^ (at >> 16); } static void set_address(uint8_t i2c_addr, uint16_t at) { char addr_bytes[2] = {at >> 8, at}; mem.start_write(i2c_addr); mem.write(at >> 8); mem.write(at); } void eeprom::init() { mem.begin(); } void eeprom::jump(uint32_t p_at) { last_block_end = 0; at = p_at; } void eeprom::read(char* data, uint16_t data_size) { uint16_t recorded = 0; while(recorded < data_size && at < LENGTH) { uint32_t block_end = at / BLOCK_SIZE * BLOCK_SIZE + BLOCK_SIZE; uint8_t read_len = min(min(block_end - at, data_size - recorded), 255); uint8_t i2c_addr = get_i2c_addr(at); if(block_end != last_block_end) { set_address(i2c_addr, at); last_block_end = block_end; } mem.start_read(i2c_addr); mem.read(data + recorded, read_len, true); recorded += read_len; at += read_len; } mem.end(); for(uint16_t i = recorded; i < data_size; i++) { data[i] = 0; } } void eeprom::page_write(uint32_t at, const char* data) { if(at >= LENGTH) return; uint8_t i2c_addr = get_i2c_addr(at); wait_for_responsive(i2c_addr); mem.start_write(i2c_addr); mem.write(at >> 8); mem.write(at); mem.write(data, PAGE_SIZE - (at % PAGE_SIZE)); mem.end(); delay(WRITE_MS); last_block_end = 0; } uint32_t eeprom::get_addr() { return at; }