i2c_bb/src/i2c.c

175 lines
3.3 KiB
C
Raw Normal View History

2019-07-18 14:26:03 +00:00
#include <assert.h>
#include <stdlib.h>
#include <syslog.h>
#include <stdbool.h>
#include <stdint.h>
#include <unistd.h>
#include <i2c_bb.h>
2019-07-20 06:53:44 +00:00
2019-07-18 14:26:03 +00:00
static void write_bit(const struct i2c_bb *i2c, uint8_t bit);
static uint8_t read_bit(const struct i2c_bb *i2c);
2019-07-23 12:53:51 +00:00
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);
2019-07-18 14:26:03 +00:00
// cppcheck-suppress unusedFunction
int i2c_open(const struct i2c_bb *i2c)
{
int res = EXIT_SUCCESS;
assert(NULL != i2c);
res = gpio_open(i2c->sda);
2019-07-22 15:27:46 +00:00
res |= gpio_open(i2c->scl);
2019-07-18 14:26:03 +00:00
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);
2019-07-22 15:27:46 +00:00
res |= gpio_close(i2c->scl);
2019-07-18 14:26:03 +00:00
return res;
}
2019-07-23 13:42:56 +00:00
// cppcheck-suppress unusedFunction
2019-07-23 13:26:50 +00:00
int i2c_read(const struct i2c_bb *i2c, uint8_t slave_addr, char *buffer, unsigned int len)
2019-07-23 12:53:51 +00:00
{
unsigned int i;
assert(NULL != i2c);
if((NULL == buffer) || len == 0) {
return 0;
}
start_condition(i2c);
write_byte(i2c, (slave_addr & 0x80));
for(i = 0; i < len; i++) {
buffer[i] = read_byte(i2c, true);
}
stop_condition(i2c);
return (int)i;
}
2019-07-23 13:42:56 +00:00
// cppcheck-suppress unusedFunction
2019-07-23 13:26:50 +00:00
int i2c_write(const struct i2c_bb *i2c, uint8_t slave_addr, const char *buffer, unsigned int len)
2019-07-23 12:53:51 +00:00
{
unsigned int i;
assert(NULL != i2c);
if((NULL == buffer) || len == 0) {
return 0;
}
start_condition(i2c);
write_byte(i2c, (slave_addr & 0x7F));
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)
2019-07-18 14:26:03 +00:00
{
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);
}
2019-07-23 12:53:51 +00:00
static void stop_condition(const struct i2c_bb *i2c)
2019-07-18 14:26:03 +00:00
{
assert( NULL != i2c);
gpio_write(i2c->sda, 0);
usleep(5);
gpio_write(i2c->scl, 1);
usleep(5);
gpio_write(i2c->sda, 1);
usleep(5);
}
2019-07-23 12:53:51 +00:00
static bool write_byte(const struct i2c_bb *i2c, uint8_t byte)
2019-07-18 14:26:03 +00:00
{
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);
}
2019-07-23 12:53:51 +00:00
static uint8_t read_byte(const struct i2c_bb *i2c, bool ack)
2019-07-18 14:26:03 +00:00
{
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, 0);
}
return res;
}
static void write_bit(const struct i2c_bb *i2c, uint8_t bit)
{
assert( NULL != i2c);
if((bit & 0x01) > 0) {
gpio_write(i2c->sda, 1);
} else {
gpio_write(i2c->sda, 1);
}
usleep(5);
gpio_write(i2c->scl, 1);
usleep(5);
gpio_write(i2c->scl, 1);
}
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, 1);
return (uint8_t) res;
}