From 191a5a44308efd8d8b035aa3da1f001301806bc4 Mon Sep 17 00:00:00 2001
From: "Theodore A. Roth" <troth@openavr.org>
Date: Mon, 24 Mar 2003 07:09:16 +0000
Subject: [PATCH] * avr.c (avr_write): Add call to pgm->write_setup() before
 the write loop. * avr910.c: Change all show_func_info() calls to
 no_show_func_info(). Add read/write to/from flash/eeprom memory
 functionality. * pgm.c: Initialize pgm->write_setup. * pgm.h: Add write_setup
 field to PROGRAMMER structure. * ser_posix.c: Remove unneeded cast in
 verbosity code.

git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk@299 81a1dc3b-b13d-400b-aceb-764788c761c2
---
 avrdude/ChangeLog   |  10 +++
 avrdude/avr.c       |   4 ++
 avrdude/avr910.c    | 168 +++++++++++++++++++++++++++++++++++++++-----
 avrdude/pgm.c       |   1 +
 avrdude/pgm.h       |   1 +
 avrdude/ser_posix.c |   8 +--
 6 files changed, 169 insertions(+), 23 deletions(-)

diff --git a/avrdude/ChangeLog b/avrdude/ChangeLog
index 49723264..9978a531 100644
--- a/avrdude/ChangeLog
+++ b/avrdude/ChangeLog
@@ -1,3 +1,13 @@
+2003-03-23  Theodore A. Roth  <troth@openavr.org>
+
+	* avr.c (avr_write): Add call to pgm->write_setup() before the write
+	loop.
+	* avr910.c: Change all show_func_info() calls to no_show_func_info().
+	Add read/write to/from flash/eeprom memory functionality.
+	* pgm.c: Initialize pgm->write_setup.
+	* pgm.h: Add write_setup field to PROGRAMMER structure.
+	* ser_posix.c: Remove unneeded cast in verbosity code.
+
 2003-03-23  Theodore A. Roth  <troth@openavr.org>
 
 	* ser_posix.c: Limit verbose output to 2 chars.
diff --git a/avrdude/avr.c b/avrdude/avr.c
index 8d7e8742..0bf18a0f 100644
--- a/avrdude/avr.c
+++ b/avrdude/avr.c
@@ -733,6 +733,10 @@ int avr_write(PROGRAMMER * pgm, AVRPART * p, char * memtype, int size,
     }
   }
 
+  if (pgm->write_setup) {
+      pgm->write_setup(pgm, p, m);
+  }
+
   for (i=0; i<wsize; i++) {
     data = m->buf[i];
     if (verbose) {
diff --git a/avrdude/avr910.c b/avrdude/avr910.c
index 2ab41e5d..6e46d9c2 100644
--- a/avrdude/avr910.c
+++ b/avrdude/avr910.c
@@ -67,7 +67,7 @@ static int avr910_recv(PROGRAMMER * pgm, char * buf, size_t len)
 
 static int avr910_drain(PROGRAMMER * pgm, int display)
 {
-  show_func_info();
+  no_show_func_info();
 
   return serial_drain(pgm->fd, display);
 }
@@ -139,12 +139,27 @@ static int avr910_chip_erase(PROGRAMMER * pgm, AVRPART * p)
   return 0;
 }
 
+
+static void avr910_enter_prog_mode(PROGRAMMER * pgm)
+{
+  avr910_send(pgm, "P", 1);
+  avr910_vfy_cmd_sent(pgm, "enter prog mode");
+}
+
+
+static void avr910_leave_prog_mode(PROGRAMMER * pgm)
+{
+  avr910_send(pgm, "L", 1);
+  avr910_vfy_cmd_sent(pgm, "leave prog mode");
+}
+
+
 /*
  * issue the 'program enable' command to the AVR device
  */
 static int avr910_program_enable(PROGRAMMER * pgm, AVRPART * p)
 {
-  show_func_info();
+  no_show_func_info();
 
   return -1;
 }
@@ -176,20 +191,6 @@ static void avr910_powerdown(PROGRAMMER * pgm)
 }
 
 
-static void avr910_enter_prog_mode(PROGRAMMER * pgm)
-{
-  avr910_send(pgm, "P", 1);
-  avr910_vfy_cmd_sent(pgm, "enter prog mode");
-}
-
-
-static void avr910_leave_prog_mode(PROGRAMMER * pgm)
-{
-  avr910_send(pgm, "L", 1);
-  avr910_vfy_cmd_sent(pgm, "leave prog mode");
-}
-
-
 /*
  * initialize the AVR device and prepare it to accept commands
  */
@@ -203,7 +204,7 @@ static int avr910_initialize(PROGRAMMER * pgm, AVRPART * p)
   unsigned char c;
   int dev_supported = 0;
 
-  show_func_info();
+  no_show_func_info();
 
   /* Get the programmer identifier. Programmer returns exactly 7 chars
      _without_ the null.*/
@@ -316,7 +317,7 @@ static int avr910_cmd(PROGRAMMER * pgm, unsigned char cmd[4],
 {
   int i;
 
-  show_func_info();
+  no_show_func_info();
 
   for (i=0; i<4; i++) {
     fprintf(stderr, "cmd[%d] = 0x%02x\n", i, cmd[i]);
@@ -352,11 +353,137 @@ static void avr910_close(PROGRAMMER * pgm)
 
 static void avr910_display(PROGRAMMER * pgm, char * p)
 {
-  show_func_info();
+  no_show_func_info();
 
   return;
 }
 
+
+static void avr910_set_addr(PROGRAMMER * pgm, unsigned long addr)
+{
+  unsigned char cmd[3];
+
+  cmd[0] = 'A';
+  cmd[1] = (addr >> 8) & 0xff;
+  cmd[2] = addr & 0xff;
+  
+  avr910_send(pgm, cmd, sizeof(cmd));
+  avr910_vfy_cmd_sent(pgm, "set addr");
+}
+
+
+/*
+ * For some reason, if we don't do this when writing to flash, the first byte
+ * of flash is not programmed. I susect that the board got out of sync after
+ * the erase and sending another command gets us back in sync. -TRoth
+ */
+static void avr910_write_setup(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m)
+{
+  if (strcmp(m->desc, "flash") == 0) {
+    avr910_send(pgm, "y", 1);
+    avr910_vfy_cmd_sent(pgm, "clear LED");
+  }
+}
+
+
+static int avr910_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
+                             unsigned long addr, unsigned char value)
+{
+  unsigned char cmd[2];
+
+  no_show_func_info();
+
+  if (strcmp(m->desc, "flash") == 0) {
+    if (addr & 0x01) {
+      cmd[0] = 'C';             /* Write Program Mem high byte */
+    }
+    else {
+      cmd[0] = 'c';
+    }
+
+    addr >>= 1;
+  }
+  else if (strcmp(m->desc, "eeprom") == 0) {
+    cmd[0] = 'D';
+  }
+  else {
+    return -1;
+  }
+
+  cmd[1] = value;
+
+  avr910_set_addr(pgm, addr);
+
+  avr910_send(pgm, cmd, sizeof(cmd));
+  avr910_vfy_cmd_sent(pgm, "write byte");
+
+  return 0;
+}
+
+
+static int avr910_read_byte_flash(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
+                                  unsigned long addr, unsigned char * value)
+{
+  static int cached = 0;
+  static unsigned char cvalue;
+  static unsigned long caddr;
+
+  if (cached && ((caddr + 1) == addr)) {
+    *value = cvalue;
+    cached = 0;
+  }
+  else {
+    unsigned char buf[2];
+
+    avr910_set_addr(pgm, addr >> 1);
+
+    avr910_send(pgm, "R", 1);
+
+    /* Read back the program mem word (MSB first) */
+    avr910_recv(pgm, buf, sizeof(buf));
+
+    if ((addr & 0x01) == 0) {
+      *value = buf[1];
+      cached = 1;
+      cvalue = buf[0];
+      caddr = addr;
+    }
+    else {
+      *value = buf[0];
+    }
+  }
+
+  return 0;
+}
+
+
+static int avr910_read_byte_eeprom(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
+                                   unsigned long addr, unsigned char * value)
+{
+  avr910_set_addr(pgm, addr);
+  avr910_send(pgm, "d", 1);
+  avr910_recv(pgm, value, 1);
+
+  return 0;
+}
+
+
+static int avr910_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
+                            unsigned long addr, unsigned char * value)
+{
+  no_show_func_info();
+
+  if (strcmp(m->desc, "flash") == 0) {
+    return avr910_read_byte_flash(pgm, p, m, addr, value);
+  }
+
+  if (strcmp(m->desc, "eeprom") == 0) {
+    return avr910_read_byte_eeprom(pgm, p, m, addr, value);
+  }
+
+  return -1;
+}
+
 /* Signature byte reads are always 3 bytes. */
 
 static int avr910_read_sig_bytes(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m)
@@ -406,5 +533,8 @@ void avr910_initpgm(PROGRAMMER * pgm)
    * optional functions
    */
 
+  pgm->write_setup = avr910_write_setup;
+  pgm->write_byte = avr910_write_byte;
+  pgm->read_byte = avr910_read_byte;
   pgm->read_sig_bytes = avr910_read_sig_bytes;
 }
diff --git a/avrdude/pgm.c b/avrdude/pgm.c
index 64bf561d..68363046 100644
--- a/avrdude/pgm.c
+++ b/avrdude/pgm.c
@@ -89,6 +89,7 @@ PROGRAMMER * pgm_new(void)
    */
   pgm->paged_write    = NULL;
   pgm->paged_load     = NULL;
+  pgm->write_setup    = NULL;
   pgm->write_byte     = NULL;
   pgm->read_byte      = NULL;
   pgm->read_sig_bytes = NULL;
diff --git a/avrdude/pgm.h b/avrdude/pgm.h
index e8fe6a32..2c12480f 100644
--- a/avrdude/pgm.h
+++ b/avrdude/pgm.h
@@ -66,6 +66,7 @@ typedef struct programmer_t {
                           int page_size, int n_bytes);
   int  (*paged_load)     (struct programmer_t * pgm, AVRPART * p, AVRMEM * m,
                           int page_size, int n_bytes);
+  void (*write_setup)    (struct programmer_t * pgm, AVRPART * p, AVRMEM * m);
   int  (*write_byte)     (struct programmer_t * pgm, AVRPART * p, AVRMEM * m,
                           unsigned long addr, unsigned char value);
   int  (*read_byte)      (struct programmer_t * pgm, AVRPART * p, AVRMEM * m,
diff --git a/avrdude/ser_posix.c b/avrdude/ser_posix.c
index 2bff1973..713c6e91 100644
--- a/avrdude/ser_posix.c
+++ b/avrdude/ser_posix.c
@@ -168,14 +168,14 @@ int serial_send(int fd, char * buf, size_t buflen)
       fprintf(stderr, "%s: Send: ", progname);
 
       while (buflen) {
-        char c = *buf;
+        unsigned char c = *buf;
         if (isprint(c)) {
           fprintf(stderr, "%c ", c);
         }
         else {
           fprintf(stderr, ". ");
         }
-        fprintf(stderr, "[%02x] ", ((unsigned int)c) & 0xff);
+        fprintf(stderr, "[%02x] ", c);
 
         buf++;
         buflen--;
@@ -277,14 +277,14 @@ int serial_recv(int fd, char * buf, size_t buflen)
       fprintf(stderr, "%s: Recv: ", progname);
 
       while (len) {
-        char c = *p;
+        unsigned char c = *p;
         if (isprint(c)) {
           fprintf(stderr, "%c ", c);
         }
         else {
           fprintf(stderr, ". ");
         }
-        fprintf(stderr, "[%02x] ", ((unsigned int)c &0xff));
+        fprintf(stderr, "[%02x] ", c);
 
         p++;
         len--;