1
0
mirror of git://projects.qi-hardware.com/ben-blinkenlights.git synced 2024-07-01 03:06:43 +03:00

ubb-patgen/ubb-patgen.c: new option -d to debounce the trigger

This commit is contained in:
Werner Almesberger 2013-01-16 03:30:04 -03:00
parent 39f4e48f8d
commit 0129a59f86
3 changed files with 74 additions and 13 deletions

View File

@ -13,7 +13,7 @@
CC = mipsel-openwrt-linux-gcc CC = mipsel-openwrt-linux-gcc
CFLAGS = -g -Wall -O9 -I../libubb/include CFLAGS = -g -Wall -O9 -I../libubb/include
LDFLAGS = LDFLAGS =
LDLIBS = -L../libubb -lubb -lm LDLIBS = -L../libubb -lubb -lm -lrt
MAIN = ubb-patgen MAIN = ubb-patgen
OBJS = ubb-patgen.o OBJS = ubb-patgen.o

View File

@ -153,5 +153,12 @@ 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.
ubb-patgen usually starts the pattern about 2 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. trigger, but this can be delayed by other system activity.
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.

View File

@ -323,8 +323,47 @@ static void wait_shifted(const struct mmcclk *clk)
} }
static void wait_trigger(int trigger, int debounce,
const struct timespec *debounce_ns)
{
struct timespec end, now;
/*
* @@@ 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);
if (!debounce)
return;
if (clock_gettime(CLOCK_REALTIME, &end)) {
perror("clock_gettime");
exit(1);
}
end.tv_sec += debounce_ns->tv_sec;
end.tv_nsec += debounce_ns->tv_nsec;
if (end.tv_nsec > 999999999) {
end.tv_nsec -= 1000000000;
end.tv_sec++;
}
while (PIN(UBB_CLK) == trigger) {
if (clock_gettime(CLOCK_REALTIME, &now)) {
perror("clock_gettime");
exit(1);
}
if (now.tv_sec > end.tv_sec)
return;
if (now.tv_sec == end.tv_sec &&
now.tv_nsec >= end.tv_nsec)
return;
}
}
}
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, int trigger) uint8_t first, unsigned long buf, int nibbles, uint32_t mask,
int trigger, int debounce, const struct timespec *debounce_ns)
{ {
/* /*
* If under control of the MMC controller, DATx tri-state until we * If under control of the MMC controller, DATx tri-state until we
@ -370,7 +409,7 @@ static void mmc_buffer(const struct mmcclk *clk,
PDFUNS = mask; PDFUNS = mask;
if (trigger != -1) if (trigger != -1)
while (PIN(UBB_CLK) != trigger); wait_trigger(trigger, debounce, debounce_ns);
/* /*
* Send the pattern with DMA. Note that we still have to send the first * Send the pattern with DMA. Note that we still have to send the first
@ -397,7 +436,8 @@ 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, int trigger) const uint8_t *buf, int nibbles, uint32_t mask,
int trigger, int debounce, const struct timespec *debounce_ns)
{ {
unsigned long phys; unsigned long phys;
@ -407,12 +447,14 @@ static void send_buffer(const struct mmcclk *clk,
} }
phys = physmem_xlat((void *) buf); phys = physmem_xlat((void *) buf);
mmc_buffer(clk, buf[0] >> 4, phys, nibbles, mask, trigger); mmc_buffer(clk, buf[0] >> 4, phys, nibbles, mask,
trigger, debounce, debounce_ns);
} }
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, int trigger,
int debounce, const struct timespec *debounce_ns)
{ {
const uint8_t *buf; const uint8_t *buf;
int n; int n;
@ -442,7 +484,7 @@ static void dma_pattern(const struct mmcclk *clk,
PDDATS = (buf[0] >> 4) << 10; PDDATS = (buf[0] >> 4) << 10;
PDDIRS = mask; PDDIRS = mask;
send_buffer(clk, buf, n, mask, trigger); send_buffer(clk, buf, n, mask, trigger, debounce, debounce_ns);
/* Final static state: the last pattern. */ /* Final static state: the last pattern. */
@ -592,10 +634,11 @@ 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] [-m mask] [-p]\n" " %s [-q] [-f freq_hz|-i interval_s] [-C|-t 0|1 [-d debounce_s]]\n"
" file|pattern\n\n" " [-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"
" -d deb_s trigger debounce time (default: no debouncing)\n"
" -f freq_hz set bus clock to the specified frequency (default: 1 MHz)\n" " -f freq_hz set bus clock to the specified frequency (default: 1 MHz)\n"
" -i inter_s set bus clock such that one cycle equals the specified " " -i inter_s set bus clock such that one cycle equals the specified "
"interval\n" "interval\n"
@ -630,15 +673,17 @@ int main(int argc, char **argv)
const char *pattern = NULL; const char *pattern = NULL;
int quiet = 0, force_pattern = 0; int quiet = 0, force_pattern = 0;
struct timespec active_ns; struct timespec active_ns;
int active_rel = 0; int active_rel;
int keep_clk = 1; int keep_clk = 1;
uint8_t mask = 0xf; uint8_t mask = 0xf;
int trigger = -1; int trigger = -1;
struct timespec debounce_ns;
int debounce = 0, debounce_rel;
char *end; char *end;
int c; int c;
unsigned long tmp; unsigned long tmp;
while ((c = getopt(argc, argv, "cCf:i:m:pqt:")) != EOF) while ((c = getopt(argc, argv, "cCd:f:i:m:pqt:")) != EOF)
switch (c) { switch (c) {
case 'f': case 'f':
if (!frequency(optarg, &bus_hz, &bus_rel)) if (!frequency(optarg, &bus_hz, &bus_rel))
@ -654,6 +699,14 @@ int main(int argc, char **argv)
case 'C': case 'C':
clkout = 1; clkout = 1;
break; break;
case 'd':
if (!duration_timespec(optarg,
&debounce_ns, &debounce_rel))
usage(*argv);
if (debounce_rel < 0)
usage(*argv);
debounce = 1;
break;
case 'm': case 'm':
tmp = strtoul(optarg, &end, 0); tmp = strtoul(optarg, &end, 0);
if (*end) if (*end)
@ -744,7 +797,8 @@ int main(int argc, char **argv)
mmcclk_start(&clk); mmcclk_start(&clk);
if (pattern) if (pattern)
dma_pattern(&clk, pattern, mask << 10, trigger); dma_pattern(&clk, pattern, mask << 10,
trigger, debounce, &debounce_ns);
if (!keep_clk) if (!keep_clk)
if (nanosleep(&active_ns, NULL)) if (nanosleep(&active_ns, NULL))