/* * ^NAME: esmr_read.c * * ^PROJECT: GSFC V0 DAAC * * ^SYNOPSIS: esmr_read < xxx.tbn > * * ^DESCRIPTION: * This software emulates the functionality of the Pascal program Rdtbnav * that was submitted to the DAAC with the data files. Its purpose is to make * the binary data files generated by the ESMR instrument during the * TOGA-COARE field experiment readable on UNIX systems. * * Background and data file structure: * * The ESMR data files were generated on a DOS system. Each file consists * of the instrument's output during one flight. The naming convention for * these files is .tbn. The data is stored in 64-byte, fixed- * length records each containing the following information: * - Brightness temperature for each of 39 beam positions(1 scan); * - A precise time code for the end of each scan * - Earth location data for the aircraft * - Several pieces of aircraft data: pitch, roll, etc. * * ^ALGORITHM: * The ESMR data files are formatted in 64-byte records as follows: * bytes 1-43 contain individual data values * bytes 44-61 are to be read as pairs into short integers * bytes 62-64 are empty * Program esmr_read ingests a 64-byte record and assigns the bytes to * variables as indicated in the format documentation. Function * show_tbnav then displays the data values on the terminal screen. The file * processing loop is user-driven. The Library function fseek positions the * read pointer at the beginning of a user-requested record. * * ^NOTES: File ESMR.dat containing the first ten ESMR data records from * file 011.tbn are provided for validation of data output from this program. * * ^LIMITATIONS: A byte-swapping function (swap_short) was required to read * the data on the DAAC's SGI machines. To help determine whether an * implementation requires a byte-swap, the bit-dumping function (bit_print) * may be enabled. * * ^AUTHOR: Patricia L. Hrubiak * * ^ADDRESS: Hughes STX * 7601 Ora Glen Dr., Suite 300 * Greenbelt, MD 20770 * * ^CREATED: 30 Dec 93 */ #ifndef __lint static char *SccsId = "@(#)esmr_read.c 1.1 2/28/94"; #endif #include #include /* * Global variables */ typedef struct { char bptemp[39]; /* Brightness temps for 1 scan */ char hour,min,sec,secfrac; /* time components*/ char other[21]; /* 2-byte data values */ } tbnavtype; /* structure declaration */ tbnavtype tbnav; /* structure variable declaration */ FILE *ifp, *ofp; /* pointers to io files */ int c = 0; /* loop control variable */ char byte_0,byte_1; /* byte buffer/swap argument */ short swapt; /* returned integer from short_swap*/ long isnum; /* variable for read pointer positioning*/ int jul_day, lat, latfrac, lon, lonfrac, alt, head, roll, pitch; /*Julian day, latitude, latitude fraction, longitude, longitude fraction, altitude, heading, aircraft roll, aircraft pitch*/ double clat, clon, csec, calt, cpitch, croll, chead; /*floating point representations of latitude, longitude, time, altitude, aircraft pitch, aircraft roll, aircraft heading*/ /* * ^FUNCTION: bit_print * * ^ARGUMENTS: * Type Variable In/Out Description * ---------------------------------------- * short v in dumps bits in * variable * ^NOTES: * Function bit_print prints out a short integer in binary. Decomment it * if you need it to determine if a byte-swap is indicated. */ /*void bit_print(short v) { int i, mask = 1 << 15; ++ mask = 100 ... 0++ for (i = 1; i <= 16; ++i) { putchar(((v & mask) == 0) ? '0' : '1'); v <<= 1; if (i % 8 == 0 && i != 16) putchar(' '); } }*//* end bit-print */ /* * ^FUNCTION: swap_short * * ^RETURN VALUE: short integer y.i, a swapped pair of bytes * * ^ARGUMENTS: * Type Variable In/Out Description * ---------------------------------------- * char p0 in byte * char p1 in byte * * ^NOTES: Function swap_short is called with two 1-byte character arguments * which together comprise a data value and loads them into a short integer * in the reverse of the order in which they were read. This addresses the * byte-order assignment difference between the DAAC's SGI implementation and * the DOS implementation on which the ESMR files were generated. */ short swap_short(char p0,char p1) { union bytes { short i; char c[2]; }; union bytes y; y.c[0] = p1; y.c[1] = p0; return(y.i); } /* end byte swap */ /* * ^FUNCTION: show_tbnav * * ^ARGUMENTS: * Type Variable In/Out Description * ----------------------------------------- * structure tb_nav in a 64-byte (char) record * * ^NOTES: Function show_tbnav assigns the values ingested in structure * tbnav to specific variables and displays the record on the screen. * The 45th through the 61st elements of the record are paired bytes to be * read into short integers then converted to floating point variables. The * bytes are swapped then assigned to variables by a switch that uses the * value of array index k to determine what an input should be from its * position in array "order". */ void show_tbnav() { int k, tbn; printf( "\nLeft Brightness Temps:\n"); for (k = 0; k <= 18; k++) { tbn = tbnav.bptemp[k]+100; printf("%d\t",tbn); } printf("\n\nNadir Brightness Temp:\t%d\n",(tbnav.bptemp[19]+100)); printf("\nRight Brightness Temps:\n"); for (k =20; k <= 38; k++) { tbn = tbnav.bptemp[k]+100; printf("%d\t",tbn); } for (k = 0; k <= 20; k+=2) { /* printf("\nOther[%d]=: %d\n",k,tbnav.other[k]); */ byte_0 = tbnav.other[k]; byte_1 = tbnav.other[k+1]; swapt = swap_short(byte_0,byte_1); /* bit_print(swapt);*/ /* printf("\nelement[%d] of array other =: %d\n",k,swapt);*/ switch (k) { case 0 : jul_day = swapt; break; case 2 : lat = swapt; break; case 4 : latfrac = swapt; clat = lat + .0001*latfrac; break; case 6 : lon = swapt; break; case 8 : lonfrac = swapt; clon = lon + .0001*lonfrac; break; case 10 : alt = swapt; calt = 10.*alt; break; case 12 : head = swapt; chead = head/10.; break; case 14 : roll = swapt; croll = roll/10.; break; case 16 : pitch = swapt; cpitch = pitch/10.; } /* end case */ } /* End of display of other */ csec = tbnav.sec + .01*tbnav.secfrac; printf("\n\nJulian Day %d Time: %d:%d:%5.2f\n", jul_day,tbnav.hour,tbnav.min,csec); printf("\nLatitude: %10.4f\tLongitude: %10.4f\n",clat,clon); printf("\nAltitude: %7.0f\tHeading: %8.2f\n",calt,chead); printf("\nPitch: %8.2f\tRoll:\t%8.2f\n",cpitch,croll); } /* end function show_tbnav */ /* * ^FUNCTION: main * * ^ALGORITHM: The main program is driven by a "while" loop and offers the * user the options of displaying the next record in sequence, skipping to * a desired record or quitting the program. Keying in an invalid value * such as characters or a negative number returns the prompt. Keying in a * number greater than the number of records in the file returns a message * stating the number of records in the file followed by the prompt. */ main() { int buf, tot, sub_tot, j, go, code; long pos; /*variable to hold file position*/ char infn[8], option[10]; /*infn=filename, option=user input*/ extern int errno, sys_nerr; /*variable to capture system error*/ extern char *sys_errlist[]; /*array of system error messages*/ /* * Prompt user for input filename */ printf("Filename of binary TBNAV file: "); scanf("%8s", infn); /* * Open input file */ if ((ifp = fopen (infn,"r")) == NULL) { if (errno >0 && errno < sys_nerr) { fprintf(stderr," (%s)\n",sys_errlist[errno]); errno = 0; } exit(0); } /* * Retrieve File Size */ fseek(ifp, 0, 2); pos = ftell(ifp)/64; /* * Reset read pointer to beginning of file */ fseek(ifp, 0, 0); printf("\nFile pointer positioned at byte %d of %8s\n",ftell(ifp)/64,infn); /* * Loop through input file ... */ while (c++ != EOF) { /* * Prompt user for request */ printf("\nPress 'n' to continue, a number to skip, or 'q' to quit: "); scanf("%10s", &option); if(option[0] == 'q') { exit(0); } else if (option[0] == 'n') { buf = fread((char *) &tbnav, sizeof(tbnav), 1, ifp); printf("\nRecord %d:\n\n",ftell(ifp)/64); show_tbnav(); } else { sscanf(option, "%d", &isnum); if(isnum <= pos) { code = fseek(ifp, ((isnum-1)*64), 0); if (code == 0) { buf = fread((char *) &tbnav,sizeof(tbnav),1,ifp); printf("\nRecord %d:\n\n",ftell(ifp)/64); show_tbnav(); } } else { printf("\nFile %8s contains %d records. \n",infn,pos); } } } /* END while-not-EOF */ } /* END main program */