1 //
2 // conversion_example.c
3 //
4 // This example demonstrates conversion from complex baseband to a real-valued
5 // signal, and then down-conversion back to complex baseband while removing the
6 // negative image.
7 //
8 // STEP 1: A signal is generated at complex baseband consisting of narrow-band
9 // filtered noise and an offset tone (to show asymmetry in the transmit
10 // spectrum).
11 //
12 // STEP 2: The signal is mixed up to a carrier 'fc' (relative to the sampling
13 // frequency) and the real-component of the result is retained. This is
14 // the DAC output. The spectrum of this signal has two images: one at
15 // +fc, the other at -fc.
16 //
17 // STEP 3: The DAC output is mixed back down to complex baseband and the lower
18 // image is (mostly) filtered off. Reminants of the lower frequency
19 // component are still visible due to the wide-band and low-order
20 // filter on the receiver. The received complex baseband signal also
21 // has a reduction in power by 2 because half the signal's energy (the
22 // negative image) is filtered off.
23 //
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <math.h>
28
29 #include "liquid.h"
30
31 #define OUTPUT_FILENAME "conversion_example.m"
32
main()33 int main()
34 {
35 // spectral periodogram options
36 unsigned int nfft = 1200; // spectral periodogram FFT size
37 unsigned int num_samples = 64000; // number of samples
38 float fc = 0.20f; // carrier (relative to sampling rate)
39
40 // create objects
41 iirfilt_crcf filter_tx = iirfilt_crcf_create_lowpass(15, 0.05);
42 nco_crcf mixer_tx = nco_crcf_create(LIQUID_VCO);
43 nco_crcf mixer_rx = nco_crcf_create(LIQUID_VCO);
44 iirfilt_crcf filter_rx = iirfilt_crcf_create_lowpass(7, 0.2);
45
46 // set carrier frequencies
47 nco_crcf_set_frequency(mixer_tx, fc * 2*M_PI);
48 nco_crcf_set_frequency(mixer_rx, fc * 2*M_PI);
49
50 // create objects for measuring power spectral density
51 spgramcf spgram_tx = spgramcf_create_default(nfft);
52 spgramf spgram_dac = spgramf_create_default(nfft);
53 spgramcf spgram_rx = spgramcf_create_default(nfft);
54
55 // run through loop one step at a time
56 unsigned int i;
57 for (i=0; i<num_samples; i++) {
58 // STEP 1: generate input signal (filtered noise with offset tone)
59 float complex v1 = (randnf() + randnf()*_Complex_I) + 3.0f*cexpf(-_Complex_I*0.2f*i);
60 iirfilt_crcf_execute(filter_tx, v1, &v1);
61
62 // save spectrum
63 spgramcf_push(spgram_tx, v1);
64
65 // STEP 2: mix signal up and save real part (DAC output)
66 nco_crcf_mix_up(mixer_tx, v1, &v1);
67 float v2 = crealf(v1);
68 nco_crcf_step(mixer_tx);
69
70 // save spectrum
71 spgramf_push(spgram_dac, v2);
72
73 // STEP 3: mix signal down and filter off image
74 float complex v3;
75 nco_crcf_mix_down(mixer_rx, v2, &v3);
76 iirfilt_crcf_execute(filter_rx, v3, &v3);
77 nco_crcf_step(mixer_rx);
78
79 // save spectrum
80 spgramcf_push(spgram_rx, v3);
81 }
82
83 // compute power spectral density output
84 float psd_tx [nfft];
85 float psd_dac [nfft];
86 float psd_rx [nfft];
87 spgramcf_get_psd(spgram_tx, psd_tx);
88 spgramf_get_psd( spgram_dac, psd_dac);
89 spgramcf_get_psd(spgram_rx, psd_rx);
90
91 // destroy objects
92 spgramcf_destroy(spgram_tx);
93 spgramf_destroy(spgram_dac);
94 spgramcf_destroy(spgram_rx);
95
96 iirfilt_crcf_destroy(filter_tx);
97 nco_crcf_destroy(mixer_tx);
98 nco_crcf_destroy(mixer_rx);
99 iirfilt_crcf_destroy(filter_rx);
100
101 //
102 // export output file
103 //
104 FILE * fid = fopen(OUTPUT_FILENAME,"w");
105 fprintf(fid,"%% %s : auto-generated file\n", OUTPUT_FILENAME);
106 fprintf(fid,"clear all;\n");
107 fprintf(fid,"close all;\n\n");
108
109 fprintf(fid,"nfft = %u;\n", nfft);
110 fprintf(fid,"f = [0:(nfft-1)]/nfft - 0.5;\n");
111 fprintf(fid,"psd_tx = zeros(1,nfft);\n");
112 fprintf(fid,"psd_dac= zeros(1,nfft);\n");
113 fprintf(fid,"psd_rx = zeros(1,nfft);\n");
114
115 for (i=0; i<nfft; i++) {
116 fprintf(fid,"psd_tx (%6u) = %12.4e;\n", i+1, psd_tx [i]);
117 fprintf(fid,"psd_dac(%6u) = %12.4e;\n", i+1, psd_dac[i]);
118 fprintf(fid,"psd_rx (%6u) = %12.4e;\n", i+1, psd_rx [i]);
119 }
120
121 fprintf(fid,"figure;\n");
122 fprintf(fid,"hold on;\n");
123 fprintf(fid," plot(f, psd_tx, '-', 'LineWidth',1.5,'Color',[0.7 0.7 0.7]);\n");
124 fprintf(fid," plot(f, psd_dac, '-', 'LineWidth',1.5,'Color',[0.0 0.5 0.3]);\n");
125 fprintf(fid," plot(f, psd_rx, '-', 'LineWidth',1.5,'Color',[0.0 0.3 0.5]);\n");
126 fprintf(fid,"hold off;\n");
127 fprintf(fid,"xlabel('Normalized Frequency [f/F_s]');\n");
128 fprintf(fid,"ylabel('Power Spectral Density [dB]');\n");
129 fprintf(fid,"grid on;\n");
130 fprintf(fid,"axis([-0.5 0.5 -100 60]);\n");
131 fprintf(fid,"legend('transmit (complex)','DAC output (real)','receive (complex)','location','northeast');\n");
132
133 fclose(fid);
134 printf("results written to %s.\n", OUTPUT_FILENAME);
135
136 printf("done.\n");
137 return 0;
138 }
139
140