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:
parent
6c64025717
commit
0cbd9657d2
|
@ -25,6 +25,7 @@ libcommon_a_SOURCES = \
|
|||
fft.c \
|
||||
fm_modulation.c \
|
||||
ffsk.c \
|
||||
hagelbarger.c \
|
||||
sender.c \
|
||||
display_wave.c \
|
||||
display_status.c \
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -8,7 +8,6 @@ nmt_SOURCES = \
|
|||
countries.c \
|
||||
transaction.c \
|
||||
dsp.c \
|
||||
hagelbarger.c \
|
||||
frame.c \
|
||||
dms.c \
|
||||
sms.c \
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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 = \
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue