1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
|
// This example demonstrates the performance of the qpacket modem
// object to combine forward error-correction and modulation in one
// simple interface.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <time.h>
#include <getopt.h>
#include <assert.h>
#include "liquid.h"
#define OUTPUT_FILENAME "qpacketmodem_performance_example.m"
void usage()
{
printf("qpacketmodem_performance_example [options]\n");
printf(" -h : print usage\n");
printf(" -p : payload length [bytes], default: 400\n");
printf(" -m : modulation scheme (qpsk default)\n");
liquid_print_modulation_schemes();
printf(" -v : data integrity check: crc32 default\n");
liquid_print_crc_schemes();
printf(" -c : coding scheme (inner): g2412 default\n");
printf(" -k : coding scheme (outer): none default\n");
liquid_print_fec_schemes();
printf(" -s : SNR start [dB], default: -5\n");
printf(" -x : SNR max [dB], default: 20\n");
printf(" -d : SNR step [dB], default: 0.5\n");
printf(" -e : minimum number of packet errors per step, default: 50\n");
printf(" -t : minimum number of packet trials per step, default: 2000\n");
printf(" -T : maximum number of packet trials per step, default: 40000\n");
}
int main(int argc, char *argv[])
{
// options (defaults to frame64 parameters)
modulation_scheme ms = LIQUID_MODEM_QPSK; // mod. scheme
crc_scheme check = LIQUID_CRC_24; // data validity check
fec_scheme fec0 = LIQUID_FEC_NONE; // fec (inner)
fec_scheme fec1 = LIQUID_FEC_GOLAY2412; // fec (outer)
unsigned int payload_len = 72; // payload length
float SNRdB_min = -5.0f; // signal-to-noise ratio (minimum)
float SNRdB_max = 20.0f; // signal-to-noise ratio (maximum)
float SNRdB_step = 0.5f; // signal-to-noise ratio (maximum)
unsigned int min_packet_errors = 50; // minimum errors to observe for each step
unsigned int min_packet_trials = 2000; // minimum number of packets for each step
unsigned int max_packet_trials =40000; // maximum number of packets for each step
// get options
int dopt;
while((dopt = getopt(argc,argv,"hp:m:v:c:k:s:x:d:e:t:T:")) != EOF){
switch (dopt) {
case 'h': usage(); return 0;
case 'p': payload_len = atol(optarg); break;
case 'm': ms = liquid_getopt_str2mod(optarg); break;
case 'v': check = liquid_getopt_str2crc(optarg); break;
case 'c': fec0 = liquid_getopt_str2fec(optarg); break;
case 'k': fec1 = liquid_getopt_str2fec(optarg); break;
case 's': SNRdB_min = atof(optarg); break;
case 'x': SNRdB_max = atof(optarg); break;
case 'd': SNRdB_step = atof(optarg); break;
case 'e': min_packet_errors = atoi(optarg); break;
case 't': min_packet_trials = atoi(optarg); break;
case 'T': max_packet_trials = atoi(optarg); break;
default:
exit(-1);
}
}
unsigned int i;
// create and configure packet encoder/decoder object
qpacketmodem q = qpacketmodem_create();
qpacketmodem_configure(q, payload_len, check, fec0, fec1, ms);
qpacketmodem_print(q);
// get frame length
unsigned int frame_len = qpacketmodem_get_frame_len(q);
// initialize payload
unsigned char payload_tx [payload_len]; // payload (transmitted)
unsigned char payload_rx [payload_len]; // payload (received)
float complex frame_tx [frame_len]; // frame samples (transmitted)
float complex frame_rx [frame_len]; // frame samples (received)
// output file
FILE* fid = fopen(OUTPUT_FILENAME, "w");
fprintf(fid,"%% %s: auto-generated file\n", OUTPUT_FILENAME);
fprintf(fid,"clear all; close all; SNR=[]; ber=[]; per=[];\n");
printf(" %8s %8s %8s %12s %8s %8s %6s\n",
"SNR [dB]", "errors", "bits", "BER", "errors", "packets", "PER");
float SNRdB = SNRdB_min;
while (SNRdB < SNRdB_max) {
// reset counters
float nstd = powf(10.0f, -SNRdB/20.0f); // noise standard deviation
unsigned int num_packet_trials = 0, num_packet_errors = 0;
unsigned int num_bit_trials = 0, num_bit_errors = 0;
while (1) {
// initialize payload
for (i=0; i<payload_len; i++) {
payload_tx[i] = rand() & 0xff;
payload_rx[i] = 0x00;
}
// encode frame
qpacketmodem_encode(q, payload_tx, frame_tx);
// add noise
for (i=0; i<frame_len; i++)
frame_rx[i] = frame_tx[i] + nstd*(randnf() + _Complex_I*randnf())*M_SQRT1_2;
// decode frame
int crc_pass = qpacketmodem_decode(q, frame_rx, payload_rx);
// accumulate errors
num_bit_errors += count_bit_errors_array(payload_tx, payload_rx, payload_len);
num_packet_errors += crc_pass ? 0 : 1;
num_packet_trials += 1;
num_bit_trials += 8*payload_len;
if (num_packet_trials < min_packet_trials)
continue;
if (num_packet_errors >= min_packet_errors)
break;
if (num_packet_trials >= max_packet_trials)
break;
}
float BER = (float)num_bit_errors / (float)num_bit_trials;
float PER = (float)num_packet_errors / (float)num_packet_trials;
printf(" %8.2f %8u %8u %12.4e %8u %8u %6.2f%%\n",
SNRdB,
num_bit_errors, num_bit_trials, BER,
num_packet_errors, num_packet_trials, PER*100.0f);
fprintf(fid,"SNR(end+1)=%g; ber(end+1)=%g; per(end+1)=%g;\n", SNRdB, BER, PER);
if (num_packet_errors < min_packet_errors)
break;
SNRdB += SNRdB_step;
}
// destroy allocated objects
qpacketmodem_destroy(q);
fprintf(fid,"figure('position',[100 100 500 720]);\n");
fprintf(fid,"subplot(2,1,1);\n");
fprintf(fid," gamma = 10.^(SNR/10);\n");
fprintf(fid," ber_qpsk = 0.5*(1 - erf(sqrt(gamma)/sqrt(2)));\n");
fprintf(fid," hold on;\n");
fprintf(fid," semilogy(SNR, ber, '-o', 'LineWidth',2, 'MarkerSize',2);\n");
fprintf(fid," semilogy(SNR, ber_qpsk,'-o', 'LineWidth',2, 'MarkerSize',2);\n");
fprintf(fid," hold off;\n");
fprintf(fid," xlabel('SNR [dB]');\n");
fprintf(fid," ylabel('Bit Error Rate');\n");
fprintf(fid," axis([%f SNR(end)+5 1e-6 1]);\n", SNRdB_min);
fprintf(fid," grid on;\n");
fprintf(fid," legend('Measured','Uncoded QPSK','location','southwest');\n");
fprintf(fid,"subplot(2,1,2);\n");
fprintf(fid," semilogy(SNR, per,'-o', 'LineWidth',2, 'MarkerSize',2);\n");
fprintf(fid," xlabel('SNR [dB]');\n");
fprintf(fid," ylabel('Packet Error Rate');\n");
fprintf(fid," axis([%f SNR(end)+5 1e-3 1]);\n", SNRdB_min);
fprintf(fid," grid on;\n");
fclose(fid);
printf("results written to %s\n", OUTPUT_FILENAME);
printf("done.\n");
return 0;
}
|