mirror of https://github.com/wb2osz/direwolf.git
First fully-working BCH code.
This commit is contained in:
parent
1fb18ed542
commit
07209b5f22
|
@ -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)
|
||||
|
|
147
src/bch.c
147
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
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#ifndef __BCH_H
|
||||
#define __BCH_H
|
||||
#include <stdlib.h>
|
||||
|
||||
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);
|
||||
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h> // uint64_t
|
||||
#include <stdlib.h>
|
||||
|
||||
//#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;
|
||||
|
|
Loading…
Reference in New Issue