2024-08-31 01:53:25 +10:00
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <inttypes.h>
|
|
|
|
|
|
|
|
struct SoftTWI {
|
|
|
|
|
2024-08-31 16:31:19 +10:00
|
|
|
constexpr SoftTWI(unsigned sda, unsigned scl, unsigned delay = 0);
|
2024-08-31 01:53:25 +10:00
|
|
|
|
|
|
|
void begin();
|
2024-08-31 16:31:19 +10:00
|
|
|
inline void sleep(uint8_t=1) {}
|
|
|
|
inline void wait_scl();
|
|
|
|
|
|
|
|
void set_pin(uint8_t, bool);
|
|
|
|
inline void set_sda(bool);
|
|
|
|
inline void set_scl(bool);
|
|
|
|
|
|
|
|
bool read_pin(uint8_t);
|
|
|
|
inline bool read_sda();
|
|
|
|
inline bool read_scl();
|
|
|
|
|
|
|
|
inline void write_bit(bool);
|
2024-08-31 01:53:25 +10:00
|
|
|
bool write(uint8_t);
|
|
|
|
unsigned write(const uint8_t*, unsigned);
|
|
|
|
|
2024-08-31 16:31:19 +10:00
|
|
|
inline bool read_bit();
|
2024-08-31 01:53:25 +10:00
|
|
|
uint8_t read(bool=true);
|
|
|
|
void read(uint8_t*, unsigned, bool=false);
|
|
|
|
|
2024-08-31 16:31:19 +10:00
|
|
|
inline bool start_read(uint8_t);
|
|
|
|
inline bool start_write(uint8_t);
|
2024-08-31 01:53:25 +10:00
|
|
|
|
2024-08-31 16:31:19 +10:00
|
|
|
inline void start();
|
|
|
|
inline void end();
|
2024-08-31 01:53:25 +10:00
|
|
|
|
|
|
|
private:
|
2024-08-31 16:31:19 +10:00
|
|
|
unsigned _sda;
|
|
|
|
unsigned _scl;
|
2024-08-31 01:53:25 +10:00
|
|
|
unsigned _delay;
|
|
|
|
};
|
|
|
|
|
2024-08-31 16:31:19 +10:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|