Skip to content

Commit

Permalink
Merge branch 'dsssframe64-dev'
Browse files Browse the repository at this point in the history
  • Loading branch information
jgaeddert committed Mar 17, 2024
2 parents e78ced9 + f8a3418 commit 011cbad
Show file tree
Hide file tree
Showing 7 changed files with 950 additions and 0 deletions.
97 changes: 97 additions & 0 deletions examples/dsssframe64sync_example.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
// This example demonstrates the basic interface to the dsssframe64gen and
// dsssframe64sync objects.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <time.h>
#include <getopt.h>
#include <assert.h>

#include "liquid.h"

// static callback function
static int callback(unsigned char * _header,
int _header_valid,
unsigned char * _payload,
unsigned int _payload_len,
int _payload_valid,
framesyncstats_s _stats,
void * _context)
{
printf("*** callback invoked (%s) ***\n", _payload_valid ? "pass" : "FAIL");
framesyncstats_print(&_stats);

// save recovered symbols to file
unsigned int i;
FILE * fid = (FILE*)_context;
for (i=0; i<_stats.num_framesyms; i++) {
fprintf(fid,"s(%3u) = %12.8f + %12.8fj;\n", i+1,
crealf(_stats.framesyms[i]), cimagf(_stats.framesyms[i]));
}
return 0;
}

int main(int argc, char *argv[])
{
// options
unsigned int nfft = 2400;
float SNRdB = -10.0f;
const char * filename = "dsssframe64sync_example.m";

// create dsssframe64gen object
dsssframe64gen fg = dsssframe64gen_create();

// generate the frame in blocks
unsigned int buf_len = dsssframe64gen_get_frame_len(fg);
float complex * buf_tx = (float complex *)malloc(buf_len*sizeof(float complex));
float complex * buf_rx = (float complex *)malloc(buf_len*sizeof(float complex));

// export results to file
FILE * fid = fopen(filename,"w");
fprintf(fid,"%% %s : auto-generated file\n", filename);
fprintf(fid,"clear all; close all;\n");
fprintf(fid,"s=[];\n");

// generate in one step (for now)
dsssframe64gen_execute(fg, NULL, NULL, buf_tx);

// apply channel (AWGN)
float nstd = powf(10.0f,-SNRdB/20.0f);
unsigned int i;
for (i=0; i<buf_len; i++)
buf_rx[i] = buf_tx[i]*M_SQRT1_2 + nstd*(randnf() + _Complex_I*randnf())/M_SQRT2;

// run through sync
dsssframe64sync fs = dsssframe64sync_create(callback, (void*)fid);
dsssframe64sync_execute(fs, buf_rx, buf_len);
dsssframe64sync_destroy(fs);

// push resulting sample through periodogram
spgramcf periodogram = spgramcf_create_default(nfft);
spgramcf_write(periodogram, buf_rx, buf_len);
float psd[nfft];
spgramcf_get_psd(periodogram, psd);
spgramcf_destroy(periodogram);

// plot results
fprintf(fid,"nfft=%u; Y=zeros(1,nfft);\n", nfft);
for (i=0; i<nfft; i++)
fprintf(fid,"Y(%4u) = %12.8f;\n", i+1, psd[i]);
fprintf(fid,"figure('position',[100 100 1200 400]);\n");
fprintf(fid,"subplot(1,5,1:3);\n");
fprintf(fid," f=[0:(nfft-1)]/nfft-0.5; plot(f,Y); xlim([-0.5 0.5]); grid on;\n");
fprintf(fid," xlabel('Normalized Frequency [f/Fs]'); ylabel('PSD [dB]');\n");
fprintf(fid,"subplot(1,5,4:5);\n");
fprintf(fid," plot(real(s),imag(s),'.','MarkerSize',6); grid on; axis([-1 1 -1 1]*1.5)\n");
fprintf(fid," axis('square'); xlabel('I'); ylabel('Q');\n");
fclose(fid);
printf("results written to %s\n", filename);

// destroy allocated objects and free memory
dsssframe64gen_destroy(fg);
free(buf_tx);
free(buf_rx);
return 0;
}

101 changes: 101 additions & 0 deletions examples/dsssframe64sync_performance_example.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
// This example tests the performance for detecting and decoding frames
// with the dsssframe64gen and dsssframe64sync objects.
// SEE ALSO: dsssframe64sync_example.c
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "liquid.h"
#define OUTPUT_FILENAME "dsssframe64sync_performance_example.m"

// add noise to channel
void frame64_add_noise(float complex * _buf,
unsigned int _buf_len, float _SNRdB)
{
float nstd = powf(10.0f, -_SNRdB/20.0f);
nstd *= M_SQRT2; // scale noise to account for signal being over-sampled by 2
unsigned int i;
for (i=0; i<_buf_len; i++)
_buf[i] += nstd*( randnf() + _Complex_I*randnf() ) * M_SQRT1_2;
}

int main(int argc, char*argv[])
{
// create frame generator, synchronizer objects
dsssframe64gen fg = dsssframe64gen_create();
dsssframe64sync fs = dsssframe64sync_create(NULL,NULL);
unsigned int min_errors = 5;
unsigned int min_trials = 80;
unsigned int max_trials = 1000;

// create buffer for the frame samples
unsigned int frame_len = dsssframe64gen_get_frame_len(fg);
float complex * frame = (float complex *)malloc(frame_len*sizeof(float complex));
float SNRdB = -25.0f;
FILE* fid = fopen(OUTPUT_FILENAME, "w");
fprintf(fid,"%% %s: auto-generated file\n", OUTPUT_FILENAME);
fprintf(fid,"clear all; close all;\n");
fprintf(fid,"SNR=[]; pdetect=[]; pvalid=[];\n");
printf("# %8s %6s (%7s) %6s (%7s) %6s\n", "SNR", "missed", "percent", "errors", "percent", "trials");
fclose(fid);
while (SNRdB < -5.0f) {
dsssframe64sync_reset_framedatastats(fs);
unsigned int num_trials = 0, num_errors = 0;
while (1) {
unsigned int i;
for (i=0; i<min_trials; i++) {
// reset frame synchronizer
dsssframe64sync_reset(fs);

// generate the frame with random header and payload
dsssframe64gen_execute(fg, NULL, NULL, frame);

// add channel effects
frame64_add_noise(frame, frame_len, SNRdB);

// synchronize/receive the frame
dsssframe64sync_execute(fs, frame, frame_len);
}
num_trials += min_trials;
num_errors = num_trials - dsssframe64sync_get_framedatastats(fs).num_payloads_valid;
if (num_errors >= min_errors)
break;
if (num_trials >= max_trials)
break;
}
// print results
framedatastats_s stats = dsssframe64sync_get_framedatastats(fs);
unsigned int num_misses = num_trials - stats.num_frames_detected;
float pmd = (float) num_misses / (float) num_trials;
float per = (float) num_errors / (float) num_trials;
printf(" %8.3f %6u (%6.2f%%) %6u (%6.2f%%) %6u\n",
SNRdB,num_misses,pmd*100,num_errors,per*100,num_trials);
fid = fopen(OUTPUT_FILENAME,"a");
fprintf(fid,"SNR(end+1)=%g; pdetect(end+1)=%12g; pvalid(end+1)=%12g;\n",
SNRdB,
(float)stats.num_frames_detected / (float)num_trials,
(float)stats.num_payloads_valid / (float)num_trials);
fclose(fid);
if (num_errors < min_errors)
break;
SNRdB += 1.0f;
}
fid = fopen(OUTPUT_FILENAME,"a");
fprintf(fid,"figure;\n");
fprintf(fid,"hold on;\n");
fprintf(fid," semilogy(SNR, 1-pdetect+eps,'-o', 'LineWidth',2, 'MarkerSize',2);\n");
fprintf(fid," semilogy(SNR, 1-pvalid +eps,'-o', 'LineWidth',2, 'MarkerSize',2);\n");
fprintf(fid,"hold off;\n");
fprintf(fid,"xlabel('SNR [dB]');\n");
fprintf(fid,"ylabel('Prob. of Error');\n");
fprintf(fid,"legend('detect','decoding','location','northeast');\n");
fprintf(fid,"axis([-30 10 1e-3 1]);\n");
fprintf(fid,"grid on;\n");
fclose(fid);
printf("results written to %s\n", OUTPUT_FILENAME);

// clean up allocated objects and memory blocks
dsssframe64gen_destroy(fg);
dsssframe64sync_destroy(fs);
free(frame);
return 0;
}
77 changes: 77 additions & 0 deletions include/liquid.h
Original file line number Diff line number Diff line change
Expand Up @@ -5993,6 +5993,83 @@ int dsssframesync_debug_disable (dsssframesync _q);
int dsssframesync_debug_print (dsssframesync _q, const char * _filename);
framedatastats_s dsssframesync_get_framedatastats (dsssframesync _q);

//
// Direct sequence/spread spectrum framing with fixed 64-byte payload
//

// frame generator object type
typedef struct dsssframe64gen_s * dsssframe64gen;

// create dsssframe64gen object
dsssframe64gen dsssframe64gen_create();

// copy object
dsssframe64gen dsssframe64gen_copy(dsssframe64gen q_orig);

// destroy dsssframe64gen object
int dsssframe64gen_destroy(dsssframe64gen _q);

// print dsssframe64gen object internals
int dsssframe64gen_print(dsssframe64gen _q);

// get length of assembled frame (samples)
unsigned int dsssframe64gen_get_frame_len(dsssframe64gen _q);

// generate a frame
// _q : frame generator object
// _header : 8-byte header data, NULL for random
// _payload : 64-byte payload data, NULL for random
// _frame : output frame samples, [size: dsssframegen64gen_get_frame_len() x 1]
int dsssframe64gen_execute(dsssframe64gen _q,
const unsigned char * _header,
const unsigned char * _payload,
liquid_float_complex * _buf);

// get full frame length [samples]
unsigned int dsssframe64gen_get_frame_len(dsssframe64gen _q);

// frame synchronizer object type
typedef struct dsssframe64sync_s * dsssframe64sync;

dsssframe64sync dsssframe64sync_create(framesync_callback _callback, void * _userdata);

// copy object
dsssframe64sync dsssframe64sync_copy(dsssframe64sync q_orig);

int dsssframe64sync_destroy (dsssframe64sync _q);
int dsssframe64sync_print (dsssframe64sync _q);
int dsssframe64sync_reset (dsssframe64sync _q);
int dsssframe64sync_is_frame_open (dsssframe64sync _q);
int dsssframe64sync_set_callback(dsssframe64sync _q,
framesync_callback _callback);
int dsssframe64sync_set_context(dsssframe64sync _q,
void * _context);
// execute frame synchronizer
// _q : frame synchronizer object
// _buf : input sample array, shape: (_buf_len,)
// _buf_len : number of input samples
int dsssframe64sync_execute(dsssframe64sync _q, liquid_float_complex * _buf, unsigned int _buf_len);

// get detection threshold
float dsssframe64sync_get_threshold(dsssframe64sync _q);

// set detection threshold
int dsssframe64sync_set_threshold(dsssframe64sync _q,
float _threshold);

// get carrier offset search range [radians/sample]
float dsssframe64sync_get_range(dsssframe64sync _q);

// set carrier offset search range
int dsssframe64sync_set_range(dsssframe64sync _q,
float _dphi_max);

// reset frame data statistics
int dsssframe64sync_reset_framedatastats(dsssframe64sync _q);

// retrieve frame data statistics
framedatastats_s dsssframe64sync_get_framedatastats(dsssframe64sync _q);

//
// OFDM flexframe generator
//
Expand Down
5 changes: 5 additions & 0 deletions makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -632,6 +632,8 @@ framing_objects := \
src/framing/src/bpacketgen.o \
src/framing/src/bpacketsync.o \
src/framing/src/detector_cccf.o \
src/framing/src/dsssframe64gen.o \
src/framing/src/dsssframe64sync.o \
src/framing/src/dsssframegen.o \
src/framing/src/dsssframesync.o \
src/framing/src/framedatastats.o \
Expand Down Expand Up @@ -680,6 +682,7 @@ framing_autotests := \
src/framing/tests/bpacketsync_autotest.c \
src/framing/tests/bsync_autotest.c \
src/framing/tests/detector_autotest.c \
src/framing/tests/dsssframe64_autotest.c \
src/framing/tests/dsssframesync_autotest.c \
src/framing/tests/flexframesync_autotest.c \
src/framing/tests/framesync64_autotest.c \
Expand Down Expand Up @@ -1514,6 +1517,8 @@ example_programs := \
examples/cvsd_example \
examples/detector_cccf_example \
examples/dds_cccf_example \
examples/dsssframe64sync_performance_example \
examples/dsssframe64sync_example \
examples/dsssframesync_example \
examples/dotprod_rrrf_example \
examples/dotprod_cccf_example \
Expand Down
Loading

0 comments on commit 011cbad

Please sign in to comment.