blob: fb915a90d514ab03d6147c88ebaed5cee4e6c274 [file] [log] [blame]
/** \file vp880_calibration_common.c
* vp880_calibration_common.c
*
* This file contains the line and device calibration functions that are common
* within the 880 device family (for ABS and Tracker).
*
* Copyright (c) 2011, Microsemi
*
* $Revision: 1.1.2.1.8.3 $
* $LastChangedDate: 2011-11-07 13:39:50 -0600 (Mon, 07 Nov 2011) $
*/
#include "../includes/vp_api_cfg.h"
#if defined (VP_CC_880_SERIES)
/* INCLUDES */
#include "../../arch/uvb/vp_api_types.h"
#include "../includes/vp_api.h"
#include "../includes/vp_api_int.h"
#include "../includes/vp880_api.h"
#include "../vp880_api/vp880_api_int.h"
#include "../../arch/uvb/vp_hal.h"
#include "../../arch/uvb/sys_service.h"
#if defined (VP_CSLAC_RUNTIME_CAL_ENABLED) && defined (VP880_FXS_SUPPORT)
#define VP880_IMT_SETTLE_MS 100
#define VP880_DCFEED_SETTLE_MS 100
#define VP880_IMT_10MA 5679L
/* Functions for Cal Line = FXS only */
static bool
CalLineNextState(
VpDevCtxType *pDevCtx,
VpLineCtxType *pLineCtx,
Vp880DeviceObjectType *pDevObj,
Vp880LineObjectType *pLineObj,
uint16 *pCalTimerMs);
#ifdef VP880_TRACKER_SUPPORT
static void
ComputeFinalVas(
VpLineCtxType *pLineCtx,
uint16 *vasValue);
#endif
static void
SetAdc(
VpLineCtxType *pLineCtx,
VpDeviceIdType deviceId,
uint8 ecVal,
uint8 adcRoute);
static bool
GetXData(
VpLineCtxType *pLineCtx,
VpDeviceIdType deviceId,
uint8 ecVal,
int16 *pData);
#endif
#if defined (VP_CSLAC_RUNTIME_CAL_ENABLED) && defined (VP880_FXS_SUPPORT)
/**
* Vp880CalCodec() -- Tracker and ABS Function
* This function initiates a calibration operation for analog circuits
* associated with all the lines of a device. See VP-API reference guide for
* more information.
* Preconditions:
* The device and line context must be created and initialized before calling
* this function.
*
* Postconditions:
* This function generates an event upon completing the requested action.
*/
VpStatusType
Vp880CalCodec(
VpLineCtxType *pLineCtx,
VpDeviceCalType mode)
{
Vp880LineObjectType *pLineObj = pLineCtx->pLineObj;
VpDevCtxType *pDevCtx = pLineCtx->pDevCtx;
Vp880DeviceObjectType *pDevObj = pDevCtx->pDevObj;
VpDeviceIdType deviceId = pDevObj->deviceId;
uint8 maxChannels = pDevObj->staticInfo.maxChannels;
uint8 chanNum;
VpLineStateType currentState;
VP_API_FUNC_INT(VpLineCtxType, pLineCtx, ("Vp880CalCodec+"));
VpSysEnterCritical(deviceId, VP_CODE_CRITICAL_SEC);
pDevObj->responseData = VP_CAL_SUCCESS;
if (pDevObj->stateInt & VP880_DEVICE_CAL_COMPLETE) {
pDevObj->deviceEvents.response |= VP_EVID_CAL_CMP;
VP_API_FUNC_INT(VpLineCtxType, pLineCtx, ("Vp880CalCodec-"));
VpSysExitCritical(deviceId, VP_CODE_CRITICAL_SEC);
return VP_STATUS_SUCCESS;
}
if (mode == VP_DEV_CAL_NBUSY) {
for (chanNum = 0; chanNum < maxChannels; chanNum++) {
if (pDevCtx->pLineCtx[chanNum] != VP_NULL) {
pLineObj = pLineCtx->pLineObj;
currentState = pLineObj->lineState.currentState;
if (pLineObj->status & VP880_IS_FXO) {
if ((currentState == VP_LINE_FXO_TALK)
|| (currentState == VP_LINE_FXO_LOOP_CLOSE)) {
pDevObj->deviceEvents.response |= VP_EVID_CAL_BUSY;
pDevObj->deviceEvents.response &= ~VP_EVID_CAL_CMP;
VP_API_FUNC_INT(VpLineCtxType, pLineCtx, ("Vp880CalCodec-"));
VpSysExitCritical(deviceId, VP_CODE_CRITICAL_SEC);
return VP_STATUS_SUCCESS;
}
} else {
if ((currentState != VP_LINE_STANDBY)
&& (currentState != VP_LINE_DISCONNECT)) {
pDevObj->deviceEvents.response |= VP_EVID_CAL_BUSY;
pDevObj->deviceEvents.response &= ~VP_EVID_CAL_CMP;
VP_API_FUNC_INT(VpLineCtxType, pLineCtx, ("Vp880CalCodec-"));
VpSysExitCritical(deviceId, VP_CODE_CRITICAL_SEC);
return VP_STATUS_SUCCESS;
}
}
}
}
}
pDevObj->state |= VP_DEV_IN_CAL;
if (!(pDevObj->stateInt & VP880_IS_ABS)) {
#ifdef VP880_TRACKER_SUPPORT
pDevObj->state |= VP_DEV_ABV_CAL;
Vp880CalCodecInt(pDevCtx);
#endif
} else {
#ifdef VP880_ABS_SUPPORT
if (Vp880SetCalFlags(pDevObj) == TRUE) {
Vp880CalCodecInt(pDevCtx);
}
#endif
}
VP_API_FUNC_INT(VpLineCtxType, pLineCtx, ("Vp880CalCodec-"));
VpSysExitCritical(deviceId, VP_CODE_CRITICAL_SEC);
return VP_STATUS_SUCCESS;
} /* Vp880CalCodec() */
/**
* Vp880CalCodecInt() -- Tracker and ABS Function
* This function initiates a calibration operation for analog circuits
* associated with all the lines of a device. See VP-API reference guide for
* more information.
* Preconditions:
* The device and line context must be created and initialized before calling
* this function.
*
* Postconditions:
* This function generates an event upon completing the requested action.
*/
VpStatusType
Vp880CalCodecInt(
VpDevCtxType *pDevCtx)
{
Vp880DeviceObjectType *pDevObj = pDevCtx->pDevObj;
VP_API_FUNC_INT(VpDevCtxType, pDevCtx, ("Vp880CalCodecInt+"));
#ifdef VP880_TRACKER_SUPPORT
if (pDevObj->state & VP_DEV_ABV_CAL) {
VP_CALIBRATION(VpDevCtxType, pDevCtx, ("Calling ABV Cal inside Vp880CalCodecInt() for Tracker"));
Vp880CalAbv(pDevCtx);
VP_API_FUNC_INT(VpDevCtxType, pDevCtx, ("Vp880CalCodecInt-"));
return VP_STATUS_SUCCESS;
}
#endif
#ifdef VP880_ABS_SUPPORT
if (pDevObj->state & VP_DEV_ABV_CAL_ABS) {
VP_CALIBRATION(VpDevCtxType, pDevCtx, ("Calling ABV Cal inside Vp880CalCodecInt() for ABS"));
Vp880CalAbvAbsDev(pDevCtx);
VP_API_FUNC_INT(VpDevCtxType, pDevCtx, ("Vp880CalCodecInt-"));
return VP_STATUS_SUCCESS;
}
if (pDevObj->state & VP_DEV_ABS_BAT_CAL) {
VP_CALIBRATION(VpDevCtxType, pDevCtx, ("Calling ABS Cal (Vp880AbsCalibration()) inside Vp880CalCodecInt()"));
Vp880AbsCalibration(pDevCtx);
VP_API_FUNC_INT(VpDevCtxType, pDevCtx, ("Vp880CalCodecInt-"));
return VP_STATUS_SUCCESS;
}
#endif
VP_ERROR(VpDevCtxType, pDevCtx, ("Vp880CalCodecInt- Exit to unspecified calibration state!!"));
VP_API_FUNC_INT(VpDevCtxType, pDevCtx, ("Vp880CalCodecInt-"));
return VP_STATUS_SUCCESS;
} /* Vp880CalCodecInt() */
/**
* Vp880CalLine()
* This function initiates a calibration operation for analog circuits
* associated with a given line. See VP-API reference guide for more
* information.
* Preconditions:
* The device and line context must be created and initialized before calling
* this function.
*
* Postconditions:
* This function generates an event upon completing the requested action.
*/
VpStatusType
Vp880CalLine(
VpLineCtxType *pLineCtx)
{
Vp880LineObjectType *pLineObj = pLineCtx->pLineObj;
VpDevCtxType *pDevCtx = pLineCtx->pDevCtx;
Vp880DeviceObjectType *pDevObj = pDevCtx->pDevObj;
VpDeviceIdType deviceId = pDevObj->deviceId;
uint16 tickRate = pDevObj->devProfileData.tickRate;
VpLineStateType currentState = pLineObj->lineState.usrCurrent;
uint8 ecVal = pLineObj->ecVal;
uint8 opCond[VP880_OP_COND_LEN];
VP_API_FUNC_INT(VpLineCtxType, pLineCtx, ("+Vp880CalLine()"));
/* Block if device init is not complete */
if (!(pDevObj->state & VP_DEV_INIT_CMP)) {
return VP_STATUS_DEV_NOT_INITIALIZED;
}
if (pLineObj->status & VP880_IS_FXO) {
return VP_STATUS_INVALID_ARG;
}
/*
* Do not proceed if the device calibration is in progress. This could
* damage the device.
*/
if (pDevObj->state & VP_DEV_IN_CAL) {
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("Return NOT_INITIALIZED from Vp880CalLine()"));
VP_API_FUNC_INT(VpLineCtxType, pLineCtx,
("-Vp880CalLine()"));
return VP_STATUS_DEV_NOT_INITIALIZED;
}
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("Running Cal Line on Channel %d at time %d target 0x%02X 0x%02X",
pLineObj->channelId, pDevObj->timeStamp,
pLineObj->calLineData.dcFeedRef[0],
pLineObj->calLineData.dcFeedRef[1]));
VpSysEnterCritical(deviceId, VP_CODE_CRITICAL_SEC);
/* Don't run calibration if previously complete on this line */
if ((pLineObj->calLineData.calDone == TRUE) ||
(pDevObj->staticInfo.rcnPcn[VP880_RCN_LOCATION] < VP880_REV_JE)) {
pLineObj->lineEvents.response |= VP_EVID_CAL_CMP;
pLineObj->lineState.calType = VP_CSLAC_CAL_NONE;
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("Calibration Previously Done. Cal Line Complete"));
VpSysExitCritical(deviceId, VP_CODE_CRITICAL_SEC);
return VP_STATUS_SUCCESS;
}
pLineObj->status |= VP880_LINE_IN_CAL;
/* Make sure line calibration can be run */
switch(currentState) {
case VP_LINE_OHT:
break;
case VP_LINE_STANDBY:
pLineObj->lineState.calType = VP_CSLAC_CAL_NONE;
Vp880SetLineState(pLineCtx, VP_LINE_OHT);
break;
case VP_LINE_STANDBY_POLREV:
case VP_LINE_OHT_POLREV:
pLineObj->lineState.calType = VP_CSLAC_CAL_NONE;
Vp880SetLineState(pLineCtx, VP_LINE_OHT_POLREV);
break;
default:
VpSysExitCritical(deviceId, VP_CODE_CRITICAL_SEC);
VP_API_FUNC_INT(VpLineCtxType, pLineCtx, ("-Vp880CalLine()"));
return VP_STATUS_INVALID_ARG;
}
/* we need to remember if we started in polrev */
if (pLineObj->slicValueCache & VP880_SS_POLARITY_MASK) {
pLineObj->calLineData.reversePol = TRUE;
} else {
pLineObj->calLineData.reversePol = FALSE;
}
#ifdef VP880_LP_SUPPORT
/*
* Force a LPM Exit update before proceeding with Calibration. If this
* isn't done before setting the device mask, the LPM code to exit LPM will
* not run (because it otherwise does not touch the device while in
* calibration). If it is not a LPM device, this function doesn't do
* anything.
*/
Vp880LowPowerMode(pDevCtx);
#endif
pLineObj->lineTimers.timers.timer[VP_LINE_CAL_LINE_TIMER] =
MS_TO_TICKRATE(VP880_MIN_CAL_WAIT_TIME, tickRate);
pLineObj->lineTimers.timers.timer[VP_LINE_CAL_LINE_TIMER] |=
VP_ACTIVATE_TIMER;
/* Reprogram the Operating Conditions Register, affected by Set Line State */
opCond[0] = (VP880_CUT_TXPATH | VP880_CUT_RXPATH | VP880_HIGH_PASS_DIS);
VpMpiCmdWrapper(deviceId, ecVal, VP880_OP_COND_WRT, VP880_OP_COND_LEN, opCond);
pLineObj->opCond[0] = opCond[0];
pLineObj->calLineData.calLineState = VP880_CAL_SETUP;
/*
* Vp880ServiceFxsInterrupts uses this to decide if ring exit debounce
* or CID need to be handled. Setting it to something other than
* VP_CSLAC_CAL_NONE should be good enough.
*/
pLineObj->lineState.calType = VP_CSLAC_CAL_VOC;
VpSysExitCritical(deviceId, VP_CODE_CRITICAL_SEC);
VP_API_FUNC_INT(VpLineCtxType, pLineCtx, ("-Vp880CalLine()"));
return VP_STATUS_SUCCESS;
}
/**
* Vp880CalLineInt()
* This function is called each time the VP_LINE_CAL_LINE_TIMER expires.
* Its basic purpose is to continue calling CalLineNextState until it
* returns false.
*
* Postconditions:
* This function generates an event upon completing the requested action or
* sets up the cal timer to expire at a later time to run the next state.
*/
VpStatusType
Vp880CalLineInt(
VpLineCtxType *pLineCtx)
{
Vp880LineObjectType *pLineObj = pLineCtx->pLineObj;
VpDevCtxType *pDevCtx = pLineCtx->pDevCtx;
Vp880DeviceObjectType *pDevObj = pDevCtx->pDevObj;
uint16 tickRate = pDevObj->devProfileData.tickRate;
uint16 calTimerMs = 0;
pDevObj->responseData = VP_CAL_SUCCESS;
VP_API_FUNC_INT(VpLineCtxType, pLineCtx, ("+Vp880CalLineInt()"));
/* Continue calling the cal state machine until it indicates FALSE */
while (CalLineNextState(pDevCtx, pLineCtx, pDevObj, pLineObj, &calTimerMs));
if (calTimerMs != 0) {
/* Setup the Cal timer to expire in requested ms */
pLineObj->lineTimers.timers.timer[VP_LINE_CAL_LINE_TIMER] =
MS_TO_TICKRATE(calTimerMs, tickRate);
pLineObj->lineTimers.timers.timer[VP_LINE_CAL_LINE_TIMER] |=
VP_ACTIVATE_TIMER;
} else {
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("Generating VP_EVID_CAL_CMP Event for Channel %d EventMask 0x%04X",
pLineObj->channelId, pLineObj->lineEventsMask.response));
/* If no timer was requested, Cal must be done so generate and event */
pLineObj->lineState.calType = VP_CSLAC_CAL_NONE;
pLineObj->lineEvents.response |= VP_EVID_CAL_CMP;
pLineObj->status &= ~VP880_LINE_IN_CAL;
/*
* Set calDone = TRUE only if there wasn't a failure detected. If the
* calDone flag is TRUE, the line can't be recalibrated without the
* hidden setting with APPLY_SYSTEM_CEOFF and NULL profile.
*/
if (pDevObj->responseData == VP_CAL_FAILURE) {
/*
* This should be redundant because calibration won't run unless
* this value was previously set to FALSE. But it's safe just to
* make sure it's set to a know value for a known condition.
*/
pLineObj->calLineData.calDone = FALSE;
} else {
pLineObj->calLineData.calDone = TRUE;
}
/* line calibration is no longer in progress at this point */
pLineObj->status &= ~VP880_LINE_IN_CAL;
}
VP_API_FUNC_INT(VpLineCtxType, pLineCtx, ("-Vp880CalLineInt()"));
return VP_STATUS_SUCCESS;
} /* Vp880CalLineInt */
/**
* CalLineNextState()
* This function implements the steps of the 880 Calibration algorithm.
*
* The state machine will move to the next state when the Cal timer
* expires or if the function returns TRUE.
*
* Postconditions:
* Returns true indicating that another state should be run immediately.
* Returns false indicating that the state machine is done with the current
* state.
*/
static bool
CalLineNextState(
VpDevCtxType *pDevCtx,
VpLineCtxType *pLineCtx,
Vp880DeviceObjectType *pDevObj,
Vp880LineObjectType *pLineObj,
uint16 *pCalTimerMs)
{
uint8 channelId = pLineObj->channelId;
uint8 ecVal = pLineObj->ecVal;
VpDeviceIdType deviceId = pDevObj->deviceId;
Vp880CalLineState nextState = VP880_CAL_ENUM_SIZE;
bool runAnotherState = FALSE;
uint8 mpiIndex = 0;
uint8 mpiBuffer[254];
*pCalTimerMs = 0;
switch(pLineObj->calLineData.calLineState) {
/***********************************************************************
* This state is used to setup the device for the cal sequence
* by clearing out values in registers.
**********************************************************************/
case VP880_CAL_SETUP: {
uint8 disnVal = 0;
uint8 vpGain = 0;
uint8 codec = VP880_LINEAR_CODEC;
uint8 loopSup[VP880_LOOP_SUP_LEN];
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("Cal State VP880_CAL_SETUP"));
/*
* Start off with the assumption calibration will work. Simpler to
* let the algorithm detect failure and set this accordingly rather
* than have each possible good exit set it for pass.
*/
pDevObj->responseData = VP_CAL_SUCCESS;
/* Store LoopSup, DISN , Voice Path Gain, ICR2, SLIC state, and genA */
VpMemCpy(pLineObj->calLineData.loopSup, pLineObj->loopSup,
VP880_LOOP_SUP_LEN);
VpMpiCmdWrapper(deviceId, ecVal, VP880_SS_CONFIG_RD,
VP880_SS_CONFIG_LEN, &pLineObj->calLineData.asscReg);
VpMemCpy(loopSup, pLineObj->calLineData.loopSup, VP880_LOOP_SUP_LEN);
VpMpiCmdWrapper(deviceId, ecVal, VP880_DISN_RD,
VP880_DISN_LEN, pLineObj->calLineData.disnVal);
VpMpiCmdWrapper(deviceId, ecVal, VP880_VP_GAIN_RD,
VP880_VP_GAIN_LEN,pLineObj->calLineData.vpGain);
VpMemCpy(pLineObj->calLineData.icr2, pLineObj->icr2Values, VP880_ICR2_LEN);
VpMemCpy(pLineObj->calLineData.icr3, pLineObj->icr3Values, VP880_ICR3_LEN);
VpMpiCmdWrapper(deviceId, ecVal, VP880_SIGA_PARAMS_RD,
VP880_SIGA_PARAMS_LEN, pLineObj->calLineData.sigGenA);
VpMpiCmdWrapper(deviceId, ecVal, VP880_OP_FUNC_RD,
VP880_OP_FUNC_LEN, &pLineObj->calLineData.codecReg);
/* Set Hook Debounce to 8 ms */
loopSup[VP880_LOOP_SUP_DEBOUNCE_BYTE] &= ~VP880_SWHOOK_DEBOUNCE_MASK;
loopSup[VP880_LOOP_SUP_DEBOUNCE_BYTE] |= 0x04;
mpiIndex = VpCSLACBuildMpiBuffer(mpiIndex, mpiBuffer,
VP880_LOOP_SUP_WRT, VP880_LOOP_SUP_LEN, loopSup);
/* Set DISN = 0 and Voice Path Gain = 0dB TX */
mpiIndex = VpCSLACBuildMpiBuffer(mpiIndex, mpiBuffer,
VP880_DISN_WRT, VP880_DISN_LEN, &disnVal);
mpiIndex = VpCSLACBuildMpiBuffer(mpiIndex, mpiBuffer,
VP880_VP_GAIN_WRT,VP880_VP_GAIN_LEN, &vpGain);
/* Set the device mode register for single buffer mode */
pDevObj->devMode[0] &= ~(VP880_DEV_MODE_TEST_DATA);
mpiIndex = VpCSLACBuildMpiBuffer(mpiIndex, mpiBuffer,
VP880_DEV_MODE_WRT, VP880_DEV_MODE_LEN, pDevObj->devMode);
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("\n\rVP880_CAL_SETUP: Writing 0x%02X to Operating Functions", codec));
/* Set for Linear Mode and disable AC Coefficients */
mpiIndex = VpCSLACBuildMpiBuffer(mpiIndex, mpiBuffer,
VP880_OP_FUNC_WRT, VP880_OP_FUNC_LEN, &codec);
/* Cut TX/RX PCM and disable HPF */
pLineObj->opCond[0] = (VP880_CUT_TXPATH | VP880_CUT_RXPATH | VP880_HIGH_PASS_DIS);
mpiIndex = VpCSLACBuildMpiBuffer(mpiIndex, mpiBuffer,
VP880_OP_COND_WRT, VP880_OP_COND_LEN, pLineObj->opCond);
/* Copy the reference dcfeed data into the polrev dcfeed array */
VpMemCpy(pLineObj->calLineData.dcFeedPr,
pLineObj->calLineData.dcFeedRef, VP880_DC_FEED_LEN);
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("\n\rVP880_CAL_SETUP: Copied 0x%02X 0x%02X to dcFeedPr",
pLineObj->calLineData.dcFeedPr[0], pLineObj->calLineData.dcFeedPr[1]));
if (!(pDevObj->stateInt & VP880_IS_ABS)) {
#ifdef VP880_TRACKER_SUPPORT
/* set VAS to 3.0V (min) */
pLineObj->calLineData.dcFeedPr[0] &= 0xFC;
pLineObj->calLineData.dcFeedPr[1] &= 0x3F;
/* Start for Tracker Device */
nextState = VP880_CAL_SETUP_RELEASE_CLAMPS;
#endif
} else {
#ifdef VP880_ABS_SUPPORT
/* Start for ABS Device */
nextState = VP880_RAMP_TO_POLREV_SETUP;
#endif
}
/* set ila to 40mA */
pLineObj->calLineData.dcFeedPr[1] &= ~VP880_ILA_MASK;
pLineObj->calLineData.dcFeedPr[1] |= (VP880_ILA_MASK & 0x16);
/* Set DC-Feed to values from dc profile */
mpiIndex = VpCSLACBuildMpiBuffer(mpiIndex, mpiBuffer,
VP880_DC_FEED_WRT, VP880_DC_FEED_LEN, pLineObj->calLineData.dcFeedPr);
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("\n\rVP880_CAL_SETUP: Modified to 0x%02X 0x%02X to dcFeedPr",
pLineObj->calLineData.dcFeedPr[0], pLineObj->calLineData.dcFeedPr[1]));
/* next state info */
*pCalTimerMs = 10;
break;
}
case VP880_CAL_SETUP_RELEASE_CLAMPS:
if ((pDevObj->stateInt & VP880_IS_HIGH_VOLTAGE) &&
!pDevObj->devProfileData.lowVoltOverride) {
/*
* if this is a high voltage device and designed
* with a high voltage supply then we need to set
* the voltage clamps to 150V to give the slower
* battery designs time to ramp up.
*/
pLineObj->icr2Values[2] |= 0x0C;
pLineObj->icr2Values[3] |= 0x0C;
mpiIndex = VpCSLACBuildMpiBuffer(mpiIndex, mpiBuffer,
VP880_ICR2_WRT, VP880_ICR2_LEN, pLineObj->icr2Values);
}
/* if we are not already in polrev then we need to go there */
if (!pLineObj->calLineData.reversePol) {
nextState = VP880_RAMP_TO_POLREV_SETUP;
*pCalTimerMs = 10;
} else {
nextState = VP880_IMT_PR_SETUP;
/*
* mimic the time required by ramp pol rev to give
* battery from the slower power supplies time to
* finish moving.
*/
*pCalTimerMs = 100;
}
break;
/***********************************************************************
* These states are used to force the line into polrev using a ramp
*
* Need to ramp to negative polarity so that we dont ding a phone. Due
* to a device issue, we have to split the ramp in two. The first
* ramp will start at -45V and ramp to 0V. Once 0V is acheived, the deivce
* the polarity of the line will be flipped. Then the ramp will
* continue to +45V. Finally the line will be taken out of ringing
* and put into active. Performing the polrev at 0V prevents a tip/ring
* transient at the end when we go from balanced ringing to active polrev.
**********************************************************************/
case VP880_RAMP_TO_POLREV_SETUP: {
uint8 asscReg = (pLineObj->calLineData.asscReg | VP880_ZXR_MASK);
/* setup siggen to mimic a 45V VOC once ringing is enabled */
uint8 sigGenA[VP880_SIGA_PARAMS_LEN] =
{0x00, 0x25, 0x4E, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00 ,0x00, 0x00};
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("Cal State VP880_RAMP_TO_POLREV_SETUP"));
/* disable auto ring entery / exit */
mpiIndex = VpCSLACBuildMpiBuffer(mpiIndex, mpiBuffer,
VP880_SS_CONFIG_WRT, VP880_SS_CONFIG_LEN, &asscReg);
/* Prepare the sig gen with ramp info */
mpiIndex = VpCSLACBuildMpiBuffer(mpiIndex, mpiBuffer,
VP880_SIGA_PARAMS_WRT, VP880_SIGA_PARAMS_LEN, sigGenA);
/*
* go to the balanced ringing state. This should generate a
* longitudinal shift. The direction and size will depend on
* the value of VOC in the DC feed register.
*/
pLineObj->slicValueCache &= ~VP880_SS_STATE_MASK;
pLineObj->slicValueCache |= VP880_SS_BALANCED_RINGING;
mpiIndex = VpCSLACBuildMpiBuffer(mpiIndex, mpiBuffer,
VP880_SYS_STATE_WRT, VP880_SYS_STATE_LEN, &pLineObj->slicValueCache);
/* enable longitudinal clamp even in ringing for duration of the CalLine */
pLineObj->icr3Values[2] |= 0x40;
pLineObj->icr3Values[3] = (pLineObj->icr3Values[3] & ~0x40);
mpiIndex = VpCSLACBuildMpiBuffer(mpiIndex, mpiBuffer,
VP880_ICR3_WRT, VP880_ICR3_LEN, pLineObj->icr3Values);
/* next state info */
*pCalTimerMs = 10;
nextState = VP880_RAMP_TO_POLREV_RAMP1;
break;
}
case VP880_RAMP_TO_POLREV_RAMP1: {
/* force the siggen to start a negative ramp of 45V */
uint8 sigGenA[VP880_SIGA_PARAMS_LEN] =
{0x07, 0x25, 0x4E, 0x00, 0x25, 0x25, 0x4E, 0x00, 0x00 ,0x00, 0x00};
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("Cal State VP880_RAMP_TO_POLREV_RAMP1"));
mpiIndex = VpCSLACBuildMpiBuffer(mpiIndex, mpiBuffer,
VP880_SIGA_PARAMS_WRT, VP880_SIGA_PARAMS_LEN, sigGenA);
*pCalTimerMs = 100;
nextState = VP880_RAMP_TO_POLREV_SWAP_POLARITY;
break;
}
case VP880_RAMP_TO_POLREV_SWAP_POLARITY: {
/* go to balanced ringing polrev */
pLineObj->slicValueCache &= ~VP880_SS_STATE_MASK;
pLineObj->slicValueCache |= VP880_SS_BALANCED_RINGING_PR;
mpiIndex = VpCSLACBuildMpiBuffer(mpiIndex, mpiBuffer,
VP880_SYS_STATE_WRT, VP880_SYS_STATE_LEN, &pLineObj->slicValueCache);
runAnotherState = TRUE;
nextState = VP880_RAMP_TO_POLREV_RAMP2;
break;
}
case VP880_RAMP_TO_POLREV_RAMP2: {
/* force the siggen to complete the ramp */
uint8 sigGenA[VP880_SIGA_PARAMS_LEN] =
{0x03, 0x25, 0x4E, 0x00, 0x25, 0x25, 0x4E, 0x00, 0x00 ,0x00, 0x00};
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("Cal State VP880_RAMP_TO_POLREV_RAMP2"));
mpiIndex = VpCSLACBuildMpiBuffer(mpiIndex, mpiBuffer,
VP880_SIGA_PARAMS_WRT, VP880_SIGA_PARAMS_LEN, sigGenA);
*pCalTimerMs = 50;
nextState = VP880_RAMP_TO_POLREV_GOACTIVE;
break;
}
case VP880_RAMP_TO_POLREV_GOACTIVE: {
uint8 sigGenA[VP880_SIGA_PARAMS_LEN] =
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00 ,0x00, 0x00};
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("Cal State VP880_RAMP_TO_POLREV_GOACTIVE"));
/* go to active polrev */
pLineObj->slicValueCache &= ~VP880_SS_STATE_MASK;
pLineObj->slicValueCache |= VP880_SS_ACTIVE_POLREV;
mpiIndex = VpCSLACBuildMpiBuffer(mpiIndex, mpiBuffer,
VP880_SYS_STATE_WRT, VP880_SYS_STATE_LEN, &pLineObj->slicValueCache);
/* remove the siggen ramp */
mpiIndex = VpCSLACBuildMpiBuffer(mpiIndex, mpiBuffer,
VP880_SIGA_PARAMS_WRT, VP880_SIGA_PARAMS_LEN, sigGenA);
*pCalTimerMs = 10;
nextState = VP880_RAMP_TO_POLREV_COMPLETE;
break;
}
case VP880_RAMP_TO_POLREV_COMPLETE: {
/* restore the automatic system state control */
mpiIndex = VpCSLACBuildMpiBuffer(mpiIndex, mpiBuffer,
VP880_SS_CONFIG_WRT, VP880_SS_CONFIG_LEN, &pLineObj->calLineData.asscReg);
*pCalTimerMs = 20;
nextState = VP880_IMT_PR_SETUP;
}
/***********************************************************************
* Settle IMT in PolRev -
*
* These states setup, measure Metallic polrev current until it
* settles. This is done to prevent high REN loads from distorting
* the VAS measurements
**********************************************************************/
case VP880_IMT_PR_SETUP: {
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("Cal State VP880_IMT_PR_SETUP"));
if (!(pDevObj->stateInt & VP880_IS_ABS)) {
#ifdef VP880_TRACKER_SUPPORT
/* Enable battery and DC Speed up */
pLineObj->icr2Values[2] |= 0xC0;
pLineObj->icr2Values[3] |= 0xC0;
#endif
} else {
#ifdef VP880_ABS_SUPPORT
/* Enable DC Speed up only */
pLineObj->icr2Values[2] |= 0x80;
pLineObj->icr2Values[3] |= 0x80;
#endif
}
mpiIndex = VpCSLACBuildMpiBuffer(mpiIndex, mpiBuffer,
VP880_ICR2_WRT, VP880_ICR2_LEN, pLineObj->icr2Values);
/* prepare storage data */
pLineObj->calLineData.typeData.loopData.loopNum = 0;
pLineObj->calLineData.typeData.loopData.prevVal = 0;
*pCalTimerMs = 10;
nextState = VP880_IMT_PR_SET_ADC;
break;
}
case VP880_IMT_PR_SET_ADC: {
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("Cal State VP880_IMT_PR_SET_ADC"));
SetAdc(pLineCtx, deviceId, ecVal, VP880_METALLIC_DC_I);
*pCalTimerMs = 10;
nextState = VP880_IMT_PR_MEASURE;
break;
}
case VP880_IMT_PR_MEASURE: {
int16 imOld = 0;
int16 imNew = 0;
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("Cal State VP880_IMT_PR_MEASURE"));
if ( !GetXData(pLineCtx, deviceId, ecVal, &imNew)) {
*pCalTimerMs = 10;
nextState = VP880_IMT_PR_MEASURE;
break;
}
/* if this is the first imt measurement then get another */
if (pLineObj->calLineData.typeData.loopData.loopNum++ == 0) {
pLineObj->calLineData.typeData.loopData.prevVal = imNew;
*pCalTimerMs = VP880_IMT_SETTLE_MS;
nextState = VP880_IMT_PR_MEASURE;
break;
}
imOld = pLineObj->calLineData.typeData.loopData.prevVal;
/* have we settled enough or taken to long > 200ms*/
if ( (pLineObj->calLineData.typeData.loopData.loopNum < 20 /*200ms*/) &&
(((imNew + 15 - imOld) & 0xFFE0) != 0) ) {
/* nope run it again */
pLineObj->calLineData.typeData.loopData.prevVal = imNew;
*pCalTimerMs = VP880_IMT_SETTLE_MS;
nextState = VP880_IMT_PR_MEASURE;
break;
}
runAnotherState = TRUE;
if (!(pDevObj->stateInt & VP880_IS_ABS)) {
#ifdef VP880_TRACKER_SUPPORT
nextState = VP880_VAS_PR_SETUP;
#endif
} else {
nextState = VP880_VAB_PR_SETUP;
}
break;
}
#ifdef VP880_TRACKER_SUPPORT
/***********************************************************************
* Measure VAS in PolRev -
*
* These five states step through VAS values and measure IMT.
* This will continue until:
* VAS >= 10.25V ||
* new IMT < 10mA && (new IMT - old IMT are with in +9 to -7mA)
*
* We only loop to 10.25V because we will always add 3.75V to VAS
* and the max value of the VAS register is 14.25V.
**********************************************************************/
case VP880_VAS_PR_SETUP:
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("Cal State VP880_VAS_PR_SETUP"));
/* prepare storage data */
pLineObj->calLineData.typeData.loopData.loopNum = 0;
pLineObj->calLineData.typeData.loopData.prevVal = 0x7FFF;
pLineObj->calLineData.vasStart = 3000;
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("VP880_VAS_PR_SETUP: Best Actual VAS Start %d",
pLineObj->calLineData.vasStart));
runAnotherState = TRUE;
nextState = VP880_VAS_PR_STEP;
break;
case VP880_VAS_PR_STEP: {
uint8 loopNum = pLineObj->calLineData.typeData.loopData.loopNum;
uint16 vasVal = pLineObj->calLineData.vasStart + (750 * loopNum);
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("Cal State VP880_VAS_PR_STEP"));
/*
* If the calculated VAS is max, advance to battery adjustment
* steps.
*/
if (vasVal > VP880_VAS_MAX) {
runAnotherState = TRUE;
nextState = VP880_VAS_PR_STORE;
break;
}
/* set VAS to the next value */
VpCSLACSetVas(pLineObj->calLineData.dcFeedPr, vasVal);
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("VP880_VAS_PR_STEP: Setting VAS (%d) with Values 0x%02X 0x%02X at time %d",
vasVal,
pLineObj->calLineData.dcFeedPr[0], pLineObj->calLineData.dcFeedPr[1],
pDevObj->timeStamp));
mpiIndex = VpCSLACBuildMpiBuffer(mpiIndex, mpiBuffer,
VP880_DC_FEED_WRT, VP880_DC_FEED_LEN, pLineObj->calLineData.dcFeedPr);
/* dcfeed takes 100ms to settle after each step be very carefull adjusting this */
*pCalTimerMs = VP880_DCFEED_SETTLE_MS;
nextState = VP880_VAS_PR_SET_ADC;
break;
}
case VP880_VAS_PR_SET_ADC: {
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("Cal State VP880_VAS_PR_SET_ADC"));
SetAdc(pLineCtx, deviceId, ecVal, VP880_METALLIC_DC_I);
*pCalTimerMs = 10;
nextState = VP880_VAS_PR_MEASURE;
break;
}
case VP880_VAS_PR_MEASURE: {
int16 imtOld = pLineObj->calLineData.typeData.loopData.prevVal;
int16 imtNew = 0;
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("Cal State VP880_VAS_PR_MEASURE"));
if ( !GetXData(pLineCtx, deviceId, ecVal, &imtNew)) {
*pCalTimerMs = 10;
nextState = VP880_VAS_PR_MEASURE;
break;
}
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("VP880_VAS_PR_MEASURE: IMT Old %d IMT New %d",
imtOld, imtNew));
runAnotherState = TRUE;
if (pLineObj->calLineData.typeData.loopData.loopNum++ == 0) {
/* if this is the first imt measurement then get another */
nextState = VP880_VAS_PR_STEP;
} else if ((imtNew > VP880_IMT_10MA) ||
(((imtNew + 15 - imtOld) & 0xFFE0) != 0) ) {
/*
* if the measured value is greater than 10 mA or the difference
* between old and new values are greater +9/-7 then get another
*/
nextState = VP880_VAS_PR_STEP;
} else {
/* if there is nothing left then store the data */
nextState = VP880_VAS_PR_STORE;
}
/* replace the old with the new */
pLineObj->calLineData.typeData.loopData.prevVal = imtNew;
break;
}
case VP880_VAS_PR_STORE: {
uint16 vasVal;
uint8 dcFeed[VP880_DC_FEED_LEN];
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("Cal State VP880_VAS_PR_STORE"));
/* Compute final VAS Values */
VpMpiCmdWrapper(deviceId, ecVal, VP880_DC_FEED_RD, VP880_DC_FEED_LEN, dcFeed);
vasVal = VP880_VAS_CONVERSION(dcFeed[0], dcFeed[1]);
/*
* This function will determine if VAS is at max, and if so then
* increase Battery correction by the overhead amount.
*/
ComputeFinalVas(pLineCtx, &vasVal);
/*
* Set VAS to the final value. Note that this is NOT redundant from
* the previous read because VAS can be actually be reduced. It is
* the case when VAS reaches max and a battery adjustment increases
* such that the total VAS_MAX + battery_adjust_actual is > the
* required VAS + Overhead. This occurs due to differences in step
* sizes betwen battery adjustment and VAS.
*/
VpCSLACSetVas(pLineObj->calLineData.dcFeedPr, vasVal);
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("VP880_VAS_PR_STORE: Setting VAS (%d) with Final Values 0x%02X 0x%02X at time %d",
vasVal,
pLineObj->calLineData.dcFeedPr[0], pLineObj->calLineData.dcFeedPr[1],
pDevObj->timeStamp));
mpiIndex = VpCSLACBuildMpiBuffer(mpiIndex, mpiBuffer,
VP880_DC_FEED_WRT, VP880_DC_FEED_LEN, pLineObj->calLineData.dcFeedPr);
/* Second byte contains the lower two bits of VAS */
pDevObj->vp880SysCalData.vas[channelId][VP880_REV_POLARITY] =
((pLineObj->calLineData.dcFeedPr[1] >> 6) & 0x3);
/* First byte contains the upper two bits of VAS */
pDevObj->vp880SysCalData.vas[channelId][VP880_REV_POLARITY] |=
((pLineObj->calLineData.dcFeedPr[0] << 2) & 0xC);
runAnotherState = TRUE;
nextState = VP880_VAB_PR_SETUP;
break;
}
#endif
/***********************************************************************
* Measure VAB (VOC) in polrev -
*
* These two states setup and measure the VAB (VOC) value in polrev.
**********************************************************************/
case VP880_VAB_PR_SETUP: {
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("Cal State VP880_VAB_PR_SETUP"));
SetAdc(pLineCtx, deviceId, ecVal, VP880_METALLIC_DC_V);
*pCalTimerMs = 10; /* wait for data */
nextState = VP880_VAB_PR_MEASURE;
break;
}
case VP880_VAB_PR_MEASURE: {
int16 *pVocRev = &pLineObj->calLineData.typeData.vocData.vocRev;
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("Cal State VP880_VAB_PR_MEASURE"));
if ( !GetXData(pLineCtx, deviceId, ecVal, pVocRev)) {
*pCalTimerMs = 10;
nextState = VP880_VAB_PR_MEASURE;
} else {
runAnotherState = TRUE;
nextState = VP880_VAB_PR_ADC_OFFSET_SETUP;
}
break;
}
/***********************************************************************
* Measure VAB ADC offset in polrev -
*
* These two states setup and measure the ADC Tip to Ring voltage in
* polrev.
**********************************************************************/
case VP880_VAB_PR_ADC_OFFSET_SETUP: {
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("Cal State VP880_VAB_PR_ADC_OFFSET_SETUP"));
/* Disconnect tip and ring sense - start feed collapse */
pLineObj->icr6Values[0] = 0x00;
pLineObj->icr6Values[1] = (VP880_C_RING_SNS_CUT | VP880_C_TIP_SNS_CUT);
mpiIndex = VpCSLACBuildMpiBuffer(mpiIndex, mpiBuffer,
VP880_ICR6_WRT, VP880_ICR6_LEN, pLineObj->icr6Values);
/* set the converter config register to measure Metallic DC Voltage */
SetAdc(pLineCtx, deviceId, ecVal, VP880_METALLIC_DC_V);
*pCalTimerMs = 10; /* wait for data */
nextState = VP880_VAB_PR_ADC_OFFSET_MEASURE;
break;
}
case VP880_VAB_PR_ADC_OFFSET_MEASURE: {
int16 temp = 0;
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("Cal State VP880_VAB_PR_ADC_OFFSET_MEASURE"));
if ( !GetXData(pLineCtx, deviceId, ecVal, &temp)) {
*pCalTimerMs = 10;
nextState = VP880_VAB_PR_ADC_OFFSET_MEASURE;
} else {
pDevObj->vp880SysCalData.vocOffset[channelId][VP880_REV_POLARITY] = temp;
runAnotherState = TRUE;
nextState = VP880_VA_PR_ADC_OFFSET_SETUP;
}
break;
}
/***********************************************************************
* Measure VA ADC offset in polrev
*
* These two states setup and measure the ADC Tip to Gnd voltage
* offset in normal polarity.
**********************************************************************/
case VP880_VA_PR_ADC_OFFSET_SETUP: {
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("Cal State VP880_VA_PR_ADC_OFFSET_SETUP"));
/* set the converter config register to measure Tip DC Voltage */
SetAdc(pLineCtx, deviceId, ecVal, VP880_TIP_TO_GND_V);
*pCalTimerMs = 10; /* wait for data */
nextState = VP880_VA_PR_ADC_OFFSET_MEASURE;
break;
}
case VP880_VA_PR_ADC_OFFSET_MEASURE: {
int16 temp = 0;
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("Cal State VP880_VA_PR_ADC_OFFSET_MEASURE"));
if ( !GetXData(pLineCtx, deviceId, ecVal, &temp)) {
*pCalTimerMs = 10;
nextState = VP880_VA_PR_ADC_OFFSET_MEASURE;
} else {
/* compensate for the static offset of 1.5V on 880*/
pDevObj->vp880SysCalData.vagOffsetRev[channelId] = temp + 205;
runAnotherState = TRUE;
nextState = VP880_VB_PR_ADC_OFFSET_SETUP;
}
break;
}
/***********************************************************************
* Measure VB ADC offset in polrev
*
* These two states setup and measure the ADC RING to Gnd voltage
* offset in normal polarity.
**********************************************************************/
case VP880_VB_PR_ADC_OFFSET_SETUP: {
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("Cal State VP880_VB_PR_ADC_OFFSET_SETUP"));
/* set the converter config register to measure Ring DC Voltage */
SetAdc(pLineCtx, deviceId, ecVal, VP880_RING_TO_GND_V);
*pCalTimerMs = 10; /* wait for data */
nextState = VP880_VB_PR_ADC_OFFSET_MEASURE;
break;
}
case VP880_VB_PR_ADC_OFFSET_MEASURE: {
int16 temp = 0;
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("Cal State VP880_VB_PR_ADC_OFFSET_MEASURE"));
if ( !GetXData(pLineCtx, deviceId, ecVal, &temp)) {
*pCalTimerMs = 10;
nextState = VP880_VB_PR_ADC_OFFSET_MEASURE;
} else {
/* compensate for the static offset of 1.5V on 880*/
pDevObj->vp880SysCalData.vbgOffsetRev[channelId] = temp + 205;
runAnotherState = TRUE;
nextState = VP880_COLLAPSE_FEED;
}
break;
}
/***********************************************************************
* Collapse Feed
*
* This state collapses tip and ring and switches to normal polarity.
* This is done with the tip/ring sense cut to prevent a transient.
*
* We are also preparing the siggen A for calibration test.
**********************************************************************/
case VP880_COLLAPSE_FEED: {
/* Sig Gen A cal setup */
uint8 sigGenA[VP880_SIGA_PARAMS_LEN] =
{0x00, 0x00, 0x00, 0x0A, 0xAB, 0x00, 0x02, 0x00, 0x00 ,0x00, 0x00};
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("Cal State VP880_COLLAPSE_FEED"));
/* Disable VOC DAC */
pLineObj->icr2Values[0] |= 0x20;
pLineObj->icr2Values[1] &= ~0x20;
mpiIndex = VpCSLACBuildMpiBuffer(mpiIndex, mpiBuffer,
VP880_ICR2_WRT, VP880_ICR2_LEN, pLineObj->icr2Values);
/* Re-Enable tip and ring sense */
pLineObj->icr6Values[0] = 0x00;
pLineObj->icr6Values[1] = 0x00;
mpiIndex = VpCSLACBuildMpiBuffer(mpiIndex, mpiBuffer,
VP880_ICR6_WRT, VP880_ICR6_LEN, pLineObj->icr6Values);
/* switch to normal polarity */
pLineObj->slicValueCache &= ~VP880_SS_POLARITY_MASK;
VpMpiCmdWrapper(deviceId, ecVal, VP880_SYS_STATE_WRT,
VP880_SYS_STATE_LEN, &pLineObj->slicValueCache);
/*
* set the sig gen with 0 bias, almost no amplitude and
* 1000Hz use for ring offset
*/
mpiIndex = VpCSLACBuildMpiBuffer(mpiIndex, mpiBuffer,
VP880_SIGA_PARAMS_WRT, VP880_SIGA_PARAMS_LEN, sigGenA);
*pCalTimerMs = 100;
nextState = VP880_GENA_NP_OFFSET_SETUP;
break;
}
/***********************************************************************
* Measure SIGGEN A offset -
*
* These states setup and measure the offset in the signal generator
**********************************************************************/
case VP880_GENA_NP_OFFSET_SETUP: {
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("Cal State VP880_GENA_NP_OFFSET_SETUP"));
/* store the current slicState */
pLineObj->calLineData.sysState = pLineObj->slicValueCache;
/* go to ringing state */
pLineObj->slicValueCache &= ~VP880_SS_STATE_MASK;
pLineObj->slicValueCache |= VP880_SS_BALANCED_RINGING;
VpMpiCmdWrapper(deviceId, ecVal, VP880_SYS_STATE_WRT,
VP880_SYS_STATE_LEN, &pLineObj->slicValueCache);
*pCalTimerMs = 20; /* wait for ringing */
nextState = VP880_GENA_NP_OFFSET_SET_ADC;
break;
}
case VP880_GENA_NP_OFFSET_SET_ADC: {
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("Cal State VP880_GENA_NP_OFFSET_SET_ADC"));
/* set the converter config register to measure Metallic DC Voltage */
SetAdc(pLineCtx, deviceId, ecVal, VP880_METALLIC_DC_V);
*pCalTimerMs = 10; /* wait for data */
nextState = VP880_GENA_NP_OFFSET_MEASURE;
break;
}
case VP880_GENA_NP_OFFSET_MEASURE: {
int16 temp = 0;
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("Cal State VP880_GENA_NP_OFFSET_MEASURE"));
if ( !GetXData(pLineCtx, deviceId, ecVal, &temp)) {
*pCalTimerMs = 10;
nextState = VP880_GENA_NP_OFFSET_MEASURE;
} else {
/* no need to measure offet in rev polrity */
pDevObj->vp880SysCalData.sigGenAError[channelId][VP880_NORM_POLARITY] = temp;
/*
* we must get the slic out of ringing before restoring
* siggen A or risk catching some of the ring cycle
* and pinging a phone.
*/
pLineObj->slicValueCache = pLineObj->calLineData.sysState;
VpMpiCmdWrapper(deviceId, ecVal, VP880_SYS_STATE_WRT,
VP880_SYS_STATE_LEN, &pLineObj->slicValueCache);
*pCalTimerMs = 10;
nextState = VP880_GENA_NP_OFFSET_RESTORE;
}
break;
}
case VP880_GENA_NP_OFFSET_RESTORE: {
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("Cal State VP880_GENA_NP_OFFSET_RESTORE"));
/* restore the siggen A register */
VpMpiCmdWrapper(deviceId, ecVal, VP880_SIGA_PARAMS_WRT,
VP880_SIGA_PARAMS_LEN, pLineObj->calLineData.sigGenA);
*pCalTimerMs = 30; /* give the device time to get out of ringing */
nextState = VP880_ILG_OFFSET_SETUP;
break;
}
/***********************************************************************
* Measure ILG offset -
*
* These two states setup and measure ILG offset in normal polarity.
* This measurement is take with tip/ring collapsed and sense enabled
**********************************************************************/
case VP880_ILG_OFFSET_SETUP: {
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("Cal State VP880_ILG_OFFSET_SETUP"));
/* set the converter config register to measure Logitudinal Current */
SetAdc(pLineCtx, deviceId, ecVal, VP880_LONGITUDINAL_DC_I);
*pCalTimerMs = 10; /* wait for data */
nextState = VP880_ILG_OFFSET_MEASURE;
break;
}
case VP880_ILG_OFFSET_MEASURE: {
int16 temp = 0;
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("Cal State VP880_ILG_OFFSET_MEASURE"));
if ( !GetXData(pLineCtx, deviceId, ecVal, &temp)) {
*pCalTimerMs = 10;
nextState = VP880_ILG_OFFSET_MEASURE;
} else {
pDevObj->vp880SysCalData.ilgOffsetNorm[channelId] = temp;
runAnotherState = TRUE;
nextState = VP880_ILA_OFFSET_SETUP;
}
break;
}
/***********************************************************************
* Measure ILA offset -
*
* These two states setup and measure ILA offset in normal polarity.
* This measurement is take with tip/ring collapsed and sense enabled
**********************************************************************/
case VP880_ILA_OFFSET_SETUP: {
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("Cal State VP880_ILA_OFFSET_SETUP"));
/* set the converter config register to measure Metallic DC Current */
SetAdc(pLineCtx, deviceId, ecVal, VP880_METALLIC_DC_I);
*pCalTimerMs = 10; /* wait for data */
nextState = VP880_ILA_OFFSET_MEASURE;
break;
}
case VP880_ILA_OFFSET_MEASURE: {
int16 temp = 0;
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("Cal State VP880_ILA_OFFSET_MEASURE"));
if ( !GetXData(pLineCtx, deviceId, ecVal, &temp)) {
*pCalTimerMs = 10;
nextState = VP880_ILA_OFFSET_MEASURE;
} else {
pDevObj->vp880SysCalData.ilaOffsetNorm[channelId] = temp;
runAnotherState = TRUE;
nextState = VP880_RESTORE_DAC;
}
break;
}
/***********************************************************************
* Restore Feed
*
* This state restores the DC Feed to the reference dc
* profile value and reenables the DAC while in normal polarity.
*
* Additionally, this state will disable tip/ring
* sense for future offset measurements in normal polarity.
**********************************************************************/
case VP880_RESTORE_DAC: {
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("Cal State VP880_RESTORE_DAC"));
/* Store the ref dcfeed from profile into normal cal dcfeed */
VpMemCpy(pLineObj->calLineData.dcFeed, pLineObj->calLineData.dcFeedRef,
VP880_DC_FEED_LEN);
#ifdef VP880_TRACKER_SUPPORT
if (!(pDevObj->stateInt & VP880_IS_ABS)) {
/* we want to start with a 3.0V VAS for tracker */
pLineObj->calLineData.dcFeed[0] &= 0xFC;
pLineObj->calLineData.dcFeed[1] &= 0x3F;
}
#endif
mpiIndex = VpCSLACBuildMpiBuffer(mpiIndex, mpiBuffer,
VP880_DC_FEED_WRT, VP880_DC_FEED_LEN, pLineObj->calLineData.dcFeed);
/* Enable VOC DAC */
pLineObj->icr2Values[0] &= ~0x20;
mpiIndex = VpCSLACBuildMpiBuffer(mpiIndex, mpiBuffer,
VP880_ICR2_WRT, VP880_ICR2_LEN, pLineObj->icr2Values);
/* disable tip and ring sense */
pLineObj->icr6Values[0] = 0x00;
pLineObj->icr6Values[1] = (VP880_C_RING_SNS_CUT | VP880_C_TIP_SNS_CUT);
mpiIndex = VpCSLACBuildMpiBuffer(mpiIndex, mpiBuffer,
VP880_ICR6_WRT, VP880_ICR6_LEN, pLineObj->icr6Values);
runAnotherState = TRUE;
nextState = VP880_VAB_NP_ADC_OFFSET_SETUP;
break;
}
/***********************************************************************
* Measure VAB ADC offset in normal polarity -
*
* These two states setup and measure ADC Tip to RING voltage offset in
* normal polarity.
**********************************************************************/
case VP880_VAB_NP_ADC_OFFSET_SETUP: {
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("Cal State VP880_VAB_NP_ADC_OFFSET_SETUP"));
/* set the converter config register to measure Metallic DC Voltage */
SetAdc(pLineCtx, deviceId, ecVal, VP880_METALLIC_DC_V);
*pCalTimerMs = 10; /* wait for data */
nextState = VP880_VAB_NP_ADC_OFFSET_MEASURE;
break;
}
case VP880_VAB_NP_ADC_OFFSET_MEASURE: {
int16 temp = 0;
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("Cal State VP880_VAB_NP_ADC_OFFSET_MEASURE"));
if ( !GetXData(pLineCtx, deviceId, ecVal, &temp)) {
*pCalTimerMs = 10;
nextState = VP880_VAB_NP_ADC_OFFSET_MEASURE;
} else {
pDevObj->vp880SysCalData.vocOffset[channelId][VP880_NORM_POLARITY] = temp;
runAnotherState = TRUE;
nextState = VP880_VA_NP_ADC_OFFSET_SETUP;
}
break;
}
/***********************************************************************
* Measure VA ADC offset in normal polarity
*
* These two states setup and measure the ADC Tip to Gnd voltage
* offset in normal polarity.
**********************************************************************/
case VP880_VA_NP_ADC_OFFSET_SETUP: {
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("Cal State VP880_VA_NP_ADC_OFFSET_SETUP"));
/* set the converter config register to measure Tip DC Voltage */
SetAdc(pLineCtx, deviceId, ecVal, VP880_TIP_TO_GND_V);
*pCalTimerMs = 10; /* wait for data */
nextState = VP880_VA_NP_ADC_OFFSET_MEASURE;
break;
}
case VP880_VA_NP_ADC_OFFSET_MEASURE: {
int16 temp = 0;
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("Cal State VP880_VA_NP_ADC_OFFSET_MEASURE"));
if ( !GetXData(pLineCtx, deviceId, ecVal, &temp)) {
*pCalTimerMs = 10;
nextState = VP880_VA_NP_ADC_OFFSET_MEASURE;
} else {
/* compensate for the static offset of 1.5V on 880*/
pDevObj->vp880SysCalData.vagOffsetNorm[channelId] = temp + 205;
runAnotherState = TRUE;
nextState = VP880_VB_NP_ADC_OFFSET_SETUP;
}
break;
}
/***********************************************************************
* Measure VB ADC offset in normal polarity
*
* These two states setup and measure the ADC RING to Gnd voltage
* offset in normal polarity.
**********************************************************************/
case VP880_VB_NP_ADC_OFFSET_SETUP: {
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("Cal State VP880_VB_NP_ADC_OFFSET_SETUP"));
/* set the converter config register to measure Ring DC Voltage */
SetAdc(pLineCtx, deviceId, ecVal, VP880_RING_TO_GND_V);
*pCalTimerMs = 10; /* wait for data */
nextState = VP880_VB_NP_ADC_OFFSET_MEASURE;
break;
}
case VP880_VB_NP_ADC_OFFSET_MEASURE: {
int16 temp = 0;
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("Cal State VP880_VB_NP_ADC_OFFSET_MEASURE"));
if ( !GetXData(pLineCtx, deviceId, ecVal, &temp)) {
*pCalTimerMs = 10;
nextState = VP880_VB_NP_ADC_OFFSET_MEASURE;
} else {
/* compensate for the static offset of 1.5V on 880*/
pDevObj->vp880SysCalData.vbgOffsetNorm[channelId] = temp + 205;
runAnotherState = TRUE;
nextState = VP880_ILA_SETUP;
}
break;
}
/***********************************************************************
* Measure ILA at 4 different values -
*
* These xyz states setup and measure ILA offset in normal polarity
* at 4 different ILA settings (20, 25, 32 and 40mA).
**********************************************************************/
case VP880_ILA_SETUP: {
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("Cal State VP880_ILA_SETUP"));
/* prepare storage data */
pLineObj->calLineData.typeData.loopData.loopNum = 0;
pLineObj->calLineData.typeData.loopData.prevVal = 0;
pLineObj->calLineData.minVas = 0;
runAnotherState = TRUE;
nextState = VP880_ILA_ADJUST;
break;
}
case VP880_ILA_ADJUST: {
uint8 *pDcFeed = pLineObj->calLineData.dcFeed;
uint8 loopNum = pLineObj->calLineData.typeData.loopData.loopNum;
uint16 vasValue = VP880_VAS_CONVERSION(pDcFeed[0], pDcFeed[1]);
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("Cal State VP880_ILA_ADJUST"));
/* adjust the ila value and vas */
pDcFeed[1] &= ~VP880_ILA_MASK;
if (loopNum == 0) { /* 20mA */
pDcFeed[1] |= (VP880_ILA_MASK & 0x02);
vasValue = 3000;
} else if (loopNum == 1) { /* 25mA */
pDcFeed[1] |= (VP880_ILA_MASK & 0x07);
vasValue = 3750;
} else if (loopNum == 2) { /* 32mA */
pDcFeed[1] |= (VP880_ILA_MASK & 0x0E);
vasValue = 4500;
} else if (loopNum == 3) { /* 40mA */
pDcFeed[1] |= (VP880_ILA_MASK & 0x16);
vasValue = 5250;
} else {
/*
* If we're here, it's because off-hook has not yet been
* detected with VAS increments, so we have to continue past
* normal ILA calibration.
*/
vasValue += 750;
}
#ifdef VP880_TRACKER_SUPPORT
/* only adjust VAS if device is a tracking supply */
if (!(pDevObj->stateInt & VP880_IS_ABS)) {
if (vasValue < VP880_VAS_MAX) {
VpCSLACSetVas(pDcFeed, vasValue);
} else {
/* ERROR!! Cannot increase VAS. Need to move on */
pLineObj->calLineData.minVas = VP880_VAS_MAX;
runAnotherState = TRUE;
nextState = VP880_RESTORE_FEED;
}
}
#endif
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("VP880_ILA_ADJUST: Writing DC FEED 0x%02X 0x%02X", pDcFeed[0], pDcFeed[1]));
VpMpiCmdWrapper(deviceId, ecVal, VP880_DC_FEED_WRT, VP880_DC_FEED_LEN, pDcFeed);
*pCalTimerMs = 10;
nextState = VP880_ILA_SET_ADC;
break;
}
case VP880_ILA_SET_ADC: {
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("Cal State VP880_ILA_SET_ADC"));
/* set the converter config register to measure Metallic DC Current */
SetAdc(pLineCtx, deviceId, ecVal, VP880_METALLIC_DC_I);
*pCalTimerMs = 10;
nextState = VP880_ILA_MEASURE;
break;
}
case VP880_ILA_MEASURE: {
int16 temp = 0;
uint8 loopNum = pLineObj->calLineData.typeData.loopData.loopNum;
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("Cal State VP880_ILA_MEASURE"));
if ( !GetXData(pLineCtx, deviceId, ecVal, &temp)) {
*pCalTimerMs = 10;
nextState = VP880_ILA_MEASURE;
break;
}
/* store the measured ila data */
if (loopNum == 0) { /* 20mA */
pDevObj->vp880SysCalData.ila20[channelId] = temp;
} else if (loopNum == 1) { /* 25mA */
pDevObj->vp880SysCalData.ila25[channelId] = temp;
} else if (loopNum == 2) { /* 32mA */
pDevObj->vp880SysCalData.ila32[channelId] = temp;
} else if (loopNum == 3) { /* 40mA */
pDevObj->vp880SysCalData.ila40[channelId] = temp;
}
runAnotherState = TRUE;
if (!(pDevObj->stateInt & VP880_IS_ABS)) {
#ifdef VP880_TRACKER_SUPPORT
nextState = VP880_ILA_MEASURE_TRACKER;
#endif
} else {
#ifdef VP880_ABS_SUPPORT
nextState = VP880_ILA_MEASURE_ABS;
#endif
}
break;
}
case VP880_ILA_MEASURE_TRACKER: {
uint8 sigReg[VP880_NO_UL_SIGREG_LEN];
uint16 vasValue;
VpMpiCmdWrapper(deviceId, ecVal, VP880_NO_UL_SIGREG_RD,
VP880_NO_UL_SIGREG_LEN, sigReg);
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("VP880_ILA_MEASURE: SIG REG 0x%02X 0x%02X", sigReg[0], sigReg[1]));
if ((sigReg[channelId] & VP880_HOOK1_MASK) && (pLineObj->calLineData.minVas == 0)) {
vasValue = VP880_VAS_CONVERSION(
pLineObj->calLineData.dcFeed[0],
pLineObj->calLineData.dcFeed[1]);
if (vasValue < VP880_VAS_MAX) {
pLineObj->calLineData.minVas = vasValue;
} else {
pLineObj->calLineData.minVas = VP880_VAS_MAX;
}
VP_CALIBRATION(VpLineCtxType, pLineCtx, ("VP880_ILA_MEASURE: Saving Min VAS (%d)",
pLineObj->calLineData.minVas));
}
if ((pLineObj->calLineData.typeData.loopData.loopNum++ < 3)
|| (!(sigReg[channelId] & VP880_HOOK1_MASK))) {
nextState = VP880_ILA_ADJUST;
} else {
nextState = VP880_RESTORE_FEED;
}
runAnotherState = TRUE;
break;
}
case VP880_ILA_MEASURE_ABS:
if (pLineObj->calLineData.typeData.loopData.loopNum++ < 3) {
nextState = VP880_ILA_ADJUST;
} else {
nextState = VP880_RESTORE_FEED;
}
runAnotherState = TRUE;
break;
/***********************************************************************
* Restore Feed
*
* For the most part feed is already restored. All we do here is
* reenable the tip and ring sense and allow the line to settle.
**********************************************************************/
case VP880_RESTORE_FEED: {
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("Cal State VP880_RESTORE_FEED"));
/* Re-Enable tip and ring sense */
pLineObj->icr6Values[0] = 0x00;
pLineObj->icr6Values[1] = 0x00;
mpiIndex = VpCSLACBuildMpiBuffer(mpiIndex, mpiBuffer,
VP880_ICR6_WRT, VP880_ICR6_LEN, pLineObj->icr6Values);
*pCalTimerMs = 10;
nextState = VP880_IMT_NP_SETUP;
break;
}
/***********************************************************************
* Settle IMT in PolRev -
*
* These states setup, measure Metallic current until it
* settles. This is done to prevent high REN loads from distorting
* the VAS measurements
**********************************************************************/
case VP880_IMT_NP_SETUP: {
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("Cal State VP880_IMT_NP_SETUP"));
/* prepare storage data */
pLineObj->calLineData.typeData.loopData.loopNum = 0;
pLineObj->calLineData.typeData.loopData.prevVal = 0;
runAnotherState = TRUE;
nextState = VP880_IMT_NP_SET_ADC;
break;
}
case VP880_IMT_NP_SET_ADC: {
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("Cal State VP880_IMT_NP_SET_ADC"));
SetAdc(pLineCtx, deviceId, ecVal, VP880_METALLIC_DC_I);
*pCalTimerMs = 10;
nextState = VP880_IMT_NP_MEASURE;
break;
}
case VP880_IMT_NP_MEASURE: {
int16 imOld = 0;
int16 imNew = 0;
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("Cal State VP880_IMT_NP_MEASURE"));
if ( !GetXData(pLineCtx, deviceId, ecVal, &imNew)) {
*pCalTimerMs = 10;
nextState = VP880_IMT_NP_MEASURE;
break;
}
/* if this is the first imt measurement then get another */
if (pLineObj->calLineData.typeData.loopData.loopNum++ == 0) {
pLineObj->calLineData.typeData.loopData.prevVal = imNew;
*pCalTimerMs = VP880_IMT_SETTLE_MS;
nextState = VP880_IMT_NP_MEASURE;
break;
}
imOld = pLineObj->calLineData.typeData.loopData.prevVal;
/* have we settled enough or taken to long > 200ms*/
if ( (pLineObj->calLineData.typeData.loopData.loopNum < 20 /*200ms*/) &&
(((imNew + 15 - imOld) & 0xFFE0) != 0) ) {
/* nope run it again */
pLineObj->calLineData.typeData.loopData.prevVal = imNew;
*pCalTimerMs = VP880_IMT_SETTLE_MS;
nextState = VP880_IMT_NP_MEASURE;
break;
}
if (!(pDevObj->stateInt & VP880_IS_ABS)) {
#ifdef VP880_TRACKER_SUPPORT
nextState = VP880_VAS_NP_SETUP;
#endif
} else {
#ifdef VP880_ABS_SUPPORT
nextState = VP880_VAB_NP_SETUP;
#endif
}
runAnotherState = TRUE;
break;
}
#ifdef VP880_TRACKER_SUPPORT
/***********************************************************************
* Measure VAS in Normal Polarity -
*
* These five states step through VAS values and measure IMT.
* The VAS adjustment portion of this process will continue until:
* VAS >= 14.25V ||
* new IMT < 10mA && (new IMT - old IMT are with in +9 to -7mA)
*
* If VAS reaches 14.25, proceed to Battery Adjustments.
**********************************************************************/
case VP880_VAS_NP_SETUP: {
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("Cal State VP880_VAS_NP_SETUP"));
/* prepare storage data */
pLineObj->calLineData.typeData.loopData.loopNum = 0;
pLineObj->calLineData.typeData.loopData.prevVal = 0;
pLineObj->calLineData.vasStart = 3000;
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("VP880_VAS_NP_SETUP: Best Actual VAS Start %d",
pLineObj->calLineData.vasStart));
runAnotherState = TRUE;
nextState = VP880_VAS_NP_STEP;
break;
}
case VP880_VAS_NP_STEP: {
uint8 loopNum = pLineObj->calLineData.typeData.loopData.loopNum;
uint16 vasVal = pLineObj->calLineData.vasStart + (750 * loopNum);
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("Cal State VP880_VAS_NP_STEP"));
/* If the calculated VAS is max, we need to move to battery steps */
if (vasVal > VP880_VAS_MAX) {
runAnotherState = TRUE;
nextState = VP880_VAS_NP_STORE;
break;
}
/* set VAS to the next value */
VpCSLACSetVas(pLineObj->calLineData.dcFeed, vasVal);
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("VP880_VAS_NP_STEP: Setting VAS (%d) with Values 0x%02X 0x%02X at time %d",
vasVal,
pLineObj->calLineData.dcFeed[0], pLineObj->calLineData.dcFeed[1],
pDevObj->timeStamp));
mpiIndex = VpCSLACBuildMpiBuffer(mpiIndex, mpiBuffer,
VP880_DC_FEED_WRT, VP880_DC_FEED_LEN, pLineObj->calLineData.dcFeed);
/* dcfeed takes 100ms to settle after each step be very carefull adjusting this */
*pCalTimerMs = VP880_DCFEED_SETTLE_MS;
nextState = VP880_VAS_NP_SET_ADC;
break;
}
case VP880_VAS_NP_SET_ADC: {
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("Cal State VP880_VAS_NP_SET_ADC"));
/* set the converter config register to measure Metallic DC Current */
SetAdc(pLineCtx, deviceId, ecVal, VP880_METALLIC_DC_I);
*pCalTimerMs = 10;
nextState = VP880_VAS_NP_MEASURE;
break;
}
case VP880_VAS_NP_MEASURE: {
int16 imtOld = pLineObj->calLineData.typeData.loopData.prevVal;
int16 imtNew = 0;
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("Cal State VP880_VAS_NP_MEASURE"));
if ( !GetXData(pLineCtx, deviceId, ecVal, &imtNew)) {
*pCalTimerMs = 10;
nextState = VP880_VAS_NP_MEASURE;
break;
}
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("VP880_VAS_NP_MEASURE: IMT Old %d IMT New %d",
imtOld, imtNew));
runAnotherState = TRUE;
if (pLineObj->calLineData.typeData.loopData.loopNum++ == 0) {
/* if this is the first imt measurement then get another */
nextState = VP880_VAS_NP_STEP;
} else if ((imtNew > VP880_IMT_10MA) ||
(((imtOld + 15 - imtNew) & 0xFFE0) != 0) ) {
/*
* if the measured value is greater than 10 mA or the difference
* between old and new values are greater +9/-7 then get another
*/
nextState = VP880_VAS_NP_STEP;
} else {
/* if there is nothing left then store the data */
nextState = VP880_VAS_NP_STORE;
}
/* replace the old with the new */
pLineObj->calLineData.typeData.loopData.prevVal = imtNew;
break;
}
case VP880_VAS_NP_STORE: {
uint16 vasVal;
uint8 dcFeed[VP880_DC_FEED_LEN];
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("Cal State VP880_VAS_NP_STORE"));
/* Compute final VAS Values */
VpMpiCmdWrapper(deviceId, ecVal, VP880_DC_FEED_RD, VP880_DC_FEED_LEN, dcFeed);
vasVal = VP880_VAS_CONVERSION(dcFeed[0], dcFeed[1]);
/*
* This function will determine if VAS is at max, and if so then
* increase Battery correction by the overhead amount.
*/
ComputeFinalVas(pLineCtx, &vasVal);
/*
* Set VAS to the final value. Note that this is NOT redundant from
* the previous read because VAS can actually be reduced. It is
* the case when VAS reaches max and a battery adjustment increases
* such that the total VAS_MAX + battery_adjust_actual is > the
* required VAS + Overhead. This occurs due to differences in step
* sizes betwen battery adjustment and VAS.
*
* Make sure VAS is not set below minimum determined from Battery
* Saturation Detection algorithm.
*/
if (vasVal < pLineObj->calLineData.minVas) {
vasVal = pLineObj->calLineData.minVas;
}
VpCSLACSetVas(pLineObj->calLineData.dcFeed, vasVal);
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("VP880_VAS_NP_STORE: Setting VAS (%d) with Final Values 0x%02X 0x%02X at time %d",
vasVal,
pLineObj->calLineData.dcFeed[0], pLineObj->calLineData.dcFeed[1],
pDevObj->timeStamp));
mpiIndex = VpCSLACBuildMpiBuffer(mpiIndex, mpiBuffer,
VP880_DC_FEED_WRT, VP880_DC_FEED_LEN, pLineObj->calLineData.dcFeed);
/* Second byte contains the lower two bits of VAS */
pDevObj->vp880SysCalData.vas[channelId][VP880_NORM_POLARITY] =
((pLineObj->calLineData.dcFeed[1] >> 6) & 0x3);
/* First byte contains the upper two bits of VAS */
pDevObj->vp880SysCalData.vas[channelId][VP880_NORM_POLARITY] |=
((pLineObj->calLineData.dcFeed[0] << 2) & 0xC);
/*
* Make sure Reverse Polarity VAS is not set below minimum
* determined from Battery Saturation Detection algorithm.
*/
vasVal = VP880_VAS_CONVERSION(pLineObj->calLineData.dcFeedPr[0],
pLineObj->calLineData.dcFeedPr[1]);
if (vasVal < pLineObj->calLineData.minVas) {
VpCSLACSetVas(pLineObj->calLineData.dcFeedPr,
pLineObj->calLineData.minVas);
/* Second byte contains the lower two bits of VAS */
pDevObj->vp880SysCalData.vas[channelId][VP880_REV_POLARITY] =
((pLineObj->calLineData.dcFeedPr[1] >> 6) & 0x3);
/* First byte contains the upper two bits of VAS */
pDevObj->vp880SysCalData.vas[channelId][VP880_REV_POLARITY] |=
((pLineObj->calLineData.dcFeedPr[0] << 2) & 0xC);
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("VP880_VAS_NP_STORE: PolRev VAS below minVas (%d) - correcting VAS (%d) with Final Values 0x%02X 0x%02X at time %d",
pLineObj->calLineData.minVas, vasVal,
pLineObj->calLineData.dcFeedPr[0], pLineObj->calLineData.dcFeedPr[1],
pDevObj->timeStamp));
}
runAnotherState = TRUE;
nextState = VP880_VAB_NP_SETUP;
break;
}
#endif
/***********************************************************************
* Measure VAB (VOC) in normal polarity -
*
* These two states setup and measure the VAB (VOC) value in normal pol.
**********************************************************************/
case VP880_VAB_NP_SETUP: {
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("Cal State VP880_VAB_NP_SETUP"));
/* set the converter config register to measure Metallic DC Voltage */
SetAdc(pLineCtx, deviceId, ecVal, VP880_METALLIC_DC_V);
*pCalTimerMs = 10; /* wait for data */
nextState = VP880_VAB_NP_MEASURE;
break;
}
case VP880_VAB_NP_MEASURE: {
int16 temp = 0;
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("Cal State VP880_VAB_NP_MEASURE"));
if ( !GetXData(pLineCtx, deviceId, ecVal, &temp)) {
*pCalTimerMs = 10;
nextState = VP880_VAB_NP_MEASURE;
} else {
pLineObj->calLineData.typeData.vocData.vocNorm = temp;
runAnotherState = TRUE;
nextState = VP880_CAL_ADJUST;
}
break;
}
/***********************************************************************
* This state is used to perform calcualtions
**********************************************************************/
case VP880_CAL_ADJUST: {
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("Cal State VP880_CAL_ADJUST"));
/* Set VOC to the device profile value */
Vp880AdjustVoc(pLineCtx, ((pLineObj->calLineData.dcFeedRef[0] >> 2) & 0x7), FALSE);
/* Set ILA to the device profile value */
Vp880AdjustIla(pLineCtx, (pLineObj->calLineData.dcFeedRef[1] & VP880_ILA_MASK));
runAnotherState = TRUE;
nextState = VP880_CAL_RESTORE;
break;
}
/***********************************************************************
* This state is used to restore registers and clean up after cal
**********************************************************************/
case VP880_CAL_RESTORE: {
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("Cal State VP880_CAL_RESTORE"));
/* Restore Device Mode */
pDevObj->devMode[0] |= VP880_DEV_MODE_TEST_DATA;
mpiIndex = VpCSLACBuildMpiBuffer(mpiIndex, mpiBuffer,
VP880_DEV_MODE_WRT, VP880_DEV_MODE_LEN, pDevObj->devMode);
/* Restore Loop Supervision */
mpiIndex = VpCSLACBuildMpiBuffer(mpiIndex, mpiBuffer,
VP880_LOOP_SUP_WRT, VP880_LOOP_SUP_LEN, pLineObj->calLineData.loopSup);
/* Restore Codec Mode */
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("VP880_CAL_RESTORE: Writing 0x%02X to Operating Functions",
pLineObj->calLineData.codecReg));
mpiIndex = VpCSLACBuildMpiBuffer(mpiIndex, mpiBuffer,
VP880_OP_FUNC_WRT, VP880_OP_FUNC_LEN, &pLineObj->calLineData.codecReg);
/* Restore TX/RX PCM and enable HPF */
pLineObj->opCond[0] = (VP880_CUT_TXPATH | VP880_CUT_RXPATH);
mpiIndex = VpCSLACBuildMpiBuffer(mpiIndex, mpiBuffer,
VP880_OP_COND_WRT, VP880_OP_COND_LEN, pLineObj->opCond);
/* Restore disn */
mpiIndex = VpCSLACBuildMpiBuffer(mpiIndex, mpiBuffer,
VP880_DISN_WRT, VP880_DISN_LEN, pLineObj->calLineData.disnVal);
/* Restore vpGain */
mpiIndex = VpCSLACBuildMpiBuffer(mpiIndex, mpiBuffer,
VP880_VP_GAIN_WRT, VP880_VP_GAIN_LEN, pLineObj->calLineData.vpGain);
/* Restore ICR2 */
mpiIndex = VpCSLACBuildMpiBuffer(mpiIndex, mpiBuffer,
VP880_ICR2_WRT, VP880_ICR2_LEN, pLineObj->calLineData.icr2);
VpMemCpy(pLineObj->icr2Values, pLineObj->calLineData.icr2, VP880_ICR2_LEN);
/* Restore ICR3 */
mpiIndex = VpCSLACBuildMpiBuffer(mpiIndex, mpiBuffer,
VP880_ICR3_WRT, VP880_ICR3_LEN, pLineObj->calLineData.icr3);
VpMemCpy(pLineObj->icr3Values, pLineObj->calLineData.icr3, VP880_ICR2_LEN);
/*
* Restore Line State (note: this won't correctly update the
* calibrated DC feed settings because we're still in calibration.
* So we have to do that manually)
*/
Vp880SetLineState(pLineCtx, pLineObj->lineState.usrCurrent);
if (pLineObj->calLineData.reversePol) {
/* write polrev dcfeed here */
mpiIndex = VpCSLACBuildMpiBuffer(mpiIndex, mpiBuffer,
VP880_DC_FEED_WRT, VP880_DC_FEED_LEN, pLineObj->calLineData.dcFeedPr);
} else {
/* write normal dcfeed here */
mpiIndex = VpCSLACBuildMpiBuffer(mpiIndex, mpiBuffer,
VP880_DC_FEED_WRT, VP880_DC_FEED_LEN, pLineObj->calLineData.dcFeed);
}
Vp880LLSetSysState(deviceId, pLineCtx, 0, FALSE);
#ifdef VP880_LP_SUPPORT
/* Force an update on the line */
Vp880LowPowerMode(pDevCtx);
#endif
break;
}
default:
VP_CALIBRATION(VpLineCtxType, pLineCtx,("Cal Error - Bad State jumping to DONE"));
pLineObj->calLineData.calLineState = VP880_CAL_RESTORE;
runAnotherState = TRUE;
pDevObj->responseData = VP_CAL_FAILURE;
break;
}
/* write down any data required by a state */
if (mpiIndex > 0) {
VpMpiCmdWrapper(deviceId, ecVal, mpiBuffer[0],
mpiIndex-1, &mpiBuffer[1]);
}
pLineObj->calLineData.calLineState = nextState;
return runAnotherState;
}
#ifdef VP880_TRACKER_SUPPORT
/*
* ComputeFinalVas()
* This function computes the final VAS value based on converged VAS and
* overhead. If the result exceeds silicon capabilities, the battery is
* adjusted and the new value saved to the device object error value. This
* value is directly used for Battery Settings and provided in the calibration
* profile (see VpCal(VP_CAL_GET_SYSTEM_COEFFF)).
*/
void
ComputeFinalVas(
VpLineCtxType *pLineCtx,
uint16 *vasValue)
{
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("ComputeFinalVas: Adding Overhead (%d) to base VAS Value (%d)",
VP880_VAS_OVERHEAD, *vasValue));
/*
* Apply known adjustments JUST to the computed VAS Value. This result does
* not need (yet) to correspond to a programmable value.
*/
*vasValue += VP880_VAS_OVERHEAD;
/*
* Determine if a battery adjustment is necessary just based on the required
* vas value exceeding programmable limits.
*/
if (*vasValue > VP880_VAS_MAX) {
Vp880LineObjectType *pLineObj = pLineCtx->pLineObj;
VpDevCtxType *pDevCtx = pLineCtx->pDevCtx;
Vp880DeviceObjectType *pDevObj = pDevCtx->pDevObj;
uint8 channelId = pLineObj->channelId; /* Used several times... */
int32 newTarget;
int16 targetCalVoltage, batteryCorrection, batteryOverage;
/*
* VAS and Battery Adjustments are in two different scales. This will
* require fixing one (VAS) and round up (Batttery Adjustment). It may
* give an overall lower VAS+Battery by rounding VAS because VAS is in
* lower steps, but the Battery needs to be minimized.
*
* Remove the maximum VAS setting and round the remaining to the nearest
* available battery step.
*/
batteryCorrection = (*vasValue - VP880_VAS_MAX);
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("ComputeFinalVas: Raw Battery Correction: %d",
batteryCorrection));
/* Convert the current setting into scale of 1mv */
targetCalVoltage = pDevObj->vp880SysCalData.abvError[0] * 10;
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("ComputeFinalVas: Target Cal Voltage (%d) mV from Cal Profile: (%d)",
targetCalVoltage, pDevObj->vp880SysCalData.abvError[0]));
/* Compute the unconstrained new battery calibration target. */
newTarget = (targetCalVoltage + batteryCorrection);
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("ComputeFinalVas: Current Battery Calibration %d New Target Theory %ld",
targetCalVoltage, newTarget));
/*
* At this point, the battery calibration target computed may not be
* programmable in the silicon. Round up and limit to the max setting.
* Keep track of the overage being programmed because we'll want to reduce
* VAS by this amount or as close as possible without going too low.
*/
batteryOverage = (VP880_BAT_CAL_STEP - (newTarget % VP880_BAT_CAL_STEP));
newTarget += batteryOverage;
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("ComputeFinalVas: Rounded Battery Correction: %ld", newTarget));
/*
* In case we can't adjust the battery enough to match the theoretical
* requirement, limit to max and disable VAS reduction.
*/
if (newTarget > VP880_BAT_CAL_MAX) {
newTarget = VP880_BAT_CAL_MAX;
batteryOverage = 0;
}
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("ComputeFinalVas: Final Battery Correction: %ld", newTarget));
/*
* The value is now in a programmable range, but does not correspond to
* the error scale from the calibration profile and stored in the device
* object. That is in 10mV, this is 10x greater than that.
*/
newTarget /= 10;
/*
* Make sure the value we just computed is NOT lower than the value
* previously computed. This can occur during VAS calibration due to
* differences in polarity.
*/
if (newTarget > pDevObj->vp880SysCalData.abvError[channelId]) {
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("ComputeFinalVas: Modifying Current ABV Error from %d to %d on Channel %d",
pDevObj->vp880SysCalData.abvError[channelId], (int16)newTarget, channelId));
pDevObj->vp880SysCalData.abvError[channelId] = (int16)newTarget;
/*
* Write to the silicon - make sure Wideband Mode Bit IF set is
* disabled for this write. It shouldn't occur, but be 100% sure
*/
Vp880BatteryCalAdjust(pDevObj, (pLineObj->ecVal & VP880_EC_BITS_MASK));
}
/*
* Don't forget that the pointer provided needs to correspond to the
* final VAS value being programmed. Reduce by as much as possible
* without reducing by more than theoretical.
*/
*vasValue = VP880_VAS_MAX
- (batteryOverage - (batteryOverage % VP880_VAS_STEP));
}
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("ComputeFinalVas: Overhead %d => rounded off final VAS %d",
VP880_VAS_OVERHEAD, *vasValue));
return;
}
#endif
static void
SetAdc(
VpLineCtxType *pLineCtx,
VpDeviceIdType deviceId,
uint8 ecVal,
uint8 adcRoute)
{
Vp880LineObjectType *pLineObj = pLineCtx->pLineObj;
uint8 adcConfig;
VpMpiCmdWrapper(deviceId, ecVal, VP880_CONV_CFG_RD,
VP880_CONV_CFG_LEN, &adcConfig);
/* set the adc requested measurement do not adjust the sample rate */
adcConfig = (adcConfig & ~VP880_CONV_CONNECT_BITS) | adcRoute;
/* adcConfig = adcRoute; */
VpMpiCmdWrapper(deviceId, ecVal, VP880_CONV_CFG_WRT,
VP880_CONV_CFG_LEN, &adcConfig);
/* store the currently requested ADC route */
pLineObj->calLineData.typeData.loopData.adcRoute = adcRoute;
/* reset the adcLoopCounter to 0*/
pLineObj->calLineData.typeData.loopData.adcLoopMax = 0;
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("INFO: setting ADC to 0x%02x", adcRoute));
return;
}
static bool
GetXData(
VpLineCtxType *pLineCtx,
VpDeviceIdType deviceId,
uint8 ecVal,
int16 *pData)
{
Vp880LineObjectType *pLineObj = pLineCtx->pLineObj;
uint8 *adcLoopMax = &pLineObj->calLineData.typeData.loopData.adcLoopMax;
uint8 reqAdcRoute = pLineObj->calLineData.typeData.loopData.adcRoute;
uint8 currentAdc;
VpMpiCmdWrapper(deviceId, ecVal, VP880_CONV_CFG_RD,
VP880_CONV_CFG_LEN, &currentAdc);
if ((currentAdc & 0xF) == reqAdcRoute) {
/*
* if the ADC is still set to what we want it to
* requested setting then take the measurement.
*/
uint8 xdata[2];
VpMpiCmdWrapper(deviceId, ecVal, VP880_TX_PCM_DATA_RD,
VP880_TX_PCM_DATA_LEN, xdata);
*pData = ( (((int16)xdata[0] << 8) & 0xFF00) | ((int16)xdata[1] & 0x00FF) );
return TRUE;
} else if ((*adcLoopMax)++ < 10) {
/*
* if the ADC is not correct but we have not exceeded
* our loopcount, then set it again and get out.
*/
uint8 adcAgain = (currentAdc & ~VP880_CONV_CONNECT_BITS) | reqAdcRoute;
VpMpiCmdWrapper(deviceId, ecVal, VP880_CONV_CFG_WRT,
VP880_CONV_CFG_LEN, &adcAgain);
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("WARNING: ADC route set to 0x%02X, trying for 0x%02x",
(currentAdc & 0x0F), reqAdcRoute));
return FALSE;
}
/*
* if the adc is still not right but we have
* exceeded our loop count then just move on
* and print a debug error.
*/
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("ERROR: unable to set ADC to %i after 10 attempts.. moving on", reqAdcRoute));
return TRUE;
}
/**
* Vp880AdcSettling() -- Tracker and ABS Function
* This function read ADC/PCM and set the converter register
*
* Preconditions:
* The device and line context must be created and initialized before calling
* this function.
*
* Postconditions:
* This function return the value pcm red.
*/
int16
Vp880AdcSettling(
Vp880DeviceObjectType *pDevObj,
uint8 ecVal,
uint8 adcConfig,
bool *validData)
{
VpDeviceIdType deviceId = pDevObj->deviceId;
uint8 xdataTemp[VP880_TX_PCM_DATA_LEN];
int16 tempNew;
uint8 cfg[VP880_CONV_CFG_LEN];
VP_API_FUNC_INT(None, VP_NULL, ("Vp880AdcSettling+"));
/*
* If the device mode was changed (by other channel), need to change it back
* so data can be taken.
*/
if ((pDevObj->staticInfo.rcnPcn[VP880_RCN_LOCATION] > VP880_REV_VC) &&
(pDevObj->devMode[0] & VP880_DEV_MODE_TEST_DATA)) {
pDevObj->devMode[0] &= ~(VP880_DEV_MODE_TEST_DATA);
VpMpiCmdWrapper(deviceId, ecVal, VP880_DEV_MODE_WRT, VP880_DEV_MODE_LEN,
pDevObj->devMode);
}
if (validData != VP_NULL) {
VpMpiCmdWrapper(deviceId, ecVal, VP880_CONV_CFG_RD, VP880_CONV_CFG_LEN, cfg);
if (cfg[0] != adcConfig) {
*validData = FALSE;
VP_CALIBRATION(None, NULL,("Vp880AdcSettling() - CONVERTER FAIL (0x%02X -> should be 0x%02X) on ecVal 0x%02X",
cfg[0], adcConfig, ecVal));
VpMpiCmdWrapper(deviceId, ecVal, VP880_CONV_CFG_WRT,
VP880_CONV_CFG_LEN, &adcConfig);
} else {
*validData = TRUE;
}
}
VpMpiCmdWrapper(deviceId, ecVal, VP880_TX_PCM_DATA_RD, VP880_TX_PCM_DATA_LEN,
xdataTemp);
tempNew = ((xdataTemp[0] << 8) | xdataTemp[1]);
VP_CALIBRATION(None, NULL,("Vp880AdcSettling(adcConfig = 0x%02X): AdcPcm %d ecVal 0x%02X",
adcConfig, tempNew, ecVal));
VP_API_FUNC_INT(None, VP_NULL, ("Vp880AdcSettling-"));
return tempNew;
} /* Vp880AdcSettling() */
#endif
#ifdef VP880_TRACKER_SUPPORT
/**
* Vp880BatteryCalAdjust()
* This function computes the battery calibration error and adjust the device
* register and object content.
*
* Preconditions:
* The device and line context must be created and initialized before calling
* this function.
*
* Postconditions:
* Battery calibration registers are adjusted. Device object is updated.
*/
void
Vp880BatteryCalAdjust(
Vp880DeviceObjectType *pDevObj,
uint8 ecVal)
{
uint8 channelId = ((ecVal == VP880_EC_CH1) ? 0 : 1);
VpDeviceIdType deviceId = pDevObj->deviceId;
uint8 swCal[VP880_BAT_CALIBRATION_LEN];
int32 abvError =
(pDevObj->vp880SysCalData.abvError[channelId] * 10000 / VP880_V_PCM_LSB);
uint16 swCalError;
VP_API_FUNC_INT(None, VP_NULL, ("Vp880BatteryCalAdjust+"));
VpMpiCmdWrapper(deviceId, ecVal, VP880_BAT_CALIBRATION_RD,
VP880_BAT_CALIBRATION_LEN, swCal);
swCal[0] &= ~(VP880_BAT_CAL_SWCAL_MASK);
/* Conversion from 7.324mV to 1.25V */
swCalError = (ABS(abvError) / 171);
if (((ABS(abvError) + 85) / 171) > swCalError) {
swCalError+=1;
}
swCalError = (swCalError > 3) ? 3 : swCalError;
swCal[0] |= (swCalError << 3);
/*
* Positive error means voltage is too low (not negative enough).
* Positive adjustment makes the battery voltage more negative.
*/
swCal[0] |= (abvError > 0) ? 0 : VP880_BAT_CAL_SWCAL_SIGN;
VP_CALIBRATION(None, VP_NULL,
("Ch %d: Battery Calibration Correction 0x%02X 0x%02X",
channelId, swCal[0], swCal[1]));
/*
* This write MUST take into account Wideband setting because it can occur
* during normal system operation using "Apply System Coefficients". If
* called during normal calibration, the value of pDevObj must be cleared
* of the Wideband setting.
*/
VpMpiCmdWrapper(deviceId, (pDevObj->ecVal | ecVal), VP880_BAT_CALIBRATION_WRT,
VP880_BAT_CALIBRATION_LEN, swCal);
pDevObj->vp880SysCalData.abvError[0] = swCal[0];
pDevObj->vp880SysCalData.abvError[1] = swCal[1];
VP_API_FUNC_INT(None, VP_NULL, ("Vp880BatteryCalAdjust-"));
return;
}
#endif
/**
* Vp880AdjustIla() -- Tracker and ABS Function
* This function adjusts the line object data for the adjusted ILA value. No
* changes are made however if ILA calibration was not previously done.
*
* Preconditions:
* The device and line context must be created and initialized before calling
* this function.
*
* Postconditions:
* If previous calibration done, return TRUE and adjust line object data.
* Otherwise, return FALSE and no line object change made.
*/
bool
Vp880AdjustIla(
VpLineCtxType *pLineCtx,
uint8 targetIla)
{
Vp880LineObjectType *pLineObj = pLineCtx->pLineObj;
VpDevCtxType *pDevCtx = pLineCtx->pDevCtx;
Vp880DeviceObjectType *pDevObj = pDevCtx->pDevObj;
uint8 channelId = pLineObj->channelId;
int32 imtMeasured = 0;
uint8 imtTarget;
int16 ilaError, imtActual;
uint8 ilaAdjust;
VP_API_FUNC_INT(VpLineCtxType, pLineCtx, ("Vp880AdjustIla+"));
/*
* This function can run IF we're currently in calibration OR if the line
* has been previously calibrated.
*/
if ((pLineObj->calLineData.calDone == FALSE) /* Line not previously calibrated */
&& (!(pLineObj->status & VP880_LINE_IN_CAL))) { /* Not currently in cal */
VP_API_FUNC_INT(VpLineCtxType, pLineCtx, ("Vp880AdjustIla-"));
return FALSE;
}
if (targetIla < 4) { /* 18mA to < 22mA */
imtMeasured = pDevObj->vp880SysCalData.ila20[channelId];
imtTarget = 20;
} else if (targetIla < 10) { /* 23mA to < 28mA */
imtMeasured = pDevObj->vp880SysCalData.ila25[channelId];
imtTarget = 25;
} else if (targetIla < 18) { /* 29mA to < 36mA */
imtMeasured = pDevObj->vp880SysCalData.ila32[channelId];
imtTarget = 32;
} else { /* 36mA and higher */
imtMeasured = pDevObj->vp880SysCalData.ila40[channelId];
imtTarget = 40;
}
/* Always force ref ILA into the the normal and rev polarity feeds */
pLineObj->calLineData.dcFeed[VP880_ILA_INDEX] &= ~VP880_ILA_MASK;
pLineObj->calLineData.dcFeed[VP880_ILA_INDEX] |=
(pLineObj->calLineData.dcFeedRef[VP880_ILA_INDEX] & VP880_ILA_MASK);
pLineObj->calLineData.dcFeedPr[VP880_ILA_INDEX] &= ~VP880_ILA_MASK;
pLineObj->calLineData.dcFeedPr[VP880_ILA_INDEX] |=
(pLineObj->calLineData.dcFeedRef[VP880_ILA_INDEX] & VP880_ILA_MASK);
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("Vp880AdjustIla: dcFeedPr 0x%02X 0x%02X",
pLineObj->calLineData.dcFeedPr[0], pLineObj->calLineData.dcFeedPr[1]));
VP_CALIBRATION(VpLineCtxType, pLineCtx,
("Vp880AdjustIla: dcFeed 0x%02X 0x%02X",
pLineObj->calLineData.dcFeed[0], pLineObj->calLineData.dcFeed[1]));
/* determine the error */
imtActual = imtMeasured - pDevObj->vp880SysCalData.ilaOffsetNorm[channelId];
ilaError = imtActual - (imtTarget * VP880_ILA_SCALE_1MA);
/*
* only make an adjustment only if the error is greater
* than or equal to 500uA = 273 at PCM
*/
if (ABS(ilaError) >= (VP880_ILA_SCALE_1MA / 2)) {
uint8 tempIlaValue = pLineObj->calLineData.dcFeedRef[VP880_ILA_INDEX] & VP880_ILA_MASK;
int8 tempLowValue = (int8)tempIlaValue;
ilaAdjust = ((ABS(ilaError)+(VP880_ILA_SCALE_1MA / 2)) / VP880_ILA_SCALE_1MA);
if (ilaError < 0) {
tempIlaValue += ilaAdjust;
if (tempIlaValue <= VP880_ILA_MASK) {
pLineObj->calLineData.dcFeed[VP880_ILA_INDEX] += ilaAdjust;
} else {
pLineObj->calLineData.dcFeed[VP880_ILA_INDEX] |= VP880_ILA_MASK;
}
} else {
tempLowValue -= ilaAdjust;
if (tempLowValue >= 0) {
pLineObj->calLineData.dcFeed[VP880_ILA_INDEX] -= ilaAdjust;
} else {
pLineObj->calLineData.dcFeed[VP880_ILA_INDEX] &= ~VP880_ILA_MASK;
}
}
}
VP_CALIBRATION(VpLineCtxType, pLineCtx, ("Chan %d: ILA Actual Norm (10uA) %d",
channelId,
(int16)(imtActual * 100 / VP880_ILA_SCALE_1MA)));
VP_CALIBRATION(VpLineCtxType, pLineCtx, ("Chan %d: ILA Target (10uA) %d ILA Error Norm (10uA) %d",
channelId,
(int16)(((targetIla + 18) * 100)),
(int16)(ilaError * 100 / VP880_ILA_SCALE_1MA)));
VP_API_FUNC_INT(VpLineCtxType, pLineCtx, ("Vp880AdjustIla-"));
return TRUE;
} /* Vp880AdjustIla() */
/**
* Vp880AdjustVoc() -- Tracker and ABS Function
* This function adjusts the line object data for the adjusted VOC value. No
* changes are made however if VOC calibration was not previously done.
*
* Preconditions:
* The device and line context must be created and initialized before calling
* this function.
*
* Postconditions:
* If previous calibration done, return TRUE and adjust line object data.
* Otherwise, return FALSE and no line object change made.
*/
bool
Vp880AdjustVoc(
VpLineCtxType *pLineCtx,
uint8 targetVoc,
bool previousCal)
{
Vp880LineObjectType *pLineObj = pLineCtx->pLineObj;
uint8 channelId = pLineObj->channelId;
VpDevCtxType *pDevCtx = pLineCtx->pDevCtx;
Vp880DeviceObjectType *pDevObj = pDevCtx->pDevObj;
int16 vocActual, vocActualRev;
int32 pcmTargetVoc;
int16 vocErrorList[VP880_NUM_POLARITY];
uint8 vocErrIndex;
uint8 *dcFeedByte[VP880_NUM_POLARITY];
VP_API_FUNC_INT(VpLineCtxType, pLineCtx, ("Vp880AdjustVoc+"));
dcFeedByte[VP880_NORM_POLARITY] = &(pLineObj->calLineData.dcFeed[0]);
dcFeedByte[VP880_REV_POLARITY] = &(pLineObj->calLineData.dcFeedPr[0]);
pcmTargetVoc = (int32)(targetVoc * 3);
pcmTargetVoc += 36;
pcmTargetVoc *= VP880_V_1V_SCALE;
pcmTargetVoc /= VP880_V_1V_RANGE;
if (previousCal == FALSE) {
vocActual =
pLineObj->calLineData.typeData.vocData.vocNorm
- pDevObj->vp880SysCalData.vocOffset[channelId][VP880_NORM_POLARITY];
vocActualRev =
pLineObj->calLineData.typeData.vocData.vocRev
- pDevObj->vp880SysCalData.vocOffset[channelId][VP880_REV_POLARITY];
/*
* Target is always positive. Normal feed is positive. Negative error means
* voltage is too low (magnitude), positive means too high (magnitude).
*/
pDevObj->vp880SysCalData.vocError[channelId][VP880_NORM_POLARITY] = (vocActual - (int16)pcmTargetVoc);
VP_CALIBRATION(VpLineCtxType, pLineCtx, ("(In 10mV): VOC Norm %d Rev %d OffsetNorm %d OffsetRev %d Channel %d",
(int16)(pLineObj->calLineData.typeData.vocData.vocNorm * VP880_V_PCM_LSB/VP880_V_SCALE),
(int16)(pLineObj->calLineData.typeData.vocData.vocRev * VP880_V_PCM_LSB/VP880_V_SCALE),
(int16)(pDevObj->vp880SysCalData.vocOffset[channelId][VP880_NORM_POLARITY] * VP880_V_PCM_LSB/VP880_V_SCALE),
(int16)(pDevObj->vp880SysCalData.vocOffset[channelId][VP880_REV_POLARITY] * VP880_V_PCM_LSB/VP880_V_SCALE),
channelId));
VP_CALIBRATION(VpLineCtxType, pLineCtx, ("Chan %d: VOC (10mV) Actual Norm %d Rev Norm %d",
channelId,
(int16)(vocActual * VP880_V_PCM_LSB/VP880_V_SCALE),
(int16)(vocActualRev * VP880_V_PCM_LSB/VP880_V_SCALE)));
/*
* Target is always positive. Reverse feed is negative. Negative error means
* voltage is too low (magnitude), positive means too high (magnitude).
*/
pDevObj->vp880SysCalData.vocError[channelId][VP880_REV_POLARITY] = (-vocActualRev - (int16)pcmTargetVoc);
VP_CALIBRATION(VpLineCtxType, pLineCtx, ("Chan %d: VOC Target %d VOC Error Norm %d Error Rev %d",
channelId,
(int16)((targetVoc * 3 + 36) * 100),
(int16)(pDevObj->vp880SysCalData.vocError[channelId][VP880_NORM_POLARITY] * VP880_V_PCM_LSB/VP880_V_SCALE),
(int16)(pDevObj->vp880SysCalData.vocError[channelId][VP880_REV_POLARITY] * VP880_V_PCM_LSB/VP880_V_SCALE)));
VP_CALIBRATION(VpLineCtxType, pLineCtx, ("Chan %d: DC Feed Values Normal Before 0x%02X 0x%02X",
channelId, pLineObj->calLineData.dcFeed[0],
pLineObj->calLineData.dcFeed[1]));
VP_CALIBRATION(VpLineCtxType, pLineCtx, ("Chan %d: DC Feed Values Reverse Before 0x%02X 0x%02X",
channelId, pLineObj->calLineData.dcFeedPr[0],
pLineObj->calLineData.dcFeedPr[1]));
}
/*
* Adjust if error is more than 1/2 a step size for each parameter based
* on PCM scale.
*/
vocErrorList[VP880_NORM_POLARITY] = pDevObj->vp880SysCalData.vocError[channelId][VP880_NORM_POLARITY];
vocErrorList[VP880_REV_POLARITY] = pDevObj->vp880SysCalData.vocError[channelId][VP880_REV_POLARITY];
for (vocErrIndex = 0; vocErrIndex < VP880_NUM_POLARITY; vocErrIndex++) {
/* VOC Scale: 1.5V = 204.8 at PCM. Adjust to account for bit shift */
if (ABS(vocErrorList[vocErrIndex]) >= 205) {
if (vocErrorList[vocErrIndex] < 0) {
/* Error is low, so need to increase VOC */
/* Saturate the value, to prevent the rollover */
if ((*dcFeedByte[vocErrIndex] & VP880_VOC_MASK) != VP880_VOC_MASK) {
/* Not saturated within scale. So can adjust up */
*dcFeedByte[vocErrIndex] += 0x04;
} else if ((*dcFeedByte[vocErrIndex] & VP880_VOC_LOW_RANGE) ==
VP880_VOC_LOW_RANGE) {
/*
* Saturated within scale, but not within device. Change
* scale (moves up 3V) and clear incremental values or we'll
* end up at the top of the high range.
*/
*dcFeedByte[vocErrIndex] &= ~VP880_VOC_MASK;
*dcFeedByte[vocErrIndex] &= ~VP880_VOC_LOW_RANGE;
}
} else {
/* Error is high, so need to decrease VOC */
/* Saturate the value, to prevent the rollover */
if ((*dcFeedByte[vocErrIndex] & VP880_VOC_MASK) != 0x00) {
/* Not saturated within scale. So can adjust down */
*dcFeedByte[vocErrIndex] -= 0x04;
} else if ((*dcFeedByte[vocErrIndex] & VP880_VOC_LOW_RANGE) !=
VP880_VOC_LOW_RANGE) {
/*
* Saturated within scale, but not within device. Change
* scale (moves down 3V) and max incremental values or we'll
* end up at the bottom of the low range.
*/
*dcFeedByte[vocErrIndex] |= VP880_VOC_MASK;
*dcFeedByte[vocErrIndex] |= VP880_VOC_LOW_RANGE;
}
}
}
}
VP_CALIBRATION(VpLineCtxType, pLineCtx, ("Vp880AdjustVoc() Chan %d: DC Feed Values Normal After 0x%02X 0x%02X",
channelId, pLineObj->calLineData.dcFeed[0],
pLineObj->calLineData.dcFeed[1]));
VP_CALIBRATION(VpLineCtxType, pLineCtx, ("Vp880AdjustVoc() Chan %d: DC Feed Values Reverse After 0x%02X 0x%02X",
channelId, pLineObj->calLineData.dcFeedPr[0],
pLineObj->calLineData.dcFeedPr[1]));
VP_API_FUNC_INT(VpLineCtxType, pLineCtx, ("Vp880AdjustVoc-"));
return TRUE;
} /* Vp880AdjustVoc() */
/**
* Vp880Cal() -- Tracker and ABS Function
* This function calibrates a selected block of the device/line.
*
* Preconditions:
* The device and line context must be created and initialized before calling
* this function.
*
* Postconditions:
* This function generates an event upon completing the requested action.
*/
VpStatusType
Vp880Cal(
VpLineCtxType *pLineCtx,
VpCalType calType,
void *inputArgs)
{
Vp880LineObjectType *pLineObj = pLineCtx->pLineObj;
VpDevCtxType *pDevCtx = pLineCtx->pDevCtx;
Vp880DeviceObjectType *pDevObj = pDevCtx->pDevObj;
VpDeviceIdType deviceId = pDevObj->deviceId;
VpStatusType status = VP_STATUS_SUCCESS;
uint8 profileIndex;
uint8 *profileData;
VP_API_FUNC_INT(VpLineCtxType, pLineCtx, ("Vp880Cal+"));
VpSysEnterCritical(deviceId, VP_CODE_CRITICAL_SEC);
switch(calType) {
case VP_CAL_GET_SYSTEM_COEFF:
if (pDevObj->stateInt & VP880_SYS_CAL_COMPLETE) {
/* Data length is header (6 bytes) + 880 calibration data */
pDevObj->mpiLen = 6 + VP880_CAL_STRUCT_SIZE;
pLineObj->responseData = (uint8)VP_CAL_GET_SYSTEM_COEFF;
pLineObj->lineEvents.response |= VP_EVID_CAL_CMP;
} else {
status = VP_STATUS_LINE_NOT_CONFIG;
}
break;
case VP_CAL_APPLY_SYSTEM_COEFF:
profileData = (uint8 *)inputArgs;
if (profileData == VP_NULL) {
VpMemSet(&pDevObj->vp880SysCalData, 0, sizeof(Vp880SysCalResultsType));
pDevObj->stateInt &= ~(VP880_SYS_CAL_COMPLETE | VP880_CAL_RELOAD_REQ | VP880_DEVICE_CAL_COMPLETE);
pDevObj->stateInt |= VP880_SYS_CAL_RESET;
pLineObj->lineEvents.response |= VP_EVID_CAL_CMP;
pLineObj->responseData = VP_CAL_SUCCESS;
VP_API_FUNC_INT(VpLineCtxType, pLineCtx, ("Vp880Cal-"));
VpSysExitCritical(deviceId, VP_CODE_CRITICAL_SEC);
return VP_STATUS_SUCCESS;
}
if ((profileData[VP_PROFILE_TYPE_LSB] != VP_PRFWZ_PROFILE_CAL) ||
(profileData[VP_PROFILE_TYPE_MSB] != VP_DEV_880_SERIES) ||
(profileData[VP_PROFILE_LENGTH] < (VP880_CAL_STRUCT_SIZE + 2))) {
VP_API_FUNC_INT(VpLineCtxType, pLineCtx, ("Vp880Cal-"));
VpSysExitCritical(deviceId, VP_CODE_CRITICAL_SEC);
return VP_STATUS_INVALID_ARG;
}
profileIndex = VP_PROFILE_DATA_START;
pDevObj->vp880SysCalData.abvError[0] = VpConvertToInt16(&profileData[profileIndex]);
profileIndex+=2;
VP_CALIBRATION(VpDevCtxType, pDevCtx, ("ABV Y Error %d", pDevObj->vp880SysCalData.abvError[0]));
pDevObj->vp880SysCalData.abvError[1] = VpConvertToInt16(&profileData[profileIndex]);
profileIndex+=2;
VP_CALIBRATION(VpDevCtxType, pDevCtx, ("ABV Z Error %d", pDevObj->vp880SysCalData.abvError[1]));
pDevObj->vp880SysCalData.vocOffset[0][0] = VpConvertToInt16(&profileData[profileIndex]);
profileIndex+=2;
VP_CALIBRATION(VpDevCtxType, pDevCtx, ("VOC Offset Norm Ch 0 %d", pDevObj->vp880SysCalData.vocOffset[0][0]));
pDevObj->vp880SysCalData.vocError[0][0] = VpConvertToInt16(&profileData[profileIndex]);
profileIndex+=2;
VP_CALIBRATION(VpDevCtxType, pDevCtx, ("VOC Error Norm Ch 0 %d", pDevObj->vp880SysCalData.vocError[0][0]));
pDevObj->vp880SysCalData.vocOffset[0][1] = VpConvertToInt16(&profileData[profileIndex]);
profileIndex+=2;
VP_CALIBRATION(VpDevCtxType, pDevCtx, ("VOC Offset Rev Ch 0 %d", pDevObj->vp880SysCalData.vocOffset[0][1]));
pDevObj->vp880SysCalData.vocError[0][1] = VpConvertToInt16(&profileData[profileIndex]);
profileIndex+=2;
VP_CALIBRATION(VpDevCtxType, pDevCtx, ("VOC Error Rev Ch 0 %d", pDevObj->vp880SysCalData.vocError[0][1]));
pDevObj->vp880SysCalData.vocOffset[1][0] = VpConvertToInt16(&profileData[profileIndex]);
profileIndex+=2;
VP_CALIBRATION(VpDevCtxType, pDevCtx, ("VOC Offset Norm Ch 1 %d", pDevObj->vp880SysCalData.vocOffset[1][0]));
pDevObj->vp880SysCalData.vocError[1][0] = VpConvertToInt16(&profileData[profileIndex]);
profileIndex+=2;
VP_CALIBRATION(VpDevCtxType, pDevCtx, ("VOC Error Norm Ch 1 %d", pDevObj->vp880SysCalData.vocError[1][0]));
pDevObj->vp880SysCalData.vocOffset[1][1] = VpConvertToInt16(&profileData[profileIndex]);
profileIndex+=2;
VP_CALIBRATION(VpDevCtxType, pDevCtx, ("VOC Offset Rev Ch 1 %d", pDevObj->vp880SysCalData.vocOffset[1][1]));
pDevObj->vp880SysCalData.vocError[1][1] = VpConvertToInt16(&profileData[profileIndex]);
profileIndex+=2;
VP_CALIBRATION(VpDevCtxType, pDevCtx, ("VOC Error Rev Ch 1 %d", pDevObj->vp880SysCalData.vocError[1][1]));
pDevObj->vp880SysCalData.sigGenAError[0][0] = VpConvertToInt16(&profileData[profileIndex]);
profileIndex+=2;
VP_CALIBRATION(VpDevCtxType, pDevCtx, ("SigGenA Norm Ch 0 Error %d", pDevObj->vp880SysCalData.sigGenAError[0][0]));
pDevObj->vp880SysCalData.sigGenAError[0][1] = VpConvertToInt16(&profileData[profileIndex]);
profileIndex+=2;
VP_CALIBRATION(VpDevCtxType, pDevCtx, ("SigGenA Rev Ch 0 Error %d", pDevObj->vp880SysCalData.sigGenAError[0][1]));
pDevObj->vp880SysCalData.sigGenAError[1][0] = VpConvertToInt16(&profileData[profileIndex]);
profileIndex+=2;
VP_CALIBRATION(VpDevCtxType, pDevCtx, ("SigGenA Norm Ch 1 Error %d", pDevObj->vp880SysCalData.sigGenAError[1][0]));
pDevObj->vp880SysCalData.sigGenAError[1][1] = VpConvertToInt16(&profileData[profileIndex]);
profileIndex+=2;
VP_CALIBRATION(VpDevCtxType, pDevCtx, ("SigGenA Rev Ch 1 Error %d", pDevObj->vp880SysCalData.sigGenAError[1][1]));
pDevObj->vp880SysCalData.ila20[0] = VpConvertToInt16(&profileData[profileIndex]);
profileIndex+=2;
VP_CALIBRATION(VpDevCtxType, pDevCtx, ("ILA 20mA Ch 0 %d", pDevObj->vp880SysCalData.ila20[0]));
pDevObj->vp880SysCalData.ila20[1] = VpConvertToInt16(&profileData[profileIndex]);
profileIndex+=2;
VP_CALIBRATION(VpDevCtxType, pDevCtx, ("ILA 20mA Ch 1 %d", pDevObj->vp880SysCalData.ila20[1]));
pDevObj->vp880SysCalData.ila25[0] = VpConvertToInt16(&profileData[profileIndex]);
profileIndex+=2;
VP_CALIBRATION(VpDevCtxType, pDevCtx, ("ILA 25mA Ch 0 %d", pDevObj->vp880SysCalData.ila25[0]));
pDevObj->vp880SysCalData.ila25[1] = VpConvertToInt16(&profileData[profileIndex]);
profileIndex+=2;
VP_CALIBRATION(VpDevCtxType, pDevCtx, ("ILA 25mA Ch 1 %d", pDevObj->vp880SysCalData.ila25[1]));
pDevObj->vp880SysCalData.ila32[0] = VpConvertToInt16(&profileData[profileIndex]);
profileIndex+=2;
VP_CALIBRATION(VpDevCtxType, pDevCtx, ("ILA 32mA Ch 0 %d", pDevObj->vp880SysCalData.ila32[0]));
pDevObj->vp880SysCalData.ila32[1] = VpConvertToInt16(&profileData[profileIndex]);
profileIndex+=2;
VP_CALIBRATION(VpDevCtxType, pDevCtx, ("ILA 32mA Ch 1 %d", pDevObj->vp880SysCalData.ila32[1]));
pDevObj->vp880SysCalData.ila40[0] = VpConvertToInt16(&profileData[profileIndex]);
profileIndex+=2;
VP_CALIBRATION(VpDevCtxType, pDevCtx, ("ILA 40mA Ch 0 %d", pDevObj->vp880SysCalData.ila40[0]));
pDevObj->vp880SysCalData.ila40[1] = VpConvertToInt16(&profileData[profileIndex]);
profileIndex+=2;
VP_CALIBRATION(VpDevCtxType, pDevCtx, ("ILA 40mA Ch 1 %d", pDevObj->vp880SysCalData.ila40[1]));
pDevObj->vp880SysCalData.ilaOffsetNorm[0] = VpConvertToInt16(&profileData[profileIndex]);
profileIndex+=2;
VP_CALIBRATION(VpDevCtxType, pDevCtx, ("ILA Offset Ch 0 %d", pDevObj->vp880SysCalData.ilaOffsetNorm[0]));
pDevObj->vp880SysCalData.ilaOffsetNorm[1] = VpConvertToInt16(&profileData[profileIndex]);
profileIndex+=2;
VP_CALIBRATION(VpDevCtxType, pDevCtx, ("ILA Offset Ch 1 %d", pDevObj->vp880SysCalData.ilaOffsetNorm[1]));
pDevObj->vp880SysCalData.ilgOffsetNorm[0] = VpConvertToInt16(&profileData[profileIndex]);
profileIndex+=2;
VP_CALIBRATION(VpDevCtxType, pDevCtx, ("ILG Offset Ch 0 %d", pDevObj->vp880SysCalData.ilgOffsetNorm[0]));
pDevObj->vp880SysCalData.ilgOffsetNorm[1] = VpConvertToInt16(&profileData[profileIndex]);
profileIndex+=2;
VP_CALIBRATION(VpDevCtxType, pDevCtx, ("ILG Offset Ch 1 %d", pDevObj->vp880SysCalData.ilgOffsetNorm[1]));
pDevObj->vp880SysCalData.vas[0][0] = profileData[profileIndex++];
VP_CALIBRATION(VpDevCtxType, pDevCtx, ("VAS Norm Ch 0 %d", pDevObj->vp880SysCalData.vas[0][0]));
pDevObj->vp880SysCalData.vas[0][1] = profileData[profileIndex++];
VP_CALIBRATION(VpDevCtxType, pDevCtx, ("VAS Rev Ch 0 %d", pDevObj->vp880SysCalData.vas[0][1]));
pDevObj->vp880SysCalData.vas[1][0] = profileData[profileIndex++];
VP_CALIBRATION(VpDevCtxType, pDevCtx, ("VAS Norm Ch 1 %d", pDevObj->vp880SysCalData.vas[1][0]));
pDevObj->vp880SysCalData.vas[1][1] = profileData[profileIndex++];
VP_CALIBRATION(VpDevCtxType, pDevCtx, ("VAS Rev Ch 1 %d", pDevObj->vp880SysCalData.vas[1][1]));
pDevObj->vp880SysCalData.vagOffsetNorm[0] = VpConvertToInt16(&profileData[profileIndex]);
profileIndex+=2;
VP_CALIBRATION(VpDevCtxType, pDevCtx, ("VAG Offset Norm Ch 0 %d", pDevObj->vp880SysCalData.vagOffsetNorm[0]));
pDevObj->vp880SysCalData.vagOffsetNorm[1] = VpConvertToInt16(&profileData[profileIndex]);
profileIndex+=2;
VP_CALIBRATION(VpDevCtxType, pDevCtx, ("VAG Offset Norm Ch 1 %d", pDevObj->vp880SysCalData.vagOffsetNorm[1]));
pDevObj->vp880SysCalData.vagOffsetRev[0] = VpConvertToInt16(&profileData[profileIndex]);
profileIndex+=2;
VP_CALIBRATION(VpDevCtxType, pDevCtx, ("VAG Offset Rev Ch 0 %d", pDevObj->vp880SysCalData.vagOffsetRev[0]));
pDevObj->vp880SysCalData.vagOffsetRev[1] = VpConvertToInt16(&profileData[profileIndex]);
profileIndex+=2;
VP_CALIBRATION(VpDevCtxType, pDevCtx, ("VAG Offset Rev Ch 1 %d", pDevObj->vp880SysCalData.vagOffsetRev[1]));
pDevObj->vp880SysCalData.vbgOffsetNorm[0] = VpConvertToInt16(&profileData[profileIndex]);
profileIndex+=2;
VP_CALIBRATION(VpDevCtxType, pDevCtx, ("VBG Offset Norm Ch 0 %d", pDevObj->vp880SysCalData.vbgOffsetNorm[0]));
pDevObj->vp880SysCalData.vbgOffsetNorm[1] = VpConvertToInt16(&profileData[profileIndex]);
profileIndex+=2;
VP_CALIBRATION(VpDevCtxType, pDevCtx, ("VBG Offset Norm Ch 1 %d", pDevObj->vp880SysCalData.vbgOffsetNorm[1]));
pDevObj->vp880SysCalData.vbgOffsetRev[0] = VpConvertToInt16(&profileData[profileIndex]);
profileIndex+=2;
VP_CALIBRATION(VpDevCtxType, pDevCtx, ("VBG Offset Rev Ch 0 %d", pDevObj->vp880SysCalData.vbgOffsetRev[0]));
pDevObj->vp880SysCalData.vbgOffsetRev[1] = VpConvertToInt16(&profileData[profileIndex]);
profileIndex+=2;
VP_CALIBRATION(VpDevCtxType, pDevCtx, ("VBG Offset Rev Ch 1 %d", pDevObj->vp880SysCalData.vbgOffsetRev[1]));
pDevObj->vp880SysCalData.absNormCal[0] = profileData[profileIndex++];
VP_CALIBRATION(VpDevCtxType, pDevCtx, ("Auto-Bat Switch Norm Ch 0 Cal %d", pDevObj->vp880SysCalData.absNormCal[0]));
pDevObj->vp880SysCalData.absPolRevCal[0] = profileData[profileIndex++];
VP_CALIBRATION(VpDevCtxType, pDevCtx, ("Auto-Bat Switch Rev Ch 0 Cal %d", pDevObj->vp880SysCalData.absPolRevCal[0]));
pDevObj->vp880SysCalData.absNormCal[1] = profileData[profileIndex++];
VP_CALIBRATION(VpDevCtxType, pDevCtx, ("Auto-Bat Switch Norm Ch 1 Cal %d", pDevObj->vp880SysCalData.absNormCal[1]));
pDevObj->vp880SysCalData.absPolRevCal[1] = profileData[profileIndex++];
VP_CALIBRATION(VpDevCtxType, pDevCtx, ("Auto-Bat Switch Rev Ch 1 Cal %d", pDevObj->vp880SysCalData.absPolRevCal[1]));
pDevObj->vp880SysCalData.swyOffset[0] = VpConvertToInt16(&profileData[profileIndex]);
profileIndex+=2;
VP_CALIBRATION(VpDevCtxType, pDevCtx, ("SWY Offset Ch 0 %d", pDevObj->vp880SysCalData.swyOffset[0]));
pDevObj->vp880SysCalData.swyOffset[1] = VpConvertToInt16(&profileData[profileIndex]);
profileIndex+=2;
VP_CALIBRATION(VpDevCtxType, pDevCtx, ("SWY Offset Ch 1 %d", pDevObj->vp880SysCalData.swyOffset[1]));
pDevObj->vp880SysCalData.swzOffset[0] = VpConvertToInt16(&profileData[profileIndex]);
profileIndex+=2;
VP_CALIBRATION(VpDevCtxType, pDevCtx, ("SWZ Offset Ch 0 %d", pDevObj->vp880SysCalData.swzOffset[0]));
pDevObj->vp880SysCalData.swzOffset[1] = VpConvertToInt16(&profileData[profileIndex]);
profileIndex+=2;
VP_CALIBRATION(VpDevCtxType, pDevCtx, ("SWZ Offset Ch 1 %d", pDevObj->vp880SysCalData.swzOffset[1]));
pDevObj->vp880SysCalData.swxbOffset[0] = VpConvertToInt16(&profileData[profileIndex]);
profileIndex+=2;
VP_CALIBRATION(VpDevCtxType, pDevCtx, ("XB Offset Ch 0 %d", pDevObj->vp880SysCalData.swxbOffset[0]));
pDevObj->vp880SysCalData.swxbOffset[1] = VpConvertToInt16(&profileData[profileIndex]);
profileIndex+=2;
VP_CALIBRATION(VpDevCtxType, pDevCtx, ("XB Offset Ch 1 %d", pDevObj->vp880SysCalData.swxbOffset[1]));
pDevObj->vp880SysCalData.tipCapCal[0] = VpConvertToInt32(&profileData[profileIndex]);
profileIndex+=4;
VP_CALIBRATION(VpDevCtxType, pDevCtx, ("Tip Cap Ch 0 %li", pDevObj->vp880SysCalData.tipCapCal[0]));
pDevObj->vp880SysCalData.tipCapCal[1] = VpConvertToInt32(&profileData[profileIndex]);
profileIndex+=4;
VP_CALIBRATION(VpDevCtxType, pDevCtx, ("Tip Cap Ch 1 %li", pDevObj->vp880SysCalData.tipCapCal[1]));
pDevObj->vp880SysCalData.ringCapCal[0] = VpConvertToInt32(&profileData[profileIndex]);
profileIndex+=4;
VP_CALIBRATION(VpDevCtxType, pDevCtx, ("Ring Cap Ch 0 %li", pDevObj->vp880SysCalData.ringCapCal[0]));
pDevObj->vp880SysCalData.ringCapCal[1] = VpConvertToInt32(&profileData[profileIndex]);
profileIndex+=4;
VP_CALIBRATION(VpDevCtxType, pDevCtx, ("Ring Cap Ch 1 %li", pDevObj->vp880SysCalData.ringCapCal[1]));
VP_CALIBRATION(VpDevCtxType, pDevCtx, ("Calibration Data Length - %d", profileIndex));
pDevObj->stateInt |= (VP880_SYS_CAL_COMPLETE | VP880_CAL_RELOAD_REQ | VP880_DEVICE_CAL_COMPLETE);
pLineObj->lineEvents.response |= VP_EVID_CAL_CMP;
pLineObj->responseData = VP_CAL_SUCCESS;
break;
default:
status = VP_STATUS_INVALID_ARG;
break;
}
VP_API_FUNC_INT(VpLineCtxType, pLineCtx, ("Vp880Cal-"));
VpSysExitCritical(deviceId, VP_CODE_CRITICAL_SEC);
return status;
} /* Vp880Cal() */
#endif /* VP_CC_880_SERIES */