1 // ----------------------------------------------------------------------------
2 // ICOMkeying.cxx   serial string CW interface to Elecraft transceivers
3 //
4 // Copyright (C) 2020
5 //		Dave Freese, W1HKJ
6 //
7 // This file is part of fldigi.
8 //
9 // Fldigi is free software: you can redistribute it and/or modify
10 // it under the terms of the GNU General Public License as published by
11 // the Free Software Foundation, either version 3 of the License, or
12 // (at your option) any later version.
13 //
14 // Fldigi is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 // GNU General Public License for more details.
18 //
19 // You should have received a copy of the GNU General Public License
20 // along with fldigi.  If not, see <http://www.gnu.org/licenses/>.
21 // ----------------------------------------------------------------------------
22 
23 #include <iostream>
24 #include <string>
25 
26 #include "ICOMkeying.h"
27 #include "configuration.h"
28 #include "rigio.h"
29 #include "threads.h"
30 #include "debug.h"
31 #include "rigsupport.h"
32 #include "morse.h"
33 #include "fl_digi.h"
34 #include "util.h"
35 
36 int ICOMwpm = 0;
37 bool use_ICOMkeyer = false;
38 static std::string ICOMcmd;
39 static cMorse ICOMmorse;
40 char lastICOMchar = 0;
41 
42 static std::string hexvals = "0123456789ABCDEF";
CIVaddr(std::string s)43 int CIVaddr(std::string s)
44 {
45 	int val = 0;
46 	if (s.length() != 2) return 0;
47 	if (hexvals.find(s[0]) == std::string::npos) return 0;
48 	if (hexvals.find(s[1]) == std::string::npos) return 0;
49 	val = hexvals.find(s[0]) * 16 + hexvals.find(s[1]);
50 	return val;
51 }
52 
ICOMheader()53 std::string ICOMheader()
54 {
55 	std::string s;
56 	s.assign("\xFE\xFE");
57 	s += ((char)CIVaddr(progdefaults.ICOMcivaddr));
58 	s.append("\xE0");
59 	return s;
60 }
61 
hexstr(std::string s)62 std::string hexstr(std::string s)
63 {
64 	std::string hex;
65 	for (size_t i = 0; i < s.length(); i++) {
66 		hex.append(" x");
67 		hex += hexvals[(s[i] & 0xFF) >> 4];
68 		hex += hexvals[s[i] & 0xF];
69 	}
70 	return hex;
71 }
72 
73 
set_ICOMkeyer()74 void set_ICOMkeyer() {
75 	ICOMwpm = progdefaults.CWspeed;
76 	if (ICOMwpm < 6) ICOMwpm = 6;
77 	if (ICOMwpm > 48) ICOMwpm = 48;
78 	progdefaults.CWspeed = ICOMwpm;
79 	int hexwpm = (ICOMwpm - 6) * 6 + 2;
80 	ICOMcmd.assign(ICOMheader());
81 	ICOMcmd.append("\x14\x0C");
82 	ICOMcmd += (char)(hexwpm / 100);
83 	ICOMcmd += (char)(((hexwpm % 100) / 10) * 16 + (hexwpm % 10));
84 	ICOMcmd += '\xFD';
85 	if (progdefaults.fldigi_client_to_flrig) {
86 		xmlrpc_priority(hexstr(ICOMcmd));
87 	} else {
88 		guard_lock ser_guard( &rigCAT_mutex);
89 		rigio.WriteBuffer((unsigned char *)ICOMcmd.c_str(), ICOMcmd.length());
90 	}
91 	MilliSleep(100);
92 }
93 
ICOMkeyer_send_char(int c)94 void ICOMkeyer_send_char(int c)
95 {
96 	if (ICOMwpm != progdefaults.CWspeed) {
97 		set_ICOMkeyer();
98 	}
99 
100 	if (c == GET_TX_CHAR_NODATA || c == 0x0d) {
101 		MilliSleep(50);
102 		return;
103 	}
104 
105 	int set_time = 0;
106 
107 	c = toupper(c);
108 	if (c < ' ') c = ' ';
109 	if (c > 'Z') c = ' ';
110 
111 	int tc = 1200 / progdefaults.CWspeed;
112 	if (progdefaults.CWusefarnsworth && (progdefaults.CWspeed > progdefaults.CWfarnsworth))
113 		tc = 1200 / progdefaults.CWfarnsworth;
114 
115 	if (c == ' ') {
116 		if (lastICOMchar == ' ')
117 			tc *= 7;
118 		else
119 			tc *= 5;
120 	} else {
121 		tc *= (ICOMmorse.tx_length(c));
122 
123 		ICOMcmd.assign(ICOMheader());
124 		ICOMcmd.append("\x17");
125 		ICOMcmd += (char)(c);
126 		ICOMcmd += '\xFD';
127 
128 		if (progdefaults.fldigi_client_to_flrig) {
129 			xmlrpc_priority(ICOMcmd);
130 		} else if (progdefaults.chkUSERIGCATis) {
131 			guard_lock ser_guard( &rigCAT_mutex);
132 			rigio.WriteBuffer((unsigned char *)ICOMcmd.c_str(), ICOMcmd.length());
133 		}
134 	}
135 
136 	tc -= progdefaults.CATkeying_compensation / (progdefaults.CWspeed  * 6);
137 	tc = int(tc);
138 	if (set_time < tc)
139 		MilliSleep((int)(tc - set_time));
140 
141 	lastICOMchar = c;
142 }
143