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