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