University of Rochester / Ultrasound Research Laboratory
2D Array Library

 
Class hierarchy   Compound list   File list   Header files   Compound Members   File Members   Examples  

txaper.cpp

This code is documented so that the advanced programmer can see how to make calls to the low-level driver functions.

/*
  $Id: Txaper.cpp,v 1.2 1999-03-11 16:14:32-05 ljb Exp ljb $
  $Revision: 1.2 $
 
  $Log: Txaper.cpp,v $
  Revision 1.2  1999-03-11 16:14:32-05  ljb
  Made some updates to documentation.

  Revision 1.1  1999-03-05 16:30:39-05  ljb
  Initial revision

  Revision 1.6  1998/10/23 14:25:19  LJB
  Warning messages regarding clipping, overflow and underflow now go to STDERR
  and can be redirected to a file on the command line using "2>"

  Revision 1.5  1998/09/01 11:21:27  LJB
  Removed yesterday's bug fix.  Now it is handled by the calling program.
  Also re-order the sequence in which the Txwaveform array is filled
  when reading NTX files.  The current order is (slowest -> fastest)
  NX then NY then NZ.  This is corresponds to Liu's 8/10/98 email message.

  Revision 1.4  1998/08/31 10:23:46  LJB
  Fixed bug associated with the number of zones in an NTX file.
  Current version assumes only 1 zone in each NTX file

  Revision 1.3  1998/08/27 13:54:36  LJB
  Now Compensate checks xp and yp to be sure they are in range.

  Revision 1.2  1998/08/06 15:09:06  LJB
  Updated documantation.

  Revision 1.1  1998/06/19 15:49:54  LJB
  Initial revision


*/



//#define VERBOSE                     //Define to output test files

#include "common.h"
#include "tdefs.h"
#include "util.h"
#include "wpair.h"
#include "errcodes.h"
#include "2dcntrl.h"
#include "uasaddr.h"
#include "txaper.h"
#include "sigpro.h"
#include "acq.h"
#include "sigpro.h"

extern TwoDCntrlClass *pci;

#define TX_CLOCK MASTER_CLOCK
#define TXDEF 0x80


TTxAper::TTxAper():
waveforms(0),buffer(0),pulse(0),compwaves(0)
{
      Aperture::Init( WPAIR( TX_MAX_XSIZE, TX_MAX_YSIZE) ); 
      freq = 3.0;
      numcycles = 1;
}          


void
TTxAper::SetFreq( float f){ freq = f;}


void TTxAper::SetNumCycles( WORD n){ numcycles = n;}


void TTxAper::DiodeOffset( BYTE *input, BYTE *output, int npts, float offset, float band) {
  int i;
  float x,y;
  for (i=0 ; i<npts; i++){
    x = (float)input[i] - 128.;                    //Convert to float
    if( x < -band ) y = x - offset ;
    else if( x > band ) y = x + offset ;
    else y =  x + offset * sin( ( 0.5 * PI ) * ( x / band ) ) ;
    y +=128.;
    output[i] =  (BYTE) MAX(0,MIN(255, NINT(y) )); //Convert to BYTE
  }
}


WORD
TTxAper::SetWaveforms( char *name){  
  FILE *fp;
  size_t status;
  int i, j,k;
  char *buf;
  char string[80];
  INT16 temp;
  INT16 lnx, lny, lnp;
  WPAIR wsize;

  //free memory if necessary, assume current wsize is correct
  if ( waveforms != 0){
    wsize = GetWaveSize();
    free_3D_BYTE( waveforms, X(wsize), Y(wsize));
  }

  if ( compwaves != 0){
    wsize = GetWaveSize();
    free_3D_BYTE( compwaves, X(wsize), Y(wsize));
  }

  //Read the size of the file 
  fp = fopen( name, "rb");
  if (fp == NULL) {
    sprintf(string,"TTxAper::SetWaveforms: Problem opening %s",name);
    throw(PCIClassErr((char*)string));
  }
  fread( &lnx, sizeof(INT16), 1, fp);
  fread( &lny, sizeof(INT16), 1, fp);
  fread( &lnp, sizeof(INT16), 1, fp);

  //Set the sizes in the TxAper Object
  wsize = WPAIR( lnx, lny);
  SetupAper( UTW, wsize);
  SetWaveSize(wsize);
  SetWavePoints(lnp);

  //allocate new memory
  waveforms = get_3D_BYTE((INT16)lnx,(INT16)lny,(INT16)lnp); 
  compwaves = get_3D_BYTE((INT16)lnx,(INT16)lny,(INT16)lnp); 
  if( waveforms == NULL || compwaves == NULL) 
    throw(PCIClassErr("TTxAper::SetWaveforms: Problem allocating memory"));

  buf = new char[lnp];
  for(i=0; i<lnx;i++){
    for(j=0; j<lny; j++){
      status = fread( buf, sizeof(BYTE), lnp, fp);
      if( status != lnp) 
        throw(PCIClassErr("TTxAper::SetWaveforms: Problem reading data"));
      for( k=0; k<lnp; k++){
        temp = buf[k];
        temp += 128;
        waveforms[i][j][k] = (BYTE)temp; //Uncompensated waveforms 
        compwaves[i][j][k] = (BYTE)temp; //Make a copy for convenience
      } 
    }
  }
  delete[] buf;
  return SUCCESS;
}


WORD
TTxAper::SetWaveforms( char *name, int ia, int iz){  
  FILE *fp;
  size_t status;
  int i, j,k,fx,fy,lx,ly,ii,jj,kk;
  char *buf;
  char string[80];
  INT16 temp;
  INT16 lnx, lny, lnp;
  WPAIR wsize;
  TEST_HDR_TYPE *th;
  long *raw_index, foffset;
  float *y,*y1,*y2, ftemp, sample;    //needed for interpolation
  float del, delmax, fdel;
  int ntxpts, maxpts, idel;

  th = new TEST_HDR_TYPE;

  wsize = GetWaveSize();

  //free memory if necessary, assume current wsize is correct
  if ( waveforms != 0) free_3D_BYTE( waveforms, X(wsize), Y(wsize));
  if ( compwaves != 0) free_3D_BYTE( compwaves, X(wsize), Y(wsize));

  //Read the size of the file 
  fp = fopen( name, "rb");
  if (fp == NULL) {
    sprintf(string,"TTxAper::SetWaveforms: Problem opening %s",name);
    throw(PCIClassErr((char*)string));
  }

  // Read the expt header
  read_header( fp, th);

  // there should be no need for byte swapping with the latest version of gentx1
  // dp 1342 15feb99
#if defined(BYTE_SWAP)
  int *ptr;
  ptr = (int *)th;
  for (i=0; i<512; i++) ptr[i] = ByteSwap( (long)ptr[i] );
#endif

  // Read the index 
  int nlength = th->brief.nAscans * th->brief.nZones;
  raw_index = new long[nlength];  assert( raw_index != 0);
  int nread = fread( raw_index, sizeof(long), nlength, fp);
  assert( nread == nlength);
#if defined(BYTE_SWAP)
  for (i=0; i<nlength; i++) raw_index[i] = ByteSwap( raw_index[i]);
#endif
  // Position at the right record
  int record = ia * th->brief.nZones + iz;
  fseek( fp, raw_index[record], SEEK_SET);

  // Read the raw record header
  RAW_RECORD_HEADER_TYPE hd;
  fread( &hd, sizeof(RAW_RECORD_HEADER_TYPE),1,fp);

#if defined(BYTE_SWAP)
  //BitReverse
  hd.nX = ByteSwap(hd.nX);
  hd.nY = ByteSwap(hd.nY);
  hd.npt = ByteSwap(hd.npt);
#endif
  //Find the maximum delay for this aperture
  delmax = GetMaxDelay();
  ntxpts = delmax * (float)TX_CLOCK + 2*hd.npt + 1;
  SetWavePoints(ntxpts);

  //allocate new memory
  waveforms = get_3D_BYTE((INT16)X(wsize),(INT16)Y(wsize),(INT16)ntxpts); 
  compwaves = get_3D_BYTE((INT16)X(wsize),(INT16)Y(wsize),(INT16)ntxpts); 
  if( waveforms == NULL || compwaves == NULL) 
    throw(PCIClassErr("TTxAper::SetWaveforms: Problem allocating memory"));

  if( hd.nX < X(wsize) || hd.nY < Y(wsize) )
    throw(PCIClassErr("TTxAper::SetWaveforms: Problem reading the .NTX file"));

  //Read everything into a temporary array...order NOT adjusted for Liu's files
  char *cbuf;
  BYTE ***barray;
  barray = get_3D_BYTE( hd.nX, hd.nY, hd.npt);
  cbuf = new char[hd.npt];
  for(i=0; i<hd.nX;i++){
    for(j=0; j<hd.nY; j++){
      status = fread( cbuf, sizeof(BYTE), hd.npt, fp);
      if( status != hd.npt) 
        throw(PCIClassErr("TTxAper::SetWaveforms: Problem reading data"));
      for(k=0; k<hd.npt; k++){
        temp = cbuf[k];
        temp += 128;
        barray[i][j][k] = (BYTE)( temp);
//        printf(" %3d ",temp);
//        if (k % 10 == 9) printf("\n");
      }
//    printf("\n\n");
    }
  }
  fx = (hd.nX - X(wsize) )/2;  lx = (hd.nX + X(wsize) )/2;
  fy = (hd.nY - Y(wsize) )/2;  ly = (hd.nY + Y(wsize) )/2;

  maxpts = hd.npt;
  y = new float[maxpts];
  y1= new float[maxpts];
  y2= new float[maxpts];
  for (i=fx,ii=0; i<lx; i++, ii++){
    for (j=fy,jj=0; j<ly; j++, jj++){
      for( k=0; k<maxpts; k++){
        y[k] = (float)barray[i][j][k] - 128;;
      }
      equi_spline(y,y1,y2,maxpts);
      memset( waveforms[ii][jj], 128, ntxpts); //Sets the Txwaveform record to default
      memset( compwaves[ii][jj], 128, ntxpts); //Sets the Txwaveform record to default
      del = GetDelay(ii,jj)-GetAberDelay(ii,jj);
      idel = del * (float)TX_CLOCK;                          //whole delay index
      fdel = del - ((float)idel /  (float)TX_CLOCK);          //fractional delay
      for( kk=0, k=idel; k < ntxpts; k++, kk++){
        if ( k >=0 && k < ntxpts){
          sample = 0.5*(float)kk + fdel;
          ftemp = equi_splint( y1,y2,maxpts,sample);
          temp = NINT(ftemp);
          temp += 128;
          if (temp > 255) temp = 255;
          if (temp < 0) temp =0;
//        printf(" %3d ",temp);
//        if (kk % 10 == 9) printf("\n");
          waveforms[ii][jj][k] = (BYTE)temp; //Uncompensated waveforms 
          compwaves[ii][jj][k] = (BYTE)temp; //Make a copy for convenience
        } else {
          printf("Problem in txaper\n");
        }
 	  }
//	  printf("\n\n");
    }
  }

  //Find the time of the max signal of the center element
  i = X(wsize) / 2;
  j = Y(wsize) / 2;
  int maxv = 0;
  kk = 0;
  for(k = 0; k < ntxpts; k++){
    temp = waveforms[i][j][k];
    if (temp > maxv){
    maxv = temp;
    kk = k;
    }
  }
  delay_center = (float)kk / (float)TX_CLOCK;
  
  free_3D_BYTE( barray, hd.nX, hd.nY);
  delete th, delete[] raw_index; delete[] cbuf; delete[] y; delete[] y1; delete[] y2;
  fclose(fp);
  return SUCCESS;
}



WORD
TTxAper::SetWaveforms( float F_0, float DeltaF, float phase, float amp){  
  int i,j,k,kk,idel;
  WPAIR wsize;
  INT16 lsp,lnp,lnx,lny;
  float amplitude,delmax,del,fdel;

  //free memory if necessary, assume current wsize is correct
  if ( waveforms != 0){
    wsize = GetWaveSize();
    free_3D_BYTE( waveforms, X(wsize), Y(wsize));
  }
  if ( compwaves != 0){
    wsize = GetWaveSize();
    free_3D_BYTE( compwaves, X(wsize), Y(wsize));
  }


  //Get the size of the current aperture 
  wsize = GetAperSize();
  SetWaveSize(wsize);                            //make wavesize = aperture size
  lsp = StdPulse( F_0, DeltaF, phase, amp, 0.0);      //How long is the Tx Pulse
  lsp++;                                            //Make room for 1 more point

  //Find the maximum delay for this aperture
  delmax = GetMaxDelay();
  lnp = delmax * (float)TX_CLOCK + lsp +1;

  lnx = X(wsize);
  lny = Y(wsize);

  SetWavePoints(lnp);

  //allocate new memory
  waveforms = get_3D_BYTE((INT16)lnx,(INT16)lny,(INT16)lnp); 
  if( waveforms == NULL) 
    throw(PCIClassErr("TTxAper::SetWaveforms: Problem allocating memory"));
  compwaves = get_3D_BYTE((INT16)lnx,(INT16)lny,(INT16)lnp); 
  if( compwaves == NULL) 
    throw(PCIClassErr("TTxAper::SetWaveforms: Problem allocating compwaves"));

#ifdef VERBOSE
  FILE *fp1, *fp2, *fp3;
  fp1 = fopen("delay.tst","wb");
  fp2 = fopen("idelay.tst","wb");
  fp3 = fopen("fdelay.tst","wb");

  fwrite( &lnx, 1, sizeof(INT16), fp1);
  fwrite( &lny, 1, sizeof(INT16), fp1);
  fwrite( &lnx, 1, sizeof(INT16), fp2);
  fwrite( &lny, 1, sizeof(INT16), fp2);
  fwrite( &lnx, 1, sizeof(INT16), fp3);
  fwrite( &lny, 1, sizeof(INT16), fp3);
#endif

  for(i=0; i<lnx;i++){
    for(j=0; j<lny; j++){
      memset( waveforms[i][j], 128, lnp); //Sets the Txwaveform record to default
      memset( compwaves[i][j], 128, lnp); //Sets the Txwaveform record to default
      del = GetDelay(i,j)-GetAberDelay(i,j);
      idel = del * (float)TX_CLOCK;                          //whole delay index
      fdel = del - ((float)idel /  (float)TX_CLOCK);          //fractional delay
#ifdef VERBOSE
    fwrite( &del, 1, sizeof(float), fp1);
    fwrite( &idel, 1, sizeof(int), fp2);
    fwrite( &fdel, 1, sizeof(float), fp3);
#endif
      amplitude = amp;
      amplitude *= GetApodPoint( i,j);            //Apodize
      lsp = StdPulse( F_0, DeltaF, phase, amplitude, fdel);
      for( k=idel, kk=0; k< idel+lsp; k++, kk++){
        if (k >=0 && k <lnp){
          waveforms[i][j][k] = pulse[kk];
          compwaves[i][j][k] = pulse[kk];
        } else {
//        printf("Problem in txaper\n");
        }
      }
    }
  }
#ifdef VERBOSE
  fclose(fp1); fclose(fp2); fclose(fp3);
#endif
  float adjust = (float) lsp / (2.* (float)TX_CLOCK) ;
  delay_center += adjust;
  return SUCCESS;
}


WORD
TTxAper::ClearWaveforms( void){  
  int i,j;
  WPAIR wsize;

  //Get the size of the current aperture 
  wsize = GetAperSize();

  int lnp = GetNumWavePts();
  for(i=0; i<X(wsize);i++){
    for(j=0; j<Y(wsize); j++){
      memset( waveforms[i][j], 128, lnp); //Set the Txwaveform record to default
      memset( compwaves[i][j], 128, lnp); //Set to default
    }
  }
  return SUCCESS;
}


WORD
TTxAper::LoadBuffer( WPAIR pC0, WPAIR pC1, WPAIR aC0, WPAIR aC1){
  size_t seqlength[8] = {68, 132, 260, 516, 1028, 2052, 4100, 8192};
  BYTE TSEQBITS;
  BYTE NDELBITS;
  BYTE  txchan, txchan_org;
  BYTE *src,*src2;
  WPAIR maxss;
  int ip,jp,                                   //Physical counters
      ia,ja;                                   //aperture counters
  int i,j,nxmit;
  size_t npts;
  float txtime;
  BurstCntrl_t bct;
  long address,index,offset;

  npts = GetNumWavePts();       //real Waveform
//  printf("TxAper: npts=%4d\n",npts);
  for (i=0; i<8; i++){
    if (( seqlength[i] / npts ) == 1) break;
  }
  TSEQBITS = (BYTE)i;
  nxmit = seqlength[i];
  txtime = npts / (float)TX_CLOCK;
  NDELBITS = BYTE(0.5 + txtime / .640);
  maxss = GetMaxSubSize();
  size_t buf_size = area(maxss) * nxmit;

#if defined(HW_AVAIL)
    BYTE *buffer = (BYTE *)pci->getVirtDMAPtr();
#else
    BYTE *buffer;
    buffer = new BYTE[buf_size];               //Tem
#endif
  memset( buffer, (BYTE)TXDEF, buf_size);              //Only clear what's necessary
 
  bct.type = TransferByte;
  bct.ChannelSize =  MAX_TX_POINTS;
  int npad = nxmit - npts;
  int tx_max_xsize = TX_MAX_XSIZE;
  int tx_max_ysize = TX_MAX_YSIZE;
  src2 = new BYTE[npts];    assert( src2 != 0);
  for(ia=X(aC0), ip=X(pC0); ia <= X(aC1) && ip <=X(pC1); ip++,ia++){
    if (ip >= 0 && ip < 80){

      BYTE xfactor = (BYTE)(tx_max_ysize * (ip % tx_max_xsize));
      for(ja=Y(aC0), jp=Y(pC0); ja <= Y(aC1) && jp <= Y(pC1) ; jp++, ja++){
        if( jp >= 0 && jp < 80){
          BYTE yfactor = jp % TX_MAX_YSIZE;
          txchan_org = xfactor + yfactor;
          txchan = GetChannel( ip, jp); //xfactor + yfactor;
#if defined(VERBOSE)
  printf("Row = %d, Col = %d, TxChan_old = %d, TxChan_new = %d\n", 
    jp, ip, txchan_org, txchan);
#endif
          src = GetCompPtr(ia,ja);
          offset = (int)txchan * nxmit;
          DiodeOffset( src, src2, npts, 20., 2.);
          memcpy( &buffer[offset],src2,npts);    //Load data
          offset += npts;
          memset( &buffer[offset],(BYTE)TXDEF,npad);  //Load Default Value

#if defined(OUTPUT)
  FILE *fp;
  fp = fopen("TxOut.RAW","wb"); 
  if( fp == NULL)
    throw(PCIClassErr("TTxAper::LoadBuffer: Problem opening temporary file"));
  fwrite( &npts, sizeof(int), 1, fp);
  fwrite( src, sizeof(BYTE), npts, fp);
  fclose( fp);
#endif

        } // end of jp test
      }
    } //end of ip
  }
  bct.UASAddr = TWAVERAM;
  bct.DwordOffset = 0;
  bct.NumbOfChannels = 128;
  bct.ChannelTransferCount = nxmit;

  index = 0;
  pci->writeUAS( (long)TSEQLEN,  (char)TSEQBITS );       //txseqlength
#if defined(HW_AVAIL)
    pci->doUASBurstWrite( bct);                     //send all data
#else
    delete[] buffer;
#endif

  delete[] src2;
  return(SUCCESS);

}


TBool 
TTxAper::LoadMT( MuxTwoDType *mt, WPAIR pc0, WPAIR pc1){
  TBool ret_val = bFALSE;
  TBool Xok, Yok;
  int min_x, max_x;
  int min_y, max_y;

  min_x = X(pc0);
  max_x = X(pc1);
  min_y = Y(pc0);
  max_y = Y(pc1);

  //See if anything is in range
  if ( min_x >= 0 && min_x < 80) Xok = bTRUE;
  if ( max_x >= 0 && max_x < 80) Xok = bTRUE;
  if ( min_y >= 0 && min_y < 80) Yok = bTRUE;
  if ( max_y >= 0 && max_y < 80) Yok = bTRUE;

  ret_val = (TBool)(Xok && Yok);
  if( !ret_val) return(bFALSE);   //bail out if nothing in range

  mt->b.XmtStartCol = MIN(79,MAX( 0,min_x));
  mt->b.XmtEndCol   = MIN(79,MAX( 0,max_x));
  mt->b.XmtStartRow = MIN(79,MAX( 0,min_y));
  mt->b.XmtEndRow   = MIN(79,MAX( 0,max_y));
#ifdef VERBOSE
  printf( "TxLoadMT (R:C): from (%3d:%3d) to  (%3d:%3d)\n",
    mt->b.XmtStartRow, mt->b.XmtStartCol, mt->b.XmtEndRow, mt->b.XmtEndCol);
#endif
  return(bTRUE);
}


INT16 TTxAper::StdPulse( float F_0, float DeltaF, float phase, float amp, float dtime)
{
  int i, ppts, ncenter;
  double t,p;

  double pi = 4.*atan(1.0);                                   
  double omega = 2.0 * pi * F_0;
  double sigmaT = sqrt(2. * log(2.0)) / DeltaF / pi;
  BYTE pmin, pmax;
  pmin = pmax = (BYTE)127;

  //Calculate the number of points required to digitize the whole pulse
  //i.e. when does the envelope go below Tx DAC resolution (.005)
  double tcut = sqrt( -2. * sigmaT * sigmaT * log(.005)); 
  ncenter = (int)(tcut * (float)TX_CLOCK );
  ppts = 2*ncenter +1;

  if (pulse != NULL) delete[] pulse;
  pulse = new BYTE[ppts];
  for( i=0; i<ppts; i++){
    t = -dtime + (float)(i-ncenter)/(float)TX_CLOCK;     //time in microseconds
    p = 127.*amp*exp(-(t*t)/(2. *  sigmaT * sigmaT )) * sin((omega * t) + phase);
    pulse[i] = (BYTE)(128 + NINT(p));
//	printf("%3d, %3d,  %.4f\n",i,pulse[i],p);
  }

  for (i=0; i<ppts; i++){
    if (pulse[i] > pmax) pmax = pulse[i];
    if (pulse[i] < pmin) pmin = pulse[i];
  }
  printf("TxMax = %d, TxMin = %d\n",pmax, pmin);

  return (INT16)ppts;
}

TTxAper::~TTxAper( void) {
//  cout << "TTxAper destructor"<<endl;
  if( waveforms != 0){
    WPAIR wsize = GetWaveSize();  
    free_3D_BYTE( waveforms, X(wsize), Y(wsize));
  }
  if( compwaves != 0){
    WPAIR wsize = GetWaveSize();  
    free_3D_BYTE( compwaves, X(wsize), Y(wsize));
  }
}


WORD TTxAper::Compensate( SystemProps *ap){
  WPAIR l_corner = center - size/2;
  return Compensate( ap, l_corner);
}


WORD TTxAper::Compensate( SystemProps *ap, WPAIR pC0){
  int ix, iy, k, xp, yp,index;
  float scale, ftemp;
  float *wave, *filt, *output, *scratch;
  int n_filt_pts = ap->GetNumImprPts();
  int npts       = GetNumWavePts();
  INT16 *ftmp;
  BYTE  *wtmp;
  BYTE  *wout;

  filt    = new float[n_filt_pts];
  output  = new float[n_filt_pts+ npts];
  scratch = new float[npts+2*n_filt_pts];
  wave    = new float[npts];  
  if ( filt == NULL || output == NULL || scratch == NULL || wave == NULL)
    throw(PCIClassErr("TTxAper::Compensate: Problem allocating temporary arrays"));

#if defined(VERBOSE)
  printf("Compensating TxWave at element (%2d:%2d)\n", X(pC0), Y(pC0));
#endif
  //figure out where this Tx aperture is located
  WPAIR wsize   = GetWaveSize();

  if( compwaves != 0) free_3D_BYTE(compwaves, X(wsize), Y(wsize));
  compwaves = get_3D_BYTE( X(wsize), Y(wsize), npts); 
  if( compwaves == NULL)
    throw(PCIClassErr("TTxAper::Compensate: Problem allocating compwaves"));


  scale = 1.0 / (float)ap->GetImprScale();

  xp = X(pC0);
  for( ix = 0; ix < X(wsize); ix++, xp++){
    yp = Y(pC0);
    for( iy = 0; iy< Y(wsize); iy++, yp++){

      if( xp >= 0 && xp < MAXDIM && yp >= 0 && yp < MAXDIM){
        //fetch input data
        wtmp = GetWavePtr(ix,iy);
        wout = GetCompPtr(ix,iy);
        for (k = 0; k<npts; k++) wave[k] = (float)wtmp[k] - 128.;
              
        //fetch filter -- linked to physical element
        ftmp = ap->GetImprPtr(xp,yp);
        for( k = 0; k<n_filt_pts; k++) filt[k] = (float)ftmp[k];

#if defined(OUTPUT)
  FILE *fp;
  fp = fopen("TxInput.dat","wb"); 
  if( fp == NULL)
    throw(PCIClassErr("TTxAper::Compensate: Problem opening TxInput.dat"));
  fwrite( &npts, sizeof(int), 1, fp);
  fwrite( wave, sizeof(float), npts, fp);
  fclose( fp);

  fp = fopen("TxFilter.dat","wb");
  if( fp == NULL)
    throw(PCIClassErr("TTxAper::Compensate: Problem opening TxFilter.dat"));

  fwrite( &n_filt_pts, sizeof(int), 1, fp);
  fwrite( filt, sizeof(float), n_filt_pts, fp);
  fclose( fp);
#endif

 
        //Do the convolution
        conv2( filt, wave, output, scratch, n_filt_pts, npts);

        //scale the results
        index = n_filt_pts/2;
#if defined(OUTPUT)
  fp = fopen("TxOutput.dat","wb"); 
  if( fp == NULL)
    throw(PCIClassErr("TTxAper::Compensate: Problem opening TxOutput.dat"));

  fwrite( &npts, sizeof(int), 1, fp);
  fwrite( &output[index], sizeof(float), npts, fp);
  fclose( fp);
#endif
        for( k=0; k<npts; k++){
          ftemp = output[index++];
          ftemp *= scale;
          ftemp += 128.;
          if ((ftemp > 255) || (ftemp < 0)) {
            fprintf( stderr,"Tx Waveform: (%3d,%3d), Point:%4d value of %f will be clipped\n",
              xp,yp,k,ftemp);
          }
          wout[k] = (BYTE) MAX(0,MIN(255, NINT(ftemp) )); //Convert to BYTE
        }
      }           // end of if
    }           //next y
  }           //next x
  delete[] wave;delete[] filt;delete[] output; delete[] scratch;
  return SUCCESS;
} 


WORD
TTxAper::WriteRawAperture( FILE *fp){
  struct { WORD nx, ny, nz, xcenter, ycenter, nbytes; } hd;
  int ix, iy, iz, written;

  if (fp == NULL) return(1);
  WPAIR size = GetWaveSize();
  WPAIR center = GetCenterEl();
  hd.nx = X(size);
  hd.ny = Y(size);
  hd.nz = GetNumWavePts();
  hd.xcenter = X(center);
  hd.ycenter = Y(center);
  hd.nbytes = sizeof(INT16);

  if ( (fwrite( &hd, sizeof(hd), 1, fp)) != 1) return(2);

  for(ix=0; ix < hd.nx; ix++){
    for(iy=0; iy < hd.ny; iy++){
//      printf("[%2d,%2d]..", ix, iy);
      written = fwrite( waveforms[ix][iy], sizeof(BYTE), hd.nz, fp);
      if (written != hd.nz) return(3);
    }
  }

  return(0);
}


WORD
TTxAper::WriteCompAperture( FILE *fp){
  struct { WORD nx, ny, nz, xcenter, ycenter, nbytes; } hd;
  int ix, iy, iz, written;

  if (fp == NULL) return(1);
  WPAIR size = GetWaveSize();
  WPAIR center = GetCenterEl();
  hd.nx = X(size);
  hd.ny = Y(size);
  hd.nz = GetNumWavePts();
  hd.xcenter = X(center);
  hd.ycenter = Y(center);
  hd.nbytes = sizeof(INT16);

  if ( (fwrite( &hd, sizeof(hd), 1, fp)) != 1) return(2);

  for(ix=0; ix < hd.nx; ix++){
    for(iy=0; iy < hd.ny; iy++){
//      printf("[%2d,%2d]..", ix, iy);
      written = fwrite( compwaves[ix][iy], sizeof(BYTE), hd.nz, fp);
      if (written != hd.nz) return(3);
    }
  }

  return(0);
}


WORD
TTxAper::TestTxWaveRam( size_t npts, size_t channel){
  size_t seqlength[8] = {68, 132, 260, 516, 1028, 2052, 4100, 8192};

  BYTE TSEQBITS;
  BYTE NDELBITS;
  BYTE  txchan;
  BYTE *buf1;
  float txtime;
  int i,nxmit;

  BurstCntrl_t bct;
  long address,index,offset;

  for (i=0; i<8; i++){
    if (( seqlength[i] / npts ) == 1) break;
  }
  TSEQBITS = (BYTE)i;
  nxmit = seqlength[i];
  txtime = npts / (float)TX_CLOCK;
  NDELBITS = BYTE(0.5 + txtime / .640);

  size_t buf_size = nxmit;

  buf1 = new BYTE[nxmit]; assert( buf1 != 0); //Setup output buffer

  //Fill the ouput buffer with random numbers
  int rval;
  int nshift;
  for( i=0; i<nxmit; i++) {
    rval = rand();
    buf1[i] = rval;
  }

#if defined(HW_AVAIL)
    BYTE *buffer = (BYTE *)pci->getVirtDMAPtr();
#else
    BYTE *buffer;
    buffer = new BYTE[buf_size];               //Tem
#endif
  memcpy( buffer, buf1, buf_size); 
 
  bct.type = TransferByte;
  bct.ChannelSize =  MAX_TX_POINTS;

  bct.UASAddr = TWAVERAM + channel * MAX_TX_POINTS;
  bct.DwordOffset = 0;
  bct.NumbOfChannels = 128;
  bct.ChannelTransferCount = nxmit;

  index = 0;
  pci->writeUAS( (long)TSEQLEN,  (char)TSEQBITS );       //txseqlength
#if defined(HW_AVAIL)
    pci->doUASBurstWrite( bct);    //send all data
	Sleep(10);
    pci->doUASBurstRead( bct);                      //Read it back data
#endif

  //Compare buf1 to buffer
  int nbad = 0;
  printf("Testing TxChannel %3d \n", (int)channel);
  for (i=0; i<nxmit; i++){
    if( buf1[i] != buffer[i]){
      printf("Point %4d is bad: input = 0x%2x   output = 0x%2x \n",
        i, buf1[i], buffer[i]);
      nbad++;
    }
  }
  if (nbad == 0)
    printf("input and output agree\n");

#if !defined(HW_AVAIL)
  delete[] buffer;
#endif

  delete[] buf1;
  if (nbad == 0) return(SUCCESS);
  else return( FAILURE);

}

Software written by
Larry Busse of LJB Development
and Bill Glenn, Al Murphy and John Losche of TETRAD Corporation
Documentation generated 3/11/1999