diff --git a/AUTHORS b/AUTHORS index 63d37f66b..f6b813f37 100644 --- a/AUTHORS +++ b/AUTHORS @@ -184,6 +184,9 @@ C: Francois Retief [fodtrack] M: Luc Langehegermann, LX2GT +[heathkit:HD 1780 Intellirotor] +M: Rob Frohne, KL7NA + [rotorez] M: Nate Bargmann, N0NB diff --git a/Makefile.am b/Makefile.am index 0434b408d..0698f38ee 100644 --- a/Makefile.am +++ b/Makefile.am @@ -18,7 +18,7 @@ DIST_SUBDIRS = macros include lib libltdl src c++ bindings tests doc \ icom kenwood aor yaesu dummy pcr alinco uniden tentec kachina jrc \ rpcrig winradio easycomm fodtrack rpcrot gnuradio drake rotorez \ flexradio sartek lowe rft tapr kit skanti wj racal tuner \ - gs232a + gs232a heathkit rpm: Makefile make dist diff --git a/bindings/ignore.swg b/bindings/ignore.swg index da62b7218..88e89a949 100644 --- a/bindings/ignore.swg +++ b/bindings/ignore.swg @@ -77,6 +77,8 @@ %ignore ROT_BACKEND_GS232A; %ignore ROT_KIT; %ignore ROT_BACKEND_KIT; +%ignore ROT_HEATHKIT; +%ignore ROT_BACKEND_HEATHKIT; %ignore PRIfreq; %ignore SCNfreq; diff --git a/configure.ac b/configure.ac index abe71e57c..867270dd6 100644 --- a/configure.ac +++ b/configure.ac @@ -235,7 +235,7 @@ AC_SUBST(RIGMATRIX) BACKEND_LIST="icom kenwood aor yaesu dummy pcr alinco uniden tentec kachina jrc drake lowe rft kit skanti tapr flexradio wj racal tuner" -ROT_BACKEND_LIST="dummy easycomm fodtrack gs232a kit rotorez sartek" +ROT_BACKEND_LIST="dummy easycomm fodtrack gs232a heathkit kit rotorez sartek" BINDINGS="" BINDING_ALL="" BINDING_CHECK="" @@ -524,6 +524,7 @@ gnuradio/Makefile easycomm/Makefile fodtrack/Makefile gs232a/Makefile +heathkit/Makefile sartek/Makefile rpcrig/Makefile rpcrot/Makefile diff --git a/heathkit/Makefile.am b/heathkit/Makefile.am new file mode 100644 index 000000000..ede6e3d2b --- /dev/null +++ b/heathkit/Makefile.am @@ -0,0 +1,7 @@ + +lib_LTLIBRARIES = hamlib-heathkit.la +hamlib_heathkit_la_SOURCES = hd1780.c +hamlib_heathkit_la_LDFLAGS = -no-undefined -module -avoid-version +hamlib_heathkit_la_LIBADD = $(top_builddir)/src/libhamlib.la + +noinst_HEADERS = hd1780.h diff --git a/heathkit/hd1780.c b/heathkit/hd1780.c new file mode 100644 index 000000000..562c91fde --- /dev/null +++ b/heathkit/hd1780.c @@ -0,0 +1,295 @@ +/* + * Hamlib backend library for the HD 1780 Intellirotor command set. + * + * hd1780.c - (C) Nate Bargmann 2003 (n0nb at arrl.net) + * (C) Rob Frohne 2008 (kl7na at arrl.net) + * + * This shared library provides an API for communicating + * via serial interface to a Heathkit HD 1780 Intellirotor. + * + * Heathkit is a trademark of Heath Company + * + * + * + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include /* Standard library definitions */ +#include /* String function definitions */ +#include /* UNIX standard function definitions */ + +#include "hamlib/rotator.h" +#include "serial.h" +#include "misc.h" +#include "register.h" + +#include "hd1780.h" + + +/* + * Private data structure + */ +struct hd1780_rot_priv_data { + azimuth_t az; +}; + +/* + * Private helper function prototypes + */ + +static int hd1780_send_priv_cmd(ROT *rot, const char *cmd); + + +/* + * HD 1780 Intellirotor rotor capabilities + */ + +const struct rot_caps hd1780_rot_caps = { + .rot_model = ROT_MODEL_HD1780, + .model_name = "HD 1780 Intellirotor", + .mfg_name = "Heathkit", + .version = "0.1", + .copyright = "LGPL", + .status = RIG_STATUS_BETA, + .rot_type = ROT_TYPE_OTHER, + .port_type = RIG_PORT_SERIAL, + .serial_rate_min = 300, + .serial_rate_max = 9600, + .serial_data_bits = 8, + .serial_stop_bits = 1, + .serial_parity = RIG_PARITY_NONE, + .serial_handshake = RIG_HANDSHAKE_NONE, + .write_delay = 10, + .post_write_delay = 500, + .timeout = 60000, + .retry = 0, + + .min_az = 0, + .max_az = 360, + .min_el = 0, + .max_el = 0, + + .priv = NULL, /* priv */ + + .rot_init = hd1780_rot_init, + .rot_cleanup = hd1780_rot_cleanup, + .set_position = hd1780_rot_set_position, + .get_position = hd1780_rot_get_position, +}; + + +/* ************************************ + * + * API functions + * + * ************************************ + */ + + +/* + * Initialize data structures + */ + +static int hd1780_rot_init(ROT *rot) { + struct hd1780_rot_priv_data *priv; + + rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__); + + if (!rot) + return -RIG_EINVAL; + + priv = (struct hd1780_rot_priv_data*) + malloc(sizeof(struct hd1780_rot_priv_data)); + + if (!priv) + return -RIG_ENOMEM; + rot->state.priv = (void*)priv; + + rot->state.rotport.type.rig = RIG_PORT_SERIAL; + + priv->az = 0; + + return RIG_OK; +} + +/* + * Clean up allocated memory structures + */ + +static int hd1780_rot_cleanup(ROT *rot) { + + rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__); + + if (!rot) + return -RIG_EINVAL; + + if (rot->state.priv) + free(rot->state.priv); + rot->state.priv = NULL; + + return RIG_OK; +} + + +/* + * Set position + * HD 1780 protocol supports azimuth only--elevation is ignored + * Range is converted to an integer string, 0 to 360 degrees + */ + +static int hd1780_rot_set_position(ROT *rot, azimuth_t azimuth, elevation_t elevation) { + struct rot_state *rs; + char cmdstr[8]; + char execstr[5] = "\r", ok[3]; + int err; + + rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__); + + if (!rot) + return -RIG_EINVAL; + + if (azimuth < 0 || azimuth > 360) + return -RIG_EINVAL; + + + sprintf(cmdstr, "%03.0f", azimuth); /* Target bearing */ + err = hd1780_send_priv_cmd(rot, cmdstr); + if (err != RIG_OK) + return err; + + err = hd1780_send_priv_cmd(rot, execstr); /* Execute command */ + if (err != RIG_OK) + return err; + +/* We need to look for the + to signify that everything finished. The HD 1780 + * sends a when it is finished rotating. + */ + rs = &rot->state; + err = read_block(&rs->rotport, ok, 2); + if (err != 2) + return -RIG_ETRUNC; + if ((ok[0] != '\r')||(ok[1] != '\n')) + return -RIG_ETRUNC; + + + return RIG_OK; +} + + +/* + * Get position + * Returns current azimuth position in whole degrees. + * Range returned from Rotor-EZ is an integer, 0 to 359 degrees + * Elevation is set to 0 + */ + +static int hd1780_rot_get_position(ROT *rot, azimuth_t *azimuth, elevation_t *elevation) { + struct rot_state *rs; + char cmdstr[3] = "b\r"; + char az[7]; /* read azimuth string */ + char *p; + azimuth_t tmp = 0; + int err; + + rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__); + + if (!rot) + return -RIG_EINVAL; + + err = hd1780_send_priv_cmd(rot, cmdstr); + if (err != RIG_OK) + return err; + + rs = &rot->state; + err = read_block(&rs->rotport, az, AZ_READ_LEN); + if (err != AZ_READ_LEN) + return -RIG_ETRUNC; + + /* + * HD 1780 returns a four octet string consisting of + * three octets containing the rotor's position in degrees followed by a + * space and a and a . The + * space is ignored when passing the string to atof(). + */ + az[4] = 0x00; /* NULL terminated string */ + p = az; /* for hd1780 */ + tmp = (azimuth_t)atof(p); + rig_debug(RIG_DEBUG_TRACE, "%s: \"%s\" after conversion = %.1f\n", + __func__, p, tmp); + + if (tmp < 0 || tmp > 359) + return -RIG_EINVAL; + + *azimuth = tmp; + *elevation = 0; /* assume aiming at the horizon */ + + rig_debug(RIG_DEBUG_TRACE, + "%s: azimuth = %.1f deg; elevation = %.1f deg\n", + __func__, *azimuth, *elevation); + + return RIG_OK; +} + + + +/* + * Send command string to rotor. + * + * To make sure that the rotor is ready to take a command, we send it a and + * it will normally reply with a ? . If you don't do this, using the + * w: command of rotctl it is possible to get it out of sequence. This kind of + * resets its command buffer before sending the command. + */ + +static int hd1780_send_priv_cmd(ROT *rot, const char *cmdstr) { + struct rot_state *rs; + int err; + + rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__); + + if (!rot) + return -RIG_EINVAL; + + rs = &rot->state; + + err = write_block(&rs->rotport, cmdstr, strlen(cmdstr)); + if (err != RIG_OK) + return err; + + return RIG_OK; +} + + +/* + * Initialize backend + */ + +DECLARE_INITROT_BACKEND(heathkit) +{ + rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__); + + rot_register(&hd1780_rot_caps); + + return RIG_OK; +} + + diff --git a/heathkit/hd1780.h b/heathkit/hd1780.h new file mode 100644 index 000000000..3df823735 --- /dev/null +++ b/heathkit/hd1780.h @@ -0,0 +1,51 @@ +/* + * Hamlib backend library for the Heathkit HD 1780 Intellirotor command set. + * + * hd1780.h - (C) Nate Bargmann 2003 (n0nb at arrl.net) + * (C) Rob Frohne 2008 (kl7na at arrl.net) + * + * This shared library provides an API for communicating + * via serial interface to a Heathkit Intellirotor HD 1780 + * + * + * + * + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef _ROT_HD1780_H +#define _ROT_HD1780_H 1 + +#define AZ_READ_LEN 6 + +extern const struct rot_caps hd1780_rot_caps; + +/* + * API local implementation + * + */ + +static int hd1780_rot_init(ROT *rot); +static int hd1780_rot_cleanup(ROT *rot); + +static int hd1780_rot_set_position(ROT *rot, azimuth_t azimuth, elevation_t elevation); +static int hd1780_rot_get_position(ROT *rot, azimuth_t *azimuth, elevation_t *elevation); + + + +#endif /* _ROT_HD1780_H */ + diff --git a/include/hamlib/rotlist.h b/include/hamlib/rotlist.h index eb5152efa..e89f8a289 100644 --- a/include/hamlib/rotlist.h +++ b/include/hamlib/rotlist.h @@ -1,9 +1,9 @@ /* * Hamlib Interface - list of known rotators - * Copyright (c) 2000-2008 by Stephane Fillod + * Copyright (c) 2000-2009 by Stephane Fillod * Copyright (c) 2000-2002 by Stephane Fillod and Frank Singleton * - * $Id: rotlist.h,v 1.14 2008-10-31 07:45:17 fillods Exp $ + * $Id: rotlist.h,v 1.15 2009-01-20 19:42: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 @@ -159,6 +159,13 @@ #define ROT_BACKEND_KIT "kit" #define ROT_MODEL_PCROTOR ROT_MAKE_MODEL(ROT_KIT, 1) +/*! \def ROT_MODEL_HD1780 + * \brief A macro that returns the model number of the HD 1780 backend. + */ +#define ROT_HEATHKIT 8 +#define ROT_BACKEND_HEATHKIT "heathkit" +#define ROT_MODEL_HD1780 ROT_MAKE_MODEL(ROT_HEATHKIT, 1) + /*! \typedef typedef int rot_model_t \brief Convenience type definition for rotator model. */ @@ -180,6 +187,7 @@ typedef int rot_model_t; { ROT_SARTEK, ROT_BACKEND_SARTEK }, \ { ROT_GS232A, ROT_BACKEND_GS232A }, \ { ROT_KIT, ROT_BACKEND_KIT }, \ + { ROT_HEATHKIT, ROT_BACKEND_HEATHKIT }, \ { 0, NULL }, /* end */ \ }