diff --git a/include/hamlib/rig.h b/include/hamlib/rig.h index edd0f4c90..bf3e20eed 100644 --- a/include/hamlib/rig.h +++ b/include/hamlib/rig.h @@ -1594,6 +1594,8 @@ struct rig_caps { int (*send_morse)(RIG *rig, vfo_t vfo, const char *msg); + int (*send_voice_mem)(RIG *rig, vfo_t vfo, int ch); + int (*set_bank)(RIG *rig, vfo_t vfo, int bank); int (*set_mem)(RIG *rig, vfo_t vfo, int ch); @@ -2206,6 +2208,11 @@ rig_send_morse HAMLIB_PARAMS((RIG *rig, vfo_t vfo, const char *msg)); +extern HAMLIB_EXPORT(int) +rig_send_voice_mem HAMLIB_PARAMS((RIG *rig, + vfo_t vfo, + int ch)); + extern HAMLIB_EXPORT(int) rig_set_bank HAMLIB_PARAMS((RIG *rig, vfo_t vfo, diff --git a/rigs/icom/ic7300.c b/rigs/icom/ic7300.c index 2afb2c6ea..e64f1d80a 100644 --- a/rigs/icom/ic7300.c +++ b/rigs/icom/ic7300.c @@ -418,7 +418,8 @@ const struct rig_caps ic7300_caps = .get_powerstat = icom_get_powerstat, .power2mW = icom_power2mW, .mW2power = icom_mW2power, - .send_morse = icom_send_morse + .send_morse = icom_send_morse, + .send_voice_mem = icom_send_voice_mem }; const struct rig_caps ic9700_caps = @@ -592,5 +593,6 @@ const struct rig_caps ic9700_caps = .set_powerstat = icom_set_powerstat, .power2mW = icom_power2mW, .mW2power = icom_mW2power, - .send_morse = icom_send_morse + .send_morse = icom_send_morse, + .send_voice_mem = icom_send_voice_mem }; diff --git a/rigs/icom/icom.c b/rigs/icom/icom.c index cf3fc1835..0ef883e7c 100644 --- a/rigs/icom/icom.c +++ b/rigs/icom/icom.c @@ -5865,6 +5865,38 @@ int icom_get_level_raw(RIG *rig, setting_t level, int cmd, int subcmd, return RIG_OK; } +/* + * icom_send_voice_mem + * Assumes rig!=NULL, rig->state.priv!=NULL + */ +int icom_send_voice_mem(RIG *rig, vfo_t vfo, int ch) +{ + unsigned char chbuf[1]; + unsigned char ackbuf[MAXFRAMELEN]; + int ack_len = sizeof(ackbuf), retval; + + rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__); + + to_bcd_be(chbuf, ch, 2); + + retval = icom_transaction(rig, C_SND_VOICE, 0, chbuf, 1, + 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", __func__, + ackbuf[0], ack_len); + return -RIG_ERJCTED; + } + + return RIG_OK; +} + // Sets rig vfo && priv->curr_vfo to default VFOA, or current vfo, or the vfo requested static int set_vfo_curr(RIG *rig, vfo_t vfo, vfo_t curr_vfo) { diff --git a/rigs/icom/icom.h b/rigs/icom/icom.h index 5e1d39061..9da81f872 100644 --- a/rigs/icom/icom.h +++ b/rigs/icom/icom.h @@ -260,6 +260,7 @@ int icom_power2mW(RIG *rig, unsigned int *mwpower, float power, freq_t freq, int icom_mW2power(RIG *rig, float *power, unsigned int mwpower, freq_t freq, rmode_t mode); int icom_send_morse(RIG *rig, vfo_t vfo, const char *msg); +int icom_send_voice_mem(RIG *rig, vfo_t vfo, int bank); /* Exposed routines */ int icom_get_split_vfos(const RIG *rig, vfo_t *rx_vfo, vfo_t *tx_vfo); int icom_set_raw(RIG *rig, int cmd, int subcmd, int subcmdbuflen, diff --git a/rigs/icom/icom_defs.h b/rigs/icom/icom_defs.h index 904f86670..4a9f107bb 100644 --- a/rigs/icom/icom_defs.h +++ b/rigs/icom/icom_defs.h @@ -96,8 +96,9 @@ #define C_CTL_DIG 0x20 /* Digital modes settings & status */ #define C_CTL_RIT 0x21 /* RIT/XIT control */ #define C_CTL_DSD 0x22 /* D-STAR Data */ -#define C_SEND_SEL_FREQ 0x25 /* Send/Recv sel/unsel VFO frequency */ +#define C_SEND_SEL_FREQ 0x25 /* Send/Recv sel/unsel VFO frequency */ #define C_CTL_SCP 0x27 /* Scope control & data */ +#define C_SND_VOICE 0x28 /* Transmit Voice Memory Contents */ #define C_CTL_MTEXT 0x70 /* Microtelecom Extension */ #define C_CTL_MISC 0x7f /* Miscellaneous control, Sc */ diff --git a/src/rig.c b/src/rig.c index 1cd87a2db..8d1d5e725 100644 --- a/src/rig.c +++ b/src/rig.c @@ -4332,6 +4332,74 @@ int HAMLIB_API rig_send_morse(RIG *rig, vfo_t vfo, const char *msg) } +/** + * \brief send voice memory content + * \param rig The rig handle + * \param vfo The target VFO + * \param ch Voice memory number to be sent + * + * Sends voice memory content. + * + * \return RIG_OK if the operation has been sucessful, otherwise + * a negative value if an error occured (in which case, cause is + * set appropriately). + * + */ + +int HAMLIB_API rig_send_voice_mem(RIG *rig, vfo_t vfo, int ch) +{ + const struct rig_caps *caps; + int retcode, rc2; + vfo_t curr_vfo; + + rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__); + + if CHECK_RIG_ARG(rig) + { + return -RIG_EINVAL; + } + + caps = rig->caps; + + if (caps->send_voice_mem == NULL) + { + return -RIG_ENAVAIL; + } + + if ((caps->targetable_vfo & RIG_TARGETABLE_PURE) + || vfo == RIG_VFO_CURR + || vfo == rig->state.current_vfo) + { + return caps->send_voice_mem(rig, vfo, ch); + } + + if (!caps->set_vfo) + { + return -RIG_ENTARGET; + } + + curr_vfo = rig->state.current_vfo; + retcode = caps->set_vfo(rig, vfo); + + if (retcode != RIG_OK) + { + return retcode; + } + + retcode = caps->send_voice_mem(rig, vfo, ch); + /* try and revert even if we had an error above */ + rc2 = caps->set_vfo(rig, curr_vfo); + + if (RIG_OK == retcode) + { + /* return the first error code */ + retcode = rc2; + } + + return retcode; +} + + /** * \brief find the freq_range of freq/mode * \param range_list The range list to search from diff --git a/tests/dumpcaps.c b/tests/dumpcaps.c index 33798a9a1..c64b10006 100644 --- a/tests/dumpcaps.c +++ b/tests/dumpcaps.c @@ -687,6 +687,7 @@ int dumpcaps(RIG *rig, FILE *fout) fprintf(fout, "Can send DTMF:\t%c\n", caps->send_dtmf != NULL ? 'Y' : 'N'); fprintf(fout, "Can recv DTMF:\t%c\n", caps->recv_dtmf != NULL ? 'Y' : 'N'); fprintf(fout, "Can send Morse:\t%c\n", caps->send_morse != NULL ? 'Y' : 'N'); + fprintf(fout, "Can send Voice:\t%c\n", caps->send_voice_mem != NULL ? 'Y' : 'N'); fprintf(fout, "Can decode Events:\t%c\n", diff --git a/tests/rigctl_parse.c b/tests/rigctl_parse.c index e31d64139..815eb2afc 100644 --- a/tests/rigctl_parse.c +++ b/tests/rigctl_parse.c @@ -215,6 +215,7 @@ declare_proto_rig(set_ant); declare_proto_rig(get_ant); declare_proto_rig(reset); declare_proto_rig(send_morse); +declare_proto_rig(send_voice_mem); declare_proto_rig(send_cmd); declare_proto_rig(set_powerstat); declare_proto_rig(get_powerstat); @@ -296,6 +297,7 @@ static struct test_table test_list[] = { 'w', "send_cmd", ACTION(send_cmd), ARG_IN1 | ARG_IN_LINE | ARG_OUT2 | ARG_NOVFO, "Cmd", "Reply" }, { 'W', "send_cmd_rx", ACTION(send_cmd), ARG_IN | ARG_OUT2 | ARG_NOVFO, "Cmd", "Reply"}, { 'b', "send_morse", ACTION(send_morse), ARG_IN | ARG_IN_LINE, "Morse" }, + { 0x94, "send_voice_mem", ACTION(send_voice_mem), ARG_IN , "Voice Mem#" }, { 0x8b, "get_dcd", ACTION(get_dcd), ARG_OUT, "DCD" }, { '2', "power2mW", ACTION(power2mW), ARG_IN1 | ARG_IN2 | ARG_IN3 | ARG_OUT1 | ARG_NOVFO, "Power [0.0..1.0]", "Frequency", "Mode", "Power mW" }, { '4', "mW2power", ACTION(mW2power), ARG_IN1 | ARG_IN2 | ARG_IN3 | ARG_OUT1 | ARG_NOVFO, "Power mW", "Frequency", "Mode", "Power [0.0..1.0]" }, @@ -3993,6 +3995,14 @@ declare_proto_rig(send_morse) return rig_send_morse(rig, vfo, arg1); } +/* '8' */ +declare_proto_rig(send_voice_mem) +{ + int ch; + + CHKSCN1ARG(sscanf(arg1, "%d", &ch)); + return rig_send_voice_mem(rig, vfo, ch); +} declare_proto_rig(send_dtmf) {