ether6: New rotor backend from Jonny, DG9OAA

I have now written a new rotor control based on an Atmel ethernet board
and used with me. It works well so far.

Signed-off-by: Nate Bargmann <n0nb@n0nb.us>
Hamlib-3.0
Jonny public 2013-07-12 16:24:02 +02:00 zatwierdzone przez Nate Bargmann
rodzic d992919d27
commit dd5a8f58b6
8 zmienionych plików z 408 dodań i 2 usunięć

Wyświetl plik

@ -23,7 +23,8 @@ DIST_SUBDIRS = libltdl macros include lib src c++ bindings tests doc \
icom kenwood aor yaesu dummy pcr alinco uniden tentec kachina jrc \ icom kenwood aor yaesu dummy pcr alinco uniden tentec kachina jrc \
winradio adat easycomm fodtrack drake rotorez \ winradio adat easycomm fodtrack drake rotorez \
flexradio sartek lowe rft rs tapr kit skanti prm80 wj racal tuner \ flexradio sartek lowe rft rs tapr kit skanti prm80 wj racal tuner \
gs232a heathkit spid ars m2 amsat scripts ts7400 celestron android gs232a heathkit spid ars m2 amsat scripts ts7400 celestron android \
ether6
# Install any third party macros into our tree for distribution # Install any third party macros into our tree for distribution
ACLOCAL_AMFLAGS = -I macros --install ACLOCAL_AMFLAGS = -I macros --install

Wyświetl plik

@ -47,7 +47,7 @@ m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
dnl New backends must be listed here! Also the new Makefile path must be dnl New backends must be listed here! Also the new Makefile path must be
dnl added to AC_CONFIG_FILES near the end of this file. See README.developer dnl added to AC_CONFIG_FILES near the end of this file. See README.developer
BACKEND_LIST="icom kenwood aor yaesu dummy pcr alinco uniden tentec kachina jrc drake lowe rft rs kit skanti prm80 tapr flexradio wj racal tuner adat" BACKEND_LIST="icom kenwood aor yaesu dummy pcr alinco uniden tentec kachina jrc drake lowe rft rs kit skanti prm80 tapr flexradio wj racal tuner adat"
ROT_BACKEND_LIST="dummy easycomm fodtrack gs232a heathkit kit rotorez sartek spid ars m2 amsat ts7400 celestron" ROT_BACKEND_LIST="dummy easycomm fodtrack gs232a heathkit kit rotorez sartek spid ars m2 amsat ts7400 celestron ether6"
dnl See README.release on setting these values dnl See README.release on setting these values
# Values given to -version-info when linking. See libtool documentation. # Values given to -version-info when linking. See libtool documentation.
@ -724,6 +724,7 @@ amsat/Makefile
adat/Makefile adat/Makefile
ts7400/Makefile ts7400/Makefile
celestron/Makefile celestron/Makefile
ether6/Makefile
scripts/Makefile scripts/Makefile
android/Makefile android/Makefile
hamlib.pc]) hamlib.pc])

Wyświetl plik

@ -0,0 +1,7 @@
pkglib_LTLIBRARIES = hamlib-ether6.la
hamlib_ether6_la_SOURCES = ether6.c ether6.h
hamlib_ether6_la_LDFLAGS = -no-undefined -module -avoid-version
hamlib_ether6_la_LIBADD = $(top_builddir)/src/libhamlib.la
EXTRA_DIST = README.ether6 ether6.txt

Wyświetl plik

@ -0,0 +1,34 @@
Quirks, known bugs, and other notes.
====================================
In this document I will try to describe the operation of the rotor Ethersex
interfaces. The project Ethersex (www.ethersex.de) provides a simple
linking against its own projects. The software runs on Atmel AVR
processors.
The rotor control I realized for the following AVR boards:
* etherrape http://www.lochraster.org/etherrape/
and
* AVR-NET-IO http://www.pollin.de/shop/dt/MTQ5OTgxOTk-/Bausaetze_Module/Bausaetze/Bausatz_AVR_NET_IO.html
The functioning of the etersex rotor control is easy. A voltage of 0 - 5 V
indicates the direction of rotation. One output for CW, CCW and, if
necessary, the brake control. When creating the software (Ethersex) can be
adjusted by a more detailed configuration menu. The controller supports only
a subset of the command set of rotor position.
* set position
* get position
* park
* stop
* move (turn cw or ccw)
A detailed description of the software can be found at Ethersex:
http://www.ethersex.de/index.php/Rotor_(Deutsch)
An example of the direct control via the command found in the File ether6.txt
Does anyone have any suggestions or comments send an e mail to dg9oaa@darc.de

297
ether6/ether6.c 100644
Wyświetl plik

@ -0,0 +1,297 @@
/*
* Hamlib Ether6 backend - main file
* Copyright (c) 2001-2009 by Stephane Fillod
* Copyright (c) 2013 by Jonny Röker <Jonny.Roeker@t-online.de>
*
*
* 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.1 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdlib.h>
#include <string.h> /* String function definitions */
#include <unistd.h> /* UNIX standard function definitions */
#include <math.h>
#include <sys/time.h>
#include <time.h>
#include <hamlib/rotator.h>
#include "serial.h"
#include "misc.h"
#include "register.h"
#include "ether6.h"
#define CMD_MAX 32
#define BUF_MAX 64
/*
* Helper function with protocol return code parsing
*/
static int ether_transaction(ROT *rot, char *cmd, int len, char *buf)
{
int ret;
ret = write_block(&rot->state.rotport, cmd, len);
rig_debug(RIG_DEBUG_VERBOSE, "function %s(1): ret=%d || send=%s\n",__FUNCTION__ , ret, cmd);
if (ret != RIG_OK)
return ret;
ret = read_string(&rot->state.rotport, buf, BUF_MAX, "\n", sizeof("\n"));
rig_debug(RIG_DEBUG_VERBOSE, "function %s(2): ret=%d || receive=%s\n",__FUNCTION__ , ret, buf);
if (ret < 0)
return ret;
if (!memcmp(buf, ROTORCTL_RET, strlen(ROTORCTL_RET))) {
rig_debug(RIG_DEBUG_VERBOSE, "function %s(2a): receive=%s\n",__FUNCTION__ , buf);
return RIG_OK;
}
if (!memcmp(buf, NETROTCTL_RET, strlen(NETROTCTL_RET))) {
int rv = atoi(buf+strlen(NETROTCTL_RET));
rig_debug(RIG_DEBUG_VERBOSE, "function %s(2): ret=%d || receive=%d\n",__FUNCTION__ , ret, rv);
return atoi(buf+strlen(NETROTCTL_RET));
}
return ret;
}
static int ether_rot_open(ROT *rot)
{
int ret, len;
int sval;
float min_az, max_az, min_el, max_el;
struct rot_state *rs = &rot->state;
char cmd[CMD_MAX];
char buf[BUF_MAX];
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __FUNCTION__);
/* elevation not need */
len = sprintf(cmd, "rotor state\n");
/*-180/180 0/90*/
ret = ether_transaction(rot, cmd, len, buf);
if (ret <= 0)
return (ret < 0) ? ret : -RIG_EPROTO;
sval = sscanf(buf, "%f/%f %f/%f", &min_az, &max_az, &min_el, &max_el);
rs->min_az = min_az;
rs->max_az = max_az;
rs->min_el = min_el;
rs->max_el = max_el;
rig_debug(RIG_DEBUG_VERBOSE, "ret(%d)%f/%f %f/%f\n", sval, rs->min_az, rs->max_az, rs->min_el, rs->max_el);
return RIG_OK;
}
static int ether_rot_close(ROT *rot)
{
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __FUNCTION__);
/* clean signoff, no read back */
write_block(&rot->state.rotport, "\n", 1);
return RIG_OK;
}
static int ether_rot_set_position(ROT *rot, azimuth_t az, elevation_t el)
{
int ret, len;
char cmd[CMD_MAX];
char buf[BUF_MAX];
rig_debug(RIG_DEBUG_VERBOSE,"%s called: %f %f\n", __FUNCTION__,
az, el);
len = sprintf(cmd, "rotor move %d %d\n", (int)az, (int)el);
ret = ether_transaction(rot, cmd, len, buf);
if (ret > 0)
return -RIG_EPROTO;
else
return ret;
}
static int ether_rot_get_position(ROT *rot, azimuth_t *az, elevation_t *el)
{
int ret, len, sval, speed, adv;
char cmd[CMD_MAX];
char buf[BUF_MAX];
char mv[BUF_MAX];
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __FUNCTION__);
len = sprintf(cmd, "rotor status\n");
ret = ether_transaction(rot, cmd, len, buf);
if (ret <= 0)
return (ret < 0) ? ret : -RIG_EPROTO;
// example "hold,az=87,el=0,v=8,ad0=346"
sval = sscanf(buf, "%4s az=%f el=%f v=%d ad0=%d", mv, az, el, &speed, &adv);
rig_debug(RIG_DEBUG_VERBOSE, "az=%f el=%f mv=%s ad(az)=%d\n", *az, *el, mv, adv);
if (sval == 5)
return RIG_OK;
else
return -RIG_EPROTO;
}
/**
* stop the rotor
*/
static int ether_rot_stop(ROT *rot)
{
int ret, len;
char cmd[CMD_MAX];
char buf[BUF_MAX];
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __FUNCTION__);
len = sprintf(cmd, "rotor stop\n");
ret = ether_transaction(rot, cmd, len, buf);
if (ret > 0)
return -RIG_EPROTO;
else
return ret;
}
/**
* park the rotor
*/
static int ether_rot_park(ROT *rot)
{
int ret, len;
char cmd[CMD_MAX];
char buf[BUF_MAX];
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __FUNCTION__);
len = sprintf(cmd, "rotor park\n");
ret = ether_transaction(rot, cmd, len, buf);
if (ret > 0)
return -RIG_EPROTO;
else
return ret;
}
static int ether_rot_reset(ROT *rot, rot_reset_t reset)
{
int ret, len;
char cmd[CMD_MAX];
char buf[BUF_MAX];
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __FUNCTION__);
// orig len = sprintf(cmd, "R %d\n", reset);
len = sprintf(cmd, "reset\n");
ret = ether_transaction(rot, cmd, len, buf);
if (ret > 0)
return -RIG_EPROTO;
else
return ret;
}
/**
* call rotor cw or rotor ccw
* if direction value 0 turn cw and if direction value 1 turn ccw
*/
static int ether_rot_move(ROT *rot, int direction, int speed)
{
int ret, len;
char cmd[CMD_MAX];
char buf[BUF_MAX];
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __FUNCTION__);
if (direction == 0)
len = sprintf(cmd, "rotor cw %d\n", speed);
else
len = sprintf(cmd, "rotor ccw %d\n", speed);
ret = ether_transaction(rot, cmd, len, buf);
if (ret > 0)
return -RIG_EPROTO;
else
return ret;
}
static const char *ether_rot_get_info(ROT *rot)
{
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
return "ip rotator via ethersex";
}
/*
* Dummy rotator capabilities.
*/
const struct rot_caps ether6_rot_caps = {
.rot_model = ROT_MODEL_ETHER6,
.model_name = "Ether6 (via ethernet)",
.mfg_name = "DG9OAA",
.version = "0.1",
.copyright = "LGPL",
.status = RIG_STATUS_BETA,
.rot_type = ROT_FLAG_AZIMUTH,
.port_type = RIG_PORT_NETWORK,
.timeout = 5000,
.retry = 3,
.min_az = 0.,
.max_az = 360,
.min_el = 0,
.max_el = 90,
.priv = NULL, /* priv */
/* .rot_init = ether_rot_init, */
/* .rot_cleanup = ether_rot_cleanup, */
.rot_open = ether_rot_open,
.rot_close = ether_rot_close,
.set_position = ether_rot_set_position,
.get_position = ether_rot_get_position,
.park = ether_rot_park,
.stop = ether_rot_stop,
.reset = ether_rot_reset,
.move = ether_rot_move,
.get_info = ether_rot_get_info,
};
DECLARE_INITROT_BACKEND(ether6)
{
rig_debug(RIG_DEBUG_VERBOSE, "ether6: _init called\n");
rot_register(&ether6_rot_caps);
return RIG_OK;
}

30
ether6/ether6.h 100644
Wyświetl plik

@ -0,0 +1,30 @@
/*
* Hamlib Ether6 backend - main header
* Copyright (c) 2001-2008 by Stephane Fillod
* Copyright (c) 2013 by Jonny Röker <Jonny.Roeker@t-online.de>
*
*
* 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.1 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifndef _ROT_ETHER6_H
#define _ROT_ETHER6_H 1
#define ROTORCTL_RET "OK"
extern const struct rot_caps ether6_rot_caps;
#endif /* _ROT_ETHER6_H */

26
ether6/ether6.txt 100644
Wyświetl plik

@ -0,0 +1,26 @@
jro@sunny:~ $ socat stdio tcp4:etherrape:2701
rotor status
cw az=-87 el=88 v=50 ad0=370
rotor cw
rotor ccw
rotor stop
rotor park
rotor state
-180/180 0/90
.... all commands
rotor move
rotor status
rotor state
rotor cw
rotor ccw
rotor stop
rotor park
rotor setparkpos
rotor calibrate
rotor get calibrate

Wyświetl plik

@ -261,6 +261,15 @@
#define ROT_BACKEND_CELESTRON "celestron" #define ROT_BACKEND_CELESTRON "celestron"
#define ROT_MODEL_NEXSTAR ROT_MAKE_MODEL(ROT_CELESTRON, 1) #define ROT_MODEL_NEXSTAR ROT_MAKE_MODEL(ROT_CELESTRON, 1)
/*! \def ROT_MODEL_ETHER6
* \brief A macro that returns the model number of the Ether6 backend.
*
* The Ether6 backend can be used with rotators that support the Ether6
* protocol and alike.
*/
#define ROT_ETHER6 15
#define ROT_BACKEND_ETHER6 "ether6"
#define ROT_MODEL_ETHER6 ROT_MAKE_MODEL(ROT_ETHER6, 1)
/*! \typedef typedef int rot_model_t /*! \typedef typedef int rot_model_t
\brief Convenience type definition for rotator model. \brief Convenience type definition for rotator model.
@ -290,6 +299,7 @@ typedef int rot_model_t;
{ ROT_AMSAT, ROT_BACKEND_AMSAT }, \ { ROT_AMSAT, ROT_BACKEND_AMSAT }, \
{ ROT_TS7400, ROT_BACKEND_TS7400 }, \ { ROT_TS7400, ROT_BACKEND_TS7400 }, \
{ ROT_CELESTRON, ROT_BACKEND_CELESTRON }, \ { ROT_CELESTRON, ROT_BACKEND_CELESTRON }, \
{ ROT_ETHER6, ROT_BACKEND_ETHER6 }, \
{ 0, NULL }, /* end */ \ { 0, NULL }, /* end */ \
} }