5 |
5 |
6 /***** HP 34970A communication class ***/ |
6 /***** HP 34970A communication class ***/ |
7 |
7 |
8 #define RXTIMEOUT 50ms |
8 #define RXTIMEOUT 50ms |
9 #define STARTUPRETRY 0.5 |
9 #define STARTUPRETRY 0.5 |
10 |
|
11 uint8_t startup_seq[] = { |
|
12 0x33, |
|
13 0x02, // 0x02? |
|
14 0x00, |
|
15 0x00, |
|
16 }; |
|
17 |
10 |
18 HPSerial::statemethod HPSerial::state_table[NUM_STATES] = { |
11 HPSerial::statemethod HPSerial::state_table[NUM_STATES] = { |
19 &HPSerial::do_state_initial, // STATE_IDLE |
12 &HPSerial::do_state_initial, // STATE_IDLE |
20 &HPSerial::do_state_command, // STATE_COMMAND |
13 &HPSerial::do_state_command, // STATE_COMMAND |
21 &HPSerial::do_state_payload_size, // STATE_PAYLOAD_SIZE |
14 &HPSerial::do_state_payload_size, // STATE_PAYLOAD_SIZE |
34 cur_state = STATE_IDLE; |
27 cur_state = STATE_IDLE; |
35 send_thread.start(callback(this, &HPSerial::send_pending_key)); |
28 send_thread.start(callback(this, &HPSerial::send_pending_key)); |
36 serial.attach(callback(this, &HPSerial::rx_irq), SerialBase::RxIrq); |
29 serial.attach(callback(this, &HPSerial::rx_irq), SerialBase::RxIrq); |
37 } |
30 } |
38 |
31 |
39 void HPSerial::startup(uint8_t keycode) { |
32 |
40 cur_gstate = GSTATE_STARTING; |
33 // SEND related methods |
41 |
|
42 if (keycode != 0xFF) { |
|
43 printf("Set startup keycode to %X\n", keycode); |
|
44 startup_seq[2] = 0xFF; |
|
45 startup_seq[3] = keycode; |
|
46 } |
|
47 else |
|
48 startup_seq[2] = 0x00; |
|
49 set_timer(10ms); // launch the startup in 10ms |
|
50 } |
|
51 |
|
52 void HPSerial::_startup(void) |
|
53 { |
|
54 cur_gstate = GSTATE_STARTING; |
|
55 tr_data.cmd = 0xFF; |
|
56 tr_data.pos = 0; |
|
57 |
|
58 if (startup_seq[2] == 0xFF) |
|
59 tr_data.size = 4; |
|
60 else |
|
61 tr_data.size = 3; // sizeof(startup_seq); |
|
62 for(uint8_t i=0; i<tr_data.size; i++) |
|
63 tr_data.payload[i] = startup_seq[i]; |
|
64 cur_state = do_state_sending(); |
|
65 } |
|
66 |
|
67 void HPSerial::sendkey(uint8_t keycode) |
34 void HPSerial::sendkey(uint8_t keycode) |
68 { |
35 { |
69 if (!sendbuf.full()) |
36 if (!sendbuf.full()) |
70 sendbuf.push(keycode); |
37 sendbuf.push(keycode); |
71 } |
38 } |
72 |
39 |
73 |
40 |
74 bool HPSerial::wait_for(uint8_t value) |
41 bool HPSerial::wait_for(uint8_t value) |
75 { |
42 { // wait for an expected character in the serial port |
76 char c; |
43 char c; |
77 |
44 |
78 for(uint8_t i=0; i<2; i++) |
45 for(uint8_t i=0; i<2; i++) |
79 { |
46 { |
80 while(!serial.readable()) |
47 while(!serial.readable()) |
81 wait_us(10); |
48 wait_us(10); |
82 //ThisThread::sleep_for(0.1ms); |
|
83 serial.read(&c, 1); |
49 serial.read(&c, 1); |
84 if (value == c) |
50 if (value == c) |
85 return true; |
51 return true; |
86 } |
52 } |
87 return false; |
53 return false; |
88 } |
54 } |
|
55 |
89 |
56 |
90 void HPSerial::send_pending_key() { |
57 void HPSerial::send_pending_key() { |
91 uint8_t c; |
58 uint8_t c; |
92 |
59 |
93 while(true) |
60 while(true) |
117 //else // prevent from flooding the main unit |
84 //else // prevent from flooding the main unit |
118 ThisThread::sleep_for(5ms); |
85 ThisThread::sleep_for(5ms); |
119 } |
86 } |
120 } |
87 } |
121 |
88 |
|
89 |
122 void HPSerial::send_startup_seq(uint8_t keycode) { |
90 void HPSerial::send_startup_seq(uint8_t keycode) { |
123 uint8_t c; |
91 uint8_t c; |
124 |
92 |
125 while (cur_gstate != GSTATE_IDLE) { |
93 while (cur_gstate != GSTATE_IDLE) { |
126 ThisThread::sleep_for(1ms); |
94 ThisThread::sleep_for(1ms); |
151 cur_gstate = GSTATE_IDLE; |
119 cur_gstate = GSTATE_IDLE; |
152 serial.attach(callback(this, &HPSerial::rx_irq), SerialBase::RxIrq); |
120 serial.attach(callback(this, &HPSerial::rx_irq), SerialBase::RxIrq); |
153 |
121 |
154 } |
122 } |
155 |
123 |
|
124 |
156 void HPSerial::send_startup_seq() { |
125 void HPSerial::send_startup_seq() { |
157 uint8_t c; |
126 uint8_t c; |
158 |
127 |
159 while (cur_gstate != GSTATE_IDLE) { |
128 while (cur_gstate != GSTATE_IDLE) { |
160 ThisThread::sleep_for(1ms); |
129 ThisThread::sleep_for(1ms); |
180 serial.write(&c, 1); |
149 serial.write(&c, 1); |
181 cur_gstate = GSTATE_IDLE; |
150 cur_gstate = GSTATE_IDLE; |
182 serial.attach(callback(this, &HPSerial::rx_irq), SerialBase::RxIrq); |
151 serial.attach(callback(this, &HPSerial::rx_irq), SerialBase::RxIrq); |
183 } |
152 } |
184 |
153 |
185 void HPSerial::send_key_when_idle() { |
154 |
186 if (!sendbuf.empty() && cur_gstate == GSTATE_IDLE) |
155 // RECV related methods |
187 { |
|
188 uint8_t keycode; |
|
189 cur_gstate = GSTATE_TX; |
|
190 sendbuf.pop(keycode); |
|
191 tr_data.size = 2; |
|
192 tr_data.cmd = 0xFF; |
|
193 tr_data.pos = 0; |
|
194 tr_data.payload[0] = 0x66; |
|
195 tr_data.payload[1] = keycode; |
|
196 cur_state = do_state_sending(); |
|
197 } |
|
198 } |
|
199 |
156 |
200 bool HPSerial::cmd_available(void) |
157 bool HPSerial::cmd_available(void) |
201 { |
158 { |
202 return !cmdbuf.empty(); |
159 return !cmdbuf.empty(); |
203 } |
160 } |
204 |
161 |
|
162 |
205 bool HPSerial::pop(CMD& cmd) |
163 bool HPSerial::pop(CMD& cmd) |
206 { |
164 { |
207 return cmdbuf.pop(cmd); |
165 return cmdbuf.pop(cmd); |
208 } |
166 } |
209 |
167 |
|
168 |
210 bool HPSerial::cmd_buf_full(void) |
169 bool HPSerial::cmd_buf_full(void) |
211 { |
170 { |
212 return cmdbuf.full(); |
171 return cmdbuf.full(); |
213 } |
172 } |
214 |
173 |
|
174 |
215 unsigned int HPSerial::nerrors(uint8_t errorno) |
175 unsigned int HPSerial::nerrors(uint8_t errorno) |
216 { |
176 { |
217 return errs[errorno]; |
177 return errs[errorno]; |
218 } |
178 } |
|
179 |
219 |
180 |
220 void HPSerial::pushCmd(uint8_t cmd, uint8_t size, char *payload) { |
181 void HPSerial::pushCmd(uint8_t cmd, uint8_t size, char *payload) { |
221 CMD val; |
182 CMD val; |
222 uint8_t i; |
183 uint8_t i; |
223 val.id = ncmd++; |
184 val.id = ncmd++; |
227 val.value[i] = payload[i]; |
188 val.value[i] = payload[i]; |
228 val.value[i] = 0x00; |
189 val.value[i] = 0x00; |
229 cmdbuf.push(val); |
190 cmdbuf.push(val); |
230 } |
191 } |
231 |
192 |
|
193 |
232 void HPSerial::send_ack(uint8_t c) { |
194 void HPSerial::send_ack(uint8_t c) { |
233 serial.write(&c, 1); |
195 serial.write(&c, 1); |
234 set_timer(RXTIMEOUT); // if nothing else happen in the next RXTIMEOUT ms, reset |
196 set_timer(RXTIMEOUT); // if nothing else happen in the next RXTIMEOUT ms, reset |
235 } |
197 } |
|
198 |
236 |
199 |
237 HPSerial::state_t HPSerial::do_state_initial(uint8_t c) |
200 HPSerial::state_t HPSerial::do_state_initial(uint8_t c) |
238 { |
201 { |
239 // we are idle, incoming char is a handcheck |
202 // we are idle, incoming char is a handcheck |
240 // knwon handcheck values are 0x66 and 0x33 |
203 // knwon handcheck values are 0x66 and 0x33 |
275 return HPSerial::STATE_IDLE; |
239 return HPSerial::STATE_IDLE; |
276 } |
240 } |
277 return STATE_PAYLOAD_SIZE; |
241 return STATE_PAYLOAD_SIZE; |
278 } |
242 } |
279 |
243 |
|
244 |
280 HPSerial::state_t HPSerial::do_state_payload_size(uint8_t c) |
245 HPSerial::state_t HPSerial::do_state_payload_size(uint8_t c) |
281 { |
246 { |
282 tr_data.size = c; |
247 tr_data.size = c; |
283 tr_data.pos = 0; |
248 tr_data.pos = 0; |
284 send_ack(0x00); |
249 send_ack(0x00); |
285 return STATE_PAYLOAD; |
250 return STATE_PAYLOAD; |
286 } |
251 } |
|
252 |
287 |
253 |
288 HPSerial::state_t HPSerial::do_state_payload(uint8_t c) |
254 HPSerial::state_t HPSerial::do_state_payload(uint8_t c) |
289 { |
255 { |
290 tr_data.payload[tr_data.pos++] = c; |
256 tr_data.payload[tr_data.pos++] = c; |
291 send_ack(0x00); |
257 send_ack(0x00); |
294 return STATE_IDLE; |
260 return STATE_IDLE; |
295 } |
261 } |
296 return STATE_PAYLOAD; |
262 return STATE_PAYLOAD; |
297 } |
263 } |
298 |
264 |
|
265 |
299 HPSerial::state_t HPSerial::do_state_sending(uint8_t c) |
266 HPSerial::state_t HPSerial::do_state_sending(uint8_t c) |
300 { |
267 { |
301 // check the ack value returned by the main unit |
268 // check the ack value returned by the main unit |
302 |
269 |
303 if ((tr_data.pos == 1) && (tr_data.payload[0] == 0x66)) |
270 if ((tr_data.pos == 1) && (tr_data.payload[0] == 0x66)) |
304 { |
271 { |
305 if (c != 0x99) |
272 if (c != 0x99) |
306 { |
273 { |
307 //::printf("ACK ERROR %X [exp. %X]\n", c, ~(tr_data.payload[0])); |
|
308 // did not received the expected ack |
274 // did not received the expected ack |
309 if (c == 0x66) |
275 if (c == 0x66) |
310 { |
276 { |
311 // we received a start of transmission while trying to emit something, |
277 // we received a start of transmission while trying to emit something, |
312 // ignore it, the correct ack should be sent but the main unit just behind... |
278 // ignore it, the correct ack should be sent but the main unit just behind... |
342 set_timer(RXTIMEOUT); |
308 set_timer(RXTIMEOUT); |
343 return STATE_SENDING; |
309 return STATE_SENDING; |
344 } |
310 } |
345 } |
311 } |
346 |
312 |
|
313 |
347 HPSerial::state_t HPSerial::run_state(HPSerial::state_t cur_state, |
314 HPSerial::state_t HPSerial::run_state(HPSerial::state_t cur_state, |
348 uint8_t c) |
315 uint8_t c) |
349 { |
316 { |
350 return (this->*(HPSerial::state_table[cur_state]))(c); |
317 return (this->*(HPSerial::state_table[cur_state]))(c); |
351 }; |
318 }; |
|
319 |
352 |
320 |
353 void HPSerial::rx_irq(void) { |
321 void HPSerial::rx_irq(void) { |
354 uint8_t val; |
322 uint8_t val; |
355 if(serial.readable()) |
323 if(serial.readable()) |
356 { // no reason why we would end here without |
324 { // no reason why we would end here without |
365 } |
333 } |
366 |
334 |
367 |
335 |
368 void HPSerial::timeout(void) { |
336 void HPSerial::timeout(void) { |
369 set_timer(); // detach the timeouter |
337 set_timer(); // detach the timeouter |
370 if (cur_gstate == GSTATE_STARTING) |
338 cur_gstate = GSTATE_IDLE; |
371 _startup(); |
339 cur_state = STATE_IDLE; |
372 else // CPU took too long to reply, reset |
340 } |
373 { |
|
374 cur_gstate = GSTATE_IDLE; |
|
375 cur_state = STATE_IDLE; |
|
376 } |
|
377 } |
|