src/hp34comm.cpp

changeset 19
a52d60613cf7
parent 18
4fd621551d55
child 21
9ffa9d727d80
equal deleted inserted replaced
18:4fd621551d55 19:a52d60613cf7
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
137 #ifdef DEBUG2 239 #ifdef DEBUG2
138 inrx=1; 240 inrx=1;
139 #endif 241 #endif
140 lled = 1; 242 lled = 1;
141 val = serial.getc(); 243 val = serial.getc();
142 cur_state = run_state(cur_state, &rx_data, val); 244 cur_state = run_state(cur_state, val);
143 lled = 0; 245 lled = 0;
144 #ifdef DEBUG2 246 #ifdef DEBUG2
145 inrx=0; 247 inrx=0;
146 #endif 248 #endif
147 } 249 }
148 } 250 }
149 251
150 252
151 void HPSerial::timeout(void) { 253 void HPSerial::timeout(void) {
152 cur_state = do_state_initial(&rx_data, 0x00); 254 set_timer(); // detach the timeouter
153 } 255 if (cur_gstate == GSTATE_STARTING)
256 _startup();
257 else if (cur_gstate == GSTATE_STARTING2)
258 _startup2();
259 else // reset
260 {
261 cur_gstate = GSTATE_IDLE;
262 cur_state = STATE_IDLE;
263 }
264 }
265
266

mercurial