optimise I2C
This commit is contained in:
parent
1077930330
commit
78965abed2
|
@ -33,10 +33,6 @@ static void set_address(uint8_t i2c_addr, uint16_t at) {
|
||||||
mem.write(at);
|
mem.write(at);
|
||||||
}
|
}
|
||||||
|
|
||||||
void eeprom::init() {
|
|
||||||
mem.begin();
|
|
||||||
}
|
|
||||||
|
|
||||||
void eeprom::jump(uint32_t p_at) {
|
void eeprom::jump(uint32_t p_at) {
|
||||||
last_block_end = 0;
|
last_block_end = 0;
|
||||||
at = p_at;
|
at = p_at;
|
||||||
|
|
|
@ -12,7 +12,6 @@ namespace eeprom {
|
||||||
|
|
||||||
inline SoftTWI mem(A4, A5);
|
inline SoftTWI mem(A4, A5);
|
||||||
|
|
||||||
void init();
|
|
||||||
void jump(uint32_t addr);
|
void jump(uint32_t addr);
|
||||||
void read(char* data, uint16_t len);
|
void read(char* data, uint16_t len);
|
||||||
void page_write(uint32_t at, const char* data);
|
void page_write(uint32_t at, const char* data);
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "util.hpp"
|
||||||
|
|
||||||
|
namespace port {
|
||||||
|
struct Drain {
|
||||||
|
uint8_t mask;
|
||||||
|
uint8_t imask;
|
||||||
|
volatile uint8_t* mode;
|
||||||
|
volatile uint8_t* in;
|
||||||
|
|
||||||
|
inline Drain(unsigned pin) AW_IN {
|
||||||
|
mask = digitalPinToBitMask(pin);
|
||||||
|
mode = portModeRegister(digitalPinToPort(pin));
|
||||||
|
in = portInputRegister(digitalPinToPort(pin));
|
||||||
|
imask = ~mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void set(uint8_t b) AW_IN {
|
||||||
|
if(b) {
|
||||||
|
*mode &= imask;
|
||||||
|
} else {
|
||||||
|
*mode |= mask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint8_t get() AW_IN {
|
||||||
|
return *in & mask;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Input {
|
||||||
|
uint8_t mask;
|
||||||
|
uint8_t imask;
|
||||||
|
volatile uint8_t* in;
|
||||||
|
|
||||||
|
inline Input(unsigned pin) AW_IN {
|
||||||
|
mask = digitalPinToBitMask(pin);
|
||||||
|
in = portInputRegister(digitalPinToPort(pin));
|
||||||
|
imask = ~mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint8_t get() AW_IN {
|
||||||
|
return *in & mask;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Output {
|
||||||
|
uint8_t mask;
|
||||||
|
uint8_t imask;
|
||||||
|
volatile uint8_t* out;
|
||||||
|
|
||||||
|
inline Output(unsigned pin) AW_IN {
|
||||||
|
mask = digitalPinToBitMask(pin);
|
||||||
|
out = portOutputRegister(digitalPinToPort(pin));
|
||||||
|
imask = ~mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void set(uint8_t b) AW_IN {
|
||||||
|
if(b) {
|
||||||
|
*out |= mask;
|
||||||
|
} else {
|
||||||
|
*out &= imask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
77
soft_twi.cpp
77
soft_twi.cpp
|
@ -1,42 +1,53 @@
|
||||||
|
|
||||||
#include "soft_twi.hpp"
|
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
#include "soft_twi.hpp"
|
||||||
void SoftTWI::set_pin(uint8_t pin, bool state) {
|
#include "port.hpp"
|
||||||
uint8_t bitmask = digitalPinToBitMask(pin);
|
|
||||||
volatile uint8_t* reg = portModeRegister(digitalPinToPort(pin));
|
|
||||||
if(state) {
|
|
||||||
*reg &= ~bitmask;
|
|
||||||
} else {
|
|
||||||
*reg |= bitmask;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SoftTWI::begin() {
|
|
||||||
digitalWrite(_sda, 0);
|
|
||||||
digitalWrite(_scl, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SoftTWI::read_pin(uint8_t pin) {
|
|
||||||
return digitalRead(pin);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t SoftTWI::read(bool ack) {
|
uint8_t SoftTWI::read(bool ack) {
|
||||||
|
port::Drain sda(_sda);
|
||||||
|
port::Drain scl(_scl);
|
||||||
|
|
||||||
uint8_t v = 0;
|
uint8_t v = 0;
|
||||||
for(unsigned m = 0x80; m; m >>= 1) {
|
for(unsigned m = 0x80; m; m >>= 1) {
|
||||||
if(read_bit()) {
|
sda.set(1);
|
||||||
|
scl.set(1);
|
||||||
|
while(!scl.get()) {}
|
||||||
|
if(sda.get()) {
|
||||||
v |= m;
|
v |= m;
|
||||||
}
|
}
|
||||||
|
scl.set(0);
|
||||||
}
|
}
|
||||||
write_bit(!ack); // send ACK
|
|
||||||
|
// send ACK
|
||||||
|
if(ack) {
|
||||||
|
sda.set(!ack);
|
||||||
|
scl.set(1);
|
||||||
|
while(!scl.get()) {}
|
||||||
|
scl.set(0);
|
||||||
|
}
|
||||||
|
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SoftTWI::write(uint8_t v) {
|
bool SoftTWI::write(uint8_t v) {
|
||||||
|
port::Drain sda(_sda);
|
||||||
|
port::Drain scl(_scl);
|
||||||
|
|
||||||
for(unsigned m = 0x80; m; m >>= 1) {
|
for(unsigned m = 0x80; m; m >>= 1) {
|
||||||
write_bit(v & m);
|
sda.set(v & m);
|
||||||
|
scl.set(1);
|
||||||
|
while(!scl.get()) {}
|
||||||
|
scl.set(0);
|
||||||
}
|
}
|
||||||
return !read_bit(); // get ACK
|
|
||||||
|
// get ACK
|
||||||
|
sda.set(1);
|
||||||
|
scl.set(1);
|
||||||
|
while(!scl.get()) {}
|
||||||
|
uint8_t s = sda.get();
|
||||||
|
scl.set(0);
|
||||||
|
|
||||||
|
return !s;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoftTWI::read(uint8_t* data, unsigned data_len, bool nack_at_end) {
|
void SoftTWI::read(uint8_t* data, unsigned data_len, bool nack_at_end) {
|
||||||
|
@ -54,3 +65,21 @@ unsigned SoftTWI::write(const uint8_t* data, unsigned data_len) {
|
||||||
return data_len;
|
return data_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SoftTWI::start(uint8_t addr) {
|
||||||
|
port::Drain sda(_sda);
|
||||||
|
port::Drain scl(_scl);
|
||||||
|
sda.set(1);
|
||||||
|
scl.set(1);
|
||||||
|
sda.set(0);
|
||||||
|
scl.set(0);
|
||||||
|
write(addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoftTWI::end() {
|
||||||
|
port::Drain sda(_sda);
|
||||||
|
port::Drain scl(_scl);
|
||||||
|
sda.set(0);
|
||||||
|
scl.set(1);
|
||||||
|
sda.set(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
116
soft_twi.hpp
116
soft_twi.hpp
|
@ -6,115 +6,29 @@
|
||||||
|
|
||||||
struct SoftTWI {
|
struct SoftTWI {
|
||||||
|
|
||||||
constexpr SoftTWI(unsigned sda, unsigned scl, unsigned delay = 0);
|
constexpr SoftTWI::SoftTWI(unsigned sda, unsigned scl)
|
||||||
|
: _sda(sda)
|
||||||
|
, _scl(scl) {
|
||||||
|
}
|
||||||
|
|
||||||
void begin();
|
|
||||||
inline void sleep(uint8_t=1) AW_IN {}
|
|
||||||
inline void wait_scl() AW_IN;
|
|
||||||
|
|
||||||
void set_pin(uint8_t, bool);
|
|
||||||
inline void set_sda(bool) AW_IN;
|
|
||||||
inline void set_scl(bool) AW_IN;
|
|
||||||
|
|
||||||
bool read_pin(uint8_t);
|
|
||||||
inline bool read_sda() AW_IN;
|
|
||||||
inline bool read_scl() AW_IN;
|
|
||||||
|
|
||||||
inline void write_bit(bool) AW_IN;
|
|
||||||
bool write(uint8_t);
|
|
||||||
unsigned write(const uint8_t*, unsigned);
|
unsigned write(const uint8_t*, unsigned);
|
||||||
|
|
||||||
inline bool read_bit() AW_IN;
|
|
||||||
uint8_t read(bool=true);
|
|
||||||
void read(uint8_t*, unsigned, bool=false);
|
void read(uint8_t*, unsigned, bool=false);
|
||||||
|
uint8_t read(bool=true);
|
||||||
|
bool write(uint8_t);
|
||||||
|
void end();
|
||||||
|
|
||||||
inline bool start_read(uint8_t) AW_IN;
|
inline bool start_read(uint8_t addr) {
|
||||||
inline bool start_write(uint8_t) AW_IN;
|
return start((addr << 1) | 1);
|
||||||
|
}
|
||||||
|
|
||||||
inline void start() AW_IN;
|
inline bool start_write(uint8_t addr) {
|
||||||
inline void end() AW_IN;
|
return start(addr << 1);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
unsigned _sda;
|
unsigned _sda;
|
||||||
unsigned _scl;
|
unsigned _scl;
|
||||||
unsigned _delay;
|
|
||||||
|
bool start(uint8_t addr);
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr SoftTWI::SoftTWI(unsigned sda, unsigned scl, unsigned delay)
|
|
||||||
: _sda(sda)
|
|
||||||
, _scl(scl)
|
|
||||||
, _delay(delay) {
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void SoftTWI::set_sda(bool s) {
|
|
||||||
set_pin(_sda, s);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void SoftTWI::set_scl(bool s) {
|
|
||||||
set_pin(_scl, s);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool SoftTWI::read_sda() {
|
|
||||||
return read_pin(_sda);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool SoftTWI::read_scl() {
|
|
||||||
return read_pin(_scl);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void SoftTWI::wait_scl() {
|
|
||||||
while(!read_pin(_scl)) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void SoftTWI::write_bit(bool s) {
|
|
||||||
set_sda(s);
|
|
||||||
sleep();
|
|
||||||
set_scl(1);
|
|
||||||
sleep(2);
|
|
||||||
wait_scl();
|
|
||||||
set_scl(0);
|
|
||||||
sleep();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void SoftTWI::start() {
|
|
||||||
set_sda(1);
|
|
||||||
sleep();
|
|
||||||
set_scl(1);
|
|
||||||
sleep();
|
|
||||||
set_sda(0);
|
|
||||||
sleep();
|
|
||||||
set_scl(0);
|
|
||||||
sleep();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void SoftTWI::end() {
|
|
||||||
set_sda(0);
|
|
||||||
sleep();
|
|
||||||
set_scl(1);
|
|
||||||
sleep();
|
|
||||||
set_sda(1);
|
|
||||||
sleep(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool SoftTWI::start_read(uint8_t addr) {
|
|
||||||
start();
|
|
||||||
return write((addr << 1) | 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool SoftTWI::start_write(uint8_t addr) {
|
|
||||||
start();
|
|
||||||
return write(addr << 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,6 @@ void setup() {
|
||||||
Tone::init();
|
Tone::init();
|
||||||
dac::init();
|
dac::init();
|
||||||
serial::init();
|
serial::init();
|
||||||
eeprom::init();
|
|
||||||
tones::init();
|
tones::init();
|
||||||
indicator::init();
|
indicator::init();
|
||||||
buttons::init();
|
buttons::init();
|
||||||
|
|
Loading…
Reference in New Issue