mirror of
git://projects.qi-hardware.com/ben-blinkenlights.git
synced 2024-11-27 16:48:26 +02:00
ubb-patgen/ubb-patgen.c: new option -d to debounce the trigger
This commit is contained in:
parent
39f4e48f8d
commit
0129a59f86
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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))
|
||||
|
Loading…
Reference in New Issue
Block a user