OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
neb2raw.c
Go to the documentation of this file.
1 /* ============================================================================ */
2 /* */
3 /* neb2raw - converts OSC nebula files to native S/C frames (13860-byte,10-bit) */
4 /* */
5 /* Synopsis: */
6 /* */
7 /* neb2raw [ -f nebula-file ] [ -o raw-file ] [-b backorbit-file ] */
8 /* */
9 /* nebula-file: name of input nebula file to read */
10 /* (default is to read from standard input, see warning) */
11 /* raw-file: name of output file for raw S/C frames */
12 /* (default is to write to standard output) */
13 /* backorbit-file: name of output file for back-orbit SOH messages */
14 /* (default is to discard back-orbit records) */
15 /* */
16 /* Description: */
17 /* */
18 /* A SeaWiFS data file in OSC's Nebula format is provided to the program */
19 /* via standard input or the -f option flag. The file is searched, record */
20 /* by record, to find any of three types of data records: */
21 /* */
22 /* 1) HRPT records, which are stored as single nebula records consisting */
23 /* of: the 40-byte nebula header and 13862-bytes of the S/C frame. An */
24 /* HRPT frame is actually 13862.5 bytes, but the last half-byte gets */
25 /* truncated by the OSC front-end. There is no useful data longward of */
26 /* byte 13735 (the 20-bit pad), so this trunctaion doesn't matter. This */
27 /* program extracts the first 13860 bytes of the HRPT record, and */
28 /* writes it either to standard output, or to a named file provided via */
29 /* the -o option. */
30 /* */
31 /* 2) Stored GAC/LAC records, which are divided over four 3540-byte nebula */
32 /* records. The first record in the sequence contains a 40-byte nebula */
33 /* header, an 8-byte HDLC header, a 2-byte length field, and 3490 bytes */
34 /* of a recorded S/C frame. The next two records contain a 40-byte neb */
35 /* header, an 8-byte HDLC header, and 3492 bytes of the S/C frame. The */
36 /* final record in the sequence has the 40-byte neb header, the 8-byte */
37 /* HDLC header, the remaining 3386 bytes of the S/C frame, and 103 */
38 /* bytes of padding. The program checks for proper sequence order, but */
39 /* it can not distinguish between the middle two records. The raw */
40 /* frames are reconstructed from the nebula record and written to */
41 /* standard output, or to a named file provided with the -o option. */
42 /* Out-of-order sequences, which are most likely associated with a */
43 /* corrupted HDLC header, are discarded. */
44 /* */
45 /* 3) Logger (back-orbit) records, which are stored in 3540-byte nebula */
46 /* records. Each record consists of a 40-byte neb header and an 8-byte */
47 /* HDLC header, followed by a series of variable-length spacecraft */
48 /* messages originating from the GIM or SCM memory subsystem. Each of */
49 /* these messages are just wrappers around another spacecraft message. */
50 /* The program reads the 3540-byte nebula records and writes a 3502 */
51 /* byte record containing the HDLC header and the 3492 bytes that */
52 /* follow it. The last two bytes are a placeholder to account for the */
53 /* CRC bytes that are stored in the SeaSpace version of the back-orbit */
54 /* file, but that are not available from the nebula input file. */
55 /* */
56 /* Generally, nebula files from OSC will contain either type 1 records, or */
57 /* type 2 and 3 records, but any combination can be handled. Nebula */
58 /* records which do not meet one of these three types are probably just */
59 /* status messages from OSC's high-speed front-end. */
60 /* */
61 /* */
62 /* Warnings: */
63 /* */
64 /* Due to the random-seek capability required to step through the nebula */
65 /* records, the program can not read from a pipe. */
66 /* */
67 /* */
68 /* See Also: */
69 /* */
70 /* raw2L0 */
71 /* */
72 /* */
73 /* Written By: */
74 /* */
75 /* Bryan A. Franz */
76 /* General Sciences Corp. */
77 /* 4 June 1996 */
78 /* */
79 /* ============================================================================ */
80 
81 #include <stdint.h>
82 #include <stdio.h>
83 #include <stdlib.h>
84 #include <fcntl.h>
85 #include <string.h>
86 #include <errno.h>
87 #include <unistd.h>
88 #include "loghdr.h"
89 
90 
91 #define CMD_ARGS "f:o:b:" /* Valid commandline options */
92 #define HRPTRECLEN 13902 /* Length of HRPT nebula record */
93 #define STORRECLEN 3540 /* Length of recorded data rec */
94 #define FRAMELEN 13860 /* Bytes in spacecraft mnf */
95 #define SIZEOFBUF (16*10124) /* Data buffer length */
96 #define SIZEOFHDR sizeof(struct LOGHDR) /* Nebula header length */
97 #define SIZEOFHDLC 8 /* HDLC header length */
98 #define GACID 80 /* GAC ID in HDLC header */
99 #define LACID 96 /* LAC ID in HDLC header */
100 #define BRBID 64 /* Back-orbit ID in HDLC header */
101 #define IDBYTE 3 /* ID byte location HDLC header */
102 #define SQBYTE 5 /* Sequence # location HDLC hdr */
103 
104 
105 
106 int issoh(int addr);
107 int extract_loggermsgs(FILE *outfp, BYTE *buf, int buflen);
108 
109 
110 
111 /* ---------------------------------------------------------------------------- */
112 /* main */
113 
114 /* ---------------------------------------------------------------------------- */
115 int main(int argc, char* argv[]) {
116  FILE *infp = stdin; /* Input file pointer */
117  FILE *outfp = stdout; /* Output file pointer */
118  FILE *brbfp = NULL; /* Back-orbit file pntr */
119 
120  struct LOGHDR hdrbuf; /* Nebula header buffer */
121  struct LOGHDR *hdr = &hdrbuf; /* Pointer to neb hdr */
122  unsigned char hdlc[SIZEOFHDLC]; /* HDLC header buffer */
123  unsigned char buf[SIZEOFBUF]; /* Data buffer */
124 
125  int32_t inRecNum = 0L; /* # Input neb records */
126  int32_t outRecNum = 0L; /* # Output mnf records */
127  int32_t brbRecNum = 0L; /* # Output brb records */
128 
129  int32_t inPos = 0L; /* Byte pos in neb file */
130  int swap = 0; /* Byte swapping flag */
131  int first = 1; /* First neb rec flag */
132  int partnum = 0; /* Frame sequence flag */
133 
134  extern int opterr; /* used by getopt() */
135  extern int optind; /* used by getopt() */
136  extern char *optarg; /* used by getopt() */
137  int c; /* used by getopt() */
138 
139  /* */
140  /* Process command-line inputs */
141  /* */
142  while ((c = getopt(argc, argv, CMD_ARGS)) != EOF) {
143  switch (c) {
144  case 'f':
145  if ((infp = fopen(optarg, "r")) == NULL) {
146  fprintf(stderr, "%s: Error opening %s for reading.\n", argv[0], optarg);
147  exit(1);
148  }
149  break;
150  case 'o':
151  if ((outfp = fopen(optarg, "w")) == NULL) {
152  fprintf(stderr, "%s: Error opening %s for writing.\n", argv[0], optarg);
153  exit(1);
154  }
155  break;
156  case 'b':
157  if ((brbfp = fopen(optarg, "w")) == NULL) {
158  fprintf(stderr, "%s: Error opening %s for writing.\n", argv[0], optarg);
159  exit(1);
160  }
161  break;
162  default:
163  fprintf(stderr, "Usage: %s [-f input-nebula-filename]\n", argv[0]);
164  fprintf(stderr, " [-o output-raw-filename]\n");
165  fprintf(stderr, " [-b backorbit-filename]\n");
166  break;
167  }
168  }
169 
170 
171  /* */
172  /* Read through end of input file */
173  /* */
174  while (fread(hdr, SIZEOFHDR, 1, infp) == 1) {
175 
176  /* */
177  /* If this is the first Nebula record processed, determine swapping for */
178  /* Nebula macros. */
179  /* */
180  if (first) {
181  first = 0;
182  switch (hdr->headerVersion) {
183  case 0x0100:
184  swap = 1;
185  break;
186  case 0x0001:
187  swap = 0;
188  break;
189  default:
190  swap = 0;
191  break;
192  }
193  }
194 
195  /* */
196  /* Do some quality checking on the Nebula header */
197  /* */
198  if (HDR_WORD(hdr->headerVersion) != 1) {
199  fprintf(stderr, "Bad nebula header at record %d\n", inRecNum);
200  fclose(infp);
201  exit(5);
202  }
203 
204  /* */
205  /* If this is the record we want, read the data */
206  /* */
207  if (HDR_LONG(hdr->blockSize) == HRPTRECLEN) {
208 
209  /* */
210  /* HRPT Record, just copy data from input to output */
211  /* */
212  if (fread(buf, FRAMELEN, 1, infp) != 1) {
213  fprintf(stderr, "Error reading input file at record %d\n", inRecNum);
214  exit(1);
215  }
216  if (fwrite(buf, FRAMELEN, 1, outfp) != 1) {
217  fprintf(stderr, "Error writing output file at record %d\n", outRecNum);
218  exit(1);
219  } else
220  outRecNum++;
221 
222  } else if (HDR_LONG(hdr->blockSize) == STORRECLEN) {
223 
224  /* */
225  /* Possibly part of a stored GAC or LAC record, or it maybe */
226  /* some back-orbit telemetry messages. Examine the HDLC header. */
227  /* */
228  if (fread(hdlc, SIZEOFHDLC, 1, infp) != 1) {
229  fprintf(stderr, "Error reading input file at record %d\n", inRecNum);
230  exit(1);
231  }
232  if (hdlc[IDBYTE] == GACID || hdlc[IDBYTE] == LACID) {
233 
234  /* */
235  /* Part of stored LAC or GAC, but which part. */
236  /* */
237  if (partnum == 0 && hdlc[SQBYTE] == 2) {
238 
239  /* */
240  /* Beginning of sequence, read into beginning of buffer. */
241  /* */
242  partnum++;
243  fseek(infp, 2, SEEK_CUR); /* Skip msg length field */
244  if (fread(&buf[0], 1, 3490, infp) != 3490) {
245  fprintf(stderr, "Error reading input file at record %d\n", inRecNum);
246  exit(1);
247  }
248 
249  } else if (partnum == 1 && hdlc[SQBYTE] == 0) {
250 
251  /* */
252  /* Middle segment (assumed to be second) */
253  /* */
254  partnum++;
255  if (fread(&buf[3490], 1, 3492, infp) != 3492) {
256  fprintf(stderr, "Error reading input file at record %d\n", inRecNum);
257  exit(1);
258  }
259 
260  } else if (partnum == 2 && hdlc[SQBYTE] == 0) {
261 
262  /* */
263  /* Middle segment (assumed to be third) */
264  /* */
265  partnum++;
266  if (fread(&buf[6982], 1, 3492, infp) != 3492) {
267  fprintf(stderr, "Error reading input file at record %d\n", inRecNum);
268  exit(1);
269  }
270 
271  } else if (hdlc[SQBYTE] == 1) {
272 
273  /* */
274  /* Last segment, write output record if sequence O.K. */
275  /* */
276  partnum++;
277  if (partnum != 4) {
278  fprintf(stderr, "Sequence error at record %d\n", inRecNum);
279  } else {
280  if (fread(&buf[10474], 1, 3386, infp) != 3386) {
281  fprintf(stderr, "Error reading input file at record %d\n", inRecNum);
282  exit(1);
283  }
284  if (fwrite(buf, 1, 13860, outfp) != 13860) {
285  printf("Error writing output file at record %d\n", outRecNum);
286  exit(1);
287  } else
288  outRecNum++;
289  }
290  partnum = 0;
291 
292  } else
293  fprintf(stderr, "Sequence error at record %d\n", inRecNum);
294 
295  } else if (hdlc[IDBYTE] == BRBID && brbfp != NULL) {
296 
297  if (fwrite(hdlc, SIZEOFHDLC, 1, brbfp) != 1) {
298  fprintf(stderr, "Error writing backorbit file at record %d\n", inRecNum);
299  exit(1);
300  }
301 
302  /* */
303  /* Back-orbit telemetry. Copy data to buffer and write to the */
304  /* back-orbit file. */
305  /* */
306  if (fread(buf, 1, 3494, infp) != 3494) {
307  printf("Error reading input file at record %d\n", inRecNum);
308  exit(1);
309  }
310  if (fwrite(buf, 1, 3494, brbfp) != 3494) {
311  fprintf(stderr, "Error writing backorbit file at record %d\n", inRecNum);
312  exit(1);
313  }
314 
315  brbRecNum++;
316 
317  }
318  }
319 
320  /* */
321  /* Update input file position to start of next Nebula record */
322  /* */
323  inRecNum++;
324  inPos += HDR_LONG(hdr->blockSize);
325  fseek(infp, inPos, SEEK_SET);
326 
327  }
328 
329  /* */
330  /* Check for error on input stream */
331  /* */
332  if (ferror(infp)) {
333  fprintf(stderr, "Error reading input file at record %d\n", inRecNum);
334  fclose(infp);
335  exit(1);
336  }
337 
338  /* */
339  /* Normal Termination. */
340  /* */
341  fprintf(stderr, "End of file reached.\n");
342  fprintf(stderr, "Number of input records = %d\n", inRecNum);
343  fprintf(stderr, "Number of output records = %d\n", outRecNum);
344  fprintf(stderr, "Number of back-orbit records = %d\n", brbRecNum);
345  // if (infp != NULL && infp != stdin ) fclose(infp );
346  // if (outfp != NULL && outfp != stdout) fclose(outfp);
347  // if (brbfp != NULL) fclose(brbfp);
348 
349  return (0);
350 
351 }
352 
353 
354 /* ---------------------------------------------------------------------------- */
355 /* extract_loggermsgs() - write any SOH messages found in the input buffer to */
356 /* the output file. Returns number of messages written. */
357 /* */
358 /* The input buffer is assummed to contain a stream of SeaStar memory logger */
359 /* messages from the GIM or SCM memory modules. Each message functions as a */
360 /* wrapper around another message, and it is some of those innermost messages */
361 /* which this function extracts. Specifically, it looks for SOH subsytem msgs */
362 /* and writes them to the output file. */
363 /* */
364 /* Written By: BA Franz, GSC, June 1996 */
365 /* */
366 
367 /* ---------------------------------------------------------------------------- */
368 int extract_loggermsgs(FILE *outfp, /* Output file pointer */
369  BYTE *buf, /* Buffer holding stream of GIM/SCM msg */
370  int buflen) /* Buffer length */ {
371  int i = 0;
372  short int addr = 0; /* Spacecraft message source address */
373  short int len = 1; /* GIM/SCM S/C message length */
374  short int newlen = 0; /* SOH-subsystem S/C message length */
375  int cnt = 0; /* Number of SOH messages found */
376 
377  /* */
378  /* Step-through GIM/SCM messages, looking inside for SOH subsystem messages */
379  /* */
380  while (i < buflen && len > 0) {
381  memcpy(&len, &buf[i], 2);
382  if (len > 0) {
383  memcpy(&addr, &buf[i + 24], 2);
384  if (issoh(addr)) {
385 
386  /* */
387  /* Need to adjust length field in s/c msg header. The logger */
388  /* includes the trailing four of the GIM/SCM wrapper here, but */
389  /* we are extracting the message from that wrapper so that it */
390  /* will look no different than a recorded SOH message. */
391  /* */
392  memcpy(&newlen, &buf[i + 10], 2);
393  newlen -= 4;
394  memcpy(&buf[i + 10], &newlen, 2);
395 
396  /* */
397  /* Write S/C message to output file and count it */
398  /* */
399  if (fwrite(&buf[i + 10], 1, len - 14, outfp) != len - 14)
400  return ( -1);
401  else
402  cnt++;
403  }
404  }
405  i += len;
406  }
407 
408  return (cnt);
409 }
410 
411 
412 
413 /* ---------------------------------------------------------------------------- */
414 /* issoh() - returns true if the input address is associated with an SOH subsys */
415 
416 /* ---------------------------------------------------------------------------- */
417 int issoh(int addr) {
418  switch (addr) {
419  case 4416: /* SGA */
420  case 4384: /* SAC */
421  case 4368: /* SAA */
422  case 9217: /* RXS-1 */
423  case 9218: /* RXS-2 */
424  case 9985: /* TXL */
425  case 9729: /* TXS */
426  case 4609: /* SMU */
427  case 8705: /* EPS */
428  case 1281: /* FDR-1 */
429  case 1282: /* FDR-2 */
430  case 8544: /* GUA */
431  case 8464: /* GSC */
432  case 272: /* PSA */
433  case 320: /* PFA */
434  case 4544: /* SHM */
435  case 8640: /* GHM */
436  return (1);
437  default:
438  return (0);
439  }
440 }
441 
442 
443 
444 
#define IDBYTE
Definition: neb2raw.c:101
#define HDR_WORD(w)
Definition: loghdr.h:39
#define SQBYTE
Definition: neb2raw.c:102
Definition: loghdr.h:5
#define L(lambda, T)
Definition: PreprocessP.h:185
#define FRAMELEN
Definition: neb2raw.c:94
#define GACID
Definition: neb2raw.c:98
#define NULL
Definition: decode_rs.h:63
#define CMD_ARGS
Definition: neb2raw.c:91
int extract_loggermsgs(FILE *outfp, BYTE *buf, int buflen)
Definition: neb2raw.c:368
unsigned char BYTE
Definition: elements.h:4
uint32_t blockSize
Definition: loghdr.h:8
#define BRBID
Definition: neb2raw.c:100
int issoh(int addr)
Definition: neb2raw.c:417
#define HRPTRECLEN
Definition: neb2raw.c:92
#define SIZEOFBUF
Definition: neb2raw.c:95
#define SIZEOFHDLC
Definition: neb2raw.c:97
unsigned short int headerVersion
Definition: loghdr.h:6
#define HDR_LONG(l)
Definition: loghdr.h:40
no change in intended resolving MODur00064 Corrected handling of bad ephemeris attitude resolving resolving GSFcd00179 Corrected handling of fill values for[Sensor|Solar][Zenith|Azimuth] resolving MODxl01751 Changed to validate LUT version against a value retrieved from the resolving MODxl02056 Changed to calculate Solar Diffuser angles without adjustment for estimated post launch changes in the MODIS orientation relative to incidentally resolving defects MODxl01766 Also resolves MODxl01947 Changed to ignore fill values in SCI_ABNORM and SCI_STATE rather than treating them as resolving MODxl01780 Changed to use spacecraft ancillary data to recognise when the mirror encoder data is being set by side A or side B and to change calculations accordingly This removes the need for seperate LUTs for Side A and Side B data it makes the new LUTs incompatible with older versions of the and vice versa Also resolves MODxl01685 A more robust GRing algorithm is being which will create a non default GRing anytime there s even a single geolocated pixel in a granule Removed obsolete messages from seed as required for compatibility with version of the SDP toolkit Corrected test output file names to end in per delivery and then split off a new MYD_PR03 pcf file for Aqua Added AssociatedPlatformInstrumentSensor to the inventory metadata in MOD01 mcf and MOD03 mcf Created new versions named MYD01 mcf and MYD03 where AssociatedPlatformShortName is rather than Terra The program itself has been changed to read the Satellite Instrument validate it against the input L1A and LUT and to use it determine the correct files to retrieve the ephemeris and attitude data from Changed to produce a LocalGranuleID starting with MYD03 if run on Aqua data Added the Scan Type file attribute to the Geolocation copied from the L1A and attitude_angels to radians rather than degrees The accumulation of Cumulated gflags was moved from GEO_validate_earth_location c to GEO_locate_one_scan c
Definition: HISTORY.txt:464
int main(int argc, char *argv[])
Definition: neb2raw.c:115
int i
Definition: decode_rs.h:71
#define LACID
Definition: neb2raw.c:99
#define STORRECLEN
Definition: neb2raw.c:93
#define SIZEOFHDR
Definition: neb2raw.c:96