1 /* AFC (Automatic Frequency Correction) Implementation */
3 /* (C) 2010 by Harald Welte <laforge@gnumonks.org>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 #include <osmocore/gsm_utils.h>
29 #include <layer1/afc.h>
30 #include <layer1/avg.h>
31 #include <calypso/dsp.h>
33 #define AFC_INITIAL_DAC_VALUE -700
35 /* Over how many TDMA frames do we want to average? (this may change in dedicated mode) */
37 /* How many of our measurements have to be valid? */
38 #define AFC_MIN_MUN_VALID 8
40 /* The actual AFC code */
43 struct running_avg ravg; /* running average */
44 int16_t dac_value; /* current DAC output value */
48 static void afc_ravg_output(struct running_avg *ravg, int32_t avg);
50 static struct afc_state afc_state = {
52 .outfn = &afc_ravg_output,
54 .min_valid = AFC_MIN_MUN_VALID,
56 .dac_value = AFC_INITIAL_DAC_VALUE,
59 /* The AFC DAC in the ABB has to be configured as follows:
60 * DAC = 1MHz / 947MHz * FreqErr(Hz) / AFCslop(ppm/LSB)
62 * 947 MHz is the center of EGSM
63 * AFCslope is coded F1.15, thus a normalization factor of 2^15 aplpies
66 #define AFC_NORM_FACTOR_GSM ((1<<15) / 947)
67 #define AFC_NORM_FACTOR_DCS ((1<<15) / 1894)
69 /* we assume 8.769ppb per LSB, equals 0.008769 * 32768 == 287 */
70 //#define AFC_SLOPE 320
73 /* The DSP can measure the frequency error in the following ranges:
74 * FB_MODE0: +/- 20 kHz
76 * Sync Burst: +/- 1 kHz
77 * Normal Burst: +/- 400 Hz
80 /* Update the AFC with a frequency error, bypassing averaging */
81 void afc_correct(int16_t freq_error, uint16_t arfcn)
83 int32_t afc_norm_factor;
86 switch (gsm_arfcn2band(arfcn)) {
89 afc_norm_factor = AFC_NORM_FACTOR_GSM;
92 afc_norm_factor = AFC_NORM_FACTOR_DCS;
95 delta = (int16_t) ((afc_norm_factor * (int32_t)freq_error) / AFC_SLOPE);
96 printd("afc_correct(error=%dHz, arfcn=%u): delta=%d, afc_dac(old=%d,new=%d)\n",
97 freq_error, arfcn, delta, afc_state.dac_value, afc_state.dac_value+delta);
98 afc_state.dac_value += delta;
100 /* The AFC DAC has only 13 bits */
101 if (afc_state.dac_value > 4095)
102 afc_state.dac_value = 4095;
103 else if (afc_state.dac_value < -4096)
104 afc_state.dac_value = -4096;
109 afc_state.dac_value = AFC_INITIAL_DAC_VALUE;
112 void afc_input(int32_t freq_error, uint16_t arfcn, int valid)
114 afc_state.arfcn = arfcn;
115 runavg_input(&afc_state.ravg, freq_error, valid);
116 runavg_check_output(&afc_state.ravg);
119 /* callback function for runavg */
120 static void afc_ravg_output(struct running_avg *ravg, int32_t avg)
122 afc_correct(avg, afc_state.arfcn);
125 /* Update DSP with new AFC DAC value to be used for next TDMA frame */
126 void afc_load_dsp(void)
128 dsp_api.db_w->d_afc = afc_state.dac_value;
129 dsp_api.db_w->d_ctrl_abb |= (1 << B_AFC);