|
@@ -0,0 +1,192 @@
|
|
|
+/*
|
|
|
+ * I2C.c
|
|
|
+ * k4be 2022
|
|
|
+ * License: BSD
|
|
|
+ */
|
|
|
+
|
|
|
+#include <avr/io.h>
|
|
|
+#include <util/delay.h>
|
|
|
+#include "I2C.h"
|
|
|
+#include "main.h"
|
|
|
+
|
|
|
+void I2C_init(void){
|
|
|
+ TWBR = 18;
|
|
|
+ TWSR |= 0;
|
|
|
+}
|
|
|
+
|
|
|
+/* two byte command (or command + value) */
|
|
|
+unsigned int I2C_SendCommand(unsigned char address, unsigned char command, unsigned char data_byte)
|
|
|
+{
|
|
|
+ unsigned int error = ERROR_I2C;
|
|
|
+ for(int index = 0 ; (index < MAX_REPEAT_I2C) && (error != ERROR_NO); index++)
|
|
|
+ {
|
|
|
+ error = 0;
|
|
|
+ TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN); // Send START condition
|
|
|
+ error |= I2C_WaitForTWInt();
|
|
|
+
|
|
|
+ error |= I2C_SendOneCommandByte(address << 1);
|
|
|
+ error |= I2C_SendOneCommandByte(command);
|
|
|
+ error |= I2C_SendOneCommandByte(data_byte);
|
|
|
+
|
|
|
+ TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
|
|
|
+ }
|
|
|
+
|
|
|
+ return error;
|
|
|
+}
|
|
|
+
|
|
|
+/* three byte command (or command + 2 values) */
|
|
|
+unsigned int I2C_SendCommand3byte(unsigned char address,unsigned char command,unsigned char data0, unsigned char data1)
|
|
|
+{
|
|
|
+ unsigned int error = ERROR_I2C;
|
|
|
+ for(int index = 0 ; (index < MAX_REPEAT_I2C) && (error != ERROR_NO); index++)
|
|
|
+ {
|
|
|
+ error = 0;
|
|
|
+ TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN); // Send START condition
|
|
|
+ error |= I2C_WaitForTWInt();
|
|
|
+
|
|
|
+ error |= I2C_SendOneCommandByte(address << 1);
|
|
|
+ error |= I2C_SendOneCommandByte(command);
|
|
|
+ error |= I2C_SendOneCommandByte(data0);
|
|
|
+ error |= I2C_SendOneCommandByte(data1);
|
|
|
+
|
|
|
+ TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
|
|
|
+ }
|
|
|
+
|
|
|
+ return error;
|
|
|
+}
|
|
|
+
|
|
|
+/* read single byte */
|
|
|
+unsigned int I2C_ReceiveCommand(unsigned char address, unsigned char command, unsigned char *data_byte)
|
|
|
+{
|
|
|
+ unsigned int error = ERROR_I2C;
|
|
|
+ unsigned char _unused;
|
|
|
+ for(int index = 0 ; (index < MAX_REPEAT_I2C) && (error != ERROR_NO); index++)
|
|
|
+ {
|
|
|
+ error = 0;
|
|
|
+ TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN); // Send START condition
|
|
|
+ error |= I2C_WaitForTWInt();
|
|
|
+
|
|
|
+ error |= I2C_SendOneCommandByte(address << 1);
|
|
|
+ error |= I2C_SendOneCommandByte(command);
|
|
|
+ error |= I2C_SendOneCommandByte((address << 1) | 1);
|
|
|
+
|
|
|
+ TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
|
|
|
+ error |= I2C_WaitForTWInt();
|
|
|
+
|
|
|
+ error |= I2C_ReceiveOneCommandByte(&_unused, 0);
|
|
|
+ error |= I2C_ReceiveOneCommandByte(data_byte, 0);
|
|
|
+
|
|
|
+ TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
|
|
|
+ }
|
|
|
+
|
|
|
+ return error;
|
|
|
+}
|
|
|
+
|
|
|
+/* send command + any byte count */
|
|
|
+unsigned int I2C_Send_n_bytes(unsigned char address,unsigned char command, const unsigned char *data, unsigned int length)
|
|
|
+{
|
|
|
+ unsigned int error = ERROR_I2C;
|
|
|
+ unsigned int i;
|
|
|
+
|
|
|
+ for(int index = 0 ; (index < MAX_REPEAT_I2C) && (error != ERROR_NO); index++)
|
|
|
+ {
|
|
|
+ error = 0;
|
|
|
+ TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN); // Send START condition
|
|
|
+ error |= I2C_WaitForTWInt();
|
|
|
+
|
|
|
+ error |= I2C_SendOneCommandByte(address << 1);
|
|
|
+ error |= I2C_SendOneCommandByte(command);
|
|
|
+ for(i=0;i<length;i++){
|
|
|
+ error |= I2C_SendOneCommandByte(data[i]);
|
|
|
+ }
|
|
|
+
|
|
|
+ TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
|
|
|
+ }
|
|
|
+
|
|
|
+ return error;
|
|
|
+}
|
|
|
+
|
|
|
+/* read any byte count */
|
|
|
+unsigned int I2C_Receive_n_bytes(unsigned char address, unsigned char command, unsigned char *data, unsigned int length)
|
|
|
+{
|
|
|
+ unsigned int i;
|
|
|
+ unsigned int error = ERROR_I2C;
|
|
|
+ for(int index = 0 ; (index < MAX_REPEAT_I2C) && (error != ERROR_NO); index++)
|
|
|
+ {
|
|
|
+ error = 0;
|
|
|
+ TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN); // Send START condition
|
|
|
+ error |= I2C_WaitForTWInt();
|
|
|
+
|
|
|
+ error |= I2C_SendOneCommandByte(address << 1);
|
|
|
+ error |= I2C_SendOneCommandByte(command);
|
|
|
+
|
|
|
+ TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
|
|
|
+ _delay_us(1);
|
|
|
+ TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
|
|
|
+ error |= I2C_WaitForTWInt();
|
|
|
+
|
|
|
+ error |= I2C_SendOneCommandByte((address << 1) | 1);
|
|
|
+
|
|
|
+ for(i=0; i<length; i++){
|
|
|
+ error |= I2C_ReceiveOneCommandByte(&data[i], i != length-1);
|
|
|
+ }
|
|
|
+
|
|
|
+ TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
|
|
|
+ }
|
|
|
+
|
|
|
+ return error;
|
|
|
+}
|
|
|
+
|
|
|
+/* read 2 bytes */
|
|
|
+unsigned int I2C_ReceiveCommand3byte(unsigned char address, unsigned char command, unsigned char *data0, unsigned char *data1)
|
|
|
+{
|
|
|
+ unsigned int error = ERROR_I2C;
|
|
|
+ unsigned char addressTrash;
|
|
|
+ for(int index = 0 ; (index < MAX_REPEAT_I2C) && (error != ERROR_NO); index++)
|
|
|
+ {
|
|
|
+ error = 0;
|
|
|
+ TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN);//Send START condition
|
|
|
+ error |= I2C_WaitForTWInt();
|
|
|
+
|
|
|
+ error |= I2C_SendOneCommandByte(address << 1);
|
|
|
+ error |= I2C_SendOneCommandByte(command);
|
|
|
+ error |= I2C_SendOneCommandByte((address << 1) | 1);
|
|
|
+
|
|
|
+ TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
|
|
|
+ error |= I2C_WaitForTWInt();
|
|
|
+
|
|
|
+ error |= I2C_ReceiveOneCommandByte(&addressTrash, 0);
|
|
|
+ error |= I2C_ReceiveOneCommandByte(data0, 0);
|
|
|
+ error |= I2C_ReceiveOneCommandByte(data1, 0);
|
|
|
+
|
|
|
+ TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
|
|
|
+ }
|
|
|
+
|
|
|
+ return error;
|
|
|
+}
|
|
|
+
|
|
|
+unsigned int I2C_SendOneCommandByte(unsigned char command)
|
|
|
+{
|
|
|
+ TWDR = command;
|
|
|
+ TWCR = (1<<TWINT) | (1<<TWEN);
|
|
|
+ return I2C_WaitForTWInt();
|
|
|
+}
|
|
|
+
|
|
|
+unsigned int I2C_ReceiveOneCommandByte(unsigned char *command, unsigned char ack)
|
|
|
+{
|
|
|
+ TWCR = (1<<TWINT) | (1<<TWEN) | (ack?_BV(TWEA):0);
|
|
|
+ unsigned int error = I2C_WaitForTWInt();
|
|
|
+ *command = TWDR;
|
|
|
+ return error;
|
|
|
+}
|
|
|
+
|
|
|
+unsigned int I2C_WaitForTWInt(void){
|
|
|
+ unsigned char count = 20;
|
|
|
+ while (count && !(TWCR & (1<<TWINT))){
|
|
|
+ count--;
|
|
|
+ _delay_us(10);
|
|
|
+ }
|
|
|
+ if(count == 0) return ERROR_I2C_TIMEOUT;
|
|
|
+
|
|
|
+ return ERROR_NO;
|
|
|
+}
|