📄 maui_cal.c
字号:
A_UINT16 numExtrema, numTotalExtrema ;
A_UINT16 *extrema ;
A_UINT16 ii, jj;
numTotalExtrema = 0;
extrema = (A_UINT16 *)malloc(pDataset->numChannels * sizeof(A_UINT16)) ;
if (extrema == NULL)
{
uiPrintf("Could not allocate memory for extrema. Exiting...\n");
exit(0);
}
for (ii=0; ii<pDataset->pDataPerChannel[0].numPcdacValues; ii++)
{
pick_local_extrema(pDerivDataset, ii, extrema, &(numExtrema)) ; // numExtrema stores the number of extrema found
for (jj=0; jj<numExtrema; jj++)
{
addUniqueElementToList(TPlist, extrema[jj], &(numTotalExtrema));
}
}
*totalTPs = numTotalExtrema ;
qsort( (void *) TPlist, numTotalExtrema, sizeof(A_UINT16), numerical_compare) ;
free(extrema);
}
void addUniqueElementToList(A_UINT16 *list, A_UINT16 element, A_UINT16 *listSize)
{
A_UINT16 ii = 0;
A_BOOL isUnique = TRUE;
A_UINT16 size = *listSize ;
while ((ii<size) && (isUnique))
{
if (element == list[ii])
{
isUnique = FALSE;
}
ii++;
}
if (isUnique)
{
list[size] = element ;
(*listSize) = size + 1 ;
}
}
int numerical_compare( const void *arg1, const void *arg2 )
{
A_INT16 comparison = 0;
A_UINT16 val1 = * ( A_UINT16 * ) arg1;
A_UINT16 val2 = * ( A_UINT16 * ) arg2;
if (val1 > val2)
comparison = 1;
if (val1 < val2)
comparison = -1;
return ( comparison );
}
void pick_local_extrema(dPCDACS_EEPROM *pDataset, A_UINT16 pcd_idx, A_UINT16 *retList, A_UINT16 *listSize)
{
A_UINT16 ii;
A_INT16 flatRunStartDirection, dirxn, newDirexn, midPoint ;
A_UINT16 *flatRun ;
A_UINT16 sizeFlatRun =0;
A_UINT16 ch0, ch1, chN;
double noise;
double delta;
A_UINT16 numTPs = 0;
flatRun = (A_UINT16*)malloc(pDataset->numChannels * sizeof(A_UINT16)) ;
if (flatRun == NULL)
{
uiPrintf("Could not allocate memory for list flatRun. Exiting...\n");
exit(0);
}
ch0 = pDataset->pChannels[0];
ch1 = pDataset->pChannels[1];
chN = pDataset->pChannels[pDataset->numChannels-1];
// noise calculated to ignore a change in slope causing a 1dB deviation over entire range
// an adjustment factor of 10 seems to work better for a 30MHz measurement step
noise = fabs(1.0/(10*(ch1-ch0)*(chN-ch0))) ;
retList[numTPs] = ch0;
numTPs++;
flatRunStartDirection = 0; // implicitly indicates out of flatrun
delta = (pDataset->pDataPerChannel[1].pPwrValues[pcd_idx] - pDataset->pDataPerChannel[0].pPwrValues[pcd_idx]) ;
newDirexn = (delta >= 0) ? 1 : -1 ;
for (ii=1; ii<(pDataset->numChannels-1); ii++)
{
dirxn = newDirexn;
newDirexn = 0;
delta = (pDataset->pDataPerChannel[ii+1].pPwrValues[pcd_idx] - pDataset->pDataPerChannel[ii].pPwrValues[pcd_idx]) ;
if (delta > 2*noise)
{
newDirexn = 1;
}
if (-delta > 2*noise)
{
newDirexn = -1;
}
if (abs(newDirexn - dirxn) < 1) // that is, no change in direction
{
if (abs(dirxn) < 1) // start populating flatRun
{
flatRun[sizeFlatRun] = ii ;
sizeFlatRun++;
}
continue;
}
if (abs(newDirexn - dirxn) > 1) // a reversal in direction
{
// pick only the NON-ZERO extrema
if (fabs(pDataset->pDataPerChannel[ii].pPwrValues[pcd_idx]) > noise)
{
retList[numTPs] = pDataset->pChannels[ii];
numTPs++;
}
continue;
}
// at this point, either starting a flatrun or ending one
if (abs(newDirexn) < 1) // implies start of a flatrun
{
flatRunStartDirection = newDirexn;
flatRun[sizeFlatRun] = ii ;
sizeFlatRun++;
continue ;
}
if (abs(dirxn) < 1) // implies end of a flatrun
{
midPoint = flatRun[(A_UINT16)(sizeFlatRun-1)/2] ;
if ((abs(newDirexn-flatRunStartDirection) > 1) && // pick only extrema, not plateaus
(fabs(pDataset->pDataPerChannel[midPoint].pPwrValues[pcd_idx]) > noise)) // only non-zero extrema
{
retList[numTPs] = pDataset->pChannels[ii];
numTPs++;
}
flatRunStartDirection = 0 ;
sizeFlatRun = 0; // effectively clears the list flatRun
}
}
retList[numTPs] = pDataset->pChannels[pDataset->numChannels-1];
numTPs++;
*listSize = numTPs;
free(flatRun);
}
void consolidate_turning_points(A_UINT16 **tpList, A_UINT16 *sizeList, A_UINT16 debug)
{
A_UINT16 *newList;
A_UINT16 sizeNewList = 0;
A_UINT16 binSize = 40;
A_UINT16 ii;
newList = (A_UINT16 *)malloc(numRAWChannels * sizeof(A_UINT16));
if (newList == NULL)
{
uiPrintf("Could not allocate newList to consolidate turning points. Exiting...\n");
exit(0);
}
newList[0] = (*tpList)[0] ;
sizeNewList++;
for (ii=1; ii<*sizeList-2; ii++)
{
if ( ((*tpList)[ii] - newList[sizeNewList-1]) > binSize)
{
newList[sizeNewList] = (*tpList)[ii];
sizeNewList++;
}
}
if ( ( ((*tpList)[*sizeList-2] - newList[sizeNewList-1]) > binSize) &&
( ((*tpList)[*sizeList-1] - (*tpList)[*sizeList-2]) > binSize) )
{
newList[sizeNewList] = (*tpList)[*sizeList-2];
sizeNewList++;
}
newList[sizeNewList] = (*tpList)[*sizeList-1];
sizeNewList++;
// free the memory associated with the old list that had all the TPs
free( (void *) (*tpList));
// point the allTP list to the consolidated list
(*tpList) = newList ;
*sizeList = sizeNewList ;
}
void build_turningpoint_totempole(dPCDACS_EEPROM *pDataset, TP_VAL **totempole, A_UINT16 sizeTotempole, A_UINT16 *tpList, A_UINT16 debug)
{
A_INT16 ii, jj;
double avg, cost;
A_UINT16 left, right;
(*totempole) = (TP_VAL *)malloc(sizeTotempole * sizeof(TP_VAL)) ;
if ((*totempole) == NULL)
{
uiPrintf("Could not allocate memory for the totempole. Exiting...\n");
exit(0);
}
jj = 0;
for (ii=0; ii<pDataset->numChannels; ii++)
{
if (tpList[jj] == pDataset->pChannels[ii])
{
(*totempole)[jj].channel_idx = ii ;
jj++ ;
}
}
if (jj != sizeTotempole)
{
uiPrintf("Bad juju happened in assigning totempole. jj=%d, numTPs=%d. Exiting...\n",jj, sizeTotempole);
exit(0);
}
for (ii=1; ii<(sizeTotempole-1); ii++)
{
cost = 0.0;
left = pRawDataset->pChannels[(*totempole)[ii].channel_idx] -
pRawDataset->pChannels[(*totempole)[ii-1].channel_idx];
right= pRawDataset->pChannels[(*totempole)[ii+1].channel_idx] -
pRawDataset->pChannels[(*totempole)[ii].channel_idx];
for (jj=0; jj<pDataset->pDataPerChannel[0].numPcdacValues; jj++)
{
avg = (double) (right*pDataset->pDataPerChannel[(*totempole)[ii-1].channel_idx].pPwrValues[jj] +
left*pDataset->pDataPerChannel[(*totempole)[ii+1].channel_idx].pPwrValues[jj])/(left+right) ;
cost += fabs(pDataset->pDataPerChannel[(*totempole)[ii].channel_idx].pPwrValues[jj] - avg);
}
(*totempole)[ii].val = cost ;
if(debug > 0)
{
uiPrintf("Impact of TP#%d at %d = %2.1f.\n", ii, pDataset->pChannels[(*totempole)[ii].channel_idx], (*totempole)[ii].val);
}
}
//guarantee inclusion of 1st and last TP
(*totempole)[0].val = 9999.0;
(*totempole)[sizeTotempole-1].val = 9999.0;
}
int totempole_compare( const void *arg1, const void *arg2 )
{
A_INT16 comparison = 0;
TP_VAL tp1 = * ( TP_VAL * ) arg1;
TP_VAL tp2 = * ( TP_VAL * ) arg2;
if ( tp1.val> tp2.val )
comparison = -1;
if ( tp1.val < tp2.val )
comparison = 1;
return ( comparison ); // for descending qsort of totempole
}
void dMapGrid(dPCDACS_EEPROM *pSrcStruct, dPCDACS_EEPROM *pDestStruct)
{
dDATA_PER_CHANNEL *pChannelData;
A_UINT16 *pPcdacValue;
double *pPwrValue;
A_UINT16 i, j;
A_UINT16 channel, pcdac;
pChannelData = pDestStruct->pDataPerChannel;
for(i = 0; i < pDestStruct->numChannels; i++ ) {
pPcdacValue = pChannelData->pPcdacValues;
pPwrValue = pChannelData->pPwrValues;
for(j = 0; j < pChannelData->numPcdacValues; j++ ) {
channel = pChannelData->channelValue;
pcdac = *pPcdacValue;
*pPwrValue = getPowerAt(channel, pcdac, pSrcStruct);
pPcdacValue++;
pPwrValue++;
}
pChannelData++;
}
}
double getPowerAt( A_UINT16 channel, A_UINT16 pcdacValue, dPCDACS_EEPROM *pSrcStruct)
{
double powerValue;
A_UINT16 lFreq, rFreq; //left and right frequency values
A_UINT16 llPcdac, ulPcdac; //lower and upper left pcdac values
A_UINT16 lrPcdac, urPcdac; //lower and upper right pcdac values
double lPwr, uPwr; //lower and upper temp pwr values
double lScaledPwr, rScaledPwr; //left and right scaled power
if(dFindValueInList(channel, pcdacValue, pSrcStruct, &powerValue)){
//value was copied from srcStruct
return(powerValue);
}
dGetLeftRightChannels(channel, pSrcStruct, &lFreq, &rFreq);
dGetLowerUpperPcdacs(pcdacValue, lFreq, pSrcStruct, &llPcdac, &ulPcdac);
dGetLowerUpperPcdacs(pcdacValue, rFreq, pSrcStruct, &lrPcdac, &urPcdac);
//get the power index for the pcdac value
dFindValueInList(lFreq, llPcdac, pSrcStruct, &lPwr);
dFindValueInList(lFreq, ulPcdac, pSrcStruct, &uPwr);
lScaledPwr = dGetInterpolatedValue( pcdacValue, llPcdac, ulPcdac, lPwr, uPwr);
dFindValueInList(rFreq, lrPcdac, pSrcStruct, &lPwr);
dFindValueInList(rFreq, urPcdac, pSrcStruct, &uPwr);
rScaledPwr = dGetInterpolatedValue( pcdacValue, lrPcdac, urPcdac, lPwr, uPwr);
return(dGetInterpolatedValue( channel, lFreq, rFreq, lScaledPwr, rScaledPwr));
}
// the "double" returning version of findValueInList that works with scaled integer values
A_BOOL dFindValueInList( A_UINT16 channel, A_UINT16 pcdacValue, dPCDACS_EEPROM *pSrcStruct, double *powerValue)
{
dDATA_PER_CHANNEL *pChannelData;
A_UINT16 *pPcdac;
A_UINT16 i, j;
pChannelData = pSrcStruct->pDataPerChannel;
for(i = 0; i < pSrcStruct->numChannels; i++ ) {
if (pChannelData->channelValue == channel) {
pPcdac = pChannelData->pPcdacValues;
for(j = 0; j < pChannelData->numPcdacValues; j++ ) {
if (*pPcdac == pcdacValue) {
*powerValue = pChannelData->pPwrValues[j];
return(1);
}
pPcdac++;
}
}
pChannelData++;
}
return(0);
}
// only searches for integer values in integer lists. used for channel and pcdac lists
void iGetLowerUpperValues
(
A_UINT16 value, //value to search for
A_UINT16 *pList, //ptr to the list to search
A_UINT16 listSize, //number of entries in list
A_UINT16 *pLowerValue, //return the lower value
A_UINT16 *pUpperValue //return the upper value
)
{
A_UINT16 i;
A_UINT16 listEndValue = *(pList + listSize - 1);
A_UINT16 target = value ;
//see if value is lower than the first value in the list
//if so return first value
if (target <= (*pList)) {
*pLowerValue = *pList;
*pUpperValue = *pList;
return;
}
//see if value is greater than last value in list
//if so return last value
if (target >= listEndValue) {
*pLowerValue = listEndValue;
*pUpperValue = listEndValue;
return;
}
//look for value being near or between 2 values in list
for(i = 0; i < listSize; 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) {
*pLowerValu
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -