43 } |
39 } |
44 |
40 |
45 unsigned int HPSerial::nerrors(uint8_t errorno) { |
41 unsigned int HPSerial::nerrors(uint8_t errorno) { |
46 return errs[errorno]; |
42 return errs[errorno]; |
47 } |
43 } |
48 |
|
49 |
|
50 |
|
51 void HPSerial::reset(uint8_t errorno) { |
|
52 timeouter.detach(); |
|
53 head = 0; |
|
54 tx_state = Idle; |
|
55 setstatedbg(); |
|
56 tx_cmd = 0xFF; |
|
57 tx_ack = false; |
|
58 tx_len = 0xFF; |
|
59 memset(buf, 0, BUF_SIZE); |
|
60 if (errorno != 0xFF){ |
|
61 errs[errorno]++; |
|
62 } |
|
63 |
|
64 } |
|
65 |
44 |
66 void HPSerial::handleAck(uint8_t val) { |
45 void HPSerial::pushCmd(uint8_t cmd, uint8_t size, char *payload) { |
67 if ((tx_state == Rx) & (tx_cmd == 0xFF) & (tx_ack == false) & (val == 0x66)) { |
|
68 // special case: keypad does not acknwledge and takes precedence |
|
69 // on the "bus" |
|
70 tx_state = Tx; |
|
71 setstatedbg(); |
|
72 } else |
|
73 if (tx_cmd == 0xFF) // beginning of a packet, expect 0x99 as ack |
|
74 if (val == 0x99) |
|
75 { |
|
76 tx_ack = true; |
|
77 #ifdef DEBUG2 |
|
78 ack = 1; |
|
79 wait_us(2); |
|
80 ack = 0; |
|
81 #endif |
|
82 } |
|
83 else |
|
84 reset(1); |
|
85 |
|
86 else // expect 0x00 as ack |
|
87 if (val == 0x00) |
|
88 { |
|
89 tx_ack = true; |
|
90 #ifdef DEBUG2 |
|
91 ack = 1; |
|
92 wait_us(2); |
|
93 ack = 0; |
|
94 #endif |
|
95 } |
|
96 else |
|
97 reset(2); |
|
98 } |
|
99 |
|
100 void HPSerial::pushCmd(TrState direction, uint8_t cmd, uint8_t size, char *payload) { |
|
101 CMD val; |
46 CMD val; |
102 uint8_t i; |
47 uint8_t i; |
103 val.id = ncmd++; |
48 val.id = ncmd++; |
104 val.direction = direction; |
|
105 val.cmd = cmd; |
49 val.cmd = cmd; |
106 val.size = size; |
50 val.size = size; |
107 for(i=0; i<size; i++) |
51 for(i=0; i<size; i++) |
108 val.value[i] = payload[i]; |
52 val.value[i] = payload[i]; |
109 val.value[i] = 0x00; |
53 val.value[i] = 0x00; |
110 cmdbuf.push(val); |
54 cmdbuf.push(val); |
111 } |
55 } |
112 |
56 |
113 void HPSerial::handleChar(uint8_t val) { |
57 void HPSerial::send_ack(uint8_t c) { |
114 if (tx_ack == false) |
58 timeouter.attach(this, &HPSerial::timeout, 0.001); // if nothing else happen in the next ms, reset |
115 reset(3); |
59 serial.putc(c); |
116 else // remaining of the state machine |
|
117 if (tx_cmd == 0xFF) { |
|
118 // begin of transmission, expect a cmd |
|
119 tx_cmd = val; |
|
120 tx_ack = false; |
|
121 tx_len = 0xFF; |
|
122 } |
|
123 else if (tx_len == 0xFF) { |
|
124 if (val == 0x55) { |
|
125 // packet was in fact a keystroke, tx_cmd is in fact the key |
|
126 // stroke and no payload is expected |
|
127 #ifdef DEBUG2 |
|
128 statetx = 1; |
|
129 #endif |
|
130 pushCmd((TrState)Tx, tx_cmd, 0, (char*)buf); |
|
131 #ifdef DEBUG2 |
|
132 wait_us(2); |
|
133 statetx = 0; |
|
134 #endif |
|
135 reset(); |
|
136 } else { |
|
137 // got a cmd, expect a payload size |
|
138 tx_len = val; |
|
139 tx_ack = false; |
|
140 } |
|
141 } |
|
142 else if (tx_len == 0x55) { |
|
143 // packet was in fact a keystroke, tx_cmd is in fact the key |
|
144 // stroke and no payload is expected |
|
145 #ifdef DEBUG2 |
|
146 statetx = 1; |
|
147 #endif |
|
148 pushCmd((TrState)Tx, tx_cmd, 0, (char*)buf); |
|
149 #ifdef DEBUG2 |
|
150 wait_us(2); |
|
151 statetx = 0; |
|
152 #endif |
|
153 reset(); |
|
154 } |
|
155 else if (tx_len > 0) { |
|
156 // a payload char |
|
157 buf[head++] = val; |
|
158 tx_len--; |
|
159 tx_ack = false; |
|
160 } |
|
161 else { // end of payload, manage sent content |
|
162 uint8_t cur_state = tx_state; |
|
163 pushCmd((TrState)tx_state, tx_cmd, head, (char*)buf); |
|
164 |
|
165 switch(val) { |
|
166 case 0x66: // a new transmisson |
|
167 reset(); |
|
168 tx_state = cur_state; |
|
169 setstatedbg(); |
|
170 break; |
|
171 case 0x55: |
|
172 reset(); |
|
173 break; |
|
174 default: |
|
175 reset(6); |
|
176 break; |
|
177 } |
|
178 } |
|
179 } |
60 } |
180 |
61 |
|
62 HPSerial::state_t HPSerial::do_state_initial(HPSerial::instance_data_t *data, |
|
63 uint8_t c) |
|
64 { |
|
65 // go back to initial state |
|
66 data->cmd = 0xFF; |
|
67 data->size = 0; |
|
68 data->received = 0; |
|
69 timeouter.detach(); |
|
70 return HPSerial::STATE_IDLE; |
|
71 } |
181 |
72 |
|
73 HPSerial::state_t HPSerial::do_state_handcheck(HPSerial::instance_data_t *data, |
|
74 uint8_t c) |
|
75 { |
|
76 // we are idle, incoming char is a handcheck |
|
77 // knwon handcheck values are 0x66 and 0x33 |
|
78 switch (c) { |
|
79 case 0x33: |
|
80 send_ack(0xCC); |
|
81 return HPSerial::STATE_PAYLOAD_SIZE; |
|
82 break; |
|
83 case 0x66: |
|
84 send_ack(0x99); |
|
85 return HPSerial::STATE_COMMAND; |
|
86 break; |
|
87 default: |
|
88 return do_state_initial(data, 0x00); |
|
89 } |
|
90 } |
182 |
91 |
183 void HPSerial::setstatedbg(void) { |
92 HPSerial::state_t HPSerial::do_state_command(HPSerial::instance_data_t *data, |
184 #ifdef DEBUG2 |
93 uint8_t c) |
185 if (tx_state == Rx) |
94 { |
186 staterx = 1; |
95 if (c == 0x55) { // EoT |
187 else |
96 return do_state_initial(data, 0x00); |
188 staterx = 0; |
97 } |
189 if (tx_state == Tx) |
98 |
190 statetx = 1; |
99 data->cmd = c; |
191 else |
100 data->size = 0; |
192 statetx = 0; |
101 send_ack(0x00); |
193 #endif |
102 return HPSerial::STATE_PAYLOAD_SIZE; |
194 } |
103 } |
|
104 |
|
105 HPSerial::state_t HPSerial::do_state_payload_size(HPSerial::instance_data_t *data, |
|
106 uint8_t c) |
|
107 { |
|
108 data->size = c; |
|
109 data->received = 0; |
|
110 send_ack(0x00); |
|
111 return HPSerial::STATE_PAYLOAD; |
|
112 } |
|
113 |
|
114 HPSerial::state_t HPSerial::do_state_payload(HPSerial::instance_data_t *data, |
|
115 uint8_t c) |
|
116 { |
|
117 data->payload[data->received++] = c; |
|
118 send_ack(0x00); |
|
119 if (data->received >= data->size) { |
|
120 pushCmd(data->cmd, data->size, data->payload); |
|
121 return HPSerial::STATE_COMMAND; |
|
122 } |
|
123 return HPSerial::STATE_PAYLOAD; |
|
124 } |
|
125 |
|
126 HPSerial::state_t HPSerial::run_state(HPSerial::state_t cur_state, |
|
127 HPSerial::instance_data_t *data, |
|
128 uint8_t c) |
|
129 { |
|
130 return (this->*(HPSerial::state_table[cur_state]))(data, c); |
|
131 }; |
195 |
132 |
196 void HPSerial::rxIrq(void) { |
133 void HPSerial::rxIrq(void) { |
197 uint8_t val; |
134 uint8_t val; |
198 if(serial_rx.readable()) { // no reason why we would end here without this condition, but hey |
135 if(serial.readable()) { // no reason why we would end here without |
|
136 // this condition, but hey |
199 #ifdef DEBUG2 |
137 #ifdef DEBUG2 |
200 inrx=1; |
138 inrx=1; |
201 #endif |
139 #endif |
202 lled = 1; |
140 lled = 1; |
203 val = serial_rx.getc(); |
141 val = serial.getc(); |
204 |
142 cur_state = run_state(cur_state, &rx_data, val); |
205 timeouter.attach(this, &HPSerial::timeout, 0.001); // if nothing else happen in the next ms, reset |
|
206 |
|
207 if (tx_state == Idle) |
|
208 if (val == 0x66) { |
|
209 // no transmission in progress, expect a start of transmission |
|
210 tx_state = Rx; |
|
211 tx_ack = false; |
|
212 setstatedbg(); |
|
213 } |
|
214 else { |
|
215 reset(4); |
|
216 } |
|
217 else if (tx_ack == false) // manage the acks |
|
218 handleAck(val); |
|
219 else |
|
220 handleChar(val); |
|
221 lled = 0; |
143 lled = 0; |
222 #ifdef DEBUG2 |
144 #ifdef DEBUG2 |
223 inrx=0; |
145 inrx=0; |
224 #endif |
146 #endif |
225 } |
147 } |
226 } |
148 } |
227 |
149 |
228 |
150 |
229 void HPSerial::timeout(void) { |
151 void HPSerial::timeout(void) { |
230 if (tx_state != Idle) { |
152 cur_state = do_state_initial(&rx_data, 0x00); |
231 reset(7); |
|
232 } |
|
233 } |
153 } |