Hamlib/kenwood/ic10.c
Bill Somerville 4a74db654a Clarify the handling of Kenwood CAT message terminators
There was an inconsistency in  whether the CAT terminator character is
included  in  returned  messages.   It  now  follows  the  comment  in
kenwood_transaction()  i.e. strips  of  the terminator  and returns  a
message length that reflects that.
2015-02-13 18:07:10 +00:00

987 lines
22 KiB
C

/*
* Hamlib Kenwood backend - IC-10 interface for:
* TS-940, TS-811, TS-711, TS-440, and R-5000
*
* Copyright (c) 2000-2010 by Stephane Fillod and others
*
*
* 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
*
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdlib.h>
#include <stdio.h>
#include <string.h> /* String function definitions */
#include <unistd.h> /* UNIX standard function definitions */
#include <math.h>
#include <ctype.h> /* character class tests */
#include "hamlib/rig.h"
#include "serial.h"
#include "misc.h"
#include "register.h"
#include "kenwood.h"
#include "ic10.h"
/****
* ic10_cmd_trim
* gobbles up additional spaces at the end of a line
*
****/
int ic10_cmd_trim (char *data, int data_len) {
int i;
rig_debug(RIG_DEBUG_TRACE, "%s: incoming data_len is '%d'\n",
__func__, data_len);
/* suck up additional spaces at end of the data buffer */
for (i=data_len; !isdigit((int)data[i-1]); i--) {
data_len = data_len-1;
rig_debug(RIG_DEBUG_TRACE,"%s: data['%d'] is '%c'\n",
__func__, i-1, data[i-1]);
rig_debug(RIG_DEBUG_TRACE,"%s: For i='%d' data_len is now '%d'\n",
__func__, i, data_len);
}
rig_debug(RIG_DEBUG_TRACE, "%s: finished loop.. i='%d' data_len='%d' data[i-1]='%c'\n",
__func__, i, data_len, data[i-1]);
return data_len;
}
/**
* ic10_transaction
* Assumes rig!=NULL rig->state!=NULL rig->caps!=NULL
**/
int ic10_transaction (RIG *rig, const char *cmd, int cmd_len, char *data, int *data_len)
{
int retval;
struct rig_state *rs;
rs = &rig->state;
serial_flush(&rs->rigport);
retval = write_block(&rs->rigport, cmd, cmd_len);
if (retval != RIG_OK)
return retval;
if (!data || !data_len)
return 0;
retval = read_string(&rs->rigport, data, 50, ";", 1);
if (retval == -RIG_ETIMEOUT)
retval = 0;
if (retval < 0)
return retval;
*data_len = retval;
return RIG_OK;
}
/*
* Get the anwser of IF command, with retry handling
*/
static int get_ic10_if (RIG *rig, char *data)
{
struct kenwood_priv_caps *priv = (struct kenwood_priv_caps *)rig->caps->priv;
int i, data_len, retval=!RIG_OK;
for (i=0; retval!=RIG_OK && i < rig->caps->retry; i++) {
data_len = 37;
retval = ic10_transaction (rig, "IF;", 3, data, &data_len);
if (retval != RIG_OK)
continue;
if (retval == RIG_OK &&
(data_len < priv->if_len ||
data[0] != 'I' || data[1] != 'F')) {
rig_debug(RIG_DEBUG_WARN,"%s: unexpected answer %s, len=%d\n",
__func__, data, data_len);
retval = -RIG_ERJCTED;
}
}
return retval;
}
/*
* ic10_set_vfo
* Assumes rig!=NULL
*/
int ic10_set_vfo(RIG *rig, vfo_t vfo)
{
char ackbuf[16], cmdbuf[6];
int cmd_len, retval, ack_len;
char vfo_function;
switch (vfo) {
case RIG_VFO_VFO:
case RIG_VFO_A: vfo_function = '0'; break;
case RIG_VFO_B: vfo_function = '1'; break;
case RIG_VFO_MEM: vfo_function = '2'; break;
case RIG_VFO_CURR: return RIG_OK;
default:
rig_debug(RIG_DEBUG_ERR,"%s: unsupported VFO %d\n",
__func__, vfo);
return -RIG_EINVAL;
}
cmd_len = sprintf(cmdbuf, "FN%c;", vfo_function);
retval = ic10_transaction (rig, cmdbuf, cmd_len, ackbuf, &ack_len);
return retval;
}
/*
* ic10_get_vfo
* Assumes rig!=NULL, !vfo
*/
int ic10_get_vfo(RIG *rig, vfo_t *vfo)
{
struct kenwood_priv_caps *priv = (struct kenwood_priv_caps *)rig->caps->priv;
char vfobuf[50];
unsigned char c;
int retval, iflen;
/* query RX VFO */
retval = get_ic10_if(rig, vfobuf);
if (retval != RIG_OK)
return retval;
/* trim extra spaces */
iflen = ic10_cmd_trim(vfobuf, priv->if_len);
/* IFggmmmkkkhhh snnnzrx yytdfcp */
/* IFggmmmkkkhhhxxxxxrrrrrssxcctmfcp */
c = vfobuf[iflen - 3];
switch (c) {
case '0': *vfo = RIG_VFO_A; break;
case '1': *vfo = RIG_VFO_B; break;
case '2': *vfo = RIG_VFO_MEM; break;
default:
rig_debug(RIG_DEBUG_ERR,"%s: unsupported VFO %c\n",
__func__, c);
return -RIG_EPROTO;
}
return RIG_OK;
}
int ic10_set_split_vfo(RIG *rig, vfo_t vfo, split_t split, vfo_t txvfo)
{
char ackbuf[16];
int ack_len;
return ic10_transaction (rig, split==RIG_SPLIT_ON? "SP1;":"SP0;", 4,
ackbuf, &ack_len);
}
int ic10_get_split_vfo(RIG *rig, vfo_t vfo, split_t *split, vfo_t *txvfo)
{
struct kenwood_priv_caps *priv = (struct kenwood_priv_caps *)rig->caps->priv;
char infobuf[50];
int retval, iflen;
retval = get_ic10_if (rig, infobuf);
if (retval != RIG_OK)
return retval;
/* trim extra spaces */
iflen = ic10_cmd_trim(infobuf, priv->if_len);
/* IFggmmmkkkhhh snnnzrx yytdfcp */
/* IFggmmmkkkhhhxxxxxrrrrrssxcctmfcp */
*split = infobuf[iflen-1] == '0' ? RIG_SPLIT_OFF : RIG_SPLIT_ON;
return RIG_OK;
}
/*
* ic10_get_mode
* Assumes rig!=NULL, !vfo
*/
int ic10_get_mode(RIG *rig, vfo_t vfo, rmode_t *mode, pbwidth_t *width)
{
struct kenwood_priv_caps *priv = (struct kenwood_priv_caps *)rig->caps->priv;
char modebuf[50];
unsigned char c;
int retval, iflen;
/* query RX VFO */
retval = get_ic10_if (rig, modebuf);
if (retval != RIG_OK)
return retval;
/* trim extra spaces */
iflen = ic10_cmd_trim(modebuf, priv->if_len);
/* IFggmmmkkkhhh snnnzrx yytdfcp */
/* IFggmmmkkkhhhxxxxxrrrrrssxcctmfcp */
c = modebuf[iflen-4];
switch (c) {
case MD_CW : *mode = RIG_MODE_CW; break;
case MD_USB : *mode = RIG_MODE_USB; break;
case MD_LSB : *mode = RIG_MODE_LSB; break;
case MD_FM : *mode = RIG_MODE_FM; break;
case MD_AM : *mode = RIG_MODE_AM; break;
case MD_FSK : *mode = RIG_MODE_RTTY; break;
case MD_NONE: *mode = RIG_MODE_NONE; break;
default:
rig_debug(RIG_DEBUG_ERR,"%s: unsupported mode '%c'\n",
__func__, c);
return -RIG_EINVAL;
}
*width = rig_passband_normal(rig, *mode);
return RIG_OK;
}
/*
* ic10_set_mode
* Assumes rig!=NULL
*/
int ic10_set_mode(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width)
{
char modebuf[6], ackbuf[16];
int mode_len, ack_len, retval;
char mode_letter;
switch (mode) {
case RIG_MODE_LSB : mode_letter = MD_LSB; break;
case RIG_MODE_USB : mode_letter = MD_USB; break;
case RIG_MODE_CW : mode_letter = MD_CW; break;
case RIG_MODE_FM : mode_letter = MD_FM; break;
case RIG_MODE_AM : mode_letter = MD_AM; break;
case RIG_MODE_RTTY : mode_letter = MD_FSK; break;
default:
rig_debug(RIG_DEBUG_ERR,"%s: unsupported mode %d\n",
__func__,mode);
return -RIG_EINVAL;
}
mode_len = sprintf(modebuf,"MD%c;", mode_letter);
retval = ic10_transaction (rig, modebuf, mode_len, ackbuf, &ack_len);
return retval;
}
/*
* ic10_get_freq
* Assumes rig!=NULL, freq!=NULL
*/
int ic10_get_freq(RIG *rig, vfo_t vfo, freq_t *freq)
{
char infobuf[50];
int retval;
if (vfo != RIG_VFO_CURR) {
/* targeted freq retrieval */
return kenwood_get_freq(rig, vfo, freq);
}
retval = get_ic10_if (rig, infobuf);
if (retval != RIG_OK)
return retval;
/* IFggmmmkkkhhh snnnzrx yytdfcp */
/* IFggmmmkkkhhhxxxxxrrrrrssxcctmfcp */
infobuf[13] = '\0';
sscanf(infobuf+2, "%011"SCNfreq, freq);
return RIG_OK;
}
/*
* ic10_set_freq
* Assumes rig!=NULL
*/
int ic10_set_freq(RIG *rig, vfo_t vfo, freq_t freq)
{
char freqbuf[16], ackbuf[16];
int freq_len, ack_len, retval;
unsigned char vfo_letter;
vfo_t tvfo;
if(vfo==RIG_VFO_CURR)
tvfo=rig->state.current_vfo;
else
tvfo=vfo;
switch (tvfo) {
case RIG_VFO_A: vfo_letter = 'A'; break;
case RIG_VFO_B: vfo_letter = 'B'; break;
default:
rig_debug(RIG_DEBUG_ERR,"%s: unsupported VFO %d\n",
__func__,vfo);
return -RIG_EINVAL;
}
freq_len = sprintf(freqbuf,"F%c%011"PRIll";", vfo_letter, (int64_t)freq);
retval = ic10_transaction (rig, freqbuf, freq_len, ackbuf, &ack_len);
return retval;
}
/*
* ic10_set_ant
* Assumes rig!=NULL
*/
int ic10_set_ant(RIG *rig, vfo_t vfo, ant_t ant)
{
char buf[6], ackbuf[16];
int len, ack_len, retval;
len = sprintf(buf,"AN%c;", ant==RIG_ANT_1?'1':'2');
retval = ic10_transaction(rig, buf, len, ackbuf, &ack_len);
return retval;
}
/*
* ic10_get_ant
* Assumes rig!=NULL, ptt!=NULL
*/
int ic10_get_ant(RIG *rig, vfo_t vfo, ant_t *ant)
{
char infobuf[50];
int info_len, retval;
info_len = 4;
retval = ic10_transaction (rig, "AN;", 3, infobuf, &info_len);
if (retval != RIG_OK)
return retval;
if (info_len < 4 || infobuf[0] != 'A' || infobuf[1] != 'N') {
rig_debug(RIG_DEBUG_ERR,"%s: wrong answer len=%d\n",
__func__,info_len);
return -RIG_ERJCTED;
}
*ant = infobuf[2] == '1' ? RIG_ANT_1 : RIG_ANT_2;
return RIG_OK;
}
/*
* ic10_get_ptt
* Assumes rig!=NULL, ptt!=NULL
*/
int ic10_get_ptt(RIG *rig, vfo_t vfo, ptt_t *ptt)
{
struct kenwood_priv_caps *priv = (struct kenwood_priv_caps *)rig->caps->priv;
char infobuf[50];
int retval, iflen;
retval = get_ic10_if (rig, infobuf);
if (retval != RIG_OK)
return retval;
/* trim extra spaces */
iflen = ic10_cmd_trim(infobuf, priv->if_len);
/* IFggmmmkkkhhh snnnzrx yytdfcp */
/* IFggmmmkkkhhhxxxxxrrrrrssxcctmfcp */
*ptt = infobuf[iflen-5] == '0' ? RIG_PTT_OFF : RIG_PTT_ON;
return RIG_OK;
}
/*
* ic10_set_ptt
* Assumes rig!=NULL
*/
int ic10_set_ptt(RIG *rig, vfo_t vfo, ptt_t ptt)
{
char pttbuf[4], ackbuf[16];
int ptt_len, ack_len, retval;
unsigned char ptt_letter;
switch (ptt) {
case RIG_PTT_OFF: ptt_letter = 'R'; break;
case RIG_PTT_ON : ptt_letter = 'T'; break;
default:
rig_debug(RIG_DEBUG_ERR,"%s: unsupported PTT %d\n",
__func__,ptt);
return -RIG_EINVAL;
}
ptt_len = sprintf(pttbuf,"%cX;", ptt_letter);
retval = ic10_transaction (rig, pttbuf, ptt_len, ackbuf, &ack_len);
return retval;
}
/*
* ic10_get_mem
* Assumes rig!=NULL
*/
int ic10_get_mem(RIG *rig, vfo_t vfo, int *ch)
{
struct kenwood_priv_caps *priv = (struct kenwood_priv_caps *)rig->caps->priv;
char membuf[50];
int retval, iflen;
retval = get_ic10_if (rig, membuf);
if (retval != RIG_OK)
return retval;
/* trim extra spaces */
iflen = ic10_cmd_trim(membuf, priv->if_len);
/* IFggmmmkkkhhh snnnzrx yytdfcp */
/* IFggmmmkkkhhhxxxxxrrrrrssxcctmfcp */
membuf[iflen-5] = '\0';
*ch = atoi(membuf+priv->if_len-7);
return RIG_OK;
}
/*
* ic10_set_mem
* Assumes rig!=NULL
*/
int ic10_set_mem(RIG *rig, vfo_t vfo, int ch)
{
char membuf[8], ackbuf[16];
int mem_len, ack_len, retval;
mem_len = sprintf(membuf, "MC %02d;", ch);
retval = ic10_transaction (rig, membuf, mem_len, ackbuf, &ack_len);
return retval;
}
int ic10_get_channel(RIG *rig, channel_t *chan)
{
char membuf[16],infobuf[32];
int retval,info_len,len;
len = sprintf(membuf,"MR0 %02d;",chan->channel_num);
info_len = 24;
retval = ic10_transaction(rig, membuf, len, infobuf, &info_len);
if (retval != RIG_OK && info_len > 17)
return retval;
/* MRn rrggmmmkkkhhhdz ; */
switch (infobuf[17]) {
case MD_CW : chan->mode = RIG_MODE_CW; break;
case MD_USB : chan->mode = RIG_MODE_USB; break;
case MD_LSB : chan->mode = RIG_MODE_LSB; break;
case MD_FM : chan->mode = RIG_MODE_FM; break;
case MD_AM : chan->mode = RIG_MODE_AM; break;
case MD_FSK : chan->mode = RIG_MODE_RTTY; break;
case MD_NONE: chan->mode = RIG_MODE_NONE; break;
default:
rig_debug(RIG_DEBUG_ERR,"%s: unsupported mode '%c'\n",
__func__,infobuf[17]);
return -RIG_EINVAL;
}
chan->width = rig_passband_normal(rig, chan->mode);
/* infobuf[17] = ' '; */
infobuf[17] = '\0';
sscanf(infobuf+6, "%011"SCNfreq, &chan->freq);
chan->vfo=RIG_VFO_MEM;
/* TX VFO (Split channel only) */
len = sprintf(membuf,"MR1 %02d;",chan->channel_num);
info_len = 24;
retval = ic10_transaction(rig, membuf, len, infobuf, &info_len);
if (retval == RIG_OK && info_len > 17) {
/* MRn rrggmmmkkkhhhdz ; */
switch (infobuf[17]) {
case MD_CW : chan->tx_mode = RIG_MODE_CW; break;
case MD_USB : chan->tx_mode = RIG_MODE_USB; break;
case MD_LSB : chan->tx_mode = RIG_MODE_LSB; break;
case MD_FM : chan->tx_mode = RIG_MODE_FM; break;
case MD_AM : chan->tx_mode = RIG_MODE_AM; break;
case MD_FSK : chan->tx_mode = RIG_MODE_RTTY; break;
case MD_NONE: chan->tx_mode = RIG_MODE_NONE; break;
default:
rig_debug(RIG_DEBUG_ERR,"%s: unsupported mode '%c'\n",
__func__,infobuf[17]);
return -RIG_EINVAL;
}
chan->tx_width = rig_passband_normal(rig, chan->tx_mode);
/* infobuf[17] = ' '; */
infobuf[17] = '\0';
sscanf(infobuf+6, "%011"SCNfreq, &chan->tx_freq);
}
return RIG_OK;
}
int ic10_set_channel(RIG *rig, const channel_t *chan)
{
char membuf[32],ackbuf[32];
int retval,ack_len,len,md;
int64_t freq;
freq = (int64_t) chan->freq;
switch (chan->mode) {
case RIG_MODE_CW : md = MD_CW; break;
case RIG_MODE_USB : md = MD_USB; break;
case RIG_MODE_LSB : md = MD_LSB; break;
case RIG_MODE_FM : md = MD_FM; break;
case RIG_MODE_AM : md = MD_AM; break;
case RIG_MODE_RTTY: md = MD_FSK; break;
case RIG_MODE_NONE: md = MD_NONE; break;
default:
rig_debug(RIG_DEBUG_ERR,"%s: unsupported mode %d\n",
__func__,chan->mode);
return -RIG_EINVAL;
}
/* MWnxrrggmmmkkkhhhdzxxxx; */
len = sprintf(membuf,"MW0 %02d%011"PRIll"%c0 ;",
chan->channel_num,
freq,
md
);
retval = ic10_transaction(rig, membuf, len, ackbuf, &ack_len);
if (retval != RIG_OK)
return retval;
/* TX VFO (Split channel only) */
freq = chan->tx_freq;
switch (chan->tx_mode) {
case RIG_MODE_CW: md = MD_CW; break;
case RIG_MODE_USB: md = MD_USB; break;
case RIG_MODE_LSB: md = MD_LSB; break;
case RIG_MODE_FM: md = MD_FM; break;
case RIG_MODE_AM: md = MD_AM; break;
case RIG_MODE_RTTY: md = MD_FSK; break;
case RIG_MODE_NONE: md = MD_NONE; break;
default:
rig_debug(RIG_DEBUG_ERR,"%s: unsupported mode %d\n",
__func__,chan->tx_mode);
return -RIG_EINVAL;
}
/* MWnxrrggmmmkkkhhhdzxxxx; */
len = sprintf(membuf,"MW1 %02d%011"PRIll"%c0 ;",
chan->channel_num,
freq,
md
);
retval = ic10_transaction(rig, membuf, len, ackbuf, &ack_len);
return RIG_OK;
}
/*
* ic10_get_func
* Assumes rig!=NULL, val!=NULL
*/
int ic10_get_func(RIG *rig, vfo_t vfo, setting_t func, int *status)
{
char cmdbuf[6],fctbuf[50];
int cmdlen, fct_len, retval;
fct_len = 4;
switch (func) {
case RIG_FUNC_LOCK: cmdlen = sprintf(cmdbuf,"LK;"); break;
default:
rig_debug(RIG_DEBUG_ERR,"%s: Unsupported get_func %#x",
__func__,func);
return -RIG_EINVAL;
}
retval = ic10_transaction (rig, cmdbuf, cmdlen, fctbuf, &fct_len);
if (retval != RIG_OK)
return retval;
if (fct_len != 4) {
rig_debug(RIG_DEBUG_ERR,"%s: wrong answer len=%d\n",
__func__,fct_len);
return -RIG_ERJCTED;
}
*status = fctbuf[2] == '0' ? 0 : 1;
return RIG_OK;
}
/*
* ic10_set_func
* Assumes rig!=NULL, val!=NULL
*/
int ic10_set_func(RIG *rig, vfo_t vfo, setting_t func, int status)
{
char cmdbuf[4], fctbuf[16], ackbuf[16];
int cmdlen, fct_len, ack_len;
switch (func) {
case RIG_FUNC_LOCK:
cmdlen = sprintf(cmdbuf,"LK");
if (cmdlen < 0)
return -RIG_ETRUNC;
break;
default:
rig_debug(RIG_DEBUG_ERR,"%s: Unsupported set_func %#x",
__func__,func);
return -RIG_EINVAL;
}
fct_len = sprintf(fctbuf,"%s%c;", cmdbuf, status==0?'0':'1');
if (fct_len < 0)
return -RIG_ETRUNC;
return ic10_transaction (rig, fctbuf, fct_len, ackbuf, &ack_len);
return RIG_OK;
}
/*
* ic10_set_parm
* Assumes rig!=NULL
*/
int ic10_set_parm(RIG *rig, setting_t parm, value_t val)
{
char cmdbuf[50];
int cmd_len;
int hours;
int minutes;
int seconds;
switch (parm) {
case RIG_PARM_TIME:
minutes = val.i/60;
hours = minutes/60;
seconds = val.i-(minutes*60);
minutes = minutes%60;
cmd_len = sprintf(cmdbuf, "CK1%02d%02d%02d;", hours, minutes, seconds);
return ic10_transaction (rig, cmdbuf, cmd_len, NULL, NULL);
break;
default:
rig_debug(RIG_DEBUG_ERR,"%s: Unsupported set_parm %d\n",
__func__,parm);
return -RIG_EINVAL;
}
return RIG_OK;
}
/*
* ic10_get_parm
* Assumes rig!=NULL, val!=NULL
*/
int ic10_get_parm(RIG *rig, setting_t parm, value_t *val)
{
int retval, lvl_len, i;
char lvlbuf[50];
switch (parm) {
case RIG_PARM_TIME:
lvl_len = 10;
retval = ic10_transaction (rig, "CK1;", 4, lvlbuf, &lvl_len);
if (retval != RIG_OK)
return retval;
/* "CK1hhmmss;"*/
if (lvl_len != 10) {
rig_debug(RIG_DEBUG_ERR,"%s: wrong answer len=%d\n",
__func__,lvl_len);
return -RIG_ERJCTED;
}
/* convert ASCII to numeric 0..9 */
for (i=3; i<9; i++) {
lvlbuf[i] -= '0';
}
val->i = ((10*lvlbuf[3] + lvlbuf[4])*60 + /* hours */
10*lvlbuf[5] + lvlbuf[6])*60 + /* minutes */
10*lvlbuf[7] + lvlbuf[8]; /* seconds */
break;
default:
rig_debug(RIG_DEBUG_ERR,"%s: Unsupported get_parm %d\n",
__func__,parm);
return -RIG_EINVAL;
}
return RIG_OK;
}
/*
* ic10_set_powerstat
* Assumes rig!=NULL
*/
int ic10_set_powerstat(RIG *rig, powerstat_t status)
{
char pwrbuf[16], ackbuf[16];
int pwr_len, ack_len;
pwr_len = sprintf(pwrbuf,"PS%c;", status==RIG_POWER_ON?'1':'0');
return ic10_transaction (rig, pwrbuf, pwr_len, ackbuf, &ack_len);
}
/*
* ic10_get_powerstat
* Assumes rig!=NULL, trn!=NULL
*/
int ic10_get_powerstat(RIG *rig, powerstat_t *status)
{
char pwrbuf[50];
int pwr_len, retval;
pwr_len = 4;
retval = ic10_transaction (rig, "PS;", 3, pwrbuf, &pwr_len);
if (retval != RIG_OK)
return retval;
if (pwr_len != 4) {
rig_debug(RIG_DEBUG_ERR,"%s: wrong answer len=%d\n",
__func__,pwr_len);
return -RIG_ERJCTED;
}
*status = pwrbuf[2] == '0' ? RIG_POWER_OFF : RIG_POWER_ON;
return RIG_OK;
}
/*
* ic10_set_trn
* Assumes rig!=NULL
*/
int ic10_set_trn(RIG *rig, int trn)
{
char trnbuf[16], ackbuf[16];
int trn_len, ack_len;
trn_len = sprintf(trnbuf,"AI%c;", trn==RIG_TRN_RIG?'1':'0');
return ic10_transaction (rig, trnbuf, trn_len, ackbuf, &ack_len);
}
/*
* ic10_get_trn
* Assumes rig!=NULL, trn!=NULL
*/
int ic10_get_trn(RIG *rig, int *trn)
{
char trnbuf[50];
int trn_len, retval;
trn_len = 38;
retval = ic10_transaction (rig, "AI;", 3, trnbuf, &trn_len);
if (retval != RIG_OK)
return retval;
if (trn_len != 38) {
rig_debug(RIG_DEBUG_ERR,"%s: wrong answer len=%d\n",
__func__,trn_len);
return -RIG_ERJCTED;
}
*trn = trnbuf[2] != '0' ? RIG_TRN_RIG : RIG_TRN_OFF;
return RIG_OK;
}
/*
* ic10_vfo_op
* Assumes rig!=NULL
*/
int ic10_vfo_op(RIG *rig, vfo_t vfo, vfo_op_t op)
{
char *cmd, ackbuf[16];
int ack_len;
switch(op) {
case RIG_OP_UP : cmd = "UP;"; break;
case RIG_OP_DOWN : cmd = "DN;"; break;
default:
rig_debug(RIG_DEBUG_ERR,"%s: unsupported op %#x\n",
__func__,op);
return -RIG_EINVAL;
}
return ic10_transaction (rig, cmd, 3, ackbuf, &ack_len);
}
/*
* ic10_scan
* Assumes rig!=NULL, val!=NULL
*/
int ic10_scan(RIG * rig, vfo_t vfo, scan_t scan, int ch)
{
char ackbuf[16];
int ack_len;
return ic10_transaction (rig, scan==RIG_SCAN_STOP? "SC0;":"SC1;", 4,
ackbuf, &ack_len);
}
/*
* ic10_get_info
* Assumes rig!=NULL
*/
const char* ic10_get_info(RIG *rig)
{
char firmbuf[50];
int firm_len, retval;
firm_len = 6;
retval = ic10_transaction (rig, "ID;", 3, firmbuf, &firm_len);
if (retval != RIG_OK)
return NULL;
if (firm_len != 6) {
rig_debug(RIG_DEBUG_ERR,"%s: wrong answer len=%d\n",
__func__,firm_len);
return NULL;
}
switch (firmbuf[4]) {
case '4': return "ID: TS-440S";
case '5': return "ID: R-5000";
default: return "ID: unknown";
}
}
/*
* ic10_decode_event is called by sa_sigio, when some asynchronous
* data has been received from the rig.
*/
int ic10_decode_event (RIG *rig)
{
struct kenwood_priv_caps *priv = (struct kenwood_priv_caps *)rig->caps->priv;
char asyncbuf[128],c;
int retval,async_len=128, iflen;
vfo_t vfo;
freq_t freq;
rmode_t mode;
ptt_t ptt;
rig_debug(RIG_DEBUG_TRACE, "%s: called\n", __func__);
retval = ic10_transaction(rig, NULL, 0, asyncbuf, &async_len);
if (retval != RIG_OK)
return retval;
rig_debug(RIG_DEBUG_TRACE, "%s: Decoding message\n", __func__);
/* --------------------------------------------------------------------- */
if (async_len<priv->if_len || asyncbuf[0] != 'I' || asyncbuf[1] != 'F') {
rig_debug(RIG_DEBUG_ERR, "%s: Unsupported transceive cmd '%s'\n",
__func__, asyncbuf);
return -RIG_ENIMPL;
}
/* trim extra spaces */
iflen = ic10_cmd_trim(asyncbuf, priv->if_len);
/* IFggmmmkkkhhh snnnzrx yytdfcp */
/* IFggmmmkkkhhhxxxxxrrrrrssxcctmfcp */
c = asyncbuf[iflen-3];
switch (c) {
case '0': vfo = RIG_VFO_A; break;
case '1': vfo = RIG_VFO_B; break;
case '2': vfo = RIG_VFO_MEM; break;
default:
rig_debug(RIG_DEBUG_ERR,"%s: unsupported VFO %c\n",
__func__, c);
return -RIG_EPROTO;
}
c = asyncbuf[iflen-4];
switch (c) {
case MD_CW : mode = RIG_MODE_CW; break;
case MD_USB : mode = RIG_MODE_USB; break;
case MD_LSB : mode = RIG_MODE_LSB; break;
case MD_FM : mode = RIG_MODE_FM; break;
case MD_AM : mode = RIG_MODE_AM; break;
case MD_FSK : mode = RIG_MODE_RTTY; break;
case MD_NONE: mode = RIG_MODE_NONE; break;
default:
rig_debug(RIG_DEBUG_ERR,"%s: unsupported mode '%c'\n",
__func__,c);
return -RIG_EINVAL;
}
ptt = asyncbuf[iflen-5] == '0' ? RIG_PTT_OFF : RIG_PTT_ON;
asyncbuf[13] = '\0';
sscanf(asyncbuf+2, "%011"SCNfreq, &freq);
/* Callback execution */
if (rig->callbacks.vfo_event) {
rig->callbacks.vfo_event(rig, vfo, rig->callbacks.vfo_arg);
}
if (rig->callbacks.freq_event) {
rig->callbacks.freq_event(rig, vfo, freq, rig->callbacks.freq_arg);
}
if (rig->callbacks.mode_event) {
rig->callbacks.mode_event(rig, vfo, mode, RIG_PASSBAND_NORMAL,
rig->callbacks.mode_arg);
}
if (rig->callbacks.ptt_event) {
rig->callbacks.ptt_event(rig, vfo, ptt, rig->callbacks.ptt_arg);
}
return RIG_OK;
}