mirror of
git://projects.qi-hardware.com/ben-blinkenlights.git
synced 2024-11-27 18:06:16 +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
|
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
|
||||||
|
@ -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.
|
||||||
|
@ -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))
|
||||||
|
Loading…
Reference in New Issue
Block a user