From 2e3fb8371b6dcb924729d42f8af5b5e285d21d02 Mon Sep 17 00:00:00 2001
From: bsd <bsd@81a1dc3b-b13d-400b-aceb-764788c761c2>
Date: Sat, 5 Aug 2000 05:12:50 +0000
Subject: [PATCH] This commit was generated by cvs2svn to compensate for
 changes in r2, which included commits to RCS files with non-trunk default
 branches.

git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@3 81a1dc3b-b13d-400b-aceb-764788c761c2
---
 Makefile  |  16 ++
 avrprog.c | 716 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 732 insertions(+)
 create mode 100644 Makefile
 create mode 100644 avrprog.c

diff --git a/Makefile b/Makefile
new file mode 100644
index 00000000..fabd1ac1
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,16 @@
+#
+# $Id$
+#
+
+TARGET = avrprog
+
+all : ${TARGET}
+
+CFLAGS = -Wall
+
+${TARGET} : avrprog.c
+	${CC} ${CFLAGS} -o ${TARGET} avrprog.c
+
+clean :
+	rm -f *.o ${TARGET} *~
+
diff --git a/avrprog.c b/avrprog.c
new file mode 100644
index 00000000..5898b946
--- /dev/null
+++ b/avrprog.c
@@ -0,0 +1,716 @@
+/*
+ * Copyright 2000, Brian Dean
+ * All Rights Reserved.
+ */
+
+/* $Id$ */
+
+/*
+ * Code to program an Atmel AVR device using the parallel port.
+ *
+ * Make the following connections:
+ *
+ *  Pin  2 -> PB7(SCK)  CLOCK IN             (data bit 0)
+ *  Pin  3 -> PB5(MOSI) Instruction input    (data bit 1)
+ *  Pin  4 -> /RESET                         (data bit 2)
+ *  Pin 10 <- PB6(MISO) Data out             (status bit 6)
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <stdarg.h>
+#include <sys/stat.h>
+#include </sys/dev/ppbus/ppi.h>
+#include </sys/dev/ppbus/ppbconf.h>
+
+#define PARALLEL "/dev/ppi0"
+
+char * progname;
+
+
+#define AVR_CLOCK 0x01  /* bit 0 of data register */
+#define AVR_INSTR 0x02  /* bit 1 of data register */
+#define AVR_RESET 0x04  /* bit 2 of data register */
+#define AVR_DATA  0x40  /* bit 6 of status register */
+
+
+enum {
+  PPIDATA,
+  PPICTRL,
+  PPISTATUS
+};
+
+
+enum {
+  AVR_EEPROM,
+  AVR_FLASH,
+  AVR_FLASH_LO,
+  AVR_FLASH_HI
+};
+
+
+int dprintf ( FILE * f, char * format, ... )
+{
+#if DEBUG
+  va_list ap;
+  int rc;
+
+  va_start(ap,format);
+  rc = vfprintf(f,format,ap);
+  va_end(ap);
+
+  return rc;
+#else
+  return 0;
+#endif
+}
+
+
+int ppi_getops ( int reg, unsigned long * get, unsigned long * set )
+{
+  switch (reg) {
+    case PPIDATA:
+      *set = PPISDATA;
+      *get = PPIGDATA;
+      break;
+    case PPICTRL:
+      *set = PPISCTRL;
+      *get = PPIGCTRL;
+      break;
+    case PPISTATUS:
+      *set = PPISSTATUS;
+      *get = PPIGSTATUS;
+      break;
+    default:
+      fprintf ( stderr, "%s: avr_set(): invalid register=%d\n",
+                progname, reg );
+      return -1;
+      break;
+  }
+
+  return 0;
+}
+
+
+int ppi_set ( int fd, int reg, int bit )
+{
+  unsigned char v;
+  unsigned long get, set;
+  int rc;
+
+  rc = ppi_getops ( reg, &get, &set );
+  if (rc)
+    return -1;
+
+  ioctl(fd, get, &v);
+  v |= bit;
+  ioctl(fd, set, &v);
+
+  return 0;
+}
+
+
+int ppi_clr ( int fd, int reg, int bit )
+{
+  unsigned char v;
+  unsigned long get, set;
+  int rc;
+
+  rc = ppi_getops ( reg, &get, &set );
+  if (rc)
+    return -1;
+
+  ioctl(fd, get, &v);
+  v &= ~bit;
+  ioctl(fd, set, &v);
+
+  return 0;
+}
+
+
+int ppi_get ( int fd, int reg, int bit )
+{
+  unsigned char v;
+  unsigned long get, set;
+  int rc;
+
+  rc = ppi_getops ( reg, &get, &set );
+  if (rc)
+    return -1;
+
+  ioctl(fd, get, &v);
+  v &= bit;
+
+  return (v == bit);
+}
+
+
+int ppi_toggle ( int fd, int reg, int bit )
+{
+  unsigned char v;
+  unsigned long get, set;
+  int rc;
+
+  rc = ppi_getops ( reg, &get, &set );
+  if (rc)
+    return -1;
+
+  ioctl(fd, get, &v);
+  v |= bit;
+  ioctl(fd, set, &v);
+
+  v &= ~bit;
+  ioctl(fd, set, &v);
+
+  return 0;
+}
+
+
+int avr_txrx_bit ( int fd, int bit )
+{
+  unsigned char d;
+  int r;
+
+  ioctl(fd, PPIGDATA, &d);
+
+  r = ppi_get(fd, PPISTATUS, AVR_DATA);
+
+  if (bit)
+    ppi_set(fd, PPIDATA, AVR_INSTR);
+  else
+    ppi_clr(fd, PPIDATA, AVR_INSTR);
+
+  ppi_toggle(fd, PPIDATA, AVR_CLOCK);
+
+  return r;
+}
+
+
+unsigned char avr_txrx ( int fd, unsigned char byte )
+{
+  int i;
+  unsigned char r, b, rbyte;
+
+  rbyte = 0;
+  for (i=0; i<8; i++) {
+    b = (byte >> (7-i)) & 0x01;
+    r = avr_txrx_bit ( fd, b );
+    rbyte = rbyte | (r << (7-i));
+  }
+
+  return rbyte;
+}
+
+
+unsigned char avr_read_byte ( int fd, unsigned short addr, int memtype )
+{
+  unsigned char r;
+
+  switch (memtype) {
+    case AVR_FLASH_LO: 
+      avr_txrx(fd, 0x20); 
+      break;
+    case AVR_FLASH_HI: 
+      avr_txrx(fd, 0x28); 
+      break;
+    case AVR_EEPROM: 
+      avr_txrx(fd, 0xa0); 
+      addr &= 0x7f;
+      break;
+    default:
+      fprintf(stderr, "%s: avr_read_byte(); internal error: invalid memtype=%d\n",
+              progname, memtype);
+      exit(1);
+      break;
+  }
+
+  avr_txrx(fd, addr >> 8);     /* high order bits of address       */
+  avr_txrx(fd, addr & 0x0ff);  /* low order bits of address        */
+  r = avr_txrx(fd, 0);         /* don't care                       */
+
+  return r;
+}
+
+
+int avr_read ( int fd, int memtype, unsigned start, unsigned n, 
+               unsigned char * buf, int bufsize )
+{
+  unsigned char rbyte;
+  unsigned short data;
+  unsigned short end, i, bi;
+
+  switch (memtype) {
+    case AVR_FLASH  : 
+    case AVR_EEPROM : 
+      break;
+    default:
+      fprintf(stderr, "%s: avr_read(); internal error: invalid memtype=%d\n",
+              progname, memtype);
+      exit(1);
+      break;
+  }
+
+  end = start+n;
+
+  bi = 0;
+
+  for (i=start; i<end; i++) {
+    if (memtype == AVR_FLASH) {
+      rbyte = avr_read_byte(fd, i, AVR_FLASH_LO);  /* flash low byte */
+      fprintf ( stderr, "                    \r%4u  0x%02x", i, rbyte );
+      data = rbyte;
+      if (bi < bufsize) {
+        buf[bi++] = rbyte;
+      }
+
+      rbyte = avr_read_byte(fd, i, AVR_FLASH_HI);  /* flash high byte */
+      fprintf ( stderr, " 0x%02x", rbyte );
+      data |= (rbyte << 8);
+      if (bi < bufsize) {
+        buf[bi++] = rbyte;
+      }
+    }
+    else {
+      rbyte = avr_read_byte(fd, i, memtype);  /* eeprom byte */
+      fprintf ( stderr, "          \r%4u  0x%02x", i, rbyte );
+      if (bi < bufsize) {
+        buf[bi++] = rbyte;
+      }
+    }
+
+  }
+
+  fprintf ( stderr, "\n" );
+
+  return 0;
+}
+
+
+int avr_write_byte ( int fd, int memtype, unsigned short addr, unsigned char data )
+{
+  unsigned char r;
+  int ready;
+  int tries;
+
+  switch (memtype) {
+    case AVR_FLASH_LO: 
+      avr_txrx(fd, 0x40); 
+      break;
+    case AVR_FLASH_HI: 
+      avr_txrx(fd, 0x48); 
+      break;
+    case AVR_EEPROM: 
+      avr_txrx(fd, 0xc0); 
+      addr &= 0x7f;
+      break;
+    default:
+      fprintf(stderr, "%s: avr_write_byte(); internal error: invalid memtype=%d\n",
+              progname, memtype);
+      exit(1);
+      break;
+  }
+
+  avr_txrx(fd, addr >> 8);     /* high order bits of address       */
+  avr_txrx(fd, addr & 0x0ff);  /* low order bits of address        */
+  avr_txrx(fd, data);          /* data                             */
+
+  tries = 0;
+  ready = 0;
+  while (!ready) {
+    usleep(5000);               /* flash write delay */
+    r = avr_read_byte ( fd, addr, memtype );
+    if (data == 0x7f) {
+      usleep(20000);
+      ready = 1;
+    }
+    else if (r == data) {
+      ready = 1;
+    }
+    tries++;
+    if (!ready && tries > 10) {
+      fprintf(stderr, "**" );
+      ready = 1;
+    }
+  }
+
+  return 0;
+}
+
+
+int avr_write ( int fd, int memtype, unsigned start, 
+                unsigned char * buf, int size )
+{
+  unsigned char data;
+  unsigned short end, i, bi;
+
+  switch (memtype) {
+    case AVR_FLASH  : 
+      end = start+size/2;
+      break;
+    case AVR_EEPROM : 
+      end = start+size;
+      break;
+    default:
+      fprintf(stderr, "%s: avr_write(); internal error: invalid memtype=%d\n",
+              progname, memtype);
+      exit(1);
+      break;
+  }
+
+  bi = 0;
+
+  for (i=start; i<end; i++) {
+    if (memtype == AVR_FLASH) {
+      /* low byte */
+      data = buf[bi++];
+      avr_write_byte(fd, AVR_FLASH_LO, i, data );
+      fprintf ( stderr, "                      \r%4u 0x%02x", i, data );
+
+      /* high byte */
+      data = buf[bi++];
+      avr_write_byte(fd, AVR_FLASH_HI, i, data );
+      fprintf ( stderr, " 0x%02x", data );
+    }
+    else {
+      data = buf[bi++];
+      avr_write_byte(fd, memtype, i, data );
+      fprintf ( stderr, "            \r%4u 0x%02x", i, data );
+    }
+
+  }
+
+  fprintf ( stderr, "\n" );
+
+  return 0;
+}
+
+
+int avr_program_enable ( int fd )
+{
+  unsigned char data[4] = {0xac, 0x53, 0x00, 0x00};
+  unsigned char byte, rbyte;
+  int avrok;
+  int i;
+
+  avrok = 0;
+
+  for (i=0; i<4; i++) {
+    byte = data[i];
+    rbyte = avr_txrx ( fd, byte );
+    if (i == 2) {
+      if (rbyte == data[1])
+        avrok = 1;
+    }
+  }
+
+  if (!avrok)
+    return -1;
+
+  return 0;
+}
+
+
+int avr_chip_erase ( int fd )
+{
+  unsigned char data[4] = {0xac, 0x80, 0x00, 0x00};
+  int i;
+
+  for (i=0; i<4; i++) {
+    avr_txrx ( fd, data[i] );
+  }
+
+  usleep(20000);
+
+  return 0;
+}
+
+
+int avr_initialize ( int fd )
+{
+  int rc;
+  int tries;
+
+  ppi_clr(fd, PPIDATA, AVR_CLOCK);
+  ppi_clr(fd, PPIDATA, AVR_RESET);
+  ppi_toggle(fd, PPIDATA, AVR_RESET);
+
+  usleep(20000); /* 20 ms */
+
+  tries = 0;
+  do {
+    rc = avr_program_enable ( fd );
+    if (rc == 0)
+      break;
+    ppi_toggle(fd, PPIDATA, AVR_CLOCK);
+    tries++;
+  } while (tries < 32);
+  if (tries == 32) {
+    fprintf ( stderr, "%s: AVR device not responding\n", progname );
+    return -1;
+  }
+  return 0;
+}
+
+
+int ppi_sense_test ( int fd )
+{
+  unsigned char v, pv;
+
+  pv = 1;
+  do {
+    v = ppi_get(fd, PPISTATUS, AVR_DATA);
+    if (v != pv) {
+      fprintf ( stderr, "PPISTATUS bit = %d\n", v );
+    }
+    pv = v;
+  } while(1);
+
+  return 0;
+}
+
+
+
+/* vars for getopt() */
+char *optarg;
+int optind;
+int optopt;
+int opterr;
+int optreset;
+
+
+void usage ( void )
+{
+  fprintf ( stderr, 
+            "\nUsage:  %s [-r] [-e|-f] [-u InputFile|-o Outputfile]\n"
+            "\n"
+            "  Available Options:\n"
+            "    -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"
+            "    -u InputFile  : write data from this file\n"
+            "    -o OutputFile : write data to this file\n"
+            "\n",
+            progname );
+}
+
+
+int main ( int argc, char * argv [] )
+{
+  int fd;
+  int rc;
+  unsigned char buf[2048];
+  int ch;
+  int iofd;
+  int flash, eeprom, doread, erase;
+  int size;
+  char * outputf;
+  char * inputf;
+
+  iofd    = -1;
+  outputf = NULL;
+  inputf  = NULL;
+  doread  = 1;
+  eeprom  = 0;
+  flash   = 0;
+  erase   = 0;
+
+  progname = rindex(argv[0],'/');
+  if (progname)
+    progname++;
+  else
+    progname = argv[0];
+
+  while ((ch = getopt(argc,argv,"?efo:ru:")) != -1) {
+    switch (ch) {
+      case 'e':
+        if (flash) {
+          fprintf(stderr,"%s: -e and -f are incompatible\n", progname);
+          return 1;
+        }
+        eeprom = 1;
+        break;
+      case 'r':
+        erase = 1;
+        break;
+      case 'f':
+        if (eeprom) {
+          fprintf(stderr,"%s: -e and -f are incompatible\n", progname);
+          return 1;
+        }
+        flash = 1;
+        break;
+      case 'o':
+        if (inputf) {
+          fprintf(stderr,"%s: -o and -u are incompatible\n", progname);
+          return 1;
+        }
+        doread = 1;
+        outputf = optarg;
+        if (strcmp(outputf,"-")==0) {
+          iofd = fileno(stdout);
+        }
+        else {
+          iofd = open ( outputf, O_WRONLY|O_CREAT|O_TRUNC,
+                        S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
+          if (iofd < 0) {
+            fprintf(stderr, "%s: can't open output file \"%s\": %s\n",
+                    progname, outputf, strerror(errno));
+            return 1;
+          }
+        }
+        break;
+      case 'u':
+        if (outputf) {
+          fprintf(stderr,"%s: -o and -u are incompatible\n", progname);
+          return 1;
+        }
+        doread = 0;
+        inputf = optarg;
+        iofd = open ( inputf, O_RDONLY, 0);
+        if (iofd < 0) {
+          fprintf(stderr, "%s: can't open input file \"%s\": %s\n",
+                  progname, inputf, strerror(errno));
+          return 1;
+        }
+        break;
+      case '?':
+        usage();
+        return 1;
+        break;
+      default:
+        fprintf(stderr, "%s: invalid option -%c\n", progname, ch);
+        usage();
+        return 1;
+        break;
+    }
+  }
+
+  fd = open ( PARALLEL, O_RDWR );
+  if (fd < 0) {
+    fprintf ( stderr, "%s: can't open device \"%s\": %s\n",
+              progname, PARALLEL, strerror(errno) );
+    return 1;
+  }
+
+  fprintf ( stderr, "%s: initializing\n", progname );
+  rc = avr_initialize(fd);
+  if (rc < 0) {
+    fprintf ( stderr, "%s: initialization failed, rc=%d\n", progname, rc );
+    return 1;
+  }
+
+  fprintf ( stderr, "%s: AVR device initialized and ready to accept instructions\n",
+            progname );
+
+  if (erase) {
+    fprintf(stderr, "%s: erasing chip\n", progname );
+    avr_chip_erase(fd);
+    avr_initialize(fd);
+    fprintf(stderr, "%s: done.\n", progname );
+  }
+
+  if (iofd < 0) {
+    fprintf(stderr, "%s: you must specify an input or an output file\n",
+            progname);
+    return 1;
+  }
+
+  if (!(eeprom||flash)) {
+    fprintf(stderr, 
+            "%s: please specify either the eeprom (-e) or the flash (-f) memory\n",
+            progname);
+    return 1;
+  }
+
+  if (doread) {
+    /*
+     * read device memory 
+     */
+    if (flash) {
+      size = 2048;
+      fprintf ( stderr, "%s: reading flash memory:\n", progname );
+      rc = avr_read ( fd, AVR_FLASH, 0, size/2, buf, size );
+      if (rc) {
+        fprintf ( stderr, "%s: failed to read all of flash memory, rc=%d\n", 
+                  progname, rc );
+        return 1;
+      }
+    }
+    else if (eeprom) {
+      size = 128;
+      fprintf ( stderr, "%s: reading eeprom memory:\n", progname );
+      rc = avr_read ( fd, AVR_EEPROM, 0, size, buf, size );
+      if (rc) {
+        fprintf ( stderr, "%s: failed to read all of eeprom memory, rc=%d\n", 
+                  progname, rc );
+        return 1;
+      }
+    }
+
+    rc = write ( iofd, buf, size );
+    if (rc < 0) {
+      fprintf(stderr, "%s: write error: %s\n", progname, strerror(errno));
+      return 1;
+    }
+    else if (rc != size) {
+      fprintf(stderr, "%s: wrote only %d bytes of the expected %d\n", 
+              progname, rc, size);
+      return 1;
+    }
+  }
+  else {
+    /*
+     * write device memory 
+     */
+    if (flash) {
+      size = 2048;
+    }
+    else if (eeprom) {
+      size = 128;
+    }
+
+    /* read in the data file */
+    rc = read(iofd, buf, size);
+    if (rc < 0) {
+      fprintf(stderr, "%s: read error from \"%s\": %s\n", 
+              progname, inputf, strerror(errno));
+      return 1;
+    }
+    else if (rc != size) {
+      fprintf(stderr, "%s: read only %d bytes of the expected %d from \"%s\"\n", 
+              progname, rc, size, inputf);
+      return 1;
+    }
+
+    if (flash) {
+      fprintf ( stderr, "%s: writing flash memory:\n", progname );
+      rc = avr_write ( fd, AVR_FLASH, 0, buf, size );
+      if (rc) {
+        fprintf ( stderr, "%s: failed to write flash memory, rc=%d\n", 
+                  progname, rc );
+        return 1;
+      }
+    }
+    else if (eeprom) {
+      fprintf ( stderr, "%s: writing eeprom memory:\n", progname );
+      rc = avr_write ( fd, AVR_EEPROM, 0, buf, size );
+      if (rc) {
+        fprintf ( stderr, "%s: failed to write eeprom memory, rc=%d\n", 
+                  progname, rc );
+        return 1;
+      }
+    }
+  }
+
+  close(fd);
+  close(iofd);
+
+  return 0;
+}
+
+