|
ocssw
1.0
|
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
1.7.6.1