diff --git a/ubb-patgen/README b/ubb-patgen/README index 5d74f19..22eee31 100644 --- a/ubb-patgen/README +++ b/ubb-patgen/README @@ -153,6 +153,10 @@ send the pattern immediately. Likewise, -t 1 waits for CLK to become 1. -t cannot be used with 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 trigger, but this can be delayed by other system activity. An 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 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. diff --git a/ubb-patgen/ubb-patgen.c b/ubb-patgen/ubb-patgen.c index 863d534..6309119 100644 --- a/ubb-patgen/ubb-patgen.c +++ b/ubb-patgen/ubb-patgen.c @@ -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) { 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 * slightly cleaner but could increase deviations. */ - while (1) { - while (PIN(UBB_CLK) != trigger); + while (*trigger) { + while (PIN(UBB_CLK) != *trigger-'0'); if (!debounce) - return; + goto next; +again: if (clock_gettime(CLOCK_REALTIME, &end)) { perror("clock_gettime"); exit(1); @@ -377,24 +378,27 @@ static void wait_trigger(int trigger, int debounce, end.tv_nsec -= 1000000000; end.tv_sec++; } - while (PIN(UBB_CLK) == trigger) { + while (PIN(UBB_CLK) == *trigger-'0') { if (clock_gettime(CLOCK_REALTIME, &now)) { perror("clock_gettime"); exit(1); } if (now.tv_sec > end.tv_sec) - return; + goto next; if (now.tv_sec == end.tv_sec && now.tv_nsec >= end.tv_nsec) - return; + goto next; } + goto again; +next: + trigger++; } } static void mmc_buffer(const struct mmcclk *clk, 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) { /* @@ -442,7 +446,7 @@ static void mmc_buffer(const struct mmcclk *clk, realtimize(); - if (trigger != -1) + if (trigger) wait_trigger(trigger, debounce, debounce_ns); if (wait_ns->tv_sec || wait_ns->tv_nsec) 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, 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) { unsigned long phys; @@ -493,7 +497,7 @@ static void send_buffer(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, const struct timespec *wait_ns) { @@ -511,7 +515,7 @@ static void dma_pattern(const struct mmcclk *clk, exit(1); } - if (trigger != -1) { + if (trigger) { PDFUNC = UBB_CLK; IN(UBB_CLK); } @@ -676,7 +680,7 @@ static void usage(const char *name) "usage: %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|-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" " -c output bus clock on CLK without sending a pattern\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" " -q quiet. Don't pretty-print frequencies; don't report clock\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" " -w wait_s wait between trigger and sending the pattern\n\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 keep_clk = 1; uint8_t mask = 0xf; - int trigger = -1; + const char *trigger = NULL; struct timespec debounce_ns; int debounce = 0, debounce_rel; struct timespec wait_ns = { 0, 0 }; @@ -727,6 +731,7 @@ int main(int argc, char **argv) char *end; int c; unsigned long tmp; + const char *p; while ((c = getopt(argc, argv, "cCd:f:i:m:pqt:w:")) != EOF) switch (c) { @@ -769,12 +774,12 @@ int main(int argc, char **argv) quiet = 1; break; case 't': - if (!strcmp(optarg, "0")) - trigger = 0; - else if (!strcmp(optarg, "1")) - trigger = 1; - else + trigger = optarg; + if (!*trigger) usage(*argv); + for (p = trigger; *p; p++) + if (*p != '0' && *p != '1') + usage(*argv); break; case 'w': if (!duration_timespec(optarg, @@ -789,14 +794,14 @@ int main(int argc, char **argv) if (clkout && clk_only) usage(*argv); - if ((clkout || clk_only) && trigger != -1) + if ((clkout || clk_only) && trigger) usage(*argv); switch (argc-optind) { case 0: if (clk_only) break; - if (clkout || force_pattern || trigger != -1) + if (clkout || force_pattern || trigger) usage(*argv); ubb_open(UBB_ALL); @@ -857,7 +862,7 @@ int main(int argc, char **argv) perror("nanosleep"); if (pattern) { mmcclk_stop(); - ubb_close(mask << 10 | (trigger == -1 ? 0 : UBB_CLK)); + ubb_close(mask << 10 | (trigger ? UBB_CLK : 0)); } else if (keep_clk) { ubb_close(UBB_CLK); } else {