From 9a9d9e5116fb08d3d175ecc758981a1c493845ee Mon Sep 17 00:00:00 2001 From: "Nate Bargmann, N0NB" Date: Sat, 17 Jan 2009 14:37:28 +0000 Subject: [PATCH] Improved buffer flush by shortening serial timeout from 5 to 1.5 seconds. Re-worked rotorez_rot_set_conf to use token values defined in rotorez.h but will need to wait until tokens are available in Hamlib for full use. Improved documentation in rotorez.txt of changes. git-svn-id: https://hamlib.svn.sourceforge.net/svnroot/hamlib/trunk@2588 7ae35d74-ebe9-4afe-98af-79ac388436b8 --- rotorez/rotorez.c | 153 +++++++++++++++++++++++++++++--------------- rotorez/rotorez.h | 15 ++++- rotorez/rotorez.txt | 47 +++++++++++++- 3 files changed, 160 insertions(+), 55 deletions(-) diff --git a/rotorez/rotorez.c b/rotorez/rotorez.c index c01e8ef92..0c8ebd856 100644 --- a/rotorez/rotorez.c +++ b/rotorez/rotorez.c @@ -11,8 +11,10 @@ * Rotor-EZ is a trademark of Idiom Press * Hy-Gain is a trademark of MFJ Enterprises * + * Tested on a HAM-IV with the Rotor-EZ V1.4S interface installed. * - * $Id: rotorez.c,v 1.11 2009-01-16 04:21:11 n0nb Exp $ + * + * $Id: rotorez.c,v 1.12 2009-01-17 14:37:28 n0nb Exp $ * * * This library is free software; you can redistribute it and/or @@ -39,6 +41,7 @@ #include /* Standard library definitions */ #include /* String function definitions */ #include /* UNIX standard function definitions */ +#include /* for isdigit function */ #include "hamlib/rotator.h" #include "serial.h" @@ -72,16 +75,17 @@ static int rotorez_flush_buffer(ROT *rot); /* - * Rotor-EZ enhanced rotor capabilities + * Idiom Press Rotor-EZ enhanced rotor capabilities for + * Hy-Gain CD45, Ham-II, Ham-III, Ham IV and all TailTwister rotors */ const struct rot_caps rotorez_rot_caps = { .rot_model = ROT_MODEL_ROTOREZ, .model_name = "Rotor-EZ", .mfg_name = "Idiom Press", - .version = "0.2", + .version = "0.5", .copyright = "LGPL", - .status = RIG_STATUS_UNTESTED, + .status = RIG_STATUS_BETA, .rot_type = ROT_TYPE_OTHER, .port_type = RIG_PORT_SERIAL, .serial_rate_min = 4800, @@ -92,8 +96,8 @@ const struct rot_caps rotorez_rot_caps = { .serial_handshake = RIG_HANDSHAKE_NONE, .write_delay = 0, .post_write_delay = 500, - .timeout = 5000, - .retry = 3, + .timeout = 1500, + .retry = 2, .min_az = 0, .max_az = 360, @@ -113,14 +117,15 @@ const struct rot_caps rotorez_rot_caps = { /* - * RotorCard enhanced rotor capabilities + * Idiom Press RotorCard enhanced rotor capabilities for + * Yaesu SDX and DXA series rotors */ const struct rot_caps rotorcard_rot_caps = { .rot_model = ROT_MODEL_ROTORCARD, .model_name = "RotorCard", .mfg_name = "Idiom Press", - .version = "0.2", + .version = "0.5", .copyright = "LGPL", .status = RIG_STATUS_UNTESTED, .rot_type = ROT_TYPE_OTHER, @@ -133,8 +138,8 @@ const struct rot_caps rotorcard_rot_caps = { .serial_handshake = RIG_HANDSHAKE_NONE, .write_delay = 0, .post_write_delay = 500, - .timeout = 5000, - .retry = 3, + .timeout = 1500, + .retry = 2, .min_az = 0, .max_az = 360, @@ -161,7 +166,7 @@ const struct rot_caps dcu_rot_caps = { .rot_model = ROT_MODEL_DCU, .model_name = "DCU-1/DCU-1X", .mfg_name = "Hy-Gain", - .version = "0.2", + .version = "0.5", .copyright = "LGPL", .status = RIG_STATUS_UNTESTED, .rot_type = ROT_TYPE_OTHER, @@ -174,8 +179,8 @@ const struct rot_caps dcu_rot_caps = { .serial_handshake = RIG_HANDSHAKE_NONE, .write_delay = 0, .post_write_delay = 500, - .timeout = 5000, - .retry = 3, + .timeout = 1500, + .retry = 2, .min_az = 0, .max_az = 360, @@ -288,7 +293,7 @@ static int rotorez_rot_set_position(ROT *rot, azimuth_t azimuth, elevation_t ele static int rotorez_rot_get_position(ROT *rot, azimuth_t *azimuth, elevation_t *elevation) { struct rot_state *rs; char cmdstr[5] = "AI1;"; - char az[5]; /* read azimuth string */ + char az[5]; /* read azimuth string */ char *p; azimuth_t tmp = 0; int err; @@ -298,26 +303,37 @@ static int rotorez_rot_get_position(ROT *rot, azimuth_t *azimuth, elevation_t *e if (!rot) return -RIG_EINVAL; -get_az: - err = rotorez_send_priv_cmd(rot, cmdstr); - if (err != RIG_OK) - return err; + do { + err = rotorez_send_priv_cmd(rot, cmdstr); + if (err != RIG_OK) + return err; - rs = &rot->state; + rs = &rot->state; - err = read_block(&rs->rotport, az, AZ_READ_LEN); - if (err != AZ_READ_LEN) - return -RIG_ETRUNC; + err = read_block(&rs->rotport, az, AZ_READ_LEN); + if (err != AZ_READ_LEN) + return -RIG_ETRUNC; - /* The azimuth string should be ';xxx' beginning at offset 0. If the - * ';' is not there, it's likely the RotorEZ has received an invalid - * command and the buffer needs to be flushed. See rotorez_flush_buffer() - * definition below for a complete description. - */ - if (az[0] != ';') { - rotorez_flush_buffer(rot); - goto get_az; - } + /* The azimuth string should be ';xxx' beginning at offset 0. If the + * ';' is not there, it's likely the RotorEZ has received an invalid + * command and the buffer needs to be flushed. See rotorez_flush_buffer() + * definition below for a complete description. + */ + if (az[0] != ';') { + err = rotorez_flush_buffer(rot); + if (err == -RIG_EIO) + return err; + else + err = -RIG_EINVAL; + } else if (err == AZ_READ_LEN && az[0] == ';') { + /* Check if remaining chars are digits if az[0] == ';' */ + for (p = az + 1;p < az + 4; p++) + if (isdigit(*p)) + continue; + else + err = -RIG_EINVAL; + } + } while (err == -RIG_EINVAL); /* * Rotor-EZ returns a four octet string consisting of a ';' followed @@ -330,7 +346,9 @@ get_az: rig_debug(RIG_DEBUG_TRACE, "%s: \"%s\" after conversion = %.1f\n", __func__, p, tmp); - if (tmp < 0 || tmp > 359) + if (tmp == 360) + tmp = 0; + else if (tmp < 0 || tmp > 359) return -RIG_EINVAL; *azimuth = tmp; @@ -367,36 +385,65 @@ static int rotorez_rot_stop(ROT *rot) { /* * Send configuration character * - * token is ignored * Rotor-EZ interface will act on these commands immediately -- - * no other command or command terminator is needed + * no other command or command terminator is needed. Expects token + * define in rotorez.h and *val of '1' or '0' (enable/disable). */ static int rotorez_rot_set_conf(ROT *rot, token_t token, const char *val) { - int err; + char cmdstr[2]; + char c; + int err; - rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__); + rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__); + rig_debug(RIG_DEBUG_TRACE, "%s: token = %d, *val = %c\n", + __func__, token, *val); - if (!rot) - return -RIG_EINVAL; + if (!rot) + return -RIG_EINVAL; - switch(*val) { - case 'E': /* Enable endpoint option */ - case 'e': /* Disable endpoint option */ - case 'J': /* Enable jam protection */ - case 'j': /* Disable jam protection -- not recommended */ - case 'O': /* Enable overshoot option */ - case 'o': /* Disable overshoot option */ - case 'S': /* Enable unstick option */ - case 's': /* Disable unstick option */ - err = rotorez_send_priv_cmd(rot, val); + if (*val < '0' || *val > '1') + return -RIG_EINVAL; + + switch(token) { + case ENDPT: /* Endpoint option */ + if (*val == '1') + c = 'E'; + else + c = 'e'; + break; + case JAM: /* Jam protection */ + if (*val == '1') + c = 'J'; + else + c = 'j'; + break; + case OVRSHT: /* Overshoot option */ + if (*val == '1') + c = 'O'; + else + c = 'o'; + break; + case UNSTICK: /* Unstick option */ + if (*val == '1') + c = 'S'; + else + c = 's'; + break; + default: + return -RIG_EINVAL; + } + rig_debug(RIG_DEBUG_TRACE, "%s: c = %c, *val = %c\n", __func__, c, *val); + snprintf(cmdstr, sizeof(cmdstr), "%c", c); + + rig_debug(RIG_DEBUG_TRACE, "%s: cmdstr = %s, *val = %c\n", + __func__, cmdstr, *val); + + err = rotorez_send_priv_cmd(rot, cmdstr); if (err != RIG_OK) - return err; - + return err; + return RIG_OK; - default: - return -RIG_EINVAL; - } } diff --git a/rotorez/rotorez.h b/rotorez/rotorez.h index 90021966f..56841a1c9 100644 --- a/rotorez/rotorez.h +++ b/rotorez/rotorez.h @@ -9,7 +9,7 @@ * supports the Hy-Gain DCU-1. * * - * $Id: rotorez.h,v 1.5 2003-04-16 22:30:41 fillods Exp $ + * $Id: rotorez.h,v 1.6 2009-01-17 14:37:28 n0nb Exp $ * * * This library is free software; you can redistribute it and/or @@ -37,6 +37,19 @@ extern const struct rot_caps rotorez_rot_caps; extern const struct rot_caps rotorcard_rot_caps; extern const struct rot_caps dcu_rot_caps; +/* + * Tokens used by rotorez_rot_set_conf and the 'C' command in rotctl + * and rotctld followed by a value of '0' to disable a Rotor-EZ option + * and '1' to enable it. + */ +enum { + NONE = 0, + ENDPT, + JAM, + OVRSHT, + UNSTICK +}; + /* * API local implementation * diff --git a/rotorez/rotorez.txt b/rotorez/rotorez.txt index 0b2c3312d..bf98df803 100644 --- a/rotorez/rotorez.txt +++ b/rotorez/rotorez.txt @@ -1,3 +1,48 @@ +Further testing has revealed that the RotorEZ interface will place +undocumented characters into the serial buffer. Additions to the +rotorez backend now take this into account and test for a valid azimuth +reply and flush the buffer if necessary. + +When the unit is first powered on, it appears as though at least one +character is placed into the buffer. I have seen this as 0xE0 although +it is possible some other character could be placed there. + +If the RotorEZ should receive an invalid command, such as an the ';' +character while the rotor is not in motion, as sent by the rotorez_rot_stop +function ('S' command from `rotctl'), it will output the following +string, "C2000 IDIOM V1.4S " into the input buffer. A new function, +rotorez_flush_buffer, flushes the buffer by reading it until a timeout +occurs. Once the timeout occurs, this function returns and the buffer is +presumed to be empty. Should read_block return an IO error, it is passed +back to the application. + +Flushing the buffer is done by reading the buffer until the read_block +function times out. By necessity, this means that the delay could be up +to a few seconds before the rotorez_rot_get_position function returns a +valid azimuth. + +----- + +As of version 0.5 of the rotorez backend, the serial timeout has been +shortened to 1500 mS and the retry count reduced to 2 to speed up +recovery when flushing the buffer as described above. Also, four +tokens have been defined in rotorez.h for the set_conf function used by +`rotctl' and `rotctld'. They are: + + ENDPT, + JAM, + OVRSHT, + UNSTICK + +and have the integer values of 1-4 respectively. Until tokens are more +completely developed in the Hamlib frontend, passing the integers to +`rotcrl' and `rotctld' will be necessary. The 'value' given to +`rotclt' and `rotctld' is the character '0' or '1' to disable or +enable the function. For example, to disable Endpoint Protection give +the command 'C 1 0' and to enable it again use 'C 1 1'. + +======================================================================= + The following email describes the command set used by the Rotor-EZ interface for Hy-Gain rotors and the RotorCard interface for Yaesu rotors manufactured and sold by Idiom Press, http://www.idiompres.com @@ -6,7 +51,7 @@ The Hy-Gain DCU-1/DCU-1X Digital Control Unit supports a subset of these commands--AP1XXX; and AM1; The DCU-1/DCU-1X is manufactured and sold by Hy-Gain, http://www.hy-gain.com -$Id: rotorez.txt,v 1.2 2009-01-16 04:21:11 n0nb Exp $ +$Id: rotorez.txt,v 1.3 2009-01-17 14:37:28 n0nb Exp $ From: "sales@idiompress.com" To: "Nate Bargmann"