Rev 624 Rev 816
1 #include <avr/pgmspace.h> 1 #include <avr/pgmspace.h>
2 #include <avr/interrupt.h> 2 #include <avr/interrupt.h>
3 #include <avr/signal.h> 3 #include <avr/signal.h>
4 #include <avr/sleep.h> 4 #include <avr/sleep.h>
5   5  
6 #include "common.h" 6 #include "common.h"
7 #include "usart.h" 7 #include "usart.h"
8 #include "twi_aap.h" 8 #include "twi_aap.h"
9 #include "eeprom.h" 9 #include "eeprom.h"
10   10  
11 /********* 11 /*********
12 switch (TWOStatus) { 12 switch (TWOStatus) {
13 case TW_SR_SLA_ACK: //0x60 13 case TW_SR_SLA_ACK: //0x60
14 break; 14 break;
15 case TW_SR_ARB_LOST_SLA_ACK: //0x68 15 case TW_SR_ARB_LOST_SLA_ACK: //0x68
16 break; 16 break;
17 case TW_SR_GCALL_ACK: //0x70 17 case TW_SR_GCALL_ACK: //0x70
18 break; 18 break;
19 case TW_SR_ARB_LOST_GCALL_ACK: //0x78 19 case TW_SR_ARB_LOST_GCALL_ACK: //0x78
20 break; 20 break;
21 case TW_SR_DATA_ACK: //0x80 21 case TW_SR_DATA_ACK: //0x80
22 break; 22 break;
23 case TW_SR_DATA_NACK: //0x88 23 case TW_SR_DATA_NACK: //0x88
24 break; 24 break;
25 case TW_SR_GCALL_DATA_ACK: //0x90 25 case TW_SR_GCALL_DATA_ACK: //0x90
26 break; 26 break;
27 case TW_SR_GCALL_DATA_NACK: //0x98 27 case TW_SR_GCALL_DATA_NACK: //0x98
28 break; 28 break;
29 case TW_ST_LAST_DATA: //0xC8 29 case TW_ST_LAST_DATA: //0xC8
30 case TW_SR_STOP: //0xA0 30 case TW_SR_STOP: //0xA0
31 State = MS_Idle; 31 State = MS_Idle;
32 SETBIT(TWIControl,(1 << TWEA)); // turn address recognition back on 32 SETBIT(TWIControl,(1 << TWEA)); // turn address recognition back on
33 break; 33 break;
34 default: // All non-handled states will basically terminate any processing 34 default: // All non-handled states will basically terminate any processing
35 State = MS_Idle; 35 State = MS_Idle;
36 CLRBIT(TWIControl,(1 << TWEA)); // will return NACK, i.e. will pretend to be unaddressed 36 CLRBIT(TWIControl,(1 << TWEA)); // will return NACK, i.e. will pretend to be unaddressed
37 break; 37 break;
38 } 38 }
39   39  
40 switch (TWOStatus) { 40 switch (TWOStatus) {
41 case TW_ST_SLA_ACK: //0xA8 41 case TW_ST_SLA_ACK: //0xA8
42 break; 42 break;
43 case TW_ST_ARB_LOST_SLA_ACK: //0xB0 43 case TW_ST_ARB_LOST_SLA_ACK: //0xB0
44 break; 44 break;
45 case TW_ST_DATA_ACK: //0xB8 45 case TW_ST_DATA_ACK: //0xB8
46 break; 46 break;
47 case TW_ST_DATA_NACK: //0xC0 47 case TW_ST_DATA_NACK: //0xC0
48 break; 48 break;
49 case TW_ST_ARB_LOST: //0x38 - let's hope it works 49 case TW_ST_ARB_LOST: //0x38 - let's hope it works
50 break; 50 break;
51 case TW_ST_LAST_DATA: //0xC8 51 case TW_ST_LAST_DATA: //0xC8
52 State = MS_Idle; 52 State = MS_Idle;
53 SETBIT(TWIControl,(1 << TWEA)); // turn address recognition back on 53 SETBIT(TWIControl,(1 << TWEA)); // turn address recognition back on
54 break; 54 break;
55 default: // All non-handled states will basically terminate any processing 55 default: // All non-handled states will basically terminate any processing
56 State = MS_Idle; 56 State = MS_Idle;
57 CLRBIT(TWIControl,(1 << TWEA)); // will return NACK, i.e. will pretend to be unaddressed 57 CLRBIT(TWIControl,(1 << TWEA)); // will return NACK, i.e. will pretend to be unaddressed
58 break; 58 break;
59 } 59 }
60 **********/ 60 **********/
61   61  
62 namespace TWI { 62 namespace TWI {
63 extern const sConfigRecord ConfigRecord PROGMEM __attribute__ ((weak)) = {UniqueIDUnassigned,DevClassUnassigned,DevUnassigned}; 63 extern const sConfigRecord ConfigRecord PROGMEM __attribute__ ((weak)) = {UniqueIDUnassigned,DevClassUnassigned,DevUnassigned};
64   64  
65 // void TWI::UserInit() __attribute__ ((weak)); 65 // void TWI::UserInit() __attribute__ ((weak));
66 void TWI::HandleUserReceive() __attribute__ ((weak)); 66 void TWI::HandleUserReceive() __attribute__ ((weak));
67 void TWI::HandleUserTransmit() __attribute__ ((weak)); 67 void TWI::HandleUserTransmit() __attribute__ ((weak));
68 void TWI::HandleUserState() __attribute__ ((weak)); 68 void TWI::HandleUserState() __attribute__ ((weak));
69 static inline void TWI::HandleState_MS_Idle(); 69 static inline void TWI::HandleState_MS_Idle();
70 static inline void TWI::HandleState_MS_Addressed(); 70 static inline void TWI::HandleState_MS_Addressed();
71 static inline void TWI::StateMachine(); 71 static inline void TWI::StateMachine();
72   72  
73 uint8_t ConfigCnt; 73 uint8_t ConfigCnt;
74 } 74 }
75   75  
76 void TWI::ResetTWITransmit() { 76 void TWI::ResetTWITransmit() {
77 // Same as above, but also returns the statemachine to the idle state 77 // Same as above, but also returns the statemachine to the idle state
78 State = MS_Idle; 78 State = MS_Idle;
79 LastCmd = TWI_AAPCmd_Reserved; 79 LastCmd = TWI_AAPCmd_Reserved;
80 // In slave-transmitter mode it's not possible to reset the TWI. 80 // In slave-transmitter mode it's not possible to reset the TWI.
81 // But at least we can transmit all '1'-s so we won't interfere with the bus. 81 // But at least we can transmit all '1'-s so we won't interfere with the bus.
82 #ifdef SERIAL_DBG 82 #ifdef SERIAL_DBG
83 USART0::SendData('*'); 83 USART0::SendData('*');
84 #endif 84 #endif
85 TWDR = 0xff; 85 TWDR = 0xff;
86 SETBIT(TWIControl,(1 << TWEA) | (1 << TWSTO)); 86 SETBIT(TWIControl,(1 << TWEA) | (1 << TWSTO));
87 } 87 }
88 void TWI::ResetTWIReceive() { 88 void TWI::ResetTWIReceive() {
89 // Same as above, but also returns the statemachine to the idle state 89 // Same as above, but also returns the statemachine to the idle state
90 State = MS_Idle; 90 State = MS_Idle;
91 LastCmd = TWI_AAPCmd_Reserved; 91 LastCmd = TWI_AAPCmd_Reserved;
92 // In slave-transmitter mode it's not possible to reset the TWI. 92 // In slave-transmitter mode it's not possible to reset the TWI.
93 // But at least we can transmit all '1'-s so we won't interfere with the bus. 93 // But at least we can transmit all '1'-s so we won't interfere with the bus.
94 #ifdef SERIAL_DBG 94 #ifdef SERIAL_DBG
95 USART0::SendData('#'); 95 USART0::SendData('#');
96 #endif 96 #endif
97 TWDR = 0xff; 97 TWDR = 0xff;
98 SETBIT(TWIControl,(1 << TWSTO)); 98 SETBIT(TWIControl,(1 << TWSTO));
99 CLRBIT(TWIControl,(1 << TWEA)); 99 CLRBIT(TWIControl,(1 << TWEA));
100 } 100 }
101 void TWI::ResetTWI() { 101 void TWI::ResetTWI() {
102 switch (TWIStatus) { 102 switch (TWIStatus) {
103 case TW_ST_LAST_DATA: //0xC8 103 case TW_ST_LAST_DATA: //0xC8
104 case TW_SR_STOP: 104 case TW_SR_STOP:
105 case TW_ST_DATA_NACK: 105 case TW_ST_DATA_NACK:
106 case TW_SR_DATA_NACK: 106 case TW_SR_DATA_NACK:
107 case TW_SR_GCALL_DATA_NACK: 107 case TW_SR_GCALL_DATA_NACK:
108 State = MS_Idle; 108 State = MS_Idle;
109 SETBIT(TWIControl,(1 << TWEA)); // turn address recognition back on 109 SETBIT(TWIControl,(1 << TWEA)); // turn address recognition back on
110 CLRBIT(TWIControl,(1 << TWSTO)); // even if we did so, stop aborting 110 CLRBIT(TWIControl,(1 << TWSTO)); // even if we did so, stop aborting
111 break; 111 break;
112 case TW_BUS_ERROR: 112 case TW_BUS_ERROR:
113 // This is the point where we re-enable the address recognition 113 // This is the point where we re-enable the address recognition
114 ResetTWITransmit(); 114 ResetTWITransmit();
115 break; 115 break;
116 default: 116 default:
117 ResetTWIReceive(); 117 ResetTWIReceive();
118 break; 118 break;
119 } 119 }
120 } 120 }
121   121  
122 /*void TWI::UserInit() { 122 /*void TWI::UserInit() {
123 }*/ 123 }*/
124   124  
125 void TWI::HandleUserReceive() { 125 void TWI::HandleUserReceive() {
126 #ifdef SERIAL_DBG 126 #ifdef SERIAL_DBG
127 USART0::SendData('r'); 127 USART0::SendData('r');
128 #endif 128 #endif
129 ResetTWI(); 129 ResetTWI();
130 } 130 }
131   131  
132 void TWI::HandleUserTransmit() { 132 void TWI::HandleUserTransmit() {
133 #ifdef SERIAL_DBG 133 #ifdef SERIAL_DBG
134 USART0::SendData('t'); 134 USART0::SendData('t');
135 #endif 135 #endif
136 ResetTWI(); 136 ResetTWI();
137 } 137 }
138   138  
139 void TWI::HandleUserState() { 139 void TWI::HandleUserState() {
140 } 140 }
141   141  
142   142  
143 static inline void TWI::HandleState_MS_Idle() { 143 static inline void TWI::HandleState_MS_Idle() {
144 switch (TWIStatus) { 144 switch (TWIStatus) {
145 case TW_SR_SLA_ACK: 145 case TW_SR_SLA_ACK:
146 LastCmd = TWI_AAPCmd_Reserved; 146 LastCmd = TWI_AAPCmd_Reserved;
147 HandleUserReceive(); 147 HandleUserReceive();
148 break; 148 break;
149 case TW_SR_GCALL_ACK: 149 case TW_SR_GCALL_ACK:
150 State = MS_Addressed; 150 State = MS_Addressed;
151 break; 151 break;
152 case TW_ST_SLA_ACK: 152 case TW_ST_SLA_ACK:
153 if ((TWIData & 0xfe) == GeneralCallAddr) { 153 if ((TWIData & 0xfe) == GeneralCallAddr) {
154 // TWI_AAP read command: things depend on what the last (write) command was: 154 // TWI_AAP read command: things depend on what the last (write) command was:
155 if (LastCmd == TWI_AAPCmd_GetConfig) { 155 if (LastCmd == TWI_AAPCmd_GetConfig) {
156 // This is the read part of the GetUDID command: Send the byte count and change state 156 // This is the read part of the GetUDID command: Send the byte count and change state
157 TWIPrevData = sizeof(ConfigRecord); 157 TWIPrevData = sizeof(ConfigRecord);
158 TWDR = TWIPrevData; 158 TWDR = TWIPrevData;
159 State = AAP_CmdGetConfig_SendConfig; 159 State = AAP_CmdGetConfig_SendConfig;
160 ConfigCnt = 0; 160 ConfigCnt = 0;
161 //SETBIT(TWIControl,(1 << TWEA)); // require ACK 161 //SETBIT(TWIControl,(1 << TWEA)); // require ACK
162 } else { 162 } else {
163 //Unknown read command: ignore 163 //Unknown read command: ignore
164 ResetTWITransmit(); 164 ResetTWITransmit();
165 } 165 }
166 } else { 166 } else {
167 HandleUserTransmit(); 167 HandleUserTransmit();
168 } 168 }
169 break; 169 break;
170 case TW_ST_LAST_DATA: 170 case TW_ST_LAST_DATA:
171 case TW_SR_STOP: 171 case TW_SR_STOP:
172 #ifdef SERIAL_DBG 172 #ifdef SERIAL_DBG
173 USART0::SendData('.'); 173 USART0::SendData('.');
174 #endif 174 #endif
175 State = MS_Idle; 175 State = MS_Idle;
176 SETBIT(TWIControl,(1 << TWEA)); // turn address recognition back on 176 SETBIT(TWIControl,(1 << TWEA)); // turn address recognition back on
177 CLRBIT(TWIControl,(1 << TWSTO)); // even if we did so, stop aborting 177 CLRBIT(TWIControl,(1 << TWSTO)); // even if we did so, stop aborting
178 break; 178 break;
179 case TW_ST_DATA_ACK: 179 case TW_ST_DATA_ACK:
180 case TW_SR_DATA_ACK: 180 case TW_SR_DATA_ACK:
181 case TW_SR_GCALL_DATA_ACK: 181 case TW_SR_GCALL_DATA_ACK:
182 ResetTWIReceive(); 182 ResetTWIReceive();
183 break; 183 break;
184 case TW_BUS_ERROR: 184 case TW_BUS_ERROR:
185 case TW_ST_DATA_NACK: 185 case TW_ST_DATA_NACK:
186 case TW_SR_DATA_NACK: 186 case TW_SR_DATA_NACK:
187 case TW_SR_GCALL_DATA_NACK: 187 case TW_SR_GCALL_DATA_NACK:
188 // This is the point where we re-enable the address recognition 188 // This is the point where we re-enable the address recognition
189 ResetTWITransmit(); 189 ResetTWITransmit();
190 break; 190 break;
191 default: 191 default:
192 State = MS_Idle; 192 State = MS_Idle;
193 SETBIT(TWIControl,(1 << TWEA) | (1 << TWSTO)); // reset the TWI 193 SETBIT(TWIControl,(1 << TWEA) | (1 << TWSTO)); // reset the TWI
194 break; 194 break;
195 } 195 }
196 } 196 }
197   197  
198 static inline void TWI::HandleState_MS_Addressed() { 198 static inline void TWI::HandleState_MS_Addressed() {
199 switch (TWIStatus) { 199 switch (TWIStatus) {
200 case TW_SR_GCALL_DATA_ACK: 200 case TW_SR_GCALL_DATA_ACK:
201 switch(TWIData) { 201 switch(TWIData) {
202 case TWI_AAPCmd_ResetDevices: 202 case TWI_AAPCmd_ResetDevices:
203 LastCmd = TWIData; 203 LastCmd = TWIData;
204 State = MS_Idle; 204 State = MS_Idle;
205 SoftAddress = 0; 205 SoftAddress = 0;
206 TWAR = SoftAddress | 1; // General call recognition and slave-receiver mode through address being 0 206 TWAR = SoftAddress | 1; // General call recognition and slave-receiver mode through address being 0
207 break; 207 break;
208 case TWI_AAPCmd_ResetToPermAddress: 208 case TWI_AAPCmd_ResetToPermAddress:
209 LastCmd = TWIData; 209 LastCmd = TWIData;
210 State = MS_Idle; 210 State = MS_Idle;
211 SoftAddress = EEPROM::GetByte(EEPROM_layout::TWI_SoftAddr_Ofs); 211 SoftAddress = EEPROM::GetByte(EEPROM_layout::TWI_SoftAddr_Ofs);
212 TWAR = SoftAddress | 1; // General call recognition and slave-receiver mode 212 TWAR = SoftAddress | 1; // General call recognition and slave-receiver mode
213 if (SoftAddress != 0) { 213 if (SoftAddress != 0) {
214 // We have a valid address, do not respond to this command 214 // We have a valid address, do not respond to this command
215 LastCmd = TWI_AAPCmd_Reserved; 215 LastCmd = TWI_AAPCmd_Reserved;
216 } 216 }
217 break; 217 break;
218 case TWI_AAPCmd_GetConfig: 218 case TWI_AAPCmd_GetConfig:
219 LastCmd = TWIData; 219 LastCmd = TWIData;
220 State = AAP_CmdGetConfig_GetAddress; 220 State = AAP_CmdGetConfig_GetAddress;
221 break; 221 break;
222 case TWI_AAPCmd_AssignAddress: 222 case TWI_AAPCmd_AssignAddress:
223 LastCmd = TWIData; 223 LastCmd = TWIData;
224 ConfigCnt = 0; 224 ConfigCnt = 0;
225 State = AAP_CmdAssignAddress_GetUniqueID; 225 State = AAP_CmdAssignAddress_GetUniqueID;
226 break; 226 break;
227 default: 227 default:
228 // unknown command - ignore the rest 228 // unknown command - ignore the rest
229 ResetTWIReceive(); 229 ResetTWIReceive();
230 break; 230 break;
231 } 231 }
232 break; 232 break;
233 default: 233 default:
234 ResetTWI(); 234 ResetTWI();
235 break; 235 break;
236 } 236 }
237 } 237 }
238   238  
239 static inline void TWI::StateMachine() { 239 static inline void TWI::StateMachine() {
240 TWIStatus = TWSR & TW_STATUS_MASK; 240 TWIStatus = TWSR & TW_STATUS_MASK;
241 TWIControl = TWCR; 241 TWIControl = TWCR;
242 if (TWIStatus != TW_SR_STOP) { 242 if (TWIStatus != TW_SR_STOP) {
243 TWIData = TWDR; 243 TWIData = TWDR;
244 } else { 244 } else {
245 // Fast short-circuit for stop-bit detection 245 // Fast short-circuit for stop-bit detection
246 // This condition cannot use clock-stretching so we might miss the next start if we don't hurry 246 // This condition cannot use clock-stretching so we might miss the next start if we don't hurry
247 State = MS_Idle; 247 State = MS_Idle;
248 SETBIT(TWIControl,(1 << TWEA)); // turn address recognition back on 248 SETBIT(TWIControl,(1 << TWEA)); // turn address recognition back on
249 CLRBIT(TWIControl,(1 << TWSTO)); // even if we did so, stop aborting 249 CLRBIT(TWIControl,(1 << TWSTO)); // even if we did so, stop aborting
250 SETBIT(TWIControl,(1 << TWINT)); 250 SETBIT(TWIControl,(1 << TWINT));
251 TWCR = TWIControl; 251 TWCR = TWIControl;
252 return; 252 return;
253 } 253 }
254   254  
255 #ifdef SERIAL_DBG 255 #ifdef SERIAL_DBG
256 // DUMP state to serial port 256 // DUMP state to serial port
257 USART0::SendData('s'); USART0::SendData(' '); USART0::SendHexData(TWIStatus); USART0::SendData(' '); 257 USART0::SendData('s'); USART0::SendData(' '); USART0::SendHexData(TWIStatus); USART0::SendData(' ');
258 USART0::SendData('d'); USART0::SendData(' '); USART0::SendHexData(TWIData); USART0::SendData(' '); 258 USART0::SendData('d'); USART0::SendData(' '); USART0::SendHexData(TWIData); USART0::SendData(' ');
259 USART0::SendData('S'); USART0::SendData(' '); USART0::SendHexData(State); USART0::SendData(' '); 259 USART0::SendData('S'); USART0::SendData(' '); USART0::SendHexData(State); USART0::SendData(' ');
260 USART0::SendData('L'); USART0::SendData(' '); USART0::SendHexData(LastCmd); USART0::SendData(' '); 260 USART0::SendData('L'); USART0::SendData(' '); USART0::SendHexData(LastCmd); USART0::SendData(' ');
261 USART0::SendData('A'); USART0::SendData(' '); USART0::SendHexData(SoftAddress); USART0::SendData('-'); 261 USART0::SendData('A'); USART0::SendData(' '); USART0::SendHexData(SoftAddress); USART0::SendData('-');
262 #endif 262 #endif
263 switch (State) { 263 switch (State) {
264 case MS_Idle: 264 case MS_Idle:
265 HandleState_MS_Idle(); 265 HandleState_MS_Idle();
266 break; 266 break;
267 case MS_Addressed: 267 case MS_Addressed:
268 HandleState_MS_Addressed(); 268 HandleState_MS_Addressed();
269 break; 269 break;
270   270  
271 case AAP_CmdGetConfig_GetAddress: 271 case AAP_CmdGetConfig_GetAddress:
272 switch (TWIStatus) { 272 switch (TWIStatus) {
273 case TW_SR_GCALL_DATA_ACK: 273 case TW_SR_GCALL_DATA_ACK:
274 State = MS_Idle; 274 State = MS_Idle;
275 SETBIT(TWIControl,(1 << TWEA) | (1 << TWSTO)); // reset the TWI 275 SETBIT(TWIControl,(1 << TWEA) | (1 << TWSTO)); // reset the TWI
276 if (SoftAddress != TWIData) { 276 if (SoftAddress != TWIData) {
277 // We have a valid address, or was not addressed -> do not respond to this command 277 // We have a valid address, or was not addressed -> do not respond to this command
278 LastCmd = TWI_AAPCmd_Reserved; 278 LastCmd = TWI_AAPCmd_Reserved;
279 } 279 }
280 break; 280 break;
281 default: 281 default:
282 ResetTWI(); 282 ResetTWI();
283 break; 283 break;
284 } 284 }
285 break; 285 break;
286   286  
287 case AAP_CmdAssignAddress_GetUniqueID: 287 case AAP_CmdAssignAddress_GetUniqueID:
288 switch (TWIStatus) { 288 switch (TWIStatus) {
289 case TW_SR_GCALL_DATA_ACK: 289 case TW_SR_GCALL_DATA_ACK:
290 if (TWIData == pgm_read_byte(ConfigRecord.UniqueID+ConfigCnt)) { 290 if (TWIData == pgm_read_byte(ConfigRecord.UniqueID+ConfigCnt)) {
291 ++ConfigCnt; 291 ++ConfigCnt;
292 if (ConfigCnt == UniqueID_Size) State = AAP_CmdAssignAddress_GetAddress; 292 if (ConfigCnt == UniqueID_Size) State = AAP_CmdAssignAddress_GetAddress;
293 } else { 293 } else {
294 // UDID is not ours, abort command 294 // UDID is not ours, abort command
295 ResetTWIReceive(); 295 ResetTWIReceive();
296 } 296 }
297 break; 297 break;
298 default: 298 default:
299 ResetTWI(); 299 ResetTWI();
300 break; 300 break;
301 } 301 }
302 break; 302 break;
303 case AAP_CmdAssignAddress_GetAddress: 303 case AAP_CmdAssignAddress_GetAddress:
304 switch (TWIStatus) { 304 switch (TWIStatus) {
305 case TW_SR_GCALL_DATA_ACK: 305 case TW_SR_GCALL_DATA_ACK:
306 SoftAddress = TWIData & 0xfe; 306 SoftAddress = TWIData & 0xfe;
307 if (TWIData & 0x01 == 1) { 307 if (TWIData & 0x01 == 1) {
308 EEPROM::SetByte(EEPROM_layout::TWI_SoftAddr_Ofs,SoftAddress); 308 EEPROM::SetByte(EEPROM_layout::TWI_SoftAddr_Ofs,SoftAddress);
309 } 309 }
310 State = MS_Idle; 310 State = MS_Idle;
311 TWAR = SoftAddress | 1; // General call recognition and normal operation 311 TWAR = SoftAddress | 1; // General call recognition and normal operation
312 SETBIT(TWIControl,(1 << TWEA) | (1 << TWSTO)); // reset the TWI 312 SETBIT(TWIControl,(1 << TWEA) | (1 << TWSTO)); // reset the TWI
313 LastCmd = TWI_AAPCmd_Reserved; 313 LastCmd = TWI_AAPCmd_Reserved;
314 break; 314 break;
315 default: 315 default:
316 ResetTWI(); 316 ResetTWI();
317 break; 317 break;
318 } 318 }
319 break; 319 break;
320   320  
321   321  
322   322  
323 // Read-oriented commands 323 // Read-oriented commands
324 case AAP_CmdGetConfig_SendConfig: 324 case AAP_CmdGetConfig_SendConfig:
325 switch (TWIStatus) { 325 switch (TWIStatus) {
326 case TW_ST_DATA_ACK: 326 case TW_ST_DATA_ACK:
327 if (TWIData != TWIPrevData) { 327 if (TWIData != TWIPrevData) {
328 // We've lost the arbitration 328 // We've lost the arbitration
329 ResetTWITransmit(); 329 ResetTWITransmit();
330 break; 330 break;
331 } 331 }
332 TWIPrevData = pgm_read_byte(((uint8_t*)(&ConfigRecord))+ConfigCnt); 332 TWIPrevData = pgm_read_byte(((uint8_t*)(&ConfigRecord))+ConfigCnt);
333 TWDR = TWIPrevData; 333 TWDR = TWIPrevData;
334 ConfigCnt++; 334 ConfigCnt++;
335 //At the last byte, we require NACK 335 //At the last byte, we require NACK
336 if (ConfigCnt == sizeof(ConfigRecord)) { 336 if (ConfigCnt == sizeof(ConfigRecord)) {
337 State = MS_Idle; 337 State = MS_Idle;
338 CLRBIT(TWIControl,(1 << TWEA)); // require NACK 338 CLRBIT(TWIControl,(1 << TWEA)); // require NACK
339 } else { 339 } else {
340 State = AAP_CmdGetConfig_SendConfig; 340 State = AAP_CmdGetConfig_SendConfig;
341 SETBIT(TWIControl,(1 << TWEA)); // require ACK 341 SETBIT(TWIControl,(1 << TWEA)); // require ACK
342 } 342 }
343 break; 343 break;
344   344  
345 default: 345 default:
346 ResetTWI(); 346 ResetTWI();
347 break; 347 break;
348 } 348 }
349 break; 349 break;
350   350  
351 // User commands 351 // User commands
352 default: 352 default:
353 HandleUserState(); 353 HandleUserState();
354 break; 354 break;
355 } 355 }
356 // re-enable the TWI interrupts 356 // re-enable the TWI interrupts
357 SETBIT(TWIControl,1 << TWINT); 357 SETBIT(TWIControl,1 << TWINT);
358 #ifdef SERIAL_DBG 358 #ifdef SERIAL_DBG
359 USART0::SendData('S'); USART0::SendData(' '); USART0::SendHexData(State); USART0::SendData(' '); 359 USART0::SendData('S'); USART0::SendData(' '); USART0::SendHexData(State); USART0::SendData(' ');
360 USART0::SendData('L'); USART0::SendData(' '); USART0::SendHexData(LastCmd); USART0::SendData(' '); 360 USART0::SendData('L'); USART0::SendData(' '); USART0::SendHexData(LastCmd); USART0::SendData(' ');
361 USART0::SendData('A'); USART0::SendData(' '); USART0::SendHexData(SoftAddress); USART0::SendData(' '); 361 USART0::SendData('A'); USART0::SendData(' '); USART0::SendHexData(SoftAddress); USART0::SendData(' ');
362 USART0::SendData('C'); USART0::SendData(' '); USART0::SendHexData(TWIControl); USART0::SendData(0x0d); USART0::SendData(0x0a); 362 USART0::SendData('C'); USART0::SendData(' '); USART0::SendHexData(TWIControl); USART0::SendData(0x0d); USART0::SendData(0x0a);
363 #endif 363 #endif
364 TWCR = TWIControl; 364 TWCR = TWIControl;
365 } 365 }
366   366  
367 SIGNAL(SIG_TWI) {TWI::StateMachine();} 367 SIGNAL(SIG_TWI) {TWI::StateMachine();}
368   368  
369 uint8_t TWI::State; 369 uint8_t TWI::State;
370 uint8_t TWI::LastCmd; 370 uint8_t TWI::LastCmd;
371 uint8_t TWI::SoftAddress; 371 uint8_t TWI::SoftAddress;
372 uint8_t TWI::TWIStatus; 372 uint8_t TWI::TWIStatus;
373 uint8_t TWI::TWIData; 373 uint8_t TWI::TWIData;
374 uint8_t TWI::TWIPrevData; 374 uint8_t TWI::TWIPrevData;
375 uint8_t TWI::TWIControl; 375 uint8_t TWI::TWIControl;