diff options
Diffstat (limited to 'drivers/avr')
-rwxr-xr-x | drivers/avr/i2c_master.c | 160 | ||||
-rwxr-xr-x | drivers/avr/i2c_master.h | 2 | ||||
-rwxr-xr-x | drivers/avr/i2c_slave.c | 2 |
3 files changed, 69 insertions, 95 deletions
diff --git a/drivers/avr/i2c_master.c b/drivers/avr/i2c_master.c index 19bae33e9..d97a35cd6 100755 --- a/drivers/avr/i2c_master.c +++ b/drivers/avr/i2c_master.c | |||
@@ -7,43 +7,44 @@ | |||
7 | 7 | ||
8 | #include "i2c_master.h" | 8 | #include "i2c_master.h" |
9 | #include "timer.h" | 9 | #include "timer.h" |
10 | #include "wait.h" | ||
10 | 11 | ||
11 | #ifndef F_SCL | 12 | #ifndef F_SCL |
12 | #define F_SCL 400000UL // SCL frequency | 13 | # define F_SCL 400000UL // SCL frequency |
13 | #endif | 14 | #endif |
14 | #define Prescaler 1 | 15 | #define Prescaler 1 |
15 | #define TWBR_val ((((F_CPU / F_SCL) / Prescaler) - 16 ) / 2) | 16 | #define TWBR_val ((((F_CPU / F_SCL) / Prescaler) - 16) / 2) |
16 | 17 | ||
17 | void i2c_init(void) | 18 | void i2c_init(void) { |
18 | { | 19 | TWSR = 0; /* no prescaler */ |
19 | TWSR = 0; /* no prescaler */ | ||
20 | TWBR = (uint8_t)TWBR_val; | 20 | TWBR = (uint8_t)TWBR_val; |
21 | } | 21 | } |
22 | 22 | ||
23 | i2c_status_t i2c_start(uint8_t address, uint16_t timeout) | 23 | i2c_status_t i2c_start(uint8_t address, uint16_t timeout) { |
24 | { | ||
25 | // reset TWI control register | 24 | // reset TWI control register |
26 | TWCR = 0; | 25 | TWCR = 0; |
27 | // transmit START condition | 26 | // transmit START condition |
28 | TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN); | 27 | TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN); |
29 | 28 | ||
30 | uint16_t timeout_timer = timer_read(); | 29 | uint16_t timeout_timer = timer_read(); |
31 | while( !(TWCR & (1<<TWINT)) ) { | 30 | while (!(TWCR & (1 << TWINT))) { |
32 | if ((timeout != I2C_TIMEOUT_INFINITE) && ((timer_read() - timeout_timer) >= timeout)) { | 31 | if ((timeout != I2C_TIMEOUT_INFINITE) && ((timer_read() - timeout_timer) >= timeout)) { |
33 | return I2C_STATUS_TIMEOUT; | 32 | return I2C_STATUS_TIMEOUT; |
34 | } | 33 | } |
35 | } | 34 | } |
36 | 35 | ||
37 | // check if the start condition was successfully transmitted | 36 | // check if the start condition was successfully transmitted |
38 | if(((TW_STATUS & 0xF8) != TW_START) && ((TW_STATUS & 0xF8) != TW_REP_START)){ return I2C_STATUS_ERROR; } | 37 | if (((TW_STATUS & 0xF8) != TW_START) && ((TW_STATUS & 0xF8) != TW_REP_START)) { |
38 | return I2C_STATUS_ERROR; | ||
39 | } | ||
39 | 40 | ||
40 | // load slave address into data register | 41 | // load slave address into data register |
41 | TWDR = address; | 42 | TWDR = address; |
42 | // start transmission of address | 43 | // start transmission of address |
43 | TWCR = (1<<TWINT) | (1<<TWEN); | 44 | TWCR = (1 << TWINT) | (1 << TWEN); |
44 | 45 | ||
45 | timeout_timer = timer_read(); | 46 | timeout_timer = timer_read(); |
46 | while( !(TWCR & (1<<TWINT)) ) { | 47 | while (!(TWCR & (1 << TWINT))) { |
47 | if ((timeout != I2C_TIMEOUT_INFINITE) && ((timer_read() - timeout_timer) >= timeout)) { | 48 | if ((timeout != I2C_TIMEOUT_INFINITE) && ((timer_read() - timeout_timer) >= timeout)) { |
48 | return I2C_STATUS_TIMEOUT; | 49 | return I2C_STATUS_TIMEOUT; |
49 | } | 50 | } |
@@ -51,38 +52,39 @@ i2c_status_t i2c_start(uint8_t address, uint16_t timeout) | |||
51 | 52 | ||
52 | // check if the device has acknowledged the READ / WRITE mode | 53 | // check if the device has acknowledged the READ / WRITE mode |
53 | uint8_t twst = TW_STATUS & 0xF8; | 54 | uint8_t twst = TW_STATUS & 0xF8; |
54 | if ( (twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK) ) return I2C_STATUS_ERROR; | 55 | if ((twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK)) { |
56 | return I2C_STATUS_ERROR; | ||
57 | } | ||
55 | 58 | ||
56 | return I2C_STATUS_SUCCESS; | 59 | return I2C_STATUS_SUCCESS; |
57 | } | 60 | } |
58 | 61 | ||
59 | i2c_status_t i2c_write(uint8_t data, uint16_t timeout) | 62 | i2c_status_t i2c_write(uint8_t data, uint16_t timeout) { |
60 | { | ||
61 | // load data into data register | 63 | // load data into data register |
62 | TWDR = data; | 64 | TWDR = data; |
63 | // start transmission of data | 65 | // start transmission of data |
64 | TWCR = (1<<TWINT) | (1<<TWEN); | 66 | TWCR = (1 << TWINT) | (1 << TWEN); |
65 | 67 | ||
66 | uint16_t timeout_timer = timer_read(); | 68 | uint16_t timeout_timer = timer_read(); |
67 | while( !(TWCR & (1<<TWINT)) ) { | 69 | while (!(TWCR & (1 << TWINT))) { |
68 | if ((timeout != I2C_TIMEOUT_INFINITE) && ((timer_read() - timeout_timer) >= timeout)) { | 70 | if ((timeout != I2C_TIMEOUT_INFINITE) && ((timer_read() - timeout_timer) >= timeout)) { |
69 | return I2C_STATUS_TIMEOUT; | 71 | return I2C_STATUS_TIMEOUT; |
70 | } | 72 | } |
71 | } | 73 | } |
72 | 74 | ||
73 | if( (TW_STATUS & 0xF8) != TW_MT_DATA_ACK ){ return I2C_STATUS_ERROR; } | 75 | if ((TW_STATUS & 0xF8) != TW_MT_DATA_ACK) { |
76 | return I2C_STATUS_ERROR; | ||
77 | } | ||
74 | 78 | ||
75 | return I2C_STATUS_SUCCESS; | 79 | return I2C_STATUS_SUCCESS; |
76 | } | 80 | } |
77 | 81 | ||
78 | int16_t i2c_read_ack(uint16_t timeout) | 82 | int16_t i2c_read_ack(uint16_t timeout) { |
79 | { | ||
80 | |||
81 | // start TWI module and acknowledge data after reception | 83 | // start TWI module and acknowledge data after reception |
82 | TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA); | 84 | TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWEA); |
83 | 85 | ||
84 | uint16_t timeout_timer = timer_read(); | 86 | uint16_t timeout_timer = timer_read(); |
85 | while( !(TWCR & (1<<TWINT)) ) { | 87 | while (!(TWCR & (1 << TWINT))) { |
86 | if ((timeout != I2C_TIMEOUT_INFINITE) && ((timer_read() - timeout_timer) >= timeout)) { | 88 | if ((timeout != I2C_TIMEOUT_INFINITE) && ((timer_read() - timeout_timer) >= timeout)) { |
87 | return I2C_STATUS_TIMEOUT; | 89 | return I2C_STATUS_TIMEOUT; |
88 | } | 90 | } |
@@ -92,14 +94,12 @@ int16_t i2c_read_ack(uint16_t timeout) | |||
92 | return TWDR; | 94 | return TWDR; |
93 | } | 95 | } |
94 | 96 | ||
95 | int16_t i2c_read_nack(uint16_t timeout) | 97 | int16_t i2c_read_nack(uint16_t timeout) { |
96 | { | ||
97 | |||
98 | // start receiving without acknowledging reception | 98 | // start receiving without acknowledging reception |
99 | TWCR = (1<<TWINT) | (1<<TWEN); | 99 | TWCR = (1 << TWINT) | (1 << TWEN); |
100 | 100 | ||
101 | uint16_t timeout_timer = timer_read(); | 101 | uint16_t timeout_timer = timer_read(); |
102 | while( !(TWCR & (1<<TWINT)) ) { | 102 | while (!(TWCR & (1 << TWINT))) { |
103 | if ((timeout != I2C_TIMEOUT_INFINITE) && ((timer_read() - timeout_timer) >= timeout)) { | 103 | if ((timeout != I2C_TIMEOUT_INFINITE) && ((timer_read() - timeout_timer) >= timeout)) { |
104 | return I2C_STATUS_TIMEOUT; | 104 | return I2C_STATUS_TIMEOUT; |
105 | } | 105 | } |
@@ -109,115 +109,89 @@ int16_t i2c_read_nack(uint16_t timeout) | |||
109 | return TWDR; | 109 | return TWDR; |
110 | } | 110 | } |
111 | 111 | ||
112 | i2c_status_t i2c_transmit(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout) | 112 | i2c_status_t i2c_transmit(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout) { |
113 | { | ||
114 | i2c_status_t status = i2c_start(address | I2C_WRITE, timeout); | 113 | i2c_status_t status = i2c_start(address | I2C_WRITE, timeout); |
115 | if (status) return status; | ||
116 | 114 | ||
117 | for (uint16_t i = 0; i < length; i++) { | 115 | for (uint16_t i = 0; i < length && status >= 0; i++) { |
118 | status = i2c_write(data[i], timeout); | 116 | status = i2c_write(data[i], timeout); |
119 | if (status) return status; | ||
120 | } | 117 | } |
121 | 118 | ||
122 | status = i2c_stop(timeout); | 119 | i2c_stop(); |
123 | if (status) return status; | ||
124 | 120 | ||
125 | return I2C_STATUS_SUCCESS; | 121 | return status; |
126 | } | 122 | } |
127 | 123 | ||
128 | i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout) | 124 | i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout) { |
129 | { | ||
130 | i2c_status_t status = i2c_start(address | I2C_READ, timeout); | 125 | i2c_status_t status = i2c_start(address | I2C_READ, timeout); |
131 | if (status) return status; | ||
132 | 126 | ||
133 | for (uint16_t i = 0; i < (length-1); i++) { | 127 | for (uint16_t i = 0; i < (length - 1) && status >= 0; i++) { |
134 | status = i2c_read_ack(timeout); | 128 | status = i2c_read_ack(timeout); |
135 | if (status >= 0) { | 129 | if (status >= 0) { |
136 | data[i] = status; | 130 | data[i] = status; |
137 | } else { | ||
138 | return status; | ||
139 | } | 131 | } |
140 | } | 132 | } |
141 | 133 | ||
142 | status = i2c_read_nack(timeout); | 134 | if (status >= 0) { |
143 | if (status >= 0 ) { | 135 | status = i2c_read_nack(timeout); |
144 | data[(length-1)] = status; | 136 | if (status >= 0) { |
145 | } else { | 137 | data[(length - 1)] = status; |
146 | return status; | 138 | } |
147 | } | 139 | } |
148 | 140 | ||
149 | status = i2c_stop(timeout); | 141 | i2c_stop(); |
150 | if (status) return status; | ||
151 | 142 | ||
152 | return I2C_STATUS_SUCCESS; | 143 | return status; |
153 | } | 144 | } |
154 | 145 | ||
155 | i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout) | 146 | i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout) { |
156 | { | ||
157 | i2c_status_t status = i2c_start(devaddr | 0x00, timeout); | 147 | i2c_status_t status = i2c_start(devaddr | 0x00, timeout); |
158 | if (status) return status; | 148 | if (status >= 0) { |
159 | 149 | status = i2c_write(regaddr, timeout); | |
160 | status = i2c_write(regaddr, timeout); | ||
161 | if (status) return status; | ||
162 | 150 | ||
163 | for (uint16_t i = 0; i < length; i++) { | 151 | for (uint16_t i = 0; i < length && status >= 0; i++) { |
164 | status = i2c_write(data[i], timeout); | 152 | status = i2c_write(data[i], timeout); |
165 | if (status) return status; | 153 | } |
166 | } | 154 | } |
167 | 155 | ||
168 | status = i2c_stop(timeout); | 156 | i2c_stop(); |
169 | if (status) return status; | ||
170 | 157 | ||
171 | return I2C_STATUS_SUCCESS; | 158 | return status; |
172 | } | 159 | } |
173 | 160 | ||
174 | i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout) | 161 | i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout) { |
175 | { | ||
176 | i2c_status_t status = i2c_start(devaddr, timeout); | 162 | i2c_status_t status = i2c_start(devaddr, timeout); |
177 | if (status) return status; | 163 | if (status < 0) { |
164 | goto error; | ||
165 | } | ||
178 | 166 | ||
179 | status = i2c_write(regaddr, timeout); | 167 | status = i2c_write(regaddr, timeout); |
180 | if (status) return status; | 168 | if (status < 0) { |
181 | 169 | goto error; | |
182 | status = i2c_stop(timeout); | 170 | } |
183 | if (status) return status; | ||
184 | 171 | ||
185 | status = i2c_start(devaddr | 0x01, timeout); | 172 | status = i2c_start(devaddr | 0x01, timeout); |
186 | if (status) return status; | ||
187 | 173 | ||
188 | for (uint16_t i = 0; i < (length-1); i++) { | 174 | for (uint16_t i = 0; i < (length - 1) && status >= 0; i++) { |
189 | status = i2c_read_ack(timeout); | 175 | status = i2c_read_ack(timeout); |
190 | if (status >= 0) { | 176 | if (status >= 0) { |
191 | data[i] = status; | 177 | data[i] = status; |
192 | } else { | ||
193 | return status; | ||
194 | } | 178 | } |
195 | } | 179 | } |
196 | 180 | ||
197 | status = i2c_read_nack(timeout); | 181 | if (status >= 0) { |
198 | if (status >= 0 ) { | 182 | status = i2c_read_nack(timeout); |
199 | data[(length-1)] = status; | 183 | if (status >= 0) { |
200 | } else { | 184 | data[(length - 1)] = status; |
201 | return status; | 185 | } |
202 | } | 186 | } |
203 | 187 | ||
204 | status = i2c_stop(timeout); | 188 | error: |
205 | if (status) return status; | 189 | i2c_stop(); |
206 | 190 | ||
207 | return I2C_STATUS_SUCCESS; | 191 | return status; |
208 | } | 192 | } |
209 | 193 | ||
210 | i2c_status_t i2c_stop(uint16_t timeout) | 194 | void i2c_stop(void) { |
211 | { | ||
212 | // transmit STOP condition | 195 | // transmit STOP condition |
213 | TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO); | 196 | TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO); |
214 | |||
215 | uint16_t timeout_timer = timer_read(); | ||
216 | while(TWCR & (1<<TWSTO)) { | ||
217 | if ((timeout != I2C_TIMEOUT_INFINITE) && ((timer_read() - timeout_timer) >= timeout)) { | ||
218 | return I2C_STATUS_TIMEOUT; | ||
219 | } | ||
220 | } | ||
221 | |||
222 | return I2C_STATUS_SUCCESS; | ||
223 | } | 197 | } |
diff --git a/drivers/avr/i2c_master.h b/drivers/avr/i2c_master.h index 89c64599c..81a7fb5e3 100755 --- a/drivers/avr/i2c_master.h +++ b/drivers/avr/i2c_master.h | |||
@@ -26,6 +26,6 @@ i2c_status_t i2c_transmit(uint8_t address, uint8_t* data, uint16_t length, uint1 | |||
26 | i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout); | 26 | i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout); |
27 | i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout); | 27 | i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout); |
28 | i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout); | 28 | i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout); |
29 | i2c_status_t i2c_stop(uint16_t timeout); | 29 | void i2c_stop(void); |
30 | 30 | ||
31 | #endif // I2C_MASTER_H \ No newline at end of file | 31 | #endif // I2C_MASTER_H \ No newline at end of file |
diff --git a/drivers/avr/i2c_slave.c b/drivers/avr/i2c_slave.c index 18a29a45a..dbb9fb0df 100755 --- a/drivers/avr/i2c_slave.c +++ b/drivers/avr/i2c_slave.c | |||
@@ -16,7 +16,7 @@ static volatile bool slave_has_register_set = false; | |||
16 | 16 | ||
17 | void i2c_slave_init(uint8_t address){ | 17 | void i2c_slave_init(uint8_t address){ |
18 | // load address into TWI address register | 18 | // load address into TWI address register |
19 | TWAR = (address << 1); | 19 | TWAR = address; |
20 | // set the TWCR to enable address matching and enable TWI, clear TWINT, enable TWI interrupt | 20 | // set the TWCR to enable address matching and enable TWI, clear TWINT, enable TWI interrupt |
21 | TWCR = (1 << TWIE) | (1 << TWEA) | (1 << TWINT) | (1 << TWEN); | 21 | TWCR = (1 << TWIE) | (1 << TWEA) | (1 << TWINT) | (1 << TWEN); |
22 | } | 22 | } |