From 983020f84fd7eb567f7eb5378cbe4a86923d026f Mon Sep 17 00:00:00 2001 From: Philipp Claves <pclaves@web.de> Date: Sun, 6 Nov 2011 00:22:14 +0100 Subject: [PATCH] common/i2c: Support 1 and 2 byte adresses. commin/i2c: Support bitrate changes (this seems to be broken, needs debugging) --- common/i2c_common.h | 6 ++-- common/i2c_master.c | 80 ++++++++++++++------------------------------- common/i2c_master.h | 23 +++++-------- 3 files changed, 37 insertions(+), 72 deletions(-) diff --git a/common/i2c_common.h b/common/i2c_common.h index 1db1d90..ab7282b 100644 --- a/common/i2c_common.h +++ b/common/i2c_common.h @@ -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. diff --git a/common/i2c_master.c b/common/i2c_master.c index 64764c5..723a51b 100644 --- a/common/i2c_master.c +++ b/common/i2c_master.c @@ -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; diff --git a/common/i2c_master.h b/common/i2c_master.h index 96f6a6d..3020519 100644 --- a/common/i2c_master.h +++ b/common/i2c_master.h @@ -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 -- GitLab