📄 driv0299.c
字号:
#define ENABLE_CENTRE_TIMING
/* #define ENABLE_DEBUG_PRINT_LOCAL */
#define SYNCHRONISE_WITH_TUNER_TASK_STATE
/*
-- =================================================
-- ||| STV 0299 evaluation software |||
-- ||| Version 1.1 dated Dec 1999 |||
-- ||| Authors : Jean-Yves COUET |||
-- ||| : Mariano BONA |||
-- ||| : Ardisson Stephane |||
-- ||| SGS-THOMSON Video application Lab. |||
-- =================================================
*/
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "st_tuner.h" /* Enabling STAPI environment */
#include "vdbase.h"
#if (HOST > 1000)
#include "panel_u.h"
#include "i2c.h"
#include "System.h"
#include "ReportP.h"
#include "ScanP.h"
#include "bmarkp.h"
#endif
#include "fereport.h"
/*
* VICKY - 100200 - added two state variables to break from the search loop,
* so that during the channel search, we will have faster response.
*/
extern signed char cTransponderIndex2bRetrieved;
extern signed short int asSymbolRateOffset [ MAX_NO_OF_TRANSPONDERS ];
extern int iCurFsRegOffset;
extern int iCurTunerTaskState,
iSavedTunerTaskState;
SEARCHPARAMS Params;
SEARCHRESULT Result;
/*==============================================================================
--==============================================================================
--
-- MESSAGES ROUTINES
--
--------------------------------------------------------------------------------
-- SendDebugMessage(int, long, long)
--
-- This routine selects the message to insert in
-- the execution report (if required)
--
------------------------------------------------------------------------------*/
void SendDebugMessage(int _MessageNumber, long _Value1, long _Value2)
{
#if( HOST > 1000 )
ReportInsertMessage(_MessageNumber, _Value1, _Value2) ;
#endif
}
#if( HOST < 1000 )
void SystemWaitFor(int ms)
{
DEMOD_Delay(ms);
}
#endif
/*****************************************************
--FUNCTION :: WaitTuner
--ACTION :: Wait for tuner locked
--PARAMS IN :: TimeOut -> Maximum waiting time (in ms)
--PARAMS OUT:: NONE
--RETURN :: NONE
--***************************************************/
void WaitTuner(int TimeOut)
{
int Time=0;
int TunerLocked = FALSE;
while(!TunerLocked && (Time<TimeOut))
{
SystemWaitFor(1);
TunerLocked = TunerGetTunerLock();
Time++;
}
Time--;
}
/****************************************************
--FUNCTION :: CheckAgc1
--ACTION :: Check agc1 value
--PARAMS IN :: pParams -> Pointer to SEARCHPARAMS structure
--PARAMS OUT:: pParams->State is modified
--RETURN :: NOAGC1 if AGC1=-128, AGC1SATURATION
-- if AGC1=127, AGC1OK otherwise
--**************************************************/
SIGNALTYPE CheckAgc1(SEARCHPARAMS *pParams)
{
int AGC1Value;
int Agc1Threshold = -128;
AGC1Value = RegGetField(AGCINTEGRATORVALUE);
if (AGC1Value == Agc1Threshold)
pParams->State = NOAGC1;
else if(AGC1Value == 127)
pParams->State = AGC1SATURATION;
else
pParams->State = AGC1OK;
REPORT_PRINT ( ( FE_MSG_AGC1_CHECK, AGC1Value, pParams -> State, 0 ) );
return pParams->State;
}
/*****************************************************
--FUNCTION :: CheckTiming
--ACTION :: Check for timing locked
--PARAMS IN :: pParams->Ttiming => Time to wait for timing loop locked
--PARAMS OUT:: pParams->State => result of the check
--RETURN :: NOTIMING if timing not locked, TIMINGOK otherwise
--***************************************************/
SIGNALTYPE CheckTiming(SEARCHPARAMS *pParams)
{
int locked,
timing,
TimingFreq;
unsigned char Sr[3];
SystemWaitFor(pParams->Ttiming);
locked=RegGetField(TLIR);
timing=abs(RegGetField(RTF));
if(locked >= 43)
{
/* VICKY - 030300 - modified the timing check only based on lock value */
#if 0
if((locked > 48) && (timing >= 110))
pParams->State = ANALOGCARRIER;
else
#else
if(locked > 48)
#endif
pParams->State = TIMINGOK;
}
else
pParams->State = NOTIMING;
REPORT_PRINT ( ( FE_MSG_TIMING_CHECK, locked, pParams -> State, 0 ) );
return pParams->State;
}
/*****************************************************
--FUNCTION :: CheckCarrier
--ACTION :: Check for carrier founded
--PARAMS IN :: pParams => Pointer to SEARCHPARAMS structure
--PARAMS OUT:: pParams->State => Result of the check
--RETURN :: NOCARRIER carrier not founded, CARRIEROK otherwise
--***************************************************/
SIGNALTYPE CheckCarrier(SEARCHPARAMS *pParams)
{
SystemWaitFor(pParams->Tderot); /* wait for derotator ok */
RegSetField(CFD_ALGO,0);
if (RegGetField(CF))
pParams->State = CARRIEROK;
else
pParams->State = NOCARRIER;
return pParams->State;
}
/*****************************************************
--FUNCTION :: CheckData
--ACTION :: Check for data founded
--PARAMS IN :: pParams => Pointer to SEARCHPARAMS structure
--PARAMS OUT:: pParams->State => Result of the check
--RETURN :: NODATA data not founded, DATAOK otherwise
--***************************************************/
SIGNALTYPE CheckData(SEARCHPARAMS *pParams)
{
SystemWaitFor(pParams->Tdata); /* Wait for data */
if (RegGetField(LK))
pParams->State = DATAOK;
else
pParams->State = NODATA;
return pParams->State;
}
/*****************************************************
--FUNCTION :: IQInvertion
--ACTION :: Invert I and Q
--PARAMS IN :: NONE
--PARAMS OUT:: NONE
--RETURN :: NONE
--***************************************************/
void IQInvertion(void)
{
RegSetField(IQ,0x01 & (~RegGetField(IQ))); /* inverting the I/Q configuration */
}
/*****************************************************
--FUNCTION :: CalcTimingTimeConstant
--ACTION :: Compute the amount of time needed by the timing loop to lock
--PARAMS IN :: SymbolRate -> symbol rate value
--PARAMS OUT:: NONE
--RETURN :: Timing loop time constant (ms)
--***************************************************/
long CalcTimingTimeConstant(long SymbolRate)
{
return (200000/(SymbolRate/1000));
}
/*****************************************************
--FUNCTION :: CalcDerotTimeConstant
--ACTION :: Compute the amount of time needed by the Derotator to lock
--PARAMS IN :: SymbolRate -> symbol rate value
--PARAMS OUT:: NONE
--RETURN :: Derotator time constant (ms)
--***************************************************/
long CalcDerotTimeConstant(long SymbolRate)
{
return (10000/(SymbolRate/1000));
}
/*****************************************************
--FUNCTION :: CalcDataTimeConstant
--ACTION :: Compute the amount of time needed to capture data
--PARAMS IN :: Er -> Viterbi rror rate
-- Sn -> viterbi averaging period
-- To -> viterbi time out
-- Hy -> viterbi hysteresis
-- SymbolRate -> symbol rate value
--PARAMS OUT:: NONE
--RETURN :: Data time constant
--***************************************************/
long CalcDataTimeConstant(int Er, int Sn,int To,int Hy,long SymbolRate)
{
long Tviterbi = 0,
TimeOut =0,
THysteresis = 0,
PhaseNumber[5] = {2,6,4,6,8},
averaging[4] = {1024L,4096L,16384L,65536L},
InnerCode = 1000,
HigherRate = 1000;
int i;
/* =======================================================================
-- Data capture time (in ms)
-- -------------------------
-- This time is due to the Viterbi synchronisation.
--
-- For each authorized inner code, the Viterbi search time is calculated,
-- and the results are cumulated in ViterbiSearch. */
for(i=0;i<5;i++)
{
if (((Er >> i)& 0x01) == 0x01)
{
switch(i)
{
case 0: /* inner code 1/2 */
InnerCode = 2000; /* 2.0 */
break;
case 1: /* inner code 2/3 */
InnerCode = 1500; /* 1.5 */
break;
case 2: /* inner code 3/4 */
InnerCode = 1333; /* 1.333 */
break;
case 3: /* inner code 5/6 */
InnerCode = 1200; /* 1.2 */
break;
case 4: /* inner code 7/8 */
InnerCode = 1143; /* 1.143 */
break;
}
Tviterbi +=(int)((PhaseNumber[i]*averaging[Sn]*InnerCode)/SymbolRate);
if(HigherRate < InnerCode)
HigherRate = InnerCode;
}
}
/* time out calculation (TimeOut)
-- ------------------------------
-- This value indicates the maximum duration of the synchro word research. */
TimeOut = (int)((HigherRate * 16384L * (To + 1))/(2*SymbolRate));
/* Hysteresis duration (Hysteresis)
-- ------------------------------ */
THysteresis = (int)((HigherRate * 26112L * (Hy +1))/(2*SymbolRate)); /* 26112= 16*204*8 bits */
/* a guard time of 1 mS is added */
return (1 + Tviterbi + TimeOut + THysteresis);
}
/*****************************************************
--FUNCTION :: CarrierWidth
--ACTION :: Compute the width of the carrier
--PARAMS IN :: SymbolRate -> Symbol rate of the carrier (Kbauds or Mbauds)
-- RollOff -> Rolloff * 100
--PARAMS OUT:: NONE
--RETURN :: Width of the carrier (KHz or MHz)
--***************************************************/
long CarrierWidth(long SymbolRate, long RollOff)
{
return (SymbolRate + (SymbolRate*RollOff)/100);
}
/*****************************************************
--FUNCTION :: InitParams
--ACTION :: Set Params fields that are never changed during search algorithm
--PARAMS IN :: NONE
--PARAMS OUT:: NONE
--RETURN :: NONE
--***************************************************/
void InitParams(void)
{
int stdby,dirclk,k,m,p,
m1,betaagc1,
agc2coef,MasterClock;
/* Read registers (in burst mode) */
RegGetRegisters(R_RCR,2); /* Read RCR and MCR registers */
RegGetOneRegister(R_AGC1C);
RegGetRegisters(R_AGC1R,2); /* Read AGC1R and AGC2O registers */
/* Get fields values */
stdby=FieldGetVal(STDBY);
dirclk=FieldGetVal(DIRCLK);
k=FieldGetVal(K);
m=FieldGetVal(M);
p=FieldGetVal(P);
m1=FieldGetVal(AGC1_REF);
betaagc1=FieldGetVal(BETA_AGC1);
agc2coef=FieldGetVal(AGC2COEF);
/* Initial calculations */
MasterClock = CalcMasterClkFrequency(stdby,dirclk,k,m,p);
Params.Tagc1 = CalcAGC1TimeConstant(m1,MasterClock,betaagc1)/20L;
Params.Tagc2 = CalcAGC2TimeConstant(agc2coef,m1,MasterClock)/1000000L;
Params.MasterClock = MasterClock;
Params.Mclk = MasterClock/65536L;
Params.RollOff = RegGetRollOff();
}
/*****************************************************
--FUNCTION :: InitSearch
--ACTION :: Set Params fields that are used by the search algorithm
--PARAMS IN :: Frequency => Frequency used to start zig zag
-- SymbolRate => searched symbol rate
-- SearchRange => Range of the search
-- DerotStep => Size of derotator's steps used in the carrier search (in per thousand of symbol frequency)
-- Mode => Search context (SCAN or SEARCH)
--PARAMS OUT:: NONE
--RETURN :: NONE
--***************************************************/
void InitSearch(int Frequency, int SymbolRate, int SearchRange, int DerotStep, SCANMODE Mode)
{
TUNER_PROP Tnr;
Params.BaseFreq = Frequency;
Params.SymbolRate = SymbolRate;
Params.SearchRange = SearchRange;
Params.DerotPercent = DerotStep;
TunerGetProperties(&Tnr);
Params.TunerStep = Tnr.StepSize;
Params.TunerBW = TunerSelectBandwidth(CarrierWidth(SymbolRate,Params.RollOff)/1000 + 3000)*1000;
Params.TunerIF = Tnr.IF;
Params.ScanMode = Mode;
Result.SignalType = NOAGC1;
Result.Frequency = 0;
Result.SymbolRate = 0;
}
/*****************************************************
--FUNCTION :: SearchTiming
--ACTION :: Perform an Fs/2 zig zag to found timing
--PARAMS IN :: NONE
--PARAMS OUT:: NONE
--RETURN :: NOTIMING if no valid timing had been found, TIMINGOK otherwise
--***************************************************/
SIGNALTYPE SearchTiming(SEARCHPARAMS *pParams, SEARCHRESULT *pResult)
{
short int DerotStep,
DerotFreq = 0,
DerotLimit,
LastDerotFreq = 0,
NextLoop = 3;
int index = 0;
pParams->State = NOTIMING;
/* timing loop computation & symbol rate optimisation */
DerotLimit = (pParams->SubRange/2L)/pParams->Mclk;
DerotStep = (pParams->SymbolRate/2L)/pParams->Mclk;
do
{
#if (HOST > 1000)
ReportInsertMessage(SEARCHOFFSET,DerotFreq,pParams->Mclk);
#endif
REPORT_PRINT ( ( FE_MSG_TIMING_SEARCH, DerotFreq, DerotStep, DerotLimit ) );
if(CheckTiming(pParams)!=TIMINGOK)
{
index++;
#if 1 /* LP 101100 */
LastDerotFreq = DerotFreq;
#endif
DerotFreq += index*pParams->Direction*DerotStep; /* Compute the next derotator position for the zig zag */
if(ABS(DerotFreq) > DerotLimit)
NextLoop--;
if(NextLoop)
{
FieldSetVal(DEROTATORFREQUENCYMSB,MSB(DerotFreq));
FieldSetVal(DEROTATORFREQUENCYLSB,LSB(DerotFreq));
RegSetRegisters(R_CFRM,2); /* Set the derotator frequency */
}
}
else
{
pResult->SymbolRate = pParams->SymbolRate;
}
pParams->Direction = -pParams->Direction; /* Change the zigzag direction */
}
#ifdef SYNCHRONISE_WITH_TUNER_TASK_STATE
while((pParams->State!=TIMINGOK) && NextLoop && iCurTunerTaskState == iSavedTunerTaskState );
#else
while((pParams->State!=TIMINGOK) && NextLoop );
#endif
if(pParams->State == TIMINGOK)
{
RegGetRegisters(R_CFRM,2); /* Get the derotator frequency */
pParams->DerotFreq = (short int) MAKEWORD(FieldGetVal(DEROTATORFREQUENCYMSB),FieldGetVal(DEROTATORFREQUENCYLSB));
}
#if 1 /* LP on 101100 */
else { pParams->DerotFreq = LastDerotFreq; } #endif
return pParams->State;
}
/*****************************************************
--FUNCTION :: SearchCarrier
--ACTION :: Search a QPSK carrier with the derotator
--PARAMS IN ::
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -