From 426ceae8a7ce3dfdd1ef99dbdbe47b1ff2cf53c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Fillod=2C=20F8CFE?= Date: Mon, 19 May 2003 06:57:44 +0000 Subject: [PATCH] Patch from Michael Smith adding support for RIG_LEVEL_AF, as well as tape jack support, 5khz window support, and support for reading various status bits from the os456. git-svn-id: https://hamlib.svn.sourceforge.net/svnroot/hamlib/trunk@1474 7ae35d74-ebe9-4afe-98af-79ac388436b8 --- icom/Makefile.am | 2 +- icom/icom.h | 14 +-- icom/optoscan.c | 318 ++++++++++++++++++++++++++++++++++++++++++++++- icom/os456.c | 19 ++- icom/os535.c | 6 +- 5 files changed, 337 insertions(+), 22 deletions(-) diff --git a/icom/Makefile.am b/icom/Makefile.am index 8daae15ea..8f6664d4f 100644 --- a/icom/Makefile.am +++ b/icom/Makefile.am @@ -8,4 +8,4 @@ hamlib_icom_la_SOURCES = $(ICOMSRCLIST) icom.c frame.c optoscan.c hamlib_icom_la_LDFLAGS = -no-undefined -module -avoid-version hamlib_icom_la_LIBADD = $(top_builddir)/src/libhamlib.la -noinst_HEADERS = frame.h icom.h icom_defs.h +noinst_HEADERS = frame.h icom.h icom_defs.h optoscan.h diff --git a/icom/icom.h b/icom/icom.h index 05b0b7b69..712ad09fb 100644 --- a/icom/icom.h +++ b/icom/icom.h @@ -2,7 +2,7 @@ * Hamlib CI-V backend - main header * Copyright (c) 2000-2003 by Stephane Fillod * - * $Id: icom.h,v 1.56 2003-04-16 22:30:40 fillods Exp $ + * $Id: icom.h,v 1.57 2003-05-19 06:57:44 fillods Exp $ * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as @@ -137,13 +137,6 @@ int icom_set_powerstat(RIG *rig, powerstat_t status); int icom_get_powerstat(RIG *rig, powerstat_t *status); int icom_decode_event(RIG *rig); -int optoscan_open(RIG *rig); -int optoscan_close(RIG *rig); -const char* optoscan_get_info(RIG *rig); -int optoscan_get_ctcss_tone(RIG *rig, vfo_t vfo, tone_t *tone); -int optoscan_get_dcs_code(RIG * rig, vfo_t vfo, tone_t *code); -int optoscan_recv_dtmf(RIG *rig, vfo_t vfo, char *digits, int *length); - extern const struct confparams icom_cfg_params[]; extern const struct rig_caps ic706_caps; @@ -166,11 +159,10 @@ extern const struct rig_caps icr8500_caps; extern const struct rig_caps ic275_caps; extern const struct rig_caps ic475_caps; +extern const struct rig_caps omnivip_caps; + extern const struct rig_caps os456_caps; extern const struct rig_caps os535_caps; -extern const struct rig_caps omnivip_caps; - - #endif /* _ICOM_H */ diff --git a/icom/optoscan.c b/icom/optoscan.c index f56f701e1..56a122c22 100644 --- a/icom/optoscan.c +++ b/icom/optoscan.c @@ -2,7 +2,7 @@ * Hamlib CI-V backend - OptoScan extensions * Copyright (c) 2000-2003 by Stephane Fillod * - * $Id: optoscan.c,v 1.5 2003-04-09 06:43:54 fillods Exp $ + * $Id: optoscan.c,v 1.6 2003-05-19 06:57:44 fillods Exp $ * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as @@ -38,8 +38,23 @@ #include "icom.h" #include "icom_defs.h" #include "frame.h" +#include "optoscan.h" +const struct confparams opto_ext_parms[] = { + { TOK_TAPECNTL, "tapecntl", "Toggle Tape Switch", "Toggles built in tape switch", 0, RIG_CONF_CHECKBUTTON, {} }, + { TOK_5KHZWIN, "5khzwin", "Toggle 5kHz Search Window", "Toggles 5kHz search window", 0, RIG_CONF_CHECKBUTTON, {} }, + { TOK_SPEAKER, "speaker", "Toggle speaker audio", "Toggles speaker audio", 0, RIG_CONF_CHECKBUTTON, {} }, + { TOK_AUDIO, "audio", "Audio present", "Audio present", NULL, RIG_CONF_CHECKBUTTON, {} }, + { TOK_DTMFPEND, "dtmfpend", "DTMF Digit Pending", "DTMF Digit Pending", NULL, RIG_CONF_CHECKBUTTON, {} }, + { TOK_DTMFOVRR, "dtmfovrr", "DTMF Buffer Overflow", "DTMF Buffer Overflow", NULL, RIG_CONF_CHECKBUTTON, {} }, + { TOK_CTCSSACT, "ctcssact", "CTCSS Tone Active", "CTCSS Tone Active", NULL, RIG_CONF_CHECKBUTTON, {} }, + { TOK_DCSACT, "dcsact", "DCS Code Active", "DCS Code Active", NULL, RIG_CONF_CHECKBUTTON, {} }, + { RIG_CONF_END, NULL, } +}; + +static int optoscan_get_status_block(RIG *rig, struct optostat *status_block); + /* * optoscan_open * Assumes rig!=NULL, rig->state.priv!=NULL @@ -242,3 +257,304 @@ int optoscan_recv_dtmf(RIG *rig, vfo_t vfo, char *digits, int *length) return RIG_OK; } + +/* + * Assumes rig!=NULL, rig->state.priv!=NULL + */ +int optoscan_set_ext_parm(RIG *rig, token_t token, value_t val) +{ + unsigned char epbuf[MAXFRAMELEN], ackbuf[MAXFRAMELEN]; + int ack_len, val_len; + int retval,subcode; + + memset(epbuf,0,MAXFRAMELEN); + memset(ackbuf,0,MAXFRAMELEN); + + val_len = 1; + + switch(token) { + case TOK_TAPECNTL: + if( val.i == 0 ) { + subcode = S_OPTO_TAPE_OFF; + } + else { + subcode = S_OPTO_TAPE_ON; + } + break; + case TOK_5KHZWIN: + if( val.i == 0 ) { + subcode = S_OPTO_5KSCOFF; + } + else { + subcode = S_OPTO_5KSCON; + } + break; + case TOK_SPEAKER: + if( val.i == 0 ) { + subcode = S_OPTO_SPKROFF; + } + else { + subcode = S_OPTO_SPKRON; + } + break; + default: + return -RIG_EINVAL; + } + + retval = icom_transaction (rig, C_CTL_MISC, subcode, epbuf, 0, + ackbuf, &ack_len); + if (retval != RIG_OK) + return retval; + + if (ack_len != 1 || ackbuf[0] != ACK) { + rig_debug(RIG_DEBUG_ERR, "%s: ack NG (%#.2x), " + "len=%d\n", __FUNCTION__, ackbuf[0], ack_len); + return -RIG_ERJCTED; + } + + return RIG_OK; +} + +/* + * Assumes rig!=NULL, rig->state.priv!=NULL + * and val points to a buffer big enough to hold the conf value. + */ +int optoscan_get_ext_parm(RIG *rig, token_t token, value_t *val) +{ + struct optostat status_block; + int retval; + + retval = optoscan_get_status_block(rig,&status_block); + + if (retval != RIG_OK) + return retval; + + switch(token) { + case TOK_TAPECNTL: + val->i = status_block.tape_enabled; + break; + case TOK_5KHZWIN: + val->i = status_block.fivekhz_enabled; + break; + case TOK_SPEAKER: + val->i = status_block.speaker_enabled; + break; + case TOK_AUDIO: + val->i = status_block.audio_present; + break; + case TOK_DTMFPEND: + val->i = status_block.DTMF_pending; + break; + case TOK_DTMFOVRR: + val->i = status_block.DTMF_overrun; + break; + case TOK_CTCSSACT: + val->i = status_block.CTCSS_active; + break; + case TOK_DCSACT: + val->i = status_block.DCS_active; + break; + default: + return -RIG_ENIMPL; + } + + return RIG_OK; +} + +/* + * optoscan_set_level + * Assumes rig!=NULL, rig->state.priv!=NULL + */ +int optoscan_set_level(RIG *rig, vfo_t vfo, setting_t level, value_t val) +{ + struct icom_priv_data *priv; + struct rig_state *rs; + unsigned char lvlbuf[MAXFRAMELEN], ackbuf[MAXFRAMELEN]; + int ack_len; + int lvl_cn, lvl_sc; /* Command Number, Subcommand */ + int icom_val; + int retval; + + rs = &rig->state; + priv = (struct icom_priv_data*)rs->priv; + + memset(lvlbuf,0,MAXFRAMELEN); + + /* + * So far, levels of float type are in [0.0..1.0] range + */ + if (RIG_LEVEL_IS_FLOAT(level)) + icom_val = val.f * 255; + else + icom_val = val.i; + + switch (level) { + case RIG_LEVEL_AF: + lvl_cn = C_CTL_MISC; + if( icom_val == 0 ) { + lvl_sc = S_OPTO_SPKROFF; + } + else { + lvl_sc = S_OPTO_SPKRON; + } + break; + default: + rig_debug(RIG_DEBUG_ERR,"Unsupported set_level %d", level); + return -RIG_EINVAL; + } + + retval = icom_transaction (rig, lvl_cn, lvl_sc, lvlbuf, 0, + ackbuf, &ack_len); + if (retval != RIG_OK) + return retval; + + if (ack_len != 1 || ackbuf[0] != ACK) { + rig_debug(RIG_DEBUG_ERR,"optoscan_set_level: ack NG (%#.2x), " + "len=%d\n", ackbuf[0], ack_len); + return -RIG_ERJCTED; + } + + return RIG_OK; +} + +/* + * optoscan_get_level + * Assumes rig!=NULL, rig->state.priv!=NULL, val!=NULL + */ +int optoscan_get_level(RIG *rig, vfo_t vfo, setting_t level, value_t *val) +{ + struct optostat status_block; + struct icom_priv_data *priv; + struct rig_state *rs; + unsigned char lvlbuf[MAXFRAMELEN]; + int lvl_len; + int lvl_cn, lvl_sc; /* Command Number, Subcommand */ + int icom_val; + int cmdhead; + int retval; + + rs = &rig->state; + priv = (struct icom_priv_data*)rs->priv; + + if( level != RIG_LEVEL_AF ) + { + switch (level) { + case RIG_LEVEL_STRENGTH: + lvl_cn = C_RD_SQSM; + lvl_sc = S_SML; + break; + case RIG_LEVEL_SQLSTAT: + lvl_cn = C_RD_SQSM; + lvl_sc = S_SQL; + break; + default: + rig_debug(RIG_DEBUG_ERR,"Unsupported get_level %d", level); + return -RIG_EINVAL; + } + + retval = icom_transaction (rig, lvl_cn, lvl_sc, NULL, 0, + lvlbuf, &lvl_len); + if (retval != RIG_OK) + return retval; + + /* + * strbuf should contain Cn,Sc,Data area + */ + cmdhead = (lvl_sc == -1) ? 1:2; + lvl_len -= cmdhead; + + if (lvlbuf[0] != ACK && lvlbuf[0] != lvl_cn) { + rig_debug(RIG_DEBUG_ERR,"optoscan_get_level: ack NG (%#.2x), " + "len=%d\n", lvlbuf[0],lvl_len); + return -RIG_ERJCTED; + } + + /* + * The result is a 3 digit BCD, but in *big endian* order: 0000..0255 + * (from_bcd is little endian) + */ + icom_val = from_bcd_be(lvlbuf+cmdhead, lvl_len*2); + } + else /* level == RIG_LEVEL_AF */ + { + retval = optoscan_get_status_block(rig,&status_block); + + if (retval != RIG_OK) + return retval; + + icom_val = 0; + if( status_block.speaker_enabled == 1 ) + icom_val = 255; + } + + switch (level) { + case RIG_LEVEL_STRENGTH: + val->i = rig_raw2val(icom_val, &priv->str_cal); + break; + case RIG_LEVEL_SQLSTAT: + /* + * 0x00=sql closed, 0x01=sql open + */ + val->i = icom_val; + break; + default: + if (RIG_LEVEL_IS_FLOAT(level)) + val->f = (float)icom_val/255; + else + val->i = icom_val; + } + + rig_debug(RIG_DEBUG_TRACE,"optoscan_get_level: %d %d %d %f\n", lvl_len, + icom_val, val->i, val->f); + + return RIG_OK; +} + + +/* + * Assumes rig!=NULL, status_block !=NULL + */ +static int optoscan_get_status_block(RIG *rig, struct optostat *status_block) +{ + int retval, ack_len; + unsigned char ackbuf[MAXFRAMELEN]; + + memset(status_block,0,sizeof(struct optostat)); + + retval = icom_transaction (rig, C_CTL_MISC, S_OPTO_RDSTAT, NULL, 0, + ackbuf, &ack_len); + + if (retval != RIG_OK) + return retval; + + if (ack_len != 4 ) { + rig_debug(RIG_DEBUG_ERR,"optoscan_get_status_block: ack NG (%#.2x), " + "len=%d\n", ackbuf[0], ack_len); + return -RIG_ERJCTED; + } + + if( ackbuf[2] & 1 ) status_block->remote_control = 1; + if( ackbuf[2] & 2 ) status_block->DTMF_pending = 1; + if( ackbuf[2] & 4 ) status_block->DTMF_overrun = 1; + if( ackbuf[2] & 16 ) status_block->squelch_open = 1; + if( ackbuf[2] & 32 ) status_block->CTCSS_active = 1; + if( ackbuf[2] & 64 ) status_block->DCS_active = 1; + + if( ackbuf[3] & 1 ) status_block->tape_enabled = 1; + if( ackbuf[3] & 2 ) status_block->speaker_enabled = 1; + if( ackbuf[3] & 4 ) status_block->fivekhz_enabled = 1; + if( ackbuf[3] & 16 ) status_block->audio_present = 1; + + rig_debug(RIG_DEBUG_VERBOSE,"remote_control = %d\n",status_block->remote_control); + rig_debug(RIG_DEBUG_VERBOSE,"DTMF_pending = %d\n",status_block->DTMF_pending); + rig_debug(RIG_DEBUG_VERBOSE,"DTMF_overrun = %d\n",status_block->DTMF_overrun); + rig_debug(RIG_DEBUG_VERBOSE,"squelch_open = %d\n",status_block->squelch_open); + rig_debug(RIG_DEBUG_VERBOSE,"CTCSS_active = %d\n",status_block->CTCSS_active); + rig_debug(RIG_DEBUG_VERBOSE,"DCS_active = %d\n",status_block->DCS_active); + rig_debug(RIG_DEBUG_VERBOSE,"tape_enabled = %d\n",status_block->tape_enabled ); + rig_debug(RIG_DEBUG_VERBOSE,"speaker_enabled = %d\n",status_block->speaker_enabled); + rig_debug(RIG_DEBUG_VERBOSE,"fivekhz_enabled = %d\n",status_block->fivekhz_enabled); + rig_debug(RIG_DEBUG_VERBOSE,"audio_present = %d\n",status_block->audio_present); + + return RIG_OK; +} diff --git a/icom/os456.c b/icom/os456.c index 63cf188f0..a36fe3392 100644 --- a/icom/os456.c +++ b/icom/os456.c @@ -2,7 +2,7 @@ * Hamlib CI-V backend - description of the OptoScan456 * Copyright (c) 2000-2003 by Stephane Fillod * - * $Id: os456.c,v 1.4 2003-04-26 09:54:49 fillods Exp $ + * $Id: os456.c,v 1.5 2003-05-19 06:57:44 fillods Exp $ * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as @@ -27,13 +27,14 @@ #include #include "icom.h" #include "tones.h" +#include "token.h" +#include "optoscan.h" +extern struct confparams opto_ext_parms[]; #define OS456_MODES (RIG_MODE_AM|RIG_MODE_FM|RIG_MODE_WFM) - #define OS456_VFO_ALL (RIG_VFO_A) - -#define OS456_LEVELS (RIG_LEVEL_SQLSTAT|RIG_LEVEL_STRENGTH) +#define OS456_LEVELS (RIG_LEVEL_SQLSTAT|RIG_LEVEL_STRENGTH|RIG_LEVEL_AF) /* * The signal strength data is in the form of two bytes, each consisting @@ -87,7 +88,7 @@ const struct rig_caps os456_caps = { .has_get_func = RIG_FUNC_NONE, .has_set_func = RIG_FUNC_NONE, .has_get_level = OS456_LEVELS, -.has_set_level = RIG_LEVEL_NONE, +.has_set_level = RIG_LEVEL_AF, .has_get_parm = RIG_PARM_NONE, .has_set_parm = RIG_PARM_NONE, .level_gran = {}, @@ -150,7 +151,6 @@ const struct rig_caps os456_caps = { .get_mode = icom_get_mode, .set_vfo = icom_set_vfo, -.get_level = icom_get_level, .get_dcd = icom_get_dcd, .decode_event = icom_decode_event, @@ -161,5 +161,12 @@ const struct rig_caps os456_caps = { .get_dcs_code = optoscan_get_dcs_code, .recv_dtmf = optoscan_recv_dtmf, +.extparms = opto_ext_parms, +.set_ext_parm = optoscan_set_ext_parm, +.get_ext_parm = optoscan_get_ext_parm, + +.set_level = optoscan_set_level, +.get_level = optoscan_get_level, + }; diff --git a/icom/os535.c b/icom/os535.c index 705b68666..11553f5a0 100644 --- a/icom/os535.c +++ b/icom/os535.c @@ -2,7 +2,7 @@ * Hamlib CI-V backend - description of the OptoScan535 * Copyright (c) 2000-2002 by Stephane Fillod * - * $Id: os535.c,v 1.4 2002-08-16 17:43:01 fillods Exp $ + * $Id: os535.c,v 1.5 2003-05-19 06:57:44 fillods Exp $ * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as @@ -27,12 +27,12 @@ #include #include "icom.h" #include "tones.h" +#include "optoscan.h" +extern struct confparams opto_ext_parms[]; #define OS535_MODES (RIG_MODE_AM|RIG_MODE_FM|RIG_MODE_WFM) - #define OS535_VFO_ALL (RIG_VFO_A) - #define OS535_LEVELS (RIG_LEVEL_STRENGTH) #define OS535_STR_CAL { 2, { \