From 65264e41e74e7c656260dc758198555a4f9a8105 Mon Sep 17 00:00:00 2001 From: Troels Jessen Date: Mon, 13 Apr 2026 19:04:09 +0200 Subject: [PATCH 1/2] Compile-time optional RS encoding --- include/cblk/csp_if_cblk.h | 5 ++ meson.build | 8 +++ meson_options.txt | 1 + src/ccsds_randomize.c | 58 ++++++++++++++++ src/ccsds_randomize.h | 27 ++++++++ src/csp_if_cblk.c | 14 ++++ src/rs.h | 133 +++++++++++++++++++++++++++++++++++++ src/rs_encode.c | 73 ++++++++++++++++++++ 8 files changed, 319 insertions(+) create mode 100644 src/ccsds_randomize.c create mode 100644 src/ccsds_randomize.h create mode 100644 src/rs.h create mode 100644 src/rs_encode.c diff --git a/include/cblk/csp_if_cblk.h b/include/cblk/csp_if_cblk.h index 5030bad..be49ad0 100644 --- a/include/cblk/csp_if_cblk.h +++ b/include/cblk/csp_if_cblk.h @@ -30,6 +30,11 @@ typedef struct __attribute__((packed)) uint8_t data[]; //! Space Inventor specific data } cblk_frame_t; +#ifdef RS_ENCODE +#define ASM_LEN 4 +#define RS_CHECKSUM_LEN 32 +#endif + #define CCSDS_FRAME_LEN 223 #define CBLK_DATA_LEN (CCSDS_FRAME_LEN-sizeof(cblk_hdr_t)) #define CRYPTO_PREAMP 16 /* crypto_secretbox_BOXZEROBYTES */ diff --git a/meson.build b/meson.build index 4994682..3fb085b 100644 --- a/meson.build +++ b/meson.build @@ -19,6 +19,14 @@ cblk_src = files([ 'src/crypto/crypto_param.c', ]) +if get_option('rs_encode') + cblk_args += '-DRS_ENCODE' + cblk_src += files([ + 'src/ccsds_randomize.c', + 'src/rs_encode.c', + ]) +endif + nacl_impl = get_option('nacl_impl') if nacl_impl == 'tweetnacl' diff --git a/meson_options.txt b/meson_options.txt index bbcaa81..a66e571 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -4,3 +4,4 @@ option('nacl_impl', value: 'tweetnacl', description: 'Which NaCl implementation to use' ) +option('rs_encode', type: 'boolean', value: false, description: 'Do Reed-Solomon encoding as part TX') diff --git a/src/ccsds_randomize.c b/src/ccsds_randomize.c new file mode 100644 index 0000000..040c4f1 --- /dev/null +++ b/src/ccsds_randomize.c @@ -0,0 +1,58 @@ +/* + * ccsds_randomize.c + * + * Created on: 25 aug 2022 + * Author: Per Henrik Michaelsen + */ + +#include +#include +#include + +static bool _initialized = 0; +static uint8_t _mask[255] = { 0 }; + +bool _check() +{ + // First 40 bit provided in CCSDS 131.0-B-4. + // 1111 1111 0100 1000 0000 1110 1100 0000 1001 1010 + uint8_t check[] = { 0xff, 0x48, 0x0e, 0xc0, 0x9a }; + bool equal = true; + for (size_t i = 0; i < sizeof(check); ++i) { + equal &= (_mask[i] == check[i]); + } + return equal; +} + +static void _init() +{ + uint8_t lfsr = 0xff; + uint8_t next = 0; + uint8_t val = 0; + size_t i = 0; + size_t j = 0; + for (i = 0; i < 255; ++i) { + val = 0; + for (j = 0; j < 8; ++j) { + val = (val << 1) | (lfsr & 1); + next = lfsr ^ (lfsr >> 3) ^ (lfsr >> 5) ^ (lfsr >> 7); + lfsr = (lfsr >> 1) | ((next & 1) << 7); + } + _mask[i] = val; + } + + if (!_check()) { + printf("ERROR: CCSDS randomization first 40 bits are wrong."); + } +} + +void ccsds_randomize(uint8_t * block) +{ + if (!_initialized) { + _init(); + _initialized = 1; + } + for (size_t i = 0; i < 255; ++i) { + block[i] ^= _mask[i]; + } +} diff --git a/src/ccsds_randomize.h b/src/ccsds_randomize.h new file mode 100644 index 0000000..1dbd47b --- /dev/null +++ b/src/ccsds_randomize.h @@ -0,0 +1,27 @@ +/* + * ccsds_randomize.h + * + * Created on: 25 nov 2022 + * Author: Per Henrik Michaelsen + */ +#ifndef CCSDA_RANDOMIZE_H_ +#define CCSDS_RANDOMIZE_H_ + +#include +#include +#include + +/** + * Randomization is a mask xor'ed on a Reed-Solomon (255,223) block, + * which is the data that comes after the ASM in a CADU frame. + */ + +/** + * @brief CCSDS randomize + * Aplly the CCSDS randomization mask on a single Reed-Solomon block. + * + * @param block The block + */ +void ccsds_randomize(uint8_t * block); + +#endif // CCSDS_RANDOMIZE_H_ diff --git a/src/csp_if_cblk.c b/src/csp_if_cblk.c index 01dd5d7..c3b81f7 100644 --- a/src/csp_if_cblk.c +++ b/src/csp_if_cblk.c @@ -9,6 +9,11 @@ #include "crypto/crypto.h" #include +#ifdef RS_ENCODE +#include "rs.h" +#include "ccsds_randomize.h" +#endif + uint8_t _cblk_rx_debug = 0; uint8_t _cblk_tx_debug = 0; @@ -101,6 +106,15 @@ int csp_if_cblk_tx(csp_iface_t * iface, uint16_t via, csp_packet_t *packet, int memcpy(tx_ccsds_buf->data, frame_begin+(frame_length-bytes_remain), segment_len); bytes_remain -= segment_len; +#ifdef RS_ENCODE + /* In case RS encoding is enabled, the driver is expected to allocate additional space around the CCSDS frame */ + uint32_t *frame_asm = &(*(((uint32_t*)tx_ccsds_buf)-1)); + *frame_asm = htobe32(0x1ACFFC1D); + + encode_rs_ccsds((uint8_t *)tx_ccsds_buf, ((uint8_t *)tx_ccsds_buf)+CCSDS_FRAME_LEN, 0); + ccsds_randomize((uint8_t *)tx_ccsds_buf); +#endif + if (ifdata->cblk_tx_send(iface, tx_ccsds_buf) < 0) { ifdata->cblk_tx_unlock(iface); csp_buffer_free(packet); diff --git a/src/rs.h b/src/rs.h new file mode 100644 index 0000000..806d25f --- /dev/null +++ b/src/rs.h @@ -0,0 +1,133 @@ +/* + * rs.h + * + * @author Phil-Karn + * Copyright Feb 2004, Phil Karn, KA9Q + * May be used under the terms of the GNU Lesser General Public License (LGPL) + * + * Created on: Jul 5, 2018 + * Author: johan + */ + +#ifndef SRC_CODING_RS_H_ +#define SRC_CODING_RS_H_ + +typedef unsigned char data_t; + +#define RS_BLOCK_LENGTH 255 +#define RS_CHECK_LENGTH 32 + +static inline int mod255(int x){ + while (x >= 255) { + x -= 255; + x = (x >> 8) + (x & 255); + } + return x; +} +#define MODNN(x) mod255(x) + +static const data_t CCSDS_alpha_to[] = { +0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0x87,0x89,0x95,0xad,0xdd,0x3d,0x7a,0xf4, +0x6f,0xde,0x3b,0x76,0xec,0x5f,0xbe,0xfb,0x71,0xe2,0x43,0x86,0x8b,0x91,0xa5,0xcd, +0x1d,0x3a,0x74,0xe8,0x57,0xae,0xdb,0x31,0x62,0xc4,0x0f,0x1e,0x3c,0x78,0xf0,0x67, +0xce,0x1b,0x36,0x6c,0xd8,0x37,0x6e,0xdc,0x3f,0x7e,0xfc,0x7f,0xfe,0x7b,0xf6,0x6b, +0xd6,0x2b,0x56,0xac,0xdf,0x39,0x72,0xe4,0x4f,0x9e,0xbb,0xf1,0x65,0xca,0x13,0x26, +0x4c,0x98,0xb7,0xe9,0x55,0xaa,0xd3,0x21,0x42,0x84,0x8f,0x99,0xb5,0xed,0x5d,0xba, +0xf3,0x61,0xc2,0x03,0x06,0x0c,0x18,0x30,0x60,0xc0,0x07,0x0e,0x1c,0x38,0x70,0xe0, +0x47,0x8e,0x9b,0xb1,0xe5,0x4d,0x9a,0xb3,0xe1,0x45,0x8a,0x93,0xa1,0xc5,0x0d,0x1a, +0x34,0x68,0xd0,0x27,0x4e,0x9c,0xbf,0xf9,0x75,0xea,0x53,0xa6,0xcb,0x11,0x22,0x44, +0x88,0x97,0xa9,0xd5,0x2d,0x5a,0xb4,0xef,0x59,0xb2,0xe3,0x41,0x82,0x83,0x81,0x85, +0x8d,0x9d,0xbd,0xfd,0x7d,0xfa,0x73,0xe6,0x4b,0x96,0xab,0xd1,0x25,0x4a,0x94,0xaf, +0xd9,0x35,0x6a,0xd4,0x2f,0x5e,0xbc,0xff,0x79,0xf2,0x63,0xc6,0x0b,0x16,0x2c,0x58, +0xb0,0xe7,0x49,0x92,0xa3,0xc1,0x05,0x0a,0x14,0x28,0x50,0xa0,0xc7,0x09,0x12,0x24, +0x48,0x90,0xa7,0xc9,0x15,0x2a,0x54,0xa8,0xd7,0x29,0x52,0xa4,0xcf,0x19,0x32,0x64, +0xc8,0x17,0x2e,0x5c,0xb8,0xf7,0x69,0xd2,0x23,0x46,0x8c,0x9f,0xb9,0xf5,0x6d,0xda, +0x33,0x66,0xcc,0x1f,0x3e,0x7c,0xf8,0x77,0xee,0x5b,0xb6,0xeb,0x51,0xa2,0xc3,0x00, +}; + +static const data_t CCSDS_index_of[] = { +255, 0, 1, 99, 2,198,100,106, 3,205,199,188,101,126,107, 42, + 4,141,206, 78,200,212,189,225,102,221,127, 49,108, 32, 43,243, + 5, 87,142,232,207,172, 79,131,201,217,213, 65,190,148,226,180, +103, 39,222,240,128,177, 50, 53,109, 69, 33, 18, 44, 13,244, 56, + 6,155, 88, 26,143,121,233,112,208,194,173,168, 80,117,132, 72, +202,252,218,138,214, 84, 66, 36,191,152,149,249,227, 94,181, 21, +104, 97, 40,186,223, 76,241, 47,129,230,178, 63, 51,238, 54, 16, +110, 24, 70,166, 34,136, 19,247, 45,184, 14, 61,245,164, 57, 59, + 7,158,156,157, 89,159, 27, 8,144, 9,122, 28,234,160,113, 90, +209, 29,195,123,174, 10,169,145, 81, 91,118,114,133,161, 73,235, +203,124,253,196,219, 30,139,210,215,146, 85,170, 67, 11, 37,175, +192,115,153,119,150, 92,250, 82,228,236, 95, 74,182,162, 22,134, +105,197, 98,254, 41,125,187,204,224,211, 77,140,242, 31, 48,220, +130,171,231, 86,179,147, 64,216, 52,176,239, 38, 55, 12, 17, 68, +111,120, 25,154, 71,116,167,193, 35, 83,137,251, 20, 93,248,151, + 46, 75,185, 96, 15,237, 62,229,246,135,165, 23, 58,163, 60,183, +}; + +static const data_t CCSDS_poly[] = { + 0,249, 59, 66, 4, 43,126,251, 97, 30, 3,213, 50, 66,170, 5, + 24, 5,170, 66, 50,213, 3, 30, 97,251,126, 43, 4, 66, 59,249, + 0, +}; + +static const data_t TalToDualBasis[] = { + 0x00,0x7b,0xaf,0xd4,0x99,0xe2,0x36,0x4d,0xfa,0x81,0x55,0x2e,0x63,0x18,0xcc,0xb7, + 0x86,0xfd,0x29,0x52,0x1f,0x64,0xb0,0xcb,0x7c,0x07,0xd3,0xa8,0xe5,0x9e,0x4a,0x31, + 0xec,0x97,0x43,0x38,0x75,0x0e,0xda,0xa1,0x16,0x6d,0xb9,0xc2,0x8f,0xf4,0x20,0x5b, + 0x6a,0x11,0xc5,0xbe,0xf3,0x88,0x5c,0x27,0x90,0xeb,0x3f,0x44,0x09,0x72,0xa6,0xdd, + 0xef,0x94,0x40,0x3b,0x76,0x0d,0xd9,0xa2,0x15,0x6e,0xba,0xc1,0x8c,0xf7,0x23,0x58, + 0x69,0x12,0xc6,0xbd,0xf0,0x8b,0x5f,0x24,0x93,0xe8,0x3c,0x47,0x0a,0x71,0xa5,0xde, + 0x03,0x78,0xac,0xd7,0x9a,0xe1,0x35,0x4e,0xf9,0x82,0x56,0x2d,0x60,0x1b,0xcf,0xb4, + 0x85,0xfe,0x2a,0x51,0x1c,0x67,0xb3,0xc8,0x7f,0x04,0xd0,0xab,0xe6,0x9d,0x49,0x32, + 0x8d,0xf6,0x22,0x59,0x14,0x6f,0xbb,0xc0,0x77,0x0c,0xd8,0xa3,0xee,0x95,0x41,0x3a, + 0x0b,0x70,0xa4,0xdf,0x92,0xe9,0x3d,0x46,0xf1,0x8a,0x5e,0x25,0x68,0x13,0xc7,0xbc, + 0x61,0x1a,0xce,0xb5,0xf8,0x83,0x57,0x2c,0x9b,0xe0,0x34,0x4f,0x02,0x79,0xad,0xd6, + 0xe7,0x9c,0x48,0x33,0x7e,0x05,0xd1,0xaa,0x1d,0x66,0xb2,0xc9,0x84,0xff,0x2b,0x50, + 0x62,0x19,0xcd,0xb6,0xfb,0x80,0x54,0x2f,0x98,0xe3,0x37,0x4c,0x01,0x7a,0xae,0xd5, + 0xe4,0x9f,0x4b,0x30,0x7d,0x06,0xd2,0xa9,0x1e,0x65,0xb1,0xca,0x87,0xfc,0x28,0x53, + 0x8e,0xf5,0x21,0x5a,0x17,0x6c,0xb8,0xc3,0x74,0x0f,0xdb,0xa0,0xed,0x96,0x42,0x39, + 0x08,0x73,0xa7,0xdc,0x91,0xea,0x3e,0x45,0xf2,0x89,0x5d,0x26,0x6b,0x10,0xc4,0xbf + }; + +static const data_t TalToConventional[] = { + 0x00,0xcc,0xac,0x60,0x79,0xb5,0xd5,0x19,0xf0,0x3c,0x5c,0x90,0x89,0x45,0x25,0xe9, + 0xfd,0x31,0x51,0x9d,0x84,0x48,0x28,0xe4,0x0d,0xc1,0xa1,0x6d,0x74,0xb8,0xd8,0x14, + 0x2e,0xe2,0x82,0x4e,0x57,0x9b,0xfb,0x37,0xde,0x12,0x72,0xbe,0xa7,0x6b,0x0b,0xc7, + 0xd3,0x1f,0x7f,0xb3,0xaa,0x66,0x06,0xca,0x23,0xef,0x8f,0x43,0x5a,0x96,0xf6,0x3a, + 0x42,0x8e,0xee,0x22,0x3b,0xf7,0x97,0x5b,0xb2,0x7e,0x1e,0xd2,0xcb,0x07,0x67,0xab, + 0xbf,0x73,0x13,0xdf,0xc6,0x0a,0x6a,0xa6,0x4f,0x83,0xe3,0x2f,0x36,0xfa,0x9a,0x56, + 0x6c,0xa0,0xc0,0x0c,0x15,0xd9,0xb9,0x75,0x9c,0x50,0x30,0xfc,0xe5,0x29,0x49,0x85, + 0x91,0x5d,0x3d,0xf1,0xe8,0x24,0x44,0x88,0x61,0xad,0xcd,0x01,0x18,0xd4,0xb4,0x78, + 0xc5,0x09,0x69,0xa5,0xbc,0x70,0x10,0xdc,0x35,0xf9,0x99,0x55,0x4c,0x80,0xe0,0x2c, + 0x38,0xf4,0x94,0x58,0x41,0x8d,0xed,0x21,0xc8,0x04,0x64,0xa8,0xb1,0x7d,0x1d,0xd1, + 0xeb,0x27,0x47,0x8b,0x92,0x5e,0x3e,0xf2,0x1b,0xd7,0xb7,0x7b,0x62,0xae,0xce,0x02, + 0x16,0xda,0xba,0x76,0x6f,0xa3,0xc3,0x0f,0xe6,0x2a,0x4a,0x86,0x9f,0x53,0x33,0xff, + 0x87,0x4b,0x2b,0xe7,0xfe,0x32,0x52,0x9e,0x77,0xbb,0xdb,0x17,0x0e,0xc2,0xa2,0x6e, + 0x7a,0xb6,0xd6,0x1a,0x03,0xcf,0xaf,0x63,0x8a,0x46,0x26,0xea,0xf3,0x3f,0x5f,0x93, + 0xa9,0x65,0x05,0xc9,0xd0,0x1c,0x7c,0xb0,0x59,0x95,0xf5,0x39,0x20,0xec,0x8c,0x40, + 0x54,0x98,0xf8,0x34,0x2d,0xe1,0x81,0x4d,0xa4,0x68,0x08,0xc4,0xdd,0x11,0x71,0xbd + }; + +#define MM 8 +#define NN 255 +#define ALPHA_TO CCSDS_alpha_to +#define INDEX_OF CCSDS_index_of +#define GENPOLY CCSDS_poly +#define NROOTS 32 +#define FCR 112 +#define PRIM 11 +#define IPRIM 116 +#define PAD pad + +#undef MIN +#define MIN(a,b) ((a) < (b) ? (a) : (b)) +#undef A0 +#define A0 (NN) + +/* CCSDS standard (255,223) RS codec with conventional (*not* dual-basis) + * symbol representation + */ +void encode_rs_ccsds(unsigned char *data,unsigned char *parity,int pad); +int decode_rs_ccsds(data_t *data,int *eras_pos,int no_eras,int pad); + +#endif /* SRC_CODING_RS_H_ */ diff --git a/src/rs_encode.c b/src/rs_encode.c new file mode 100644 index 0000000..24729e1 --- /dev/null +++ b/src/rs_encode.c @@ -0,0 +1,73 @@ +/* + * rs-encode.c + * + * @author Phil-Karn + * Copyright Feb 2004, Phil Karn, KA9Q + * May be used under the terms of the GNU Lesser General Public License (LGPL) + * + * Created on: Jul 5, 2018 + * Author: johan + */ + +#include +#include "rs.h" + +/* Portable C version */ +void encode_rs_ccsds(data_t *data, data_t *parity,int pad) { + +/* The guts of the Reed-Solomon encoder, meant to be #included + * into a function body with the following typedefs, macros and variables supplied + * according to the code parameters: + + * data_t - a typedef for the data symbol + * data_t data[] - array of NN-NROOTS-PAD and type data_t to be encoded + * data_t parity[] - an array of NROOTS and type data_t to be written with parity symbols + * NROOTS - the number of roots in the RS code generator polynomial, + * which is the same as the number of parity symbols in a block. + * Integer variable or literal. + + * NN - the total number of symbols in a RS block. Integer variable or literal. + * PAD - the number of pad symbols in a block. Integer variable or literal. + * ALPHA_TO - The address of an array of NN elements to convert Galois field + * elements in index (log) form to polynomial form. Read only. + * INDEX_OF - The address of an array of NN elements to convert Galois field + * elements in polynomial form to index (log) form. Read only. + * MODNN - a function to reduce its argument modulo NN. May be inline or a macro. + * GENPOLY - an array of NROOTS+1 elements containing the generator polynomial in index form + + * The memset() and memmove() functions are used. The appropriate header + * file declaring these functions (usually ) must be included by the calling + * program. + + * Copyright 2004, Phil Karn, KA9Q + * May be used under the terms of the GNU Lesser General Public License (LGPL) + */ + + int i, j; + data_t feedback; + + memset(parity,0,NROOTS*sizeof(data_t)); + + for(i=0;i Date: Mon, 13 Apr 2026 19:29:57 +0200 Subject: [PATCH 2/2] Create config header file to define if RS encode is enabled --- include/cblk/csp_if_cblk.h | 2 ++ meson.build | 14 ++++++++------ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/include/cblk/csp_if_cblk.h b/include/cblk/csp_if_cblk.h index be49ad0..55974c6 100644 --- a/include/cblk/csp_if_cblk.h +++ b/include/cblk/csp_if_cblk.h @@ -5,6 +5,8 @@ #include #include +#include + typedef enum { CBLK_EXTHDR_NOSUPPORT = 0b00, CBLK_EXTHDR_SUPPORT = 0b01, CBLK_EXTHDR_PRESENT = 0b10} ext_hdr_e; typedef struct __attribute__((packed)) diff --git a/meson.build b/meson.build index 3fb085b..68d6f40 100644 --- a/meson.build +++ b/meson.build @@ -2,6 +2,7 @@ project('cblk', ['c', 'cpp']) cblk_deps = [] cblk_args = [] +conf = configuration_data() if not meson.is_subproject() csp_dep = dependency('csp', fallback : ['csp', 'csp_dep'], required: true).partial_dependency(links: true, includes: true) @@ -20,7 +21,7 @@ cblk_src = files([ ]) if get_option('rs_encode') - cblk_args += '-DRS_ENCODE' + conf.set('RS_ENCODE', 1) cblk_src += files([ 'src/ccsds_randomize.c', 'src/rs_encode.c', @@ -43,19 +44,20 @@ elif nacl_impl == 'sodium' cblk_args += '-DUSE_SODIUM' endif -cblk_inc = include_directories('src') -api = include_directories('include') +cblk_inc = include_directories('.', 'include') + +libcblk_h = configure_file(output: 'libcblk.h', configuration: conf) cblk_lib = static_library('cblk', - sources: [cblk_src], - include_directories : [cblk_inc, api], + sources: [cblk_src, libcblk_h], + include_directories : [cblk_inc], dependencies : cblk_deps, c_args : cblk_args, install : false ) cblk_dep = declare_dependency( - include_directories : api, + include_directories : cblk_inc, link_with : cblk_lib, dependencies: cblk_deps, )