lib/dvb/sec.cpp: fixed typo (LOF/tuner frequency check was broken since latest unicab...
[vuplus_dvbapp] / lib / dvb / sec.cpp
index ac1a202..a8292c0 100644 (file)
@@ -37,7 +37,7 @@ void eDVBSatelliteEquipmentControl::setParam(int param, int value)
 }
 
 eDVBSatelliteEquipmentControl::eDVBSatelliteEquipmentControl(eSmartPtrList<eDVBRegisteredFrontend> &avail_frontends, eSmartPtrList<eDVBRegisteredFrontend> &avail_simulate_frontends)
-       :m_lnbidx((sizeof(m_lnbs) / sizeof(eDVBSatelliteLNBParameters))-1), m_curSat(m_lnbs[0].m_satellites.end()), m_avail_frontends(avail_frontends), m_avail_simulate_frontends(avail_simulate_frontends), m_rotorMoving(false)
+       :m_lnbidx((sizeof(m_lnbs) / sizeof(eDVBSatelliteLNBParameters))-1), m_curSat(m_lnbs[0].m_satellites.end()), m_avail_frontends(avail_frontends), m_avail_simulate_frontends(avail_simulate_frontends), m_rotorMoving(0)
 {
        if (!instance)
                instance = this;
@@ -60,6 +60,44 @@ int eDVBSatelliteEquipmentControl::canTune(const eDVBFrontendParametersSatellite
        bool simulate = ((eDVBFrontend*)fe)->is_simulate();
        bool direct_connected = m_not_linked_slot_mask & slot_id;
        int score=0, satcount=0;
+       long linked_prev_ptr=-1, linked_next_ptr=-1, linked_csw=-1, linked_ucsw=-1, linked_toneburst=-1,
+               fe_satpos_depends_ptr=-1, fe_rotor_pos=-1;
+       bool linked_in_use = false;
+
+       eSecDebugNoSimulate("direct_connected %d", !!direct_connected);
+
+       fe->getData(eDVBFrontend::LINKED_PREV_PTR, linked_prev_ptr);
+       fe->getData(eDVBFrontend::LINKED_NEXT_PTR, linked_next_ptr);
+       fe->getData(eDVBFrontend::SATPOS_DEPENDS_PTR, fe_satpos_depends_ptr);
+
+       // first we search the linkage base frontend and check if any tuner in prev direction is used
+       while (linked_prev_ptr != -1)
+       {
+               eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*) linked_prev_ptr;
+               if (linked_fe->m_inuse)
+                       linked_in_use = true;
+               fe = linked_fe->m_frontend;
+               linked_fe->m_frontend->getData(eDVBFrontend::LINKED_PREV_PTR, (long&)linked_prev_ptr);
+       }
+
+       fe->getData(eDVBFrontend::ROTOR_POS, fe_rotor_pos);
+
+       // now check also the linked tuners  is in use
+       while (!linked_in_use && linked_next_ptr != -1)
+       {
+               eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*) linked_next_ptr;
+               if (linked_fe->m_inuse)
+                       linked_in_use = true;
+               linked_fe->m_frontend->getData(eDVBFrontend::LINKED_NEXT_PTR, (long&)linked_next_ptr);
+       }
+
+       // when a linked in use tuner is found we get the tuner data...
+       if (linked_in_use)
+       {
+               fe->getData(eDVBFrontend::CSW, linked_csw);
+               fe->getData(eDVBFrontend::UCSW, linked_ucsw);
+               fe->getData(eDVBFrontend::TONEBURST, linked_toneburst);
+       }
 
        if (highest_score_lnb)
                *highest_score_lnb = -1;
@@ -70,6 +108,9 @@ int eDVBSatelliteEquipmentControl::canTune(const eDVBFrontendParametersSatellite
        {
                bool rotor=false;
                eDVBSatelliteLNBParameters &lnb_param = m_lnbs[idx];
+               bool is_unicable = lnb_param.SatCR_idx != -1;
+               bool is_unicable_position_switch = lnb_param.SatCR_positions > 1;
+
                if ( lnb_param.m_slot_mask & slot_id ) // lnb for correct tuner?
                {
                        int ret = 0;
@@ -85,17 +126,13 @@ int eDVBSatelliteEquipmentControl::canTune(const eDVBFrontendParametersSatellite
                        {
                                bool diseqc=false;
                                long band=0,
-                                       linked_prev_ptr=-1,
-                                       linked_next_ptr=-1,
-                                       satpos_depends_ptr=-1,
+                                       satpos_depends_ptr=fe_satpos_depends_ptr,
                                        csw = di_param.m_committed_cmd,
                                        ucsw = di_param.m_uncommitted_cmd,
                                        toneburst = di_param.m_toneburst_param,
-                                       curRotorPos;
+                                       rotor_pos = fe_rotor_pos;
 
                                eSecDebugNoSimulate("sat %d found", sat.orbital_position);
-                               fe->getData(eDVBFrontend::LINKED_PREV_PTR, linked_prev_ptr);
-                               fe->getData(eDVBFrontend::SATPOS_DEPENDS_PTR, satpos_depends_ptr);
 
                                if ( sat.frequency > lnb_param.m_lof_threshold )
                                        band |= 1;
@@ -114,7 +151,7 @@ int eDVBSatelliteEquipmentControl::canTune(const eDVBFrontendParametersSatellite
                                        if ( di_param.m_diseqc_mode == eDVBSatelliteDiseqcParameters::V1_2 )  // ROTOR
                                                rotor = true;
 
-                                       ret=10000;
+                                       ret = 10000;
                                }
                                else
                                {
@@ -122,109 +159,66 @@ int eDVBSatelliteEquipmentControl::canTune(const eDVBFrontendParametersSatellite
                                        ret = 15000;
                                }
 
+                               if (sat.no_rotor_command_on_tune && !rotor) {
+                                       eSecDebugNoSimulate("no rotor but no_rotor_command_on_tune is set.. ignore lnb %d", idx);
+                                       continue;
+                               }
+
                                eSecDebugNoSimulate("ret1 %d", ret);
 
-                               if (direct_connected)  // frontend with direct connection?
+                               if (linked_in_use && !is_unicable)
                                {
-                                       long ocsw = -1,
-                                               oucsw = -1,
-                                               oToneburst = -1;
-                                       eSecDebugNoSimulate("direct");
-                                       fe->getData(eDVBFrontend::ROTOR_POS, curRotorPos);
-                                       fe->getData(eDVBFrontend::LINKED_NEXT_PTR, linked_next_ptr);
-                                       fe->getData(eDVBFrontend::CSW, ocsw);
-                                       fe->getData(eDVBFrontend::UCSW, oucsw);
-                                       fe->getData(eDVBFrontend::TONEBURST, oToneburst);
-                                       while (ret && linked_prev_ptr != -1)  // check for linked tuners..
+                                       // compare tuner data
+                                       if ( (csw != linked_csw) ||
+                                               ( diseqc && (ucsw != linked_ucsw || toneburst != linked_toneburst) ) ||
+                                               ( rotor && rotor_pos != sat.orbital_position ) )
                                        {
-                                               eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*) linked_prev_ptr;
-                                               if (linked_fe->m_inuse)
-                                               {
-                                                       if ( (csw != ocsw) ||
-                                                               ( diseqc && (ucsw != oucsw || toneburst != oToneburst) ) ||
-                                                               ( rotor && curRotorPos != sat.orbital_position ) )
-                                                       {
-                                                               ret=0;
-                                                       }
-                                               }
-                                               linked_fe->m_frontend->getData(eDVBFrontend::LINKED_PREV_PTR, (long&)linked_prev_ptr);
+                                               ret = 0;
                                        }
+                                       else
+                                               ret += 15;
                                        eSecDebugNoSimulate("ret2 %d", ret);
-                                       while (ret && linked_next_ptr != -1)  // check for linked tuners..
-                                       {
-                                               eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*) linked_next_ptr;
-                                               if (linked_fe->m_inuse)
-                                               {
-                                                       if ( (csw != ocsw) ||
-                                                               ( diseqc && (ucsw != oucsw || toneburst != oToneburst) ) ||
-                                                               ( rotor && curRotorPos != sat.orbital_position ) )
-                                                       {
-                                                               ret=0;
-                                                       }
-                                               }
-                                               linked_fe->m_frontend->getData(eDVBFrontend::LINKED_NEXT_PTR, (long&)linked_next_ptr);
-                                       }
-                                       eSecDebugNoSimulate("ret3 %d", ret);
                                }
-                               else // linked frontend..
+                               else if ((satpos_depends_ptr != -1) && !(is_unicable && is_unicable_position_switch))
                                {
-                                       long ocsw = -1,
-                                               oucsw = -1,
-                                               oToneburst = -1;
-                                       while (linked_prev_ptr != -1)
+                                       eSecDebugNoSimulate("satpos depends");
+                                       eDVBRegisteredFrontend *satpos_depends_to_fe = (eDVBRegisteredFrontend*) satpos_depends_ptr;
+                                       if (direct_connected) // current fe is direct connected.. (can turn the rotor)
                                        {
-                                               eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*) linked_prev_ptr;
-                                               linked_fe->m_frontend->getData(eDVBFrontend::LINKED_PREV_PTR, (long&)linked_prev_ptr);
-                                               if (linked_prev_ptr == -1)
+                                               if (satpos_depends_to_fe->m_inuse) // if the dependent frontend is in use?
                                                {
-                                                       iDVBFrontend *sec_fe = linked_fe->m_frontend;
-                                                       sec_fe->getData(eDVBFrontend::ROTOR_POS, curRotorPos);
-                                                       if (linked_fe->m_inuse)
-                                                       {
-                                                               sec_fe->getData(eDVBFrontend::CSW, ocsw);
-                                                               sec_fe->getData(eDVBFrontend::UCSW, oucsw);
-                                                               sec_fe->getData(eDVBFrontend::TONEBURST, oToneburst);
-                                                               eSecDebug("(%ld != %ld) || \n(%d && (%ld != %ld || %ld != %ld) ) ||\n( %d && %ld != %d ) )",
-                                                                       csw, ocsw, diseqc, ucsw, oucsw, toneburst, oToneburst, rotor, curRotorPos, sat.orbital_position);
-                                                               if ( (csw != ocsw) ||
-                                                                       ( diseqc && (ucsw != oucsw || toneburst != oToneburst) ) ||
-                                                                       ( rotor && curRotorPos != sat.orbital_position ) )
-                                                               {
-                                                                       ret=0;
-                                                               }
-                                                       }
+                                                       if (!rotor || rotor_pos != sat.orbital_position) // new orbital position not equal to current orbital pos?
+                                                               ret = 0;
+                                                       else
+                                                               ret += 10;
                                                }
+                                               eSecDebugNoSimulate("ret3 %d", ret);
                                        }
-                                       eSecDebugNoSimulate("ret4 %d", ret);
-                               }
-
-                               if (ret)
-                                       if (satpos_depends_ptr != -1)
+                                       else // current fe is dependent of another tuner ... (so this fe can't turn the rotor!)
                                        {
-                                               eSecDebugNoSimulate("satpos depends");
-                                               eDVBRegisteredFrontend *satpos_depends_to_fe = (eDVBRegisteredFrontend*) satpos_depends_ptr;
-                                               if ( satpos_depends_to_fe->m_inuse )
+                                               // get current orb pos of the tuner with rotor connection
+                                               satpos_depends_to_fe->m_frontend->getData(eDVBFrontend::ROTOR_POS, rotor_pos);
+                                               if (!rotor || rotor_pos == -1 /* we dont know the rotor position yet */
+                                                       || rotor_pos != sat.orbital_position ) // not the same orbital position?
                                                {
-                                                       if (!direct_connected)
-                                                               satpos_depends_to_fe->m_frontend->getData(eDVBFrontend::ROTOR_POS, curRotorPos);
-                                                       if (!rotor || curRotorPos != sat.orbital_position)
-                                                               ret=0;
+                                                       ret = 0;
                                                }
-                                               eSecDebugNoSimulate("ret5 %d", ret);
                                        }
+                                       eSecDebugNoSimulate("ret4 %d", ret);
+                               }
 
-                               if (ret && rotor && curRotorPos != -1)
-                                       ret -= abs(curRotorPos-sat.orbital_position);
+                               if (ret && rotor && rotor_pos != -1)
+                                       ret -= abs(rotor_pos-sat.orbital_position);
 
-                               eSecDebugNoSimulate("ret6 %d", ret);
+                               eSecDebugNoSimulate("ret5 %d", ret);
 
-                               if (ret)
+                               if (ret && lnb_param.SatCR_idx == -1)
                                {
                                        int lof = sat.frequency > lnb_param.m_lof_threshold ?
                                                lnb_param.m_lof_hi : lnb_param.m_lof_lo;
                                        int tuner_freq = abs(sat.frequency - lof);
                                        if (tuner_freq < 900000 || tuner_freq > 2200000)
-                                               ret=0;
+                                               ret = 0;
                                }
 
                                if (ret && lnb_param.m_prio != -1)
@@ -314,7 +308,6 @@ RESULT eDVBSatelliteEquipmentControl::prepare(iDVBFrontend &frontend, FRONTENDPA
                        eDVBSatelliteSwitchParameters &sw_param = sit->second;
                        bool doSetFrontend = true;
                        bool doSetVoltageToneFrontend = true;
-                       bool forceStaticMode = true;
                        bool forceChanged = false;
                        bool needDiSEqCReset = false;
                        long band=0,
@@ -385,8 +378,8 @@ RESULT eDVBSatelliteEquipmentControl::prepare(iDVBFrontend &frontend, FRONTENDPA
                        {
                        // calc Frequency
                                local = abs(sat.frequency 
-                                       - ((lof - (lof % 1000)) + ((lof % 1000)>500 ? 1000 : 0)) ); //TODO für den Mist mal ein Macro schreiben
-                               parm.FREQUENCY = (local - (local % 125)) + ((local % 125)>62 ? 125 : 0);
+                                       - lof);
+                               parm.FREQUENCY = ((((local * 2) / 125) + 1) / 2) * 125;
                                frontend.setData(eDVBFrontend::FREQ_OFFSET, sat.frequency - parm.FREQUENCY);
 
                                if ( voltage_mode == eDVBSatelliteSwitchParameters::_14V
@@ -406,20 +399,21 @@ RESULT eDVBSatelliteEquipmentControl::prepare(iDVBFrontend &frontend, FRONTENDPA
                        }
                        else
                        {
-                               unsigned int tmp = abs(sat.frequency 
-                                               - ((lof - (lof % 1000)) + ((lof % 1000)>500 ? 1000 : 0)) )
+                               int tmp1 = abs(sat.frequency 
+                                               -lof)
                                                + lnb_param.SatCRvco
                                                - 1400000
                                                + lnb_param.guard_offset;
-                               parm.FREQUENCY = (lnb_param.SatCRvco - (tmp % 4000))+((tmp%4000)>2000?4000:0)+lnb_param.guard_offset;
-                               lnb_param.UnicableTuningWord = (((tmp / 4000)+((tmp%4000)>2000?1:0)) 
+                               int tmp2 = ((((tmp1 * 2) / 4000) + 1) / 2) * 4000;
+                               parm.FREQUENCY = lnb_param.SatCRvco - (tmp1-tmp2) + lnb_param.guard_offset;
+                               lnb_param.UnicableTuningWord = ((tmp2 / 4000) 
                                                | ((band & 1) ? 0x400 : 0)                      //HighLow
                                                | ((band & 2) ? 0x800 : 0)                      //VertHor
                                                | ((lnb_param.LNBNum & 1) ? 0 : 0x1000)                 //Umschaltung LNB1 LNB2
                                                | (lnb_param.SatCR_idx << 13));         //Adresse des SatCR
                                                eDebug("[prepare] UnicableTuningWord %#04x",lnb_param.UnicableTuningWord);
                                                eDebug("[prepare] guard_offset %d",lnb_param.guard_offset);
-                               frontend.setData(eDVBFrontend::FREQ_OFFSET, sat.frequency - ((lnb_param.UnicableTuningWord & 0x3FF) *4000 + 1400000 - lnb_param.SatCRvco + lof));
+                               frontend.setData(eDVBFrontend::FREQ_OFFSET, (lnb_param.UnicableTuningWord & 0x3FF) *4000 + 1400000 + lof - (2 * (lnb_param.SatCRvco - (tmp1-tmp2))) );
                        }
 
                        if (diseqc_mode >= eDVBSatelliteDiseqcParameters::V1_0)
@@ -563,7 +557,7 @@ RESULT eDVBSatelliteEquipmentControl::prepare(iDVBFrontend &frontend, FRONTENDPA
                                                compare.tone = iDVBFrontend::toneOff;
                                                sec_sequence.push_back( eSecCommand(eSecCommand::IF_TONE_GOTO, compare) );
                                                sec_sequence.push_back( eSecCommand(eSecCommand::SET_TONE, iDVBFrontend::toneOff) );
-                                               sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_CONT_TONE]) );
+                                               sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_CONT_TONE_DISABLE_BEFORE_DISEQC]) );
 
                                                if (diseqc13V)
                                                        vlt = iDVBFrontend::voltage13;
@@ -705,7 +699,7 @@ RESULT eDVBSatelliteEquipmentControl::prepare(iDVBFrontend &frontend, FRONTENDPA
                                                        compare.tone = iDVBFrontend::toneOff;
                                                        sec_sequence.push_back( eSecCommand(eSecCommand::IF_TONE_GOTO, compare) );
                                                        sec_sequence.push_back( eSecCommand(eSecCommand::SET_TONE, iDVBFrontend::toneOff) );
-                                                       sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_CONT_TONE]) );
+                                                       sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_CONT_TONE_DISABLE_BEFORE_DISEQC]) );
 
                                                        compare.voltage = iDVBFrontend::voltageOff;
                                                        compare.steps = +4;
@@ -753,9 +747,10 @@ RESULT eDVBSatelliteEquipmentControl::prepare(iDVBFrontend &frontend, FRONTENDPA
                                                        diseqc.data[3] = RotorCmd;
                                                        diseqc.data[4] = 0x00;
                                                }
-                                               if(lnb_param.SatCR_idx == -1)
+//                                             if(lnb_param.SatCR_idx == -1)
                                                {
-                                                       if ( rotor_param.m_inputpower_parameters.m_use )
+                                                       int mrt = m_params[MOTOR_RUNNING_TIMEOUT]; // in seconds!
+                                                       if ( rotor_param.m_inputpower_parameters.m_use || lnb_param.SatCR_idx == -1)
                                                        { // use measure rotor input power to detect rotor state
                                                                bool turn_fast = need_turn_fast(rotor_param.m_inputpower_parameters.m_turning_speed);
                                                                eSecCommand::rotor cmd;
@@ -801,7 +796,7 @@ RESULT eDVBSatelliteEquipmentControl::prepare(iDVBFrontend &frontend, FRONTENDPA
                                                                sec_sequence.push_back( eSecCommand(eSecCommand::SET_ROTOR_MOVING) );
                                                                if (turn_fast)
                                                                        sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, VOLTAGE(18)) );
-                                                               sec_sequence.push_back( eSecCommand(eSecCommand::SET_TIMEOUT, m_params[MOTOR_RUNNING_TIMEOUT]*20) );  // 2 minutes running timeout
+                                                               sec_sequence.push_back( eSecCommand(eSecCommand::SET_TIMEOUT, mrt*20) );  // mrt is in seconds... our SLEEP time is 50ms.. so * 20
        // rotor running loop
                                                                sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 50) );  // wait 50msec
                                                                sec_sequence.push_back( eSecCommand(eSecCommand::MEASURE_RUNNING_INPUTPOWER) );
@@ -816,6 +811,17 @@ RESULT eDVBSatelliteEquipmentControl::prepare(iDVBFrontend &frontend, FRONTENDPA
                                                        }
                                                        else
                                                        {  // use normal turning mode
+                                                               if (curRotorPos != -1)
+                                                               {               
+                                                                       mrt = abs(curRotorPos - sat.orbital_position);
+                                                                       if (mrt > 1800)
+                                                                               mrt = 3600 - mrt;
+                                                                       if (mrt % 10)
+                                                                               mrt += 10; // round a little bit
+                                                                       mrt *= 2000;  // (we assume a very slow rotor with just 0.5 degree per second here)
+                                                                       mrt /= 10000;
+                                                                       mrt += 3; // a little bit overhead
+                                                               }
                                                                doSetVoltageToneFrontend=false;
                                                                doSetFrontend=false;
                                                                eSecCommand::rotor cmd;
@@ -829,37 +835,40 @@ RESULT eDVBSatelliteEquipmentControl::prepare(iDVBFrontend &frontend, FRONTENDPA
                                                                sec_sequence.push_back( eSecCommand(eSecCommand::INVALIDATE_CURRENT_ROTORPARMS) );
                                                                sec_sequence.push_back( eSecCommand(eSecCommand::SET_ROTOR_MOVING) );
                                                                sec_sequence.push_back( eSecCommand(eSecCommand::SEND_DISEQC, diseqc) );
-       
+                                                               sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 1000) ); // sleep one second before change voltage or tone
+
                                                                compare.voltage = voltage;
                                                                compare.steps = +3;
                                                                sec_sequence.push_back( eSecCommand(eSecCommand::IF_VOLTAGE_GOTO, compare) ); // correct final voltage?
                                                                sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 2000) );  // wait 2 second before set high voltage
                                                                sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, voltage) );
-       
+
                                                                compare.tone = tone;
                                                                sec_sequence.push_back( eSecCommand(eSecCommand::IF_TONE_GOTO, compare) );
                                                                sec_sequence.push_back( eSecCommand(eSecCommand::SET_TONE, tone) );
-                                                               sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_CONT_TONE]) );
-                                                               sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
+                                                               sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_FINAL_CONT_TONE_CHANGE]) );
+                                                               sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND, 0) );
        
                                                                cmd.direction=1;  // check for running rotor
                                                                cmd.deltaA=0;
-                                                               cmd.steps=+3;
+                                                               cmd.steps = +3;
                                                                cmd.okcount=0;
-                                                               sec_sequence.push_back( eSecCommand(eSecCommand::SET_TIMEOUT, m_params[MOTOR_RUNNING_TIMEOUT]*4) );  // 2 minutes running timeout
+                                                               sec_sequence.push_back( eSecCommand(eSecCommand::SET_TIMEOUT, mrt*4) );  // mrt is in seconds... our SLEEP time is 250ms.. so * 4
                                                                sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 250) );  // 250msec delay
                                                                sec_sequence.push_back( eSecCommand(eSecCommand::IF_TUNER_LOCKED_GOTO, cmd ) );
-                                                               sec_sequence.push_back( eSecCommand(eSecCommand::IF_TIMEOUT_GOTO, +3 ) ); 
+                                                               sec_sequence.push_back( eSecCommand(eSecCommand::IF_TIMEOUT_GOTO, +5 ) );
                                                                sec_sequence.push_back( eSecCommand(eSecCommand::GOTO, -3) );  // goto loop start
                                                                sec_sequence.push_back( eSecCommand(eSecCommand::UPDATE_CURRENT_ROTORPARAMS) );
                                                                sec_sequence.push_back( eSecCommand(eSecCommand::SET_ROTOR_STOPPED) );
-                                                               sec_sequence.push_back( eSecCommand(eSecCommand::GOTO, +3) );
-                                                               sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
-                                                               sec_sequence.push_back( eSecCommand(eSecCommand::GOTO, -4) );
+                                                               sec_sequence.push_back( eSecCommand(eSecCommand::GOTO, +4) );
+                                                               sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, tunetimeout) );
+                                                               sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND, 1) );
+                                                               sec_sequence.push_back( eSecCommand(eSecCommand::GOTO, -5) );
                                                        }
+                                                       eDebug("set rotor timeout to %d seconds", mrt);
+                                                       sec_fe->setData(eDVBFrontend::NEW_ROTOR_CMD, RotorCmd);
+                                                       sec_fe->setData(eDVBFrontend::NEW_ROTOR_POS, sat.orbital_position);
                                                }
-                                               sec_fe->setData(eDVBFrontend::NEW_ROTOR_CMD, RotorCmd);
-                                               sec_fe->setData(eDVBFrontend::NEW_ROTOR_POS, sat.orbital_position);
                                        }
                                }
                        }
@@ -884,7 +893,7 @@ RESULT eDVBSatelliteEquipmentControl::prepare(iDVBFrontend &frontend, FRONTENDPA
                                compare.tone = tone;
                                sec_sequence.push_back( eSecCommand(eSecCommand::IF_TONE_GOTO, compare) );
                                sec_sequence.push_back( eSecCommand(eSecCommand::SET_TONE, tone) );
-                               sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_CONT_TONE]) );
+                               sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_FINAL_CONT_TONE_CHANGE]) );
                        }
 
                        sec_sequence.push_back( eSecCommand(eSecCommand::UPDATE_CURRENT_SWITCHPARMS) );
@@ -897,11 +906,11 @@ RESULT eDVBSatelliteEquipmentControl::prepare(iDVBFrontend &frontend, FRONTENDPA
                                compare.voltage = iDVBFrontend::voltageOff;
                                sec_sequence.push_back( eSecCommand(eSecCommand::IF_NOT_VOLTAGE_GOTO, compare) );
                                sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
-                               sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 50 ) );
+                               sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_ENABLE_VOLTAGE_BEFORE_SWITCH_CMDS] ) );
 
                                sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage18_5) );
                                sec_sequence.push_back( eSecCommand(eSecCommand::SET_TONE, iDVBFrontend::toneOff) );
-                               sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_VOLTAGE_CHANGE_BEFORE_MOTOR_CMD]) );  // wait 150msec after voltage change
+                               sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_VOLTAGE_CHANGE_BEFORE_SWITCH_CMDS]) );  // wait 20 ms after voltage change
        
                                eDVBDiseqcCommand diseqc;
                                memset(diseqc.data, 0, MAX_DISEQC_LENGTH);
@@ -920,14 +929,13 @@ RESULT eDVBSatelliteEquipmentControl::prepare(iDVBFrontend &frontend, FRONTENDPA
                        if (doSetFrontend)
                        {
                                sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, tunetimeout) );
-                               sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
-                       }
-                               
-                       if (forceStaticMode)
-                       {
-                               sec_sequence.push_front( eSecCommand(eSecCommand::SET_POWER_LIMITING_MODE, eSecCommand::modeStatic) );
-                               sec_sequence.push_back( eSecCommand(eSecCommand::SET_POWER_LIMITING_MODE, eSecCommand::modeDynamic) );
+                               sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND, 1) );
                        }
+
+                       sec_sequence.push_front( eSecCommand(eSecCommand::SET_POWER_LIMITING_MODE, eSecCommand::modeStatic) );
+                       sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 500) );
+                       sec_sequence.push_back( eSecCommand(eSecCommand::SET_POWER_LIMITING_MODE, eSecCommand::modeDynamic) );
+
                        frontend.setSecSequence(sec_sequence);
 
                        return 0;
@@ -946,6 +954,40 @@ RESULT eDVBSatelliteEquipmentControl::prepare(iDVBFrontend &frontend, FRONTENDPA
        return -1;
 }
 
+void eDVBSatelliteEquipmentControl::prepareTurnOffSatCR(iDVBFrontend &frontend, int satcr)
+{
+       eSecCommandList sec_sequence;
+
+       // check if voltage is disabled
+       eSecCommand::pair compare;
+       compare.steps = +9;     //only close frontend
+       compare.voltage = iDVBFrontend::voltageOff;
+
+       sec_sequence.push_back( eSecCommand(eSecCommand::IF_VOLTAGE_GOTO, compare) );
+       sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
+       sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_ENABLE_VOLTAGE_BEFORE_SWITCH_CMDS]) );
+
+       sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage18_5) );
+       sec_sequence.push_back( eSecCommand(eSecCommand::SET_TONE, iDVBFrontend::toneOff) );
+       sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_VOLTAGE_CHANGE_BEFORE_SWITCH_CMDS]) );
+
+       eDVBDiseqcCommand diseqc;
+       memset(diseqc.data, 0, MAX_DISEQC_LENGTH);
+       diseqc.len = 5;
+       diseqc.data[0] = 0xE0;
+       diseqc.data[1] = 0x10;
+       diseqc.data[2] = 0x5A;
+       diseqc.data[3] = satcr << 5;
+       diseqc.data[4] = 0x00;
+
+       sec_sequence.push_back( eSecCommand(eSecCommand::SEND_DISEQC, diseqc) );
+       sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_LAST_DISEQC_CMD]) );
+       sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
+       sec_sequence.push_back( eSecCommand(eSecCommand::DELAYED_CLOSE_FRONTEND) );
+
+       frontend.setSecSequence(sec_sequence);
+}
+
 RESULT eDVBSatelliteEquipmentControl::clear()
 {
        eSecDebug("eDVBSatelliteEquipmentControl::clear()");
@@ -963,7 +1005,8 @@ RESULT eDVBSatelliteEquipmentControl::clear()
        for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(m_avail_frontends.begin()); it != m_avail_frontends.end(); ++it)
        {
                long tmp;
-               if (!strcmp(it->m_frontend->getDescription(), "BCM4501 (internal)") && !it->m_frontend->getData(eDVBFrontend::LINKED_PREV_PTR, tmp) && tmp != -1)
+               char c;
+               if (sscanf(it->m_frontend->getDescription(), "BCM450%c (internal)", &c) == 1 && !it->m_frontend->getData(eDVBFrontend::LINKED_PREV_PTR, tmp) && tmp != -1)
                {
                        FILE *f=fopen("/proc/stb/tsmux/lnb_b_input", "w");
                        if (!f || fwrite("B", 1, 1, f) != 1)
@@ -1249,6 +1292,26 @@ RESULT eDVBSatelliteEquipmentControl::setLNBSatCRvco(int SatCRvco)
                return -ENOENT;
        return 0;
 }
+
+RESULT eDVBSatelliteEquipmentControl::setLNBSatCRpositions(int SatCR_positions)
+{
+       eSecDebug("eDVBSatelliteEquipmentControl::setLNBSatCRpositions(%d)", SatCR_positions);
+       if(SatCR_positions < 1 || SatCR_positions > 2)
+               return -EPERM;
+       if ( currentLNBValid() )
+               m_lnbs[m_lnbidx].SatCR_positions = SatCR_positions;
+       else
+               return -ENOENT;
+       return 0;
+}
+
+RESULT eDVBSatelliteEquipmentControl::getLNBSatCRpositions()
+{
+       if ( currentLNBValid() )
+               return m_lnbs[m_lnbidx].SatCR_positions;
+       return -ENOENT;
+}
+
 RESULT eDVBSatelliteEquipmentControl::getLNBSatCR()
 {
        if ( currentLNBValid() )
@@ -1372,8 +1435,8 @@ RESULT eDVBSatelliteEquipmentControl::setTunerLinked(int tu1, int tu2)
        if (tu1 != tu2)
        {
                eDVBRegisteredFrontend *p1=NULL, *p2=NULL;
-
-               for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(m_avail_frontends.begin()); it != m_avail_frontends.end(); ++it)
+               eSmartPtrList<eDVBRegisteredFrontend>::iterator it(m_avail_frontends.begin());
+               for (; it != m_avail_frontends.end(); ++it)
                {
                        if (it->m_frontend->getSlotID() == tu1)
                                p1 = *it;
@@ -1382,9 +1445,10 @@ RESULT eDVBSatelliteEquipmentControl::setTunerLinked(int tu1, int tu2)
                }
                if (p1 && p2)
                {
+                       char c;
                        p1->m_frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)p2);
                        p2->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)p1);
-                       if (!strcmp(p1->m_frontend->getDescription(), p2->m_frontend->getDescription()) && !strcmp(p1->m_frontend->getDescription(), "BCM4501 (internal)"))
+                       if (!strcmp(p1->m_frontend->getDescription(), p2->m_frontend->getDescription()) && sscanf(p1->m_frontend->getDescription(), "BCM450%c (internal)", &c) == 1)
                        {
                                FILE *f=fopen("/proc/stb/tsmux/lnb_b_input", "w");
                                if (!f || fwrite("A", 1, 1, f) != 1)
@@ -1398,7 +1462,8 @@ RESULT eDVBSatelliteEquipmentControl::setTunerLinked(int tu1, int tu2)
                }
 
                p1=p2=NULL;
-               for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(m_avail_simulate_frontends.begin()); it != m_avail_simulate_frontends.end(); ++it)
+               it=m_avail_simulate_frontends.begin();
+               for (; it != m_avail_simulate_frontends.end(); ++it)
                {
                        if (it->m_frontend->getSlotID() == tu1)
                                p1 = *it;
@@ -1465,7 +1530,10 @@ bool eDVBSatelliteEquipmentControl::isRotorMoving()
        return m_rotorMoving;
 }
 
-void eDVBSatelliteEquipmentControl::setRotorMoving(bool b)
+void eDVBSatelliteEquipmentControl::setRotorMoving(int slot_no, bool b)
 {
-       m_rotorMoving=b;
+       if (b)
+               m_rotorMoving |= (1 << slot_no);
+       else
+               m_rotorMoving &= ~(1 << slot_no);
 }