From 741fd469472ea74717853cd54ceeb8e78fc4358d Mon Sep 17 00:00:00 2001 From: Nate Bargmann Date: Mon, 8 Sep 2014 21:08:47 -0500 Subject: [PATCH] Initial crack at RT-21 rotor backend Even though the Green Heron RT-21 rotor controller is billed as being RotorEZ compatible, it returns its value as 'XXX;' instead of ';XXX'. As a new backend model is being written anyway, the backend query's the controller to return the real value which is 'XXX.Y;'. --- include/hamlib/rotlist.h | 7 +++ rotorez/rotorez.c | 112 +++++++++++++++++++++++++++++++++++++++ rotorez/rotorez.h | 2 + 3 files changed, 121 insertions(+) diff --git a/include/hamlib/rotlist.h b/include/hamlib/rotlist.h index 7e91c67dc..6744ecdad 100644 --- a/include/hamlib/rotlist.h +++ b/include/hamlib/rotlist.h @@ -122,12 +122,19 @@ * The Rotor-EZ backend can be used with rotators that support the * DCU command set by DF9GR (currently the ERC). */ +/*! \def ROT_MODEL_RT21 + * \brief A macro that returns the model number of the RT21 backend. + * + * The Rotor-EZ backend can be used with rotators that support the + * DCU command set by Green Heron (currently the RT-21). + */ #define ROT_ROTOREZ 4 #define ROT_BACKEND_ROTOREZ "rotorez" #define ROT_MODEL_ROTOREZ ROT_MAKE_MODEL(ROT_ROTOREZ, 1) #define ROT_MODEL_ROTORCARD ROT_MAKE_MODEL(ROT_ROTOREZ, 2) #define ROT_MODEL_DCU ROT_MAKE_MODEL(ROT_ROTOREZ, 3) #define ROT_MODEL_ERC ROT_MAKE_MODEL(ROT_ROTOREZ, 4) +#define ROT_MODEL_RT21 ROT_MAKE_MODEL(ROT_ROTOREZ, 5) /*! \def ROT_MODEL_SARTEK1 * \brief A macro that returns the model number of the SARtek-1 backend. diff --git a/rotorez/rotorez.c b/rotorez/rotorez.c index 5f68b3139..10489b5dc 100644 --- a/rotorez/rotorez.c +++ b/rotorez/rotorez.c @@ -60,6 +60,7 @@ static int rotorez_rot_cleanup(ROT *rot); static int rotorez_rot_set_position(ROT *rot, azimuth_t azimuth, elevation_t elevation); static int rotorez_rot_get_position(ROT *rot, azimuth_t *azimuth, elevation_t *elevation); static int erc_rot_get_position(ROT *rot, azimuth_t *azimuth, elevation_t *elevation); +static int rt21_rot_get_position(ROT *rot, azimuth_t *azimuth, elevation_t *elevation); static int rotorez_rot_reset(ROT *rot, rot_reset_t reset); static int rotorez_rot_stop(ROT *rot); @@ -287,6 +288,45 @@ const struct rot_caps erc_rot_caps = { }; +const struct rot_caps rt21_rot_caps = { + .rot_model = ROT_MODEL_RT21, + .model_name = "RT-21", + .mfg_name = "Green Heron", + .version = "2014-09-08", + .copyright = "LGPL", + .status = RIG_STATUS_ALPHA, + .rot_type = ROT_TYPE_OTHER, + .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 = 500, + .timeout = 1500, + .retry = 2, + + .min_az = 0, + .max_az = 360, + .min_el = 0, + .max_el = 0, + + .priv = NULL, /* priv */ +// .cfgparams = rotorez_cfg_params, + + .rot_init = rotorez_rot_init, + .rot_cleanup = rotorez_rot_cleanup, + .set_position = rotorez_rot_set_position, + .get_position = rt21_rot_get_position, +// .stop = rotorez_rot_stop, +// .set_conf = rotorez_rot_set_conf, +// .get_info = rotorez_rot_get_info, + +}; + + /* ************************************ * * API functions @@ -541,6 +581,77 @@ static int erc_rot_get_position(ROT *rot, azimuth_t *azimuth, elevation_t *eleva } +/* + * Get position from Green Heron RT-21 series of controllers + * Returns current azimuth position in degrees and tenths. + * Range returned from RT-21 is a float, 0.0 to 359.9 degrees + * Elevation is set to 0 + */ + +static int rt21_rot_get_position(ROT *rot, azimuth_t *azimuth, elevation_t *elevation) { + struct rot_state *rs; + char cmdstr[5] = "BI1;"; + char az[7]; /* read azimuth string */ + char *p = NULL; + azimuth_t tmp = 0; + int err; + + rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__); + + if (!rot) + return -RIG_EINVAL; + + do { + err = rotorez_send_priv_cmd(rot, cmdstr); + if (err != RIG_OK) + return err; + + rs = &rot->state; + + err = read_block(&rs->rotport, az, RT21_AZ_LEN); + if (err != RT21_AZ_LEN) + return -RIG_ETRUNC; + + /* The azimuth string should be 'xxx.y;' beginning at offset 0. If the + * first character is not a digit, it's likely something needs + * debugging. + */ + if (err == RT21_AZ_LEN && isdigit(az[0])) { + continue; + } else { + err = -RIG_EINVAL; + } + + } while (err == -RIG_EINVAL); + + /* + * RT-21 returns a six octet string consisting of by three octets + * containing the rotor's position in degrees, one octet containing a + * decimal '.', one octet containing the rotor's position in tenths of a + * degree, and one octet with the terminating ';'--'XXX.Y;'. The + * semi-colon is ignored when passing the string to atof(). + */ + az[5] = 0x00; /* NULL terminated string, truncating ';' */ + p = az; + tmp = (azimuth_t)atof(p); + rig_debug(RIG_DEBUG_TRACE, "%s: \"%s\" after conversion = %.1f\n", + __func__, p, tmp); + + if (tmp == 360.0) + tmp = 0; + else if (tmp < 0.0 || tmp > 359.9) + return -RIG_EINVAL; + + *azimuth = tmp; + *elevation = 0.0; /* RT-21 backend does not support el at this time. */ + rig_debug(RIG_DEBUG_TRACE, + "%s: azimuth = %.1f deg; elevation = %.1f deg\n", + __func__, *azimuth, *elevation); + + return RIG_OK; +} + + /* * Stop rotation on RotorEZ, reset on DCU-1 * @@ -743,6 +854,7 @@ DECLARE_INITROT_BACKEND(rotorez) rot_register(&rotorcard_rot_caps); rot_register(&dcu_rot_caps); rot_register(&erc_rot_caps); + rot_register(&rt21_rot_caps); return RIG_OK; } diff --git a/rotorez/rotorez.h b/rotorez/rotorez.h index 9d33e7fa3..d1d42b8ac 100644 --- a/rotorez/rotorez.h +++ b/rotorez/rotorez.h @@ -31,11 +31,13 @@ #include "token.h" #define AZ_READ_LEN 4 +#define RT21_AZ_LEN 6 extern const struct rot_caps rotorez_rot_caps; extern const struct rot_caps rotorcard_rot_caps; extern const struct rot_caps dcu_rot_caps; extern const struct rot_caps erc_rot_caps; +extern const struct rot_caps rt21_rot_caps; /* * Tokens used by rotorez_rot_set_conf and the 'C' command in rotctl