mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-19 17:14:40 +08:00
443f18d0d5
Do the automatic CodingStyle fixes found at Lindent. No functional changes. Acked-by: Devin Heitmueller <dheitmueller@kernellabs.com> Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
1511 lines
44 KiB
C
1511 lines
44 KiB
C
/*
|
|
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 */
|