mirror of
git://projects.qi-hardware.com/ben-blinkenlights.git
synced 2024-11-16 22:07:12 +02:00
ubb-patgen/ubb-patgen.c: support trigger sequences, e.g., 01 for a rising edge
This commit is contained in:
parent
4729d00b30
commit
66080fe72e
@ -153,6 +153,10 @@ 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.
|
||||||
|
|
||||||
|
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
|
ubb-patgen usually starts the pattern about 2-10 us after the
|
||||||
trigger, but this can be delayed by other system activity. An
|
trigger, but this can be delayed by other system activity. An
|
||||||
extra delay can be added with the option -w, e.g.,
|
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
|
# ubb-patgen -t 0 -d 100us 0f0
|
||||||
|
|
||||||
This accepts the trigger only after it has been zero for at least
|
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.
|
||||||
|
@ -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)
|
const struct timespec *debounce_ns)
|
||||||
{
|
{
|
||||||
struct timespec end, now;
|
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
|
* @@@ could also try to use POSIX per-process timers here. May be
|
||||||
* slightly cleaner but could increase deviations.
|
* slightly cleaner but could increase deviations.
|
||||||
*/
|
*/
|
||||||
while (1) {
|
while (*trigger) {
|
||||||
while (PIN(UBB_CLK) != trigger);
|
while (PIN(UBB_CLK) != *trigger-'0');
|
||||||
if (!debounce)
|
if (!debounce)
|
||||||
return;
|
goto next;
|
||||||
|
again:
|
||||||
if (clock_gettime(CLOCK_REALTIME, &end)) {
|
if (clock_gettime(CLOCK_REALTIME, &end)) {
|
||||||
perror("clock_gettime");
|
perror("clock_gettime");
|
||||||
exit(1);
|
exit(1);
|
||||||
@ -377,24 +378,27 @@ static void wait_trigger(int trigger, int debounce,
|
|||||||
end.tv_nsec -= 1000000000;
|
end.tv_nsec -= 1000000000;
|
||||||
end.tv_sec++;
|
end.tv_sec++;
|
||||||
}
|
}
|
||||||
while (PIN(UBB_CLK) == trigger) {
|
while (PIN(UBB_CLK) == *trigger-'0') {
|
||||||
if (clock_gettime(CLOCK_REALTIME, &now)) {
|
if (clock_gettime(CLOCK_REALTIME, &now)) {
|
||||||
perror("clock_gettime");
|
perror("clock_gettime");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
if (now.tv_sec > end.tv_sec)
|
if (now.tv_sec > end.tv_sec)
|
||||||
return;
|
goto next;
|
||||||
if (now.tv_sec == end.tv_sec &&
|
if (now.tv_sec == end.tv_sec &&
|
||||||
now.tv_nsec >= end.tv_nsec)
|
now.tv_nsec >= end.tv_nsec)
|
||||||
return;
|
goto next;
|
||||||
}
|
}
|
||||||
|
goto again;
|
||||||
|
next:
|
||||||
|
trigger++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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,
|
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)
|
const struct timespec *wait_ns)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -442,7 +446,7 @@ static void mmc_buffer(const struct mmcclk *clk,
|
|||||||
|
|
||||||
realtimize();
|
realtimize();
|
||||||
|
|
||||||
if (trigger != -1)
|
if (trigger)
|
||||||
wait_trigger(trigger, debounce, debounce_ns);
|
wait_trigger(trigger, debounce, debounce_ns);
|
||||||
if (wait_ns->tv_sec || wait_ns->tv_nsec)
|
if (wait_ns->tv_sec || wait_ns->tv_nsec)
|
||||||
if (nanosleep(wait_ns, NULL))
|
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,
|
static void send_buffer(const struct mmcclk *clk,
|
||||||
const uint8_t *buf, int nibbles, uint32_t mask,
|
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)
|
const struct timespec *wait_ns)
|
||||||
{
|
{
|
||||||
unsigned long phys;
|
unsigned long phys;
|
||||||
@ -493,7 +497,7 @@ static void send_buffer(const struct mmcclk *clk,
|
|||||||
|
|
||||||
|
|
||||||
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, const char *trigger,
|
||||||
int debounce, const struct timespec *debounce_ns,
|
int debounce, const struct timespec *debounce_ns,
|
||||||
const struct timespec *wait_ns)
|
const struct timespec *wait_ns)
|
||||||
{
|
{
|
||||||
@ -511,7 +515,7 @@ static void dma_pattern(const struct mmcclk *clk,
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (trigger != -1) {
|
if (trigger) {
|
||||||
PDFUNC = UBB_CLK;
|
PDFUNC = UBB_CLK;
|
||||||
IN(UBB_CLK);
|
IN(UBB_CLK);
|
||||||
}
|
}
|
||||||
@ -676,7 +680,7 @@ 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 [-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"
|
" [-w wait_s] [-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"
|
||||||
@ -688,7 +692,7 @@ static void usage(const char *name)
|
|||||||
" -p force interpretation of argument as pattern (and not file)\n"
|
" -p force interpretation of argument as pattern (and not file)\n"
|
||||||
" -q quiet. Don't pretty-print frequencies; don't report clock\n"
|
" -q quiet. Don't pretty-print frequencies; don't report clock\n"
|
||||||
" differences.\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"
|
" (default: start pattern immediately)\n"
|
||||||
" -w wait_s wait between trigger and sending the pattern\n\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"
|
" 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 active_rel;
|
||||||
int keep_clk = 1;
|
int keep_clk = 1;
|
||||||
uint8_t mask = 0xf;
|
uint8_t mask = 0xf;
|
||||||
int trigger = -1;
|
const char *trigger = NULL;
|
||||||
struct timespec debounce_ns;
|
struct timespec debounce_ns;
|
||||||
int debounce = 0, debounce_rel;
|
int debounce = 0, debounce_rel;
|
||||||
struct timespec wait_ns = { 0, 0 };
|
struct timespec wait_ns = { 0, 0 };
|
||||||
@ -727,6 +731,7 @@ int main(int argc, char **argv)
|
|||||||
char *end;
|
char *end;
|
||||||
int c;
|
int c;
|
||||||
unsigned long tmp;
|
unsigned long tmp;
|
||||||
|
const char *p;
|
||||||
|
|
||||||
while ((c = getopt(argc, argv, "cCd:f:i:m:pqt:w:")) != EOF)
|
while ((c = getopt(argc, argv, "cCd:f:i:m:pqt:w:")) != EOF)
|
||||||
switch (c) {
|
switch (c) {
|
||||||
@ -769,11 +774,11 @@ int main(int argc, char **argv)
|
|||||||
quiet = 1;
|
quiet = 1;
|
||||||
break;
|
break;
|
||||||
case 't':
|
case 't':
|
||||||
if (!strcmp(optarg, "0"))
|
trigger = optarg;
|
||||||
trigger = 0;
|
if (!*trigger)
|
||||||
else if (!strcmp(optarg, "1"))
|
usage(*argv);
|
||||||
trigger = 1;
|
for (p = trigger; *p; p++)
|
||||||
else
|
if (*p != '0' && *p != '1')
|
||||||
usage(*argv);
|
usage(*argv);
|
||||||
break;
|
break;
|
||||||
case 'w':
|
case 'w':
|
||||||
@ -789,14 +794,14 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
if (clkout && clk_only)
|
if (clkout && clk_only)
|
||||||
usage(*argv);
|
usage(*argv);
|
||||||
if ((clkout || clk_only) && trigger != -1)
|
if ((clkout || clk_only) && trigger)
|
||||||
usage(*argv);
|
usage(*argv);
|
||||||
|
|
||||||
switch (argc-optind) {
|
switch (argc-optind) {
|
||||||
case 0:
|
case 0:
|
||||||
if (clk_only)
|
if (clk_only)
|
||||||
break;
|
break;
|
||||||
if (clkout || force_pattern || trigger != -1)
|
if (clkout || force_pattern || trigger)
|
||||||
usage(*argv);
|
usage(*argv);
|
||||||
|
|
||||||
ubb_open(UBB_ALL);
|
ubb_open(UBB_ALL);
|
||||||
@ -857,7 +862,7 @@ int main(int argc, char **argv)
|
|||||||
perror("nanosleep");
|
perror("nanosleep");
|
||||||
if (pattern) {
|
if (pattern) {
|
||||||
mmcclk_stop();
|
mmcclk_stop();
|
||||||
ubb_close(mask << 10 | (trigger == -1 ? 0 : UBB_CLK));
|
ubb_close(mask << 10 | (trigger ? UBB_CLK : 0));
|
||||||
} else if (keep_clk) {
|
} else if (keep_clk) {
|
||||||
ubb_close(UBB_CLK);
|
ubb_close(UBB_CLK);
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
Reference in New Issue
Block a user