changeset 5:1a405bda2ffe

rewrite gpib using state machine instead of procedural code, add proper timeout, command queueing, several new commands, improve hardcopy utility
author Frank Kingswood <frank@kingswood-consulting.co.uk>
date Sat, 29 Mar 2014 23:23:58 +0000
parents 1e7540113e8d
children acbd0ddd002b
files Makefile avr32u4.h commands.cc formatting.h gpib.cc gpib.h hardcopy main.cc program
diffstat 9 files changed, 900 insertions(+), 525 deletions(-) [+]
line wrap: on
line diff
     1.1 --- a/Makefile	Sat Mar 29 09:11:28 2014 +0000
     1.2 +++ b/Makefile	Sat Mar 29 23:23:58 2014 +0000
     1.3 @@ -5,7 +5,8 @@
     1.4  CPU:=atmega32u4
     1.5  
     1.6  CFLAGS:=-mmcu=$(CPU) -mtiny-stack -O3 -Os -DCPU=$(CPU) -DF_CPU=16 \
     1.7 -         -Werror -foptimize-sibling-calls -fpeephole -fpeephole2  \
     1.8 +         -Wall -Wno-uninitialized -Werror \
     1.9 +         -foptimize-sibling-calls -fpeephole -fpeephole2  \
    1.10           --param max-unrolled-insns=3 --param max-unroll-times=3  \
    1.11           --param inline-unit-growth=1 -fno-tree-scev-cprop -fsplit-wide-types
    1.12  
     2.1 --- a/avr32u4.h	Sat Mar 29 09:11:28 2014 +0000
     2.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.3 @@ -1,83 +0,0 @@
     2.4 -
     2.5 -// Teensy 2.0 has two complete 8-bit ports PB and PD
     2.6 -// Arduino Leonardo and "Pro Micro" have 15 out of 16, good try!
     2.7 -// 20 mA/pin, 100 mA max for 8-bit port
     2.8 -//
     2.9 -// 32U4       Arduino  GPIB      32U4       Arduino  GPIB
    2.10 -// ---------- -----    ----      ---------- -----    ----
    2.11 -// PB0 (SS)   -      : DIO1      PD0 (INT0) "d3"   : EOI
    2.12 -// PB1 (SCLK) "sck"  : DIO2      PD1 (INT1) "d2"   : NRFD
    2.13 -// PB2 (MOSI) "mosi" : DIO3      PD2 (INT2) "rxi"  : NDAC
    2.14 -// PB3 (MISO) "miso" : DIO4      PD3 (INT3) "txo"  : SRQ
    2.15 -// PB4        "d8"   : DIO5      PD4        "d4"     (pull down for arduino)
    2.16 -// PB5        "d9"   : DIO6      PD5        (LED)    (debug serial)
    2.17 -// PB6        "d10"  : DIO7      PD6 (LED)  -        -
    2.18 -// PB7        -      : DIO8      PD7        "d6"   : DAV
    2.19 -//
    2.20 -// Other pins
    2.21 -//
    2.22 -// 32U4       Arduino  GPIB      32U4       Arduino  GPIB
    2.23 -// ---------- -----    ----      ---------- -----    ----
    2.24 -// PF0 (ADC0) -        -         PC6        "d5"     DIO8
    2.25 -// PF1 (ADC1) -        -         PC7        -
    2.26 -// PF4 (ADC4) "a3"   : ATN       PE6        "d7"     DIO1
    2.27 -// PF5 (ADC5) "a2"   : IFC
    2.28 -// PF6 (ADC6) "a1"   : REN
    2.29 -// PF7 (ADC7) "a0"   : 
    2.30 -//
    2.31 -// Teensy has LED on PD6 to GND (shared)
    2.32 -// Arduino has LED on PD5 to VCC
    2.33 -//             and on PB0 to VCC (shared with DIO1)
    2.34 -
    2.35 -
    2.36 -/* -------------------------------------------------------------------------- */
    2.37 -
    2.38 -
    2.39 -// GPIB Connector
    2.40 -//
    2.41 -// Pin  Name    Signal Description          Pin  Name    Signal Description
    2.42 -// ---  ------  -------------------------   ---  ------  -------------------------
    2.43 -// 1    DIO1    Data Input/Output Bit 1     13   DIO5    Data Input/Output Bit 5
    2.44 -// 2    DIO2    Data Input/Output Bit 2     14   DIO6    Data Input/Output Bit 6
    2.45 -// 3    DIO3    Data Input/Output Bit 3     15   DIO7    Data Input/Output Bit 7
    2.46 -// 4    DIO4    Data Input/Output Bit 4     16   DIO8    Data Input/Output Bit 8
    2.47 -// 5    EIO     End-Or-Identify             17   REN     Remote Enable
    2.48 -// 6    DAV     Data Valid                  18   GND     Ground DAV
    2.49 -// 7    NRFD    Not Ready For Data          19   GND     Ground NRFD
    2.50 -// 8    NDAC    Not Data Accepted           20   GND     Ground NDAC
    2.51 -// 9    IFC     Interface Clear             21   GND     Ground IFC
    2.52 -// 10   SRQ     Service Request             22   GND     Ground SRQ
    2.53 -// 11   ATN     Attention                   23   GND     Ground ATN
    2.54 -// 12   Shield  Chassis Ground              24   GND     Ground DIO, REN, EOI
    2.55 -//
    2.56 -// DAV can be used to enable 74ABT541 output buffer (sinks 64 mA)
    2.57 -// Use 100R between A and B port.
    2.58 -//
    2.59 -//             +---+--+---+
    2.60 -// BUFEN = GAB |1  +--+ 20| VCC
    2.61 -//          A1 |2       19| /GBA = VCC
    2.62 -//          A2 |3       18| B1
    2.63 -//          A3 |4       17| B2
    2.64 -//   AVR    A4 |5  74   16| B3
    2.65 -//   PB     A5 |6  623  15| B4   GPIB
    2.66 -//          A6 |7       14| B5   BUS
    2.67 -//          A7 |8       13| B6
    2.68 -//          A8 |9       12| B7
    2.69 -//         GND |10      11| B8
    2.70 -//             +----------+
    2.71 -//
    2.72 -// Handshake  Output
    2.73 -// ---------  ---------
    2.74 -//   NRFD     Listener
    2.75 -//   NDAC     Listener
    2.76 -//   DAV      Talker
    2.77 -//
    2.78 -// Control    Output
    2.79 -// ---------  ---------
    2.80 -//   ATN      Controller
    2.81 -//   IFC      Controller
    2.82 -//   REN      Controller
    2.83 -//   SRQ      Any
    2.84 -//   EOI      Talker and Controller
    2.85 -//
    2.86 -// Parallel poll ATN & EIO asserted -> must respond within 200ns
     3.1 --- a/commands.cc	Sat Mar 29 09:11:28 2014 +0000
     3.2 +++ b/commands.cc	Sat Mar 29 23:23:58 2014 +0000
     3.3 @@ -86,6 +86,88 @@
     3.4     return value;
     3.5  }
     3.6  
     3.7 +
     3.8 +/* ----- GPIB defined command bytes ----------------------------------------- */
     3.9 +
    3.10 +int16_t Byte_MLA(char *)
    3.11 +{  return GPIB.CMD_SOURCE | GPIB.CMD_ATN | 0x20 | (GPIB.MyAddress&31);
    3.12 +}
    3.13 +
    3.14 +int16_t Byte_MSA(char *)
    3.15 +{
    3.16 +   if((GPIB.MyAddress & 0xff00)!=0)
    3.17 +      return GPIB.CMD_SOURCE | GPIB.CMD_ATN | 0x60 | ((GPIB.MyAddress>>8)&31);
    3.18 +   return 0;
    3.19 +}
    3.20 +
    3.21 +int16_t Byte_MTA(char *)
    3.22 +{  return GPIB.CMD_SOURCE | GPIB.CMD_ATN | 0x40 | (GPIB.MyAddress&31);
    3.23 +}
    3.24 +
    3.25 +int16_t Byte_DCL(char *)
    3.26 +{  return GPIB.CMD_SOURCE | GPIB.CMD_ATN | 0x14;
    3.27 +}
    3.28 +
    3.29 +int16_t Byte_GET(char *)
    3.30 +{  return GPIB.CMD_SOURCE | GPIB.CMD_ATN | 0x08;
    3.31 +}
    3.32 +
    3.33 +int16_t Byte_GTL(char *)
    3.34 +{  return GPIB.CMD_SOURCE | GPIB.CMD_ATN | 0x01;
    3.35 +}
    3.36 +
    3.37 +int16_t Byte_LLO(char *)
    3.38 +{  return GPIB.CMD_SOURCE | GPIB.CMD_ATN | 0x11;
    3.39 +}
    3.40 +
    3.41 +int16_t Byte_PPC(char *)
    3.42 +{  return GPIB.CMD_SOURCE | GPIB.CMD_ATN | 0x05;
    3.43 +}
    3.44 +
    3.45 +int16_t Byte_PPU(char *)
    3.46 +{  return GPIB.CMD_SOURCE | GPIB.CMD_ATN | 0x15;
    3.47 +}
    3.48 +
    3.49 +int16_t Byte_SDC(char *)
    3.50 +{  return GPIB.CMD_SOURCE | GPIB.CMD_ATN | 0x04;
    3.51 +}
    3.52 +
    3.53 +int16_t Byte_SPD(char *)
    3.54 +{  return GPIB.CMD_SOURCE | GPIB.CMD_ATN | 0x19;
    3.55 +}
    3.56 +
    3.57 +int16_t Byte_SPE(char *)
    3.58 +{  return GPIB.CMD_SOURCE | GPIB.CMD_ATN | 0x18;
    3.59 +}
    3.60 +
    3.61 +int16_t Byte_TCT(char *)
    3.62 +{  return GPIB.CMD_SOURCE | GPIB.CMD_ATN | 0x09;
    3.63 +}
    3.64 +
    3.65 +int16_t Byte_UNL(char *)
    3.66 +{  return GPIB.CMD_SOURCE | GPIB.CMD_ATN | 0x3f;
    3.67 +}
    3.68 +
    3.69 +int16_t Byte_UNT(char *)
    3.70 +{  return GPIB.CMD_SOURCE | GPIB.CMD_ATN | 0x5f;
    3.71 +}
    3.72 +
    3.73 +int16_t Byte_LAD(char *)
    3.74 +{  return GPIB.CMD_SOURCE | GPIB.CMD_ATN | 0x20 | (GPIB.DeviceAddress&31);
    3.75 +}
    3.76 +
    3.77 +int16_t Byte_TAD(char *)
    3.78 +{  return GPIB.CMD_SOURCE | GPIB.CMD_ATN | 0x40 | (GPIB.DeviceAddress&31);
    3.79 +}
    3.80 +
    3.81 +int16_t Byte_SAD(char *)
    3.82 +{
    3.83 +   if((GPIB.DeviceAddress & 0xff00)!=0)
    3.84 +      return GPIB.CMD_SOURCE | GPIB.CMD_ATN | 0x60 | ((GPIB.DeviceAddress>>8)&31);
    3.85 +   return 0;
    3.86 +}
    3.87 +
    3.88 +
    3.89  /* ----- command functions -------------------------------------------------- */
    3.90  
    3.91  /* Return codes
    3.92 @@ -158,7 +240,6 @@
    3.93   */
    3.94  int16_t Command_ATN(char *tail)
    3.95  {
    3.96 -   int16_t i;
    3.97     switch(*tail)
    3.98     {  case 0:
    3.99        case '?':
   3.100 @@ -192,34 +273,7 @@
   3.101   */
   3.102  int16_t Command_cac(char *tail)
   3.103  {
   3.104 -   GPIB.ATN(false);
   3.105 -   _delay_ms(1);
   3.106 -   GPIB.EOI(false);
   3.107 -   _delay_ms(1);
   3.108 -   GPIB.NRFD(false);
   3.109 -   _delay_ms(1);
   3.110 -   GPIB.DAV(false);
   3.111 -   _delay_ms(1);
   3.112 -   GPIB.NDAC(false);
   3.113 -   _delay_ms(1);
   3.114 -
   3.115 -   if(*tail!='1')
   3.116 -   {
   3.117 -      static const uint16_t TIMEOUT=2000; // 2 seconds
   3.118 -      uint16_t timeout;
   3.119 -      for(timeout=TIMEOUT; timeout!=0; timeout--)
   3.120 -      {
   3.121 -         _delay_ms(1);
   3.122 -
   3.123 -         if(!(GPIB.ATN() || GPIB.NRFD() || GPIB.NDAC() || GPIB.DAV()))
   3.124 -            break;
   3.125 -      }
   3.126 -
   3.127 -      if(!timeout)
   3.128 -         return ETIMEOUT;
   3.129 -   }
   3.130 -
   3.131 -   GPIB.Controller();
   3.132 +   GPIB.Command(GPIB.CMD_CONTROLLER | *tail);
   3.133     return NONE;
   3.134  }
   3.135  
   3.136 @@ -229,14 +283,23 @@
   3.137   * ++clr [<device>]
   3.138   *    - selected/universal device clear
   3.139   *    - if device=="all":
   3.140 - *     ++cmd MTA UNL DCL
   3.141 - *     else:
   3.142 - *     ++cmd MTA UNL LAD SAD SDC
   3.143 + *         ++cmd MTA UNL DCL
   3.144 + *      else:
   3.145 + *         ++cmd MTA UNL LAD SAD SDC
   3.146   */
   3.147  int16_t Command_clr(char *tail)
   3.148  {
   3.149 -   Serial<<ROMS("clr ")<<tail<<endl;
   3.150 -   return ECOMMAND;
   3.151 +   GPIB.Command(Byte_MTA(0));
   3.152 +   GPIB.Command(Byte_UNL(0));
   3.153 +   if(!strcmp_P(tail, PSTR("all")))
   3.154 +      GPIB.Command(Byte_DCL(0));
   3.155 +   else
   3.156 +   {
   3.157 +      GPIB.Command(Byte_LAD(0));
   3.158 +      GPIB.Command(Byte_SAD(0));
   3.159 +      GPIB.Command(Byte_SDC(0));
   3.160 +   }
   3.161 +   return NONE;
   3.162  }
   3.163  
   3.164  /* ..........................................................................
   3.165 @@ -249,83 +312,6 @@
   3.166  
   3.167  #define BYTE(s) { String_##s, Byte_##s }
   3.168  
   3.169 -int16_t Byte_MLA(char *)
   3.170 -{  return 0x20|(GPIB.MyAddress&31);
   3.171 -}
   3.172 -
   3.173 -int16_t Byte_MSA(char *)
   3.174 -{
   3.175 -   if((GPIB.MyAddress & 0xff00)!=0)
   3.176 -      return 0x60|((GPIB.MyAddress>>8)&31);
   3.177 -}
   3.178 -
   3.179 -int16_t Byte_MTA(char *)
   3.180 -{  return 0x40|(GPIB.MyAddress&31);
   3.181 -}
   3.182 -
   3.183 -int16_t Byte_DCL(char *)
   3.184 -{  return 0x14;
   3.185 -}
   3.186 -
   3.187 -int16_t Byte_GET(char *)
   3.188 -{  return 0x08;
   3.189 -}
   3.190 -
   3.191 -int16_t Byte_GTL(char *)
   3.192 -{  return 0x01;
   3.193 -}
   3.194 -
   3.195 -int16_t Byte_LLO(char *)
   3.196 -{  return 0x11;
   3.197 -}
   3.198 -
   3.199 -int16_t Byte_PPC(char *)
   3.200 -{  return 0x05;
   3.201 -}
   3.202 -
   3.203 -int16_t Byte_PPU(char *)
   3.204 -{  return 0x15;
   3.205 -}
   3.206 -
   3.207 -int16_t Byte_SDC(char *)
   3.208 -{  return 0x04;
   3.209 -}
   3.210 -
   3.211 -int16_t Byte_SPD(char *)
   3.212 -{  return 0x19;
   3.213 -}
   3.214 -
   3.215 -int16_t Byte_SPE(char *)
   3.216 -{  return 0x18;
   3.217 -}
   3.218 -
   3.219 -int16_t Byte_TCT(char *)
   3.220 -{  return 0x09;
   3.221 -}
   3.222 -
   3.223 -int16_t Byte_UNL(char *)
   3.224 -{  return 0x3f;
   3.225 -}
   3.226 -
   3.227 -int16_t Byte_UNT(char *)
   3.228 -{  return 0x5f;
   3.229 -}
   3.230 -
   3.231 -int16_t Byte_LAD(char *)
   3.232 -{  return 0x20|(GPIB.DeviceAddress&31);
   3.233 -}
   3.234 -
   3.235 -int16_t Byte_TAD(char *)
   3.236 -{  return 0x40|(GPIB.DeviceAddress&31);
   3.237 -}
   3.238 -
   3.239 -int16_t Byte_SAD(char *)
   3.240 -{
   3.241 -   if((GPIB.DeviceAddress & 0xff00)!=0)
   3.242 -      return 0x60|((GPIB.DeviceAddress>>8)&31);
   3.243 -   return 0;
   3.244 -}
   3.245 -
   3.246  #undef SPE
   3.247  STRING(DCL); STRING(GET); STRING(GTL); STRING(LAD); STRING(LLO);
   3.248  STRING(MLA); STRING(MSA); STRING(MTA); STRING(PPC); STRING(PPU);
   3.249 @@ -345,8 +331,9 @@
   3.250  
   3.251  int16_t Command_cmd_wrt(char *tail,bool atn)
   3.252  {
   3.253 -   GPIB.ATN(atn);
   3.254 +   //GPIB.ATN(atn);
   3.255     uint8_t eoi=0;
   3.256 +   uint16_t cmd;
   3.257     while(char c=*tail)
   3.258     {  const char *word=tail++;
   3.259  
   3.260 @@ -363,12 +350,19 @@
   3.261           {
   3.262              tail++;
   3.263  
   3.264 -            GPIB.EOI(eoi && *tail=='"');
   3.265 -            byte=GPIB.Out(c);
   3.266 -            GPIB.EOI(false);
   3.267 +            //GPIB.EOI(eoi && *tail=='"');
   3.268 +            //byte=GPIB.Out(c);
   3.269 +            //GPIB.EOI(false);
   3.270 +            //
   3.271 +            //if(byte)
   3.272 +            //   goto fail;
   3.273  
   3.274 -            if(byte)
   3.275 -               goto fail;
   3.276 +            cmd=GPIB.CMD_SOURCE | (c&0xff);
   3.277 +            if(atn)
   3.278 +               cmd|=GPIB.CMD_ATN;
   3.279 +            if(eoi && *tail=='"')
   3.280 +               cmd|=GPIB.CMD_EOI;
   3.281 +            GPIB.Command(cmd);
   3.282           }
   3.283  
   3.284           if(c!='"')
   3.285 @@ -432,11 +426,18 @@
   3.286  
   3.287           if(!skip)
   3.288           {
   3.289 -            GPIB.EOI(eoi);
   3.290 -            byte=GPIB.Out(byte);
   3.291 -            GPIB.EOI(false);
   3.292 -            if(byte)
   3.293 -               goto fail;
   3.294 +            //GPIB.EOI(eoi);
   3.295 +            //byte=GPIB.Out(byte);
   3.296 +            //GPIB.EOI(false);
   3.297 +            //if(byte)
   3.298 +            //   goto fail;
   3.299 +
   3.300 +            cmd=GPIB.CMD_SOURCE | byte;
   3.301 +            if(atn)
   3.302 +               cmd|=GPIB.CMD_ATN;
   3.303 +            if(eoi)
   3.304 +               cmd|=GPIB.CMD_EOI;
   3.305 +            GPIB.Command(cmd);
   3.306           }
   3.307        }
   3.308  
   3.309 @@ -444,13 +445,11 @@
   3.310        eoi=0;
   3.311     }
   3.312  
   3.313 -   // moved to rd
   3.314 -   // GPIB.ATN(false);
   3.315     return NONE;
   3.316  
   3.317  fail:
   3.318 -   GPIB.EOI(false);
   3.319 -   GPIB.ATN(false);
   3.320 +   //GPIB.EOI(false);
   3.321 +   //GPIB.ATN(false);
   3.322     return EINVCHAR;
   3.323  }
   3.324  
   3.325 @@ -727,8 +726,12 @@
   3.326   */
   3.327  int16_t Command_llo(char *tail)
   3.328  {
   3.329 -   Serial<<ROMS("llo ")<<tail<<endl;
   3.330 -   return ECOMMAND;
   3.331 +   GPIB.Command(Byte_LAD(0));
   3.332 +   GPIB.Command(Byte_SAD(0));
   3.333 +   GPIB.Command(Byte_LLO(0));
   3.334 +   GPIB.Command(Byte_UNL(0));
   3.335 +
   3.336 +   return NONE;
   3.337  }
   3.338  
   3.339  /* ..........................................................................
   3.340 @@ -738,8 +741,14 @@
   3.341   */
   3.342  int16_t Command_loc(char *tail)
   3.343  {
   3.344 -   Serial<<ROMS("loc ")<<tail<<endl;
   3.345 -   return ECOMMAND;
   3.346 +   GPIB.Command(Byte_TAD(0));
   3.347 +   GPIB.Command(Byte_SAD(0));
   3.348 +   GPIB.Command(Byte_UNL(0));
   3.349 +   GPIB.Command(Byte_LAD(0));
   3.350 +   GPIB.Command(Byte_SAD(0));
   3.351 +   GPIB.Command(Byte_GTL(0));
   3.352 +
   3.353 +   return NONE;
   3.354  }
   3.355  
   3.356  /* ..........................................................................
   3.357 @@ -818,8 +827,15 @@
   3.358   */
   3.359  int16_t Command_pct(char *tail)
   3.360  {
   3.361 -   Serial<<ROMS("pct ")<<tail<<endl;
   3.362 -   return ECOMMAND;
   3.363 +   GPIB.Command(Byte_UNL(0));
   3.364 +   GPIB.Command(Byte_LAD(0));
   3.365 +   GPIB.Command(Byte_SAD(0));
   3.366 +   GPIB.Command(Byte_TAD(0));
   3.367 +   GPIB.Command(Byte_SAD(0));
   3.368 +   GPIB.Command(Byte_TCT(0));
   3.369 +   GPIB.Command(GPIB.CMD_RELEASE);
   3.370 +
   3.371 +   return NONE;
   3.372  }
   3.373  
   3.374  /* ..........................................................................
   3.375 @@ -829,23 +845,7 @@
   3.376   */
   3.377  int16_t Command_rd(char *tail)
   3.378  {
   3.379 -   GPIB.NDAC(true);
   3.380 -   GPIB.NRFD(true);
   3.381 -   _delay_us(1);
   3.382 -   GPIB.ATN(false);
   3.383 -
   3.384 -   while(true)
   3.385 -   {
   3.386 -      int16_t data=GPIB.In();
   3.387 -
   3.388 -      if(data<0)
   3.389 -         break;
   3.390 -
   3.391 -      USB.SendSafeChar(data);
   3.392 -
   3.393 -      if(data&0xff00)
   3.394 -         return data>>8;
   3.395 -   }
   3.396 +   GPIB.Command(GPIB.CMD_ACCEPT);
   3.397  
   3.398     return NONE;
   3.399  }
   3.400 @@ -866,24 +866,25 @@
   3.401   */
   3.402  int16_t Command_read(char *tail)
   3.403  {
   3.404 -   uint8_t byte;
   3.405 +   GPIB.Command(Byte_UNL(0));
   3.406 +   GPIB.Command(Byte_MLA(0));
   3.407 +   GPIB.Command(Byte_TAD(0));
   3.408 +   GPIB.Command(Byte_SAD(0));
   3.409  
   3.410 -   GPIB.ATN(true);
   3.411 -   GPIB.EOI(false);
   3.412 -   GPIB.Out(Byte_UNL(0));
   3.413 -   GPIB.Out(Byte_MLA(0));
   3.414 -   GPIB.Out(Byte_TAD(0));
   3.415 -   byte=Byte_SAD(0);
   3.416 -   if(byte)
   3.417 -      GPIB.Out(byte);
   3.418 +   uint16_t cmd=GPIB.CMD_ACCEPT;
   3.419 +   if(!strcmp_P(tail, PSTR("eoi")))
   3.420 +   { }
   3.421 +   else if(!strcmp_P(tail, PSTR("tmo")))
   3.422 +      cmd|=GPIB.CMD_AC_TMO;
   3.423 +   else if(*tail)
   3.424 +   {
   3.425 +      uint8_t n=strtoi(tail,(const char **)&tail);
   3.426 +      cmd|=GPIB.CMD_AC_COUNT | n;
   3.427 +   }
   3.428  
   3.429 -   int16_t r=Command_rd(tail);
   3.430 +   GPIB.Command(cmd);
   3.431  
   3.432 -   GPIB.NDAC(false);
   3.433 -   GPIB.NRFD(false);
   3.434 -
   3.435 -   USB<<endl;
   3.436 -   return r<0 ? r : NONE;
   3.437 +   return NONE;
   3.438  }
   3.439  
   3.440  /* ..........................................................................
   3.441 @@ -915,8 +916,8 @@
   3.442   */
   3.443  int16_t Command_rpp(char *tail)
   3.444  {
   3.445 -   Serial<<ROMS("rpp ")<<tail<<endl;
   3.446 -   return ECOMMAND;
   3.447 +   GPIB.Command(GPIB.CMD_PARPOLL);
   3.448 +   return NONE;
   3.449  }
   3.450  
   3.451  /* ..........................................................................
   3.452 @@ -929,8 +930,15 @@
   3.453   */
   3.454  int16_t Command_rsp(char *tail)
   3.455  {
   3.456 -   Serial<<ROMS("rsp ")<<tail<<endl;
   3.457 -   return ECOMMAND;
   3.458 +   GPIB.Command(Byte_UNL(0));
   3.459 +   GPIB.Command(Byte_MLA(0));
   3.460 +   GPIB.Command(Byte_SPE(0));
   3.461 +   GPIB.Command(Byte_TAD(0));
   3.462 +   GPIB.Command(Byte_SAD(0));
   3.463 +   GPIB.Command(GPIB.CMD_ACCEPT | GPIB.CMD_AC_COUNT | 0x01);
   3.464 +   GPIB.Command(Byte_SPD(0));
   3.465 +
   3.466 +   return NONE;
   3.467  }
   3.468  
   3.469  /* ..........................................................................
   3.470 @@ -999,30 +1007,12 @@
   3.471   */
   3.472  int16_t Command_sic(char *tail)
   3.473  {
   3.474 -   GPIB.IFC(true);
   3.475 -   for(uint8_t i=0; i<100; i++)
   3.476 -   {  _delay_ms(100);
   3.477 -      if(!(GPIB.DAV() || GPIB.NRFD() || GPIB.NDAC()))
   3.478 -         break;
   3.479 -   }
   3.480 -   GPIB.IFC(false);
   3.481 -
   3.482 +   GPIB.Command(GPIB.CMD_SIC);
   3.483     return NONE;
   3.484  }
   3.485  
   3.486  /* ..........................................................................
   3.487   *
   3.488 - * ++spoll
   3.489 - *     serial poll
   3.490 - */
   3.491 -int16_t Command_spoll(char *tail)
   3.492 -{
   3.493 -   Serial<<ROMS("spoll ")<<tail<<endl;
   3.494 -   return ECOMMAND;
   3.495 -}
   3.496 -
   3.497 -/* ..........................................................................
   3.498 - *
   3.499   * ++SRQ <value>
   3.500   * ++SRQ? -> <value>
   3.501   *
   3.502 @@ -1049,7 +1039,7 @@
   3.503   * ++status? -> <value>
   3.504   *     report device status
   3.505   * ++rsv <byte>
   3.506 - *     set or return status byte
   3.507 + *     set or return status byte to be used when we are a slave
   3.508   *     if byte&0x40: SRQ=0
   3.509   */
   3.510  int16_t Command_status(char *tail)
   3.511 @@ -1084,8 +1074,13 @@
   3.512   */
   3.513  int16_t Command_trg(char *tail)
   3.514  {
   3.515 -   Serial<<ROMS("trg ")<<tail<<endl;
   3.516 -   return ECOMMAND;
   3.517 +   GPIB.Command(Byte_MTA(0));
   3.518 +   GPIB.Command(Byte_UNL(0));
   3.519 +   GPIB.Command(Byte_LAD(0));
   3.520 +   GPIB.Command(Byte_SAD(0));
   3.521 +   GPIB.Command(Byte_GET(0));
   3.522 +
   3.523 +   return NONE;
   3.524  }
   3.525  
   3.526  /* ..........................................................................
   3.527 @@ -1118,20 +1113,12 @@
   3.528   */
   3.529  int16_t Command_write(char *tail)
   3.530  {
   3.531 -   uint8_t byte;
   3.532 +   GPIB.Command(Byte_MTA(0));
   3.533 +   GPIB.Command(Byte_UNL(0));
   3.534 +   GPIB.Command(Byte_LAD(0));
   3.535 +   GPIB.Command(Byte_SAD(0));
   3.536  
   3.537 -   GPIB.ATN(true);
   3.538 -   GPIB.EOI(false);
   3.539 -   GPIB.Out(Byte_MTA(0));
   3.540 -   GPIB.Out(Byte_UNL(0));
   3.541 -   GPIB.Out(Byte_LAD(0));
   3.542 -   byte=Byte_SAD(0);
   3.543 -   if(byte)
   3.544 -      GPIB.Out(byte);
   3.545 -
   3.546 -   int16_t r=Command_wrt(tail);
   3.547 -
   3.548 -   return r;
   3.549 +   return Command_wrt(tail);
   3.550  }
   3.551  
   3.552  
   3.553 @@ -1172,7 +1159,7 @@
   3.554     { String_rsv, Command_status },
   3.555     COMMAND(savecfg),
   3.556     COMMAND(self),   COMMAND(sic),
   3.557 -   COMMAND(spoll),
   3.558 +   { String_spoll, Command_rsp },
   3.559     { String_sre, Command_REN },
   3.560     COMMAND(status), COMMAND(tmo),    COMMAND(trg),
   3.561     COMMAND(ver),    COMMAND(write),  COMMAND(wrt),
   3.562 @@ -1274,4 +1261,3 @@
   3.563  }
   3.564  
   3.565  /* ----- EOF commands.cc ----- */
   3.566 -
     4.1 --- a/formatting.h	Sat Mar 29 09:11:28 2014 +0000
     4.2 +++ b/formatting.h	Sat Mar 29 23:23:58 2014 +0000
     4.3 @@ -33,9 +33,9 @@
     4.4           Send(c);
     4.5        else
     4.6        {  Send('\\');
     4.7 -         Send('0'+((c>>6))&3);
     4.8 -         Send('0'+((c>>3))&7);
     4.9 -         Send('0'+((c>>0))&7);
    4.10 +         Send(char('0'+(((c>>6))&3)));
    4.11 +         Send(char('0'+(((c>>3))&7)));
    4.12 +         Send(char('0'+(((c>>0))&7)));
    4.13        }
    4.14     }
    4.15  
     5.1 --- a/gpib.cc	Sat Mar 29 09:11:28 2014 +0000
     5.2 +++ b/gpib.cc	Sat Mar 29 23:23:58 2014 +0000
     5.3 @@ -8,8 +8,8 @@
     5.4     |                                                                        |
     5.5     #------------------------------------------------------------------------# */
     5.6  
     5.7 -#include <avr/io.h>
     5.8  #include <avr/pgmspace.h>
     5.9 +#include <avr/interrupt.h>
    5.10  #include <stdint.h>
    5.11  #include <ctype.h>
    5.12  #include <util/delay.h>
    5.13 @@ -17,12 +17,77 @@
    5.14  #include "serial.h"
    5.15  #include "gpib.h"
    5.16  
    5.17 -#define Debug USB
    5.18 +// GPIB Connector
    5.19 +//
    5.20 +// Pin  Name    Signal Description          Pin  Name    Signal Description
    5.21 +// ---  ------  -------------------------   ---  ------  -------------------------
    5.22 +// 1    DIO1    Data Input/Output Bit 1     13   DIO5    Data Input/Output Bit 5
    5.23 +// 2    DIO2    Data Input/Output Bit 2     14   DIO6    Data Input/Output Bit 6
    5.24 +// 3    DIO3    Data Input/Output Bit 3     15   DIO7    Data Input/Output Bit 7
    5.25 +// 4    DIO4    Data Input/Output Bit 4     16   DIO8    Data Input/Output Bit 8
    5.26 +// 5    EIO     End-Or-Identify             17   REN     Remote Enable
    5.27 +// 6    DAV     Data Valid                  18   GND     Ground DAV
    5.28 +// 7    NRFD    Not Ready For Data          19   GND     Ground NRFD
    5.29 +// 8    NDAC    Not Data Accepted           20   GND     Ground NDAC
    5.30 +// 9    IFC     Interface Clear             21   GND     Ground IFC
    5.31 +// 10   SRQ     Service Request             22   GND     Ground SRQ
    5.32 +// 11   ATN     Attention                   23   GND     Ground ATN
    5.33 +// 12   Shield  Chassis Ground              24   GND     Ground DIO, REN, EOI
    5.34 +//
    5.35 +// Handshake  Output
    5.36 +// ---------  ---------
    5.37 +//   NRFD     Listener
    5.38 +//   NDAC     Listener
    5.39 +//   DAV      Talker
    5.40 +//
    5.41 +// Control    Output
    5.42 +// ---------  ---------
    5.43 +//   ATN      Controller
    5.44 +//   IFC      Controller
    5.45 +//   REN      Controller
    5.46 +//   SRQ      Any
    5.47 +//   EOI      Talker and Controller
    5.48 +//
    5.49 +// Teensy 2.0 has two complete 8-bit ports PB and PD
    5.50 +// Arduino Leonardo and "Pro Micro" have 15 out of 16, good try!
    5.51 +// 20 mA/pin, 100 mA max for 8-bit port
    5.52 +//
    5.53 +// 32U4       Arduino  GPIB      32U4       Arduino  GPIB
    5.54 +// ---------- -----    ----      ---------- -----    ----
    5.55 +// PB0 (SS)   -      : DIO1      PD0 (INT0) "d3"   : EOI
    5.56 +// PB1 (SCLK) "sck"  : DIO2      PD1 (INT1) "d2"   : NRFD
    5.57 +// PB2 (MOSI) "mosi" : DIO3      PD2 (INT2) "rxi"  : NDAC
    5.58 +// PB3 (MISO) "miso" : DIO4      PD3 (INT3) "txo"  : SRQ
    5.59 +// PB4        "d8"   : DIO5      PD4        "d4"     (pull down for arduino)
    5.60 +// PB5        "d9"   : DIO6      PD5        (LED)    (debug serial)
    5.61 +// PB6        "d10"  : DIO7      PD6 (LED)  -        -
    5.62 +// PB7        -      : DIO8      PD7        "d6"   : DAV
    5.63 +//
    5.64 +// Other pins
    5.65 +//
    5.66 +// 32U4       Arduino  GPIB      32U4       Arduino  GPIB
    5.67 +// ---------- -----    ----      ---------- -----    ----
    5.68 +// PF0 (ADC0) -        -         PC6        "d5"     DIO8
    5.69 +// PF1 (ADC1) -        -         PC7        -
    5.70 +// PF4 (ADC4) "a3"   : ATN       PE6        "d7"     DIO1
    5.71 +// PF5 (ADC5) "a2"   : IFC
    5.72 +// PF6 (ADC6) "a1"   : REN
    5.73 +// PF7 (ADC7) "a0"   :
    5.74 +//
    5.75 +// Teensy has LED on PD6 to GND (shared)
    5.76 +// Arduino has LED on PD5 to VCC
    5.77 +//             and on PB0 to VCC (shared with DIO1)
    5.78 +
    5.79 +#undef DEBUG
    5.80 +
    5.81 +Queue<128> GPIBDriver::CommandQueue;
    5.82 +Queue<128> GPIBDriver::ReadQueue;
    5.83  
    5.84  uint16_t GPIBDriver::MyAddress;
    5.85  uint16_t GPIBDriver::DeviceAddress;
    5.86  uint16_t GPIBDriver::Timeout;
    5.87  bool GPIBDriver::MicroPro;
    5.88 +GPIBDriver::State_t GPIBDriver::State;
    5.89  
    5.90  GPIBDriver::GPIBDriver()
    5.91  {
    5.92 @@ -31,12 +96,43 @@
    5.93  
    5.94  void GPIBDriver::Initialize()
    5.95  {
    5.96 +   Float();
    5.97     MyAddress=0;
    5.98     DeviceAddress=1;
    5.99 +   Timeout=1000;     // one second
   5.100     MicroPro=test_bit_clear(PIND,PORTD_TEENSY_N_ARDUINO);
   5.101 -   Float();
   5.102 +   FloatData();
   5.103 +
   5.104 +   CommandQueue.Clear();
   5.105 +   ReadQueue.Clear();
   5.106 +   State=RESET;
   5.107 +
   5.108 +   TCCR0A=(1<<WGM01)|(1<<WGM00);          // fast pwm mode (but no PWM output)
   5.109 +   TCCR0B=(1<<WGM02)|(1<<CS01)|(1<<CS00); // prescaler=64
   5.110 +   OCR0A=250-1;                           // 258*64=16000 cycles, 1ms
   5.111 +   OCR0B=255;
   5.112 +   TIMSK0=(1<<TOIE0);                     // enable overflow interrupt
   5.113  }
   5.114  
   5.115 +uint16_t Timer;
   5.116 +bool TimedOut;
   5.117 +ISR(TIMER0_OVF_vect)
   5.118 +{
   5.119 +   if(Timer)
   5.120 +   {  if(--Timer==0)
   5.121 +         TimedOut=true;
   5.122 +   }
   5.123 +}
   5.124 +
   5.125 +void StartTimer()
   5.126 +{
   5.127 +   cli();
   5.128 +   TimedOut=false;
   5.129 +   Timer=GPIBDriver::Timeout;
   5.130 +   sei();
   5.131 +}
   5.132 +
   5.133 +
   5.134  // float data bus
   5.135  void GPIBDriver::FloatData()
   5.136  {
   5.137 @@ -72,7 +168,7 @@
   5.138     PORTD=(PORTD&~used_d)|(0xff&used_d);
   5.139  
   5.140     // controls, used indicates bits that are used by us
   5.141 -   static const uint8_t used_f=(1<<PORTF_ATN) | (1<<PORTF_IFC) | (1<<PORTF_REN) | (1<<PORTF_DIO8);
   5.142 +   static const uint8_t used_f=(1<<PORTF_ATN) | (1<<PORTF_IFC) | (1<<PORTF_REN);
   5.143     DDRF&=0xff^used_f;
   5.144     PORTF=(PORTF&~used_f)|(0xff&used_f);
   5.145  }
   5.146 @@ -104,8 +200,8 @@
   5.147  {
   5.148     Float();
   5.149  
   5.150 -   // start driving ATN IFC and REN, pull up DIO8
   5.151 -   PORTF |= (1<<PORTF_ATN) | (1<<PORTF_IFC) | (1<<PORTF_REN) | (1<<PORTF_DIO8);
   5.152 +   // start driving ATN IFC and REN
   5.153 +   PORTF |= (1<<PORTF_ATN) | (1<<PORTF_IFC) | (1<<PORTF_REN);
   5.154     DDRF  |= (1<<PORTF_ATN) | (1<<PORTF_IFC) | (1<<PORTF_REN);
   5.155  
   5.156     // pull /REN low to become actice controller
   5.157 @@ -122,46 +218,36 @@
   5.158     return ~(pf | pd);
   5.159  }
   5.160  
   5.161 -void GPIBDriver::Report(const char *msg)
   5.162 +void GPIBDriver::Report(_ROMS msg)
   5.163  {
   5.164     if(msg)
   5.165 -   {
   5.166 -      Debug<<msg<<':';
   5.167 -   }
   5.168 -   Debug<<'<';
   5.169 -   Debug.Hex(Data());
   5.170 +      USB<<msg<<':';
   5.171 +   else
   5.172 +      USB<<'<';
   5.173 +   if(DDRB==0)
   5.174 +      USB<<"i=";
   5.175 +   else
   5.176 +      USB<<"o=";
   5.177 +   USB.Hex(Data());
   5.178  
   5.179     uint8_t lines=Lines();
   5.180 -   if(lines & (1<<PORTD_EOI))  Debug<<ROMS(" EOI");
   5.181 -   if(lines & (1<<PORTF_ATN))  Debug<<ROMS(" ATN");
   5.182 -   if(lines & (1<<PORTD_SRQ))  Debug<<ROMS(" SRQ");
   5.183 -   if(lines & (1<<PORTF_REN))  Debug<<ROMS(" REN");
   5.184 -   if(lines & (1<<PORTF_IFC))  Debug<<ROMS(" IFC");
   5.185 -   if(lines & (1<<PORTD_NRFD)) Debug<<ROMS(" NRFD");
   5.186 -   if(lines & (1<<PORTD_NDAC)) Debug<<ROMS(" NDAC");
   5.187 -   if(lines & (1<<PORTD_DAV))  Debug<<ROMS(" DAV");
   5.188 +   if(lines & (1<<PORTD_EOI))  USB<<ROMS(" EOI");
   5.189 +   if(lines & (1<<PORTF_ATN))  USB<<ROMS(" ATN");
   5.190 +   if(lines & (1<<PORTD_SRQ))  USB<<ROMS(" SRQ");
   5.191 +   if(lines & (1<<PORTF_REN))  USB<<ROMS(" REN");
   5.192 +   if(lines & (1<<PORTF_IFC))  USB<<ROMS(" IFC");
   5.193 +   if(lines & (1<<PORTD_NRFD)) USB<<ROMS(" NRFD");
   5.194 +   if(lines & (1<<PORTD_NDAC)) USB<<ROMS(" NDAC");
   5.195 +   if(lines & (1<<PORTD_DAV))  USB<<ROMS(" DAV");
   5.196  
   5.197 -   Debug<<'>';
   5.198     if(msg)
   5.199 -      Debug<<endl;
   5.200 +      USB<<endl;
   5.201 +   else
   5.202 +      USB<<'>';
   5.203  }
   5.204  
   5.205  static const uint32_t TIMEOUT=0x1ff000ULL;  // 20 seconds
   5.206  
   5.207 -int16_t GPIBDriver::Command(const int16_t *command)
   5.208 -{
   5.209 -   int8_t status=0;
   5.210 -   while(int16_t word=pgm_read_word(*command++))
   5.211 -   {
   5.212 -      ATN(word&(1<<9));
   5.213 -      EOI(word&(1<<8));
   5.214 -      status=Out(word);
   5.215 -      if(status)
   5.216 -         break;
   5.217 -   }
   5.218 -   return -status;
   5.219 -}
   5.220 -
   5.221  void GPIBDriver::Data(uint8_t byte)
   5.222  {
   5.223     PORTB=~byte;
   5.224 @@ -191,68 +277,6 @@
   5.225     }
   5.226  }
   5.227  
   5.228 -uint8_t GPIBDriver::Out(uint8_t byte)
   5.229 -{
   5.230 -   DAV(false);
   5.231 -
   5.232 -   if(!NRFD() && !NDAC())
   5.233 -   {  USB<<ROMS("++error 1\r\n");
   5.234 -      // disabled while debugging
   5.235 -      // return -1;
   5.236 -   }
   5.237 -
   5.238 -   // drive data
   5.239 -   Data(byte);
   5.240 -
   5.241 -   // settling delay
   5.242 -   _delay_us(2);
   5.243 -
   5.244 -   uint32_t timeout;
   5.245 -   for(timeout=TIMEOUT; timeout!=0; timeout--)
   5.246 -   {
   5.247 -      _delay_us(10);
   5.248 -
   5.249 -      if(!NRFD())
   5.250 -         break;
   5.251 -   }
   5.252 -
   5.253 -   if(!timeout)
   5.254 -      goto fail;
   5.255 -
   5.256 -   DAV(true);
   5.257 -
   5.258 -   for(timeout=TIMEOUT; timeout!=0; timeout--)
   5.259 -   {
   5.260 -      _delay_us(10);
   5.261 -
   5.262 -      if(!NDAC())
   5.263 -         break;
   5.264 -   }
   5.265 -
   5.266 -   if(!timeout)
   5.267 -      goto fail;
   5.268 -
   5.269 -   DAV(false);
   5.270 -
   5.271 -   // float data bus
   5.272 -   PORTB=0xff;
   5.273 -   DDRB=0;
   5.274 -
   5.275 -   return 0;
   5.276 -
   5.277 -fail:
   5.278 -   DAV(false);
   5.279 -
   5.280 -   // float data bus
   5.281 -   PORTB=0xff;
   5.282 -   DDRB=0;
   5.283 -
   5.284 -   USB<<ROMS("++error 2\r\n");
   5.285 -   return -1;
   5.286 -}
   5.287 -
   5.288 -/* .......................................................................... */
   5.289 -
   5.290  uint8_t GPIBDriver::Data()
   5.291  {
   5.292     uint8_t byte=~PINB;
   5.293 @@ -262,63 +286,381 @@
   5.294        byte &= 0x7e;
   5.295        if(test_bit_clear(PINE,6))
   5.296           byte |= 1;
   5.297 -      if(test_bit_clear(PINE,6))
   5.298 +      if(test_bit_clear(PINC,6))
   5.299           byte |= 0x80;
   5.300     }
   5.301 +   return byte;
   5.302  }
   5.303  
   5.304 -int16_t GPIBDriver::In()
   5.305 +bool GPIBDriver::Command(uint16_t data)
   5.306  {
   5.307 -   NRFD(true);
   5.308 -   NDAC(true);
   5.309 +#ifdef DEBUG
   5.310 +   USB<<ROMS("Command(");
   5.311 +   USB.Hex(data);
   5.312 +   USB<<ROMS(")\r\n");
   5.313 +#endif
   5.314 +   if(data==0)
   5.315 +      return true;
   5.316 +   return CommandQueue.Put(data);
   5.317 +}
   5.318  
   5.319 -   // ready for data
   5.320 -   NRFD(false);
   5.321 +uint16_t GPIBDriver::Read()
   5.322 +{
   5.323 +   return ReadQueue.Get();
   5.324 +}
   5.325  
   5.326 -   uint8_t byte,atn,eoi;
   5.327 -   uint32_t timeout;
   5.328 -   for(timeout=TIMEOUT; timeout!=0; timeout--)
   5.329 +#ifdef DEBUG
   5.330 +GPIBDriver::State_t last=(GPIBDriver::State_t)~0;  // debug
   5.331 +uint16_t lasttimer=0;
   5.332 +#endif
   5.333 +
   5.334 +int8_t GPIBDriver::Poll()
   5.335 +{
   5.336 +   // tune this so we go round the loop often enough to send/receive one byte
   5.337 +   for(uint8_t loop=0; loop<100; loop++)
   5.338     {
   5.339 -      _delay_us(10);
   5.340 +   #ifdef DEBUG
   5.341 +      if(Timer%128==1 && Timer!=lasttimer)
   5.342 +      {
   5.343 +         last=(GPIBDriver::State_t)~0;
   5.344 +         lasttimer=Timer;
   5.345 +      }
   5.346  
   5.347 -      if(DAV())
   5.348 -         break;
   5.349 +      if(State!=last)
   5.350 +      {
   5.351 +         //Report();
   5.352 +         USB<<ROMS(" state=")<<State<<
   5.353 +                ROMS(" cq=")<<CommandQueue.Used()<<
   5.354 +                ROMS(" rq=")<<ReadQueue.Used()<<
   5.355 +                ROMS(" t=")<<Timer;
   5.356 +         if(TimedOut)
   5.357 +         {
   5.358 +            USB<<ROMS(" TO");
   5.359 +         }
   5.360 +         USB<<endl;
   5.361 +         last=State;
   5.362 +      }
   5.363 +   #endif
   5.364 +
   5.365 +      switch(State)
   5.366 +      {
   5.367 +         case RESET:
   5.368 +            Float();
   5.369 +            TimedOut=false;
   5.370 +            CommandQueue.Clear();
   5.371 +            State=IDLE;
   5.372 +            return 0;
   5.373 +
   5.374 +         case IDLE:
   5.375 +         {  uint16_t data=CommandQueue.Peek();
   5.376 +
   5.377 +         #ifdef DEBUG
   5.378 +            if(data)
   5.379 +            {
   5.380 +               USB<<ROMS("data=");
   5.381 +               USB.Hex(data);
   5.382 +               USB<<endl;
   5.383 +            }
   5.384 +         #endif
   5.385 +
   5.386 +            switch(data & CMD_MASK)
   5.387 +            {  case 0:
   5.388 +                  return 0;   // idle
   5.389 +               case CMD_SOURCE:
   5.390 +                  State=SH_START;
   5.391 +                  break;
   5.392 +               case CMD_ACCEPT:
   5.393 +                  State=AH_START;
   5.394 +                  break;
   5.395 +               case CMD_CONTROLLER:
   5.396 +                  State=CAC_START;
   5.397 +                  break;
   5.398 +               case CMD_SIC:
   5.399 +                  State=SIC_START;
   5.400 +                  break;
   5.401 +               case CMD_RELEASE:
   5.402 +                  Float();
   5.403 +                  State=IDLE;
   5.404 +                  break;
   5.405 +               default:
   5.406 +                  // drop unknown command
   5.407 +                  CommandQueue.Get();
   5.408 +                  return EINTERN;   // internal error
   5.409 +            }
   5.410 +         }  break;
   5.411 +
   5.412 +
   5.413 +         /* ..... source handshake ................................................... */
   5.414 +
   5.415 +         case SH_START:
   5.416 +         {  uint16_t data=CommandQueue.Peek();
   5.417 +            ATN(data&CMD_ATN);
   5.418 +            DAV(false);
   5.419 +
   5.420 +            // settling delay
   5.421 +            _delay_us(2);
   5.422 +
   5.423 +            if(!NRFD() && !NDAC())
   5.424 +            {  State=RESET;
   5.425 +               return EACPROT;      // acceptor protocol error
   5.426 +            }
   5.427 +            State=SH_DATA;
   5.428 +         }  break;
   5.429 +
   5.430 +         case SH_DATA:
   5.431 +         {  // remove command from the queue
   5.432 +            uint16_t data=CommandQueue.Get();
   5.433 +
   5.434 +            // drive data
   5.435 +            EOI(data&CMD_EOI);
   5.436 +            Data(data);
   5.437 +
   5.438 +            // settling delay
   5.439 +            _delay_us(2);
   5.440 +
   5.441 +            // start timer default
   5.442 +            StartTimer();
   5.443 +
   5.444 +            State=SH_WAIT_NRFD;
   5.445 +         }  break;
   5.446 +
   5.447 +         case SH_WAIT_NRFD:
   5.448 +            if(!NRFD())
   5.449 +               State=SH_DAV;
   5.450 +            else if(TimedOut)
   5.451 +            {  State=RESET;
   5.452 +               return EACTMO;      // acceptor timeout
   5.453 +            }
   5.454 +            break;
   5.455 +
   5.456 +         case SH_DAV:
   5.457 +            DAV(true);
   5.458 +
   5.459 +            // start timer default
   5.460 +            StartTimer();
   5.461 +
   5.462 +            State=SH_WAIT_NDAC;
   5.463 +            break;
   5.464 +
   5.465 +         case SH_WAIT_NDAC:
   5.466 +            if(!NDAC())
   5.467 +               State=SH_N_DAV;
   5.468 +            else if(TimedOut)
   5.469 +            {  State=RESET;
   5.470 +               return EACTMO;      // acceptor timeout
   5.471 +            }
   5.472 +            break;
   5.473 +
   5.474 +         case SH_N_DAV:
   5.475 +            DAV(false);
   5.476 +            EOI(false);
   5.477 +            FloatData();
   5.478 +            State=IDLE;
   5.479 +            break;
   5.480 +
   5.481 +
   5.482 +         /* ..... acceptor handshake ................................................. */
   5.483 +
   5.484 +         case AH_START:
   5.485 +            // NRFD(true); // old code used to do this
   5.486 +            NDAC(true);
   5.487 +
   5.488 +            if(ATN())
   5.489 +            {  // settling delay
   5.490 +               _delay_us(1);
   5.491 +               State=AH_N_ATN;
   5.492 +            }
   5.493 +            else
   5.494 +               State=AH_READY;
   5.495 +            break;
   5.496 +
   5.497 +         case AH_N_ATN:
   5.498 +            // negate ATN
   5.499 +            ATN(false);
   5.500 +            State=AH_READY;
   5.501 +            break;
   5.502 +
   5.503 +         case AH_READY:
   5.504 +            // ready for data
   5.505 +            NRFD(false);
   5.506 +
   5.507 +            // start timer default
   5.508 +            StartTimer();
   5.509 +
   5.510 +            State=AH_WAIT_DAV;
   5.511 +            break;
   5.512 +
   5.513 +         case AH_WAIT_DAV:
   5.514 +            if(DAV())
   5.515 +               State=AH_NRFD;
   5.516 +            else if(TimedOut)
   5.517 +            {  State=RESET;
   5.518 +               return ESRCTMO;      // source timeout
   5.519 +            }
   5.520 +            break;
   5.521 +
   5.522 +         case AH_NRFD:
   5.523 +         {  NRFD(true);
   5.524 +
   5.525 +            uint16_t cmd=CommandQueue.Peek();
   5.526 +            uint8_t eoi=EOI();
   5.527 +
   5.528 +            uint16_t data=CMD_ACCEPT | Data();
   5.529 +            if(ATN())
   5.530 +               data|=CMD_ATN;
   5.531 +            if(eoi)
   5.532 +               data|=CMD_EOI;
   5.533 +
   5.534 +         #ifdef DEBUG
   5.535 +            USB<<ROMS("data=");
   5.536 +            USB.Hex(data);
   5.537 +            if((data&0xff)>=32 && (data&0xff)<127)
   5.538 +            {  USB<<' '<<'\''<<char(data)<<'\'';
   5.539 +            }
   5.540 +            USB<<endl;
   5.541 +         #endif
   5.542 +
   5.543 +            bool last=((cmd&CMD_AC_EOI)!=0 && eoi) ||                    // EOI on byte
   5.544 +                      ((cmd&CMD_AC_BYTE)!=0 && ((cmd^data)&0xff)==0) ||  // byte match
   5.545 +                      ((cmd&CMD_AC_COUNT)!=0);                           // counter
   5.546 +
   5.547 +            if(ReadQueue.Put(data))
   5.548 +               State=last ? AH_N_NDAC_LAST : AH_N_NDAC;
   5.549 +            else if(TimedOut)
   5.550 +            {  State=last ? AH_WAIT_NDAV_LAST : AH_WAIT_NDAV;
   5.551 +               return EFULL;      // timeout on read queue
   5.552 +            }
   5.553 +            else
   5.554 +               return 0;
   5.555 +         } break;
   5.556 +
   5.557 +         case AH_N_NDAC:
   5.558 +            NDAC(false);
   5.559 +            State=AH_WAIT_NDAV;
   5.560 +            break;
   5.561 +
   5.562 +         case AH_WAIT_NDAV:
   5.563 +            if(!DAV())
   5.564 +               State=AH_NDAC;
   5.565 +            else if(TimedOut)
   5.566 +            {  State=RESET;
   5.567 +               return ESRCTMO;      // source timeout
   5.568 +            }
   5.569 +            break;
   5.570 +
   5.571 +         case AH_NDAC:
   5.572 +            NDAC(true);
   5.573 +            State=AH_READY;
   5.574 +            break;
   5.575 +
   5.576 +         case AH_N_NDAC_LAST:
   5.577 +            NDAC(false);
   5.578 +            State=AH_WAIT_NDAV_LAST;
   5.579 +            break;
   5.580 +
   5.581 +         case AH_WAIT_NDAV_LAST:
   5.582 +            if(!DAV())
   5.583 +            {  CommandQueue.Get();  // remove command from queue
   5.584 +               State=IDLE;
   5.585 +            }
   5.586 +            else if(TimedOut)
   5.587 +            {  State=RESET;
   5.588 +               return ESRCTMO;      // source timeout
   5.589 +            }
   5.590 +            break;
   5.591 +
   5.592 +
   5.593 +         /* ..... take control ....................................................... */
   5.594 +
   5.595 +         case CAC_START:
   5.596 +            GPIB.ATN(false);
   5.597 +            GPIB.EOI(false);
   5.598 +            GPIB.NRFD(false);
   5.599 +            GPIB.DAV(false);
   5.600 +            GPIB.NDAC(false);
   5.601 +
   5.602 +            if(CommandQueue.Get()&CMD_CTRL_FORCE)
   5.603 +               State=CAC_COMPLETE;
   5.604 +            else
   5.605 +            {
   5.606 +               StartTimer();
   5.607 +               State=CAC_WAIT;
   5.608 +            }
   5.609 +            break;
   5.610 +
   5.611 +         case CAC_WAIT:
   5.612 +            if(!(GPIB.ATN() || GPIB.NRFD() || GPIB.NDAC() || GPIB.DAV()))
   5.613 +               State=CAC_COMPLETE;
   5.614 +            else if(TimedOut)
   5.615 +            {  State=RESET;
   5.616 +               return ECTRLTMO;      // controller timeout
   5.617 +            }
   5.618 +            break;
   5.619 +
   5.620 +         case CAC_COMPLETE:
   5.621 +            Controller();
   5.622 +            State=IDLE;
   5.623 +            break;
   5.624 +
   5.625 +
   5.626 +         /* ..... send interface clear ............................................... */
   5.627 +
   5.628 +         case SIC_START:
   5.629 +            CommandQueue.Get();
   5.630 +            GPIB.IFC(true);
   5.631 +            StartTimer();
   5.632 +            State=SIC_WAIT;
   5.633 +            break;
   5.634 +
   5.635 +         case SIC_WAIT:
   5.636 +            if(!(GPIB.DAV() || GPIB.NRFD() || GPIB.NDAC()))
   5.637 +               State=SIC_COMPLETE;
   5.638 +            else if(TimedOut)
   5.639 +            {  State=SIC_COMPLETE;
   5.640 +               return ECTRLTMO;      // controller timeout
   5.641 +            }
   5.642 +            break;
   5.643 +
   5.644 +         case SIC_COMPLETE:
   5.645 +            GPIB.IFC(false);
   5.646 +            State=IDLE;
   5.647 +            break;
   5.648 +
   5.649 +
   5.650 +         /* ..... parallel poll ...................................................... */
   5.651 +
   5.652 +         case PP_START:
   5.653 +            GPIB.ATN(true);
   5.654 +            GPIB.EOI(true);
   5.655 +            // settling delay
   5.656 +            _delay_us(1);
   5.657 +            State=PP_COMPLETE;
   5.658 +            break;
   5.659 +
   5.660 +         case PP_COMPLETE:
   5.661 +         {  uint16_t data;
   5.662 +
   5.663 +            data=CMD_PARPOLL | Data();
   5.664 +            GPIB.ATN(false);
   5.665 +            GPIB.EOI(false);
   5.666 +            State=IDLE;
   5.667 +
   5.668 +            if(!ReadQueue.Put(data))
   5.669 +               return EFULL;      // timeout on read queue
   5.670 +
   5.671 +         }  break;
   5.672 +
   5.673 +         /* .......................................................................... */
   5.674 +
   5.675 +         default:
   5.676 +            State=RESET;
   5.677 +            return EINTERN;         // internal error
   5.678 +      }
   5.679     }
   5.680 +   return 0;
   5.681 +}
   5.682  
   5.683 -   if(!timeout)
   5.684 -      goto fail;
   5.685 -
   5.686 -   NRFD(true);
   5.687 -
   5.688 -   byte=Data();
   5.689 -
   5.690 -   atn=ATN();
   5.691 -   eoi=EOI();
   5.692 -
   5.693 -   NDAC(false);
   5.694 -
   5.695 -   for(timeout=TIMEOUT; timeout!=0; timeout--)
   5.696 -   {
   5.697 -      _delay_us(10);
   5.698 -
   5.699 -      if(!DAV())
   5.700 -         break;
   5.701 -   }
   5.702 -
   5.703 -   if(!timeout)
   5.704 -      goto fail;
   5.705 -
   5.706 -   if(!eoi)
   5.707 -      NDAC(true);
   5.708 -
   5.709 -   return byte | (eoi<<8) | (atn<<9);
   5.710 -
   5.711 -fail:
   5.712 -   NDAC(false);
   5.713 -   NRFD(false);
   5.714 -   USB<<ROMS("++error 4\r\n");
   5.715 -   return -1;
   5.716 -}
   5.717 +/* ========================================================================== */
   5.718  
   5.719  const GPIBDriver __attribute__((__progmem__)) GPIB;
   5.720  
   5.721 @@ -361,4 +703,3 @@
   5.722  //
   5.723  
   5.724  /* ----- EOF gpib.cc ----- */
   5.725 -
     6.1 --- a/gpib.h	Sat Mar 29 09:11:28 2014 +0000
     6.2 +++ b/gpib.h	Sat Mar 29 23:23:58 2014 +0000
     6.3 @@ -13,10 +13,66 @@
     6.4  
     6.5  #include <avr/io.h>
     6.6  
     6.7 +template<unsigned SIZE> class Queue
     6.8 +{
     6.9 +   uint8_t In, Out;
    6.10 +   uint16_t Data[SIZE];
    6.11 +
    6.12 +public:
    6.13 +   static const uint8_t Size=SIZE;
    6.14 +
    6.15 +   __attribute__((noinline)) Queue()
    6.16 +   {  Clear();
    6.17 +   }
    6.18 +   __attribute__((noinline)) void Clear()
    6.19 +   {  In=Out=0;
    6.20 +   }
    6.21 +
    6.22 +   __attribute__((noinline)) uint8_t Used()
    6.23 +   {
    6.24 +      if(In>=Out)
    6.25 +         return In-Out;
    6.26 +      else
    6.27 +         return In+Size-Out;
    6.28 +   }
    6.29 +
    6.30 +   __attribute__((noinline)) uint16_t Peek()
    6.31 +   {
    6.32 +      uint8_t o=Out;
    6.33 +      if(In==o)
    6.34 +         return 0;
    6.35 +      return Data[o];
    6.36 +   }
    6.37 +
    6.38 +   __attribute__((noinline)) uint16_t Get()
    6.39 +   {
    6.40 +      uint8_t o=Out;
    6.41 +      if(In==o)
    6.42 +         return 0;
    6.43 +      uint16_t value=Data[o];
    6.44 +      if(++o>=SIZE)
    6.45 +         o=0;
    6.46 +      Out=o;
    6.47 +      return value;
    6.48 +   }
    6.49 +   __attribute__((noinline)) bool Put(uint16_t value)
    6.50 +   {
    6.51 +      uint8_t i=In+1;
    6.52 +      if(i>=SIZE)
    6.53 +         i=0;
    6.54 +      if(i==Out)
    6.55 +         return false;
    6.56 +      Data[In]=value;
    6.57 +      In=i;
    6.58 +      return true;
    6.59 +   }
    6.60 +};
    6.61 +
    6.62  class GPIBDriver
    6.63  {
    6.64  public:
    6.65 -   static const bool SAFER=1;
    6.66 +   // we never actively pull any signals high when this is true
    6.67 +   static const bool SAFER=true;
    6.68  
    6.69     static const unsigned PORTD_EOI=0,
    6.70                           PORTD_NRFD=1,
    6.71 @@ -30,13 +86,38 @@
    6.72     // By happy coincidence the bits here are unused on port D
    6.73     static const unsigned PORTF_ATN=4,
    6.74                           PORTF_IFC=5,
    6.75 -                         PORTF_REN=6,
    6.76 -                         PORTF_DIO8=7;
    6.77 +                         PORTF_REN=6;
    6.78  
    6.79     // Data pins for MicroPro
    6.80     static const unsigned PORTC_DIO8=6;
    6.81     static const unsigned PORTE_DIO1=6;
    6.82  
    6.83 +   // command and read queues
    6.84 +   static const unsigned QUEUE_SIZE=128;
    6.85 +   static Queue<128> CommandQueue;
    6.86 +   static Queue<128> ReadQueue;
    6.87 +
    6.88 +   // GPIB state machine
    6.89 +   enum State_t { RESET, IDLE,
    6.90 +                  // source handshake
    6.91 +                  SH_START, SH_DATA, SH_WAIT_NRFD, SH_DAV, SH_WAIT_NDAC, SH_N_DAV,
    6.92 +                  // acceptor handshake
    6.93 +                  AH_START, AH_N_ATN, AH_READY, AH_WAIT_DAV, AH_NRFD, AH_N_NDAC,
    6.94 +                  AH_WAIT_NDAV, AH_NDAC, AH_N_NDAC_LAST, AH_WAIT_NDAV_LAST,
    6.95 +                  // become active controller
    6.96 +                  CAC_START, CAC_WAIT, CAC_COMPLETE,
    6.97 +                  // send interface clear
    6.98 +                  SIC_START, SIC_WAIT, SIC_COMPLETE,
    6.99 +                  // parallel poll
   6.100 +                  PP_START, PP_COMPLETE
   6.101 +                  // serial poll
   6.102 +                };
   6.103 +   static State_t State;
   6.104 +
   6.105 +   // obsolete
   6.106 +   static uint8_t Out(uint8_t byte);
   6.107 +   static int16_t In();
   6.108 +
   6.109  public:
   6.110     GPIBDriver();
   6.111     static void LED(bool);
   6.112 @@ -54,13 +135,41 @@
   6.113     static void Float();
   6.114     static void Controller();
   6.115  
   6.116 -   int16_t Command(const int16_t *command);  // UNIM
   6.117 +   /* ..... polled commands and reads .......................................... */
   6.118 +
   6.119 +   // commands
   6.120 +   static const uint16_t CMD_SOURCE       =1<<12,     // source handshake
   6.121 +                            CMD_ATN       =1<<9,      //    assert ATN
   6.122 +                            CMD_EOI       =1<<8,      //    assert EOI
   6.123 +                         CMD_ACCEPT       =2<<12,     // accept handshake
   6.124 +                            CMD_AC_EOI    =0<<8,      //    until eoi
   6.125 +                            CMD_AC_TMO    =1<<8,      //    until timeout (i.e. forever)
   6.126 +                            CMD_AC_COUNT  =2<<8,      //    byte count in LSBs (only support count=1 for now)
   6.127 +                            CMD_AC_BYTE   =3<<8,      //    until byte seen
   6.128 +                         CMD_CONTROLLER   =3<<12,     // take control of bus
   6.129 +                            CMD_CTRL_FORCE=1<<0,      //    without waiting for it to be idle
   6.130 +                         CMD_SIC          =4<<12,     // send interface clear
   6.131 +                         CMD_RELEASE      =5<<12,     // release control of the bus
   6.132 +                         CMD_PARPOLL      =6<<12,     // parallel poll
   6.133 +                         CMD_MASK         =15<<12;    // mask of commands
   6.134 +
   6.135 +   // error returns
   6.136 +   static const int8_t OK=0,
   6.137 +                       EINTERN=-9,     // internal error
   6.138 +                       EACPROT=-10,    // acceptor protocol error
   6.139 +                       EACTMO=-11,     // acceptor timeout
   6.140 +                       ESRCPROT=-12,   // source protocl error
   6.141 +                       ESRCTMO=-13,    // source timeout
   6.142 +                       ECTRLTMO=-14,   // controller timeout
   6.143 +                       EFULL=-15;      // queue full
   6.144 +
   6.145 +   static int8_t Poll();
   6.146 +   static bool Command(uint16_t);
   6.147 +   static uint16_t Read();
   6.148  
   6.149     /* ..... byte level commands ................................................ */
   6.150  
   6.151 -   static uint8_t Out(uint8_t byte);
   6.152 -   static int16_t In();
   6.153 -   static void Report(const char *msg=0);
   6.154 +   static void Report(_ROMS msg=_ROMS(0));
   6.155  
   6.156     static uint8_t Lines();
   6.157     #define set_bit(port_,bit_)                           \
   6.158 @@ -255,67 +364,6 @@
   6.159  
   6.160  extern const GPIBDriver GPIB;
   6.161  
   6.162 -// #define GPIB_S_DAT  1
   6.163 -// #define GPIB_R_DAT  2
   6.164 -// #define GPIB_R_SRQ  3
   6.165 -// #define RD_AD_CMD   4
   6.166 -// #define SET_IO_CMD  5
   6.167 -// #define RESET_CMD       6
   6.168 -//
   6.169 -// #define FLASH_SECTION_READ     0x01
   6.170 -// #define FLASH_SECTION_WRITE    0x02
   6.171 -//
   6.172 -// #define TIMEOUT 100000
   6.173 -// #define true 1
   6.174 -// #define false 0
   6.175 -// //
   6.176 -// // GPIB receive finite-state-machine states
   6.177 -// //
   6.178 -// #define GPIB_RX_START           0
   6.179 -// #define GPIB_RX_ACCEPT          1
   6.180 -// #define GPIB_RX_WAIT_DAV        2
   6.181 -// #define GPIB_RX_DAV_LOW         3
   6.182 -// #define GPIB_RX_WAIT_DAV_HIGH   4
   6.183 -// #define GPIB_RX_DAV_HIGH        5
   6.184 -// #define GPIB_RX_EOI             6
   6.185 -// #define GPIB_RX_FINISH          9
   6.186 -// #define GPIB_RX_DAV_TIMEOUT     10
   6.187 -// #define GPIB_RX_DONE            99
   6.188 -//
   6.189 -// //
   6.190 -// // GPIB send finite-state-machine states
   6.191 -// //
   6.192 -// #define GPIB_TX_START           0
   6.193 -// #define GPIB_TX_CHECK           1
   6.194 -// #define GPIB_TX_PUT_DATA        2
   6.195 -// #define GPIB_TX_WAIT_FOR_NRFD   3
   6.196 -// #define GPIB_TX_SET_DAV_LOW     4
   6.197 -// #define GPIB_TX_WAIT_FOR_NDAC   5
   6.198 -// #define GPIB_TX_SET_DAV_HIGH    6
   6.199 -// #define GPIB_TX_FINISH          9
   6.200 -// #define GPIB_TX_ERROR           98
   6.201 -// #define GPIB_TX_DONE            99
   6.202 -//
   6.203 -// #define GPIB_MAX_TX_LEN         64      // Max length of transmit GPIB string
   6.204 -// #define GPIB_MAX_RX_LEN         128     // Max length of receive GPIB string
   6.205 -// #define GPIB_MAX_CMD_LEN        32      // Max length of GPIB incoming command
   6.206 -//
   6.207 -// extern unsigned char gpib_buff[GPIB_MAX_RX_LEN];
   6.208 -// extern unsigned char gpib_ptr;
   6.209 -// extern char gpib_tx_buff[GPIB_MAX_TX_LEN];
   6.210 -// extern char gpib_tx_ptr;
   6.211 -// extern char gpib_cmd_buff[GPIB_MAX_CMD_LEN];
   6.212 -// extern unsigned char gpib_cmd_ptr;
   6.213 -// extern unsigned char listening;
   6.214 -// extern unsigned char in_command;
   6.215 -//
   6.216 -// void gpib_init(void);
   6.217 -// void sendgpib (void);
   6.218 -// int readgpib(void);
   6.219 -// void gpib_ren(unsigned char state);
   6.220 -// void gpib_ifc(void);
   6.221 -
   6.222  #endif /* GPIB_H_ */
   6.223  
   6.224  /* ----- EOF gpib.h ----- */
   6.225 -
     7.1 --- a/hardcopy	Sat Mar 29 09:11:28 2014 +0000
     7.2 +++ b/hardcopy	Sat Mar 29 23:23:58 2014 +0000
     7.3 @@ -7,12 +7,19 @@
     7.4     print "Serial library not found - install python-serial"
     7.5     sys.exit(99)
     7.6  
     7.7 +state=0
     7.8 +byte=0
     7.9 +
    7.10  def main():
    7.11     p=argparse.ArgumentParser(description="Take hardcopy from Tek scope")
    7.12     p.add_argument(dest="File", metavar="file", type=str, nargs="?", default="hardcopy.bmp",
    7.13                    help="output file to write")
    7.14     p.add_argument("-d","--port", dest="Device", action="store", default=0,
    7.15                    help="serial port to use")
    7.16 +   p.add_argument("-v","--verbose", dest="Verbose", action="store_true",
    7.17 +                  help="Be more verbose")
    7.18 +   p.add_argument("--debug", dest="Debug", action="store_true",
    7.19 +                  help="Show commands and data")
    7.20     args=p.parse_args()
    7.21  
    7.22     if args.Device=="-":
    7.23 @@ -23,34 +30,89 @@
    7.24     else:
    7.25        usbgpib=serial.Serial(args.Device,timeout=5)
    7.26  
    7.27 -   data=""
    7.28 -   while True:
    7.29 -      d=usbgpib.read(1)
    7.30 -      if d=="" or d==chr(13) or d==chr(10):
    7.31 +   def w(data):
    7.32 +      if args.Debug:
    7.33 +         print "> %s"%repr(data)[1:-1]
    7.34 +      usbgpib.write("%s\n"%data)
    7.35 +
    7.36 +   def r(binary=False):
    7.37 +      global byte,state
    7.38 +      data=""
    7.39 +      while True:
    7.40 +         d=usbgpib.read(1)
    7.41 +         #print "state=%d d=%r"%(state,d)
    7.42 +         if not binary:
    7.43 +            if d==chr(13):
    7.44 +               continue
    7.45 +            if d==chr(10):
    7.46 +               break
    7.47 +         if d=="":
    7.48 +            break
    7.49 +         if state==0 and d=="\\":
    7.50 +            state=1
    7.51 +            byte=0
    7.52 +         elif state==1:
    7.53 +            if d>='0' and d<='3':
    7.54 +               byte=64*int(d)
    7.55 +               state=2
    7.56 +            else:
    7.57 +               data+=d
    7.58 +               state=0
    7.59 +         elif state==2:
    7.60 +            byte+=8*int(d)
    7.61 +            state=3
    7.62 +         elif state==3:
    7.63 +            byte+=int(d)
    7.64 +            state=0
    7.65 +            data+=chr(byte)
    7.66 +         else:
    7.67 +            data+=d
    7.68 +         if binary and len(data)==256:
    7.69 +            break
    7.70 +      if args.Debug: print "< %s"%repr(data)[1:-1]
    7.71 +      return data
    7.72 +
    7.73 +   for t in range(10):
    7.74 +      data=r()
    7.75 +      if "USB-GPIB" in data:
    7.76           break
    7.77 -      data+=d
    7.78 +      if not data:
    7.79 +         w("++ver")
    7.80 +
    7.81     if "USB-GPIB" not in data:
    7.82        print "USB-GPIB not found"
    7.83        sys.exit(2)
    7.84  
    7.85 -   usbgpib.write("rst\n")
    7.86 +   w('rst')
    7.87 +   r()
    7.88 +   w('cac')
    7.89 +   r()
    7.90 +
    7.91 +   w('write -"hardcopy:format bmp;port gpib;layout portrait"')
    7.92 +   r()
    7.93 +   w('write -"hardcopy start"')
    7.94     time.sleep(0.2)
    7.95 -   usbgpib.write("cac\n")
    7.96 -   time.sleep(0.2)
    7.97 -   usbgpib.write("cmd MTA UNL LAD\n")
    7.98 -   usbgpib.write("wrt -\"hardcopy start\"\n")
    7.99 -   usbgpib.write("cmd UNL MLA TAD\n")
   7.100 -   usbgpib.write("read\n")
   7.101 +   r()
   7.102 +   w('read')
   7.103 +   r()
   7.104     data=""
   7.105     while True:
   7.106 -      d=usbgpib.read()
   7.107 +      d=r(True)
   7.108        if d=="":
   7.109           break
   7.110        data+=d
   7.111 -   usbgpib.write("rst\n")
   7.112 +      if args.Verbose:
   7.113 +        sys.stdout.write("%d\r"%len(data))
   7.114 +        sys.stdout.flush()
   7.115 +   if args.Verbose:
   7.116 +        print
   7.117 +   w("rst")
   7.118  
   7.119 -   if data.startswith("\r"): data=data[1:]
   7.120 -   if data.startswith("\n"): data=data[1:]
   7.121 +   i=data.find("BM")
   7.122 +   if i>=0 and i<200:
   7.123 +      data=data[i:]
   7.124 +   if data.endswith("\r\n++"):
   7.125 +      data=data[:-4]
   7.126  
   7.127     print "%d bytes"%len(data)
   7.128     if args.File.endswith(".bmp"):
   7.129 @@ -60,7 +122,9 @@
   7.130        fd=tempfile.NamedTemporaryFile("wb",suffix=".bmp")
   7.131        fd.write(data)
   7.132        fd.flush()
   7.133 -      os.system("convert %s %s"%(fd.name,args.File))
   7.134 +      cmd="convert %s %s"%(fd.name,args.File)
   7.135 +      if args.Verbose:print "$ %s"%cmd
   7.136 +      os.system(cmd)
   7.137        del fd
   7.138  
   7.139  if __name__=="__main__":
     8.1 --- a/main.cc	Sat Mar 29 09:11:28 2014 +0000
     8.2 +++ b/main.cc	Sat Mar 29 23:23:58 2014 +0000
     8.3 @@ -116,6 +116,23 @@
     8.4  
     8.5     while(count < size)
     8.6     {
     8.7 +      // TODO: move to main
     8.8 +      r=GPIB.Poll();
     8.9 +      if(r)
    8.10 +         USB<<ROMS("++error ")<<r<<endl;
    8.11 +
    8.12 +      r=GPIB.Read();
    8.13 +      if(r)
    8.14 +      {
    8.15 +         r&=0xff;
    8.16 +         if(r==10)
    8.17 +            USB<<ROMS("\\012\r\n");
    8.18 +         else if(r=='\\')
    8.19 +            USB<<ROMS("\\134");
    8.20 +         else
    8.21 +            USB.SendSafeChar(r);
    8.22 +      }
    8.23 +
    8.24        r = usb_serial_getchar();
    8.25        if(r==-1)
    8.26        {
     9.1 --- a/program	Sat Mar 29 09:11:28 2014 +0000
     9.2 +++ b/program	Sat Mar 29 23:23:58 2014 +0000
     9.3 @@ -11,7 +11,7 @@
     9.4  done
     9.5  
     9.6  MODE=
     9.7 -if lsusb -d 16c0:047a ; then
     9.8 +if lsusb -d 16c0:047a >/dev/null ; then
     9.9     echo "Autodetecting USB-GPIB"
    9.10  
    9.11     exec 3<>$DEV
    9.12 @@ -50,10 +50,10 @@
    9.13     exec 3>&-
    9.14     sleep 0.5
    9.15  
    9.16 -elif lsusb -d 2341:8036 ; then
    9.17 +elif lsusb -d 2341:8036 >/dev/null ; then
    9.18     MODE=AVR109
    9.19  
    9.20 -elif lsusb -d 16c0:0478 ; then
    9.21 +elif lsusb -d 16c0:0478 >/dev/null ; then
    9.22     MODE=Teensy
    9.23  
    9.24  else
    9.25 @@ -67,6 +67,7 @@
    9.26     exit 1
    9.27  fi
    9.28  
    9.29 +sleep 0.5
    9.30  set -x
    9.31  
    9.32  case "$MODE" in