////////////////////////////////////////////////////////////////////////////// // // (C) Philips Semiconductors-CSU 1999 // All rights are reserved. Reproduction in whole or in part is prohibited // without the written consent of the copyright owner. // // Philips reserves the right to make changes without notice at any time. // Philips makes no warranty, expressed, implied or statutory, including but // not limited to any implied warranty of merchantibility or fitness for any // particular purpose, or that the use will not infringe any third party // patent, copyright or trademark. Philips must not be liable for any loss // or damage arising from its use. // // VSBBASE.CPP ////////////////////////////////////////////////////////////////////////////// #include "philtune.h" #include "vsbbase.h" /* * CVSBDemod() * Input : * Output: TRUE - if initialization data can be written to I2C * FALSE - if there is an I2C error * Description: CVSBDemod Constructor. */ CVSBDemod::CVSBDemod(CI2CScript *p_I2CScript, BoardInfoType *p_BoardInfo, NTSTATUS *p_Status) :m_RegisterLock(1) { m_pI2CScript = p_I2CScript; m_ucVsbDemodAddress = VSB_I2C_ADDRESS; } /* * SetRegisterList() * Input: * Output: * Description: */ UINT CVSBDemod::SetRegisterList(RegisterType *p_Registers, UINT uiNumRegisters) { return SetControlRegister(p_Registers, uiNumRegisters); } /* * GetRegisterList() * Input: * Output: * Description: */ UINT CVSBDemod::GetRegisterList(RegisterType *p_Registers, UINT uiNumRegisters, UINT uiRegisterType) { if(uiRegisterType == CONTROL_REGISTER) { return GetControlRegister(p_Registers, uiNumRegisters); } else if(uiRegisterType == STATUS_REGISTER) { return GetStatusRegister(p_Registers, uiNumRegisters); } else{} return WDMMINI_INVALIDPARAM; } /* * SetCoeff() * Input:VsbCoeffType *p_Coeff - pointer to the coefficients register * structure * UINT uiNumCoeff - Number of coefficients * Output : UINT - Error code * Description: Lock register access and Set the coefficients into the chip */ UINT CVSBDemod::SetCoeff(VsbCoeffType *p_Coeff, UINT uiNumRegisters) { UINT uiResult; UINT i; // Lock the Register control handle m_RegisterLock.Lock(); VsbCoeffType *pp_TempCoeff[MAX_VSB_COEFF]; UCHAR ucEnable = 0; if (p_Coeff != NULL) { for (i = 0; i < uiNumRegisters; i++) { pp_TempCoeff[i] = &p_Coeff[i]; ucEnable |= p_Coeff[i].uiID; } if(!EnableCoefficients(ucEnable)) { uiResult = WDMMINI_HARDWAREFAILURE; goto errexit; } uiResult = WriteCoeff(pp_TempCoeff, uiNumRegisters); if(!DisableCoefficients()) { uiResult = WDMMINI_HARDWAREFAILURE; goto errexit; } } else { _DbgPrintF( DEBUGLVL_ERROR,("CVSBDemod::WriteCoeff() No Coeff !!! \n")); uiResult = WDMMINI_INVALIDPARAM; } errexit: m_RegisterLock.Unlock(); return uiResult; } /* * GetCoeff() * Input:VsbCoeffType *p_Coeff - pointer to the coefficients register * structure * UINT uiNumCoeff - Number of coefficients * Output : UINT - Error code * Description: Lock register access and Get the coefficients from the chip */ UINT CVSBDemod::GetCoeff(VsbCoeffType *p_Coeff, UINT uiNumRegisters) { UINT uiResult; UINT i; UCHAR ucEnable = 0; // Lock the Register control handle m_RegisterLock.Lock(); VsbCoeffType *pp_TempCoeff[MAX_VSB_COEFF]; if (p_Coeff != NULL) { for (i = 0; i < uiNumRegisters; i++) { pp_TempCoeff[i] = &p_Coeff[i]; ucEnable |= p_Coeff[i].uiID; } if(!EnableCoefficients(ucEnable)) { uiResult = WDMMINI_HARDWAREFAILURE; goto errexit; } uiResult = ReadCoeff(pp_TempCoeff, uiNumRegisters); if(!DisableCoefficients()) { uiResult = WDMMINI_HARDWAREFAILURE; goto errexit; } } else { _DbgPrintF( DEBUGLVL_ERROR,("CVSBDemod::ReadAndCreateRegisters() No Coeff !!! \n")); uiResult = WDMMINI_INVALIDPARAM; } errexit: m_RegisterLock.Unlock(); return uiResult; } /* * SetControlRegister() * Input: * Output: * Description: */ UINT CVSBDemod::SetControlRegister(RegisterType *p_Registers, UINT uiNumRegisters) { int i; UINT uiResult; UINT uiPrevAddress = 0; m_RegisterLock.Lock(); uiResult = WriteControlReg(p_Registers, uiNumRegisters, TRUE); m_RegisterLock.Unlock(); return uiResult; } /* * GetControlRegister() * Input: * Output: * Description: */ UINT CVSBDemod::GetControlRegister(RegisterType *p_Registers, UINT uiNumRegisters) { UINT i, a, b; RegisterType Temp; UINT uiResult = WDMMINI_NOERROR; // This read operation is a shadow operation. The values in the control // regsiter (in memory) is passed back // Lock the Register control handle m_RegisterLock.Lock(); // Write data into control registers (memory) for (i = 0; i < uiNumRegisters; i++) { // Check to see that the address is within the specified // range for the chip UINT uiAddr = p_Registers[i].uiAddress; if ( uiAddr <= m_uiMaxControlRegisterAddress) { // Copy the register values from the control register // in memory MemoryCopy(p_Registers[i].p_ucBuffer, &m_ucControlReg[uiAddr], p_Registers[i].uiLength); } else { uiResult = WDMMINI_INVALIDPARAM; break; } } m_RegisterLock.Unlock(); return uiResult; } /* * GetStatusRegister() * Input: * Output: * Description: */ UINT CVSBDemod::GetStatusRegister(RegisterType *p_Registers, UINT uiNumRegisters) { UINT uiResult; // Lock the Register control handle m_RegisterLock.Lock(); uiResult = ReadStatusReg(p_Registers, uiNumRegisters); m_RegisterLock.Unlock(); return uiResult; } /* * WriteControlReg() * Input:RegisterType *p_reg_list- Register list to be written to control registers int i_num_reg - Number of registers in the list * Output : UINT - Error code * Description: Update the control registers and write to chip */ UINT CVSBDemod::WriteControlReg(RegisterType *p_Registers, UINT uiNumRegisters, BOOL bWrite) { UINT uiResult = WDMMINI_NOERROR; UINT i; UINT uiPrevAddress; UINT uiLastAddress; UINT uiAddress; uiPrevAddress = p_Registers[0].uiAddress; // Write data into control registers (memory) for (i = 0; i < uiNumRegisters; i++) { // Check to see that the address is within the specified // range for the chip uiAddress = p_Registers[i].uiAddress; uiLastAddress = uiAddress + p_Registers[i].uiLength - 1; if ( (uiLastAddress)<= m_uiMaxControlRegisterAddress) { // Copy the register values into the control register //memory MemoryCopy(&m_ucControlReg[uiAddress], p_Registers[i].p_ucBuffer, p_Registers[i].uiLength); } else { uiResult = WDMMINI_INVALIDPARAM; return uiResult ; } // Find the highest address if(uiPrevAddress < uiLastAddress) uiPrevAddress = uiLastAddress; if (bWrite) { if((uiResult = Write(m_ucControlReg, (uiPrevAddress + 1), 0)) != WDMMINI_NOERROR) { _DbgPrintF( DEBUGLVL_ERROR,("CVSBDemod::WriteControlReg() Error in Write !!! \n")); return uiResult; } } } _DbgPrintF( DEBUGLVL_VERBOSE,("CVSBDemod::WriteControlReg() Write !!! ------------ \n")); return uiResult; } /* * ReadStatusReg() * Input:RegisterType *p_reg_list- Register list to be written to control registers int i_num_reg - Number of registers in the list * Output : UINT - Error code * Description: Update the control registers and write to chip */ UINT CVSBDemod::ReadStatusReg(RegisterType *p_Registers, UINT uiNumRegisters) { UINT uiResult = WDMMINI_NOERROR; UINT i; UINT uiPrevAddress; UINT uiLastAddress; UINT uiAddress; uiPrevAddress = p_Registers[0].uiAddress; // Write data into control registers (memory) for (i = 0; i < uiNumRegisters; i++) { // Check to see that the address is within the specified // range for the chip uiAddress = p_Registers[i].uiAddress; uiLastAddress = uiAddress + p_Registers[i].uiLength - 1; if (uiLastAddress <= m_uiMaxStatusRegisterAddress) { // Find the highest address if(uiPrevAddress < uiLastAddress) uiPrevAddress = uiLastAddress; } else { _DbgPrintF( DEBUGLVL_ERROR,("CVSBDemod::ReadStatusReg() Error: Too many values !!! \n")); return(WDMMINI_INVALIDPARAM); } } // Read I2C data if((uiResult = Read(m_ucI2CBuffer, uiPrevAddress + 1, 0)) != WDMMINI_NOERROR) { _DbgPrintF( DEBUGLVL_ERROR,("CVSBDemod::ReadStatusReg() Error in Read !!! \n")); return uiResult; } // Read data from status registers (memory) for (i = 0; i < uiNumRegisters; i++) { // Copy the register values into the control register //memory MemoryCopy(p_Registers[i].p_ucBuffer, &m_ucI2CBuffer[p_Registers[i].uiAddress], p_Registers[i].uiLength); } _DbgPrintF( DEBUGLVL_VERBOSE,("CVSBDemod::ReadStatusReg() Read !!! ------------ \n")); return uiResult; } /* * WriteCoeff() * Input:VsbCoeffType **pp_Coeff -pointer to an array of pointers pointing to * coefficients register structure * UINT uiNumCoeff - Number of coefficient pointers * Output : UINT - Error code * Description: Write the coefficients into the chip */ UINT CVSBDemod::WriteCoeff(VsbCoeffType **pp_Coeff, UINT uiNumCoeff) { UINT uiResult = WDMMINI_NOERROR; UINT uiStart = 0; UINT uiCurrentPos = 0; UINT uiNumValues = 0; UINT uiIndex = 0; UINT i, j; VsbCoeffType *p_TempCoeff; uiCurrentPos = 0; p_TempCoeff = pp_Coeff[0]; // Find the least address coefficient. // Fill up the output buffer with control register values upto // this least coefficient. // Write the coefficient values. // Find the next least address coefficient. // Write the control register values between the previous coefficient end // and this coefficient beginning. for (i = 0; i < uiNumCoeff; i++) { p_TempCoeff = pp_Coeff[i]; uiIndex = i; for(j = i; j < uiNumCoeff; j++) { if(pp_Coeff[j]->uiAddress < p_TempCoeff->uiAddress) { p_TempCoeff = pp_Coeff[j]; uiIndex = j; } } pp_Coeff[uiIndex] = pp_Coeff[i]; pp_Coeff[i] = p_TempCoeff; // Number of control registers to be copied into the I2C buffer before // the coefficient array uiNumValues = p_TempCoeff->uiAddress - uiStart; // Copy the partial control registers MemoryCopy(&m_ucI2CBuffer[uiCurrentPos], &m_ucControlReg[uiStart], uiNumValues) ; // position the pointer to the next position in the i2C buffer uiCurrentPos += uiNumValues; // Position the pointer to the next control register uiStart += uiNumValues + 1; // Write 0 to coefficient write trigger point. It is not necessary to write 0, // but as the document does not say what value should be written, its better to // write 0. In VSB1, writing to the coefficient trigger point freezes the Equalizer // thats the reason for keeping the write to trigger point a separate operation m_ucI2CBuffer[uiCurrentPos] = 0; // position the pointer to the next position in the i2C buffer uiCurrentPos += 1; // Copy the coefficient values into the I2C control buffer MemoryCopy(&m_ucI2CBuffer[uiCurrentPos], p_TempCoeff->p_ucBuffer, p_TempCoeff->uiLength); // Update i2C buffer position pointer uiCurrentPos += p_TempCoeff->uiLength; } // Copy control register values to I2C buffer and write //to chip if((uiResult = Write(m_ucI2CBuffer, uiCurrentPos, 0)) != WDMMINI_NOERROR) { _DbgPrintF( DEBUGLVL_ERROR,("CVSBDemod::WriteCoeff() Error in Write !!! \n")); } else { _DbgPrintF( DEBUGLVL_VERBOSE,("CVSBDemod::WriteCoeff() Write !!! \n")); } return uiResult; } /* * ReadCoeff() * Input:VsbCoeffType **pp_Coeff - pointer to an array of pointers pointing to * coefficients register structure * UINT uiNumCoeff - Number of coefficient pointers * Output : UINT - Error code * Description:Read the coefficients from the chip */ UINT CVSBDemod::ReadCoeff(VsbCoeffType **pp_Coeff, UINT uiNumCoeff) { UINT uiResult = WDMMINI_NOERROR; UINT uiStart = 0; UINT uiCurrentPos = 0; UINT uiNumValues = 0; UINT i, j; UINT uiLength = 0; UINT uiIndex = 0; VsbCoeffType *p_TempCoeff; p_TempCoeff = pp_Coeff[0]; UINT uiTempAdd = p_TempCoeff->uiAddress; for (i = 0; i < uiNumCoeff; i++) { if(uiTempAdd < pp_Coeff[i]->uiAddress) { uiTempAdd = pp_Coeff[i]->uiAddress; } uiLength += pp_Coeff[i]->uiLength; } uiLength += uiTempAdd + 1; // Read I2C data if((uiResult = Read(m_ucI2CBuffer, uiLength, 0)) != WDMMINI_NOERROR) { _DbgPrintF( DEBUGLVL_ERROR,("CVSBDemod::ReadAndCreateRegisters() Error in Read !!! \n")); return uiResult; } else _DbgPrintF( DEBUGLVL_VERBOSE,("CVSBDemod::ReadAndCreateRegisters() Read !!! \n")); // Sort Array for (i = 0; i < uiNumCoeff; i++) { p_TempCoeff = pp_Coeff[i]; uiIndex = i; for(j = i; j < uiNumCoeff; j++) { if(pp_Coeff[j]->uiAddress < p_TempCoeff->uiAddress) { p_TempCoeff = pp_Coeff[j]; uiIndex = j; } } pp_Coeff[uiIndex] = pp_Coeff[i]; pp_Coeff[i] = p_TempCoeff; // Number of values to be ignored includes the coefficient-read trigger point uiNumValues = p_TempCoeff->uiAddress - uiStart + 1; // Update i2C buffer pointer position uiCurrentPos += uiNumValues; // Update status register pointer position uiStart += uiNumValues; // Copy the coefficient values MemoryCopy(p_TempCoeff->p_ucBuffer, &m_ucI2CBuffer[uiCurrentPos], p_TempCoeff->uiLength); uiCurrentPos += p_TempCoeff->uiLength; } return uiResult; } /* * Write() * Input:UCHAR *p_ucBuffer - buffer to be written * int uiNumReg - Number of registers to be written * UINT uiStartAddr - start address * Output : UINT - Error code * Description: Write data to chip */ UINT CVSBDemod::Write(UCHAR *p_ucBuffer, UINT uiNumReg, UINT uiStartAddr) { UINT uiResult = WDMMINI_NOERROR; // The present versions of the chip do not support sub-addressing, hence // uiStartAddr is not used. // write to chip //$REVIEW - Should change function decl to make uiNumReg be USHORT - TCP if(!m_pI2CScript->WriteSeq(m_ucVsbDemodAddress, p_ucBuffer, (USHORT) uiNumReg)) uiResult = WDMMINI_HARDWAREFAILURE; return uiResult; } /* * Read() * Input:UCHAR *p_ucBuffer - buffer to be filled * int uiNumReg - Number of registers to be read * UINT uiStartAddr - start address * Output : UINT - Error code * Description: Read data from chip */ UINT CVSBDemod::Read(UCHAR *p_ucBuffer, UINT uiNumReg, UINT uiStartAddr) { UINT uiResult = WDMMINI_NOERROR; // The present versions of the chip do not support sub-addressing, hence // uiStartAddr is not used. // write to chip //$REVIEW - Should change function decl to make uiNumReg be USHORT - TCP if(!m_pI2CScript->ReadSeq(m_ucVsbDemodAddress, p_ucBuffer, (USHORT) uiNumReg)) uiResult = WDMMINI_HARDWAREFAILURE; return uiResult; } /* * IsVSBLocked() * Input : * Output: TRUE - if chip is locked * FALSE - if chip is not locked * Description: Check if chip is locked ( equalizer lock ) */ BOOL CVSBDemod::IsVSBLocked() { BOOL bLocked = FALSE; UCHAR ucByte = 0; RegisterType Status; Status.uiLength = 1; Status.uiAddress = VSB_REG_STATE; Status.p_ucBuffer = &ucByte; if(GetStatusRegister(&Status, 1) !=WDMMINI_NOERROR) return FALSE; bLocked = ((ucByte & 0x7) == 0x7) ? 1 : 0; if (bLocked) { _DbgPrintF( DEBUGLVL_TERSE,("CVSBDemod: 8VSB LOCKED !!! ------------ \n")); } else { _DbgPrintF( DEBUGLVL_TERSE,("CVSBDemod: 8VSB not locked %x!!!\n", ucByte)); } return(bLocked); } /* * SoftwareReset() * Input: Reset control * Output : * Description: Reset chip */ BOOL CVSBDemod::SoftwareReset(ULONG ulResetCtrl) { RegisterType Control; UCHAR ucMask; UCHAR ucReset = m_ucControlReg[VSB_REG_RESET]; if(ulResetCtrl & VSB_GENERAL_RESET) ucMask = VSB_GENERAL_RESET; else if(ulResetCtrl & VSB_INITIAL_RESET) ucMask = VSB_INITIAL_RESET; else return FALSE; ucReset |= ucMask; Control.uiAddress = VSB_REG_RESET; Control.uiLength = 1; Control.p_ucBuffer = &ucReset; // Reset chip SetControlRegister(&Control, 1); ucReset &= ~ucMask; //50ms delay Delay(500000); // Remove reset SetControlRegister(&Control, 1); //50ms delay Delay(500000); // Initialize VSB if INITIAL RESET is done if(ulResetCtrl & VSB_INITIAL_RESET) if(!InitVSB()) return FALSE; return TRUE; }