Skip to content

Commit 07209b5

Browse files
committed
First fully-working BCH code.
1 parent 1fb18ed commit 07209b5

File tree

5 files changed

+109
-149
lines changed

5 files changed

+109
-149
lines changed

Diff for: src/CMakeLists.txt

+2
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ list(APPEND direwolf_SOURCES
8686
dwgpsd.c
8787
mheard.c
8888
eotd.c
89+
bch.c
8990
)
9091

9192
if(LINUX)
@@ -319,6 +320,7 @@ list(APPEND atest_SOURCES
319320
tt_text.c
320321
textcolor.c
321322
eotd.c
323+
bch.c
322324
)
323325

324326
if(WIN32 OR CYGWIN)

Diff for: src/bch.c

+9-138
Original file line numberDiff line numberDiff line change
@@ -518,7 +518,7 @@ int apply_bch(const bch_t *bch, int *recd)
518518
}
519519

520520
/* LEFT justified in hex */
521-
void bytes_to_bits(const int *bytes, int *bit_dest, int num_bits) {
521+
void bytes_to_bits(const uint8_t *bytes, int *bit_dest, int num_bits) {
522522
for (int i = 0; i < num_bits; i++) {
523523
int index = i / 8;
524524
int bit_pos = 7 - (i % 8);
@@ -527,7 +527,7 @@ void bytes_to_bits(const int *bytes, int *bit_dest, int num_bits) {
527527
}
528528
}
529529

530-
void bits_to_bytes(const int *bits, int *byte_dest, int num_bits) {
530+
void bits_to_bytes(const int *bits, uint8_t *byte_dest, int num_bits) {
531531

532532
int index;
533533

@@ -540,8 +540,6 @@ void bits_to_bytes(const int *bits, int *byte_dest, int num_bits) {
540540
byte_dest[index] <<= 1;
541541
byte_dest[index] |= (bits[i] & 0x01);
542542
}
543-
544-
byte_dest[index] <<= 8 - (num_bits % 8);
545543
}
546544

547545
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) {
555553
}
556554
}
557555

558-
int rotate_byte(int x) {
559-
int y = 0;
556+
uint8_t rotate_byte(uint8_t x) {
557+
uint8_t y = 0;
560558

561559
for (int i = 0; i < 8; i++) {
562560
y <<= 1;
@@ -583,143 +581,16 @@ void dump_bch(const bch_t *bch) {
583581
printf("m: %d length: %d t: %d n: %d k: %d\n", bch->m, bch->length, bch->t, bch->n, bch->k);
584582
}
585583

586-
void print_array(const char *msg, const char *format, const int *bytes, int num_bytes) {
584+
void print_bytes(const char *msg, const uint8_t *bytes, int num_bytes) {
587585
printf("%s", msg);
588586
for (int i = 0; i < num_bytes; i++) {
589-
printf(format, bytes[i]);
587+
printf("%02x ", bytes[i]);
590588
}
591589
}
592590

593-
void print_bytes(const char *msg, const int *bytes, int num_bytes) {
594-
print_array(msg, "%02x ", bytes, num_bytes);
595-
}
596-
597591
void print_bits(const char *msg, const int *bits, int num_bits) {
598-
print_array(msg, "%d ", bits, num_bits);
599-
}
600-
601-
#undef MAIN
602-
#undef TEST_BYTES_TO_BITS
603-
#define TEST_SWAP
604-
#ifdef MAIN
605-
int main()
606-
{
607-
int test[][8] = {
608-
/* 0 errors */ { 0xb2, 0x17, 0xa2, 0xb9, 0x53, 0xdd, 0xc5, 0x52 }, /* perfect random test */
609-
{ 0xf0, 0x5a, 0x6a, 0x6a, 0x01, 0x63, 0x33, 0xd0 }, /* g001-cut-lenthened_457.938M.wav */
610-
{ 0xf0, 0x81, 0x52, 0x6b, 0x71, 0xa5, 0x63, 0x08 }, /* 1st in eotd_received_data */
611-
/* 3 errors */ { 0xf0, 0x85, 0x50, 0x6a, 0x01, 0xe5, 0x6e, 0x84 }, /* 2nd in eotd_received_data - 3 bad bits */
612-
/* 0 errors */ { 0xf0, 0x85, 0x50, 0x6a, 0x01, 0xe5, 0x06, 0x84 }, /* 2nd, but with the bits fixed */
613-
/* 3 errors */ { 0xf0, 0x85, 0x59, 0x5a, 0x01, 0xe5, 0x6e, 0x84 }, /* 3rd - 3 bad bits */
614-
/* 0 errors */ { 0xb0, 0x85, 0x59, 0x5a, 0x11, 0xe5, 0x6f, 0x84 }, /* 3rd fixed */
615-
{ 0xf1, 0x34, 0x50, 0x1a, 0x01, 0xe5, 0x66, 0xfe }, /* 4th */
616-
{ 0xf0, 0xeb, 0x10, 0xea, 0x01, 0x6e, 0x54, 0x1c }, /* 5th */
617-
{ 0xf0, 0xea, 0x5c, 0xea, 0x01, 0x6e, 0x55, 0x0e }, /* 6th */
618-
{ 0xe0, 0x21, 0x10, 0x1a, 0x01, 0x32, 0xbc, 0xe4 }, /* Sun Mar 20 05:41:00 2022 */
619-
{ 0xf0, 0x42, 0x50, 0x5b, 0xcf, 0xd5, 0x64, 0xe4 }, /* Sun Mar 20 12:58:43 2022 */
620-
{ 0xf0, 0x8c, 0x10, 0xaa, 0x01, 0x73, 0x7b, 0x1a }, /* Sun Mar 20 13:35:48 2022 */
621-
{ 0xf0, 0x8c, 0x10, 0xb1, 0xc0, 0xe0, 0x90, 0x64 }, /* Sun Mar 20 13:37:05 2022 */
622-
/* 3 errors */ { 0xf0, 0x8c, 0x10, 0x6a, 0x01, 0x64, 0x7a, 0xe8 }, /* Sun Mar 20 13:37:48 2022 - 3 bad bits */
623-
/* 0 errors */ { 0x50, 0x8c, 0x12, 0x6a, 0x01, 0x64, 0x7a, 0xe8 }, /* Sun Mar 20 13:37:48 2022 with bits fixed */
624-
};
625-
626-
int bits[63];
627-
int temp[8];
628-
bch_t bch;
629-
630-
init_bch(&bch, 6, 63, 3);
631-
632-
for (int count = 0; count < sizeof(test) / sizeof(*test); count++) {
633-
bytes_to_bits(test[count], bits, 63);
634-
635-
printf("--------------------------\nORIG pkt [%d] ", count);
636-
for (int i = 0; i < 8; i++) {
637-
printf("%02x ", test[count][i]);
638-
}
639-
printf("\n");
640-
641-
#ifdef TEST_BYTES_TO_BITS
642-
643-
printf("ORIG pkt[%d] bits\n", count);
644-
for (int i = 0; i < 63; i++) {
645-
printf("%d ", bits[i]);
646-
}
647-
printf("\n");
648-
649-
bits_to_bytes(bits, temp, 63);
650-
printf("bits_to_bytes pkt [%d]\n", count);
651-
for (int i = 0; i < 8; i++) {
652-
printf("%02x ", temp[i]);
653-
}
654-
printf("\n");
655-
656-
#endif
657-
658-
#ifdef TEST_GENERATE
659-
int bch_code[18];
660-
generate_bch(&bch, bits, bch_code);
661-
printf("generated BCH\n");
662-
for (int i = 0; i < 18; i++) {
663-
printf("%d ", bch_code[i]);
664-
}
665-
printf("\n");
666-
#endif
667-
668-
#ifdef TEST_SWAP
669-
printf("orig: ");
670-
for (int i = 0; i < 63; i++) {
671-
printf("%d ", bits[i]);
672-
}
673-
printf("\n");
674-
675-
swap_format(bits, 45, 63);
676-
677-
printf("rev: ");
678-
for (int i = 0; i < 63; i++) {
679-
printf("%d ", bits[i]);
680-
}
681-
printf("\n");
682-
#endif
683-
#ifdef TEST_APPLY
684-
int recv[63];
685-
686-
for (int i = 0; i < 63; i++) {
687-
recv[i] = bits[i];
688-
}
689-
/*
690-
printf("rearranged packet [%d]: ", count);
691-
for (int i = 0; i < 63; i++) {
692-
printf("%d ", recv[i]);
693-
}
694-
printf("\n");
695-
696-
bits_to_bytes(recv, temp, 63);
697-
698-
printf("original [%d] bytes: ", count);
699-
for (int i = 0; i < 8; i++) {
700-
printf("%02x ", temp[i]);
701-
}
702-
printf("\n");
703-
*/
704-
int corrected = apply_bch(&bch, recv);
705-
706-
if (corrected >= 0) {
707-
/*
708-
printf("corrected [%d] packet: ", corrected);
709-
for (int i = 0; i < 63; i++) {
710-
printf("%d ", recv[i]);
711-
}
712-
printf("\n");
713-
*/
714-
bits_to_bytes(recv, temp, 63);
715-
716-
printf("corrected [%d] bytes: ", corrected);
717-
for (int i = 0; i < 8; i++) {
718-
printf("%02x ", temp[i]);
719-
}
720-
printf("\n");
721-
}
722-
#endif
592+
printf("%s", msg);
593+
for (int i = 0; i < num_bits; i++) {
594+
printf("%d ", bits[i]);
723595
}
724596
}
725-
#endif

Diff for: src/bch.h

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#ifndef __BCH_H
22
#define __BCH_H
3+
#include <stdlib.h>
34

45
struct bch {
56
int m; // 2^m - 1 is max length, n
@@ -21,17 +22,17 @@ void generate_bch(bch_t *bch, const int *data, int *bb);
2122

2223
int apply_bch(const bch_t *bch, int *recd);
2324

24-
void bytes_to_bits(const int *bytes, int *bit_dest, int num_bits);
25+
void bytes_to_bits(const uint8_t *bytes, int *bit_dest, int num_bits);
2526

26-
void bits_to_bytes(const int *bits, int *byte_dest, int num_bits);
27+
void bits_to_bytes(const int *bits, uint8_t *byte_dest, int num_bits);
2728

2829
void swap_format(const int *bits, int *dest, int cutoff, int num_bits);
2930

30-
int rotate_byte(int x);
31+
uint8_t rotate_byte(uint8_t x);
3132

3233
void rotate_bits(const int *in, int *out, int num_bits);
3334

34-
void print_bytes(const char *msg, const int *bytes, int num_bytes);
35+
void print_bytes(const char *msg, const uint8_t *bytes, int num_bytes);
3536

3637
void print_bits(const char *msg, const int *bits, int num_bits);
3738

Diff for: src/eotd.c

+6-2
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
#include "eotd_defs.h"
4141
#include "eotd.h"
4242

43-
#define EOTD_RAW
43+
#undef EOTD_RAW
4444
#define EOTD_TIMESTAMP
4545
#define EOTD_APPEND_HEX
4646

@@ -283,7 +283,11 @@ void eotd_to_text (unsigned char *eotd, int eotd_len, char *text, int text_size)
283283
add_comma(text, text_size);
284284
snprintf(hex, sizeof(hex), "%llx", pkt);
285285
strlcat(text, "hex=", text_size);
286-
strlcat(text, hex, text_size);
286+
for (int i = 56; i >= 0; i -= 8) {
287+
sprintf(hex, "%02x ", (unsigned char) (pkt >> i) & 0xff);
288+
strlcat(text, hex, text_size);
289+
}
290+
text[strlen(text) - 1] = '\0'; // zap trailing space
287291
#endif
288292
#else
289293
char temp[8];

Diff for: src/hdlc_rec.c

+87-5
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include <assert.h>
3434
#include <string.h>
3535
#include <stdint.h> // uint64_t
36+
#include <stdlib.h>
3637

3738
//#include "tune.h"
3839
#include "demod.h"
@@ -46,6 +47,7 @@
4647
#include "demod_9600.h" /* for descramble() */
4748
#include "ptt.h"
4849
#include "fx25.h"
50+
#include "bch.h"
4951
#include "eotd_defs.h"
5052

5153

@@ -233,7 +235,6 @@ static int my_rand (void) {
233235
static void eas_rec_bit (int chan, int subchan, int slice, int raw, int future_use)
234236
{
235237
struct hdlc_state_s *H;
236-
237238
/*
238239
* Different state information for each channel / subchannel / slice.
239240
*/
@@ -408,6 +409,85 @@ a good modem here and providing a result when it is received.
408409
409410
*/
410411

412+
413+
int is_eotd_valid(struct hdlc_state_s *H) {
414+
/*
415+
The data as received in the frame buffer is in HCB+ATAD format; that is, the first
416+
(leftmost) bit is the dummy bit or odd parity bit (which is the last bit transmitted)
417+
followed by the BCH code (LSB first, so HCB) followed by the DATA, LSB first (ATAD).
418+
419+
The apply_bch funtion requires the packet in int[63] format, with the bits arranged
420+
in either BCH+ATAD or ATAD+BCH format. Very odd. We'll use the first one.
421+
*/
422+
static uint8_t r2f_mask[] = {0x07, 0x76, 0xa0 };
423+
static bch_t *bch_r2f = NULL;
424+
static bch_t *bch_f2r = NULL;
425+
426+
int bits[64];
427+
428+
assert(H != NULL);
429+
// +1 for 'type' byte at end
430+
assert(H->frame_len == EOTD_LENGTH + 1);
431+
432+
if(bch_r2f == NULL) {
433+
bch_r2f = malloc(sizeof(bch_t));
434+
int status = init_bch(bch_r2f, 6, 63, 3);
435+
if (status != 0) {
436+
fprintf(stderr, "BCH_R2F initialization failed: %d", status);
437+
free(bch_r2f);
438+
bch_r2f = NULL;
439+
return status;
440+
}
441+
}
442+
443+
if(bch_f2r == NULL) {
444+
bch_f2r = malloc(sizeof(bch_t));
445+
int status = init_bch(bch_f2r, 6, 63, 6);
446+
if (status != 0) {
447+
fprintf(stderr, "BCH_F2R initialization failed: %d", status);
448+
free(bch_f2r);
449+
bch_f2r = NULL;
450+
return status;
451+
}
452+
}
453+
454+
int temp_bits[64];
455+
bch_t *temp_bch;
456+
457+
if (H->eotd_type == EOTD_TYPE_F2R) {
458+
temp_bch = bch_f2r;
459+
} else {
460+
temp_bch = bch_r2f;
461+
// The HCB needs to be XOR'ed with a special constant.
462+
print_bytes("IN BYTES: ", H->frame_buf, H->frame_len);printf("\n");
463+
for (int i = 0; i < sizeof(r2f_mask); i++) {
464+
H->frame_buf[i] ^= r2f_mask[i];
465+
}
466+
print_bytes("XOR BYTES: ", H->frame_buf, H->frame_len);printf("\n");
467+
}
468+
469+
int crc_len = temp_bch->n - temp_bch->k;
470+
471+
bytes_to_bits(H->frame_buf, bits, 64);
472+
473+
// +1 is to skip the dummy/parity bit.
474+
rotate_bits(bits + 1 , temp_bits, crc_len);
475+
memcpy(bits + 1, temp_bits, crc_len * sizeof(int));
476+
print_bits("BCH+ATAD : ", bits, 64);printf("\n");
477+
478+
// Note: bits are changed in-place.
479+
int corrected = apply_bch(temp_bch, bits + 1);
480+
printf("Corrected %d\n", corrected);
481+
// Put back in HCB+ATAD format
482+
rotate_bits(bits + 1, temp_bits, crc_len);
483+
memcpy(bits + 1, temp_bits, crc_len * sizeof(int));
484+
print_bits("COR BITS: ", bits, 64);printf("\n");
485+
bits_to_bytes(bits, H->frame_buf, 64);
486+
print_bytes("COR BYTES: ", H->frame_buf, H->frame_len);printf("\n");
487+
488+
return corrected;
489+
}
490+
411491
/***********************************************************************************
412492
*
413493
* Name: eotd_rec_bit
@@ -480,17 +560,19 @@ dw_printf("chan=%d subchan=%d slice=%d raw=%d\n", chan, subchan, slice, raw);
480560
H->frame_buf[EOTD_LENGTH] = H->eotd_type;
481561
done = 1;
482562
#ifdef EOTD_DEBUG
483-
for (int ii=0; ii < EOTD_MAX_LENGTH; ii++) {dw_printf("%02x ", H->frame_buf[ii]); } dw_printf("\n");
563+
for (int ii=0; ii < EOTD_LENGTH; ii++) {dw_printf("%02x ", H->frame_buf[ii]); } dw_printf("\n");
484564
#endif
485565
}
486566
}
487567

488568
if (done) {
489569
#ifdef DEBUG_E
490-
dw_printf ("frame_buf %d = %s\n", slice, H->frame_buf);
570+
dw_printf ("frame_buf %d = %*s\n", slice, H->frame_len, H->frame_buf);
491571
#endif
492-
alevel_t alevel = demod_get_audio_level (chan, subchan);
493-
multi_modem_process_rec_frame (chan, subchan, slice, H->frame_buf, H->frame_len, alevel, 0, 0);
572+
if (is_eotd_valid(H) >= 0) {
573+
alevel_t alevel = demod_get_audio_level (chan, subchan);
574+
multi_modem_process_rec_frame (chan, subchan, slice, H->frame_buf, H->frame_len, alevel, 0, 0);
575+
}
494576

495577
H->eotd_acc = 0;
496578
H->eotd_gathering = 0;

0 commit comments

Comments
 (0)