From f177b994be61142be9e6284c2eeed40bb763064c Mon Sep 17 00:00:00 2001
From: Rene Liebscher <r.liebscher@gmx.de>
Date: Wed, 30 Jan 2013 17:58:48 +0000
Subject: [PATCH] =?UTF-8?q?patch=20#7723=20Bus=20Pirate=20=E2=80=9Craw-wir?=
 =?UTF-8?q?e=E2=80=9D=20mode=20which=20can=20run=20down=20to=205=20kHz=20?=
 =?UTF-8?q?=09*=20buspirate.c:=20added=20raw=20wire=20mode=20=09*=20avrdud?=
 =?UTF-8?q?e.1:=20added=20doc=20for=20rawfreq=20parameter=20=09*=20doc/avr?=
 =?UTF-8?q?dude.texi:=20added=20doc=20for=20rawfreq=20parameter?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk@1136 81a1dc3b-b13d-400b-aceb-764788c761c2
---
 avrdude/ChangeLog        |  7 ++++
 avrdude/avrdude.1        | 20 +++++++--
 avrdude/buspirate.c      | 91 ++++++++++++++++++++++++++++------------
 avrdude/doc/avrdude.texi | 21 ++++++++--
 4 files changed, 106 insertions(+), 33 deletions(-)

diff --git a/avrdude/ChangeLog b/avrdude/ChangeLog
index e014fb63..13ff069a 100644
--- a/avrdude/ChangeLog
+++ b/avrdude/ChangeLog
@@ -1,3 +1,10 @@
+2013-01-30  Rene Liebscher <R.Liebscher@gmx.de>
+
+	patch #7723 Bus Pirate “raw-wire” mode which can run down to 5 kHz
+	* buspirate.c: added raw wire mode
+	* avrdude.1: added doc for rawfreq parameter
+	* doc/avrdude.texi: added doc for rawfreq parameter
+
 2013-01-30  Rene Liebscher <R.Liebscher@gmx.de>
 
 	bug #37977 Support for Openmoko Debug Board
diff --git a/avrdude/avrdude.1 b/avrdude/avrdude.1
index 8fe1ae5f..a8789a93 100644
--- a/avrdude/avrdude.1
+++ b/avrdude/avrdude.1
@@ -907,7 +907,7 @@ good candidates with the latches driven by the appropriate reset pin (cs,
 aux or aux2). Otherwise the SPI traffic in one active circuit may interfere
 with programming the AVR in the other design.
 .It Ar spifreq=<0..7>
-BusPirate to AVR SPI speed:
+The SPI speed for the Bus Pirate's binary SPI mode:
 .Bd -literal
 0 ..  30 kHz   (default)
 1 .. 125 kHz
@@ -918,14 +918,26 @@ BusPirate to AVR SPI speed:
 6 ..   4 MHz
 7 ..   8 MHz
 .Ed
+.It Ar rawfreq=<0..3>
+Sets the SPI speed and uses the Bus Pirate's binary "raw-wire" mode:
+.Bd -literal
+0 ..   5 kHz
+1 ..  50 kHz
+2 .. 100 kHz   (Firmware v4.2+ only)
+3 .. 400 kHz   (v4.2+)
+.Ed
+.Pp
+The only advantage of the "raw-wire" mode is the different SPI frequencies
+available. Paged writing is not implemented in this mode.
 .It Ar ascii
-Attempt to ASCII mode even when the firmware supports BinMode (binary mode). 
+Attempt to use ASCII mode even when the firmware supports BinMode (binary
+mode). 
 BinMode is supported in firmware 2.7 and newer, older FW's either don't
 have BinMode or their BinMode is buggy. ASCII mode is slower and makes 
 the above
-.Ar reset=
+.Ar reset= , spifreq=
 and 
-.Ar spifreq=
+.Ar rawfreq=
 parameters unavailable. Be aware that ASCII mode is not guaranteed to work
 with newer firmware versions, and is retained only to maintain compatability
 with older firmware versions.
diff --git a/avrdude/buspirate.c b/avrdude/buspirate.c
index b5d98381..b1515c2c 100644
--- a/avrdude/buspirate.c
+++ b/avrdude/buspirate.c
@@ -64,15 +64,14 @@
 #define BP_FLAG_XPARM_SPIFREQ       (1<<3)
 #define BP_FLAG_NOPAGEDWRITE        (1<<4)
 #define BP_FLAG_XPARM_CPUFREQ       (1<<5)
+#define BP_FLAG_XPARM_RAWFREQ       (1<<6)
 
 struct pdata
 {
-	char	hw_version[10];
-	int	fw_version;		/* = 100*fw_major + fw_minor */
 	int	binmode_version;
-	int	bin_spi_version;
+	int	submode_version;
 	int	current_peripherals_config;
-	int	spifreq;		/* 0..7 - see buspirate manual for what freq each value means */
+	int	spifreq;		/* For "set speed" commands */
 	int	cpufreq;		/* (125)..4000 kHz - see buspirate manual */
 	int	serial_recv_timeout; /* timeout in ms, default 100 */
 	int	reset;			/* See BP_RESET_* above */
@@ -305,8 +304,22 @@ buspirate_parseextparms(struct programmer_t *pgm, LISTID extparms)
 				fprintf(stderr, "BusPirate: see BusPirate manual for details.\n");
 				return -1;
 			}
+			pgm->flag = (pgm->flag & ~BP_FLAG_XPARM_RAWFREQ) |
+				BP_FLAG_XPARM_SPIFREQ;
 			PDATA(pgm)->spifreq = spifreq;
-			pgm->flag |= BP_FLAG_XPARM_SPIFREQ;
+			continue;
+		}
+		
+		unsigned rawfreq;
+		if (sscanf(extended_param, "rawfreq=%u", &rawfreq) == 1) {
+			if (rawfreq >= 4) {
+				fprintf(stderr, "BusPirate: rawfreq must be "
+					"between 0 and 3.\n");
+				return -1;
+			}
+			pgm->flag = (pgm->flag & ~BP_FLAG_XPARM_SPIFREQ) |
+				BP_FLAG_XPARM_RAWFREQ;
+			PDATA(pgm)->spifreq = rawfreq;
 			continue;
 		}
 
@@ -371,7 +384,8 @@ buspirate_verifyconfig(struct programmer_t *pgm)
 		return -1;
 	}
 
-	if ((pgm->flag & BP_FLAG_XPARM_SPIFREQ) && buspirate_uses_ascii(pgm)) {
+	if (( (pgm->flag & BP_FLAG_XPARM_SPIFREQ) ||
+	(pgm->flag & BP_FLAG_XPARM_RAWFREQ) ) && buspirate_uses_ascii(pgm)) {
 		fprintf(stderr, "BusPirate: SPI speed selection is not supported in ASCII mode\n");
 		return -1;
 	}
@@ -442,8 +456,37 @@ static void buspirate_reset_from_binmode(struct programmer_t *pgm)
 		fprintf(stderr, "BusPirate is back in the text mode\n");
 }
 
-static int buspirate_start_spi_mode_bin(struct programmer_t *pgm)
+static int buspirate_start_mode_bin(struct programmer_t *pgm)
 {
+	const struct submode {
+		const char *name;  /* Name of mode for user messages */
+		char enter;  /* Command to enter from base binary mode */
+		const char *entered_format;  /* Response, for "scanf" */
+		char config;  /* Command to setup submode parameters */
+	} *submode;
+	if (pgm->flag & BP_FLAG_XPARM_RAWFREQ) {
+		submode = &(const struct submode){
+			.name = "Raw-wire",
+			.enter = 0x05,
+			.entered_format = "RAW%d",
+			.config = 0x8C,
+		};
+		pgm->flag |= BP_FLAG_NOPAGEDWRITE;
+	} else {
+		submode = &(const struct submode){
+			.name = "SPI",
+			.enter = 0x01,
+			.entered_format = "SPI%d",
+			
+			/* 1000wxyz - SPI config, w=HiZ(0)/3.3v(1), x=CLK idle, y=CLK edge, z=SMP sample
+			 * we want: 3.3V(1), idle low(0), data change on
+			 *          trailing edge (1), sample in the middle
+			 *          of the pulse (0)
+			 *       => 0b10001010 = 0x8a */
+			.config = 0x8A,
+		};
+	}
+	
 	char buf[20] = { '\0' };
 
 	/* == Switch to binmode - send 20x '\0' == */
@@ -463,19 +506,21 @@ static int buspirate_start_spi_mode_bin(struct programmer_t *pgm)
 
 	pgm->flag |= BP_FLAG_IN_BINMODE;
 
-	/* == Enter SPI mode == */
-	buf[0] = 0x01;	/* Enter raw SPI mode */
+	/* == Set protocol sub-mode of binary mode == */
+	buf[0] = submode->enter;
 	buspirate_send_bin(pgm, buf, 1);
 	memset(buf, 0, sizeof(buf));
 	buspirate_recv_bin(pgm, buf, 4);
-	if (sscanf(buf, "SPI%d", &PDATA(pgm)->bin_spi_version) != 1) {
-		fprintf(stderr, "SPI mode not confirmed: '%s'\n", buf);
+	if (sscanf(buf, submode->entered_format,
+	&PDATA(pgm)->submode_version) != 1) {
+		fprintf(stderr, "%s mode not confirmed: '%s'\n",
+			submode->name, buf);
 		buspirate_reset_from_binmode(pgm);
 		return -1;
 	}
 	if (verbose)
-		fprintf(stderr, "BusPirate SPI version: %d\n",
-			PDATA(pgm)->bin_spi_version);
+		fprintf(stderr, "BusPirate %s version: %d\n",
+			submode->name, PDATA(pgm)->submode_version);
 
 	if (pgm->flag & BP_FLAG_NOPAGEDWRITE) {
 		if (verbose)
@@ -511,17 +556,11 @@ static int buspirate_start_spi_mode_bin(struct programmer_t *pgm)
 	buspirate_expect_bin_byte(pgm, PDATA(pgm)->current_peripherals_config, 0x01);
 	usleep(50000);	// sleep for 50ms after power up
 
-	/* 01100xxx -  SPI speed
-	 * xxx = 000=30kHz, 001=125kHz, 010=250kHz, 011=1MHz,
-	 *       100=2MHz, 101=2.6MHz, 110=4MHz, 111=8MHz
-	 * use 30kHz = 0x60 */
+	/* 01100xxx -  Set speed */
 	buspirate_expect_bin_byte(pgm, 0x60 | PDATA(pgm)->spifreq, 0x01);
 
-	/* 1000wxyz - SPI config, w=HiZ(0)/3.3v(1), x=CLK idle, y=CLK edge, z=SMP sample
-	 * we want: 3.3V(1), idle low(0), data change on trailing edge (1),
-	 *          sample in the middle of the pulse (0)
-	 *       => 0b10001010 = 0x8a */
-	buspirate_expect_bin_byte(pgm, 0x8A, 0x01);
+	/* Submode config */
+	buspirate_expect_bin_byte(pgm, submode->config, 0x01);
 
 	return 0;
 }
@@ -600,10 +639,10 @@ static void buspirate_enable(struct programmer_t *pgm)
 		serial_drain(&pgm->fd, 0);
 
 		/* Attempt to enter binary mode: */
-		if (buspirate_start_spi_mode_bin(pgm) >= 0)
+		if (buspirate_start_mode_bin(pgm) >= 0)
 			return;
 		else
-			fprintf(stderr, "%s: Failed to start binary SPI mode, falling back to ASCII...\n", progname);
+			fprintf(stderr, "%s: Failed to start binary mode, falling back to ASCII...\n", progname);
 	}
 
 	fprintf(stderr, "Attempting to initiate BusPirate ASCII mode...\n");
@@ -665,7 +704,7 @@ static int buspirate_initialize(struct programmer_t *pgm, AVRPART * p)
 static void buspirate_powerup(struct programmer_t *pgm)
 {
 	if (pgm->flag & BP_FLAG_IN_BINMODE) {
-		/* Powerup in BinMode is handled in SPI init */
+		/* Powerup in BinMode is handled in binary mode init */
 		return;
 	} else {
 		if (buspirate_expect(pgm, "W\n", "Power supplies ON", 1)) {
@@ -716,7 +755,7 @@ static int buspirate_cmd_bin(struct programmer_t *pgm,
 				unsigned char cmd[4],
 				unsigned char res[4])
 {
-	/* 0001xxxx - Bulk SPI transfer, send/read 1-16 bytes (0=1byte!)
+	/* 0001xxxx - Bulk transfer, send/read 1-16 bytes (0=1byte!)
 	 * we are sending 4 bytes -> 0x13 */
 	if (!buspirate_expect_bin_byte(pgm, 0x13, 0x01))
 		return -1;
diff --git a/avrdude/doc/avrdude.texi b/avrdude/doc/avrdude.texi
index e28c50ae..fe2a90fe 100644
--- a/avrdude/doc/avrdude.texi
+++ b/avrdude/doc/avrdude.texi
@@ -805,14 +805,29 @@ with programming the AVR in the other design.
 @item @code{7} @tab   8 MHz
 @end multitable
 
+@item @samp{rawfreq=0..3}
+Sets the SPI speed and uses the Bus Pirate's binary ``raw-wire'' mode instead
+of the default binary SPI mode:
+
+@multitable @columnfractions .05 .3
+@item @code{0} @tab 5 kHz
+@item @code{1} @tab 50 kHz
+@item @code{2} @tab 100 kHz (Firmware v4.2+ only)
+@item @code{3} @tab 400 kHz (v4.2+)
+@end multitable
+
+The only advantage of the ``raw-wire'' mode is that different SPI frequencies
+are available. Paged writing is not implemented in this mode.
+
 @item @samp{ascii}
-Attempt to ASCII mode even when the firmware supports BinMode (binary mode).
+Attempt to use ASCII mode even when the firmware supports BinMode (binary
+mode).
 BinMode is supported in firmware 2.7 and newer, older FW's either don't
 have BinMode or their BinMode is buggy. ASCII mode is slower and makes
 the above
-@samp{reset=}
+@samp{reset=}, @samp{spifreq=}
 and
-@samp{spifreq=}
+@samp{rawfreq=}
 parameters unavailable. Be aware that ASCII mode is not guaranteed to work
 with newer firmware versions, and is retained only to maintain compatability
 with older firmware versions.