Main Site Documentation

Glide touch problem with Cobra III and NHVN T43


#1

Hi everyone, yes this is the 1000th topic about this problem, but I’ve read almost all the other topics, tried all the suggestions contained into them, but still not working…
So I’m here to ask for any other idea…
This is the scenario: COBRA III with NHVN touch display T43 connected to the board using the Display NHVN adapter via the 40 pins connector (see attached pictures). I’m trying to use Glide.
The display is working, infact I see the button on the screen. As far as I understand, Glide should handle touch out of the box, but no feedback when the button is tapped…
I don’t know what else to try…
I’m using this piece of code, which I found in a similar topic on the forum:

public class Program
{
    static private GHI.Glide.UI.Button btn;
    static private GHI.Glide.Display.Window MyWindows;

    public static void Main()
    {
        StartTest();
        Thread.Sleep(Timeout.Infinite);
    }

    static void StartTest()
    {
        MyWindows = GlideLoader.LoadWindow(Resources.GetString(Resources.StringResources.TestWindow));
        GlideTouch.Initialize();
        btn = (GHI.Glide.UI.Button)MyWindows.GetChildByName("btn");
        btn.TapEvent += btn_TapEvent;
        Glide.MainWindow = MyWindows;
    }

    static void btn_TapEvent(Object sender)
    {
        Debug.Print("Button tapped.");
    }
}

The “Button tapped” message on the debug screen does not appear when i tap the button on screen

I also tried to use the CalibrationWindow: when I start the app the Calibration window appears with the message “Touch the screen to start”, but even if I try to touch the screen, I get no response…

I desperately need help !
Thanks, Matteo.


#2

It looks like you are using a Capacitive Touch version of the Newhaven Display. Glide or NetMF do not have native methods for handling touch from a Capacitive display. Therefore, you will have to use a driver to handle touch and feed the touch events to Glide.

Look on the old forum in codeshare and you will find many examples on how to do this.


#3

Thank you very much!
Ok, yes, I’m using a capacitive touch screen.
Could you be so kind to post me a link to start ? I’m a bit newbie, I tried a lot of pieces of code from codeshare following the links found on the old forum, but no one of them worked for me…
Thanks again!
Matteo

UPDATE:

I’ve found this promising class:

    #region Event Delegates

public delegate void OnTouchDown(object sender, int x, int y, int finger, int touchId);
public delegate void OnTouchUp(object sender, int x, int y, int finger, int touchId);
public delegate void OnTouchMove(object sender, int x, int y, int finger, int touchId);

#endregion

public class NewHavenCapTouch
{

    #region Enumerations

    public enum DeviceModes
    {
        Normal = 0,
        SystemInfo = 1,
        TestMode = 4,
    }

    public enum GestureId
    {
        ZoomIn = 0x48,
        ZoomOut = 0x49,
        None = 0x00
    }

    #endregion

    #region Variables

    private InterruptPort _touchInterrupt;
    private I2CDevice _i2cBus;
    private I2CDevice.I2CTransaction[] _transactions;
    private byte[] _addressBuffer, _resultBuffer;
    private bool[] _touching;
    private int[] _x, _y;
    private bool _singleTouch;

    #endregion

    #region Constructor

    public NewHavenCapTouch(Cpu.Pin interruptPin)
    {
        _addressBuffer = new byte[1];
        _resultBuffer = new byte[1];
        _transactions = new I2CDevice.I2CTransaction[2];
        _touching = new bool[5];
        _x = new int[5];
        _y = new int[5];

        _i2cBus = new I2CDevice(new I2CDevice.Configuration(0x38, 400));
        _touchInterrupt = new InterruptPort(interruptPin, false, Port.ResistorMode.Disabled, Port.InterruptMode.InterruptEdgeBoth);
        _touchInterrupt.OnInterrupt += (a, b, c) => touchEvent();
    }

    #endregion

    #region Properties

    public DeviceModes DeviceMode
    {
        get
        {
            // Bits 6 & 5
            return (DeviceModes)ReadRegister(0x00);
        }
    }

    public GestureId GestureID
    {
        get
        {
            return (GestureId)ReadRegister(0x01);
        }
    }

    public bool SingleTouchMode
    {
        get { return _singleTouch; }
        set { _singleTouch = value; }
    }

    public int TouchDownCount
    {
        get
        {
            // Bits 3 - 0
            return (int)ReadRegister(0x02);
        }
    }

    public int VendorId
    {
        get { return (int)ReadRegister(0xA3); }
    }

    public Version Version
    {
        get
        {
            return new Version(ReadRegister(0xA1), ReadRegister(0xA2));
        }
    }

    #endregion

    #region Events

    public event OnTouchDown TouchDown;
    protected virtual void OnTouchDown(object sender, int x, int y, int finger, int touchId)
    {
        if (TouchDown != null)
            TouchDown(sender, x, y, finger, touchId);
    }

    public event OnTouchUp TouchUp;
    protected virtual void OnTouchUp(object sender, int x, int y, int finger, int touchId)
    {
        if (TouchUp != null)
            TouchUp(sender, x, y, finger, touchId);
    }

    public event OnTouchMove TouchMove;
    protected virtual void OnTouchMove(object sender, int x, int y, int finger, int touchId)
    {
        if (TouchMove != null)
            TouchMove(sender, x, y, finger, touchId);
    }

    #endregion

    #region Private Methods

    private byte ReadRegister(byte address)
    {
        _addressBuffer[0] = address;

        _transactions[0] = I2CDevice.CreateWriteTransaction(_addressBuffer);
        _transactions[1] = I2CDevice.CreateReadTransaction(_resultBuffer);

        _i2cBus.Execute(this._transactions, 1000);

        return _resultBuffer[0];
    }

    private void touchEvent()
    {
        byte reg = 0x03;
        byte val;
        int x, y;
        int status;
        int touchId;
        int tc = 5;

        if (_singleTouch)
            tc = 1;

        // New Haven allows for up to 5 touches
        for (int i = 0; i < tc; i++)
        {
            val = ReadRegister(reg++);
            status = val >> 6; // 0 = Down, 1 = Up, 2 = Contact, 3 = Reserved
            x = ((val & 0x0F) << 8) + ReadRegister(reg++);

            val = ReadRegister(reg++);
            touchId = val >> 4;
            y = ((val & 0x0F) << 8) + ReadRegister(reg++);

            switch (status)
            {
                case 0:		//Down
                    _touching[i] = true;
                    OnTouchDown(this, x, y, i, touchId);
                    break;
                case 1:		// Up
                case 3:		// Reserved
                    _touching[i] = false;
                    OnTouchUp(this, x, y, i, touchId);
                    break;
                case 2:		// Contact
                    // Make sure not to keep raising move
                    // unless we've actually moved
                    if (_x[i] != x || _y[i] != y)
                    {
                        OnTouchMove(this, x, y, i, touchId);
                    }
                    break;
            }

            _x[i] = x;
            _y[i] = y;

            reg += 2;
        }
    }

    #endregion

}

but i don’t know which is the interrupt pin to be passed to the constructor in my configuration…

the example says:

            touch = new NewHavenCapTouch((Cpu.Pin)43);

but in my case i get a unhandled exception…

Thanks again !
Matteo


#4

You need to check the schematics for the mainboard that you are using to map Pin 36 on the Newhaven Module to pin 36 on the mainboard LCD header.


#5

THanks, i will try


#6

Note that you need to install the 2.2k pullup-resistors for the i2c-lines.


#7

mmm, resistors ?
Is there a discussion anywhere in the forum explaining what to do ?
Thasnks,


#8

Just take two 2.2k resistors to pull the SDA- and SCL-lines to 3.3V.
But I just noticed that the Cobra III already has them installed.


#9

Infact It seeem that there are already installed…

Now tried to modify the initialization code like this:

touch = new NewHavenCapTouch(GHI.Pins.G120.P0_6);

this is the behaviour:

If i don’t touch the screen nothing happens.
As soon as i touch the screen i receive tons of move events even if i don’t move the finger.
As soon as i release the touch i receive tons of neverending touchup events…
No touchDown event is fired…


#10

This should just work. I’ve never used that driver myself though. In the old Codeshare there is this one from Skewworks.

http://old.ghielectronics.com/community/codeshare/entry/1078

and this one form Simon and this is the one I use with modifications for my own touch panels. It is plain NETMF

http://old.ghielectronics.com/community/codeshare/entry/794


#11

Thanks, everyone for your help, I will try the driver suggested by Dave.
Matteo.

EDIT:

the first class is exactly the one I’m using…
I will try the second one from Simon

Thanks


#12

Hi Dave,
thanks for your suggestions!
The example class from Simon works prefectly…

Now I have another perhaps stupid question:

As “scardinale” says: “you will have to use a driver to handle touch and feed the touch events to Glide.”, I would like to use Glide, but how can i “Feed” the events to glide, so that when i tap a button the tap_down event over the button is fired ?

Thanks!
Matteo.

EDIT:

Perhaps something like this:

GlideTouch.RaiseTouchDownEvent(sender, new GHI.Glide.TouchEventArgs(new GHI.Glide.Geom.Point(e.X, e.Y)));

#13

I created a new class for the driver. Here is the code I used. This include the backlight control where it switches the backlight off after a certain time and then detects the touch to put it back on without passing the touch through to the GUI.

using System;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Presentation.Media;
using System.IO.Ports;
using Microsoft.SPOT.Hardware;
using Microsoft.SPOT.Touch;
using Microsoft.SPOT.Net;
using System.IO;
using GHI.Glide;
using GHI.Glide.Display;
using GHI.Glide.UI;
using GHI.IO;
using GHI.Processor;
using GHI.Networking;
using GHI.IO.Storage;
using Microsoft.SPOT.IO;
using Microsoft.SPOT.Net.NetworkInformation;
using System.Net;
using System.Text;

using GlideButton = GHI.Glide.UI.Button;
using GlideColors = GHI.Glide.Colors;
using System.Collections;

namespace AX9100
{
class CapTouchDriver
{
static public DisplayNhd5 display;
static InterruptPort touchPin;
static Microsoft.SPOT.Touch.TouchInput[] touches;
//
// LCD backlight
//
static OutputPort LCDbacklight;
static long msBacklightTime; // Time in ms for backlight to go off
static long msDisplayTimeout; // Next backlight time to go off
static bool BacklightOff = false;
static bool LCDTurnedOn = false;

    public CapTouchDriver(I2CDevice sharedBus)
    {
        display = new DisplayNhd5(sharedBus);
        LCDbacklight = new OutputPort(GHI.Pins.G120.P1_19, true);
        LCDbacklight.Write(true);
        msBacklightTime = 0;            // Default is off
        msDisplayTimeout = 0;
        display.TouchUp += display_TouchUp;
        display.TouchDown += display_TouchDown;
        display.ZoomIn += display_ZoomIn;
        display.ZoomOut += display_ZoomOut;
        touches = new Microsoft.SPOT.Touch.TouchInput[1];
        touches[0] = new TouchInput();
        //
        // Using interrupt (for G120)
        //
        touchPin = new InterruptPort(GHI.Pins.G120.P0_25, false, Port.ResistorMode.PullUp, Port.InterruptMode.InterruptEdgeLow);
        touchPin.OnInterrupt += touchPin_OnInterrupt;
        //
        // Create thread the handle the backlight timeout
        //
        Thread threadBacklight = new Thread(backlightHandler);
        threadBacklight.Start();
    }
    void backlightHandler()
    {
        while (true)
        {
            if (msBacklightTime > 0 && BacklightOff == false)
            {
                if (UtilsClass.msTime() > msDisplayTimeout)
                {
                    BacklightOff = true;
                    LCDbacklight.Write(false);  // Switch it off
                }
            }
            Thread.Sleep(1000);
        }
    }
    void display_ZoomOut(DisplayNhd5 sender, EventArgs e)
    {
        Debug.Print("Zoom out");
    }
    void display_ZoomIn(DisplayNhd5 sender, EventArgs e)
    {
        Debug.Print("Zoom in");
    }
    static void display_TouchDown(DisplayNhd5 sender, TouchEventArgs e)
    {

// Debug.Print(“Finger " + e.FingerNumber + " down!”);
// Debug.Print("Where " + e.X + “,” + e.Y);
//
// Check if backlight is off and if so, we will switch it back
// on and consume the touch
//
if (BacklightOff)
{
BacklightOff = false;
LCDbacklight.Write(true);

            ResetBacklightInternal();   // Reset the timer
            LCDTurnedOn = true;         // We should ignore the touch up
            return;
        }
        else
        {
            ResetBacklightInternal();   // Each touch will reset the timer
        }
        touches[0].X = e.X;
        touches[0].Y = e.Y;
        GlideTouch.RaiseTouchDownEvent(null, new GHI.Glide.TouchEventArgs(touches));
    }
    static void display_TouchUp(DisplayNhd5 sender, TouchEventArgs e)
    {

// Debug.Print(“Finger " + e.FingerNumber + " up!”);
if (LCDTurnedOn)
{
LCDTurnedOn = false;
return;
}
touches[0].X = e.X;
touches[0].Y = e.Y;
GlideTouch.RaiseTouchUpEvent(null, new GHI.Glide.TouchEventArgs(touches));
}

    static void touchPin_OnInterrupt(uint data1, uint data2, DateTime time)
    {
        display.ReadAndProcessTouchData();
    }
    public void Calibrate()
    {
        touchPin.OnInterrupt -= touchPin_OnInterrupt;   // Remove the IRQ until we calibrate it
        display.ReadInformation();
        display.Calibrtate();
        touchPin.OnInterrupt += touchPin_OnInterrupt;
    }
    static void ResetBacklightInternal()
    {
        msDisplayTimeout = UtilsClass.msTime() + msBacklightTime;
    }
    public void ResetBacklight()
    {
        msDisplayTimeout = UtilsClass.msTime() + msBacklightTime;
    }
    public void SetBacklightTime(long msTime)
    {
        msBacklightTime = msTime;
    }
    public void SwitchBacklightOff()
    {
        //
        // This will cause the backlight to go off
        //
        msBacklightTime = UtilsClass.msTime();
    }
    public void SwithcBacklightOn()
    {
        //
        // Override the timer and bring it on. 
        //
        BacklightOff = false;
        LCDbacklight.Write(true);
        ResetBacklightInternal();   // Reset the timer
    }
}

}


#14

Wow, thanks!
I try it immediately

And what about if I need move events also?

Thanks again,
Matteo.


#15

Write your own code. :slight_smile:


#16

Ok, I did not explain me enough… sorry… I don’t pretend to have a ready to use code… l’m only asking if anyone could tell me which register to use, or how to intercept move events… The class from Skewworks has the code for move events, but due to my inexperience I don’t understand how to integrate it in the class from Simon or in the one already shared by Dave.
Or, alternatively, do you think it is better to handle move events via code only? Saving a flag when the finger is down and releasing the flag when it is up? And send move events if the flag is true?

Thanks!


#17

The datasheet for the FT touch IC gives you the registers you need to work with.


#18

Ok, thanks.