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";
This commit is contained in:
Stefan Rueger 2022-07-19 22:59:46 +01:00
parent db37c9d286
commit 30041e3f5f
1 changed files with 20 additions and 9 deletions

View File

@ -1653,7 +1653,6 @@ static int parse_cmdbits(OPCODE * op, int opnum)
{ {
TOKEN * t; TOKEN * t;
int bitno; int bitno;
char ch;
char * e; char * e;
char * q; char * q;
int len; int len;
@ -1665,9 +1664,17 @@ static int parse_cmdbits(OPCODE * op, int opnum)
t = lrmv_n(string_list, 1); 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) { while (rv == 0 && s != NULL) {
// Ignore visual grouping characters in compact mode
if(*s != '.' && *s != '-' && *s != '_' && *s !='/')
bitno--; bitno--;
if (bitno < 0) { if (bitno < 0) {
yyerror("too many opcode bits for instruction"); yyerror("too many opcode bits for instruction");
@ -1683,10 +1690,8 @@ static int parse_cmdbits(OPCODE * op, int opnum)
break; break;
} }
ch = s[0];
if (len == 1) { if (len == 1) {
switch (ch) { switch (*s) {
case '1': case '1':
op->bit[bitno].type = AVR_CMDBIT_VALUE; op->bit[bitno].type = AVR_CMDBIT_VALUE;
op->bit[bitno].value = 1; 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].value = 0;
op->bit[bitno].bitno = bitno % 8; op->bit[bitno].bitno = bitno % 8;
break; break;
case '.':
case '-':
case '_':
case '/':
break;
default : default :
yyerror("invalid bit specifier '%c'", ch); yyerror("invalid bit specifier '%c'", *s);
rv = -1; rv = -1;
break; break;
} }
} }
else { else {
if (ch == 'a') { if (*s == 'a') {
q = &s[1]; q = &s[1];
op->bit[bitno].bitno = strtol(q, &e, 0); op->bit[bitno].bitno = strtol(q, &e, 0);
if ((e == 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 */ } /* while */
free_token(t); free_token(t);