Customize window size of the touch calibration

Hello,

We need to customize the size of the calibration touch application because the solution that we are working doesn´t have buttons to pressing esc in case of cancelling

thanks

Dear @Eliezer

The calibration window cannot be easily adjusted. You might also run into a general issue: How would you press an “abort” button, if the touch screen calibration is completely off. So you might want to implement a timeout.

The solution for you would be to implement your own calibration application. The required functions are documented at Microsoft:

The calibration result is finally stored in the registry at [HKLM\HARDWARE\DEVICEMAP\TOUCH] CalibrationData.

I looked through the source code of the current calibration routine, the basic function calls seem to be:

  1. TouchPanelGetDeviceCaps() to read the number of required calibration points (usually 5)

  2. For each calibration point:

  3. TouchPanelGetDeviceCaps() to read the screen coordinates of the calibration point

  4. Draw an orientation point / cross onto the screen

  5. TouchPanelReadCalibrationPoint() to read the raw touch coordinates

  6. TouchPanelSetCalibration() to inform the driver about the new calibration data

  7. ( TouchPanelReadCalibrationAbort() if you don’t finish the calibration process for any reason)

Regards
Andy

It generates the following exception :
System.MissingMethodException: Can’t find an Entry Point ‘TouchPanelGetDeviceCaps’ in a PInvoke DLL ‘coredll’.

The code that I´ve made is this:

  [DllImport("coredll")]
        private static extern bool KernelIoControl(Int32 IoControlCode, IntPtr InputBuffer, Int32 InputBufferSize,
            byte[] OutputBuffer, Int32 OutputBufferSize, ref Int32 BytesReturned);

        [DllImport("coredll")]
        private static extern bool TouchPanelGetDeviceCaps(Int32 iIndex, out LPVOID lpOutput);

        [DllImport("coredll")]
        private static extern bool TouchPanelReadCalibrationPoint(Int32 pRawX, Int32 pRawY);

        [DllImport("coredll")]
        private static extern bool TouchPanelSetCalibration(Int32 TouchPanelSetCalibration, out Int32[] pScreenXBuffer,
            out Int32[] pScreenYBuffer, out Int32[] pUncalXBuffer, out Int32[] pUncalYBuffer);

        [DllImport("coredll")]
        private static extern bool TouchPanelReadCalibrationAbort();

If you could help me, I´m still needing this solution

Thanks

Dear @Eliezer

Please look at the documentation of TouchPanelGetDeviceCaps() which I refered to in my first answer. This function is not part of the coredll.dll.

Regards, Andy

Hello, but when I use tchproxy generates the another exception: System.MissingMethodException: Can’t find PInvoke DLL ‘tchproxy’.

Dear @Eliezer

I checked our BSP. TouchPanelGetDeviceCaps() and the other required touch functions are located in our dll colibri_touch.dll.

Regards
Andy

When I use colibri_touch generates same exception. Where do I get that DLL?

Dear @Eliezer
The problem seems to be a bit more complex than I thought, but I believe I found a solution:

The touch driver inside the image is flagged to be a Kernel mode driver. This prevents your application to access the driver in user mode. To overcome this limitation you need to load the same driver from the flash file system:

  1. Download the iMX6 BSP
  2. Unzip it and take the touch driver colibri_touch.dll.
    This is the only file you need from the BSP package.
  3. Rename colibri_touch.dll, for example to imx6tch2013.dll.
  4. Store the file on your target device, in the folder _\Flashdisk\System\ _
  5. Edit the target device’s registry to use the driver on the Flashdisk:
[HKLM\HARDWARE\DEVICEMAP\TOUCH]  
Dll="imx6tch2013.dll"
[HKLM\Drivers\Builtin]
Dll="busenum.dll"

The second entry is required to control the boot timing. Without it, the system would try to load the touch driver from the Flashdisk, before the Flashdisk driver is ready.

  1. Save the registry.
  2. Reboot.
    The standard calibration feature should still work, and your application should be able to access the touch driver functions.

Regards,
Andy

Hello again, It was posible to execute to calibration, but the system becomes very slow after changing the DLL, and the calibration registry doesn´t changes, so it doesnt calibrate. I´m using the RegFlushKey command, and it doesn´t seem to work.

Dear @Eliezer

Can you please define what exactly became slow. The boot time will be longer, because we avoid parallel driver loading. Beside this, there should be no difference in performance.

Are you sure the calibration process was successfully finished? You should get a message confirming the success. If the calibration cannot be done successfully (e.g. because there was too much jitter in the signal), the calibration will be repeated.
The new calibration values should be effective immediately. To keep them permanent over a reboot, you need to save the registry, as you did.

Regards, Andy

Hello,

Can you please define what exactly became slow.
When changing the regkey “HKLM\Drivers\Builtin\Dll”.

Are you sure the calibration process was successfully finished?
Yes, but doesn’t changing the regkey “HKLM\HARDWARE\DEVICEMAP\TOUCH\CalibrationData”

Dear @Eliezer,

Could you share .NET application code, it will help us to debug the problem with your application code.

Thank you.

Yes, the code:

private struct LPVOID
{            
	public TPDC_SAMPLE_RATE TPDC_SAMPLE_RATE_ID;
	public TPDC_CALIBRATION_POINT_COUNT TPDC_DEVICE_TYPE_ID;
	public TPDC_DEVICE_TYPE TPDC_CALIBRATION_POINT_COUNT_ID;
	public TPDC_CALIBRATION_POINT TPDC_CALIBRATION_POINT_ID;
}

private struct TPDC_SAMPLE_RATE
{
	public int SamplesPerSecondLow;
	public int SamplesPerSecondHigh;
	public int CurrentSampleRateSetting;
};

private struct TPDC_CALIBRATION_POINT_COUNT
{
	public UInt32 flags;
	public int cCalibrationPoints;
};

private struct TPDC_DEVICE_TYPE
{
	public TouchType touchType;
	public uint dwTouchInputMask;
};

private struct TPDC_CALIBRATION_POINT
{
	public int PointNumber;
	public int cDisplayWidth;
	public int cDisplayHeight;
	public int CalibrationX;
	public int CalibrationY;
};
 
[DllImport("imx6tch2013")]
private static extern bool TouchPanelGetDeviceCaps(Int32 iIndex, out LPVOID lpOutput);

[DllImport("imx6tch2013")]
private static extern bool TouchPanelReadCalibrationPoint(Int32 pRawX, Int32 pRawY);

[DllImport("imx6tch2013")]
private static extern bool TouchPanelSetCalibration(int TouchPanelSetCalibration, int[] pScreenXBuffer,
	int[] pScreenYBuffer, int[] pUncalXBuffer, int[] pUncalYBuffer);

[DllImport("imx6tch2013")]
private static extern bool TouchPanelReadCalibrationAbort();

[DllImport("coredll")]
private static extern uint RegFlushKey(IntPtr hKey);
    
public void CalibrateTouchScreen(IEnumerable<Point> screenPoints, IEnumerable<Point> selectedPoints)
{
	try
	{
		var points = (from pT in screenPoints.Select((o, i) => new { Position = o, Index = i })
						from pS in selectedPoints.Select((o, i) => new { Position = o, Index = i })
						where
							pT.Index == pS.Index
						select
							new
							{
								Index = pT.Index,
								ScreenPosition = tP.Position,
								SelectedPosition = sP.Position
							}).ToList();

		LPVOID lpOutput = new LPVOID();
		lpOutput.TPDC_CALIBRATION_POINT_COUNT_ID.touchType = TouchType.TOUCHTYPE_SINGLETOUCH;

		var numberPoints = points.Count();

		var pScreenXBuffer = new int[numberPoints];
		var pScreenYBuffer = new int[numberPoints];
		var pUncalXBuffer = new int[numberPoints];
		var pUncalYBuffer = new int[numberPoints];                

		foreach (var p in points)
		{
			pScreenXBuffer[p.Index] = p.ScreenPosition.X;
			pScreenYBuffer[p.Index] = p.ScreenPosition.Y;
			pUncalXBuffer[p.Index] = p.SelectedPosition.X;
			pUncalYBuffer[p.Index] = p.SelectedPosition.Y;
		}

		TouchPanelGetDeviceCaps(numberPoints, out lpOutput);

		if (!TouchPanelSetCalibration(numberPoints, pScreenXBuffer, pScreenYBuffer,
												pUncalXBuffer, pUncalYBuffer))
		{
			throw new Exception("Error on capture the points");
		}
		SaveRegister(HKEY_LOCAL_MACHINE);
	}
	catch 
	{
		TouchPanelReadCalibrationAbort();
		throw;
	}
}

private void SaveRegister(uint key)
{
	var handled = new IntPtr(unchecked((int)key));
	RegFlushKey(handled);
	GC.KeepAlive(handled);
}

Dear @Eliezer,

Still, I am looking into the details.

Did you test with the default control panel applet calibration application? Is that changing the registry?

Is TouchPanelSetCalibration returns TRUE?

If you are interested to look more details, there is a touch test application code available with WinCE installation::\WINCE700\private\test\BaseOS\Drivers\Touch\winmain.cpp. WinCE can be installed from here : https://docs.microsoft.com/en-us/previous-versions/windows/embedded/gg154201(v=winembedded.70)

Hello, yes, returned true but doesn’t changing registry.
Using calibration with the control panel and saving registries works.

Dear @Eliezer,

Thank you for your reply. If TouchPanelSetCalibration returns TRUE then calibration points are valid. I am not able to find it where the CalibrationData registry would be set by the OS. However, I would like to suggest manually update the registry method.

Please follow this post : http://www.toradex.com/community/comments/49633/view.html for calibration points information.

[HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\TOUCH]
“CalibrationData”=“x1,y1 x2,y2 x3,y3 x4,y4 x5,y5”

CalibrationData is a string registry.

Use Registry access APIs to update and save the registry. Find reference code here : https://developer.toradex.com/knowledge-base/registry-access-using-program

Let us know if you have any other questions. Still, if touch not working properly then you might need to Debug with DEBUG build for finding the issue and fix it. Share touch panel resolution and orientation aligned with display then we will share manually calculated calibration points with you.

So this method will only serve to verify that the points are correct and should I update the record manually?

And another situation, why did the OS get slow after using DLL?