?? dstr_2d.c
字號:
/* ======================================================================== */
/* DMA Stream abstractions for Imaging. */
/* */
/* These streams tie a large "external" buffer with a small "internal" */
/* buffer, and provide a generalized interface for streaming data to/from */
/* the external buffer from/to the internal buffer. */
/* ======================================================================== */
#define MYDAT_2D1D 0
#define MYDAT_1D2D 1
#include "dstr_2d.h"
#include "csl_dat.h"
#include "csl_irq.h"
/*#define DSTR_DEBUG*/
#ifdef DSTR_DEBUG
# include <stdio.h>
# define dprintf(x) printf x ; fflush(stdout)
#else
# define dprintf(x)
#endif
/* ======================================================================== */
/* DSTR_OPEN -- Initialize a new DMA Stream object. */
/* ======================================================================== */
int dstr_open
(
dstr_t *dstr, /* DMA Stream structure. */
void *x_data, /* "External" data buffer. */
int x_size, /* Size of external data buffer. */
void *i_data, /* "Internal" data buffer. */
unsigned short i_size, /* Size of internal data buffer. */
unsigned short quantum, /* Size of a single transfer (get or put) */
unsigned short multiple, /* Number of lines to fetch */
unsigned short stride, /* Stride amount to increment ext. memory */
unsigned short w_size, /* Window size. Set to 1 for double buf. */
dstr_dir_t dir /* Direction (Input or Output) */
)
{
/* -------------------------------------------------------------------- */
/* Sanity check all of the arguments. We might consider providing */
/* a range of error codes here, rather than just -1, but for now, */
/* this will do. */
/* -------------------------------------------------------------------- */
if (!dstr || !x_data || !i_data || !quantum || !i_size || !multiple)
return -1;
if (dir == DSTR_OUTPUT && w_size != 1) return -2;
if ((2 * w_size * quantum * multiple) > i_size || w_size < 1)
{
dprintf(("i_size:%d, exp_size:%d \n",
i_size, (2 * w_size * quantum * multiple)));
return -3;
}
/* -------------------------------------------------------------------- */
/* Poke all the appropriate values into the structure. */
/* Make sure our external and internal sizes are rounded to multiples */
/* of our transfer quantum. */
/* -------------------------------------------------------------------- */
dstr->x_data = (char *) x_data;
dstr->x_size = x_size - (x_size % (stride * multiple));
dstr->i_data = (char *) i_data;
dstr->i_size = (2 * quantum * multiple * w_size);
dstr->i_ofs = 0;
dstr->quantum = quantum;
dstr->multiple = multiple;
dstr->w_size = (w_size * multiple *quantum);
dstr->stride = stride;
dstr->x_ofs = 0;
/* -------------------------------------------------------------------- */
/* If this is an external-to-internal transfer, start off the initial */
/* transfers to pipe up the stream. */
/* -------------------------------------------------------------------- */
if (dir == DSTR_INPUT)
{
unsigned id;
dprintf(("PREFETCH: ACTIVE = %d\n", dstr->x_ofs));
id = DAT_copy2d( DAT_2D1D,
(void*) (dstr->x_data),
(void*) (dstr->i_data),
dstr->quantum,
w_size * multiple,
dstr->stride);
dstr->x_ofs += (dstr->stride * multiple * w_size);
dstr->i_ofs += (dstr->quantum * multiple * w_size);
dstr->xfer_id = id;
}
else
/* -------------------------------------------------------------------- */
/* If this is an internal-to-external transfer, start our x_ofs at -1 */
/* to indicate that this stream has not yet been written to. */
/* -------------------------------------------------------------------- */
{
dstr->x_ofs = -1;
}
return 0;
}
/* ======================================================================== */
/* DSTR_GET -- Get the next buffer from a stream. */
/* ======================================================================== */
void * dstr_get(dstr_t *dstr)
{
unsigned id;
char *ready, *active;
int do_copy = 0;
/* -------------------------------------------------------------------- */
/* Remember the pointer to the currently ready buffer, and generate */
/* a pointer to the new active buffer. */
/* */
/* The ready buffer is always 'w_size' quanta behind the active */
/* buffer, modulo the total buffer size. The conditional handles */
/* the one wraparound case. The input offset marches from 'w_size - */
/* quantum' thru 'i_size - quantum'. */
/* */
/* We also decide whether an extra 'copy' transfer is issued here, */
/* based on the current value of i_ofs relative to the window size. */
/* -------------------------------------------------------------------- */
active = dstr->i_data + dstr->i_ofs;
do_copy = dstr->i_ofs >= (dstr->w_size + dstr->quantum);
if (dstr->i_ofs >= dstr->w_size)
ready = dstr->i_data + dstr->i_ofs - dstr->w_size; /* Normal */
else
ready = dstr->i_data + dstr->w_size; /* Wraparound */
/* -------------------------------------------------------------------- */
/* Update our input offset for the next transfer, and handle its */
/* wraparound case as well. */
/* -------------------------------------------------------------------- */
dstr->i_ofs += dstr->quantum;
if (dstr->i_ofs >= dstr->i_size)
dstr->i_ofs = dstr->w_size - dstr->quantum;
dprintf(("ACTIVE: %3d READY: %3d COPY: %d W_SIZE: %d\n",
active - i_data, ready - i_data, do_copy, w_size));
/* -------------------------------------------------------------------- */
/* Fire off a new transfer for the next buffer. */
/* -------------------------------------------------------------------- */
if (dstr->x_ofs < dstr->x_size)
{
id = DAT_copy((void *) (dstr->x_data + dstr->x_ofs),
(void *) (active),
dstr->quantum);
}
/* -------------------------------------------------------------------- */
/* Handle extra copy for sliding window. We replace the previous */
/* "ready" line with a copy of the new "active" line. In the case */
/* where we do this extra copy, we block on the extra copy only. */
/* -------------------------------------------------------------------- */
if (do_copy)
{
id = DAT_copy((void *) (active),
(void *) (ready - dstr->quantum),
dstr->quantum);
}
/* -------------------------------------------------------------------- */
/* Actually wait the ready buffer, to be sure it's truly ready. */
/* -------------------------------------------------------------------- */
DAT_wait(dstr->xfer_id);
/* -------------------------------------------------------------------- */
/* Remember the new transfer ID, and update our external data pointer. */
/* -------------------------------------------------------------------- */
dstr->xfer_id = id;
dstr->x_ofs += dstr->stride;
/* -------------------------------------------------------------------- */
/* Return the pointer to the ready buffer. We're done. */
/* -------------------------------------------------------------------- */
return (void*) ready;
}
/* ======================================================================== */
/* DSTR_PUT -- Write out the next buffer in a double-buffer. */
/* ======================================================================== */
void *dstr_put(dstr_t *dstr)
{
unsigned id;
char *ready;
/* -------------------------------------------------------------------- */
/* If x_ofs < 0, then we haven't started yet. Return the initial */
/* buffer pointer for the user to start writing data. */
/* -------------------------------------------------------------------- */
if (dstr->x_ofs < 0)
{
dstr->x_ofs = 0;
dstr->i_ofs = 0;
id = DAT_copy((void *) (dstr->i_data + dstr->i_ofs),
(void *) (dstr->x_data + dstr->x_ofs),
1);
dstr->xfer_id = id;
return (void *) dstr->i_data;
}
/* -------------------------------------------------------------------- */
/* Otherwise, fire off the copy for the dirty buffer. */
/* -------------------------------------------------------------------- */
if (dstr->x_ofs < dstr->x_size)
{
id = DAT_copy((void *) (dstr->i_data + dstr->i_ofs),
(void *) (dstr->x_data + dstr->x_ofs),
dstr->quantum);
}
/* -------------------------------------------------------------------- */
/* Generate the pointer to the newly ready buffer, and move our */
/* output's data pointer. */
/* -------------------------------------------------------------------- */
dstr->x_ofs += dstr->stride;
dstr->i_ofs ^= dstr->quantum;
ready = dstr->i_data + dstr->i_ofs;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -