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

📄 cmx990.c

📁 CMX990 demonstration board (DE9901)
💻 C
📖 第 1 页 / 共 3 页
字号:
}

/******************************************************************************
 * Routine    :  CMX_ReadAdc
 * Description:  Reads the 10-bit value from an ADC in the CMX990.
 ******************************************************************************/
u16 CMX_ReadAdc(AdcSelect_t adcNumber) {
  enum CMX_ControlWordsRead adcRegMsb;
  enum CMX_ControlWordsRead adcRegLsb;
  u16 d;

  switch (adcNumber) {
    case ADC_PA_TEMP_SENSE:
      adcRegMsb = CMX_Adc0Msb;
      adcRegLsb = CMX_Adc0Lsb;
      break;
    case ADC_TEMP_SENSE:
      adcRegMsb = CMX_Adc1Msb;
      adcRegLsb = CMX_Adc1Lsb;
      break;
    case ADC_TX_POW:
      adcRegMsb = CMX_Adc2Msb;
      adcRegLsb = CMX_Adc2Lsb;
      break;
    case ADC_3:
      adcRegMsb = CMX_Adc3Msb;
      adcRegLsb = CMX_Adc3Lsb;
      break;
    case ADC_EXT:
      adcRegMsb = CMX_Adc4Msb;
      adcRegLsb = CMX_Adc4Lsb;
      break;
    case ADC_IN:
      adcRegMsb = CMX_Adc5Msb;
      adcRegLsb = CMX_Adc5Lsb;
      break;
    default:
      CYG_FAIL("Illegal ADC number.");
      break;
  }
  /* We must read MSB first */
  d = ((u16)CMX_Read(adcRegMsb))<<2;
  d |= (u16)CMX_Read(adcRegLsb)&0x03;
  return d;
}

/******************************************************************************
 * Routine    :  CMX_WritePll
 * Description:  Writes a 16 or 24 bits PLL register in the CMX990.
 ******************************************************************************/
void CMX_WritePll(PllSelect_t pllNo, u32 value) {
  enum CMX_ControlWordsWrite reg;

  switch(pllNo) {
    case MAIN_M:
      reg = CMX_MainPllMMsb;
      txLODiv = value & 0x4000;
      PrintEvent("pll mainM=%d", value, 0);
      break;
    case MAIN_N:
      reg = CMX_MainPllNMsb;
      rxIfSummer = value & 0x800000;
      PrintEvent("pll mainN=%d", value, 0);
      cmxWriteRegValue[reg] = (value>>16)&0xFF;
      CMX_MEM_WRITE(((u32)CMX_BASE+(u32)reg), (u8)((value>>16)&0xFF));
      reg--;
      break;
    case AUX_M:
      reg = CMX_AuxPllMMsb;
      txIfFilter = value & 0x6000;
      PrintEvent("pll auxM=%d", value, 0);
      break;
    case AUX_N:
      reg = CMX_AuxPllNMsb;
      txIfDiv = value & 0x8000;
      PrintEvent("pll auxN=%d", value, 0);
      break;
    default:
      CYG_FAIL("Illegal PLL number.");
      break;
  }
  cmxWriteRegValue[reg] = (value>>8)&0xFF;
  CMX_MEM_WRITE(((u32)CMX_BASE+(u32)reg), (u8)((value>>8)&0xFF));
  reg--;
  cmxWriteRegValue[reg] = value&0xFF;
  CMX_MEM_WRITE(((u32)CMX_BASE+(u32)reg), (u8)(value&0xFF));
}

/******************************************************************************
 * Routine    :  CMX_ReadPll
 * Description:  Reads 16 or 24 bits PLL register in the CMX990.
 ******************************************************************************/
u32 CMX_ReadPll(PllSelect_t pllNo) {
  enum CMX_ControlWordsWrite reg;
  u32 value;

  switch(pllNo) {
    case MAIN_M:
      reg = CMX_MainPllMMsb;
      break;
    case MAIN_N:
      reg = CMX_MainPllNMsb;
      break;
    case AUX_M:
      reg = CMX_AuxPllMMsb;
      break;
    case AUX_N:
      reg = CMX_AuxPllNMsb;
      break;
    default:
      CYG_FAIL("Illegal PLL number.");
      break;
  }
  DISABLE_INTERRUPTS(); {
#if 0
    CMX_MEM_WRITE(CMX_HW_TESTACCESS_2, CMX_HW_SWAP_IO | CMX_HW_TRIM);
    value = (u32)CMX_MEM_READ(((u32)CMX_BASE+(u32)reg));
    reg--;
    value = (value << 8) | (u32)CMX_MEM_READ((u32)CMX_BASE+(u32)reg);
    if (pllNo == MAIN_N) {
      /* Read one more register for MAIN_N */
      reg--;
      value = (value << 8) | (u32)CMX_MEM_READ((u32)CMX_BASE+(u32)reg);
    }
    CMX_MEM_WRITE(CMX_HW_TESTACCESS_2, CMX_HW_TRIM);
#else
    value = (u32)cmxWriteRegValue[reg];
    reg--;
    value = (value << 8) | (u32)cmxWriteRegValue[reg];
    if (pllNo == MAIN_N) {
      /* Read one more register for MAIN_N */
      reg--;
      value = (value << 8) | (u32)cmxWriteRegValue[reg];
    }
#endif
  } ENABLE_INTERRUPTS();
  return value;
}

/******************************************************************************
 * Routine    :  CMX_SetLNA
 * Description:  Sets the LNA on and off.
 ******************************************************************************/
static void CMX_SetLNA(bool state) {
  u8 reg;
  reg = CMX_ReadWriteReg(CMX_PowerUp2, TRUE) & (0xFF - CMX_LNA);
  if (state) {
    CMX_Write(CMX_PowerUp2, (reg | CMX_LNA));
  } else {
    CMX_Write(CMX_PowerUp2, reg);
  }
}

/******************************************************************************
 * Routine    :  CMX_GetPrbsStat
 * Description:  Returns the current PRBS statistics.
 ******************************************************************************/
void CMX_GetPrbsStat(CMX_PrbsStatistics_t *prbs) {
  *prbs = prbsData;
}

/******************************************************************************
 * Routine    :  CMX_ResetPrbs
 * Description:  Resets the PRBS statistics.
 ******************************************************************************/
void CMX_ResetPrbs(void) {
  prbsData.totalNoBits = 0;
  prbsData.errorNoBits = 0;
}

/******************************************************************************
 * Routine    :  CMX_ResetPrbsRx
 * Description:  Resets the PRBS rx register.
 ******************************************************************************/
static void CMX_ResetPrbsRx(void) {
  prbsRxRegister = 0x01ff;
}

/******************************************************************************
 * Routine    :  CMX_GetNextPrbsRxBit
 * Description:  Calculates and returns the next bit in the PRBS.
 ******************************************************************************/
static u16 CMX_GetNextPrbsRxBit(void) {
  u16 bit9, bit5;
  bit9 = prbsRxRegister & 1;
  bit5 = (prbsRxRegister >> 4) & 1;
  prbsRxRegister = (prbsRxRegister >> 1) | ((bit9^bit5) << 8);
  return bit9;
}

/******************************************************************************
 * Routine    :  CMX_UpdateRxPll
 * Description:  Sets the PLL for rxFreq.
 ******************************************************************************/
static void CMX_UpdateRxPll(void) {
  CMX_WritePll(AUX_N, ((rxAuxFreq/auxStep) | txIfDiv));
  CMX_WritePll(AUX_M, (refClk/auxStep) | txIfFilter | CMX_PLL_ENABLE);
  CMX_WritePll(MAIN_N, ((rxFreq+rxIf*(rxIfSummer == CMX_RX_IF_SUMMER_POS ? 1 : -1))/mainStep) | rxIfSummer | txVcoCharge);
  CMX_WritePll(MAIN_M, (refClk/mainStep) | txLODiv | txMixFilter | CMX_PLL_ENABLE);
}

/******************************************************************************
 * Routine    :  CMX_UpdateTxPll
 * Description:  Sets the PLL for txFreq.
 ******************************************************************************/
static void CMX_UpdateTxPll(void) {
  CMX_WritePll(AUX_N, ((txAuxFreq/auxStep) | txIfDiv));
  CMX_WritePll(AUX_M, (refClk/auxStep) | txIfFilter | CMX_PLL_ENABLE);
  CMX_WritePll(MAIN_N, (((txFreq+txIf*(txIfHighSide ? 1 : -1))/mainStep)/(txLODiv == CMX_TX_LO_DIV2 ? 1 : 2)) | txSlope);
  CMX_WritePll(MAIN_M, (refClk/mainStep) | txLODiv | txMixFilter | CMX_PLL_ENABLE);
}

/******************************************************************************
 * Routine    :  CMX_SetRxFreq
 * Description:  Sets the frequency used for RX.
 ******************************************************************************/
void CMX_SetRxFreq(s32 freq) {
  CYG_ASSERT(freq >= minRxFreq && freq <= maxRxFreq, "RX frequency is out of band");
  rxFreq = freq;
  if (rxActive) {
    /* Rx is active and we shall change the PLL now. */
    CMX_UpdateRxPll();
  }
}
s32 CMX_GetRxFreq(void) {
  return rxFreq;
}

/******************************************************************************
 * Routine    :  CMX_SetTxFreq
 * Description:  Sets the frequency used for TX.
 ******************************************************************************/
void CMX_SetTxFreq(s32 freq) {
  CYG_ASSERT(freq >= minTxFreq && freq <= maxTxFreq, "TX frequency is out of band");
  txFreq = freq;
  if (txActive) {
    /* Tx is active and we shall change the PLL now. */
    CMX_UpdateTxPll();
  }
}
s32 CMX_GetTxFreq(void) {
  return txFreq;
}

/******************************************************************************
 * Routine    :  CMX_RxActive
 * Description:  Turns the receiver on and off.
 ******************************************************************************/
void CMX_RxActive(bool state, bool minSet) {
  u8 reg;

  if (txActive) {
    CMX_TxActive(FALSE, minSet);
  }
  if (state) {
    if (rxActive == FALSE) {
      /* Turn Rx on */
      //BINIO_SetPort(BINIO_VRX_ON, BINIO_HIGH);
      //BINIO_SetPort(BINIO_RX_ON, BINIO_HIGH);
      CMX_UpdateRxPll();
      CMX_SetLNA(TRUE);
      if (minSet == FALSE) {
        reg = CMX_ReadWriteReg(CMX_Mode, TRUE) & (CMX_IRQEN | CMX_INVBIT | CMX_PLL_IRQEN | CMX_DQ_IRQEN);
        reg |= (CMX_SCREN | CMX_ADC_EN);
        CMX_Write(CMX_Mode, reg);
        reg = CMX_ReadWriteReg(CMX_PowerUp1, TRUE) & (CMX_CLOCK | CMX_BASEBAND | CMX_VREG | CMX_OP12);
        reg |= (CMX_RXIF | CMX_RXRF1 | CMX_RXRF2);
        CMX_Write(CMX_PowerUp1, reg);
      }
    }
    if (cmxWorkingMode != CMX_ModeIdle) {
      CMX_WriteCmd(CMX_RXTASK_RESET);
    }
    HAL_DELAY_US(250); // Wait 2 bit times to stabilize the RX signal.
    cmxWorkingMode = CMX_ModeAquireChannel;
    CMX_WriteCmd(CMX_AQIQ);
  } else {
    /* Turn Rx off */
    CMX_WriteCmd(CMX_RXTASK_RESET);
    CMX_SetLNA(FALSE);
    //BINIO_SetPort(BINIO_VRX_ON, BINIO_LOW);
    //BINIO_SetPort(BINIO_RX_ON, BINIO_LOW);
    if (minSet == FALSE) {
      // Leave TxRxN in current state.
      reg = CMX_ReadWriteReg(CMX_Mode, TRUE) & (CMX_TXRXN | CMX_IRQEN | CMX_INVBIT | CMX_PLL_IRQEN | CMX_DQ_IRQEN);
      CMX_Write(CMX_Mode, reg);
      reg = CMX_ReadWriteReg(CMX_PowerUp1, TRUE) & (CMX_CLOCK | CMX_BASEBAND | CMX_VREG | CMX_OP12);
      CMX_Write(CMX_PowerUp1, reg);
    }
    cmxWorkingMode = CMX_ModeIdle;
  }
  rxActive = state;
}

/******************************************************************************
 * Routine    :  CMX_TxActive
 * Description:  Turns the transmitter on and off.
 ******************************************************************************/
void CMX_TxActive(bool state, bool minSet) {
  u8 reg;
  if (rxActive) {
    CMX_RxActive(FALSE, minSet);
  }
  if (state) {
    /* Turn Tx on, we don't use a power ramp in this test application. */
    BINIO_SetPort(BINIO_TX_ON, BINIO_HIGH);
    //BINIO_SetPort(BINIO_VTX_ON, BINIO_HIGH);
    if (CMX_ReadDac(VREF_PA) == 0) {
      CMX_WriteDac(VREF_PA, 1023); /* Set max power to PA, approx. 0.5 W */
    }
    cyg_thread_delay(5);
    if (minSet == FALSE) {
      reg = CMX_ReadWriteReg(CMX_Mode, TRUE) & (CMX_IRQEN | CMX_INVBIT | CMX_PLL_IRQEN | CMX_DQ_IRQEN);
      reg |= (CMX_TXRXN | CMX_DAC_EN | CMX_SCREN);
      CMX_Write(CMX_Mode, reg);
      reg = CMX_ReadWriteReg(CMX_PowerUp1, TRUE) & (CMX_CLOCK | CMX_BASEBAND | CMX_VREG | CMX_OP12);
      reg |= CMX_TXRFIF;
      CMX_Write(CMX_PowerUp1, reg);
      CMX_Write(CMX_AnalogSetup1W, CMX_TX_ATT_10DB | 32);
    }
    CMX_UpdateTxPll();
    cmxWorkingMode = CMX_ModeTxPrbs;
    CMX_WriteCmd(CMX_TXTASK_TSO);
  } else {
    /* Turn Tx off, we don't use a power ramp in this test application. */
    CMX_WriteCmd(CMX_TXTASK_RESET);
    if (CMX_ReadDac(VREF_PA) == 1023) {
      CMX_WriteDac(VREF_PA, 0); /* Set min power to PA */
    }
    //BINIO_SetPort(BINIO_VTX_ON, BINIO_LOW);
    BINIO_SetPort(BINIO_TX_ON, BINIO_LOW);
    if (minSet == FALSE) {
      reg = CMX_ReadWriteReg(CMX_Mode, TRUE) & (CMX_IRQEN | CMX_INVBIT | CMX_PLL_IRQEN | CMX_DQ_IRQEN);
      CMX_Write(CMX_Mode, reg);
      reg = CMX_ReadWriteReg(CMX_PowerUp1, TRUE) & (CMX_CLOCK | CMX_BASEBAND | CMX_VREG | CMX_OP12);
      CMX_Write(CMX_PowerUp1, reg);
    }
    CMX_UpdateRxPll();
    cmxWorkingMode = CMX_ModeIdle;
  }
  txActive = state;
}

/******************************************************************************
 * Routine    :  CMX_Isr
 * Description:  
 * Handles the CMX interrupt. The actual handling is done in the DSR.
 * The ISR reads the status bytes.
 * For each interrupt we call the DSR ones.
 * The buffer used is 2 bytes long, alternating for each interrupt run.
 * If buffer overflow occur, we have a problem.
 * The interrupt from CMX990 is coming to fast for the system to handle them in
 * the DSR. Report this error and disable the interrupts in the CMX990 mode register.
 ******************************************************************************/
static u8 status1Isr[2], status2Isr[2];
static int statusIndexIsr = 0;
static int cmxIsrCount = 0;
static int cmxIsrOverrun = 0;
cyg_uint32 CMX_Isr(cyg_vector_t vector, cyg_addrword_t data) {

  status1Isr[statusIndexIsr] = CMX_Read(CMX_Status1);
  status2Isr[statusIndexIsr] = CMX_Read(CMX_Status2);
  cyg_drv_interrupt_acknowledge(vector);

  if (cmxWorkingMode == CMX_ModeRxPrbs) {
    /* Handle RX prbs here to avoid timing conflict with the serial port drivers. */
    if ((status1Isr[statusIndexIsr] & CMX_BFREE) && expectBFREE) {
      int currentErrors;
      u8 prbsByte;
      s32 i;
      CMX_GetDataBlock(&prbsByte, 1);
      CMX_WriteCmd(CMX_RXTASK_RSB);
      /* Get prbs byte and check bit errors */
      prbsData.totalNoBits += 8;
      currentErrors = 0;
      prbsRecSeq = ((prbsRecSeq << 8) & 0xFFFFFF00) | (u32)prbsByte;
      for (i=7; i>=0; i--) {
        if ((((u16)prbsByte >> i)&1) != CMX_GetNextPrbsRxBit()) {
          prbsData.errorNoBits++;
          currentErrors++;
        }
      }
      // We don't need to run the DSR now since we have handled the RX prbs here.
      return (CYG_ISR_HANDLED);
    }
  }
  statusIndexIsr = 1 - statusIndexIsr;
  if (cmxIsrCount > 0) {
    cmxIsrOverrun = 1;
    // Disable IRQ in mode register
    cmxWriteRegValue[CMX_Mode] = cmxWriteRegValue[CMX_Mode] & 0x7f;
    CMX_MEM_WRITE(CMX_MODE, cmxWriteRegValue[CMX_Mode]);
    if (cmxIsrCount > 1) {
      /* We still get interrupts even if IRQ is disabled in mode register. */
      /* Disable CMX interrupt in the ARM processor. */
      cyg_drv_interrupt_mask(vector);
      cmxIsrOverrun  = 2;
    }
  }
  cmxIsrCount++;
  return (CYG_ISR_CALL_DSR);
}

/******************************************************************************
 * Routine    :  CMX_Dsr
 * Description:  DSR for processing interrupts from the CMX.
 ******************************************************************************/
static void CMX_Dsr(cyg_vector_t vector, cyg_ucount32 dsrCount, cyg_addrword_t dsrData) {
  static int statusIndexDsr = 0; // This index shows which byte has been read in the ISR.
  u8 status1, status2;
  u8 prbsByte;
  static u8 lastStatus1 = 0, lastStatus2 = 0;
  static u32 limitStatusPrint = 0;

⌨️ 快捷键说明

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