src/hp34comm.cpp

changeset 44
b3c3d54d2c7c
parent 39
63c6a720cb97
child 47
11c57010e4f9
equal deleted inserted replaced
43:c850674a3101 44:b3c3d54d2c7c
3 #include <mbed.h> 3 #include <mbed.h>
4 #include <CircularBuffer.h> 4 #include <CircularBuffer.h>
5 5
6 /***** HP 34970A communication class ***/ 6 /***** HP 34970A communication class ***/
7 7
8 #ifdef DEBUG2
9
10 DigitalOut inrx(D9);
11
12 #endif
13
14 DigitalOut lled(LED3);
15
16 #define RXTIMEOUT 50ms 8 #define RXTIMEOUT 50ms
17 #define STARTUPRETRY 0.5 9 #define STARTUPRETRY 0.5
18 10
19 uint8_t startup_seq[] = { 11 uint8_t startup_seq[] = {
20 0x33, 12 0x33,
21 0x02, 13 0x02, // 0x02?
22 0x00, 14 0x00,
23 0x00, // to be replaced by the actual keycode, if any 15 0x00,
24 }; 16 };
25 17
26 HPSerial::statemethod HPSerial::state_table[NUM_STATES] = { 18 HPSerial::statemethod HPSerial::state_table[NUM_STATES] = {
27 &HPSerial::do_state_initial, 19 &HPSerial::do_state_initial, // STATE_IDLE
28 &HPSerial::do_state_command, 20 &HPSerial::do_state_command, // STATE_COMMAND
29 &HPSerial::do_state_payload_size, 21 &HPSerial::do_state_payload_size, // STATE_PAYLOAD_SIZE
30 &HPSerial::do_state_payload, 22 &HPSerial::do_state_payload, // STATE_PAYLOAD
31 &HPSerial::do_state_sending, 23 &HPSerial::do_state_sending, // STATE_SENDING
32 &HPSerial::do_state_eot,
33 }; 24 };
34 25
35 26
36 HPSerial::HPSerial(PinName tx, PinName rx): 27 HPSerial::HPSerial(PinName tx, PinName rx):
37 serial(tx, rx), 28 serial(tx, rx),
38 ncmd(0), 29 ncmd(0),
39 cur_gstate(GSTATE_IDLE) 30 cur_gstate(GSTATE_IDLE)
40 { 31 {
41 serial.baud(187500); 32 serial.baud(187500);
33 serial.format(8, BufferedSerial::Even, 1);
42 cur_state = STATE_IDLE; 34 cur_state = STATE_IDLE;
43 serial.attach(callback(this, &HPSerial::rxIrq), SerialBase::RxIrq); 35 serial.attach(callback(this, &HPSerial::rx_irq), SerialBase::RxIrq);
44 } 36 }
45 37
46 void HPSerial::startup(uint8_t keycode) { 38 void HPSerial::startup(uint8_t keycode) {
39 cur_gstate = GSTATE_STARTING;
40
47 if (keycode != 0xFF) { 41 if (keycode != 0xFF) {
48 startup_sed[2] = 0xFF; 42 printf("Set startup keycode to %X\n", keycode);
49 startup_sed[3] = keycode; 43 startup_seq[2] = 0xFF;
50 } 44 startup_seq[3] = keycode;
51 45 }
52 cur_gstate = GSTATE_STARTING; 46 else
47 startup_seq[2] = 0x00;
53 set_timer(10ms); // launch the startup in 10ms 48 set_timer(10ms); // launch the startup in 10ms
54 } 49 }
55 50
56 void HPSerial::_startup(void) 51 void HPSerial::_startup(void)
57 { 52 {
63 tr_data.size = 4; 58 tr_data.size = 4;
64 else 59 else
65 tr_data.size = 3; // sizeof(startup_seq); 60 tr_data.size = 3; // sizeof(startup_seq);
66 for(uint8_t i=0; i<tr_data.size; i++) 61 for(uint8_t i=0; i<tr_data.size; i++)
67 tr_data.payload[i] = startup_seq[i]; 62 tr_data.payload[i] = startup_seq[i];
68
69 cur_state = do_state_sending(); 63 cur_state = do_state_sending();
70 } 64 }
71 65
72 void HPSerial::sendkey(uint8_t keycode) 66 void HPSerial::sendkey(uint8_t keycode)
73 { 67 {
74 tr_data.size = 2; 68 if (!sendbuf.full())
75 tr_data.cmd = 0xFF; 69 sendbuf.push(keycode);
76 tr_data.pos = 0; 70 }
77 tr_data.payload[0] = 0x66; 71
78 tr_data.payload[1] = keycode; 72 void HPSerial::send_key_when_idle() {
79 cur_state = do_state_sending(); 73 if (!sendbuf.empty() && cur_gstate == GSTATE_IDLE)
74 {
75 uint8_t keycode;
76 cur_gstate = GSTATE_TX;
77 sendbuf.pop(keycode);
78 tr_data.size = 2;
79 tr_data.cmd = 0xFF;
80 tr_data.pos = 0;
81 tr_data.payload[0] = 0x66;
82 tr_data.payload[1] = keycode;
83 cur_state = do_state_sending();
84 }
80 } 85 }
81 86
82 bool HPSerial::cmd_available(void) 87 bool HPSerial::cmd_available(void)
83 { 88 {
84 return !cmdbuf.empty(); 89 return !cmdbuf.empty();
110 val.value[i] = 0x00; 115 val.value[i] = 0x00;
111 cmdbuf.push(val); 116 cmdbuf.push(val);
112 } 117 }
113 118
114 void HPSerial::send_ack(uint8_t c) { 119 void HPSerial::send_ack(uint8_t c) {
115 serial.write(&c, 1); 120 serial.write(&c, 1);
116 set_timer(RXTIMEOUT); // if nothing else happen in the next ms, reset 121 set_timer(RXTIMEOUT); // if nothing else happen in the next RXTIMEOUT ms, reset
117 } 122 }
118 123
119 HPSerial::state_t HPSerial::do_state_initial(uint8_t c) 124 HPSerial::state_t HPSerial::do_state_initial(uint8_t c)
120 { 125 {
121 // we are idle, incoming char is a handcheck 126 // we are idle, incoming char is a handcheck
122 // knwon handcheck values are 0x66 and 0x33 127 // knwon handcheck values are 0x66 and 0x33
123 set_timer(RXTIMEOUT); // reset the watchdog 128 set_timer(RXTIMEOUT); // reset the watchdog
124 switch (c) { 129 switch (c) {
125 case 0x33: 130 case 0x33: // XXX? when are we expecting a 0x33 here?
126 send_ack(0xCC); 131 send_ack(0xCC);
127 return HPSerial::STATE_PAYLOAD_SIZE; 132 return HPSerial::STATE_PAYLOAD_SIZE;
128 break; 133 break;
129 case 0x55: // EoT 134 case 0x55: // EoT
130 return HPSerial::STATE_IDLE; 135 return HPSerial::STATE_IDLE;
171 { 176 {
172 tr_data.payload[tr_data.pos++] = c; 177 tr_data.payload[tr_data.pos++] = c;
173 send_ack(0x00); 178 send_ack(0x00);
174 if (tr_data.pos >= tr_data.size) { 179 if (tr_data.pos >= tr_data.size) {
175 pushCmd(tr_data.cmd, tr_data.size, tr_data.payload); 180 pushCmd(tr_data.cmd, tr_data.size, tr_data.payload);
176 return HPSerial::STATE_IDLE; 181 return STATE_IDLE;
177 } 182 }
178 return HPSerial::STATE_PAYLOAD; 183 return STATE_PAYLOAD;
179 } 184 }
180 185
181 HPSerial::state_t HPSerial::do_state_sending(uint8_t c) 186 HPSerial::state_t HPSerial::do_state_sending(uint8_t c)
182 { 187 {
183 // ghee 188 // ghee
184 if (c == 0xFF) 189 if (c == 0xFF)
185 { // resend current char 190 { // resend current char
186 tr_data.pos--; 191 tr_data.pos--;
187 tr_data.payload[tr_data.pos] += 1;
188 } 192 }
189 // TODO: check ACK values (c is the received ack) 193 // TODO: check ACK values (c is the received ack)
190 if (tr_data.pos >= tr_data.size) 194 if (tr_data.pos >= tr_data.size)
191 { 195 {
192 return do_state_eot(); 196 c = 0x55;
193 } 197 serial.write(&c, 1); // EoT
194 serial.write(&tr_data.payload[tr_data.pos++], 1); 198 cur_gstate = GSTATE_IDLE;
195 set_timer(RXTIMEOUT); 199 set_timer(); // We are IDLE, detach the timeouter
196 return HPSerial::STATE_SENDING; 200 return STATE_IDLE;
197 } 201 }
198 202 else
199 HPSerial::state_t HPSerial::do_state_eot(uint8_t c) 203 {
200 { 204 serial.write(&tr_data.payload[tr_data.pos++], 1);
201 serial.write(&c, 1); // EoT 205 set_timer(RXTIMEOUT);
202 cur_gstate = GSTATE_IDLE; 206 return STATE_SENDING;
203 set_timer(); // We are IDLE, detach the timeouter 207 }
204 return STATE_IDLE;
205 } 208 }
206 209
207 HPSerial::state_t HPSerial::run_state(HPSerial::state_t cur_state, 210 HPSerial::state_t HPSerial::run_state(HPSerial::state_t cur_state,
208 uint8_t c) 211 uint8_t c)
209 { 212 {
210 return (this->*(HPSerial::state_table[cur_state]))(c); 213 return (this->*(HPSerial::state_table[cur_state]))(c);
211 }; 214 };
212 215
213 void HPSerial::rxIrq(void) { 216 void HPSerial::rx_irq(void) {
214 uint8_t val; 217 uint8_t val;
215 if(serial.readable()) 218 if(serial.readable())
216 { // no reason why we would end here without 219 { // no reason why we would end here without
217 // this condition, but hey 220 // this condition, but hey
218 #ifdef DEBUG2 221 if (cur_gstate == GSTATE_IDLE)
219 inrx=1; 222 // occurs when the CPU starts a new transmission
220 #endif 223 // at this point, cur_state should be STATE_IDLE also (TODO add a check?)
221 //lled = 1; 224 cur_gstate = GSTATE_RX;
222 //val = serial.getc();
223 serial.read(&val, 1); 225 serial.read(&val, 1);
224 cur_state = run_state(cur_state, val); 226 cur_state = run_state(cur_state, val);
225 //lled = 0;
226 #ifdef DEBUG2
227 inrx=0;
228 #endif
229 } 227 }
230 } 228 }
231 229
232 230
233 void HPSerial::timeout(void) { 231 void HPSerial::timeout(void) {
234 set_timer(); // detach the timeouter 232 set_timer(); // detach the timeouter
235 if (cur_gstate == GSTATE_STARTING) 233 if (cur_gstate == GSTATE_STARTING)
236 _startup(); 234 _startup();
237 else // reset 235 else // CPU took too long to reply, reset
238 { 236 {
239 cur_gstate = GSTATE_IDLE; 237 cur_gstate = GSTATE_IDLE;
240 cur_state = STATE_IDLE; 238 cur_state = STATE_IDLE;
241 } 239 }
242 } 240 }

mercurial