?? meep6000.c
字號:
A_UINT16 tPdGainOverlap, A_INT16 *pMinCalPower, A_UINT16 * pPdGainBoundaries,
A_UINT8 * pPDADCValues, A_UINT16 * xpdGainValues, A_UINT16 numXpdGains)
{
LIB_DEV_INFO *pLibDev = gLibInfo.pLibDevArray[devNum];
A_BOOL is2GHz = ((pLibDev->mode == MODE_11G) || (pLibDev->mode == MODE_11B));
int i, j, k;
A_INT16 ss; /* potentially -ve index for taking care of pdGainOverlap */
A_UINT16 idxL, idxR, numPiers; /* Pier indexes */
/* filled out Vpd table for all pdGains (chanL) */
static A_UINT8 vpdTableL[AR6000_NUM_PD_GAINS][AR6000_MAX_PWR_RANGE_IN_HALF_DB];
/* filled out Vpd table for all pdGains (chanR) */
static A_UINT8 vpdTableR[AR6000_NUM_PD_GAINS][AR6000_MAX_PWR_RANGE_IN_HALF_DB];
/* filled out Vpd table for all pdGains (interpolated) */
static A_UINT8 vpdTableI[AR6000_NUM_PD_GAINS][AR6000_MAX_PWR_RANGE_IN_HALF_DB];
A_UINT8 *pVpdL, *pVpdR, *pPwrL, *pPwrR;
A_UINT8 minPwrT4[AR6000_NUM_PD_GAINS];
A_UINT8 maxPwrT4[AR6000_NUM_PD_GAINS];
A_UINT16 numVpd = 0;
A_INT16 vpdStep;
A_INT16 tmpVal;
A_UINT16 sizeCurrVpdTable, maxIndex, tgtIndex;
A_BOOL match;
/* Trim numPiers for the number of populated channel Piers */
for (numPiers = 0; numPiers < availPiers; numPiers++) {
if (bChans[numPiers] == AR6000_BCHAN_UNUSED) {
break;
}
}
/* Find pier indexes around the current channel */
match = getLowerUpperIndex(FREQ2FBIN(freq, is2GHz), bChans,
numPiers, &idxL, &idxR);
if (match) {
/* Directly fill both vpd tables from the matching index */
minPwrT4[0] = pRawDataSet[idxL].pwrPdg0[0];
minPwrT4[1] = pRawDataSet[idxL].pwrPdg1[0];
maxPwrT4[0] = pRawDataSet[idxL].pwrPdg0[3];
maxPwrT4[1] = pRawDataSet[idxL].pwrPdg1[4];
ar6000FillVpdTable(minPwrT4[0], maxPwrT4[0], pRawDataSet[idxL].pwrPdg0,
pRawDataSet[idxL].vpdPdg0, 4, vpdTableI[0]);
ar6000FillVpdTable(minPwrT4[1], maxPwrT4[1], pRawDataSet[idxL].pwrPdg1,
pRawDataSet[idxL].vpdPdg1, 5, vpdTableI[1]);
} else {
for (i = 0; i < numXpdGains; i++) {
if (i == 0) {
numVpd = 4;
pVpdL = pRawDataSet[idxL].vpdPdg0;
pPwrL = pRawDataSet[idxL].pwrPdg0;
pVpdR = pRawDataSet[idxR].vpdPdg0;
pPwrR = pRawDataSet[idxR].pwrPdg0;
} else {
numVpd = 5;
pVpdL = pRawDataSet[idxL].vpdPdg1;
pPwrL = pRawDataSet[idxL].pwrPdg1;
pVpdR = pRawDataSet[idxR].vpdPdg1;
pPwrR = pRawDataSet[idxR].pwrPdg1;
}
/* Start Vpd interpolation from the max of the minimum powers */
minPwrT4[i] = A_MAX(pPwrL[0], pPwrR[0]);
/* End Vpd interpolation from the min of the max powers */
maxPwrT4[i] = A_MIN(pPwrL[numVpd - 1], pPwrR[numVpd - 1]);
assert(maxPwrT4[i] > minPwrT4[i]);
/* Fill pier Vpds */
ar6000FillVpdTable(minPwrT4[i], maxPwrT4[i], pPwrL, pVpdL, numVpd, vpdTableL[i]);
ar6000FillVpdTable(minPwrT4[i], maxPwrT4[i], pPwrR, pVpdR, numVpd, vpdTableR[i]);
/* Interpolate the final vpd */
for (j = 0; j < (maxPwrT4[i] - minPwrT4[i]) / 2; j++) {
vpdTableI[i][j] = interpolate(FREQ2FBIN(freq, is2GHz), bChans[idxL],
bChans[idxR], vpdTableL[i][j], vpdTableR[i][j]);
}
}
}
*pMinCalPower = minPwrT4[0] / 2;
k = 0; /* index for the final table */
for (i = 0; i < numXpdGains; i++) {
if (i == (numXpdGains - 1)) {
pPdGainBoundaries[i] = maxPwrT4[i] / 2;
} else {
pPdGainBoundaries[i] = ((maxPwrT4[i] + minPwrT4[i+1]) / 4 );
}
pPdGainBoundaries[i] = A_MIN(63, pPdGainBoundaries[i]);
/* Find starting index for this pdGain */
if (i == 0) {
ss = 0; /* for the first pdGain, start from index 0 */
} else {
ss = (pPdGainBoundaries[i-1] - (minPwrT4[i] / 2)) - tPdGainOverlap + 1;
}
vpdStep = (vpdTableI[i][1] - vpdTableI[i][0]);
vpdStep = ((vpdStep < 1) ? 1 : vpdStep);
/*
*-ve ss indicates need to extrapolate data below for this pdGain
*/
while ((ss < 0) && (k < (AR6000_NUM_PDADC_VALUES - 1))) {
tmpVal = (vpdTableI[i][0] + ss * vpdStep);
pPDADCValues[k++] = ((tmpVal < 0) ? 0 : tmpVal);
ss++;
}
sizeCurrVpdTable = (maxPwrT4[i] - minPwrT4[i]) / 2;
tgtIndex = pPdGainBoundaries[i] + tPdGainOverlap - (minPwrT4[i] / 2);
maxIndex = (tgtIndex < sizeCurrVpdTable) ? tgtIndex : sizeCurrVpdTable;
while ((ss < maxIndex) && (k < (AR6000_NUM_PDADC_VALUES - 1))) {
pPDADCValues[k++] = vpdTableI[i][ss++];
}
vpdStep = (vpdTableI[i][sizeCurrVpdTable - 1] - vpdTableI[i][sizeCurrVpdTable - 2]);
vpdStep = ((vpdStep < 1) ? 1 : vpdStep);
/*
* for last gain, pdGainBoundary == Pmax_t2, so will
* have to extrapolate
*/
if (tgtIndex > maxIndex) { /* need to extrapolate above */
while ((ss <= tgtIndex) && (k < (AR6000_NUM_PDADC_VALUES - 1))) {
tmpVal = (vpdTableI[i][sizeCurrVpdTable - 1] +
(ss - maxIndex) * vpdStep);
pPDADCValues[k++] = (tmpVal > 255) ? 255 : tmpVal;
ss++;
}
} /* extrapolated above */
} /* for all pdGainUsed */
/* Fill out pdGainBoundaries - only up to 2 allowed here, but hardware allows up to 4 */
while (i < AR6000_PD_GAINS_IN_MASK) {
pPdGainBoundaries[i] = pPdGainBoundaries[i-1];
i++;
}
while (k < AR6000_NUM_PDADC_VALUES) {
pPDADCValues[k] = pPDADCValues[k-1];
k++;
}
return;
}
/**************************************************************
* getLowerUppderIndex
*
* Return indices surrounding the value in sorted integer lists.
* Requirement: the input list must be monotonically increasing
* and populated up to the list size
* Returns: match is set if an index in the array matches exactly
* or a the target is before or after the range of the array.
*/
static A_BOOL
getLowerUpperIndex(A_UINT8 target, A_UINT8 *pList, A_UINT16 listSize,
A_UINT16 *indexL, A_UINT16 *indexR)
{
A_UINT16 i;
/*
* Check first and last elements for beyond ordered array cases.
*/
if (target <= pList[0]) {
*indexL = *indexR = 0;
return TRUE;
}
if (target >= pList[listSize-1]) {
*indexL = *indexR = listSize - 1;
return TRUE;
}
/* look for value being near or between 2 values in list */
for (i = 0; i < listSize - 1; i++) {
/*
* If value is close to the current value of the list
* then target is not between values, it is one of the values
*/
if (pList[i] == target) {
*indexL = *indexR = i;
return TRUE;
}
/*
* Look for value being between current value and next value
* if so return these 2 values
*/
if (target < pList[i + 1]) {
*indexL = i;
*indexR = i + 1;
return FALSE;
}
}
assert(0);
return FALSE;
}
/**************************************************************
* ar6000FillVpdTable
*
* Fill the Vpdlist for indices Pmax-Pmin
* Note: pwrMin, pwrMax and Vpdlist are all in dBm * 4
*/
static A_BOOL
ar6000FillVpdTable(A_UINT8 pwrMin, A_UINT8 pwrMax, A_UINT8 *pPwrList,
A_UINT8 *pVpdList, A_UINT16 numIntercepts, A_UINT8 *pRetVpdList)
{
A_UINT16 i, k;
A_UINT8 currPwr = pwrMin;
A_UINT16 idxL, idxR;
assert(pwrMax > pwrMin);
for (i = 0; i <= (pwrMax - pwrMin) / 2; i++) {
getLowerUpperIndex(currPwr, pPwrList, numIntercepts,
&(idxL), &(idxR));
if (idxR < 1)
idxR = 1; /* extrapolate below */
if (idxL == numIntercepts - 1)
idxL = numIntercepts - 2; /* extrapolate above */
if (pPwrList[idxL] == pPwrList[idxR])
k = pVpdList[idxL];
else
k = ( ((currPwr - pPwrList[idxL]) * pVpdList[idxR] + (pPwrList[idxR] - currPwr) * pVpdList[idxL]) /
(pPwrList[idxR] - pPwrList[idxL]) );
assert(k < 256);
pRetVpdList[i] = (A_UINT8)k;
currPwr += 2; /* half dB steps */
}
return TRUE;
}
/**************************************************************************
* interpolate
*
* Returns signed interpolated or the scaled up interpolated value
*/
static A_INT16
interpolate(A_UINT16 target, A_UINT16 srcLeft, A_UINT16 srcRight,
A_INT16 targetLeft, A_INT16 targetRight)
{
A_INT16 rv;
if (srcRight == srcLeft) {
rv = targetLeft;
} else {
rv = ((target - srcLeft) * targetRight +
(srcRight - target) * targetLeft) / (srcRight - srcLeft);
}
return rv;
}
/**************************************************************************
* fbin2freq
*
* Get channel value from binary representation held in eeprom
* RETURNS: the frequency in MHz
*/
static A_UINT16
fbin2freq(A_UINT8 fbin, A_BOOL is2GHz)
{
/*
* Reserved value 0xFF provides an empty definition both as
* an fbin and as a frequency - do not convert
*/
if (fbin == AR6000_BCHAN_UNUSED) {
return fbin;
}
return ((is2GHz) ? (2300 + fbin) : (4800 + 5 * fbin));
}
void getAR6000Struct(
A_UINT32 devNum,
void **ppReturnStruct, //return ptr to struct asked for
A_UINT32 *pNumBytes //return the size of the structure
)
{
LIB_DEV_INFO *pLibDev = gLibInfo.pLibDevArray[devNum];
*ppReturnStruct = pLibDev->ar6kEep;
*pNumBytes = sizeof(AR6K_EEPROM);
return;
}
void
ar6000GetPowerPerRateTable(A_UINT32 devNum, A_UINT16 freq, A_INT16 *pRatesPower)
{
LIB_DEV_INFO *pLibDev = gLibInfo.pLibDevArray[devNum];
A_UINT16 cfgCtl = pLibDev->ar6kEep->baseEepHeader.regDmn & 0xFF;
A_UINT16 twiceAntennaReduction = (cfgCtl = 0x10) ? 6 : 0;
A_UINT16 powerLimit = AR6000_MAX_RATE_POWER;
switch (pLibDev->mode) {
case MODE_11A:
cfgCtl |= CTL_11A;
break;
case MODE_11G:
case MODE_11O:
cfgCtl |= CTL_11G;
break;
case MODE_11B:
cfgCtl |= CTL_11B;
break;
default:
assert(0);
}
assert(pRatesPower);
ar6000SetPowerPerRateTable(devNum, freq, (A_UINT16 *)pRatesPower, cfgCtl, twiceAntennaReduction, powerLimit);
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -