📄 ar5112.c
字号:
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(u_int16_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(u_int16_t target, u_int16_t srcLeft, u_int16_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(u_int16_t v, u_int16_t *lp, u_int16_t listSize, u_int32_t *vlo, u_int32_t *vhi){ u_int32_t target = v; u_int16_t *ep = lp+listSize; u_int16_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(u_int16_t numPcdacs, u_int16_t *pcdacs, int16_t *power, int16_t maxPower, int16_t *retVals){ u_int16_t ii; u_int16_t idxL = 0; u_int16_t idxR = 1; if (numPcdacs < 2) { HALDEBUG(AH_NULL, "%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, u_int16_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, u_int16_t retVals[], int16_t *pMid){ int16_t ii, jj, jjMax; int16_t pMin, pMax, currPower; int16_t *pwrTableT4; u_int16_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;}/* * Free memory for analog bank scratch buffers */static voidar5112Detach(struct ath_hal *ah){ struct ath_hal_5212 *ahp = AH5212(ah); if (ahp->ah_pcdacTable != AH_NULL) { ath_hal_free(ahp->ah_pcdacTable); ahp->ah_pcdacTable = AH_NULL; } if (ahp->ah_analogBanks != AH_NULL) { ath_hal_free(ahp->ah_analogBanks); ahp->ah_analogBanks = AH_NULL; }}static int16_tar5112GetMinPower(struct ath_hal *ah, 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){ struct ath_hal_5212 *ahp = (struct ath_hal_5212 *) ah; int numChannels=0,i,last; int totalD, totalF,totalMin; EXPN_DATA_PER_CHANNEL_5112 *data=AH_NULL; EEPROM_POWER_EXPN_5112 *powerArray=AH_NULL; *maxPow = 0; if (IS_CHAN_A(chan)) { powerArray = ahp->ah_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 = ahp->ah_modePowerArray5112; data = powerArray[headerInfo11G].pDataPerChannel; numChannels = powerArray[headerInfo11G].numChannels; } else if (IS_CHAN_B(chan)) { powerArray = ahp->ah_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); }} static HAL_BOOLar5112GetChipPowerLimits(struct ath_hal *ah, HAL_CHANNEL *chans, u_int32_t nchans){ HAL_BOOL retVal = AH_TRUE; int i; int16_t maxPow,minPow; for (i=0; i<nchans; i++) { if (ar5112GetChannelMaxMinPower(ah, &chans[i], &maxPow, &minPow)) { /* XXX -Need to adjust pcdac values to indicate dBm */ chans[i].maxTxPower = maxPow; chans[i].minTxPower = minPow; } else { HALDEBUG(ah, "Failed setting power table for nchans=%d\n",i); retVal= AH_FALSE; } }#ifdef AH_DEBUG for (i=0; i<nchans; i++) { ath_hal_printf(ah,"Chan %d: MaxPow = %d MinPow = %d\n", chans[i].channel,chans[i].maxTxPower, chans[i].minTxPower); }#endif return (retVal);}/* * Allocate memory for analog bank scratch buffers * Scratch Buffer will be reinitialized every reset so no need to zero now */HAL_BOOLar5112RfAttach(struct ath_hal *ah, HAL_STATUS *status){ struct ath_hal_5212 *ahp = AH5212(ah); HALASSERT(ahp->ah_analogBanks == AH_NULL); ahp->ah_analogBanks = ath_hal_malloc(sizeof(AR5212_RF_BANKS_5112)); if (ahp->ah_analogBanks == AH_NULL) { ath_hal_printf(ah, "%s: cannot allocate RF banks\n", __func__); *status = HAL_ENOMEM; /* XXX */ return AH_FALSE; } HALASSERT(ahp->ah_pcdacTable == AH_NULL); ahp->ah_pcdacTableSize = PWR_TABLE_SIZE * sizeof(u_int16_t); ahp->ah_pcdacTable = ath_hal_malloc(ahp->ah_pcdacTableSize); if (ahp->ah_pcdacTable == AH_NULL) { ath_hal_printf(ah, "%s: cannot allocate PCDAC table\n", __func__); *status = HAL_ENOMEM; /* XXX */ return AH_FALSE; } ahp->ah_pcdacTableSize = PWR_TABLE_SIZE; ahp->ah_rfHal.rfDetach = ar5112Detach; ahp->ah_rfHal.writeRegs = ar5112WriteRegs; ahp->ah_rfHal.getRfBank = ar5112GetRfBank; ahp->ah_rfHal.setChannel = ar5112SetChannel; ahp->ah_rfHal.setRfRegs = ar5112SetRfRegs; ahp->ah_rfHal.setPowerTable = ar5112SetPowerTable; ahp->ah_rfHal.getChipPowerLim = ar5112GetChipPowerLimits; return AH_TRUE;}#endif /* AH_SUPPORT_5112 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -