aboutsummaryrefslogtreecommitdiff
path: root/drivers/avr/i2c_master.c
diff options
context:
space:
mode:
authorJack Humbert <jack.humb@gmail.com>2018-06-12 23:37:06 -0400
committerJack Humbert <jack.humb@gmail.com>2018-06-12 23:37:06 -0400
commitbad56a4f2b91fc8591f6d33a1710ea0050abcfbf (patch)
treece6400e681028237464ac2f869249a17b00ab1e4 /drivers/avr/i2c_master.c
parentb8564f5dd08f49ee0fc6d28957a376132bd7038d (diff)
downloadqmk_firmware-bad56a4f2b91fc8591f6d33a1710ea0050abcfbf.tar.gz
qmk_firmware-bad56a4f2b91fc8591f6d33a1710ea0050abcfbf.zip
adds timeout to avr i2c
Diffstat (limited to 'drivers/avr/i2c_master.c')
-rwxr-xr-xdrivers/avr/i2c_master.c89
1 files changed, 77 insertions, 12 deletions
diff --git a/drivers/avr/i2c_master.c b/drivers/avr/i2c_master.c
index cd3c2e1c8..97f690043 100755
--- a/drivers/avr/i2c_master.c
+++ b/drivers/avr/i2c_master.c
@@ -6,6 +6,7 @@
6#include <util/twi.h> 6#include <util/twi.h>
7 7
8#include "i2c_master.h" 8#include "i2c_master.h"
9#include "timer.h"
9 10
10#define F_SCL 400000UL // SCL frequency 11#define F_SCL 400000UL // SCL frequency
11#define Prescaler 1 12#define Prescaler 1
@@ -24,8 +25,18 @@ uint8_t i2c_start(uint8_t address)
24 TWCR = 0; 25 TWCR = 0;
25 // transmit START condition 26 // transmit START condition
26 TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN); 27 TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
27 // wait for end of transmission 28
28 while( !(TWCR & (1<<TWINT)) ); 29 #ifdef I2C_TIMEOUT
30 uint16_t timeout_timer = timer_read();
31 while( !(TWCR & (1<<TWINT)) ) {
32 if ((timer_read() - timeout_timer) > I2C_TIMEOUT) {
33 return 2; // should make these codes standard
34 }
35 }
36 #else
37 // wait for end of transmission
38 while( !(TWCR & (1<<TWINT)) );
39 #endif
29 40
30 // check if the start condition was successfully transmitted 41 // check if the start condition was successfully transmitted
31 if(((TW_STATUS & 0xF8) != TW_START) && ((TW_STATUS & 0xF8) != TW_REP_START)){ return 1; } 42 if(((TW_STATUS & 0xF8) != TW_START) && ((TW_STATUS & 0xF8) != TW_REP_START)){ return 1; }
@@ -34,8 +45,18 @@ uint8_t i2c_start(uint8_t address)
34 TWDR = address; 45 TWDR = address;
35 // start transmission of address 46 // start transmission of address
36 TWCR = (1<<TWINT) | (1<<TWEN); 47 TWCR = (1<<TWINT) | (1<<TWEN);
37 // wait for end of transmission 48
38 while( !(TWCR & (1<<TWINT)) ); 49 #ifdef I2C_TIMEOUT
50 timeout_timer = timer_read();
51 while( !(TWCR & (1<<TWINT)) ) {
52 if ((timer_read() - timeout_timer) > I2C_TIMEOUT) {
53 return 2; // should make these codes standard
54 }
55 }
56 #else
57 // wait for end of transmission
58 while( !(TWCR & (1<<TWINT)) );
59 #endif
39 60
40 // check if the device has acknowledged the READ / WRITE mode 61 // check if the device has acknowledged the READ / WRITE mode
41 uint8_t twst = TW_STATUS & 0xF8; 62 uint8_t twst = TW_STATUS & 0xF8;
@@ -50,8 +71,18 @@ uint8_t i2c_write(uint8_t data)
50 TWDR = data; 71 TWDR = data;
51 // start transmission of data 72 // start transmission of data
52 TWCR = (1<<TWINT) | (1<<TWEN); 73 TWCR = (1<<TWINT) | (1<<TWEN);
74
75 #ifdef I2C_TIMEOUT
76 uint16_t timeout_timer = timer_read();
77 while( !(TWCR & (1<<TWINT)) ) {
78 if ((timer_read() - timeout_timer) > I2C_TIMEOUT) {
79 return 2; // should make these codes standard
80 }
81 }
82 #else
53 // wait for end of transmission 83 // wait for end of transmission
54 while( !(TWCR & (1<<TWINT)) ); 84 while( !(TWCR & (1<<TWINT)) );
85 #endif
55 86
56 if( (TW_STATUS & 0xF8) != TW_MT_DATA_ACK ){ return 1; } 87 if( (TW_STATUS & 0xF8) != TW_MT_DATA_ACK ){ return 1; }
57 88
@@ -63,8 +94,19 @@ uint8_t i2c_read_ack(void)
63 94
64 // start TWI module and acknowledge data after reception 95 // start TWI module and acknowledge data after reception
65 TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA); 96 TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA);
66 // wait for end of transmission 97
67 while( !(TWCR & (1<<TWINT)) ); 98 #ifdef I2C_TIMEOUT
99 uint16_t timeout_timer = timer_read();
100 while( !(TWCR & (1<<TWINT)) ) {
101 if ((timer_read() - timeout_timer) > I2C_TIMEOUT) {
102 return 2; // should make these codes standard
103 }
104 }
105 #else
106 // wait for end of transmission
107 while( !(TWCR & (1<<TWINT)) );
108 #endif
109
68 // return received data from TWDR 110 // return received data from TWDR
69 return TWDR; 111 return TWDR;
70} 112}
@@ -74,8 +116,19 @@ uint8_t i2c_read_nack(void)
74 116
75 // start receiving without acknowledging reception 117 // start receiving without acknowledging reception
76 TWCR = (1<<TWINT) | (1<<TWEN); 118 TWCR = (1<<TWINT) | (1<<TWEN);
77 // wait for end of transmission 119
78 while( !(TWCR & (1<<TWINT)) ); 120 #ifdef I2C_TIMEOUT
121 uint16_t timeout_timer = timer_read();
122 while( !(TWCR & (1<<TWINT)) ) {
123 if ((timer_read() - timeout_timer) > I2C_TIMEOUT) {
124 return 2; // should make these codes standard
125 }
126 }
127 #else
128 // wait for end of transmission
129 while( !(TWCR & (1<<TWINT)) );
130 #endif
131
79 // return received data from TWDR 132 // return received data from TWDR
80 return TWDR; 133 return TWDR;
81} 134}
@@ -144,10 +197,22 @@ uint8_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t le
144 return 0; 197 return 0;
145} 198}
146 199
147void i2c_stop(void) 200uint8_t i2c_stop(void)
148{ 201{
149 // transmit STOP condition 202 // transmit STOP condition
150 TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO); 203 TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
151 // wait until stop condition is executed and bus released 204
152 while(TWCR & (1<<TWSTO)); 205 #ifdef I2C_TIMEOUT
206 uint16_t timeout_timer = timer_read();
207 while(TWCR & (1<<TWSTO)) {
208 if ((timer_read() - timeout_timer) > I2C_TIMEOUT) {
209 return 2; // should make these codes standard
210 }
211 }
212 #else
213 // wait for end of transmission
214 while(TWCR & (1<<TWSTO));
215 #endif
216
217 return 0;
153} 218}