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