From cb1c87e6a371d405b7064b66002127c9d500c7d4 Mon Sep 17 00:00:00 2001 From: Daniel Friesel Date: Mon, 22 Feb 2016 19:15:16 +0100 Subject: Working loadPattern() code is working \o/ --- src/storage.cc | 104 +++++++++++++++++++++++++++++++++++++-------------------- src/storage.h | 9 ++--- src/system.cc | 12 +++++-- 3 files changed, 82 insertions(+), 43 deletions(-) diff --git a/src/storage.cc b/src/storage.cc index a517f53..21eed31 100644 --- a/src/storage.cc +++ b/src/storage.cc @@ -1,3 +1,4 @@ +#include #include #include @@ -8,12 +9,12 @@ Storage storage; /* * EEPROM data structure ("file system"): * - * Organized as 64B-pages, all animations/texts are page-aligned. Byte 0 .. + * Organized as 32B-pages, all animations/texts are page-aligned. Byte 0 .. * 255 : storage metadata. Byte 0 contains the number of animations, byte 1 the * page offset of the first animation, byte 2 of the second, and so on. * Byte 256+: texts/animations without additional storage metadata, aligned - * to 64B. So, a maximum of 256-(256/64) = 252 texts/animations can be stored, - * and a maximum of 255 * 64 = 16320 Bytes (almost 16 kB / 128 kbit) can be + * to 32B. So, a maximum of 256-(256/32) = 248 texts/animations can be stored, + * and a maximum of 255 * 32 = 8160 Bytes (almost 8 kB / 64 kbit) can be * addressed. To support larger EEPROMS, change the metadate area to Byte 2 .. * 511 and use 16bit page pointers. * @@ -21,16 +22,16 @@ Storage storage; * * Example: * Byte 0 = 3 -> we've got a total of three animations - * Byte 1 = 4 -> first text/animation starts at byte 64*4 = 256 - * Byte 2 = 8 -> second starts at byte 64*8 = 512 - * Byte 3 = 9 -> third starts at 64*9 * 576 + * Byte 1 = 0 -> first text/animation starts at byte 256 + 32*0 = 256 + * Byte 2 = 4 -> second starts at byte 256 + 32*4 = 384 + * Byte 3 = 5 -> third starts at 256 + 32*5 * 416 * Byte 4 = whatever * . * . * . * Byte 256ff = first text/animation. Has a header encoding its length in bytes. - * Byte 512ff = second - * Byte 576ff = third + * Byte 384ff = second + * Byte 416ff = third * . * . * . @@ -47,7 +48,7 @@ void Storage::enable() TWSR = 0; // the lower two bits control TWPS TWBR = ((F_CPU / 100000UL) - 16) / 2; - i2c_read(0, 1, &num_anims); + i2c_read(0, 0, 1, &num_anims); } @@ -117,7 +118,7 @@ uint8_t Storage::i2c_send(uint8_t len, uint8_t *data) return pos; } - return pos + 1; + return pos; } /* @@ -140,7 +141,7 @@ uint8_t Storage::i2c_receive(uint8_t len, uint8_t *data) data[pos] = TWDR; } - return pos + 1; + return pos; } /* @@ -148,19 +149,33 @@ uint8_t Storage::i2c_receive(uint8_t len, uint8_t *data) * Does not check for page boundaries yet. * Includes a complete I2C transaction. */ -uint8_t Storage::i2c_write(uint16_t pos, uint8_t len, uint8_t *data) +uint8_t Storage::i2c_write(uint8_t addrhi, uint8_t addrlo, uint8_t len, uint8_t *data) { uint8_t addr_buf[2]; + uint8_t num_tries; - addr_buf[0] = pos >> 8; - addr_buf[1] = pos & 0xff; + addr_buf[0] = addrhi; + addr_buf[1] = addrlo; - i2c_start_write(); - i2c_send(2, addr_buf); - i2c_send(len, data); - i2c_stop(); + for (num_tries = 0; num_tries < 16; num_tries++) { + if (num_tries > 0) + _delay_ms(1); + + if (i2c_start_write() != I2C_OK) + continue; + + if (i2c_send(2, addr_buf) != 2) + continue; + + if (i2c_send(len, data) != len) + continue; - return 0; // TODO proper return code to indicate write errors + i2c_stop(); + return I2C_OK; + } + + i2c_stop(); + return I2C_ERR; } /* @@ -168,26 +183,43 @@ uint8_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. */ -uint8_t Storage::i2c_read(uint16_t pos, uint8_t len, uint8_t *data) +uint8_t Storage::i2c_read(uint8_t addrhi, uint8_t addrlo, uint8_t len, uint8_t *data) { uint8_t addr_buf[2]; - addr_buf[0] = pos >> 8; - addr_buf[1] = pos & 0xff; + uint8_t num_tries; - i2c_start_write(); - i2c_send(2, addr_buf); - i2c_start_read(); - i2c_receive(len, data); - i2c_stop(); + addr_buf[0] = addrhi; + addr_buf[1] = addrlo; - return 0; // TODO proper return code to indicate read/write errors + for (num_tries = 0; num_tries < 16; num_tries++) { + if (num_tries > 0) + _delay_ms(1); + + if (i2c_start_write() != I2C_OK) + continue; + + if (i2c_send(2, addr_buf) != 2) + continue; + + if (i2c_start_read() != I2C_OK) + continue; + + if (i2c_receive(len, data) != len) + continue; + + i2c_stop(); + return I2C_OK; + } + + i2c_stop(); + return I2C_ERR; } void Storage::reset() { first_free_page = 0; num_anims = 0xff; - i2c_write(0, 1, &num_anims); // pretend the EEPROM was never written to + i2c_write(0, 0, 1, &num_anims); // pretend the EEPROM was never written to num_anims = 0; } @@ -199,21 +231,21 @@ bool Storage::hasData() return true; } -void Storage::load(uint16_t idx, uint8_t *data) +void Storage::load(uint8_t idx, uint8_t *data) { uint8_t page_offset; uint8_t header[2]; - i2c_read(1 + idx, 1, &page_offset); + i2c_read(0, 1 + idx, 1, &page_offset); - i2c_read(256 + (64 * (uint16_t)page_offset), 2, header); - i2c_read(256 + (64 * (uint16_t)page_offset), header[1] + 2, data); + i2c_read(1 + (page_offset / 8), (page_offset % 8) * 32, 2, header); + i2c_read(1 + (page_offset / 8), (page_offset % 8) * 32, header[1] + 2, data); } void Storage::save(uint8_t *data) { num_anims++; - i2c_write(0, 1, &num_anims); - i2c_write(num_anims, 1, &first_free_page); + i2c_write(0, 0, 1, &num_anims); + i2c_write(0, num_anims, 1, &first_free_page); append(data); } @@ -222,6 +254,6 @@ void Storage::append(uint8_t *data) // the header indicates the length of the data, but we really don't care // - it's easier to just write the whole page and skip the trailing // garbage when reading. - i2c_write(256 + (64 * (uint16_t)first_free_page), 64, data); + i2c_write(1 + (first_free_page / 8), (first_free_page % 8) * 32, 32, data); first_free_page++; } diff --git a/src/storage.h b/src/storage.h index 5366ed9..d0a4a67 100644 --- a/src/storage.h +++ b/src/storage.h @@ -11,13 +11,14 @@ class Storage { void i2c_stop(void); 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); + uint8_t i2c_read(uint8_t addrhi, uint8_t addrlo, uint8_t len, uint8_t *data); + uint8_t i2c_write(uint8_t addrhi, uint8_t addrlo, uint8_t len, uint8_t *data); enum I2CStatus : uint8_t { I2C_OK, I2C_START_ERR, - I2C_ADDR_ERR + I2C_ADDR_ERR, + I2C_ERR }; public: @@ -53,7 +54,7 @@ class Storage { * @param data pointer to data structure for the pattern. Must be * at least 256 Bytes */ - void load(uint16_t idx, uint8_t *data); + void load(uint8_t idx, uint8_t *data); /** * Save (possibly partial) pattern on the EEPROM. 64 bytes of diff --git a/src/system.cc b/src/system.cc index dd09b5a..1cbeec1 100644 --- a/src/system.cc +++ b/src/system.cc @@ -16,7 +16,7 @@ System rocket; animation_t active_anim; uint8_t disp_buf[260]; // 4 byte header + 256 byte data -uint8_t *rx_buf = disp_buf + 64; +uint8_t *rx_buf = disp_buf + sizeof(disp_buf) - 64; void System::initialize() { @@ -33,11 +33,15 @@ void System::initialize() modem.enable(); storage.enable(); + storage.reset(); + storage.save((uint8_t *)"\x10\x0a\x11\x00nootnoot"); + storage.save((uint8_t *)"\x10\x0a\x20\x00nootnoot"); + sei(); if (storage.hasData()) { current_anim_no = 0; - loadPattern(0); + loadPattern(1); } else { active_anim.type = AnimationType::TEXT; active_anim.speed = (2 << 4) + 15; @@ -82,7 +86,7 @@ void System::loadPattern(uint8_t anim_no) storage.load(anim_no, disp_buf); active_anim.type = (AnimationType)(disp_buf[0] >> 4); - active_anim.length = disp_buf[1]; + active_anim.length = disp_buf[1] - 2; if (active_anim.type == AnimationType::TEXT) { active_anim.speed = (disp_buf[2] & 0xf0) + 15; @@ -116,6 +120,8 @@ void System::receive(void) rx_buf[rx_pos] = modem.buffer_get(); } + // TODO adjust for 32 Byte rx buffer size + switch(rxExpect) { case START1: if (rx_byte == 0x99) -- cgit v1.2.3