1
0
mirror of git://projects.qi-hardware.com/ben-blinkenlights.git synced 2024-06-28 22:21:06 +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
CFLAGS = -g -Wall -O9 -I../libubb/include
LDFLAGS =
LDLIBS = -L../libubb -lubb -lm
LDLIBS = -L../libubb -lubb -lm -lrt
MAIN = ubb-patgen
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
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.
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,
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
@ -370,7 +409,7 @@ static void mmc_buffer(const struct mmcclk *clk,
PDFUNS = mask;
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
@ -397,7 +436,8 @@ 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)
const uint8_t *buf, int nibbles, uint32_t mask,
int trigger, int debounce, const struct timespec *debounce_ns)
{
unsigned long phys;
@ -407,12 +447,14 @@ static void send_buffer(const struct mmcclk *clk,
}
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,
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;
int n;
@ -442,7 +484,7 @@ static void dma_pattern(const struct mmcclk *clk,
PDDATS = (buf[0] >> 4) << 10;
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. */
@ -592,10 +634,11 @@ 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] [-m mask] [-p]\n"
" file|pattern\n\n"
" %s [-q] [-f freq_hz|-i interval_s] [-C|-t 0|1 [-d debounce_s]]\n"
" [-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"
" -d deb_s trigger debounce time (default: no debouncing)\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 "
"interval\n"
@ -630,15 +673,17 @@ int main(int argc, char **argv)
const char *pattern = NULL;
int quiet = 0, force_pattern = 0;
struct timespec active_ns;
int active_rel = 0;
int active_rel;
int keep_clk = 1;
uint8_t mask = 0xf;
int trigger = -1;
struct timespec debounce_ns;
int debounce = 0, debounce_rel;
char *end;
int c;
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) {
case 'f':
if (!frequency(optarg, &bus_hz, &bus_rel))
@ -654,6 +699,14 @@ int main(int argc, char **argv)
case 'C':
clkout = 1;
break;
case 'd':
if (!duration_timespec(optarg,
&debounce_ns, &debounce_rel))
usage(*argv);
if (debounce_rel < 0)
usage(*argv);
debounce = 1;
break;
case 'm':
tmp = strtoul(optarg, &end, 0);
if (*end)
@ -744,7 +797,8 @@ int main(int argc, char **argv)
mmcclk_start(&clk);
if (pattern)
dma_pattern(&clk, pattern, mask << 10, trigger);
dma_pattern(&clk, pattern, mask << 10,
trigger, debounce, &debounce_ns);
if (!keep_clk)
if (nanosleep(&active_ns, NULL))