?? meep6000.c
字號(hào):
* ar6000SetPowerPerRateTable
*
* Sets the transmit power in the baseband for the given
* operating channel and mode.
*/
static void
ar6000SetPowerPerRateTable(A_UINT32 devNum, A_UINT32 freq, A_UINT16 *ratesArray,
A_UINT16 cfgCtl, A_UINT16 AntennaReduction, A_UINT16 powerLimit)
{
LIB_DEV_INFO *pLibDev = gLibInfo.pLibDevArray[devNum];
A_BOOL is2GHz = ((pLibDev->mode == MODE_11G) || (pLibDev->mode == MODE_11B));
A_UINT16 twiceMaxEdgePower = AR6000_MAX_RATE_POWER;
A_UINT16 twiceMaxEdgePowerCck = AR6000_MAX_RATE_POWER;
A_UINT16 twiceMaxRDPower = AR6000_MAX_RATE_POWER;
int i;
A_INT16 twiceAntennaReduction;
CAL_CTL_DATA *rep;
CAL_TARGET_POWER targetPower;
A_INT16 scaledPower;
twiceMaxRDPower = AR6000_MAX_RATE_POWER;
/* Compute TxPower reduction due to Antenna Gain */
twiceAntennaReduction = A_MAX((AntennaReduction * 2) - pLibDev->ar6kEep->modalHeader[is2GHz].antennaGain, 0);
for (i = 0; (i < AR6000_NUM_CTLS) && pLibDev->ar6kEep->ctlIndex[i]; i++) {
A_UINT16 twiceMinEdgePower;
if ((cfgCtl == pLibDev->ar6kEep->ctlIndex[i]) ||
(cfgCtl == ((pLibDev->ar6kEep->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL)))
{
rep = &(pLibDev->ar6kEep->ctlData[i]);
twiceMinEdgePower = ar6000GetMaxEdgePower(freq, rep->ctlEdges, is2GHz);
if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) {
/* Find the minimum of all CTL edge powers that apply to this channel */
twiceMaxEdgePower = A_MIN(twiceMaxEdgePower, twiceMinEdgePower);
} else {
twiceMaxEdgePower = twiceMinEdgePower;
break;
}
}
}
if (pLibDev->mode == MODE_11G) {
/* Check for a CCK CTL for 11G CCK powers */
cfgCtl = (cfgCtl &~ ~CTL_MODE_M) | CTL_11B;
for (i = 0; (i < AR6000_NUM_CTLS) && pLibDev->ar6kEep->ctlIndex[i]; i++) {
A_UINT16 twiceMinEdgePowerCck;
if ((cfgCtl == pLibDev->ar6kEep->ctlIndex[i]) ||
(cfgCtl == ((pLibDev->ar6kEep->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL)))
{
rep = &(pLibDev->ar6kEep->ctlData[i]);
twiceMinEdgePowerCck = ar6000GetMaxEdgePower(freq, rep->ctlEdges, is2GHz);
if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) {
/* Find the minimum of all CTL edge powers that apply to this channel */
twiceMaxEdgePowerCck = A_MIN(twiceMaxEdgePowerCck, twiceMinEdgePowerCck);
} else {
twiceMaxEdgePowerCck = twiceMinEdgePowerCck;
break;
}
}
}
} else {
/* Set the 11B cck edge power to the one found before */
twiceMaxEdgePowerCck = twiceMaxEdgePower;
}
/* Get OFDM target powers */
if (is2GHz) {
ar6000GetTargetPowers(freq, pLibDev->ar6kEep->calTargetPower11G,
AR6000_NUM_11G_TARGET_POWERS, &targetPower, is2GHz);
} else {
ar6000GetTargetPowers(freq, pLibDev->ar6kEep->calTargetPower11A,
AR6000_NUM_11A_TARGET_POWERS, &targetPower, is2GHz);
}
/* Reduce by CTL edge power and regulatory allowable power */
scaledPower = A_MIN(twiceMaxEdgePower, twiceMaxRDPower + twiceAntennaReduction);
/* Apply PER target power restriction */
scaledPower = A_MIN(scaledPower, targetPower.tPow6to24);
/* Reduce power by user set power limit */
scaledPower = A_MIN(scaledPower, powerLimit);
/* Set OFDM rates 9, 12, 18, 24 */
ratesArray[0] = ratesArray[1] = ratesArray[2] = ratesArray[3] = ratesArray[4] = scaledPower;
/* Set OFDM rates 36, 48, 54, XR */
ratesArray[5] = A_MIN(scaledPower, targetPower.tPow36);
ratesArray[6] = A_MIN(scaledPower, targetPower.tPow48);
ratesArray[7] = A_MIN(scaledPower, targetPower.tPow54);
/* XR uses 6mb power */
ratesArray[15] = scaledPower;
if (is2GHz) {
/* Get final CCK target powers */
ar6000GetTargetPowers(freq, pLibDev->ar6kEep->calTargetPower11B,
AR6000_NUM_11B_TARGET_POWERS, &targetPower, is2GHz);
/* Reduce by CTL edge power and regulatory allowable power */
scaledPower = A_MIN(twiceMaxEdgePowerCck, twiceMaxRDPower + twiceAntennaReduction);
/* Apply PER target power restriction */
scaledPower = A_MIN(scaledPower, targetPower.tPow6to24);
/* Reduce power by user set power limit */
scaledPower = A_MIN(scaledPower, powerLimit);
/* Set CCK rates 2L, 2S, 5.5L, 5.5S, 11L, 11S */
ratesArray[8] = scaledPower;
ratesArray[9] = A_MIN(scaledPower, targetPower.tPow36);
ratesArray[10] = ratesArray[9];
ratesArray[11] = A_MIN(scaledPower, targetPower.tPow48);
ratesArray[12] = ratesArray[11];
ratesArray[13] = A_MIN(scaledPower, targetPower.tPow54);
ratesArray[14] = ratesArray[13];
}
return;
}
/**************************************************************
* ar6000GetMaxEdgePower
*
* Find the maximum conformance test limit for the given channel and CTL info
*/
static A_UINT16
ar6000GetMaxEdgePower(A_UINT32 freq, CAL_CTL_EDGES *pRdEdgesPower, A_BOOL is2GHz)
{
A_UINT16 twiceMaxEdgePower = AR6000_MAX_RATE_POWER;
int i;
/* Get the edge power */
for (i = 0; (i < AR6000_NUM_BAND_EDGES) && (pRdEdgesPower[i].bChannel != AR6000_BCHAN_UNUSED) ; i++) {
/*
* If there's an exact channel match or an inband flag set
* on the lower channel use the given rdEdgePower
*/
if (freq == fbin2freq(pRdEdgesPower[i].bChannel, is2GHz)) {
twiceMaxEdgePower = pRdEdgesPower[i].tPower;
break;
} else if ((i > 0) && (freq < fbin2freq(pRdEdgesPower[i].bChannel, is2GHz))) {
if (fbin2freq(pRdEdgesPower[i - 1].bChannel, is2GHz) < freq && pRdEdgesPower[i - 1].flag) {
twiceMaxEdgePower = pRdEdgesPower[i - 1].tPower;
}
/* Leave loop - no more affecting edges possible in this monotonic increasing list */
break;
}
}
assert(twiceMaxEdgePower > 0);
return twiceMaxEdgePower;
}
/**************************************************************
* ar6000GetTargetPowers
*
* Return the four rates of target power for the given target power table
* channel, and number of channels
*/
static void
ar6000GetTargetPowers(A_UINT32 freq, CAL_TARGET_POWER *powInfo,
A_UINT16 numChannels, CAL_TARGET_POWER *pNewPower, A_BOOL is2GHz)
{
int clo, chi;
int i;
int matchIndex = -1, lowIndex = -1;
/* Copy the target powers into the temp channel list */
if (freq <= fbin2freq(powInfo[0].bChannel, is2GHz)) {
matchIndex = 0;
} else {
for (i = 0; (i < numChannels) && (powInfo[i].bChannel != AR6000_BCHAN_UNUSED); i++) {
if (freq == fbin2freq(powInfo[i].bChannel, is2GHz)) {
matchIndex = i;
break;
} else if ((freq < fbin2freq(powInfo[i].bChannel, is2GHz)) &&
(freq > fbin2freq(powInfo[i - 1].bChannel, is2GHz)))
{
lowIndex = i - 1;
break;
}
}
if ((matchIndex == -1) && (lowIndex == -1)) {
assert(freq > fbin2freq(powInfo[i - 1].bChannel, is2GHz));
matchIndex = i - 1;
}
}
if (matchIndex != -1) {
*pNewPower = powInfo[matchIndex];
} else {
assert(lowIndex != -1);
/*
* Get the lower and upper channels, target powers,
* and interpolate between them.
*/
clo = fbin2freq(powInfo[lowIndex].bChannel, is2GHz);
chi = fbin2freq(powInfo[lowIndex + 1].bChannel, is2GHz);
pNewPower->tPow6to24 = interpolate(freq, clo, chi,
powInfo[lowIndex].tPow6to24, powInfo[lowIndex + 1].tPow6to24);
pNewPower->tPow36 = interpolate(freq, clo, chi,
powInfo[lowIndex].tPow36, powInfo[lowIndex + 1].tPow36);
pNewPower->tPow48 = interpolate(freq, clo, chi,
powInfo[lowIndex].tPow48, powInfo[lowIndex + 1].tPow48);
pNewPower->tPow54 = interpolate(freq, clo, chi,
powInfo[lowIndex].tPow54, powInfo[lowIndex + 1].tPow54);
}
}
/**************************************************************
* ar6000SetPowerCalTable
*
* Pull the PDADC piers from cal data and interpolate them across the given
* points as well as from the nearest pier(s) to get a power detector
* linear voltage to power level table.
*/
static void
ar6000SetPowerCalTable(A_UINT32 devNum, A_UINT32 freq, A_INT16 *pTxPowerIndexOffset)
{
LIB_DEV_INFO *pLibDev = gLibInfo.pLibDevArray[devNum];
A_BOOL is2GHz = ((pLibDev->mode == MODE_11G) || (pLibDev->mode == MODE_11B));
CAL_DATA_PER_FREQ *pRawDataset = NULL;
A_UINT8 *pCalBChans = NULL;
A_UINT16 pdGainOverlap_t2;
static A_UINT8 pdadcValues[AR6000_NUM_PDADC_VALUES];
A_UINT16 gainBoundaries[AR6000_PD_GAINS_IN_MASK];
A_UINT16 numPiers;
A_INT16 tMinCalPower;
A_UINT16 numXpdGain, xpdMask;
A_UINT16 xpdGainValues[AR6000_NUM_PD_GAINS];
A_UINT32 i, reg32, regOffset;
if (is2GHz) {
pRawDataset = pLibDev->ar6kEep->calPierData11G;
pCalBChans = pLibDev->ar6kEep->calFreqPier11G;
numPiers = AR6000_NUM_11G_CAL_PIERS;
xpdMask = pLibDev->ar6kEep->modalHeader[1].xpdGain;
} else {
pRawDataset = pLibDev->ar6kEep->calPierData11A;
pCalBChans = pLibDev->ar6kEep->calFreqPier11A;
numPiers = AR6000_NUM_11A_CAL_PIERS;
xpdMask = pLibDev->ar6kEep->modalHeader[0].xpdGain;
}
pdGainOverlap_t2 = REGR(devNum, TPCRG5_REG) & BB_PD_GAIN_OVERLAP_MASK;
numXpdGain = 0;
/* Calculate the value of xpdgains from the xpdGain Mask */
for (i = 1; i <= AR6000_PD_GAINS_IN_MASK; i++) {
if ((xpdMask >> (AR6000_PD_GAINS_IN_MASK - i)) & 1) {
if (numXpdGain >= AR6000_NUM_PD_GAINS) {
assert(0);
break;
}
xpdGainValues[numXpdGain] = AR6000_PD_GAINS_IN_MASK - i;
pLibDev->eepData.xpdGainValues[numXpdGain] = xpdGainValues[numXpdGain];
numXpdGain++;
}
}
pLibDev->eepData.numPdGain = numXpdGain;
ar6000GetGainBoundariesAndPdadcs(devNum, freq, pRawDataset, pCalBChans, numPiers, pdGainOverlap_t2,
&tMinCalPower, gainBoundaries, pdadcValues, xpdGainValues, numXpdGain);
pLibDev->eepData.midPower = gainBoundaries[0];
REGW(devNum, TPCRG1_REG, (REGR(devNum, TPCRG1_REG) & 0xFFFF3FFF) |
(((numXpdGain - 1) & 0x3) << 14));
/*
* Note the pdadc table may not start at 0 dBm power, could be
* negative or greater than 0. Need to offset the power
* values by the amount of minPower for griffin
*/
if (tMinCalPower != 0) {
*pTxPowerIndexOffset = 0 - tMinCalPower;
} else {
*pTxPowerIndexOffset = 0;
}
/* Finally, write the power values into the baseband power table */
regOffset = 0x9800 + (672 << 2); /* beginning of pdadc table in griffin */
for (i = 0; i < 32; i++) {
reg32 = ((pdadcValues[4*i + 0] & 0xFF) << 0) |
((pdadcValues[4*i + 1] & 0xFF) << 8) |
((pdadcValues[4*i + 2] & 0xFF) << 16) |
((pdadcValues[4*i + 3] & 0xFF) << 24) ;
REGW(devNum, regOffset, reg32);
// printf("Snoop: regOffset = %x, regValue = %x\n", regOffset, reg32);
regOffset += 4;
}
REGW(devNum, 0xa26c,
(pdGainOverlap_t2 & 0xf) |
((gainBoundaries[0] & 0x3f) << 4) |
((gainBoundaries[1] & 0x3f) << 10) |
((gainBoundaries[2] & 0x3f) << 16) |
((gainBoundaries[3] & 0x3f) << 22));
// printf("SNOOP: overlap register 0xa26c = %x\n",
// (pdGainOverlap_t2 & 0xf) |
// ((gainBoundaries[0] & 0x3f) << 4) |
// ((gainBoundaries[1] & 0x3f) << 10) |
// ((gainBoundaries[2] & 0x3f) << 16) |
// ((gainBoundaries[3] & 0x3f) << 22));
return;
}
/**************************************************************
* ar6000GetGainBoundariesAndPdadcs
*
* Uses the data points read from EEPROM to reconstruct the pdadc power table
* Called by ar6000SetPowerCalTable only.
*/
static void
ar6000GetGainBoundariesAndPdadcs(A_UINT32 devNum, A_UINT32 freq, CAL_DATA_PER_FREQ * pRawDataSet,
A_UINT8 * bChans, A_UINT16 availPiers,
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -