1 /* -*- c++ -*- */
2 /*
3  * Gqrx SDR: Software defined radio receiver powered by GNU Radio and Qt
4  *           https://gqrx.dk/
5  *
6  * Copyright 2011-2013 Alexandru Csete OZ9AEC.
7  *
8  * Gqrx 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 3, or (at your option)
11  * any later version.
12  *
13  * Gqrx 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 Gqrx; see the file COPYING.  If not, write to
20  * the Free Software Foundation, Inc., 51 Franklin Street,
21  * Boston, MA 02110-1301, USA.
22  */
23 #include <QDebug>
24 #include "demod_options.h"
25 #include "ui_demod_options.h"
26 
27 
28 /* convert between deemphasis time constant and combo-index */
29 const double tau_tbl[] = {
30     0.0, 25.0e-6, 50.0e-6, 75.0e-6, 100.0e-6, 250.0e-6, 530.0e-6, 1.0e-3
31 };
32 const int tau_tbl_maxidx = 7;
33 
tau_from_index(int index)34 double tau_from_index(int index)
35 {
36     if (index < 0 || index > tau_tbl_maxidx)
37         return 0.0;
38 
39     return tau_tbl[index];
40 }
41 
tau_to_index(double tau)42 int tau_to_index(double tau)
43 {
44     int i;
45     for (i = 0; i < tau_tbl_maxidx; i++)
46     {
47         if (tau < (tau_tbl[i] + 0.5 * (tau_tbl[i+1] - tau_tbl[i])))
48             return i;
49     }
50     return 0;
51 }
52 
53 /* convert betweenFM max dev and combo index */
maxdev_from_index(int index)54 float maxdev_from_index(int index)
55 {
56     switch(index)
57     {
58     case 0:
59         /* Voice 2.5k */
60         return 2500.0;
61     case 1:
62         /* Voice 5k */
63         return 5000.0;
64     case 2:
65         /* APT 17k */
66         return 17000.0;
67     case 3:
68         /* APT 25k (17k but need some margin for Doppler and freq error) */
69         return 25000.0;
70     default:
71         /* Voice 5k */
72         qDebug() << "Invalid max_dev index: " << index;
73         return 5000.0;
74     }
75 }
76 
maxdev_to_index(float max_dev)77 int maxdev_to_index(float max_dev)
78 {
79     if (max_dev < 3000.0)
80         /* Voice 2.5k */
81         return 0;
82     else if (max_dev < 10000.0)
83         /* Voice 5k */
84         return 1;
85     else if (max_dev < 20000.0)
86         /* APT 17k */
87         return 2;
88     else
89         /* APT 25k */
90         return 3;
91 }
92 
93 /* convert between synchronous AM PLL bandwidth and combo index */
pll_bw_from_index(int index)94 static float pll_bw_from_index(int index)
95 {
96     switch(index)
97     {
98     case 0:
99         /* Fast */
100         return 0.01;
101     case 1:
102         /* Medium */
103         return 0.001;
104     case 2:
105         /* Slow */
106         return 0.0001;
107     default:
108         qDebug() << "Invalid AM-Sync PLL BW index: " << index;
109         return 0.001;
110     }
111 }
112 
pll_bw_to_index(float pll_bw)113 static int pll_bw_to_index(float pll_bw)
114 {
115     if (pll_bw < 0.00015)
116         /* Slow */
117         return 2;
118     else if (pll_bw < 0.0015)
119         /* Medium */
120         return 1;
121     else if (pll_bw < 0.015)
122         /* Fast */
123         return 0;
124     else
125         /* Medium */
126         return 1;
127 }
128 
CDemodOptions(QWidget * parent)129 CDemodOptions::CDemodOptions(QWidget *parent) :
130     QDialog(parent),
131     ui(new Ui::CDemodOptions)
132 {
133     ui->setupUi(this);
134 }
135 
~CDemodOptions()136 CDemodOptions::~CDemodOptions()
137 {
138     delete ui;
139 }
140 
141 
142 /*! \brief Catch window close events.
143  *
144  * This method is called when the user closes the demod options dialog
145  * window using the window close icon. We catch the event and hide the
146  * dialog but keep it around for later use.
147  */
closeEvent(QCloseEvent * event)148 void CDemodOptions::closeEvent(QCloseEvent *event)
149 {
150     hide();
151     event->ignore();
152 }
153 
setCurrentPage(int index)154 void CDemodOptions::setCurrentPage(int index)
155 {
156     if (index < PAGE_NUM)
157         ui->demodOptions->setCurrentIndex(index);
158 }
159 
currentPage() const160 int CDemodOptions::currentPage() const
161 {
162     return ui->demodOptions->currentIndex();
163 }
164 
setCwOffset(int offset)165 void CDemodOptions::setCwOffset(int offset)
166 {
167     ui->cwOffsetSpin->setValue(offset);
168 }
169 
getCwOffset(void) const170 int  CDemodOptions::getCwOffset(void) const
171 {
172     return ui->cwOffsetSpin->value();
173 }
174 
setMaxDev(float max_dev)175 void CDemodOptions::setMaxDev(float max_dev)
176 {
177     ui->maxdevSelector->setCurrentIndex(maxdev_to_index(max_dev));
178 }
179 
getMaxDev(void) const180 float CDemodOptions::getMaxDev(void) const
181 {
182     return maxdev_from_index(ui->maxdevSelector->currentIndex());
183 }
184 
setEmph(double tau)185 void CDemodOptions::setEmph(double tau)
186 {
187     ui->emphSelector->setCurrentIndex((tau_to_index(tau)));
188 }
189 
getEmph(void) const190 double CDemodOptions::getEmph(void) const
191 {
192     return tau_from_index(ui->emphSelector->currentIndex());
193 }
194 
on_maxdevSelector_activated(int index)195 void CDemodOptions::on_maxdevSelector_activated(int index)
196 {
197     emit fmMaxdevSelected(maxdev_from_index(index));
198 }
199 
on_emphSelector_activated(int index)200 void CDemodOptions::on_emphSelector_activated(int index)
201 {
202     emit fmEmphSelected(tau_from_index(index));
203 }
204 
on_dcrCheckBox_toggled(bool checked)205 void CDemodOptions::on_dcrCheckBox_toggled(bool checked)
206 {
207     emit amDcrToggled(checked);
208 }
209 
on_cwOffsetSpin_valueChanged(int value)210 void CDemodOptions::on_cwOffsetSpin_valueChanged(int value)
211 {
212     emit cwOffsetChanged(value);
213 }
214 
on_syncdcrCheckBox_toggled(bool checked)215 void CDemodOptions::on_syncdcrCheckBox_toggled(bool checked)
216 {
217     emit amSyncDcrToggled(checked);
218 }
219 
setPllBw(float pll_bw)220 void CDemodOptions::setPllBw(float pll_bw)
221 {
222     ui->pllBwSelector->setCurrentIndex(pll_bw_to_index(pll_bw));
223 }
224 
getPllBw(void) const225 float CDemodOptions::getPllBw(void) const
226 {
227     return pll_bw_from_index(ui->pllBwSelector->currentIndex());
228 }
229 
on_pllBwSelector_activated(int index)230 void CDemodOptions::on_pllBwSelector_activated(int index)
231 {
232     emit amSyncPllBwSelected(pll_bw_from_index(index));
233 }
234