www.pudn.com > motiotest.rar > 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# 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; /* -------------------------------------------------------------------- */ /* Wait for the "ready" buffer to truly be ready. */ /* -------------------------------------------------------------------- */ DAT_wait(dstr->xfer_id); /* -------------------------------------------------------------------- */ /* Remember our dirty buffer's transfer ID. */ /* -------------------------------------------------------------------- */ dstr->xfer_id = id; /* -------------------------------------------------------------------- */ /* Return the pointer to the readied output buffer. */ /* -------------------------------------------------------------------- */ return (void *) ready; } /* ======================================================================== */ /* DSTR_GET -- Get the next buffer from a stream. */ /* ======================================================================== */ void *dstr_get_2D(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 * dstr->multiple)); 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 * dstr->multiple); if (dstr->i_ofs >= dstr->i_size) dstr->i_ofs = dstr->w_size - (dstr->quantum * dstr->multiple); 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_copy2d( DAT_2D1D, (void *) (dstr->x_data + dstr->x_ofs), (void *) (active), dstr->quantum, dstr->multiple, dstr->stride); } /* -------------------------------------------------------------------- */ /* 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->multiple)), dstr->quantum * dstr->multiple); } /* -------------------------------------------------------------------- */ /* 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 * dstr->multiple); /* -------------------------------------------------------------------- */ /* 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_2D(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_copy2d( DAT_1D2D, (void *) (dstr->i_data + dstr->i_ofs), (void *) (dstr->x_data + dstr->x_ofs), dstr->quantum, dstr->multiple, dstr->stride); } /* -------------------------------------------------------------------- */ /* Generate the pointer to the newly ready buffer, and move our */ /* output's data pointer. */ /* -------------------------------------------------------------------- */ dstr->x_ofs += dstr->stride * dstr->multiple; dstr->i_ofs ^= (dstr->quantum * dstr->multiple); ready = dstr->i_data + dstr->i_ofs; /* -------------------------------------------------------------------- */ /* Wait for the "ready" buffer to truly be ready. */ /* -------------------------------------------------------------------- */ DAT_wait(dstr->xfer_id); /* -------------------------------------------------------------------- */ /* Remember our dirty buffer's transfer ID. */ /* -------------------------------------------------------------------- */ dstr->xfer_id = id; /* -------------------------------------------------------------------- */ /* Return the pointer to the readied output buffer. */ /* -------------------------------------------------------------------- */ return (void *) ready; } /* ======================================================================== */ /* DSTR_REWUIND -- Initialize a new DMA Stream object. */ /* ======================================================================== */ int dstr_rewind ( dstr_t *dstr, /* DMA Stream structure. */ void *x_data, /* "External" data buffer. */ dstr_dir_t dir, /* Direction (Input or Output) */ unsigned short w_size /* Window size. Set to 1 for double buf. */ ) { /* -------------------------------------------------------------------- */ /* 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->i_ofs = 0; dstr->x_ofs = 0; if (dir == DSTR_OUTPUT) { dstr->x_ofs = -1; DAT_wait(dstr->xfer_id); } /* -------------------------------------------------------------------- */ /* 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 * dstr->multiple, dstr->stride); dstr->x_ofs += (dstr->stride * dstr->multiple * w_size); dstr->i_ofs += (dstr->quantum * dstr->multiple * w_size); dstr->xfer_id = id; } return 0; } /*--------------------------------------------------------------------------*/ /* Function obtains transfer id and makes sure that DAT_wait completes. */ /*--------------------------------------------------------------------------*/ void dstr_close(dstr_t *dstr) { unsigned id; id = dstr->xfer_id; // DAT_wait(id); } /* ======================================================================== */ /* End of file: dstr.c */ /* ------------------------------------------------------------------------ */ /* Copyright (c) 2000 Texas Instruments, Incorporated. */ /* All Rights Reserved. */ /* ======================================================================== */