Support for Python3

I think you should always be returning false from the xpt7603_read callback, and thus you should rename valid to something more accurate like pressed.

@Lazar_Demin Where do you call lv_task_handler periodically? Maybe it’s not called?

You can verify it if you display an animation and make sure if it keeps moving when you are on the infinite loop at the bottom of your script.

You can also try to call it explicitly on that loop

print('starting loop')
while True:

I’m using the linux framebuffer (with the existing modfb from lv_binding_micropython) for display and the touch input is I2C-based. So can’t be clashing.

lv_task_handler is being called by modfb using mp_sched_schedule. I confirmed that it’s running with a print statement in the C code.

Tried calling it explicitly, didn’t make a difference.

Great suggestion! The animation freezes while I’m touching the screen:

Any idea why this could be happening even though I’ve confirmed the lv_task_handler function is being run periodically?

Is there something that could be making the xpt7603_read callback blocking?
Should the xpt7603_read callback always return false, like @embeddedt suggested?

Yes it can be related to @embeddedt comment.
When read returns “true” it means that there is more data to be sent, false means no more data, so in general you almost always want to return false from read.

1 Like

I’m 99% sure you should always return false from that function. Otherwise, LittlevGL will freeze (as you can see from the first and last lines of this code snippet).

Happy new year everyone! I had some time to revisit this and changed the xpt7603_read callback to always return false

Good news: it resolved the blocking issue I was seeing before. I can touch the screen and animations will still do their thing:

Bad news: touch input still isn’t properly propagating to the rest of lvgl.
My test script has a button with a callback attached and the callback never gets called no matter what I do.

Appreciative of any ideas and pointers

If you uncomment this printf, what coordinates do you see?

Could you try reading coordinates from your script as well?
Something like:

p = lv.point_t()
lv.indev_get_point(lv.indev_get_act(), p)
print("x=%d, y=%d" % (p.x, p.y))

Note that, lv_indev_act() is valid only in events and signals when there are an active (being processed) indev. Instead, I suggest using lv_indev_next() to get the first indev:

p = lv.point_t()
lv.indev_get_point(lv.indev_next(null), p)
print("x=%d, y=%d" % (p.x, p.y))

Thanks for pointing this out.
Instead of null, you need to pass None.

1 Like

Uncommented as you suggested and recompiled. Here’s what I see while pressing down on the touchscreen:

xpt7603_read data: x = 57, y = 55, pressed = 1, state = 1
xpt7603_read data: x = 57, y = 55, pressed = 1, state = 1
xpt7603_read data: x = 58, y = 55, pressed = 1, state = 1
xpt7603_read data: x = 58, y = 55, pressed = 1, state = 1
xpt7603_read data: x = 59, y = 56, pressed = 1, state = 1
xpt7603_read data: x = 58, y = 55, pressed = 1, state = 1

And then when I let go:

xpt7603_read data: x = 58, y = 55, pressed = 0, state = 0
xpt7603_read data: x = 58, y = 55, pressed = 0, state = 0
xpt7603_read data: x = 58, y = 55, pressed = 0, state = 0

For reference, data->state is an enum:


So it looks like the driver is correctly reading the interrupt and touch input.
But still no print statements from my button event callback. (My button is at 50,50)

Am I correctly setting up the button and event callback?

I tried to follow your suggestion to read the coordinates from the script, but ran into issues.

I added the following code to my infinite while loop:

        p = lv.point_t()
        lv.indev_get_point(lv.indev_next(None), p)
        print("x=%d, y=%d" % (p.x, p.y))

But when I run the script, I get an error:

  File "", line 64, in <module>
AttributeError: 'module' object has no attribute 'indev_next'

That should be lv.indev_get_next, instead of indev_next.
Give it a try.

One problem I noticed in your code:

According to the docs, the read callback function should return false when there is no more data to read.
However, your read callback is returning valid.

I also find it confusing that the read function should return false when it succeeds.
@kisvegabor - how about changing this for future releases? I’ve already seen number of people fall in this.

Wasn’t this problem already corrected here?

Changed it to use lv.indev_get_next(None) but then it gives me an error:

  File "", line 64, in <module>
SyntaxError: Can't convert NoneType to lv_indev_t!

If I try it with no arguments, lv.indev_get_next():

  File "", line 64, in <module>
TypeError: function takes 1 positional arguments but 0 were given

Also tried creating a temporary variable tmp = lv.indev_t() and passing that to lv.indev_get_next but then I just get

x=-1, y=-1

Is there a way I can create an indev_t typed variable and set it to None?

That’s right, this was fixed. The Omega2 Dash uses the XPT7603

indev_get_next expects lv_indev_t type.
You can set it to NULL like this: lv.indev_t(None).
I agree it would be more intuitive to use None directly, I’ve added an issue to track this.

I didn’t notice any other problem with your code. The way you register the driver looks fine and the fact that your read function is called by lvgl shows that it was registered correctly.

So I suggest debugging this:

  • with lv.indev_get_point as discussed
  • with printings in lvgl code
  • with a a debugger, if that’s available.

@amirgon Thanks for your continued support on this!

I tried this out:

tmp = lv.indev_t(None)

print('starting loop')
while True:
        p = lv.point_t()
        lv.indev_get_point(lv.indev_get_next(tmp), p)
        print("x=%d, y=%d" % (p.x, p.y))

And I get this error:

Traceback (most recent call last):
  File "", line 57, in <module>
SyntaxError: Can't convert NoneType to lv_indev_t!

Where line 57 is tmp = lv.indev_t(None)

Looks like indev_t also expects a lv_indev_t type. Seems like a chicken and egg type of thing?

Do you have any suggestions on where I should start looking with a debugger?

Sorry - the correct syntax is: tmp = lv.indev_t.cast(None)
That should work.

I’d probably start with the call site of your callback:

then single-step through and try to understand how the point coordinates and state are used (or why they are not).
Perhaps @embeddedt or @kisvegabor could give some tips what you should look at.

Awesome! That works!

I see this type of output:

xpt7603_read data: x = 80, y = 71, pressed = 1, state = 1
x=-1, y=-1
x=-1, y=-1
xpt7603_read data: x = 80, y = 71, pressed = 0, state = 0
x=-1, y=-1

Now we know the driver correctly reads the touch input coordinates but doesn’t pass it along.

Once I get a debugger up and running to check out the call site of indev driver read callback, I’ll report back.

Thanks for your help!

1 Like

I fixed that, now you can use lv.indev_get_next(None)

Closing the loop here! Fixed the issue with touch input!

The root cause was kind of silly. The xpt7603_read function did not have the two arguments expected by the read_cb function pointer in lv_indev_drv_t

So it would read the touch input coordinates from the device correctly. But because of the incorrect arguments the coordinates did not get propagated to the rest of the code.

The fix is here:

A silly issue but difficult to debug.

Note that I copied the structure of my xpt7603 driver from the existing xpt2046 implmentation. It has the same issue:

Thanks for the update!

The driver which is officially supported is, where I believe the problem is not present.