| /* |
| Copyright (c), 2004-2005,2007-2010 Trident Microsystems, Inc. |
| All rights reserved. |
| |
| Redistribution and use in source and binary forms, with or without |
| modification, are permitted provided that the following conditions are met: |
| |
| * Redistributions of source code must retain the above copyright notice, |
| this list of conditions and the following disclaimer. |
| * Redistributions in binary form must reproduce the above copyright notice, |
| this list of conditions and the following disclaimer in the documentation |
| and/or other materials provided with the distribution. |
| * Neither the name of Trident Microsystems nor Hauppauge Computer Works |
| nor the names of its contributors may be used to endorse or promote |
| products derived from this software without specific prior written |
| permission. |
| |
| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
| LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| /** |
| * \file $Id: drx_driver.c,v 1.40 2010/01/12 01:24:56 lfeng Exp $ |
| * |
| * \brief Generic DRX functionality, DRX driver core. |
| * |
| */ |
| |
| /*------------------------------------------------------------------------------ |
| INCLUDE FILES |
| ------------------------------------------------------------------------------*/ |
| #include "drx_driver.h" |
| #include "bsp_host.h" |
| |
| #define VERSION_FIXED 0 |
| #if VERSION_FIXED |
| #define VERSION_MAJOR 0 |
| #define VERSION_MINOR 0 |
| #define VERSION_PATCH 0 |
| #else |
| #include "drx_driver_version.h" |
| #endif |
| |
| /*------------------------------------------------------------------------------ |
| DEFINES |
| ------------------------------------------------------------------------------*/ |
| |
| /*============================================================================*/ |
| /*=== MICROCODE RELATED DEFINES ==============================================*/ |
| /*============================================================================*/ |
| |
| /** \brief Magic word for checking correct Endianess of microcode data. */ |
| #ifndef DRX_UCODE_MAGIC_WORD |
| #define DRX_UCODE_MAGIC_WORD ((((u16_t)'H')<<8)+((u16_t)'L')) |
| #endif |
| |
| /** \brief CRC flag in ucode header, flags field. */ |
| #ifndef DRX_UCODE_CRC_FLAG |
| #define DRX_UCODE_CRC_FLAG (0x0001) |
| #endif |
| |
| /** \brief Compression flag in ucode header, flags field. */ |
| #ifndef DRX_UCODE_COMPRESSION_FLAG |
| #define DRX_UCODE_COMPRESSION_FLAG (0x0002) |
| #endif |
| |
| /** \brief Maximum size of buffer used to verify the microcode. |
| Must be an even number. */ |
| #ifndef DRX_UCODE_MAX_BUF_SIZE |
| #define DRX_UCODE_MAX_BUF_SIZE (DRXDAP_MAX_RCHUNKSIZE) |
| #endif |
| #if DRX_UCODE_MAX_BUF_SIZE & 1 |
| #error DRX_UCODE_MAX_BUF_SIZE must be an even number |
| #endif |
| |
| /*============================================================================*/ |
| /*=== CHANNEL SCAN RELATED DEFINES ===========================================*/ |
| /*============================================================================*/ |
| |
| /** |
| * \brief Maximum progress indication. |
| * |
| * Progress indication will run from 0 upto DRX_SCAN_MAX_PROGRESS during scan. |
| * |
| */ |
| #ifndef DRX_SCAN_MAX_PROGRESS |
| #define DRX_SCAN_MAX_PROGRESS 1000 |
| #endif |
| |
| /*============================================================================*/ |
| /*=== MACROS =================================================================*/ |
| /*============================================================================*/ |
| |
| #define DRX_ISPOWERDOWNMODE( mode ) ( ( mode == DRX_POWER_MODE_9 ) || \ |
| ( mode == DRX_POWER_MODE_10 ) || \ |
| ( mode == DRX_POWER_MODE_11 ) || \ |
| ( mode == DRX_POWER_MODE_12 ) || \ |
| ( mode == DRX_POWER_MODE_13 ) || \ |
| ( mode == DRX_POWER_MODE_14 ) || \ |
| ( mode == DRX_POWER_MODE_15 ) || \ |
| ( mode == DRX_POWER_MODE_16 ) || \ |
| ( mode == DRX_POWER_DOWN ) ) |
| |
| /*------------------------------------------------------------------------------ |
| GLOBAL VARIABLES |
| ------------------------------------------------------------------------------*/ |
| |
| /*------------------------------------------------------------------------------ |
| STRUCTURES |
| ------------------------------------------------------------------------------*/ |
| /** \brief Structure of the microcode block headers */ |
| typedef struct { |
| u32_t addr; |
| /**< Destination address of the data in this block */ |
| u16_t size; |
| /**< Size of the block data following this header counted in |
| 16 bits words */ |
| u16_t flags; |
| /**< Flags for this data block: |
| - bit[0]= CRC on/off |
| - bit[1]= compression on/off |
| - bit[15..2]=reserved */ |
| u16_t CRC;/**< CRC value of the data block, only valid if CRC flag is |
| set. */ |
| } DRXUCodeBlockHdr_t, *pDRXUCodeBlockHdr_t; |
| |
| /*------------------------------------------------------------------------------ |
| FUNCTIONS |
| ------------------------------------------------------------------------------*/ |
| |
| /*============================================================================*/ |
| /*============================================================================*/ |
| /*== Channel Scan Functions ==================================================*/ |
| /*============================================================================*/ |
| /*============================================================================*/ |
| |
| #ifndef DRX_EXCLUDE_SCAN |
| |
| /* Prototype of default scanning function */ |
| static DRXStatus_t |
| ScanFunctionDefault(void *scanContext, |
| DRXScanCommand_t scanCommand, |
| pDRXChannel_t scanChannel, pBool_t getNextChannel); |
| |
| /** |
| * \brief Get pointer to scanning function. |
| * \param demod: Pointer to demodulator instance. |
| * \return DRXScanFunc_t. |
| */ |
| static DRXScanFunc_t GetScanFunction(pDRXDemodInstance_t demod) |
| { |
| pDRXCommonAttr_t commonAttr = (pDRXCommonAttr_t) (NULL); |
| DRXScanFunc_t scanFunc = (DRXScanFunc_t) (NULL); |
| |
| /* get scan function from common attributes */ |
| commonAttr = (pDRXCommonAttr_t) demod->myCommonAttr; |
| scanFunc = commonAttr->scanFunction; |
| |
| if (scanFunc != NULL) { |
| /* return device-specific scan function if it's not NULL */ |
| return scanFunc; |
| } |
| /* otherwise return default scan function in core driver */ |
| return &ScanFunctionDefault; |
| } |
| |
| /** |
| * \brief Get Context pointer. |
| * \param demod: Pointer to demodulator instance. |
| * \param scanContext: Context Pointer. |
| * \return DRXScanFunc_t. |
| */ |
| void *GetScanContext(pDRXDemodInstance_t demod, void *scanContext) |
| { |
| pDRXCommonAttr_t commonAttr = (pDRXCommonAttr_t) (NULL); |
| |
| /* get scan function from common attributes */ |
| commonAttr = (pDRXCommonAttr_t) demod->myCommonAttr; |
| scanContext = commonAttr->scanContext; |
| |
| if (scanContext == NULL) { |
| scanContext = (void *)demod; |
| } |
| |
| return scanContext; |
| } |
| |
| /** |
| * \brief Wait for lock while scanning. |
| * \param demod: Pointer to demodulator instance. |
| * \param lockStat: Pointer to bool indicating if end result is lock or not. |
| * \return DRXStatus_t. |
| * \retval DRX_STS_OK: Success |
| * \retval DRX_STS_ERROR: I2C failure or bsp function failure. |
| * |
| * Wait until timeout, desired lock or NEVER_LOCK. |
| * Assume: |
| * - lock function returns : at least DRX_NOT_LOCKED and a lock state |
| * higher than DRX_NOT_LOCKED. |
| * - BSP has a clock function to retrieve a millisecond ticker value. |
| * - BSP has a sleep function to enable sleep of n millisecond. |
| * |
| * In case DRX_NEVER_LOCK is returned the poll-wait will be aborted. |
| * |
| */ |
| static DRXStatus_t ScanWaitForLock(pDRXDemodInstance_t demod, pBool_t isLocked) |
| { |
| Bool_t doneWaiting = FALSE; |
| DRXLockStatus_t lockState = DRX_NOT_LOCKED; |
| DRXLockStatus_t desiredLockState = DRX_NOT_LOCKED; |
| u32_t timeoutValue = 0; |
| u32_t startTimeLockStage = 0; |
| u32_t currentTime = 0; |
| u32_t timerValue = 0; |
| |
| *isLocked = FALSE; |
| timeoutValue = (u32_t) demod->myCommonAttr->scanDemodLockTimeout; |
| desiredLockState = demod->myCommonAttr->scanDesiredLock; |
| startTimeLockStage = DRXBSP_HST_Clock(); |
| |
| /* Start polling loop, checking for lock & timeout */ |
| while (doneWaiting == FALSE) { |
| |
| if (DRX_Ctrl(demod, DRX_CTRL_LOCK_STATUS, &lockState) != |
| DRX_STS_OK) { |
| return DRX_STS_ERROR; |
| } |
| currentTime = DRXBSP_HST_Clock(); |
| |
| timerValue = currentTime - startTimeLockStage; |
| if (lockState >= desiredLockState) { |
| *isLocked = TRUE; |
| doneWaiting = TRUE; |
| } /* if ( lockState >= desiredLockState ) .. */ |
| else if (lockState == DRX_NEVER_LOCK) { |
| doneWaiting = TRUE; |
| } /* if ( lockState == DRX_NEVER_LOCK ) .. */ |
| else if (timerValue > timeoutValue) { |
| /* lockState == DRX_NOT_LOCKED and timeout */ |
| doneWaiting = TRUE; |
| } else { |
| if (DRXBSP_HST_Sleep(10) != DRX_STS_OK) { |
| return DRX_STS_ERROR; |
| } |
| } /* if ( timerValue > timeoutValue ) .. */ |
| |
| } /* while */ |
| |
| return DRX_STS_OK; |
| } |
| |
| /*============================================================================*/ |
| |
| /** |
| * \brief Determine next frequency to scan. |
| * \param demod: Pointer to demodulator instance. |
| * \param skip : Minimum frequency step to take. |
| * \return DRXStatus_t. |
| * \retval DRX_STS_OK: Succes. |
| * \retval DRX_STS_INVALID_ARG: Invalid frequency plan. |
| * |
| * Helper function for CtrlScanNext() function. |
| * Compute next frequency & index in frequency plan. |
| * Check if scan is ready. |
| * |
| */ |
| static DRXStatus_t |
| ScanPrepareNextScan(pDRXDemodInstance_t demod, DRXFrequency_t skip) |
| { |
| pDRXCommonAttr_t commonAttr = (pDRXCommonAttr_t) (NULL); |
| u16_t tableIndex = 0; |
| u16_t frequencyPlanSize = 0; |
| pDRXFrequencyPlan_t frequencyPlan = (pDRXFrequencyPlan_t) (NULL); |
| DRXFrequency_t nextFrequency = 0; |
| DRXFrequency_t tunerMinFrequency = 0; |
| DRXFrequency_t tunerMaxFrequency = 0; |
| |
| commonAttr = (pDRXCommonAttr_t) demod->myCommonAttr; |
| tableIndex = commonAttr->scanFreqPlanIndex; |
| frequencyPlan = commonAttr->scanParam->frequencyPlan; |
| nextFrequency = commonAttr->scanNextFrequency; |
| tunerMinFrequency = commonAttr->tunerMinFreqRF; |
| tunerMaxFrequency = commonAttr->tunerMaxFreqRF; |
| |
| do { |
| /* Search next frequency to scan */ |
| |
| /* always take at least one step */ |
| (commonAttr->scanChannelsScanned)++; |
| nextFrequency += frequencyPlan[tableIndex].step; |
| skip -= frequencyPlan[tableIndex].step; |
| |
| /* and then as many steps necessary to exceed 'skip' |
| without exceeding end of the band */ |
| while ((skip > 0) && |
| (nextFrequency <= frequencyPlan[tableIndex].last)) { |
| (commonAttr->scanChannelsScanned)++; |
| nextFrequency += frequencyPlan[tableIndex].step; |
| skip -= frequencyPlan[tableIndex].step; |
| } |
| /* reset skip, in case we move to the next band later */ |
| skip = 0; |
| |
| if (nextFrequency > frequencyPlan[tableIndex].last) { |
| /* reached end of this band */ |
| tableIndex++; |
| frequencyPlanSize = |
| commonAttr->scanParam->frequencyPlanSize; |
| if (tableIndex >= frequencyPlanSize) { |
| /* reached end of frequency plan */ |
| commonAttr->scanReady = TRUE; |
| } else { |
| nextFrequency = frequencyPlan[tableIndex].first; |
| } |
| } |
| if (nextFrequency > (tunerMaxFrequency)) { |
| /* reached end of tuner range */ |
| commonAttr->scanReady = TRUE; |
| } |
| } while ((nextFrequency < tunerMinFrequency) && |
| (commonAttr->scanReady == FALSE)); |
| |
| /* Store new values */ |
| commonAttr->scanFreqPlanIndex = tableIndex; |
| commonAttr->scanNextFrequency = nextFrequency; |
| |
| return DRX_STS_OK; |
| } |
| |
| /*============================================================================*/ |
| |
| /** |
| * \brief Default DTV scanning function. |
| * |
| * \param demod: Pointer to demodulator instance. |
| * \param scanCommand: Scanning command: INIT, NEXT or STOP. |
| * \param scanChannel: Channel to check: frequency and bandwidth, others AUTO |
| * \param getNextChannel: Return TRUE if next frequency is desired at next call |
| * |
| * \return DRXStatus_t. |
| * \retval DRX_STS_OK: Channel found, DRX_CTRL_GET_CHANNEL can be used |
| * to retrieve channel parameters. |
| * \retval DRX_STS_BUSY: Channel not found (yet). |
| * \retval DRX_STS_ERROR: Something went wrong. |
| * |
| * scanChannel and getNextChannel will be NULL for INIT and STOP. |
| */ |
| static DRXStatus_t |
| ScanFunctionDefault(void *scanContext, |
| DRXScanCommand_t scanCommand, |
| pDRXChannel_t scanChannel, pBool_t getNextChannel) |
| { |
| pDRXDemodInstance_t demod = NULL; |
| DRXStatus_t status = DRX_STS_ERROR; |
| Bool_t isLocked = FALSE; |
| |
| demod = (pDRXDemodInstance_t) scanContext; |
| |
| if (scanCommand != DRX_SCAN_COMMAND_NEXT) { |
| /* just return OK if not doing "scan next" */ |
| return DRX_STS_OK; |
| } |
| |
| *getNextChannel = FALSE; |
| |
| status = DRX_Ctrl(demod, DRX_CTRL_SET_CHANNEL, scanChannel); |
| if (status != DRX_STS_OK) { |
| return (status); |
| } |
| |
| status = ScanWaitForLock(demod, &isLocked); |
| if (status != DRX_STS_OK) { |
| return status; |
| } |
| |
| /* done with this channel, move to next one */ |
| *getNextChannel = TRUE; |
| |
| if (isLocked == FALSE) { |
| /* no channel found */ |
| return DRX_STS_BUSY; |
| } |
| /* channel found */ |
| return DRX_STS_OK; |
| } |
| |
| /*============================================================================*/ |
| |
| /** |
| * \brief Initialize for channel scan. |
| * \param demod: Pointer to demodulator instance. |
| * \param scanParam: Pointer to scan parameters. |
| * \return DRXStatus_t. |
| * \retval DRX_STS_OK: Initialized for scan. |
| * \retval DRX_STS_ERROR: No overlap between frequency plan and tuner |
| * range. |
| * \retval DRX_STS_INVALID_ARG: Wrong parameters. |
| * |
| * This function should be called before starting a complete channel scan. |
| * It will prepare everything for a complete channel scan. |
| * After calling this function the DRX_CTRL_SCAN_NEXT control function can be |
| * used to perform the actual scanning. Scanning will start at the first |
| * center frequency of the frequency plan that is within the tuner range. |
| * |
| */ |
| static DRXStatus_t |
| CtrlScanInit(pDRXDemodInstance_t demod, pDRXScanParam_t scanParam) |
| { |
| DRXStatus_t status = DRX_STS_ERROR; |
| pDRXCommonAttr_t commonAttr = (pDRXCommonAttr_t) (NULL); |
| DRXFrequency_t maxTunerFreq = 0; |
| DRXFrequency_t minTunerFreq = 0; |
| u16_t nrChannelsInPlan = 0; |
| u16_t i = 0; |
| void *scanContext = NULL; |
| |
| commonAttr = (pDRXCommonAttr_t) demod->myCommonAttr; |
| commonAttr->scanActive = TRUE; |
| |
| /* invalidate a previous SCAN_INIT */ |
| commonAttr->scanParam = (pDRXScanParam_t) (NULL); |
| commonAttr->scanNextFrequency = 0; |
| |
| /* Check parameters */ |
| if (((demod->myTuner == NULL) && |
| (scanParam->numTries != 1)) || |
| (scanParam == NULL) || |
| (scanParam->numTries == 0) || |
| (scanParam->frequencyPlan == NULL) || |
| (scanParam->frequencyPlanSize == 0) |
| ) { |
| commonAttr->scanActive = FALSE; |
| return DRX_STS_INVALID_ARG; |
| } |
| |
| /* Check frequency plan contents */ |
| maxTunerFreq = commonAttr->tunerMaxFreqRF; |
| minTunerFreq = commonAttr->tunerMinFreqRF; |
| for (i = 0; i < (scanParam->frequencyPlanSize); i++) { |
| DRXFrequency_t width = 0; |
| DRXFrequency_t step = scanParam->frequencyPlan[i].step; |
| DRXFrequency_t firstFreq = scanParam->frequencyPlan[i].first; |
| DRXFrequency_t lastFreq = scanParam->frequencyPlan[i].last; |
| DRXFrequency_t minFreq = 0; |
| DRXFrequency_t maxFreq = 0; |
| |
| if (step <= 0) { |
| /* Step must be positive and non-zero */ |
| commonAttr->scanActive = FALSE; |
| return DRX_STS_INVALID_ARG; |
| } |
| |
| if (firstFreq > lastFreq) { |
| /* First center frequency is higher than last center frequency */ |
| commonAttr->scanActive = FALSE; |
| return DRX_STS_INVALID_ARG; |
| } |
| |
| width = lastFreq - firstFreq; |
| |
| if ((width % step) != 0) { |
| /* Difference between last and first center frequency is not |
| an integer number of steps */ |
| commonAttr->scanActive = FALSE; |
| return DRX_STS_INVALID_ARG; |
| } |
| |
| /* Check if frequency plan entry intersects with tuner range */ |
| if (lastFreq >= minTunerFreq) { |
| if (firstFreq <= maxTunerFreq) { |
| if (firstFreq >= minTunerFreq) { |
| minFreq = firstFreq; |
| } else { |
| DRXFrequency_t n = 0; |
| |
| n = (minTunerFreq - firstFreq) / step; |
| if (((minTunerFreq - |
| firstFreq) % step) != 0) { |
| n++; |
| } |
| minFreq = firstFreq + n * step; |
| } |
| |
| if (lastFreq <= maxTunerFreq) { |
| maxFreq = lastFreq; |
| } else { |
| DRXFrequency_t n = 0; |
| |
| n = (lastFreq - maxTunerFreq) / step; |
| if (((lastFreq - |
| maxTunerFreq) % step) != 0) { |
| n++; |
| } |
| maxFreq = lastFreq - n * step; |
| } |
| } |
| } |
| |
| /* Keep track of total number of channels within tuner range |
| in this frequency plan. */ |
| if ((minFreq != 0) && (maxFreq != 0)) { |
| nrChannelsInPlan += |
| (u16_t) (((maxFreq - minFreq) / step) + 1); |
| |
| /* Determine first frequency (within tuner range) to scan */ |
| if (commonAttr->scanNextFrequency == 0) { |
| commonAttr->scanNextFrequency = minFreq; |
| commonAttr->scanFreqPlanIndex = i; |
| } |
| } |
| |
| } /* for ( ... ) */ |
| |
| if (nrChannelsInPlan == 0) { |
| /* Tuner range and frequency plan ranges do not overlap */ |
| commonAttr->scanActive = FALSE; |
| return DRX_STS_ERROR; |
| } |
| |
| /* Store parameters */ |
| commonAttr->scanReady = FALSE; |
| commonAttr->scanMaxChannels = nrChannelsInPlan; |
| commonAttr->scanChannelsScanned = 0; |
| commonAttr->scanParam = scanParam; /* SCAN_NEXT is now allowed */ |
| |
| scanContext = GetScanContext(demod, scanContext); |
| |
| status = (*(GetScanFunction(demod))) |
| (scanContext, DRX_SCAN_COMMAND_INIT, NULL, NULL); |
| |
| commonAttr->scanActive = FALSE; |
| |
| return DRX_STS_OK; |
| } |
| |
| /*============================================================================*/ |
| |
| /** |
| * \brief Stop scanning. |
| * \param demod: Pointer to demodulator instance. |
| * \return DRXStatus_t. |
| * \retval DRX_STS_OK: Scan stopped. |
| * \retval DRX_STS_ERROR: Something went wrong. |
| * \retval DRX_STS_INVALID_ARG: Wrong parameters. |
| */ |
| static DRXStatus_t CtrlScanStop(pDRXDemodInstance_t demod) |
| { |
| DRXStatus_t status = DRX_STS_ERROR; |
| pDRXCommonAttr_t commonAttr = (pDRXCommonAttr_t) (NULL); |
| void *scanContext = NULL; |
| |
| commonAttr = (pDRXCommonAttr_t) demod->myCommonAttr; |
| commonAttr->scanActive = TRUE; |
| |
| if ((commonAttr->scanParam == NULL) || |
| (commonAttr->scanMaxChannels == 0)) { |
| /* Scan was not running, just return OK */ |
| commonAttr->scanActive = FALSE; |
| return DRX_STS_OK; |
| } |
| |
| /* Call default or device-specific scanning stop function */ |
| scanContext = GetScanContext(demod, scanContext); |
| |
| status = (*(GetScanFunction(demod))) |
| (scanContext, DRX_SCAN_COMMAND_STOP, NULL, NULL); |
| |
| /* All done, invalidate scan-init */ |
| commonAttr->scanParam = NULL; |
| commonAttr->scanMaxChannels = 0; |
| commonAttr->scanActive = FALSE; |
| |
| return status; |
| } |
| |
| /*============================================================================*/ |
| |
| /** |
| * \brief Scan for next channel. |
| * \param demod: Pointer to demodulator instance. |
| * \param scanProgress: Pointer to scan progress. |
| * \return DRXStatus_t. |
| * \retval DRX_STS_OK: Channel found, DRX_CTRL_GET_CHANNEL can be used |
| * to retrieve channel parameters. |
| * \retval DRX_STS_BUSY: Tried part of the channels, as specified in |
| * numTries field of scan parameters. At least one |
| * more call to DRX_CTRL_SCAN_NEXT is needed to |
| * complete scanning. |
| * \retval DRX_STS_READY: Reached end of scan range. |
| * \retval DRX_STS_ERROR: Something went wrong. |
| * \retval DRX_STS_INVALID_ARG: Wrong parameters. The scanProgress may be NULL. |
| * |
| * Progress indication will run from 0 upto DRX_SCAN_MAX_PROGRESS during scan. |
| * |
| */ |
| static DRXStatus_t CtrlScanNext(pDRXDemodInstance_t demod, pu16_t scanProgress) |
| { |
| pDRXCommonAttr_t commonAttr = (pDRXCommonAttr_t) (NULL); |
| pBool_t scanReady = (pBool_t) (NULL); |
| u16_t maxProgress = DRX_SCAN_MAX_PROGRESS; |
| u32_t numTries = 0; |
| u32_t i = 0; |
| |
| commonAttr = (pDRXCommonAttr_t) demod->myCommonAttr; |
| |
| /* Check scan parameters */ |
| if (scanProgress == NULL) { |
| commonAttr->scanActive = FALSE; |
| return DRX_STS_INVALID_ARG; |
| } |
| |
| *scanProgress = 0; |
| commonAttr->scanActive = TRUE; |
| if ((commonAttr->scanParam == NULL) || |
| (commonAttr->scanMaxChannels == 0)) { |
| /* CtrlScanInit() was not called succesfully before CtrlScanNext() */ |
| commonAttr->scanActive = FALSE; |
| return DRX_STS_ERROR; |
| } |
| |
| *scanProgress = (u16_t) (((commonAttr->scanChannelsScanned) * |
| ((u32_t) (maxProgress))) / |
| (commonAttr->scanMaxChannels)); |
| |
| /* Scan */ |
| numTries = commonAttr->scanParam->numTries; |
| scanReady = &(commonAttr->scanReady); |
| |
| for (i = 0; ((i < numTries) && ((*scanReady) == FALSE)); i++) { |
| DRXChannel_t scanChannel = { 0 }; |
| DRXStatus_t status = DRX_STS_ERROR; |
| pDRXFrequencyPlan_t freqPlan = (pDRXFrequencyPlan_t) (NULL); |
| Bool_t nextChannel = FALSE; |
| void *scanContext = NULL; |
| |
| /* Next channel to scan */ |
| freqPlan = |
| &(commonAttr->scanParam-> |
| frequencyPlan[commonAttr->scanFreqPlanIndex]); |
| scanChannel.frequency = commonAttr->scanNextFrequency; |
| scanChannel.bandwidth = freqPlan->bandwidth; |
| scanChannel.mirror = DRX_MIRROR_AUTO; |
| scanChannel.constellation = DRX_CONSTELLATION_AUTO; |
| scanChannel.hierarchy = DRX_HIERARCHY_AUTO; |
| scanChannel.priority = DRX_PRIORITY_HIGH; |
| scanChannel.coderate = DRX_CODERATE_AUTO; |
| scanChannel.guard = DRX_GUARD_AUTO; |
| scanChannel.fftmode = DRX_FFTMODE_AUTO; |
| scanChannel.classification = DRX_CLASSIFICATION_AUTO; |
| scanChannel.symbolrate = 0; |
| scanChannel.interleavemode = DRX_INTERLEAVEMODE_AUTO; |
| scanChannel.ldpc = DRX_LDPC_AUTO; |
| scanChannel.carrier = DRX_CARRIER_AUTO; |
| scanChannel.framemode = DRX_FRAMEMODE_AUTO; |
| scanChannel.pilot = DRX_PILOT_AUTO; |
| |
| /* Call default or device-specific scanning function */ |
| scanContext = GetScanContext(demod, scanContext); |
| |
| status = (*(GetScanFunction(demod))) |
| (scanContext, DRX_SCAN_COMMAND_NEXT, &scanChannel, |
| &nextChannel); |
| |
| /* Proceed to next channel if requested */ |
| if (nextChannel == TRUE) { |
| DRXStatus_t nextStatus = DRX_STS_ERROR; |
| DRXFrequency_t skip = 0; |
| |
| if (status == DRX_STS_OK) { |
| /* a channel was found, so skip some frequency steps */ |
| skip = commonAttr->scanParam->skip; |
| } |
| nextStatus = ScanPrepareNextScan(demod, skip); |
| |
| /* keep track of progress */ |
| *scanProgress = |
| (u16_t) (((commonAttr->scanChannelsScanned) * |
| ((u32_t) (maxProgress))) / |
| (commonAttr->scanMaxChannels)); |
| |
| if (nextStatus != DRX_STS_OK) { |
| commonAttr->scanActive = FALSE; |
| return (nextStatus); |
| } |
| } |
| if (status != DRX_STS_BUSY) { |
| /* channel found or error */ |
| commonAttr->scanActive = FALSE; |
| return status; |
| } |
| } /* for ( i = 0; i < ( ... numTries); i++) */ |
| |
| if ((*scanReady) == TRUE) { |
| /* End of scan reached: call stop-scan, ignore any error */ |
| CtrlScanStop(demod); |
| commonAttr->scanActive = FALSE; |
| return (DRX_STS_READY); |
| } |
| |
| commonAttr->scanActive = FALSE; |
| |
| return DRX_STS_BUSY; |
| } |
| |
| #endif /* #ifndef DRX_EXCLUDE_SCAN */ |
| |
| /*============================================================================*/ |
| |
| /** |
| * \brief Program tuner. |
| * \param demod: Pointer to demodulator instance. |
| * \param tunerChannel: Pointer to tuning parameters. |
| * \return DRXStatus_t. |
| * \retval DRX_STS_OK: Tuner programmed successfully. |
| * \retval DRX_STS_ERROR: Something went wrong. |
| * \retval DRX_STS_INVALID_ARG: Wrong parameters. |
| * |
| * tunerChannel passes parameters to program the tuner, |
| * but also returns the actual RF and IF frequency from the tuner. |
| * |
| */ |
| static DRXStatus_t |
| CtrlProgramTuner(pDRXDemodInstance_t demod, pDRXChannel_t channel) |
| { |
| pDRXCommonAttr_t commonAttr = (pDRXCommonAttr_t) (NULL); |
| DRXStandard_t standard = DRX_STANDARD_UNKNOWN; |
| TUNERMode_t tunerMode = 0; |
| DRXStatus_t status = DRX_STS_ERROR; |
| DRXFrequency_t ifFrequency = 0; |
| Bool_t tunerSlowMode = FALSE; |
| |
| /* can't tune without a tuner */ |
| if (demod->myTuner == NULL) { |
| return DRX_STS_INVALID_ARG; |
| } |
| |
| commonAttr = (pDRXCommonAttr_t) demod->myCommonAttr; |
| |
| /* select analog or digital tuner mode based on current standard */ |
| if (DRX_Ctrl(demod, DRX_CTRL_GET_STANDARD, &standard) != DRX_STS_OK) { |
| return DRX_STS_ERROR; |
| } |
| |
| if (DRX_ISATVSTD(standard)) { |
| tunerMode |= TUNER_MODE_ANALOG; |
| } else { /* note: also for unknown standard */ |
| |
| tunerMode |= TUNER_MODE_DIGITAL; |
| } |
| |
| /* select tuner bandwidth */ |
| switch (channel->bandwidth) { |
| case DRX_BANDWIDTH_6MHZ: |
| tunerMode |= TUNER_MODE_6MHZ; |
| break; |
| case DRX_BANDWIDTH_7MHZ: |
| tunerMode |= TUNER_MODE_7MHZ; |
| break; |
| case DRX_BANDWIDTH_8MHZ: |
| tunerMode |= TUNER_MODE_8MHZ; |
| break; |
| default: /* note: also for unknown bandwidth */ |
| return DRX_STS_INVALID_ARG; |
| } |
| |
| DRX_GET_TUNERSLOWMODE(demod, tunerSlowMode); |
| |
| /* select fast (switch) or slow (lock) tuner mode */ |
| if (tunerSlowMode) { |
| tunerMode |= TUNER_MODE_LOCK; |
| } else { |
| tunerMode |= TUNER_MODE_SWITCH; |
| } |
| |
| if (commonAttr->tunerPortNr == 1) { |
| Bool_t bridgeClosed = TRUE; |
| DRXStatus_t statusBridge = DRX_STS_ERROR; |
| |
| statusBridge = |
| DRX_Ctrl(demod, DRX_CTRL_I2C_BRIDGE, &bridgeClosed); |
| if (statusBridge != DRX_STS_OK) { |
| return statusBridge; |
| } |
| } |
| |
| status = DRXBSP_TUNER_SetFrequency(demod->myTuner, |
| tunerMode, channel->frequency); |
| |
| /* attempt restoring bridge before checking status of SetFrequency */ |
| if (commonAttr->tunerPortNr == 1) { |
| Bool_t bridgeClosed = FALSE; |
| DRXStatus_t statusBridge = DRX_STS_ERROR; |
| |
| statusBridge = |
| DRX_Ctrl(demod, DRX_CTRL_I2C_BRIDGE, &bridgeClosed); |
| if (statusBridge != DRX_STS_OK) { |
| return statusBridge; |
| } |
| } |
| |
| /* now check status of DRXBSP_TUNER_SetFrequency */ |
| if (status != DRX_STS_OK) { |
| return status; |
| } |
| |
| /* get actual RF and IF frequencies from tuner */ |
| status = DRXBSP_TUNER_GetFrequency(demod->myTuner, |
| tunerMode, |
| &(channel->frequency), |
| &(ifFrequency)); |
| if (status != DRX_STS_OK) { |
| return status; |
| } |
| |
| /* update common attributes with information available from this function; |
| TODO: check if this is required and safe */ |
| DRX_SET_INTERMEDIATEFREQ(demod, ifFrequency); |
| |
| return DRX_STS_OK; |
| } |
| |
| /*============================================================================*/ |
| |
| /** |
| * \brief function to do a register dump. |
| * \param demod: Pointer to demodulator instance. |
| * \param registers: Registers to dump. |
| * \return DRXStatus_t. |
| * \retval DRX_STS_OK: Dump executed successfully. |
| * \retval DRX_STS_ERROR: Something went wrong. |
| * \retval DRX_STS_INVALID_ARG: Wrong parameters. |
| * |
| */ |
| DRXStatus_t CtrlDumpRegisters(pDRXDemodInstance_t demod, |
| pDRXRegDump_t registers) |
| { |
| u16_t i = 0; |
| |
| if (registers == NULL) { |
| /* registers not supplied */ |
| return DRX_STS_INVALID_ARG; |
| } |
| |
| /* start dumping registers */ |
| while (registers[i].address != 0) { |
| DRXStatus_t status = DRX_STS_ERROR; |
| u16_t value = 0; |
| u32_t data = 0; |
| |
| status = |
| demod->myAccessFunct->readReg16Func(demod->myI2CDevAddr, |
| registers[i].address, |
| &value, 0); |
| |
| data = (u32_t) value; |
| |
| if (status != DRX_STS_OK) { |
| /* no breakouts; |
| depending on device ID, some HW blocks might not be available */ |
| data |= ((u32_t) status) << 16; |
| } |
| registers[i].data = data; |
| i++; |
| } |
| |
| /* all done, all OK (any errors are saved inside data) */ |
| return DRX_STS_OK; |
| } |
| |
| /*============================================================================*/ |
| /*============================================================================*/ |
| /*===Microcode related functions==============================================*/ |
| /*============================================================================*/ |
| /*============================================================================*/ |
| |
| /** |
| * \brief Read a 16 bits word, expects big endian data. |
| * \param addr: Pointer to memory from which to read the 16 bits word. |
| * \return u16_t The data read. |
| * |
| * This function takes care of the possible difference in endianness between the |
| * host and the data contained in the microcode image file. |
| * |
| */ |
| 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; |
| } |
| |
| /*============================================================================*/ |
| |
| /** |
| * \brief Read a 32 bits word, expects big endian data. |
| * \param addr: Pointer to memory from which to read the 32 bits word. |
| * \return u32_t The data read. |
| * |
| * This function takes care of the possible difference in endianness between the |
| * host and the data contained in the microcode image file. |
| * |
| */ |
| 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; |
| } |
| |
| /*============================================================================*/ |
| |
| /** |
| * \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)); |
| } |
| |
| /*============================================================================*/ |
| |
| /** |
| * \brief Handle microcode upload or verify. |
| * \param devAddr: Address of device. |
| * \param mcInfo: Pointer to information about microcode data. |
| * \param action: Either UCODE_UPLOAD or UCODE_VERIFY |
| * \return DRXStatus_t. |
| * \retval DRX_STS_OK: |
| * - In case of UCODE_UPLOAD: code is successfully uploaded. |
| * - In case of UCODE_VERIFY: image on device is equal to |
| * image provided to this control function. |
| * \retval DRX_STS_ERROR: |
| * - In case of UCODE_UPLOAD: I2C error. |
| * - In case of UCODE_VERIFY: I2C error or image on device |
| * is not equal to image provided to this control function. |
| * \retval DRX_STS_INVALID_ARG: |
| * - Invalid arguments. |
| * - Provided image is corrupt |
| */ |
| static DRXStatus_t |
| CtrlUCode(pDRXDemodInstance_t demod, |
| pDRXUCodeInfo_t mcInfo, DRXUCodeAction_t action) |
| { |
| DRXStatus_t rc; |
| u16_t i = 0; |
| u16_t mcNrOfBlks = 0; |
| u16_t mcMagicWord = 0; |
| pu8_t mcData = (pu8_t) (NULL); |
| pI2CDeviceAddr_t devAddr = (pI2CDeviceAddr_t) (NULL); |
| |
| devAddr = demod->myI2CDevAddr; |
| |
| /* Check arguments */ |
| if ((mcInfo == NULL) || (mcInfo->mcData == NULL)) { |
| 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 != DRX_UCODE_MAGIC_WORD) || (mcNrOfBlks == 0)) { |
| /* wrong endianess or wrong data ? */ |
| return DRX_STS_INVALID_ARG; |
| } |
| |
| /* Scan microcode blocks first for version info if uploading */ |
| if (action == UCODE_UPLOAD) { |
| /* Clear version block */ |
| DRX_SET_MCVERTYPE(demod, 0); |
| DRX_SET_MCDEV(demod, 0); |
| DRX_SET_MCVERSION(demod, 0); |
| DRX_SET_MCPATCH(demod, 0); |
| for (i = 0; i < mcNrOfBlks; i++) { |
| DRXUCodeBlockHdr_t blockHdr; |
| |
| /* 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); |
| |
| if (blockHdr.flags & 0x8) { |
| /* Aux block. Check type */ |
| pu8_t auxblk = mcInfo->mcData + blockHdr.addr; |
| u16_t auxtype = UCodeRead16(auxblk); |
| if (DRX_ISMCVERTYPE(auxtype)) { |
| DRX_SET_MCVERTYPE(demod, |
| UCodeRead16(auxblk)); |
| auxblk += sizeof(u16_t); |
| DRX_SET_MCDEV(demod, |
| UCodeRead32(auxblk)); |
| auxblk += sizeof(u32_t); |
| DRX_SET_MCVERSION(demod, |
| UCodeRead32(auxblk)); |
| auxblk += sizeof(u32_t); |
| DRX_SET_MCPATCH(demod, |
| UCodeRead32(auxblk)); |
| } |
| } |
| |
| /* Next block */ |
| mcData += blockHdr.size * sizeof(u16_t); |
| } |
| |
| /* After scanning, validate the microcode. |
| It is also valid if no validation control exists. |
| */ |
| rc = DRX_Ctrl(demod, DRX_CTRL_VALIDATE_UCODE, NULL); |
| if (rc != DRX_STS_OK && rc != DRX_STS_FUNC_NOT_AVAILABLE) { |
| return rc; |
| } |
| |
| /* Restore data pointer */ |
| mcData = mcInfo->mcData + 2 * sizeof(u16_t); |
| } |
| |
| /* 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: |
| - data larger than 64Kb |
| - if CRC enabled check CRC |
| */ |
| if ((blockHdr.size > 0x7FFF) || |
| (((blockHdr.flags & DRX_UCODE_CRC_FLAG) != 0) && |
| (blockHdr.CRC != UCodeComputeCRC(mcData, blockHdr.size))) |
| ) { |
| /* Wrong data ! */ |
| return DRX_STS_INVALID_ARG; |
| } |
| |
| mcBlockNrBytes = blockHdr.size * ((u16_t) sizeof(u16_t)); |
| |
| if (blockHdr.size != 0) { |
| /* Perform the desired action */ |
| 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); |
| } /* if */ |
| }; |
| break; |
| |
| /*================================================================*/ |
| case UCODE_VERIFY: |
| { |
| int result = 0; |
| u8_t mcDataBuffer |
| [DRX_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) |
| DRX_UCODE_MAX_BUF_SIZE)) { |
| bytesToCompare = |
| ((u32_t) |
| DRX_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 > DRX_UCODE_MAX_BUF_SIZE ) */ |
| }; |
| break; |
| |
| /*================================================================*/ |
| default: |
| return DRX_STS_INVALID_ARG; |
| break; |
| |
| } /* switch ( action ) */ |
| } |
| |
| /* if (blockHdr.size != 0 ) */ |
| /* Next block */ |
| mcData += mcBlockNrBytes; |
| |
| } /* for( i = 0 ; i<mcNrOfBlks ; i++ ) */ |
| |
| return DRX_STS_OK; |
| } |
| |
| /*============================================================================*/ |
| |
| /** |
| * \brief Build list of version information. |
| * \param demod: A pointer to a demodulator instance. |
| * \param versionList: Pointer to linked list of versions. |
| * \return DRXStatus_t. |
| * \retval DRX_STS_OK: Version information stored in versionList |
| * \retval DRX_STS_INVALID_ARG: Invalid arguments. |
| */ |
| static DRXStatus_t |
| CtrlVersion(pDRXDemodInstance_t demod, pDRXVersionList_t * versionList) |
| { |
| static char drxDriverCoreModuleName[] = "Core driver"; |
| static char drxDriverCoreVersionText[] = |
| DRX_VERSIONSTRING(VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH); |
| |
| static DRXVersion_t drxDriverCoreVersion; |
| static DRXVersionList_t drxDriverCoreVersionList; |
| |
| pDRXVersionList_t demodVersionList = (pDRXVersionList_t) (NULL); |
| DRXStatus_t returnStatus = DRX_STS_ERROR; |
| |
| /* Check arguments */ |
| if (versionList == NULL) { |
| return DRX_STS_INVALID_ARG; |
| } |
| |
| /* Get version info list from demod */ |
| returnStatus = (*(demod->myDemodFunct->ctrlFunc)) (demod, |
| DRX_CTRL_VERSION, |
| (void *) |
| &demodVersionList); |
| |
| /* Always fill in the information of the driver SW . */ |
| drxDriverCoreVersion.moduleType = DRX_MODULE_DRIVERCORE; |
| drxDriverCoreVersion.moduleName = drxDriverCoreModuleName; |
| drxDriverCoreVersion.vMajor = VERSION_MAJOR; |
| drxDriverCoreVersion.vMinor = VERSION_MINOR; |
| drxDriverCoreVersion.vPatch = VERSION_PATCH; |
| drxDriverCoreVersion.vString = drxDriverCoreVersionText; |
| |
| drxDriverCoreVersionList.version = &drxDriverCoreVersion; |
| drxDriverCoreVersionList.next = (pDRXVersionList_t) (NULL); |
| |
| if ((returnStatus == DRX_STS_OK) && (demodVersionList != NULL)) { |
| /* Append versioninfo from driver to versioninfo from demod */ |
| /* Return version info in "bottom-up" order. This way, multiple |
| devices can be handled without using malloc. */ |
| pDRXVersionList_t currentListElement = demodVersionList; |
| while (currentListElement->next != NULL) { |
| currentListElement = currentListElement->next; |
| } |
| currentListElement->next = &drxDriverCoreVersionList; |
| |
| *versionList = demodVersionList; |
| } else { |
| /* Just return versioninfo from driver */ |
| *versionList = &drxDriverCoreVersionList; |
| } |
| |
| return DRX_STS_OK; |
| } |
| |
| /*============================================================================*/ |
| /*============================================================================*/ |
| /*== Exported functions ======================================================*/ |
| /*============================================================================*/ |
| /*============================================================================*/ |
| |
| /** |
| * \brief This function is obsolete. |
| * \param demods: Don't care, parameter is ignored. |
| * \return DRXStatus_t Return status. |
| * \retval DRX_STS_OK: Initialization completed. |
| * |
| * This function is obsolete, prototype available for backward compatability. |
| * |
| */ |
| |
| DRXStatus_t DRX_Init(pDRXDemodInstance_t demods[]) |
| { |
| return DRX_STS_OK; |
| } |
| |
| /*============================================================================*/ |
| |
| /** |
| * \brief This function is obsolete. |
| * \return DRXStatus_t Return status. |
| * \retval DRX_STS_OK: Terminated driver successful. |
| * |
| * This function is obsolete, prototype available for backward compatability. |
| * |
| */ |
| |
| DRXStatus_t DRX_Term(void) |
| { |
| return DRX_STS_OK; |
| } |
| |
| /*============================================================================*/ |
| |
| /** |
| * \brief Open a demodulator instance. |
| * \param demod: A pointer to a demodulator instance. |
| * \return DRXStatus_t Return status. |
| * \retval DRX_STS_OK: Opened demod instance with succes. |
| * \retval DRX_STS_ERROR: Driver not initialized or unable to initialize |
| * demod. |
| * \retval DRX_STS_INVALID_ARG: Demod instance has invalid content. |
| * |
| */ |
| |
| DRXStatus_t DRX_Open(pDRXDemodInstance_t demod) |
| { |
| DRXStatus_t status = DRX_STS_OK; |
| |
| if ((demod == NULL) || |
| (demod->myDemodFunct == NULL) || |
| (demod->myCommonAttr == NULL) || |
| (demod->myExtAttr == NULL) || |
| (demod->myI2CDevAddr == NULL) || |
| (demod->myCommonAttr->isOpened == TRUE)) { |
| return (DRX_STS_INVALID_ARG); |
| } |
| |
| status = (*(demod->myDemodFunct->openFunc)) (demod); |
| |
| if (status == DRX_STS_OK) { |
| demod->myCommonAttr->isOpened = TRUE; |
| } |
| |
| return status; |
| } |
| |
| /*============================================================================*/ |
| |
| /** |
| * \brief Close device. |
| * \param demod: A pointer to a demodulator instance. |
| * \return DRXStatus_t Return status. |
| * \retval DRX_STS_OK: Closed demod instance with succes. |
| * \retval DRX_STS_ERROR: Driver not initialized or error during close |
| * demod. |
| * \retval DRX_STS_INVALID_ARG: Demod instance has invalid content. |
| * |
| * Free resources occupied by device instance. |
| * Put device into sleep mode. |
| */ |
| |
| DRXStatus_t DRX_Close(pDRXDemodInstance_t demod) |
| { |
| DRXStatus_t status = DRX_STS_OK; |
| |
| if ((demod == NULL) || |
| (demod->myDemodFunct == NULL) || |
| (demod->myCommonAttr == NULL) || |
| (demod->myExtAttr == NULL) || |
| (demod->myI2CDevAddr == NULL) || |
| (demod->myCommonAttr->isOpened == FALSE)) { |
| return DRX_STS_INVALID_ARG; |
| } |
| |
| status = (*(demod->myDemodFunct->closeFunc)) (demod); |
| |
| DRX_SET_ISOPENED(demod, FALSE); |
| |
| return status; |
| } |
| |
| /*============================================================================*/ |
| |
| /** |
| * \brief Control the device. |
| * \param demod: A pointer to a demodulator instance. |
| * \param ctrl: Reference to desired control function. |
| * \param ctrlData: Pointer to data structure for control function. |
| * \return DRXStatus_t Return status. |
| * \retval DRX_STS_OK: Control function completed successfully. |
| * \retval DRX_STS_ERROR: Driver not initialized or error during |
| * control demod. |
| * \retval DRX_STS_INVALID_ARG: Demod instance or ctrlData has invalid |
| * content. |
| * \retval DRX_STS_FUNC_NOT_AVAILABLE: Specified control function is not |
| * available. |
| * |
| * Data needed or returned by the control function is stored in ctrlData. |
| * |
| */ |
| |
| DRXStatus_t |
| DRX_Ctrl(pDRXDemodInstance_t demod, DRXCtrlIndex_t ctrl, void *ctrlData) |
| { |
| DRXStatus_t status = DRX_STS_ERROR; |
| |
| if ((demod == NULL) || |
| (demod->myDemodFunct == NULL) || |
| (demod->myCommonAttr == NULL) || |
| (demod->myExtAttr == NULL) || (demod->myI2CDevAddr == NULL) |
| ) { |
| return (DRX_STS_INVALID_ARG); |
| } |
| |
| if (((demod->myCommonAttr->isOpened == FALSE) && |
| (ctrl != DRX_CTRL_PROBE_DEVICE) && (ctrl != DRX_CTRL_VERSION)) |
| ) { |
| return (DRX_STS_INVALID_ARG); |
| } |
| |
| if ((DRX_ISPOWERDOWNMODE(demod->myCommonAttr->currentPowerMode) && |
| (ctrl != DRX_CTRL_POWER_MODE) && |
| (ctrl != DRX_CTRL_PROBE_DEVICE) && |
| (ctrl != DRX_CTRL_NOP) && (ctrl != DRX_CTRL_VERSION) |
| ) |
| ) { |
| return DRX_STS_FUNC_NOT_AVAILABLE; |
| } |
| |
| /* Fixed control functions */ |
| switch (ctrl) { |
| /*======================================================================*/ |
| case DRX_CTRL_NOP: |
| /* No operation */ |
| return DRX_STS_OK; |
| break; |
| |
| /*======================================================================*/ |
| case DRX_CTRL_VERSION: |
| return CtrlVersion(demod, (pDRXVersionList_t *) ctrlData); |
| break; |
| |
| /*======================================================================*/ |
| default: |
| /* Do nothing */ |
| break; |
| } |
| |
| /* Virtual functions */ |
| /* First try calling function from derived class */ |
| status = (*(demod->myDemodFunct->ctrlFunc)) (demod, ctrl, ctrlData); |
| if (status == DRX_STS_FUNC_NOT_AVAILABLE) { |
| /* Now try calling a the base class function */ |
| switch (ctrl) { |
| /*===================================================================*/ |
| case DRX_CTRL_LOAD_UCODE: |
| return CtrlUCode(demod, |
| (pDRXUCodeInfo_t) ctrlData, |
| UCODE_UPLOAD); |
| break; |
| |
| /*===================================================================*/ |
| case DRX_CTRL_VERIFY_UCODE: |
| { |
| return CtrlUCode(demod, |
| (pDRXUCodeInfo_t) ctrlData, |
| UCODE_VERIFY); |
| } |
| break; |
| |
| #ifndef DRX_EXCLUDE_SCAN |
| /*===================================================================*/ |
| case DRX_CTRL_SCAN_INIT: |
| { |
| return CtrlScanInit(demod, |
| (pDRXScanParam_t) ctrlData); |
| } |
| break; |
| |
| /*===================================================================*/ |
| case DRX_CTRL_SCAN_NEXT: |
| { |
| return CtrlScanNext(demod, (pu16_t) ctrlData); |
| } |
| break; |
| |
| /*===================================================================*/ |
| case DRX_CTRL_SCAN_STOP: |
| { |
| return CtrlScanStop(demod); |
| } |
| break; |
| #endif /* #ifndef DRX_EXCLUDE_SCAN */ |
| |
| /*===================================================================*/ |
| case DRX_CTRL_PROGRAM_TUNER: |
| { |
| return CtrlProgramTuner(demod, |
| (pDRXChannel_t) |
| ctrlData); |
| } |
| break; |
| |
| /*===================================================================*/ |
| case DRX_CTRL_DUMP_REGISTERS: |
| { |
| return CtrlDumpRegisters(demod, |
| (pDRXRegDump_t) |
| ctrlData); |
| } |
| break; |
| |
| /*===================================================================*/ |
| default: |
| return DRX_STS_FUNC_NOT_AVAILABLE; |
| } |
| } else { |
| return (status); |
| } |
| |
| return DRX_STS_OK; |
| } |
| |
| /*============================================================================*/ |
| |
| /* END OF FILE */ |