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);
|
||||
}
|
||||
|
||||
void eeprom::init() {
|
||||
mem.begin();
|
||||
}
|
||||
|
||||
void eeprom::jump(uint32_t p_at) {
|
||||
last_block_end = 0;
|
||||
at = p_at;
|
||||
|
|
|
@ -12,7 +12,6 @@ namespace eeprom {
|
|||
|
||||
inline SoftTWI mem(A4, A5);
|
||||
|
||||
void init();
|
||||
void jump(uint32_t addr);
|
||||
void read(char* data, uint16_t len);
|
||||
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>
|
||||
|
||||
void SoftTWI::set_pin(uint8_t pin, bool state) {
|
||||
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);
|
||||
}
|
||||
#include "soft_twi.hpp"
|
||||
#include "port.hpp"
|
||||
|
||||
uint8_t SoftTWI::read(bool ack) {
|
||||
port::Drain sda(_sda);
|
||||
port::Drain scl(_scl);
|
||||
|
||||
uint8_t v = 0;
|
||||
for(unsigned m = 0x80; m; m >>= 1) {
|
||||
if(read_bit()) {
|
||||
sda.set(1);
|
||||
scl.set(1);
|
||||
while(!scl.get()) {}
|
||||
if(sda.get()) {
|
||||
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;
|
||||
}
|
||||
|
||||
bool SoftTWI::write(uint8_t v) {
|
||||
port::Drain sda(_sda);
|
||||
port::Drain scl(_scl);
|
||||
|
||||
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) {
|
||||
|
@ -54,3 +65,21 @@ unsigned SoftTWI::write(const uint8_t* data, unsigned 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);
|
||||
}
|
||||
|
||||
|
|
118
soft_twi.hpp
118
soft_twi.hpp
|
@ -6,115 +6,29 @@
|
|||
|
||||
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);
|
||||
|
||||
inline bool read_bit() AW_IN;
|
||||
uint8_t read(bool=true);
|
||||
void read(uint8_t*, unsigned, bool=false);
|
||||
uint8_t read(bool=true);
|
||||
bool write(uint8_t);
|
||||
void end();
|
||||
|
||||
inline bool start_read(uint8_t addr) {
|
||||
return start((addr << 1) | 1);
|
||||
}
|
||||
|
||||
inline bool start_read(uint8_t) AW_IN;
|
||||
inline bool start_write(uint8_t) AW_IN;
|
||||
|
||||
inline void start() AW_IN;
|
||||
inline void end() AW_IN;
|
||||
inline bool start_write(uint8_t addr) {
|
||||
return start(addr << 1);
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned _sda;
|
||||
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();
|
||||
dac::init();
|
||||
serial::init();
|
||||
eeprom::init();
|
||||
tones::init();
|
||||
indicator::init();
|
||||
buttons::init();
|
||||
|
|
Loading…
Reference in New Issue