2013-08-21 11:02:52 +02:00
|
|
|
/*
|
|
|
|
* positioner.h: Steerable dish positioning
|
|
|
|
*
|
|
|
|
* See the main source file 'vdr.c' for copyright information and
|
|
|
|
* how to reach the author.
|
|
|
|
*
|
2013-10-20 09:32:23 +02:00
|
|
|
* $Id: positioner.h 3.2 2013/10/20 09:29:41 kls Exp $
|
2013-08-21 11:02:52 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef __POSITIONER_H
|
|
|
|
#define __POSITIONER_H
|
|
|
|
|
|
|
|
#include "thread.h"
|
|
|
|
#include "tools.h"
|
|
|
|
|
|
|
|
/// A steerable satellite dish generally points to the south on the northern hemisphere,
|
|
|
|
/// and to the north on the southern hemisphere (unless you're located directly on the
|
|
|
|
/// equator, in which case the general direction is "up"). Therefore, moving the dish
|
|
|
|
/// "east" or "west" means something different on either hemisphere. From the local dish
|
|
|
|
/// motor's point of view, it makes more sense to speak of turning the dish "left" or
|
|
|
|
/// "right", which is independent of the actual hemisphere the dish is located in.
|
|
|
|
/// In the cPositioner class context, when a dish on the northern hemisphere moves "east",
|
|
|
|
/// it is considered to be moving "left". Imagine standing behind the dish and looking
|
|
|
|
/// towards the satellites, and clearly "east" is "left". On the southern hemisphere
|
|
|
|
/// the same move to the "left" would go to the "west". So on the hardware level it is
|
|
|
|
/// clear what "left" and "right" means. The user interface may present different labels
|
|
|
|
/// to the viewer, depending on the hemisphere the dish is on.
|
|
|
|
/// All angles in this context are given in "degrees * 10", which allows for an angular
|
|
|
|
/// resolution of 0.1 degrees.
|
|
|
|
|
|
|
|
class cPositioner {
|
|
|
|
private:
|
|
|
|
mutable cMutex mutex;
|
|
|
|
static cPositioner *positioner;
|
|
|
|
int capabilities;
|
|
|
|
int frontend; // file descriptor of the DVB frontend
|
|
|
|
mutable int lastLongitude; // the longitude the dish has last been moved to
|
|
|
|
int targetLongitude; // the longitude the dish is supposed to be moved to
|
|
|
|
mutable int lastHourAngle; // the hour angle the positioner has last been moved to
|
|
|
|
int targetHourAngle; // the hour angle the positioner is supposed to be moved to
|
|
|
|
int swingTime;
|
|
|
|
cTimeMs movementStart;
|
|
|
|
protected:
|
|
|
|
cPositioner(void);
|
|
|
|
virtual ~cPositioner();
|
|
|
|
void SetCapabilities(int Capabilities) { capabilities = Capabilities; }
|
|
|
|
///< A derived class shall call this function in its constructor to set the
|
|
|
|
///< capability flags it supports.
|
|
|
|
int Frontend(void) const { return frontend; }
|
|
|
|
///< Returns the file descriptor of the DVB frontend the positioner is
|
|
|
|
///< connected to. If the positioner is not connected to any DVB device,
|
|
|
|
///< -1 will be returned.
|
|
|
|
static int CalcHourAngle(int Longitude);
|
|
|
|
///< Takes the longitude and latitude of the dish location from the system
|
|
|
|
///< setup and the given Longitude to calculate the "hour angle" to which to move
|
|
|
|
///< the dish to in order to point to the satellite at orbital position Longitude.
|
|
|
|
///< An hour angle of zero means the dish shall point directly towards the
|
|
|
|
///< celestial equator (which is south on the northern hemisphere, and north on
|
|
|
|
///< the southern hemisphere). Negative values mean that the dish needs to be
|
|
|
|
///< moved to the left (as seen from behind the dish), while positive values
|
|
|
|
///< require a movement to the right.
|
|
|
|
static int CalcLongitude(int HourAngle);
|
|
|
|
///< Returns the longitude of the satellite position the dish points at when the
|
|
|
|
///< positioner is moved to the given HourAngle.
|
|
|
|
void StartMovementTimer(int Longitude);
|
|
|
|
///< Starts a timer that estimates how long it will take to move the dish from
|
|
|
|
///< the current position to the one given by Longitude. The default implementation
|
|
|
|
///< of CurrentLongitude() uses this timer.
|
|
|
|
public:
|
|
|
|
enum ePositionerCapabilities {
|
|
|
|
pcCanNothing = 0x0000,
|
|
|
|
pcCanDrive = 0x0001,
|
|
|
|
pcCanStep = 0x0002,
|
|
|
|
pcCanHalt = 0x0004,
|
|
|
|
pcCanSetLimits = 0x0008,
|
|
|
|
pcCanDisableLimits = 0x0010,
|
|
|
|
pcCanEnableLimits = 0x0020,
|
|
|
|
pcCanStorePosition = 0x0040,
|
|
|
|
pcCanRecalcPositions = 0x0080,
|
|
|
|
pcCanGotoPosition = 0x0100,
|
|
|
|
pcCanGotoAngle = 0x0200,
|
|
|
|
};
|
|
|
|
enum ePositionerDirection { pdLeft, pdRight };
|
|
|
|
static int NormalizeAngle(int Angle);
|
|
|
|
///< Normalizes the given Angle into the range -1800...1800.
|
|
|
|
int Capabilities(void) const { return capabilities; }
|
|
|
|
///< Returns a flag word defining all the things this positioner is
|
|
|
|
///< capable of.
|
|
|
|
void SetFrontend(int Frontend) { frontend = Frontend; }
|
|
|
|
///< This function is called whenever the positioner is connected to
|
|
|
|
///< a DVB frontend.
|
|
|
|
static int HorizonLongitude(ePositionerDirection Direction);
|
|
|
|
///< Returns the longitude of the satellite position that is just at the
|
|
|
|
///< horizon when looking in the given Direction. Note that this function
|
|
|
|
///< only delivers reasonable values for site latitudes between +/-81 degrees.
|
|
|
|
///< Beyond these limits (i.e. near the north or south pole) a constant value
|
2013-10-20 09:32:23 +02:00
|
|
|
///< of 0 will be returned.
|
2013-08-21 11:02:52 +02:00
|
|
|
int HardLimitLongitude(ePositionerDirection Direction) const;
|
|
|
|
///< Returns the longitude of the positioner's hard limit in the given
|
|
|
|
///< Direction. Note that the value returned here may be larger (or smaller,
|
|
|
|
///< depending on the Direction) than that returned by HorizonLongitude(),
|
|
|
|
///< which would mean that it lies below that horizon.
|
|
|
|
int LastLongitude(void) const { return lastLongitude; }
|
|
|
|
///< Returns the longitude the dish has last been moved to.
|
|
|
|
int TargetLongitude(void) const { return targetLongitude; }
|
|
|
|
///< Returns the longitude the dish is supposed to be moved to. Once the target
|
|
|
|
///< longitude has been reached, this is the same as the value returned by
|
|
|
|
///< CurrentLongitude().
|
|
|
|
virtual cString Error(void) const { return NULL; }
|
|
|
|
///< Returns a short, single line string indicating an error condition (if
|
|
|
|
///< the positioner is able to report any errors).
|
|
|
|
///< NULL means there is no error.
|
|
|
|
virtual void Drive(ePositionerDirection Direction) {}
|
|
|
|
///< Continuously move the dish to the given Direction until Halt() is
|
|
|
|
///< called or it hits the soft or hard limit.
|
|
|
|
virtual void Step(ePositionerDirection Direction, uint Steps = 1) {}
|
|
|
|
///< Move the dish the given number of Steps in the given Direction.
|
|
|
|
///< The maximum number of steps a particular positioner can do in a single
|
|
|
|
///< call may be limited.
|
|
|
|
///< A "step" is the smallest possible movement the positioner can make, which
|
|
|
|
///< is typically 0.1 degrees.
|
|
|
|
virtual void Halt(void) {}
|
|
|
|
///< Stop any ongoing motion of the dish.
|
|
|
|
virtual void SetLimit(ePositionerDirection Direction) {}
|
|
|
|
///< Set the soft limit of the dish movement in the given Direction to the
|
|
|
|
///< current position.
|
|
|
|
virtual void DisableLimits(void) {}
|
|
|
|
///< Disables the soft limits for the dish movement.
|
|
|
|
virtual void EnableLimits(void) {}
|
|
|
|
///< Enables the soft limits for the dish movement.
|
|
|
|
virtual void StorePosition(uint Number) {}
|
|
|
|
///< Store the current position as a satellite position with the given Number.
|
|
|
|
///< Number can be in the range 1...255. However, a particular positioner
|
|
|
|
///< may only have a limited number of satellite positions it can store.
|
|
|
|
virtual void RecalcPositions(uint Number) {}
|
|
|
|
///< Take the difference betwen the current actual position of the dish and
|
|
|
|
///< the position stored with teh given Number, and apply the difference to
|
|
|
|
///< all stored positions.
|
|
|
|
virtual void GotoPosition(uint Number, int Longitude);
|
|
|
|
///< Move the dish to the satellite position stored under the given Number.
|
|
|
|
///< Number must be one of the values previously used with StorePosition().
|
|
|
|
///< The special value 0 shall move the dish to a "reference position",
|
|
|
|
///< which usually is due south (or north, if you're on the southern hemisphere).
|
|
|
|
///< Longitude will be used to calculate how long it takes to move the dish
|
|
|
|
///< from its current position to the given Longitude.
|
|
|
|
///< A derived class must call the base class function to have the target
|
|
|
|
///< longitude stored.
|
|
|
|
virtual void GotoAngle(int Longitude);
|
|
|
|
///< Move the dish to the given angular position. Longitude can be in the range
|
|
|
|
///< -1800...+1800. A positive sign indicates a position east of Greenwich,
|
|
|
|
///< while western positions have a negative sign. The absolute value is in
|
|
|
|
///< "degrees * 10", which allows for a resolution of 1/10 of a degree.
|
|
|
|
///< A derived class must call the base class function to have the target
|
|
|
|
///< longitude stored.
|
|
|
|
virtual int CurrentLongitude(void) const;
|
|
|
|
///< Returns the longitude the dish currently points to. If the dish is in motion,
|
|
|
|
///< this may be an estimate based on the angular speed of the positioner.
|
|
|
|
///< The default implementation takes the last and target longitude as well as
|
|
|
|
///< the rotation speed of the positioner to calculate the estimated current
|
|
|
|
///< longitude the dish points to.
|
|
|
|
virtual bool IsMoving(void) const;
|
|
|
|
///< Returns true if the dish is currently moving as a result of a call to
|
|
|
|
///< GotoPosition() or GotoAngle().
|
|
|
|
static cPositioner *GetPositioner(void);
|
|
|
|
///< Returns a previously created positioner. If no plugin has created
|
|
|
|
///< a positioner, there will always be the default DiSEqC positioner.
|
|
|
|
static void DestroyPositioner(void);
|
|
|
|
///< Destroys a previously created positioner.
|
|
|
|
};
|
|
|
|
|
|
|
|
#endif //__POSITIONER_H
|