ubbctl/README |
30 | 30 | pull-up is enabled. |
31 | 31 | |
32 | 32 | "F0" and "F1" indicate that the pin configured as a function (i.e., |
33 | | for the MMC controller) and does not operate as GPIO. |
| 33 | for the MMC controller) and does not operate as GPIO. If the second |
| 34 | function of the pin is selected, "Fb..." is shown instead of "F...". |
| 35 | |
| 36 | "I..." indicates that the pin is configured as an interrupt. The |
| 37 | next letter defines the type of interrupt, "r" for rising edge, |
| 38 | "f" for falling edge, "h" for high level, and "l" for low level. If |
| 39 | the pull-up is enabled, ubbctl adds an "R". Finally, it shows the |
| 40 | pin status. E.g., "IfR1" would be an interrupt triggering on the |
| 41 | falling edge, with pull-up enabled, and currently inactive. |
34 | 42 | |
35 | 43 | ubbctl can run in continuous mode, in which it updates the status |
36 | 44 | regularly (currently every 200 ms): |
ubbctl/ubbctl.c |
1 | 1 | /* |
2 | 2 | * ubbctl.c - Set and query UBB signals |
3 | 3 | * |
4 | | * Written 2013 by Werner Almesberger |
5 | | * Copyright 2013 Werner Almesberger |
| 4 | * Written 2013-2014 by Werner Almesberger |
| 5 | * Copyright 2013-2014 Werner Almesberger |
6 | 6 | * |
7 | 7 | * This program is free software; you can redistribute it and/or modify |
8 | 8 | * it under the terms of the GNU General Public License as published by |
... | ... | |
46 | 46 | pin = PIN(p->mask); |
47 | 47 | if (PDFUN & p->mask) { |
48 | 48 | putchar('F'); |
| 49 | if (PDSEL & p->mask) |
| 50 | putchar('b'); |
| 51 | } else if (PDSEL & p->mask) { |
| 52 | putchar('I'); |
| 53 | if (PDTRG & p->mask) { |
| 54 | if (PDDIR & p->mask) |
| 55 | putchar('r'); |
| 56 | else |
| 57 | putchar('f'); |
| 58 | } else { |
| 59 | if (PDDIR & p->mask) |
| 60 | putchar('h'); |
| 61 | else |
| 62 | putchar('l'); |
| 63 | } |
| 64 | if (!(PDPULL & p->mask)) |
| 65 | putchar('R'); |
49 | 66 | } else if (PDDIR & p->mask) { |
50 | 67 | set = !!(PDDAT & p->mask); |
51 | 68 | if (pin != set) |
... | ... | |
65 | 82 | |
66 | 83 | static int setup_pin(const char *s, int doit) |
67 | 84 | { |
| 85 | static const char trigger[] = "lhfrLHFR"; |
68 | 86 | const struct pin *p; |
69 | | const char *eq; |
| 87 | const char *eq, *t; |
| 88 | uint8_t trig; |
70 | 89 | |
71 | 90 | if (!strcasecmp(s, "on")) |
72 | 91 | s = "nPWR=0"; |
... | ... | |
83 | 102 | if (!p->name) |
84 | 103 | return 0; |
85 | 104 | |
86 | | if (!strcasecmp(eq+1, "f")) { |
87 | | if (doit) |
| 105 | if (!strcasecmp(eq+1, "f") || !strcasecmp(eq+1, "fa")) { |
| 106 | if (doit) { |
| 107 | PDFUNS = p->mask; |
| 108 | PDSELC = p->mask; |
| 109 | } |
| 110 | return 1; |
| 111 | } |
| 112 | if (!strcasecmp(eq+1, "fb")) { |
| 113 | if (doit) { |
88 | 114 | PDFUNS = p->mask; |
89 | | } else if (!strcmp(eq+1, "0")) { |
| 115 | PDSELS = p->mask; |
| 116 | } |
| 117 | return 1; |
| 118 | } |
| 119 | if (!strcmp(eq+1, "0")) { |
90 | 120 | if (doit) { |
91 | 121 | PDDATC = p->mask; |
92 | 122 | PDDIRS = p->mask; |
93 | 123 | PDFUNC = p->mask; |
94 | 124 | } |
95 | | } else if (!strcmp(eq+1, "1")) { |
| 125 | return 1; |
| 126 | } |
| 127 | if (!strcmp(eq+1, "1")) { |
96 | 128 | if (doit) { |
97 | 129 | PDDATS = p->mask; |
98 | 130 | PDDIRS = p->mask; |
99 | 131 | PDFUNC = p->mask; |
100 | 132 | } |
101 | | } else if (!strcasecmp(eq+1, "r")) { |
| 133 | return 1; |
| 134 | } |
| 135 | if (!strcasecmp(eq+1, "r")) { |
102 | 136 | if (doit) { |
103 | 137 | PDPULLC = p->mask; |
104 | 138 | PDDIRC = p->mask; |
105 | 139 | PDFUNC = p->mask; |
| 140 | PDSELC = p->mask; |
106 | 141 | } |
107 | | } else if (!strcasecmp(eq+1, "z")) { |
| 142 | return 1; |
| 143 | } |
| 144 | if (!strcasecmp(eq+1, "z")) { |
108 | 145 | if (doit) { |
109 | 146 | PDPULLS = p->mask; |
110 | 147 | PDDIRC = p->mask; |
111 | 148 | PDFUNC = p->mask; |
| 149 | PDSELC = p->mask; |
112 | 150 | } |
| 151 | return 1; |
| 152 | } |
| 153 | if (eq[1] != 'i' && eq[1] != 'I') |
| 154 | return 0; |
| 155 | |
| 156 | t = strchr(trigger, eq[2]); |
| 157 | if (!t || !*t) |
| 158 | return 0; |
| 159 | |
| 160 | if (!eq[3] || eq[3] == 'z' || eq[3] == 'Z') { |
| 161 | if (doit) |
| 162 | PDPULLS = p->mask; |
| 163 | } else if (eq[3] == 'r' || eq[3] == 'R') { |
| 164 | if (doit) |
| 165 | PDPULLC = p->mask; |
113 | 166 | } else { |
114 | 167 | return 0; |
115 | 168 | } |
| 169 | |
| 170 | if (!doit) |
| 171 | return 1; |
| 172 | |
| 173 | PDFUNC = p->mask; |
| 174 | PDSELS = p->mask; |
| 175 | trig = (t-trigger) & 3; |
| 176 | if (trig & 1) |
| 177 | PDDIRS = p->mask; |
| 178 | else |
| 179 | PDDIRC = p->mask; |
| 180 | if (trig & 2) |
| 181 | PDTRGS = p->mask; |
| 182 | else |
| 183 | PDTRGC = p->mask; |
| 184 | |
116 | 185 | return 1; |
117 | 186 | } |
118 | 187 | |
... | ... | |
124 | 193 | " %s name=value|action ...\n\n" |
125 | 194 | " -c continously update the pin status (until user interrupts)\n\n" |
126 | 195 | "Names: nPWR, CMD, CLK, DAT0, DAT1, DAT2, DAT3\n" |
127 | | "Values: F, 0, 1, Z, R\n" |
| 196 | "Values: F, Fa, Fb, 0, 1, Z, R, Ir[R|Z], If[R|Z], Ih[R|Z], Il[R|Z]\n" |
128 | 197 | "Actions: ON, OFF\n" |
129 | 198 | , name, name); |
130 | 199 | exit(1); |