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
|
// Demonstrate using qpilotsync for carrier recovery.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <time.h>
#include <getopt.h>
#include <assert.h>
#include "liquid.h"
void usage()
{
printf("%s [options]\n", __FILE__);
printf(" h : print usage\n");
printf(" n : payload length [symbols], default: 400\n");
printf(" p : pilot spacing [symbols], default: 20\n");
printf(" s : SNR [dB], default: 20\n");
printf(" m : modulation scheme, default: qam16\n");
liquid_print_modulation_schemes();
}
int main(int argc, char *argv[])
{
//srand( time(NULL) );
// options
int ms = LIQUID_MODEM_QAM16; // mod. scheme
unsigned int payload_len = 400; // payload length
unsigned int pilot_spacing = 20; // pilot spacing
float SNRdB = 20.0f; // signal-to-noise ratio [dB]
const char filename[] = "qpilotsync_example.m"; // output filename
float dphi = -0.0075f; // carrier frequency offset
float phi = 2.1800f; // carrier phase offset
float gain = 0.5f; // channel gain
// get options
int dopt;
while((dopt = getopt(argc,argv,"hn:p:s:m:")) != EOF){
switch (dopt) {
case 'h': usage(); return 0;
case 'n': payload_len = atoi(optarg); break;
case 'p': pilot_spacing = atoi(optarg); break;
case 's': SNRdB = atof(optarg); break;
case 'm': ms = liquid_getopt_str2mod(optarg); break;
default:
exit(-1);
}
}
unsigned int i;
// derived values
float nstd = powf(10.0f, -SNRdB/20.0f);
// create pilot generator and synchronizer objects
qpilotgen pg = qpilotgen_create( payload_len, pilot_spacing);
qpilotsync ps = qpilotsync_create(payload_len, pilot_spacing);
qpilotgen_print(pg);
// get frame length
unsigned int frame_len = qpilotgen_get_frame_len(pg);
// allocate arrays
unsigned char payload_sym_tx[payload_len]; // transmitted payload symbols
float complex payload_tx [payload_len]; // transmitted payload samples
float complex frame_tx [frame_len]; // transmitted frame samples
float complex frame_rx [frame_len]; // received frame samples
float complex payload_rx [payload_len]; // received payload samples
unsigned char payload_sym_rx[payload_len]; // received payload symbols
// create modem objects for payload
modemcf mod = modemcf_create(ms);
modemcf dem = modemcf_create(ms);
// assemble payload symbols
for (i=0; i<payload_len; i++) {
// generate random symbol
payload_sym_tx[i] = modemcf_gen_rand_sym(mod);
// modulate
modemcf_modulate(mod, payload_sym_tx[i], &payload_tx[i]);
}
// assemble frame
qpilotgen_execute(pg, payload_tx, frame_tx);
// add channel impairments
for (i=0; i<frame_len; i++) {
frame_rx[i] = frame_tx[i] * cexpf(_Complex_I*dphi*i + _Complex_I*phi);
frame_rx[i] += nstd*(randnf() + _Complex_I*randnf())*M_SQRT1_2;
frame_rx[i] *= gain;
}
// receive frame
qpilotsync_execute(ps, frame_rx, payload_rx);
// demodulate
for (i=0; i<payload_len; i++) {
unsigned int sym_demod;
modemcf_demodulate(dem, payload_rx[i], &sym_demod);
payload_sym_rx[i] = (unsigned char)sym_demod;
}
// count errors
unsigned int bit_errors = 0;
for (i=0; i<payload_len; i++)
bit_errors += count_bit_errors(payload_sym_rx[i], payload_sym_tx[i]);
printf("received bit errors : %u / %u\n", bit_errors, payload_len * modemcf_get_bps(mod));
// destroy allocated objects
qpilotgen_destroy(pg);
qpilotsync_destroy(ps);
modemcf_destroy(mod);
modemcf_destroy(dem);
// write symbols to output file for plotting
FILE * fid = fopen(filename,"w");
if (!fid) {
fprintf(stderr,"error: could not open '%s' for writing\n", filename);
return -1;
}
fprintf(fid,"%% %s : auto-generated file\n", filename);
fprintf(fid,"clear all;\n");
fprintf(fid,"close all;\n");
fprintf(fid,"payload_len = %u;\n", payload_len);
fprintf(fid,"frame_len = %u;\n", frame_len);
fprintf(fid,"frame_tx = zeros(1,frame_len);\n");
fprintf(fid,"payload_rx = zeros(1,payload_len);\n");
for (i=0; i<frame_len; i++)
fprintf(fid,"frame_rx(%6u) = %12.4e + 1i*%12.4e;\n", i+1, crealf(frame_rx[i]), cimagf(frame_rx[i]));
for (i=0; i<payload_len; i++)
fprintf(fid,"payload_rx(%6u) = %12.4e + 1i*%12.4e;\n", i+1, crealf(payload_rx[i]), cimagf(payload_rx[i]));
fprintf(fid,"figure('Color','white','position',[100 100 950 400]);\n");
fprintf(fid,"subplot(1,2,1);\n");
fprintf(fid," plot(real(frame_rx), imag(frame_rx), 'x','MarkerSize',3);\n");
fprintf(fid," axis([-1 1 -1 1]*1.5);\n");
fprintf(fid," axis square;\n");
fprintf(fid," grid on;\n");
fprintf(fid," xlabel('real');\n");
fprintf(fid," ylabel('imag');\n");
fprintf(fid," title('received');\n");
fprintf(fid,"subplot(1,2,2);\n");
fprintf(fid," plot(real(payload_rx),imag(payload_rx),'x','MarkerSize',3);\n");
fprintf(fid," axis([-1 1 -1 1]*1.5);\n");
fprintf(fid," axis square;\n");
fprintf(fid," grid on;\n");
fprintf(fid," xlabel('real');\n");
fprintf(fid," ylabel('imag');\n");
fprintf(fid," title('recovered');\n");
fclose(fid);
printf("results written to '%s'\n", filename);
printf("done.\n");
return 0;
}
|