diff -r 000000000000 -r a41df078684a bsptemplate/asspandvariant/template_variant/specific/xyin.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bsptemplate/asspandvariant/template_variant/specific/xyin.cpp Mon Oct 19 15:55:17 2009 +0100 @@ -0,0 +1,1037 @@ +// Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of the License "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// template\Template_Variant\Specific\xyin.cpp +// Implementation of a digitiser (touch-screen) driver. +// This code assumes that an interrupt is generated on pen-down and pen-up events. +// This file is part of the Template Base port +// We use this driver to exemplify the usage of Resource Management for shared resources, Peripheral "Sleep" +// and detection and notification of Wakeup events +// +// + + +#include +#include +#include +#include "mconf.h" +#include +#include "template_power.h" + + + + +// +// TO DO: (mandatory) +// +// Define the following constants that describe the digitiser position & dimensions +// This is only example code... you need to modify it for your hardware + +// digitiser origin & size in pixels +const TUint KConfigXyOffsetX = 0; // digitiser origin - same as display area +const TUint KConfigXyOffsetY = 0; +const TUint KConfigXyWidth = 640; // 640 pixels per line +const TUint KConfigXyHeight = 480; // 480 lines per panel + +// digitiser dimensions in digitiser co-ordinates +const TInt KConfigXyBitsX = 12; +const TInt KConfigXyBitsY = 12; +const TInt KConfigXySpreadX = 1 << KConfigXyBitsX; // maximum valid X spread +const TInt KConfigXySpreadY = 1 << KConfigXyBitsY; // maximum valid Y spread +const TInt KConfigXyMinX = 0; // minimum valid X value +const TInt KConfigXyMinY = 0; // minimum valid Y value +const TInt KConfigXyMaxX = KConfigXySpreadX - 1; // maximum valid X value +const TInt KConfigXyMaxY = KConfigXySpreadY - 1; // maximum valid Y value + + +// Define a 2x2 matrix and two constants Tx and Ty to convert digitiser co-ordinates +// to pixels such that +// +// (X<<16 Y<<16) = (x y) x (R11 R12) + (Tx Ty) +// (R21 R22) +// or : +// +// X = (x*R11 + y*R21 + TX) >> 16; +// Y = (x*R12 + y*R22 + TY) >> 16; + +// +// where x,y are digitiser coordinates, Tx,Ty are constant offsets and X,Y are screen +// coordinates. Left shifting by 16 bits is used so as not to lose precision. +// +// These are default values to be used before calibration has taken place +// These are best set by observation. +// The example values given below are for a digitiser whose origin is at bottom left +// (the screen origin is at top left) +const TInt KConfigXyR11 = (KConfigXyWidth << 16) / KConfigXySpreadX; // 10240 +const TInt KConfigXyR12 = 0; +const TInt KConfigXyR21 = 0; +const TInt KConfigXyR22 = - ((KConfigXyHeight << 16) / KConfigXySpreadY); // -7680 +const TInt KConfigXyTx = 0; +const TInt KConfigXyTy = (KConfigXyHeight << 16) / KConfigXySpreadY; + +// +// TO DO: (optional) +// +// Define the following constants that describe the digitiser behaviour +// This is only example code... you need to modify it for your hardware + +// After taking a sample, wait for the specified number of nano-kernel ticks (normally 1 ms) +// before taking the next sample +const TInt KInterSampleTime = 1; + +// After a group of samples has been processed by the DDigitiser::ProcessRawSample() DFC, +// wait for the specified number of nano-kernel ticks before taking the next sample +const TInt KInterGroupTime = 1; + +// After a pen-down interrupt, +// wait for the specified number of nano-kernel ticks before taking the next sample +const TInt KPenDownDelayTime = 2; + +// If powering up the device with the pen down, +// wait for the specified number of nano-kernel ticks before taking the next sample +const TInt KPenUpPollTime = 30; + +// After a pen-up interrupt, +// wait for the specified number of nano-kernel ticks before calling PenUp() +const TInt KPenUpDebounceTime = 10; + +// number of samples to discard on pen-down +const TInt KConfigXyPenDownDiscard = 1; + +// number of samples to discard on pen-up +const TInt KConfigXyPenUpDiscard = 1; + +// offset in pixels to cause movement in X direction +const TInt KConfigXyAccThresholdX = 12; + +// offset in pixels to cause movement in Y direction +const TInt KConfigXyAccThresholdY = 12; + +// number of samples to average - MUST be <= KMaxXYSamples +const TInt KConfigXyNumXYSamples = 2; + +// disregard extremal values in each 4-sample group +const TBool KConfigXyDisregardMinMax= EFalse; + + + +// obsolete constants : +const TInt KConfigXyDriveXRise = 0; +const TInt KConfigXyDriveYRise = 0; +const TInt KConfigXyMaxJumpX = 0; +const TInt KConfigXyMaxJumpY = 0; + + + +/****************************************************** + * Main Digitiser Class + ******************************************************/ + +// +// TO DO: (optional) +// +// Add any private functions and data you require +// +NONSHARABLE_CLASS(DTemplateDigitiser) : public DDigitiser + { +public: + enum TState + { + E_HW_PowerUp, + E_HW_PenUpDebounce, + E_HW_CollectSample + }; + +public: + // from DDigitiser - initialisation + DTemplateDigitiser(); + virtual TInt DoCreate(); + void SetDefaultConfig(); + + // from DDigitiser - signals to hardware-dependent code + virtual void WaitForPenDown(); + virtual void WaitForPenUp(); + virtual void WaitForPenUpDebounce(); + virtual void DigitiserOn(); + virtual void DigitiserOff(); + virtual void FilterPenMove(const TPoint& aPoint); + virtual void ResetPenMoveFilter(); + + // from DDigitiser - machine-configuration related things + virtual TInt DigitiserToScreen(const TPoint& aDigitiserPoint, TPoint& aScreenPoint); + virtual void ScreenToDigitiser(TInt& aX, TInt& aY); + virtual TInt SetXYInputCalibration(const TDigitizerCalibration& aCalibration); + virtual TInt CalibrationPoints(TDigitizerCalibration& aCalibration); + virtual TInt SaveXYInputCalibration(); + virtual TInt RestoreXYInputCalibration(TDigitizerCalibrationType aType); + virtual void DigitiserInfo(TDigitiserInfoV01& aInfo); + + // from DPowerHandler + virtual void PowerDown(TPowerState); + virtual void PowerUp(); + +public: + // implementation + void TakeSample(); + void PenInterrupt(); + void DigitiserPowerUp(); + void PowerUpDfc(); + +public: + NTimer iTimer; + NTimer iTimerInt; + TDfc iTakeReadingDfc; + TDfc iPowerDownDfc; + TDfc iPowerUpDfc; + TInt iSamplesCount; + TState iState; + TUint8 iPoweringDown; + + TSize iScreenSize; + TActualMachineConfig& iMachineConfig; + }; + +/****************************************************** + * Digitiser main code + ******************************************************/ +/** +Sample timer callback +Schedules a DFC to take a sample + +@param aPtr a pointer to DTemplateDigitiser +*/ +LOCAL_C void timerExpired(TAny* aPtr) + { + DTemplateDigitiser* pD=(DTemplateDigitiser*)aPtr; + __KTRACE_OPT(KHARDWARE,Kern::Printf("T")); + pD->iTakeReadingDfc.Add(); + } + +/** +Debounce timer callback +schedules a DFC to process a pen-down interrupt + +@param aPtr a pointer to DTemplateDigitiser +*/ +LOCAL_C void timerIntExpired(TAny* aPtr) + { + DTemplateDigitiser* pD=(DTemplateDigitiser*)aPtr; + __KTRACE_OPT(KHARDWARE,Kern::Printf("TI")); + // clear xy interrupt -> re-triggers the interrupt mechanism to catch the next IRQ + + // TO DO: (mandatory) + // Write to the appropriate hardware register to clear the digitiser interrupt + // + + pD->iTakeReadingDfc.Add(); + } + +/** +Pen-up/down interrupt handler + +@param aPtr a pointer to DTemplateDigitiser +*/ +LOCAL_C void penInterrupt(TAny* aPtr) + { + DTemplateDigitiser* pD=(DTemplateDigitiser*)aPtr; + pD->PenInterrupt(); + } + +/** +DFC for taking a sample + +@param aPtr a pointer to DTemplateDigitiser +*/ +LOCAL_C void takeReading(TAny* aPtr) + { + DTemplateDigitiser* pD=(DTemplateDigitiser*)aPtr; + pD->TakeSample(); + } + +/** +DFC for powering down the device + +@param aPtr a pointer to DTemplateDigitiser +*/ +LOCAL_C void powerDownDfc(TAny* aPtr) + { + DTemplateDigitiser* pD=(DTemplateDigitiser*)aPtr; + pD->DigitiserOff(); + } + +/** +DFC for powering up the device + +@param aPtr a pointer to DTemplateDigitiser +*/ +LOCAL_C void powerUpDfc(TAny* aPtr) + { + DTemplateDigitiser* pD=(DTemplateDigitiser*)aPtr; + pD->PowerUpDfc(); + } + +/** +Creates a new instance of DDigitiser. +Called by extension entry point (PIL) to create a DDigitiser-derived object. + +@return a pointer to a DTemplateDigitiser object +*/ +DDigitiser* DDigitiser::New() + { + return new DTemplateDigitiser; + } + +/** +Default constructor +*/ +DTemplateDigitiser::DTemplateDigitiser() : + iTimer(timerExpired,this), + iTimerInt(timerIntExpired,this), + iTakeReadingDfc(takeReading,this,5), + iPowerDownDfc(powerDownDfc,this,5), + iPowerUpDfc(powerUpDfc,this,5), + iMachineConfig(TheActualMachineConfig()) + { + iDfcQ = Kern::DfcQue0(); + iTakeReadingDfc.SetDfcQ(iDfcQ); + iPowerDownDfc.SetDfcQ(iDfcQ); + iPowerUpDfc.SetDfcQ(iDfcQ); + } + +/** +Perform hardware-dependent initialisation + +Called by platform independent layer +*/ +TInt DTemplateDigitiser::DoCreate() + { + __KTRACE_OPT(KEXTENSION,Kern::Printf("DTemplateDigitiser::DoCreate")); + + if (Kern::ColdStart()) + { + __KTRACE_OPT(KEXTENSION,Kern::Printf("Resetting digitiser calibration")); + + // Emergency digitiser calibration values + iMachineConfig.iCalibration.iR11 = KConfigXyR11; + iMachineConfig.iCalibration.iR12 = KConfigXyR12; + iMachineConfig.iCalibration.iR21 = KConfigXyR21; + iMachineConfig.iCalibration.iR22 = KConfigXyR22; + iMachineConfig.iCalibration.iTx = KConfigXyTx; + iMachineConfig.iCalibration.iTy = KConfigXyTy; + } + + // register power handler + Add(); + DigitiserPowerUp(); + + // bind to the pen-up/down interrupt + TInt r=Interrupt::Bind(KIntIdDigitiser, penInterrupt, this); + if (r!=KErrNone) + return r; + + // set up the default configuration + SetDefaultConfig(); + + return r; + } + +/** +Initialise the DDigitiser::iCfg structure +*/ +void DTemplateDigitiser::SetDefaultConfig() + { + iCfg.iPenDownDiscard = KConfigXyPenDownDiscard; // number of samples to discard on pen-down + iCfg.iPenUpDiscard = KConfigXyPenUpDiscard; // number of samples to discard on pen-up + iCfg.iDriveXRise = KConfigXyDriveXRise; // number of milliseconds to wait when driving horizontal edges + iCfg.iDriveYRise = KConfigXyDriveYRise; // number of milliseconds to wait when driving vertical edges + iCfg.iMinX = KConfigXyMinX; // minimum valid X value + iCfg.iMaxX = KConfigXyMaxX; // maximum valid X value + iCfg.iSpreadX = KConfigXySpreadX; // maximum valid X spread + iCfg.iMinY = KConfigXyMinY; // minimum valid Y value + iCfg.iMaxY = KConfigXyMaxY; // maximum valid Y value + iCfg.iSpreadY = KConfigXySpreadY; // maximum valid Y spread + iCfg.iMaxJumpX = KConfigXyMaxJumpX; // maximum X movement per sample (pixels) + iCfg.iMaxJumpY = KConfigXyMaxJumpY; // maximum Y movement per sample (pixels) + iCfg.iAccThresholdX = KConfigXyAccThresholdX; // offset in pixels to cause movement in X direction + iCfg.iAccThresholdY = KConfigXyAccThresholdY; // offset in pixels to cause movement in Y direction + iCfg.iNumXYSamples = KConfigXyNumXYSamples; // number of samples to average + iCfg.iDisregardMinMax = KConfigXyDisregardMinMax; // disregard extremal values in each 4-sample group + } + +/** +Takes a sample from the digitiser. +Called in the context of a DFC thread. +*/ +void DTemplateDigitiser::TakeSample() + { + TTemplatePowerController::WakeupEvent(); // notify of pendown (wakeup event) and let the power controller sort + // out if it needs propagation + + TBool penDown = EFalse; + + // TO DO: (mandatory) + // Read from appropriate hardware register to determine whether digitiser panel is being touched + // Set penDown to ETrue if touched or EFalse if not touched. + // + + __KTRACE_OPT(KHARDWARE,Kern::Printf("TS: S%d PD%d Sp%d", (TInt)iState, penDown?1:0, iSamplesCount)); + + if (iState==E_HW_PowerUp) + { + // waiting for pen to go up after switch on due to pen down or through the HAL + // coverity[dead_error_condition] + // The next line should be reachable when this template file is edited for use + if (!penDown) // pen has gone up -> transition to new state + { + iState=E_HW_CollectSample; + iSamplesCount=0; // reset sample buffer + + // TO DO: (mandatory) + // Write to the appropriate hardware register to clear the digitiser interrupt + // + + // TO DO: (mandatory) + // Write to the appropriate hardware register(s) to allow the hardware + // to detect when the digitizer panel is touched + // + + Interrupt::Enable(KIntIdDigitiser); // enable pen-down interrupt + + // TO DO: (mandatory) + // Write to the appropriate hardware register to enable the digitiser interrupt + // + + } + else // pen is still down, wait a bit longer in this state + { + iTimer.OneShot(KPenUpPollTime); + } + return; + } + + if (!penDown) + { + if (iState==E_HW_PenUpDebounce) + { + iState=E_HW_CollectSample; // back to initial state, no samples collected + iSamplesCount=0; // reset sample buffer + // Need to lock the kernel to simulate ISR context and thus defer preemption, + // since PenUp() expects an ISR context and calls TDfc::Add(). + NKern::Lock(); + PenUp(); // adds DFC + NKern::Unlock(); + } + else // iState=E_HW_CollectSample + { + iState=E_HW_PenUpDebounce; + iTimer.OneShot(KPenUpDebounceTime); // wait a bit to make sure pen still up + } + return; + } + else if (iState==E_HW_PenUpDebounce) // pen down + { + // false alarm - pen is down again + iState=E_HW_CollectSample; // take a new set of samples + iSamplesCount=0; // reset sample buffer + } + // default: pen down and iState=E_HW_CollectSample + + // TO DO: (mandatory) + // Read from appropriate hardware register to get the current digitiser coordinates + // of the point that is being touched. Set aResults accordingly. + // This is only example code... you need to modify it for your hardware + // + TPoint aResults; + + // X axis + iX[iSamplesCount] = aResults.iX; + // Y axis + iY[iSamplesCount] = aResults.iY; + + __KTRACE_OPT(KHARDWARE,Kern::Printf("Raw: X=%d Y=%d",iX[iSamplesCount],iY[iSamplesCount])); + + // Put the hardware back into pen-detect mode + + // TO DO: (mandatory) + // Write to the appropriate hardware register(s) to allow the hardware + // to detect when the digitizer panel is touched + // + + // count samples collected - if it's less than minimum, + // schedule the reading of another sample + if (++iSamplesCount < iCfg.iNumXYSamples) // iX[] and iY[] are 4 levels deep in xyin.h... + { + if(KInterSampleTime > 0) // need to check this config param as it might be zero! + iTimer.OneShot(KInterSampleTime); // haven't got a complete group yet, so queue timer to sample again + else + iTakeReadingDfc.Enque(); + return; + } + + // Have a complete group of samples so pass up to processing layer (PIL) + + // Need to lock the kernel to simulate ISR context and thus defer preemption, + // since RawSampleValid() expects an ISR context and calls TDfc::Add(). + NKern::Lock(); + RawSampleValid(); // adds DFC + NKern::Unlock(); + } + +/** +Request for an interrupt to be generated when the pen is next down +Called by PIL at startup or when pen leaves digitiser after pen-up event issued +*/ +void DTemplateDigitiser::WaitForPenDown() + { + // Called at startup or when pen leaves digitiser after pen-up event issued + __KTRACE_OPT(KHARDWARE,Kern::Printf("WD: PowerDownMask %x",iPoweringDown)); + if (iPoweringDown) + { + // powering down + + // TO DO: (mandatory) + // Write to the appropriate hardware register(s) to allow the hardware + // to detect when the digitizer panel is touched and wakes up the system if in standby + // + + // + // TO DO: (optional) + // + // Relinquish request on power resources + // This will place the peripheral hardware in a low power "Sleep" mode which is Interrupt detection capable + // EXAMPLE ONLY + // + TemplateResourceManager* aManager = TTemplatePowerController::ResourceManager(); + aManager -> ModifyToLevel(TemplateResourceManager::AsynchMlResourceUsedByXOnly, 50 /* a percentage */); + aManager -> SharedBResource1() -> Release(); + + iPoweringDown = EFalse; + PowerDownDone(); + } + else + { + + // TO DO: (mandatory) + // Write to the appropriate hardware register to clear the digitiser interrupt + // + + // TO DO: (mandatory) + // Write to the appropriate hardware register(s) to allow the hardware + // to detect when the digitizer panel is touched + // + + if ((iTimer.iState == NTimer::EIdle) && (iTimerInt.iState == NTimer::EIdle)) + Interrupt::Enable(KIntIdDigitiser); // enable pen-down interrupt + } + } + +/** +Called by PIL after it has processed a group of raw samples while pen is down. +Used to indicate that the iX, iY buffers may be re-used +*/ +void DTemplateDigitiser::WaitForPenUp() + { + __KTRACE_OPT(KHARDWARE,Kern::Printf("WU")); + iState = E_HW_CollectSample; + iSamplesCount = 0; // reset sample buffer + if(KInterGroupTime > 0) // need to check this config param as it might be zero! + iTimer.OneShot(KInterGroupTime); + else + iTakeReadingDfc.Enque(); + } + +/** +Called by PIL if the group of samples collected is not good enough +Used to indicate that the iX, iY buffers may be re-used +*/ +void DTemplateDigitiser::WaitForPenUpDebounce() + { + __KTRACE_OPT(KHARDWARE,Kern::Printf("WUDB")); + iState = E_HW_CollectSample; + iSamplesCount = 0; // reset sample buffer + if(KInterGroupTime > 0) // need to check this config param as it might be zero! + iTimer.OneShot(KInterGroupTime); + else + iTakeReadingDfc.Enque(); + } + +/** +Pen up/down interrupt service routine (ISR) +*/ +void DTemplateDigitiser::PenInterrupt() + { + __KTRACE_OPT(KHARDWARE,Kern::Printf("I")); + + + Interrupt::Clear(KIntIdDigitiser); // should already have been cleared + + // TO DO: (mandatory) + // Read from appropriate hardware register to determine whether digitiser panel is being touched + // Set penDown to ETrue if touched or EFalse if not touched. + // This is only example code... you need to modify it for your hardware + TBool penDown = EFalse; + + // coverity[dead_error_condition] + if(!penDown) // pen up + { + + // TO DO: (mandatory) + // Write to the appropriate hardware register to clear the digitiser interrupt + // + + // TO DO: (mandatory) + // Write to the appropriate hardware register(s) to allow the hardware + // to detect when the digitizer panel is touched + // + + return; // ... and exit! + } + + Interrupt::Disable(KIntIdDigitiser); // do NOT disable the capability to generate interrupts at the source + + if (KPenDownDelayTime>0) // need to check this config param as it might be zero! + iTimerInt.OneShot(KPenDownDelayTime); // start a debounce timer which will queue a DFC to process the interrupt + else + { + + // TO DO: (mandatory) + // Write to the appropriate hardware register to clear the digitiser interrupt + // This will re-trigger the interrupt mechanism to catch the next interrupt... + // + + iTakeReadingDfc.Add(); + } + } + +/** +DPowerHandler pure virtual +*/ +void DTemplateDigitiser::PowerUp() + { + iPowerUpDfc.Enque(); // queue a DFC in this driver's context + } + +/** +Called by power up DFC +*/ +void DTemplateDigitiser::PowerUpDfc() + { + __KTRACE_OPT(KPOWER, Kern::Printf("DTemplateDigitiser::PowerUpDfc()")); + DigitiserOn(); + PowerUpDone(); // must be called from a different thread than PowerUp() + } + +/** +Turn the digitiser on +May be called as a result of a power transition or from the HAL +If called from HAL, then the digitiser may be already be on (iPointerOn == ETrue) +*/ +void DTemplateDigitiser::DigitiserOn() + { + __KTRACE_OPT(KPOWER,Kern::Printf("DTemplateDigitiser::DigitiserOn() iPointerOn=%d", iPointerOn)); + + if (!iPointerOn) // may have been powered up already + DigitiserPowerUp(); + } + +/** +Power-up the digitiser. Assumes digitiser is off. +*/ +void DTemplateDigitiser::DigitiserPowerUp() + { + __KTRACE_OPT(KPOWER, Kern::Printf("DigitiserPowerUp")); + iPointerOn = ETrue; // now turned on + + // TO DO: (mandatory) + // Write to the appropriate hardware register to clear the digitiser interrupt + // + + // + // TO DO: (optional) + // + // Reassert request on power resources + // This will move the peripheral hardware out of low power "Sleep" mode back to fully operational + // EXAMPLE ONLY + // + TemplateResourceManager* aManager = TTemplatePowerController::ResourceManager(); + aManager -> ModifyToLevel(TemplateResourceManager::AsynchMlResourceUsedByXOnly, 100 /* a percentage */); + aManager -> SharedBResource1() -> Use(); + + // TO DO: (mandatory) + // Write to the appropriate hardware register(s) to allow the hardware + // to detect when the digitizer panel is touched + // + + iState = E_HW_PowerUp; // so we wait for pen up if necessary + iTakeReadingDfc.Enque(); + } + +/** +DPowerHandler pure virtual + +@param aPowerState the current power state +*/ +void DTemplateDigitiser::PowerDown(TPowerState /*aPowerState*/) + { + iPoweringDown = ETrue; + iPowerDownDfc.Enque(); // queue a DFC in this driver's context + } + +/** +Turn the digitiser off +May be called as a result of a power transition or from the HAL +If called from Power Manager, then the digitiser may be already be off (iPointerOn == EFalse) +if the platform is in silent running mode +*/ +void DTemplateDigitiser::DigitiserOff() + { + __KTRACE_OPT(KPOWER,Kern::Printf("DTemplateDigitiser::DigitiserOff() iPointerOn=%d", iPointerOn)); + if (iPointerOn) // can have been powered down from HAL + { + iPointerOn = EFalse; + Interrupt::Disable(KIntIdDigitiser); + + // TO DO: (mandatory) + // Write to the appropriate hardware register to disable the digitiser interrupt + // + + iTimer.Cancel(); + iTimerInt.Cancel(); + iTakeReadingDfc.Cancel(); + if (iState != E_HW_CollectSample) + { + // Need to lock the kernel to simulate ISR context and thus defer preemption, + // since PenUp() expects an ISR context and calls TDfc::Add(). + NKern::Lock(); + PenUp(); // adds DFC (will call WaitForPenDown) + NKern::Unlock(); + } + else + { + + // TO DO: (mandatory) + // Write to the appropriate hardware register(s) to allow the hardware + // to detect when the digitizer panel is touched and wakes up the system if in standby + // + + // + // TO DO: (optional) + // + // Relinquish request on power resources as we are being powered down + // This will place the peripheral hardware in a low power "Sleep" mode which is Interrupt detection capable + // EXAMPLE ONLY + // + TemplateResourceManager* aManager = TTemplatePowerController::ResourceManager(); + aManager -> ModifyToLevel(TemplateResourceManager::AsynchMlResourceUsedByXOnly, 0 /* a percentage */); + aManager -> SharedBResource1() -> Release(); + + if (iPoweringDown) // came here through PowerDown + { + iPoweringDown = EFalse; + PowerDownDone(); + } + } + } + else // already powered down (by HAL) + { + if (iPoweringDown) // came here through PowerDown + { + iPoweringDown = EFalse; + PowerDownDone(); + } + } + } + + + + +/** +Convert digitiser coordinates to screen coordinates + +@param aDigitiserPoint the digitiser coordinates +@param aScreenPoint A TPoint supplied by the caller. + On return, set to the converted screen coordinates in pixels. + +@return KErrNone if successful +*/ +TInt DTemplateDigitiser::DigitiserToScreen(const TPoint& aDigitiserPoint, TPoint& aScreenPoint) + { + NKern::LockSystem(); + TInt R11 = iMachineConfig.iCalibration.iR11; + TInt R12 = iMachineConfig.iCalibration.iR12; + TInt R21 = iMachineConfig.iCalibration.iR21; + TInt R22 = iMachineConfig.iCalibration.iR22; + TInt TX = iMachineConfig.iCalibration.iTx; + TInt TY = iMachineConfig.iCalibration.iTy; + NKern::UnlockSystem(); + TInt X = aDigitiserPoint.iX; + TInt Y = aDigitiserPoint.iY; + + aScreenPoint.iX = (X*R11 + Y*R21 + TX) >> 16; + aScreenPoint.iY = (X*R12 + Y*R22 + TY) >> 16; + + __KTRACE_OPT(KHARDWARE,Kern::Printf("DtS: Dp.x %d, Dp.y %d, Sp.x %d, Sp.y %d", X,Y,aScreenPoint.iX,aScreenPoint.iY)); + + return KErrNone; + } + +/** +Convert screen coordinates back into digitiser coordinates +using the current constants from the superpage + +@param aX The screen X coordinate in pixels; On return, set to the digitiser X coordinate. +@param aY The screen Y coordinate in pixels; On return, set to the digitiser Y coordinate. +*/ +void DTemplateDigitiser::ScreenToDigitiser(TInt& aX, TInt& aY) + { + NKern::LockSystem(); + Int64 R11 = iMachineConfig.iCalibration.iR11; + Int64 R12 = iMachineConfig.iCalibration.iR12; + Int64 R21 = iMachineConfig.iCalibration.iR21; + Int64 R22 = iMachineConfig.iCalibration.iR22; + Int64 TX = iMachineConfig.iCalibration.iTx; + Int64 TY = iMachineConfig.iCalibration.iTy; + NKern::UnlockSystem(); + Int64 X = aX; + Int64 Y = aY; + // + // Xd=(Xs<<16)*R22-(Ys<<16)*R21-(TX*R22)+(TY*R21) + // ------------------------------------------- + // (R22*R11)-(R21*R12) + // + // + // Yd=(Xs<<16)*R12-(Ys<<16)*R11-(TX*R12)+(TY*R11) + // ------------------------------------------- + // (R21*R12)-(R22*R11) + // + // where Xd and Yd are digitiser coordinates + // Xs and Ys are supplied screen coordinates + // + X<<=16; + Y<<=16; + + Int64 d=Int64(R21)*Int64(R12)-Int64(R22)*Int64(R11); + + Int64 r=(X*R12)-(Y*R11)-(TX*R12)+(TY*R11); + + r=r/d; + + aY=(TInt)r; + + r=(X*R22)-(Y*R21)-(TX*R22)+(TY*R21); + + r=r/(-d); + + aX=(TInt)r; + } + +/** +Calculate values for R11, R12, R21, R22, TX and TY + +@param aCalibration the screen coordinates of points touched +@return KErrNone if successful +*/ +TInt DTemplateDigitiser::SetXYInputCalibration(const TDigitizerCalibration& aCalibration) + { + TInt R11,R12,R21,R22,TX,TY; + // + // Get coords of expected points + // + TDigitizerCalibration cal; + TInt ret=CalibrationPoints(cal); + if (ret!=KErrNone) + return ret; + + TInt Xp1=cal.iTl.iX; + TInt Yp1=cal.iTl.iY; + TInt Xp2=cal.iBl.iX; + TInt Yp2=cal.iBl.iY; + TInt Xp3=cal.iBr.iX; + TInt Yp3=cal.iBr.iY; + // + // Get coords of points touched in screen coordinates + // + TInt X1=aCalibration.iTl.iX; + TInt Y1=aCalibration.iTl.iY; + TInt X2=aCalibration.iBl.iX; + TInt Y2=aCalibration.iBl.iY; + TInt X3=aCalibration.iBr.iX; + TInt Y3=aCalibration.iBr.iY; + // + // Convert back to raw digitiser coordinates + // + ScreenToDigitiser(X1,Y1); + ScreenToDigitiser(X2,Y2); + ScreenToDigitiser(X3,Y3); + // + // (Y1-Y2)(Xp1-Xp3) - (Y1-Y3)(Xp1-Xp2) + // ----------------------------------- = R11 + // (Y1-Y2)(X1-X3) - (Y1-Y3)(X1-X2) + // + Int64 r=((Int64(Y1-Y2)*Int64(Xp1-Xp3))-(Int64(Y1-Y3)*Int64(Xp1-Xp2))); + r<<=16; + r/=(Int64(Y1-Y2)*Int64(X1-X3)-Int64(Y1-Y3)*Int64(X1-X2)); + R11=(TInt)r; + // + // (Y1-Y2)(Yp1-Yp3) - (Y1-Y3)(Yp1-Yp2) + // ----------------------------------- = R12 + // (Y1-Y2)(X1-X3) - (Y1-Y3)(X1-X2) + // + r=((Int64(Y1-Y2)*Int64(Yp1-Yp3))-(Int64(Y1-Y3)*Int64(Yp1-Yp2))); + r<<=16; + r/=(Int64(Y1-Y2)*Int64(X1-X3)-Int64(Y1-Y3)*Int64(X1-X2)); + R12=(TInt)r; + // + // (X1-X3)(Xp2-Xp3) - (X2-X3)(Xp1-Xp3) + // ----------------------------------- = R21 + // (Y2-Y3)(X1-X3) - (Y1-Y3)(X2-X3) + // + r=(((X1-X3)*(Xp2-Xp3))-((X2-X3)*(Xp1-Xp3))); + r<<=16; + r/=(Int64(Y2-Y3)*Int64(X1-X3)-Int64(Y1-Y3)*Int64(X2-X3)); + R21=(TInt)r; + // + // (X1-X3)(Yp2-Yp3) - (X2-X3)(Yp1-Yp3) + // ----------------------------------- = R22 + // (Y2-Y3)(X1-X3) - (Y1-Y3)(X2-X3) + // + r=((Int64(X1-X3)*Int64(Yp2-Yp3))-(Int64(X2-X3)*Int64(Yp1-Yp3))); + r<<=16; + r/=(Int64(Y2-Y3)*Int64(X1-X3)-Int64(Y1-Y3)*Int64(X2-X3)); + R22=(TInt)r; + // + // TX = Xp1 - X1*R11 - Y1*R21 + // + TX=(Xp1<<16)-(X1*R11)-(Y1*R21); + // + // TY = Yp1 - X1*R12 - Y1*R22 + // + TY=(Yp1<<16)-(X1*R12)-(Y1*R22); + + // + // Write new values into the superpage + // + NKern::LockSystem(); + iMachineConfig.iCalibration.iR11 = R11; + iMachineConfig.iCalibration.iR12 = R12; + iMachineConfig.iCalibration.iR21 = R21; + iMachineConfig.iCalibration.iR22 = R22; + iMachineConfig.iCalibration.iTx = TX; + iMachineConfig.iCalibration.iTy = TY; + NKern::UnlockSystem(); + + return(KErrNone); + } + +/** +Informs the user-side calibration application where to draw +the cross-hairs on the screen + +@param aCalibration On return contains the for points on the screen (in screen coordinates) + where the cross-hairs should be drawn +@return KErrNone if succcessful +*/ +TInt DTemplateDigitiser::CalibrationPoints(TDigitizerCalibration& aCalibration) + { + TVideoInfoV01Buf buf; + TVideoInfoV01& vidinfo=buf(); + TInt r = Kern::HalFunction(EHalGroupDisplay, EDisplayHalCurrentModeInfo, (TAny*)&buf, NULL); + if (r!=KErrNone) + return r; + iScreenSize=vidinfo.iSizeInPixels; + + aCalibration.iBl.iX = aCalibration.iTl.iX = iScreenSize.iWidth/10; + aCalibration.iTr.iY = aCalibration.iTl.iY = iScreenSize.iHeight/10; + aCalibration.iBr.iY = aCalibration.iBl.iY = iScreenSize.iHeight-iScreenSize.iHeight/10; + aCalibration.iTr.iX = aCalibration.iBr.iX = iScreenSize.iWidth-iScreenSize.iWidth/10; + return r; + } +/** +Saves the digitiser calibration to the persistent machine configuration area +so that it can be restored after a power-down/up + +@return KErrNone if succcessful +*/ +TInt DTemplateDigitiser::SaveXYInputCalibration() + { + NKern::LockSystem(); + iMachineConfig.iCalibrationSaved = iMachineConfig.iCalibration; + NKern::UnlockSystem(); + return(KErrNone); + } + +/** +Restores the digitiser calibration from the persistent machine configuration area +following a power-up + +@param aType indicates whether to restore factory or saved settings +@return KErrNone if succcessful +*/ +TInt DTemplateDigitiser::RestoreXYInputCalibration(TDigitizerCalibrationType aType) + { + TInt r=KErrNone; + NKern::LockSystem(); + switch (aType) + { + case EFactory: + iMachineConfig.iCalibration=iMachineConfig.iCalibrationFactory; + break; + case ESaved: + iMachineConfig.iCalibration=iMachineConfig.iCalibrationSaved; + break; + default: + r=KErrNotSupported; + break; + } + NKern::UnlockSystem(); + return r; + } + +/** +Gets the digitiser configuration information + +@param aInfo On return, contains information about the digitiser's dimensions etc. +*/ +void DTemplateDigitiser::DigitiserInfo(TDigitiserInfoV01& aInfo) + { + __KTRACE_OPT(KEXTENSION,Kern::Printf("DTemplateDigitiser::DigitiserInfo")); + aInfo.iDigitiserSize.iWidth=KConfigXyWidth; + aInfo.iDigitiserSize.iHeight=KConfigXyHeight; + aInfo.iOffsetToDisplay.iX=KConfigXyOffsetX; + aInfo.iOffsetToDisplay.iY=KConfigXyOffsetY; + } + +/** +Issues a pen move event if the distance from the last point is greater than the threshold + +@param aPoint the pen position in screen coordinates +*/ +void DTemplateDigitiser::FilterPenMove(const TPoint& aPoint) + { + TPoint offset=aPoint; + offset.iX-=iLastPos.iX; + offset.iY-=iLastPos.iY; + if (Abs(offset.iX)>=iCfg.iAccThresholdX || Abs(offset.iY)>=iCfg.iAccThresholdY) + { + iLastPos=aPoint; + IssuePenMoveEvent(aPoint); + } + } + +/** +Reset the pen move filter +*/ +void DTemplateDigitiser::ResetPenMoveFilter() + { + } +