added bufferless i2c implementation
This commit is contained in:
parent
89aaa0c91a
commit
ab6bb7d14b
39
data.cpp
39
data.cpp
|
@ -13,36 +13,19 @@ using namespace data;
|
||||||
static Mode mode = Mode::none;
|
static Mode mode = Mode::none;
|
||||||
|
|
||||||
static void flash_data() {
|
static void flash_data() {
|
||||||
char buff[128];
|
uint32_t at = 0;
|
||||||
unsigned count;
|
uint16_t count;
|
||||||
unsigned at = 0;
|
char buffer[eeprom::PAGE_SIZE];
|
||||||
unsigned max_len = eeprom::length();
|
|
||||||
|
|
||||||
for(;;) {
|
do {
|
||||||
unsigned count = sizeof(buff);
|
count = serial::read(buffer, eeprom::PAGE_SIZE);
|
||||||
unsigned end = at + count;
|
eeprom::page_write(at, buffer);
|
||||||
|
at += eeprom::PAGE_SIZE;
|
||||||
|
delay(10);
|
||||||
|
} while(count == eeprom::PAGE_SIZE);
|
||||||
|
|
||||||
if(end <= at) {
|
while(serial::is_connected()) {
|
||||||
break;
|
serial::get();
|
||||||
}
|
|
||||||
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))) {
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
88
eeprom.cpp
88
eeprom.cpp
|
@ -1,41 +1,87 @@
|
||||||
|
|
||||||
#include <Wire.h>
|
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <SparkFun_External_EEPROM.h>
|
|
||||||
#include "eeprom.hpp"
|
#include "eeprom.hpp"
|
||||||
|
#include "util.hpp"
|
||||||
|
|
||||||
|
using namespace eeprom;
|
||||||
|
|
||||||
|
constexpr uint8_t WRITE_MS = 3;
|
||||||
constexpr uint8_t ADDR = 0x50;
|
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() {
|
void eeprom::init() {
|
||||||
Wire.setClock(400000);
|
|
||||||
Wire.begin();
|
|
||||||
mem.setMemoryType(1025);
|
|
||||||
mem.begin();
|
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() {
|
void eeprom::jump(uint32_t p_at) {
|
||||||
return mem.length();
|
p_at = at;
|
||||||
}
|
}
|
||||||
|
|
||||||
void eeprom::jump(unsigned loc) {
|
void eeprom::read(char* data, uint16_t data_size) {
|
||||||
at = loc;
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
void eeprom::read(char* data, unsigned len) {
|
mem.end();
|
||||||
mem.read(at, data, len);
|
|
||||||
at += len;
|
for(uint16_t i = recorded; i < data_size; i++) {
|
||||||
|
data[i] = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void eeprom::read(unsigned loc, char* data, unsigned len) {
|
void eeprom::page_write(uint32_t at, const char* data) {
|
||||||
mem.read(loc, data, len);
|
uint8_t i2c_addr = get_i2c_addr(at);
|
||||||
}
|
wait_for_responsive(i2c_addr);
|
||||||
|
mem.start_write(i2c_addr);
|
||||||
void eeprom::write(unsigned loc, const char* data, unsigned len) {
|
mem.write(at >> 8);
|
||||||
mem.write(loc, data, len);
|
mem.write(at);
|
||||||
|
mem.write(data, PAGE_SIZE - (at % PAGE_SIZE));
|
||||||
|
mem.end();
|
||||||
|
delay(WRITE_MS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
17
eeprom.hpp
17
eeprom.hpp
|
@ -1,15 +1,20 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include "soft_twi.hpp"
|
||||||
|
|
||||||
namespace eeprom {
|
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 init();
|
||||||
void jump(unsigned addr);
|
void jump(uint32_t addr);
|
||||||
void read(char* data, unsigned len);
|
void read(char* data, uint16_t len);
|
||||||
void read(unsigned addr, char* data, unsigned len);
|
void page_write(uint32_t at, const char* data);
|
||||||
void write(unsigned addr, const char* data, unsigned len);
|
|
||||||
unsigned length();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -3,21 +3,24 @@
|
||||||
#include "indicator.hpp"
|
#include "indicator.hpp"
|
||||||
#include "tones.hpp"
|
#include "tones.hpp"
|
||||||
|
|
||||||
constexpr int PIN = 10;
|
constexpr int PIN = 9;
|
||||||
|
|
||||||
void indicator::init() {
|
void indicator::init() {
|
||||||
pinMode(PIN, OUTPUT);
|
pinMode(PIN+0, OUTPUT);
|
||||||
|
pinMode(PIN+1, OUTPUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void indicator::reset() {
|
void indicator::reset() {
|
||||||
analogWrite(PIN, 0);
|
analogWrite(PIN+0, 0);
|
||||||
|
analogWrite(PIN+1, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void indicator::update() {
|
void indicator::update() {
|
||||||
unsigned v = 0;
|
unsigned v[2] = {2};
|
||||||
for(int i = 0; i < tones::active; i++) {
|
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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,10 +22,6 @@ struct {
|
||||||
bool active = false;
|
bool active = false;
|
||||||
} next;
|
} next;
|
||||||
|
|
||||||
constexpr uint64_t bm(int n) {
|
|
||||||
return ((uint64_t)1 << n) - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void scheduler::reset() {
|
void scheduler::reset() {
|
||||||
tones::clear_all();
|
tones::clear_all();
|
||||||
ts_init = micros();
|
ts_init = micros();
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <SoftwareSerial.h>
|
#include <SoftwareSerial.h>
|
||||||
#include <avr/pgmspace.h>
|
|
||||||
|
|
||||||
namespace serial {
|
namespace serial {
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,126 @@
|
||||||
|
|
||||||
|
#include "soft_twi.hpp"
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
Loading…
Reference in New Issue