130 lines
2.2 KiB
Plaintext
130 lines
2.2 KiB
Plaintext
#include "SoftI2C.h"
|
|
|
|
SoftI2C::SoftI2C(uint8_t sda, uint8_t scl, uint32_t freq) {
|
|
sda_pin = sda;
|
|
scl_pin = scl;
|
|
delay_us = 1000000 / (2 * freq); // نیم پریود
|
|
}
|
|
|
|
void SoftI2C::begin() {
|
|
pinMode(sda_pin, INPUT_PULLUP);
|
|
pinMode(scl_pin, INPUT_PULLUP);
|
|
delay(10);
|
|
}
|
|
|
|
void SoftI2C::end() {
|
|
stop_condition();
|
|
pinMode(sda_pin, INPUT);
|
|
pinMode(scl_pin, INPUT);
|
|
}
|
|
|
|
void SoftI2C::start_condition() {
|
|
pinMode(sda_pin, OUTPUT);
|
|
sda_high();
|
|
scl_high();
|
|
i2c_delay();
|
|
sda_low();
|
|
i2c_delay();
|
|
scl_low();
|
|
i2c_delay();
|
|
}
|
|
|
|
void SoftI2C::stop_condition() {
|
|
pinMode(sda_pin, OUTPUT);
|
|
sda_low();
|
|
i2c_delay();
|
|
scl_high();
|
|
i2c_delay();
|
|
sda_high();
|
|
i2c_delay();
|
|
pinMode(sda_pin, INPUT_PULLUP);
|
|
pinMode(scl_pin, INPUT_PULLUP);
|
|
}
|
|
|
|
bool SoftI2C::write_byte(uint8_t data) {
|
|
pinMode(sda_pin, OUTPUT);
|
|
|
|
for(int i = 7; i >= 0; i--) {
|
|
if(data & (1 << i)) {
|
|
sda_high();
|
|
} else {
|
|
sda_low();
|
|
}
|
|
i2c_delay();
|
|
scl_high();
|
|
i2c_delay();
|
|
scl_low();
|
|
i2c_delay();
|
|
}
|
|
|
|
// خواندن ACK
|
|
pinMode(sda_pin, INPUT_PULLUP);
|
|
i2c_delay();
|
|
scl_high();
|
|
i2c_delay();
|
|
bool ack = !read_sda();
|
|
scl_low();
|
|
i2c_delay();
|
|
|
|
return ack;
|
|
}
|
|
|
|
uint8_t SoftI2C::read_byte(bool ack) {
|
|
pinMode(sda_pin, INPUT_PULLUP);
|
|
uint8_t data = 0;
|
|
|
|
for(int i = 7; i >= 0; i--) {
|
|
scl_high();
|
|
i2c_delay();
|
|
if(read_sda()) {
|
|
data |= (1 << i);
|
|
}
|
|
scl_low();
|
|
i2c_delay();
|
|
}
|
|
|
|
// ارسال ACK/NACK
|
|
pinMode(sda_pin, OUTPUT);
|
|
if(ack) {
|
|
sda_low();
|
|
} else {
|
|
sda_high();
|
|
}
|
|
i2c_delay();
|
|
scl_high();
|
|
i2c_delay();
|
|
scl_low();
|
|
i2c_delay();
|
|
|
|
return data;
|
|
}
|
|
|
|
bool SoftI2C::begin_transmission(uint8_t addr) {
|
|
start_condition();
|
|
return write_byte(addr << 1); // آدرس + بیت write
|
|
}
|
|
|
|
bool SoftI2C::write(uint8_t data) {
|
|
return write_byte(data);
|
|
}
|
|
|
|
bool SoftI2C::end_transmission() {
|
|
stop_condition();
|
|
return true;
|
|
}
|
|
|
|
uint8_t SoftI2C::request_from(uint8_t addr, uint8_t count) {
|
|
start_condition();
|
|
if(!write_byte((addr << 1) | 1)) { // آدرس + بیت read
|
|
return 0;
|
|
}
|
|
return count;
|
|
}
|
|
|
|
uint8_t SoftI2C::read() {
|
|
return read_byte(true);
|
|
}
|
|
|
|
bool SoftI2C::available() {
|
|
return true;
|
|
} |