177 lines
3.4 KiB
C
177 lines
3.4 KiB
C
#include <assert.h>
|
|
#include <stdlib.h>
|
|
#include <syslog.h>
|
|
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
#include <unistd.h>
|
|
|
|
#include <i2c_bb.h>
|
|
|
|
|
|
static void write_bit(const struct i2c_bb *i2c, uint8_t bit);
|
|
static uint8_t read_bit(const struct i2c_bb *i2c);
|
|
static void start_condition(const struct i2c_bb *i2c);
|
|
static void stop_condition(const struct i2c_bb *i2c);
|
|
static bool write_byte(const struct i2c_bb *i2c, uint8_t byte);
|
|
static uint8_t read_byte(const struct i2c_bb *i2c, bool ack);
|
|
|
|
// cppcheck-suppress unusedFunction
|
|
int i2c_open(const struct i2c_bb *i2c)
|
|
{
|
|
int res = EXIT_SUCCESS;
|
|
|
|
assert(NULL != i2c);
|
|
|
|
res = gpio_open(i2c->sda);
|
|
res |= gpio_open(i2c->scl);
|
|
res |= gpio_write(i2c->sda, 1);
|
|
res |= gpio_write(i2c->scl, 1);
|
|
|
|
return res;
|
|
}
|
|
|
|
// cppcheck-suppress unusedFunction
|
|
int i2c_close(const struct i2c_bb *i2c)
|
|
{
|
|
int res = EXIT_SUCCESS;
|
|
assert(NULL != i2c);
|
|
|
|
res = gpio_close(i2c->sda);
|
|
res |= gpio_close(i2c->scl);
|
|
|
|
return res;
|
|
}
|
|
|
|
// cppcheck-suppress unusedFunction
|
|
int i2c_read(const struct i2c_bb *i2c, uint8_t slave_addr, char *buffer, unsigned int len)
|
|
{
|
|
unsigned int i;
|
|
assert(NULL != i2c);
|
|
|
|
if((NULL == buffer) || len == 0) {
|
|
return 0;
|
|
}
|
|
|
|
start_condition(i2c);
|
|
write_byte(i2c, (slave_addr << 1) | 1);
|
|
for(i = 0; i < len; i++) {
|
|
buffer[i] = read_byte(i2c, true);
|
|
}
|
|
stop_condition(i2c);
|
|
|
|
return (int)i;
|
|
}
|
|
|
|
// cppcheck-suppress unusedFunction
|
|
int i2c_write(const struct i2c_bb *i2c, uint8_t slave_addr, const char *buffer, unsigned int len)
|
|
{
|
|
unsigned int i;
|
|
|
|
assert(NULL != i2c);
|
|
|
|
if((NULL == buffer) || len == 0) {
|
|
return 0;
|
|
}
|
|
|
|
start_condition(i2c);
|
|
write_byte(i2c, slave_addr << 1);
|
|
for(i = 0; i < len; i++) {
|
|
write_byte(i2c, buffer[i]);
|
|
}
|
|
stop_condition(i2c);
|
|
|
|
return (int)i;
|
|
}
|
|
|
|
static void start_condition(const struct i2c_bb *i2c)
|
|
{
|
|
assert( NULL != i2c);
|
|
|
|
gpio_write(i2c->scl, 1);
|
|
gpio_write(i2c->sda, 1);
|
|
usleep(5);
|
|
gpio_write(i2c->sda, 0);
|
|
usleep(5);
|
|
gpio_write(i2c->scl, 0);
|
|
usleep(5);
|
|
}
|
|
|
|
static void stop_condition(const struct i2c_bb *i2c)
|
|
{
|
|
assert( NULL != i2c);
|
|
|
|
gpio_write(i2c->sda, 0);
|
|
usleep(5);
|
|
gpio_write(i2c->scl, 1);
|
|
usleep(5);
|
|
gpio_write(i2c->sda, 1);
|
|
usleep(5);
|
|
}
|
|
|
|
static bool write_byte(const struct i2c_bb *i2c, uint8_t byte)
|
|
{
|
|
uint8_t ack, i;
|
|
|
|
assert(NULL != i2c);
|
|
|
|
for(i = 0; i < 8; i++) {
|
|
write_bit(i2c, byte & 0x80);
|
|
byte <<= 1;
|
|
}
|
|
|
|
ack = read_bit(i2c);
|
|
|
|
return (bool)(ack & 0x01);
|
|
}
|
|
|
|
static uint8_t read_byte(const struct i2c_bb *i2c, bool ack)
|
|
{
|
|
uint8_t res = 0, i;
|
|
|
|
assert(NULL != i2c);
|
|
|
|
for(i = 0; i < 8; i++) {
|
|
res <<= 1;
|
|
res |= read_bit(i2c);
|
|
}
|
|
|
|
if(ack) {
|
|
write_bit(i2c, 0);
|
|
} else {
|
|
write_bit(i2c, 1);
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static void write_bit(const struct i2c_bb *i2c, uint8_t bit)
|
|
{
|
|
assert( NULL != i2c);
|
|
|
|
if(bit > 0) {
|
|
gpio_write(i2c->sda, 1);
|
|
} else {
|
|
gpio_write(i2c->sda, 0);
|
|
}
|
|
usleep(5);
|
|
gpio_write(i2c->scl, 1);
|
|
usleep(5);
|
|
gpio_write(i2c->scl, 0);
|
|
}
|
|
|
|
static uint8_t read_bit(const struct i2c_bb *i2c)
|
|
{
|
|
unsigned int res;
|
|
|
|
assert(NULL != i2c);
|
|
|
|
gpio_write(i2c->sda, 1);
|
|
usleep(5);
|
|
gpio_write(i2c->scl, 1);
|
|
usleep(5);
|
|
gpio_read(i2c->sda, &res);
|
|
gpio_write(i2c->scl, 0);
|
|
|
|
return (uint8_t) res;
|
|
}
|