1 /*****************************************************************************/
2
3 /*
4 * sm_afsk2400_7.c -- soundcard radio modem driver, 2400 baud AFSK modem
5 *
6 * Copyright (C) 1996 Thomas Sailer (sailer@ife.ee.ethz.ch)
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 *
22 * Please note that the GPL allows you to use the driver, NOT the radio.
23 * In order to use the radio, you need a license from the communications
24 * authority of your country.
25 *
26 */
27
28 /*
29 * This driver is intended to be compatible with TCM3105 modems
30 * overclocked to 7.3728MHz. The mark and space frequencies therefore
31 * lie at 3658 and 1996 Hz.
32 * Note that I do _not_ recommend the building of such links, I provide
33 * this only for the users who live in the coverage area of such
34 * a "legacy" link.
35 */
36
37 #include "sm.h"
38 #include "sm_tbl_afsk2400_7.h"
39
40 /* --------------------------------------------------------------------- */
41
42 struct demod_state_afsk24 {
43 unsigned int shreg;
44 unsigned int bit_pll;
45 unsigned char last_sample;
46 unsigned int dcd_shreg;
47 int dcd_sum0, dcd_sum1, dcd_sum2;
48 unsigned int dcd_time;
49 unsigned char last_rxbit;
50 };
51
52 struct mod_state_afsk24 {
53 unsigned int shreg;
54 unsigned char tx_bit;
55 unsigned int bit_pll;
56 unsigned int tx_seq;
57 unsigned int phinc;
58 };
59
60 /* --------------------------------------------------------------------- */
61
62 static const int dds_inc[2] = { AFSK24_TX_FREQ_LO*0x10000/AFSK24_SAMPLERATE,
63 AFSK24_TX_FREQ_HI*0x10000/AFSK24_SAMPLERATE };
64
modulator_2400_u8(struct sm_state * sm,unsigned char * buf,unsigned int buflen)65 static void modulator_2400_u8(struct sm_state *sm, unsigned char *buf, unsigned int buflen)
66 {
67 struct mod_state_afsk24 *st = (struct mod_state_afsk24 *)(&sm->m);
68
69 for (; buflen > 0; buflen--, buf++) {
70 if (st->tx_seq < 0x5555) {
71 if (st->shreg <= 1)
72 st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000;
73 st->tx_bit = (st->tx_bit ^ (!(st->shreg & 1))) & 1;
74 st->shreg >>= 1;
75 st->phinc = dds_inc[st->tx_bit & 1];
76 }
77 st->tx_seq += 0x5555;
78 st->tx_seq &= 0xffff;
79 *buf = OFFSCOS(st->bit_pll);
80 st->bit_pll += st->phinc;
81 }
82 }
83
84 /* --------------------------------------------------------------------- */
85
modulator_2400_s16(struct sm_state * sm,short * buf,unsigned int buflen)86 static void modulator_2400_s16(struct sm_state *sm, short *buf, unsigned int buflen)
87 {
88 struct mod_state_afsk24 *st = (struct mod_state_afsk24 *)(&sm->m);
89
90 for (; buflen > 0; buflen--, buf++) {
91 if (st->tx_seq < 0x5555) {
92 if (st->shreg <= 1)
93 st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000;
94 st->tx_bit = (st->tx_bit ^ (!(st->shreg & 1))) & 1;
95 st->shreg >>= 1;
96 st->phinc = dds_inc[st->tx_bit & 1];
97 }
98 st->tx_seq += 0x5555;
99 st->tx_seq &= 0xffff;
100 *buf = COS(st->bit_pll);
101 st->bit_pll += st->phinc;
102 }
103 }
104
105 /* --------------------------------------------------------------------- */
106
convolution14_u8(const unsigned char * st,const int * coeff,int csum)107 static inline int convolution14_u8(const unsigned char *st, const int *coeff, int csum)
108 {
109 int sum = -0x80 * csum;
110
111 sum += (st[0] * coeff[0]);
112 sum += (st[-1] * coeff[1]);
113 sum += (st[-2] * coeff[2]);
114 sum += (st[-3] * coeff[3]);
115 sum += (st[-4] * coeff[4]);
116 sum += (st[-5] * coeff[5]);
117 sum += (st[-6] * coeff[6]);
118 sum += (st[-7] * coeff[7]);
119 sum += (st[-8] * coeff[8]);
120 sum += (st[-9] * coeff[9]);
121 sum += (st[-10] * coeff[10]);
122 sum += (st[-11] * coeff[11]);
123 sum += (st[-12] * coeff[12]);
124 sum += (st[-13] * coeff[13]);
125
126 sum >>= 7;
127 return sum * sum;
128 }
129
convolution14_s16(const short * st,const int * coeff,int csum)130 static inline int convolution14_s16(const short *st, const int *coeff, int csum)
131 {
132 int sum = 0;
133
134 sum += (st[0] * coeff[0]);
135 sum += (st[-1] * coeff[1]);
136 sum += (st[-2] * coeff[2]);
137 sum += (st[-3] * coeff[3]);
138 sum += (st[-4] * coeff[4]);
139 sum += (st[-5] * coeff[5]);
140 sum += (st[-6] * coeff[6]);
141 sum += (st[-7] * coeff[7]);
142 sum += (st[-8] * coeff[8]);
143 sum += (st[-9] * coeff[9]);
144 sum += (st[-10] * coeff[10]);
145 sum += (st[-11] * coeff[11]);
146 sum += (st[-12] * coeff[12]);
147 sum += (st[-13] * coeff[13]);
148
149 sum >>= 15;
150 return sum * sum;
151 }
152
do_filter_2400_u8(const unsigned char * buf)153 static inline int do_filter_2400_u8(const unsigned char *buf)
154 {
155 int sum = convolution14_u8(buf, afsk24_tx_lo_i, SUM_AFSK24_TX_LO_I);
156 sum += convolution14_u8(buf, afsk24_tx_lo_q, SUM_AFSK24_TX_LO_Q);
157 sum -= convolution14_u8(buf, afsk24_tx_hi_i, SUM_AFSK24_TX_HI_I);
158 sum -= convolution14_u8(buf, afsk24_tx_hi_q, SUM_AFSK24_TX_HI_Q);
159 return sum;
160 }
161
do_filter_2400_s16(const short * buf)162 static inline int do_filter_2400_s16(const short *buf)
163 {
164 int sum = convolution14_s16(buf, afsk24_tx_lo_i, SUM_AFSK24_TX_LO_I);
165 sum += convolution14_s16(buf, afsk24_tx_lo_q, SUM_AFSK24_TX_LO_Q);
166 sum -= convolution14_s16(buf, afsk24_tx_hi_i, SUM_AFSK24_TX_HI_I);
167 sum -= convolution14_s16(buf, afsk24_tx_hi_q, SUM_AFSK24_TX_HI_Q);
168 return sum;
169 }
170
171 /* --------------------------------------------------------------------- */
172
demodulator_2400_u8(struct sm_state * sm,const unsigned char * buf,unsigned int buflen)173 static void demodulator_2400_u8(struct sm_state *sm, const unsigned char *buf, unsigned int buflen)
174 {
175 struct demod_state_afsk24 *st = (struct demod_state_afsk24 *)(&sm->d);
176 int j;
177 int sum;
178 unsigned char newsample;
179
180 for (; buflen > 0; buflen--, buf++) {
181 sum = do_filter_2400_u8(buf);
182 st->dcd_shreg <<= 1;
183 st->bit_pll += AFSK24_BITPLL_INC;
184 newsample = (sum > 0);
185 if (st->last_sample ^ newsample) {
186 st->last_sample = newsample;
187 st->dcd_shreg |= 1;
188 if (st->bit_pll < (0x8000+AFSK24_BITPLL_INC/2))
189 st->bit_pll += AFSK24_BITPLL_INC/2;
190 else
191 st->bit_pll -= AFSK24_BITPLL_INC/2;
192 j = /* 2 * */ hweight8(st->dcd_shreg & 0x1c)
193 - hweight16(st->dcd_shreg & 0x1e0);
194 st->dcd_sum0 += j;
195 }
196 hdlcdrv_channelbit(&sm->hdrv, st->last_sample);
197 if ((--st->dcd_time) <= 0) {
198 hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 +
199 st->dcd_sum1 +
200 st->dcd_sum2) < 0);
201 st->dcd_sum2 = st->dcd_sum1;
202 st->dcd_sum1 = st->dcd_sum0;
203 st->dcd_sum0 = 2; /* slight bias */
204 st->dcd_time = 120;
205 }
206 if (st->bit_pll >= 0x10000) {
207 st->bit_pll &= 0xffff;
208 st->shreg >>= 1;
209 st->shreg |= (!(st->last_rxbit ^
210 st->last_sample)) << 16;
211 st->last_rxbit = st->last_sample;
212 diag_trigger(sm);
213 if (st->shreg & 1) {
214 hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1);
215 st->shreg = 0x10000;
216 }
217 }
218 diag_add(sm, (((int)*buf)-0x80) << 8, sum);
219 }
220 }
221
222 /* --------------------------------------------------------------------- */
223
demodulator_2400_s16(struct sm_state * sm,const short * buf,unsigned int buflen)224 static void demodulator_2400_s16(struct sm_state *sm, const short *buf, unsigned int buflen)
225 {
226 struct demod_state_afsk24 *st = (struct demod_state_afsk24 *)(&sm->d);
227 int j;
228 int sum;
229 unsigned char newsample;
230
231 for (; buflen > 0; buflen--, buf++) {
232 sum = do_filter_2400_s16(buf);
233 st->dcd_shreg <<= 1;
234 st->bit_pll += AFSK24_BITPLL_INC;
235 newsample = (sum > 0);
236 if (st->last_sample ^ newsample) {
237 st->last_sample = newsample;
238 st->dcd_shreg |= 1;
239 if (st->bit_pll < (0x8000+AFSK24_BITPLL_INC/2))
240 st->bit_pll += AFSK24_BITPLL_INC/2;
241 else
242 st->bit_pll -= AFSK24_BITPLL_INC/2;
243 j = /* 2 * */ hweight8(st->dcd_shreg & 0x1c)
244 - hweight16(st->dcd_shreg & 0x1e0);
245 st->dcd_sum0 += j;
246 }
247 hdlcdrv_channelbit(&sm->hdrv, st->last_sample);
248 if ((--st->dcd_time) <= 0) {
249 hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 +
250 st->dcd_sum1 +
251 st->dcd_sum2) < 0);
252 st->dcd_sum2 = st->dcd_sum1;
253 st->dcd_sum1 = st->dcd_sum0;
254 st->dcd_sum0 = 2; /* slight bias */
255 st->dcd_time = 120;
256 }
257 if (st->bit_pll >= 0x10000) {
258 st->bit_pll &= 0xffff;
259 st->shreg >>= 1;
260 st->shreg |= (!(st->last_rxbit ^
261 st->last_sample)) << 16;
262 st->last_rxbit = st->last_sample;
263 diag_trigger(sm);
264 if (st->shreg & 1) {
265 hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1);
266 st->shreg = 0x10000;
267 }
268 }
269 diag_add(sm, *buf, sum);
270 }
271 }
272
273 /* --------------------------------------------------------------------- */
274
demod_init_2400(struct sm_state * sm)275 static void demod_init_2400(struct sm_state *sm)
276 {
277 struct demod_state_afsk24 *st = (struct demod_state_afsk24 *)(&sm->d);
278
279 st->dcd_time = 120;
280 st->dcd_sum0 = 2;
281 }
282
283 /* --------------------------------------------------------------------- */
284
285 const struct modem_tx_info sm_afsk2400_7_tx = {
286 "afsk2400_7", sizeof(struct mod_state_afsk24), AFSK24_SAMPLERATE, 2400,
287 modulator_2400_u8, modulator_2400_s16, NULL
288 };
289
290 const struct modem_rx_info sm_afsk2400_7_rx = {
291 "afsk2400_7", sizeof(struct demod_state_afsk24),
292 AFSK24_SAMPLERATE, 2400, 14, AFSK24_SAMPLERATE/2400,
293 demodulator_2400_u8, demodulator_2400_s16, demod_init_2400
294 };
295
296 /* --------------------------------------------------------------------- */
297