aboutsummaryrefslogtreecommitdiff
path: root/drivers/avr
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/avr')
-rwxr-xr-xdrivers/avr/i2c_master.c160
-rwxr-xr-xdrivers/avr/i2c_master.h2
-rwxr-xr-xdrivers/avr/i2c_slave.c2
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
17void i2c_init(void) 18void 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
23i2c_status_t i2c_start(uint8_t address, uint16_t timeout) 23i2c_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
59i2c_status_t i2c_write(uint8_t data, uint16_t timeout) 62i2c_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
78int16_t i2c_read_ack(uint16_t timeout) 82int16_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
95int16_t i2c_read_nack(uint16_t timeout) 97int16_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
112i2c_status_t i2c_transmit(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout) 112i2c_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
128i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout) 124i2c_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
155i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout) 146i2c_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
174i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout) 161i2c_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); 188error:
205 if (status) return status; 189 i2c_stop();
206 190
207 return I2C_STATUS_SUCCESS; 191 return status;
208} 192}
209 193
210i2c_status_t i2c_stop(uint16_t timeout) 194void 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
26i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout); 26i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout);
27i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout); 27i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);
28i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout); 28i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);
29i2c_status_t i2c_stop(uint16_t timeout); 29void 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
17void i2c_slave_init(uint8_t address){ 17void 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}