/* wr.c -- Read/write VLBI VSIB input/output board and disks. */ /* * $Log: wr.c,v $ * Revision 1.13 2003/03/05 08:01:56 amn * March 2003 Jb2/Mh Mk4/5-style Gbit test version. * * Revision 1.12 2002/11/29 10:58:40 amn * Unified ft2 and ft3; made mrg seq. numbered file opening work; wr parms. * * Revision 1.11 2002/11/07 09:06:49 amn * First Mk5A 1Gbit/s tests with Jodrell. * * Revision 1.10 2002/11/01 13:19:58 amn * Just before changing to use a common tstamp.cc file. * * Revision 1.9 2002/09/20 07:39:15 amn * Added mrg.c, merge/split for multi-PC files. * * Revision 1.8 2002/09/02 16:39:47 amn * Test version suitable for 50MHz/2 test pattern recording, for pb/JB. * * Revision 1.7 2002/08/09 11:26:56 amn * Jul-2002 first fringes Dwingeloo test version. * * Revision 1.5 2002/06/15 10:07:31 amn * Added shared memory and seek support. * * Revision 1.4 2002/06/14 13:02:34 amn * Dwingeloo test trip version. * */ /* Copyright (C) 2001--2002 Ari Mujunen, Ari.Mujunen@hut.fi This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include #include /* open() */ #include /* open() */ #include /* open() */ #include /* gettimeofday() */ #include /* gettimeofday(), usleep(), getopt() */ extern char *optarg; extern int optind, opterr, optopt; #include /* strstr(),strtok() */ #include /* for shared memory */ #include #include #include "vsib_ioctl.h" #define TIMED_START 1 #define ONEPPS 1 // #define LOOP // Write (and overwrite) the files in a continous loop /* Depending on readMode either standard input or output. */ int vsib_fileno; /* A protected (error-checking) ioctl() for VSIB driver. */ static void vsib_ioctl( unsigned int mode, unsigned long arg ) { if (ioctl(vsib_fileno, mode, arg) ) { char *which; char err[255]; if (vsib_fileno == STDOUT_FILENO) { which = "rd"; } else { which = "wr"; } snprintf(err, sizeof(err), "%s: ioctl(vsib_fileno, 0x%04x,...)", which, mode); perror(err); fprintf(stderr, "%s: standard I/O is not an VSIB board\n", which); exit(EXIT_FAILURE); } } /* vsib_ioctl */ typedef struct sDir { char *nameTemplate; int nameNumber; int blocksPerFile; int fid; int nowBlocks; double prevOperTime; double maxOperTime; } tDir, *pDir; double tim(void) { struct timeval tv; double t; assert( gettimeofday(&tv, NULL) == 0 ); t = (double)tv.tv_sec + (double)tv.tv_usec/1000000.0; return t; } /* tim */ void randbuf(char *buf, ssize_t nbytes) { int i; for (i=0; i*/0) | VSIB_MODE_RUN | (0 ? VSIB_MODE_GIGABIT : 0) #ifdef ONEPPS | (1 ? VSIB_MODE_EMBED_1PPS_MARKERS : 0) #else | (0 ? VSIB_MODE_EMBED_1PPS_MARKERS : 0) #endif | (/*skip_samples=>*/0 & 0x0000ffff)) ); break; case 1: // 16 alternate bit streams vsib_ioctl(VSIB_SET_MODE, // 16-bit Mark5A. */ (VSIB_MODE_MODE(/*vsib_mode=>*/1) | VSIB_MODE_RUN | (0 ? VSIB_MODE_GIGABIT : 0) #ifdef ONEPPS | (1 ? VSIB_MODE_EMBED_1PPS_MARKERS : 0) #else | (0 ? VSIB_MODE_EMBED_1PPS_MARKERS : 0) #endif | (/*skip_samples=>*/0 & 0x0000ffff)) ); break; case 2: // 16 bottom bit streams vsib_ioctl(VSIB_SET_MODE, // S2 Mode - cwest --- testing with modes 2(16bit) 3(8bit)*/ (VSIB_MODE_MODE(/*vsib_mode=>*/2) | VSIB_MODE_RUN | (0 ? VSIB_MODE_GIGABIT : 0) #ifdef ONEPPS | (1 ? VSIB_MODE_EMBED_1PPS_MARKERS : 0) #else | (0 ? VSIB_MODE_EMBED_1PPS_MARKERS : 0) #endif | (/*skip_samples=>*/0 & 0x0000ffff)) ); break; case 3: // 8 bottom bit streams vsib_ioctl(VSIB_SET_MODE, // S2 Mode - cwest --- testing with modes 2(16bit) 3(8bit)*/ (VSIB_MODE_MODE(/*vsib_mode=>*/3) | VSIB_MODE_RUN | (0 ? VSIB_MODE_GIGABIT : 0) #ifdef ONEPPS | (1 ? VSIB_MODE_EMBED_1PPS_MARKERS : 0) #else | (0 ? VSIB_MODE_EMBED_1PPS_MARKERS : 0) #endif | (/*skip_samples=>*/0 & 0x0000ffff)) ); break; case 4: // 8 alternate bit streams vsib_ioctl(VSIB_SET_MODE, // 8-bit Mark5A. */ (VSIB_MODE_MODE(/*vsib_mode=>*/4) | VSIB_MODE_RUN | (0 ? VSIB_MODE_GIGABIT : 0) #ifdef ONEPPS | (1 ? VSIB_MODE_EMBED_1PPS_MARKERS : 0) #else | (0 ? VSIB_MODE_EMBED_1PPS_MARKERS : 0) #endif | (/*skip_samples=>*/0 & 0x0000ffff)) ); break; default: exit(printf("Unknown mode: %d\n",mode)); #else vsib_ioctl(VSIB_SET_MODE, // Set at run time (VSIB_MODE_MODE(mode) | VSIB_MODE_RUN | (0 ? VSIB_MODE_GIGABIT : 0) #ifdef ONEPPS | (1 ? VSIB_MODE_EMBED_1PPS_MARKERS : 0) #else | (0 ? VSIB_MODE_EMBED_1PPS_MARKERS : 0) #endif | (/*skip_samples=>*/0 & 0x0000ffff)) ); #endif } /* start_VSIB */ /* Upcoming wrshm.h: */ #define fourCharLong(a,b,c,d) ( ((long)a)<<24 | ((long)b)<<16 | ((long)c)<<8 | d ) #include "sh.h" /* typedef struct sSh { */ int relSeekBlocks; /* } tSh, *ptSh; */ int main(int argc, char *argv[]) { char *wr_version="1.0.1"; // Added 1PPS check int readMode; int blksize=32000; int totalblks=3600; /* 1 hour */ int memblks; char *memblk,*iptr,*optr,tmp_ptr,*local_knowledge; char *p,*fileout=NULL; int ndirs=1; pDir dirs; int i; double recordStart; double totalDur; int usleeps; int vsib_started = 0; int blk=10000; double mbits; int rate=32; // Default rate 32 MB/s #define FALSE 0 #define TRUE 1 int loop=FALSE,verbose=TRUE,tb_in_sec=TRUE; int c_mode=15,mode=3; /* Shared memory unique identifier (key) and the returned reference id. */ key_t shKey; int shId = -1; ptSh sh; #ifdef TIMED_START char datestr[100]; struct timeval current; struct timezone zone; struct tm *date; time_t now; #endif /* if (argc < 4) { fprintf(stderr, "%s: needs at least blocksize totalblocks ndirs { path%%d blks }\n", argv[0]); exit(EXIT_FAILURE); }*/ while ((tmp_ptr = getopt(argc, argv, "r:t:b:f:m:c:d:i:o:lvh")) != EOF) switch (tmp_ptr) { case 'r': // recording rate rate=atoi(optarg); if (verbose) fprintf(stderr,"Rate: %d\n",rate); if (!rate) exit(fprintf(stderr,"Rate given (%s) is zero\n",optarg)); break; case 'b': // block size blksize=atoi(optarg); if (verbose) fprintf(stderr,"Blocksize: %d\n",blksize); if (!blksize) exit(fprintf(stderr,"Block size given (%s) is zero\n",optarg)); break; case 'f': // blocks per file blk=atoi(optarg); if (verbose) fprintf(stderr,"Blocks per file: %d\n",blk); if (!blk) exit(fprintf(stderr,"Blocks per file given (%s) is zero\n",optarg)); break; case 't': // seconds to record if (optarg[strlen(optarg)-1]=='s') tb_in_sec=TRUE; else tb_in_sec=FALSE; totalblks=atoi(optarg); if (verbose) fprintf(stderr,"Recording time: %d\n",totalblks); if (!totalblks) exit(fprintf(stderr,"Time to record (%s) is zero\n",optarg)); break; case 'd': // Number of directories ndirs=atoi(optarg); if (verbose) fprintf(stderr,"Number of directories: %d\n",ndirs); if (!ndirs) exit(fprintf(stderr,"Number of directories to record (%s) is zero\n",optarg)); break; case 'c': // Compress on the fly if (!strcmp(optarg,"oooo")) { c_mode=0; fprintf(stderr,"No data!\n"); } else if (!strcmp(optarg,"ooox")) { c_mode=1; if (verbose) fprintf(stderr,"Channel one only\n"); } else if (!strcmp(optarg,"ooxo")) { c_mode=2; if (verbose) fprintf(stderr,"Channel two only\n"); exit(fprintf(stderr,"Not yet supported!\n")); } else if (!strcmp(optarg,"ooxx")) { c_mode=3; if (verbose) fprintf(stderr,"Channel one & two\n"); } else if (!strcmp(optarg,"oxoo")) { c_mode=4; if (verbose) fprintf(stderr,"Channel three only\n"); exit(fprintf(stderr,"Not yet supported!\n")); } else if (!strcmp(optarg,"oxox")) { c_mode=5; if (verbose) fprintf(stderr,"Channel one & three\n"); } else if (!strcmp(optarg,"oxxo")) { c_mode=6; if (verbose) fprintf(stderr,"Channel two & three\n"); exit(fprintf(stderr,"Not yet supported!\n")); } else if (!strcmp(optarg,"oxxx")) { c_mode=7; if (verbose) fprintf(stderr,"Channel one, two & three\n"); exit(fprintf(stderr,"Not yet supported!\n")); } else if (!strcmp(optarg,"xooo")) { c_mode=8; if (verbose) fprintf(stderr,"Channel four only\n"); exit(fprintf(stderr,"Not yet supported!\n")); } else if (!strcmp(optarg,"xoox")) { c_mode=9; if (verbose) fprintf(stderr,"Channel one & four\n"); exit(fprintf(stderr,"Not yet supported!\n")); } else if (!strcmp(optarg,"xoxo")) { c_mode=10; if (verbose) fprintf(stderr,"Channel two & four\n"); exit(fprintf(stderr,"Not yet supported!\n")); } else if (!strcmp(optarg,"xoxx")) { c_mode=11; if (verbose) fprintf(stderr,"Channel one, two & four\n"); exit(fprintf(stderr,"Not yet supported!\n")); } else if (!strcmp(optarg,"xxoo")) { c_mode=12; if (verbose) fprintf(stderr,"Channel three & four\n"); exit(fprintf(stderr,"Not yet supported!\n")); } else if (!strcmp(optarg,"xxox")) { c_mode=13; if (verbose) fprintf(stderr,"Channel one, three & four\n"); exit(fprintf(stderr,"Not yet supported!\n")); } else if (!strcmp(optarg,"xxxo")) { c_mode=14; if (verbose) fprintf(stderr,"Channel two, three & four\n"); exit(fprintf(stderr,"Not yet supported!\n")); } else if (!strcmp(optarg,"xxxx")) { c_mode=15; if (verbose) fprintf(stderr,"No compression\n"); } else { exit(fprintf(stderr,"Unknown channel mode %s\n",optarg)); } break; case 'o': // file to record fileout=(char *) strdup(optarg); if (verbose) fprintf(stderr,"Disk File: %s\n",fileout); if (!fileout) exit(fprintf(stderr,"File to record to (%s) is zero\n",optarg)); break; case 'm': // mode to record mode=atoi(optarg); if (verbose) fprintf(stderr,"Mode: %d\n",mode); if (mode<0 || mode>13) exit(fprintf(stderr,"invalid mode %s\n",optarg)); if (mode>4) fprintf(stderr,"invalid mode %s\n",optarg); break; case 'l': // loop recording loop=TRUE; if (verbose) fprintf(stderr,"Looping mode\n"); break; case 'v': // verbose verbose=TRUE; if (verbose) fprintf(stderr,"Verbose mode\n"); break; case 'h': // help or unknown case '?': exit(fprintf(stderr, "usage : %s -r rate(MHz) -t recording_time(blks_or_secs) -b blksize -f blk -o filename -c compact_mode -m mode -l (loop) -h (help) -v (verbose)\nVersion %s\n", argv[0],wr_version)); } // Rounding errors (I think) mess this step up // if (tb_in_sec) totalblks=(((float)totalblks)*rate*1000000)/blksize; if (verbose) fprintf(stderr,"Total number of blocks: %d\n",totalblks); if (verbose) fprintf(stderr,"blocksize: %d\n",blksize); if (verbose) fprintf(stderr,"No. blocks per file: %d\n",blk); if (!fileout) fileout=strdup("/i1/t/test%03d"); #define TIMESTART(i) \ { dirs[i].prevOperTime = tim(); } #define TIMESTOP(i) \ { double dur = tim() - dirs[i].prevOperTime; \ if (dur > dirs[i].maxOperTime) dirs[i].maxOperTime = dur; } /* Init variables according to command line, allocate buffers. */ readMode = (strstr(argv[0], "rd") != NULL); if (readMode) { /* Read from disk, write to stdout to VSIB board. */ // if (filein) vsib_fileno = fopen(filein,"w"); else vsib_fileno = STDOUT_FILENO; } else { // if (filein) vsib_fileno = fopen(filein,"r"); else vsib_fileno = STDIN_FILENO; } // blksize = atoi(argv[1]); // totalblks = atoi(argv[2]); /* memblks = atoi(argv[ ]); */ memblks = 1; assert( (memblk = malloc(memblks*blksize)) != NULL ); #if 0 /* Init memblk with random values. */ { double st = tim(); fprintf(stderr, "Initializing memory buffer with rand()..."); fflush(stdout); randbuf(memblk, (memblks*blksize)); fprintf(stderr, "took %f seconds.\n", tim()-st); } #endif // ndirs = atoi(argv[3]); // The names // assert( (argc >= (4 + ndirs*2)) ); /* Allocate one extra struct for call-to-call time statistics. */ assert( (dirs = malloc((ndirs+1)*sizeof(tDir))) != NULL ); for (i=0; icontrol' shared memory. */ shKey = fourCharLong('v','s','i','b'); assert( (shId = shmget(shKey, sizeof(tSh), IPC_CREAT | 0777)) != -1 ); assert( (sh = (ptSh)shmat(shId, NULL, 0)) != (void *)-1 ); sh->relSeekBlocks = 0; local_knowledge=malloc(160); if (!strlen(sh->vsi_header)) { iptr=malloc(HEAD_SIZE);optr=iptr; optr+=sprintf(optr,"$EXP_CODE \n"); optr+=sprintf(optr,"$EXP_MODE \n"); optr+=sprintf(optr,"$SOURCE_NAME \n"); optr+=sprintf(optr,"$SOURCE_RA \n"); optr+=sprintf(optr,"$SOURCE_DEC \n"); optr+=sprintf(optr,"$STATION_NAME \n"); optr+=sprintf(optr,"$STATION_POSITION \n"); optr+=sprintf(optr,"$STATION_CLOCK \n"); optr+=sprintf(optr,"$FREQUENCY_CH00 \n"); strncpy(sh->vsi_header,iptr,HEAD_SIZE); free(iptr); } sh->vsibcliMode=VCM_record; // Start up and record #if 0 Opening the device special file already does this. For write() this open()-related (extra) DMA reset clears memory buffers and r/w pointers with arg==0. /* Init DMA. */ vsib_ioctl(VSIB_RESET_DMA, 0); #endif /* Start the board. (After opening it is still stopped.) */ /* For disk write, start VSIB first and write to disk later. */ /* For disk read, read first and start VSIB later. */ if (readMode) { vsib_started = 0; } else { #ifdef TIMED_START // This section of the code delays the start to a range of (0.3 -> 0.8) seconds // This is done to ensure the program knows what second it is starting on. // system("date"); gettimeofday(¤t, &zone); fprintf(stderr, "%g\n", current.tv_usec/1000000.0); while(current.tv_usec < 300000 || current.tv_usec > 800000){ usleep(100); gettimeofday(¤t, &zone); fprintf(stderr, "%g\n", current.tv_usec/1000000.0); } now = current.tv_sec + 1; date = gmtime(&now); // will start on the next second strftime(datestr, 99, "%Y %B %e %H:%M:%S UTC", date); fprintf(stderr, "Start will occur at: %s\n", datestr); strftime(datestr, 99, "%Y%m%d:%H%M%S\n", date); sprintf(local_knowledge, "$HEAD_SIZE %5d\n$EXP_BMODE %01d\n$START%29s", HEAD_SIZE,mode,datestr); #endif start_VSIB(mode); } /* Start looping for total number of blocks. */ usleeps = 0; recordStart = tim(); TIMESTART(ndirs); /* call-to-call (not per file) */ //#ifdef LOOP blk=0; while (sh->vsibcliMode!=VCM_stop && blkvsibcliMode==VCM_record) { //#else // for (blk=0; blkrelSeekBlocks) { int bl; /* Adjust 'blk' (and i and newBlocks) based on 'sh->relSeekBlocks'. */ /* xxx: initially only within a single open file */ bl = dirs[i].nowBlocks + sh->relSeekBlocks; if (bl < 0) { sh->relSeekBlocks -= bl; bl = 0; } bl = dirs[i].nowBlocks + sh->relSeekBlocks; if (bl > dirs[i].blocksPerFile) { sh->relSeekBlocks -= (bl - dirs[i].blocksPerFile); bl = dirs[i].blocksPerFile; } assert( lseek(dirs[i].fid, (bl*blksize), SEEK_SET) != (off_t)-1 ); fprintf(stderr, "at block = %d, repositioning %+d blocks (to byte offset %d)\n", blk, sh->relSeekBlocks, (bl*blksize) ); dirs[i].nowBlocks = bl; blk += sh->relSeekBlocks; /* xxx: cannot really update i... */ /* Seeking done, notify shared memory. */ sh->relSeekBlocks = 0; } /* if external adjustments */ if (dirs[i].nowBlocks >= dirs[i].blocksPerFile) { /* Open a new file in this directory / template. */ char pn[255]; int n = blk / dirs[i].blocksPerFile; snprintf(pn, sizeof(pn), dirs[i].nameTemplate, n); if (n==0) TIMESTART(i); /* only for first file */ if (readMode) { assert((dirs[i].fid=open(pn, O_RDONLY)) != -1 ); } else { assert((dirs[i].fid=creat(pn, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH))!=-1); #ifdef TIMED_START // This section of code is used to insert a timestamp into the datafile // without this it could be very difficult to know which point in time this file // really comes from assert( write(dirs[i].fid, datestr, 16) == 16); assert( write(dirs[i].fid, local_knowledge, strlen(local_knowledge)) == strlen(local_knowledge)); assert( write(dirs[i].fid, sh->vsi_header, HEAD_SIZE-strlen(local_knowledge)) == HEAD_SIZE-strlen(local_knowledge)); #endif /* O_SYNC here doesn't change 2.4.xx buffer flush behavior. */ } #ifdef TIMED_START system("date"); fprintf(stderr, "TIME: %s%g\n", datestr, current.tv_usec/1000000.0); #endif fprintf(stderr, "at block = %d, opened file '%s'\n", blk, pn); dirs[i].nowBlocks = 0; } /* Write (or read) one block. */ /* xxx: need to add '-1' error checks to VSIB read()/write() calls */ p = &(memblk[(blk % memblks)*blksize]); if (readMode) { size_t nwritten; assert( (read(dirs[i].fid, p, blksize)) == blksize ); /* Write a block to VSIB; if not enough space, sleep a little. */ nwritten = write (vsib_fileno, memblk, blksize); while (nwritten < (size_t) blksize) { /* Not space for one full block in buffer, start VSIB transmission */ /* and wait for vacant space. */ if (readMode) { if (!vsib_started) { fprintf(stderr, "starting vsib because bigbuf full\n"); /* xxx: reload PLX FIFOs */ vsib_ioctl(VSIB_RESET_DMA, /*skip_clear=>*/1); start_VSIB(mode); vsib_started = 1; } } usleep(1000); /* a small amount, probably ends up to be 10--20msec */ usleeps++; nwritten += write (vsib_fileno, memblk+nwritten, blksize-nwritten); } /* while not at least one full block in VSIB DMA ring buffer */ } else { size_t nread,nwrite; /* Read a block from VSIB; if not enough, sleep a little. */ nread = read (vsib_fileno, memblk, blksize); #ifdef ONEPPS if (!dirs[i].nowBlocks) { // new file iptr=memblk; if ((iptr[0]&0xFF)==0xFF)) fprintf(stderr,"1PPS OKAY\r"); else fprintf(stderr,"1PPS transition ABSENT (%02x) at %s\n", iptr[0],datestr);} #endif while (nread < (size_t) blksize) { /* Not one full block in buffer, wait. */ usleep(1000); /* a small amount, probably ends up to be 10--20msec */ usleeps++; nread += read (vsib_fileno, memblk+nread, blksize-nread); } /* while not at least one full block in VSIB DMA ring buffer */ nwrite=nread; // Write it all out switch (c_mode) { // I create the first byte separately as the output buffer // is the input buffer. This is not needed is the btye // selecting & shifting is atomic case 0: nwrite=0; break; // Skip the write case 1: // Channel 1 iptr=memblk; tmp_ptr = *iptr & 0x03; iptr++; tmp_ptr |= (*iptr & 0x03)<<2; iptr++; tmp_ptr |= (*iptr & 0x03)<<4; iptr++; tmp_ptr |= (*iptr & 0x03)<<6; iptr++; memblk[0]=tmp_ptr; optr=memblk;optr++; for (rate=1; rate<(int) nread/4; rate++) { *optr = *iptr & 0x03; iptr++; *optr |= (*iptr & 0x03)<<2; iptr++; *optr |= (*iptr & 0x03)<<4; iptr++; *optr |= (*iptr & 0x03)<<6; iptr++; optr++; } nwrite = nread/4; break; case 3: // Channel 1+2 iptr=memblk; tmp_ptr = *iptr & 0x0F; iptr++; tmp_ptr |= (*iptr & 0x0F)<<4; iptr++; memblk[0]=tmp_ptr; optr=memblk;optr++; for (rate=1; rate<(int) nread/2; rate++) { *optr = *iptr & 0x0F; iptr++; *optr |= (*iptr & 0x0F)<<4; iptr++; optr++; } nwrite = nread/2; break; case 5: // Channel 1+3 iptr=memblk; tmp_ptr = (*iptr & 0x03)|(*iptr & 0x30)>>2; iptr++; tmp_ptr |= (*iptr & 0x03)<<4|(*iptr & 0x30)<<2; iptr++; *memblk=tmp_ptr;optr=memblk;optr++; for (rate=1; rate<(int) nread/2; rate++) { *optr = (*iptr & 0x03)|(*iptr & 0x30)>>2; iptr++; *optr |= (*iptr & 0x03)<<4 | (*iptr & 0x30)<<2; iptr++; optr++; } nwrite = nread/2; break; case 15: // Normal full write default: } #ifdef FILTER if (filter) { float h_parms[] = { -0.0371458, 0, -0.0373675, 0, -0.0375406, 0, -0.0376645, 0, -0.0377390, 0, 0.9252135, 0, -0.0377390, 0, -0.0376645, 0, -0.0375406, 0, -0.0373675, 0, -0.0371458}; // 21 parm FIR float hilb_parms[]={0, -0.0909457, 0, -0.1273240, 0, -0.2122066, 0, -0.6366197, 0, 0.6366197, 0, 0.2122066, 0, 0.1273240, 0, 0.0909457, 0}; //17 parm hilbert int **i_ptr,nf;float f; int xc[]={1,-1,3,-3}; // bits to values (antf) int cx[]={3,x,1,x,0,x,2}; // map back //int xc[]={3,-1,1,-3}; // bits to values (vlba) //int cx[]={3,x,1,x,2,x,0}; // map back for (nnn=4;n>=nread/nwrite;n--) optr=iptr=memblk; for (nf=0;nf<(maxnf+maxnf);nf+=4) { i_ptr[][nf] =xc[*iptr&0x03]; i_ptr[][nf+1]=xc[*iptr&0x0C>>2]; i_ptr[][nf+2]=xc[*iptr&0x30>>4]; i_ptr[][nf+3]=xc[*iptr&0xC0>>6]; iptr++;} for (rate=0; rate<(int) nwrite; rate++) { for (f=0,nf=0;nf>2]; i_ptr[][nf+2]=xc[*iptr&0x30>>4]; i_ptr[][nf+3]=xc[*iptr&0xC0>>6]; iptr++;}} // if ((nnn%4)==3) optr=(i_ptr[0])|(i_ptr[1]<<2)|(i_ptr[3]<<4)|(i_ptr[3]<<6); } } // Filter #endif assert( (write(dirs[i].fid, p, nwrite)) == nwrite ); } TIMESTOP(i); /* accumulates close--open-write in worst case */ TIMESTOP(ndirs); /* call-to-call */ TIMESTART(i); TIMESTART(ndirs); dirs[i].nowBlocks++; /* Time to switch to another file? */ if (dirs[i].nowBlocks >= dirs[i].blocksPerFile) { /* Close the ready file before opening a new. */ assert( (close(dirs[i].fid) != -1) ); #ifdef TIMED_START gettimeofday(¤t, &zone); if(current.tv_usec/1000000.0 > 0.5) now = current.tv_sec + 1; else now = current.tv_sec; date = gmtime(&now); // will start on the next second strftime(datestr, 99, "%Y%m%d:%H%M%S\n", date); sprintf(local_knowledge, "$HEAD_SIZE %5d\n$EXP_BMODE %01d\n$START%29s", HEAD_SIZE,mode,datestr); #endif } if (loop) blk=(++blk)%totalblks; else blk++; } /* while loop */ TIMESTOP(ndirs); totalDur = tim() - recordStart; /* Wait for the data to get out of VSIB. */ if (readMode) { unsigned long b; if (!vsib_started) { fprintf(stderr, "all written to bigbuf, starting vsib...\n"); /* xxx: reload PLX FIFOs */ vsib_ioctl(VSIB_RESET_DMA, /*skip_clear=>*/1); start_VSIB(mode); usleep(2000000); /* xxx */ } #if 1 vsib_ioctl(VSIB_GET_BYTES_IN_BIGBUF, (unsigned long)&b); while (b > 0) { fprintf(stderr, "Waiting for ring buffer to empty (%lu bytes, sl=%d)\n", b, usleeps); /* Still bytes in bigbuf waiting for transmit. */ usleep(500000); /* 0.5sec */ usleeps++; vsib_ioctl(VSIB_GET_BYTES_IN_BIGBUF, (unsigned long)&b); } /* while not bigbuf empty */ #endif } /* if readMode, wait for data to get out of ring buffer */ /* Stop the board, first DMA, and when the last descriptor */ /* has been transferred, then write stop to board command register. */ vsib_ioctl(VSIB_DELAYED_STOP_DMA, 0); { unsigned long b; vsib_ioctl(VSIB_IS_DMA_DONE, (unsigned long)&b); while (!b) { fprintf(stderr, "Waiting for last DMA descriptor (sl=%d)\n", usleeps); usleep(100000); usleeps++; vsib_ioctl(VSIB_IS_DMA_DONE, (unsigned long)&b); } } vsib_ioctl(VSIB_SET_MODE, VSIB_MODE_STOP); /* Final report. */ mbits = 8.0*totalblks*blksize/totalDur/1000.0/1000.0; fprintf(stderr, "Took %f seconds, %f Mbits(dec)/s (%.1f%% of PCI33), usleeps = %d.\n", totalDur, mbits, mbits/(33.0*4.0*8.0)*100.0, usleeps ); for (i=0; i<=ndirs; i++) { fprintf(stderr, "%s max. %f seconds.\n", dirs[i].nameTemplate, dirs[i].maxOperTime ); } /* for each directory */ /* Remove shared memory to mark that 'wr/rd' is no more running. */ // if ((shId != -1) && (sh != (ptSh)-1) && (sh != NULL)) { // assert( shmctl(shId, IPC_RMID, NULL) == 0 ); // assert( shmdt(sh) == 0 ); //} // if shared memory was allocated return(EXIT_SUCCESS); } /* main */