src/main.cpp

changeset 5
f1c85c2500f2
parent 4
219766126afb
child 7
5cf4034ba4e0
equal deleted inserted replaced
4:219766126afb 5:f1c85c2500f2
1 #include "stdio.h" 1 #include "stdio.h"
2 2
3 #include "mbed.h" 3 #include "mbed.h"
4 #include "rtos.h"
4 #include "string" 5 #include "string"
5 #include "CircularBuffer.h"
6 6
7 #include "Terminal6x8.h" 7 #include "Terminal6x8.h"
8 #include "Mono19x27.h" 8 #include "Mono19x27.h"
9 #include "Mono15x22.h" 9 #include "Mono15x22.h"
10 #include "Arial12x12.h" 10 #include "Arial12x12.h"
11 11
12 #include "SSD1322.h" 12 #include "SSD1322.h"
13 #include "hp34comm.h"
13 14
14 Serial pc(USBTX, USBRX); 15 Serial pc(USBTX, USBRX);
15 16
16 //BufferedSerial hp(NC, PA_1, 64, 0); // serial4 17 #define DEBUG
17 #define HP_SERIAL_TX PC_7 // serial6 RX 18
18 #define HP_SERIAL_RX PA_1 // serial4 RX 19 SSD1322 dsp(SPI_8, 20000000, PB_15, PB_14, PB_13, PB_12, D11, D12, "SSD1322", 256, 64);
19 20
20 SSD1322 dsp(SPI_8, 10000000, PB_15, PB_14, PB_13, PB_12, D11, D12, "SSD1322", 256, 64); 21
21
22 #define BUF_SIZE 32
23 #define MAX_BUFF 15
24 #define MAX_ERRS 10
25 uint8_t curchar; 22 uint8_t curchar;
26 uint8_t cmd; 23 uint8_t cmd;
27 uint8_t nchars; 24 uint8_t nchars;
28 char buffer[MAX_BUFF+1]; 25 char buffer[MAX_BUFF+1];
29 26
32 uint8_t cmd; 29 uint8_t cmd;
33 uint8_t color; 30 uint8_t color;
34 uint8_t bgcolor; 31 uint8_t bgcolor;
35 uint8_t x0; 32 uint8_t x0;
36 uint8_t y0; 33 uint8_t y0;
37 uint8_t fmt; // 0=>ascii, 1=>hex, 2=>bits, 3=>flags 34 uint8_t fmt; // 0x01=>ascii, 0x02=>hex, 0x04=>bits, 0x08=>flags, 0x80=>ignore
38 uint8_t maxsize; 35 uint8_t maxsize;
39 uint8_t width; 36 uint8_t width;
40 const unsigned char* font; 37 const unsigned char* font;
41 char buffer[MAX_BUFF+1]; 38 char buffer[MAX_BUFF+1];
42 } DSP; 39 } DSP;
43 40
44 static DSP table[] = 41 static DSP table[] =
45 { 42 {
46 { 0x00, 0xF, 0x0, 0, 0, 0, MAX_BUFF, 245, Mono19x27}, // main display 43 { 0x00, 0xF, 0x0, 0, 0, 0x01, MAX_BUFF, 245, Mono19x27}, // main display
47 { 0x0C, 0xF, 0x0,204, 38, 0, 3, 45, Mono15x22}, // channels display 44 { 0x0C, 0xF, 0x0,204, 38, 0x01, 3, 45, Mono15x22}, // channels display
48 { 0x01, 0xF, 0x0, 0, 0, 4, MAX_BUFF, 0, Terminal6x8}, 45 { 0x01, 0xF, 0x0, 0, 0, 0x80, MAX_BUFF, 0, Terminal6x8},
49 { 0x02, 0xF, 0x0, 0, 0, 4, MAX_BUFF, 0, Terminal6x8}, 46 { 0x02, 0xF, 0x0, 0, 0, 0x80, MAX_BUFF, 0, Terminal6x8},
50 { 0x0A, 0xF, 0x0, 0, 57, 2, 4, 0, Terminal6x8}, 47 { 0x0A, 0xF, 0x0, 0, 57, 0x0C, 4, 0, Terminal6x8}, // flags + bits
51 { 0x0A, 0xF, 0x0, 0, 0, 3, 4, 0, Terminal6x8}, // flags 48 { 0xFF, 0xF, 0x0, 0, 0, 0x80, MAX_BUFF, 0, Terminal6x8},
52 { 0xFF, 0xF, 0x0, 0, 0, 4, MAX_BUFF, 0, Terminal6x8},
53 }; 49 };
54 50
55 // 9x10 51 // 9x10
56 const unsigned char icon_alarm[] __attribute__((aligned (2))) = 52 const unsigned char icon_alarm[] __attribute__((aligned (2))) =
57 { 53 {
91 } FLAG; 87 } FLAG;
92 88
93 static const FLAG flags[] = 89 static const FLAG flags[] =
94 { 90 {
95 //{ 0x00, 160, 30, "Alarm"}, // for the 'alarm' box 91 //{ 0x00, 160, 30, "Alarm"}, // for the 'alarm' box
96 { 0x00, 246, 0, NULL, icon_alarm}, // F1.1 92 { 0x00, 246, 0, NULL, icon_alarm}, // F1.1
97 { 0x01, 246, 11, NULL, icon_curve}, // F1.2 93 { 0x01, 246, 11, NULL, icon_curve}, // F1.2
98 { 0x03, 204, 30, "Channel"}, // F1.4 94 { 0x03, 204, 30, "Channel"}, // F1.4
99 { 0x14, 68, 44, "4W"}, // F2.5 95 { 0x14, 68, 44, "4W"}, // F2.5
100 { 0x33, 40, 44, "VIEW"}, // F4.4 96 { 0x32, 40, 44, "*"}, // F4.3
101 { 0x34, 0, 30, "MON"}, // F4.5 97 { 0x33, 40, 44, "VIEW"}, // F4.4
102 { 0x36, 0, 44, "CONFIG"}, // F4.7 98 { 0x34, 0, 30, "MON"}, // F4.5
103 99 { 0x35, 0, 44, "SCAN"}, // F4.6
104 { 0xFF, 0, 0, "SCAN"}, // F4.6 or F4.3 100 { 0x36, 0, 44, "CONFIG"}, // F4.7
105 { 0xFF, 0, 0, "*"}, 101
106 { 0xFF, 0, 0, "ADRS"}, 102 { 0xFF, 0, 0, "ADRS"},
107 { 0xFF, 0, 0, "RMT"}, 103 { 0xFF, 0, 0, "RMT"},
108 { 0xFF, 0, 0, "ERROR"}, 104 { 0xFF, 0, 0, "ERROR"},
109 { 0xFF, 0, 0, "EXT"}, 105 { 0xFF, 0, 0, "EXT"},
110 { 0xFF, 0, 0, "ONCE"}, 106 { 0xFF, 0, 0, "ONCE"},
123 { 0xFF, 0, 0, "4"}, 119 { 0xFF, 0, 0, "4"},
124 { 0xFF, 0, 0, "L"}, 120 { 0xFF, 0, 0, "L"},
125 121
126 }; 122 };
127 123
124 typedef struct _FRAME
125 {
126 uint8_t flag;
127 uint8_t x0;
128 uint8_t y0;
129 uint8_t x1;
130 uint8_t y1;
131 } FRAME;
132
133 static const FRAME frames[] =
134 {
135 { 0x02, 203, 35, 248, 55}, // F1.3
136 };
137
128 138
129 #ifdef DEBUG 139 #ifdef DEBUG
130 #define DBGPIN PC_0 140 #define DBGPIN PC_0
131 141
132 DigitalOut dbgpin(DBGPIN); 142 DigitalOut dbgpin(DBGPIN);
133 inline void DebugPulse(uint8_t count=1) 143 inline void pulse(uint8_t count=1, bool stayup=false)
134 { 144 {
145 dbgpin = 0;
146 wait_us(2);
135 while (count--) 147 while (count--)
136 { 148 {
137 dbgpin = 1; 149 dbgpin = 1;
138 dbgpin = 0; 150 wait_us(2);
139 } 151 dbgpin = 0;
152 wait_us(2);
153 }
154 if (stayup)
155 dbgpin = 1;
156
140 } 157 }
141 #else 158 #else
142 inline void DebugPulse(uint8_t count=1) 159 inline void pulse(uint8_t count=1, bool stayup=false)
143 {} 160 {}
144 #endif 161 #endif
145 162
146 163
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; 164 HPSerial hp;
338 Ticker dsp_refresher;
339 volatile bool must_refresh; 165 volatile bool must_refresh;
166 Thread tdsp, tloop;
340 167
341 void copy_to_lcd(void); 168 void copy_to_lcd(void);
342 void test_dsp(); 169 void test_dsp();
343 170
344 void setup() { 171 void setup() {
360 187
361 cmd = 0xFF; 188 cmd = 0xFF;
362 curchar = 0; 189 curchar = 0;
363 nchars = 0; 190 nchars = 0;
364 191
365 192 for (uint8_t i=0; i<sizeof(table)/sizeof(table[0]); ++i)
193 memset(table[i].buffer, 0, MAX_BUFF+1);
194
366 dsp.printf("HP34970A"); 195 dsp.printf("HP34970A");
367 dsp.set_font(Terminal6x8); 196 dsp.set_font(Terminal6x8);
368 for(uint8_t i=0; i<4; i++) { 197 for(uint8_t i=0; i<4; i++) {
369 dsp.locate(160, i*8); 198 dsp.locate(160, i*8);
370 dsp.printf("Lg %d", i+1); 199 dsp.printf("Lg %d", i+1);
373 } 202 }
374 dsp.copy_to_lcd(); 203 dsp.copy_to_lcd();
375 wait(2); 204 wait(2);
376 dsp.cls(); 205 dsp.cls();
377 206
378 dsp_refresher.attach(&copy_to_lcd, 0.1);
379 test_dsp(); 207 test_dsp();
208 dsp.copy_to_lcd();
380 wait(2); 209 wait(2);
381 dsp.cls(); 210 dsp.cls();
382 211
383 } 212 }
384 213
385 void copy_to_lcd(void) { 214 void copy_to_lcd(void) {
386 if (must_refresh) 215 while(1) {
387 dsp.copy_to_lcd(); 216 pulse(0, true);
217 if (must_refresh) {
218 must_refresh = false;
219 dsp.copy_to_lcd();
220 }
221 pulse(0, false);
222 Thread::wait(100);
223 }
388 } 224 }
389 225
390 void show(uint8_t cmd, char *txt, uint8_t nchar=0) { 226 void show(uint8_t cmd, char *txt, uint8_t nchar=0) {
391 uint8_t i, len; 227 uint8_t i, len;
392 uint16_t bgcolor, fgcolor; 228 uint16_t bgcolor, fgcolor;
393 char *oldv; 229 char *oldv;
394 230
231 pulse(1, true);
232
395 must_refresh = false; 233 must_refresh = false;
396 234
397 len = MAX_BUFF; 235 len = MAX_BUFF;
398 236
399 for (i=0; i<sizeof(table)/sizeof(table[0]); ++i) { 237 for (i=0; i<sizeof(table)/sizeof(table[0]); ++i) {
404 dsp.foreground(fgcolor); 242 dsp.foreground(fgcolor);
405 dsp.locate(table[i].x0, table[i].y0); 243 dsp.locate(table[i].x0, table[i].y0);
406 dsp.set_font((unsigned char*) table[i].font); 244 dsp.set_font((unsigned char*) table[i].font);
407 oldv = table[i].buffer; 245 oldv = table[i].buffer;
408 246
409 switch (table[i].fmt) { 247
410 case 0: //ascii 248 if (table[i].fmt & 0x01 ) {
249 // ascii
411 if (table[i].width > 0) 250 if (table[i].width > 0)
412 dsp.fillrect(table[i].x0, table[i].y0, table[i].x0 + table[i].width, table[i].y0 + table[i].font[2], bgcolor); 251 dsp.fillrect(table[i].x0, table[i].y0, table[i].x0 + table[i].width, table[i].y0 + table[i].font[2], bgcolor);
413 dsp.printf(txt); 252 for (uint8_t k=0; ;k++) {
414 break; 253 if (txt[k] == 0x00)
415 case 1: // hex 254 {
255 dsp.printf(txt);
256 break;
257 }
258 if (txt[k] == 0x09) { // \t is a special char for 'unselected' display value
259 txt[k] = 0x00;
260 dsp.printf(txt);
261
262 if (fgcolor == table[i].color)
263 fgcolor /= 2;
264 else
265 fgcolor = table[i].color;
266 dsp.foreground(fgcolor);
267 txt = &(txt[k+1]);
268 k = 0;
269 }
270 }
271 }
272
273 if (table[i].fmt & 0x02 ) {
274 // hex
416 for (uint8_t j=0;; j++) { 275 for (uint8_t j=0;; j++) {
417 if (txt[j] == 0x00) 276 if (txt[j] == 0x00)
418 break; 277 break;
419 dsp.printf("%02X ", txt[j]); 278 dsp.printf("%02X ", txt[j]);
420 } 279 }
421 for (uint8_t j=3*strlen(txt); j<table[i].maxsize; j++) 280 for (uint8_t j=3*strlen(txt); j<table[i].maxsize; j++)
422 dsp.printf(" "); 281 dsp.printf(" ");
423 break; 282 }
424 case 2: // binary 283
284 if (table[i].fmt & 0x04 ) {
285 // binary
425 dsp.foreground(fgcolor); 286 dsp.foreground(fgcolor);
426 dsp.printf(" ["); 287 dsp.printf(" [");
427 for (uint8_t j=0; j<max(nchar, table[i].maxsize) ; j++) { 288 for (uint8_t j=0; j<max(nchar, table[i].maxsize) ; j++) {
428 if (j>0) { 289 if (j>0) {
429 dsp.foreground(fgcolor); 290 dsp.foreground(fgcolor);
437 dsp.printf("%d", (8-k)); 298 dsp.printf("%d", (8-k));
438 } 299 }
439 } 300 }
440 dsp.foreground(fgcolor); 301 dsp.foreground(fgcolor);
441 dsp.printf("]"); 302 dsp.printf("]");
442 break; 303 }
443 case 3: // flags 304
305 if (table[i].fmt & 0x08 ) {
306 // flags
444 for (uint8_t j=0; j<max(nchar, table[i].maxsize) ; j++) { 307 for (uint8_t j=0; j<max(nchar, table[i].maxsize) ; j++) {
445 for (uint8_t k=0; k<8; k++) { 308 for (uint8_t k=0; k<8; k++) {
446 if ((txt[j] & (1 << k) ) != (oldv[j] & (1 << k))) { 309 if ((txt[j] & (1 << k) ) != (oldv[j] & (1 << k))) {
447 310
448 if (txt[j] & (1 << k)) 311 if (txt[j] & (1 << k))
449 dsp.foreground(fgcolor); 312 dsp.foreground(fgcolor);
450 else 313 else
451 dsp.foreground(bgcolor); 314 dsp.foreground(bgcolor);
315
316 for (uint8_t l=0;
317 l<(sizeof(frames)/sizeof(frames[0])); ++l) {
318 if (frames[l].flag & ((j<<4) + k))
319 dsp.rect(frames[l].x0, frames[l].y0,
320 frames[l].x1, frames[l].y1,
321 fgcolor);
322 else
323 dsp.rect(frames[l].x0, frames[l].y0,
324 frames[l].x1, frames[l].y1,
325 bgcolor);
326
327 }
328
452 for (uint8_t l=0; 329 for (uint8_t l=0;
453 l<(sizeof(flags)/sizeof(flags[0])); ++l) { 330 l<(sizeof(flags)/sizeof(flags[0])); ++l) {
454 if (flags[l].flag == ((j<<4) + k)) { 331 if (flags[l].flag == ((j<<4) + k)) {
455 if (flags[l].msg != NULL) { // a string 332 if (flags[l].msg != NULL) { // a string
456 dsp.locate(flags[l].x, flags[l].y); 333 dsp.locate(flags[l].x, flags[l].y);
457 dsp.printf(flags[l].msg);} 334 dsp.printf(flags[l].msg);}
458 else { // an icon 335 else { // an icon
459 Bitmap_s pic = {9, 10, 2, flags[l].icon}; 336 Bitmap_s pic = {9, 10, 2, flags[l].icon};
460 dsp.Bitmap_BW(pic, flags[l].x, flags[l].y); 337 dsp.Bitmap_BW(pic, flags[l].x, flags[l].y);
461 } 338 }
462 break; 339 //break;
463 } 340 }
464 } 341 }
465 } 342 }
466 } 343 }
467 oldv[j] = txt[j];
468 } 344 }
469 break;
470 case 4: //ignore
471 break;
472 } 345 }
346
347 for(uint8_t j=0; j<table[i].maxsize; j++)
348 oldv[j] = txt[j];
473 } 349 }
474 } 350 }
351
475 must_refresh = true; 352 must_refresh = true;
476 //dsp.copy_to_lcd(); 353 //dsp.copy_to_lcd();
354 pulse(1, false);
477 } 355 }
478 356
479 void test_dsp() 357 void test_dsp()
480 { 358 {
481 show(0x00, "8g8g8g8g8g8g8", 13); // main dsp 359 show(0x00, "8g8g8g8g8g8g8", 13); // main dsp
482 show(0x0C, "888", 3); // channel dsp 360 show(0x0C, "888", 3); // channel dsp
483 show(0x0A, "\xFF\xFF\xFF\xFF", 4); // flags 361 show(0x0A, "\xFF\xFF\xFF\xFF", 4); // all flags
484 } 362 }
485 363
486 364
487 void loop() { // run over and over 365 void loop() { // run over and over
366 while(1){
488 if (hp.cmd_available()) 367 if (hp.cmd_available())
489 { 368 {
490 HPSerial::CMD cmd; 369 HPSerial::CMD cmd;
491 if (hp.pop(cmd)) 370 if (hp.pop(cmd))
492 { 371 {
493 pc.printf("CMD[%s:%d %d/%d/%d/%d/%d/%d] %X\n", (cmd.direction==HPSerial::Rx)?"Rx":"Tx", cmd.id, 372 pc.printf("CMD[%s:%d %d/%d/%d/%d/%d/%d/%d] %X\n", (cmd.direction==HPSerial::Rx)?"Rx":"Tx", cmd.id,
494 hp.nerrors(0), 373 hp.nerrors(0),
495 hp.nerrors(1), 374 hp.nerrors(1),
496 hp.nerrors(2), 375 hp.nerrors(2),
497 hp.nerrors(3), 376 hp.nerrors(3),
498 hp.nerrors(4), 377 hp.nerrors(4),
499 hp.nerrors(5), 378 hp.nerrors(5),
379 hp.nerrors(6),
500 cmd.cmd); 380 cmd.cmd);
501 381
502 if (cmd.direction == HPSerial::Rx) { 382 if (cmd.direction == HPSerial::Rx) {
503 if ((cmd.cmd == 0x00) || (cmd.cmd == 0x0C)) 383 if ((cmd.cmd == 0x00) || (cmd.cmd == 0x0C))
504 pc.printf(" data=%s\n", cmd.value); 384 pc.printf(" data=%s\n", cmd.value);
505 show(cmd.cmd, cmd.value, cmd.size); 385 show(cmd.cmd, cmd.value, cmd.size);
506 386
507 } 387 }
508 } 388 }
509 } 389 }
390 Thread::wait(0.01);
391 }
510 } 392 }
511 393
512 int main() 394 int main()
513 { 395 {
514 setup(); 396 setup();
515 while(1) 397 tdsp.start(copy_to_lcd);
516 loop(); 398 tloop.start(loop);
517 } 399 while(1);
400 //loop();
401 }

mercurial