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; |