diff --git a/ubbctl/README b/ubbctl/README index 471a15d..097d252 100644 --- a/ubbctl/README +++ b/ubbctl/README @@ -30,7 +30,15 @@ respectively. pull-up is enabled. "F0" and "F1" indicate that the pin configured as a function (i.e., -for the MMC controller) and does not operate as GPIO. +for the MMC controller) and does not operate as GPIO. If the second +function of the pin is selected, "Fb..." is shown instead of "F...". + +"I..." indicates that the pin is configured as an interrupt. The +next letter defines the type of interrupt, "r" for rising edge, +"f" for falling edge, "h" for high level, and "l" for low level. If +the pull-up is enabled, ubbctl adds an "R". Finally, it shows the +pin status. E.g., "IfR1" would be an interrupt triggering on the +falling edge, with pull-up enabled, and currently inactive. ubbctl can run in continuous mode, in which it updates the status regularly (currently every 200 ms): diff --git a/ubbctl/ubbctl.c b/ubbctl/ubbctl.c index 0da9232..a5a3d2e 100644 --- a/ubbctl/ubbctl.c +++ b/ubbctl/ubbctl.c @@ -1,8 +1,8 @@ /* * ubbctl.c - Set and query UBB signals * - * Written 2013 by Werner Almesberger - * Copyright 2013 Werner Almesberger + * Written 2013-2014 by Werner Almesberger + * Copyright 2013-2014 Werner Almesberger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -46,6 +46,23 @@ static void show_pins(void) pin = PIN(p->mask); if (PDFUN & p->mask) { putchar('F'); + if (PDSEL & p->mask) + putchar('b'); + } else if (PDSEL & p->mask) { + putchar('I'); + if (PDTRG & p->mask) { + if (PDDIR & p->mask) + putchar('r'); + else + putchar('f'); + } else { + if (PDDIR & p->mask) + putchar('h'); + else + putchar('l'); + } + if (!(PDPULL & p->mask)) + putchar('R'); } else if (PDDIR & p->mask) { set = !!(PDDAT & p->mask); if (pin != set) @@ -65,8 +82,10 @@ static void show_pins(void) static int setup_pin(const char *s, int doit) { + static const char trigger[] = "lhfrLHFR"; const struct pin *p; - const char *eq; + const char *eq, *t; + uint8_t trig; if (!strcasecmp(s, "on")) s = "nPWR=0"; @@ -83,36 +102,86 @@ static int setup_pin(const char *s, int doit) if (!p->name) return 0; - if (!strcasecmp(eq+1, "f")) { - if (doit) + if (!strcasecmp(eq+1, "f") || !strcasecmp(eq+1, "fa")) { + if (doit) { PDFUNS = p->mask; - } else if (!strcmp(eq+1, "0")) { + PDSELC = p->mask; + } + return 1; + } + if (!strcasecmp(eq+1, "fb")) { + if (doit) { + PDFUNS = p->mask; + PDSELS = p->mask; + } + return 1; + } + if (!strcmp(eq+1, "0")) { if (doit) { PDDATC = p->mask; PDDIRS = p->mask; PDFUNC = p->mask; } - } else if (!strcmp(eq+1, "1")) { + return 1; + } + if (!strcmp(eq+1, "1")) { if (doit) { PDDATS = p->mask; PDDIRS = p->mask; PDFUNC = p->mask; } - } else if (!strcasecmp(eq+1, "r")) { + return 1; + } + if (!strcasecmp(eq+1, "r")) { if (doit) { PDPULLC = p->mask; PDDIRC = p->mask; PDFUNC = p->mask; + PDSELC = p->mask; } - } else if (!strcasecmp(eq+1, "z")) { + return 1; + } + if (!strcasecmp(eq+1, "z")) { if (doit) { PDPULLS = p->mask; PDDIRC = p->mask; PDFUNC = p->mask; + PDSELC = p->mask; } + return 1; + } + if (eq[1] != 'i' && eq[1] != 'I') + return 0; + + t = strchr(trigger, eq[2]); + if (!t || !*t) + return 0; + + if (!eq[3] || eq[3] == 'z' || eq[3] == 'Z') { + if (doit) + PDPULLS = p->mask; + } else if (eq[3] == 'r' || eq[3] == 'R') { + if (doit) + PDPULLC = p->mask; } else { return 0; } + + if (!doit) + return 1; + + PDFUNC = p->mask; + PDSELS = p->mask; + trig = (t-trigger) & 3; + if (trig & 1) + PDDIRS = p->mask; + else + PDDIRC = p->mask; + if (trig & 2) + PDTRGS = p->mask; + else + PDTRGC = p->mask; + return 1; } @@ -124,7 +193,7 @@ static void usage(const char *name) " %s name=value|action ...\n\n" " -c continously update the pin status (until user interrupts)\n\n" "Names: nPWR, CMD, CLK, DAT0, DAT1, DAT2, DAT3\n" -"Values: F, 0, 1, Z, R\n" +"Values: F, Fa, Fb, 0, 1, Z, R, Ir[R|Z], If[R|Z], Ih[R|Z], Il[R|Z]\n" "Actions: ON, OFF\n" , name, name); exit(1);