6
* Copyright 2009, Dave Freese, W1HKJ
8
* Additions by Kent Haase, VE4KEH
9
* Ref Elecraft KIO2 Programmer's Reference (Rev E, 3 Feb, 2004)
10
* K2 MCU firmware rev 2.04
18
const char K2name_[] = "K2";
20
const char *K2modes_[] = {
21
"LSB", "USB", "CW", "FM", "AM", "RTTY-L", "CW-R", "USER-L", "RTTY-U", NULL};
23
static const char K2_mode_type[] =
24
{'L', 'U', 'U', 'U', 'U', 'L', 'L', 'L', 'U', 'U'};
26
const char *K2_widths[] = {"FL1", "FL2", "FL3", "FL4", NULL};
28
static GUI k2_widgets[]= {
29
{ (Fl_Widget *)sldrPOWER, 266, 105, 156 },
30
{ (Fl_Widget *)NULL, 0, 0, 0 }
37
bandwidths_ = K2_widths;
41
comm_baudrate = BR4800;
54
freqB = freqA = 14070000;
58
has_attenuator_control =
62
has_bandwidth_control =
67
has_tune_control = true;
74
has_swr_control = false;
83
int RIG_K2::adjust_bandwidth(int m)
88
void RIG_K2::initialize()
90
k2_widgets[0].W = sldrPOWER;
92
//enable extended command mode
93
sendCommand("K22;", 0);
94
//disable auto reporting of info
95
sendCommand("AI0;", 0);
96
//ensure K2 is in VFO A
101
* IF (Transceiver Information; GET only)
103
* RSP format: IF[f]*****+yyyyrx*00tmvspb01*; where the fields are defined as follows:
106
* 0123456789012345678901234567890123456789
107
* IFfffffffffff*****+yyyyrx*00tmvspb01*;
109
* 2..12 [f] operating frequency, excluding any RIT/XIT offset (11 digits; see FA command)
110
* 13..17 * represents a space (BLANK, or ASCII 0x20)
111
* 18 + either "+" or "-" (sign of RIT/XIT offset)
112
* 19..22 yyyy RIT/XIT offset in Hz (range is -9990 to +9990 Hz when computer-controlled)
113
* 23 r 1 if RIT is on, 0 if off
114
* 24 x 1 if XIT is on, 0 if off
116
* 28 t 1 if the K2 is in transmit mode, 0 if receive
117
* 29 m operating mode (see MD command)
118
* 30 v receive-mode VFO selection, 0 for VFO A, 1 for VFO B
119
* 31 s 1 if scan is in progress, 0 otherwise
120
* 32 p 1 if the transeiver is in split mode, 0 otherwise
121
* 33 b basic RSP format: always 0
122
* extended RSP format:
123
* 1 if the present IF response is due to a K2 band change and
127
* The fixed-value fields (space, 0, and 1) are provided for syntactic compatibility with existing software.
129
// set replystr to teststr to test for various control bytes
130
//const char *teststr = "IFfffffffffff*****+yyyyrx*000m0s1b01*;";
132
static void do_selectA(void *)
137
static void do_selectB(void *)
142
bool RIG_K2::get_info()
146
int ret = waitN(38, 100, "get info", ASC);
147
if (ret < 38) return false;
148
size_t p = replystr.find(rsp);
149
if (PTT && (replystr[p+28]=='0')) Fl::awake(setPTT, (void*)0);
150
if (!PTT && (replystr[p+28]=='1')) Fl::awake(setPTT, (void*)1);
151
if (useB && (replystr[p+30]=='0')) Fl::awake(do_selectA, (void*)0);
152
else if(!useB && (replystr[p+30]=='1')) Fl::awake(do_selectB, (void*)0);
153
K2split = replystr[p+32]-'0';
157
void RIG_K2::selectA()
162
showresp(WARN, ASC, "select A", cmd, replystr);
165
void RIG_K2::selectB()
170
showresp(WARN, ASC, "select B", cmd, replystr);
173
bool RIG_K2::can_split()
178
void RIG_K2::set_split(bool val)
186
showresp(WARN, ASC, "set split ON", cmd, replystr);
193
showresp(WARN, ASC, "set split OFF", cmd, replystr);
197
int RIG_K2::get_split()
202
long RIG_K2::get_vfoA ()
206
int ret = waitN(14, 100, "get vfo A", ASC);
207
if (ret < 14) return freqA;
208
size_t p = replystr.rfind(rsp);
209
if (p == string::npos) return freqA;
211
for (size_t n = 2; n < 13; n++)
212
f = f*10 + replystr[p + n] - '0';
217
void RIG_K2::set_vfoA (long freq)
220
cmd = "FA00000000000;";
221
for (int i = 12; i > 1; i--) {
226
showresp(WARN, ASC, "SET vfo A", cmd, replystr);
229
long RIG_K2::get_vfoB()
233
int ret = waitN(14, 100, "get vfo B", ASC);
234
if (ret < 14) return freqB;
235
size_t p = replystr.rfind(rsp);
236
if (p == string::npos) return freqB;
238
for (size_t n = 2; n < 13; n++)
239
f = f*10 + replystr[p + n] - '0';
244
void RIG_K2::set_vfoB(long freq)
247
cmd = "FB00000000000;";
248
for (int i = 12; i > 1; i--) {
253
showresp(WARN, ASC, "SET vfo B", cmd, replystr);
256
void RIG_K2::set_modeA(int val)
263
showresp(WARN, ASC, "SET mode A", cmd, replystr);
266
int RIG_K2::get_modeA()
270
int ret = waitN(4, 100, "get mode A", ASC);
271
if (ret < 4) return 0;
272
size_t p = replystr.rfind(rsp);
273
if (p == string::npos) return 0;
274
modeA = replystr[p + 2] - '1';
278
void RIG_K2::set_modeB(int val)
285
showresp(WARN, ASC, "SET mode B", cmd, replystr);
288
int RIG_K2::get_modeB()
292
int ret = waitN(4, 100, "get mode B", ASC);
293
if (ret < 4) return 0;
294
size_t p = replystr.rfind(rsp);
295
if (p == string::npos) return 0;
296
modeB = replystr[p + 2] - '1';
300
int RIG_K2::get_modetype(int n)
302
return K2_mode_type[n];
305
void RIG_K2::set_bwA(int val)
309
case 0 : cmd = "FW00001;"; break;
310
case 1 : cmd = "FW00002;"; break;
311
case 2 : cmd = "FW00003;"; break;
312
case 3 : cmd = "FW00004;"; break;
313
default: cmd = "FW00001;";
316
showresp(WARN, ASC, "set bwA", cmd, replystr);
319
int RIG_K2::get_bwA()
323
int ret = waitN(9, 100, "get bw A", ASC);
324
if (ret < 9) return 0;
325
size_t p = replystr.rfind(rsp);
326
if (p == string::npos) return 0;
327
bwA = replystr[p + 6] - '1';
331
void RIG_K2::set_bwB(int val)
335
case 0 : cmd = "FW00001;"; break;
336
case 1 : cmd = "FW00002;"; break;
337
case 2 : cmd = "FW00003;"; break;
338
case 3 : cmd = "FW00004;"; break;
339
default: cmd = "FW00001;";
342
showresp(WARN, ASC, "set bwA", cmd, replystr);
345
int RIG_K2::get_bwB()
349
int ret = waitN(9, 100, "get bw B", ASC);
350
if (ret < 9) return 0;
351
size_t p = replystr.rfind(rsp);
352
if (p == string::npos) return 0;
353
bwB = replystr[p + 6] - '1';
357
void RIG_K2::tune_rig()
361
showresp(WARN, ASC, "tune", cmd, replystr);
364
int RIG_K2::get_smeter()
368
int ret = waitN(5, 100, "get smeter", ASC);
369
if (ret < 5) return 0;
370
size_t p = replystr.rfind(rsp);
371
if (p == string::npos) return 0;
372
int mtr = 10 * (replystr[p + 2] - '0')
373
+ replystr[p + 3] - '0'; //assemble two chars into 2 digit int
374
if (mtr > 10) { //if int greater than 10 (bar mode)
375
mtr -= 12; //shift down to 0 thru 10
377
mtr *= 10; //normalize to 0 thru 100
381
int RIG_K2::get_power_out()
385
int ret = waitN(5, 100, "get power", ASC);
386
if (ret < 5) return 0;
387
size_t p = replystr.rfind(rsp);
388
if (p == string::npos) return 0;
389
int mtr = 10 * (replystr[p + 2] - '0')
390
+ replystr[p + 3] - '0'; //assemble two chars into 2 digit int
391
if (mtr > 10) { //if int greater than 10 (bar mode)
392
mtr -= 12; //shift down to 0 thru 10
394
mtr *= 10; //normalize to 0 thru 100
398
int RIG_K2::get_power_control()
400
rsp = cmd = "PC;"; // extended mode for get power
402
int ret = waitN(7, 100, "get pwr cont", ASC);
403
if (ret < 7) return progStatus.power_level;
404
size_t p = replystr.rfind(rsp);
405
if (p == string::npos) return 0;
406
hipower = (replystr[p+5] == '1');
407
int mtr = fm_decimal(&replystr[p+4], 3);
408
if (!hipower) mtr /= 10;
412
void RIG_K2::set_power_control(double val)
415
cmd = "PC"; //init the cmd string
419
cmd.append(to_decimal(ival,3)).append("1;");
422
cmd.append(to_decimal((int)(val*10),3)).append("0;");
425
showresp(WARN, ASC, "SET pwr", cmd, replystr);
428
void RIG_K2::get_pc_min_max_step(double &min, double &max, double &step)
431
min = 1.0; max_power = max = 110.0; step = 1.0;
433
min = 0.1; max_power = max = 20; step = 0.1;
437
void RIG_K2::set_PTT_control(int val)
439
if (val) cmd = "TX;";
442
showresp(WARN, ASC, "SET ptt", cmd, replystr);
445
void RIG_K2::set_attenuator(int val)
447
if (val) cmd = "RA01;";
450
showresp(WARN, ASC, "SET att", cmd, replystr);
453
int RIG_K2::get_attenuator()
457
int ret = waitN(5, 100, "get att", ASC);
458
if (ret < 5) return 0;
459
size_t p = replystr.rfind(rsp);
460
if (p == string::npos) return 0;
461
return (replystr[p + 3] == '1' ? 1 : 0);
464
void RIG_K2::set_preamp(int val)
466
if (val) cmd = "PA1;";
469
showresp(WARN, ASC, "SET pre", cmd, replystr);
472
int RIG_K2::get_preamp()
476
int ret = waitN(4, 100, "get pre", ASC);
477
if (ret < 4) return 0;
478
size_t p = replystr.rfind(rsp);
479
if (p == string::npos) return 0;
480
return (replystr[p + 2] == '1' ? 1 : 0);