diff options
author | Jack Humbert <jack.humb@gmail.com> | 2018-06-12 23:37:06 -0400 |
---|---|---|
committer | Jack Humbert <jack.humb@gmail.com> | 2018-06-12 23:37:06 -0400 |
commit | bad56a4f2b91fc8591f6d33a1710ea0050abcfbf (patch) | |
tree | ce6400e681028237464ac2f869249a17b00ab1e4 /drivers/avr/i2c_master.c | |
parent | b8564f5dd08f49ee0fc6d28957a376132bd7038d (diff) | |
download | qmk_firmware-bad56a4f2b91fc8591f6d33a1710ea0050abcfbf.tar.gz qmk_firmware-bad56a4f2b91fc8591f6d33a1710ea0050abcfbf.zip |
adds timeout to avr i2c
Diffstat (limited to 'drivers/avr/i2c_master.c')
-rwxr-xr-x | drivers/avr/i2c_master.c | 89 |
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 | ||
147 | void i2c_stop(void) | 200 | uint8_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 | } |