mirror of
git://projects.qi-hardware.com/ben-blinkenlights.git
synced 2024-11-24 00:40:36 +02:00
ubb-la/ubb-la.c: option -n N to enter experimental multi-buffer mode (WIP)
This commit is contained in:
parent
96ae3319c5
commit
37a219b0b9
105
ubb-la/ubb-la.c
105
ubb-la/ubb-la.c
@ -99,6 +99,7 @@ static void dma_setup(unsigned long buf, int nibbles)
|
|||||||
{
|
{
|
||||||
assert(!(nibbles & 63));
|
assert(!(nibbles & 63));
|
||||||
|
|
||||||
|
/* need to reset DSA, DTA, DTC when done. uncertain about DCS */
|
||||||
DCS(DMA) = DCS_NDES; /* no-descriptor transfer */
|
DCS(DMA) = DCS_NDES; /* no-descriptor transfer */
|
||||||
DSA(DMA) = REG_PADDR(MSC_RXFIFO); /* source */
|
DSA(DMA) = REG_PADDR(MSC_RXFIFO); /* source */
|
||||||
DTA(DMA) = buf; /* destination */
|
DTA(DMA) = buf; /* destination */
|
||||||
@ -166,6 +167,61 @@ quit:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void xfers(unsigned long *bufs, int n_bufs, int nibbles)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
dma_init();
|
||||||
|
|
||||||
|
MSC_STRPCL = MSC_STRPCRL_START_CLOCK; /* start the bus clock */
|
||||||
|
MSC_RESTO = MSC_RESTO_MASK; /* maximum response time-out */
|
||||||
|
MSC_RDTO = MSC_RDTO_MASK;
|
||||||
|
MSC_BLKLEN = nibbles >> 1;
|
||||||
|
|
||||||
|
MSC_CMDAT =
|
||||||
|
MSC_CMDAT_BUS_WIDTH_4 << MSC_CMDAT_BUS_WIDTH_SHIFT |
|
||||||
|
MSC_CMDAT_DMA_EN | /* DMA */
|
||||||
|
MSC_CMDAT_DATA_EN | /* with data transfer */
|
||||||
|
MSC_CMDAT_RESPONSE_FORMAT_NONE; /* no response required */
|
||||||
|
|
||||||
|
disable_interrupts();
|
||||||
|
|
||||||
|
OUT(UBB_CMD);
|
||||||
|
dma_setup(bufs[0], nibbles);
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
MSC_STRPCL = MSC_STRPCRL_START_OP;
|
||||||
|
|
||||||
|
while (MSC_STAT & MSC_STAT_DATA_FIFO_EMPTY);
|
||||||
|
|
||||||
|
IN(UBB_CMD);
|
||||||
|
|
||||||
|
DCS(DMA) =
|
||||||
|
DCS_NDES | /* no descriptor */
|
||||||
|
DCS_CTE; /* enable channel */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @@@ We could enable interrupts while waiting, particularly
|
||||||
|
* at low sample rates, as long as the probability of missing
|
||||||
|
* the end of the DMA transfer is acceptably low.
|
||||||
|
*/
|
||||||
|
wait_dma_done();
|
||||||
|
|
||||||
|
if (++i == n_bufs)
|
||||||
|
break;
|
||||||
|
|
||||||
|
OUT(UBB_CMD);
|
||||||
|
dma_setup(bufs[i], nibbles);
|
||||||
|
|
||||||
|
while (!(MSC_STAT & MSC_STAT_DATA_TRAN_DONE));
|
||||||
|
}
|
||||||
|
|
||||||
|
enable_interrupts();
|
||||||
|
|
||||||
|
dma_cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void print_samples(FILE *file, uint8_t *buf, int skip, int nibbles)
|
static void print_samples(FILE *file, uint8_t *buf, int skip, int nibbles)
|
||||||
{
|
{
|
||||||
uint8_t v, last = 0xff;
|
uint8_t v, last = 0xff;
|
||||||
@ -225,6 +281,38 @@ static int do_buf(int nibbles, uint32_t trigger, uint32_t mask)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void do_bufs(int n_bufs, int nibbles)
|
||||||
|
{
|
||||||
|
uint8_t *bufs[n_bufs];
|
||||||
|
struct physmem_vec vecs[n_bufs];
|
||||||
|
unsigned long addrs[n_bufs];
|
||||||
|
int i,n;
|
||||||
|
|
||||||
|
if (mlockall(MCL_CURRENT | MCL_FUTURE)) {
|
||||||
|
perror("mlockall");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i != n_bufs; i++) {
|
||||||
|
bufs[i] = physmem_malloc(4096);
|
||||||
|
memset(bufs[i], 0, 4096);
|
||||||
|
physmem_flush(bufs[i], 4096);
|
||||||
|
|
||||||
|
n = physmem_xlat(bufs[i], nibbles >> 1, vecs+i, 1);
|
||||||
|
if (n != 1) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"physmem_xlat_vec: expected 1, got %d\n", n);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
addrs[i] = vecs[i].addr;
|
||||||
|
}
|
||||||
|
xfers(addrs, n_bufs, nibbles);
|
||||||
|
|
||||||
|
for (i = 0; i != n_bufs; i++)
|
||||||
|
print_samples(stdout, bufs[i], INITIAL_SKIP, nibbles);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ----- Command-line processing ------------------------------------------- */
|
/* ----- Command-line processing ------------------------------------------- */
|
||||||
|
|
||||||
|
|
||||||
@ -263,9 +351,11 @@ static unsigned long xlat_pins(unsigned long pins)
|
|||||||
static void usage(const char *name)
|
static void usage(const char *name)
|
||||||
{
|
{
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"usage: %s [-C] [-t pattern/mask] [-f frequency_MHz]\n\n"
|
"usage: %s [-C] [-t pattern/mask] [-f frequency_MHz] [-n N]\n\n"
|
||||||
" -C output the MMC clock on CLK/TRIG (for debugging)\n"
|
" -C output the MMC clock on CLK/TRIG (for debugging)\n"
|
||||||
" -f freq_MHz select the specified frequency (default; 1 MHz)\n"
|
" -f freq_MHz select the specified frequency (default; 1 MHz)\n"
|
||||||
|
" -n N capture N buffers worth of samples without waiting for a\n"
|
||||||
|
" trigger\n"
|
||||||
" -t pattern/mask start capture at the specified pattern (DAT0 = 1, etc.,\n"
|
" -t pattern/mask start capture at the specified pattern (DAT0 = 1, etc.,\n"
|
||||||
" CLK = 16). Default: any change on TRIG.\n"
|
" CLK = 16). Default: any change on TRIG.\n"
|
||||||
, name);
|
, name);
|
||||||
@ -277,12 +367,13 @@ int main(int argc, char **argv)
|
|||||||
{
|
{
|
||||||
double freq_mhz = 1;
|
double freq_mhz = 1;
|
||||||
unsigned long trigger = 1, mask = 0;
|
unsigned long trigger = 1, mask = 0;
|
||||||
|
unsigned long multi = 0;
|
||||||
int clkout = 0;
|
int clkout = 0;
|
||||||
struct mmcclk clk;
|
struct mmcclk clk;
|
||||||
char *end;
|
char *end;
|
||||||
int c, res;
|
int c, res;
|
||||||
|
|
||||||
while ((c = getopt(argc, argv, "Cf:t:")) != EOF)
|
while ((c = getopt(argc, argv, "Cf:n:t:")) != EOF)
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'C':
|
case 'C':
|
||||||
clkout = 1;
|
clkout = 1;
|
||||||
@ -292,6 +383,11 @@ int main(int argc, char **argv)
|
|||||||
if (*end)
|
if (*end)
|
||||||
usage(*argv);
|
usage(*argv);
|
||||||
break;
|
break;
|
||||||
|
case 'n':
|
||||||
|
multi = strtoul(optarg, &end, 0);
|
||||||
|
if (*end)
|
||||||
|
usage(*argv);
|
||||||
|
break;
|
||||||
case 't':
|
case 't':
|
||||||
trigger = strtoul(optarg, &end, 0);
|
trigger = strtoul(optarg, &end, 0);
|
||||||
if (*end != '/')
|
if (*end != '/')
|
||||||
@ -327,7 +423,12 @@ int main(int argc, char **argv)
|
|||||||
mask = UBB_CLK;
|
mask = UBB_CLK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!multi) {
|
||||||
res = !do_buf(8128, trigger, mask);
|
res = !do_buf(8128, trigger, mask);
|
||||||
|
} else {
|
||||||
|
do_bufs(multi, 8128);
|
||||||
|
res = 0;
|
||||||
|
}
|
||||||
|
|
||||||
mmcclk_stop();
|
mmcclk_stop();
|
||||||
ubb_close(UBB_ALL);
|
ubb_close(UBB_ALL);
|
||||||
|
Loading…
Reference in New Issue
Block a user