📄 cmx990.c
字号:
}
/******************************************************************************
* 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 + -