src/hp34comm.h~

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

mercurial