start rotor with 13V and static power limiting mode (LNBP21).. after 500msec switch...
authorAndreas Monzner <andreas.monzner@multimedia-labs.de>
Wed, 26 Oct 2005 08:14:11 +0000 (08:14 +0000)
committerAndreas Monzner <andreas.monzner@multimedia-labs.de>
Wed, 26 Oct 2005 08:14:11 +0000 (08:14 +0000)
TODO: change limiting mode should be done in driver.. not in userspace.. at the moment this is only working for the first tuner... (hardcoded i2c bus)

lib/dvb/frontend.cpp
lib/dvb/frontend.h
lib/dvb/sec.cpp
lib/dvb/sec.h

index 69519837c25d885bcf3fddbd8736f0be4d65f97d..a4ad170da539afd1279abbe75139b0c489d5d1c4 100644 (file)
@@ -204,7 +204,7 @@ RESULT eDVBFrontendParameters::getHash(unsigned long &hash) const
 
 DEFINE_REF(eDVBFrontend);
 
-eDVBFrontend::eDVBFrontend(int adap, int fe, int &ok): m_type(-1)
+eDVBFrontend::eDVBFrontend(int adap, int fe, int &ok): m_type(-1), m_curVoltage(-1)
 {
 #if HAVE_DVB_API_VERSION < 3
        char sec_filename[128];
@@ -435,8 +435,9 @@ void eDVBFrontend::tuneLoop()  // called by m_tuneTimer
                                        ++m_sec_sequence.current();
                                break;
                        case eSecCommand::SET_VOLTAGE:
-                               eDebug("[SEC] setVoltage %d", m_sec_sequence.current()->voltage);
-                               setVoltage(m_sec_sequence.current()++->voltage);
+                               int voltage = m_sec_sequence.current()++->voltage;
+                               eDebug("[SEC] setVoltage %d", voltage);
+                               setVoltage(voltage);
                                break;
                        case eSecCommand::SET_TONE:
                                eDebug("[SEC] setTone %d", m_sec_sequence.current()->tone);
@@ -444,10 +445,10 @@ void eDVBFrontend::tuneLoop()  // called by m_tuneTimer
                                break;
                        case eSecCommand::SEND_DISEQC:
                                sendDiseqc(m_sec_sequence.current()->diseqc);
-                               eDebugNoNewLine("sendDiseqc: ");
+                               eDebugNoNewLine("[SEC] sendDiseqc: ");
                                for (int i=0; i < m_sec_sequence.current()->diseqc.len; ++i)
                                    eDebugNoNewLine("%02x", m_sec_sequence.current()->diseqc.data[i]);
-                               eDebug("[SEC] ");
+                               eDebug("");
                                ++m_sec_sequence.current();
                                break;
                        case eSecCommand::SEND_TONEBURST:
@@ -460,10 +461,17 @@ void eDVBFrontend::tuneLoop()  // called by m_tuneTimer
                                ++m_sec_sequence.current();
                                break;
                        case eSecCommand::MEASURE_IDLE_INPUTPOWER:
-                               m_idleInputpower = readInputpower();
-                               eDebug("[SEC] idleInputpower is %d", m_idleInputpower);
-                               ++m_sec_sequence.current();
+                       {
+                               int idx = m_sec_sequence.current()++->val;
+                               if ( idx == 0 || idx == 1 )
+                               {
+                                       m_idleInputpower[idx] = readInputpower();
+                                       eDebug("[SEC] idleInputpower[%d] is %d", idx, m_idleInputpower[idx]);
+                               }
+                               else
+                                       eDebug("[SEC] idleInputpower measure index(%d) out of bound !!!", idx);
                                break;
+                       }
                        case eSecCommand::MEASURE_RUNNING_INPUTPOWER:
                                m_runningInputpower = readInputpower();
                                eDebug("[SEC] runningInputpower is %d", m_runningInputpower);
@@ -481,26 +489,57 @@ void eDVBFrontend::tuneLoop()  // called by m_tuneTimer
                                break;
                        case eSecCommand::IF_TIMEOUT_GOTO:
                                if (!m_timeoutCount)
+                               {
+                                       eDebug("[SEC] rotor timout");
                                        setSecSequencePos(m_sec_sequence.current()->steps);
+                               }
                                else
                                        ++m_sec_sequence.current();
                                break;
+                       case eSecCommand::SET_POWER_LIMITING_MODE:
+                       {
+                               int fd=::open("/dev/i2c/0", O_RDWR);
+                               unsigned char data[2];
+                               ::ioctl(fd, I2C_SLAVE_FORCE, 0x10 >> 1);
+                               if(::read(fd, data, 1) != 1)
+                                       eDebug("[SEC] error read lnbp (%m)");
+                               if ( m_sec_sequence.current()->mode == eSecCommand::modeStatic )
+                               {
+                                       data[0] |= 0x90;  // enable static current limiting
+                                       eDebug("[SEC] set static current limiting");
+                               }
+                               else
+                               {
+                                       data[0] &= ~0x90;  // enable dynamic current limiting
+                                       eDebug("[SEC] set dynamic current limiting");
+                               }
+                               if(::write(fd, data, 1) != 1)
+                                       eDebug("[SEC] error write lnbp (%m)");
+                               ::close(fd);
+                               ++m_sec_sequence.current();
+                               break;
+                       }
+                       case eSecCommand::IF_IDLE_INPUTPOWER_AVAIL_GOTO:
+                               if (m_idleInputpower[0] && m_idleInputpower[1] && setSecSequencePos(m_sec_sequence.current()->steps))
+                                       break;
+                               ++m_sec_sequence.current();
+                               break;
                        case eSecCommand::IF_INPUTPOWER_DELTA_GOTO:
                        {
+                               int idleInputpower = m_idleInputpower[m_curVoltage == iDVBFrontend::voltage13 ? 0 : 1];
                                eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
                                const char *txt = cmd.direction ? "running" : "stopped";
-                               eDebug("[SEC] waiting for rotor %s", txt);
-                               eDebug("[SEC] %s %d, idle %d, delta %d",
+                               eDebug("[SEC] waiting for rotor %s %d, idle %d, delta %d",
                                        txt,
                                        m_runningInputpower,
-                                       m_idleInputpower,
+                                       idleInputpower,
                                        cmd.deltaA);
-                               if ( (cmd.direction && abs(m_runningInputpower - m_idleInputpower) >= cmd.deltaA)
-                                       || (!cmd.direction && abs(m_runningInputpower - m_idleInputpower) <= cmd.deltaA) )
+                               if ( (cmd.direction && abs(m_runningInputpower - idleInputpower) >= cmd.deltaA)
+                                       || (!cmd.direction && abs(m_runningInputpower - idleInputpower) <= cmd.deltaA) )
                                {
                                        ++cmd.okcount;
                                        eDebug("[SEC] rotor %s step %d ok", txt, cmd.okcount);
-                                       if ( cmd.okcount > 1 )
+                                       if ( cmd.okcount > 6 )
                                        {
                                                eDebug("[SEC] rotor is %s", txt);
                                                if (setSecSequencePos(cmd.steps))
@@ -516,6 +555,14 @@ void eDVBFrontend::tuneLoop()  // called by m_tuneTimer
                                ++m_sec_sequence.current();
                                break;
                        }
+                       case eSecCommand::IF_VOLTAGE_GOTO:
+                       {
+                               eSecCommand::pair &compare = m_sec_sequence.current()->compare;
+                               if ( compare.voltage == m_curVoltage && setSecSequencePos(compare.steps) )
+                                       break;
+                               ++m_sec_sequence.current();
+                               break;
+                       }
                        default:
                                ++m_sec_sequence.current();
                                eDebug("[SEC] unhandled sec command");
@@ -725,6 +772,7 @@ RESULT eDVBFrontend::setVoltage(int voltage)
        fe_sec_voltage_t vlt;
 #endif
 
+       m_curVoltage=voltage;
        switch (voltage)
        {
        case voltageOff:
index a0ca08ece453afea50069715af335cca15625727..c091227bfbd844a78ffe594760bfe72b4a672d98 100644 (file)
@@ -62,9 +62,10 @@ class eDVBFrontend: public iDVBFrontend, public Object
                data[5] = curRotorCmd
                data[6] = curRotorPos */
 
-       int m_idleInputpower;
+       int m_idleInputpower[2];  // 13V .. 18V
        int m_runningInputpower;
        int m_timeoutCount; // needed for timeout
+       int m_curVoltage;
 
        void feEvent(int);
        void timeout();
index 876d7d292a1adf7748eb403500e135c3e7025aed..71f7c900ee7df56891cb392665609cc7376595fc 100644 (file)
@@ -149,7 +149,6 @@ RESULT eDVBSatelliteEquipmentControl::prepare(iDVBFrontend &frontend, FRONTENDPA
                                tone = iDVBFrontend::toneOff;
 
                        eSecCommandList sec_sequence;
-                       bool setVoltage=true;
 
                        if (di_param.m_diseqc_mode >= eDVBSatelliteDiseqcParameters::V1_0)
                        {
@@ -187,9 +186,12 @@ RESULT eDVBSatelliteEquipmentControl::prepare(iDVBFrontend &frontend, FRONTENDPA
                                if ( send_diseqc || changed_burst )
                                {
                                        sec_sequence.push_back( eSecCommand(eSecCommand::SET_TONE, iDVBFrontend::toneOff) );
+                                       eSecCommand::pair compare;
+                                       compare.voltage = voltage;
+                                       compare.steps = +3;
+                                       sec_sequence.push_back( eSecCommand(eSecCommand::IF_VOLTAGE_GOTO, compare) ); // voltage already correct ?
                                        sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, voltage) );
-                                       sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 30) );  // standard says 15 msek here
-                                       setVoltage=false;
+                                       sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 50) ); 
                                }
 
                                if ( send_diseqc )
@@ -329,6 +331,25 @@ RESULT eDVBSatelliteEquipmentControl::prepare(iDVBFrontend &frontend, FRONTENDPA
                                        }
                                        if ( RotorCmd != lastRotorCmd )
                                        {
+                                               if ( changed_burst || send_diseqc )
+                                               {
+                                                       // override first voltage change
+                                                       *(++(++sec_sequence.begin()))=eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13);
+                                                       // wait 1 second after first switch diseqc command
+                                                       sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 1000) );  
+                                               }
+                                               else  // no other diseqc commands before
+                                               {
+                                                       sec_sequence.push_back( eSecCommand(eSecCommand::SET_TONE, iDVBFrontend::toneOff) );
+                                                       sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 15) );  // wait 50msec after voltage change
+                                                       eSecCommand::pair compare;
+                                                       compare.voltage = voltage;
+                                                       compare.steps = +3;
+                                                       sec_sequence.push_back( eSecCommand(eSecCommand::IF_VOLTAGE_GOTO, compare) ); // voltage already correct ?
+                                                       sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
+                                                       sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 50) );  // wait 50msec after voltage change
+                                               }
+
                                                eDVBDiseqcCommand diseqc;
                                                diseqc.data[0] = 0xE0;
                                                diseqc.data[1] = 0x31;          // positioner
@@ -345,30 +366,47 @@ RESULT eDVBSatelliteEquipmentControl::prepare(iDVBFrontend &frontend, FRONTENDPA
                                                        diseqc.data[2] = 0x6B;  // goto stored sat position
                                                        diseqc.data[3] = RotorCmd;
                                                }
+
                                                if ( rotor_param.m_inputpower_parameters.m_use )
                                                { // use measure rotor input power to detect rotor state
-                                                       sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage18) ); // always turn with high voltage
-                                                       sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 50) );  // wait 50sec after voltage change
-                                                       sec_sequence.push_back( eSecCommand(eSecCommand::MEASURE_IDLE_INPUTPOWER) );
+                                                       eSecCommand::rotor cmd;
+// measure idle power values
+                                                       sec_sequence.push_back( eSecCommand(eSecCommand::IF_IDLE_INPUTPOWER_AVAIL_GOTO, +8) ); // already measured?
+                                                       sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 50) );  // wait 50msec after voltage change
+                                                       sec_sequence.push_back( eSecCommand(eSecCommand::MEASURE_IDLE_INPUTPOWER, 0) );
+                                                       sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage18) );
+                                                       sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 100) );  // wait 100msec before measure
+                                                       sec_sequence.push_back( eSecCommand(eSecCommand::MEASURE_IDLE_INPUTPOWER, 1) );
+                                                       sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) ); // back to lower voltage
+                                                       sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 50) );  // wait 50msec
+////////////////////////////
+                                                       sec_sequence.push_back( eSecCommand(eSecCommand::SET_POWER_LIMITING_MODE, eSecCommand::modeStatic) );
+                                                       sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 50) );  // wait 50msec after voltage change
                                                        sec_sequence.push_back( eSecCommand(eSecCommand::SEND_DISEQC, diseqc) );
-                                                       sec_sequence.push_back( eSecCommand(eSecCommand::SET_TIMEOUT, 8) );  // 2 seconds rotor start timout
-                                                       sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 250) );
+                                                       sec_sequence.push_back( eSecCommand(eSecCommand::SET_TIMEOUT, 40) );  // 2 seconds rotor start timout
+// rotor start loop
+                                                       sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 50) );  // 50msec delay
                                                        sec_sequence.push_back( eSecCommand(eSecCommand::MEASURE_RUNNING_INPUTPOWER) );
-                                                       eSecCommand::rotor cmd;
                                                        cmd.direction=1;  // check for running rotor
                                                        cmd.deltaA=rotor_param.m_inputpower_parameters.m_threshold;
                                                        cmd.steps=+3;
                                                        cmd.okcount=0;
-                                                       sec_sequence.push_back( eSecCommand(eSecCommand::IF_INPUTPOWER_DELTA_GOTO, cmd ) );
-                                                       sec_sequence.push_back( eSecCommand(eSecCommand::IF_TIMEOUT_GOTO, +8 ) );
-                                                       sec_sequence.push_back( eSecCommand(eSecCommand::GOTO, -4) );
-                                                       sec_sequence.push_back( eSecCommand(eSecCommand::SET_TIMEOUT, 240) );  // 1 minute running timeout
-                                                       sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 250) );
+                                                       sec_sequence.push_back( eSecCommand(eSecCommand::IF_INPUTPOWER_DELTA_GOTO, cmd ) );  // check if rotor has started
+                                                       sec_sequence.push_back( eSecCommand(eSecCommand::IF_TIMEOUT_GOTO, +11 ) );  // timeout ?
+                                                       sec_sequence.push_back( eSecCommand(eSecCommand::GOTO, -4) );  // goto loop start
+////////////////////
+                                                       sec_sequence.push_back( eSecCommand(eSecCommand::SET_TIMEOUT, 2400) );  // 2 minutes running timeout
+                                                       sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage18) );
+                                                       sec_sequence.push_back( eSecCommand(eSecCommand::SET_POWER_LIMITING_MODE, eSecCommand::modeDynamic) );
+// rotor running loop
+                                                       sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 50) );  // wait 50msec
                                                        sec_sequence.push_back( eSecCommand(eSecCommand::MEASURE_RUNNING_INPUTPOWER) );
                                                        cmd.direction=0;  // check for stopped rotor
+                                                       cmd.steps=+3;
                                                        sec_sequence.push_back( eSecCommand(eSecCommand::IF_INPUTPOWER_DELTA_GOTO, cmd ) );
-                                                       sec_sequence.push_back( eSecCommand(eSecCommand::IF_TIMEOUT_GOTO, +2 ) );
-                                                       sec_sequence.push_back( eSecCommand(eSecCommand::GOTO, -4) );
+                                                       sec_sequence.push_back( eSecCommand(eSecCommand::IF_TIMEOUT_GOTO, +3 ) );  // timeout ?
+                                                       sec_sequence.push_back( eSecCommand(eSecCommand::GOTO, -4) );  // running loop start
+/////////////////////
                                                        sec_sequence.push_back( eSecCommand(eSecCommand::UPDATE_CURRENT_ROTORPARAMS) );
                                                        frontend.setData(3, RotorCmd);
                                                        frontend.setData(4, sat.orbital_position);
@@ -379,11 +417,12 @@ RESULT eDVBSatelliteEquipmentControl::prepare(iDVBFrontend &frontend, FRONTENDPA
                                }
                        }
 
-                       if ( setVoltage )
-                       {
-                               sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, voltage) );
-                               sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 10) );
-                       }
+                       eSecCommand::pair compare;
+                       compare.voltage = voltage;
+                       compare.steps = +3;
+                       sec_sequence.push_back( eSecCommand(eSecCommand::IF_VOLTAGE_GOTO, compare) ); // voltage already correct ?
+                       sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, voltage) );
+                       sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 10) );
 
                        sec_sequence.push_back( eSecCommand(eSecCommand::SET_TONE, tone) );
                        sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 15) );
index 574fd9d6972b2a55a18ae32e0d83d2a0e8085bbd..0b06afc609096f7b057dec37f5cd86aa9f170e86 100644 (file)
@@ -8,12 +8,15 @@
 class eSecCommand
 {
 public:
+       enum { modeStatic, modeDynamic };
        enum {
                NONE, SLEEP, SET_VOLTAGE, SET_TONE, GOTO,
                SEND_DISEQC, SEND_TONEBURST, SET_FRONTEND,
                MEASURE_IDLE_INPUTPOWER, MEASURE_RUNNING_INPUTPOWER,
                IF_TIMEOUT_GOTO, IF_INPUTPOWER_DELTA_GOTO,
-               UPDATE_CURRENT_ROTORPARAMS, SET_TIMEOUT
+               UPDATE_CURRENT_ROTORPARAMS, SET_TIMEOUT,
+               IF_IDLE_INPUTPOWER_AVAIL_GOTO, SET_POWER_LIMITING_MODE,
+               IF_VOLTAGE_GOTO
        };
        int cmd;
        struct rotor
@@ -23,6 +26,11 @@ public:
                int steps;    // goto steps
                int direction;
        };
+       struct pair
+       {
+               int voltage;
+               int steps;
+       };
        union
        {
                int val;
@@ -32,8 +40,10 @@ public:
                int tone;
                int toneburst;
                int msec;
+               int mode;
                rotor measure;
                eDVBDiseqcCommand diseqc;
+               pair compare;
        };
        eSecCommand( int cmd )
                :cmd(cmd)
@@ -47,6 +57,9 @@ public:
        eSecCommand( int cmd, rotor measure )
                :cmd(cmd), measure(measure)
        {}
+       eSecCommand( int cmd, pair compare )
+               :cmd(cmd), compare(compare)
+       {}
        eSecCommand()
                :cmd(NONE)
        {}