kopia lustrzana https://github.com/kgoba/ft8_lib
Changed pointer declarations, made some function static that should be
rodzic
7699003ade
commit
e6076b6ed1
|
@ -7,7 +7,7 @@
|
|||
#include <stdint.h>
|
||||
|
||||
// Save signal in floating point format (-1 .. +1) as a WAVE file using 16-bit signed integers.
|
||||
void save_wav(const float* signal, int num_samples, int sample_rate, const char* path)
|
||||
void save_wav(const float *signal, int num_samples, int sample_rate, const char *path)
|
||||
{
|
||||
char subChunk1ID[4] = { 'f', 'm', 't', ' ' };
|
||||
uint32_t subChunk1Size = 16; // 16 for PCM
|
||||
|
@ -25,7 +25,7 @@ void save_wav(const float* signal, int num_samples, int sample_rate, const char*
|
|||
uint32_t chunkSize = 4 + (8 + subChunk1Size) + (8 + subChunk2Size);
|
||||
char format[4] = { 'W', 'A', 'V', 'E' };
|
||||
|
||||
int16_t* raw_data = (int16_t*)malloc(num_samples * blockAlign);
|
||||
int16_t *raw_data = malloc(num_samples * blockAlign);
|
||||
for (int i = 0; i < num_samples; i++) {
|
||||
float x = signal[i];
|
||||
if (x > 1.0)
|
||||
|
@ -35,7 +35,7 @@ void save_wav(const float* signal, int num_samples, int sample_rate, const char*
|
|||
raw_data[i] = (int)(0.5 + (x * 32767.0));
|
||||
}
|
||||
|
||||
FILE* f = fopen(path, "wb");
|
||||
FILE *f = fopen(path, "wb");
|
||||
|
||||
// NOTE: works only on little-endian architecture
|
||||
fwrite(chunkID, sizeof(chunkID), 1, f);
|
||||
|
@ -62,7 +62,7 @@ void save_wav(const float* signal, int num_samples, int sample_rate, const char*
|
|||
}
|
||||
|
||||
// Load signal in floating point format (-1 .. +1) as a WAVE file using 16-bit signed integers.
|
||||
int load_wav(float* signal, int* num_samples, int* sample_rate, const char* path)
|
||||
int load_wav(float *signal, int *num_samples, int *sample_rate, const char *path)
|
||||
{
|
||||
char subChunk1ID[4]; // = {'f', 'm', 't', ' '};
|
||||
uint32_t subChunk1Size; // = 16; // 16 for PCM
|
||||
|
@ -80,34 +80,34 @@ int load_wav(float* signal, int* num_samples, int* sample_rate, const char* path
|
|||
uint32_t chunkSize; // = 4 + (8 + subChunk1Size) + (8 + subChunk2Size);
|
||||
char format[4]; // = {'W', 'A', 'V', 'E'};
|
||||
|
||||
FILE* f = fopen(path, "rb");
|
||||
FILE *f = fopen(path, "rb");
|
||||
|
||||
if (f == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// NOTE: works only on little-endian architecture
|
||||
fread((void*)chunkID, sizeof(chunkID), 1, f);
|
||||
fread((void*)&chunkSize, sizeof(chunkSize), 1, f);
|
||||
fread((void*)format, sizeof(format), 1, f);
|
||||
fread(chunkID, sizeof(chunkID), 1, f);
|
||||
fread(&chunkSize, sizeof(chunkSize), 1, f);
|
||||
fread(format, sizeof(format), 1, f);
|
||||
|
||||
fread((void*)subChunk1ID, sizeof(subChunk1ID), 1, f);
|
||||
fread((void*)&subChunk1Size, sizeof(subChunk1Size), 1, f);
|
||||
fread(subChunk1ID, sizeof(subChunk1ID), 1, f);
|
||||
fread(&subChunk1Size, sizeof(subChunk1Size), 1, f);
|
||||
if (subChunk1Size != 16)
|
||||
return -1;
|
||||
|
||||
fread((void*)&audioFormat, sizeof(audioFormat), 1, f);
|
||||
fread((void*)&numChannels, sizeof(numChannels), 1, f);
|
||||
fread((void*)&sampleRate, sizeof(sampleRate), 1, f);
|
||||
fread((void*)&byteRate, sizeof(byteRate), 1, f);
|
||||
fread((void*)&blockAlign, sizeof(blockAlign), 1, f);
|
||||
fread((void*)&bitsPerSample, sizeof(bitsPerSample), 1, f);
|
||||
fread(&audioFormat, sizeof(audioFormat), 1, f);
|
||||
fread(&numChannels, sizeof(numChannels), 1, f);
|
||||
fread(&sampleRate, sizeof(sampleRate), 1, f);
|
||||
fread(&byteRate, sizeof(byteRate), 1, f);
|
||||
fread(&blockAlign, sizeof(blockAlign), 1, f);
|
||||
fread(&bitsPerSample, sizeof(bitsPerSample), 1, f);
|
||||
|
||||
if (audioFormat != 1 || numChannels != 1 || bitsPerSample != 16)
|
||||
return -1;
|
||||
|
||||
fread((void*)subChunk2ID, sizeof(subChunk2ID), 1, f);
|
||||
fread((void*)&subChunk2Size, sizeof(subChunk2Size), 1, f);
|
||||
fread(subChunk2ID, sizeof(subChunk2ID), 1, f);
|
||||
fread(&subChunk2Size, sizeof(subChunk2Size), 1, f);
|
||||
|
||||
if (subChunk2Size / blockAlign > *num_samples)
|
||||
return -2;
|
||||
|
@ -115,9 +115,9 @@ int load_wav(float* signal, int* num_samples, int* sample_rate, const char* path
|
|||
*num_samples = subChunk2Size / blockAlign;
|
||||
*sample_rate = sampleRate;
|
||||
|
||||
int16_t* raw_data = (int16_t*)malloc(*num_samples * blockAlign);
|
||||
int16_t *raw_data = malloc(*num_samples * blockAlign);
|
||||
|
||||
fread((void*)raw_data, blockAlign, *num_samples, f);
|
||||
fread(raw_data, blockAlign, *num_samples, f);
|
||||
for (int i = 0; i < *num_samples; i++) {
|
||||
signal[i] = raw_data[i] / 32768.0f;
|
||||
}
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
#define _INCLUDE_WAVE_H_
|
||||
|
||||
// Save signal in floating point format (-1 .. +1) as a WAVE file using 16-bit signed integers.
|
||||
void save_wav(const float* signal, int num_samples, int sample_rate, const char* path);
|
||||
void save_wav(const float *signal, int num_samples, int sample_rate, const char *path);
|
||||
|
||||
// Load signal in floating point format (-1 .. +1) as a WAVE file using 16-bit signed integers.
|
||||
int load_wav(float* signal, int* num_samples, int* sample_rate, const char* path);
|
||||
int load_wav(float *signal, int *num_samples, int *sample_rate, const char *path);
|
||||
|
||||
#endif // _INCLUDE_WAVE_H_
|
||||
|
|
|
@ -8,11 +8,11 @@
|
|||
#include "common/wave.h"
|
||||
#include "ft8.h"
|
||||
|
||||
static FILE* reference;
|
||||
static FILE *reference;
|
||||
static bool identical;
|
||||
|
||||
// decode callback, called by ft8_decode() for each decoded message
|
||||
static void ft8_decode_callback(char* message, float frequency, float time_dev, float snr, int score, void* ctx)
|
||||
static void ft8_decode_callback(char *message, float frequency, float time_dev, float snr, int score, void *ctx)
|
||||
{
|
||||
char buf[256], buf2[256];
|
||||
printf("000000 %3d %+4.2f %4.1f %4.0f ~ %s\n", score, time_dev, snr, frequency, message);
|
||||
|
@ -24,7 +24,7 @@ static void ft8_decode_callback(char* message, float frequency, float time_dev,
|
|||
}
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
#if 0
|
||||
// Expect one command-line argument
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
// Adapted from https://barrgroup.com/Embedded-Systems/How-To/CRC-Calculation-C-Code
|
||||
// [IN] message - byte sequence (MSB first)
|
||||
// [IN] num_bits - number of bits in the sequence
|
||||
uint16_t ftx_compute_crc(const uint8_t message[], int num_bits)
|
||||
uint16_t ftx_compute_crc(const uint8_t *message, int num_bits)
|
||||
{
|
||||
uint16_t remainder = 0;
|
||||
int idx_byte = 0;
|
||||
|
@ -31,13 +31,13 @@ uint16_t ftx_compute_crc(const uint8_t message[], int num_bits)
|
|||
return remainder & ((TOPBIT << 1) - 1u);
|
||||
}
|
||||
|
||||
uint16_t ftx_extract_crc(const uint8_t a91[])
|
||||
uint16_t ftx_extract_crc(const uint8_t *a91)
|
||||
{
|
||||
uint16_t chksum = ((a91[9] & 0x07) << 11) | (a91[10] << 3) | (a91[11] >> 5);
|
||||
return chksum;
|
||||
}
|
||||
|
||||
void ftx_add_crc(const uint8_t payload[], uint8_t a91[])
|
||||
void ftx_add_crc(const uint8_t *payload, uint8_t *a91)
|
||||
{
|
||||
// Copy 77 bits of payload data
|
||||
for (int i = 0; i < 10; i++)
|
||||
|
|
|
@ -7,16 +7,16 @@
|
|||
// Compute 14-bit CRC for a sequence of given number of bits using FT8/FT4 CRC polynomial
|
||||
// [IN] message - byte sequence (MSB first)
|
||||
// [IN] num_bits - number of bits in the sequence
|
||||
uint16_t ftx_compute_crc(const uint8_t message[], int num_bits);
|
||||
uint16_t ftx_compute_crc(const uint8_t *message, int num_bits);
|
||||
|
||||
/// Extract the FT8/FT4 CRC of a packed message (during decoding)
|
||||
/// @param[in] a91 77 bits of payload data + CRC
|
||||
/// @return Extracted CRC
|
||||
uint16_t ftx_extract_crc(const uint8_t a91[]);
|
||||
uint16_t ftx_extract_crc(const uint8_t *a9);
|
||||
|
||||
/// Add FT8/FT4 CRC to a packed message (during encoding)
|
||||
/// @param[in] payload 77 bits of payload data
|
||||
/// @param[out] a91 91 bits of payload data + CRC
|
||||
void ftx_add_crc(const uint8_t payload[], uint8_t a91[]);
|
||||
void ftx_add_crc(const uint8_t *payload, uint8_t *a91);
|
||||
|
||||
#endif // _INCLUDE_CRC_H_
|
||||
|
|
71
ft8/decode.c
71
ft8/decode.c
|
@ -31,7 +31,7 @@ typedef struct {
|
|||
int num_bins; ///< number of FFT bins in terms of 6.25 Hz
|
||||
int time_osr; ///< number of time subdivisions
|
||||
int freq_osr; ///< number of frequency subdivisions
|
||||
uint8_t* mag; ///< FFT magnitudes stored as uint8_t[blocks][time_osr][freq_osr][num_bins]
|
||||
uint8_t *mag; ///< FFT magnitudes stored as uint8_t[blocks][time_osr][freq_osr][num_bins]
|
||||
int block_stride; ///< Helper value = time_osr * freq_osr * num_bins
|
||||
ftx_protocol_t protocol; ///< Indicate if using FT4 or FT8
|
||||
} waterfall_t;
|
||||
|
@ -79,13 +79,13 @@ typedef struct {
|
|||
int subblock_size; ///< Analysis shift size (number of samples)
|
||||
int nfft; ///< FFT size
|
||||
float fft_norm; ///< FFT normalization factor
|
||||
float* window; ///< Window function for STFT analysis (nfft samples)
|
||||
float* last_frame; ///< Current STFT analysis frame (nfft samples)
|
||||
float *window; ///< Window function for STFT analysis (nfft samples)
|
||||
float *last_frame; ///< Current STFT analysis frame (nfft samples)
|
||||
waterfall_t wf; ///< Waterfall object
|
||||
float max_mag; ///< Maximum detected magnitude (debug stats)
|
||||
|
||||
// KISS FFT housekeeping variables
|
||||
void* fft_work; ///< Work area required by Kiss FFT
|
||||
void *fft_work; ///< Work area required by Kiss FFT
|
||||
kiss_fftr_cfg fft_cfg; ///< Kiss FFT housekeeping object
|
||||
} monitor_t;
|
||||
|
||||
|
@ -94,11 +94,11 @@ static float max4(float a, float b, float c, float d);
|
|||
static void heapify_down(candidate_t heap[], int heap_size);
|
||||
static void heapify_up(candidate_t heap[], int heap_size);
|
||||
|
||||
static void ftx_normalize_logl(float* log174);
|
||||
static void ft4_extract_symbol(const uint8_t* wf, float* logl);
|
||||
static void ft8_extract_symbol(const uint8_t* wf, float* logl);
|
||||
static void ftx_normalize_logl(float *log174);
|
||||
static void ft4_extract_symbol(const uint8_t *wf, float *logl);
|
||||
static void ft8_extract_symbol(const uint8_t *wf, float *logl);
|
||||
|
||||
static void waterfall_init(waterfall_t* me, int max_blocks, int num_bins, int time_osr, int freq_osr)
|
||||
static void waterfall_init(waterfall_t *me, int max_blocks, int num_bins, int time_osr, int freq_osr)
|
||||
{
|
||||
me->max_blocks = max_blocks;
|
||||
me->num_blocks = 0;
|
||||
|
@ -109,9 +109,12 @@ static void waterfall_init(waterfall_t* me, int max_blocks, int num_bins, int ti
|
|||
me->mag = calloc(max_blocks * time_osr * freq_osr * num_bins, sizeof(me->mag[0]));
|
||||
}
|
||||
|
||||
static void waterfall_free(waterfall_t* me) { free(me->mag); }
|
||||
static void waterfall_free(waterfall_t *me)
|
||||
{
|
||||
free(me->mag);
|
||||
}
|
||||
|
||||
static void monitor_init(monitor_t* me, const monitor_config_t* cfg)
|
||||
static void monitor_init(monitor_t *me, const monitor_config_t *cfg)
|
||||
{
|
||||
float slot_time = (cfg->protocol == PROTO_FT4) ? FT4_SLOT_TIME : FT8_SLOT_TIME;
|
||||
float symbol_period = (cfg->protocol == PROTO_FT4) ? FT4_SYMBOL_PERIOD : FT8_SYMBOL_PERIOD;
|
||||
|
@ -120,8 +123,6 @@ static void monitor_init(monitor_t* me, const monitor_config_t* cfg)
|
|||
me->subblock_size = me->block_size / cfg->time_osr;
|
||||
me->nfft = me->block_size * cfg->freq_osr;
|
||||
me->fft_norm = 2.0f / me->nfft;
|
||||
// const int len_window = 1.8f * me->block_size; // hand-picked and optimized
|
||||
|
||||
me->window = calloc(me->nfft, sizeof(me->window[0]));
|
||||
for (int i = 0; i < me->nfft; ++i) {
|
||||
// hann window
|
||||
|
@ -144,7 +145,7 @@ static void monitor_init(monitor_t* me, const monitor_config_t* cfg)
|
|||
me->max_mag = -120.0f;
|
||||
}
|
||||
|
||||
static void monitor_free(monitor_t* me)
|
||||
static void monitor_free(monitor_t *me)
|
||||
{
|
||||
waterfall_free(&me->wf);
|
||||
free(me->fft_work);
|
||||
|
@ -153,7 +154,7 @@ static void monitor_free(monitor_t* me)
|
|||
}
|
||||
|
||||
// Compute FFT magnitudes (log wf) for a frame in the signal and update waterfall data
|
||||
static void monitor_process(monitor_t* me, const float* frame)
|
||||
static void monitor_process(monitor_t *me, const float *frame)
|
||||
{
|
||||
// Check if we can still store more waterfall data
|
||||
if (me->wf.num_blocks >= me->wf.max_blocks)
|
||||
|
@ -205,7 +206,7 @@ static void monitor_process(monitor_t* me, const float* frame)
|
|||
++me->wf.num_blocks;
|
||||
}
|
||||
|
||||
static int get_index(const waterfall_t* wf, const candidate_t* candidate)
|
||||
static int get_index(const waterfall_t *wf, const candidate_t *candidate)
|
||||
{
|
||||
int offset = candidate->time_offset;
|
||||
offset = (offset * wf->time_osr) + candidate->time_sub;
|
||||
|
@ -237,13 +238,13 @@ static void pack_bits(const uint8_t bit_array[], int num_bits, uint8_t packed[])
|
|||
}
|
||||
}
|
||||
|
||||
static int ft8_sync_score(const waterfall_t* wf, const candidate_t* candidate)
|
||||
static int ft8_sync_score(const waterfall_t *wf, const candidate_t *candidate)
|
||||
{
|
||||
int score = 0;
|
||||
int num_average = 0;
|
||||
|
||||
// Get the pointer to symbol 0 of the candidate
|
||||
const uint8_t* mag_cand = wf->mag + get_index(wf, candidate);
|
||||
const uint8_t *mag_cand = wf->mag + get_index(wf, candidate);
|
||||
|
||||
// Compute average score over sync symbols (m+k = 0-7, 36-43, 72-79)
|
||||
for (int m = 0; m < FT8_NUM_SYNC; ++m) {
|
||||
|
@ -257,7 +258,7 @@ static int ft8_sync_score(const waterfall_t* wf, const candidate_t* candidate)
|
|||
break;
|
||||
|
||||
// Get the pointer to symbol 'block' of the candidate
|
||||
const uint8_t* p8 = mag_cand + (block * wf->block_stride);
|
||||
const uint8_t *p8 = mag_cand + (block * wf->block_stride);
|
||||
|
||||
#if 0
|
||||
// Weighted difference between the expected and all other symbols
|
||||
|
@ -300,13 +301,13 @@ static int ft8_sync_score(const waterfall_t* wf, const candidate_t* candidate)
|
|||
return score;
|
||||
}
|
||||
|
||||
static int ft4_sync_score(const waterfall_t* wf, const candidate_t* candidate)
|
||||
static int ft4_sync_score(const waterfall_t *wf, const candidate_t *candidate)
|
||||
{
|
||||
int score = 0;
|
||||
int num_average = 0;
|
||||
|
||||
// Get the pointer to symbol 0 of the candidate
|
||||
const uint8_t* mag_cand = wf->mag + get_index(wf, candidate);
|
||||
const uint8_t *mag_cand = wf->mag + get_index(wf, candidate);
|
||||
|
||||
// Compute average score over sync symbols (block = 1-4, 34-37, 67-70, 100-103)
|
||||
for (int m = 0; m < FT4_NUM_SYNC; ++m) {
|
||||
|
@ -320,7 +321,7 @@ static int ft4_sync_score(const waterfall_t* wf, const candidate_t* candidate)
|
|||
break;
|
||||
|
||||
// Get the pointer to symbol 'block' of the candidate
|
||||
const uint8_t* p4 = mag_cand + (block * wf->block_stride);
|
||||
const uint8_t *p4 = mag_cand + (block * wf->block_stride);
|
||||
|
||||
int sm = kFT4_Costas_pattern[m][k]; // Index of the expected bin
|
||||
|
||||
|
@ -358,7 +359,7 @@ static int ft4_sync_score(const waterfall_t* wf, const candidate_t* candidate)
|
|||
return score;
|
||||
}
|
||||
|
||||
int ft8_find_sync(const waterfall_t* wf, int num_candidates, candidate_t heap[], int min_score)
|
||||
int ft8_find_sync(const waterfall_t *wf, int num_candidates, candidate_t *heap, int min_score)
|
||||
{
|
||||
int heap_size = 0;
|
||||
candidate_t candidate;
|
||||
|
@ -411,9 +412,9 @@ int ft8_find_sync(const waterfall_t* wf, int num_candidates, candidate_t heap[],
|
|||
return heap_size;
|
||||
}
|
||||
|
||||
static void ft4_extract_likelihood(const waterfall_t* wf, const candidate_t* cand, float* log174)
|
||||
static void ft4_extract_likelihood(const waterfall_t *wf, const candidate_t *cand, float *log174)
|
||||
{
|
||||
const uint8_t* mag_cand = wf->mag + get_index(wf, cand);
|
||||
const uint8_t *mag_cand = wf->mag + get_index(wf, cand);
|
||||
|
||||
// Go over FSK tones and skip Costas sync symbols
|
||||
for (int k = 0; k < FT4_ND; ++k) {
|
||||
|
@ -429,16 +430,16 @@ static void ft4_extract_likelihood(const waterfall_t* wf, const candidate_t* can
|
|||
log174[bit_idx + 1] = 0;
|
||||
} else {
|
||||
// Pointer to 4 bins of the current symbol
|
||||
const uint8_t* ps = mag_cand + (sym_idx * wf->block_stride);
|
||||
const uint8_t *ps = mag_cand + (sym_idx * wf->block_stride);
|
||||
|
||||
ft4_extract_symbol(ps, log174 + bit_idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ft8_extract_likelihood(const waterfall_t* wf, const candidate_t* cand, float* log174)
|
||||
static void ft8_extract_likelihood(const waterfall_t *wf, const candidate_t *cand, float *log174)
|
||||
{
|
||||
const uint8_t* mag_cand = wf->mag + get_index(wf, cand);
|
||||
const uint8_t *mag_cand = wf->mag + get_index(wf, cand);
|
||||
|
||||
// Go over FSK tones and skip Costas sync symbols
|
||||
for (int k = 0; k < FT8_ND; ++k) {
|
||||
|
@ -455,14 +456,14 @@ static void ft8_extract_likelihood(const waterfall_t* wf, const candidate_t* can
|
|||
log174[bit_idx + 2] = 0;
|
||||
} else {
|
||||
// Pointer to 8 bins of the current symbol
|
||||
const uint8_t* ps = mag_cand + (sym_idx * wf->block_stride);
|
||||
const uint8_t *ps = mag_cand + (sym_idx * wf->block_stride);
|
||||
|
||||
ft8_extract_symbol(ps, log174 + bit_idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ftx_normalize_logl(float* log174)
|
||||
static void ftx_normalize_logl(float *log174)
|
||||
{
|
||||
// Compute the variance of log174
|
||||
float sum = 0;
|
||||
|
@ -481,7 +482,7 @@ static void ftx_normalize_logl(float* log174)
|
|||
}
|
||||
}
|
||||
|
||||
bool ft8_decode(const waterfall_t* wf, const candidate_t* cand, message_t* message, int max_iterations, decode_status_t* status)
|
||||
bool ft8_decode(const waterfall_t *wf, const candidate_t *cand, message_t *message, int max_iterations, decode_status_t *status)
|
||||
{
|
||||
float log174[FTX_LDPC_N]; // message bits encoded as likelihood
|
||||
if (wf->protocol == PROTO_FT4) {
|
||||
|
@ -583,7 +584,7 @@ static void heapify_up(candidate_t heap[], int heap_size)
|
|||
}
|
||||
|
||||
// Compute unnormalized log likelihood log(p(1) / p(0)) of 2 message bits (1 FSK symbol)
|
||||
static void ft4_extract_symbol(const uint8_t* wf, float* logl)
|
||||
static void ft4_extract_symbol(const uint8_t *wf, float *logl)
|
||||
{
|
||||
// Cleaned up code for the simple case of n_syms==1
|
||||
float s2[4];
|
||||
|
@ -597,7 +598,7 @@ static void ft4_extract_symbol(const uint8_t* wf, float* logl)
|
|||
}
|
||||
|
||||
// Compute unnormalized log likelihood log(p(1) / p(0)) of 3 message bits (1 FSK symbol)
|
||||
static void ft8_extract_symbol(const uint8_t* wf, float* logl)
|
||||
static void ft8_extract_symbol(const uint8_t *wf, float *logl)
|
||||
{
|
||||
// Cleaned up code for the simple case of n_syms==1
|
||||
float s2[8];
|
||||
|
@ -612,7 +613,7 @@ static void ft8_extract_symbol(const uint8_t* wf, float* logl)
|
|||
}
|
||||
|
||||
// decode FT4 or FT8 signal, call callback for every decoded message
|
||||
int ftx_decode(float* signal, int num_samples, int sample_rate, ftx_protocol_t protocol, ftx_decode_callback_t callback, void* ctx)
|
||||
int ftx_decode(float *signal, int num_samples, int sample_rate, ftx_protocol_t protocol, ftx_decode_callback_t callback, void *ctx)
|
||||
{
|
||||
// Compute FFT over the whole signal and store it
|
||||
monitor_t mon;
|
||||
|
@ -631,7 +632,7 @@ int ftx_decode(float* signal, int num_samples, int sample_rate, ftx_protocol_t p
|
|||
// Hash table for decoded messages (to check for duplicates)
|
||||
int num_decoded = 0;
|
||||
message_t decoded[kMax_decoded_messages];
|
||||
message_t* decoded_hashtable[kMax_decoded_messages];
|
||||
message_t *decoded_hashtable[kMax_decoded_messages];
|
||||
|
||||
// Initialize hash table pointers
|
||||
for (int i = 0; i < kMax_decoded_messages; ++i) {
|
||||
|
@ -640,7 +641,7 @@ int ftx_decode(float* signal, int num_samples, int sample_rate, ftx_protocol_t p
|
|||
|
||||
// Go over candidates and attempt to decode messages
|
||||
for (int idx = 0; idx < num_candidates; ++idx) {
|
||||
const candidate_t* cand = &candidate_list[idx];
|
||||
const candidate_t *cand = &candidate_list[idx];
|
||||
|
||||
float freq_hz = (cand->freq_offset + (float)cand->freq_sub / mon.wf.freq_osr) / mon.symbol_period;
|
||||
float time_sec = (cand->time_offset + (float)cand->time_sub / mon.wf.time_osr) * mon.symbol_period;
|
||||
|
|
14
ft8/encode.c
14
ft8/encode.c
|
@ -19,7 +19,7 @@
|
|||
/// @param[in] symbol_bt Shape parameter (values defined for FT8/FT4)
|
||||
/// @param[out] pulse Output array of pulse samples
|
||||
///
|
||||
void gfsk_pulse(int n_spsym, float symbol_bt, float* pulse)
|
||||
void gfsk_pulse(int n_spsym, float symbol_bt, float *pulse)
|
||||
{
|
||||
for (int i = 0; i < 3 * n_spsym; ++i) {
|
||||
float t = i / (float)n_spsym - 1.5f;
|
||||
|
@ -39,7 +39,7 @@ void gfsk_pulse(int n_spsym, float symbol_bt, float* pulse)
|
|||
/// @param[in] signal_rate Sample rate of synthesized signal, Hertz
|
||||
/// @param[out] signal Output array of signal waveform samples (should have space for n_sym*n_spsym samples)
|
||||
///
|
||||
void synth_gfsk(const uint8_t* symbols, int n_sym, float f0, float symbol_bt, float symbol_period, int signal_rate, float* signal)
|
||||
void synth_gfsk(const uint8_t *symbols, int n_sym, float f0, float symbol_bt, float symbol_period, int signal_rate, float *signal)
|
||||
{
|
||||
int n_spsym = (int)(0.5f + signal_rate * symbol_period); // Samples per symbol
|
||||
int n_wave = n_sym * n_spsym; // Number of output samples
|
||||
|
@ -47,7 +47,7 @@ void synth_gfsk(const uint8_t* symbols, int n_sym, float f0, float symbol_bt, fl
|
|||
|
||||
// Compute the smoothed frequency waveform.
|
||||
// Length = (nsym+2)*n_spsym samples, first and last symbols extended
|
||||
float* dphi = malloc((n_wave + 2 * n_spsym) * sizeof(float));
|
||||
float *dphi = malloc((n_wave + 2 * n_spsym) * sizeof(float));
|
||||
if (dphi != NULL) {
|
||||
float dphi_peak = 2 * M_PI * hmod / n_spsym;
|
||||
|
||||
|
@ -105,7 +105,7 @@ static uint8_t parity8(uint8_t x)
|
|||
// Arguments:
|
||||
// [IN] message - array of 91 bits stored as 12 bytes (MSB first)
|
||||
// [OUT] codeword - array of 174 bits stored as 22 bytes (MSB first)
|
||||
static void encode174(const uint8_t* message, uint8_t* codeword)
|
||||
static void encode174(const uint8_t *message, uint8_t *codeword)
|
||||
{
|
||||
// This implementation accesses the generator bits straight from the packed binary representation in kFTX_LDPC_generator
|
||||
|
||||
|
@ -143,7 +143,7 @@ static void encode174(const uint8_t* message, uint8_t* codeword)
|
|||
}
|
||||
}
|
||||
|
||||
void ft8_encode(const uint8_t* payload, uint8_t* tones)
|
||||
void ft8_encode(const uint8_t *payload, uint8_t *tones)
|
||||
{
|
||||
uint8_t a91[FTX_LDPC_K_BYTES]; // Store 77 bits of payload + 14 bits CRC
|
||||
|
||||
|
@ -194,7 +194,7 @@ void ft8_encode(const uint8_t* payload, uint8_t* tones)
|
|||
}
|
||||
}
|
||||
|
||||
void ft4_encode(const uint8_t* payload, uint8_t* tones)
|
||||
void ft4_encode(const uint8_t *payload, uint8_t *tones)
|
||||
{
|
||||
uint8_t a91[FTX_LDPC_K_BYTES]; // Store 77 bits of payload + 14 bits CRC
|
||||
uint8_t payload_xor[10]; // Encoded payload data
|
||||
|
@ -250,7 +250,7 @@ void ft4_encode(const uint8_t* payload, uint8_t* tones)
|
|||
}
|
||||
|
||||
// generate FT4 or FT8 signal for message
|
||||
int ftx_encode(char* message, float* signal, int num_samples, float frequency, int sample_rate, ftx_protocol_t protocol)
|
||||
int ftx_encode(char *message, float *signal, int num_samples, float frequency, int sample_rate, ftx_protocol_t protocol)
|
||||
{
|
||||
// First, pack the text data into binary message
|
||||
uint8_t packed[FTX_LDPC_K_BYTES];
|
||||
|
|
10
ft8/ldpc.c
10
ft8/ldpc.c
|
@ -17,7 +17,7 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static int ldpc_check(uint8_t codeword[]);
|
||||
static int ldpc_check(uint8_t *codeword);
|
||||
static float fast_tanh(float x);
|
||||
static float fast_atanh(float x);
|
||||
|
||||
|
@ -25,7 +25,7 @@ static float fast_atanh(float x);
|
|||
// plain is a return value, 174 ints, to be 0 or 1.
|
||||
// max_iters is how hard to try.
|
||||
// ok == 87 means success.
|
||||
void ldpc_decode(float codeword[], int max_iters, uint8_t plain[], int* ok)
|
||||
void ldpc_decode(float *codeword, int max_iters, uint8_t *plain, int* ok)
|
||||
{
|
||||
float m[FTX_LDPC_M][FTX_LDPC_N]; // ~60 kB
|
||||
float e[FTX_LDPC_M][FTX_LDPC_N]; // ~60 kB
|
||||
|
@ -94,7 +94,7 @@ void ldpc_decode(float codeword[], int max_iters, uint8_t plain[], int* ok)
|
|||
// returns the number of parity errors.
|
||||
// 0 means total success.
|
||||
//
|
||||
static int ldpc_check(uint8_t codeword[])
|
||||
static int ldpc_check(uint8_t *codeword)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
|
@ -110,7 +110,7 @@ static int ldpc_check(uint8_t codeword[])
|
|||
return errors;
|
||||
}
|
||||
|
||||
void bp_decode(float codeword[], int max_iters, uint8_t plain[], int* ok)
|
||||
void bp_decode(float *codeword, int max_iters, uint8_t *plain, int *ok)
|
||||
{
|
||||
float tov[FTX_LDPC_N][3];
|
||||
float toc[FTX_LDPC_M][7];
|
||||
|
@ -187,6 +187,7 @@ void bp_decode(float codeword[], int max_iters, uint8_t plain[], int* ok)
|
|||
// * https://mathr.co.uk/blog/2017-09-06_approximating_hyperbolic_tangent.html
|
||||
// * https://math.stackexchange.com/a/446411
|
||||
|
||||
#warning remove!
|
||||
static float fast_tanh(float x)
|
||||
{
|
||||
if (x < -4.97f) {
|
||||
|
@ -205,6 +206,7 @@ static float fast_tanh(float x)
|
|||
return a / b;
|
||||
}
|
||||
|
||||
#warning remove!
|
||||
static float fast_atanh(float x)
|
||||
{
|
||||
float x2 = x * x;
|
||||
|
|
|
@ -7,9 +7,11 @@
|
|||
// plain is a return value, 174 ints, to be 0 or 1.
|
||||
// iters is how hard to try.
|
||||
// ok == 87 means success.
|
||||
void ldpc_decode(float codeword[], int max_iters, uint8_t plain[], int *ok);
|
||||
#warning remove OK and return value
|
||||
void ldpc_decode(float *codeword, int max_iters, uint8_t *plain, int *ok);
|
||||
|
||||
void bp_decode(float codeword[], int max_iters, uint8_t plain[], int *ok);
|
||||
#warning remove OK and return value
|
||||
void bp_decode(float *codeword, int max_iters, uint8_t *plain, int *ok);
|
||||
|
||||
#endif // _INCLUDE_LDPC_H_
|
||||
|
||||
|
|
22
ft8/pack.c
22
ft8/pack.c
|
@ -20,7 +20,7 @@ const char A4[] = " ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
|||
|
||||
// Pack a special token, a 22-bit hash code, or a valid base call
|
||||
// into a 28-bit integer.
|
||||
int32_t pack28(const char* callsign)
|
||||
static int32_t pack28(const char *callsign)
|
||||
{
|
||||
// Check for special tokens first
|
||||
if (starts_with(callsign, "DE "))
|
||||
|
@ -88,7 +88,7 @@ int32_t pack28(const char* callsign)
|
|||
// Check if a string could be a valid standard callsign or a valid
|
||||
// compound callsign.
|
||||
// Return base call "bc" and a logical "cok" indicator.
|
||||
bool chkcall(const char* call, char* bc)
|
||||
static bool chkcall(const char *call, char *bc)
|
||||
{
|
||||
int length = strlen(call); // n1=len_trim(w)
|
||||
if (length > 11)
|
||||
|
@ -109,7 +109,7 @@ bool chkcall(const char* call, char* bc)
|
|||
return true;
|
||||
}
|
||||
|
||||
uint16_t packgrid(const char* grid4)
|
||||
static uint16_t packgrid(const char *grid4)
|
||||
{
|
||||
if (grid4 == 0) {
|
||||
// Two callsigns only, no report/grid
|
||||
|
@ -150,15 +150,15 @@ uint16_t packgrid(const char* grid4)
|
|||
}
|
||||
|
||||
// Pack Type 1 (Standard 77-bit message) and Type 2 (ditto, with a "/P" call)
|
||||
int pack77_1(const char* msg, uint8_t* b77)
|
||||
static int pack77_1(const char *msg, uint8_t *b77)
|
||||
{
|
||||
// Locate the first delimiter
|
||||
const char* s1 = strchr(msg, ' ');
|
||||
const char *s1 = strchr(msg, ' ');
|
||||
if (s1 == 0)
|
||||
return -1;
|
||||
|
||||
const char* call1 = msg; // 1st call
|
||||
const char* call2 = s1 + 1; // 2nd call
|
||||
const char *call1 = msg; // 1st call
|
||||
const char *call2 = s1 + 1; // 2nd call
|
||||
|
||||
int32_t n28a = pack28(call1);
|
||||
int32_t n28b = pack28(call2);
|
||||
|
@ -169,7 +169,7 @@ int pack77_1(const char* msg, uint8_t* b77)
|
|||
uint16_t igrid4;
|
||||
|
||||
// Locate the second delimiter
|
||||
const char* s2 = strchr(s1 + 1, ' ');
|
||||
const char *s2 = strchr(s1 + 1, ' ');
|
||||
if (s2 != 0) {
|
||||
igrid4 = packgrid(s2 + 1);
|
||||
} else {
|
||||
|
@ -200,9 +200,9 @@ int pack77_1(const char* msg, uint8_t* b77)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void packtext77(const char* text, uint8_t* b77)
|
||||
static void packtext77(const char *text, uint8_t *b77)
|
||||
{
|
||||
int length = strlen(text);
|
||||
size_t length = strlen(text);
|
||||
|
||||
// Skip leading and trailing spaces
|
||||
while (*text == ' ' && *text != 0) {
|
||||
|
@ -255,7 +255,7 @@ void packtext77(const char* text, uint8_t* b77)
|
|||
b77[9] &= 0x00;
|
||||
}
|
||||
|
||||
int pack77(const char* msg, uint8_t* c77)
|
||||
int pack77(const char *msg, uint8_t *c77)
|
||||
{
|
||||
// Check Type 1 (Standard 77-bit message) or Type 2, with optional "/P"
|
||||
if (0 == pack77_1(msg, c77)) {
|
||||
|
|
|
@ -6,6 +6,6 @@
|
|||
// Pack FT8 text message into 72 bits
|
||||
// [IN] msg - FT8 message (e.g. "CQ TE5T KN01")
|
||||
// [OUT] c77 - 10 byte array to store the 77 bit payload (MSB first)
|
||||
int pack77(const char* msg, uint8_t* c77);
|
||||
int pack77(const char *msg, uint8_t *c77);
|
||||
|
||||
#endif // _INCLUDE_PACK_H_
|
||||
|
|
22
ft8/text.c
22
ft8/text.c
|
@ -2,7 +2,7 @@
|
|||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
|
||||
const char* trim_front(const char* str)
|
||||
const char *trim_front(const char *str)
|
||||
{
|
||||
// Skip leading whitespace
|
||||
while (*str == ' ') {
|
||||
|
@ -11,7 +11,7 @@ const char* trim_front(const char* str)
|
|||
return str;
|
||||
}
|
||||
|
||||
void trim_back(char* str)
|
||||
void trim_back(char *str)
|
||||
{
|
||||
// Skip trailing whitespace by replacing it with '\0' characters
|
||||
size_t idx = strlen(str) - 1;
|
||||
|
@ -22,7 +22,7 @@ void trim_back(char* str)
|
|||
|
||||
// 1) trims a string from the back by changing whitespaces to '\0'
|
||||
// 2) trims a string from the front by skipping whitespaces
|
||||
char* trim(char* str)
|
||||
char *trim(char *str)
|
||||
{
|
||||
str = (char*)trim_front(str);
|
||||
trim_back(str);
|
||||
|
@ -30,11 +30,17 @@ char* trim(char* str)
|
|||
return str;
|
||||
}
|
||||
|
||||
bool in_range(char c, char min, char max) { return (c >= min) && (c <= max); }
|
||||
bool in_range(char c, char min, char max)
|
||||
{
|
||||
return c >= min && c <= max;
|
||||
}
|
||||
|
||||
bool starts_with(const char* string, const char* prefix) { return 0 == memcmp(string, prefix, strlen(prefix)); }
|
||||
bool starts_with(const char *string, const char *prefix)
|
||||
{
|
||||
return memcmp(string, prefix, strlen(prefix)) == 0;
|
||||
}
|
||||
|
||||
int char_index(const char* string, char c)
|
||||
int char_index(const char *string, char c)
|
||||
{
|
||||
for (int i = 0; *string; ++i, ++string) {
|
||||
if (c == *string) {
|
||||
|
@ -45,7 +51,7 @@ int char_index(const char* string, char c)
|
|||
}
|
||||
|
||||
// Parse a 2 digit integer from string
|
||||
int dd_to_int(const char* str, int length)
|
||||
int dd_to_int(const char *str, int length)
|
||||
{
|
||||
int result = 0;
|
||||
bool negative;
|
||||
|
@ -72,7 +78,7 @@ int dd_to_int(const char* str, int length)
|
|||
}
|
||||
|
||||
// Convert a 2 digit integer to string
|
||||
void int_to_dd(char* str, int value, int width, bool full_sign)
|
||||
void int_to_dd(char *str, int value, int width, bool full_sign)
|
||||
{
|
||||
if (value < 0) {
|
||||
*str = '-';
|
||||
|
|
10
ft8/text.h
10
ft8/text.h
|
@ -6,20 +6,20 @@
|
|||
|
||||
// Utility functions for characters and strings
|
||||
|
||||
const char *trim_front(const char* str);
|
||||
const char *trim_front(const char *str);
|
||||
void trim_back(char *str);
|
||||
char *trim(char *str);
|
||||
|
||||
bool in_range(char c, char min, char max);
|
||||
bool starts_with(const char* string, const char* prefix);
|
||||
bool starts_with(const char *string, const char *prefix);
|
||||
|
||||
int char_index(const char* string, char c);
|
||||
int char_index(const char *string, char c);
|
||||
|
||||
// Parse a 2 digit integer from string
|
||||
int dd_to_int(const char* str, int length);
|
||||
int dd_to_int(const char *str, int length);
|
||||
|
||||
// Convert a 2 digit integer to string
|
||||
void int_to_dd(char* str, int value, int width, bool full_sign);
|
||||
void int_to_dd(char *str, int value, int width, bool full_sign);
|
||||
|
||||
char charn(int c, int table_idx);
|
||||
int nchar(char c, int table_idx);
|
||||
|
|
26
ft8/unpack.c
26
ft8/unpack.c
|
@ -9,7 +9,7 @@
|
|||
|
||||
// n28 is a 28-bit integer, e.g. n28a or n28b, containing all the
|
||||
// call sign bits from a packed message.
|
||||
int unpack_callsign(uint32_t n28, uint8_t ip, uint8_t i3, char* result)
|
||||
static int unpack_callsign(uint32_t n28, uint8_t ip, uint8_t i3, char *result)
|
||||
{
|
||||
// Check for special tokens DE, QRZ, CQ, CQ_nnn, CQ_aaaa
|
||||
if (n28 < NTOKENS) {
|
||||
|
@ -34,7 +34,7 @@ int unpack_callsign(uint32_t n28, uint8_t ip, uint8_t i3, char* result)
|
|||
char aaaa[5];
|
||||
|
||||
aaaa[4] = '\0';
|
||||
for (int i = 3; /* */; --i) {
|
||||
for (int i = 3;; --i) {
|
||||
aaaa[i] = charn(n % 27, 4);
|
||||
if (i == 0)
|
||||
break;
|
||||
|
@ -95,7 +95,7 @@ int unpack_callsign(uint32_t n28, uint8_t ip, uint8_t i3, char* result)
|
|||
return 0; // Success
|
||||
}
|
||||
|
||||
int unpack_type1(const uint8_t* a77, uint8_t i3, char* call_to, char* call_de, char* extra)
|
||||
static int unpack_type1(const uint8_t *a77, uint8_t i3, char *call_to, char *call_de, char *extra)
|
||||
{
|
||||
uint32_t n28a, n28b;
|
||||
uint16_t igrid4;
|
||||
|
@ -133,7 +133,7 @@ int unpack_type1(const uint8_t* a77, uint8_t i3, char* call_to, char* call_de, c
|
|||
// save_hash_call(call_de)
|
||||
// }
|
||||
|
||||
char* dst = extra;
|
||||
char *dst = extra;
|
||||
|
||||
if (igrid4 <= MAXGRID4) {
|
||||
// Extract 4 symbol grid locator
|
||||
|
@ -184,7 +184,7 @@ int unpack_type1(const uint8_t* a77, uint8_t i3, char* call_to, char* call_de, c
|
|||
return 0; // Success
|
||||
}
|
||||
|
||||
int unpack_text(const uint8_t* a71, char* text)
|
||||
static int unpack_text(const uint8_t *a71, char *text)
|
||||
{
|
||||
// TODO: test
|
||||
uint8_t b71[9];
|
||||
|
@ -213,7 +213,7 @@ int unpack_text(const uint8_t* a71, char* text)
|
|||
return 0; // Success
|
||||
}
|
||||
|
||||
int unpack_telemetry(const uint8_t* a71, char* telemetry)
|
||||
static int unpack_telemetry(const uint8_t *a71, char *telemetry)
|
||||
{
|
||||
uint8_t b71[9];
|
||||
|
||||
|
@ -240,7 +240,7 @@ int unpack_telemetry(const uint8_t* a71, char* telemetry)
|
|||
|
||||
// none standard for wsjt-x 2.0
|
||||
// by KD8CEC
|
||||
int unpack_nonstandard(const uint8_t* a77, char* call_to, char* call_de, char* extra)
|
||||
static int unpack_nonstandard(const uint8_t *a77, char *call_to, char *call_de, char *extra)
|
||||
{
|
||||
uint32_t n12, iflip, nrpt, icq;
|
||||
uint64_t n58;
|
||||
|
@ -264,7 +264,7 @@ int unpack_nonstandard(const uint8_t* a77, char* call_to, char* call_de, char* e
|
|||
char c11[12];
|
||||
c11[11] = '\0';
|
||||
|
||||
for (int i = 10; /* no condition */; --i) {
|
||||
for (int i = 10;; --i) {
|
||||
c11[i] = charn(n58 % 38, 5);
|
||||
if (i == 0)
|
||||
break;
|
||||
|
@ -279,8 +279,8 @@ int unpack_nonstandard(const uint8_t* a77, char* call_to, char* call_de, char* e
|
|||
// call_3[5] = '>';
|
||||
// call_3[6] = '\0';
|
||||
|
||||
char* call_1 = (iflip) ? c11 : call_3;
|
||||
char* call_2 = (iflip) ? call_3 : c11;
|
||||
char *call_1 = (iflip) ? c11 : call_3;
|
||||
char *call_2 = (iflip) ? call_3 : c11;
|
||||
// save_hash_call(c11_trimmed);
|
||||
|
||||
if (icq == 0) {
|
||||
|
@ -303,7 +303,7 @@ int unpack_nonstandard(const uint8_t* a77, char* call_to, char* call_de, char* e
|
|||
return 0;
|
||||
}
|
||||
|
||||
int unpack77_fields(const uint8_t* a77, char* call_to, char* call_de, char* extra)
|
||||
static int unpack77_fields(const uint8_t *a77, char *call_to, char *call_de, char *extra)
|
||||
{
|
||||
call_to[0] = call_de[0] = extra[0] = '\0';
|
||||
|
||||
|
@ -353,7 +353,7 @@ int unpack77_fields(const uint8_t* a77, char* call_to, char* call_de, char* extr
|
|||
return -1;
|
||||
}
|
||||
|
||||
int unpack77(const uint8_t* a77, char* message)
|
||||
int unpack77(const uint8_t *a77, char *message)
|
||||
{
|
||||
char call_to[14];
|
||||
char call_de[14];
|
||||
|
@ -364,7 +364,7 @@ int unpack77(const uint8_t* a77, char* message)
|
|||
return rc;
|
||||
|
||||
// int msg_sz = strlen(call_to) + strlen(call_de) + strlen(extra) + 2;
|
||||
char* dst = message;
|
||||
char *dst = message;
|
||||
|
||||
dst[0] = '\0';
|
||||
|
||||
|
|
|
@ -3,12 +3,7 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
// field1 - at least 14 bytes
|
||||
// field2 - at least 14 bytes
|
||||
// field3 - at least 7 bytes
|
||||
int unpack77_fields(const uint8_t* a77, char* field1, char* field2, char* field3);
|
||||
|
||||
// message should have at least 35 bytes allocated (34 characters + zero terminator)
|
||||
int unpack77(const uint8_t* a77, char* message);
|
||||
int unpack77(const uint8_t *a77, char *message);
|
||||
|
||||
#endif // _INCLUDE_UNPACK_H_
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#define FT4_SLOT_TIME 6.0f // total length of output waveform in seconds
|
||||
#define FT8_SLOT_TIME 15.0f // total length of output waveform in seconds
|
||||
|
||||
int main(int argc, char** argv)
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int sample_rate = 8000;
|
||||
|
||||
|
|
20
looptest.c
20
looptest.c
|
@ -6,10 +6,6 @@
|
|||
|
||||
#include "ft8.h"
|
||||
|
||||
#warning remove again
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define FT4_SLOT_TIME 6.0f // total length of output waveform in seconds
|
||||
#define FT8_SLOT_TIME 15.0f // total length of output waveform in seconds
|
||||
|
||||
|
@ -24,7 +20,7 @@ struct context {
|
|||
float frequency;
|
||||
};
|
||||
|
||||
static char* random_callsign(char* callsign)
|
||||
static char *random_callsign(char *callsign)
|
||||
{
|
||||
int x = rand();
|
||||
switch (x >> 29) {
|
||||
|
@ -44,14 +40,14 @@ static char* random_callsign(char* callsign)
|
|||
return callsign;
|
||||
}
|
||||
|
||||
static char* random_locator(char* locator)
|
||||
static char *random_locator(char *locator)
|
||||
{
|
||||
int x = rand();
|
||||
sprintf(locator, "%c%c%d%d", 'A' + RP(x, 1, 18), 'A' + RP(x, 18, 18), RP(x, 180, 10), RP(x, 1800, 10));
|
||||
return locator;
|
||||
}
|
||||
|
||||
static char* random_message(char* message)
|
||||
static char *random_message(char *message)
|
||||
{
|
||||
int x = rand();
|
||||
char callsign1[8], callsign2[8], locator[5];
|
||||
|
@ -79,14 +75,14 @@ static char* random_message(char* message)
|
|||
}
|
||||
|
||||
// decode callback, called by ft8_decode() for each decoded message
|
||||
static void ft8_decode_callback(char* message, float frequency, float time_dev, float snr, int score, void* ctx)
|
||||
static void ft8_decode_callback(char *message, float frequency, float time_dev, float snr, int score, void *ctx)
|
||||
{
|
||||
struct context* context = ctx;
|
||||
struct context *context = ctx;
|
||||
bool ok = strcmp(context->message, message) == 0;
|
||||
printf("%-8s000000 %3d %+4.2f %4.0f ~ %s (%s)\n", ok ? "OK" : "ERROR", score, time_dev, frequency, message, context->message);
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int iterations = 1000;
|
||||
int sample_rate = 8000;
|
||||
|
@ -110,9 +106,9 @@ int main(int argc, char* argv[])
|
|||
random_message(ctx.message);
|
||||
ctx.frequency = frequency;
|
||||
|
||||
if (ftx_encode(ctx.message, signal, num_samples, frequency, sample_rate, protocol) == 0) {
|
||||
if (ftx_encode(ctx.message, signal, num_samples, 200.0 + rand() % 3000, sample_rate, protocol) == 0) {
|
||||
// add noise
|
||||
for (float* fp = signal; fp < signal + num_samples; fp++) {
|
||||
for (float *fp = signal; fp < signal + num_samples; fp++) {
|
||||
*fp = (*fp + 2.0 * NOISE_AMPLITUDE * rand() / RAND_MAX - NOISE_AMPLITUDE) / (1.0 + NOISE_AMPLITUDE);
|
||||
}
|
||||
r = ftx_decode(signal, num_samples, sample_rate, protocol, ft8_decode_callback, &ctx);
|
||||
|
|
Ładowanie…
Reference in New Issue