[go: up one dir, main page]

Menu

[073328]: / kenwood / elecraft.c  Maximize  Restore  History

Download this file

320 lines (254 with data), 9.2 kB

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
/*
* Hamlib Elecraft backend--support Elecraft extensions to Kenwood commands
* Copyright (C) 2010,2011 by Nate Bargmann, n0nb@n0nb.us
* Copyright (C) 2011 by Alexander Sack, Alexander Sack, pisymbol@gmail.com
*
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* See the file 'COPYING.LIB' in the main Hamlib distribution directory for
* the complete text of the GNU Lesser Public License version 2.1.
*
*/
#include <string.h>
#include <stdlib.h>
#include "serial.h"
#include "elecraft.h"
#include "kenwood.h"
static const struct elec_ext_id_str elec_ext_id_str_lst[] = {
{ K20, "K20" },
{ K21, "K21" },
{ K22, "K22" },
{ K23, "K23" },
{ K30, "K30" },
{ K31, "K31" },
{ EXT_LEVEL_NONE, NULL }, /* end marker */
};
/* K3 firmware revision level, will be assigned to the fw_rev pointer in
* kenwood_priv_data structure at runtime in electraft_open(). The array is
* declared here so that the sizeof operator can be used in the call to
* elecraft_get_firmware_revision_level() to calculate the exact size of the
* array for the call to strncpy().
*/
static char k3_fw_rev[KENWOOD_MAX_BUF_LEN];
/* Private Elecraft extra levels definitions
*
* Token definitions for .cfgparams in rig_caps
* See enum rig_conf_e and struct confparams in rig.h
*/
const struct confparams elecraft_ext_levels[] = {
{ TOK_IF_FREQ, "ifctr", "IF center frequency", "IF center freq",
NULL, RIG_CONF_NUMERIC, { .n = { 0, 9990, 10 } }
},
{ TOK_TX_STAT, "txst", "TX status", "TX status",
NULL, RIG_CONF_CHECKBUTTON, { { } },
},
{ TOK_RIT_CLR, "ritclr", "RIT clear", "RIT clear",
NULL, RIG_CONF_BUTTON, { { } },
},
{ RIG_CONF_END, NULL, }
};
/* Private function declarations */
int verify_kenwood_id(RIG *rig, char *id);
int elecraft_get_extension_level(RIG *rig, const char *cmd, int *ext_level);
int elecraft_get_firmware_revision_level(RIG *rig, const char *cmd, char *fw_rev, size_t fw_rev_sz);
/* Shared backend function definitions */
/* elecraft_open()
*
* First checks for ID of '017' then tests for an Elecraft radio/backend using
* the K2; command. Here we also test for a K3 and if that fails, assume a K2.
* Finally, save the value for later reading.
*
*/
int elecraft_open(RIG *rig)
{
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
if (!rig)
return -RIG_EINVAL;
int err;
char id[KENWOOD_MAX_BUF_LEN];
/* Actual read extension levels from radio.
*
* The value stored in the k?_ext_lvl variables map to
* elec_ext_id_str_lst.level and is only written to by the
* elecraft_get_extension_level() private function during elecraft_open()
* and thereafter shall be treated as READ ONLY!
*/
struct kenwood_priv_data *priv = rig->state.priv;
/* As k3_fw_rev is declared static, it is persistent so the structure
* can point to it. This way was chosen to allow the compiler to
* calculate the size of the array to resolve a bug found by gcc 4.8.x
*/
priv->fw_rev = k3_fw_rev;
/* Use check for "ID017;" to verify rig is reachable */
rig_debug(RIG_DEBUG_TRACE, "%s: rig_model=%d,%d\n", __func__,rig->caps->rig_model,RIG_MODEL_XG3);
if (rig->caps->rig_model == RIG_MODEL_XG3) { // XG3 doesn't have ID
struct rig_state *rs = &rig->state;
char *cmd = "V;";
char data[32];
strcpy(data,"EMPTY");
// Not going to get carried away with retries and such
err = write_block(&rs->rigport, cmd, strlen(cmd));
if (err != RIG_OK) {
rig_debug(RIG_DEBUG_TRACE, "%s: XG3 cannot request identification\n", __func__);
return err;
}
err = read_string(&rs->rigport, id, sizeof(id), ";", 1);
if (err < 0) {
rig_debug(RIG_DEBUG_TRACE, "%s: XG3 cannot get identification\n", __func__);
return err;
}
rig_debug(RIG_DEBUG_VERBOSE, "%s: id=%s\n", __func__,id);
#if 0
if (err != RIG_OK) {
rig_debug(RIG_DEBUG_TRACE, "%s: cannot get identification\n", __func__);
return err;
}
#endif
}
else { // Standard Kenwood
err = verify_kenwood_id(rig, id);
if (err != RIG_OK)
return err;
}
switch(rig->caps->rig_model) {
case RIG_MODEL_K2:
err = elecraft_get_extension_level(rig, "K2", &priv->k2_ext_lvl);
if (err != RIG_OK)
return err;
rig_debug(RIG_DEBUG_VERBOSE, "%s: K2 level is %d, %s\n", __func__,
priv->k2_ext_lvl, elec_ext_id_str_lst[priv->k2_ext_lvl].id);
break;
case RIG_MODEL_K3:
err = elecraft_get_extension_level(rig, "K2", &priv->k2_ext_lvl);
if (err != RIG_OK)
return err;
rig_debug(RIG_DEBUG_VERBOSE, "%s: K2 level is %d, %s\n", __func__,
priv->k2_ext_lvl, elec_ext_id_str_lst[priv->k2_ext_lvl].id);
err = elecraft_get_extension_level(rig, "K3", &priv->k3_ext_lvl);
if (err != RIG_OK)
return err;
rig_debug(RIG_DEBUG_VERBOSE, "%s: K3 level is %d, %s\n", __func__,
priv->k3_ext_lvl, elec_ext_id_str_lst[priv->k3_ext_lvl].id);
err = elecraft_get_firmware_revision_level(rig, "RVM", priv->fw_rev,
(sizeof(k3_fw_rev) / sizeof(k3_fw_rev[0])));
if (err != RIG_OK)
return err;
break;
case RIG_MODEL_XG3:
rig_debug(RIG_DEBUG_VERBOSE, "%s: XG3 level is %d, %s\n", __func__,
priv->k3_ext_lvl, elec_ext_id_str_lst[priv->k3_ext_lvl].id);
break;
default:
rig_debug(RIG_DEBUG_WARN, "%s: unrecognized rig model %d\n",
__func__, rig->caps->rig_model);
return -RIG_EINVAL;
}
if (RIG_MODEL_XG3 != rig->caps->rig_model)
{
/* currently we cannot cope with AI mode so turn it off in case
last client left it on */
kenwood_set_trn(rig, RIG_TRN_OFF); /* ignore status in case it's
not supported */
}
return RIG_OK;
}
/* Private helper functions */
/* Tests for Kenwood ID string of "017" */
int verify_kenwood_id(RIG *rig, char *id)
{
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
if (!rig || !id)
return -RIG_EINVAL;
int err;
char *idptr;
/* Check for an Elecraft K2|K3 which returns "017" */
err = kenwood_get_id(rig, id);
if (err != RIG_OK) {
rig_debug(RIG_DEBUG_VERBOSE, "%s: cannot get identification\n", __func__);
return err;
}
/* ID is 'ID017;' */
if (strlen(id) < 5) {
rig_debug(RIG_DEBUG_VERBOSE, "%s: unknown ID type (%s)\n", __func__, id);
return -RIG_EPROTO;
}
/* check for any white space and skip it */
idptr = &id[2];
if (*idptr == ' ')
idptr++;
if (strcmp("017", idptr) != 0) {
rig_debug(RIG_DEBUG_VERBOSE, "%s: Rig (%s) is not a K2 or K3\n", __func__, id);
return -RIG_EPROTO;
} else
rig_debug(RIG_DEBUG_VERBOSE, "%s: Rig ID is %s\n", __func__, id);
return RIG_OK;
}
/* Determines K2 and K3 extension level */
int elecraft_get_extension_level(RIG *rig, const char *cmd, int *ext_level)
{
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
if (!rig || !ext_level)
return -RIG_EINVAL;
int err, i;
char buf[KENWOOD_MAX_BUF_LEN];
char *bufptr;
err = kenwood_safe_transaction(rig, cmd, buf, KENWOOD_MAX_BUF_LEN, 3);
if (err != RIG_OK) {
rig_debug(RIG_DEBUG_VERBOSE, "%s: Cannot get K2|K3 ID\n", __func__);
return err;
}
/* Get extension level string */
bufptr = &buf[0];
for (i = 0; elec_ext_id_str_lst[i].level != EXT_LEVEL_NONE; i++) {
if (strcmp(elec_ext_id_str_lst[i].id, bufptr) != 0)
continue;
if (strcmp(elec_ext_id_str_lst[i].id, bufptr) == 0) {
*ext_level = elec_ext_id_str_lst[i].level;
rig_debug(RIG_DEBUG_VERBOSE, "%s: %s extension level is %d, %s\n",
__func__, cmd, *ext_level, elec_ext_id_str_lst[i].id);
}
}
return RIG_OK;
}
/* Determine firmware revision level */
int elecraft_get_firmware_revision_level(RIG *rig, const char *cmd,
char *fw_rev, size_t fw_rev_sz)
{
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
if (!rig || !fw_rev)
return -RIG_EINVAL;
int err;
char *bufptr;
char buf[KENWOOD_MAX_BUF_LEN];
/* Get the actual firmware revision number. */
err = kenwood_transaction(rig, cmd, buf, sizeof (buf));
if (err != RIG_OK) {
rig_debug(RIG_DEBUG_VERBOSE, "%s: Cannot get firmware revision level\n", __func__);
return err;
}
/* Now buf[] contains the string from the K3 which includes the command
* and the firmware revision number as: "RVM04.67".
*/
bufptr = &buf[0];
/* Skip the command string */
bufptr += strlen(cmd);
/* Skip leading zero(s) as the revision number has the format of: "04.67" */
while (bufptr && *bufptr == '0') { bufptr++; }
/* Copy out */
strncpy(fw_rev, bufptr, fw_rev_sz - 1);
rig_debug(RIG_DEBUG_VERBOSE, "%s: Elecraft firmware revision is %s\n", __func__, fw_rev);
return RIG_OK;
}