src/hp34comm.cpp

changeset 5
f1c85c2500f2
child 8
55021f3f1929
equal deleted inserted replaced
4:219766126afb 5:f1c85c2500f2
1 #include "hp34comm.h"
2 #include "mbed.h"
3 #include "CircularBuffer.h"
4
5 /***** HP 34970A communication class ***/
6
7 #define HP_SERIAL_TX PC_7 // serial6 RX
8 #define HP_SERIAL_RX PA_1 // serial4 RX
9
10 #ifdef DEBUG
11
12 DigitalOut inrx(PC_0);
13 DigitalOut intx(PC_1);
14 DigitalOut ack(PC_3);
15 DigitalOut staterx(PC_2);
16 DigitalOut statetx(PH_1);
17
18 #endif
19
20
21 HPSerial::HPSerial():
22 ncmd(0),
23 serial_tx(NC, HP_SERIAL_TX), serial_rx(NC, HP_SERIAL_RX) {
24
25 //pc.printf("HPSerial init\n");
26
27 for(uint8_t i=0; i<MAX_ERRS; i++)
28 errs[i] = 0;
29 reset();
30
31 serial_tx.baud(187500);
32 serial_tx.attach(this, &HPSerial::txIrq, Serial::RxIrq); //sic!
33
34 serial_rx.baud(187500);
35 serial_rx.attach(this, &HPSerial::rxIrq, Serial::RxIrq);
36 }
37
38 bool HPSerial::cmd_available(void) {
39 return !cmdbuf.empty();
40 }
41
42 bool HPSerial::pop(CMD& cmd) {
43 return cmdbuf.pop(cmd);
44 }
45
46 bool HPSerial::cmd_buf_full(void) {
47 return cmdbuf.full();
48 }
49
50 unsigned int HPSerial::nerrors(uint8_t errorno) {
51 return errs[errorno];
52 }
53
54
55
56 void HPSerial::reset(uint8_t errorno) {
57 timeouter.detach();
58 head = 0;
59 tx_state = Idle;
60 setstatedbg();
61 tx_cmd = 0xFF;
62 tx_ack = false;
63 tx_len = 0xFF;
64 memset(buf, 0, BUF_SIZE);
65 if (errorno != 0xFF){
66 errs[errorno]++;
67 }
68
69 }
70
71 void HPSerial::handleAck(uint8_t val) {
72 if ((tx_state == Rx) & (tx_cmd == 0xFF) & (tx_ack == false) & (val == 0x66)) {
73 // special case: keypad does not acknwledge and takes precedence
74 // on the "bus"
75 tx_state = Tx;
76 setstatedbg();
77 } else
78
79 if (tx_ack == true)
80 reset(0);
81
82 else
83 if (tx_cmd == 0xFF) // still at the beginning of a packet, expect 0x99 as ack
84 if (val == 0x99)
85 {
86 tx_ack = true;
87 #ifdef DEBUG
88 ack = 1;
89 wait_us(2);
90 ack = 0;
91 #endif
92 }
93 else
94 reset(1);
95
96 else // expect 0x00 as ack
97 if (val == 0x00)
98 {
99 tx_ack = true;
100 #ifdef DEBUG
101 ack = 1;
102 wait_us(2);
103 ack = 0;
104 wait_us(2);
105 ack = 1;
106 wait_us(2);
107 ack = 0;
108 #endif
109 }
110 else
111 reset(2);
112 }
113
114 void HPSerial::pushCmd(TrState direction, uint8_t cmd, uint8_t size, char *payload) {
115 CMD val;
116 uint8_t i;
117 val.id = ncmd++;
118 val.direction = direction;
119 val.cmd = cmd;
120 val.size = size;
121 for(i=0; i<size; i++)
122 val.value[i] = payload[i];
123 val.value[i] = 0x00;
124 cmdbuf.push(val);
125 }
126
127 void HPSerial::handleChar(uint8_t val) {
128 if (tx_ack == false)
129 reset(3);
130 else // remaining of the state machine
131 if (tx_cmd == 0xFF) {
132 // begin of transmission, expect a cmd
133 tx_cmd = val;
134 tx_ack = false;
135 if (tx_state == Rx)
136 tx_len = 0xFF;
137 else
138 tx_len = 0x00; // no payload: tx_cmd is the key stroke
139 }
140 else if (tx_len == 0xFF) {
141 // got a cmd, expect a payload size
142 tx_len = val;
143 tx_ack = false;
144 }
145 else if (tx_len > 0) {
146 // a payload char
147 buf[head++] = val;
148 tx_len--;
149 tx_ack = false;
150 }
151 else { // end of payload, manage sent content
152 uint8_t cur_state = tx_state;
153 pushCmd(tx_state, tx_cmd, head, buf);
154
155 switch(val) {
156 case 0x66: // a new transmisson
157 reset();
158 tx_state = cur_state;
159 setstatedbg();
160 break;
161 case 0x55:
162 reset();
163 break;
164 default:
165 reset(6);
166 break;
167 }
168 }
169 }
170
171
172
173 void HPSerial::setstatedbg(void) {
174 /*
175 if (tx_state == Rx)
176 staterx = 1;
177 else
178 staterx = 0;
179 if (tx_state == Tx)
180 statetx = 1;
181 else
182 statetx = 0;
183 */
184 }
185
186 void HPSerial::rxIrq(void) {
187 uint8_t val;
188 if(serial_rx.readable()) { // no reason why we would end here without this condition, but hey
189 #ifdef DEBUG
190 inrx=1;
191 #endif
192 val = serial_rx.getc();
193
194 timeouter.attach(this, &HPSerial::timeout, 0.001); // if nothing else happen in the next ms, reset
195
196 if (tx_state == Idle)
197 if (val == 0x66) {
198 // no transmission in progress, expect a start of transmission
199 tx_state = Rx;
200 tx_ack = false;
201 setstatedbg();
202 }
203 else
204 reset(4);
205
206 else if (tx_state == Tx) // manage the acks
207 handleAck(val);
208
209 else
210 handleChar(val);
211 #ifdef DEBUG
212 inrx=0;
213 #endif
214 }
215 }
216
217 void HPSerial::txIrq(void) {
218 uint8_t val;
219 if(serial_tx.readable()) { // no reason why we would end here without this condition, but hey
220 #ifdef DEBUG
221 intx=1;
222 #endif
223 val = serial_tx.getc();
224
225 timeouter.attach(this, &HPSerial::timeout, 0.001); // if nothing else happen in the next ms, reset
226
227 if (tx_state == Idle)
228 if (val == 0x66) {
229 // no transmission in progress, expect a start of transmission
230 tx_state = Tx;
231 tx_ack = false;
232 setstatedbg();
233 }
234 else
235 reset(5);
236
237 else if (tx_state == Rx) // manage the acks
238 handleAck(val);
239
240 else
241 handleChar(val);
242 }
243 #ifdef DEBUG
244 intx=0;
245 #endif
246 }
247
248 void HPSerial::timeout(void) {
249 if (tx_state != Idle) {
250 reset(7);
251 }
252 }

mercurial