mirror of
git://projects.qi-hardware.com/ben-blinkenlights.git
synced 2024-11-27 15:20:16 +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:
parent
e5cb1c98ea
commit
3febc9072a
@ -287,27 +287,71 @@ 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();
|
||||||
|
|
||||||
/* Initial static state: the first pattern. */
|
/* Initial static state: the first pattern. */
|
||||||
@ -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");
|
||||||
|
Loading…
Reference in New Issue
Block a user