src/hp34comm.cpp

changeset 50
279868684eb3
parent 49
c146d19101a3
child 66
48f29a1d43d6
equal deleted inserted replaced
49:c146d19101a3 50:279868684eb3
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
257 send_ack(0xFF); 220 send_ack(0xFF);
258 return HPSerial::STATE_IDLE; 221 return HPSerial::STATE_IDLE;
259 } 222 }
260 } 223 }
261 224
225
262 HPSerial::state_t HPSerial::do_state_command(uint8_t c) 226 HPSerial::state_t HPSerial::do_state_command(uint8_t c)
263 { 227 {
264 if (c == 0x55) { // EoT 228 if (c == 0x55) { // EoT
265 return STATE_IDLE; 229 return STATE_IDLE;
266 } 230 }
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 }

mercurial