Mon, 28 Jan 2019 21:51:45 +0100
Add the (missing?) Keypad lib
5 | 1 | #include "hp34comm.h" |
2 | #include "mbed.h" | |
3 | #include "CircularBuffer.h" | |
4 | ||
5 | /***** HP 34970A communication class ***/ | |
6 | ||
8 | 7 | #ifdef DEBUG2 |
5 | 8 | |
8 | 9 | DigitalOut inrx(D9); |
5 | 10 | |
11 | #endif | |
12 | ||
21 | 13 | DigitalOut lled(LED3); |
18
4fd621551d55
[full replacement] implement a state machine for Rx
David Douard <david.douard@logilab.fr>
parents:
16
diff
changeset
|
14 | |
19 | 15 | #define RXTIMEOUT 0.05 |
16 | #define STARTUPRETRY 0.5 | |
21 | 17 | |
19 | 18 | const uint8_t startup_seq[] = { |
19 | 0x33, | |
20 | 0x02, | |
21 | 0x00, | |
22 | }; | |
23 | ||
24 | HPSerial::statemethod HPSerial::state_table[NUM_STATES] = { | |
25 | &HPSerial::do_state_initial, | |
26 | &HPSerial::do_state_command, | |
27 | &HPSerial::do_state_payload_size, | |
28 | &HPSerial::do_state_payload, | |
29 | &HPSerial::do_state_sending, | |
30 | &HPSerial::do_state_eot, | |
31 | }; | |
5 | 32 | |
18
4fd621551d55
[full replacement] implement a state machine for Rx
David Douard <david.douard@logilab.fr>
parents:
16
diff
changeset
|
33 | HPSerial::HPSerial(PinName tx, PinName rx): |
19 | 34 | serial(tx, rx), |
35 | cur_gstate(GSTATE_IDLE), | |
36 | ncmd(0) | |
18
4fd621551d55
[full replacement] implement a state machine for Rx
David Douard <david.douard@logilab.fr>
parents:
16
diff
changeset
|
37 | { |
21 | 38 | serial.baud(187500); |
19 | 39 | cur_state = STATE_IDLE; |
40 | serial.attach(callback(this, &HPSerial::rxIrq), Serial::RxIrq); | |
41 | } | |
42 | ||
43 | void HPSerial::startup(void) { | |
21 | 44 | cur_gstate = GSTATE_STARTING; |
19 | 45 | set_timer(0.002); // launch the startup in 10ms |
46 | } | |
47 | ||
48 | void HPSerial::_startup(void) | |
49 | { | |
50 | cur_gstate = GSTATE_STARTING; | |
51 | tr_data.size = sizeof(startup_seq); | |
52 | tr_data.cmd = 0xFF; | |
53 | tr_data.pos = 0; | |
54 | for(uint8_t i=0; i<tr_data.size; i++) | |
55 | tr_data.payload[i] = startup_seq[i]; | |
56 | cur_state = do_state_sending(); | |
5 | 57 | } |
58 | ||
19 | 59 | void HPSerial::send(const uint8_t *buf, uint8_t size) |
60 | { | |
61 | // tx_data-> | |
62 | //send(startup, sizeof(startup)/sizeof(startup[0])); | |
63 | } | |
64 | ||
65 | void HPSerial::sendkey(uint8_t keycode) | |
66 | { | |
67 | tr_data.size = 2; | |
68 | tr_data.cmd = 0xFF; | |
69 | tr_data.pos = 0; | |
70 | tr_data.payload[0] = 0x66; | |
71 | tr_data.payload[1] = keycode; | |
72 | cur_state = do_state_sending(); | |
73 | } | |
74 | ||
75 | bool HPSerial::cmd_available(void) | |
76 | { | |
5 | 77 | return !cmdbuf.empty(); |
78 | } | |
79 | ||
19 | 80 | bool HPSerial::pop(CMD& cmd) |
81 | { | |
5 | 82 | return cmdbuf.pop(cmd); |
83 | } | |
84 | ||
19 | 85 | bool HPSerial::cmd_buf_full(void) |
86 | { | |
5 | 87 | return cmdbuf.full(); |
88 | } | |
89 | ||
19 | 90 | unsigned int HPSerial::nerrors(uint8_t errorno) |
21 | 91 | { |
5 | 92 | return errs[errorno]; |
93 | } | |
94 | ||
18
4fd621551d55
[full replacement] implement a state machine for Rx
David Douard <david.douard@logilab.fr>
parents:
16
diff
changeset
|
95 | void HPSerial::pushCmd(uint8_t cmd, uint8_t size, char *payload) { |
5 | 96 | CMD val; |
97 | uint8_t i; | |
98 | val.id = ncmd++; | |
99 | val.cmd = cmd; | |
100 | val.size = size; | |
101 | for(i=0; i<size; i++) | |
102 | val.value[i] = payload[i]; | |
103 | val.value[i] = 0x00; | |
104 | cmdbuf.push(val); | |
105 | } | |
106 | ||
18
4fd621551d55
[full replacement] implement a state machine for Rx
David Douard <david.douard@logilab.fr>
parents:
16
diff
changeset
|
107 | void HPSerial::send_ack(uint8_t c) { |
4fd621551d55
[full replacement] implement a state machine for Rx
David Douard <david.douard@logilab.fr>
parents:
16
diff
changeset
|
108 | serial.putc(c); |
19 | 109 | set_timer(RXTIMEOUT); // if nothing else happen in the next ms, reset |
18
4fd621551d55
[full replacement] implement a state machine for Rx
David Douard <david.douard@logilab.fr>
parents:
16
diff
changeset
|
110 | } |
4fd621551d55
[full replacement] implement a state machine for Rx
David Douard <david.douard@logilab.fr>
parents:
16
diff
changeset
|
111 | |
19 | 112 | HPSerial::state_t HPSerial::do_state_initial(uint8_t c) |
18
4fd621551d55
[full replacement] implement a state machine for Rx
David Douard <david.douard@logilab.fr>
parents:
16
diff
changeset
|
113 | { |
4fd621551d55
[full replacement] implement a state machine for Rx
David Douard <david.douard@logilab.fr>
parents:
16
diff
changeset
|
114 | // we are idle, incoming char is a handcheck |
4fd621551d55
[full replacement] implement a state machine for Rx
David Douard <david.douard@logilab.fr>
parents:
16
diff
changeset
|
115 | // knwon handcheck values are 0x66 and 0x33 |
19 | 116 | set_timer(RXTIMEOUT); // reset the watchdog |
18
4fd621551d55
[full replacement] implement a state machine for Rx
David Douard <david.douard@logilab.fr>
parents:
16
diff
changeset
|
117 | switch (c) { |
4fd621551d55
[full replacement] implement a state machine for Rx
David Douard <david.douard@logilab.fr>
parents:
16
diff
changeset
|
118 | case 0x33: |
4fd621551d55
[full replacement] implement a state machine for Rx
David Douard <david.douard@logilab.fr>
parents:
16
diff
changeset
|
119 | send_ack(0xCC); |
4fd621551d55
[full replacement] implement a state machine for Rx
David Douard <david.douard@logilab.fr>
parents:
16
diff
changeset
|
120 | return HPSerial::STATE_PAYLOAD_SIZE; |
4fd621551d55
[full replacement] implement a state machine for Rx
David Douard <david.douard@logilab.fr>
parents:
16
diff
changeset
|
121 | break; |
19 | 122 | case 0x55: // EoT |
123 | return HPSerial::STATE_IDLE; | |
124 | break; | |
18
4fd621551d55
[full replacement] implement a state machine for Rx
David Douard <david.douard@logilab.fr>
parents:
16
diff
changeset
|
125 | case 0x66: |
4fd621551d55
[full replacement] implement a state machine for Rx
David Douard <david.douard@logilab.fr>
parents:
16
diff
changeset
|
126 | send_ack(0x99); |
4fd621551d55
[full replacement] implement a state machine for Rx
David Douard <david.douard@logilab.fr>
parents:
16
diff
changeset
|
127 | return HPSerial::STATE_COMMAND; |
4fd621551d55
[full replacement] implement a state machine for Rx
David Douard <david.douard@logilab.fr>
parents:
16
diff
changeset
|
128 | break; |
19 | 129 | case 0xFF: |
130 | return HPSerial::STATE_IDLE; | |
131 | default: // unknown value | |
132 | send_ack(0xFF); | |
133 | return HPSerial::STATE_IDLE; | |
18
4fd621551d55
[full replacement] implement a state machine for Rx
David Douard <david.douard@logilab.fr>
parents:
16
diff
changeset
|
134 | } |
5 | 135 | } |
136 | ||
19 | 137 | HPSerial::state_t HPSerial::do_state_command(uint8_t c) |
18
4fd621551d55
[full replacement] implement a state machine for Rx
David Douard <david.douard@logilab.fr>
parents:
16
diff
changeset
|
138 | { |
4fd621551d55
[full replacement] implement a state machine for Rx
David Douard <david.douard@logilab.fr>
parents:
16
diff
changeset
|
139 | if (c == 0x55) { // EoT |
19 | 140 | return STATE_IDLE; |
18
4fd621551d55
[full replacement] implement a state machine for Rx
David Douard <david.douard@logilab.fr>
parents:
16
diff
changeset
|
141 | } |
5 | 142 | |
19 | 143 | tr_data.cmd = c; |
144 | tr_data.size = 0; | |
145 | tr_data.pos = 0; | |
18
4fd621551d55
[full replacement] implement a state machine for Rx
David Douard <david.douard@logilab.fr>
parents:
16
diff
changeset
|
146 | send_ack(0x00); |
19 | 147 | |
148 | if (c == 0x86) { // shutdown | |
149 | pushCmd(tr_data.cmd, tr_data.size, tr_data.payload); | |
150 | return HPSerial::STATE_IDLE; | |
21 | 151 | } |
19 | 152 | return STATE_PAYLOAD_SIZE; |
18
4fd621551d55
[full replacement] implement a state machine for Rx
David Douard <david.douard@logilab.fr>
parents:
16
diff
changeset
|
153 | } |
5 | 154 | |
19 | 155 | HPSerial::state_t HPSerial::do_state_payload_size(uint8_t c) |
18
4fd621551d55
[full replacement] implement a state machine for Rx
David Douard <david.douard@logilab.fr>
parents:
16
diff
changeset
|
156 | { |
19 | 157 | tr_data.size = c; |
158 | tr_data.pos = 0; | |
18
4fd621551d55
[full replacement] implement a state machine for Rx
David Douard <david.douard@logilab.fr>
parents:
16
diff
changeset
|
159 | send_ack(0x00); |
19 | 160 | return STATE_PAYLOAD; |
5 | 161 | } |
162 | ||
19 | 163 | HPSerial::state_t HPSerial::do_state_payload(uint8_t c) |
18
4fd621551d55
[full replacement] implement a state machine for Rx
David Douard <david.douard@logilab.fr>
parents:
16
diff
changeset
|
164 | { |
19 | 165 | tr_data.payload[tr_data.pos++] = c; |
18
4fd621551d55
[full replacement] implement a state machine for Rx
David Douard <david.douard@logilab.fr>
parents:
16
diff
changeset
|
166 | send_ack(0x00); |
19 | 167 | if (tr_data.pos >= tr_data.size) { |
168 | pushCmd(tr_data.cmd, tr_data.size, tr_data.payload); | |
169 | return HPSerial::STATE_IDLE; | |
18
4fd621551d55
[full replacement] implement a state machine for Rx
David Douard <david.douard@logilab.fr>
parents:
16
diff
changeset
|
170 | } |
4fd621551d55
[full replacement] implement a state machine for Rx
David Douard <david.douard@logilab.fr>
parents:
16
diff
changeset
|
171 | return HPSerial::STATE_PAYLOAD; |
4fd621551d55
[full replacement] implement a state machine for Rx
David Douard <david.douard@logilab.fr>
parents:
16
diff
changeset
|
172 | } |
4fd621551d55
[full replacement] implement a state machine for Rx
David Douard <david.douard@logilab.fr>
parents:
16
diff
changeset
|
173 | |
19 | 174 | HPSerial::state_t HPSerial::do_state_sending(uint8_t c) |
175 | { | |
176 | // ghee | |
177 | if (c == 0xFF) | |
21 | 178 | { // resend current char |
179 | tr_data.pos--; | |
180 | tr_data.payload[tr_data.pos] += 1; | |
181 | } | |
19 | 182 | // TODO: check ACK values (c is the received ack) |
183 | if (tr_data.pos >= tr_data.size) | |
21 | 184 | { |
185 | return do_state_eot(); | |
186 | } | |
19 | 187 | serial.putc(tr_data.payload[tr_data.pos++]); |
188 | set_timer(RXTIMEOUT); | |
189 | return HPSerial::STATE_SENDING; | |
190 | } | |
191 | ||
192 | HPSerial::state_t HPSerial::do_state_eot(uint8_t c) | |
193 | { | |
21 | 194 | serial.putc(0x55); // EoT |
195 | cur_gstate = GSTATE_IDLE; | |
196 | set_timer(); // We are IDLE, detach the timeouter | |
19 | 197 | return STATE_IDLE; |
198 | } | |
199 | ||
18
4fd621551d55
[full replacement] implement a state machine for Rx
David Douard <david.douard@logilab.fr>
parents:
16
diff
changeset
|
200 | HPSerial::state_t HPSerial::run_state(HPSerial::state_t cur_state, |
4fd621551d55
[full replacement] implement a state machine for Rx
David Douard <david.douard@logilab.fr>
parents:
16
diff
changeset
|
201 | uint8_t c) |
4fd621551d55
[full replacement] implement a state machine for Rx
David Douard <david.douard@logilab.fr>
parents:
16
diff
changeset
|
202 | { |
19 | 203 | return (this->*(HPSerial::state_table[cur_state]))(c); |
18
4fd621551d55
[full replacement] implement a state machine for Rx
David Douard <david.douard@logilab.fr>
parents:
16
diff
changeset
|
204 | }; |
4fd621551d55
[full replacement] implement a state machine for Rx
David Douard <david.douard@logilab.fr>
parents:
16
diff
changeset
|
205 | |
5 | 206 | void HPSerial::rxIrq(void) { |
207 | uint8_t val; | |
21 | 208 | if(serial.readable()) |
209 | { // no reason why we would end here without | |
210 | // this condition, but hey | |
8 | 211 | #ifdef DEBUG2 |
5 | 212 | inrx=1; |
213 | #endif | |
21 | 214 | //lled = 1; |
18
4fd621551d55
[full replacement] implement a state machine for Rx
David Douard <david.douard@logilab.fr>
parents:
16
diff
changeset
|
215 | val = serial.getc(); |
19 | 216 | cur_state = run_state(cur_state, val); |
21 | 217 | //lled = 0; |
8 | 218 | #ifdef DEBUG2 |
5 | 219 | inrx=0; |
220 | #endif | |
221 | } | |
222 | } | |
223 | ||
224 | ||
225 | void HPSerial::timeout(void) { | |
19 | 226 | set_timer(); // detach the timeouter |
227 | if (cur_gstate == GSTATE_STARTING) | |
228 | _startup(); | |
229 | else // reset | |
230 | { | |
231 | cur_gstate = GSTATE_IDLE; | |
232 | cur_state = STATE_IDLE; | |
233 | } | |
5 | 234 | } |