From 019b9583c04a1b14db458201cceed4110973ba47 Mon Sep 17 00:00:00 2001
From: "Brian S. Dean" <bsd@bsdhome.com>
Date: Sun, 31 Dec 2000 02:24:50 +0000
Subject: [PATCH] Update after receiving some good feedback from Joerg Wunsch. 
 We should now be able to program AT90S1200's.

git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk@16 81a1dc3b-b13d-400b-aceb-764788c761c2
---
 avrdude/avrprog.c | 143 +++++++++++++++++++++++++++++++---------------
 1 file changed, 97 insertions(+), 46 deletions(-)

diff --git a/avrdude/avrprog.c b/avrdude/avrprog.c
index c5dc6e22..59a134db 100644
--- a/avrdude/avrprog.c
+++ b/avrdude/avrprog.c
@@ -55,7 +55,6 @@
 #include <stdarg.h>
 #include <sys/stat.h>
 #include </sys/dev/ppbus/ppi.h>
-#include </sys/dev/ppbus/ppbconf.h>
 
 #define PARALLEL "/dev/ppi0"
 
@@ -105,21 +104,11 @@ struct avrpart {
 
 struct avrpart parts[] = {
   { "AT90S8515", "8515", 8192, 512 },
-  { "AT90S2313", "2313", 2048, 128 }
+  { "AT90S2313", "2313", 2048, 128 },
+  { "AT90S1200", "1200", 1200,  64 }
 };
 
 
-
-/*
- * variable declarations required for getopt() 
- */
-char *optarg;
-int optind;
-int optopt;
-int opterr;
-int optreset;
-
-
 /*
  * set 'get' and 'set' appropriately for subsequent passage to ioctl()
  * to get/set the specified PPI registers.  
@@ -250,18 +239,24 @@ int ppi_pulse ( int fd, int reg, int bit )
  */
 int avr_txrx_bit ( int fd, int bit )
 {
-  unsigned char d;
   int r;
 
-  ioctl(fd, PPIGDATA, &d);
-
+  /* 
+   * 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);
 
+  /* set the data input line as desired */
   if (bit)
     ppi_set(fd, PPIDATA, AVR_INSTR);
   else
     ppi_clr(fd, PPIDATA, AVR_INSTR);
 
+  /* 
+   * pulse the clock line, clocking in the MOSI data, and clocking out
+   * the next result bit
+   */
   ppi_pulse(fd, PPIDATA, AVR_CLOCK);
 
   return r;
@@ -586,7 +581,7 @@ void avr_powerdown ( int fd )
 /*
  * initialize the AVR device and prepare it to accept commands
  */
-int avr_initialize ( int fd )
+int avr_initialize ( int fd, struct avrpart * p )
 {
   int rc;
   int tries;
@@ -600,24 +595,33 @@ int avr_initialize ( int fd )
   usleep(20000); /* 20 ms */
 
   /*
-   * enable programming mode, try up to 32 times in order to possibly
-   * get back into sync with the chip if we are out of sync.  
+   * Enable programming mode.  If we are programming an AT90S1200, we
+   * can only issue the command and hope it worked.  If we are using
+   * one of the other chips, the chip will echo 0x53 when issuing the
+   * third byte of the command.  In this case, try up to 32 times in
+   * order to possibly get back into sync with the chip if we are out
+   * of sync.
    */
-  tries = 0;
-  do {
-    rc = avr_program_enable ( fd );
-    if (rc == 0)
-      break;
-    ppi_pulse(fd, PPIDATA, AVR_CLOCK);
-    tries++;
-  } while (tries < 32);
+  if (strcmp(p->partdesc, "AT90S1200")==0) {
+    avr_program_enable ( fd );
+  }
+  else {
+    tries = 0;
+    do {
+      rc = avr_program_enable ( fd );
+      if (rc == 0)
+        break;
+      ppi_pulse(fd, PPIDATA, AVR_CLOCK);
+      tries++;
+    } while (tries < 32);
 
-  /*
-   * can't sync with the device, maybe it's not attached?
-   */
-  if (tries == 32) {
-    fprintf ( stderr, "%s: AVR device not responding\n", progname );
-    return -1;
+    /*
+     * can't sync with the device, maybe it's not attached?
+     */
+    if (tries == 32) {
+      fprintf ( stderr, "%s: AVR device not responding\n", progname );
+      return -1;
+    }
   }
 
   return 0;
@@ -654,6 +658,8 @@ int ppi_sense_test ( int fd )
  */
 void usage ( void )
 {
+  int i;
+
   fprintf ( stderr, 
             "\nUsage:  %s [-r] [-e|-f] [-u InputFile|-o Outputfile]\n"
             "\n"
@@ -661,11 +667,21 @@ void usage ( void )
             "    -r            : erase the flash and eeprom (required before programming)\n"
             "    -e            : select eeprom for reading or writing\n"
             "    -f            : select flash for reading or writing\n"
-            "    -p Part       : 8515 or 2313\n"
+            "    -p Part       : see below for valid parts\n"
             "    -u InputFile  : write data from this file\n"
             "    -o OutputFile : write data to this file\n"
+            "    -F            : override invalid device signature check\n"
+            "    -s            : read device signature bytes\n"
             "\n",
             progname );
+
+  fprintf(stderr, "  Valid Parts for the -p option are:\n");
+  for (i=0; i<sizeof(parts)/sizeof(parts[0]); i++) {
+    fprintf(stderr, "    \"%s\" = %s\n", 
+            parts[i].optiontag, parts[i].partdesc);
+  }
+  fprintf(stderr, "\n");
+
 }
 
 
@@ -678,7 +694,6 @@ int main ( int argc, char * argv [] )
   int rc, exitrc;
   int i;
   unsigned char * buf;
-  unsigned char sig[4];
   int ch;
   int iofd;
   int flash, eeprom, doread, erase, dosig;
@@ -687,6 +702,9 @@ int main ( int argc, char * argv [] )
   char * inputf;
   char * p1, * p2;
   struct avrpart * p;
+  unsigned char sig[4], nulldev[4];
+  int len;
+  int ovsigck;
 
   iofd    = -1;
   outputf = NULL;
@@ -697,6 +715,7 @@ int main ( int argc, char * argv [] )
   erase   = 0;
   dosig   = 0;
   p       = NULL;
+  ovsigck = 0;
 
   progname = rindex(argv[0],'/');
   if (progname)
@@ -740,7 +759,7 @@ int main ( int argc, char * argv [] )
   /*
    * process command line arguments
    */
-  while ((ch = getopt(argc,argv,"?efo:p:rsu:")) != -1) {
+  while ((ch = getopt(argc,argv,"?efFo:p:rsu:")) != -1) {
     switch (ch) {
       case 'e': /* select eeprom memory */
         if (flash) {
@@ -749,12 +768,6 @@ int main ( int argc, char * argv [] )
         }
         eeprom = 1;
         break;
-      case 'r': /* perform a chip erase */
-        erase = 1;
-        break;
-      case 's': /* read out the signature bytes */
-        dosig = 1;
-        break;
       case 'f': /* select flash memory */
         if (eeprom) {
           fprintf(stderr,"%s: -e and -f are incompatible\n", progname);
@@ -762,6 +775,9 @@ int main ( int argc, char * argv [] )
         }
         flash = 1;
         break;
+      case 'F': /* override invalid signature check */
+        ovsigck = 1;
+        break;
       case 'o': /* specify output file */
         if (inputf) {
           fprintf(stderr,"%s: -o and -u are incompatible\n", progname);
@@ -801,6 +817,12 @@ int main ( int argc, char * argv [] )
           return 1;
         }
         break;
+      case 'r': /* perform a chip erase */
+        erase = 1;
+        break;
+      case 's': /* read out the signature bytes */
+        dosig = 1;
+        break;
       case 'u': /* specify input (upload) file */
         if (outputf) {
           fprintf(stderr,"%s: -o and -u are incompatible\n", progname);
@@ -827,7 +849,6 @@ int main ( int argc, char * argv [] )
     }
   }
 
-
   if (p == NULL) {
     fprintf(stderr, 
             "%s: No AVR part has been specified, use \"-p Part\"\n\n"
@@ -875,7 +896,7 @@ int main ( int argc, char * argv [] )
   /*
    * initialize the chip in preperation for accepting commands
    */
-  rc = avr_initialize(fd);
+  rc = avr_initialize(fd,p);
   if (rc < 0) {
     fprintf ( stderr, "%s: initialization failed, rc=%d\n", progname, rc );
     exitrc = 1;
@@ -885,6 +906,36 @@ int main ( int argc, char * argv [] )
   fprintf ( stderr, "%s: AVR device initialized and ready to accept instructions\n",
             progname );
 
+  /*
+   * Let's read the signature bytes to make sure there is at least a
+   * chip on the other end that is responding correctly.  A check
+   * against 0xffffffff should ensure that the signature bytes are
+   * valid.  
+   */
+  avr_signature(fd, sig);
+  fprintf(stderr, "%s: Device signature = 0x", progname);
+  for (i=0; i<4; i++)
+    fprintf(stderr, "%02x", sig[i]);
+  fprintf(stderr, "\n");
+
+  memset(nulldev,0xff,4);
+  if (memcmp(sig,nulldev,4)==0) {
+    len = strlen(progname) + 2;
+    for (i=0; i<len; i++)
+      buf[i] = ' ';
+    buf[i] = 0;
+    fprintf(stderr, 
+            "%s: Yikes!  Invalid device signature.\n", progname);
+    if (!ovsigck) {
+      fprintf(stderr, 
+              "%sDouble check connections and try again, or use -F to override\n"
+              "%sthis check.\n\n",
+              buf, buf );
+      exit(1);
+    }
+  }
+
+  fprintf(stderr, "\n");
 
   if (erase) {
     /*
@@ -893,7 +944,7 @@ int main ( int argc, char * argv [] )
      */
     fprintf(stderr, "%s: erasing chip\n", progname );
     avr_chip_erase(fd);
-    avr_initialize(fd);
+    avr_initialize(fd,p);
     fprintf(stderr, "%s: done.\n", progname );
   }
 
@@ -905,7 +956,7 @@ int main ( int argc, char * argv [] )
     fprintf(stderr, "%s: reading signature bytes: ", progname );
     avr_signature(fd, sig);
     for (i=0; i<4; i++)
-      fprintf(stderr, "0x%02x ", sig[i]);
+      fprintf(stderr, "%02x", sig[i]);
     fprintf(stderr, "\n");
   }