1 /*---------------------------------------------------------------------------*\
2 
3   FILE........: fsk.h
4   AUTHOR......: Brady O'Brien
5   DATE CREATED: 6 January 2016
6 
7   C Implementation of 2FSK/4FSK modulator/demodulator, based on octave/fsk_horus.m
8 
9 \*---------------------------------------------------------------------------*/
10 
11 /*
12   Copyright (C) 2016 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 
29 #ifndef __C2FSK_H
30 #define __C2FSK_H
31 
32 #include <stdint.h>
33 #include "comp.h"
34 #include "kiss_fftr.h"
35 #include "modem_stats.h"
36 
37 #define MODE_2FSK 2
38 #define MODE_4FSK 4
39 
40 #define MODE_M_MAX 4
41 
42 #define FSK_SCALE 16383
43 
44 /* default internal parameters */
45 #define FSK_DEFAULT_P     8      /* Number of timing offsets we have to choose from, try to keep P >= 8 */
46 #define FSK_DEFAULT_NSYM 50      /* See Nsym below */
47 #define FSK_NONE         -1      /* unused parameter */
48 
49 struct FSK {
50     /*  Static parameters set up by fsk_init */
51     int Ndft;               /* freq offset est fft */
52     int Fs;                 /* sample freq */
53     int N;                  /* processing buffer size */
54     int Rs;                 /* symbol rate */
55     int Ts;                 /* samples per symbol */
56     int Nmem;               /* size of extra mem for timing adj */
57     int P;                  /* oversample rate for timing est/adj */
58     int Nsym;               /* Number of symbols processed by demodulator in each call, also the timing estimator window */
59     int Nbits;              /* Number of bits spat out in a processing frame */
60     int f1_tx;              /* f1 for modulator */
61     int tone_spacing;       /* Space between TX freqs for modulator (and option mask freq estimator) */
62     int mode;               /* 2FSK or 4FSK */
63     float tc;               /* time constant for smoothing FFTs */
64     int est_min;            /* Minimum frequency for freq. estimator */
65     int est_max;            /* Maximum frequency for freq. estimator */
66     int est_space;          /* Minimum frequency spacing for freq. estimator */
67     float* hann_table;	    /* Precomputed or runtime computed hann window table */
68 
69     /*  Parameters used by demod */
70     float* Sf;	            /* Average of magnitude spectrum */
71     COMP phi_c[MODE_M_MAX]; /* phase of each demod local oscillator */
72     COMP *f_dc;             /* down converted samples               */
73 
74     kiss_fft_cfg fft_cfg;   /* Config for KISS FFT, used in freq est */
75     float norm_rx_timing;   /* Normalized RX timing */
76 
77     /*  Parameters used by mod */
78     COMP tx_phase_c;        /* TX phase, but complex */
79 
80     /*  Statistics generated by demod */
81     float  EbNodB;            /* Estimated EbNo in dB */
82     float  f_est[MODE_M_MAX]; /* Estimated frequencies (peak method) */
83     float  f2_est[MODE_M_MAX];/* Estimated frequencies (mask method) */
84     int    freq_est_type;     /* which estimator to use              */
85     float  ppm;               /* Estimated PPM clock offset */
86     float  SNRest;            /* used for LLRs */
87     float  v_est;             /* used for LLRs */
88     float  rx_sig_pow;
89     float  rx_nse_pow;
90 
91     /*  Parameters used by mod/demod and driving code */
92     int nin;                /* Number of samples to feed the next demod cycle */
93     int burst_mode;         /* enables/disables 'burst' mode */
94     int lock_nin;           /* locks nin during testing */
95 
96     /*  modem statistics struct */
97     struct MODEM_STATS *stats;
98     int normalise_eye;      /* enables/disables normalisation of eye diagram */
99 };
100 
101 /*
102  * Create a FSK modem
103  *
104  * int Fs - Sample frequency
105  * int Rs - Symbol rate
106  * int M  - 2 for 2FSK, 4 for 4FSK
107  * int f1_tx - first tone frequency
108  * int tone_spacing - frequency spacing (for modulator and optional "mask" freq estimator)
109  */
110 struct FSK * fsk_create(int Fs, int Rs, int M, int f1_tx, int tone_spacing);
111 
112 /*
113  * Create a FSK modem - advanced version
114  *
115  * int Fs - Sample frequency
116  * int Rs - Symbol rate
117  * int M  - 2 for 2FSK, 4 for 4FSK
118  * int P  - number of timing offsets to choose from (suggest >= 8)
119  * int Nsym  - windows size for timing estimator
120  * int f1_tx - first tone frequency
121  * int tone_spacing - frequency spacing (for modulator and optional "mask" freq estimator)
122  */
123 struct FSK * fsk_create_hbr(int Fs, int Rs, int M, int P, int Nsym, int f1_tx, int tone_spacing);
124 
125 /*
126  * Set the minimum and maximum frequencies at which the freq. estimator can find tones
127  */
128 void fsk_set_freq_est_limits(struct FSK *fsk,int fmin, int fmax);
129 
130 /*
131  * Clear the estimator states
132  */
133 void fsk_clear_estimators(struct FSK *fsk);
134 
135 /*
136  * Fills MODEM_STATS struct with demod statistics
137  */
138 void fsk_get_demod_stats(struct FSK *fsk, struct MODEM_STATS *stats);
139 
140 /*
141  * Destroy an FSK state struct and free it's memory
142  *
143  * struct FSK *fsk - FSK config/state struct to be destroyed
144  */
145 void fsk_destroy(struct FSK *fsk);
146 
147 /*
148  * Modulates Nsym bits into N samples
149  *
150  * struct FSK *fsk   - FSK config/state struct, set up by fsk_create
151  * float fsk_out[]   - Buffer for samples of modulated FSK, fsk->Ts*(nbits/(M>>1)) in length
152  * uint8_t tx_bits[] - Buffer containing Nbits unpacked bits
153  * int     nbits     - number of bits to transmit
154  */
155 void fsk_mod(struct FSK *fsk, float fsk_out[], uint8_t tx_bits[], int nbits);
156 
157 /*
158  * Modulates Nsym bits into N samples
159  *
160  * struct FSK *fsk   - FSK config/state struct, set up by fsk_create
161  * float fsk_out[]   - Buffer for samples of "voltage" used to modulate an external VCO
162  *                   - fsk->Ts*(nbits/(M>>1)) in length
163  * uint8_t tx_bits[] - Buffer containing Nbits unpacked bits
164  * int     nbits     - number of bits to transmit
165  */
166 void fsk_mod_ext_vco(struct FSK *fsk, float vco_out[], uint8_t tx_bits[], int nbits);
167 
168 /*
169  * Modulates Nsym bits into N complex samples
170  *
171  * struct FSK *fsk   - FSK config/state struct, set up by fsk_create
172  * comp fsk_out[]    - Buffer for samples of modulated FSK, fsk->Ts*(nbits/(M>>1)) in length
173  * uint8_t tx_bits[] - Buffer containing Nbits unpacked bits
174  * int     nbits     - number of bits to transmit
175  */
176 void fsk_mod_c(struct FSK *fsk, COMP fsk_out[], uint8_t tx_bits[], int nbits);
177 
178 /*
179  * Returns the number of samples needed for the next fsk_demod() cycle
180  *
181  * struct FSK *fsk - FSK config/state struct, set up by fsk_create
182  * returns - number of samples to be fed into fsk_demod next cycle
183  */
184 uint32_t fsk_nin(struct FSK *fsk);
185 
186 
187 /*
188  * Demodulate some number of FSK samples. The number of samples to be
189  *  demodulated can be found by calling fsk_nin().
190  *
191  * struct FSK *fsk   - FSK config/state struct, set up by fsk_create
192  * uint8_t rx_bits[] - Buffer for fsk->Nbits unpacked bits to be written
193  * float fsk_in[]    - nin samples of modulated FSK
194  */
195 void fsk_demod(struct FSK *fsk, uint8_t rx_bits[], COMP fsk_in[]);
196 
197 /*
198  * Soft decision demodulation
199  *
200  * struct FSK *fsk - FSK config/state struct, set up by fsk_create
201  * float rx_flit[] - M x Nsym array of filtermagnitude outputs
202  * float fsk_in[]  - nin samples of modualted FSK
203  */
204 void fsk_demod_sd(struct FSK *fsk, float rx_filt[], COMP fsk_in[]);
205 
206 /* enables/disables normalisation of eye diagram samples */
207 
208 void fsk_stats_normalise_eye(struct FSK *fsk, int normalise_enable);
209 
210 /* Set the FSK modem into burst demod mode */
211 
212 void fsk_enable_burst_mode(struct FSK *fsk);
213 
214 /* Set freq est algorithm 0: peak 1:mask */
215 void fsk_set_freq_est_alg(struct FSK *fsk, int est_type);
216 
217 #endif
218