adafruit / Adafruit_HX8357_Library

Arduino library for HX8357
39 stars 37 forks source link

merged-in touch button example; not working for Feather M4 #21

Closed dsyleixa closed 5 years ago

dsyleixa commented 5 years ago

re: merged-in touch button example; not working for Feather M4 https://github.com/adafruit/Adafruit_HX8357_Library/issues/12#event-2296117523 (edit: regrettably this issue was locked so I could not respond there)

Thanks for merging in the touch button example https://github.com/adafruit/Adafruit_HX8357_Library/pull/15 nonetheless, my Feather M4 board could not be detected and thus the code could not be compiled because of missing board #defines and mis-spelling TFT-pin macros (partialy spelled lower-case instead of upper-case) .

Instead, this fix works for my Feather M4:


/*
 * gfxbuttontest_featherwing
 */

#include <SPI.h>
#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_HX8357.h>
#include <Adafruit_STMPE610.h>

#ifdef ESP8266
   #define STMPE_CS 16
   #define TFT_CS   0
   #define TFT_DC   15
   #define SD_CS    2

#elif defined ESP32
   #define STMPE_CS 32
   #define TFT_CS   15
   #define TFT_DC   33
   #define SD_CS    14

#elif defined TEENSYDUINO
   #define TFT_DC   10
   #define TFT_CS   4
   #define STMPE_CS 3
   #define SD_CS    8

#elif defined ARDUINO_STM32_FEATHER
   #define TFT_DC   PB4
   #define TFT_CS   PA15
   #define STMPE_CS PC7
   #define SD_CS    PC5

#elif defined ARDUINO_FEATHER52
   #define STMPE_CS 30
   #define TFT_CS   13
   #define TFT_DC   11
   #define SD_CS    27

#elif  defined(ARDUINO_MAX32620FTHR) || defined(ARDUINO_MAX32630FTHR)
   #define TFT_DC   P5_4
   #define TFT_CS   P5_3
   #define STMPE_CS P3_3
   #define SD_CS    P3_2

// Something else!
#elif  defined (__AVR_ATmega32U4__) || defined(ARDUINO_SAMD_FEATHER_M0) || defined (__AVR_ATmega328P__) || defined(ARDUINO_SAMD_ZERO) || defined(__SAMD51__)   
   #define STMPE_CS 6
   #define TFT_CS   9
   #define TFT_DC   10
   #define SD_CS    5

 // optional different defaults 
#else
   #define STMPE_CS 6
   #define TFT_CS   9
   #define TFT_DC   10
   #define SD_CS    5
#endif

#define TFT_RST -1

// Use hardware SPI and the above for CS/DC
Adafruit_HX8357  tft = Adafruit_HX8357( TFT_CS,  TFT_DC,  TFT_RST);
Adafruit_STMPE610 ts = Adafruit_STMPE610(STMPE_CS);

// This is calibration data for the raw touch data to the screen coordinates
// For rotation 1, these put the buttons at the top of the screen
#define TS_MINX 3800
#define TS_MAXX 100
#define TS_MINY 100
#define TS_MAXY 3750

// Redefine original colors, add additional colors to match those available with the ILI9341 library
#define HX8357_BLACK       0x0000  ///<   0,   0,   0
#define HX8357_NAVY        0x000F  ///<   0,   0, 123
#define HX8357_DARKGREEN   0x03E0  ///<   0, 125,   0
#define HX8357_DARKCYAN    0x03EF  ///<   0, 125, 123
#define HX8357_MAROON      0x7800  ///< 123,   0,   0
#define HX8357_PURPLE      0x780F  ///< 123,   0, 123
#define HX8357_OLIVE       0x7BE0  ///< 123, 125,   0
#define HX8357_LIGHTGREY   0xC618  ///< 198, 195, 198
#define HX8357_DARKGREY    0x7BEF  ///< 123, 125, 123
#define HX8357_BLUE        0x001F  ///<   0,   0, 255
#define HX8357_GREEN       0x07E0  ///<   0, 255,   0
#define HX8357_CYAN        0x07FF  ///<   0, 255, 255
#define HX8357_RED         0xF800  ///< 255,   0,   0
#define HX8357_MAGENTA     0xF81F  ///< 255,   0, 255
#define HX8357_YELLOW      0xFFE0  ///< 255, 255,   0
#define HX8357_WHITE       0xFFFF  ///< 255, 255, 255
#define HX8357_ORANGE      0xFD20  ///< 255, 165,   0
#define HX8357_GREENYELLOW 0xAFE5  ///< 173, 255,  41
#define HX8357_PINK        0xFC18  ///< 255, 130, 198

// UI Buttondetails
#define BUTTON_X 40
#define BUTTON_Y 40
#define BUTTON_W 80
#define BUTTON_H 80
#define BUTTON_TEXTSIZE 2
#define DISPLAY_XOFFSET 80
#define DISPLAY_TEXTOFFSET 90
#define DISPLAY_YOFFSET 0

enum ButtonName {
  BTN_UP,
  BTN_SELECT,
  BTN_DOWN,
  BTN_RETURN
};

#define MENU1_BTN_CNT 4
Adafruit_GFX_Button Menu1Buttons[MENU1_BTN_CNT];
char Menu1Labels[MENU1_BTN_CNT][5] = {"Up", "Sel", "Down", "Ret"};
uint16_t Menu1Colors[MENU1_BTN_CNT] = {HX8357_DARKGREY, HX8357_DARKGREY, 
                               HX8357_DARKGREY, HX8357_DARKGREY};

#define MENU2_BTN_CNT 4
Adafruit_GFX_Button Menu2Buttons[MENU2_BTN_CNT];
char Menu2Labels[MENU2_BTN_CNT][5] = {"Up", "Sel", "Down", "Ret"};
uint16_t Menu2Colors[MENU2_BTN_CNT] = {HX8357_BLUE, HX8357_BLUE, 
                               HX8357_BLUE, HX8357_BLUE};

int textSize = 2;
int textColorIndex = 0;
uint16_t textColor[7] = {
 HX8357_WHITE,
 HX8357_RED,
 HX8357_GREEN,
 HX8357_BLUE,
 HX8357_CYAN,
 HX8357_MAGENTA,
 HX8357_YELLOW
};

//-------------------------------------------------------------------------
void setTextColorIndex(int updown) {
    textColorIndex += updown;
    if (textColorIndex > 6)  
        textColorIndex = 0;
    else if (textColorIndex < 0)
        textColorIndex = 6;
     tft.setTextColor(textColor[textColorIndex]);
}

//-------------------------------------------------------------------------
void setTextSizeIndex(int updown) {
    textSize += updown;
    if (textSize > 3)  
        textSize = 1;
    else if (textSize < 1)
        textSize = 3;
     tft.setTextSize(textSize);
}

//-------------------------------------------------------------------------
bool initializeButtons(
            Adafruit_GFX_Button menuButtons[], 
            uint16_t menuColors[], 
            char menuLabels[][5], 
            int menuButtonCount) {
     tft.fillScreen(HX8357_BLACK);

    for (uint8_t row=0; row<menuButtonCount; row++) 
    {
        menuButtons[row].initButton(& tft, 
            BUTTON_X, 
            BUTTON_Y + row *(BUTTON_H),    
            BUTTON_W, 
            BUTTON_H, 
            HX8357_BLACK, 
            menuColors[row], 
            HX8357_WHITE,
            menuLabels[row], BUTTON_TEXTSIZE);    
        menuButtons[row].drawButton();
    }
    return true;
}

//-------------------------------------------------------------------------
void tftSetCenterCursor(String str, int16_t xIn, int16_t yIn) {
  int16_t xText, yText;
  uint16_t w, h;  

    tft.getTextBounds(str, 0, 0, &xText, &yText, &w, &h);
    tft.setCursor(xIn-w/2, yIn-h/2);  
}

//--------------------------------------------------------------------------------
void tftPrint(String str) {
    int16_t xText, yText;
    uint16_t w, h;  

      tft.getTextBounds(str, 0, 0, &xText, &yText, &w, &h);
      tft.fillRect(  tft.getCursorX(),   tft.getCursorY(), w, h, HX8357_BLACK);
      tft.print(str);
}

//-------------------------------------------------------------------------
void tftCenterPrint(String str) {
      tft.setTextSize(textSize);
      tftSetCenterCursor(str, 
                   DISPLAY_TEXTOFFSET + (  tft.width()-DISPLAY_TEXTOFFSET)/2, 
                   DISPLAY_YOFFSET + ( tft.height()-DISPLAY_YOFFSET)/2);
     tftPrint(str);
}

//--------------------------------------------------------------------------------
void setup() {
    Serial.begin(115200);
    delay(100);
    Serial.println("");

    // if the touchscreen returns true, assume we have the  tft device
    if (!ts.begin())
        return;

    Serial.println("Touchscreen started");
     tft.begin();
     tft.setRotation(1);
     tft.setTextWrap(false);

    initializeButtons(Menu1Buttons, Menu1Colors, Menu1Labels, MENU1_BTN_CNT);
}

//--------------------------------------------------------------------------------
int  tftButtonRelease(Adafruit_GFX_Button menuButtons[], int menuButtonCount) {
    int btn = -1;
    TS_Point p;

    if (ts.bufferSize()) 
    {
        p = ts.getPoint(); 
    } 
    else 
    {
        // this is our way of tracking touch 'release'!
        p.x = p.y = p.z = -1;
    }

    // Scale from ~0->4000 to  tft.width using the calibration #'s
    if (p.z != -1) 
    {
        int16_t px = p.x;
        int16_t py = p.y;
        p.x = map(py, TS_MINY, TS_MAXY, 0,  tft.width());
        p.y = map(px, TS_MINX, TS_MAXX, 0,  tft.height()); 
    }

    // go thru all the buttons, checking if they were pressed
    for (uint8_t b=0; b<menuButtonCount; b++) 
    {
        if (menuButtons[b].contains(p.x, p.y)) 
        {
          Serial.print("Pressing: "); Serial.println(b);
          menuButtons[b].press(true);  // tell the button it is pressed
        } 
        else 
        {
          menuButtons[b].press(false);  // tell the button it is NOT pressed
        }
    }

    // now we can ask the buttons if their state has changed
    for (uint8_t b=0; b<menuButtonCount; b++) 
    {
        if (menuButtons[b].justReleased()) 
        {
          Serial.print("Released: "); Serial.println(b);
          menuButtons[b].drawButton();  // draw normal
          btn = b;
        }

        if (menuButtons[b].justPressed()) 
        {
            menuButtons[b].drawButton(true);  // draw invert!
            delay(100); // UI debouncing
        }
    }
    return btn;
}

//--------------------------------------------------------------------------------
void processMenu2() {
    String msg = "";
    bool exitLoop = false;

    initializeButtons(Menu2Buttons, Menu2Colors, Menu2Labels, MENU2_BTN_CNT);

    msg = "   Menu 2 Up button   ";
    Serial.println(msg);
    setTextColorIndex(0);
    setTextSizeIndex(0);
     tftCenterPrint(msg);

    while (!exitLoop)
    {   
        int btn =  tftButtonRelease(Menu2Buttons, MENU2_BTN_CNT);
        if (btn >= 0 && btn < MENU2_BTN_CNT)
        {
            Serial.print("btn = "); Serial.println(btn);
        }

        switch (btn)
        {
          case BTN_UP:
            msg = "Menu 2 Up button      ";
            Serial.println(msg);
            setTextColorIndex(1);
             tftCenterPrint(msg);
            break;

          case BTN_SELECT:
            msg = "Menu 2 Select Button  ";
            Serial.println(msg);
            setTextColorIndex(0);
             tftCenterPrint(msg);
            break;

          case BTN_DOWN:
            msg = "Menu 2 Down Button    ";
            Serial.println(msg);
            setTextColorIndex(-1);
             tftCenterPrint(msg);
            break;

          case BTN_RETURN:
            msg = "Menu 2 Ret Button     ";
            Serial.println(msg);
            Serial.println("Exiting Menu2, Returing to Menu1");

            exitLoop = true;
            break;

          default:
            break;
        }
    }
}

//--------------------------------------------------------------------------------
void processMenu1() {
    String msg = "";

    int btn =  tftButtonRelease(Menu1Buttons, MENU1_BTN_CNT);
    if (btn >= 0 && btn < MENU1_BTN_CNT)
    {
        Serial.print("btn = "); Serial.println(btn);
    }

    switch (btn)
    {
      case BTN_UP:
        msg = "Menu 1 Up Button    ";
        Serial.println(msg);
         tft.fillRect(DISPLAY_XOFFSET,DISPLAY_YOFFSET, tft.width(), tft.height(), HX8357_BLACK);
        setTextColorIndex(0);
        setTextSizeIndex(1);
         tftCenterPrint(msg);
        break;

      case BTN_SELECT:
        msg = "Menu 1 Select Button";
        Serial.println(msg);
        processMenu2();

        initializeButtons(Menu1Buttons, Menu1Colors, Menu1Labels, MENU1_BTN_CNT);

        msg = "Returned from Menu2 ";
        Serial.println(msg);
        setTextColorIndex(0);
        setTextSizeIndex(0);
        tftCenterPrint(msg);
        break;

      case BTN_DOWN:
        msg = "Menu 1 Down Button  ";
        Serial.println(msg);
         tft.fillRect(DISPLAY_XOFFSET,DISPLAY_YOFFSET, tft.width(), tft.height(), HX8357_BLACK);
        setTextColorIndex(0);
        setTextSizeIndex(-1);
         tftCenterPrint(msg);
        break;

      case BTN_RETURN:
        msg = "Menu 1 Ret Button   ";
        Serial.println(msg);
        tftCenterPrint(msg);
        break;

      default:
        break;
    }
}

//--------------------------------------------------------------------------------
void loop() {

    processMenu1();

}
makermelissa commented 5 years ago

Interesting. The Feather M4 was the first board I tested with and it seemed to be working. Do you want to update your code and submit another PR?

makermelissa commented 5 years ago

This has been updated.

dsyleixa commented 5 years ago

hello, all I formerly had found from you was https://github.com/adafruit/Adafruit_HX8357_Library/issues/12#event-2296117523 and https://github.com/adafruit/Adafruit_HX8357_Library/pull/15 whilst in the Adafruit repo the TFT button example code was already 5 or 7 months old (CMIIW)

Now I tried this version (now 4 hours old): https://github.com/adafruit/Adafruit_HX8357_Library/blob/master/examples/gfxbuttontest_featherwing/gfxbuttontest_featherwing.ino and that works fine!

dsyleixa commented 5 years ago

PS, in the Adafruit HX8357 repo folder
gfxbuttontest_featherwing is another extra file .mega2560.test.skip https://github.com/adafruit/Adafruit_HX8357_Library/blob/master/examples/gfxbuttontest_featherwing/.mega2560.test.skip what is that for?

makermelissa commented 5 years ago

The .mega2560.test.skp file causes the automated test for the Arduino Mega 2560 to be skipped when the code is tested. Since it was designed for a TFT FeatherWing, that was fine.

dsyleixa commented 5 years ago

but why is that an extra file? Why is the code not integrated in the main .ino file? Finally the code is an example to work for all boards, as long as wired accordingly to either MCU board...?

dsyleixa commented 5 years ago

PS, as to .mega2560.test.skp Why has it such a weird name? (not .ino, not .h, not .cpp, and 1 leading dot and 1 more dot in between?) Is that a Arduino code file at all? I cannot even see a single code line inside!

makermelissa commented 5 years ago

The dot at the beginning causes the file to be hidden. The mega2560 means it should only skip the Arduino Mega 2560 test and the test.skp is just the type of file it is. It has no usefulness other than as a way of telling the automated tests which ones to skip. Without it, all tests are run and sometimes we want to skip them.

dsyleixa commented 5 years ago

Are the automated tests made to be used by end users? Where can I see those automated tests? OTOH, actually to me the .mega2560.test.skp file is NOT hidden in the lib.

Or can I delete this .mega2560.test.skp file from the lib if the automated tests are NOT intended to be used for end users.

If I delete it and wire accordingly to the correct Mega pins, will it work for the Mega too, or will it damage the Mega then?

makermelissa commented 5 years ago

Nope. They’re run whenever we submit changes to reduce the chances of breaking something. You can delete it if it bothers you. It shouldn’t damage the Mega, but it may or may not compile for it. If you’re able to get it compiling then there’s really no reason to have the skip file. It was just included as part of the pull request.

dsyleixa commented 5 years ago

yes, it compiles for the Mega2560 cpu platform.

makermelissa commented 5 years ago

Awesome. thanks for letting us know.

dsyleixa commented 5 years ago

you're welcome, I'm glad if I could help. Unfortunately some of your contributers or owners (e.g., LadyAda) are acting very unpolite and lock an issue report even if it's not resolved, so follow-up questions or remarks or updates are not possible any more. That is IMO - friendly spoken - not helpful at all, neither for your libs nor for the customers purchasing Adafruit products. Gladfully you are keeping it open until it's reported to be resolved, thank you!

ladyada commented 5 years ago

@dsyleixa hiya, we cannot do tech support in github issues, if you have technical questions about why a library or hardware is designed a certain way you can ask in the forums, its not for posting in github. bug reports, code contributions only here. thanks!

dsyleixa commented 5 years ago

well, sometimes for you it seems to be a support request at first glance, but then it turned out to be bug though. e.g. my report about SPI clock for HX8357: the freq parameter to ::begin(freq) does not represent a frequency at all, and it makes no change at all for either arbitrary value - that's definitely a bug, but I couldn't report that cause it's locked.

ladyada commented 5 years ago

bug reports are welcome - if you find a bug, open a specific issue with how to reproduce it (e.g. proof of bug)

dsyleixa commented 5 years ago

ok, then I will post th issue anew.