-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathi2c.c
227 lines (173 loc) · 6.07 KB
/
i2c.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
/*
Title: i2c.c
Authors: Mikael Ferland, Joël Brisson
Date: 12/11/2015
Purpose: Initialysation, writing and reading for TWI between master and slaves, using i2c protocol.
Software: AVR-GCC to compile
Hardware: ATMega32 on STK500 board
Note: 0xFE and 0xFF is reserved by the system for restart and stop condition.
*/
#include "i2c.h"
u08 buffer; //Store value temporary to execute decision base on value
u08 *buffer_ptr; //Address of the "buffer" variable
// Two Wire Interface initialisation and write starting parameter to Ping Sensor
void TWIInit()
{
/*Set TWPS and TWS to 0 in the TWSR register
TWPS is the Prescaler of TWI
TWBR is the value of the TWI Bit Rate Register
Use the following formula to calculate an SCL frequency of 10kHz
SCL frequency = (CPU Clock)/(16+(TWBR)*4^(TWPS))
*/
//TWSR = (bits 7..3) TWS and (bits 1..0) TWPS
//Set prescaler to 1, clear all TWI Status
TWSR = 0;
//TWBR = TWI Bit Rate
//Set bit rate to 0xC6
TWBR = 0xC6;
//TWCR = TWI Control Register
//Clear Interrupt Flag, Enable TWI Interrupt, Enable TWI Acknowledge Bit, Enable TWI
TWCR = (1<<TWEN) | (1<<TWEA) | (1<<TWIE);
//Set some initial value to both ping sensor
twiWrite(0xE0, 0x02, 0x5A);
putDataOutBuf(0xFE); //Send restart
twiWrite(0xE2, 0x02, 0x5A);
putDataOutBuf(0xFE);
twiWrite(0xE0, 0x01, 0x0A);
putDataOutBuf(0xFE);
twiWrite(0xE2, 0x01, 0x0A);
putDataOutBuf(0xFF); //Send stop
TWCR |= (1<<TWSTA); // then start the TWI
}
/******************************************************************************
* Insert in buffer out
*****************************************************************************/
void putDataOutBuf(u08 data){
CircularBufferOutEnd++;
CircularBufferOutEnd %= CIRCULAR_BUFFER_SIZE;
CircularBufferOut[CircularBufferOutEnd] = data;
}
/******************************************************************************
* Retrieve from buffer out
*****************************************************************************/
u08 getDataOutBuf(void){
CircularBufferOutIndex++;
CircularBufferOutIndex %= CIRCULAR_BUFFER_SIZE;
return (u08)CircularBufferOut[CircularBufferOutIndex];
}
/******************************************************************************
* Insert in buffer in
*****************************************************************************/
void putDataInBuf(u08 * ptr){
CircularBufferInEnd++;
CircularBufferInEnd %= CIRCULAR_BUFFER_SIZE;
CircularBufferIn[CircularBufferInEnd] = ptr;
}
/******************************************************************************
* Retrieve from buffer in
*****************************************************************************/
u08 * getDataInBuf(void){
CircularBufferInIndex++;
CircularBufferInIndex %= CIRCULAR_BUFFER_SIZE;
return CircularBufferIn[CircularBufferInIndex];
}
/******************************************************************************
* Write on TWI bus
*****************************************************************************/
void twiWrite(u08 address, u08 registre, u08 data){
cli();
putDataOutBuf(address);
putDataOutBuf(registre);
putDataOutBuf(data);
sei();
}
/******************************************************************************
* Read on TWI bus
*****************************************************************************/
void twiRead(u08 address, u08 registre, u08 *ptr){
cli();
putDataOutBuf(address);
putDataOutBuf(registre);
putDataOutBuf(0xFE);
putDataOutBuf(address+1);
putDataInBuf(ptr);
sei();
}
/******************************************************************************
*Attach Interrupt signal and execute this routine
*****************************************************************************/
SIGNAL(SIG_2WIRE_SERIAL) {
u08 status = TWSR & 0xF8;
switch (status) {
/*Case: start or restart condition */
case 0x08: /* Start Condition */
case 0x10: /* Restart Condition */
TWDR = getDataOutBuf();
//Reset TWI flag, Enable TWI, Enable TWI Acknoledge, Enable TWI Interrupt
TWCR = (1<<TWEN) | (1<<TWEA) | (1<<TWIE);
TWCR |= (1<<TWINT);
break;
/*case: write data on bus*/
case 0x18: /* Address Write Ack */
case 0x28: /* Data Write Ack */
case 0x30: /* Date Write NoAck */
buffer = getDataOutBuf();
//Reset TWI flag, Enable TWI, Enable TWI Acknoledge, Enable TWI Interrupt
TWCR = (1<<TWEN) | (1<<TWEA) | (1<<TWIE);
// if start or restart condition is read on the bus
if(buffer == 0xFF) // 0xFF will stop TWI
{
TWCR |= (1<<TWSTO);
}
else if(buffer == 0xFE) // 0xFE will restart TWI
{
TWCR |= (1<<TWSTA);
}
else // Put the value from "buffer" on the register "TWDR"
{
TWDR = buffer;
TWCR |= (1<<TWINT);
}
break;
/*case: Read data on the bus*/
case 0x50: /* Data Read Ack */
case 0x58: /* Data Read NoAck */
buffer_ptr = getDataInBuf(); //get Data from the circular buffer
*buffer_ptr = TWDR; //Write the value found in "TWDR" at the address of "buffer"
buffer = getDataOutBuf(); //Read next value in the circular buffer
//Reset TWI flag, Enable TWI, Enable TWI Acknoledge, Enable TWI Interrupt
TWCR = (1<<TWEN) | (1<<TWEA) | (1<<TWIE);
if(buffer == 0xFF) // 0xFF will stop TWI
{
TWCR |= (1<<TWSTO);
}
else if(buffer == 0xFE) // 0xFE will restart TWI
{
TWCR |= (1<<TWSTA);
}
else // Put the value from "buffer" on the register "TWDR"
{
TWDR = buffer;
TWCR |= (1<<TWINT);
}
break; // Added this break to hendel stop condition
/*case: Received the Acknoledge from slave to read desired value*/
case 0x40: /* Address Read Ack */
//Reset TWI flag, Enable TWI, Enable TWI Acknoledge, Enable TWI Interrupt
TWCR = (1<<TWEN) | (1<<TWIE);
TWCR |= (1<<TWINT);
break;
/*case: No response from Sensor*/
case 0x48: /* Address Read NoAck */
case 0x20: /* Address Write NoAck */
//Reset TWI flag, Enable TWI, Enable TWI Acknoledge, Enable TWI Interrupt
TWCR = (1<<TWEN) | (1<<TWSTO); //stop TWI
TWCR |= (1<<TWINT);
break;
default :
/*
Should not be use
*/
break;
}
}