mirror of
https://github.com/vdr-projects/vdr.git
synced 2025-03-01 10:50:46 +00:00
VDR version 2.2.0 is now available at ftp://ftp.tvdr.de/vdr/vdr-2.2.0.tar.bz2 A 'diff' against the previous developer version is available at ftp://ftp.tvdr.de/vdr/vdr-2.1.10-2.2.0.diff MD5 checksums: 8853f64c0fc3d41ffd3b4bfc6f0a14b7 vdr-2.2.0.tar.bz2 2d75806f90a4f1c8b3e30d7568891dc6 vdr-2.1.10-2.2.0.diff A summary of all the major changes since the last stable version 2.0.0 can be found at http://www.tvdr.de/changelog.htm When updating from an earlier version of VDR please make sure you read the INSTALL and MANUAL files that come with the VDR source _before_ doing so! Please make sure you have backup copies of all your configuration files, and verify carefully that your timers will be set to the correct channels after switching to this new version. Thanks to the many people who have contributed in the making, testing and debugging of this new version of VDR, and also to all users who have been enjoying VDR over the past 15 years! Please also visit the VDR homepage at http://www.tvdr.de and VDR's facebook page at https://www.facebook.com/VideoDiskRecorder Have fun! Klaus From the HISTORY file: - Updated the Lithuanian OSD texts (thanks to Valdemaras Pipiras). - Updated the Macedonian OSD texts (thanks to Dimitar Petrovski). - Updated the Romanian OSD texts (thanks to Lucian Muresan). - Updated the Estonian OSD texts (thanks to Arthur Konovalov). - Updated the Italian OSD texts (thanks to Diego Pierotto and Nino Gerbino). - Updated the Finnish OSD texts (thanks to Rolf Ahrenberg). - Updated the Swedish OSD texts (thanks to Magnus Sirwiö). - Updated the Hungarian OSD texts (thanks to István Füley and Albert Danis). - Modified the German translations of the OSD texts regarding "adaptive skipping". - Fixed pausing replay at the last editing mark (reported by Stefan Herdler). - Updated the Polish OSD texts (thanks to Tomasz Maciej Nowak). - Updated the Ukrainian OSD texts (thanks to Yarema Aka Knedlyk). - Fixed using the default sort mode in a video directory without a ".sort" file (reported by Stefan Herdler). - Improved the German translations of "EPG bugfix level"", "StreamId" and "T2SystemId" (thanks to Albert Danis). - Updated the Czech OSD texts (thanks to Ales Jurik). - Updated the Slovak OSD texts (thanks to Milan Hrala). - Updated sources.conf to reflect the fact that Thor 5/6 and Intelsat 10-02 are actually in two separate positions. - Updated the French OSD texts (thanks to Régis Bossut). - Updated the Spanish OSD texts (thanks to Gabriel Bonich). - Fixed leading/trailing/multiple blanks in the translation files. - Bumped all version numbers to 2.2.0. - Official release.
142 lines
4.2 KiB
C
142 lines
4.2 KiB
C
/*
|
|
* positioner.c: Steerable dish positioning
|
|
*
|
|
* See the main source file 'vdr.c' for copyright information and
|
|
* how to reach the author.
|
|
*
|
|
* For an explanation (in German) of the theory behind the calculations see
|
|
* http://www.vdr-portal.de/board17-developer/board97-vdr-core/p1154305-grundlagen-und-winkelberechnungen-f%C3%BCr-h-h-diseqc-motor-antennenanlagen
|
|
* by Albert Danis.
|
|
*
|
|
* $Id: positioner.c 3.5 2015/02/14 11:54:31 kls Exp $
|
|
*/
|
|
|
|
#include "positioner.h"
|
|
#include <math.h>
|
|
#include "config.h"
|
|
|
|
#define SAT_EARTH_RATIO 0.1513 // the Earth's radius, divided by the distance from the Earth's center to the satellite
|
|
#define SAT_VISIBILITY_LAT 812 // the absolute latitude beyond which no satellite can be seen (degrees * 10)
|
|
|
|
#define RAD(x) ((x) * M_PI / 1800)
|
|
#define DEG(x) ((x) * 1800 / M_PI)
|
|
|
|
cPositioner *cPositioner::positioner = NULL;
|
|
|
|
cPositioner::cPositioner(void)
|
|
{
|
|
capabilities = pcCanNothing;
|
|
frontend = -1;
|
|
targetLongitude = lastLongitude = Setup.PositionerLastLon;
|
|
targetHourAngle = lastHourAngle = CalcHourAngle(lastLongitude);
|
|
swingTime = 0;
|
|
delete positioner;
|
|
positioner = this;
|
|
}
|
|
|
|
cPositioner::~cPositioner()
|
|
{
|
|
positioner = NULL;
|
|
}
|
|
|
|
int cPositioner::NormalizeAngle(int Angle)
|
|
{
|
|
while (Angle < -1800)
|
|
Angle += 3600;
|
|
while (Angle > 1800)
|
|
Angle -= 3600;
|
|
return Angle;
|
|
}
|
|
|
|
int cPositioner::CalcHourAngle(int Longitude)
|
|
{
|
|
double Alpha = RAD(Longitude - Setup.SiteLon);
|
|
double Lat = RAD(Setup.SiteLat);
|
|
int Sign = Setup.SiteLat >= 0 ? -1 : 1; // angles to the right are positive, angles to the left are negative
|
|
return Sign * round(DEG(atan2(sin(Alpha), cos(Alpha) - cos(Lat) * SAT_EARTH_RATIO)));
|
|
}
|
|
|
|
int cPositioner::CalcLongitude(int HourAngle)
|
|
{
|
|
double Lat = RAD(Setup.SiteLat);
|
|
double Lon = RAD(Setup.SiteLon);
|
|
double Delta = RAD(HourAngle);
|
|
double Alpha = Delta - asin(sin(M_PI - Delta) * cos(Lat) * SAT_EARTH_RATIO);
|
|
int Sign = Setup.SiteLat >= 0 ? 1 : -1;
|
|
return NormalizeAngle(round(DEG(Lon - Sign * Alpha)));
|
|
}
|
|
|
|
int cPositioner::HorizonLongitude(ePositionerDirection Direction)
|
|
{
|
|
double Delta;
|
|
if (abs(Setup.SiteLat) <= SAT_VISIBILITY_LAT)
|
|
Delta = acos(SAT_EARTH_RATIO / cos(RAD(Setup.SiteLat)));
|
|
else
|
|
Delta = 0;
|
|
if ((Setup.SiteLat >= 0) != (Direction == pdLeft))
|
|
Delta = -Delta;
|
|
return NormalizeAngle(round(DEG(RAD(Setup.SiteLon) + Delta)));
|
|
}
|
|
|
|
int cPositioner::HardLimitLongitude(ePositionerDirection Direction) const
|
|
{
|
|
return CalcLongitude(Direction == pdLeft ? -Setup.PositionerSwing : Setup.PositionerSwing);
|
|
}
|
|
|
|
void cPositioner::StartMovementTimer(int Longitude)
|
|
{
|
|
if (Setup.PositionerSpeed <= 0)
|
|
return;
|
|
cMutexLock MutexLock(&mutex);
|
|
lastLongitude = CurrentLongitude(); // in case the dish was already in motion
|
|
targetLongitude = Longitude;
|
|
lastHourAngle = CalcHourAngle(lastLongitude);
|
|
targetHourAngle = CalcHourAngle(targetLongitude);
|
|
swingTime = abs(targetHourAngle - lastHourAngle) * 1000 / Setup.PositionerSpeed; // time (ms) it takes to move the dish from lastHourAngle to targetHourAngle
|
|
movementStart.Set();
|
|
Setup.PositionerLastLon = targetLongitude;
|
|
}
|
|
|
|
void cPositioner::GotoPosition(uint Number, int Longitude)
|
|
{
|
|
if (Longitude != targetLongitude)
|
|
dsyslog("moving positioner to position %d, longitude %d", Number, Longitude);
|
|
StartMovementTimer(Longitude);
|
|
}
|
|
|
|
void cPositioner::GotoAngle(int Longitude)
|
|
{
|
|
if (Longitude != targetLongitude)
|
|
dsyslog("moving positioner to longitude %d", Longitude);
|
|
StartMovementTimer(Longitude);
|
|
}
|
|
|
|
int cPositioner::CurrentLongitude(void) const
|
|
{
|
|
cMutexLock MutexLock(&mutex);
|
|
if (targetLongitude != lastLongitude) {
|
|
int Elapsed = movementStart.Elapsed(); // it's important to make this 'int', otherwise the expression below yields funny results
|
|
if (swingTime <= Elapsed)
|
|
lastLongitude = targetLongitude;
|
|
else
|
|
return CalcLongitude(lastHourAngle + (targetHourAngle - lastHourAngle) * Elapsed / swingTime);
|
|
}
|
|
return lastLongitude;
|
|
}
|
|
|
|
bool cPositioner::IsMoving(void) const
|
|
{
|
|
cMutexLock MutexLock(&mutex);
|
|
return CurrentLongitude() != targetLongitude;
|
|
}
|
|
|
|
cPositioner *cPositioner::GetPositioner(void)
|
|
{
|
|
return positioner;
|
|
}
|
|
|
|
void cPositioner::DestroyPositioner(void)
|
|
{
|
|
delete positioner;
|
|
}
|