kopia lustrzana https://github.com/Hamlib/Hamlib
Merge pull request #1164 from andz82/master
Added FLIR/DirectedPerception PTU rotor backendpull/1191/head
commit
d369b60f6d
|
@ -48,7 +48,7 @@ dnl Beware of duplication should a backend directory include both rig and
|
||||||
dnl rotor definitions, e.g. "dummy". Optional backends will not be listed
|
dnl rotor definitions, e.g. "dummy". Optional backends will not be listed
|
||||||
dnl here but will be added later, e.g. "winradio".
|
dnl here but will be added later, e.g. "winradio".
|
||||||
RIG_BACKEND_LIST="rigs/adat rigs/alinco rigs/aor rigs/barrett rigs/codan rigs/dorji rigs/drake rigs/dummy rigs/elad rigs/flexradio rigs/icom rigs/icmarine rigs/jrc rigs/kachina rigs/kenwood rigs/kit rigs/lowe rigs/pcr rigs/prm80 rigs/racal rigs/rft rigs/rs rigs/skanti rigs/tapr rigs/tentec rigs/tuner rigs/uniden rigs/winradio rigs/wj rigs/yaesu rigs/gomspace rigs/mds"
|
RIG_BACKEND_LIST="rigs/adat rigs/alinco rigs/aor rigs/barrett rigs/codan rigs/dorji rigs/drake rigs/dummy rigs/elad rigs/flexradio rigs/icom rigs/icmarine rigs/jrc rigs/kachina rigs/kenwood rigs/kit rigs/lowe rigs/pcr rigs/prm80 rigs/racal rigs/rft rigs/rs rigs/skanti rigs/tapr rigs/tentec rigs/tuner rigs/uniden rigs/winradio rigs/wj rigs/yaesu rigs/gomspace rigs/mds"
|
||||||
ROT_BACKEND_LIST="rotators/amsat rotators/ars rotators/celestron rotators/cnctrk rotators/grbltrk rotators/easycomm rotators/ether6 rotators/fodtrack rotators/gs232a rotators/heathkit rotators/m2 rotators/meade rotators/rotorez rotators/sartek rotators/spid rotators/ts7400 rotators/prosistel rotators/ioptron rotators/satel rotators/radant"
|
ROT_BACKEND_LIST="rotators/amsat rotators/ars rotators/celestron rotators/cnctrk rotators/grbltrk rotators/easycomm rotators/ether6 rotators/flir rotators/fodtrack rotators/gs232a rotators/heathkit rotators/m2 rotators/meade rotators/rotorez rotators/sartek rotators/spid rotators/ts7400 rotators/prosistel rotators/ioptron rotators/satel rotators/radant"
|
||||||
# Amplifiers are all in the amplifiers directory
|
# Amplifiers are all in the amplifiers directory
|
||||||
AMP_BACKEND_LIST="amplifiers/elecraft amplifiers/gemini"
|
AMP_BACKEND_LIST="amplifiers/elecraft amplifiers/gemini"
|
||||||
|
|
||||||
|
@ -834,6 +834,7 @@ rotators/cnctrk/Makefile
|
||||||
rotators/grbltrk/Makefile
|
rotators/grbltrk/Makefile
|
||||||
rotators/easycomm/Makefile
|
rotators/easycomm/Makefile
|
||||||
rotators/ether6/Makefile
|
rotators/ether6/Makefile
|
||||||
|
rotators/flir/Makefile
|
||||||
rotators/fodtrack/Makefile
|
rotators/fodtrack/Makefile
|
||||||
rotators/gs232a/Makefile
|
rotators/gs232a/Makefile
|
||||||
rotators/heathkit/Makefile
|
rotators/heathkit/Makefile
|
||||||
|
|
|
@ -650,6 +650,21 @@
|
||||||
#define ROT_MODEL_GRBLTRK_SER ROT_MAKE_MODEL(ROT_GRBLTRK, 1)
|
#define ROT_MODEL_GRBLTRK_SER ROT_MAKE_MODEL(ROT_GRBLTRK, 1)
|
||||||
#define ROT_MODEL_GRBLTRK_NET ROT_MAKE_MODEL(ROT_GRBLTRK, 2)
|
#define ROT_MODEL_GRBLTRK_NET ROT_MAKE_MODEL(ROT_GRBLTRK, 2)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief A macro that returns the model number of the FLIR backend.
|
||||||
|
*
|
||||||
|
* \def ROT_MODEL_FLIR
|
||||||
|
*
|
||||||
|
* The FLIR backend can be used with FLIR and DirectedPercepition
|
||||||
|
* rotators using the PTU protocol (e.g. PTU-D48). Currently only
|
||||||
|
* the serial interaface is supported and no ethernet.
|
||||||
|
*/
|
||||||
|
//! @cond Doxygen_Suppress
|
||||||
|
#define ROT_FLIR 25
|
||||||
|
#define ROT_BACKEND_FLIR "flir"
|
||||||
|
//! @endcond
|
||||||
|
#define ROT_MODEL_FLIR ROT_MAKE_MODEL(ROT_FLIR, 1)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Convenience type definition for a rotator model.
|
* \brief Convenience type definition for a rotator model.
|
||||||
*
|
*
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
LOCAL_PATH:= $(call my-dir)
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
|
LOCAL_SRC_FILES := flir.c
|
||||||
|
LOCAL_MODULE := flir
|
||||||
|
|
||||||
|
LOCAL_CFLAGS :=
|
||||||
|
LOCAL_C_INCLUDES := android include src
|
||||||
|
LOCAL_LDLIBS := -lhamlib -Lobj/local/$(TARGET_ARCH_ABI)
|
||||||
|
|
||||||
|
include $(BUILD_STATIC_LIBRARY)
|
|
@ -0,0 +1,6 @@
|
||||||
|
FLIRSRC = flir.c flir.h
|
||||||
|
|
||||||
|
noinst_LTLIBRARIES = libhamlib-flir.la
|
||||||
|
libhamlib_flir_la_SOURCES = $(FLIRSRC)
|
||||||
|
|
||||||
|
EXTRA_DIST = README.md Android.mk
|
|
@ -0,0 +1,75 @@
|
||||||
|
# FLIR/DirectedPerception PTU Rotor Module
|
||||||
|
|
||||||
|
This module interfaces FLIR and DirectedPerception
|
||||||
|
rotor using the PTU protocol via serial.
|
||||||
|
|
||||||
|
This includes:
|
||||||
|
|
||||||
|
* PTU-D48(E)
|
||||||
|
* PTU-E46
|
||||||
|
* PTU-D100(E)
|
||||||
|
* PTU-D300(E)
|
||||||
|
|
||||||
|
Tested only with PTU-D48 yet and with one rotor per chain only.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
1. Connect the rotor via serial (RS232 or RS485)
|
||||||
|
2. Power up the rotor
|
||||||
|
3. The rotor must be calibrated after each power up. This can be accived
|
||||||
|
either using the rotctl `Reset` command (R) or manually via serial terminal
|
||||||
|
sending the `R\n` command.
|
||||||
|
4. To enable the rotor to fully turn +/- 180°, the softlock must be disabled.
|
||||||
|
This is included in the rotctl `Reset` commnad or manually via serial terminal
|
||||||
|
seinden the command `LD\n`. **WARNING:** Send this command only after the rotor is
|
||||||
|
calibrated, or you risk damage running into the hard endstops (at about +/-190°)
|
||||||
|
5. Start `rotctl` or `rotctld` with the arguments `-m 2501 -r <Serial
|
||||||
|
Interface>`
|
||||||
|
|
||||||
|
Have Fun.
|
||||||
|
|
||||||
|
### Hints
|
||||||
|
|
||||||
|
1. Setup the max. velocity, power and acceleration according to your antenna load.
|
||||||
|
This must be done via serial terminal, as the functions are not implemented yet.
|
||||||
|
2. Never use the maximum hold power, only use the low or off. If you use max or regular,
|
||||||
|
the rotor may easily overheat!
|
||||||
|
|
||||||
|
## PTU Protocol
|
||||||
|
|
||||||
|
* [Protocol Version 3.02 (2011)](https://flir.netx.net/file/asset/11556/original/attachment)
|
||||||
|
|
||||||
|
## Current Status
|
||||||
|
|
||||||
|
The current status is **ALPHA**. It is tested with DirectedPercepiton PTU-D48 (Firmware v2.13.4r0(D48-C14/E))
|
||||||
|
Linux with `rotctl` and `gpredict`.
|
||||||
|
|
||||||
|
### Implemented so far:
|
||||||
|
|
||||||
|
* init
|
||||||
|
* cleanup
|
||||||
|
* open
|
||||||
|
* close
|
||||||
|
* set_position
|
||||||
|
* get_position
|
||||||
|
* park
|
||||||
|
* stop
|
||||||
|
* reset
|
||||||
|
* move
|
||||||
|
* info
|
||||||
|
|
||||||
|
### Needs to be implemented:
|
||||||
|
|
||||||
|
#### Parameters
|
||||||
|
|
||||||
|
* velocity
|
||||||
|
* acceleration
|
||||||
|
* velocity profile
|
||||||
|
* user soft-limits
|
||||||
|
* power commands (move and hold)
|
||||||
|
* step mode
|
||||||
|
* reset on startup
|
||||||
|
|
||||||
|
#### Functions
|
||||||
|
|
||||||
|
* usage of chained rotors via RS485
|
|
@ -0,0 +1,555 @@
|
||||||
|
/*
|
||||||
|
* Hamlib FLIR PTU rotor backend - main file
|
||||||
|
* Copyright (c) 2022 by Andreas Mueller (DC1MIL)
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <hamlib/config.h>
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h> /* String function definitions */
|
||||||
|
#include <math.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
|
#include "hamlib/rotator.h"
|
||||||
|
#include "register.h"
|
||||||
|
#include "idx_builtin.h"
|
||||||
|
#include "serial.h"
|
||||||
|
|
||||||
|
#include "flir.h"
|
||||||
|
|
||||||
|
#define FLIR_FUNC 0
|
||||||
|
#define FLIR_LEVEL ROT_LEVEL_SPEED
|
||||||
|
#define FLIR_PARM 0
|
||||||
|
|
||||||
|
#define FLIR_STATUS (ROT_STATUS_MOVING | ROT_STATUS_MOVING_AZ | ROT_STATUS_MOVING_LEFT | ROT_STATUS_MOVING_RIGHT | \
|
||||||
|
ROT_STATUS_MOVING_EL | ROT_STATUS_MOVING_UP | ROT_STATUS_MOVING_DOWN | \
|
||||||
|
ROT_STATUS_LIMIT_UP | ROT_STATUS_LIMIT_DOWN | ROT_STATUS_LIMIT_LEFT | ROT_STATUS_LIMIT_RIGHT)
|
||||||
|
|
||||||
|
struct flir_priv_data
|
||||||
|
{
|
||||||
|
azimuth_t az;
|
||||||
|
elevation_t el;
|
||||||
|
|
||||||
|
struct timeval tv; /* time last az/el update */
|
||||||
|
azimuth_t target_az;
|
||||||
|
elevation_t target_el;
|
||||||
|
rot_status_t status;
|
||||||
|
|
||||||
|
setting_t funcs;
|
||||||
|
value_t levels[RIG_SETTING_MAX];
|
||||||
|
value_t parms[RIG_SETTING_MAX];
|
||||||
|
|
||||||
|
char info[256];
|
||||||
|
|
||||||
|
struct ext_list *ext_funcs;
|
||||||
|
struct ext_list *ext_levels;
|
||||||
|
struct ext_list *ext_parms;
|
||||||
|
|
||||||
|
char *magic_conf;
|
||||||
|
|
||||||
|
float_t resolution_pp;
|
||||||
|
float_t resolution_tp;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int flir_request(ROT *rot, char *request, char *response,
|
||||||
|
int resp_size)
|
||||||
|
{
|
||||||
|
int return_value = -RIG_EINVAL;
|
||||||
|
int retry_read = 0;
|
||||||
|
int read_char = 0;
|
||||||
|
|
||||||
|
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
|
||||||
|
|
||||||
|
rig_flush(&rot->state.rotport);
|
||||||
|
|
||||||
|
if (request)
|
||||||
|
{
|
||||||
|
return_value = write_block(&rot->state.rotport, (unsigned char *)request,
|
||||||
|
strlen(request));
|
||||||
|
if (return_value != RIG_OK)
|
||||||
|
{
|
||||||
|
rig_debug(RIG_DEBUG_VERBOSE, "%s request not OK\n", __func__);
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Is a direct response expected?
|
||||||
|
if (response != NULL)
|
||||||
|
{
|
||||||
|
while(retry_read < rot->state.rotport.retry)
|
||||||
|
{
|
||||||
|
memset(response, 0, (size_t)resp_size);
|
||||||
|
read_char = read_string(&rot->state.rotport, (unsigned char *)response, resp_size,
|
||||||
|
"\r\n", sizeof("\r\n"), 0, 1);
|
||||||
|
if(read_char > 0)
|
||||||
|
{
|
||||||
|
if(response[0] == '*')
|
||||||
|
{
|
||||||
|
rig_debug(RIG_DEBUG_VERBOSE, "accepted command %s\n", request);
|
||||||
|
return RIG_OK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rig_debug(RIG_DEBUG_VERBOSE, "NOT accepted command %s\n", request);
|
||||||
|
return -RIG_ERJCTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
retry_read++;
|
||||||
|
}
|
||||||
|
response = "";
|
||||||
|
rig_debug(RIG_DEBUG_VERBOSE, "timeout for command %s\n", request);
|
||||||
|
return -RIG_ETIMEOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return return_value;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int flir_init(ROT *rot)
|
||||||
|
{
|
||||||
|
struct flir_priv_data *priv;
|
||||||
|
|
||||||
|
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
|
||||||
|
|
||||||
|
rot->state.priv = (struct flir_priv_data *)
|
||||||
|
calloc(1, sizeof(struct flir_priv_data));
|
||||||
|
|
||||||
|
if (!rot->state.priv)
|
||||||
|
{
|
||||||
|
return -RIG_ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
priv = rot->state.priv;
|
||||||
|
|
||||||
|
priv->az = priv->el = 0;
|
||||||
|
|
||||||
|
priv->target_az = priv->target_el = 0;
|
||||||
|
|
||||||
|
priv->magic_conf = strdup("ROTATOR");
|
||||||
|
|
||||||
|
priv->resolution_pp = 92.5714;
|
||||||
|
priv->resolution_tp = 46.2857;
|
||||||
|
|
||||||
|
return RIG_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int flir_cleanup(ROT *rot)
|
||||||
|
{
|
||||||
|
struct flir_priv_data *priv = (struct flir_priv_data *)
|
||||||
|
rot->state.priv;
|
||||||
|
|
||||||
|
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
|
||||||
|
|
||||||
|
free(priv->ext_funcs);
|
||||||
|
free(priv->ext_levels);
|
||||||
|
free(priv->ext_parms);
|
||||||
|
free(priv->magic_conf);
|
||||||
|
|
||||||
|
if (rot->state.priv)
|
||||||
|
{
|
||||||
|
free(rot->state.priv);
|
||||||
|
}
|
||||||
|
|
||||||
|
rot->state.priv = NULL;
|
||||||
|
|
||||||
|
return RIG_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int flir_open(ROT *rot)
|
||||||
|
{
|
||||||
|
struct flir_priv_data *priv;
|
||||||
|
char return_str[MAXBUF];
|
||||||
|
float_t resolution_pp, resolution_tp;
|
||||||
|
int return_value = RIG_OK;
|
||||||
|
|
||||||
|
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
|
||||||
|
|
||||||
|
priv = rot->state.priv;
|
||||||
|
|
||||||
|
// Disable ECHO
|
||||||
|
return_value = flir_request(rot, "ED\n", NULL, MAXBUF);
|
||||||
|
|
||||||
|
// Disable Verbose Mode
|
||||||
|
return_value = flir_request(rot, "FT\n", return_str, MAXBUF);
|
||||||
|
|
||||||
|
// Get PAN resolution in arcsecs
|
||||||
|
if(flir_request(rot, "PR\n", return_str, MAXBUF) == RIG_OK)
|
||||||
|
{
|
||||||
|
sscanf(return_str, "* %f", &resolution_pp);
|
||||||
|
rig_debug(RIG_DEBUG_VERBOSE, "PAN resolution: %f arcsecs per position\n", resolution_pp);
|
||||||
|
priv->resolution_pp = resolution_pp;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return_value = -RIG_EPROTO;
|
||||||
|
}
|
||||||
|
// Get TILT resolution in arcsecs
|
||||||
|
if(flir_request(rot, "TR\n", return_str, MAXBUF) == RIG_OK)
|
||||||
|
{
|
||||||
|
sscanf(return_str, "* %f", &resolution_tp);
|
||||||
|
rig_debug(RIG_DEBUG_VERBOSE, "TILT resolution: %f arcsecs per position\n", resolution_tp);
|
||||||
|
priv->resolution_tp = resolution_tp;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return_value = -RIG_EPROTO;
|
||||||
|
}
|
||||||
|
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int flir_close(ROT *rot)
|
||||||
|
{
|
||||||
|
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
|
||||||
|
|
||||||
|
return RIG_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int flir_set_conf(ROT *rot, token_t token, const char *val)
|
||||||
|
{
|
||||||
|
return -RIG_ENIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int flir_get_conf(ROT *rot, token_t token, char *val)
|
||||||
|
{
|
||||||
|
return -RIG_ENIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int flir_set_position(ROT *rot, azimuth_t az, elevation_t el)
|
||||||
|
{
|
||||||
|
int32_t t_pan_positions, t_tilt_positions;
|
||||||
|
char return_str[MAXBUF];
|
||||||
|
char cmd_str[MAXBUF];
|
||||||
|
struct flir_priv_data *priv = (struct flir_priv_data *)
|
||||||
|
rot->state.priv;
|
||||||
|
|
||||||
|
rig_debug(RIG_DEBUG_VERBOSE, "%s called: %.2f %.2f\n", __func__,
|
||||||
|
az, el);
|
||||||
|
|
||||||
|
priv->target_az = az;
|
||||||
|
priv->target_el = el;
|
||||||
|
|
||||||
|
t_pan_positions = (az * 3600) / priv->resolution_pp;
|
||||||
|
t_tilt_positions = - ((90.0 - el) * 3600) / priv->resolution_tp;
|
||||||
|
|
||||||
|
sprintf(cmd_str, "PP%d TP%d\n", t_pan_positions, t_tilt_positions);
|
||||||
|
|
||||||
|
return flir_request(rot, cmd_str, return_str, MAXBUF);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get position of rotor
|
||||||
|
*/
|
||||||
|
static int flir_get_position(ROT *rot, azimuth_t *az, elevation_t *el)
|
||||||
|
{
|
||||||
|
int return_value = RIG_OK;
|
||||||
|
char return_str[MAXBUF];
|
||||||
|
int32_t pan_positions, tilt_positions;
|
||||||
|
|
||||||
|
struct flir_priv_data *priv = (struct flir_priv_data *)
|
||||||
|
rot->state.priv;
|
||||||
|
|
||||||
|
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
|
||||||
|
|
||||||
|
|
||||||
|
if(flir_request(rot, "PP\n", return_str, MAXBUF) == RIG_OK)
|
||||||
|
{
|
||||||
|
rig_debug(RIG_DEBUG_VERBOSE, "PP Return String: %s\n", return_str);
|
||||||
|
sscanf(return_str, "* %d", &pan_positions);
|
||||||
|
priv->az = (pan_positions * priv->resolution_pp) / 3600;
|
||||||
|
*az = priv->az;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rig_debug(RIG_DEBUG_VERBOSE, "PP Wrong Return String: %s\n", return_str);
|
||||||
|
return_value = -RIG_EPROTO;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(flir_request(rot, "TP\n", return_str, MAXBUF) == RIG_OK)
|
||||||
|
{
|
||||||
|
rig_debug(RIG_DEBUG_VERBOSE, "TP Return String: %s\n", return_str);
|
||||||
|
sscanf(return_str, "* %d", &tilt_positions);
|
||||||
|
priv->el = 90.0 + ((tilt_positions * priv->resolution_tp) / 3600);
|
||||||
|
*el = priv->el;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rig_debug(RIG_DEBUG_VERBOSE, "PP Wrong Return String: %s\n", return_str);
|
||||||
|
return_value = -RIG_EPROTO;
|
||||||
|
}
|
||||||
|
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int flir_stop(ROT *rot)
|
||||||
|
{
|
||||||
|
int return_value = RIG_OK;
|
||||||
|
|
||||||
|
struct flir_priv_data *priv = (struct flir_priv_data *)
|
||||||
|
rot->state.priv;
|
||||||
|
azimuth_t az;
|
||||||
|
elevation_t el;
|
||||||
|
|
||||||
|
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
|
||||||
|
|
||||||
|
return_value = flir_request(rot, "H\n", NULL, MAXBUF);
|
||||||
|
// Wait 2s until rotor has stopped (Needs to be refactored)
|
||||||
|
hl_usleep(2000000);
|
||||||
|
|
||||||
|
return_value = flir_get_position(rot, &az, &el);
|
||||||
|
|
||||||
|
priv->target_az = priv->az = az;
|
||||||
|
priv->target_el = priv->el = el;
|
||||||
|
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int flir_park(ROT *rot)
|
||||||
|
{
|
||||||
|
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
|
||||||
|
|
||||||
|
/* Assume park Position is 0,90 */
|
||||||
|
flir_set_position(rot, 0, 90);
|
||||||
|
|
||||||
|
return RIG_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int flir_reset(ROT *rot, rot_reset_t reset)
|
||||||
|
{
|
||||||
|
int return_value = RIG_OK;
|
||||||
|
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
|
||||||
|
if (reset != 0)
|
||||||
|
{
|
||||||
|
return_value = flir_request(rot, "r\n", NULL, 0);
|
||||||
|
// After Reset: Disable Hard Limits
|
||||||
|
if(return_value == RIG_OK)
|
||||||
|
{
|
||||||
|
return_value = flir_request(rot, "LD\n", NULL, MAXBUF);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int flir_move(ROT *rot, int direction, int speed)
|
||||||
|
{
|
||||||
|
struct flir_priv_data *priv = (struct flir_priv_data *)
|
||||||
|
rot->state.priv;
|
||||||
|
|
||||||
|
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
|
||||||
|
rig_debug(RIG_DEBUG_TRACE, "%s: Direction = %d, Speed = %d\n", __func__,
|
||||||
|
direction, speed);
|
||||||
|
|
||||||
|
switch (direction)
|
||||||
|
{
|
||||||
|
case ROT_MOVE_UP:
|
||||||
|
return flir_set_position(rot, priv->target_az, 90);
|
||||||
|
|
||||||
|
case ROT_MOVE_DOWN:
|
||||||
|
return flir_set_position(rot, priv->target_az, 0);
|
||||||
|
|
||||||
|
case ROT_MOVE_CCW:
|
||||||
|
return flir_set_position(rot, -180, priv->target_el);
|
||||||
|
|
||||||
|
case ROT_MOVE_CW:
|
||||||
|
return flir_set_position(rot, 180, priv->target_el);
|
||||||
|
|
||||||
|
default:
|
||||||
|
return -RIG_EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return RIG_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *flir_get_info(ROT *rot)
|
||||||
|
{
|
||||||
|
char firmware_str[121];
|
||||||
|
char info_str[101];
|
||||||
|
|
||||||
|
struct flir_priv_data *priv = (struct flir_priv_data *)
|
||||||
|
rot->state.priv;
|
||||||
|
|
||||||
|
sprintf(priv->info, "No Info");
|
||||||
|
|
||||||
|
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
|
||||||
|
if(flir_request(rot, "V\n", firmware_str, 120) != RIG_OK)
|
||||||
|
{
|
||||||
|
return "No Info available";
|
||||||
|
}
|
||||||
|
hl_usleep(500000);
|
||||||
|
if(flir_request(rot, "O\n", info_str, 100) != RIG_OK)
|
||||||
|
{
|
||||||
|
return "No Info available";
|
||||||
|
}
|
||||||
|
sprintf(priv->info, "Firmware: %s\nPower: %s", firmware_str, info_str);
|
||||||
|
|
||||||
|
return priv->info;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int flir_set_func(ROT *rot, setting_t func, int status)
|
||||||
|
{
|
||||||
|
return -RIG_ENIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int flir_get_func(ROT *rot, setting_t func, int *status)
|
||||||
|
{
|
||||||
|
return -RIG_ENIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int flir_set_level(ROT *rot, setting_t level, value_t val)
|
||||||
|
{
|
||||||
|
return -RIG_ENIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int flir_get_level(ROT *rot, setting_t level, value_t *val)
|
||||||
|
{
|
||||||
|
return -RIG_ENIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int flir_set_ext_level(ROT *rot, token_t token, value_t val)
|
||||||
|
{
|
||||||
|
return -RIG_ENIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int flir_get_ext_level(ROT *rot, token_t token, value_t *val)
|
||||||
|
{
|
||||||
|
return -RIG_ENIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int flir_set_ext_func(ROT *rot, token_t token, int status)
|
||||||
|
{
|
||||||
|
return -RIG_ENIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int flir_get_ext_func(ROT *rot, token_t token, int *status)
|
||||||
|
{
|
||||||
|
return -RIG_ENIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int flir_set_parm(ROT *rot, setting_t parm, value_t val)
|
||||||
|
{
|
||||||
|
return -RIG_ENIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int flir_get_parm(ROT *rot, setting_t parm, value_t *val)
|
||||||
|
{
|
||||||
|
return -RIG_ENIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int flir_set_ext_parm(ROT *rot, token_t token, value_t val)
|
||||||
|
{
|
||||||
|
return -RIG_ENIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int flir_get_ext_parm(ROT *rot, token_t token, value_t *val)
|
||||||
|
{
|
||||||
|
return -RIG_ENIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int flir_get_status(ROT *rot, rot_status_t *status)
|
||||||
|
{
|
||||||
|
struct flir_priv_data *priv = (struct flir_priv_data *)
|
||||||
|
rot->state.priv;
|
||||||
|
*status = priv->status;
|
||||||
|
|
||||||
|
return RIG_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* flir rotator capabilities.
|
||||||
|
*/
|
||||||
|
struct rot_caps flir_caps =
|
||||||
|
{
|
||||||
|
ROT_MODEL(ROT_MODEL_FLIR),
|
||||||
|
.model_name = "PTU Serial",
|
||||||
|
.mfg_name = "FLIR",
|
||||||
|
.version = "20221126.0",
|
||||||
|
.copyright = "LGPL",
|
||||||
|
.status = RIG_STATUS_ALPHA,
|
||||||
|
.rot_type = ROT_TYPE_AZEL,
|
||||||
|
.port_type = RIG_PORT_SERIAL,
|
||||||
|
.serial_rate_min = 9600,
|
||||||
|
.serial_rate_max = 9600,
|
||||||
|
.serial_data_bits = 8,
|
||||||
|
.serial_stop_bits = 1,
|
||||||
|
.serial_parity = RIG_PARITY_NONE,
|
||||||
|
.serial_handshake = RIG_HANDSHAKE_NONE,
|
||||||
|
.write_delay = 0,
|
||||||
|
.post_write_delay = 300,
|
||||||
|
.timeout = 400,
|
||||||
|
.retry = 3,
|
||||||
|
|
||||||
|
.min_az = -180.,
|
||||||
|
.max_az = 180.,
|
||||||
|
.min_el = 0.,
|
||||||
|
.max_el = 90.,
|
||||||
|
|
||||||
|
.priv = NULL, /* priv */
|
||||||
|
|
||||||
|
.has_get_func = FLIR_FUNC,
|
||||||
|
.has_set_func = FLIR_FUNC,
|
||||||
|
.has_get_level = FLIR_LEVEL,
|
||||||
|
.has_set_level = ROT_LEVEL_SET(FLIR_LEVEL),
|
||||||
|
.has_get_parm = FLIR_PARM,
|
||||||
|
.has_set_parm = ROT_PARM_SET(FLIR_PARM),
|
||||||
|
|
||||||
|
.level_gran = { [ROT_LVL_SPEED] = { .min = { .i = 1 }, .max = { .i = 4 }, .step = { .i = 1 } } },
|
||||||
|
|
||||||
|
.has_status = FLIR_STATUS,
|
||||||
|
|
||||||
|
.rot_init = flir_init,
|
||||||
|
.rot_cleanup = flir_cleanup,
|
||||||
|
.rot_open = flir_open,
|
||||||
|
.rot_close = flir_close,
|
||||||
|
|
||||||
|
.set_conf = flir_set_conf,
|
||||||
|
.get_conf = flir_get_conf,
|
||||||
|
|
||||||
|
.set_position = flir_set_position,
|
||||||
|
.get_position = flir_get_position,
|
||||||
|
.park = flir_park,
|
||||||
|
.stop = flir_stop,
|
||||||
|
.reset = flir_reset,
|
||||||
|
.move = flir_move,
|
||||||
|
|
||||||
|
.set_func = flir_set_func,
|
||||||
|
.get_func = flir_get_func,
|
||||||
|
.set_level = flir_set_level,
|
||||||
|
.get_level = flir_get_level,
|
||||||
|
.set_parm = flir_set_parm,
|
||||||
|
.get_parm = flir_get_parm,
|
||||||
|
|
||||||
|
.set_ext_func = flir_set_ext_func,
|
||||||
|
.get_ext_func = flir_get_ext_func,
|
||||||
|
.set_ext_level = flir_set_ext_level,
|
||||||
|
.get_ext_level = flir_get_ext_level,
|
||||||
|
.set_ext_parm = flir_set_ext_parm,
|
||||||
|
.get_ext_parm = flir_get_ext_parm,
|
||||||
|
|
||||||
|
.get_info = flir_get_info,
|
||||||
|
.get_status = flir_get_status,
|
||||||
|
};
|
||||||
|
|
||||||
|
DECLARE_INITROT_BACKEND(flir)
|
||||||
|
{
|
||||||
|
rig_debug(RIG_DEBUG_VERBOSE, "%s: _init called\n", __func__);
|
||||||
|
|
||||||
|
rot_register(&flir_caps);
|
||||||
|
rot_register(&netrotctl_caps);
|
||||||
|
|
||||||
|
return RIG_OK;
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
* Hamlib FLIR PTU rotor backend - main header
|
||||||
|
* Copyright (c) 2022 by Andreas Mueller (DC1MIL)
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* 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_FLIR_H
|
||||||
|
#define _ROT_FLIR_H 1
|
||||||
|
|
||||||
|
#include "token.h"
|
||||||
|
|
||||||
|
/* backend conf */
|
||||||
|
#define TOK_CFG_ROT_MAGICCONF TOKEN_BACKEND(1)
|
||||||
|
#define TOK_CFG_ROT_STATIC_DATA TOKEN_BACKEND(2)
|
||||||
|
|
||||||
|
/* ext_level's and ext_parm's tokens */
|
||||||
|
#define TOK_EL_ROT_MAGICLEVEL TOKEN_BACKEND(1)
|
||||||
|
#define TOK_EL_ROT_MAGICFUNC TOKEN_BACKEND(2)
|
||||||
|
#define TOK_EL_ROT_MAGICOP TOKEN_BACKEND(3)
|
||||||
|
#define TOK_EP_ROT_MAGICPARM TOKEN_BACKEND(4)
|
||||||
|
#define TOK_EL_ROT_MAGICCOMBO TOKEN_BACKEND(5)
|
||||||
|
#define TOK_EL_ROT_MAGICEXTFUNC TOKEN_BACKEND(6)
|
||||||
|
|
||||||
|
#define MAXBUF 64
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
extern struct rot_caps flir_caps;
|
||||||
|
extern struct rot_caps netrotctl_caps;
|
||||||
|
|
||||||
|
#endif /* _ROT_FLIR_H */
|
|
@ -90,6 +90,7 @@ DEFINE_INITROT_BACKEND(indi);
|
||||||
DEFINE_INITROT_BACKEND(androidsensor);
|
DEFINE_INITROT_BACKEND(androidsensor);
|
||||||
#endif
|
#endif
|
||||||
DEFINE_INITROT_BACKEND(grbltrk);
|
DEFINE_INITROT_BACKEND(grbltrk);
|
||||||
|
DEFINE_INITROT_BACKEND(flir);
|
||||||
//! @endcond
|
//! @endcond
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -138,6 +139,7 @@ static struct
|
||||||
{ ROT_ANDROIDSENSOR, ROT_BACKEND_ANDROIDSENSOR, ROT_FUNCNAMA(androidsensor) },
|
{ ROT_ANDROIDSENSOR, ROT_BACKEND_ANDROIDSENSOR, ROT_FUNCNAMA(androidsensor) },
|
||||||
#endif
|
#endif
|
||||||
{ ROT_GRBLTRK, ROT_BACKEND_GRBLTRK, ROT_FUNCNAMA(grbltrk) },
|
{ ROT_GRBLTRK, ROT_BACKEND_GRBLTRK, ROT_FUNCNAMA(grbltrk) },
|
||||||
|
{ ROT_FLIR, ROT_BACKEND_FLIR, ROT_FUNCNAMA(flir) },
|
||||||
{ 0, NULL }, /* end */
|
{ 0, NULL }, /* end */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Ładowanie…
Reference in New Issue