view commands.cc @ 7:ef38703286dd

add ++echo command, bigger queues, infinite timeout on usb
author Frank Kingswood <frank@kingswood-consulting.co.uk>
date Fri, 11 Apr 2014 17:21:26 +0100
parents acbd0ddd002b
children
line wrap: on
line source
1 /* #------------------------------------------------------------------------#
2 | |
3 | commands.cc |
4 | |
5 | USB-GPIB command processing |
6 | |
7 | Copyright 2014, Frank A. Kingswood, www.kingswood-consulting.co.uk |
8 | |
9 #------------------------------------------------------------------------# */
11 #include <avr/io.h>
12 #include <avr/pgmspace.h>
13 #include <stdint.h>
14 #include <ctype.h>
15 #include <util/delay.h>
16 #include <avr/interrupt.h>
17 #include "usb_serial.h"
18 #include "serial.h"
19 #include "gpib.h"
21 static const int16_t NONE=0x8000;
22 static const int16_t EINVCHAR=-1;
23 static const int16_t EBUFFER=-2;
24 static const int16_t ETOOMANY=-3;
25 static const int16_t ESYNTAX=-4;
26 static const int16_t ERANGE=-5;
27 static const int16_t EVALUE=-6;
28 static const int16_t EUNDERFLOW=-7;
29 static const int16_t ETIMEOUT=-8;
30 static const int16_t ECOMMAND=-100;
32 /* -------------------------------------------------------------------------- */
34 #define ROM_PTR /* PROGMEN as a modifier to a pointer */
35 #define STR2(a) #a
36 #define STR(a) STR2(a)
37 #define STRING(s) PROGMEM static const char String_##s[]=STR(s)
39 typedef int16_t (*Method)(char *);
40 struct Commands
41 {
42 const char *Command;
43 Method Function;
44 } __attribute__((__progmem__));
45 const ROM_PTR struct Commands *FindCommand(const ROM_PTR struct Commands *table,
46 const char *command);
48 extern const struct Commands commandTable[];
50 char *skipws(char *ptr)
51 {
52 while(isspace(*ptr))
53 ptr++;
54 return ptr;
55 }
57 int16_t strtoi(const char *ptr, const char **end)
58 {
59 int16_t value=0;
61 char c=*ptr;
62 if(c=='0' && ptr[1]=='x')
63 { ptr+=2;
64 while(isxdigit(c=*ptr))
65 {
66 ptr++;
67 if(c<='9')
68 c-='0';
69 else
70 c=tolower(c)-'a'+10;
71 value=(value<<4) | c;
72 }
73 }
74 else
75 { ptr++;
76 value=c-'0';
77 while(isdigit(c=*ptr))
78 {
79 ptr++;
80 c-='0';
81 value=value*10 + c;
82 }
83 }
84 if(end)
85 *end=ptr;
86 return value;
87 }
90 /* ----- GPIB defined command bytes ----------------------------------------- */
92 int16_t Byte_MLA(char *)
93 { return GPIB.CMD_SOURCE | GPIB.CMD_ATN | 0x20 | (GPIB.MyAddress&31);
94 }
96 int16_t Byte_MSA(char *)
97 {
98 if((GPIB.MyAddress & 0xff00)!=0)
99 return GPIB.CMD_SOURCE | GPIB.CMD_ATN | 0x60 | ((GPIB.MyAddress>>8)&31);
100 return 0;
101 }
103 int16_t Byte_MTA(char *)
104 { return GPIB.CMD_SOURCE | GPIB.CMD_ATN | 0x40 | (GPIB.MyAddress&31);
105 }
107 int16_t Byte_DCL(char *)
108 { return GPIB.CMD_SOURCE | GPIB.CMD_ATN | 0x14;
109 }
111 int16_t Byte_GET(char *)
112 { return GPIB.CMD_SOURCE | GPIB.CMD_ATN | 0x08;
113 }
115 int16_t Byte_GTL(char *)
116 { return GPIB.CMD_SOURCE | GPIB.CMD_ATN | 0x01;
117 }
119 int16_t Byte_LLO(char *)
120 { return GPIB.CMD_SOURCE | GPIB.CMD_ATN | 0x11;
121 }
123 int16_t Byte_PPC(char *)
124 { return GPIB.CMD_SOURCE | GPIB.CMD_ATN | 0x05;
125 }
127 int16_t Byte_PPU(char *)
128 { return GPIB.CMD_SOURCE | GPIB.CMD_ATN | 0x15;
129 }
131 int16_t Byte_SDC(char *)
132 { return GPIB.CMD_SOURCE | GPIB.CMD_ATN | 0x04;
133 }
135 int16_t Byte_SPD(char *)
136 { return GPIB.CMD_SOURCE | GPIB.CMD_ATN | 0x19;
137 }
139 int16_t Byte_SPE(char *)
140 { return GPIB.CMD_SOURCE | GPIB.CMD_ATN | 0x18;
141 }
143 int16_t Byte_TCT(char *)
144 { return GPIB.CMD_SOURCE | GPIB.CMD_ATN | 0x09;
145 }
147 int16_t Byte_UNL(char *)
148 { return GPIB.CMD_SOURCE | GPIB.CMD_ATN | 0x3f;
149 }
151 int16_t Byte_UNT(char *)
152 { return GPIB.CMD_SOURCE | GPIB.CMD_ATN | 0x5f;
153 }
155 int16_t Byte_LAD(char *)
156 { return GPIB.CMD_SOURCE | GPIB.CMD_ATN | 0x20 | (GPIB.DeviceAddress&31);
157 }
159 int16_t Byte_TAD(char *)
160 { return GPIB.CMD_SOURCE | GPIB.CMD_ATN | 0x40 | (GPIB.DeviceAddress&31);
161 }
163 int16_t Byte_SAD(char *)
164 {
165 if((GPIB.DeviceAddress & 0xff00)!=0)
166 return GPIB.CMD_SOURCE | GPIB.CMD_ATN | 0x60 | ((GPIB.DeviceAddress>>8)&31);
167 return 0;
168 }
171 /* ----- command functions -------------------------------------------------- */
173 /* Return codes
174 * --------------
175 * ++eoi
176 * - message when EOI is seen when listening and not in ++rd or ++read eoi command
177 * ++srq
178 * - message when SRQ is asserted
179 * ++error <value>
180 * - message when an error occurs
181 *
182 *
183 * Maybe later:
184 * ++dev <pad> <sad> <tmo> <eot> <eos> -> <name>
185 * Assign settings to user-configurable device, return identifier
186 * ++config/++ask various options
187 * ++ln [<device>] -> result
188 * check for presence of a device on the bus
189 * (not clear how this is done?)
190 * ++onl [<device>] <v>
191 * Set device online/offline
192 * ++pad <device> <address>
193 * Change device primary address
194 * ++rsc
195 * Request/release system control
196 * ++sad <device> <address>
197 * Change device secondary address
198 *
199 */
202 /* ..........................................................................
203 *
204 * ++addr <addr> [<secondary>]
205 * ++addr? -> <addr>
206 * - set or return default device address to <device> (default 1)
207 * - may include secondary address either as second word or MSBs in <device>
208 */
209 int16_t Command_addr(char *tail)
210 {
211 if(*tail==0 || *tail=='?')
212 return GPIB.DeviceAddress;
214 uint16_t addr=strtoi(tail,(const char **)&tail);
216 if(*tail)
217 { if((addr & 0xffe0)!=0)
218 return EVALUE;
220 tail=skipws(tail);
221 if(*tail)
222 {
223 uint16_t second=strtoi(tail,(const char **)&tail);
224 if((second & 0xffe0)!=0)
225 return EVALUE;
226 addr|=(0x60 | second)<<8;
227 }
228 }
229 GPIB.DeviceAddress=addr;
231 return NONE;
232 }
234 /* ..........................................................................
235 *
236 * ++ATN <value>
237 * ++ATN? -> <value>
238 *
239 * set or return ~ATN
240 */
241 int16_t Command_ATN(char *tail)
242 {
243 switch(*tail)
244 { case 0:
245 case '?':
246 return GPIB.ATN();
247 case '0':
248 case '1':
249 GPIB.ATN(*tail&1);
250 return NONE;
251 }
253 return EVALUE;
254 }
256 /* ..........................................................................
257 *
258 * ++auto <state>
259 * if state==1: automatic ++read eoi after sending a string ending in "?"
260 * elif state==0: leave in LISTEN state
261 */
262 int16_t Command_auto(char *tail)
263 {
264 Serial<<ROMS("auto ")<<tail<<endl;
265 return ECOMMAND;
266 }
268 /* ..........................................................................
269 *
270 * ++cac <v>
271 * if v!=1: wait for handshake to complete
272 * Become active controller
273 */
274 int16_t Command_cac(char *tail)
275 {
276 GPIB.Command(GPIB.CMD_CONTROLLER | *tail);
277 return NONE;
278 }
281 /* ..........................................................................
282 *
283 * ++clr [<device>]
284 * - selected/universal device clear
285 * - if device=="all":
286 * ++cmd MTA UNL DCL
287 * else:
288 * ++cmd MTA UNL LAD SAD SDC
289 */
290 int16_t Command_clr(char *tail)
291 {
292 GPIB.Command(Byte_MTA(0));
293 GPIB.Command(Byte_UNL(0));
294 if(!strcmp_P(tail, PSTR("all")))
295 GPIB.Command(Byte_DCL(0));
296 else
297 {
298 GPIB.Command(Byte_LAD(0));
299 GPIB.Command(Byte_SAD(0));
300 GPIB.Command(Byte_SDC(0));
301 }
302 return NONE;
303 }
305 /* ..........................................................................
306 *
307 * ++cmd <bytes or codes>
308 * - set ATN=0, send bytes, set ATN=1, set ATN=float
309 * - for each byte, if code is preceded by "-": EOI=0
310 * else: EOI=1
311 */
313 #define BYTE(s) { String_##s, Byte_##s }
315 #undef SPE
316 STRING(DCL); STRING(GET); STRING(GTL); STRING(LAD); STRING(LLO);
317 STRING(MLA); STRING(MSA); STRING(MTA); STRING(PPC); STRING(PPU);
318 STRING(SAD); STRING(SDC); STRING(SPD); STRING(SPE); STRING(TAD);
319 STRING(TCT); STRING(UNL); STRING(UNT);
321 static const struct Commands byteTable[]=
322 {
323 BYTE(DCL), BYTE(GET), BYTE(GTL), BYTE(LAD), BYTE(LLO),
324 BYTE(MLA), BYTE(MSA), BYTE(MTA), BYTE(PPC), BYTE(PPU),
325 BYTE(SAD), BYTE(SDC), BYTE(SPD), BYTE(SPE), BYTE(TAD),
326 BYTE(TCT), BYTE(UNL), BYTE(UNT),
327 { 0,0 },
328 };
330 #define Debug USB
332 int16_t Command_cmd_wrt(char *tail,bool atn)
333 {
334 //GPIB.ATN(atn);
335 uint8_t eoi=0;
336 uint16_t cmd;
337 while(char c=*tail)
338 { const char *word=tail++;
340 if(c=='-')
341 { eoi=1;
342 continue;
343 }
345 uint8_t byte=0;
347 if(c=='"')
348 {
349 while((c=*tail)!='"' && c>=' ')
350 {
351 tail++;
353 cmd=GPIB.CMD_SOURCE | (c&0xff);
354 if(atn)
355 cmd|=GPIB.CMD_ATN;
356 if(eoi && *tail=='"')
357 cmd|=GPIB.CMD_EOI;
358 GPIB.Command(cmd);
359 }
361 if(c!='"')
362 goto fail;
364 tail++;
365 }
366 else
367 {
368 uint8_t skip=0;
370 if(isdigit(c))
371 {
372 if(c=='0' && *tail=='x')
373 { tail++;
374 while(isxdigit(c=*tail))
375 {
376 byte<<=4;
377 if(c<='9')
378 byte+=c-'0';
379 else
380 byte+=tolower(c)-'a'+10;
381 tail++;
382 }
383 }
384 else
385 {
386 byte=c-'0';
387 while(isdigit(c=*tail))
388 {
389 byte=byte*10+c-'0';
390 tail++;
391 }
392 }
394 if(!(c==' ' || c==0))
395 goto fail;
396 }
397 else
398 {
399 while(isalnum(*tail))
400 tail++;
402 c=*tail;
403 *tail=0;
405 const ROM_PTR struct Commands *cmd=FindCommand(byteTable,word);
407 if(!cmd)
408 goto fail;
410 *tail=c;
411 Method f=(Method)(pgm_read_word(&cmd->Function));
413 byte=f(tail);
415 // handle cases where there is nothing to send
416 if(!byte)
417 skip=1;
418 }
420 if(!skip)
421 {
422 //GPIB.EOI(eoi);
423 //byte=GPIB.Out(byte);
424 //GPIB.EOI(false);
425 //if(byte)
426 // goto fail;
428 cmd=GPIB.CMD_SOURCE | byte;
429 if(atn)
430 cmd|=GPIB.CMD_ATN;
431 if(eoi)
432 cmd|=GPIB.CMD_EOI;
433 GPIB.Command(cmd);
434 }
435 }
437 tail=skipws(tail);
438 eoi=0;
439 }
441 return NONE;
443 fail:
444 //GPIB.EOI(false);
445 //GPIB.ATN(false);
446 return EINVCHAR;
447 }
449 int16_t Command_cmd(char *tail)
450 {
451 return Command_cmd_wrt(tail,true);
452 }
454 /* ..........................................................................
455 *
456 * ++data? -> <byte>
457 * return ~DIO[8:1]
458 */
459 int16_t Command_data(char *tail)
460 {
461 return GPIB.Data();
462 }
464 /* ..........................................................................
465 *
466 * ++DAV <value>
467 * ++DAV? -> <value>
468 *
469 * set or return ~DAV
470 */
471 int16_t Command_DAV(char *tail)
472 {
473 switch(*tail)
474 { case 0:
475 case '?':
476 return GPIB.DAV();
477 case '0':
478 case '1':
479 GPIB.DAV(*tail&1);
480 return NONE;
481 }
483 return EVALUE;
484 }
486 /* ..........................................................................
487 *
488 * ++DEBUG <value>
489 * do whatever we think is interesting
490 */
491 int16_t Command_DEBUG(char *tail)
492 {
493 if(*tail)
494 {
495 int16_t addr=strtoi(tail,(const char **)&tail);
497 if(!*tail)
498 {
499 USB<<addr<<endl;
500 USB.Flush();
502 _delay_ms(100);
504 Method f=(Method)addr;
505 GPIB.Float();
506 cli();
507 UDCON=1;
508 USBCON=(1<<FRZCLK); // disable USB
509 UCSR1B=0;
510 EIMSK=0; PCICR=0; SPCR=0; ACSR=0; EECR=0; ADCSRA=0;
511 TIMSK0=0; TIMSK1=0; TIMSK3=0; TIMSK4=0; UCSR1B=0; TWCR=0;
512 _delay_ms(10);
514 f(tail);
515 sei();
516 }
517 }
519 USB<<ROMS("ddrb="); USB.Hex(uint8_t(DDRB));
520 USB<<ROMS(" portb="); USB.Hex(uint8_t(PORTB));
521 USB<<ROMS(" pinb="); USB.Hex(uint8_t(PINB));
522 USB<<endl;
524 USB<<ROMS("ddrc="); USB.Hex(uint8_t(DDRC));
525 USB<<ROMS(" portc="); USB.Hex(uint8_t(PORTC));
526 USB<<ROMS(" pinc="); USB.Hex(uint8_t(PINC));
527 USB<<endl;
529 USB<<ROMS("ddrd="); USB.Hex(uint8_t(DDRD));
530 USB<<ROMS(" portd="); USB.Hex(uint8_t(PORTD));
531 USB<<ROMS(" pind="); USB.Hex(uint8_t(PIND));
532 USB<<endl;
534 USB<<ROMS("ddre="); USB.Hex(uint8_t(DDRE));
535 USB<<ROMS(" porte="); USB.Hex(uint8_t(PORTE));
536 USB<<ROMS(" pine="); USB.Hex(uint8_t(PINE));
537 USB<<endl;
539 USB<<ROMS("ddrf="); USB.Hex(uint8_t(DDRF));
540 USB<<ROMS(" portf="); USB.Hex(uint8_t(PORTF));
541 USB<<ROMS(" pinf="); USB.Hex(uint8_t(PINF));
542 USB<<endl;
544 GPIB.Report();
545 USB<<endl;
547 return NONE;
548 }
550 /* ..........................................................................
551 *
552 * ++echo <mode>
553 * if mode==1: echo commands
554 * else: do not echo
555 */
556 extern bool Echo;
557 int16_t Command_echo(char *tail)
558 {
559 switch(*tail)
560 { case 0:
561 case '?':
562 return Echo;
563 case '0':
564 case '1':
565 Echo=(*tail&1);
566 return NONE;
567 }
569 return EVALUE;
570 }
572 /* ..........................................................................
573 *
574 * ++EOI <value>
575 * ++EOI? -> <value>
576 *
577 * set or return ~EOI
578 */
579 int16_t Command_EOI(char *tail)
580 {
581 switch(*tail)
582 { case 0:
583 case '?':
584 return GPIB.EOI();
585 case '0':
586 case '1':
587 GPIB.EOI(*tail&1);
588 return NONE;
589 }
591 return EVALUE;
592 }
594 /* ..........................................................................
595 *
596 * ++eoi <mode>
597 * if mode==0: no EOI asserted
598 * else: assert EOI on last byte of a command (default)
599 */
600 int16_t Command_eoi(char *tail)
601 {
602 Serial<<ROMS("eoi ")<<tail<<endl;
603 return ECOMMAND;
604 }
606 /* ..........................................................................
607 *
608 * ++eos <mode>
609 * if mode==0: append "\r\n" to commands
610 * elif mode==1: append "\r" to commands
611 * elif mode==2: append "\n" to commands
612 * else: do not append anything (default)
613 * ++eos {4|8} <byte>
614 * if arg=0,1,2,3: prologix
615 * else:
616 * if first arg==4 or 12: terminate reads on <byte>
617 * if first arg==8 or 12: set EOI when writing <byte>
618 */
620 int16_t Command_eos(char *tail)
621 {
622 Serial<<ROMS("eos ")<<tail<<endl;
623 return ECOMMAND;
624 }
626 /* ..........................................................................
627 *
628 * ++eot_char <byte>
629 * set eot_char
630 */
631 int16_t Command_eot_char(char *tail)
632 {
633 Serial<<ROMS("eot_char ")<<tail<<endl;
634 return ECOMMAND;
635 }
637 /* ..........................................................................
638 *
639 * ++eot_enable <eot>
640 * control how EOI when receiving data is handled
641 * if eot==0: ignore
642 * elif eot==1: send <eot_char>
643 * else: send ++eoi (default)
644 */
645 int16_t Command_eot_enable(char *tail)
646 {
647 Serial<<ROMS("eot_enable ")<<tail<<endl;
648 return ECOMMAND;
649 }
651 /* ..........................................................................
652 *
653 *
654 *
655 */
656 int16_t Command_error(char *tail)
657 {
658 Serial<<ROMS("error ")<<tail<<endl;
659 return ECOMMAND;
660 }
662 /* ..........................................................................
663 *
664 * ++gts <v>
665 * if v:
666 * transfer data as acceptor, until END
667 * float all pins
668 * ++mode 0 (device)
669 */
670 int16_t Command_gts(char *tail)
671 {
672 Serial<<ROMS("gts ")<<tail<<endl;
673 GPIB.Float();
674 return ECOMMAND;
675 }
677 /* ..........................................................................
678 *
679 * ++ver
680 * Display version string
681 */
682 void Version()
683 {
684 static const char version[] PROGMEM =
685 " version"
686 #include "version.h"
687 "\r\n";
688 USB<<ROMS("Kingswood USB-GPIB-32U4 ");
689 if(GPIB.MicroPro)
690 USB<<ROMS("MicroPro");
691 else
692 USB<<ROMS("Teensy");
693 USB<<ROM(version);
694 }
696 /* ..........................................................................
697 *
698 * ++IFC <value>
699 * ++IFC? -> <value>
700 * set or return ~IFC
701 */
702 int16_t Command_IFC(char *tail)
703 {
704 switch(*tail)
705 { case 0:
706 case '?':
707 return GPIB.IFC();
708 case '0':
709 case '1':
710 GPIB.IFC(*tail&1);
711 return NONE;
712 }
714 return EVALUE;
715 }
717 /* ..........................................................................
718 *
719 * ++lines? -> <byte>
720 * - return ~{EOI,ATN,SRQ,REN,IFC,NRFD,NDAC,DAV}
721 */
722 int16_t Command_lines(char *tail)
723 {
724 uint8_t byte=0;
725 if(GPIB.EOI()) byte|=1<<7;
726 if(GPIB.ATN()) byte|=1<<6;
727 if(GPIB.SRQ()) byte|=1<<5;
728 if(GPIB.REN()) byte|=1<<4;
729 if(GPIB.IFC()) byte|=1<<3;
730 if(GPIB.NRFD()) byte|=1<<2;
731 if(GPIB.NDAC()) byte|=1<<1;
732 if(GPIB.DAV()) byte|=1<<0;
734 return byte;
735 }
737 /* ..........................................................................
738 *
739 * ++llo [<device>]
740 * equivalent to ++cmd LAD SAD LLO UNL
741 */
742 int16_t Command_llo(char *tail)
743 {
744 GPIB.Command(Byte_LAD(0));
745 GPIB.Command(Byte_SAD(0));
746 GPIB.Command(Byte_LLO(0));
747 GPIB.Command(Byte_UNL(0));
749 return NONE;
750 }
752 /* ..........................................................................
753 *
754 * ++loc [<device>]
755 * equivalent to ++cmd TAD SAD UNL LAD SAD GTL
756 */
757 int16_t Command_loc(char *tail)
758 {
759 GPIB.Command(Byte_TAD(0));
760 GPIB.Command(Byte_SAD(0));
761 GPIB.Command(Byte_UNL(0));
762 GPIB.Command(Byte_LAD(0));
763 GPIB.Command(Byte_SAD(0));
764 GPIB.Command(Byte_GTL(0));
766 return NONE;
767 }
769 /* ..........................................................................
770 *
771 * ++lon <value>
772 * enable listen only (promiscuous listen) mode
773 */
774 int16_t Command_lon(char *tail)
775 {
776 Serial<<ROMS("lon ")<<tail<<endl;
777 return ECOMMAND;
778 }
780 /* ..........................................................................
781 *
782 * ++mode <mode>
783 * if mode==0 or mode=='d': device mode
784 * elif mode==1 or mode=='c': controller in command mode
785 * elif mode=='+': prompting mode (default)
786 */
787 int16_t Command_mode(char *tail)
788 {
789 Serial<<ROMS("mode ")<<tail<<endl;
790 return ECOMMAND;
791 }
793 /* ..........................................................................
794 *
795 * ++NDAC <value>
796 * ++NDAC? -> <value>
797 *
798 * set or return ~NDAC
799 */
800 int16_t Command_NDAC(char *tail)
801 {
802 switch(*tail)
803 { case 0:
804 case '?':
805 return GPIB.NDAC();
806 case '0':
807 case '1':
808 GPIB.NDAC(*tail&1);
809 return NONE;
810 }
812 return EVALUE;
813 }
815 /* ..........................................................................
816 *
817 * ++NRFD <value>
818 * ++NRFD? -> <value>
819 *
820 * set or return ~NRFD
821 */
822 int16_t Command_NRFD(char *tail)
823 {
824 switch(*tail)
825 { case 0:
826 case '?':
827 return GPIB.NRFD();
828 case '0':
829 case '1':
830 GPIB.NRFD(*tail&1);
831 return NONE;
832 }
834 return EVALUE;
835 }
837 /* ..........................................................................
838 *
839 * ++pct <address>
840 * pass CIC to device
841 * equivalent to ++cmd UNL LAD SAD TAD SAD TCT
842 */
843 int16_t Command_pct(char *tail)
844 {
845 GPIB.Command(Byte_UNL(0));
846 GPIB.Command(Byte_LAD(0));
847 GPIB.Command(Byte_SAD(0));
848 GPIB.Command(Byte_TAD(0));
849 GPIB.Command(Byte_SAD(0));
850 GPIB.Command(Byte_TCT(0));
851 GPIB.Command(GPIB.CMD_RELEASE);
853 return NONE;
854 }
856 /* ..........................................................................
857 *
858 * ++rd <count>
859 * read <count> bytes or until EOI or timeout
860 */
861 int16_t Command_rd(char *tail)
862 {
863 GPIB.Command(GPIB.CMD_ACCEPT);
865 return NONE;
866 }
868 /* ..........................................................................
869 *
870 * ++read [<end>]
871 * ++cmd UNL UNT TAD SAD MLA
872 * if end=="eoi": read until eoi
873 * elif end=="tmo": read until timeout
874 * elif end: read until byte <end>
875 * else: read until timeout
876 * ++read <device> <end>
877 * ++cmd UNL UNT <device> MLA
878 * if end=="eoi": read until eoi
879 * elif end=="tmo": read until timeout
880 * else: read until byte <end>
881 */
882 int16_t Command_read(char *tail)
883 {
884 GPIB.Command(Byte_UNL(0));
885 GPIB.Command(Byte_MLA(0));
886 GPIB.Command(Byte_TAD(0));
887 GPIB.Command(Byte_SAD(0));
889 uint16_t cmd=GPIB.CMD_ACCEPT;
890 if(!strcmp_P(tail, PSTR("eoi")))
891 { }
892 else if(!strcmp_P(tail, PSTR("tmo")))
893 cmd|=GPIB.CMD_AC_TMO;
894 else if(*tail)
895 {
896 uint8_t n=strtoi(tail,(const char **)&tail);
897 cmd|=GPIB.CMD_AC_COUNT | n;
898 }
900 GPIB.Command(cmd);
902 return NONE;
903 }
905 /* ..........................................................................
906 *
907 * ++REN <value>
908 * ++REN? -> <value>
909 *
910 * set or return ~REN
911 */
912 int16_t Command_REN(char *tail)
913 {
914 switch(*tail)
915 { case 0:
916 case '?':
917 return GPIB.REN();
918 case '0':
919 case '1':
920 GPIB.REN(*tail&1);
921 return NONE;
922 }
924 return EVALUE;
925 }
927 /* ..........................................................................
928 *
929 * ++rpp -> <result>
930 * perform parallel poll by asserting ATN and EOI, reading response from data bus
931 */
932 int16_t Command_rpp(char *tail)
933 {
934 GPIB.Command(GPIB.CMD_PARPOLL);
935 return NONE;
936 }
938 /* ..........................................................................
939 *
940 * ++rsp <device> -> <result>
941 * read serial poll data, equivalent to
942 * ++cmd UNL MLA SPE TAD SAD
943 * ++rd <1 byte>
944 * ++cmd SPD
945 */
946 int16_t Command_rsp(char *tail)
947 {
948 GPIB.Command(Byte_UNL(0));
949 GPIB.Command(Byte_MLA(0));
950 GPIB.Command(Byte_SPE(0));
951 GPIB.Command(Byte_TAD(0));
952 GPIB.Command(Byte_SAD(0));
953 GPIB.Command(GPIB.CMD_ACCEPT | GPIB.CMD_AC_COUNT | 0x01);
954 GPIB.Command(Byte_SPD(0));
956 return NONE;
957 }
959 /* ..........................................................................
960 *
961 * ++rst
962 * - float all pins
963 * - set defaults
964 */
965 int16_t Command_rst(char *tail)
966 {
967 Echo=true;
968 GPIB.Initialize();
969 return NONE;
970 }
972 /* ..........................................................................
973 *
974 * ++savecfg <state>
975 * (no operation)
976 * if state=1: save <mode> <addr> <auto> <aoi> <eos> <eot> <timeout> whenver changed
977 * else: do not save
978 */
979 int16_t Command_savecfg(char *tail)
980 {
981 Serial<<ROMS("savecfg ")<<tail<<endl;
982 return ECOMMAND;
983 }
985 /* ..........................................................................
986 *
987 * ++self <address> [<secondary>]
988 * ++self? -> <address>
989 * set or return address of USB-GPIB (default 0)
990 */
991 int16_t Command_self(char *tail)
992 {
993 if(*tail==0 || *tail=='?')
994 return GPIB.MyAddress;
996 uint16_t addr=strtoi(tail,(const char **)&tail);
997 USB.Hex(addr);
999 if(*tail)
1000 { if((addr & 0xffe0)!=0)
1001 return EVALUE;
1003 tail=skipws(tail);
1004 if(*tail)
1006 uint16_t second=strtoi(tail,(const char **)&tail);
1007 if((second & 0xffe0)!=0)
1008 return EVALUE;
1009 addr|=(0x60 | second)<<8;
1012 USB.Hex(addr);
1014 GPIB.MyAddress=addr;
1016 return NONE;
1019 /* ..........................................................................
1021 * ++sic [<value>]
1022 * send interface clear
1023 */
1024 int16_t Command_sic(char *tail)
1026 GPIB.Command(GPIB.CMD_SIC);
1027 return NONE;
1030 /* ..........................................................................
1032 * ++SRQ <value>
1033 * ++SRQ? -> <value>
1035 * set or return ~SRQ
1036 */
1037 int16_t Command_SRQ(char *tail)
1039 switch(*tail)
1040 { case 0:
1041 case '?':
1042 return GPIB.SRQ();
1043 case '0':
1044 case '1':
1045 GPIB.SRQ(*tail&1);
1046 return NONE;
1049 return EVALUE;
1052 /* ..........................................................................
1054 * ++status <value>
1055 * ++status? -> <value>
1056 * report device status
1057 * ++rsv <byte>
1058 * set or return status byte to be used when we are a slave
1059 * if byte&0x40: SRQ=0
1060 */
1061 int16_t Command_status(char *tail)
1063 Serial<<ROMS("status ")<<tail<<endl;
1064 return ECOMMAND;
1067 /* ..........................................................................
1069 * ++tmo <timeout>
1070 * set timeout in ms (up to 65 seconds)
1071 */
1072 int16_t Command_tmo(char *tail)
1074 if(*tail==0 || *tail=='?')
1075 return GPIB.Timeout;
1077 uint16_t tmo=strtoi(tail,(const char **)&tail);
1078 if(*tail)
1079 return EVALUE;
1081 GPIB.Timeout=tmo;
1082 return NONE;
1085 /* ..........................................................................
1087 * ++trg <device> [<device>...]
1088 * triggers one or more devices
1089 * equivalent to ++cmd MTA UNL LAD SAD ... GET
1090 */
1091 int16_t Command_trg(char *tail)
1093 GPIB.Command(Byte_MTA(0));
1094 GPIB.Command(Byte_UNL(0));
1095 GPIB.Command(Byte_LAD(0));
1096 GPIB.Command(Byte_SAD(0));
1097 GPIB.Command(Byte_GET(0));
1099 return NONE;
1102 /* ..........................................................................
1104 * ++ver
1105 * show version
1106 */
1107 int16_t Command_ver(char *tail)
1109 Version();
1110 return NONE;
1113 /* ..........................................................................
1115 * ++wrt <bytes>
1116 * - set ATN=1, send bytes, set ATN=float
1117 * - for each byte, if code is preceded by "-": EOI=0
1118 * else: EOI=1
1119 */
1120 int16_t Command_wrt(char *tail)
1122 return Command_cmd_wrt(tail,false);
1125 /* ..........................................................................
1127 * ++write <bytes>
1128 * - set ATN=1, send MTA UNL LAD SAD, followed by bytes
1129 */
1130 int16_t Command_write(char *tail)
1132 GPIB.Command(Byte_MTA(0));
1133 GPIB.Command(Byte_UNL(0));
1134 GPIB.Command(Byte_LAD(0));
1135 GPIB.Command(Byte_SAD(0));
1137 return Command_wrt(tail);
1141 /* ----- command strings ---------------------------------------------------- */
1143 STRING(addr); STRING(ATN); STRING(auto); STRING(cac);
1144 STRING(clr); STRING(cmd); STRING(data); STRING(DAV);
1145 STRING(DEBUG); STRING(EOI); STRING(eoi); STRING(eos);
1146 STRING(eot_char); STRING(eot_enable);
1147 STRING(error); STRING(gts); STRING(help); STRING(IFC);
1148 STRING(lines); STRING(llo);
1149 STRING(loc); STRING(lon); STRING(mode); STRING(NDAC);
1150 STRING(NRFD); STRING(pct); STRING(rd); STRING(read);
1151 STRING(REN); STRING(rpp);
1152 STRING(rsp); STRING(rst); STRING(rsv); STRING(savecfg);
1153 STRING(self); STRING(sic); STRING(spoll); STRING(sre);
1154 STRING(SRQ); STRING(status); STRING(tmo); STRING(trg);
1155 STRING(ver); STRING(write); STRING(wrt); STRING(echo);
1157 #define COMMAND(s) { String_##s, Command_##s }
1159 int16_t Command_help(char *tail);
1160 const struct Commands commandTable[]=
1162 COMMAND(ATN), COMMAND(DAV), COMMAND(DEBUG), COMMAND(EOI),
1163 COMMAND(IFC), COMMAND(NDAC), COMMAND(NRFD), COMMAND(REN),
1164 COMMAND(SRQ),
1166 COMMAND(addr), COMMAND(auto), COMMAND(cac),
1167 COMMAND(clr), COMMAND(cmd), COMMAND(data),
1168 COMMAND(echo), COMMAND(eoi), COMMAND(eos), COMMAND(eot_char),
1169 COMMAND(eot_enable),
1170 COMMAND(error), COMMAND(gts), COMMAND(help),
1171 COMMAND(lines), COMMAND(llo), COMMAND(loc), COMMAND(lon),
1172 COMMAND(mode), COMMAND(pct),
1173 COMMAND(rd), COMMAND(read),
1174 COMMAND(rpp), COMMAND(rsp), COMMAND(rst),
1175 { String_rsv, Command_status },
1176 COMMAND(savecfg),
1177 COMMAND(self), COMMAND(sic),
1178 { String_spoll, Command_rsp },
1179 { String_sre, Command_REN },
1180 COMMAND(status), COMMAND(tmo), COMMAND(trg),
1181 COMMAND(ver), COMMAND(write), COMMAND(wrt),
1182 { 0,0 },
1183 };
1185 const ROM_PTR struct Commands *FindCommand(const ROM_PTR struct Commands *table,
1186 const char *command)
1188 uint8_t lim;
1189 for(lim=0; pgm_read_word(&table[lim].Command)!=0; lim++)
1190 { }
1192 for(; lim!=0; lim>>=1)
1194 const ROM_PTR struct Commands *p = table + (lim >> 1);
1195 const ROM_PTR char *entry=(const ROM_PTR char *)pgm_read_word(&p->Command);
1196 int8_t cmp=strcmp_P(command, entry);
1198 if(cmp==0)
1199 return p;
1200 else if(cmp > 0)
1201 { /* command > p: move right */
1202 table = p + 1;
1203 lim--;
1205 else
1206 { /* move left */ }
1209 return 0;
1213 int16_t Command(char *command)
1214 { char c;
1215 char *tail=command;
1217 if(*command<' ')
1218 return 0;
1220 int r=ECOMMAND;
1221 if(*command=='?')
1222 r=Command_help(command+1);
1223 else
1225 while(isalnum(*tail))
1226 tail++;
1228 c=*tail;
1229 *tail=0;
1231 const ROM_PTR struct Commands *cmd=FindCommand(commandTable,command);
1233 if(cmd)
1235 *tail=c;
1236 tail=skipws(tail);
1238 Method f=(Method)(pgm_read_word(&cmd->Function));
1239 r=f(tail);
1243 if(r!=NONE)
1244 USB<<r<<endl;
1245 return r;
1249 /* ..........................................................................
1251 * ++help
1252 * show available commands
1253 */
1254 int16_t Command_help(char *tail)
1256 Version();
1257 USB<<ROMS("Available commands:");
1259 const char *p;
1260 for(uint8_t i=0; (p=(const char *)pgm_read_word(&commandTable[i].Command))!=0; i++)
1262 char c=pgm_read_byte(p);
1264 if(*tail=='?' || c>='a' || c==*tail)
1266 USB<<ROMS("\r\n ++")<<ROM(p);
1267 if(p==String_cmd)
1269 USB<<ROMS(" [-]<byte> ... or one of:\r\n ");
1270 for(uint8_t i=0; (p=(const char *)pgm_read_word(&byteTable[i].Command))!=0; i++)
1271 USB<<' '<<ROM(p);
1275 USB<<endl;
1276 return NONE;
1279 /* ----- EOF commands.cc ----- */