summaryrefslogtreecommitdiff
path: root/dvbdevice.c
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 /dvbdevice.c
parent5b76eec1afbe435b5d1dfabaaa9546f8e400cba7 (diff)
downloadvdr-cd10b439d0465afa6bce38188a4e9d8a5e74d859.tar.gz
vdr-cd10b439d0465afa6bce38188a4e9d8a5e74d859.tar.bz2
Added basic support for positioners to control steerable satellite dishes
Diffstat (limited to 'dvbdevice.c')
-rw-r--r--dvbdevice.c99
1 files changed, 82 insertions, 17 deletions
diff --git a/dvbdevice.c b/dvbdevice.c
index b2dd17ad..9504834d 100644
--- a/dvbdevice.c
+++ b/dvbdevice.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: dvbdevice.c 3.1 2013/04/08 22:13:35 kls Exp $
+ * $Id: dvbdevice.c 3.2 2013/08/17 13:52:05 kls Exp $
*/
#include "dvbdevice.h"
@@ -284,7 +284,7 @@ bool cDvbTransponderParameters::Parse(const char *s)
class cDvbTuner : public cThread {
private:
static cMutex bondMutex;
- enum eTunerStatus { tsIdle, tsSet, tsTuned, tsLocked };
+ enum eTunerStatus { tsIdle, tsSet, tsPositioning, tsTuned, tsLocked };
int frontendType;
const cDvbDevice *device;
int fd_frontend;
@@ -295,6 +295,9 @@ private:
time_t lastTimeoutReport;
cChannel channel;
const cDiseqc *lastDiseqc;
+ int diseqcOffset;
+ int lastSource;
+ cPositioner *positioner;
const cScr *scr;
bool lnbPowerTurnedOn;
eTunerStatus tunerStatus;
@@ -309,6 +312,7 @@ private:
bool IsBondedMaster(void) const { return !bondedTuner || bondedMaster; }
void ClearEventQueue(void) const;
bool GetFrontendStatus(fe_status_t &Status) const;
+ cPositioner *GetPositioner(void);
void ExecuteDiseqc(const cDiseqc *Diseqc, unsigned int *Frequency);
void ResetToneAndVoltage(void);
bool SetFrontend(void);
@@ -325,6 +329,7 @@ public:
bool IsTunedTo(const cChannel *Channel) const;
void SetChannel(const cChannel *Channel);
bool Locked(int TimeoutMs = 0);
+ const cPositioner *Positioner(void) const { return positioner; }
int GetSignalStrength(void) const;
int GetSignalQuality(void) const;
};
@@ -343,6 +348,9 @@ cDvbTuner::cDvbTuner(const cDvbDevice *Device, int Fd_Frontend, int Adapter, int
lockTimeout = 0;
lastTimeoutReport = 0;
lastDiseqc = NULL;
+ diseqcOffset = 0;
+ lastSource = 0;
+ positioner = NULL;
scr = NULL;
lnbPowerTurnedOn = false;
tunerStatus = tsIdle;
@@ -482,6 +490,7 @@ void cDvbTuner::SetChannel(const cChannel *Channel)
cMutexLock MutexLock(&mutex);
if (!IsTunedTo(Channel))
tunerStatus = tsSet;
+ diseqcOffset = 0;
channel = *Channel;
lastTimeoutReport = 0;
newSet.Broadcast();
@@ -662,6 +671,15 @@ static unsigned int FrequencyToHz(unsigned int f)
return f;
}
+cPositioner *cDvbTuner::GetPositioner(void)
+{
+ if (!positioner) {
+ positioner = cPositioner::GetPositioner();
+ positioner->SetFrontend(fd_frontend);
+ }
+ return positioner;
+}
+
void cDvbTuner::ExecuteDiseqc(const cDiseqc *Diseqc, unsigned int *Frequency)
{
if (!lnbPowerTurnedOn) {
@@ -673,23 +691,47 @@ void cDvbTuner::ExecuteDiseqc(const cDiseqc *Diseqc, unsigned int *Frequency)
Mutex.Lock();
struct dvb_diseqc_master_cmd cmd;
const char *CurrentAction = NULL;
- for (;;) {
+ cPositioner *Positioner = NULL;
+ bool Break = false;
+ for (int i = 0; !Break; i++) {
cmd.msg_len = sizeof(cmd.msg);
cDiseqc::eDiseqcActions da = Diseqc->Execute(&CurrentAction, cmd.msg, &cmd.msg_len, scr, Frequency);
- if (da == cDiseqc::daNone)
+ if (da == cDiseqc::daNone) {
+ diseqcOffset = 0;
break;
+ }
+ bool d = i >= diseqcOffset;
switch (da) {
- case cDiseqc::daToneOff: CHECK(ioctl(fd_frontend, FE_SET_TONE, SEC_TONE_OFF)); break;
- case cDiseqc::daToneOn: CHECK(ioctl(fd_frontend, FE_SET_TONE, SEC_TONE_ON)); break;
- case cDiseqc::daVoltage13: CHECK(ioctl(fd_frontend, FE_SET_VOLTAGE, SEC_VOLTAGE_13)); break;
- case cDiseqc::daVoltage18: CHECK(ioctl(fd_frontend, FE_SET_VOLTAGE, SEC_VOLTAGE_18)); break;
- case cDiseqc::daMiniA: CHECK(ioctl(fd_frontend, FE_DISEQC_SEND_BURST, SEC_MINI_A)); break;
- case cDiseqc::daMiniB: CHECK(ioctl(fd_frontend, FE_DISEQC_SEND_BURST, SEC_MINI_B)); break;
- case cDiseqc::daCodes: CHECK(ioctl(fd_frontend, FE_DISEQC_SEND_MASTER_CMD, &cmd)); break;
+ case cDiseqc::daToneOff: if (d) CHECK(ioctl(fd_frontend, FE_SET_TONE, SEC_TONE_OFF)); break;
+ case cDiseqc::daToneOn: if (d) CHECK(ioctl(fd_frontend, FE_SET_TONE, SEC_TONE_ON)); break;
+ case cDiseqc::daVoltage13: if (d) CHECK(ioctl(fd_frontend, FE_SET_VOLTAGE, SEC_VOLTAGE_13)); break;
+ case cDiseqc::daVoltage18: if (d) CHECK(ioctl(fd_frontend, FE_SET_VOLTAGE, SEC_VOLTAGE_18)); break;
+ case cDiseqc::daMiniA: if (d) CHECK(ioctl(fd_frontend, FE_DISEQC_SEND_BURST, SEC_MINI_A)); break;
+ case cDiseqc::daMiniB: if (d) CHECK(ioctl(fd_frontend, FE_DISEQC_SEND_BURST, SEC_MINI_B)); break;
+ case cDiseqc::daCodes: if (d) CHECK(ioctl(fd_frontend, FE_DISEQC_SEND_MASTER_CMD, &cmd)); break;
+ case cDiseqc::daPositionN: if ((Positioner = GetPositioner()) != NULL) {
+ if (d) {
+ Positioner->GotoPosition(Diseqc->Position(), cSource::Position(channel.Source()));
+ Break = Positioner->IsMoving();
+ }
+ }
+ break;
+ case cDiseqc::daPositionA: if ((Positioner = GetPositioner()) != NULL) {
+ if (d) {
+ Positioner->GotoAngle(cSource::Position(channel.Source()));
+ Break = Positioner->IsMoving();
+ }
+ }
+ break;
+ case cDiseqc::daScr:
+ case cDiseqc::daWait: break;
default: esyslog("ERROR: unknown diseqc command %d", da);
}
+ if (Break)
+ diseqcOffset = i + 1;
}
- if (scr)
+ positioner = Positioner;
+ if (scr && !Break)
ResetToneAndVoltage(); // makes sure we don't block the bus!
if (Diseqc->IsScr())
Mutex.Unlock();
@@ -752,7 +794,7 @@ bool cDvbTuner::SetFrontend(void)
if (Setup.DiSEqC) {
if (const cDiseqc *diseqc = Diseqcs.Get(device->CardIndex() + 1, channel.Source(), frequency, dtp.Polarization(), &scr)) {
frequency -= diseqc->Lof();
- if (diseqc != lastDiseqc || diseqc->IsScr()) {
+ if (diseqc != lastDiseqc || diseqc->IsScr() || diseqc->Position() >= 0 && channel.Source() != lastSource) {
if (IsBondedMaster()) {
ExecuteDiseqc(diseqc, &frequency);
if (frequency == 0)
@@ -761,6 +803,7 @@ bool cDvbTuner::SetFrontend(void)
else
ResetToneAndVoltage();
lastDiseqc = diseqc;
+ lastSource = channel.Source();
}
}
else {
@@ -877,15 +920,30 @@ void cDvbTuner::Action(void)
int WaitTime = 1000;
switch (tunerStatus) {
case tsIdle:
- break;
+ break; // we want the TimedWait() below!
case tsSet:
- tunerStatus = SetFrontend() ? tsTuned : tsIdle;
- Timer.Set(tuneTimeout + (scr ? rand() % SCR_RANDOM_TIMEOUT : 0));
+ tunerStatus = SetFrontend() ? tsPositioning : tsIdle;
continue;
+ case tsPositioning:
+ if (positioner) {
+ if (positioner->IsMoving())
+ break; // we want the TimedWait() below!
+ else if (diseqcOffset) {
+ lastDiseqc = NULL;
+ tunerStatus = tsSet; // have it process the rest of the DiSEqC sequence
+ continue;
+ }
+ }
+ tunerStatus = tsTuned;
+ Timer.Set(tuneTimeout + (scr ? rand() % SCR_RANDOM_TIMEOUT : 0));
+ if (positioner)
+ continue;
+ // otherwise run directly into tsTuned...
case tsTuned:
if (Timer.TimedOut()) {
tunerStatus = tsSet;
lastDiseqc = NULL;
+ lastSource = 0;
if (time(NULL) - lastTimeoutReport > 60) { // let's not get too many of these
isyslog("frontend %d/%d timed out while tuning to channel %d, tp %d", adapter, frontend, channel.Number(), channel.Transponder());
lastTimeoutReport = time(NULL);
@@ -893,10 +951,12 @@ void cDvbTuner::Action(void)
continue;
}
WaitTime = 100; // allows for a quick change from tsTuned to tsLocked
+ // run into tsLocked...
case tsLocked:
if (Status & FE_REINIT) {
tunerStatus = tsSet;
lastDiseqc = NULL;
+ lastSource = 0;
isyslog("frontend %d/%d was reinitialized", adapter, frontend);
lastTimeoutReport = 0;
continue;
@@ -1357,7 +1417,7 @@ void cDvbDevice::UnBond(void)
bool cDvbDevice::BondingOk(const cChannel *Channel, bool ConsiderOccupied) const
{
cMutexLock MutexLock(&bondMutex);
- if (bondedDevice)
+ if (bondedDevice || Positioner())
return dvbTuner && dvbTuner->BondingOk(Channel, ConsiderOccupied);
return true;
}
@@ -1539,6 +1599,11 @@ int cDvbDevice::NumProvidedSystems(void) const
return numDeliverySystems + numModulations;
}
+const cPositioner *cDvbDevice::Positioner(void) const
+{
+ return dvbTuner ? dvbTuner->Positioner() : NULL;
+}
+
int cDvbDevice::SignalStrength(void) const
{
return dvbTuner ? dvbTuner->GetSignalStrength() : -1;