Move Hagelbarger error correction code from NMT to common code

It will be used by Radiocom 2000 also.
Some minor fixes and improvements apply.
This commit is contained in:
Andreas Eversberg 2017-07-24 19:18:01 +02:00
parent 6c64025717
commit 0cbd9657d2
7 changed files with 32 additions and 14 deletions

View File

@ -25,6 +25,7 @@ libcommon_a_SOURCES = \
fft.c \
fm_modulation.c \
ffsk.c \
hagelbarger.c \
sender.c \
display_wave.c \
display_status.c \

View File

@ -27,10 +27,13 @@
#include "stdint.h"
/* enable to debug the process of parity check */
//#define DEBUG_HAGEL
/* To encode NMT message: (MSB first)
* Use input with 9 bytes, the last byte must be 0x00.
* Use output with 18 bytes, ignore the last four (lower) bits of last byte.
* Use length of 72.
* Use length of 70.
*/
void hagelbarger_encode(const uint8_t *input, uint8_t *output, int length)
{
@ -49,6 +52,9 @@ void hagelbarger_encode(const uint8_t *input, uint8_t *output, int length)
/* put check bit and data bit to output (MSB first) */
output[i / 4] = (output[i / 4] << 2) | (check << 1) | data;
}
/* shift last output byte all the way to MSB */
while ((i % 4))
output[i++ / 4] <<= 2;
}
/* To decode NMT message: (MSB first)
@ -58,12 +64,12 @@ void hagelbarger_encode(const uint8_t *input, uint8_t *output, int length)
*/
void hagelbarger_decode(const uint8_t *input, uint8_t *output, int length)
{
uint16_t reg_data = 0x00, reg_check = 0x00, data, check, r_parity, s_parity;
int i;
uint16_t reg_data = 0x00, reg_check = 0xff, data, check, r_parity, s_parity;
int i, o;
length += 10;
for (i = 0; i < length; i++) {
for (i = 0, o = 0; i < length; i++) {
/* get check bit from input (MSB first) */
check = (input[i / 4] >> (7 - (i & 3) * 2)) & 1;
/* get data bit from input (MSB first) */
@ -75,13 +81,21 @@ void hagelbarger_decode(const uint8_t *input, uint8_t *output, int length)
/* calculate parity */
r_parity = (reg_data + (reg_data >> 3) + (reg_check >> 6) + 1) & 1;
s_parity = ((reg_data >> 3) + (reg_data >> 6) + (reg_check >> 9) + 1) & 1;
#ifdef DEBUG_HAGEL
printf("#%d: r=%d s=%d\n", i - 10, r_parity, s_parity);
#endif
/* flip message bit, if both parity checks fail */
/* use 4th bit that will be shifted to 5th bit next loop */
if (r_parity && s_parity)
reg_data ^= 0x0008;
/* put message bit to output (MSB first) */
if (i >= 10)
output[(i - 10) / 8] = (output[(i - 10) / 8] << 1) | ((reg_data >> 4) & 1);
if (i >= 10) {
output[o / 8] = (output[o / 8] << 1) | ((reg_data >> 4) & 1);
o++;
}
}
/* shift last output byte all the way to MSB */
while ((o % 8))
output[o++ / 8] <<= 1;
}

View File

@ -8,7 +8,6 @@ nmt_SOURCES = \
countries.c \
transaction.c \
dsp.c \
hagelbarger.c \
frame.c \
dms.c \
sms.c \

View File

@ -25,9 +25,9 @@
#include "../common/sample.h"
#include "../common/debug.h"
#include "../common/timer.h"
#include "../common/hagelbarger.h"
#include "nmt.h"
#include "frame.h"
#include "hagelbarger.h"
uint64_t nmt_encode_channel(int nmt_system, int channel, int power)
{
@ -1146,7 +1146,7 @@ const char *encode_frame(int nmt_system, frame_t *frame, int debug)
message[8] = 0x00;
for (i = 0; i < 8; i++)
message[i] = (digits[i * 2] << 4) | digits[i * 2 + 1];
hagelbarger_encode(message, code, 72);
hagelbarger_encode(message, code, 70);
memcpy(bits, "10101010101010111100010010", 26);
for (i = 0; i < 140; i++)
bits[i + 26] = ((code[i / 8] >> (7 - (i & 7))) & 1) + '0';

View File

@ -79,7 +79,7 @@ test_performance_LDADD = \
-lm
test_hagelbarger_SOURCES = \
$(top_builddir)/src/nmt/hagelbarger.c \
$(top_builddir)/src/common/hagelbarger.c \
test_hagelbarger.c
test_hagelbarger_LDADD = \

View File

@ -1,7 +1,7 @@
#include "stdio.h"
#include "stdint.h"
#include "string.h"
#include "../nmt/hagelbarger.h"
#include "../common/hagelbarger.h"
int main(void)
{
@ -9,11 +9,15 @@ int main(void)
printf("Message: %s\n", message);
/* clean tail at code bit 72 and above */
/* clean tail at code bit 70 and above */
memset(code, 0, sizeof(code));
/* encode message */
hagelbarger_encode(message, code, 72);
hagelbarger_encode(message, code, 70);
/* decode */
hagelbarger_decode(code, message, 64);
printf("Decoded without corruption: %s (must be the same as above)\n", message);
/* corrupt data */
code[0] ^= 0xfc;
@ -22,7 +26,7 @@ int main(void)
/* decode */
hagelbarger_decode(code, message, 64);
printf("Decoded: %s (must be the same as above)\n", message);
printf("Decoded with corruption: %s (must be the same as above)\n", message);
return 0;
}