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