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 <stdlib.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <math.h>
25 
26 #include "RAY152.h"
27 
28 //=============================================================================
29 
30 const char RIG_RAY152name_[] = "RAY 152";
31 
32 const char *RIG_RAY152modes_[] = { "USB", "LSB", "H3E", "A1A", "F1B", NULL};
33 static const char RIG_RAY152_mode_type[] = {'U', 'L', 'U', 'L', 'U'};
34 
35 static GUI rig_widgets[]= {
36 	{ (Fl_Widget *)btnVol, 2, 145,  50 },
37 	{ (Fl_Widget *)sldrVOLUME, 54, 145, 368 },
38 	{ (Fl_Widget *)sldrRFGAIN, 54, 125, 156 },
39 	{ (Fl_Widget *)sldrSQUELCH, 266, 125, 156 },
40 	{ (Fl_Widget *)NULL, 0, 0, 0 }
41 };
42 
RIG_RAY152()43 RIG_RAY152::RIG_RAY152() {
44 	name_ = RIG_RAY152name_;
45 	modes_ = RIG_RAY152modes_;
46 
47 	widgets = rig_widgets;
48 
49 	comm_baudrate = BR1200;
50 	stopbits = 1;
51 	comm_retries = 2;
52 	comm_wait = 10;
53 	comm_timeout = 50;
54 	comm_echo = true;
55 	comm_rtscts = false;
56 	comm_rtsplus = false;
57 	comm_dtrplus = true;
58 	comm_catptt = true;
59 	comm_rtsptt = false;
60 	comm_dtrptt = false;
61 
62 	A.freq = 14070000;
63 	A.imode = 0;
64 	A.iBW = 0;
65 
66 	B.freq = 3580000;
67 	B.imode = 0;
68 	B.iBW = 0;
69 
70 	precision = 100;
71 	ndigits = 6;
72 
73 	has_mode_control = true;
74 	has_ptt_control = true;
75 	has_rf_control = true;
76 	has_volume_control = true;
77 	has_rit = true;
78 	has_sql_control = true;
79 	has_noise_control = true;
80 	has_auto_notch = true;
81 };
82 
83 
nocr(string & s)84 static void nocr( string & s)
85 {
86 	for (size_t i = 0; i < s.length(); i++)
87 		if (s[i] == '\r') s[i] = ' ';
88 }
89 
90 /*
91 Data string returned by the 'O' command
92 		3	A*\r         AGC ON/OFF
93 		5	C***\r       Memory channel #
94 		5	D+/-**\r     Clarifier frequency
95 		9	FT******\r  Transmit frequemcy
96 		9	FR******\r  Receive frequency
97 		6	I****\r      ITU channel #
98 		3	M*\r         Mode
99 		3	N*\r         Noise blanker status
100 		3	P*\r         Power reduction status
101 		5	Q***\r       Squelch setting
102 		5	R***\r       RF gain setting
103 		5	V***\r       Volume setting
104 		3	Z*\r         Meter function
105 total  64
106 */
107 
check()108 bool RIG_RAY152::check()
109 {
110 	int ret = sendCommand("O\r");
111 	if (ret < 66) return false;
112 	return true;
113 }
114 
get_data()115 void RIG_RAY152::get_data()
116 {
117 	int ret = sendCommand("O\r");
118 	if (ret < 66) return;
119 // test string
120 //replystr = "A1\rC000\rD-05\rFT1407000\rFR1407000\rI0000\rM1\rN1\rP0\rQ000\rR100\rV128\rZ1\r";
121 
122 	if (dumpdata)
123 		LOG_WARN("\n%s", replystr.c_str());
124 	dumpdata = false;
125 
126 	size_t pos;
127 
128 	pos = replystr.find("FR"); // receive frequency
129 	if (pos != string::npos) {
130 		int freq;
131 		sscanf(&replystr[pos + 2], "%d", &freq);
132 		A.freq = 100 * freq;
133 	}
134 
135 	pos = replystr.find("M"); // mode
136 	if (pos != string::npos)
137 		A.imode = replystr[pos + 1] - '1';
138 
139 	pos = replystr.find("D");
140 	if (pos != string::npos) {
141 		sscanf(&replystr[pos + 1], "%d", &RitFreq);
142 		RitFreq *= 10;
143 	}
144 
145 	pos = replystr.find("\rR");
146 	if (pos != string::npos)
147 		sscanf(&replystr[pos + 2], "%d", &rfg);
148 
149 	pos = replystr.find("V");
150 	if (pos != string::npos) {
151 		sscanf(&replystr[pos + 1], "%d", &vol);
152 		vol *= 100;
153 		vol /= 255;
154 	}
155 
156 	pos = replystr.find("Q");
157 	if (pos != string::npos) {
158 		sscanf(&replystr[pos + 1], "%d", &squelch);
159 	}
160 
161 	pos = replystr.find("N");
162 	if (pos != string::npos) {
163 		if (replystr[pos + 1] > '0') {
164 			nb_set = replystr[pos+1];
165 			nb = 1;
166 		}
167 		else {
168 			nb = 0;
169 			nb_set = '2';
170 		}
171 	}
172 
173 // RAY152 usurps the autonotch button for AGC control
174 	pos = replystr.find("A");
175 	if (pos != string::npos)
176 		agc = replystr[1] == '1' ? 1 : 0;
177 
178 }
179 
initialize()180 void RIG_RAY152::initialize()
181 {
182 	rig_widgets[0].W = btnVol;
183 	rig_widgets[1].W = sldrVOLUME;
184 	rig_widgets[2].W = sldrRFGAIN;
185 	rig_widgets[3].W = sldrSQUELCH;
186 
187 	sendCommand("E1\r", 0);
188 	sendCommand("Z1\r", 0);
189 	dumpdata = true;
190 	get_data();
191 	set_auto_notch(agc);
192 }
193 
shutdown()194 void RIG_RAY152::shutdown()
195 {
196 	sendCommand("E0\r", 0);
197 LOG_INFO("%s", cmd.c_str());
198 }
199 
get_vfoA()200 unsigned long int RIG_RAY152::get_vfoA ()
201 {
202 	return A.freq;
203 }
204 
set_vfoA(unsigned long int freq)205 void RIG_RAY152::set_vfoA (unsigned long int freq)
206 {
207 	A.freq = freq;
208 	cmd = "FT000000\r";
209 	freq /= 100;
210 	cmd[7] += freq % 10; freq /= 10;
211 	cmd[6] += freq % 10; freq /= 10;
212 	cmd[5] += freq % 10; freq /= 10;
213 	cmd[4] += freq % 10; freq /= 10;
214 	cmd[3] += freq % 10; freq /=10;
215 	cmd[2] += freq;
216 	sendCommand(cmd, 0);
217 LOG_INFO("%s", cmd.c_str());
218 	cmd[1] = 'R';
219 	sendCommand(cmd, 0);
220 LOG_INFO("%s", cmd.c_str());
221 }
222 
get_vfoB()223 unsigned long int RIG_RAY152::get_vfoB ()
224 {
225 	return B.freq;
226 }
227 
set_vfoB(unsigned long int freq)228 void RIG_RAY152::set_vfoB (unsigned long int freq)
229 {
230 	B.freq = freq;
231 	cmd = "FT000000\r";
232 	freq /= 100;
233 	cmd[7] += freq % 10; freq /= 10;
234 	cmd[6] += freq % 10; freq /= 10;
235 	cmd[5] += freq % 10; freq /= 10;
236 	cmd[4] += freq % 10; freq /= 10;
237 	cmd[3] += freq % 10; freq /=10;
238 	cmd[2] += freq;
239 	sendCommand(cmd, 0);
240 LOG_INFO("%s", cmd.c_str());
241 	cmd[1] = 'R';
242 	sendCommand(cmd, 0);
243 LOG_INFO("%s", cmd.c_str());
244 }
245 
set_PTT_control(int val)246 void RIG_RAY152::set_PTT_control(int val)
247 {
248 	cmd = val ? "X1\r" : "X0\r";
249 	sendCommand(cmd,0);
250 LOG_INFO("%s", cmd.c_str());
251 	ptt_ = val;
252 }
253 
set_modeA(int md)254 void RIG_RAY152::set_modeA(int md)
255 {
256 	A.imode = md;
257 	cmd = "M";
258 	cmd += (md  + '1');
259 	cmd += '\r';
260 	sendCommand(cmd, 0);
261 LOG_INFO("%s", cmd.c_str());
262 }
263 
get_modeA()264 int RIG_RAY152::get_modeA()
265 {
266 	return A.imode;
267 }
268 
set_modeB(int md)269 void RIG_RAY152::set_modeB(int md)
270 {
271 	B.imode = md;
272 	cmd = "M";
273 	cmd += (md  + '1');
274 	cmd += '\r';
275 	sendCommand(cmd, 0);
276 LOG_INFO("%s", cmd.c_str());
277 }
278 
get_modeB()279 int RIG_RAY152::get_modeB()
280 {
281 	return B.imode;
282 }
283 
get_modetype(int n)284 int RIG_RAY152::get_modetype(int n)
285 {
286 	return RIG_RAY152_mode_type[n];
287 }
288 
set_volume_control(int val)289 void RIG_RAY152::set_volume_control(int val)
290 {
291 	vol = val;
292 	string cmd = "V000\r";
293 	val *= 255;
294 	val /= 100;
295 	cmd[3] += val % 10; val /= 10;
296 	cmd[2] += val % 10; val /= 10;
297 	cmd[1] += val;
298 	sendCommand(cmd, 0);
299 LOG_INFO("%s", cmd.c_str());
300 }
301 
set_rf_gain(int val)302 void RIG_RAY152::set_rf_gain(int val)
303 {
304 	rfg = val;
305 	cmd = "R000\r";
306 	cmd[3] += val % 10; val /= 10;
307 	cmd[2] += val % 10; val /= 10;
308 	cmd[1] += val;
309 	sendCommand(cmd, 0);
310 LOG_INFO("%s", cmd.c_str());
311 }
312 
get_smeter(void)313 int RIG_RAY152::get_smeter(void)
314 {
315 	cmd = "U\r";
316 	int ret = sendCommand(cmd);
317 	string s = replystr;
318 	nocr(s);
319 LOG_WARN("%s", s.c_str());
320 	if (ret < 5) return 0;
321 	if (replystr[ret - 5] == 'U') {
322 		int val;
323 		sscanf(&replystr[ret - 5 + 1], "%d", &val);
324 		val = (int)(60.0 * (256.0 / (val + 16.0) - 1.0));
325 		if (val > 100) val = 100;
326 		if (val < 0) val = 0;
327 		return val;
328 	}
329 	return 0;
330 }
331 
get_power_out(void)332 int RIG_RAY152::get_power_out(void)
333 {
334 	int ret = sendCommand("U\r");
335 	if (ret < 5) return 0;
336 	if (replystr[ret - 5] == 'U') {
337 		int val;
338 		sscanf(&replystr[ret - 5 + 1], "%d", &val);
339 		val /= 128;
340 		val *= 100;
341 		return val;
342 	}
343 	return -1;
344 }
345 
346 
setRit(int v)347 void RIG_RAY152::setRit(int v)
348 {
349 	RitFreq = v;
350 	cmd = "D+00\r";
351 	if (v < 0) cmd[1] = '-';
352 	v /= 10;
353 	v = abs(v);
354 	cmd[3] += v % 10; v /= 10;
355 	cmd[2] += v % 10;
356 	sendCommand(cmd, 0);
357 LOG_INFO("%s", cmd.c_str());
358 }
359 
getRit()360 int  RIG_RAY152::getRit()
361 {
362 	return RitFreq;
363 }
364 
set_squelch(int val)365 void RIG_RAY152::set_squelch(int val)
366 {
367 	squelch = val;
368 	cmd = "Q000\r";
369 	cmd[3] += val % 10; val /= 10;
370 	cmd[2] += val % 10; val /= 10;
371 	cmd[1] += val;
372 	sendCommand(cmd, 0);
373 LOG_INFO("%s", cmd.c_str());
374 }
375 
get_squelch()376 int RIG_RAY152::get_squelch()
377 {
378 	return squelch;
379 }
380 
set_noise(bool on)381 void RIG_RAY152::set_noise(bool on)
382 {
383 	cmd = "Nx\r";
384 	cmd[1] = on ? nb_set : '0';
385 	sendCommand(cmd, 0);
386 LOG_INFO("%s", cmd.c_str());
387 }
388 
get_noise()389 int RIG_RAY152::get_noise()
390 {
391 	return nb;
392 }
393 
set_auto_notch(int v)394 void RIG_RAY152::set_auto_notch(int v)
395 {
396 	cmd = "Ax\r";
397 	cmd[1] = v ? '1' : '0';
398 	sendCommand(cmd, 0);
399 LOG_INFO("%s", cmd.c_str());
400 }
401 
get_auto_notch()402 int RIG_RAY152::get_auto_notch()
403 {
404 	return agc;
405 }
406 
407