1 /*---------------------------------------------------------------------------*\
2 
3   FILE........: ofdm_internal.h
4   AUTHORS.....: David Rowe & Steve Sampson
5   DATE CREATED: June 2017
6 
7   OFDM Internal definitions.
8 
9 \*---------------------------------------------------------------------------*/
10 
11 /*
12   Copyright (C) 2017 David Rowe
13 
14   All rights reserved.
15 
16   This program is free software; you can redistribute it and/or modify
17   it under the terms of the GNU Lesser General Public License version 2.1, as
18   published by the Free Software Foundation.  This program is
19   distributed in the hope that it will be useful, but WITHOUT ANY
20   WARRANTY; without even the implied warranty of MERCHANTABILITY or
21   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
22   License for more details.
23 
24   You should have received a copy of the GNU Lesser General Public License
25   along with this program; if not, see <http://www.gnu.org/licenses/>.
26  */
27 
28 #ifndef OFDM_INTERNAL_H
29 #define OFDM_INTERNAL_H
30 
31 #include <complex.h>
32 #include <stdbool.h>
33 #include <stdint.h>
34 
35 #include "codec2_ofdm.h"
36 #include "filter.h"
37 
38 #ifdef __cplusplus
39 extern "C"
40 {
41 #endif
42 
43 #ifndef M_PI
44 #define M_PI        3.14159265358979323846f
45 #endif
46 
47 #define TAU         (2.0f * M_PI)
48 #define ROT45       (M_PI / 4.0f)
49 #define MAX_UW_BITS 64
50 
51 #define cmplx(value) (cosf(value) + sinf(value) * I)
52 #define cmplxconj(value) (cosf(value) + sinf(value) * -I)
53 
54 /* modem state machine states */
55 typedef enum {
56     search,
57     trial,
58     synced
59 } State;
60 
61 typedef enum {
62     unsync,             /* force sync state machine to lose sync, and search for new sync */
63     autosync,           /* falls out of sync automatically */
64     manualsync          /* fall out of sync only under operator control */
65 } Sync;
66 
67 /* phase estimator bandwidth options */
68 
69 typedef enum {
70     low_bw,             /* can only track a narrow freq offset, but accurate         */
71     high_bw             /* can track wider freq offset, but less accurate at low SNR */
72 } PhaseEstBandwidth;
73 
74 /*
75  * User-defined configuration for OFDM modem.  Used to set up
76  * constants at init time, e.g. for different bit rate modems.
77  */
78 
79 struct OFDM_CONFIG {
80     float tx_centre;   /* TX Centre Audio Frequency */
81     float rx_centre;   /* RX Centre Audio Frequency */
82     float fs;          /* Sample Frequency */
83     float rs;          /* Symbol Rate */
84     float ts;          /* symbol duration */
85     float tcp;         /* Cyclic Prefix duration */
86     float timing_mx_thresh;
87 
88     int nc;            /* Number of carriers */
89     int ns;            /* Number of Symbol frames */
90     int np;            /* number of modem frames per packet */
91     int bps;           /* Bits per Symbol */
92     int txtbits;       /* number of auxiliary data bits */
93     int nuwbits;       /* number of unique word bits */
94     int bad_uw_errors;
95     int ftwindowwidth;
96     int edge_pilots;
97     char *state_machine;  /* name of sync state machine used for this mode */
98     char *codename;       /* name of LDPC code used with this mode */
99     uint8_t tx_uw[MAX_UW_BITS]; /* user defined unique word */
100     int amp_est_mode;
101     bool tx_bpf_en;       /* default clippedtx BPF state */
102     bool foff_limiter;    /* tames freq offset updates in low SNR */
103     float amp_scale;      /* used to scale Tx waveform to approx FREEDV_PEAK with clipper off */
104     float clip_gain1;     /* gain we apply to Tx signal before clipping to control PAPR*/
105     float clip_gain2;     /* gain we apply to Tx signal after clipping and BBF to control peak level */
106     bool  clip_en;
107     char mode[16];        /* OFDM mode in string form */
108     char *data_mode;
109 };
110 
111 struct OFDM {
112     struct OFDM_CONFIG config;
113 
114     char mode[16];        /* mode in string form */
115     /*
116      * See 700D Part 4 Acquisition blog post and ofdm_dev.m routines
117      * for how this was set
118      */
119     float timing_mx_thresh;
120 
121     int nc;
122     int ns;              	 /* NS-1 = data symbols between pilots  */
123     int bps; 	             /* Bits per symbol */
124     int m; 	               /* duration of each symbol in samples */
125     int ncp; 	             /* duration of CP in samples */
126     int np;                /* number of modem frames per packet. In some modes we want */
127                            /* the total packet of data to span multiple modem frames, e.g. HF data */
128                            /* and/or when the FEC codeword is larger than the one */
129                            /* modem frame.  In other modes (e.g. 700D/2020) Np=1, ie the modem frame */
130                            /* is the same length as the packet/FEC frame. */
131     int ftwindowwidth;
132     int bitsperframe;      /* total bits in all data symbols in modem frame */
133     int bitsperpacket;     /* total bits in all data symbols in a packet */
134     int rowsperframe;
135     int samplespersymbol;
136     int samplesperframe;
137     int nrxbufhistory;    /* extra storage at start of rxbuf to allow us to step back in time */
138     int nrxbufmin;        /* min number of samples we need in rxbuf to process a modem frame */
139     int rxbufst;          /* start of rxbuf window used for demod of current rx frame */
140     int pre, post;        /* pre-amble and post-amble detections */
141     int max_samplesperframe;
142     int nuwframes;
143     int nrxbuf;
144     int ntxtbits;         /* reserve bits/frame for aux text information */
145     int nuwbits;          /* number of unique word bits used to achieve packet frame sync */
146     int bad_uw_errors;    /* threshold for UW detection check */
147     int uw_fails;         /* number of times we exceeded bad_uw_errors and dropped sync */
148     int edge_pilots;      /* insert pilots at 1 and Nc+2, to support low bandwidth phase est */
149     char *data_mode;      /* "", "streaming", "burst"  */
150     int packetsperburst;  /* for OFDM data modes, how many packets before we reset state machine */
151     int amp_est_mode;     /* amplitude estimtor algorithm */
152     float amp_scale;
153     float clip_gain1;
154     float clip_gain2;
155     bool  clip_en;
156 
157     float tx_centre;      /* TX Center frequency */
158     float rx_centre;      /* RX Center frequency */
159     float fs;             /* Sample rate */
160     float ts;             /* Symbol cycle time */
161     float rs;             /* Symbol rate */
162     float tcp;            /* Cyclic prefix duration */
163     float tpacket;        /* time for one packet in ms */
164     float inv_m;          /* 1/m */
165     float tx_nlower;      /* TX lowest carrier freq */
166     float rx_nlower;      /* RX lowest carrier freq */
167     float doc;            /* division of radian circle */
168 
169     // Pointers
170 
171     struct quisk_cfFilter *tx_bpf;
172 
173     complex float *pilot_samples;
174     complex float *rxbuf;
175     complex float *pilots;
176     complex float **rx_sym;
177     complex float *rx_np;
178     complex float *tx_uw_syms;
179     COMP          *tx_preamble;
180     COMP          *tx_postamble;
181 
182     float *rx_amp;
183     float *aphase_est_pilot_log;
184 
185     uint8_t tx_uw[MAX_UW_BITS];
186     int *uw_ind;
187     int *uw_ind_sym;
188 
189     // State enums
190     State sync_state;
191     State last_sync_state;
192 
193     // Sync enums
194     Sync sync_mode;
195 
196     // Phase enums
197     PhaseEstBandwidth phase_est_bandwidth;
198 
199     int phase_est_bandwidth_mode;
200 
201     // Complex
202     complex float foff_metric;
203 
204     // Float
205     float foff_est_gain;
206     bool  foff_limiter;
207     float foff_est_hz;
208     float timing_mx;
209     float coarse_foff_est_hz;
210     float timing_norm;
211     float mean_amp;
212 
213     // Integer
214     int clock_offset_counter;
215     int verbose;
216     int sample_point;
217     int timing_est;
218     int timing_valid;
219     int ct_est;
220     int nin;
221     int uw_errors;
222     int sync_counter;
223     int frame_count;  /* general purpose counter of modem frames */
224     int packet_count; /* data mode: number of packets received so far */
225     int modem_frame;  /* increments for every modem frame in packet */
226 
227     // Boolean
228     bool sync_start;
229     bool sync_end;
230     bool timing_en;
231     bool foff_est_en;
232     bool phase_est_en;
233     bool tx_bpf_en;
234     bool dpsk_en;
235     bool postambledetectoren; /* allows us to optionally disable the postamble detector */
236 
237     char *codename;
238     char *state_machine;
239 };
240 
241 /* Prototypes */
242 
243 complex float qpsk_mod(int *);
244 complex float qam16_mod(int *);
245 void qpsk_demod(complex float, int *);
246 void qam16_demod(complex float, int *);
247 void ofdm_txframe(struct OFDM *, complex float *, complex float []);
248 void ofdm_assemble_qpsk_modem_packet(struct OFDM *, uint8_t [], uint8_t [], uint8_t []);
249 void ofdm_assemble_qpsk_modem_packet_symbols(struct OFDM *, complex float [], COMP [], uint8_t []);
250 void ofdm_disassemble_qpsk_modem_packet(struct OFDM *, complex float rx_syms[], float rx_amps[], COMP [], float [], short []);
251 void ofdm_disassemble_qpsk_modem_packet_with_text_amps(struct OFDM *, complex float rx_syms[], float rx_amps[], COMP [], float [], short [], int*);
252 void ofdm_extract_uw(struct OFDM *ofdm, complex float rx_syms[], float rx_amps[], uint8_t rx_uw[]);
253 void ofdm_rand(uint16_t [], int);
254 void ofdm_rand_seed(uint16_t r[], int n, uint64_t seed) ;
255 void ofdm_generate_payload_data_bits(uint8_t data_bits[], int n);
256 void ofdm_generate_preamble(struct OFDM *ofdm, COMP *tx_preamble, int seed);
257 int ofdm_get_phase_est_bandwidth_mode(struct OFDM *);
258 void ofdm_set_phase_est_bandwidth_mode(struct OFDM *, int);
259 void ofdm_clip(complex float tx[], float clip_thresh, int n);
260 void ofdm_hilbert_clipper(struct OFDM *ofdm, complex float *tx, size_t n);
261 float ofdm_esno_est_calc(complex float *rx_sym, int nsym);
262 float ofdm_snr_from_esno(struct OFDM *ofdm, float EsNodB);
263 void ofdm_get_demod_stats(struct OFDM *ofdm, struct MODEM_STATS *stats, complex float *rx_syms, int Nsymsperpacket);
264 
265 #ifdef __cplusplus
266 }
267 #endif
268 
269 #endif
270