view commands.cc @ 3:a70e0a8ac73e

ostream inserters are nice
author Frank Kingswood <frank@kingswood-consulting.co.uk>
date Thu, 27 Mar 2014 17:24:33 +0000
parents 6dfcd8e5b8df
children 1a405bda2ffe
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 }
89 /* ----- command functions -------------------------------------------------- */
91 /* Return codes
92 * --------------
93 * ++eoi
94 * - message when EOI is seen when listening and not in ++rd or ++read eoi command
95 * ++srq
96 * - message when SRQ is asserted
97 * ++error <value>
98 * - message when an error occurs
99 *
100 *
101 * Maybe later:
102 * ++dev <pad> <sad> <tmo> <eot> <eos> -> <name>
103 * Assign settings to user-configurable device, return identifier
104 * ++config/++ask various options
105 * ++ln [<device>] -> result
106 * check for presence of a device on the bus
107 * (not clear how this is done?)
108 * ++onl [<device>] <v>
109 * Set device online/offline
110 * ++pad <device> <address>
111 * Change device primary address
112 * ++rsc
113 * Request/release system control
114 * ++sad <device> <address>
115 * Change device secondary address
116 *
117 */
120 /* ..........................................................................
121 *
122 * ++addr <addr> [<secondary>]
123 * ++addr? -> <addr>
124 * - set or return default device address to <device> (default 1)
125 * - may include secondary address either as second word or MSBs in <device>
126 */
127 int16_t Command_addr(char *tail)
128 {
129 if(*tail==0 || *tail=='?')
130 return GPIB.DeviceAddress;
132 uint16_t addr=strtoi(tail,(const char **)&tail);
134 if(*tail)
135 { if((addr & 0xffe0)!=0)
136 return EVALUE;
138 tail=skipws(tail);
139 if(*tail)
140 {
141 uint16_t second=strtoi(tail,(const char **)&tail);
142 if((second & 0xffe0)!=0)
143 return EVALUE;
144 addr|=(0x60 | second)<<8;
145 }
146 }
147 GPIB.DeviceAddress=addr;
149 return NONE;
150 }
152 /* ..........................................................................
153 *
154 * ++ATN <value>
155 * ++ATN? -> <value>
156 *
157 * set or return ~ATN
158 */
159 int16_t Command_ATN(char *tail)
160 {
161 int16_t i;
162 switch(*tail)
163 { case 0:
164 case '?':
165 return GPIB.ATN();
166 case '0':
167 case '1':
168 GPIB.ATN(*tail&1);
169 return NONE;
170 }
172 return EVALUE;
173 }
175 /* ..........................................................................
176 *
177 * ++auto <state>
178 * if state==1: automatic ++read eoi after sending a string ending in "?"
179 * elif state==0: leave in LISTEN state
180 */
181 int16_t Command_auto(char *tail)
182 {
183 Serial<<ROMS("auto ")<<tail<<endl;
184 return ECOMMAND;
185 }
187 /* ..........................................................................
188 *
189 * ++cac <v>
190 * if v!=1: wait for handshake to complete
191 * Become active controller
192 */
193 int16_t Command_cac(char *tail)
194 {
195 GPIB.ATN(false);
196 _delay_ms(1);
197 GPIB.EOI(false);
198 _delay_ms(1);
199 GPIB.NRFD(false);
200 _delay_ms(1);
201 GPIB.DAV(false);
202 _delay_ms(1);
203 GPIB.NDAC(false);
204 _delay_ms(1);
206 if(*tail!='1')
207 {
208 static const uint16_t TIMEOUT=2000; // 2 seconds
209 uint16_t timeout;
210 for(timeout=TIMEOUT; timeout!=0; timeout--)
211 {
212 _delay_ms(1);
214 if(!(GPIB.ATN() || GPIB.NRFD() || GPIB.NDAC() || GPIB.DAV()))
215 break;
216 }
218 if(!timeout)
219 return ETIMEOUT;
220 }
222 GPIB.Controller();
223 return NONE;
224 }
227 /* ..........................................................................
228 *
229 * ++clr [<device>]
230 * - selected/universal device clear
231 * - if device=="all":
232 * ++cmd MTA UNL DCL
233 * else:
234 * ++cmd MTA UNL LAD SAD SDC
235 */
236 int16_t Command_clr(char *tail)
237 {
238 Serial<<ROMS("clr ")<<tail<<endl;
239 return ECOMMAND;
240 }
242 /* ..........................................................................
243 *
244 * ++cmd <bytes or codes>
245 * - set ATN=0, send bytes, set ATN=1, set ATN=float
246 * - for each byte, if code is preceded by "-": EOI=0
247 * else: EOI=1
248 */
250 #define BYTE(s) { String_##s, Byte_##s }
252 int16_t Byte_MLA(char *)
253 { return 0x20|(GPIB.MyAddress&31);
254 }
256 int16_t Byte_MSA(char *)
257 {
258 if((GPIB.MyAddress & 0xff00)!=0)
259 return 0x60|((GPIB.MyAddress>>8)&31);
260 }
262 int16_t Byte_MTA(char *)
263 { return 0x40|(GPIB.MyAddress&31);
264 }
266 int16_t Byte_DCL(char *)
267 { return 0x14;
268 }
270 int16_t Byte_GET(char *)
271 { return 0x08;
272 }
274 int16_t Byte_GTL(char *)
275 { return 0x01;
276 }
278 int16_t Byte_LLO(char *)
279 { return 0x11;
280 }
282 int16_t Byte_PPC(char *)
283 { return 0x05;
284 }
286 int16_t Byte_PPU(char *)
287 { return 0x15;
288 }
290 int16_t Byte_SDC(char *)
291 { return 0x04;
292 }
294 int16_t Byte_SPD(char *)
295 { return 0x19;
296 }
298 int16_t Byte_SPE(char *)
299 { return 0x18;
300 }
302 int16_t Byte_TCT(char *)
303 { return 0x09;
304 }
306 int16_t Byte_UNL(char *)
307 { return 0x3f;
308 }
310 int16_t Byte_UNT(char *)
311 { return 0x5f;
312 }
314 int16_t Byte_LAD(char *)
315 { return 0x20|(GPIB.DeviceAddress&31);
316 }
318 int16_t Byte_TAD(char *)
319 { return 0x40|(GPIB.DeviceAddress&31);
320 }
322 int16_t Byte_SAD(char *)
323 {
324 if((GPIB.DeviceAddress & 0xff00)!=0)
325 return 0x60|((GPIB.DeviceAddress>>8)&31);
326 return 0;
327 }
329 #undef SPE
330 STRING(DCL); STRING(GET); STRING(GTL); STRING(LAD); STRING(LLO);
331 STRING(MLA); STRING(MSA); STRING(MTA); STRING(PPC); STRING(PPU);
332 STRING(SAD); STRING(SDC); STRING(SPD); STRING(SPE); STRING(TAD);
333 STRING(TCT); STRING(UNL); STRING(UNT);
335 static const struct Commands byteTable[]=
336 {
337 BYTE(DCL), BYTE(GET), BYTE(GTL), BYTE(LAD), BYTE(LLO),
338 BYTE(MLA), BYTE(MSA), BYTE(MTA), BYTE(PPC), BYTE(PPU),
339 BYTE(SAD), BYTE(SDC), BYTE(SPD), BYTE(SPE), BYTE(TAD),
340 BYTE(TCT), BYTE(UNL), BYTE(UNT),
341 { 0,0 },
342 };
344 #define Debug USB
346 int16_t Command_cmd_wrt(char *tail,bool atn)
347 {
348 GPIB.ATN(atn);
349 uint8_t eoi=0;
350 while(char c=*tail)
351 { const char *word=tail++;
353 if(c=='-')
354 { eoi=1;
355 continue;
356 }
358 uint8_t byte=0;
360 if(c=='"')
361 {
362 while((c=*tail)!='"' && c>=' ')
363 {
364 tail++;
366 GPIB.EOI(eoi && *tail=='"');
367 byte=GPIB.Out(c);
368 GPIB.EOI(false);
370 if(byte)
371 goto fail;
372 }
374 if(c!='"')
375 goto fail;
377 tail++;
378 }
379 else
380 {
381 uint8_t skip=0;
383 if(isdigit(c))
384 {
385 if(c=='0' && *tail=='x')
386 { tail++;
387 while(isxdigit(c=*tail))
388 {
389 byte<<=4;
390 if(c<='9')
391 byte+=c-'0';
392 else
393 byte+=tolower(c)-'a'+10;
394 tail++;
395 }
396 }
397 else
398 {
399 byte=c-'0';
400 while(isdigit(c=*tail))
401 {
402 byte=byte*10+c-'0';
403 tail++;
404 }
405 }
407 if(!(c==' ' || c==0))
408 goto fail;
409 }
410 else
411 {
412 while(isalnum(*tail))
413 tail++;
415 c=*tail;
416 *tail=0;
418 const ROM_PTR struct Commands *cmd=FindCommand(byteTable,word);
420 if(!cmd)
421 goto fail;
423 *tail=c;
424 Method f=(Method)(pgm_read_word(&cmd->Function));
426 byte=f(tail);
428 // handle cases where there is nothing to send
429 if(!byte)
430 skip=1;
431 }
433 if(!skip)
434 {
435 GPIB.EOI(eoi);
436 byte=GPIB.Out(byte);
437 GPIB.EOI(false);
438 if(byte)
439 goto fail;
440 }
441 }
443 tail=skipws(tail);
444 eoi=0;
445 }
447 // moved to rd
448 // GPIB.ATN(false);
449 return NONE;
451 fail:
452 GPIB.EOI(false);
453 GPIB.ATN(false);
454 return EINVCHAR;
455 }
457 int16_t Command_cmd(char *tail)
458 {
459 return Command_cmd_wrt(tail,true);
460 }
462 /* ..........................................................................
463 *
464 * ++data? -> <byte>
465 * return ~DIO[8:1]
466 */
467 int16_t Command_data(char *tail)
468 {
469 return GPIB.Data();
470 }
472 /* ..........................................................................
473 *
474 * ++DAV <value>
475 * ++DAV? -> <value>
476 *
477 * set or return ~DAV
478 */
479 int16_t Command_DAV(char *tail)
480 {
481 switch(*tail)
482 { case 0:
483 case '?':
484 return GPIB.DAV();
485 case '0':
486 case '1':
487 GPIB.DAV(*tail&1);
488 return NONE;
489 }
491 return EVALUE;
492 }
494 /* ..........................................................................
495 *
496 * ++DEBUG <value>
497 * do whatever we think is interesting
498 */
499 int16_t Command_DEBUG(char *tail)
500 {
501 if(*tail)
502 {
503 int16_t addr=strtoi(tail,(const char **)&tail);
505 if(!*tail)
506 {
507 USB<<addr<<endl;
508 USB.Flush();
510 _delay_ms(100);
512 Method f=(Method)addr;
513 cli();
514 UDCON = 1;
515 USBCON = (1<<FRZCLK); // disable USB
516 UCSR1B = 0;
517 EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0; ADCSRA = 0;
518 TIMSK0 = 0; TIMSK1 = 0; TIMSK3 = 0; TIMSK4 = 0; UCSR1B = 0; TWCR = 0;
519 DDRB = 0; DDRC = 0; DDRD = 0; DDRE = 0; DDRF = 0; TWCR = 0;
520 PORTB = 0; PORTC = 0; PORTD = 0; PORTE = 0; PORTF = 0;
521 _delay_ms(10);
523 f(tail);
524 sei();
525 }
526 }
528 USB<<ROMS("ddrb="); USB.Hex(uint8_t(DDRB));
529 USB<<ROMS(" portb="); USB.Hex(uint8_t(PORTB));
530 USB<<ROMS(" pinb="); USB.Hex(uint8_t(PINB));
531 USB<<endl;
533 USB<<ROMS("ddrc="); USB.Hex(uint8_t(DDRC));
534 USB<<ROMS(" portc="); USB.Hex(uint8_t(PORTC));
535 USB<<ROMS(" pinc="); USB.Hex(uint8_t(PINC));
536 USB<<endl;
538 USB<<ROMS("ddrd="); USB.Hex(uint8_t(DDRD));
539 USB<<ROMS(" portd="); USB.Hex(uint8_t(PORTD));
540 USB<<ROMS(" pind="); USB.Hex(uint8_t(PIND));
541 USB<<endl;
543 USB<<ROMS("ddre="); USB.Hex(uint8_t(DDRE));
544 USB<<ROMS(" porte="); USB.Hex(uint8_t(PORTE));
545 USB<<ROMS(" pine="); USB.Hex(uint8_t(PINE));
546 USB<<endl;
548 USB<<ROMS("ddrf="); USB.Hex(uint8_t(DDRF));
549 USB<<ROMS(" portf="); USB.Hex(uint8_t(PORTF));
550 USB<<ROMS(" pinf="); USB.Hex(uint8_t(PINF));
551 USB<<endl;
553 GPIB.Report();
554 USB<<endl;
556 return NONE;
557 }
559 /* ..........................................................................
560 *
561 * ++EOI <value>
562 * ++EOI? -> <value>
563 *
564 * set or return ~EOI
565 */
566 int16_t Command_EOI(char *tail)
567 {
568 switch(*tail)
569 { case 0:
570 case '?':
571 return GPIB.EOI();
572 case '0':
573 case '1':
574 GPIB.EOI(*tail&1);
575 return NONE;
576 }
578 return EVALUE;
579 }
581 /* ..........................................................................
582 *
583 * ++eoi <mode>
584 * if mode==0: no EOI asserted
585 * else: assert EOI on last byte of a command (default)
586 */
587 int16_t Command_eoi(char *tail)
588 {
589 Serial<<ROMS("eoi ")<<tail<<endl;
590 return ECOMMAND;
591 }
593 /* ..........................................................................
594 *
595 * ++eos <mode>
596 * if mode==0: append "\r\n" to commands
597 * elif mode==1: append "\r" to commands
598 * elif mode==2: append "\n" to commands
599 * else: do not append anything (default)
600 * ++eos {4|8} <byte>
601 * if arg=0,1,2,3: prologix
602 * else:
603 * if first arg==4 or 12: terminate reads on <byte>
604 * if first arg==8 or 12: set EOI when writing <byte>
605 */
606 int16_t Command_eos(char *tail)
607 {
608 Serial<<ROMS("eos ")<<tail<<endl;
609 return ECOMMAND;
610 }
612 /* ..........................................................................
613 *
614 * ++eot_char <byte>
615 * set eot_char
616 */
617 int16_t Command_eot_char(char *tail)
618 {
619 Serial<<ROMS("eot_char ")<<tail<<endl;
620 return ECOMMAND;
621 }
623 /* ..........................................................................
624 *
625 * ++eot_enable <eot>
626 * control how EOI when receiving data is handled
627 * if eot==0: ignore
628 * elif eot==1: send <eot_char>
629 * else: send ++eoi (default)
630 */
631 int16_t Command_eot_enable(char *tail)
632 {
633 Serial<<ROMS("eot_enable ")<<tail<<endl;
634 return ECOMMAND;
635 }
637 /* ..........................................................................
638 *
639 *
640 *
641 */
642 int16_t Command_error(char *tail)
643 {
644 Serial<<ROMS("error ")<<tail<<endl;
645 return ECOMMAND;
646 }
648 /* ..........................................................................
649 *
650 * ++gts <v>
651 * if v:
652 * transfer data as acceptor, until END
653 * float all pins
654 * ++mode 0 (device)
655 */
656 int16_t Command_gts(char *tail)
657 {
658 Serial<<ROMS("gts ")<<tail<<endl;
659 GPIB.Float();
660 return ECOMMAND;
661 }
663 /* ..........................................................................
664 *
665 * ++ver
666 * Display version string
667 */
668 void Version()
669 {
670 static const char version[] PROGMEM =
671 " version"
672 #include "version.h"
673 "\r\n";
674 USB<<ROMS("Kingswood USB-GPIB-32U4 ");
675 if(GPIB.MicroPro)
676 USB<<ROMS("MicroPro");
677 else
678 USB<<ROMS("Teensy");
679 USB<<ROM(version);
680 }
682 /* ..........................................................................
683 *
684 * ++IFC <value>
685 * ++IFC? -> <value>
686 * set or return ~IFC
687 */
688 int16_t Command_IFC(char *tail)
689 {
690 switch(*tail)
691 { case 0:
692 case '?':
693 return GPIB.IFC();
694 case '0':
695 case '1':
696 GPIB.IFC(*tail&1);
697 return NONE;
698 }
700 return EVALUE;
701 }
703 /* ..........................................................................
704 *
705 * ++lines? -> <byte>
706 * - return ~{EOI,ATN,SRQ,REN,IFC,NRFD,NDAC,DAV}
707 */
708 int16_t Command_lines(char *tail)
709 {
710 uint8_t byte=0;
711 if(GPIB.EOI()) byte|=1<<7;
712 if(GPIB.ATN()) byte|=1<<6;
713 if(GPIB.SRQ()) byte|=1<<5;
714 if(GPIB.REN()) byte|=1<<4;
715 if(GPIB.IFC()) byte|=1<<3;
716 if(GPIB.NRFD()) byte|=1<<2;
717 if(GPIB.NDAC()) byte|=1<<1;
718 if(GPIB.DAV()) byte|=1<<0;
720 return byte;
721 }
723 /* ..........................................................................
724 *
725 * ++llo [<device>]
726 * equivalent to ++cmd LAD SAD LLO UNL
727 */
728 int16_t Command_llo(char *tail)
729 {
730 Serial<<ROMS("llo ")<<tail<<endl;
731 return ECOMMAND;
732 }
734 /* ..........................................................................
735 *
736 * ++loc [<device>]
737 * equivalent to ++cmd TAD SAD UNL LAD SAD GTL
738 */
739 int16_t Command_loc(char *tail)
740 {
741 Serial<<ROMS("loc ")<<tail<<endl;
742 return ECOMMAND;
743 }
745 /* ..........................................................................
746 *
747 * ++lon <value>
748 * enable listen only (promiscuous listen) mode
749 */
750 int16_t Command_lon(char *tail)
751 {
752 Serial<<ROMS("lon ")<<tail<<endl;
753 return ECOMMAND;
754 }
756 /* ..........................................................................
757 *
758 * ++mode <mode>
759 * if mode==0 or mode=='d': device mode
760 * elif mode==1 or mode=='c': controller in command mode
761 * elif mode=='+': prompting mode (default)
762 */
763 int16_t Command_mode(char *tail)
764 {
765 Serial<<ROMS("mode ")<<tail<<endl;
766 return ECOMMAND;
767 }
769 /* ..........................................................................
770 *
771 * ++NDAC <value>
772 * ++NDAC? -> <value>
773 *
774 * set or return ~NDAC
775 */
776 int16_t Command_NDAC(char *tail)
777 {
778 switch(*tail)
779 { case 0:
780 case '?':
781 return GPIB.NDAC();
782 case '0':
783 case '1':
784 GPIB.NDAC(*tail&1);
785 return NONE;
786 }
788 return EVALUE;
789 }
791 /* ..........................................................................
792 *
793 * ++NRFD <value>
794 * ++NRFD? -> <value>
795 *
796 * set or return ~NRFD
797 */
798 int16_t Command_NRFD(char *tail)
799 {
800 switch(*tail)
801 { case 0:
802 case '?':
803 return GPIB.NRFD();
804 case '0':
805 case '1':
806 GPIB.NRFD(*tail&1);
807 return NONE;
808 }
810 return EVALUE;
811 }
813 /* ..........................................................................
814 *
815 * ++pct <address>
816 * pass CIC to device
817 * equivalent to ++cmd UNL LAD SAD TAD SAD TCT
818 */
819 int16_t Command_pct(char *tail)
820 {
821 Serial<<ROMS("pct ")<<tail<<endl;
822 return ECOMMAND;
823 }
825 /* ..........................................................................
826 *
827 * ++rd <count>
828 * read <count> bytes or until EOI or timeout
829 */
830 int16_t Command_rd(char *tail)
831 {
832 GPIB.NDAC(true);
833 GPIB.NRFD(true);
834 _delay_us(1);
835 GPIB.ATN(false);
837 while(true)
838 {
839 int16_t data=GPIB.In();
841 if(data<0)
842 break;
844 USB.SendSafeChar(data);
846 if(data&0xff00)
847 return data>>8;
848 }
850 return NONE;
851 }
853 /* ..........................................................................
854 *
855 * ++read [<end>]
856 * ++cmd UNL UNT TAD SAD MLA
857 * if end=="eoi": read until eoi
858 * elif end=="tmo": read until timeout
859 * elif end: read until byte <end>
860 * else: read until timeout
861 * ++read <device> <end>
862 * ++cmd UNL UNT <device> MLA
863 * if end=="eoi": read until eoi
864 * elif end=="tmo": read until timeout
865 * else: read until byte <end>
866 */
867 int16_t Command_read(char *tail)
868 {
869 uint8_t byte;
871 GPIB.ATN(true);
872 GPIB.EOI(false);
873 GPIB.Out(Byte_UNL(0));
874 GPIB.Out(Byte_MLA(0));
875 GPIB.Out(Byte_TAD(0));
876 byte=Byte_SAD(0);
877 if(byte)
878 GPIB.Out(byte);
880 int16_t r=Command_rd(tail);
882 GPIB.NDAC(false);
883 GPIB.NRFD(false);
885 USB<<endl;
886 return r<0 ? r : NONE;
887 }
889 /* ..........................................................................
890 *
891 * ++REN <value>
892 * ++REN? -> <value>
893 *
894 * set or return ~REN
895 */
896 int16_t Command_REN(char *tail)
897 {
898 switch(*tail)
899 { case 0:
900 case '?':
901 return GPIB.REN();
902 case '0':
903 case '1':
904 GPIB.REN(*tail&1);
905 return NONE;
906 }
908 return EVALUE;
909 }
911 /* ..........................................................................
912 *
913 * ++rpp -> <result>
914 * perform parallel poll by asserting ATN and EOI, reading response from data bus
915 */
916 int16_t Command_rpp(char *tail)
917 {
918 Serial<<ROMS("rpp ")<<tail<<endl;
919 return ECOMMAND;
920 }
922 /* ..........................................................................
923 *
924 * ++rsp <device> -> <result>
925 * read serial poll data, equivalent to
926 * ++cmd UNL MLA SPE TAD SAD
927 * ++rd <1 byte>
928 * ++cmd SPD
929 */
930 int16_t Command_rsp(char *tail)
931 {
932 Serial<<ROMS("rsp ")<<tail<<endl;
933 return ECOMMAND;
934 }
936 /* ..........................................................................
937 *
938 * ++rst
939 * - float all pins
940 * - set defaults
941 */
942 int16_t Command_rst(char *tail)
943 {
944 GPIB.Initialize();
945 return NONE;
946 }
948 /* ..........................................................................
949 *
950 * ++savecfg <state>
951 * (no operation)
952 * if state=1: save <mode> <addr> <auto> <aoi> <eos> <eot> <timeout> whenver changed
953 * else: do not save
954 */
955 int16_t Command_savecfg(char *tail)
956 {
957 Serial<<ROMS("savecfg ")<<tail<<endl;
958 return ECOMMAND;
959 }
961 /* ..........................................................................
962 *
963 * ++self <address> [<secondary>]
964 * ++self? -> <address>
965 * set or return address of USB-GPIB (default 0)
966 */
967 int16_t Command_self(char *tail)
968 {
969 if(*tail==0 || *tail=='?')
970 return GPIB.MyAddress;
972 uint16_t addr=strtoi(tail,(const char **)&tail);
973 USB.Hex(addr);
975 if(*tail)
976 { if((addr & 0xffe0)!=0)
977 return EVALUE;
979 tail=skipws(tail);
980 if(*tail)
981 {
982 uint16_t second=strtoi(tail,(const char **)&tail);
983 if((second & 0xffe0)!=0)
984 return EVALUE;
985 addr|=(0x60 | second)<<8;
986 }
987 }
988 USB.Hex(addr);
990 GPIB.MyAddress=addr;
992 return NONE;
993 }
995 /* ..........................................................................
996 *
997 * ++sic [<value>]
998 * send interface clear
999 */
1000 int16_t Command_sic(char *tail)
1002 GPIB.IFC(true);
1003 for(uint8_t i=0; i<100; i++)
1004 { _delay_ms(100);
1005 if(!(GPIB.DAV() || GPIB.NRFD() || GPIB.NDAC()))
1006 break;
1008 GPIB.IFC(false);
1010 return NONE;
1013 /* ..........................................................................
1015 * ++spoll
1016 * serial poll
1017 */
1018 int16_t Command_spoll(char *tail)
1020 Serial<<ROMS("spoll ")<<tail<<endl;
1021 return ECOMMAND;
1024 /* ..........................................................................
1026 * ++SRQ <value>
1027 * ++SRQ? -> <value>
1029 * set or return ~SRQ
1030 */
1031 int16_t Command_SRQ(char *tail)
1033 switch(*tail)
1034 { case 0:
1035 case '?':
1036 return GPIB.SRQ();
1037 case '0':
1038 case '1':
1039 GPIB.SRQ(*tail&1);
1040 return NONE;
1043 return EVALUE;
1046 /* ..........................................................................
1048 * ++status <value>
1049 * ++status? -> <value>
1050 * report device status
1051 * ++rsv <byte>
1052 * set or return status byte
1053 * if byte&0x40: SRQ=0
1054 */
1055 int16_t Command_status(char *tail)
1057 Serial<<ROMS("status ")<<tail<<endl;
1058 return ECOMMAND;
1061 /* ..........................................................................
1063 * ++tmo <timeout>
1064 * set timeout in ms (up to 65 seconds)
1065 */
1066 int16_t Command_tmo(char *tail)
1068 if(*tail==0 || *tail=='?')
1069 return GPIB.Timeout;
1071 uint16_t tmo=strtoi(tail,(const char **)&tail);
1072 if(*tail)
1073 return EVALUE;
1075 GPIB.Timeout=tmo;
1076 return NONE;
1079 /* ..........................................................................
1081 * ++trg <device> [<device>...]
1082 * triggers one or more devices
1083 * equivalent to ++cmd MTA UNL LAD SAD ... GET
1084 */
1085 int16_t Command_trg(char *tail)
1087 Serial<<ROMS("trg ")<<tail<<endl;
1088 return ECOMMAND;
1091 /* ..........................................................................
1093 * ++ver
1094 * show version
1095 */
1096 int16_t Command_ver(char *tail)
1098 Version();
1099 return NONE;
1102 /* ..........................................................................
1104 * ++wrt <bytes>
1105 * - set ATN=1, send bytes, set ATN=float
1106 * - for each byte, if code is preceded by "-": EOI=0
1107 * else: EOI=1
1108 */
1109 int16_t Command_wrt(char *tail)
1111 return Command_cmd_wrt(tail,false);
1114 /* ..........................................................................
1116 * ++write <bytes>
1117 * - set ATN=1, send MTA UNL LAD SAD, followed by bytes
1118 */
1119 int16_t Command_write(char *tail)
1121 uint8_t byte;
1123 GPIB.ATN(true);
1124 GPIB.EOI(false);
1125 GPIB.Out(Byte_MTA(0));
1126 GPIB.Out(Byte_UNL(0));
1127 GPIB.Out(Byte_LAD(0));
1128 byte=Byte_SAD(0);
1129 if(byte)
1130 GPIB.Out(byte);
1132 int16_t r=Command_wrt(tail);
1134 return r;
1138 /* ----- command strings ---------------------------------------------------- */
1140 STRING(addr); STRING(ATN); STRING(auto); STRING(cac);
1141 STRING(clr); STRING(cmd); STRING(data); STRING(DAV);
1142 STRING(DEBUG); STRING(EOI); STRING(eoi); STRING(eos);
1143 STRING(eot_char); STRING(eot_enable);
1144 STRING(error); STRING(gts); STRING(help); STRING(IFC);
1145 STRING(lines); STRING(llo);
1146 STRING(loc); STRING(lon); STRING(mode); STRING(NDAC);
1147 STRING(NRFD); STRING(pct); STRING(rd); STRING(read);
1148 STRING(REN); STRING(rpp);
1149 STRING(rsp); STRING(rst); STRING(rsv); STRING(savecfg);
1150 STRING(self); STRING(sic); STRING(spoll); STRING(sre);
1151 STRING(SRQ); STRING(status); STRING(tmo); STRING(trg);
1152 STRING(ver); STRING(write); STRING(wrt);
1154 #define COMMAND(s) { String_##s, Command_##s }
1156 int16_t Command_help(char *tail);
1157 const struct Commands commandTable[]=
1159 COMMAND(ATN), COMMAND(DAV), COMMAND(DEBUG), COMMAND(EOI),
1160 COMMAND(IFC), COMMAND(NDAC), COMMAND(NRFD), COMMAND(REN),
1161 COMMAND(SRQ),
1163 COMMAND(addr), COMMAND(auto), COMMAND(cac),
1164 COMMAND(clr), COMMAND(cmd), COMMAND(data),
1165 COMMAND(eoi), COMMAND(eos), COMMAND(eot_char),
1166 COMMAND(eot_enable),
1167 COMMAND(error), COMMAND(gts), COMMAND(help),
1168 COMMAND(lines), COMMAND(llo), COMMAND(loc), COMMAND(lon),
1169 COMMAND(mode), COMMAND(pct),
1170 COMMAND(rd), COMMAND(read),
1171 COMMAND(rpp), COMMAND(rsp), COMMAND(rst),
1172 { String_rsv, Command_status },
1173 COMMAND(savecfg),
1174 COMMAND(self), COMMAND(sic),
1175 COMMAND(spoll),
1176 { String_sre, Command_REN },
1177 COMMAND(status), COMMAND(tmo), COMMAND(trg),
1178 COMMAND(ver), COMMAND(write), COMMAND(wrt),
1179 { 0,0 },
1180 };
1182 const ROM_PTR struct Commands *FindCommand(const ROM_PTR struct Commands *table,
1183 const char *command)
1185 uint8_t lim;
1186 for(lim=0; pgm_read_word(&table[lim].Command)!=0; lim++)
1187 { }
1189 for(; lim!=0; lim>>=1)
1191 const ROM_PTR struct Commands *p = table + (lim >> 1);
1192 const ROM_PTR char *entry=(const ROM_PTR char *)pgm_read_word(&p->Command);
1193 int8_t cmp=strcmp_P(command, entry);
1195 if(cmp==0)
1196 return p;
1197 else if(cmp > 0)
1198 { /* command > p: move right */
1199 table = p + 1;
1200 lim--;
1202 else
1203 { /* move left */ }
1206 return 0;
1210 int16_t Command(char *command)
1211 { char c;
1212 char *tail=command;
1214 if(*command<' ')
1215 return 0;
1217 int r=ECOMMAND;
1218 if(*command=='?')
1219 r=Command_help(command+1);
1220 else
1222 while(isalnum(*tail))
1223 tail++;
1225 c=*tail;
1226 *tail=0;
1228 const ROM_PTR struct Commands *cmd=FindCommand(commandTable,command);
1230 if(cmd)
1232 *tail=c;
1233 tail=skipws(tail);
1235 Method f=(Method)(pgm_read_word(&cmd->Function));
1236 r=f(tail);
1240 if(r!=NONE)
1241 USB<<r<<endl;
1242 return r;
1246 /* ..........................................................................
1248 * ++help
1249 * show available commands
1250 */
1251 int16_t Command_help(char *tail)
1253 Version();
1254 USB<<ROMS("Available commands:");
1256 const char *p;
1257 for(uint8_t i=0; (p=(const char *)pgm_read_word(&commandTable[i].Command))!=0; i++)
1259 char c=pgm_read_byte(p);
1261 if(*tail=='?' || c>='a' || c==*tail)
1263 USB<<ROMS("\r\n ++")<<ROM(p);
1264 if(p==String_cmd)
1266 USB<<ROMS(" [-]<byte> ... or one of:\r\n ");
1267 for(uint8_t i=0; (p=(const char *)pgm_read_word(&byteTable[i].Command))!=0; i++)
1268 USB<<' '<<ROM(p);
1272 USB<<endl;
1273 return NONE;
1276 /* ----- EOF commands.cc ----- */