home-automation/hardware/arduino/Plant_Monitor/extern/lipo_fuelgauge-v10/i2c.h

175 lines
4.6 KiB
C

// This library provides the high-level functions needed to use the I2C
// serial interface supported by the hardware of several AVR processors.
#include <avr/io.h>
#include <avr/interrupt.h>
#include "types.h"
#include "defs.h"
// TWSR values (not bits)
// (taken from avr-libc twi.h - thank you Marek Michalkiewicz)
// Master
#define TW_START 0x08
#define TW_REP_START 0x10
// Master Transmitter
#define TW_MT_SLA_ACK 0x18
#define TW_MT_SLA_NACK 0x20
#define TW_MT_DATA_ACK 0x28
#define TW_MT_DATA_NACK 0x30
#define TW_MT_ARB_LOST 0x38
// Master Receiver
#define TW_MR_ARB_LOST 0x38
#define TW_MR_SLA_ACK 0x40
#define TW_MR_SLA_NACK 0x48
#define TW_MR_DATA_ACK 0x50
#define TW_MR_DATA_NACK 0x58
// Slave Transmitter
#define TW_ST_SLA_ACK 0xA8
#define TW_ST_ARB_LOST_SLA_ACK 0xB0
#define TW_ST_DATA_ACK 0xB8
#define TW_ST_DATA_NACK 0xC0
#define TW_ST_LAST_DATA 0xC8
// Slave Receiver
#define TW_SR_SLA_ACK 0x60
#define TW_SR_ARB_LOST_SLA_ACK 0x68
#define TW_SR_GCALL_ACK 0x70
#define TW_SR_ARB_LOST_GCALL_ACK 0x78
#define TW_SR_DATA_ACK 0x80
#define TW_SR_DATA_NACK 0x88
#define TW_SR_GCALL_DATA_ACK 0x90
#define TW_SR_GCALL_DATA_NACK 0x98
#define TW_SR_STOP 0xA0
// Misc
#define TW_NO_INFO 0xF8
#define TW_BUS_ERROR 0x00
// defines and constants
#define TWCR_CMD_MASK 0x0F
#define TWSR_STATUS_MASK 0xF8
// return values
#define I2C_OK 0x00
#define I2C_ERROR_NODEV 0x01
#define WRITE_sda() DDRC = DDRC | 0b00010000 //SDA must be output when writing
#define READ_sda() DDRC = DDRC & 0b11101111 //SDA must be input when reading - don't forget the resistor on SDA!!
#define sbi(var, mask) ((var) |= (uint8_t)(1 << mask))
#define cbi(var, mask) ((var) &= (uint8_t)~(1 << mask))
// functions
//! Initialize I2C (TWI) interface
void i2cInit(void);
//! Set the I2C transaction bitrate (in KHz)
void i2cSetBitrate(unsigned short bitrateKHz);
// Low-level I2C transaction commands
//! Send an I2C start condition in Master mode
void i2cSendStart(void);
//! Send an I2C stop condition in Master mode
void i2cSendStop(void);
//! Wait for current I2C operation to complete
void i2cWaitForComplete(void);
//! Send an (address|R/W) combination or a data byte over I2C
void i2cSendByte(unsigned char data);
//! Receive a data byte over I2C
// ackFlag = TRUE if recevied data should be ACK'ed
// ackFlag = FALSE if recevied data should be NACK'ed
void i2cReceiveByte(unsigned char ackFlag);
//! Pick up the data that was received with i2cReceiveByte()
unsigned char i2cGetReceivedByte(void);
//! Get current I2c bus status from TWSR
unsigned char i2cGetStatus(void);
// high-level I2C transaction commands
//! send I2C data to a device on the bus (non-interrupt based)
unsigned char i2cMasterSendNI(unsigned char deviceAddr, unsigned char length, unsigned char* data);
//! receive I2C data from a device on the bus (non-interrupt based)
unsigned char i2cMasterReceiveNI(unsigned char deviceAddr, unsigned char length, unsigned char *data);
/*********************
****I2C Functions****
*********************/
void i2cInit(void)
{
// set i2c bit rate to 40KHz
i2cSetBitrate(100);
// enable TWI (two-wire interface)
sbi(TWCR, TWEN);
}
void i2cSetBitrate(unsigned short bitrateKHz)
{
unsigned char bitrate_div;
cbi(TWSR, TWPS0);
cbi(TWSR, TWPS1);
// calculate bitrate division
bitrate_div = ((F_CPU/4000l)/bitrateKHz);
if(bitrate_div >= 16)
bitrate_div = (bitrate_div-16)/2;
outb(TWBR, bitrate_div);
}
void i2cSendStart(void)
{
WRITE_sda();
// send start condition
TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
}
void i2cSendStop(void)
{
// transmit stop condition
TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
}
void i2cWaitForComplete(void)
{
int i = 0; //time out variable
// wait for i2c interface to complete operation
while ((!(TWCR & (1<<TWINT))) && (i < 90))
i++;
}
void i2cSendByte(unsigned char data)
{
WRITE_sda();
// save data to the TWDR
TWDR = data;
// begin send
TWCR = (1<<TWINT)|(1<<TWEN);
}
void i2cReceiveByte(unsigned char ackFlag)
{
// begin receive over i2c
if( ackFlag )
{
// ackFlag = TRUE: ACK the recevied data
outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA));
}
else
{
// ackFlag = FALSE: NACK the recevied data
outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT));
}
}
unsigned char i2cGetReceivedByte(void)
{
// retieve received data byte from i2c TWDR
return( inb(TWDR) );
}
unsigned char i2cGetStatus(void)
{
// retieve current i2c status from i2c TWSR
return( inb(TWSR) );
}