dfm: ecc2 - soft decision

pull/27/head
Zilog80 2020-05-04 01:20:53 +02:00
rodzic 86333eb604
commit 89d8518954
3 zmienionych plików z 252 dodań i 25 usunięć

Wyświetl plik

@ -183,13 +183,13 @@ static int check(int opt_ecc, hsbit_t code[8]) {
if (ret > 0) code[ret-1].hb ^= 0x1; // d=1: 1-bit-error
else if (ret < 0 && opt_ecc == 2) { // d=2: 2-bit-error: soft decision
// Hamming [8,4]
// Hamming(8,4)
// 256 words:
// 16 codewords
// 16*8=128 1-error words (dist=1)
// 16*7=112 2-error words (dist=2)
// each 2-error word has 4 codewords w/ dist=2
// choose best "correlation"
// each 2-error word has 4 codewords w/ dist=2,
// choose best match/correlation
int n;
int maxn = -1;
int d = 0;
@ -203,14 +203,14 @@ static int check(int opt_ecc, hsbit_t code[8]) {
*/
for (n = 0; n < 16; n++) {
d = 0;
sum = 0.0;
for (i = 0; i < 8; i++) { // d(a,b) = sum_i a[i]^b[i]
if (code[i].hb != codewords[n][i]) d++;
}
if (d == 2) { // dist=2
if (d == 2) { // check dist=2 codewords - in principle, all codewords could be tested
// softbits correlation:
// - interleaving
// + no pulse-shaping -> sum
sum = 0.0;
for (i = 0; i < 8; i++) {
sum += (2*codewords[n][i]-1) * code[i].sb;
}
@ -1077,6 +1077,11 @@ int main(int argc, char **argv) {
}
if (!wavloaded) fp = stdin;
// ecc2-soft_decision accepts also 2-error words,
// so the probability for 3 errors is high and will
// produce wrong codewords. hence ecc2 is not recommended
// for reliable frame decoding.
//
if ( option_dist || option_json ) option_ecc = 1;

Wyświetl plik

@ -322,6 +322,56 @@ int read_rawbit3(FILE *fp, int *bit) {
return 0;
}
typedef struct {
ui8_t hb;
float sb;
} hsbit_t;
int soft_read_rawbit2(FILE *fp, hsbit_t *shb) {
int sample;
int sum;
ui8_t bit = 0;
sum = 0;
if (bitstart) {
scount = 0; // eigentlich scount = 1
bitgrenze = 0; // oder bitgrenze = -1
bitstart = 0;
}
bitgrenze += samples_per_bit;
do {
sample = read_signed_sample(fp);
if (sample == EOF_INT) return EOF;
//sample_count++; // in read_signed_sample()
//par = (sample >= 0) ? 1 : -1; // 8bit: 0..127,128..255 (-128..-1,0..127)
sum += sample;
scount++;
} while (scount < bitgrenze); // n < samples_per_bit
bitgrenze += samples_per_bit;
do {
sample = read_signed_sample(fp);
if (sample == EOF_INT) return EOF;
//sample_count++; // in read_signed_sample()
//par = (sample >= 0) ? 1 : -1; // 8bit: 0..127,128..255 (-128..-1,0..127)
sum -= sample;
scount++;
} while (scount < bitgrenze); // n < samples_per_bit
if (option_inv) sum = -sum; // sum=0 bleibt bit=1
// jedoch sb und hb werden zusammen invertiert
if (sum >= 0) bit = 1;
else bit = 0;
shb->hb = bit;
shb->sb = sum;
return 0;
}
/* -------------------------------------------------------------------------- */
//#define BITS (2*8) // 16
@ -341,6 +391,8 @@ int bufpos = -1;
char frame_rawbits[RAWBITFRAME_LEN+8] = "01100101011001101010010110101010"; //->"0100010111001111";
char frame_bits[BITFRAME_LEN+4];
hsbit_t frm[BITFRAME_LEN+4];
void inc_bufpos() {
bufpos = (bufpos+1) % HEADLEN;
@ -417,6 +469,16 @@ void manchester1(char* frame_rawbits, char *frame_bits, int pos) {
#define DAT2 (16+160) // 104 bit
// frame: 280 bit
ui8_t G[8][4] = // Generator
{{ 1, 0, 0, 0},
{ 0, 1, 0, 0},
{ 0, 0, 1, 0},
{ 0, 0, 0, 1},
{ 0, 1, 1, 1},
{ 1, 0, 1, 1},
{ 1, 1, 0, 1},
{ 1, 1, 1, 0}};
ui8_t H[4][8] = // Parity-Check
{{ 0, 1, 1, 1, 1, 0, 0, 0},
{ 1, 0, 1, 1, 0, 1, 0, 0},
@ -432,6 +494,33 @@ ui8_t block_conf[ 7*S]; // 7*4=28
ui8_t block_dat1[13*S]; // 13*4=52
ui8_t block_dat2[13*S];
hsbit_t soft_hamming_conf[ 7*B]; // 7*8=56
hsbit_t soft_hamming_dat1[13*B]; // 13*8=104
hsbit_t soft_hamming_dat2[13*B];
ui8_t codewords[16][8];
int nib4bits(ui8_t nib, ui8_t *bits) { // big endian
int j;
nib &= 0xF;
for (j = 0; j < 4; j++) {
bits[j] = (nib>>(3-j)) & 0x1;
}
return 0;
}
int gencode(ui8_t msg[4], ui8_t code[8]) {
int i, j; // Gm=c
for (i = 0; i < 8; i++) {
code[i] = 0;
for (j = 0; j < 4; j++) {
code[i] ^= G[i][j] & msg[j];
}
}
return 0;
}
ui32_t bits2val(ui8_t *bits, int len) { // big endian
int j;
ui32_t val;
@ -454,6 +543,15 @@ void deinterleave(char *str, int L, ui8_t *block) {
}
}
void soft_deinterleave(hsbit_t *str, int L, hsbit_t *block) {
int i, j;
for (j = 0; j < B; j++) { // L = 7, 13
for (i = 0; i < L; i++) {
block[B*i+j] = str[L*j+i];
}
}
}
int check(ui8_t code[8]) {
int i, j; // Bei Demodulierung durch Nulldurchgaenge, wenn durch Fehler ausser Takt,
ui32_t synval = 0; // verschieben sich die bits. Fuer Hamming-Decode waere es besser,
@ -494,6 +592,82 @@ int hamming(ui8_t *ham, int L, ui8_t *sym) {
return ret;
}
int soft_check(hsbit_t code[8]) {
int i, j; // Bei Demodulierung durch Nulldurchgaenge, wenn durch Fehler ausser Takt,
ui32_t synval = 0; // verschieben sich die bits. Fuer Hamming-Decode waere es besser,
ui8_t syndrom[4]; // sync zu Beginn mit Header und dann Takt beibehalten fuer decision.
int ret=0;
for (i = 0; i < 4; i++) { // S = 4
syndrom[i] = 0;
for (j = 0; j < 8; j++) { // B = 8
syndrom[i] ^= H[i][j] & code[j].hb;
}
}
synval = bits2val(syndrom, 4);
if (synval) {
ret = -1;
for (j = 0; j < 8; j++) { // 1-bit-error
if (synval == He[j]) { // reicht auf databits zu pruefen, d.h.
ret = j+1; // (systematischer Code) He[0..3]
break;
}
}
}
else ret = 0; // d=0: valid codeword
if (ret > 0) code[ret-1].hb ^= 0x1; // d=1: 1-bit-error
else if (ret < 0 && option_ecc == 2) { // d=2: 2-bit-error: soft decision
int n;
int count = 0;
int maxn = -1;
int d = 0;
float sum = 0.0;
float maxsum = 0.0;
for (n = 0; n < 16; n++) {
d = 0;
for (i = 0; i < 8; i++) { // d(a,b) = sum_i a[i]^b[i]
if (code[i].hb != codewords[n][i]) d++;
}
if (d == 2) { // dist=2
count++;
// sum softbits
// correlation: - interleaving
// + no pulse-shaping -> sum
//
sum = 0.0;
for (i = 0; i < 8; i++) {
sum += (2*codewords[n][i]-1) * code[i].sb;
}
if (sum >= maxsum) {
maxsum = sum;
maxn = n;
}
}
}
if (maxn >= 0) {
for (i = 0; i < 8; i++) {
if (code[i].hb = codewords[maxn][i]);
}
//ret = 0x100;
}
}
return ret;
}
int soft_hamming(hsbit_t *ham, int L, ui8_t *sym) {
int i, j;
int ret = 0; // L = 7, 13
for (i = 0; i < L; i++) { // L * 2 nibble (data+parity)
if (option_ecc) ret |= soft_check(ham+B*i);
for (j = 0; j < S; j++) { // systematic: bits 0..S-1 data
sym[S*i+j] = ham[B*i+j].hb;
}
}
return ret;
}
char nib2chr(ui8_t nib) {
char c = '_';
if (nib < 0x10) {
@ -998,13 +1172,27 @@ void print_frame() {
manchester1(frame_rawbits, frame_bits, RAWBITFRAME_LEN);
}
deinterleave(frame_bits+CONF, 7, hamming_conf);
deinterleave(frame_bits+DAT1, 13, hamming_dat1);
deinterleave(frame_bits+DAT2, 13, hamming_dat2);
ret0 = hamming(hamming_conf, 7, block_conf);
ret1 = hamming(hamming_dat1, 13, block_dat1);
ret2 = hamming(hamming_dat2, 13, block_dat2);
if (option_ecc == 2) {
soft_deinterleave(frm+CONF, 7, soft_hamming_conf);
soft_deinterleave(frm+DAT1, 13, soft_hamming_dat1);
soft_deinterleave(frm+DAT2, 13, soft_hamming_dat2);
ret0 = soft_hamming(soft_hamming_conf, 7, block_conf);
ret1 = soft_hamming(soft_hamming_dat1, 13, block_dat1);
ret2 = soft_hamming(soft_hamming_dat2, 13, block_dat2);
}
else {
deinterleave(frame_bits+CONF, 7, hamming_conf);
deinterleave(frame_bits+DAT1, 13, hamming_dat1);
deinterleave(frame_bits+DAT2, 13, hamming_dat2);
ret0 = hamming(hamming_conf, 7, block_conf);
ret1 = hamming(hamming_dat1, 13, block_dat1);
ret2 = hamming(hamming_dat2, 13, block_dat2);
}
if (option_raw == 1) {
@ -1042,14 +1230,14 @@ void print_frame() {
}
else if (option_ecc) {
if (ret0 == 0 || ret0 > 0) {
if (ret0 == 0 || ret0 > 0 || option_ecc == 2) {
conf_out(block_conf);
}
if (ret1 == 0 || ret1 > 0) {
if (ret1 == 0 || ret1 > 0 || option_ecc == 2) {
frid = dat_out(block_dat1);
if (frid == 8) print_gpx();
}
if (ret2 == 0 || ret2 > 0) {
if (ret2 == 0 || ret2 > 0 || option_ecc == 2) {
frid = dat_out(block_dat2);
if (frid == 8) print_gpx();
}
@ -1120,9 +1308,8 @@ int main(int argc, char **argv) {
else if (strcmp(*argv, "-b" ) == 0) { option_b = 1; }
else if (strcmp(*argv, "-b2") == 0) { option_b = 2; }
else if (strcmp(*argv, "-b3") == 0) { option_b = 3; }
else if ( (strcmp(*argv, "--ecc") == 0) ) {
option_ecc = 1;
}
else if ( (strcmp(*argv, "--ecc" ) == 0) ) { option_ecc = 1; }
else if ( (strcmp(*argv, "--ecc2") == 0) ) { option_ecc = 2; }
else if ( (strcmp(*argv, "--ptu") == 0) ) {
option_ptu = 1;
//ptu_out = 1; // force ptu (non PS-15)
@ -1140,6 +1327,7 @@ int main(int argc, char **argv) {
}
if (!wavloaded) fp = stdin;
if (option_ecc == 2) option_b = 2;
i = read_wav_header(fp);
if (i) {
@ -1155,6 +1343,16 @@ int main(int argc, char **argv) {
}
if (option_ecc == 2) {
ui8_t nib, msg[4], code[8];
for (nib = 0; nib < 16; nib++) {
nib4bits(nib, msg);
gencode(msg, code);
for (i = 0; i < 8; i++) codewords[nib][i] = code[i];
}
}
for (i = 0; i < 9; i++) {
for (j = 0; j < 13; j++) dat_str[i][j] = ' ';
}
@ -1224,9 +1422,26 @@ int main(int argc, char **argv) {
manchester1(frame_rawbits, frame_bits, pos);
pos /= 2;
if (option_ecc == 2) {
for (i = 0; i < pos; i++) {
frm[i].hb = frame_bits[i] % 1;
frm[i].sb = 0.0; // (ecc2) bit=1: sb>0 , bit=0: sb<0
}
}
while ( pos < BITFRAME_LEN ) {
if (option_b==2) { if (read_rawbit2(fp, &bit) == EOF) break; }
else { if (read_rawbit3(fp, &bit) == EOF) break; }
if (option_b == 2) {
if (option_ecc == 2) {
if (soft_read_rawbit2(fp, frm+pos) == EOF) break;
bit = frm[pos].hb;
}
else {
if (read_rawbit2(fp, &bit) == EOF) break;
}
}
else { // option_b==3
if (read_rawbit3(fp, &bit) == EOF) break;
}
frame_bits[pos] = 0x30 + bit;
pos++;
}

Wyświetl plik

@ -5,14 +5,21 @@ Einige Radiosonden senden frames mit Codewoertern, die eine Fehlerkorrektur ermo
Graw
====
BCH/Hamming code (N, N-R) = (2^m - 1, N-m), d.h. R=mt mit t=1,
Hammingcode (N, N-R) = (2^m - 1, N-m), d.h. R=mt mit t=1,
korrigiert t=1 Fehler pro Codewort der Laenge N,
die Codewoerter haben den Abstand d=3 (bei 2 Fehlern
wird falsch dekodiert).
Fuer die Sonden DFM-06/09 ist m=3, d.h. Hamming (7, 4),
jedoch mit einem Paritaetsbit zu (8, 4) erweitert.
Der erweiterte Hammingcode (8, 4) kann zudem 2 Fehler
die Codewoerter haben den (min.) Abstand d=3
(bei 2 Fehlern wird zum Nachbarcodewort falsch dekodiert).
Fuer die Sonden DFM-06/09 ist m=3, d.h. Hamming(7,4),
jedoch mit einem Paritaetsbit zu (8,4) erweitert.
Der erweiterte Hammingcode (8,4) kann zudem 2 Fehler
als nicht-korrigierbar erkennen (wird nicht falsch decodiert).
Zu einem Wort mit 2 Fehlern gibt es 4 Codewoerter mit Abstand 2.
Von diesen kann das Codewort, das am besten passt, ausgewaehlt
werden (soft decision). Allerdings steigt die Wahrscheinlichkeit,
dass neben 2 Fehlern auch Woerter mit 3 Fehlern vorkommen, wobei
diese dann falsch decodiert werden.
Meisei