?? cal_inf_apc_1.cpp
字號:
// cal_inf_apc_1.cpp
// calibrate the Infineon chipset automatic power control
// n steffen
// April 4, 2000
//
// April 18, 2000
// Changed interpolation and extrapolation to round rather than truncate
//
// September 18, 2000
// Changed tolerance to a variable - lower powers now only need to be within 1
// dB of target.
// Detect cycles while determining DAC value for each peak power
//
//
//------------- new method for searching for power - do a binary search like in
//------------- Diana. Old method suffers from too much sensitivity and doesn't
//------------- converge on sensitive phones.
//
// October 31, 2000
// added user parameters for ramp length, up and down delta, and pedestal
//
// February 5, 2001
// Reduce pedestal by 8 for power levels >= 9
// Reduce first value in ramp down by 1 dB for any peak power > 31 dBm
//
// February 9, 2001
// Increase DCS pedestal by 8 for power levels >=9
// Replaced 8 with PEDESTAL_DELTA
//
// February 15, 2001
// Replaced PEDESTAL_DELTA with separate DCS and GSM values
// DSC_PEDESTAL_DELTA set to 0 (for now)
//
#include <math.h>
#include "error.h"
#include "caltypes.h"
#include "HS.h"
#include "measure.h"
#include "cal_class.h"
#include "ramp_status.h"
#include "UIapi.h"
#define GSM_STARTING_RAMP_INDEX 3
#define GSM_ENDING_RAMP_INDEX 17
#define DCS_STARTING_RAMP_INDEX 3
#define DCS_ENDING_RAMP_INDEX 18
#define PCS_STARTING_RAMP_INDEX 3
#define PCS_ENDING_RAMP_INDEX 18
#define GSM850_STARTING_RAMP_INDEX 3
#define GSM850_ENDING_RAMP_INDEX 17
#define RAMP_TABLE_SIZE 19
#define NUMBER_OF_RAMP_POINTS 16
#define GSM_LOWEST_POWER (-79)
#define GSM_LOWEST_PEAK_DAC 0
#define DCS_LOWEST_POWER (-79)
#define DCS_LOWEST_PEAK_DAC 0
#define MIN_DAC (0x10)
#define DELTA 68
#define PI 3.1415926
#define MAX_TX_TRIALS 32
#define HIGH_POWER_TOLERANCE (0.5)
#define LOW_POWER_TOLERANCE (1.0)
#define MAX_INFINEON_PEDESTAL_TRIALS 32
#define NUMBER_OF_DAC_CODES 1024
#define UNUSED_DAC 1000.0
#define SEARCH_DOWN 1
#define SEARCH_UP 0
#define COARSE_PEDESTAL_STEP 5
#define FINE_PEDESTAL_STEP 1
#define GSM_TRIAL_PEDESTAL 0x58
#define DCS_TRIAL_PEDESTAL 0x58
#define PCS_TRIAL_PEDESTAL 0x58
#define GSM850_TRIAL_PEDESTAL 0x58
unsigned interpolate(float target_y,unsigned *x,float *y,unsigned number,Error_t *stat);
unsigned extrapolate(float target_y,unsigned *x,float *y,unsigned number,Error_t *stat);
void build_trial_ramp(unsigned ramp[32],float peak,unsigned band,unsigned pedestal);
float get_expected_power(float power[NUMBER_OF_DAC_CODES],unsigned index);
unsigned get_dac_value(float power[NUMBER_OF_DAC_CODES],float target_pwr);
Error_t build_infineon_trial_ramp(unsigned ramp[32],
float peak_power,
int up_length,int up_delta,
int down_length,int down_delta,
int pedestal,
unsigned number_of_points,unsigned x[RAMP_TABLE_SIZE+1],float measured[RAMP_TABLE_SIZE+1]);
// these are the power levels as a function of the tx ramp index, NOT the tx power level
// gsm ramp index 0 maps to GSM power levels 0-2
// gsm ramp index 1 maps to GSM power level 3
// gsm ramp index 2 maps to GSM power level 4
// gsm ramp index 3 maps to GSM power level 5 - the first "real" level
// ...
// gsm ramp index 16 maps to GSM power level 18
// gsm ramp index 17 maps to GSM power levels 19-31 - 19 is the last "real" level
//
// dcs ramp index 0 maps to
// dcs ramp index 1 maps to
// dcs ramp index 2 maps to
// dcs ramp index 3 maps to DCS power level 0 (29.5 dBm)
// dcs ramp index 4 maps to DCS power level 1 (28 dBm)
// ...
// dcs ramp index 17 maps to DCS power level 14 (2 dBm)
// dcs ramp index 18 maps to DCS power level 15 (0 dBm)
// PCS will use the DCS entries
// target values
static float TargetTxPwr[4][RAMP_TABLE_SIZE]=
{ //0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 //index
// 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 //GSM level
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 //DCS level
{32.5, 32.5, 32.5, 32.5, 31, 29, 27, 25, 23, 21, 19, 17, 15, 13, 11, 9, 7, 5, 5}, //GSM
{29.5, 29.5, 29.5, 29.5, 28, 26, 24, 22, 20, 18, 16, 14, 12, 10, 8, 6, 4, 2, 0}, //DCS
{29.5, 29.5, 29.5, 29.5, 27.5, 26, 24, 22, 20, 18, 16, 14, 12, 10, 8, 6, 4, 2, 0},
{32.5, 32.5, 32.5, 32.5, 30.5, 29, 27, 25, 23, 21, 19, 17, 15, 13, 11, 9, 7, 5, 5}
};
static const float gain[RAMP_TABLE_SIZE]=
//0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 //index
{20.0, 20.0, 20.0, 20.0, 10.0, 10.0, 5.0, 5.0, 5.0, 5.0, 2.0, 2.0,2.0,1.0,1.0,1.0,1.0,1.0,1.0}; //GSM
static const unsigned canonical_gsm_ramp[32]=
{
0x007a, 0x0086, 0x0094, 0x00a4, 0x00b5, 0x00c6, 0x00d6, 0x00eb,
0x0117, 0x0162, 0x01c6, 0x023c, 0x0266, 0x0266, 0x0266, 0x0266,
0x023c, 0x01c6, 0x0162, 0x0117, 0x00eb, 0x00d6, 0x00c6, 0x00b5,
0x00a4, 0x0094, 0x0086, 0x007a, 0x0071, 0x006c, 0x006b, 0x0010
};
static const unsigned canonical_dcs_ramp[32]=
{
112,114,116,120,125,137,164,225,329,486,709,897,961,961,961,961,
861,592,352,210,144,123,112,102,87, 73, 63, 56, 54, 54, 54, 54};
static const unsigned canonical_pcs_ramp[32]=
{
112,114,116,120,125,137,164,225,329,486,709,897,961,961,961,961,
861,592,352,210,144,123,112,102,87, 73, 63, 56, 54, 54, 54, 54};
static const unsigned canonical_gsm850_ramp[32]=
{
0x007a, 0x0086, 0x0094, 0x00a4, 0x00b5, 0x00c6, 0x00d6, 0x00eb,
0x0117, 0x0162, 0x01c6, 0x023c, 0x0266, 0x0266, 0x0266, 0x0266,
0x023c, 0x01c6, 0x0162, 0x0117, 0x00eb, 0x00d6, 0x00c6, 0x00b5,
0x00a4, 0x0094, 0x0086, 0x007a, 0x0071, 0x006c, 0x006b, 0x0010
};
Error_t cal::CalInfineonAPC(float coarse_tx_delta,
unsigned *current_peak_dac,
unsigned ramp_table[NUMBER_OF_RAMP_POINTS][2*RAMP_TABLE_SIZE],
float highest_power,
int *ramp_up_length,
int *ramp_down_length,
int *ramp_up_delta,
int *ramp_down_delta,
float *ramp_pedestal_slope,
float *ramp_pedestal_power,
float lowest_power,float next_lowest_power,
float lowest_slope,float next_lowest_slope)
{
float measured[RAMP_TABLE_SIZE+1]; // dependent variable (measured Tx power)
unsigned x[RAMP_TABLE_SIZE+1]; // independent variable (Peak DAC value)
unsigned i,j,z;
Error_t error;
unsigned stat;
unsigned number_of_points;
float expected_power;
float power;
unsigned dac_code;
unsigned prev_dac_code;
double factor;
double old_factor;
unsigned min_power_too_large;
unsigned trial_ramp[32];
float msrd;
float peak;
unsigned num_trials;
float error_scale;
unsigned upper_limit;
unsigned lower_limit;
unsigned hard_upper_limit;
unsigned hard_lower_limit;
int up_delta;
int down_delta;
int up_length;
int down_length;
int offset;
float pedestal_slope;
float pedestal_power;
int search;
unsigned pedestal_done;
unsigned count;
float power_table[NUMBER_OF_DAC_CODES];
float ref_table[NUMBER_OF_DAC_CODES];
unsigned low_power_pedestal;
unsigned high_power_pedestal;
unsigned num_msmnt_pts;
struct limit_msmnt m[3]; // size this for DCS, which measures 3 points for pedestal
unsigned too_low;
unsigned too_high;
unsigned pedestal_step;
int initial_up_length;
int current_ramp;
for(i=0;i<RAMP_TABLE_SIZE+1;i++)
{
measured[i]=0;
x[i]=0;
}
if(band==GSM)
{
hard_lower_limit=0x140;
hard_upper_limit=0x3ff;
// first, find DAC value that gives highest power
TargetTxPwr[GSM][0]=TargetTxPwr[GSM][1]=TargetTxPwr[GSM][2]=
TargetTxPwr[GSM][3]=highest_power;
peak=(float)canonical_gsm_ramp[15];
i=GSM_STARTING_RAMP_INDEX;
error_scale=gain[i];
cal_hs.HS_SetTxLev(i);
// Handset needs a while to monitor current received signal power value
Sleep(300);
expected_power=TargetTxPwr[band][i] + coarse_tx_delta;
// get measured values
build_trial_ramp(trial_ramp,peak,band,GSM_TRIAL_PEDESTAL);
cal_hs.HS_SetRamp(trial_ramp);
Sleep(100);
stat=cal_measure.GetTxPower(expected_power,&msrd,expected_power>15.0);
if(stat==FALSE)
{
return POWER_ERROR;
}
num_trials=0;
// initialize the power table
for(z=0;z<NUMBER_OF_DAC_CODES;z++)
{
power_table[z]=UNUSED_DAC; // mark all locations as being unused so far
ref_table[z]=UNUSED_DAC; // mark all locations as being unused so far
}
// adjust peak DAC value to get correct power
while(fabs(msrd-TargetTxPwr[band][i])>0.5 && num_trials<MAX_TX_TRIALS)
{
peak+=error_scale*(TargetTxPwr[band][i]-msrd);
if(peak>0x3ff || peak<0)
{
return APC_DAC_CODE_TOO_LARGE;
}
build_trial_ramp(trial_ramp,peak,band,GSM_TRIAL_PEDESTAL);
cal_hs.HS_SetRamp(trial_ramp);
cal_hs.HS_SetStop();
cal_hs.HS_SetStart();
Sleep(200);
stat=cal_measure.GetTxPower(expected_power,&msrd,expected_power>15.0);
ref_table[(unsigned)(peak+0.5)]=msrd;
if(stat!=FALSE)
power_table[(unsigned)(peak+0.5)]=msrd;
if(stat==FALSE || msrd<(TargetTxPwr[band][18]-2.0))
return POWER_ERROR;
num_trials++;
}
if(num_trials==MAX_TX_TRIALS)
return TOO_MANY_TX_TRIALS;
measured[i-GSM_STARTING_RAMP_INDEX]=msrd;
x[i-GSM_STARTING_RAMP_INDEX]=(unsigned)(peak+0.5);
// put the high power value in
power_table[(unsigned)(peak+0.5)]=msrd;
hard_upper_limit=(unsigned)(peak+0.5);
// now have the highest power and its DAC value
// do binary search for other powers. The limits will be adjusted dynamically
peak=peak-50.0; // move away from highest power
build_trial_ramp(trial_ramp,peak,band,GSM_TRIAL_PEDESTAL);
cal_hs.HS_SetRamp(trial_ramp);
cal_hs.HS_SetStop();
cal_hs.HS_SetStart();
Sleep(200);
stat=cal_measure.GetTxPower(expected_power,&msrd,SEARCH_DOWN);
for(i=GSM_STARTING_RAMP_INDEX+1;i<=GSM_ENDING_RAMP_INDEX;i++)
{
expected_power=TargetTxPwr[band][i] + coarse_tx_delta;
upper_limit=(unsigned)(peak+0.5); // start from old upper limit
lower_limit=hard_lower_limit;
num_trials=0;
search=0;
build_trial_ramp(trial_ramp,peak,band,GSM_TRIAL_PEDESTAL);
cal_hs.HS_SetRamp(trial_ramp);
cal_hs.HS_SetStop();
cal_hs.HS_SetStart();
Sleep(100);
stat=cal_measure.GetTxPower(expected_power,&msrd);
for(z=hard_upper_limit;z>hard_lower_limit;z--)
{
if(fabs(ref_table[z]-(TargetTxPwr[band][i] + coarse_tx_delta))<0.5)
{
msrd=ref_table[z];
peak=z;
power_table[(unsigned)(peak+0.5)]=msrd;
search=1;
break;
}
}
while(fabs(msrd-TargetTxPwr[band][i])>0.5 && num_trials<MAX_TX_TRIALS && upper_limit>lower_limit+1 && search==0)
{
if(msrd>TargetTxPwr[band][i])
{
upper_limit=(unsigned)(peak+0.5); // know that correct value of peak is lower than current
peak=(peak+lower_limit)/2; // search halfway between current value and minimum
}
else
{
lower_limit=(unsigned)(peak+0.5); // know that correct value of peak is higher than current
peak=(peak+upper_limit)/2; // search halfway between current value and maximum
}
num_trials++;
build_trial_ramp(trial_ramp,peak,band,GSM_TRIAL_PEDESTAL);
cal_hs.HS_SetRamp(trial_ramp);
cal_hs.HS_SetStop();
cal_hs.HS_SetStart();
Sleep(200);
expected_power=get_expected_power(power_table,(unsigned)(peak+0.5));
stat=cal_measure.GetTxPowerDown(expected_power,&msrd);
ref_table[(unsigned)(peak+0.5)]=msrd;
if(stat!=FALSE)
{
power_table[(unsigned)(peak+0.5)]=msrd;
}
if(stat==FALSE || msrd<(TargetTxPwr[band][18]-2.0))
{
hard_lower_limit=(unsigned)(peak-0.5); // don't go below this - can't measure the power
msrd=-3.0; // set this artificially low to indicate low power
}
}
if(num_trials==MAX_TX_TRIALS) // let the first index be less than target power
{
return TOO_MANY_TX_TRIALS;
}
measured[i-GSM_STARTING_RAMP_INDEX]=msrd;
x[i-GSM_STARTING_RAMP_INDEX]=(unsigned)(peak+0.5);
} // end for all GSM power levels
number_of_points=GSM_ENDING_RAMP_INDEX-GSM_STARTING_RAMP_INDEX+3;
// check min power to see if it's less than 5 dB above expected value
if(measured[number_of_points-3]-TargetTxPwr[band][GSM_ENDING_RAMP_INDEX]>5.00)
{
min_power_too_large=TRUE;
}
else
{
min_power_too_large=FALSE;
}
// put in values for end of table (low power)
// use user-entered slopes to calculate the dac (x) values
measured[number_of_points-2]=next_lowest_power;
x[number_of_points-2]=next_lowest_slope*(measured[number_of_points-2]-measured[number_of_points-3])+x[number_of_points-3];
measured[number_of_points-1]=lowest_power;
x[number_of_points-1]=lowest_slope*(measured[number_of_points-1]-measured[number_of_points-2])+x[number_of_points-2];;
// added in version 6.28 for calculating pedestal values
// build a ramp for power level 19 (index 17)
// initialize pedestal ramp limits
// m0 = -1 usec, -0.55 dB, lower limit
m[0].time=-1.0e-6;
m[0].power=-0.55;
m[0].llimit=1;
m[0].ulimit=0;
// m1 = -10 usec, -5.7 dB, upper limit
m[1].time=-10.0e-6;
m[1].power=-5.7;
m[1].llimit=0;
m[1].ulimit=1;
// m2 = -18 usec, -33 dB, upper limit
m[2].time=-18.0e-6;
m[2].power=-33.0;
m[2].llimit=0;
m[2].ulimit=1;
// 3 points
num_msmnt_pts=3;
current_ramp=17;
up_length=ramp_up_length[14];
down_length=ramp_down_length[14];
up_delta=ramp_up_delta[14];
down_delta=ramp_down_delta[14];
pedestal_slope=ramp_pedestal_slope[14];
pedestal_power=ramp_pedestal_power[14];
low_power_pedestal=pedestal_slope*(pedestal_power-measured[number_of_points-3])+x[number_of_points-3];
cal_measure.GetUpperRampStatus((unsigned)TRUE,TargetTxPwr[GSM][current_ramp],num_msmnt_pts,m);
count=0;
pedestal_done=FALSE;
too_high=0; // haven't been too low or too high yet
too_low=0;
pedestal_step=COARSE_PEDESTAL_STEP;
while(!pedestal_done)
{
if(too_high && too_low)
pedestal_step=FINE_PEDESTAL_STEP;
build_infineon_trial_ramp(trial_ramp,TargetTxPwr[GSM][current_ramp],
up_length,up_delta,down_length,down_delta,low_power_pedestal,
number_of_points,x,measured);
cal_hs.HS_SetRamp(trial_ramp);
cal_measure.GetUpperRampStatus((unsigned)FALSE,TargetTxPwr[GSM][current_ramp],num_msmnt_pts,m);
count++;
if(m[0].passed && m[1].passed && m[2].passed)
pedestal_done=TRUE;
if(count>MAX_INFINEON_PEDESTAL_TRIALS)
{
pedestal_done=FALSE;
break;
}
if(!m[0].passed && !m[1].passed && !m[2].passed) // failed either low and the high limit
break;
else if(!m[2].passed)
{
low_power_pedestal-=pedestal_step;
too_high=1;
}
else if(!m[0].passed || !m[1].passed)
{
low_power_pedestal+=pedestal_step;
too_low=1;
}
}
if(!pedestal_done)
return INFINEON_PEDESTAL_ERROR;
// added in version 6.44 for calculating pedestal value at higher power
// build a ramp for power level 10 (index 8)
// initialize pedestal ramp limits
// m0 = -1 usec, -0.55 dB, lower limit
m[0].time=-1.0e-6;
m[0].power=-0.55;
m[0].llimit=1;
m[0].ulimit=0;
// m1 = -18 usec, -38 dB, lower limit
m[1].time=-18.0e-6;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -