1/*****************************************************************************/
2
3/*
4 *	sm_afsk1200.c  -- soundcard radio modem driver, 1200 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#include "sm.h"
29#include "sm_tbl_afsk1200.h"
30
31/* --------------------------------------------------------------------- */
32
33struct demod_state_afsk12 {
34	unsigned int shreg;
35	unsigned int bit_pll;
36	unsigned char last_sample;
37	unsigned int dcd_shreg;
38	int dcd_sum0, dcd_sum1, dcd_sum2;
39	unsigned int dcd_time;
40	unsigned char last_rxbit;
41};
42
43struct mod_state_afsk12 {
44	unsigned int shreg;
45	unsigned char tx_bit;
46	unsigned int bit_pll;
47	unsigned int dds_inc;
48	unsigned int txphase;
49};
50
51/* --------------------------------------------------------------------- */
52
53static const int dds_inc[2] = {
54	AFSK12_TX_FREQ_LO*0x10000/AFSK12_SAMPLE_RATE,
55	AFSK12_TX_FREQ_HI*0x10000/AFSK12_SAMPLE_RATE
56};
57
58static void modulator_1200_u8(struct sm_state *sm, unsigned char *buf,
59			      unsigned int buflen)
60{
61	struct mod_state_afsk12 *st = (struct mod_state_afsk12 *)(&sm->m);
62
63	for (; buflen > 0; buflen--) {
64		if (!((st->txphase++) & 7)) {
65			if (st->shreg <= 1)
66				st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000;
67			st->tx_bit = (st->tx_bit ^ (!(st->shreg & 1))) & 1;
68			st->shreg >>= 1;
69		}
70		st->dds_inc = dds_inc[st->tx_bit & 1];
71		*buf++ = OFFSCOS(st->bit_pll);
72		st->bit_pll += st->dds_inc;
73	}
74}
75
76/* --------------------------------------------------------------------- */
77
78static void modulator_1200_s16(struct sm_state *sm, short *buf, unsigned int buflen)
79{
80	struct mod_state_afsk12 *st = (struct mod_state_afsk12 *)(&sm->m);
81
82	for (; buflen > 0; buflen--) {
83		if (!((st->txphase++) & 7)) {
84			if (st->shreg <= 1)
85				st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000;
86			st->tx_bit = (st->tx_bit ^ (!(st->shreg & 1))) & 1;
87			st->shreg >>= 1;
88		}
89		st->dds_inc = dds_inc[st->tx_bit & 1];
90		*buf++ = COS(st->bit_pll);
91		st->bit_pll += st->dds_inc;
92	}
93}
94
95/* --------------------------------------------------------------------- */
96
97static inline int convolution8_u8(const unsigned char *st, const int *coeff, int csum)
98{
99	int sum = -0x80 * csum;
100
101	sum += (st[0] * coeff[0]);
102	sum += (st[-1] * coeff[1]);
103	sum += (st[-2] * coeff[2]);
104	sum += (st[-3] * coeff[3]);
105	sum += (st[-4] * coeff[4]);
106	sum += (st[-5] * coeff[5]);
107	sum += (st[-6] * coeff[6]);
108	sum += (st[-7] * coeff[7]);
109
110	sum >>= 7;
111	return sum * sum;
112}
113
114static inline int convolution8_s16(const short *st, const int *coeff, int csum)
115{
116	int sum = 0;
117
118	sum += (st[0] * coeff[0]);
119	sum += (st[-1] * coeff[1]);
120	sum += (st[-2] * coeff[2]);
121	sum += (st[-3] * coeff[3]);
122	sum += (st[-4] * coeff[4]);
123	sum += (st[-5] * coeff[5]);
124	sum += (st[-6] * coeff[6]);
125	sum += (st[-7] * coeff[7]);
126
127	sum >>= 15;
128	return sum * sum;
129}
130
131static inline int do_filter_1200_u8(const unsigned char *buf)
132{
133	int sum = convolution8_u8(buf, afsk12_tx_lo_i, SUM_AFSK12_TX_LO_I);
134	sum += convolution8_u8(buf, afsk12_tx_lo_q, SUM_AFSK12_TX_LO_Q);
135	sum -= convolution8_u8(buf, afsk12_tx_hi_i, SUM_AFSK12_TX_HI_I);
136	sum -= convolution8_u8(buf, afsk12_tx_hi_q, SUM_AFSK12_TX_HI_Q);
137	return sum;
138}
139
140static inline int do_filter_1200_s16(const short *buf)
141{
142	int sum = convolution8_s16(buf, afsk12_tx_lo_i, SUM_AFSK12_TX_LO_I);
143	sum += convolution8_s16(buf, afsk12_tx_lo_q, SUM_AFSK12_TX_LO_Q);
144	sum -= convolution8_s16(buf, afsk12_tx_hi_i, SUM_AFSK12_TX_HI_I);
145	sum -= convolution8_s16(buf, afsk12_tx_hi_q, SUM_AFSK12_TX_HI_Q);
146	return sum;
147}
148
149/* --------------------------------------------------------------------- */
150
151static const int pll_corr[2] = { -0x1000, 0x1000 };
152
153static void demodulator_1200_u8(struct sm_state *sm, const unsigned char *buf, unsigned int buflen)
154{
155	struct demod_state_afsk12 *st = (struct demod_state_afsk12 *)(&sm->d);
156	int j;
157	int sum;
158	unsigned char newsample;
159
160	for (; buflen > 0; buflen--, buf++) {
161		sum = do_filter_1200_u8(buf);
162		st->dcd_shreg <<= 1;
163		st->bit_pll += 0x2000;
164		newsample = (sum > 0);
165		if (st->last_sample ^ newsample) {
166			st->last_sample = newsample;
167			st->dcd_shreg |= 1;
168			st->bit_pll += pll_corr
169				[st->bit_pll < 0x9000];
170			j = 4 * hweight8(st->dcd_shreg & 0x38)
171				- hweight16(st->dcd_shreg & 0x7c0);
172			st->dcd_sum0 += j;
173		}
174		hdlcdrv_channelbit(&sm->hdrv, st->last_sample);
175		if ((--st->dcd_time) <= 0) {
176			hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 +
177						   st->dcd_sum1 +
178						   st->dcd_sum2) < 0);
179			st->dcd_sum2 = st->dcd_sum1;
180			st->dcd_sum1 = st->dcd_sum0;
181			st->dcd_sum0 = 2; /* slight bias */
182			st->dcd_time = 120;
183		}
184		if (st->bit_pll >= 0x10000) {
185			st->bit_pll &= 0xffff;
186			st->shreg >>= 1;
187			st->shreg |= (!(st->last_rxbit ^
188					st->last_sample)) << 16;
189			st->last_rxbit = st->last_sample;
190			diag_trigger(sm);
191			if (st->shreg & 1) {
192				hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1);
193				st->shreg = 0x10000;
194			}
195		}
196		diag_add(sm, (((int)*buf)-0x80) << 8, sum);
197	}
198}
199
200/* --------------------------------------------------------------------- */
201
202static void demodulator_1200_s16(struct sm_state *sm, const short *buf, unsigned int buflen)
203{
204	struct demod_state_afsk12 *st = (struct demod_state_afsk12 *)(&sm->d);
205	int j;
206	int sum;
207	unsigned char newsample;
208
209	for (; buflen > 0; buflen--, buf++) {
210		sum = do_filter_1200_s16(buf);
211		st->dcd_shreg <<= 1;
212		st->bit_pll += 0x2000;
213		newsample = (sum > 0);
214		if (st->last_sample ^ newsample) {
215			st->last_sample = newsample;
216			st->dcd_shreg |= 1;
217			st->bit_pll += pll_corr
218				[st->bit_pll < 0x9000];
219			j = 4 * hweight8(st->dcd_shreg & 0x38)
220				- hweight16(st->dcd_shreg & 0x7c0);
221			st->dcd_sum0 += j;
222		}
223		hdlcdrv_channelbit(&sm->hdrv, st->last_sample);
224		if ((--st->dcd_time) <= 0) {
225			hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 +
226						   st->dcd_sum1 +
227						   st->dcd_sum2) < 0);
228			st->dcd_sum2 = st->dcd_sum1;
229			st->dcd_sum1 = st->dcd_sum0;
230			st->dcd_sum0 = 2; /* slight bias */
231			st->dcd_time = 120;
232		}
233		if (st->bit_pll >= 0x10000) {
234			st->bit_pll &= 0xffff;
235			st->shreg >>= 1;
236			st->shreg |= (!(st->last_rxbit ^
237					st->last_sample)) << 16;
238			st->last_rxbit = st->last_sample;
239			diag_trigger(sm);
240			if (st->shreg & 1) {
241				hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1);
242				st->shreg = 0x10000;
243			}
244		}
245		diag_add(sm, *buf, sum);
246	}
247}
248
249/* --------------------------------------------------------------------- */
250
251static void demod_init_1200(struct sm_state *sm)
252{
253	struct demod_state_afsk12 *st = (struct demod_state_afsk12 *)(&sm->d);
254
255       	st->dcd_time = 120;
256	st->dcd_sum0 = 2;
257}
258
259/* --------------------------------------------------------------------- */
260
261const struct modem_tx_info sm_afsk1200_tx = {
262	"afsk1200", sizeof(struct mod_state_afsk12),
263	AFSK12_SAMPLE_RATE, 1200, modulator_1200_u8, modulator_1200_s16, NULL
264};
265
266const struct modem_rx_info sm_afsk1200_rx = {
267	"afsk1200", sizeof(struct demod_state_afsk12),
268	AFSK12_SAMPLE_RATE, 1200, 8, AFSK12_SAMPLE_RATE/1200,
269	demodulator_1200_u8, demodulator_1200_s16, demod_init_1200
270};
271
272/* --------------------------------------------------------------------- */
273