3 common defs and code for parm update
5 This file is part of a program that implements a Software-Defined Radio.
7 Copyright (C) 2004 by Frank Brickle, AB2KT and Bob McGwier, N4HY
9 This program 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 2 of the License, or
12 (at your option) any later version.
14 This program 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.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 The authors can be reached by email at
31 The DTTS Microwave Society
38 ////////////////////////////////////////////////////////////////////////////
39 // for commands affecting RX, which RX is Listening
41 #define RL (uni.multirx.lis)
43 ////////////////////////////////////////////////////////////////////////////
46 dB2lin(REAL dB) { return pow(10.0, dB / 20.0); }
49 setRXFilter(int n, char **p) {
50 REAL low_frequency = atof(p[0]),
51 high_frequency = atof(p[1]);
52 int ncoef = uni.buflen + 1;
53 int i, fftlen = 2 * uni.buflen;
57 if (fabs(low_frequency) >= 0.5 * uni.samplerate) return -1;
58 if (fabs(high_frequency) >= 0.5 * uni.samplerate) return -2;
59 if ((low_frequency + 10) >= high_frequency) return -3;
60 delFIR_COMPLEX(rx[RL].filt.coef);
62 rx[RL].filt.coef = newFIR_Bandpass_COMPLEX(low_frequency,
67 zcvec = newvec_COMPLEX(fftlen, "filter z vec in setFilter");
68 ptmp = fftw_create_plan(fftlen, FFTW_FORWARD, uni.wisdom.bits);
70 for (i = 0; i < ncoef; i++)
71 zcvec[i] = rx[RL].filt.coef->coef[i];
73 for (i = 0; i < ncoef; i++)
74 zcvec[fftlen - ncoef + i] = rx[RL].filt.coef->coef[i];
77 (fftw_complex *) zcvec,
78 (fftw_complex *) rx[RL].filt.ovsv->zfvec);
79 fftw_destroy_plan(ptmp);
80 delvec_COMPLEX(zcvec);
81 normalize_vec_COMPLEX(rx[RL].filt.ovsv->zfvec,
82 rx[RL].filt.ovsv->fftlen);
83 memcpy((char *) rx[RL].filt.save,
84 (char *) rx[RL].filt.ovsv->zfvec,
85 rx[RL].filt.ovsv->fftlen * sizeof(COMPLEX));
92 setTXFilter(int n, char **p) {
93 REAL low_frequency = atof(p[0]),
94 high_frequency = atof(p[1]);
95 int ncoef = uni.buflen + 1;
96 int i, fftlen = 2 * uni.buflen;
100 if (fabs(low_frequency) >= 0.5 * uni.samplerate) return -1;
101 if (fabs(high_frequency) >= 0.5 * uni.samplerate) return -2;
102 if ((low_frequency + 10) >= high_frequency) return -3;
103 delFIR_COMPLEX(tx.filt.coef);
104 tx.filt.coef = newFIR_Bandpass_COMPLEX(low_frequency,
109 zcvec = newvec_COMPLEX(fftlen, "filter z vec in setFilter");
110 ptmp = fftw_create_plan(fftlen, FFTW_FORWARD, uni.wisdom.bits);
112 for (i = 0; i < ncoef; i++)
113 zcvec[i] = tx.filt.coef->coef[i];
115 for (i = 0; i < ncoef; i++)
116 zcvec[fftlen - ncoef + i] = tx.filt.coef->coef[i];
119 (fftw_complex *) zcvec,
120 (fftw_complex *) tx.filt.ovsv->zfvec);
121 fftw_destroy_plan(ptmp);
122 delvec_COMPLEX(zcvec);
123 normalize_vec_COMPLEX(tx.filt.ovsv->zfvec,
124 tx.filt.ovsv->fftlen);
125 memcpy((char *) tx.filt.save,
126 (char *) tx.filt.ovsv->zfvec,
127 tx.filt.ovsv->fftlen * sizeof(COMPLEX));
133 setFilter(int n, char **p) {
134 if (n == 2) return setRXFilter(n, p);
136 int trx = atoi(p[2]);
137 if (trx == RX) return setRXFilter(n, p);
138 else if (trx == TX) return setTXFilter(n, p);
143 // setMode <mode> [TRX]
146 setMode(int n, char **p) {
147 int mode = atoi(p[0]);
149 int trx = atoi(p[1]);
151 case TX: tx.mode = mode; break;
153 default: rx[RL].mode = mode; break;
156 tx.mode = rx[RL].mode = uni.mode.sdr = mode;
157 if (rx[RL].mode == AM) rx[RL].am.gen->mode = AMdet;
158 if (rx[RL].mode == SAM) rx[RL].am.gen->mode = SAMdet;
162 // setOsc <freq> [TRX]
164 setOsc(int n, char **p) {
165 REAL newfreq = atof(p[0]);
166 if (fabs(newfreq) >= 0.5 * uni.samplerate) return -1;
167 newfreq *= 2.0 * M_PI / uni.samplerate;
169 int trx = atoi(p[1]);
171 case TX: tx.osc.gen->Frequency = newfreq; break;
173 default: rx[RL].osc.gen->Frequency = newfreq; break;
176 tx.osc.gen->Frequency = rx[RL].osc.gen->Frequency = newfreq;
181 setSampleRate(int n, char **p) {
182 REAL samplerate = atof(p[0]);
183 uni.samplerate = samplerate;
188 setNR(int n, char **p) {
189 rx[RL].anr.flag = atoi(p[0]);
194 setANF(int n, char **p) {
195 rx[RL].anf.flag = atoi(p[0]);
200 setNB(int n, char **p) {
201 rx[RL].nb.flag = atoi(p[0]);
206 setNBvals(int n, char **p) {
207 REAL threshold = atof(p[0]);
208 rx[RL].nb.gen->threshold = rx[RL].nb.thresh = threshold;
213 setSDROM(int n, char **p) {
214 rx[RL].nb_sdrom.flag = atoi(p[0]);
219 setSDROMvals(int n, char **p) {
220 REAL threshold = atof(p[0]);
221 rx[RL].nb_sdrom.gen->threshold = rx[RL].nb_sdrom.thresh = threshold;
226 setBIN(int n, char **p) {
227 rx[RL].bin.flag = atoi(p[0]);
231 // setfixedAGC <gain> [TRX]
233 setfixedAGC(int n, char **p) {
234 REAL gain = atof(p[0]);
236 int trx = atoi(p[1]);
238 case TX: tx.agc.gen->gain.now = gain; break;
240 default: rx[RL].agc.gen->gain.now = gain; break;
243 tx.agc.gen->gain.now = rx[RL].agc.gen->gain.now = gain;
248 setRXAGC(int n, char **p) {
249 int setit = atoi(p[0]);
252 rx[RL].agc.gen->mode = agcOFF;
253 rx[RL].agc.flag = TRUE;
256 rx[RL].agc.gen->mode = agcSLOW;
257 rx[RL].agc.gen->hang = 10;
258 rx[RL].agc.flag = TRUE;
261 rx[RL].agc.gen->mode = agcMED;
262 rx[RL].agc.gen->hang = 6;
263 rx[RL].agc.flag = TRUE;
266 rx[RL].agc.gen->mode = agcFAST;
267 rx[RL].agc.gen->hang = 3;
268 rx[RL].agc.flag = TRUE;
271 rx[RL].agc.gen->mode = agcLONG;
272 rx[RL].agc.gen->hang = 23;
273 rx[RL].agc.flag = TRUE;
280 setRXAGCCompression(int n, char **p) {
281 REAL rxcompression = atof(p[0]);
282 rx[RL].agc.gen->gain.top = pow(10.0 , rxcompression * 0.05);
287 setRXAGCHang(int n, char **p) {
288 int hang = atoi(p[0]);
289 rx[RL].agc.gen->hang =
292 hang * uni.samplerate / (1e3 * uni.buflen)));
297 setRXAGCLimit(int n, char **p) {
298 REAL limit = atof(p[0]);
299 rx[RL].agc.gen->gain.lim = 0.001 * limit;
304 setTXAGC(int n, char **p) {
305 int setit = atoi(p[0]);
308 tx.agc.gen->mode = agcOFF;
312 tx.agc.gen->mode = agcSLOW;
313 tx.agc.gen->hang = 10;
317 tx.agc.gen->mode = agcMED;
318 tx.agc.gen->hang = 6;
322 tx.agc.gen->mode = agcFAST;
323 tx.agc.gen->hang = 3;
327 tx.agc.gen->mode = agcLONG;
328 tx.agc.gen->hang = 23;
336 setTXAGCCompression(int n, char **p) {
337 REAL txcompression = atof(p[0]);
338 tx.agc.gen->gain.top = pow(10.0 , txcompression * 0.05);
343 setTXAGCFF(int n, char **p) {
344 tx.spr.flag = atoi(p[0]);
349 setTXAGCFFCompression(int n, char **p) {
350 REAL txcompression = atof(p[0]);
351 tx.spr.gen->MaxGain = pow(10.0 , txcompression * 0.05);
356 setTXAGCHang(int n, char **p) {
357 int hang = atoi(p[0]);
361 hang * uni.samplerate / (1e3 * uni.buflen)));
366 setTXAGCLimit(int n, char **p) {
367 REAL limit = atof(p[0]);
368 tx.agc.gen->gain.lim = 0.001 * limit;
373 setTXSpeechCompression(int n, char **p) {
374 tx.spr.flag = atoi(p[0]);
379 setTXSpeechCompressionGain(int n, char **p) {
380 tx.spr.gen->MaxGain = dB2lin(atof(p[0]));
384 //============================================================
388 REAL fix = tx.filt.ovsv->fftlen * f / uni.samplerate;
389 return (int) (fix + 0.5);
392 //------------------------------------------------------------
395 apply_txeq_band(REAL lof, REAL dB, REAL hif) {
399 l = tx.filt.ovsv->fftlen;
401 COMPLEX *src = tx.filt.save,
402 *trg = tx.filt.ovsv->zfvec;
403 for (i = lox; i < hix; i++) {
404 trg[i] = Cscl(src[i], g);
407 trg[j] = Cscl(src[j], g);
413 // 0 dB1 75 dB2 150 dB3 300 dB4 600 dB5 1200 dB6 2000 dB7 2800 dB8 3600
414 // approximates W2IHY bandcenters.
415 // no args, revert to no EQ.
418 setTXEQ(int n, char **p) {
421 memcpy((char *) tx.filt.ovsv->zfvec,
422 (char *) tx.filt.save,
423 tx.filt.ovsv->fftlen * sizeof(COMPLEX));
427 REAL lof = atof(p[0]);
428 for (i = 0; i < n - 2; i += 2) {
429 REAL dB = atof(p[i + 1]),
430 hif = atof(p[i + 2]);
431 if (lof < 0.0 || hif <= lof) return -1;
432 apply_txeq_band(lof, dB, hif);
439 //------------------------------------------------------------
442 apply_rxeq_band(REAL lof, REAL dB, REAL hif) {
446 l = rx[RL].filt.ovsv->fftlen;
448 COMPLEX *src = rx[RL].filt.save,
449 *trg = rx[RL].filt.ovsv->zfvec;
450 for (i = lox; i < hix; i++) {
451 trg[i] = Cscl(src[i], g);
454 trg[j] = Cscl(src[j], g);
460 setRXEQ(int n, char **p) {
463 memcpy((char *) rx[RL].filt.ovsv->zfvec,
464 (char *) rx[RL].filt.save,
465 rx[RL].filt.ovsv->fftlen * sizeof(COMPLEX));
469 REAL lof = atof(p[0]);
470 for (i = 0; i < n - 2; i += 2) {
471 REAL dB = atof(p[i + 1]),
472 hif = atof(p[i + 2]);
473 if (lof < 0.0 || hif <= lof) return -1;
474 apply_rxeq_band(lof, dB, hif);
481 //============================================================
484 setANFvals(int n, char **p) {
485 int taps = atoi(p[0]),
487 REAL gain = atof(p[2]),
489 rx[RL].anf.gen->adaptive_filter_size = taps;
490 rx[RL].anf.gen->delay = delay;
491 rx[RL].anf.gen->adaptation_rate = gain;
492 rx[RL].anf.gen->leakage = leak;
497 setNRvals(int n, char **p) {
498 int taps = atoi(p[0]),
500 REAL gain = atof(p[2]),
502 rx[RL].anr.gen->adaptive_filter_size = taps;
503 rx[RL].anr.gen->delay = delay;
504 rx[RL].anr.gen->adaptation_rate = gain;
505 rx[RL].anr.gen->leakage = leak;
510 setcorrectIQ(int n, char **p) {
511 int phaseadjustment = atoi(p[0]),
512 gainadjustment = atoi(p[1]);
513 rx[RL].iqfix->phase = 0.001 * (REAL) phaseadjustment;
514 rx[RL].iqfix->gain = 1.0+ 0.001 * (REAL) gainadjustment;
519 setcorrectIQphase(int n, char **p) {
520 int phaseadjustment = atoi(p[0]);
521 rx[RL].iqfix->phase = 0.001 * (REAL) phaseadjustment;
526 setcorrectIQgain(int n, char **p) {
527 int gainadjustment = atoi(p[0]);
528 rx[RL].iqfix->gain = 1.0 + 0.001 * (REAL) gainadjustment;
533 setSquelch(int n, char **p) {
534 rx[RL].squelch.thresh = -atof(p[0]);
539 setSquelchSt(int n, char **p) {
540 rx[RL].squelch.flag = atoi(p[0]);
545 setTRX(int n, char **p) {
546 uni.mode.trx = atoi(p[0]);
551 setRunState(int n, char **p) {
552 RUNMODE rs = (RUNMODE) atoi(p[0]);
558 setSpotToneVals(int n, char **p) {
559 REAL gain = atof(p[0]),
563 setSpotToneGenVals(rx[RL].spot.gen, gain, freq, rise, fall);
568 setSpotTone(int n, char **p) {
570 SpotToneOn(rx[RL].spot.gen);
571 rx[RL].spot.flag = TRUE;
573 SpotToneOff(rx[RL].spot.gen);
578 setRXPreScl(int n, char **p) {
579 rx[RL].scl.pre.flag = atoi(p[0]);
584 setRXPreSclVal(int n, char **p) {
585 rx[RL].scl.pre.val = dB2lin(atof(p[0]));
590 setTXPreScl(int n, char **p) {
591 tx.scl.pre.flag = atoi(p[0]);
596 setTXPreSclVal(int n, char **p) {
597 tx.scl.pre.val = dB2lin(atof(p[0]));
602 setRXPostScl(int n, char **p) {
603 rx[RL].scl.post.flag = atoi(p[0]);
608 setRXPostSclVal(int n, char **p) {
609 rx[RL].scl.post.val = dB2lin(atof(p[0]));
614 setTXPostScl(int n, char **p) {
615 tx.scl.post.flag = atoi(p[0]);
620 setTXPostSclVal(int n, char **p) {
621 tx.scl.post.val = dB2lin(atof(p[0]));
626 setFinished(int n, char **p) {
628 pthread_cancel(top.thrd.trx.id);
629 pthread_cancel(top.thrd.upd.id);
630 pthread_cancel(top.thrd.mon.id);
634 // next-trx-mode [nbufs-to-zap]
636 setSWCH(int n, char **p) {
637 top.swch.trx.next = atoi(p[0]);
638 if (n > 1) top.swch.bfct.want = atoi(p[1]);
639 else top.swch.bfct.want = 0;
640 top.swch.bfct.have = 0;
641 top.swch.run.last = top.state;
642 top.state = RUN_SWCH;
647 setMonDump(int n, char **p) {
648 sem_post(&top.sync.mon.sem);
653 setRingBufferReset(int n, char **p) {
654 extern void clear_jack_ringbuffer(jack_ringbuffer_t *rb, int nbytes);
655 jack_ringbuffer_reset(top.jack.ring.i.l);
656 jack_ringbuffer_reset(top.jack.ring.i.r);
657 jack_ringbuffer_reset(top.jack.ring.o.l);
658 jack_ringbuffer_reset(top.jack.ring.o.r);
659 clear_jack_ringbuffer(top.jack.ring.o.l, top.hold.size.bytes);
660 clear_jack_ringbuffer(top.jack.ring.o.r, top.hold.size.bytes);
665 setRXListen(int n, char **p) {
666 int lis = atoi(p[0]);
667 if (lis < 0 || lis >= uni.multirx.nrx)
670 uni.multirx.lis = lis;
676 setRXOn(int n, char **p) {
678 if (uni.multirx.act[RL])
681 uni.multirx.act[RL] = TRUE;
688 if (k < 0 || k >= uni.multirx.nrx)
691 if (uni.multirx.act[k])
694 uni.multirx.act[k] = TRUE;
704 setRXOff(int n, char **p) {
706 if (!uni.multirx.act[RL])
709 uni.multirx.act[RL] = FALSE;
715 if (k < 0 || k >= uni.multirx.nrx)
718 if (!uni.multirx.act[k])
721 uni.multirx.act[k] = FALSE;
730 setRXPan(int n, char **p) {
734 theta = (1.0 - pos) * M_PI / 2.0;
735 rx[RL].azim = Cmplx(cos(theta), sin(theta));
738 if ((pos = atof(p[0])) < 0.0 || pos > 1.0)
740 theta = (1.0 - pos) * M_PI / 2.0;
741 rx[RL].azim = Cmplx(cos(theta), sin(theta));
746 //========================================================================
750 CTE update_cmds[] = {
752 {"setANFvals", setANFvals},
754 {"setFilter", setFilter},
755 {"setFinished", setFinished},
756 {"setMode", setMode},
758 {"setNBvals", setNBvals},
760 {"setNRvals", setNRvals},
762 {"setRXAGC", setRXAGC},
763 {"setRXAGCCompression", setRXAGCCompression},
764 {"setRXAGCHang", setRXAGCHang},
765 {"setRXAGCLimit", setRXAGCLimit},
766 {"setRXEQ", setRXEQ},
767 {"setRXPostScl", setRXPostScl},
768 {"setRXPostSclVal", setRXPostSclVal},
769 {"setRXPreScl", setRXPreScl},
770 {"setRXPreSclVal", setRXPreSclVal},
771 {"setRunState", setRunState},
772 {"setSDROM", setSDROM},
773 {"setSDROMvals",setSDROMvals},
774 {"setSWCH", setSWCH},
775 {"setSampleRate", setSampleRate},
776 {"setSpotTone", setSpotTone},
777 {"setSpotToneVals", setSpotToneVals},
778 {"setSquelch", setSquelch},
779 {"setSquelchSt", setSquelchSt},
781 {"setTXAGC", setTXAGC},
782 {"setTXAGCCompression", setTXAGCCompression},
783 {"setTXAGCFFCompression",setTXAGCFFCompression},
784 {"setTXAGCHang", setTXAGCHang},
785 {"setTXAGCLimit", setTXAGCLimit},
786 {"setTXEQ", setTXEQ},
787 {"setTXPostScl", setTXPostScl},
788 {"setTXPostSclVal", setTXPostSclVal},
789 {"setTXPreScl", setTXPreScl},
790 {"setTXPreSclVal", setTXPreSclVal},
791 {"setTXSpeechCompression", setTXSpeechCompression},
792 {"setTXSpeechCompressionGain", setTXSpeechCompressionGain},
793 {"setcorrectIQ", setcorrectIQ},
794 {"setcorrectIQgain", setcorrectIQgain},
795 {"setcorrectIQphase", setcorrectIQphase},
796 {"setfixedAGC", setfixedAGC},
797 {"setMonDump", setMonDump},
798 {"setRingBufferReset", setRingBufferReset},
799 {"setRXListen", setRXListen},
800 {"setRXOn", setRXOn},
801 {"setRXOff", setRXOff},
802 {"setRXPan", setRXPan},
806 //........................................................................
809 do_update(char *str, FILE *log) {
810 SPLIT splt = &uni.update.splt;
814 if (NF(splt) < 1) return -1;
817 Thunk thk = Thunk_lookup(update_cmds, F(splt, 0));
822 sem_wait(&top.sync.upd.sem);
823 val = (*thk)(NF(splt) - 1, Fptr(splt, 1));
824 sem_post(&top.sync.upd.sem);
828 char *s = since(&top.start_tv);
829 fprintf(log, "update[%s]: returned %d from", s, val);
830 for (i = 0; i < NF(splt); i++)
831 fprintf(log, " %s", F(splt, i));