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 "TS940S.h"
22 
23 const char TS940Sname_[] = "TS940S";
24 
25 const char *TS940Smodes_[] =             {"LSB", "USB", "CW", "FM", "AM", "FSK", NULL};
26 static const char TS940S_mode_type[] =   {'L',   'U',   'U',  'U',  'U',  'L'        };
27 static const char TS940S_mode_chr[] =    {'1',   '2',   '3',  '4',  '5',  '6',       };
28 
RIG_TS940S()29 RIG_TS940S::RIG_TS940S() {
30 // base class values
31 	name_ = TS940Sname_;
32 	modes_ = TS940Smodes_;
33 	bandwidths_ = NULL;
34 	comm_baudrate = BR4800;
35 	stopbits = 2;
36 	comm_retries = 2;
37 	comm_wait = 5;
38 	comm_timeout = 50;
39 	comm_rtscts = false;
40 	comm_rtsplus = false;
41 	comm_dtrplus = false;
42 	comm_catptt = true;
43 	comm_rtsptt = false;
44 	comm_dtrptt = false;
45 	modeA = 1;
46 	bwA = 2;
47 
48 	has_mode_control =
49 	has_tune_control =
50 	has_split =
51 	has_split_AB =
52 	has_ptt_control = true;
53 
54 	has_attenuator_control =
55 	has_preamp_control =
56 	has_power_control =
57 	has_volume_control =
58 	has_bandwidth_control =
59 	has_micgain_control =
60 	has_notch_control =
61 	has_ifshift_control =
62 	has_swr_control = false;
63 
64 	precision = 10;
65 	ndigits = 7;
66 
67 }
68 
69 /*
70 ========================================================================
71 	frequency & mode data are contained in the IF; response
72 		IFaaaaaaaaaaaXXXXXbbbbbcdXeefghjklmmX;
73 		12345678901234567890123456789012345678
74 		01234567890123456789012345678901234567 byte #
75 		IF00014070000       -00300     000200;
76 
77 		where:
78 			aaaaaaaaaaa => decimal value of vfo frequency
79 			bbbbb => rit/xit frequency
80 			c => rit off/on
81 			d => xit off/on
82 			e => memory channel
83 			f => tx/rx
84 			g => mode
85 			h => function
86 			j => scan off/on
87 			k => split off /on
88 			l => tone off /on
89 			m => tone number
90 			X => unused characters
91 
92 	Test output from Minicom to IF; command
93 
94 	IF00014070000   -00300 000200;
95 
96 	0001000 is vfoA in LSB
97 	0002000 is vfoA in USB
98 	0003000 CW
99 	0004000 FM
100 	0005000 AM
101 	0007000 CWN	(dont have narrow filter however)
102 	0002100 VFOB in USB
103 	0002001 VFOA in USB SPILT
104 	0012000 PTT on in USB
105 ========================================================================
106 */
107 
check()108 bool RIG_TS940S::check ()
109 {
110 	cmd = "FA;";
111 	int ret = wait_char(';', 14, 100, "check", ASC);
112 
113 	get_trace(2, "check()", replystr.c_str());
114 
115 	if (ret < 14) return false;
116 	return true;
117 }
118 
getvfoAorB()119 int RIG_TS940S::getvfoAorB()
120 {
121         int vfovalue =0;
122 	cmd = "IF;";
123 	int ret = wait_char(';', 38, 100, "get vfo a or b", ASC);
124 
125 	get_trace(2, "getvfoAorB()", replystr.c_str());
126 
127 	if (ret < 38) return vfovalue;
128 
129 	vfovalue = replybuff[ret - 38 + 30] - '0';
130 
131 	showresp(WARN, ASC, "get vfo A or B", cmd, "");
132 
133 	return vfovalue;
134 }
135 
136 
get_vfoA()137 unsigned long int RIG_TS940S::get_vfoA ()
138 {
139 	cmd = "FA;";
140 	if (wait_char(';', 14, 100, "get vfo A", ASC) < 14) return A.freq;
141 
142 	get_trace(2, "get_vfoA()", replystr.c_str());
143 
144 	size_t p = replystr.rfind("FA");
145 	if (p != string::npos && (p + 12 < replystr.length())) {
146 		int f = 0;
147 		for (size_t n = 2; n < 13; n++)
148 			f = f*10 + replystr[p+n] - '0';
149 		A.freq = f;
150 	}
151 	return A.freq;
152 }
153 
set_vfoA(unsigned long int freq)154 void RIG_TS940S::set_vfoA (unsigned long int freq)
155 {
156 	A.freq = freq;
157 	cmd = "FA00000000000;";
158 	for (int i = 12; i > 1; i--) {
159 		cmd[i] += freq % 10;
160 		freq /= 10;
161 	}
162 	sendCommand(cmd);
163 	showresp(WARN, ASC, "set vfo A", cmd, "");
164 	set_trace(2, "set_vfoA()", replystr.c_str());
165 }
166 
get_vfoB()167 unsigned long int RIG_TS940S::get_vfoB ()
168 {
169 	cmd = "FB;";
170 	if (wait_char(';', 14, 100, "get vfo B", ASC) < 14) return B.freq;
171 
172 	get_trace(2, "get_vfoB()", replystr.c_str());
173 
174 	size_t p = replystr.rfind("FB");
175 	if (p != string::npos && (p + 12 < replystr.length())) {
176 		int f = 0;
177 		for (size_t n = 2; n < 13; n++)
178 			f = f*10 + replystr[p+n] - '0';
179 		B.freq = f;
180 	}
181 	return B.freq;
182 }
183 
set_vfoB(unsigned long int freq)184 void RIG_TS940S::set_vfoB (unsigned long int freq)
185 {
186 	B.freq = freq;
187 	cmd = "FB00000000000;";
188 	for (int i = 12; i > 1; i--) {
189 		cmd[i] += freq % 10;
190 		freq /= 10;
191 	}
192 	sendCommand(cmd);
193 	showresp(WARN, ASC, "set vfo B", cmd, "");
194 	set_trace(2, "set_vfoB()", replystr.c_str());
195 }
196 
get_modetype(int n)197 int RIG_TS940S::get_modetype(int n)
198 {
199 	return TS940S_mode_type[n];
200 }
201 
set_modeA(int val)202 void RIG_TS940S::set_modeA(int val)
203 {
204 	A.imode = val;
205 	cmd = "MD";
206 	cmd += TS940S_mode_chr[val];
207 	cmd += ';';
208 	sendCommand(cmd);
209 	showresp(WARN, ASC, "set mode", cmd, "");
210 	set_trace(2, "set_mode()", replystr.c_str());
211 }
212 
get_modeA()213 int RIG_TS940S::get_modeA()
214 {
215 	modeA = 0;
216 	cmd = "IF;";
217 	int ret = wait_char(';', 38, 100, "get mode", ASC);
218 
219 	get_trace(2, "get_mode()", replystr.c_str());
220 
221 	if (ret < 38) return modeA;
222 
223 	int md = replybuff[ret - 38 + 29] - '1';
224 	if (md < 0) md = 0;
225 	if (md > 5) md = 5;
226 	modeA = md;
227 
228 	showresp(WARN, ASC, "get mode", cmd, "");
229 
230 	return modeA;
231 }
232 
get_modeB()233 int RIG_TS940S::get_modeB()
234 {
235   return get_modeA();
236 }
237 
set_modeB(int val)238 void RIG_TS940S::set_modeB(int val)
239 {
240   set_modeA(val);
241 }
242 
243 // Tranceiver PTT on/off
set_PTT_control(int val)244 void RIG_TS940S::set_PTT_control(int val)
245 {
246 	if (val) {
247 		sendCommand("TX;");
248 		showresp(WARN, ASC, "TX on", cmd, "");
249 		set_trace(2, "set_PTT(on)", replystr.c_str());
250 	} else {
251 		sendCommand("RX;");
252 		showresp(WARN, ASC, "RX on", cmd, "");
253 		set_trace(2, "set_PTT(off)", replystr.c_str());
254 	}
255 	ptt_ = val;
256 }
257 
258 /*
259 ========================================================================
260 	frequency & mode data are contained in the IF; response
261 		IFaaaaaaaaaaaXXXXXbbbbbcdXeefghjklmmX;
262 		12345678901234567890123456789012345678
263 		01234567890123456789012345678901234567 byte #
264 		          1         2         3
265 		                            ^ position 28
266 		where:
267 			aaaaaaaaaaa => decimal value of vfo frequency
268 			bbbbb => rit/xit frequency
269 			c => rit off/on
270 			d => xit off/on
271 			e => memory channel
272 			f => tx/rx
273 			g => mode
274 			h => function
275 			j => scan off/on
276 			k => split off /on
277 			l => tone off /on
278 			m => tone number
279 			X => unused characters
280 
281 ========================================================================
282 */
283 
get_PTT()284 int RIG_TS940S::get_PTT()
285 {
286 	cmd = "IF;";
287 	int ret = wait_char(';', 38, 100, "get VFO", ASC);
288 
289 	get_trace(2, "get_PTT()", replystr.c_str());
290 
291 	if (ret < 38) return ptt_;
292 	ptt_ = (replybuff[28] == '1');
293 	showresp(WARN, ASC, "get ptt", cmd, "");
294 	return ptt_;
295 }
296 
297 
tune_rig()298 void RIG_TS940S::tune_rig()
299 {
300 	cmd = "AT1;";
301 	LOG_WARN("%s", cmd.c_str());
302 	sendCommand(cmd);
303 	showresp(WARN, ASC, "rig tune set", cmd, "");
304 	set_trace(2, "tune_rig()", replystr.c_str());
305 }
306 
get_split()307 int RIG_TS940S::get_split()
308 {
309 	int splitvalue =0;
310 	cmd = "IF;";
311 	int ret = wait_char(';', 38, 100, "get split", ASC);
312 
313 	get_trace(2, "get_split()", replystr.c_str());
314 
315 	if (ret < 38) return splitvalue;
316 
317 	splitvalue = replybuff[ret - 38 + 32] - '0';
318 
319 	showresp(WARN, ASC, "get split", cmd, "");
320 
321 	return splitvalue;
322 }
323 
set_split(bool val)324 void RIG_TS940S::set_split(bool val)
325 {
326 	if (val) {
327 		cmd = "SP1;";
328 		sendCommand(cmd);
329 		showresp(WARN, ASC, "split on", cmd, "");
330 		set_trace(2, "set_split(on)", replystr.c_str());
331 	} else {
332 		cmd = "SP0;";
333 		sendCommand(cmd);
334 		showresp(WARN, ASC, "split off", cmd, "");
335 		set_trace(2, "set_split(off)", replystr.c_str());
336 	}
337 }
338 
can_split()339 bool RIG_TS940S::can_split()
340 {
341 	return true;
342 }
343 
selectA()344 void RIG_TS940S::selectA()
345 {
346 	set_split(0);
347 	cmd="FN0;";
348 	sendCommand(cmd);
349 	showresp(WARN, ASC, "select VFO A", cmd, "");
350 	set_trace(2, "selectA()", replystr.c_str());
351 }
352 
selectB()353 void RIG_TS940S::selectB()
354 {
355 	set_split(0);
356 	cmd="FN1;";
357 	sendCommand(cmd);
358 	showresp(WARN, ASC, "select VFO B", cmd, "");
359 	set_trace(2, "selectB()", replystr.c_str());
360 }
361