mirror of
git://projects.qi-hardware.com/ben-blinkenlights.git
synced 2024-11-23 23:40:36 +02:00
ubb-la/ubb-la.c: add command-line options, keyboard abort
This commit is contained in:
parent
bac21bf8cb
commit
62284fb78e
117
ubb-la/ubb-la.c
117
ubb-la/ubb-la.c
@ -13,6 +13,7 @@
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <assert.h>
|
||||
@ -26,6 +27,8 @@
|
||||
|
||||
#define DMA 5
|
||||
|
||||
#define KEY_MASK 0x5fc0000
|
||||
|
||||
|
||||
/* ----- Enable/disable interrupts ----------------------------------------- */
|
||||
|
||||
@ -103,7 +106,8 @@ static void wait_dma_done(void)
|
||||
/* ----- MMC control ------------------------------------------------------- */
|
||||
|
||||
|
||||
static void xfer(unsigned long buf, int nibbles)
|
||||
static int xfer(unsigned long buf, int nibbles,
|
||||
uint32_t trigger, uint32_t mask)
|
||||
{
|
||||
dma_init();
|
||||
dma_setup(buf, nibbles);
|
||||
@ -127,9 +131,9 @@ static void xfer(unsigned long buf, int nibbles)
|
||||
|
||||
disable_interrupts();
|
||||
|
||||
while (!(PDPIN & UBB_DAT1));
|
||||
|
||||
// sleep(1); /* @@@ wait here for trigger */
|
||||
while ((PDPIN & mask) != trigger)
|
||||
if ((PDPIN & KEY_MASK) != KEY_MASK)
|
||||
goto quit;
|
||||
|
||||
DCS(DMA) =
|
||||
DCS_NDES | /* no descriptor */
|
||||
@ -139,16 +143,23 @@ static void xfer(unsigned long buf, int nibbles)
|
||||
|
||||
wait_dma_done();
|
||||
|
||||
printf("MSC_STAT = %08x\n", MSC_STAT);
|
||||
//printf("MSC_STAT = %08x\n", MSC_STAT);
|
||||
|
||||
dma_cleanup();
|
||||
|
||||
return 1;
|
||||
|
||||
quit:
|
||||
enable_interrupts();
|
||||
dma_cleanup();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void do_buf(int nibbles)
|
||||
static int do_buf(int nibbles, uint32_t trigger, uint32_t mask)
|
||||
{
|
||||
uint8_t *buf = physmem_malloc(4095);
|
||||
uint8_t *buf = physmem_malloc(4096);
|
||||
struct physmem_vec vec;
|
||||
int n, i;
|
||||
uint8_t v, last = 0xff;
|
||||
@ -159,15 +170,16 @@ static void do_buf(int nibbles)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
memset(buf, 0, 4095);
|
||||
physmem_flush(buf, 4095);
|
||||
memset(buf, 0, 4096);
|
||||
physmem_flush(buf, 4096);
|
||||
|
||||
n = physmem_xlat((void *) buf, nibbles >> 1, &vec, 1);
|
||||
if (n != 1) {
|
||||
fprintf(stderr, "physmem_xlat_vec: expected 1, got %d\n", n);
|
||||
exit(1);
|
||||
}
|
||||
xfer(vec.addr, nibbles);
|
||||
if (!xfer(vec.addr, nibbles, trigger, mask))
|
||||
return 0;
|
||||
|
||||
for (i = 0; i != nibbles; i++) {
|
||||
v = (buf[i >> 1] >> (4*(~i & 1))) & 0xf;
|
||||
@ -192,9 +204,18 @@ static void do_buf(int nibbles)
|
||||
printf("%X\n", last);
|
||||
else
|
||||
printf("%X{%d}\n", last, count);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* ----- Command-line processing ------------------------------------------- */
|
||||
|
||||
|
||||
/*
|
||||
* Among equal bus rates, pick the configuration with the fastest MMC clock.
|
||||
* It'll save a few nanoseconds.
|
||||
*/
|
||||
|
||||
static void frequency(struct mmcclk *clk, int hz)
|
||||
{
|
||||
struct mmcclk mmc;
|
||||
@ -202,31 +223,97 @@ static void frequency(struct mmcclk *clk, int hz)
|
||||
mmcclk_first(&mmc, 0);
|
||||
*clk = mmc;
|
||||
while (mmcclk_next(&mmc))
|
||||
if (fabs(clk->bus_clk_hz-hz) > fabs(mmc.bus_clk_hz-hz))
|
||||
if (fabs(clk->bus_clk_hz-hz) > fabs(mmc.bus_clk_hz-hz) ||
|
||||
(fabs(clk->bus_clk_hz-hz) == fabs(mmc.bus_clk_hz-hz) &&
|
||||
clk->clkdiv > mmc.clkdiv))
|
||||
*clk = mmc;
|
||||
}
|
||||
|
||||
|
||||
static unsigned long xlat_pins(unsigned long pins)
|
||||
{
|
||||
if (pins & ~0x1fUL) {
|
||||
fprintf(stderr, "invalid trigger set/mask: 0x%lx\n", pins);
|
||||
exit(1);
|
||||
}
|
||||
pins <<= 10;
|
||||
if (pins & (0x10 << 10))
|
||||
pins = (pins ^ (0x10 << 10)) | UBB_CLK;
|
||||
return pins;
|
||||
}
|
||||
|
||||
|
||||
static void usage(const char *name)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"usage: %s [-C] [-t pattern/mask] [-f frequency_MHz]\n\n"
|
||||
" -C output the MMC clock on CLK/TRIG (for debugging)\n"
|
||||
" -f freq_MHz select the specified frequency (default; 1 MHz)\n"
|
||||
" -t pattern/mask start capture at the specified pattern (DAT0 = 1, etc.,\n"
|
||||
" CLK = 16). Default: any change on TRIG.\n"
|
||||
, name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
double freq_mhz = 1;
|
||||
unsigned long trigger = 1, mask = 0;
|
||||
int clkout = 0;
|
||||
struct mmcclk clk;
|
||||
char *end;
|
||||
int c, res;
|
||||
|
||||
while ((c = getopt(argc, argv, "Cf:t:")) != EOF)
|
||||
switch (c) {
|
||||
case 'C':
|
||||
clkout = 1;
|
||||
break;
|
||||
case 'f':
|
||||
freq_mhz = strtod(optarg, &end);
|
||||
if (*end)
|
||||
usage(*argv);
|
||||
break;
|
||||
case 't':
|
||||
trigger = strtoul(optarg, &end, 0);
|
||||
if (*end != '/')
|
||||
usage(*argv);
|
||||
mask = strtoul(end+1, &end, 0);
|
||||
if (*end)
|
||||
usage(*argv);
|
||||
trigger = xlat_pins(trigger);
|
||||
mask = xlat_pins(mask);
|
||||
break;
|
||||
default:
|
||||
usage(*argv);
|
||||
}
|
||||
|
||||
if (optind != argc)
|
||||
usage(*argv);
|
||||
|
||||
ubb_open(UBB_ALL);
|
||||
PDFUNS = UBB_DAT0 | UBB_DAT1 | UBB_DAT2 | UBB_DAT3;
|
||||
if (clkout)
|
||||
PDFUNS = UBB_CLK;
|
||||
OUT(UBB_CMD);
|
||||
CLR(UBB_CMD);
|
||||
PDFUNC = UBB_CMD;
|
||||
|
||||
frequency(&clk, atoi(argv[1]));
|
||||
printf("bus %g MHz (MSC %g MHz)\n", clk.bus_clk_hz/1e6,
|
||||
frequency(&clk, 1e6*freq_mhz);
|
||||
fprintf(stderr, "bus %g MHz controller %g MHz\n", clk.bus_clk_hz/1e6,
|
||||
clk.sys_clk_hz/(clk.clkdiv+1.0)/1e6);
|
||||
mmcclk_start(&clk);
|
||||
|
||||
do_buf(6400);
|
||||
if (trigger == 1) {
|
||||
trigger = ~PDPIN & UBB_CLK;
|
||||
mask = UBB_CLK;
|
||||
}
|
||||
|
||||
res = !do_buf(8128, trigger, mask);
|
||||
|
||||
mmcclk_stop();
|
||||
ubb_close(UBB_ALL);
|
||||
|
||||
return 0;
|
||||
return res;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user