📄 wmauxadc.c
字号:
WM_BOOL streamADC;
unsigned int sampleRate = 0;
WM_REGVAL conversionRate = 0;
WM_REGVAL settleDelay = 0;
/*
* Variables for shorthand.
*/
streamTouch = pDeviceContext->v_pADCData->flags & WM_DRVCTX_AUXADC_TOUCH_STREAMING;
streamADC = pDeviceContext->v_pADCData->flags & WM_DRVCTX_AUXADC_ADC_STREAMING;
/*
* Work out our request.
*/
adcSelVal = private_GetAdcSelVal( hDevice );
/* If we've got something, add in the rest to enable streaming */
if ( 0 != adcSelVal )
{
/* Use at least the touch conversion rates if touch is requested. */
if ( streamTouch )
{
sampleRate = WM_TOUCH_SAMPLE_RATE;
settleDelay = WM_TOUCH_SETTLE_DELAY;
}
/* An Auxiliary ADC? */
if ( streamADC && ( 0 != pDeviceContext->v_pADCData->activeADCs ) )
{
/*
* The conversion rate is the faster of the touch panel and the ADC.
*
* If we're not using the touch panel, this will currently be 0.
*/
sampleRate = WM_MAX( sampleRate, WM_DIGITISER_SAMPLE_RATE );
/*
* The settle delay is the longer of the touch panel and the ADC.
* Higher number is longer.
*
* If we're not using the touch panel, this will currently be 0.
*/
settleDelay = WM_MAX( settleDelay, WM_AUXADC_SETTLE_DELAY );
}
/* Now convert from sample rate to CR setting */
if ( IS_WM9713_FAMILY( hDevice ) )
{
if ( sampleRate > 154 )
{
if ( sampleRate > 187 )
{
WM_TRACE( hDevice, ( "WM9713 maximum sample rate is 187.5Hz" ));
}
conversionRate = WM9713_TOUCHCTRL_CR_187Hz;
}
else if ( sampleRate > 120 )
{
conversionRate = WM9713_TOUCHCTRL_CR_154Hz;
}
else if ( sampleRate > 94 )
{
conversionRate = WM9713_TOUCHCTRL_CR_120Hz;
}
else
{
conversionRate = WM9713_TOUCHCTRL_CR_94Hz;
}
}
else /* => WM9705 or WM9712 */
{
if ( sampleRate > 375 )
{
if ( sampleRate > 750 )
{
WM_TRACE( hDevice, ( "WM9705/WM9712 maximum sample rate is 750Hz" ) );
}
conversionRate = WM97_TOUCHCTRL_CR_750Hz;
}
else if ( sampleRate > 187 )
{
conversionRate = WM97_TOUCHCTRL_CR_375Hz;
}
else if ( sampleRate > 94 )
{
conversionRate = WM97_TOUCHCTRL_CR_187Hz;
}
else
{
conversionRate = WM97_TOUCHCTRL_CR_94Hz;
}
}
/*
* Select and configure continuous mode.
*/
controlVal |= WM97_TOUCHCTRL_SLEN /* Slot enable */
| WM97_AUXADC_SLOT /* Slot selection */
| conversionRate /* Conversion rate */
| settleDelay; /* Settling time */
if ( !(pDeviceContext->v_pADCData->flags & WM_DRVCTX_AUXADC_STREAMING) )
{
/*
* Make sure the digitiser is powered up.
*/
status = WMAuxADCPowerUp( hDevice, WM_POWER_AUXADC_DIGITISER );
if ( WM_ERROR( status ) )
{
goto error;
}
}
/*
* Do a poll with the new settings to get things started.
* Note: it's enough to set the poll bit to kick things off and then
* switch immediately to continuous mode. This way the result will
* come across the slot as normal, but we won't have to wait for our
* first set of results.
*/
if ( WM_USES_ADCSEL( hDevice ) )
{
adcSelVal |= WM_ADCSEL_POLL;
}
else
{
controlVal |= WM_TOUCHCTRL_POLL | adcSelVal;
}
/*
* Now write our control (and ADC selection on WM9705/12)
*/
status = WMWrite( hDevice, WM97_DIGITISER_CONTROL, controlVal );
if ( WM_ERROR( status ) )
{
goto error;
}
/*
* Write the ADCSEL if separate.
*/
if ( WM_USES_ADCSEL( hDevice ) )
{
status = WMWrite( hDevice, WM97_DIGITISER_ADCSEL, adcSelVal );
if ( WM_ERROR( status ) )
{
goto error;
}
}
/*
* Now switch to continuous mode. The poll will complete and send
* the results across the slot, and the timer will start so we'll
* get our readings continuously from now on.
*/
if ( WM_USES_ADCSEL( hDevice ) )
{
adcSelVal = (adcSelVal & ~WM_ADCSEL_POLL) | WM_ADCSEL_CTC;
/*
* Now tell the chip to start the new stream.
*/
status = WMWrite( hDevice, WM97_DIGITISER_ADCSEL, adcSelVal );
if ( WM_ERROR( status ) )
{
goto error;
}
}
else
{
controlVal = (controlVal & ~WM_TOUCHCTRL_POLL) | WM_TOUCHCTRL_CTC;
/*
* Now tell the chip to start the new stream.
*/
status = WMWrite( hDevice, WM97_DIGITISER_CONTROL, controlVal );
if ( WM_ERROR( status ) )
{
goto error;
}
}
/*
* We're streaming.
*/
pDeviceContext->v_pADCData->flags |= WM_DRVCTX_AUXADC_STREAMING;
}
else
{
/*
* Tell the chip to stop streaming.
*/
if ( WM_USES_ADCSEL( hDevice ) )
{
status = WMWrite( hDevice, WM97_DIGITISER_ADCSEL, 0 );
}
else
{
status = WMWrite( hDevice, WM97_DIGITISER_CONTROL, 0 );
}
if ( WM_ERROR( status ) )
{
goto error;
}
/*
* If we're not streaming, power down the digitiser again.
*/
status = WMAuxADCPowerDown( hDevice, WM_POWER_AUXADC_DIGITISER );
if ( WM_ERROR( status ) )
{
goto error;
}
/*
* We're not streaming.
*/
pDeviceContext->v_pADCData->flags &= ~WM_DRVCTX_AUXADC_STREAMING;
}
/*
* It worked.
*/
return WMS_SUCCESS;
error:
/*
* Return the status we received
*/
return status;
}
/*-----------------------------------------------------------------------------
* Function: private_GetAdcSelVal (streaming mode)
*
* Returns the ADCSEL value for the Aux ADC currently selected, appropriate
* for the device in question (i.e. for WM97_DIGITISER_CONTROL for the WM9712,
* for WM97_DIGITISER_ADCSEL for the WM9713).
*
* Note: this _doesn't_ turn on continuous mode.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
*
* Returns: WM_REGVAL
* The ADCSEL value to pass to the ADCSEL sections of the appropriate
* register.
*---------------------------------------------------------------------------*/
static WM_REGVAL private_GetAdcSelVal( WM_DEVICE_HANDLE hDevice )
{
WM_DEVICE_CONTEXT *pDeviceContext = WMHANDLE_TO_DEVICE( hDevice );
WM_REGVAL adcSelVal = 0;
if ( WM_USES_ADCSEL( hDevice ) )
{
adcSelVal = ADCSEL_FROM_BUCKET_MASK( pDeviceContext->v_pADCData->activeADCs );
}
else
{
int bit;
int bitmask;
int activeADCs = pDeviceContext->v_pADCData->activeADCs;
/*
* If we've got touch, turn on coordinate mode, and mask off X and Y
* from our checks.
*/
if ( pDeviceContext->v_pADCData->flags & WM_DRVCTX_AUXADC_TOUCH_STREAMING )
{
adcSelVal |= WM_TOUCHCTRL_COO;
activeADCs &= ~TOUCH_ACTIVE_MASK;
}
/*
* Run through the bits until we find one which is set.
* The '05 and '12 can only do one input (other than touch) at a time,
* so we'll take the first we find (ignoring touch).
*/
for ( bit = 0; bit < ADC_COUNT; bit++ )
{
bitmask = 1U << bit;
if ( activeADCs & bitmask )
{
adcSelVal = ADCADR_FROM_BUCKET_INDEX( bit );
break;
}
}
}
/*
* And return the value we've built up.
*/
return adcSelVal;
}
/*-----------------------------------------------------------------------------
* Function: private_SampleADC (streaming mode)
*
* Returns the next raw sample of the given type, using streaming mode.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
* adcAdr The ADCADR address to look for (from the chipDef).
* pValue Variable to receive the value (between 0 and 0xFFFF).
*
* Returns: WMSTATUS
* See WMStatus.h.
*---------------------------------------------------------------------------*/
static WMSTATUS private_SampleADC( WM_DEVICE_HANDLE hDevice,
WM_REGVAL adcAdr,
WM_REGVAL *pValue
)
{
WM_DEVICE_CONTEXT *pDeviceContext = WMHANDLE_TO_DEVICE( hDevice );
WMSTATUS status = WMS_SUCCESS;
unsigned int bucket;
unsigned short activeFlag;
int sampleCount;
/*
* Protect ourselves from interference.
*/
if ( !WMLockGlobalData( hDevice ) )
{
status = WMS_LOCK_TIMED_OUT;
goto error0;
}
/*
* Work out our bucket.
*/
bucket = BUCKET_INDEX_FROM_ADCADR( adcAdr );
WM_ASSERT( hDevice, bucket < ADC_COUNT );
activeFlag = 1 << bucket;
/*
* Wait for something in our bucket.
*/
sampleCount = 0;
while ( WM_INVALID_SAMPLE == pDeviceContext->v_pADCData->reading[bucket]
&& pDeviceContext->v_pADCData->activeADCs & activeFlag
&& sampleCount < SAMPLE_CYCLE_COUNT
)
{
status = private_GetADCValue( hDevice );
if ( WMS_NO_DATA == status )
{
MicroSleep( hDevice, SAMPLE_DATA_WAIT );
}
else if ( WM_ERROR( status ) )
{
goto error1;
}
sampleCount++;
}
/*
* Read the value.
*/
*pValue = pDeviceContext->v_pADCData->reading[bucket];
if ( WM_INVALID_SAMPLE == *pValue )
{
*pValue = pDeviceContext->v_pADCData->lastReading[bucket];
}
/*
* If we still haven't got anything, give up.
*/
if ( WM_INVALID_SAMPLE == *pValue )
{
/*
* Check we're actually reading this ADC.
*/
if ( !pDeviceContext->v_pADCData->activeADCs & (1 << bucket) )
{
status = WMS_AUXADC_INACTIVE;
}
else
{
status = WMS_NO_DATA;
}
goto error1;
}
/*
* Now we've got something, save it and zap the bucket.
*/
pDeviceContext->v_pADCData->lastReading[bucket] =
pDeviceContext->v_pADCData->reading[bucket];
pDeviceContext->v_pADCData->reading[bucket] = WM_INVALID_SAMPLE;
/*
* Let other threads in.
*/
WMUnlockGlobalData( hDevice );
return WMS_SUCCESS;
/*
* Failure.
*/
error1:
WMUnlockGlobalData( hDevice );
error0:
return status;
}
/*-----------------------------------------------------------------------------
* Function: private_GetADCValue (streaming mode)
*
* Reads the next sample off the stream and puts it into the appropriate
* bucket, using streaming mode.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
*
* Returns: WMSTATUS
* See WMStatus.h.
*---------------------------------------------------------------------------*/
static WMSTATUS private_GetADCValue( WM_DEVICE_HANDLE hDevice )
{
WM_DEVICE_CONTEXT *pDeviceContext = WMHANDLE_TO_DEVICE( hDevice );
WMSTATUS status = WMS_SUCCESS;
unsigned int bucket;
WM_REGVAL adcVal;
status = WMPlatformReadCTCAuxADC( hDevice, &adcVal );
if ( WM_ERROR( status ) )
{
goto error;
}
bucket = BUCKET_INDEX_FROM_ADCADR( adcVal );
if ( bucket >= ADC_COUNT )
{
status = WMS_UNEXPECTED_DATA;
goto error;
}
pDeviceContext->v_pADCData->reading[bucket] = adcVal;
/*
WM_TRACE( hDevice,
( "private_SampleADC: received 0x%X (bucket %d, value 0x%X%s)",
adcVal,
bucket,
adcVal & WM_DATA_VAL,
(adcVal & WM_DATA_PENDOWN) ? ", pen down" : ""
));
*/
return WMS_SUCCESS;
error:
return status;
}
#endif /* WM_STREAM_AUXADC */
#endif /* WM_AUXADC */
/*------------------------------ END OF FILE ---------------------------------*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -