1 // ----------------------------------------------------------------------------
2 //    mt63.cxx  --  MT63 modem for fldigi
3 //
4 // Copyright (C) 1999-2004 Pawel Jalocha, SP9VRC
5 // Copyright (c) 2007-2011 Dave Freese, W1HKJ
6 //
7 // This file is part of fldigi.
8 //
9 // Fldigi is free software: you can redistribute it and/or modify
10 // it under the terms of the GNU General Public License as published by
11 // the Free Software Foundation, either version 3 of the License, or
12 // (at your option) any later version.
13 //
14 // Fldigi is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 // GNU General Public License for more details.
18 //
19 // You should have received a copy of the GNU General Public License
20 // along with fldigi.  If not, see <http://www.gnu.org/licenses/>.
21 // ----------------------------------------------------------------------------
22 
23 #include <config.h>
24 
25 #include "configuration.h"
26 #include "fl_digi.h"
27 #include "status.h"
28 #include "mt63.h"
29 
30 //------------------------------------------------------------------------------
31 #include "threads.h"
32 
33 static pthread_mutex_t mt63_mutex = PTHREAD_MUTEX_INITIALIZER;
34 //------------------------------------------------------------------------------
35 
36 using namespace std;
37 bool startflag = true;
38 
tx_init()39 void mt63::tx_init()
40 {
41 	guard_lock dsp_lock(&mt63_mutex);
42 
43 	Tx->Preset(get_txfreq_woffset(), (int)bandwidth, Interleave == 64 ? 1 : 0);
44 	flush = Tx->DataInterleave;
45 	videoText();
46 	startflag = true;
47 }
48 
rx_init()49 void mt63::rx_init()
50 {
51 	guard_lock dsp_lock(&mt63_mutex);
52 
53 	Rx->Preset( frequency,
54 				(int)bandwidth,
55 				Interleave == 64 ? 1 : 0,
56 				long_integral ? 32 : 16 );
57 	InpLevel->Preset(64.0, 0.75);
58 	escape = 0;
59 }
60 
tx_process()61 int mt63::tx_process()
62 {
63 	rx_flush();
64 // do not put above rx_flush()
65 
66 	modem::tx_process();
67 
68 	guard_lock dsp_lock(&mt63_mutex);
69 
70 	int c;
71 
72 	if (startflag == true) {
73 		startflag = false;
74 		maxval = 0.0;
75 		if (progdefaults.mt63_usetones) {
76 			double w1 = 2.0 * M_PI * (get_txfreq_woffset() - bandwidth / 2.0) / samplerate;
77 			double w2 = 2.0 * M_PI * (get_txfreq_woffset() + 31.0 * bandwidth / 64.0) / samplerate;
78 			double phi1 = 0.0;
79 			double phi2 = 0.0;
80 			double buff[512];
81 			int numsmpls = samplerate * progdefaults.mt63_tone_duration / 512;
82 			for (int i = 0; i < numsmpls; i++) {
83 				for (int j = 0; j < 512; j++) {
84 					buff[j] = TONE_AMP * (progdefaults.mt63_twotones ? 0.5 : 1.0) * cos(phi1) +
85 							  TONE_AMP * (progdefaults.mt63_twotones ? 0.5 : 0.0) * cos(phi2);
86 					phi1 += w1;
87 					phi2 += w2;
88 					if (i == 0) buff[j] *= (1.0 - exp(-1.0 * j / 40.0));
89 					if (i == progdefaults.mt63_tone_duration - 1)
90 						buff[j] *= (1.0 - exp(-1.0 * (samplerate - j) / 40.0));
91 				}
92 				Fl::awake();
93 				ModulateXmtr(buff, 512);
94 			}
95 		}
96 		for (int i = 0; i < Tx->DataInterleave; i++) {
97 			Tx->SendChar(0);
98 			Fl::awake();
99 		}
100 	}
101 
102 	c = get_tx_char();
103 	if (c == GET_TX_CHAR_ETX)  {
104 		stopflag = true;
105 		flush = Tx->DataInterleave;
106 	}
107 
108 	if (c == GET_TX_CHAR_NODATA || stopflag == true) c = 0;
109 
110 	if (stopflag) {
111 		stopflag = false;
112 		while (--flush) {
113 			Tx->SendChar(0);
114 			double buff[Tx->Comb.Output.Len];
115 			for (int i = 0; i < Tx->Comb.Output.Len; i++)
116 				if (fabs(Tx->Comb.Output.Data[i]) > maxval)
117 					maxval = fabs(Tx->Comb.Output.Data[i]);
118 			for (int i = 0; i < Tx->Comb.Output.Len; i++)
119 				buff[i] = Tx->Comb.Output.Data[i] /= maxval;
120 			ModulateXmtr(buff,Tx->Comb.Output.Len);
121 		}
122 		Tx->SendJam();
123 		maxval = 0.0;
124 		double buff[Tx->Comb.Output.Len];
125 		for (int i = 0; i < Tx->Comb.Output.Len; i++)
126 			if (fabs(Tx->Comb.Output.Data[i]) > maxval)
127 				maxval = fabs(Tx->Comb.Output.Data[i]);
128 		for (int i = 0; i < Tx->Comb.Output.Len; i++)
129 			buff[i] = Tx->Comb.Output.Data[i] * 1.0 / maxval;
130 		ModulateXmtr(buff,Tx->Comb.Output.Len);
131 		return -1;	/* we're done */
132 	}
133 
134 	if (c > 255 || (!progdefaults.mt63_8bit && c > 127))
135 		c = '.';
136 
137 	int sendc = c;
138 
139 	if (sendc > 127) {
140 		sendc &= 127;
141 		Tx->SendChar(127);
142 		double buff[Tx->Comb.Output.Len];
143 		for (int i = 0; i < Tx->Comb.Output.Len; i++)
144 			if (fabs(Tx->Comb.Output.Data[i]) > maxval)
145 				maxval = fabs(Tx->Comb.Output.Data[i]);
146 		for (int i = 0; i < Tx->Comb.Output.Len; i++)
147 			buff[i] = Tx->Comb.Output.Data[i] * 1.0 / maxval;
148 		ModulateXmtr(buff,Tx->Comb.Output.Len);
149 	}
150 
151 	Tx->SendChar(sendc);
152 	double buff[Tx->Comb.Output.Len];
153 	int len = Tx->Comb.Output.Len;
154 	for (int i = 0; i < len; i++) {
155 		buff[i] = Tx->Comb.Output.Data[i];
156 		if (maxval < fabs(buff[i])) maxval = fabs(buff[i]);
157 	}
158 	for (int i = 0; i < len; i++) {
159 		buff[i] *= 1.0 / maxval;
160 	}
161 	ModulateXmtr(buff,len);
162 
163 	put_echo_char(c);
164 
165 	return 0;
166 }
167 
rx_process(const double * buf,int len)168 int mt63::rx_process(const double *buf, int len)
169 {
170 	double snr;
171 	unsigned int c;
172 	int i;
173 	static char msg1[20];
174 	static char msg2[20];
175 	double f_offset;
176 
177 	if (long_integral != progdefaults.mt63_rx_integration) {
178 		long_integral = progdefaults.mt63_rx_integration;
179 		restart();
180 	}
181 
182 	if (InpBuff->EnsureSpace(len) == -1) {
183 		fprintf(stderr, "mt63_rxprocess: buffer error\n");
184 		return -1;
185 	}
186 
187 	for (i = 0; i < len; i++)
188 		InpBuff->Data[i] = buf[i];
189 
190 	{ // critical section
191 		guard_lock dsp_lock(&mt63_mutex);
192 
193 		InpBuff->Len = len;
194 		InpLevel->Process(InpBuff);
195 
196 		Rx->Process(InpBuff);
197 
198 		snr = Rx->FEC_SNR();
199 		if (progStatus.sqlonoff && snr < progStatus.sldrSquelchValue) {
200 			put_Status1("");
201 			put_Status2("");
202 			display_metric(0);
203 			return 0;
204 		}
205 
206 		for (i = 0; i < Rx->Output.Len; i++) {
207 			c = Rx->Output.Data[i];
208 			if (!progdefaults.mt63_8bit) {
209 				put_rx_char(c);
210 				continue;
211 			}
212 			if ((c < 8) && (escape == 0))
213 				continue;
214 			if (c == 127) {
215 				escape = 1;
216 				continue;
217 			}
218 			if (escape) {
219 				c += 128;
220 				escape = 0;
221 			}
222 			put_rx_char(c);
223 		}
224 
225 		f_offset = Rx->TotalFreqOffset();
226 
227 	} // end critical section
228 
229 	if (snr > 99.9) snr = 99.9;
230 
231 	display_metric(snr);
232 
233 	double s2n = 10.0*log10( snr == 0 ? 0.001 : snr);
234 	snprintf(msg1, sizeof(msg1), "s/n %2d dB", (int)(floor(s2n)));
235 	put_Status1(msg1);
236 
237 	snprintf(msg2, sizeof(msg2), "f/o %+4.1f Hz", f_offset);
238 	put_Status2(msg2, 5, STATUS_CLEAR);
239 
240 	flushbuffer = true;
241 
242 	return 0;
243 }
244 
rx_flush()245 void mt63::rx_flush()
246 {
247 	guard_lock dsp_lock(&mt63_mutex);
248 
249 	unsigned int c;
250 	int len = 512;
251 	int dlen = 0;
252 
253 	if (!flushbuffer) return;
254 
255 	if (emptyBuff->EnsureSpace(len) == -1) {
256 		flushbuffer = false;
257 		return;
258 	}
259 
260 	for (int j = 0; j < len; j++)
261 		emptyBuff->Data[j] = 0.0;
262 	emptyBuff->Len = len;
263 	InpLevel->Process(emptyBuff);
264 	Rx->Process(emptyBuff);
265 	dlen = Rx->Output.Len;
266 
267 	while (Rx->SYNC_LockStatus()) {
268 		for (int i = 0; i < dlen; i++) {
269 			c = Rx->Output.Data[i];
270 			if (!progdefaults.mt63_8bit) {
271 				put_rx_char(c);
272 				continue;
273 			}
274 			if ((c < 8) && (escape == 0))
275 				continue;
276 			if (c == 127) {
277 				escape = 1;
278 				continue;
279 			}
280 			if (escape) {
281 				c += 128;
282 				escape = 0;
283 			}
284 			put_rx_char(c);
285 		}
286 		for (int j = 0; j < len; j++)
287 			emptyBuff->Data[j] = 0.0;
288 		emptyBuff->Len = len;
289 		InpLevel->Process(emptyBuff);
290 		Rx->Process(emptyBuff);
291 		dlen = Rx->Output.Len;
292 	}
293 	flushbuffer = false;
294 
295 	return;
296 }
297 
restart()298 void mt63::restart()
299 {
300 	int err;
301 
302 	put_MODEstatus(mode);
303 	set_scope_mode(Digiscope::BLANK);
304 
305 	{ // critical section
306 		guard_lock dsp_lock(&mt63_mutex);
307 
308 		err = Tx->Preset(get_txfreq_woffset(), (int)bandwidth, Interleave == 64 ? 1 : 0);
309 		if (err)
310 			fprintf(stderr, "mt63_txinit: init failed\n");
311 		flush = Tx->DataInterleave;
312 
313 		err = Rx->Preset( frequency, (int)bandwidth,
314 					  Interleave == 64 ? 1 : 0,
315 					  long_integral ? 32 : 16);
316 	} // end critical section
317 	if (err)
318 		fprintf(stderr, "mt63_rxinit: init failed\n");
319 	InpLevel->Preset(64.0, 0.75);
320 	stopflag = false;
321 }
322 
init()323 void mt63::init()
324 {
325 	modem::init();
326 	restart();
327 	flushbuffer = false;
328 	maxval = 0.0;
329 
330 	if (progdefaults.mt63_at500) {
331 		frequency = 500 + bandwidth / 2;
332 		modem::set_freq(frequency);
333 	}
334 	else if (progdefaults.mt63_centered) {
335 		frequency = 1500;
336 		modem::set_freq(frequency);
337 	}
338 	else if (progStatus.carrier != 0) {
339 		set_freq(progStatus.carrier);
340 #if !BENCHMARK_MODE
341 		progStatus.carrier = 0;
342 #endif
343 	} else
344 		set_freq(wf->Carrier());
345 
346 }
347 
mt63(trx_mode mt63_mode)348 mt63::mt63 (trx_mode mt63_mode) : modem()
349 {
350 	mode = mt63_mode;
351 	switch (mode) {
352 	case MODE_MT63_500S:
353 		Interleave = 32;
354 		bandwidth = 500;
355 		break;
356 	case MODE_MT63_500L:
357 		Interleave = 64;
358 		bandwidth = 500;
359 		break;
360 	case MODE_MT63_1000S:
361 		Interleave = 32;
362 		bandwidth = 1000;
363 		break;
364 	case MODE_MT63_1000L:
365 		Interleave = 64;
366 		bandwidth = 1000;
367 		break;
368 	case MODE_MT63_2000S:
369 		Interleave = 32;
370 		bandwidth = 2000;
371 		break;
372 	case MODE_MT63_2000L:
373 		Interleave = 64;
374 		bandwidth = 2000;
375 		break;
376 	}
377 
378 	long_integral = progdefaults.mt63_rx_integration;
379 
380 	Tx = new MT63tx;
381 	Rx = new MT63rx;
382 
383 	InpLevel = new dspLevelMonitor;
384 	InpBuff = new double_buff;
385 	emptyBuff = new double_buff;
386 
387 	samplerate = 8000;
388 	fragmentsize = 1024;
389 
390 }
391 
~mt63()392 mt63::~mt63()
393 {
394 	guard_lock dsp_lock(&mt63_mutex);
395 
396 	if (Tx) delete Tx;
397 	if (Rx) delete Rx;
398 
399 	if (InpLevel) delete InpLevel;
400 	if (InpBuff) delete InpBuff;
401 }
402 
403 // W1HKJ
404 // user can select manual or fixed positioning of the MT63 encoder/decoder
405 // progdefaults.mt63_at500 TRUE ==> fixed position
set_freq(double f)406 void mt63::set_freq(double f)
407 {
408 	if (progdefaults.mt63_at500)
409 		frequency = 500 + bandwidth / 2;
410 	else if (progdefaults.mt63_centered)
411 		frequency = 1500;
412 	else
413 		frequency = f;
414 
415 	modem::set_freq(frequency);
416 	rx_init();
417 }
418