diff --git a/avr.c b/avr.c
index ebed6dc9..88d93754 100644
--- a/avr.c
+++ b/avr.c
@@ -110,19 +110,16 @@ int avr_txrx_bit ( int fd, int bit )
    * read the result bit (it is either valid from a previous clock
    * pulse or it is ignored in the current context)
    */
-  r = ppi_get(fd, PPISTATUS, AVR_DATA);
+  r = ppi_getpin(fd, PIN_AVR_MISO);
 
   /* set the data input line as desired */
-  if (bit)
-    ppi_set(fd, PPIDATA, AVR_INSTR);
-  else
-    ppi_clr(fd, PPIDATA, AVR_INSTR);
+  ppi_setpin(fd, PIN_AVR_MOSI, bit);
 
   /* 
    * pulse the clock line, clocking in the MOSI data, and clocking out
    * the next result bit
    */
-  ppi_pulse(fd, PPIDATA, AVR_CLOCK);
+  ppi_pulsepin(fd, PIN_AVR_SCK);
 
   return r;
 }
@@ -400,7 +397,7 @@ int avr_signature ( int fd, unsigned char sig[4] )
  */
 void avr_powerup ( int fd )
 {
-  ppi_set(fd, PPIDATA, AVR_POWER);    /* power up */
+  ppi_set(fd, PPIDATA, PPI_AVR_VCC);    /* power up */
   usleep(100000);
 }
 
@@ -410,7 +407,7 @@ void avr_powerup ( int fd )
  */
 void avr_powerdown ( int fd )
 {
-  ppi_clr(fd, PPIDATA, AVR_POWER);    /* power down */
+  ppi_clr(fd, PPIDATA, PPI_AVR_VCC);    /* power down */
 }
 
 
@@ -424,9 +421,10 @@ int avr_initialize ( int fd, struct avrpart * p )
 
   avr_powerup(fd);
 
-  ppi_clr(fd, PPIDATA, AVR_CLOCK);
-  ppi_clr(fd, PPIDATA, AVR_RESET);
-  ppi_pulse(fd, PPIDATA, AVR_RESET);
+
+  ppi_setpin(fd, PIN_AVR_SCK, 0);
+  ppi_setpin(fd, PIN_AVR_RESET, 0);
+  ppi_pulsepin(fd, PIN_AVR_RESET);
 
   usleep(20000); /* 20 ms XXX should be a per-chip parameter */
 
@@ -447,7 +445,7 @@ int avr_initialize ( int fd, struct avrpart * p )
       rc = avr_program_enable ( fd );
       if (rc == 0)
         break;
-      ppi_pulse(fd, PPIDATA, AVR_CLOCK);
+      ppi_pulsepin(fd, PIN_AVR_SCK);
       tries++;
     } while (tries < 32);
 
diff --git a/avr.h b/avr.h
index 9a22e5d8..a77adca5 100644
--- a/avr.h
+++ b/avr.h
@@ -34,14 +34,18 @@
 
 #include <stdio.h>
 
-/*
- * bit definitions for AVR device connections
- */
-#define AVR_POWER 0xf1  /* bit 0 and 4...7 of data register */
-#define AVR_CLOCK 0x02  /* bit 1 of data register           */
-#define AVR_INSTR 0x04  /* bit 2 of data register           */
-#define AVR_RESET 0x08  /* bit 3 of data register           */
-#define AVR_DATA  0x40  /* bit 6 of status register         */
+
+#define PPI_AVR_VCC    0x0f  /* ppi pins 2-5, data reg bits 0-3 */
+#define PIN_AVR_BUFF   6
+#define PIN_AVR_RESET  7
+#define PIN_AVR_SCK    8
+#define PIN_AVR_MOSI   9
+#define PIN_AVR_MISO  10
+#define PIN_LED_ERR    1
+#define PIN_LED_RDY   14
+#define PIN_LED_PGM   16
+#define PIN_LED_VFY   17
+
 
 
 /*
@@ -61,7 +65,7 @@ struct avrmem {
   AVRMEM          memtype;
   int             startaddr;
   int             size;
-  unsigned char   buf;
+  unsigned char * buf;
   struct avrmem * next;
 };
 #endif
@@ -72,20 +76,14 @@ struct avrpart {
   int             memsize[AVR_MAXMEMTYPES]; /* sizes for eeprom,
                                                flash, etc, indexed by
                                                AVR_EEPROM or AVR_FLASH */
-#if 0
-  int             flash_size;       /* size in bytes of flash */
-  int             eeprom_size;      /* size in bytes of eeprom */
-#endif
   unsigned char   f_readback;       /* flash write polled readback value */
   unsigned char   e_readback[2];    /* eeprom write polled readback values */
   int             min_write_delay;  /* microseconds */
   int             max_write_delay;  /* microseconds */
   int             chip_erase_delay; /* microseconds */
-  unsigned char * mem[AVR_MAXMEMTYPES];
-#if 0
-  unsigned char * flash;
-  unsigned char * eeprom;
-#endif
+  unsigned char * mem[AVR_MAXMEMTYPES]; /* pointers to avr memory
+                                           buffers, indexed by
+                                           AVR_EEPROM or AVR_FLASH */
 };
 
 extern struct avrpart parts[];
diff --git a/main.c b/main.c
index 06165500..2a365eaf 100644
--- a/main.c
+++ b/main.c
@@ -32,25 +32,44 @@
 /*
  * Code to program an Atmel AVR AT90S device using the parallel port.
  *
- * Make the following connections:
+ * Make the following (minimal) connections:
  *
- *  Parallel Port      Atmel AVR
- *  -------------      ----------------------------
- *    Pin  2       ->   Vcc      (see NOTE below)
- *    Pin  3       ->   SCK      CLOCK IN
- *    Pin  4       ->   MOSI     Instruction input
- *    Pin  5       ->   /RESET
- *    Pin  6,7,8,9 ->   Vcc      (Can be tied together with Schottky diodes)
- *    Pin 10       <-   MISO     Data out
- *    Pin 18       <-   GND
+ *  Parallel Port      Programmer Function
+ *  -------------      -----------------------------
+ *       Pins 2-5  ->  Vcc (see note below)
+ *       Pin    7  ->  AVR /RESET
+ *       Pin    8  ->  AVR SCK  (clock input)
+ *       Pin    9  ->  AVR MOSI (instruction in)
+ *       Pin   10  <-  AVR MISO (data out)
+ *       Pin   18      Signal Ground
+ *
+ * Additionally, the following conntections can be made to enable
+ * additional features:
+ *
+ *  Parallel Port      Programmer Function
+ *  -------------      -----------------------------
+ *       Pin    1      STATUS LED, active low (program or verify error)
+ *       Pin    6  ->  /ENABLE ('367 bus driver)
+ *       Pin   14      STATUS LED, active low (ready)
+ *       Pin   16      STATUS LED, active low (programming)
+ *       Pin   17      STATUS LED, active low (verifying)
+ *
+ *  Pin 6 can be tied to the enable line of a 74HC367 in order to
+ *  isolate and buffer the data to and from the PC parallel port.
+ *  This is useful for connecting to a device in-circuit, and keeps
+ *  the state of the parallel port pins from interfering with the
+ *  normal operation of the target system.  When programming is
+ *  complete, this pin is driven high, causing to pins of the '367 to
+ *  float.
  *
  *  NOTE on Vcc connection: make sure your parallel port can supply an
- *  adequate amount of current to power your device.  6-10 mA is
- *  common for parallel port signal lines, but is not guaranteed,
- *  especially for notebook computers.  Optionally, you can tie pins
- *  6, 7, 8, and 9 also to Vcc with Schottky diodes to supply
- *  additional current.  If in doubt, don't risk damaging your
- *  parallel port, use an external power supply.
+ *  adequate amount of current to power your device.  6-10 mA per pin
+ *  is common for parallel port signal lines, but is not guaranteed,
+ *  especially for notebook computers.  For additional power, use
+ *  multiple pins tied together with Schottky diodes.  If in doubt,
+ *  don't risk damaging your parallel port, use an external power
+ *  supply.
+ * 
  */
 
 #include <stdio.h>
@@ -104,16 +123,16 @@ int getexitspecs ( char *s, int *set, int *clr )
 
   while ((cp = strtok(s, ","))) {
     if (strcmp(cp, "reset") == 0) {
-      *clr |= AVR_RESET; 
+      *clr |= ppi_getpinmask(PIN_AVR_RESET);
     }
     else if (strcmp(cp, "noreset") == 0) {
-      *set |= AVR_RESET; 
+      *set |= ppi_getpinmask(PIN_AVR_RESET);
     }
     else if (strcmp(cp, "vcc") == 0) { 
-      *set |= AVR_POWER; 
+      *set |= PPI_AVR_VCC;
     }
     else if (strcmp(cp, "novcc") == 0) {
-      *clr |= AVR_POWER; 
+      *clr |= PPI_AVR_VCC;
     }
     else {
       return -1;
@@ -374,6 +393,10 @@ int main ( int argc, char * argv [] )
 
   exitrc = 0;
 
+#if 0
+  ppi_sense(fd);
+#endif
+
   ppidata = ppi_getall(fd, PPIDATA);
   if (ppidata < 0) {
     fprintf ( stderr, "%s: error reading status of ppi data port\n", progname);
diff --git a/ppi.c b/ppi.c
index 0c85a3ba..286f613b 100644
--- a/ppi.c
+++ b/ppi.c
@@ -37,6 +37,36 @@
 
 extern char * progname;
 
+struct ppipins_t {
+  int pin;
+  int reg;
+  int bit;
+  int inverted;
+};
+
+static struct ppipins_t pins[] = {
+  {  1, PPICTRL,   0x01, 1 },
+  {  2, PPIDATA,   0x01, 0 },
+  {  3, PPIDATA,   0x02, 0 },
+  {  4, PPIDATA,   0x04, 0 },
+  {  5, PPIDATA,   0x08, 0 },
+  {  6, PPIDATA,   0x10, 0 },
+  {  7, PPIDATA,   0x20, 0 },
+  {  8, PPIDATA,   0x40, 0 },
+  {  9, PPIDATA,   0x80, 0 },
+  { 10, PPISTATUS, 0x40, 0 },
+  { 11, PPISTATUS, 0x80, 1 },
+  { 12, PPISTATUS, 0x20, 0 },
+  { 13, PPISTATUS, 0x10, 0 },
+  { 14, PPICTRL,   0x02, 1 }, 
+  { 15, PPISTATUS, 0x08, 0 },
+  { 16, PPICTRL,   0x04, 0 }, 
+  { 17, PPICTRL,   0x08, 1 }
+};
+
+#define NPINS (sizeof(pins)/sizeof(struct ppipins_t))
+
+
 /*
  * set 'get' and 'set' appropriately for subsequent passage to ioctl()
  * to get/set the specified PPI registers.  
@@ -125,7 +155,7 @@ int ppi_get ( int fd, int reg, int bit )
   ioctl(fd, get, &v);
   v &= bit;
 
-  return (v == bit);
+  return v; /* v == bit */
 }
 
 /*
@@ -198,24 +228,114 @@ int ppi_pulse ( int fd, int reg, int bit )
 }
 
 
+int ppi_setpin ( int fd, int pin, int value )
+{
+
+  if (pin < 1 || pin > 17)
+    return -1;
+
+  pin--;
+
+  if (pins[pin].inverted)
+    value = !value;
+
+  if (value)
+    ppi_set(fd, pins[pin].reg, pins[pin].bit);
+  else
+    ppi_clr(fd, pins[pin].reg, pins[pin].bit);
+
+  return 0;
+}
+
+
+int ppi_getpin ( int fd, int pin )
+{
+  int value;
+
+  if (pin < 1 || pin > 17)
+    return -1;
+
+  pin--;
+
+  value = ppi_get(fd, pins[pin].reg, pins[pin].bit);
+
+  if (value)
+    value = 1;
+    
+  if (pins[pin].inverted)
+    value = !value;
+
+  return value;
+}
+
+
+int ppi_pulsepin ( int fd, int pin )
+{
+
+  if (pin < 1 || pin > 17)
+    return -1;
+
+  pin--;
+
+  ppi_toggle(fd, pins[pin].reg, pins[pin].bit);
+  ppi_toggle(fd, pins[pin].reg, pins[pin].bit);
+
+  return 0;
+}
+
+
+int ppi_getpinmask ( int pin )
+{
+  if (pin < 1 || pin > 17)
+    return -1;
+
+  return pins[pin-1].bit;
+}
+
+
+int ppi_getpinreg ( int pin )
+{
+  if (pin < 1 || pin > 17)
+    return -1;
+
+  return pins[pin-1].reg;
+}
+
+
 /*
  * infinite loop, sensing on the pin that we use to read data out of
  * the device; this is a debugging aid, you can insert a call to this
  * function in 'main()' and can use it to determine whether your sense
  * pin is actually sensing.  
  */
-int ppi_sense_test ( int fd, int reg, int bit )
+int ppi_sense ( int fd )
 {
-  unsigned char v, pv;
+  unsigned int r, pr;
+  unsigned int v;
+  int count;
+  char buf[128];
+  int i;
 
-  pv = 1;
+  count = 0;
+
+  fprintf ( stderr, 
+            "parallel port data:\n"
+            "         111111111\n"
+            "123456789012345678\n" );
+
+  buf[17] = 0;
+  pr = 1;
   do {
-    usleep(100000); /* check every 100 ms */
-    v = ppi_get(fd, reg, bit);
-    if (v != pv) {
-      fprintf ( stderr, "sense bit = %d\n", v );
+    usleep(1); /* don't be too much of a cpu hog */
+    for (i=1; i<=17; i++) {
+      buf[i-1] = ppi_getpin(fd, i);
+      if (buf[i-1])
+        buf[i-1] = '|';
+      else
+        buf[i-1] = '.';
     }
-    pv = v;
+    fprintf(stderr, "\r                   \r%s", buf);
+
   } while(1);
 
   return 0;
diff --git a/ppi.h b/ppi.h
index 66c51764..1225e6fa 100644
--- a/ppi.h
+++ b/ppi.h
@@ -41,21 +41,33 @@ enum {
   PPISTATUS
 };
 
-int ppi_getops ( int reg, unsigned long * get, unsigned long * set );
+int ppi_getops     ( int reg, unsigned long * get, unsigned long * set );
 
-int ppi_set    ( int fd, int reg, int bit );
+int ppi_set        ( int fd, int reg, int bit );
 
-int ppi_clr    ( int fd, int reg, int bit );
+int ppi_clr        ( int fd, int reg, int bit );
 
-int ppi_get    ( int fd, int reg, int bit );
+int ppi_get        ( int fd, int reg, int bit );
 
-int ppi_toggle ( int fd, int reg, int bit );
+int ppi_toggle     ( int fd, int reg, int bit );
 
-int ppi_getall ( int fd, int reg );
+int ppi_getall     ( int fd, int reg );
 
-int ppi_setall ( int fd, int reg, int val );
+int ppi_setall     ( int fd, int reg, int val );
 
-int ppi_pulse  ( int fd, int reg, int bit );
+int ppi_pulse      ( int fd, int reg, int bit );
+
+int ppi_setpin     ( int fd, int pin, int value );
+
+int ppi_getpin     ( int fd, int pin );
+
+int ppi_pulsepin   ( int fd, int pin );
+
+int ppi_getpinmask ( int pin );
+
+int ppi_getpinreg  ( int pin );
+
+int ppi_sense      ( int fd );
 
 #endif