From 30041e3f5f4ce5f10e3679f61d30d6e01219acc5 Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Tue, 19 Jul 2022 22:59:46 +0100 Subject: [PATCH] Add compact alternative specification for SPI opcodes in avrdude.conf As the address bit numbers in the SPI opcodes are highly systematic, they don't really need to be specified. Each bit can therefore be described as one of the characters 0 (always 0), 1 (always 1), x (don't care, but will be set as 0), a (a copy of the correct bit of the byte or word address of read, write, load, pagewrite or load extended address command of memories with more than one byte), i (input bit for a load/write) or o (output bit from a read). The bits therefore do not need to be individually separated. If a string in the list of strings that describe an SPI opcode does *not* contain a space *and* is longer than 7 characters, it is interpreted as a compact bit-pattern representation. The characters 0, 1, x, a, i and o will be recognised as the corresponding bit, whilst any of the characters ., -, _ or / can act as arbitrary visual separators, which are ignored. Examples: loadpage_lo = "0100.0000--000x.xxxx--xxaa.aaaa--iiii.iiii"; loadpage_lo = "0100.0000", "000x.xxxx", "xxaa.aaaa", "iiii.iiii"; loadpage_lo = "0100.0000", "000x.xxxx.xxaa.aaaa", "iiii.iiii"; loadpage_lo = "0100.0000-000x.xxxx--xxaa.aaaa-iiii.iiii"; loadpage_lo = "0100.0000/000x.xxxx/xxaa.aaaa/iiii.iiii"; The compact format is an extension of the current format, which remains valid. Both, the compact and the traditional specification can be mixed in different strings, albeit not in the same string: load_ext_addr = "0100.1101", "0000.0000.0000", "0 0 0 a16", "0000.0000"; --- src/config_gram.y | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/src/config_gram.y b/src/config_gram.y index 7a8cb7eb..3b979c20 100644 --- a/src/config_gram.y +++ b/src/config_gram.y @@ -1653,7 +1653,6 @@ static int parse_cmdbits(OPCODE * op, int opnum) { TOKEN * t; int bitno; - char ch; char * e; char * q; int len; @@ -1665,10 +1664,18 @@ static int parse_cmdbits(OPCODE * op, int opnum) t = lrmv_n(string_list, 1); - s = strtok_r(t->value.string, " ", &brkt); + char *str = t->value.string; + // Compact alternative specification? (eg, "0100.0000--000x.xxxx--xxaa.aaaa--iiii.iiii") + char bit[2] = {0, 0}, *cc = str; + int compact = !strchr(str, ' ') && strlen(str) > 7; + + bit[0] = *cc++; + s = !compact? strtok_r(str, " ", &brkt): *bit? bit: NULL; while (rv == 0 && s != NULL) { - bitno--; + // Ignore visual grouping characters in compact mode + if(*s != '.' && *s != '-' && *s != '_' && *s !='/') + bitno--; if (bitno < 0) { yyerror("too many opcode bits for instruction"); rv = -1; @@ -1683,10 +1690,8 @@ static int parse_cmdbits(OPCODE * op, int opnum) break; } - ch = s[0]; - if (len == 1) { - switch (ch) { + switch (*s) { case '1': op->bit[bitno].type = AVR_CMDBIT_VALUE; op->bit[bitno].value = 1; @@ -1720,14 +1725,19 @@ static int parse_cmdbits(OPCODE * op, int opnum) op->bit[bitno].value = 0; op->bit[bitno].bitno = bitno % 8; break; + case '.': + case '-': + case '_': + case '/': + break; default : - yyerror("invalid bit specifier '%c'", ch); + yyerror("invalid bit specifier '%c'", *s); rv = -1; break; } } else { - if (ch == 'a') { + if (*s == 'a') { q = &s[1]; op->bit[bitno].bitno = strtol(q, &e, 0); if ((e == q)||(*e != 0)) { @@ -1745,7 +1755,8 @@ static int parse_cmdbits(OPCODE * op, int opnum) } } - s = strtok_r(NULL, " ", &brkt); + bit[0] = *cc++; + s = !compact? strtok_r(NULL, " ", &brkt): *bit? bit: NULL; } /* while */ free_token(t);