Hello again!
So i did some minor modifications to the code found on the MIT: How to Make Almost Anything website, and I got it working. It isn't even a library, just the raw functions for a Bit-Bang approach. I'm guessing it doesn't support bit stretching and may lack some other functionality, but hey better than nothing.
here is my code:
#include "TinyWireS.h"
//
// hello.ADXL343.c
//
// ADXL343 accelerometer hello-world
// 9600 baud FTDI interface
//
// Neil Gershenfeld 11/8/15
// (c) Massachusetts Institute of Technology 2015
//
// This work may be reproduced, modified, distributed,
// performed, and displayed for any purpose. Copyright is
// retained and must be preserved. The work is provided
// as is; no warranty is provided, and users accept all
// liability.
//
#include <avr/io.h>
#include <util/delay.h>
#define output(directions,pin) (directions |= pin) // set port direction for output
#define input(directions,pin) (directions &= (~pin)) // set port direction for input
#define set(port,pin) (port |= pin) // set port pin
#define clear(port,pin) (port &= (~pin)) // clear port pin
#define pin_test(pins,pin) (pins & pin) // test for port pin
#define bit_test(byte,bit) (byte & (1 << bit)) // test for bit set
#define bit_delay_time 102 // bit delay for 9600 with overhead
#define bit_delay() _delay_us(bit_delay_time) // RS232 bit delay
#define half_bit_delay() _delay_us(bit_delay_time/2) // RS232 half bit delay
#define I2C_slave_address 0x53 // ADXL345 alt address
#define I2C_delay() _delay_us(5)
#define SCL_pin (1 << PB3)
#define SCL_pins PINB
#define SCL_port PORTB
#define SCL_direction DDRB
#define SDA_pin (1 << PB4)
#define SDA_pins PINB
#define SDA_port PORTB
#define SDA_direction DDRB
#define SLAVE_ADDR 0x27
unsigned char data[6] = {0, 1, 2, 3, 4, 5};
unsigned char ret;
void requestEvent()
{
for (int i = 0; i < sizeof(data); i++)
TinyWireS.write(data[i]); // send it back to master
}
void setup() {
TinyWireS.begin(SLAVE_ADDR);
TinyWireS.onRequest(requestEvent);
//
// set clock divider to /1
//
CLKPR = (1 << CLKPCE);
CLKPR = (0 << CLKPS3) | (0 << CLKPS2) | (0 << CLKPS1) | (0 << CLKPS0);
//
// main loop
//
I2C_init();
data[0] = 0x2D; // POWER_CTL register
data[1] = 8; // turn on measure bit
ret = I2C_master_write(data, 2, I2C_slave_address);
}
void loop() {
//
// read data
//
data[0] = 0x32; // X0 register
ret = I2C_master_write(data, 1, I2C_slave_address);
ret = I2C_master_read(data, 6, I2C_slave_address);
}
void SCL_write(char bit) {
//
// write SCL bit
//
if (bit == 0) {
output(SCL_direction, SCL_pin);
clear(SCL_port, SCL_pin);
}
else {
input(SCL_direction, SCL_pin);
while (pin_test(SCL_pins, SCL_pin) == 0); // check for clock stretching
}
}
void SDA_write(char bit) {
//
// write SDA bit
//
if (bit == 0) {
output(SDA_direction, SDA_pin);
clear(SDA_port, SDA_pin);
}
else
input(SDA_direction, SDA_pin);
}
void I2C_init() {
//
// initialize I2C lines
//
SDA_write(1);
SCL_write(1);
}
char I2C_master_write_byte(unsigned char byte) {
//
// master write I2C byte
//
unsigned char bit;
//
// loop over bits
//
for (bit = 0; bit < 8; ++bit) {
if ((byte & 0x80) == 0)
SDA_write(0);
else
SDA_write(1);
SCL_write(1);
I2C_delay();
SCL_write(0);
I2C_delay();
byte <<= 1;
}
//
// check for ACK
//
SDA_write(1);
SCL_write(1);
I2C_delay();
if (pin_test(SDA_pins, SDA_pin) != 0) {
//
// no ACK, return 1
//
return 1;
}
//
// yes ACK, return 0
//
SCL_write(0);
I2C_delay();
return 0;
}
char I2C_master_write(unsigned char* data, unsigned char nbytes, unsigned char slave_address) {
//
// I2C master write
//
unsigned char index, ret, slave_address_write;
//
// send start
//
SDA_write(0);
I2C_delay();
SCL_write(0);
I2C_delay();
//
// send slave address
//
slave_address_write = slave_address << 1;
if (I2C_master_write_byte(slave_address_write) != 0)
//
// no ACK, return 1
//
return 1;
//
// loop over bytes
//
for (index = 0; index < nbytes; ++index) {
ret = I2C_master_write_byte(data[index]);
if (ret != 0)
//
// no ACK, return 1
//
break;
//
// yes ACK, continue
//
}
//
// send stop
//
SCL_write(1);
I2C_delay();
SDA_write(1);
I2C_delay();
return ret;
}
void I2C_master_read_byte(unsigned char* data, unsigned char index, unsigned char nbytes) {
//
// master read I2C byte
//
unsigned char byte, bit;
SDA_write(1);
byte = 0;
//
// loop over bits
//
for (bit = 0; bit < 8; ++bit) {
SCL_write(1);
I2C_delay();
if (pin_test(SDA_pins, SDA_pin) != 0)
byte |= (1 << (7 - bit));
SCL_write(0);
I2C_delay();
}
data[index] = byte;
if (index < (nbytes - 1)) {
//
// not done, send ACK
//
SDA_write(0);
SCL_write(1);
I2C_delay();
SCL_write(0);
SDA_write(1);
I2C_delay();
}
else {
//
// done, send NACK
//
SDA_write(1);
SCL_write(1);
I2C_delay();
SCL_write(0);
I2C_delay();
}
}
char I2C_master_read(unsigned char* data, unsigned char nbytes, unsigned char slave_address) {
//
// I2C master read
//
unsigned char index, slave_address_read;
//
// send start
//
SDA_write(0);
I2C_delay();
SCL_write(0);
I2C_delay();
//
// send slave address
//
slave_address_read = (slave_address << 1) + 1;
if (I2C_master_write_byte(slave_address_read) == 1)
//
// no ACK, return 1
//
return 1;
//
// loop over bytes
//
for (index = 0; index < nbytes; ++index)
I2C_master_read_byte(data, index, nbytes);
//
// send stop
//
SCL_write(1);
I2C_delay();
SDA_write(1);
I2C_delay();
return 0;
}
I would still be interested in implementing a library that might be a bit more robust, so if you have any ideas, please let me know.