kopia lustrzana https://github.com/M17-Project/M17_Implementations
Porównaj commity
12 Commity
d582dbd14a
...
e71b3546cb
Autor | SHA1 | Data |
---|---|---|
Wojciech Kaczmarski | e71b3546cb | |
Wojciech Kaczmarski | 33c381ab9b | |
Wojciech Kaczmarski | b1c4b62f27 | |
Wojciech Kaczmarski | b2bfd472d5 | |
Wojciech Kaczmarski | c392be03b3 | |
Wojciech Kaczmarski | 5145711d92 | |
A. Maitland Bottoms | c4287118a9 | |
A. Maitland Bottoms | 6d2e3038d5 | |
A. Maitland Bottoms | 1832a8eda5 | |
Wojciech Kaczmarski | 1c6a39d679 | |
Wojciech Kaczmarski | 282f986994 | |
Wojciech Kaczmarski | 5cf820845d |
|
@ -4,3 +4,4 @@
|
|||
/SP5WWP/m17-packet/m17-packet-encode
|
||||
/SP5WWP/m17-packet/m17-packet-decode
|
||||
/SP5WWP/.vscode
|
||||
*.json
|
||||
|
|
|
@ -0,0 +1,151 @@
|
|||
//--------------------------------------------------------------------
|
||||
// M17 C library - m17.h
|
||||
//
|
||||
// Wojciech Kaczmarski, SP5WWP
|
||||
// M17 Project, 29 December 2023
|
||||
//--------------------------------------------------------------------
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
// M17 C library - lib/lib.c
|
||||
#define BSB_SPS 10 //samples per symbol
|
||||
#define FLT_SPAN 8 //baseband RRC filter span in symbols
|
||||
#define SYM_PER_SWD 8 //symbols per syncword
|
||||
#define SW_LEN (BSB_SPS*SYM_PER_SWD) //syncword detector length
|
||||
#define SYM_PER_PLD 184 //symbols per payload in a frame
|
||||
#define SYM_PER_FRA 192 //symbols per whole 40 ms frame
|
||||
#define RRC_DEV 7168.0f //.rrc file deviation for +1.0 symbol
|
||||
|
||||
//L2 metric threshold
|
||||
#define DIST_THRESH 2.0f //threshold for distance (syncword detection)
|
||||
|
||||
void send_preamble(float out[SYM_PER_FRA], uint32_t *cnt, const uint8_t type);
|
||||
void send_syncword(float out[SYM_PER_SWD], uint32_t *cnt, const uint16_t syncword);
|
||||
void send_data(float out[SYM_PER_PLD], uint32_t *cnt, const uint8_t* in);
|
||||
void send_eot(float out[SYM_PER_FRA], uint32_t *cnt);
|
||||
|
||||
// M17 C library - lib/payload/call.c
|
||||
#define CHAR_MAP " ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-/."
|
||||
|
||||
void decode_callsign_bytes(uint8_t *outp, const uint8_t inp[6]);
|
||||
void decode_callsign_value(uint8_t *outp, const uint64_t inp);
|
||||
int8_t encode_callsign_bytes(uint8_t out[6], const uint8_t *inp);
|
||||
int8_t encode_callsign_value(uint64_t *out, const uint8_t *inp);
|
||||
|
||||
// M17 C library - payload
|
||||
/**
|
||||
* @brief Structure holding Link Setup Frame data.
|
||||
*
|
||||
*/
|
||||
struct LSF
|
||||
{
|
||||
uint8_t dst[6];
|
||||
uint8_t src[6];
|
||||
uint8_t type[2];
|
||||
uint8_t meta[112/8];
|
||||
uint8_t crc[2];
|
||||
};
|
||||
|
||||
// M17 C library - lib/encode/convol.c
|
||||
extern const uint8_t puncture_pattern_1[61];
|
||||
extern const uint8_t puncture_pattern_2[12];
|
||||
extern const uint8_t puncture_pattern_3[8];
|
||||
|
||||
void conv_encode_stream_frame(uint8_t* out, const uint8_t* in, const uint16_t fn);
|
||||
void conv_encode_packet_frame(uint8_t* out, const uint8_t* in);
|
||||
void conv_encode_LSF(uint8_t* out, const struct LSF *in);
|
||||
|
||||
// M17 C library - lib/payload/crc.c
|
||||
//M17 CRC polynomial
|
||||
extern const uint16_t M17_CRC_POLY;
|
||||
|
||||
uint16_t CRC_M17(const uint8_t *in, const uint16_t len);
|
||||
uint16_t LSF_CRC(const struct LSF *in);
|
||||
|
||||
// M17 C library - lib/payload/lich.c
|
||||
void extract_LICH(uint8_t outp[6], const uint8_t cnt, const struct LSF *inp);
|
||||
|
||||
// M17 C library - lib/math/golay.c
|
||||
extern const uint16_t encode_matrix[12];
|
||||
extern const uint16_t decode_matrix[12];
|
||||
|
||||
uint32_t golay24_encode(const uint16_t data);
|
||||
uint16_t golay24_sdecode(const uint16_t codeword[24]);
|
||||
void decode_LICH(uint8_t outp[6], const uint16_t inp[96]);
|
||||
void encode_LICH(uint8_t outp[12], const uint8_t inp[6]);
|
||||
|
||||
// M17 C library - lib/phy/interleave.c
|
||||
//interleaver pattern
|
||||
extern const uint16_t intrl_seq[SYM_PER_PLD*2];
|
||||
|
||||
void reorder_bits(uint8_t outp[SYM_PER_PLD*2], const uint8_t inp[SYM_PER_PLD*2]);
|
||||
|
||||
// M17 C library - lib/math/math.c
|
||||
uint16_t q_abs_diff(const uint16_t v1, const uint16_t v2);
|
||||
float eucl_norm(const float* in1, const int8_t* in2, const uint8_t n);
|
||||
void int_to_soft(uint16_t* out, const uint16_t in, const uint8_t len);
|
||||
uint16_t soft_to_int(const uint16_t* in, const uint8_t len);
|
||||
uint16_t div16(const uint16_t a, const uint16_t b);
|
||||
uint16_t mul16(const uint16_t a, const uint16_t b);
|
||||
uint16_t soft_bit_XOR(const uint16_t a, const uint16_t b);
|
||||
void soft_XOR(uint16_t* out, const uint16_t* a, const uint16_t* b, const uint8_t len);
|
||||
|
||||
// M17 C library - lib/phy/randomize.c
|
||||
//randomizing pattern
|
||||
extern const uint8_t rand_seq[46];
|
||||
|
||||
void randomize_bits(uint8_t inp[SYM_PER_PLD*2]);
|
||||
|
||||
// M17 C library - lib/math/rrc.c
|
||||
//sample RRC filter for 48kHz sample rate
|
||||
//alpha=0.5, span=8, sps=10, gain=sqrt(sps)
|
||||
extern const float rrc_taps_10[8*10+1];
|
||||
|
||||
//sample RRC filter for 24kHz sample rate
|
||||
//alpha=0.5, span=8, sps=5, gain=sqrt(sps)
|
||||
extern const float rrc_taps_5[8*5+1];
|
||||
|
||||
// M17 C library - lib/encode/symbols.c
|
||||
// dibits-symbols map (TX)
|
||||
extern const int8_t symbol_map[4];
|
||||
extern const int8_t symbol_list[4];
|
||||
|
||||
// M17 C library - lib/phy/sync.c
|
||||
//syncwords
|
||||
extern const uint16_t SYNC_LSF;
|
||||
extern const uint16_t SYNC_STR;
|
||||
extern const uint16_t SYNC_PKT;
|
||||
extern const uint16_t SYNC_BER;
|
||||
extern const uint16_t EOT_MRKR;
|
||||
|
||||
// M17 C library - lib/decode/viterbi.c
|
||||
#define K 5 //constraint length
|
||||
#define NUM_STATES (1 << (K - 1)) //number of states
|
||||
|
||||
uint32_t viterbi_decode(uint8_t* out, const uint16_t* in, const uint16_t len);
|
||||
uint32_t viterbi_decode_punctured(uint8_t* out, const uint16_t* in, const uint8_t* punct, const uint16_t in_len, const uint16_t p_len);
|
||||
void viterbi_decode_bit(uint16_t s0, uint16_t s1, size_t pos);
|
||||
uint32_t viterbi_chainback(uint8_t* out, size_t pos, const uint16_t len);
|
||||
void viterbi_reset(void);
|
||||
|
||||
//End of Transmission symbol pattern
|
||||
extern const float eot_symbols[8];
|
||||
|
||||
// M17 C library - decode/symbols.c
|
||||
// syncword patterns (RX)
|
||||
// TODO: Compute those at runtime from the consts below
|
||||
extern const int8_t lsf_sync_symbols[8];
|
||||
extern const int8_t str_sync_symbols[8];
|
||||
extern const int8_t pkt_sync_symbols[8];
|
||||
|
||||
// symbol levels (RX)
|
||||
extern const float symbol_levels[4];
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -1,8 +1,8 @@
|
|||
INC = -I .
|
||||
INC = -I ../include
|
||||
|
||||
TARGET = libm17.so
|
||||
|
||||
CFLAGS = $(INC) -fPIC -Wall
|
||||
CFLAGS = $(INC) -fPIC -Wall -Wextra
|
||||
LDFLAGS = -shared -lm
|
||||
SRCS = $(wildcard *.c) $(wildcard */*.c)
|
||||
OBJS = $(SRCS:.c=.o)
|
||||
|
@ -15,6 +15,15 @@ clean:
|
|||
fclean:
|
||||
rm -f $(TARGET)
|
||||
|
||||
test:
|
||||
$(CC) $(CFLAGS) ../tests/unit_tests.c -o ../tests/unit_tests -lm -lunity -lm17
|
||||
|
||||
testrun:
|
||||
./../tests/unit_tests
|
||||
|
||||
install:
|
||||
sudo install $(TARGET) /usr/local/lib
|
||||
|
||||
$(TARGET): $(OBJS)
|
||||
$(CC) $(CFLAGS) $(OBJS) -o $@ $(LDFLAGS)
|
||||
|
||||
|
|
|
@ -2,4 +2,4 @@
|
|||
|
||||
### Compiling
|
||||
|
||||
To compile simply run `make`. This will generate a shared library `libm17.so`.
|
||||
To compile, simply run `make`. This will generate a shared library `libm17.so`.
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
// Wojciech Kaczmarski, SP5WWP
|
||||
// M17 Project, 29 December 2023
|
||||
//--------------------------------------------------------------------
|
||||
#include "symbols.h"
|
||||
#include <m17/m17.h>
|
||||
|
||||
// syncword patterns (RX)
|
||||
// TODO: Compute those at runtime from the consts below
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
//-------------------------------
|
||||
// M17 C library - decode/symbols.h
|
||||
//
|
||||
// Wojciech Kaczmarski, SP5WWP
|
||||
// M17 Project, 28 December 2023
|
||||
//-------------------------------
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
|
||||
// syncword patterns (RX)
|
||||
// TODO: Compute those at runtime from the consts below
|
||||
extern const int8_t lsf_sync_symbols[8];
|
||||
extern const int8_t str_sync_symbols[8];
|
||||
extern const int8_t pkt_sync_symbols[8];
|
||||
|
||||
// symbol levels (RX)
|
||||
extern const float symbol_levels[4];
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -10,8 +10,7 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <math/math.h>
|
||||
#include "viterbi.h"
|
||||
#include <m17/m17.h>
|
||||
|
||||
static uint32_t prevMetrics[NUM_STATES];
|
||||
static uint32_t currMetrics[NUM_STATES];
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
//--------------------------------------------------------------------
|
||||
// M17 C library - decode/viterbi.h
|
||||
//
|
||||
// Wojciech Kaczmarski, SP5WWP
|
||||
// M17 Project, 29 December 2023
|
||||
//--------------------------------------------------------------------
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
|
||||
#define K 5 //constraint length
|
||||
#define NUM_STATES (1 << (K - 1)) //number of states
|
||||
|
||||
uint32_t viterbi_decode(uint8_t* out, const uint16_t* in, const uint16_t len);
|
||||
uint32_t viterbi_decode_punctured(uint8_t* out, const uint16_t* in, const uint8_t* punct, const uint16_t in_len, const uint16_t p_len);
|
||||
void viterbi_decode_bit(uint16_t s0, uint16_t s1, size_t pos);
|
||||
uint32_t viterbi_chainback(uint8_t* out, size_t pos, const uint16_t len);
|
||||
void viterbi_reset(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -8,7 +8,7 @@
|
|||
// M17 Project, 29 December 2023
|
||||
//--------------------------------------------------------------------
|
||||
#include <string.h>
|
||||
#include "convol.h"
|
||||
#include <m17/m17.h>
|
||||
|
||||
const uint8_t puncture_pattern_1[61] = {
|
||||
1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
//--------------------------------------------------------------------
|
||||
// M17 C library - encode/convol.h
|
||||
//
|
||||
// Wojciech Kaczmarski, SP5WWP
|
||||
// M17 Project, 29 December 2023
|
||||
//--------------------------------------------------------------------
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
#include <payload/lsf.h>
|
||||
|
||||
extern const uint8_t puncture_pattern_1[61];
|
||||
extern const uint8_t puncture_pattern_2[12];
|
||||
extern const uint8_t puncture_pattern_3[8];
|
||||
|
||||
void conv_encode_stream_frame(uint8_t* out, const uint8_t* in, const uint16_t fn);
|
||||
void conv_encode_packet_frame(uint8_t* out, const uint8_t* in);
|
||||
void conv_encode_LSF(uint8_t* out, const struct LSF *in);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -2,9 +2,15 @@
|
|||
// M17 C library - encode/symbols.c
|
||||
//
|
||||
// Wojciech Kaczmarski, SP5WWP
|
||||
// M17 Project, 29 December 2023
|
||||
// M17 Project, 8 January 2024
|
||||
//--------------------------------------------------------------------
|
||||
#include "symbols.h"
|
||||
#include <m17/m17.h>
|
||||
|
||||
// dibits-symbols map (TX)
|
||||
//dibits-symbols map (TX)
|
||||
const int8_t symbol_map[4]={+1, +3, -1, -3};
|
||||
|
||||
//symbol list (RX)
|
||||
const int8_t symbol_list[4]={-3, -1, +1, +3};
|
||||
|
||||
//End of Transmission symbol pattern
|
||||
const float eot_symbols[8]={+3, +3, +3, +3, +3, +3, -3, +3};
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
//-------------------------------
|
||||
// M17 C library - encode/symbols.h
|
||||
//
|
||||
// Wojciech Kaczmarski, SP5WWP
|
||||
// M17 Project, 28 December 2023
|
||||
//-------------------------------
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
|
||||
// dibits-symbols map (TX)
|
||||
extern const int8_t symbol_map[4];
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -2,66 +2,79 @@
|
|||
// M17 C library - lib.c
|
||||
//
|
||||
// Wojciech Kaczmarski, SP5WWP
|
||||
// M17 Project, 29 December 2023
|
||||
// M17 Project, 5 January 2024
|
||||
//--------------------------------------------------------------------
|
||||
#include <stdio.h>
|
||||
#include <encode/symbols.h>
|
||||
#include "lib.h"
|
||||
#include <m17/m17.h>
|
||||
|
||||
//misc
|
||||
void send_preamble(const uint8_t type)
|
||||
/**
|
||||
* @brief Generate symbol stream for a preamble.
|
||||
*
|
||||
* @param out Frame buffer (192 floats)
|
||||
* @param cnt Pointer to a variable holding the number of written symbols.
|
||||
* @param type Preamble type (pre-BERT or pre-LSF).
|
||||
*/
|
||||
void send_preamble(float out[SYM_PER_FRA], uint32_t *cnt, const uint8_t type)
|
||||
{
|
||||
float symb;
|
||||
|
||||
if(type) //pre-BERT
|
||||
{
|
||||
for(uint16_t i=0; i<192/2; i++) //40ms * 4800 = 192
|
||||
for(uint16_t i=0; i<SYM_PER_FRA/2; i++) //40ms * 4800 = 192
|
||||
{
|
||||
symb=-3.0;
|
||||
fwrite((uint8_t*)&symb, sizeof(float), 1, stdout);
|
||||
symb=+3.0;
|
||||
fwrite((uint8_t*)&symb, sizeof(float), 1, stdout);
|
||||
out[(*cnt)++]=-3.0;
|
||||
out[(*cnt)++]=+3.0;
|
||||
}
|
||||
}
|
||||
else //pre-LSF
|
||||
{
|
||||
for(uint16_t i=0; i<192/2; i++) //40ms * 4800 = 192
|
||||
for(uint16_t i=0; i<SYM_PER_FRA/2; i++) //40ms * 4800 = 192
|
||||
{
|
||||
symb=+3.0;
|
||||
fwrite((uint8_t*)&symb, sizeof(float), 1, stdout);
|
||||
symb=-3.0;
|
||||
fwrite((uint8_t*)&symb, sizeof(float), 1, stdout);
|
||||
out[(*cnt)++]=+3.0;
|
||||
out[(*cnt)++]=-3.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void send_syncword(const uint16_t syncword)
|
||||
/**
|
||||
* @brief Generate symbol stream for a syncword.
|
||||
*
|
||||
* @param out Output buffer (8 floats).
|
||||
* @param cnt Pointer to a variable holding the number of written symbols.
|
||||
* @param syncword Syncword.
|
||||
*/
|
||||
void send_syncword(float out[SYM_PER_SWD], uint32_t *cnt, const uint16_t syncword)
|
||||
{
|
||||
float symb;
|
||||
|
||||
for(uint8_t i=0; i<16; i+=2)
|
||||
for(uint8_t i=0; i<SYM_PER_SWD*2; i+=2)
|
||||
{
|
||||
symb=symbol_map[(syncword>>(14-i))&3];
|
||||
fwrite((uint8_t*)&symb, sizeof(float), 1, stdout);
|
||||
out[(*cnt)++]=symbol_map[(syncword>>(14-i))&3];
|
||||
}
|
||||
}
|
||||
|
||||
//send the data (can be used for both LSF and frames)
|
||||
void send_data(const uint8_t* in)
|
||||
/**
|
||||
* @brief Generate symbol stream for frame contents (without syncword).
|
||||
* Can be used for both LSF and data frames.
|
||||
*
|
||||
* @param out Output buffer (184 floats).
|
||||
* @param cnt Pointer to a variable holding the number of written symbols.
|
||||
* @param in Data input.
|
||||
*/
|
||||
void send_data(float out[SYM_PER_PLD], uint32_t *cnt, const uint8_t* in)
|
||||
{
|
||||
float s=0.0;
|
||||
for(uint16_t i=0; i<SYM_PER_PLD; i++) //40ms * 4800 - 8 (syncword)
|
||||
{
|
||||
s=symbol_map[in[2*i]*2+in[2*i+1]];
|
||||
fwrite((uint8_t*)&s, sizeof(float), 1, stdout);
|
||||
out[(*cnt)++]=symbol_map[in[2*i]*2+in[2*i+1]];
|
||||
}
|
||||
}
|
||||
|
||||
void send_eot(void)
|
||||
/**
|
||||
* @brief Generate symbol stream for the End of Transmission marker.
|
||||
*
|
||||
* @param out Output buffer (192 floats).
|
||||
* @param cnt Pointer to a variable holding the number of written symbols.
|
||||
*/
|
||||
void send_eot(float out[SYM_PER_FRA], uint32_t *cnt)
|
||||
{
|
||||
float symb=+3.0;
|
||||
for(uint16_t i=0; i<192; i++) //40ms * 4800 = 192
|
||||
for(uint16_t i=0; i<SYM_PER_FRA; i++) //40ms * 4800 = 192
|
||||
{
|
||||
fwrite((uint8_t*)&symb, sizeof(float), 1, stdout);
|
||||
out[(*cnt)++]=eot_symbols[i%8];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,32 +0,0 @@
|
|||
//-------------------------------
|
||||
// M17 C library - lib.h
|
||||
//
|
||||
// Wojciech Kaczmarski, SP5WWP
|
||||
// M17 Project, 28 December 2023
|
||||
//-------------------------------
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
|
||||
#define BSB_SPS 10 //samples per symbol
|
||||
#define FLT_SPAN 8 //baseband RRC filter span in symbols
|
||||
#define SYM_PER_SWD 8 //symbols per syncword
|
||||
#define SW_LEN (BSB_SPS*SYM_PER_SWD) //syncword detector length
|
||||
#define SYM_PER_PLD 184 //symbols per payload in a frame
|
||||
#define SYM_PER_FRA 192 //symbols per whole 40 ms frame
|
||||
#define RRC_DEV 7168.0f //.rrc file deviation for +1.0 symbol
|
||||
|
||||
//L2 metric threshold
|
||||
#define DIST_THRESH 2.0f //threshold for distance (syncword detection)
|
||||
|
||||
void send_preamble(const uint8_t type);
|
||||
void send_syncword(const uint16_t syncword);
|
||||
void send_data(const uint8_t* in);
|
||||
void send_eot(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -11,8 +11,7 @@
|
|||
//--------------------------------------------------------------------
|
||||
#include <string.h>
|
||||
|
||||
#include <math/math.h>
|
||||
#include "golay.h"
|
||||
#include <m17/m17.h>
|
||||
|
||||
/**
|
||||
* @brief Precomputed encoding matrix for Golay(24, 12).
|
||||
|
@ -52,7 +51,7 @@ uint32_t golay24_encode(const uint16_t data)
|
|||
}
|
||||
}
|
||||
|
||||
return (data<<12) | checksum;
|
||||
return ((uint32_t)data<<12) | checksum;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -242,11 +241,11 @@ uint16_t golay24_sdecode(const uint16_t codeword[24])
|
|||
* @param outp An array of packed, decoded bits.
|
||||
* @param inp Pointer to an array of 96 soft bits.
|
||||
*/
|
||||
void decode_LICH(uint8_t* outp, const uint16_t* inp)
|
||||
void decode_LICH(uint8_t outp[6], const uint16_t inp[96])
|
||||
{
|
||||
uint16_t tmp;
|
||||
|
||||
memset(outp, 0, 5);
|
||||
//memset(outp, 0, 6);
|
||||
|
||||
tmp=golay24_sdecode(&inp[0]);
|
||||
outp[0]=(tmp>>4)&0xFF;
|
||||
|
@ -261,3 +260,25 @@ void decode_LICH(uint8_t* outp, const uint16_t* inp)
|
|||
outp[4]|=(tmp>>8)&0xF;
|
||||
outp[5]=tmp&0xFF;
|
||||
}
|
||||
|
||||
void encode_LICH(uint8_t outp[12], const uint8_t inp[6])
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
val=golay24_encode((inp[0]<<4)|(inp[1]>>4));
|
||||
outp[0]=(val>>16)&0xFF;
|
||||
outp[1]=(val>>8)&0xFF;
|
||||
outp[2]=(val>>0)&0xFF;
|
||||
val=golay24_encode(((inp[1]&0x0F)<<8)|inp[2]);
|
||||
outp[3]=(val>>16)&0xFF;
|
||||
outp[4]=(val>>8)&0xFF;
|
||||
outp[5]=(val>>0)&0xFF;
|
||||
val=golay24_encode((inp[3]<<4)|(inp[4]>>4));
|
||||
outp[6]=(val>>16)&0xFF;
|
||||
outp[7]=(val>>8)&0xFF;
|
||||
outp[8]=(val>>0)&0xFF;
|
||||
val=golay24_encode(((inp[4]&0x0F)<<8)|inp[5]);
|
||||
outp[9]=(val>>16)&0xFF;
|
||||
outp[10]=(val>>8)&0xFF;
|
||||
outp[11]=(val>>0)&0xFF;
|
||||
}
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
//--------------------------------------------------------------------
|
||||
// M17 C library - math/golay.h
|
||||
//
|
||||
// Wojciech Kaczmarski, SP5WWP
|
||||
// M17 Project, 29 December 2023
|
||||
//--------------------------------------------------------------------
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
|
||||
extern const uint16_t encode_matrix[12];
|
||||
extern const uint16_t decode_matrix[12];
|
||||
|
||||
uint32_t golay24_encode(const uint16_t data);
|
||||
uint16_t golay24_sdecode(const uint16_t codeword[24]);
|
||||
void decode_LICH(uint8_t* outp, const uint16_t* inp);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -11,7 +11,7 @@
|
|||
// M17 Project, 29 December 2023
|
||||
//--------------------------------------------------------------------
|
||||
#include <math.h>
|
||||
#include "math.h"
|
||||
#include <m17/m17.h>
|
||||
|
||||
/**
|
||||
* @brief Utility function returning the absolute value of a difference between
|
||||
|
@ -105,7 +105,10 @@ uint16_t add16(const uint16_t a, const uint16_t b)
|
|||
*/
|
||||
uint16_t sub16(const uint16_t a, const uint16_t b)
|
||||
{
|
||||
return a>=b ? a-b : 0x0000U;
|
||||
if(a>=b)
|
||||
return a-b;
|
||||
else
|
||||
return 0x0000U;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
//--------------------------------------------------------------------
|
||||
// M17 C library - math/math.h
|
||||
//
|
||||
// Wojciech Kaczmarski, SP5WWP
|
||||
// M17 Project, 29 December 2023
|
||||
//--------------------------------------------------------------------
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
|
||||
uint16_t q_abs_diff(const uint16_t v1, const uint16_t v2);
|
||||
float eucl_norm(const float* in1, const int8_t* in2, const uint8_t n);
|
||||
void int_to_soft(uint16_t* out, const uint16_t in, const uint8_t len);
|
||||
uint16_t soft_to_int(const uint16_t* in, const uint8_t len);
|
||||
uint16_t div16(const uint16_t a, const uint16_t b);
|
||||
uint16_t mul16(const uint16_t a, const uint16_t b);
|
||||
uint16_t soft_bit_XOR(const uint16_t a, const uint16_t b);
|
||||
void soft_XOR(uint16_t* out, const uint16_t* a, const uint16_t* b, const uint8_t len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -4,7 +4,7 @@
|
|||
// Wojciech Kaczmarski, SP5WWP
|
||||
// M17 Project, 29 December 2023
|
||||
//--------------------------------------------------------------------
|
||||
#include "rrc.h"
|
||||
#include <m17/m17.h>
|
||||
|
||||
//sample RRC filter for 48kHz sample rate
|
||||
//alpha=0.5, span=8, sps=10, gain=sqrt(sps)
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
//-------------------------------
|
||||
// M17 C library - math/rrc.h
|
||||
//
|
||||
// Wojciech Kaczmarski, SP5WWP
|
||||
// M17 Project, 28 December 2023
|
||||
//-------------------------------
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
//sample RRC filter for 48kHz sample rate
|
||||
//alpha=0.5, span=8, sps=10, gain=sqrt(sps)
|
||||
extern const float rrc_taps_10[8*10+1];
|
||||
|
||||
//sample RRC filter for 24kHz sample rate
|
||||
//alpha=0.5, span=8, sps=5, gain=sqrt(sps)
|
||||
extern const float rrc_taps_5[8*5+1];
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -2,30 +2,35 @@
|
|||
// M17 C library - payload/call.c
|
||||
//
|
||||
// This file contains:
|
||||
// - callsign encoder and decoders
|
||||
// - callsign encoders and decoders
|
||||
//
|
||||
// Wojciech Kaczmarski, SP5WWP
|
||||
// M17 Project, 29 December 2023
|
||||
//--------------------------------------------------------------------
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "call.h"
|
||||
#include <m17/m17.h>
|
||||
|
||||
//decodes a 6-byte long array to a callsign
|
||||
void decode_callsign_bytes(uint8_t *outp, const uint8_t *inp)
|
||||
/**
|
||||
* @brief Decode a 6-byte long array (little-endian) into callsign string.
|
||||
*
|
||||
* @param outp Decoded callsign string.
|
||||
* @param inp Pointer to a byte array holding the encoded value (little-endian).
|
||||
*/
|
||||
void decode_callsign_bytes(uint8_t *outp, const uint8_t inp[6])
|
||||
{
|
||||
uint64_t encoded=0;
|
||||
|
||||
//repack the data to a uint64_t
|
||||
for(uint8_t i=0; i<6; i++)
|
||||
encoded|=(uint64_t)inp[5-i]<<(8*i);
|
||||
encoded|=(uint64_t)inp[i]<<(8*i);
|
||||
|
||||
//check if the value is reserved (not a callsign)
|
||||
if(encoded>=262144000000000ULL)
|
||||
{
|
||||
if(encoded==0xFFFFFFFFFFFF) //broadcast
|
||||
if(encoded==0xFFFFFFFFFFFF) //"ALL"
|
||||
{
|
||||
sprintf((char*)outp, "#BCAST");
|
||||
sprintf((char*)outp, "ALL"); //'#' prefix needed here?
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -39,14 +44,19 @@ void decode_callsign_bytes(uint8_t *outp, const uint8_t *inp)
|
|||
uint8_t i=0;
|
||||
while(encoded>0)
|
||||
{
|
||||
outp[i]=" ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-/."[encoded%40];
|
||||
outp[i]=CHAR_MAP[encoded%40];
|
||||
encoded/=40;
|
||||
i++;
|
||||
}
|
||||
outp[i]=0;
|
||||
}
|
||||
|
||||
//decodes a 48-bit value to a callsign
|
||||
/**
|
||||
* @brief Decode a 48-bit value (stored as uint64_t) into callsign string.
|
||||
*
|
||||
* @param outp Decoded callsign string.
|
||||
* @param inp Encoded value.
|
||||
*/
|
||||
void decode_callsign_value(uint8_t *outp, const uint64_t inp)
|
||||
{
|
||||
uint64_t encoded=inp;
|
||||
|
@ -54,9 +64,9 @@ void decode_callsign_value(uint8_t *outp, const uint64_t inp)
|
|||
//check if the value is reserved (not a callsign)
|
||||
if(encoded>=262144000000000ULL)
|
||||
{
|
||||
if(encoded==0xFFFFFFFFFFFF) //broadcast
|
||||
if(encoded==0xFFFFFFFFFFFF) //"ALL"
|
||||
{
|
||||
sprintf((char*)outp, "#BCAST");
|
||||
sprintf((char*)outp, "ALL"); //'#' prefix needed here?
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -70,15 +80,21 @@ void decode_callsign_value(uint8_t *outp, const uint64_t inp)
|
|||
uint8_t i=0;
|
||||
while(encoded>0)
|
||||
{
|
||||
outp[i]=" ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-/."[encoded%40];
|
||||
outp[i]=CHAR_MAP[encoded%40];
|
||||
encoded/=40;
|
||||
i++;
|
||||
}
|
||||
outp[i]=0;
|
||||
}
|
||||
|
||||
//encode callsign into a 48-bit value
|
||||
uint8_t encode_callsign(uint64_t* out, const uint8_t* inp)
|
||||
/**
|
||||
* @brief Encode callsign string and store in a 6-byte array (little-endian)
|
||||
*
|
||||
* @param out Pointer to a byte array for the encoded value (little-endian).
|
||||
* @param inp Callsign string.
|
||||
* @return int8_t Return value, 0 -> OK.
|
||||
*/
|
||||
int8_t encode_callsign_bytes(uint8_t out[6], const uint8_t *inp)
|
||||
{
|
||||
//assert inp length
|
||||
if(strlen((const char*)inp)>9)
|
||||
|
@ -86,7 +102,51 @@ uint8_t encode_callsign(uint64_t* out, const uint8_t* inp)
|
|||
return -1;
|
||||
}
|
||||
|
||||
const uint8_t charMap[40]=" ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-/.";
|
||||
const uint8_t charMap[40]=CHAR_MAP;
|
||||
|
||||
uint64_t tmp=0;
|
||||
|
||||
if(strcmp((const char*)inp, "ALL")==0)
|
||||
{
|
||||
tmp=0xFFFFFFFFFFFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int8_t i=strlen((const char*)inp)-1; i>=0; i--)
|
||||
{
|
||||
for(uint8_t j=0; j<40; j++)
|
||||
{
|
||||
if(inp[i]==charMap[j])
|
||||
{
|
||||
tmp=tmp*40+j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(uint8_t i=0; i<6; i++)
|
||||
out[i]=(tmp>>(8*i))&0xFF;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Encode callsign string into a 48-bit value, stored as uint64_t.
|
||||
*
|
||||
* @param out Pointer to a uint64_t variable for the encoded value.
|
||||
* @param inp Callsign string.
|
||||
* @return int8_t Return value, 0 -> OK.
|
||||
*/
|
||||
int8_t encode_callsign_value(uint64_t *out, const uint8_t *inp)
|
||||
{
|
||||
//assert inp length
|
||||
if(strlen((const char*)inp)>9)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
const uint8_t charMap[40]=CHAR_MAP;
|
||||
|
||||
uint64_t tmp=0;
|
||||
|
||||
|
|
|
@ -1,20 +0,0 @@
|
|||
//--------------------------------------------------------------------
|
||||
// M17 C library - payload/call.h
|
||||
//
|
||||
// Wojciech Kaczmarski, SP5WWP
|
||||
// M17 Project, 29 December 2023
|
||||
//--------------------------------------------------------------------
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
|
||||
void decode_callsign_bytes(uint8_t *outp, const uint8_t *inp);
|
||||
void decode_callsign_value(uint8_t *outp, const uint64_t inp);
|
||||
uint8_t encode_callsign(uint64_t* out, const uint8_t* inp);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -8,7 +8,7 @@
|
|||
// M17 Project, 29 December 2023
|
||||
//--------------------------------------------------------------------
|
||||
#include <string.h>
|
||||
#include "crc.h"
|
||||
#include <m17/m17.h>
|
||||
|
||||
//M17 CRC polynomial
|
||||
const uint16_t M17_CRC_POLY = 0x5935;
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
//--------------------------------------------------------------------
|
||||
// M17 C library - payload/crc.h
|
||||
//
|
||||
// Wojciech Kaczmarski, SP5WWP
|
||||
// M17 Project, 29 December 2023
|
||||
//--------------------------------------------------------------------
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
#include "lsf.h"
|
||||
|
||||
//M17 CRC polynomial
|
||||
extern const uint16_t M17_CRC_POLY;
|
||||
|
||||
uint16_t CRC_M17(const uint8_t *in, const uint16_t len);
|
||||
uint16_t LSF_CRC(const struct LSF *in);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,78 @@
|
|||
//--------------------------------------------------------------------
|
||||
// M17 C library - payload/lich.c
|
||||
//
|
||||
// This file contains:
|
||||
// - Link Information CHannel (LICH) repacking functions
|
||||
//
|
||||
// Wojciech Kaczmarski, SP5WWP
|
||||
// M17 Project, 8 January 2024
|
||||
//--------------------------------------------------------------------
|
||||
#include <string.h>
|
||||
#include <m17/m17.h>
|
||||
|
||||
/**
|
||||
* @brief Extract LICH from the whole LSF.
|
||||
*
|
||||
* @param outp 6-byte array for the LICH.
|
||||
* @param cnt LICH counter (0 to 5)
|
||||
* @param inp Pointer to an LSF struct.
|
||||
*/
|
||||
void extract_LICH(uint8_t outp[6], const uint8_t cnt, const struct LSF *inp)
|
||||
{
|
||||
switch(cnt)
|
||||
{
|
||||
case 0:
|
||||
outp[0]=inp->dst[0];
|
||||
outp[1]=inp->dst[1];
|
||||
outp[2]=inp->dst[2];
|
||||
outp[3]=inp->dst[3];
|
||||
outp[4]=inp->dst[4];
|
||||
break;
|
||||
|
||||
case 1:
|
||||
outp[0]=inp->dst[5];
|
||||
outp[1]=inp->src[0];
|
||||
outp[2]=inp->src[1];
|
||||
outp[3]=inp->src[2];
|
||||
outp[4]=inp->src[3];
|
||||
break;
|
||||
|
||||
case 2:
|
||||
outp[0]=inp->src[4];
|
||||
outp[1]=inp->src[5];
|
||||
outp[2]=inp->type[0];
|
||||
outp[3]=inp->type[1];
|
||||
outp[4]=inp->meta[0];
|
||||
break;
|
||||
|
||||
case 3:
|
||||
outp[0]=inp->meta[1];
|
||||
outp[1]=inp->meta[2];
|
||||
outp[2]=inp->meta[3];
|
||||
outp[3]=inp->meta[4];
|
||||
outp[4]=inp->meta[5];
|
||||
break;
|
||||
|
||||
case 4:
|
||||
outp[0]=inp->meta[6];
|
||||
outp[1]=inp->meta[7];
|
||||
outp[2]=inp->meta[8];
|
||||
outp[3]=inp->meta[9];
|
||||
outp[4]=inp->meta[10];
|
||||
break;
|
||||
|
||||
case 5:
|
||||
outp[0]=inp->meta[11];
|
||||
outp[1]=inp->meta[12];
|
||||
outp[2]=inp->meta[13];
|
||||
outp[3]=inp->crc[0];
|
||||
outp[4]=inp->crc[1];
|
||||
break;
|
||||
|
||||
default:
|
||||
;
|
||||
break;
|
||||
}
|
||||
|
||||
outp[5]=cnt<<5;
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
//-------------------------------
|
||||
// M17 C library - payload/lsf.h
|
||||
//
|
||||
// Wojciech Kaczmarski, SP5WWP
|
||||
// M17 Project, 28 December 2023
|
||||
//-------------------------------
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Structure holding Link Setup Frame data.
|
||||
*
|
||||
*/
|
||||
struct LSF
|
||||
{
|
||||
uint8_t dst[6];
|
||||
uint8_t src[6];
|
||||
uint8_t type[2];
|
||||
uint8_t meta[112/8];
|
||||
uint8_t crc[2];
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -5,10 +5,10 @@
|
|||
// M17 Project, 28 December 2023
|
||||
//-------------------------------
|
||||
|
||||
#include "interleave.h"
|
||||
#include <m17/m17.h>
|
||||
|
||||
//interleaver pattern
|
||||
const uint16_t intrl_seq[368]=
|
||||
const uint16_t intrl_seq[SYM_PER_PLD*2]=
|
||||
{
|
||||
0, 137, 90, 227, 180, 317, 270, 39, 360, 129, 82, 219, 172, 309, 262, 31,
|
||||
352, 121, 74, 211, 164, 301, 254, 23, 344, 113, 66, 203, 156, 293, 246, 15,
|
||||
|
@ -34,3 +34,15 @@ const uint16_t intrl_seq[368]=
|
|||
32, 169, 122, 259, 212, 349, 302, 71, 24, 161, 114, 251, 204, 341, 294, 63,
|
||||
16, 153, 106, 243, 196, 333, 286, 55, 8, 145, 98, 235, 188, 325, 278, 47
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Reorder (interleave) unpacked payload bits.
|
||||
*
|
||||
* @param outp Reordered, unpacked type-4 bits.
|
||||
* @param inp Input unpacked type-2/3 bits.
|
||||
*/
|
||||
void reorder_bits(uint8_t outp[SYM_PER_PLD*2], const uint8_t inp[SYM_PER_PLD*2])
|
||||
{
|
||||
for(uint16_t i=0; i<SYM_PER_PLD*2; i++)
|
||||
outp[i]=inp[intrl_seq[i]];
|
||||
}
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
//-------------------------------
|
||||
// M17 C library - phy/interleave.h
|
||||
//
|
||||
// Wojciech Kaczmarski, SP5WWP
|
||||
// M17 Project, 28 December 2023
|
||||
//-------------------------------
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
|
||||
//interleaver pattern
|
||||
extern const uint16_t intrl_seq[368];
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -4,7 +4,7 @@
|
|||
// Wojciech Kaczmarski, SP5WWP
|
||||
// M17 Project, 29 December 2023
|
||||
//--------------------------------------------------------------------
|
||||
#include "randomize.h"
|
||||
#include <m17/m17.h>
|
||||
|
||||
//randomizing pattern
|
||||
const uint8_t rand_seq[46]=
|
||||
|
@ -12,3 +12,22 @@ const uint8_t rand_seq[46]=
|
|||
0xD6, 0xB5, 0xE2, 0x30, 0x82, 0xFF, 0x84, 0x62, 0xBA, 0x4E, 0x96, 0x90, 0xD8, 0x98, 0xDD, 0x5D, 0x0C, 0xC8, 0x52, 0x43, 0x91, 0x1D, 0xF8,
|
||||
0x6E, 0x68, 0x2F, 0x35, 0xDA, 0x14, 0xEA, 0xCD, 0x76, 0x19, 0x8D, 0xD5, 0x80, 0xD1, 0x33, 0x87, 0x13, 0x57, 0x18, 0x2D, 0x29, 0x78, 0xC3
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Randomize type-4 unpacked bits.
|
||||
*
|
||||
* @param inp Input 368 unpacked type-4 bits.
|
||||
*/
|
||||
void randomize_bits(uint8_t inp[SYM_PER_PLD*2])
|
||||
{
|
||||
for(uint16_t i=0; i<SYM_PER_PLD*2; i++)
|
||||
{
|
||||
if((rand_seq[i/8]>>(7-(i%8)))&1) //flip bit if '1'
|
||||
{
|
||||
if(inp[i])
|
||||
inp[i]=0;
|
||||
else
|
||||
inp[i]=1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
//-------------------------------
|
||||
// M17 C library - phy/randomize.h
|
||||
//
|
||||
// Wojciech Kaczmarski, SP5WWP
|
||||
// M17 Project, 28 December 2023
|
||||
//-------------------------------
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
|
||||
//randomizing pattern
|
||||
extern const uint8_t rand_seq[46];
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -4,7 +4,7 @@
|
|||
// Wojciech Kaczmarski, SP5WWP
|
||||
// M17 Project, 29 December 2023
|
||||
//--------------------------------------------------------------------
|
||||
#include "sync.h"
|
||||
#include <m17/m17.h>
|
||||
|
||||
//syncwords
|
||||
const uint16_t SYNC_LSF = 0x55F7;
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
//-------------------------------
|
||||
// M17 C library - phy/sync.h
|
||||
//
|
||||
// Wojciech Kaczmarski, SP5WWP
|
||||
// M17 Project, 28 December 2023
|
||||
//-------------------------------
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
|
||||
//syncwords
|
||||
extern const uint16_t SYNC_LSF;
|
||||
extern const uint16_t SYNC_STR;
|
||||
extern const uint16_t SYNC_PKT;
|
||||
extern const uint16_t SYNC_BER;
|
||||
extern const uint16_t EOT_MRKR;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -1,5 +1,5 @@
|
|||
m17-coder-sym: m17-coder-sym.c
|
||||
gcc -I ../lib -L ../lib -O2 -Wall m17-coder-sym.c -o m17-coder-sym -lm -lm17
|
||||
gcc -I ../include -L ../lib -O2 -Wall -Wextra m17-coder-sym.c -o m17-coder-sym -lm -lm17
|
||||
|
||||
clean:
|
||||
rm -f m17-coder-sym
|
||||
|
|
|
@ -4,14 +4,7 @@
|
|||
#include <string.h>
|
||||
|
||||
//libm17
|
||||
#include <lib.h>
|
||||
#include <encode/convol.h>
|
||||
#include <math/golay.h>
|
||||
#include <payload/crc.h>
|
||||
#include <payload/lsf.h>
|
||||
#include <phy/interleave.h>
|
||||
#include <phy/randomize.h>
|
||||
#include <phy/sync.h>
|
||||
#include <m17/m17.h>
|
||||
|
||||
//#define FN60_DEBUG
|
||||
|
||||
|
@ -22,6 +15,9 @@ uint8_t lich_encoded[12]; //96 bits packed, encoded LICH
|
|||
uint8_t enc_bits[SYM_PER_PLD*2]; //type-2 bits, unpacked
|
||||
uint8_t rf_bits[SYM_PER_PLD*2]; //type-4 bits, unpacked
|
||||
|
||||
float frame_buff[192];
|
||||
uint32_t frame_buff_cnt;
|
||||
|
||||
uint8_t data[16], next_data[16]; //raw payload, packed bits
|
||||
uint16_t fn=0; //16-bit Frame Number (for the stream mode)
|
||||
uint8_t lich_cnt=0; //0..5 LICH counter
|
||||
|
@ -66,84 +62,14 @@ int main(void)
|
|||
if(got_lsf) //stream frames
|
||||
{
|
||||
//send stream frame syncword
|
||||
send_syncword(SYNC_STR);
|
||||
frame_buff_cnt=0;
|
||||
send_syncword(frame_buff, &frame_buff_cnt, SYNC_STR);
|
||||
|
||||
//extract LICH from the whole LSF
|
||||
switch(lich_cnt)
|
||||
{
|
||||
case 0:
|
||||
lich[0]=lsf.dst[0];
|
||||
lich[1]=lsf.dst[1];
|
||||
lich[2]=lsf.dst[2];
|
||||
lich[3]=lsf.dst[3];
|
||||
lich[4]=lsf.dst[4];
|
||||
break;
|
||||
|
||||
case 1:
|
||||
lich[0]=lsf.dst[5];
|
||||
lich[1]=lsf.src[0];
|
||||
lich[2]=lsf.src[1];
|
||||
lich[3]=lsf.src[2];
|
||||
lich[4]=lsf.src[3];
|
||||
break;
|
||||
|
||||
case 2:
|
||||
lich[0]=lsf.src[4];
|
||||
lich[1]=lsf.src[5];
|
||||
lich[2]=lsf.type[0];
|
||||
lich[3]=lsf.type[1];
|
||||
lich[4]=lsf.meta[0];
|
||||
break;
|
||||
|
||||
case 3:
|
||||
lich[0]=lsf.meta[1];
|
||||
lich[1]=lsf.meta[2];
|
||||
lich[2]=lsf.meta[3];
|
||||
lich[3]=lsf.meta[4];
|
||||
lich[4]=lsf.meta[5];
|
||||
break;
|
||||
|
||||
case 4:
|
||||
lich[0]=lsf.meta[6];
|
||||
lich[1]=lsf.meta[7];
|
||||
lich[2]=lsf.meta[8];
|
||||
lich[3]=lsf.meta[9];
|
||||
lich[4]=lsf.meta[10];
|
||||
break;
|
||||
|
||||
case 5:
|
||||
lich[0]=lsf.meta[11];
|
||||
lich[1]=lsf.meta[12];
|
||||
lich[2]=lsf.meta[13];
|
||||
lich[3]=lsf.crc[0];
|
||||
lich[4]=lsf.crc[1];
|
||||
break;
|
||||
|
||||
default:
|
||||
;
|
||||
break;
|
||||
}
|
||||
lich[5]=lich_cnt<<5;
|
||||
extract_LICH(lich, lich_cnt, &lsf);
|
||||
|
||||
//encode the LICH
|
||||
uint32_t val;
|
||||
|
||||
val=golay24_encode((lich[0]<<4)|(lich[1]>>4));
|
||||
lich_encoded[0]=(val>>16)&0xFF;
|
||||
lich_encoded[1]=(val>>8)&0xFF;
|
||||
lich_encoded[2]=(val>>0)&0xFF;
|
||||
val=golay24_encode(((lich[1]&0x0F)<<8)|lich[2]);
|
||||
lich_encoded[3]=(val>>16)&0xFF;
|
||||
lich_encoded[4]=(val>>8)&0xFF;
|
||||
lich_encoded[5]=(val>>0)&0xFF;
|
||||
val=golay24_encode((lich[3]<<4)|(lich[4]>>4));
|
||||
lich_encoded[6]=(val>>16)&0xFF;
|
||||
lich_encoded[7]=(val>>8)&0xFF;
|
||||
lich_encoded[8]=(val>>0)&0xFF;
|
||||
val=golay24_encode(((lich[4]&0x0F)<<8)|lich[5]);
|
||||
lich_encoded[9]=(val>>16)&0xFF;
|
||||
lich_encoded[10]=(val>>8)&0xFF;
|
||||
lich_encoded[11]=(val>>0)&0xFF;
|
||||
encode_LICH(lich_encoded, lich);
|
||||
|
||||
//unpack LICH (12 bytes)
|
||||
memset(enc_bits, 0, SYM_PER_PLD*2);
|
||||
|
@ -157,20 +83,10 @@ int main(void)
|
|||
conv_encode_stream_frame(&enc_bits[96], data, finished ? (fn | 0x8000) : fn);
|
||||
|
||||
//reorder bits
|
||||
for(uint16_t i=0; i<SYM_PER_PLD*2; i++)
|
||||
rf_bits[i]=enc_bits[intrl_seq[i]];
|
||||
reorder_bits(rf_bits, enc_bits);
|
||||
|
||||
//randomize
|
||||
for(uint16_t i=0; i<SYM_PER_PLD*2; i++)
|
||||
{
|
||||
if((rand_seq[i/8]>>(7-(i%8)))&1) //flip bit if '1'
|
||||
{
|
||||
if(rf_bits[i])
|
||||
rf_bits[i]=0;
|
||||
else
|
||||
rf_bits[i]=1;
|
||||
}
|
||||
}
|
||||
randomize_bits(rf_bits);
|
||||
|
||||
//send dummy symbols (debug)
|
||||
/*float s=0.0;
|
||||
|
@ -178,7 +94,9 @@ int main(void)
|
|||
fwrite((uint8_t*)&s, sizeof(float), 1, stdout);*/
|
||||
|
||||
//send frame data
|
||||
send_data(rf_bits);
|
||||
frame_buff_cnt=0;
|
||||
send_data(frame_buff, &frame_buff_cnt, rf_bits);
|
||||
fwrite((uint8_t*)frame_buff, SYM_PER_FRA*sizeof(float), 1, stdout);
|
||||
|
||||
/*printf("\tDATA: ");
|
||||
for(uint8_t i=0; i<16; i++)
|
||||
|
@ -204,11 +122,15 @@ int main(void)
|
|||
//encode LSF data
|
||||
conv_encode_LSF(enc_bits, &lsf);
|
||||
|
||||
//send out the preamble and LSF
|
||||
send_preamble(0); //0 - LSF preamble, as opposed to 1 - BERT preamble
|
||||
//send out the preamble
|
||||
frame_buff_cnt=0;
|
||||
send_preamble(frame_buff, &frame_buff_cnt, 0); //0 - LSF preamble, as opposed to 1 - BERT preamble
|
||||
fwrite((uint8_t*)frame_buff, SYM_PER_FRA*sizeof(float), 1, stdout);
|
||||
|
||||
//send LSF syncword
|
||||
send_syncword(SYNC_LSF);
|
||||
frame_buff_cnt=0;
|
||||
send_syncword(frame_buff, &frame_buff_cnt, SYNC_LSF);
|
||||
fwrite((uint8_t*)frame_buff, SYM_PER_SWD*sizeof(float), 1, stdout);
|
||||
|
||||
//reorder bits
|
||||
for(uint16_t i=0; i<SYM_PER_PLD*2; i++)
|
||||
|
@ -227,7 +149,9 @@ int main(void)
|
|||
}
|
||||
|
||||
//send LSF data
|
||||
send_data(rf_bits);
|
||||
frame_buff_cnt=0;
|
||||
send_data(frame_buff, &frame_buff_cnt, rf_bits);
|
||||
fwrite((uint8_t*)frame_buff, SYM_PER_PLD*sizeof(float), 1, stdout);
|
||||
|
||||
//send dummy symbols (debug)
|
||||
/*float s=0.0;
|
||||
|
@ -253,7 +177,11 @@ int main(void)
|
|||
}
|
||||
|
||||
if(finished)
|
||||
send_eot();
|
||||
{
|
||||
frame_buff_cnt=0;
|
||||
send_eot(frame_buff, &frame_buff_cnt);
|
||||
fwrite((uint8_t*)frame_buff, SYM_PER_PLD*sizeof(float), 1, stdout);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
m17-decoder-sym: m17-decoder-sym.c
|
||||
gcc -I ../lib -L ../lib -Wall -O2 m17-decoder-sym.c -o m17-decoder-sym -lm -lm17
|
||||
gcc -I ../include -L ../lib -Wall -Wextra -O2 m17-decoder-sym.c -o m17-decoder-sym -lm -lm17
|
||||
|
||||
clean:
|
||||
rm -f m17-decoder-sym
|
||||
|
|
|
@ -4,18 +4,7 @@
|
|||
#include <string.h>
|
||||
|
||||
//libm17
|
||||
#include <lib.h>
|
||||
#include <decode/symbols.h>
|
||||
#include <decode/viterbi.h>
|
||||
#include <encode/convol.h>
|
||||
#include <encode/symbols.h>
|
||||
#include <math/golay.h>
|
||||
#include <math/math.h>
|
||||
#include <payload/call.h>
|
||||
#include <payload/crc.h>
|
||||
#include <phy/interleave.h>
|
||||
#include <phy/sync.h>
|
||||
#include <phy/randomize.h>
|
||||
#include <m17/m17.h>
|
||||
|
||||
#define DECODE_CALLSIGNS
|
||||
#define SHOW_VITERBI_ERRS
|
||||
|
@ -93,21 +82,21 @@ int main(void)
|
|||
for(uint8_t i=0; i<SYM_PER_PLD; i++)
|
||||
{
|
||||
//bit 0
|
||||
if(pld[i]>=symbol_map[3])
|
||||
if(pld[i]>=symbol_list[3])
|
||||
{
|
||||
soft_bit[i*2+1]=0xFFFF;
|
||||
}
|
||||
else if(pld[i]>=symbol_map[2])
|
||||
else if(pld[i]>=symbol_list[2])
|
||||
{
|
||||
soft_bit[i*2+1]=-(float)0xFFFF/(symbol_map[3]-symbol_map[2])*symbol_map[2]+pld[i]*(float)0xFFFF/(symbol_map[3]-symbol_map[2]);
|
||||
soft_bit[i*2+1]=-(float)0xFFFF/(symbol_list[3]-symbol_list[2])*symbol_list[2]+pld[i]*(float)0xFFFF/(symbol_list[3]-symbol_list[2]);
|
||||
}
|
||||
else if(pld[i]>=symbol_map[1])
|
||||
else if(pld[i]>=symbol_list[1])
|
||||
{
|
||||
soft_bit[i*2+1]=0x0000;
|
||||
}
|
||||
else if(pld[i]>=symbol_map[0])
|
||||
else if(pld[i]>=symbol_list[0])
|
||||
{
|
||||
soft_bit[i*2+1]=(float)0xFFFF/(symbol_map[1]-symbol_map[0])*symbol_map[1]-pld[i]*(float)0xFFFF/(symbol_map[1]-symbol_map[0]);
|
||||
soft_bit[i*2+1]=(float)0xFFFF/(symbol_list[1]-symbol_list[0])*symbol_list[1]-pld[i]*(float)0xFFFF/(symbol_list[1]-symbol_list[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -115,13 +104,13 @@ int main(void)
|
|||
}
|
||||
|
||||
//bit 1
|
||||
if(pld[i]>=symbol_map[2])
|
||||
if(pld[i]>=symbol_list[2])
|
||||
{
|
||||
soft_bit[i*2]=0x0000;
|
||||
}
|
||||
else if(pld[i]>=symbol_map[1])
|
||||
else if(pld[i]>=symbol_list[1])
|
||||
{
|
||||
soft_bit[i*2]=0x7FFF-pld[i]*(float)0xFFFF/(symbol_map[2]-symbol_map[1]);
|
||||
soft_bit[i*2]=0x7FFF-pld[i]*(float)0xFFFF/(symbol_list[2]-symbol_list[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
all: m17-packet-encode m17-packet-decode
|
||||
|
||||
m17-packet-encode: m17-packet-encode.c
|
||||
gcc -I ../lib -L ../lib -O2 -Wall m17-packet-encode.c -o m17-packet-encode -lm -lm17
|
||||
gcc -I ../include -L ../lib -O2 -Wall -Wextra m17-packet-encode.c -o m17-packet-encode -lm -lm17
|
||||
|
||||
m17-packet-decode: m17-packet-decode.c
|
||||
gcc -I ../lib -L ../lib -O2 -Wall m17-packet-decode.c -o m17-packet-decode -lm -lm17
|
||||
gcc -I ../include -L ../lib -O2 -Wall -Wextra m17-packet-decode.c -o m17-packet-decode -lm -lm17
|
||||
|
||||
install: all
|
||||
sudo install m17-packet-encode /usr/local/bin
|
||||
|
|
|
@ -4,18 +4,7 @@
|
|||
#include <string.h>
|
||||
|
||||
//libm17
|
||||
#include <lib.h>
|
||||
#include <decode/symbols.h>
|
||||
#include <decode/viterbi.h>
|
||||
#include <encode/convol.h>
|
||||
#include <encode/symbols.h>
|
||||
#include <math/golay.h>
|
||||
#include <math/math.h>
|
||||
#include <payload/call.h>
|
||||
#include <payload/crc.h>
|
||||
#include <phy/interleave.h>
|
||||
#include <phy/sync.h>
|
||||
#include <phy/randomize.h>
|
||||
#include <m17/m17.h>
|
||||
|
||||
float sample; //last raw sample from the stdin
|
||||
float last[8]; //look-back buffer for finding syncwords
|
||||
|
@ -135,21 +124,21 @@ int main(int argc, char* argv[])
|
|||
for(uint8_t i=0; i<SYM_PER_PLD; i++)
|
||||
{
|
||||
//bit 0
|
||||
if(pld[i]>=symbol_map[3])
|
||||
if(pld[i]>=symbol_list[3])
|
||||
{
|
||||
soft_bit[i*2+1]=0xFFFF;
|
||||
}
|
||||
else if(pld[i]>=symbol_map[2])
|
||||
else if(pld[i]>=symbol_list[2])
|
||||
{
|
||||
soft_bit[i*2+1]=-(float)0xFFFF/(symbol_map[3]-symbol_map[2])*symbol_map[2]+pld[i]*(float)0xFFFF/(symbol_map[3]-symbol_map[2]);
|
||||
soft_bit[i*2+1]=-(float)0xFFFF/(symbol_list[3]-symbol_list[2])*symbol_list[2]+pld[i]*(float)0xFFFF/(symbol_list[3]-symbol_list[2]);
|
||||
}
|
||||
else if(pld[i]>=symbol_map[1])
|
||||
else if(pld[i]>=symbol_list[1])
|
||||
{
|
||||
soft_bit[i*2+1]=0x0000;
|
||||
}
|
||||
else if(pld[i]>=symbol_map[0])
|
||||
else if(pld[i]>=symbol_list[0])
|
||||
{
|
||||
soft_bit[i*2+1]=(float)0xFFFF/(symbol_map[1]-symbol_map[0])*symbol_map[1]-pld[i]*(float)0xFFFF/(symbol_map[1]-symbol_map[0]);
|
||||
soft_bit[i*2+1]=(float)0xFFFF/(symbol_list[1]-symbol_list[0])*symbol_list[1]-pld[i]*(float)0xFFFF/(symbol_list[1]-symbol_list[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -157,13 +146,13 @@ int main(int argc, char* argv[])
|
|||
}
|
||||
|
||||
//bit 1
|
||||
if(pld[i]>=symbol_map[2])
|
||||
if(pld[i]>=symbol_list[2])
|
||||
{
|
||||
soft_bit[i*2]=0x0000;
|
||||
}
|
||||
else if(pld[i]>=symbol_map[1])
|
||||
else if(pld[i]>=symbol_list[1])
|
||||
{
|
||||
soft_bit[i*2]=0x7FFF-pld[i]*(float)0xFFFF/(symbol_map[2]-symbol_map[1]);
|
||||
soft_bit[i*2]=0x7FFF-pld[i]*(float)0xFFFF/(symbol_list[2]-symbol_list[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -5,17 +5,7 @@
|
|||
#include <math.h>
|
||||
|
||||
//libm17
|
||||
#include <lib.h>
|
||||
#include <encode/convol.h>
|
||||
#include <encode/symbols.h>
|
||||
#include <math/golay.h>
|
||||
#include <math/rrc.h>
|
||||
#include <payload/call.h>
|
||||
#include <payload/crc.h>
|
||||
#include <payload/lsf.h>
|
||||
#include <phy/interleave.h>
|
||||
#include <phy/randomize.h>
|
||||
#include <phy/sync.h>
|
||||
#include <m17/m17.h>
|
||||
|
||||
#define FLT_LEN (BSB_SPS*FLT_SPAN+1) //for 48kHz sample rate this is 81
|
||||
|
||||
|
@ -217,8 +207,8 @@ int main(int argc, char* argv[])
|
|||
//encode dst, src for the lsf struct
|
||||
uint64_t dst_encoded=0, src_encoded=0;
|
||||
uint16_t type=0;
|
||||
encode_callsign(&dst_encoded, dst_raw);
|
||||
encode_callsign(&src_encoded, src_raw);
|
||||
encode_callsign_value(&dst_encoded, dst_raw);
|
||||
encode_callsign_value(&src_encoded, src_raw);
|
||||
for(int8_t i=5; i>=0; i--)
|
||||
{
|
||||
lsf.dst[5-i]=(dst_encoded>>(i*8))&0xFF;
|
||||
|
@ -232,7 +222,7 @@ int main(int argc, char* argv[])
|
|||
//fprintf(stderr, "DST: %02X %02X %02X %02X %02X %02X\n", lsf.dst[0], lsf.dst[1], lsf.dst[2], lsf.dst[3], lsf.dst[4], lsf.dst[5]);
|
||||
//fprintf(stderr, "SRC: %02X %02X %02X %02X %02X %02X\n", lsf.src[0], lsf.src[1], lsf.src[2], lsf.src[3], lsf.src[4], lsf.src[5]);
|
||||
fprintf(stderr, "Data CRC:\t%04hX\n", packet_crc);
|
||||
type=((uint16_t)0b01<<1)|((uint16_t)can<<7); //packet mode, content: data
|
||||
type=((uint16_t)0x01<<1)|((uint16_t)can<<7); //packet mode, content: data
|
||||
lsf.type[0]=(uint16_t)type>>8;
|
||||
lsf.type[1]=(uint16_t)type&0xFF;
|
||||
memset(&lsf.meta, 0, 112/8);
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
unit_tests
|
|
@ -0,0 +1,614 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
#include <unity/unity.h>
|
||||
#include <m17/m17.h>
|
||||
|
||||
//this is run before every test
|
||||
void setUp(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//this is run after every test
|
||||
void tearDown(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void soft_logic_xor(void)
|
||||
{
|
||||
TEST_ASSERT_EQUAL(0x0000, soft_bit_XOR(0x0000, 0x0000));
|
||||
TEST_ASSERT_EQUAL(0x7FFE, soft_bit_XOR(0x0000, 0x7FFF)); //off by 1 is acceptable
|
||||
TEST_ASSERT_EQUAL(0xFFFE, soft_bit_XOR(0x0000, 0xFFFF)); //off by 1 is acceptable
|
||||
|
||||
TEST_ASSERT_EQUAL(0x7FFE, soft_bit_XOR(0x7FFF, 0x0000)); //off by 1 is acceptable
|
||||
TEST_ASSERT_EQUAL(0x7FFE, soft_bit_XOR(0x7FFF, 0x7FFF));
|
||||
TEST_ASSERT_EQUAL(0x7FFF, soft_bit_XOR(0x7FFF, 0xFFFF));
|
||||
|
||||
TEST_ASSERT_EQUAL(0xFFFE, soft_bit_XOR(0xFFFF, 0x0000)); //off by 1 is acceptable
|
||||
TEST_ASSERT_EQUAL(0x7FFF, soft_bit_XOR(0xFFFF, 0x7FFF));
|
||||
TEST_ASSERT_EQUAL(0x0000, soft_bit_XOR(0xFFFF, 0xFFFF));
|
||||
}
|
||||
|
||||
void symbol_to_soft_dibit(uint16_t dibit[2], float symb_in)
|
||||
{
|
||||
//bit 0
|
||||
if(symb_in>=symbol_list[3])
|
||||
{
|
||||
dibit[1]=0xFFFF;
|
||||
}
|
||||
else if(symb_in>=symbol_list[2])
|
||||
{
|
||||
dibit[1]=-(float)0xFFFF/(symbol_list[3]-symbol_list[2])*symbol_list[2]+symb_in*(float)0xFFFF/(symbol_list[3]-symbol_list[2]);
|
||||
}
|
||||
else if(symb_in>=symbol_list[1])
|
||||
{
|
||||
dibit[1]=0x0000;
|
||||
}
|
||||
else if(symb_in>=symbol_list[0])
|
||||
{
|
||||
dibit[1]=(float)0xFFFF/(symbol_list[1]-symbol_list[0])*symbol_list[1]-symb_in*(float)0xFFFF/(symbol_list[1]-symbol_list[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
dibit[1]=0xFFFF;
|
||||
}
|
||||
|
||||
//bit 1
|
||||
if(symb_in>=symbol_list[2])
|
||||
{
|
||||
dibit[0]=0x0000;
|
||||
}
|
||||
else if(symb_in>=symbol_list[1])
|
||||
{
|
||||
dibit[0]=0x7FFF-symb_in*(float)0xFFFF/(symbol_list[2]-symbol_list[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
dibit[0]=0xFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
void symbol_to_dibit(void)
|
||||
{
|
||||
uint16_t dibit[2];
|
||||
|
||||
symbol_to_soft_dibit(dibit, +30.0);
|
||||
TEST_ASSERT_EQUAL(0x0000, dibit[0]);
|
||||
TEST_ASSERT_EQUAL(0xFFFF, dibit[1]); //this is the LSB...
|
||||
|
||||
symbol_to_soft_dibit(dibit, +4.0);
|
||||
TEST_ASSERT_EQUAL(0x0000, dibit[0]);
|
||||
TEST_ASSERT_EQUAL(0xFFFF, dibit[1]);
|
||||
|
||||
symbol_to_soft_dibit(dibit, +3.0);
|
||||
TEST_ASSERT_EQUAL(0x0000, dibit[0]);
|
||||
TEST_ASSERT_EQUAL(0xFFFF, dibit[1]);
|
||||
|
||||
symbol_to_soft_dibit(dibit, +2.0);
|
||||
TEST_ASSERT_EQUAL(0x0000, dibit[0]);
|
||||
TEST_ASSERT_EQUAL(0x7FFF, dibit[1]);
|
||||
|
||||
symbol_to_soft_dibit(dibit, +1.0);
|
||||
TEST_ASSERT_EQUAL(0x0000, dibit[0]);
|
||||
TEST_ASSERT_EQUAL(0x0000, dibit[1]);
|
||||
|
||||
symbol_to_soft_dibit(dibit, 0.0);
|
||||
TEST_ASSERT_EQUAL(0x7FFF, dibit[0]);
|
||||
TEST_ASSERT_EQUAL(0x0000, dibit[1]);
|
||||
|
||||
symbol_to_soft_dibit(dibit, -1.0);
|
||||
TEST_ASSERT_EQUAL(0xFFFE, dibit[0]); //off by one is acceptable
|
||||
TEST_ASSERT_EQUAL(0x0000, dibit[1]);
|
||||
|
||||
symbol_to_soft_dibit(dibit, -2.0);
|
||||
TEST_ASSERT_EQUAL(0xFFFF, dibit[0]);
|
||||
TEST_ASSERT_EQUAL(0x7FFF, dibit[1]);
|
||||
|
||||
symbol_to_soft_dibit(dibit, -3.0);
|
||||
TEST_ASSERT_EQUAL(0xFFFF, dibit[0]);
|
||||
TEST_ASSERT_EQUAL(0xFFFF, dibit[1]);
|
||||
|
||||
symbol_to_soft_dibit(dibit, -4.0);
|
||||
TEST_ASSERT_EQUAL(0xFFFF, dibit[0]);
|
||||
TEST_ASSERT_EQUAL(0xFFFF, dibit[1]);
|
||||
|
||||
symbol_to_soft_dibit(dibit, -30.0);
|
||||
TEST_ASSERT_EQUAL(0xFFFF, dibit[0]);
|
||||
TEST_ASSERT_EQUAL(0xFFFF, dibit[1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Apply errors to a soft-valued 24-bit logic vector.
|
||||
* Errors are spread out evenly among num_errs bits.
|
||||
* @param vect Input vector.
|
||||
* @param start_pos
|
||||
* @param end_pos
|
||||
* @param num_errs Number of bits to apply errors to.
|
||||
* @param sum_errs Sum of all errors (total).
|
||||
*/
|
||||
void apply_errors(uint16_t vect[24], uint8_t start_pos, uint8_t end_pos, uint8_t num_errs, float sum_errs)
|
||||
{
|
||||
if(end_pos<start_pos)
|
||||
{
|
||||
printf("ERROR: Invalid bit range.\nExiting.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uint8_t bit_pos;
|
||||
uint8_t num_bits=end_pos-start_pos+1;
|
||||
|
||||
if(num_errs>num_bits || num_bits>24 || num_errs>24 || sum_errs>num_errs) //too many errors or too wide range
|
||||
{
|
||||
printf("ERROR: Impossible combination of error value and number of bits.\nExiting.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uint16_t val=roundf((float)0xFFFF*sum_errs/num_errs);
|
||||
uint32_t err_loc=0;
|
||||
|
||||
for(uint8_t i=0; i<num_errs; i++)
|
||||
{
|
||||
//assure we didnt select the same bit more than once
|
||||
do
|
||||
{
|
||||
bit_pos=start_pos+(rand()%num_bits);
|
||||
}
|
||||
while(err_loc&(1<<bit_pos));
|
||||
|
||||
vect[bit_pos]^=val; //apply error
|
||||
err_loc|=(1<<bit_pos);
|
||||
}
|
||||
}
|
||||
|
||||
void golay_encode(void)
|
||||
{
|
||||
uint16_t data=0x0800;
|
||||
|
||||
//single-bit data
|
||||
for(uint8_t i=sizeof(encode_matrix)/sizeof(uint16_t)-1; i>0; i--)
|
||||
{
|
||||
TEST_ASSERT_EQUAL(((uint32_t)data<<12)|encode_matrix[i], golay24_encode(data));
|
||||
data>>=1;
|
||||
}
|
||||
|
||||
//test data vector
|
||||
data=0x0D78;
|
||||
TEST_ASSERT_EQUAL(0x0D7880FU, golay24_encode(data));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Golay soft-decode one known codeword.
|
||||
*
|
||||
*/
|
||||
void golay_soft_decode_clean(void)
|
||||
{
|
||||
uint16_t vector[24];
|
||||
|
||||
//clean D78|80F
|
||||
for(uint8_t i=0; i<24; i++)
|
||||
vector[23-i]=((0x0D7880F>>i)&1)*0xFFFF;
|
||||
|
||||
TEST_ASSERT_EQUAL(0x0D78, golay24_sdecode(vector));
|
||||
}
|
||||
|
||||
void golay_soft_decode_flipped_parity_1(void)
|
||||
{
|
||||
uint16_t vector[24]; //soft-logic 24-bit vector
|
||||
|
||||
//clean D78|80F to soft-logic data
|
||||
for(uint8_t i=0; i<24; i++)
|
||||
vector[23-i]=((0x0D7880F>>i)&1)*0xFFFF;
|
||||
|
||||
for(uint16_t j=0; j<1000; j++)
|
||||
{
|
||||
apply_errors(vector, 0, 11, 1, 1.0);
|
||||
TEST_ASSERT_EQUAL(0x0D78, golay24_sdecode(vector));
|
||||
for(uint8_t i=0; i<24; i++)
|
||||
vector[23-i]=((0x0D7880F>>i)&1)*0xFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
void golay_soft_decode_erased_parity_1(void)
|
||||
{
|
||||
uint16_t vector[24]; //soft-logic 24-bit vector
|
||||
|
||||
//clean D78|80F to soft-logic data
|
||||
for(uint8_t i=0; i<24; i++)
|
||||
vector[23-i]=((0x0D7880F>>i)&1)*0xFFFF;
|
||||
|
||||
for(uint16_t j=0; j<1000; j++)
|
||||
{
|
||||
apply_errors(vector, 0, 11, 1, 0.5);
|
||||
TEST_ASSERT_EQUAL(0x0D78, golay24_sdecode(vector));
|
||||
for(uint8_t i=0; i<24; i++)
|
||||
vector[23-i]=((0x0D7880F>>i)&1)*0xFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
void golay_soft_decode_flipped_parity_2(void)
|
||||
{
|
||||
uint16_t vector[24]; //soft-logic 24-bit vector
|
||||
|
||||
//clean D78|80F to soft-logic data
|
||||
for(uint8_t i=0; i<24; i++)
|
||||
vector[23-i]=((0x0D7880F>>i)&1)*0xFFFF;
|
||||
|
||||
for(uint16_t j=0; j<1000; j++)
|
||||
{
|
||||
apply_errors(vector, 0, 11, 2, 2.0);
|
||||
TEST_ASSERT_EQUAL(0x0D78, golay24_sdecode(vector));
|
||||
for(uint8_t i=0; i<24; i++)
|
||||
vector[23-i]=((0x0D7880F>>i)&1)*0xFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
void golay_soft_decode_erased_parity_2(void)
|
||||
{
|
||||
uint16_t vector[24]; //soft-logic 24-bit vector
|
||||
|
||||
//clean D78|80F to soft-logic data
|
||||
for(uint8_t i=0; i<24; i++)
|
||||
vector[23-i]=((0x0D7880F>>i)&1)*0xFFFF;
|
||||
|
||||
for(uint16_t j=0; j<1000; j++)
|
||||
{
|
||||
apply_errors(vector, 0, 11, 2, 1.0);
|
||||
TEST_ASSERT_EQUAL(0x0D78, golay24_sdecode(vector));
|
||||
for(uint8_t i=0; i<24; i++)
|
||||
vector[23-i]=((0x0D7880F>>i)&1)*0xFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
void golay_soft_decode_flipped_parity_3(void)
|
||||
{
|
||||
uint16_t vector[24]; //soft-logic 24-bit vector
|
||||
|
||||
//clean D78|80F to soft-logic data
|
||||
for(uint8_t i=0; i<24; i++)
|
||||
vector[23-i]=((0x0D7880F>>i)&1)*0xFFFF;
|
||||
|
||||
for(uint16_t j=0; j<1000; j++)
|
||||
{
|
||||
apply_errors(vector, 0, 11, 3, 3.0);
|
||||
TEST_ASSERT_EQUAL(0x0D78, golay24_sdecode(vector));
|
||||
for(uint8_t i=0; i<24; i++)
|
||||
vector[23-i]=((0x0D7880F>>i)&1)*0xFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
void golay_soft_decode_erased_parity_3(void)
|
||||
{
|
||||
uint16_t vector[24]; //soft-logic 24-bit vector
|
||||
|
||||
//clean D78|80F to soft-logic data
|
||||
for(uint8_t i=0; i<24; i++)
|
||||
vector[23-i]=((0x0D7880F>>i)&1)*0xFFFF;
|
||||
|
||||
for(uint16_t j=0; j<1000; j++)
|
||||
{
|
||||
apply_errors(vector, 0, 11, 3, 1.5);
|
||||
TEST_ASSERT_EQUAL(0x0D78, golay24_sdecode(vector));
|
||||
for(uint8_t i=0; i<24; i++)
|
||||
vector[23-i]=((0x0D7880F>>i)&1)*0xFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
void golay_soft_decode_erased_parity_3_5(void)
|
||||
{
|
||||
uint16_t vector[24]; //soft-logic 24-bit vector
|
||||
|
||||
//clean D78|80F to soft-logic data
|
||||
for(uint8_t i=0; i<24; i++)
|
||||
vector[23-i]=((0x0D7880F>>i)&1)*0xFFFF;
|
||||
|
||||
for(uint16_t j=0; j<1000; j++)
|
||||
{
|
||||
apply_errors(vector, 0, 11, 7, 3.5);
|
||||
TEST_ASSERT_NOT_EQUAL(0x0D78, golay24_sdecode(vector));
|
||||
for(uint8_t i=0; i<24; i++)
|
||||
vector[23-i]=((0x0D7880F>>i)&1)*0xFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
//4 errors is exactly half the hamming distance, so due to rounding etc., results may vary
|
||||
//therefore we run 2 tests here to prove that
|
||||
void golay_soft_decode_flipped_parity_4(void)
|
||||
{
|
||||
uint16_t vector[24]; //soft-logic 24-bit vector
|
||||
|
||||
//clean D78|80F to soft-logic data
|
||||
for(uint8_t i=0; i<24; i++)
|
||||
vector[23-i]=((0x0D7880F>>i)&1)*0xFFFF;
|
||||
|
||||
vector[6]^=0xFFFF;
|
||||
vector[7]^=0xFFFF;
|
||||
vector[8]^=0xFFFF;
|
||||
vector[11]^=0xFFFF;
|
||||
TEST_ASSERT_NOT_EQUAL(0x0D78, golay24_sdecode(vector));
|
||||
for(uint8_t i=0; i<24; i++)
|
||||
vector[23-i]=((0x0D7880F>>i)&1)*0xFFFF;
|
||||
|
||||
vector[6]^=0xFFFF;
|
||||
vector[7]^=0xFFFF;
|
||||
vector[8]^=0xFFFF;
|
||||
vector[9]^=0xFFFF;
|
||||
TEST_ASSERT_EQUAL(0x0D78, golay24_sdecode(vector));
|
||||
for(uint8_t i=0; i<24; i++)
|
||||
vector[23-i]=((0x0D7880F>>i)&1)*0xFFFF;
|
||||
}
|
||||
|
||||
void golay_soft_decode_erased_parity_5(void)
|
||||
{
|
||||
uint16_t vector[24]; //soft-logic 24-bit vector
|
||||
|
||||
//clean D78|80F to soft-logic data
|
||||
for(uint8_t i=0; i<24; i++)
|
||||
vector[23-i]=((0x0D7880F>>i)&1)*0xFFFF;
|
||||
|
||||
for(uint16_t j=0; j<1000; j++)
|
||||
{
|
||||
apply_errors(vector, 0, 11, 5, 2.5);
|
||||
TEST_ASSERT_NOT_EQUAL(0x0D78, golay24_sdecode(vector));
|
||||
for(uint8_t i=0; i<24; i++)
|
||||
vector[23-i]=((0x0D7880F>>i)&1)*0xFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
void golay_soft_decode_flipped_parity_5(void)
|
||||
{
|
||||
uint16_t vector[24]; //soft-logic 24-bit vector
|
||||
|
||||
//clean D78|80F to soft-logic data
|
||||
for(uint8_t i=0; i<24; i++)
|
||||
vector[23-i]=((0x0D7880F>>i)&1)*0xFFFF;
|
||||
|
||||
for(uint16_t j=0; j<1000; j++)
|
||||
{
|
||||
apply_errors(vector, 0, 11, 5, 5.0);
|
||||
TEST_ASSERT_NOT_EQUAL(0x0D78, golay24_sdecode(vector));
|
||||
for(uint8_t i=0; i<24; i++)
|
||||
vector[23-i]=((0x0D7880F>>i)&1)*0xFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
void golay_soft_decode_flipped_data_1(void)
|
||||
{
|
||||
uint16_t vector[24]; //soft-logic 24-bit vector
|
||||
|
||||
//clean D78|80F to soft-logic data
|
||||
for(uint8_t i=0; i<24; i++)
|
||||
vector[23-i]=((0x0D7880F>>i)&1)*0xFFFF;
|
||||
|
||||
for(uint16_t j=0; j<1000; j++)
|
||||
{
|
||||
apply_errors(vector, 12, 23, 1, 1.0);
|
||||
TEST_ASSERT_EQUAL(0x0D78, golay24_sdecode(vector));
|
||||
for(uint8_t i=0; i<24; i++)
|
||||
vector[23-i]=((0x0D7880F>>i)&1)*0xFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
void golay_soft_decode_erased_data_1(void)
|
||||
{
|
||||
uint16_t vector[24]; //soft-logic 24-bit vector
|
||||
|
||||
//clean D78|80F to soft-logic data
|
||||
for(uint8_t i=0; i<24; i++)
|
||||
vector[23-i]=((0x0D7880F>>i)&1)*0xFFFF;
|
||||
|
||||
for(uint16_t j=0; j<1000; j++)
|
||||
{
|
||||
apply_errors(vector, 12, 23, 1, 0.5);
|
||||
TEST_ASSERT_EQUAL(0x0D78, golay24_sdecode(vector));
|
||||
for(uint8_t i=0; i<24; i++)
|
||||
vector[23-i]=((0x0D7880F>>i)&1)*0xFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
void golay_soft_decode_flipped_data_2(void)
|
||||
{
|
||||
uint16_t vector[24]; //soft-logic 24-bit vector
|
||||
|
||||
//clean D78|80F to soft-logic data
|
||||
for(uint8_t i=0; i<24; i++)
|
||||
vector[23-i]=((0x0D7880F>>i)&1)*0xFFFF;
|
||||
|
||||
for(uint16_t j=0; j<1000; j++)
|
||||
{
|
||||
apply_errors(vector, 12, 23, 2, 2.0);
|
||||
TEST_ASSERT_EQUAL(0x0D78, golay24_sdecode(vector));
|
||||
for(uint8_t i=0; i<24; i++)
|
||||
vector[23-i]=((0x0D7880F>>i)&1)*0xFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
void golay_soft_decode_erased_data_2(void)
|
||||
{
|
||||
uint16_t vector[24]; //soft-logic 24-bit vector
|
||||
|
||||
//clean D78|80F to soft-logic data
|
||||
for(uint8_t i=0; i<24; i++)
|
||||
vector[23-i]=((0x0D7880F>>i)&1)*0xFFFF;
|
||||
|
||||
for(uint16_t j=0; j<1000; j++)
|
||||
{
|
||||
apply_errors(vector, 12, 23, 2, 1.0);
|
||||
TEST_ASSERT_EQUAL(0x0D78, golay24_sdecode(vector));
|
||||
for(uint8_t i=0; i<24; i++)
|
||||
vector[23-i]=((0x0D7880F>>i)&1)*0xFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
void golay_soft_decode_flipped_data_3(void)
|
||||
{
|
||||
uint16_t vector[24]; //soft-logic 24-bit vector
|
||||
|
||||
//clean D78|80F to soft-logic data
|
||||
for(uint8_t i=0; i<24; i++)
|
||||
vector[23-i]=((0x0D7880F>>i)&1)*0xFFFF;
|
||||
|
||||
for(uint16_t j=0; j<1000; j++)
|
||||
{
|
||||
apply_errors(vector, 12, 23, 3, 3.0);
|
||||
TEST_ASSERT_EQUAL(0x0D78, golay24_sdecode(vector));
|
||||
for(uint8_t i=0; i<24; i++)
|
||||
vector[23-i]=((0x0D7880F>>i)&1)*0xFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
void golay_soft_decode_erased_data_3(void)
|
||||
{
|
||||
uint16_t vector[24]; //soft-logic 24-bit vector
|
||||
|
||||
//clean D78|80F to soft-logic data
|
||||
for(uint8_t i=0; i<24; i++)
|
||||
vector[23-i]=((0x0D7880F>>i)&1)*0xFFFF;
|
||||
|
||||
for(uint16_t j=0; j<1000; j++)
|
||||
{
|
||||
apply_errors(vector, 12, 23, 3, 1.5);
|
||||
TEST_ASSERT_EQUAL(0x0D78, golay24_sdecode(vector));
|
||||
for(uint8_t i=0; i<24; i++)
|
||||
vector[23-i]=((0x0D7880F>>i)&1)*0xFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
void golay_soft_decode_erased_data_3_5(void)
|
||||
{
|
||||
uint16_t vector[24]; //soft-logic 24-bit vector
|
||||
|
||||
//clean D78|80F to soft-logic data
|
||||
for(uint8_t i=0; i<24; i++)
|
||||
vector[23-i]=((0x0D7880F>>i)&1)*0xFFFF;
|
||||
|
||||
for(uint16_t j=0; j<1000; j++)
|
||||
{
|
||||
apply_errors(vector, 12, 23, 7, 3.5);
|
||||
TEST_ASSERT_EQUAL(0x0D78, golay24_sdecode(vector));
|
||||
for(uint8_t i=0; i<24; i++)
|
||||
vector[23-i]=((0x0D7880F>>i)&1)*0xFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
//4 errors is exactly half the hamming distance, so due to rounding etc., results may vary
|
||||
//therefore we run 2 tests here to prove that
|
||||
void golay_soft_decode_flipped_data_4(void)
|
||||
{
|
||||
uint16_t vector[24]; //soft-logic 24-bit vector
|
||||
|
||||
//clean D78|80F to soft-logic data
|
||||
for(uint8_t i=0; i<24; i++)
|
||||
vector[23-i]=((0x0D7880F>>i)&1)*0xFFFF;
|
||||
|
||||
vector[12]^=0xFFFF;
|
||||
vector[13]^=0xFFFF;
|
||||
vector[16]^=0xFFFF;
|
||||
vector[22]^=0xFFFF;
|
||||
TEST_ASSERT_NOT_EQUAL(0x0D78, golay24_sdecode(vector));
|
||||
for(uint8_t i=0; i<24; i++)
|
||||
vector[23-i]=((0x0D7880F>>i)&1)*0xFFFF;
|
||||
|
||||
vector[14]^=0xFFFF;
|
||||
vector[16]^=0xFFFF;
|
||||
vector[17]^=0xFFFF;
|
||||
vector[20]^=0xFFFF;
|
||||
TEST_ASSERT_EQUAL(0x0D78, golay24_sdecode(vector));
|
||||
for(uint8_t i=0; i<24; i++)
|
||||
vector[23-i]=((0x0D7880F>>i)&1)*0xFFFF;
|
||||
}
|
||||
|
||||
void golay_soft_decode_corrupt_data_4_5(void)
|
||||
{
|
||||
uint16_t vector[24]; //soft-logic 24-bit vector
|
||||
|
||||
//clean D78|80F to soft-logic data
|
||||
for(uint8_t i=0; i<24; i++)
|
||||
vector[23-i]=((0x0D7880F>>i)&1)*0xFFFF;
|
||||
|
||||
//4.5 errors - should be uncorrectable - WTF?
|
||||
apply_errors(vector, 12, 23, 12, 4.5);
|
||||
TEST_ASSERT_EQUAL(0x0D78, golay24_sdecode(vector));
|
||||
for(uint8_t i=0; i<24; i++)
|
||||
vector[23-i]=((0x0D7880F>>i)&1)*0xFFFF;
|
||||
}
|
||||
|
||||
void golay_soft_decode_erased_data_5(void)
|
||||
{
|
||||
uint16_t vector[24]; //soft-logic 24-bit vector
|
||||
|
||||
//clean D78|80F to soft-logic data
|
||||
for(uint8_t i=0; i<24; i++)
|
||||
vector[23-i]=((0x0D7880F>>i)&1)*0xFFFF;
|
||||
|
||||
for(uint16_t j=0; j<1000; j++)
|
||||
{
|
||||
apply_errors(vector, 12, 23, 5, 2.5);
|
||||
TEST_ASSERT_EQUAL(0x0D78, golay24_sdecode(vector));
|
||||
for(uint8_t i=0; i<24; i++)
|
||||
vector[23-i]=((0x0D7880F>>i)&1)*0xFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
void golay_soft_decode_flipped_data_5(void)
|
||||
{
|
||||
uint16_t vector[24]; //soft-logic 24-bit vector
|
||||
|
||||
//clean D78|80F to soft-logic data
|
||||
for(uint8_t i=0; i<24; i++)
|
||||
vector[23-i]=((0x0D7880F>>i)&1)*0xFFFF;
|
||||
|
||||
for(uint16_t j=0; j<1000; j++)
|
||||
{
|
||||
apply_errors(vector, 12, 23, 5, 5.0);
|
||||
TEST_ASSERT_NOT_EQUAL(0x0D78, golay24_sdecode(vector));
|
||||
for(uint8_t i=0; i<24; i++)
|
||||
vector[23-i]=((0x0D7880F>>i)&1)*0xFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
srand(time(NULL));
|
||||
|
||||
UNITY_BEGIN();
|
||||
|
||||
//soft logic arithmetic
|
||||
RUN_TEST(soft_logic_xor);
|
||||
|
||||
//symbol to dibit
|
||||
RUN_TEST(symbol_to_dibit);
|
||||
|
||||
//soft Golay
|
||||
RUN_TEST(golay_encode);
|
||||
RUN_TEST(golay_soft_decode_clean);
|
||||
|
||||
RUN_TEST(golay_soft_decode_erased_parity_1);
|
||||
RUN_TEST(golay_soft_decode_flipped_parity_1);
|
||||
RUN_TEST(golay_soft_decode_erased_parity_2);
|
||||
RUN_TEST(golay_soft_decode_flipped_parity_2);
|
||||
RUN_TEST(golay_soft_decode_erased_parity_3);
|
||||
RUN_TEST(golay_soft_decode_flipped_parity_3);
|
||||
RUN_TEST(golay_soft_decode_erased_parity_3_5);
|
||||
RUN_TEST(golay_soft_decode_flipped_parity_4);
|
||||
RUN_TEST(golay_soft_decode_erased_parity_5);
|
||||
RUN_TEST(golay_soft_decode_flipped_parity_5);
|
||||
|
||||
RUN_TEST(golay_soft_decode_erased_data_1);
|
||||
RUN_TEST(golay_soft_decode_flipped_data_1);
|
||||
RUN_TEST(golay_soft_decode_erased_data_2);
|
||||
RUN_TEST(golay_soft_decode_flipped_data_2);
|
||||
RUN_TEST(golay_soft_decode_erased_data_3);
|
||||
RUN_TEST(golay_soft_decode_flipped_data_3);
|
||||
RUN_TEST(golay_soft_decode_erased_data_3_5);
|
||||
RUN_TEST(golay_soft_decode_flipped_data_4);
|
||||
RUN_TEST(golay_soft_decode_corrupt_data_4_5);
|
||||
RUN_TEST(golay_soft_decode_erased_data_5);
|
||||
RUN_TEST(golay_soft_decode_flipped_data_5);
|
||||
|
||||
return UNITY_END();
|
||||
}
|
Ładowanie…
Reference in New Issue