dcmpitst.c



/* --------------------------------------------------------------------
File dcmpitst.c

Source code for dcmpftst.860
Run a test of the SDL ROI decompressor board with interlaced output.
Compile and link by running hcidcmp script.

-------------------------------------------------------------------- */

/* ------------------------ Rev history -------------------------------

LRE 2-19-96 Created
LRE 2-22-96 Ready to run?

----------------------------------------------------------------------- */

/* ---------------------- includes ------------------------------------ */

#include "dcmpitst.h"


/* ---------------------- prototypes --------------------------------- */


void setup_decomps(volatile unsigned short int **) ;
void load_decomps(char *, volatile unsigned short int **, long, long) ;
void exit_no_fn() ; 
void print_msg(int) ;
void exit_bad(long, int) ;
void * setup_cmp_frm_buf(SMB_handle *) ;
ssize_t ld_cmp_frame(char *, void *) ;
void  setup_dcmp_frm_bufs(void **,SMB_handle *) ;
DEV_handle attach_rino(char *) ;
DX_transfer setup_cmp_frm_out_xfr(SMB_handle, DEV_handle, ssize_t) ;
DX_transfer setup_dcmp_frms_in_mstr_xfr(SMB_handle *,DEV_handle) ;
DX_transfer setup_dcmp_frms_in_slv_xfr(SMB_handle *,DEV_handle) ;
void reset_rout(DEV_handle) ;
void reset_rint(DEV_handle) ;
void wr_output_file(void **,char *) ;

/* -------------------- file globals -------------------------------- */

     /* Makes sense to use global verbosity */
long        verbose = FALSE;

#ifdef  TST
long        test = TRUE ;         
#else
long        test = FALSE ;  
#endif

/* ----------------- Start of main ---------------------------------- */

int main (int argc, char **argv)

  {


    long        rc ;
    long        lin_flag = FALSE ;
    long        half_flag = FALSE ;
    char        *decomp_ld_fn = 0x0 ;
    char        *cmp_frm_fn = 0x0 ;
    char        *out_fn = 0x0 ;
    volatile unsigned short int  *dcmp_cntl_word_ptrs[2] = {NULL, NULL} ;
    void        *cmp_frm_buf_ptr ;
    SMB_handle  cmp_frm_mem_handle ;
    ssize_t     cmp_frm_size ;
    void        *dcmp_frm_buf_ptrs[NUM_DCMP_FRM_BUFS] ;
    SMB_handle  dcmp_frm_mem_handles[NUM_DCMP_FRM_BUFS] ;
    DEV_handle  rino_dev_handle ;
    DEV_handle  rint_1_dev_handle ;
    DEV_handle  rint_2_dev_handle = 0x0 ;
    DX_transfer cmp_file_out_xfr ;
    DX_transfer rint_1_transfer ;
    DX_transfer rint_2_transfer = 0x0 ;

    TMR_ts      time1, time2 ;
    TMR_timespec elapsed ;

       /* get filenames */
    if (argc < 4) exit_no_fn() ;
    
    decomp_ld_fn = argv[1] ;
    cmp_frm_fn = argv[2] ;
    out_fn = argv[3] ;

        /* Check for verbosity and/or linear mode */
    if (argc > 4) {
      for(rc=4;rc<argc;rc++) {
        if (strcmp("-v", argv[rc]) == 0)
           verbose = TRUE;
        else if(strcmp("-l",argv[rc]) == 0)
            lin_flag = TRUE ;
        else if(strcmp("-h",argv[rc]) == 0)
            half_flag = TRUE ;
        }
     }

    CHK_VERB(START_MSG_ID) 

    /* ------- initialize --------------- */
    setup_decomps(dcmp_cntl_word_ptrs) ; 
    load_decomps(decomp_ld_fn, dcmp_cntl_word_ptrs,lin_flag,half_flag) ; 
    cmp_frm_buf_ptr = setup_cmp_frm_buf(&cmp_frm_mem_handle) ;
    cmp_frm_size = ld_cmp_frame(cmp_frm_fn,cmp_frm_buf_ptr) ;
    setup_dcmp_frm_bufs(dcmp_frm_buf_ptrs,dcmp_frm_mem_handles) ;
    rino_dev_handle = attach_rino(ROUT_NAME) ;
    rint_1_dev_handle = attach_rino(RINT_NAME_1) ;
    if(!test) rint_2_dev_handle = attach_rino(RINT_NAME_2) ;
       /* --------- reset io ----------------- */
       CHK_VERB(RESETTING_IO_MSG_ID) 
       reset_rout(rino_dev_handle) ;
       reset_rint(rint_1_dev_handle) ;
       if(!test) reset_rint(rint_2_dev_handle) ;
    cmp_file_out_xfr = setup_cmp_frm_out_xfr(cmp_frm_mem_handle, 
                rino_dev_handle, cmp_frm_size) ;
    rint_1_transfer = setup_dcmp_frms_in_mstr_xfr(
                    dcmp_frm_mem_handles,rint_1_dev_handle) ;
    if(!test) rint_2_transfer = setup_dcmp_frms_in_slv_xfr(
                    dcmp_frm_mem_handles,rint_2_dev_handle) ;
    else rint_2_transfer = setup_dcmp_frms_in_slv_xfr(
                    dcmp_frm_mem_handles,rint_1_dev_handle) ;

    /* ----- done initalizing ------------ */

    /* turn on decompressor boards */
    CHK_VERB(STRT_DCMP_MSG_ID) 
    dcmp_cntl_word_ptrs[0][CNTL_WORD_OFFSET] |= SET_FRM_VALID ;
    if(!test) dcmp_cntl_word_ptrs[1][CNTL_WORD_OFFSET]
                 |= SET_FRM_VALID ;

    /* --------- start io ----------------- */
    CHK_VERB(STRT_IO_MSG_ID) 

    rc = tmr_timestamp(&time1) ;

    rc = dx_start(rint_1_transfer,0) ;
    CHK_RC(CE_SUCCESS,RINT_1_STRT_ERR)
    if(!test) {
        rc = dx_start(rint_2_transfer,0) ;
        CHK_RC(CE_SUCCESS,RINT_2_STRT_ERR)
      }

    rc = dx_start(cmp_file_out_xfr,0) ; 
    CHK_RC(CE_SUCCESS,ROUT_STRT_ERR)
    CHK_VERB(IO_STRTED_MSG_ID) 

    /* --------- wait for output done ----------------- */

    CHK_VERB(WAIT_OUT_DONE_MSG_ID) 
    rc = dx_get_status(cmp_file_out_xfr,DX_POLL,0) ; 
    CHK_RC(CE_SUCCESS,WAIT_OUT_DONE_ERR)

    /* reset decompressor boards */
    CHK_VERB(RESET_DCMP_MSG_ID) 
    dcmp_cntl_word_ptrs[0][CNTL_WORD_OFFSET] &= !SET_FRM_VALID ;
    if(!test) dcmp_cntl_word_ptrs[1][CNTL_WORD_OFFSET] 
                    &= !SET_FRM_VALID ;

    /* --------- wait for input done ----------------- */

    CHK_VERB(WAIT_IN_DONE_MSG_ID) 
    rc = dx_get_status(rint_1_transfer,DX_POLL,0) ;
    CHK_RC(CE_SUCCESS,WAIT_IN_1_DONE_ERR)
    if(!test) {
        rc = dx_get_status(rint_2_transfer,DX_POLL,0) ;
        CHK_RC(CE_SUCCESS,WAIT_IN_2_DONE_ERR)
      }

    rc = tmr_timestamp(&time2) ;
    rc = tmr_diff(time1,time2,0,&elapsed) ;
    printf("IO elapsed time = %d.%09d seconds.\n",
        elapsed.tv_sec,elapsed.tv_nsec) ;

    /* ---- write the decompressed frame to file ------ */

    wr_output_file(dcmp_frm_buf_ptrs,out_fn) ;

    CHK_VERB(ALL_DONE_MSG_ID) 
    return( 0 ) ;

  }  /* end main */

/* ----------------------- End of main ----------------------------- */

/* -------------------- Start of setup_decomps ----------------------- */

void setup_decomps(
         volatile unsigned short int *dcmp_cntl_word_ptrs[]) {

long                rc, i, n = 2 ;
DEV_handle          dcmp_dev_handle ;
SMB_handle          dcmp_mem_handle ;
SMB_mapping_handle  dcmp_map_handle ;
SMB_mapping_info    dcmp_map_info ;
char                brd_vme_name[2][20] = {
                            DCMP_1_VME_NAME,
                            DCMP_2_VME_NAME } ;
    
    for(i=0;i<n;i++) {

    /* attach decompressor VME registers & code book mem */
    CHK_VERB(STRT_VME_ATTACH_MSG_ID) 
    rc = dev_attach(brd_vme_name[i],0,&dcmp_dev_handle) ;
    CHK_RC(CE_SUCCESS,DCMP_MEM_ATTACH_ERR)
    CHK_VERB(VME_ATTACHED_MSG_ID) 

    /* create decompressor VME registers & code book mem */
    CHK_VERB(STRT_VME_CREATE_MSG_ID) 
    rc = smb_create(brd_vme_name[i], SMB_RAW | SMB_GLOBAL, DCMP_BD_SIZE,
                MEM_DEVICE, dcmp_dev_handle, 0, &dcmp_mem_handle ) ;
    CHK_RC(CE_SUCCESS,DCMP_MEM_CREATE_ERR)
    CHK_VERB(VME_CREATED_MSG_ID)
 
    /* map decompressor VME registers & code book mem to proc mem */
    CHK_VERB(STRT_VME_MAP_MSG_ID) 
    rc = smb_map(dcmp_mem_handle,0,0,0,0,0,0,
                &dcmp_map_handle,&dcmp_map_info ) ;
    CHK_RC(CE_SUCCESS,DCMP_MEM_MAP_ERR)
    CHK_VERB(VME_MAPPED_MSG_ID)

    dcmp_cntl_word_ptrs[i] = 
                (volatile unsigned short int *) dcmp_map_info.process.vaddr ;

    } /* end for i */

    return ;

  }
/* ------------------ end of setup_decomps -------------------------- */

/* -------------------- Start of load_decomps ----------------------- */

void load_decomps(char * ld_fn,
         volatile unsigned short int *dcmp_cntl_word_ptrs[], 
            long lin_flag, long half_flag) {

long                rc, i, j, k, m, n=2, asic ;
int                 filedes ;
ssize_t             read_cnt ;
char                *rd_ptr ; 
unsigned short int  *reg_ptr ;
unsigned short int  cntl_word = (SET_INIT_MODE | SET_MS_MODE) ;

TMR_ts      time1, time2 ;
TMR_timespec elapsed ;

    rd_ptr =  malloc(DCMP_BD_SIZE) ; 
    if(rd_ptr == 0) exit_bad(errno, DCMP_MALLOC_ERR) ;
    reg_ptr = (unsigned short int *) rd_ptr ;

    rc = tmr_timestamp(&time1) ;


    /* open binary data file */
    CHK_VERB(STRT_DCMP_LD_FILE_OPEN_MSG_ID) 
    filedes = open(ld_fn,O_RDONLY) ;
    if (filedes < 0) exit_bad(errno, DCMP_LD_FILE_OPEN_ERR) ;
    CHK_VERB(DCMP_LD_FILE_OPENED_MSG_ID) 
   

    /* read binary file data into buffer memory */

    CHK_VERB(STRT_BIN_LD_MSG_ID) 
    read_cnt = read(filedes, rd_ptr, DCMP_BD_SIZE) ; 
    if (read_cnt < 0) exit_bad(errno, DCMP_LD_FILE_RD_ERR) ;
    if (read_cnt != DCMP_BD_SIZE) 
                exit_bad(errno, DCMP_SHRT_FILE_ERR) ;
    CHK_VERB(BIN_LDED_MSG_ID) 

    /* close binary data file */
    CHK_VERB(STRT_DCMP_LD_FILE_CLOSE_MSG_ID) 
    rc = close(filedes) ;
    if (rc < 0) exit_bad(errno, DCMP_LD_FILE_CLOSE_ERR) ;
    CHK_VERB(DCMP_LD_FILE_CLOSED_MSG_ID) 

    rc = tmr_timestamp(&time2) ;
    rc = tmr_diff(time1,time2,0,&elapsed) ;
    printf("Decomp bin file ld elapsed time = %d.%09d seconds.\n",
        elapsed.tv_sec,elapsed.tv_nsec) ;

    /* load decompressors */

    if(lin_flag) cntl_word |= SET_LINEAR ;

    for(i=0;i<n;i++) {

        /* Set control word */
      if(i != 0) cntl_word |= SET_SLAVE ;
      dcmp_cntl_word_ptrs[i][CNTL_WORD_OFFSET] = cntl_word ;

        /* Load asic's */
      for(asic=0;asic<4;asic++) {

            /* index to asic */
        m = (asic * 0x4000) ;

            /* Load 1st part of asic */
        for(j=0;j<MI_COEF1_OFFSET;j++) {
         dcmp_cntl_word_ptrs[i][j + m] = reg_ptr[j + m] ;
          }

            /* Load 1st three coefficient sets */
        for(j=MI_COEF1_OFFSET;j<=MI_COEF3_OFFSET;j+=4) {
            for(k=0;k<4;k++) {
             dcmp_cntl_word_ptrs[i][COEF_REGA_OFFSET + k +m] =
                 reg_ptr[j + k +m] ;
             }
            dcmp_cntl_word_ptrs[i][j + m] = 0 ;
          }

             /* Load 2nd three coefficient sets */
       for(j=MI_COEF4_OFFSET;j<=MI_COEF6_OFFSET;j+=4) {
            for(k=0;k<4;k++) {
             dcmp_cntl_word_ptrs[i][COEF_REGA_OFFSET + k + m] =
                 reg_ptr[j + k + m] ;
             }
            dcmp_cntl_word_ptrs[i][j + m] = 0 ;
          }

            /* Load rest of asic */
        for(j=(COEF_REGD_OFFSET + 1);j<STATUS_OFFSET;j++) {
         dcmp_cntl_word_ptrs[i][j + m] = reg_ptr[j + m] ;
          }
        } /* End load asic's */

            /* Load control */
        for(j=STATUS_OFFSET;j<CNTL_WORD_OFFSET;j++) {
         dcmp_cntl_word_ptrs[i][j] = reg_ptr[j] ;
          }

        for(j=(CNTL_WORD_OFFSET +1);j<SEQ_VALID_OFFSET;j++) {
         dcmp_cntl_word_ptrs[i][j] = reg_ptr[j] ;
          }

        if(half_flag)
          dcmp_cntl_word_ptrs[i][SEQ_VALID_OFFSET] = HALF_RES ;
        else
          dcmp_cntl_word_ptrs[i][SEQ_VALID_OFFSET] = FULL_RES ;

        for(j=(SEQ_VALID_OFFSET +1);j<LINE_LNGTH_OFFSET;j++) {
         dcmp_cntl_word_ptrs[i][j] = reg_ptr[j] ;
          }

        if(lin_flag)
          dcmp_cntl_word_ptrs[i][LINE_LNGTH_OFFSET] = LIN_LINE_LNGTH ;
        else
          dcmp_cntl_word_ptrs[i][LINE_LNGTH_OFFSET] = AREA_LINE_LNGTH ;

            /* Load LUT */
        for(j=LUT_OFFSET;j<(DCMP_BD_SIZE / 2);j++) {
         dcmp_cntl_word_ptrs[i][j] = reg_ptr[j] ;
          }

          /* Take decompressor board out initialization */
        dcmp_cntl_word_ptrs[i][CNTL_WORD_OFFSET] &= 
                (!SET_FRM_VALID & !SET_INIT_MODE) ;

    } /* end for i */

    free(rd_ptr) ;
       
    return ;

  }
/* ------------------ end of load_decomps -------------------------- */


/* ----------------- Start of setup_cmp_frm_buf ------------------- */

void * setup_cmp_frm_buf(SMB_handle *ret_cmp_frm_mem_handle) {

long                rc ;
SMB_handle          cmp_frm_mem_handle ;
SMB_mapping_handle  cmp_frm_map_handle ;
SMB_mapping_info    cmp_frm_map_info ;

    /* create compressed frame buffer */
    CHK_VERB(STRT_CMP_FRM_BUF_CREATE_MSG_ID) 

    rc = smb_create(CMP_FRM_BUF_NAME, SMB_GLOBAL | SMB_DMA, CMP_FRM_BUF_SIZE,
                MEM_CE_PHYS, CMP_FRM_BUF_CEID, 0, &cmp_frm_mem_handle ) ;

/*    rc = smb_create(CMP_FRM_BUF_NAME, SMB_GLOBAL | SMB_DMA, CMP_FRM_BUF_SIZE,
                0, 0, 0, &cmp_frm_mem_handle ) ;
*/
    CHK_RC(CE_SUCCESS,CMP_FRM_BUF_CREATE_ERR)
    CHK_VERB(CMP_FRM_BUF_CREATED_MSG_ID)

    /* map compressed frame buffer proc mem */
    CHK_VERB(STRT_CMP_FRM_BUF_MAP_MSG_ID) 
    rc = smb_map(cmp_frm_mem_handle,0,0,0,0,0,0,
                &cmp_frm_map_handle,&cmp_frm_map_info ) ;
    CHK_RC(CE_SUCCESS,CMP_FRM_BUF_MAP_ERR)
    CHK_VERB(CMP_FRM_BUF_MAPPED_MSG_ID)

    *ret_cmp_frm_mem_handle = cmp_frm_mem_handle ;

    return( (void *) cmp_frm_map_info.process.vaddr ) ;

    }
/* ----------------- end of setup_cmp_frm_buf ------------------- */

/* ----------------- start of ld_cmp_frm -------------------------- */

ssize_t ld_cmp_frame(char *cmp_frm_fn, void *cmp_frm_buf_ptr) {

    ssize_t     read_cnt ;
    int         filedes, rc ;

TMR_ts      time1, time2 ;
TMR_timespec elapsed ;

    rc = tmr_timestamp(&time1) ;

    /* open compressed frame data file */
    CHK_VERB(STRT_CMP_FRM_FILE_OPEN_MSG_ID) 
    filedes = open(cmp_frm_fn,O_RDONLY) ;
    if (filedes < 0) exit_bad(errno, CMP_FRM_FILE_OPEN_ERR) ;
    CHK_VERB(CMP_FRM_FILE_OPENED_MSG_ID) 
   

    /* read compressed frame file data into buffer */
    CHK_VERB(STRT_CMP_FRM_LD_MSG_ID) 
    read_cnt = read(filedes, cmp_frm_buf_ptr,CMP_FRM_BUF_SIZE) ;
    if (read_cnt < 0) exit_bad(errno, CMP_FRM_FILE_RD_ERR) ;
    CHK_VERB(CMP_FRM_LDED_MSG_ID) 

    /* close compressed frame data file */
    CHK_VERB(STRT_CMP_FRM_FILE_CLOSE_MSG_ID) 
    rc = close(filedes) ;
    if (rc < 0) exit_bad(errno, CMP_FRM_FILE_CLOSE_ERR) ;
    CHK_VERB(CMP_FRM_FILE_CLOSED_MSG_ID) 

    rc = tmr_timestamp(&time2) ;
    rc = tmr_diff(time1,time2,0,&elapsed) ;
    printf("Comp frm file ld elapsed time = %d.%09d seconds.\n",
        elapsed.tv_sec,elapsed.tv_nsec) ;

    return(read_cnt) ;

    }
/* ----------------- end of ld_cmp_frm -------------------------- */


/* ----------------- Start of setup_dcmp_frm_bufs ------------------- */

void  setup_dcmp_frm_bufs(void *dcmp_frm_buf_ptrs[],SMB_handle ret_mem_handles[]) {

long                rc ;
int                 i ;
char                buf_name[16] ;
unsigned long       ceid_num ;
SMB_handle          dcmp_frm_mem_handles[NUM_DCMP_FRM_BUFS] ;
SMB_mapping_handle  dcmp_frm_map_handles[NUM_DCMP_FRM_BUFS] ;
SMB_mapping_info    dcmp_frm_map_infos[NUM_DCMP_FRM_BUFS] ;

    /* create compressed frame buffer */
    CHK_VERB(STRT_DCMP_FRM_BUFS_CREATE_MSG_ID) 

    for(i=0;i<NUM_DCMP_FRM_BUFS;i++) { 
        sprintf(buf_name,"%s%d",DCMP_BUF_BASE_NAME,i) ; 
        if(verbose) printf("Creating decomp frame buffer %s.\n",buf_name) ; 
        if(i < (NUM_DCMP_FRM_BUFS/2)) ceid_num = FIRST_DCMP_FRM_BUF_CEID ;
          else ceid_num = SECOND_DCMP_FRM_BUF_CEID ;
        rc = smb_create(buf_name, SMB_GLOBAL | SMB_DMA,
                (DCMP_FRM_SIZE / NUM_DCMP_FRM_BUFS),
                MEM_CE_PHYS, ceid_num, 0, &dcmp_frm_mem_handles[i] ) ;
        CHK_RC(CE_SUCCESS,DCMP_FRM_BUFS_CREATE_ERR)
     }
    CHK_VERB(DCMP_FRM_BUFS_CREATED_MSG_ID)

    /* map compressed frame buffer proc mem */
    CHK_VERB(STRT_DCMP_FRM_BUFS_MAP_MSG_ID) 

    for(i=0;i<NUM_DCMP_FRM_BUFS;i++) {
        if(verbose) printf("Mapping decomp frame buffer %d.\n",i) ; 
        rc = smb_map(dcmp_frm_mem_handles[i],0,0,0,0,0,0,
                &dcmp_frm_map_handles[i],&dcmp_frm_map_infos[i] ) ;
        CHK_RC(CE_SUCCESS,DCMP_FRM_BUFS_MAP_ERR)
     } 
    CHK_VERB(DCMP_FRM_BUFS_MAPPED_MSG_ID)


    for(i=0;i<NUM_DCMP_FRM_BUFS;i++) {

    ret_mem_handles[i] = dcmp_frm_mem_handles[i] ;
    dcmp_frm_buf_ptrs[i] = (void *) dcmp_frm_map_infos[i].process.vaddr ;
      }


    return ;

    }
/* ----------------- end of setup_dcmp_frm_bufs ------------------- */


/* ----------------- start of attach_rino ------------------- */

DEV_handle attach_rino(char *dev_name) {

    long        rc ;
    DEV_handle  rino_dev_handle ;

    /* attach rint or rout */
    CHK_VERB(STRT_RINO_ATTACH_MSG_ID) 
    if(verbose) printf("Attaching %s.\n",dev_name) ; 
    rc = dev_attach(dev_name,0,&rino_dev_handle) ;
    CHK_RC(CE_SUCCESS,RINO_ATTACH_ERR)
    CHK_VERB(RINO_ATTACHED_MSG_ID) 

    return(rino_dev_handle) ;

    }
/* ----------------- end of attach_rino ------------------- */

/* ------------ start of setup_cmp_frm_out_xfr -------------------- */

DX_transfer setup_cmp_frm_out_xfr(SMB_handle smb_handle,
                 DEV_handle dev_handle, ssize_t cmp_frm_size) {

    long        rc ;
    DX_template dx_template ;
    DX_transfer dx_transfer ;    

    /* create data transfer template */
    CHK_VERB(STRT_CMP_FRM_TEMPL_CREATE_MSG_ID) 
    rc = dx_create(smb_handle,dev_handle,0L,0L,0L,0L,0L,&dx_template) ;
    CHK_RC(CE_SUCCESS,CMP_FRM_TEMPL_CREATE_ERR)
    CHK_VERB(CMP_FRM_TEMPL_CREATED_MSG_ID) 

    /* setup data transfer */
    CHK_VERB(STRT_CMP_FRM_SETUP_XFR_MSG_ID) 
    rc = dx_copy(dx_template,0,0,cmp_frm_size,0,0,0,&dx_transfer) ;
    CHK_RC(CE_SUCCESS,CMP_FRM_XFR_SETUP_ERR)
    CHK_VERB(CMP_FRM_XFR_SETUP_MSG_ID) 

    return(dx_transfer) ;

    }
/* ------------ end of setup_cmp_frm_out_xfr -------------------- */

/* ------------ start of setup_dcmp_frms_in_mstr_xfr -------------------- */

    DX_transfer setup_dcmp_frms_in_mstr_xfr(
              SMB_handle smb_handles[],DEV_handle dev_handle) {

    long        rc ;
    int         i, j ;

    TMR_ts      time1, time2 ;
    TMR_timespec elapsed ;
    float       f_create_tm_diff, f_min_create_tm = 5000.0, 
                f_create_total_tm = 0.0, f_max_create_tm = 0.0 ;
    float       f_copy_tm_diff, f_min_copy_tm, f_copy_total_tm,
                        f_max_copy_tm ;
    float       total_tm = 0.0 ;

    DX_template dx_template ;
    DX_transfer *dx_transfer ;  

    static DX_transfer group_transfer ;

    dx_transfer = malloc((NUM_LINES + 1) * sizeof(DX_transfer)) ;

    CHK_VERB(STRT_SETUP_DCMP_FRMS_XFR_MSG_ID) 

    for(i=0;i<NUM_DCMP_FRM_BUFS;i++) {

      if(verbose) printf("Creating master data transfer in templates in loop %d.\n",i) ; 
      if(verbose) printf("Describing master data transfer in dx_copys in loop %d.\n",i) ; 

      f_min_copy_tm = 5000.0 ;
      f_max_copy_tm = 0.0 ;
      f_copy_total_tm = 0 ;

            /* create data transfer template */
      rc = tmr_timestamp(&time1) ;

      rc = dx_create(dev_handle,smb_handles[i],0L,0L,0L,0L,0L,
                &dx_template) ;
      CHK_RC(CE_SUCCESS,DCMP_FRM_TEMPL_CREATE_ERR)

      rc = tmr_timestamp(&time2) ;
      rc = tmr_diff(time1,time2,0,&elapsed) ;
      f_create_tm_diff = (float)elapsed.tv_sec + (float)
                        (elapsed.tv_nsec / 1000000000.0) ;
      if(f_create_tm_diff < f_min_create_tm) f_min_create_tm =
                                f_create_tm_diff ;
      if(f_create_tm_diff > f_max_create_tm) f_max_create_tm =
                                f_create_tm_diff ;
      f_create_total_tm += f_create_tm_diff ;

      for(j=0;j<LINES_PER_BUF;j++) {


        rc = tmr_timestamp(&time1) ;

            /* setup data transfer */
          rc = dx_copy(dx_template,0,
                    (j * LINE_LNGTH),(LINE_LNGTH / 2),
                    0,0,0,&dx_transfer[(i * LINES_PER_BUF) + j]) ;
          CHK_RC(CE_SUCCESS,DCMP_FRM_XFR_SETUP_ERR)

        rc = tmr_timestamp(&time2) ;
        rc = tmr_diff(time1,time2,0,&elapsed) ;
        f_copy_tm_diff = (float)elapsed.tv_sec + (float)
                            (elapsed.tv_nsec / 1000000000.0) ;
        if(f_copy_tm_diff < f_min_copy_tm) f_min_copy_tm =
                                f_copy_tm_diff ;
        if(f_copy_tm_diff > f_max_copy_tm) f_max_copy_tm =
                                f_copy_tm_diff ;
        f_copy_total_tm += f_copy_tm_diff ;

        } /* end for j */


        printf("dx_copy min time = %f seconds.\n",f_min_copy_tm) ;
        printf("dx_copy max time = %f seconds.\n",f_max_copy_tm) ;
        printf("dx_copy total time = %f seconds.\n",f_copy_total_tm) ;
        printf("dx_copy average time = %f seconds.\n\n",
                (f_copy_total_tm / (float) LINES_PER_BUF)) ;
        total_tm += f_copy_total_tm ;

     } /* end for i */

    printf("dx_create min time = %f seconds.\n",f_min_create_tm) ;
    printf("dx_create max time = %f seconds.\n",f_max_create_tm) ;
    printf("dx_create total time = %f seconds.\n",f_create_total_tm) ;
    printf("dx_create average time = %f seconds.\n\n",
                (f_create_total_tm / (float) NUM_DCMP_FRM_BUFS)) ;
    total_tm += f_create_total_tm ;

    printf("master bd transfer setup total time = %f seconds.\n\n",total_tm) ;

      /* terminate list */
    dx_transfer[NUM_LINES] = 0 ;

    rc = tmr_timestamp(&time1) ;

    rc= dx_group(dx_transfer,0,&group_transfer) ;
    CHK_RC(CE_SUCCESS,DCMP_GRP_XFR_SETUP_ERR)

    rc = tmr_timestamp(&time2) ;
    rc = tmr_diff(time1,time2,0,&elapsed) ;
    printf("master bd group setup elapsed time = %d.%09d seconds.\n",
        elapsed.tv_sec,elapsed.tv_nsec) ;

    CHK_VERB(DCMP_FRMS_GRP_SETUP_MSG_ID) 

    return(group_transfer) ;

    }

/* ------------ end of setup_dcmp_frms_in_mstr_xfr -------------------- */

/* ------------ start of setup_dcmp_frms_in_slv_xfr -------------------- */

    DX_transfer setup_dcmp_frms_in_slv_xfr(
              SMB_handle smb_handles[],DEV_handle dev_handle) {

    long        rc ;
    int         i, j ;

    TMR_ts      time1, time2 ;
    TMR_timespec elapsed ;
    float       f_create_tm_diff, f_min_create_tm = 5000.0, 
                f_create_total_tm = 0.0, f_max_create_tm = 0.0 ;
    float       f_copy_tm_diff, f_min_copy_tm, f_copy_total_tm,
                        f_max_copy_tm ;
    float       total_tm = 0.0 ;

    DX_template dx_template ;
    DX_transfer *dx_transfer ;  

    static DX_transfer group_transfer ;

    dx_transfer = malloc((NUM_LINES + 1) * sizeof(DX_transfer)) ;

    CHK_VERB(STRT_SETUP_DCMP_FRMS_XFR_MSG_ID) 

    for(i=0;i<NUM_DCMP_FRM_BUFS;i++) {

    if(verbose) printf("Creating slave data transfer in templates in loop %d.\n",i) ; 
    if(verbose) printf("Describing slave data transfer in dx_copys in loop %d.\n",i) ; 

    f_min_copy_tm = 5000.0 ;
    f_max_copy_tm = 0.0 ;
    f_copy_total_tm = 0 ;

            /* create data transfer template */
      rc = tmr_timestamp(&time1) ;

      rc = dx_create(dev_handle,smb_handles[i],0L,0L,0L,0L,0L,
                &dx_template) ;
      CHK_RC(CE_SUCCESS,DCMP_FRM_TEMPL_CREATE_ERR)

      rc = tmr_timestamp(&time2) ;
      rc = tmr_diff(time1,time2,0,&elapsed) ;
      f_create_tm_diff = (float)elapsed.tv_sec + (float)
                        (elapsed.tv_nsec / 1000000000.0) ;
      if(f_create_tm_diff < f_min_create_tm) f_min_create_tm =
                                f_create_tm_diff ;
      if(f_create_tm_diff > f_max_create_tm) f_max_create_tm =
                                f_create_tm_diff ;
      f_create_total_tm += f_create_tm_diff ;

      for(j=0;j<LINES_PER_BUF;j++) {

        rc = tmr_timestamp(&time1) ;

            /* setup data transfer */
          rc = dx_copy(dx_template,0,
                    ((j * LINE_LNGTH) + (LINE_LNGTH / 2)),(LINE_LNGTH / 2),
                    0,0,0,&dx_transfer[(i * LINES_PER_BUF) + j]) ;
          CHK_RC(CE_SUCCESS,DCMP_FRM_XFR_SETUP_ERR)

        rc = tmr_timestamp(&time2) ;
        rc = tmr_diff(time1,time2,0,&elapsed) ;
        f_copy_tm_diff = (float)elapsed.tv_sec + (float)
                            (elapsed.tv_nsec / 1000000000.0) ;
        if(f_copy_tm_diff < f_min_copy_tm) f_min_copy_tm =
                                f_copy_tm_diff ;
        if(f_copy_tm_diff > f_max_copy_tm) f_max_copy_tm =
                                f_copy_tm_diff ;
        f_copy_total_tm += f_copy_tm_diff ;

        } /* end for j */

        printf("dx_copy min time = %f seconds.\n",f_min_copy_tm) ;
        printf("dx_copy max time = %f seconds.\n",f_max_copy_tm) ;
        printf("dx_copy total time = %f seconds.\n",f_copy_total_tm) ;
        printf("dx_copy average time = %f seconds.\n\n",
                (f_copy_total_tm / (float) LINES_PER_BUF)) ;
        total_tm += f_create_total_tm ;
        total_tm += f_copy_total_tm ;

     } /* end for i */

    printf("dx_create min time = %f seconds.\n",f_min_create_tm) ;
    printf("dx_create max time = %f seconds.\n",f_max_create_tm) ;
    printf("dx_create total time = %f seconds.\n",f_create_total_tm) ;
    printf("dx_create average time = %f seconds.\n\n",
                (f_create_total_tm / (float) NUM_DCMP_FRM_BUFS)) ;
    total_tm += f_create_total_tm ;

    printf("slave bd transfer setup total time = %f seconds.\n\n",total_tm) ;

      /* terminate list */
    dx_transfer[NUM_LINES] = 0 ;

    rc = tmr_timestamp(&time1) ;

    rc= dx_group(dx_transfer,0,&group_transfer) ;
    CHK_RC(CE_SUCCESS,DCMP_GRP_XFR_SETUP_ERR)

    rc = tmr_timestamp(&time2) ;
    rc = tmr_diff(time1,time2,0,&elapsed) ;
    printf("slave bd group setup elapsed time = %d.%09d seconds.\n",
        elapsed.tv_sec,elapsed.tv_nsec) ;

    CHK_VERB(DCMP_FRMS_GRP_SETUP_MSG_ID) 

    return(group_transfer) ;

    }

/* ------------ end of setup_dcmp_frms_in_slv_xfr -------------------- */


/* ---------------- start of reset_rout ------------------------- */

void reset_rout(DEV_handle dev_handle) {

    long        rc ;

    CHK_VERB(STRT_ROUT_RESET_MSG_ID) 

    rc = dev_control(dev_handle,DEV_RESET) ;
    CHK_RC(CE_SUCCESS,ROUT_RESET_ERR)

    if(test) {
        rc = dev_control(dev_handle,RIO_TEST_MODE_ON,
                        TEST_DATA) ;
        CHK_RC(CE_SUCCESS,ROUT_RESET_ERR)
       }

    CHK_VERB(END_ROUT_RESET_MSG_ID) 

    return ;
    }
/* ---------------- end of reset_rout ------------------------- */

/* ---------------- start of reset_rint ------------------------- */

void reset_rint(DEV_handle dev_handle) {

    long        rc ;

    CHK_VERB(STRT_RINT_RESET_MSG_ID) 

    rc = dev_control(dev_handle,DEV_RESET) ;
    CHK_RC(CE_SUCCESS,RINT_RESET_ERR)

    if(test) {
        rc = dev_control(dev_handle,RIO_TEST_MODE_ON,
                        TEST_DATA) ;
        CHK_RC(CE_SUCCESS,RINT_RESET_ERR)
       }
    else  {
        rc = dev_control(dev_handle,DEV_ENABLE_INPUT) ;
        CHK_RC(CE_SUCCESS,RINT_RESET_ERR)
       }
    CHK_VERB(END_RINT_RESET_MSG_ID) 

    return ;
    }
/* ---------------- end of reset_rint ------------------------- */


/* -------------- start of wr_output_file --------------------- */
/* NOTE!! Even tho it's slow, have to use buffered file system.
   Otherwise CE's have to be reset & configured each time
   this file is run if the unbuffered file system is used.  */


    void wr_output_file(void *dcmp_frm_buf_ptrs[],char *out_fn) {

    FILE        *fp ;
    ssize_t     wr_cnt ;
    int         rc, i ;

    /* open decompressed frame data output file */
    CHK_VERB(STRT_DCMP_FRM_OUT_FILE_OPEN_MSG_ID) 
    fp = fopen(out_fn,"w") ;
    if (fp == 0) exit_bad(errno, DCMP_FRM_FILE_OPEN_ERR) ;
    CHK_VERB(DCMP_FRM_OUT_FILE_OPENED_MSG_ID) 

    
   
    /* write decompressed frame data from buffer to file */
    for(i=0;i<NUM_DCMP_FRM_BUFS;i++) {
       CHK_VERB(STRT_DCMP_FRM_WR_MSG_ID) 
       wr_cnt = fwrite(dcmp_frm_buf_ptrs[i],1,
                  (DCMP_FRM_SIZE / NUM_DCMP_FRM_BUFS),fp) ;
       if(wr_cnt != (DCMP_FRM_SIZE / NUM_DCMP_FRM_BUFS))
                  exit_bad(errno, DCMP_FRM_SHORT_FILE_WR_ERR) ;
       CHK_VERB(DCMP_FRM_WRITTEN_MSG_ID) 
     }

    /* close compressed frame data file */
    CHK_VERB(STRT_DCMP_FRM_OUT_FILE_CLOSE_MSG_ID) 
    rc = fclose(fp) ;
    if (rc != 0) exit_bad(errno, DCMP_FRM_FILE_CLOSE_ERR) ;
    CHK_VERB(DCMP_FRM_OUT_FILE_CLOSED_MSG_ID) 

    return ;

    }


/* -------------- start of wr_output_file --------------------- */


/* ----------------- start of exit_no_fn -------------------------- */

void exit_no_fn() { 
    printf("No decompressor filename supplied. Exiting!") ;
    exit(0) ;
    }
/* ------------------ end of exit_no_fn --------------------------- */


/* ------------------ start of print_msg -------------------------- */

void print_msg(int msg_num) {

char messages[][60] = {
    "dcmiftst started.\n",
    "Attaching decompressor VME memory.\n",
    "Attached decompressor VME memory.\n",
    "Creating decompressor VME memory.\n",
    "Created decompressor VME memory.\n",
    "Mapping decompressor VME memory.\n",
    "Mapped decompressor VME memory.\n",
    "Opening decompressor load file.\n",
    "Opened decompressor load file.\n",
    "Reading decompressor load file.\n",
    "Read decompressor load file.\n",
    "Creating compressed frame buffer.\n",
    "Created compressed frame buffer.\n",
    "Mapping compressed frame buffer.\n",
    "Mapped compressed frame buffer.\n",
    "Opening compressed frame file.\n",
    "Opened compressed frame file.\n",
    "Reading compressed frame file.\n",
    "Read compressed load file.\n",
    "Creating decompressed frame buffers.\n",
    "Created decompressed frame buffers.\n",
    "Mapping decompressed frame buffers.\n",
    "Mapped decompressed frame buffers.\n",
    "Attaching RINO device.\n",
    "Attached RINO device.\n",
    "Creating compressed frame transfer template.\n",
    "Created compressed frame transfer template.\n",
    "Setting up compressed frame transfer.\n",
    "Set up compressed frame transfer.\n",
    "Setting up decompressed frame group transfer.\n",
    "Set up decompressed frame group transfer.\n",
    "Resetting ROUT.\n",
    "ROUT reset.\n",
    "Resetting RINT.\n",
    "RINT reset.\n",
    "Resetting IO.\n",
    "Starting decompressor.\n",
    "Starting IO.\n",
    "IO started.\n",
    "Waiting for ROUT done.\n",
    "Resetting decompressor.\n",
    "Waiting for RINTs done.\n",
    "Decompression interlace test done.\n",
    "Closing compressed frame file.\n",
    "Closed compressed frame file.\n",
    "Closing decompressor load file.\n",
    "Closed decompressor load file.\n",
    "Creating decompressed frame file.\n",
    "Created decompressed frame file.\n",
    "Writing decompressed frame buf to file.\n",
    "Wrote decompressed frame buf to file.\n",
    "Closing decompressed frame file.\n",
    "Closed decompressed frame file.\n",
    "Progress msg overflow!!.\n",
    "Progress msg overflow!!.\n"
    } ;

    printf("%s",messages[msg_num - MSG_ID_BASE]) ;

    }

/* ------------------ end of print_msg -------------------------- */


/* ------------------ start of exit_bad -------------------------- */

void exit_bad(long rc, int err_id) {

char messages[][60] = {
    "Decompressor mem attach failed.\n",
    "Decompressor mem create failed.\n",
    "Decompressor mem map failed.\n",

    "Compressed frame buffer create failed.\n",
    "Compressed frame buffer mapping failed.\n",

    "Decompressor bin file open failed.\n",
    "Decompressor bin file read failed.\n",

    "Compressed frame file open failed.\n",
    "Compressed frame file read failed.\n",

    "Decompressed frame buffer create failed.\n",
    "Decompressed frame buffer mapping failed.\n",

    "RINO dev attach failed.\n",
    "Compressed frame template create failed.\n",
    "Compressed frame transfer setup failed.\n",

    "Decompressed frame template create failed.\n",
    "Decompressed frame transfer setup failed.\n",
    "Group decompressed frame transfer setup failed.\n",

    "ROUT reset failed.\n",
    "RINT reset failed.\n",
    "RINT 1 start failed.\n",
    "RINT 2 start failed.\n",
    "ROUT start failed.\n",
    "ROUT wait failed.\n",

    "RINT 1 wait failed.\n",
    "RINT 2 wait failed.\n",

    "Compressed frame file close failed.\n",
    "Decompressor bin file close failed.\n", 

    "Decompressed frame file creat failed.\n",
    "Decompressed frame file write failed.\n",
    "Decompressed frame short file write failure.\n",
    "Decompressed frame file close failed.\n",

    "Decompressor reg ld malloc failed.\n",
    "Decompressor short file error.\n",
    "Err msg overflow!!.\n",
    "Err msg overflow!!.\n"
    } ;

    err_print(rc, ERR_GET_ALL) ;
    printf("%s",messages[err_id - ERR_ID_BASE]) ;
    exit(err_id) ;

    }

/* ------------------ end of exit_bad -------------------------- */