From 3823e9c4053da84517037f5f1242cd9a1ef5f57b Mon Sep 17 00:00:00 2001
From: Rene Liebscher <r.liebscher@gmx.de>
Date: Tue, 13 Nov 2012 21:34:02 +0000
Subject: [PATCH] bug #35186 inverting pins with "~" doesn't work for pin lists
 (i.e. vcc) bug #37727 Add support for LM3S811 dev board as a programmer *
 lexer.l,config_gram.y: accepting inverted pins at pin lists 	       
 syntax: ~num or ~(num,num,...) * par.c: par_set_many_bits is now usable with
 inverted pins * avrftdi.c: fixed wrong index in ftdi_pin_name *
 avrdude.conf.in: added programmer lm3s811

git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@1106 81a1dc3b-b13d-400b-aceb-764788c761c2
---
 ChangeLog       | 10 ++++++++++
 avrdude.conf.in | 27 ++++++++++++++++++++++++++-
 avrftdi.c       |  7 ++++++-
 config_gram.y   | 45 ++++++++++++++++++++++++++++-----------------
 lexer.l         |  2 ++
 par.c           |  7 +++++--
 6 files changed, 77 insertions(+), 21 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 75e24259..eeb7419d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2012-11-13  Rene Liebscher <R.Liebscher@gmx.de>
+
+	bug #35186 inverting pins with "~" doesn't work for pin lists (i.e. vcc)
+	bug #37727 Add support for LM3S811 dev board as a programmer
+	* lexer.l,config_gram.y: accepting inverted pins at pin lists 
+	        syntax: ~num or ~(num,num,...)
+	* par.c: par_set_many_bits is now usable with inverted pins
+	* avrftdi.c: fixed wrong index in ftdi_pin_name
+	* avrdude.conf.in: added programmer lm3s811
+
 2012-11-04  Rene Liebscher <R.Liebscher@gmx.de>
 
 	* lexer.l,config_gram.y,config.[hc]: changed reading of numbers to integers
diff --git a/avrdude.conf.in b/avrdude.conf.in
index 4335b63e..4aee6bfa 100644
--- a/avrdude.conf.in
+++ b/avrdude.conf.in
@@ -38,6 +38,9 @@
 #       usbsn    = <serialno>;                      # USB Serial Number
 #
 #        To invert a bit, use = ~ <num>, the spaces are important.
+#        For a pin list all pins must be inverted.
+#        A single pin can be specified as usual = ~ <num>, for lists
+#        specify it as follows = ~ ( <num> [, <num2> ... ] ) .
 #     ;
 #
 #   part
@@ -473,6 +476,28 @@ programmer parent "jtagkey"
   usbproduct = "USB<=>JTAG&RS232";
 ;
 
+# Only Rev. A boards.
+# Schematic and user manual: http://www.cs.put.poznan.pl/wswitala/download/pdf/811EVBK.pdf
+programmer
+  id         = "lm3s811";
+  desc       = "Luminary Micro LM3S811 Eval Board (Rev. A)";
+  type       = "avrftdi";
+  connection_type = usb;
+  usbvid     = 0x0403;
+  usbpid     = 0xbcd9;
+  usbvendor  = "LMI";
+  usbproduct = "LM3S811 Evaluation Board";
+  usbdev     = "A";
+  usbsn      = "";
+#ISP-signals - lower ACBUS-Nibble (default)
+  reset  = 4;
+  sck    = 1;
+  mosi   = 2;
+  miso   = 3;
+# Enable correct buffers
+  buff   = ~8;
+;
+
 programmer
   id    = "avrisp";
   desc  = "Atmel AVR ISP";
@@ -1065,7 +1090,7 @@ programmer
 ;
 
 # It is almost same as pony-stk200, except vcc on pin 5 to auto
-# disconnect port (download on http://electropol.free.fr)
+# disconnect port (download on http://electropol.free.fr/spip/spip.php?article27)
 programmer parent "pony-stk200"
   id    = "frank-stk200";
   desc  = "Frank STK200";
diff --git a/avrftdi.c b/avrftdi.c
index 7546ed85..698d32a2 100644
--- a/avrftdi.c
+++ b/avrftdi.c
@@ -129,7 +129,7 @@ ftdi_pin_name(avrftdi_t* pdata, int pin)
 	/* This is FTDI's naming scheme.
 	 * probably 'D' is for data and 'C' for control
 	 */
-	if(pin < 8)
+	if(pin <= 8)
 		port = 'D';
 	else
 		port = 'C';
@@ -517,6 +517,11 @@ static int set_led_vfy(struct programmer_t * pgm, int value)
 	return set_pin(pgm, PIN_LED_VFY, value);
 }
 
+/* Send 'buf_size' bytes from 'cmd' to device and return data from device in
+ * buffer 'data'.
+ * Write is only performed when mode contains MPSSE_DO_WRITE.
+ * Read is only performed when mode contains MPSSE_DO_READ.
+ */
 static int avrftdi_transmit(avrftdi_t* pdata, unsigned char mode, unsigned char *cmd,
 			    unsigned char *data, int buf_size)
 {
diff --git a/config_gram.y b/config_gram.y
index 8145ff83..f04bdb12 100644
--- a/config_gram.y
+++ b/config_gram.y
@@ -48,6 +48,7 @@ int yylex(void);
 int yyerror(char * errmsg);
 
 static int assign_pin(int pinno, TOKEN * v, int invert);
+static int assign_pin_list(int invert);
 static int which_opcode(TOKEN * opcode);
 static int parse_cmdbits(OPCODE * op);
 
@@ -199,6 +200,8 @@ static int pin_name;
 %token TKN_EQUAL
 %token TKN_SEMI
 %token TKN_TILDE
+%token TKN_LEFT_PAREN
+%token TKN_RIGHT_PAREN
 %token TKN_NUMBER
 %token TKN_NUMBER_REAL
 %token TKN_STRING
@@ -539,22 +542,11 @@ pin_number:
 ;
 
 pin_list:
-  num_list {
-    {
-      TOKEN * t;
-      int pin;
-
-      current_prog->pinno[pin_name] = 0;
-
-      while (lsize(number_list)) {
-        t = lrmv_n(number_list, 1);
-        pin = t->value.number;
-        current_prog->pinno[pin_name] |= (1 << pin);
-
-        free_token(t);
-      }
-    }
-  }
+  num_list            { assign_pin_list(0); }
+  |
+  TKN_TILDE TKN_NUMBER { assign_pin(pin_name, $2, 1); }
+  |
+  TKN_TILDE TKN_LEFT_PAREN num_list TKN_RIGHT_PAREN { assign_pin_list(1); }
   |
   /* empty */ {
     current_prog->pinno[pin_name] = 0;
@@ -1331,7 +1323,8 @@ mem_spec :
 static char * vtypestr(int type)
 {
   switch (type) {
-    case V_NUM : return "NUMERIC";
+    case V_NUM : return "INTEGER";
+    case V_NUM_REAL: return "REAL";
     case V_STR : return "STRING";
     default:
       return "<UNKNOWN>";
@@ -1362,6 +1355,24 @@ static int assign_pin(int pinno, TOKEN * v, int invert)
   return 0;
 }
 
+static int assign_pin_list(int invert)
+{
+  TOKEN * t;
+  int pin;
+
+  current_prog->pinno[pin_name] = 0;
+  while (lsize(number_list)) {
+    t = lrmv_n(number_list, 1);
+    pin = t->value.number;
+    current_prog->pinno[pin_name] |= (1 << pin);
+    if (invert)
+      current_prog->pinno[pin_name] |= PIN_INVERSE;
+    free_token(t);
+  }
+
+  return 0;
+}
+
 static int which_opcode(TOKEN * opcode)
 {
   switch (opcode->primary) {
diff --git a/lexer.l b/lexer.l
index 06440969..6846759c 100644
--- a/lexer.l
+++ b/lexer.l
@@ -248,6 +248,8 @@ yes              { yylval=new_token(K_YES); return K_YES; }
 "="       { yylval = NULL; pyytext(); return TKN_EQUAL; }
 ";"       { yylval = NULL; pyytext(); return TKN_SEMI; }
 "~"       { yylval = NULL; pyytext(); return TKN_TILDE; }
+"("       { yylval = NULL; pyytext(); return TKN_LEFT_PAREN; }
+")"       { yylval = NULL; pyytext(); return TKN_RIGHT_PAREN; }
 
 "\n"      { lineno++; }
 [ \r\t]+  { /* ignore whitespace */ }
diff --git a/par.c b/par.c
index 64095f9d..dea790c1 100644
--- a/par.c
+++ b/par.c
@@ -106,11 +106,14 @@ static int par_setpin(PROGRAMMER * pgm, int pin, int value)
 
 static void par_setmany(PROGRAMMER * pgm, unsigned int pinset, int value)
 {
-  int pin;
+  int pin, mask;
+
+  /* mask is anything non-pin - needs to be applied to each par_setpin to preserve inversion */
+  mask = pinset & (~PIN_MASK);
 
   for (pin = 1; pin <= 17; pin++) {
     if (pinset & (1 << pin))
-      par_setpin(pgm, pin, value);
+      par_setpin(pgm, pin | mask, value);
   }
 }