From b06b185af030936be0d1f1c4ae6e398566232018 Mon Sep 17 00:00:00 2001 From: Michael Black Date: Wed, 19 Jul 2017 17:57:18 -0500 Subject: [PATCH 1/2] IC-M710 now working with WSJST-X --- icmarine/icm710.c | 744 +++++++++++++++++++++++++++++++++++++------- icmarine/icm710.h | 85 +++++ icmarine/icmarine.c | 18 ++ icmarine/icmarine.h | 2 + 4 files changed, 735 insertions(+), 114 deletions(-) create mode 100644 icmarine/icm710.h diff --git a/icmarine/icm710.c b/icmarine/icm710.c index 41a3dd959..0b3472b36 100644 --- a/icmarine/icm710.c +++ b/icmarine/icm710.c @@ -1,7 +1,7 @@ /* * Hamlib ICOM Marine backend - description of IC-M710 caps * Copyright (c) 2015 by Stephane Fillod - * + * Copyright (c) 2017 by Michael Black W9MDB * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -23,13 +23,25 @@ #include "config.h" #endif +#include #include +#include +#include +#include + +#include +#include +#include +#include +#include +#include -#include "hamlib/rig.h" -#include "icmarine.h" #include "idx_builtin.h" #include "bandplan.h" +#include "icm710.h" +#include "icmarine.h" + #define ICM710_MODES (RIG_MODE_SSB|RIG_MODE_CW|RIG_MODE_RTTY) #define ICM710_RX_MODES (ICM710_MODES|RIG_MODE_AM) @@ -49,131 +61,635 @@ #define ICM710_STR_CAL { 2, {{ 0, -60}, { 8, 60}} } -static const struct icmarine_priv_caps icm710_priv_caps = { - .default_remote_id = 0x01, /* default address */ +static const struct icm710_priv_caps icm710_priv_caps = { + .default_remote_id = 0x01, /* default address */ }; const struct rig_caps icm710_caps = { -.rig_model = RIG_MODEL_IC_M710, -.model_name = "IC-M710", -.mfg_name = "Icom", -.version = BACKEND_VER, -.copyright = "LGPL", -.status = RIG_STATUS_UNTESTED, -.rig_type = RIG_TYPE_TRANSCEIVER, -.ptt_type = RIG_PTT_RIG, -.dcd_type = RIG_DCD_RIG, -.port_type = RIG_PORT_SERIAL, -.serial_rate_min = 4800, -.serial_rate_max = 4800, -.serial_data_bits = 8, -.serial_stop_bits = 1, -.serial_parity = RIG_PARITY_NONE, -.serial_handshake = RIG_HANDSHAKE_NONE, -.write_delay = 0, -.post_write_delay = 0, -.timeout = 500, -.retry = 0, -.has_get_func = ICM710_FUNC_ALL, -.has_set_func = ICM710_FUNC_ALL, -.has_get_level = ICM710_LEVEL_ALL, -.has_set_level = RIG_LEVEL_SET(ICM710_LEVEL_ALL), -.has_get_parm = RIG_PARM_NONE, -.has_set_parm = RIG_PARM_NONE, -.level_gran = { - [LVL_RAWSTR] = { .min = { .i = 0 }, .max = { .i = 8 } }, - }, -.parm_gran = {}, -.str_cal = ICM710_STR_CAL, -.ctcss_list = NULL, -.dcs_list = NULL, -.preamp = { RIG_DBLST_END, }, -.attenuator = { RIG_DBLST_END, }, -.max_rit = Hz(0), -.max_xit = Hz(0), -.max_ifshift = Hz(0), -.targetable_vfo = 0, -.vfo_ops = ICM710_VFO_OPS, -.scan_ops = ICM710_SCAN_OPS, -.transceive = RIG_TRN_OFF, -.bank_qty = 0, -.chan_desc_sz = 0, + .rig_model = RIG_MODEL_IC_M710, + .model_name = "IC-M710", + .mfg_name = "Icom", + .version = BACKEND_VER".1", + .copyright = "LGPL", + .status = RIG_STATUS_STABLE, + .rig_type = RIG_TYPE_TRANSCEIVER, + .ptt_type = RIG_PTT_RIG, + .dcd_type = RIG_DCD_RIG, + .port_type = RIG_PORT_SERIAL, + .serial_rate_min = 4800, + .serial_rate_max = 4800, + .serial_data_bits = 8, + .serial_stop_bits = 1, + .serial_parity = RIG_PARITY_NONE, + .serial_handshake = RIG_HANDSHAKE_NONE, + .write_delay = 0, + .post_write_delay = 0, + .timeout = 500, + .retry = 0, + .has_get_func = ICM710_FUNC_ALL, + .has_set_func = ICM710_FUNC_ALL, + .has_get_level = ICM710_LEVEL_ALL, + .has_set_level = RIG_LEVEL_SET(ICM710_LEVEL_ALL), + .has_get_parm = RIG_PARM_NONE, + .has_set_parm = RIG_PARM_NONE, + .level_gran = { + [LVL_RAWSTR] = { .min = { .i = 0 }, .max = { .i = 8 } }, + }, + .parm_gran = {}, + .str_cal = ICM710_STR_CAL, + .ctcss_list = NULL, + .dcs_list = NULL, + .preamp = { RIG_DBLST_END, }, + .attenuator = { RIG_DBLST_END, }, + .max_rit = Hz(0), + .max_xit = Hz(0), + .max_ifshift = Hz(0), + .targetable_vfo = 0, + .vfo_ops = ICM710_VFO_OPS, +//.scan_ops = ICM710_SCAN_OPS, + .transceive = RIG_TRN_OFF, + .bank_qty = 0, + .chan_desc_sz = 0, -.chan_list = { - RIG_CHAN_END, - }, + .chan_list = { + RIG_CHAN_END, + }, -.rx_range_list1 = { {kHz(500),MHz(30)-100,ICM710_RX_MODES,-1,-1,ICM710_VFO_ALL}, - RIG_FRNG_END, }, -.tx_range_list1 = { - {kHz(1600),MHz(3)-100,ICM710_MODES,W(60),W(150),ICM710_VFO_ALL,RIG_ANT_1}, - {MHz(4), MHz(5)-100,ICM710_MODES,W(60),W(150),ICM710_VFO_ALL,RIG_ANT_1}, - {MHz(6), MHz(7)-100,ICM710_MODES,W(60),W(150),ICM710_VFO_ALL,RIG_ANT_1}, - {MHz(8), MHz(9)-100,ICM710_MODES,W(60),W(150),ICM710_VFO_ALL,RIG_ANT_1}, - {MHz(12), MHz(14)-100,ICM710_MODES,W(60),W(150),ICM710_VFO_ALL,RIG_ANT_1}, - {MHz(16), MHz(18)-100,ICM710_MODES,W(60),W(150),ICM710_VFO_ALL,RIG_ANT_1}, - {MHz(18), MHz(20)-100,ICM710_MODES,W(60),W(150),ICM710_VFO_ALL,RIG_ANT_1}, - {MHz(22), MHz(23)-100,ICM710_MODES,W(60),W(150),ICM710_VFO_ALL,RIG_ANT_1}, - {MHz(25), MHz(27.500),ICM710_MODES,W(60),W( 60),ICM710_VFO_ALL,RIG_ANT_1}, - RIG_FRNG_END, -}, + .rx_range_list1 = { {kHz(500), MHz(30) - 100, ICM710_RX_MODES, -1, -1, ICM710_VFO_ALL}, + RIG_FRNG_END, + }, + .tx_range_list1 = { + {kHz(1600), MHz(3) - 100, ICM710_MODES, W(60), W(150), ICM710_VFO_ALL, RIG_ANT_1}, + {MHz(4), MHz(5) - 100, ICM710_MODES, W(60), W(150), ICM710_VFO_ALL, RIG_ANT_1}, + {MHz(6), MHz(7) - 100, ICM710_MODES, W(60), W(150), ICM710_VFO_ALL, RIG_ANT_1}, + {MHz(8), MHz(9) - 100, ICM710_MODES, W(60), W(150), ICM710_VFO_ALL, RIG_ANT_1}, + {MHz(12), MHz(14) - 100, ICM710_MODES, W(60), W(150), ICM710_VFO_ALL, RIG_ANT_1}, + {MHz(16), MHz(18) - 100, ICM710_MODES, W(60), W(150), ICM710_VFO_ALL, RIG_ANT_1}, + {MHz(18), MHz(20) - 100, ICM710_MODES, W(60), W(150), ICM710_VFO_ALL, RIG_ANT_1}, + {MHz(22), MHz(23) - 100, ICM710_MODES, W(60), W(150), ICM710_VFO_ALL, RIG_ANT_1}, + {MHz(25), MHz(27.500), ICM710_MODES, W(60), W(60), ICM710_VFO_ALL, RIG_ANT_1}, + RIG_FRNG_END, + }, -.rx_range_list2 = { {kHz(500),MHz(30)-100,ICM710_RX_MODES,-1,-1,ICM710_VFO_ALL}, - RIG_FRNG_END, }, -.tx_range_list2 = { - {kHz(1600),MHz(3)-100,ICM710_MODES,W(20),W(150),ICM710_VFO_ALL,RIG_ANT_1}, - {MHz(4), MHz(5)-100,ICM710_MODES,W(20),W(150),ICM710_VFO_ALL,RIG_ANT_1}, - {MHz(6), MHz(7)-100,ICM710_MODES,W(20),W(150),ICM710_VFO_ALL,RIG_ANT_1}, - {MHz(8), MHz(9)-100,ICM710_MODES,W(20),W(150),ICM710_VFO_ALL,RIG_ANT_1}, - {MHz(12), MHz(14)-100,ICM710_MODES,W(20),W(150),ICM710_VFO_ALL,RIG_ANT_1}, - {MHz(16), MHz(18)-100,ICM710_MODES,W(20),W(150),ICM710_VFO_ALL,RIG_ANT_1}, - {MHz(18), MHz(20)-100,ICM710_MODES,W(20),W(150),ICM710_VFO_ALL,RIG_ANT_1}, - {MHz(22), MHz(23)-100,ICM710_MODES,W(20),W(150),ICM710_VFO_ALL,RIG_ANT_1}, - {MHz(25), MHz(27.500),ICM710_MODES,W(20),W( 60),ICM710_VFO_ALL,RIG_ANT_1}, - RIG_FRNG_END, -}, + .rx_range_list2 = { {kHz(500), MHz(30) - 100, ICM710_RX_MODES, -1, -1, ICM710_VFO_ALL}, + RIG_FRNG_END, + }, + .tx_range_list2 = { + {kHz(1600), MHz(3) - 100, ICM710_MODES, W(20), W(150), ICM710_VFO_ALL, RIG_ANT_1}, + {MHz(4), MHz(5) - 100, ICM710_MODES, W(20), W(150), ICM710_VFO_ALL, RIG_ANT_1}, + {MHz(6), MHz(7) - 100, ICM710_MODES, W(20), W(150), ICM710_VFO_ALL, RIG_ANT_1}, + {MHz(8), MHz(9) - 100, ICM710_MODES, W(20), W(150), ICM710_VFO_ALL, RIG_ANT_1}, + {MHz(12), MHz(14) - 100, ICM710_MODES, W(20), W(150), ICM710_VFO_ALL, RIG_ANT_1}, + {MHz(16), MHz(18) - 100, ICM710_MODES, W(20), W(150), ICM710_VFO_ALL, RIG_ANT_1}, + {MHz(18), MHz(20) - 100, ICM710_MODES, W(20), W(150), ICM710_VFO_ALL, RIG_ANT_1}, + {MHz(22), MHz(23) - 100, ICM710_MODES, W(20), W(150), ICM710_VFO_ALL, RIG_ANT_1}, + {MHz(25), MHz(27.500), ICM710_MODES, W(20), W(60), ICM710_VFO_ALL, RIG_ANT_1}, + RIG_FRNG_END, + }, -.tuning_steps = { - {ICM710_RX_MODES,Hz(1)}, - RIG_TS_END, - }, - /* mode/filter list, remember: order matters! */ -.filters = { - {RIG_MODE_SSB|RIG_MODE_CW|RIG_MODE_RTTY, kHz(2.3)}, - {RIG_MODE_AM, kHz(14)}, - RIG_FLT_END, - }, + .tuning_steps = { + {ICM710_RX_MODES, Hz(1)}, + RIG_TS_END, + }, + /* mode/filter list, remember: order matters! */ + .filters = { + {RIG_MODE_SSB | RIG_MODE_CW | RIG_MODE_RTTY, kHz(2.3)}, + {RIG_MODE_AM, kHz(14)}, + RIG_FLT_END, + }, -.cfgparams = icmarine_cfg_params, -.set_conf = icmarine_set_conf, -.get_conf = icmarine_get_conf, + .cfgparams = icm710_cfg_params, + .set_conf = icm710_set_conf, + .get_conf = icm710_get_conf, -.priv = (void*)&icm710_priv_caps, -.rig_init = icmarine_init, -.rig_cleanup = icmarine_cleanup, -.rig_open = NULL, -.rig_close = NULL, + .priv = (void *)& icm710_priv_caps, + .rig_init = icm710_init, + .rig_cleanup = icm710_cleanup, + .rig_open = icm710_open, + .rig_close = icm710_close, -.set_freq = icmarine_set_freq, -.get_freq = icmarine_get_freq, -.set_split_freq = icmarine_set_tx_freq, -.get_split_freq = icmarine_get_tx_freq, -.set_split_vfo = icmarine_set_split_vfo, -.get_split_vfo = icmarine_get_split_vfo, -.set_mode = icmarine_set_mode, -.get_mode = icmarine_get_mode, + .set_freq = icm710_set_freq, + .get_freq = icm710_get_freq, + .set_split_freq = icm710_set_tx_freq, + .get_split_freq = icm710_get_tx_freq, + .set_split_vfo = icm710_set_split_vfo, + .get_split_vfo = icm710_get_split_vfo, + .set_mode = icm710_set_mode, + .get_mode = icm710_get_mode, -.set_ptt = icmarine_set_ptt, -.get_ptt = icmarine_get_ptt, -.get_dcd = icmarine_get_dcd, -.vfo_op = icmarine_vfo_op, + .set_ptt = icm710_set_ptt, + .get_ptt = icm710_get_ptt, + .vfo_op = icm710_vfo_op, -.set_level = icmarine_set_level, -.get_level = icmarine_get_level, -.set_func = icmarine_set_func, -.get_func = icmarine_get_func, + .set_level = icm710_set_level, + .get_level = icm710_get_level, + .set_func = icm710_set_func, + .get_func = icm710_get_func, }; +/* + * NMEA 0183 protocol + * + * Total message is maximum 82 characters, including '$' and CR+LF. + * + * Serial setup is 8N1, msb always 0, -> ASCII protocol + * + * Proprietary Extension Message format: + * Byte pos Length Value Description + * 0 1 0x24 '$' Start character + * 1 1 0x50 'P' Type: Proprietary + * 2 3 'ICO' Manufacturer ID + * 5 Message Data + */ + + +/* CR LF */ +#define EOM "\x0d\x0a" + +#define BUFSZ 96 + +/* + * Protocol stuff + */ + +#define CONTROLLER_ID 90 + +#define MD_LSB "LSB" +#define MD_USB "USB" +#define MD_CW "CW" +#define MD_AM "AM" +#define MD_FSK "AFS" + +#define CMD_TXFREQ "TXF" /* Transmit frequency */ +#define CMD_RXFREQ "RXF" /* Receive frequency */ +#define CMD_MODE "MODE" /* Mode */ +#define CMD_REMOTE "REMOTE" /* Remote */ +#define CMD_PTT "TRX" /* PTT */ +#define CMD_AFGAIN "AFG" +#define CMD_RFGAIN "RFG" +#define CMD_RFPWR "TXP" +#define CMD_NB "NB" +#define CMD_AGC "AGC" +#define CMD_TUNER "TUNER" + +/* Data Output Commands */ +#define CMD_SMETER "SIGM" /* S-meter read */ +#define CMD_SQLS "SQLS" /* Squelch status */ + + +/* Tokens */ +#define TOK_REMOTEID TOKEN_BACKEND(1) + +const struct confparams icm710_cfg_params[] = { + { + TOK_REMOTEID, "remoteid", "Remote ID", "Transceiver's remote ID", + "1", RIG_CONF_NUMERIC, { .n = { 1, 99, 1 } } + }, + { RIG_CONF_END, NULL, } +}; + +/* + * Basically, set up *priv + */ +int icm710_init(RIG *rig) +{ + struct icm710_priv_data *priv; + const struct icm710_priv_caps *priv_caps; + const struct rig_caps *caps; + + if (!rig || !rig->caps) { + return -RIG_EINVAL; + } + + caps = rig->caps; + + if (!caps->priv) { + return -RIG_ECONF; + } + + priv_caps = (const struct icm710_priv_caps *) caps->priv; + + priv = (struct icm710_priv_data *)calloc(1, sizeof(struct icm710_priv_data)); + + if (!priv) { + /* whoops! memory shortage! */ + return -RIG_ENOMEM; + } + + rig->state.priv = (void *)priv; + + priv->remote_id = priv_caps->default_remote_id; + priv->split = RIG_SPLIT_OFF; + return RIG_OK; +} + +int icm710_open(RIG *rig) +{ + int retval = icmarine_transaction(rig, "REMOTE", "ON", NULL); + + if (retval != RIG_OK) { + rig_debug(RIG_DEBUG_VERBOSE, "%s: rig not responding? %s\n", __FUNCTION__, rigerror(retval)); + + } + + return RIG_OK; +} + +int icm710_close(RIG *rig) +{ + int retval = icmarine_transaction(rig, "REMOTE", "OFF", NULL); + + if (retval != RIG_OK) { + rig_debug(RIG_DEBUG_VERBOSE, "%s: rig not responding? %s\n", __FUNCTION__, rigerror(retval)); + + } + + return RIG_OK; +} +int icm710_cleanup(RIG *rig) +{ + if (!rig) { + return -RIG_EINVAL; + } + + if (rig->state.priv) { + free(rig->state.priv); + } + + rig->state.priv = NULL; + + return RIG_OK; +} + +int icm710_set_conf(RIG *rig, token_t token, const char *val) +{ + struct icm710_priv_data *priv; + + priv = (struct icm710_priv_data *)rig->state.priv; + + switch (token) { + case TOK_REMOTEID: + priv->remote_id = atoi(val); + break; + + default: + return -RIG_EINVAL; + } + + return RIG_OK; +} + +int icm710_get_conf(RIG *rig, token_t token, char *val) +{ + struct icm710_priv_data *priv; + + priv = (struct icm710_priv_data *)rig->state.priv; + + switch (token) { + case TOK_REMOTEID: + sprintf(val, "%u", priv->remote_id); + break; + + default: + return -RIG_EINVAL; + } + + return RIG_OK; +} + +int icm710_set_freq(RIG *rig, vfo_t vfo, freq_t freq) +{ + char freqbuf[BUFSZ]; + struct icm710_priv_data *priv; + int retval; + + priv = (struct icm710_priv_data *)rig->state.priv; + + sprintf(freqbuf, "%.6f", freq / MHz(1)); + + /* no error reporting upon TXFREQ failure */ + if (RIG_SPLIT_OFF == priv->split) { + retval = icmarine_transaction(rig, CMD_TXFREQ, freqbuf, NULL); + + if (retval != RIG_OK) { + return retval; + } + + priv->txfreq = freq; + } + + retval = icmarine_transaction(rig, CMD_RXFREQ, freqbuf, NULL); + + if (retval != RIG_OK) { + return retval; + } + + priv->rxfreq = freq; + + return RIG_OK; +} + +/* + * icm710_get_freq + * Assumes rig!=NULL, freq!=NULL + * The M710 does not respond to queries so we keep our own copy of things as a virtual rig response + */ +int icm710_get_freq(RIG *rig, vfo_t vfo, freq_t *freq) +{ + *freq = ((struct icm710_priv_data *)rig->state.priv)->rxfreq; + + return RIG_OK; +} + +int icm710_set_tx_freq(RIG *rig, vfo_t vfo, freq_t freq) +{ + char freqbuf[BUFSZ]; + int retval; + struct icm710_priv_data *priv; + + priv = (struct icm710_priv_data *)rig->state.priv; + + sprintf(freqbuf, "%.6f", freq / MHz(1)); + + retval = icmarine_transaction(rig, CMD_TXFREQ, freqbuf, NULL); + + if (retval != RIG_OK) { + return retval; + } + + priv->txfreq = freq; + return RIG_OK; +} + +int icm710_get_tx_freq(RIG *rig, vfo_t vfo, freq_t *freq) +{ + struct icm710_priv_data *priv; + + priv = (struct icm710_priv_data *)rig->state.priv; + + *freq = priv->txfreq; + return RIG_OK; +} + +int icm710_set_split_vfo(RIG *rig, vfo_t rx_vfo, split_t split, vfo_t tx_vfo) +{ + struct icm710_priv_data *priv; + + priv = (struct icm710_priv_data *)rig->state.priv; + + + /* when disabling split mode */ + if (RIG_SPLIT_ON == priv->split && RIG_SPLIT_OFF == split) { + int retval = icm710_set_tx_freq(rig, rx_vfo, priv->rxfreq); + + if (retval != RIG_OK) { + return retval; + } + } + + priv->split = split; + + return RIG_OK; +} + +int icm710_get_split_vfo(RIG *rig, vfo_t rx_vfo, split_t *split, vfo_t *tx_vfo) +{ + struct icm710_priv_data *priv; + + priv = (struct icm710_priv_data *)rig->state.priv; + + *split = priv->split; + *tx_vfo = rx_vfo; + + return RIG_OK; +} + +/* REM: no way to change passband width ? */ +int icm710_set_mode(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width) +{ + const char *pmode; + + switch (mode) { + case RIG_MODE_CW: + pmode = MD_CW; + break; + + case RIG_MODE_USB: + pmode = MD_USB; + break; + + case RIG_MODE_LSB: + pmode = MD_LSB; + break; + + case RIG_MODE_AM: + pmode = MD_AM; + break; + + case RIG_MODE_RTTY: + pmode = MD_FSK; + break; + + default: + rig_debug(RIG_DEBUG_ERR, + "%s: unsupported mode %d\n", + __func__, mode); + return -RIG_EINVAL; + } + + return icmarine_transaction(rig, CMD_MODE, pmode, NULL); +} + +int icm710_get_mode(RIG *rig, vfo_t vfo, rmode_t *mode, pbwidth_t *width) +{ + *mode = ((struct icm710_priv_data *)rig->state.priv)->mode; + *width = 2200; + + return RIG_OK; +} + +/* + * Rem: The "TX" command will fail on invalid frequencies. + */ +int icm710_set_ptt(RIG *rig, vfo_t vfo, ptt_t ptt) +{ + int retval; + struct icm710_priv_data *priv; + + priv = (struct icm710_priv_data *)rig->state.priv; + retval = icmarine_transaction(rig, CMD_PTT, + ptt == RIG_PTT_ON ? "TX" : "RX", NULL); + + if (retval != RIG_OK) { + return retval; + } + + priv->ptt = ptt; + return RIG_OK; +} + + +int icm710_get_ptt(RIG *rig, vfo_t vfo, ptt_t *ptt) +{ + *ptt = ((struct icm710_priv_data *)rig->state.priv)->ptt; + + return RIG_OK; +} + +int icm710_vfo_op(RIG *rig, vfo_t vfo, vfo_op_t op) +{ + if (RIG_OP_TUNE != op && RIG_OP_NONE != op) { + return -RIG_EINVAL; + } + + return icmarine_transaction(rig, CMD_TUNER, + RIG_OP_TUNE == op ? "ON" : "OFF", NULL); +} + +int icm710_set_func(RIG *rig, vfo_t vfo, setting_t func, int status) +{ + int retval; + + switch (func) { + case RIG_FUNC_NB: + retval = icmarine_transaction(rig, CMD_NB, status ? "ON" : "OFF", NULL); + break; + + default: + return -RIG_EINVAL; + } + + return retval; +} + +int icm710_get_func(RIG *rig, vfo_t vfo, setting_t func, int *status) +{ + char funcbuf[BUFSZ]; + int retval; + + switch (func) { + case RIG_FUNC_NB: + retval = icmarine_transaction(rig, CMD_NB, NULL, funcbuf); + break; + + default: + return -RIG_EINVAL; + } + + *status = !strcmp(funcbuf, "ON"); + + return retval; +} + + +int icm710_set_level(RIG *rig, vfo_t vfo, setting_t level, value_t val) +{ + char lvlbuf[BUFSZ]; + int retval; + unsigned value; + struct icm710_priv_data *priv; + + priv = (struct icm710_priv_data *)rig->state.priv; + + + switch (level) { + case RIG_LEVEL_AF: + value = (unsigned)(val.f * 255); + sprintf(lvlbuf, "%u", value); + retval = icmarine_transaction(rig, CMD_AFGAIN, lvlbuf, NULL); + + if (retval == RIG_OK) { + priv->afgain = value; + } + + break; + + case RIG_LEVEL_RF: + value = (unsigned)(val.f * 9); + sprintf(lvlbuf, "%u", value); + retval = icmarine_transaction(rig, CMD_RFGAIN, lvlbuf, NULL); + + if (retval == RIG_OK) { + priv->rfgain = value; + } + + break; + + case RIG_LEVEL_RFPOWER: + value = (unsigned)(val.f * 2); + sprintf(lvlbuf, "%u", value); + retval = icmarine_transaction(rig, CMD_RFPWR, lvlbuf, NULL); + + if (retval == RIG_OK) { + priv->rfpwr = value; + } + + break; + + case RIG_LEVEL_AGC: + retval = icmarine_transaction(rig, CMD_AGC, + RIG_AGC_OFF == val.i ? "OFF" : "ON", NULL); + + if (retval == RIG_OK) { + priv->afgain = val.i; + } + + break; + + default: + return -RIG_EINVAL; + } + + return retval; +} + +int icm710_get_level(RIG *rig, vfo_t vfo, setting_t level, value_t *val) +{ + struct icm710_priv_data *priv; + + priv = (struct icm710_priv_data *)rig->state.priv; + + + switch (level) { + + case RIG_LEVEL_AF: + val->f = priv->afgain / 255.; + break; + + case RIG_LEVEL_RF: + val->f = priv->rfgain / 9.; + break; + + case RIG_LEVEL_RFPOWER: + val->f = priv->rfpwr / 3.; + break; + + case RIG_LEVEL_AGC: + val->i = priv->agc; + break; + + default: + return -RIG_EINVAL; + } + + return -RIG_OK; +} + + + +/* + * initrigs_icm710 is called by rig_backend_load + */ +DECLARE_INITRIG_BACKEND(icm710) +{ + rig_debug(RIG_DEBUG_VERBOSE, "icm710: icm710_init called\n"); + + rig_register(&icm700pro_caps); + rig_register(&icm710_caps); + rig_register(&icm802_caps); + + return RIG_OK; +} diff --git a/icmarine/icm710.h b/icmarine/icm710.h new file mode 100644 index 000000000..1a5c2b44b --- /dev/null +++ b/icmarine/icm710.h @@ -0,0 +1,85 @@ +/* + * Hamlib ICOM M710 backend - main header + * Copyright (c) 2014-2015 by Stephane Fillod + * + * + * 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 + * + */ + +#ifndef _ICM710_H +#define _ICM710_H 1 + +#include "hamlib/rig.h" +#include "cal.h" +#include "tones.h" + +#ifdef HAVE_SYS_TIME_H +#include +#endif + +struct icm710_priv_caps { + unsigned char default_remote_id; /* the remote default equipment's ID */ +}; + +/* The M710 does not support queries */ +/* So we keep a copy of settings in priv to support get functions */ +/* The priv settings only reflect what has been previously set */ +/* So get's will return 0 until the value has been set */ +struct icm710_priv_data { + unsigned char remote_id; /* the remote equipment's ID */ + split_t split; /* current split mode */ + freq_t rxfreq, txfreq; + mode_t mode; + ptt_t ptt; + unsigned afgain; + unsigned rfgain; + unsigned rfpwr; + unsigned agc; +}; + +extern const struct confparams icm710_cfg_params[]; + +int icm710_init(RIG *rig); +int icm710_cleanup(RIG *rig); +int icm710_open(RIG *rig); +int icm710_close(RIG *rig); +int icm710_set_freq(RIG *rig, vfo_t vfo, freq_t freq); +int icm710_get_freq(RIG *rig, vfo_t vfo, freq_t *freq); +int icm710_set_tx_freq(RIG *rig, vfo_t vfo, freq_t freq); +int icm710_get_tx_freq(RIG *rig, vfo_t vfo, freq_t *freq); +int icm710_set_split_vfo(RIG *rig, vfo_t rx_vfo, split_t split, vfo_t tx_vfo); +int icm710_get_split_vfo(RIG *rig, vfo_t rx_vfo, split_t *split, vfo_t *tx_vfo); +int icm710_set_mode(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width); +int icm710_get_mode(RIG *rig, vfo_t vfo, rmode_t *mode, pbwidth_t *width); +int icm710_set_split_freq(RIG *rig, vfo_t vfo, freq_t tx_freq); +int icm710_get_split_freq(RIG *rig, vfo_t vfo, freq_t *tx_freq); +int icm710_set_ptt(RIG *rig, vfo_t vfo, ptt_t ptt); +int icm710_get_ptt(RIG *rig, vfo_t vfo, ptt_t *ptt); +int icm710_vfo_op(RIG *rig, vfo_t vfo, vfo_op_t op); +int icm710_set_level(RIG *rig, vfo_t vfo, setting_t level, value_t val); +int icm710_get_level(RIG *rig, vfo_t vfo, setting_t level, value_t *val); +int icm710_set_func(RIG *rig, vfo_t vfo, setting_t func, int status); +int icm710_get_func(RIG *rig, vfo_t vfo, setting_t func, int *status); +int icm710_set_parm(RIG *rig, setting_t parm, value_t val); +int icm710_get_parm(RIG *rig, setting_t parm, value_t *val); +int icm710_set_conf(RIG *rig, token_t token, const char *val); +int icm710_get_conf(RIG *rig, token_t token, char *val); + +extern const struct rig_caps icm700pro_caps; +extern const struct rig_caps icm710_caps; +extern const struct rig_caps icm802_caps; + +#endif /* _ICM710_H */ diff --git a/icmarine/icmarine.c b/icmarine/icmarine.c index ff7ec3975..0d20d3a15 100644 --- a/icmarine/icmarine.c +++ b/icmarine/icmarine.c @@ -101,6 +101,8 @@ /* Tokens */ #define TOK_REMOTEID TOKEN_BACKEND(1) +int icmarine_transaction(RIG *rig, const char *cmd, const char *param, char *response); + const struct confparams icmarine_cfg_params[] = { { TOK_REMOTEID, "remoteid", "Remote ID", "Transceiver's remote ID", "1", RIG_CONF_NUMERIC, { .n = { 1, 99, 1 } } @@ -153,6 +155,19 @@ int icmarine_cleanup(RIG *rig) return RIG_OK; } +int icmarine_open(RIG *rig) +{ + char respbuf[BUFSZ+1]; + rig_debug(RIG_DEBUG_VERBOSE,"%s called\n", __FUNCTION__); + int retval = icmarine_transaction(rig, "REMOTE", "ON", respbuf); + if (retval != RIG_OK) { + rig_debug(RIG_DEBUG_VERBOSE, "%s: rig not responding? %s\n",__FUNCTION__, rigerror(retval)); + + } + return RIG_OK; +} + + int icmarine_set_conf(RIG *rig, token_t token, const char *val) { struct icmarine_priv_data *priv; @@ -260,6 +275,9 @@ int icmarine_transaction(RIG *rig, const char *cmd, const char *param, char *res } /* So this is a query */ + retval = read_string(&rs->rigport, respbuf, BUFSZ, LF, strlen(LF)); + if (retval < 0) + return retval; /* strip *checksum and CR/LF from string */ respbuf[retval-5] = 0; diff --git a/icmarine/icmarine.h b/icmarine/icmarine.h index a12162925..dd002a4d1 100644 --- a/icmarine/icmarine.h +++ b/icmarine/icmarine.h @@ -43,8 +43,10 @@ struct icmarine_priv_data { extern const struct confparams icmarine_cfg_params[]; +int icmarine_transaction(RIG *rig, const char *cmd, const char *param, char *response); int icmarine_init(RIG *rig); int icmarine_cleanup(RIG *rig); +int icmarine_open(RIG *rig); int icmarine_set_freq(RIG *rig, vfo_t vfo, freq_t freq); int icmarine_get_freq(RIG *rig, vfo_t vfo, freq_t *freq); int icmarine_set_tx_freq(RIG *rig, vfo_t vfo, freq_t freq); From 41a5e64dd5997bf53936e77a034af3484c58337b Mon Sep 17 00:00:00 2001 From: Michael Black Date: Thu, 20 Jul 2017 08:42:39 -0500 Subject: [PATCH 2/2] Add icm710.h to icmarine Makefile.am --- icmarine/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/icmarine/Makefile.am b/icmarine/Makefile.am index e3991ba52..7866c52c3 100644 --- a/icmarine/Makefile.am +++ b/icmarine/Makefile.am @@ -1,5 +1,5 @@ #icm802.c -ICMARINESRC = icm700pro.c icm710.c icm802.c \ +ICMARINESRC = icm700pro.c icm710.c icm710.h icm802.c \ icmarine.c icmarine.h noinst_LTLIBRARIES = libhamlib-icmarine.la