summaryrefslogtreecommitdiff
path: root/positioner.h
diff options
context:
space:
mode:
authorKlaus Schmidinger <vdr@tvdr.de>2013-08-21 11:02:52 +0200
committerKlaus Schmidinger <vdr@tvdr.de>2013-08-21 11:02:52 +0200
commitcd10b439d0465afa6bce38188a4e9d8a5e74d859 (patch)
tree54480623232fb0e8e94fd37a5c9e31603301dd35 /positioner.h
parent5b76eec1afbe435b5d1dfabaaa9546f8e400cba7 (diff)
downloadvdr-cd10b439d0465afa6bce38188a4e9d8a5e74d859.tar.gz
vdr-cd10b439d0465afa6bce38188a4e9d8a5e74d859.tar.bz2
Added basic support for positioners to control steerable satellite dishes
Diffstat (limited to 'positioner.h')
-rw-r--r--positioner.h171
1 files changed, 171 insertions, 0 deletions
diff --git a/positioner.h b/positioner.h
new file mode 100644
index 00000000..6e019ed6
--- /dev/null
+++ b/positioner.h
@@ -0,0 +1,171 @@
+/*
+ * positioner.h: Steerable dish positioning
+ *
+ * See the main source file 'vdr.c' for copyright information and
+ * how to reach the author.
+ *
+ * $Id: positioner.h 3.1 2013/06/10 14:27:14 kls Exp $
+ */
+
+#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
+ ///< of +/-14.5 degrees (integer value 145) will be returned.
+ 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