Update contrib.
1 // Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of the License "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // template\Template_Variant\Specific\xyin.cpp
15 // Implementation of a digitiser (touch-screen) driver.
16 // This code assumes that an interrupt is generated on pen-down and pen-up events.
17 // This file is part of the Template Base port
18 // We use this driver to exemplify the usage of Resource Management for shared resources, Peripheral "Sleep"
19 // and detection and notification of Wakeup events
25 #include <template_assp.h>
26 #include <videodriver.h>
28 #include <drivers/xyin.h>
29 #include "template_power.h"
37 // Define the following constants that describe the digitiser position & dimensions
38 // This is only example code... you need to modify it for your hardware
40 // digitiser origin & size in pixels
41 const TUint KConfigXyOffsetX = 0; // digitiser origin - same as display area
42 const TUint KConfigXyOffsetY = 0;
43 const TUint KConfigXyWidth = 640; // 640 pixels per line
44 const TUint KConfigXyHeight = 480; // 480 lines per panel
46 // digitiser dimensions in digitiser co-ordinates
47 const TInt KConfigXyBitsX = 12;
48 const TInt KConfigXyBitsY = 12;
49 const TInt KConfigXySpreadX = 1 << KConfigXyBitsX; // maximum valid X spread
50 const TInt KConfigXySpreadY = 1 << KConfigXyBitsY; // maximum valid Y spread
51 const TInt KConfigXyMinX = 0; // minimum valid X value
52 const TInt KConfigXyMinY = 0; // minimum valid Y value
53 const TInt KConfigXyMaxX = KConfigXySpreadX - 1; // maximum valid X value
54 const TInt KConfigXyMaxY = KConfigXySpreadY - 1; // maximum valid Y value
57 // Define a 2x2 matrix and two constants Tx and Ty to convert digitiser co-ordinates
58 // to pixels such that
60 // (X<<16 Y<<16) = (x y) x (R11 R12) + (Tx Ty)
64 // X = (x*R11 + y*R21 + TX) >> 16;
65 // Y = (x*R12 + y*R22 + TY) >> 16;
68 // where x,y are digitiser coordinates, Tx,Ty are constant offsets and X,Y are screen
69 // coordinates. Left shifting by 16 bits is used so as not to lose precision.
71 // These are default values to be used before calibration has taken place
72 // These are best set by observation.
73 // The example values given below are for a digitiser whose origin is at bottom left
74 // (the screen origin is at top left)
75 const TInt KConfigXyR11 = (KConfigXyWidth << 16) / KConfigXySpreadX; // 10240
76 const TInt KConfigXyR12 = 0;
77 const TInt KConfigXyR21 = 0;
78 const TInt KConfigXyR22 = - ((KConfigXyHeight << 16) / KConfigXySpreadY); // -7680
79 const TInt KConfigXyTx = 0;
80 const TInt KConfigXyTy = (KConfigXyHeight << 16) / KConfigXySpreadY;
85 // Define the following constants that describe the digitiser behaviour
86 // This is only example code... you need to modify it for your hardware
88 // After taking a sample, wait for the specified number of nano-kernel ticks (normally 1 ms)
89 // before taking the next sample
90 const TInt KInterSampleTime = 1;
92 // After a group of samples has been processed by the DDigitiser::ProcessRawSample() DFC,
93 // wait for the specified number of nano-kernel ticks before taking the next sample
94 const TInt KInterGroupTime = 1;
96 // After a pen-down interrupt,
97 // wait for the specified number of nano-kernel ticks before taking the next sample
98 const TInt KPenDownDelayTime = 2;
100 // If powering up the device with the pen down,
101 // wait for the specified number of nano-kernel ticks before taking the next sample
102 const TInt KPenUpPollTime = 30;
104 // After a pen-up interrupt,
105 // wait for the specified number of nano-kernel ticks before calling PenUp()
106 const TInt KPenUpDebounceTime = 10;
108 // number of samples to discard on pen-down
109 const TInt KConfigXyPenDownDiscard = 1;
111 // number of samples to discard on pen-up
112 const TInt KConfigXyPenUpDiscard = 1;
114 // offset in pixels to cause movement in X direction
115 const TInt KConfigXyAccThresholdX = 12;
117 // offset in pixels to cause movement in Y direction
118 const TInt KConfigXyAccThresholdY = 12;
120 // number of samples to average - MUST be <= KMaxXYSamples
121 const TInt KConfigXyNumXYSamples = 2;
123 // disregard extremal values in each 4-sample group
124 const TBool KConfigXyDisregardMinMax= EFalse;
128 // obsolete constants :
129 const TInt KConfigXyDriveXRise = 0;
130 const TInt KConfigXyDriveYRise = 0;
131 const TInt KConfigXyMaxJumpX = 0;
132 const TInt KConfigXyMaxJumpY = 0;
136 /******************************************************
137 * Main Digitiser Class
138 ******************************************************/
143 // Add any private functions and data you require
145 NONSHARABLE_CLASS(DTemplateDigitiser) : public DDigitiser
156 // from DDigitiser - initialisation
157 DTemplateDigitiser();
158 virtual TInt DoCreate();
159 void SetDefaultConfig();
161 // from DDigitiser - signals to hardware-dependent code
162 virtual void WaitForPenDown();
163 virtual void WaitForPenUp();
164 virtual void WaitForPenUpDebounce();
165 virtual void DigitiserOn();
166 virtual void DigitiserOff();
167 virtual void FilterPenMove(const TPoint& aPoint);
168 virtual void ResetPenMoveFilter();
170 // from DDigitiser - machine-configuration related things
171 virtual TInt DigitiserToScreen(const TPoint& aDigitiserPoint, TPoint& aScreenPoint);
172 virtual void ScreenToDigitiser(TInt& aX, TInt& aY);
173 virtual TInt SetXYInputCalibration(const TDigitizerCalibration& aCalibration);
174 virtual TInt CalibrationPoints(TDigitizerCalibration& aCalibration);
175 virtual TInt SaveXYInputCalibration();
176 virtual TInt RestoreXYInputCalibration(TDigitizerCalibrationType aType);
177 virtual void DigitiserInfo(TDigitiserInfoV01& aInfo);
179 // from DPowerHandler
180 virtual void PowerDown(TPowerState);
181 virtual void PowerUp();
187 void DigitiserPowerUp();
193 TDfc iTakeReadingDfc;
198 TUint8 iPoweringDown;
201 TActualMachineConfig& iMachineConfig;
204 /******************************************************
205 * Digitiser main code
206 ******************************************************/
208 Sample timer callback
209 Schedules a DFC to take a sample
211 @param aPtr a pointer to DTemplateDigitiser
213 LOCAL_C void timerExpired(TAny* aPtr)
215 DTemplateDigitiser* pD=(DTemplateDigitiser*)aPtr;
216 __KTRACE_OPT(KHARDWARE,Kern::Printf("T"));
217 pD->iTakeReadingDfc.Add();
221 Debounce timer callback
222 schedules a DFC to process a pen-down interrupt
224 @param aPtr a pointer to DTemplateDigitiser
226 LOCAL_C void timerIntExpired(TAny* aPtr)
228 DTemplateDigitiser* pD=(DTemplateDigitiser*)aPtr;
229 __KTRACE_OPT(KHARDWARE,Kern::Printf("TI"));
230 // clear xy interrupt -> re-triggers the interrupt mechanism to catch the next IRQ
232 // TO DO: (mandatory)
233 // Write to the appropriate hardware register to clear the digitiser interrupt
236 pD->iTakeReadingDfc.Add();
240 Pen-up/down interrupt handler
242 @param aPtr a pointer to DTemplateDigitiser
244 LOCAL_C void penInterrupt(TAny* aPtr)
246 DTemplateDigitiser* pD=(DTemplateDigitiser*)aPtr;
251 DFC for taking a sample
253 @param aPtr a pointer to DTemplateDigitiser
255 LOCAL_C void takeReading(TAny* aPtr)
257 DTemplateDigitiser* pD=(DTemplateDigitiser*)aPtr;
262 DFC for powering down the device
264 @param aPtr a pointer to DTemplateDigitiser
266 LOCAL_C void powerDownDfc(TAny* aPtr)
268 DTemplateDigitiser* pD=(DTemplateDigitiser*)aPtr;
273 DFC for powering up the device
275 @param aPtr a pointer to DTemplateDigitiser
277 LOCAL_C void powerUpDfc(TAny* aPtr)
279 DTemplateDigitiser* pD=(DTemplateDigitiser*)aPtr;
284 Creates a new instance of DDigitiser.
285 Called by extension entry point (PIL) to create a DDigitiser-derived object.
287 @return a pointer to a DTemplateDigitiser object
289 DDigitiser* DDigitiser::New()
291 return new DTemplateDigitiser;
297 DTemplateDigitiser::DTemplateDigitiser() :
298 iTimer(timerExpired,this),
299 iTimerInt(timerIntExpired,this),
300 iTakeReadingDfc(takeReading,this,5),
301 iPowerDownDfc(powerDownDfc,this,5),
302 iPowerUpDfc(powerUpDfc,this,5),
303 iMachineConfig(TheActualMachineConfig())
305 iDfcQ = Kern::DfcQue0();
306 iTakeReadingDfc.SetDfcQ(iDfcQ);
307 iPowerDownDfc.SetDfcQ(iDfcQ);
308 iPowerUpDfc.SetDfcQ(iDfcQ);
312 Perform hardware-dependent initialisation
314 Called by platform independent layer
316 TInt DTemplateDigitiser::DoCreate()
318 __KTRACE_OPT(KEXTENSION,Kern::Printf("DTemplateDigitiser::DoCreate"));
320 if (Kern::ColdStart())
322 __KTRACE_OPT(KEXTENSION,Kern::Printf("Resetting digitiser calibration"));
324 // Emergency digitiser calibration values
325 iMachineConfig.iCalibration.iR11 = KConfigXyR11;
326 iMachineConfig.iCalibration.iR12 = KConfigXyR12;
327 iMachineConfig.iCalibration.iR21 = KConfigXyR21;
328 iMachineConfig.iCalibration.iR22 = KConfigXyR22;
329 iMachineConfig.iCalibration.iTx = KConfigXyTx;
330 iMachineConfig.iCalibration.iTy = KConfigXyTy;
333 // register power handler
337 // bind to the pen-up/down interrupt
338 TInt r=Interrupt::Bind(KIntIdDigitiser, penInterrupt, this);
342 // set up the default configuration
349 Initialise the DDigitiser::iCfg structure
351 void DTemplateDigitiser::SetDefaultConfig()
353 iCfg.iPenDownDiscard = KConfigXyPenDownDiscard; // number of samples to discard on pen-down
354 iCfg.iPenUpDiscard = KConfigXyPenUpDiscard; // number of samples to discard on pen-up
355 iCfg.iDriveXRise = KConfigXyDriveXRise; // number of milliseconds to wait when driving horizontal edges
356 iCfg.iDriveYRise = KConfigXyDriveYRise; // number of milliseconds to wait when driving vertical edges
357 iCfg.iMinX = KConfigXyMinX; // minimum valid X value
358 iCfg.iMaxX = KConfigXyMaxX; // maximum valid X value
359 iCfg.iSpreadX = KConfigXySpreadX; // maximum valid X spread
360 iCfg.iMinY = KConfigXyMinY; // minimum valid Y value
361 iCfg.iMaxY = KConfigXyMaxY; // maximum valid Y value
362 iCfg.iSpreadY = KConfigXySpreadY; // maximum valid Y spread
363 iCfg.iMaxJumpX = KConfigXyMaxJumpX; // maximum X movement per sample (pixels)
364 iCfg.iMaxJumpY = KConfigXyMaxJumpY; // maximum Y movement per sample (pixels)
365 iCfg.iAccThresholdX = KConfigXyAccThresholdX; // offset in pixels to cause movement in X direction
366 iCfg.iAccThresholdY = KConfigXyAccThresholdY; // offset in pixels to cause movement in Y direction
367 iCfg.iNumXYSamples = KConfigXyNumXYSamples; // number of samples to average
368 iCfg.iDisregardMinMax = KConfigXyDisregardMinMax; // disregard extremal values in each 4-sample group
372 Takes a sample from the digitiser.
373 Called in the context of a DFC thread.
375 void DTemplateDigitiser::TakeSample()
377 TTemplatePowerController::WakeupEvent(); // notify of pendown (wakeup event) and let the power controller sort
378 // out if it needs propagation
380 TBool penDown = EFalse;
382 // TO DO: (mandatory)
383 // Read from appropriate hardware register to determine whether digitiser panel is being touched
384 // Set penDown to ETrue if touched or EFalse if not touched.
387 __KTRACE_OPT(KHARDWARE,Kern::Printf("TS: S%d PD%d Sp%d", (TInt)iState, penDown?1:0, iSamplesCount));
389 if (iState==E_HW_PowerUp)
391 // waiting for pen to go up after switch on due to pen down or through the HAL
392 // coverity[dead_error_condition]
393 // The next line should be reachable when this template file is edited for use
394 if (!penDown) // pen has gone up -> transition to new state
396 iState=E_HW_CollectSample;
397 iSamplesCount=0; // reset sample buffer
399 // TO DO: (mandatory)
400 // Write to the appropriate hardware register to clear the digitiser interrupt
403 // TO DO: (mandatory)
404 // Write to the appropriate hardware register(s) to allow the hardware
405 // to detect when the digitizer panel is touched
408 Interrupt::Enable(KIntIdDigitiser); // enable pen-down interrupt
410 // TO DO: (mandatory)
411 // Write to the appropriate hardware register to enable the digitiser interrupt
415 else // pen is still down, wait a bit longer in this state
417 iTimer.OneShot(KPenUpPollTime);
424 if (iState==E_HW_PenUpDebounce)
426 iState=E_HW_CollectSample; // back to initial state, no samples collected
427 iSamplesCount=0; // reset sample buffer
428 // Need to lock the kernel to simulate ISR context and thus defer preemption,
429 // since PenUp() expects an ISR context and calls TDfc::Add().
434 else // iState=E_HW_CollectSample
436 iState=E_HW_PenUpDebounce;
437 iTimer.OneShot(KPenUpDebounceTime); // wait a bit to make sure pen still up
441 else if (iState==E_HW_PenUpDebounce) // pen down
443 // false alarm - pen is down again
444 iState=E_HW_CollectSample; // take a new set of samples
445 iSamplesCount=0; // reset sample buffer
447 // default: pen down and iState=E_HW_CollectSample
449 // TO DO: (mandatory)
450 // Read from appropriate hardware register to get the current digitiser coordinates
451 // of the point that is being touched. Set aResults accordingly.
452 // This is only example code... you need to modify it for your hardware
457 iX[iSamplesCount] = aResults.iX;
459 iY[iSamplesCount] = aResults.iY;
461 __KTRACE_OPT(KHARDWARE,Kern::Printf("Raw: X=%d Y=%d",iX[iSamplesCount],iY[iSamplesCount]));
463 // Put the hardware back into pen-detect mode
465 // TO DO: (mandatory)
466 // Write to the appropriate hardware register(s) to allow the hardware
467 // to detect when the digitizer panel is touched
470 // count samples collected - if it's less than minimum,
471 // schedule the reading of another sample
472 if (++iSamplesCount < iCfg.iNumXYSamples) // iX[] and iY[] are 4 levels deep in xyin.h...
474 if(KInterSampleTime > 0) // need to check this config param as it might be zero!
475 iTimer.OneShot(KInterSampleTime); // haven't got a complete group yet, so queue timer to sample again
477 iTakeReadingDfc.Enque();
481 // Have a complete group of samples so pass up to processing layer (PIL)
483 // Need to lock the kernel to simulate ISR context and thus defer preemption,
484 // since RawSampleValid() expects an ISR context and calls TDfc::Add().
486 RawSampleValid(); // adds DFC
491 Request for an interrupt to be generated when the pen is next down
492 Called by PIL at startup or when pen leaves digitiser after pen-up event issued
494 void DTemplateDigitiser::WaitForPenDown()
496 // Called at startup or when pen leaves digitiser after pen-up event issued
497 __KTRACE_OPT(KHARDWARE,Kern::Printf("WD: PowerDownMask %x",iPoweringDown));
502 // TO DO: (mandatory)
503 // Write to the appropriate hardware register(s) to allow the hardware
504 // to detect when the digitizer panel is touched and wakes up the system if in standby
510 // Relinquish request on power resources
511 // This will place the peripheral hardware in a low power "Sleep" mode which is Interrupt detection capable
514 TemplateResourceManager* aManager = TTemplatePowerController::ResourceManager();
515 aManager -> ModifyToLevel(TemplateResourceManager::AsynchMlResourceUsedByXOnly, 50 /* a percentage */);
516 aManager -> SharedBResource1() -> Release();
518 iPoweringDown = EFalse;
524 // TO DO: (mandatory)
525 // Write to the appropriate hardware register to clear the digitiser interrupt
528 // TO DO: (mandatory)
529 // Write to the appropriate hardware register(s) to allow the hardware
530 // to detect when the digitizer panel is touched
533 if ((iTimer.iState == NTimer::EIdle) && (iTimerInt.iState == NTimer::EIdle))
534 Interrupt::Enable(KIntIdDigitiser); // enable pen-down interrupt
539 Called by PIL after it has processed a group of raw samples while pen is down.
540 Used to indicate that the iX, iY buffers may be re-used
542 void DTemplateDigitiser::WaitForPenUp()
544 __KTRACE_OPT(KHARDWARE,Kern::Printf("WU"));
545 iState = E_HW_CollectSample;
546 iSamplesCount = 0; // reset sample buffer
547 if(KInterGroupTime > 0) // need to check this config param as it might be zero!
548 iTimer.OneShot(KInterGroupTime);
550 iTakeReadingDfc.Enque();
554 Called by PIL if the group of samples collected is not good enough
555 Used to indicate that the iX, iY buffers may be re-used
557 void DTemplateDigitiser::WaitForPenUpDebounce()
559 __KTRACE_OPT(KHARDWARE,Kern::Printf("WUDB"));
560 iState = E_HW_CollectSample;
561 iSamplesCount = 0; // reset sample buffer
562 if(KInterGroupTime > 0) // need to check this config param as it might be zero!
563 iTimer.OneShot(KInterGroupTime);
565 iTakeReadingDfc.Enque();
569 Pen up/down interrupt service routine (ISR)
571 void DTemplateDigitiser::PenInterrupt()
573 __KTRACE_OPT(KHARDWARE,Kern::Printf("I"));
576 Interrupt::Clear(KIntIdDigitiser); // should already have been cleared
578 // TO DO: (mandatory)
579 // Read from appropriate hardware register to determine whether digitiser panel is being touched
580 // Set penDown to ETrue if touched or EFalse if not touched.
581 // This is only example code... you need to modify it for your hardware
582 TBool penDown = EFalse;
584 // coverity[dead_error_condition]
585 if(!penDown) // pen up
588 // TO DO: (mandatory)
589 // Write to the appropriate hardware register to clear the digitiser interrupt
592 // TO DO: (mandatory)
593 // Write to the appropriate hardware register(s) to allow the hardware
594 // to detect when the digitizer panel is touched
597 return; // ... and exit!
600 Interrupt::Disable(KIntIdDigitiser); // do NOT disable the capability to generate interrupts at the source
602 if (KPenDownDelayTime>0) // need to check this config param as it might be zero!
603 iTimerInt.OneShot(KPenDownDelayTime); // start a debounce timer which will queue a DFC to process the interrupt
607 // TO DO: (mandatory)
608 // Write to the appropriate hardware register to clear the digitiser interrupt
609 // This will re-trigger the interrupt mechanism to catch the next interrupt...
612 iTakeReadingDfc.Add();
617 DPowerHandler pure virtual
619 void DTemplateDigitiser::PowerUp()
621 iPowerUpDfc.Enque(); // queue a DFC in this driver's context
625 Called by power up DFC
627 void DTemplateDigitiser::PowerUpDfc()
629 __KTRACE_OPT(KPOWER, Kern::Printf("DTemplateDigitiser::PowerUpDfc()"));
631 PowerUpDone(); // must be called from a different thread than PowerUp()
635 Turn the digitiser on
636 May be called as a result of a power transition or from the HAL
637 If called from HAL, then the digitiser may be already be on (iPointerOn == ETrue)
639 void DTemplateDigitiser::DigitiserOn()
641 __KTRACE_OPT(KPOWER,Kern::Printf("DTemplateDigitiser::DigitiserOn() iPointerOn=%d", iPointerOn));
643 if (!iPointerOn) // may have been powered up already
648 Power-up the digitiser. Assumes digitiser is off.
650 void DTemplateDigitiser::DigitiserPowerUp()
652 __KTRACE_OPT(KPOWER, Kern::Printf("DigitiserPowerUp"));
653 iPointerOn = ETrue; // now turned on
655 // TO DO: (mandatory)
656 // Write to the appropriate hardware register to clear the digitiser interrupt
662 // Reassert request on power resources
663 // This will move the peripheral hardware out of low power "Sleep" mode back to fully operational
666 TemplateResourceManager* aManager = TTemplatePowerController::ResourceManager();
667 aManager -> ModifyToLevel(TemplateResourceManager::AsynchMlResourceUsedByXOnly, 100 /* a percentage */);
668 aManager -> SharedBResource1() -> Use();
670 // TO DO: (mandatory)
671 // Write to the appropriate hardware register(s) to allow the hardware
672 // to detect when the digitizer panel is touched
675 iState = E_HW_PowerUp; // so we wait for pen up if necessary
676 iTakeReadingDfc.Enque();
680 DPowerHandler pure virtual
682 @param aPowerState the current power state
684 void DTemplateDigitiser::PowerDown(TPowerState /*aPowerState*/)
686 iPoweringDown = ETrue;
687 iPowerDownDfc.Enque(); // queue a DFC in this driver's context
691 Turn the digitiser off
692 May be called as a result of a power transition or from the HAL
693 If called from Power Manager, then the digitiser may be already be off (iPointerOn == EFalse)
694 if the platform is in silent running mode
696 void DTemplateDigitiser::DigitiserOff()
698 __KTRACE_OPT(KPOWER,Kern::Printf("DTemplateDigitiser::DigitiserOff() iPointerOn=%d", iPointerOn));
699 if (iPointerOn) // can have been powered down from HAL
702 Interrupt::Disable(KIntIdDigitiser);
704 // TO DO: (mandatory)
705 // Write to the appropriate hardware register to disable the digitiser interrupt
710 iTakeReadingDfc.Cancel();
711 if (iState != E_HW_CollectSample)
713 // Need to lock the kernel to simulate ISR context and thus defer preemption,
714 // since PenUp() expects an ISR context and calls TDfc::Add().
716 PenUp(); // adds DFC (will call WaitForPenDown)
722 // TO DO: (mandatory)
723 // Write to the appropriate hardware register(s) to allow the hardware
724 // to detect when the digitizer panel is touched and wakes up the system if in standby
730 // Relinquish request on power resources as we are being powered down
731 // This will place the peripheral hardware in a low power "Sleep" mode which is Interrupt detection capable
734 TemplateResourceManager* aManager = TTemplatePowerController::ResourceManager();
735 aManager -> ModifyToLevel(TemplateResourceManager::AsynchMlResourceUsedByXOnly, 0 /* a percentage */);
736 aManager -> SharedBResource1() -> Release();
738 if (iPoweringDown) // came here through PowerDown
740 iPoweringDown = EFalse;
745 else // already powered down (by HAL)
747 if (iPoweringDown) // came here through PowerDown
749 iPoweringDown = EFalse;
759 Convert digitiser coordinates to screen coordinates
761 @param aDigitiserPoint the digitiser coordinates
762 @param aScreenPoint A TPoint supplied by the caller.
763 On return, set to the converted screen coordinates in pixels.
765 @return KErrNone if successful
767 TInt DTemplateDigitiser::DigitiserToScreen(const TPoint& aDigitiserPoint, TPoint& aScreenPoint)
770 TInt R11 = iMachineConfig.iCalibration.iR11;
771 TInt R12 = iMachineConfig.iCalibration.iR12;
772 TInt R21 = iMachineConfig.iCalibration.iR21;
773 TInt R22 = iMachineConfig.iCalibration.iR22;
774 TInt TX = iMachineConfig.iCalibration.iTx;
775 TInt TY = iMachineConfig.iCalibration.iTy;
776 NKern::UnlockSystem();
777 TInt X = aDigitiserPoint.iX;
778 TInt Y = aDigitiserPoint.iY;
780 aScreenPoint.iX = (X*R11 + Y*R21 + TX) >> 16;
781 aScreenPoint.iY = (X*R12 + Y*R22 + TY) >> 16;
783 __KTRACE_OPT(KHARDWARE,Kern::Printf("DtS: Dp.x %d, Dp.y %d, Sp.x %d, Sp.y %d", X,Y,aScreenPoint.iX,aScreenPoint.iY));
789 Convert screen coordinates back into digitiser coordinates
790 using the current constants from the superpage
792 @param aX The screen X coordinate in pixels; On return, set to the digitiser X coordinate.
793 @param aY The screen Y coordinate in pixels; On return, set to the digitiser Y coordinate.
795 void DTemplateDigitiser::ScreenToDigitiser(TInt& aX, TInt& aY)
798 Int64 R11 = iMachineConfig.iCalibration.iR11;
799 Int64 R12 = iMachineConfig.iCalibration.iR12;
800 Int64 R21 = iMachineConfig.iCalibration.iR21;
801 Int64 R22 = iMachineConfig.iCalibration.iR22;
802 Int64 TX = iMachineConfig.iCalibration.iTx;
803 Int64 TY = iMachineConfig.iCalibration.iTy;
804 NKern::UnlockSystem();
808 // Xd=(Xs<<16)*R22-(Ys<<16)*R21-(TX*R22)+(TY*R21)
809 // -------------------------------------------
810 // (R22*R11)-(R21*R12)
813 // Yd=(Xs<<16)*R12-(Ys<<16)*R11-(TX*R12)+(TY*R11)
814 // -------------------------------------------
815 // (R21*R12)-(R22*R11)
817 // where Xd and Yd are digitiser coordinates
818 // Xs and Ys are supplied screen coordinates
823 Int64 d=Int64(R21)*Int64(R12)-Int64(R22)*Int64(R11);
825 Int64 r=(X*R12)-(Y*R11)-(TX*R12)+(TY*R11);
831 r=(X*R22)-(Y*R21)-(TX*R22)+(TY*R21);
839 Calculate values for R11, R12, R21, R22, TX and TY
841 @param aCalibration the screen coordinates of points touched
842 @return KErrNone if successful
844 TInt DTemplateDigitiser::SetXYInputCalibration(const TDigitizerCalibration& aCalibration)
846 TInt R11,R12,R21,R22,TX,TY;
848 // Get coords of expected points
850 TDigitizerCalibration cal;
851 TInt ret=CalibrationPoints(cal);
862 // Get coords of points touched in screen coordinates
864 TInt X1=aCalibration.iTl.iX;
865 TInt Y1=aCalibration.iTl.iY;
866 TInt X2=aCalibration.iBl.iX;
867 TInt Y2=aCalibration.iBl.iY;
868 TInt X3=aCalibration.iBr.iX;
869 TInt Y3=aCalibration.iBr.iY;
871 // Convert back to raw digitiser coordinates
873 ScreenToDigitiser(X1,Y1);
874 ScreenToDigitiser(X2,Y2);
875 ScreenToDigitiser(X3,Y3);
877 // (Y1-Y2)(Xp1-Xp3) - (Y1-Y3)(Xp1-Xp2)
878 // ----------------------------------- = R11
879 // (Y1-Y2)(X1-X3) - (Y1-Y3)(X1-X2)
881 Int64 r=((Int64(Y1-Y2)*Int64(Xp1-Xp3))-(Int64(Y1-Y3)*Int64(Xp1-Xp2)));
883 r/=(Int64(Y1-Y2)*Int64(X1-X3)-Int64(Y1-Y3)*Int64(X1-X2));
886 // (Y1-Y2)(Yp1-Yp3) - (Y1-Y3)(Yp1-Yp2)
887 // ----------------------------------- = R12
888 // (Y1-Y2)(X1-X3) - (Y1-Y3)(X1-X2)
890 r=((Int64(Y1-Y2)*Int64(Yp1-Yp3))-(Int64(Y1-Y3)*Int64(Yp1-Yp2)));
892 r/=(Int64(Y1-Y2)*Int64(X1-X3)-Int64(Y1-Y3)*Int64(X1-X2));
895 // (X1-X3)(Xp2-Xp3) - (X2-X3)(Xp1-Xp3)
896 // ----------------------------------- = R21
897 // (Y2-Y3)(X1-X3) - (Y1-Y3)(X2-X3)
899 r=(((X1-X3)*(Xp2-Xp3))-((X2-X3)*(Xp1-Xp3)));
901 r/=(Int64(Y2-Y3)*Int64(X1-X3)-Int64(Y1-Y3)*Int64(X2-X3));
904 // (X1-X3)(Yp2-Yp3) - (X2-X3)(Yp1-Yp3)
905 // ----------------------------------- = R22
906 // (Y2-Y3)(X1-X3) - (Y1-Y3)(X2-X3)
908 r=((Int64(X1-X3)*Int64(Yp2-Yp3))-(Int64(X2-X3)*Int64(Yp1-Yp3)));
910 r/=(Int64(Y2-Y3)*Int64(X1-X3)-Int64(Y1-Y3)*Int64(X2-X3));
913 // TX = Xp1 - X1*R11 - Y1*R21
915 TX=(Xp1<<16)-(X1*R11)-(Y1*R21);
917 // TY = Yp1 - X1*R12 - Y1*R22
919 TY=(Yp1<<16)-(X1*R12)-(Y1*R22);
922 // Write new values into the superpage
925 iMachineConfig.iCalibration.iR11 = R11;
926 iMachineConfig.iCalibration.iR12 = R12;
927 iMachineConfig.iCalibration.iR21 = R21;
928 iMachineConfig.iCalibration.iR22 = R22;
929 iMachineConfig.iCalibration.iTx = TX;
930 iMachineConfig.iCalibration.iTy = TY;
931 NKern::UnlockSystem();
937 Informs the user-side calibration application where to draw
938 the cross-hairs on the screen
940 @param aCalibration On return contains the for points on the screen (in screen coordinates)
941 where the cross-hairs should be drawn
942 @return KErrNone if succcessful
944 TInt DTemplateDigitiser::CalibrationPoints(TDigitizerCalibration& aCalibration)
946 TVideoInfoV01Buf buf;
947 TVideoInfoV01& vidinfo=buf();
948 TInt r = Kern::HalFunction(EHalGroupDisplay, EDisplayHalCurrentModeInfo, (TAny*)&buf, NULL);
951 iScreenSize=vidinfo.iSizeInPixels;
953 aCalibration.iBl.iX = aCalibration.iTl.iX = iScreenSize.iWidth/10;
954 aCalibration.iTr.iY = aCalibration.iTl.iY = iScreenSize.iHeight/10;
955 aCalibration.iBr.iY = aCalibration.iBl.iY = iScreenSize.iHeight-iScreenSize.iHeight/10;
956 aCalibration.iTr.iX = aCalibration.iBr.iX = iScreenSize.iWidth-iScreenSize.iWidth/10;
960 Saves the digitiser calibration to the persistent machine configuration area
961 so that it can be restored after a power-down/up
963 @return KErrNone if succcessful
965 TInt DTemplateDigitiser::SaveXYInputCalibration()
968 iMachineConfig.iCalibrationSaved = iMachineConfig.iCalibration;
969 NKern::UnlockSystem();
974 Restores the digitiser calibration from the persistent machine configuration area
977 @param aType indicates whether to restore factory or saved settings
978 @return KErrNone if succcessful
980 TInt DTemplateDigitiser::RestoreXYInputCalibration(TDigitizerCalibrationType aType)
987 iMachineConfig.iCalibration=iMachineConfig.iCalibrationFactory;
990 iMachineConfig.iCalibration=iMachineConfig.iCalibrationSaved;
996 NKern::UnlockSystem();
1001 Gets the digitiser configuration information
1003 @param aInfo On return, contains information about the digitiser's dimensions etc.
1005 void DTemplateDigitiser::DigitiserInfo(TDigitiserInfoV01& aInfo)
1007 __KTRACE_OPT(KEXTENSION,Kern::Printf("DTemplateDigitiser::DigitiserInfo"));
1008 aInfo.iDigitiserSize.iWidth=KConfigXyWidth;
1009 aInfo.iDigitiserSize.iHeight=KConfigXyHeight;
1010 aInfo.iOffsetToDisplay.iX=KConfigXyOffsetX;
1011 aInfo.iOffsetToDisplay.iY=KConfigXyOffsetY;
1015 Issues a pen move event if the distance from the last point is greater than the threshold
1017 @param aPoint the pen position in screen coordinates
1019 void DTemplateDigitiser::FilterPenMove(const TPoint& aPoint)
1021 TPoint offset=aPoint;
1022 offset.iX-=iLastPos.iX;
1023 offset.iY-=iLastPos.iY;
1024 if (Abs(offset.iX)>=iCfg.iAccThresholdX || Abs(offset.iY)>=iCfg.iAccThresholdY)
1027 IssuePenMoveEvent(aPoint);
1032 Reset the pen move filter
1034 void DTemplateDigitiser::ResetPenMoveFilter()