⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 drx_driver.c

📁 用于DRX3973或DRX39系列的芯片的控制
💻 C
📖 第 1 页 / 共 3 页
字号:
/**
* \file $Id: drx_driver.c,v 1.16 2005/11/07 10:15:29 paulja Exp $
*
* \brief Generic DRX functionality, DRX driver core.
*
* \author Paul Janssen
*/

/*
* $(c) 2004-2005 Micronas GmbH. All rights reserved.
*
* This software and related documentation (the 'Software') are intellectual
* property owned by Micronas and are copyright of Micronas, unless specifically
* noted otherwise.
*
* Any use of the Software is permitted only pursuant to the terms of the
* license agreement, if any, which accompanies, is included with or applicable
* to the Software ('License Agreement') or upon express written consent of
* Micronas. Any copying, reproduction or redistribution of the Software in
* whole or in part by any means not in accordance with the License Agreement
* or as agreed in writing by Micronas is expressly prohibited.
*
* THE SOFTWARE IS WARRANTED, IF AT ALL, ONLY ACCORDING TO THE TERMS OF THE
* LICENSE AGREEMENT. EXCEPT AS WARRANTED IN THE LICENSE AGREEMENT THE SOFTWARE
* IS DELIVERED 'AS IS' AND MICRONAS HEREBY DISCLAIMS ALL WARRANTIES AND
* CONDITIONS WITH REGARD TO THE SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
* AND CONDITIONS OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIT
* ENJOYMENT, TITLE AND NON-INFRINGEMENT OF ANY THIRD PARTY INTELLECTUAL
* PROPERTY OR OTHER RIGHTS WHICH MAY RESULT FROM THE USE OR THE INABILITY
* TO USE THE SOFTWARE.
*
* IN NO EVENT SHALL MICRONAS BE LIABLE FOR INDIRECT, INCIDENTAL, CONSEQUENTIAL,
* PUNITIVE, SPECIAL OR OTHER DAMAGES WHATSOEVER INCLUDING WITHOUT LIMITATION,
* DAMAGES FOR LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS
* INFORMATION, AND THE LIKE, ARISING OUT OF OR RELATING TO THE USE OF OR THE
* INABILITY TO USE THE SOFTWARE, EVEN IF MICRONAS HAS BEEN ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES, EXCEPT PERSONAL INJURY OR DEATH RESULTING FROM
* MICRONAS' NEGLIGENCE.                                                        $
*
*/

/*-----------------------------------------------------------------------------
INCLUDE FILES
----------------------------------------------------------------------------*/
#include "drx_driver.h"
#include "drx_driver_version.h"
#include "bsp_host.h"


/*-----------------------------------------------------------------------------
DEFINES
----------------------------------------------------------------------------*/

/*============================================================================*/
/*=== MICROCODE RELATED DEFINES ==============================================*/
/*============================================================================*/

/**
* \def UCODE_MAGIC_WORD
* \brief Magic word for checking correct Endianess of microcode data.
*
*/
#define UCODE_MAGIC_WORD         ((((char)'H')<<8)+((char)'L'))
/**
* \def UCODE_CRC_FLAG
* \brief CRC flag in ucode header, flags field.
*
*/
#define UCODE_CRC_FLAG           (0x0001)
/**
* \def UCODE_COMPRESSION_FLAG
* \brief Compression flag in ucode header, flags field.
*
*/
#define UCODE_COMPRESSION_FLAG   (0x0002)

/*============================================================================*/
/*=== CHANNEL SCAN RELATED DEFINES ===========================================*/
/*============================================================================*/

/**
* \def DRX_SCAN_MAX_PROGRESS
* \brief Maximum progress indication.
*
* Progress indication will run from 0 upto DRX_SCAN_MAX_PROGRESS during scan.
*
*/
#define DRX_SCAN_MAX_PROGRESS 1000

/**
* \def DRX_SCAN_8MHZ_STEP
* \brief Distance in kHz between two centre frequencies in 8Mhz grid
*/
#define DRX_SCAN_8MHZ_STEP 8000

/**
* \def DRX_SCAN_7MHZ_STEP
* \brief Distance in kHz between two centre frequencies in 7Mhz grid
*/
#define DRX_SCAN_7MHZ_STEP 7000

/**
* \def DRX_SCAN_6MHZ_STEP
* \brief Distance in kHz between two centre frequencies in 6Mhz grid
*/
#define DRX_SCAN_6MHZ_STEP 6000

/*-----------------------------------------------------------------------------
GLOBAL VARIABLES
----------------------------------------------------------------------------*/

/*============================================================================*/
/*============================================================================*/
/*== Instance administration =================================================*/
/*============================================================================*/
/*============================================================================*/

/* NULL terminated array of pointer to demod instance controled by driver. */
static pDRXDemodInstance_t *drxDriverDemodsInstancesList = NULL;


/*-----------------------------------------------------------------------------
STRUCTURES
----------------------------------------------------------------------------*/

typedef struct {
   u32_t addr;
   u16_t size;
   u16_t flags; /* bit[15..2]=reserved,
                   bit[1]= compression on/off
                   bit[0]= CRC on/off */
   u16_t CRC;
} DRXUCodeBlockHdr_t, *pDRXUCodeBlockHdr_t;

/*-----------------------------------------------------------------------------
FUNCTIONS
----------------------------------------------------------------------------*/

/*============================================================================*/
/*============================================================================*/
/*== Channel Scan Functions ==================================================*/
/*============================================================================*/
/*============================================================================*/

/**
* \fn DRXStatus_t ScanWaitForLock()
* \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.
*
* Wait until timeout, DEMOD_LOCK or NEVER_LOCK.
*
* Assume lock function returns : at least DRX_NOT_LOCKED and DRX_DEMOD_LOCK.
* In case DRX_NEVER_LOCK is returned the poll-wait will be aborted.
*
* Assume BSP has a clock function to retreive a millisecond ticker value.
*
*/
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;

   /* Check arguments */
   if ( isLocked == NULL )
   {
      return ( DRX_STS_INVALID_ARG);
   }

   *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();

      /* Check for time out in this lock stage */
      timerValue = currentTime - startTimeLockStage;
      if ( timerValue > timeoutValue )
      {
         /* Maximum timeout for this lock stage reached, return no_lock */
         doneWaiting = TRUE;
      }
      else
      {
         if ( lockState >= desiredLockState )
         {
                  *isLocked = TRUE;
                  doneWaiting = TRUE;
         }
         else if ( lockState == DRX_NEVER_LOCK )
         {
                  doneWaiting = TRUE;
         } /* if ( lockState != oldLockState ) .. */
      } /* if ( timerValue > timeoutValue ) */
   } /* while */

   return (DRX_STS_OK);
}

/*============================================================================*/

/**
* \fn DRXStatus_t ScanPrepareNextScan()
* \brief Determine next frequency to scan.
* \param demod Pointer to demodulator instance.
* \return DRXStatus_t.
* \retval DRX_STS_OK Succes.
* \retval DRX_STS_ERROR Something went wrong.
* \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 )
{
   pDRXCommonAttr_t     commonAttr=NULL;
   u16_t                tableIndex = 0;
   u16_t                frequencyPlanSize = 0;
   pDRXFrequencyPlan_t  frequencyPlan = NULL;
   DRXFrequency_t       nextFrequency = 0;
   DRXFrequency_t       frequencyStep = 0;
   DRXFrequency_t       tunerMinFrequency = 0;
   DRXFrequency_t       tunerMaxFrequency = 0;

   /* Check parameters */
   if ( demod ->myCommonAttr->scanParam == NULL)
   {
      return (DRX_STS_ERROR);
   }

   commonAttr        = (pDRXCommonAttr_t)demod->myCommonAttr;
   tableIndex        = commonAttr->scanFreqPlanIndex;
   frequencyPlan     = commonAttr->scanParam->frequencyPlan;
   nextFrequency     = commonAttr->scanNextFrequency;
   tunerMinFrequency = commonAttr->tunerMinFreqRF;
   tunerMaxFrequency = commonAttr->tunerMaxFreqRF;

   do {
      /* Determine frequency step of channel to scan */
      switch ( frequencyPlan[tableIndex].bandwidth ) {
         case DRX_BANDWIDTH_8MHZ:
            frequencyStep = DRX_SCAN_8MHZ_STEP;
            break;
         case DRX_BANDWIDTH_7MHZ:
            frequencyStep = DRX_SCAN_7MHZ_STEP;
            break;
         case DRX_BANDWIDTH_6MHZ:
            frequencyStep = DRX_SCAN_6MHZ_STEP;
            break;
         default:
            /* Frequency plan content is invalid */
            return (DRX_STS_INVALID_ARG);
            break;
      };

      /* Search next frequency to scan */
      nextFrequency += frequencyStep;
      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);
}

/*============================================================================*/

/**
* \fn DRXStatus_t CtrlScanInit()
* \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.
*
* After calling this routine scanning will start at the first centre frequency
* of the frequency plan that is within the tuner range.
*
*/
static DRXStatus_t
CtrlScanInit( pDRXDemodInstance_t  demod,
               pDRXScanParam_t scanParam )
{
   pDRXCommonAttr_t commonAttr=NULL;
   DRXFrequency_t maxTunerFreq = 0;
   DRXFrequency_t minTunerFreq = 0;
   u16_t nrChannelsInPlan = 0;
   u16_t i = 0;

   commonAttr = (pDRXCommonAttr_t)demod -> myCommonAttr;
   commonAttr->scanActive = TRUE;

   /* invalidate a previous SCAN_INIT */
   commonAttr->scanParam = NULL;
   commonAttr->scanNextFrequency = 0;

   /* Check parameters */
   if ( ( demod->myTuner == NULL) ||

        ( scanParam == NULL) ||

        ( scanParam->numTries == 0) ||

        ( scanParam->frequencyPlan == NULL) ||

        ( scanParam->frequencyPlanSize == 0 )
       )
   {
      commonAttr->scanActive = FALSE;
      return (DRX_STS_INVALID_ARG);
   } /* if */

   /* Check frequency plan contents */
   maxTunerFreq = commonAttr->tunerMaxFreqRF;
   minTunerFreq = commonAttr->tunerMinFreqRF;
   for( i = 0; i < (scanParam->frequencyPlanSize); i++ )
   {
      DRXFrequency_t width = 0;
      DRXFrequency_t step = 0;
      DRXFrequency_t firstFreq = scanParam->frequencyPlan[i].first;
      DRXFrequency_t lastFreq  = scanParam->frequencyPlan[i].last;
      DRXFrequency_t minFreq = 0;
      DRXFrequency_t maxFreq = 0;

      if ( firstFreq > lastFreq )
      {
            /* First centre frequency is higher then last centre frequency */
            commonAttr->scanActive = FALSE;
            return (DRX_STS_INVALID_ARG);
      } /* if */

      width = lastFreq - firstFreq;
      switch ( scanParam->frequencyPlan[i].bandwidth ) {
         case DRX_BANDWIDTH_6MHZ:
            step = DRX_SCAN_6MHZ_STEP;
            break;
         case DRX_BANDWIDTH_7MHZ:
            step = DRX_SCAN_7MHZ_STEP;
            break;
         case DRX_BANDWIDTH_8MHZ:
            step = DRX_SCAN_8MHZ_STEP;
            break;
         default:
            /* Invalid bandwidth parameter in frequency plan */
            commonAttr->scanActive = FALSE;
            return (DRX_STS_INVALID_ARG);
            break;
      }; /* switch */

      if ( (width % step) != 0 )
      {
            /* Difference between last and first centre frequency is not
               an integer number of bandwidths */
            commonAttr->scanActive = FALSE;
            return (DRX_STS_INVALID_ARG);
      } /* if */

      /* Check if frequency plan entry intersects with tuner range */
      if ( lastFreq >= minTunerFreq )
      {
         if ( firstFreq <= maxTunerFreq )
         {
            if (  firstFreq >= minTunerFreq )
            {
               minFreq = firstFreq;
            } else {
               u32_t n=0;

               n=( minTunerFreq - firstFreq )/step;
               if ( (( minTunerFreq - firstFreq )%step) != 0 )
               {
                  n++;
               }
               minFreq = firstFreq + n*step;
            }
            if ( lastFreq <= maxTunerFreq )
            {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -