NASA Logo
Ocean Color Science Software

ocssw V2022
outernetDecode.c
Go to the documentation of this file.
1 /*
2  * Program to decode Channel Access Data Units following
3  * CCSDS TM Sync and Channel Coding as proposed for use on Outernet.
4  *
5  * Mark McCrum
6  */
7 
8 // Modification history:
9 // Programmer Organization Date Ver Description of change
10 // ---------- ------------ ---- --- ---------------------
11 // Joel Gales FutureTech 10/18/18 0.90 Continue processing after
12 // decode error.
13 // Liang Hong SAIC 05/05/23 1.00 moved excess warning to verbose
14 
15 #include "fec.h"
16 #include <stdio.h>
17 #include <string.h>
18 #include <stdlib.h>
19 #include <unistd.h>
20 
21 #define I 4 /* Interleave depth */
22 #define L_SYMBOL 223 /* RS Symbol size (bytes) */
23 #define L_CODEWORD 255 /* RS Codeword size (bytes) */
24 #define L_PARITY 32 /* Codeword parity bytes */
25 #define L_CODEBLOCK (I * L_CODEWORD)
26 #define FRAME_SIZE (I * L_SYMBOL) /* User data in a frame */
27 #define SYMBOLS_NO_CONV (L_ASM + L_CODEBLOCK)
28 #define MAX_SYMBOLS ( 2 * (L_ASM + L_CODEBLOCK + 1))
29  /* Max symbols in a CADU */
30 #define L_ASM 4 /* Length of sync vector */
31 
32 /* Viterbi decoded config */
33 #define V_FRAMEBITS (8 * SYMBOLS_NO_CONV) /* Bits in frame */
34 
35 #define VERSION "1.00"
36 
40 void formatHex(unsigned char* data, int length) {
41  int col = 0;
42  while(length) {
43  printf("0x%02hhx", *(data++));
44  length--;
45  if (length) {
46  printf(", ");
47  }
48  col += 4;
49  if (col > 80) {
50  col = 0;
51  putchar('\n');
52  }
53  }
54  putchar('\n');
55 }
56 
60 void outputHex(unsigned char* data, int length) {
61  while(length) {
62  printf("%02hhx", *(data++));
63  length--;
64  }
65 }
66 
67 /*
68  * LFSR for CCSDS Pseudo-random number generator
69  *
70  * lfsr Pointer to state of linear feedback shift register. Should initially
71  * be 0xFF
72  *
73  * o Pointer to output byte, existing value will be xor'd with the next
74  * random number output by the generator.
75  */
76 void prng(unsigned char* lfsr, unsigned char* o) {
77  unsigned char rnd = 0U;
78  unsigned char bit = 0U;
79  unsigned int i;
80  for (i = 0; i < 8; i++) {
81  rnd = (rnd << 1) | (*lfsr & 0x1U);
82  bit = (((*lfsr >> 3) ^ *lfsr) ^ (*lfsr >> 5)) ^ (*lfsr >>7);
83  *lfsr = (*lfsr >> 1) | (bit << 7);
84  }
85  *o = *o ^ rnd;
86 }
87 
88 void convDecode(unsigned char* data, unsigned char* coded) {
89  void *vp = create_viterbi27(V_FRAMEBITS);
90  int polys[] = {V27POLYB, -V27POLYA}; /* CCSDS Polynomial config */
91  unsigned char symbols[2 * (V_FRAMEBITS + 6)]; /* Channel symbols inc.
92  tail bits */
93  int i;
94 
95  /* build array of symbols (one element per bit) includes 6 tail bits*/
96  for (i = 0; i < 2 * (V_FRAMEBITS + 6); i++) {
97  symbols[i ] = ((coded[i/8] << (i % 8)) & 0x80) > 0 ? 255 : 0;
98  }
99 
101  init_viterbi27(vp, 0);
102 
103  /* Decode block */
104  update_viterbi27_blk(vp, symbols, V_FRAMEBITS + 6);
105 
106  /* Do Viterbi chainback */
108 
109  delete_viterbi27(vp);
110 }
111 
112 void showHelp(char *progname) {
113  printf("\nTest decoded for Outernet\n");
114  printf("\nDecode Channel Access Data Units encoded via propsed use of");
115  printf("\nCCSDS TM Sync and Channel Coding standard\n\n");
116  printf("Use: %s [options]\n", progname);
117  printf(" c Indicates that CADU has been convolutionally coded\n");
118  printf(" A Viterbi decoder will be used\n");
119  printf("Output:\n");
120  printf(" Decoded frame\n");
121  printf("Notes:\n");
122  printf(" Errors from the Reed-Solomon decode are detected but not\n");
123  printf(" corrected.\n");
124  exit(0);
125 }
126 
127 
128 int main(int argc, char** argv) {
129  unsigned char sync[] = {0x1A, 0xCF, 0xFC, 0x1D}; /* Attached sync marker */
130  unsigned char symbols[MAX_SYMBOLS]; /* CADU symbols */
131  unsigned char convdecoded[SYMBOLS_NO_CONV + 1];
132  /* frame after conv decoding */
133  //unsigned char frame[ FRAME_SIZE ]; /* Transfer frame */
134  unsigned char codeword[L_CODEWORD]; /* Single RS code word*/
135  unsigned char lfsr = 0xFFU; /* Shift register for randomiser */
136  //unsigned char csr = 0x00; /* Shift register for convolutional coder */
137  //unsigned char flush = 0x00; /* Flush byte for convolutional coder */
138  int rsErrCnt; /* RS error count */
139  //int pad = 0; /* RS coding padding */
140  int i, j; /* Loop counters */
141  int d; /* Getopt option */
142  int convolution = 0; /* Do convolutional coding? */
143  int verbose = 0;
144 
145  FILE* in;// = stdin; /* Input file */
146  FILE* out; /* Output file */
147  int caduSymbols;
148  int errPos[L_PARITY]; /* Error positions */
149 
150  printf("outernetDecode %s (%s %s)\n", VERSION, __DATE__, __TIME__);
151 
152  if ( argc == 1) {
153  printf("\nouternetDecode input_downlink_filename output_telemetry_filename\n");
154  return 0;
155  }
156 
157  /* Process command line options */
158  while ((d = getopt(argc, argv, "cv")) != EOF) {
159  switch(d) {
160  case 'c':
161  convolution = 1;
162  break;
163  case 'v':
164  verbose = 1;
165  break;
166  case '?':
167  showHelp(argv[0]);
168  }
169  }
170 
171  printf("MAX_SYMBOLS: %d\n", MAX_SYMBOLS);
172  printf("FRAME_SIZE: %d\n", FRAME_SIZE);
173 
174  /* Number of bytes to read per frame depends on convolutional coding */
175  caduSymbols = convolution ? MAX_SYMBOLS : SYMBOLS_NO_CONV;
176 
177  in = fopen(argv[optind], "r");
178  out = fopen(argv[optind+1], "w");
179 
180  int ierr=0;
181  while (fread(symbols, sizeof(char), caduSymbols, in) == caduSymbols) {
182 
183  lfsr = 0xFFU; /* reset the randomiser shift register */
184  memset(convdecoded, 0, SYMBOLS_NO_CONV);
185  if (convolution) {
186  /* Run a viterbi decoder on the data */
187  convDecode(convdecoded, symbols);
188  } else {
189  memcpy(convdecoded, symbols, SYMBOLS_NO_CONV);
190  }
191  /* Check the attached sync marker */
192  if(memcmp(sync, convdecoded, L_ASM) != 0) {
193  fprintf(stderr, "ASM not found\n");
194  // break;
195  }
196 
197  /* De-randomise the data */
198  for (i = 0; i < ( L_CODEBLOCK); i++) {
199  prng(&lfsr, &convdecoded[L_ASM + i]);
200  }
201 
202  /* Check parity */
203  for (i = 0; i < I; i++) {
204  /* codeword interleaving */
205  for (j = 0; j < L_SYMBOL; j++) {
206  codeword[j] = convdecoded[L_ASM + i + j * I];
207  }
208 
209  /* parity interleaving */
210  for(j = 0; j < L_PARITY; j++) {
211  codeword[j + L_SYMBOL] =
212  convdecoded[L_ASM + FRAME_SIZE + i + j * I];
213  }
214 
215  /* run the RS decoder */
216  rsErrCnt = decode_rs_ccsds(codeword, errPos, 0, 0);
217  if (rsErrCnt == -1) {
218  if (verbose > 0) fprintf(stderr, "Uncorrectable errors in frame\n");
219  ierr = 1;
220  // break;
221  } else if (rsErrCnt > 0 & verbose > 0) {
222  /* TODO: Copy the corrections back into the frame */
223  fprintf(stderr, "%d errors in block\n", rsErrCnt);
224  while(rsErrCnt) {
225  fprintf(stderr, "symbol: %i\n",
226  errPos[--rsErrCnt]);
227  }
228  }
229  }
230  if (ierr == 0) {
231  /* Output the frame */
232  // outputHex(&convdecoded[L_ASM], FRAME_SIZE);
233  //putchar('\n');
234  fwrite(&convdecoded[L_ASM], sizeof(char), FRAME_SIZE, out);
235  } else {
236  ierr = 0;
237  }
238  }
239 
240  fclose(in);
241  fclose(out);
242 
243  return 0;
244 }
245 
int main(int argc, char **argv)
#define L_CODEBLOCK
int init_viterbi27(void *vp, int starting_state)
Definition: fec_seahawk.c:221
int j
Definition: decode_rs.h:73
int chainback_viterbi27(void *vp, unsigned char *data, unsigned int nbits, unsigned int endstate)
Definition: fec_seahawk.c:242
void outputHex(unsigned char *data, int length)
#define L_ASM
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 out
Definition: HISTORY.txt:422
#define V_FRAMEBITS
int update_viterbi27_blk(void *vp, unsigned char sym[], int npairs)
Definition: fec_seahawk.c:297
#define V27POLYA
Definition: fec.h:13
#define MAX_SYMBOLS
void prng(unsigned char *lfsr, unsigned char *o)
void showHelp(char *progname)
#define L_PARITY
#define I
int decode_rs_ccsds(unsigned char *data, int *eras_pos, int no_eras, int pad)
Definition: fec_seahawk.c:53
void formatHex(unsigned char *data, int length)
void set_viterbi27_polynomial(int polys[2])
Definition: fec_seahawk.c:195
void convDecode(unsigned char *data, unsigned char *coded)
no change in intended resolving MODur00064 Corrected handling of bad ephemeris attitude data
Definition: HISTORY.txt:356
#define VERSION
#define SYMBOLS_NO_CONV
#define V27POLYB
Definition: fec.h:14
void * create_viterbi27(int len)
Definition: fec_seahawk.c:173
#define L_CODEWORD
#define L_SYMBOL
int i
Definition: decode_rs.h:71
void delete_viterbi27(void *vp)
Definition: fec_seahawk.c:268
int verbose
Definition: fmt_check.c:6
#define FRAME_SIZE