📄 ar5112.c
字号:
numPcd*sizeof(uint16_t)); OS_MEMCPY(&powers[0], &pRawCh->pDataPerXPD[jj].pwr_t4[0], numPcd*sizeof(int16_t)); if (!getFullPwrTable(numPcd, &pcdacs[0], &powers[0], pRawCh->maxPower_t4, &tmpPowerTable[0])) { return AH_FALSE; } OS_MEMCPY(&powTableLXPD[kk][0], &tmpPowerTable[0], 64 * sizeof(int16_t)); jj = xgainList[1]; numPcd = pRawCh->pDataPerXPD[jj].numPcdacs; OS_MEMCPY(&pcdacs[0], &pRawCh->pDataPerXPD[jj].pcdac[0], numPcd * sizeof(uint16_t)); OS_MEMCPY(&powers[0], &pRawCh->pDataPerXPD[jj].pwr_t4[0], numPcd * sizeof(int16_t)); if (!getFullPwrTable(numPcd, &pcdacs[0], &powers[0], pRawCh->maxPower_t4, &tmpPowerTable[0])) { return AH_FALSE; } OS_MEMCPY(&powTableHXPD[kk][0], &tmpPowerTable[0], 64 * sizeof(int16_t)); } kk++; } chan_L = pPowerExpn->pChannels[chan_idx_L]; chan_R = pPowerExpn->pChannels[chan_idx_R]; kk = chan_idx_R - chan_idx_L; if (xgainList[1] == 0xDEAD) { for (jj = 0; jj < 64; jj++) { pwr_table0[jj] = interpolate_signed( chan->channel, chan_L, chan_R, powTableLXPD[0][jj], powTableLXPD[kk][jj]); } Pmin = getPminAndPcdacTableFromPowerTable(&pwr_table0[0], ahp->ah_pcdacTable); *pPowerMin = (int16_t) (Pmin / 2); *pPowerMid = (int16_t) (pwr_table0[63] / 2); *pPowerMax = (int16_t) (pwr_table0[63] / 2); rfXpdGain[0] = xgainList[0]; rfXpdGain[1] = rfXpdGain[0]; } else { for (jj = 0; jj < 64; jj++) { pwr_table0[jj] = interpolate_signed( chan->channel, chan_L, chan_R, powTableLXPD[0][jj], powTableLXPD[kk][jj]); pwr_table1[jj] = interpolate_signed( chan->channel, chan_L, chan_R, powTableHXPD[0][jj], powTableHXPD[kk][jj]); } if (numXpdGain == 2) { Pmin = getPminAndPcdacTableFromTwoPowerTables( &pwr_table0[0], &pwr_table1[0], ahp->ah_pcdacTable, &Pmid); *pPowerMin = (int16_t) (Pmin / 2); *pPowerMid = (int16_t) (Pmid / 2); *pPowerMax = (int16_t) (pwr_table0[63] / 2); rfXpdGain[0] = xgainList[0]; rfXpdGain[1] = xgainList[1]; } else if (minPwr_t4 <= pwr_table1[63] && maxPwr_t4 <= pwr_table1[63]) { Pmin = getPminAndPcdacTableFromPowerTable( &pwr_table1[0], ahp->ah_pcdacTable); rfXpdGain[0] = xgainList[1]; rfXpdGain[1] = rfXpdGain[0]; *pPowerMin = (int16_t) (Pmin / 2); *pPowerMid = (int16_t) (pwr_table1[63] / 2); *pPowerMax = (int16_t) (pwr_table1[63] / 2); } else { Pmin = getPminAndPcdacTableFromPowerTable( &pwr_table0[0], ahp->ah_pcdacTable); rfXpdGain[0] = xgainList[0]; rfXpdGain[1] = rfXpdGain[0]; *pPowerMin = (int16_t) (Pmin/2); *pPowerMid = (int16_t) (pwr_table0[63] / 2); *pPowerMax = (int16_t) (pwr_table0[63] / 2); } } /* * Move 5112 rates to match power tables where the max * power table entry corresponds with maxPower. */ HALASSERT(*pPowerMax <= PCDAC_STOP); ahp->ah_txPowerIndexOffset = PCDAC_STOP - *pPowerMax; return AH_TRUE;}/* * Returns interpolated or the scaled up interpolated value */static int16_tinterpolate_signed(uint16_t target, uint16_t srcLeft, uint16_t srcRight, int16_t targetLeft, int16_t targetRight){ int16_t rv; if (srcRight != srcLeft) { rv = ((target - srcLeft)*targetRight + (srcRight - target)*targetLeft) / (srcRight - srcLeft); } else { rv = targetLeft; } return rv;}/* * Return indices surrounding the value in sorted integer lists. * * NB: the input list is assumed to be sorted in ascending order */static voidar5212GetLowerUpperIndex(uint16_t v, uint16_t *lp, uint16_t listSize, uint32_t *vlo, uint32_t *vhi){ uint32_t target = v; uint16_t *ep = lp+listSize; uint16_t *tp; /* * Check first and last elements for out-of-bounds conditions. */ if (target < lp[0]) { *vlo = *vhi = 0; return; } if (target >= ep[-1]) { *vlo = *vhi = listSize - 1; return; } /* look for value being near or between 2 values in list */ for (tp = lp; tp < ep; tp++) { /* * If value is close to the current value of the list * then target is not between values, it is one of the values */ if (*tp == target) { *vlo = *vhi = tp - lp; return; } /* * Look for value being between current value and next value * if so return these 2 values */ if (target < tp[1]) { *vlo = tp - lp; *vhi = *vlo + 1; return; } }}static HAL_BOOLgetFullPwrTable(uint16_t numPcdacs, uint16_t *pcdacs, int16_t *power, int16_t maxPower, int16_t *retVals){ uint16_t ii; uint16_t idxL = 0; uint16_t idxR = 1; if (numPcdacs < 2) { HALDEBUG(AH_NULL, HAL_DEBUG_ANY, "%s: at least 2 pcdac values needed [%d]\n", __func__, numPcdacs); return AH_FALSE; } for (ii = 0; ii < 64; ii++) { if (ii>pcdacs[idxR] && idxR < numPcdacs-1) { idxL++; idxR++; } retVals[ii] = interpolate_signed(ii, pcdacs[idxL], pcdacs[idxR], power[idxL], power[idxR]); if (retVals[ii] >= maxPower) { while (ii < 64) retVals[ii++] = maxPower; } } return AH_TRUE;}/* * Takes a single calibration curve and creates a power table. * Adjusts the new power table so the max power is relative * to the maximum index in the power table. * * WARNING: rates must be adjusted for this relative power table */static int16_tgetPminAndPcdacTableFromPowerTable(int16_t *pwrTableT4, uint16_t retVals[]){ int16_t ii, jj, jjMax; int16_t pMin, currPower, pMax; /* If the spread is > 31.5dB, keep the upper 31.5dB range */ if ((pwrTableT4[63] - pwrTableT4[0]) > 126) { pMin = pwrTableT4[63] - 126; } else { pMin = pwrTableT4[0]; } pMax = pwrTableT4[63]; jjMax = 63; /* Search for highest pcdac 0.25dB below maxPower */ while ((pwrTableT4[jjMax] > (pMax - 1) ) && (jjMax >= 0)) { jjMax--; } jj = jjMax; currPower = pMax; for (ii = 63; ii >= 0; ii--) { while ((jj < 64) && (jj > 0) && (pwrTableT4[jj] >= currPower)) { jj--; } if (jj == 0) { while (ii >= 0) { retVals[ii] = retVals[ii + 1]; ii--; } break; } retVals[ii] = jj; currPower -= 2; // corresponds to a 0.5dB step } return pMin;}/* * Combines the XPD curves from two calibration sets into a single * power table and adjusts the power table so the max power is relative * to the maximum index in the power table * * WARNING: rates must be adjusted for this relative power table */static int16_tgetPminAndPcdacTableFromTwoPowerTables(int16_t *pwrTableLXpdT4, int16_t *pwrTableHXpdT4, uint16_t retVals[], int16_t *pMid){ int16_t ii, jj, jjMax; int16_t pMin, pMax, currPower; int16_t *pwrTableT4; uint16_t msbFlag = 0x40; // turns on the 7th bit of the pcdac /* If the spread is > 31.5dB, keep the upper 31.5dB range */ if ((pwrTableLXpdT4[63] - pwrTableHXpdT4[0]) > 126) { pMin = pwrTableLXpdT4[63] - 126; } else { pMin = pwrTableHXpdT4[0]; } pMax = pwrTableLXpdT4[63]; jjMax = 63; /* Search for highest pcdac 0.25dB below maxPower */ while ((pwrTableLXpdT4[jjMax] > (pMax - 1) ) && (jjMax >= 0)){ jjMax--; } *pMid = pwrTableHXpdT4[63]; jj = jjMax; ii = 63; currPower = pMax; pwrTableT4 = &(pwrTableLXpdT4[0]); while (ii >= 0) { if ((currPower <= *pMid) || ( (jj == 0) && (msbFlag == 0x40))){ msbFlag = 0x00; pwrTableT4 = &(pwrTableHXpdT4[0]); jj = 63; } while ((jj > 0) && (pwrTableT4[jj] >= currPower)) { jj--; } if ((jj == 0) && (msbFlag == 0x00)) { while (ii >= 0) { retVals[ii] = retVals[ii+1]; ii--; } break; } retVals[ii] = jj | msbFlag; currPower -= 2; // corresponds to a 0.5dB step ii--; } return pMin;}static int16_tar5112GetMinPower(struct ath_hal *ah, const EXPN_DATA_PER_CHANNEL_5112 *data){ int i, minIndex; int16_t minGain,minPwr,minPcdac,retVal; /* Assume NUM_POINTS_XPD0 > 0 */ minGain = data->pDataPerXPD[0].xpd_gain; for (minIndex=0,i=1; i<NUM_XPD_PER_CHANNEL; i++) { if (data->pDataPerXPD[i].xpd_gain < minGain) { minIndex = i; minGain = data->pDataPerXPD[i].xpd_gain; } } minPwr = data->pDataPerXPD[minIndex].pwr_t4[0]; minPcdac = data->pDataPerXPD[minIndex].pcdac[0]; for (i=1; i<NUM_POINTS_XPD0; i++) { if (data->pDataPerXPD[minIndex].pwr_t4[i] < minPwr) { minPwr = data->pDataPerXPD[minIndex].pwr_t4[i]; minPcdac = data->pDataPerXPD[minIndex].pcdac[i]; } } retVal = minPwr - (minPcdac*2); return(retVal);} static HAL_BOOLar5112GetChannelMaxMinPower(struct ath_hal *ah, HAL_CHANNEL *chan, int16_t *maxPow, int16_t *minPow){ const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; int numChannels=0,i,last; int totalD, totalF,totalMin; const EXPN_DATA_PER_CHANNEL_5112 *data=AH_NULL; const EEPROM_POWER_EXPN_5112 *powerArray=AH_NULL; *maxPow = 0; if (IS_CHAN_A(chan)) { powerArray = ee->ee_modePowerArray5112; data = powerArray[headerInfo11A].pDataPerChannel; numChannels = powerArray[headerInfo11A].numChannels; } else if (IS_CHAN_G(chan) || IS_CHAN_108G(chan)) { /* XXX - is this correct? Should we also use the same power for turbo G? */ powerArray = ee->ee_modePowerArray5112; data = powerArray[headerInfo11G].pDataPerChannel; numChannels = powerArray[headerInfo11G].numChannels; } else if (IS_CHAN_B(chan)) { powerArray = ee->ee_modePowerArray5112; data = powerArray[headerInfo11B].pDataPerChannel; numChannels = powerArray[headerInfo11B].numChannels; } else { return (AH_TRUE); } /* Make sure the channel is in the range of the TP values * (freq piers) */ if (numChannels < 1) return(AH_FALSE); if ((chan->channel < data[0].channelValue) || (chan->channel > data[numChannels-1].channelValue)) { if (chan->channel < data[0].channelValue) { *maxPow = data[0].maxPower_t4; *minPow = ar5112GetMinPower(ah, &data[0]); return(AH_TRUE); } else { *maxPow = data[numChannels - 1].maxPower_t4; *minPow = ar5112GetMinPower(ah, &data[numChannels - 1]); return(AH_TRUE); } } /* Linearly interpolate the power value now */ for (last=0,i=0; (i<numChannels) && (chan->channel > data[i].channelValue); last=i++); totalD = data[i].channelValue - data[last].channelValue; if (totalD > 0) { totalF = data[i].maxPower_t4 - data[last].maxPower_t4; *maxPow = (int8_t) ((totalF*(chan->channel-data[last].channelValue) + data[last].maxPower_t4*totalD)/totalD); totalMin = ar5112GetMinPower(ah,&data[i]) - ar5112GetMinPower(ah, &data[last]); *minPow = (int8_t) ((totalMin*(chan->channel-data[last].channelValue) + ar5112GetMinPower(ah, &data[last])*totalD)/totalD); return (AH_TRUE); } else { if (chan->channel == data[i].channelValue) { *maxPow = data[i].maxPower_t4; *minPow = ar5112GetMinPower(ah, &data[i]); return(AH_TRUE); } else return(AH_FALSE); }}/* * Free memory for analog bank scratch buffers */static voidar5112RfDetach(struct ath_hal *ah){ struct ath_hal_5212 *ahp = AH5212(ah); HALASSERT(ahp->ah_rfHal != AH_NULL); ath_hal_free(ahp->ah_rfHal); ahp->ah_rfHal = AH_NULL;}/* * Allocate memory for analog bank scratch buffers * Scratch Buffer will be reinitialized every reset so no need to zero now */static HAL_BOOLar5112RfAttach(struct ath_hal *ah, HAL_STATUS *status){ struct ath_hal_5212 *ahp = AH5212(ah); struct ar5112State *priv; HALASSERT(ah->ah_magic == AR5212_MAGIC); HALASSERT(ahp->ah_rfHal == AH_NULL); priv = ath_hal_malloc(sizeof(struct ar5112State)); if (priv == AH_NULL) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: cannot allocate private state\n", __func__); *status = HAL_ENOMEM; /* XXX */ return AH_FALSE; } priv->base.rfDetach = ar5112RfDetach; priv->base.writeRegs = ar5112WriteRegs; priv->base.getRfBank = ar5112GetRfBank; priv->base.setChannel = ar5112SetChannel; priv->base.setRfRegs = ar5112SetRfRegs; priv->base.setPowerTable = ar5112SetPowerTable; priv->base.getChannelMaxMinPower = ar5112GetChannelMaxMinPower; priv->base.getNfAdjust = ar5212GetNfAdjust; ahp->ah_pcdacTable = priv->pcdacTable; ahp->ah_pcdacTableSize = sizeof(priv->pcdacTable); ahp->ah_rfHal = &priv->base; return AH_TRUE;}static HAL_BOOLar5112Probe(struct ath_hal *ah){ return IS_RAD5112(ah);}AH_RF(RF5112, ar5112Probe, ar5112RfAttach);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -