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