From 359e5fdfad94fe09fa3d2f8bf2e9675eb196edf4 Mon Sep 17 00:00:00 2001 From: "Nate Bargmann, N0NB" Date: Fri, 22 Sep 2006 18:27:18 +0000 Subject: [PATCH] 20060922: Update: Applied tentec2.c from Dave Freese, W1HKJ git-svn-id: https://hamlib.svn.sourceforge.net/svnroot/hamlib/trunk@2115 7ae35d74-ebe9-4afe-98af-79ac388436b8 --- tentec/tentec2.c | 357 ++++++++++++++++++++++++++--------------------- 1 file changed, 201 insertions(+), 156 deletions(-) diff --git a/tentec/tentec2.c b/tentec/tentec2.c index 9553ea2b7..ba3a71468 100644 --- a/tentec/tentec2.c +++ b/tentec/tentec2.c @@ -2,7 +2,7 @@ * Hamlib Tentec backend - Argonaut, Jupiter, RX-350 * Copyright (c) 2001-2004 by Stephane Fillod * - * $Id: tentec2.c,v 1.4 2004-05-17 21:09:44 fillods Exp $ + * $Id: tentec2.c,v 1.5 2006-09-22 18:27:18 n0nb 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 @@ -19,6 +19,38 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ +/* + * Module rewritten and tested by Dave Freese, W1HKJ + * Tested using the distributed test program "rigctl" to control an Argonaut V xcvr. + * Linked to digital modem program, "gmfsk" and bench tested and used on-air + * Linked to experimental digital modem program "fldigi", bench tested + * and used on-air. + * + * Note for anyone wishing to expand on the command set. + * Recommend using the + * + * tentec_transaction (rig, sendbuf, sendlen, rcvbuf, &rcv_len) + * + * function to send the command and receive the response. + * + * The Argo V always sends a response and ends the response with a "G\r" to + * indicate that the command was accepted. A rejected command is responded to by a + * two character sequence "Z\r". You should always expect a maximum response equal + * to the number of data bytes plus two. + * + * For example: + * A request for the present receiver filter bandwidth is the the string: + * "?W\r" which is 3 bytes in length + * The response from the Argonaut V will be: + * "Wn\rG\r" which is 5 bytes in length, where n is an unsigned char (byte) + * If the transceiver failed to receive the command correctly it will respond: + * "Z\r" ----> you need to check for that condition + * + * The tentec_transaction(...) function will always terminate the rcvbuf with a null + * character. The pointer to the receive buffer length MUST be initialized to the + * length of the max # chars for that command PLUS 1 for the terminator. + * For the above command, rcv_len should be 6. +*/ #ifdef HAVE_CONFIG_H #include "config.h" @@ -39,16 +71,12 @@ #include "tentec.h" #include "tentec2.h" -#define EOM "\015" /* CR */ - #define TT_AM '0' #define TT_USB '1' #define TT_LSB '2' #define TT_CW '3' #define TT_FM '4' - - /************************************************************************************* * * Specs from http://www.rfsquared.com @@ -66,41 +94,39 @@ */ int tentec2_set_freq(RIG *rig, vfo_t vfo, freq_t freq) { - struct rig_state *rs = &rig->state; - int freq_len, retval; - unsigned char freqbuf[16]; - int vfo_val; + int retval, ret_len; + char freqbuf[16] = "*Axxxx\r"; unsigned long f = (unsigned long)freq; - /* - * TODO: make use of rig_state.current_vfo - */ if (vfo == RIG_VFO_CURR) { - retval = tentec2_get_vfo(rig, &vfo); - if (retval != RIG_OK) + if ((retval = tentec2_get_vfo(rig, &vfo)) != RIG_OK) return retval; } switch(vfo) { - case RIG_VFO_A: vfo_val = 'A'; break; - case RIG_VFO_B: vfo_val = 'B'; break; + case RIG_VFO_A: break; + case RIG_VFO_B: freqbuf[1] = 'B'; break; default: rig_debug(RIG_DEBUG_ERR,"%s: unsupported VFO %s\n", __FUNCTION__, rig_strvfo(vfo)); return -RIG_EINVAL; } - freq_len = sprintf(freqbuf, "*%c%c%c%c%c" EOM, - vfo_val, - (int)(f >> 24) & 0xff, - (int)(f >> 16) & 0xff, - (int)(f >> 8) & 0xff, - (int)(f & 0xff)); - - retval = write_block(&rs->rigport, freqbuf, freq_len); - if (retval != RIG_OK) - return retval; + freqbuf[2] = (f >> 24) & 0xFF; + freqbuf[3] = (f >> 16) & 0xFF; + freqbuf[4] = (f >> 8) & 0xFF; + freqbuf[5] = f & 0xFF; +// Argo V will respond +// "G\r" or "Z\r" + ret_len = 3; + retval = tentec_transaction (rig, freqbuf, 7, freqbuf, &ret_len); - return RIG_OK; + if (retval != RIG_OK || ret_len != 2) + return -RIG_EINVAL; + + if (freqbuf[0] == 'G') + return RIG_OK; + + return -RIG_ERJCTED; } /* @@ -109,37 +135,42 @@ int tentec2_set_freq(RIG *rig, vfo_t vfo, freq_t freq) */ int tentec2_get_freq(RIG *rig, vfo_t vfo, freq_t *freq) { - int freq_len, retval; - unsigned char freqbuf[16]; - int vfo_val; + int retval, ret_len; + char freqbuf[16] = "?A\r"; - /* - * TODO: make use of rig_state.current_vfo - */ if (vfo == RIG_VFO_CURR) { - retval = tentec2_get_vfo(rig, &vfo); - if (retval != RIG_OK) + if ((retval = tentec2_get_vfo(rig, &vfo)) != RIG_OK) return retval; } switch(vfo) { - case RIG_VFO_A: vfo_val = 'A'; break; - case RIG_VFO_B: vfo_val = 'B'; break; + case RIG_VFO_A: break; + case RIG_VFO_B: freqbuf[1] = 'B'; break; default: rig_debug(RIG_DEBUG_ERR,"%s: unsupported VFO %s\n", __FUNCTION__, rig_strvfo(vfo)); return -RIG_EINVAL; } - freq_len = sprintf(freqbuf, "?%c" EOM, vfo_val); + +// Argo V will respond with 8 characters +// "Annnn\rG\r" or "Bnnnn\rG\r" +// or it will respond +// "Z\r" meaning the command was rejected + ret_len = 9; - retval = tentec_transaction (rig, freqbuf, freq_len, freqbuf, &freq_len); + retval = tentec_transaction (rig, freqbuf, strlen(freqbuf), freqbuf, &ret_len); if (retval != RIG_OK) return retval; - if (freq_len != 6) - return -RIG_EPROTO; - - *freq = (freqbuf[2] << 24) |(freqbuf[3] << 16) | (freqbuf[4] << 8) | freqbuf[5]; + if (ret_len == 2 && freqbuf[1] == 'Z') + return -RIG_ERJCTED; + if (ret_len < 6) + return -RIG_EINVAL; + + *freq = (unsigned int)((freqbuf[1] & 0x0FF) << 24) + + (unsigned int)((freqbuf[2] & 0x0FF) << 16) + + (unsigned int)((freqbuf[3] & 0x0FF) << 8) + + (unsigned int)(freqbuf[4] & 0x0FF); return RIG_OK; } @@ -150,14 +181,9 @@ int tentec2_get_freq(RIG *rig, vfo_t vfo, freq_t *freq) */ int tentec2_set_vfo(RIG *rig, vfo_t vfo) { - struct rig_state *rs = &rig->state; - int vfo_len, retval; - unsigned char vfobuf[16]; - int vfo_val; + int retval, ret_len; + char vfobuf[16] = "*EVA\r"; - /* - * TODO: make use of rig_state.current_vfo - */ if ((vfo & ~RIG_VFO_MEM) == RIG_VFO_NONE || vfo == RIG_VFO_VFO) { vfo_t cvfo; retval = tentec2_get_vfo(rig, &cvfo); @@ -166,24 +192,28 @@ int tentec2_set_vfo(RIG *rig, vfo_t vfo) vfo = (cvfo&(RIG_VFO_A|RIG_VFO_B)) | (vfo & RIG_VFO_MEM); } + if (vfo & RIG_VFO_MEM) vfobuf[2] = 'M'; + switch(vfo & ~RIG_VFO_MEM) { - case RIG_VFO_A: vfo_val = 'A'; break; - case RIG_VFO_B: vfo_val = 'B'; break; + case RIG_VFO_A: break; + case RIG_VFO_B: vfobuf[3] = 'B'; break; default: rig_debug(RIG_DEBUG_ERR,"%s: unsupported VFO %s\n", __FUNCTION__, rig_strvfo(vfo)); return -RIG_EINVAL; } - vfo_len = sprintf(vfobuf, "*E%c%c" EOM, - vfo_val, - vfo & RIG_VFO_MEM ? 'M' : 'V' - ); + + ret_len = 3; + + retval = tentec_transaction (rig, vfobuf, 5, vfobuf, &ret_len); - retval = write_block(&rs->rigport, vfobuf, vfo_len); if (retval != RIG_OK) return retval; + + if (vfobuf[0] == 'G') + return RIG_OK; - return RIG_OK; + return -RIG_ERJCTED; } /* @@ -192,18 +222,27 @@ int tentec2_set_vfo(RIG *rig, vfo_t vfo) */ int tentec2_get_vfo(RIG *rig, vfo_t *vfo) { - int vfo_len, retval; - unsigned char vfobuf[16]; - - retval = tentec_transaction (rig, "?E" EOM, 3, vfobuf, &vfo_len); + int ret_len, retval; + unsigned char vfobuf[16] = "?E\r"; + + ret_len = 7; + retval = tentec_transaction (rig, vfobuf, 3, vfobuf, &ret_len); if (retval != RIG_OK) return retval; - if (vfo_len != 4) +// ArgoV sends back 6 character string +// "EVA\rG\r" or "EVB\rG\r" +// or 2 character failure string +// "Z\r" + + if (ret_len == 2 && vfobuf[0] == 'Z') + return -RIG_ERJCTED; + + if (ret_len != 6) return -RIG_EPROTO; - *vfo = vfobuf[3] == 'A' ? RIG_VFO_A : RIG_VFO_B; - if (vfobuf[2] == 'M') + *vfo = vfobuf[2] == 'A' ? RIG_VFO_A : RIG_VFO_B; + if (vfobuf[1] == 'M') *vfo |= RIG_VFO_MEM; return RIG_OK; @@ -217,12 +256,24 @@ int tentec2_get_vfo(RIG *rig, vfo_t *vfo) */ int tentec2_set_split_vfo(RIG *rig, vfo_t vfo, split_t split, vfo_t tx_vfo) { - struct rig_state *rs = &rig->state; + int retval, ret_len; + char retbuf[10] = "*Ox\r"; - /* - * TODO: handle tx_vfo - */ - return write_block(&rs->rigport, split==RIG_SPLIT_ON? "*O\1"EOM:"*O\0"EOM, 4); + if (split == RIG_SPLIT_ON) + retbuf[1] = 1; + else + retbuf[1] = 0; + + ret_len = 3; + retval = tentec_transaction( rig, retbuf, 4, retbuf, &ret_len ); + + if (retval != RIG_OK) + return retval; + + if (ret_len == 2 && retbuf[0] == 'Z') + return -RIG_ERJCTED; + + return RIG_OK; } /* @@ -231,21 +282,28 @@ int tentec2_set_split_vfo(RIG *rig, vfo_t vfo, split_t split, vfo_t tx_vfo) */ int tentec2_get_split_vfo(RIG *rig, vfo_t vfo, split_t *split, vfo_t *tx_vfo) { - int split_len, retval; - unsigned char splitbuf[16]; + int ret_len, retval; + char splitbuf[16] = "?O\r"; /* * TODO: handle tx_vfo */ - retval = tentec_transaction (rig, "?O"EOM, 3, splitbuf, &split_len); + ret_len = 5; + retval = tentec_transaction (rig, splitbuf, 3, splitbuf, &ret_len); +// Argo V returns +// "On\rG\r" or +// "Z\r" + if (retval != RIG_OK) return retval; - if (split_len != 3) { - return -RIG_EPROTO; - } + if (ret_len == 2 && splitbuf[0] == 'Z') + return -RIG_ERJCTED; - *split = splitbuf[2] == '\0' ? RIG_SPLIT_OFF : RIG_SPLIT_ON; + if (ret_len != 4) + return -RIG_EPROTO; + + *split = splitbuf[1] == 0 ? RIG_SPLIT_OFF : RIG_SPLIT_ON; return RIG_OK; } @@ -258,10 +316,9 @@ int tentec2_get_split_vfo(RIG *rig, vfo_t vfo, split_t *split, vfo_t *tx_vfo) */ int tentec2_set_mode(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width) { - struct rig_state *rs = &rig->state; - unsigned char ttmode, ttmode_a, ttmode_b; - int mdbuf_len, ttfilter, retval; - unsigned char mdbuf[32]; + char ttmode, ttmode_a, ttmode_b; + int ttfilter, retval, ret_len; + unsigned char mdbuf[16]; switch (mode) { case RIG_MODE_USB: ttmode = TT_USB; break; @@ -275,6 +332,18 @@ int tentec2_set_mode(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width) return -RIG_EINVAL; } + ttmode_a = ttmode_b = ttmode; + + strcpy(mdbuf, "*M00\r" ); + ret_len = 3; + mdbuf[2] = ttmode_a; mdbuf[3] = ttmode_b; + retval = tentec_transaction (rig, mdbuf, 5, mdbuf, &ret_len); + + if (retval != RIG_OK) + return retval; + if (ret_len == 2 && mdbuf[1] == 'Z') + return -RIG_ERJCTED; + if (width == RIG_PASSBAND_NORMAL) width = rig_passband_normal(rig, mode); @@ -290,47 +359,16 @@ int tentec2_set_mode(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width) else ttfilter = (width / 100) + 6; - retval = tentec_transaction (rig, "?M"EOM, 3, mdbuf, &mdbuf_len); + strcpy (mdbuf, "*Wn\r"); + mdbuf[2] = ttfilter; + ret_len = 3; + retval = tentec_transaction (rig, mdbuf, 5, mdbuf, &ret_len); + if (retval != RIG_OK) return retval; - - if (mdbuf_len != 4) { - /* return -RIG_EPROTO; */ - } - ttmode_a = mdbuf[2]; - ttmode_b = mdbuf[3]; - - /* - * TODO: make use of rig_state.current_vfo - */ - if (vfo == RIG_VFO_CURR) { - retval = tentec2_get_vfo(rig, &vfo); - if (retval != RIG_OK) - return retval; - } + if (ret_len == 2 && mdbuf[0] == 'Z') + return -RIG_ERJCTED; - switch(vfo) { - case RIG_VFO_A: ttmode_a = ttmode; break; - case RIG_VFO_B: ttmode_b = ttmode; break; - default: - rig_debug(RIG_DEBUG_ERR,"%s: unsupported VFO %s\n", - __FUNCTION__, rig_strvfo(vfo)); - return -RIG_EINVAL; - } - - /* - * FIXME: the 'W' command is not VFO targetable - */ - mdbuf_len = sprintf(mdbuf, "*W%c" EOM "*M%c%c" EOM, - ttfilter, - ttmode_a, - ttmode_b - ); - retval = write_block(&rs->rigport, mdbuf, mdbuf_len); - if (retval != RIG_OK) { - return retval; - } - return RIG_OK; } @@ -342,54 +380,43 @@ int tentec2_set_mode(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width) */ int tentec2_get_mode(RIG *rig, vfo_t vfo, rmode_t *mode, pbwidth_t *width) { - unsigned char ttmode; - int mdbuf_len, ttfilter, retval; - unsigned char mdbuf[32]; + int ttfilter, retval, ret_len; + char mdbuf[16]; - /* - * TODO: make use of rig_state.current_vfo - */ if (vfo == RIG_VFO_CURR) { - retval = tentec2_get_vfo(rig, &vfo); - if (retval != RIG_OK) + if ((retval = tentec2_get_vfo(rig, &vfo)) != RIG_OK) return retval; } - retval = tentec_transaction (rig, "?M"EOM, 3, mdbuf, &mdbuf_len); +// response to "?M\r" command: +// "M00" -> AM, "M1" -> USB, "M2" -> LSB, "M3" -> CW, "M4" -> FM + ret_len = 7; + retval = tentec_transaction (rig, "?M\r", 3, mdbuf, &ret_len); if (retval != RIG_OK) return retval; - if (mdbuf_len != 4) { - /* return -RIG_EPROTO; */ - } - - switch(vfo) { - case RIG_VFO_A: ttmode = mdbuf[2]; break; - case RIG_VFO_B: ttmode = mdbuf[3]; break; - default: - rig_debug(RIG_DEBUG_ERR,"%s: unsupported VFO %s\n", - __FUNCTION__, rig_strvfo(vfo)); - return -RIG_EINVAL; - } - switch (ttmode) { + if (ret_len != 6) + return -RIG_EPROTO; + + switch (mdbuf[1]) { case TT_USB: *mode = RIG_MODE_USB; break; case TT_LSB: *mode = RIG_MODE_LSB; break; - case TT_CW: *mode = RIG_MODE_CW; break; - case TT_AM: *mode = RIG_MODE_AM; break; - case TT_FM: *mode = RIG_MODE_FM; break; + case TT_CW: *mode = RIG_MODE_CW; break; + case TT_AM: *mode = RIG_MODE_AM; break; + case TT_FM: *mode = RIG_MODE_FM; break; default: rig_debug(RIG_DEBUG_ERR, "%s: unsupported mode '%c'\n", - __FUNCTION__, ttmode); + __FUNCTION__, mdbuf[1]); return -RIG_EPROTO; } - retval = tentec_transaction (rig, "?W"EOM, 3, mdbuf, &mdbuf_len); + ret_len = 6; + retval = tentec_transaction (rig, "?W\r", 3, mdbuf, &ret_len); if (retval != RIG_OK) return retval; - if (mdbuf_len != 3) { - /* return -RIG_EPROTO; */ - } + if (ret_len != 5) + return -RIG_EPROTO; /* * Filter 0: 200 @@ -398,7 +425,10 @@ int tentec2_get_mode(RIG *rig, vfo_t vfo, rmode_t *mode, pbwidth_t *width) * .. * Filter 36: 3000 */ - ttfilter = mdbuf[2]; + ttfilter = mdbuf[1]; + if (ttfilter < 0 || ttfilter > 36) + return -RIG_EPROTO; + if (ttfilter < 16) *width = (ttfilter + 4) * 50; else @@ -414,9 +444,20 @@ int tentec2_get_mode(RIG *rig, vfo_t vfo, rmode_t *mode, pbwidth_t *width) */ int tentec2_set_ptt(RIG *rig, vfo_t vfo, ptt_t ptt) { - struct rig_state *rs = &rig->state; + int retval, ret_len; + char retbuf[10]; + + ret_len = 3; + retval = tentec_transaction ( rig, + ptt==RIG_PTT_ON? "#1\r" : "#0\r", 3, + retbuf, &ret_len); + if (retval != RIG_OK) + return retval; + if (ret_len == 2 && retbuf[0] == 'G') + return RIG_OK; + + return -RIG_ERJCTED; - return write_block(&rs->rigport, ptt==RIG_PTT_ON? "#1"EOM:"#0"EOM, 3); } @@ -428,7 +469,8 @@ int tentec2_reset(RIG *rig, reset_t reset) int retval, reset_len; char reset_buf[32]; - retval = tentec_transaction (rig, "*X" EOM, 3, reset_buf, &reset_len); + reset_len = 32; + retval = tentec_transaction (rig, "*X\r", 3, reset_buf, &reset_len); if (retval != RIG_OK) return retval; @@ -451,8 +493,8 @@ const char *tentec2_get_info(RIG *rig) /* * protocol version */ - firmware_len = 7; - retval = tentec_transaction (rig, "?V" EOM, 3, buf, &firmware_len); + firmware_len = 100; + retval = tentec_transaction (rig, "?V\r", 3, buf, &firmware_len); /* "VER 1010-516" */ if (retval != RIG_OK || firmware_len != 12) { @@ -460,7 +502,10 @@ const char *tentec2_get_info(RIG *rig) __FUNCTION__, firmware_len); return NULL; } - buf[firmware_len] = '\0'; + if (firmware_len < 100) + buf[firmware_len] = 0; + else + buf[0] = 0; return buf; }