📄 wmauxadc.c
字号:
goto error0;
}
/*
* We only have to do anything in streaming mode.
*/
#if WM_STREAM_AUXADC
{
WM_DEVICE_CONTEXT *pDeviceContext = WMHANDLE_TO_DEVICE( hDevice );
unsigned int index;
unsigned int bucket;
WM_REGVAL adcAdr;
/*
* Protect ourselves from interference.
*/
if ( !WMLockGlobalData( hDevice ) )
{
status = WMS_LOCK_TIMED_OUT;
goto error0;
}
/* Touch is a special case */
if ( WM_ADC_TOUCH == adcType )
{
if ( !(pDeviceContext->v_pADCData->flags & WM_DRVCTX_AUXADC_TOUCH_STREAMING) )
{
/* Nothing to do */
goto done;
}
pDeviceContext->v_pADCData->flags &= ~WM_DRVCTX_AUXADC_TOUCH_STREAMING;
/* Stop the buckets */
bucket = BUCKET_INDEX_FROM_ADCADR( WM_AUXADC_X_COORD );
WM_ASSERT( hDevice, bucket < ADC_COUNT );
pDeviceContext->v_pADCData->activeADCs &= ~(1 << bucket);
bucket = BUCKET_INDEX_FROM_ADCADR( WM_AUXADC_Y_COORD );
WM_ASSERT( hDevice, bucket < ADC_COUNT );
pDeviceContext->v_pADCData->activeADCs &= ~(1 << bucket);
}
else
{
/* Work out the index into our table */
index = INDEX_FROM_ADCVAL( adcType );
WM_ASSERT( hDevice, index < pDeviceContext->pChipDef->adcCount );
/* Now look up the address */
adcAdr = pDeviceContext->pChipDef->pAuxADCDetails[index].adcAdr;
bucket = BUCKET_INDEX_FROM_ADCADR( adcAdr );
WM_ASSERT( hDevice, bucket < ADC_COUNT );
if ( !(pDeviceContext->v_pADCData->activeADCs & (1 << bucket)) )
{
/* Nothing to do */
goto done;
}
pDeviceContext->v_pADCData->activeADCs &= ~(1 << bucket);
pDeviceContext->v_pADCData->flags &= ~WM_DRVCTX_AUXADC_ADC_STREAMING;
/* Stop the bucket */
pDeviceContext->v_pADCData->activeADCs &= ~(1 << bucket);
}
/*
* If we get here, we've got a change.
*/
status = private_SwitchStreaming( hDevice );
if ( WM_ERROR( status ) )
{
goto error1;
}
done:
/*
* Let other threads in.
*/
WMUnlockGlobalData( hDevice );
}
#endif /* WM_STREAM_AUXADC */
return WMS_SUCCESS;
#if WM_STREAM_AUXADC
error1:
/*
* Let other threads in.
*/
WMUnlockGlobalData( hDevice );
#endif /* WM_STREAM_AUXADC */
error0:
return status;
}
/*-----------------------------------------------------------------------------
* Function: WMSampleADC
*
* Returns the next sample of the given type.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
* adcType One of the WM_AUXADC_TYPE constants.
* pValue Variable to receive the value (between 0 and 0xFFF).
* Set to WM_INVALID_SAMPLE on error.
*
* Returns: WMSTATUS
* See WMStatus.h.
*---------------------------------------------------------------------------*/
WMSTATUS WMSampleADC( WM_DEVICE_HANDLE hDevice,
WM_AUXADC_TYPE adcType,
WM_REGVAL *pValue
)
{
WM_DEVICE_CONTEXT *pDeviceContext = WMHANDLE_TO_DEVICE( hDevice );
WMSTATUS status;
WM_REGVAL adcSel;
WM_REGVAL adcAdr;
WM_BOOL needPenDown = FALSE;
WM_REGVAL rawValue;
unsigned int index;
/* Check we've got AUX ADC */
if ( !WM_IS_AUXADC_SUPPORTED( hDevice ) )
{
status = WMS_UNSUPPORTED;
goto error;
}
/*
* Work out our ADC address.
* First calculate the index into our table...
*/
index = INDEX_FROM_ADCVAL( adcType );
if ( index >= pDeviceContext->pChipDef->adcCount )
{
status = WMS_INVALID_PARAMETER;
goto error;
}
/* Now look up the address */
adcSel = pDeviceContext->pChipDef->pAuxADCDetails[index].adcSel;
adcAdr = pDeviceContext->pChipDef->pAuxADCDetails[index].adcAdr;
needPenDown = pDeviceContext->pChipDef->pAuxADCDetails[index].needPenDown;
if ( WM_AUXADC_INVALID == adcAdr )
{
status = WMS_INVALID_PARAMETER;
goto error;
}
/*
* Get the sample.
*/
#if WM_STREAM_AUXADC
if ( pDeviceContext->v_pADCData->flags & WM_DRVCTX_AUXADC_STREAMING )
{
/*
* Now sample the ADC. Note we pass in the ADCADR instead of the
* ADCSEL because we're checking against the returned data, not
* requesting a new sample.
*/
status = private_SampleADC( hDevice, adcAdr, &rawValue );
}
else
#endif /* WM_STREAM_AUXADC */
{
status = private_PollADC( hDevice, adcSel, &rawValue );
}
if ( WM_ERROR( status ) )
{
goto error;
}
/*
* Check it's the right ADC.
*/
if ( (rawValue & WM_AUXADC_MASK) != adcAdr )
{
status = WMS_UNEXPECTED_DATA;
goto error;
}
/*
* Check pen down if we need it.
*/
if ( needPenDown && !(rawValue & WM_DATA_PENDOWN) )
{
status = WMS_NO_PEN_DOWN;
goto error;
}
/*
* Get the adcAdr sample.
*/
*pValue = rawValue & WM_DATA_VAL; // lowest 12 bits
/*
* Do any post-processing.
*/
switch ( adcType )
{
/*
* Invert the sample if requested.
*/
#if WM_TOUCH_INVERT_X
case WM_ADC_X_COORD:
*pValue = WM_MAX_DATA_VAL - *pValue;
break;
#endif /* WM_TOUCH_INVERT_X */
#if WM_TOUCH_INVERT_Y
case WM_ADC_Y_COORD:
*pValue = WM_MAX_DATA_VAL - *pValue;
break;
#endif /* WM_TOUCH_INVERT_Y */
/*
* BMON has a divide by three to bring it within range of VRef.
* Note: doing the multiply means we can return values greater
* than WM_MAX_DATA_VAL.
*/
#if WM_BATTERY_NORMALISE
case WM_ADC_BMON:
*pValue *= 3;
break;
#endif /* WM_BATTERY_NORMALISE */
default:
break;
}
return WMS_SUCCESS;
error:
*pValue = WM_INVALID_SAMPLE;
return status;
}
/*-----------------------------------------------------------------------------
* Function: private_PollADC
*
* Returns the next raw sample of the given type, using polling mode.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
* adcSel The ADCSEL address to pass to the chip (from the chipDef).
* pValue Variable to receive the value (between 0 and 0xFFFF).
*
* Returns: WMSTATUS
* See WMStatus.h.
*---------------------------------------------------------------------------*/
static WMSTATUS private_PollADC( WM_DEVICE_HANDLE hDevice,
WM_REGVAL adcSel,
WM_REGVAL *pValue
)
{
WMSTATUS status;
WM_REGVAL controlValue = 0;
WM_REGVAL controlMask = 0;
WM_REGVAL pollBit = WM_TOUCHCTRL_POLL;
WM_REGTYPE adcSelReg = WM97_DIGITISER_CONTROL;
WM_REGVAL adcSelValue = 0;
unsigned int tFail;
WM_BOOL isTouch = FALSE;
/*
* Make sure the digitiser is powered up.
*/
status = WMAuxADCPowerUp( hDevice, WM_POWER_AUXADC_DIGITISER );
if ( WM_ERROR( status ) )
{
goto error;
}
/*
* Set delay.
*/
controlMask = WM_TOUCHCTRL_DEL_MASK;
/* Select the ADC */
if ( WM_USES_ADCSEL( hDevice ) )
{
if ( WM_ADCSEL_X_COORD == adcSel || WM_ADCSEL_X_COORD == adcSel )
isTouch = TRUE;
}
else
{
if ( WM_AUXADC_X_COORD == adcSel || WM_AUXADC_X_COORD == adcSel )
isTouch = TRUE;
}
/* Set our delay appropriately */
if ( isTouch )
controlValue |= WM_TOUCH_SETTLE_DELAY;
else
controlValue |= WM_AUXADC_SETTLE_DELAY;
/*
* And write these to the registers.
* First digitiser control. Note this includes ADC input select on the
* WM9705 and WM9712.
*/
if ( !WM_USES_ADCSEL( hDevice ) )
{
controlValue |= WM_TOUCHCTRL_POLL | adcSel;
controlMask |= WM_TOUCHCTRL_POLL | WM_AUXADC_MASK;
/* The control register is the ADC select */
adcSelReg = WM97_DIGITISER_CONTROL;
pollBit = WM_TOUCHCTRL_POLL;
}
status = WMSetField( hDevice, WM97_DIGITISER_CONTROL, controlValue, controlMask );
if ( WM_ERROR( status ) )
{
goto error;
}
/*
* Now digitiser ADC input select for any device not yet covered.
*/
if ( WM_USES_ADCSEL( hDevice ) )
{
WM_REGVAL adcSelMask;
adcSelMask = WM_ADCSEL_POLL | WM_ADCSEL_MASK;
adcSelValue = WM_ADCSEL_POLL | adcSel;
status = WMSetField( hDevice, WM97_DIGITISER_ADCSEL, adcSelValue, adcSelMask );
if ( WM_ERROR( status ) )
{
goto error;
}
/* The control register is the ADC select */
adcSelReg = WM97_DIGITISER_ADCSEL;
pollBit = WM_ADCSEL_POLL;
}
/*
* Wait for the sample to complete (polling bit will reset itself).
* If it doesn't complete within a couple of milliseconds, assume
* something's gone wrong.
*/
tFail = GetMillisecondTimestamp( hDevice ) + 2;
do
{
status = WMRead( hDevice, adcSelReg, &adcSelValue );
if ( WM_ERROR( status ) )
{
goto error;
}
/* Are we done? */
if ( !(adcSelValue & pollBit) )
{
break;
}
/* Let other things have a bit of time */
WMBeNice( hDevice );
} while ( GetMillisecondTimestamp( hDevice ) < tFail );
/* Did we time out? */
if ( adcSelValue & pollBit )
{
status = WMS_NO_DATA;
goto error;
}
/*
* Now read the value.
*/
status = WMRead( hDevice, WM97_DIGITISER_DATA, pValue );
if ( WM_ERROR( status ) )
{
goto error;
}
/*
* Power down the digitiser again. If we've come to this function, we're
* not streaming, so it's safe to do this.
*/
status = WMAuxADCPowerDown( hDevice, WM_POWER_AUXADC_DIGITISER );
if ( WM_ERROR( status ) )
{
goto error;
}
/*
* It worked.
*/
return WMS_SUCCESS;
/*
* Error cleanup.
*/
error:
/*
* Power down the digitiser again. If we've come to this function, we're
* not streaming, so it's safe to do this.
*/
WMAuxADCPowerDown( hDevice, WM_POWER_AUXADC_DIGITISER );
return status;
}
#if WM_STREAM_AUXADC
/*-----------------------------------------------------------------------------
* Function: private_PrepareBucket
*
* Prepares the ADC functionality to handle readings of the appropriate type.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
* adc Which ADC to prepare.
*
* Returns: WMSTATUS
* See WMStatus.h
*---------------------------------------------------------------------------*/
static void private_PrepareBucket( WM_DEVICE_HANDLE hDevice, WM_REGVAL adcAdr )
{
WM_DEVICE_CONTEXT *pDeviceContext = WMHANDLE_TO_DEVICE( hDevice );
unsigned int bucket;
bucket = BUCKET_INDEX_FROM_ADCADR( adcAdr );
WM_ASSERT( hDevice, bucket < ADC_COUNT );
/*
* The '05 and '12 can only do one input (other than touch) at a time.
*/
if ( IS_WM9705_FAMILY( hDevice ) || IS_WM9712_FAMILY( hDevice ) )
{
/*
* Zap the other active ADCs, leaving just the touch.
*/
pDeviceContext->v_pADCData->activeADCs &= TOUCH_ACTIVE_MASK;
}
/* Prepare the bucket and set the desired ADC */
pDeviceContext->v_pADCData->reading[bucket] = WM_INVALID_SAMPLE;
pDeviceContext->v_pADCData->lastReading[bucket] = WM_INVALID_SAMPLE;
pDeviceContext->v_pADCData->activeADCs |= 1 << bucket;
}
/*-----------------------------------------------------------------------------
* Function: private_SwitchStreaming
*
* Enables or disables streaming and/or coordinate mode according to what has
* been asked for.
*
* Streaming mode only.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
*
* Returns: WMSTATUS
* See WMStatus.h
*---------------------------------------------------------------------------*/
static WMSTATUS private_SwitchStreaming( WM_DEVICE_HANDLE hDevice )
{
WM_DEVICE_CONTEXT *pDeviceContext = WMHANDLE_TO_DEVICE( hDevice );
WMSTATUS status;
WM_REGVAL controlVal = 0;
WM_REGVAL adcSelVal = 0;
WM_BOOL streamTouch;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -