1
0
mirror of git://projects.qi-hardware.com/ben-blinkenlights.git synced 2024-11-16 22:07:12 +02:00

ubb-patgen/ubb-patgen.c: support trigger sequences, e.g., 01 for a rising edge

This commit is contained in:
Werner Almesberger 2013-01-16 04:45:49 -03:00
parent 4729d00b30
commit 66080fe72e
2 changed files with 34 additions and 24 deletions

View File

@ -153,6 +153,10 @@ send the pattern immediately.
Likewise, -t 1 waits for CLK to become 1. -t cannot be used with Likewise, -t 1 waits for CLK to become 1. -t cannot be used with
the -C option. the -C option.
The trigger can also be a sequence, e.g., -t 01 would first wait
for CLK to become zero (if it isn't already), then wait for it to
become one.
ubb-patgen usually starts the pattern about 2-10 us after the ubb-patgen usually starts the pattern about 2-10 us after the
trigger, but this can be delayed by other system activity. An trigger, but this can be delayed by other system activity. An
extra delay can be added with the option -w, e.g., extra delay can be added with the option -w, e.g.,
@ -164,4 +168,5 @@ The trigger signal can be debounced with the option -d, e.g.,
# ubb-patgen -t 0 -d 100us 0f0 # ubb-patgen -t 0 -d 100us 0f0
This accepts the trigger only after it has been zero for at least This accepts the trigger only after it has been zero for at least
100 microseconds. 100 microseconds. If the trigger is a sequence, debouncing is
applied at each step.

View File

@ -354,7 +354,7 @@ static void wait_shifted(const struct mmcclk *clk)
} }
static void wait_trigger(int trigger, int debounce, static void wait_trigger(const char *trigger, int debounce,
const struct timespec *debounce_ns) const struct timespec *debounce_ns)
{ {
struct timespec end, now; struct timespec end, now;
@ -363,10 +363,11 @@ static void wait_trigger(int trigger, int debounce,
* @@@ could also try to use POSIX per-process timers here. May be * @@@ could also try to use POSIX per-process timers here. May be
* slightly cleaner but could increase deviations. * slightly cleaner but could increase deviations.
*/ */
while (1) { while (*trigger) {
while (PIN(UBB_CLK) != trigger); while (PIN(UBB_CLK) != *trigger-'0');
if (!debounce) if (!debounce)
return; goto next;
again:
if (clock_gettime(CLOCK_REALTIME, &end)) { if (clock_gettime(CLOCK_REALTIME, &end)) {
perror("clock_gettime"); perror("clock_gettime");
exit(1); exit(1);
@ -377,24 +378,27 @@ static void wait_trigger(int trigger, int debounce,
end.tv_nsec -= 1000000000; end.tv_nsec -= 1000000000;
end.tv_sec++; end.tv_sec++;
} }
while (PIN(UBB_CLK) == trigger) { while (PIN(UBB_CLK) == *trigger-'0') {
if (clock_gettime(CLOCK_REALTIME, &now)) { if (clock_gettime(CLOCK_REALTIME, &now)) {
perror("clock_gettime"); perror("clock_gettime");
exit(1); exit(1);
} }
if (now.tv_sec > end.tv_sec) if (now.tv_sec > end.tv_sec)
return; goto next;
if (now.tv_sec == end.tv_sec && if (now.tv_sec == end.tv_sec &&
now.tv_nsec >= end.tv_nsec) now.tv_nsec >= end.tv_nsec)
return; goto next;
} }
goto again;
next:
trigger++;
} }
} }
static void mmc_buffer(const struct mmcclk *clk, static void mmc_buffer(const struct mmcclk *clk,
uint8_t first, unsigned long buf, int nibbles, uint32_t mask, uint8_t first, unsigned long buf, int nibbles, uint32_t mask,
int trigger, int debounce, const struct timespec *debounce_ns, const char *trigger, int debounce, const struct timespec *debounce_ns,
const struct timespec *wait_ns) const struct timespec *wait_ns)
{ {
/* /*
@ -442,7 +446,7 @@ static void mmc_buffer(const struct mmcclk *clk,
realtimize(); realtimize();
if (trigger != -1) if (trigger)
wait_trigger(trigger, debounce, debounce_ns); wait_trigger(trigger, debounce, debounce_ns);
if (wait_ns->tv_sec || wait_ns->tv_nsec) if (wait_ns->tv_sec || wait_ns->tv_nsec)
if (nanosleep(wait_ns, NULL)) if (nanosleep(wait_ns, NULL))
@ -476,7 +480,7 @@ static void mmc_buffer(const struct mmcclk *clk,
static void send_buffer(const struct mmcclk *clk, static void send_buffer(const struct mmcclk *clk,
const uint8_t *buf, int nibbles, uint32_t mask, const uint8_t *buf, int nibbles, uint32_t mask,
int trigger, int debounce, const struct timespec *debounce_ns, const char *trigger, int debounce, const struct timespec *debounce_ns,
const struct timespec *wait_ns) const struct timespec *wait_ns)
{ {
unsigned long phys; unsigned long phys;
@ -493,7 +497,7 @@ static void send_buffer(const struct mmcclk *clk,
static void dma_pattern(const struct mmcclk *clk, static void dma_pattern(const struct mmcclk *clk,
const char *pattern, uint32_t mask, int trigger, const char *pattern, uint32_t mask, const char *trigger,
int debounce, const struct timespec *debounce_ns, int debounce, const struct timespec *debounce_ns,
const struct timespec *wait_ns) const struct timespec *wait_ns)
{ {
@ -511,7 +515,7 @@ static void dma_pattern(const struct mmcclk *clk,
exit(1); exit(1);
} }
if (trigger != -1) { if (trigger) {
PDFUNC = UBB_CLK; PDFUNC = UBB_CLK;
IN(UBB_CLK); IN(UBB_CLK);
} }
@ -676,7 +680,7 @@ static void usage(const char *name)
"usage: %s\n" "usage: %s\n"
" %s [-q] -f freq_hz|-i interval_s\n" " %s [-q] -f freq_hz|-i interval_s\n"
" %s [-q] [-f freq_hz|-i interval_s] -c [active_s]\n" " %s [-q] [-f freq_hz|-i interval_s] -c [active_s]\n"
" %s [-q] [-f freq_hz|-i interval_s] [-C|-t 0|1 [-d debounce_s]]\n" " %s [-q] [-f freq_hz|-i interval_s] [-C|-t 0|1... [-d debounce_s]]\n"
" [-w wait_s] [-m mask] [-p] file|pattern\n\n" " [-w wait_s] [-m mask] [-p] file|pattern\n\n"
" -c output bus clock on CLK without sending a pattern\n" " -c output bus clock on CLK without sending a pattern\n"
" -C temporarily output bus clock on CLK (for debugging)\n" " -C temporarily output bus clock on CLK (for debugging)\n"
@ -688,7 +692,7 @@ static void usage(const char *name)
" -p force interpretation of argument as pattern (and not file)\n" " -p force interpretation of argument as pattern (and not file)\n"
" -q quiet. Don't pretty-print frequencies; don't report clock\n" " -q quiet. Don't pretty-print frequencies; don't report clock\n"
" differences.\n" " differences.\n"
" -t 0|1 start pattern when trigger/CLK becomes 0 or 1 respectively\n" " -t 0|1... start pattern when trigger/CLK has passed through the sequence\n"
" (default: start pattern immediately)\n" " (default: start pattern immediately)\n"
" -w wait_s wait between trigger and sending the pattern\n\n" " -w wait_s wait between trigger and sending the pattern\n\n"
" active_s keep running that many seconds after setting the clock\n" " active_s keep running that many seconds after setting the clock\n"
@ -719,7 +723,7 @@ int main(int argc, char **argv)
int active_rel; int active_rel;
int keep_clk = 1; int keep_clk = 1;
uint8_t mask = 0xf; uint8_t mask = 0xf;
int trigger = -1; const char *trigger = NULL;
struct timespec debounce_ns; struct timespec debounce_ns;
int debounce = 0, debounce_rel; int debounce = 0, debounce_rel;
struct timespec wait_ns = { 0, 0 }; struct timespec wait_ns = { 0, 0 };
@ -727,6 +731,7 @@ int main(int argc, char **argv)
char *end; char *end;
int c; int c;
unsigned long tmp; unsigned long tmp;
const char *p;
while ((c = getopt(argc, argv, "cCd:f:i:m:pqt:w:")) != EOF) while ((c = getopt(argc, argv, "cCd:f:i:m:pqt:w:")) != EOF)
switch (c) { switch (c) {
@ -769,11 +774,11 @@ int main(int argc, char **argv)
quiet = 1; quiet = 1;
break; break;
case 't': case 't':
if (!strcmp(optarg, "0")) trigger = optarg;
trigger = 0; if (!*trigger)
else if (!strcmp(optarg, "1")) usage(*argv);
trigger = 1; for (p = trigger; *p; p++)
else if (*p != '0' && *p != '1')
usage(*argv); usage(*argv);
break; break;
case 'w': case 'w':
@ -789,14 +794,14 @@ int main(int argc, char **argv)
if (clkout && clk_only) if (clkout && clk_only)
usage(*argv); usage(*argv);
if ((clkout || clk_only) && trigger != -1) if ((clkout || clk_only) && trigger)
usage(*argv); usage(*argv);
switch (argc-optind) { switch (argc-optind) {
case 0: case 0:
if (clk_only) if (clk_only)
break; break;
if (clkout || force_pattern || trigger != -1) if (clkout || force_pattern || trigger)
usage(*argv); usage(*argv);
ubb_open(UBB_ALL); ubb_open(UBB_ALL);
@ -857,7 +862,7 @@ int main(int argc, char **argv)
perror("nanosleep"); perror("nanosleep");
if (pattern) { if (pattern) {
mmcclk_stop(); mmcclk_stop();
ubb_close(mask << 10 | (trigger == -1 ? 0 : UBB_CLK)); ubb_close(mask << 10 | (trigger ? UBB_CLK : 0));
} else if (keep_clk) { } else if (keep_clk) {
ubb_close(UBB_CLK); ubb_close(UBB_CLK);
} else { } else {