Skip to content
Snippets Groups Projects
Commit 983020f8 authored by da1l6's avatar da1l6
Browse files

common/i2c: Support 1 and 2 byte adresses.

commin/i2c: Support bitrate changes (this seems to be broken, needs debugging)
parent 66f28133
No related branches found
No related tags found
No related merge requests found
......@@ -9,9 +9,9 @@
#define I2C_MODE_WRITE 0
//SCL_Freq = F_CPU/(16+2(TWBR)*4**TWPS)
// #define I2C_BITRATE_REG 92 //20Mhz -> 100kHz I²C
// #define I2C_BITRATE_REG 17 //20Mhz -> 400kHz I²C
#define I2C_BITRATE_REG 2 //20Mhz -> 1MHz I²C
#define I2C_BITRATE_REG_100K 92 //20Mhz -> 100kHz I²C
#define I2C_BITRATE_REG_400K 17 //20Mhz -> 400kHz I²C
#define I2C_BITRATE_REG_1M 2 //20Mhz -> 1MHz I²C
#define I2C_PRESCALER 0
#define I2C_STATUS_MASK ((unsigned char)~I2C_PRESCALER) //only need to mask prescaler bits if they are actually present, instead of always masking 0xF8.
......
......@@ -3,11 +3,17 @@
#include <util/delay.h>
void i2c_master_init(void){
TWBR = I2C_BITRATE_REG; //set
TWBR = I2C_BITRATE_REG_100K; //set
TWSR = I2C_PRESCALER; //bitrate
TWCR = (1<<TWEN); //enable i2c
}
void i2c_master_set_speed(uint8_t bitrate){
// TWCR = 0; //enable i2c
// TWBR = bitrate;
// TWCR = (1<<TWEN); //enable i2c
}
void i2c_master_reset(void){ //TODO: Is this really the proper way to reset the i2c contoller?
TWCR = (1 << TWEN) | (1 << TWSTO);
TWCR = (1<<TWINT); //| (1<<TWEN);
......@@ -20,7 +26,7 @@ void i2c_master_reset(void){ //TODO: Is this really the proper way to reset the
/**
* Waits for the i2c interface to become ready for the next byte (TWINT is cleared)
*/
unsigned char i2c_master_wait_ready(void){
uint8_t i2c_master_wait_ready(void){
uint32_t c = 0;
while (!(TWCR & (1<<TWINT))) {
c++;
......@@ -38,7 +44,7 @@ void i2c_master_stop(void){
}
unsigned char i2c_master_start(unsigned char dest, unsigned char mode){
uint8_t i2c_master_start(uint8_t dest, uint8_t mode){
TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN); //send start signal
if (!i2c_master_wait_ready()) return I2C_ERROR_TIMEOUT+1; //wait until start signal has been sent.
if (((TWSR & I2C_STATUS_MASK) != TW_START) &&
......@@ -58,7 +64,7 @@ unsigned char i2c_master_start(unsigned char dest, unsigned char mode){
* @param b byte to send
* @param last if non-zero the byte is expected to be answered by a slave NACK, if zero an ACK is expected.
*/
unsigned char i2c_master_send_byte(unsigned char b){
uint8_t i2c_master_send_byte(uint8_t b){
TWDR = b;
TWCR = (1<<TWINT) | (1<<TWEN); //transmit
if (!i2c_master_wait_ready()) return I2C_ERROR_TIMEOUT; //wait until the byte has been sent.
......@@ -73,7 +79,7 @@ unsigned char i2c_master_send_byte(unsigned char b){
* @param memory address where to write the byte to.
* @param last if non-zero a NACK will be returned to the sender to signal the end of transmission.
**/
unsigned char i2c_master_read_byte(unsigned char* b, uint8_t last){
uint8_t i2c_master_read_byte(uint8_t* b, uint8_t last){
//set ACK/NACK Status //TODO: could this be too late?
TWCR = (1<<TWEN) | (1<<TWINT) | (last ? 0 : (1<<TWEA)); //TODO: Is it a good idea to fiddle with this REG before a read?
......@@ -100,8 +106,8 @@ unsigned char i2c_master_read_byte(unsigned char* b, uint8_t last){
* @param length number of bytes to transmit
* @param buffer pointer to the transmit buffer
*/
unsigned char i2c_master_write(unsigned char dest, unsigned int addr, unsigned char* buffer, unsigned char length){
unsigned char ret;
uint8_t i2c_master_write(uint8_t dest, uint16_t addr, uint8_t addr_size, uint8_t* buffer, uint8_t length){
uint8_t ret;
i2c_master_last_error_position = 0x01;
......@@ -110,15 +116,17 @@ unsigned char i2c_master_write(unsigned char dest, unsigned int addr, unsigned c
i2c_master_last_error_position = 0x02;
ret = i2c_master_send_byte(addr >> 8);
if (ret != I2C_SUCCESS) I2C_ERROR(ret); //sends stop and returns the error code
if (addr_size >= 2){
ret = i2c_master_send_byte(addr >> 8);
if (ret != I2C_SUCCESS) I2C_ERROR(ret); //sends stop and returns the error code
}
ret = i2c_master_send_byte(addr & 0xFF);
if (ret != I2C_SUCCESS) I2C_ERROR(ret); //sends stop and returns the error code
i2c_master_last_error_position = 0x03;
for (unsigned char i = 0; i < length; i++){
for (uint8_t i = 0; i < length; i++){
ret = i2c_master_send_byte(buffer[i]);
if (ret != I2C_SUCCESS) I2C_ERROR(ret); //sends stop and returns the error code
i2c_master_last_error_position = 0xD0+i;
......@@ -129,46 +137,6 @@ unsigned char i2c_master_write(unsigned char dest, unsigned int addr, unsigned c
return I2C_SUCCESS;
}
/**
* Writes length bytes to the target. The bytes are obtained by calling the source function for each byte.
* @param dest i2c address of the target host
* @param addr register address at the target host
* @param length number of bytes to transmit
* @param souzrce pointer to te function returning the bytes to send
*/
unsigned char i2c_master_write_cut_through(unsigned char dest, unsigned int addr, unsigned char (*source)(void), unsigned char length){
unsigned char ret;
i2c_master_last_error_position = 0x41;
ret = i2c_master_start(dest, I2C_MODE_WRITE); //send dest address and write mode
if (ret != I2C_SUCCESS) I2C_ERROR(ret); //sends stop and returns the error code
i2c_master_last_error_position = 0x42;
ret = i2c_master_send_byte(addr >> 8); //send register address (high)
if (ret != I2C_SUCCESS) I2C_ERROR(ret); //error
ret = i2c_master_send_byte(addr & 0xFF); //send register address (low)
if (ret != I2C_SUCCESS) I2C_ERROR(ret); //sends stop and returns the error code
i2c_master_last_error_position = 0x43;
for (unsigned char i = 0; i < length; i++){
unsigned char b = source();
ret = i2c_master_send_byte(b);
if (ret != I2C_SUCCESS) I2C_ERROR(ret); //sends stop and returns the error code
i2c_master_last_error_position = 0x50+i;
}
i2c_master_stop();
TWCR = (1<<TWINT);
return I2C_SUCCESS;
}
/**
* Reads bytes from the target into a buffer
* @param dest i2c address of the target host
......@@ -176,8 +144,8 @@ unsigned char i2c_master_write_cut_through(unsigned char dest, unsigned int addr
* @param length number of bytes to read
* @param buffer pointer to the receive buffer
*/
unsigned char i2c_master_read(unsigned char dest, unsigned int addr, unsigned char* buffer, unsigned char length){
unsigned int ret;
uint8_t i2c_master_read(uint8_t dest, uint16_t addr, uint8_t addr_size, uint8_t* buffer, uint8_t length){
uint16_t ret;
i2c_master_last_error_position = 0x81;
......@@ -186,8 +154,10 @@ unsigned char i2c_master_read(unsigned char dest, unsigned int addr, unsigned ch
i2c_master_last_error_position = 0x82;
ret = i2c_master_send_byte(addr >> 8); //send register address (high)
if (ret != I2C_SUCCESS) I2C_ERROR(ret); //error
if (addr_size >= 2){
ret = i2c_master_send_byte(addr >> 8); //send register address (high)
if (ret != I2C_SUCCESS) I2C_ERROR(ret); //error
}
ret = i2c_master_send_byte(addr & 0xFF); //send register address (low)
if (ret != I2C_SUCCESS) I2C_ERROR(ret); //sends stop and returns the error code
......@@ -207,7 +177,7 @@ unsigned char i2c_master_read(unsigned char dest, unsigned int addr, unsigned ch
i2c_master_last_error_position = 0x85;
for (unsigned char i = 0; i < length; i++){
for (uint8_t i = 0; i < length; i++){
ret = i2c_master_read_byte(&(buffer[i]), i+1 == length);
if (ret != I2C_SUCCESS) I2C_ERROR(ret); //sends stop and returns the error code
i2c_master_last_error_position = 0x86+i;
......
......@@ -18,39 +18,34 @@
#define I2C_ERROR(ret) {i2c_master_last_error_status = (TWSR & I2C_STATUS_MASK); i2c_master_last_error_control = TWCR; i2c_master_stop(); return (ret);}
unsigned char i2c_master_last_error_status;
unsigned char i2c_master_last_error_control;
unsigned char i2c_master_last_error_position;
uint8_t i2c_master_last_error_status;
uint8_t i2c_master_last_error_control;
uint8_t i2c_master_last_error_position;
void i2c_master_init(void);
void i2c_master_set_speed(uint8_t bitrate);
void i2c_master_reset(void);
/**
* Writes a buffer to a target
* @param dest i2c address of the target host
* @param addr register address at the target host
* @param addr_size size of the register address (1 or 2 byte)
* @param length number of bytes to transmit
* @param buffer pointer to the transmit buffer
*/
unsigned char i2c_master_write(unsigned char dest, unsigned int addr, unsigned char* buffer, unsigned char length);
/**
* Writes length bytes to the target. The bytes are obtained by calling the source function for each byte.
* @param dest i2c address of the target host
* @param addr register address at the target host
* @param length number of bytes to transmit
* @param souzrce pointer to te function returning the bytes to send
*/
unsigned char i2c_master_write_cut_through(unsigned char dest, unsigned int addr, unsigned char (*source)(void), unsigned char length);
uint8_t i2c_master_write(uint8_t dest, uint16_t addr, uint8_t addr_size, uint8_t* buffer, uint8_t length);
/**
* Reads bytes from the target into a buffer
* @param dest i2c address of the target host
* @param addr register address at the target host
* @param addr_size size of the register address (1 or 2 byte)
* @param length number of bytes to read
* @param buffer pointer to the receive buffer
*/
unsigned char i2c_master_read(unsigned char dest, unsigned int addr, unsigned char* buffer, unsigned char length);
uint8_t i2c_master_read(uint8_t dest, uint16_t addr, uint8_t addr_size, uint8_t* buffer, uint8_t length);
#endif
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment