[SOLVED] emWIN Slider thumb changes when LCD touched but is even close to the slider

This site uses cookies. By continuing to browse this site, you are agreeing to our Cookie Policy.

  • [SOLVED] emWIN Slider thumb changes when LCD touched but is even close to the slider

    I used an example from the emWIN and just replaced the screen source files.

    I am using Keil MDK v5 pro with a GUISingleThread template.
    On a Keil MCBSTM32F400 with STM32F407 and a 2.4" LCD resistive touch

    If I touch the slider and move it and release it close to the top ( I have the slider positioned vertically), if I then place my finger all the way on the other side of the LCD sometimes the slider will react to the change in X position even though the Y is not even close. I just have the slider widgets dropped on the screen I do not have any code in their WM handlers yet.

    I seem to notice it is only when the slider still has focus.


    I thought WM would take care of this, should it not know the Y position of the new touch is not in the area of the widget?
    Can you think of a reason the WM would not know the new area is not withing the x,y of the slider widget?

    Here is a video of the behavior.
    drive.google.com/open?id=0B5Oz…jBpVXZrUjU1dGM&authuser=0



    I was thinking if I added code in the slider RELEASED method to remove focus might remedy this situation, do you think this would work?




    This is my GUI thread

    void GUIThread (void const *argument) {

    GUI_Init(); /* Initialize the Graphics Component */
    GUI_CURSOR_Show();
    WM_SetCreateFlags(WM_CF_MEMDEV); // Use memory devices on all windows to avoid flicker
    /* Add GUI setup code here */
    //GUI_DispString("Hello World!");
    Createiccp_main();
    while (1) {

    /* All GUI related activities might only be called from here */

    #ifdef RTE_Graphics_Touchscreen /* Graphics Input Device Touchscreen enabled */
    GUI_TOUCH_Exec(); /* Execute Touchscreen support */
    #endif
    GUI_Exec(); /* Execute all GUI jobs ... Return 0 if nothing was done. */
    GUI_X_ExecIdle(); /* Nothing left to do for the moment ... Idle processing */
    }
    }






    /*********************************************************************
    *
    * _cbDialog
    */
    static void _cbDialog(WM_MESSAGE * pMsg) {
    WM_HWIN hItem;
    int NCode;
    int Id;
    // USER START (Optionally insert additional variables)
    // USER END

    switch (pMsg->MsgId) {
    case WM_INIT_DIALOG:
    //
    // Initialization of 'iccp_cv'
    //
    hItem = pMsg->hWin;
    FRAMEWIN_SetText(hItem, "CV Adjust");
    FRAMEWIN_SetTitleHeight(hItem, 20);
    //
    // Initialization of 'Home_Btn'
    //
    hItem = WM_GetDialogItem(pMsg->hWin, ID_BUTTON_0);
    BUTTON_SetText(hItem, "HOME");
    BUTTON_SetFont(hItem, GUI_FONT_16B_ASCII);
    //
    // Initialization of 'Save'
    //
    hItem = WM_GetDialogItem(pMsg->hWin, ID_BUTTON_1);
    BUTTON_SetFont(hItem, GUI_FONT_16B_ASCII);
    //
    // Initialization of 'Amps_txt'
    //
    hItem = WM_GetDialogItem(pMsg->hWin, ID_TEXT_0);
    TEXT_SetTextAlign(hItem, GUI_TA_HCENTER | GUI_TA_VCENTER);
    TEXT_SetFont(hItem, GUI_FONT_D24X32);
    TEXT_SetText(hItem, "49.5");
    TEXT_SetTextColor(hItem, 0x000303E7);
    //
    // Initialization of 'Volts'
    //
    hItem = WM_GetDialogItem(pMsg->hWin, ID_TEXT_1);
    TEXT_SetTextAlign(hItem, GUI_TA_HCENTER | GUI_TA_VCENTER);
    TEXT_SetFont(hItem, GUI_FONT_20_1);
    TEXT_SetTextColor(hItem, 0x00FF0000);
    // USER START (Optionally insert additional code for further widget initialization)
    // USER END
    break;
    case WM_NOTIFY_PARENT:
    Id = WM_GetId(pMsg->hWinSrc);
    NCode = pMsg->Data.v;
    switch(Id) {
    case ID_BUTTON_0: // Notifications sent by 'Home_Btn'
    switch(NCode) {
    case WM_NOTIFICATION_CLICKED:
    // USER START (Optionally insert code for reacting on notification message)

    // USER END
    break;
    case WM_NOTIFICATION_RELEASED:
    // USER START (Optionally insert code for reacting on notification message)
    Createiccp_main();
    // USER END
    break;
    // USER START (Optionally insert additional code for further notification handling)
    // USER END
    }
    break;
    case ID_BUTTON_1: // Notifications sent by 'Save'
    switch(NCode) {
    case WM_NOTIFICATION_CLICKED:
    // USER START (Optionally insert code for reacting on notification message)
    // USER END
    break;
    case WM_NOTIFICATION_RELEASED:
    // USER START (Optionally insert code for reacting on notification message)
    // USER END
    break;
    // USER START (Optionally insert additional code for further notification handling)
    // USER END
    }
    break;
    case ID_SLIDER_0: // Notifications sent by 'Slider'
    switch(NCode) {
    case WM_NOTIFICATION_CLICKED:
    // USER START (Optionally insert code for reacting on notification message)
    // USER END
    break;
    case WM_NOTIFICATION_RELEASED:
    // USER START (Optionally insert code for reacting on notification message)
    // USER END
    break;
    case WM_NOTIFICATION_VALUE_CHANGED:
    // USER START (Optionally insert code for reacting on notification message)
    // USER END
    break;
    // USER START (Optionally insert additional code for further notification handling)
    // USER END
    }
    break;
    // USER START (Optionally insert additional code for further Ids)
    // USER END
    }
    break;
    // USER START (Optionally insert additional message handling)
    // USER END
    default:
    WM_DefaultProc(pMsg);
    break;
    }
    }

    The post was edited 1 time, last by likeitlowlevel ().

  • Hello,

    Thank you for providing the video. It seems your touch implementation does not provide emWin with a release event. Therefor the SLIDER widget still reacts to a touch event which happened obviously outside the widget borders.

    Best regards,
    Adrian
  • Hi Adrian,

    I set a breakpoint in my project's slider WM_NOTIFICATION_RELEASED method and indeed when I release the slider the break point fires.
    So does that not tell me emWIN WM did get the "release" or not pressed info from the touch implementation?


    If this is the code you are referring to.
    What else should I have to do?
    I figured that emWIN knew the widget was released because WM_NOTIFICATION_RELEASED was passed to the parent.
    So emWIN already knows the new touch is not from an xy cord that slider widget is part if.


    After testing this I loaded the Segger demo DIALOG_SliderColor.c, and sure enough the sliders reacts exactly the same way.
    It moves when I touch an xy way outside the slider widgets xy area. Now this does not occur every time, but more than 25% of the time it does.
    Another behavior I noticed in my project and the Segger slider demo is I can move off the slider while sliding and be up to .5" away and the slider still moves like emWIN thinks the touch xy is still in the widget.
    And of course that demo is using its own touch input function not the one from my project.


    Video of the Segger demo, same exact behavior my project sees.

    drive.google.com/file/d/0B5OzB…OVDhwZ00/view?usp=sharing



    This is the touch handler from my project which is unchanged from the demo project I got from Keil or Segger.
    I am not sure which company actually supplied it.
    Not the slider demo but another demo, however since the slider demo from Segger behaves the same I believe this is not where the problem is starting from.



    This where the touch implementation informs emWIN the touch screen was pressed or no longer being pressed.


    GUI_TOUCH_Exec()

    I see here it looks for pressed and sets flag if being pressed.
    Then if not pressed but was recently pressed it calls GUI_TOUCH_StoreState(-1, -1);

    I am not 100% sure what passing in -1,-1 for x & y values would tell emWIN, but I assume
    that is the mechanism to tell it "RELEASED" or at least NOT PRESSED.
    I searched the manual but it did not mention what that meant.




    void GUI_TOUCH_Exec (void) {
    TOUCH_STATE touch_state;
    static U8 PressedOld = 0;
    static int xOld = 0;
    static int yOld = 0;
    int x, y;
    int xDiff, yDiff;
    int xSize, ySize;

    Touch_GetState(&touch_state);

    if (touch_state.pressed) {
    // Touch screen is pressed

    if (TouchOrientation & GUI_SWAP_XY) {
    TouchPhysX = touch_state.y;
    TouchPhysY = touch_state.x;
    } else {
    TouchPhysX = touch_state.x;
    TouchPhysY = touch_state.y;
    }

    // Convert touch values to pixels
    x = TouchPhysX - TouchPhysLim[0].Min;
    y = TouchPhysY - TouchPhysLim[1].Min;
    if (TouchOrientation & GUI_SWAP_XY) {
    xSize = LCD_GetYSize();
    ySize = LCD_GetXSize();
    } else {
    xSize = LCD_GetXSize();
    ySize = LCD_GetYSize();
    }
    x *= xSize - 1;
    x /= TouchPhysLim[0].Max - TouchPhysLim[0].Min;
    y *= ySize - 1;
    y /= TouchPhysLim[1].Max - TouchPhysLim[1].Min;

    if (PressedOld == 1) {
    // Touch screen has already been pressed

    // Calculate difference between new and old position
    xDiff = (x > xOld) ? (x - xOld) : (xOld - x);
    yDiff = (y > yOld) ? (y - yOld) : (yOld - y);

    // Store state if new position differs significantly
    if (xDiff + yDiff > 2) {
    GUI_TOUCH_StoreState(x, y);
    xOld = x;
    yOld = y;
    }
    }
    else {
    // Touch screen was previously not pressed

    // Store state regardless of position
    GUI_TOUCH_StoreState(x, y);
    xOld = x;
    yOld = y;
    PressedOld = 1;
    }
    }
    else {
    // Touch screen is not pressed

    // Store state if it was released recently
    if (PressedOld == 1) {
    PressedOld = 0;
    GUI_TOUCH_StoreState(-1, -1);
    }
    }
    }



    The post was edited 5 times, last by likeitlowlevel ().

  • Hello,

    Thank you for the additional explanation.

    The second behavior you mentioned is the intended way. It might be annoying for the user to keep the touch input within the borders of the widget while dragging.

    I was not able to reproduce the first behavior. I understand that release events are thrown correctly in your implementation. Still I believe the problem is hardware related. Your touch screen recognizes the release and the press event correctly , but it seems it uses the wrong (old) coordinates for the first press event(s).

    I would recommend you to track the very first coordinates when pressing the touch screen in order to verify the correctness of the coordinates.

    Best regards,
    Adrian
  • Touch data captured in debug print.

    Hi Adrian,

    I added some debug prints in the GUI_X_Touch.c I got from the Keil sample.

    I added one printf when the touch release is detected.
    I added another when new x & y values are compared against the xOld & yOld values.

    So then I would release the slider and the "RLSD" printf show up in the dbg window.
    Then I would touch way outside the widget (a good 2-3 seconds after the RLSD) and the dbg window prints the xDiff & yDiff, xOld & yOld, new x & y values

    Here is what was printed. And again this is when the slider reacts to changes outside it bounds, maybe 1-1.25 inches.
    So as in my video I am using my LCD in landscape my slider vertical so I start out by moving the slider in the y axis (up and down) then I release and touch the LCD 2 seconds later about 1 inch outside the x axis boundary of the slider widget.

    RLSD This is when I released the slider, the next line occurs about 2 seconds later when I touch the other side of the LCD
    xDiff=163 yDiff=143 xOld=48 x=211 yOld=38 y=181 GUI_stroreState is called right here passing these new values to emWIN
    xDiff=12 yDiff=7 xOld=211 x=199 yOld=181 y=188
    RLSD

    I attached a picture of the code where the touches are passed into emWIN to go along with this debug capture above. From all indications I see the data is being passed into emWIN to let it know the new touch is def where I touched.

    If we see the first touch after I released shows xOld was 48 ( that is within the slider) the new x is 211, which almost the other side of the LCD not within the slider and yet the slider reacted to the new y position of 181.

    GUI_Touch_StoreState is called and these new x&y values are passed into emWIN. But the slider is reacting incorrectly.

    The one thing I did notice is if I drag my finger off the slider after I stop moving it then release once I am off the slider. This behavior never occurs.

    But at this point the data is in the library and I cannot debug any further into why it is happening.

    What do you think?




  • Hello,

    The SLIDER widget captures touch events outside its borders once the touch screen is pressed inside its borders. This is done as long as the touch screen remains in pressed state. In addition to your current test code, could you please implement the following test in order to verify if this problem is caused by the capturing function?

    int HasCaptured;

    switch (pMsg->MsgId) {
    case WM_TOUCH:
    HasCaptured = WM_HasCaptured(pMsg->hWin);
    printf(...)
    default:
    SLIDER_Callback(pMsg);
    }

    The problem is that the SLIDER widget still reacts to a touch event outside its borders after it was released. I would like to know if this event was captured or not. Unfortunately I am still not able to reproduce this behavior.

    Best regards,
    Adrian
  • Hi Adrian,

    Good news is I got it fixed. SOLVED
    Sorry it took me a week to find time to get back to this. So I did not get to implement that block of test code you asked me to BUT I got it working.

    I rewrote GUI_TOUCH_Exe() and the main change was if TS is NOT PRESSED along with sending -1 for x & y. I also set the struct x & y elements equal to -1 as well.
    And now it works perfect, when I released the slider I can see focus is removed from it. That did not happen before.


    PS. This problem first was seen using the Keil MCBST32F400 eval board and then I bought an ST STM32F429I-EVAL and saw the same thing. Thats when I knew it could not be hardware.

    So good news is my LCD code is up and running and now I can move on to adding TCPIP.

    Here is my new routine which is the STemWin BSP_Pointer_Update with my NOT pressed modification.
    Interestingly enough ST's BSP_Pointer_Update behaved the same as the Keil GUI_TOUCH_Exe().

    C Source Code

    1. void Touch_Capture(void){ GUI_PID_STATE TS_State; static TS_StateTypeDef prev_state; TS_StateTypeDef ts; uint16_t xDiff, yDiff; BSP_TS_GetState(&ts); TS_State.Pressed = ts.TouchDetected; xDiff = (prev_state.x > ts.x) ? (prev_state.x - ts.x) : (ts.x - prev_state.x); yDiff = (prev_state.y > ts.y) ? (prev_state.y - ts.y) : (ts.y - prev_state.y); if(ts.TouchDetected) { if((prev_state.TouchDetected != ts.TouchDetected )|| (xDiff > 3 )|| (yDiff > 3)) { prev_state = ts; TS_State.Layer = 0; TS_State.x = ts.x; TS_State.y = ts.y; GUI_TOUCH_StoreStateEx(&TS_State); } } else //if released store NOT PRESSED { TS_State.Layer = 0; TS_State.x = -1; TS_State.y = -1; GUI_TOUCH_StoreStateEx(&TS_State); }}