1
0
mirror of git://projects.qi-hardware.com/ben-blinkenlights.git synced 2024-11-27 17:34:04 +02:00

ubb-patgen/ubb-patgen.c (dma_pattern): move pattern parser to parse_pattern

... and introduce pattern multipliers <hex>{<repetitions>}
This commit is contained in:
Werner Almesberger 2013-01-14 19:26:15 -03:00
parent e5cb1c98ea
commit 3febc9072a

View File

@ -287,26 +287,70 @@ static void send_buffer(const struct mmcclk *clk,
} }
static int dma_pattern(const struct mmcclk *clk, static void *parse_pattern(const char *s, int *nibbles)
{
uint8_t *buf = physmem_malloc(4095); /* maximum block size */
int n = 0;
uint8_t v = 0;
char *end;
unsigned long i;
memset(buf, 0, 4095);
while (*s) {
char ch[2] = { *s, 0 };
v = strtoul(ch, &end, 16);
if (*end) {
fprintf(stderr, "\"%c\" is not a hex digit\n", *s);
exit(1);
}
if (s[1] == '{') {
i = strtoul(s+2, &end, 0);
if (!*end) {
fprintf(stderr, "unterminated range\n");
exit(1);
}
if (*end != '}' || end == s+2) {
fprintf(stderr, "invalid range \"%.*s\"\n",
end-s, s+1);
exit(1);
}
s = end+1;
} else {
i = 1;
s++;
}
while (i) {
if (n == 8192-64-1) {
fprintf(stderr, "pattern is too long\n");
exit(1);
}
buf[n >> 1] |= v << 4*(~n & 1);
n++;
i--;
}
}
/* pad to multiples of 32 bytes */
while (n & 63) {
buf[n >> 1] |= v << 4*(~n & 1);
n++;
}
*nibbles = n;
return buf;
}
static void dma_pattern(const struct mmcclk *clk,
const char *pattern, uint32_t mask) const char *pattern, uint32_t mask)
{ {
int n = strlen(pattern); const uint8_t *buf;
int rounded = (n+63) & ~63; int n;
uint8_t *buf = physmem_malloc(rounded >> 1);
int i;
if (!n) if (!*pattern) {
return 1; fprintf(stderr, "pattern is empty\n");
exit(1);
memset(buf, 0, rounded);
for (i = 0; i != rounded; i++) {
char ch[2] = { pattern[i < n ? i : n-1], 0 };
char *end;
buf[i >> 1] |= strtoul(ch, &end, 16) << 4*(~i & 1);
if (*end)
return 0;
} }
buf = parse_pattern(pattern, &n);
dma_init(); dma_init();
@ -317,18 +361,16 @@ static int dma_pattern(const struct mmcclk *clk,
PDDATS = (buf[0] >> 4) << 10; PDDATS = (buf[0] >> 4) << 10;
PDDIRS = mask; PDDIRS = mask;
send_buffer(clk, buf, rounded, mask); send_buffer(clk, buf, n, mask);
/* Final static state: the last pattern. */ /* Final static state: the last pattern. */
PDDATC = ~((buf[(rounded >> 1)-1] & 0xf) << 10) & mask; PDDATC = ~((buf[(n >> 1)-1] & 0xf) << 10) & mask;
PDDATS = (buf[(rounded >> 1)-1] & 0xf) << 10; PDDATS = (buf[(n >> 1)-1] & 0xf) << 10;
PDFUNC = mask; PDFUNC = mask;
dma_cleanup(); dma_cleanup();
return 1;
} }
@ -396,6 +438,7 @@ static void usage(const char *name)
" \"+\" selects a frequency >= the specified one, \"-\" one <=.\n" " \"+\" selects a frequency >= the specified one, \"-\" one <=.\n"
" Without +/-, the closest available frequency is selected.\n" " Without +/-, the closest available frequency is selected.\n"
"Pattern: hex digits corresponding to 1 for DAT0, 2 for DAT1, etc.\n" "Pattern: hex digits corresponding to 1 for DAT0, 2 for DAT1, etc.\n"
" {n} repeats the preceding digit n times, e.g., 1{3} is equivalent to 111.\n"
, name, name); , name, name);
exit(1); exit(1);
} }
@ -482,9 +525,8 @@ int main(int argc, char **argv)
mmcclk_start(&clk); mmcclk_start(&clk);
if (pattern) if (pattern)
if (!dma_pattern(&clk, pattern, dma_pattern(&clk, pattern,
UBB_DAT0 | UBB_DAT1 | UBB_DAT2 | UBB_DAT3)) UBB_DAT0 | UBB_DAT1 | UBB_DAT2 | UBB_DAT3);
usage(*argv);
if (nanosleep(&active_ns, NULL)) if (nanosleep(&active_ns, NULL))
perror("nanosleep"); perror("nanosleep");