Jump to content

GINPUT Driver Usage


kengineer

Recommended Posts

Hi, I'm trying to get the MCU touch driver working on uGFX. I've implemented all the methods (and tested) needed to successfully use the MCU touch driver with an ADC and put these in the board file under read_xyz(). I've included the driver as well in my build.

I've also set the following:

#define GFX_USE_GINPUT                                TRUE
#define GINPUT_NEED_MOUSE                        TRUE
#define GINPUT_TOUCH_STARTRAW               TRUE

What I'm not understanding is how to properly utilize this driver. I assumed that read_xyz() would be regularly polled by uGFX, however it seems that it only gets called once sometime during startup and then never again.

I then try calling ginputCalibrateMouse(0) after init. I see the calibration come on screen but then it enters a loop waiting for a condition to happen. Do I need to implement the call to poll the touchscreen read myself some how like in an interrupt? This is a bare metal system currently and I don't have threads or anything like that setup. Anyways, just looking for a little insight as I'm not understanding the proper usage of the module and how to run a simple calibration example.

Link to comment
Share on other sites

First thing to do is to make sure that your raw32 threads are working properly as they are definitely needed for any touch and can be tricky with raw32. The simplist way of checking this is to make sure that gtimer works as expected. In fact your problem sounds like it could be an issue in this area.

Once you know threading and gtimer is working then look in the demos and test subdirectiries (i can't remember which) as there are some test ugfx programs specifically designed for testing touch and getting the right parameters for the various levels and timings. Most drivers work well with the default values but the mcu driver can be a little more finicky as the software is getting no assistance from hardware intelligence. 

Link to comment
Share on other sites

All you have to do to use the MCU driver is to copy the board file /drivers/ginput/touch/MCU/gmouse_lld_MCU_board_template.h to your project and rename it to gmouse_lld_board.h. The rest is supposed to work out of the box.

It's correct that the GINPUT module will periodically call read_xyz(). This is done through a GTIMER. If it's not working then most likely the GTIMER thread crashed. This can have a couple of different reasons. The most popular ones are that the stack size of the GTIMER thread is too small or that the scheduler isn't working properly. In either case the proper way to debug this is to verify that the GTIMER module is working correctly.
Increasing the stack size of the GTIMER thread is fairly easy and can be done in the configuration file as explained in the corresponding documentation. However, the default value is already very big and shouldn't cause any problems UNLESS you are running other GTIMER jobs too. As the documentation explains all GTIMER jobs share the same stack size. If one of them needs more than what the GTIMER module provides it will crash.
The more likely case is that the very minimalistic scheduler that's implemented in the RAW32 bare metal port is not working correctly on your platform. The way to check this is to create two threads using the GOS threading API. It's enough to simply toggle an LED in each thread - or, if your display is already working - to increment a counter. But in that case make sure that you enable multi-threading support in the GDISP module by setting GDISP_NEED_MULTITHREAD to TRUE in your configuration file.

Please report back your testing results and let us know which architecture/platform you are working on. In case of it's not a specifically supported one note that there's a known problem that causes the scheduler not-to-work: Bugs in the setjmp() and longjmp() function in the clib of embedded toolchains seems to be a very common thing: https://community.ugfx.org/topic/380-f429discoveryraw32-hardfault-after-mouse-calibration/#comment-2828
In case of you are using a platform that is specifically supported by uGFX make sure that you enable the corresponding GFX_CPU_xxx support in the configuration file.

Note: Just in case of you're interested, you can find an explanation on why µGFX doesn't provide an interrupt based interface for reading the touchpanel here: https://community.ugfx.org/topic/327-touch-driver-in-semi-polling-mode

 

Link to comment
Share on other sites

Hi Joel,

I didn't even have to do your example, I just tried implementing a simple gfxSleepMilliseconds and following where that went. With GINPUT disabled (no threading), sleep function works fine. When GINPUT is enabled, after CXT_RESTORE(newt->cxt, 1 (aka longjmp) is called, I land in an exception handler for my part (Hard Fault). I'm using Atmel's SAMD series (Cortex M0+) which uses ARM GCC. I'm looking at your other link that you sent me regarding the longjmp bug.

Link to comment
Share on other sites

Yep, sadly as the linked forum posts mentions it's a very common problem that functions like setjmp() and longjmp() aren't working correctly in embedded libraries. It seems like they are simply not tested at all. This even happens with libraries from large companies like Keil (which is ARM itself).

We have implemented a scheduler ourselves for all the Cortex-M series including the Cortex-M0. I'm not sure about the Cortex-M0+ but I think that the Cortex-M0 scheduler should work on it just fine. You can enable it by setting GFX_CPU to GFX_CPU_CORTEX_M0 in your configuration file.

Link to comment
Share on other sites

Hi Joel,

I tried defining 

#define GFX_CPU                                  GFX_CPU_CORTEX_M0

the other day but this generates many compile errors, seems maybe there is some incompatibility between the two:

lo register required -- `str sp,[r2,#20]' 
lo register required -- `ldr sp,[r3,#20]' 
invalid register list to push/pop instruction -- `push {r4,r5,r6,r7,r8,r9,r10,r11,lr}'
 

etc.

Link to comment
Share on other sites

Yes. The linked forum post lists the available options:

  • Use a library that provides working setjmp() and longjmp() implementations
  • Get the provider of your library to fix their broken implementations (experience tells that they won't care much)
  • Implement your own setjmp() and longjmp() functions
  • Implement your own context switching assembly code in the existing GOS threading
  • Use an RTOS

Sorry, there's not much else we can do here. We try our best to be as flexible as possible but if the 3rd party underlying system is broken it's difficult to make something functional out of it.
For instant success you definitely might want to consider using an RTOS. Personally I may recommend ChibiOS/RT and FreeRTOS.

Link to comment
Share on other sites

So what I'm not understanding is what values I should be returned by the read_xyz function. Remember this is a resitive touch display so I'm using the MCU touch driver. Returning raw values in my board file does not work for the  ginputCalibrateMouse() calibration routine. However if I adjust these emperically to get a lower range, it seems to see my touches. I assumed that I could provide raw ADC values and the calibration routine would figure out how to map these properly to actual x y coordinates based on my touches.

 

FYI, I have confirmed that when I touch I can get ADC values proportional to my x,y location, it's just that these are raw ADC values (i.e. 3000,3000 in a corner). In the two board file examples I see in uGFX, it seems like they calculate it slightly different with each.

Edited by kengineer
Link to comment
Share on other sites

I'm not exactly understanding your question / your concern. You are not supposed to mess with ginputCalibrateMous() or anything else yourself. Implement the board file and that's it. The struct you have in your board file allows you to configure many things like the calibration tolerances and so on. Don't modify anything else. If you are just using a regular setup with just one touchscreen there's also no need to ever manually use any of the GINPUT API.

The  ginputCalibrateMouse() function is called automatically for you unless you have disabled it. It's also possible to load calibration data that has been obtained by a previous calibration process. If the loading of calibration data succeeded, the calibration screen won't be shown on startup. You can find all the information needed here: http://wiki.ugfx.org/index.php/Touchscreen_Calibration

Link to comment
Share on other sites

Hi Joel,

I was talking about the specific implementation in the board file. I figured out the issue though, it was adjustments to the #defines in the board file.

The calibration routine wasn't starting automatically because I had defined GINPUT_TOUCH_STARTRAW as true. I disabled it and now it starts, so problem solved. Thanks!

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...