ocssw  1.0
/disk01/web/ocssw/build/src/neb2raw_seawifs/neb2raw.c (r8096/r4494)
Go to the documentation of this file.
00001 /* ============================================================================ */
00002 /*                                                                              */
00003 /* neb2raw - converts OSC nebula files to native S/C frames (13860-byte,10-bit) */
00004 /*                                                                              */
00005 /* Synopsis:                                                                    */
00006 /*                                                                              */
00007 /*  neb2raw [ -f nebula-file ] [ -o raw-file ] [-b backorbit-file ]     */
00008 /*                                      */
00009 /*  nebula-file:    name of input nebula file to read           */
00010 /*          (default is to read from standard input, see warning)   */
00011 /*  raw-file:   name of output file for raw S/C frames          */
00012 /*          (default is to write to standard output)        */
00013 /*  backorbit-file: name of output file for back-orbit SOH messages     */
00014 /*          (default is to discard back-orbit records)      */
00015 /*                                                                              */
00016 /* Description:                                 */
00017 /*                                                                      */
00018 /*  A SeaWiFS data file in OSC's Nebula format is provided to the program   */
00019 /*  via standard input or the -f option flag.  The file is searched, record */
00020 /*  by record, to find any of three types of data records:          */
00021 /*                                                                      */
00022 /*  1) HRPT records, which are stored as single nebula records consisting   */
00023 /*     of: the 40-byte nebula header and 13862-bytes of the S/C frame.  An  */
00024 /*     HRPT frame is actually 13862.5 bytes, but the last half-byte gets    */
00025 /*     truncated by the OSC front-end.  There is no useful data longward of */
00026 /*     byte 13735 (the 20-bit pad), so this trunctaion doesn't matter. This */
00027 /*     program extracts the first 13860 bytes of the HRPT record, and   */
00028 /*     writes it either to standard output, or to a named file provided via */
00029 /*     the -o option.                           */
00030 /*                                      */
00031 /*  2) Stored GAC/LAC records, which are divided over four 3540-byte nebula */
00032 /*     records. The first record in the sequence contains a 40-byte nebula  */
00033 /*     header, an 8-byte HDLC header, a 2-byte length field, and 3490 bytes */
00034 /*     of a recorded S/C frame.  The next two records contain a 40-byte neb */
00035 /*     header, an 8-byte HDLC header, and 3492 bytes of the S/C frame.  The */
00036 /*     final record in the sequence has the 40-byte neb header, the 8-byte  */
00037 /*     HDLC header, the remaining 3386 bytes of the S/C frame, and 103  */
00038 /*     bytes of padding.  The program checks for proper sequence order, but */
00039 /*     it can not distinguish between the middle two records.  The raw  */
00040 /*     frames are reconstructed from the nebula record and written to   */
00041 /*     standard output, or to a named file provided with the -o option.     */
00042 /*     Out-of-order sequences, which are most likely associated with a  */
00043 /*     corrupted HDLC header, are discarded.                */
00044 /*                                                                      */
00045 /*  3) Logger (back-orbit) records, which are stored in 3540-byte nebula    */
00046 /*     records. Each record consists of a 40-byte neb header and an 8-byte  */
00047 /*     HDLC header, followed by a series of variable-length spacecraft  */
00048 /*     messages originating from the GIM or SCM memory subsystem.  Each of  */
00049 /*     these messages are just wrappers around another spacecraft message.  */
00050 /*     The program reads the 3540-byte nebula records and writes a 3502 */
00051 /*     byte record containing the HDLC header and the 3492 bytes that       */
00052 /*     follow it. The last two bytes are a placeholder to account for the   */
00053 /*     CRC bytes that are stored in the SeaSpace version of the back-orbit  */
00054 /*         file, but that are not available from the nebula input file.     */
00055 /*                                          */
00056 /*  Generally, nebula files from OSC will contain either type 1 records, or */
00057 /*  type 2 and 3 records, but any combination can be handled.  Nebula   */
00058 /*  records which do not meet one of these three types are probably just    */
00059 /*  status messages from OSC's high-speed front-end.            */
00060 /*                                                                      */
00061 /*                                      */
00062 /* Warnings:                                    */
00063 /*                                      */
00064 /*  Due to the random-seek capability required to step through the nebula   */
00065 /*  records, the program can not read from a pipe.              */
00066 /*                                      */
00067 /*                                      */
00068 /* See Also:                                    */
00069 /*                                      */
00070 /*  raw2L0                                  */
00071 /*                                                                              */
00072 /*                                                                              */
00073 /* Written By:                                                                  */
00074 /*                                                                              */
00075 /*     Bryan A. Franz                                                           */
00076 /*     General Sciences Corp.                                                   */
00077 /*     4 June 1996                                                              */
00078 /*                                                                              */
00079 /* ============================================================================ */
00080 
00081 #include <stdint.h>
00082 #include <stdio.h>
00083 #include <stdlib.h>
00084 #include <fcntl.h>
00085 #include <string.h>
00086 #include <errno.h>
00087 #include <unistd.h>
00088 #include "loghdr.h"
00089 
00090 
00091 #define CMD_ARGS        "f:o:b:"            /* Valid commandline options    */
00092 #define  HRPTRECLEN 13902           /* Length of HRPT nebula record */
00093 #define  STORRECLEN 3540            /* Length of recorded data rec  */
00094 #define  FRAMELEN   13860           /* Bytes in spacecraft mnf  */
00095 #define SIZEOFBUF       (16*10124)      /* Data buffer length       */
00096 #define SIZEOFHDR   sizeof(struct LOGHDR)   /* Nebula header length     */
00097 #define SIZEOFHDLC  8           /* HDLC header length       */
00098 #define GACID       80          /* GAC ID in HDLC header    */
00099 #define LACID       96          /* LAC ID in HDLC header    */
00100 #define BRBID       64          /* Back-orbit ID in HDLC header */
00101 #define IDBYTE      3           /* ID byte location HDLC header */
00102 #define SQBYTE      5           /* Sequence # location HDLC hdr */
00103 
00104 
00105 
00106 int issoh( int addr);
00107 int extract_loggermsgs( FILE *outfp, BYTE *buf, int buflen);
00108 
00109 
00110 
00111 /* ---------------------------------------------------------------------------- */
00112 /* main                                     */
00113 /* ---------------------------------------------------------------------------- */
00114 int main (int argc, char* argv[])
00115 {
00116     FILE        *infp       = stdin;    /* Input file pointer   */
00117     FILE        *outfp      = stdout;   /* Output file pointer  */
00118     FILE        *brbfp      = NULL;     /* Back-orbit file pntr */
00119 
00120     struct LOGHDR       hdrbuf;             /* Nebula header buffer */
00121     struct LOGHDR       *hdr = &hdrbuf;         /* Pointer to neb hdr   */
00122     unsigned char       hdlc[SIZEOFHDLC];       /* HDLC header buffer   */
00123     unsigned char       buf[SIZEOFBUF];         /* Data buffer      */
00124 
00125     int32_t                inRecNum        = 0L;        /* # Input neb records  */
00126     int32_t                outRecNum       = 0L;        /* # Output mnf records */
00127     int32_t                brbRecNum       = 0L;        /* # Output brb records */
00128 
00129     int32_t                inPos        = 0L;       /* Byte pos in neb file */
00130     int                 swap            = 0;        /* Byte swapping flag   */
00131     int                 first           = 1;        /* First neb rec flag   */
00132     int         partnum     = 0;        /* Frame sequence flag  */
00133 
00134     extern int      opterr;                         /* used by getopt()     */
00135     extern int      optind;                         /* used by getopt()     */
00136     extern char    *optarg;                         /* used by getopt()     */
00137     int            c;                           /* used by getopt()     */
00138  
00139     /*                                      */
00140     /* Process command-line inputs                      */
00141     /*                                      */
00142     while ((c = getopt(argc, argv, CMD_ARGS)) != EOF) {
00143         switch (c) {
00144             case 'f':
00145                 if ( (infp = fopen(optarg,"r")) == NULL ) {
00146                   fprintf(stderr,"%s: Error opening %s for reading.\n", argv[0], optarg);
00147                   exit(1);
00148                 }
00149                 break;
00150             case 'o':
00151                 if ( (outfp = fopen(optarg,"w")) == NULL ) {
00152                   fprintf(stderr,"%s: Error opening %s for writing.\n", argv[0], optarg);
00153                   exit(1);
00154                 }
00155                 break;
00156             case 'b':
00157                 if ( (brbfp = fopen(optarg,"w")) == NULL ) {
00158                   fprintf(stderr,"%s: Error opening %s for writing.\n", argv[0], optarg);
00159                   exit(1);
00160                 }
00161                 break;
00162             default:
00163                   fprintf(stderr,"Usage: %s [-f input-nebula-filename]\n", argv[0]);
00164                   fprintf(stderr,"          [-o output-raw-filename]\n");
00165                   fprintf(stderr,"          [-b backorbit-filename]\n");
00166                   break;
00167         }
00168     }
00169 
00170 
00171     /*                                      */
00172     /* Read through end of input file                       */
00173     /*                                      */
00174     while ( fread(hdr, SIZEOFHDR, 1, infp) == 1 ) {
00175 
00176         /*                                  */
00177         /* If this is the first Nebula record processed, determine swapping for */
00178         /* Nebula macros.                           */
00179         /*                                  */
00180         if (first) {
00181             first = 0;
00182             switch (hdr->headerVersion) {
00183               case 0x0100 : 
00184                   swap = 1;
00185                   break;
00186               case 0x0001 : 
00187                   swap = 0;
00188                   break;
00189               default: 
00190                   swap = 0;
00191                   break;
00192             }
00193         }
00194 
00195         /*                                  */
00196         /* Do some quality checking on the Nebula header            */
00197         /*                                  */
00198         if ( HDR_WORD(hdr->headerVersion) != 1) {
00199             fprintf(stderr,"Bad nebula header at record %d\n", inRecNum);
00200             fclose(infp);
00201             exit(5);
00202         }
00203 
00204         /*                                  */
00205         /* If this is the record we want, read the data             */
00206         /*                                  */
00207         if (HDR_LONG(hdr->blockSize) == HRPTRECLEN) {
00208 
00209             /*                                  */
00210             /* HRPT Record, just copy data from input to output         */
00211             /*                                  */
00212             if (fread ( buf, FRAMELEN, 1, infp) != 1 ) {
00213                 fprintf(stderr,"Error reading input file at record %d\n", inRecNum);
00214                 exit(1);
00215             }
00216             if (fwrite( buf, FRAMELEN, 1, outfp) != 1) {
00217                 fprintf(stderr,"Error writing output file at record %d\n", outRecNum);
00218                 exit(1);
00219             } else 
00220                 outRecNum++;
00221 
00222         } else if (HDR_LONG(hdr->blockSize) == STORRECLEN) {
00223 
00224             /*                                  */  
00225             /* Possibly part of a stored GAC or LAC record, or it maybe     */
00226             /* some back-orbit telemetry messages. Examine the HDLC header. */
00227             /*                                  */
00228             if (fread ( hdlc, SIZEOFHDLC, 1, infp) != 1 ) {
00229                 fprintf(stderr,"Error reading input file at record %d\n", inRecNum);
00230                 exit(1);
00231             }
00232             if (hdlc[IDBYTE] == GACID || hdlc[IDBYTE] == LACID) {
00233 
00234                 /*                              */
00235                 /* Part of stored LAC or GAC, but which part.           */
00236                 /*                              */
00237                 if ( partnum == 0 && hdlc[SQBYTE] == 2 ) {
00238 
00239                     /*                              */
00240                     /* Beginning of sequence, read into beginning of buffer.    */
00241                     /*                              */
00242                     partnum++;
00243                     fseek(infp,2,SEEK_CUR); /* Skip msg length field */
00244                     if (fread ( &buf[0], 1, 3490, infp) != 3490 ) {
00245                         fprintf(stderr,"Error reading input file at record %d\n", inRecNum);
00246                         exit(1);
00247                     }
00248 
00249                 } else if (partnum == 1 && hdlc[SQBYTE] == 0) {
00250 
00251                     /*                              */
00252                     /* Middle segment (assumed to be second)            */
00253                     /*                              */
00254                     partnum++;
00255                     if (fread ( &buf[3490], 1, 3492, infp) != 3492 ) {
00256                         fprintf(stderr,"Error reading input file at record %d\n", inRecNum);
00257                         exit(1);
00258                     }
00259 
00260                 } else if (partnum == 2 && hdlc[SQBYTE] == 0) {
00261 
00262                     /*                              */
00263                     /* Middle segment (assumed to be third)         */
00264                     /*                              */
00265                     partnum++;
00266                     if (fread ( &buf[6982], 1, 3492, infp) != 3492 ) {
00267                         fprintf(stderr,"Error reading input file at record %d\n", inRecNum);
00268                         exit(1);
00269                     }
00270 
00271                 } else if (hdlc[SQBYTE] == 1) {
00272 
00273                     /*                              */
00274                     /* Last segment, write output record if sequence O.K.   */
00275                     /*                              */
00276                     partnum++;
00277                     if (partnum != 4) {
00278                         fprintf(stderr,"Sequence error at record %d\n", inRecNum);
00279                     } else {
00280                         if (fread ( &buf[10474], 1, 3386, infp) != 3386 ) {
00281                             fprintf(stderr,"Error reading input file at record %d\n", inRecNum);
00282                             exit(1);
00283                         }
00284                         if (fwrite( buf, 1, 13860, outfp) != 13860) {
00285                             printf("Error writing output file at record %d\n", outRecNum);
00286                             exit(1);
00287                          } else 
00288                             outRecNum++;
00289                     }     
00290                     partnum = 0;
00291 
00292                 } else
00293                     fprintf(stderr,"Sequence error at record %d\n", inRecNum);
00294                 
00295             } else if (hdlc[IDBYTE] == BRBID && brbfp != NULL) {
00296 
00297                 if (fwrite ( hdlc, SIZEOFHDLC, 1, brbfp) != 1 ) {
00298                     fprintf(stderr,"Error writing backorbit file at record %d\n", inRecNum);
00299                     exit(1);
00300                 }
00301 
00302                 /*                              */
00303                 /* Back-orbit telemetry. Copy data to buffer and write to the   */
00304                 /* back-orbit file.                                 */
00305                 /*                              */
00306                 if (fread ( buf, 1, 3494, infp) != 3494 ) {
00307                     printf("Error reading input file at record %d\n", inRecNum);
00308                     exit(1);
00309                 }
00310                 if (fwrite ( buf, 1, 3494, brbfp) != 3494 ) {
00311                     fprintf(stderr,"Error writing backorbit file at record %d\n", inRecNum);
00312                     exit(1);
00313                 }
00314 
00315                 brbRecNum++;
00316 
00317             }
00318         } 
00319 
00320         /*                                  */
00321         /* Update input file position to start of next Nebula record        */
00322         /*                                  */
00323         inRecNum++;
00324         inPos += HDR_LONG(hdr->blockSize);
00325         fseek( infp, inPos, SEEK_SET);
00326 
00327     }
00328 
00329     /*                                      */
00330     /* Check for error on input stream                      */
00331     /*                                      */
00332     if ( ferror(infp) ) {
00333         fprintf(stderr,"Error reading input file at record %d\n", inRecNum);
00334         fclose(infp);
00335         exit(1);
00336     } 
00337 
00338     /*                                      */
00339     /* Normal Termination.                          */
00340     /*                                      */
00341     fprintf(stderr,"End of file reached.\n");
00342     fprintf(stderr,"Number of  input records      = %d\n", inRecNum);
00343     fprintf(stderr,"Number of output records      = %d\n", outRecNum);
00344     fprintf(stderr,"Number of back-orbit records  = %d\n", brbRecNum);
00345     //    if (infp  != NULL && infp  != stdin ) fclose(infp );
00346     //    if (outfp != NULL && outfp != stdout) fclose(outfp);
00347     //    if (brbfp != NULL) fclose(brbfp);
00348 
00349     return(0);
00350 
00351 }
00352 
00353 
00354 /* ---------------------------------------------------------------------------- */
00355 /* extract_loggermsgs() - write any SOH messages found in the input buffer to   */
00356 /*            the output file. Returns number of messages written.  */
00357 /*                                      */
00358 /* The input buffer is assummed to contain a stream of SeaStar memory logger    */
00359 /* messages from the GIM or SCM memory modules.  Each message functions as a    */
00360 /* wrapper around another message, and it is some of those innermost messages   */
00361 /* which this function extracts.  Specifically, it looks for SOH subsytem msgs  */
00362 /* and writes them to the output file.                      */
00363 /*                                      */
00364 /* Written By: BA Franz, GSC, June 1996                     */
00365 /*                                      */
00366 /* ---------------------------------------------------------------------------- */
00367 int extract_loggermsgs( FILE *outfp,    /* Output file pointer          */ 
00368             BYTE *buf,  /* Buffer holding stream of GIM/SCM msg */
00369             int  buflen)    /* Buffer length            */
00370 {
00371     int i       = 0;
00372     short int   addr    = 0;    /* Spacecraft message source address        */
00373     short int   len     = 1;    /* GIM/SCM S/C message length           */
00374     short int   newlen  = 0;    /* SOH-subsystem S/C message length     */
00375     int cnt         = 0;    /* Number of SOH messages found         */ 
00376 
00377     /*                                      */
00378     /* Step-through GIM/SCM messages, looking inside for SOH subsystem messages */
00379     /*                                      */
00380     while (i < buflen && len > 0) {
00381         memcpy( &len,  &buf[i], 2);
00382         if (len > 0) {
00383             memcpy( &addr, &buf[i+24], 2);
00384             if ( issoh( addr)) {
00385 
00386                 /*                                                             */
00387                 /* Need to adjust length field in s/c msg header.  The logger  */
00388                 /* includes the trailing four of the GIM/SCM wrapper here, but */
00389                 /* we are extracting the message from that wrapper so that it  */
00390                 /* will look no different than a recorded SOH message.         */
00391                 /*                                                             */
00392                 memcpy(&newlen, &buf[i+10], 2);
00393                 newlen -= 4;
00394                 memcpy(&buf[i+10], &newlen, 2);
00395 
00396                 /*                                                             */
00397                 /* Write S/C message to output file and count it               */
00398                 /*                                                             */
00399                 if (fwrite( &buf[i+10], 1, len-14, outfp) != len-14)
00400                     return( -1);
00401                 else 
00402                     cnt++;
00403             }
00404         }
00405         i += len;
00406     }
00407 
00408     return (cnt);
00409 }
00410 
00411 
00412 
00413 /* ---------------------------------------------------------------------------- */
00414 /* issoh() - returns true if the input address is associated with an SOH subsys */
00415 /* ---------------------------------------------------------------------------- */
00416 int issoh( int addr)
00417 {
00418     switch (addr) {
00419         case 4416:  /* SGA   */
00420         case 4384:  /* SAC   */
00421         case 4368:      /* SAA   */
00422         case 9217:      /* RXS-1 */
00423         case 9218:      /* RXS-2 */
00424         case 9985:      /* TXL   */
00425         case 9729:      /* TXS   */
00426         case 4609:      /* SMU   */
00427         case 8705:      /* EPS   */
00428         case 1281:      /* FDR-1 */
00429         case 1282:      /* FDR-2 */
00430         case 8544:      /* GUA   */
00431         case 8464:      /* GSC   */
00432         case  272:      /* PSA   */
00433         case  320:      /* PFA   */
00434         case 4544:      /* SHM   */
00435         case 8640:  /* GHM   */
00436             return(1);
00437         default:    
00438             return(0); 
00439     }
00440 }
00441 
00442 
00443 
00444