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.                           */ 
/* ======================================================================== */