1 #include "stdio.h" |
1 #include "stdio.h" |
|
2 |
2 #include "mbed.h" |
3 #include "mbed.h" |
3 #include "string" |
4 #include "string" |
|
5 #include "CircularBuffer.h" |
|
6 |
4 #include "Terminal6x8.h" |
7 #include "Terminal6x8.h" |
5 #include "Mono19x27.h" |
8 #include "Mono19x27.h" |
6 #include "Mono15x22.h" |
9 #include "Mono15x22.h" |
7 #include "Arial12x12.h" |
10 #include "Arial12x12.h" |
8 |
11 |
9 #include "BufferedSerial.h" |
|
10 |
|
11 #include "SSD1322.h" |
12 #include "SSD1322.h" |
12 |
13 |
13 Serial pc(USBTX, USBRX); |
14 Serial pc(USBTX, USBRX); |
14 BufferedSerial hp(NC, PA_1, 64, 0); // serial4 |
15 |
|
16 //BufferedSerial hp(NC, PA_1, 64, 0); // serial4 |
|
17 #define HP_SERIAL_TX PC_7 // serial6 RX |
|
18 #define HP_SERIAL_RX PA_1 // serial4 RX |
15 |
19 |
16 SSD1322 dsp(SPI_8, 10000000, PB_15, PB_14, PB_13, PB_12, D11, D12, "SSD1322", 256, 64); |
20 SSD1322 dsp(SPI_8, 10000000, PB_15, PB_14, PB_13, PB_12, D11, D12, "SSD1322", 256, 64); |
17 |
21 |
18 #define MAX_BUFF 14 |
22 #define BUF_SIZE 32 |
|
23 #define MAX_BUFF 15 |
|
24 #define MAX_ERRS 10 |
19 uint8_t curchar; |
25 uint8_t curchar; |
20 uint8_t cmd; |
26 uint8_t cmd; |
21 uint8_t nchars; |
27 uint8_t nchars; |
22 char buffer[MAX_BUFF+1]; |
28 char buffer[MAX_BUFF+1]; |
23 |
29 |
135 #else |
141 #else |
136 inline void DebugPulse(uint8_t count=1) |
142 inline void DebugPulse(uint8_t count=1) |
137 {} |
143 {} |
138 #endif |
144 #endif |
139 |
145 |
|
146 |
|
147 |
|
148 /***** HP 34970A communication class ***/ |
|
149 |
|
150 class HPSerial { |
|
151 |
|
152 public: |
|
153 enum TrState { |
|
154 Idle = 0, |
|
155 Tx, |
|
156 Rx, |
|
157 }; |
|
158 typedef struct _CMD |
|
159 { |
|
160 TrState direction; |
|
161 uint8_t cmd; |
|
162 uint8_t size; |
|
163 char value[MAX_BUFF+1]; |
|
164 unsigned long id; |
|
165 } CMD; |
|
166 |
|
167 |
|
168 |
|
169 HPSerial(): ncmd(0), serial_tx(NC, HP_SERIAL_TX), serial_rx(NC, HP_SERIAL_RX) { |
|
170 pc.printf("HPSerial init\n"); |
|
171 for(uint8_t i=0; i<MAX_ERRS; i++) |
|
172 errs[i] = 0; |
|
173 reset(); |
|
174 |
|
175 serial_tx.baud(187500); |
|
176 serial_tx.attach(this, &HPSerial::txIrq, Serial::RxIrq); //sic! |
|
177 |
|
178 serial_rx.baud(187500); |
|
179 serial_rx.attach(this, &HPSerial::rxIrq, Serial::RxIrq); |
|
180 } |
|
181 |
|
182 bool cmd_available(void) { |
|
183 return !cmdbuf.empty(); |
|
184 } |
|
185 |
|
186 bool pop(CMD& cmd) { |
|
187 return cmdbuf.pop(cmd); |
|
188 } |
|
189 |
|
190 bool cmd_buf_full(void) { |
|
191 return cmdbuf.full(); |
|
192 } |
|
193 |
|
194 unsigned int nerrors(uint8_t errorno) { |
|
195 return errs[errorno]; |
|
196 } |
|
197 |
|
198 |
|
199 |
|
200 private: |
|
201 void reset(uint8_t errorno=0xFF) { |
|
202 head = 0; |
|
203 tx_state = Idle; |
|
204 tx_cmd = 0xFF; |
|
205 tx_ack = false; |
|
206 tx_len = 0xFF; |
|
207 memset(buf, 0, BUF_SIZE); |
|
208 if (errorno != 0xFF) |
|
209 errs[errorno]++; |
|
210 } |
|
211 |
|
212 void handleAck(uint8_t val) { |
|
213 if (tx_ack == true) |
|
214 reset(0); |
|
215 |
|
216 else |
|
217 if (tx_cmd == 0xFF) // still at the beginning of a packet, expect 0x99 as ack |
|
218 if (val == 0x99) |
|
219 tx_ack = true; |
|
220 else |
|
221 reset(1); |
|
222 |
|
223 else // expect 0x00 as ack |
|
224 if (val == 0x00) |
|
225 tx_ack = true; |
|
226 else |
|
227 reset(2); |
|
228 } |
|
229 |
|
230 void pushCmd(TrState direction, uint8_t cmd, uint8_t size, char *payload) { |
|
231 CMD val; |
|
232 uint8_t i; |
|
233 val.id = ncmd++; |
|
234 val.direction = direction; |
|
235 val.cmd = cmd; |
|
236 val.size = size; |
|
237 for(i=0; i<size; i++) |
|
238 val.value[i] = payload[i]; |
|
239 val.value[i] = 0x00; |
|
240 cmdbuf.push(val); |
|
241 } |
|
242 |
|
243 void handleChar(uint8_t val) { |
|
244 if (tx_ack == false) |
|
245 reset(3); |
|
246 else // remaining of the state machine |
|
247 if (tx_cmd == 0xFF) { |
|
248 // begin of transmission, expect a cmd |
|
249 tx_cmd = val; |
|
250 tx_ack = false; |
|
251 tx_len = 0xFF; |
|
252 } |
|
253 else if (tx_len == 0xFF) { |
|
254 // got a cmd, expect a payload size |
|
255 tx_len = val; |
|
256 tx_ack = false; |
|
257 } |
|
258 else if (tx_len > 0) { |
|
259 // a payload char |
|
260 buf[head++] = val; |
|
261 tx_len--; |
|
262 tx_ack = false; |
|
263 } |
|
264 else { |
|
265 uint8_t cur_state = tx_state; |
|
266 pushCmd(tx_state, tx_cmd, head, buf); |
|
267 reset(); |
|
268 |
|
269 if (val != 0x55) { // not an end of transmission |
|
270 // should be another cmd I think |
|
271 tx_cmd = val; |
|
272 tx_state = cur_state; |
|
273 } |
|
274 } |
|
275 } |
|
276 |
|
277 |
|
278 void rxIrq(void) { |
|
279 uint8_t val; |
|
280 if(serial_rx.readable()) { // no reason why we would end here without this condition, but hey |
|
281 val = serial_rx.getc(); |
|
282 |
|
283 if (tx_state == Idle) |
|
284 if (val == 0x66) { |
|
285 // no transmission in progress, expect a start of transmission |
|
286 tx_state = Rx; |
|
287 tx_ack = false; |
|
288 } |
|
289 else |
|
290 reset(4); |
|
291 |
|
292 else if (tx_state == Tx) // manage the acks |
|
293 handleAck(val); |
|
294 |
|
295 else |
|
296 handleChar(val); |
|
297 } |
|
298 } |
|
299 |
|
300 void txIrq(void) { |
|
301 uint8_t val; |
|
302 if(serial_tx.readable()) { // no reason why we would end here without this condition, but hey |
|
303 val = serial_tx.getc(); |
|
304 |
|
305 if (tx_state == Idle) |
|
306 if (val == 0x66) { |
|
307 // no transmission in progress, expect a start of transmission |
|
308 tx_state = Tx; |
|
309 tx_ack = false; |
|
310 } |
|
311 else |
|
312 reset(5); |
|
313 |
|
314 else if (tx_state == Rx) // manage the acks |
|
315 handleAck(val); |
|
316 |
|
317 else |
|
318 handleChar(val); |
|
319 } |
|
320 } |
|
321 |
|
322 private: |
|
323 RawSerial serial_tx; |
|
324 RawSerial serial_rx; |
|
325 uint8_t buf[BUF_SIZE]; |
|
326 uint8_t head; |
|
327 uint8_t tx_state; |
|
328 uint8_t tx_cmd; |
|
329 uint8_t tx_len; |
|
330 bool tx_ack; |
|
331 CircularBuffer<CMD, 32> cmdbuf; |
|
332 unsigned long ncmd; |
|
333 unsigned int errs[MAX_ERRS]; |
|
334 }; |
|
335 |
|
336 |
|
337 HPSerial hp; |
|
338 Ticker dsp_refresher; |
|
339 volatile bool must_refresh; |
|
340 |
|
341 void copy_to_lcd(void); |
140 void test_dsp(); |
342 void test_dsp(); |
141 |
343 |
142 void setup() { |
344 void setup() { |
143 // init the LCD |
345 // init the LCD |
144 |
346 |
145 //dsp.set_orientation(3); |
347 //dsp.set_orientation(3); |
146 pc.baud (115200); |
348 pc.baud (115200); |
147 pc.printf("\n\nSystem Core Clock = %.3f MHZ\r\n", |
349 pc.printf("\n\nSystem Core Clock = %.3f MHZ\r\n", |
148 (float)SystemCoreClock/1000000); |
350 (float)SystemCoreClock/1000000); |
149 |
|
150 hp.baud(187500); |
|
151 |
351 |
152 // myLCD.set_font((unsigned char*) Terminal6x8); |
352 // myLCD.set_font((unsigned char*) Terminal6x8); |
153 // myLCD.claim(stdout); // send stdout to the LCD display |
353 // myLCD.claim(stdout); // send stdout to the LCD display |
154 // myLCD.claim(stderr); // send stderr to the LCD display |
354 // myLCD.claim(stderr); // send stderr to the LCD display |
155 dsp.background(Black); // set background to black |
355 dsp.background(Black); // set background to black |
171 dsp.printf("Lg %d", i+1); |
372 dsp.printf("Lg %d", i+1); |
172 } |
373 } |
173 dsp.copy_to_lcd(); |
374 dsp.copy_to_lcd(); |
174 wait(2); |
375 wait(2); |
175 dsp.cls(); |
376 dsp.cls(); |
|
377 |
|
378 dsp_refresher.attach(©_to_lcd, 0.1); |
176 test_dsp(); |
379 test_dsp(); |
177 wait(2); |
380 wait(2); |
178 dsp.cls(); |
381 dsp.cls(); |
179 } |
382 |
180 |
383 } |
181 void go_msg() { |
384 |
182 dsp.set_font((unsigned char*) Arial12x12); |
385 void copy_to_lcd(void) { |
183 dsp.locate(0, 38); |
386 if (must_refresh) |
|
387 dsp.copy_to_lcd(); |
184 } |
388 } |
185 |
389 |
186 void show(uint8_t cmd, char *txt, uint8_t nchar=0) { |
390 void show(uint8_t cmd, char *txt, uint8_t nchar=0) { |
187 uint8_t i, len; |
391 uint8_t i, len; |
188 uint16_t bgcolor, fgcolor; |
392 uint16_t bgcolor, fgcolor; |
189 char *oldv; |
393 char *oldv; |
190 |
394 |
|
395 must_refresh = false; |
|
396 |
191 len = MAX_BUFF; |
397 len = MAX_BUFF; |
192 |
398 |
193 for (i=0; i<sizeof(table)/sizeof(table[0]); ++i) { |
399 for (i=0; i<sizeof(table)/sizeof(table[0]); ++i) { |
194 if (table[i].cmd == cmd) { |
400 if (table[i].cmd == cmd) { |
195 bgcolor = table[i].bgcolor; |
401 bgcolor = table[i].bgcolor; |
264 case 4: //ignore |
470 case 4: //ignore |
265 break; |
471 break; |
266 } |
472 } |
267 } |
473 } |
268 } |
474 } |
269 dsp.copy_to_lcd(); |
475 must_refresh = true; |
270 |
476 //dsp.copy_to_lcd(); |
271 } |
477 } |
272 |
478 |
273 void test_dsp() |
479 void test_dsp() |
274 { |
480 { |
275 show(0x00, "8g8g8g8g8g8g8", 13); // main dsp |
481 show(0x00, "8g8g8g8g8g8g8", 13); // main dsp |
276 show(0x0C, "888", 3); // channel dsp |
482 show(0x0C, "888", 3); // channel dsp |
277 show(0x0A, "\xFF\xFF\xFF\xFF", 4); // flags |
483 show(0x0A, "\xFF\xFF\xFF\xFF", 4); // flags |
278 dsp.copy_to_lcd(); |
|
279 } |
484 } |
280 |
485 |
281 |
486 |
282 void loop() { // run over and over |
487 void loop() { // run over and over |
283 if (hp.readable()) { |
488 if (hp.cmd_available()) |
284 uint8_t val = hp.getc(); |
489 { |
285 DebugPulse(3); |
490 HPSerial::CMD cmd; |
286 // 0xFF: idle |
491 if (hp.pop(cmd)) |
287 // 0xFE: frame finished |
492 { |
288 // 0x66: Start of transmission received |
493 pc.printf("CMD[%s:%d %d/%d/%d/%d/%d/%d] %X\n", (cmd.direction==HPSerial::Rx)?"Rx":"Tx", cmd.id, |
289 pc.printf(" VAL=0x%X\tCMD=0x%X\n", val, cmd); |
494 hp.nerrors(0), |
290 if (cmd == 0xFF) { |
495 hp.nerrors(1), |
291 if ((val == 0x66) || (val == 0x99)) { |
496 hp.nerrors(2), |
292 cmd = val; |
497 hp.nerrors(3), |
293 } else if ((val == 0x00) || (val == 0x55)){ |
498 hp.nerrors(4), |
294 // probably an ACK for a keypad related event |
499 hp.nerrors(5), |
295 } else { |
500 cmd.cmd); |
296 // display "junk" byte |
501 |
297 //DebugPulse(); |
502 if (cmd.direction == HPSerial::Rx) { |
298 show(0xFF, "", 0); |
503 if ((cmd.cmd == 0x00) || (cmd.cmd == 0x0C)) |
299 dsp.printf("%02X:> %02x", cmd, val); |
504 pc.printf(" data=%s\n", cmd.value); |
300 } |
505 show(cmd.cmd, cmd.value, cmd.size); |
301 |
506 |
302 } else if (cmd == 0xFE ) { |
507 } |
303 if ((val == 0x66) || (val == 0x99)) { |
508 } |
304 cmd = val; |
509 } |
305 } else if (val == 0x55) { |
|
306 cmd = 0xFF; |
|
307 } else if (val == 0x00){ |
|
308 // probably an ACK for a keypad related event |
|
309 } else { |
|
310 // display "junk" byte |
|
311 DebugPulse(); |
|
312 show(0xFF, "", 5); |
|
313 dsp.printf("%02X=> %02x", cmd, val); |
|
314 } |
|
315 |
|
316 } else if (cmd == 0x66) { // waiting for the display command |
|
317 if ((val == 0x0C) || (val == 0x00) || (val == 0x01) || (val == 0x02) || (val == 0x0A)) { |
|
318 cmd = val; |
|
319 nchars = 0; |
|
320 } else { |
|
321 cmd = 0xFE; |
|
322 // display unknown cmd byte |
|
323 DebugPulse(); |
|
324 show(0xFF, "", 10); |
|
325 dsp.printf("%02X-> %02x", cmd, val); |
|
326 } |
|
327 |
|
328 } else if (cmd == 0x99) { // waiting for a 0x00, it's the DP that sent a keypress event |
|
329 if (val != 0x00) { |
|
330 show(0xFF, "", 0); |
|
331 dsp.printf("%02X kp %02X", cmd, val); |
|
332 } |
|
333 cmd = 0xFF; |
|
334 |
|
335 } else if (nchars == 0) { // waiting for the number of chars to display |
|
336 if (val>MAX_BUFF) { |
|
337 // display warning |
|
338 //dsp(); |
|
339 //dsp << cmd << " got len " << val; |
|
340 //DebugPulse(); |
|
341 show(0xFF, "", 0); |
|
342 dsp.printf("%02X len %d", cmd, val); |
|
343 cmd = 0xFE; // weird |
|
344 } else { |
|
345 nchars = val; |
|
346 curchar = 0; |
|
347 } |
|
348 |
|
349 } else { // a character to display |
|
350 buffer[curchar] = val; |
|
351 curchar++; |
|
352 if (curchar == nchars) { |
|
353 buffer[curchar] = 0x00; |
|
354 show(cmd, buffer, nchars); |
|
355 nchars = 0; |
|
356 curchar = 0; |
|
357 cmd = 0xFE; |
|
358 } |
|
359 } |
|
360 |
|
361 DebugPulse(4); |
|
362 |
|
363 } |
|
364 } |
510 } |
365 |
511 |
366 int main() |
512 int main() |
367 { |
513 { |
368 setup(); |
514 setup(); |