Implement -c */[sSA] (syntax-correct dump of programmer structure)

This commit is contained in:
Stefan Rueger 2022-08-08 16:52:09 +01:00
parent 075dee1dd3
commit 49fcd8a96e
No known key found for this signature in database
GPG Key ID: B0B4F1FD86B1EC55
12 changed files with 281 additions and 95 deletions

View File

@ -672,7 +672,7 @@ void avr_mem_display(const char * prefix, FILE * f, AVRMEM * m, AVRPART * p,
AVRPART * avr_new_part(void)
{
AVRPART * p;
char *nulp = cache_string("");
const char *nulp = cache_string("");
p = (AVRPART *)malloc(sizeof(AVRPART));
if (p == NULL) {

View File

@ -366,7 +366,7 @@ int read_config(const char * file)
// Linear-search cache for a few often-referenced strings
char *cache_string(const char *file) {
const char *cache_string(const char *file) {
static char **fnames;
static int n=0;
@ -394,3 +394,8 @@ char *cache_string(const char *file) {
return fnames[n++];
}
// Captures comments during parsing
int capture_comment_char(int c) {
return c;
}

View File

@ -101,6 +101,8 @@ void pyytext(void);
char * dup_string(const char * str);
int capture_comment_char(int c);
#ifdef __cplusplus
}
#endif

View File

@ -1397,7 +1397,8 @@ yesno :
mem_specs :
mem_spec TKN_SEMI |
mem_alias TKN_SEMI |
mem_specs mem_spec TKN_SEMI
mem_specs mem_spec TKN_SEMI |
/* empty */
;

View File

@ -613,8 +613,8 @@ void dev_output_part_defs(char *partdesc) {
if((flags = strchr(partdesc, '/')))
*flags++ = 0;
if(!flags && !strcmp(partdesc, "*")) // Treat -p * as if it was -p */*
flags = "*";
if(!flags && !strcmp(partdesc, "*")) // Treat -p * as if it was -p */s
flags = "s";
if(!*flags || !strchr("cdoASsrw*t", *flags)) {
dev_info("%s: flags for developer option -p <wildcard>/<flags> not recognised\n", progname);
@ -640,7 +640,7 @@ void dev_output_part_defs(char *partdesc) {
" $ avrdude -p m328*/st | grep chip_erase_delay\n"
" avrdude -p*/r | sort\n"
"Notes:\n"
" -p * is the same as -p */*\n"
" -p * is the same as -p */s\n"
" This help message is printed using any unrecognised flag, eg, -p/h\n"
" Leaving no space after -p can be an OK substitute for quoting in shells\n"
" /s, /S and /A outputs are designed to be used as input in avrdude.conf\n"
@ -935,19 +935,37 @@ static void dev_pgm_raw(PROGRAMMER *pgm) {
dp.id = NULL;
dp.parent_id = NULL;
dp.initpgm = NULL;
dp.usbpid = NULL;
dp.usbdev = NULL;
dp.usbsn = NULL;
dp.usbvendor = NULL;
dp.usbproduct = NULL;
dp.hvupdi_support = NULL;
// Only dump contents of PROGRAMMER struct up to and excluding the fd component
dev_raw_dump((char *) &dp, offsetof(PROGRAMMER, fd), id, "pgm", 0);
}
static void dev_pgm_strct(PROGRAMMER *pgm, bool tsv, PROGRAMMER *base) {
if(!tsv) {
int firstid = 1;
static const char *connstr(conntype_t conntype) {
switch(conntype) {
case CONNTYPE_PARALLEL: return "parallel";
case CONNTYPE_SERIAL: return "serial";
case CONNTYPE_USB: return "usb";
case CONNTYPE_SPI: return "spi";
default: return "<unknown>";
}
}
static void dev_pgm_strct(PROGRAMMER *pgm, bool tsv, PROGRAMMER *base) {
char *id = ldata(lfirst(pgm->id));
LNODEID ln;
int firstid;
if(!tsv) {
dev_info("#------------------------------------------------------------\n");
dev_info("# ");
for(LNODEID ln=lfirst(pgm->id); ln; ln=lnext(ln)) {
for(firstid=1, ln=lfirst(pgm->id); ln; ln=lnext(ln)) {
if(!firstid)
dev_info("/");
firstid = 0;
@ -961,6 +979,67 @@ static void dev_pgm_strct(PROGRAMMER *pgm, bool tsv, PROGRAMMER *base) {
dev_info("\nprogrammer\n");
}
if(tsv)
dev_info(".prog\t%s\tid\t", id);
else
dev_info(" %-19s = ", "id");
for(firstid=1, ln=lfirst(pgm->id); ln; ln=lnext(ln)) {
if(!firstid)
dev_info(", ");
firstid = 0;
dev_info("\"%s\"", ldata(ln));
}
dev_info(tsv? "\n": ";\n");
_if_pgmout(strcmp, "\"%s\"", desc);
_pgmout_fmt("type", "\"%s\"", locate_programmer_type_id(pgm->initpgm));
_pgmout_fmt("connection_type", "%s", connstr(pgm->conntype));
_if_pgmout(intcmp, "%d", baudrate);
_if_pgmout(intcmp, "0x%04x", usbvid);
if(pgm->usbpid && lfirst(pgm->usbpid)) {
if(tsv)
dev_info(".prog\t%s\tusbpid\t", id);
else
dev_info(" %-19s = ", "usbpid");
for(firstid=1, ln=lfirst(pgm->usbpid); ln; ln=lnext(ln)) {
if(!firstid)
dev_info(", ");
firstid = 0;
dev_info("0x%04x", *(unsigned int *) ldata(ln));
}
dev_info(tsv? "\n": ";\n");
}
_if_pgmout(strcmp, "\"%s\"", usbdev);
_if_pgmout(strcmp, "\"%s\"", usbsn);
_if_pgmout(strcmp, "\"%s\"", usbvendor);
_if_pgmout(strcmp, "\"%s\"", usbproduct);
for(int i=0; i<N_PINS; i++) {
char *str = pins_to_strdup(pgm->pin+i);
if(str && *str)
_pgmout_fmt(avr_pin_lcname(i), "%s", str);
if(str)
free(str);
}
if(pgm->hvupdi_support && lfirst(pgm->hvupdi_support)) {
if(tsv)
dev_info(".prog\t%s\thvupdu_support\t", id);
else
dev_info(" %-19s = ", "hvupdi_support");
for(firstid=1, ln=lfirst(pgm->hvupdi_support); ln; ln=lnext(ln)) {
if(!firstid)
dev_info(", ");
firstid = 0;
dev_info("%d", *(unsigned int *) ldata(ln));
}
dev_info(tsv? "\n": ";\n");
}
if(!tsv)
dev_info(";\n");
}

View File

@ -51,6 +51,22 @@ static int dev_message(int msglvl, const char *fmt, ...);
#define dev_notice(...) dev_message(DEV_NOTICE, __VA_ARGS__)
#define dev_notice2(...) dev_message(DEV_NOTICE2, __VA_ARGS__)
#define _pgmout(fmt, component) \
dev_part_strct_entry(tsv, ".prog", id, NULL, #component, dev_sprintf(fmt, pgm->component))
#define _pgmout_fmt(name, fmt, what) \
dev_part_strct_entry(tsv, ".prog", id, NULL, name, dev_sprintf(fmt, what))
#define _if_pgmout(cmp, fmt, component) do { \
if(!base || cmp(base->component, pgm->component)) \
dev_part_strct_entry(tsv, ".prog", id, NULL, #component, dev_sprintf(fmt, pgm->component)); \
} while(0)
#define _if_pgmout_str(cmp, result, component) do { \
if(!base || cmp(base->component, pgm->component)) \
dev_part_strct_entry(tsv, ".prog", id, NULL, #component, result); \
} while(0)
#define _partout(fmt, component) \
dev_part_strct_entry(tsv, ".pt", p->desc, NULL, #component, dev_sprintf(fmt, p->component))

View File

@ -67,13 +67,20 @@ SIGN [+-]
# { /* The following eats '#' style comments to end of line */
# { /* The following captures all '#' style comments to end of line */
BEGIN(comment); }
<comment>[^\n] { /* eat comments */ }
<comment>\n { cfg_lineno++; BEGIN(INITIAL); }
<comment>[^\n]*\n+ { /* eat comments */
capture_comment_char('#');
for(int i=0; yytext[i]; i++) {
capture_comment_char(yytext[i]);
if(yytext[i] == '\n')
cfg_lineno++;
}
BEGIN(INITIAL);
}
"/*" { /* The following eats multiline C style comments */
"/*" { /* The following eats multiline C style comments, they are not captured */
int c;
int comment_start;

View File

@ -516,7 +516,15 @@ int pins_check(const struct programmer_t * const pgm, const struct pin_checklist
const char * avr_pin_name(int pinname);
/**
* This function returns a string representation of defined pins eg. ~1,2,~4,~5,7
* Returns the name of the pin as lowercase string.
*
* @param pinname the pinname which we want as string.
* @returns a lowercase string with the pinname, or <unknown> if pinname is invalid.
*/
const char * avr_pin_lcname(int pinname);
/**
* This function returns a string of defined pins, eg, ~1,2,~4,~5,7 or " (not used)"
* Another execution of this function will overwrite the previous result in the static buffer.
*
* @param[in] pindef the pin definition for which we want the string representation
@ -525,9 +533,17 @@ const char * avr_pin_name(int pinname);
const char * pins_to_str(const struct pindef_t * const pindef);
/**
* This function returns a string representation of pins in the mask eg. 1,3,5-7,9,12
* This function returns a string of defined pins, eg, ~1, 2, ~4, ~5, 7 or ""
*
* @param[in] pindef the pin definition for which we want the string representation
* @returns a pointer to a string, which was created by strdup (NULL if out of memory)
*/
char *pins_to_strdup(const struct pindef_t * const pindef);
/**
* This function returns a string representation of pins in the mask, eg, 1,3,5-7,9,12
* Another execution of this function will overwrite the previous result in the static buffer.
* Consecutive pin number are representated as start-end.
* Consecutive pin number are represented as start-end.
*
* @param[in] pinmask the pin mask for which we want the string representation
* @returns pointer to a static string.
@ -670,29 +686,32 @@ typedef enum {
typedef struct programmer_t {
LISTID id;
char desc[PGM_DESCLEN];
char type[PGM_TYPELEN];
char port[PGM_PORTLEN];
const char *parent_id;
unsigned int pinno[N_PINS];
void (*initpgm)(struct programmer_t *pgm);
const char *parent_id; // Used by developer options -c*/[sr...]
struct pindef_t pin[N_PINS];
exit_vcc_t exit_vcc;
exit_reset_t exit_reset;
exit_datahigh_t exit_datahigh;
conntype_t conntype;
int ppidata;
int ppictrl;
int baudrate;
int usbvid;
LISTID usbpid;
LISTID hvupdi_support; // List of UPDI HV variants the tool supports, see HV_UPDI_VARIANT_x
const char *usbdev, *usbsn, *usbvendor, *usbproduct;
double bitclock; // JTAG ICE clock period in microseconds
int ispdelay; // ISP clock delay
int page_size; // Page size if the programmer supports paged write/load
const char *usbdev;
const char *usbsn;
const char *usbvendor;
const char *usbproduct;
LISTID hvupdi_support; // List of UPDI HV variants the tool supports, see HV_UPDI_VARIANT_x
// Values below are not set by config_gram.y; first one must be fd for dev_pgm_raw()
// Values below are not set by config_gram.y; make sure fd is first for dev_pgm_raw()
union filedescriptor fd;
void (*initpgm)(struct programmer_t * pgm);
char type[PGM_TYPELEN];
char port[PGM_PORTLEN];
unsigned int pinno[N_PINS]; // TODO to be removed if old pin data no longer needed
exit_vcc_t exit_vcc; // Should these be set in avrdude.conf?
exit_reset_t exit_reset;
exit_datahigh_t exit_datahigh;
int ppidata;
int ppictrl;
int ispdelay; // ISP clock delay
int page_size; // Page size if the programmer supports paged write/load
double bitclock; // JTAG ICE clock period in microseconds
int (*rdy_led) (struct programmer_t * pgm, int value);
int (*err_led) (struct programmer_t * pgm, int value);
@ -957,7 +976,9 @@ typedef struct programmer_type_t {
extern "C" {
#endif
const PROGRAMMER_TYPE * locate_programmer_type(/*LISTID programmer_types, */const char * id);
const PROGRAMMER_TYPE *locate_programmer_type(const char *id);
const char *locate_programmer_type_id(const void (*initpgm)(struct programmer_t *pgm));
typedef void (*walk_programmer_types_cb)(const char *id, const char *desc,
void *cookie);
@ -991,7 +1012,7 @@ void cleanup_config(void);
int read_config(const char * file);
char *cache_string(const char *file);
const char *cache_string(const char *file);
#ifdef __cplusplus
}

View File

@ -752,13 +752,21 @@ int main(int argc, char * argv [])
}
avrdude_message(MSG_NOTICE, "\n");
int dev_opts = 0;
// Developer option -c <wildcard>/[ASsrt] prints programmer description(s) and exits
if(programmer && (strcmp(programmer, "*") == 0 || strchr(programmer, '/'))) {
dev_output_pgm_defs(programmer);
dev_opts = 1;
}
// Developer option -p <wildcard>/[dASsrcow*t] prints part description(s) and exits
if(partdesc && (strcmp(partdesc, "*") == 0 || strchr(partdesc, '/'))) {
dev_output_part_defs(partdesc);
exit(1);
dev_opts = 1;
}
if(dev_opts)
exit(0);
avrdude_message(MSG_NOTICE, "\n");
if (partdesc) {
if (strcmp(partdesc, "?") == 0) {
@ -770,12 +778,6 @@ int main(int argc, char * argv [])
}
}
// Developer option -c <wildcard>/[ASsrt] prints programmer description(s) and exits
if(programmer && (strcmp(programmer, "*") == 0 || strchr(programmer, '/'))) {
dev_output_pgm_defs(programmer);
exit(1);
}
if (programmer) {
if (strcmp(programmer, "?") == 0) {
avrdude_message(MSG_INFO, "\n");

View File

@ -65,7 +65,7 @@ PROGRAMMER * pgm_new(void)
{
int i;
PROGRAMMER * pgm;
char *nulp = cache_string("");
const char *nulp = cache_string("");
pgm = (PROGRAMMER *)malloc(sizeof(*pgm));
if (pgm == NULL) {

View File

@ -57,55 +57,55 @@
#include "xbee.h"
const PROGRAMMER_TYPE programmers_types[] = {
{"arduino", arduino_initpgm, arduino_desc},
{"avr910", avr910_initpgm, avr910_desc},
{"avrftdi", avrftdi_initpgm, avrftdi_desc},
{"buspirate", buspirate_initpgm, buspirate_desc},
{"buspirate_bb", buspirate_bb_initpgm, buspirate_bb_desc},
{"butterfly", butterfly_initpgm, butterfly_desc},
{"butterfly_mk", butterfly_mk_initpgm, butterfly_mk_desc},
{"dragon_dw", jtagmkII_dragon_dw_initpgm, jtagmkII_dragon_dw_desc},
{"dragon_hvsp", stk500v2_dragon_hvsp_initpgm, stk500v2_dragon_hvsp_desc},
{"dragon_isp", stk500v2_dragon_isp_initpgm, stk500v2_dragon_isp_desc},
{"dragon_jtag", jtagmkII_dragon_initpgm, jtagmkII_dragon_desc},
{"dragon_pdi", jtagmkII_dragon_pdi_initpgm, jtagmkII_dragon_pdi_desc},
{"dragon_pp", stk500v2_dragon_pp_initpgm, stk500v2_dragon_pp_desc},
{"flip1", flip1_initpgm, flip1_desc},
{"flip2", flip2_initpgm, flip2_desc},
{"ftdi_syncbb", ft245r_initpgm, ft245r_desc},
{"jtagmki", jtagmkI_initpgm, jtagmkI_desc},
{"jtagmkii", jtagmkII_initpgm, jtagmkII_desc},
{"jtagmkii_avr32", jtagmkII_avr32_initpgm, jtagmkII_avr32_desc},
{"jtagmkii_dw", jtagmkII_dw_initpgm, jtagmkII_dw_desc},
{"jtagmkii_isp", stk500v2_jtagmkII_initpgm, stk500v2_jtagmkII_desc},
{"jtagmkii_pdi", jtagmkII_pdi_initpgm, jtagmkII_pdi_desc},
{"jtagmkii_updi", jtagmkII_updi_initpgm, jtagmkII_updi_desc},
{"jtagice3", jtag3_initpgm, jtag3_desc},
{"jtagice3_pdi", jtag3_pdi_initpgm, jtag3_pdi_desc},
{"jtagice3_updi", jtag3_updi_initpgm, jtag3_updi_desc},
{"jtagice3_dw", jtag3_dw_initpgm, jtag3_dw_desc},
{"jtagice3_isp", stk500v2_jtag3_initpgm, stk500v2_jtag3_desc},
{"linuxgpio", linuxgpio_initpgm, linuxgpio_desc},
{"linuxspi", linuxspi_initpgm, linuxspi_desc},
{"micronucleus", micronucleus_initpgm, micronucleus_desc},
{"par", par_initpgm, par_desc},
{"pickit2", pickit2_initpgm, pickit2_desc},
{"serbb", serbb_initpgm, serbb_desc},
{"serialupdi", serialupdi_initpgm, serialupdi_desc},
{"stk500", stk500_initpgm, stk500_desc},
{"stk500generic", stk500generic_initpgm, stk500generic_desc},
{"stk500v2", stk500v2_initpgm, stk500v2_desc},
{"stk500hvsp", stk500hvsp_initpgm, stk500hvsp_desc},
{"stk500pp", stk500pp_initpgm, stk500pp_desc},
{"stk600", stk600_initpgm, stk600_desc},
{"stk600hvsp", stk600hvsp_initpgm, stk600hvsp_desc},
{"stk600pp", stk600pp_initpgm, stk600pp_desc},
{"teensy", teensy_initpgm, teensy_desc},
{"usbasp", usbasp_initpgm, usbasp_desc},
{"usbtiny", usbtiny_initpgm, usbtiny_desc},
{"wiring", wiring_initpgm, wiring_desc},
{"xbee", xbee_initpgm, xbee_desc},
const PROGRAMMER_TYPE programmers_types[] = { // Name(s) the programmers call themselves
{"arduino", arduino_initpgm, arduino_desc}, // "Arduino"
{"avr910", avr910_initpgm, avr910_desc}, // "avr910"
{"avrftdi", avrftdi_initpgm, avrftdi_desc}, // "avrftdi"
{"buspirate", buspirate_initpgm, buspirate_desc}, // "BusPirate"
{"buspirate_bb", buspirate_bb_initpgm, buspirate_bb_desc}, // "BusPirate_BB"
{"butterfly", butterfly_initpgm, butterfly_desc}, // "butterfly"
{"butterfly_mk", butterfly_mk_initpgm, butterfly_mk_desc}, // "butterfly_mk"
{"dragon_dw", jtagmkII_dragon_dw_initpgm, jtagmkII_dragon_dw_desc}, // "DRAGON_DW"
{"dragon_hvsp", stk500v2_dragon_hvsp_initpgm, stk500v2_dragon_hvsp_desc}, // "DRAGON_HVSP"
{"dragon_isp", stk500v2_dragon_isp_initpgm, stk500v2_dragon_isp_desc}, // "DRAGON_ISP"
{"dragon_jtag", jtagmkII_dragon_initpgm, jtagmkII_dragon_desc}, // "DRAGON_JTAG"
{"dragon_pdi", jtagmkII_dragon_pdi_initpgm, jtagmkII_dragon_pdi_desc}, // "DRAGON_PDI"
{"dragon_pp", stk500v2_dragon_pp_initpgm, stk500v2_dragon_pp_desc}, // "DRAGON_PP"
{"flip1", flip1_initpgm, flip1_desc}, // "flip1"
{"flip2", flip2_initpgm, flip2_desc}, // "flip2"
{"ftdi_syncbb", ft245r_initpgm, ft245r_desc}, // "ftdi_syncbb"
{"jtagmki", jtagmkI_initpgm, jtagmkI_desc}, // "JTAGMKI"
{"jtagmkii", jtagmkII_initpgm, jtagmkII_desc}, // "JTAGMKII"
{"jtagmkii_avr32", jtagmkII_avr32_initpgm, jtagmkII_avr32_desc}, // "JTAGMKII_AVR32"
{"jtagmkii_dw", jtagmkII_dw_initpgm, jtagmkII_dw_desc}, // "JTAGMKII_DW"
{"jtagmkii_isp", stk500v2_jtagmkII_initpgm, stk500v2_jtagmkII_desc}, // "JTAGMKII_ISP"
{"jtagmkii_pdi", jtagmkII_pdi_initpgm, jtagmkII_pdi_desc}, // "JTAGMKII_PDI"
{"jtagmkii_updi", jtagmkII_updi_initpgm, jtagmkII_updi_desc}, // "JTAGMKII_UPDI"
{"jtagice3", jtag3_initpgm, jtag3_desc}, // "JTAGICE3"
{"jtagice3_pdi", jtag3_pdi_initpgm, jtag3_pdi_desc}, // "JTAGICE3_PDI"
{"jtagice3_updi", jtag3_updi_initpgm, jtag3_updi_desc}, // "JTAGICE3_UPDI"
{"jtagice3_dw", jtag3_dw_initpgm, jtag3_dw_desc}, // "JTAGICE3_DW"
{"jtagice3_isp", stk500v2_jtag3_initpgm, stk500v2_jtag3_desc}, // "JTAG3_ISP"
{"linuxgpio", linuxgpio_initpgm, linuxgpio_desc}, // "linuxgpio"
{"linuxspi", linuxspi_initpgm, linuxspi_desc}, // LINUXSPI
{"micronucleus", micronucleus_initpgm, micronucleus_desc}, // "micronucleus" or "Micronucleus V2.0"
{"par", par_initpgm, par_desc}, // "PPI"
{"pickit2", pickit2_initpgm, pickit2_desc}, // "pickit2"
{"serbb", serbb_initpgm, serbb_desc}, // "SERBB"
{"serialupdi", serialupdi_initpgm, serialupdi_desc}, // "serialupdi"
{"stk500", stk500_initpgm, stk500_desc}, // "STK500"
{"stk500generic", stk500generic_initpgm, stk500generic_desc}, // "STK500GENERIC"
{"stk500v2", stk500v2_initpgm, stk500v2_desc}, // "STK500V2"
{"stk500hvsp", stk500hvsp_initpgm, stk500hvsp_desc}, // "STK500HVSP"
{"stk500pp", stk500pp_initpgm, stk500pp_desc}, // "STK500PP"
{"stk600", stk600_initpgm, stk600_desc}, // "STK600"
{"stk600hvsp", stk600hvsp_initpgm, stk600hvsp_desc}, // "STK600HVSP"
{"stk600pp", stk600pp_initpgm, stk600pp_desc}, // "STK600PP"
{"teensy", teensy_initpgm, teensy_desc}, // "teensy"
{"usbasp", usbasp_initpgm, usbasp_desc}, // "usbasp"
{"usbtiny", usbtiny_initpgm, usbtiny_desc}, // "USBtiny" or "usbtiny"
{"wiring", wiring_initpgm, wiring_desc}, // "Wiring"
{"xbee", xbee_initpgm, xbee_desc}, // "XBee"
};
const PROGRAMMER_TYPE * locate_programmer_type(const char * id)
@ -128,6 +128,16 @@ const PROGRAMMER_TYPE * locate_programmer_type(const char * id)
return NULL;
}
// Return type id given the init function or "" if not found
const char *locate_programmer_type_id(void (*initpgm)(struct programmer_t *pgm)) {
for (int i=0; i < sizeof programmers_types/sizeof*programmers_types; i++)
if(programmers_types[i].initpgm == initpgm)
return programmers_types[i].id;
return "";
}
/*
* Iterate over the list of programmers given as "programmers", and
* call the callback function cb for each entry found. cb is being

View File

@ -312,7 +312,7 @@ int pins_check(const struct programmer_t * const pgm, const struct pin_checklist
}
/**
* This function returns a string representation of defined pins eg. ~1,2,~4,~5,7
* This function returns a string of defined pins, eg, ~1,2,~4,~5,7 or " (not used)"
* Another execution of this function will overwrite the previous result in the static buffer.
*
* @param[in] pindef the pin definition for which we want the string representation
@ -346,6 +346,28 @@ const char * pins_to_str(const struct pindef_t * const pindef) {
return buf;
}
/**
* This function returns a string of defined pins, eg, ~1, 2, ~4, ~5, 7 or ""
*
* @param[in] pindef the pin definition for which we want the string representation
* @returns a pointer to a string, which was created by strdup (NULL if out of memory)
*/
char *pins_to_strdup(const struct pindef_t * const pindef) {
char buf[6*(PIN_MAX+1)], *p = buf;
*buf = 0;
for(int pin = PIN_MIN; pin <= PIN_MAX; pin++) {
int index = pin / PIN_FIELD_ELEMENT_SIZE, bit = pin % PIN_FIELD_ELEMENT_SIZE;
if(pindef->mask[index] & (1 << bit)) {
if(*buf)
*p++ = ',', *p++=' ';
p += sprintf(p, "~%d" + !(pindef->inverse[index] & (1 << bit)), pin);
}
}
return strdup(buf);
}
/**
* Returns the name of the pin as string.
*
@ -369,3 +391,24 @@ const char * avr_pin_name(int pinname) {
}
/**
* Returns the name of the pin as string.
*
* @param pinname the pinname which we want as string.
* @returns a lowercase string with the pinname, or <unknown> if pinname is invalid.
*/
const char * avr_pin_lcname(int pinname) {
switch(pinname) {
case PPI_AVR_VCC : return "vcc";
case PPI_AVR_BUFF : return "buff";
case PIN_AVR_RESET : return "reset";
case PIN_AVR_SCK : return "sck";
case PIN_AVR_MOSI : return "mosi";
case PIN_AVR_MISO : return "miso";
case PIN_LED_ERR : return "errled";
case PIN_LED_RDY : return "rdyled";
case PIN_LED_PGM : return "pgmled";
case PIN_LED_VFY : return "vfyled";
default : return "<unknown>";
}
}