From 07209b5f224fc8864c7efeea276784571a822f9a Mon Sep 17 00:00:00 2001 From: "David E. Tiller" <3858971+dtiller@users.noreply.github.com> Date: Mon, 4 Apr 2022 13:52:07 -0400 Subject: [PATCH] First fully-working BCH code. --- src/CMakeLists.txt | 2 + src/bch.c | 147 +++------------------------------------------ src/bch.h | 9 +-- src/eotd.c | 8 ++- src/hdlc_rec.c | 92 ++++++++++++++++++++++++++-- 5 files changed, 109 insertions(+), 149 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7afa21e..581a5e2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -86,6 +86,7 @@ list(APPEND direwolf_SOURCES dwgpsd.c mheard.c eotd.c + bch.c ) if(LINUX) @@ -319,6 +320,7 @@ list(APPEND atest_SOURCES tt_text.c textcolor.c eotd.c + bch.c ) if(WIN32 OR CYGWIN) diff --git a/src/bch.c b/src/bch.c index 7237148..92ea0b4 100644 --- a/src/bch.c +++ b/src/bch.c @@ -518,7 +518,7 @@ int apply_bch(const bch_t *bch, int *recd) } /* LEFT justified in hex */ -void bytes_to_bits(const int *bytes, int *bit_dest, int num_bits) { +void bytes_to_bits(const uint8_t *bytes, int *bit_dest, int num_bits) { for (int i = 0; i < num_bits; i++) { int index = i / 8; int bit_pos = 7 - (i % 8); @@ -527,7 +527,7 @@ void bytes_to_bits(const int *bytes, int *bit_dest, int num_bits) { } } -void bits_to_bytes(const int *bits, int *byte_dest, int num_bits) { +void bits_to_bytes(const int *bits, uint8_t *byte_dest, int num_bits) { int index; @@ -540,8 +540,6 @@ void bits_to_bytes(const int *bits, int *byte_dest, int num_bits) { byte_dest[index] <<= 1; byte_dest[index] |= (bits[i] & 0x01); } - - byte_dest[index] <<= 8 - (num_bits % 8); } void swap_format(const int *bits, int *dest, int cutoff, int num_bits) { @@ -555,8 +553,8 @@ void swap_format(const int *bits, int *dest, int cutoff, int num_bits) { } } -int rotate_byte(int x) { - int y = 0; +uint8_t rotate_byte(uint8_t x) { + uint8_t y = 0; for (int i = 0; i < 8; i++) { y <<= 1; @@ -583,143 +581,16 @@ void dump_bch(const bch_t *bch) { printf("m: %d length: %d t: %d n: %d k: %d\n", bch->m, bch->length, bch->t, bch->n, bch->k); } -void print_array(const char *msg, const char *format, const int *bytes, int num_bytes) { +void print_bytes(const char *msg, const uint8_t *bytes, int num_bytes) { printf("%s", msg); for (int i = 0; i < num_bytes; i++) { - printf(format, bytes[i]); + printf("%02x ", bytes[i]); } } -void print_bytes(const char *msg, const int *bytes, int num_bytes) { - print_array(msg, "%02x ", bytes, num_bytes); -} - void print_bits(const char *msg, const int *bits, int num_bits) { - print_array(msg, "%d ", bits, num_bits); -} - -#undef MAIN -#undef TEST_BYTES_TO_BITS -#define TEST_SWAP -#ifdef MAIN -int main() -{ - int test[][8] = { -/* 0 errors */ { 0xb2, 0x17, 0xa2, 0xb9, 0x53, 0xdd, 0xc5, 0x52 }, /* perfect random test */ - { 0xf0, 0x5a, 0x6a, 0x6a, 0x01, 0x63, 0x33, 0xd0 }, /* g001-cut-lenthened_457.938M.wav */ - { 0xf0, 0x81, 0x52, 0x6b, 0x71, 0xa5, 0x63, 0x08 }, /* 1st in eotd_received_data */ -/* 3 errors */ { 0xf0, 0x85, 0x50, 0x6a, 0x01, 0xe5, 0x6e, 0x84 }, /* 2nd in eotd_received_data - 3 bad bits */ -/* 0 errors */ { 0xf0, 0x85, 0x50, 0x6a, 0x01, 0xe5, 0x06, 0x84 }, /* 2nd, but with the bits fixed */ -/* 3 errors */ { 0xf0, 0x85, 0x59, 0x5a, 0x01, 0xe5, 0x6e, 0x84 }, /* 3rd - 3 bad bits */ -/* 0 errors */ { 0xb0, 0x85, 0x59, 0x5a, 0x11, 0xe5, 0x6f, 0x84 }, /* 3rd fixed */ - { 0xf1, 0x34, 0x50, 0x1a, 0x01, 0xe5, 0x66, 0xfe }, /* 4th */ - { 0xf0, 0xeb, 0x10, 0xea, 0x01, 0x6e, 0x54, 0x1c }, /* 5th */ - { 0xf0, 0xea, 0x5c, 0xea, 0x01, 0x6e, 0x55, 0x0e }, /* 6th */ - { 0xe0, 0x21, 0x10, 0x1a, 0x01, 0x32, 0xbc, 0xe4 }, /* Sun Mar 20 05:41:00 2022 */ - { 0xf0, 0x42, 0x50, 0x5b, 0xcf, 0xd5, 0x64, 0xe4 }, /* Sun Mar 20 12:58:43 2022 */ - { 0xf0, 0x8c, 0x10, 0xaa, 0x01, 0x73, 0x7b, 0x1a }, /* Sun Mar 20 13:35:48 2022 */ - { 0xf0, 0x8c, 0x10, 0xb1, 0xc0, 0xe0, 0x90, 0x64 }, /* Sun Mar 20 13:37:05 2022 */ -/* 3 errors */ { 0xf0, 0x8c, 0x10, 0x6a, 0x01, 0x64, 0x7a, 0xe8 }, /* Sun Mar 20 13:37:48 2022 - 3 bad bits */ -/* 0 errors */ { 0x50, 0x8c, 0x12, 0x6a, 0x01, 0x64, 0x7a, 0xe8 }, /* Sun Mar 20 13:37:48 2022 with bits fixed */ - }; - - int bits[63]; - int temp[8]; - bch_t bch; - - init_bch(&bch, 6, 63, 3); - - for (int count = 0; count < sizeof(test) / sizeof(*test); count++) { - bytes_to_bits(test[count], bits, 63); - - printf("--------------------------\nORIG pkt [%d] ", count); - for (int i = 0; i < 8; i++) { - printf("%02x ", test[count][i]); - } - printf("\n"); - -#ifdef TEST_BYTES_TO_BITS - - printf("ORIG pkt[%d] bits\n", count); - for (int i = 0; i < 63; i++) { - printf("%d ", bits[i]); - } - printf("\n"); - - bits_to_bytes(bits, temp, 63); - printf("bits_to_bytes pkt [%d]\n", count); - for (int i = 0; i < 8; i++) { - printf("%02x ", temp[i]); - } - printf("\n"); - -#endif - -#ifdef TEST_GENERATE - int bch_code[18]; - generate_bch(&bch, bits, bch_code); - printf("generated BCH\n"); - for (int i = 0; i < 18; i++) { - printf("%d ", bch_code[i]); - } - printf("\n"); -#endif - -#ifdef TEST_SWAP - printf("orig: "); - for (int i = 0; i < 63; i++) { - printf("%d ", bits[i]); - } - printf("\n"); - - swap_format(bits, 45, 63); - - printf("rev: "); - for (int i = 0; i < 63; i++) { - printf("%d ", bits[i]); - } - printf("\n"); -#endif -#ifdef TEST_APPLY - int recv[63]; - - for (int i = 0; i < 63; i++) { - recv[i] = bits[i]; - } -/* - printf("rearranged packet [%d]: ", count); - for (int i = 0; i < 63; i++) { - printf("%d ", recv[i]); - } - printf("\n"); - - bits_to_bytes(recv, temp, 63); - - printf("original [%d] bytes: ", count); - for (int i = 0; i < 8; i++) { - printf("%02x ", temp[i]); - } - printf("\n"); -*/ - int corrected = apply_bch(&bch, recv); - - if (corrected >= 0) { -/* - printf("corrected [%d] packet: ", corrected); - for (int i = 0; i < 63; i++) { - printf("%d ", recv[i]); - } - printf("\n"); -*/ - bits_to_bytes(recv, temp, 63); - - printf("corrected [%d] bytes: ", corrected); - for (int i = 0; i < 8; i++) { - printf("%02x ", temp[i]); - } - printf("\n"); - } -#endif + printf("%s", msg); + for (int i = 0; i < num_bits; i++) { + printf("%d ", bits[i]); } } -#endif diff --git a/src/bch.h b/src/bch.h index 34f0ec6..2b22af7 100644 --- a/src/bch.h +++ b/src/bch.h @@ -1,5 +1,6 @@ #ifndef __BCH_H #define __BCH_H +#include struct bch { int m; // 2^m - 1 is max length, n @@ -21,17 +22,17 @@ void generate_bch(bch_t *bch, const int *data, int *bb); int apply_bch(const bch_t *bch, int *recd); -void bytes_to_bits(const int *bytes, int *bit_dest, int num_bits); +void bytes_to_bits(const uint8_t *bytes, int *bit_dest, int num_bits); -void bits_to_bytes(const int *bits, int *byte_dest, int num_bits); +void bits_to_bytes(const int *bits, uint8_t *byte_dest, int num_bits); void swap_format(const int *bits, int *dest, int cutoff, int num_bits); -int rotate_byte(int x); +uint8_t rotate_byte(uint8_t x); void rotate_bits(const int *in, int *out, int num_bits); -void print_bytes(const char *msg, const int *bytes, int num_bytes); +void print_bytes(const char *msg, const uint8_t *bytes, int num_bytes); void print_bits(const char *msg, const int *bits, int num_bits); diff --git a/src/eotd.c b/src/eotd.c index cec5ad1..e87b46b 100644 --- a/src/eotd.c +++ b/src/eotd.c @@ -40,7 +40,7 @@ #include "eotd_defs.h" #include "eotd.h" -#define EOTD_RAW +#undef EOTD_RAW #define EOTD_TIMESTAMP #define EOTD_APPEND_HEX @@ -283,7 +283,11 @@ void eotd_to_text (unsigned char *eotd, int eotd_len, char *text, int text_size) add_comma(text, text_size); snprintf(hex, sizeof(hex), "%llx", pkt); strlcat(text, "hex=", text_size); - strlcat(text, hex, text_size); + for (int i = 56; i >= 0; i -= 8) { + sprintf(hex, "%02x ", (unsigned char) (pkt >> i) & 0xff); + strlcat(text, hex, text_size); + } + text[strlen(text) - 1] = '\0'; // zap trailing space #endif #else char temp[8]; diff --git a/src/hdlc_rec.c b/src/hdlc_rec.c index f6a024c..4d47b10 100644 --- a/src/hdlc_rec.c +++ b/src/hdlc_rec.c @@ -33,6 +33,7 @@ #include #include #include // uint64_t +#include //#include "tune.h" #include "demod.h" @@ -46,6 +47,7 @@ #include "demod_9600.h" /* for descramble() */ #include "ptt.h" #include "fx25.h" +#include "bch.h" #include "eotd_defs.h" @@ -233,7 +235,6 @@ static int my_rand (void) { static void eas_rec_bit (int chan, int subchan, int slice, int raw, int future_use) { struct hdlc_state_s *H; - /* * Different state information for each channel / subchannel / slice. */ @@ -408,6 +409,85 @@ a good modem here and providing a result when it is received. */ + +int is_eotd_valid(struct hdlc_state_s *H) { +/* + The data as received in the frame buffer is in HCB+ATAD format; that is, the first + (leftmost) bit is the dummy bit or odd parity bit (which is the last bit transmitted) + followed by the BCH code (LSB first, so HCB) followed by the DATA, LSB first (ATAD). + + The apply_bch funtion requires the packet in int[63] format, with the bits arranged + in either BCH+ATAD or ATAD+BCH format. Very odd. We'll use the first one. +*/ + static uint8_t r2f_mask[] = {0x07, 0x76, 0xa0 }; + static bch_t *bch_r2f = NULL; + static bch_t *bch_f2r = NULL; + + int bits[64]; + + assert(H != NULL); + // +1 for 'type' byte at end + assert(H->frame_len == EOTD_LENGTH + 1); + + if(bch_r2f == NULL) { + bch_r2f = malloc(sizeof(bch_t)); + int status = init_bch(bch_r2f, 6, 63, 3); + if (status != 0) { + fprintf(stderr, "BCH_R2F initialization failed: %d", status); + free(bch_r2f); + bch_r2f = NULL; + return status; + } + } + + if(bch_f2r == NULL) { + bch_f2r = malloc(sizeof(bch_t)); + int status = init_bch(bch_f2r, 6, 63, 6); + if (status != 0) { + fprintf(stderr, "BCH_F2R initialization failed: %d", status); + free(bch_f2r); + bch_f2r = NULL; + return status; + } + } + + int temp_bits[64]; + bch_t *temp_bch; + + if (H->eotd_type == EOTD_TYPE_F2R) { + temp_bch = bch_f2r; + } else { + temp_bch = bch_r2f; + // The HCB needs to be XOR'ed with a special constant. +print_bytes("IN BYTES: ", H->frame_buf, H->frame_len);printf("\n"); + for (int i = 0; i < sizeof(r2f_mask); i++) { + H->frame_buf[i] ^= r2f_mask[i]; + } +print_bytes("XOR BYTES: ", H->frame_buf, H->frame_len);printf("\n"); + } + + int crc_len = temp_bch->n - temp_bch->k; + + bytes_to_bits(H->frame_buf, bits, 64); + + // +1 is to skip the dummy/parity bit. + rotate_bits(bits + 1 , temp_bits, crc_len); + memcpy(bits + 1, temp_bits, crc_len * sizeof(int)); +print_bits("BCH+ATAD : ", bits, 64);printf("\n"); + + // Note: bits are changed in-place. + int corrected = apply_bch(temp_bch, bits + 1); +printf("Corrected %d\n", corrected); + // Put back in HCB+ATAD format + rotate_bits(bits + 1, temp_bits, crc_len); + memcpy(bits + 1, temp_bits, crc_len * sizeof(int)); +print_bits("COR BITS: ", bits, 64);printf("\n"); + bits_to_bytes(bits, H->frame_buf, 64); +print_bytes("COR BYTES: ", H->frame_buf, H->frame_len);printf("\n"); + + return corrected; +} + /*********************************************************************************** * * Name: eotd_rec_bit @@ -480,17 +560,19 @@ dw_printf("chan=%d subchan=%d slice=%d raw=%d\n", chan, subchan, slice, raw); H->frame_buf[EOTD_LENGTH] = H->eotd_type; done = 1; #ifdef EOTD_DEBUG -for (int ii=0; ii < EOTD_MAX_LENGTH; ii++) {dw_printf("%02x ", H->frame_buf[ii]); } dw_printf("\n"); +for (int ii=0; ii < EOTD_LENGTH; ii++) {dw_printf("%02x ", H->frame_buf[ii]); } dw_printf("\n"); #endif } } if (done) { #ifdef DEBUG_E - dw_printf ("frame_buf %d = %s\n", slice, H->frame_buf); + dw_printf ("frame_buf %d = %*s\n", slice, H->frame_len, H->frame_buf); #endif - alevel_t alevel = demod_get_audio_level (chan, subchan); - multi_modem_process_rec_frame (chan, subchan, slice, H->frame_buf, H->frame_len, alevel, 0, 0); + if (is_eotd_valid(H) >= 0) { + alevel_t alevel = demod_get_audio_level (chan, subchan); + multi_modem_process_rec_frame (chan, subchan, slice, H->frame_buf, H->frame_len, alevel, 0, 0); + } H->eotd_acc = 0; H->eotd_gathering = 0;