/*
    TDA10024  - DVB-C decoder
    (as used in Philips CU1216-3 NIM and the Reelbox DVB-C tuner card)

    Copyright (C) 2005 Georg Acher, BayCom GmbH (acher at baycom dot de)
    Copyright (c) 2006 Hartmut Birr (e9hack at gmail dot com)

    Remotely based on tda10021.c
    Copyright (C) 1999 Convergence Integrated Media GmbH <ralph@convergence.de>
    Copyright (C) 2004 Markus Schulz <msc@antzsystem.de>
       Support for TDA10021

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

//-----------------------------------------------------------------------------
// Standard include files:
//-----------------------------------------------------------------------------
//

#undef _WIN32
#define NO_FLOAT
#define _CHINA_CABLE_
#define NO_REDUNDANT_LOCKING
#define  ENABLE_MAINALGO
#define  QAM256_OPTIMIZATION
#undef INIT_FIX



#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/string.h>
#include <linux/slab.h>

#include <asm/div64.h>

#include "dvb_frontend.h"

//-----------------------------------------------------------------------------
// Project include files:
//-----------------------------------------------------------------------------
//
#include "tda10024.h"

//-----------------------------------------------------------------------------
// Types and defines:
//-----------------------------------------------------------------------------
//

//-----------------------------------------------------------------------------
// Standard include files:
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
// Project include files:
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
// Types and defines:
//-----------------------------------------------------------------------------
//


#if !defined(_TMtypes_h)
/** Standard Type mappings. */
#define Void void
typedef signed   char   Int8;       /*  8-bit   signed integer */
typedef signed   short  Int16;      /* 16-bit   signed integer */
typedef signed   long   Int32;      /* 32-bit   signed integer */
typedef unsigned char   UInt8;      /*  8-bit unsigned integer */
typedef unsigned short  UInt16;     /* 16-bit unsigned integer */
typedef unsigned int    UInt32;     /* 32-bit unsigned integer */
typedef float           Float;      /* 32-bit floating point */
typedef float           Float32;    /* 32-bit floating point */
typedef unsigned char   Bool;       /* Boolean (True/False) */
typedef char            Char;       /* character, character array ptr */
typedef int             Int;        /* machine-natural integer */
typedef unsigned int    UInt;       /* machine-natural unsigned integer */
typedef char           *String;     /* Null-terminated 8-bit char str */

typedef unsigned long tmErrorCode_t;
typedef Int       tmUnitSelect_t, *ptmUnitSelect_t;

#ifndef TM_OK
/** Global success return status */
#define TM_OK 0U
#endif

#define Null            ((void *) 0)

#define TM_FALSE        0
#define TM_TRUE         1
#define False            TM_FALSE
#define True            TM_TRUE

#endif //!defined(_TMtypes_h)


//#define NO_FLOAT
#define SEND_TRACEFCT1(x,y)
#define SEND_TRACEFCT2(x,y)
#define SEND_TRACEFCT3(x,y)
#define SEND_TRACEFCT4(x,y)
#define SEND_TRACE(x,y)
//#define DEBUG_SCAN 1
//-----------------------------------------------------------------------------
// Global data:
//-----------------------------------------------------------------------------
//

#define TDA10023_BSL_COMP_NUM       1
#define TDA10023_BSL_MAJOR_VER      3
#define TDA10023_BSL_MINOR_VER      20

//-------------
// ERROR CODES
//-------------
#ifndef TM_ERR_BAD_UNIT_NUMBER
#define TM_ERR_BAD_UNIT_NUMBER  2
#define TM_ERR_NOT_INITIALIZED  3
#define TM_ERR_BAD_PARAMETER  4
#define TM_ERR_NOT_SUPPORTED  5
#endif
#define TM_ERR_IIC_ERR      6

#define TMBSL_ERR_DEMOD_BASE    0x00

#define TMBSL_ERR_TUNER_BASE  0x00

// Invalid unit id
#define TMBSL_ERR_DEMOD_BAD_UNIT_NUMBER \
(TMBSL_ERR_DEMOD_BASE + TM_ERR_BAD_UNIT_NUMBER)

// Component is not initialized
#define TMBSL_ERR_DEMOD_NOT_INITIALIZED \
(TMBSL_ERR_DEMOD_BASE+ TM_ERR_NOT_INITIALIZED)

// Invalid input parameter
#define TMBSL_ERR_DEMOD_BAD_PARAMETER \
(TMBSL_ERR_DEMOD_BASE + TM_ERR_BAD_PARAMETER)

// Function is not supported
#define TMBSL_ERR_DEMOD_NOT_SUPPORTED \
(TMBSL_ERR_DEMOD_BASE + TM_ERR_NOT_SUPPORTED)

#define TDA10023_ALGO_NOT_FINISHED_RET  0
#define TDA10023_ALGO_SUCCESS_RET       1
#define TDA10023_ALGO_FAILED_RET        2
#define TDA10023_ALGO_CARRIER_OK_RET  3

//---------
// CHANNEL
//---------
#define TDA10023_MAX_UNITS              0
#define TDA10023_RF_MIN                 170000
#define TDA10023_RF_MAX                 1000000000 // extented from 887000000 to 1 GHz
               // for validation of tda8274AHN

#define TDA10023_JQAMFILTER_NB          15
#define TDA10023_JQAMFILTER_ADDR_OFFSET 0x04

#define TDA10023_ANALOG_THRESHOLD   180
#define DERIV_THRESHOLD  100
#define SPECTRUM_THRESHOLD  80000
#define TDA10023_LEVEL_POWER 500

// two possible values for uBandwidth : 6MHz or 8MHz therefore
// maximum value for NB_MAX_CHANNEL is : (862 - 47 + 3)/6 = 136
#define NB_MAX_CHANNEL    136

//-----------------------------------------------
//    DEFAULT VALUES FOR CONFIGURATION MANAGEMENT
//-----------------------------------------------
#define OM5700_BOARD_DEF            0x57000000
#define OM5755_BOARD_DEF            0x57550000
#define OM5763_BOARD_DEF            0x57630000
#define OM5764_BOARD_DEF      0x57640000
#define OM5764_MAXBOARD_DEF     0x57640022
#define CU1216_BOARD_DEF      0x12160000
#define OM5795_BOARD_DEF      0x57950000  // Modified by David Han
#define OM3853C_BOARD_DEF     0x38530000  // Added by Daniel Guo for 18251
#define CUSTOM_BOARD_DEF            0x00000000    //custom

#define OM57XX_XTALL_DEF            16000000
#define OM57XX_MODE_DVB_DEF         0
#define OM57XX_MODE_MCNS_DEF        1

#ifdef _CHINA_CABLE_
//PR SHZ_STBT#203 Modify tmbsl10023 to solve ADC harmonics problem
#define OM57XX_PLLMFACTOR_DVB_DEF 0x06
#define OM57XX_PLLNFACTOR_DVB_DEF   0x00
#define OM57XX_PLLPFACTOR_DVB_DEF 0x01

#define OM57XX_PLLMFACTOR_DVB_HARM_DEF 0x10
#define OM57XX_PLLNFACTOR_DVB_HARM_DEF 0x00
#define OM57XX_PLLPFACTOR_DVB_HARM_DEF 0x03

#else
#define OM57XX_PLLMFACTOR_DVB_DEF   0x0a
#define OM57XX_PLLNFACTOR_DVB_DEF   0x00
#define OM57XX_PLLPFACTOR_DVB_DEF   0x02
#endif //#ifdef _CHINA_CABLE_

#define OM57XX_PLLMFACTOR_MCNS_DEF  0x11
#define OM57XX_PLLNFACTOR_MCNS_DEF  0x00
#define OM57XX_PLLPFACTOR_MCNS_DEF  0x03

#define OM57XX_FSAMPLING_DEF        1

#define OM57XX_POLAPWM1_DEF         0
#define OM57XX_POLAPWM2_DEF         0
#define OM57XX_IFMAX_DEF            0xff
#define OM57XX_IFMIN_DEF            0x96
#define OM57XX_TUNMAX_DEF           0xff
#define OM57XX_TUNMIN_DEF           0x00
#define OM57XX_AGCTRESHOLD_DEF      255
#define OM57XX_EQUALTYPE_DEF        1////2
#define OM57XX_BERDEPTH_DVB_DEF     2
#define OM57XX_BERDEPTH_MCNS_DEF    1
#define OM57XX_BERWINDOW_DEF        8           // Depth of the sliding window used in MCNS to calculate the BER (possible values: 8, 64, 512, 4096)
#define OM57XX_CLKOFFSETRANGE_DEF   0
#define OM57XX_IQSWAP_DEF           1
#define OM57XX_IF_DVB_DEF           36130000
#define OM57XX_IF_MCNS_DEF          43750000
#define OM57XX_OCLK1_DEF            1
#define OM57XX_PARASER1_DEF         0
#define OM57XX_MSBFIRST1_DEF        1//0
#define OM57XX_MODEABC1_DEF         0
#define OM57XX_PARADIV1_DEF         0
#define OM57XX_OCLK2_DEF            1
#define OM57XX_MSBFIRST2_DEF        0
#define OM57XX_SWDYN_DEF            1 //7 //O
#define OM57XX_SWSTEP_DEF           1

#define OM5763_FSAMPLING_DEF        0
#define OM5763_IF_DVB_DEF           5000000
#define OM5763_IF_MCNS_DEF          4000000


#define CU1216_PLLMFACTOR_MCNS_DEF  0x09
#define CU1216_PLLNFACTOR_MCNS_DEF  0x00
#define CU1216_PLLPFACTOR_MCNS_DEF  0x03
#define CU1216_PLLMFACTOR_DVB_DEF  0x07
#define CU1216_PLLNFACTOR_DVB_DEF  0x00
#define CU1216_PLLPFACTOR_DVB_DEF  0x03

#ifdef _CHINA_CABLE_
//PR SHZ_STBT#203 Modify tmbsl10023 to solve ADC harmonics problem
#define CU1216_PLLMFACTOR_DVB_HARM_DEF 0x18
#define CU1216_PLLNFACTOR_DVB_HARM_DEF 0x02
#define CU1216_PLLPFACTOR_DVB_HARM_DEF 0x03
#define CU1216_FSAMPLING_HARM_DEF      1              // for 60.25M SACLK

#endif //_CHINA_CABLE_

#define CU1216_XTALL_FREQ_28     28920000

/* modified by David Han */
#define OM5795_PLLMFACTOR_MCNS_DEF  0x09
#define OM5795_PLLNFACTOR_MCNS_DEF  0x00
#define OM5795_PLLPFACTOR_MCNS_DEF  0x03
#define OM5795_PLLMFACTOR_DVB_DEF  0x07
#define OM5795_PLLNFACTOR_DVB_DEF  0x00
#define OM5795_PLLPFACTOR_DVB_DEF  0x03
#define OM5795_XTALL_FREQ_28     28920000
#define OM5795_IFMIN_DEF            0x60

#define OM57XX_STARTSR_DEF              7500000 //Max SR specified by Nordig spec is 7.2 MS/s
#define OM57XX_STOPSR_DEF               1000000
#define OM57XX_SRMAXMARGIN_DEF          30
#define OM57XX_SRMINMARGIN_DEF          20

//---------------
//  DEMOD INDEX
//---------------
#define TDA10023_GPR_IND                0x00
#define TDA10023_AGCREF_IND             0x01
#define TDA10023_AGCCONF1_IND           0x02
#define TDA10023_CLKCONF_IND            0x03
#define TDA10023_CARCONF_IND            0x04
#define TDA10023_LOCKTHR_IND            0x05
#define TDA10023_EQCONF1_IND            0x06
#define TDA10023_EQSTEP_IND             0x07
#define TDA10023_MSETH_IND              0x08
#define TDA10023_AREF_IND               0x09
#define TDA10023_BDRLSB_IND             0x0A
#define TDA10023_BDRMID_IND             0x0B
#define TDA10023_BDRMSB_IND             0x0C
#define TDA10023_BDRINV_IND             0x0D
#define TDA10023_GAIN1_IND              0x0E
#define TDA10023_TEST_IND               0x0F
#define TDA10023_FECDVBCFG1_IND         0x10
#define TDA10023_STATUS_IND             0x11
#define TDA10023_INTP1_IND              0x12
#define TDA10023_FECDVBCFG2_IND         0x13
#define TDA10023_BERLSB_IND             0x14
#define TDA10023_BERMID_IND             0x15
#define TDA10023_BERMSB_IND             0x16
#define TDA10023_AGCTUN_IND             0x17
#define TDA10023_MSE_IND                0x18
#define TDA10023_AFC_IND                0x19
#define TDA10023_IDENTITY_IND           0x1A
#define TDA10023_ADC_IND                0x1B
#define TDA10023_EQCONF2_IND            0x1C
#define TDA10023_CKOFF_IND              0x1D
#define TDA10023_CONTROL_IND            0x1E
#define TDA10023_RESET_IND              0x1F
#define TDA10023_INTP2_IND              0x20
#define TDA10023_SATNYQ_IND             0x21
#define TDA10023_SATADC_IND             0x22
#define TDA10023_HALFADC_IND            0x23
#define TDA10023_SATDEC1_IND            0x24
#define TDA10023_SATDEC2_IND            0x25
#define TDA10023_SATDEC3_IND            0x26
#define TDA10023_SATAAF_IND             0x27
#define TDA10023_PLL1_IND               0x28
#define TDA10023_PLL2_IND               0x29
#define TDA10023_PLL3_IND               0x2A
#define TDA10023_INTS1_IND              0x2B
#define TDA10023_INTPS_IND              0x2C
#define TDA10023_SWEEP_IND              0x2D
#define TDA10023_AGCCONF2_IND           0x2E
#define TDA10023_AGCIF_IND              0x2F
#define TDA10023_SATTHR_IND             0x30
#define TDA10023_HALFTHR_IND            0x31
#define TDA10023_ITSEL1_IND             0x32
#define TDA10023_ITSEL2_IND             0x33
#define TDA10023_PWMREF_IND             0x34
#define TDA10023_TUNMAX_IND             0x35
#define TDA10023_TUNMIN_IND             0x36
#define TDA10023_DELTAF_LSB_IND         0x37
#define TDA10023_DELTAF_MSB_IND         0x38
#define TDA10023_CONSTI_IND             0x39
#define TDA10023_CONSTQ_IND             0x3A
#define TDA10023_IFMAX_IND              0x3B
#define TDA10023_IFMIN_IND              0x3C

#define TDA10023_GAIN2_IND              0x3D
#define TDA10023_ITSTAT1_IND            0x3E
#define TDA10023_ITSTAT2_IND            0x3F

#define TDA10023_REQCO_IND              0x40
#define TDA10023_REQCO_CENTRALCOEF_IND  0x50

#define TDA10023_CPT_TSP_UNCOR1_IND     0x74
#define TDA10023_CPT_TSP_UNCOR2_IND     0x75
#define TDA10023_CPT_TSP_UNCOR3_IND     0x76
#define TDA10023_CPT_TSP_UNCOR4_IND     0x77
#define TDA10023_CPT_TSP_COR1_IND       0x78
#define TDA10023_CPT_TSP_COR2_IND       0x79
#define TDA10023_CPT_TSP_COR3_IND       0x7A
#define TDA10023_CPT_TSP_COR4_IND       0x7B
#define TDA10023_CPT_TSP_OK1_IND        0x7C
#define TDA10023_CPT_TSP_OK2_IND        0x7D
#define TDA10023_CPT_TSP_OK3_IND        0x7E
#define TDA10023_CPT_TSP_OK4_IND        0x7F

#define TDA10023_IEQCO_IND              0x80
#define TDA10023_IEQCO_CENTRALCOEF_IND  0x90

#define TDA10023_AGCREFNYQ_IND          0xB4
#define TDA10023_ERAGC_THD_IND          0xB5
#define TDA10023_ERAGCNYQ_THD_IND       0xB6
#define TDA10023_SCIN_THDL_IND          0xB7
#define TDA10023_SCIN_THDH_IND          0xB8
#define TDA10023_SCIN_CPTL_IND          0xB9
#define TDA10023_SCIN_CPTH_IND          0xBA
#define TDA10023_SCIN_CPT_IND           0xBB
#define TDA10023_SCIN_NBTSAT_IND        0xBC
#define TDA10023_SATDEC0_IND            0xBD
#define TDA10023_INVQ_AGC_IND           0xBE
#define TDA10023_BW_AGC_IND             0xBF
#define TDA10023_XTAL_PLL4_IND          0xC0
#define TDA10023_PLL5_IND               0xC1
#define TDA10023_CLBSTIM_I2CSWTCH_IND   0xC2
#define TDA10023_TIMING_SCAN_IND        0xC3
#define TDA10023_TIMING_PPM_IND         0xC4
#define TDA10023_TIMING_PARA1_IND       0xC5
#define TDA10023_TIMING_PARA2_IND       0xC6
#define TDA10023_TIMING_STATUS_IND      0xC7
#define TDA10023_CPT_TRANS_IND          0xC8
#define TDA10023_PERCENTAGE_IND         0xC9
#define TDA10023_ERTIM_THD_IND          0xCA
#define TDA10023_DSP_IND                0xCB
#define TDA10023_POWER1_IND             0xCC
#define TDA10023_POWER2_IND             0xCD
#define TDA10023_POWER3_IND             0xCE

#define TDA10023_CTRL1_IND              0xD0
#define TDA10023_CTRL2_IND              0xD1
#define TDA10023_TRELDAT_IND            0xD2
#define TDA10023_TRELCOR_IND            0xD3
#define TDA10023_FECSYNC_IND            0xD4
#define TDA10023_DRNDSD1_IND            0xD5
#define TDA10023_DRNDSD2_IND            0xD6
#define TDA10023_DRNDSD3_IND            0xD7
#define TDA10023_CPT_RSB_UNCOR1_IND     0xD8
#define TDA10023_CPT_RSB_UNCOR2_IND     0xD9
#define TDA10023_CPT_RSB_UNCOR3_IND     0xDA
#define TDA10023_CPT_RSB_UNCOR4_IND     0xDB
#define TDA10023_FECRSYNC_IND           0xDC
#define TDA10023_DEINTRLV_IND           0xDD

#define TDA10023_STATUS_MCNS_IND        0xE0
#define TDA10023_VITERBI_LOCK_IND       0xE1
#define TDA10023_RSUNCORLO_IND          0xE2
#define TDA10023_RSUNCORHI_IND          0xE3
#define TDA10023_RSBERLO_IND            0xE4
#define TDA10023_RSBERHI_IND            0xE5
#define TDA10023_RSCFG_IND              0xE6
#define TDA10023_CPT_RSB_COR1_IND       0xE7
#define TDA10023_CPT_RSB_COR2_IND       0xE8
#define TDA10023_CPT_RSB_COR3_IND       0xE9
#define TDA10023_CPT_RSB_COR4_IND       0xEA
#define TDA10023_CPT_RSB_OK1_IND        0xEB
#define TDA10023_CPT_RSB_OK2_IND        0xEC
#define TDA10023_CPT_RSB_OK3_IND        0xED
#define TDA10023_CPT_RSB_OK4_IND        0xEE

#define TDA10023_EMPTY_FECMCNS_IND      0xFA
#define TDA10023_EMPTY1_TOP_IND         0xFB
#define TDA10023_EMPTY2_TOP_IND         0xFC
#define TDA10023_EMPTY_DEMOD_IND        0xFD
#define TDA10023_EMPTY_FEC_DVB_IND      0xFE



//---------------------
//  JQAM FILTER INDEX
//---------------------
#define TDA10023_JQAM_MODE_IND      0x00
#define TDA10023_REQ_TS_IDH_IND     0x01
#define TDA10023_REQ_TS_IDL_IND     0x02
#define TDA10023_REQ_ON_IDH_IND     0x03
#define TDA10023_REQ_ON_IDL_IND     0x04
#define TDA10023_REG5_IND           0x05
#define TDA10023_TS_STATUS_H_IND    0x06
#define TDA10023_TS_STATUS_L_IND    0x07
#define TDA10023_RCV_STATUS4_IND    0x08
#define TDA10023_RCV_STATUS3_IND    0x09
#define TDA10023_RCV_STATUS2_IND    0x0A
#define TDA10023_RCV_STATUS1_IND    0x0B
#define TDA10023_TS_ID1H_IND        0x0C
#define TDA10023_TS_ID1L_IND        0x0D
#define TDA10023_ON_ID1H_IND        0x0E
#define TDA10023_ON_ID1L_IND        0x0F
#define TDA10023_TS_ID2H_IND        0x10
#define TDA10023_TS_ID2L_IND        0x11
#define TDA10023_ON_ID2H_IND        0x12
#define TDA10023_ON_ID2L_IND        0x13
#define TDA10023_TS_ID3H_IND        0x14
#define TDA10023_TS_ID3L_IND        0x15
#define TDA10023_ON_ID3H_IND        0x16
#define TDA10023_ON_ID3L_IND        0x17
#define TDA10023_TS_ID4H_IND        0x18
#define TDA10023_TS_ID4L_IND        0x19
#define TDA10023_ON_ID4H_IND        0x1A
#define TDA10023_ON_ID4L_IND        0x1B
#define TDA10023_TS_ID5H_IND        0x1C
#define TDA10023_TS_ID5L_IND        0x1D
#define TDA10023_ON_ID5H_IND        0x1E
#define TDA10023_ON_ID5L_IND        0x1F
#define TDA10023_TS_ID6H_IND        0x20
#define TDA10023_TS_ID6L_IND        0x21
#define TDA10023_ON_ID6H_IND        0x22
#define TDA10023_ON_ID6L_IND        0x23
#define TDA10023_TS_ID7H_IND        0x24
#define TDA10023_TS_ID7L_IND        0x25
#define TDA10023_ON_ID7H_IND        0x26
#define TDA10023_ON_ID7L_IND        0x27
#define TDA10023_TS_ID8H_IND        0x28
#define TDA10023_TS_ID8L_IND        0x29
#define TDA10023_ON_ID8H_IND        0x2A
#define TDA10023_ON_ID8L_IND        0x2B
#define TDA10023_TS_ID9H_IND        0x2C
#define TDA10023_TS_ID9L_IND        0x2D
#define TDA10023_ON_ID9H_IND        0x2E
#define TDA10023_ON_ID9L_IND        0x2F
#define TDA10023_TS_ID10H_IND       0x30
#define TDA10023_TS_ID10L_IND       0x31
#define TDA10023_ON_ID10H_IND       0x32
#define TDA10023_ON_ID10L_IND       0x33
#define TDA10023_TS_ID11H_IND       0x34
#define TDA10023_TS_ID11L_IND       0x35
#define TDA10023_ON_ID11H_IND       0x36
#define TDA10023_ON_ID11L_IND       0x37
#define TDA10023_TS_ID12H_IND       0x38
#define TDA10023_TS_ID12L_IND       0x39
#define TDA10023_ON_ID12H_IND       0x3A
#define TDA10023_ON_ID12L_IND       0x3B
#define TDA10023_TS_ID13H_IND       0x3C
#define TDA10023_TS_ID13L_IND       0x3D
#define TDA10023_ON_ID13H_IND       0x3E
#define TDA10023_ON_ID13L_IND       0x3F
#define TDA10023_TS_ID14H_IND       0x40
#define TDA10023_TS_ID14L_IND       0x41
#define TDA10023_ON_ID14H_IND       0x42
#define TDA10023_ON_ID14L_IND       0x43
#define TDA10023_TS_ID15H_IND       0x44
#define TDA10023_TS_ID15L_IND       0x45
#define TDA10023_ON_ID15H_IND       0x46
#define TDA10023_ON_ID15L_IND       0x47
#define TDA10023_SCIN_NBTSAT_IND  0xBC

//------------------
//  DEFAULT VALUES
//------------------
#define TDA10023_IDENTITY_DEF       0x7D

#define TDA10023_GAIN1_DEF          0x80

#define TDA10023_INTP2_INTSEL_PARA_DEF 0x00
#define TDA10023_INTP2_INTSEL_PARB_DEF 0x01
#define TDA10023_INTP2_INTSEL_PARC_DEF 0x02
#define TDA10023_INTP2_INTSEL_SER_DEF 0x03

#define TDA10023_PWMREF_DEF         0x80
#define TDA10023_AGCREF_DEF         0x30 /*optimized for adjacent signal*/

#ifdef _CHINA_CABLE_
  #define TDA10023_AGCREF_SECAM_DEF   0x30 //modified by David Han for 172MHz in Beijing network
#else
#define TDA10023_AGCREF_SECAM_DEF   0x50 /*optimized for adjacent signal*/
#endif

#define TDA10023_EQCONF1_DEF        0x70
#define TDA10023_SWEEP_DEF          0x82

//----------------
//  DEFINE MASKS
//----------------
#define TDA10023_GPR_QAM_MSK            0x1C

#define TDA10023_CLKCONF_NDEC_MSK       0xC0

#define TDA10023_CLK_C_MASK             0x07

#define TDA10023_CARCONF_CAR_C_MSK      0x0F

#define TDA10023_PLL2_PDIV_MSK          0x3F
#define TDA10023_PLL2_NDIV_MSK          0xC0

#define TDA10023_GAIN1_GNYQ_MSK         0x70
#define TDA10023_GAIN1_AUTOGNYQ_MSK     0x80

#define TDA10023_FECDVBCFG1_PVBER_MSK   0xC0

#define TDA10023_GAIN2_SFIL_MSK         0x80

#define TDA10023_RSCFG_PRG_TBER_MSK     0x0C

#define TDA10023_JQAM_MODE_JQAM_MODE_MSK    0x03

#define TDA10023_ROLL_OFF_MSK     0x03
#define TDA10023_SWEEP_MODE_MSK     0x10
#define TDA10023_AGC_INTEG_NB_MSK   0x07
#define TDA10023_EQSTTRAC_MSK     0x38
#define TDA10023_EQSTACQ_MSK      0x07
//---------------
//  DEFINE BITS
//---------------
#define TDA10023_GPR_CLBS_BIT           0x01
#define TDA10023_GPR_CLBS2_BIT          0x02
#define TDA10023_GPR_FSAMPLING_BIT      0x20
#define TDA10023_GPR_FIRSTIF_BIT        0x40
#define TDA10023_GPR_STDBY_BIT          0x80

#define TDA10023_CLKCONF_DYN_BIT        0x08

#define TDA10023_CARCONF_INVIQ_BIT      0x20
#define TDA10023_CARCONF_AUTOINVIQ_BIT  0x40

#define TDA10023_EQCONF1_ENEQUAL_BIT    0x02
#define TDA10023_EQCONF1_ENADAPT_BIT    0x04

#define TDA10023_TEST_BYPIIC_BIT        0x80
#define TDA10023_TEST_SCLT0_BIT         0x40

#define TDA10023_FECDVBCFG1_CLB_CPT_TSP_BIT 0x20

#define TDA10023_STATUS_CARLOCK_BIT     0x02
#define TDA10023_STATUS_FSYNC_BIT       0x04
#define TDA10023_STATUS_FEL_BIT         0x08
#define TDA10023_STATUS_NODVB_BIT       0x40

#define TDA10023_INTP1_POCLKP_BIT       0x01

#define TDA10023_ADC_GAINADC_BIT        0x20
#define TDA10023_ADC_TWOS_BIT           0x08

#define TDA10023_EQCONF2_SGNALGO_BIT    0x20
#define TDA10023_EQCONF2_STEPALGO_BIT   0x10
#define TDA10023_EQCONF2_CTADAPT_BIT    0x08

#define TDA10023_CONTROL_OLDBYTECLK_BIT 0x80
#define TDA10023_CONTROL_SACLK_ON_BIT   0x04

#define TDA10023_RESET_DVBMCNS_BIT      0x80

#define TDA10023_INTP2_MSBFIRSTP_BIT    0x04

#define TDA10023_PLL3_PDPLL_BIT         0x01
#define TDA10023_PLL3_BYPPLL_BIT        0x02
#define TDA10023_PLL3_LOCK_BIT          0x04
#define TDA10023_PLL3_PSACLK_BIT        0x08

#define TDA10023_INTS1_POCLKS_BIT       0x01

#define TDA10023_INTPS_TRIS_BIT         0x01
#define TDA10023_INTPS_TRIP_BIT         0x02
#define TDA10023_INTPS_MSBFIRSTS_BIT    0x40

#define TDA10023_AGCCONF2_PWMIFTY_BIT 0x01    //modified by David Han
#define TDA10023_AGCCONF2_PPWMIF_BIT    0x02
#define TDA10023_AGCCONF2_PWMTUNTY_BIT  0x04    //modified by David Han
#define TDA10023_AGCCONF2_PPWMTUN_BIT   0x08
#define TDA10023_AGCCONF2_ENAGCIF_BIT   0x10
#define TDA10023_AGCCONF2_POSAGC_BIT    0x20
#define TDA10023_AGCCONF2_TRIAGC_BIT    0x80

#define TDA10023_DELTAF_MSB_ALGOD_BIT   0x80

#define TDA10023_CTRL1_QAMMODE_BIT      0x02

#define TDA10023_STATUS_MCNS_MPEGLCK_BIT    0x04
#define TDA10023_STATUS_MCNS_FRAMELCK_BIT   0x02

#define TDA10023_RSCFG_CLB_CPT_RSB_BIT  0x01

#define TDA10023_PSD_START_BIT      0x01
#define TDA10023_PSD_FINISHED_BIT   0x20

#define TDA10023_ANALYSIS_LENGTH        0x06


//-----------------------------------------------------------------------------
// Structure:
//-----------------------------------------------------------------------------
typedef enum _tm10023cfgIndex_t
{
    BOARD = 0,
    STANDARD,
    DVBMCNS,
    XTALL,
    PLLMFACTOR,
    PLLNFACTOR,
    PLLPFACTOR,
    FSAMPLING,
    IFMAX,
    IFMIN,
    TUNMAX,
    TUNMIN,
    AGCTRESHOLD,
    EQUALTYPE,
    POLAPWM1,
    POLAPWM2,
    BERDEPTH,
    BERWINDOW,
    CLKOFFSETRANGE,
    IQSWAP,
    IF,
    OCLK1,
    PARASER1,
    MSBFIRST1,
    MODEABC1,
    PARADIV1,
    OCLK2,
    MSBFIRST2,
    SWDYN,
    SWSTEP,

    FEINIT = 100,
    SWITCH,
    IDENTITY,
    READSYNC,
    READIQ,
    READAGC,
    READMSE = 127,
    READCOEF,
    STARTEQUAL,
    STOPEQUAL,
    JQAMMODE,
    JQAMREQTS,
    JQAMREQON,
    JQAMGETREG5,
    JQAMGETTSSTATUS,
    JQAMGETRCVSTATUS,
    JQAMGETTSON,

    GETNBOFUNIT = 200,

    TUNERLVL = 301,
    BAND = 302,   // Accessible via tmhalFeTypes.h
  SRMIN = 314,  // correspond to tmhalFESRMin
  SRMAX = 315   // correspond to tmhalFESRMax
} tm10023cfgIndex_t;


// config items
typedef enum _tmhalFEConfig_t {
    tmhalFEBoard = 0,
    tmhalFEStandard,
    tmhalFEMCNSDVBMode,
    tmhalFELPSEL = 6,
    tmhalFEPort1 = 14,
    tmhalFEPort0,
    tmhalFEInit = 100,
    tmhalFEI2cSwitch,
    tmhalFECheckIdentity,
    tmhalFEReadSync,
    tmhalFEReadIQ,
    tmhalFEReadAgc,
    tmhalFEReadTVBER,       // = 106 - BSD
    tmhalFEReadTCPTU,
    tmhalFEReadTMCC,
    tmhalFEReadCBER,    // = 109 - DVB-T
    tmhalFEReadConfidence,
    tmhalFEReadRepImpul,
    tmhalFEReadRepFreq,
    tmhalFEReadCellId,
    tmhalFEReadDspVersion,
    tmhalFECarrierHigh,
    tmhalFECarrierLow,
    tmhalFECarrierStep,
    tmhalFECarrierCurrent,
    tmhalFEStartIQ,
    tmhalFEStopIQ,
    tmhalFEStartRepImpul,
    tmhalFEStopRepImpul,
    tmhalFEReadACI,
    tmhalFEReadCCI,
    tmhalFEReadLEE,
    tmhalFEReadCRC,
    tmhalFEReadMSE,     // = 127 - DVB-C
    tmhalFEReadCOEF,
    tmhalFEStartEqual,
    tmhalFEStopEqual,
    tmhalFEDspCrcVersionOK,
    tmhalFEReadRSSI = 138,    //138
    tmhalFERFTone,
    tmhalFERFToneIndex,
    tmhalFEToneSearchState,
    tmhalFENbOfUnit = 200,
    tmhalFEOutOfGIEcho,          //DVB_T
    tmhalFEDSPDownload,
    tmhalFEDSPloadFromHost,
    tmhalFEDSPloadFromEEPROM,
    tmhalFEEnable4k,
    tmhalFEModePer,
    tmhalFEGiveCfgToTuner,
    tmhalFEAGCBusEnable,
    tmhalFEAGCExt,
    tmhalFEAGCGainIndex,
    tmhalFEAGCGainValue,
    tmhalFELOFreqIndex,
    tmhalFELOFreqValue,
    tmhalFEXtalMode,
    tmhalFEEnableLNA,
    tmhalFECutOffIndex,
    tmhalFEGiveCfgToDemodNum,
    tmhalFETunerBandwidth = 300,
    tmhalFETunerLVL,
    tmhalFEBand,
    tmhalFERF,
    tmhalFEID,
    tmhalFEPOR,
    tmhalFELOCK,
    tmhalFEFCC,
    tmhalFETEMP,
    tmhalFERFAGC,
    tmhalFEIFAGC,
    tmhalFEAGCandTEMP,
    tmhalFEPowerState,
    tmhalFESensibility,
    tmhalFESRMin,
    tmhalFESRMax,
    tmhalFEBandAuto = 330,
    tmhalFEManualBandWidth,
    tmhalRFCALOK = 355,
    tmhalIRCALOK,
    tmhalFEReadInit = 372,
    tmhalFEStatusByte = 380,
    tmhalFEInitVCOLPF,          //For Tuner adjustement
    tmhalFEStandardMode = 400,
    tmhalFESound,
    tmhalFEDemodStatus,
    tmhalFEReadAFC,
    tmhalFEReadHlock,
    tmhalFEReadVlock,
    tmhalFEReadDIFAGC,
    tmhalFEReadTIFAGC,
    //tmhalFEICIdentity,
    tmhalFESetFI,
    tmhalFESetGPI0Analog,
    tmhalFEDemodHwAdd = 500,        // SW Patch to allow the TDA8275A to control Demod PIO for LNA control
    tmhalFEDemodWriteBitFct,
    tmhalFEEEPROMWriteFct,
    tmhalFEEEPROMReadFct,
    tmhalFEIF = 517,
    tmhalFENbRetry = 519,
    tmhalFESetAntennaPower = 600,         // Control GPIO1 in open-drain for Vestel application
    tmhalFEZapMode,
    tmhalFEChannelInfo,
    tmhalFETimeErr,
    tmhalFEFreqErr,
    tmhalFEEnableI2cSwitch,
    tmhalFEReadFreqFilter = 606,
    tmhalFEReadChannelType,
    tmhalFEReadCCIDetection,
    tmhalFEReadDopplerDetection,
    tmhalFEReadCumulatedHS,
    tmhalFEReadACIDetection,
    tmhalFEReadPKUse,
    tmhalFEReadIIRTimeInter,
    tmhalFEReadEchoType,
    tmhalFEReadChangeDetect,
    tmhalFEReadNBPath,
    tmhalFEReadChannelLength,
    tmhalFEEnableIQDetect,
    tmhalFEDemodReadFct     = 621,
    tmhalFEAutoOffsetLock,
    tmhalFEICMODE           = 631,
    tmhalFESACLKOUTPUTMODE,
    tmhalFEEnable8295Equal = 633,
    tmhalFECustomGDCoeff,
    tmhalFECustomCVBSCoeff,
    tmhalFEGDEqSect1,
    tmhalFEGDEqSect2,
    tmhalFEGDEqSect3,
    tmhalFEGDEqSect4,
    tmhalFECVBSEqCoeff0,
    tmhalFECVBSEqCoeff1,
    tmhalFECVBSEqCoeff2,
    tmhalFECVBSEqCoeff3,
    tmhalFECVBSEqCoeff4,
    tmhalFECVBSEqCoeff5,

} tmhalFEConfig_t, *ptmhalFEConfig_t;


typedef struct _tm10023config_t
{
    UInt32  uBoard;
    UInt8   bModeDvbMcns;
    UInt32  uXtalFreq;
    UInt8   bPLL_M_Factor;
    UInt8   bPLL_N_Factor;
    UInt8   bPLL_P_Factor;
    UInt8   bFsampling;
    UInt8   bIFMax;
    UInt8   bIFMin;
    UInt8   bTUNMax;
    UInt8   bTUNMin;
    UInt8   bAGCtreshold;
    UInt8   bEqualType;
    UInt8   bPolaPWM1;
    UInt8   bPolaPWM2;
    UInt8   bBERdepth;
    UInt32  uBERwindow;
    UInt8   bClkOffsetRange;
    UInt8   bTUN_IQSwap;
    UInt32  uTUN_IF;
    UInt8   bOUT_OClk1;
    UInt8   bOUT_bParaSer1;
    UInt8   bOUT_bMSBFirst1;
    UInt8   bOUT_ModeABC1;
    UInt8   bOUT_ParaDiv1;
    UInt8   bOUT_OClk2;
    UInt8   bOUT_bMSBFirst2;
    UInt8   bSwDyn;
    UInt8   bSwStep;
    UInt32  uStartSymbolRate;
    UInt32  uStopSymbolRate;
    UInt32  uSrMaxMargin;
    UInt32  uSrMinMargin;
  UInt32  uBoardConf;
} tm10023config_t, *ptm10023config_t;

// spectral inversion
typedef enum _tmhalFESpectrum_t {
    tmhalFESpectrumAuto = 0,
    tmhalFESpectrumNormal,
    tmhalFESpectrumInverted,
    tmhalFESpectralInvMax
} tmhalFESpectrum_t, *ptmhalFESpectrum_t;

// standard
typedef enum _tmhalFEStandard_t {
    tmhalFEStandardDSS = 0,
    tmhalFEStandardDVBS,
    tmhalFEStandardBSD,
    tmhalFEStandardDVBT,
    tmhalFEStandardDVBC,
    tmhalFEStandardMax
} tmhalFEStandard_t, *ptmhalFEStandard_t;


// modulation
typedef enum _tmhalFEModulation_t {
    tmhalFEModulationAuto = 0,
    tmhalFEModulationBpsk,
    tmhalFEModulationQpsk,
    tmhalFEModulationQam4,
    tmhalFEModulationPsk8,
    tmhalFEModulationQam16,
    tmhalFEModulationQam32,
    tmhalFEModulationQam64,
    tmhalFEModulationQam128,
    tmhalFEModulationQam256,
    tmhalFEModulationQam512,
    tmhalFEModulationQam1024,
    tmhalFEModulationMax
} tmhalFEModulation_t, *ptmhalFEModulation_t;


typedef enum _tmhalFEBandType_t
{
    tmhalFEBandTypeDefault = 0,
    tmhalFEBandTypeSECAM_L,
    tmhalFEBandTypeMax
} tmhalFEBandType_t;

// system function
typedef struct _tmhalFEBslSystemFunc_t
{
  UInt32  (*SY_GetTickTime) (void);
  UInt32  (*SY_GetTickPeriod) (void);
    Bool    (*SY_TimerStart)    (UInt32 FeInstance_U, UInt32 Time_U);
    Bool    (*SY_TimerWait)     (UInt32 FeInstance_U);

  UInt32  (*SY_GetCommErrors) (void);
  Bool  (*SY_Write)     (UInt32  uAddress,
                                 UInt32  uSubAddress,
                                 UInt32  uNbData,
                                 UInt32* pDataBuff);
  Bool  (*SY_WriteBit)    (UInt32  uAddress,
                                 UInt32  uSubAddress,
                                 UInt32  uMaskValue,
                                 UInt32  uValue);
  Bool  (*SY_Read)      (UInt32  uAddress,
                                 UInt32  uSubAddress,
                                 UInt32  uNbData,
                                 UInt32* pDataBuff);
} tmhalFEBslSystemFunc_t, *ptmhalFEBslSystemFunc_t;

typedef struct _tmbslTuParam_t
{
  unsigned long         uHwAddress;
  tmhalFEBslSystemFunc_t  systemFunc;
} tmbslTuParam_t, *ptmbslTuParam_t;

/*-----------------------------------------------------------------------------
** Software Version Structure
*/
typedef struct tmSWVersion
{
    UInt32      compatibilityNr;        /* Interface compatibility number */
    UInt32      majorVersionNr;         /* Interface major version number */
    UInt32      minorVersionNr;         /* Interface minor version number */

}   tmSWVersion_t, *ptmSWVersion_t;

typedef enum tmPowerState
{
    tmPowerOn,                          /* Device powered on      (D0 state) */
    tmPowerStandby,                     /* Device power standby   (D1 state) */
    tmPowerSuspend,                     /* Device power suspended (D2 state) */
    tmPowerOff                          /* Device powered off     (D3 state) */

}   tmPowerState_t, *ptmPowerState_t;



typedef struct _tmbslDcParam_t {
  unsigned long         uHwAddress;
  tmhalFEBslSystemFunc_t  systemFunc;
  tmUnitSelect_t        eTunerUnit;
#ifndef _WIN32
    UInt32                  dlFeInstance_U;
#endif
} tmbslDcParam_t, *ptmbslDcParam_t;

typedef struct _tm10023flags_t
{
    unsigned int iScan      :1;
    unsigned int iStartAlgo :1;
    unsigned int iInit      :1;
    unsigned int iAutoSi    :1;
    unsigned int iAutoQam   :1;
    unsigned int iPreScan   :1;
} tm10023flags_t, *ptm10023flags_t;

typedef struct _tm10023channel_t
{
    UInt32              uRF;
    UInt32              uSR;
    tmhalFESpectrum_t   eSI;
    tmhalFEModulation_t eMOD;
} tm10023channel_t, *ptm10023channel_t;


typedef struct _tm10023object_t
{
    UInt32                  uDemodHwAdd;
    tmUnitSelect_t          eTunerUnit;
    tmhalFEBslSystemFunc_t  systemFunc;
#ifndef _WIN32
    UInt32                  dlFeInstance_U;     /* permit to recover the front-End DevLib instance for Llevel interface, type: tmdlFeInstance_t */
#endif
    tm10023channel_t        sCurrentChannel;
    tm10023config_t         sConfig;
    tm10023flags_t          sApiFlags;
    UInt32          uStartFrequency;
    UInt32                  uStopFrequency;
    UInt32                  uSysClk;
    UInt8                   bGainAlgo;
    UInt32                  uSyncReg;
    UInt8                   bState;
    UInt8                   bStateClkOffset;
    UInt32                  uScanStep;
    Int32                   lClkOffCst;
    UInt32                  uTickEnd;
    UInt32                  uTickAnalogEnd;
    UInt8         bAnalogScanCounter;
    UInt32          uNbSamples;
    UInt32          uNbChannels;
    UInt32*                 pbSpectrum;
    Int32*          pbDeriv;
  UInt32*         pPotentialChannel;
    UInt32          uSpectrumChannelIndex;
    Bool          bStateSpectrum;
    UInt32          uAnalysisBand;
    UInt32          uBandwidth;
    UInt32          uStartSymbolRate;
    UInt32          uStopSymbolRate;
    Bool                    bCarrierAnalyser;
  tmhalFEBandType_t   eBandType;
  Bool          bFiltersGainSet;
  UInt32          NoiseFloor;
  UInt32          uAvgSpectrumPotential;
  Int32         UpperMaxDeriv;
  Int32         LowerMinDeriv;
  UInt32          uAvgVarDerivPotential;
  UInt32*         puNumMaxVal;
  UInt32*         puAverageSpectrum;
  Int32*          piMaxDeriv;
  Int32*          piMinDeriv;
  UInt32*         puVarDeriv;
  UInt32*         puNoiseChannel;
  UInt16          uNbSamplesSSAT; //Nb of samples in STAT depends on reg SSAT
  Bool          GainOK;
  Bool          QuickFinding;
  UInt32          uSWDynValue;
  UInt32          uSWStepValue;
  Bool          bFlagAutoScan;
  UInt32          uRFPrevious;
} tm10023object_t, *ptm10023object_t;

typedef struct _tm10023Qam_t
{
    UInt32  uQam;
    UInt32  uLockthr;
    UInt32  uMseth;
    UInt32  uAref;
    UInt32  uAgcRefNyq;
    UInt32  uErAgcNyqThd;
} tm10023Qam_t, *ptm10023Qam_t;


#ifdef _CHINA_CABLE_
typedef struct _tm10023RFLvl_Agc_t
{
  UInt8 fRFLvl;
  UInt8 uAgcRF;
  UInt8 uAgcIF;
} tm10023RFLvl_Agc_t, *ptm10023RFLvl_Agc_t;
#endif //#ifdef _CHINA_CABLE_

// status of the manager function
typedef enum _tmhalFEManagerStatus_t {
    tmhalFEManagerStatusCarrierOk = 0,
    tmhalFEManagerStatusNoCarrier,
    tmhalFEManagerStatusNotCompleted,
    tmhalFEManagerStatusMax
} tmhalFEManagerStatus_t, *ptmhalFEManagerStatus_t;



//-----------------------------------------------------------------------------
// Global data:
//-----------------------------------------------------------------------------
//

static tm10023object_t g10023Instance[] =
{
    {
        (UInt32)0,                      // Demod Hw Address not set
        (tmUnitSelect_t)0,              // Tuner unit not set
        {   Null, Null, Null,           // Demod system function not initialized
            Null, Null, Null,
            Null, Null
        },
#ifndef _WIN32
        (UInt32)0,                      // front-End DevLib instance not set
#endif
        {   (UInt32)0,          // Channel structure not initialized
            (UInt32)6875000,
            (tmhalFESpectrum_t)0,
            (tmhalFEModulation_t)0
        },
        {   OM5763_BOARD_DEF,           // Default configuration structure
            OM57XX_MODE_DVB_DEF,
            OM57XX_XTALL_DEF,
            OM57XX_PLLMFACTOR_DVB_DEF,
            OM57XX_PLLNFACTOR_DVB_DEF,
            OM57XX_PLLPFACTOR_DVB_DEF,
            OM57XX_FSAMPLING_DEF,
            OM57XX_IFMAX_DEF,
            OM57XX_IFMIN_DEF,
            OM57XX_TUNMAX_DEF,
            OM57XX_TUNMIN_DEF,
            OM57XX_AGCTRESHOLD_DEF,
            OM57XX_EQUALTYPE_DEF,
            OM57XX_POLAPWM1_DEF,
            OM57XX_POLAPWM2_DEF,
            OM57XX_BERDEPTH_DVB_DEF,
            OM57XX_BERWINDOW_DEF,
            OM57XX_CLKOFFSETRANGE_DEF,
            OM57XX_IQSWAP_DEF,
            OM57XX_IF_DVB_DEF,
            OM57XX_OCLK1_DEF,
            OM57XX_PARASER1_DEF,
            OM57XX_MSBFIRST1_DEF,
            OM57XX_MODEABC1_DEF,
            OM57XX_PARADIV1_DEF,
            OM57XX_OCLK2_DEF,
            OM57XX_MSBFIRST2_DEF,
            OM57XX_SWDYN_DEF,
            OM57XX_SWSTEP_DEF,
            OM57XX_STARTSR_DEF,
            OM57XX_STOPSR_DEF,
            OM57XX_SRMAXMARGIN_DEF,
            OM57XX_SRMINMARGIN_DEF,
      OM5763_BOARD_DEF,
        },
        {   0, 0, 0, 0, 0, 0            // api flags
        },
        47000000,           // start scanning frequency
        858000000,                      // stop scanning frequency
        0,                              // system clock
        0,                              // gain algo
        0,                              // syncreg
        0,                              // state of the algo
        0,                              // state of the clock offset algo
        0,                              // state of the scanning step
        0,                              // clock offset range
        1,                              // timer
        1,                // Timer for analog carrier detection
        0,                // Threshold for analog carrier detection
      0,                // Nb Samples per channel for spectrum
      0,                // Nb Channels
      0,                        // Pointer on the Spectrum array
      0,                // Pointer on the Derivation array
    0,                // Pointer on potentiel channel
      0,                // Index of channel reached by spectrum analyser function
      0,                // Flag for spectrum analysis done or not
      0,                // Analysis Band i.e; step of spectrum analysis
      0,                // channel bandwidth
      0,                // Start Symbol Rate
      0,                // Stop Symbol Rate
        0,                              // Carrier analyser
    (tmhalFEBandType_t)0, //(tmhalFEBandType_t)tmhalFEBandTypeSECAM_L, //     // Band type
    0,                // Filters gain set
    0,                // Noise floor
    0,                // Average spectrum
    0,                // UpperMaxDeriv
    1073741824,           // 2 exp 31 initial value for LowerMinDeriv
    0,                // uAvgVarDerivPotential
    0,                // Pointer on NumMqx array
    0,                // Pointer on Avg Specturm arrau
    0,                // Pointer on max Deriv
    0,                // Pointer on min deriv
    0,                // Pointer on var deriv
    0,                // Pointer on noise channel
    0,                // Nb samples of SSAT
    0,                // Gain OK or Not
    0,                // QuickFinding
    468,              // default value 4.68%
    0,                // default uSWStepValue
    0,                // Bool AutoScan is working
        0                               // uRFPrevious to know which last frequency have been detected
    }
};

#ifdef _CHINA_CABLE_
//for china cable project which use CD1616
static tm10023RFLvl_Agc_t RFLvl_Agc_Table_CD1616_GIGH[]=
{
  {23 , 255,  96},
  {24 , 217,  96},
  {25 , 187,  96},
  {26 , 174,  96},
  {27 , 165,  96},
  {28 , 157,  96},
  {29 , 151,  96},
  {30 , 146,  96},
  {31 , 141,  96},
  {32 , 137,  96},
  {33 , 132,  96},
  {34 , 128,  96},
  {35 , 124,  96},
  {36 , 121,  96},
  {37 , 118,  96},
  {38 , 115,  96},
  {39 , 112,  96},
  {40 , 109,  96},
  {41 , 107,  96},
  {42 , 104,  96},
  {43 , 101,  96},
  {44 , 99  , 96},
  {45 , 97  , 96},
  {46 , 94  , 96},
  {47 , 92  , 96},
  {48 , 90  , 96},
  {49 , 87  , 96},
  {50 , 85  , 96},
  {51 , 83  , 96},
  {52 , 81  , 96},
  {53 , 79  , 96},
  {54 , 78  , 96},
  {55 , 77  , 96},
  {56 , 77  , 96},
  {57 , 76  , 96},
  {58 , 76  , 96},
  {59 , 76  , 96},
  {60 , 76  , 96},
  {61 , 76  , 96},
  {62 , 75  , 96},
  {63 , 75  , 96},
  {64 , 75  , 96},
  {65 , 75  , 96},
  {66 , 75  , 96},
  {67 , 75  , 96},
  {68 , 75  , 96},
  {69 , 75  , 96},
  {70 , 75  , 96},
  {71 , 75  , 96},
  {72 , 75  , 96},
  {73 , 75  , 96},
  {74 , 74  , 96},
  {75 , 74  , 96},
  {76 , 74  , 96},
  {77 , 74  , 96},
  {78 , 74  , 96},
  {79 , 74  , 96},
  {80 , 74  , 96},
  {81 , 74  , 96},
  {82 , 74  , 96},
  {83 , 74  , 96},
  {84 , 74  , 96},
  {85 , 73  , 96},
  {86 , 73  , 96},
  {87 , 73  , 96},
  {88 , 73  , 96},
  {89 , 73  , 96},
  {90 , 73  , 96},

  {0      ,0      , 0}              // end of table mark!!
};

static tm10023RFLvl_Agc_t RFLvl_Agc_Table_CU1216_AGIGH[]=
{
  {23 , 255,  96},
  {24 , 255,  96},
  {25 , 255,  96},
  {26 , 255,  96},
  {27 , 255,  96},
  {28 , 255,  96},
  {29 , 255,  96},
  {30 , 255,  96},
  {31 , 255,  96},
  {32 , 255,  96},
  {33 , 255,  96},
  {34 , 208,  96},
  {35 , 192,  96},
  {36 , 181,  96},
  {37 , 172,  96},
  {38 , 165,  96},
  {39 , 159,  96},
  {40 , 153,  96},
  {41 , 149,  96},
  {42 , 144,  96},
  {43 , 140,  96},
  {44 , 136 , 96},
  {45 , 133 , 96},
  {46 , 129 , 96},
  {47 , 126 , 96},
  {48 , 123 , 96},
  {49 , 119 , 96},
  {50 , 117 , 96},
  {51 , 114 , 96},
  {52 , 111 , 96},
  {53 , 108 , 96},
  {54 , 105 , 96},
  {55 , 103 , 96},
  {56 , 101 , 96},
  {57 , 98  , 96},
  {58 , 96  , 96},
  {59 , 93  , 96},
  {60 , 91  , 96},
  {61 , 89  , 96},
  {62 , 88  , 96},
  {63 , 87  , 96},
  {64 , 86  , 96},
  {65 , 86  , 96},
  {66 , 86  , 96},
  {67 , 86  , 96},
  {68 , 86  , 96},
  {69 , 86  , 96},
  {70 , 86  , 96},
  {71 , 85  , 96},
  {72 , 85  , 96},
  {73 , 85  , 96},
  {74 , 85  , 96},
  {75 , 85  , 96},
  {76 , 85  , 96},
  {77 , 85  , 96},
  {78 , 85  , 96},
  {79 , 85  , 96},
  {80 , 85  , 96},
  {81 , 85  , 96},
  {82 , 85  , 96},
  {83 , 84  , 96},
  {84 , 84  , 96},
  {85 , 84  , 96},
  {86 , 84  , 96},
  {87 , 84  , 96},
  {88 , 84  , 96},
  {89 , 84  , 96},
  {90 , 84  , 96},

  {0      ,0      , 0}              // end of table mark!!
};


//for china cable project which use CD1616
static tm10023RFLvl_Agc_t RFLvl_Agc_Table_CD1616_IFMIN_60[]=
{
  {94     ,31     ,96   }      ,
  {93     ,33     ,96    }     ,
  {93     ,34     ,96    }     ,
  {92     ,35     ,96    }     ,
  {92     ,36     ,96    }     ,
  {91     ,37     ,96    }     ,
  {91     ,39     ,96    }     ,
  {90     ,40     ,96    }     ,
  {90     ,41     ,96    }     ,
  {89     ,42     ,96    }     ,
  {89     ,44     ,96    }     ,
  {88     ,45     ,96    }     ,
  {88     ,47     ,96    }     ,
  {87     ,49     ,96    }     ,
  {87     ,50     ,96    }     ,
  {86     ,52     ,96    }     ,
  {86     ,53     ,96    }     ,
  {85     ,55     ,96    }     ,
  {85     ,57     ,96    }     ,
  {84     ,59     ,96    }     ,
  {84     ,61     ,96    }     ,
  {83     ,63     ,96    }     ,
  {83     ,66     ,96    }     ,
  {82     ,68     ,96    }     ,
  {82     ,70     ,96    }     ,
  {81     ,72     ,96    }     ,
  {81     ,75     ,96    }     ,
  {80     ,78     ,96    }     ,
  {80     ,81     ,96    }     ,
  {79     ,83     ,96    }     ,
  {79     ,86     ,96    }     ,
  {78     ,89     ,96    }     ,
  {78     ,93     ,96    }     ,
  {77     ,96     ,96    }     ,
  {77     ,99     ,96    }     ,
  {76     ,103    , 96    }    ,
  {76     ,106    , 96    }    ,
  {75     ,109    , 96    }    ,
  {75     ,112    , 96    }    ,
  {74     ,115    , 96    }    ,
  {74     ,118    , 96    }    ,
  {73     ,121    , 96    }    ,
  {73     ,124    , 96    }    ,
  {72     ,126    , 96    }    ,
  {72     ,130    , 96    }    ,
  {71     ,132    , 96    }    ,
  {71     ,134    , 96    }    ,
  {70     ,136    , 96    }    ,
  {70     ,138    , 96    }    ,
  {69     ,140    , 96    }    ,
  {69     ,142    , 96    }    ,
  {68     ,144    , 96    }    ,
  {68     ,146    , 96    }    ,
  {67     ,147    , 96    }    ,
  {67     ,149    , 96    }    ,
  {66     ,150    , 96    }    ,
  {66     ,152    , 96    }    ,
  {65     ,153    , 96    }    ,
  {65     ,154    , 96    }    ,
  {64     ,156    , 96    }    ,
  {64     ,157    , 96    }    ,
  {63     ,158    , 96    }    ,
  {63     ,159    , 96    }    ,
  {62     ,160    , 96    }    ,
  {62     ,161    , 96    }    ,
  {61     ,163    , 96    }    ,
  {61     ,164    , 96    }    ,
  {60     ,165    , 96    }    ,
  {60     ,166    , 96    }    ,
  {59     ,167    , 96    }    ,
  {59     ,168    , 96    }    ,
  {58     ,169    , 96    }    ,
  {58     ,171    , 96    }    ,
  {57     ,172    , 96    }    ,
  {57     ,173    , 96    }    ,
  {56     ,174    , 96    }    ,
  {56     ,175    , 96    }    ,
  {55     ,176    , 96    }    ,
  {55     ,178    , 96    }    ,
  {54     ,179    , 96    }    ,
  {54     ,181    , 96    }    ,
  {53     ,182    , 96    }    ,
  {53     ,185    , 96    }    ,
  {52     ,188    , 96    }    ,
  {52     ,193    , 96    }    ,
  {51     ,205    , 96    }    ,
  {51     ,225    , 96    }    ,
  {50     ,255    , 96    }    ,
  {50     ,255    , 97    }    ,
  {49     ,255    , 98    }    ,
  {49     ,255    , 100   }    ,
  {48     ,255    , 101   }    ,
  {48     ,255    , 102   }    ,
  {47     ,255    , 104   }    ,
  {47     ,255    , 105   }    ,
  {46     ,255    , 106   }    ,
  {46     ,255    , 108   }    ,
  {45     ,255    , 109   }    ,
  {45     ,255    , 110   }    ,
  {44     ,255    , 112   }    ,
  {44     ,255    , 113   }    ,
  {43     ,255    , 115   }    ,
  {43     ,255    , 116   }    ,
  {42     ,255    , 118   }    ,
  {42     ,255    , 119   }    ,
  {41     ,255    , 121   }    ,
  {41     ,255    , 123   }    ,
  {40     ,255    , 124   }    ,
  {40     ,255    , 126   }    ,
  {39     ,255    , 128   }    ,
  {39     ,255    , 130   }    ,
  {38     ,255    , 132   }    ,
  {38     ,255    , 134   }    ,
  {37     ,255    , 136   }    ,
  {37     ,255    , 139   }    ,
  {36     ,255    , 141   }    ,
  {36     ,255    , 144   }    ,
  {35     ,255    , 146   }    ,
  {35     ,255    , 149   }    ,
  {34     ,255    , 152   }    ,
  {34     ,255    , 155   }    ,
  {33     ,255    , 159   }    ,
  {33     ,255    , 163   }    ,
  {32     ,255    , 167   }    ,
  {32     ,255    , 173   }    ,
  {31     ,255    , 180   }    ,
  {31     ,255    , 186   }    ,
  {30     ,255    , 199   }    ,
  {30     ,255    , 225   }    ,
  {29     ,255    , 255   }    ,
  {29     ,255    , 255   }    ,
  {28     ,255    , 255   }    ,
  {28     ,255    , 255   }    ,
  {27     ,255    , 255   }    ,
  {27     ,255    , 255   }    ,
  {26     ,255    , 255   }    ,
  {26     ,255    , 255   }    ,

  {0      ,0      , 0}              // end of table mark!!
};


#endif //#ifdef _CHINA_CABLE_


#ifdef NO_REDUNDANT_LOCKING
static struct dvb_frontend_parameters  sCurrent;
#endif

static  UInt32 uNbNoLock = 0;
static struct tda10024_state* sState;
//-----------------------------------------------------------------------------
// Internal Prototypes:
//-----------------------------------------------------------------------------
//
tmErrorCode_t tmbsl10023GetIQ (tmUnitSelect_t demodUnit, UInt32 *puIQ);
tmErrorCode_t tmbsl10023GetCOEF (tmUnitSelect_t demodUnit, Int32 *plCoef);

tmErrorCode_t Tda10023WriteInit(tm10023object_t *psObject);
tmErrorCode_t Tda10023WriteRF (tm10023object_t *psObject, UInt32 *puRF);
tmErrorCode_t Tda10023WriteSR (tm10023object_t *psObject, UInt32 *puSR);
tmErrorCode_t Tda10023WriteQAM (tm10023object_t *psObject, UInt32 uMod);
tmErrorCode_t Tda10023WriteNextScan (tm10023object_t *psObject);
tmErrorCode_t Tda10023ResetAll (tm10023object_t *psObject);

tmErrorCode_t Tda10023ReadAFC (tm10023object_t *psObject, Int32 *plAfc);
tmErrorCode_t Tda10023ReadRSSI (tm10023object_t  *psObject, Int8 *pRssi);

#ifdef _CHINA_CABLE_
tmErrorCode_t Tda10023GetLVL (tm10023object_t  *psObject, Int8 *pRssi);
#endif //#ifdef _CHINA_CABLE_

UInt16 Tda10023_AlgoCalcTimer( tm10023object_t *psObject, UInt32 uNbSymbol);
UInt16 Tda10023_CalcTimerAnalog( tm10023object_t *psObject);
tmhalFEManagerStatus_t Tda10023_MainAlgo (tm10023object_t *psObject, UInt16 *pAlgoTimer);
tmhalFEManagerStatus_t Tda10023_AlgoGain(tm10023object_t *psObject, UInt16 *pAlgoTimer);
tmhalFEManagerStatus_t Tda10023_AlgoMod( tm10023object_t *psObject);
tmhalFEManagerStatus_t Tda10023_AlgoClkOffset( tm10023object_t *psObject);
tmErrorCode_t Tda10023ResetDeltaF(tm10023object_t *psObject);
tmErrorCode_t Tda10023ManageBandType(tm10023object_t *psObject);
tmErrorCode_t Tda10023ManageBandTypeGain(tm10023object_t *psObject, tmhalFEManagerStatus_t *Status);

#ifdef _CHINA_CABLE_
void TDA10023SolveADCHarmonic(tmUnitSelect_t demodUnit, UInt32 uRF);
#endif //#ifdef _CHINA_CABLE_

#ifdef NO_FLOAT
void Tda10023Mul64(UInt32 uUp1, UInt32 uUp2, UInt32* uHighInt, UInt32* uLowInt);
UInt32 Tda10023Div64(UInt32 uHighInt, UInt32 uLowInt, UInt32 uDown);
UInt32 Tda10023MulDiv32(UInt32 uUp1, UInt32 uUp2, UInt32 uDown);
#endif



static void internal10023Wait(int ms)
{
    mdelay(ms);
}

//-----------------------------------------------------------------------------
// Exported functions:
//-----------------------------------------------------------------------------
//

//-----------------------------------------------------------------------------
// Initialization functions:
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
// FUNCTION:    tmbsl10023Init:
//
// DESCRIPTION: create an instance of a TDA10023 demodulator
//
// RETURN:      TMBSL_ERR_DEMOD_BAD_UNIT_NUMBER
//              TM_OK
//
// NOTES:
//-----------------------------------------------------------------------------
//
tmErrorCode_t
tmbsl10023Init(
    tmUnitSelect_t  demodUnit,      //  I: Demodulator unit number
    tmbslDcParam_t  sParam          //  I: setup parameters
    )
{
    SEND_TRACEFCT1(DEBUG_INIT_ID, 0);

    //----------------------
    // test input parameters
    //----------------------
    // test the max number
    if (demodUnit > TDA10023_MAX_UNITS)
        return TMBSL_ERR_DEMOD_BAD_UNIT_NUMBER;

    // return if already initialized
    if(g10023Instance[demodUnit].sApiFlags.iInit == True)
        return TMBSL_ERR_DEMOD_BAD_UNIT_NUMBER;

    //----------------
    // init the object
    //----------------
    // initialize the object
    g10023Instance[demodUnit].sApiFlags.iInit = True;
    g10023Instance[demodUnit].uDemodHwAdd     = sParam.uHwAddress;
    g10023Instance[demodUnit].systemFunc      = sParam.systemFunc;
#ifndef _WIN32
    g10023Instance[demodUnit].dlFeInstance_U  = sParam.dlFeInstance_U;
#endif

    // call init function here to prevent calling SetConfig if the default values are OK
    return Tda10023WriteInit(&g10023Instance[demodUnit]);
}


//-----------------------------------------------------------------------------
// FUNCTION:    tmbsl10023DeInit:
//
// DESCRIPTION: destroy an instance of a TDA10023 tuner
//
// RETURN:      TMBSL_ERR_DEMOD_BAD_UNIT_NUMBER
//              TMBSL_ERR_DEMOD_NOT_INITIALIZED
//              TM_OK
//
// NOTES:
//-----------------------------------------------------------------------------
//
tmErrorCode_t
tmbsl10023DeInit (
    tmUnitSelect_t   demodUnit     //  I: Demod unit number
    )
{
    SEND_TRACEFCT1(DEBUG_DEINIT_ID, 0);

    //----------------------
    // test input parameters
    //----------------------
    // test the instance number
    if (demodUnit > TDA10023_MAX_UNITS)
        return TMBSL_ERR_DEMOD_BAD_UNIT_NUMBER;

    // test the object
    if (g10023Instance[demodUnit].sApiFlags.iInit == False)
        return TMBSL_ERR_DEMOD_NOT_INITIALIZED;

    //-------------------------
    // De-initialize the object
    //-------------------------
    g10023Instance[demodUnit].sApiFlags.iInit = False;

    return TM_OK;
}


//-----------------------------------------------------------------------------
// FUNCTION:    tmbsl10023GetSWVersion:
//
// DESCRIPTION: Return the version of this device
//
// RETURN:      TM_OK
//
// NOTES:       Values defined in the tm10023local.h file
//-----------------------------------------------------------------------------
//
tmErrorCode_t
tmbsl10023GetSWVersion (
    ptmSWVersion_t   pSWVersion     //  I: Receives SW Version
    )
{
    SEND_TRACEFCT1(DEBUG_GETSWVER_ID, 0);

    pSWVersion->compatibilityNr = TDA10023_BSL_COMP_NUM;
    pSWVersion->majorVersionNr  = TDA10023_BSL_MAJOR_VER;
    pSWVersion->minorVersionNr  = TDA10023_BSL_MINOR_VER;

    return TM_OK;
}

//-----------------------------------------------------------------------------
// Configuration functions:
//-----------------------------------------------------------------------------
//

//-----------------------------------------------------------------------------
// FUNCTION:    tmbsl10023SetPowerState:
//
// DESCRIPTION: Set the power state of the 10023
//
// RETURN:      TMBSL_ERR_DEMOD_BAD_UNIT_NUMBER
//              TMBSL_ERR_DEMOD_NOT_INITIALIZED
//              TM_ERR_IIC_ERR
//              TM_OK
//
// NOTES:
//-----------------------------------------------------------------------------
//
tmErrorCode_t
tmbsl10023SetPowerState(
        tmUnitSelect_t    demodUnit,      //  I: demodUnit number
        tmPowerState_t    ePowerState     //  I: Power state of the device
        )
{
    UInt32 uByte=0;

    SEND_TRACEFCT1(DEBUG_SETPOWERSTATE_ID, 0);

    //----------------------
    // test input parameters
    //----------------------
    // test the instance number
    if (demodUnit > TDA10023_MAX_UNITS)
        return TMBSL_ERR_DEMOD_BAD_UNIT_NUMBER;

    // test the object
    if (g10023Instance[demodUnit].sApiFlags.iInit == False)
        return TMBSL_ERR_DEMOD_NOT_INITIALIZED;

    //----------------------
    // Implementation
    //----------------------
    switch (ePowerState)
    {
        case tmPowerStandby:
            uByte = TDA10023_GPR_STDBY_BIT;
            break;
        case tmPowerOn:
            uByte = 0;
            break;
    }

    // program the chip
    if (g10023Instance[demodUnit].systemFunc.SY_WriteBit(
        g10023Instance[demodUnit].uDemodHwAdd,
        TDA10023_GPR_IND, TDA10023_GPR_STDBY_BIT,
        uByte) != True)
        return TM_ERR_IIC_ERR;

  // connect tuner to I2C bus
     if(g10023Instance[demodUnit].systemFunc.SY_WriteBit( g10023Instance[demodUnit].uDemodHwAdd,
        TDA10023_TEST_IND, TDA10023_TEST_BYPIIC_BIT,
        TDA10023_TEST_BYPIIC_BIT) == False) return TM_ERR_IIC_ERR;

    // tuner is disconnected from the I2C bus
    if(g10023Instance[demodUnit].systemFunc.SY_WriteBit( g10023Instance[demodUnit].uDemodHwAdd,
        TDA10023_TEST_IND, TDA10023_TEST_BYPIIC_BIT, 0) == False) return TM_ERR_IIC_ERR;


    return TM_OK;
}

//-----------------------------------------------------------------------------
// FUNCTION:    tmbsl10023GetPowerState:
//
// DESCRIPTION: Set the power state of the 10023
//
// RETURN:      TMBSL_ERR_DEMOD_BAD_UNIT_NUMBER
//              TMBSL_ERR_DEMOD_NOT_INITIALIZED
//              TM_ERR_IIC_ERR
//              TM_OK
//
// NOTES:
//-----------------------------------------------------------------------------
//
tmErrorCode_t
tmbsl10023GetPowerState(
    tmUnitSelect_t     demodUnit,        //  I: demodUnit number
    ptmPowerState_t    pPowerState       //  O: Receives current power state
    )
{
    UInt32 uByte;

    SEND_TRACEFCT1(DEBUG_GETPOWERSTATE_ID, 0);

    //----------------------
    // test input parameters
    //----------------------
    // test the instance number
    if (demodUnit > TDA10023_MAX_UNITS)
        return TMBSL_ERR_DEMOD_BAD_UNIT_NUMBER;

    // test the object
    if (g10023Instance[demodUnit].sApiFlags.iInit == False)
        return TMBSL_ERR_DEMOD_NOT_INITIALIZED;

    //----------------------
    // Implementation
    //----------------------
    if (g10023Instance[demodUnit].systemFunc.SY_Read(
        g10023Instance[demodUnit].uDemodHwAdd,
        TDA10023_GPR_IND, 1,
        &uByte) != True)
        return TM_ERR_IIC_ERR;

    if (uByte & TDA10023_GPR_STDBY_BIT)
        *pPowerState = tmPowerStandby;
    else
        *pPowerState = tmPowerOn;

    return TM_OK;
}

//-----------------------------------------------------------------------------
// FUNCTION:    tmbsl10023SetConfig:
//
// DESCRIPTION: Set the config of the 10023
//
// RETURN:      TMBSL_ERR_DEMOD_BAD_UNIT_NUMBER
//              TMBSL_ERR_DEMOD_NOT_INITIALIZED
//              TM_ERR_BAD_PARAMETER
//              TM_ERR_IIC_ERR
//              TM_OK
//
// NOTES:       This function can be removed if needed
//-----------------------------------------------------------------------------
//
tmErrorCode_t
tmbsl10023SetConfig(
    tmUnitSelect_t    demodUnit,   //  I: demodUnit number
    UInt32            uItemId,     //  I: Identifier of the item to modify
    UInt32            uValue       //  I: Value to set for the config item
    )
{
    UInt32 puBytes[2];
    tmErrorCode_t Error_Code;

    SEND_TRACEFCT2(DEBUG_SETCONFIG_ID, 0);

    //----------------------
    // test input parameters
    //----------------------
    // test the instance number
    if (demodUnit > TDA10023_MAX_UNITS)
        return TMBSL_ERR_DEMOD_BAD_UNIT_NUMBER;

    // test the object
    if (g10023Instance[demodUnit].sApiFlags.iInit == False)
        return TMBSL_ERR_DEMOD_NOT_INITIALIZED;

    //--------------
    // set the value
    //--------------
    switch((tm10023cfgIndex_t)uItemId)
    {
        case BOARD:
            // default hardware config
//            g10023Instance[demodUnit].sConfig.bModeDvbMcns      = OM57XX_MODE_MCNS_DEF;
            g10023Instance[demodUnit].sConfig.uXtalFreq         = OM57XX_XTALL_DEF;
//            g10023Instance[demodUnit].sConfig.bPLL_M_Factor     = OM57XX_PLLMFACTOR_MCNS_DEF;
//            g10023Instance[demodUnit].sConfig.bPLL_N_Factor     = OM57XX_PLLNFACTOR_MCNS_DEF;
//            g10023Instance[demodUnit].sConfig.bPLL_P_Factor     = OM57XX_PLLPFACTOR_MCNS_DEF;
//            g10023Instance[demodUnit].sConfig.bFsampling        = OM57XX_FSAMPLING_DEF;
            g10023Instance[demodUnit].sConfig.bIFMax            = OM57XX_IFMAX_DEF;
            g10023Instance[demodUnit].sConfig.bIFMin            = OM57XX_IFMIN_DEF;
            g10023Instance[demodUnit].sConfig.bTUNMax           = OM57XX_TUNMAX_DEF;
            g10023Instance[demodUnit].sConfig.bTUNMin           = OM57XX_TUNMIN_DEF;
            g10023Instance[demodUnit].sConfig.bAGCtreshold      = OM57XX_AGCTRESHOLD_DEF;
            g10023Instance[demodUnit].sConfig.bEqualType        = OM57XX_EQUALTYPE_DEF;
            g10023Instance[demodUnit].sConfig.bPolaPWM1         = OM57XX_POLAPWM1_DEF;
            g10023Instance[demodUnit].sConfig.bPolaPWM2         = OM57XX_POLAPWM2_DEF;
//            g10023Instance[demodUnit].sConfig.bBERdepth         = OM57XX_BERDEPTH_MCNS_DEF;
            g10023Instance[demodUnit].sConfig.bClkOffsetRange   = OM57XX_CLKOFFSETRANGE_DEF;
            g10023Instance[demodUnit].sConfig.bTUN_IQSwap       = OM57XX_IQSWAP_DEF;
//            g10023Instance[demodUnit].sConfig.uTUN_IF           = OM57XX_IF_MCNS_DEF;
            g10023Instance[demodUnit].sConfig.bOUT_OClk1        = OM57XX_OCLK1_DEF;
            g10023Instance[demodUnit].sConfig.bOUT_bParaSer1    = OM57XX_PARASER1_DEF;
            g10023Instance[demodUnit].sConfig.bOUT_bMSBFirst1   = OM57XX_MSBFIRST1_DEF;
            g10023Instance[demodUnit].sConfig.bOUT_ModeABC1     = OM57XX_MODEABC1_DEF;
            g10023Instance[demodUnit].sConfig.bOUT_ParaDiv1     = OM57XX_PARADIV1_DEF;
            g10023Instance[demodUnit].sConfig.bOUT_OClk2        = OM57XX_OCLK2_DEF;
            g10023Instance[demodUnit].sConfig.bOUT_bMSBFirst2   = OM57XX_MSBFIRST2_DEF;
            g10023Instance[demodUnit].sConfig.bSwDyn            = OM57XX_SWDYN_DEF;
            g10023Instance[demodUnit].sConfig.bSwStep           = OM57XX_SWSTEP_DEF;
      g10023Instance[demodUnit].sConfig.uBoardConf    = uValue;

      if (uValue!=0)
        g10023Instance[demodUnit].sConfig.uBoard = uValue;
      else
        uValue = g10023Instance[demodUnit].sConfig.uBoard;

            switch (g10023Instance[demodUnit].sConfig.bSwDyn)
      {
      case 0:
        g10023Instance[demodUnit].uSWDynValue = 234;
        break;
      case 1:
        g10023Instance[demodUnit].uSWDynValue = 468;
        break;
      case 2:
        g10023Instance[demodUnit].uSWDynValue = 700;
        break;
      case 3:
        g10023Instance[demodUnit].uSWDynValue = 937;
        break;
      case 4:
        g10023Instance[demodUnit].uSWDynValue = 1170;
        break;
      case 5:
        g10023Instance[demodUnit].uSWDynValue = 1406;
        break;
      case 6:
        g10023Instance[demodUnit].uSWDynValue = 1640;
        break;
      case 7:
        g10023Instance[demodUnit].uSWDynValue = 1875;
        break;
      default:
        g10023Instance[demodUnit].uSWDynValue = 468;
        break;
      }
      switch (g10023Instance[demodUnit].sConfig.bSwStep)
      {
      case 0:
        g10023Instance[demodUnit].uSWStepValue = 145;
        break;
      case 1:
        g10023Instance[demodUnit].uSWStepValue = 290;
        break;
      default:
        g10023Instance[demodUnit].uSWStepValue = 290;
        break;
      }
            // specific board config
            switch (uValue & 0xffff0000)
            {
            case OM5755_BOARD_DEF:
                // sub-board
                switch(uValue & 0xff00)
                {

        case 0x0100:
                    g10023Instance[demodUnit].sConfig.bModeDvbMcns  = OM57XX_MODE_MCNS_DEF;
                    g10023Instance[demodUnit].sConfig.uTUN_IF       = OM57XX_IF_MCNS_DEF;
                    g10023Instance[demodUnit].sConfig.bPLL_M_Factor = OM57XX_PLLMFACTOR_MCNS_DEF;
                    g10023Instance[demodUnit].sConfig.bPLL_N_Factor = OM57XX_PLLNFACTOR_MCNS_DEF;
                    g10023Instance[demodUnit].sConfig.bPLL_P_Factor = OM57XX_PLLPFACTOR_MCNS_DEF;
                    g10023Instance[demodUnit].sConfig.bBERdepth     = OM57XX_BERDEPTH_MCNS_DEF;
                    g10023Instance[demodUnit].sConfig.bFsampling    = OM57XX_FSAMPLING_DEF;
                    break;

        case 0x0200:
                    g10023Instance[demodUnit].sConfig.bModeDvbMcns  = OM57XX_MODE_DVB_DEF;
                    g10023Instance[demodUnit].sConfig.uTUN_IF       = OM57XX_IF_DVB_DEF;
                    g10023Instance[demodUnit].sConfig.bPLL_M_Factor = OM57XX_PLLMFACTOR_DVB_DEF;
                    g10023Instance[demodUnit].sConfig.bPLL_N_Factor = OM57XX_PLLNFACTOR_DVB_DEF;
                    g10023Instance[demodUnit].sConfig.bPLL_P_Factor = OM57XX_PLLPFACTOR_DVB_DEF;
                    g10023Instance[demodUnit].sConfig.bBERdepth     = OM57XX_BERDEPTH_DVB_DEF;
                    g10023Instance[demodUnit].sConfig.bFsampling    = OM57XX_FSAMPLING_DEF;
                    break;

                default:
                    // board not supported
                    return TM_ERR_NOT_SUPPORTED;
                }
               break;

            case OM5763_BOARD_DEF:
            case OM5764_BOARD_DEF:
                // sub-board
                switch(uValue & 0xff00)
                {
                case 0x0000:
                    g10023Instance[demodUnit].sConfig.bModeDvbMcns  = OM57XX_MODE_MCNS_DEF;
                    g10023Instance[demodUnit].sConfig.uTUN_IF       = OM5763_IF_MCNS_DEF;
                    g10023Instance[demodUnit].sConfig.bPLL_M_Factor = OM57XX_PLLMFACTOR_MCNS_DEF;
                    g10023Instance[demodUnit].sConfig.bPLL_N_Factor = OM57XX_PLLNFACTOR_MCNS_DEF;
                    g10023Instance[demodUnit].sConfig.bPLL_P_Factor = OM57XX_PLLPFACTOR_MCNS_DEF;
                    g10023Instance[demodUnit].sConfig.bBERdepth     = OM57XX_BERDEPTH_MCNS_DEF;
                    g10023Instance[demodUnit].sConfig.bFsampling    = OM5763_FSAMPLING_DEF;
                    break;

                case 0x0100:
                    g10023Instance[demodUnit].sConfig.bModeDvbMcns  = OM57XX_MODE_DVB_DEF;
                    g10023Instance[demodUnit].sConfig.uTUN_IF       = OM5763_IF_DVB_DEF;
                    g10023Instance[demodUnit].sConfig.bPLL_M_Factor = OM57XX_PLLMFACTOR_DVB_DEF;
                    g10023Instance[demodUnit].sConfig.bPLL_N_Factor = OM57XX_PLLNFACTOR_DVB_DEF;
                    g10023Instance[demodUnit].sConfig.bPLL_P_Factor = OM57XX_PLLPFACTOR_DVB_DEF;
                    g10023Instance[demodUnit].sConfig.bBERdepth     = OM57XX_BERDEPTH_DVB_DEF;
                    g10023Instance[demodUnit].sConfig.bFsampling    = OM5763_FSAMPLING_DEF;
                    break;

                default:
                    // board not supported
                    return TM_ERR_NOT_SUPPORTED;
                }
               break;

      case CU1216_BOARD_DEF:
                // sub-board
                switch(uValue & 0xff00)
                {
                case 0x0000:
                    g10023Instance[demodUnit].sConfig.bModeDvbMcns  = OM57XX_MODE_DVB_DEF;
                    g10023Instance[demodUnit].sConfig.uTUN_IF       = OM57XX_IF_DVB_DEF;
                    g10023Instance[demodUnit].sConfig.bPLL_M_Factor = OM57XX_PLLMFACTOR_DVB_DEF;
                    g10023Instance[demodUnit].sConfig.bPLL_N_Factor = OM57XX_PLLNFACTOR_DVB_DEF;
                    g10023Instance[demodUnit].sConfig.bPLL_P_Factor = OM57XX_PLLPFACTOR_DVB_DEF;
                    g10023Instance[demodUnit].sConfig.bBERdepth     = OM57XX_BERDEPTH_DVB_DEF;
                    g10023Instance[demodUnit].sConfig.bFsampling    = OM57XX_FSAMPLING_DEF;

          g10023Instance[demodUnit].sConfig.uXtalFreq         = CU1216_XTALL_FREQ_28;// for 1306.
                    if (g10023Instance[demodUnit].sConfig.uXtalFreq == CU1216_XTALL_FREQ_28)
          {
            g10023Instance[demodUnit].sConfig.bPLL_M_Factor = CU1216_PLLMFACTOR_DVB_DEF;
            g10023Instance[demodUnit].sConfig.bPLL_N_Factor = CU1216_PLLNFACTOR_DVB_DEF;
            g10023Instance[demodUnit].sConfig.bPLL_P_Factor = CU1216_PLLPFACTOR_DVB_DEF;
          }
          break;
                case 0x0100:
                    g10023Instance[demodUnit].sConfig.bModeDvbMcns  = OM57XX_MODE_MCNS_DEF;
                    g10023Instance[demodUnit].sConfig.uTUN_IF       = OM57XX_IF_MCNS_DEF;
                    g10023Instance[demodUnit].sConfig.bPLL_M_Factor = OM57XX_PLLMFACTOR_MCNS_DEF;
                    g10023Instance[demodUnit].sConfig.bPLL_N_Factor = OM57XX_PLLNFACTOR_MCNS_DEF;
                    g10023Instance[demodUnit].sConfig.bPLL_P_Factor = OM57XX_PLLPFACTOR_MCNS_DEF;
                    g10023Instance[demodUnit].sConfig.bBERdepth     = OM57XX_BERDEPTH_MCNS_DEF;
                    g10023Instance[demodUnit].sConfig.bFsampling    = OM57XX_FSAMPLING_DEF;

                    if (g10023Instance[demodUnit].sConfig.uXtalFreq == CU1216_XTALL_FREQ_28)
          {
            g10023Instance[demodUnit].sConfig.bPLL_M_Factor = CU1216_PLLMFACTOR_MCNS_DEF;
            g10023Instance[demodUnit].sConfig.bPLL_N_Factor = CU1216_PLLNFACTOR_MCNS_DEF;
            g10023Instance[demodUnit].sConfig.bPLL_P_Factor = CU1216_PLLPFACTOR_MCNS_DEF;
          }
          break;

                default:
                    // board not supported
                    return TM_ERR_NOT_SUPPORTED;
                }
               break;

               /* Modified by David Han */
               /* Board CD1616 + TDA10023*/
            case OM5795_BOARD_DEF:

                g10023Instance[demodUnit].sConfig.uXtalFreq       = OM5795_XTALL_FREQ_28; // modified by David Han if 28.92MHz XTAL used for TDA10023
                g10023Instance[demodUnit].sConfig.bIFMin          = OM5795_IFMIN_DEF;   // Modified by David Han for CD1616 RF TOP
                g10023Instance[demodUnit].sConfig.bFsampling = OM57XX_FSAMPLING_DEF;

                // sub-board
                switch(uValue & 0xff00)
                {
                case 0x0000:
                    g10023Instance[demodUnit].sConfig.bModeDvbMcns  = OM57XX_MODE_DVB_DEF;
                    g10023Instance[demodUnit].sConfig.uTUN_IF       = OM57XX_IF_DVB_DEF;
            g10023Instance[demodUnit].sConfig.bPLL_M_Factor = OM5795_PLLMFACTOR_DVB_DEF;
            g10023Instance[demodUnit].sConfig.bPLL_N_Factor = OM5795_PLLNFACTOR_DVB_DEF;
            g10023Instance[demodUnit].sConfig.bPLL_P_Factor = OM5795_PLLPFACTOR_DVB_DEF;
                        g10023Instance[demodUnit].sConfig.bBERdepth     = OM57XX_BERDEPTH_DVB_DEF;

          break;

                case 0x0100:
                    g10023Instance[demodUnit].sConfig.bModeDvbMcns  = OM57XX_MODE_MCNS_DEF;
                    g10023Instance[demodUnit].sConfig.uTUN_IF       = OM57XX_IF_MCNS_DEF;
            g10023Instance[demodUnit].sConfig.bPLL_M_Factor = OM5795_PLLMFACTOR_MCNS_DEF;
            g10023Instance[demodUnit].sConfig.bPLL_N_Factor = OM5795_PLLNFACTOR_MCNS_DEF;
            g10023Instance[demodUnit].sConfig.bPLL_P_Factor = OM5795_PLLPFACTOR_MCNS_DEF;
                        g10023Instance[demodUnit].sConfig.bBERdepth     = OM57XX_BERDEPTH_MCNS_DEF;

          break;

                default:
                    // board not supported
                    return TM_ERR_NOT_SUPPORTED;
                }

               break;

      case 0x38530000:
                    g10023Instance[demodUnit].sConfig.bModeDvbMcns  = OM57XX_MODE_DVB_DEF;
                    g10023Instance[demodUnit].sConfig.uTUN_IF       = OM5763_IF_DVB_DEF;
                    g10023Instance[demodUnit].sConfig.bPLL_M_Factor = OM57XX_PLLMFACTOR_DVB_DEF;
                    g10023Instance[demodUnit].sConfig.bPLL_N_Factor = OM57XX_PLLNFACTOR_DVB_DEF;
                    g10023Instance[demodUnit].sConfig.bPLL_P_Factor = OM57XX_PLLPFACTOR_DVB_DEF;
                    g10023Instance[demodUnit].sConfig.bBERdepth     = OM57XX_BERDEPTH_DVB_DEF;
                    g10023Instance[demodUnit].sConfig.bFsampling    = OM5763_FSAMPLING_DEF;
        break;

            case CUSTOM_BOARD_DEF:
                // do nothing more than setting the default values
                break;

            default:
                // board not supported
                return TM_ERR_NOT_SUPPORTED;
            }

            break;

        case DVBMCNS:
            g10023Instance[demodUnit].sConfig.bModeDvbMcns = (UInt8)uValue;
            if(g10023Instance[demodUnit].sConfig.bModeDvbMcns)
            {
                // MCNS mode
                g10023Instance[demodUnit].sConfig.bPLL_M_Factor = OM57XX_PLLMFACTOR_MCNS_DEF;
                g10023Instance[demodUnit].sConfig.bPLL_N_Factor = OM57XX_PLLNFACTOR_MCNS_DEF;
                g10023Instance[demodUnit].sConfig.bPLL_P_Factor = OM57XX_PLLPFACTOR_MCNS_DEF;
                g10023Instance[demodUnit].sConfig.bBERdepth     = OM57XX_BERDEPTH_MCNS_DEF;

                if((g10023Instance[demodUnit].sConfig.uBoard & 0xffff0000) == OM5755_BOARD_DEF)
                {
                    g10023Instance[demodUnit].sConfig.uTUN_IF       = OM57XX_IF_MCNS_DEF;
                }
        else if ((g10023Instance[demodUnit].sConfig.uBoard & 0xffff0000) == CU1216_BOARD_DEF)
        {
                   g10023Instance[demodUnit].sConfig.uTUN_IF       = OM57XX_IF_MCNS_DEF;

           if (g10023Instance[demodUnit].sConfig.uXtalFreq == CU1216_XTALL_FREQ_28)
           {
            g10023Instance[demodUnit].sConfig.bPLL_M_Factor = CU1216_PLLMFACTOR_MCNS_DEF;
            g10023Instance[demodUnit].sConfig.bPLL_N_Factor = CU1216_PLLNFACTOR_MCNS_DEF;
            g10023Instance[demodUnit].sConfig.bPLL_P_Factor = CU1216_PLLPFACTOR_MCNS_DEF;
           }
        }
        else if((g10023Instance[demodUnit].sConfig.uBoard & 0xffff0000) == OM5795_BOARD_DEF)
                {
                    g10023Instance[demodUnit].sConfig.uTUN_IF       = OM57XX_IF_MCNS_DEF;

          if (g10023Instance[demodUnit].sConfig.uXtalFreq == OM5795_XTALL_FREQ_28)
          {
            g10023Instance[demodUnit].sConfig.bPLL_M_Factor = OM5795_PLLMFACTOR_MCNS_DEF;
            g10023Instance[demodUnit].sConfig.bPLL_N_Factor = OM5795_PLLNFACTOR_MCNS_DEF;
            g10023Instance[demodUnit].sConfig.bPLL_P_Factor = OM5795_PLLPFACTOR_MCNS_DEF;
          }
                }
                else
                {
                    g10023Instance[demodUnit].sConfig.uTUN_IF       = OM5763_IF_MCNS_DEF;
                }

            }
            else
            {
                // DVB mode
                g10023Instance[demodUnit].sConfig.bPLL_M_Factor = OM57XX_PLLMFACTOR_DVB_DEF;
                g10023Instance[demodUnit].sConfig.bPLL_N_Factor = OM57XX_PLLNFACTOR_DVB_DEF;
                g10023Instance[demodUnit].sConfig.bPLL_P_Factor = OM57XX_PLLPFACTOR_DVB_DEF;
                g10023Instance[demodUnit].sConfig.bBERdepth     = OM57XX_BERDEPTH_DVB_DEF;

                if((g10023Instance[demodUnit].sConfig.uBoard & 0xffff0000) == OM5755_BOARD_DEF)
                {
                    g10023Instance[demodUnit].sConfig.uTUN_IF       = OM57XX_IF_DVB_DEF;
                }
                else if((g10023Instance[demodUnit].sConfig.uBoard & 0xffff0000) == CU1216_BOARD_DEF)
                {
                    g10023Instance[demodUnit].sConfig.uTUN_IF       = OM57XX_IF_DVB_DEF;

          if (g10023Instance[demodUnit].sConfig.uXtalFreq == CU1216_XTALL_FREQ_28)
          {
            g10023Instance[demodUnit].sConfig.bPLL_M_Factor = CU1216_PLLMFACTOR_DVB_DEF;
            g10023Instance[demodUnit].sConfig.bPLL_N_Factor = CU1216_PLLNFACTOR_DVB_DEF;
            g10023Instance[demodUnit].sConfig.bPLL_P_Factor = CU1216_PLLPFACTOR_DVB_DEF;
          }
                }
                else if((g10023Instance[demodUnit].sConfig.uBoard & 0xffff0000) == OM5795_BOARD_DEF)
                {
                    g10023Instance[demodUnit].sConfig.uTUN_IF       = OM57XX_IF_DVB_DEF;

          if (g10023Instance[demodUnit].sConfig.uXtalFreq == OM5795_XTALL_FREQ_28)
          {
            g10023Instance[demodUnit].sConfig.bPLL_M_Factor = OM5795_PLLMFACTOR_DVB_DEF;
            g10023Instance[demodUnit].sConfig.bPLL_N_Factor = OM5795_PLLNFACTOR_DVB_DEF;
            g10023Instance[demodUnit].sConfig.bPLL_P_Factor = OM5795_PLLPFACTOR_DVB_DEF;
          }
                }
                else
                {
                    g10023Instance[demodUnit].sConfig.uTUN_IF       = OM5763_IF_DVB_DEF;
                }


        //write roll off (0.15)
        if(g10023Instance[demodUnit].systemFunc.SY_WriteBit(
          g10023Instance[demodUnit].uDemodHwAdd,
          TDA10023_GAIN2_IND, TDA10023_ROLL_OFF_MSK, 2) == False) return TM_ERR_IIC_ERR;

            }
            break;
        case XTALL:
            g10023Instance[demodUnit].sConfig.uXtalFreq = uValue;
            break;
        case PLLMFACTOR:
            g10023Instance[demodUnit].sConfig.bPLL_M_Factor = (UInt8)uValue;
            break;
        case PLLNFACTOR:
            g10023Instance[demodUnit].sConfig.bPLL_N_Factor = (UInt8)uValue;
            break;
        case PLLPFACTOR:
            g10023Instance[demodUnit].sConfig.bPLL_P_Factor = (UInt8)uValue;
            break;
        case FSAMPLING:
            g10023Instance[demodUnit].sConfig.bFsampling = (UInt8)uValue;
            break;
        case IFMAX:
            g10023Instance[demodUnit].sConfig.bIFMax = (UInt8)uValue;
            break;
        case IFMIN:
            g10023Instance[demodUnit].sConfig.bIFMin = (UInt8)uValue;
            break;
        case TUNMAX:
            g10023Instance[demodUnit].sConfig.bTUNMax = (UInt8)uValue;
            break;
        case TUNMIN:
            g10023Instance[demodUnit].sConfig.bTUNMin = (UInt8)uValue;
            break;
        case AGCTRESHOLD:
            g10023Instance[demodUnit].sConfig.bAGCtreshold = (UInt8)uValue;
            break;
        case EQUALTYPE:
            g10023Instance[demodUnit].sConfig.bEqualType = (UInt8)uValue;
            break;
        case POLAPWM1:
            g10023Instance[demodUnit].sConfig.bPolaPWM1 = (UInt8)uValue;
            break;
        case POLAPWM2:
            g10023Instance[demodUnit].sConfig.bPolaPWM2 = (UInt8)uValue;
            break;
        case BERDEPTH:
            g10023Instance[demodUnit].sConfig.bBERdepth = (UInt8)uValue;
            break;
        case BERWINDOW:
            g10023Instance[demodUnit].sConfig.uBERwindow = uValue;
            break;
        case CLKOFFSETRANGE:
            g10023Instance[demodUnit].sConfig.bClkOffsetRange = (UInt8)uValue;
            break;
        case IQSWAP:
            g10023Instance[demodUnit].sConfig.bTUN_IQSwap = (UInt8)uValue;
            break;
        case IF:
            g10023Instance[demodUnit].sConfig.uTUN_IF = uValue;
      switch (g10023Instance[demodUnit].sConfig.uBoard)
      {
        case 0x57640199:
                case 0x57640122:
          if(g10023Instance[demodUnit].systemFunc.SY_WriteBit(
            g10023Instance[demodUnit].uDemodHwAdd,
            TDA10023_TEST_IND, TDA10023_TEST_BYPIIC_BIT,
            TDA10023_TEST_BYPIIC_BIT) == False) return TM_ERR_IIC_ERR;

            // tuner is disconnected from the I2C bus
          if(g10023Instance[demodUnit].systemFunc.SY_WriteBit(
            g10023Instance[demodUnit].uDemodHwAdd,
            TDA10023_TEST_IND, TDA10023_TEST_BYPIIC_BIT, 0) == False) return TM_ERR_IIC_ERR;
            break;
                default:
                    break;
      }
            break;
        case OCLK1:
            g10023Instance[demodUnit].sConfig.bOUT_OClk1 = (UInt8)uValue;
            break;
        case PARASER1:
            g10023Instance[demodUnit].sConfig.bOUT_bParaSer1 = (UInt8)uValue;
            break;
        case MSBFIRST1:
            g10023Instance[demodUnit].sConfig.bOUT_bMSBFirst1 = (UInt8)uValue;
            break;
        case MODEABC1:
            g10023Instance[demodUnit].sConfig.bOUT_ModeABC1 = (UInt8)uValue;
            break;
        case PARADIV1:
            g10023Instance[demodUnit].sConfig.bOUT_ParaDiv1 = (UInt8)uValue;
            break;
        case OCLK2:
            g10023Instance[demodUnit].sConfig.bOUT_OClk2 = (UInt8)uValue;
            break;
        case MSBFIRST2:
            g10023Instance[demodUnit].sConfig.bOUT_bMSBFirst2 = (UInt8)uValue;
            break;
        case SWDYN:
            g10023Instance[demodUnit].sConfig.bSwDyn = (UInt8)uValue;

      switch (g10023Instance[demodUnit].sConfig.bSwDyn)
      {
      case 0:
        g10023Instance[demodUnit].uSWDynValue = 234;
        break;
      case 1:
        g10023Instance[demodUnit].uSWDynValue = 468;
        break;
      case 2:
        g10023Instance[demodUnit].uSWDynValue = 700;
        break;
      case 3:
        g10023Instance[demodUnit].uSWDynValue = 937;
        break;
      case 4:
        g10023Instance[demodUnit].uSWDynValue = 1170;
        break;
      case 5:
        g10023Instance[demodUnit].uSWDynValue = 1406;
        break;
      case 6:
        g10023Instance[demodUnit].uSWDynValue = 1640;
        break;
      case 7:
        g10023Instance[demodUnit].uSWDynValue = 1875;
        break;
      default:
        g10023Instance[demodUnit].uSWDynValue = 468;
        break;
      }

            break;
        case SWSTEP:
            g10023Instance[demodUnit].sConfig.bSwStep = (UInt8)uValue;

      switch (g10023Instance[demodUnit].sConfig.bSwStep)
      {
      case 0:
        g10023Instance[demodUnit].uSWStepValue = 145;
        break;
      case 1:
        g10023Instance[demodUnit].uSWStepValue = 290;
        break;
      default:
        g10023Instance[demodUnit].uSWStepValue = 290;
        break;
      }

            break;

        // backdoor functions
        case FEINIT:
            // init
            Error_Code = Tda10023WriteInit(&g10023Instance[demodUnit]);
            if(Error_Code != TM_OK) return(Error_Code);

            switch (g10023Instance[demodUnit].sConfig.uBoard)
            {
                case 0x57640122:
                    /* tuner is accessible*/
                    if(g10023Instance[demodUnit].systemFunc.SY_WriteBit(
                        g10023Instance[demodUnit].uDemodHwAdd,
                        TDA10023_TEST_IND, TDA10023_TEST_BYPIIC_BIT,
                        TDA10023_TEST_BYPIIC_BIT) == False) return TM_ERR_IIC_ERR;


                    /* tuner is disconnected from the I2C bus */
                    if(g10023Instance[demodUnit].systemFunc.SY_WriteBit(
                        g10023Instance[demodUnit].uDemodHwAdd,
                        TDA10023_TEST_IND, TDA10023_TEST_BYPIIC_BIT,
                        0) == False) return TM_ERR_IIC_ERR;
                    break;

                default:
                    break;
            }

            break;

        case SWITCH:
            if (uValue)
      {
                // tuner is accessible
                if(g10023Instance[demodUnit].systemFunc.SY_WriteBit(
                    g10023Instance[demodUnit].uDemodHwAdd,
                    TDA10023_TEST_IND, TDA10023_TEST_BYPIIC_BIT,
                    TDA10023_TEST_BYPIIC_BIT) == False) return TM_ERR_IIC_ERR;
      }
            else
            {
                // tuner is disconnected from the I2C bus
                if(g10023Instance[demodUnit].systemFunc.SY_WriteBit(
                    g10023Instance[demodUnit].uDemodHwAdd,
                    TDA10023_TEST_IND, TDA10023_TEST_BYPIIC_BIT, 0) == False) return TM_ERR_IIC_ERR;
            }
            break;

        case JQAMMODE:
            if(g10023Instance[demodUnit].systemFunc.SY_WriteBit(
                g10023Instance[demodUnit].uDemodHwAdd | TDA10023_JQAMFILTER_ADDR_OFFSET,
                TDA10023_JQAM_MODE_IND, TDA10023_JQAM_MODE_JQAM_MODE_MSK, uValue) == False) return TM_ERR_IIC_ERR;
            break;

        case JQAMREQTS:
            puBytes[0] = (UInt8)(uValue >> 8);
            puBytes[1] = (UInt8)(uValue);
            if(g10023Instance[demodUnit].systemFunc.SY_Write(
                g10023Instance[demodUnit].uDemodHwAdd | TDA10023_JQAMFILTER_ADDR_OFFSET,
                TDA10023_REQ_TS_IDH_IND, 2, puBytes) == False) return TM_ERR_IIC_ERR;
            break;

        case JQAMREQON:
            puBytes[0] = (UInt8)(uValue >> 8);
            puBytes[1] = (UInt8)(uValue);
            if(g10023Instance[demodUnit].systemFunc.SY_Write(
                g10023Instance[demodUnit].uDemodHwAdd | TDA10023_JQAMFILTER_ADDR_OFFSET,
                TDA10023_REQ_ON_IDH_IND, 2, puBytes) == False) return TM_ERR_IIC_ERR;
            break;

        case SRMIN:
            g10023Instance[demodUnit].sConfig.uStartSymbolRate = uValue;
            break;
        case SRMAX:
            g10023Instance[demodUnit].sConfig.uStopSymbolRate = uValue;
            break;

        case BAND:
      g10023Instance[demodUnit].eBandType = uValue;
      Tda10023ManageBandType( &g10023Instance[demodUnit] );
            break;

        default:
            return TM_ERR_BAD_PARAMETER;
    }

    // start algo
    if ((tm10023cfgIndex_t)uItemId != SWITCH )
    g10023Instance[demodUnit].sApiFlags.iStartAlgo = True;

    return TM_OK;
}

//-----------------------------------------------------------------------------
// FUNCTION:    tmbsl10023GetConfig:
//
// DESCRIPTION: Get the config of the 10023
//
// RETURN:      TMBSL_ERR_DEMOD_BAD_UNIT_NUMBER
//              TMBSL_ERR_DEMOD_NOT_INITIALIZED
//              TM_ERR_BAD_PARAMETER
//              TM_ERR_IIC_ERR
//              TM_OK
//
// NOTES:       This function can be removed if needed
//-----------------------------------------------------------------------------
//
tmErrorCode_t
tmbsl10023GetConfig(
    tmUnitSelect_t   demodUnit,   //  I: Demod unit number
    UInt32           uItemId,     //  I: Identifier of the item to modify
    UInt32*          puValue      //  O: Value to set for the config item
    )
{
    UInt32 uByte;
    UInt32 puBytes[4];
    int i;
  int j = 0;
  UInt32 uByteIT,uByteTestUncor,uByteUncor;

    SEND_TRACEFCT2(DEBUG_GETCONFIG_ID, 0);

    //----------------------
    // test input parameters
    //----------------------
    // test the instance number
    if (demodUnit > TDA10023_MAX_UNITS)
        return TMBSL_ERR_DEMOD_BAD_UNIT_NUMBER;

    // test the object
    if (g10023Instance[demodUnit].sApiFlags.iInit == False)
        return TMBSL_ERR_DEMOD_NOT_INITIALIZED;

    //----------------------
    // Implementation
    //----------------------
    // get the value
    switch((tm10023cfgIndex_t)uItemId)
    {
        // Board config
        case BOARD:
            *puValue = g10023Instance[demodUnit].sConfig.uBoardConf;
            break;
        case STANDARD:
            *puValue = tmhalFEStandardDVBC;
            break;
        case DVBMCNS:
            *puValue = g10023Instance[demodUnit].sConfig.bModeDvbMcns;
            break;
        case XTALL:
            *puValue = g10023Instance[demodUnit].sConfig.uXtalFreq;
            break;
        case PLLMFACTOR:
            *puValue = g10023Instance[demodUnit].sConfig.bPLL_M_Factor;
            break;
        case PLLNFACTOR:
            *puValue = g10023Instance[demodUnit].sConfig.bPLL_N_Factor;
            break;
        case PLLPFACTOR:
            *puValue = g10023Instance[demodUnit].sConfig.bPLL_P_Factor;
            break;
        case FSAMPLING:
            *puValue = g10023Instance[demodUnit].sConfig.bFsampling;
            break;
        case IFMAX:
            *puValue = g10023Instance[demodUnit].sConfig.bIFMax;
            break;
        case IFMIN:
            *puValue = g10023Instance[demodUnit].sConfig.bIFMin;
            break;
        case TUNMAX:
            *puValue = g10023Instance[demodUnit].sConfig.bTUNMax;
            break;
        case TUNMIN:
            *puValue = g10023Instance[demodUnit].sConfig.bTUNMin;
            break;
        case AGCTRESHOLD:
            *puValue = g10023Instance[demodUnit].sConfig.bAGCtreshold;
            break;
        case EQUALTYPE:
            *puValue = g10023Instance[demodUnit].sConfig.bEqualType;
            break;
        case POLAPWM1:
            *puValue = g10023Instance[demodUnit].sConfig.bPolaPWM1;
            break;
        case POLAPWM2:
            *puValue = g10023Instance[demodUnit].sConfig.bPolaPWM2;
            break;
        case BERDEPTH:
            *puValue = g10023Instance[demodUnit].sConfig.bBERdepth;
            break;
        case BERWINDOW:
            *puValue = g10023Instance[demodUnit].sConfig.uBERwindow;
            break;
        case CLKOFFSETRANGE:
            *puValue = g10023Instance[demodUnit].sConfig.bClkOffsetRange;
            break;
        case IQSWAP:
            *puValue = g10023Instance[demodUnit].sConfig.bTUN_IQSwap;
            break;
        case IF:
            *puValue = g10023Instance[demodUnit].sConfig.uTUN_IF;
            break;
        case OCLK1:
            *puValue = g10023Instance[demodUnit].sConfig.bOUT_OClk1;
            break;
        case PARASER1:
            *puValue = g10023Instance[demodUnit].sConfig.bOUT_bParaSer1;
            break;
        case MSBFIRST1:
            *puValue = g10023Instance[demodUnit].sConfig.bOUT_bMSBFirst1;
            break;
        case MODEABC1:
            *puValue = g10023Instance[demodUnit].sConfig.bOUT_ModeABC1;
            break;
        case PARADIV1:
            *puValue = g10023Instance[demodUnit].sConfig.bOUT_ParaDiv1;
            break;
        case OCLK2:
            *puValue = g10023Instance[demodUnit].sConfig.bOUT_OClk2;
            break;
        case MSBFIRST2:
            *puValue = g10023Instance[demodUnit].sConfig.bOUT_bMSBFirst2;
            break;
        case SWDYN:
            *puValue = g10023Instance[demodUnit].sConfig.bSwDyn;
            break;
        case SWSTEP:
            *puValue = g10023Instance[demodUnit].sConfig.bSwStep;
            break;
        case SRMIN:
            *puValue = g10023Instance[demodUnit].uStartSymbolRate;
            break;
        case SRMAX:
            *puValue = g10023Instance[demodUnit].uStopSymbolRate;
            break;
        // backdoor functions
  // Do not test IIC error since reading of IDENTITY happens after a reboot
        case IDENTITY:
            g10023Instance[demodUnit].systemFunc.SY_Read(
                g10023Instance[demodUnit].uDemodHwAdd,
                TDA10023_IDENTITY_IND, 1, &uByte);
            if (uByte != TDA10023_IDENTITY_DEF)
                *puValue = False;
            else
                *puValue = True;
            break;

        case READSYNC:
            if(g10023Instance[demodUnit].sConfig.bModeDvbMcns)
            {
                // MCNS mode
                // MPEGLCK and FRAMELCK
                if(g10023Instance[demodUnit].systemFunc.SY_Read(
                    g10023Instance[demodUnit].uDemodHwAdd,
                    TDA10023_STATUS_MCNS_IND, 1, &uByte) == False) return TM_ERR_IIC_ERR;

                // shift register to the left in order to have an equivalent mapping as in DVB mode
                *puValue = (uByte & (TDA10023_STATUS_MCNS_MPEGLCK_BIT | TDA10023_STATUS_MCNS_FRAMELCK_BIT)) << 1;

                // CARLOCK
                if(g10023Instance[demodUnit].systemFunc.SY_Read(
                    g10023Instance[demodUnit].uDemodHwAdd,
                    TDA10023_STATUS_IND, 1, &uByte) == False) return TM_ERR_IIC_ERR;

                *puValue |= (uByte & TDA10023_STATUS_CARLOCK_BIT);


        /****************************************************/
        /*BUG CORRECTION FOR STUFFING ISSUE IN MCNS     */
        /****************************************************/

        if(g10023Instance[demodUnit].systemFunc.SY_Read(
            g10023Instance[demodUnit].uDemodHwAdd,
            TDA10023_CPT_RSB_UNCOR1_IND,    4, puBytes) == False) return TM_ERR_IIC_ERR;

        uByteTestUncor = (puBytes[3]<<24) | (puBytes[2]<<16) | (puBytes[1]<<8) | puBytes[0];

        g10023Instance[demodUnit].systemFunc.SY_Read(
            g10023Instance[demodUnit].uDemodHwAdd,
            TDA10023_ITSTAT1_IND,    1, &uByteIT);

        internal10023Wait(1);

        g10023Instance[demodUnit].systemFunc.SY_Read(
            g10023Instance[demodUnit].uDemodHwAdd,
            TDA10023_ITSTAT1_IND,    1, &uByteIT);

        if(g10023Instance[demodUnit].systemFunc.SY_Read(
            g10023Instance[demodUnit].uDemodHwAdd,
            TDA10023_CPT_RSB_UNCOR1_IND,    4, puBytes) == False) return TM_ERR_IIC_ERR;

        uByteUncor = (puBytes[3]<<24) | (puBytes[2]<<16) | (puBytes[1]<<8) | puBytes[0];

        if ((uByteTestUncor == uByteUncor) && ((uByteIT & 0x04) != 0x00))
          *puValue &= 0xF7;

        /****************************************************/

            }
            else
            {
                // DVB mode
                if(g10023Instance[demodUnit].systemFunc.SY_Read(
                    g10023Instance[demodUnit].uDemodHwAdd,
                    TDA10023_STATUS_IND, 1, puValue) == False) return TM_ERR_IIC_ERR;
            }
            break;

        case READAGC:
            if(g10023Instance[demodUnit].systemFunc.SY_Read(
                g10023Instance[demodUnit].uDemodHwAdd,
                TDA10023_AGCIF_IND, 1, &uByte) == False) return TM_ERR_IIC_ERR;
            *puValue = uByte << 8;
            if(g10023Instance[demodUnit].systemFunc.SY_Read(
                g10023Instance[demodUnit].uDemodHwAdd,
                TDA10023_AGCTUN_IND, 1, &uByte) == False) return TM_ERR_IIC_ERR;
            *puValue |= uByte;
            break;

        case GETNBOFUNIT:
            *puValue = TDA10023_MAX_UNITS;
            break;

        case READIQ:
            return tmbsl10023GetIQ(demodUnit, puValue);

        case READCOEF:
            return tmbsl10023GetCOEF(demodUnit, puValue);

        case READMSE:
            if(g10023Instance[demodUnit].systemFunc.SY_Read(
                g10023Instance[demodUnit].uDemodHwAdd,
                TDA10023_MSE_IND, 1, puValue) == False) return TM_ERR_IIC_ERR;
            break;

        case STOPEQUAL:
            // freeze the equalizer coef only if the algorithm is not working
            if (g10023Instance[demodUnit].bState == 0)
                if(g10023Instance[demodUnit].systemFunc.SY_WriteBit(
                    g10023Instance[demodUnit].uDemodHwAdd,
                    TDA10023_EQCONF1_IND, TDA10023_EQCONF1_ENADAPT_BIT, 0) == False) return TM_ERR_IIC_ERR;
            break;

        case STARTEQUAL:
            // unfreeze the equalizer coef only if the algorithm is not working
            if (g10023Instance[demodUnit].bState == 0)
                if(g10023Instance[demodUnit].systemFunc.SY_WriteBit(
                    g10023Instance[demodUnit].uDemodHwAdd,
                    TDA10023_EQCONF1_IND, TDA10023_EQCONF1_ENADAPT_BIT, TDA10023_EQCONF1_ENADAPT_BIT) == False) return TM_ERR_IIC_ERR;
            break;

        case TUNERLVL:
            // Test if the GetLevel function is implemented
            // NOTE: if the GetLevel function is not implemented or not enabled, we must not
            // change the I2C switch. The trick used to determine if the function is enabled
            // is to call the getCfgFunc with a null pointer for the last parameter. In this
            // case, the function return TM_OK if the function is enabled.
            return TMBSL_ERR_DEMOD_NOT_SUPPORTED;
            break;


        case JQAMMODE:
            if(g10023Instance[demodUnit].systemFunc.SY_Read(
                g10023Instance[demodUnit].uDemodHwAdd | TDA10023_JQAMFILTER_ADDR_OFFSET,
                TDA10023_JQAM_MODE_IND, 1, puValue) == False) return TM_ERR_IIC_ERR;
            break;

        case JQAMREQTS:
            if(g10023Instance[demodUnit].systemFunc.SY_Read(
                g10023Instance[demodUnit].uDemodHwAdd | TDA10023_JQAMFILTER_ADDR_OFFSET,
                TDA10023_REQ_TS_IDH_IND, 2, puBytes) == False) return TM_ERR_IIC_ERR;
            *puValue = (puBytes[0] << 8) | puBytes[1];
            break;

        case JQAMREQON:
            if(g10023Instance[demodUnit].systemFunc.SY_Read(
                g10023Instance[demodUnit].uDemodHwAdd | TDA10023_JQAMFILTER_ADDR_OFFSET,
                TDA10023_REQ_ON_IDH_IND, 2, puBytes) == False) return TM_ERR_IIC_ERR;
            *puValue = (puBytes[0] << 8) | puBytes[1];
            break;

        case JQAMGETREG5:
            if(g10023Instance[demodUnit].systemFunc.SY_Read(
                g10023Instance[demodUnit].uDemodHwAdd | TDA10023_JQAMFILTER_ADDR_OFFSET,
                TDA10023_REG5_IND, 1, puValue) == False) return TM_ERR_IIC_ERR;
            break;

        case JQAMGETTSSTATUS:
            if(g10023Instance[demodUnit].systemFunc.SY_Read(
                g10023Instance[demodUnit].uDemodHwAdd | TDA10023_JQAMFILTER_ADDR_OFFSET,
                TDA10023_TS_STATUS_H_IND, 2, puBytes) == False) return TM_ERR_IIC_ERR;
            *puValue = (puBytes[0] << 8) | puBytes[1];
            break;

        case JQAMGETRCVSTATUS:
            if(g10023Instance[demodUnit].systemFunc.SY_Read(
                g10023Instance[demodUnit].uDemodHwAdd | TDA10023_JQAMFILTER_ADDR_OFFSET,
                TDA10023_RCV_STATUS4_IND, 4, puBytes) == False) return TM_ERR_IIC_ERR;
            *puValue = (puBytes[0] << 24) | (puBytes[1] << 16) | (puBytes[2] << 8) | puBytes[3];
            break;

        case JQAMGETTSON:
            for(i=0 ; i< TDA10023_JQAMFILTER_NB ; i++)
            {
                if(g10023Instance[demodUnit].systemFunc.SY_Read(
                    g10023Instance[demodUnit].uDemodHwAdd | TDA10023_JQAMFILTER_ADDR_OFFSET,
                    TDA10023_TS_ID1H_IND+(4*i), 4, puBytes) == False) return TM_ERR_IIC_ERR;

                *puValue = (puBytes[0] << 24) | (puBytes[1] << 16) | (puBytes[2] << 8) | puBytes[3];
                puValue++;
            }
            break;
    case BAND:
      *puValue = g10023Instance[demodUnit].eBandType;
      break;
        default:
            return TM_ERR_BAD_PARAMETER;
    }

    return TM_OK;
}


//-----------------------------------------------------------------------------
// FUNCTION:    tmbsl10023Write
//
// DESCRIPTION: this function writes bytes in the demod registers.
//
// RETURN:      TMBSL_ERR_DEMOD_BAD_UNIT_NUMBER
//              TMBSL_ERR_DEMOD_NOT_INITIALIZED
//              TM_ERR_IIC_ERR
//              TM_OK
//
// NOTES:       This function can be removed if needed
//-----------------------------------------------------------------------------
//
tmErrorCode_t
tmbsl10023Write (
    tmUnitSelect_t     demodUnit,     //  I: Demod unit number
    UInt32             uIndex,        //  I: Start index to write
    UInt32             uNbBytes,      //  I: Number of bytes to write
    UInt32*            puBytes        //  I: Pointer on an array of bytes
)
{
    SEND_TRACEFCT1(DEBUG_WRITE_ID, 0);

    //----------------------
    // test input parameters
    //----------------------
    // test the instance number
    if (demodUnit > TDA10023_MAX_UNITS)
        return TMBSL_ERR_DEMOD_BAD_UNIT_NUMBER;

    // test the object
    if (g10023Instance[demodUnit].sApiFlags.iInit == False)
        return TMBSL_ERR_DEMOD_NOT_INITIALIZED;

    //----------------------
    // Implementation
    //----------------------
    if (g10023Instance[demodUnit].systemFunc.SY_Write(
        g10023Instance[demodUnit].uDemodHwAdd,
        uIndex, uNbBytes, puBytes) == False)
        return TM_ERR_IIC_ERR;

    return TM_OK;
}

//-----------------------------------------------------------------------------
// FUNCTION:    tmbsl10023WriteBit
//
// DESCRIPTION: this function writes a bit to the mask position
//
// RETURN:      TMBSL_ERR_DEMOD_BAD_UNIT_NUMBER
//              TMBSL_ERR_DEMOD_NOT_INITIALIZED
//              TM_ERR_IIC_ERR
//              TM_OK
//
// NOTES:       This function can be removed if needed
//-----------------------------------------------------------------------------
//
tmErrorCode_t
tmbsl10023WriteBit (
    tmUnitSelect_t     demodUnit,     //  I: Demod unit number
    UInt32             uIndex,        //  I: Index to write
    UInt32             uBitMask,      //  I: byte mask
    UInt32             uByte          //  I: value
)
{
    SEND_TRACEFCT1(DEBUG_WRITEBIT_ID, 0);

    //----------------------
    // test input parameters
    //----------------------
    // test the instance number
    if (demodUnit > TDA10023_MAX_UNITS)
        return TMBSL_ERR_DEMOD_BAD_UNIT_NUMBER;

    // test the object
    if (g10023Instance[demodUnit].sApiFlags.iInit == False)
        return TMBSL_ERR_DEMOD_NOT_INITIALIZED;

    //----------------------
    // Implementation
    //----------------------
    if (g10023Instance[demodUnit].systemFunc.SY_WriteBit(
        g10023Instance[demodUnit].uDemodHwAdd,
        uIndex, uBitMask, uByte) == False)
        return TM_ERR_IIC_ERR;

    return TM_OK;
}

//-----------------------------------------------------------------------------
// FUNCTION:    tmbsl10023Read
//
// DESCRIPTION: this function reads bytes
//
// RETURN:      TMBSL_ERR_DEMOD_BAD_UNIT_NUMBER
//              TMBSL_ERR_DEMOD_NOT_INITIALIZED
//              TM_ERR_IIC_ERR
//              TM_OK
//
// NOTES:       This function can be removed if needed
//-----------------------------------------------------------------------------
//
tmErrorCode_t
tmbsl10023Read (
    tmUnitSelect_t     demodUnit,   //  I: Demod unit number
    UInt32             uIndex,      //  I: Start index to write
    UInt32             uNbBytes,    //  I: Number of bytes to read
    UInt32*            puBytes      //  O: Pointer on an array of bytes
)
{
    SEND_TRACEFCT1(DEBUG_READ_ID, 0);

    //----------------------
    // test input parameters
    //----------------------
    // test the instance number
    if (demodUnit > TDA10023_MAX_UNITS)
        return TMBSL_ERR_DEMOD_BAD_UNIT_NUMBER;

    // test the object
    if (g10023Instance[demodUnit].sApiFlags.iInit == False)
        return TMBSL_ERR_DEMOD_NOT_INITIALIZED;

    //----------------------
    // Implementation
    //----------------------
    if (g10023Instance[demodUnit].systemFunc.SY_Read(
            g10023Instance[demodUnit].uDemodHwAdd,
            uIndex,    uNbBytes, puBytes) == False)
        return TM_ERR_IIC_ERR;

    return TM_OK;
}

//-----------------------------------------------------------------------------
// Demod-Tuner programming functions:
//-----------------------------------------------------------------------------
//

//-----------------------------------------------------------------------------
// FUNCTION:    tmbsl10023SetRF
//
// DESCRIPTION: this function will program the tuner
//
// RETURN:      TMBSL_ERR_DEMOD_BAD_UNIT_NUMBER
//              TMBSL_ERR_DEMOD_NOT_INITIALIZED
//              TM_ERR_IIC_ERR
//              TM_OK
//
// NOTES:
//-----------------------------------------------------------------------------
//
tmErrorCode_t
tmbsl10023SetRF (
    tmUnitSelect_t    demodUnit,   //  I: Demod unit number
    UInt32            uRF          //  I: RF frequency (Hz)
)
{
    UInt32 uByte;

    tmErrorCode_t Error_Code;

    SEND_TRACEFCT1(DEBUG_SETRF_ID, 0);

    //----------------------
    // test input parameters
    //----------------------
    // test the instance number
    if (demodUnit > TDA10023_MAX_UNITS)
        return TMBSL_ERR_DEMOD_BAD_UNIT_NUMBER;

    // test the object
    if (g10023Instance[demodUnit].sApiFlags.iInit == False)
        return TMBSL_ERR_DEMOD_NOT_INITIALIZED;

    // test the parameter value
    if (uRF < TDA10023_RF_MIN || uRF > TDA10023_RF_MAX)
        return TMBSL_ERR_DEMOD_BAD_PARAMETER;

    //----------------------
    // Implementation
    //----------------------
#ifdef _CHINA_CABLE_
//PR SHZ_STBT#203 Modify tmbsl10023 to solve ADC harmonics problem
  TDA10023SolveADCHarmonic(demodUnit, uRF);
#endif  //#ifdef _CHINA_CABLE_

    // set the KAGCIF and KAGCTUN to acquisition mode
#ifdef _CHINA_CABLE_
            uByte = 0x92;
#else
            uByte = 0x96;
#endif
    if(g10023Instance[demodUnit].systemFunc.SY_Write(
        g10023Instance[demodUnit].uDemodHwAdd,
        TDA10023_AGCCONF1_IND,
        1,
        &uByte) == False) return TM_ERR_IIC_ERR;

  Error_Code = Tda10023WriteRF(&g10023Instance[demodUnit], &uRF);
    if(Error_Code != TM_OK) return(Error_Code);
       udelay(20);

  if ( g10023Instance[demodUnit].eBandType  == tmhalFEBandTypeSECAM_L )
    Tda10023ManageBandType( &g10023Instance[demodUnit] );

    // update return value
    g10023Instance[demodUnit].sCurrentChannel.uRF = uRF;

    // start algo
    g10023Instance[demodUnit].sApiFlags.iStartAlgo = True;

    return TM_OK;
}

//-----------------------------------------------------------------------------
// FUNCTION:    tmbsl10023GetRF
//
// DESCRIPTION: this function gets the current RF Frequency.
//
// RETURN:      TMBSL_ERR_DEMOD_BAD_UNIT_NUMBER
//              TMBSL_ERR_DEMOD_NOT_INITIALIZED
//              TM_OK
//
// NOTES:       the value sotcked in the object is returned
//-----------------------------------------------------------------------------
//
tmErrorCode_t
tmbsl10023GetRF (
    tmUnitSelect_t   demodUnit,   // I: Demod unit number
    UInt32           *puRF        // O: RF frequency (Hz)
)
{
    SEND_TRACEFCT2(DEBUG_GETRF_ID, 0);

    //----------------------
    // test input parameters
    //----------------------
    // test the instance number
    if (demodUnit > TDA10023_MAX_UNITS)
        return TMBSL_ERR_DEMOD_BAD_UNIT_NUMBER;

    // test the object
    if (g10023Instance[demodUnit].sApiFlags.iInit == False)
        return TMBSL_ERR_DEMOD_NOT_INITIALIZED;

    //----------------------
    // Implementation
    //----------------------
    *puRF = g10023Instance[demodUnit].sCurrentChannel.uRF;

    return TM_OK;
}

//-----------------------------------------------------------------------------
// FUNCTION:    tmbsl10023SetSR
//
// DESCRIPTION: this function set the symbol rate
//
// RETURN:      TMBSL_ERR_DEMOD_BAD_UNIT_NUMBER
//              TMBSL_ERR_DEMOD_NOT_INITIALIZED
//              TMBSL_ERR_DEMOD_BAD_PARAMETER
//              TM_OK
//
// NOTES:
//-----------------------------------------------------------------------------
//
tmErrorCode_t
tmbsl10023SetSR (
    tmUnitSelect_t    demodUnit,    //  I: Demod unit number
    UInt32            uSR           //  I: Symbol rate (bauds)
)
{
    tmErrorCode_t Error_Code;

    SEND_TRACEFCT1(DEBUG_SETSR_ID, 0);

    //----------------------
    // test input parameters
    //----------------------
    // test the instance number
    if (demodUnit > TDA10023_MAX_UNITS)
        return TMBSL_ERR_DEMOD_BAD_UNIT_NUMBER;

    // test the object
    if (g10023Instance[demodUnit].sApiFlags.iInit == False)
        return TMBSL_ERR_DEMOD_NOT_INITIALIZED;

    // test the parameter value
    // SACLK = SysClk/2     (SACLK max = 36MHz)
    // (SACLK/64) < uSR < (SACLK/4)
    // or with high sampling clock (SACLK = SysClk, SACLK max = 72MHz)
    // (SACLK/128) < uSR < (SACLK/8)
    if (uSR < (g10023Instance[demodUnit].uSysClk/(2*64)) || uSR > (g10023Instance[demodUnit].uSysClk/(2*4)))
        return TMBSL_ERR_DEMOD_BAD_PARAMETER;

    //----------------------
    // Implementation
    //----------------------
    Error_Code = Tda10023WriteSR (&g10023Instance[demodUnit], &uSR);
    if(Error_Code != TM_OK) return(Error_Code);

    // update current config
    g10023Instance[demodUnit].sCurrentChannel.uSR = uSR;

    return TM_OK;
}

//-----------------------------------------------------------------------------
// FUNCTION:    tmbsl10023GetSR
//
// DESCRIPTION: this function returns the symbol rate
//
// RETURN:      TMBSL_ERR_DEMOD_BAD_UNIT_NUMBER
//              TMBSL_ERR_DEMOD_NOT_INITIALIZED
//              TM_OK
//
// NOTES:       the value stored in the object is returned
//-----------------------------------------------------------------------------
//
tmErrorCode_t
tmbsl10023GetSR (
    tmUnitSelect_t    demodUnit,    //  I: Demod unit number
    UInt32            *puSR         //  O: Symbol rate (bauds)
)
{
    SEND_TRACEFCT2(DEBUG_GETSR_ID, 0);

    //----------------------
    // test input parameters
    //----------------------
    // test the instance number
    if (demodUnit > TDA10023_MAX_UNITS)
        return TMBSL_ERR_DEMOD_BAD_UNIT_NUMBER;

    // test the object
    if (g10023Instance[demodUnit].sApiFlags.iInit == False)
        return TMBSL_ERR_DEMOD_NOT_INITIALIZED;

    //----------------------
    // Implementation
    //----------------------
    *puSR = g10023Instance[demodUnit].sCurrentChannel.uSR;

    return TM_OK;
}

//-----------------------------------------------------------------------------
// FUNCTION:    tmbsl10023SetSI
//
// DESCRIPTION: this function programs the spectral inversion
//
// RETURN:      TMBSL_ERR_DEMOD_BAD_UNIT_NUMBER
//              TMBSL_ERR_DEMOD_NOT_INITIALIZED
//              TMBSL_ERR_DEMOD_BAD_PARAMETER
//              TM_ERR_IIC_ERR
//              TM_OK
//
// NOTES:
//-----------------------------------------------------------------------------
//
tmErrorCode_t
tmbsl10023SetSI (
    tmUnitSelect_t      demodUnit,    //  I: Demod unit number
    tmhalFESpectrum_t   eSI           //  I: Spectral Inversion
)
{
    UInt32 uSi=0;

    SEND_TRACEFCT1(DEBUG_SETSI_ID, 0);

    //----------------------
    // test input parameters
    //----------------------
    // test the instance number
    if (demodUnit > TDA10023_MAX_UNITS)
        return TMBSL_ERR_DEMOD_BAD_UNIT_NUMBER;

    // test the object
    if (g10023Instance[demodUnit].sApiFlags.iInit == False)
        return TMBSL_ERR_DEMOD_NOT_INITIALIZED;

    // test the parameter value
    if (eSI >= tmhalFESpectralInvMax || eSI < tmhalFESpectrumAuto)
        return TMBSL_ERR_DEMOD_BAD_PARAMETER;

    //----------------------
    // Implementation
    //----------------------
    switch (eSI)
    {
    case tmhalFESpectrumAuto:
        g10023Instance[demodUnit].sApiFlags.iAutoSi = True;
        //return TM_OK;
    break;

    case tmhalFESpectrumNormal:
        g10023Instance[demodUnit].sApiFlags.iAutoSi = False;
        if (g10023Instance[demodUnit].sConfig.bTUN_IQSwap)
            uSi = TDA10023_CARCONF_INVIQ_BIT;
        else
            uSi = 0;
        break;

    case tmhalFESpectrumInverted:
        g10023Instance[demodUnit].sApiFlags.iAutoSi = False;
        if (g10023Instance[demodUnit].sConfig.bTUN_IQSwap)
            uSi = 0;
        else
            uSi = TDA10023_CARCONF_INVIQ_BIT;
        break;

    default:
        return TMBSL_ERR_DEMOD_BAD_PARAMETER;
    }

    // write the spectral inversion
    if(g10023Instance[demodUnit].sApiFlags.iAutoSi == False)
    {
        if(g10023Instance[demodUnit].systemFunc.SY_WriteBit(
            g10023Instance[demodUnit].uDemodHwAdd,
            TDA10023_CARCONF_IND,
            TDA10023_CARCONF_AUTOINVIQ_BIT | TDA10023_CARCONF_INVIQ_BIT,
            uSi) == False) return TM_ERR_IIC_ERR;
    }
    else
    {
        if(g10023Instance[demodUnit].systemFunc.SY_WriteBit(
            g10023Instance[demodUnit].uDemodHwAdd,
            TDA10023_CARCONF_IND,
            TDA10023_CARCONF_AUTOINVIQ_BIT,
            TDA10023_CARCONF_AUTOINVIQ_BIT) == False) return TM_ERR_IIC_ERR;
    }
    // update value
    g10023Instance[demodUnit].sCurrentChannel.eSI = eSI;

    // start algo
    g10023Instance[demodUnit].sApiFlags.iStartAlgo = True;

    return TM_OK;
}

//-----------------------------------------------------------------------------
// FUNCTION:    tmbsl10023GetSI
//
// DESCRIPTION: this function reads the spectral inversion regarding to the value of the
//              IQswapped at the input of the tuner.
//                0: no spectral inversion else spectral inversion.
//
// RETURN:      TMBSL_ERR_DEMOD_BAD_UNIT_NUMBER
//              TMBSL_ERR_DEMOD_NOT_INITIALIZED
//              TM_ERR_IIC_ERR
//              TM_OK
//
// NOTES:       the register is readed each time
//-----------------------------------------------------------------------------
//
tmErrorCode_t
tmbsl10023GetSI (
    tmUnitSelect_t     demodUnit,     //  I: Demod unit number
    tmhalFESpectrum_t  *peSI          //  O: Spectral Inversion
)
{
    UInt32 uSi;

    SEND_TRACEFCT2(DEBUG_GETSI_ID, 0);

    //----------------------
    // test input parameters
    //----------------------
    // test the instance number
    if (demodUnit > TDA10023_MAX_UNITS)
        return TMBSL_ERR_DEMOD_BAD_UNIT_NUMBER;

    // test the object
    if (g10023Instance[demodUnit].sApiFlags.iInit == False)
        return TMBSL_ERR_DEMOD_NOT_INITIALIZED;

    //----------------------
    // Implementation
    //----------------------
    if(g10023Instance[demodUnit].systemFunc.SY_Read(
        g10023Instance[demodUnit].uDemodHwAdd, TDA10023_CARCONF_IND, 1, &uSi) == False) return TM_ERR_IIC_ERR;

    // test different cases regarding to the spectral inversion in the tuner
    if ((uSi & TDA10023_CARCONF_INVIQ_BIT) && g10023Instance[demodUnit].sConfig.bTUN_IQSwap)
        *peSI = tmhalFESpectrumNormal;
    else if ((uSi & TDA10023_CARCONF_INVIQ_BIT) && !g10023Instance[demodUnit].sConfig.bTUN_IQSwap)
        *peSI = tmhalFESpectrumInverted;
    else if (!(uSi & TDA10023_CARCONF_INVIQ_BIT) && g10023Instance[demodUnit].sConfig.bTUN_IQSwap)
        *peSI = tmhalFESpectrumInverted;
    else if (!(uSi & TDA10023_CARCONF_INVIQ_BIT) && !g10023Instance[demodUnit].sConfig.bTUN_IQSwap)
        *peSI = tmhalFESpectrumNormal;

    // update value
    g10023Instance[demodUnit].sCurrentChannel.eSI = *peSI;

    return TM_OK;
}

//-----------------------------------------------------------------------------
// FUNCTION:    tmbsl10023SetMod
//
// DESCRIPTION: this function programs the modulation
//
// RETURN:      TMBSL_ERR_DEMOD_BAD_UNIT_NUMBER
//              TMBSL_ERR_DEMOD_NOT_INITIALIZED
//              TMBSL_ERR_DEMOD_BAD_PARAMETER
//              TM_OK
//
// NOTES:
//-----------------------------------------------------------------------------
//
tmErrorCode_t
tmbsl10023SetMod (
    tmUnitSelect_t         demodUnit,    //  I: Demod unit number
    tmhalFEModulation_t    eMOD          //  I: Modulation type
)
{
    UInt32 uMod;
    tmErrorCode_t Error_Code;

    SEND_TRACEFCT1(DEBUG_SETMOD_ID, 0);

    //----------------------
    // test input parameters
    //----------------------
    // test the instance number
    if (demodUnit > TDA10023_MAX_UNITS)
        return TMBSL_ERR_DEMOD_BAD_UNIT_NUMBER;

    // test the object
    if (g10023Instance[demodUnit].sApiFlags.iInit == False)
        return TMBSL_ERR_DEMOD_NOT_INITIALIZED;

    // test the parameter value
    if (eMOD >= tmhalFEModulationMax)
        return TMBSL_ERR_DEMOD_BAD_PARAMETER;

    // In MCNS mode, only 64QAM and 256QAM are allowed
    if ((g10023Instance[demodUnit].sConfig.bModeDvbMcns) &&
        (eMOD != tmhalFEModulationAuto) &&
        (eMOD != tmhalFEModulationQam64) &&
        (eMOD != tmhalFEModulationQam256) )
        return TMBSL_ERR_DEMOD_BAD_PARAMETER;

    //----------------------
    // Implementation
    //----------------------
    switch (eMOD)
    {
    case tmhalFEModulationAuto:
        g10023Instance[demodUnit].sApiFlags.iAutoQam = True;
        uMod = 2;
        break;
    case tmhalFEModulationQam4:
        g10023Instance[demodUnit].sApiFlags.iAutoQam = False;
        uMod = 5;
        break;
    case tmhalFEModulationQam16:
        g10023Instance[demodUnit].sApiFlags.iAutoQam = False;
        uMod = 0;
        break;
    case tmhalFEModulationQam32:
        g10023Instance[demodUnit].sApiFlags.iAutoQam = False;
        uMod = 1;
        break;
    case tmhalFEModulationQam64:
        g10023Instance[demodUnit].sApiFlags.iAutoQam = False;
        uMod = 2;
        break;
    case tmhalFEModulationQam128:
        g10023Instance[demodUnit].sApiFlags.iAutoQam = False;
        uMod = 3;
        break;
    case tmhalFEModulationQam256:
        g10023Instance[demodUnit].sApiFlags.iAutoQam = False;
        uMod = 4;
        break;
    default:
        return TMBSL_ERR_DEMOD_BAD_PARAMETER;
    }

    // write the new modulation
    Error_Code = Tda10023WriteQAM(&g10023Instance[demodUnit], uMod);
    if(Error_Code != TM_OK) return(Error_Code);

    // update current config
    if (tmhalFEModulationAuto == eMOD)
        g10023Instance[demodUnit].sCurrentChannel.eMOD = tmhalFEModulationQam64;
    else
        g10023Instance[demodUnit].sCurrentChannel.eMOD = eMOD;

    // start algo
    g10023Instance[demodUnit].sApiFlags.iStartAlgo = True;

    return TM_OK;
}

//-----------------------------------------------------------------------------
// FUNCTION:    tmbsl10023GetMod
//
// DESCRIPTION: this function reads the current modulation
//
// RETURN:      TMBSL_ERR_DEMOD_BAD_UNIT_NUMBER
//              TMBSL_ERR_DEMOD_NOT_INITIALIZED
//              TM_OK
//
// NOTES:
//-----------------------------------------------------------------------------
//
tmErrorCode_t
tmbsl10023GetMod (
    tmUnitSelect_t        demodUnit,  //  I: Demod unit number
    tmhalFEModulation_t   *peMOD      //  O: Modulation type
)
{
    SEND_TRACEFCT2(DEBUG_GETMOD_ID, 0);

    //----------------------
    // test input parameters
    //----------------------
    // test the instance number
    if (demodUnit > TDA10023_MAX_UNITS)
        return TMBSL_ERR_DEMOD_BAD_UNIT_NUMBER;

    // test the object
    if (g10023Instance[demodUnit].sApiFlags.iInit == False)
        return TMBSL_ERR_DEMOD_NOT_INITIALIZED;

    //----------------------
    // Implementation
    //----------------------
    *peMOD = g10023Instance[demodUnit].sCurrentChannel.eMOD;

    return TM_OK;
}

//-----------------------------------------------------------------------------
// Status functions:
//-----------------------------------------------------------------------------
//

//-----------------------------------------------------------------------------
// FUNCTION:    tmbsl10023GetBER
//
// DESCRIPTION: this function reads the BER
//
// RETURN:      TMBSL_ERR_DEMOD_BAD_UNIT_NUMBER
//              TMBSL_ERR_DEMOD_NOT_INITIALIZED
//              TM_ERR_IIC_ERR
//              TM_OK
//
// NOTES:       the ber value read needs to be corrected due to the real
//              counter depth for 10e5
//
//-----------------------------------------------------------------------------
//
tmErrorCode_t
tmbsl10023GetBER (
    tmUnitSelect_t    demodUnit,     //  I: Demod unit number
    UInt32            *puBer         //  O: BER
)
{

    UInt32    puBerBuf[3], puUncorBuf[2], uBerDepth;
    UInt32    uUncor;
    UInt32 uMeanBer;
    static UInt32 *psuPrevBer = Null;
    static UInt32 suIndex=0;
    static UInt32 suWindowSize = 0;

    SEND_TRACEFCT2(DEBUG_GETBER_ID, 0);

    //----------------------
    // test input parameters
    //----------------------
    // test the instance number
    if (demodUnit > TDA10023_MAX_UNITS)
        return TMBSL_ERR_DEMOD_BAD_UNIT_NUMBER;

    // test the object
    if (g10023Instance[demodUnit].sApiFlags.iInit == False)
        return TMBSL_ERR_DEMOD_NOT_INITIALIZED;

    //----------------------
    // Implementation
    //----------------------
    if(g10023Instance[demodUnit].sConfig.bModeDvbMcns)
    {
        // MCNS mode
        // Read RSBER
        if(g10023Instance[demodUnit].systemFunc.SY_Read(g10023Instance[demodUnit].uDemodHwAdd,
            TDA10023_RSBERLO_IND, 2, puBerBuf) == False) return TM_ERR_IIC_ERR;

        // Read RSUNCOR
        if(g10023Instance[demodUnit].systemFunc.SY_Read(g10023Instance[demodUnit].uDemodHwAdd,
            TDA10023_RSUNCORLO_IND, 2, puUncorBuf) == False) return TM_ERR_IIC_ERR;

        *puBer = puBerBuf[1]<<8 | puBerBuf[0];
        uUncor = puUncorBuf[1]<<8 | puUncorBuf[0];

        // We consider that there are 16 wrong bits per uncor
        *puBer += (uUncor*16);


        // read the BER depth
        if(g10023Instance[demodUnit].systemFunc.SY_Read(g10023Instance[demodUnit].uDemodHwAdd,
            TDA10023_RSCFG_IND, 1, &uBerDepth) == False) return TM_ERR_IIC_ERR;

        if(((uBerDepth & TDA10023_RSCFG_PRG_TBER_MSK)>>2) == 0x01)
        {
            if(g10023Instance[demodUnit].sConfig.uBERwindow != 0)
            {
                UInt32 i;

                // If not already done, configure sliding window
                if(suWindowSize != g10023Instance[demodUnit].sConfig.uBERwindow)
                {
                    if(psuPrevBer != Null)
                    {
                        // Delete the previous buffer
                        kfree(psuPrevBer);
                        psuPrevBer = Null;
                    }

                    // Allocate a new buffer to store the BER values
                    psuPrevBer = (UInt32*) kmalloc(g10023Instance[demodUnit].sConfig.uBERwindow * sizeof(UInt32) , GFP_KERNEL);
                    if (psuPrevBer == Null)
                    {
                        return TMBSL_ERR_DEMOD_NOT_SUPPORTED;
                    }
                    suWindowSize = g10023Instance[demodUnit].sConfig.uBERwindow;

                    suIndex = 0;
                }

                uMeanBer = *puBer;

                // Calculate the mean value with a sliding window of N samples
                for(i = 0; i<g10023Instance[demodUnit].sConfig.uBERwindow; i++)
                {
                    uMeanBer += psuPrevBer[i];
                }

                uMeanBer -= psuPrevBer[suIndex];
                psuPrevBer[suIndex] = *puBer;
                suIndex++;
                if(suIndex == g10023Instance[demodUnit].sConfig.uBERwindow)
                    suIndex = 0;

                *puBer = uMeanBer/g10023Instance[demodUnit].sConfig.uBERwindow;
            }
        }

        switch(uBerDepth & TDA10023_RSCFG_PRG_TBER_MSK)
        {
        case 0x00:  // 262144
            *puBer *= 545;     // 100000000/(262144*7) = 54.5       (7 is the number of bits per symbol)
            *puBer += 5;
            *puBer /= 10;
            break;
        case 0x04:  // 2097152
            *puBer *= 681;     // 100000000/(2097152*7) = 6.812
            *puBer += 50;
            *puBer /= 100;
            break;
        case 0x08:  // 16777216
            *puBer *= 851;     // 100000000/(16777216*7) = 0.8515
            *puBer += 500;
            *puBer /= 1000;
            break;
        case 0x0c:  // 134217728
            *puBer *= 1064;     // 100000000/(134217728*7) = 0.1064
            *puBer += 5000;
            *puBer /= 10000;
            break;
        }

    }
    else
    {
        // DVB mode
        if(g10023Instance[demodUnit].systemFunc.SY_Read(g10023Instance[demodUnit].uDemodHwAdd,
            TDA10023_BERLSB_IND, 3, puBerBuf) == False) return TM_ERR_IIC_ERR;

        *puBer = puBerBuf[2]<<16 | puBerBuf[1]<<8 | puBerBuf[0];

        // read the BER depth
        if(g10023Instance[demodUnit].systemFunc.SY_Read(g10023Instance[demodUnit].uDemodHwAdd,
            TDA10023_FECDVBCFG1_IND, 1, &uBerDepth) == False) return TM_ERR_IIC_ERR;

        switch(uBerDepth & TDA10023_FECDVBCFG1_PVBER_MSK)
        {
        case 0x00:  // 1,00E+05
            *puBer *= 1000;
            break;
        case 0x40:  // 1,00E+06
            *puBer *= 100;
            break;
        case 0x80:  // 1,00E+07
            *puBer *= 10;
            break;
        case 0xc0:  // 1,00E+08
            break;
        }
    }

    return TM_OK;
}

//-----------------------------------------------------------------------------
// FUNCTION:    tmbsl10023GetSNR
//
// DESCRIPTION: this function calculate the signal noise ratio in dB
//
// RETURN:      TMBSL_ERR_DEMOD_BAD_UNIT_NUMBER
//              TMBSL_ERR_DEMOD_NOT_INITIALIZED
//              TM_ERR_IIC_ERR
//              TM_OK
//
// NOTES:       TBD
//-----------------------------------------------------------------------------
//
tmErrorCode_t
tmbsl10023GetSNR (
    tmUnitSelect_t    demodUnit,      //  I: Demod unit number
    Int8              *pbSNR          //  O: SNR
)
{
#ifndef NO_FLOAT
    float fSNR, fMSE;
#endif
    UInt32 uCounter, uMSE;

    SEND_TRACEFCT2(DEBUG_GETSNR_ID, 0);

    //----------------------
    // test input parameters
    //----------------------
    // test the instance number
    if (demodUnit > TDA10023_MAX_UNITS)
        return TMBSL_ERR_DEMOD_BAD_UNIT_NUMBER;

    // test the object
    if (g10023Instance[demodUnit].sApiFlags.iInit == False)
        return TMBSL_ERR_DEMOD_NOT_INITIALIZED;

    //----------------------
    // Implementation
    //----------------------
#ifndef NO_FLOAT
    fMSE = (float)0;
    for (uCounter = 0; uCounter < 10; uCounter++)
    {
        // average value of the MSE on 10 values
        if(g10023Instance[demodUnit].systemFunc.SY_Read(g10023Instance[demodUnit].uDemodHwAdd,
            TDA10023_MSE_IND, 1, &uMSE) == False) return TM_ERR_IIC_ERR;
        fMSE += (float)uMSE;
    }
    fMSE /= (float)uCounter;

    // calculate the SNR regarding to the modulation
    switch (g10023Instance[demodUnit].sCurrentChannel.eMOD)
    {
    case tmhalFEModulationQam16:
        fSNR = (float)((195.0/(0.32*fMSE + 1.38)) + 10.0);
        break;

    case tmhalFEModulationQam32:
        fSNR = (float)((215.0/(0.40*fMSE + 5.0)) + 13.5);
        break;

    case tmhalFEModulationQam64:
        fSNR = (float)((210.0/(0.40*fMSE + 5.0)) + 12.5);
        break;

    case tmhalFEModulationQam128:
        fSNR = (float)((185.0/(0.38*fMSE + 4.0)) + 13.8);
        break;

    case tmhalFEModulationQam256:
        fSNR = (float)((180.0/(1.00*fMSE + 0.4)) + 20.3);
        break;

    default:
        return TMBSL_ERR_DEMOD_NOT_SUPPORTED;
    }

    // update value
    *pbSNR = (Int8)fSNR;

    return TM_OK;

#else // NO_FLOAT
{
    unsigned int iMSE ;
    unsigned int iSNR;
    iMSE = 0;
    for (uCounter = 0; uCounter < 5; uCounter++)
    {
        // average value of the MSE on 10 values
        if(g10023Instance[demodUnit].systemFunc.SY_Read(g10023Instance[demodUnit].uDemodHwAdd,
            TDA10023_MSE_IND, 1, &uMSE) == False) return TM_ERR_IIC_ERR;
        iMSE += uMSE;
    }
    iMSE /= uCounter;

    // calculate the SNR regarding to the modulation
    // calculate the SNR regarding to the modulation
    switch (g10023Instance[demodUnit].sCurrentChannel.eMOD)
    {
    case tmhalFEModulationQam16:
        iSNR = ((1950000/(32*iMSE + 138)) + 1000);
        break;

    case tmhalFEModulationQam32:
        iSNR = ((2150000/(40*iMSE + 500)) + 1350);
        break;

    case tmhalFEModulationQam64:
        iSNR = ((2100000/(40*iMSE + 500)) + 1250);
        break;

    case tmhalFEModulationQam128:
        iSNR = ((1850000/(38*iMSE + 400)) + 1380);
        break;

    case tmhalFEModulationQam256:
        iSNR = ((1800000/(100*iMSE + 40)) + 2030);
        break;

    default:
        return TMBSL_ERR_DEMOD_NOT_SUPPORTED;
    }

    // update value
    *pbSNR = ((iSNR+50)/100);

    return TM_OK;
}


#endif // NO_FLOAT

}

//-----------------------------------------------------------------------------
// FUNCTION:    tmbsl10023GetLVL
//
// DESCRIPTION: this function reads an estimated level in dBm.
//
// RETURN:     TMBSL_ERR_DEMOD_BAD_UNIT_NUMBER
//             TMBSL_ERR_DEMOD_NOT_INITIALIZED
//             TM_FALSE
//             TM_OK
// NOTES:
//-----------------------------------------------------------------------------
//
tmErrorCode_t
tmbsl10023GetLVL (
    tmUnitSelect_t      demodUnit,          //  I: Demod unit number
    Int8*               pbLVL               //  O: Level in unit of dBm
)
{
    SEND_TRACEFCT2(DEBUG_GETLVL_ID, 0);

    //----------------------
    // test input parameters
    //----------------------
    // test the instance number
    if (demodUnit > TDA10023_MAX_UNITS)
        return TMBSL_ERR_DEMOD_BAD_UNIT_NUMBER;

    // test the object
    if (g10023Instance[demodUnit].sApiFlags.iInit == False)
        return TMBSL_ERR_DEMOD_NOT_INITIALIZED;

    //----------------------
    // Implementation
    //----------------------
  if (Tda10023ReadRSSI(&g10023Instance[demodUnit],pbLVL) == TM_FALSE)
    return TM_FALSE;
  return TM_OK;
}


//-----------------------------------------------------------------------------
// FUNCTION:    Tda10023ReadRSSI
//
// DESCRIPTION: this function will read the RSSI
//
// RETURN:
//              TM_ERR_IIC_ERR
//              TM_OK
//
// NOTES:
//-----------------------------------------------------------------------------
//
tmErrorCode_t
Tda10023ReadRSSI (
    tm10023object_t     *psObject,   // IO: Demod object
    Int8        *pRssi        //  O: RSSI

)
{
    UInt32  puAgc1,puAgc2,puAdc;
  // tuner is accessible
    if(psObject->systemFunc.SY_WriteBit( psObject->uDemodHwAdd,
        TDA10023_TEST_IND, TDA10023_TEST_BYPIIC_BIT,
        TDA10023_TEST_BYPIIC_BIT) == False) return TM_ERR_IIC_ERR;

    // tuner is disconnected from the I2C bus
   if(psObject->systemFunc.SY_WriteBit( psObject->uDemodHwAdd,
        TDA10023_TEST_IND, TDA10023_TEST_BYPIIC_BIT, 0) == False) return TM_ERR_IIC_ERR;

#ifdef _CHINA_CABLE_
//for china cable project which use CD1616
  //If tuner does not support checking RF level,
  //here will caculate the RF level according to the AGCTUNE and AGCIF, Daniel Guo.
    Tda10023GetLVL(psObject, pRssi);
#endif //#ifdef _CHINA_CABLE_

    return TM_OK;
}


#ifdef _CHINA_CABLE_
//for china cable project which use CD1616
//-----------------------------------------------------------------------------
// FUNCTION:    Tda10023GetLVL
//
// DESCRIPTION: this function will get the RF level by checking AGCTune and AGCIF
//
// RETURN:
//              TM_ERR_IIC_ERR
//              TM_OK
//
// NOTES:
//-----------------------------------------------------------------------------
//
tmErrorCode_t Tda10023GetLVL (tm10023object_t  *psObject, Int8 *pRssi)
{
  UInt32 uAgcRF=0xff, uAgcIF=0xff, uIfMin=0xff, cntr = 0;
  ptm10023RFLvl_Agc_t pTable;

  //Read AGC_Tune, AGC_IF, IF_MIN value
  if(psObject->systemFunc.SY_Read(psObject->uDemodHwAdd,  TDA10023_AGCTUN_IND, 1, &uAgcRF) ==False)
    return TM_ERR_IIC_ERR;

#if 0
  if(psObject->systemFunc.SY_Read(psObject->uDemodHwAdd,  TDA10023_AGCIF_IND, 1, &uAgcIF) ==False)
    return TM_ERR_IIC_ERR;

  if(psObject->systemFunc.SY_Read(psObject->uDemodHwAdd,  TDA10023_IFMIN_IND, 1, &uIfMin) ==False)
    return TM_ERR_IIC_ERR;
#endif

#ifdef QAM256_OPTIMIZATION
  if(0x57950000 == psObject->sConfig.uBoard)
    pTable = RFLvl_Agc_Table_CD1616_GIGH;
  else if(0x12160000 == psObject->sConfig.uBoard)
    pTable = RFLvl_Agc_Table_CU1216_AGIGH;
  else
    pTable = RFLvl_Agc_Table_CD1616_GIGH;
    // here use this table for other board temprarily
#else
//choose the correct table according to the boardtype.
  if(0x57950000 == psObject->sConfig.uBoard)
    pTable = RFLvl_Agc_Table_CD1616_IFMIN_60;
  else
    pTable = RFLvl_Agc_Table_CD1616_IFMIN_60;
    // only CD1616(board 5799) table is available
    // so, here use this table for other board temprarily
    //Currently only IFMIN = 0x60 table is supported.
#endif


  // set default max value for RF level
  *pRssi = 90;

  while(pTable[cntr].uAgcRF)
  {

    if(uAgcRF >= pTable[cntr].uAgcRF)
    {
      *pRssi = (Int8)pTable[cntr].fRFLvl;
      break;
    }
    else
      cntr ++;

  }

//  printf("uAgcRF [%d], uAgcIF [%d], uIfMin [%d], fRFLvl [%d]\n", uAgcRF, uAgcIF, uIfMin, *pRssi);

  return TM_OK;
}
#endif //#ifdef _CHINA_CABLE_

//-----------------------------------------------------------------------------
// FUNCTION:    tmbsl10023GetAFC
//
// DESCRIPTION: this function calculate the AFC in hertz
//
// RETURN:      TMBSL_ERR_DEMOD_BAD_UNIT_NUMBER
//              TMBSL_ERR_DEMOD_NOT_INITIALIZED
//              TM_OK
//
// NOTES:
//
//-----------------------------------------------------------------------------
//
tmErrorCode_t
tmbsl10023GetAFC (
    tmUnitSelect_t   demodUnit,   //  I: Demod unit number
    Int32            *plAFC       //  O: AFC
)
{
    tmErrorCode_t Error_Code;
    SEND_TRACEFCT2(DEBUG_GETAFC_ID, 0);

    //----------------------
    // test input parameters
    //----------------------
    // test the instance number
    if (demodUnit > TDA10023_MAX_UNITS)
        return TMBSL_ERR_DEMOD_BAD_UNIT_NUMBER;

    // test the object
    if (g10023Instance[demodUnit].sApiFlags.iInit == False)
        return TMBSL_ERR_DEMOD_NOT_INITIALIZED;

    //----------------------
    // Implementation
    //----------------------
    Error_Code = Tda10023ReadAFC(&g10023Instance[demodUnit], plAFC);
    if(Error_Code != TM_OK) return(Error_Code);

    return TM_OK;
}

//-----------------------------------------------------------------------------
// FUNCTION:    tmbsl10023GetACC
//
// DESCRIPTION: the function calculates symbol frequency error in ppm
//
// RETURN:      TMBSL_ERR_DEMOD_BAD_UNIT_NUMBER
//              TMBSL_ERR_DEMOD_NOT_INITIALIZED
//              TM_ERR_IIC_ERR
//              TM_OK
//
// NOTES:       formula:
//                if DYN= 0: CKoffset*10e6/2^19 ppm
//                if DYN= 1: CKoffset*10e6/2^18 ppm
//
//-----------------------------------------------------------------------------
//
tmErrorCode_t
tmbsl10023GetACC (
    tmUnitSelect_t   demodUnit,  //  I: Demod unit number
    Int32            *plACC      //  O: frequency error in ppm
)
{
    SEND_TRACEFCT2(DEBUG_GETACC_ID, 0);

    //----------------------
    // test input parameters
    //----------------------
    // test the instance number
    if (demodUnit > TDA10023_MAX_UNITS)
        return TMBSL_ERR_DEMOD_BAD_UNIT_NUMBER;

    // test the object
    if (g10023Instance[demodUnit].sApiFlags.iInit == False)
        return TMBSL_ERR_DEMOD_NOT_INITIALIZED;

    //----------------------
    // Implementation
    //----------------------
    if(g10023Instance[demodUnit].systemFunc.SY_Read(
        g10023Instance[demodUnit].uDemodHwAdd, TDA10023_CKOFF_IND, 1, plACC) == False) return TM_ERR_IIC_ERR;

    // signed value if needed -> 8 bits
    if (*plACC & 0x80)
        *plACC |= 0xFFFFFF00;

    // calculate the error in ppm - assumed +/-480ppm for DYN
    *plACC *= 1000000;
    *plACC /= 262144;   // 262144 = 2^18

    // add constant use in the algo to extend the clk offset range
    // TBD
    *plACC += g10023Instance[demodUnit].lClkOffCst;

    return TM_OK;
}

//-----------------------------------------------------------------------------
// FUNCTION:    tmbsl10023GetUBK
//
// DESCRIPTION: the function reads the uncorrected block number.
//
// RETURN:      TMBSL_ERR_DEMOD_BAD_UNIT_NUMBER
//              TMBSL_ERR_DEMOD_NOT_INITIALIZED
//              TM_ERR_IIC_ERR
//              TM_OK
//              TM_FALSE
//
// NOTES:
//-----------------------------------------------------------------------------
//
tmErrorCode_t
tmbsl10023GetUBK (
    tmUnitSelect_t    demodUnit,   //  I: Demod unit number
    UInt32            *puUBK       //  O: Uncor
)
{
    UInt32 puBytes[4];

    SEND_TRACEFCT2(DEBUG_GETUBK_ID, 0);

    //----------------------
    // test input parameters
    //----------------------
    // test the instance number
    if (demodUnit > TDA10023_MAX_UNITS)
        return TMBSL_ERR_DEMOD_BAD_UNIT_NUMBER;

    // test the object
    if (g10023Instance[demodUnit].sApiFlags.iInit == False)
        return TMBSL_ERR_DEMOD_NOT_INITIALIZED;

    //----------------------
    // Implementation
    //----------------------
    if(g10023Instance[demodUnit].sConfig.bModeDvbMcns)
    {
        // MCNS mode

        if(g10023Instance[demodUnit].systemFunc.SY_Read(
            g10023Instance[demodUnit].uDemodHwAdd,
            TDA10023_CPT_RSB_UNCOR1_IND,    4, puBytes) == False) return TM_ERR_IIC_ERR;

        *puUBK = (puBytes[3]<<24) | (puBytes[2]<<16) | (puBytes[1]<<8) | puBytes[0];

        // reset the counter is needed if there are uncors
        if (*puUBK)
        {
            if(g10023Instance[demodUnit].systemFunc.SY_WriteBit(
                g10023Instance[demodUnit].uDemodHwAdd,
                TDA10023_RSCFG_IND, TDA10023_RSCFG_CLB_CPT_RSB_BIT, 0) == False) return TM_ERR_IIC_ERR;
            if(g10023Instance[demodUnit].systemFunc.SY_WriteBit(
                g10023Instance[demodUnit].uDemodHwAdd,
                TDA10023_RSCFG_IND, TDA10023_RSCFG_CLB_CPT_RSB_BIT, TDA10023_RSCFG_CLB_CPT_RSB_BIT) == False) return TM_ERR_IIC_ERR;
        }
    }
    else
    {
        // DVB mode

        if(g10023Instance[demodUnit].systemFunc.SY_Read(
            g10023Instance[demodUnit].uDemodHwAdd,
            TDA10023_CPT_TSP_UNCOR1_IND,    4, puBytes) == False) return TM_ERR_IIC_ERR;

        *puUBK = (puBytes[3]<<24) | (puBytes[2]<<16) | (puBytes[1]<<8) | puBytes[0];

        // reset the counter is needed if there are uncors
        if (*puUBK)
        {
            if(g10023Instance[demodUnit].systemFunc.SY_WriteBit(
                g10023Instance[demodUnit].uDemodHwAdd,
                TDA10023_FECDVBCFG1_IND, TDA10023_FECDVBCFG1_CLB_CPT_TSP_BIT, 0) == False) return TM_ERR_IIC_ERR;
            if(g10023Instance[demodUnit].systemFunc.SY_WriteBit(
                g10023Instance[demodUnit].uDemodHwAdd,
                TDA10023_FECDVBCFG1_IND, TDA10023_FECDVBCFG1_CLB_CPT_TSP_BIT, TDA10023_FECDVBCFG1_CLB_CPT_TSP_BIT) == False) return TM_ERR_IIC_ERR;
        }
    }

    return TM_OK;
}

//-----------------------------------------------------------------------------
// FUNCTION:    tmbsl10023GetIQ
//
// DESCRIPTION: read I and Q to display the scatter
//
// RETURN:      TM_FALSE
//              TM_ERR_IIC_ERR
//              TM_OK
//
// NOTES:       This function can be removed if needed
//-----------------------------------------------------------------------------
//
tmErrorCode_t
tmbsl10023GetIQ (
    tmUnitSelect_t   demodUnit,   //  I: Demod unit number
    UInt32           *puIQ        //  O: IQ values
)
{
    UInt32 puIQbuf[2];

    SEND_TRACEFCT1(DEBUG_GETIQ_ID, 0);

    //----------------------
    // test input parameters
    //----------------------
    // test the instance number
    if (demodUnit > TDA10023_MAX_UNITS)
        return TMBSL_ERR_DEMOD_BAD_UNIT_NUMBER;

    // test the object
    if (g10023Instance[demodUnit].sApiFlags.iInit == False)
        return TMBSL_ERR_DEMOD_NOT_INITIALIZED;

    //----------------------
    // Implementation
    //----------------------
    if(g10023Instance[demodUnit].systemFunc.SY_Read(
        g10023Instance[demodUnit].uDemodHwAdd,
        TDA10023_CONSTI_IND, 2, puIQbuf) == False) return TM_ERR_IIC_ERR;

    // update return values
    *puIQ = puIQbuf[0] << 8 | puIQbuf[1];

    return TM_OK;
}

//-----------------------------------------------------------------------------
// FUNCTION:    tmbsl10023GetCOEF
//
// DESCRIPTION: read the equalizer coefficients
//
// RETURN:      TM_FALSE
//              TM_ERR_IIC_ERR
//              TM_OK
//
// NOTES:       This function can be removed if needed
//                plCoef->I0, Q0, ...., I25, Q25
//-----------------------------------------------------------------------------
//
tmErrorCode_t
tmbsl10023GetCOEF (
    tmUnitSelect_t   demodUnit,   //  I: Demod unit number
    Int32            *plCoef      //  O: Imaginary part
)
{
    Int32 alICoef[52], alRCoef[52];
    UInt32 uCounter;

    SEND_TRACEFCT1(DEBUG_GETCOEF_ID, 0);

    //----------------------
    // test input parameters
    //----------------------
    // test the instance number
    if (demodUnit > TDA10023_MAX_UNITS)
        return TMBSL_ERR_DEMOD_BAD_UNIT_NUMBER;

    // test the object
    if (g10023Instance[demodUnit].sApiFlags.iInit == False)
        return TMBSL_ERR_DEMOD_NOT_INITIALIZED;

    //----------------------
    // Implementation
    //----------------------
    // read the imaginary part of coef
    if(g10023Instance[demodUnit].systemFunc.SY_Read(
        g10023Instance[demodUnit].uDemodHwAdd, TDA10023_IEQCO_IND, 52, alICoef) == False) return TM_ERR_IIC_ERR;

    // read the real part of coef
    if(g10023Instance[demodUnit].systemFunc.SY_Read(
        g10023Instance[demodUnit].uDemodHwAdd, TDA10023_REQCO_IND, 52, alRCoef) == False) return TM_ERR_IIC_ERR;

    // fill the array
    for (uCounter = 0; uCounter < 52; uCounter += 2)
    {
        // imaginary part
        *plCoef = (alICoef[uCounter] << 3) | (alICoef[uCounter+1] >> 5);
        if (*plCoef & 0x0400)
            *plCoef |= 0xFFFFF800;
        plCoef++;
    }
    for (uCounter = 0; uCounter < 52; uCounter += 2)
    {
        // real part
        *plCoef = (alRCoef[uCounter] << 3) | (alRCoef[uCounter+1] >> 5);
        if (*plCoef & 0x0400)
            *plCoef |= 0xFFFFF800;
        plCoef++;
    }

    return TM_OK;
}

//-----------------------------------------------------------------------------
// algorithm for scanning and tuning:
//-----------------------------------------------------------------------------
//

#if 0
//-----------------------------------------------------------------------------
// FUNCTION:    tmbsl10023StartScan:
//
// DESCRIPTION: Start the RF scanning
//
// RETURN:      TMBSL_ERR_DEMOD_BAD_UNIT_NUMBER
//              TMBSL_ERR_DEMOD_NOT_INITIALIZED
//              TM_OK
//
// NOTES:
//-----------------------------------------------------------------------------
//
tmErrorCode_t
tmbsl10023StartScan(
    tmUnitSelect_t  demodUnit,        //  I: Demod unit number
    UInt32          uStopFrequency    //  I: End of the RF freqency band (Hz)
    )
{
  tmErrorCode_t errCode;

    SEND_TRACEFCT1(DEBUG_STARTSCAN_ID, 0);


    //----------------------
    // test input parameters
    //----------------------
    // test the instance number
    if (demodUnit > TDA10023_MAX_UNITS)
        return TMBSL_ERR_DEMOD_BAD_UNIT_NUMBER;

    // test the object
    if (g10023Instance[demodUnit].sApiFlags.iInit == False)
        return TMBSL_ERR_DEMOD_NOT_INITIALIZED;

    // test if the stop frequency is higher than the current frequency
    if (uStopFrequency <= g10023Instance[demodUnit].sCurrentChannel.uRF)
        return TM_ERR_BAD_PARAMETER;

    //----------------------
    // Implementation
    //----------------------
    g10023Instance[demodUnit].sApiFlags.iScan = True;
    g10023Instance[demodUnit].uStopFrequency = uStopFrequency;
    g10023Instance[demodUnit].uRFPrevious = 0;
    g10023Instance[demodUnit].QuickFinding = False;

    // initialize other algo
    g10023Instance[demodUnit].bStateClkOffset = 0;
    g10023Instance[demodUnit].lClkOffCst = 0;

    //Patch YFL
    if (g10023Instance[demodUnit].uNbSamples == 0)
    {
        g10023Instance[demodUnit].uStartSymbolRate = g10023Instance[demodUnit].sConfig.uStartSymbolRate;
        g10023Instance[demodUnit].uStopSymbolRate = g10023Instance[demodUnit].sConfig.uStopSymbolRate;
    }

    if (g10023Instance[demodUnit].uNbSamples == 0 &&
       (g10023Instance[demodUnit].uStartSymbolRate != g10023Instance[demodUnit].uStopSymbolRate))
    {
    g10023Instance[demodUnit].bFlagAutoScan = True;
    errCode = Tda10023StartPreScan( &g10023Instance[demodUnit]);
    if ( errCode != TM_OK)
      return errCode;
  }

  // FastScan Move to the next potential channel
  else if (g10023Instance[demodUnit].uNbSamples != 0 )
  {
    UInt32 uIndex;
    UInt32 uOffset;
    UInt32 uNextRF;

    //Find index of current channel
    uIndex = g10023Instance[demodUnit].sCurrentChannel.uRF - g10023Instance[demodUnit].uStartFrequency - (g10023Instance[demodUnit].uBandwidth/2);
    uIndex += g10023Instance[demodUnit].uBandwidth / 2;
    uIndex /= g10023Instance[demodUnit].uBandwidth;

    uOffset = g10023Instance[demodUnit].sCurrentChannel.uRF - (g10023Instance[demodUnit].uStartFrequency + g10023Instance[demodUnit].uBandwidth * uIndex + g10023Instance[demodUnit].uBandwidth/2);

    // if current channel is marked as potential channel but locked failed
    //move at least to the next channel
    if (g10023Instance[demodUnit].pPotentialChannel[uIndex])
      uIndex ++;
    else
    {
      // Find next channel that potentially contains a carrier
      while ( (g10023Instance[demodUnit].pPotentialChannel[uIndex] != 1)
          && (uIndex < NB_MAX_CHANNEL) )
      {
        uIndex ++;
      }
      if (g10023Instance[demodUnit].pPotentialChannel[uIndex] != 1)
      {
        g10023Instance[demodUnit].sCurrentChannel.uRF = g10023Instance[demodUnit].uStopFrequency;
        errCode = Tda10023WriteRF (&g10023Instance[demodUnit], &g10023Instance[demodUnit].sCurrentChannel.uRF);
        return errCode;
      }
    }

    // Move to the center of the next potential channel plus offset
    uNextRF =  g10023Instance[demodUnit].uStartFrequency + g10023Instance[demodUnit].uBandwidth * uIndex + (g10023Instance[demodUnit].uBandwidth/2) + uOffset;
    if ( uNextRF < g10023Instance[demodUnit].uStopFrequency )
    {
      g10023Instance[demodUnit].sCurrentChannel.uRF = uNextRF;
      g10023Instance[demodUnit].bState = 1;
      errCode = Tda10023WriteRF (&g10023Instance[demodUnit], &g10023Instance[demodUnit].sCurrentChannel.uRF);
      if ( errCode != TM_OK)
        return errCode;
    }
    else
    {
      g10023Instance[demodUnit].sCurrentChannel.uRF = g10023Instance[demodUnit].uStopFrequency;
    }
    }

    return TM_OK;
}

//-----------------------------------------------------------------------------
// FUNCTION:    tmbsl10023StopScan:
//
// DESCRIPTION: Stop the RF scanning
//
// RETURN:      TMBSL_ERR_DEMOD_BAD_UNIT_NUMBER
//              TMBSL_ERR_DEMOD_NOT_INITIALIZED
//              TM_OK
//
// NOTES:
//-----------------------------------------------------------------------------
//
tmErrorCode_t
tmbsl10023StopScan(
    tmUnitSelect_t demodUnit        //  I: Demod unit number
    )
{

    SEND_TRACEFCT1(DEBUG_STOPSCAN_ID, 0);

    //----------------------
    // test input parameters
    //----------------------
    // test the instance number
    if (demodUnit > TDA10023_MAX_UNITS)
        return TMBSL_ERR_DEMOD_BAD_UNIT_NUMBER;

    // test the object
    if (g10023Instance[demodUnit].sApiFlags.iInit == False)
        return TMBSL_ERR_DEMOD_NOT_INITIALIZED;

    //----------------------
    // Implementation
    //----------------------
  g10023Instance[demodUnit].sApiFlags.iPreScan = False;
  g10023Instance[demodUnit].sApiFlags.iScan = False;
  g10023Instance[demodUnit].bCarrierAnalyser = False;
  g10023Instance[demodUnit].bStateSpectrum = 10;

  if (!g10023Instance[demodUnit].bFlagAutoScan)
  {
    g10023Instance[demodUnit].uNbSamples = 0;
  }


    return TM_OK;
}
#endif


//-----------------------------------------------------------------------------
// FUNCTION:    tmbsl10023Manager
//
// DESCRIPTION: the function manages the synchronization algorithm.
//
// RETURN:      TMBSL_ERR_DEMOD_BAD_UNIT_NUMBER
//              TMBSL_ERR_DEMOD_NOT_INITIALIZED
//              TM_ERR_IIC_ERR
//              TM_OK
//        TM_FALSE
//
// NOTES:       TBD
//-----------------------------------------------------------------------------
//
tmErrorCode_t
tmbsl10023Manager (
    tmUnitSelect_t            demodUnit,         //  I: Demod unit number
    tmhalFEManagerStatus_t    *peStatusManager   //  O: status manager
)
{


    UInt32 NB_sat = 0, CVagc = 0, stop_bit = 0;

    SEND_TRACEFCT1(DEBUG_MANAGER_ID, 0);

    //----------------------
    // test input parameters
    //----------------------
    // test the instance number
    if (demodUnit > TDA10023_MAX_UNITS)
        return TMBSL_ERR_DEMOD_BAD_UNIT_NUMBER;

    // test the object
    if (g10023Instance[demodUnit].sApiFlags.iInit == False)
        return TMBSL_ERR_DEMOD_NOT_INITIALIZED;

    //--------------------
    // Test if not waiting
    //--------------------
    // read SYNC register
  if (g10023Instance[demodUnit].sConfig.bModeDvbMcns)
  {
    g10023Instance[demodUnit].systemFunc.SY_Read(
    g10023Instance[demodUnit].uDemodHwAdd, TDA10023_STATUS_MCNS_IND, 1, &g10023Instance[demodUnit].uSyncReg);

  }
  else
  {
    g10023Instance[demodUnit].systemFunc.SY_Read(
        g10023Instance[demodUnit].uDemodHwAdd, TDA10023_STATUS_IND, 1, &g10023Instance[demodUnit].uSyncReg);

  }


//no auto scan requirement
#if 0

    if (g10023Instance[demodUnit].sApiFlags.iPreScan)
    {
        tmErrorCode_t eAlgoResult;

      // test the symbol rate to check if is fixed or not
      if (g10023Instance[demodUnit].sConfig.uStartSymbolRate != g10023Instance[demodUnit].sConfig.uStopSymbolRate)
        {
            // Get the spectrum of the full RF range
            eAlgoResult = Tda10023SpectrumAnalyzer(&g10023Instance[demodUnit]);

            // test if the algorithm is completed
            if (eAlgoResult == TDA10023_ALGO_NOT_FINISHED_RET)
            {
              // leave function
              *peStatusManager = tmhalFEManagerStatusNotCompleted;
              return TM_OK;
            }
      else if (eAlgoResult == TDA10023_ALGO_SUCCESS_RET)
      {
        // Compute derivation
        eAlgoResult = Tda10023Derivation(&g10023Instance[demodUnit]);

              // test if the algorithm is completed
              if (eAlgoResult == TDA10023_ALGO_NOT_FINISHED_RET)
              {
                // leave function
                *peStatusManager = tmhalFEManagerStatusNotCompleted;
                return TM_OK;
              }
        else if (eAlgoResult == TDA10023_ALGO_SUCCESS_RET)
        {
          // Mark channel that potential contain a carrier
          eAlgoResult = Tda10023SpectrumFindCarrier(&g10023Instance[demodUnit]);

                // test if the algorithm is completed
                if (eAlgoResult == TDA10023_ALGO_NOT_FINISHED_RET)
                {
                  // leave function
                  *peStatusManager = tmhalFEManagerStatusNotCompleted;
                  return TM_OK;
                }
          else if (eAlgoResult == TDA10023_ALGO_SUCCESS_RET)
          {
            // re-start algo
            g10023Instance[demodUnit].sApiFlags.iStartAlgo = True;
            g10023Instance[demodUnit].sApiFlags.iPreScan = False;
            g10023Instance[demodUnit].sApiFlags.iScan = True;
            g10023Instance[demodUnit].bCarrierAnalyser = False;
            g10023Instance[demodUnit].uScanStep = 0;
            g10023Instance[demodUnit].sCurrentChannel.uRF = g10023Instance[demodUnit].uStartFrequency;
            Tda10023ResetDeltaF(&g10023Instance[demodUnit]);
              }

            }

            }

      }
    }

#endif



    //-----------------
    // Tuning managment
    //-----------------
    // main algo Initialization
    if (g10023Instance[demodUnit].sApiFlags.iStartAlgo == True)
    {
        UInt16    wAlgoTimer = 0;

        #ifdef BSL_DEBUG_BASIC
            SEND_TRACE(DEBUG_STARTALGO_ID, 0);
        #endif

    // clear the flag
        g10023Instance[demodUnit].sApiFlags.iStartAlgo = False;

        //Init ppm recovery
        g10023Instance[demodUnit].bStateClkOffset = 0;
        g10023Instance[demodUnit].lClkOffCst = 0;
        g10023Instance[demodUnit].GainOK = False;

        // initialize the main algo
        g10023Instance[demodUnit].bState = 0;
        Tda10023_MainAlgo(&g10023Instance[demodUnit], &wAlgoTimer);
        // leave function
        internal10023Wait(wAlgoTimer);

        *peStatusManager = tmhalFEManagerStatusNotCompleted;

        return TM_OK;
    }

    // main algo processing
    if (g10023Instance[demodUnit].bState)
    {
        UInt16    wAlgoTimer = 0;
        tmhalFEManagerStatus_t eAlgoStatus;

        // execute
        eAlgoStatus = Tda10023_MainAlgo(&g10023Instance[demodUnit], &wAlgoTimer);
        // test if the algorithm is completed
        if (eAlgoStatus == tmhalFEManagerStatusNotCompleted)
        {
            // initialize the timer
             internal10023Wait(wAlgoTimer);

            // leave function
            *peStatusManager = tmhalFEManagerStatusNotCompleted;
            return TM_OK;
        }
        else if (eAlgoStatus == tmhalFEManagerStatusCarrierOk)
        {
            // program the CARCONF register regarding to the symbol rate value
            if ((g10023Instance[demodUnit].sCurrentChannel.uSR <= 1750000) &&
                (g10023Instance[demodUnit].sCurrentChannel.eMOD != tmhalFEModulationQam256))
                g10023Instance[demodUnit].systemFunc.SY_WriteBit(g10023Instance[demodUnit].uDemodHwAdd,
                    TDA10023_CARCONF_IND, TDA10023_CARCONF_CAR_C_MSK, 0x05);
            else if (g10023Instance[demodUnit].sCurrentChannel.uSR > 3000000)
                g10023Instance[demodUnit].systemFunc.SY_WriteBit(g10023Instance[demodUnit].uDemodHwAdd,
                    TDA10023_CARCONF_IND, TDA10023_CARCONF_CAR_C_MSK, 0x02);
            else
                g10023Instance[demodUnit].systemFunc.SY_WriteBit(g10023Instance[demodUnit].uDemodHwAdd,
                    TDA10023_CARCONF_IND, TDA10023_CARCONF_CAR_C_MSK, 0x0a);

             // algo completed
            g10023Instance[demodUnit].bState = 0;

            // stop a scanning, a frequency is found
            g10023Instance[demodUnit].sApiFlags.iScan = False;

            #ifdef BSL_DEBUG_BASIC
                SEND_TRACE(DEBUG_ALGOSUCCESS_ID, 0);
            #endif
        }
        else if (eAlgoStatus == tmhalFEManagerStatusNoCarrier)
        {
      // program the CARCONF register regarding to the symbol rate value
            if ((g10023Instance[demodUnit].sCurrentChannel.uSR <= 1750000) &&
                (g10023Instance[demodUnit].sCurrentChannel.eMOD != tmhalFEModulationQam256))
                g10023Instance[demodUnit].systemFunc.SY_WriteBit(g10023Instance[demodUnit].uDemodHwAdd,
                    TDA10023_CARCONF_IND, TDA10023_CARCONF_CAR_C_MSK, 0x05);
            else if (g10023Instance[demodUnit].sCurrentChannel.uSR > 3000000)
                g10023Instance[demodUnit].systemFunc.SY_WriteBit(g10023Instance[demodUnit].uDemodHwAdd,
                    TDA10023_CARCONF_IND, TDA10023_CARCONF_CAR_C_MSK, 0x02);
            else
                g10023Instance[demodUnit].systemFunc.SY_WriteBit(g10023Instance[demodUnit].uDemodHwAdd,
                    TDA10023_CARCONF_IND, TDA10023_CARCONF_CAR_C_MSK, 0x0a);
            // calculate the step for the next frequency in scanning
            if (2 == g10023Instance[demodUnit].bState /*|| 3 == g10023Instance[demodUnit].bState*/)
            {
                // step frequency is 50% of SR
                g10023Instance[demodUnit].uScanStep = g10023Instance[demodUnit].sCurrentChannel.uSR/2;

            }
            else
            {
                // step frequency is uScanStep/10000 (default is 4.68%) of SR
                #ifdef NO_FLOAT
                g10023Instance[demodUnit].uScanStep = Tda10023MulDiv32(g10023Instance[demodUnit].sCurrentChannel.uSR,g10023Instance[demodUnit].uSWDynValue,100);
                #else
                g10023Instance[demodUnit].uScanStep = (UInt32)(g10023Instance[demodUnit].sCurrentChannel.uSR*(((float)g10023Instance[demodUnit].uSWDynValue/100)));
                #endif
                g10023Instance[demodUnit].uScanStep += 50;
                g10023Instance[demodUnit].uScanStep /= 100;
            }

      // In case of fast scan
      if ((2 == g10023Instance[demodUnit].bState) && (g10023Instance[demodUnit].sApiFlags.iScan) && (g10023Instance[demodUnit].uNbSamples))
      {
        UInt32 uIndex;

        uIndex = g10023Instance[demodUnit].sCurrentChannel.uRF - g10023Instance[demodUnit].uStartFrequency - g10023Instance[demodUnit].uBandwidth / 2;
        uIndex += g10023Instance[demodUnit].uBandwidth / 2;
        uIndex /= g10023Instance[demodUnit].uBandwidth;
        if (g10023Instance[demodUnit].pPotentialChannel[uIndex])
        {
          // step frequency is uScanStep/10000 of SR
          #ifdef NO_FLOAT
          g10023Instance[demodUnit].uScanStep = Tda10023MulDiv32(g10023Instance[demodUnit].sCurrentChannel.uSR,g10023Instance[demodUnit].uSWDynValue,100);
          #else
          g10023Instance[demodUnit].uScanStep = (UInt32)(g10023Instance[demodUnit].sCurrentChannel.uSR*((float)g10023Instance[demodUnit].uSWDynValue/100));
          #endif
          g10023Instance[demodUnit].uScanStep += 50;
          g10023Instance[demodUnit].uScanStep /= 100;
        }

      }

            // algo completed
            g10023Instance[demodUnit].bState = 0;

            #ifdef BSL_DEBUG_BASIC
                SEND_TRACE(DEBUG_ALGOFAILED_ID, 0);
            #endif
        }
    }

    //--------------------
    // Scanning management
    //--------------------
    if (g10023Instance[demodUnit].sApiFlags.iScan)
    {
        // test if the end of band is reached
        if (Tda10023WriteNextScan(&g10023Instance[demodUnit]) == TM_FALSE)
        {
            // stop the scanning
            g10023Instance[demodUnit].sApiFlags.iScan = 0;
      g10023Instance[demodUnit].uNbSamples = 0;
            *peStatusManager = tmhalFEManagerStatusNoCarrier;
            return TM_OK;
        }

        // re-start algo
        g10023Instance[demodUnit].sApiFlags.iStartAlgo = True;
        *peStatusManager = tmhalFEManagerStatusNotCompleted;

        return TM_OK;
    }

    //-------------
    // Return Value
    //-------------
    if ((g10023Instance[demodUnit].uSyncReg & TDA10023_STATUS_FSYNC_BIT)||
    (g10023Instance[demodUnit].uSyncReg & TDA10023_STATUS_MCNS_MPEGLCK_BIT))
        *peStatusManager = tmhalFEManagerStatusCarrierOk;
    else
        *peStatusManager = tmhalFEManagerStatusNoCarrier;













    return TM_OK;
}

//-----------------------------------------------------------------------------
// Internal Read functions:
//-----------------------------------------------------------------------------
//

//-----------------------------------------------------------------------------
// FUNCTION:    Tda10023ReadAFC:
//
// DESCRIPTION: read the AFC
//
// RETURN:      TM_ERR_IIC_ERR
//              TM_OK
//
// NOTES:
//-----------------------------------------------------------------------------
//




tmErrorCode_t
Tda10023ReadAFC (
    tm10023object_t *psObject,
    Int32            *plAfc
)
{
    SEND_TRACEFCT4(DEBUG_READAFC_ID, 0);

    // read the registers
    if(psObject->systemFunc.SY_Read( psObject->uDemodHwAdd, TDA10023_AFC_IND, 1, plAfc) == False) return TM_ERR_IIC_ERR;

    // signed value
    if (*plAfc & 0x80)
        *plAfc |= 0xFFFFFF00;

    // calculate the value in Hz
    *plAfc *= (Int32)((psObject->sCurrentChannel.uSR + 256)/512);

    // invert the AFC to display the offset and not the correction
  if (psObject->sConfig.bTUN_IQSwap == 1)
    *plAfc = -*plAfc;

    return TM_OK;
}


//-----------------------------------------------------------------------------
// Internal Write functions:
//-----------------------------------------------------------------------------
//

//-----------------------------------------------------------------------------
// FUNCTION:    Tda10023WriteInit:
//
// DESCRIPTION: write the default configuration
//
// RETURN:      TM_ERR_IIC_ERR
//              TM_OK
//
// NOTES:       TBD
//-----------------------------------------------------------------------------
//
tmErrorCode_t
Tda10023WriteInit (
    tm10023object_t *psObject
)
{
    UInt32 puByte[3], uByte, uFilterBW;
    Int32 lDeltaF;
    UInt32 uSACLK;
    tmErrorCode_t Error_Code;

    SEND_TRACEFCT3(DEBUG_WRITEINIT_ID, 0);

    // calculate the system frequency
    psObject->uSysClk = psObject->sConfig.uXtalFreq * (psObject->sConfig.bPLL_M_Factor+1);
    psObject->uSysClk /= (psObject->sConfig.bPLL_N_Factor+1)*(psObject->sConfig.bPLL_P_Factor+1);

    // Calculate the sampling clock
    if(psObject->sConfig.bFsampling)
    {
        // high sampling clock
        uSACLK = psObject->uSysClk;
    }
    else
    {
        // low sampling clock
        uSACLK = psObject->uSysClk/2;
    }

    switch(psObject->sConfig.uBoard)
    {
  case 0x57640122:
         // SCL_T is force to 0 for 0x57640022
        if(psObject->systemFunc.SY_WriteBit(
            psObject->uDemodHwAdd,
            TDA10023_TEST_IND, TDA10023_TEST_SCLT0_BIT,
            0) == False) return TM_ERR_IIC_ERR;
    break;
    default:

    break;
  }



    // read the PLL M,N,P values
    if (psObject->systemFunc.SY_Read(psObject->uDemodHwAdd, TDA10023_PLL1_IND, 2, puByte) != True)
        return TM_ERR_IIC_ERR;

    if(psObject->systemFunc.SY_Read(psObject->uDemodHwAdd, TDA10023_GPR_IND, 1, &uByte) == False) return TM_ERR_IIC_ERR;

    // change the PLL M,N,P values and FSAMPLING only if different
    if((puByte[0] != psObject->sConfig.bPLL_M_Factor) ||
       ((puByte[1] & TDA10023_PLL2_PDIV_MSK) != psObject->sConfig.bPLL_N_Factor) ||
       (((puByte[1] & TDA10023_PLL2_NDIV_MSK)>>6) != psObject->sConfig.bPLL_P_Factor) ||
       (((uByte & TDA10023_GPR_FSAMPLING_BIT) >> 5) != psObject->sConfig.bFsampling) )
    {
        UInt32 uPLL3;

        // disable the PLL
        if(psObject->systemFunc.SY_Read(psObject->uDemodHwAdd,
            TDA10023_PLL3_IND, 1, &uPLL3) == False) return TM_ERR_IIC_ERR;
        uPLL3 |= (TDA10023_PLL3_BYPPLL_BIT | TDA10023_PLL3_PDPLL_BIT);
        if(psObject->systemFunc.SY_Write(psObject->uDemodHwAdd,
            TDA10023_PLL3_IND, 1, &uPLL3) == False) return TM_ERR_IIC_ERR;

        // !!!! NOTE !!!! : When the PLL is disable, TDA10023 registers can't be read
        // Therefore, SY_Read and SY_WriteBit functions must not be called


        internal10023Wait(100);

        // PLL factors
        puByte[0]  = (UInt32)psObject->sConfig.bPLL_M_Factor;
        puByte[1]  = (UInt32)psObject->sConfig.bPLL_N_Factor;
        puByte[1] |= (UInt32)(psObject->sConfig.bPLL_P_Factor << 6);

        // write the PLL registers with PLL bypassed
        if(psObject->systemFunc.SY_Write(psObject->uDemodHwAdd, TDA10023_PLL1_IND, 2, puByte) == False) return TM_ERR_IIC_ERR;

        // Set FSAMPLING
        if(psObject->sConfig.bFsampling)
        {
//            psObject->systemFunc.SY_WriteBit(
//                psObject->uDemodHwAdd,
//                TDA10023_GPR_IND,
//                TDA10023_GPR_FSAMPLING_BIT | TDA10023_GPR_CLBS2_BIT | TDA10023_GPR_CLBS_BIT,
//                TDA10023_GPR_FSAMPLING_BIT | TDA10023_GPR_CLBS2_BIT | TDA10023_GPR_CLBS_BIT);

            uByte = TDA10023_GPR_FSAMPLING_BIT | TDA10023_GPR_CLBS2_BIT | TDA10023_GPR_CLBS_BIT;
            if(psObject->systemFunc.SY_Write(psObject->uDemodHwAdd, TDA10023_GPR_IND, 1, &uByte) == False) return TM_ERR_IIC_ERR;
        }
        else
        {
//            psObject->systemFunc.SY_WriteBit(
//                psObject->uDemodHwAdd,
//                TDA10023_GPR_IND,
//                TDA10023_GPR_FSAMPLING_BIT | TDA10023_GPR_CLBS2_BIT | TDA10023_GPR_CLBS_BIT,
//                0                          | TDA10023_GPR_CLBS2_BIT | TDA10023_GPR_CLBS_BIT);


            uByte = TDA10023_GPR_CLBS2_BIT | TDA10023_GPR_CLBS_BIT;
            if(psObject->systemFunc.SY_Write(psObject->uDemodHwAdd, TDA10023_GPR_IND, 1, &uByte) == False) return TM_ERR_IIC_ERR;
        }

        // enable the PLL
//        psObject->systemFunc.SY_WriteBit(psObject->uDemodHwAdd,
//            TDA10023_PLL3_IND, TDA10023_PLL3_BYPPLL_BIT | TDA10023_PLL3_PDPLL_BIT, 0);
        uPLL3 &= ~(TDA10023_PLL3_BYPPLL_BIT | TDA10023_PLL3_PDPLL_BIT);
        if(psObject->systemFunc.SY_Write(psObject->uDemodHwAdd,
            TDA10023_PLL3_IND, 1, &uPLL3) == False) return TM_ERR_IIC_ERR;

        internal10023Wait(100);

    }

#ifdef _ALPS_TDQE_
  // change I2C switch clock for ALPS TDQE5
  uByte=0x03;
  if(psObject->systemFunc.SY_Write(psObject->uDemodHwAdd,
    TDA10023_CLBSTIM_I2CSWTCH_IND, 1, &uByte) == False) return TM_ERR_IIC_ERR;
#endif

    // Set DVB/MCNS mode
    if (psObject->sConfig.bModeDvbMcns)
    {
        // MCNS mode
        if(psObject->systemFunc.SY_WriteBit(
            psObject->uDemodHwAdd,
            TDA10023_RESET_IND,
            TDA10023_RESET_DVBMCNS_BIT,
            TDA10023_RESET_DVBMCNS_BIT) == False) return TM_ERR_IIC_ERR;

        // set the BER depth
        if(psObject->systemFunc.SY_WriteBit(psObject->uDemodHwAdd,
            TDA10023_RSCFG_IND, TDA10023_RSCFG_PRG_TBER_MSK, psObject->sConfig.bBERdepth << 2) == False) return TM_ERR_IIC_ERR;

    //Configure the IT to know if there are Uncor
    if(psObject->systemFunc.SY_WriteBit(psObject->uDemodHwAdd,
            TDA10023_ITSEL1_IND, 0x04, 0x04) == False) return TM_ERR_IIC_ERR;

    //Configure the IT to know if there are Uncor
    if(psObject->systemFunc.SY_WriteBit(psObject->uDemodHwAdd,
            TDA10023_ITSEL2_IND, 0x04, 0x04) == False) return TM_ERR_IIC_ERR;

    }
    else
    {
        // DVB mode
        if(psObject->systemFunc.SY_WriteBit(
            psObject->uDemodHwAdd,
            TDA10023_RESET_IND,
            TDA10023_RESET_DVBMCNS_BIT,
            0) == False) return TM_ERR_IIC_ERR;

        // set the BER depth
        if(psObject->systemFunc.SY_WriteBit(psObject->uDemodHwAdd,
            TDA10023_FECDVBCFG1_IND, TDA10023_FECDVBCFG1_PVBER_MSK, psObject->sConfig.bBERdepth << 6) == False) return TM_ERR_IIC_ERR;

    }

    // set GAIN1 bit to 0
  if ( psObject->eBandType  != tmhalFEBandTypeSECAM_L )
  {
      uByte = TDA10023_GAIN1_DEF;
    if(psObject->systemFunc.SY_Write(psObject->uDemodHwAdd, TDA10023_GAIN1_IND, 1, &uByte) == False) return TM_ERR_IIC_ERR;
  }
  else
  {
    if(psObject->systemFunc.SY_Read(psObject->uDemodHwAdd, TDA10023_GAIN1_IND, 1, &uByte) == False) return TM_ERR_IIC_ERR;
    uByte &= 0x7C;
    if(psObject->systemFunc.SY_Write(psObject->uDemodHwAdd, TDA10023_GAIN1_IND, 1, &uByte) == False) return TM_ERR_IIC_ERR;
  }

  // program the SWEEP Ramp mode
    psObject->systemFunc.SY_WriteBit( psObject->uDemodHwAdd,
        TDA10023_CARCONF_IND, TDA10023_SWEEP_MODE_MSK, TDA10023_SWEEP_MODE_MSK);

  // Nb of samples in STAT depends on reg SSAT
    if (psObject->systemFunc.SY_Read(
            psObject->uDemodHwAdd,
            TDA10023_GAIN1_IND, 1, &uByte) == False)
        return TM_ERR_IIC_ERR;

    switch ((uByte & 0x03) )
    {
      case 0:
      psObject->uNbSamplesSSAT = 16384;
        break;
      case 1:
      psObject->uNbSamplesSSAT = 8192;
        break;
      case 2:
      psObject->uNbSamplesSSAT = 4096;
        break;
      case 3:
      psObject->uNbSamplesSSAT = 2048;
        break;
  }
    // set the acquisition to +/-480ppm
    if(psObject->systemFunc.SY_WriteBit(psObject->uDemodHwAdd,
        TDA10023_CLKCONF_IND, TDA10023_CLKCONF_DYN_BIT, TDA10023_CLKCONF_DYN_BIT) == False) return TM_ERR_IIC_ERR;

    if (psObject->sConfig.bClkOffsetRange)
    {
        // set CLK_C to the minimum
        if(psObject->systemFunc.SY_WriteBit(psObject->uDemodHwAdd,
            TDA10023_CLKCONF_IND, TDA10023_CLK_C_MASK, 0x00) == False) return TM_ERR_IIC_ERR;
    }
    else
    {
        // set CLK_C to the default value (2)
        if(psObject->systemFunc.SY_WriteBit(psObject->uDemodHwAdd,
            TDA10023_CLKCONF_IND, TDA10023_CLK_C_MASK, 0x02) == False) return TM_ERR_IIC_ERR;
    }

    // TRIAGC, POSAGC, enable AGCIF
#ifdef _MULTIFE_CU1216
    if(psObject->systemFunc.SY_WriteBit(psObject->uDemodHwAdd,
        TDA10023_AGCCONF2_IND,
        TDA10023_AGCCONF2_TRIAGC_BIT | TDA10023_AGCCONF2_POSAGC_BIT | TDA10023_AGCCONF2_ENAGCIF_BIT,
        0                            | TDA10023_AGCCONF2_POSAGC_BIT) == False) return TM_ERR_IIC_ERR;
#else
  if ( psObject->eBandType  != tmhalFEBandTypeSECAM_L )
  {
    if(psObject->systemFunc.SY_WriteBit(psObject->uDemodHwAdd,
      TDA10023_AGCCONF2_IND,
      TDA10023_AGCCONF2_TRIAGC_BIT | TDA10023_AGCCONF2_POSAGC_BIT | TDA10023_AGCCONF2_ENAGCIF_BIT,
      0                            | TDA10023_AGCCONF2_POSAGC_BIT | TDA10023_AGCCONF2_ENAGCIF_BIT) == False) return TM_ERR_IIC_ERR;

    // set the AGCREF
    uByte = TDA10023_AGCREF_DEF; /*optimized for adjacent signal*/
    if(psObject->systemFunc.SY_Write(psObject->uDemodHwAdd, TDA10023_AGCREF_IND, 1, &uByte) == False) return TM_ERR_IIC_ERR;
  }
  else
  {
    if(psObject->systemFunc.SY_WriteBit(psObject->uDemodHwAdd,
      TDA10023_AGCCONF2_IND,
      TDA10023_AGCCONF2_TRIAGC_BIT | TDA10023_AGCCONF2_POSAGC_BIT | TDA10023_AGCCONF2_ENAGCIF_BIT,
      0                            | 0 | TDA10023_AGCCONF2_ENAGCIF_BIT) == False) return TM_ERR_IIC_ERR;

    // set the AGCREF
    uByte = TDA10023_AGCREF_SECAM_DEF; /*optimized for adjacent signal*/
    if(psObject->systemFunc.SY_Write(psObject->uDemodHwAdd, TDA10023_AGCREF_IND, 1, &uByte) == False) return TM_ERR_IIC_ERR;
  }
#endif

    // set SACLK_OFF
    // Remove SACLK sice it is not used and generate interferences
    if(psObject->systemFunc.SY_WriteBit(psObject->uDemodHwAdd,
        TDA10023_CONTROL_IND,
        TDA10023_CONTROL_OLDBYTECLK_BIT ,
        TDA10023_CONTROL_OLDBYTECLK_BIT ) == False) return TM_ERR_IIC_ERR;

    // program CS depending on SACLK and set GAINADC
/*
    if (uSACLK < 25000000)
    {
        uByte = (0<<6) | TDA10023_ADC_GAINADC_BIT | TDA10023_ADC_TWOS_BIT;
    }
    else if (uSACLK < 35000000)
    {
        uByte = (1<<6) | TDA10023_ADC_GAINADC_BIT | TDA10023_ADC_TWOS_BIT;;
    }
    else if (uSACLK < 50000000)
    {
        uByte = (2<<6) | TDA10023_ADC_TWOS_BIT;;
    }
    else
    {
        uByte = (3<<6) | TDA10023_ADC_TWOS_BIT;;
    }
*/
    if (uSACLK < 60000000)
        uByte = 0x48; // according to Pascal recommendation to reduce sampling clock interference
    else
        uByte = 0xC8;

    if(psObject->systemFunc.SY_Write(psObject->uDemodHwAdd,
        TDA10023_ADC_IND,
        1,
        &uByte) == False) return TM_ERR_IIC_ERR;


    // set the polarity of the PWM for the AGC
    if (psObject->sConfig.bPolaPWM1)
  {
        if(psObject->systemFunc.SY_WriteBit(psObject->uDemodHwAdd, TDA10023_AGCCONF2_IND, TDA10023_AGCCONF2_PPWMTUN_BIT, TDA10023_AGCCONF2_PPWMTUN_BIT) == False) return TM_ERR_IIC_ERR;
  }
    else
  {
        if(psObject->systemFunc.SY_WriteBit(psObject->uDemodHwAdd, TDA10023_AGCCONF2_IND, TDA10023_AGCCONF2_PPWMTUN_BIT, 0) == False) return TM_ERR_IIC_ERR;
  }
    if (psObject->sConfig.bPolaPWM2)
  {
        if(psObject->systemFunc.SY_WriteBit(psObject->uDemodHwAdd, TDA10023_AGCCONF2_IND, TDA10023_AGCCONF2_PPWMIF_BIT, TDA10023_AGCCONF2_PPWMIF_BIT) == False) return TM_ERR_IIC_ERR;
  }
    else
  {
        if(psObject->systemFunc.SY_WriteBit(psObject->uDemodHwAdd, TDA10023_AGCCONF2_IND, TDA10023_AGCCONF2_PPWMIF_BIT, 0) == False) return TM_ERR_IIC_ERR;
  }
    // set the threshold for the IF AGC
    puByte[0] = psObject->sConfig.bIFMax;
    puByte[1] = psObject->sConfig.bIFMin;
    if(psObject->systemFunc.SY_Write(psObject->uDemodHwAdd, TDA10023_IFMAX_IND, 2, puByte) == False) return TM_ERR_IIC_ERR;

    // set the threshold for the TUN AGC
    puByte[0] = psObject->sConfig.bTUNMax;
    puByte[1] = psObject->sConfig.bTUNMin;
    if(psObject->systemFunc.SY_Write(psObject->uDemodHwAdd, TDA10023_TUNMAX_IND, 2, puByte) == False) return TM_ERR_IIC_ERR;

    // configure the equalizer
    if(psObject->sConfig.bEqualType == 0)
    {
        // disable the equalizer
        uByte = TDA10023_EQCONF1_DEF;
    }
    else
    {
        // enable the equalizer and set the DFE bit
        uByte = TDA10023_EQCONF1_DEF |
                TDA10023_EQCONF1_ENADAPT_BIT |
                TDA10023_EQCONF1_ENEQUAL_BIT |
                (psObject->sConfig.bEqualType-1);
    }
    if(psObject->systemFunc.SY_Write(psObject->uDemodHwAdd, TDA10023_EQCONF1_IND, 1, &uByte) == False) return TM_ERR_IIC_ERR;

    //
    if(psObject->systemFunc.SY_WriteBit(
        psObject->uDemodHwAdd,
        TDA10023_EQCONF2_IND,
        TDA10023_EQCONF2_SGNALGO_BIT | TDA10023_EQCONF2_STEPALGO_BIT,
        TDA10023_EQCONF2_SGNALGO_BIT | TDA10023_EQCONF2_STEPALGO_BIT) == False) return TM_ERR_IIC_ERR;

#ifdef _CTPHASE_
  //not use, leave here in case it's needed
  //changejb force the CTPHASE to 1 bit 6 reg 0x1c
  if(psObject->systemFunc.SY_WriteBit(
        psObject->uDemodHwAdd,
        TDA10023_EQCONF2_IND,
        0x40,
        0x40) == False) return TM_ERR_IIC_ERR;
#endif

    // set ALGOD and deltaF
    if(psObject->sConfig.bFsampling)
    {
        // FSAMPLING = 1 - high sampling clock
        // SACLK = Sysclk  (SACLK max = 72MHz)
        lDeltaF  = (Int32)(psObject->sConfig.uTUN_IF/1000);
        lDeltaF *= 32768;                                   // 32768 = 2^20/32
        lDeltaF += (Int32)(psObject->uSysClk/500);
        lDeltaF /= (Int32)(psObject->uSysClk/1000);
        lDeltaF -= 53248; // 53248 = (2^20/32) * 13/8
    }
    else
    {
        // FSAMPLING = 0 - low sampling clock
        // SACLK = Sysclk/2 (SACLK max = 36MHz)
        lDeltaF  = (Int32)(psObject->sConfig.uTUN_IF/1000);
        lDeltaF *= 32768;                                   // 32768 = 2^20/32
        lDeltaF += (Int32)(psObject->uSysClk/1000);
        lDeltaF /= (Int32)(psObject->uSysClk/2000);
        lDeltaF -= 40960;  // 40960 = (2^20/32) * 5/4;
    }

    puByte[0] = (UInt8)lDeltaF;
    puByte[1] = (UInt8)(((lDeltaF>>8) & 0x7F) | TDA10023_DELTAF_MSB_ALGOD_BIT);
    if(psObject->systemFunc.SY_Write(psObject->uDemodHwAdd, TDA10023_DELTAF_LSB_IND, 2, puByte) == False) return TM_ERR_IIC_ERR;

    // set the KAGCIF and KAGCTUN to acquisition mode
#ifdef _CHINA_CABLE_
            uByte = 0x92;
#else
            uByte = 0x96;
#endif
    if(psObject->systemFunc.SY_Write(psObject->uDemodHwAdd,
        TDA10023_AGCCONF1_IND, 1, &uByte) == False) return TM_ERR_IIC_ERR;


    // set carrier algorithm parameters
    uByte  = TDA10023_SWEEP_DEF;
    uByte |= psObject->sConfig.bSwDyn << 4;
    uByte |= psObject->sConfig.bSwStep << 2;
    if(psObject->systemFunc.SY_Write(psObject->uDemodHwAdd, TDA10023_SWEEP_IND, 1, &uByte) == False) return TM_ERR_IIC_ERR;

    // set the MPEG output clock polarity
    if(psObject->sConfig.bOUT_OClk1)
  {
        if(psObject->systemFunc.SY_WriteBit(psObject->uDemodHwAdd,
        TDA10023_INTP1_IND, TDA10023_INTP1_POCLKP_BIT, TDA10023_INTP1_POCLKP_BIT) == False) return TM_ERR_IIC_ERR;
    }
    else
  {
        if(psObject->systemFunc.SY_WriteBit(psObject->uDemodHwAdd,
        TDA10023_INTP1_IND, TDA10023_INTP1_POCLKP_BIT, 0) == False) return TM_ERR_IIC_ERR;
  }
    if(psObject->sConfig.bOUT_OClk2)
  {
        if(psObject->systemFunc.SY_WriteBit(psObject->uDemodHwAdd,
        TDA10023_INTS1_IND, TDA10023_INTS1_POCLKS_BIT, TDA10023_INTS1_POCLKS_BIT) == False) return TM_ERR_IIC_ERR;
    }
    else
  {
        if(psObject->systemFunc.SY_WriteBit(psObject->uDemodHwAdd,
        TDA10023_INTS1_IND, TDA10023_INTS1_POCLKS_BIT, 0) == False) return TM_ERR_IIC_ERR;
  }
    // TS interface 1
    uByte = 0;
    if(psObject->sConfig.bOUT_bMSBFirst1)
        uByte |= TDA10023_INTP2_MSBFIRSTP_BIT;
    if(psObject->sConfig.bOUT_bParaSer1)
    {
        // SERIAL
        uByte |= TDA10023_INTP2_INTSEL_SER_DEF;
    }
    else
    {
        // PARALLEL
        // set to 1 MSB if parallel
//        uByte |= TDA10023_INTP2_MSBFIRSTP_BIT;

        if(psObject->sConfig.bOUT_ModeABC1 == 0)
        {
            // PARALLEL mode A
            uByte |= TDA10023_INTP2_INTSEL_PARA_DEF;
        }
        else if(psObject->sConfig.bOUT_ModeABC1 == 1)
        {
            // PARALLEL mode B
            uByte |= TDA10023_INTP2_INTSEL_PARB_DEF;
            uByte |= psObject->sConfig.bOUT_ParaDiv1 << 4;
        }
        else //if(psObject->sConfig.bOUT_ModeABC1 == 2)
        {
            // PARALLEL mode C
            uByte |= TDA10023_INTP2_INTSEL_PARC_DEF;
        }
    }
    if(psObject->systemFunc.SY_Write(psObject->uDemodHwAdd, TDA10023_INTP2_IND, 1, &uByte) == False) return TM_ERR_IIC_ERR;

    // TS interface 2
    if(psObject->sConfig.bOUT_bMSBFirst2)
  {
        if(psObject->systemFunc.SY_WriteBit(psObject->uDemodHwAdd,
        TDA10023_INTPS_IND, TDA10023_INTPS_MSBFIRSTS_BIT, TDA10023_INTPS_MSBFIRSTS_BIT) == False) return TM_ERR_IIC_ERR;
  }
    else
  {
        if(psObject->systemFunc.SY_WriteBit(psObject->uDemodHwAdd,
        TDA10023_INTPS_IND, TDA10023_INTPS_MSBFIRSTS_BIT, 0) == False) return TM_ERR_IIC_ERR;
  }
    // disable the tri state of the outputs
    if(psObject->systemFunc.SY_WriteBit(psObject->uDemodHwAdd,
        TDA10023_INTPS_IND, TDA10023_INTPS_TRIP_BIT | TDA10023_INTPS_TRIS_BIT, 0) == False) return TM_ERR_IIC_ERR;

        psObject->uBandwidth = 8000000 ;

#ifdef QAM256_OPTIMIZATION
    /* --> Equalizer setting:  */
    /* Equalizer Step in acquisition phase -> set 1 to program low step for in-band tilt */
    if(psObject->systemFunc.SY_WriteBit(psObject->uDemodHwAdd,
        TDA10023_EQSTEP_IND, TDA10023_EQSTACQ_MSK, 0x01) == False) return TM_ERR_IIC_ERR;

    /* Equalizer Step in tracking phase -> set 5 to program high step for 100Hz hum(amplitude modulation) */
    if(psObject->systemFunc.SY_WriteBit(psObject->uDemodHwAdd,
        TDA10023_EQSTEP_IND, TDA10023_EQSTTRAC_MSK, 0x28) == False) return TM_ERR_IIC_ERR;

    /* --> AGC convergence threshold: set to 0x60 to avoid unlock with 100Hz hum */
    uByte = 0x60;
    if(psObject->systemFunc.SY_Write(psObject->uDemodHwAdd,
        TDA10023_ERAGC_THD_IND, 1, &uByte) == False) return TM_ERR_IIC_ERR;
#endif

    // Soft reset
    Error_Code = Tda10023ResetAll(psObject);
    if(Error_Code != TM_OK) return(Error_Code);

    return TM_OK;
}

//-----------------------------------------------------------------------------
// FUNCTION:    Tda10023ResetAll:
//
// DESCRIPTION: reset the TDA10023 and start all hardware algo
//
// RETURN:      TM_OK or TM_ERR_IIC_ERR
//
// NOTES:
//-----------------------------------------------------------------------------
//
tmErrorCode_t
Tda10023ResetAll (
    tm10023object_t *psObject
)
{
    SEND_TRACEFCT3(DEBUG_RESETALL_ID, 0);

    // reset the chip
    if(psObject->systemFunc.SY_WriteBit(
        psObject->uDemodHwAdd,
        TDA10023_GPR_IND,
        TDA10023_GPR_CLBS2_BIT | TDA10023_GPR_CLBS_BIT,
        TDA10023_GPR_CLBS2_BIT | 0) == False) return TM_ERR_IIC_ERR;

    return TM_OK;
}

//-----------------------------------------------------------------------------
// FUNCTION:    Tda10023WriteRF
//
// DESCRIPTION: this function will program the tuner and the offset
//
// RETURN:      TM_FALSE
//              TM_ERR_IIC_ERR
//              TM_OK
//
// NOTES:
//-----------------------------------------------------------------------------
//
tmErrorCode_t
Tda10023WriteRF (
    tm10023object_t  *psObject,  // IO: Demod object
    UInt32           *puRF       // IO: Frequency
)
{
struct dvb_frontend_parameters p;
    SEND_TRACEFCT3(DEBUG_WRITERF_ID, 0);

    // tuner is accessible
    if(psObject->systemFunc.SY_WriteBit( psObject->uDemodHwAdd,
        TDA10023_TEST_IND, TDA10023_TEST_BYPIIC_BIT,
        TDA10023_TEST_BYPIIC_BIT) == False) return TM_ERR_IIC_ERR;


    p.frequency = *puRF;
    // call the tuner function with the tuner IF
       if (sState->frontend.ops.tuner_ops.set_params)
      {
        sState->frontend.ops.tuner_ops.set_params(&(sState->frontend), &p);
        if (sState->frontend.ops.i2c_gate_ctrl)
        {
            sState->frontend.ops.i2c_gate_ctrl(&(sState->frontend), 0);
        }
      }
    // tuner is disconnected from the I2C bus
    if(psObject->systemFunc.SY_WriteBit( psObject->uDemodHwAdd,
        TDA10023_TEST_IND, TDA10023_TEST_BYPIIC_BIT, 0) == False) return TM_ERR_IIC_ERR;

    /* call the tuner function with the tuner IF */
    switch(psObject->sConfig.uBoard)
    {
  case 0x57640199:
  case 0x38530000:
    break;
    default:
        *puRF -= psObject->sConfig.uTUN_IF;
    break;
  }

    #ifdef BSL_SCANNING_BASIC
        SEND_TRACE(DEBUG_FREQUENCY_ID, *puRF);
    #endif

    return TM_OK;
}

//-----------------------------------------------------------------------------
// FUNCTION:    Tda10023WriteQAM
//
// DESCRIPTION: this function will program the modulation
//
// RETURN:      TM_FALSE
//              TM_ERR_IIC_ERR
//              TM_OK
//
// NOTES:       0->16qam 1->32qam 2->64qam 3->128qam 4->256qam 5->4qam
//-----------------------------------------------------------------------------
//
tmErrorCode_t
Tda10023WriteQAM (
    tm10023object_t   *psObject,  // I: Demod object
    UInt32            uMod        // I: Modulation
)
{
    static tm10023Qam_t sTypeQAM[] = {
      //  QAM   LOCKTHR  MSETH   AREF AGCREFNYQ  ERAGCNYQ_THD
        { 0x00, 0x87,    0xa2,   0x91,   0x8c,   0x57 /*0x4f*/ },  // 16 QAM   <=> qam=0
        { 0x04, 0x64,    0x74,   0x96,   0x8c,   0x57 /*0x4f*/ },  // 32 QAM   <=> qam=1
        { 0x08, 0x46,    0x43,   0x6a,   0x6a,   0x56 /*0x44*/ /*0x3c*/ },  // 64 QAM   <=> qam=2
        { 0x0c, 0x36,    0x34,   0x7e,   0x78,   0x52 /*0x4c*/ /*0x44*/ },  // 128 QAM  <=> qam=3
        { 0x10, 0x26,    0x23,   0x6c,   0x5c,   0x4a /*0x3c*/ /*0x34*/ },  // 256 QAM  <=> qam=4
        { 0x14, 0x78,    0x8c,   0x96,   0x78,   0x4c /*0x44*/ }   // 4 QAM    <=> qam=5
    };
  ///////////////////////////////////////////////////////
  /*value of ERAGCNYQ_THD optimized for adjacent signal*/
  ///////////////////////////////////////////////////////

    SEND_TRACEFCT3(DEBUG_WRITEQAM_ID, 0);

    // LOCKTHR
    if(psObject->systemFunc.SY_Write(psObject->uDemodHwAdd,
        TDA10023_LOCKTHR_IND, 1, &sTypeQAM[uMod].uLockthr) == False) return TM_ERR_IIC_ERR;

    // MSETH
    if(psObject->systemFunc.SY_Write(psObject->uDemodHwAdd,
        TDA10023_MSETH_IND, 1, &sTypeQAM[uMod].uMseth) == False) return TM_ERR_IIC_ERR;

    // AREF
    if(psObject->systemFunc.SY_Write(psObject->uDemodHwAdd,
        TDA10023_AREF_IND, 1, &sTypeQAM[uMod].uAref) == False) return TM_ERR_IIC_ERR;

    // AGCREFNYQ
    if(psObject->systemFunc.SY_Write(psObject->uDemodHwAdd,
        TDA10023_AGCREFNYQ_IND, 1, &sTypeQAM[uMod].uAgcRefNyq) == False) return TM_ERR_IIC_ERR;


    // ERAGCNYQ_THD
    if(psObject->systemFunc.SY_Write(psObject->uDemodHwAdd,
        TDA10023_ERAGCNYQ_THD_IND, 1, &sTypeQAM[uMod].uErAgcNyqThd) == False) return TM_ERR_IIC_ERR;

    if(psObject->sConfig.bModeDvbMcns)
    {
        // MCNS mode

        // GPR: program the modulation in QAM bits
        if(psObject->systemFunc.SY_WriteBit(
            psObject->uDemodHwAdd,
            TDA10023_GPR_IND, TDA10023_GPR_QAM_MSK, sTypeQAM[uMod].uQam) == False) return TM_ERR_IIC_ERR;

        // CTRL1: program the modulation in QAMMODE bit
        if(uMod == 2)
        {
            // 64 QAM
            if(psObject->systemFunc.SY_WriteBit(
                psObject->uDemodHwAdd,
                TDA10023_CTRL1_IND, TDA10023_CTRL1_QAMMODE_BIT, TDA10023_CTRL1_QAMMODE_BIT) == False) return TM_ERR_IIC_ERR;
      //write roll off
      if(psObject->systemFunc.SY_WriteBit(
                psObject->uDemodHwAdd,
                TDA10023_GAIN2_IND, TDA10023_ROLL_OFF_MSK, 0) == False) return TM_ERR_IIC_ERR;
         }
        else if(uMod == 4)
        {
            // 256 QAM
            if(psObject->systemFunc.SY_WriteBit(
                psObject->uDemodHwAdd,
                TDA10023_CTRL1_IND, TDA10023_CTRL1_QAMMODE_BIT, 0) == False) return TM_ERR_IIC_ERR;
      //write roll off
      if(psObject->systemFunc.SY_WriteBit(
                psObject->uDemodHwAdd,
                TDA10023_GAIN2_IND, TDA10023_ROLL_OFF_MSK, 1) == False) return TM_ERR_IIC_ERR;
    }

    }
    else
    {
        // DVB mode

        // GPR: program the modulation in QAM bits
        if(psObject->systemFunc.SY_WriteBit(
            psObject->uDemodHwAdd,
            TDA10023_GPR_IND, TDA10023_GPR_QAM_MSK, sTypeQAM[uMod].uQam) == False) return TM_ERR_IIC_ERR;
    }

    #ifdef BSL_DEBUG_BASIC
        SEND_TRACE(DEBUG_MODULATION_ID, uMod);
    #endif

    return TM_OK;
}

//-----------------------------------------------------------------------------
// FUNCTION:    Tda10023WriteSR
//
// DESCRIPTION: this function write the symbol rate
//
// RETURN:      TMBSL_ERR_DEMOD_BAD_UNIT_NUMBER
//              TMBSL_ERR_DEMOD_NOT_INITIALIZED
//              TMBSL_ERR_DEMOD_BAD_PARAMETER
//              TM_ERR_IIC_ERR
//              TM_OK
//
// NOTES:       TBD
//-----------------------------------------------------------------------------
//
tmErrorCode_t
Tda10023WriteSR (
    tm10023object_t   *psObject,  // I: Demod object
    UInt32            *puSR       // I: Symbol rate
)
{
    UInt32 puWrite[4];
    UInt32 uBDR, uBDRI, uSR, uNDec, uSFil;

    SEND_TRACEFCT3(DEBUG_WRITESR_ID, 0);


    uSR = *puSR;

    //------------------------------------------------------------
    // calculate the number of decimation and the antialias filter
    //------------------------------------------------------------
    if (uSR/10 < psObject->uSysClk/984)
    {
        uNDec = 3;
        uSFil = 1;
    }
    else if (uSR/10 < psObject->uSysClk/640)
    {
        uNDec = 3;
        uSFil = 0;
    }
    else if (uSR/10 < psObject->uSysClk/492)
    {
        uNDec = 2;
        uSFil = 1;
    }
    else if (uSR/10 < psObject->uSysClk/320)
    {
        uNDec = 2;
        uSFil = 0;
    }
    else if (uSR/10 < psObject->uSysClk/246)
    {
        uNDec = 1;
        uSFil = 1;
    }
    else if (uSR/10 < psObject->uSysClk/160)
    {
        uNDec = 1;
        uSFil = 0;
    }
    else if (uSR/10 < psObject->uSysClk/123)
    {
        uNDec = 0;
        uSFil = 1;
    }
    else
    {
        uNDec = 0;
        uSFil = 0;
    }

    // program SFIL
    if(psObject->systemFunc.SY_WriteBit (psObject->uDemodHwAdd, TDA10023_GAIN2_IND, TDA10023_GAIN2_SFIL_MSK, uSFil << 7) == False) return TM_ERR_IIC_ERR;

    // program NDEC
    if(psObject->systemFunc.SY_WriteBit (psObject->uDemodHwAdd, TDA10023_CLKCONF_IND, TDA10023_CLKCONF_NDEC_MSK, uNDec << 6) == False) return TM_ERR_IIC_ERR;

    //---------------------------------------
    // program the symbol frequency registers
    //---------------------------------------
    // calculate the inversion of the symbol frequency
    uBDRI   = psObject->uSysClk*16;
    uBDRI >>= uNDec;
    uBDRI  += *puSR/2;
    uBDRI  /= *puSR;
    if (uBDRI > 255)
    {
        uBDRI = 255;
    }

    // calculate the symbol rate
    {
#ifdef NO_FLOAT

        uBDR = Tda10023MulDiv32(1<<(24+uNDec), *puSR, psObject->uSysClk);

#else

        float fFreqSymb = (float)*puSR;
        float fSysClk = (float)psObject->uSysClk;
        float fResult;

        fResult  = (float)(1<<(24+uNDec));
        fResult /= fSysClk;
        fResult *= fFreqSymb;
        uBDR = (UInt32)fResult;

#endif
    }

    // program the value in register of the symbol rate
    puWrite[0] = (UInt8)(uBDR);
    puWrite[1] = (UInt8)(uBDR >> 8);
    puWrite[2] = (UInt8)(uBDR >> 16);
    puWrite[3] = (UInt8)uBDRI;
    if(psObject->systemFunc.SY_Write( psObject->uDemodHwAdd, TDA10023_BDRLSB_IND, 4, puWrite) == False) return TM_ERR_IIC_ERR;


    // return the value programmed
    {
#ifdef NO_FLOAT

        *puSR = Tda10023MulDiv32(uBDR, psObject->uSysClk, 1<<(24+uNDec));

#else

        float fBDR = (float)uBDR;
        float fSysClk = (float)psObject->uSysClk;
        float fResult;

        fResult  = fBDR*fSysClk;
        fResult /= (float)(1<<(24+uNDec));
        *puSR = (UInt32)fResult;

#endif
    }

    return TM_OK;
}

//-----------------------------------------------------------------------------
// Algorithms
//-----------------------------------------------------------------------------
//


//-----------------------------------------------------------------------------
// FUNCTION:    Tda10023WriteNextScan
//
// DESCRIPTION: this function will calculate and program the next RF frequency
//
// RETURN:      TM_OK: if the frequency has been incremented
//              False: the end of band is reached
//
// NOTES:       TBD
//-----------------------------------------------------------------------------
//
tmErrorCode_t
Tda10023WriteNextScan (
    tm10023object_t *psObject            // IO: Demod object
)
{
    UInt32 uRf, uSr, uRfStop;
    tmErrorCode_t ErrCode;

    SEND_TRACEFCT3(DEBUG_WRITENEXTSCAN_ID, 0);
  if (psObject->sApiFlags.iAutoQam )
  {
    tmErrorCode_t Error_Code;
    psObject->sCurrentChannel.eMOD = tmhalFEModulationQam64;
    Error_Code = Tda10023WriteQAM(psObject, 2);
    if(Error_Code != TM_OK) return(Error_Code);
  }

    psObject->lClkOffCst = 0;
    psObject->bStateClkOffset = 0;
    psObject->GainOK = False;

    // get current RF
    uRf = psObject->sCurrentChannel.uRF;

    // get the current symbol rate
    uSr = psObject->sCurrentChannel.uSR;

  uNbNoLock = 0;

  //=============
    // Simple Scan
    //=============
  if ( psObject->uNbSamples == 0)
  {
      // when the scanning starts, it must start from the real frequency
      // to prevent the demod to lock on it at the next step
      if (psObject->uSyncReg & TDA10023_STATUS_FEL_BIT)
      {
          Int32 lAFC;

          // the DVB roll off 115% of SR
          psObject->uScanStep = uSr * 115;
          psObject->uScanStep += 50;
          psObject->uScanStep /= 100;

          // calculate the starting frequency
          Tda10023ReadAFC(psObject, &lAFC);
          psObject->uScanStep = (UInt32)(lAFC + (Int32)psObject->uScanStep);
      }

    #ifdef BSL_SCANNING_BASIC
        SEND_TRACE(DEBUG_RFSTEP_ID, psObject->uScanStep);
    #endif
      // calculate the new frequency to apply
      uRf += psObject->uScanStep;
  }

  //=============
  // FastScan
  //=============
  else
  {
    UInt32 uIndex;
    UInt32 uFreqNextChannel;

    //Find index of current channel
    uIndex = psObject->sCurrentChannel.uRF - psObject->uStartFrequency - psObject->uBandwidth / 2;
    uIndex += psObject->uBandwidth / 2;
    uIndex /= psObject->uBandwidth;
    uFreqNextChannel = psObject->uStartFrequency + (uIndex+1)*psObject->uBandwidth;

    // If current channel is a potential channel, scan it completely.
    if (psObject->pPotentialChannel[uIndex])
    {
      if ((psObject->sCurrentChannel.uRF + psObject->uScanStep) < uFreqNextChannel)
      {
        uRf += psObject->uScanStep;
      }
      else
      {
        uIndex ++;
        uRf = psObject->uStartFrequency + psObject->uBandwidth * uIndex ;
        psObject->bFiltersGainSet = False;
      }

    }
    else
    {
      uIndex ++;
      // Find next channel that potentially contains a carrier
      while ( (psObject->pPotentialChannel[uIndex] != 1)
          && (uIndex < NB_MAX_CHANNEL) )
      {
        uIndex ++;
      }
      uRf = psObject->uStartFrequency + psObject->uBandwidth * uIndex ;
    }
  }


    // calculate the ending frequency regarding to the AFC max
    uRfStop  = uSr*(UInt32)((float)(psObject->uSWDynValue)/100);
    uRfStop += 50;
    uRfStop /= 100;
    uRfStop += psObject->uStopFrequency;


#if 0 //tao:TBD
    // test if the end of band is reached
    if (uRf > uRfStop)
    {
      // stop the scanning
        Tda10023FreeBuffers(psObject);
      return TM_FALSE;
    }
#endif

    // program the tuner
    ErrCode = Tda10023WriteRF(psObject, &uRf);
  if ( ErrCode != TM_OK)
    return ErrCode;

  // set current RF
    psObject->sCurrentChannel.uRF = uRf;

    // carry on the scanning
    return TM_OK;
}

//-----------------------------------------------------------------------------
// FUNCTION:    Tda10023_MainAlgo
//
// DESCRIPTION: Try to find a signal with the current configuration of the front-end
//
// RETURN:      tmhalFEManagerStatusCarrierOk        : a carrier was found
//              tmhalFEManagerStatusNoCarrier        : a carrier was not found
//              tmhalFEManagerStatusNotCompleted    : wait
//
// NOTES:       TBD
//-----------------------------------------------------------------------------
//
tmhalFEManagerStatus_t
Tda10023_MainAlgo(
    tm10023object_t *psObject,            //  I: Demod unit number
    UInt16            *pAlgoTimer            //  O: time to wait
)
{

  tmhalFEManagerStatus_t  status;
  UInt32 uByte;
  UInt32 uByteW;

    SEND_TRACEFCT3(DEBUG_MAINALGO_ID, 0);

    #ifdef BSL_DEBUG_BASIC
        SEND_TRACE(DEBUG_STATE_ID, psObject->bState);
    #endif


    // init the algo
    if ( psObject->bState == 0 )
    {
    if (psObject->sApiFlags.iScan)
      uByte = 0x93;//bit 7 and 6 are forced  (KAGCTUN and KAGCIF)
    else
#ifdef _CHINA_CABLE_
            uByte = 0x92;
#else
            uByte = 0x96;
#endif

        psObject->systemFunc.SY_Write( psObject->uDemodHwAdd,
            TDA10023_AGCCONF1_IND, 1, &uByte);

        // program the CARCONF
         psObject->systemFunc.SY_WriteBit( psObject->uDemodHwAdd,
            TDA10023_CARCONF_IND, TDA10023_CARCONF_CAR_C_MSK, 0x0c);

        // reset all chip
        Tda10023ResetAll(psObject);

        // next state
        psObject->bState++;
        *pAlgoTimer = Tda10023_AlgoCalcTimer(psObject, 600);
        return tmhalFEManagerStatusNotCompleted;
    }

    // waiting for AGC convergence
    if (psObject->bState == 1)
    {
         // set the AGC time constant
     // set the KAGCIF and KAGCTUN to tracking mode
    if (psObject->sApiFlags.iScan)
      uByte = 0x9B;//bit 7 and 6 are forced  (KAGCTUN and KAGCIF)
    else
#ifdef _CHINA_CABLE_
            uByte = 0x92;
#else
            uByte = 0x9E;
#endif


        if(psObject->systemFunc.SY_Write(psObject->uDemodHwAdd,
            TDA10023_AGCCONF1_IND, 1, &uByte) == False) return TM_ERR_IIC_ERR;
        // next state
        psObject->bState++;
        *pAlgoTimer = Tda10023_AlgoCalcTimer(psObject, 10*psObject->uSWDynValue*16384/psObject->uSWStepValue);
        return tmhalFEManagerStatusNotCompleted;
    }

    // test if there is a signal
    if (psObject->bState == 2)
    {

    UInt32 uAgcRF;

    // read the AGC RF value
        psObject->systemFunc.SY_Read(psObject->uDemodHwAdd,  TDA10023_AGCTUN_IND, 1, &uAgcRF);

#ifdef DEBUG_SCAN
    {
/*      Int32 lRCentralCoef, lICentralCoef;
      UInt32 puReadCoef[2];

      if(psObject->systemFunc.SY_Read( psObject->uDemodHwAdd,
        TDA10023_REQCO_CENTRALCOEF_IND, 2, puReadCoef) == False) return TM_ERR_IIC_ERR;
      lRCentralCoef = puReadCoef[0] << 3 | puReadCoef[1] >> 5;
      if (lRCentralCoef & 0x400)
        lRCentralCoef |= 0xFFFFF800;

      // read the imaginary part of the central coef of the equalizer
      if(psObject->systemFunc.SY_Read( psObject->uDemodHwAdd,
        TDA10023_IEQCO_CENTRALCOEF_IND, 2, puReadCoef) == False) return TM_ERR_IIC_ERR;
      lICentralCoef = puReadCoef[0] << 3 | puReadCoef[1] >> 5;
      if (lICentralCoef & 0x400)
        lICentralCoef |= 0xFFFFF800;

      //pFile = fopen("C:\\Test10023\\traceScan.txt","a");
      sprintf(strTmp,"\n \n ****************************************\n Start looking for carrier at RF  %d\n\n",psObject->sCurrentChannel.uRF);
      sprintf(strTmp2,"bState = %d ***** AGCRF = %d\n",psObject->bState, uAgcRF);
      strcat(strTmp,strTmp2);
      sprintf(strTmp2,"bState = %d ***** equalizer centrel coef real part = %d\n",psObject->bState, lRCentralCoef);
      strcat(strTmp,strTmp2);
      sprintf(strTmp2,"bState = %d ***** equalizer centrel coef imaginary part = %d\n",psObject->bState, lICentralCoef);
      strcat(strTmp,strTmp2);
      fprintf(pFile, strTmp);
      if (uAgcRF ==255)
        fprintf(pFile,"\t\t\t returning statusNoCarrier \n"); */
      //fclose(pFile);
    }
#endif

#if 0
    if ((psObject->sCurrentChannel.uSR >= 3000000)
      && ((psObject->sConfig.uBoard & 0xFFFF0000) != OM5755_BOARD_DEF)
      && (psObject->sConfig.uBoard != CU1216_BOARD_DEF)
      && (psObject->sConfig.uBoard != OM5795_BOARD_DEF)
      )
    {
      if (uAgcRF == 255)
      {
        psObject->QuickFinding = True;
        return tmhalFEManagerStatusNoCarrier;
      }
      else if ((psObject->QuickFinding == True)
            && (psObject->sApiFlags.iScan)
            && (psObject->sCurrentChannel.uRF > psObject->uStartFrequency)
                        && (psObject->uNbSamples == 0))
      {
        // uScanStep/10000 of the SR
        psObject->uScanStep = psObject->sCurrentChannel.uSR*70;
        psObject->uScanStep /= 100;
        psObject->sCurrentChannel.uRF += (UInt32)(psObject->uScanStep-psObject->sCurrentChannel.uSR*((float)(psObject->uSWDynValue)/10000));
        psObject->QuickFinding = False;
        if(Tda10023WriteRF(psObject,&psObject->sCurrentChannel.uRF) == TM_ERR_IIC_ERR) return TM_ERR_IIC_ERR;
          *pAlgoTimer = Tda10023_AlgoCalcTimer(psObject,10*psObject->uSWDynValue*16384/psObject->uSWStepValue);
            return tmhalFEManagerStatusNotCompleted;
      }
      else if ((psObject->sCurrentChannel.uRF == psObject->uStartFrequency))
        psObject->QuickFinding = False;
    }

#endif

        // next state
        psObject->bState++;
    }

    // find best gain
    if (psObject->bState == 3)
    {
    if ( psObject->eBandType  != tmhalFEBandTypeSECAM_L )
    {
      status = Tda10023_AlgoGain(psObject, pAlgoTimer);
    }
    else if (psObject->GainOK != True)
    {
      Tda10023ManageBandTypeGain(psObject,&status);
      psObject->bFiltersGainSet = True;
      psObject->GainOK = True;
    }
        else
            status = tmhalFEManagerStatusNotCompleted;
#ifdef DEBUG_SCAN
/*    {
      //pFile = fopen("C:\\Test10023\\traceScan.txt","a");
      sprintf(strTmp,"bState = %d ***** Check algo gain. Gain = %d\n",psObject->bState,psObject->bGainAlgo);
      if (status == tmhalFEManagerStatusNoCarrier)
        sprintf(strTmp2,"\t\t\t returning statusNoCarrier \n");
      else if (status == tmhalFEManagerStatusNotCompleted)
        sprintf(strTmp2,"\t\t\t returning statusNotCompleted \n");
      else if (status == tmhalFEManagerStatusCarrierOk )
        sprintf(strTmp2,"\t\t\t returning statusCarrierOk \n");
      strcat(strTmp,strTmp2);
      fprintf(pFile,strTmp);
      //fclose(pFile);
    }*/
#else
if (((psObject->sConfig.uBoard & 0xFFFF0000) == OM5755_BOARD_DEF)
    || (psObject->sConfig.uBoard == CU1216_BOARD_DEF)
    || (psObject->sConfig.uBoard == OM5795_BOARD_DEF))
{
    #ifndef _CHINA_CABLE_
                uByte = 0x9A;
                if(psObject->systemFunc.SY_Write(psObject->uDemodHwAdd,
                TDA10023_AGCCONF1_IND, 1, &uByte) == False) return TM_ERR_IIC_ERR;
    #endif

          internal10023Wait(100);

    #ifndef _CHINA_CABLE_
                if (psObject->sApiFlags.iScan)
              uByte = 0x9B;
                else
                    uByte = 0x9E;
                if(psObject->systemFunc.SY_Write(psObject->uDemodHwAdd,
                TDA10023_AGCCONF1_IND, 1, &uByte) == False) return TM_ERR_IIC_ERR;
    #endif
}
else
{
    internal10023Wait(100);
}
#endif

    // test the algo in used
      switch (status)
      {
      case tmhalFEManagerStatusNoCarrier:
        return tmhalFEManagerStatusNoCarrier;
      case tmhalFEManagerStatusNotCompleted:
            case tmhalFEManagerStatusCarrierOk:
                // next state
                psObject->bState++;
        return tmhalFEManagerStatusNotCompleted;
      }
    }

    // wait for frame lock
    if (psObject->bState == 4)
  {
        *pAlgoTimer = Tda10023_AlgoCalcTimer(psObject,/*10000*/10*psObject->uSWDynValue*16384/psObject->uSWStepValue/*wait time for frame sync*/);
    psObject->bState ++;
    return tmhalFEManagerStatusNotCompleted;
  }

  if (psObject->bState == 5)
  {

    UInt32 uCounter;

       if (psObject->sConfig.bModeDvbMcns)
     {
            // MCNS mode
            // read STATUS_MCNS register (10 times to avoid false lock)
            uCounter = 0;
            do
            {
                if(psObject->systemFunc.SY_Read(
                    psObject->uDemodHwAdd, TDA10023_STATUS_MCNS_IND, 1, &(psObject->uSyncReg)) == False) return TM_ERR_IIC_ERR;

                SEND_TRACE(DEBUG_FEL_ID, psObject->uSyncReg & TDA10023_STATUS_MCNS_MPEGLCK_BIT);

                internal10023Wait(50);

                uCounter++;
            }while((!(psObject->uSyncReg & TDA10023_STATUS_MCNS_MPEGLCK_BIT)) && (uCounter < 10));


            if(psObject->uSyncReg & TDA10023_STATUS_MCNS_MPEGLCK_BIT)
            {
                psObject->bState ++;
        return  tmhalFEManagerStatusNotCompleted;
            }

        }
        else
        {
            // DVB mode
            // read STATUS register (10 times to avoid false lock)
            uCounter = 0;

            do
            {
                if(psObject->systemFunc.SY_Read(
                    psObject->uDemodHwAdd, TDA10023_STATUS_IND, 1, &psObject->uSyncReg) == False) return TM_ERR_IIC_ERR;

                SEND_TRACE(DEBUG_FEL_ID, psObject->uSyncReg & TDA10023_STATUS_FSYNC_BIT);

                uCounter++;
            }while(((psObject->uSyncReg & TDA10023_STATUS_FSYNC_BIT)) && (uCounter < 10));


            if(psObject->uSyncReg & TDA10023_STATUS_FSYNC_BIT)
            {
          psObject->bState ++;

          return  tmhalFEManagerStatusNotCompleted;

            }

        }

    if (psObject->sApiFlags.iAutoQam)
      status = Tda10023_AlgoMod(psObject);

    if (psObject->sApiFlags.iAutoQam && ( status == tmhalFEManagerStatusNotCompleted))
        {
            // re-start all algo
          psObject->bState = 3;

      if(Tda10023_MainAlgo(psObject, pAlgoTimer) == TM_ERR_IIC_ERR) return TM_ERR_IIC_ERR;
            return tmhalFEManagerStatusNotCompleted;
    }

            if (psObject->sConfig.bClkOffsetRange && (Tda10023_AlgoClkOffset(psObject) == tmhalFEManagerStatusNotCompleted))
            {
          // init modulation algo if needed
          if (psObject->sApiFlags.iAutoQam) psObject->sCurrentChannel.eMOD = tmhalFEModulationQam64;


            // reset all chip
            Tda10023ResetAll(psObject);
            // re-start algo from state 4
      psObject->bState = 4;
          if(Tda10023_MainAlgo(psObject, pAlgoTimer) == TM_ERR_IIC_ERR) return TM_ERR_IIC_ERR;

                return tmhalFEManagerStatusNotCompleted;
            }

    return tmhalFEManagerStatusNoCarrier;
    }

  if (psObject->bState == 6)
  {
    // test if frame sync and DVB
    if ((psObject->uSyncReg & TDA10023_STATUS_FSYNC_BIT)||
      (psObject->uSyncReg & TDA10023_STATUS_MCNS_MPEGLCK_BIT))
        {
            // Adjust the AFC
            Int32    lAFC;
      UInt32 uByteIT,uByteTestUncor,uByteUncor;
      UInt32 puBytes[4];

      int j = 0;
      uByteTestUncor = 0;
      uByteUncor = 0;

            #ifdef BSL_DEBUG_BASIC
                SEND_TRACE(DEBUG_FSYNC_ID, 0);
            #endif

#if 0
      /****************************************************/
      /*BUG CORRECTION FOR STUFFING ISSUE IN MCNS     */
      /****************************************************/
      if((psObject->sConfig.bModeDvbMcns) && (!(psObject->sApiFlags.iScan)))
      {
        if(psObject->systemFunc.SY_Read(
            psObject->uDemodHwAdd,
            TDA10023_CPT_RSB_UNCOR1_IND,    4, puBytes) == False) return TM_ERR_IIC_ERR;

        uByteTestUncor = (puBytes[3]<<24) | (puBytes[2]<<16) | (puBytes[1]<<8) | puBytes[0];

        psObject->systemFunc.SY_Read(
            psObject->uDemodHwAdd,
            TDA10023_ITSTAT1_IND,    1, &uByteIT);

        // wait 1ms
        internal10023Wait(1);

        psObject->systemFunc.SY_Read(
            psObject->uDemodHwAdd,
            TDA10023_ITSTAT1_IND,    1, &uByteIT);

        if(psObject->systemFunc.SY_Read(
            psObject->uDemodHwAdd,
            TDA10023_CPT_RSB_UNCOR1_IND,    4, puBytes) == False) return TM_ERR_IIC_ERR;

        uByteUncor = (puBytes[3]<<24) | (puBytes[2]<<16) | (puBytes[1]<<8) | puBytes[0];

        if ((uByteTestUncor == uByteUncor) && ((uByteIT & 0x04) != 0x00))
        {
          do
          {

          uByteW = 0xFB;
          if (psObject->systemFunc.SY_Write(
          psObject->uDemodHwAdd,
          TDA10023_RESET_IND , 1, &uByteW) == False)
          return TM_ERR_IIC_ERR;

          // wait 100ms
          internal10023Wait(100);

          if(psObject->systemFunc.SY_Read(
            psObject->uDemodHwAdd,
            TDA10023_CPT_RSB_UNCOR1_IND,    4, puBytes) == False) return TM_ERR_IIC_ERR;

          uByteTestUncor = (puBytes[3]<<24) | (puBytes[2]<<16) | (puBytes[1]<<8) | puBytes[0];

          psObject->systemFunc.SY_Read(
            psObject->uDemodHwAdd,
            TDA10023_ITSTAT1_IND,    1, &uByteIT);

          // wait 1ms
          internal10023Wait(1);

          psObject->systemFunc.SY_Read(
            psObject->uDemodHwAdd,
            TDA10023_ITSTAT1_IND,    1, &uByteIT);


          if(psObject->systemFunc.SY_Read(
            psObject->uDemodHwAdd,
            TDA10023_CPT_RSB_UNCOR1_IND,    4, puBytes) == False) return TM_ERR_IIC_ERR;

          uByteUncor = (puBytes[3]<<24) | (puBytes[2]<<16) | (puBytes[1]<<8) | puBytes[0];

          j++;


          } while ((uByteUncor == uByteTestUncor) && ((uByteIT & 0x04) != 0x00) && (j<11));
        }

        psObject->systemFunc.SY_Read(
              psObject->uDemodHwAdd,
              TDA10023_STATUS_MCNS_IND,    1, &uByteW);

        if (!(uByteW & TDA10023_STATUS_MCNS_MPEGLCK_BIT))
        {
          return tmhalFEManagerStatusNoCarrier;
        }

      }
#endif



      /****************************************************/
            // next state anyway
            psObject->bState = 7;

            // read AFC
            if(Tda10023ReadAFC(psObject, &lAFC) == TM_ERR_IIC_ERR) return TM_ERR_IIC_ERR;

            if ((lAFC) && (psObject->sApiFlags.iScan))
            {
        // change the frequency
        psObject->sCurrentChannel.uRF += (Int32)lAFC;

        if (abs(psObject->uRFPrevious-psObject->sCurrentChannel.uRF) < 100000)
        {
          psObject->sCurrentChannel.uRF -= (Int32)lAFC;
          return tmhalFEManagerStatusNoCarrier;
        }

        psObject->uRFPrevious = psObject->sCurrentChannel.uRF;

                // program frequency
                if(Tda10023WriteRF(psObject,&psObject->sCurrentChannel.uRF) == TM_ERR_IIC_ERR) return TM_ERR_IIC_ERR;
        *pAlgoTimer = Tda10023_AlgoCalcTimer(psObject,20*psObject->uSWDynValue*16384/psObject->uSWStepValue);
      return tmhalFEManagerStatusNotCompleted;
            }
    *pAlgoTimer = Tda10023_AlgoCalcTimer(psObject,10*psObject->uSWDynValue*16384/psObject->uSWStepValue);
    return tmhalFEManagerStatusNotCompleted;
        }
  }

  if (psObject->bState == 7)
  {
    if ((psObject->uSyncReg & TDA10023_STATUS_FSYNC_BIT)||
      (psObject->uSyncReg & TDA10023_STATUS_MCNS_MPEGLCK_BIT))

      return tmhalFEManagerStatusCarrierOk;
    }

    // For compiler
    return tmhalFEManagerStatusMax;;
}

//-----------------------------------------------------------------------------
// FUNCTION:    Tda10023_AlgoGain
//
// DESCRIPTION: Try to find a the best gain
//
// RETURN:      tmhalFEManagerStatusCarrierOk        : a carrier was found
//              tmhalFEManagerStatusNoCarrier        : a carrier was not found
//              tmhalFEManagerStatusNotCompleted    : wait
//
// NOTES:       TBD
//-----------------------------------------------------------------------------
//
tmhalFEManagerStatus_t
Tda10023_AlgoGain(
    tm10023object_t *psObject,            //  I: Demod unit number
    UInt16            *pAlgoTimer            //  O: time to wait
)
{

    Int32 lRCentralCoef, lICentralCoef;
    UInt32 puReadCoef[2];

    // read the real part of the central coef of the equalizer
    psObject->systemFunc.SY_Read( psObject->uDemodHwAdd,
        TDA10023_REQCO_CENTRALCOEF_IND, 2, puReadCoef);
    lRCentralCoef = puReadCoef[0] << 3 | puReadCoef[1] >> 5;
    if (lRCentralCoef & 0x400)
        lRCentralCoef |= 0xFFFFF800;

    // lRCentralCoef^2
    lRCentralCoef *= lRCentralCoef;

    // read the imaginary part of the central coef of the equalizer
    psObject->systemFunc.SY_Read( psObject->uDemodHwAdd,
        TDA10023_IEQCO_CENTRALCOEF_IND, 2, puReadCoef);
    lICentralCoef = puReadCoef[0] << 3 | puReadCoef[1] >> 5;
    if (lICentralCoef & 0x400)
        lICentralCoef |= 0xFFFFF800;

    // lICentralCoef^2
    lICentralCoef *= lICentralCoef;

    #ifdef BSL_DEBUG_BASIC
        SEND_TRACE(DEBUG_CENTRALCOEF_ID, lRCentralCoef + lICentralCoef);
    #endif

    // test the module
    if ((lRCentralCoef + lICentralCoef) > 700*700)
  {
        UInt8 bGainMax;
    UInt32 bGainNyq;

        // don't test all gains in scanning
        if (psObject->sApiFlags.iScan)
            bGainMax = 5;
        else
            bGainMax = 7;

    // Read GNYQ
    if( psObject->systemFunc.SY_Read( psObject->uDemodHwAdd,
                TDA10023_GAIN1_IND, 1, puReadCoef) == False) return TM_ERR_IIC_ERR;
    bGainNyq= puReadCoef[0] >> 5;

        // test if gain max is reached
        if (bGainNyq >= bGainMax)
            return tmhalFEManagerStatusNoCarrier;

//CB 151205
#ifdef DEBUG_SCAN
    {
      //pFile = fopen("C:\\Test10023\\traceScan.txt","a");
//      fprintf(pFile,"Algogain ***** Gain = %d\n",bGainNyq);
      //fclose (pFile);
    }
#endif

      #ifdef BSL_DEBUG_BASIC
          SEND_TRACE(DEBUG_GAIN_ID, psObject->bGainAlgo);
        #endif
//End CB
        // wait for synchro
       *pAlgoTimer = Tda10023_AlgoCalcTimer(psObject, 10000);
        return tmhalFEManagerStatusNotCompleted;
    }

    return tmhalFEManagerStatusCarrierOk;
}

//-----------------------------------------------------------------------------
// FUNCTION:    Tda10023_AlgoMod
//
// DESCRIPTION: algorithm for auto modulation : 64->256->16->32->128->4
//
// RETURN:      tmhalFEManagerStatusCarrierOk       : a carrier was found
//              tmhalFEManagerStatusNoCarrier       : a carrier was not found
//              tmhalFEManagerStatusNotCompleted    : wait
//
// NOTES:
//-----------------------------------------------------------------------------
//
tmhalFEManagerStatus_t
Tda10023_AlgoMod(
    tm10023object_t *psObject            //  I: Demod unit number
)
{

    UInt32 uMod;

    // program new modulation
    if(psObject->sConfig.bModeDvbMcns)
    {
        // MCNS mode
        switch (psObject->sCurrentChannel.eMOD)
        {
        case tmhalFEModulationQam64:
            psObject->sCurrentChannel.eMOD = tmhalFEModulationQam256;
            uMod = 4;
            break;

        case tmhalFEModulationQam256:
            psObject->sCurrentChannel.eMOD = tmhalFEModulationQam64;
            uMod = 2;
            break;

        default:
            return tmhalFEManagerStatusNoCarrier;
        }
    }
    else if (!psObject->sApiFlags.iScan)
    {
        // DVB mode
        switch (psObject->sCurrentChannel.eMOD)
        {
        case tmhalFEModulationQam64:
            psObject->sCurrentChannel.eMOD = tmhalFEModulationQam256;
            uMod = 4;
            break;

        case tmhalFEModulationQam256:
            psObject->sCurrentChannel.eMOD = tmhalFEModulationQam16;
            uMod = 0;
            break;

        case tmhalFEModulationQam16:
            psObject->sCurrentChannel.eMOD = tmhalFEModulationQam32;
            uMod = 1;
            break;

        case tmhalFEModulationQam32:
            psObject->sCurrentChannel.eMOD = tmhalFEModulationQam128;
            uMod = 3;
            break;

        case tmhalFEModulationQam128:
            psObject->sCurrentChannel.eMOD = tmhalFEModulationQam4;
            uMod = 5;
            break;

        case tmhalFEModulationQam4:
            psObject->sCurrentChannel.eMOD = tmhalFEModulationQam64;
            uMod = 2;
            break;

        default:
            return tmhalFEManagerStatusNoCarrier;
        }
    }
  else if (psObject->sApiFlags.iScan) //no need to find 4,16,32 QAM modulation for the moment
  {
    // DVB mode
        switch (psObject->sCurrentChannel.eMOD)
        {
        case tmhalFEModulationQam64:
            psObject->sCurrentChannel.eMOD = tmhalFEModulationQam256;
            uMod = 4;
            break;

        case tmhalFEModulationQam256:
            psObject->sCurrentChannel.eMOD = tmhalFEModulationQam128;
            uMod = 3;
            break;

        case tmhalFEModulationQam128:
            psObject->sCurrentChannel.eMOD = tmhalFEModulationQam64;
            uMod = 2;
            break;

        default:
            return tmhalFEManagerStatusNoCarrier;
        }
  }

    // write new QAM
    Tda10023WriteQAM(psObject, uMod);

    //-------------------------------------------
    // Calculate new gain - skipped always equals
    //-------------------------------------------
    // newgain = oldgain*sqrt(arefnew/arefold)

    // if 64qam the algorithm is completed
    if (2 == uMod)
  {
        return tmhalFEManagerStatusNoCarrier;
  }
    else
        return tmhalFEManagerStatusNotCompleted;

    // For compiler
    // return True;
}

//-----------------------------------------------------------------------------
// FUNCTION:    Tda10023_AlgoClkOffset
//
// DESCRIPTION: algorithm to increase the symbol rate range up to +/-2000ppm
//
// RETURN:      tmhalFEManagerStatusCarrierOk      : a carrier was found
//              tmhalFEManagerStatusNoCarrier      : a carrier was not found
//              tmhalFEManagerStatusNotCompleted   : wait
//
// NOTES:       TBD
//-----------------------------------------------------------------------------
//
tmhalFEManagerStatus_t
Tda10023_AlgoClkOffset(
    tm10023object_t *psObject            //  I: Demod unit number
)
{

    UInt32 uSrOffset, uNewSr;

    // calculate the offset +-400ppm - assumed +/-480ppm for DYN
    uSrOffset = psObject->sCurrentChannel.uSR*40/100000;

    // set the offset
    switch (psObject->bStateClkOffset)
    {
    case 0:
        psObject->lClkOffCst = -2*400;
        uNewSr = psObject->sCurrentChannel.uSR - 2*uSrOffset;
        break;

    case 1:
        psObject->lClkOffCst = +2*400;
        uNewSr = psObject->sCurrentChannel.uSR + 2*uSrOffset;
        break;

    case 2:
        psObject->lClkOffCst = -4*400;
        uNewSr = psObject->sCurrentChannel.uSR - 4*uSrOffset;
        break;

    case 3:
        psObject->lClkOffCst = +4*400;
        uNewSr = psObject->sCurrentChannel.uSR + 4*uSrOffset;
        break;

    default:
        psObject->lClkOffCst = 0;
        psObject->bStateClkOffset = 0;
        uNewSr = psObject->sCurrentChannel.uSR;
        Tda10023WriteSR (psObject, &uNewSr);
        return tmhalFEManagerStatusNoCarrier;
    }

    // write new SR
    if(Tda10023WriteSR (psObject, &uNewSr) == TM_ERR_IIC_ERR) return TM_ERR_IIC_ERR;
    psObject->bStateClkOffset++;

    return tmhalFEManagerStatusNotCompleted;

}


//-----------------------------------------------------------------------------
// FUNCTION:    Tda10023ResetDeltaF:
//
// DESCRIPTION: Reset DeltaF
//
// RETURN:      TMBSL_ERR_DEMOD_BAD_UNIT_NUMBER
//              TMBSL_ERR_DEMOD_NOT_INITIALIZED
//              TM_OK
//
// NOTES:
//-----------------------------------------------------------------------------
//
tmErrorCode_t
Tda10023ResetDeltaF(
    tm10023object_t *psObject            //  I: Demod unit number
    )
{
    UInt32 puByte[3];
    Int32 lDeltaF;

    //----------------------
    // Implementation
    //----------------------
    // set ALGOD and deltaF
    if(psObject->sConfig.bFsampling)
    {
        // FSAMPLING = 1 - high sampling clock
        // SACLK = Sysclk  (SACLK max = 72MHz)
        lDeltaF  = (Int32)(psObject->sConfig.uTUN_IF/1000);
        lDeltaF *= 32768;                                   // 32768 = 2^20/32
        lDeltaF += (Int32)(psObject->uSysClk/500);
        lDeltaF /= (Int32)(psObject->uSysClk/1000);
        lDeltaF -= 53248;                                   // 53248 = (2^20/32) * 13/8
    }
    else
    {
        // FSAMPLING = 0 - low sampling clock
        // SACLK = Sysclk/2 (SACLK max = 36MHz)
        lDeltaF  = (Int32)(psObject->sConfig.uTUN_IF/1000);
        lDeltaF *= 32768;                                   // 32768 = 2^20/32
        lDeltaF += (Int32)(psObject->uSysClk/1000);
        lDeltaF /= (Int32)(psObject->uSysClk/2000);
        lDeltaF -= 40960;                                   // 53248 = (2^20/32) * 5/4
    }

    puByte[0] = (UInt8)lDeltaF;
    puByte[1] = (UInt8)(((lDeltaF>>8) & 0x7F) | TDA10023_DELTAF_MSB_ALGOD_BIT);
    psObject->systemFunc.SY_Write(psObject->uDemodHwAdd, TDA10023_DELTAF_LSB_IND, 2, puByte);

    return TM_OK;
}


//-----------------------------------------------------------------------------
// FUNCTION:    Tda10023ManageBandType:
//
// DESCRIPTION: In case of peculiar band type such as SECAM-L, manage filters
//        gain to reduce deterioration due to adjacent channels
//
// RETURN:      TMBSL_ERR_DEMOD_BAD_UNIT_NUMBER
//              TMBSL_ERR_DEMOD_NOT_INITIALIZED
//              TM_OK
//
// NOTES:
//-----------------------------------------------------------------------------
//
tmErrorCode_t
Tda10023ManageBandType(
  tm10023object_t *psObject            //  I: Demod unit number
    )
{
  UInt32  uValue,uByte;
  tmErrorCode_t Error_Code;
  tmhalFEManagerStatus_t Status;

  uValue = psObject->eBandType;

  // Second possible algo
  if ( uValue == tmhalFEBandTypeSECAM_L )
  {
    // set POSAGC to 0
    if(psObject->systemFunc.SY_Read(psObject->uDemodHwAdd, TDA10023_AGCCONF2_IND, 1, &uByte) == False) return TM_ERR_IIC_ERR;
    uByte &= 0xdf ;  // set bit 5 to 0
    if(psObject->systemFunc.SY_Write(psObject->uDemodHwAdd, TDA10023_AGCCONF2_IND, 1, &uByte) == False) return TM_ERR_IIC_ERR;

      // set AUTOGNYQ to 0
    if(psObject->systemFunc.SY_Read(psObject->uDemodHwAdd, TDA10023_GAIN1_IND, 1, &uByte) == False) return TM_ERR_IIC_ERR;
    uByte &= 0x7f;  // set bit7 to 0
    if(psObject->systemFunc.SY_Write(psObject->uDemodHwAdd, TDA10023_GAIN1_IND, 1, &uByte) == False) return TM_ERR_IIC_ERR;

      // set register GAIN1 to  0
    if(psObject->systemFunc.SY_Read(psObject->uDemodHwAdd, TDA10023_GAIN1_IND, 1, &uByte) == False) return TM_ERR_IIC_ERR;
    uByte &= 0xFB;   // set bit2 to 0
    if(psObject->systemFunc.SY_Write(psObject->uDemodHwAdd, TDA10023_GAIN1_IND, 1, &uByte) == False) return TM_ERR_IIC_ERR;

    // set register  GAIN2 to 0 and register GAIN3 to 0
    if(psObject->systemFunc.SY_Read(psObject->uDemodHwAdd, TDA10023_CLKCONF_IND, 1, &uByte) == False) return TM_ERR_IIC_ERR;
    uByte &= 0xcf;  // set bit5 to 0
    if(psObject->systemFunc.SY_Write(psObject->uDemodHwAdd, TDA10023_CLKCONF_IND,1, &uByte) == False) return TM_ERR_IIC_ERR;

    // set register GAAF to 1
    if(psObject->systemFunc.SY_Read(psObject->uDemodHwAdd, TDA10023_GAIN2_IND, 1, &uByte) == False) return TM_ERR_IIC_ERR;
    uByte &= 0x8f;  // set bits6,5,4 to 0
    if(psObject->systemFunc.SY_Write(psObject->uDemodHwAdd, TDA10023_GAIN2_IND,1, &uByte) == False) return TM_ERR_IIC_ERR;

      Error_Code = Tda10023ManageBandTypeGain(psObject,&Status);
    if(Error_Code != TM_OK) return(Error_Code);

  } // SECAM_L
  else
  {
    // set POSAGC to 1
    if(psObject->systemFunc.SY_Read(psObject->uDemodHwAdd, TDA10023_AGCCONF2_IND, 1, &uByte) == False) return TM_ERR_IIC_ERR;
    uByte |= 0x20 ;  // set bit 5 to 1
    if(psObject->systemFunc.SY_Write(psObject->uDemodHwAdd, TDA10023_AGCCONF2_IND, 1, &uByte) == False) return TM_ERR_IIC_ERR;

    // set the AGCREF to 0x50
//    uByte = TDA10023_AGCREF_DEF;
//    if(psObject->systemFunc.SY_Write(psObject->uDemodHwAdd, TDA10023_AGCREF_IND, 1, &uByte) == False) return TM_ERR_IIC_ERR;

      // set AUTOGNYQ to 1
    if(psObject->systemFunc.SY_Read(psObject->uDemodHwAdd, TDA10023_GAIN1_IND, 1, &uByte) == False) return TM_ERR_IIC_ERR;
    uByte |= 0x80;  // set bit7 to 1
    if(psObject->systemFunc.SY_Write(psObject->uDemodHwAdd, TDA10023_GAIN1_IND, 1, &uByte) == False) return TM_ERR_IIC_ERR;
  }

  return TM_OK;
}

//-----------------------------------------------------------------------------
// FUNCTION:    Tda10023ManageBandTypeGain:
//
// DESCRIPTION: Set Nyquist filter gain according to saturation counter
//
// RETURN:      TMBSL_ERR_DEMOD_BAD_UNIT_NUMBER
//              TMBSL_ERR_DEMOD_NOT_INITIALIZED
//              TM_OK
//
// NOTES:
//-----------------------------------------------------------------------------
//
tmErrorCode_t
Tda10023ManageBandTypeGain(
  tm10023object_t *psObject,            //  I: Demod unit number
  tmhalFEManagerStatus_t *Status
    )
{
  UInt32  uByte, uByteSat[7];
  Int8  i;
  UInt32  uSATADC, uHALFADC, uSATDEC1, uSATDEC2, uSATDEC3, uSATAAF, uSATNYQ, uSATADC_2, uHALFADC_2, uSATDEC1_2;
  Int8 bGainMax,bGainMin;

  *Status = tmhalFEManagerStatusCarrierOk;
  // don't test all gains in scanning
    if (psObject->sApiFlags.iScan)
  {
    bGainMin = 3;
        bGainMax = 4;
  }
    else
  {
    bGainMin = 2;
        bGainMax = 6;
  }
  if (psObject->sCurrentChannel.uSR < 3800000)
    bGainMin = 0;

  if(psObject->systemFunc.SY_Read(psObject->uDemodHwAdd, TDA10023_GAIN1_IND, 1, &uByte) == False) return TM_ERR_IIC_ERR;
  uByte &= 0x8f;
  uByte |= (bGainMin<<4);
  if(psObject->systemFunc.SY_Write(psObject->uDemodHwAdd, TDA10023_GAIN1_IND,1, &uByte) == False) return TM_ERR_IIC_ERR;

  //Time to refresh sat register (s) = Nb of samples selected in SSAT register / Sr
  //Value in function Tda10023InitTick must be in ms
  internal10023Wait((UInt16)(1000*2*(psObject->uNbSamplesSSAT)/(psObject->sCurrentChannel.uSR)));

  // read saturation counters
  if(psObject->systemFunc.SY_Read(psObject->uDemodHwAdd, TDA10023_SATNYQ_IND, 7, uByteSat) == False) return TM_ERR_IIC_ERR;
  uSATADC = uByteSat[1];
  uHALFADC = uByteSat[2];
  uSATDEC1 = uByteSat[3];
  uSATDEC2 = uByteSat[4];
  uSATDEC3 = uByteSat[5];
  uSATAAF = uByteSat[6];
  uSATNYQ = uByteSat[0];

  //Time to refresh sat register = Nb of samples selected in SSAT register / Sr
  internal10023Wait((UInt16)(1000*2*(psObject->uNbSamplesSSAT)/(psObject->sCurrentChannel.uSR)));

  // read again saturation counters
  if(psObject->systemFunc.SY_Read(psObject->uDemodHwAdd, TDA10023_SATNYQ_IND, 4, uByteSat) == False) return TM_ERR_IIC_ERR;
  uSATADC_2 = uByteSat[1];
  uHALFADC_2 = uByteSat[2];
  uSATDEC1_2 = uByteSat[3];

  i = bGainMin+1;

  while ((i <= bGainMax) && ((uSATDEC1_2 > 1) || (uSATADC_2 > 1) || (uHALFADC_2 == 0) || (uSATADC > 1) || (uHALFADC == 0) || (uSATDEC1 > 1) || (uSATDEC2 > 1) || (uSATDEC3 > 1) || (uSATAAF > 1) || (uSATNYQ > 1)))
  {
    // increase NYG gain
    if(psObject->systemFunc.SY_Read(psObject->uDemodHwAdd, TDA10023_GAIN1_IND, 1, &uByte) == False) return TM_ERR_IIC_ERR;
    uByte &= 0x8f;
    uByte |= (i<<4);
    if(psObject->systemFunc.SY_Write(psObject->uDemodHwAdd, TDA10023_GAIN1_IND,1, &uByte) == False) return TM_ERR_IIC_ERR;

    //Time to refresh sat register = Nb of samples selected in SSAT register / Sr
    internal10023Wait((UInt16)(1000*2*(psObject->uNbSamplesSSAT)/(psObject->sCurrentChannel.uSR)));

    // read again saturation counters
    if(psObject->systemFunc.SY_Read(psObject->uDemodHwAdd, TDA10023_SATNYQ_IND, 7, uByteSat) == False) return TM_ERR_IIC_ERR;
    uSATADC = uByteSat[1];
    uHALFADC = uByteSat[2];
    uSATDEC1 = uByteSat[3];
    uSATDEC2 = uByteSat[4];
    uSATDEC3 = uByteSat[5];
    uSATAAF = uByteSat[6];
    uSATNYQ = uByteSat[0];

    //Time to refresh sat register = Nb of samples selected in SSAT register / Sr
    internal10023Wait((UInt16)(1000*2*(psObject->uNbSamplesSSAT)/(psObject->sCurrentChannel.uSR)));

    // read again saturation counters
    if(psObject->systemFunc.SY_Read(psObject->uDemodHwAdd, TDA10023_SATNYQ_IND, 4, uByteSat) == False) return TM_ERR_IIC_ERR;
    uSATADC_2 = uByteSat[1];
    uHALFADC_2 = uByteSat[2];
    uSATDEC1_2 = uByteSat[3];

    psObject->bFiltersGainSet = True;

    i++;
  }

  return TM_OK;
}

//-----------------------------------------------------------------------------
// Timer functions:
//-----------------------------------------------------------------------------
//

//-----------------------------------------------------------------------------
// FUNCTION:    Tda10023_AlgoCalcTimer
//
// DESCRIPTION: this function the numer of milliseconds regarding to the number of
//              symbols
//
// RETURN:      number of milliseconds to wait
//
// NOTES:
//-----------------------------------------------------------------------------
//
UInt16
Tda10023_AlgoCalcTimer(
    tm10023object_t *psObject,    //  I: Demod unit number
    UInt32          uNbSymbol     //  I: Number of symbols to wait for
)
{
    // prevent division by 0
    if (0 == psObject->sCurrentChannel.uSR) return 0;

    // calculate the timer in milliseconds
    uNbSymbol *= 1000;
    uNbSymbol += psObject->sCurrentChannel.uSR/2;
    uNbSymbol /= psObject->sCurrentChannel.uSR;

    return (UInt16)uNbSymbol;
}


#ifdef NO_FLOAT

//-----------------------------------------------------------------------------
// Math functions:
//-----------------------------------------------------------------------------
//


//-----------------------------------------------------------------------------
// FUNCTION:    Tda10023Mul64
//
// DESCRIPTION: multiplication Up1*Up2
//              Up1 = X1<<16 + X0;
//              Up2 = Y1<<16 + Y0;
//              result = (X1Y1<<32 + (X1Y0+X0Y1)<<16 + Y0X0)
//
//              32bits*32Bits->64bits
//
// RETURN:      None
//
// NOTES:
//-----------------------------------------------------------------------------
//
void Tda10023Mul64(UInt32 uUp1, UInt32 uUp2, UInt32* uHighInt, UInt32* uLowInt)
{
    UInt32  uLowIntTmp, uHighIntTmp, uUp1_16, uUp1_0, uUp2_16, uUp2_0;
    UInt8   bCounter;

    // init value
    uUp1_0  = uUp1 & 0x0000FFFF;
    uUp1_16 = uUp1 >> 16;
    uUp2_0  = uUp2 & 0x0000FFFF;
    uUp2_16 = uUp2 >> 16;

    // calculate X1Y1
    *uHighInt = uUp1_16*uUp2_16;

    // calculate X0Y1+X1Y0
    uLowIntTmp = uUp1_16*uUp2_0+uUp1_0*uUp2_16;
    uHighIntTmp = 0;
    for (bCounter = 0; bCounter < 16; bCounter++)
    {
        if ((uLowIntTmp & 0x80000000) || (uHighIntTmp != 0))
        {
            uHighIntTmp <<= 1;
            uHighIntTmp |= (uLowIntTmp>>31);
        }
        uLowIntTmp <<= 1;
    }

    // test overflow for low byte
    *uLowInt  = (uUp1_0*uUp2_0)>>1;
    *uLowInt += uLowIntTmp>>1;
    if (*uLowInt & 0x80000000)
        uHighIntTmp++;

    // calculate X0Y0 Low Byte
    *uLowInt = uUp1_0*uUp2_0+uLowIntTmp;

    // calculate High Byte
    *uHighInt += uHighIntTmp;
}

//-----------------------------------------------------------------------------
// FUNCTION:    Tda10023Div64
//
// DESCRIPTION: division HIGHINT*LOWINT/Down
//              LOWINT += HIGHINT*((2^32-1)/Down)) + HIGHINT/Down + LOWINT/Down
//
//              64bits/32bits -> 32bits
//
// RETURN:      Result of division
//
// NOTES:
//-----------------------------------------------------------------------------
//
UInt32 Tda10023Div64(UInt32 uHighInt, UInt32 uLowInt, UInt32 uDown)
{
    UInt32 volatile uResult;     // no optimisation
    UInt32 volatile uRemain1;    // no optimisation
    UInt32 volatile uRemain2;    // no optimisation
    UInt32 uHighInt1, uLowInt1;
    UInt32 uHighInt2, uLowInt2, uRemain3;

    // divide uHighInt by uDown
    uResult = 0xFFFFFFFF/uDown;
    uResult *= uHighInt;

    // calculate the remainder
    Tda10023Mul64((0xFFFFFFFF%uDown), uHighInt, &uHighInt1, &uLowInt1);

    // uRemain = Div64(uHighIntTmp, uLowIntTmp, uDown);
    // divide the remainder
    uRemain1 =  0xFFFFFFFF/uDown;
    uRemain1 *= uHighInt1;

    // calculate the remainder of the remainder
    Tda10023Mul64((0xFFFFFFFF%uDown), uHighInt1, &uHighInt2, &uLowInt2);

    // uRemain = Div64(uHighIntTmp, uLowIntTmp, uDown);
    // divide the remainder
    uRemain2 =  0xFFFFFFFF/uDown;
    uRemain2 *= uHighInt2;

    // calculate the remainder of the remainder
    uRemain3 = 0xFFFFFFFF%uDown;
    uRemain3 *= uHighInt2;

    //update the remainder
    uRemain2 += (uLowInt2+uHighInt2+uRemain3+(uDown/2))/uDown;

    //update the remainder
    uRemain1 += (uLowInt1+uHighInt1+(uDown/2))/uDown + uRemain2;

    // divide uLowInt by uDown and add remain
    uResult += (uLowInt+uHighInt+(uDown/2))/uDown + uRemain1;

    return uResult;
}

//-----------------------------------------------------------------------------
// FUNCTION:    Tda10023MulDiv32
//
// DESCRIPTION: uUp1*uUp2/uDown
//
//              32bits*32bits/32bits
//
// RETURN:      Result of operation
//
// NOTES:
//-----------------------------------------------------------------------------
//
UInt32 Tda10023MulDiv32(UInt32 uUp1, UInt32 uUp2, UInt32 uDown)
{
    UInt32 uHighInt, uLowInt;

    // multiplied 32bits*32Bits->64bits
    Tda10023Mul64(uUp1, uUp2, &uHighInt, &uLowInt);

    // divide 64bits/32bits->32bits
    return Tda10023Div64(uHighInt, uLowInt, uDown);
}

#endif // NO_FLOAT

#ifdef _CHINA_CABLE_
void TDA10023SolveADCHarmonic(tmUnitSelect_t demodUnit, UInt32 uRF)
{
  UInt32 xtall, pllMFactor, pllNFactor, pllPFactor, fSampling, uBoardvalue, dvbMcns;
  UInt32 sysClk, saClk, flag, k;
  static UInt32 uPLLSetting =0;

  dvbMcns = g10023Instance[demodUnit].sConfig.bModeDvbMcns;
  // Only for DVB mode, use 2nd PLL setting
  if(dvbMcns != OM57XX_MODE_DVB_DEF)
    return;

  uBoardvalue = g10023Instance[demodUnit].sConfig.uBoardConf;
  switch (uBoardvalue & 0xffff0000)
    {
  case OM5764_BOARD_DEF:
  case OM3853C_BOARD_DEF:
  default:
    xtall = OM57XX_XTALL_DEF;
    pllMFactor = OM57XX_PLLMFACTOR_DVB_DEF;
    pllNFactor = OM57XX_PLLNFACTOR_DVB_DEF;
    pllPFactor = OM57XX_PLLPFACTOR_DVB_DEF;
    fSampling = OM5763_FSAMPLING_DEF;
    break;

  case CU1216_BOARD_DEF:
  case OM5795_BOARD_DEF:
    xtall = CU1216_XTALL_FREQ_28;
    pllMFactor = CU1216_PLLMFACTOR_DVB_DEF;
    pllNFactor = CU1216_PLLNFACTOR_DVB_DEF;
    pllPFactor = CU1216_PLLPFACTOR_DVB_DEF;
    fSampling = OM57XX_FSAMPLING_DEF;
    break;
  }

  sysClk = (xtall * (pllMFactor+1))/((pllNFactor+1)*(pllPFactor+1));
  if(fSampling == 1)
    saClk = sysClk;
  else
    saClk = sysClk >> 1;
  k = uRF/saClk;
  if(((uRF - k*saClk) < 4000000) ||(( (k+1)*saClk - uRF) < 4000000))
    flag = 1;
  else
    flag = 0;
  if(uPLLSetting == flag)
    return;
  uPLLSetting = flag;
  // change PLL settings to avoid harmonic freq
  if(uPLLSetting == 0)
  {
    switch(uBoardvalue & 0xffff0000)
    {
      case OM5764_BOARD_DEF:
      case OM3853C_BOARD_DEF:
      default:
        g10023Instance[demodUnit].sConfig.bPLL_M_Factor = OM57XX_PLLMFACTOR_DVB_DEF;
        g10023Instance[demodUnit].sConfig.bPLL_N_Factor = OM57XX_PLLNFACTOR_DVB_DEF;
        g10023Instance[demodUnit].sConfig.bPLL_P_Factor = OM57XX_PLLPFACTOR_DVB_DEF;
      break;
      case CU1216_BOARD_DEF:
      case OM5795_BOARD_DEF:
        g10023Instance[demodUnit].sConfig.bPLL_M_Factor = CU1216_PLLMFACTOR_DVB_DEF;
        g10023Instance[demodUnit].sConfig.bPLL_N_Factor = CU1216_PLLNFACTOR_DVB_DEF;
        g10023Instance[demodUnit].sConfig.bPLL_P_Factor = CU1216_PLLPFACTOR_DVB_DEF;
        g10023Instance[demodUnit].sConfig.bFsampling    = OM57XX_FSAMPLING_DEF;
      break;
    }
  }
  else
  {
    switch(g10023Instance[demodUnit].sConfig.uBoard & 0xffff0000)
    {
      case OM5764_BOARD_DEF:
      case OM3853C_BOARD_DEF:
      default:
        g10023Instance[demodUnit].sConfig.bPLL_M_Factor = OM57XX_PLLMFACTOR_DVB_HARM_DEF;
        g10023Instance[demodUnit].sConfig.bPLL_N_Factor = OM57XX_PLLNFACTOR_DVB_HARM_DEF;
        g10023Instance[demodUnit].sConfig.bPLL_P_Factor = OM57XX_PLLPFACTOR_DVB_HARM_DEF;
      break;
      case CU1216_BOARD_DEF:
      case OM5795_BOARD_DEF:
        g10023Instance[demodUnit].sConfig.bPLL_M_Factor = CU1216_PLLMFACTOR_DVB_HARM_DEF;
        g10023Instance[demodUnit].sConfig.bPLL_N_Factor = CU1216_PLLNFACTOR_DVB_HARM_DEF;
        g10023Instance[demodUnit].sConfig.bPLL_P_Factor = CU1216_PLLPFACTOR_DVB_HARM_DEF;
        g10023Instance[demodUnit].sConfig.bFsampling    = CU1216_FSAMPLING_HARM_DEF;
      break;
    }
  }

  Tda10023WriteInit(&g10023Instance[demodUnit]);

  return;
}

#endif   //#ifdef _CHINA_CABLE_


static u8 tda10024_readreg (struct tda10024_state* state, u8 reg)
{
  u8 b0 [] = { reg };
  u8 b1 [] = { 0 };
  struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 },
          { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } };
  int ret;

  ret = i2c_transfer (state->i2c, msg, 2);
  if (ret != 2)
    printk("DVB: TDA10024: %s: readreg error (ret == %i)\n",
         __FUNCTION__, ret);
  return b1[0];
}


static int tda10024_writereg (struct tda10024_state* state, u8 reg, u8 data)
{
  u8 buf[] = { reg, data };
  struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 };
  int ret;

  ret = i2c_transfer (state->i2c, &msg, 1);
  if (ret != 1)
    printk("DVB: TDA10024(%d): %s, writereg error "
      "(reg == 0x%02x, val == 0x%02x, ret == %i)\n",
      state->frontend.dvb->num, __FUNCTION__, reg, data, ret);

  return (ret != 1) ? -EREMOTEIO : 0;
}


static int tda10024_writebit (struct tda10024_state* state, u8 reg, u8 mask,u8 data)
{
  if (mask==0xff)
    return tda10024_writereg(state, reg, data);
  else {
    u8 val;
    val=tda10024_readreg(state,reg);
    val&=~mask;
    val|=(data&mask);
    return tda10024_writereg(state, reg, val);
  }
}


  Bool  Write_func     (UInt32  uAddress,
                                 UInt32  uSubAddress,
                                 UInt32  uNbData,
                                 UInt32* pDataBuff)
  {
    int i= 0;
    u8 reg = 0;
    u8 data = 0;
    int ret = 0;

    if (1 == uNbData)
    {
        reg=(u8)(uSubAddress);
        data = (u8)(pDataBuff[0]);
        ret = tda10024_writereg(sState,reg,data);
        if (ret != 0)
        {
            return False;
        }
    }
    else
    {
        for(i=0;i<uNbData;i++)
        {
            reg=(u8)(uSubAddress+i);
            data = (u8)(pDataBuff[i]);
            ret = tda10024_writereg(sState,reg,data);
            if (ret != 0)
            {
                return False;
            }
        }
    }
    return True;
  }

  Bool  WriteBit_func    (UInt32  uAddress,
                                 UInt32  uSubAddress,
                                 UInt32  uMaskValue,
                                 UInt32  uValue)
  {
    int ret = 0;

    if (0== tda10024_writebit(sState,(u8)uSubAddress,(u8)uMaskValue,(u8)uValue))
    {
        return True;
    }

    return False;
  }

  Bool  Read_func      (UInt32  uAddress,
                                 UInt32  uSubAddress,
                                 UInt32  uNbData,
                                 UInt32* pDataBuff)
  {
    int i= 0;
    u8 reg = 0;
    u8 data = 0;


    if (1 == uNbData)
    {
        reg=(u8)(uSubAddress);
        pDataBuff[0] = tda10024_readreg(sState,reg);
    }
    else
    {
        for(i=0;i<uNbData;i++)
        {
            reg=(u8)(uSubAddress+i);
            pDataBuff[i] = tda10024_readreg(sState,reg);
        }
    }

    return True;
  }


//get access to tuner
static int lock_tuner(struct tda10024_state* state)
{
  u8 buf[2] = { 0x0f, 0xc0 };
  struct i2c_msg msg = {.addr=state->config->demod_address, .flags=0, .buf=buf, .len=2};

  if(i2c_transfer(state->i2c, &msg, 1) != 1)
  {
    printk("tda10024: lock tuner fails\n");
    return -EREMOTEIO;
  }
  return 0;
}

//release access from tuner
static int unlock_tuner(struct tda10024_state* state)
{
  u8 buf[2] = { 0x0f, 0x40 };
  struct i2c_msg msg_post={.addr=state->config->demod_address, .flags=0, .buf=buf, .len=2};

  if(i2c_transfer(state->i2c, &msg_post, 1) != 1)
  {
    printk("tda10024: unlock tuner fails\n");
    return -EREMOTEIO;
  }
  return 0;
}

static int tda10024_setup_reg0 (struct tda10024_state* state, u8 reg0)
{
  reg0 |= state->reg0 & 0x63;

  tda10024_writereg (state, 0x00, reg0 & 0xfe);
  tda10024_writereg (state, 0x00, reg0 | 0x01);

  state->reg0 = reg0;
  return 0;
}

static int tda10024_set_symbolrate (struct tda10024_state* state, u32 sr)
{
    if (TM_OK != tmbsl10023SetSR(0,sr))
    {
        return -1;
    }

    return 0;
}

static int tda10024_init (struct dvb_frontend *fe)
{
    return 0;
}

static int tda10024_read_status(struct dvb_frontend* fe, fe_status_t* status);

static int tda10024_set_parameters (struct dvb_frontend *fe,
              struct dvb_frontend_parameters *p)
{
    struct tda10024_state* state = fe->demodulator_priv;
    tmErrorCode_t ret = TM_OK;
    tmhalFEManagerStatus_t managerStatus= tmhalFEManagerStatusNotCompleted;
#ifdef NO_REDUNDANT_LOCKING
    fe_status_t status = 0;
#endif

#ifdef NO_REDUNDANT_LOCKING
     tda10024_read_status(fe,&status);
     if ((status & FE_HAS_LOCK) == FE_HAS_LOCK)
     {
        /*locked*/
        if (p->u.qam.modulation == sCurrent.u.qam.modulation &&
            p->frequency == sCurrent.frequency &&
            p->u.qam.symbol_rate== sCurrent.u.qam.symbol_rate)
        {
             //printk("--->TDA10024: Already locked!\n");
             return 0;
        }
     }

#endif

  if (TM_OK != tmbsl10023SetRF(0,p->frequency))
  {
        return -1;
  }

  tda10024_set_symbolrate (state, p->u.qam.symbol_rate);

  if (p->inversion == INVERSION_ON)
  {
      tmbsl10023SetSI(0,tmhalFESpectrumInverted);
  }
  else
  {
      tmbsl10023SetSI(0,tmhalFESpectrumAuto);
  }

  switch (p->u.qam.modulation)
  {
       case QAM_16:
         ret=tmbsl10023SetMod(0,tmhalFEModulationQam16);
        break;
       case QAM_32:
         ret=tmbsl10023SetMod(0,tmhalFEModulationQam32);
        break;
       case QAM_64:
         ret=tmbsl10023SetMod(0,tmhalFEModulationQam64);
        break;
       case QAM_128:
         ret=tmbsl10023SetMod(0,tmhalFEModulationQam128);
        break;
       case QAM_256:
         ret=tmbsl10023SetMod(0,tmhalFEModulationQam256);
        break;

       case QAM_AUTO:
         ret=tmbsl10023SetMod(0,tmhalFEModulationQam64);
        break;
       default:
         ret=tmbsl10023SetMod(0,tmhalFEModulationQam64);
        break;
  }


    if (ret != TM_OK)
    {
        return -1;
    }

#ifdef NO_REDUNDANT_LOCKING
       memcpy (&sCurrent,p,sizeof (struct dvb_frontend_parameters));
#endif

#ifdef ENABLE_MAINALGO

    ret = TM_OK;
    while (ret == TM_OK && (managerStatus != tmhalFEManagerStatusNoCarrier) && (managerStatus != tmhalFEManagerStatusCarrierOk))
    {
        ret = tmbsl10023Manager(0,&managerStatus);
    }

#endif


    return 0;
}

static int tda10024_read_status(struct dvb_frontend* fe, fe_status_t* status)
{
  struct tda10024_state* state = fe->demodulator_priv;
  int sync;

  *status = 0;

  //0x11[1] == CARLOCK -> Carrier locked
  //0x11[2] == FSYNC -> Frame synchronisation
  //0x11[3] == FEL -> Front End locked
  //0x11[6] == NODVB -> DVB Mode Information
  sync = tda10024_readreg (state, 0x11);

  if (sync & 2)
    *status |= FE_HAS_SIGNAL|FE_HAS_CARRIER;

  if (sync & 4)
    *status |= FE_HAS_SYNC|FE_HAS_VITERBI;

  if (sync & 8)
    *status |= FE_HAS_LOCK;

  //printk("******************* nhy| sync is %02x\n",sync);

  return 0;
}

static int tda10024_read_ber(struct dvb_frontend* fe, u32* ber)
{

  if (TM_OK != tmbsl10023GetBER(0,ber))
  {
      *ber=0;
      return -1;
  }

  return 0;
}

static int tda10024_read_signal_strength(struct dvb_frontend* fe, u16* strength)
{
  struct tda10024_state* state = fe->demodulator_priv;
  u8 ifgain=tda10024_readreg(state, 0x2f);

  u16 gain = ((255-tda10024_readreg(state, 0x17))) + (255-ifgain)/16;
  // Max raw value is about 0xb0 -> Normalize to >0xf0 after 0x90
  if (gain>0x90)
    gain=gain+2*(gain-0x90);
  if (gain>255)
    gain=255;

  *strength = (gain<<8)|gain;
  return 0;
}

static int tda10024_read_snr(struct dvb_frontend* fe, u16* snr)
{
    Int8 iSnr=0;

    if (TM_OK !=tmbsl10023GetSNR(0,&iSnr))
    {
        *snr = 0;
        return -1;
    }
    else
    {
        *snr = iSnr;
    }
    return 0;
}

static int tda10024_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
{
  struct tda10024_state* state = fe->demodulator_priv;
  u8 a,b,c,d;
  a= tda10024_readreg (state, 0x74);
  b= tda10024_readreg (state, 0x75);
  c= tda10024_readreg (state, 0x76);
  d= tda10024_readreg (state, 0x77);
  *ucblocks = a | (b<<8)|(c<<16)|(d<<24);

  tda10024_writebit (state, 0x10, 0x20,0x00);
  tda10024_writebit (state, 0x10, 0x20,0x20);
  tda10024_writebit (state, 0x13, 0x01, 0x00);

  return 0;
}

static int tda10024_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
{
  struct tda10024_state* state = fe->demodulator_priv;
  int sync,inv;
  s8 afc = 0;

  sync = tda10024_readreg(state, 0x11);
  afc = tda10024_readreg(state, 0x19);
  inv = tda10024_readreg(state, 0x04);


  p->inversion = (inv&0x20?0:1);
  p->u.qam.modulation = ((state->reg0 >> 2) & 7) + QAM_16;

  p->u.qam.fec_inner = FEC_NONE;
  p->frequency = ((p->frequency + 31250) / 62500) * 62500;

  if (sync & 2)
    p->frequency -= ((s32)p->u.qam.symbol_rate * afc) >> 10;

  return 0;
}

static int tda10024_sleep(struct dvb_frontend* fe)
{

  if (TM_OK != tmbsl10023SetPowerState(0,tmPowerStandby))
  {
      return -1;
  }

  return 0;
}

static int tda10024_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
{
  struct tda10024_state* state = fe->demodulator_priv;

  if (enable) {
    lock_tuner(state);
  } else {
    unlock_tuner(state);
  }
  return 0;
}

static void tda10024_release(struct dvb_frontend* fe)
{
  struct tda10024_state* state = fe->demodulator_priv;
  kfree(state);
}

static struct dvb_frontend_ops tda10024_ops;

struct dvb_frontend* tda10024_attach(const struct tda10024_config* config,
    struct i2c_adapter* i2c,
    u8 pwm)
{
  struct tda10024_state* state = NULL;
  tmbslDcParam_t sParam;
  int i;

  /* allocate memory for the internal state */
  state = kmalloc(sizeof(struct tda10024_state), GFP_KERNEL);
  if (state == NULL) goto error;

  /* setup the state */
  state->config = config;
  state->i2c = i2c;
  memcpy(&state->frontend.ops, &tda10024_ops, sizeof(struct dvb_frontend_ops));
  state->pwm = pwm;


  /* create dvb_frontend */
  memcpy(&state->frontend.ops, &tda10024_ops, sizeof(struct dvb_frontend_ops));
  state->frontend.demodulator_priv = state;

  sState = state;

  sParam.systemFunc.SY_Read =&Read_func;
  sParam.systemFunc.SY_Write = &Write_func;
  sParam.systemFunc.SY_WriteBit = &WriteBit_func;
  tmbsl10023Init(0,sParam);
  if (TDA10024_tuner_TDA18252 == config->tunerType)
  {
        ;
  }
  else if (TDA10024_tuner_CD1616 == config->tunerType)
  {
      tmbsl10023SetConfig(0,BOARD,OM5795_BOARD_DEF);
  }

  tmbsl10023SetConfig(0,FEINIT,0);
  tmbsl10023SetConfig(0,SWITCH,1);


 #ifdef INIT_FIX
    tda10024_writereg(sState,0x04,0x70);
    tda10024_writereg(sState,0x1C,0xb0);
    tda10024_writereg(sState,0xb4,0x5c);
    tda10024_writereg(sState,0xb6,0x4a);
 #endif

  if (TM_OK != tmbsl10023SetPowerState(0,tmPowerOn))
  {
      return -1;
  }

  return &state->frontend;

error:
  kfree(state);
  return NULL;
}

/*jg add 2009.05.27*/
static int tda10024_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fe_tune_settings)
{
  /* I have no idea about this - it may not be needed */
  fe_tune_settings->min_delay_ms = 150;
  fe_tune_settings->step_size=1000;
  fe_tune_settings->max_drift=2000;
  return 0;
}
/*jg add 2009.05.27*/

static struct dvb_frontend_ops tda10024_ops = {

  .info = {
    .name = "Philips TDA10024 DVB-C",
    .type = FE_QAM,
    .frequency_stepsize = 62500,
    .frequency_min = 47000000,
    .frequency_max = 862000000,
    .symbol_rate_min = 3000000,     /* SACLK/64 == (SYSCLK/2)/64 */
    .symbol_rate_max = 7000000,      /* SACLK/4 */
    .caps = 0x400 | //FE_CAN_QAM_4
      FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 |
      FE_CAN_QAM_128 | FE_CAN_QAM_256 |
      FE_CAN_FEC_AUTO
  },

  .release = tda10024_release,

  .init = tda10024_init,
  .sleep = tda10024_sleep,
  .i2c_gate_ctrl = tda10024_i2c_gate_ctrl,

  .set_frontend = tda10024_set_parameters,
  .get_frontend = tda10024_get_frontend,

  .read_status = tda10024_read_status,
  .read_ber = tda10024_read_ber,
  .read_signal_strength = tda10024_read_signal_strength,
  .read_snr = tda10024_read_snr,
  .read_ucblocks = tda10024_read_ucblocks,
  .get_tune_settings = tda10024_get_tune_settings,
};


MODULE_DESCRIPTION("Philips TDA10024 DVB-C demodulator driver");
MODULE_AUTHOR("Georg Acher, Hartmut Birr");
MODULE_LICENSE("GPL");

EXPORT_SYMBOL(tda10024_attach);

