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 <iostream>
22
23 #include "ICbase.h"
24 #include "debug.h"
25 #include "support.h"
26 #include "icons.h"
27 #include "tod_clock.h"
28 #include "trace.h"
29 #include "status.h"
30 #include "threads.h"
31
32 pthread_mutex_t command_mutex = PTHREAD_MUTEX_INITIALIZER;
33
34 //=============================================================================
35
adjustCIV(uchar adr)36 void RIG_ICOM::adjustCIV(uchar adr)
37 {
38 CIV = adr;
39 pre_to[2] = ok[3] = bad[3] = pre_fm[3] = CIV;
40 }
41
checkresponse()42 void RIG_ICOM::checkresponse()
43 {
44 if (!progStatus.use_tcpip && !RigSerial->IsOpen())
45 return;
46
47 if (replystr.rfind(ok) != string::npos)
48 return;
49
50 string s1 = str2hex(cmd.c_str(), cmd.length());
51 string s2 = str2hex(replystr.c_str(), replystr.length());
52 LOG_ERROR("\nsent %s\nreply %s", s1.c_str(), s2.c_str());
53 }
54
sendICcommand(string cmd,int nbr)55 bool RIG_ICOM::sendICcommand(string cmd, int nbr)
56 {
57 guard_lock reply_lock(&mutex_replystr);
58
59 int ret = sendCommand(cmd);
60
61 if (!progStatus.use_tcpip && !RigSerial->IsOpen())
62 return false;
63
64 if (ret < nbr) {
65 LOG_ERROR("Expected %d received %d", nbr, ret);
66 return false;
67 }
68
69 if (ret > nbr) respstr.erase(0, ret - nbr);
70
71 // look for preamble at beginning
72 if (respstr.rfind(pre_fm) == string::npos) {
73 LOG_ERROR("preamble: %s not in %s", pre_fm.c_str(), cmd.c_str());
74 replystr.clear();
75 return false;
76 }
77
78 // look for postamble
79 if (respstr.rfind(post) == string::npos) {
80 LOG_ERROR("postample: %s not at end of %s", post.c_str(), cmd.c_str());
81 replystr.clear();
82 return false;
83 }
84 replystr = respstr;
85 return true;
86 }
87
delayCommand(string cmd,int wait)88 void RIG_ICOM::delayCommand(string cmd, int wait)
89 {
90 int oldwait = progStatus.comm_wait;
91 progStatus.comm_wait += wait;
92 sendCommand(cmd);
93 progStatus.comm_wait = oldwait;
94 }
95
96 #include <fstream>
97
ICtrace(string cmd,string hexstr)98 void RIG_ICOM::ICtrace(string cmd, string hexstr)
99 {
100 string s1 = str2hex(hexstr.c_str(), hexstr.length());
101 rig_trace(2, cmd.c_str(), s1.c_str());
102 }
103
waitFB(const char * sz,int timeout)104 bool RIG_ICOM::waitFB(const char *sz, int timeout)
105 {
106 guard_lock cmd_lock(&command_mutex);
107
108 guard_lock reply_lock(&mutex_replystr);
109 //std::cout << ztime() << " waitFB( " << sz << ", " << timeout << " ): " << str2hex(cmd.c_str(), cmd.length()) << std::endl;
110
111 char sztemp[100];
112 string returned = "";
113 string tosend = cmd;
114 unsigned long int msec_start = 0;
115 int diff;
116
117 if (!progStatus.use_tcpip && !RigSerial->IsOpen()) {
118 replystr = cmd;//returned;
119 return false;
120 }
121 int num = cmd.length() + ok.length();
122
123 int wait_msec = progStatus.use_tcpip ? progStatus.tcpip_ping_delay : 0;
124 wait_msec += 100;
125 wait_msec += num * 11000.0 / RigSerial->Baud();
126
127 timeout += wait_msec;
128
129 unsigned long int loop_start;
130
131 msec_start = zmsec();
132
133 respstr.clear();
134 sendCommand(cmd, 0);
135 returned.clear();
136 loop_start = zmsec();
137 diff = zmsec() - loop_start;
138
139 while ( diff < timeout) { //wait_msec + 10 ) {
140 returned.append(respstr);
141 if (returned.find(ok) != string::npos) {
142 replystr = returned;
143 unsigned long int waited = zmsec() - msec_start;
144 snprintf(sztemp, sizeof(sztemp), "%s ans in %ld ms, OK", sz, waited);
145 showresp(DEBUG, HEX, sztemp, tosend, returned);
146 //std::cout << ztime() << " Response: " << str2hex(returned.c_str(), returned.length()) << std::endl;
147 return true;
148 }
149 if (returned.find(bad) != string::npos) {
150 replystr = returned;
151 unsigned long int waited = zmsec() - msec_start;
152 snprintf(sztemp, sizeof(sztemp), "%s ans in %ld ms, FAILED", sz, waited);
153 showresp(ERR, HEX, sztemp, tosend, returned);
154 //std::cout << ztime() << " ERROR: " << str2hex(returned.c_str(), returned.length()) << std::endl;
155 return false;
156 }
157 readResponse();
158 diff = zmsec() - loop_start;
159 }
160
161 diff = zmsec() - msec_start;
162 replystr = returned;
163 snprintf(sztemp, sizeof(sztemp), "%s TIMED OUT : %d ms", sz, diff);
164 showresp(ERR, HEX, sztemp, tosend, returned);
165 //std::cout << ztime() << " TIMED OUT: " << str2hex(returned.c_str(), returned.length()) << std::endl;
166
167 return false;
168 }
169
waitFOR(size_t n,const char * sz,int timeout)170 bool RIG_ICOM::waitFOR(size_t n, const char *sz, int timeout)
171 {
172 guard_lock cmd_lock(&command_mutex);
173
174 guard_lock reply_lock(&mutex_replystr);
175
176 //std::cout << ztime() << " waitFOR( " << n << ", " << sz << ", " << timeout << " ): " << str2hex(cmd.c_str(), cmd.length()) << std::endl;
177
178 char sztemp[100];
179 string returned = "";
180 string tosend = cmd;
181 size_t num = n;
182 int diff = 0;
183 if (progStatus.comm_echo) num += cmd.length();
184
185 unsigned long int msec_start;
186 unsigned long int repeat_start;
187
188 int delay = progStatus.use_tcpip ? progStatus.tcpip_ping_delay : 0;
189 delay += 100;
190 delay += num * 11000.0 / RigSerial->Baud();
191
192 if (!progStatus.use_tcpip && !RigSerial->IsOpen()) {
193 replystr = cmd;
194 return false;
195 }
196 if (timeout == 0) timeout = progStatus.comm_retries * delay;
197 msec_start = zmsec();
198
199 repeat_start = zmsec();
200 respstr.clear();
201
202 sendCommand(tosend, 0);
203 returned = respstr;
204
205 while (int(zmsec() - repeat_start) < timeout) {
206 if (returned.find(bad) != string::npos) {
207 snprintf(sztemp, sizeof(sztemp), "%s : %d ms", sz, int(zmsec() - msec_start));
208 showresp(ERR, HEX, sztemp, tosend, returned);
209 //std::cout << ztime() << " ERROR: " << str2hex(returned.c_str(), returned.length()) << std::endl;
210 return false;
211 }
212 if (returned.length() >= num) {
213 replystr = returned;
214 snprintf(sztemp, sizeof(sztemp), "%s : %d ms", sz, int(zmsec() - msec_start));
215 showresp(DEBUG, HEX, sztemp, tosend, returned);
216 //std::cout << ztime() << " Response: " << str2hex(returned.c_str(), returned.length()) << std::endl;
217 return true;
218 }
219 if (readResponse())
220 returned.append(respstr);
221 }
222
223 diff = zmsec() - msec_start;
224 replystr = returned;
225 snprintf(sztemp, sizeof(sztemp), "%s TIMED OUT : %d ms", sz, diff);
226 showresp(ERR, HEX, sztemp, tosend, returned);
227 //std::cout << ztime() << " " << sztemp << " " << str2hex(returned.c_str(), returned.length()) << std::endl;
228
229 return false;
230 }
231
232 // exchange & equalize are available in these Icom xcvrs
233 // 718 706MKIIG 746 746PRO 756 756PRO 756PROII 756PROIII
234 // 910 7000 7100 7200 7300 7410 7600 7700 7800 9100
235
236 // 5/04/18 dhf
237
swapAB()238 void RIG_ICOM::swapAB()
239 {
240 cmd = pre_to;
241 cmd += 0x07; cmd += 0xB0;
242 ICtrace("A<>B", cmd);
243 cmd.append(post);
244 int fil = filB;
245 filB = filA;
246 filA = fil;
247 waitFB("A<>B");
248 ICtrace("A<>B", replystr);
249 }
250
A2B()251 void RIG_ICOM::A2B()
252 {
253 cmd = pre_to;
254 cmd += 0x07; cmd += 0xA0;
255 ICtrace("A2B", cmd);
256 cmd.append(post);
257 if (useB) filA = filB;
258 else filB = filA;
259 waitFB("Equalize vfos");
260 ICtrace("A2B", replystr);
261 }
262
tune_rig(int how)263 void RIG_ICOM::tune_rig(int how)
264 {
265 cmd = pre_to;
266 cmd.append("\x1c\x01");
267 switch (how) {
268 default:
269 case 0:
270 cmd += '\x00';
271 break;
272 case 1:
273 cmd += '\x01';
274 break;
275 case 2:
276 cmd += '\x02';
277 break;
278 }
279 cmd.append( post );
280 waitFB("tune rig");
281 ICtrace("tune rig", replystr);
282 }
283
get_tune()284 int RIG_ICOM::get_tune()
285 {
286 string resp;
287 string cstr = "\x1C\x01";
288 cmd.assign(pre_to).append(cstr).append(post);
289 resp.assign(pre_fm).append(cstr);
290 int val = tune_;
291 if (waitFOR(8, "get TUNE")) {
292 size_t p = replystr.rfind(resp);
293 if (p != string::npos)
294 val = replystr[p + 6];
295 }
296 return (tune_ = val);
297 }
298
hexstr(std::string s)299 std::string RIG_ICOM::hexstr(std::string s)
300 {
301 return str2hex(s.c_str(), s.length());
302 }
303
304