1 // ----------------------------------------------------------------------------
2 // Copyright (C) 2014
3 // David Freese, W1HKJ
4 //
5 // This file is part of flrig.
6 //
7 // flrig is free software; you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License as published by
9 // the Free Software Foundation; either version 3 of the License, or
10 // (at your option) any later version.
11 //
12 // flrig is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // aunsigned long int with this program. If not, see <http://www.gnu.org/licenses/>.
19 // ----------------------------------------------------------------------------
20
21 #include "FT990a.h"
22 #include "rig.h"
23
24 static const char FT990Aname_[] = "FT-990A";
25 static const char *FT990Amodes_[] =
26 { "LSB", "USB", "CW2.4", "CW500",
27 "AM2.4", "FM",
28 "RTTY(L)", "RTTY(U)", "PKT(L)", "PKT(FM)", NULL};
29
30 static const int FT990A_def_bw[] = {
31 0, 0, 0, 2,
32 0, 0,
33 0, 0, 0, 0 };
34
35 static const int FT990A_mode_val[] = {
36 0, 1, 2, 3,
37 4, 5, 6,
38 8, 9, 10, 11 };
39
40 static const char FT990A_mode_type[] = {
41 'L', 'U', 'L', 'L',
42 'U', 'U',
43 'L', 'U', 'L', 'U' };
44
45 static const char *FT990Awidths_[] =
46 { "2400", "2000", "500", "250", NULL};
47
48 static int FT990A_bw_vals[] = {
49 1,2,3,4,WVALS_LIMIT};
50
51 static const int FT990A_bw_val[] =
52 { 0, 1, 2, 3 };
53
RIG_FT990A()54 RIG_FT990A::RIG_FT990A() {
55 name_ = FT990Aname_;
56 modes_ = FT990Amodes_;
57 bandwidths_ = FT990Awidths_;
58 bw_vals_ = FT990A_bw_vals;
59
60 comm_baudrate = BR4800;
61 stopbits = 2;
62 comm_retries = 2;
63 comm_wait = 5;
64 comm_timeout = 100;
65 comm_rtscts = false;
66 comm_rtsplus = false;
67 comm_dtrplus = true;
68 comm_catptt = true;
69 comm_rtsptt = false;
70 comm_dtrptt = false;
71 afreq = bfreq = A.freq = B.freq = 14070000;
72 amode = bmode = A.imode = B.imode = 1;
73 aBW = bBW = A.iBW = B.iBW = 2;
74
75 precision = 10;
76 ndigits = 9;
77
78
79 has_get_info = true;
80
81 has_split = has_split_AB =
82 has_smeter =
83 has_power_out =
84 has_swr_control =
85 has_mode_control =
86 has_bandwidth_control =
87 has_ptt_control = true;
88
89 }
90
adjust_bandwidth(int m)91 int RIG_FT990A::adjust_bandwidth(int m)
92 {
93 if (m == 0 || m == 1 || m == 5) return 2;
94 if (m == 2 || m == 3 ) return 1;
95 if (m == 4 || m == 6 || m == 7) return 3;
96 return 2;
97 }
98
init_cmd()99 void RIG_FT990A::init_cmd()
100 {
101 cmd = "00000";
102 for (size_t i = 0; i < 5; i++) cmd[i] = 0;
103 replystr.clear();
104 }
105
initialize()106 void RIG_FT990A::initialize()
107 {
108 init_cmd();
109 cmd[4] = 0x0E;
110 sendCommand(cmd);
111 }
112
selectA()113 void RIG_FT990A::selectA()
114 {
115 init_cmd();
116 cmd[4] = 0x05;
117 sendCommand(cmd);
118 showresp(WARN, HEX, "select A", cmd, "");
119 }
120
selectB()121 void RIG_FT990A::selectB()
122 {
123 init_cmd();
124 cmd[3] = 0x01;
125 cmd[4] = 0x05;
126 sendCommand(cmd);
127 showresp(WARN, HEX, "select B", cmd, "");
128 }
129
set_split(bool val)130 void RIG_FT990A::set_split(bool val)
131 {
132 split = val;
133 init_cmd();
134 cmd[3] = val ? 0x01 : 0x00;
135 cmd[4] = 0x01;
136 sendCommand(cmd);
137 if (val)
138 showresp(WARN, HEX, "set split ON", cmd, "");
139 else
140 showresp(WARN, HEX, "set split OFF", cmd, "");
141 }
142
check()143 bool RIG_FT990A::check()
144 {
145 init_cmd();
146 cmd[3] = 0x00;
147 cmd[4] = 0xFA;
148 int ret = waitN(5, 100, "check");
149 if (ret >= 5) return true;
150 return false;
151 }
152
get_info()153 bool RIG_FT990A::get_info()
154 {
155 bool memmode = false, vfobmode = false;
156 int pfreq, pmode, pbw;
157 init_cmd();
158 cmd[3] = 0x00;
159 cmd[4] = 0xFA;
160 int ret = waitN(5, 100, "Read flags");
161
162 if (ret >= 5) {
163 size_t p = ret - 5;
164 memmode = ((replystr[p+1] & 0x10) == 0x10);
165 vfobmode = ((replystr[p] & 0x02) == 0x02);
166 if (memmode) return false;
167 if (vfobmode && !useB) {
168 useB = true;
169 Fl::awake(highlight_vfo, (void *)0);
170 } else if (!vfobmode && useB) {
171 useB = false;
172 Fl::awake(highlight_vfo, (void *)0);
173 }
174 }
175
176 init_cmd();
177 cmd[4] = 0x10; // update info
178 cmd[0] = 0x02; // 1 16 byte sequences for current VFO / MEM
179 ret = waitN(16, 100, "Read info");
180
181 if (ret >= 16) {
182 size_t p = ret - 16;
183 // current VFO / MEM
184 pfreq = 0;
185 for (size_t n = 1; n < 5; n++)
186 pfreq = pfreq * 256 + (unsigned char)replystr[p + n];
187 pfreq = pfreq * 1.25; // 100D resolution is 1.25 Hz / bit for read
188
189 int rmode = replystr[p + 7] & 0x07;
190 switch (rmode) {
191 case 0 : pmode = 0; break; // LSB
192 case 1 : pmode = 1; break; // USB
193 case 2 : pmode = 2; break; // CW
194 case 3 : pmode = 5; break; // AM
195 case 4 : pmode = 6; break; // FM
196 case 5 : pmode = 8; break; // RTTY
197 case 6 : pmode = 9; break; // PKT
198 default : pmode = 1; break;
199 }
200
201 int rpbw = replystr[p + 8];
202 pbw = rpbw & 0x05;
203 if (pbw > 4) pbw = 4;
204 if ((rpbw & 0x80) == 0x80) {
205 if (pmode == 10) pmode = 11;
206 if (pmode == 8) pmode = 9;
207 }
208 if (pmode == 6) pbw = 0;
209 if (useB) {
210 B.freq = pfreq; B.imode = pmode; B.iBW = pbw;
211 } else {
212 A.freq = pfreq; A.imode = pmode; A.iBW = pbw;
213 }
214 LOG_WARN("Vfo %c = %d, BW %s", vfobmode ? 'B' : 'A', pfreq, FT990Awidths_[pbw]);
215 return true;
216 }
217 return false;
218 }
219
get_vfoA()220 unsigned long int RIG_FT990A::get_vfoA ()
221 {
222 return A.freq;
223 }
224
set_vfoA(unsigned long int freq)225 void RIG_FT990A::set_vfoA (unsigned long int freq)
226 {
227 A.freq = freq;
228 freq /=10;
229 cmd = to_bcd_be(freq, 8);
230 cmd += 0x0A;
231 sendCommand(cmd);
232 showresp(WARN, HEX, "set freq A", cmd, "");
233 }
234
get_modeA()235 int RIG_FT990A::get_modeA()
236 {
237 return A.imode;
238 }
239
set_modeA(int val)240 void RIG_FT990A::set_modeA(int val)
241 {
242 A.imode = val;
243 init_cmd();
244 cmd[3] = FT990A_mode_val[val];
245 cmd[4] = 0x0C;
246 sendCommand(cmd);
247 showresp(WARN, HEX, "set mode A", cmd, "");
248 }
249
set_bwA(int val)250 void RIG_FT990A::set_bwA (int val)
251 {
252 A.iBW = val;
253 init_cmd();
254 cmd[3] = FT990A_bw_val[val];
255 cmd[4] = 0x8C;
256 sendCommand(cmd);
257 showresp(WARN, HEX, "set BW A", cmd, "");
258 }
259
260
get_bwA()261 int RIG_FT990A::get_bwA()
262 {
263 return A.iBW;
264 }
265
get_vfoB()266 unsigned long int RIG_FT990A::get_vfoB()
267 {
268 return B.freq;
269 }
270
set_vfoB(unsigned long int freq)271 void RIG_FT990A::set_vfoB(unsigned long int freq)
272 {
273 B.freq = freq;
274 freq /=10;
275 cmd = to_bcd_be(freq, 8);
276 cmd += 0x0A;
277 sendCommand(cmd);
278 showresp(WARN, HEX, "set freq B", cmd, "");
279 }
280
set_modeB(int val)281 void RIG_FT990A::set_modeB(int val)
282 {
283 B.imode = val;
284 init_cmd();
285 cmd[3] = FT990A_mode_val[val];
286 cmd[4] = 0x0C;
287 sendCommand(cmd);
288 showresp(WARN, HEX, "set mode B", cmd, "");
289 }
290
get_modeB()291 int RIG_FT990A::get_modeB()
292 {
293 return B.imode;
294 }
295
set_bwB(int val)296 void RIG_FT990A::set_bwB(int val)
297 {
298 B.iBW = val;
299 init_cmd();
300 cmd[3] = FT990A_bw_val[val];
301 cmd[4] = 0x8C;
302 sendCommand(cmd);
303 showresp(WARN, HEX, "set bw B", cmd, "");
304 }
305
get_bwB()306 int RIG_FT990A::get_bwB()
307 {
308 return B.iBW;
309 }
310
def_bandwidth(int m)311 int RIG_FT990A::def_bandwidth(int m)
312 {
313 return FT990A_def_bw[m];
314 }
315
316 // Tranceiver PTT on/off
set_PTT_control(int val)317 void RIG_FT990A::set_PTT_control(int val)
318 {
319 init_cmd();
320 if (val) cmd[3] = 1;
321 cmd[4] = 0x0F;
322 sendCommand(cmd);
323 if (val)
324 showresp(WARN, HEX, "set PTT ON", cmd, "");
325 else
326 showresp(WARN, HEX, "set PTT OFF", cmd, "");
327 ptt_ = val;
328 }
329
get_smeter()330 int RIG_FT990A::get_smeter()
331 {
332 init_cmd();
333 cmd[4] = 0xF7;
334 int ret = waitN(5, 100, "S-meter");
335 if (ret < 5) return 0;
336 int sval = (unsigned char)replybuff[0];
337 if (sval < 90) sval = 90;
338 if (sval > 200) sval = 200;
339 if (sval < 120) sval = 250 - 5 * sval / 3;
340 else sval = 125 - 5 * sval / 8;
341 return sval;
342 }
343
get_swr()344 int RIG_FT990A::get_swr()
345 {
346 return 0;
347 }
348
get_power_out()349 int RIG_FT990A::get_power_out()
350 {
351 init_cmd();
352 cmd[4] = 0xF7;
353 int ret = waitN(5, 100, "Power out");
354 if (ret < 5) return 0;
355 int sval = (unsigned char)replybuff[0];
356 if (sval < 90) sval = 90;
357 if (sval > 200) sval = 200;
358 if (sval < 120) sval = 250 - 5 * sval / 3;
359 else sval = 125 - 5 * sval / 8;
360 return sval;
361 }
362
363