diff options
Diffstat (limited to 'drivers/media/dvb-frontends/drx39xyj/drxj.c')
-rw-r--r-- | drivers/media/dvb-frontends/drx39xyj/drxj.c | 16680 |
1 files changed, 16680 insertions, 0 deletions
diff --git a/drivers/media/dvb-frontends/drx39xyj/drxj.c b/drivers/media/dvb-frontends/drx39xyj/drxj.c new file mode 100644 index 00000000000..a83f2ad67e7 --- /dev/null +++ b/drivers/media/dvb-frontends/drx39xyj/drxj.c @@ -0,0 +1,16680 @@ +/** +* \file $Id: drxj.c,v 1.637 2010/01/18 17:21:10 dingtao Exp $ +* +* \brief DRXJ specific implementation of DRX driver +* +* \author Dragan Savic, Milos Nikolic, Mihajlo Katona, Tao Ding, Paul Janssen +*/ + +/* +* $(c) 2006-2010 Trident Microsystems, Inc. - All rights reserved. +* +* This software and related documentation (the 'Software') are intellectual +* property owned by Trident and are copyright of Trident, unless specifically +* noted otherwise. +* +* Any use of the Software is permitted only pursuant to the terms of the +* license agreement, if any, which accompanies, is included with or applicable +* to the Software ('License Agreement') or upon express written consent of +* Trident. Any copying, reproduction or redistribution of the Software in +* whole or in part by any means not in accordance with the License Agreement +* or as agreed in writing by Trident is expressly prohibited. +* +* THE SOFTWARE IS WARRANTED, IF AT ALL, ONLY ACCORDING TO THE TERMS OF THE +* LICENSE AGREEMENT. EXCEPT AS WARRANTED IN THE LICENSE AGREEMENT THE SOFTWARE +* IS DELIVERED 'AS IS' AND TRIDENT HEREBY DISCLAIMS ALL WARRANTIES AND +* CONDITIONS WITH REGARD TO THE SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES +* AND CONDITIONS OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIT +* ENJOYMENT, TITLE AND NON-INFRINGEMENT OF ANY THIRD PARTY INTELLECTUAL +* PROPERTY OR OTHER RIGHTS WHICH MAY RESULT FROM THE USE OR THE INABILITY +* TO USE THE SOFTWARE. +* +* IN NO EVENT SHALL TRIDENT BE LIABLE FOR INDIRECT, INCIDENTAL, CONSEQUENTIAL, +* PUNITIVE, SPECIAL OR OTHER DAMAGES WHATSOEVER INCLUDING WITHOUT LIMITATION, +* DAMAGES FOR LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS +* INFORMATION, AND THE LIKE, ARISING OUT OF OR RELATING TO THE USE OF OR THE +* INABILITY TO USE THE SOFTWARE, EVEN IF TRIDENT HAS BEEN ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGES, EXCEPT PERSONAL INJURY OR DEATH RESULTING FROM +* TRIDENT'S NEGLIGENCE. $ +* +*/ + +/*----------------------------------------------------------------------------- +INCLUDE FILES +----------------------------------------------------------------------------*/ + +#include "drxj.h" +#include "drxj_map.h" + +#ifdef DRXJ_OPTIONS_H +#include "drxj_options.h" +#endif + + +/*============================================================================*/ +/*=== DEFINES ================================================================*/ +/*============================================================================*/ + +/** +* \brief Maximum u32_t value. +*/ +#ifndef MAX_U32 +#define MAX_U32 ((u32_t) (0xFFFFFFFFL)) +#endif + +/* Customer configurable hardware settings, etc */ +#ifndef MPEG_SERIAL_OUTPUT_PIN_DRIVE_STRENGTH +#define MPEG_SERIAL_OUTPUT_PIN_DRIVE_STRENGTH 0x02 +#endif + +#ifndef MPEG_PARALLEL_OUTPUT_PIN_DRIVE_STRENGTH +#define MPEG_PARALLEL_OUTPUT_PIN_DRIVE_STRENGTH 0x02 +#endif + +#ifndef MPEG_OUTPUT_CLK_DRIVE_STRENGTH +#define MPEG_OUTPUT_CLK_DRIVE_STRENGTH 0x06 +#endif + +#ifndef OOB_CRX_DRIVE_STRENGTH +#define OOB_CRX_DRIVE_STRENGTH 0x02 +#endif + +#ifndef OOB_DRX_DRIVE_STRENGTH +#define OOB_DRX_DRIVE_STRENGTH 0x02 +#endif +/**** START DJCOMBO patches to DRXJ registermap constants *********************/ +/**** registermap 200706071303 from drxj **************************************/ +#define ATV_TOP_CR_AMP_TH_FM 0x0 +#define ATV_TOP_CR_AMP_TH_L 0xA +#define ATV_TOP_CR_AMP_TH_LP 0xA +#define ATV_TOP_CR_AMP_TH_BG 0x8 +#define ATV_TOP_CR_AMP_TH_DK 0x8 +#define ATV_TOP_CR_AMP_TH_I 0x8 +#define ATV_TOP_CR_CONT_CR_D_MN 0x18 +#define ATV_TOP_CR_CONT_CR_D_FM 0x0 +#define ATV_TOP_CR_CONT_CR_D_L 0x20 +#define ATV_TOP_CR_CONT_CR_D_LP 0x20 +#define ATV_TOP_CR_CONT_CR_D_BG 0x18 +#define ATV_TOP_CR_CONT_CR_D_DK 0x18 +#define ATV_TOP_CR_CONT_CR_D_I 0x18 +#define ATV_TOP_CR_CONT_CR_I_MN 0x80 +#define ATV_TOP_CR_CONT_CR_I_FM 0x0 +#define ATV_TOP_CR_CONT_CR_I_L 0x80 +#define ATV_TOP_CR_CONT_CR_I_LP 0x80 +#define ATV_TOP_CR_CONT_CR_I_BG 0x80 +#define ATV_TOP_CR_CONT_CR_I_DK 0x80 +#define ATV_TOP_CR_CONT_CR_I_I 0x80 +#define ATV_TOP_CR_CONT_CR_P_MN 0x4 +#define ATV_TOP_CR_CONT_CR_P_FM 0x0 +#define ATV_TOP_CR_CONT_CR_P_L 0x4 +#define ATV_TOP_CR_CONT_CR_P_LP 0x4 +#define ATV_TOP_CR_CONT_CR_P_BG 0x4 +#define ATV_TOP_CR_CONT_CR_P_DK 0x4 +#define ATV_TOP_CR_CONT_CR_P_I 0x4 +#define ATV_TOP_CR_OVM_TH_MN 0xA0 +#define ATV_TOP_CR_OVM_TH_FM 0x0 +#define ATV_TOP_CR_OVM_TH_L 0xA0 +#define ATV_TOP_CR_OVM_TH_LP 0xA0 +#define ATV_TOP_CR_OVM_TH_BG 0xA0 +#define ATV_TOP_CR_OVM_TH_DK 0xA0 +#define ATV_TOP_CR_OVM_TH_I 0xA0 +#define ATV_TOP_EQU0_EQU_C0_FM 0x0 +#define ATV_TOP_EQU0_EQU_C0_L 0x3 +#define ATV_TOP_EQU0_EQU_C0_LP 0x3 +#define ATV_TOP_EQU0_EQU_C0_BG 0x7 +#define ATV_TOP_EQU0_EQU_C0_DK 0x0 +#define ATV_TOP_EQU0_EQU_C0_I 0x3 +#define ATV_TOP_EQU1_EQU_C1_FM 0x0 +#define ATV_TOP_EQU1_EQU_C1_L 0x1F6 +#define ATV_TOP_EQU1_EQU_C1_LP 0x1F6 +#define ATV_TOP_EQU1_EQU_C1_BG 0x197 +#define ATV_TOP_EQU1_EQU_C1_DK 0x198 +#define ATV_TOP_EQU1_EQU_C1_I 0x1F6 +#define ATV_TOP_EQU2_EQU_C2_FM 0x0 +#define ATV_TOP_EQU2_EQU_C2_L 0x28 +#define ATV_TOP_EQU2_EQU_C2_LP 0x28 +#define ATV_TOP_EQU2_EQU_C2_BG 0xC5 +#define ATV_TOP_EQU2_EQU_C2_DK 0xB0 +#define ATV_TOP_EQU2_EQU_C2_I 0x28 +#define ATV_TOP_EQU3_EQU_C3_FM 0x0 +#define ATV_TOP_EQU3_EQU_C3_L 0x192 +#define ATV_TOP_EQU3_EQU_C3_LP 0x192 +#define ATV_TOP_EQU3_EQU_C3_BG 0x12E +#define ATV_TOP_EQU3_EQU_C3_DK 0x18E +#define ATV_TOP_EQU3_EQU_C3_I 0x192 +#define ATV_TOP_STD_MODE_MN 0x0 +#define ATV_TOP_STD_MODE_FM 0x1 +#define ATV_TOP_STD_MODE_L 0x0 +#define ATV_TOP_STD_MODE_LP 0x0 +#define ATV_TOP_STD_MODE_BG 0x0 +#define ATV_TOP_STD_MODE_DK 0x0 +#define ATV_TOP_STD_MODE_I 0x0 +#define ATV_TOP_STD_VID_POL_MN 0x0 +#define ATV_TOP_STD_VID_POL_FM 0x0 +#define ATV_TOP_STD_VID_POL_L 0x2 +#define ATV_TOP_STD_VID_POL_LP 0x2 +#define ATV_TOP_STD_VID_POL_BG 0x0 +#define ATV_TOP_STD_VID_POL_DK 0x0 +#define ATV_TOP_STD_VID_POL_I 0x0 +#define ATV_TOP_VID_AMP_MN 0x380 +#define ATV_TOP_VID_AMP_FM 0x0 +#define ATV_TOP_VID_AMP_L 0xF50 +#define ATV_TOP_VID_AMP_LP 0xF50 +#define ATV_TOP_VID_AMP_BG 0x380 +#define ATV_TOP_VID_AMP_DK 0x394 +#define ATV_TOP_VID_AMP_I 0x3D8 +#define IQM_CF_OUT_ENA_OFDM__M 0x4 +#define IQM_FS_ADJ_SEL_B_QAM 0x1 +#define IQM_FS_ADJ_SEL_B_OFF 0x0 +#define IQM_FS_ADJ_SEL_B_VSB 0x2 +#define IQM_RC_ADJ_SEL_B_OFF 0x0 +#define IQM_RC_ADJ_SEL_B_QAM 0x1 +#define IQM_RC_ADJ_SEL_B_VSB 0x2 +/**** END DJCOMBO patches to DRXJ registermap *********************************/ + +#include "drx_driver_version.h" + +//#define DRX_DEBUG +#ifdef DRX_DEBUG +#include <stdio.h> +#endif + +/*----------------------------------------------------------------------------- +ENUMS +----------------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------------- +DEFINES +----------------------------------------------------------------------------*/ +#ifndef DRXJ_WAKE_UP_KEY +#define DRXJ_WAKE_UP_KEY (demod -> myI2CDevAddr -> i2cAddr) +#endif + +/** +* \def DRXJ_DEF_I2C_ADDR +* \brief Default I2C addres of a demodulator instance. +*/ +#define DRXJ_DEF_I2C_ADDR (0x52) + +/** +* \def DRXJ_DEF_DEMOD_DEV_ID +* \brief Default device identifier of a demodultor instance. +*/ +#define DRXJ_DEF_DEMOD_DEV_ID (1) + +/** +* \def DRXJ_SCAN_TIMEOUT +* \brief Timeout value for waiting on demod lock during channel scan (millisec). +*/ +#define DRXJ_SCAN_TIMEOUT 1000 + +/** +* \def DRXJ_DAP +* \brief Name of structure containing all data access protocol functions. +*/ +#define DRXJ_DAP drxDapDRXJFunct_g + +/** +* \def HI_I2C_DELAY +* \brief HI timing delay for I2C timing (in nano seconds) +* +* Used to compute HI_CFG_DIV +*/ +#define HI_I2C_DELAY 42 + +/** +* \def HI_I2C_BRIDGE_DELAY +* \brief HI timing delay for I2C timing (in nano seconds) +* +* Used to compute HI_CFG_BDL +*/ +#define HI_I2C_BRIDGE_DELAY 750 + +/** +* \brief Time Window for MER and SER Measurement in Units of Segment duration. +*/ +#define VSB_TOP_MEASUREMENT_PERIOD 64 +#define SYMBOLS_PER_SEGMENT 832 + +/** +* \brief bit rate and segment rate constants used for SER and BER. +*/ +/* values taken from the QAM microcode */ +#define DRXJ_QAM_SL_SIG_POWER_QAM_UNKNOWN 0 +#define DRXJ_QAM_SL_SIG_POWER_QPSK 32768 +#define DRXJ_QAM_SL_SIG_POWER_QAM8 24576 +#define DRXJ_QAM_SL_SIG_POWER_QAM16 40960 +#define DRXJ_QAM_SL_SIG_POWER_QAM32 20480 +#define DRXJ_QAM_SL_SIG_POWER_QAM64 43008 +#define DRXJ_QAM_SL_SIG_POWER_QAM128 20992 +#define DRXJ_QAM_SL_SIG_POWER_QAM256 43520 +/** +* \brief Min supported symbolrates. +*/ +#ifndef DRXJ_QAM_SYMBOLRATE_MIN +#define DRXJ_QAM_SYMBOLRATE_MIN (520000) +#endif + +/** +* \brief Max supported symbolrates. +*/ +#ifndef DRXJ_QAM_SYMBOLRATE_MAX +#define DRXJ_QAM_SYMBOLRATE_MAX (7233000) +#endif + +/** +* \def DRXJ_QAM_MAX_WAITTIME +* \brief Maximal wait time for QAM auto constellation in ms +*/ +#ifndef DRXJ_QAM_MAX_WAITTIME +#define DRXJ_QAM_MAX_WAITTIME 900 +#endif + +#ifndef DRXJ_QAM_FEC_LOCK_WAITTIME +#define DRXJ_QAM_FEC_LOCK_WAITTIME 150 +#endif + +#ifndef DRXJ_QAM_DEMOD_LOCK_EXT_WAITTIME +#define DRXJ_QAM_DEMOD_LOCK_EXT_WAITTIME 200 +#endif + +/** +* \def SCU status and results +* \brief SCU +*/ +#define DRX_SCU_READY 0 +#define DRXJ_MAX_WAITTIME 100 /* ms */ +#define FEC_RS_MEASUREMENT_PERIOD 12894 /* 1 sec */ +#define FEC_RS_MEASUREMENT_PRESCALE 1 /* n sec */ + +/** +* \def DRX_AUD_MAX_DEVIATION +* \brief Needed for calculation of prescale feature in AUD +*/ +#ifndef DRXJ_AUD_MAX_FM_DEVIATION +#define DRXJ_AUD_MAX_FM_DEVIATION 100 /* kHz */ +#endif + +/** +* \brief Needed for calculation of NICAM prescale feature in AUD +*/ +#ifndef DRXJ_AUD_MAX_NICAM_PRESCALE +#define DRXJ_AUD_MAX_NICAM_PRESCALE (9) /* dB */ +#endif + +/** +* \brief Needed for calculation of NICAM prescale feature in AUD +*/ +#ifndef DRXJ_AUD_MAX_WAITTIME +#define DRXJ_AUD_MAX_WAITTIME 250 /* ms */ +#endif + +/* ATV config changed flags */ +#define DRXJ_ATV_CHANGED_COEF ( 0x00000001UL ) +#define DRXJ_ATV_CHANGED_PEAK_FLT ( 0x00000008UL ) +#define DRXJ_ATV_CHANGED_NOISE_FLT ( 0x00000010UL ) +#define DRXJ_ATV_CHANGED_OUTPUT ( 0x00000020UL ) +#define DRXJ_ATV_CHANGED_SIF_ATT ( 0x00000040UL ) + +/* UIO define */ +#define DRX_UIO_MODE_FIRMWARE_SMA DRX_UIO_MODE_FIRMWARE0 +#define DRX_UIO_MODE_FIRMWARE_SAW DRX_UIO_MODE_FIRMWARE1 + +#ifdef DRXJ_SPLIT_UCODE_UPLOAD +/*============================================================================*/ +/*=== MICROCODE RELATED DEFINES ==============================================*/ +/*============================================================================*/ + +/** +* \def DRXJ_UCODE_MAGIC_WORD +* \brief Magic word for checking correct Endianess of microcode data. +* +*/ + +#ifndef DRXJ_UCODE_MAGIC_WORD +#define DRXJ_UCODE_MAGIC_WORD ((((u16_t)'H')<<8)+((u16_t)'L')) +#endif + +/** +* \def DRXJ_UCODE_CRC_FLAG +* \brief CRC flag in ucode header, flags field. +* +*/ + +#ifndef DRXJ_UCODE_CRC_FLAG +#define DRXJ_UCODE_CRC_FLAG (0x0001) +#endif + +/** +* \def DRXJ_UCODE_COMPRESSION_FLAG +* \brief Compression flag in ucode header, flags field. +* +*/ + +#ifndef DRXJ_UCODE_COMPRESSION_FLAG +#define DRXJ_UCODE_COMPRESSION_FLAG (0x0002) +#endif + +/** +* \def DRXJ_UCODE_MAX_BUF_SIZE +* \brief Maximum size of buffer used to verify the microcode.Must be an even number. +* +*/ + +#ifndef DRXJ_UCODE_MAX_BUF_SIZE +#define DRXJ_UCODE_MAX_BUF_SIZE (DRXDAP_MAX_RCHUNKSIZE) +#endif +#if DRXJ_UCODE_MAX_BUF_SIZE & 1 +#error DRXJ_UCODE_MAX_BUF_SIZE must be an even number +#endif + +#endif /* DRXJ_SPLIT_UCODE_UPLOAD */ + +/* Pin safe mode macro */ +#define DRXJ_PIN_SAFE_MODE 0x0000 +/*============================================================================*/ +/*=== GLOBAL VARIABLEs =======================================================*/ +/*============================================================================*/ +/** +*/ + +/** +* \brief Temporary register definitions. +* (register definitions that are not yet available in register master) +*/ + +/******************************************************************************/ +/* Audio block 0x103 is write only. To avoid shadowing in driver accessing */ +/* RAM adresses directly. This must be READ ONLY to avoid problems. */ +/* Writing to the interface adresses is more than only writing the RAM */ +/* locations */ +/******************************************************************************/ +/** +* \brief RAM location of MODUS registers +*/ +#define AUD_DEM_RAM_MODUS_HI__A 0x10204A3 +#define AUD_DEM_RAM_MODUS_HI__M 0xF000 + +#define AUD_DEM_RAM_MODUS_LO__A 0x10204A4 +#define AUD_DEM_RAM_MODUS_LO__M 0x0FFF + +/** +* \brief RAM location of I2S config registers +*/ +#define AUD_DEM_RAM_I2S_CONFIG1__A 0x10204B1 +#define AUD_DEM_RAM_I2S_CONFIG2__A 0x10204B2 + +/** +* \brief RAM location of DCO config registers +*/ +#define AUD_DEM_RAM_DCO_B_HI__A 0x1020461 +#define AUD_DEM_RAM_DCO_B_LO__A 0x1020462 +#define AUD_DEM_RAM_DCO_A_HI__A 0x1020463 +#define AUD_DEM_RAM_DCO_A_LO__A 0x1020464 + +/** +* \brief RAM location of Threshold registers +*/ +#define AUD_DEM_RAM_NICAM_THRSHLD__A 0x102045A +#define AUD_DEM_RAM_A2_THRSHLD__A 0x10204BB +#define AUD_DEM_RAM_BTSC_THRSHLD__A 0x10204A6 + +/** +* \brief RAM location of Carrier Threshold registers +*/ +#define AUD_DEM_RAM_CM_A_THRSHLD__A 0x10204AF +#define AUD_DEM_RAM_CM_B_THRSHLD__A 0x10204B0 + +/** +* \brief FM Matrix register fix +*/ +#ifdef AUD_DEM_WR_FM_MATRIX__A +#undef AUD_DEM_WR_FM_MATRIX__A +#endif +#define AUD_DEM_WR_FM_MATRIX__A 0x105006F + +/*============================================================================*/ +/** +* \brief Defines required for audio +*/ +#define AUD_VOLUME_ZERO_DB 115 +#define AUD_VOLUME_DB_MIN -60 +#define AUD_VOLUME_DB_MAX 12 +#define AUD_CARRIER_STRENGTH_QP_0DB 0x4000 +#define AUD_CARRIER_STRENGTH_QP_0DB_LOG10T100 421 +#define AUD_MAX_AVC_REF_LEVEL 15 +#define AUD_I2S_FREQUENCY_MAX 48000UL +#define AUD_I2S_FREQUENCY_MIN 12000UL +#define AUD_RDS_ARRAY_SIZE 18 + +/** +* \brief Needed for calculation of prescale feature in AUD +*/ +#ifndef DRX_AUD_MAX_FM_DEVIATION +#define DRX_AUD_MAX_FM_DEVIATION (100) /* kHz */ +#endif + +/** +* \brief Needed for calculation of NICAM prescale feature in AUD +*/ +#ifndef DRX_AUD_MAX_NICAM_PRESCALE +#define DRX_AUD_MAX_NICAM_PRESCALE (9) /* dB */ +#endif + + +/*============================================================================*/ +/* Values for I2S Master/Slave pin configurations */ +#define SIO_PDR_I2S_CL_CFG_MODE__MASTER 0x0004 +#define SIO_PDR_I2S_CL_CFG_DRIVE__MASTER 0x0008 +#define SIO_PDR_I2S_CL_CFG_MODE__SLAVE 0x0004 +#define SIO_PDR_I2S_CL_CFG_DRIVE__SLAVE 0x0000 + +#define SIO_PDR_I2S_DA_CFG_MODE__MASTER 0x0003 +#define SIO_PDR_I2S_DA_CFG_DRIVE__MASTER 0x0008 +#define SIO_PDR_I2S_DA_CFG_MODE__SLAVE 0x0003 +#define SIO_PDR_I2S_DA_CFG_DRIVE__SLAVE 0x0008 + +#define SIO_PDR_I2S_WS_CFG_MODE__MASTER 0x0004 +#define SIO_PDR_I2S_WS_CFG_DRIVE__MASTER 0x0008 +#define SIO_PDR_I2S_WS_CFG_MODE__SLAVE 0x0004 +#define SIO_PDR_I2S_WS_CFG_DRIVE__SLAVE 0x0000 + +/*============================================================================*/ +/*=== REGISTER ACCESS MACROS =================================================*/ +/*============================================================================*/ + +#ifdef DRXJDRIVER_DEBUG +#include <stdio.h> +#define CHK_ERROR( s ) \ + do{ \ + if ( (s) != DRX_STS_OK ) \ + { \ + fprintf(stderr, \ + "ERROR[\n file : %s\n line : %d\n]\n", \ + __FILE__,__LINE__); \ + goto rw_error; }; \ + } \ + while (0 != 0) +#else +#define CHK_ERROR( s ) \ + do{ \ + if ( (s) != DRX_STS_OK ) { goto rw_error; } \ + } while (0 != 0) +#endif + +#define CHK_ZERO( s ) \ + do{ \ + if ( (s) == 0 ) return DRX_STS_ERROR; \ + } while (0) + +#define DUMMY_READ() \ + do{ \ + u16_t dummy; \ + RR16( demod->myI2CDevAddr, SCU_RAM_VERSION_HI__A, &dummy ); \ + } while (0) + +#define WR16( dev, addr, val) \ + CHK_ERROR( DRXJ_DAP.writeReg16Func( (dev), (addr), (val), 0 ) ) + +#define RR16( dev, addr, val) \ + CHK_ERROR( DRXJ_DAP.readReg16Func( (dev), (addr), (val), 0 ) ) + +#define WR32( dev, addr, val) \ + CHK_ERROR( DRXJ_DAP.writeReg32Func( (dev), (addr), (val), 0 ) ) + +#define RR32( dev, addr, val) \ + CHK_ERROR( DRXJ_DAP.readReg32Func( (dev), (addr), (val), 0 ) ) + +#define WRB( dev, addr, len, block ) \ + CHK_ERROR( DRXJ_DAP.writeBlockFunc( (dev), (addr), (len), (block), 0 ) ) + +#define RRB( dev, addr, len, block ) \ + CHK_ERROR( DRXJ_DAP.readBlockFunc( (dev), (addr), (len), (block), 0 ) ) + +#define BCWR16( dev, addr, val ) \ + CHK_ERROR( DRXJ_DAP.writeReg16Func( (dev), (addr), (val), DRXDAP_FASI_BROADCAST ) ) + +#define ARR32( dev, addr, val) \ + CHK_ERROR( DRXJ_DAP_AtomicReadReg32( (dev), (addr), (val), 0 ) ) + +#define SARR16( dev, addr, val) \ + CHK_ERROR( DRXJ_DAP_SCU_AtomicReadReg16( (dev), (addr), (val), 0 ) ) + +#define SAWR16( dev, addr, val) \ + CHK_ERROR( DRXJ_DAP_SCU_AtomicWriteReg16( (dev), (addr), (val), 0 ) ) + +/** +* This macro is used to create byte arrays for block writes. +* Block writes speed up I2C traffic between host and demod. +* The macro takes care of the required byte order in a 16 bits word. +* x -> lowbyte(x), highbyte(x) +*/ +#define DRXJ_16TO8( x ) ((u8_t) (((u16_t)x) &0xFF)), \ + ((u8_t)((((u16_t)x)>>8)&0xFF)) +/** +* This macro is used to convert byte array to 16 bit register value for block read. +* Block read speed up I2C traffic between host and demod. +* The macro takes care of the required byte order in a 16 bits word. +*/ +#define DRXJ_8TO16( x ) ((u16_t) (x[0] | (x[1] << 8))) + +/*============================================================================*/ +/*=== MISC DEFINES ===========================================================*/ +/*============================================================================*/ + +/*============================================================================*/ +/*=== HI COMMAND RELATED DEFINES =============================================*/ +/*============================================================================*/ + +/** +* \brief General maximum number of retries for ucode command interfaces +*/ +#define DRXJ_MAX_RETRIES (100) + +/*============================================================================*/ +/*=== STANDARD RELATED MACROS ================================================*/ +/*============================================================================*/ + +#define DRXJ_ISATVSTD( std ) ( ( std == DRX_STANDARD_PAL_SECAM_BG ) || \ + ( std == DRX_STANDARD_PAL_SECAM_DK ) || \ + ( std == DRX_STANDARD_PAL_SECAM_I ) || \ + ( std == DRX_STANDARD_PAL_SECAM_L ) || \ + ( std == DRX_STANDARD_PAL_SECAM_LP ) || \ + ( std == DRX_STANDARD_NTSC ) || \ + ( std == DRX_STANDARD_FM ) ) + +#define DRXJ_ISQAMSTD( std ) ( ( std == DRX_STANDARD_ITU_A ) || \ + ( std == DRX_STANDARD_ITU_B ) || \ + ( std == DRX_STANDARD_ITU_C ) || \ + ( std == DRX_STANDARD_ITU_D )) + +/*----------------------------------------------------------------------------- +STATIC VARIABLES +----------------------------------------------------------------------------*/ +DRXStatus_t DRXJ_Open ( pDRXDemodInstance_t demod ); +DRXStatus_t DRXJ_Close ( pDRXDemodInstance_t demod); +DRXStatus_t DRXJ_Ctrl ( pDRXDemodInstance_t demod, + DRXCtrlIndex_t ctrl, + void *ctrlData); + +/*----------------------------------------------------------------------------- +GLOBAL VARIABLES +----------------------------------------------------------------------------*/ +/* + * DRXJ DAP structures + */ + +static DRXStatus_t DRXJ_DAP_ReadBlock ( + pI2CDeviceAddr_t devAddr, + DRXaddr_t addr, + u16_t datasize, + pu8_t data, + DRXflags_t flags); + +static DRXStatus_t DRXJ_DAP_ReadModifyWriteReg8 ( + pI2CDeviceAddr_t devAddr, + DRXaddr_t waddr, + DRXaddr_t raddr, + u8_t wdata, + pu8_t rdata); + +static DRXStatus_t DRXJ_DAP_ReadModifyWriteReg16 ( + pI2CDeviceAddr_t devAddr, + DRXaddr_t waddr, + DRXaddr_t raddr, + u16_t wdata, + pu16_t rdata); + +static DRXStatus_t DRXJ_DAP_ReadModifyWriteReg32 ( + pI2CDeviceAddr_t devAddr, + DRXaddr_t waddr, + DRXaddr_t raddr, + u32_t wdata, + pu32_t rdata); + +static DRXStatus_t DRXJ_DAP_ReadReg8 ( + pI2CDeviceAddr_t devAddr, + DRXaddr_t addr, + pu8_t data, + DRXflags_t flags); + +static DRXStatus_t DRXJ_DAP_ReadReg16 ( + pI2CDeviceAddr_t devAddr, + DRXaddr_t addr, + pu16_t data, + DRXflags_t flags); + +static DRXStatus_t DRXJ_DAP_ReadReg32 ( + pI2CDeviceAddr_t devAddr, + DRXaddr_t addr, + pu32_t data, + DRXflags_t flags); + +static DRXStatus_t DRXJ_DAP_WriteBlock ( + pI2CDeviceAddr_t devAddr, + DRXaddr_t addr, + u16_t datasize, + pu8_t data, + DRXflags_t flags); + +static DRXStatus_t DRXJ_DAP_WriteReg8 ( + pI2CDeviceAddr_t devAddr, + DRXaddr_t addr, + u8_t data, + DRXflags_t flags); + +static DRXStatus_t DRXJ_DAP_WriteReg16 ( + pI2CDeviceAddr_t devAddr, + DRXaddr_t addr, + u16_t data, + DRXflags_t flags); + +static DRXStatus_t DRXJ_DAP_WriteReg32 ( + pI2CDeviceAddr_t devAddr, + DRXaddr_t addr, + u32_t data, + DRXflags_t flags); + +/* The version structure of this protocol implementation */ +char drxDapDRXJModuleName[] = "DRXJ Data Access Protocol"; +char drxDapDRXJVersionText[] = "0.0.0"; + +DRXVersion_t drxDapDRXJVersion = { + DRX_MODULE_DAP, /**< type identifier of the module */ + drxDapDRXJModuleName, /**< name or description of module */ + + 0, /**< major version number */ + 0, /**< minor version number */ + 0, /**< patch version number */ + drxDapDRXJVersionText /**< version as text string */ +}; + +/* The structure containing the protocol interface */ +DRXAccessFunc_t drxDapDRXJFunct_g = { + &drxDapDRXJVersion, + DRXJ_DAP_WriteBlock, /* Supported */ + DRXJ_DAP_ReadBlock, /* Supported */ + DRXJ_DAP_WriteReg8, /* Not supported */ + DRXJ_DAP_ReadReg8, /* Not supported */ + DRXJ_DAP_ReadModifyWriteReg8, /* Not supported */ + DRXJ_DAP_WriteReg16, /* Supported */ + DRXJ_DAP_ReadReg16, /* Supported */ + DRXJ_DAP_ReadModifyWriteReg16, /* Supported */ + DRXJ_DAP_WriteReg32, /* Supported */ + DRXJ_DAP_ReadReg32, /* Supported */ + DRXJ_DAP_ReadModifyWriteReg32, /* Not supported */ +}; + +/** +* /var DRXJ_Func_g +* /brief The driver functions of the drxj +*/ +DRXDemodFunc_t DRXJFunctions_g = +{ + DRXJ_TYPE_ID, + DRXJ_Open, + DRXJ_Close, + DRXJ_Ctrl +}; + +DRXJData_t DRXJData_g = +{ + FALSE, /* hasLNA : TRUE if LNA (aka PGA) present */ + FALSE, /* hasOOB : TRUE if OOB supported */ + FALSE, /* hasNTSC: TRUE if NTSC supported */ + FALSE, /* hasBTSC: TRUE if BTSC supported */ + FALSE, /* hasSMATX: TRUE if SMA_TX pin is available */ + FALSE, /* hasSMARX: TRUE if SMA_RX pin is available */ + FALSE, /* hasGPIO : TRUE if GPIO pin is available */ + FALSE, /* hasIRQN : TRUE if IRQN pin is available */ + 0, /* mfx A1/A2/A... */ + + /* tuner settings */ + FALSE, /* tuner mirrors RF signal */ + /* standard/channel settings */ + DRX_STANDARD_UNKNOWN, /* current standard */ + DRX_CONSTELLATION_AUTO, /* constellation */ + 0, /* frequency in KHz */ + DRX_BANDWIDTH_UNKNOWN, /* currBandwidth */ + DRX_MIRROR_NO, /* mirror */ + + /* signal quality information: */ + /* default values taken from the QAM Programming guide */ + /* fecBitsDesired should not be less than 4000000 */ + 4000000, /* fecBitsDesired */ + 5, /* fecVdPlen */ + 4, /* qamVdPrescale */ + 0xFFFF, /* qamVDPeriod */ + 204*8, /* fecRsPlen annex A */ + 1, /* fecRsPrescale */ + FEC_RS_MEASUREMENT_PERIOD,/* fecRsPeriod */ + TRUE, /* resetPktErrAcc */ + 0, /* pktErrAccStart */ + + /* HI configuration */ + 0, /* HICfgTimingDiv */ + 0, /* HICfgBridgeDelay */ + 0, /* HICfgWakeUpKey */ + 0, /* HICfgCtrl */ + 0, /* HICfgTimeout */ + /* UIO configuartion */ + DRX_UIO_MODE_DISABLE, /* uioSmaRxMode */ + DRX_UIO_MODE_DISABLE, /* uioSmaTxMode */ + DRX_UIO_MODE_DISABLE, /* uioASELMode */ + DRX_UIO_MODE_DISABLE, /* uioIRQNMode */ + /* FS setting */ + 0UL, /* iqmFsRateOfs */ + FALSE, /* posImage */ + /* RC setting */ + 0UL, /* iqmRcRateOfs */ + /* AUD information */ +/* FALSE, * flagSetAUDdone */ +/* FALSE, * detectedRDS */ +/* TRUE, * flagASDRequest */ +/* FALSE, * flagHDevClear */ +/* FALSE, * flagHDevSet */ +/* (u16_t) 0xFFF, * rdsLastCount */ + +/*#ifdef DRXJ_SPLIT_UCODE_UPLOAD + FALSE, * flagAudMcUploaded */ +/*#endif * DRXJ_SPLIT_UCODE_UPLOAD */ + /* ATV configuartion */ + 0UL, /* flags cfg changes */ + /* shadow of ATV_TOP_EQU0__A */ + {-5, + ATV_TOP_EQU0_EQU_C0_FM, + ATV_TOP_EQU0_EQU_C0_L, + ATV_TOP_EQU0_EQU_C0_LP, + ATV_TOP_EQU0_EQU_C0_BG, + ATV_TOP_EQU0_EQU_C0_DK, + ATV_TOP_EQU0_EQU_C0_I + }, + /* shadow of ATV_TOP_EQU1__A */ + {-50, + ATV_TOP_EQU1_EQU_C1_FM, + ATV_TOP_EQU1_EQU_C1_L, + ATV_TOP_EQU1_EQU_C1_LP, + ATV_TOP_EQU1_EQU_C1_BG, + ATV_TOP_EQU1_EQU_C1_DK, + ATV_TOP_EQU1_EQU_C1_I + }, + /* shadow of ATV_TOP_EQU2__A */ + {210, + ATV_TOP_EQU2_EQU_C2_FM, + ATV_TOP_EQU2_EQU_C2_L, + ATV_TOP_EQU2_EQU_C2_LP, + ATV_TOP_EQU2_EQU_C2_BG, + ATV_TOP_EQU2_EQU_C2_DK, + ATV_TOP_EQU2_EQU_C2_I + }, + /* shadow of ATV_TOP_EQU3__A */ + {-160, + ATV_TOP_EQU3_EQU_C3_FM, + ATV_TOP_EQU3_EQU_C3_L, + ATV_TOP_EQU3_EQU_C3_LP, + ATV_TOP_EQU3_EQU_C3_BG, + ATV_TOP_EQU3_EQU_C3_DK, + ATV_TOP_EQU3_EQU_C3_I + }, + FALSE, /* flag: TRUE=bypass */ + ATV_TOP_VID_PEAK__PRE, /* shadow of ATV_TOP_VID_PEAK__A */ + ATV_TOP_NOISE_TH__PRE, /* shadow of ATV_TOP_NOISE_TH__A */ + TRUE, /* flag CVBS ouput enable */ + FALSE, /* flag SIF ouput enable */ + DRXJ_SIF_ATTENUATION_0DB, /* current SIF att setting */ + { /* qamRfAgcCfg */ + DRX_STANDARD_ITU_B, /* standard */ + DRX_AGC_CTRL_AUTO, /* ctrlMode */ + 0, /* outputLevel */ + 0, /* minOutputLevel */ + 0xFFFF, /* maxOutputLevel */ + 0x0000, /* speed */ + 0x0000, /* top */ + 0x0000 /* c.o.c. */ + }, + { /* qamIfAgcCfg */ + DRX_STANDARD_ITU_B, /* standard */ + DRX_AGC_CTRL_AUTO, /* ctrlMode */ + 0, /* outputLevel */ + 0, /* minOutputLevel */ + 0xFFFF, /* maxOutputLevel */ + 0x0000, /* speed */ + 0x0000, /* top (don't care) */ + 0x0000 /* c.o.c. (don't care) */ + }, + { /* vsbRfAgcCfg */ + DRX_STANDARD_8VSB, /* standard */ + DRX_AGC_CTRL_AUTO, /* ctrlMode */ + 0, /* outputLevel */ + 0, /* minOutputLevel */ + 0xFFFF, /* maxOutputLevel */ + 0x0000, /* speed */ + 0x0000, /* top (don't care) */ + 0x0000 /* c.o.c. (don't care) */ + }, + { /* vsbIfAgcCfg */ + DRX_STANDARD_8VSB, /* standard */ + DRX_AGC_CTRL_AUTO, /* ctrlMode */ + 0, /* outputLevel */ + 0, /* minOutputLevel */ + 0xFFFF, /* maxOutputLevel */ + 0x0000, /* speed */ + 0x0000, /* top (don't care) */ + 0x0000 /* c.o.c. (don't care) */ + }, + 0, /* qamPgaCfg */ + 0, /* vsbPgaCfg */ + { /* qamPreSawCfg */ + DRX_STANDARD_ITU_B, /* standard */ + 0, /* reference */ + FALSE /* usePreSaw */ + }, + { /* vsbPreSawCfg */ + DRX_STANDARD_8VSB, /* standard */ + 0, /* reference */ + FALSE /* usePreSaw */ + }, + + /* Version information */ +#ifndef _CH_ + { + "01234567890", /* human readable version microcode */ + "01234567890" /* human readable version device specific code */ + }, + { + { /* DRXVersion_t for microcode */ + DRX_MODULE_UNKNOWN, + (char*)(NULL), + 0, + 0, + 0, + (char*)(NULL) + }, + { /* DRXVersion_t for device specific code */ + DRX_MODULE_UNKNOWN, + (char*)(NULL), + 0, + 0, + 0, + (char*)(NULL) + } + }, + { + { /* DRXVersionList_t for microcode */ + (pDRXVersion_t)(NULL), + (pDRXVersionList_t)(NULL) + }, + { /* DRXVersionList_t for device specific code */ + (pDRXVersion_t)(NULL), + (pDRXVersionList_t)(NULL) + } + }, +#endif + FALSE, /* smartAntInverted */ + /* Tracking filter setting for OOB */ + { + 12000, + 9300, + 6600, + 5280, + 3700, + 3000, + 2000, + 0 + }, + FALSE, /* oobPowerOn */ + 0, /* mpegTsStaticBitrate */ + FALSE, /* disableTEIhandling */ + FALSE, /* bitReverseMpegOutout */ + DRXJ_MPEGOUTPUT_CLOCK_RATE_AUTO, /* mpegOutputClockRate */ + DRXJ_MPEG_START_WIDTH_1CLKCYC, /* mpegStartWidth */ + + /* Pre SAW & Agc configuration for ATV */ + { + DRX_STANDARD_NTSC, /* standard */ + 7, /* reference */ + TRUE /* usePreSaw */ + }, + { /* ATV RF-AGC */ + DRX_STANDARD_NTSC, /* standard */ + DRX_AGC_CTRL_AUTO, /* ctrlMode */ + 0, /* outputLevel */ + 0, /* minOutputLevel (d.c.) */ + 0, /* maxOutputLevel (d.c.) */ + 3, /* speed */ + 9500, /* top */ + 4000 /* cut-off current */ + }, + { /* ATV IF-AGC */ + DRX_STANDARD_NTSC, /* standard */ + DRX_AGC_CTRL_AUTO, /* ctrlMode */ + 0, /* outputLevel */ + 0, /* minOutputLevel (d.c.) */ + 0, /* maxOutputLevel (d.c.) */ + 3, /* speed */ + 2400, /* top */ + 0 /* c.o.c. (d.c.) */ + }, + 140, /* ATV PGA config */ + 0, /* currSymbolRate */ + + FALSE, /* pdrSafeMode */ + SIO_PDR_GPIO_CFG__PRE, /* pdrSafeRestoreValGpio */ + SIO_PDR_VSYNC_CFG__PRE, /* pdrSafeRestoreValVSync */ + SIO_PDR_SMA_RX_CFG__PRE, /* pdrSafeRestoreValSmaRx */ + SIO_PDR_SMA_TX_CFG__PRE, /* pdrSafeRestoreValSmaTx */ + + 4, /* oobPreSaw */ + DRXJ_OOB_LO_POW_MINUS10DB, /* oobLoPow */ + { + FALSE /* audData, only first member */ + }, +}; + + +/** +* \var DRXJDefaultAddr_g +* \brief Default I2C address and device identifier. +*/ +I2CDeviceAddr_t DRXJDefaultAddr_g = { + DRXJ_DEF_I2C_ADDR, /* i2c address */ + DRXJ_DEF_DEMOD_DEV_ID /* device id */ +}; + +/** +* \var DRXJDefaultCommAttr_g +* \brief Default common attributes of a drxj demodulator instance. +*/ +DRXCommonAttr_t DRXJDefaultCommAttr_g = { + (pu8_t)NULL, /* ucode ptr */ + 0, /* ucode size */ + TRUE, /* ucode verify switch */ + { 0 }, /* version record */ + + 44000, /* IF in kHz in case no tuner instance is used */ + (151875-0), /* system clock frequency in kHz */ + 0, /* oscillator frequency kHz */ + 0, /* oscillator deviation in ppm, signed */ + FALSE, /* If TRUE mirror frequency spectrum */ + { + /* MPEG output configuration */ + TRUE, /* If TRUE, enable MPEG ouput */ + FALSE, /* If TRUE, insert RS byte */ + TRUE, /* If TRUE, parallel out otherwise serial */ + FALSE, /* If TRUE, invert DATA signals */ + FALSE, /* If TRUE, invert ERR signal */ + FALSE, /* If TRUE, invert STR signals */ + FALSE, /* If TRUE, invert VAL signals */ + FALSE, /* If TRUE, invert CLK signals */ + TRUE, /* If TRUE, static MPEG clockrate will + be used, otherwise clockrate will + adapt to the bitrate of the TS */ + 19392658UL, /* Maximum bitrate in b/s in case + static clockrate is selected */ + DRX_MPEG_STR_WIDTH_1 /* MPEG Start width in clock cycles */ + }, + /* Initilisations below can be ommited, they require no user input and + are initialy 0, NULL or FALSE. The compiler will initialize them to these + values when ommited. */ + FALSE, /* isOpened */ + + /* SCAN */ + NULL, /* no scan params yet */ + 0, /* current scan index */ + 0, /* next scan frequency */ + FALSE, /* scan ready flag */ + 0, /* max channels to scan */ + 0, /* nr of channels scanned */ + NULL, /* default scan function */ + NULL, /* default context pointer */ + 0, /* millisec to wait for demod lock */ + DRXJ_DEMOD_LOCK, /* desired lock */ + FALSE, + + /* Power management */ + DRX_POWER_UP, + + /* Tuner */ + 1, /* nr of I2C port to wich tuner is */ + 0L, /* minimum RF input frequency, in kHz */ + 0L, /* maximum RF input frequency, in kHz */ + FALSE, /* Rf Agc Polarity */ + FALSE, /* If Agc Polarity */ + FALSE, /* tuner slow mode */ + + + { /* current channel (all 0) */ + 0UL /* channel.frequency */ + }, + DRX_STANDARD_UNKNOWN, /* current standard */ + DRX_STANDARD_UNKNOWN, /* previous standard */ + DRX_STANDARD_UNKNOWN, /* diCacheStandard */ + FALSE, /* useBootloader */ + 0UL, /* capabilities */ + 0 /* mfx */ + +}; + +/** +* \var DRXJDefaultDemod_g +* \brief Default drxj demodulator instance. +*/ +DRXDemodInstance_t DRXJDefaultDemod_g = { + &DRXJFunctions_g, /* demod functions */ + &DRXJ_DAP, /* data access protocol functions */ + NULL, /* tuner instance */ + &DRXJDefaultAddr_g, /* i2c address & device id */ + &DRXJDefaultCommAttr_g, /* demod common attributes */ + &DRXJData_g /* demod device specific attributes */ +}; + +/** +* \brief Default audio data structure for DRK demodulator instance. +* +* This structure is DRXK specific. +* +*/ +DRXAudData_t DRXJDefaultAudData_g = +{ + FALSE, /* audioIsActive */ + DRX_AUD_STANDARD_AUTO, /* audioStandard */ + + /* i2sdata */ + { + FALSE, /* outputEnable */ + 48000, /* frequency */ + DRX_I2S_MODE_MASTER, /* mode */ + DRX_I2S_WORDLENGTH_32, /* wordLength */ + DRX_I2S_POLARITY_RIGHT, /* polarity */ + DRX_I2S_FORMAT_WS_WITH_DATA /* format */ + }, + /* volume */ + { + TRUE, /* mute; */ + 0, /* volume */ + DRX_AUD_AVC_OFF , /* avcMode */ + 0, /* avcRefLevel */ + DRX_AUD_AVC_MAX_GAIN_12DB, /* avcMaxGain */ + DRX_AUD_AVC_MAX_ATTEN_24DB, /* avcMaxAtten */ + 0, /* strengthLeft */ + 0 /* strengthRight */ + }, + DRX_AUD_AUTO_SOUND_SELECT_ON_CHANGE_ON,/* autoSound */ + /* assThresholds */ + { + 440, /* A2 */ + 12, /* BTSC */ + 700, /* NICAM */ + }, + /* carrier */ + { + /* a */ + { + 42, /* thres */ + DRX_NO_CARRIER_NOISE, /* opt */ + 0, /* shift */ + 0 /* dco */ + }, + /* b */ + { + 42, /* thres */ + DRX_NO_CARRIER_MUTE, /* opt */ + 0, /* shift */ + 0 /* dco */ + }, + + }, + /* mixer */ + { + DRX_AUD_SRC_STEREO_OR_A, /* sourceI2S */ + DRX_AUD_I2S_MATRIX_STEREO, /* matrixI2S */ + DRX_AUD_FM_MATRIX_SOUND_A /* matrixFm */ + }, + DRX_AUD_DEVIATION_NORMAL, /* deviation */ + DRX_AUD_AVSYNC_OFF, /* avSync */ + + /* prescale */ + { + DRX_AUD_MAX_FM_DEVIATION, /* fmDeviation */ + DRX_AUD_MAX_NICAM_PRESCALE /* nicamGain */ + }, + DRX_AUD_FM_DEEMPH_75US, /* deemph */ + DRX_BTSC_STEREO, /* btscDetect */ + 0, /* rdsDataCounter */ + FALSE /* rdsDataPresent */ +}; + + +/*----------------------------------------------------------------------------- +STRUCTURES +----------------------------------------------------------------------------*/ +typedef struct { + u16_t eqMSE; + u8_t eqMode; + u8_t eqCtrl; + u8_t eqStat; +} DRXJEQStat_t, *pDRXJEQStat_t; + +/* HI command */ +typedef struct { + u16_t cmd; + u16_t param1; + u16_t param2; + u16_t param3; + u16_t param4; + u16_t param5; + u16_t param6; +} DRXJHiCmd_t, *pDRXJHiCmd_t; + +#ifdef DRXJ_SPLIT_UCODE_UPLOAD +/*============================================================================*/ +/*=== MICROCODE RELATED STRUCTURES ===========================================*/ +/*============================================================================*/ + +typedef struct { + u32_t addr; + u16_t size; + u16_t flags; /* bit[15..2]=reserved, + bit[1]= compression on/off + bit[0]= CRC on/off */ + u16_t CRC; +} DRXUCodeBlockHdr_t, *pDRXUCodeBlockHdr_t; +#endif /* DRXJ_SPLIT_UCODE_UPLOAD */ + +/*----------------------------------------------------------------------------- +FUNCTIONS +----------------------------------------------------------------------------*/ +/* Some prototypes */ +static DRXStatus_t +HICommand(const pI2CDeviceAddr_t devAddr, + const pDRXJHiCmd_t cmd, + pu16_t result); + +static DRXStatus_t +CtrlLockStatus( pDRXDemodInstance_t demod, + pDRXLockStatus_t lockStat ); + +static DRXStatus_t +CtrlPowerMode( pDRXDemodInstance_t demod, + pDRXPowerMode_t mode ); + +static DRXStatus_t +PowerDownAud( pDRXDemodInstance_t demod ); + +#ifndef DRXJ_DIGITAL_ONLY +static DRXStatus_t +PowerUpAud( pDRXDemodInstance_t demod, + Bool_t setStandard ); +#endif + +static DRXStatus_t +AUDCtrlSetStandard ( pDRXDemodInstance_t demod, + pDRXAudStandard_t standard ); + +static DRXStatus_t +CtrlSetCfgPreSaw ( pDRXDemodInstance_t demod, pDRXJCfgPreSaw_t preSaw ); + +static DRXStatus_t +CtrlSetCfgAfeGain ( pDRXDemodInstance_t demod, pDRXJCfgAfeGain_t afeGain ); + +#ifdef DRXJ_SPLIT_UCODE_UPLOAD +static DRXStatus_t +CtrlUCodeUpload( pDRXDemodInstance_t demod, + pDRXUCodeInfo_t mcInfo, + DRXUCodeAction_t action, + Bool_t audioMCUpload ); +#endif /* DRXJ_SPLIT_UCODE_UPLOAD */ + +/*============================================================================*/ +/*============================================================================*/ +/*== HELPER FUNCTIONS ==*/ +/*============================================================================*/ +/*============================================================================*/ + +/** +* \fn void Mult32(u32_t a, u32_t b, pu32_t h, pu32_t l) +* \brief 32bitsx32bits signed multiplication +* \param a 32 bits multiplicant, typecast from signed to unisgned +* \param b 32 bits multiplier, typecast from signed to unisgned +* \param h pointer to high part 64 bits result, typecast from signed to unisgned +* \param l pointer to low part 64 bits result +* +* For the 2n+n addition a + b: +* if a >= 0, then h += 0 (sign extension = 0) +* but if a < 0, then h += 2^n-1 ==> h -= 1. +* +* Also, if a + b < 2^n, then a + b >= a && a + b >= b +* but if a + b >= 2^n, then R = a + b - 2^n, +* and because a < 2^n && b < 2*n ==> R < a && R < b. +* Therefore, to detect overflow, simply compare the addition result with +* one of the operands; if the result is smaller, overflow has occurred and +* h must be incremented. +* +* Booth multiplication uses additions and subtractions to reduce the number +* of iterations. This is done by taking three subsequent bits abc and calculating +* the following multiplication factor: -2a + b + c. This factor is multiplied +* by the second operand and added to the result. Next, the first operand is +* shifted two bits (hence one of the three bits is reused) and the process +* repeated. The last iteration has only two bits left, but we simply add +* a zero to the end. +* +* Hence: (n=4) +* 1 * a = 0 * 4a + 1 * a +* 2 * a = 1 * 4a - 2 * a +* 3 * a = 1 * 4a - 1 * a +* -1 * a = 0 * 4a - 1 * a +* -5 * a = -1 * 4a - 1 * a +* +* etc. +* +* Note that the function is type size independent. Any unsigned integer type +* can be substituted for booth_t. +* +*/ + +#define DRX_IS_BOOTH_NEGATIVE(__a) (((__a) & (1 << (sizeof (u32_t) * 8 - 1))) != 0) + +static void Mult32(u32_t a, u32_t b, pu32_t h, pu32_t l) +{ + unsigned int i; + *h = *l = 0; + + /* n/2 iterations; shift operand a left two bits after each iteration. */ + /* This automatically appends a zero to the operand for the last iteration. */ + for (i = 0; i < sizeof (a) * 8; i += 2, a = a << 2) + { + /* Shift result left two bits */ + *h = (*h << 2) + (*l >> (sizeof (*l) * 8 - 2)); + *l = (*l << 2); + + /* Take the first three bits of operand a for the Booth conversion: */ + /* 0, 7: do nothing */ + /* 1, 2: add b */ + /* 3 : add 2b */ + /* 4 : subtract 2b */ + /* 5, 6: subtract b */ + switch (a >> (sizeof (a) * 8 - 3)) + { + case 3: + *l += b; + *h = *h - DRX_IS_BOOTH_NEGATIVE (b) + (*l < b); + case 1: + case 2: + *l += b; + *h = *h - DRX_IS_BOOTH_NEGATIVE (b) + (*l < b); + break; + case 4: + *l -= b; + *h = *h - !DRX_IS_BOOTH_NEGATIVE (b) + !b + (*l < ((u32_t) (-((s32_t)b))) ); + case 5: + case 6: + *l -= b; + *h = *h - !DRX_IS_BOOTH_NEGATIVE (b) + !b + (*l < ((u32_t) (-((s32_t)b))) ); + break; + } + } +} + +/*============================================================================*/ + +/* +* \fn u32_t Frac28(u32_t N, u32_t D) +* \brief Compute: (1<<28)*N/D +* \param N 32 bits +* \param D 32 bits +* \return (1<<28)*N/D +* This function is used to avoid floating-point calculations as they may +* not be present on the target platform. + +* Frac28 performs an unsigned 28/28 bits division to 32-bit fixed point +* fraction used for setting the Frequency Shifter registers. +* N and D can hold numbers up to width: 28-bits. +* The 4 bits integer part and the 28 bits fractional part are calculated. + +* Usage condition: ((1<<28)*n)/d < ((1<<32)-1) => (n/d) < 15.999 + +* N: 0...(1<<28)-1 = 268435454 +* D: 0...(1<<28)-1 +* Q: 0...(1<<32)-1 +*/ +static u32_t Frac28(u32_t N, u32_t D) +{ + int i=0; + u32_t Q1=0; + u32_t R0=0; + + R0 = (N%D)<<4; /* 32-28 == 4 shifts possible at max */ + Q1 = N/D; /* integer part, only the 4 least significant bits + will be visible in the result */ + + /* division using radix 16, 7 nibbles in the result */ + for (i=0; i<7; i++) { + Q1 = (Q1 << 4) | R0/D; + R0 = (R0%D)<<4; + } + /* rounding */ + if ((R0>>3) >= D) Q1++; + + return Q1; +} + +/** +* \fn u32_t Log10Times100( u32_t x) +* \brief Compute: 100*log10(x) +* \param x 32 bits +* \return 100*log10(x) +* +* 100*log10(x) +* = 100*(log2(x)/log2(10))) +* = (100*(2^15)*log2(x))/((2^15)*log2(10)) +* = ((200*(2^15)*log2(x))/((2^15)*log2(10)))/2 +* = ((200*(2^15)*(log2(x/y)+log2(y)))/((2^15)*log2(10)))/2 +* = ((200*(2^15)*log2(x/y))+(200*(2^15)*log2(y)))/((2^15)*log2(10)))/2 +* +* where y = 2^k and 1<= (x/y) < 2 +*/ + +static u32_t Log10Times100( u32_t x) +{ + static const u8_t scale=15; + static const u8_t indexWidth=5; + /* + log2lut[n] = (1<<scale) * 200 * log2( 1.0 + ( (1.0/(1<<INDEXWIDTH)) * n )) + 0 <= n < ((1<<INDEXWIDTH)+1) + */ + + static const u32_t log2lut[] = { + 0, /* 0.000000 */ + 290941, /* 290941.300628 */ + 573196, /* 573196.476418 */ + 847269, /* 847269.179851 */ + 1113620, /* 1113620.489452 */ + 1372674, /* 1372673.576986 */ + 1624818, /* 1624817.752104 */ + 1870412, /* 1870411.981536 */ + 2109788, /* 2109787.962654 */ + 2343253, /* 2343252.817465 */ + 2571091, /* 2571091.461923 */ + 2793569, /* 2793568.696416 */ + 3010931, /* 3010931.055901 */ + 3223408, /* 3223408.452106 */ + 3431216, /* 3431215.635215 */ + 3634553, /* 3634553.498355 */ + 3833610, /* 3833610.244726 */ + 4028562, /* 4028562.434393 */ + 4219576, /* 4219575.925308 */ + 4406807, /* 4406806.721144 */ + 4590402, /* 4590401.736809 */ + 4770499, /* 4770499.491025 */ + 4947231, /* 4947230.734179 */ + 5120719, /* 5120719.018555 */ + 5291081, /* 5291081.217197 */ + 5458428, /* 5458427.996830 */ + 5622864, /* 5622864.249668 */ + 5784489, /* 5784489.488298 */ + 5943398, /* 5943398.207380 */ + 6099680, /* 6099680.215452 */ + 6253421, /* 6253420.939751 */ + 6404702, /* 6404701.706649 */ + 6553600, /* 6553600.000000 */ + }; + + + u8_t i = 0; + u32_t y = 0; + u32_t d = 0; + u32_t k = 0; + u32_t r = 0; + + if (x==0) return (0); + + /* Scale x (normalize) */ + /* computing y in log(x/y) = log(x) - log(y) */ + if ( (x & (((u32_t)(-1))<<(scale+1)) ) == 0 ) + { + for (k = scale; k>0 ; k--) + { + if (x & (((u32_t)1)<<scale)) break; + x <<= 1; + } + } else { + for (k = scale; k<31 ; k++) + { + if ((x & (((u32_t)(-1))<<(scale+1)))==0) break; + x >>= 1; + } + } + /* + Now x has binary point between bit[scale] and bit[scale-1] + and 1.0 <= x < 2.0 */ + + /* correction for divison: log(x) = log(x/y)+log(y) */ + y = k * ( ( ((u32_t)1) << scale ) * 200 ); + + /* remove integer part */ + x &= ((((u32_t)1) << scale)-1); + /* get index */ + i = (u8_t) (x >> (scale -indexWidth)); + /* compute delta (x-a) */ + d = x & ((((u32_t)1) << (scale-indexWidth))-1); + /* compute log, multiplication ( d* (.. )) must be within range ! */ + y += log2lut[i] + (( d*( log2lut[i+1]-log2lut[i] ))>>(scale-indexWidth)); + /* Conver to log10() */ + y /= 108853; /* (log2(10) << scale) */ + r = (y>>1); + /* rounding */ + if (y&((u32_t)1)) r++; + + return (r); + +} + +/** +* \fn u32_t FracTimes1e6( u16_t N, u32_t D) +* \brief Compute: (N/D) * 1000000. +* \param N nominator 16-bits. +* \param D denominator 32-bits. +* \return u32_t +* \retval ((N/D) * 1000000), 32 bits +* +* No check on D=0! +*/ +static u32_t FracTimes1e6( u32_t N, u32_t D) +{ + u32_t remainder = 0; + u32_t frac = 0; + + /* + frac = (N * 1000000) / D + To let it fit in a 32 bits computation: + frac = (N * (1000000 >> 4)) / (D >> 4) + This would result in a problem in case D < 16 (div by 0). + So we do it more elaborate as shown below. + */ + frac = ( ((u32_t)N) * (1000000 >> 4) ) / D ; + frac <<= 4 ; + remainder = ( ((u32_t)N) * (1000000 >> 4) ) % D ; + remainder <<= 4; + frac += remainder / D; + remainder = remainder % D ; + if( (remainder * 2) > D ) + { + frac++; + } + + return ( frac ); +} + +/*============================================================================*/ + +/** +* \brief Compute: 100 * 10^( GdB / 200 ). +* \param u32_t GdB Gain in 0.1dB +* \return u32_t Gainfactor in 0.01 resolution +* +*/ +static u32_t dB2LinTimes100( u32_t GdB ) +{ + u32_t result = 0; + u32_t nr6dBSteps = 0; + u32_t remainder = 0; + u32_t remainderFac = 0; + + /* start with factors 2 (6.02dB) */ + nr6dBSteps = GdB * 1000UL / 60206UL; + if ( nr6dBSteps > 17 ) + { + /* Result max overflow if > log2( maxu32 / 2e4 ) ~= 17.7 */ + return MAX_U32; + } + result = (1<<nr6dBSteps); + + /* calculate remaining factor, + poly approximation of 10^(GdB/200): + + y = 1E-04x2 + 0.0106x + 1.0026 + + max deviation < 0.005 for range x = [0 ... 60] + */ + remainder = ( ( GdB * 1000UL ) % 60206UL ) / 1000UL; + /* using 1e-4 for poly calculation */ + remainderFac = 1 * remainder * remainder; + remainderFac += 106 * remainder; + remainderFac += 10026; + + /* multiply by remaining factor */ + result *= remainderFac; + + /* conversion from 1e-4 to 1e-2 */ + return ( (result + 50 ) / 100); +} + + +#ifndef DRXJ_DIGITAL_ONLY +#define FRAC_FLOOR 0 +#define FRAC_CEIL 1 +#define FRAC_ROUND 2 +/** +* \fn u32_t Frac( u32_t N, u32_t D, u16_t RC ) +* \brief Compute: N/D. +* \param N nominator 32-bits. +* \param D denominator 32-bits. +* \param RC-result correction: 0-floor; 1-ceil; 2-round +* \return u32_t +* \retval N/D, 32 bits +* +* If D=0 returns 0 +*/ +static u32_t Frac( u32_t N, u32_t D, u16_t RC ) +{ + u32_t remainder = 0; + u32_t frac = 0; + u16_t bitCnt = 32; + + if ( D == 0 ) + { + frac = 0; + remainder = 0; + + return ( frac ); + } + + if ( D > N ) + { + frac = 0; + remainder = N; + } + else + { + remainder = 0; + frac = N; + while ( bitCnt-- > 0 ) + { + remainder <<= 1; + remainder |= ( ( frac & 0x80000000 ) >> 31 ); + frac <<= 1; + if ( remainder < D ) + { + frac &= 0xFFFFFFFE; + } + else + { + remainder -= D; + frac |= 0x1; + } + } + + /* result correction if needed */ + if ( ( RC == FRAC_CEIL ) && ( remainder != 0 ) ) + { + /* ceil the result */ + /*(remainder is not zero -> value behind decimal point exists) */ + frac++; + } + if ( ( RC == FRAC_ROUND ) && ( remainder >= D>>1 ) ) + { + /* remainder is bigger from D/2 -> round the result */ + frac++; + } + } + + return ( frac ); +} +#endif + +#ifdef DRXJ_SPLIT_UCODE_UPLOAD +/*============================================================================*/ + +/** +* \fn u16_t UCodeRead16( pu8_t addr) +* \brief Read a 16 bits word, expect big endian data. +* \return u16_t The data read. +*/ +static u16_t +UCodeRead16( pu8_t addr) +{ + /* Works fo any host processor */ + + u16_t word=0; + + word = ((u16_t)addr[0]); + word <<= 8; + word |=((u16_t)addr[1]); + + return ( word ); +} + +/*============================================================================*/ + +/** +* \fn u32_t UCodeRead32( pu8_t addr) +* \brief Read a 32 bits word, expect big endian data. +* \return u32_t The data read. +*/ +static u32_t +UCodeRead32( pu8_t addr) +{ + /* Works fo any host processor */ + + u32_t word=0; + + word = ((u16_t)addr[0]); + word <<= 8; + word |= ((u16_t)addr[1]); + word <<= 8; + word |= ((u16_t)addr[2]); + word <<= 8; + word |= ((u16_t)addr[3]); + + return ( word ); +} + +/*============================================================================*/ + +/** +* \fn u16_t UCodeComputeCRC (pu8_t blockData, u16_t nrWords) +* \brief Compute CRC of block of microcode data. +* \param blockData Pointer to microcode data. +* \param nrWords Size of microcode block (number of 16 bits words). +* \return u16_t The computed CRC residu. +*/ +static u16_t +UCodeComputeCRC (pu8_t blockData, u16_t nrWords) +{ + u16_t i = 0; + u16_t j = 0; + u32_t CRCWord=0; + u32_t carry=0; + + while (i < nrWords) { + CRCWord |= (u32_t) UCodeRead16(blockData); + for (j = 0; j < 16; j++) + { + CRCWord <<= 1; + if (carry != 0) + CRCWord ^= 0x80050000UL; + carry = CRCWord & 0x80000000UL; + } + i++; + blockData+=(sizeof(u16_t)); + } + return ((u16_t) (CRCWord >> 16)); +} +#endif /* DRXJ_SPLIT_UCODE_UPLOAD */ + +/** +* \brief Values for NICAM prescaler gain. Computed from dB to integer +* and rounded. For calc used formula: 16*10^(prescaleGain[dB]/20). +* +*/ +static const u16_t NicamPrescTableVal[43] = { 1,1,1,1,2,2,2,2,3,3,3,4,4, + 5,5,6,6,7,8,9,10,11,13,14,16, + 18,20,23,25,28,32,36,40,45, + 51,57,64,71,80,90,101,113,127 + }; + +/*============================================================================*/ +/*== END HELPER FUNCTIONS ==*/ +/*============================================================================*/ + + +/*============================================================================*/ +/*============================================================================*/ +/*== DRXJ DAP FUNCTIONS ==*/ +/*============================================================================*/ +/*============================================================================*/ + +/* + This layer takes care of some device specific register access protocols: + -conversion to short address format + -access to audio block + This layer is placed between the drx_dap_fasi and the rest of the drxj + specific implementation. This layer can use address map knowledge whereas + dap_fasi may not use memory map knowledge. + + * For audio currently only 16 bits read and write register access is + supported. More is not needed. RMW and 32 or 8 bit access on audio + registers will have undefined behaviour. Flags (RMW, CRC reset, broadcast + single/multi master) will be ignored. + + + TODO: check ignoring single/multimaster is ok for AUD access ? +*/ + +#define DRXJ_ISAUDWRITE( addr ) (((((addr)>>16)&1)==1)?TRUE:FALSE) +#define DRXJ_DAP_AUDTRIF_TIMEOUT 80 /* millisec */ +/*============================================================================*/ + +/** +* \fn Bool_t IsHandledByAudTrIf( DRXaddr_t addr ) +* \brief Check if this address is handled by the audio token ring interface. +* \param addr +* \return Bool_t +* \retval TRUE Yes, handled by audio token ring interface +* \retval FALSE No, not handled by audio token ring interface +* +*/ +static +Bool_t IsHandledByAudTrIf( DRXaddr_t addr ) +{ + Bool_t retval = FALSE; + + if ( (DRXDAP_FASI_ADDR2BLOCK( addr ) == 4) && + ( DRXDAP_FASI_ADDR2BANK( addr) > 1 ) && + ( DRXDAP_FASI_ADDR2BANK( addr) < 6 ) ) + { + retval=TRUE; + } + + return (retval); +} + +/*============================================================================*/ + +static DRXStatus_t DRXJ_DAP_ReadBlock ( + pI2CDeviceAddr_t devAddr, + DRXaddr_t addr, + u16_t datasize, + pu8_t data, + DRXflags_t flags) +{ + return drxDapFASIFunct_g.readBlockFunc( devAddr, + addr, + datasize, + data, + flags); +} + +/*============================================================================*/ + +static DRXStatus_t DRXJ_DAP_ReadModifyWriteReg8 ( + pI2CDeviceAddr_t devAddr, + DRXaddr_t waddr, + DRXaddr_t raddr, + u8_t wdata, + pu8_t rdata) +{ + return drxDapFASIFunct_g.readModifyWriteReg8Func( devAddr, + waddr, + raddr, + wdata, + rdata); +} + +/*============================================================================*/ + +/** +* \fn DRXStatus_t DRXJ_DAP_RMWriteReg16Short +* \brief Read modify write 16 bits audio register using short format only. +* \param devAddr +* \param waddr Address to write to +* \param raddr Address to read from (usually SIO_HI_RA_RAM_S0_RMWBUF__A) +* \param wdata Data to write +* \param rdata Buffer for data to read +* \return DRXStatus_t +* \retval DRX_STS_OK Succes +* \retval DRX_STS_ERROR Timeout, I2C error, illegal bank +* +* 16 bits register read modify write access using short addressing format only. +* Requires knowledge of the registermap, thus device dependent. +* Using DAP FASI directly to avoid endless recursion of RMWs to audio registers. +* +*/ + +/* TODO correct define should be #if ( DRXDAPFASI_SHORT_ADDR_ALLOWED==1 ) + See comments DRXJ_DAP_ReadModifyWriteReg16 */ +#if ( DRXDAPFASI_LONG_ADDR_ALLOWED == 0 ) +static DRXStatus_t DRXJ_DAP_RMWriteReg16Short ( + pI2CDeviceAddr_t devAddr, + DRXaddr_t waddr, + DRXaddr_t raddr, + u16_t wdata, + pu16_t rdata) +{ + DRXStatus_t rc; + + if (rdata == NULL) + { + return DRX_STS_INVALID_ARG; + } + + /* Set RMW flag */ + rc = drxDapFASIFunct_g.writeReg16Func (devAddr, + SIO_HI_RA_RAM_S0_FLG_ACC__A, + SIO_HI_RA_RAM_S0_FLG_ACC_S0_RWM__M, + 0x0000); + if (rc == DRX_STS_OK) + { + /* Write new data: triggers RMW */ + rc = drxDapFASIFunct_g.writeReg16Func (devAddr, waddr, wdata, 0x0000 ); + } + if (rc == DRX_STS_OK) + { + /* Read old data */ + rc = drxDapFASIFunct_g.readReg16Func (devAddr, raddr, rdata, 0x0000 ); + } + if (rc == DRX_STS_OK) + { + /* Reset RMW flag */ + rc = drxDapFASIFunct_g.writeReg16Func (devAddr, + SIO_HI_RA_RAM_S0_FLG_ACC__A, + 0, + 0x0000); + } + + return rc; +} +#endif + +/*============================================================================*/ + +static DRXStatus_t DRXJ_DAP_ReadModifyWriteReg16 ( + pI2CDeviceAddr_t devAddr, + DRXaddr_t waddr, + DRXaddr_t raddr, + u16_t wdata, + pu16_t rdata) +{ + /* TODO: correct short/long addressing format decision, + now long format has higher prio then short because short also + needs virt bnks (not impl yet) for certain audio registers */ +#if ( DRXDAPFASI_LONG_ADDR_ALLOWED==1 ) + return drxDapFASIFunct_g.readModifyWriteReg16Func( devAddr, + waddr, + raddr, + wdata, + rdata); +#else + return DRXJ_DAP_RMWriteReg16Short( devAddr, + waddr, + raddr, + wdata, + rdata); +#endif +} + +/*============================================================================*/ + +static DRXStatus_t DRXJ_DAP_ReadModifyWriteReg32 ( + pI2CDeviceAddr_t devAddr, + DRXaddr_t waddr, + DRXaddr_t raddr, + u32_t wdata, + pu32_t rdata) +{ + return drxDapFASIFunct_g.readModifyWriteReg32Func( devAddr, + waddr, + raddr, + wdata, + rdata); +} + +/*============================================================================*/ + +static DRXStatus_t DRXJ_DAP_ReadReg8 ( + pI2CDeviceAddr_t devAddr, + DRXaddr_t addr, + pu8_t data, + DRXflags_t flags) +{ + return drxDapFASIFunct_g.readReg8Func( devAddr, + addr, + data, + flags); +} + +/*============================================================================*/ + +/** +* \fn DRXStatus_t DRXJ_DAP_ReadAudReg16 +* \brief Read 16 bits audio register +* \param devAddr +* \param addr +* \param data +* \return DRXStatus_t +* \retval DRX_STS_OK Succes +* \retval DRX_STS_ERROR Timeout, I2C error, illegal bank +* +* 16 bits register read access via audio token ring interface. +* +*/ +static DRXStatus_t DRXJ_DAP_ReadAudReg16 ( + pI2CDeviceAddr_t devAddr, + DRXaddr_t addr, + pu16_t data) +{ + u32_t startTimer = 0; + u32_t currentTimer = 0; + u32_t deltaTimer = 0; + u16_t trStatus = 0; + DRXStatus_t stat = DRX_STS_ERROR; + + /* No read possible for bank 3, return with error */ + if ( DRXDAP_FASI_ADDR2BANK(addr) == 3 ) + { + stat=DRX_STS_INVALID_ARG; + } else { + const DRXaddr_t writeBit = ((DRXaddr_t)1)<<16; + + /* Force reset write bit */ + addr &= (~writeBit); + + /* Set up read */ + startTimer = DRXBSP_HST_Clock(); + do { + /* RMW to aud TR IF until request is granted or timeout */ + stat = DRXJ_DAP_ReadModifyWriteReg16( devAddr, + addr, + SIO_HI_RA_RAM_S0_RMWBUF__A, + 0x0000, + &trStatus); + + if ( stat != DRX_STS_OK ) + { + break; + }; + + currentTimer = DRXBSP_HST_Clock(); + deltaTimer = currentTimer - startTimer; + if ( deltaTimer > DRXJ_DAP_AUDTRIF_TIMEOUT ) + { + stat = DRX_STS_ERROR; + break; + }; + + } while ( ( ( trStatus & AUD_TOP_TR_CTR_FIFO_LOCK__M ) == + AUD_TOP_TR_CTR_FIFO_LOCK_LOCKED ) || + ( ( trStatus & AUD_TOP_TR_CTR_FIFO_FULL__M ) == + AUD_TOP_TR_CTR_FIFO_FULL_FULL ) ); + } /* if ( DRXDAP_FASI_ADDR2BANK(addr)!=3 ) */ + + /* Wait for read ready status or timeout */ + if ( stat == DRX_STS_OK ) + { + startTimer = DRXBSP_HST_Clock(); + + while ( ( trStatus & AUD_TOP_TR_CTR_FIFO_RD_RDY__M) != + AUD_TOP_TR_CTR_FIFO_RD_RDY_READY) + { + stat = DRXJ_DAP_ReadReg16( devAddr, + AUD_TOP_TR_CTR__A, + &trStatus, + 0x0000); + if ( stat != DRX_STS_OK ) + { + break; + }; + + currentTimer = DRXBSP_HST_Clock(); + deltaTimer = currentTimer - startTimer; + if ( deltaTimer > DRXJ_DAP_AUDTRIF_TIMEOUT ) + { + stat = DRX_STS_ERROR; + break; + }; + } /* while ( ... ) */ + } /* if { stat == DRX_STS_OK ) */ + + /* Read value */ + if ( stat == DRX_STS_OK ) + { + stat = DRXJ_DAP_ReadModifyWriteReg16( devAddr, + AUD_TOP_TR_RD_REG__A, + SIO_HI_RA_RAM_S0_RMWBUF__A, + 0x0000, + data); + } /* if { stat == DRX_STS_OK ) */ + + return stat; +} + +/*============================================================================*/ + +static DRXStatus_t DRXJ_DAP_ReadReg16 ( + pI2CDeviceAddr_t devAddr, + DRXaddr_t addr, + pu16_t data, + DRXflags_t flags) +{ + DRXStatus_t stat = DRX_STS_ERROR; + + /* Check param */ + if ( ( devAddr == NULL ) || ( data == NULL ) ) + { + return DRX_STS_INVALID_ARG; + } + + if ( IsHandledByAudTrIf(addr) ) + { + stat = DRXJ_DAP_ReadAudReg16 (devAddr, + addr, + data); + } else { + stat = drxDapFASIFunct_g.readReg16Func( devAddr, + addr, + data, + flags); + } + + return stat; +} + +/*============================================================================*/ + +static DRXStatus_t DRXJ_DAP_ReadReg32 ( + pI2CDeviceAddr_t devAddr, + DRXaddr_t addr, + pu32_t data, + DRXflags_t flags) +{ + return drxDapFASIFunct_g.readReg32Func( devAddr, + addr, + data, + flags); +} + +/*============================================================================*/ + +static DRXStatus_t DRXJ_DAP_WriteBlock ( + pI2CDeviceAddr_t devAddr, + DRXaddr_t addr, + u16_t datasize, + pu8_t data, + DRXflags_t flags) +{ + return drxDapFASIFunct_g.writeBlockFunc( devAddr, + addr, + datasize, + data, + flags); +} + +/*============================================================================*/ + +static DRXStatus_t DRXJ_DAP_WriteReg8 ( + pI2CDeviceAddr_t devAddr, + DRXaddr_t addr, + u8_t data, + DRXflags_t flags) +{ + return drxDapFASIFunct_g.writeReg8Func( devAddr, + addr, + data, + flags); +} + +/*============================================================================*/ + +/** +* \fn DRXStatus_t DRXJ_DAP_WriteAudReg16 +* \brief Write 16 bits audio register +* \param devAddr +* \param addr +* \param data +* \return DRXStatus_t +* \retval DRX_STS_OK Succes +* \retval DRX_STS_ERROR Timeout, I2C error, illegal bank +* +* 16 bits register write access via audio token ring interface. +* +*/ +static DRXStatus_t DRXJ_DAP_WriteAudReg16 ( + pI2CDeviceAddr_t devAddr, + DRXaddr_t addr, + u16_t data) +{ + DRXStatus_t stat = DRX_STS_ERROR; + + /* No write possible for bank 2, return with error */ + if ( DRXDAP_FASI_ADDR2BANK(addr) == 2 ) + { + stat=DRX_STS_INVALID_ARG; + } else { + u32_t startTimer = 0; + u32_t currentTimer = 0; + u32_t deltaTimer = 0; + u16_t trStatus = 0; + const DRXaddr_t writeBit = ((DRXaddr_t)1)<<16; + + /* Force write bit */ + addr |= writeBit; + startTimer = DRXBSP_HST_Clock(); + do { + /* RMW to aud TR IF until request is granted or timeout */ + stat = DRXJ_DAP_ReadModifyWriteReg16( devAddr, + addr, + SIO_HI_RA_RAM_S0_RMWBUF__A, + data, + &trStatus); + if ( stat != DRX_STS_OK ) + { + break; + }; + + currentTimer = DRXBSP_HST_Clock(); + deltaTimer = currentTimer - startTimer; + if ( deltaTimer > DRXJ_DAP_AUDTRIF_TIMEOUT ) + { + stat = DRX_STS_ERROR; + break; + }; + + } while ( ( ( trStatus & AUD_TOP_TR_CTR_FIFO_LOCK__M ) == + AUD_TOP_TR_CTR_FIFO_LOCK_LOCKED ) || + ( ( trStatus & AUD_TOP_TR_CTR_FIFO_FULL__M ) == + AUD_TOP_TR_CTR_FIFO_FULL_FULL ) ); + + } /* if ( DRXDAP_FASI_ADDR2BANK(addr)!=2 ) */ + + return stat; +} + +/*============================================================================*/ + +static DRXStatus_t DRXJ_DAP_WriteReg16 ( + pI2CDeviceAddr_t devAddr, + DRXaddr_t addr, + u16_t data, + DRXflags_t flags) +{ + DRXStatus_t stat=DRX_STS_ERROR; + + /* Check param */ + if ( devAddr == NULL ) + { + return DRX_STS_INVALID_ARG; + } + + + if ( IsHandledByAudTrIf(addr) ) + { + stat = DRXJ_DAP_WriteAudReg16 (devAddr, + addr, + data); + } else { + stat = drxDapFASIFunct_g.writeReg16Func( devAddr, + addr, + data, + flags); + } + + return stat; +} + +/*============================================================================*/ + +static DRXStatus_t DRXJ_DAP_WriteReg32 ( + pI2CDeviceAddr_t devAddr, + DRXaddr_t addr, + u32_t data, + DRXflags_t flags) +{ + return drxDapFASIFunct_g.writeReg32Func( devAddr, + addr, + data, + flags); +} + +/*============================================================================*/ + +/* Free data ram in SIO HI */ +#define SIO_HI_RA_RAM_USR_BEGIN__A 0x420040 +#define SIO_HI_RA_RAM_USR_END__A 0x420060 + +#define DRXJ_HI_ATOMIC_BUF_START (SIO_HI_RA_RAM_USR_BEGIN__A) +#define DRXJ_HI_ATOMIC_BUF_END (SIO_HI_RA_RAM_USR_BEGIN__A + 7) +#define DRXJ_HI_ATOMIC_READ SIO_HI_RA_RAM_PAR_3_ACP_RW_READ +#define DRXJ_HI_ATOMIC_WRITE SIO_HI_RA_RAM_PAR_3_ACP_RW_WRITE + +/** +* \fn DRXStatus_t DRXJ_DAP_AtomicReadWriteBlock() +* \brief Basic access routine for atomic read or write access +* \param devAddr pointer to i2c dev address +* \param addr destination/source address +* \param datasize size of data buffer in bytes +* \param data pointer to data buffer +* \return DRXStatus_t +* \retval DRX_STS_OK Succes +* \retval DRX_STS_ERROR Timeout, I2C error, illegal bank +* +*/ +static +DRXStatus_t DRXJ_DAP_AtomicReadWriteBlock ( + pI2CDeviceAddr_t devAddr, + DRXaddr_t addr, + u16_t datasize, + pu8_t data, + Bool_t readFlag) +{ + DRXJHiCmd_t hiCmd; + + u16_t word; + u16_t dummy=0; + u16_t i=0; + + /* Parameter check */ + if ( ( data == NULL ) || + ( devAddr == NULL ) || + ( (datasize%2)!= 0 ) || + ( (datasize/2) > 8 ) + ) + { + return (DRX_STS_INVALID_ARG); + } + + /* Set up HI parameters to read or write n bytes */ + hiCmd.cmd = SIO_HI_RA_RAM_CMD_ATOMIC_COPY; + hiCmd.param1 = + (u16_t)(( DRXDAP_FASI_ADDR2BLOCK( DRXJ_HI_ATOMIC_BUF_START ) << 6 ) + + DRXDAP_FASI_ADDR2BANK( DRXJ_HI_ATOMIC_BUF_START ) ); + hiCmd.param2 = (u16_t)DRXDAP_FASI_ADDR2OFFSET( DRXJ_HI_ATOMIC_BUF_START ); + hiCmd.param3 = (u16_t)((datasize/2) - 1); + if ( readFlag == FALSE ) + { + hiCmd.param3 |= DRXJ_HI_ATOMIC_WRITE; + } else { + hiCmd.param3 |= DRXJ_HI_ATOMIC_READ; + } + hiCmd.param4 = (u16_t) ( ( DRXDAP_FASI_ADDR2BLOCK(addr) << 6 ) + + DRXDAP_FASI_ADDR2BANK(addr) ); + hiCmd.param5 = (u16_t)DRXDAP_FASI_ADDR2OFFSET(addr); + + if ( readFlag == FALSE ) + { + /* write data to buffer */ + for (i = 0; i < (datasize/2); i++) + { + + + word = ((u16_t)data[2*i]); + word += (((u16_t)data[(2*i)+1])<<8); + DRXJ_DAP_WriteReg16 (devAddr, (DRXJ_HI_ATOMIC_BUF_START + i), word, 0); + } + } + + CHK_ERROR( HICommand( devAddr, &hiCmd, &dummy) ); + + if ( readFlag == TRUE ) + { + /* read data from buffer */ + for (i = 0; i < (datasize/2); i++) + { + DRXJ_DAP_ReadReg16 (devAddr, (DRXJ_HI_ATOMIC_BUF_START + i), &word, 0); + data[2*i] = (u8_t) (word & 0xFF); + data[(2*i) + 1] = (u8_t) (word >> 8 ); + } + } + + return DRX_STS_OK; + + rw_error: + return (DRX_STS_ERROR); + +} + +/*============================================================================*/ + +/** +* \fn DRXStatus_t DRXJ_DAP_AtomicReadReg32() +* \brief Atomic read of 32 bits words +*/ +static +DRXStatus_t DRXJ_DAP_AtomicReadReg32 ( + pI2CDeviceAddr_t devAddr, + DRXaddr_t addr, + pu32_t data, + DRXflags_t flags) +{ + u8_t buf[sizeof (*data)]; + DRXStatus_t rc = DRX_STS_ERROR; + u32_t word = 0; + + if (!data) + { + return DRX_STS_INVALID_ARG; + } + + rc = DRXJ_DAP_AtomicReadWriteBlock ( devAddr, addr, + sizeof (*data), buf, TRUE); + + word = (u32_t)buf[3]; + word <<= 8; + word |= (u32_t)buf[2]; + word <<= 8; + word |= (u32_t)buf[1]; + word <<= 8; + word |= (u32_t)buf[0]; + + *data = word; + + return rc; +} + + +/*============================================================================*/ + + +/*============================================================================*/ +/*== END DRXJ DAP FUNCTIONS ==*/ +/*============================================================================*/ + +/*============================================================================*/ +/*============================================================================*/ +/*== HOST INTERFACE FUNCTIONS ==*/ +/*============================================================================*/ +/*============================================================================*/ + +/** +* \fn DRXStatus_t HICfgCommand() +* \brief Configure HI with settings stored in the demod structure. +* \param demod Demodulator. +* \return DRXStatus_t. +* +* This routine was created because to much orthogonal settings have +* been put into one HI API function (configure). Especially the I2C bridge +* enable/disable should not need re-configuration of the HI. +* +*/ +static DRXStatus_t +HICfgCommand(const pDRXDemodInstance_t demod) +{ + pDRXJData_t extAttr = (pDRXJData_t)(NULL); + DRXJHiCmd_t hiCmd; + u16_t result=0; + + extAttr = (pDRXJData_t)demod -> myExtAttr; + + hiCmd.cmd = SIO_HI_RA_RAM_CMD_CONFIG; + hiCmd.param1 = SIO_HI_RA_RAM_PAR_1_PAR1_SEC_KEY; + hiCmd.param2 = extAttr -> HICfgTimingDiv; + hiCmd.param3 = extAttr -> HICfgBridgeDelay; + hiCmd.param4 = extAttr -> HICfgWakeUpKey; + hiCmd.param5 = extAttr -> HICfgCtrl; + hiCmd.param6 = extAttr -> HICfgTransmit; + + CHK_ERROR( HICommand( demod -> myI2CDevAddr, &hiCmd, &result) ); + + /* Reset power down flag (set one call only) */ + extAttr -> HICfgCtrl &= (~(SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ)); + + return (DRX_STS_OK); + + rw_error: + return (DRX_STS_ERROR); +} + +/** +* \fn DRXStatus_t HICommand() +* \brief Configure HI with settings stored in the demod structure. +* \param devAddr I2C address. +* \param cmd HI command. +* \param result HI command result. +* \return DRXStatus_t. +* +* Sends command to HI +* +*/ +static DRXStatus_t +HICommand(const pI2CDeviceAddr_t devAddr, + const pDRXJHiCmd_t cmd, + pu16_t result) +{ + u16_t waitCmd=0; + u16_t nrRetries = 0; + Bool_t powerdown_cmd = FALSE; + + + /* Write parameters */ + switch ( cmd->cmd ) { + + case SIO_HI_RA_RAM_CMD_CONFIG: + case SIO_HI_RA_RAM_CMD_ATOMIC_COPY: + WR16(devAddr, SIO_HI_RA_RAM_PAR_6__A, cmd->param6); + WR16(devAddr, SIO_HI_RA_RAM_PAR_5__A, cmd->param5); + WR16(devAddr, SIO_HI_RA_RAM_PAR_4__A, cmd->param4); + WR16(devAddr, SIO_HI_RA_RAM_PAR_3__A, cmd->param3); + /* fallthrough */ + case SIO_HI_RA_RAM_CMD_BRDCTRL: + WR16(devAddr, SIO_HI_RA_RAM_PAR_2__A, cmd->param2); + WR16(devAddr, SIO_HI_RA_RAM_PAR_1__A, cmd->param1); + /* fallthrough */ + case SIO_HI_RA_RAM_CMD_NULL: + /* No parameters */ + break; + + default: + return (DRX_STS_INVALID_ARG); + break; + } + + /* Write command */ + WR16(devAddr, SIO_HI_RA_RAM_CMD__A, cmd->cmd); + + if ( (cmd->cmd) == SIO_HI_RA_RAM_CMD_RESET ) + { + /* Allow for HI to reset */ + DRXBSP_HST_Sleep(1); + } + + /* Detect power down to ommit reading result */ + powerdown_cmd = (Bool_t)( ( cmd->cmd == SIO_HI_RA_RAM_CMD_CONFIG ) && + ( ((cmd->param5) & SIO_HI_RA_RAM_PAR_5_CFG_SLEEP__M) == + SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ ) ); + if ( powerdown_cmd == FALSE ) + { + /* Wait until command rdy */ + do + { + nrRetries++; + if ( nrRetries > DRXJ_MAX_RETRIES ) + { + goto rw_error; + }; + + RR16(devAddr, SIO_HI_RA_RAM_CMD__A, &waitCmd); + } while ( waitCmd != 0 ); + + /* Read result */ + RR16(devAddr, SIO_HI_RA_RAM_RES__A, result); + + } /* if ( powerdown_cmd == TRUE ) */ + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} + +/** +* \fn DRXStatus_t InitHI( const pDRXDemodInstance_t demod ) +* \brief Initialise and configurate HI. +* \param demod pointer to demod data. +* \return DRXStatus_t Return status. +* \retval DRX_STS_OK Success. +* \retval DRX_STS_ERROR Failure. +* +* Needs to know Psys (System Clock period) and Posc (Osc Clock period) +* Need to store configuration in driver because of the way I2C +* bridging is controlled. +* +*/ +static DRXStatus_t +InitHI( const pDRXDemodInstance_t demod ) +{ + pDRXJData_t extAttr =(pDRXJData_t)(NULL); + pDRXCommonAttr_t commonAttr =(pDRXCommonAttr_t)(NULL); + pI2CDeviceAddr_t devAddr =(pI2CDeviceAddr_t)(NULL); + + extAttr = (pDRXJData_t) demod -> myExtAttr; + commonAttr = (pDRXCommonAttr_t) demod -> myCommonAttr; + devAddr = demod -> myI2CDevAddr; + + /* PATCH for bug 5003, HI ucode v3.1.0 */ + WR16( devAddr, 0x4301D7, 0x801 ); + + /* Timing div, 250ns/Psys */ + /* Timing div, = ( delay (nano seconds) * sysclk (kHz) )/ 1000 */ + extAttr -> HICfgTimingDiv = + (u16_t)((commonAttr->sysClockFreq/1000)* HI_I2C_DELAY)/1000 ; + /* Clipping */ + if ( (extAttr -> HICfgTimingDiv) > SIO_HI_RA_RAM_PAR_2_CFG_DIV__M ) + { + extAttr -> HICfgTimingDiv = SIO_HI_RA_RAM_PAR_2_CFG_DIV__M; + } + /* Bridge delay, uses oscilator clock */ + /* Delay = ( delay (nano seconds) * oscclk (kHz) )/ 1000 */ + /* SDA brdige delay */ + extAttr -> HICfgBridgeDelay = + (u16_t)((commonAttr->oscClockFreq/1000)* HI_I2C_BRIDGE_DELAY)/1000 ; + /* Clipping */ + if ( (extAttr -> HICfgBridgeDelay) > SIO_HI_RA_RAM_PAR_3_CFG_DBL_SDA__M ) + { + extAttr -> HICfgBridgeDelay = SIO_HI_RA_RAM_PAR_3_CFG_DBL_SDA__M; + } + /* SCL bridge delay, same as SDA for now */ + extAttr -> HICfgBridgeDelay += ((extAttr -> HICfgBridgeDelay)<< + SIO_HI_RA_RAM_PAR_3_CFG_DBL_SCL__B); + /* Wakeup key, setting the read flag (as suggest in the documentation) does + not always result into a working solution (barebones worked VI2C failed). + Not setting the bit works in all cases . */ + extAttr -> HICfgWakeUpKey = DRXJ_WAKE_UP_KEY; + /* port/bridge/power down ctrl */ + extAttr -> HICfgCtrl = ( SIO_HI_RA_RAM_PAR_5_CFG_SLV0_SLAVE ); + /* transit mode time out delay and watch dog divider */ + extAttr ->HICfgTransmit = SIO_HI_RA_RAM_PAR_6__PRE; + + CHK_ERROR( HICfgCommand( demod ) ); + + return (DRX_STS_OK); + + rw_error: + return (DRX_STS_ERROR); +} + + +/*============================================================================*/ +/*== END HOST INTERFACE FUNCTIONS ==*/ +/*============================================================================*/ + +/*============================================================================*/ +/*============================================================================*/ +/*== AUXILIARY FUNCTIONS ==*/ +/*============================================================================*/ +/*============================================================================*/ + +/** +* \fn DRXStatus_t GetDeviceCapabilities() +* \brief Get and store device capabilities. +* \param demod Pointer to demodulator instance. +* \return DRXStatus_t. +* \return DRX_STS_OK Success +* \retval DRX_STS_ERROR Failure +* +* Depending on pulldowns on MDx pins the following internals are set: +* * commonAttr->oscClockFreq +* * extAttr->hasLNA +* * extAttr->hasNTSC +* * extAttr->hasBTSC +* * extAttr->hasOOB +* +*/ +static DRXStatus_t +GetDeviceCapabilities( pDRXDemodInstance_t demod ) +{ + pDRXCommonAttr_t commonAttr = (pDRXCommonAttr_t)(NULL); + pDRXJData_t extAttr = (pDRXJData_t)NULL; + pI2CDeviceAddr_t devAddr = (pI2CDeviceAddr_t)(NULL); + u16_t sioPdrOhwCfg = 0; + u32_t sioTopJtagidLo = 0; + u16_t bid = 0; + + commonAttr = (pDRXCommonAttr_t) demod -> myCommonAttr; + extAttr = (pDRXJData_t) demod -> myExtAttr; + devAddr = demod -> myI2CDevAddr; + + WR16 ( devAddr, SIO_TOP_COMM_KEY__A , SIO_TOP_COMM_KEY_KEY); + RR16 ( devAddr, SIO_PDR_OHW_CFG__A , &sioPdrOhwCfg); + WR16 ( devAddr, SIO_TOP_COMM_KEY__A , SIO_TOP_COMM_KEY__PRE); + + switch ( (sioPdrOhwCfg & SIO_PDR_OHW_CFG_FREF_SEL__M ) ) + { + case 0: + /* ignore (bypass ?)*/ + break; + case 1: + /* 27 MHz */ + commonAttr->oscClockFreq = 27000; + break; + case 2: + /* 20.25 MHz */ + commonAttr->oscClockFreq = 20250; + break; + case 3: + /* 4 MHz */ + commonAttr->oscClockFreq = 4000; + break; + default: + return (DRX_STS_ERROR); + } + + /* + Determine device capabilities + Based on pinning v47 + */ + RR32( devAddr, SIO_TOP_JTAGID_LO__A , &sioTopJtagidLo); + extAttr->mfx = (u8_t)((sioTopJtagidLo>>29)&0xF) ; + + switch ((sioTopJtagidLo>>12)&0xFF) + { + case 0x31: + WR16( devAddr, SIO_TOP_COMM_KEY__A , SIO_TOP_COMM_KEY_KEY); + RR16( devAddr, SIO_PDR_UIO_IN_HI__A , &bid); + bid = (bid >> 10) & 0xf; + WR16( devAddr, SIO_TOP_COMM_KEY__A , SIO_TOP_COMM_KEY__PRE); + + extAttr->hasLNA = TRUE; + extAttr->hasNTSC = FALSE; + extAttr->hasBTSC = FALSE; + extAttr->hasOOB = FALSE; + extAttr->hasSMATX = TRUE; + extAttr->hasSMARX = FALSE; + extAttr->hasGPIO = FALSE; + extAttr->hasIRQN = FALSE; + break; + case 0x33: + extAttr->hasLNA = FALSE; + extAttr->hasNTSC = FALSE; + extAttr->hasBTSC = FALSE; + extAttr->hasOOB = FALSE; + extAttr->hasSMATX = TRUE; + extAttr->hasSMARX = FALSE; + extAttr->hasGPIO = FALSE; + extAttr->hasIRQN = FALSE; + break; + case 0x45: + extAttr->hasLNA = TRUE; + extAttr->hasNTSC = TRUE; + extAttr->hasBTSC = FALSE; + extAttr->hasOOB = FALSE; + extAttr->hasSMATX = TRUE; + extAttr->hasSMARX = TRUE; + extAttr->hasGPIO = TRUE; + extAttr->hasIRQN = FALSE; + break; + case 0x46: + extAttr->hasLNA = FALSE; + extAttr->hasNTSC = TRUE; + extAttr->hasBTSC = FALSE; + extAttr->hasOOB = FALSE; + extAttr->hasSMATX = TRUE; + extAttr->hasSMARX = TRUE; + extAttr->hasGPIO = TRUE; + extAttr->hasIRQN = FALSE; + break; + case 0x41: + extAttr->hasLNA = TRUE; + extAttr->hasNTSC = TRUE; + extAttr->hasBTSC = TRUE; + extAttr->hasOOB = FALSE; + extAttr->hasSMATX = TRUE; + extAttr->hasSMARX = TRUE; + extAttr->hasGPIO = TRUE; + extAttr->hasIRQN = FALSE; + break; + case 0x43: + extAttr->hasLNA = FALSE; + extAttr->hasNTSC = TRUE; + extAttr->hasBTSC = TRUE; + extAttr->hasOOB = FALSE; + extAttr->hasSMATX = TRUE; + extAttr->hasSMARX = TRUE; + extAttr->hasGPIO = TRUE; + extAttr->hasIRQN = FALSE; + break; + case 0x32: + extAttr->hasLNA = TRUE; + extAttr->hasNTSC = FALSE; + extAttr->hasBTSC = FALSE; + extAttr->hasOOB = TRUE; + extAttr->hasSMATX = TRUE; + extAttr->hasSMARX = TRUE; + extAttr->hasGPIO = TRUE; + extAttr->hasIRQN = TRUE; + break; + case 0x34: + extAttr->hasLNA = FALSE; + extAttr->hasNTSC = TRUE; + extAttr->hasBTSC = TRUE; + extAttr->hasOOB = TRUE; + extAttr->hasSMATX = TRUE; + extAttr->hasSMARX = TRUE; + extAttr->hasGPIO = TRUE; + extAttr->hasIRQN = TRUE; + break; + case 0x42: + extAttr->hasLNA = TRUE ; + extAttr->hasNTSC = TRUE ; + extAttr->hasBTSC = TRUE ; + extAttr->hasOOB = TRUE ; + extAttr->hasSMATX = TRUE; + extAttr->hasSMARX = TRUE; + extAttr->hasGPIO = TRUE; + extAttr->hasIRQN = TRUE; + break; + case 0x44: + extAttr->hasLNA = FALSE; + extAttr->hasNTSC = TRUE; + extAttr->hasBTSC = TRUE; + extAttr->hasOOB = TRUE; + extAttr->hasSMATX = TRUE; + extAttr->hasSMARX = TRUE; + extAttr->hasGPIO = TRUE; + extAttr->hasIRQN = TRUE; + break; + default: + /* Unknown device variant */ + return (DRX_STS_ERROR); + break; + } + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} + + +/** +* \fn DRXStatus_t PowerUpDevice() +* \brief Power up device. +* \param demod Pointer to demodulator instance. +* \return DRXStatus_t. +* \return DRX_STS_OK Success +* \retval DRX_STS_ERROR Failure, I2C or max retries reached +* +*/ + +#ifndef DRXJ_MAX_RETRIES_POWERUP +#define DRXJ_MAX_RETRIES_POWERUP 10 +#endif + +static DRXStatus_t +PowerUpDevice( pDRXDemodInstance_t demod ) +{ + pI2CDeviceAddr_t devAddr =(pI2CDeviceAddr_t)(NULL); + u8_t data = 0 ; + u16_t retryCount = 0; + I2CDeviceAddr_t wakeUpAddr; + + devAddr = demod->myI2CDevAddr; + wakeUpAddr.i2cAddr = DRXJ_WAKE_UP_KEY; + wakeUpAddr.i2cDevId = devAddr->i2cDevId; + wakeUpAddr.userData = devAddr->userData; + /* CHK_ERROR macro not used, I2C access may fail in this case: no ack + dummy write must be used to wake uop device, dummy read must be used to + reset HI state machine (avoiding actual writes) */ + do + { + data = 0; + DRXBSP_I2C_WriteRead( &wakeUpAddr, 1, &data, + (pI2CDeviceAddr_t)(NULL), 0, (pu8_t)(NULL) ); + DRXBSP_HST_Sleep(10); + retryCount++ ; + }while ( (DRXBSP_I2C_WriteRead( (pI2CDeviceAddr_t)(NULL), 0, (pu8_t)(NULL), + devAddr, 1, &data ) + != DRX_STS_OK ) && + (retryCount < DRXJ_MAX_RETRIES_POWERUP) ); + + /* Need some recovery time .... */ + DRXBSP_HST_Sleep(10); + + if ( retryCount == DRXJ_MAX_RETRIES_POWERUP ) + { + return (DRX_STS_ERROR); + } + + return (DRX_STS_OK); +} + +/*----------------------------------------------------------------------------*/ +/* MPEG Output Configuration Functions - begin */ +/*----------------------------------------------------------------------------*/ +/** +* \fn DRXStatus_t CtrlSetCfgMPEGOutput() +* \brief Set MPEG output configuration of the device. +* \param devmod Pointer to demodulator instance. +* \param cfgData Pointer to mpeg output configuaration. +* \return DRXStatus_t. +* +* Configure MPEG output parameters. +* +*/ +static DRXStatus_t +CtrlSetCfgMPEGOutput( pDRXDemodInstance_t demod, + pDRXCfgMPEGOutput_t cfgData ) +{ + pI2CDeviceAddr_t devAddr =(pI2CDeviceAddr_t)(NULL); + pDRXJData_t extAttr =(pDRXJData_t)(NULL); + pDRXCommonAttr_t commonAttr =(pDRXCommonAttr_t)(NULL); + u16_t fecOcRegMode = 0; + u16_t fecOcRegIprMode = 0; + u16_t fecOcRegIprInvert = 0; + u32_t maxBitRate = 0; + u32_t rcnRate = 0; + u32_t nrBits = 0; + u16_t sioPdrMdCfg = 0; + /* data mask for the output data byte */ + u16_t InvertDataMask = FEC_OC_IPR_INVERT_MD7__M | FEC_OC_IPR_INVERT_MD6__M | + FEC_OC_IPR_INVERT_MD5__M | FEC_OC_IPR_INVERT_MD4__M | + FEC_OC_IPR_INVERT_MD3__M | FEC_OC_IPR_INVERT_MD2__M | + FEC_OC_IPR_INVERT_MD1__M | FEC_OC_IPR_INVERT_MD0__M; + /* check arguments */ + if (( demod == NULL ) || + ( cfgData == NULL )) + { + return (DRX_STS_INVALID_ARG); + } + + devAddr = demod -> myI2CDevAddr; + extAttr = (pDRXJData_t) demod -> myExtAttr; + commonAttr = (pDRXCommonAttr_t) demod -> myCommonAttr; + + if ( cfgData->enableMPEGOutput == TRUE ) + { + /* quick and dirty patch to set MPEG incase current std is not + producing MPEG */ + switch ( extAttr->standard ) + { + case DRX_STANDARD_8VSB: + case DRX_STANDARD_ITU_A: + case DRX_STANDARD_ITU_B: + case DRX_STANDARD_ITU_C: + break; + default: + /* not an MPEG producing std, just store MPEG cfg */ + commonAttr->mpegCfg.enableMPEGOutput = cfgData->enableMPEGOutput; + commonAttr->mpegCfg.insertRSByte = cfgData->insertRSByte; + commonAttr->mpegCfg.enableParallel = cfgData->enableParallel; + commonAttr->mpegCfg.invertDATA = cfgData->invertDATA; + commonAttr->mpegCfg.invertERR = cfgData->invertERR; + commonAttr->mpegCfg.invertSTR = cfgData->invertSTR; + commonAttr->mpegCfg.invertVAL = cfgData->invertVAL; + commonAttr->mpegCfg.invertCLK = cfgData->invertCLK; + commonAttr->mpegCfg.staticCLK = cfgData->staticCLK; + commonAttr->mpegCfg.bitrate = cfgData->bitrate; + return (DRX_STS_OK); + } + + WR16( devAddr, FEC_OC_OCR_INVERT__A, 0); + switch (extAttr->standard) + { + case DRX_STANDARD_8VSB: + WR16( devAddr, FEC_OC_FCT_USAGE__A, 7 ); /* 2048 bytes fifo ram */ + WR16( devAddr, FEC_OC_TMD_CTL_UPD_RATE__A, 10); + WR16( devAddr, FEC_OC_TMD_INT_UPD_RATE__A, 10); + WR16( devAddr, FEC_OC_AVR_PARM_A__A, 5); + WR16( devAddr, FEC_OC_AVR_PARM_B__A, 7); + WR16( devAddr, FEC_OC_RCN_GAIN__A, 10); + /* Low Water Mark for synchronization */ + WR16( devAddr, FEC_OC_SNC_LWM__A, 3 ); + /* High Water Mark for synchronization */ + WR16( devAddr, FEC_OC_SNC_HWM__A, 5 ); + break; + case DRX_STANDARD_ITU_A: + case DRX_STANDARD_ITU_C: + switch ( extAttr->constellation ) + { + case DRX_CONSTELLATION_QAM256: + nrBits = 8; + break; + case DRX_CONSTELLATION_QAM128: + nrBits = 7; + break; + case DRX_CONSTELLATION_QAM64: + nrBits = 6; + break; + case DRX_CONSTELLATION_QAM32: + nrBits = 5; + break; + case DRX_CONSTELLATION_QAM16: + nrBits = 4; + break; + default: + return (DRX_STS_ERROR); + } /* extAttr->constellation */ + /* maxBitRate = symbolRate * nrBits * coef */ + /* coef = 188/204 */ + maxBitRate = ( extAttr->currSymbolRate / 8 ) * nrBits * 188; + /* pass through b/c Annex A/c need following settings */ + case DRX_STANDARD_ITU_B: + WR16( devAddr, FEC_OC_FCT_USAGE__A, FEC_OC_FCT_USAGE__PRE); + WR16( devAddr, FEC_OC_TMD_CTL_UPD_RATE__A, FEC_OC_TMD_CTL_UPD_RATE__PRE); + WR16( devAddr, FEC_OC_TMD_INT_UPD_RATE__A, 5); + WR16( devAddr, FEC_OC_AVR_PARM_A__A, FEC_OC_AVR_PARM_A__PRE); + WR16( devAddr, FEC_OC_AVR_PARM_B__A, FEC_OC_AVR_PARM_B__PRE); + if (cfgData->staticCLK == TRUE) + { + WR16( devAddr, FEC_OC_RCN_GAIN__A, 0xD ); + } + else + { + WR16( devAddr, FEC_OC_RCN_GAIN__A, FEC_OC_RCN_GAIN__PRE ); + } + WR16( devAddr, FEC_OC_SNC_LWM__A, 2); + WR16( devAddr, FEC_OC_SNC_HWM__A, 12); + break; + default: + break; + }/* swtich (standard) */ + + /* Check insertion of the Reed-Solomon parity bytes */ + RR16( devAddr, FEC_OC_MODE__A , &fecOcRegMode ); + RR16( devAddr, FEC_OC_IPR_MODE__A, &fecOcRegIprMode ); + if ( cfgData->insertRSByte == TRUE ) + { + /* enable parity symbol forward */ + fecOcRegMode |= FEC_OC_MODE_PARITY__M; + /* MVAL disable during parity bytes */ + fecOcRegIprMode |= FEC_OC_IPR_MODE_MVAL_DIS_PAR__M; + switch ( extAttr->standard ) + { + case DRX_STANDARD_8VSB: + rcnRate = 0x004854D3; + break; + case DRX_STANDARD_ITU_B: + fecOcRegMode |= FEC_OC_MODE_TRANSPARENT__M; + switch ( extAttr->constellation ) + { + case DRX_CONSTELLATION_QAM256: + rcnRate = 0x008945E7; + break; + case DRX_CONSTELLATION_QAM64: + rcnRate = 0x005F64D4; + break; + default: + return (DRX_STS_ERROR); + } + break; + case DRX_STANDARD_ITU_A: + case DRX_STANDARD_ITU_C: + /* insertRSByte = TRUE -> coef = 188/188 -> 1, RS bits are in MPEG output */ + rcnRate = ( Frac28 ( maxBitRate, ( u32_t )( commonAttr->sysClockFreq / 8 ) ) ) / 188; + break; + default: + return (DRX_STS_ERROR); + } /* extAttr->standard */ + } + else /* insertRSByte == FALSE */ + { + /* disable parity symbol forward */ + fecOcRegMode &= (~FEC_OC_MODE_PARITY__M); + /* MVAL enable during parity bytes */ + fecOcRegIprMode &= (~FEC_OC_IPR_MODE_MVAL_DIS_PAR__M); + switch ( extAttr->standard ) + { + case DRX_STANDARD_8VSB: + rcnRate = 0x0041605C; + break; + case DRX_STANDARD_ITU_B: + fecOcRegMode &= (~FEC_OC_MODE_TRANSPARENT__M); + switch ( extAttr->constellation ) + { + case DRX_CONSTELLATION_QAM256: + rcnRate = 0x0082D6A0; + break; + case DRX_CONSTELLATION_QAM64: + rcnRate = 0x005AEC1A; + break; + default: + return (DRX_STS_ERROR); + } + break; + case DRX_STANDARD_ITU_A: + case DRX_STANDARD_ITU_C: + /* insertRSByte = FALSE -> coef = 188/204, RS bits not in MPEG output */ + rcnRate = ( Frac28 ( maxBitRate, ( u32_t )( commonAttr->sysClockFreq / 8 ) ) ) / 204; + break; + default: + return (DRX_STS_ERROR); + } /* extAttr->standard */ + } + + if ( cfgData->enableParallel == TRUE ) + { /* MPEG data output is paralel -> clear ipr_mode[0] */ + fecOcRegIprMode &= (~(FEC_OC_IPR_MODE_SERIAL__M)); + } + else + { /* MPEG data output is serial -> set ipr_mode[0] */ + fecOcRegIprMode |= FEC_OC_IPR_MODE_SERIAL__M; + } + + /* Control slective inversion of output bits */ + if ( cfgData->invertDATA == TRUE ) + { + fecOcRegIprInvert |= InvertDataMask; + } + else + { + fecOcRegIprInvert &= (~(InvertDataMask)); + } + + if ( cfgData->invertERR == TRUE ) + { + fecOcRegIprInvert |= FEC_OC_IPR_INVERT_MERR__M; + } + else + { + fecOcRegIprInvert &= (~(FEC_OC_IPR_INVERT_MERR__M)); + } + + if ( cfgData->invertSTR == TRUE ) + { + fecOcRegIprInvert |= FEC_OC_IPR_INVERT_MSTRT__M; + } + else + { + fecOcRegIprInvert &= (~(FEC_OC_IPR_INVERT_MSTRT__M)); + } + + if ( cfgData->invertVAL == TRUE ) + { + fecOcRegIprInvert |= FEC_OC_IPR_INVERT_MVAL__M; + } + else + { + fecOcRegIprInvert &= (~(FEC_OC_IPR_INVERT_MVAL__M)); + } + + if ( cfgData->invertCLK == TRUE ) + { + fecOcRegIprInvert |= FEC_OC_IPR_INVERT_MCLK__M; + } + else + { + fecOcRegIprInvert &= (~(FEC_OC_IPR_INVERT_MCLK__M)); + } + + if ( cfgData->staticCLK == TRUE ) /* Static mode */ + { + u32_t dtoRate = 0; + u32_t bitRate = 0; + u16_t fecOcDtoBurstLen = 0; + u16_t fecOcDtoPeriod = 0; + + fecOcDtoBurstLen = FEC_OC_DTO_BURST_LEN__PRE; + + switch ( extAttr->standard ) + { + case DRX_STANDARD_8VSB: + fecOcDtoPeriod = 4; + if ( cfgData->insertRSByte == TRUE ) + { + fecOcDtoBurstLen = 208; + } + break; + case DRX_STANDARD_ITU_A: + { + u32_t symbolRateTh = 6400000; + if ( cfgData->insertRSByte == TRUE ) + { + fecOcDtoBurstLen = 204; + symbolRateTh = 5900000; + } + if ( extAttr->currSymbolRate >= symbolRateTh) + { + fecOcDtoPeriod = 0; + } + else + { + fecOcDtoPeriod = 1; + } + } + break; + case DRX_STANDARD_ITU_B: + fecOcDtoPeriod = 1; + if ( cfgData->insertRSByte == TRUE ) + { + fecOcDtoBurstLen = 128; + } + break; + case DRX_STANDARD_ITU_C: + fecOcDtoPeriod = 1; + if ( cfgData->insertRSByte == TRUE ) + { + fecOcDtoBurstLen = 204; + } + break; + default: + return (DRX_STS_ERROR); + } + bitRate = commonAttr->sysClockFreq * 1000 / (fecOcDtoPeriod + 2); + dtoRate = Frac28(bitRate, commonAttr->sysClockFreq * 1000 ); + dtoRate >>= 3; + WR16 ( devAddr, FEC_OC_DTO_RATE_HI__A, (u16_t) ((dtoRate >> 16) & FEC_OC_DTO_RATE_HI__M) ); + WR16 ( devAddr, FEC_OC_DTO_RATE_LO__A, (u16_t) (dtoRate & FEC_OC_DTO_RATE_LO_RATE_LO__M) ); + WR16 ( devAddr, FEC_OC_DTO_MODE__A, FEC_OC_DTO_MODE_DYNAMIC__M | FEC_OC_DTO_MODE_OFFSET_ENABLE__M ); + WR16 ( devAddr, FEC_OC_FCT_MODE__A, FEC_OC_FCT_MODE_RAT_ENA__M | FEC_OC_FCT_MODE_VIRT_ENA__M ); + WR16 ( devAddr, FEC_OC_DTO_BURST_LEN__A, fecOcDtoBurstLen ); + if ( extAttr->mpegOutputClockRate != DRXJ_MPEGOUTPUT_CLOCK_RATE_AUTO ) + fecOcDtoPeriod = extAttr->mpegOutputClockRate - 1; + WR16 ( devAddr, FEC_OC_DTO_PERIOD__A, fecOcDtoPeriod ); + } + else /* Dynamic mode */ + { + WR16 ( devAddr, FEC_OC_DTO_MODE__A, FEC_OC_DTO_MODE_DYNAMIC__M ); + WR16 ( devAddr, FEC_OC_FCT_MODE__A, 0 ); + } + + WR32 ( devAddr, FEC_OC_RCN_CTL_RATE_LO__A, rcnRate ); + + /* Write appropriate registers with requested configuration */ + WR16 ( devAddr, FEC_OC_MODE__A, fecOcRegMode ); + WR16 ( devAddr, FEC_OC_IPR_MODE__A, fecOcRegIprMode ); + WR16 ( devAddr, FEC_OC_IPR_INVERT__A, fecOcRegIprInvert ); + + /* enabling for both parallel and serial now */ + /* Write magic word to enable pdr reg write */ + WR16 ( devAddr, SIO_TOP_COMM_KEY__A, 0xFABA); + /* Set MPEG TS pads to outputmode */ + WR16 ( devAddr, SIO_PDR_MSTRT_CFG__A, 0x0013); + WR16 ( devAddr, SIO_PDR_MERR_CFG__A, 0x0013); + WR16 ( devAddr, SIO_PDR_MCLK_CFG__A, + MPEG_OUTPUT_CLK_DRIVE_STRENGTH << SIO_PDR_MCLK_CFG_DRIVE__B + | 0x03 << SIO_PDR_MCLK_CFG_MODE__B ); + WR16 ( devAddr, SIO_PDR_MVAL_CFG__A, 0x0013); + sioPdrMdCfg = MPEG_SERIAL_OUTPUT_PIN_DRIVE_STRENGTH << SIO_PDR_MD0_CFG_DRIVE__B + |0x03 << SIO_PDR_MD0_CFG_MODE__B; + WR16 ( devAddr, SIO_PDR_MD0_CFG__A, sioPdrMdCfg); + if ( cfgData->enableParallel == TRUE ) + { /* MPEG data output is paralel -> set MD1 to MD7 to output mode */ + sioPdrMdCfg = MPEG_PARALLEL_OUTPUT_PIN_DRIVE_STRENGTH << SIO_PDR_MD0_CFG_DRIVE__B + |0x03 << SIO_PDR_MD0_CFG_MODE__B; + WR16 ( devAddr, SIO_PDR_MD0_CFG__A, sioPdrMdCfg); + WR16 ( devAddr, SIO_PDR_MD1_CFG__A, sioPdrMdCfg); + WR16 ( devAddr, SIO_PDR_MD2_CFG__A, sioPdrMdCfg); + WR16 ( devAddr, SIO_PDR_MD3_CFG__A, sioPdrMdCfg); + WR16 ( devAddr, SIO_PDR_MD4_CFG__A, sioPdrMdCfg); + WR16 ( devAddr, SIO_PDR_MD5_CFG__A, sioPdrMdCfg); + WR16 ( devAddr, SIO_PDR_MD6_CFG__A, sioPdrMdCfg); + WR16 ( devAddr, SIO_PDR_MD7_CFG__A, sioPdrMdCfg); + } + else + { /* MPEG data output is serial -> set MD1 to MD7 to tri-state */ + WR16 ( devAddr, SIO_PDR_MD1_CFG__A, 0x0000); + WR16 ( devAddr, SIO_PDR_MD2_CFG__A, 0x0000); + WR16 ( devAddr, SIO_PDR_MD3_CFG__A, 0x0000); + WR16 ( devAddr, SIO_PDR_MD4_CFG__A, 0x0000); + WR16 ( devAddr, SIO_PDR_MD5_CFG__A, 0x0000); + WR16 ( devAddr, SIO_PDR_MD6_CFG__A, 0x0000); + WR16 ( devAddr, SIO_PDR_MD7_CFG__A, 0x0000); + } + /* Enable Monitor Bus output over MPEG pads and ctl input */ + WR16 ( devAddr, SIO_PDR_MON_CFG__A, 0x0000); + /* Write nomagic word to enable pdr reg write */ + WR16 ( devAddr, SIO_TOP_COMM_KEY__A, 0x0000); + } + else + { + /* Write magic word to enable pdr reg write */ + WR16 ( devAddr, SIO_TOP_COMM_KEY__A , 0xFABA); + /* Set MPEG TS pads to inputmode */ + WR16 ( devAddr, SIO_PDR_MSTRT_CFG__A , 0x0000); + WR16 ( devAddr, SIO_PDR_MERR_CFG__A , 0x0000); + WR16 ( devAddr, SIO_PDR_MCLK_CFG__A , 0x0000); + WR16 ( devAddr, SIO_PDR_MVAL_CFG__A , 0x0000); + WR16 ( devAddr, SIO_PDR_MD0_CFG__A , 0x0000); + WR16 ( devAddr, SIO_PDR_MD1_CFG__A , 0x0000); + WR16 ( devAddr, SIO_PDR_MD2_CFG__A , 0x0000); + WR16 ( devAddr, SIO_PDR_MD3_CFG__A , 0x0000); + WR16 ( devAddr, SIO_PDR_MD4_CFG__A , 0x0000); + WR16 ( devAddr, SIO_PDR_MD5_CFG__A , 0x0000); + WR16 ( devAddr, SIO_PDR_MD6_CFG__A , 0x0000); + WR16 ( devAddr, SIO_PDR_MD7_CFG__A , 0x0000); + /* Enable Monitor Bus output over MPEG pads and ctl input */ + WR16 ( devAddr, SIO_PDR_MON_CFG__A , 0x0000); + /* Write nomagic word to enable pdr reg write */ + WR16 ( devAddr, SIO_TOP_COMM_KEY__A , 0x0000); + } + + /* save values for restore after re-acquire */ + commonAttr->mpegCfg.enableMPEGOutput = cfgData->enableMPEGOutput; + commonAttr->mpegCfg.insertRSByte = cfgData->insertRSByte; + commonAttr->mpegCfg.enableParallel = cfgData->enableParallel; + commonAttr->mpegCfg.invertDATA = cfgData->invertDATA; + commonAttr->mpegCfg.invertERR = cfgData->invertERR; + commonAttr->mpegCfg.invertSTR = cfgData->invertSTR; + commonAttr->mpegCfg.invertVAL = cfgData->invertVAL; + commonAttr->mpegCfg.invertCLK = cfgData->invertCLK; + commonAttr->mpegCfg.staticCLK = cfgData->staticCLK; + commonAttr->mpegCfg.bitrate = cfgData->bitrate; + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} + +/*----------------------------------------------------------------------------*/ + +/** +* \fn DRXStatus_t CtrlGetCfgMPEGOutput() +* \brief Get MPEG output configuration of the device. +* \param devmod Pointer to demodulator instance. +* \param cfgData Pointer to MPEG output configuaration struct. +* \return DRXStatus_t. +* +* Retrieve MPEG output configuartion. +* +*/ +static DRXStatus_t +CtrlGetCfgMPEGOutput( pDRXDemodInstance_t demod, + pDRXCfgMPEGOutput_t cfgData ) +{ + pI2CDeviceAddr_t devAddr = (pI2CDeviceAddr_t)(NULL); + pDRXCommonAttr_t commonAttr = (pDRXCommonAttr_t)(NULL); + DRXLockStatus_t lockStatus = DRX_NOT_LOCKED; + u32_t rateReg = 0; + u32_t data64Hi = 0; + u32_t data64Lo = 0; + + if( cfgData == NULL ) + { + return (DRX_STS_INVALID_ARG); + } + devAddr = demod->myI2CDevAddr; + commonAttr = demod->myCommonAttr; + + cfgData->enableMPEGOutput = commonAttr->mpegCfg.enableMPEGOutput; + cfgData->insertRSByte = commonAttr->mpegCfg.insertRSByte; + cfgData->enableParallel = commonAttr->mpegCfg.enableParallel; + cfgData->invertDATA = commonAttr->mpegCfg.invertDATA; + cfgData->invertERR = commonAttr->mpegCfg.invertERR; + cfgData->invertSTR = commonAttr->mpegCfg.invertSTR; + cfgData->invertVAL = commonAttr->mpegCfg.invertVAL; + cfgData->invertCLK = commonAttr->mpegCfg.invertCLK; + cfgData->staticCLK = commonAttr->mpegCfg.staticCLK; + cfgData->bitrate = 0; + + CHK_ERROR( CtrlLockStatus( demod, &lockStatus) ); + if ( (lockStatus == DRX_LOCKED) ) + { + RR32 (devAddr, FEC_OC_RCN_DYN_RATE_LO__A, &rateReg); + /* Frcn_rate = rateReg * Fsys / 2 ^ 25 */ + Mult32 ( rateReg, commonAttr->sysClockFreq * 1000, &data64Hi, &data64Lo ); + cfgData->bitrate = (data64Hi << 7) | (data64Lo >> 25); + } + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} + +/*----------------------------------------------------------------------------*/ +/* MPEG Output Configuration Functions - end */ +/*----------------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------------*/ +/* miscellaneous configuartions - begin */ +/*----------------------------------------------------------------------------*/ + +/** +* \fn DRXStatus_t SetMPEGTEIHandling() +* \brief Activate MPEG TEI handling settings. +* \param devmod Pointer to demodulator instance. +* \return DRXStatus_t. +* +* This routine should be called during a set channel of QAM/VSB +* +*/ +static DRXStatus_t +SetMPEGTEIHandling( pDRXDemodInstance_t demod ) +{ + pDRXJData_t extAttr = (pDRXJData_t)(NULL); + pI2CDeviceAddr_t devAddr = (pI2CDeviceAddr_t)(NULL); + u16_t fecOcDprMode = 0; + u16_t fecOcSncMode = 0; + u16_t fecOcEmsMode = 0; + + devAddr = demod -> myI2CDevAddr; + extAttr = (pDRXJData_t) demod -> myExtAttr; + + RR16( devAddr, FEC_OC_DPR_MODE__A, &fecOcDprMode ); + RR16( devAddr, FEC_OC_SNC_MODE__A, &fecOcSncMode ); + RR16( devAddr, FEC_OC_EMS_MODE__A, &fecOcEmsMode ); + + /* reset to default, allow TEI bit to be changed */ + fecOcDprMode &= (~FEC_OC_DPR_MODE_ERR_DISABLE__M); + fecOcSncMode &= (~(FEC_OC_SNC_MODE_ERROR_CTL__M | + FEC_OC_SNC_MODE_CORR_DISABLE__M)); + fecOcEmsMode &= (~FEC_OC_EMS_MODE_MODE__M); + + if ( extAttr->disableTEIhandling == TRUE ) + { + /* do not change TEI bit */ + fecOcDprMode |= FEC_OC_DPR_MODE_ERR_DISABLE__M; + fecOcSncMode |= FEC_OC_SNC_MODE_CORR_DISABLE__M | + ( (0x2)<<(FEC_OC_SNC_MODE_ERROR_CTL__B)); + fecOcEmsMode |= ((0x01)<<(FEC_OC_EMS_MODE_MODE__B)); + } + + WR16( devAddr, FEC_OC_DPR_MODE__A, fecOcDprMode ); + WR16( devAddr, FEC_OC_SNC_MODE__A, fecOcSncMode ); + WR16( devAddr, FEC_OC_EMS_MODE__A, fecOcEmsMode ); + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} + +/*----------------------------------------------------------------------------*/ +/** +* \fn DRXStatus_t BitReverseMPEGOutput() +* \brief Set MPEG output bit-endian settings. +* \param devmod Pointer to demodulator instance. +* \return DRXStatus_t. +* +* This routine should be called during a set channel of QAM/VSB +* +*/ +static DRXStatus_t +BitReverseMPEGOutput ( pDRXDemodInstance_t demod ) +{ + pDRXJData_t extAttr = (pDRXJData_t)(NULL); + pI2CDeviceAddr_t devAddr = (pI2CDeviceAddr_t)(NULL); + u16_t fecOcIprMode = 0; + + devAddr = demod -> myI2CDevAddr; + extAttr = (pDRXJData_t) demod -> myExtAttr; + + RR16( devAddr, FEC_OC_IPR_MODE__A, &fecOcIprMode ); + + /* reset to default (normal bit order) */ + fecOcIprMode &= (~FEC_OC_IPR_MODE_REVERSE_ORDER__M); + + if ( extAttr->bitReverseMpegOutout == TRUE) + { + /* reverse bit order */ + fecOcIprMode |= FEC_OC_IPR_MODE_REVERSE_ORDER__M; + } + + WR16( devAddr, FEC_OC_IPR_MODE__A, fecOcIprMode ); + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} + +/*----------------------------------------------------------------------------*/ +/** +* \fn DRXStatus_t SetMPEGOutputClockRate() +* \brief Set MPEG output clock rate. +* \param devmod Pointer to demodulator instance. +* \return DRXStatus_t. +* +* This routine should be called during a set channel of QAM/VSB +* +*/ +static DRXStatus_t +SetMPEGOutputClockRate ( pDRXDemodInstance_t demod ) +{ + pDRXJData_t extAttr = (pDRXJData_t)(NULL); + pI2CDeviceAddr_t devAddr = (pI2CDeviceAddr_t)(NULL); + + devAddr = demod -> myI2CDevAddr; + extAttr = (pDRXJData_t) demod -> myExtAttr; + + if ( extAttr->mpegOutputClockRate != DRXJ_MPEGOUTPUT_CLOCK_RATE_AUTO ) + { + WR16 ( devAddr, FEC_OC_DTO_PERIOD__A, extAttr->mpegOutputClockRate - 1 ); + } + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} + +/*----------------------------------------------------------------------------*/ +/** +* \fn DRXStatus_t SetMPEGStartWidth() +* \brief Set MPEG start width. +* \param devmod Pointer to demodulator instance. +* \return DRXStatus_t. +* +* This routine should be called during a set channel of QAM/VSB +* +*/ +static DRXStatus_t +SetMPEGStartWidth ( pDRXDemodInstance_t demod ) +{ + pDRXJData_t extAttr = (pDRXJData_t)(NULL); + pI2CDeviceAddr_t devAddr = (pI2CDeviceAddr_t)(NULL); + u16_t fecOcCommMb = 0; + pDRXCommonAttr_t commonAttr = (pDRXCommonAttr_t) NULL; + + devAddr = demod -> myI2CDevAddr; + extAttr = (pDRXJData_t) demod -> myExtAttr; + commonAttr = demod->myCommonAttr; + + if ((commonAttr->mpegCfg.staticCLK == TRUE) && (commonAttr->mpegCfg.enableParallel == FALSE)) + { + RR16 ( devAddr, FEC_OC_COMM_MB__A, &fecOcCommMb ); + fecOcCommMb &= ~FEC_OC_COMM_MB_CTL_ON; + if ( extAttr->mpegStartWidth == DRXJ_MPEG_START_WIDTH_8CLKCYC ) + { + fecOcCommMb |= FEC_OC_COMM_MB_CTL_ON; + } + WR16 ( devAddr, FEC_OC_COMM_MB__A, fecOcCommMb); + } + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} + +/*----------------------------------------------------------------------------*/ +/** +* \fn DRXStatus_t CtrlSetCfgMpegOutputMisc() +* \brief Set miscellaneous configuartions +* \param devmod Pointer to demodulator instance. +* \param cfgData pDRXJCfgMisc_t +* \return DRXStatus_t. +* +* This routine can be used to set configuartion options that are DRXJ +* specific and/or added to the requirements at a late stage. +* +*/ +static DRXStatus_t +CtrlSetCfgMpegOutputMisc( + pDRXDemodInstance_t demod, + pDRXJCfgMpegOutputMisc_t cfgData ) +{ + pDRXJData_t extAttr = (pDRXJData_t)(NULL); + + if(cfgData == NULL) + { + return (DRX_STS_INVALID_ARG); + } + + extAttr = (pDRXJData_t) demod -> myExtAttr; + + /* + Set disable TEI bit handling flag. + TEI must be left untouched by device in case of BER measurements using + external equipment that is unable to ignore the TEI bit in the TS. + Default will FALSE (enable TEI bit handling). + Reverse output bit order. Default is FALSE (msb on MD7 (parallel) or out first (serial)). + Set clock rate. Default is auto that is derived from symbol rate. + The flags and values will also be used to set registers during a set channel. + */ + extAttr->disableTEIhandling = cfgData->disableTEIHandling; + extAttr->bitReverseMpegOutout = cfgData->bitReverseMpegOutout; + extAttr->mpegOutputClockRate = cfgData->mpegOutputClockRate; + extAttr->mpegStartWidth = cfgData->mpegStartWidth; + /* Don't care what the active standard is, activate setting immediatly */ + CHK_ERROR ( SetMPEGTEIHandling( demod ) ); + CHK_ERROR ( BitReverseMPEGOutput( demod ) ); + CHK_ERROR ( SetMPEGOutputClockRate( demod ) ); + CHK_ERROR ( SetMPEGStartWidth ( demod ) ); + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} + +/*----------------------------------------------------------------------------*/ + +/** +* \fn DRXStatus_t CtrlGetCfgMpegOutputMisc() +* \brief Get miscellaneous configuartions. +* \param devmod Pointer to demodulator instance. +* \param cfgData Pointer to DRXJCfgMisc_t. +* \return DRXStatus_t. +* +* This routine can be used to retreive the current setting of the configuartion +* options that are DRXJ specific and/or added to the requirements at a +* late stage. +* +*/ +static DRXStatus_t +CtrlGetCfgMpegOutputMisc( + pDRXDemodInstance_t demod, + pDRXJCfgMpegOutputMisc_t cfgData ) +{ + pDRXJData_t extAttr = (pDRXJData_t)(NULL); + u16_t data = 0; + + if(cfgData == NULL) + { + return (DRX_STS_INVALID_ARG); + } + + extAttr = (pDRXJData_t) demod -> myExtAttr; + cfgData->disableTEIHandling = extAttr->disableTEIhandling; + cfgData->bitReverseMpegOutout = extAttr->bitReverseMpegOutout; + cfgData->mpegStartWidth = extAttr->mpegStartWidth; + if (extAttr->mpegOutputClockRate != DRXJ_MPEGOUTPUT_CLOCK_RATE_AUTO) + { + cfgData->mpegOutputClockRate = extAttr->mpegOutputClockRate; + } + else + { + RR16 ( demod->myI2CDevAddr, FEC_OC_DTO_PERIOD__A, &data ); + cfgData->mpegOutputClockRate = (DRXJMpegOutputClockRate_t) (data + 1); + } + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} + +/*----------------------------------------------------------------------------*/ + +/** +* \fn DRXStatus_t CtrlGetCfgHwCfg() +* \brief Get HW configuartions. +* \param devmod Pointer to demodulator instance. +* \param cfgData Pointer to Bool. +* \return DRXStatus_t. +* +* This routine can be used to retreive the current setting of the configuartion +* options that are DRXJ specific and/or added to the requirements at a +* late stage. +* +*/ +static DRXStatus_t +CtrlGetCfgHwCfg( pDRXDemodInstance_t demod, + pDRXJCfgHwCfg_t cfgData ) +{ + u16_t data = 0; + pDRXJData_t extAttr = (pDRXJData_t)(NULL); + + if(cfgData == NULL) + { + return (DRX_STS_INVALID_ARG); + } + + extAttr = (pDRXJData_t) demod -> myExtAttr; + WR16 ( demod->myI2CDevAddr, SIO_TOP_COMM_KEY__A, 0xFABA); + RR16 ( demod->myI2CDevAddr, SIO_PDR_OHW_CFG__A, &data ); + WR16 ( demod->myI2CDevAddr, SIO_TOP_COMM_KEY__A, 0x0000); + + cfgData->i2cSpeed = (DRXJI2CSpeed_t)((data >> 6) & 0x1); + cfgData->xtalFreq = (DRXJXtalFreq_t)(data & 0x3); + + return (DRX_STS_OK); + rw_error: + return (DRX_STS_ERROR); +} +/*----------------------------------------------------------------------------*/ +/* miscellaneous configuartions - end */ +/*----------------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------------*/ +/* UIO Configuration Functions - begin */ +/*----------------------------------------------------------------------------*/ +/** +* \fn DRXStatus_t CtrlSetUIOCfg() +* \brief Configure modus oprandi UIO. +* \param demod Pointer to demodulator instance. +* \param UIOCfg Pointer to a configuration setting for a certain UIO. +* \return DRXStatus_t. +*/ +static DRXStatus_t +CtrlSetUIOCfg( pDRXDemodInstance_t demod, pDRXUIOCfg_t UIOCfg ) +{ + pDRXJData_t extAttr = (pDRXJData_t)(NULL); + + if (( UIOCfg == NULL ) || ( demod == NULL )) + { + return DRX_STS_INVALID_ARG; + } + extAttr = (pDRXJData_t)demod -> myExtAttr; + + /* Write magic word to enable pdr reg write */ + WR16( demod->myI2CDevAddr, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY ); + switch ( UIOCfg->uio ) { + /*====================================================================*/ + case DRX_UIO1 : + /* DRX_UIO1: SMA_TX UIO-1 */ + if (extAttr->hasSMATX != TRUE) + return DRX_STS_ERROR; + switch ( UIOCfg->mode ) + { + case DRX_UIO_MODE_FIRMWARE_SMA: /* falltrough */ + case DRX_UIO_MODE_FIRMWARE_SAW: /* falltrough */ + case DRX_UIO_MODE_READWRITE: + extAttr->uioSmaTxMode = UIOCfg->mode; + break; + case DRX_UIO_MODE_DISABLE: + extAttr->uioSmaTxMode = UIOCfg->mode; + /* pad configuration register is set 0 - input mode */ + WR16( demod->myI2CDevAddr, SIO_PDR_SMA_TX_CFG__A, 0 ); + break; + default: + return DRX_STS_INVALID_ARG; + } /* switch ( UIOCfg->mode ) */ + break; + /*====================================================================*/ + case DRX_UIO2 : + /* DRX_UIO2: SMA_RX UIO-2 */ + if (extAttr->hasSMARX != TRUE) + return DRX_STS_ERROR; + switch ( UIOCfg->mode ) + { + case DRX_UIO_MODE_FIRMWARE0: /* falltrough */ + case DRX_UIO_MODE_READWRITE: + extAttr->uioSmaRxMode = UIOCfg->mode; + break; + case DRX_UIO_MODE_DISABLE: + extAttr->uioSmaRxMode = UIOCfg->mode; + /* pad configuration register is set 0 - input mode */ + WR16( demod->myI2CDevAddr, SIO_PDR_SMA_RX_CFG__A, 0 ); + break; + default: + return DRX_STS_INVALID_ARG; + break; + } /* switch ( UIOCfg->mode ) */ + break; + /*====================================================================*/ + case DRX_UIO3 : + /* DRX_UIO3: GPIO UIO-3 */ + if (extAttr->hasGPIO != TRUE) + return DRX_STS_ERROR; + switch ( UIOCfg->mode ) + { + case DRX_UIO_MODE_FIRMWARE0: /* falltrough */ + case DRX_UIO_MODE_READWRITE: + extAttr->uioGPIOMode = UIOCfg->mode; + break; + case DRX_UIO_MODE_DISABLE: + extAttr->uioGPIOMode = UIOCfg->mode; + /* pad configuration register is set 0 - input mode */ + WR16( demod->myI2CDevAddr, SIO_PDR_GPIO_CFG__A, 0 ); + break; + default: + return DRX_STS_INVALID_ARG; + break; + } /* switch ( UIOCfg->mode ) */ + break; + /*====================================================================*/ + case DRX_UIO4 : + /* DRX_UIO4: IRQN UIO-4 */ + if (extAttr->hasIRQN != TRUE) + return DRX_STS_ERROR; + switch ( UIOCfg->mode ) + { + case DRX_UIO_MODE_READWRITE: + extAttr->uioIRQNMode = UIOCfg->mode; + break; + case DRX_UIO_MODE_DISABLE: + /* pad configuration register is set 0 - input mode */ + WR16( demod->myI2CDevAddr, SIO_PDR_IRQN_CFG__A, 0 ); + extAttr->uioIRQNMode = UIOCfg->mode; + break; + case DRX_UIO_MODE_FIRMWARE0: /* falltrough */ + default: + return DRX_STS_INVALID_ARG; + break; + } /* switch ( UIOCfg->mode ) */ + break; + /*====================================================================*/ + default: + return DRX_STS_INVALID_ARG; + } /* switch ( UIOCfg->uio ) */ + + /* Write magic word to disable pdr reg write */ + WR16 ( demod->myI2CDevAddr, SIO_TOP_COMM_KEY__A, 0x0000); + + return (DRX_STS_OK); + rw_error: + return (DRX_STS_ERROR); +} + +/*============================================================================*/ +/** +* \fn DRXStatus_t CtrlGetUIOCfg() +* \brief Get modus oprandi UIO. +* \param demod Pointer to demodulator instance. +* \param UIOCfg Pointer to a configuration setting for a certain UIO. +* \return DRXStatus_t. +*/ +static DRXStatus_t +CtrlGetUIOCfg( pDRXDemodInstance_t demod, pDRXUIOCfg_t UIOCfg ) +{ + + pDRXJData_t extAttr = (pDRXJData_t) NULL; + pDRXUIOMode_t UIOMode[4] = {NULL}; + pBool_t UIOAvailable[4] = {NULL}; + + extAttr = demod->myExtAttr; + + UIOMode[DRX_UIO1] = &extAttr->uioSmaTxMode; + UIOMode[DRX_UIO2] = &extAttr->uioSmaRxMode; + UIOMode[DRX_UIO3] = &extAttr->uioGPIOMode; + UIOMode[DRX_UIO4] = &extAttr->uioIRQNMode; + + UIOAvailable[DRX_UIO1] = &extAttr->hasSMATX; + UIOAvailable[DRX_UIO2] = &extAttr->hasSMARX; + UIOAvailable[DRX_UIO3] = &extAttr->hasGPIO; + UIOAvailable[DRX_UIO4] = &extAttr->hasIRQN; + + if ( UIOCfg == NULL ) + { + return DRX_STS_INVALID_ARG; + } + + if ( ( UIOCfg->uio > DRX_UIO4 ) || + ( UIOCfg->uio < DRX_UIO1 ) ) + { + return DRX_STS_INVALID_ARG; + } + + if( *UIOAvailable[UIOCfg->uio] == FALSE ) + { + return DRX_STS_ERROR; + } + + UIOCfg->mode = *UIOMode[ UIOCfg->uio ]; + + return DRX_STS_OK; +} + +/** +* \fn DRXStatus_t CtrlUIOWrite() +* \brief Write to a UIO. +* \param demod Pointer to demodulator instance. +* \param UIOData Pointer to data container for a certain UIO. +* \return DRXStatus_t. +*/ +static DRXStatus_t +CtrlUIOWrite( pDRXDemodInstance_t demod, + pDRXUIOData_t UIOData) +{ + pDRXJData_t extAttr = (pDRXJData_t)(NULL); + u16_t pinCfgValue = 0; + u16_t value = 0; + + if (( UIOData == NULL ) || ( demod == NULL )) + { + return DRX_STS_INVALID_ARG; + } + + extAttr = (pDRXJData_t)demod -> myExtAttr; + + /* Write magic word to enable pdr reg write */ + WR16( demod->myI2CDevAddr, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY ); + switch ( UIOData->uio ) { + /*====================================================================*/ + case DRX_UIO1: + /* DRX_UIO1: SMA_TX UIO-1 */ + if (extAttr->hasSMATX != TRUE) + return DRX_STS_ERROR; + if ( ( extAttr->uioSmaTxMode != DRX_UIO_MODE_READWRITE ) + && ( extAttr->uioSmaTxMode != DRX_UIO_MODE_FIRMWARE_SAW ) ) + { + return DRX_STS_ERROR; + } + pinCfgValue = 0; + /* io_pad_cfg register (8 bit reg.) MSB bit is 1 (default value) */ + pinCfgValue |= 0x0113; + /* io_pad_cfg_mode output mode is drive always */ + /* io_pad_cfg_drive is set to power 2 (23 mA) */ + + /* write to io pad configuration register - output mode */ + WR16( demod->myI2CDevAddr, SIO_PDR_SMA_TX_CFG__A, pinCfgValue ); + + /* use corresponding bit in io data output registar */ + RR16( demod->myI2CDevAddr, SIO_PDR_UIO_OUT_LO__A, &value ); + if (UIOData->value == FALSE) + { + value &= 0x7FFF; /* write zero to 15th bit - 1st UIO */ + } else { + value |= 0x8000; /* write one to 15th bit - 1st UIO */ + } + /* write back to io data output register */ + WR16( demod->myI2CDevAddr, SIO_PDR_UIO_OUT_LO__A, value ); + break; + /*======================================================================*/ + case DRX_UIO2: + /* DRX_UIO2: SMA_RX UIO-2 */ + if (extAttr->hasSMARX != TRUE) + return DRX_STS_ERROR; + if ( extAttr->uioSmaRxMode != DRX_UIO_MODE_READWRITE ) + { + return DRX_STS_ERROR; + } + pinCfgValue = 0; + /* io_pad_cfg register (8 bit reg.) MSB bit is 1 (default value) */ + pinCfgValue |= 0x0113; + /* io_pad_cfg_mode output mode is drive always */ + /* io_pad_cfg_drive is set to power 2 (23 mA) */ + + /* write to io pad configuration register - output mode */ + WR16( demod->myI2CDevAddr, SIO_PDR_SMA_RX_CFG__A, pinCfgValue ); + + /* use corresponding bit in io data output registar */ + RR16( demod->myI2CDevAddr, SIO_PDR_UIO_OUT_LO__A, &value ); + if (UIOData->value == FALSE) + { + value &= 0xBFFF; /* write zero to 14th bit - 2nd UIO */ + } else { + value |= 0x4000; /* write one to 14th bit - 2nd UIO */ + } + /* write back to io data output register */ + WR16( demod->myI2CDevAddr, SIO_PDR_UIO_OUT_LO__A, value ); + break; + /*====================================================================*/ + case DRX_UIO3: + /* DRX_UIO3: ASEL UIO-3 */ + if (extAttr->hasGPIO != TRUE) + return DRX_STS_ERROR; + if ( extAttr->uioGPIOMode != DRX_UIO_MODE_READWRITE ) + { + return DRX_STS_ERROR; + } + pinCfgValue = 0; + /* io_pad_cfg register (8 bit reg.) MSB bit is 1 (default value) */ + pinCfgValue |= 0x0113; + /* io_pad_cfg_mode output mode is drive always */ + /* io_pad_cfg_drive is set to power 2 (23 mA) */ + + /* write to io pad configuration register - output mode */ + WR16( demod->myI2CDevAddr, SIO_PDR_GPIO_CFG__A, pinCfgValue ); + + /* use corresponding bit in io data output registar */ + RR16( demod->myI2CDevAddr, SIO_PDR_UIO_OUT_HI__A, &value ); + if (UIOData->value == FALSE) + { + value &= 0xFFFB; /* write zero to 2nd bit - 3rd UIO */ + } else { + value |= 0x0004; /* write one to 2nd bit - 3rd UIO */ + } + /* write back to io data output register */ + WR16( demod->myI2CDevAddr, SIO_PDR_UIO_OUT_HI__A, value ); + break; + /*=====================================================================*/ + case DRX_UIO4: + /* DRX_UIO4: IRQN UIO-4 */ + if (extAttr->hasIRQN != TRUE) + return DRX_STS_ERROR; + + if ( extAttr->uioIRQNMode != DRX_UIO_MODE_READWRITE ) + { + return DRX_STS_ERROR; + } + pinCfgValue = 0; + /* io_pad_cfg register (8 bit reg.) MSB bit is 1 (default value) */ + pinCfgValue |= 0x0113; + /* io_pad_cfg_mode output mode is drive always */ + /* io_pad_cfg_drive is set to power 2 (23 mA) */ + + /* write to io pad configuration register - output mode */ + WR16( demod->myI2CDevAddr, SIO_PDR_IRQN_CFG__A, pinCfgValue ); + + /* use corresponding bit in io data output registar */ + RR16( demod->myI2CDevAddr, SIO_PDR_UIO_OUT_LO__A, &value ); + if (UIOData->value == FALSE) + { + value &= 0xEFFF; /* write zero to 12th bit - 4th UIO */ + } else { + value |= 0x1000; /* write one to 12th bit - 4th UIO */ + } + /* write back to io data output register */ + WR16( demod->myI2CDevAddr, SIO_PDR_UIO_OUT_LO__A, value ); + break; + /*=====================================================================*/ + default: + return DRX_STS_INVALID_ARG; + } /* switch ( UIOData->uio ) */ + + /* Write magic word to disable pdr reg write */ + WR16 ( demod->myI2CDevAddr, SIO_TOP_COMM_KEY__A, 0x0000); + + return (DRX_STS_OK); + rw_error: + return (DRX_STS_ERROR); +} + + +/** +*\fn DRXStatus_t CtrlUIORead +*\brief Read from a UIO. +* \param demod Pointer to demodulator instance. +* \param UIOData Pointer to data container for a certain UIO. +* \return DRXStatus_t. +*/ +static DRXStatus_t +CtrlUIORead( pDRXDemodInstance_t demod, + pDRXUIOData_t UIOData) +{ + pDRXJData_t extAttr = (pDRXJData_t)(NULL); + u16_t pinCfgValue = 0; + u16_t value = 0; + + if (( UIOData == NULL ) || ( demod == NULL )) + { + return DRX_STS_INVALID_ARG; + } + + extAttr = (pDRXJData_t)demod -> myExtAttr; + + /* Write magic word to enable pdr reg write */ + WR16( demod->myI2CDevAddr, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY ); + switch ( UIOData->uio ) { + /*====================================================================*/ + case DRX_UIO1: + /* DRX_UIO1: SMA_TX UIO-1 */ + if (extAttr->hasSMATX != TRUE) + return DRX_STS_ERROR; + + if ( extAttr->uioSmaTxMode != DRX_UIO_MODE_READWRITE ) + { + return DRX_STS_ERROR; + } + pinCfgValue = 0; + /* io_pad_cfg register (8 bit reg.) MSB bit is 1 (default value) */ + pinCfgValue |= 0x0110; + /* io_pad_cfg_mode output mode is drive always */ + /* io_pad_cfg_drive is set to power 2 (23 mA) */ + + /* write to io pad configuration register - input mode */ + WR16( demod->myI2CDevAddr, SIO_PDR_SMA_TX_CFG__A, pinCfgValue ); + + RR16( demod->myI2CDevAddr, SIO_PDR_UIO_IN_LO__A, &value ); + if ( (value & 0x8000) != 0 ) /* check 15th bit - 1st UIO */ + { + UIOData->value = TRUE; + } else { + UIOData->value = FALSE; + } + break; + /*======================================================================*/ + case DRX_UIO2: + /* DRX_UIO2: SMA_RX UIO-2 */ + if (extAttr->hasSMARX != TRUE) + return DRX_STS_ERROR; + + if ( extAttr->uioSmaRxMode != DRX_UIO_MODE_READWRITE ) + { + return DRX_STS_ERROR; + } + pinCfgValue = 0; + /* io_pad_cfg register (8 bit reg.) MSB bit is 1 (default value) */ + pinCfgValue |= 0x0110; + /* io_pad_cfg_mode output mode is drive always */ + /* io_pad_cfg_drive is set to power 2 (23 mA) */ + + /* write to io pad configuration register - input mode */ + WR16( demod->myI2CDevAddr, SIO_PDR_SMA_RX_CFG__A, pinCfgValue ); + + RR16( demod->myI2CDevAddr, SIO_PDR_UIO_IN_LO__A, &value ); + + if ( (value & 0x4000) != 0 ) /* check 14th bit - 2nd UIO */ + { + UIOData->value = TRUE; + } else { + UIOData->value = FALSE; + } + break; + /*=====================================================================*/ + case DRX_UIO3: + /* DRX_UIO3: GPIO UIO-3 */ + if (extAttr->hasGPIO != TRUE) + return DRX_STS_ERROR; + + if ( extAttr->uioGPIOMode != DRX_UIO_MODE_READWRITE ) + { + return DRX_STS_ERROR; + } + pinCfgValue = 0; + /* io_pad_cfg register (8 bit reg.) MSB bit is 1 (default value) */ + pinCfgValue |= 0x0110; + /* io_pad_cfg_mode output mode is drive always */ + /* io_pad_cfg_drive is set to power 2 (23 mA) */ + + /* write to io pad configuration register - input mode */ + WR16( demod->myI2CDevAddr, SIO_PDR_GPIO_CFG__A, pinCfgValue ); + + /* read io input data registar */ + RR16( demod->myI2CDevAddr, SIO_PDR_UIO_IN_HI__A, &value ); + if ( (value & 0x0004) != 0 ) /* check 2nd bit - 3rd UIO */ + { + UIOData->value = TRUE; + } else { + UIOData->value = FALSE; + } + break; + /*=====================================================================*/ + case DRX_UIO4: + /* DRX_UIO4: IRQN UIO-4 */ + if (extAttr->hasIRQN != TRUE) + return DRX_STS_ERROR; + + if ( extAttr->uioIRQNMode != DRX_UIO_MODE_READWRITE ) + { + return DRX_STS_ERROR; + } + pinCfgValue = 0; + /* io_pad_cfg register (8 bit reg.) MSB bit is 1 (default value) */ + pinCfgValue |= 0x0110; + /* io_pad_cfg_mode output mode is drive always */ + /* io_pad_cfg_drive is set to power 2 (23 mA) */ + + /* write to io pad configuration register - input mode */ + WR16( demod->myI2CDevAddr, SIO_PDR_IRQN_CFG__A, pinCfgValue ); + + /* read io input data registar */ + RR16( demod->myI2CDevAddr, SIO_PDR_UIO_IN_LO__A, &value ); + if ( (value & 0x1000) != 0 ) /* check 12th bit - 4th UIO */ + { + UIOData->value = TRUE; + } else { + UIOData->value = FALSE; + } + break; + /*====================================================================*/ + default: + return DRX_STS_INVALID_ARG; + } /* switch ( UIOData->uio ) */ + + /* Write magic word to disable pdr reg write */ + WR16 ( demod->myI2CDevAddr, SIO_TOP_COMM_KEY__A, 0x0000); + + return (DRX_STS_OK); + rw_error: + return (DRX_STS_ERROR); +} +/*---------------------------------------------------------------------------*/ +/* UIO Configuration Functions - end */ +/*---------------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------------*/ +/* I2C Bridge Functions - begin */ +/*----------------------------------------------------------------------------*/ +/** +* \fn DRXStatus_t CtrlI2CBridge() +* \brief Open or close the I2C switch to tuner. +* \param demod Pointer to demodulator instance. +* \param bridgeClosed Pointer to bool indication if bridge is closed not. +* \return DRXStatus_t. + +*/ +static DRXStatus_t +CtrlI2CBridge( pDRXDemodInstance_t demod, + pBool_t bridgeClosed ) +{ + DRXJHiCmd_t hiCmd; + u16_t result = 0; + + /* check arguments */ + if (bridgeClosed == NULL ) + { + return (DRX_STS_INVALID_ARG); + } + + hiCmd.cmd = SIO_HI_RA_RAM_CMD_BRDCTRL; + hiCmd.param1 = SIO_HI_RA_RAM_PAR_1_PAR1_SEC_KEY; + if (*bridgeClosed == TRUE) + { + hiCmd.param2 = SIO_HI_RA_RAM_PAR_2_BRD_CFG_CLOSED; + } + else + { + hiCmd.param2 = SIO_HI_RA_RAM_PAR_2_BRD_CFG_OPEN; + } + + return HICommand( demod -> myI2CDevAddr, &hiCmd, &result); +} +/*----------------------------------------------------------------------------*/ +/* I2C Bridge Functions - end */ +/*----------------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------------*/ +/* Smart antenna Functions - begin */ +/*----------------------------------------------------------------------------*/ +/** +* \fn DRXStatus_t SmartAntInit() +* \brief Initialize Smart Antenna. +* \param pointer to DRXDemodInstance_t. +* \return DRXStatus_t. +* +*/ +static DRXStatus_t +SmartAntInit(pDRXDemodInstance_t demod) +{ + u16_t data = 0; + pDRXJData_t extAttr = NULL; + pI2CDeviceAddr_t devAddr = NULL; + DRXUIOCfg_t UIOCfg = {DRX_UIO1, DRX_UIO_MODE_FIRMWARE_SMA}; + + devAddr = demod -> myI2CDevAddr; + extAttr = (pDRXJData_t) demod -> myExtAttr; + + /* Write magic word to enable pdr reg write */ + WR16( demod->myI2CDevAddr, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY ); + /* init smart antenna */ + RR16( devAddr, SIO_SA_TX_COMMAND__A, &data ); + if (extAttr->smartAntInverted) + WR16( devAddr, SIO_SA_TX_COMMAND__A, + (data | SIO_SA_TX_COMMAND_TX_INVERT__M ) + | SIO_SA_TX_COMMAND_TX_ENABLE__M ); + else + WR16( devAddr, SIO_SA_TX_COMMAND__A, + (data & (~SIO_SA_TX_COMMAND_TX_INVERT__M)) + | SIO_SA_TX_COMMAND_TX_ENABLE__M ); + + /* config SMA_TX pin to smart antenna mode*/ + CHK_ERROR( CtrlSetUIOCfg( demod, &UIOCfg ) ); + WR16( demod->myI2CDevAddr, SIO_PDR_SMA_TX_CFG__A, 0x13 ); + WR16( demod->myI2CDevAddr, SIO_PDR_SMA_TX_GPIO_FNC__A, 0x03 ); + + /* Write magic word to disable pdr reg write */ + WR16( demod->myI2CDevAddr, SIO_TOP_COMM_KEY__A, 0x0000 ); + + return ( DRX_STS_OK ); +rw_error: + return (DRX_STS_ERROR); +} + +/** +* \fn DRXStatus_t CtrlSetCfgSmartAnt() +* \brief Set Smart Antenna. +* \param pointer to DRXJCfgSmartAnt_t. +* \return DRXStatus_t. +* +*/ +static DRXStatus_t +CtrlSetCfgSmartAnt ( pDRXDemodInstance_t demod, pDRXJCfgSmartAnt_t smartAnt ) +{ + pDRXJData_t extAttr = NULL; + pI2CDeviceAddr_t devAddr = NULL; + u16_t data = 0; + u32_t startTime = 0; + static Bool_t bitInverted = FALSE; + + devAddr = demod -> myI2CDevAddr; + extAttr = (pDRXJData_t)demod->myExtAttr; + + /* check arguments */ + if ( smartAnt == NULL ) + { + return (DRX_STS_INVALID_ARG); + } + + if ( bitInverted != extAttr->smartAntInverted + || extAttr->uioSmaTxMode != DRX_UIO_MODE_FIRMWARE_SMA) + { + CHK_ERROR(SmartAntInit(demod)); + bitInverted = extAttr->smartAntInverted; + } + + /* Write magic word to enable pdr reg write */ + WR16( demod->myI2CDevAddr, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY ); + + switch (smartAnt->io) + { + case DRXJ_SMT_ANT_OUTPUT: + /* enable Tx if Mode B (input) is supported */ + /* + RR16( devAddr, SIO_SA_TX_COMMAND__A, &data ); + WR16( devAddr, SIO_SA_TX_COMMAND__A, data | SIO_SA_TX_COMMAND_TX_ENABLE__M ); + */ + startTime = DRXBSP_HST_Clock(); + do{ + RR16( devAddr, SIO_SA_TX_STATUS__A, &data ); + } while ( (data & SIO_SA_TX_STATUS_BUSY__M) && ( (DRXBSP_HST_Clock() - startTime) < DRXJ_MAX_WAITTIME ) ); + + if ( data & SIO_SA_TX_STATUS_BUSY__M ) + { + return (DRX_STS_ERROR); + } + + /* write to smart antenna configuration register */ + WR16( devAddr, SIO_SA_TX_DATA0__A, 0x9200 + | ((smartAnt->ctrlData & 0x0001) << 8) + | ((smartAnt->ctrlData & 0x0002) << 10) + | ((smartAnt->ctrlData & 0x0004) << 12) + ); + WR16( devAddr, SIO_SA_TX_DATA1__A, 0x4924 + | ((smartAnt->ctrlData & 0x0008) >> 2) + | ((smartAnt->ctrlData & 0x0010) ) + | ((smartAnt->ctrlData & 0x0020) << 2) + | ((smartAnt->ctrlData & 0x0040) << 4) + | ((smartAnt->ctrlData & 0x0080) << 6) + ); + WR16( devAddr, SIO_SA_TX_DATA2__A, 0x2492 + | ((smartAnt->ctrlData & 0x0100) >> 8) + | ((smartAnt->ctrlData & 0x0200) >> 6) + | ((smartAnt->ctrlData & 0x0400) >> 4) + | ((smartAnt->ctrlData & 0x0800) >> 2) + | ((smartAnt->ctrlData & 0x1000) ) + | ((smartAnt->ctrlData & 0x2000) << 2) + ); + WR16( devAddr, SIO_SA_TX_DATA3__A, 0xff8d ); + + /* trigger the sending */ + WR16( devAddr, SIO_SA_TX_LENGTH__A, 56 ); + + break; + case DRXJ_SMT_ANT_INPUT: + /* disable Tx if Mode B (input) is supported */ + /* + RR16( devAddr, SIO_SA_TX_COMMAND__A, &data ); + WR16( devAddr, SIO_SA_TX_COMMAND__A, data & (~SIO_SA_TX_COMMAND_TX_ENABLE__M) ); + */ + default: + return (DRX_STS_INVALID_ARG); + } + /* Write magic word to enable pdr reg write */ + WR16( demod->myI2CDevAddr, SIO_TOP_COMM_KEY__A, 0x0000 ); + + return ( DRX_STS_OK ); +rw_error: + return (DRX_STS_ERROR); +} + +static DRXStatus_t +SCUCommand( pI2CDeviceAddr_t devAddr, pDRXJSCUCmd_t cmd ) +{ + u16_t curCmd = 0; + u32_t startTime = 0; + + /* Check param */ + if ( cmd == NULL ) + return (DRX_STS_INVALID_ARG); + + /* Wait until SCU command interface is ready to receive command */ + RR16( devAddr, SCU_RAM_COMMAND__A, &curCmd ); + if ( curCmd != DRX_SCU_READY ) + { + return (DRX_STS_ERROR); + } + + switch ( cmd->parameterLen ) + { + case 5: + WR16( devAddr, SCU_RAM_PARAM_4__A , *(cmd->parameter + 4)); /* fallthrough */ + case 4: + WR16( devAddr, SCU_RAM_PARAM_3__A , *(cmd->parameter + 3)); /* fallthrough */ + case 3: + WR16( devAddr, SCU_RAM_PARAM_2__A , *(cmd->parameter + 2)); /* fallthrough */ + case 2: + WR16( devAddr, SCU_RAM_PARAM_1__A , *(cmd->parameter + 1)); /* fallthrough */ + case 1: + WR16( devAddr, SCU_RAM_PARAM_0__A , *(cmd->parameter + 0)); /* fallthrough */ + case 0: + /* do nothing */ + break; + default: + /* this number of parameters is not supported */ + return (DRX_STS_ERROR); + } + WR16( devAddr, SCU_RAM_COMMAND__A, cmd->command ); + + /* Wait until SCU has processed command */ + startTime = DRXBSP_HST_Clock(); + do{ + RR16( devAddr, SCU_RAM_COMMAND__A, &curCmd ); + } while ( ! ( curCmd == DRX_SCU_READY ) && ( (DRXBSP_HST_Clock() - startTime) < DRXJ_MAX_WAITTIME ) ); + + if ( curCmd != DRX_SCU_READY ) + { + return (DRX_STS_ERROR); + } + + /* read results */ + if ( (cmd->resultLen > 0) && (cmd->result != NULL) ) + { + s16_t err; + + switch ( cmd->resultLen ) + { + case 4: + RR16( devAddr, SCU_RAM_PARAM_3__A , cmd->result + 3); /* fallthrough */ + case 3: + RR16( devAddr, SCU_RAM_PARAM_2__A , cmd->result + 2); /* fallthrough */ + case 2: + RR16( devAddr, SCU_RAM_PARAM_1__A , cmd->result + 1); /* fallthrough */ + case 1: + RR16( devAddr, SCU_RAM_PARAM_0__A , cmd->result + 0); /* fallthrough */ + case 0: + /* do nothing */ + break; + default: + /* this number of parameters is not supported */ + return (DRX_STS_ERROR); + } + + + /* Check if an error was reported by SCU */ + err = cmd->result[0]; + + /* check a few fixed error codes */ + if ( ( err == (s16_t)SCU_RAM_PARAM_0_RESULT_UNKSTD ) + || ( err == (s16_t)SCU_RAM_PARAM_0_RESULT_UNKCMD ) + || ( err == (s16_t)SCU_RAM_PARAM_0_RESULT_INVPAR ) + || ( err == (s16_t)SCU_RAM_PARAM_0_RESULT_SIZE ) + ) + { + return DRX_STS_INVALID_ARG; + } + /* here it is assumed that negative means error, and positive no error */ + else if ( err < 0 ) + { + return DRX_STS_ERROR; + } + else + { + return DRX_STS_OK; + } + } + + return (DRX_STS_OK); + + rw_error: + return (DRX_STS_ERROR); +} +/** +* \fn DRXStatus_t DRXJ_DAP_SCUAtomicReadWriteBlock() +* \brief Basic access routine for SCU atomic read or write access +* \param devAddr pointer to i2c dev address +* \param addr destination/source address +* \param datasize size of data buffer in bytes +* \param data pointer to data buffer +* \return DRXStatus_t +* \retval DRX_STS_OK Succes +* \retval DRX_STS_ERROR Timeout, I2C error, illegal bank +* +*/ +#define ADDR_AT_SCU_SPACE(x) ((x - 0x82E000) * 2) +static +DRXStatus_t DRXJ_DAP_SCU_AtomicReadWriteBlock ( + pI2CDeviceAddr_t devAddr, + DRXaddr_t addr, + u16_t datasize, /* max 30 bytes because the limit of SCU parameter */ + pu8_t data, + Bool_t readFlag) +{ + DRXJSCUCmd_t scuCmd; + u16_t setParamParameters[15]; + u16_t cmdResult[15]; + + /* Parameter check */ + if ( ( data == NULL ) || + ( devAddr == NULL ) || + ( (datasize%2)!= 0 ) || + ( (datasize/2) > 16 ) + ) + { + return (DRX_STS_INVALID_ARG); + } + + setParamParameters[1] = (u16_t)ADDR_AT_SCU_SPACE (addr); + if (readFlag) /* read */ + { + setParamParameters[0] = ((~(0x0080)) & datasize); + scuCmd.parameterLen = 2; + scuCmd.resultLen = datasize/2 + 2; + } else { + int i = 0; + + setParamParameters[0] = 0x0080 | datasize; + for (i = 0; i < (datasize/2); i++) + { + setParamParameters[i+2] = (data[2*i] | (data[(2*i)+1]<<8)); + } + scuCmd.parameterLen = datasize / 2 + 2; + scuCmd.resultLen = 1; + } + + scuCmd.command = SCU_RAM_COMMAND_STANDARD_TOP | SCU_RAM_COMMAND_CMD_AUX_SCU_ATOMIC_ACCESS; + scuCmd.result = cmdResult; + scuCmd.parameter = setParamParameters; + CHK_ERROR( SCUCommand( devAddr, &scuCmd ) ); + + if ( readFlag==TRUE ) + { + int i = 0; + /* read data from buffer */ + for (i = 0; i < (datasize/2); i++) + { + data[2*i] = (u8_t) (scuCmd.result[i+2] & 0xFF); + data[(2*i) + 1] = (u8_t) (scuCmd.result[i+2] >> 8 ); + } + } + + return DRX_STS_OK; + + rw_error: + return (DRX_STS_ERROR); + +} + +/*============================================================================*/ + +/** +* \fn DRXStatus_t DRXJ_DAP_AtomicReadReg16() +* \brief Atomic read of 16 bits words +*/ +static +DRXStatus_t DRXJ_DAP_SCU_AtomicReadReg16 ( + pI2CDeviceAddr_t devAddr, + DRXaddr_t addr, + pu16_t data, + DRXflags_t flags) +{ + u8_t buf[2]; + DRXStatus_t rc = DRX_STS_ERROR; + u16_t word = 0; + + if (!data) + { + return DRX_STS_INVALID_ARG; + } + + rc = DRXJ_DAP_SCU_AtomicReadWriteBlock ( devAddr, addr, + 2, buf, TRUE); + + word = (u16_t)(buf[0] + (buf[1] << 8)); + + *data = word; + + return rc; +} +/*============================================================================*/ +/** +* \fn DRXStatus_t DRXJ_DAP_SCU_AtomicWriteReg16() +* \brief Atomic read of 16 bits words +*/ +static +DRXStatus_t DRXJ_DAP_SCU_AtomicWriteReg16 ( + pI2CDeviceAddr_t devAddr, + DRXaddr_t addr, + u16_t data, + DRXflags_t flags) +{ + u8_t buf[2]; + DRXStatus_t rc = DRX_STS_ERROR; + + buf[0] = (u8_t) (data & 0xff); + buf[1] = (u8_t) ((data >> 8) & 0xff); + + rc = DRXJ_DAP_SCU_AtomicReadWriteBlock ( devAddr, addr, + 2, buf, FALSE); + + return rc; +} + +static DRXStatus_t +CtrlI2CWriteRead( pDRXDemodInstance_t demod, + pDRXI2CData_t i2cData ) +{ + return (DRX_STS_FUNC_NOT_AVAILABLE); +} + +DRXStatus_t +TunerI2CWriteRead( pTUNERInstance_t tuner, + pI2CDeviceAddr_t wDevAddr, + u16_t wCount, + pu8_t wData, + pI2CDeviceAddr_t rDevAddr, + u16_t rCount, + pu8_t rData) +{ + pDRXDemodInstance_t demod; + DRXI2CData_t i2cData = { 2, wDevAddr, wCount, wData, rDevAddr, rCount, rData }; + + demod = (pDRXDemodInstance_t) (tuner->myCommonAttr->myUserData); + + return ( CtrlI2CWriteRead( demod, &i2cData ) ); +} + +/* -------------------------------------------------------------------------- */ +/** +* \brief Measure result of ADC synchronisation +* \param demod demod instance +* \param count (returned) count +* \return DRXStatus_t. +* \retval DRX_STS_OK Success +* \retval DRX_STS_ERROR Failure: I2C error +* +*/ +static DRXStatus_t +ADCSyncMeasurement( pDRXDemodInstance_t demod, + pu16_t count ) +{ + u16_t data = 0; + pI2CDeviceAddr_t devAddr = NULL; + + devAddr = demod -> myI2CDevAddr; + + /* Start measurement */ + WR16( devAddr, IQM_AF_COMM_EXEC__A, IQM_AF_COMM_EXEC_ACTIVE); + WR16( devAddr, IQM_AF_START_LOCK__A, 1); + + /* Wait at least 3*128*(1/sysclk) <<< 1 millisec */ + CHK_ERROR( DRXBSP_HST_Sleep(1)); + + *count = 0; + RR16( devAddr, IQM_AF_PHASE0__A, &data); + if ( data == 127 ) + { + *count = *count+1; + } + RR16( devAddr, IQM_AF_PHASE1__A, &data); + if ( data == 127 ) + { + *count = *count+1; + } + RR16( devAddr, IQM_AF_PHASE2__A, &data); + if ( data == 127 ) + { + *count = *count+1; + } + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} + +/** +* \brief Synchronize analog and digital clock domains +* \param demod demod instance +* \return DRXStatus_t. +* \retval DRX_STS_OK Success +* \retval DRX_STS_ERROR Failure: I2C error or failure to synchronize +* +* An IQM reset will also reset the results of this synchronization. +* After an IQM reset this routine needs to be called again. +* +*/ + +static DRXStatus_t +ADCSynchronization( pDRXDemodInstance_t demod ) +{ + u16_t count = 0; + pI2CDeviceAddr_t devAddr = NULL; + + devAddr = demod -> myI2CDevAddr; + + CHK_ERROR( ADCSyncMeasurement( demod, &count )); + + if (count==1) + { + /* Try sampling on a diffrent edge */ + u16_t clkNeg = 0; + + RR16( devAddr, IQM_AF_CLKNEG__A, &clkNeg); + + clkNeg ^= IQM_AF_CLKNEG_CLKNEGDATA__M; + WR16( devAddr, IQM_AF_CLKNEG__A, clkNeg); + + CHK_ERROR( ADCSyncMeasurement( demod, &count )); + } + + if ( count < 2 ) + { + /* TODO: implement fallback scenarios */ + return (DRX_STS_ERROR); + } + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} + +/** +* \brief Configure IQM AF registers +* \param demod instance of demodulator. +* \param active +* \return DRXStatus_t. +*/ +static DRXStatus_t +IQMSetAf ( pDRXDemodInstance_t demod, Bool_t active ) +{ + u16_t data = 0; + pI2CDeviceAddr_t devAddr = NULL; + pDRXJData_t extAttr = NULL; + + extAttr = (pDRXJData_t)demod->myExtAttr; + devAddr = demod -> myI2CDevAddr; + + /* Configure IQM */ + RR16( devAddr, IQM_AF_STDBY__A , &data ); + if( !active ) + { + data &= ((~IQM_AF_STDBY_STDBY_ADC_A2_ACTIVE) + & (~IQM_AF_STDBY_STDBY_AMP_A2_ACTIVE) + & (~IQM_AF_STDBY_STDBY_PD_A2_ACTIVE) + & (~IQM_AF_STDBY_STDBY_TAGC_IF_A2_ACTIVE) + & (~IQM_AF_STDBY_STDBY_TAGC_RF_A2_ACTIVE) + ); + } else /* active */ + { + data |= (IQM_AF_STDBY_STDBY_ADC_A2_ACTIVE + | IQM_AF_STDBY_STDBY_AMP_A2_ACTIVE + | IQM_AF_STDBY_STDBY_PD_A2_ACTIVE + | IQM_AF_STDBY_STDBY_TAGC_IF_A2_ACTIVE + | IQM_AF_STDBY_STDBY_TAGC_RF_A2_ACTIVE + ); + } + WR16( devAddr, IQM_AF_STDBY__A , data ); + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} + +/* -------------------------------------------------------------------------- */ +static DRXStatus_t +CtrlSetCfgATVOutput( pDRXDemodInstance_t demod , + pDRXJCfgAtvOutput_t outputCfg ); + +/** +* \brief set configuration of pin-safe mode +* \param demod instance of demodulator. +* \param enable boolean; TRUE: activate pin-safe mode, FALSE: de-activate p.s.m. +* \return DRXStatus_t. +*/ +static DRXStatus_t +CtrlSetCfgPdrSafeMode ( pDRXDemodInstance_t demod, + pBool_t enable ) +{ + pDRXJData_t extAttr = (pDRXJData_t) NULL; + pI2CDeviceAddr_t devAddr = (pI2CDeviceAddr_t) NULL; + pDRXCommonAttr_t commonAttr = (pDRXCommonAttr_t) NULL; + + if ( enable == NULL) + { + return (DRX_STS_INVALID_ARG); + } + + devAddr = demod->myI2CDevAddr; + extAttr = (pDRXJData_t) demod->myExtAttr; + commonAttr = demod->myCommonAttr; + + /* Write magic word to enable pdr reg write */ + WR16( devAddr, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY ); + + if ( *enable == TRUE ) + { + Bool_t bridgeEnabled = FALSE; + + /* MPEG pins to input */ + WR16 ( devAddr, SIO_PDR_MSTRT_CFG__A, DRXJ_PIN_SAFE_MODE ); + WR16 ( devAddr, SIO_PDR_MERR_CFG__A, DRXJ_PIN_SAFE_MODE ); + WR16 ( devAddr, SIO_PDR_MCLK_CFG__A, DRXJ_PIN_SAFE_MODE ); + WR16 ( devAddr, SIO_PDR_MVAL_CFG__A, DRXJ_PIN_SAFE_MODE ); + WR16 ( devAddr, SIO_PDR_MD0_CFG__A, DRXJ_PIN_SAFE_MODE ); + WR16 ( devAddr, SIO_PDR_MD1_CFG__A, DRXJ_PIN_SAFE_MODE ); + WR16 ( devAddr, SIO_PDR_MD2_CFG__A, DRXJ_PIN_SAFE_MODE ); + WR16 ( devAddr, SIO_PDR_MD3_CFG__A, DRXJ_PIN_SAFE_MODE ); + WR16 ( devAddr, SIO_PDR_MD4_CFG__A, DRXJ_PIN_SAFE_MODE ); + WR16 ( devAddr, SIO_PDR_MD5_CFG__A, DRXJ_PIN_SAFE_MODE ); + WR16 ( devAddr, SIO_PDR_MD6_CFG__A, DRXJ_PIN_SAFE_MODE ); + WR16 ( devAddr, SIO_PDR_MD7_CFG__A, DRXJ_PIN_SAFE_MODE ); + + /* PD_I2C_SDA2 Bridge off, Port2 Inactive + PD_I2C_SCL2 Bridge off, Port2 Inactive */ + CHK_ERROR( CtrlI2CBridge( demod, &bridgeEnabled ) ); + WR16 ( devAddr, SIO_PDR_I2C_SDA2_CFG__A, DRXJ_PIN_SAFE_MODE ); + WR16 ( devAddr, SIO_PDR_I2C_SCL2_CFG__A, DRXJ_PIN_SAFE_MODE ); + + /* PD_GPIO Store and set to input + PD_VSYNC Store and set to input + PD_SMA_RX Store and set to input + PD_SMA_TX Store and set to input */ + RR16 ( devAddr, SIO_PDR_GPIO_CFG__A, &extAttr->pdrSafeRestoreValGpio ); + RR16 ( devAddr, SIO_PDR_VSYNC_CFG__A, &extAttr->pdrSafeRestoreValVSync ); + RR16 ( devAddr, SIO_PDR_SMA_RX_CFG__A, &extAttr->pdrSafeRestoreValSmaRx ); + RR16 ( devAddr, SIO_PDR_SMA_TX_CFG__A, &extAttr->pdrSafeRestoreValSmaTx ); + WR16 ( devAddr, SIO_PDR_GPIO_CFG__A, DRXJ_PIN_SAFE_MODE ); + WR16 ( devAddr, SIO_PDR_VSYNC_CFG__A, DRXJ_PIN_SAFE_MODE ); + WR16 ( devAddr, SIO_PDR_SMA_RX_CFG__A, DRXJ_PIN_SAFE_MODE ); + WR16 ( devAddr, SIO_PDR_SMA_TX_CFG__A, DRXJ_PIN_SAFE_MODE ); + + /* PD_RF_AGC Analog DAC outputs, cannot be set to input or tristate! + PD_IF_AGC Analog DAC outputs, cannot be set to input or tristate! */ + CHK_ERROR( IQMSetAf ( demod, FALSE ) ); + + /* PD_CVBS Analog DAC output, standby mode + PD_SIF Analog DAC output, standby mode */ + WR16 ( devAddr, ATV_TOP_STDBY__A, ( ATV_TOP_STDBY_SIF_STDBY_STANDBY & + (~ATV_TOP_STDBY_CVBS_STDBY_A2_ACTIVE) ) ); + + /* PD_I2S_CL Input + PD_I2S_DA Input + PD_I2S_WS Input */ + WR16 ( devAddr, SIO_PDR_I2S_CL_CFG__A, DRXJ_PIN_SAFE_MODE ); + WR16 ( devAddr, SIO_PDR_I2S_DA_CFG__A, DRXJ_PIN_SAFE_MODE ); + WR16 ( devAddr, SIO_PDR_I2S_WS_CFG__A, DRXJ_PIN_SAFE_MODE ); + } + else + { + /* No need to restore MPEG pins; + is done in SetStandard/SetChannel */ + + /* PD_I2C_SDA2 Port2 active + PD_I2C_SCL2 Port2 active */ + WR16 ( devAddr, SIO_PDR_I2C_SDA2_CFG__A, SIO_PDR_I2C_SDA2_CFG__PRE ); + WR16 ( devAddr, SIO_PDR_I2C_SCL2_CFG__A, SIO_PDR_I2C_SCL2_CFG__PRE ); + + /* PD_GPIO Restore + PD_VSYNC Restore + PD_SMA_RX Restore + PD_SMA_TX Restore */ + WR16 ( devAddr, SIO_PDR_GPIO_CFG__A, extAttr->pdrSafeRestoreValGpio ); + WR16 ( devAddr, SIO_PDR_VSYNC_CFG__A, extAttr->pdrSafeRestoreValVSync ); + WR16 ( devAddr, SIO_PDR_SMA_RX_CFG__A, extAttr->pdrSafeRestoreValSmaRx ); + WR16 ( devAddr, SIO_PDR_SMA_TX_CFG__A, extAttr->pdrSafeRestoreValSmaTx ); + + /* PD_RF_AGC, PD_IF_AGC + No need to restore; will be restored in SetStandard/SetChannel */ + + /* PD_CVBS, PD_SIF + No need to restore; will be restored in SetStandard/SetChannel */ + + /* PD_I2S_CL, PD_I2S_DA, PD_I2S_WS + Should be restored via DRX_CTRL_SET_AUD */ + } + + /* Write magic word to disable pdr reg write */ + WR16 ( devAddr, SIO_TOP_COMM_KEY__A, 0x0000 ); + extAttr->pdrSafeMode = *enable; + + return (DRX_STS_OK); + + rw_error: + return (DRX_STS_ERROR); +} + +/* -------------------------------------------------------------------------- */ + +/** +* \brief get configuration of pin-safe mode +* \param demod instance of demodulator. +* \param enable boolean indicating whether pin-safe mode is active +* \return DRXStatus_t. +*/ +static DRXStatus_t +CtrlGetCfgPdrSafeMode ( pDRXDemodInstance_t demod, + pBool_t enabled ) +{ + pDRXJData_t extAttr = (pDRXJData_t) NULL; + + if ( enabled == NULL ) + { + return (DRX_STS_INVALID_ARG); + } + + extAttr = (pDRXJData_t) demod->myExtAttr; + *enabled = extAttr->pdrSafeMode; + + return (DRX_STS_OK); +} + +/** +* \brief Verifies whether microcode can be loaded. +* \param demod Demodulator instance. +* \return DRXStatus_t. +*/ +static DRXStatus_t +CtrlValidateUCode (pDRXDemodInstance_t demod) +{ + u32_t mcDev, mcPatch; + u16_t verType; + + /* Check device. + * Disallow microcode if: + * - MC has version record AND + * - device ID in version record is not 0 AND + * - product ID in version record's device ID does not + * match DRXJ1 product IDs - 0x393 or 0x394 + */ + DRX_GET_MCVERTYPE (demod, verType); + DRX_GET_MCDEV (demod, mcDev); + DRX_GET_MCPATCH (demod, mcPatch); + + if (DRX_ISMCVERTYPE (verType)) + { + if ((mcDev != 0) && + (((mcDev >> 16) & 0xFFF) != 0x393) && + (((mcDev >> 16) & 0xFFF) != 0x394)) + { + /* Microcode is marked for another device - error */ + return DRX_STS_INVALID_ARG; + } + else if (mcPatch != 0) + { + /* Patch not allowed because there is no ROM */ + return DRX_STS_INVALID_ARG; + } + } + + /* Everything else: OK */ + return DRX_STS_OK; +} + +/*============================================================================*/ +/*== END AUXILIARY FUNCTIONS ==*/ +/*============================================================================*/ + +/*============================================================================*/ +/*============================================================================*/ +/*== 8VSB & QAM COMMON DATAPATH FUNCTIONS ==*/ +/*============================================================================*/ +/*============================================================================*/ +/** +* \fn DRXStatus_t InitAGC () +* \brief Initialize AGC for all standards. +* \param demod instance of demodulator. +* \param channel pointer to channel data. +* \return DRXStatus_t. +*/ +static DRXStatus_t +InitAGC ( pDRXDemodInstance_t demod ) +{ + pI2CDeviceAddr_t devAddr = NULL; + pDRXCommonAttr_t commonAttr = NULL; + pDRXJData_t extAttr = NULL; + pDRXJCfgAgc_t pAgcRfSettings = NULL; + pDRXJCfgAgc_t pAgcIfSettings = NULL; + u16_t IngainTgtMax = 0; + u16_t clpDirTo = 0; + u16_t snsSumMax = 0; + u16_t clpSumMax = 0; + u16_t snsDirTo = 0; + u16_t kiInnergainMin = 0; + u16_t agcKi = 0; + u16_t kiMax = 0; + u16_t ifIaccuHiTgtMin = 0; + u16_t data = 0; + u16_t agcKiDgain = 0; + u16_t kiMin = 0; + u16_t clpCtrlMode = 0; + u16_t agcRf = 0; + u16_t agcIf = 0; + devAddr = demod->myI2CDevAddr; + commonAttr = (pDRXCommonAttr_t) demod->myCommonAttr; + extAttr = (pDRXJData_t)demod->myExtAttr; + + switch (extAttr->standard) + { + case DRX_STANDARD_8VSB : + clpSumMax = 1023; + clpDirTo = (u16_t)(-9); + snsSumMax = 1023; + snsDirTo = (u16_t)(-9); + kiInnergainMin = (u16_t)(-32768); + kiMax = 0x032C; + agcKiDgain = 0xC; + ifIaccuHiTgtMin = 2047; + kiMin = 0x0117; + IngainTgtMax = 16383; + clpCtrlMode = 0; + WR16( devAddr, SCU_RAM_AGC_KI_MINGAIN__A, 0x7fff ); + WR16( devAddr, SCU_RAM_AGC_KI_MAXGAIN__A, 0x0 ); + WR16( devAddr, SCU_RAM_AGC_CLP_SUM__A, 0 ); + WR16( devAddr, SCU_RAM_AGC_CLP_CYCCNT__A, 0 ); + WR16( devAddr, SCU_RAM_AGC_CLP_DIR_WD__A, 0 ); + WR16( devAddr, SCU_RAM_AGC_CLP_DIR_STP__A, 1 ); + WR16( devAddr, SCU_RAM_AGC_SNS_SUM__A, 0 ); + WR16( devAddr, SCU_RAM_AGC_SNS_CYCCNT__A, 0 ); + WR16( devAddr, SCU_RAM_AGC_SNS_DIR_WD__A, 0 ); + WR16( devAddr, SCU_RAM_AGC_SNS_DIR_STP__A, 1 ); + WR16( devAddr, SCU_RAM_AGC_INGAIN__A, 1024 ); + WR16( devAddr, SCU_RAM_VSB_AGC_POW_TGT__A, 22600 ); + WR16( devAddr, SCU_RAM_AGC_INGAIN_TGT__A, 13200 ); + pAgcIfSettings = &(extAttr->vsbIfAgcCfg); + pAgcRfSettings = &(extAttr->vsbRfAgcCfg); + break; +#ifndef DRXJ_VSB_ONLY + case DRX_STANDARD_ITU_A: + case DRX_STANDARD_ITU_C: + case DRX_STANDARD_ITU_B: + IngainTgtMax = 5119; + clpSumMax = 1023; + clpDirTo = (u16_t)(-5); + snsSumMax = 127; + snsDirTo = (u16_t)(-3); + kiInnergainMin = 0; + kiMax = 0x0657; + ifIaccuHiTgtMin = 2047; + agcKiDgain = 0x7; + kiMin = 0x0117; + clpCtrlMode = 0; + WR16( devAddr, SCU_RAM_AGC_KI_MINGAIN__A, 0x7fff ); + WR16( devAddr, SCU_RAM_AGC_KI_MAXGAIN__A, 0x0 ); + WR16( devAddr, SCU_RAM_AGC_CLP_SUM__A, 0 ); + WR16( devAddr, SCU_RAM_AGC_CLP_CYCCNT__A, 0 ); + WR16( devAddr, SCU_RAM_AGC_CLP_DIR_WD__A, 0 ); + WR16( devAddr, SCU_RAM_AGC_CLP_DIR_STP__A, 1 ); + WR16( devAddr, SCU_RAM_AGC_SNS_SUM__A, 0 ); + WR16( devAddr, SCU_RAM_AGC_SNS_CYCCNT__A, 0 ); + WR16( devAddr, SCU_RAM_AGC_SNS_DIR_WD__A, 0 ); + WR16( devAddr, SCU_RAM_AGC_SNS_DIR_STP__A, 1 ); + pAgcIfSettings = &(extAttr->qamIfAgcCfg); + pAgcRfSettings = &(extAttr->qamRfAgcCfg); + WR16( devAddr, SCU_RAM_AGC_INGAIN_TGT__A, pAgcIfSettings->top ); + + RR16( devAddr, SCU_RAM_AGC_KI__A, &agcKi ); + agcKi &= 0xf000; + WR16( devAddr, SCU_RAM_AGC_KI__A, agcKi ); + break; +#endif +#ifndef DRXJ_DIGITAL_ONLY + case DRX_STANDARD_FM: + clpSumMax = 1023; + snsSumMax = 1023; + kiInnergainMin = (u16_t)(-32768); + ifIaccuHiTgtMin = 2047; + agcKiDgain = 0x7; + kiMin = 0x0225; + kiMax = 0x0547; + clpDirTo = (u16_t)(-9); + snsDirTo = (u16_t)(-9); + IngainTgtMax = 9000; + clpCtrlMode = 1; + pAgcIfSettings = &(extAttr->atvIfAgcCfg); + pAgcRfSettings = &(extAttr->atvRfAgcCfg); + WR16( devAddr, SCU_RAM_AGC_INGAIN_TGT__A, pAgcIfSettings->top ); + break; + case DRX_STANDARD_NTSC: + case DRX_STANDARD_PAL_SECAM_BG: + case DRX_STANDARD_PAL_SECAM_DK: + case DRX_STANDARD_PAL_SECAM_I : + clpSumMax = 1023; + snsSumMax = 1023; + kiInnergainMin = (u16_t)(-32768); + ifIaccuHiTgtMin = 2047; + agcKiDgain = 0x7; + kiMin = 0x0225; + kiMax = 0x0547; + clpDirTo = (u16_t)(-9); + IngainTgtMax = 9000; + pAgcIfSettings = &(extAttr->atvIfAgcCfg); + pAgcRfSettings = &(extAttr->atvRfAgcCfg); + snsDirTo = (u16_t)(-9); + clpCtrlMode = 1; + WR16( devAddr, SCU_RAM_AGC_INGAIN_TGT__A, pAgcIfSettings->top ); + break; + case DRX_STANDARD_PAL_SECAM_L : + case DRX_STANDARD_PAL_SECAM_LP: + clpSumMax = 1023; + snsSumMax = 1023; + kiInnergainMin = (u16_t)(-32768); + ifIaccuHiTgtMin = 2047; + agcKiDgain = 0x7; + kiMin = 0x0225; + kiMax = 0x0547; + clpDirTo = (u16_t)(-9); + snsDirTo = (u16_t)(-9); + IngainTgtMax = 9000; + clpCtrlMode = 1; + pAgcIfSettings = &(extAttr->atvIfAgcCfg); + pAgcRfSettings = &(extAttr->atvRfAgcCfg); + WR16( devAddr, SCU_RAM_AGC_INGAIN_TGT__A, pAgcIfSettings->top ); + break; +#endif + default: + return ( DRX_STS_INVALID_ARG ); + } + + /* for new AGC interface */ + WR16( devAddr, SCU_RAM_AGC_INGAIN_TGT_MIN__A, pAgcIfSettings->top ); + WR16( devAddr, SCU_RAM_AGC_INGAIN__A, pAgcIfSettings->top ); /* Gain fed from inner to outer AGC */ + WR16( devAddr, SCU_RAM_AGC_INGAIN_TGT_MAX__A, IngainTgtMax ); + WR16( devAddr, SCU_RAM_AGC_IF_IACCU_HI_TGT_MIN__A, ifIaccuHiTgtMin ); + WR16( devAddr, SCU_RAM_AGC_IF_IACCU_HI__A, 0 ); /* set to pAgcSettings->top before */ + WR16( devAddr, SCU_RAM_AGC_IF_IACCU_LO__A, 0 ); + WR16( devAddr, SCU_RAM_AGC_RF_IACCU_HI__A, 0 ); + WR16( devAddr, SCU_RAM_AGC_RF_IACCU_LO__A, 0 ); + WR16( devAddr, SCU_RAM_AGC_RF_MAX__A, 32767 ); + WR16( devAddr, SCU_RAM_AGC_CLP_SUM_MAX__A, clpSumMax ); + WR16( devAddr, SCU_RAM_AGC_SNS_SUM_MAX__A, snsSumMax ); + WR16( devAddr, SCU_RAM_AGC_KI_INNERGAIN_MIN__A, kiInnergainMin ); + WR16( devAddr, SCU_RAM_AGC_FAST_SNS_CTRL_DELAY__A, 50 ); + WR16( devAddr, SCU_RAM_AGC_KI_CYCLEN__A, 500 ); + WR16( devAddr, SCU_RAM_AGC_SNS_CYCLEN__A, 500 ); + WR16( devAddr, SCU_RAM_AGC_KI_MAXMINGAIN_TH__A, 20 ); + WR16( devAddr, SCU_RAM_AGC_KI_MIN__A, kiMin ); + WR16( devAddr, SCU_RAM_AGC_KI_MAX__A, kiMax ); + WR16( devAddr, SCU_RAM_AGC_KI_RED__A, 0 ); + WR16( devAddr, SCU_RAM_AGC_CLP_SUM_MIN__A, 8 ); + WR16( devAddr, SCU_RAM_AGC_CLP_CYCLEN__A, 500 ); + WR16( devAddr, SCU_RAM_AGC_CLP_DIR_TO__A, clpDirTo ); + WR16( devAddr, SCU_RAM_AGC_SNS_SUM_MIN__A, 8 ); + WR16( devAddr, SCU_RAM_AGC_SNS_DIR_TO__A, snsDirTo ); + WR16( devAddr, SCU_RAM_AGC_FAST_CLP_CTRL_DELAY__A, 50 ); + WR16( devAddr, SCU_RAM_AGC_CLP_CTRL_MODE__A, clpCtrlMode ); + + agcRf = 0x800 + pAgcRfSettings->cutOffCurrent; + if ( commonAttr->tunerRfAgcPol == TRUE ) + { + agcRf = 0x87ff - agcRf; + } + + agcIf = 0x800; + if ( commonAttr->tunerIfAgcPol == TRUE ) + { + agcRf = 0x87ff - agcRf; + } + + WR16( devAddr, IQM_AF_AGC_RF__A, agcRf ); + WR16( devAddr, IQM_AF_AGC_IF__A, agcIf ); + + /* Set/restore Ki DGAIN factor */ + RR16( devAddr, SCU_RAM_AGC_KI__A, &data ); + data &= ~SCU_RAM_AGC_KI_DGAIN__M; + data |= ( agcKiDgain << SCU_RAM_AGC_KI_DGAIN__B ); + WR16( devAddr, SCU_RAM_AGC_KI__A, data ); + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} + +/** +* \fn DRXStatus_t SetFrequency () +* \brief Set frequency shift. +* \param demod instance of demodulator. +* \param channel pointer to channel data. +* \param tunerFreqOffset residual frequency from tuner. +* \return DRXStatus_t. +*/ +static DRXStatus_t +SetFrequency ( pDRXDemodInstance_t demod, + pDRXChannel_t channel, + DRXFrequency_t tunerFreqOffset + ) +{ + pI2CDeviceAddr_t devAddr = NULL; + pDRXCommonAttr_t commonAttr = NULL; + DRXFrequency_t samplingFrequency = 0; + DRXFrequency_t frequencyShift = 0; + DRXFrequency_t ifFreqActual = 0; + DRXFrequency_t rfFreqResidual = 0; + DRXFrequency_t adcFreq = 0; + DRXFrequency_t intermediateFreq = 0; + u32_t iqmFsRateOfs = 0; + pDRXJData_t extAttr = NULL; + Bool_t adcFlip = TRUE; + Bool_t selectPosImage = FALSE; + Bool_t rfMirror = FALSE; + Bool_t tunerMirror = TRUE; + Bool_t imageToSelect = TRUE; + DRXFrequency_t fmFrequencyShift = 0; + + devAddr = demod -> myI2CDevAddr; + commonAttr = (pDRXCommonAttr_t) demod -> myCommonAttr; + extAttr = (pDRXJData_t)demod->myExtAttr; + rfFreqResidual = -1 * tunerFreqOffset; + rfMirror = (extAttr->mirror == DRX_MIRROR_YES)?TRUE:FALSE; + tunerMirror = demod->myCommonAttr->mirrorFreqSpect?FALSE:TRUE; + /* + Program frequency shifter + No need to account for mirroring on RF + */ + switch (extAttr->standard) + { + case DRX_STANDARD_ITU_A: /* fallthrough */ + case DRX_STANDARD_ITU_C: /* fallthrough */ + case DRX_STANDARD_PAL_SECAM_LP: /* fallthrough */ + case DRX_STANDARD_8VSB: + selectPosImage = TRUE; + break; + case DRX_STANDARD_FM: + /* After IQM FS sound carrier must appear at 4 Mhz in spect. + Sound carrier is already 3Mhz above centre frequency due + to tuner setting so now add an extra shift of 1MHz... */ + fmFrequencyShift = 1000; + case DRX_STANDARD_ITU_B: /* fallthrough */ + case DRX_STANDARD_NTSC: /* fallthrough */ + case DRX_STANDARD_PAL_SECAM_BG: /* fallthrough */ + case DRX_STANDARD_PAL_SECAM_DK: /* fallthrough */ + case DRX_STANDARD_PAL_SECAM_I: /* fallthrough */ + case DRX_STANDARD_PAL_SECAM_L: + selectPosImage = FALSE; + break; + default: + return ( DRX_STS_INVALID_ARG ); + } + intermediateFreq = demod->myCommonAttr->intermediateFreq; + samplingFrequency = demod->myCommonAttr->sysClockFreq/3; + if ( tunerMirror == TRUE ) + { + /* tuner doesn't mirror */ + ifFreqActual = intermediateFreq + rfFreqResidual + fmFrequencyShift; + } else { + /* tuner mirrors */ + ifFreqActual = intermediateFreq - rfFreqResidual - fmFrequencyShift; + } + if ( ifFreqActual > samplingFrequency / 2) + { + /* adc mirrors */ + adcFreq = samplingFrequency - ifFreqActual; + adcFlip = TRUE; + } else { + /* adc doesn't mirror */ + adcFreq = ifFreqActual; + adcFlip = FALSE; + } + + frequencyShift = adcFreq; + imageToSelect = (Bool_t)(rfMirror ^ tunerMirror ^ adcFlip ^ selectPosImage); + iqmFsRateOfs = Frac28(frequencyShift,samplingFrequency); + + if (imageToSelect) + iqmFsRateOfs = ~iqmFsRateOfs + 1; + + /* Program frequency shifter with tuner offset compensation */ + /* frequencyShift += tunerFreqOffset; TODO */ + WR32( devAddr, IQM_FS_RATE_OFS_LO__A , iqmFsRateOfs ); + extAttr->iqmFsRateOfs = iqmFsRateOfs; + extAttr->posImage = (Bool_t)(rfMirror ^ tunerMirror ^ selectPosImage); + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} + +/** +* \fn DRXStatus_t GetSigStrength() +* \brief Retrieve signal strength for VSB and QAM. +* \param demod Pointer to demod instance +* \param u16-t Pointer to signal strength data; range 0, .. , 100. +* \return DRXStatus_t. +* \retval DRX_STS_OK sigStrength contains valid data. +* \retval DRX_STS_INVALID_ARG sigStrength is NULL. +* \retval DRX_STS_ERROR Erroneous data, sigStrength contains invalid data. +*/ +#define DRXJ_AGC_TOP 0x2800 +#define DRXJ_AGC_SNS 0x1600 +#define DRXJ_RFAGC_MAX 0x3fff +#define DRXJ_RFAGC_MIN 0x800 + +static DRXStatus_t +GetSigStrength( pDRXDemodInstance_t demod, + pu16_t sigStrength ) +{ + u16_t rfGain = 0; + u16_t ifGain = 0; + u16_t ifAgcSns = 0; + u16_t ifAgcTop = 0; + u16_t rfAgcMax = 0; + u16_t rfAgcMin = 0; + pDRXJData_t extAttr = NULL; + pI2CDeviceAddr_t devAddr = NULL; + + extAttr = (pDRXJData_t)demod->myExtAttr; + devAddr = demod -> myI2CDevAddr; + + RR16( devAddr, IQM_AF_AGC_IF__A, &ifGain ); + ifGain &= IQM_AF_AGC_IF__M; + RR16( devAddr, IQM_AF_AGC_RF__A, &rfGain ); + rfGain &= IQM_AF_AGC_RF__M; + + ifAgcSns = DRXJ_AGC_SNS; + ifAgcTop = DRXJ_AGC_TOP; + rfAgcMax = DRXJ_RFAGC_MAX; + rfAgcMin = DRXJ_RFAGC_MIN; + + if (ifGain > ifAgcTop) + { + if (rfGain > rfAgcMax) + *sigStrength = 100; + else if (rfGain > rfAgcMin) + { + CHK_ZERO (rfAgcMax - rfAgcMin); + *sigStrength = 75 + 25 * (rfGain - rfAgcMin) / (rfAgcMax - rfAgcMin); + } + else + *sigStrength = 75; + } + else if (ifGain > ifAgcSns) + { + CHK_ZERO(ifAgcTop - ifAgcSns); + *sigStrength = 20 + 55* (ifGain - ifAgcSns)/ (ifAgcTop - ifAgcSns); + } + else + { + CHK_ZERO (ifAgcSns); + *sigStrength = (20 * ifGain / ifAgcSns); + } + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} + +/** +* \fn DRXStatus_t GetAccPktErr() +* \brief Retrieve signal strength for VSB and QAM. +* \param demod Pointer to demod instance +* \param packetErr Pointer to packet error +* \return DRXStatus_t. +* \retval DRX_STS_OK sigStrength contains valid data. +* \retval DRX_STS_INVALID_ARG sigStrength is NULL. +* \retval DRX_STS_ERROR Erroneous data, sigStrength contains invalid data. +*/ +#ifdef DRXJ_SIGNAL_ACCUM_ERR +static DRXStatus_t +GetAccPktErr( pDRXDemodInstance_t demod, + pu16_t packetErr ) +{ + static u16_t pktErr = 0; + static u16_t lastPktErr = 0; + u16_t data = 0; + pDRXJData_t extAttr = NULL; + pI2CDeviceAddr_t devAddr = NULL; + + extAttr = (pDRXJData_t)demod->myExtAttr; + devAddr = demod -> myI2CDevAddr; + + RR16( devAddr, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, &data ); + if ( extAttr->resetPktErrAcc == TRUE ) + { + lastPktErr = data; + pktErr = 0; + extAttr->resetPktErrAcc = FALSE; + } + + if (data < lastPktErr) + { + pktErr += 0xffff - lastPktErr; + pktErr += data; + } + else + { + pktErr += (data - lastPktErr); + } + *packetErr = pktErr; + lastPktErr = data; + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} +#endif + +/** +* \fn DRXStatus_t ResetAccPktErr() +* \brief Reset Accumulating packet error count. +* \param demod Pointer to demod instance +* \return DRXStatus_t. +* \retval DRX_STS_OK. +* \retval DRX_STS_ERROR Erroneous data. +*/ +static DRXStatus_t +CtrlSetCfgResetPktErr( pDRXDemodInstance_t demod ) +{ +#ifdef DRXJ_SIGNAL_ACCUM_ERR + pDRXJData_t extAttr = NULL; + u16_t packetError = 0; + + extAttr = (pDRXJData_t)demod->myExtAttr; + extAttr->resetPktErrAcc = TRUE; + /* call to reset counter */ + CHK_ERROR (GetAccPktErr (demod, &packetError)); + + return (DRX_STS_OK); +rw_error: +#endif + return (DRX_STS_ERROR); +} + +/** +* \fn static short GetSTRFreqOffset() +* \brief Get symbol rate offset in QAM & 8VSB mode +* \return Error code +*/ +static DRXStatus_t +GetSTRFreqOffset( pDRXDemodInstance_t demod, + s32_t *STRFreq + ) +{ + u32_t symbolFrequencyRatio = 0; + u32_t symbolNomFrequencyRatio = 0; + + DRXStandard_t standard = DRX_STANDARD_UNKNOWN; + pI2CDeviceAddr_t devAddr = NULL; + pDRXJData_t extAttr = NULL; + + devAddr = demod -> myI2CDevAddr; + extAttr = (pDRXJData_t)demod->myExtAttr; + standard = extAttr->standard; + + ARR32( devAddr, IQM_RC_RATE_LO__A, &symbolFrequencyRatio ); + symbolNomFrequencyRatio = extAttr->iqmRcRateOfs; + + if ( symbolFrequencyRatio > symbolNomFrequencyRatio ) + *STRFreq = -1 * FracTimes1e6( ( symbolFrequencyRatio - symbolNomFrequencyRatio ), (symbolFrequencyRatio + (1 << 23)) ); + else + *STRFreq = FracTimes1e6( ( symbolNomFrequencyRatio - symbolFrequencyRatio ), (symbolFrequencyRatio + (1 << 23)) ); + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} + +/** +* \fn static short GetCTLFreqOffset +* \brief Get the value of CTLFreq in QAM & ATSC mode +* \return Error code +*/ +static DRXStatus_t +GetCTLFreqOffset ( pDRXDemodInstance_t demod, + s32_t *CTLFreq + ) +{ + DRXFrequency_t samplingFrequency = 0; + s32_t currentFrequency = 0; + s32_t nominalFrequency = 0; + s32_t carrierFrequencyShift = 0; + s32_t sign = 1; + u32_t data64Hi = 0; + u32_t data64Lo = 0; + pDRXJData_t extAttr = NULL; + pDRXCommonAttr_t commonAttr = NULL; + pI2CDeviceAddr_t devAddr = NULL; + + devAddr = demod -> myI2CDevAddr; + extAttr = (pDRXJData_t)demod->myExtAttr; + commonAttr = (pDRXCommonAttr_t) demod -> myCommonAttr; + + samplingFrequency = commonAttr->sysClockFreq/3; + + /* both registers are sign extended */ + nominalFrequency = extAttr->iqmFsRateOfs; + ARR32( devAddr, IQM_FS_RATE_LO__A, (pu32_t) ¤tFrequency ); + + if ( extAttr->posImage == TRUE ) + { + /* negative image */ + carrierFrequencyShift = nominalFrequency - currentFrequency; + } else { + /* positive image */ + carrierFrequencyShift = currentFrequency - nominalFrequency; + } + + /* carrier Frequency Shift In Hz */ + if (carrierFrequencyShift < 0) + { + sign = -1; + carrierFrequencyShift *= sign; + } + + /* *CTLFreq = carrierFrequencyShift * 50.625e6 / (1 << 28); */ + Mult32 ( carrierFrequencyShift, samplingFrequency, &data64Hi, &data64Lo ); + *CTLFreq = (s32_t)((((data64Lo >> 28) & 0xf) | (data64Hi << 4)) * sign); + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} + +/*============================================================================*/ + +/** +* \fn DRXStatus_t SetAgcRf () +* \brief Configure RF AGC +* \param demod instance of demodulator. +* \param agcSettings AGC configuration structure +* \return DRXStatus_t. +*/ +static DRXStatus_t +SetAgcRf ( pDRXDemodInstance_t demod, pDRXJCfgAgc_t agcSettings, Bool_t atomic ) +{ + pI2CDeviceAddr_t devAddr = NULL; + pDRXJData_t extAttr = NULL; + pDRXJCfgAgc_t pAgcSettings = NULL; + pDRXCommonAttr_t commonAttr = NULL; + DRXWriteReg16Func_t ScuWr16 = NULL; + DRXReadReg16Func_t ScuRr16 = NULL; + + commonAttr = (pDRXCommonAttr_t) demod -> myCommonAttr; + devAddr = demod -> myI2CDevAddr; + extAttr = (pDRXJData_t)demod->myExtAttr; + + if (atomic) + { + ScuRr16 = DRXJ_DAP_SCU_AtomicReadReg16; + ScuWr16 = DRXJ_DAP_SCU_AtomicWriteReg16; + } + else + { + ScuRr16 = DRXJ_DAP.readReg16Func; + ScuWr16 = DRXJ_DAP.writeReg16Func; + } + + /* Configure AGC only if standard is currently active*/ + if ( ( extAttr->standard == agcSettings->standard ) || + ( DRXJ_ISQAMSTD( extAttr->standard ) && + DRXJ_ISQAMSTD( agcSettings->standard ) ) || + ( DRXJ_ISATVSTD( extAttr->standard ) && + DRXJ_ISATVSTD( agcSettings->standard ) ) ) + { + u16_t data = 0; + + switch ( agcSettings->ctrlMode ) + { + case DRX_AGC_CTRL_AUTO: + + /* Enable RF AGC DAC */ + RR16( devAddr, IQM_AF_STDBY__A , &data ); + data |= IQM_AF_STDBY_STDBY_TAGC_RF_A2_ACTIVE; + WR16( devAddr, IQM_AF_STDBY__A, data ); + + /* Enable SCU RF AGC loop */ + CHK_ERROR((*ScuRr16)( devAddr, SCU_RAM_AGC_KI__A, &data, 0 )); + data &= ~SCU_RAM_AGC_KI_RF__M; + if ( extAttr->standard == DRX_STANDARD_8VSB ) + { + data |= ( 2 << SCU_RAM_AGC_KI_RF__B ); + } + else if (DRXJ_ISQAMSTD( extAttr->standard )) + { + data |= ( 5 << SCU_RAM_AGC_KI_RF__B ); + } + else + { + data |= ( 4 << SCU_RAM_AGC_KI_RF__B ); + } + + if (commonAttr->tunerRfAgcPol) + { + data |= SCU_RAM_AGC_KI_INV_RF_POL__M; + } + else + { + data &= ~SCU_RAM_AGC_KI_INV_RF_POL__M; + } + CHK_ERROR((*ScuWr16)( devAddr, SCU_RAM_AGC_KI__A, data, 0 )); + + /* Set speed ( using complementary reduction value ) */ + CHK_ERROR((*ScuRr16)( devAddr, SCU_RAM_AGC_KI_RED__A , &data, 0 )); + data &= ~SCU_RAM_AGC_KI_RED_RAGC_RED__M; + CHK_ERROR((*ScuWr16)( devAddr, SCU_RAM_AGC_KI_RED__A , + (~(agcSettings->speed << SCU_RAM_AGC_KI_RED_RAGC_RED__B) + & SCU_RAM_AGC_KI_RED_RAGC_RED__M ) + | data, 0 )); + + if (agcSettings->standard == DRX_STANDARD_8VSB) + pAgcSettings = &(extAttr->vsbIfAgcCfg); + else if (DRXJ_ISQAMSTD( agcSettings->standard )) + pAgcSettings = &(extAttr->qamIfAgcCfg); + else if (DRXJ_ISATVSTD( agcSettings->standard )) + pAgcSettings = &(extAttr->atvIfAgcCfg); + else + return (DRX_STS_INVALID_ARG); + + /* Set TOP, only if IF-AGC is in AUTO mode */ + if ( pAgcSettings->ctrlMode == DRX_AGC_CTRL_AUTO) + { + CHK_ERROR((*ScuWr16)( devAddr, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, + agcSettings->top, 0 )); + CHK_ERROR((*ScuWr16)( devAddr, SCU_RAM_AGC_IF_IACCU_HI_TGT__A, + agcSettings->top, 0 )); + } + + /* Cut-Off current */ + CHK_ERROR((*ScuWr16)( devAddr, SCU_RAM_AGC_RF_IACCU_HI_CO__A, + agcSettings->cutOffCurrent, 0 )); + break; + case DRX_AGC_CTRL_USER: + + /* Enable RF AGC DAC */ + RR16( devAddr, IQM_AF_STDBY__A , &data ); + data |= IQM_AF_STDBY_STDBY_TAGC_RF_A2_ACTIVE; + WR16( devAddr, IQM_AF_STDBY__A , data ); + + /* Disable SCU RF AGC loop */ + CHK_ERROR((*ScuRr16)( devAddr, SCU_RAM_AGC_KI__A, &data, 0 )); + data &= ~SCU_RAM_AGC_KI_RF__M; + if (commonAttr->tunerRfAgcPol) + { + data |= SCU_RAM_AGC_KI_INV_RF_POL__M; + } + else + { + data &= ~SCU_RAM_AGC_KI_INV_RF_POL__M; + } + CHK_ERROR((*ScuWr16)( devAddr, SCU_RAM_AGC_KI__A, data, 0 )); + + /* Write value to output pin */ + CHK_ERROR((*ScuWr16)( devAddr, SCU_RAM_AGC_RF_IACCU_HI__A, agcSettings->outputLevel, 0 )); + break; + case DRX_AGC_CTRL_OFF: + + /* Disable RF AGC DAC */ + RR16( devAddr, IQM_AF_STDBY__A , &data ); + data &= (~IQM_AF_STDBY_STDBY_TAGC_RF_A2_ACTIVE); + WR16( devAddr, IQM_AF_STDBY__A , data ); + + /* Disable SCU RF AGC loop */ + CHK_ERROR((*ScuRr16)( devAddr, SCU_RAM_AGC_KI__A, &data, 0 )); + data &= ~SCU_RAM_AGC_KI_RF__M; + CHK_ERROR((*ScuWr16)( devAddr, SCU_RAM_AGC_KI__A, data, 0 )); + break; + default: + return (DRX_STS_INVALID_ARG); + } /* switch ( agcsettings->ctrlMode ) */ + } + + /* Store rf agc settings */ + switch ( agcSettings->standard){ + case DRX_STANDARD_8VSB: + extAttr->vsbRfAgcCfg = *agcSettings; + break; +#ifndef DRXJ_VSB_ONLY + case DRX_STANDARD_ITU_A: + case DRX_STANDARD_ITU_B: + case DRX_STANDARD_ITU_C: + extAttr->qamRfAgcCfg = *agcSettings; + break; +#endif +#ifndef DRXJ_DIGITAL_ONLY + case DRX_STANDARD_PAL_SECAM_BG: + case DRX_STANDARD_PAL_SECAM_DK: + case DRX_STANDARD_PAL_SECAM_I: + case DRX_STANDARD_PAL_SECAM_L: + case DRX_STANDARD_PAL_SECAM_LP: + case DRX_STANDARD_NTSC: + case DRX_STANDARD_FM: + extAttr->atvRfAgcCfg = *agcSettings; + break; +#endif + default: + return (DRX_STS_ERROR); + } + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} + +/** +* \fn DRXStatus_t GetAgcRf () +* \brief get configuration of RF AGC +* \param demod instance of demodulator. +* \param agcSettings AGC configuration structure +* \return DRXStatus_t. +*/ +static DRXStatus_t +GetAgcRf ( pDRXDemodInstance_t demod, pDRXJCfgAgc_t agcSettings ) +{ + pI2CDeviceAddr_t devAddr = NULL; + pDRXJData_t extAttr = NULL; + DRXStandard_t standard = DRX_STANDARD_UNKNOWN; + + devAddr = demod -> myI2CDevAddr; + extAttr = (pDRXJData_t)demod->myExtAttr; + + /* Return stored AGC settings */ + standard = agcSettings->standard; + switch ( agcSettings->standard){ + case DRX_STANDARD_8VSB: + *agcSettings = extAttr->vsbRfAgcCfg; + break; +#ifndef DRXJ_VSB_ONLY + case DRX_STANDARD_ITU_A: + case DRX_STANDARD_ITU_B: + case DRX_STANDARD_ITU_C: + *agcSettings = extAttr->qamRfAgcCfg; + break; +#endif +#ifndef DRXJ_DIGITAL_ONLY + case DRX_STANDARD_PAL_SECAM_BG: + case DRX_STANDARD_PAL_SECAM_DK: + case DRX_STANDARD_PAL_SECAM_I: + case DRX_STANDARD_PAL_SECAM_L: + case DRX_STANDARD_PAL_SECAM_LP: + case DRX_STANDARD_NTSC: + case DRX_STANDARD_FM: + *agcSettings = extAttr->atvRfAgcCfg; + break; +#endif + default: + return (DRX_STS_ERROR); + } + agcSettings->standard = standard; + + /* Get AGC output only if standard is currently active. */ + if ( ( extAttr->standard == agcSettings->standard ) || + ( DRXJ_ISQAMSTD( extAttr->standard ) && + DRXJ_ISQAMSTD( agcSettings->standard ) ) || + ( DRXJ_ISATVSTD( extAttr->standard ) && + DRXJ_ISATVSTD( agcSettings->standard ) ) ) + { + SARR16( devAddr, SCU_RAM_AGC_RF_IACCU_HI__A, + &(agcSettings->outputLevel)); + } + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} + +/** +* \fn DRXStatus_t SetAgcIf () +* \brief Configure If AGC +* \param demod instance of demodulator. +* \param agcSettings AGC configuration structure +* \return DRXStatus_t. +*/ +static DRXStatus_t +SetAgcIf ( pDRXDemodInstance_t demod, pDRXJCfgAgc_t agcSettings, Bool_t atomic ) +{ + pI2CDeviceAddr_t devAddr = NULL; + pDRXJData_t extAttr = NULL; + pDRXJCfgAgc_t pAgcSettings = NULL; + pDRXCommonAttr_t commonAttr = NULL; + DRXWriteReg16Func_t ScuWr16 = NULL; + DRXReadReg16Func_t ScuRr16 = NULL; + + commonAttr = (pDRXCommonAttr_t) demod -> myCommonAttr; + devAddr = demod -> myI2CDevAddr; + extAttr = (pDRXJData_t)demod->myExtAttr; + + if (atomic) + { + ScuRr16 = DRXJ_DAP_SCU_AtomicReadReg16; + ScuWr16 = DRXJ_DAP_SCU_AtomicWriteReg16; + } + else + { + ScuRr16 = DRXJ_DAP.readReg16Func; + ScuWr16 = DRXJ_DAP.writeReg16Func; + } + + /* Configure AGC only if standard is currently active*/ + if ( ( extAttr->standard == agcSettings->standard ) || + ( DRXJ_ISQAMSTD( extAttr->standard ) && + DRXJ_ISQAMSTD( agcSettings->standard ) ) || + ( DRXJ_ISATVSTD( extAttr->standard ) && + DRXJ_ISATVSTD( agcSettings->standard ) ) ) + { + u16_t data = 0; + + switch ( agcSettings->ctrlMode ) + { + case DRX_AGC_CTRL_AUTO: + /* Enable IF AGC DAC */ + RR16( devAddr, IQM_AF_STDBY__A , &data ); + data |= IQM_AF_STDBY_STDBY_TAGC_IF_A2_ACTIVE; + WR16( devAddr, IQM_AF_STDBY__A , data ); + + /* Enable SCU IF AGC loop */ + CHK_ERROR((*ScuRr16)( devAddr, SCU_RAM_AGC_KI__A, &data, 0 )); + data &= ~SCU_RAM_AGC_KI_IF_AGC_DISABLE__M; + data &= ~SCU_RAM_AGC_KI_IF__M; + if ( extAttr->standard == DRX_STANDARD_8VSB ) + { + data |= (3 << SCU_RAM_AGC_KI_IF__B ); + } + else if (DRXJ_ISQAMSTD( extAttr->standard )) + { + data |= (6 << SCU_RAM_AGC_KI_IF__B ); + } + else + { + data |= ( 5 << SCU_RAM_AGC_KI_IF__B ); + } + + if (commonAttr->tunerIfAgcPol) + { + data |= SCU_RAM_AGC_KI_INV_IF_POL__M; + } + else + { + data &= ~SCU_RAM_AGC_KI_INV_IF_POL__M; + } + CHK_ERROR((*ScuWr16)( devAddr, SCU_RAM_AGC_KI__A, data, 0 )); + + /* Set speed (using complementary reduction value) */ + CHK_ERROR((*ScuRr16)( devAddr, SCU_RAM_AGC_KI_RED__A , &data, 0 )); + data &= ~SCU_RAM_AGC_KI_RED_IAGC_RED__M; + CHK_ERROR((*ScuWr16)( devAddr, SCU_RAM_AGC_KI_RED__A , + (~(agcSettings->speed << SCU_RAM_AGC_KI_RED_IAGC_RED__B) + & SCU_RAM_AGC_KI_RED_IAGC_RED__M ) + | data, 0 )); + + if (agcSettings->standard == DRX_STANDARD_8VSB) + pAgcSettings = &(extAttr->vsbRfAgcCfg); + else if (DRXJ_ISQAMSTD( agcSettings->standard )) + pAgcSettings = &(extAttr->qamRfAgcCfg); + else if (DRXJ_ISATVSTD( agcSettings->standard )) + pAgcSettings = &(extAttr->atvRfAgcCfg); + else + return (DRX_STS_INVALID_ARG); + + /* Restore TOP */ + if ( pAgcSettings->ctrlMode == DRX_AGC_CTRL_AUTO) + { + CHK_ERROR((*ScuWr16)( devAddr, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, + pAgcSettings->top, 0 )); + CHK_ERROR((*ScuWr16)( devAddr, SCU_RAM_AGC_IF_IACCU_HI_TGT__A, + pAgcSettings->top, 0 )); + } + else + { + CHK_ERROR((*ScuWr16)( devAddr, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, 0, 0 )); + CHK_ERROR((*ScuWr16)( devAddr, SCU_RAM_AGC_IF_IACCU_HI_TGT__A, 0, 0 )); + } + break; + + case DRX_AGC_CTRL_USER: + + /* Enable IF AGC DAC */ + RR16( devAddr, IQM_AF_STDBY__A , &data ); + data |= IQM_AF_STDBY_STDBY_TAGC_IF_A2_ACTIVE; + WR16( devAddr, IQM_AF_STDBY__A , data ); + + /* Disable SCU IF AGC loop */ + CHK_ERROR((*ScuRr16)( devAddr, SCU_RAM_AGC_KI__A, &data, 0 )); + data &= ~SCU_RAM_AGC_KI_IF_AGC_DISABLE__M; + data |= SCU_RAM_AGC_KI_IF_AGC_DISABLE__M; + if (commonAttr->tunerIfAgcPol) + { + data |= SCU_RAM_AGC_KI_INV_IF_POL__M; + } + else + { + data &= ~SCU_RAM_AGC_KI_INV_IF_POL__M; + } + CHK_ERROR((*ScuWr16)( devAddr, SCU_RAM_AGC_KI__A, data, 0 )); + + /* Write value to output pin */ + CHK_ERROR((*ScuWr16)( devAddr, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, + agcSettings->outputLevel, 0 )); + break; + + case DRX_AGC_CTRL_OFF: + + /* Disable If AGC DAC */ + RR16( devAddr, IQM_AF_STDBY__A , &data ); + data &= (~IQM_AF_STDBY_STDBY_TAGC_IF_A2_ACTIVE); + WR16( devAddr, IQM_AF_STDBY__A , data ); + + /* Disable SCU IF AGC loop */ + CHK_ERROR((*ScuRr16)( devAddr, SCU_RAM_AGC_KI__A, &data, 0 )); + data &= ~SCU_RAM_AGC_KI_IF_AGC_DISABLE__M; + data |= SCU_RAM_AGC_KI_IF_AGC_DISABLE__M; + CHK_ERROR((*ScuWr16)( devAddr, SCU_RAM_AGC_KI__A, data, 0 )); + break; + default: + return (DRX_STS_INVALID_ARG); + } /* switch ( agcsettings->ctrlMode ) */ + + /* always set the top to support configurations without if-loop */ + CHK_ERROR((*ScuWr16)( devAddr, + SCU_RAM_AGC_INGAIN_TGT_MIN__A, + agcSettings->top, + 0 ) ); + } + + /* Store if agc settings */ + switch ( agcSettings->standard){ + case DRX_STANDARD_8VSB: + extAttr->vsbIfAgcCfg = *agcSettings; + break; +#ifndef DRXJ_VSB_ONLY + case DRX_STANDARD_ITU_A: + case DRX_STANDARD_ITU_B: + case DRX_STANDARD_ITU_C: + extAttr->qamIfAgcCfg = *agcSettings; + break; +#endif +#ifndef DRXJ_DIGITAL_ONLY + case DRX_STANDARD_PAL_SECAM_BG: + case DRX_STANDARD_PAL_SECAM_DK: + case DRX_STANDARD_PAL_SECAM_I: + case DRX_STANDARD_PAL_SECAM_L: + case DRX_STANDARD_PAL_SECAM_LP: + case DRX_STANDARD_NTSC: + case DRX_STANDARD_FM: + extAttr->atvIfAgcCfg = *agcSettings; + break; +#endif + default: + return (DRX_STS_ERROR); + } + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} + +/** +* \fn DRXStatus_t GetAgcIf () +* \brief get configuration of If AGC +* \param demod instance of demodulator. +* \param agcSettings AGC configuration structure +* \return DRXStatus_t. +*/ +static DRXStatus_t +GetAgcIf ( pDRXDemodInstance_t demod, pDRXJCfgAgc_t agcSettings ) +{ + pI2CDeviceAddr_t devAddr = NULL; + pDRXJData_t extAttr = NULL; + DRXStandard_t standard = DRX_STANDARD_UNKNOWN; + + devAddr = demod -> myI2CDevAddr; + extAttr = (pDRXJData_t)demod->myExtAttr; + + /* Return stored ATV AGC settings */ + standard = agcSettings->standard; + switch ( agcSettings->standard){ + case DRX_STANDARD_8VSB: + *agcSettings = extAttr->vsbIfAgcCfg; + break; +#ifndef DRXJ_VSB_ONLY + case DRX_STANDARD_ITU_A: + case DRX_STANDARD_ITU_B: + case DRX_STANDARD_ITU_C: + *agcSettings = extAttr->qamIfAgcCfg; + break; +#endif +#ifndef DRXJ_DIGITAL_ONLY + case DRX_STANDARD_PAL_SECAM_BG: + case DRX_STANDARD_PAL_SECAM_DK: + case DRX_STANDARD_PAL_SECAM_I: + case DRX_STANDARD_PAL_SECAM_L: + case DRX_STANDARD_PAL_SECAM_LP: + case DRX_STANDARD_NTSC: + case DRX_STANDARD_FM: + *agcSettings = extAttr->atvIfAgcCfg; + break; +#endif + default: + return (DRX_STS_ERROR); + } + agcSettings->standard = standard; + + /* Get AGC output only if standard is currently active */ + if ( ( extAttr->standard == agcSettings->standard ) || + ( DRXJ_ISQAMSTD( extAttr->standard ) && + DRXJ_ISQAMSTD( agcSettings->standard ) ) || + ( DRXJ_ISATVSTD( extAttr->standard ) && + DRXJ_ISATVSTD( agcSettings->standard ) ) ) + { + /* read output level */ + SARR16( devAddr, SCU_RAM_AGC_IF_IACCU_HI__A, + &(agcSettings->outputLevel) ); + } + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} + +/** +* \fn DRXStatus_t SetIqmAf () +* \brief Configure IQM AF registers +* \param demod instance of demodulator. +* \param active +* \return DRXStatus_t. +*/ +static DRXStatus_t +SetIqmAf ( pDRXDemodInstance_t demod, Bool_t active ) +{ + u16_t data = 0; + pI2CDeviceAddr_t devAddr = NULL; + + devAddr = demod -> myI2CDevAddr; + + /* Configure IQM */ + RR16( devAddr, IQM_AF_STDBY__A , &data ); + if( !active ) + { + data &= ((~IQM_AF_STDBY_STDBY_ADC_A2_ACTIVE) + & (~IQM_AF_STDBY_STDBY_AMP_A2_ACTIVE) + & (~IQM_AF_STDBY_STDBY_PD_A2_ACTIVE) + & (~IQM_AF_STDBY_STDBY_TAGC_IF_A2_ACTIVE) + & (~IQM_AF_STDBY_STDBY_TAGC_RF_A2_ACTIVE) + ); + } + else /* active */ + { + data |= (IQM_AF_STDBY_STDBY_ADC_A2_ACTIVE + | IQM_AF_STDBY_STDBY_AMP_A2_ACTIVE + | IQM_AF_STDBY_STDBY_PD_A2_ACTIVE + | IQM_AF_STDBY_STDBY_TAGC_IF_A2_ACTIVE + | IQM_AF_STDBY_STDBY_TAGC_RF_A2_ACTIVE + ); + } + WR16( devAddr, IQM_AF_STDBY__A , data ); + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} + +/*============================================================================*/ +/*== END 8VSB & QAM COMMON DATAPATH FUNCTIONS ==*/ +/*============================================================================*/ + +/*============================================================================*/ +/*============================================================================*/ +/*== 8VSB DATAPATH FUNCTIONS ==*/ +/*============================================================================*/ +/*============================================================================*/ + + +/** +* \fn DRXStatus_t PowerDownVSB () +* \brief Powr down QAM related blocks. +* \param demod instance of demodulator. +* \param channel pointer to channel data. +* \return DRXStatus_t. +*/ +static DRXStatus_t +PowerDownVSB( pDRXDemodInstance_t demod, Bool_t primary ) +{ + pI2CDeviceAddr_t devAddr = NULL; + DRXJSCUCmd_t cmdSCU = { /* command */ 0, + /* parameterLen */ 0, + /* resultLen */ 0, + /* *parameter */ NULL, + /* *result */ NULL }; + u16_t cmdResult = 0; + pDRXJData_t extAttr = NULL; + DRXCfgMPEGOutput_t cfgMPEGOutput; + + devAddr = demod -> myI2CDevAddr; + extAttr = (pDRXJData_t) demod->myExtAttr; + /* + STOP demodulator + reset of FEC and VSB HW + */ + cmdSCU.command = SCU_RAM_COMMAND_STANDARD_VSB | + SCU_RAM_COMMAND_CMD_DEMOD_STOP; + cmdSCU.parameterLen = 0; + cmdSCU.resultLen = 1; + cmdSCU.parameter = NULL; + cmdSCU.result = &cmdResult; + CHK_ERROR( SCUCommand( devAddr, &cmdSCU ) ); + + /* stop all comm_exec */ + WR16( devAddr, FEC_COMM_EXEC__A, FEC_COMM_EXEC_STOP ); + WR16( devAddr, VSB_COMM_EXEC__A, VSB_COMM_EXEC_STOP ); + if (primary == TRUE) + { + WR16( devAddr, IQM_COMM_EXEC__A, IQM_COMM_EXEC_STOP ); + CHK_ERROR( SetIqmAf( demod, FALSE ) ); + } + else + { + WR16( devAddr, IQM_FS_COMM_EXEC__A, IQM_FS_COMM_EXEC_STOP ); + WR16( devAddr, IQM_FD_COMM_EXEC__A, IQM_FD_COMM_EXEC_STOP ); + WR16( devAddr, IQM_RC_COMM_EXEC__A, IQM_RC_COMM_EXEC_STOP ); + WR16( devAddr, IQM_RT_COMM_EXEC__A, IQM_RT_COMM_EXEC_STOP ); + WR16( devAddr, IQM_CF_COMM_EXEC__A, IQM_CF_COMM_EXEC_STOP ); + } + + cfgMPEGOutput.enableMPEGOutput = FALSE; + CHK_ERROR( CtrlSetCfgMPEGOutput( demod, &cfgMPEGOutput) ); + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} +/** +* \fn DRXStatus_t SetVSBLeakNGain () +* \brief Set ATSC demod. +* \param demod instance of demodulator. +* \return DRXStatus_t. +*/ +static DRXStatus_t +SetVSBLeakNGain ( pDRXDemodInstance_t demod ) +{ + pI2CDeviceAddr_t devAddr = NULL; + + const u8_t vsb_ffe_leak_gain_ram0[]= { + DRXJ_16TO8( 0x8 ), /* FFETRAINLKRATIO1 */ + DRXJ_16TO8( 0x8 ), /* FFETRAINLKRATIO2 */ + DRXJ_16TO8( 0x8 ), /* FFETRAINLKRATIO3 */ + DRXJ_16TO8( 0xf ), /* FFETRAINLKRATIO4 */ + DRXJ_16TO8( 0xf ), /* FFETRAINLKRATIO5 */ + DRXJ_16TO8( 0xf ), /* FFETRAINLKRATIO6 */ + DRXJ_16TO8( 0xf ), /* FFETRAINLKRATIO7 */ + DRXJ_16TO8( 0xf ), /* FFETRAINLKRATIO8 */ + DRXJ_16TO8( 0xf ), /* FFETRAINLKRATIO9 */ + DRXJ_16TO8( 0x8 ), /* FFETRAINLKRATIO10 */ + DRXJ_16TO8( 0x8 ), /* FFETRAINLKRATIO11 */ + DRXJ_16TO8( 0x8 ), /* FFETRAINLKRATIO12 */ + DRXJ_16TO8( 0x10 ), /* FFERCA1TRAINLKRATIO1 */ + DRXJ_16TO8( 0x10 ), /* FFERCA1TRAINLKRATIO2 */ + DRXJ_16TO8( 0x10 ), /* FFERCA1TRAINLKRATIO3 */ + DRXJ_16TO8( 0x20 ), /* FFERCA1TRAINLKRATIO4 */ + DRXJ_16TO8( 0x20 ), /* FFERCA1TRAINLKRATIO5 */ + DRXJ_16TO8( 0x20 ), /* FFERCA1TRAINLKRATIO6 */ + DRXJ_16TO8( 0x20 ), /* FFERCA1TRAINLKRATIO7 */ + DRXJ_16TO8( 0x20 ), /* FFERCA1TRAINLKRATIO8 */ + DRXJ_16TO8( 0x20 ), /* FFERCA1TRAINLKRATIO9 */ + DRXJ_16TO8( 0x10 ), /* FFERCA1TRAINLKRATIO10 */ + DRXJ_16TO8( 0x10 ), /* FFERCA1TRAINLKRATIO11 */ + DRXJ_16TO8( 0x10 ), /* FFERCA1TRAINLKRATIO12 */ + DRXJ_16TO8( 0x10 ), /* FFERCA1DATALKRATIO1 */ + DRXJ_16TO8( 0x10 ), /* FFERCA1DATALKRATIO2 */ + DRXJ_16TO8( 0x10 ), /* FFERCA1DATALKRATIO3 */ + DRXJ_16TO8( 0x20 ), /* FFERCA1DATALKRATIO4 */ + DRXJ_16TO8( 0x20 ), /* FFERCA1DATALKRATIO5 */ + DRXJ_16TO8( 0x20 ), /* FFERCA1DATALKRATIO6 */ + DRXJ_16TO8( 0x20 ), /* FFERCA1DATALKRATIO7 */ + DRXJ_16TO8( 0x20 ), /* FFERCA1DATALKRATIO8 */ + DRXJ_16TO8( 0x20 ), /* FFERCA1DATALKRATIO9 */ + DRXJ_16TO8( 0x10 ), /* FFERCA1DATALKRATIO10 */ + DRXJ_16TO8( 0x10 ), /* FFERCA1DATALKRATIO11 */ + DRXJ_16TO8( 0x10 ), /* FFERCA1DATALKRATIO12 */ + DRXJ_16TO8( 0x10 ), /* FFERCA2TRAINLKRATIO1 */ + DRXJ_16TO8( 0x10 ), /* FFERCA2TRAINLKRATIO2 */ + DRXJ_16TO8( 0x10 ), /* FFERCA2TRAINLKRATIO3 */ + DRXJ_16TO8( 0x20 ), /* FFERCA2TRAINLKRATIO4 */ + DRXJ_16TO8( 0x20 ), /* FFERCA2TRAINLKRATIO5 */ + DRXJ_16TO8( 0x20 ), /* FFERCA2TRAINLKRATIO6 */ + DRXJ_16TO8( 0x20 ), /* FFERCA2TRAINLKRATIO7 */ + DRXJ_16TO8( 0x20 ), /* FFERCA2TRAINLKRATIO8 */ + DRXJ_16TO8( 0x20 ), /* FFERCA2TRAINLKRATIO9 */ + DRXJ_16TO8( 0x10 ), /* FFERCA2TRAINLKRATIO10 */ + DRXJ_16TO8( 0x10 ), /* FFERCA2TRAINLKRATIO11 */ + DRXJ_16TO8( 0x10 ), /* FFERCA2TRAINLKRATIO12 */ + DRXJ_16TO8( 0x10 ), /* FFERCA2DATALKRATIO1 */ + DRXJ_16TO8( 0x10 ), /* FFERCA2DATALKRATIO2 */ + DRXJ_16TO8( 0x10 ), /* FFERCA2DATALKRATIO3 */ + DRXJ_16TO8( 0x20 ), /* FFERCA2DATALKRATIO4 */ + DRXJ_16TO8( 0x20 ), /* FFERCA2DATALKRATIO5 */ + DRXJ_16TO8( 0x20 ), /* FFERCA2DATALKRATIO6 */ + DRXJ_16TO8( 0x20 ), /* FFERCA2DATALKRATIO7 */ + DRXJ_16TO8( 0x20 ), /* FFERCA2DATALKRATIO8 */ + DRXJ_16TO8( 0x20 ), /* FFERCA2DATALKRATIO9 */ + DRXJ_16TO8( 0x10 ), /* FFERCA2DATALKRATIO10 */ + DRXJ_16TO8( 0x10 ), /* FFERCA2DATALKRATIO11 */ + DRXJ_16TO8( 0x10 ), /* FFERCA2DATALKRATIO12 */ + DRXJ_16TO8( 0x07 ), /* FFEDDM1TRAINLKRATIO1 */ + DRXJ_16TO8( 0x07 ), /* FFEDDM1TRAINLKRATIO2 */ + DRXJ_16TO8( 0x07 ), /* FFEDDM1TRAINLKRATIO3 */ + DRXJ_16TO8( 0x0e ), /* FFEDDM1TRAINLKRATIO4 */ + DRXJ_16TO8( 0x0e ), /* FFEDDM1TRAINLKRATIO5 */ + DRXJ_16TO8( 0x0e ), /* FFEDDM1TRAINLKRATIO6 */ + DRXJ_16TO8( 0x0e ), /* FFEDDM1TRAINLKRATIO7 */ + DRXJ_16TO8( 0x0e ), /* FFEDDM1TRAINLKRATIO8 */ + DRXJ_16TO8( 0x0e ), /* FFEDDM1TRAINLKRATIO9 */ + DRXJ_16TO8( 0x07 ), /* FFEDDM1TRAINLKRATIO10 */ + DRXJ_16TO8( 0x07 ), /* FFEDDM1TRAINLKRATIO11 */ + DRXJ_16TO8( 0x07 ), /* FFEDDM1TRAINLKRATIO12 */ + DRXJ_16TO8( 0x07 ), /* FFEDDM1DATALKRATIO1 */ + DRXJ_16TO8( 0x07 ), /* FFEDDM1DATALKRATIO2 */ + DRXJ_16TO8( 0x07 ), /* FFEDDM1DATALKRATIO3 */ + DRXJ_16TO8( 0x0e ), /* FFEDDM1DATALKRATIO4 */ + DRXJ_16TO8( 0x0e ), /* FFEDDM1DATALKRATIO5 */ + DRXJ_16TO8( 0x0e ), /* FFEDDM1DATALKRATIO6 */ + DRXJ_16TO8( 0x0e ), /* FFEDDM1DATALKRATIO7 */ + DRXJ_16TO8( 0x0e ), /* FFEDDM1DATALKRATIO8 */ + DRXJ_16TO8( 0x0e ), /* FFEDDM1DATALKRATIO9 */ + DRXJ_16TO8( 0x07 ), /* FFEDDM1DATALKRATIO10 */ + DRXJ_16TO8( 0x07 ), /* FFEDDM1DATALKRATIO11 */ + DRXJ_16TO8( 0x07 ), /* FFEDDM1DATALKRATIO12 */ + DRXJ_16TO8( 0x06 ), /* FFEDDM2TRAINLKRATIO1 */ + DRXJ_16TO8( 0x06 ), /* FFEDDM2TRAINLKRATIO2 */ + DRXJ_16TO8( 0x06 ), /* FFEDDM2TRAINLKRATIO3 */ + DRXJ_16TO8( 0x0c ), /* FFEDDM2TRAINLKRATIO4 */ + DRXJ_16TO8( 0x0c ), /* FFEDDM2TRAINLKRATIO5 */ + DRXJ_16TO8( 0x0c ), /* FFEDDM2TRAINLKRATIO6 */ + DRXJ_16TO8( 0x0c ), /* FFEDDM2TRAINLKRATIO7 */ + DRXJ_16TO8( 0x0c ), /* FFEDDM2TRAINLKRATIO8 */ + DRXJ_16TO8( 0x0c ), /* FFEDDM2TRAINLKRATIO9 */ + DRXJ_16TO8( 0x06 ), /* FFEDDM2TRAINLKRATIO10 */ + DRXJ_16TO8( 0x06 ), /* FFEDDM2TRAINLKRATIO11 */ + DRXJ_16TO8( 0x06 ), /* FFEDDM2TRAINLKRATIO12 */ + DRXJ_16TO8( 0x06 ), /* FFEDDM2DATALKRATIO1 */ + DRXJ_16TO8( 0x06 ), /* FFEDDM2DATALKRATIO2 */ + DRXJ_16TO8( 0x06 ), /* FFEDDM2DATALKRATIO3 */ + DRXJ_16TO8( 0x0c ), /* FFEDDM2DATALKRATIO4 */ + DRXJ_16TO8( 0x0c ), /* FFEDDM2DATALKRATIO5 */ + DRXJ_16TO8( 0x0c ), /* FFEDDM2DATALKRATIO6 */ + DRXJ_16TO8( 0x0c ), /* FFEDDM2DATALKRATIO7 */ + DRXJ_16TO8( 0x0c ), /* FFEDDM2DATALKRATIO8 */ + DRXJ_16TO8( 0x0c ), /* FFEDDM2DATALKRATIO9 */ + DRXJ_16TO8( 0x06 ), /* FFEDDM2DATALKRATIO10 */ + DRXJ_16TO8( 0x06 ), /* FFEDDM2DATALKRATIO11 */ + DRXJ_16TO8( 0x06 ), /* FFEDDM2DATALKRATIO12 */ + DRXJ_16TO8( 0x2020 ), /* FIRTRAINGAIN1 */ + DRXJ_16TO8( 0x2020 ), /* FIRTRAINGAIN2 */ + DRXJ_16TO8( 0x2020 ), /* FIRTRAINGAIN3 */ + DRXJ_16TO8( 0x4040 ), /* FIRTRAINGAIN4 */ + DRXJ_16TO8( 0x4040 ), /* FIRTRAINGAIN5 */ + DRXJ_16TO8( 0x4040 ), /* FIRTRAINGAIN6 */ + DRXJ_16TO8( 0x4040 ), /* FIRTRAINGAIN7 */ + DRXJ_16TO8( 0x4040 ), /* FIRTRAINGAIN8 */ + DRXJ_16TO8( 0x4040 ), /* FIRTRAINGAIN9 */ + DRXJ_16TO8( 0x2020 ), /* FIRTRAINGAIN10 */ + DRXJ_16TO8( 0x2020 ), /* FIRTRAINGAIN11 */ + DRXJ_16TO8( 0x2020 ), /* FIRTRAINGAIN12 */ + DRXJ_16TO8( 0x0808 ), /* FIRRCA1GAIN1 */ + DRXJ_16TO8( 0x0808 ), /* FIRRCA1GAIN2 */ + DRXJ_16TO8( 0x0808 ), /* FIRRCA1GAIN3 */ + DRXJ_16TO8( 0x1010 ), /* FIRRCA1GAIN4 */ + DRXJ_16TO8( 0x1010 ), /* FIRRCA1GAIN5 */ + DRXJ_16TO8( 0x1010 ), /* FIRRCA1GAIN6 */ + DRXJ_16TO8( 0x1010 ), /* FIRRCA1GAIN7 */ + DRXJ_16TO8( 0x1010 ) /* FIRRCA1GAIN8 */ + }; + + const u8_t vsb_ffe_leak_gain_ram1[]= { + DRXJ_16TO8( 0x1010 ), /* FIRRCA1GAIN9 */ + DRXJ_16TO8( 0x0808 ), /* FIRRCA1GAIN10 */ + DRXJ_16TO8( 0x0808 ), /* FIRRCA1GAIN11 */ + DRXJ_16TO8( 0x0808 ), /* FIRRCA1GAIN12 */ + DRXJ_16TO8( 0x0808 ), /* FIRRCA2GAIN1 */ + DRXJ_16TO8( 0x0808 ), /* FIRRCA2GAIN2 */ + DRXJ_16TO8( 0x0808 ), /* FIRRCA2GAIN3 */ + DRXJ_16TO8( 0x1010 ), /* FIRRCA2GAIN4 */ + DRXJ_16TO8( 0x1010 ), /* FIRRCA2GAIN5 */ + DRXJ_16TO8( 0x1010 ), /* FIRRCA2GAIN6 */ + DRXJ_16TO8( 0x1010 ), /* FIRRCA2GAIN7 */ + DRXJ_16TO8( 0x1010 ), /* FIRRCA2GAIN8 */ + DRXJ_16TO8( 0x1010 ), /* FIRRCA2GAIN9 */ + DRXJ_16TO8( 0x0808 ), /* FIRRCA2GAIN10 */ + DRXJ_16TO8( 0x0808 ), /* FIRRCA2GAIN11 */ + DRXJ_16TO8( 0x0808 ), /* FIRRCA2GAIN12 */ + DRXJ_16TO8( 0x0303 ), /* FIRDDM1GAIN1 */ + DRXJ_16TO8( 0x0303 ), /* FIRDDM1GAIN2 */ + DRXJ_16TO8( 0x0303 ), /* FIRDDM1GAIN3 */ + DRXJ_16TO8( 0x0606 ), /* FIRDDM1GAIN4 */ + DRXJ_16TO8( 0x0606 ), /* FIRDDM1GAIN5 */ + DRXJ_16TO8( 0x0606 ), /* FIRDDM1GAIN6 */ + DRXJ_16TO8( 0x0606 ), /* FIRDDM1GAIN7 */ + DRXJ_16TO8( 0x0606 ), /* FIRDDM1GAIN8 */ + DRXJ_16TO8( 0x0606 ), /* FIRDDM1GAIN9 */ + DRXJ_16TO8( 0x0303 ), /* FIRDDM1GAIN10 */ + DRXJ_16TO8( 0x0303 ), /* FIRDDM1GAIN11 */ + DRXJ_16TO8( 0x0303 ), /* FIRDDM1GAIN12 */ + DRXJ_16TO8( 0x0303 ), /* FIRDDM2GAIN1 */ + DRXJ_16TO8( 0x0303 ), /* FIRDDM2GAIN2 */ + DRXJ_16TO8( 0x0303 ), /* FIRDDM2GAIN3 */ + DRXJ_16TO8( 0x0505 ), /* FIRDDM2GAIN4 */ + DRXJ_16TO8( 0x0505 ), /* FIRDDM2GAIN5 */ + DRXJ_16TO8( 0x0505 ), /* FIRDDM2GAIN6 */ + DRXJ_16TO8( 0x0505 ), /* FIRDDM2GAIN7 */ + DRXJ_16TO8( 0x0505 ), /* FIRDDM2GAIN8 */ + DRXJ_16TO8( 0x0505 ), /* FIRDDM2GAIN9 */ + DRXJ_16TO8( 0x0303 ), /* FIRDDM2GAIN10 */ + DRXJ_16TO8( 0x0303 ), /* FIRDDM2GAIN11 */ + DRXJ_16TO8( 0x0303 ), /* FIRDDM2GAIN12 */ + DRXJ_16TO8( 0x001f ), /* DFETRAINLKRATIO */ + DRXJ_16TO8( 0x01ff ), /* DFERCA1TRAINLKRATIO */ + DRXJ_16TO8( 0x01ff ), /* DFERCA1DATALKRATIO */ + DRXJ_16TO8( 0x004f ), /* DFERCA2TRAINLKRATIO */ + DRXJ_16TO8( 0x004f ), /* DFERCA2DATALKRATIO */ + DRXJ_16TO8( 0x01ff ), /* DFEDDM1TRAINLKRATIO */ + DRXJ_16TO8( 0x01ff ), /* DFEDDM1DATALKRATIO */ + DRXJ_16TO8( 0x0352 ), /* DFEDDM2TRAINLKRATIO */ + DRXJ_16TO8( 0x0352 ), /* DFEDDM2DATALKRATIO */ + DRXJ_16TO8( 0x0000 ), /* DFETRAINGAIN */ + DRXJ_16TO8( 0x2020 ), /* DFERCA1GAIN */ + DRXJ_16TO8( 0x1010 ), /* DFERCA2GAIN */ + DRXJ_16TO8( 0x1818 ), /* DFEDDM1GAIN */ + DRXJ_16TO8( 0x1212 ) /* DFEDDM2GAIN */ + }; + + devAddr = demod -> myI2CDevAddr; + WRB ( devAddr, VSB_SYSCTRL_RAM0_FFETRAINLKRATIO1__A, + sizeof(vsb_ffe_leak_gain_ram0), ((pu8_t)vsb_ffe_leak_gain_ram0) ); + WRB ( devAddr, VSB_SYSCTRL_RAM1_FIRRCA1GAIN9__A, + sizeof(vsb_ffe_leak_gain_ram1), ((pu8_t)vsb_ffe_leak_gain_ram1) ); + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} + +/** +* \fn DRXStatus_t SetVSB() +* \brief Set 8VSB demod. +* \param demod instance of demodulator. +* \return DRXStatus_t. +* +*/ +static DRXStatus_t +SetVSB ( pDRXDemodInstance_t demod ) +{ + pI2CDeviceAddr_t devAddr = NULL; + u16_t cmdResult = 0; + u16_t cmdParam = 0; + pDRXCommonAttr_t commonAttr = NULL; + DRXJSCUCmd_t cmdSCU; + pDRXJData_t extAttr = NULL; + const u8_t vsb_taps_re[]= { + DRXJ_16TO8( -2 ), /* re0 */ + DRXJ_16TO8( 4 ), /* re1 */ + DRXJ_16TO8( 1 ), /* re2 */ + DRXJ_16TO8( -4 ), /* re3 */ + DRXJ_16TO8( 1 ), /* re4 */ + DRXJ_16TO8( 4 ), /* re5 */ + DRXJ_16TO8( -3 ), /* re6 */ + DRXJ_16TO8( -3 ), /* re7 */ + DRXJ_16TO8( 6 ), /* re8 */ + DRXJ_16TO8( 1 ), /* re9 */ + DRXJ_16TO8( -9 ), /* re10 */ + DRXJ_16TO8( 3 ), /* re11 */ + DRXJ_16TO8( 12 ), /* re12 */ + DRXJ_16TO8( -9 ), /* re13 */ + DRXJ_16TO8( -15 ), /* re14 */ + DRXJ_16TO8( 17 ), /* re15 */ + DRXJ_16TO8( 19 ), /* re16 */ + DRXJ_16TO8( -29 ), /* re17 */ + DRXJ_16TO8( -22 ), /* re18 */ + DRXJ_16TO8( 45 ), /* re19 */ + DRXJ_16TO8( 25 ), /* re20 */ + DRXJ_16TO8( -70 ), /* re21 */ + DRXJ_16TO8( -28 ), /* re22 */ + DRXJ_16TO8( 111 ), /* re23 */ + DRXJ_16TO8( 30 ), /* re24 */ + DRXJ_16TO8( -201 ), /* re25 */ + DRXJ_16TO8( -31 ), /* re26 */ + DRXJ_16TO8( 629 ) /* re27 */ + }; + + devAddr = demod -> myI2CDevAddr; + commonAttr = (pDRXCommonAttr_t) demod -> myCommonAttr; + extAttr = (pDRXJData_t)demod->myExtAttr; + + /* stop all comm_exec */ + WR16( devAddr, FEC_COMM_EXEC__A, FEC_COMM_EXEC_STOP ); + WR16( devAddr, VSB_COMM_EXEC__A, VSB_COMM_EXEC_STOP ); + WR16( devAddr, IQM_FS_COMM_EXEC__A, IQM_FS_COMM_EXEC_STOP ); + WR16( devAddr, IQM_FD_COMM_EXEC__A, IQM_FD_COMM_EXEC_STOP ); + WR16( devAddr, IQM_RC_COMM_EXEC__A, IQM_RC_COMM_EXEC_STOP ); + WR16( devAddr, IQM_RT_COMM_EXEC__A, IQM_RT_COMM_EXEC_STOP ); + WR16( devAddr, IQM_CF_COMM_EXEC__A, IQM_CF_COMM_EXEC_STOP ); + + /* reset demodulator */ + cmdSCU.command = SCU_RAM_COMMAND_STANDARD_VSB + | SCU_RAM_COMMAND_CMD_DEMOD_RESET; + cmdSCU.parameterLen = 0; + cmdSCU.resultLen = 1; + cmdSCU.parameter = NULL; + cmdSCU.result = &cmdResult; + CHK_ERROR( SCUCommand( devAddr, &cmdSCU ) ); + + WR16( devAddr, IQM_AF_DCF_BYPASS__A, 1 ); + WR16( devAddr, IQM_FS_ADJ_SEL__A, IQM_FS_ADJ_SEL_B_VSB ); + WR16( devAddr, IQM_RC_ADJ_SEL__A, IQM_RC_ADJ_SEL_B_VSB ); + extAttr->iqmRcRateOfs = 0x00AD0D79; + WR32( devAddr, IQM_RC_RATE_OFS_LO__A, extAttr->iqmRcRateOfs ); + WR16( devAddr, VSB_TOP_CFAGC_GAINSHIFT__A, 4); + WR16( devAddr, VSB_TOP_CYGN1TRK__A, 1); + + WR16( devAddr, IQM_RC_CROUT_ENA__A, 1 ); + WR16( devAddr, IQM_RC_STRETCH__A, 28 ); + WR16( devAddr, IQM_RT_ACTIVE__A, 0 ); + WR16( devAddr, IQM_CF_SYMMETRIC__A, 0 ); + WR16( devAddr, IQM_CF_MIDTAP__A, 3 ); + WR16( devAddr, IQM_CF_OUT_ENA__A, IQM_CF_OUT_ENA_VSB__M ); + WR16( devAddr, IQM_CF_SCALE__A, 1393 ); + WR16( devAddr, IQM_CF_SCALE_SH__A, 0 ); + WR16( devAddr, IQM_CF_POW_MEAS_LEN__A, 1); + + WRB ( devAddr, IQM_CF_TAP_RE0__A, sizeof(vsb_taps_re), ((pu8_t)vsb_taps_re) ); + WRB ( devAddr, IQM_CF_TAP_IM0__A, sizeof(vsb_taps_re), ((pu8_t)vsb_taps_re) ); + + WR16( devAddr, VSB_TOP_BNTHRESH__A, 330 ); /* set higher threshold */ + WR16( devAddr, VSB_TOP_CLPLASTNUM__A, 90 ); /* burst detection on */ + WR16( devAddr, VSB_TOP_SNRTH_RCA1__A, 0x0042 ); /* drop thresholds by 1 dB */ + WR16( devAddr, VSB_TOP_SNRTH_RCA2__A, 0x0053 ); /* drop thresholds by 2 dB */ + WR16( devAddr, VSB_TOP_EQCTRL__A, 0x1 ); /* cma on */ + WR16( devAddr, SCU_RAM_GPIO__A, 0 ); /* GPIO */ + + /* Initialize the FEC Subsystem */ + WR16( devAddr, FEC_TOP_ANNEX__A, FEC_TOP_ANNEX_D ); + { + u16_t fecOcSncMode = 0; + RR16( devAddr, FEC_OC_SNC_MODE__A, &fecOcSncMode ); + /* output data even when not locked */ + WR16( devAddr, FEC_OC_SNC_MODE__A, fecOcSncMode | FEC_OC_SNC_MODE_UNLOCK_ENABLE__M ); + } + + /* set clip */ + WR16( devAddr, IQM_AF_CLP_LEN__A, 0); + WR16( devAddr, IQM_AF_CLP_TH__A, 470); + WR16( devAddr, IQM_AF_SNS_LEN__A, 0); + WR16( devAddr, VSB_TOP_SNRTH_PT__A, 0xD4 ); + /* no transparent, no A&C framing; parity is set in mpegoutput*/ + { + u16_t fecOcRegMode = 0; + RR16 ( devAddr, FEC_OC_MODE__A , &fecOcRegMode ); + WR16( devAddr, FEC_OC_MODE__A, fecOcRegMode & + (~(FEC_OC_MODE_TRANSPARENT__M + | FEC_OC_MODE_CLEAR__M + | FEC_OC_MODE_RETAIN_FRAMING__M) + ) ); + } + + WR16( devAddr, FEC_DI_TIMEOUT_LO__A, 0 ); /* timeout counter for restarting */ + WR16( devAddr, FEC_DI_TIMEOUT_HI__A, 3 ); + WR16( devAddr, FEC_RS_MODE__A, 0 ); /* bypass disabled */ + /* initialize RS packet error measurement parameters */ + WR16( devAddr, FEC_RS_MEASUREMENT_PERIOD__A, FEC_RS_MEASUREMENT_PERIOD ); + WR16( devAddr, FEC_RS_MEASUREMENT_PRESCALE__A, FEC_RS_MEASUREMENT_PRESCALE ); + + /* init measurement period of MER/SER */ + WR16( devAddr, VSB_TOP_MEASUREMENT_PERIOD__A, VSB_TOP_MEASUREMENT_PERIOD ); + WR32( devAddr, SCU_RAM_FEC_ACCUM_CW_CORRECTED_LO__A, 0 ); + WR16( devAddr, SCU_RAM_FEC_MEAS_COUNT__A, 0 ); + WR16( devAddr, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, 0 ); + + WR16( devAddr, VSB_TOP_CKGN1TRK__A, 128 ); + /* B-Input to ADC, PGA+filter in standby */ + if ( extAttr->hasLNA == FALSE ) + { + WR16( devAddr, IQM_AF_AMUX__A, 0x02); + }; + + /* turn on IQMAF. It has to be in front of setAgc**() */ + CHK_ERROR( SetIqmAf( demod, TRUE ) ); + CHK_ERROR(ADCSynchronization (demod)); + + CHK_ERROR( InitAGC( demod ) ); + CHK_ERROR( SetAgcIf( demod, &(extAttr->vsbIfAgcCfg), FALSE ) ); + CHK_ERROR( SetAgcRf( demod, &(extAttr->vsbRfAgcCfg), FALSE ) ); + { + /* TODO fix this, store a DRXJCfgAfeGain_t structure in DRXJData_t instead + of only the gain */ + DRXJCfgAfeGain_t vsbPgaCfg = { DRX_STANDARD_8VSB, 0 }; + + vsbPgaCfg.gain = extAttr->vsbPgaCfg; + CHK_ERROR( CtrlSetCfgAfeGain( demod, &vsbPgaCfg ) ); + } + CHK_ERROR( CtrlSetCfgPreSaw( demod, &(extAttr->vsbPreSawCfg)) ); + + /* Mpeg output has to be in front of FEC active */ + CHK_ERROR ( SetMPEGTEIHandling ( demod )); + CHK_ERROR ( BitReverseMPEGOutput( demod ) ); + CHK_ERROR ( SetMPEGStartWidth ( demod ) ); + { + /* TODO: move to setStandard after hardware reset value problem is solved */ + /* Configure initial MPEG output */ + DRXCfgMPEGOutput_t cfgMPEGOutput; + cfgMPEGOutput.enableMPEGOutput = TRUE; + cfgMPEGOutput.insertRSByte = commonAttr->mpegCfg.insertRSByte; + cfgMPEGOutput.enableParallel = commonAttr->mpegCfg.enableParallel; + cfgMPEGOutput.invertDATA = commonAttr->mpegCfg.invertDATA; + cfgMPEGOutput.invertERR = commonAttr->mpegCfg.invertERR; + cfgMPEGOutput.invertSTR = commonAttr->mpegCfg.invertSTR; + cfgMPEGOutput.invertVAL = commonAttr->mpegCfg.invertVAL; + cfgMPEGOutput.invertCLK = commonAttr->mpegCfg.invertCLK; + cfgMPEGOutput.staticCLK = commonAttr->mpegCfg.staticCLK; + cfgMPEGOutput.bitrate = commonAttr->mpegCfg.bitrate; + CHK_ERROR( CtrlSetCfgMPEGOutput( demod, &cfgMPEGOutput) ); + } + + /* TBD: what parameters should be set */ + cmdParam = 0x00; /* Default mode AGC on, etc */ + cmdSCU.command = SCU_RAM_COMMAND_STANDARD_VSB + | SCU_RAM_COMMAND_CMD_DEMOD_SET_PARAM; + cmdSCU.parameterLen = 1; + cmdSCU.resultLen = 1; + cmdSCU.parameter = &cmdParam; + cmdSCU.result = &cmdResult; + CHK_ERROR( SCUCommand( devAddr, &cmdSCU ) ); + + WR16(devAddr, VSB_TOP_BEAGC_GAINSHIFT__A, 0x0004 ); + WR16(devAddr, VSB_TOP_SNRTH_PT__A, 0x00D2 ); + WR16(devAddr, VSB_TOP_SYSSMTRNCTRL__A, VSB_TOP_SYSSMTRNCTRL__PRE + |VSB_TOP_SYSSMTRNCTRL_NCOTIMEOUTCNTEN__M ); + WR16(devAddr, VSB_TOP_BEDETCTRL__A, 0x142 ); + WR16(devAddr, VSB_TOP_LBAGCREFLVL__A, 640 ); + WR16(devAddr, VSB_TOP_CYGN1ACQ__A, 4 ); + WR16(devAddr, VSB_TOP_CYGN1TRK__A, 2 ); + WR16(devAddr, VSB_TOP_CYGN2TRK__A, 3 ); + + /* start demodulator */ + cmdSCU.command = SCU_RAM_COMMAND_STANDARD_VSB + | SCU_RAM_COMMAND_CMD_DEMOD_START; + cmdSCU.parameterLen = 0; + cmdSCU.resultLen = 1; + cmdSCU.parameter = NULL; + cmdSCU.result = &cmdResult; + CHK_ERROR( SCUCommand( devAddr, &cmdSCU ) ); + + WR16(devAddr, IQM_COMM_EXEC__A, IQM_COMM_EXEC_ACTIVE ); + WR16(devAddr, VSB_COMM_EXEC__A, VSB_COMM_EXEC_ACTIVE ); + WR16(devAddr, FEC_COMM_EXEC__A, FEC_COMM_EXEC_ACTIVE ); + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} + +/** +* \fn static short GetVSBPostRSPckErr(pI2CDeviceAddr_t devAddr, pu16_t PckErrs) +* \brief Get the values of packet error in 8VSB mode +* \return Error code +*/ +static DRXStatus_t +GetVSBPostRSPckErr(pI2CDeviceAddr_t devAddr, pu16_t pckErrs) +{ + u16_t data = 0; + u16_t period = 0; + u16_t prescale = 0; + u16_t packetErrorsMant = 0; + u16_t packetErrorsExp = 0; + + RR16(devAddr, FEC_RS_NR_FAILURES__A, &data ); + packetErrorsMant = data & FEC_RS_NR_FAILURES_FIXED_MANT__M; + packetErrorsExp = (data & FEC_RS_NR_FAILURES_EXP__M) + >> FEC_RS_NR_FAILURES_EXP__B; + period = FEC_RS_MEASUREMENT_PERIOD; + prescale = FEC_RS_MEASUREMENT_PRESCALE; + /* packet error rate = (error packet number) per second */ + /* 77.3 us is time for per packet */ + CHK_ZERO (period * prescale); + *pckErrs = (u16_t)FracTimes1e6(packetErrorsMant * (1 << packetErrorsExp), + (period * prescale * 77)); + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} + +/** +* \fn static short GetVSBBer(pI2CDeviceAddr_t devAddr, pu32_t ber) +* \brief Get the values of ber in VSB mode +* \return Error code +*/ +static DRXStatus_t +GetVSBpostViterbiBer(pI2CDeviceAddr_t devAddr, pu32_t ber) +{ + u16_t data = 0; + u16_t period = 0; + u16_t prescale = 0; + u16_t bitErrorsMant = 0; + u16_t bitErrorsExp = 0; + + RR16 ( devAddr, FEC_RS_NR_BIT_ERRORS__A, &data ); + period = FEC_RS_MEASUREMENT_PERIOD; + prescale = FEC_RS_MEASUREMENT_PRESCALE; + + bitErrorsMant = data & FEC_RS_NR_BIT_ERRORS_FIXED_MANT__M; + bitErrorsExp = (data & FEC_RS_NR_BIT_ERRORS_EXP__M) + >> FEC_RS_NR_BIT_ERRORS_EXP__B; + + if ( ((bitErrorsMant << bitErrorsExp) >> 3) > 68700) + *ber = 26570; + else + { + CHK_ZERO (period * prescale); + *ber = FracTimes1e6(bitErrorsMant << ((bitErrorsExp > 2)? (bitErrorsExp - 3):bitErrorsExp), + period * prescale * 207 * ((bitErrorsExp > 2)?1:8) ); + } + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} + +/** +* \fn static short GetVSBpreViterbiBer(pI2CDeviceAddr_t devAddr, pu32_t ber) +* \brief Get the values of ber in VSB mode +* \return Error code +*/ +static DRXStatus_t +GetVSBpreViterbiBer(pI2CDeviceAddr_t devAddr, pu32_t ber) +{ + u16_t data = 0; + + RR16 ( devAddr, VSB_TOP_NR_SYM_ERRS__A, &data ); + *ber = FracTimes1e6( data, VSB_TOP_MEASUREMENT_PERIOD * SYMBOLS_PER_SEGMENT ); + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} + +/** +* \fn static short GetVSBSymbErr(pI2CDeviceAddr_t devAddr, pu32_t ber) +* \brief Get the values of ber in VSB mode +* \return Error code +*/ +static DRXStatus_t +GetVSBSymbErr(pI2CDeviceAddr_t devAddr, pu32_t ser) +{ + u16_t data = 0; + u16_t period = 0; + u16_t prescale = 0; + u16_t symbErrorsMant = 0; + u16_t symbErrorsExp = 0; + + RR16 ( devAddr, FEC_RS_NR_SYMBOL_ERRORS__A, &data ); + period = FEC_RS_MEASUREMENT_PERIOD; + prescale = FEC_RS_MEASUREMENT_PRESCALE; + + symbErrorsMant = data & FEC_RS_NR_SYMBOL_ERRORS_FIXED_MANT__M; + symbErrorsExp = (data & FEC_RS_NR_SYMBOL_ERRORS_EXP__M) + >> FEC_RS_NR_SYMBOL_ERRORS_EXP__B; + + CHK_ZERO (period * prescale); + *ser = (u32_t)FracTimes1e6((symbErrorsMant << symbErrorsExp) * 1000, + (period * prescale * 77318)); + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} + +/** +* \fn static DRXStatus_t GetVSBMER(pI2CDeviceAddr_t devAddr, pu16_t mer) +* \brief Get the values of MER +* \return Error code +*/ +static DRXStatus_t +GetVSBMER (pI2CDeviceAddr_t devAddr, pu16_t mer) +{ + u16_t dataHi = 0; + + RR16( devAddr, VSB_TOP_ERR_ENERGY_H__A, &dataHi ); + *mer = (u16_t)(Log10Times100( 21504 ) - Log10Times100( (dataHi << 6) / 52 )); + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} + +/*============================================================================*/ +/** +* \fn DRXStatus_t CtrlGetVSBConstel() +* \brief Retreive a VSB constellation point via I2C. +* \param demod Pointer to demodulator instance. +* \param complexNr Pointer to the structure in which to store the + constellation point. +* \return DRXStatus_t. +*/ +static DRXStatus_t +CtrlGetVSBConstel( pDRXDemodInstance_t demod, + pDRXComplex_t complexNr ) +{ + pI2CDeviceAddr_t devAddr = NULL; /**< device address */ + u16_t vsbTopCommMb = 0; /**< VSB SL MB configuration */ + u16_t vsbTopCommMbInit = 0; /**< VSB SL MB intial configuration */ + u16_t re = 0; /**< constellation Re part */ + u32_t data = 0; + + /* read device info */ + devAddr = demod -> myI2CDevAddr; + + /* TODO: */ + /* Monitor bus grabbing is an open external interface issue */ + /* Needs to be checked when external interface PG is updated */ + + /* Configure MB (Monitor bus) */ + RR16( devAddr, VSB_TOP_COMM_MB__A, &vsbTopCommMbInit ); + /* set observe flag & MB mux */ + vsbTopCommMb = (vsbTopCommMbInit | + VSB_TOP_COMM_MB_OBS_OBS_ON | + VSB_TOP_COMM_MB_MUX_OBS_VSB_TCMEQ_2 ); + WR16( devAddr, VSB_TOP_COMM_MB__A, vsbTopCommMb ); + + /* Enable MB grabber in the FEC OC */ + WR16( devAddr, FEC_OC_OCR_MODE__A, FEC_OC_OCR_MODE_GRAB_ENABLE__M ); + + /* Disable MB grabber in the FEC OC */ + WR16( devAddr, FEC_OC_OCR_MODE__A, 0x0 ); + + /* read data */ + RR32( devAddr, FEC_OC_OCR_GRAB_RD1__A, &data ); + re = (u16_t)(((data >> 10) & 0x300 ) | ((data >> 2) & 0xff)); + if (re & 0x0200) + { + re |= 0xfc00; + } + complexNr->re = re; + complexNr->im = 0; + + /* Restore MB (Monitor bus) */ + WR16( devAddr, VSB_TOP_COMM_MB__A, vsbTopCommMbInit ); + + return (DRX_STS_OK); + rw_error: + return (DRX_STS_ERROR); +} +/*============================================================================*/ +/*== END 8VSB DATAPATH FUNCTIONS ==*/ +/*============================================================================*/ + +/*============================================================================*/ +/*============================================================================*/ +/*== QAM DATAPATH FUNCTIONS ==*/ +/*============================================================================*/ +/*============================================================================*/ + +/** +* \fn DRXStatus_t PowerDownQAM () +* \brief Powr down QAM related blocks. +* \param demod instance of demodulator. +* \param channel pointer to channel data. +* \return DRXStatus_t. +*/ +static DRXStatus_t +PowerDownQAM( pDRXDemodInstance_t demod, Bool_t primary ) +{ + DRXJSCUCmd_t cmdSCU = { /* command */ 0, + /* parameterLen */ 0, + /* resultLen */ 0, + /* *parameter */ NULL, + /* *result */ NULL }; + u16_t cmdResult = 0; + pI2CDeviceAddr_t devAddr = NULL; + pDRXJData_t extAttr = NULL; + DRXCfgMPEGOutput_t cfgMPEGOutput; + + devAddr = demod -> myI2CDevAddr; + extAttr = (pDRXJData_t)demod->myExtAttr; + + /* + STOP demodulator + resets IQM, QAM and FEC HW blocks + */ + /* stop all comm_exec */ + WR16( devAddr, FEC_COMM_EXEC__A, FEC_COMM_EXEC_STOP); + WR16( devAddr, QAM_COMM_EXEC__A, QAM_COMM_EXEC_STOP); + + cmdSCU.command = SCU_RAM_COMMAND_STANDARD_QAM | + SCU_RAM_COMMAND_CMD_DEMOD_STOP; + cmdSCU.parameterLen = 0; + cmdSCU.resultLen = 1; + cmdSCU.parameter = NULL; + cmdSCU.result = &cmdResult; + CHK_ERROR( SCUCommand( devAddr, &cmdSCU ) ); + + if (primary == TRUE) + { + WR16( devAddr, IQM_COMM_EXEC__A, IQM_COMM_EXEC_STOP ); + CHK_ERROR( SetIqmAf( demod, FALSE ) ); + } + else + { + WR16( devAddr, IQM_FS_COMM_EXEC__A, IQM_FS_COMM_EXEC_STOP ); + WR16( devAddr, IQM_FD_COMM_EXEC__A, IQM_FD_COMM_EXEC_STOP ); + WR16( devAddr, IQM_RC_COMM_EXEC__A, IQM_RC_COMM_EXEC_STOP ); + WR16( devAddr, IQM_RT_COMM_EXEC__A, IQM_RT_COMM_EXEC_STOP ); + WR16( devAddr, IQM_CF_COMM_EXEC__A, IQM_CF_COMM_EXEC_STOP ); + } + + cfgMPEGOutput.enableMPEGOutput = FALSE; + CHK_ERROR( CtrlSetCfgMPEGOutput( demod, &cfgMPEGOutput) ); + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} + +/*============================================================================*/ + +/** +* \fn DRXStatus_t SetQAMMeasurement () +* \brief Setup of the QAM Measuremnt intervals for signal quality +* \param demod instance of demod. +* \param constellation current constellation. +* \return DRXStatus_t. +* +* NOTE: +* Take into account that for certain settings the errorcounters can overflow. +* The implementation does not check this. +* +* TODO: overriding the extAttr->fecBitsDesired by constellation dependent +* constants to get a measurement period of approx. 1 sec. Remove fecBitsDesired +* field ? +* +*/ +#ifndef DRXJ_VSB_ONLY +static DRXStatus_t +SetQAMMeasurement ( pDRXDemodInstance_t demod, + DRXConstellation_t constellation, + u32_t symbolRate ) +{ + pI2CDeviceAddr_t devAddr = NULL; /* device address for I2C writes */ + pDRXJData_t extAttr = NULL; /* Global data container for DRXJ specif data */ + u32_t fecBitsDesired = 0; /* BER accounting period */ + u16_t fecRsPlen = 0; /* defines RS BER measurement period */ + u16_t fecRsPrescale = 0; /* ReedSolomon Measurement Prescale */ + u32_t fecRsPeriod = 0; /* Value for corresponding I2C register */ + u32_t fecRsBitCnt = 0; /* Actual precise amount of bits */ + u32_t fecOcSncFailPeriod = 0; /* Value for corresponding I2C register */ + u32_t qamVdPeriod = 0; /* Value for corresponding I2C register */ + u32_t qamVdBitCnt = 0; /* Actual precise amount of bits */ + u16_t fecVdPlen = 0; /* no of trellis symbols: VD SER measur period */ + u16_t qamVdPrescale = 0; /* Viterbi Measurement Prescale */ + + devAddr = demod -> myI2CDevAddr; + extAttr = (pDRXJData_t)demod->myExtAttr; + + fecBitsDesired = extAttr->fecBitsDesired; + fecRsPrescale = extAttr->fecRsPrescale; + + switch ( constellation ) { + case DRX_CONSTELLATION_QAM16: + fecBitsDesired = 4 * symbolRate; + break; + case DRX_CONSTELLATION_QAM32: + fecBitsDesired = 5 * symbolRate; + break; + case DRX_CONSTELLATION_QAM64: + fecBitsDesired = 6 * symbolRate; + break; + case DRX_CONSTELLATION_QAM128: + fecBitsDesired = 7 * symbolRate; + break; + case DRX_CONSTELLATION_QAM256: + fecBitsDesired = 8 * symbolRate; + break; + default: + return (DRX_STS_INVALID_ARG); + } + + /* Parameters for Reed-Solomon Decoder */ + /* fecrs_period = (int)ceil(FEC_BITS_DESIRED/(fecrs_prescale*plen)) */ + /* rs_bit_cnt = fecrs_period*fecrs_prescale*plen */ + /* result is within 32 bit arithmetic -> */ + /* no need for mult or frac functions */ + + /* TODO: use constant instead of calculation and remove the fecRsPlen in extAttr */ + switch ( extAttr->standard ) + { + case DRX_STANDARD_ITU_A: + case DRX_STANDARD_ITU_C: + fecRsPlen = 204 * 8; + break; + case DRX_STANDARD_ITU_B: + fecRsPlen = 128 * 7; + break; + default: + return (DRX_STS_INVALID_ARG); + } + + extAttr->fecRsPlen = fecRsPlen; /* for getSigQual */ + fecRsBitCnt = fecRsPrescale * fecRsPlen; /* temp storage */ + CHK_ZERO (fecRsBitCnt); + fecRsPeriod = fecBitsDesired / fecRsBitCnt + 1; /* ceil */ + if (extAttr->standard != DRX_STANDARD_ITU_B) + fecOcSncFailPeriod = fecRsPeriod; + + /* limit to max 16 bit value (I2C register width) if needed */ + if ( fecRsPeriod > 0xFFFF ) + fecRsPeriod = 0xFFFF; + + /* write corresponding registers */ + switch ( extAttr->standard ) + { + case DRX_STANDARD_ITU_A: + case DRX_STANDARD_ITU_C: + break; + case DRX_STANDARD_ITU_B: + switch ( constellation ) { + case DRX_CONSTELLATION_QAM64: + fecRsPeriod = 31581; + fecOcSncFailPeriod = 17932; + break; + case DRX_CONSTELLATION_QAM256: + fecRsPeriod = 45446; + fecOcSncFailPeriod = 25805; + break; + default: + return (DRX_STS_INVALID_ARG); + } + break; + default: + return (DRX_STS_INVALID_ARG); + } + + WR16 ( devAddr, FEC_OC_SNC_FAIL_PERIOD__A , ( u16_t ) fecOcSncFailPeriod ); + WR16 ( devAddr, FEC_RS_MEASUREMENT_PERIOD__A , ( u16_t ) fecRsPeriod ); + WR16 ( devAddr, FEC_RS_MEASUREMENT_PRESCALE__A , fecRsPrescale ); + extAttr->fecRsPeriod = (u16_t) fecRsPeriod; + extAttr->fecRsPrescale = fecRsPrescale; + WR32( devAddr, SCU_RAM_FEC_ACCUM_CW_CORRECTED_LO__A, 0 ); + WR16( devAddr, SCU_RAM_FEC_MEAS_COUNT__A, 0 ); + WR16( devAddr, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, 0 ); + + if (extAttr->standard == DRX_STANDARD_ITU_B) + { + /* Parameters for Viterbi Decoder */ + /* qamvd_period = (int)ceil(FEC_BITS_DESIRED/ */ + /* (qamvd_prescale*plen*(qam_constellation+1))) */ + /* vd_bit_cnt = qamvd_period*qamvd_prescale*plen */ + /* result is within 32 bit arithmetic -> */ + /* no need for mult or frac functions */ + + /* a(8 bit) * b(8 bit) = 16 bit result => Mult32 not needed */ + fecVdPlen = extAttr->fecVdPlen; + qamVdPrescale = extAttr->qamVdPrescale; + qamVdBitCnt = qamVdPrescale * fecVdPlen; /* temp storage */ + + switch ( constellation ) { + case DRX_CONSTELLATION_QAM64: + /* a(16 bit) * b(4 bit) = 20 bit result => Mult32 not needed */ + qamVdPeriod = qamVdBitCnt * ( QAM_TOP_CONSTELLATION_QAM64 + 1 ) + * ( QAM_TOP_CONSTELLATION_QAM64 + 1 ); + break; + case DRX_CONSTELLATION_QAM256: + /* a(16 bit) * b(5 bit) = 21 bit result => Mult32 not needed */ + qamVdPeriod = qamVdBitCnt * ( QAM_TOP_CONSTELLATION_QAM256 + 1 ) + * ( QAM_TOP_CONSTELLATION_QAM256 + 1 ); + break; + default: + return (DRX_STS_INVALID_ARG); + } + CHK_ZERO (qamVdPeriod); + qamVdPeriod = fecBitsDesired / qamVdPeriod; + /* limit to max 16 bit value (I2C register width) if needed */ + if ( qamVdPeriod > 0xFFFF ) + qamVdPeriod = 0xFFFF; + + /* a(16 bit) * b(16 bit) = 32 bit result => Mult32 not needed */ + qamVdBitCnt *= qamVdPeriod; + + WR16 ( devAddr, QAM_VD_MEASUREMENT_PERIOD__A , ( u16_t ) qamVdPeriod ); + WR16 ( devAddr, QAM_VD_MEASUREMENT_PRESCALE__A , qamVdPrescale ); + extAttr->qamVdPeriod = (u16_t) qamVdPeriod; + extAttr->qamVdPrescale = qamVdPrescale; + } + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} + +/*============================================================================*/ + +/** +* \fn DRXStatus_t SetQAM16 () +* \brief QAM16 specific setup +* \param demod instance of demod. +* \return DRXStatus_t. +*/ +static DRXStatus_t +SetQAM16 ( pDRXDemodInstance_t demod ) +{ + pI2CDeviceAddr_t devAddr = demod -> myI2CDevAddr; + const u8_t qamDqQualFun[]= { + DRXJ_16TO8( 2 ), /* fun0 */ + DRXJ_16TO8( 2 ), /* fun1 */ + DRXJ_16TO8( 2 ), /* fun2 */ + DRXJ_16TO8( 2 ), /* fun3 */ + DRXJ_16TO8( 3 ), /* fun4 */ + DRXJ_16TO8( 3 ), /* fun5 */ + }; + const u8_t qamEqCmaRad[]= { + DRXJ_16TO8( 13517 ), /* RAD0 */ + DRXJ_16TO8( 13517 ), /* RAD1 */ + DRXJ_16TO8( 13517 ), /* RAD2 */ + DRXJ_16TO8( 13517 ), /* RAD3 */ + DRXJ_16TO8( 13517 ), /* RAD4 */ + DRXJ_16TO8( 13517 ), /* RAD5 */ + }; + + WRB ( devAddr, QAM_DQ_QUAL_FUN0__A, sizeof(qamDqQualFun), ((pu8_t)qamDqQualFun) ); + WRB ( devAddr, SCU_RAM_QAM_EQ_CMA_RAD0__A, sizeof(qamEqCmaRad), ((pu8_t)qamEqCmaRad) ); + + WR16 ( devAddr, SCU_RAM_QAM_FSM_RTH__A, 140); + WR16 ( devAddr, SCU_RAM_QAM_FSM_FTH__A, 50); + WR16 ( devAddr, SCU_RAM_QAM_FSM_PTH__A, 120); + WR16 ( devAddr, SCU_RAM_QAM_FSM_QTH__A, 230); + WR16 ( devAddr, SCU_RAM_QAM_FSM_CTH__A, 95); + WR16 ( devAddr, SCU_RAM_QAM_FSM_MTH__A, 105); + + WR16 ( devAddr, SCU_RAM_QAM_FSM_RATE_LIM__A, 40); + WR16 ( devAddr, SCU_RAM_QAM_FSM_FREQ_LIM__A, 56); + WR16 ( devAddr, SCU_RAM_QAM_FSM_COUNT_LIM__A, 3); + + WR16 ( devAddr, SCU_RAM_QAM_FSM_MEDIAN_AV_MULT__A, 16 ); + WR16 ( devAddr, SCU_RAM_QAM_FSM_RADIUS_AV_LIMIT__A, 220); + WR16 ( devAddr, SCU_RAM_QAM_FSM_LCAVG_OFFSET1__A, 25 ); + WR16 ( devAddr, SCU_RAM_QAM_FSM_LCAVG_OFFSET2__A, 6 ); + WR16 ( devAddr, SCU_RAM_QAM_FSM_LCAVG_OFFSET3__A, (u16_t)(-24) ); + WR16 ( devAddr, SCU_RAM_QAM_FSM_LCAVG_OFFSET4__A, (u16_t)(-65)); + WR16 ( devAddr, SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A, (u16_t)(-127)); + + WR16 ( devAddr, SCU_RAM_QAM_LC_CA_FINE__A, 15); + WR16 ( devAddr, SCU_RAM_QAM_LC_CA_COARSE__A, 40); + WR16 ( devAddr, SCU_RAM_QAM_LC_CP_FINE__A, 2); + WR16 ( devAddr, SCU_RAM_QAM_LC_CP_MEDIUM__A, 20); + WR16 ( devAddr, SCU_RAM_QAM_LC_CP_COARSE__A, 255); + WR16 ( devAddr, SCU_RAM_QAM_LC_CI_FINE__A, 2); + WR16 ( devAddr, SCU_RAM_QAM_LC_CI_MEDIUM__A, 10); + WR16 ( devAddr, SCU_RAM_QAM_LC_CI_COARSE__A, 50); + WR16 ( devAddr, SCU_RAM_QAM_LC_EP_FINE__A, 12); + WR16 ( devAddr, SCU_RAM_QAM_LC_EP_MEDIUM__A, 24); + WR16 ( devAddr, SCU_RAM_QAM_LC_EP_COARSE__A, 24); + WR16 ( devAddr, SCU_RAM_QAM_LC_EI_FINE__A, 12); + WR16 ( devAddr, SCU_RAM_QAM_LC_EI_MEDIUM__A, 16); + WR16 ( devAddr, SCU_RAM_QAM_LC_EI_COARSE__A, 16); + WR16 ( devAddr, SCU_RAM_QAM_LC_CF_FINE__A, 16); + WR16 ( devAddr, SCU_RAM_QAM_LC_CF_MEDIUM__A, 32); + WR16 ( devAddr, SCU_RAM_QAM_LC_CF_COARSE__A, 240); + WR16 ( devAddr, SCU_RAM_QAM_LC_CF1_FINE__A, 5); + WR16 ( devAddr, SCU_RAM_QAM_LC_CF1_MEDIUM__A, 15); + WR16 ( devAddr, SCU_RAM_QAM_LC_CF1_COARSE__A, 32); + + WR16 ( devAddr, SCU_RAM_QAM_SL_SIG_POWER__A, 40960); + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} + +/*============================================================================*/ + +/** +* \fn DRXStatus_t SetQAM32 () +* \brief QAM32 specific setup +* \param demod instance of demod. +* \return DRXStatus_t. +*/ +static DRXStatus_t +SetQAM32 ( pDRXDemodInstance_t demod ) +{ + pI2CDeviceAddr_t devAddr = demod -> myI2CDevAddr; + const u8_t qamDqQualFun[]= { + DRXJ_16TO8( 3 ), /* fun0 */ + DRXJ_16TO8( 3 ), /* fun1 */ + DRXJ_16TO8( 3 ), /* fun2 */ + DRXJ_16TO8( 3 ), /* fun3 */ + DRXJ_16TO8( 4 ), /* fun4 */ + DRXJ_16TO8( 4 ), /* fun5 */ + }; + const u8_t qamEqCmaRad[]= { + DRXJ_16TO8( 6707 ), /* RAD0 */ + DRXJ_16TO8( 6707 ), /* RAD1 */ + DRXJ_16TO8( 6707 ), /* RAD2 */ + DRXJ_16TO8( 6707 ), /* RAD3 */ + DRXJ_16TO8( 6707 ), /* RAD4 */ + DRXJ_16TO8( 6707 ), /* RAD5 */ + }; + + WRB ( devAddr, QAM_DQ_QUAL_FUN0__A, sizeof(qamDqQualFun), ((pu8_t)qamDqQualFun) ); + WRB ( devAddr, SCU_RAM_QAM_EQ_CMA_RAD0__A, sizeof(qamEqCmaRad), ((pu8_t)qamEqCmaRad) ); + + WR16 ( devAddr, SCU_RAM_QAM_FSM_RTH__A, 90); + WR16 ( devAddr, SCU_RAM_QAM_FSM_FTH__A, 50); + WR16 ( devAddr, SCU_RAM_QAM_FSM_PTH__A, 100); + WR16 ( devAddr, SCU_RAM_QAM_FSM_QTH__A, 170); + WR16 ( devAddr, SCU_RAM_QAM_FSM_CTH__A, 80); + WR16 ( devAddr, SCU_RAM_QAM_FSM_MTH__A, 100); + + WR16 ( devAddr, SCU_RAM_QAM_FSM_RATE_LIM__A, 40); + WR16 ( devAddr, SCU_RAM_QAM_FSM_FREQ_LIM__A, 56); + WR16 ( devAddr, SCU_RAM_QAM_FSM_COUNT_LIM__A, 3); + + WR16 ( devAddr, SCU_RAM_QAM_FSM_MEDIAN_AV_MULT__A, 12 ); + WR16 ( devAddr, SCU_RAM_QAM_FSM_RADIUS_AV_LIMIT__A, 140); + WR16 ( devAddr, SCU_RAM_QAM_FSM_LCAVG_OFFSET1__A, (u16_t)(-8) ); + WR16 ( devAddr, SCU_RAM_QAM_FSM_LCAVG_OFFSET2__A, (u16_t)(-16) ); + WR16 ( devAddr, SCU_RAM_QAM_FSM_LCAVG_OFFSET3__A, (u16_t)(-26) ); + WR16 ( devAddr, SCU_RAM_QAM_FSM_LCAVG_OFFSET4__A, (u16_t)(-56)); + WR16 ( devAddr, SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A, (u16_t)(-86)); + + WR16 ( devAddr, SCU_RAM_QAM_LC_CA_FINE__A, 15); + WR16 ( devAddr, SCU_RAM_QAM_LC_CA_COARSE__A, 40); + WR16 ( devAddr, SCU_RAM_QAM_LC_CP_FINE__A, 2); + WR16 ( devAddr, SCU_RAM_QAM_LC_CP_MEDIUM__A, 20); + WR16 ( devAddr, SCU_RAM_QAM_LC_CP_COARSE__A, 255); + WR16 ( devAddr, SCU_RAM_QAM_LC_CI_FINE__A, 2); + WR16 ( devAddr, SCU_RAM_QAM_LC_CI_MEDIUM__A, 10); + WR16 ( devAddr, SCU_RAM_QAM_LC_CI_COARSE__A, 50); + WR16 ( devAddr, SCU_RAM_QAM_LC_EP_FINE__A, 12); + WR16 ( devAddr, SCU_RAM_QAM_LC_EP_MEDIUM__A, 24); + WR16 ( devAddr, SCU_RAM_QAM_LC_EP_COARSE__A, 24); + WR16 ( devAddr, SCU_RAM_QAM_LC_EI_FINE__A, 12); + WR16 ( devAddr, SCU_RAM_QAM_LC_EI_MEDIUM__A, 16); + WR16 ( devAddr, SCU_RAM_QAM_LC_EI_COARSE__A, 16); + WR16 ( devAddr, SCU_RAM_QAM_LC_CF_FINE__A, 16); + WR16 ( devAddr, SCU_RAM_QAM_LC_CF_MEDIUM__A, 32); + WR16 ( devAddr, SCU_RAM_QAM_LC_CF_COARSE__A, 176); + WR16 ( devAddr, SCU_RAM_QAM_LC_CF1_FINE__A, 5); + WR16 ( devAddr, SCU_RAM_QAM_LC_CF1_MEDIUM__A, 15); + WR16 ( devAddr, SCU_RAM_QAM_LC_CF1_COARSE__A, 8); + + WR16 ( devAddr, SCU_RAM_QAM_SL_SIG_POWER__A, 20480); + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} + +/*============================================================================*/ + +/** +* \fn DRXStatus_t SetQAM64 () +* \brief QAM64 specific setup +* \param demod instance of demod. +* \return DRXStatus_t. +*/ +static DRXStatus_t +SetQAM64 ( pDRXDemodInstance_t demod ) +{ + pI2CDeviceAddr_t devAddr = demod -> myI2CDevAddr; + const u8_t qamDqQualFun[]= { /* this is hw reset value. no necessary to re-write */ + DRXJ_16TO8( 4 ), /* fun0 */ + DRXJ_16TO8( 4 ), /* fun1 */ + DRXJ_16TO8( 4 ), /* fun2 */ + DRXJ_16TO8( 4 ), /* fun3 */ + DRXJ_16TO8( 6 ), /* fun4 */ + DRXJ_16TO8( 6 ), /* fun5 */ + }; + const u8_t qamEqCmaRad[]= { + DRXJ_16TO8( 13336 ), /* RAD0 */ + DRXJ_16TO8( 12618 ), /* RAD1 */ + DRXJ_16TO8( 11988 ), /* RAD2 */ + DRXJ_16TO8( 13809 ), /* RAD3 */ + DRXJ_16TO8( 13809 ), /* RAD4 */ + DRXJ_16TO8( 15609 ), /* RAD5 */ + }; + + WRB ( devAddr, QAM_DQ_QUAL_FUN0__A, sizeof(qamDqQualFun), ((pu8_t)qamDqQualFun) ); + WRB ( devAddr, SCU_RAM_QAM_EQ_CMA_RAD0__A, sizeof(qamEqCmaRad), ((pu8_t)qamEqCmaRad) ); + + WR16 ( devAddr, SCU_RAM_QAM_FSM_RTH__A, 105); + WR16 ( devAddr, SCU_RAM_QAM_FSM_FTH__A, 60); + WR16 ( devAddr, SCU_RAM_QAM_FSM_PTH__A, 100); + WR16 ( devAddr, SCU_RAM_QAM_FSM_QTH__A, 195); + WR16 ( devAddr, SCU_RAM_QAM_FSM_CTH__A, 80); + WR16 ( devAddr, SCU_RAM_QAM_FSM_MTH__A, 84); + + WR16 ( devAddr, SCU_RAM_QAM_FSM_RATE_LIM__A, 40); + WR16 ( devAddr, SCU_RAM_QAM_FSM_FREQ_LIM__A, 32); + WR16 ( devAddr, SCU_RAM_QAM_FSM_COUNT_LIM__A, 3); + + WR16 ( devAddr, SCU_RAM_QAM_FSM_MEDIAN_AV_MULT__A, 12 ); + WR16 ( devAddr, SCU_RAM_QAM_FSM_RADIUS_AV_LIMIT__A, 141); + WR16 ( devAddr, SCU_RAM_QAM_FSM_LCAVG_OFFSET1__A, 7 ); + WR16 ( devAddr, SCU_RAM_QAM_FSM_LCAVG_OFFSET2__A, 0 ); + WR16 ( devAddr, SCU_RAM_QAM_FSM_LCAVG_OFFSET3__A, (u16_t)(-15)); + WR16 ( devAddr, SCU_RAM_QAM_FSM_LCAVG_OFFSET4__A, (u16_t)(-45)); + WR16 ( devAddr, SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A, (u16_t)(-80)); + + WR16 ( devAddr, SCU_RAM_QAM_LC_CA_FINE__A, 15); + WR16 ( devAddr, SCU_RAM_QAM_LC_CA_COARSE__A, 40); + WR16 ( devAddr, SCU_RAM_QAM_LC_CP_FINE__A, 2); + WR16 ( devAddr, SCU_RAM_QAM_LC_CP_MEDIUM__A, 30); + WR16 ( devAddr, SCU_RAM_QAM_LC_CP_COARSE__A, 255); + WR16 ( devAddr, SCU_RAM_QAM_LC_CI_FINE__A, 2); + WR16 ( devAddr, SCU_RAM_QAM_LC_CI_MEDIUM__A, 15); + WR16 ( devAddr, SCU_RAM_QAM_LC_CI_COARSE__A, 80); + WR16 ( devAddr, SCU_RAM_QAM_LC_EP_FINE__A, 12); + WR16 ( devAddr, SCU_RAM_QAM_LC_EP_MEDIUM__A, 24); + WR16 ( devAddr, SCU_RAM_QAM_LC_EP_COARSE__A, 24); + WR16 ( devAddr, SCU_RAM_QAM_LC_EI_FINE__A, 12); + WR16 ( devAddr, SCU_RAM_QAM_LC_EI_MEDIUM__A, 16); + WR16 ( devAddr, SCU_RAM_QAM_LC_EI_COARSE__A, 16); + WR16 ( devAddr, SCU_RAM_QAM_LC_CF_FINE__A, 16); + WR16 ( devAddr, SCU_RAM_QAM_LC_CF_MEDIUM__A, 48); + WR16 ( devAddr, SCU_RAM_QAM_LC_CF_COARSE__A, 160); + WR16 ( devAddr, SCU_RAM_QAM_LC_CF1_FINE__A, 5); + WR16 ( devAddr, SCU_RAM_QAM_LC_CF1_MEDIUM__A, 15); + WR16 ( devAddr, SCU_RAM_QAM_LC_CF1_COARSE__A, 32); + + WR16 ( devAddr, SCU_RAM_QAM_SL_SIG_POWER__A, 43008); + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} + +/*============================================================================*/ + +/** +* \fn DRXStatus_t SetQAM128 () +* \brief QAM128 specific setup +* \param demod: instance of demod. +* \return DRXStatus_t. +*/ +static DRXStatus_t +SetQAM128( pDRXDemodInstance_t demod ) +{ + pI2CDeviceAddr_t devAddr = demod -> myI2CDevAddr; + const u8_t qamDqQualFun[]= { + DRXJ_16TO8( 6 ), /* fun0 */ + DRXJ_16TO8( 6 ), /* fun1 */ + DRXJ_16TO8( 6 ), /* fun2 */ + DRXJ_16TO8( 6 ), /* fun3 */ + DRXJ_16TO8( 9 ), /* fun4 */ + DRXJ_16TO8( 9 ), /* fun5 */ + }; + const u8_t qamEqCmaRad[]= { + DRXJ_16TO8( 6164 ), /* RAD0 */ + DRXJ_16TO8( 6598 ), /* RAD1 */ + DRXJ_16TO8( 6394 ), /* RAD2 */ + DRXJ_16TO8( 6409 ), /* RAD3 */ + DRXJ_16TO8( 6656 ), /* RAD4 */ + DRXJ_16TO8( 7238 ), /* RAD5 */ + }; + + WRB ( devAddr, QAM_DQ_QUAL_FUN0__A, sizeof(qamDqQualFun), ((pu8_t)qamDqQualFun) ); + WRB ( devAddr, SCU_RAM_QAM_EQ_CMA_RAD0__A, sizeof(qamEqCmaRad), ((pu8_t)qamEqCmaRad) ); + + WR16 ( devAddr, SCU_RAM_QAM_FSM_RTH__A, 50); + WR16 ( devAddr, SCU_RAM_QAM_FSM_FTH__A, 60); + WR16 ( devAddr, SCU_RAM_QAM_FSM_PTH__A, 100); + WR16 ( devAddr, SCU_RAM_QAM_FSM_QTH__A, 140); + WR16 ( devAddr, SCU_RAM_QAM_FSM_CTH__A, 80); + WR16 ( devAddr, SCU_RAM_QAM_FSM_MTH__A, 100); + + WR16 ( devAddr, SCU_RAM_QAM_FSM_RATE_LIM__A, 40); + WR16 ( devAddr, SCU_RAM_QAM_FSM_FREQ_LIM__A, 32); + WR16 ( devAddr, SCU_RAM_QAM_FSM_COUNT_LIM__A, 3); + + WR16 ( devAddr, SCU_RAM_QAM_FSM_MEDIAN_AV_MULT__A, 8 ); + WR16 ( devAddr, SCU_RAM_QAM_FSM_RADIUS_AV_LIMIT__A, 65 ); + WR16 ( devAddr, SCU_RAM_QAM_FSM_LCAVG_OFFSET1__A, 5 ); + WR16 ( devAddr, SCU_RAM_QAM_FSM_LCAVG_OFFSET2__A, 3 ); + WR16 ( devAddr, SCU_RAM_QAM_FSM_LCAVG_OFFSET3__A, (u16_t)(-1) ); + WR16 ( devAddr, SCU_RAM_QAM_FSM_LCAVG_OFFSET4__A, 12); + WR16 ( devAddr, SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A, (u16_t)(-23)); + + WR16 ( devAddr, SCU_RAM_QAM_LC_CA_FINE__A, 15); + WR16 ( devAddr, SCU_RAM_QAM_LC_CA_COARSE__A, 40); + WR16 ( devAddr, SCU_RAM_QAM_LC_CP_FINE__A, 2); + WR16 ( devAddr, SCU_RAM_QAM_LC_CP_MEDIUM__A, 40); + WR16 ( devAddr, SCU_RAM_QAM_LC_CP_COARSE__A, 255); + WR16 ( devAddr, SCU_RAM_QAM_LC_CI_FINE__A, 2); + WR16 ( devAddr, SCU_RAM_QAM_LC_CI_MEDIUM__A, 20); + WR16 ( devAddr, SCU_RAM_QAM_LC_CI_COARSE__A, 80); + WR16 ( devAddr, SCU_RAM_QAM_LC_EP_FINE__A, 12); + WR16 ( devAddr, SCU_RAM_QAM_LC_EP_MEDIUM__A, 24); + WR16 ( devAddr, SCU_RAM_QAM_LC_EP_COARSE__A, 24); + WR16 ( devAddr, SCU_RAM_QAM_LC_EI_FINE__A, 12); + WR16 ( devAddr, SCU_RAM_QAM_LC_EI_MEDIUM__A, 16); + WR16 ( devAddr, SCU_RAM_QAM_LC_EI_COARSE__A, 16); + WR16 ( devAddr, SCU_RAM_QAM_LC_CF_FINE__A, 16); + WR16 ( devAddr, SCU_RAM_QAM_LC_CF_MEDIUM__A, 32); + WR16 ( devAddr, SCU_RAM_QAM_LC_CF_COARSE__A, 144); + WR16 ( devAddr, SCU_RAM_QAM_LC_CF1_FINE__A, 5); + WR16 ( devAddr, SCU_RAM_QAM_LC_CF1_MEDIUM__A, 15); + WR16 ( devAddr, SCU_RAM_QAM_LC_CF1_COARSE__A, 16); + + WR16 ( devAddr, SCU_RAM_QAM_SL_SIG_POWER__A, 20992); + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} + +/*============================================================================*/ + +/** +* \fn DRXStatus_t SetQAM256 () +* \brief QAM256 specific setup +* \param demod: instance of demod. +* \return DRXStatus_t. +*/ +static DRXStatus_t +SetQAM256( pDRXDemodInstance_t demod ) +{ + pI2CDeviceAddr_t devAddr = demod -> myI2CDevAddr; + const u8_t qamDqQualFun[]= { + DRXJ_16TO8( 8 ), /* fun0 */ + DRXJ_16TO8( 8 ), /* fun1 */ + DRXJ_16TO8( 8 ), /* fun2 */ + DRXJ_16TO8( 8 ), /* fun3 */ + DRXJ_16TO8( 12 ), /* fun4 */ + DRXJ_16TO8( 12 ), /* fun5 */ + }; + const u8_t qamEqCmaRad[]= { + DRXJ_16TO8( 12345 ), /* RAD0 */ + DRXJ_16TO8( 12345 ), /* RAD1 */ + DRXJ_16TO8( 13626 ), /* RAD2 */ + DRXJ_16TO8( 12931 ), /* RAD3 */ + DRXJ_16TO8( 14719 ), /* RAD4 */ + DRXJ_16TO8( 15356 ), /* RAD5 */ + }; + + WRB ( devAddr, QAM_DQ_QUAL_FUN0__A, sizeof(qamDqQualFun), ((pu8_t)qamDqQualFun) ); + WRB ( devAddr, SCU_RAM_QAM_EQ_CMA_RAD0__A, sizeof(qamEqCmaRad), ((pu8_t)qamEqCmaRad) ); + + WR16 ( devAddr, SCU_RAM_QAM_FSM_RTH__A, 50); + WR16 ( devAddr, SCU_RAM_QAM_FSM_FTH__A, 60); + WR16 ( devAddr, SCU_RAM_QAM_FSM_PTH__A, 100); + WR16 ( devAddr, SCU_RAM_QAM_FSM_QTH__A, 150); + WR16 ( devAddr, SCU_RAM_QAM_FSM_CTH__A, 80); + WR16 ( devAddr, SCU_RAM_QAM_FSM_MTH__A, 110); + + WR16 ( devAddr, SCU_RAM_QAM_FSM_RATE_LIM__A, 40); + WR16 ( devAddr, SCU_RAM_QAM_FSM_FREQ_LIM__A, 16); + WR16 ( devAddr, SCU_RAM_QAM_FSM_COUNT_LIM__A, 3); + + WR16 ( devAddr, SCU_RAM_QAM_FSM_MEDIAN_AV_MULT__A, 8); + WR16 ( devAddr, SCU_RAM_QAM_FSM_RADIUS_AV_LIMIT__A, 74); + WR16 ( devAddr, SCU_RAM_QAM_FSM_LCAVG_OFFSET1__A, 18); + WR16 ( devAddr, SCU_RAM_QAM_FSM_LCAVG_OFFSET2__A, 13); + WR16 ( devAddr, SCU_RAM_QAM_FSM_LCAVG_OFFSET3__A, 7); + WR16 ( devAddr, SCU_RAM_QAM_FSM_LCAVG_OFFSET4__A, 0); + WR16 ( devAddr, SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A, (u16_t)(-8)); + + WR16 ( devAddr, SCU_RAM_QAM_LC_CA_FINE__A, 15); + WR16 ( devAddr, SCU_RAM_QAM_LC_CA_COARSE__A, 40); + WR16 ( devAddr, SCU_RAM_QAM_LC_CP_FINE__A, 2); + WR16 ( devAddr, SCU_RAM_QAM_LC_CP_MEDIUM__A, 50); + WR16 ( devAddr, SCU_RAM_QAM_LC_CP_COARSE__A, 255); + WR16 ( devAddr, SCU_RAM_QAM_LC_CI_FINE__A, 2); + WR16 ( devAddr, SCU_RAM_QAM_LC_CI_MEDIUM__A, 25); + WR16 ( devAddr, SCU_RAM_QAM_LC_CI_COARSE__A, 80); + WR16 ( devAddr, SCU_RAM_QAM_LC_EP_FINE__A, 12); + WR16 ( devAddr, SCU_RAM_QAM_LC_EP_MEDIUM__A, 24); + WR16 ( devAddr, SCU_RAM_QAM_LC_EP_COARSE__A, 24); + WR16 ( devAddr, SCU_RAM_QAM_LC_EI_FINE__A, 12); + WR16 ( devAddr, SCU_RAM_QAM_LC_EI_MEDIUM__A, 16); + WR16 ( devAddr, SCU_RAM_QAM_LC_EI_COARSE__A, 16); + WR16 ( devAddr, SCU_RAM_QAM_LC_CF_FINE__A, 16); + WR16 ( devAddr, SCU_RAM_QAM_LC_CF_MEDIUM__A, 48); + WR16 ( devAddr, SCU_RAM_QAM_LC_CF_COARSE__A, 80); + WR16 ( devAddr, SCU_RAM_QAM_LC_CF1_FINE__A, 5); + WR16 ( devAddr, SCU_RAM_QAM_LC_CF1_MEDIUM__A, 15); + WR16 ( devAddr, SCU_RAM_QAM_LC_CF1_COARSE__A, 16); + + WR16 ( devAddr, SCU_RAM_QAM_SL_SIG_POWER__A, 43520); + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} + +/*============================================================================*/ +#define QAM_SET_OP_ALL 0x1 +#define QAM_SET_OP_CONSTELLATION 0x2 +#define QAM_SET_OP_SPECTRUM 0X4 + +/** +* \fn DRXStatus_t SetQAM () +* \brief Set QAM demod. +* \param demod: instance of demod. +* \param channel: pointer to channel data. +* \return DRXStatus_t. +*/ +static DRXStatus_t +SetQAM( pDRXDemodInstance_t demod, + pDRXChannel_t channel, + DRXFrequency_t tunerFreqOffset, + u32_t op + ) +{ + pI2CDeviceAddr_t devAddr = NULL; + pDRXJData_t extAttr = NULL; + pDRXCommonAttr_t commonAttr = NULL; + u16_t cmdResult = 0; + u32_t adcFrequency = 0; + u32_t iqmRcRate = 0; + u16_t lcSymbolFreq = 0; + u16_t iqmRcStretch = 0; + u16_t setEnvParameters = 0; + u16_t setParamParameters[2] = {0}; + DRXJSCUCmd_t cmdSCU = { /* command */ 0, + /* parameterLen */ 0, + /* resultLen */ 0, + /* parameter */ NULL, + /* result */ NULL }; + const u8_t qamA_taps[]= { + DRXJ_16TO8( -1 ), /* re0 */ + DRXJ_16TO8( 1 ), /* re1 */ + DRXJ_16TO8( 1 ), /* re2 */ + DRXJ_16TO8( -1 ), /* re3 */ + DRXJ_16TO8( -1 ), /* re4 */ + DRXJ_16TO8( 2 ), /* re5 */ + DRXJ_16TO8( 1 ), /* re6 */ + DRXJ_16TO8( -2 ), /* re7 */ + DRXJ_16TO8( 0 ), /* re8 */ + DRXJ_16TO8( 3 ), /* re9 */ + DRXJ_16TO8( -1 ), /* re10 */ + DRXJ_16TO8( -3 ), /* re11 */ + DRXJ_16TO8( 4 ), /* re12 */ + DRXJ_16TO8( 1 ), /* re13 */ + DRXJ_16TO8( -8 ), /* re14 */ + DRXJ_16TO8( 4 ), /* re15 */ + DRXJ_16TO8( 13 ), /* re16 */ + DRXJ_16TO8( -13 ), /* re17 */ + DRXJ_16TO8( -19 ), /* re18 */ + DRXJ_16TO8( 28 ), /* re19 */ + DRXJ_16TO8( 25 ), /* re20 */ + DRXJ_16TO8( -53 ), /* re21 */ + DRXJ_16TO8( -31 ), /* re22 */ + DRXJ_16TO8( 96 ), /* re23 */ + DRXJ_16TO8( 37 ), /* re24 */ + DRXJ_16TO8( -190 ), /* re25 */ + DRXJ_16TO8( -40 ), /* re26 */ + DRXJ_16TO8( 619 ) /* re27 */ + }; + const u8_t qamB64_taps[]= { + DRXJ_16TO8( 0 ), /* re0 */ + DRXJ_16TO8( -2 ), /* re1 */ + DRXJ_16TO8( 1 ), /* re2 */ + DRXJ_16TO8( 2 ), /* re3 */ + DRXJ_16TO8( -2 ), /* re4 */ + DRXJ_16TO8( 0 ), /* re5 */ + DRXJ_16TO8( 4 ), /* re6 */ + DRXJ_16TO8( -2 ), /* re7 */ + DRXJ_16TO8( -4 ), /* re8 */ + DRXJ_16TO8( 4 ), /* re9 */ + DRXJ_16TO8( 3 ), /* re10 */ + DRXJ_16TO8( -6 ), /* re11 */ + DRXJ_16TO8( 0 ), /* re12 */ + DRXJ_16TO8( 6 ), /* re13 */ + DRXJ_16TO8( -5 ), /* re14 */ + DRXJ_16TO8( -3 ), /* re15 */ + DRXJ_16TO8( 11 ), /* re16 */ + DRXJ_16TO8( -4 ), /* re17 */ + DRXJ_16TO8( -19 ), /* re18 */ + DRXJ_16TO8( 19 ), /* re19 */ + DRXJ_16TO8( 28 ), /* re20 */ + DRXJ_16TO8( -45 ), /* re21 */ + DRXJ_16TO8( -36 ), /* re22 */ + DRXJ_16TO8( 90 ), /* re23 */ + DRXJ_16TO8( 42 ), /* re24 */ + DRXJ_16TO8( -185 ), /* re25 */ + DRXJ_16TO8( -46 ), /* re26 */ + DRXJ_16TO8( 614 ) /* re27 */ + }; + const u8_t qamB256_taps[]= { + DRXJ_16TO8( -2 ), /* re0 */ + DRXJ_16TO8( 4 ), /* re1 */ + DRXJ_16TO8( 1 ), /* re2 */ + DRXJ_16TO8( -4 ), /* re3 */ + DRXJ_16TO8( 0 ), /* re4 */ + DRXJ_16TO8( 4 ), /* re5 */ + DRXJ_16TO8( -2 ), /* re6 */ + DRXJ_16TO8( -4 ), /* re7 */ + DRXJ_16TO8( 5 ), /* re8 */ + DRXJ_16TO8( 2 ), /* re9 */ + DRXJ_16TO8( -8 ), /* re10 */ + DRXJ_16TO8( 2 ), /* re11 */ + DRXJ_16TO8( 11 ), /* re12 */ + DRXJ_16TO8( -8 ), /* re13 */ + DRXJ_16TO8( -15 ), /* re14 */ + DRXJ_16TO8( 16 ), /* re15 */ + DRXJ_16TO8( 19 ), /* re16 */ + DRXJ_16TO8( -27 ), /* re17 */ + DRXJ_16TO8( -22 ), /* re18 */ + DRXJ_16TO8( 44 ), /* re19 */ + DRXJ_16TO8( 26 ), /* re20 */ + DRXJ_16TO8( -69 ), /* re21 */ + DRXJ_16TO8( -28 ), /* re22 */ + DRXJ_16TO8( 110 ), /* re23 */ + DRXJ_16TO8( 31 ), /* re24 */ + DRXJ_16TO8( -201 ), /* re25 */ + DRXJ_16TO8( -32 ), /* re26 */ + DRXJ_16TO8( 628 ) /* re27 */ + }; + const u8_t qamC_taps[]= { + DRXJ_16TO8( -3 ), /* re0 */ + DRXJ_16TO8( 3 ), /* re1 */ + DRXJ_16TO8( 2 ), /* re2 */ + DRXJ_16TO8( -4 ), /* re3 */ + DRXJ_16TO8( 0 ), /* re4 */ + DRXJ_16TO8( 4 ), /* re5 */ + DRXJ_16TO8( -1 ), /* re6 */ + DRXJ_16TO8( -4 ), /* re7 */ + DRXJ_16TO8( 3 ), /* re8 */ + DRXJ_16TO8( 3 ), /* re9 */ + DRXJ_16TO8( -5 ), /* re10 */ + DRXJ_16TO8( 0 ), /* re11 */ + DRXJ_16TO8( 9 ), /* re12 */ + DRXJ_16TO8( -4 ), /* re13 */ + DRXJ_16TO8( -12 ), /* re14 */ + DRXJ_16TO8( 10 ), /* re15 */ + DRXJ_16TO8( 16 ), /* re16 */ + DRXJ_16TO8( -21 ), /* re17 */ + DRXJ_16TO8( -20 ), /* re18 */ + DRXJ_16TO8( 37 ), /* re19 */ + DRXJ_16TO8( 25 ), /* re20 */ + DRXJ_16TO8( -62 ), /* re21 */ + DRXJ_16TO8( -28 ), /* re22 */ + DRXJ_16TO8( 105 ), /* re23 */ + DRXJ_16TO8( 31 ), /* re24 */ + DRXJ_16TO8( -197 ), /* re25 */ + DRXJ_16TO8( -33 ), /* re26 */ + DRXJ_16TO8( 626 ) /* re27 */ + }; + + devAddr = demod -> myI2CDevAddr; + extAttr = (pDRXJData_t)demod -> myExtAttr; + commonAttr = (pDRXCommonAttr_t) demod -> myCommonAttr; + + if ((op & QAM_SET_OP_ALL) || (op & QAM_SET_OP_CONSTELLATION )) + { + if ( extAttr->standard == DRX_STANDARD_ITU_B ) + { + switch ( channel->constellation ) + { + case DRX_CONSTELLATION_QAM256 : + iqmRcRate = 0x00AE3562; + lcSymbolFreq = QAM_LC_SYMBOL_FREQ_FREQ_QAM_B_256; + channel->symbolrate = 5360537; + iqmRcStretch = IQM_RC_STRETCH_QAM_B_256; + break; + case DRX_CONSTELLATION_QAM64 : + iqmRcRate = 0x00C05A0E; + lcSymbolFreq = 409; + channel->symbolrate = 5056941; + iqmRcStretch = IQM_RC_STRETCH_QAM_B_64; + break; + default : + return (DRX_STS_INVALID_ARG); + } + } + else + { + adcFrequency = ( commonAttr->sysClockFreq * 1000 ) / 3; + CHK_ZERO (channel->symbolrate); + iqmRcRate = ( adcFrequency / channel->symbolrate ) * ( 1 << 21 ) + + ( Frac28 ( ( adcFrequency % channel->symbolrate ), channel->symbolrate ) >> 7 ) - ( 1 << 23 ); + lcSymbolFreq = (u16_t)( Frac28 ( channel->symbolrate + (adcFrequency >> 13), adcFrequency ) >> 16 ); + if (lcSymbolFreq > 511) + lcSymbolFreq = 511; + + iqmRcStretch = 21; + } + + if( extAttr->standard == DRX_STANDARD_ITU_A ) + { + setEnvParameters = QAM_TOP_ANNEX_A; /* annex */ + setParamParameters[0] = channel->constellation; /* constellation */ + setParamParameters[1] = DRX_INTERLEAVEMODE_I12_J17; /* interleave mode */ + } + else if( extAttr->standard == DRX_STANDARD_ITU_B ) + { + setEnvParameters = QAM_TOP_ANNEX_B; /* annex */ + setParamParameters[0] = channel->constellation; /* constellation */ + setParamParameters[1] = channel->interleavemode; /* interleave mode */ + } + else if( extAttr->standard == DRX_STANDARD_ITU_C ) + { + setEnvParameters = QAM_TOP_ANNEX_C; /* annex */ + setParamParameters[0] = channel->constellation; /* constellation */ + setParamParameters[1] = DRX_INTERLEAVEMODE_I12_J17; /* interleave mode */ + } + else + { + return (DRX_STS_INVALID_ARG); + } + } + + if (op & QAM_SET_OP_ALL) + { + /* + STEP 1: reset demodulator + resets IQM, QAM and FEC HW blocks + resets SCU variables + */ + /* stop all comm_exec */ + WR16( devAddr, FEC_COMM_EXEC__A, FEC_COMM_EXEC_STOP ); + WR16( devAddr, QAM_COMM_EXEC__A, QAM_COMM_EXEC_STOP ); + WR16( devAddr, IQM_FS_COMM_EXEC__A, IQM_FS_COMM_EXEC_STOP ); + WR16( devAddr, IQM_FD_COMM_EXEC__A, IQM_FD_COMM_EXEC_STOP ); + WR16( devAddr, IQM_RC_COMM_EXEC__A, IQM_RC_COMM_EXEC_STOP ); + WR16( devAddr, IQM_RT_COMM_EXEC__A, IQM_RT_COMM_EXEC_STOP ); + WR16( devAddr, IQM_CF_COMM_EXEC__A, IQM_CF_COMM_EXEC_STOP ); + + cmdSCU.command = SCU_RAM_COMMAND_STANDARD_QAM | + SCU_RAM_COMMAND_CMD_DEMOD_RESET; + cmdSCU.parameterLen = 0; + cmdSCU.resultLen = 1; + cmdSCU.parameter = NULL; + cmdSCU.result = &cmdResult; + CHK_ERROR( SCUCommand( devAddr, &cmdSCU ) ); + } + + if ((op & QAM_SET_OP_ALL) || (op & QAM_SET_OP_CONSTELLATION )) + { + /* + STEP 2: configure demodulator + -set env + -set params (resets IQM,QAM,FEC HW; initializes some SCU variables ) + */ + cmdSCU.command = SCU_RAM_COMMAND_STANDARD_QAM | + SCU_RAM_COMMAND_CMD_DEMOD_SET_ENV; + cmdSCU.parameterLen = 1; + cmdSCU.resultLen = 1; + cmdSCU.parameter = &setEnvParameters; + cmdSCU.result = &cmdResult; + CHK_ERROR( SCUCommand( devAddr, &cmdSCU ) ); + + cmdSCU.command = SCU_RAM_COMMAND_STANDARD_QAM | + SCU_RAM_COMMAND_CMD_DEMOD_SET_PARAM; + cmdSCU.parameterLen = 2; + cmdSCU.resultLen = 1; + cmdSCU.parameter = setParamParameters; + cmdSCU.result = &cmdResult; + CHK_ERROR( SCUCommand( devAddr, &cmdSCU ) ); + /* set symbol rate */ + WR32( devAddr, IQM_RC_RATE_OFS_LO__A, iqmRcRate ); + extAttr->iqmRcRateOfs = iqmRcRate; + CHK_ERROR( SetQAMMeasurement ( demod, channel->constellation, channel->symbolrate)); + } + /* STEP 3: enable the system in a mode where the ADC provides valid signal + setup constellation independent registers */ + /* from qam_cmd.py script (qam_driver_b)*/ + /* TODO: remove re-writes of HW reset values */ + if ((op & QAM_SET_OP_ALL) || (op & QAM_SET_OP_SPECTRUM )) + { + CHK_ERROR ( SetFrequency ( demod, channel, tunerFreqOffset ) ); + } + + if ((op & QAM_SET_OP_ALL) || (op & QAM_SET_OP_CONSTELLATION )) + { + + WR16( devAddr, QAM_LC_SYMBOL_FREQ__A, lcSymbolFreq); + WR16( devAddr, IQM_RC_STRETCH__A, iqmRcStretch ); + } + + if (op & QAM_SET_OP_ALL) + { + if (extAttr->hasLNA==FALSE) + { + WR16( devAddr, IQM_AF_AMUX__A, 0x02); + } + WR16( devAddr, IQM_CF_SYMMETRIC__A, 0 ); + WR16( devAddr, IQM_CF_MIDTAP__A, 3 ); + WR16( devAddr, IQM_CF_OUT_ENA__A, IQM_CF_OUT_ENA_QAM__M ); + + WR16( devAddr, SCU_RAM_QAM_WR_RSV_0__A, 0x5f); /* scu temporary shut down agc */ + + WR16( devAddr, IQM_AF_SYNC_SEL__A, 3); + WR16( devAddr, IQM_AF_CLP_LEN__A, 0); + WR16( devAddr, IQM_AF_CLP_TH__A, 448); + WR16( devAddr, IQM_AF_SNS_LEN__A, 0); + WR16( devAddr, IQM_AF_PDREF__A, 4); + WR16( devAddr, IQM_AF_STDBY__A, 0x10); + WR16( devAddr, IQM_AF_PGA_GAIN__A, 11); + + WR16( devAddr, IQM_CF_POW_MEAS_LEN__A, 1); + WR16( devAddr, IQM_CF_SCALE_SH__A, IQM_CF_SCALE_SH__PRE); /*! reset default val ! */ + + WR16( devAddr, QAM_SY_TIMEOUT__A, QAM_SY_TIMEOUT__PRE); /*! reset default val ! */ + if( extAttr->standard == DRX_STANDARD_ITU_B ) + { + WR16( devAddr, QAM_SY_SYNC_LWM__A, QAM_SY_SYNC_LWM__PRE); /*! reset default val ! */ + WR16( devAddr, QAM_SY_SYNC_AWM__A, QAM_SY_SYNC_AWM__PRE); /*! reset default val ! */ + WR16( devAddr, QAM_SY_SYNC_HWM__A, QAM_SY_SYNC_HWM__PRE); /*! reset default val ! */ + } + else + { + switch ( channel->constellation ) { + case DRX_CONSTELLATION_QAM16: + case DRX_CONSTELLATION_QAM64: + case DRX_CONSTELLATION_QAM256: + WR16( devAddr, QAM_SY_SYNC_LWM__A, 0x03); + WR16( devAddr, QAM_SY_SYNC_AWM__A, 0x04); + WR16( devAddr, QAM_SY_SYNC_HWM__A, QAM_SY_SYNC_HWM__PRE); /*! reset default val ! */ + break; + case DRX_CONSTELLATION_QAM32: + case DRX_CONSTELLATION_QAM128: + WR16( devAddr, QAM_SY_SYNC_LWM__A, 0x03); + WR16( devAddr, QAM_SY_SYNC_AWM__A, 0x05); + WR16( devAddr, QAM_SY_SYNC_HWM__A, 0x06); + break; + default: + return (DRX_STS_ERROR); + } /* switch */ + } + + WR16( devAddr, QAM_LC_MODE__A, QAM_LC_MODE__PRE); /*! reset default val ! */ + WR16( devAddr, QAM_LC_RATE_LIMIT__A, 3); + WR16( devAddr, QAM_LC_LPF_FACTORP__A, 4); + WR16( devAddr, QAM_LC_LPF_FACTORI__A, 4); + WR16( devAddr, QAM_LC_MODE__A, 7); + WR16( devAddr, QAM_LC_QUAL_TAB0__A, 1); + WR16( devAddr, QAM_LC_QUAL_TAB1__A, 1); + WR16( devAddr, QAM_LC_QUAL_TAB2__A, 1); + WR16( devAddr, QAM_LC_QUAL_TAB3__A, 1); + WR16( devAddr, QAM_LC_QUAL_TAB4__A, 2); + WR16( devAddr, QAM_LC_QUAL_TAB5__A, 2); + WR16( devAddr, QAM_LC_QUAL_TAB6__A, 2); + WR16( devAddr, QAM_LC_QUAL_TAB8__A, 2); + WR16( devAddr, QAM_LC_QUAL_TAB9__A, 2); + WR16( devAddr, QAM_LC_QUAL_TAB10__A, 2); + WR16( devAddr, QAM_LC_QUAL_TAB12__A, 2); + WR16( devAddr, QAM_LC_QUAL_TAB15__A, 3); + WR16( devAddr, QAM_LC_QUAL_TAB16__A, 3); + WR16( devAddr, QAM_LC_QUAL_TAB20__A, 4); + WR16( devAddr, QAM_LC_QUAL_TAB25__A, 4); + + WR16( devAddr, IQM_FS_ADJ_SEL__A, 1); + WR16( devAddr, IQM_RC_ADJ_SEL__A, 1); + WR16( devAddr, IQM_CF_ADJ_SEL__A, 1); + WR16( devAddr, IQM_CF_POW_MEAS_LEN__A, 0); + WR16( devAddr, SCU_RAM_GPIO__A, 0 ); + + /* No more resets of the IQM, current standard correctly set => + now AGCs can be configured. */ + /* turn on IQMAF. It has to be in front of setAgc**() */ + CHK_ERROR( SetIqmAf( demod, TRUE ) ); + CHK_ERROR(ADCSynchronization (demod)); + + CHK_ERROR( InitAGC( demod ) ); + CHK_ERROR( SetAgcIf( demod, &(extAttr->qamIfAgcCfg), FALSE ) ); + CHK_ERROR( SetAgcRf( demod, &(extAttr->qamRfAgcCfg), FALSE ) ); + { + /* TODO fix this, store a DRXJCfgAfeGain_t structure in DRXJData_t instead + of only the gain */ + DRXJCfgAfeGain_t qamPgaCfg = { DRX_STANDARD_ITU_B, 0 }; + + qamPgaCfg.gain = extAttr->qamPgaCfg; + CHK_ERROR( CtrlSetCfgAfeGain( demod, &qamPgaCfg ) ); + } + CHK_ERROR( CtrlSetCfgPreSaw( demod, &(extAttr->qamPreSawCfg)) ); + } + + if ((op & QAM_SET_OP_ALL) || (op & QAM_SET_OP_CONSTELLATION )) + { + if( extAttr->standard == DRX_STANDARD_ITU_A ) + { + WRB ( devAddr, IQM_CF_TAP_RE0__A, sizeof(qamA_taps), ((pu8_t)qamA_taps) ); + WRB ( devAddr, IQM_CF_TAP_IM0__A, sizeof(qamA_taps), ((pu8_t)qamA_taps) ); + } + else if ( extAttr->standard == DRX_STANDARD_ITU_B ) + { + switch ( channel->constellation ) { + case DRX_CONSTELLATION_QAM64: + WRB ( devAddr, IQM_CF_TAP_RE0__A, sizeof(qamB64_taps), ((pu8_t)qamB64_taps) ); + WRB ( devAddr, IQM_CF_TAP_IM0__A, sizeof(qamB64_taps), ((pu8_t)qamB64_taps) ); + break; + case DRX_CONSTELLATION_QAM256: + WRB ( devAddr, IQM_CF_TAP_RE0__A, sizeof(qamB256_taps), ((pu8_t)qamB256_taps) ); + WRB ( devAddr, IQM_CF_TAP_IM0__A, sizeof(qamB256_taps), ((pu8_t)qamB256_taps) ); + break; + default: + return (DRX_STS_ERROR); + } + } + else if ( extAttr->standard == DRX_STANDARD_ITU_C ) + { + WRB ( devAddr, IQM_CF_TAP_RE0__A, sizeof(qamC_taps), ((pu8_t)qamC_taps) ); + WRB ( devAddr, IQM_CF_TAP_IM0__A, sizeof(qamC_taps), ((pu8_t)qamC_taps) ); + } + + /* SETP 4: constellation specific setup */ + switch ( channel->constellation ) { + case DRX_CONSTELLATION_QAM16: + CHK_ERROR(SetQAM16( demod )); + break; + case DRX_CONSTELLATION_QAM32: + CHK_ERROR(SetQAM32( demod )); + break; + case DRX_CONSTELLATION_QAM64: + CHK_ERROR(SetQAM64( demod )); + break; + case DRX_CONSTELLATION_QAM128: + CHK_ERROR(SetQAM128( demod )); + break; + case DRX_CONSTELLATION_QAM256: + CHK_ERROR(SetQAM256( demod )); + break; + default: + return (DRX_STS_ERROR); + } /* switch */ + } + + if ((op & QAM_SET_OP_ALL)) + { + WR16(devAddr, IQM_CF_SCALE_SH__A, 0 ); + + /* Mpeg output has to be in front of FEC active */ + CHK_ERROR ( SetMPEGTEIHandling( demod )); + CHK_ERROR ( BitReverseMPEGOutput( demod ) ); + CHK_ERROR ( SetMPEGStartWidth ( demod ) ); + { + /* TODO: move to setStandard after hardware reset value problem is solved */ + /* Configure initial MPEG output */ + DRXCfgMPEGOutput_t cfgMPEGOutput; + + cfgMPEGOutput.enableMPEGOutput = TRUE; + cfgMPEGOutput.insertRSByte = commonAttr->mpegCfg.insertRSByte; + cfgMPEGOutput.enableParallel = commonAttr->mpegCfg.enableParallel; + cfgMPEGOutput.invertDATA = commonAttr->mpegCfg.invertDATA; + cfgMPEGOutput.invertERR = commonAttr->mpegCfg.invertERR; + cfgMPEGOutput.invertSTR = commonAttr->mpegCfg.invertSTR; + cfgMPEGOutput.invertVAL = commonAttr->mpegCfg.invertVAL; + cfgMPEGOutput.invertCLK = commonAttr->mpegCfg.invertCLK; + cfgMPEGOutput.staticCLK = commonAttr->mpegCfg.staticCLK; + cfgMPEGOutput.bitrate = commonAttr->mpegCfg.bitrate; + CHK_ERROR( CtrlSetCfgMPEGOutput( demod, &cfgMPEGOutput) ); + } + } + + if ((op & QAM_SET_OP_ALL) || (op & QAM_SET_OP_CONSTELLATION )) + { + + /* STEP 5: start QAM demodulator (starts FEC, QAM and IQM HW) */ + cmdSCU.command = SCU_RAM_COMMAND_STANDARD_QAM | + SCU_RAM_COMMAND_CMD_DEMOD_START; + cmdSCU.parameterLen = 0; + cmdSCU.resultLen = 1; + cmdSCU.parameter = NULL; + cmdSCU.result = &cmdResult; + CHK_ERROR( SCUCommand( devAddr, &cmdSCU ) ); + } + + WR16(devAddr, IQM_COMM_EXEC__A, IQM_COMM_EXEC_ACTIVE ); + WR16(devAddr, QAM_COMM_EXEC__A, QAM_COMM_EXEC_ACTIVE ); + WR16(devAddr, FEC_COMM_EXEC__A, FEC_COMM_EXEC_ACTIVE ); + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} + +/*============================================================================*/ +static DRXStatus_t +CtrlGetQAMSigQuality( pDRXDemodInstance_t demod, + pDRXSigQuality_t sigQuality ); +static DRXStatus_t +qamFlipSpec ( pDRXDemodInstance_t demod, + pDRXChannel_t channel) +{ + u32_t iqmFsRateOfs = 0; + u32_t iqmFsRateLo = 0; + u16_t qamCtlEna = 0; + u16_t data = 0; + u16_t equMode = 0; + u16_t fsmState = 0; + int i = 0; + int ofsofs = 0; + pI2CDeviceAddr_t devAddr = NULL; + pDRXJData_t extAttr = NULL; + + devAddr = demod -> myI2CDevAddr; + extAttr = (pDRXJData_t)demod->myExtAttr; + + /* Silence the controlling of lc, equ, and the acquisition state machine */ + RR16( devAddr, SCU_RAM_QAM_CTL_ENA__A, &qamCtlEna ); + WR16( devAddr, SCU_RAM_QAM_CTL_ENA__A, qamCtlEna + & ~ ( SCU_RAM_QAM_CTL_ENA_ACQ__M + | SCU_RAM_QAM_CTL_ENA_EQU__M + | SCU_RAM_QAM_CTL_ENA_LC__M) ); + + /* freeze the frequency control loop */ + WR16( devAddr, QAM_LC_CF__A, 0); + WR16( devAddr, QAM_LC_CF1__A, 0); + + ARR32( devAddr, IQM_FS_RATE_OFS_LO__A , &iqmFsRateOfs ); + ARR32( devAddr, IQM_FS_RATE_LO__A, &iqmFsRateLo ); + ofsofs = iqmFsRateLo - iqmFsRateOfs; + iqmFsRateOfs = ~iqmFsRateOfs + 1; + iqmFsRateOfs -= 2 * ofsofs; + + /* freeze dq/fq updating */ + RR16( devAddr, QAM_DQ_MODE__A, &data); + data = (data & 0xfff9); + WR16( devAddr, QAM_DQ_MODE__A, data ); + WR16( devAddr, QAM_FQ_MODE__A, data ); + + /* lc_cp / _ci / _ca */ + WR16( devAddr, QAM_LC_CI__A, 0 ); + WR16( devAddr, QAM_LC_EP__A, 0 ); + WR16( devAddr, QAM_FQ_LA_FACTOR__A, 0 ); + + /* flip the spec */ + WR32( devAddr, IQM_FS_RATE_OFS_LO__A , iqmFsRateOfs ); + extAttr->iqmFsRateOfs = iqmFsRateOfs; + extAttr->posImage = (extAttr->posImage)?FALSE:TRUE; + + /* freeze dq/fq updating */ + RR16( devAddr, QAM_DQ_MODE__A, &data); + equMode = data; + data = (data & 0xfff9); + WR16( devAddr, QAM_DQ_MODE__A, data ); + WR16( devAddr, QAM_FQ_MODE__A, data ); + + for ( i = 0; i < 28; i++) + { + RR16( devAddr, QAM_DQ_TAP_IM_EL0__A + (2 * i), &data); + WR16( devAddr, QAM_DQ_TAP_IM_EL0__A + (2 * i), -data); + } + + for ( i = 0; i < 24; i++) + { + RR16( devAddr, QAM_FQ_TAP_IM_EL0__A + (2 * i), &data); + WR16( devAddr, QAM_FQ_TAP_IM_EL0__A + (2 * i), -data); + } + + data = equMode; + WR16( devAddr, QAM_DQ_MODE__A, data ); + WR16( devAddr, QAM_FQ_MODE__A, data ); + + WR16( devAddr, SCU_RAM_QAM_FSM_STATE_TGT__A, 4 ); + + i = 0; + while ( (fsmState != 4) && (i++ < 100) ) + { + RR16( devAddr, SCU_RAM_QAM_FSM_STATE__A, &fsmState ); + } + WR16( devAddr, SCU_RAM_QAM_CTL_ENA__A, (qamCtlEna | 0x0016) ); + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); + +} + +#define NO_LOCK 0x0 +#define DEMOD_LOCKED 0x1 +#define SYNC_FLIPPED 0x2 +#define SPEC_MIRRORED 0x4 +/** +* \fn DRXStatus_t QAM64Auto () +* \brief auto do sync pattern switching and mirroring. +* \param demod: instance of demod. +* \param channel: pointer to channel data. +* \param tunerFreqOffset: tuner frequency offset. +* \param lockStatus: pointer to lock status. +* \return DRXStatus_t. +*/ +static DRXStatus_t +QAM64Auto( pDRXDemodInstance_t demod, + pDRXChannel_t channel, + DRXFrequency_t tunerFreqOffset, + pDRXLockStatus_t lockStatus + ) +{ + DRXSigQuality_t sigQuality; + u16_t data = 0; + u32_t state = NO_LOCK; + u32_t startTime = 0; + u32_t dLockedTime= 0; + pDRXJData_t extAttr = NULL; + u32_t timeoutOfs = 0; + + /* external attributes for storing aquired channel constellation */ + extAttr = (pDRXJData_t)demod -> myExtAttr; + *lockStatus = DRX_NOT_LOCKED; + startTime = DRXBSP_HST_Clock(); + state = NO_LOCK; + do + { + CHK_ERROR( CtrlLockStatus(demod, lockStatus) ); + + switch (state) + { + case NO_LOCK: + if ( *lockStatus == DRXJ_DEMOD_LOCK ) + { + CHK_ERROR ( CtrlGetQAMSigQuality ( demod, &sigQuality ) ); + if (sigQuality.MER > 208) + { + state = DEMOD_LOCKED; + /* some delay to see if fec_lock possible TODO find the right value */ + timeoutOfs += DRXJ_QAM_DEMOD_LOCK_EXT_WAITTIME; /* see something, waiting longer */ + dLockedTime = DRXBSP_HST_Clock(); + } + } + break; + case DEMOD_LOCKED: + if ((*lockStatus == DRXJ_DEMOD_LOCK) && /* still demod_lock in 150ms*/ + ((DRXBSP_HST_Clock() - dLockedTime) > DRXJ_QAM_FEC_LOCK_WAITTIME)) + { + RR16( demod->myI2CDevAddr, QAM_SY_TIMEOUT__A, &data ); + WR16( demod->myI2CDevAddr, QAM_SY_TIMEOUT__A, data | 0x1 ); + state = SYNC_FLIPPED; + DRXBSP_HST_Sleep(10); + } + break; + case SYNC_FLIPPED: + if (*lockStatus == DRXJ_DEMOD_LOCK) + { + if (channel->mirror == DRX_MIRROR_AUTO) + { + /* flip sync pattern back */ + RR16( demod->myI2CDevAddr, QAM_SY_TIMEOUT__A, &data ); + WR16( demod->myI2CDevAddr, QAM_SY_TIMEOUT__A, data & 0xFFFE ); + /* flip spectrum */ + extAttr->mirror = DRX_MIRROR_YES; + CHK_ERROR ( qamFlipSpec ( demod, channel ) ); + state = SPEC_MIRRORED; + /* reset timer TODO: still need 500ms? */ + startTime = dLockedTime = DRXBSP_HST_Clock(); + timeoutOfs = 0; + } + else /* no need to wait lock */ + { + startTime = DRXBSP_HST_Clock() - DRXJ_QAM_MAX_WAITTIME - timeoutOfs; + } + } + break; + case SPEC_MIRRORED: + if ((*lockStatus == DRXJ_DEMOD_LOCK) && /* still demod_lock in 150ms*/ + ((DRXBSP_HST_Clock() - dLockedTime) > DRXJ_QAM_FEC_LOCK_WAITTIME)) + { + CHK_ERROR ( CtrlGetQAMSigQuality ( demod, &sigQuality ) ); + if (sigQuality.MER > 208) + { + RR16( demod->myI2CDevAddr, QAM_SY_TIMEOUT__A, &data ); + WR16( demod->myI2CDevAddr, QAM_SY_TIMEOUT__A, data | 0x1 ); + /* no need to wait lock */ + startTime = DRXBSP_HST_Clock() - DRXJ_QAM_MAX_WAITTIME - timeoutOfs; + } + } + break; + default: + break; + } + DRXBSP_HST_Sleep(10); + } while + ( ( *lockStatus != DRX_LOCKED ) && + ( *lockStatus != DRX_NEVER_LOCK ) && + ( (DRXBSP_HST_Clock() - startTime) < (DRXJ_QAM_MAX_WAITTIME + timeoutOfs)) + ); + /* Returning control to apllication ... */ + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} + +/** +* \fn DRXStatus_t QAM256Auto () +* \brief auto do sync pattern switching and mirroring. +* \param demod: instance of demod. +* \param channel: pointer to channel data. +* \param tunerFreqOffset: tuner frequency offset. +* \param lockStatus: pointer to lock status. +* \return DRXStatus_t. +*/ +static DRXStatus_t +QAM256Auto( pDRXDemodInstance_t demod, + pDRXChannel_t channel, + DRXFrequency_t tunerFreqOffset, + pDRXLockStatus_t lockStatus + ) +{ + DRXSigQuality_t sigQuality; + u32_t state = NO_LOCK; + u32_t startTime = 0; + u32_t dLockedTime= 0; + pDRXJData_t extAttr = NULL; + u32_t timeoutOfs = DRXJ_QAM_DEMOD_LOCK_EXT_WAITTIME; + + /* external attributes for storing aquired channel constellation */ + extAttr = (pDRXJData_t)demod -> myExtAttr; + *lockStatus = DRX_NOT_LOCKED; + startTime = DRXBSP_HST_Clock(); + state = NO_LOCK; + do + { + CHK_ERROR( CtrlLockStatus( demod, lockStatus) ); + switch (state) + { + case NO_LOCK: + if ( *lockStatus == DRXJ_DEMOD_LOCK ) + { + CHK_ERROR ( CtrlGetQAMSigQuality ( demod, &sigQuality ) ); + if (sigQuality.MER > 268) + { + state = DEMOD_LOCKED; + timeoutOfs += DRXJ_QAM_DEMOD_LOCK_EXT_WAITTIME; /* see something, wait longer */ + dLockedTime = DRXBSP_HST_Clock(); + } + } + break; + case DEMOD_LOCKED: + if ( *lockStatus == DRXJ_DEMOD_LOCK ) + { + if ((channel->mirror == DRX_MIRROR_AUTO) && + ((DRXBSP_HST_Clock() - dLockedTime) > DRXJ_QAM_FEC_LOCK_WAITTIME)) + { + extAttr->mirror = DRX_MIRROR_YES; + CHK_ERROR ( qamFlipSpec ( demod, channel ) ); + state = SPEC_MIRRORED; + /* reset timer TODO: still need 300ms? */ + startTime = DRXBSP_HST_Clock(); + timeoutOfs = - DRXJ_QAM_MAX_WAITTIME / 2; + } + } + break; + case SPEC_MIRRORED: + break; + default: + break; + } + DRXBSP_HST_Sleep(10); + } while + ( ( *lockStatus < DRX_LOCKED ) && + ( *lockStatus != DRX_NEVER_LOCK ) && + ( (DRXBSP_HST_Clock() - startTime) < (DRXJ_QAM_MAX_WAITTIME + timeoutOfs)) ); + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} + +/** +* \fn DRXStatus_t SetQAMChannel () +* \brief Set QAM channel according to the requested constellation. +* \param demod: instance of demod. +* \param channel: pointer to channel data. +* \return DRXStatus_t. +*/ +static DRXStatus_t +SetQAMChannel( pDRXDemodInstance_t demod, + pDRXChannel_t channel, + DRXFrequency_t tunerFreqOffset + ) +{ + DRXLockStatus_t lockStatus = DRX_NOT_LOCKED; + pDRXJData_t extAttr = NULL; + Bool_t autoFlag = FALSE; + + /* external attributes for storing aquired channel constellation */ + extAttr = (pDRXJData_t)demod->myExtAttr; + + /* set QAM channel constellation */ + switch ( channel->constellation ) { + case DRX_CONSTELLATION_QAM16 : + case DRX_CONSTELLATION_QAM32 : + case DRX_CONSTELLATION_QAM64 : + case DRX_CONSTELLATION_QAM128 : + case DRX_CONSTELLATION_QAM256 : + extAttr->constellation = channel->constellation; + if (channel->mirror == DRX_MIRROR_AUTO) + { + extAttr->mirror = DRX_MIRROR_NO; + } + else + { + extAttr->mirror = channel->mirror; + } + CHK_ERROR ( SetQAM( demod, channel, tunerFreqOffset, QAM_SET_OP_ALL) ); + + if ( (extAttr->standard == DRX_STANDARD_ITU_B) && + (channel->constellation == DRX_CONSTELLATION_QAM64) ) + { + CHK_ERROR ( QAM64Auto( demod, channel, tunerFreqOffset, &lockStatus)); + } + + if ( (extAttr->standard == DRX_STANDARD_ITU_B) && + (channel->mirror == DRX_MIRROR_AUTO) && + (channel->constellation == DRX_CONSTELLATION_QAM256) ) + { + CHK_ERROR ( QAM256Auto( demod, channel, tunerFreqOffset, &lockStatus)); + } + break; + case DRX_CONSTELLATION_AUTO: /* for channel scan */ + if ( extAttr->standard == DRX_STANDARD_ITU_B ) + { + autoFlag = TRUE; + /* try to lock default QAM constellation: QAM64 */ + channel->constellation = DRX_CONSTELLATION_QAM256; + extAttr->constellation = DRX_CONSTELLATION_QAM256; + if (channel->mirror == DRX_MIRROR_AUTO) + { + extAttr->mirror = DRX_MIRROR_NO; + } + else + { + extAttr->mirror = channel->mirror; + } + CHK_ERROR ( SetQAM( demod, channel, tunerFreqOffset, QAM_SET_OP_ALL ) ); + CHK_ERROR ( QAM256Auto( demod, channel, tunerFreqOffset, &lockStatus )); + + if ( lockStatus < DRX_LOCKED ) + { + /* QAM254 not locked -> try to lock QAM64 constellation */ + channel->constellation = DRX_CONSTELLATION_QAM64; + extAttr->constellation = DRX_CONSTELLATION_QAM64; + if (channel->mirror == DRX_MIRROR_AUTO) + { + extAttr->mirror = DRX_MIRROR_NO; + } + else + { + extAttr->mirror = channel->mirror; + } + { + u16_t qamCtlEna = 0; + RR16( demod->myI2CDevAddr, SCU_RAM_QAM_CTL_ENA__A, &qamCtlEna ); + WR16( demod->myI2CDevAddr, SCU_RAM_QAM_CTL_ENA__A, qamCtlEna & ~SCU_RAM_QAM_CTL_ENA_ACQ__M ); + WR16( demod->myI2CDevAddr, SCU_RAM_QAM_FSM_STATE_TGT__A, 0x2 ); /* force to rate hunting */ + + CHK_ERROR ( SetQAM( demod, channel, tunerFreqOffset, QAM_SET_OP_CONSTELLATION) ); + WR16( demod->myI2CDevAddr, SCU_RAM_QAM_CTL_ENA__A, qamCtlEna ); + } + CHK_ERROR ( QAM64Auto( demod, channel, tunerFreqOffset, &lockStatus )); + } + channel->constellation = DRX_CONSTELLATION_AUTO; + } + else if ( extAttr->standard == DRX_STANDARD_ITU_C ) + { + channel->constellation = DRX_CONSTELLATION_QAM64; + extAttr->constellation = DRX_CONSTELLATION_QAM64; + autoFlag = TRUE; + + if (channel->mirror == DRX_MIRROR_AUTO) + { + extAttr->mirror = DRX_MIRROR_NO; + } + else + { + extAttr->mirror = channel->mirror; + } + { + u16_t qamCtlEna = 0; + RR16( demod->myI2CDevAddr, SCU_RAM_QAM_CTL_ENA__A, &qamCtlEna ); + WR16( demod->myI2CDevAddr, SCU_RAM_QAM_CTL_ENA__A, qamCtlEna & ~SCU_RAM_QAM_CTL_ENA_ACQ__M ); + WR16( demod->myI2CDevAddr, SCU_RAM_QAM_FSM_STATE_TGT__A, 0x2 ); /* force to rate hunting */ + + CHK_ERROR ( SetQAM( demod, channel, tunerFreqOffset, QAM_SET_OP_CONSTELLATION) ); + WR16( demod->myI2CDevAddr, SCU_RAM_QAM_CTL_ENA__A, qamCtlEna ); + } + CHK_ERROR ( QAM64Auto( demod, channel, tunerFreqOffset, &lockStatus )); + channel->constellation = DRX_CONSTELLATION_AUTO; + } + else + { + channel->constellation = DRX_CONSTELLATION_AUTO; + return (DRX_STS_INVALID_ARG); + } + break; + default: + return (DRX_STS_INVALID_ARG); + } + + return (DRX_STS_OK); +rw_error: + /* restore starting value */ + if (autoFlag) + channel->constellation = DRX_CONSTELLATION_AUTO; + return (DRX_STS_ERROR); +} + +/*============================================================================*/ + +/** +* \fn static short GetQAMRSErrCount(pI2CDeviceAddr_t devAddr) +* \brief Get RS error count in QAM mode (used for post RS BER calculation) +* \return Error code +* +* precondition: measurement period & measurement prescale must be set +* +*/ +static DRXStatus_t +GetQAMRSErrCount(pI2CDeviceAddr_t devAddr, pDRXJRSErrors_t RSErrors) +{ + u16_t nrBitErrors = 0, + nrSymbolErrors = 0, + nrPacketErrors = 0, + nrFailures = 0, + nrSncParFailCount = 0; + + /* check arguments */ + if ( devAddr == NULL ) + { + return (DRX_STS_INVALID_ARG); + } + + /* all reported errors are received in the */ + /* most recently finished measurment period */ + /* no of pre RS bit errors */ + RR16( devAddr, FEC_RS_NR_BIT_ERRORS__A, &nrBitErrors ); + /* no of symbol errors */ + RR16( devAddr, FEC_RS_NR_SYMBOL_ERRORS__A, &nrSymbolErrors ); + /* no of packet errors */ + RR16( devAddr, FEC_RS_NR_PACKET_ERRORS__A, &nrPacketErrors ); + /* no of failures to decode */ + RR16( devAddr, FEC_RS_NR_FAILURES__A, &nrFailures ); + /* no of post RS bit erros */ + RR16( devAddr, FEC_OC_SNC_FAIL_COUNT__A, &nrSncParFailCount ); + /* TODO: NOTE */ + /* These register values are fetched in non-atomic fashion */ + /* It is possible that the read values contain unrelated information */ + + RSErrors->nrBitErrors = nrBitErrors & FEC_RS_NR_BIT_ERRORS__M; + RSErrors->nrSymbolErrors = nrSymbolErrors & FEC_RS_NR_SYMBOL_ERRORS__M; + RSErrors->nrPacketErrors = nrPacketErrors & FEC_RS_NR_PACKET_ERRORS__M; + RSErrors->nrFailures = nrFailures & FEC_RS_NR_FAILURES__M; + RSErrors->nrSncParFailCount = nrSncParFailCount & FEC_OC_SNC_FAIL_COUNT__M; + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} + +/*============================================================================*/ + +/** +* \fn DRXStatus_t CtrlGetQAMSigQuality() +* \brief Retreive QAM signal quality from device. +* \param devmod Pointer to demodulator instance. +* \param sigQuality Pointer to signal quality data. +* \return DRXStatus_t. +* \retval DRX_STS_OK sigQuality contains valid data. +* \retval DRX_STS_INVALID_ARG sigQuality is NULL. +* \retval DRX_STS_ERROR Erroneous data, sigQuality contains invalid data. + +* Pre-condition: Device must be started and in lock. +*/ +static DRXStatus_t +CtrlGetQAMSigQuality( pDRXDemodInstance_t demod, + pDRXSigQuality_t sigQuality ) +{ + pI2CDeviceAddr_t devAddr = NULL; + pDRXJData_t extAttr = NULL; + DRXConstellation_t constellation = DRX_CONSTELLATION_UNKNOWN; + DRXJRSErrors_t measuredRSErrors = { 0, 0, 0, 0, 0 }; + + u32_t preBitErrRS = 0; /* pre RedSolomon Bit Error Rate */ + u32_t postBitErrRS = 0; /* post RedSolomon Bit Error Rate */ + u32_t pktErrs = 0; /* no of packet errors in RS */ + u16_t qamSlErrPower = 0; /* accumulated error between raw and sliced symbols */ + u16_t qsymErrVD = 0; /* quadrature symbol errors in QAM_VD */ + u16_t fecOcPeriod = 0; /* SNC sync failure measurement period */ + u16_t fecRsPrescale = 0; /* ReedSolomon Measurement Prescale */ + u16_t fecRsPeriod = 0; /* Value for corresponding I2C register */ + /* calculation constants */ + u32_t rsBitCnt = 0; /* RedSolomon Bit Count */ + u32_t qamSlSigPower = 0; /* used for MER, depends of QAM constellation */ + /* intermediate results */ + u32_t e = 0; /* exponent value used for QAM BER/SER */ + u32_t m = 0; /* mantisa value used for QAM BER/SER */ + u32_t berCnt = 0; /* BER count */ + /* signal quality info */ + u32_t qamSlMer = 0; /* QAM MER */ + u32_t qamPreRSBer = 0; /* Pre RedSolomon BER */ + u32_t qamPostRSBer = 0; /* Post RedSolomon BER */ + u32_t qamVDSer = 0; /* ViterbiDecoder SER */ + u16_t qamVdPrescale = 0; /* Viterbi Measurement Prescale */ + u16_t qamVdPeriod = 0; /* Viterbi Measurement period */ + u32_t vdBitCnt = 0; /* ViterbiDecoder Bit Count */ + + /* get device basic information */ + devAddr = demod -> myI2CDevAddr; + extAttr = (pDRXJData_t)demod->myExtAttr; + constellation = extAttr->constellation; + + /* read the physical registers */ + /* Get the RS error data */ + CHK_ERROR ( GetQAMRSErrCount ( devAddr, &measuredRSErrors ) ); + /* get the register value needed for MER */ + RR16( devAddr, QAM_SL_ERR_POWER__A, &qamSlErrPower ); + /* get the register value needed for post RS BER */ + RR16 ( devAddr, FEC_OC_SNC_FAIL_PERIOD__A, &fecOcPeriod ); + + /* get constants needed for signal quality calculation */ + fecRsPeriod = extAttr->fecRsPeriod; + fecRsPrescale = extAttr->fecRsPrescale; + rsBitCnt = fecRsPeriod * fecRsPrescale * extAttr->fecRsPlen; + qamVdPeriod = extAttr->qamVdPeriod; + qamVdPrescale = extAttr->qamVdPrescale; + vdBitCnt = qamVdPeriod * qamVdPrescale * extAttr->fecVdPlen; + + /* DRXJ_QAM_SL_SIG_POWER_QAMxxx * 4 */ + switch ( constellation ) + { + case DRX_CONSTELLATION_QAM16: + qamSlSigPower = DRXJ_QAM_SL_SIG_POWER_QAM16 << 2; + break; + case DRX_CONSTELLATION_QAM32: + qamSlSigPower = DRXJ_QAM_SL_SIG_POWER_QAM32 << 2; + break; + case DRX_CONSTELLATION_QAM64: + qamSlSigPower = DRXJ_QAM_SL_SIG_POWER_QAM64 << 2; + break; + case DRX_CONSTELLATION_QAM128: + qamSlSigPower = DRXJ_QAM_SL_SIG_POWER_QAM128 << 2; + break; + case DRX_CONSTELLATION_QAM256: + qamSlSigPower = DRXJ_QAM_SL_SIG_POWER_QAM256 << 2; + break; + default: + return (DRX_STS_ERROR); + } + + /* ------------------------------ */ + /* MER Calculation */ + /* ------------------------------ */ + /* MER is good if it is above 27.5 for QAM256 or 21.5 for QAM64 */ + + /* 10.0*log10(qam_sl_sig_power * 4.0 / qam_sl_err_power); */ + if ( qamSlErrPower == 0 ) + qamSlMer = 0; + else + qamSlMer = Log10Times100( qamSlSigPower ) - Log10Times100( ( u32_t ) qamSlErrPower ); + + + /* ----------------------------------------- */ + /* Pre Viterbi Symbol Error Rate Calculation */ + /* ----------------------------------------- */ + /* pre viterbi SER is good if it is bellow 0.025 */ + + /* get the register value */ + /* no of quadrature symbol errors */ + RR16( devAddr, QAM_VD_NR_QSYM_ERRORS__A , &qsymErrVD ); + /* Extract the Exponent and the Mantisa */ + /* of number of quadrature symbol errors */ + e = ( qsymErrVD & QAM_VD_NR_QSYM_ERRORS_EXP__M ) >> + QAM_VD_NR_QSYM_ERRORS_EXP__B; + m = ( qsymErrVD & QAM_VD_NR_SYMBOL_ERRORS_FIXED_MANT__M ) >> + QAM_VD_NR_SYMBOL_ERRORS_FIXED_MANT__B; + + if ( (m << e) >> 3 > 549752 ) /* the max of FracTimes1e6 */ + { + qamVDSer = 500000; /* clip BER 0.5 */ + } + else + { + qamVDSer = FracTimes1e6(m << ((e > 2)? (e - 3):e), vdBitCnt * ((e > 2)?1:8) / 8 ); + } + + /* --------------------------------------- */ + /* pre and post RedSolomon BER Calculation */ + /* --------------------------------------- */ + /* pre RS BER is good if it is below 3.5e-4 */ + + /* get the register values */ + preBitErrRS = ( u32_t ) measuredRSErrors.nrBitErrors; + pktErrs = postBitErrRS = ( u32_t ) measuredRSErrors.nrSncParFailCount; + + /* Extract the Exponent and the Mantisa of the */ + /* pre Reed-Solomon bit error count */ + e = ( preBitErrRS & FEC_RS_NR_BIT_ERRORS_EXP__M ) >> + FEC_RS_NR_BIT_ERRORS_EXP__B; + m = ( preBitErrRS & FEC_RS_NR_BIT_ERRORS_FIXED_MANT__M ) >> + FEC_RS_NR_BIT_ERRORS_FIXED_MANT__B; + + berCnt = m << e; + + /*qamPreRSBer = FracTimes1e6( berCnt, rsBitCnt ); */ + if ( m > (rsBitCnt >> (e + 1)) || (rsBitCnt >> e) == 0 ) + { + qamPreRSBer = 500000; /* clip BER 0.5 */ + } + else + { + qamPreRSBer = FracTimes1e6(m, rsBitCnt >> e ); + } + + /* post RS BER = 1000000* (11.17 * FEC_OC_SNC_FAIL_COUNT__A) / */ + /* (1504.0 * FEC_OC_SNC_FAIL_PERIOD__A) */ + /* + => c = (1000000*100*11.17)/1504 = + post RS BER = (( c* FEC_OC_SNC_FAIL_COUNT__A) / + (100 * FEC_OC_SNC_FAIL_PERIOD__A) + *100 and /100 is for more precision. + => (20 bits * 12 bits) /(16 bits * 7 bits) => safe in 32 bits computation + + Precision errors still possible. + */ + e = postBitErrRS * 742686; + m = fecOcPeriod * 100; + if ( fecOcPeriod == 0 ) + qamPostRSBer = 0xFFFFFFFF; + else + qamPostRSBer = e/m; + + /* fill signal quality data structure */ + sigQuality->MER = ( ( u16_t ) qamSlMer ); + if (extAttr->standard == DRX_STANDARD_ITU_B) + { + sigQuality->preViterbiBER = qamVDSer; + } + else + { + sigQuality->preViterbiBER = qamPreRSBer; + } + sigQuality->postViterbiBER = qamPreRSBer; + sigQuality->postReedSolomonBER = qamPostRSBer; + sigQuality->scaleFactorBER = ( ( u32_t ) 1000000 ); +#ifdef DRXJ_SIGNAL_ACCUM_ERR + CHK_ERROR (GetAccPktErr (demod, &sigQuality->packetError)); +#else + sigQuality->packetError = ( ( u16_t ) pktErrs ); +#endif + + return (DRX_STS_OK); + rw_error: + return (DRX_STS_ERROR); +} + +/** +* \fn DRXStatus_t CtrlGetQAMConstel() +* \brief Retreive a QAM constellation point via I2C. +* \param demod Pointer to demodulator instance. +* \param complexNr Pointer to the structure in which to store the + constellation point. +* \return DRXStatus_t. +*/ +static DRXStatus_t +CtrlGetQAMConstel( pDRXDemodInstance_t demod, + pDRXComplex_t complexNr ) +{ + u16_t fecOcOcrMode = 0; /**< FEC OCR grabber configuration */ + u16_t qamSlCommMb = 0; /**< QAM SL MB configuration */ + u16_t qamSlCommMbInit = 0; /**< QAM SL MB intial configuration */ + u16_t im = 0; /**< constellation Im part */ + u16_t re = 0; /**< constellation Re part */ + u32_t data = 0; + pI2CDeviceAddr_t devAddr = NULL; /**< device address */ + + /* read device info */ + devAddr = demod -> myI2CDevAddr; + + /* TODO: */ + /* Monitor bus grabbing is an open external interface issue */ + /* Needs to be checked when external interface PG is updated */ + + /* Configure MB (Monitor bus) */ + RR16( devAddr, QAM_SL_COMM_MB__A, &qamSlCommMbInit ); + /* set observe flag & MB mux */ + qamSlCommMb = qamSlCommMbInit & (~ ( QAM_SL_COMM_MB_OBS__M + + QAM_SL_COMM_MB_MUX_OBS__M ) ); + qamSlCommMb |= ( QAM_SL_COMM_MB_OBS_ON + + QAM_SL_COMM_MB_MUX_OBS_CONST_CORR ); + WR16( devAddr, QAM_SL_COMM_MB__A, qamSlCommMb ); + + /* Enable MB grabber in the FEC OC */ + fecOcOcrMode = ( /* output select: observe bus */ + ( FEC_OC_OCR_MODE_MB_SELECT__M & + ( 0x0 << FEC_OC_OCR_MODE_MB_SELECT__B ) ) | + /* grabber enable: on */ + ( FEC_OC_OCR_MODE_GRAB_ENABLE__M & + ( 0x1 << FEC_OC_OCR_MODE_GRAB_ENABLE__B ) ) | + /* grabber select: observe bus */ + ( FEC_OC_OCR_MODE_GRAB_SELECT__M & + ( 0x0 << FEC_OC_OCR_MODE_GRAB_SELECT__B ) ) | + /* grabber mode: continuous */ + ( FEC_OC_OCR_MODE_GRAB_COUNTED__M & + ( 0x0 << FEC_OC_OCR_MODE_GRAB_COUNTED__B ) ) ); + WR16( devAddr, FEC_OC_OCR_MODE__A, fecOcOcrMode ); + + /* Disable MB grabber in the FEC OC */ + WR16( devAddr, FEC_OC_OCR_MODE__A, 0x00 ); + + /* read data */ + RR32( devAddr, FEC_OC_OCR_GRAB_RD0__A, &data ); + re = (u16_t)(data & FEC_OC_OCR_GRAB_RD0__M); + im = (u16_t)((data >> 16) & FEC_OC_OCR_GRAB_RD1__M); + + /* TODO: */ + /* interpret data (re & im) according to the Monitor bus mapping ?? */ + + /* sign extension, 10th bit is sign bit */ + if ( (re & 0x0200) == 0x0200 ) + { + re |= 0xFC00; + } + if ( (im & 0x0200) == 0x0200 ) + { + im |= 0xFC00; + } + complexNr->re = ( ( s16_t ) re ) ; + complexNr->im = ( ( s16_t ) im ) ; + + /* Restore MB (Monitor bus) */ + WR16( devAddr, QAM_SL_COMM_MB__A, qamSlCommMbInit ); + + return (DRX_STS_OK); + rw_error: + return (DRX_STS_ERROR); +} +#endif /* #ifndef DRXJ_VSB_ONLY */ + +/*============================================================================*/ +/*== END QAM DATAPATH FUNCTIONS ==*/ +/*============================================================================*/ + +/*============================================================================*/ +/*============================================================================*/ +/*== ATV DATAPATH FUNCTIONS ==*/ +/*============================================================================*/ +/*============================================================================*/ + +/* + Implementation notes. + + NTSC/FM AGCs + + Four AGCs are used for NTSC: + (1) RF (used to attenuate the input signal in case of to much power) + (2) IF (used to attenuate the input signal in case of to much power) + (3) Video AGC (used to amplify the output signal in case input to low) + (4) SIF AGC (used to amplify the output signal in case input to low) + + Video AGC is coupled to RF and IF. SIF AGC is not coupled. It is assumed + that the coupling between Video AGC and the RF and IF AGCs also works in + favor of the SIF AGC. + + Three AGCs are used for FM: + (1) RF (used to attenuate the input signal in case of to much power) + (2) IF (used to attenuate the input signal in case of to much power) + (3) SIF AGC (used to amplify the output signal in case input to low) + + The SIF AGC is now coupled to the RF/IF AGCs. + The SIF AGC is needed for both SIF ouput and the internal SIF signal to + the AUD block. + + RF and IF AGCs DACs are part of AFE, Video and SIF AGC DACs are part of + the ATV block. The AGC control algorithms are all implemented in + microcode. + + ATV SETTINGS + + (Shadow settings will not be used for now, they will be implemented + later on because of the schedule) + + Several HW/SCU "settings" can be used for ATV. The standard selection + will reset most of these settings. To avoid that the end user apllication + has to perform these settings each time the ATV or FM standards is + selected the driver will shadow these settings. This enables the end user + to perform the settings only once after a DRX_Open(). The driver must + write the shadow settings to HW/SCU incase: + ( setstandard FM/ATV) || + ( settings have changed && FM/ATV standard is active) + The shadow settings will be stored in the device specific data container. + A set of flags will be defined to flag changes in shadow settings. + A routine will be implemented to write all changed shadow settings to + HW/SCU. + + The "settings" will consist of: AGC settings, filter settings etc. + + Disadvantage of use of shadow settings: + Direct changes in HW/SCU registers will not be reflected in the + shadow settings and these changes will be overwritten during a next + update. This can happen during evaluation. This will not be a problem + for normal customer usage. +*/ +/* -------------------------------------------------------------------------- */ + +/** +* \brief Get array index for atv coef (extAttr->atvTopCoefX[index]) +* \param standard +* \param pointer to index +* \return DRXStatus_t. +* +*/ +static DRXStatus_t +AtvEquCoefIndex( DRXStandard_t standard, int *index) +{ + switch(standard) + { + case DRX_STANDARD_PAL_SECAM_BG: + *index=(int)DRXJ_COEF_IDX_BG; + break; + case DRX_STANDARD_PAL_SECAM_DK: + *index=(int)DRXJ_COEF_IDX_DK; + break; + case DRX_STANDARD_PAL_SECAM_I: + *index=(int)DRXJ_COEF_IDX_I; + break; + case DRX_STANDARD_PAL_SECAM_L: + *index=(int)DRXJ_COEF_IDX_L; + break; + case DRX_STANDARD_PAL_SECAM_LP: + *index=(int)DRXJ_COEF_IDX_LP; + break; + case DRX_STANDARD_NTSC: + *index=(int)DRXJ_COEF_IDX_MN; + break; + case DRX_STANDARD_FM: + *index=(int)DRXJ_COEF_IDX_FM; + break; + default: + *index=(int)DRXJ_COEF_IDX_MN; /* still return a valid index */ + return DRX_STS_ERROR; + break; + } + + return DRX_STS_OK; +} + +/* -------------------------------------------------------------------------- */ +/** +* \fn DRXStatus_t AtvUpdateConfig () +* \brief Flush changes in ATV shadow registers to physical registers. +* \param demod instance of demodulator +* \param forceUpdate don't look at standard or change flags, flush all. +* \return DRXStatus_t. +* +*/ +static DRXStatus_t +AtvUpdateConfig( pDRXDemodInstance_t demod, + Bool_t forceUpdate ) +{ + pI2CDeviceAddr_t devAddr = NULL; + pDRXJData_t extAttr = NULL; + + devAddr = demod -> myI2CDevAddr; + extAttr = (pDRXJData_t)demod->myExtAttr; + + /* equalizer coefficients */ + if ( forceUpdate || + ((extAttr->atvCfgChangedFlags & DRXJ_ATV_CHANGED_COEF) != 0) ) + { + int index=0; + + CHK_ERROR(AtvEquCoefIndex( extAttr->standard, &index )); + WR16( devAddr, ATV_TOP_EQU0__A, extAttr->atvTopEqu0[index] ); + WR16( devAddr, ATV_TOP_EQU1__A, extAttr->atvTopEqu1[index] ); + WR16( devAddr, ATV_TOP_EQU2__A, extAttr->atvTopEqu2[index] ); + WR16( devAddr, ATV_TOP_EQU3__A, extAttr->atvTopEqu3[index] ); + } + + /* bypass fast carrier recovery */ + if ( forceUpdate ) + { + u16_t data=0; + + RR16( devAddr, IQM_RT_ROT_BP__A, &data ); + data &= (~((u16_t)IQM_RT_ROT_BP_ROT_OFF__M)); + if (extAttr->phaseCorrectionBypass) + { + data |= IQM_RT_ROT_BP_ROT_OFF_OFF; + } else { + data |= IQM_RT_ROT_BP_ROT_OFF_ACTIVE; + } + WR16( devAddr, IQM_RT_ROT_BP__A, data ); + } + + /* peak filter setting */ + if ( forceUpdate || + ((extAttr->atvCfgChangedFlags & DRXJ_ATV_CHANGED_PEAK_FLT) != 0) ) + { + WR16( devAddr, ATV_TOP_VID_PEAK__A, extAttr->atvTopVidPeak ); + } + + /* noise filter setting */ + if ( forceUpdate || + ((extAttr->atvCfgChangedFlags & DRXJ_ATV_CHANGED_NOISE_FLT) != 0) ) + { + WR16( devAddr, ATV_TOP_NOISE_TH__A, extAttr->atvTopNoiseTh ); + } + + /* SIF attenuation */ + if ( forceUpdate || + ((extAttr->atvCfgChangedFlags & DRXJ_ATV_CHANGED_SIF_ATT) != 0) ) + { + u16_t attenuation=0; + + switch( extAttr->sifAttenuation ){ + case DRXJ_SIF_ATTENUATION_0DB: + attenuation = ATV_TOP_AF_SIF_ATT_0DB; + break; + case DRXJ_SIF_ATTENUATION_3DB: + attenuation = ATV_TOP_AF_SIF_ATT_M3DB; + break; + case DRXJ_SIF_ATTENUATION_6DB: + attenuation = ATV_TOP_AF_SIF_ATT_M6DB; + break; + case DRXJ_SIF_ATTENUATION_9DB: + attenuation = ATV_TOP_AF_SIF_ATT_M9DB; + break; + default: + return DRX_STS_ERROR; + break; + } + WR16( devAddr, ATV_TOP_AF_SIF_ATT__A, attenuation ); + } + + /* SIF & CVBS enable */ + if ( forceUpdate || + ((extAttr->atvCfgChangedFlags & DRXJ_ATV_CHANGED_OUTPUT) != 0) ) + { + u16_t data = 0; + + RR16( devAddr, ATV_TOP_STDBY__A, &data ); + if ( extAttr->enableCVBSOutput ) + { + data |=ATV_TOP_STDBY_CVBS_STDBY_A2_ACTIVE; + } else { + data &= (~ATV_TOP_STDBY_CVBS_STDBY_A2_ACTIVE); + } + + if ( extAttr->enableSIFOutput ) + { + data &= (~ATV_TOP_STDBY_SIF_STDBY_STANDBY); + } else { + data |= ATV_TOP_STDBY_SIF_STDBY_STANDBY; + } + WR16( devAddr, ATV_TOP_STDBY__A, data ); + } + + extAttr->atvCfgChangedFlags = 0; + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} + +/* -------------------------------------------------------------------------- */ +/** +* \fn DRXStatus_t CtrlSetCfgATVOutput() +* \brief Configure ATV ouputs +* \param demod instance of demodulator +* \param outputCfg output configuaration +* \return DRXStatus_t. +* +*/ +static DRXStatus_t +CtrlSetCfgATVOutput( pDRXDemodInstance_t demod, + pDRXJCfgAtvOutput_t outputCfg ) +{ + pDRXJData_t extAttr = NULL; + + /* Check arguments */ + if ( outputCfg == NULL ) + { + return (DRX_STS_INVALID_ARG); + } + + extAttr = (pDRXJData_t)demod->myExtAttr; + if ( outputCfg->enableSIFOutput ) + { + switch( outputCfg->sifAttenuation ){ + case DRXJ_SIF_ATTENUATION_0DB: /* fallthrough */ + case DRXJ_SIF_ATTENUATION_3DB: /* fallthrough */ + case DRXJ_SIF_ATTENUATION_6DB: /* fallthrough */ + case DRXJ_SIF_ATTENUATION_9DB: + /* Do nothing */ + break; + default: + return DRX_STS_INVALID_ARG; + break; + } + + if(extAttr->sifAttenuation != outputCfg->sifAttenuation ) + { + extAttr->sifAttenuation = outputCfg->sifAttenuation; + extAttr->atvCfgChangedFlags |= DRXJ_ATV_CHANGED_SIF_ATT; + } + } + + if ( extAttr->enableCVBSOutput != outputCfg->enableCVBSOutput ) + { + extAttr->enableCVBSOutput = outputCfg->enableCVBSOutput; + extAttr->atvCfgChangedFlags |= DRXJ_ATV_CHANGED_OUTPUT; + } + + if ( extAttr->enableSIFOutput != outputCfg->enableSIFOutput ) + { + extAttr->enableSIFOutput = outputCfg->enableSIFOutput; + extAttr->atvCfgChangedFlags |= DRXJ_ATV_CHANGED_OUTPUT; + } + + CHK_ERROR( AtvUpdateConfig(demod, FALSE) ); + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} + +/* -------------------------------------------------------------------------- */ +#ifndef DRXJ_DIGITAL_ONLY +/** +* \fn DRXStatus_t CtrlSetCfgAtvEquCoef() +* \brief Set ATV equalizer coefficients +* \param demod instance of demodulator +* \param coef the equalizer coefficients +* \return DRXStatus_t. +* +*/ +static DRXStatus_t +CtrlSetCfgAtvEquCoef( pDRXDemodInstance_t demod , + pDRXJCfgAtvEquCoef_t coef) +{ + pDRXJData_t extAttr = NULL; + int index; + + extAttr = (pDRXJData_t)demod->myExtAttr; + + /* current standard needs to be an ATV standard */ + if (!DRXJ_ISATVSTD(extAttr->standard )) + { + return DRX_STS_ERROR; + } + + /* Check arguments */ + if ( ( coef == NULL ) || + ( coef->coef0 > (ATV_TOP_EQU0_EQU_C0__M / 2) ) || + ( coef->coef1 > (ATV_TOP_EQU1_EQU_C1__M / 2) ) || + ( coef->coef2 > (ATV_TOP_EQU2_EQU_C2__M / 2) ) || + ( coef->coef3 > (ATV_TOP_EQU3_EQU_C3__M / 2) ) || + ( coef->coef0 < ((s16_t)~(ATV_TOP_EQU0_EQU_C0__M >> 1)) ) || + ( coef->coef1 < ((s16_t)~(ATV_TOP_EQU1_EQU_C1__M >> 1)) ) || + ( coef->coef2 < ((s16_t)~(ATV_TOP_EQU2_EQU_C2__M >> 1)) ) || + ( coef->coef3 < ((s16_t)~(ATV_TOP_EQU3_EQU_C3__M >> 1)) ) ) + { + return (DRX_STS_INVALID_ARG); + } + + CHK_ERROR(AtvEquCoefIndex( extAttr->standard, &index )); + extAttr->atvTopEqu0[index] = coef->coef0; + extAttr->atvTopEqu1[index] = coef->coef1; + extAttr->atvTopEqu2[index] = coef->coef2; + extAttr->atvTopEqu3[index] = coef->coef3; + extAttr->atvCfgChangedFlags |= DRXJ_ATV_CHANGED_COEF; + + CHK_ERROR( AtvUpdateConfig(demod, FALSE) ); + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} + +/* -------------------------------------------------------------------------- */ +/** +* \fn DRXStatus_t CtrlGetCfgAtvEquCoef() +* \brief Get ATV equ coef settings +* \param demod instance of demodulator +* \param coef The ATV equ coefficients +* \return DRXStatus_t. +* +* The values are read from the shadow registers maintained by the drxdriver +* If registers are manipulated outside of the drxdriver scope the reported +* settings will not reflect these changes because of the use of shadow +* regitsers. +* +*/ +static DRXStatus_t +CtrlGetCfgAtvEquCoef( pDRXDemodInstance_t demod , + pDRXJCfgAtvEquCoef_t coef) +{ + pDRXJData_t extAttr = NULL; + int index=0; + + extAttr = (pDRXJData_t)demod->myExtAttr; + + /* current standard needs to be an ATV standard */ + if (!DRXJ_ISATVSTD(extAttr->standard )) + { + return DRX_STS_ERROR; + } + + /* Check arguments */ + if ( coef == NULL ) + { + return DRX_STS_INVALID_ARG; + } + + CHK_ERROR(AtvEquCoefIndex( extAttr->standard, &index )); + coef->coef0 = extAttr->atvTopEqu0[index]; + coef->coef1 = extAttr->atvTopEqu1[index]; + coef->coef2 = extAttr->atvTopEqu2[index]; + coef->coef3 = extAttr->atvTopEqu3[index]; + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} + +/* -------------------------------------------------------------------------- */ +/** +* \fn DRXStatus_t CtrlSetCfgAtvMisc() +* \brief Set misc. settings for ATV. +* \param demod instance of demodulator +* \param +* \return DRXStatus_t. +* +*/ +static DRXStatus_t +CtrlSetCfgAtvMisc( pDRXDemodInstance_t demod , + pDRXJCfgAtvMisc_t settings ) +{ + pDRXJData_t extAttr = NULL; + + /* Check arguments */ + if ( ( settings == NULL ) || + ((settings->peakFilter) < (s16_t)(-8) ) || + ((settings->peakFilter) > (s16_t)(15) ) || + ((settings->noiseFilter) > 15 ) ) + { + return (DRX_STS_INVALID_ARG); + } /* if */ + + extAttr = (pDRXJData_t)demod->myExtAttr; + + if ( settings->peakFilter != extAttr->atvTopVidPeak ) + { + extAttr->atvTopVidPeak = settings->peakFilter; + extAttr->atvCfgChangedFlags |= DRXJ_ATV_CHANGED_PEAK_FLT; + } + + if ( settings->noiseFilter != extAttr->atvTopNoiseTh ) + { + extAttr->atvTopNoiseTh = settings->noiseFilter; + extAttr->atvCfgChangedFlags |= DRXJ_ATV_CHANGED_NOISE_FLT; + } + + CHK_ERROR( AtvUpdateConfig(demod, FALSE) ); + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} + +/* -------------------------------------------------------------------------- */ +/** +* \fn DRXStatus_t CtrlGetCfgAtvMisc() +* \brief Get misc settings of ATV. +* \param demod instance of demodulator +* \param settings misc. ATV settings +* \return DRXStatus_t. +* +* The values are read from the shadow registers maintained by the drxdriver +* If registers are manipulated outside of the drxdriver scope the reported +* settings will not reflect these changes because of the use of shadow +* regitsers. +*/ +static DRXStatus_t +CtrlGetCfgAtvMisc( pDRXDemodInstance_t demod , + pDRXJCfgAtvMisc_t settings ) +{ + pDRXJData_t extAttr = NULL; + + /* Check arguments */ + if ( settings == NULL ) + { + return DRX_STS_INVALID_ARG; + } + + extAttr = (pDRXJData_t)demod->myExtAttr; + + settings->peakFilter = extAttr->atvTopVidPeak ; + settings->noiseFilter = extAttr->atvTopNoiseTh ; + + return (DRX_STS_OK); +} + +/* -------------------------------------------------------------------------- */ + +/* -------------------------------------------------------------------------- */ +/** +* \fn DRXStatus_t CtrlGetCfgAtvOutput() +* \brief +* \param demod instance of demodulator +* \param outputCfg output configuaration +* \return DRXStatus_t. +* +*/ +static DRXStatus_t +CtrlGetCfgAtvOutput( pDRXDemodInstance_t demod , + pDRXJCfgAtvOutput_t outputCfg ) +{ + u16_t data = 0; + + /* Check arguments */ + if ( outputCfg == NULL ) + { + return DRX_STS_INVALID_ARG; + } + + RR16( demod->myI2CDevAddr, ATV_TOP_STDBY__A, &data ); + if ( data & ATV_TOP_STDBY_CVBS_STDBY_A2_ACTIVE ) + { + outputCfg->enableCVBSOutput = TRUE; + } else { + outputCfg->enableCVBSOutput = FALSE; + } + + if ( data & ATV_TOP_STDBY_SIF_STDBY_STANDBY ) + { + outputCfg->enableSIFOutput = FALSE; + } else { + outputCfg->enableSIFOutput = TRUE; + RR16( demod->myI2CDevAddr, ATV_TOP_AF_SIF_ATT__A, &data ); + outputCfg->sifAttenuation = (DRXJSIFAttenuation_t) data; + } + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} + +/* -------------------------------------------------------------------------- */ +/** +* \fn DRXStatus_t CtrlGetCfgAtvAgcStatus() +* \brief +* \param demod instance of demodulator +* \param agcStatus agc status +* \return DRXStatus_t. +* +*/ +static DRXStatus_t +CtrlGetCfgAtvAgcStatus( pDRXDemodInstance_t demod , + pDRXJCfgAtvAgcStatus_t agcStatus ) +{ + pI2CDeviceAddr_t devAddr = NULL; + pDRXJData_t extAttr = NULL; + u16_t data = 0; + u32_t tmp = 0; + + /* Check arguments */ + if ( agcStatus == NULL ) + { + return DRX_STS_INVALID_ARG; + } + + devAddr = demod -> myI2CDevAddr; + extAttr = (pDRXJData_t)demod->myExtAttr; + + /* + RFgain = (IQM_AF_AGC_RF__A * 26.75)/1000 (uA) + = ((IQM_AF_AGC_RF__A * 27) - (0.25*IQM_AF_AGC_RF__A))/1000 + + IQM_AF_AGC_RF__A * 27 is 20 bits worst case. + */ + RR16( devAddr, IQM_AF_AGC_RF__A, &data ); + tmp = ((u32_t)data) * 27 - ((u32_t)(data>>2)); /* nA */ + agcStatus->rfAgcGain = (u16_t)(tmp/1000) ; /* uA */ + /* rounding */ + if ( tmp%1000 >= 500 ) + { + (agcStatus->rfAgcGain)++; + } + + /* + IFgain = (IQM_AF_AGC_IF__A * 26.75)/1000 (uA) + = ((IQM_AF_AGC_IF__A * 27) - (0.25*IQM_AF_AGC_IF__A))/1000 + + IQM_AF_AGC_IF__A * 27 is 20 bits worst case. + */ + RR16( devAddr, IQM_AF_AGC_IF__A, &data ); + tmp = ((u32_t)data) * 27 - ((u32_t)(data>>2)); /* nA */ + agcStatus->ifAgcGain = (u16_t)(tmp/1000) ; /* uA */ + /* rounding */ + if ( tmp%1000 >= 500 ) + { + (agcStatus->ifAgcGain)++; + } + + /* + videoGain = (ATV_TOP_SFR_VID_GAIN__A/16 -150)* 0.05 (dB) + = (ATV_TOP_SFR_VID_GAIN__A/16 -150)/20 (dB) + = 10*(ATV_TOP_SFR_VID_GAIN__A/16 -150)/20 (in 0.1 dB) + = (ATV_TOP_SFR_VID_GAIN__A/16 -150)/2 (in 0.1 dB) + = (ATV_TOP_SFR_VID_GAIN__A/32) - 75 (in 0.1 dB) + */ + + SARR16( devAddr, SCU_RAM_ATV_VID_GAIN_HI__A , &data ); + /* dividing by 32 inclusive rounding */ + data >>=4; + if ((data & 1) !=0 ) + { + data++; + } + data >>= 1; + agcStatus->videoAgcGain = ((s16_t)data)-75; /* 0.1 dB */ + + /* + audioGain = (SCU_RAM_ATV_SIF_GAIN__A -8)* 0.05 (dB) + = (SCU_RAM_ATV_SIF_GAIN__A -8)/20 (dB) + = 10*(SCU_RAM_ATV_SIF_GAIN__A -8)/20 (in 0.1 dB) + = (SCU_RAM_ATV_SIF_GAIN__A -8)/2 (in 0.1 dB) + = (SCU_RAM_ATV_SIF_GAIN__A/2) - 4 (in 0.1 dB) + */ + + SARR16( devAddr, SCU_RAM_ATV_SIF_GAIN__A, &data ); + data &= SCU_RAM_ATV_SIF_GAIN__M; + /* dividing by 2 inclusive rounding */ + if ((data & 1) !=0 ) + { + data++; + } + data >>= 1; + agcStatus->audioAgcGain = ((s16_t)data)-4; /* 0.1 dB */ + + /* Loop gain's */ + SARR16( devAddr, SCU_RAM_AGC_KI__A, &data ); + agcStatus->videoAgcLoopGain = + ( (data & SCU_RAM_AGC_KI_DGAIN__M)>>SCU_RAM_AGC_KI_DGAIN__B) ; + agcStatus->rfAgcLoopGain = + ( (data & SCU_RAM_AGC_KI_RF__M)>>SCU_RAM_AGC_KI_RF__B) ; + agcStatus->ifAgcLoopGain = + ( (data & SCU_RAM_AGC_KI_IF__M)>>SCU_RAM_AGC_KI_IF__B) ; + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} + +/* -------------------------------------------------------------------------- */ + +/** +* \fn DRXStatus_t PowerUpATV () +* \brief Power up ATV. +* \param demod instance of demodulator +* \param standard either NTSC or FM (sub strandard for ATV ) +* \return DRXStatus_t. +* +* * Starts ATV and IQM +* * AUdio already started during standard init for ATV. +*/ +static DRXStatus_t +PowerUpATV( pDRXDemodInstance_t demod , DRXStandard_t standard ) +{ + pI2CDeviceAddr_t devAddr = NULL; + pDRXJData_t extAttr = NULL; + + + devAddr = demod -> myI2CDevAddr; + extAttr = (pDRXJData_t)demod->myExtAttr; + + /* ATV NTSC */ + WR16( devAddr, ATV_COMM_EXEC__A, ATV_COMM_EXEC_ACTIVE ); + /* turn on IQM_AF */ + CHK_ERROR( SetIqmAf( demod, TRUE ) ); + CHK_ERROR(ADCSynchronization (demod)); + + WR16( devAddr, IQM_COMM_EXEC__A, IQM_COMM_EXEC_ACTIVE ); + + /* Audio, already done during set standard */ + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} +#endif /* #ifndef DRXJ_DIGITAL_ONLY */ + +/* -------------------------------------------------------------------------- */ + +/** +* \fn DRXStatus_t PowerDownATV () +* \brief Power down ATV. +* \param demod instance of demodulator +* \param standard either NTSC or FM (sub strandard for ATV ) +* \return DRXStatus_t. +* +* Stops and thus resets ATV and IQM block +* SIF and CVBS ADC are powered down +* Calls audio power down +*/ +static DRXStatus_t +PowerDownATV( pDRXDemodInstance_t demod , DRXStandard_t standard, Bool_t primary ) +{ + pI2CDeviceAddr_t devAddr = NULL; + DRXJSCUCmd_t cmdSCU = { /* command */ 0, + /* parameterLen */ 0, + /* resultLen */ 0, + /* *parameter */ NULL, + /* *result */ NULL }; + u16_t cmdResult = 0; + pDRXJData_t extAttr = NULL; + + devAddr = demod -> myI2CDevAddr; + extAttr = (pDRXJData_t) demod->myExtAttr; + /* ATV NTSC */ + + /* Stop ATV SCU (will reset ATV and IQM hardware */ + cmdSCU.command = SCU_RAM_COMMAND_STANDARD_ATV | + SCU_RAM_COMMAND_CMD_DEMOD_STOP; + cmdSCU.parameterLen = 0; + cmdSCU.resultLen = 1; + cmdSCU.parameter = NULL; + cmdSCU.result = &cmdResult; + CHK_ERROR( SCUCommand( devAddr, &cmdSCU ) ); + /* Disable ATV outputs (ATV reset enables CVBS, undo this) */ + WR16 ( devAddr, ATV_TOP_STDBY__A, ( ATV_TOP_STDBY_SIF_STDBY_STANDBY & + (~ATV_TOP_STDBY_CVBS_STDBY_A2_ACTIVE) ) ); + + WR16( devAddr, ATV_COMM_EXEC__A, ATV_COMM_EXEC_STOP); + if (primary == TRUE) + { + WR16( devAddr, IQM_COMM_EXEC__A, IQM_COMM_EXEC_STOP ); + CHK_ERROR( SetIqmAf( demod, FALSE ) ); + } + else + { + WR16( devAddr, IQM_FS_COMM_EXEC__A, IQM_FS_COMM_EXEC_STOP ); + WR16( devAddr, IQM_FD_COMM_EXEC__A, IQM_FD_COMM_EXEC_STOP ); + WR16( devAddr, IQM_RC_COMM_EXEC__A, IQM_RC_COMM_EXEC_STOP ); + WR16( devAddr, IQM_RT_COMM_EXEC__A, IQM_RT_COMM_EXEC_STOP ); + WR16( devAddr, IQM_CF_COMM_EXEC__A, IQM_CF_COMM_EXEC_STOP ); + } + CHK_ERROR( PowerDownAud(demod) ); + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} + +/* -------------------------------------------------------------------------- */ +/** +* \fn DRXStatus_t SetATVStandard () +* \brief Set up ATV demodulator. +* \param demod instance of demodulator +* \param standard either NTSC or FM (sub strandard for ATV ) +* \return DRXStatus_t. +* +* Init all channel independent registers. +* Assuming that IQM, ATV and AUD blocks have been reset and are in STOP mode +* +*/ +#ifndef DRXJ_DIGITAL_ONLY +#define SCU_RAM_ATV_ENABLE_IIR_WA__A 0x831F6D /* TODO remove after done with reg import */ +static DRXStatus_t +SetATVStandard( pDRXDemodInstance_t demod , pDRXStandard_t standard ) +{ +/* TODO: enable alternative for tap settings via external file + +something like: +#ifdef DRXJ_ATV_COEF_FILE +#include DRXJ_ATV_COEF_FILE +#else +... code defining fixed coef's ... +#endif + +Cutsomer must create file "customer_coefs.c.inc" containing +modified copy off the constants below, and define the compiler +switch DRXJ_ATV_COEF_FILE="customer_coefs.c.inc". + +Still to check if this will work; DRXJ_16TO8 macro may cause +trouble ? +*/ + const u8_t ntsc_taps_re[]= { + DRXJ_16TO8(-12 ), /* re0 */ + DRXJ_16TO8(-9 ), /* re1 */ + DRXJ_16TO8( 9 ), /* re2 */ + DRXJ_16TO8( 19 ), /* re3 */ + DRXJ_16TO8(-4 ), /* re4 */ + DRXJ_16TO8(-24 ), /* re5 */ + DRXJ_16TO8(-6 ), /* re6 */ + DRXJ_16TO8( 16 ), /* re7 */ + DRXJ_16TO8( 6 ), /* re8 */ + DRXJ_16TO8(-16 ), /* re9 */ + DRXJ_16TO8(-5 ), /* re10 */ + DRXJ_16TO8( 13 ), /* re11 */ + DRXJ_16TO8(-2 ), /* re12 */ + DRXJ_16TO8(-20 ), /* re13 */ + DRXJ_16TO8( 4 ), /* re14 */ + DRXJ_16TO8( 25 ), /* re15 */ + DRXJ_16TO8(-6 ), /* re16 */ + DRXJ_16TO8(-36 ), /* re17 */ + DRXJ_16TO8( 2 ), /* re18 */ + DRXJ_16TO8( 38 ), /* re19 */ + DRXJ_16TO8(-10 ), /* re20 */ + DRXJ_16TO8(-48 ), /* re21 */ + DRXJ_16TO8( 35 ), /* re22 */ + DRXJ_16TO8( 94 ), /* re23 */ + DRXJ_16TO8(-59 ), /* re24 */ + DRXJ_16TO8(-217 ), /* re25 */ + DRXJ_16TO8( 50 ), /* re26 */ + DRXJ_16TO8( 679 ) /* re27 */ + }; + const u8_t ntsc_taps_im[]= { + DRXJ_16TO8( 11 ), /* im0 */ + DRXJ_16TO8( 1 ), /* im1 */ + DRXJ_16TO8(-10 ), /* im2 */ + DRXJ_16TO8( 2 ), /* im3 */ + DRXJ_16TO8( 24 ), /* im4 */ + DRXJ_16TO8( 21 ), /* im5 */ + DRXJ_16TO8( 1 ), /* im6 */ + DRXJ_16TO8(-4 ), /* im7 */ + DRXJ_16TO8( 7 ), /* im8 */ + DRXJ_16TO8( 14 ), /* im9 */ + DRXJ_16TO8( 27 ), /* im10 */ + DRXJ_16TO8( 42 ), /* im11 */ + DRXJ_16TO8( 22 ), /* im12 */ + DRXJ_16TO8(-20 ), /* im13 */ + DRXJ_16TO8( 2 ), /* im14 */ + DRXJ_16TO8( 98 ), /* im15 */ + DRXJ_16TO8( 122 ), /* im16 */ + DRXJ_16TO8( 0 ), /* im17 */ + DRXJ_16TO8(-85 ), /* im18 */ + DRXJ_16TO8( 51 ), /* im19 */ + DRXJ_16TO8( 247 ), /* im20 */ + DRXJ_16TO8( 192 ), /* im21 */ + DRXJ_16TO8(-55 ), /* im22 */ + DRXJ_16TO8(-95 ), /* im23 */ + DRXJ_16TO8( 217 ), /* im24 */ + DRXJ_16TO8( 544 ), /* im25 */ + DRXJ_16TO8( 553 ), /* im26 */ + DRXJ_16TO8( 302 ) /* im27 */ + }; + const u8_t bg_taps_re[]= { + DRXJ_16TO8(-18 ), /* re0 */ + DRXJ_16TO8( 18 ), /* re1 */ + DRXJ_16TO8( 19 ), /* re2 */ + DRXJ_16TO8(-26 ), /* re3 */ + DRXJ_16TO8(-20 ), /* re4 */ + DRXJ_16TO8( 36 ), /* re5 */ + DRXJ_16TO8( 5 ), /* re6 */ + DRXJ_16TO8(-51 ), /* re7 */ + DRXJ_16TO8( 15 ), /* re8 */ + DRXJ_16TO8( 45 ), /* re9 */ + DRXJ_16TO8(-46 ), /* re10 */ + DRXJ_16TO8(-24 ), /* re11 */ + DRXJ_16TO8( 71 ), /* re12 */ + DRXJ_16TO8(-17 ), /* re13 */ + DRXJ_16TO8(-83 ), /* re14 */ + DRXJ_16TO8( 74 ), /* re15 */ + DRXJ_16TO8( 75 ), /* re16 */ + DRXJ_16TO8(-134 ), /* re17 */ + DRXJ_16TO8(-40 ), /* re18 */ + DRXJ_16TO8( 191 ), /* re19 */ + DRXJ_16TO8(-11 ), /* re20 */ + DRXJ_16TO8(-233 ), /* re21 */ + DRXJ_16TO8( 74 ), /* re22 */ + DRXJ_16TO8( 271 ), /* re23 */ + DRXJ_16TO8(-132 ), /* re24 */ + DRXJ_16TO8(-341 ), /* re25 */ + DRXJ_16TO8( 172 ), /* re26 */ + DRXJ_16TO8( 801 ) /* re27 */ + }; + const u8_t bg_taps_im[]= { + DRXJ_16TO8(-24 ), /* im0 */ + DRXJ_16TO8(-10 ), /* im1 */ + DRXJ_16TO8( 9 ), /* im2 */ + DRXJ_16TO8(-5 ), /* im3 */ + DRXJ_16TO8(-51 ), /* im4 */ + DRXJ_16TO8(-17 ), /* im5 */ + DRXJ_16TO8( 31 ), /* im6 */ + DRXJ_16TO8(-48 ), /* im7 */ + DRXJ_16TO8(-95 ), /* im8 */ + DRXJ_16TO8( 25 ), /* im9 */ + DRXJ_16TO8( 37 ), /* im10 */ + DRXJ_16TO8(-123 ), /* im11 */ + DRXJ_16TO8(-77 ), /* im12 */ + DRXJ_16TO8( 94 ), /* im13 */ + DRXJ_16TO8(-10 ), /* im14 */ + DRXJ_16TO8(-149 ), /* im15 */ + DRXJ_16TO8( 10 ), /* im16 */ + DRXJ_16TO8( 108 ), /* im17 */ + DRXJ_16TO8(-49 ), /* im18 */ + DRXJ_16TO8(-59 ), /* im19 */ + DRXJ_16TO8( 90 ), /* im20 */ + DRXJ_16TO8( 73 ), /* im21 */ + DRXJ_16TO8( 55 ), /* im22 */ + DRXJ_16TO8( 148 ), /* im23 */ + DRXJ_16TO8( 86 ), /* im24 */ + DRXJ_16TO8( 146 ), /* im25 */ + DRXJ_16TO8( 687 ), /* im26 */ + DRXJ_16TO8( 877 ) /* im27 */ + }; + const u8_t dk_i_l_lp_taps_re[]= { + DRXJ_16TO8(-23 ), /* re0 */ + DRXJ_16TO8( 9 ), /* re1 */ + DRXJ_16TO8( 16 ), /* re2 */ + DRXJ_16TO8(-26 ), /* re3 */ + DRXJ_16TO8(-3 ), /* re4 */ + DRXJ_16TO8( 13 ), /* re5 */ + DRXJ_16TO8(-19 ), /* re6 */ + DRXJ_16TO8(-3 ), /* re7 */ + DRXJ_16TO8( 13 ), /* re8 */ + DRXJ_16TO8(-26 ), /* re9 */ + DRXJ_16TO8(-4 ), /* re10 */ + DRXJ_16TO8( 28 ), /* re11 */ + DRXJ_16TO8(-15 ), /* re12 */ + DRXJ_16TO8(-14 ), /* re13 */ + DRXJ_16TO8( 10 ), /* re14 */ + DRXJ_16TO8( 1 ), /* re15 */ + DRXJ_16TO8( 39 ), /* re16 */ + DRXJ_16TO8(-18 ), /* re17 */ + DRXJ_16TO8(-90 ), /* re18 */ + DRXJ_16TO8( 109 ), /* re19 */ + DRXJ_16TO8( 113 ), /* re20 */ + DRXJ_16TO8(-235 ), /* re21 */ + DRXJ_16TO8(-49 ), /* re22 */ + DRXJ_16TO8( 359 ), /* re23 */ + DRXJ_16TO8(-79 ), /* re24 */ + DRXJ_16TO8(-459 ), /* re25 */ + DRXJ_16TO8( 206 ), /* re26 */ + DRXJ_16TO8( 894 ) /* re27 */ + }; + const u8_t dk_i_l_lp_taps_im[]= { + DRXJ_16TO8(-8 ), /* im0 */ + DRXJ_16TO8(-20 ), /* im1 */ + DRXJ_16TO8( 17 ), /* im2 */ + DRXJ_16TO8(-14 ), /* im3 */ + DRXJ_16TO8(-52 ), /* im4 */ + DRXJ_16TO8( 4 ), /* im5 */ + DRXJ_16TO8( 9 ), /* im6 */ + DRXJ_16TO8(-62 ), /* im7 */ + DRXJ_16TO8(-47 ), /* im8 */ + DRXJ_16TO8( 0 ), /* im9 */ + DRXJ_16TO8(-20 ), /* im10 */ + DRXJ_16TO8(-48 ), /* im11 */ + DRXJ_16TO8(-65 ), /* im12 */ + DRXJ_16TO8(-23 ), /* im13 */ + DRXJ_16TO8( 44 ), /* im14 */ + DRXJ_16TO8(-60 ), /* im15 */ + DRXJ_16TO8(-113 ), /* im16 */ + DRXJ_16TO8( 92 ), /* im17 */ + DRXJ_16TO8( 81 ), /* im18 */ + DRXJ_16TO8(-125 ), /* im19 */ + DRXJ_16TO8( 28 ), /* im20 */ + DRXJ_16TO8( 182 ), /* im21 */ + DRXJ_16TO8( 35 ), /* im22 */ + DRXJ_16TO8( 94 ), /* im23 */ + DRXJ_16TO8( 180 ), /* im24 */ + DRXJ_16TO8( 134 ), /* im25 */ + DRXJ_16TO8( 657 ), /* im26 */ + DRXJ_16TO8( 1023 ) /* im27 */ + }; + const u8_t fm_taps_re[]= { + DRXJ_16TO8( 0 ), /* re0 */ + DRXJ_16TO8( 0 ), /* re1 */ + DRXJ_16TO8( 0 ), /* re2 */ + DRXJ_16TO8( 0 ), /* re3 */ + DRXJ_16TO8( 0 ), /* re4 */ + DRXJ_16TO8( 0 ), /* re5 */ + DRXJ_16TO8( 0 ), /* re6 */ + DRXJ_16TO8( 0 ), /* re7 */ + DRXJ_16TO8( 0 ), /* re8 */ + DRXJ_16TO8( 0 ), /* re9 */ + DRXJ_16TO8( 0 ), /* re10 */ + DRXJ_16TO8( 0 ), /* re11 */ + DRXJ_16TO8( 0 ), /* re12 */ + DRXJ_16TO8( 0 ), /* re13 */ + DRXJ_16TO8( 0 ), /* re14 */ + DRXJ_16TO8( 0 ), /* re15 */ + DRXJ_16TO8( 0 ), /* re16 */ + DRXJ_16TO8( 0 ), /* re17 */ + DRXJ_16TO8( 0 ), /* re18 */ + DRXJ_16TO8( 0 ), /* re19 */ + DRXJ_16TO8( 0 ), /* re20 */ + DRXJ_16TO8( 0 ), /* re21 */ + DRXJ_16TO8( 0 ), /* re22 */ + DRXJ_16TO8( 0 ), /* re23 */ + DRXJ_16TO8( 0 ), /* re24 */ + DRXJ_16TO8( 0 ), /* re25 */ + DRXJ_16TO8( 0 ), /* re26 */ + DRXJ_16TO8( 0 ) /* re27 */ + }; + const u8_t fm_taps_im[]= { + DRXJ_16TO8(-6 ), /* im0 */ + DRXJ_16TO8( 2 ), /* im1 */ + DRXJ_16TO8( 14 ), /* im2 */ + DRXJ_16TO8(-38 ), /* im3 */ + DRXJ_16TO8( 58 ), /* im4 */ + DRXJ_16TO8(-62 ), /* im5 */ + DRXJ_16TO8( 42 ), /* im6 */ + DRXJ_16TO8( 0 ), /* im7 */ + DRXJ_16TO8(-45 ), /* im8 */ + DRXJ_16TO8( 73 ), /* im9 */ + DRXJ_16TO8(-65 ), /* im10 */ + DRXJ_16TO8( 23 ), /* im11 */ + DRXJ_16TO8( 34 ), /* im12 */ + DRXJ_16TO8(-77 ), /* im13 */ + DRXJ_16TO8( 80 ), /* im14 */ + DRXJ_16TO8(-39 ), /* im15 */ + DRXJ_16TO8(-25 ), /* im16 */ + DRXJ_16TO8( 78 ), /* im17 */ + DRXJ_16TO8(-90 ), /* im18 */ + DRXJ_16TO8( 52 ), /* im19 */ + DRXJ_16TO8( 16 ), /* im20 */ + DRXJ_16TO8(-77 ), /* im21 */ + DRXJ_16TO8( 97 ), /* im22 */ + DRXJ_16TO8(-62 ), /* im23 */ + DRXJ_16TO8(-8 ), /* im24 */ + DRXJ_16TO8( 75 ), /* im25 */ + DRXJ_16TO8(-100 ), /* im26 */ + DRXJ_16TO8( 70 ) /* im27 */ + }; + + pI2CDeviceAddr_t devAddr = NULL; + DRXJSCUCmd_t cmdSCU = { /* command */ 0, + /* parameterLen */ 0, + /* resultLen */ 0, + /* *parameter */ NULL, + /* *result */ NULL }; + u16_t cmdResult = 0; + u16_t cmdParam = 0; +#ifdef DRXJ_SPLIT_UCODE_UPLOAD + DRXUCodeInfo_t ucodeInfo; + pDRXCommonAttr_t commonAttr = NULL; +#endif /* DRXJ_SPLIT_UCODE_UPLOAD */ + pDRXJData_t extAttr = NULL; + + extAttr = (pDRXJData_t)demod->myExtAttr; + devAddr = demod -> myI2CDevAddr; + +#ifdef DRXJ_SPLIT_UCODE_UPLOAD + commonAttr = demod -> myCommonAttr; + + /* Check if audio microcode is already uploaded */ + if ( !( extAttr->flagAudMcUploaded ) ) + { + ucodeInfo.mcData = commonAttr->microcode; + ucodeInfo.mcSize = commonAttr->microcodeSize; + + /* Upload only audio microcode */ + CHK_ERROR ( CtrlUCodeUpload( demod, &ucodeInfo, UCODE_UPLOAD, TRUE ) ); + + if ( commonAttr->verifyMicrocode == TRUE ) + { + CHK_ERROR( CtrlUCodeUpload( demod, &ucodeInfo, UCODE_VERIFY, TRUE ) ); + } + + /* Prevent uploading audio microcode again */ + extAttr->flagAudMcUploaded = TRUE; + } +#endif /* DRXJ_SPLIT_UCODE_UPLOAD */ + + WR16( devAddr, ATV_COMM_EXEC__A, ATV_COMM_EXEC_STOP ); + WR16( devAddr, IQM_FS_COMM_EXEC__A, IQM_FS_COMM_EXEC_STOP ); + WR16( devAddr, IQM_FD_COMM_EXEC__A, IQM_FD_COMM_EXEC_STOP ); + WR16( devAddr, IQM_RC_COMM_EXEC__A, IQM_RC_COMM_EXEC_STOP ); + WR16( devAddr, IQM_RT_COMM_EXEC__A, IQM_RT_COMM_EXEC_STOP ); + WR16( devAddr, IQM_CF_COMM_EXEC__A, IQM_CF_COMM_EXEC_STOP ); + /* Reset ATV SCU */ + cmdSCU.command = SCU_RAM_COMMAND_STANDARD_ATV | + SCU_RAM_COMMAND_CMD_DEMOD_RESET; + cmdSCU.parameterLen = 0; + cmdSCU.resultLen = 1; + cmdSCU.parameter = NULL; + cmdSCU.result = &cmdResult; + CHK_ERROR( SCUCommand( devAddr, &cmdSCU ) ); + + WR16( devAddr, ATV_TOP_MOD_CONTROL__A, ATV_TOP_MOD_CONTROL__PRE ); + + /* TODO remove AUTO/OFF patches after ucode fix. */ + switch ( *standard ) + { + case DRX_STANDARD_NTSC: + /* NTSC */ + cmdParam = SCU_RAM_ATV_STANDARD_STANDARD_MN; + + WR16( devAddr, IQM_RT_LO_INCR__A , IQM_RT_LO_INCR_MN ); + WR16( devAddr, IQM_CF_MIDTAP__A , IQM_CF_MIDTAP_RE__M ); + WRB ( devAddr, IQM_CF_TAP_RE0__A , sizeof(ntsc_taps_re) , + ((pu8_t)ntsc_taps_re) ); + WRB ( devAddr, IQM_CF_TAP_IM0__A , sizeof(ntsc_taps_im) , + ((pu8_t)ntsc_taps_im) ); + + WR16( devAddr, ATV_TOP_CR_AMP_TH__A , ATV_TOP_CR_AMP_TH_MN ); + WR16( devAddr, ATV_TOP_CR_CONT__A , + ( ATV_TOP_CR_CONT_CR_P_MN | + ATV_TOP_CR_CONT_CR_D_MN | + ATV_TOP_CR_CONT_CR_I_MN ) ); + WR16( devAddr, ATV_TOP_CR_OVM_TH__A , ATV_TOP_CR_OVM_TH_MN ); + WR16( devAddr, ATV_TOP_STD__A , (ATV_TOP_STD_MODE_MN | + ATV_TOP_STD_VID_POL_MN ) ); + WR16( devAddr, ATV_TOP_VID_AMP__A , ATV_TOP_VID_AMP_MN ); + + WR16( devAddr, SCU_RAM_ATV_AGC_MODE__A, + ( SCU_RAM_ATV_AGC_MODE_SIF_STD_SIF_AGC_FM | + SCU_RAM_ATV_AGC_MODE_FAST_VAGC_EN_FAGC_ENABLE ) ); + WR16( devAddr, SCU_RAM_ATV_VID_GAIN_HI__A, 0x1000 ); + WR16( devAddr, SCU_RAM_ATV_VID_GAIN_LO__A, 0x0000 ); + WR16( devAddr, SCU_RAM_ATV_AMS_MAX_REF__A, + SCU_RAM_ATV_AMS_MAX_REF_AMS_MAX_REF_BG_MN); + extAttr->phaseCorrectionBypass = FALSE; + extAttr->enableCVBSOutput = TRUE; + break; + case DRX_STANDARD_FM: + /* FM */ + cmdParam = SCU_RAM_ATV_STANDARD_STANDARD_FM; + + WR16( devAddr, IQM_RT_LO_INCR__A , 2994 ); + WR16( devAddr, IQM_CF_MIDTAP__A , 0 ); + WRB ( devAddr, IQM_CF_TAP_RE0__A , sizeof(fm_taps_re) , + ((pu8_t)fm_taps_re) ); + WRB ( devAddr, IQM_CF_TAP_IM0__A , sizeof(fm_taps_im) , + ((pu8_t)fm_taps_im) ); + WR16( devAddr, ATV_TOP_STD__A , (ATV_TOP_STD_MODE_FM | + ATV_TOP_STD_VID_POL_FM ) ); + WR16( devAddr, ATV_TOP_MOD_CONTROL__A, 0 ); + WR16( devAddr, ATV_TOP_CR_CONT__A , 0 ); + + WR16( devAddr, SCU_RAM_ATV_AGC_MODE__A , + ( SCU_RAM_ATV_AGC_MODE_VAGC_VEL_AGC_SLOW | + SCU_RAM_ATV_AGC_MODE_SIF_STD_SIF_AGC_FM )); + WR16( devAddr, IQM_RT_ROT_BP__A, IQM_RT_ROT_BP_ROT_OFF_OFF ); + extAttr->phaseCorrectionBypass = TRUE; + extAttr->enableCVBSOutput = FALSE; + break; + case DRX_STANDARD_PAL_SECAM_BG: + /* PAL/SECAM B/G */ + cmdParam = SCU_RAM_ATV_STANDARD_STANDARD_B; + + WR16( devAddr, IQM_RT_LO_INCR__A , 1820 );/* TODO check with IS */ + WR16( devAddr, IQM_CF_MIDTAP__A , IQM_CF_MIDTAP_RE__M ); + WRB ( devAddr, IQM_CF_TAP_RE0__A , sizeof(bg_taps_re) , + ((pu8_t)bg_taps_re) ); + WRB ( devAddr, IQM_CF_TAP_IM0__A , sizeof(bg_taps_im) , + ((pu8_t)bg_taps_im) ); + WR16( devAddr, ATV_TOP_VID_AMP__A , ATV_TOP_VID_AMP_BG ); + WR16( devAddr, ATV_TOP_CR_AMP_TH__A, ATV_TOP_CR_AMP_TH_BG ); + WR16( devAddr, ATV_TOP_CR_CONT__A , + ( ATV_TOP_CR_CONT_CR_P_BG | + ATV_TOP_CR_CONT_CR_D_BG | + ATV_TOP_CR_CONT_CR_I_BG ) ); + WR16( devAddr, ATV_TOP_CR_OVM_TH__A , ATV_TOP_CR_OVM_TH_BG ); + WR16( devAddr, ATV_TOP_STD__A , (ATV_TOP_STD_MODE_BG | + ATV_TOP_STD_VID_POL_BG ) ); + WR16( devAddr, SCU_RAM_ATV_AGC_MODE__A , + ( SCU_RAM_ATV_AGC_MODE_SIF_STD_SIF_AGC_FM | + SCU_RAM_ATV_AGC_MODE_FAST_VAGC_EN_FAGC_ENABLE ) ); + WR16( devAddr, SCU_RAM_ATV_VID_GAIN_HI__A, 0x1000 ); + WR16( devAddr, SCU_RAM_ATV_VID_GAIN_LO__A, 0x0000 ); + WR16( devAddr, SCU_RAM_ATV_AMS_MAX_REF__A, + SCU_RAM_ATV_AMS_MAX_REF_AMS_MAX_REF_BG_MN); + extAttr->phaseCorrectionBypass = FALSE; + extAttr->atvIfAgcCfg.ctrlMode = DRX_AGC_CTRL_AUTO; + extAttr->enableCVBSOutput = TRUE; + break; + case DRX_STANDARD_PAL_SECAM_DK: + /* PAL/SECAM D/K */ + cmdParam = SCU_RAM_ATV_STANDARD_STANDARD_DK; + + WR16( devAddr, IQM_RT_LO_INCR__A , 2225 );/* TODO check with IS */ + WR16( devAddr, IQM_CF_MIDTAP__A , IQM_CF_MIDTAP_RE__M ); + WRB ( devAddr, IQM_CF_TAP_RE0__A , sizeof(dk_i_l_lp_taps_re) , + ((pu8_t)dk_i_l_lp_taps_re) ); + WRB ( devAddr, IQM_CF_TAP_IM0__A , sizeof(dk_i_l_lp_taps_im) , + ((pu8_t)dk_i_l_lp_taps_im) ); + WR16( devAddr, ATV_TOP_CR_AMP_TH__A , ATV_TOP_CR_AMP_TH_DK ); + WR16( devAddr, ATV_TOP_VID_AMP__A , ATV_TOP_VID_AMP_DK ); + WR16( devAddr, ATV_TOP_CR_CONT__A , + ( ATV_TOP_CR_CONT_CR_P_DK | + ATV_TOP_CR_CONT_CR_D_DK | + ATV_TOP_CR_CONT_CR_I_DK ) ); + WR16( devAddr, ATV_TOP_CR_OVM_TH__A , ATV_TOP_CR_OVM_TH_DK ); + WR16( devAddr, ATV_TOP_STD__A , (ATV_TOP_STD_MODE_DK | + ATV_TOP_STD_VID_POL_DK ) ); + WR16( devAddr, SCU_RAM_ATV_AGC_MODE__A , + ( SCU_RAM_ATV_AGC_MODE_SIF_STD_SIF_AGC_FM | + SCU_RAM_ATV_AGC_MODE_FAST_VAGC_EN_FAGC_ENABLE ) ); + WR16( devAddr, SCU_RAM_ATV_VID_GAIN_HI__A, 0x1000 ); + WR16( devAddr, SCU_RAM_ATV_VID_GAIN_LO__A, 0x0000 ); + WR16( devAddr, SCU_RAM_ATV_AMS_MAX_REF__A, + SCU_RAM_ATV_AMS_MAX_REF_AMS_MAX_REF_DK); + extAttr->phaseCorrectionBypass = FALSE; + extAttr->atvIfAgcCfg.ctrlMode =DRX_AGC_CTRL_AUTO; + extAttr->enableCVBSOutput = TRUE; + break; + case DRX_STANDARD_PAL_SECAM_I: + /* PAL/SECAM I */ + cmdParam = SCU_RAM_ATV_STANDARD_STANDARD_I; + + WR16( devAddr, IQM_RT_LO_INCR__A , 2225 );/* TODO check with IS */ + WR16( devAddr, IQM_CF_MIDTAP__A , IQM_CF_MIDTAP_RE__M ); + WRB ( devAddr, IQM_CF_TAP_RE0__A , sizeof(dk_i_l_lp_taps_re) , + ((pu8_t)dk_i_l_lp_taps_re) ); + WRB ( devAddr, IQM_CF_TAP_IM0__A , sizeof(dk_i_l_lp_taps_im) , + ((pu8_t)dk_i_l_lp_taps_im) ); + WR16( devAddr, ATV_TOP_CR_AMP_TH__A , ATV_TOP_CR_AMP_TH_I ); + WR16( devAddr, ATV_TOP_VID_AMP__A , ATV_TOP_VID_AMP_I ); + WR16( devAddr, ATV_TOP_CR_CONT__A , + ( ATV_TOP_CR_CONT_CR_P_I | + ATV_TOP_CR_CONT_CR_D_I | + ATV_TOP_CR_CONT_CR_I_I ) ); + WR16( devAddr, ATV_TOP_CR_OVM_TH__A , ATV_TOP_CR_OVM_TH_I ); + WR16( devAddr, ATV_TOP_STD__A , (ATV_TOP_STD_MODE_I | + ATV_TOP_STD_VID_POL_I ) ); + WR16( devAddr, SCU_RAM_ATV_AGC_MODE__A , + ( SCU_RAM_ATV_AGC_MODE_SIF_STD_SIF_AGC_FM | + SCU_RAM_ATV_AGC_MODE_FAST_VAGC_EN_FAGC_ENABLE ) ); + WR16( devAddr, SCU_RAM_ATV_VID_GAIN_HI__A, 0x1000 ); + WR16( devAddr, SCU_RAM_ATV_VID_GAIN_LO__A, 0x0000 ); + WR16( devAddr, SCU_RAM_ATV_AMS_MAX_REF__A, + SCU_RAM_ATV_AMS_MAX_REF_AMS_MAX_REF_I); + extAttr->phaseCorrectionBypass = FALSE; + extAttr->atvIfAgcCfg.ctrlMode = DRX_AGC_CTRL_AUTO; + extAttr->enableCVBSOutput = TRUE; + break; + case DRX_STANDARD_PAL_SECAM_L: + /* PAL/SECAM L with negative modulation */ + cmdParam = SCU_RAM_ATV_STANDARD_STANDARD_L; + + WR16( devAddr, IQM_RT_LO_INCR__A , 2225 ); /* TODO check with IS */ + WR16( devAddr, ATV_TOP_VID_AMP__A , ATV_TOP_VID_AMP_L ); + WR16( devAddr, IQM_CF_MIDTAP__A , IQM_CF_MIDTAP_RE__M ); + WRB ( devAddr, IQM_CF_TAP_RE0__A , sizeof(dk_i_l_lp_taps_re) , + ((pu8_t)dk_i_l_lp_taps_re) ); + WRB ( devAddr, IQM_CF_TAP_IM0__A , sizeof(dk_i_l_lp_taps_im) , + ((pu8_t)dk_i_l_lp_taps_im) ); + WR16( devAddr, ATV_TOP_CR_AMP_TH__A , 0x2 ); /* TODO check with IS */ + WR16( devAddr, ATV_TOP_CR_CONT__A , + ( ATV_TOP_CR_CONT_CR_P_L | + ATV_TOP_CR_CONT_CR_D_L | + ATV_TOP_CR_CONT_CR_I_L ) ); + WR16( devAddr, ATV_TOP_CR_OVM_TH__A , ATV_TOP_CR_OVM_TH_L ); + WR16( devAddr, ATV_TOP_STD__A , (ATV_TOP_STD_MODE_L | + ATV_TOP_STD_VID_POL_L ) ); + WR16( devAddr, SCU_RAM_ATV_AGC_MODE__A , + ( SCU_RAM_ATV_AGC_MODE_SIF_STD_SIF_AGC_AM | + SCU_RAM_ATV_AGC_MODE_BP_EN_BPC_ENABLE | + SCU_RAM_ATV_AGC_MODE_VAGC_VEL_AGC_SLOW ) ); + WR16( devAddr, SCU_RAM_ATV_VID_GAIN_HI__A, 0x1000 ); + WR16( devAddr, SCU_RAM_ATV_VID_GAIN_LO__A, 0x0000 ); + WR16( devAddr, SCU_RAM_ATV_AMS_MAX_REF__A, + SCU_RAM_ATV_AMS_MAX_REF_AMS_MAX_REF_LLP); + extAttr->phaseCorrectionBypass = FALSE; + extAttr->atvIfAgcCfg.ctrlMode = DRX_AGC_CTRL_USER; + extAttr->atvIfAgcCfg.outputLevel = extAttr->atvRfAgcCfg.top; + extAttr->enableCVBSOutput = TRUE; + break; + case DRX_STANDARD_PAL_SECAM_LP: + /* PAL/SECAM L with positive modulation */ + cmdParam = SCU_RAM_ATV_STANDARD_STANDARD_LP; + + WR16( devAddr, ATV_TOP_VID_AMP__A , ATV_TOP_VID_AMP_LP ); + WR16( devAddr, IQM_RT_LO_INCR__A , 2225 ); /* TODO check with IS */ + WR16( devAddr, IQM_CF_MIDTAP__A , IQM_CF_MIDTAP_RE__M ); + WRB ( devAddr, IQM_CF_TAP_RE0__A , sizeof(dk_i_l_lp_taps_re) , + ((pu8_t)dk_i_l_lp_taps_re) ); + WRB ( devAddr, IQM_CF_TAP_IM0__A , sizeof(dk_i_l_lp_taps_im) , + ((pu8_t)dk_i_l_lp_taps_im) ); + WR16( devAddr, ATV_TOP_CR_AMP_TH__A , 0x2 ); /* TODO check with IS */ + WR16( devAddr, ATV_TOP_CR_CONT__A , + ( ATV_TOP_CR_CONT_CR_P_LP | + ATV_TOP_CR_CONT_CR_D_LP | + ATV_TOP_CR_CONT_CR_I_LP ) ); + WR16( devAddr, ATV_TOP_CR_OVM_TH__A , ATV_TOP_CR_OVM_TH_LP ); + WR16( devAddr, ATV_TOP_STD__A , (ATV_TOP_STD_MODE_LP | + ATV_TOP_STD_VID_POL_LP ) ); + WR16( devAddr, SCU_RAM_ATV_AGC_MODE__A , + ( SCU_RAM_ATV_AGC_MODE_SIF_STD_SIF_AGC_AM | + SCU_RAM_ATV_AGC_MODE_BP_EN_BPC_ENABLE | + SCU_RAM_ATV_AGC_MODE_VAGC_VEL_AGC_SLOW ) ); + WR16( devAddr, SCU_RAM_ATV_VID_GAIN_HI__A, 0x1000 ); + WR16( devAddr, SCU_RAM_ATV_VID_GAIN_LO__A, 0x0000 ); + WR16( devAddr, SCU_RAM_ATV_AMS_MAX_REF__A, + SCU_RAM_ATV_AMS_MAX_REF_AMS_MAX_REF_LLP); + extAttr->phaseCorrectionBypass = FALSE; + extAttr->atvIfAgcCfg.ctrlMode = DRX_AGC_CTRL_USER; + extAttr->atvIfAgcCfg.outputLevel = extAttr->atvRfAgcCfg.top; + extAttr->enableCVBSOutput = TRUE; + break; + default: + return ( DRX_STS_ERROR ); + } + + /* Common initializations FM & NTSC & B/G & D/K & I & L & LP */ + if (extAttr->hasLNA == FALSE) + { + WR16( devAddr, IQM_AF_AMUX__A, 0x01); + } + + WR16( devAddr, SCU_RAM_ATV_STANDARD__A , 0x002 ); + WR16( devAddr, IQM_AF_CLP_LEN__A , IQM_AF_CLP_LEN_ATV ); + WR16( devAddr, IQM_AF_CLP_TH__A , IQM_AF_CLP_TH_ATV ); + WR16( devAddr, IQM_AF_SNS_LEN__A , IQM_AF_SNS_LEN_ATV ); + CHK_ERROR( CtrlSetCfgPreSaw( demod, &(extAttr->atvPreSawCfg)) ); + WR16( devAddr, IQM_AF_AGC_IF__A , 10248 ); + + extAttr->iqmRcRateOfs = 0x00200000L; + WR32( devAddr, IQM_RC_RATE_OFS_LO__A , extAttr->iqmRcRateOfs ); + WR16( devAddr, IQM_RC_ADJ_SEL__A , IQM_RC_ADJ_SEL_B_OFF ); + WR16( devAddr, IQM_RC_STRETCH__A , IQM_RC_STRETCH_ATV ); + + WR16( devAddr, IQM_RT_ACTIVE__A , IQM_RT_ACTIVE_ACTIVE_RT_ATV_FCR_ON | + IQM_RT_ACTIVE_ACTIVE_CR_ATV_CR_ON ); + + WR16( devAddr, IQM_CF_OUT_ENA__A , IQM_CF_OUT_ENA_ATV__M ); + WR16( devAddr, IQM_CF_SYMMETRIC__A , IQM_CF_SYMMETRIC_IM__M ); + /* default: SIF in standby */ + WR16( devAddr, ATV_TOP_SYNC_SLICE__A , ATV_TOP_SYNC_SLICE_MN ); + WR16( devAddr, ATV_TOP_MOD_ACCU__A , ATV_TOP_MOD_ACCU__PRE ); + + WR16( devAddr, SCU_RAM_ATV_SIF_GAIN__A , 0x080 ); + WR16( devAddr, SCU_RAM_ATV_FAGC_TH_RED__A , 10 ); + WR16( devAddr, SCU_RAM_ATV_AAGC_CNT__A , 7 ); + WR16( devAddr, SCU_RAM_ATV_NAGC_KI_MIN__A , 0x0225 ); + WR16( devAddr, SCU_RAM_ATV_NAGC_KI_MAX__A , 0x0547 ); + WR16( devAddr, SCU_RAM_ATV_KI_CHANGE_TH__A , 20 ); + WR16( devAddr, SCU_RAM_ATV_LOCK__A , 0 ); + + WR16( devAddr, IQM_RT_DELAY__A , IQM_RT_DELAY__PRE ); + WR16( devAddr, SCU_RAM_ATV_BPC_KI_MIN__A , 531 ); + WR16( devAddr, SCU_RAM_ATV_PAGC_KI_MIN__A, 1061 ); + WR16( devAddr, SCU_RAM_ATV_BP_REF_MIN__A , 100 ); + WR16( devAddr, SCU_RAM_ATV_BP_REF_MAX__A , 260 ); + WR16( devAddr, SCU_RAM_ATV_BP_LVL__A , 0 ); + WR16( devAddr, SCU_RAM_ATV_AMS_MAX__A , 0 ); + WR16( devAddr, SCU_RAM_ATV_AMS_MIN__A , 2047 ); + WR16( devAddr, SCU_RAM_GPIO__A , 0 ); + + /* Override reset values with current shadow settings */ + CHK_ERROR( AtvUpdateConfig( demod, TRUE) ); + + /* Configure/restore AGC settings */ + CHK_ERROR( InitAGC( demod ) ); + CHK_ERROR( SetAgcIf( demod, &(extAttr->atvIfAgcCfg), FALSE ) ); + CHK_ERROR( SetAgcRf( demod, &(extAttr->atvRfAgcCfg), FALSE ) ); + CHK_ERROR( CtrlSetCfgPreSaw( demod, &(extAttr->atvPreSawCfg)) ); + + /* Set SCU ATV substandard,assuming this doesn't require running ATV block */ + cmdSCU.command = SCU_RAM_COMMAND_STANDARD_ATV | + SCU_RAM_COMMAND_CMD_DEMOD_SET_ENV; + cmdSCU.parameterLen = 1; + cmdSCU.resultLen = 1; + cmdSCU.parameter = &cmdParam; + cmdSCU.result = &cmdResult; + CHK_ERROR( SCUCommand( devAddr, &cmdSCU ) ); + + /* turn the analog work around on/off (must after set_env b/c it is set in mc)*/ + if ( extAttr->mfx == 0x03 ) + { + WR16( devAddr, SCU_RAM_ATV_ENABLE_IIR_WA__A, 0 ); + } + else + { + WR16( devAddr, SCU_RAM_ATV_ENABLE_IIR_WA__A, 1 ); + WR16( devAddr, SCU_RAM_ATV_IIR_CRIT__A , 225 ); + } + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} +#endif + +/* -------------------------------------------------------------------------- */ + +#ifndef DRXJ_DIGITAL_ONLY +/** +* \fn DRXStatus_t SetATVChannel () +* \brief Set ATV channel. +* \param demod: instance of demod. +* \return DRXStatus_t. +* +* Not much needs to be done here, only start the SCU for NTSC/FM. +* Mirrored channels are not expected in the RF domain, so IQM FS setting +* doesn't need to be remembered. +* The channel->mirror parameter is therefor ignored. +* +*/ +static DRXStatus_t +SetATVChannel( pDRXDemodInstance_t demod, + DRXFrequency_t tunerFreqOffset, + pDRXChannel_t channel, + DRXStandard_t standard ) +{ + DRXJSCUCmd_t cmdSCU = {/* command */ 0, + /* parameterLen */ 0, + /* resultLen */ 0, + /* parameter */ NULL, + /* result */ NULL }; + u16_t cmdResult = 0; + pDRXJData_t extAttr = NULL; + pI2CDeviceAddr_t devAddr = NULL; + + devAddr = demod -> myI2CDevAddr; + extAttr = (pDRXJData_t)demod->myExtAttr; + + /* + Program frequency shifter + No need to account for mirroring on RF + */ + if (channel->mirror == DRX_MIRROR_AUTO) + { + extAttr->mirror = DRX_MIRROR_NO; + } + else + { + extAttr->mirror = channel->mirror; + } + + CHK_ERROR ( SetFrequency ( demod, channel, tunerFreqOffset ) ); + WR16(devAddr, ATV_TOP_CR_FREQ__A, ATV_TOP_CR_FREQ__PRE); + + /* Start ATV SCU */ + cmdSCU.command = SCU_RAM_COMMAND_STANDARD_ATV | + SCU_RAM_COMMAND_CMD_DEMOD_START; + cmdSCU.parameterLen = 0; + cmdSCU.resultLen = 1; + cmdSCU.parameter = NULL; + cmdSCU.result = &cmdResult; + CHK_ERROR( SCUCommand( devAddr, &cmdSCU ) ); + +/* if ( (extAttr->standard == DRX_STANDARD_FM) && (extAttr->flagSetAUDdone == TRUE) ) + { + extAttr->detectedRDS = (Bool_t)FALSE; + }*/ + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} +#endif + +/* -------------------------------------------------------------------------- */ + +/** +* \fn DRXStatus_t GetATVChannel () +* \brief Set ATV channel. +* \param demod: instance of demod. +* \param channel: pointer to channel data. +* \param standard: NTSC or FM. +* \return DRXStatus_t. +* +* Covers NTSC, PAL/SECAM - B/G, D/K, I, L, LP and FM. +* Computes the frequency offset in te RF domain and adds it to +* channel->frequency. Determines the value for channel->bandwidth. +* +*/ +#ifndef DRXJ_DIGITAL_ONLY +static DRXStatus_t +GetATVChannel( pDRXDemodInstance_t demod, + pDRXChannel_t channel, + DRXStandard_t standard ) +{ + DRXFrequency_t offset = 0; + pI2CDeviceAddr_t devAddr = NULL; + pDRXJData_t extAttr = NULL; + + devAddr = demod -> myI2CDevAddr; + extAttr = (pDRXJData_t)demod->myExtAttr; + + /* Bandwidth */ + channel->bandwidth = ((pDRXJData_t)demod -> myExtAttr)->currBandwidth; + + switch ( standard ) + { + case DRX_STANDARD_NTSC: + case DRX_STANDARD_PAL_SECAM_BG: + case DRX_STANDARD_PAL_SECAM_DK: + case DRX_STANDARD_PAL_SECAM_I: + case DRX_STANDARD_PAL_SECAM_L: + { + u16_t measuredOffset=0; + + /* get measured frequency offset */ + RR16(devAddr, ATV_TOP_CR_FREQ__A, &measuredOffset); + /* Signed 8 bit register => sign extension needed */ + if ( (measuredOffset & 0x0080) != 0) + { + /* sign extension */ + measuredOffset |= 0xFF80; + } + offset+= (DRXFrequency_t)( ((s16_t)measuredOffset)*10); + break; + } + case DRX_STANDARD_PAL_SECAM_LP: + { + u16_t measuredOffset=0; + + /* get measured frequency offset */ + RR16(devAddr, ATV_TOP_CR_FREQ__A, &measuredOffset); + /* Signed 8 bit register => sign extension needed */ + if ( (measuredOffset & 0x0080) != 0) + { + /* sign extension */ + measuredOffset |= 0xFF80; + } + offset-= (DRXFrequency_t)( ((s16_t)measuredOffset)*10); + } + break; + case DRX_STANDARD_FM: + /* TODO: compute offset using AUD_DSP_RD_FM_DC_LEVEL_A__A and + AUD_DSP_RD_FM_DC_LEVEL_B__A. For now leave frequency as is. + */ + /* No bandwidth know for FM */ + channel->bandwidth = DRX_BANDWIDTH_UNKNOWN; + break; + default: + return ( DRX_STS_ERROR ); + } + + channel->frequency -= offset; + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} + +/* -------------------------------------------------------------------------- */ +/** +* \fn DRXStatus_t GetAtvSigStrength() +* \brief Retrieve signal strength for ATV & FM. +* \param devmod Pointer to demodulator instance. +* \param sigQuality Pointer to signal strength data; range 0, .. , 100. +* \return DRXStatus_t. +* \retval DRX_STS_OK sigStrength contains valid data. +* \retval DRX_STS_ERROR Erroneous data, sigStrength equals 0. +* +* Taking into account: +* * digital gain +* * IF gain (not implemented yet, waiting for IF gain control by ucode) +* * RF gain +* +* All weights (digital, if, rf) must add up to 100. +* +* TODO: ? dynamically adapt weights in case RF and/or IF agc of drxj +* is not used ? +*/ +static DRXStatus_t +GetAtvSigStrength( pDRXDemodInstance_t demod, + pu16_t sigStrength ) +{ + pI2CDeviceAddr_t devAddr = NULL; + pDRXJData_t extAttr = NULL; + + /* All weights must add up to 100 (%) + TODO: change weights when IF ctrl is available */ + u32_t digitalWeight = 50; /* 0 .. 100 */ + u32_t rfWeight = 50; /* 0 .. 100 */ + u32_t ifWeight = 0; /* 0 .. 100 */ + + u16_t digitalCurrGain = 0; + u32_t digitalMaxGain = 0; + u32_t digitalMinGain = 0; + u16_t rfCurrGain = 0; + u32_t rfMaxGain = 0x800; /* taken from ucode */ + u32_t rfMinGain = 0x7fff; + u16_t ifCurrGain = 0; + u32_t ifMaxGain = 0x800; /* taken from ucode */ + u32_t ifMinGain = 0x7fff; + + u32_t digitalStrength = 0; /* 0.. 100 */ + u32_t rfStrength = 0; /* 0.. 100 */ + u32_t ifStrength = 0; /* 0.. 100 */ + + devAddr = demod -> myI2CDevAddr; + extAttr = (pDRXJData_t)demod->myExtAttr; + + *sigStrength = 0; + + switch( extAttr->standard ) + { + case DRX_STANDARD_PAL_SECAM_BG : /* fallthrough */ + case DRX_STANDARD_PAL_SECAM_DK : /* fallthrough */ + case DRX_STANDARD_PAL_SECAM_I : /* fallthrough */ + case DRX_STANDARD_PAL_SECAM_L : /* fallthrough */ + case DRX_STANDARD_PAL_SECAM_LP : /* fallthrough */ + case DRX_STANDARD_NTSC: + SARR16(devAddr, SCU_RAM_ATV_VID_GAIN_HI__A, &digitalCurrGain); + digitalMaxGain = 22512; /* taken from ucode */ + digitalMinGain = 2400; /* taken from ucode */ + break; + case DRX_STANDARD_FM: + SARR16(devAddr, SCU_RAM_ATV_SIF_GAIN__A, &digitalCurrGain); + digitalMaxGain = 0x4ff; /* taken from ucode */ + digitalMinGain = 0; /* taken from ucode */ + break; + default: + return (DRX_STS_ERROR); + break; + } + RR16(devAddr, IQM_AF_AGC_RF__A, &rfCurrGain); + RR16(devAddr, IQM_AF_AGC_IF__A, &ifCurrGain); + + /* clipping */ + if ( digitalCurrGain >= digitalMaxGain ) digitalCurrGain = (u16_t)digitalMaxGain; + if ( digitalCurrGain <= digitalMinGain ) digitalCurrGain = (u16_t)digitalMinGain; + if ( ifCurrGain <= ifMaxGain ) ifCurrGain = (u16_t)ifMaxGain; + if ( ifCurrGain >= ifMinGain ) ifCurrGain = (u16_t)ifMinGain; + if ( rfCurrGain <= rfMaxGain ) rfCurrGain = (u16_t)rfMaxGain; + if ( rfCurrGain >= rfMinGain ) rfCurrGain = (u16_t)rfMinGain; + + /* TODO: use SCU_RAM_ATV_RAGC_HR__A to shift max and min in case + of clipping at ADC */ + + /* Compute signal strength (in %) per "gain domain" */ + + /* Digital gain */ + /* TODO: ADC clipping not handled */ + digitalStrength = ( 100 *(digitalMaxGain-(u32_t)digitalCurrGain) )/ + (digitalMaxGain -digitalMinGain); + + /* TODO: IF gain not implemented yet in microcode, check after impl. */ + ifStrength = ( 100 *((u32_t)ifCurrGain-ifMaxGain) )/ + ( ifMinGain - ifMaxGain ); + + /* Rf gain */ + /* TODO: ADC clipping not handled */ + rfStrength = ( 100 *((u32_t)rfCurrGain-rfMaxGain) )/ + ( rfMinGain - rfMaxGain ); + + /* Compute a weighted signal strength (in %) */ + *sigStrength = (u16_t) (digitalWeight*digitalStrength + + rfWeight*rfStrength + + ifWeight*ifStrength); + *sigStrength /= 100; + + return (DRX_STS_OK); + rw_error: + return (DRX_STS_ERROR); +} + +/* -------------------------------------------------------------------------- */ +/** +* \fn DRXStatus_t AtvSigQuality() +* \brief Retrieve signal quality indication for ATV. +* \param devmod Pointer to demodulator instance. +* \param sigQuality Pointer to signal quality structure. +* \return DRXStatus_t. +* \retval DRX_STS_OK sigQuality contains valid data. +* \retval DRX_STS_ERROR Erroneous data, sigQuality indicator equals 0. +* +* +*/ +static DRXStatus_t +AtvSigQuality( pDRXDemodInstance_t demod, + pDRXSigQuality_t sigQuality ) +{ + pI2CDeviceAddr_t devAddr = NULL; + u16_t qualityIndicator = 0; + + devAddr = demod -> myI2CDevAddr; + + /* defined values for fields not used */ + sigQuality->MER = 0; + sigQuality->preViterbiBER = 0; + sigQuality->postViterbiBER = 0; + sigQuality->scaleFactorBER = 1; + sigQuality->packetError = 0; + sigQuality->postReedSolomonBER = 0; + + /* + Mapping: + 0x000..0x080: strong signal => 80% .. 100% + 0x080..0x700: weak signal => 30% .. 80% + 0x700..0x7ff: no signal => 0% .. 30% + */ + + SARR16( devAddr, SCU_RAM_ATV_CR_LOCK__A, &qualityIndicator ); + qualityIndicator &= SCU_RAM_ATV_CR_LOCK_CR_LOCK__M; + if ( qualityIndicator <= 0x80 ) + { + sigQuality->indicator = 80 + ( (20*(0x80-qualityIndicator))/0x80); + } else if ( qualityIndicator <= 0x700 ) + { + sigQuality->indicator = 30 + + ( (50*(0x700-qualityIndicator))/(0x700-0x81)); + } else { + sigQuality->indicator = + (30*(0x7FF-qualityIndicator))/(0x7FF-0x701); + } + + return (DRX_STS_OK); + rw_error: + return (DRX_STS_ERROR); +} +#endif /* DRXJ_DIGITAL_ONLY */ + +/*============================================================================*/ +/*== END ATV DATAPATH FUNCTIONS ==*/ +/*============================================================================*/ + +#ifndef DRXJ_EXCLUDE_AUDIO +/*===========================================================================*/ +/*===========================================================================*/ +/*== AUDIO DATAPATH FUNCTIONS ==*/ +/*===========================================================================*/ +/*===========================================================================*/ + +/* +* \brief Power up AUD. +* \param demod instance of demodulator +* \return DRXStatus_t. +* +*/ +static DRXStatus_t +PowerUpAud( pDRXDemodInstance_t demod, + Bool_t setStandard) +{ + DRXAudStandard_t audStandard = DRX_AUD_STANDARD_AUTO; + pI2CDeviceAddr_t devAddr = NULL; + + devAddr = demod->myI2CDevAddr; + + WR16( devAddr, AUD_TOP_COMM_EXEC__A, AUD_TOP_COMM_EXEC_ACTIVE); + /* setup TR interface: R/W mode, fifosize=8 */ + WR16( devAddr, AUD_TOP_TR_MDE__A, 8); + WR16( devAddr, AUD_COMM_EXEC__A, AUD_COMM_EXEC_ACTIVE); + + if ( setStandard == TRUE ) + { + CHK_ERROR( AUDCtrlSetStandard ( demod, &audStandard ) ); + } + + return DRX_STS_OK; +rw_error: + return DRX_STS_ERROR; +} + +/*============================================================================*/ + +/** +* \brief Power up AUD. +* \param demod instance of demodulator +* \return DRXStatus_t. +* +*/ +static DRXStatus_t +PowerDownAud( pDRXDemodInstance_t demod ) +{ + pI2CDeviceAddr_t devAddr = NULL; + pDRXJData_t extAttr = NULL; + + devAddr = (pI2CDeviceAddr_t)demod->myI2CDevAddr; + extAttr = (pDRXJData_t)demod->myExtAttr; + + WR16( devAddr, AUD_COMM_EXEC__A, AUD_COMM_EXEC_STOP ); + + extAttr->audData.audioIsActive = FALSE; + + return DRX_STS_OK; +rw_error: + return DRX_STS_ERROR; +} +/*============================================================================*/ +/** +* \brief Get Modus data from audio RAM +* \param demod instance of demodulator +* \param pointer to modus +* \return DRXStatus_t. +* +*/ +static DRXStatus_t +AUDGetModus ( pDRXDemodInstance_t demod, + pu16_t modus ) +{ + pI2CDeviceAddr_t devAddr = NULL; + pDRXJData_t extAttr = NULL; + + u16_t rModus = 0; + u16_t rModusHi = 0; + u16_t rModusLo = 0; + + if ( modus == NULL ) + { + return DRX_STS_INVALID_ARG; + } + + devAddr = (pI2CDeviceAddr_t)demod->myI2CDevAddr; + extAttr = (pDRXJData_t)demod->myExtAttr; + + /* power up */ + if ( extAttr->audData.audioIsActive == FALSE ) + { + CHK_ERROR ( PowerUpAud( demod , TRUE ) ); + extAttr->audData.audioIsActive = TRUE; + } + + /* Modus register is combined in to RAM location */ + RR16( devAddr, AUD_DEM_RAM_MODUS_HI__A, &rModusHi ); + RR16( devAddr, AUD_DEM_RAM_MODUS_LO__A, &rModusLo ); + + rModus = ( (rModusHi << 12 ) & AUD_DEM_RAM_MODUS_HI__M) + | ((( rModusLo & AUD_DEM_RAM_MODUS_LO__M) )); + + *modus = rModus; + + return DRX_STS_OK; +rw_error: + return DRX_STS_ERROR; + +} + +/*============================================================================*/ +/** +* \brief Get audio RDS dat +* \param demod instance of demodulator +* \param pointer to DRXCfgAudRDS_t +* \return DRXStatus_t. +* +*/ +static DRXStatus_t +AUDCtrlGetCfgRDS ( pDRXDemodInstance_t demod, + pDRXCfgAudRDS_t status ) +{ + pI2CDeviceAddr_t addr = NULL; + pDRXJData_t extAttr = NULL; + + u16_t rRDSArrayCntInit = 0; + u16_t rRDSArrayCntCheck = 0; + u16_t rRDSData = 0; + u16_t RDSDataCnt = 0; + + addr = (pI2CDeviceAddr_t)demod->myI2CDevAddr; + extAttr = (pDRXJData_t)demod->myExtAttr; + + + if ( status == NULL ) + { + return DRX_STS_INVALID_ARG; + } + + /* power up */ + if ( extAttr->audData.audioIsActive == FALSE ) + { + CHK_ERROR ( PowerUpAud( demod , TRUE ) ); + extAttr->audData.audioIsActive = TRUE; + } + + status->valid = FALSE; + + RR16( addr, AUD_DEM_RD_RDS_ARRAY_CNT__A, &rRDSArrayCntInit); + + if ( rRDSArrayCntInit == + AUD_DEM_RD_RDS_ARRAY_CNT_RDS_ARRAY_CT_RDS_DATA_NOT_VALID ) + { + /* invalid data */ + return DRX_STS_OK; + } + + if ( extAttr->audData.rdsDataCounter == rRDSArrayCntInit) + { + /* no new data */ + return DRX_STS_OK; + } + + /* RDS is detected, as long as FM radio is selected assume + RDS will be available */ + extAttr->audData.rdsDataPresent = TRUE; + + /* new data */ + /* read the data */ + for ( RDSDataCnt = 0; + RDSDataCnt < AUD_RDS_ARRAY_SIZE; + RDSDataCnt++) + { + RR16 ( addr, AUD_DEM_RD_RDS_DATA__A, &rRDSData ); + status->data[RDSDataCnt] = rRDSData; + } + + RR16( addr, AUD_DEM_RD_RDS_ARRAY_CNT__A, &rRDSArrayCntCheck); + + if ( rRDSArrayCntCheck == rRDSArrayCntInit ) + { + status->valid = TRUE; + extAttr->audData.rdsDataCounter = rRDSArrayCntCheck; + } + + return DRX_STS_OK; +rw_error: + return DRX_STS_ERROR; +} + +/*============================================================================*/ +/** +* \brief Get the current audio carrier detection status +* \param demod instance of demodulator +* \param pointer to AUDCtrlGetStatus +* \return DRXStatus_t. +* +*/ +static DRXStatus_t +AUDCtrlGetCarrierDetectStatus ( pDRXDemodInstance_t demod, + pDRXAudStatus_t status ) +{ + pDRXJData_t extAttr = NULL; + pI2CDeviceAddr_t devAddr = NULL; + + u16_t rData = 0; + + if ( status == NULL) + { + return DRX_STS_INVALID_ARG; + } + + devAddr = (pI2CDeviceAddr_t)demod->myI2CDevAddr; + extAttr = (pDRXJData_t)demod->myExtAttr; + + /* power up */ + if ( extAttr->audData.audioIsActive == FALSE ) + { + CHK_ERROR ( PowerUpAud( demod , TRUE ) ); + extAttr->audData.audioIsActive = TRUE; + } + + /* initialize the variables */ + status->carrierA = FALSE; + status->carrierB = FALSE; + status->nicamStatus = DRX_AUD_NICAM_NOT_DETECTED; + status->sap = FALSE; + status->stereo = FALSE; + + /* read stereo sound mode indication */ + RR16( devAddr, AUD_DEM_RD_STATUS__A, &rData ); + + /* carrier a detected */ + if ( (rData & AUD_DEM_RD_STATUS_STAT_CARR_A__M ) == + AUD_DEM_RD_STATUS_STAT_CARR_A_DETECTED ) + { + status->carrierA = TRUE; + } + + /* carrier b detected */ + if ( (rData & AUD_DEM_RD_STATUS_STAT_CARR_B__M ) == + AUD_DEM_RD_STATUS_STAT_CARR_B_DETECTED ) + { + status->carrierB = TRUE; + } + /* nicam detected */ + if ( (rData & AUD_DEM_RD_STATUS_STAT_NICAM__M) == + AUD_DEM_RD_STATUS_STAT_NICAM_NICAM_DETECTED) + { + if ((rData & AUD_DEM_RD_STATUS_BAD_NICAM__M) == + AUD_DEM_RD_STATUS_BAD_NICAM_OK) + { + status->nicamStatus = DRX_AUD_NICAM_DETECTED; + } + else + { + status->nicamStatus = DRX_AUD_NICAM_BAD; + } + } + + /* audio mode bilingual or SAP detected */ + if ( (rData & AUD_DEM_RD_STATUS_STAT_BIL_OR_SAP__M) == + AUD_DEM_RD_STATUS_STAT_BIL_OR_SAP_SAP) + { + status->sap = TRUE; + } + + /* stereo detected */ + if ( (rData & AUD_DEM_RD_STATUS_STAT_STEREO__M) == + AUD_DEM_RD_STATUS_STAT_STEREO_STEREO) + { + status->stereo = TRUE; + } + + return DRX_STS_OK; +rw_error: + return DRX_STS_ERROR; +} + + +/*============================================================================*/ +/** +* \brief Get the current audio status parameters +* \param demod instance of demodulator +* \param pointer to AUDCtrlGetStatus +* \return DRXStatus_t. +* +*/ +static DRXStatus_t +AUDCtrlGetStatus ( pDRXDemodInstance_t demod, + pDRXAudStatus_t status ) +{ + pDRXJData_t extAttr = NULL; + pI2CDeviceAddr_t devAddr = NULL; + DRXCfgAudRDS_t rds = { FALSE, {0} }; + u16_t rData = 0; + + if ( status == NULL) + { + return DRX_STS_INVALID_ARG; + } + + devAddr = (pI2CDeviceAddr_t)demod->myI2CDevAddr; + extAttr = (pDRXJData_t)demod->myExtAttr; + + /* carrier detection */ + CHK_ERROR ( AUDCtrlGetCarrierDetectStatus ( demod, status ) ); + + /* rds data */ + status->rds = FALSE; + CHK_ERROR ( AUDCtrlGetCfgRDS ( demod, &rds ) ); + status->rds = extAttr->audData.rdsDataPresent; + + /* fmIdent */ + RR16( devAddr, AUD_DSP_RD_FM_IDENT_VALUE__A, &rData); + rData >>= AUD_DSP_RD_FM_IDENT_VALUE_FM_IDENT__B; + status->fmIdent = (s8_t)rData; + + return DRX_STS_OK; +rw_error: + return DRX_STS_ERROR; +} + +/*============================================================================*/ +/** +* \brief Get the current volume settings +* \param demod instance of demodulator +* \param pointer to DRXCfgAudVolume_t +* \return DRXStatus_t. +* +*/ +static DRXStatus_t +AUDCtrlGetCfgVolume ( pDRXDemodInstance_t demod, + pDRXCfgAudVolume_t volume ) +{ + pI2CDeviceAddr_t devAddr = NULL; + pDRXJData_t extAttr = NULL; + + u16_t rVolume = 0; + u16_t rAVC = 0; + u16_t rStrengthLeft = 0; + u16_t rStrengthRight = 0; + + if ( volume == NULL ) + { + return DRX_STS_INVALID_ARG; + } + + devAddr = (pI2CDeviceAddr_t)demod->myI2CDevAddr; + extAttr = (pDRXJData_t)demod->myExtAttr; + + /* power up */ + if ( extAttr->audData.audioIsActive == FALSE ) + { + CHK_ERROR ( PowerUpAud( demod , TRUE ) ); + extAttr->audData.audioIsActive = TRUE; + } + + /* volume */ + volume->mute = extAttr->audData.volume.mute; + RR16( devAddr, AUD_DSP_WR_VOLUME__A, &rVolume ); + if ( rVolume == 0 ) + { + volume->mute = TRUE; + volume->volume = extAttr->audData.volume.volume; + } + else + { + volume->mute = FALSE; + volume->volume = ( ( rVolume & AUD_DSP_WR_VOLUME_VOL_MAIN__M ) >> + AUD_DSP_WR_VOLUME_VOL_MAIN__B ) - + AUD_VOLUME_ZERO_DB; + if ( volume->volume < AUD_VOLUME_DB_MIN ) + { + volume->volume = AUD_VOLUME_DB_MIN; + } + if ( volume->volume > AUD_VOLUME_DB_MAX ) + { + volume->volume = AUD_VOLUME_DB_MAX; + } + } + + /* automatic volume control */ + RR16( devAddr, AUD_DSP_WR_AVC__A, &rAVC ); + + if( ( rAVC & AUD_DSP_WR_AVC_AVC_ON__M) == + AUD_DSP_WR_AVC_AVC_ON_OFF ) + + { + volume->avcMode = DRX_AUD_AVC_OFF; + } + else + { + switch ( rAVC & AUD_DSP_WR_AVC_AVC_DECAY__M ) + { + case AUD_DSP_WR_AVC_AVC_DECAY_20_MSEC: + volume->avcMode = DRX_AUD_AVC_DECAYTIME_20MS; + break; + case AUD_DSP_WR_AVC_AVC_DECAY_8_SEC: + volume->avcMode = DRX_AUD_AVC_DECAYTIME_8S; + break; + case AUD_DSP_WR_AVC_AVC_DECAY_4_SEC: + volume->avcMode = DRX_AUD_AVC_DECAYTIME_4S; + break; + case AUD_DSP_WR_AVC_AVC_DECAY_2_SEC: + volume->avcMode = DRX_AUD_AVC_DECAYTIME_2S; + break; + default: + return DRX_STS_ERROR; + break; + } + } + + /* max attenuation */ + switch ( rAVC & AUD_DSP_WR_AVC_AVC_MAX_ATT__M ) + { + case AUD_DSP_WR_AVC_AVC_MAX_ATT_12DB: + volume->avcMaxAtten = DRX_AUD_AVC_MAX_ATTEN_12DB; + break; + case AUD_DSP_WR_AVC_AVC_MAX_ATT_18DB: + volume->avcMaxAtten = DRX_AUD_AVC_MAX_ATTEN_18DB; + break; + case AUD_DSP_WR_AVC_AVC_MAX_ATT_24DB: + volume->avcMaxAtten = DRX_AUD_AVC_MAX_ATTEN_24DB; + break; + default: + return DRX_STS_ERROR; + break; + } + + /* max gain */ + switch ( rAVC & AUD_DSP_WR_AVC_AVC_MAX_GAIN__M ) + { + case AUD_DSP_WR_AVC_AVC_MAX_GAIN_0DB: + volume->avcMaxGain = DRX_AUD_AVC_MAX_GAIN_0DB; + break; + case AUD_DSP_WR_AVC_AVC_MAX_GAIN_6DB: + volume->avcMaxGain = DRX_AUD_AVC_MAX_GAIN_6DB; + break; + case AUD_DSP_WR_AVC_AVC_MAX_GAIN_12DB: + volume->avcMaxGain = DRX_AUD_AVC_MAX_GAIN_12DB; + break; + default: + return DRX_STS_ERROR; + break; + } + + /* reference level */ + volume->avcRefLevel = (u16_t)( ( rAVC & AUD_DSP_WR_AVC_AVC_REF_LEV__M) >> + AUD_DSP_WR_AVC_AVC_REF_LEV__B ); + + /* read qpeak registers and calculate strength of left and right carrier */ + /* quasi peaks formula: QP(dB) = 20 * log( AUD_DSP_RD_QPEAKx / Q(0dB) */ + /* Q(0dB) represents QP value of 0dB (hex value 0x4000) */ + /* left carrier */ + + /* QP vaues */ + /* left carrier */ + RR16 (devAddr, AUD_DSP_RD_QPEAK_L__A, &rStrengthLeft); + volume->strengthLeft = ( ( (s16_t) Log10Times100 ( rStrengthLeft ) ) - + AUD_CARRIER_STRENGTH_QP_0DB_LOG10T100 ) / 5; + + /* right carrier */ + RR16 (devAddr, AUD_DSP_RD_QPEAK_R__A, &rStrengthRight); + volume->strengthRight = ( ( (s16_t) Log10Times100 ( rStrengthRight ) ) - + AUD_CARRIER_STRENGTH_QP_0DB_LOG10T100 ) / 5; + + return DRX_STS_OK; +rw_error: + return DRX_STS_ERROR; +} + + +/*============================================================================*/ +/** +* \brief Set the current volume settings +* \param demod instance of demodulator +* \param pointer to DRXCfgAudVolume_t +* \return DRXStatus_t. +* +*/ +static DRXStatus_t +AUDCtrlSetCfgVolume ( pDRXDemodInstance_t demod, + pDRXCfgAudVolume_t volume ) +{ + pI2CDeviceAddr_t devAddr = NULL; + pDRXJData_t extAttr = NULL; + + u16_t wVolume = 0; + u16_t wAVC = 0; + + + if ( volume == NULL ) + { + return DRX_STS_INVALID_ARG; + } + + devAddr = (pI2CDeviceAddr_t)demod->myI2CDevAddr; + extAttr = (pDRXJData_t)demod->myExtAttr; + + /* power up */ + if ( extAttr->audData.audioIsActive == FALSE ) + { + CHK_ERROR ( PowerUpAud( demod , TRUE ) ); + extAttr->audData.audioIsActive = TRUE; + } + + /* volume */ + /* volume range from -60 to 12 (expressed in dB) */ + if ( ( volume->volume < AUD_VOLUME_DB_MIN ) || + ( volume->volume > AUD_VOLUME_DB_MAX ) ) + { + return DRX_STS_INVALID_ARG; + } + + RR16( devAddr, AUD_DSP_WR_VOLUME__A, &wVolume ); + + /* clear the volume mask */ + wVolume &= (u16_t)~AUD_DSP_WR_VOLUME_VOL_MAIN__M; + if ( volume->mute == TRUE ) + { + /* mute */ + /* mute overrules volume */ + wVolume |= (u16_t) ( 0 ); + + } + else + { + wVolume |= (u16_t) ( ( volume->volume + AUD_VOLUME_ZERO_DB ) << + AUD_DSP_WR_VOLUME_VOL_MAIN__B ); + } + + WR16( devAddr, AUD_DSP_WR_VOLUME__A, wVolume ); + + /* automatic volume control */ + RR16( devAddr, AUD_DSP_WR_AVC__A, &wAVC ); + + /* clear masks that require writing */ + wAVC &= (u16_t) ~AUD_DSP_WR_AVC_AVC_ON__M; + wAVC &= (u16_t) ~AUD_DSP_WR_AVC_AVC_DECAY__M; + + if ( volume->avcMode == DRX_AUD_AVC_OFF ) + { + wAVC |= ( AUD_DSP_WR_AVC_AVC_ON_OFF ); + } + else + { + + wAVC |= ( AUD_DSP_WR_AVC_AVC_ON_ON ); + + /* avc decay */ + switch ( volume->avcMode ) + { + case DRX_AUD_AVC_DECAYTIME_20MS: + wAVC |= AUD_DSP_WR_AVC_AVC_DECAY_20_MSEC; + break; + case DRX_AUD_AVC_DECAYTIME_8S: + wAVC |= AUD_DSP_WR_AVC_AVC_DECAY_8_SEC; + break; + case DRX_AUD_AVC_DECAYTIME_4S: + wAVC |= AUD_DSP_WR_AVC_AVC_DECAY_4_SEC; + break; + case DRX_AUD_AVC_DECAYTIME_2S: + wAVC |= AUD_DSP_WR_AVC_AVC_DECAY_2_SEC; + break; + default: + return DRX_STS_INVALID_ARG; + } + } + + /* max attenuation */ + wAVC &= (u16_t) ~AUD_DSP_WR_AVC_AVC_MAX_ATT__M; + switch ( volume->avcMaxAtten ) + { + case DRX_AUD_AVC_MAX_ATTEN_12DB: + wAVC |= AUD_DSP_WR_AVC_AVC_MAX_ATT_12DB; + break; + case DRX_AUD_AVC_MAX_ATTEN_18DB: + wAVC |= AUD_DSP_WR_AVC_AVC_MAX_ATT_18DB; + break; + case DRX_AUD_AVC_MAX_ATTEN_24DB: + wAVC |= AUD_DSP_WR_AVC_AVC_MAX_ATT_24DB; + break; + default: + return DRX_STS_INVALID_ARG; + } + + /* max gain */ + wAVC &= (u16_t) ~AUD_DSP_WR_AVC_AVC_MAX_GAIN__M; + switch ( volume->avcMaxGain ) + { + case DRX_AUD_AVC_MAX_GAIN_0DB: + wAVC |= AUD_DSP_WR_AVC_AVC_MAX_GAIN_0DB; + break; + case DRX_AUD_AVC_MAX_GAIN_6DB: + wAVC |= AUD_DSP_WR_AVC_AVC_MAX_GAIN_6DB; + break; + case DRX_AUD_AVC_MAX_GAIN_12DB: + wAVC |= AUD_DSP_WR_AVC_AVC_MAX_GAIN_12DB; + break; + default: + return DRX_STS_INVALID_ARG; + } + + /* avc reference level */ + if ( volume->avcRefLevel > AUD_MAX_AVC_REF_LEVEL ) + { + return DRX_STS_INVALID_ARG; + } + + wAVC &= (u16_t)~AUD_DSP_WR_AVC_AVC_REF_LEV__M; + wAVC |= (u16_t)( volume->avcRefLevel << AUD_DSP_WR_AVC_AVC_REF_LEV__B ); + + WR16( devAddr, AUD_DSP_WR_AVC__A, wAVC ); + + /* all done, store config in data structure */ + extAttr->audData.volume = *volume; + + return DRX_STS_OK; +rw_error: + return DRX_STS_ERROR; +} + + +/*============================================================================*/ +/** +* \brief Get the I2S settings +* \param demod instance of demodulator +* \param pointer to DRXCfgI2SOutput_t +* \return DRXStatus_t. +* +*/ +static DRXStatus_t +AUDCtrlGetCfgOutputI2S ( pDRXDemodInstance_t demod, + pDRXCfgI2SOutput_t output ) +{ + pI2CDeviceAddr_t devAddr = NULL; + pDRXJData_t extAttr = NULL; + + u16_t wI2SConfig = 0; + u16_t rI2SFreq = 0; + + if ( output == NULL ) + { + return DRX_STS_INVALID_ARG; + } + + devAddr = (pI2CDeviceAddr_t)demod->myI2CDevAddr; + extAttr = (pDRXJData_t)demod->myExtAttr; + + /* power up */ + if ( extAttr->audData.audioIsActive == FALSE ) + { + CHK_ERROR ( PowerUpAud( demod , TRUE ) ); + extAttr->audData.audioIsActive = TRUE; + } + + RR16( devAddr, AUD_DEM_RAM_I2S_CONFIG2__A, &wI2SConfig ); + RR16( devAddr, AUD_DSP_WR_I2S_OUT_FS__A, &rI2SFreq ); + + /* I2S mode */ + switch ( wI2SConfig & AUD_DEM_WR_I2S_CONFIG2_I2S_SLV_MST__M ) + { + case AUD_DEM_WR_I2S_CONFIG2_I2S_SLV_MST_MASTER: + output->mode = DRX_I2S_MODE_MASTER; + break; + case AUD_DEM_WR_I2S_CONFIG2_I2S_SLV_MST_SLAVE: + output->mode = DRX_I2S_MODE_SLAVE; + break; + default: + return DRX_STS_ERROR; + } + + /* I2S format */ + switch ( wI2SConfig & AUD_DEM_WR_I2S_CONFIG2_I2S_WS_MODE__M ) + { + case AUD_DEM_WR_I2S_CONFIG2_I2S_WS_MODE_DELAY: + output->format = DRX_I2S_FORMAT_WS_ADVANCED; + break; + case AUD_DEM_WR_I2S_CONFIG2_I2S_WS_MODE_NO_DELAY: + output->format = DRX_I2S_FORMAT_WS_WITH_DATA; + break; + default: + return DRX_STS_ERROR; + } + + /* I2S word length */ + switch ( wI2SConfig & AUD_DEM_WR_I2S_CONFIG2_I2S_WORD_LEN__M ) + { + case AUD_DEM_WR_I2S_CONFIG2_I2S_WORD_LEN_BIT_16: + output->wordLength = DRX_I2S_WORDLENGTH_16; + break; + case AUD_DEM_WR_I2S_CONFIG2_I2S_WORD_LEN_BIT_32: + output->wordLength = DRX_I2S_WORDLENGTH_32; + break; + default: + return DRX_STS_ERROR; + } + + /* I2S polarity */ + switch ( wI2SConfig & AUD_DEM_WR_I2S_CONFIG2_I2S_WS_POL__M ) + { + case AUD_DEM_WR_I2S_CONFIG2_I2S_WS_POL_LEFT_HIGH: + output->polarity = DRX_I2S_POLARITY_LEFT; + break; + case AUD_DEM_WR_I2S_CONFIG2_I2S_WS_POL_LEFT_LOW: + output->polarity = DRX_I2S_POLARITY_RIGHT; + break; + default: + return DRX_STS_ERROR; + } + + /* I2S output enabled */ + if ( ( wI2SConfig & AUD_DEM_WR_I2S_CONFIG2_I2S_ENABLE__M ) + == AUD_DEM_WR_I2S_CONFIG2_I2S_ENABLE_ENABLE ) + { + output->outputEnable = TRUE; + } + else + { + output->outputEnable = FALSE; + } + + if ( rI2SFreq > 0 ) + { + output->frequency = 6144UL * 48000 / rI2SFreq; + if ( output->wordLength == DRX_I2S_WORDLENGTH_16 ) + { + output->frequency *= 2; + } + } + else + { + output->frequency = AUD_I2S_FREQUENCY_MAX; + } + + return DRX_STS_OK; +rw_error: + return DRX_STS_ERROR; +} + +/*============================================================================*/ +/** +* \brief Set the I2S settings +* \param demod instance of demodulator +* \param pointer to DRXCfgI2SOutput_t +* \return DRXStatus_t. +* +*/ +static DRXStatus_t +AUDCtrlSetCfgOutputI2S ( pDRXDemodInstance_t demod, + pDRXCfgI2SOutput_t output ) +{ + pI2CDeviceAddr_t devAddr = NULL; + pDRXJData_t extAttr = NULL; + + u16_t wI2SConfig = 0; + u16_t wI2SPadsDataDa = 0; + u16_t wI2SPadsDataCl = 0; + u16_t wI2SPadsDataWs = 0; + u32_t wI2SFreq = 0; + + if ( output == NULL ) + { + return DRX_STS_INVALID_ARG; + } + + devAddr = (pI2CDeviceAddr_t)demod->myI2CDevAddr; + extAttr = (pDRXJData_t)demod->myExtAttr; + + /* power up */ + if ( extAttr->audData.audioIsActive == FALSE ) + { + CHK_ERROR ( PowerUpAud( demod , TRUE ) ); + extAttr->audData.audioIsActive = TRUE; + } + + RR16( devAddr, AUD_DEM_RAM_I2S_CONFIG2__A, &wI2SConfig ); + + /* I2S mode */ + wI2SConfig &= (u16_t)~AUD_DEM_WR_I2S_CONFIG2_I2S_SLV_MST__M; + + switch ( output->mode ) + { + case DRX_I2S_MODE_MASTER: + wI2SConfig |= AUD_DEM_WR_I2S_CONFIG2_I2S_SLV_MST_MASTER; + break; + case DRX_I2S_MODE_SLAVE: + wI2SConfig |= AUD_DEM_WR_I2S_CONFIG2_I2S_SLV_MST_SLAVE; + break; + default: + return DRX_STS_INVALID_ARG; + } + + /* I2S format */ + wI2SConfig &= (u16_t)~AUD_DEM_WR_I2S_CONFIG2_I2S_WS_MODE__M; + + switch ( output->format ) + { + case DRX_I2S_FORMAT_WS_ADVANCED: + wI2SConfig |= AUD_DEM_WR_I2S_CONFIG2_I2S_WS_MODE_DELAY; + break; + case DRX_I2S_FORMAT_WS_WITH_DATA: + wI2SConfig |= AUD_DEM_WR_I2S_CONFIG2_I2S_WS_MODE_NO_DELAY; + break; + default: + return DRX_STS_INVALID_ARG; + } + + /* I2S word length */ + wI2SConfig &= (u16_t)~AUD_DEM_WR_I2S_CONFIG2_I2S_WORD_LEN__M; + + switch ( output->wordLength ) + { + case DRX_I2S_WORDLENGTH_16: + wI2SConfig |= AUD_DEM_WR_I2S_CONFIG2_I2S_WORD_LEN_BIT_16; + break; + case DRX_I2S_WORDLENGTH_32: + wI2SConfig |= AUD_DEM_WR_I2S_CONFIG2_I2S_WORD_LEN_BIT_32; + break; + default: + return DRX_STS_INVALID_ARG; + } + + /* I2S polarity */ + wI2SConfig &= (u16_t)~AUD_DEM_WR_I2S_CONFIG2_I2S_WS_POL__M; + switch ( output->polarity ) + { + case DRX_I2S_POLARITY_LEFT: + wI2SConfig |= AUD_DEM_WR_I2S_CONFIG2_I2S_WS_POL_LEFT_HIGH; + break; + case DRX_I2S_POLARITY_RIGHT: + wI2SConfig |= AUD_DEM_WR_I2S_CONFIG2_I2S_WS_POL_LEFT_LOW; + break; + default: + return DRX_STS_INVALID_ARG; + } + + /* I2S output enabled */ + wI2SConfig &= (u16_t)~AUD_DEM_WR_I2S_CONFIG2_I2S_ENABLE__M; + if ( output->outputEnable == TRUE ) + { + wI2SConfig |= AUD_DEM_WR_I2S_CONFIG2_I2S_ENABLE_ENABLE; + } + else + { + wI2SConfig |= AUD_DEM_WR_I2S_CONFIG2_I2S_ENABLE_DISABLE; + } + + /* + I2S frequency + + wI2SFreq = 6144 * 48000 * nrbits / ( 32 * frequency ) + + 16bit: 6144 * 48000 / ( 2 * freq ) = ( 6144 * 48000 / freq ) / 2 + 32bit: 6144 * 48000 / freq = ( 6144 * 48000 / freq ) + */ + if ( ( output->frequency > AUD_I2S_FREQUENCY_MAX ) || + output->frequency < AUD_I2S_FREQUENCY_MIN ) + { + return DRX_STS_INVALID_ARG; + } + + wI2SFreq = (6144UL * 48000UL) + (output->frequency >> 1); + wI2SFreq /= output->frequency; + + if ( output->wordLength == DRX_I2S_WORDLENGTH_16 ) + { + wI2SFreq *= 2; + } + + WR16( devAddr, AUD_DEM_WR_I2S_CONFIG2__A, wI2SConfig ); + WR16( devAddr, AUD_DSP_WR_I2S_OUT_FS__A, (u16_t) wI2SFreq ); + + /* configure I2S output pads for master or slave mode */ + WR16( devAddr, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY ); + + if (output->mode == DRX_I2S_MODE_MASTER) + { + wI2SPadsDataDa = SIO_PDR_I2S_DA_CFG_MODE__MASTER | + SIO_PDR_I2S_DA_CFG_DRIVE__MASTER; + wI2SPadsDataCl = SIO_PDR_I2S_CL_CFG_MODE__MASTER | + SIO_PDR_I2S_CL_CFG_DRIVE__MASTER; + wI2SPadsDataWs = SIO_PDR_I2S_WS_CFG_MODE__MASTER | + SIO_PDR_I2S_WS_CFG_DRIVE__MASTER; + } + else + { + wI2SPadsDataDa = SIO_PDR_I2S_DA_CFG_MODE__SLAVE | + SIO_PDR_I2S_DA_CFG_DRIVE__SLAVE; + wI2SPadsDataCl = SIO_PDR_I2S_CL_CFG_MODE__SLAVE | + SIO_PDR_I2S_CL_CFG_DRIVE__SLAVE; + wI2SPadsDataWs = SIO_PDR_I2S_WS_CFG_MODE__SLAVE | + SIO_PDR_I2S_WS_CFG_DRIVE__SLAVE; + } + + WR16( devAddr, SIO_PDR_I2S_DA_CFG__A, wI2SPadsDataDa ); + WR16( devAddr, SIO_PDR_I2S_CL_CFG__A, wI2SPadsDataCl ); + WR16( devAddr, SIO_PDR_I2S_WS_CFG__A, wI2SPadsDataWs ); + + WR16( devAddr, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY__PRE ); + + + /* all done, store config in data structure */ + extAttr->audData.i2sdata = *output; + + return DRX_STS_OK; +rw_error: + return DRX_STS_ERROR; +} + +/*============================================================================*/ +/** +* \brief Get the Automatic Standard Select (ASS) +* and Automatic Sound Change (ASC) +* \param demod instance of demodulator +* \param pointer to pDRXAudAutoSound_t +* \return DRXStatus_t. +* +*/ +static DRXStatus_t +AUDCtrlGetCfgAutoSound ( pDRXDemodInstance_t demod, + pDRXCfgAudAutoSound_t autoSound ) +{ + pI2CDeviceAddr_t devAddr = (pI2CDeviceAddr_t)NULL; + pDRXJData_t extAttr = (pDRXJData_t)NULL; + + u16_t rModus = 0; + + if ( autoSound == NULL ) + { + return DRX_STS_INVALID_ARG; + } + + devAddr = demod->myI2CDevAddr; + extAttr = (pDRXJData_t)demod->myExtAttr; + + /* power up */ + if ( extAttr->audData.audioIsActive == FALSE ) + { + CHK_ERROR ( PowerUpAud( demod , TRUE ) ); + extAttr->audData.audioIsActive = TRUE; + } + + CHK_ERROR ( AUDGetModus ( demod, &rModus )); + + switch ( rModus & ( AUD_DEM_WR_MODUS_MOD_ASS__M | + AUD_DEM_WR_MODUS_MOD_DIS_STD_CHG__M ) ) + { + case AUD_DEM_WR_MODUS_MOD_ASS_OFF | + AUD_DEM_WR_MODUS_MOD_DIS_STD_CHG_DISABLED: + case AUD_DEM_WR_MODUS_MOD_ASS_OFF | + AUD_DEM_WR_MODUS_MOD_DIS_STD_CHG_ENABLED: + *autoSound = DRX_AUD_AUTO_SOUND_OFF; + break; + case AUD_DEM_WR_MODUS_MOD_ASS_ON | + AUD_DEM_WR_MODUS_MOD_DIS_STD_CHG_ENABLED: + *autoSound = DRX_AUD_AUTO_SOUND_SELECT_ON_CHANGE_ON; + break; + case AUD_DEM_WR_MODUS_MOD_ASS_ON | + AUD_DEM_WR_MODUS_MOD_DIS_STD_CHG_DISABLED: + *autoSound = DRX_AUD_AUTO_SOUND_SELECT_ON_CHANGE_OFF; + break; + default: + return DRX_STS_ERROR; + } + + + return DRX_STS_OK; +rw_error: + return DRX_STS_ERROR; +} +/*============================================================================*/ +/** +* \brief Set the Automatic Standard Select (ASS) +* and Automatic Sound Change (ASC) +* \param demod instance of demodulator +* \param pointer to pDRXAudAutoSound_t +* \return DRXStatus_t. +* +*/ +static DRXStatus_t +AUDCtrSetlCfgAutoSound ( pDRXDemodInstance_t demod, + pDRXCfgAudAutoSound_t autoSound ) +{ + pI2CDeviceAddr_t devAddr = (pI2CDeviceAddr_t)NULL; + pDRXJData_t extAttr = (pDRXJData_t)NULL; + + u16_t rModus = 0; + u16_t wModus = 0; + + if ( autoSound == NULL ) + { + return DRX_STS_INVALID_ARG; + } + + devAddr = demod->myI2CDevAddr; + extAttr = (pDRXJData_t)demod->myExtAttr; + + /* power up */ + if ( extAttr->audData.audioIsActive == FALSE ) + { + CHK_ERROR ( PowerUpAud( demod , TRUE ) ); + extAttr->audData.audioIsActive = TRUE; + } + + + CHK_ERROR ( AUDGetModus ( demod, &rModus )); + + wModus = rModus; + /* clear ASS & ASC bits */ + wModus &= (u16_t)~AUD_DEM_WR_MODUS_MOD_ASS__M; + wModus &= (u16_t)~AUD_DEM_WR_MODUS_MOD_DIS_STD_CHG__M; + + switch ( *autoSound ) + { + case DRX_AUD_AUTO_SOUND_OFF: + wModus |= AUD_DEM_WR_MODUS_MOD_ASS_OFF; + wModus |= AUD_DEM_WR_MODUS_MOD_DIS_STD_CHG_DISABLED; + break; + case DRX_AUD_AUTO_SOUND_SELECT_ON_CHANGE_ON: + wModus |= AUD_DEM_WR_MODUS_MOD_ASS_ON; + wModus |= AUD_DEM_WR_MODUS_MOD_DIS_STD_CHG_ENABLED; + break; + case DRX_AUD_AUTO_SOUND_SELECT_ON_CHANGE_OFF: + wModus |= AUD_DEM_WR_MODUS_MOD_ASS_ON; + wModus |= AUD_DEM_WR_MODUS_MOD_DIS_STD_CHG_DISABLED; + break; + default: + return DRX_STS_INVALID_ARG; + } + + if ( wModus != rModus ) + { + WR16( devAddr, AUD_DEM_WR_MODUS__A, wModus ); + } + /* copy to data structure */ + extAttr->audData.autoSound = *autoSound; + + return DRX_STS_OK; +rw_error: + return DRX_STS_ERROR; +} + +/*============================================================================*/ +/** +* \brief Get the Automatic Standard Select thresholds +* \param demod instance of demodulator +* \param pointer to pDRXAudASSThres_t +* \return DRXStatus_t. +* +*/ +static DRXStatus_t +AUDCtrlGetCfgASSThres ( pDRXDemodInstance_t demod, + pDRXCfgAudASSThres_t thres ) +{ + pI2CDeviceAddr_t devAddr = (pI2CDeviceAddr_t)NULL; + pDRXJData_t extAttr = (pDRXJData_t)NULL; + + u16_t thresA2 = 0; + u16_t thresBtsc = 0; + u16_t thresNicam = 0; + + if ( thres == NULL ) + { + return DRX_STS_INVALID_ARG; + } + + devAddr = demod->myI2CDevAddr; + extAttr = (pDRXJData_t)demod->myExtAttr; + + /* power up */ + if ( extAttr->audData.audioIsActive == FALSE ) + { + CHK_ERROR ( PowerUpAud( demod , TRUE ) ); + extAttr->audData.audioIsActive = TRUE; + } + + RR16( devAddr , AUD_DEM_RAM_A2_THRSHLD__A, &thresA2 ); + RR16( devAddr , AUD_DEM_RAM_BTSC_THRSHLD__A, &thresBtsc ); + RR16( devAddr , AUD_DEM_RAM_NICAM_THRSHLD__A, &thresNicam ); + + thres->a2 = thresA2; + thres->btsc = thresBtsc; + thres->nicam = thresNicam; + + + return DRX_STS_OK; +rw_error: + return DRX_STS_ERROR; +} + +/*============================================================================*/ +/** +* \brief Get the Automatic Standard Select thresholds +* \param demod instance of demodulator +* \param pointer to pDRXAudASSThres_t +* \return DRXStatus_t. +* +*/ +static DRXStatus_t +AUDCtrlSetCfgASSThres ( pDRXDemodInstance_t demod, + pDRXCfgAudASSThres_t thres ) +{ + pI2CDeviceAddr_t devAddr = (pI2CDeviceAddr_t)NULL; + pDRXJData_t extAttr = (pDRXJData_t)NULL; + + if ( thres == NULL ) + { + return DRX_STS_INVALID_ARG; + } + + devAddr = demod->myI2CDevAddr; + extAttr = (pDRXJData_t)demod->myExtAttr; + + /* power up */ + if ( extAttr->audData.audioIsActive == FALSE ) + { + CHK_ERROR ( PowerUpAud( demod , TRUE ) ); + extAttr->audData.audioIsActive = TRUE; + } + + WR16( devAddr , AUD_DEM_WR_A2_THRSHLD__A, thres->a2 ); + WR16( devAddr , AUD_DEM_WR_BTSC_THRSHLD__A, thres->btsc ); + WR16( devAddr , AUD_DEM_WR_NICAM_THRSHLD__A, thres->nicam ); + + /* update DRXK data structure with hardware values */ + extAttr->audData.assThresholds = *thres; + + return DRX_STS_OK; +rw_error: + return DRX_STS_ERROR; +} + +/*============================================================================*/ +/** +* \brief Get Audio Carrier settings +* \param demod instance of demodulator +* \param pointer to pDRXAudCarrier_t +* \return DRXStatus_t. +* +*/ +static DRXStatus_t +AUDCtrlGetCfgCarrier ( pDRXDemodInstance_t demod, + pDRXCfgAudCarriers_t carriers ) +{ + pI2CDeviceAddr_t devAddr = (pI2CDeviceAddr_t)NULL; + pDRXJData_t extAttr = (pDRXJData_t)NULL; + + u16_t wModus = 0; + + u16_t dcoAHi = 0; + u16_t dcoALo = 0; + u16_t dcoBHi = 0; + u16_t dcoBLo = 0; + + u32_t valA = 0; + u32_t valB = 0; + + u16_t dcLvlA = 0; + u16_t dcLvlB = 0; + + u16_t cmThesA = 0; + u16_t cmThesB = 0; + + if ( carriers == NULL ) + { + return DRX_STS_INVALID_ARG; + } + + devAddr = demod->myI2CDevAddr; + extAttr = (pDRXJData_t)demod->myExtAttr; + + /* power up */ + if ( extAttr->audData.audioIsActive == FALSE ) + { + CHK_ERROR ( PowerUpAud( demod , TRUE ) ); + extAttr->audData.audioIsActive = TRUE; + } + + CHK_ERROR ( AUDGetModus ( demod, &wModus )); + + /* Behaviour of primary audio channel */ + switch ( wModus & ( AUD_DEM_WR_MODUS_MOD_CM_A__M) ) + { + case AUD_DEM_WR_MODUS_MOD_CM_A_MUTE: + carriers->a.opt = DRX_NO_CARRIER_MUTE; + break; + case AUD_DEM_WR_MODUS_MOD_CM_A_NOISE: + carriers->a.opt = DRX_NO_CARRIER_NOISE; + break; + default: + return DRX_STS_ERROR; + break; + } + + /* Behaviour of secondary audio channel */ + switch ( wModus & ( AUD_DEM_WR_MODUS_MOD_CM_B__M) ) + { + case AUD_DEM_WR_MODUS_MOD_CM_B_MUTE: + carriers->b.opt = DRX_NO_CARRIER_MUTE; + break; + case AUD_DEM_WR_MODUS_MOD_CM_B_NOISE: + carriers->b.opt = DRX_NO_CARRIER_NOISE; + break; + default: + return DRX_STS_ERROR; + break; + } + + /* frequency adjustment for primary & secondary audio channel */ + RR16( devAddr, AUD_DEM_RAM_DCO_A_HI__A, &dcoAHi ); + RR16( devAddr, AUD_DEM_RAM_DCO_A_LO__A, &dcoALo ); + RR16( devAddr, AUD_DEM_RAM_DCO_B_HI__A, &dcoBHi ); + RR16( devAddr, AUD_DEM_RAM_DCO_B_LO__A, &dcoBLo ); + + valA = ( ( (u32_t) dcoAHi) << 12 ) | ( (u32_t) dcoALo & 0xFFF ); + valB = ( ( (u32_t) dcoBHi) << 12 ) | ( (u32_t) dcoBLo & 0xFFF ); + + /* Multiply by 20250 * 1>>24 ~= 2 / 1657 */ + carriers->a.dco = DRX_S24TODRXFREQ( valA ) * 2L / 1657L; + carriers->b.dco = DRX_S24TODRXFREQ( valB ) * 2L / 1657L; + + /* DC level of the incoming FM signal on the primary + & seconday sound channel */ + RR16( devAddr, AUD_DSP_RD_FM_DC_LEVEL_A__A, &dcLvlA ); + RR16( devAddr, AUD_DSP_RD_FM_DC_LEVEL_B__A, &dcLvlB ); + + /* offset (kHz) = (dcLvl / 322) */ + carriers->a.shift = ( DRX_U16TODRXFREQ( dcLvlA ) / 322L ); + carriers->b.shift = ( DRX_U16TODRXFREQ( dcLvlB ) / 322L ); + + /* Carrier detetcion threshold for primary & secondary channel */ + RR16( devAddr, AUD_DEM_RAM_CM_A_THRSHLD__A, &cmThesA); + RR16( devAddr, AUD_DEM_RAM_CM_B_THRSHLD__A, &cmThesB); + + carriers->a.thres = cmThesA; + carriers->b.thres = cmThesB; + + return DRX_STS_OK; +rw_error: + return DRX_STS_ERROR; +} + +/*============================================================================*/ +/** +* \brief Set Audio Carrier settings +* \param demod instance of demodulator +* \param pointer to pDRXAudCarrier_t +* \return DRXStatus_t. +* +*/ +static DRXStatus_t +AUDCtrlSetCfgCarrier ( pDRXDemodInstance_t demod, + pDRXCfgAudCarriers_t carriers ) +{ + pI2CDeviceAddr_t devAddr = (pI2CDeviceAddr_t)NULL; + pDRXJData_t extAttr = (pDRXJData_t)NULL; + + u16_t wModus = 0; + u16_t rModus = 0; + + u16_t dcoAHi = 0; + u16_t dcoALo = 0; + u16_t dcoBHi = 0; + u16_t dcoBLo = 0; + + s32_t valA = 0; + s32_t valB = 0; + + if ( carriers == NULL ) + { + return DRX_STS_INVALID_ARG; + } + + devAddr = demod->myI2CDevAddr; + extAttr = (pDRXJData_t)demod->myExtAttr; + + /* power up */ + if ( extAttr->audData.audioIsActive == FALSE ) + { + CHK_ERROR ( PowerUpAud( demod , TRUE ) ); + extAttr->audData.audioIsActive = TRUE; + } + + + CHK_ERROR ( AUDGetModus ( demod, &rModus )); + + + wModus = rModus; + wModus &= (u16_t)~AUD_DEM_WR_MODUS_MOD_CM_A__M; + /* Behaviour of primary audio channel */ + switch ( carriers->a.opt ) + { + case DRX_NO_CARRIER_MUTE: + wModus |= AUD_DEM_WR_MODUS_MOD_CM_A_MUTE; + break; + case DRX_NO_CARRIER_NOISE: + wModus |= AUD_DEM_WR_MODUS_MOD_CM_A_NOISE; + break; + default: + return DRX_STS_INVALID_ARG; + break; + } + + /* Behaviour of secondary audio channel */ + wModus &= (u16_t)~AUD_DEM_WR_MODUS_MOD_CM_B__M; + switch ( carriers->b.opt ) + { + case DRX_NO_CARRIER_MUTE: + wModus |= AUD_DEM_WR_MODUS_MOD_CM_B_MUTE; + break; + case DRX_NO_CARRIER_NOISE: + wModus |= AUD_DEM_WR_MODUS_MOD_CM_B_NOISE; + break; + default: + return DRX_STS_INVALID_ARG; + break; + } + + /* now update the modus register */ + if ( wModus != rModus) + { + WR16( devAddr, AUD_DEM_WR_MODUS__A, wModus ); + } + + /* frequency adjustment for primary & secondary audio channel */ + valA = (s32_t) ( ( carriers->a.dco ) * 1657L / 2); + valB = (s32_t) ( ( carriers->b.dco ) * 1657L / 2); + + dcoAHi = (u16_t) ( ( valA >> 12 ) & 0xFFF ); + dcoALo = (u16_t) ( valA & 0xFFF ); + dcoBHi = (u16_t) ( ( valB >> 12 ) & 0xFFF ); + dcoBLo = (u16_t) ( valB & 0xFFF ); + + WR16( devAddr, AUD_DEM_WR_DCO_A_HI__A, dcoAHi ); + WR16( devAddr, AUD_DEM_WR_DCO_A_LO__A, dcoALo ); + WR16( devAddr, AUD_DEM_WR_DCO_B_HI__A, dcoBHi ); + WR16( devAddr, AUD_DEM_WR_DCO_B_LO__A, dcoBLo ); + + /* Carrier detetcion threshold for primary & secondary channel */ + WR16( devAddr, AUD_DEM_WR_CM_A_THRSHLD__A, carriers->a.thres); + WR16( devAddr, AUD_DEM_WR_CM_B_THRSHLD__A, carriers->b.thres); + + /* update DRXK data structure */ + extAttr->audData.carriers = *carriers; + + return DRX_STS_OK; +rw_error: + return DRX_STS_ERROR; +} + +/*============================================================================*/ +/** +* \brief Get I2S Source, I2S matrix and FM matrix +* \param demod instance of demodulator +* \param pointer to pDRXAudmixer_t +* \return DRXStatus_t. +* +*/ +static DRXStatus_t +AUDCtrlGetCfgMixer ( pDRXDemodInstance_t demod, + pDRXCfgAudMixer_t mixer ) +{ + pI2CDeviceAddr_t devAddr = (pI2CDeviceAddr_t)NULL; + pDRXJData_t extAttr = (pDRXJData_t)NULL; + + u16_t srcI2SMatr = 0; + u16_t fmMatr = 0; + + if ( mixer == NULL ) + { + return DRX_STS_INVALID_ARG; + } + + devAddr = demod->myI2CDevAddr; + extAttr = (pDRXJData_t)demod->myExtAttr; + + /* power up */ + if ( extAttr->audData.audioIsActive == FALSE ) + { + CHK_ERROR ( PowerUpAud( demod , TRUE ) ); + extAttr->audData.audioIsActive = TRUE; + } + + /* Source Selctor */ + RR16( devAddr, AUD_DSP_WR_SRC_I2S_MATR__A, &srcI2SMatr); + + switch ( srcI2SMatr & AUD_DSP_WR_SRC_I2S_MATR_SRC_I2S__M ) + { + case AUD_DSP_WR_SRC_I2S_MATR_SRC_I2S_MONO: + mixer->sourceI2S = DRX_AUD_SRC_MONO; + break; + case AUD_DSP_WR_SRC_I2S_MATR_SRC_I2S_STEREO_AB: + mixer->sourceI2S = DRX_AUD_SRC_STEREO_OR_AB; + break; + case AUD_DSP_WR_SRC_I2S_MATR_SRC_I2S_STEREO_A: + mixer->sourceI2S = DRX_AUD_SRC_STEREO_OR_A; + break; + case AUD_DSP_WR_SRC_I2S_MATR_SRC_I2S_STEREO_B: + mixer->sourceI2S = DRX_AUD_SRC_STEREO_OR_B; + break; + default: + return DRX_STS_ERROR; + } + + /* Matrix */ + switch ( srcI2SMatr & AUD_DSP_WR_SRC_I2S_MATR_MAT_I2S__M ) + { + case AUD_DSP_WR_SRC_I2S_MATR_MAT_I2S_MONO: + mixer->matrixI2S = DRX_AUD_I2S_MATRIX_MONO; + break; + case AUD_DSP_WR_SRC_I2S_MATR_MAT_I2S_STEREO: + mixer->matrixI2S = DRX_AUD_I2S_MATRIX_STEREO; + break; + case AUD_DSP_WR_SRC_I2S_MATR_MAT_I2S_SOUND_A: + mixer->matrixI2S = DRX_AUD_I2S_MATRIX_A_MONO; + break; + case AUD_DSP_WR_SRC_I2S_MATR_MAT_I2S_SOUND_B: + mixer->matrixI2S = DRX_AUD_I2S_MATRIX_B_MONO; + break; + default: + return DRX_STS_ERROR; + } + + /* FM Matrix */ + RR16( devAddr, AUD_DEM_WR_FM_MATRIX__A, &fmMatr ); + switch ( fmMatr & AUD_DEM_WR_FM_MATRIX__M ) + { + case AUD_DEM_WR_FM_MATRIX_NO_MATRIX: + mixer->matrixFm = DRX_AUD_FM_MATRIX_NO_MATRIX; + break; + case AUD_DEM_WR_FM_MATRIX_GERMAN_MATRIX: + mixer->matrixFm = DRX_AUD_FM_MATRIX_GERMAN; + break; + case AUD_DEM_WR_FM_MATRIX_KOREAN_MATRIX: + mixer->matrixFm = DRX_AUD_FM_MATRIX_KOREAN; + break; + case AUD_DEM_WR_FM_MATRIX_SOUND_A: + mixer->matrixFm = DRX_AUD_FM_MATRIX_SOUND_A; + break; + case AUD_DEM_WR_FM_MATRIX_SOUND_B: + mixer->matrixFm = DRX_AUD_FM_MATRIX_SOUND_B; + break; + default: + return DRX_STS_ERROR; + } + + return DRX_STS_OK; +rw_error: + return DRX_STS_ERROR; +} + +/*============================================================================*/ +/** +* \brief Set I2S Source, I2S matrix and FM matrix +* \param demod instance of demodulator +* \param pointer to DRXAudmixer_t +* \return DRXStatus_t. +* +*/ +static DRXStatus_t +AUDCtrlSetCfgMixer ( pDRXDemodInstance_t demod, + pDRXCfgAudMixer_t mixer ) + { + pI2CDeviceAddr_t devAddr = (pI2CDeviceAddr_t)NULL; + pDRXJData_t extAttr = (pDRXJData_t)NULL; + + u16_t srcI2SMatr = 0; + u16_t fmMatr = 0; + + if ( mixer == NULL ) + { + return DRX_STS_INVALID_ARG; + } + + devAddr = demod->myI2CDevAddr; + extAttr = (pDRXJData_t)demod->myExtAttr; + + /* power up */ + if ( extAttr->audData.audioIsActive == FALSE ) + { + CHK_ERROR ( PowerUpAud( demod , TRUE ) ); + extAttr->audData.audioIsActive = TRUE; + } + + /* Source Selctor */ + RR16( devAddr, AUD_DSP_WR_SRC_I2S_MATR__A, &srcI2SMatr); + srcI2SMatr &= (u16_t)~AUD_DSP_WR_SRC_I2S_MATR_SRC_I2S__M; + + switch (mixer->sourceI2S) + { + case DRX_AUD_SRC_MONO: + srcI2SMatr |= AUD_DSP_WR_SRC_I2S_MATR_SRC_I2S_MONO; + break; + case DRX_AUD_SRC_STEREO_OR_AB: + srcI2SMatr |= AUD_DSP_WR_SRC_I2S_MATR_SRC_I2S_STEREO_AB; + break; + case DRX_AUD_SRC_STEREO_OR_A: + srcI2SMatr |= AUD_DSP_WR_SRC_I2S_MATR_SRC_I2S_STEREO_A; + break; + case DRX_AUD_SRC_STEREO_OR_B: + srcI2SMatr |= AUD_DSP_WR_SRC_I2S_MATR_SRC_I2S_STEREO_B; + break; + default: + return DRX_STS_INVALID_ARG; + } + + /* Matrix */ + srcI2SMatr &= (u16_t)~AUD_DSP_WR_SRC_I2S_MATR_MAT_I2S__M; + switch (mixer->matrixI2S) + { + case DRX_AUD_I2S_MATRIX_MONO: + srcI2SMatr |= AUD_DSP_WR_SRC_I2S_MATR_MAT_I2S_MONO; + break; + case DRX_AUD_I2S_MATRIX_STEREO: + srcI2SMatr |= AUD_DSP_WR_SRC_I2S_MATR_MAT_I2S_STEREO ; + break; + case DRX_AUD_I2S_MATRIX_A_MONO: + srcI2SMatr |= AUD_DSP_WR_SRC_I2S_MATR_MAT_I2S_SOUND_A; + break; + case DRX_AUD_I2S_MATRIX_B_MONO: + srcI2SMatr |= AUD_DSP_WR_SRC_I2S_MATR_MAT_I2S_SOUND_B; + break; + default: + return DRX_STS_INVALID_ARG; + } + /* write the result */ + WR16( devAddr, AUD_DSP_WR_SRC_I2S_MATR__A, srcI2SMatr); + + /* FM Matrix */ + RR16( devAddr, AUD_DEM_WR_FM_MATRIX__A, &fmMatr ); + fmMatr &= (u16_t)~AUD_DEM_WR_FM_MATRIX__M; + switch (mixer->matrixFm) + { + case DRX_AUD_FM_MATRIX_NO_MATRIX: + fmMatr |= AUD_DEM_WR_FM_MATRIX_NO_MATRIX; + break; + case DRX_AUD_FM_MATRIX_GERMAN: + fmMatr |= AUD_DEM_WR_FM_MATRIX_GERMAN_MATRIX; + break; + case DRX_AUD_FM_MATRIX_KOREAN: + fmMatr |= AUD_DEM_WR_FM_MATRIX_KOREAN_MATRIX; + break; + case DRX_AUD_FM_MATRIX_SOUND_A: + fmMatr |= AUD_DEM_WR_FM_MATRIX_SOUND_A; + break; + case DRX_AUD_FM_MATRIX_SOUND_B: + fmMatr |= AUD_DEM_WR_FM_MATRIX_SOUND_B; + break; + default: + return DRX_STS_INVALID_ARG; + } + + /* Only write if ASS is off */ + if ( extAttr->audData.autoSound == DRX_AUD_AUTO_SOUND_OFF ) + { + WR16( devAddr, AUD_DEM_WR_FM_MATRIX__A, fmMatr ); + } + + /* update the data structure with hardware state */ + extAttr->audData.mixer = *mixer; + + return DRX_STS_OK; +rw_error: + return DRX_STS_ERROR; +} + +/*============================================================================*/ +/** +* \brief Set AV Sync settings +* \param demod instance of demodulator +* \param pointer to DRXICfgAVSync_t +* \return DRXStatus_t. +* +*/ +static DRXStatus_t +AUDCtrlSetCfgAVSync ( pDRXDemodInstance_t demod, + pDRXCfgAudAVSync_t avSync ) +{ + pI2CDeviceAddr_t devAddr = (pI2CDeviceAddr_t)NULL; + pDRXJData_t extAttr = (pDRXJData_t)NULL; + + u16_t wAudVidSync = 0; + + if ( avSync == NULL ) + { + return DRX_STS_INVALID_ARG; + } + + devAddr = demod->myI2CDevAddr; + extAttr = (pDRXJData_t)demod->myExtAttr; + + /* power up */ + if ( extAttr->audData.audioIsActive == FALSE ) + { + CHK_ERROR ( PowerUpAud( demod , TRUE ) ); + extAttr->audData.audioIsActive = TRUE; + } + + /* audio/video synchronisation */ + RR16( devAddr, AUD_DSP_WR_AV_SYNC__A, &wAudVidSync ); + + wAudVidSync &= (u16_t)~AUD_DSP_WR_AV_SYNC_AV_ON__M; + + if ( *avSync == DRX_AUD_AVSYNC_OFF ) + { + wAudVidSync |= AUD_DSP_WR_AV_SYNC_AV_ON_DISABLE; + } + else + { + wAudVidSync |= AUD_DSP_WR_AV_SYNC_AV_ON_ENABLE; + } + + wAudVidSync &= (u16_t)~AUD_DSP_WR_AV_SYNC_AV_STD_SEL__M; + + switch ( *avSync ) + { + case DRX_AUD_AVSYNC_NTSC: + wAudVidSync |= AUD_DSP_WR_AV_SYNC_AV_STD_SEL_NTSC; + break; + case DRX_AUD_AVSYNC_MONOCHROME: + wAudVidSync |= AUD_DSP_WR_AV_SYNC_AV_STD_SEL_MONOCHROME; + break; + case DRX_AUD_AVSYNC_PAL_SECAM: + wAudVidSync |= AUD_DSP_WR_AV_SYNC_AV_STD_SEL_PAL_SECAM; + break; + case DRX_AUD_AVSYNC_OFF: + /* OK */ + break; + default: + return DRX_STS_INVALID_ARG; + } + + WR16( devAddr, AUD_DSP_WR_AV_SYNC__A, wAudVidSync ); + return DRX_STS_OK; +rw_error: + return DRX_STS_ERROR; +} + +/*============================================================================*/ +/** +* \brief Get AV Sync settings +* \param demod instance of demodulator +* \param pointer to DRXICfgAVSync_t +* \return DRXStatus_t. +* +*/ +static DRXStatus_t +AUDCtrlGetCfgAVSync ( pDRXDemodInstance_t demod, + pDRXCfgAudAVSync_t avSync ) +{ + pI2CDeviceAddr_t devAddr = (pI2CDeviceAddr_t)NULL; + pDRXJData_t extAttr = (pDRXJData_t)NULL; + + u16_t wAudVidSync = 0; + + if ( avSync == NULL ) + { + return DRX_STS_INVALID_ARG; + } + + devAddr = demod->myI2CDevAddr; + extAttr = (pDRXJData_t)demod->myExtAttr; + + /* power up */ + if ( extAttr->audData.audioIsActive == FALSE ) + { + CHK_ERROR ( PowerUpAud( demod , TRUE ) ); + extAttr->audData.audioIsActive = TRUE; + } + + /* audio/video synchronisation */ + RR16( devAddr, AUD_DSP_WR_AV_SYNC__A, &wAudVidSync ); + + if ( ( wAudVidSync & AUD_DSP_WR_AV_SYNC_AV_ON__M ) == + AUD_DSP_WR_AV_SYNC_AV_ON_DISABLE ) + { + *avSync = DRX_AUD_AVSYNC_OFF; + return DRX_STS_OK; + } + + switch ( wAudVidSync & AUD_DSP_WR_AV_SYNC_AV_STD_SEL__M ) + { + case AUD_DSP_WR_AV_SYNC_AV_STD_SEL_NTSC: + *avSync = DRX_AUD_AVSYNC_NTSC; + break; + case AUD_DSP_WR_AV_SYNC_AV_STD_SEL_MONOCHROME: + *avSync = DRX_AUD_AVSYNC_MONOCHROME; + break; + case AUD_DSP_WR_AV_SYNC_AV_STD_SEL_PAL_SECAM: + *avSync = DRX_AUD_AVSYNC_PAL_SECAM; + break; + default: + return DRX_STS_ERROR; + } + + return DRX_STS_OK; +rw_error: + return DRX_STS_ERROR; +} + +/*============================================================================*/ +/** +* \brief Get deviation mode +* \param demod instance of demodulator +* \param pointer to DRXCfgAudDeviation_t +* \return DRXStatus_t. +* +*/ +static DRXStatus_t +AUDCtrlGetCfgDev ( pDRXDemodInstance_t demod, + pDRXCfgAudDeviation_t dev ) +{ + pI2CDeviceAddr_t devAddr = (pI2CDeviceAddr_t)NULL; + pDRXJData_t extAttr = (pDRXJData_t)NULL; + + u16_t rModus = 0; + + + if ( dev == NULL ) + { + return DRX_STS_INVALID_ARG; + } + + extAttr = (pDRXJData_t)demod->myExtAttr; + devAddr = demod->myI2CDevAddr; + + CHK_ERROR ( AUDGetModus ( demod, &rModus )); + + switch ( rModus & AUD_DEM_WR_MODUS_MOD_HDEV_A__M) + { + case AUD_DEM_WR_MODUS_MOD_HDEV_A_NORMAL: + *dev = DRX_AUD_DEVIATION_NORMAL; + break; + case AUD_DEM_WR_MODUS_MOD_HDEV_A_HIGH_DEVIATION: + *dev = DRX_AUD_DEVIATION_HIGH; + break; + default: + return DRX_STS_ERROR; + } + + return DRX_STS_OK; +rw_error: + return DRX_STS_ERROR; +} + +/*============================================================================*/ +/** +* \brief Get deviation mode +* \param demod instance of demodulator +* \param pointer to DRXCfgAudDeviation_t +* \return DRXStatus_t. +* +*/ +static DRXStatus_t +AUDCtrlSetCfgDev ( pDRXDemodInstance_t demod, + pDRXCfgAudDeviation_t dev ) +{ + pI2CDeviceAddr_t devAddr = (pI2CDeviceAddr_t)NULL; + pDRXJData_t extAttr = (pDRXJData_t)NULL; + + u16_t wModus = 0; + u16_t rModus = 0; + + if ( dev == NULL ) + { + return DRX_STS_INVALID_ARG; + } + + extAttr = (pDRXJData_t)demod->myExtAttr; + devAddr = demod->myI2CDevAddr; + + CHK_ERROR ( AUDGetModus ( demod, &rModus )); + + wModus = rModus; + + wModus &= (u16_t)~AUD_DEM_WR_MODUS_MOD_HDEV_A__M; + + switch ( *dev ) + { + case DRX_AUD_DEVIATION_NORMAL: + wModus |= AUD_DEM_WR_MODUS_MOD_HDEV_A_NORMAL; + break; + case DRX_AUD_DEVIATION_HIGH: + wModus |= AUD_DEM_WR_MODUS_MOD_HDEV_A_HIGH_DEVIATION; + break; + default: + return DRX_STS_INVALID_ARG; + } + + /* now update the modus register */ + if ( wModus != rModus) + { + WR16( devAddr, AUD_DEM_WR_MODUS__A, wModus ); + } + /* store in drxk data struct */ + extAttr->audData.deviation = *dev; + + return DRX_STS_OK; +rw_error: + return DRX_STS_ERROR; +} + + +/*============================================================================*/ +/** +* \brief Get Prescaler settings +* \param demod instance of demodulator +* \param pointer to DRXCfgAudPrescale_t +* \return DRXStatus_t. +* +*/ +static DRXStatus_t +AUDCtrlGetCfgPrescale( pDRXDemodInstance_t demod, + pDRXCfgAudPrescale_t presc ) +{ + pI2CDeviceAddr_t devAddr = (pI2CDeviceAddr_t)NULL; + pDRXJData_t extAttr = (pDRXJData_t)NULL; + + u16_t rMaxFMDeviation = 0; + u16_t rNicamPrescaler = 0; + + if ( presc == NULL ) + { + return DRX_STS_INVALID_ARG; + } + + devAddr = demod->myI2CDevAddr; + extAttr = (pDRXJData_t)demod->myExtAttr; + + /* power up */ + if ( extAttr->audData.audioIsActive == FALSE ) + { + CHK_ERROR ( PowerUpAud( demod , TRUE ) ); + extAttr->audData.audioIsActive = TRUE; + } + + /* read register data */ + RR16( devAddr, AUD_DSP_WR_NICAM_PRESC__A, &rNicamPrescaler ); + RR16( devAddr, AUD_DSP_WR_FM_PRESC__A, &rMaxFMDeviation ); + + /* calculate max FM deviation */ + rMaxFMDeviation >>= AUD_DSP_WR_FM_PRESC_FM_AM_PRESC__B; + if ( rMaxFMDeviation > 0 ) + { + presc->fmDeviation = 3600UL + (rMaxFMDeviation >> 1); + presc->fmDeviation /= rMaxFMDeviation; + } + else + { + presc->fmDeviation = 380; /* kHz */ + } + + /* calculate NICAM gain from pre-scaler */ + /* + nicamGain = 20 * ( log10( preScaler / 16) ) + = ( 100log10( preScaler ) - 100log10( 16 ) ) / 5 + + because Log10Times100() cannot return negative numbers + = ( 100log10( 10 * preScaler ) - 100log10( 10 * 16) ) / 5 + + + for 0.1dB resolution: + + nicamGain = 200 * ( log10( preScaler / 16) ) + = 2 * ( 100log10( 10 * preScaler ) - 100log10( 10 * 16) ) + = ( 100log10( 10 * preScaler^2 ) - 100log10( 10 * 16^2 ) ) + + + */ + rNicamPrescaler >>= 8; + if ( rNicamPrescaler <= 1 ) + { + presc->nicamGain = -241; + } + else + { + + presc->nicamGain = (s16_t)( ( (s32_t) + ( Log10Times100( 10 * rNicamPrescaler * + rNicamPrescaler ) ) - + (s32_t) + ( Log10Times100( 10 * 16 * 16 ) ) ) ); + } + + return DRX_STS_OK; +rw_error: + return DRX_STS_ERROR; +} + + +/*============================================================================*/ +/** +* \brief Set Prescaler settings +* \param demod instance of demodulator +* \param pointer to DRXCfgAudPrescale_t +* \return DRXStatus_t. +* +*/ +static DRXStatus_t +AUDCtrlSetCfgPrescale( pDRXDemodInstance_t demod, + pDRXCfgAudPrescale_t presc ) +{ + pI2CDeviceAddr_t devAddr = (pI2CDeviceAddr_t)NULL; + pDRXJData_t extAttr = (pDRXJData_t)NULL; + + u16_t wMaxFMDeviation = 0; + u16_t nicamPrescaler; + + if ( presc == NULL ) + { + return DRX_STS_INVALID_ARG; + } + + devAddr = demod->myI2CDevAddr; + extAttr = (pDRXJData_t)demod->myExtAttr; + + /* power up */ + if ( extAttr->audData.audioIsActive == FALSE ) + { + CHK_ERROR ( PowerUpAud( demod , TRUE ) ); + extAttr->audData.audioIsActive = TRUE; + } + + /* setting of max FM deviation */ + wMaxFMDeviation = (u16_t)(Frac (3600UL, presc->fmDeviation, 0)); + wMaxFMDeviation <<= AUD_DSP_WR_FM_PRESC_FM_AM_PRESC__B; + if ( wMaxFMDeviation >= AUD_DSP_WR_FM_PRESC_FM_AM_PRESC_28_KHZ_FM_DEVIATION ) + { + wMaxFMDeviation = AUD_DSP_WR_FM_PRESC_FM_AM_PRESC_28_KHZ_FM_DEVIATION; + } + + /* NICAM Prescaler */ + if( ( presc->nicamGain >= -241) && ( presc->nicamGain <= 180) ) + { + /* calculation + + prescaler = 16 * 10^( GdB / 20 ) + + minval of GdB = -20*log( 16 ) = -24.1dB + + negative numbers not allowed for dB2LinTimes100, so + + prescaler = 16 * 10^( GdB / 20 ) + = 10^( (GdB / 20) + log10(16) ) + = 10^( (GdB + 20log10(16)) / 20 ) + + in 0.1dB + + = 10^( G0.1dB + 200log10(16)) / 200 ) + + */ + nicamPrescaler = (u16_t) + ( ( dB2LinTimes100( presc->nicamGain + 241UL ) + 50UL ) / 100UL ); + + /* clip result */ + if ( nicamPrescaler > 127 ) + { + nicamPrescaler = 127; + } + + /* shift before writing to register */ + nicamPrescaler <<= 8; + } + else + { + return(DRX_STS_INVALID_ARG); + } + /* end of setting NICAM Prescaler */ + + WR16( devAddr, AUD_DSP_WR_NICAM_PRESC__A, nicamPrescaler ); + WR16( devAddr, AUD_DSP_WR_FM_PRESC__A, wMaxFMDeviation ); + + extAttr->audData.prescale = *presc; + + return DRX_STS_OK; +rw_error: + return DRX_STS_ERROR; +} + +/*============================================================================*/ +/** +* \brief Beep +* \param demod instance of demodulator +* \param pointer to DRXAudBeep_t +* \return DRXStatus_t. +* +*/ +static DRXStatus_t +AUDCtrlBeep ( pDRXDemodInstance_t demod, + pDRXAudBeep_t beep ) +{ + pI2CDeviceAddr_t devAddr = (pI2CDeviceAddr_t)NULL; + pDRXJData_t extAttr = (pDRXJData_t)NULL; + + u16_t theBeep = 0; + u16_t volume = 0; + u32_t frequency = 0; + + + if ( beep == NULL ) + { + return DRX_STS_INVALID_ARG; + } + + devAddr = demod->myI2CDevAddr; + extAttr = (pDRXJData_t)demod->myExtAttr; + + /* power up */ + if ( extAttr->audData.audioIsActive == FALSE ) + { + CHK_ERROR ( PowerUpAud( demod , TRUE ) ); + extAttr->audData.audioIsActive = TRUE; + } + + if (( beep->volume > 0 ) || ( beep->volume < -127 )) + { + return DRX_STS_INVALID_ARG; + } + + if ( beep->frequency > 3000 ) + { + return DRX_STS_INVALID_ARG; + } + + volume = (u16_t)beep->volume + 127; + theBeep |= volume << AUD_DSP_WR_BEEPER_BEEP_VOLUME__B; + + + frequency = ( (u32_t) beep->frequency ) * 23 / 500 ; + if ( frequency > AUD_DSP_WR_BEEPER_BEEP_FREQUENCY__M ) + { + frequency = AUD_DSP_WR_BEEPER_BEEP_FREQUENCY__M; + } + theBeep |= (u16_t) frequency; + + if ( beep->mute == TRUE ) + { + theBeep = 0; + } + + WR16( devAddr, AUD_DSP_WR_BEEPER__A, theBeep); + + return DRX_STS_OK; +rw_error: + return DRX_STS_ERROR; +} + +/*============================================================================*/ +/** +* \brief Set an audio standard +* \param demod instance of demodulator +* \param pointer to DRXAudStandard_t +* \return DRXStatus_t. +* +*/ +static DRXStatus_t +AUDCtrlSetStandard ( pDRXDemodInstance_t demod, + pDRXAudStandard_t standard ) +{ + pI2CDeviceAddr_t devAddr = NULL; + pDRXJData_t extAttr = NULL; + DRXStandard_t currentStandard = DRX_STANDARD_UNKNOWN; + + u16_t wStandard = 0; + u16_t wModus = 0; + u16_t rModus = 0; + + Bool_t muteBuffer = FALSE; + s16_t volumeBuffer = 0; + u16_t wVolume = 0; + + if ( standard == NULL ) + { + return DRX_STS_INVALID_ARG; + } + + devAddr = (pI2CDeviceAddr_t)demod->myI2CDevAddr; + extAttr = (pDRXJData_t)demod->myExtAttr; + + /* power up */ + if ( extAttr->audData.audioIsActive == FALSE ) + { + CHK_ERROR ( PowerUpAud( demod , FALSE ) ); + extAttr->audData.audioIsActive = TRUE; + } + + + /* reset RDS data availability flag */ + extAttr->audData.rdsDataPresent = FALSE; + + + /* we need to mute from here to avoid noise during standard switching */ + muteBuffer = extAttr->audData.volume.mute; + volumeBuffer = extAttr->audData.volume.volume; + + extAttr->audData.volume.mute = TRUE; + /* restore data structure from DRX ExtAttr, call volume first to mute */ + CHK_ERROR ( AUDCtrlSetCfgVolume + ( demod, &extAttr->audData.volume ) ); + CHK_ERROR ( AUDCtrlSetCfgCarrier + ( demod, &extAttr->audData.carriers ) ); + CHK_ERROR ( AUDCtrlSetCfgASSThres + ( demod, &extAttr->audData.assThresholds ) ); + CHK_ERROR ( AUDCtrSetlCfgAutoSound + ( demod, &extAttr->audData.autoSound ) ); + CHK_ERROR ( AUDCtrlSetCfgMixer + ( demod, &extAttr->audData.mixer ) ); + CHK_ERROR ( AUDCtrlSetCfgAVSync + ( demod, &extAttr->audData.avSync ) ); + CHK_ERROR ( AUDCtrlSetCfgOutputI2S + ( demod, &extAttr->audData.i2sdata ) ); + + /* get prescaler from presets */ + CHK_ERROR ( AUDCtrlSetCfgPrescale + ( demod, &extAttr->audData.prescale) ); + + CHK_ERROR ( AUDGetModus ( demod, &rModus )); + + wModus = rModus; + + switch ( *standard ) + { + case DRX_AUD_STANDARD_AUTO: + wStandard = AUD_DEM_WR_STANDARD_SEL_STD_SEL_AUTO; + break; + case DRX_AUD_STANDARD_BTSC: + wStandard = AUD_DEM_WR_STANDARD_SEL_STD_SEL_BTSC_STEREO; + if (extAttr->audData.btscDetect == DRX_BTSC_MONO_AND_SAP) + { + wStandard = AUD_DEM_WR_STANDARD_SEL_STD_SEL_BTSC_SAP; + } + break; + case DRX_AUD_STANDARD_A2: + wStandard = AUD_DEM_WR_STANDARD_SEL_STD_SEL_M_KOREA; + break; + case DRX_AUD_STANDARD_EIAJ: + wStandard = AUD_DEM_WR_STANDARD_SEL_STD_SEL_EIA_J; + break; + case DRX_AUD_STANDARD_FM_STEREO: + wStandard = AUD_DEM_WR_STANDARD_SEL_STD_SEL_FM_RADIO; + break; + case DRX_AUD_STANDARD_BG_FM: + wStandard = AUD_DEM_WR_STANDARD_SEL_STD_SEL_BG_FM; + break; + case DRX_AUD_STANDARD_D_K1: + wStandard = AUD_DEM_WR_STANDARD_SEL_STD_SEL_D_K1; + break; + case DRX_AUD_STANDARD_D_K2: + wStandard = AUD_DEM_WR_STANDARD_SEL_STD_SEL_D_K2; + break; + case DRX_AUD_STANDARD_D_K3: + wStandard = AUD_DEM_WR_STANDARD_SEL_STD_SEL_D_K3; + break; + case DRX_AUD_STANDARD_BG_NICAM_FM: + wStandard = AUD_DEM_WR_STANDARD_SEL_STD_SEL_BG_NICAM_FM; + break; + case DRX_AUD_STANDARD_L_NICAM_AM: + wStandard = AUD_DEM_WR_STANDARD_SEL_STD_SEL_L_NICAM_AM; + break; + case DRX_AUD_STANDARD_I_NICAM_FM: + wStandard = AUD_DEM_WR_STANDARD_SEL_STD_SEL_I_NICAM_FM; + break; + case DRX_AUD_STANDARD_D_K_NICAM_FM: + wStandard = AUD_DEM_WR_STANDARD_SEL_STD_SEL_D_K_NICAM_FM; + break; + case DRX_AUD_STANDARD_UNKNOWN: + wStandard = AUD_DEM_WR_STANDARD_SEL_STD_SEL_AUTO; + break; + default: + return DRX_STS_ERROR; + } + + if ( *standard == DRX_AUD_STANDARD_AUTO ) + { + /* we need the current standard here */ + currentStandard = extAttr->standard; + + + wModus &= (u16_t)~AUD_DEM_WR_MODUS_MOD_6_5MHZ__M; + + if ( ( currentStandard == DRX_STANDARD_PAL_SECAM_L ) || + ( currentStandard == DRX_STANDARD_PAL_SECAM_LP ) ) + { + wModus |= (AUD_DEM_WR_MODUS_MOD_6_5MHZ_SECAM); + } + else + { + wModus |= (AUD_DEM_WR_MODUS_MOD_6_5MHZ_D_K); + } + + wModus &= (u16_t)~AUD_DEM_WR_MODUS_MOD_4_5MHZ__M; + if ( currentStandard == DRX_STANDARD_NTSC ) + { + wModus |= ( AUD_DEM_WR_MODUS_MOD_4_5MHZ_M_BTSC); + + } + else /* non USA, ignore standard M to save time */ + { + wModus |= ( AUD_DEM_WR_MODUS_MOD_4_5MHZ_CHROMA); + } + + + } + + wModus &= (u16_t)~AUD_DEM_WR_MODUS_MOD_FMRADIO__M; + + /* just get hardcoded deemphasis and activate here */ + if ( extAttr->audData.deemph == DRX_AUD_FM_DEEMPH_50US ) + { + wModus |= ( AUD_DEM_WR_MODUS_MOD_FMRADIO_EU_50U); + } + else + { + wModus |= ( AUD_DEM_WR_MODUS_MOD_FMRADIO_US_75U); + } + + wModus &= (u16_t)~AUD_DEM_WR_MODUS_MOD_BTSC__M; + if( extAttr->audData.btscDetect == DRX_BTSC_STEREO ) + { + wModus |= ( AUD_DEM_WR_MODUS_MOD_BTSC_BTSC_STEREO); + } + else /* DRX_BTSC_MONO_AND_SAP */ + { + wModus |= ( AUD_DEM_WR_MODUS_MOD_BTSC_BTSC_SAP); + } + + if ( wModus != rModus) + { + WR16( devAddr, AUD_DEM_WR_MODUS__A, wModus ); + } + + WR16( devAddr, AUD_DEM_WR_STANDARD_SEL__A, wStandard ); + + /**************************************************************************/ + /* NOT calling AUDCtrlSetCfgVolume to avoid interfering standard */ + /* detection, need to keep things very minimal here, but keep audio */ + /* buffers intact */ + /**************************************************************************/ + extAttr->audData.volume.mute = muteBuffer; + if ( extAttr->audData.volume.mute == FALSE ) + { + wVolume |= (u16_t) ( ( volumeBuffer + AUD_VOLUME_ZERO_DB ) << + AUD_DSP_WR_VOLUME_VOL_MAIN__B ); + WR16( devAddr, AUD_DSP_WR_VOLUME__A, wVolume ); + } + + /* write standard selected */ + extAttr->audData.audioStandard = *standard; + + return DRX_STS_OK; +rw_error: + return DRX_STS_ERROR; +} + +/*============================================================================*/ +/** +* \brief Get the current audio standard +* \param demod instance of demodulator +* \param pointer to DRXAudStandard_t +* \return DRXStatus_t. +* +*/ +static DRXStatus_t +AUDCtrlGetStandard ( pDRXDemodInstance_t demod, + pDRXAudStandard_t standard ) +{ + pI2CDeviceAddr_t devAddr = NULL; + pDRXJData_t extAttr = NULL; + + u16_t rData = 0; + + if ( standard == NULL ) + { + return DRX_STS_INVALID_ARG; + } + + extAttr = (pDRXJData_t)demod->myExtAttr; + devAddr = (pI2CDeviceAddr_t)demod->myI2CDevAddr; + + /* power up */ + if ( extAttr->audData.audioIsActive == FALSE ) + { + CHK_ERROR ( PowerUpAud( demod , TRUE ) ); + extAttr->audData.audioIsActive = TRUE; + } + + *standard = DRX_AUD_STANDARD_UNKNOWN; + + RR16( devAddr, AUD_DEM_RD_STANDARD_RES__A, &rData ); + + /* return OK if the detection is not ready yet */ + if ( rData >= + AUD_DEM_RD_STANDARD_RES_STD_RESULT_DETECTION_STILL_ACTIVE ) + { + *standard = DRX_AUD_STANDARD_NOT_READY; + return DRX_STS_OK; + } + + /* detection done, return correct standard */ + switch ( rData ) + { + /* no standard detected */ + case AUD_DEM_RD_STANDARD_RES_STD_RESULT_NO_SOUND_STANDARD: + *standard = DRX_AUD_STANDARD_UNKNOWN; + break; + /* standard is KOREA(A2) */ + case AUD_DEM_RD_STANDARD_RES_STD_RESULT_NTSC_M_DUAL_CARRIER_FM: + *standard = DRX_AUD_STANDARD_A2; + break; + /* standard is EIA-J (Japan) */ + case AUD_DEM_RD_STANDARD_RES_STD_RESULT_NTSC_EIA_J: + *standard = DRX_AUD_STANDARD_EIAJ; + break; + /* standard is BTSC-stereo */ + case AUD_DEM_RD_STANDARD_RES_STD_RESULT_BTSC_STEREO: + *standard = DRX_AUD_STANDARD_BTSC; + break; + /* standard is BTSC-mono (SAP) */ + case AUD_DEM_RD_STANDARD_RES_STD_RESULT_BTSC_MONO_SAP: + *standard = DRX_AUD_STANDARD_BTSC; + break; + /* standard is FM radio */ + case AUD_DEM_RD_STANDARD_RES_STD_RESULT_FM_RADIO: + *standard = DRX_AUD_STANDARD_FM_STEREO; + break; + /* standard is BG FM */ + case AUD_DEM_RD_STANDARD_RES_STD_RESULT_B_G_DUAL_CARRIER_FM: + *standard = DRX_AUD_STANDARD_BG_FM; + break; + /* standard is DK-1 FM */ + case AUD_DEM_RD_STANDARD_RES_STD_RESULT_D_K1_DUAL_CARRIER_FM: + *standard = DRX_AUD_STANDARD_D_K1; + break; + /* standard is DK-2 FM */ + case AUD_DEM_RD_STANDARD_RES_STD_RESULT_D_K2_DUAL_CARRIER_FM: + *standard = DRX_AUD_STANDARD_D_K2; + break; + /* standard is DK-3 FM */ + case AUD_DEM_RD_STANDARD_RES_STD_RESULT_D_K3_DUAL_CARRIER_FM: + *standard = DRX_AUD_STANDARD_D_K3; + break; + /* standard is BG-NICAM FM */ + case AUD_DEM_RD_STANDARD_RES_STD_RESULT_B_G_NICAM_FM: + *standard = DRX_AUD_STANDARD_BG_NICAM_FM; + break; + /* standard is L-NICAM AM */ + case AUD_DEM_RD_STANDARD_RES_STD_RESULT_L_NICAM_AM: + *standard = DRX_AUD_STANDARD_L_NICAM_AM; + break; + /* standard is I-NICAM FM */ + case AUD_DEM_RD_STANDARD_RES_STD_RESULT_I_NICAM_FM: + *standard = DRX_AUD_STANDARD_I_NICAM_FM; + break; + /* standard is DK-NICAM FM */ + case AUD_DEM_RD_STANDARD_RES_STD_RESULT_D_K_NICAM_FM: + *standard = DRX_AUD_STANDARD_D_K_NICAM_FM; + break; + default: + *standard = DRX_AUD_STANDARD_UNKNOWN; + } + + return DRX_STS_OK; +rw_error: + return DRX_STS_ERROR; + +} + + +/*============================================================================*/ +/** +* \brief Retreive lock status in case of FM standard +* \param demod instance of demodulator +* \param pointer to lock status +* \return DRXStatus_t. +* +*/ +static DRXStatus_t +FmLockStatus( pDRXDemodInstance_t demod, + pDRXLockStatus_t lockStat ) +{ + DRXAudStatus_t status; + + /* Check detection of audio carriers */ + CHK_ERROR( AUDCtrlGetCarrierDetectStatus ( demod, &status ) ); + + /* locked if either primary or secondary carrier is detected */ + if ( ( status.carrierA == TRUE ) || + ( status.carrierB == TRUE ) ) + { + *lockStat = DRX_LOCKED; + } else { + *lockStat = DRX_NOT_LOCKED; + } + + return (DRX_STS_OK); + +rw_error: + return (DRX_STS_ERROR); +} + +/*============================================================================*/ +/** +* \brief retreive signal quality in case of FM standard +* \param demod instance of demodulator +* \param pointer to signal quality +* \return DRXStatus_t. +* +* Only the quality indicator field is will be supplied. +* This will either be 0% or 100%, nothing in between. +* +*/ +static DRXStatus_t +FmSigQuality( pDRXDemodInstance_t demod, + pDRXSigQuality_t sigQuality ) +{ + DRXLockStatus_t lockStatus = DRX_NOT_LOCKED; + + CHK_ERROR( FmLockStatus( demod, &lockStatus ) ); + if ( lockStatus == DRX_LOCKED ) + { + sigQuality->indicator = 100; + } else { + sigQuality->indicator = 0; + } + + return (DRX_STS_OK); + +rw_error: + return (DRX_STS_ERROR); +} + +#endif + + +/*===========================================================================*/ +/*== END AUDIO DATAPATH FUNCTIONS ==*/ +/*===========================================================================*/ + +/*============================================================================*/ +/*============================================================================*/ +/*== OOB DATAPATH FUNCTIONS ==*/ +/*============================================================================*/ +/*============================================================================*/ +#ifndef DRXJ_DIGITAL_ONLY +/** +* \fn DRXStatus_t GetOOBLockStatus () +* \brief Get OOB lock status. +* \param devAddr I2C address + \ oobLock OOB lock status. +* \return DRXStatus_t. +* +* Gets OOB lock status +* +*/ +static DRXStatus_t +GetOOBLockStatus( pDRXDemodInstance_t demod, + pI2CDeviceAddr_t devAddr, + pDRXLockStatus_t oobLock ) +{ + DRXJSCUCmd_t scuCmd; + u16_t cmdResult[2]; + u16_t OOBLockState; + + *oobLock = DRX_NOT_LOCKED; + + scuCmd.command = SCU_RAM_COMMAND_STANDARD_OOB | + SCU_RAM_COMMAND_CMD_DEMOD_GET_LOCK; + scuCmd.resultLen = 2; + scuCmd.result = cmdResult; + scuCmd.parameterLen = 0; + + CHK_ERROR( SCUCommand( devAddr, &scuCmd ) ); + + if ( scuCmd.result[1] < 0x4000 ) + { + /* 0x00 NOT LOCKED */ + *oobLock = DRX_NOT_LOCKED; + } + else if ( scuCmd.result[1] < 0x8000 ) + { + /* 0x40 DEMOD LOCKED */ + *oobLock = DRXJ_OOB_SYNC_LOCK; + } + else if ( scuCmd.result[1] < 0xC000 ) + { + /* 0x80 DEMOD + OOB LOCKED (system lock) */ + OOBLockState = scuCmd.result[1] & 0x00FF; + + if(OOBLockState & 0x0008) + { + *oobLock = DRXJ_OOB_SYNC_LOCK; + } + else if ((OOBLockState & 0x0002) && (OOBLockState & 0x0001)) + { + *oobLock = DRXJ_OOB_AGC_LOCK; + } + } + else + { + /* 0xC0 NEVER LOCKED (system will never be able to lock to the signal) */ + *oobLock = DRX_NEVER_LOCK; + } + + /* *oobLock = scuCmd.result[1]; */ + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} + +/** +* \fn DRXStatus_t GetOOBSymbolRateOffset () +* \brief Get OOB Symbol rate offset. Unit is [ppm] +* \param devAddr I2C address +* \ Symbol Rate Offset OOB parameter. +* \return DRXStatus_t. +* +* Gets OOB frequency offset +* +*/ +static DRXStatus_t +GetOOBSymbolRateOffset( pI2CDeviceAddr_t devAddr, ps32_t SymbolRateOffset ) +{ +/* offset = -{(timingOffset/2^19)*(symbolRate/12,656250MHz)}*10^6 [ppm] */ +/* offset = -{(timingOffset/2^19)*(symbolRate/12656250)}*10^6 [ppm] */ +/* after reconfiguration: */ +/* offset = -{(timingOffset*symbolRate)/(2^19*12656250)}*10^6 [ppm] */ +/* shift symbol rate left by 5 without lossing information */ +/* offset = -{(timingOffset*(symbolRate * 2^-5))/(2^14*12656250)}*10^6 [ppm]*/ +/* shift 10^6 left by 6 without loosing information */ +/* offset = -{(timingOffset*(symbolRate * 2^-5))/(2^8*12656250)}*15625 [ppm]*/ +/* trim 12656250/15625 = 810 */ +/* offset = -{(timingOffset*(symbolRate * 2^-5))/(2^8*810)} [ppm] */ +/* offset = -[(symbolRate * 2^-5)*(timingOffset)/(2^8)]/810 [ppm] */ + s32_t timingOffset = 0; + u32_t unsignedTimingOffset = 0; + s32_t divisionFactor = 810; + u16_t data = 0; + u32_t symbolRate = 0; + Bool_t negative = FALSE; + + *SymbolRateOffset = 0; + /* read data rate */ + SARR16( devAddr, SCU_RAM_ORX_RF_RX_DATA_RATE__A, &data ); + switch(data & SCU_RAM_ORX_RF_RX_DATA_RATE__M) + { + case SCU_RAM_ORX_RF_RX_DATA_RATE_2048KBPS_REGSPEC: + case SCU_RAM_ORX_RF_RX_DATA_RATE_2048KBPS_INVSPEC: + case SCU_RAM_ORX_RF_RX_DATA_RATE_2048KBPS_REGSPEC_ALT: + case SCU_RAM_ORX_RF_RX_DATA_RATE_2048KBPS_INVSPEC_ALT: + symbolRate = 1024000;/* bps */ + break; + case SCU_RAM_ORX_RF_RX_DATA_RATE_1544KBPS_REGSPEC: + case SCU_RAM_ORX_RF_RX_DATA_RATE_1544KBPS_INVSPEC: + symbolRate = 772000;/* bps */ + break; + case SCU_RAM_ORX_RF_RX_DATA_RATE_3088KBPS_REGSPEC: + case SCU_RAM_ORX_RF_RX_DATA_RATE_3088KBPS_INVSPEC: + symbolRate = 1544000;/* bps */ + break; + default: + return (DRX_STS_ERROR); + } + + RR16( devAddr, ORX_CON_CTI_DTI_R__A, &data ); + /* convert data to positive and keep information about sign */ + if((data & 0x8000) == 0x8000){ + if(data == 0x8000) + unsignedTimingOffset = 32768; + else + unsignedTimingOffset = 0x00007FFF & (u32_t)(-data); + negative = TRUE; + } + else + unsignedTimingOffset = (u32_t)data; + + symbolRate = symbolRate >> 5; + unsignedTimingOffset = ( unsignedTimingOffset * symbolRate ); + unsignedTimingOffset = Frac( unsignedTimingOffset, 256, FRAC_ROUND ); + unsignedTimingOffset = Frac( unsignedTimingOffset, + divisionFactor, FRAC_ROUND ); + if(negative) + timingOffset = (s32_t)unsignedTimingOffset; + else + timingOffset = -(s32_t)unsignedTimingOffset; + + *SymbolRateOffset = timingOffset; + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} + +/** +* \fn DRXStatus_t GetOOBFreqOffset () +* \brief Get OOB lock status. +* \param devAddr I2C address +* \ freqOffset OOB frequency offset. +* \return DRXStatus_t. +* +* Gets OOB frequency offset +* +*/ +static DRXStatus_t +GetOOBFreqOffset( pDRXDemodInstance_t demod, pDRXFrequency_t freqOffset ) +{ + u16_t data = 0; + u16_t rot = 0; + u16_t symbolRateReg = 0; + u32_t symbolRate = 0; + s32_t coarseFreqOffset = 0; + s32_t fineFreqOffset = 0; + s32_t fineSign = 1; + s32_t coarseSign = 1; + u32_t data64Hi = 0; + u32_t data64Lo = 0; + u32_t tempFreqOffset = 0; + pDRXCommonAttr_t commonAttr = (pDRXCommonAttr_t)(NULL); + pI2CDeviceAddr_t devAddr = NULL; + + /* check arguments */ + if ( ( demod == NULL ) || + ( freqOffset == NULL ) ) + { + return DRX_STS_INVALID_ARG; + } + + devAddr = demod -> myI2CDevAddr; + commonAttr = (pDRXCommonAttr_t) demod -> myCommonAttr; + + *freqOffset = 0; + + /* read sign (spectrum inversion) */ + RR16( devAddr, ORX_FWP_IQM_FRQ_W__A, &rot ); + + /* read frequency offset */ + SARR16( devAddr, SCU_RAM_ORX_FRQ_OFFSET__A, &data ); + /* find COARSE frequency offset */ + /* coarseFreqOffset = ( 25312500Hz*FRQ_OFFSET >> 21 ); */ + if (data & 0x8000) + { + data = (0xffff - data + 1); + coarseSign = -1; + } + Mult32 ( data, (commonAttr->sysClockFreq * 1000)/6, &data64Hi, &data64Lo ); + tempFreqOffset = (((data64Lo >> 21) & 0x7ff) | (data64Hi << 11)); + + /* get value in KHz */ + coarseFreqOffset = coarseSign * Frac( tempFreqOffset, 1000, FRAC_ROUND ); /* KHz */ + /* read data rate */ + SARR16( devAddr, SCU_RAM_ORX_RF_RX_DATA_RATE__A, &symbolRateReg ); + switch(symbolRateReg & SCU_RAM_ORX_RF_RX_DATA_RATE__M) + { + case SCU_RAM_ORX_RF_RX_DATA_RATE_2048KBPS_REGSPEC: + case SCU_RAM_ORX_RF_RX_DATA_RATE_2048KBPS_INVSPEC: + case SCU_RAM_ORX_RF_RX_DATA_RATE_2048KBPS_REGSPEC_ALT: + case SCU_RAM_ORX_RF_RX_DATA_RATE_2048KBPS_INVSPEC_ALT: + symbolRate = 1024000; + break; + case SCU_RAM_ORX_RF_RX_DATA_RATE_1544KBPS_REGSPEC: + case SCU_RAM_ORX_RF_RX_DATA_RATE_1544KBPS_INVSPEC: + symbolRate = 772000; + break; + case SCU_RAM_ORX_RF_RX_DATA_RATE_3088KBPS_REGSPEC: + case SCU_RAM_ORX_RF_RX_DATA_RATE_3088KBPS_INVSPEC: + symbolRate = 1544000; + break; + default: + return (DRX_STS_ERROR); + } + + /* find FINE frequency offset */ + /* fineFreqOffset = ( (CORRECTION_VALUE*symbolRate) >> 18 ); */ + RR16( devAddr, ORX_CON_CPH_FRQ_R__A, &data ); + /* at least 5 MSB are 0 so first divide with 2^5 without information loss*/ + fineFreqOffset = ( symbolRate >> 5 ); + if (data & 0x8000) + { + fineFreqOffset *= 0xffff - data + 1; /* Hz */ + fineSign = -1; + } else { + fineFreqOffset *= data; /* Hz */ + } + /* Left to divide with 8192 (2^13) */ + fineFreqOffset = Frac( fineFreqOffset, 8192, FRAC_ROUND ); + /* and to divide with 1000 to get KHz*/ + fineFreqOffset = fineSign * Frac( fineFreqOffset, 1000, FRAC_ROUND ); /* KHz */ + + if ( (rot & 0x8000) == 0x8000 ) + *freqOffset = -(coarseFreqOffset + fineFreqOffset); + else + *freqOffset = (coarseFreqOffset + fineFreqOffset); + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} +/** +* \fn DRXStatus_t GetOOBFrequency () +* \brief Get OOB frequency (Unit:KHz). +* \param devAddr I2C address +* \ frequency OOB frequency parameters. +* \return DRXStatus_t. +* +* Gets OOB frequency +* +*/ +static DRXStatus_t +GetOOBFrequency( pDRXDemodInstance_t demod, pDRXFrequency_t frequency ) +{ + u16_t data = 0; + DRXFrequency_t freqOffset = 0; + DRXFrequency_t freq = 0; + pI2CDeviceAddr_t devAddr = NULL; + + devAddr = demod -> myI2CDevAddr; + + *frequency = 0;/* KHz */ + + SARR16( devAddr, SCU_RAM_ORX_RF_RX_FREQUENCY_VALUE__A, &data ); + + freq = (DRXFrequency_t)((DRXFrequency_t)data * 50 + 50000L); + + CHK_ERROR ( GetOOBFreqOffset ( demod, &freqOffset ) ); + + *frequency = freq + freqOffset; + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} +/** +* \fn DRXStatus_t GetOOBMER () +* \brief Get OOB MER. +* \param devAddr I2C address + \ MER OOB parameter in dB. +* \return DRXStatus_t. +* +* Gets OOB MER. Table for MER is in Programming guide. +* +*/ +static DRXStatus_t +GetOOBMER( pI2CDeviceAddr_t devAddr, pu32_t mer ) +{ + u16_t data = 0; + + *mer = 0; + /* READ MER */ + RR16( devAddr, ORX_EQU_MER_MER_R__A, &data ); + switch (data) + { + case 0:/* fall through */ + case 1: + *mer = 39; + break; + case 2: + *mer = 33; + break; + case 3: + *mer = 29; + break; + case 4: + *mer = 27; + break; + case 5: + *mer = 25; + break; + case 6: + *mer = 23; + break; + case 7: + *mer = 22; + break; + case 8: + *mer = 21; + break; + case 9: + *mer = 20; + break; + case 10: + *mer = 19; + break; + case 11: + *mer = 18; + break; + case 12: + *mer = 17; + break; + case 13:/* fall through */ + case 14: + *mer = 16; + break; + case 15:/* fall through */ + case 16: + *mer = 15; + break; + case 17:/* fall through */ + case 18: + *mer = 14; + break; + case 19:/* fall through */ + case 20: + *mer = 13; + break; + case 21:/* fall through */ + case 22: + *mer = 12; + break; + case 23:/* fall through */ + case 24:/* fall through */ + case 25: + *mer = 11; + break; + case 26:/* fall through */ + case 27:/* fall through */ + case 28: + *mer = 10; + break; + case 29:/* fall through */ + case 30:/* fall through */ + case 31:/* fall through */ + case 32: + *mer = 9; + break; + case 33:/* fall through */ + case 34:/* fall through */ + case 35:/* fall through */ + case 36: + *mer = 8; + break; + case 37:/* fall through */ + case 38:/* fall through */ + case 39:/* fall through */ + case 40: + *mer = 7; + break; + case 41:/* fall through */ + case 42:/* fall through */ + case 43:/* fall through */ + case 44:/* fall through */ + case 45: + *mer = 6; + break; + case 46:/* fall through */ + case 47:/* fall through */ + case 48:/* fall through */ + case 49:/* fall through */ + case 50:/* fall through */ + *mer = 5; + break; + case 51:/* fall through */ + case 52:/* fall through */ + case 53:/* fall through */ + case 54:/* fall through */ + case 55:/* fall through */ + case 56:/* fall through */ + case 57: + *mer = 4; + break; + case 58:/* fall through */ + case 59:/* fall through */ + case 60:/* fall through */ + case 61:/* fall through */ + case 62:/* fall through */ + case 63: + *mer = 0; + break; + default: + *mer = 0; + break; + } + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} +#endif /*#ifndef DRXJ_DIGITAL_ONLY */ + +/** +* \fn DRXStatus_t SetOrxNsuAox() +* \brief Configure OrxNsuAox for OOB +* \param demod instance of demodulator. +* \param active +* \return DRXStatus_t. +*/ +static DRXStatus_t +SetOrxNsuAox ( pDRXDemodInstance_t demod, Bool_t active ) +{ + u16_t data = 0; + pI2CDeviceAddr_t devAddr = NULL; + pDRXJData_t extAttr = NULL; + + extAttr = (pDRXJData_t)demod->myExtAttr; + devAddr = demod -> myI2CDevAddr; + + /* Configure NSU_AOX */ + RR16( devAddr, ORX_NSU_AOX_STDBY_W__A , &data ); + if( !active ) + { + data &= ((~ORX_NSU_AOX_STDBY_W_STDBYADC_A2_ON) + & (~ORX_NSU_AOX_STDBY_W_STDBYAMP_A2_ON) + & (~ORX_NSU_AOX_STDBY_W_STDBYBIAS_A2_ON) + & (~ORX_NSU_AOX_STDBY_W_STDBYPLL_A2_ON) + & (~ORX_NSU_AOX_STDBY_W_STDBYPD_A2_ON) + & (~ORX_NSU_AOX_STDBY_W_STDBYTAGC_IF_A2_ON) + & (~ORX_NSU_AOX_STDBY_W_STDBYTAGC_RF_A2_ON) + & (~ORX_NSU_AOX_STDBY_W_STDBYFLT_A2_ON) + ); + } + else /* active */ + { + data |= (ORX_NSU_AOX_STDBY_W_STDBYADC_A2_ON + | ORX_NSU_AOX_STDBY_W_STDBYAMP_A2_ON + | ORX_NSU_AOX_STDBY_W_STDBYBIAS_A2_ON + | ORX_NSU_AOX_STDBY_W_STDBYPLL_A2_ON + | ORX_NSU_AOX_STDBY_W_STDBYPD_A2_ON + | ORX_NSU_AOX_STDBY_W_STDBYTAGC_IF_A2_ON + | ORX_NSU_AOX_STDBY_W_STDBYTAGC_RF_A2_ON + | ORX_NSU_AOX_STDBY_W_STDBYFLT_A2_ON + ); + } + WR16( devAddr, ORX_NSU_AOX_STDBY_W__A , data ); + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} + +/** +* \fn DRXStatus_t CtrlSetOOB() +* \brief Set OOB channel to be used. +* \param demod instance of demodulator +* \param oobParam OOB parameters for channel setting. +* \frequency should be in KHz +* \return DRXStatus_t. +* +* Accepts only. Returns error otherwise. +* Demapper value is written after SCUCommand START +* because START command causes COMM_EXEC transition +* from 0 to 1 which causes all registers to be +* overwritten with initial value +* +*/ + +/* Nyquist filter impulse response */ +#define IMPULSE_COSINE_ALPHA_0_3 {-3,-4,-1, 6,10, 7,-5,-20,-25,-10,29,79,123,140} /*sqrt raised-cosine filter with alpha=0.3 */ +#define IMPULSE_COSINE_ALPHA_0_5 { 2, 0,-2,-2, 2, 5, 2,-10,-20,-14,20,74,125,145} /*sqrt raised-cosine filter with alpha=0.5 */ +#define IMPULSE_COSINE_ALPHA_RO_0_5 { 0, 0, 1, 2, 3, 0,-7,-15,-16, 0,34,77,114,128} /*full raised-cosine filter with alpha=0.5 (receiver only) */ + +/* Coefficients for the nyquist fitler (total: 27 taps) */ +#define NYQFILTERLEN 27 + +static DRXStatus_t +CtrlSetOOB( pDRXDemodInstance_t demod, pDRXOOB_t oobParam ) +{ +#ifndef DRXJ_DIGITAL_ONLY + DRXOOBDownstreamStandard_t standard = DRX_OOB_MODE_A; + DRXFrequency_t freq = 0; /* KHz */ + pI2CDeviceAddr_t devAddr = NULL; + pDRXJData_t extAttr = NULL; + u16_t i = 0; + Bool_t mirrorFreqSpectOOB = FALSE; + u16_t trkFilterValue = 0; + DRXJSCUCmd_t scuCmd; + u16_t setParamParameters[3]; + u16_t cmdResult[2] = {0, 0}; + s16_t NyquistCoeffs[4][(NYQFILTERLEN+1)/2] = + { + IMPULSE_COSINE_ALPHA_0_3, /* Target Mode 0 */ + IMPULSE_COSINE_ALPHA_0_3, /* Target Mode 1 */ + IMPULSE_COSINE_ALPHA_0_5, /* Target Mode 2 */ + IMPULSE_COSINE_ALPHA_RO_0_5 /* Target Mode 3 */ + }; + u8_t mode_val[4] = {2, 2, 0, 1}; + u8_t PFICoeffs[4][6] = + { + {DRXJ_16TO8(-92), DRXJ_16TO8(-108), DRXJ_16TO8(100) }, /* TARGET_MODE = 0: PFI_A = -23/32; PFI_B = -54/32; PFI_C = 25/32; fg = 0.5 MHz (Att=26dB) */ + {DRXJ_16TO8(-64), DRXJ_16TO8(-80), DRXJ_16TO8(80) }, /* TARGET_MODE = 1: PFI_A = -16/32; PFI_B = -40/32; PFI_C = 20/32; fg = 1.0 MHz (Att=28dB) */ + {DRXJ_16TO8(-80), DRXJ_16TO8(-98), DRXJ_16TO8(92) }, /* TARGET_MODE = 2, 3: PFI_A = -20/32; PFI_B = -49/32; PFI_C = 23/32; fg = 0.8 MHz (Att=25dB) */ + {DRXJ_16TO8(-80), DRXJ_16TO8(-98), DRXJ_16TO8(92) } /* TARGET_MODE = 2, 3: PFI_A = -20/32; PFI_B = -49/32; PFI_C = 23/32; fg = 0.8 MHz (Att=25dB) */ + }; + u16_t mode_index; + + devAddr = demod -> myI2CDevAddr; + extAttr = (pDRXJData_t)demod -> myExtAttr; + mirrorFreqSpectOOB = extAttr->mirrorFreqSpectOOB; + + /* Check parameters */ + if (oobParam == NULL) + { + /* power off oob module */ + scuCmd.command = SCU_RAM_COMMAND_STANDARD_OOB + | SCU_RAM_COMMAND_CMD_DEMOD_STOP; + scuCmd.parameterLen = 0; + scuCmd.resultLen = 1; + scuCmd.result = cmdResult; + CHK_ERROR( SCUCommand( devAddr, &scuCmd ) ); + CHK_ERROR( SetOrxNsuAox( demod, FALSE ) ); + WR16 ( devAddr, ORX_COMM_EXEC__A, ORX_COMM_EXEC_STOP); + + extAttr->oobPowerOn = FALSE; + return (DRX_STS_OK); + } + + standard = oobParam->standard; + + freq = oobParam->frequency; + if ((freq < 70000) || (freq > 130000)) + return (DRX_STS_ERROR); + freq = (freq - 50000) / 50; + + { + u16_t index = 0; + u16_t remainder = 0; + pu16_t trkFiltercfg = extAttr->oobTrkFilterCfg; + + index = (u16_t)((freq - 400) / 200); + remainder = (u16_t)((freq - 400) % 200); + trkFilterValue = trkFiltercfg[index] - (trkFiltercfg[index] - trkFiltercfg[index + 1])/10 + * remainder / 20; + } + + + /*********/ + /* Stop */ + /*********/ + WR16 ( devAddr, ORX_COMM_EXEC__A, ORX_COMM_EXEC_STOP); + scuCmd.command = SCU_RAM_COMMAND_STANDARD_OOB + | SCU_RAM_COMMAND_CMD_DEMOD_STOP; + scuCmd.parameterLen = 0; + scuCmd.resultLen = 1; + scuCmd.result = cmdResult; + CHK_ERROR( SCUCommand( devAddr, &scuCmd ) ); + /*********/ + /* Reset */ + /*********/ + scuCmd.command = SCU_RAM_COMMAND_STANDARD_OOB + | SCU_RAM_COMMAND_CMD_DEMOD_RESET; + scuCmd.parameterLen = 0; + scuCmd.resultLen = 1; + scuCmd.result = cmdResult; + CHK_ERROR( SCUCommand( devAddr, &scuCmd ) ); + /***********/ + /* SET_ENV */ + /***********/ + /* set frequency, spectrum inversion and data rate */ + scuCmd.command = SCU_RAM_COMMAND_STANDARD_OOB + | SCU_RAM_COMMAND_CMD_DEMOD_SET_ENV; + scuCmd.parameterLen = 3; + /* 1-data rate;2-frequency */ + switch ( oobParam->standard ) + { + case DRX_OOB_MODE_A: + if( + /* signal is transmitted inverted */ + ( (oobParam->spectrumInverted == TRUE) & + /* and tuner is not mirroring the signal */ + (mirrorFreqSpectOOB == FALSE) ) | + /* or */ + /* signal is transmitted noninverted */ + ( (oobParam->spectrumInverted == FALSE) & + /* and tuner is mirroring the signal */ + (mirrorFreqSpectOOB == TRUE) ) + ) + setParamParameters[0] = SCU_RAM_ORX_RF_RX_DATA_RATE_2048KBPS_INVSPEC; + else + setParamParameters[0] = SCU_RAM_ORX_RF_RX_DATA_RATE_2048KBPS_REGSPEC; + break; + case DRX_OOB_MODE_B_GRADE_A: + if( + /* signal is transmitted inverted */ + ( (oobParam->spectrumInverted == TRUE) & + /* and tuner is not mirroring the signal */ + (mirrorFreqSpectOOB == FALSE) ) | + /* or */ + /* signal is transmitted noninverted */ + ( (oobParam->spectrumInverted == FALSE) & + /* and tuner is mirroring the signal */ + (mirrorFreqSpectOOB == TRUE) ) + ) + setParamParameters[0] = SCU_RAM_ORX_RF_RX_DATA_RATE_1544KBPS_INVSPEC; + else + setParamParameters[0] = SCU_RAM_ORX_RF_RX_DATA_RATE_1544KBPS_REGSPEC; + break; + case DRX_OOB_MODE_B_GRADE_B: + default: + if( + /* signal is transmitted inverted */ + ( (oobParam->spectrumInverted == TRUE) & + /* and tuner is not mirroring the signal */ + (mirrorFreqSpectOOB == FALSE) ) | + /* or */ + /* signal is transmitted noninverted */ + ( (oobParam->spectrumInverted == FALSE) & + /* and tuner is mirroring the signal */ + (mirrorFreqSpectOOB == TRUE) ) + ) + setParamParameters[0] = SCU_RAM_ORX_RF_RX_DATA_RATE_3088KBPS_INVSPEC; + else + setParamParameters[0] = SCU_RAM_ORX_RF_RX_DATA_RATE_3088KBPS_REGSPEC; + break; + } + setParamParameters[1] = ( u16_t )( freq & 0xFFFF ); + setParamParameters[2] = trkFilterValue; + scuCmd.parameter = setParamParameters; + scuCmd.resultLen = 1; + scuCmd.result = cmdResult; + mode_index = mode_val[(setParamParameters[0] & 0xC0) >> 6]; + CHK_ERROR( SCUCommand( devAddr, &scuCmd ) ); + + WR16 ( devAddr, SIO_TOP_COMM_KEY__A, 0xFABA); /* Write magic word to enable pdr reg write */ + WR16 ( devAddr, SIO_PDR_OOB_CRX_CFG__A, + OOB_CRX_DRIVE_STRENGTH << SIO_PDR_OOB_CRX_CFG_DRIVE__B + | 0x03 << SIO_PDR_OOB_CRX_CFG_MODE__B ); + WR16 ( devAddr, SIO_PDR_OOB_DRX_CFG__A, + OOB_DRX_DRIVE_STRENGTH << SIO_PDR_OOB_DRX_CFG_DRIVE__B + | 0x03 << SIO_PDR_OOB_DRX_CFG_MODE__B ); + WR16 ( devAddr, SIO_TOP_COMM_KEY__A, 0x0000); /* Write magic word to disable pdr reg write */ + + WR16 ( devAddr, ORX_TOP_COMM_KEY__A, 0); + WR16 ( devAddr, ORX_FWP_AAG_LEN_W__A, 16000); + WR16 ( devAddr, ORX_FWP_AAG_THR_W__A, 40); + + /* ddc */ + WR16( devAddr, ORX_DDC_OFO_SET_W__A, ORX_DDC_OFO_SET_W__PRE); + + /* nsu */ + WR16( devAddr, ORX_NSU_AOX_LOPOW_W__A, extAttr->oobLoPow); + + /* initialization for target mode */ + WR16( devAddr, SCU_RAM_ORX_TARGET_MODE__A, SCU_RAM_ORX_TARGET_MODE_2048KBPS_SQRT); + WR16( devAddr, SCU_RAM_ORX_FREQ_GAIN_CORR__A, SCU_RAM_ORX_FREQ_GAIN_CORR_2048KBPS); + + /* Reset bits for timing and freq. recovery */ + WR16( devAddr, SCU_RAM_ORX_RST_CPH__A, 0x0001); + WR16( devAddr, SCU_RAM_ORX_RST_CTI__A, 0x0002); + WR16( devAddr, SCU_RAM_ORX_RST_KRN__A, 0x0004); + WR16( devAddr, SCU_RAM_ORX_RST_KRP__A, 0x0008); + + /* AGN_LOCK = {2048>>3, -2048, 8, -8, 0, 1}; */ + WR16( devAddr, SCU_RAM_ORX_AGN_LOCK_TH__A, 2048>>3); + WR16( devAddr, SCU_RAM_ORX_AGN_LOCK_TOTH__A, (u16_t) (-2048)); + WR16( devAddr, SCU_RAM_ORX_AGN_ONLOCK_TTH__A, 8); + WR16( devAddr, SCU_RAM_ORX_AGN_UNLOCK_TTH__A, (u16_t)(-8)); + WR16( devAddr, SCU_RAM_ORX_AGN_LOCK_MASK__A, 1); + + /* DGN_LOCK = {10, -2048, 8, -8, 0, 1<<1}; */ + WR16( devAddr, SCU_RAM_ORX_DGN_LOCK_TH__A, 10); + WR16( devAddr, SCU_RAM_ORX_DGN_LOCK_TOTH__A, (u16_t)(-2048)); + WR16( devAddr, SCU_RAM_ORX_DGN_ONLOCK_TTH__A, 8); + WR16( devAddr, SCU_RAM_ORX_DGN_UNLOCK_TTH__A, (u16_t)(-8)); + WR16( devAddr, SCU_RAM_ORX_DGN_LOCK_MASK__A, 1<<1); + + /* FRQ_LOCK = {15,-2048, 8, -8, 0, 1<<2}; */ + WR16( devAddr, SCU_RAM_ORX_FRQ_LOCK_TH__A, 17); + WR16( devAddr, SCU_RAM_ORX_FRQ_LOCK_TOTH__A, (u16_t)(-2048)); + WR16( devAddr, SCU_RAM_ORX_FRQ_ONLOCK_TTH__A, 8); + WR16( devAddr, SCU_RAM_ORX_FRQ_UNLOCK_TTH__A, (u16_t)(-8)); + WR16( devAddr, SCU_RAM_ORX_FRQ_LOCK_MASK__A, 1<<2); + + /* PHA_LOCK = {5000, -2048, 8, -8, 0, 1<<3}; */ + WR16( devAddr, SCU_RAM_ORX_PHA_LOCK_TH__A, 3000); + WR16( devAddr, SCU_RAM_ORX_PHA_LOCK_TOTH__A, (u16_t)(-2048)); + WR16( devAddr, SCU_RAM_ORX_PHA_ONLOCK_TTH__A, 8); + WR16( devAddr, SCU_RAM_ORX_PHA_UNLOCK_TTH__A, (u16_t)(-8)); + WR16( devAddr, SCU_RAM_ORX_PHA_LOCK_MASK__A, 1<<3); + + /* TIM_LOCK = {300, -2048, 8, -8, 0, 1<<4}; */ + WR16( devAddr, SCU_RAM_ORX_TIM_LOCK_TH__A, 400); + WR16( devAddr, SCU_RAM_ORX_TIM_LOCK_TOTH__A, (u16_t)(-2048)); + WR16( devAddr, SCU_RAM_ORX_TIM_ONLOCK_TTH__A, 8); + WR16( devAddr, SCU_RAM_ORX_TIM_UNLOCK_TTH__A, (u16_t)(-8)); + WR16( devAddr, SCU_RAM_ORX_TIM_LOCK_MASK__A, 1<<4); + + /* EQU_LOCK = {20, -2048, 8, -8, 0, 1<<5}; */ + WR16( devAddr, SCU_RAM_ORX_EQU_LOCK_TH__A, 20); + WR16( devAddr, SCU_RAM_ORX_EQU_LOCK_TOTH__A, (u16_t)(-2048)); + WR16( devAddr, SCU_RAM_ORX_EQU_ONLOCK_TTH__A, 4); + WR16( devAddr, SCU_RAM_ORX_EQU_UNLOCK_TTH__A, (u16_t)(-4)); + WR16( devAddr, SCU_RAM_ORX_EQU_LOCK_MASK__A, 1<<5); + + /* PRE-Filter coefficients (PFI) */ + WRB( devAddr, ORX_FWP_PFI_A_W__A, sizeof(PFICoeffs[mode_index]), ((pu8_t)PFICoeffs[mode_index])); + WR16( devAddr, ORX_TOP_MDE_W__A, mode_index); + + /* NYQUIST-Filter coefficients (NYQ) */ + for (i = 0; i < (NYQFILTERLEN + 1) / 2; i++) + { + WR16( devAddr, ORX_FWP_NYQ_ADR_W__A, i); + WR16( devAddr, ORX_FWP_NYQ_COF_RW__A, NyquistCoeffs[mode_index][i]); + } + WR16( devAddr, ORX_FWP_NYQ_ADR_W__A, 31); + WR16 ( devAddr, ORX_COMM_EXEC__A, ORX_COMM_EXEC_ACTIVE); + /*********/ + /* Start */ + /*********/ + scuCmd.command = SCU_RAM_COMMAND_STANDARD_OOB + | SCU_RAM_COMMAND_CMD_DEMOD_START; + scuCmd.parameterLen = 0; + scuCmd.resultLen = 1; + scuCmd.result = cmdResult; + CHK_ERROR( SCUCommand( devAddr, &scuCmd ) ); + + CHK_ERROR( SetOrxNsuAox( demod, TRUE ) ); + WR16( devAddr, ORX_NSU_AOX_STHR_W__A, extAttr->oobPreSaw ); + + extAttr->oobPowerOn = TRUE; + + return (DRX_STS_OK); +rw_error: +#endif + return (DRX_STS_ERROR); +} +/** +* \fn DRXStatus_t CtrlGetOOB() +* \brief Set modulation standard to be used. +* \param demod instance of demodulator +* \param oobStatus OOB status parameters. +* \return DRXStatus_t. +*/ +static DRXStatus_t +CtrlGetOOB( pDRXDemodInstance_t demod, pDRXOOBStatus_t oobStatus ) +{ +#ifndef DRXJ_DIGITAL_ONLY + pI2CDeviceAddr_t devAddr = NULL; + pDRXJData_t extAttr = NULL; + u16_t data = 0; + + devAddr = demod -> myI2CDevAddr; + extAttr = (pDRXJData_t) demod->myExtAttr; + + /* check arguments */ + if ( oobStatus == NULL ) + { + return (DRX_STS_INVALID_ARG); + } + + if ( extAttr->oobPowerOn == FALSE) + return (DRX_STS_ERROR); + + RR16 ( devAddr, ORX_DDC_OFO_SET_W__A, &data); + RR16 ( devAddr, ORX_NSU_TUN_RFGAIN_W__A, &data); + RR16 ( devAddr, ORX_FWP_AAG_THR_W__A, &data); + SARR16 ( devAddr, SCU_RAM_ORX_DGN_KI__A, &data); + RR16 ( devAddr, ORX_FWP_SRC_DGN_W__A, &data); + + CHK_ERROR ( GetOOBLockStatus ( demod, devAddr, &oobStatus->lock )); + CHK_ERROR ( GetOOBFrequency ( demod, &oobStatus->frequency )); + CHK_ERROR ( GetOOBMER ( devAddr, &oobStatus->mer )); + CHK_ERROR ( GetOOBSymbolRateOffset ( devAddr, &oobStatus->symbolRateOffset )); + + return (DRX_STS_OK); +rw_error: +#endif + return (DRX_STS_ERROR); +} + +/** +* \fn DRXStatus_t CtrlSetCfgOOBPreSAW() +* \brief Configure PreSAW treshold value +* \param cfgData Pointer to configuration parameter +* \return Error code +*/ +#ifndef DRXJ_DIGITAL_ONLY +static DRXStatus_t +CtrlSetCfgOOBPreSAW( pDRXDemodInstance_t demod, pu16_t cfgData ) +{ + pI2CDeviceAddr_t devAddr = NULL; + pDRXJData_t extAttr = NULL; + + if(cfgData == NULL) + { + return (DRX_STS_INVALID_ARG); + } + devAddr = demod->myI2CDevAddr; + extAttr = (pDRXJData_t)demod->myExtAttr; + + WR16( devAddr, ORX_NSU_AOX_STHR_W__A, *cfgData ); + extAttr->oobPreSaw = *cfgData; + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} +#endif + +/** +* \fn DRXStatus_t CtrlGetCfgOOBPreSAW() +* \brief Configure PreSAW treshold value +* \param cfgData Pointer to configuration parameter +* \return Error code +*/ +#ifndef DRXJ_DIGITAL_ONLY +static DRXStatus_t +CtrlGetCfgOOBPreSAW( pDRXDemodInstance_t demod, pu16_t cfgData ) +{ + pDRXJData_t extAttr = NULL; + + if(cfgData == NULL) + { + return (DRX_STS_INVALID_ARG); + } + extAttr = (pDRXJData_t)demod->myExtAttr; + + *cfgData = extAttr->oobPreSaw; + + return (DRX_STS_OK); +} +#endif + +/** +* \fn DRXStatus_t CtrlSetCfgOOBLoPower() +* \brief Configure LO Power value +* \param cfgData Pointer to pDRXJCfgOobLoPower_t +* \return Error code +*/ +#ifndef DRXJ_DIGITAL_ONLY +static DRXStatus_t +CtrlSetCfgOOBLoPower( pDRXDemodInstance_t demod, pDRXJCfgOobLoPower_t cfgData ) +{ + pI2CDeviceAddr_t devAddr = NULL; + pDRXJData_t extAttr = NULL; + + if(cfgData == NULL) + { + return (DRX_STS_INVALID_ARG); + } + devAddr = demod->myI2CDevAddr; + extAttr = (pDRXJData_t)demod->myExtAttr; + + WR16( devAddr, ORX_NSU_AOX_LOPOW_W__A, *cfgData ); + extAttr->oobLoPow = *cfgData; + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} +#endif + +/** +* \fn DRXStatus_t CtrlGetCfgOOBLoPower() +* \brief Configure LO Power value +* \param cfgData Pointer to pDRXJCfgOobLoPower_t +* \return Error code +*/ +#ifndef DRXJ_DIGITAL_ONLY +static DRXStatus_t +CtrlGetCfgOOBLoPower( pDRXDemodInstance_t demod, pDRXJCfgOobLoPower_t cfgData ) +{ + pDRXJData_t extAttr = NULL; + + if(cfgData == NULL) + { + return (DRX_STS_INVALID_ARG); + } + extAttr = (pDRXJData_t)demod->myExtAttr; + + *cfgData = extAttr->oobLoPow; + + return (DRX_STS_OK); +} +#endif +/*============================================================================*/ +/*== END OOB DATAPATH FUNCTIONS ==*/ +/*============================================================================*/ + +/*============================================================================= + ===== MC command related functions ========================================== + ===========================================================================*/ + +/*============================================================================= + ===== CtrlSetChannel() ========================================================== + ===========================================================================*/ +/** +* \fn DRXStatus_t CtrlSetChannel() +* \brief Select a new transmission channel. +* \param demod instance of demod. +* \param channel Pointer to channel data. +* \return DRXStatus_t. +* +* In case the tuner module is not used and in case of NTSC/FM the pogrammer +* must tune the tuner to the centre frequency of the NTSC/FM channel. +* +*/ +static DRXStatus_t +CtrlSetChannel( pDRXDemodInstance_t demod, + pDRXChannel_t channel ) +{ + + DRXFrequency_t tunerSetFreq = 0; + DRXFrequency_t tunerGetFreq = 0; + DRXFrequency_t tunerFreqOffset = 0; + DRXFrequency_t intermediateFreq = 0; + pDRXJData_t extAttr = NULL; + pI2CDeviceAddr_t devAddr = NULL; + DRXStandard_t standard = DRX_STANDARD_UNKNOWN; + TUNERMode_t tunerMode = 0; + pDRXCommonAttr_t commonAttr = NULL; + Bool_t bridgeClosed = FALSE; +#ifndef DRXJ_VSB_ONLY + u32_t minSymbolRate = 0; + u32_t maxSymbolRate = 0; + int bandwidthTemp = 0; + int bandwidth = 0; +#endif + /*== check arguments ======================================================*/ + if ( ( demod == NULL ) || + ( channel == NULL ) ) + { + return DRX_STS_INVALID_ARG; + } + + commonAttr = (pDRXCommonAttr_t) demod -> myCommonAttr; + devAddr = demod -> myI2CDevAddr; + extAttr = (pDRXJData_t)demod -> myExtAttr; + standard = extAttr->standard; + + /* check valid standards */ + switch ( standard ) + { + case DRX_STANDARD_8VSB: +#ifndef DRXJ_VSB_ONLY + case DRX_STANDARD_ITU_A: + case DRX_STANDARD_ITU_B: + case DRX_STANDARD_ITU_C: +#endif /* DRXJ_VSB_ONLY */ +#ifndef DRXJ_DIGITAL_ONLY + case DRX_STANDARD_NTSC: + case DRX_STANDARD_FM: + case DRX_STANDARD_PAL_SECAM_BG: + case DRX_STANDARD_PAL_SECAM_DK: + case DRX_STANDARD_PAL_SECAM_I: + case DRX_STANDARD_PAL_SECAM_L: + case DRX_STANDARD_PAL_SECAM_LP: +#endif /* DRXJ_DIGITAL_ONLY */ + break; + case DRX_STANDARD_UNKNOWN: + default: + return (DRX_STS_INVALID_ARG); + } + + /* check bandwidth QAM annex B, NTSC and 8VSB */ + if ( ( standard == DRX_STANDARD_ITU_B ) || + ( standard == DRX_STANDARD_8VSB ) || + ( standard == DRX_STANDARD_NTSC ) ) + { + switch ( channel->bandwidth ) { + case DRX_BANDWIDTH_6MHZ : + case DRX_BANDWIDTH_UNKNOWN : /* fall through */ + channel->bandwidth = DRX_BANDWIDTH_6MHZ; + break; + case DRX_BANDWIDTH_8MHZ : /* fall through */ + case DRX_BANDWIDTH_7MHZ : /* fall through */ + default : + return (DRX_STS_INVALID_ARG); + } + } + +#ifndef DRXJ_DIGITAL_ONLY + if ( standard == DRX_STANDARD_PAL_SECAM_BG ) + { + switch ( channel->bandwidth ) + { + case DRX_BANDWIDTH_7MHZ : /* fall through */ + case DRX_BANDWIDTH_8MHZ : + /* ok */ + break; + case DRX_BANDWIDTH_6MHZ : /* fall through */ + case DRX_BANDWIDTH_UNKNOWN : /* fall through */ + default : + return (DRX_STS_INVALID_ARG); + } + } + /* check bandwidth PAL/SECAM */ + if ( ( standard == DRX_STANDARD_PAL_SECAM_BG ) || + ( standard == DRX_STANDARD_PAL_SECAM_DK ) || + ( standard == DRX_STANDARD_PAL_SECAM_I ) || + ( standard == DRX_STANDARD_PAL_SECAM_L ) || + ( standard == DRX_STANDARD_PAL_SECAM_LP ) ) + { + switch ( channel->bandwidth ) + { + case DRX_BANDWIDTH_8MHZ : + case DRX_BANDWIDTH_UNKNOWN : /* fall through */ + channel->bandwidth = DRX_BANDWIDTH_8MHZ; + break; + case DRX_BANDWIDTH_6MHZ : /* fall through */ + case DRX_BANDWIDTH_7MHZ : /* fall through */ + default : + return (DRX_STS_INVALID_ARG); + } + } +#endif + + /* For QAM annex A and annex C: + -check symbolrate and constellation + -derive bandwidth from symbolrate (input bandwidth is ignored) + */ +#ifndef DRXJ_VSB_ONLY + if( ( standard == DRX_STANDARD_ITU_A ) || + ( standard == DRX_STANDARD_ITU_C ) ) + { + DRXUIOCfg_t UIOCfg = {DRX_UIO1, DRX_UIO_MODE_FIRMWARE_SAW}; + int bwRolloffFactor = 0; + + bwRolloffFactor = (standard == DRX_STANDARD_ITU_A)?115:113; + minSymbolRate = DRXJ_QAM_SYMBOLRATE_MIN; + maxSymbolRate = DRXJ_QAM_SYMBOLRATE_MAX; + /* config SMA_TX pin to SAW switch mode*/ + CHK_ERROR( CtrlSetUIOCfg( demod, &UIOCfg ) ); + + if ( channel->symbolrate < minSymbolRate || + channel->symbolrate > maxSymbolRate ) + { + return ( DRX_STS_INVALID_ARG ); + } + + switch ( channel->constellation ) { + case DRX_CONSTELLATION_QAM16 : /* fall through */ + case DRX_CONSTELLATION_QAM32 : /* fall through */ + case DRX_CONSTELLATION_QAM64 : /* fall through */ + case DRX_CONSTELLATION_QAM128 : /* fall through */ + case DRX_CONSTELLATION_QAM256 : + bandwidthTemp = channel->symbolrate * bwRolloffFactor; + bandwidth = bandwidthTemp / 100; + + if( ( bandwidthTemp % 100 ) >= 50 ) + { + bandwidth++; + } + + if( bandwidth <= 6100000 ) + { + channel->bandwidth = DRX_BANDWIDTH_6MHZ; + } + else if( ( bandwidth > 6100000 ) && ( bandwidth <= 7100000 ) ) + { + channel->bandwidth = DRX_BANDWIDTH_7MHZ; + } + else if( bandwidth > 7100000 ) + { + channel->bandwidth = DRX_BANDWIDTH_8MHZ; + } + break; + default: + return (DRX_STS_INVALID_ARG); + } + } + + /* For QAM annex B: + -check constellation + */ + if ( standard == DRX_STANDARD_ITU_B ) + { + switch ( channel->constellation ) { + case DRX_CONSTELLATION_AUTO : + case DRX_CONSTELLATION_QAM256 : + case DRX_CONSTELLATION_QAM64 : + break; + default : + return (DRX_STS_INVALID_ARG); + } + + switch (channel->interleavemode) + { + case DRX_INTERLEAVEMODE_I128_J1: + case DRX_INTERLEAVEMODE_I128_J1_V2: + case DRX_INTERLEAVEMODE_I128_J2: + case DRX_INTERLEAVEMODE_I64_J2: + case DRX_INTERLEAVEMODE_I128_J3: + case DRX_INTERLEAVEMODE_I32_J4: + case DRX_INTERLEAVEMODE_I128_J4: + case DRX_INTERLEAVEMODE_I16_J8: + case DRX_INTERLEAVEMODE_I128_J5: + case DRX_INTERLEAVEMODE_I8_J16: + case DRX_INTERLEAVEMODE_I128_J6: + case DRX_INTERLEAVEMODE_I128_J7: + case DRX_INTERLEAVEMODE_I128_J8: + case DRX_INTERLEAVEMODE_I12_J17: + case DRX_INTERLEAVEMODE_I5_J4: + case DRX_INTERLEAVEMODE_B52_M240: + case DRX_INTERLEAVEMODE_B52_M720: + case DRX_INTERLEAVEMODE_UNKNOWN: + case DRX_INTERLEAVEMODE_AUTO: + break; + default: + return (DRX_STS_INVALID_ARG); + } + } + + if ( (extAttr->uioSmaTxMode) == DRX_UIO_MODE_FIRMWARE_SAW ) + { + /* SAW SW, user UIO is used for switchable SAW */ + DRXUIOData_t uio1 = { DRX_UIO1, FALSE }; + + switch ( channel->bandwidth ) + { + case DRX_BANDWIDTH_8MHZ: + uio1.value = TRUE; + break; + case DRX_BANDWIDTH_7MHZ: + uio1.value = FALSE; + break; + case DRX_BANDWIDTH_6MHZ: + uio1.value = FALSE; + break; + case DRX_BANDWIDTH_UNKNOWN: + default: + return (DRX_STS_INVALID_ARG); + } + + CHK_ERROR( CtrlUIOWrite( demod, &uio1 ) ); + } +#endif /* DRXJ_VSB_ONLY */ + WR16( devAddr, SCU_COMM_EXEC__A, SCU_COMM_EXEC_ACTIVE); + /*== Tune, fast mode ======================================================*/ + if ( demod->myTuner != NULL ) + { + /* Determine tuner mode and freq to tune to ... */ + switch ( standard ) { +#ifndef DRXJ_DIGITAL_ONLY + case DRX_STANDARD_NTSC: /* fallthrough */ + case DRX_STANDARD_PAL_SECAM_BG: /* fallthrough */ + case DRX_STANDARD_PAL_SECAM_DK: /* fallthrough */ + case DRX_STANDARD_PAL_SECAM_I: /* fallthrough */ + case DRX_STANDARD_PAL_SECAM_L: /* fallthrough */ + case DRX_STANDARD_PAL_SECAM_LP: + /* expecting center frequency, not picture carrier so no + conversion .... */ + tunerMode |= TUNER_MODE_ANALOG; + tunerSetFreq = channel->frequency; + break; + case DRX_STANDARD_FM: + /* center frequency (equals sound carrier) as input, + tune to edge of SAW */ + tunerMode |= TUNER_MODE_ANALOG; + tunerSetFreq = channel->frequency + DRXJ_FM_CARRIER_FREQ_OFFSET; + break; +#endif + case DRX_STANDARD_8VSB: /* fallthrough */ +#ifndef DRXJ_VSB_ONLY + case DRX_STANDARD_ITU_A: /* fallthrough */ + case DRX_STANDARD_ITU_B: /* fallthrough */ + case DRX_STANDARD_ITU_C: +#endif + tunerMode |= TUNER_MODE_DIGITAL; + tunerSetFreq = channel->frequency; + break; + case DRX_STANDARD_UNKNOWN: + default: + return (DRX_STS_ERROR); + } /* switch(standard) */ + + tunerMode |= TUNER_MODE_SWITCH; + switch ( channel->bandwidth ) { + case DRX_BANDWIDTH_8MHZ : + tunerMode |= TUNER_MODE_8MHZ; + break; + case DRX_BANDWIDTH_7MHZ : + tunerMode |= TUNER_MODE_7MHZ; + break; + case DRX_BANDWIDTH_6MHZ : + tunerMode |= TUNER_MODE_6MHZ; + break; + default: + /* TODO: for FM which bandwidth to use ? + also check offset from centre frequency ? + For now using 6MHz. + */ + tunerMode |= TUNER_MODE_6MHZ; + break; + /* return (DRX_STS_INVALID_ARG); */ + } + + /* store bandwidth for GetChannel() */ + extAttr->currBandwidth = channel->bandwidth; + extAttr->currSymbolRate = channel->symbolrate; + extAttr->frequency = tunerSetFreq; + if ( commonAttr->tunerPortNr == 1 ) + { + /* close tuner bridge */ + bridgeClosed = TRUE; + CHK_ERROR( CtrlI2CBridge( demod, &bridgeClosed ) ); + /* set tuner frequency */ + } + + CHK_ERROR( DRXBSP_TUNER_SetFrequency( demod->myTuner, + tunerMode, + tunerSetFreq ) ); + if ( commonAttr->tunerPortNr == 1 ) + { + /* open tuner bridge */ + bridgeClosed = FALSE; + CHK_ERROR( CtrlI2CBridge( demod, &bridgeClosed ) ); + } + + /* Get actual frequency set by tuner and compute offset */ + CHK_ERROR( DRXBSP_TUNER_GetFrequency( demod->myTuner, + 0, + &tunerGetFreq, + &intermediateFreq ) ); + tunerFreqOffset = tunerGetFreq - tunerSetFreq; + commonAttr->intermediateFreq = intermediateFreq; + } + else + { + /* no tuner instance defined, use fixed intermediate frequency */ + tunerFreqOffset = 0; + intermediateFreq = demod->myCommonAttr->intermediateFreq; + } /* if ( demod->myTuner != NULL ) */ + + /*== Setup demod for specific standard ====================================*/ + switch ( standard ) { + case DRX_STANDARD_8VSB: + if (channel->mirror == DRX_MIRROR_AUTO) + { + extAttr->mirror = DRX_MIRROR_NO; + } + else + { + extAttr->mirror = channel->mirror; + } + CHK_ERROR ( SetVSB(demod) ); + CHK_ERROR ( SetFrequency ( demod, channel, tunerFreqOffset ) ); + break; +#ifndef DRXJ_DIGITAL_ONLY + case DRX_STANDARD_NTSC: /* fallthrough */ + case DRX_STANDARD_FM: /* fallthrough */ + case DRX_STANDARD_PAL_SECAM_BG: /* fallthrough */ + case DRX_STANDARD_PAL_SECAM_DK: /* fallthrough */ + case DRX_STANDARD_PAL_SECAM_I: /* fallthrough */ + case DRX_STANDARD_PAL_SECAM_L: /* fallthrough */ + case DRX_STANDARD_PAL_SECAM_LP: + if (channel->mirror == DRX_MIRROR_AUTO) + { + extAttr->mirror = DRX_MIRROR_NO; + } + else + { + extAttr->mirror = channel->mirror; + } + CHK_ERROR ( SetATVChannel( demod, + tunerFreqOffset, + channel, + standard ) ); + break; +#endif +#ifndef DRXJ_VSB_ONLY + case DRX_STANDARD_ITU_A: /* fallthrough */ + case DRX_STANDARD_ITU_B: /* fallthrough */ + case DRX_STANDARD_ITU_C: + CHK_ERROR ( SetQAMChannel( demod, channel, tunerFreqOffset ) ); + break; +#endif + case DRX_STANDARD_UNKNOWN: + default: + return (DRX_STS_ERROR); + } + + /*== Re-tune, slow mode ===================================================*/ + if ( demod->myTuner != NULL ) + { + /* tune to slow mode */ + tunerMode &= ~TUNER_MODE_SWITCH; + tunerMode |= TUNER_MODE_LOCK; + + if ( commonAttr->tunerPortNr == 1 ) + { + /* close tuner bridge */ + bridgeClosed = TRUE; + CHK_ERROR( CtrlI2CBridge( demod, &bridgeClosed ) ); + } + + /* set tuner frequency*/ + CHK_ERROR( DRXBSP_TUNER_SetFrequency( demod->myTuner, + tunerMode, + tunerSetFreq ) ); + if ( commonAttr->tunerPortNr == 1 ) + { + /* open tuner bridge */ + bridgeClosed = FALSE; + CHK_ERROR( CtrlI2CBridge( demod, &bridgeClosed ) ); + } + } /* if ( demod->myTuner !=NULL ) */ + + /* flag the packet error counter reset */ + extAttr->resetPktErrAcc = TRUE; + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} + +/*============================================================================= + ===== CtrlGetChannel() ========================================================== + ===========================================================================*/ +/** +* \fn DRXStatus_t CtrlGetChannel() +* \brief Retreive parameters of current transmission channel. +* \param demod Pointer to demod instance. +* \param channel Pointer to channel data. +* \return DRXStatus_t. +*/ +static DRXStatus_t +CtrlGetChannel( pDRXDemodInstance_t demod, + pDRXChannel_t channel ) +{ + pI2CDeviceAddr_t devAddr = NULL; + pDRXJData_t extAttr = NULL; + DRXLockStatus_t lockStatus = DRX_NOT_LOCKED; + DRXStandard_t standard = DRX_STANDARD_UNKNOWN; + pDRXCommonAttr_t commonAttr = NULL; + DRXFrequency_t intermediateFreq = 0; + s32_t CTLFreqOffset = 0; + u32_t iqmRcRateLo = 0; + u32_t adcFrequency = 0; +#ifndef DRXJ_VSB_ONLY + int bandwidthTemp = 0; + int bandwidth = 0; +#endif + + /* check arguments */ + if ( ( demod == NULL ) || + ( channel == NULL ) ) + { + return DRX_STS_INVALID_ARG; + } + + devAddr = demod -> myI2CDevAddr; + extAttr = (pDRXJData_t)demod -> myExtAttr; + standard = extAttr->standard; + commonAttr = (pDRXCommonAttr_t) demod -> myCommonAttr; + + /* initialize channel fields */ + channel->mirror = DRX_MIRROR_UNKNOWN; + channel->hierarchy = DRX_HIERARCHY_UNKNOWN; + channel->priority = DRX_PRIORITY_UNKNOWN; + channel->coderate = DRX_CODERATE_UNKNOWN; + channel->guard = DRX_GUARD_UNKNOWN; + channel->fftmode = DRX_FFTMODE_UNKNOWN; + channel->classification = DRX_CLASSIFICATION_UNKNOWN; + channel->bandwidth = DRX_BANDWIDTH_UNKNOWN; + channel->constellation = DRX_CONSTELLATION_UNKNOWN; + channel->symbolrate = 0; + channel->interleavemode = DRX_INTERLEAVEMODE_UNKNOWN; + channel->carrier = DRX_CARRIER_UNKNOWN; + channel->framemode = DRX_FRAMEMODE_UNKNOWN; +/* channel->interleaver = DRX_INTERLEAVER_UNKNOWN;*/ + channel->ldpc = DRX_LDPC_UNKNOWN; + + if ( demod->myTuner != NULL ) + { + DRXFrequency_t tunerFreqOffset = 0; + Bool_t tunerMirror = commonAttr->mirrorFreqSpect?FALSE:TRUE; + + /* Get frequency from tuner */ + CHK_ERROR( DRXBSP_TUNER_GetFrequency( demod->myTuner, + 0, + &(channel->frequency), + &intermediateFreq ) ); + tunerFreqOffset = channel->frequency - extAttr->frequency; + if ( tunerMirror == TRUE ) + { + /* positive image */ + channel->frequency += tunerFreqOffset; + } else { + /* negative image */ + channel->frequency -= tunerFreqOffset; + } + + /* Handle sound carrier offset in RF domain */ + if ( standard == DRX_STANDARD_FM ) + { + channel->frequency -= DRXJ_FM_CARRIER_FREQ_OFFSET; + } + } + else + { + intermediateFreq = commonAttr->intermediateFreq; + } + + /* check lock status */ + CHK_ERROR( CtrlLockStatus( demod, &lockStatus) ); + if ( (lockStatus == DRX_LOCKED) || (lockStatus == DRXJ_DEMOD_LOCK) ) + { + ARR32( devAddr, IQM_RC_RATE_LO__A, &iqmRcRateLo ); + adcFrequency = ( commonAttr->sysClockFreq * 1000 ) / 3; + + channel->symbolrate = Frac28(adcFrequency, (iqmRcRateLo + (1<<23))) >> 7; + + switch ( standard ) + { + case DRX_STANDARD_8VSB: + channel->bandwidth = DRX_BANDWIDTH_6MHZ; + /* get the channel frequency */ + CHK_ERROR( GetCTLFreqOffset ( demod, &CTLFreqOffset ) ); + channel->frequency -= CTLFreqOffset; + /* get the channel constellation */ + channel->constellation = DRX_CONSTELLATION_AUTO; + break; +#ifndef DRXJ_VSB_ONLY + case DRX_STANDARD_ITU_A: + case DRX_STANDARD_ITU_B: + case DRX_STANDARD_ITU_C: + { + /* get the channel frequency */ + CHK_ERROR( GetCTLFreqOffset ( demod, &CTLFreqOffset ) ); + channel->frequency -= CTLFreqOffset; + + if (standard == DRX_STANDARD_ITU_B) + { + channel->bandwidth = DRX_BANDWIDTH_6MHZ; + } + else + { + /* annex A & C */ + + u32_t rollOff=113; /* default annex C */ + + if ( standard==DRX_STANDARD_ITU_A) + { + rollOff=115; + } + + bandwidthTemp = channel->symbolrate * rollOff; + bandwidth = bandwidthTemp / 100; + + if( ( bandwidthTemp % 100 ) >= 50 ) + { + bandwidth++; + } + + if( bandwidth <= 6000000 ) + { + channel->bandwidth = DRX_BANDWIDTH_6MHZ; + } + else if( ( bandwidth > 6000000 ) && ( bandwidth <= 7000000 ) ) + { + channel->bandwidth = DRX_BANDWIDTH_7MHZ; + } + else if( bandwidth > 7000000 ) + { + channel->bandwidth = DRX_BANDWIDTH_8MHZ; + } + } /* if (standard == DRX_STANDARD_ITU_B) */ + + { + DRXJSCUCmd_t cmdSCU = { /* command */ 0, + /* parameterLen */ 0, + /* resultLen */ 0, + /* parameter */ NULL, + /* result */ NULL }; + u16_t cmdResult[3] = { 0, 0, 0 }; + + cmdSCU.command = SCU_RAM_COMMAND_STANDARD_QAM | + SCU_RAM_COMMAND_CMD_DEMOD_GET_PARAM; + cmdSCU.parameterLen = 0; + cmdSCU.resultLen = 3; + cmdSCU.parameter = NULL; + cmdSCU.result = cmdResult; + CHK_ERROR( SCUCommand( devAddr, &cmdSCU ) ); + + channel->interleavemode = (DRXInterleaveModes_t)(cmdSCU.result[2]); + } + + switch ( extAttr->constellation ) + { + case DRX_CONSTELLATION_QAM256: + channel->constellation = DRX_CONSTELLATION_QAM256; + break; + case DRX_CONSTELLATION_QAM128: + channel->constellation = DRX_CONSTELLATION_QAM128; + break; + case DRX_CONSTELLATION_QAM64: + channel->constellation = DRX_CONSTELLATION_QAM64; + break; + case DRX_CONSTELLATION_QAM32: + channel->constellation = DRX_CONSTELLATION_QAM32; + break; + case DRX_CONSTELLATION_QAM16: + channel->constellation = DRX_CONSTELLATION_QAM16; + break; + default: + channel->constellation = DRX_CONSTELLATION_UNKNOWN; + return (DRX_STS_ERROR); + } + } + break; +#endif +#ifndef DRXJ_DIGITAL_ONLY + case DRX_STANDARD_NTSC: /* fall trough */ + case DRX_STANDARD_PAL_SECAM_BG: + case DRX_STANDARD_PAL_SECAM_DK: + case DRX_STANDARD_PAL_SECAM_I: + case DRX_STANDARD_PAL_SECAM_L: + case DRX_STANDARD_PAL_SECAM_LP: + case DRX_STANDARD_FM: + CHK_ERROR( GetATVChannel(demod, channel, standard)); + break; +#endif + case DRX_STANDARD_UNKNOWN: /* fall trough */ + default: + return (DRX_STS_ERROR); + } /* switch ( standard ) */ + + if (lockStatus == DRX_LOCKED) + { + channel->mirror = extAttr->mirror; + } + } /* if ( lockStatus == DRX_LOCKED ) */ + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} + +/*============================================================================= + ===== SigQuality() ========================================================== + ===========================================================================*/ + +static u16_t +mer2indicator ( + u16_t mer, + u16_t minMer, + u16_t thresholdMer, + u16_t maxMer) +{ + u16_t indicator = 0; + + if ( mer < minMer ) + { + indicator = 0; + } + else if ( mer < thresholdMer ) + { + if ((thresholdMer - minMer) != 0) + { + indicator = 25 * (mer - minMer) / (thresholdMer - minMer); + } + } + else if ( mer < maxMer ) + { + if ((maxMer - thresholdMer) != 0) + { + indicator = 25 + 75 * (mer - thresholdMer) / (maxMer - thresholdMer); + } + else + { + indicator = 25; + } + } + else + { + indicator = 100; + } + + return indicator; +} +/** +* \fn DRXStatus_t CtrlSigQuality() +* \brief Retreive signal quality form device. +* \param devmod Pointer to demodulator instance. +* \param sigQuality Pointer to signal quality data. +* \return DRXStatus_t. +* \retval DRX_STS_OK sigQuality contains valid data. +* \retval DRX_STS_INVALID_ARG sigQuality is NULL. +* \retval DRX_STS_ERROR Erroneous data, sigQuality contains invalid data. + +*/ +static DRXStatus_t +CtrlSigQuality( pDRXDemodInstance_t demod, + pDRXSigQuality_t sigQuality ) +{ + pI2CDeviceAddr_t devAddr = NULL; + pDRXJData_t extAttr = NULL; + DRXStandard_t standard = DRX_STANDARD_UNKNOWN; + DRXLockStatus_t lockStatus = DRX_NOT_LOCKED; + u16_t minMer = 0; + u16_t maxMer = 0; + u16_t thresholdMer = 0; + + /* Check arguments */ + if (( sigQuality == NULL ) || + ( demod == NULL )) + { + return (DRX_STS_INVALID_ARG); + } + + extAttr = (pDRXJData_t)demod->myExtAttr; + standard = extAttr->standard; + + /* get basic information */ + devAddr = demod -> myI2CDevAddr; + CHK_ERROR( CtrlLockStatus( demod, &lockStatus) ); + switch ( standard ) { + case DRX_STANDARD_8VSB: +#ifdef DRXJ_SIGNAL_ACCUM_ERR + CHK_ERROR (GetAccPktErr (demod, &sigQuality->packetError)); +#else + CHK_ERROR (GetVSBPostRSPckErr (devAddr, &sigQuality->packetError)); +#endif + if ( lockStatus != DRXJ_DEMOD_LOCK && lockStatus != DRX_LOCKED ) + { + sigQuality->postViterbiBER = 500000; + sigQuality->MER = 20; + sigQuality->preViterbiBER = 0; + } else { + /* PostViterbi is compute in steps of 10^(-6) */ + CHK_ERROR (GetVSBpreViterbiBer (devAddr, &sigQuality->preViterbiBER)); + CHK_ERROR (GetVSBpostViterbiBer (devAddr, &sigQuality->postViterbiBER)); + CHK_ERROR (GetVSBMER (devAddr, &sigQuality->MER)); + } + minMer = 20; + maxMer = 360; + thresholdMer = 145; + sigQuality->postReedSolomonBER = 0; + sigQuality->scaleFactorBER = 1000000; + sigQuality->indicator = mer2indicator (sigQuality->MER, minMer, thresholdMer, maxMer); + break; +#ifndef DRXJ_VSB_ONLY + case DRX_STANDARD_ITU_A: + case DRX_STANDARD_ITU_B: + case DRX_STANDARD_ITU_C: + CHK_ERROR ( CtrlGetQAMSigQuality ( demod, sigQuality ) ); + if ( lockStatus != DRXJ_DEMOD_LOCK && lockStatus != DRX_LOCKED ) + { + switch ( extAttr->constellation ) + { + case DRX_CONSTELLATION_QAM256: + sigQuality->MER = 210; + break; + case DRX_CONSTELLATION_QAM128: + sigQuality->MER = 180; + break; + case DRX_CONSTELLATION_QAM64: + sigQuality->MER = 150; + break; + case DRX_CONSTELLATION_QAM32: + sigQuality->MER = 120; + break; + case DRX_CONSTELLATION_QAM16: + sigQuality->MER = 90; + break; + default: + sigQuality->MER = 0; + return (DRX_STS_ERROR); + } + } + + switch ( extAttr->constellation ) + { + case DRX_CONSTELLATION_QAM256: + minMer = 210; + thresholdMer = 270; + maxMer = 380; + break; + case DRX_CONSTELLATION_QAM64: + minMer = 150; + thresholdMer = 210; + maxMer = 380; + break; + case DRX_CONSTELLATION_QAM128: + case DRX_CONSTELLATION_QAM32: + case DRX_CONSTELLATION_QAM16: + break; + default: + return (DRX_STS_ERROR); + } + sigQuality->indicator = mer2indicator (sigQuality->MER, minMer, thresholdMer, maxMer); + break; +#endif +#ifndef DRXJ_DIGITAL_ONLY + case DRX_STANDARD_PAL_SECAM_BG: + case DRX_STANDARD_PAL_SECAM_DK: + case DRX_STANDARD_PAL_SECAM_I: + case DRX_STANDARD_PAL_SECAM_L: + case DRX_STANDARD_PAL_SECAM_LP: + case DRX_STANDARD_NTSC: + CHK_ERROR ( AtvSigQuality ( demod, sigQuality ) ); + break; + case DRX_STANDARD_FM: + CHK_ERROR ( FmSigQuality ( demod, sigQuality ) ); + break; +#endif + default: + return (DRX_STS_ERROR); + } + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} + +/*============================================================================*/ + +/** +* \fn DRXStatus_t CtrlLockStatus() +* \brief Retreive lock status . +* \param devAddr Pointer to demodulator device address. +* \param lockStat Pointer to lock status structure. +* \return DRXStatus_t. +* +*/ +static DRXStatus_t +CtrlLockStatus( pDRXDemodInstance_t demod, + pDRXLockStatus_t lockStat ) +{ + DRXStandard_t standard = DRX_STANDARD_UNKNOWN; + pDRXJData_t extAttr = NULL; + pI2CDeviceAddr_t devAddr = NULL; + DRXJSCUCmd_t cmdSCU = { /* command */ 0, + /* parameterLen */ 0, + /* resultLen */ 0, + /* *parameter */ NULL, + /* *result */ NULL }; + u16_t cmdResult[2] = { 0, 0 }; + u16_t demodLock = SCU_RAM_PARAM_1_RES_DEMOD_GET_LOCK_DEMOD_LOCKED; + + /* check arguments */ + if ( ( demod == NULL ) || + ( lockStat == NULL ) ) + { + return (DRX_STS_INVALID_ARG); + } + + devAddr = demod -> myI2CDevAddr; + extAttr = (pDRXJData_t)demod->myExtAttr; + standard = extAttr->standard; + + *lockStat = DRX_NOT_LOCKED; + + /* define the SCU command code */ + switch ( standard ) { + case DRX_STANDARD_8VSB: + cmdSCU.command = SCU_RAM_COMMAND_STANDARD_VSB | + SCU_RAM_COMMAND_CMD_DEMOD_GET_LOCK; + demodLock |= 0x6; + break; +#ifndef DRXJ_VSB_ONLY + case DRX_STANDARD_ITU_A: + case DRX_STANDARD_ITU_B: + case DRX_STANDARD_ITU_C: + cmdSCU.command = SCU_RAM_COMMAND_STANDARD_QAM | + SCU_RAM_COMMAND_CMD_DEMOD_GET_LOCK; + break; +#endif +#ifndef DRXJ_DIGITAL_ONLY + case DRX_STANDARD_NTSC: + case DRX_STANDARD_PAL_SECAM_BG: + case DRX_STANDARD_PAL_SECAM_DK: + case DRX_STANDARD_PAL_SECAM_I: + case DRX_STANDARD_PAL_SECAM_L: + case DRX_STANDARD_PAL_SECAM_LP: + cmdSCU.command = SCU_RAM_COMMAND_STANDARD_ATV | + SCU_RAM_COMMAND_CMD_DEMOD_GET_LOCK; + break; + case DRX_STANDARD_FM: + return FmLockStatus( demod, lockStat); +#endif + case DRX_STANDARD_UNKNOWN: /* fallthrough */ + default: + return (DRX_STS_ERROR); + } + + /* define the SCU command paramters and execute the command */ + cmdSCU.parameterLen = 0; + cmdSCU.resultLen = 2; + cmdSCU.parameter = NULL; + cmdSCU.result = cmdResult; + CHK_ERROR( SCUCommand( devAddr, &cmdSCU ) ); + + /* set the lock status */ + if ( cmdSCU.result[1] < demodLock ) + { + /* 0x0000 NOT LOCKED */ + *lockStat = DRX_NOT_LOCKED; + } + else if ( cmdSCU.result[1] < SCU_RAM_PARAM_1_RES_DEMOD_GET_LOCK_LOCKED ) + { + *lockStat = DRXJ_DEMOD_LOCK; + } + else if ( cmdSCU.result[1] < SCU_RAM_PARAM_1_RES_DEMOD_GET_LOCK_NEVER_LOCK ) + { + /* 0x8000 DEMOD + FEC LOCKED (system lock) */ + *lockStat = DRX_LOCKED; + } + else + { + /* 0xC000 NEVER LOCKED */ + /* (system will never be able to lock to the signal) */ + *lockStat = DRX_NEVER_LOCK; + } + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} + +/*============================================================================*/ + +/** +* \fn DRXStatus_t CtrlConstel() +* \brief Retreive a constellation point via I2C. +* \param demod Pointer to demodulator instance. +* \param complexNr Pointer to the structure in which to store the + constellation point. +* \return DRXStatus_t. +*/ +static DRXStatus_t +CtrlConstel( pDRXDemodInstance_t demod, + pDRXComplex_t complexNr ) +{ + DRXStandard_t standard = DRX_STANDARD_UNKNOWN; /**< active standard */ + + /* check arguments */ + if ( ( demod == NULL ) || + ( complexNr == NULL ) ) + { + return (DRX_STS_INVALID_ARG); + } + + /* read device info */ + standard = ((pDRXJData_t)demod->myExtAttr)->standard; + + /* Read constellation point */ + switch ( standard ) { + case DRX_STANDARD_8VSB: + CHK_ERROR( CtrlGetVSBConstel( demod, complexNr ) ); + break; +#ifndef DRXJ_VSB_ONLY + case DRX_STANDARD_ITU_A: /* fallthrough */ + case DRX_STANDARD_ITU_B: /* fallthrough */ + case DRX_STANDARD_ITU_C: + CHK_ERROR( CtrlGetQAMConstel( demod, complexNr ) ); + break; +#endif + case DRX_STANDARD_UNKNOWN: + default: + return (DRX_STS_ERROR); + } + + return (DRX_STS_OK); + rw_error: + return (DRX_STS_ERROR); +} + +/*============================================================================*/ + +/** +* \fn DRXStatus_t CtrlSetStandard() +* \brief Set modulation standard to be used. +* \param standard Modulation standard. +* \return DRXStatus_t. +* +* Setup stuff for the desired demodulation standard. +* Disable and power down the previous selected demodulation standard +* +*/ +static DRXStatus_t +CtrlSetStandard( pDRXDemodInstance_t demod, pDRXStandard_t standard ) +{ + pDRXJData_t extAttr = NULL; + DRXStandard_t prevStandard; + + /* check arguments */ + if (( standard == NULL ) || + ( demod == NULL )) + { + return (DRX_STS_INVALID_ARG); + } + + extAttr = (pDRXJData_t)demod->myExtAttr; + prevStandard=extAttr->standard; + + /* + Stop and power down previous standard + */ + switch ( prevStandard ) + { +#ifndef DRXJ_VSB_ONLY + case DRX_STANDARD_ITU_A: /* fallthrough */ + case DRX_STANDARD_ITU_B: /* fallthrough */ + case DRX_STANDARD_ITU_C: + CHK_ERROR( PowerDownQAM(demod, FALSE) ); + break; +#endif + case DRX_STANDARD_8VSB: + CHK_ERROR( PowerDownVSB(demod, FALSE) ); + break; +#ifndef DRXJ_DIGITAL_ONLY + case DRX_STANDARD_NTSC: /* fallthrough */ + case DRX_STANDARD_FM: /* fallthrough */ + case DRX_STANDARD_PAL_SECAM_BG: /* fallthrough */ + case DRX_STANDARD_PAL_SECAM_DK: /* fallthrough */ + case DRX_STANDARD_PAL_SECAM_I: /* fallthrough */ + case DRX_STANDARD_PAL_SECAM_L: /* fallthrough */ + case DRX_STANDARD_PAL_SECAM_LP: + CHK_ERROR( PowerDownATV( demod, prevStandard, FALSE )); + break; +#endif + case DRX_STANDARD_UNKNOWN: + /* Do nothing */ + break; + case DRX_STANDARD_AUTO: /* fallthrough */ + default: + return ( DRX_STS_INVALID_ARG ); + } + + /* + Initialize channel independent registers + Power up new standard + */ + extAttr->standard=*standard; + + switch ( *standard ) + { +#ifndef DRXJ_VSB_ONLY + case DRX_STANDARD_ITU_A: /* fallthrough */ + case DRX_STANDARD_ITU_B: /* fallthrough */ + case DRX_STANDARD_ITU_C: + DUMMY_READ(); + break; +#endif + case DRX_STANDARD_8VSB: + CHK_ERROR(SetVSBLeakNGain(demod)); + break; +#ifndef DRXJ_DIGITAL_ONLY + case DRX_STANDARD_NTSC: /* fallthrough */ + case DRX_STANDARD_FM: /* fallthrough */ + case DRX_STANDARD_PAL_SECAM_BG: /* fallthrough */ + case DRX_STANDARD_PAL_SECAM_DK: /* fallthrough */ + case DRX_STANDARD_PAL_SECAM_I: /* fallthrough */ + case DRX_STANDARD_PAL_SECAM_L: /* fallthrough */ + case DRX_STANDARD_PAL_SECAM_LP: + CHK_ERROR( SetATVStandard( demod, standard )); + CHK_ERROR( PowerUpATV( demod, *standard )); + break; +#endif + default: + extAttr->standard=DRX_STANDARD_UNKNOWN; + return ( DRX_STS_INVALID_ARG ); + break; + } + + return (DRX_STS_OK); +rw_error: + /* Don't know what the standard is now ... try again */ + extAttr->standard=DRX_STANDARD_UNKNOWN; + return (DRX_STS_ERROR); +} + +/*============================================================================*/ + +/** +* \fn DRXStatus_t CtrlGetStandard() +* \brief Get modulation standard currently used to demodulate. +* \param standard Modulation standard. +* \return DRXStatus_t. +* +* Returns 8VSB, NTSC, QAM only. +* +*/ +static DRXStatus_t +CtrlGetStandard( pDRXDemodInstance_t demod, pDRXStandard_t standard ) +{ + pDRXJData_t extAttr = NULL; + extAttr = (pDRXJData_t)demod->myExtAttr; + + /* check arguments */ + if ( standard == NULL ) + { + return (DRX_STS_INVALID_ARG); + } + (*standard) = extAttr->standard; + DUMMY_READ(); + + return ( DRX_STS_OK ); +rw_error: + return (DRX_STS_ERROR); +} + +/*============================================================================*/ + +/** +* \fn DRXStatus_t CtrlGetCfgSymbolClockOffset() +* \brief Get frequency offsets of STR. +* \param pointer to s32_t. +* \return DRXStatus_t. +* +*/ +static DRXStatus_t +CtrlGetCfgSymbolClockOffset ( pDRXDemodInstance_t demod, + ps32_t rateOffset ) +{ + DRXStandard_t standard = DRX_STANDARD_UNKNOWN; + pI2CDeviceAddr_t devAddr = NULL; + pDRXJData_t extAttr = NULL; + + /* check arguments */ + if ( rateOffset == NULL ) + { + return (DRX_STS_INVALID_ARG); + } + + devAddr = demod -> myI2CDevAddr; + extAttr = (pDRXJData_t)demod->myExtAttr; + standard = extAttr->standard; + + switch ( standard ) { + case DRX_STANDARD_8VSB: /* fallthrough */ +#ifndef DRXJ_VSB_ONLY + case DRX_STANDARD_ITU_A: /* fallthrough */ + case DRX_STANDARD_ITU_B: /* fallthrough */ + case DRX_STANDARD_ITU_C: +#endif + CHK_ERROR ( GetSTRFreqOffset ( demod, rateOffset )); + break; + case DRX_STANDARD_NTSC: + case DRX_STANDARD_UNKNOWN: + default: + return (DRX_STS_INVALID_ARG); + } + + return ( DRX_STS_OK ); +rw_error: + return (DRX_STS_ERROR); +} +/*============================================================================*/ + +/** +* \fn DRXStatus_t CtrlPowerMode() +* \brief Set the power mode of the device to the specified power mode +* \param demod Pointer to demodulator instance. +* \param mode Pointer to new power mode. +* \return DRXStatus_t. +* \retval DRX_STS_OK Success +* \retval DRX_STS_ERROR I2C error or other failure +* \retval DRX_STS_INVALID_ARG Invalid mode argument. +* +* +*/ +static DRXStatus_t +CtrlPowerMode( pDRXDemodInstance_t demod, + pDRXPowerMode_t mode ) +{ + pDRXCommonAttr_t commonAttr = (pDRXCommonAttr_t)NULL; + pDRXJData_t extAttr = (pDRXJData_t)NULL; + pI2CDeviceAddr_t devAddr = (pI2CDeviceAddr_t)NULL; + u16_t sioCcPwdMode = 0; + + commonAttr = (pDRXCommonAttr_t)demod -> myCommonAttr; + extAttr = (pDRXJData_t)demod->myExtAttr; + devAddr = demod -> myI2CDevAddr; + + /* Check arguments */ + if ( mode == NULL ) + { + return (DRX_STS_INVALID_ARG); + } + + /* If already in requested power mode, do nothing */ + if ( commonAttr->currentPowerMode == *mode ) + { + return (DRX_STS_OK); + } + + switch ( *mode ) + { + case DRX_POWER_UP: + case DRXJ_POWER_DOWN_MAIN_PATH: + sioCcPwdMode = SIO_CC_PWD_MODE_LEVEL_NONE; + break; + case DRXJ_POWER_DOWN_CORE: + sioCcPwdMode = SIO_CC_PWD_MODE_LEVEL_CLOCK; + break; + case DRXJ_POWER_DOWN_PLL: + sioCcPwdMode = SIO_CC_PWD_MODE_LEVEL_PLL; + break; + case DRX_POWER_DOWN: + sioCcPwdMode = SIO_CC_PWD_MODE_LEVEL_OSC; + break; + default: + /* Unknow sleep mode */ + return (DRX_STS_INVALID_ARG); + break; + } + + + /* Check if device needs to be powered up */ + if ( ( commonAttr->currentPowerMode != DRX_POWER_UP ) ) + { + CHK_ERROR(PowerUpDevice(demod)); + } + + if ( ( *mode == DRX_POWER_UP ) ) + { + /* Restore analog & pin configuartion */ + } else { + /* Power down to requested mode */ + /* Backup some register settings */ + /* Set pins with possible pull-ups connected to them in input mode */ + /* Analog power down */ + /* ADC power down */ + /* Power down device */ + /* stop all comm_exec */ + /* + Stop and power down previous standard + */ + + switch ( extAttr->standard ) + { + case DRX_STANDARD_ITU_A: + case DRX_STANDARD_ITU_B: + case DRX_STANDARD_ITU_C: + CHK_ERROR( PowerDownQAM(demod, TRUE) ); + break; + case DRX_STANDARD_8VSB: + CHK_ERROR( PowerDownVSB(demod, TRUE) ); + break; + case DRX_STANDARD_PAL_SECAM_BG : /* fallthrough */ + case DRX_STANDARD_PAL_SECAM_DK : /* fallthrough */ + case DRX_STANDARD_PAL_SECAM_I : /* fallthrough */ + case DRX_STANDARD_PAL_SECAM_L : /* fallthrough */ + case DRX_STANDARD_PAL_SECAM_LP : /* fallthrough */ + case DRX_STANDARD_NTSC: /* fallthrough */ + case DRX_STANDARD_FM: + CHK_ERROR( PowerDownATV( demod, extAttr->standard, TRUE )); + break; + case DRX_STANDARD_UNKNOWN: + /* Do nothing */ + break; + case DRX_STANDARD_AUTO: /* fallthrough */ + default: + return ( DRX_STS_ERROR ); + } + + if (*mode != DRXJ_POWER_DOWN_MAIN_PATH) + { + WR16( devAddr, SIO_CC_PWD_MODE__A, sioCcPwdMode); + WR16( devAddr, SIO_CC_UPDATE__A , SIO_CC_UPDATE_KEY); + + /* Initialize HI, wakeup key especially before put IC to sleep */ + CHK_ERROR(InitHI(demod) ); + + extAttr -> HICfgCtrl |= SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ; + CHK_ERROR( HICfgCommand( demod ) ); + } + } + + commonAttr->currentPowerMode = *mode; + + return ( DRX_STS_OK ); +rw_error: + return (DRX_STS_ERROR); +} + +/*============================================================================*/ + +/** +* \fn DRXStatus_t CtrlVersion() +* \brief Report version of microcode and if possible version of device +* \param demod Pointer to demodulator instance. +* \param versionList Pointer to pointer of linked list of versions. +* \return DRXStatus_t. +* +* Using static structures so no allocation of memory is needed. +* Filling in all the fields each time, cause you don't know if they are +* changed by the application. +* +* For device: +* Major version number will be last two digits of family number. +* Minor number will be full respin number +* Patch will be metal fix number+1 +* Examples: +* DRX3942J A2 => number: 42.1.2 text: "DRX3942J:A2" +* DRX3933J B1 => number: 33.2.1 text: "DRX3933J:B1" +* +*/ +static DRXStatus_t +CtrlVersion( pDRXDemodInstance_t demod, + pDRXVersionList_t *versionList ) +{ + pDRXJData_t extAttr = (pDRXJData_t) (NULL); + pI2CDeviceAddr_t devAddr = (pI2CDeviceAddr_t) (NULL); + pDRXCommonAttr_t commonAttr = (pDRXCommonAttr_t)(NULL); + u16_t ucodeMajorMinor = 0; /* BCD Ma:Ma:Ma:Mi */ + u16_t ucodePatch = 0; /* BCD Pa:Pa:Pa:Pa */ + u16_t major = 0; + u16_t minor = 0; + u16_t patch = 0; + u16_t idx = 0; + u32_t jtag = 0; + u16_t subtype = 0; + u16_t mfx = 0; + u16_t bid = 0; + u16_t key = 0; + + static char ucodeName[] = "Microcode"; + static char deviceName[] = "Device"; + + devAddr = demod -> myI2CDevAddr; + extAttr = (pDRXJData_t)demod -> myExtAttr; + commonAttr = (pDRXCommonAttr_t)demod->myCommonAttr; + + /* Microcode version ****************************************/ + + extAttr->vVersion[0].moduleType = DRX_MODULE_MICROCODE; + extAttr->vVersion[0].moduleName = ucodeName; + extAttr->vVersion[0].vString = extAttr->vText[0]; + + if ( commonAttr->isOpened == TRUE ) + { + SARR16( devAddr, SCU_RAM_VERSION_HI__A, &ucodeMajorMinor ); + SARR16( devAddr, SCU_RAM_VERSION_LO__A, &ucodePatch ); + + /* Translate BCD to numbers and string */ + /* TODO: The most significant Ma and Pa will be ignored, check with spec */ + minor = (ucodeMajorMinor & 0xF); + ucodeMajorMinor >>= 4; + major = (ucodeMajorMinor & 0xF); + ucodeMajorMinor >>= 4; + major += (10* (ucodeMajorMinor & 0xF)); + patch = (ucodePatch & 0xF); + ucodePatch >>= 4; + patch += (10*(ucodePatch & 0xF)); + ucodePatch >>= 4; + patch += (100*(ucodePatch & 0xF)); + } + else + { + /* No microcode uploaded, No Rom existed, set version to 0.0.0 */ + patch = 0; + minor = 0; + major = 0; + } + extAttr->vVersion[0].vMajor = major; + extAttr->vVersion[0].vMinor = minor; + extAttr->vVersion[0].vPatch = patch; + + if ( major/10 != 0 ) + { + extAttr->vVersion[0].vString[idx++] = ((char)(major/10))+'0'; + major %= 10; + } + extAttr->vVersion[0].vString[idx++] = ((char)major)+'0'; + extAttr->vVersion[0].vString[idx++] = '.'; + extAttr->vVersion[0].vString[idx++] = ((char)minor)+'0'; + extAttr->vVersion[0].vString[idx++] = '.'; + if ( patch/100 != 0 ) + { + extAttr->vVersion[0].vString[idx++] = ((char)(patch/100))+'0'; + patch %= 100; + } + if ( patch/10 != 0 ) + { + extAttr->vVersion[0].vString[idx++] = ((char)(patch/10))+'0'; + patch %= 10; + } + extAttr->vVersion[0].vString[idx++] = ((char)patch)+'0'; + extAttr->vVersion[0].vString[idx] = '\0'; + + extAttr->vListElements[0].version = &(extAttr->vVersion[0]); + extAttr->vListElements[0].next = &(extAttr->vListElements[1]); + + + /* Device version ****************************************/ + /* Check device id */ + RR16( devAddr, SIO_TOP_COMM_KEY__A , &key); + WR16( devAddr, SIO_TOP_COMM_KEY__A , 0xFABA); + RR32( devAddr, SIO_TOP_JTAGID_LO__A , &jtag ); + RR16( devAddr, SIO_PDR_UIO_IN_HI__A , &bid); + WR16( devAddr, SIO_TOP_COMM_KEY__A , key); + + extAttr->vVersion[1].moduleType = DRX_MODULE_DEVICE; + extAttr->vVersion[1].moduleName = deviceName; + extAttr->vVersion[1].vString = extAttr->vText[1]; + extAttr->vVersion[1].vString[0] = 'D'; + extAttr->vVersion[1].vString[1] = 'R'; + extAttr->vVersion[1].vString[2] = 'X'; + extAttr->vVersion[1].vString[3] = '3'; + extAttr->vVersion[1].vString[4] = '9'; + extAttr->vVersion[1].vString[7] = 'J'; + extAttr->vVersion[1].vString[8] = ':'; + extAttr->vVersion[1].vString[11] = '\0'; + + /* DRX39xxJ type Ax */ + /* TODO semantics of mfx and spin are unclear */ + subtype = (u16_t)((jtag>>12)&0xFF); + mfx = (u16_t)(jtag>>29); + extAttr->vVersion[1].vMinor = 1; + if (mfx == 0x03) + { + extAttr->vVersion[1].vPatch = mfx+2; + } + else + { + extAttr->vVersion[1].vPatch = mfx+1; + } + extAttr->vVersion[1].vString[6] = ((char)(subtype&0xF))+'0'; + extAttr->vVersion[1].vMajor = (subtype & 0x0F); + subtype>>=4; + extAttr->vVersion[1].vString[5] = ((char)(subtype&0xF))+'0'; + extAttr->vVersion[1].vMajor += 10*subtype; + extAttr->vVersion[1].vString[9] = 'A'; + if (mfx == 0x03) + { + extAttr->vVersion[1].vString[10] = ((char)(mfx&0xF)) + '2' ; + } + else + { + extAttr->vVersion[1].vString[10] = ((char)(mfx&0xF)) + '1' ; + } + + extAttr->vListElements[1].version = &(extAttr->vVersion[1]); + extAttr->vListElements[1].next = (pDRXVersionList_t)(NULL); + + *versionList = &(extAttr->vListElements[0]); + + return ( DRX_STS_OK ); + + rw_error: + *versionList = (pDRXVersionList_t)(NULL); + return (DRX_STS_ERROR); + +} + +/*============================================================================*/ + +/** +* \fn DRXStatus_t CtrlProbeDevice() +* \brief Probe device, check if it is present +* \param demod Pointer to demodulator instance. +* \return DRXStatus_t. +* \retval DRX_STS_OK a drx39xxj device has been detected. +* \retval DRX_STS_ERROR no drx39xxj device detected. +* +* This funtion can be caled before open() and after close(). +* +*/ + +static DRXStatus_t +CtrlProbeDevice( pDRXDemodInstance_t demod ) +{ + DRXPowerMode_t orgPowerMode = DRX_POWER_UP; + DRXStatus_t retStatus = DRX_STS_OK; + pDRXCommonAttr_t commonAttr = (pDRXCommonAttr_t)(NULL); + + commonAttr = (pDRXCommonAttr_t)demod -> myCommonAttr; + + if ( commonAttr->isOpened == FALSE || commonAttr->currentPowerMode != DRX_POWER_UP) + { + pI2CDeviceAddr_t devAddr = NULL; + DRXPowerMode_t powerMode = DRX_POWER_UP; + u32_t jtag = 0; + + devAddr = demod -> myI2CDevAddr; + + /* Remeber original power mode */ + orgPowerMode = commonAttr->currentPowerMode; + + if(demod->myCommonAttr->isOpened == FALSE) + { + CHK_ERROR(PowerUpDevice(demod)); + commonAttr->currentPowerMode = DRX_POWER_UP; + } + else + { + /* Wake-up device, feedback from device */ + CHK_ERROR( CtrlPowerMode( demod, &powerMode )); + } + /* Initialize HI, wakeup key especially */ + CHK_ERROR(InitHI(demod) ); + + /* Check device id */ + RR32( devAddr, SIO_TOP_JTAGID_LO__A , &jtag); + jtag = (jtag>>12) & 0xFFFF; + switch ( jtag ) + { + case 0x3931: /* fallthrough */ + case 0x3932: /* fallthrough */ + case 0x3933: /* fallthrough */ + case 0x3934: /* fallthrough */ + case 0x3941: /* fallthrough */ + case 0x3942: /* fallthrough */ + case 0x3943: /* fallthrough */ + case 0x3944: /* fallthrough */ + case 0x3945: /* fallthrough */ + case 0x3946: + /* ok , do nothing */ + break; + default: + retStatus = DRX_STS_ERROR; + break; + } + + /* Device was not opened, return to orginal powermode, + feedback from device */ + CHK_ERROR( CtrlPowerMode( demod, &orgPowerMode )); + } + else + { + /* dummy read to make this function fail in case device + suddenly disappears after a succesful DRX_Open */ + DUMMY_READ(); + } + + return ( retStatus ); + + rw_error: + commonAttr->currentPowerMode=orgPowerMode; + return (DRX_STS_ERROR); +} + +#ifdef DRXJ_SPLIT_UCODE_UPLOAD +/*============================================================================*/ + +/** +* \fn DRXStatus_t IsMCBlockAudio() +* \brief Check if MC block is Audio or not Audio. +* \param addr Pointer to demodulator instance. +* \param audioUpload TRUE if MC block is Audio + FALSE if MC block not Audio +* \return Bool_t. +*/ +Bool_t IsMCBlockAudio( u32_t addr ) +{ + if ( ( addr == AUD_XFP_PRAM_4K__A ) || + ( addr == AUD_XDFP_PRAM_4K__A ) ) + { + return ( TRUE ); + } + return ( FALSE ); +} + +/*============================================================================*/ + +/** +* \fn DRXStatus_t CtrlUCodeUpload() +* \brief Handle Audio or !Audio part of microcode upload. +* \param demod Pointer to demodulator instance. +* \param mcInfo Pointer to information about microcode data. +* \param action Either UCODE_UPLOAD or UCODE_VERIFY. +* \param uploadAudioMC TRUE if Audio MC need to be uploaded. + FALSE if !Audio MC need to be uploaded. +* \return DRXStatus_t. +*/ +static DRXStatus_t +CtrlUCodeUpload( pDRXDemodInstance_t demod, + pDRXUCodeInfo_t mcInfo, + DRXUCodeAction_t action, + Bool_t uploadAudioMC ) +{ + u16_t i = 0; + u16_t mcNrOfBlks = 0; + u16_t mcMagicWord = 0; + pu8_t mcData = (pu8_t)(NULL); + pI2CDeviceAddr_t devAddr = (pI2CDeviceAddr_t)(NULL); + pDRXJData_t extAttr = (pDRXJData_t)(NULL); + + devAddr = demod -> myI2CDevAddr; + extAttr = (pDRXJData_t)demod -> myExtAttr; + + /* Check arguments */ + if ( ( mcInfo == NULL ) || + ( mcInfo->mcData == NULL ) || + ( mcInfo->mcSize == 0 ) ) + { + return DRX_STS_INVALID_ARG; + } + + mcData = mcInfo->mcData; + + /* Check data */ + mcMagicWord = UCodeRead16( mcData ); + mcData += sizeof( u16_t ); + mcNrOfBlks = UCodeRead16( mcData ); + mcData += sizeof( u16_t ); + + if ( ( mcMagicWord != DRXJ_UCODE_MAGIC_WORD ) || + ( mcNrOfBlks == 0 ) ) + { + /* wrong endianess or wrong data ? */ + return DRX_STS_INVALID_ARG; + } + + /* Process microcode blocks */ + for( i = 0 ; i<mcNrOfBlks ; i++ ) + { + DRXUCodeBlockHdr_t blockHdr; + u16_t mcBlockNrBytes = 0; + + /* Process block header */ + blockHdr.addr = UCodeRead32( mcData ); + mcData += sizeof(u32_t); + blockHdr.size = UCodeRead16( mcData ); + mcData += sizeof(u16_t); + blockHdr.flags = UCodeRead16( mcData ); + mcData += sizeof(u16_t); + blockHdr.CRC = UCodeRead16( mcData ); + mcData += sizeof(u16_t); + + /* Check block header on: + - no data + - data larger then 64Kb + - if CRC enabled check CRC + */ + if ( ( blockHdr.size == 0 ) || + ( blockHdr.size > 0x7FFF ) || + ( (( blockHdr.flags & DRXJ_UCODE_CRC_FLAG ) != 0) && + ( blockHdr.CRC != UCodeComputeCRC( mcData, blockHdr.size)) ) + ) + { + /* Wrong data ! */ + return DRX_STS_INVALID_ARG; + } + + mcBlockNrBytes = blockHdr.size * sizeof(u16_t); + + /* Perform the desired action */ + /* Check which part of MC need to be uploaded - Audio or not Audio */ + if( IsMCBlockAudio( blockHdr.addr ) == uploadAudioMC ) + { + switch ( action ) { + /*===================================================================*/ + case UCODE_UPLOAD : + { + /* Upload microcode */ + if ( demod->myAccessFunct->writeBlockFunc( + devAddr, + (DRXaddr_t) blockHdr.addr, + mcBlockNrBytes, + mcData, + 0x0000) != DRX_STS_OK) + { + return (DRX_STS_ERROR); + } + }; + break; + + /*===================================================================*/ + case UCODE_VERIFY : + { + int result = 0; + u8_t mcDataBuffer[DRXJ_UCODE_MAX_BUF_SIZE]; + u32_t bytesToCompare=0; + u32_t bytesLeftToCompare=0; + DRXaddr_t currAddr = (DRXaddr_t)0; + pu8_t currPtr =NULL; + + bytesLeftToCompare = mcBlockNrBytes; + currAddr = blockHdr.addr; + currPtr = mcData; + + while( bytesLeftToCompare != 0 ) + { + if (bytesLeftToCompare > ((u32_t)DRXJ_UCODE_MAX_BUF_SIZE) ) + { + bytesToCompare = ((u32_t)DRXJ_UCODE_MAX_BUF_SIZE); + } else { + bytesToCompare = bytesLeftToCompare; + } + + if ( demod->myAccessFunct->readBlockFunc( + devAddr, + currAddr, + (u16_t)bytesToCompare, + (pu8_t)mcDataBuffer, + 0x0000) != DRX_STS_OK) + { + return (DRX_STS_ERROR); + } + + result = DRXBSP_HST_Memcmp( currPtr, + mcDataBuffer, + bytesToCompare); + + if ( result != 0 ) + { + return (DRX_STS_ERROR); + }; + + currAddr += ((DRXaddr_t)(bytesToCompare/2)); + currPtr = &(currPtr[bytesToCompare]); + bytesLeftToCompare -= ((u32_t)bytesToCompare); + } /* while( bytesToCompare > DRXJ_UCODE_MAX_BUF_SIZE ) */ + }; + break; + + /*===================================================================*/ + default: + return DRX_STS_INVALID_ARG; + break; + + } /* switch ( action ) */ + } /* if( IsMCBlockAudio( blockHdr.addr ) == uploadAudioMC ) */ + + /* Next block */ + mcData += mcBlockNrBytes; + } /* for( i = 0 ; i<mcNrOfBlks ; i++ ) */ + + if ( uploadAudioMC == FALSE ) + { + extAttr->flagAudMcUploaded = FALSE; + } + + return (DRX_STS_OK); +} +#endif /* DRXJ_SPLIT_UCODE_UPLOAD */ + +/*============================================================================*/ +/*== CTRL Set/Get Config related functions ===================================*/ +/*============================================================================*/ + +/*===== SigStrength() =========================================================*/ +/** +* \fn DRXStatus_t CtrlSigStrength() +* \brief Retrieve signal strength. +* \param devmod Pointer to demodulator instance. +* \param sigQuality Pointer to signal strength data; range 0, .. , 100. +* \return DRXStatus_t. +* \retval DRX_STS_OK sigStrength contains valid data. +* \retval DRX_STS_INVALID_ARG sigStrength is NULL. +* \retval DRX_STS_ERROR Erroneous data, sigStrength contains invalid data. + +*/ +static DRXStatus_t +CtrlSigStrength( pDRXDemodInstance_t demod, + pu16_t sigStrength ) +{ + pDRXJData_t extAttr = NULL; + DRXStandard_t standard = DRX_STANDARD_UNKNOWN; + + /* Check arguments */ + if ( ( sigStrength == NULL ) || + ( demod == NULL ) ) + { + return (DRX_STS_INVALID_ARG); + } + + extAttr = (pDRXJData_t)demod->myExtAttr; + standard = extAttr->standard; + *sigStrength = 0; + + /* Signal strength indication for each standard */ + switch ( standard ) { + case DRX_STANDARD_8VSB: /* fallthrough */ +#ifndef DRXJ_VSB_ONLY + case DRX_STANDARD_ITU_A: /* fallthrough */ + case DRX_STANDARD_ITU_B: /* fallthrough */ + case DRX_STANDARD_ITU_C: +#endif + CHK_ERROR( GetSigStrength( demod, sigStrength ) ); + break; +#ifndef DRXJ_DIGITAL_ONLY + case DRX_STANDARD_PAL_SECAM_BG : /* fallthrough */ + case DRX_STANDARD_PAL_SECAM_DK : /* fallthrough */ + case DRX_STANDARD_PAL_SECAM_I : /* fallthrough */ + case DRX_STANDARD_PAL_SECAM_L : /* fallthrough */ + case DRX_STANDARD_PAL_SECAM_LP : /* fallthrough */ + case DRX_STANDARD_NTSC: /* fallthrough */ + case DRX_STANDARD_FM: + CHK_ERROR( GetAtvSigStrength( demod, sigStrength ) ); + break; +#endif + case DRX_STANDARD_UNKNOWN: /* fallthrough */ + default: + return (DRX_STS_INVALID_ARG); + } + + /* TODO */ + /* find out if signal strength is calculated in the same way for all standards */ + return (DRX_STS_OK); + rw_error: + return (DRX_STS_ERROR); +} + +/*============================================================================*/ +/** +* \fn DRXStatus_t CtrlGetCfgOOBMisc() +* \brief Get current state information of OOB. +* \param pointer to DRXJCfgOOBMisc_t. +* \return DRXStatus_t. +* +*/ +#ifndef DRXJ_DIGITAL_ONLY +static DRXStatus_t +CtrlGetCfgOOBMisc ( pDRXDemodInstance_t demod, pDRXJCfgOOBMisc_t misc ) +{ + pI2CDeviceAddr_t devAddr = NULL; + u16_t lock = 0U; + u16_t state = 0U; + u16_t data = 0U; + u16_t digitalAGCMant = 0U; + u16_t digitalAGCExp = 0U; + + /* check arguments */ + if ( misc == NULL ) + { + return (DRX_STS_INVALID_ARG); + } + devAddr = demod -> myI2CDevAddr; + + /* TODO */ + /* check if the same registers are used for all standards (QAM/VSB/ATV) */ + RR16( devAddr, ORX_NSU_TUN_IFGAIN_W__A, &misc->agc.IFAGC ); + RR16( devAddr, ORX_NSU_TUN_RFGAIN_W__A, &misc->agc.RFAGC ); + RR16( devAddr, ORX_FWP_SRC_DGN_W__A, &data ); + + digitalAGCMant = data & ORX_FWP_SRC_DGN_W_MANT__M; + digitalAGCExp = (data & ORX_FWP_SRC_DGN_W_EXP__M) + >> ORX_FWP_SRC_DGN_W_EXP__B; + misc->agc.DigitalAGC = digitalAGCMant << digitalAGCExp; + + SARR16( devAddr, SCU_RAM_ORX_SCU_LOCK__A, &lock ); + + misc->anaGainLock = ((lock & 0x0001)?TRUE:FALSE); + misc->digGainLock = ((lock & 0x0002)?TRUE:FALSE); + misc->freqLock = ((lock & 0x0004)?TRUE:FALSE); + misc->phaseLock = ((lock & 0x0008)?TRUE:FALSE); + misc->symTimingLock = ((lock & 0x0010)?TRUE:FALSE); + misc->eqLock = ((lock & 0x0020)?TRUE:FALSE); + + SARR16( devAddr, SCU_RAM_ORX_SCU_STATE__A, &state ); + misc->state = (state>>8) & 0xff; + + return ( DRX_STS_OK ); +rw_error: + return (DRX_STS_ERROR); +} +#endif + +/** +* \fn DRXStatus_t CtrlGetCfgVSBMisc() +* \brief Get current state information of OOB. +* \param pointer to DRXJCfgOOBMisc_t. +* \return DRXStatus_t. +* +*/ +static DRXStatus_t +CtrlGetCfgVSBMisc ( pDRXDemodInstance_t demod, pDRXJCfgVSBMisc_t misc ) +{ + pI2CDeviceAddr_t devAddr = NULL; + + /* check arguments */ + if ( misc == NULL ) + { + return (DRX_STS_INVALID_ARG); + } + devAddr = demod -> myI2CDevAddr; + + CHK_ERROR(GetVSBSymbErr(devAddr, &misc->symbError)); + + return ( DRX_STS_OK ); +rw_error: + return (DRX_STS_ERROR); +} +/*============================================================================*/ + +/** +* \fn DRXStatus_t CtrlSetCfgAgcIf() +* \brief Set IF AGC. +* \param demod demod instance +* \param agcSettings If agc configuration +* \return DRXStatus_t. +* +* Check arguments +* Dispatch handling to standard specific function. +* +*/ +static DRXStatus_t +CtrlSetCfgAgcIf ( pDRXDemodInstance_t demod, pDRXJCfgAgc_t agcSettings ) +{ + /* check arguments */ + if ( agcSettings == NULL ) + { + return ( DRX_STS_INVALID_ARG ); + } + + switch ( agcSettings->ctrlMode ) { + case DRX_AGC_CTRL_AUTO: /* fallthrough */ + case DRX_AGC_CTRL_USER: /* fallthrough */ + case DRX_AGC_CTRL_OFF: /* fallthrough */ + break; + default: + return ( DRX_STS_INVALID_ARG ); + } + + /* Distpatch */ + switch ( agcSettings->standard ) { + case DRX_STANDARD_8VSB: /* fallthrough */ +#ifndef DRXJ_VSB_ONLY + case DRX_STANDARD_ITU_A: /* fallthrough */ + case DRX_STANDARD_ITU_B: /* fallthrough */ + case DRX_STANDARD_ITU_C: +#endif +#ifndef DRXJ_DIGITAL_ONLY + case DRX_STANDARD_PAL_SECAM_BG : /* fallthrough */ + case DRX_STANDARD_PAL_SECAM_DK : /* fallthrough */ + case DRX_STANDARD_PAL_SECAM_I : /* fallthrough */ + case DRX_STANDARD_PAL_SECAM_L : /* fallthrough */ + case DRX_STANDARD_PAL_SECAM_LP : /* fallthrough */ + case DRX_STANDARD_NTSC: /* fallthrough */ + case DRX_STANDARD_FM: +#endif + return SetAgcIf ( demod, agcSettings, TRUE); + case DRX_STANDARD_UNKNOWN: + default: + return ( DRX_STS_INVALID_ARG ); + } + + return ( DRX_STS_OK ); +} + +/*============================================================================*/ + +/** +* \fn DRXStatus_t CtrlGetCfgAgcIf() +* \brief Retrieve IF AGC settings. +* \param demod demod instance +* \param agcSettings If agc configuration +* \return DRXStatus_t. +* +* Check arguments +* Dispatch handling to standard specific function. +* +*/ +static DRXStatus_t +CtrlGetCfgAgcIf ( pDRXDemodInstance_t demod, pDRXJCfgAgc_t agcSettings ) +{ + /* check arguments */ + if ( agcSettings == NULL ) + { + return ( DRX_STS_INVALID_ARG ); + } + + /* Distpatch */ + switch ( agcSettings->standard ) { + case DRX_STANDARD_8VSB: /* fallthrough */ +#ifndef DRXJ_VSB_ONLY + case DRX_STANDARD_ITU_A: /* fallthrough */ + case DRX_STANDARD_ITU_B: /* fallthrough */ + case DRX_STANDARD_ITU_C: +#endif +#ifndef DRXJ_DIGITAL_ONLY + case DRX_STANDARD_PAL_SECAM_BG : /* fallthrough */ + case DRX_STANDARD_PAL_SECAM_DK : /* fallthrough */ + case DRX_STANDARD_PAL_SECAM_I : /* fallthrough */ + case DRX_STANDARD_PAL_SECAM_L : /* fallthrough */ + case DRX_STANDARD_PAL_SECAM_LP : /* fallthrough */ + case DRX_STANDARD_NTSC: /* fallthrough */ + case DRX_STANDARD_FM: +#endif + return GetAgcIf ( demod, agcSettings); + case DRX_STANDARD_UNKNOWN: + default: + return ( DRX_STS_INVALID_ARG ); + } + + return ( DRX_STS_OK ); +} + +/*============================================================================*/ + +/** +* \fn DRXStatus_t CtrlSetCfgAgcRf() +* \brief Set RF AGC. +* \param demod demod instance +* \param agcSettings rf agc configuration +* \return DRXStatus_t. +* +* Check arguments +* Dispatch handling to standard specific function. +* +*/ +static DRXStatus_t +CtrlSetCfgAgcRf ( pDRXDemodInstance_t demod, pDRXJCfgAgc_t agcSettings ) +{ + /* check arguments */ + if ( agcSettings == NULL ) + { + return ( DRX_STS_INVALID_ARG ); + } + + switch ( agcSettings->ctrlMode ) { + case DRX_AGC_CTRL_AUTO: /* fallthrough */ + case DRX_AGC_CTRL_USER: /* fallthrough */ + case DRX_AGC_CTRL_OFF: + break; + default: + return ( DRX_STS_INVALID_ARG ); + } + + /* Distpatch */ + switch ( agcSettings->standard ) { + case DRX_STANDARD_8VSB: /* fallthrough */ +#ifndef DRXJ_VSB_ONLY + case DRX_STANDARD_ITU_A: /* fallthrough */ + case DRX_STANDARD_ITU_B: /* fallthrough */ + case DRX_STANDARD_ITU_C: +#endif +#ifndef DRXJ_DIGITAL_ONLY + case DRX_STANDARD_PAL_SECAM_BG : /* fallthrough */ + case DRX_STANDARD_PAL_SECAM_DK : /* fallthrough */ + case DRX_STANDARD_PAL_SECAM_I : /* fallthrough */ + case DRX_STANDARD_PAL_SECAM_L : /* fallthrough */ + case DRX_STANDARD_PAL_SECAM_LP : /* fallthrough */ + case DRX_STANDARD_NTSC: /* fallthrough */ + case DRX_STANDARD_FM: +#endif + return SetAgcRf ( demod, agcSettings, TRUE); + case DRX_STANDARD_UNKNOWN: + default: + return ( DRX_STS_INVALID_ARG ); + } + + return ( DRX_STS_OK ); +} + +/*============================================================================*/ + +/** +* \fn DRXStatus_t CtrlGetCfgAgcRf() +* \brief Retrieve RF AGC settings. +* \param demod demod instance +* \param agcSettings Rf agc configuration +* \return DRXStatus_t. +* +* Check arguments +* Dispatch handling to standard specific function. +* +*/ +static DRXStatus_t +CtrlGetCfgAgcRf ( pDRXDemodInstance_t demod, pDRXJCfgAgc_t agcSettings ) +{ + /* check arguments */ + if ( agcSettings == NULL ) + { + return ( DRX_STS_INVALID_ARG ); + } + + /* Distpatch */ + switch ( agcSettings->standard ) { + case DRX_STANDARD_8VSB: /* fallthrough */ +#ifndef DRXJ_VSB_ONLY + case DRX_STANDARD_ITU_A: /* fallthrough */ + case DRX_STANDARD_ITU_B: /* fallthrough */ + case DRX_STANDARD_ITU_C: +#endif +#ifndef DRXJ_DIGITAL_ONLY + case DRX_STANDARD_PAL_SECAM_BG : /* fallthrough */ + case DRX_STANDARD_PAL_SECAM_DK : /* fallthrough */ + case DRX_STANDARD_PAL_SECAM_I : /* fallthrough */ + case DRX_STANDARD_PAL_SECAM_L : /* fallthrough */ + case DRX_STANDARD_PAL_SECAM_LP : /* fallthrough */ + case DRX_STANDARD_NTSC: /* fallthrough */ + case DRX_STANDARD_FM: +#endif + return GetAgcRf ( demod, agcSettings); + case DRX_STANDARD_UNKNOWN: + default: + return ( DRX_STS_INVALID_ARG ); + } + + return ( DRX_STS_OK ); +} + + +/*============================================================================*/ + +/** +* \fn DRXStatus_t CtrlGetCfgAgcInternal() +* \brief Retrieve internal AGC value. +* \param demod demod instance +* \param u16_t +* \return DRXStatus_t. +* +* Check arguments +* Dispatch handling to standard specific function. +* +*/ +static DRXStatus_t +CtrlGetCfgAgcInternal ( pDRXDemodInstance_t demod, pu16_t agcInternal ) +{ + pI2CDeviceAddr_t devAddr = NULL; + DRXLockStatus_t lockStatus = DRX_NOT_LOCKED; + pDRXJData_t extAttr = NULL; + u16_t iqmCfScaleSh = 0; + u16_t iqmCfPower = 0; + u16_t iqmCfAmp = 0; + u16_t iqmCfGain = 0; + + /* check arguments */ + if ( agcInternal == NULL ) + { + return ( DRX_STS_INVALID_ARG ); + } + devAddr = demod -> myI2CDevAddr; + extAttr = (pDRXJData_t)demod->myExtAttr; + + CHK_ERROR( CtrlLockStatus( demod, &lockStatus) ); + if ( lockStatus != DRXJ_DEMOD_LOCK && lockStatus != DRX_LOCKED ) + { + *agcInternal = 0; + return DRX_STS_OK; + } + + /* Distpatch */ + switch ( extAttr->standard ) { + case DRX_STANDARD_8VSB: + iqmCfGain = 57; + break; +#ifndef DRXJ_VSB_ONLY + case DRX_STANDARD_ITU_A: + case DRX_STANDARD_ITU_B: + case DRX_STANDARD_ITU_C: + switch ( extAttr->constellation ) + { + case DRX_CONSTELLATION_QAM256: + case DRX_CONSTELLATION_QAM128: + case DRX_CONSTELLATION_QAM32: + case DRX_CONSTELLATION_QAM16: + iqmCfGain = 57; + break; + case DRX_CONSTELLATION_QAM64: + iqmCfGain = 56; + break; + default: + return (DRX_STS_ERROR); + } + break; +#endif + default: + return ( DRX_STS_INVALID_ARG ); + } + + RR16( devAddr, IQM_CF_POW__A, &iqmCfPower); + RR16( devAddr, IQM_CF_SCALE_SH__A, &iqmCfScaleSh); + RR16( devAddr, IQM_CF_AMP__A, &iqmCfAmp); + /* IQM_CF_PWR_CORRECTION_dB = 3; + P5dB =10*log10(IQM_CF_POW)+12-6*9-IQM_CF_PWR_CORRECTION_dB; */ + /* P4dB = P5dB -20*log10(IQM_CF_AMP)-6*10 + -IQM_CF_Gain_dB-18+6*(27-IQM_CF_SCALE_SH*2-10) + +6*7+10*log10(1+0.115/4); */ + /* PadcdB = P4dB +3 -6 +60; dBmV */ + *agcInternal = (u16_t) ( Log10Times100 (iqmCfPower) + - 2 * Log10Times100 (iqmCfAmp) + - iqmCfGain + - 120 * iqmCfScaleSh + + 781 ); + + return ( DRX_STS_OK ); +rw_error: + return (DRX_STS_ERROR); +} + +/*============================================================================*/ + +/** +* \fn DRXStatus_t CtrlSetCfgPreSaw() +* \brief Set Pre-saw reference. +* \param demod demod instance +* \param pu16_t +* \return DRXStatus_t. +* +* Check arguments +* Dispatch handling to standard specific function. +* +*/ +static DRXStatus_t +CtrlSetCfgPreSaw ( pDRXDemodInstance_t demod, pDRXJCfgPreSaw_t preSaw ) +{ + pI2CDeviceAddr_t devAddr = NULL; + pDRXJData_t extAttr = NULL; + + devAddr = demod -> myI2CDevAddr; + extAttr = (pDRXJData_t)demod->myExtAttr; + + /* check arguments */ + if ( ( preSaw == NULL ) || + ( preSaw->reference > IQM_AF_PDREF__M ) + ) + { + return ( DRX_STS_INVALID_ARG ); + } + + /* Only if standard is currently active*/ + if ( ( extAttr->standard == preSaw->standard ) || + ( DRXJ_ISQAMSTD( extAttr->standard ) && + DRXJ_ISQAMSTD( preSaw->standard ) ) || + ( DRXJ_ISATVSTD( extAttr->standard ) && + DRXJ_ISATVSTD( preSaw->standard ) ) ) + { + WR16( devAddr, IQM_AF_PDREF__A , preSaw->reference); + } + + /* Store pre-saw settings */ + switch ( preSaw->standard){ + case DRX_STANDARD_8VSB: + extAttr->vsbPreSawCfg = *preSaw; + break; +#ifndef DRXJ_VSB_ONLY + case DRX_STANDARD_ITU_A: /* fallthrough */ + case DRX_STANDARD_ITU_B: /* fallthrough */ + case DRX_STANDARD_ITU_C: + extAttr->qamPreSawCfg = *preSaw; + break; +#endif +#ifndef DRXJ_DIGITAL_ONLY + case DRX_STANDARD_PAL_SECAM_BG : /* fallthrough */ + case DRX_STANDARD_PAL_SECAM_DK : /* fallthrough */ + case DRX_STANDARD_PAL_SECAM_I : /* fallthrough */ + case DRX_STANDARD_PAL_SECAM_L : /* fallthrough */ + case DRX_STANDARD_PAL_SECAM_LP : /* fallthrough */ + case DRX_STANDARD_NTSC: /* fallthrough */ + case DRX_STANDARD_FM: + extAttr->atvPreSawCfg = *preSaw; + break; +#endif + default: + return (DRX_STS_INVALID_ARG); + } + + return ( DRX_STS_OK ); +rw_error: + return (DRX_STS_ERROR); +} + +/*============================================================================*/ + +/** +* \fn DRXStatus_t CtrlSetCfgAfeGain() +* \brief Set AFE Gain. +* \param demod demod instance +* \param pu16_t +* \return DRXStatus_t. +* +* Check arguments +* Dispatch handling to standard specific function. +* +*/ +static DRXStatus_t +CtrlSetCfgAfeGain ( pDRXDemodInstance_t demod, pDRXJCfgAfeGain_t afeGain ) +{ + pI2CDeviceAddr_t devAddr = NULL; + pDRXJData_t extAttr = NULL; + u8_t gain = 0; + + /* check arguments */ + if ( afeGain == NULL ) + { + return (DRX_STS_INVALID_ARG); + } + + devAddr = demod -> myI2CDevAddr; + extAttr = (pDRXJData_t)demod->myExtAttr; + + switch ( afeGain->standard){ + case DRX_STANDARD_8VSB: /* fallthrough */ +#ifndef DRXJ_VSB_ONLY + case DRX_STANDARD_ITU_A: /* fallthrough */ + case DRX_STANDARD_ITU_B: /* fallthrough */ + case DRX_STANDARD_ITU_C: +#endif + /* Do nothing */ + break; + default: + return (DRX_STS_INVALID_ARG); + } + + /* TODO PGA gain is also written by microcode (at least by QAM and VSB) + So I (PJ) think interface requires choice between auto, user mode */ + + if (afeGain->gain >= 329) + gain = 15; + else if (afeGain->gain <= 147) + gain = 0; + else + gain = (afeGain->gain - 140 + 6) / 13; + + /* Only if standard is currently active*/ + if( extAttr->standard == afeGain->standard ) + WR16( devAddr, IQM_AF_PGA_GAIN__A, gain); + + /* Store AFE Gain settings */ + switch ( afeGain->standard){ + case DRX_STANDARD_8VSB: + extAttr->vsbPgaCfg = gain * 13 + 140; + break; +#ifndef DRXJ_VSB_ONLY + case DRX_STANDARD_ITU_A: /* fallthrough */ + case DRX_STANDARD_ITU_B: /* fallthrough */ + case DRX_STANDARD_ITU_C: + extAttr->qamPgaCfg = gain * 13 + 140; + break; +#endif + default: + return (DRX_STS_ERROR); + } + + return ( DRX_STS_OK ); +rw_error: + return (DRX_STS_ERROR); +} + +/*============================================================================*/ + +/** +* \fn DRXStatus_t CtrlGetCfgPreSaw() +* \brief Get Pre-saw reference setting. +* \param demod demod instance +* \param pu16_t +* \return DRXStatus_t. +* +* Check arguments +* Dispatch handling to standard specific function. +* +*/ +static DRXStatus_t +CtrlGetCfgPreSaw ( pDRXDemodInstance_t demod, pDRXJCfgPreSaw_t preSaw ) +{ + pI2CDeviceAddr_t devAddr = NULL; + pDRXJData_t extAttr = NULL; + + /* check arguments */ + if ( preSaw == NULL ) + { + return ( DRX_STS_INVALID_ARG ); + } + + devAddr = demod -> myI2CDevAddr; + extAttr = (pDRXJData_t)demod->myExtAttr; + + switch ( preSaw->standard ){ + case DRX_STANDARD_8VSB: + *preSaw = extAttr->vsbPreSawCfg; + break; +#ifndef DRXJ_VSB_ONLY + case DRX_STANDARD_ITU_A: /* fallthrough */ + case DRX_STANDARD_ITU_B: /* fallthrough */ + case DRX_STANDARD_ITU_C: + *preSaw = extAttr->qamPreSawCfg; + break; +#endif +#ifndef DRXJ_DIGITAL_ONLY + case DRX_STANDARD_PAL_SECAM_BG : /* fallthrough */ + case DRX_STANDARD_PAL_SECAM_DK : /* fallthrough */ + case DRX_STANDARD_PAL_SECAM_I : /* fallthrough */ + case DRX_STANDARD_PAL_SECAM_L : /* fallthrough */ + case DRX_STANDARD_PAL_SECAM_LP : /* fallthrough */ + case DRX_STANDARD_NTSC: + extAttr->atvPreSawCfg.standard = DRX_STANDARD_NTSC; + *preSaw = extAttr->atvPreSawCfg; + break; + case DRX_STANDARD_FM: + extAttr->atvPreSawCfg.standard = DRX_STANDARD_FM; + *preSaw = extAttr->atvPreSawCfg; + break; +#endif + default: + return (DRX_STS_INVALID_ARG); + } + + return ( DRX_STS_OK ); +} + +/*============================================================================*/ + +/** +* \fn DRXStatus_t CtrlGetCfgAfeGain() +* \brief Get AFE Gain. +* \param demod demod instance +* \param pu16_t +* \return DRXStatus_t. +* +* Check arguments +* Dispatch handling to standard specific function. +* +*/ +static DRXStatus_t +CtrlGetCfgAfeGain ( pDRXDemodInstance_t demod, pDRXJCfgAfeGain_t afeGain ) +{ + pI2CDeviceAddr_t devAddr = NULL; + pDRXJData_t extAttr = NULL; + + /* check arguments */ + if ( afeGain == NULL ) + { + return ( DRX_STS_INVALID_ARG ); + } + + devAddr = demod -> myI2CDevAddr; + extAttr = (pDRXJData_t)demod->myExtAttr; + + switch ( afeGain->standard){ + case DRX_STANDARD_8VSB: + afeGain->gain = extAttr->vsbPgaCfg; + break; +#ifndef DRXJ_VSB_ONLY + case DRX_STANDARD_ITU_A: /* fallthrough */ + case DRX_STANDARD_ITU_B: /* fallthrough */ + case DRX_STANDARD_ITU_C: + afeGain->gain = extAttr->qamPgaCfg; + break; +#endif + default: + return (DRX_STS_INVALID_ARG); + } + + return ( DRX_STS_OK ); +} + +/*============================================================================*/ + +/** +* \fn DRXStatus_t CtrlGetFecMeasSeqCount() +* \brief Get FEC measurement sequnce number. +* \param demod demod instance +* \param pu16_t +* \return DRXStatus_t. +* +* Check arguments +* Dispatch handling to standard specific function. +* +*/ +static DRXStatus_t +CtrlGetFecMeasSeqCount ( pDRXDemodInstance_t demod, pu16_t fecMeasSeqCount) +{ + /* check arguments */ + if ( fecMeasSeqCount == NULL ) + { + return ( DRX_STS_INVALID_ARG ); + } + + RR16 ( demod->myI2CDevAddr, SCU_RAM_FEC_MEAS_COUNT__A, fecMeasSeqCount ); + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} +/*============================================================================*/ + +/** +* \fn DRXStatus_t CtrlGetAccumCrRSCwErr() +* \brief Get accumulative corrected RS codeword number. +* \param demod demod instance +* \param pu32_t +* \return DRXStatus_t. +* +* Check arguments +* Dispatch handling to standard specific function. +* +*/ +static DRXStatus_t +CtrlGetAccumCrRSCwErr ( pDRXDemodInstance_t demod, pu32_t accumCrRsCWErr) +{ + if(accumCrRsCWErr == NULL) + { + return (DRX_STS_INVALID_ARG); + } + + RR32 ( demod->myI2CDevAddr, SCU_RAM_FEC_ACCUM_CW_CORRECTED_LO__A, accumCrRsCWErr ); + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} + +/** +* \fn DRXStatus_t CtrlSetCfg() +* \brief Set 'some' configuration of the device. +* \param devmod Pointer to demodulator instance. +* \param config Pointer to configuration parameters (type and data). +* \return DRXStatus_t. + +*/ +static DRXStatus_t +CtrlSetCfg( pDRXDemodInstance_t demod, + pDRXCfg_t config ) +{ + if ( config == NULL ) + { + return (DRX_STS_INVALID_ARG); + } + + DUMMY_READ(); + switch ( config->cfgType ) + { + case DRX_CFG_MPEG_OUTPUT: + return CtrlSetCfgMPEGOutput( demod, (pDRXCfgMPEGOutput_t) config->cfgData ); + case DRX_CFG_PINS_SAFE_MODE: + return CtrlSetCfgPdrSafeMode( demod, (pBool_t) config->cfgData ); + case DRXJ_CFG_AGC_RF: + return CtrlSetCfgAgcRf ( demod, (pDRXJCfgAgc_t) config->cfgData ); + case DRXJ_CFG_AGC_IF: + return CtrlSetCfgAgcIf ( demod, (pDRXJCfgAgc_t) config->cfgData ); + case DRXJ_CFG_PRE_SAW: + return CtrlSetCfgPreSaw ( demod, (pDRXJCfgPreSaw_t) config->cfgData ); + case DRXJ_CFG_AFE_GAIN: + return CtrlSetCfgAfeGain ( demod, (pDRXJCfgAfeGain_t) config->cfgData ); + case DRXJ_CFG_SMART_ANT: + return CtrlSetCfgSmartAnt ( demod, (pDRXJCfgSmartAnt_t)(config->cfgData) ); + case DRXJ_CFG_RESET_PACKET_ERR: + return CtrlSetCfgResetPktErr ( demod ); +#ifndef DRXJ_DIGITAL_ONLY + case DRXJ_CFG_OOB_PRE_SAW: + return CtrlSetCfgOOBPreSAW ( demod, (pu16_t)(config->cfgData) ); + case DRXJ_CFG_OOB_LO_POW: + return CtrlSetCfgOOBLoPower ( demod, (pDRXJCfgOobLoPower_t)(config->cfgData) ); + case DRXJ_CFG_ATV_MISC: + return CtrlSetCfgAtvMisc( demod, (pDRXJCfgAtvMisc_t) config->cfgData ); + case DRXJ_CFG_ATV_EQU_COEF: + return CtrlSetCfgAtvEquCoef( demod, + (pDRXJCfgAtvEquCoef_t) config->cfgData ); + case DRXJ_CFG_ATV_OUTPUT: + return CtrlSetCfgATVOutput( demod, + (pDRXJCfgAtvOutput_t) config->cfgData ); +#endif + case DRXJ_CFG_MPEG_OUTPUT_MISC: + return CtrlSetCfgMpegOutputMisc( demod, + (pDRXJCfgMpegOutputMisc_t) config->cfgData ); +#ifndef DRXJ_EXCLUDE_AUDIO + case DRX_CFG_AUD_VOLUME: + return AUDCtrlSetCfgVolume( demod, + (pDRXCfgAudVolume_t)config->cfgData ); + case DRX_CFG_I2S_OUTPUT: + return AUDCtrlSetCfgOutputI2S( demod, + (pDRXCfgI2SOutput_t)config->cfgData ); + case DRX_CFG_AUD_AUTOSOUND: + return AUDCtrSetlCfgAutoSound( demod, + (pDRXCfgAudAutoSound_t) + config->cfgData); + case DRX_CFG_AUD_ASS_THRES: + return AUDCtrlSetCfgASSThres( demod, + (pDRXCfgAudASSThres_t) + config->cfgData); + case DRX_CFG_AUD_CARRIER: + return AUDCtrlSetCfgCarrier( demod, + (pDRXCfgAudCarriers_t)config->cfgData); + case DRX_CFG_AUD_DEVIATION: + return AUDCtrlSetCfgDev( demod, + (pDRXCfgAudDeviation_t)config->cfgData); + case DRX_CFG_AUD_PRESCALE: + return AUDCtrlSetCfgPrescale( demod, + (pDRXCfgAudPrescale_t)config->cfgData); + case DRX_CFG_AUD_MIXER: + return AUDCtrlSetCfgMixer( demod, + (pDRXCfgAudMixer_t)config->cfgData); + case DRX_CFG_AUD_AVSYNC: + return AUDCtrlSetCfgAVSync( demod, + (pDRXCfgAudAVSync_t)config->cfgData); + +#endif + default: + return (DRX_STS_INVALID_ARG); + } + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} + +/*============================================================================*/ + +/** +* \fn DRXStatus_t CtrlGetCfg() +* \brief Get 'some' configuration of the device. +* \param devmod Pointer to demodulator instance. +* \param config Pointer to configuration parameters (type and data). +* \return DRXStatus_t. +*/ + +static DRXStatus_t +CtrlGetCfg( pDRXDemodInstance_t demod, + pDRXCfg_t config ) +{ + if ( config == NULL ) + { + return (DRX_STS_INVALID_ARG); + } + + DUMMY_READ(); + + switch ( config->cfgType ) + { + case DRX_CFG_MPEG_OUTPUT: + return CtrlGetCfgMPEGOutput( demod, + (pDRXCfgMPEGOutput_t) config->cfgData ); + case DRX_CFG_PINS_SAFE_MODE: + return CtrlGetCfgPdrSafeMode( demod, (pBool_t) config->cfgData ); + case DRXJ_CFG_AGC_RF: + return CtrlGetCfgAgcRf ( demod, (pDRXJCfgAgc_t) config->cfgData ); + case DRXJ_CFG_AGC_IF: + return CtrlGetCfgAgcIf ( demod, (pDRXJCfgAgc_t) config->cfgData ); + case DRXJ_CFG_AGC_INTERNAL: + return CtrlGetCfgAgcInternal ( demod, (pu16_t) config->cfgData ); + case DRXJ_CFG_PRE_SAW: + return CtrlGetCfgPreSaw ( demod, (pDRXJCfgPreSaw_t) config->cfgData ); + case DRXJ_CFG_AFE_GAIN: + return CtrlGetCfgAfeGain ( demod, (pDRXJCfgAfeGain_t) config->cfgData ); + case DRXJ_CFG_ACCUM_CR_RS_CW_ERR: + return CtrlGetAccumCrRSCwErr ( demod, (pu32_t) config->cfgData ); + case DRXJ_CFG_FEC_MERS_SEQ_COUNT: + return CtrlGetFecMeasSeqCount ( demod, (pu16_t) config->cfgData ); + case DRXJ_CFG_VSB_MISC: + return CtrlGetCfgVSBMisc ( demod, (pDRXJCfgVSBMisc_t) config->cfgData ); + case DRXJ_CFG_SYMBOL_CLK_OFFSET: + return CtrlGetCfgSymbolClockOffset ( demod, (ps32_t) config->cfgData ); +#ifndef DRXJ_DIGITAL_ONLY + case DRXJ_CFG_OOB_MISC: + return CtrlGetCfgOOBMisc ( demod, (pDRXJCfgOOBMisc_t) config->cfgData ); + case DRXJ_CFG_OOB_PRE_SAW: + return CtrlGetCfgOOBPreSAW ( demod, (pu16_t)(config->cfgData) ); + case DRXJ_CFG_OOB_LO_POW: + return CtrlGetCfgOOBLoPower ( demod, (pDRXJCfgOobLoPower_t)(config->cfgData) ); + case DRXJ_CFG_ATV_EQU_COEF: + return CtrlGetCfgAtvEquCoef( demod, + (pDRXJCfgAtvEquCoef_t) config->cfgData ); + case DRXJ_CFG_ATV_MISC: + return CtrlGetCfgAtvMisc( demod, (pDRXJCfgAtvMisc_t) config->cfgData ); + case DRXJ_CFG_ATV_OUTPUT: + return CtrlGetCfgAtvOutput( demod, + (pDRXJCfgAtvOutput_t) config->cfgData ); + case DRXJ_CFG_ATV_AGC_STATUS: + return CtrlGetCfgAtvAgcStatus( demod, + (pDRXJCfgAtvAgcStatus_t) config->cfgData ); +#endif + case DRXJ_CFG_MPEG_OUTPUT_MISC: + return CtrlGetCfgMpegOutputMisc( demod, + (pDRXJCfgMpegOutputMisc_t) config->cfgData ); + case DRXJ_CFG_HW_CFG: + return CtrlGetCfgHwCfg( demod, + (pDRXJCfgHwCfg_t) config->cfgData ); +#ifndef DRXJ_EXCLUDE_AUDIO + case DRX_CFG_AUD_VOLUME: + return AUDCtrlGetCfgVolume ( demod, + (pDRXCfgAudVolume_t)config->cfgData ); + case DRX_CFG_I2S_OUTPUT: + return AUDCtrlGetCfgOutputI2S ( demod, + (pDRXCfgI2SOutput_t)config->cfgData ); + + case DRX_CFG_AUD_RDS: + return AUDCtrlGetCfgRDS ( demod, + (pDRXCfgAudRDS_t)config->cfgData ); + case DRX_CFG_AUD_AUTOSOUND: + return AUDCtrlGetCfgAutoSound ( demod, + (pDRXCfgAudAutoSound_t)config->cfgData); + case DRX_CFG_AUD_ASS_THRES: + return AUDCtrlGetCfgASSThres ( demod, + (pDRXCfgAudASSThres_t)config->cfgData); + case DRX_CFG_AUD_CARRIER: + return AUDCtrlGetCfgCarrier ( demod, + (pDRXCfgAudCarriers_t)config->cfgData); + case DRX_CFG_AUD_DEVIATION: + return AUDCtrlGetCfgDev ( demod, + (pDRXCfgAudDeviation_t)config->cfgData); + case DRX_CFG_AUD_PRESCALE: + return AUDCtrlGetCfgPrescale ( demod, + (pDRXCfgAudPrescale_t)config->cfgData); + case DRX_CFG_AUD_MIXER: + return AUDCtrlGetCfgMixer ( demod, + (pDRXCfgAudMixer_t)config->cfgData); + case DRX_CFG_AUD_AVSYNC: + return AUDCtrlGetCfgAVSync ( demod, + (pDRXCfgAudAVSync_t)config->cfgData); +#endif + + default: + return (DRX_STS_INVALID_ARG); + } + + return (DRX_STS_OK); +rw_error: + return (DRX_STS_ERROR); +} + +/*============================================================================= +===== EXPORTED FUNCTIONS ====================================================*/ +/** +* \fn DRXJ_Open() +* \brief Open the demod instance, configure device, configure drxdriver +* \return Status_t Return status. +* +* DRXJ_Open() can be called with a NULL ucode image => no ucode upload. +* This means that DRXJ_Open() must NOT contain SCU commands or, in general, +* rely on SCU or AUD ucode to be present. +* +*/ +DRXStatus_t +DRXJ_Open(pDRXDemodInstance_t demod) +{ + pI2CDeviceAddr_t devAddr = NULL; + pDRXJData_t extAttr = NULL; + pDRXCommonAttr_t commonAttr = NULL; + u32_t driverVersion = 0; + DRXUCodeInfo_t ucodeInfo; + DRXCfgMPEGOutput_t cfgMPEGOutput; + + /* Check arguments */ + if (demod -> myExtAttr == NULL ) + { + return ( DRX_STS_INVALID_ARG); + } + + devAddr = demod -> myI2CDevAddr; + extAttr = (pDRXJData_t) demod -> myExtAttr; + commonAttr = (pDRXCommonAttr_t) demod -> myCommonAttr; + + CHK_ERROR(PowerUpDevice(demod)); + commonAttr->currentPowerMode = DRX_POWER_UP; + + /* has to be in front of setIqmAf and setOrxNsuAox */ + CHK_ERROR(GetDeviceCapabilities(demod)); + + /* Soft reset of sys- and osc-clockdomain */ + WR16( devAddr, SIO_CC_SOFT_RST__A, ( SIO_CC_SOFT_RST_SYS__M | + SIO_CC_SOFT_RST_OSC__M ) ); + WR16( devAddr, SIO_CC_UPDATE__A, SIO_CC_UPDATE_KEY); + CHK_ERROR( DRXBSP_HST_Sleep(1) ); + + /* TODO first make sure that everything keeps working before enabling this */ + /* PowerDownAnalogBlocks() */ + WR16( devAddr, ATV_TOP_STDBY__A, (~ATV_TOP_STDBY_CVBS_STDBY_A2_ACTIVE) + |ATV_TOP_STDBY_SIF_STDBY_STANDBY ); + + CHK_ERROR( SetIqmAf( demod, FALSE ) ); + CHK_ERROR( SetOrxNsuAox( demod, FALSE ) ); + + CHK_ERROR(InitHI(demod) ); + + /* disable mpegoutput pins */ + cfgMPEGOutput.enableMPEGOutput = FALSE; + CHK_ERROR( CtrlSetCfgMPEGOutput( demod, &cfgMPEGOutput) ); + /* Stop AUD Inform SetAudio it will need to do all setting */ + CHK_ERROR( PowerDownAud(demod) ); + /* Stop SCU */ + WR16( devAddr, SCU_COMM_EXEC__A, SCU_COMM_EXEC_STOP); + + /* Upload microcode */ + if ( commonAttr->microcode != NULL ) + { + /* Dirty trick to use common ucode upload & verify, + pretend device is already open */ + commonAttr->isOpened = TRUE; + ucodeInfo.mcData = commonAttr->microcode; + ucodeInfo.mcSize = commonAttr->microcodeSize; + +#ifdef DRXJ_SPLIT_UCODE_UPLOAD + /* Upload microcode without audio part */ + CHK_ERROR( CtrlUCodeUpload( demod, &ucodeInfo, UCODE_UPLOAD, FALSE ) ); +#else + CHK_ERROR( DRX_Ctrl( demod, DRX_CTRL_LOAD_UCODE, &ucodeInfo) ); +#endif /* DRXJ_SPLIT_UCODE_UPLOAD */ + if ( commonAttr->verifyMicrocode == TRUE ) + { +#ifdef DRXJ_SPLIT_UCODE_UPLOAD + CHK_ERROR( CtrlUCodeUpload( demod, &ucodeInfo, UCODE_VERIFY, FALSE ) ); +#else + CHK_ERROR( DRX_Ctrl ( demod, DRX_CTRL_VERIFY_UCODE, &ucodeInfo) ); +#endif /* DRXJ_SPLIT_UCODE_UPLOAD */ + } + commonAttr->isOpened = FALSE; + } + + /* Run SCU for a little while to initialize microcode version numbers */ + WR16( devAddr, SCU_COMM_EXEC__A, SCU_COMM_EXEC_ACTIVE); + + /* Open tuner instance */ + if ( demod->myTuner != NULL ) + { + demod->myTuner->myCommonAttr->myUserData = (void *)demod; + + if ( commonAttr->tunerPortNr == 1 ) + { + Bool_t bridgeClosed = TRUE; + CHK_ERROR( CtrlI2CBridge( demod, &bridgeClosed ) ); + } + + CHK_ERROR( DRXBSP_TUNER_Open( demod -> myTuner ) ); + + if ( commonAttr->tunerPortNr == 1 ) + { + Bool_t bridgeClosed = FALSE; + CHK_ERROR( CtrlI2CBridge( demod, &bridgeClosed ) ); + } + commonAttr->tunerMinFreqRF = ((demod->myTuner)->myCommonAttr->minFreqRF); + commonAttr->tunerMaxFreqRF = ((demod->myTuner)->myCommonAttr->maxFreqRF); + } + + /* Initialize scan timeout */ + commonAttr -> scanDemodLockTimeout = DRXJ_SCAN_TIMEOUT; + commonAttr -> scanDesiredLock = DRX_LOCKED; + + /* Initialize default AFE configuartion for QAM */ + if (extAttr->hasLNA) + { + /* IF AGC off, PGA active */ +#ifndef DRXJ_VSB_ONLY + extAttr->qamIfAgcCfg.standard = DRX_STANDARD_ITU_B; + extAttr->qamIfAgcCfg.ctrlMode = DRX_AGC_CTRL_OFF; + extAttr->qamPgaCfg = 140+(11*13); +#endif + extAttr->vsbIfAgcCfg.standard = DRX_STANDARD_8VSB; + extAttr->vsbIfAgcCfg.ctrlMode = DRX_AGC_CTRL_OFF; + extAttr->vsbPgaCfg = 140+(11*13); + } else { + /* IF AGC on, PGA not active */ +#ifndef DRXJ_VSB_ONLY + extAttr->qamIfAgcCfg.standard = DRX_STANDARD_ITU_B; + extAttr->qamIfAgcCfg.ctrlMode = DRX_AGC_CTRL_AUTO; + extAttr->qamIfAgcCfg.minOutputLevel = 0; + extAttr->qamIfAgcCfg.maxOutputLevel = 0x7FFF; + extAttr->qamIfAgcCfg.speed = 3; + extAttr->qamIfAgcCfg.top = 1297; + extAttr->qamPgaCfg = 140; +#endif + extAttr->vsbIfAgcCfg.standard = DRX_STANDARD_8VSB; + extAttr->vsbIfAgcCfg.ctrlMode = DRX_AGC_CTRL_AUTO; + extAttr->vsbIfAgcCfg.minOutputLevel = 0; + extAttr->vsbIfAgcCfg.maxOutputLevel = 0x7FFF; + extAttr->vsbIfAgcCfg.speed = 3; + extAttr->vsbIfAgcCfg.top = 1024; + extAttr->vsbPgaCfg = 140; + } + /* TODO: remove minOutputLevel and maxOutputLevel for both QAM and VSB after */ + /* mc has not used them */ +#ifndef DRXJ_VSB_ONLY + extAttr->qamRfAgcCfg.standard = DRX_STANDARD_ITU_B; + extAttr->qamRfAgcCfg.ctrlMode = DRX_AGC_CTRL_AUTO; + extAttr->qamRfAgcCfg.minOutputLevel = 0; + extAttr->qamRfAgcCfg.maxOutputLevel = 0x7FFF; + extAttr->qamRfAgcCfg.speed = 3; + extAttr->qamRfAgcCfg.top = 9500; + extAttr->qamRfAgcCfg.cutOffCurrent = 4000; + extAttr->qamPreSawCfg.standard = DRX_STANDARD_ITU_B; + extAttr->qamPreSawCfg.reference = 0x07; + extAttr->qamPreSawCfg.usePreSaw = TRUE; +#endif + /* Initialize default AFE configuartion for VSB */ + extAttr->vsbRfAgcCfg.standard = DRX_STANDARD_8VSB; + extAttr->vsbRfAgcCfg.ctrlMode = DRX_AGC_CTRL_AUTO; + extAttr->vsbRfAgcCfg.minOutputLevel = 0; + extAttr->vsbRfAgcCfg.maxOutputLevel = 0x7FFF; + extAttr->vsbRfAgcCfg.speed = 3; + extAttr->vsbRfAgcCfg.top = 9500; + extAttr->vsbRfAgcCfg.cutOffCurrent = 4000; + extAttr->vsbPreSawCfg.standard = DRX_STANDARD_8VSB; + extAttr->vsbPreSawCfg.reference = 0x07; + extAttr->vsbPreSawCfg.usePreSaw = TRUE; + +#ifndef DRXJ_DIGITAL_ONLY + /* Initialize default AFE configuartion for ATV */ + extAttr->atvRfAgcCfg.standard = DRX_STANDARD_NTSC; + extAttr->atvRfAgcCfg.ctrlMode = DRX_AGC_CTRL_AUTO; + extAttr->atvRfAgcCfg.top = 9500; + extAttr->atvRfAgcCfg.cutOffCurrent = 4000; + extAttr->atvRfAgcCfg.speed = 3; + extAttr->atvIfAgcCfg.standard = DRX_STANDARD_NTSC; + extAttr->atvIfAgcCfg.ctrlMode = DRX_AGC_CTRL_AUTO; + extAttr->atvIfAgcCfg.speed = 3; + extAttr->atvIfAgcCfg.top = 2400; + extAttr->atvPreSawCfg.reference = 0x0007; + extAttr->atvPreSawCfg.usePreSaw = TRUE; + extAttr->atvPreSawCfg.standard = DRX_STANDARD_NTSC; +#endif + extAttr->standard=DRX_STANDARD_UNKNOWN; + + CHK_ERROR(SmartAntInit(demod)); + + /* Stamp driver version number in SCU data RAM in BCD code + Done to enable field application engineers to retreive drxdriver version + via I2C from SCU RAM + */ + driverVersion = (VERSION_MAJOR/100) % 10; + driverVersion <<= 4; + driverVersion += (VERSION_MAJOR/10) % 10; + driverVersion <<= 4; + driverVersion += (VERSION_MAJOR%10); + driverVersion <<= 4; + driverVersion += (VERSION_MINOR%10); + driverVersion <<= 4; + driverVersion += (VERSION_PATCH/1000) % 10; + driverVersion <<= 4; + driverVersion += (VERSION_PATCH/100) % 10; + driverVersion <<= 4; + driverVersion += (VERSION_PATCH/10) % 10; + driverVersion <<= 4; + driverVersion += (VERSION_PATCH%10); + WR16(devAddr, SCU_RAM_DRIVER_VER_HI__A, (u16_t)(driverVersion>>16) ); + WR16(devAddr, SCU_RAM_DRIVER_VER_LO__A, (u16_t)(driverVersion&0xFFFF) ); + + /* refresh the audio data structure with default */ + extAttr->audData = DRXJDefaultAudData_g; + + return ( DRX_STS_OK ); +rw_error: + commonAttr->isOpened = FALSE; + return (DRX_STS_ERROR); +} + +/*============================================================================*/ +/** +* \fn DRXJ_Close() +* \brief Close the demod instance, power down the device +* \return Status_t Return status. +* +*/ +DRXStatus_t +DRXJ_Close(pDRXDemodInstance_t demod) +{ + pI2CDeviceAddr_t devAddr =NULL; + pDRXJData_t extAttr =NULL; + pDRXCommonAttr_t commonAttr =NULL; + DRXPowerMode_t powerMode =DRX_POWER_UP; + + commonAttr = (pDRXCommonAttr_t) demod -> myCommonAttr; + devAddr = demod -> myI2CDevAddr; + extAttr = (pDRXJData_t) demod -> myExtAttr; + + /* power up */ + CHK_ERROR( CtrlPowerMode( demod, &powerMode )); + + if ( demod->myTuner != NULL ) + { + /* Check if bridge is used */ + if ( commonAttr->tunerPortNr == 1 ) + { + Bool_t bridgeClosed = TRUE; + CHK_ERROR( CtrlI2CBridge( demod, &bridgeClosed ) ); + } + CHK_ERROR( DRXBSP_TUNER_Close( demod -> myTuner ) ); + if ( commonAttr->tunerPortNr == 1 ) + { + Bool_t bridgeClosed = FALSE; + CHK_ERROR( CtrlI2CBridge( demod, &bridgeClosed ) ); + } + }; + + WR16( devAddr, SCU_COMM_EXEC__A, SCU_COMM_EXEC_ACTIVE); + powerMode =DRX_POWER_DOWN; + CHK_ERROR( CtrlPowerMode( demod, &powerMode )); + + return DRX_STS_OK; +rw_error: + return (DRX_STS_ERROR); +} + +/*============================================================================*/ +/** +* \fn DRXJ_Ctrl() +* \brief DRXJ specific control function +* \return Status_t Return status. +*/ +DRXStatus_t +DRXJ_Ctrl(pDRXDemodInstance_t demod, DRXCtrlIndex_t ctrl, + void *ctrlData) +{ + switch ( ctrl ) { + /*======================================================================*/ + case DRX_CTRL_SET_CHANNEL: + { + return CtrlSetChannel ( demod, + (pDRXChannel_t) ctrlData ); + } + break; + /*======================================================================*/ + case DRX_CTRL_GET_CHANNEL: + { + return CtrlGetChannel ( demod, + (pDRXChannel_t) ctrlData ); + } + break; + /*======================================================================*/ + case DRX_CTRL_SIG_QUALITY: + { + return CtrlSigQuality ( demod, + (pDRXSigQuality_t) ctrlData); + } + break; + /*======================================================================*/ + case DRX_CTRL_SIG_STRENGTH: + { + return CtrlSigStrength ( demod, + (pu16_t) ctrlData); + } + break; + /*======================================================================*/ + case DRX_CTRL_CONSTEL: + { + return CtrlConstel ( demod, + (pDRXComplex_t) ctrlData); + } + break; + /*======================================================================*/ + case DRX_CTRL_SET_CFG: + { + return CtrlSetCfg ( demod, + (pDRXCfg_t) ctrlData); + } + break; + /*======================================================================*/ + case DRX_CTRL_GET_CFG: + { + return CtrlGetCfg ( demod, (pDRXCfg_t) ctrlData); + } + break; + /*======================================================================*/ + case DRX_CTRL_I2C_BRIDGE: + { + return CtrlI2CBridge( demod, (pBool_t) ctrlData ); + } + break; + /*======================================================================*/ + case DRX_CTRL_LOCK_STATUS: + { + return CtrlLockStatus( demod, (pDRXLockStatus_t) ctrlData ); + } + break; + /*======================================================================*/ + case DRX_CTRL_SET_STANDARD: + { + return CtrlSetStandard( demod, (pDRXStandard_t) ctrlData ); + } + break; + /*======================================================================*/ + case DRX_CTRL_GET_STANDARD: + { + return CtrlGetStandard( demod, (pDRXStandard_t) ctrlData ); + } + break; + /*======================================================================*/ + case DRX_CTRL_POWER_MODE: + { + return CtrlPowerMode( demod, (pDRXPowerMode_t) ctrlData ); + } + break; + /*======================================================================*/ + case DRX_CTRL_VERSION: + { + return CtrlVersion( demod, (pDRXVersionList_t *) ctrlData ); + } + break; + /*======================================================================*/ + case DRX_CTRL_PROBE_DEVICE: + { + return CtrlProbeDevice( demod ); + } + break; + /*======================================================================*/ + case DRX_CTRL_SET_OOB: + { + return CtrlSetOOB( demod, (pDRXOOB_t) ctrlData ); + } + break; + /*======================================================================*/ + case DRX_CTRL_GET_OOB: + { + return CtrlGetOOB( demod, (pDRXOOBStatus_t) ctrlData ); + } + break; + /*======================================================================*/ + case DRX_CTRL_SET_UIO_CFG: + { + return CtrlSetUIOCfg( demod, (pDRXUIOCfg_t) ctrlData ); + } + break; + /*======================================================================*/ + case DRX_CTRL_GET_UIO_CFG: + { + return CtrlGetUIOCfg( demod, (pDRXUIOCfg_t) ctrlData ); + } + break; + /*======================================================================*/ + case DRX_CTRL_UIO_READ: + { + return CtrlUIORead( demod, (pDRXUIOData_t) ctrlData ); + } + break; + /*======================================================================*/ + case DRX_CTRL_UIO_WRITE: + { + return CtrlUIOWrite( demod, (pDRXUIOData_t) ctrlData ); + } + break; + /*======================================================================*/ + case DRX_CTRL_AUD_SET_STANDARD: + { + return AUDCtrlSetStandard( demod, (pDRXAudStandard_t) ctrlData ); + } + break; + /*======================================================================*/ + case DRX_CTRL_AUD_GET_STANDARD: + { + return AUDCtrlGetStandard( demod, (pDRXAudStandard_t) ctrlData ); + } + break; + /*======================================================================*/ + case DRX_CTRL_AUD_GET_STATUS: + { + return AUDCtrlGetStatus( demod, (pDRXAudStatus_t) ctrlData ); + } + break; + /*======================================================================*/ + case DRX_CTRL_AUD_BEEP: + { + return AUDCtrlBeep( demod, (pDRXAudBeep_t) ctrlData ); + } + break; + + /*======================================================================*/ + case DRX_CTRL_I2C_READWRITE: + { + return CtrlI2CWriteRead( demod, (pDRXI2CData_t) ctrlData ); + } + break; +#ifdef DRXJ_SPLIT_UCODE_UPLOAD + case DRX_CTRL_LOAD_UCODE: + { + return CtrlUCodeUpload( demod, (pDRXUCodeInfo_t) ctrlData, UCODE_UPLOAD, FALSE ); + } + break; + case DRX_CTRL_VERIFY_UCODE: + { + return CtrlUCodeUpload( demod, (pDRXUCodeInfo_t) ctrlData, UCODE_VERIFY, FALSE ); + } + break; +#endif /* DRXJ_SPLIT_UCODE_UPLOAD */ + case DRX_CTRL_VALIDATE_UCODE: + { + return CtrlValidateUCode (demod); + } + break; + default: + return (DRX_STS_FUNC_NOT_AVAILABLE); + } + return (DRX_STS_OK); +} +/* END OF FILE */ |