diff --git a/data.cpp b/data.cpp index 908820a..6afbbc7 100644 --- a/data.cpp +++ b/data.cpp @@ -13,36 +13,19 @@ using namespace data; static Mode mode = Mode::none; static void flash_data() { - char buff[128]; - unsigned count; - unsigned at = 0; - unsigned max_len = eeprom::length(); + uint32_t at = 0; + uint16_t count; + char buffer[eeprom::PAGE_SIZE]; - for(;;) { - unsigned count = sizeof(buff); - unsigned end = at + count; + do { + count = serial::read(buffer, eeprom::PAGE_SIZE); + eeprom::page_write(at, buffer); + at += eeprom::PAGE_SIZE; + delay(10); + } while(count == eeprom::PAGE_SIZE); - if(end <= at) { - break; - } - if(end >= max_len) { - unsigned l = end - max_len; - if(count < l) { - break; - } - count -= l; - } - - count = serial::read(buff, count); - eeprom::write(at, buff, count); - at += count; - - if(count != sizeof(buff)) { - break; - } - } - - while(serial::read(buff, sizeof(buff) == sizeof(buff))) { + while(serial::is_connected()) { + serial::get(); } } diff --git a/eeprom.cpp b/eeprom.cpp index 1af64cd..5de7439 100644 --- a/eeprom.cpp +++ b/eeprom.cpp @@ -1,41 +1,87 @@ -#include #include -#include #include "eeprom.hpp" +#include "util.hpp" +using namespace eeprom; + +constexpr uint8_t WRITE_MS = 3; constexpr uint8_t ADDR = 0x50; -constexpr unsigned DELAY = 100; -static ExternalEEPROM mem; +uint32_t at = 0; -static unsigned at = 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) { + uint8_t i2c_addr = ADDR; + if(at > 0xffff) { + i2c_addr |= 0b100; + } + return i2c_addr; +} + +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() { - Wire.setClock(400000); - Wire.begin(); - mem.setMemoryType(1025); mem.begin(); + +// Wire.setClock(400000); +// Wire.begin(); +// mem.setMemorySizeBytes(eeprom::MAX_LENGTH); +// mem.setAddressBytes(2); +// mem.setPageSizeBytes(128); +// mem.setWriteTimeMs(3); +// mem.begin(); } -unsigned eeprom::length() { - return mem.length(); +void eeprom::jump(uint32_t p_at) { + p_at = at; } -void eeprom::jump(unsigned loc) { - at = loc; +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); + + set_address(i2c_addr, at); + 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::read(char* data, unsigned len) { - mem.read(at, data, len); - at += len; -} - -void eeprom::read(unsigned loc, char* data, unsigned len) { - mem.read(loc, data, len); -} - -void eeprom::write(unsigned loc, const char* data, unsigned len) { - mem.write(loc, data, len); +void eeprom::page_write(uint32_t at, const char* data) { + 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); } diff --git a/eeprom.hpp b/eeprom.hpp index d328cfd..84e3c54 100644 --- a/eeprom.hpp +++ b/eeprom.hpp @@ -1,15 +1,20 @@ #pragma once +#include +#include "soft_twi.hpp" + namespace eeprom { - constexpr unsigned char PAGE_SIZE = 128; + constexpr uint8_t PAGE_SIZE = 128; + constexpr uint32_t BLOCK_SIZE = 0x10000; + constexpr uint32_t LENGTH = 0x20000; + + inline SoftTWI mem(A4, A5);//A4, A5); void init(); - void jump(unsigned addr); - void read(char* data, unsigned len); - void read(unsigned addr, char* data, unsigned len); - void write(unsigned addr, const char* data, unsigned len); - unsigned length(); + void jump(uint32_t addr); + void read(char* data, uint16_t len); + void page_write(uint32_t at, const char* data); }; diff --git a/indicator.cpp b/indicator.cpp index 830e14b..700c74d 100644 --- a/indicator.cpp +++ b/indicator.cpp @@ -3,21 +3,24 @@ #include "indicator.hpp" #include "tones.hpp" -constexpr int PIN = 10; +constexpr int PIN = 9; void indicator::init() { - pinMode(PIN, OUTPUT); + pinMode(PIN+0, OUTPUT); + pinMode(PIN+1, OUTPUT); } void indicator::reset() { - analogWrite(PIN, 0); + analogWrite(PIN+0, 0); + analogWrite(PIN+1, 0); } void indicator::update() { - unsigned v = 0; + unsigned v[2] = {2}; for(int i = 0; i < tones::active; i++) { - v += tones::all[i].amplitude; + v[i % 2] += tones::all[i].amplitude; } - analogWrite(PIN, min(v, 255)); + analogWrite(PIN+0, min(v[0], 255)); + analogWrite(PIN+1, min(v[1], 255)); } diff --git a/scheduler.cpp b/scheduler.cpp index bc6c23b..f2615f5 100644 --- a/scheduler.cpp +++ b/scheduler.cpp @@ -22,10 +22,6 @@ struct { bool active = false; } next; -constexpr uint64_t bm(int n) { - return ((uint64_t)1 << n) - 1; -} - void scheduler::reset() { tones::clear_all(); ts_init = micros(); diff --git a/serial.hpp b/serial.hpp index c140f5c..1dd5760 100644 --- a/serial.hpp +++ b/serial.hpp @@ -2,7 +2,6 @@ #pragma once #include -#include namespace serial { diff --git a/soft_twi.cpp b/soft_twi.cpp new file mode 100644 index 0000000..4cc0bfe --- /dev/null +++ b/soft_twi.cpp @@ -0,0 +1,126 @@ + +#include "soft_twi.hpp" +#include + +SoftTWI::SoftTWI(unsigned pin_sda, unsigned pin_scl, unsigned delay) { + _pin_scl = pin_scl; + _pin_sda = pin_sda; + _delay = delay; +} + +void SoftTWI::begin() { + digitalWrite(_pin_sda, 0); + digitalWrite(_pin_scl, 0); +} + +void SoftTWI::sleep(unsigned t) { + if(_delay) { + delayMicroseconds(_delay * t); + } +} + +void SoftTWI::set_sda(bool s) { + pinMode(_pin_sda, s ? INPUT : OUTPUT); +} + +void SoftTWI::set_scl(bool s) { + pinMode(_pin_scl, s ? INPUT : OUTPUT); +} + +bool SoftTWI::read_sda() { + return digitalRead(_pin_sda); +} + +bool SoftTWI::read_scl() { + return digitalRead(_pin_scl); +} + +void SoftTWI::wait_scl() { + while(!read_scl()) {} +} + +bool SoftTWI::read_bit() { + set_sda(1); + sleep(); + set_scl(1); + sleep(2); + wait_scl(); + bool s = read_sda(); + set_scl(0); + sleep(); + return s; +} + +void SoftTWI::write_bit(bool s) { + set_sda(s); + sleep(); + set_scl(1); + sleep(2); + wait_scl(); + set_scl(0); + sleep(); +} + +void SoftTWI::start() { + set_sda(1); + sleep(); + set_scl(1); + sleep(); + set_sda(0); + sleep(); + set_scl(0); + sleep(); +} + +void SoftTWI::end() { + set_sda(0); + sleep(); + set_scl(1); + sleep(); + set_sda(1); + sleep(2); +} + +bool SoftTWI::start_read(uint8_t addr) { + start(); + return write((addr << 1) | 1); +} + +bool SoftTWI::start_write(uint8_t addr) { + start(); + return write(addr << 1); +} + +uint8_t SoftTWI::read(bool ack) { + uint8_t v = 0; + for(unsigned m = 0x80; m; m >>= 1) { + if(read_bit()) { + v |= m; + } + } + write_bit(!ack); // send ACK + return v; +} + +bool SoftTWI::write(uint8_t v) { + for(unsigned m = 0x80; m; m >>= 1) { + write_bit(v & m); + } + return !read_bit(); // get ACK +} + +unsigned SoftTWI::write(const uint8_t* data, unsigned data_len) { + for(unsigned i = 0; i < data_len; i++) { + if(!write(data[i])) { + return i; + } + } + return data_len; +} + +void SoftTWI::read(uint8_t* data, unsigned data_len, bool nack_at_end) { + for(unsigned i = 0; i < data_len; i++) { + data[i] = read(nack_at_end ? (i < data_len - 1) : true); + } +} + diff --git a/soft_twi.hpp b/soft_twi.hpp new file mode 100644 index 0000000..1d477fa --- /dev/null +++ b/soft_twi.hpp @@ -0,0 +1,37 @@ + +#pragma once + +#include + +struct SoftTWI { + + SoftTWI(unsigned pin_sda, unsigned pin_scl, unsigned delay = 0); + + void begin(); + void sleep(unsigned=1); + void set_sda(bool); + void set_scl(bool); + bool read_sda(); + bool read_scl(); + void wait_scl(); + + void write_bit(bool); + bool write(uint8_t); + unsigned write(const uint8_t*, unsigned); + + bool read_bit(); + uint8_t read(bool=true); + void read(uint8_t*, unsigned, bool=false); + + bool start_read(uint8_t); + bool start_write(uint8_t); + + void start(); + void end(); + +private: + unsigned _pin_scl; + unsigned _pin_sda; + unsigned _delay; +}; + diff --git a/util.hpp b/util.hpp index 0dda16e..280c6fb 100644 --- a/util.hpp +++ b/util.hpp @@ -13,5 +13,6 @@ inline void swap(T& a, T& b) { a = t; } +#define bm(V) (((uint64_t)1 << V) - 1); #define size(V) (sizeof(V) / sizeof(V[0]))