kengineer Posted April 15, 2016 Report Share Posted April 15, 2016 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 More sharing options...
inmarket Posted April 16, 2016 Report Share Posted April 16, 2016 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 More sharing options...
Joel Bodenmann Posted April 16, 2016 Report Share Posted April 16, 2016 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 More sharing options...
kengineer Posted April 18, 2016 Author Report Share Posted April 18, 2016 Currently the option to use gtimer is commented out, maybe this is part of my problem. //#define GFX_USE_GTIMER FALSE Link to comment Share on other sites More sharing options...
Joel Bodenmann Posted April 18, 2016 Report Share Posted April 18, 2016 The GINPUT module will automatically enable the GTIMER module as it's a dependency. Check your compiler output log. You should get a corresponding #warning that tells you that this happened unless you set GFX_DISPLAY_RULE_WARNINGS to FALSE (which isn't a documented feature). Link to comment Share on other sites More sharing options...
kengineer Posted April 18, 2016 Author Report Share Posted April 18, 2016 My display is currently working so I'm going to try the threading example you told me above. Link to comment Share on other sites More sharing options...
Joel Bodenmann Posted April 18, 2016 Report Share Posted April 18, 2016 Sure, let us know how the test went. We're looking forward to resolving your issue Link to comment Share on other sites More sharing options...
kengineer Posted April 18, 2016 Author Report Share Posted April 18, 2016 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 More sharing options...
Joel Bodenmann Posted April 18, 2016 Report Share Posted April 18, 2016 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 More sharing options...
kengineer Posted April 18, 2016 Author Report Share Posted April 18, 2016 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 More sharing options...
Joel Bodenmann Posted April 18, 2016 Report Share Posted April 18, 2016 Well either the registers are incompatible - in which case you might be able to simply copy and modify the existing code for the Cortex-M0 - or the assembly syntax used isn't compatible with the compiler that you are using which is a huge pain in the ass. Link to comment Share on other sites More sharing options...
kengineer Posted April 18, 2016 Author Report Share Posted April 18, 2016 So the only other real solution other than fixing one of those issues you mentioned in your previous post is probably to run FreeRTOS or something? Link to comment Share on other sites More sharing options...
Joel Bodenmann Posted April 18, 2016 Report Share Posted April 18, 2016 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 More sharing options...
kengineer Posted April 20, 2016 Author Report Share Posted April 20, 2016 Hi Joel, I got FreeRTOS up and running and now read_xyz() in being called on a regular basis. Just trying to figure out how ginputCalibrateMouse() works now. Link to comment Share on other sites More sharing options...
kengineer Posted April 20, 2016 Author Report Share Posted April 20, 2016 (edited) 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 April 20, 2016 by kengineer Link to comment Share on other sites More sharing options...
Joel Bodenmann Posted April 20, 2016 Report Share Posted April 20, 2016 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 More sharing options...
kengineer Posted April 20, 2016 Author Report Share Posted April 20, 2016 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 More sharing options...
Joel Bodenmann Posted April 20, 2016 Report Share Posted April 20, 2016 Ah okay, sorry for not providing a helpful answer then. Glad to hear that you got it working, though! Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now