diff --git a/Makefile.am b/Makefile.am index 7428c1859..8d07a983d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -19,7 +19,7 @@ SUBDIRS = macros include lib \ ## Static list of distributed directories. $(BACKEND_LIST) is dynamically ## assigned by 'configure' so list rig backends statically. DIST_SUBDIRS = macros include lib src c++ bindings tests doc android scripts \ - adat alinco aor drake dummy flexradio icom jrc kachina kenwood kit \ + adat alinco aor drake dummy flexradio icom icmarine jrc kachina kenwood kit \ lowe pcr prm80 racal rft rs skanti tapr tentec tuner uniden wj yaesu \ winradio \ $(ROT_BACKEND_LIST) diff --git a/NEWS b/NEWS index 222512c73..a13ac74e0 100644 --- a/NEWS +++ b/NEWS @@ -1,12 +1,12 @@ Hamlib -- History of visible changes. Copyright (C) 2000-2003 Frank Singleton -Copyright (C) 2000-2013 Stephane Fillod, and others +Copyright (C) 2000-2015 Stephane Fillod, and others Please send Hamlib bug reports to hamlib-developer@lists.sourceforge.net Version 3.0 - 2013-??-?? + 2015-??-?? * Kill RPC backends and rpc.rigd/rpc.rotd * Remove -e|--end-marker option from rigctld and rotctld * Build system updates--remove obsolete macros, autogen.sh now @@ -51,6 +51,7 @@ Version 3.0 only invoke pkg-config when either or both of these features are selected. Only the Winradio g313 model uses libdl so test for it only when Winradio backend is enabled. + * New IC-M700PRO. Version 1.2.15.3 2012-11-01 diff --git a/configure.ac b/configure.ac index adb73231c..26fd5642f 100644 --- a/configure.ac +++ b/configure.ac @@ -49,7 +49,7 @@ dnl added to AC_CONFIG_FILES near the end of this file. See README.developer dnl Beware of duplication should a backend directory include both rig and dnl rotor definitions, e.g. "dummy". Optional backends will not be listed dnl here but will be added later, e.g. "winradio". -BACKEND_LIST="adat alinco aor drake dummy flexradio icom jrc kachina kenwood kit lowe pcr prm80 racal rft rs skanti tapr tentec tuner uniden wj yaesu" +BACKEND_LIST="adat alinco aor drake dummy flexradio icom icmarine jrc kachina kenwood kit lowe pcr prm80 racal rft rs skanti tapr tentec tuner uniden wj yaesu" ROT_BACKEND_LIST="amsat ars celestron easycomm ether6 fodtrack gs232a heathkit m2 rotorez sartek spid ts7400" dnl See README.release on setting these values @@ -695,6 +695,7 @@ lib/Makefile dummy/Makefile yaesu/Makefile icom/Makefile +icmarine/Makefile aor/Makefile kenwood/Makefile winradio/Makefile diff --git a/icmarine/Android.mk b/icmarine/Android.mk new file mode 100644 index 000000000..55901fab2 --- /dev/null +++ b/icmarine/Android.mk @@ -0,0 +1,13 @@ +LOCAL_PATH:= $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := icm700pro.c icm802.c \ + icmarine.c +LOCAL_MODULE := icmarine + +LOCAL_CFLAGS := -DHAVE_CONFIG_H +LOCAL_C_INCLUDES := android include src +LOCAL_LDLIBS := -lhamlib -Lobj/local/armeabi + +include $(BUILD_STATIC_LIBRARY) diff --git a/icmarine/Makefile.am b/icmarine/Makefile.am new file mode 100644 index 000000000..b931a62f2 --- /dev/null +++ b/icmarine/Makefile.am @@ -0,0 +1,8 @@ +#icm802.c +ICMARINESRC = icm700pro.c \ + icmarine.c icmarine.h + +noinst_LTLIBRARIES = libhamlib-icmarine.la +libhamlib_icmarine_la_SOURCES = $(ICMARINESRC) + +EXTRA_DIST = Android.mk diff --git a/icmarine/icm700pro.c b/icmarine/icm700pro.c new file mode 100644 index 000000000..96c388a72 --- /dev/null +++ b/icmarine/icm700pro.c @@ -0,0 +1,178 @@ +/* + * Hamlib ICOM Marine backend - description of IC-M700PRO caps + * 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 + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include "hamlib/rig.h" +#include "icmarine.h" +#include "idx_builtin.h" +#include "bandplan.h" + +#define ICM700PRO_MODES (RIG_MODE_SSB|RIG_MODE_CW|RIG_MODE_RTTY) +#define ICM700PRO_RX_MODES (ICM700PRO_MODES|RIG_MODE_AM) + +#define ICM700PRO_FUNC_ALL (RIG_FUNC_NB) + +#define ICM700PRO_LEVEL_ALL (RIG_LEVEL_RFPOWER|RIG_LEVEL_AF|RIG_LEVEL_RF|RIG_LEVEL_AGC|RIG_LEVEL_RAWSTR) + +#define ICM700PRO_VFO_ALL (RIG_VFO_A) + +#define ICM700PRO_VFO_OPS (RIG_OP_TUNE) + +#define ICM700PRO_SCAN_OPS (RIG_SCAN_NONE) + +/* + * TODO calibrate the real values + */ +#define ICM700PRO_STR_CAL { 2, {{ 0, -60}, { 8, 60}} } + + +static const struct icmarine_priv_caps icm700pro_priv_caps = { + .default_remote_id = 2, +}; + +const struct rig_caps icm700pro_caps = { +.rig_model = RIG_MODEL_IC_M700PRO, +.model_name = "IC-M700PRO", +.mfg_name = "Icom", +.version = BACKEND_VER, +.copyright = "LGPL", +.status = RIG_STATUS_ALPHA, +.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 = ICM700PRO_FUNC_ALL, +.has_set_func = ICM700PRO_FUNC_ALL, +.has_get_level = ICM700PRO_LEVEL_ALL, +.has_set_level = RIG_LEVEL_SET(ICM700PRO_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 = ICM700PRO_STR_CAL, +.ctcss_list = NULL, +.dcs_list = NULL, +.preamp = { RIG_DBLST_END, }, +.attenuator = { RIG_DBLST_END, }, +.max_rit = Hz(150), +.max_xit = Hz(0), +.max_ifshift = Hz(0), +.targetable_vfo = 0, +.vfo_ops = ICM700PRO_VFO_OPS, +.scan_ops = ICM700PRO_SCAN_OPS, +.transceive = RIG_TRN_OFF, +.bank_qty = 3, +.chan_desc_sz = 0, + +.chan_list = { + RIG_CHAN_END, + }, + +.rx_range_list1 = { {kHz(500),MHz(30)-100,ICM700PRO_RX_MODES,-1,-1,ICM700PRO_VFO_ALL}, + RIG_FRNG_END, }, +.tx_range_list1 = { + {kHz(1600),MHz(3)-100,ICM700PRO_MODES,W(150),W(150),ICM700PRO_VFO_ALL,RIG_ANT_1}, + {MHz(4), MHz(5)-100,ICM700PRO_MODES,W(150),W(150),ICM700PRO_VFO_ALL,RIG_ANT_1}, + {MHz(6), MHz(7)-100,ICM700PRO_MODES,W(150),W(150),ICM700PRO_VFO_ALL,RIG_ANT_1}, + {MHz(8), MHz(9)-100,ICM700PRO_MODES,W(150),W(150),ICM700PRO_VFO_ALL,RIG_ANT_1}, + {MHz(12), MHz(14)-100,ICM700PRO_MODES,W(150),W(150),ICM700PRO_VFO_ALL,RIG_ANT_1}, + {MHz(16), MHz(18)-100,ICM700PRO_MODES,W(150),W(150),ICM700PRO_VFO_ALL,RIG_ANT_1}, + {MHz(18), MHz(20)-100,ICM700PRO_MODES,W(150),W(150),ICM700PRO_VFO_ALL,RIG_ANT_1}, + {MHz(22), MHz(23)-100,ICM700PRO_MODES,W(150),W(150),ICM700PRO_VFO_ALL,RIG_ANT_1}, + {MHz(25), MHz(27.500),ICM700PRO_MODES,W( 60),W( 60),ICM700PRO_VFO_ALL,RIG_ANT_1}, + RIG_FRNG_END, +}, + +.rx_range_list2 = { {kHz(500),MHz(30)-100,ICM700PRO_RX_MODES,-1,-1,ICM700PRO_VFO_ALL}, + RIG_FRNG_END, }, +.tx_range_list2 = { + {kHz(1600),MHz(3)-100,ICM700PRO_MODES,W(150),W(150),ICM700PRO_VFO_ALL,RIG_ANT_1}, + {MHz(4), MHz(5)-100,ICM700PRO_MODES,W(150),W(150),ICM700PRO_VFO_ALL,RIG_ANT_1}, + {MHz(6), MHz(7)-100,ICM700PRO_MODES,W(150),W(150),ICM700PRO_VFO_ALL,RIG_ANT_1}, + {MHz(8), MHz(9)-100,ICM700PRO_MODES,W(150),W(150),ICM700PRO_VFO_ALL,RIG_ANT_1}, + {MHz(12), MHz(14)-100,ICM700PRO_MODES,W(150),W(150),ICM700PRO_VFO_ALL,RIG_ANT_1}, + {MHz(16), MHz(18)-100,ICM700PRO_MODES,W(150),W(150),ICM700PRO_VFO_ALL,RIG_ANT_1}, + {MHz(18), MHz(20)-100,ICM700PRO_MODES,W(150),W(150),ICM700PRO_VFO_ALL,RIG_ANT_1}, + {MHz(22), MHz(23)-100,ICM700PRO_MODES,W(150),W(150),ICM700PRO_VFO_ALL,RIG_ANT_1}, + {MHz(25), MHz(27.500),ICM700PRO_MODES,W( 60),W( 60),ICM700PRO_VFO_ALL,RIG_ANT_1}, + RIG_FRNG_END, +}, + +.tuning_steps = { + {ICM700PRO_RX_MODES,Hz(100)}, + 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, + +.priv = (void*)&icm700pro_priv_caps, +.rig_init = icmarine_init, +.rig_cleanup = icmarine_cleanup, +.rig_open = NULL, +.rig_close = NULL, + +.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_ptt = icmarine_set_ptt, +.get_ptt = icmarine_get_ptt, +.get_dcd = icmarine_get_dcd, +.vfo_op = icmarine_vfo_op, + +.set_level = icmarine_set_level, +.get_level = icmarine_get_level, +.set_func = icmarine_set_func, +.get_func = icmarine_get_func, + +}; + + diff --git a/icmarine/icmarine.c b/icmarine/icmarine.c new file mode 100644 index 000000000..9e0e45f56 --- /dev/null +++ b/icmarine/icmarine.c @@ -0,0 +1,625 @@ +/* + * Hamlib ICOM Marine backend - main file + * 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 + * + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include /* String function definitions */ +#include /* UNIX standard function definitions */ +#include + +#include +#include +#include +#include +#include +#include + +#include "icmarine.h" + + +/* + * 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 LF "\x0a" + +#define BUFSZ 96 + +#define OFFSET_CMD 13 + +/* + * Protocol stuff + */ + +#define CONTROLLER_ID 90 + +#if 0 +#define MD_LSB "J3E" +#define MD_USB "J3E" +#define MD_CW "A1A" +#define MD_AM "A3E" +#else +#define MD_LSB "LSB" +#define MD_USB "USB" +#define MD_CW "CW" +#define MD_AM "AM" +#endif +#define MD_FSK "J2B" + +#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 icmarine_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 icmarine_init(RIG *rig) +{ + struct icmarine_priv_data *priv; + const struct icmarine_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 icmarine_priv_caps *) caps->priv; + + priv = (struct icmarine_priv_data*)malloc(sizeof(struct icmarine_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 icmarine_cleanup(RIG *rig) +{ + if (!rig) + return -RIG_EINVAL; + + if (rig->state.priv) + free(rig->state.priv); + rig->state.priv = NULL; + + return RIG_OK; +} + +int icmarine_set_conf(RIG *rig, token_t token, const char *val) +{ + struct icmarine_priv_data *priv; + + priv = (struct icmarine_priv_data*)rig->state.priv; + + switch(token) { + case TOK_REMOTEID: + priv->remote_id = atoi(val); + break; + default: + return -RIG_EINVAL; + } + return RIG_OK; +} + +int icmarine_get_conf(RIG *rig, token_t token, char *val) +{ + struct icmarine_priv_data *priv; + + priv = (struct icmarine_priv_data*)rig->state.priv; + + switch(token) { + case TOK_REMOTEID: + sprintf(val, "%u", priv->remote_id); + break; + default: + return -RIG_EINVAL; + } + return RIG_OK; +} + + +/* + * icmarine_transaction + * We assume that rig!=NULL, rig->state!= NULL, data!=NULL, data_len!=NULL + * + * cmd: mandatory + * param: only 1 optional NMEA paramter, NULL for none (=query) + * response: optional (holding BUFSZ bytes) + */ +int icmarine_transaction(RIG *rig, const char *cmd, const char *param, char *response) +{ + struct icmarine_priv_data *priv; + int i, retval; + struct rig_state *rs; + char cmdbuf[BUFSZ+1]; + char respbuf[BUFSZ+1]; + char *p; + int cmd_len = 0; + unsigned csum = 0; + + rs = &rig->state; + priv = (struct icmarine_priv_data *)rs->priv; + + serial_flush(&rs->rigport); + + /* command formating */ + cmdbuf[BUFSZ]='\0'; + + cmd_len = snprintf(cmdbuf, BUFSZ, "$PICOA,%02u,%02u,%s", + CONTROLLER_ID, + priv->remote_id, + cmd); + + if (param) + cmd_len += snprintf(cmdbuf+cmd_len, BUFSZ-cmd_len, ",%s", param); + + /* NMEA checksum, betwwen '$' and '*' */ + for (i=1; irigport, cmdbuf, cmd_len); + if (retval != RIG_OK) + return retval; + + /* + * Transceiver sends an echo of cmd followed by a CR/LF + */ + retval = read_string(&rs->rigport, respbuf, BUFSZ, LF, strlen(LF)); + if (retval < 0) + return retval; + + /* Minimal length */ + if (retval < OFFSET_CMD+5) + return -RIG_EPROTO; + + respbuf[retval] = 0; + + /* check response */ + if (memcmp(respbuf, "$PICOA,", strlen("$PICOA,"))) + return -RIG_EPROTO; + + /* TODO: check ID's */ + + /* if not a query, check for correct as acknowledge */ + if (param) { + if (memcmp(cmdbuf+OFFSET_CMD, respbuf+OFFSET_CMD, cmd_len-OFFSET_CMD-5) == 0) + return RIG_OK; + else + return -RIG_ERJCTED; + } + + /* So this is a query */ + + /* strip *checksum and CR/LF from string */ + respbuf[retval-5] = 0; + + p = strchr(respbuf+OFFSET_CMD, ','); + if (p) + strncpy(response, p+1, BUFSZ); + else + return -RIG_EPROTO; + + return RIG_OK; +} + + +int icmarine_set_freq(RIG *rig, vfo_t vfo, freq_t freq) +{ + char freqbuf[BUFSZ]; + struct icmarine_priv_data *priv; + + priv = (struct icmarine_priv_data*)rig->state.priv; + + sprintf(freqbuf, "%.6f", freq/MHz(1)); + + /* no error reporting upon TXFREQ failure */ + if (RIG_SPLIT_OFF == priv->split) + icmarine_transaction (rig, CMD_TXFREQ, freqbuf, NULL); + + return icmarine_transaction (rig, CMD_RXFREQ, freqbuf, NULL); +} + +/* + * icmarine_get_freq + * Assumes rig!=NULL, freq!=NULL + */ +int icmarine_get_freq(RIG *rig, vfo_t vfo, freq_t *freq) +{ + int retval; + char freqbuf[BUFSZ] = ""; + double d; + + retval = icmarine_transaction (rig, CMD_RXFREQ, NULL, freqbuf); + if (retval != RIG_OK) + return retval; + + if (freqbuf[0] == '\0') { + *freq = 0; + } else { + if (sscanf(freqbuf, "%lf", &d) != 1) + return -RIG_EPROTO; + + *freq = (freq_t)(d*MHz(1)); + } + + return RIG_OK; +} + +int icmarine_set_tx_freq(RIG *rig, vfo_t vfo, freq_t freq) +{ + char freqbuf[BUFSZ]; + + sprintf(freqbuf, "%.6f", freq/MHz(1)); + + return icmarine_transaction (rig, CMD_TXFREQ, freqbuf, NULL); +} + +int icmarine_get_tx_freq(RIG *rig, vfo_t vfo, freq_t *freq) +{ + int retval; + char freqbuf[BUFSZ] = ""; + double d; + + retval = icmarine_transaction (rig, CMD_TXFREQ, NULL, freqbuf); + if (retval != RIG_OK) + return retval; + + if (freqbuf[0] == '\0') { + *freq = 0; + } else { + if (sscanf(freqbuf, "%lf", &d) != 1) + return -RIG_EPROTO; + + *freq = (freq_t)(d*MHz(1)); + } + + return RIG_OK; +} + +int icmarine_set_split_vfo(RIG *rig, vfo_t rx_vfo, split_t split, vfo_t tx_vfo) +{ + struct icmarine_priv_data *priv; + + priv = (struct icmarine_priv_data *)rig->state.priv; + + + /* when disabling split mode */ + if (RIG_SPLIT_ON == priv->split && + RIG_SPLIT_OFF == split) + { + freq_t freq; + if (RIG_OK == icmarine_get_freq(rig, rx_vfo, &freq)) + icmarine_set_tx_freq(rig, rx_vfo, freq); + } + + priv->split = split; + + return RIG_OK; +} + +int icmarine_get_split_vfo(RIG *rig, vfo_t rx_vfo, split_t *split, vfo_t *tx_vfo) +{ + struct icmarine_priv_data *priv; + + priv = (struct icmarine_priv_data *)rig->state.priv; + + *split = priv->split; + *tx_vfo = rx_vfo; + + return RIG_OK; +} + +/* REM: no way to change passband width ? */ +int icmarine_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 icmarine_get_mode(RIG *rig, vfo_t vfo, rmode_t *mode, pbwidth_t *width) +{ + int retval; + char modebuf[BUFSZ]; + + retval = icmarine_transaction (rig, CMD_MODE, NULL, modebuf); + if (retval != RIG_OK) + return retval; + + + if (!memcmp(modebuf, MD_LSB, strlen(MD_LSB))) + *mode = RIG_MODE_LSB; + else if (!memcmp(modebuf, MD_USB, strlen(MD_USB))) + *mode = RIG_MODE_USB; + else if (!memcmp(modebuf, MD_CW, strlen(MD_CW))) + *mode = RIG_MODE_CW; + else if (!memcmp(modebuf, MD_AM, strlen(MD_AM))) + *mode = RIG_MODE_AM; + else if (!memcmp(modebuf, MD_FSK, strlen(MD_FSK))) + *mode = RIG_MODE_RTTY; + else + retval = -RIG_EPROTO; + + if (retval == RIG_OK) + *width = rig_passband_normal(rig, *mode); + + return retval; +} + +/* + * Rem: The "TX" command will fail on invalid frequencies. + */ +int icmarine_set_ptt(RIG *rig, vfo_t vfo, ptt_t ptt) +{ + return icmarine_transaction (rig, CMD_PTT, + ptt == RIG_PTT_ON ? "TX" : "RX", NULL); +} + +int icmarine_get_ptt(RIG *rig, vfo_t vfo, ptt_t *ptt) +{ + char pttbuf[BUFSZ]; + int retval; + + retval = icmarine_transaction (rig, CMD_PTT, NULL, pttbuf); + + if (retval != RIG_OK) + return retval; + + if (!strcmp(pttbuf, "TX")) + *ptt = RIG_PTT_ON; + else if (!strcmp(pttbuf, "RX")) + *ptt = RIG_PTT_OFF; + else + retval = -RIG_EPROTO; + + return retval; +} + +int icmarine_get_dcd(RIG *rig, vfo_t vfo, dcd_t *dcd) +{ + char dcdbuf[BUFSZ]; + int retval; + + retval = icmarine_transaction (rig, CMD_SQLS, NULL, dcdbuf); + + if (retval != RIG_OK) + return retval; + + if (!strcmp(dcdbuf, "OPEN")) + *dcd = RIG_DCD_ON; + else if (!strcmp(dcdbuf, "CLOSE")) + *dcd = RIG_DCD_OFF; + else + retval = -RIG_EPROTO; + + return retval; +} + +int icmarine_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 icmarine_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 icmarine_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 icmarine_set_level(RIG *rig, vfo_t vfo, setting_t level, value_t val) +{ + char lvlbuf[BUFSZ]; + int retval; + + switch(level) { + case RIG_LEVEL_AF: + sprintf(lvlbuf, "%u", (unsigned)(val.f * 255)); + retval = icmarine_transaction (rig, CMD_AFGAIN, lvlbuf, NULL); + break; + + case RIG_LEVEL_RF: + sprintf(lvlbuf, "%u", (unsigned)(val.f * 9)); + retval = icmarine_transaction (rig, CMD_RFGAIN, lvlbuf, NULL); + break; + + case RIG_LEVEL_RFPOWER: + sprintf(lvlbuf, "%u", 1 + (unsigned)(val.f * 2)); + retval = icmarine_transaction (rig, CMD_RFPWR, lvlbuf, NULL); + break; + + case RIG_LEVEL_AGC: + retval = icmarine_transaction (rig, CMD_AGC, + RIG_AGC_OFF == val.i ? "OFF":"ON", NULL); + break; + + default: + return -RIG_EINVAL; + } + + return retval; +} + +int icmarine_get_level(RIG *rig, vfo_t vfo, setting_t level, value_t *val) +{ + char lvlbuf[BUFSZ]; + int retval; + + switch(level) { + case RIG_LEVEL_RAWSTR: + retval = icmarine_transaction (rig, CMD_SMETER, NULL, lvlbuf); + if (retval != RIG_OK) + return retval; + if (lvlbuf[0] < '0' || lvlbuf[0] > '9') + return -RIG_EPROTO; + val->i = lvlbuf[0] - '0'; + break; + case RIG_LEVEL_AF: + retval = icmarine_transaction (rig, CMD_AFGAIN, NULL, lvlbuf); + if (retval != RIG_OK) + return retval; + val->f = atof(lvlbuf)/255.; + break; + case RIG_LEVEL_RF: + retval = icmarine_transaction (rig, CMD_RFGAIN, NULL, lvlbuf); + if (retval != RIG_OK) + return retval; + if (lvlbuf[0] < '0' || lvlbuf[0] > '9') + return -RIG_EPROTO; + val->f = (float)(lvlbuf[0] - '0')/9.; + break; + case RIG_LEVEL_RFPOWER: + retval = icmarine_transaction (rig, CMD_RFPWR, NULL, lvlbuf); + if (retval != RIG_OK) + return retval; + if (lvlbuf[0] < '1' || lvlbuf[0] > '3') + return -RIG_EPROTO; + val->f = (float)(lvlbuf[0] - '1')/3.; + break; + + case RIG_LEVEL_AGC: + retval = icmarine_transaction (rig, CMD_AGC, NULL, lvlbuf); + if (retval != RIG_OK) + return retval; + val->i = !strcmp(lvlbuf, "ON") ? RIG_AGC_SLOW : RIG_AGC_OFF; + break; + + default: + return -RIG_EINVAL; + } + + return retval; +} + + + +/* + * initrigs_icmarine is called by rig_backend_load + */ +DECLARE_INITRIG_BACKEND(icmarine) +{ + rig_debug(RIG_DEBUG_VERBOSE, "icmarine: _init called\n"); + + rig_register(&icm700pro_caps); + //rig_register(&icm802_caps); + + return RIG_OK; +} + diff --git a/icmarine/icmarine.h b/icmarine/icmarine.h new file mode 100644 index 000000000..9cfb1eda4 --- /dev/null +++ b/icmarine/icmarine.h @@ -0,0 +1,74 @@ +/* + * Hamlib ICOM Marine 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 _ICMARINE_H +#define _ICMARINE_H 1 + +#include "hamlib/rig.h" +#include "cal.h" +#include "tones.h" + +#ifdef HAVE_SYS_TIME_H +#include +#endif + +#define BACKEND_VER "0.1" + +struct icmarine_priv_caps { + unsigned char default_remote_id; /* the remote default equipment's ID */ +}; + +struct icmarine_priv_data { + unsigned char remote_id; /* the remote equipment's ID */ + split_t split; /* current split mode */ +}; + +extern const struct confparams icmarine_cfg_params[]; + +int icmarine_init(RIG *rig); +int icmarine_cleanup(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); +int icmarine_get_tx_freq(RIG *rig, vfo_t vfo, freq_t *freq); +int icmarine_set_split_vfo(RIG *rig, vfo_t rx_vfo, split_t split, vfo_t tx_vfo); +int icmarine_get_split_vfo(RIG *rig, vfo_t rx_vfo, split_t *split, vfo_t *tx_vfo); +int icmarine_set_mode(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width); +int icmarine_get_mode(RIG *rig, vfo_t vfo, rmode_t *mode, pbwidth_t *width); +int icmarine_set_split_freq(RIG *rig, vfo_t vfo, freq_t tx_freq); +int icmarine_get_split_freq(RIG *rig, vfo_t vfo, freq_t *tx_freq); +int icmarine_set_ptt(RIG *rig, vfo_t vfo, ptt_t ptt); +int icmarine_get_ptt(RIG *rig, vfo_t vfo, ptt_t *ptt); +int icmarine_get_dcd(RIG *rig, vfo_t vfo, dcd_t *dcd); +int icmarine_vfo_op(RIG *rig, vfo_t vfo, vfo_op_t op); +int icmarine_set_level(RIG *rig, vfo_t vfo, setting_t level, value_t val); +int icmarine_get_level(RIG *rig, vfo_t vfo, setting_t level, value_t *val); +int icmarine_set_func(RIG *rig, vfo_t vfo, setting_t func, int status); +int icmarine_get_func(RIG *rig, vfo_t vfo, setting_t func, int *status); +int icmarine_set_parm(RIG *rig, setting_t parm, value_t val); +int icmarine_get_parm(RIG *rig, setting_t parm, value_t *val); +int icmarine_set_conf(RIG *rig, token_t token, const char *val); +int icmarine_get_conf(RIG *rig, token_t token, char *val); + +extern const struct rig_caps icm700pro_caps; +extern const struct rig_caps icm802_caps; + +#endif /* _ICMARINE_H */ diff --git a/include/hamlib/riglist.h b/include/hamlib/riglist.h index c36894621..f69c3934d 100644 --- a/include/hamlib/riglist.h +++ b/include/hamlib/riglist.h @@ -1,7 +1,7 @@ /* * Hamlib Interface - list of known rigs * Copyright (c) 2000-2003 by Frank Singleton - * Copyright (c) 2000-2012 by Stephane Fillod + * Copyright (c) 2000-2015 by Stephane Fillod * * * This library is free software; you can redistribute it and/or @@ -514,6 +514,14 @@ #define RIG_BACKEND_ADAT "adat" #define RIG_MODEL_ADT_200A RIG_MAKE_MODEL(RIG_ADAT, 1) + /* + * ICOM Marine + */ +#define RIG_ICMARINE 30 +#define RIG_BACKEND_ICMARINE "icmarine" +#define RIG_MODEL_IC_M700PRO RIG_MAKE_MODEL(RIG_ICMARINE, 1) +#define RIG_MODEL_IC_M802 RIG_MAKE_MODEL(RIG_ICMARINE, 2) + /* * TODO: RIG_MODEL_KWZ30, KNEISNER +DOERING diff --git a/src/register.c b/src/register.c index 9d576622d..72103d1ec 100644 --- a/src/register.c +++ b/src/register.c @@ -1,6 +1,6 @@ /* * Hamlib Interface - provides registering for dynamically loadable backends. - * Copyright (c) 2000-2005 by Stephane Fillod + * Copyright (c) 2000-2015 by Stephane Fillod * * * This library is free software; you can redistribute it and/or @@ -67,6 +67,7 @@ DEFINE_INITRIG_BACKEND(dummy); DEFINE_INITRIG_BACKEND(yaesu); DEFINE_INITRIG_BACKEND(kenwood); DEFINE_INITRIG_BACKEND(icom); +DEFINE_INITRIG_BACKEND(icmarine); DEFINE_INITRIG_BACKEND(pcr); DEFINE_INITRIG_BACKEND(aor); DEFINE_INITRIG_BACKEND(jrc); @@ -111,6 +112,7 @@ static struct { { RIG_YAESU, RIG_BACKEND_YAESU, RIG_FUNCNAM(yaesu) }, { RIG_KENWOOD, RIG_BACKEND_KENWOOD, RIG_FUNCNAM(kenwood) }, { RIG_ICOM, RIG_BACKEND_ICOM, RIG_FUNCNAM(icom) }, + { RIG_ICMARINE, RIG_BACKEND_ICMARINE, RIG_FUNCNAMA(icmarine) }, { RIG_PCR, RIG_BACKEND_PCR, RIG_FUNCNAMA(pcr) }, { RIG_AOR, RIG_BACKEND_AOR, RIG_FUNCNAMA(aor) }, { RIG_JRC, RIG_BACKEND_JRC, RIG_FUNCNAMA(jrc) },