acid-drop

- Hacking the planet from a LilyGo T-Deck using custom firmware
git clone git://git.acid.vegas/acid-drop.git
Log | Files | Refs | Archive | README | LICENSE

Keypad_480x320.ino (8546B)

      1 /*
      2   The TFT_eSPI library incorporates an Adafruit_GFX compatible
      3   button handling class, this sketch is based on the Arduin-o-phone
      4   example.
      5 
      6   This example diplays a keypad where numbers can be entered and
      7   send to the Serial Monitor window.
      8 
      9   The sketch has been tested on the ESP8266 (which supports SPIFFS)
     10 
     11   The minimum screen size is 320 x 240 as that is the keypad size.
     12 
     13   TOUCH_CS and SPI_TOUCH_FREQUENCY must be defined in the User_Setup.h file
     14   for the touch functions to do anything.
     15 */
     16 
     17 // The SPIFFS (FLASH filing system) is used to hold touch screen
     18 // calibration data
     19 
     20 #include "FS.h"
     21 
     22 #include <SPI.h>
     23 #include <TFT_eSPI.h>      // Hardware-specific library
     24 
     25 TFT_eSPI tft = TFT_eSPI(); // Invoke custom library
     26 
     27 // This is the file name used to store the calibration data
     28 // You can change this to create new calibration files.
     29 // The SPIFFS file name must start with "/".
     30 #define CALIBRATION_FILE "/TouchCalData2"
     31 
     32 // Set REPEAT_CAL to true instead of false to run calibration
     33 // again, otherwise it will only be done once.
     34 // Repeat calibration if you change the screen rotation.
     35 #define REPEAT_CAL false
     36 
     37 // Keypad start position, key sizes and spacing
     38 #define KEY_X 40 // Centre of key
     39 #define KEY_Y 96
     40 #define KEY_W 62 // Width and height
     41 #define KEY_H 30
     42 #define KEY_SPACING_X 18 // X and Y gap
     43 #define KEY_SPACING_Y 20
     44 #define KEY_TEXTSIZE 1   // Font size multiplier
     45 
     46 // Using two fonts since numbers are nice when bold
     47 #define LABEL1_FONT &FreeSansOblique12pt7b // Key label font 1
     48 #define LABEL2_FONT &FreeSansBold12pt7b    // Key label font 2
     49 
     50 // Numeric display box size and location
     51 #define DISP_X 1
     52 #define DISP_Y 10
     53 #define DISP_W 238
     54 #define DISP_H 50
     55 #define DISP_TSIZE 3
     56 #define DISP_TCOLOR TFT_CYAN
     57 
     58 // Number length, buffer for storing it and character index
     59 #define NUM_LEN 12
     60 char numberBuffer[NUM_LEN + 1] = "";
     61 uint8_t numberIndex = 0;
     62 
     63 // We have a status line for messages
     64 #define STATUS_X 120 // Centred on this
     65 #define STATUS_Y 65
     66 
     67 // Create 15 keys for the keypad
     68 char keyLabel[15][5] = {"New", "Del", "Send", "1", "2", "3", "4", "5", "6", "7", "8", "9", ".", "0", "#" };
     69 uint16_t keyColor[15] = {TFT_RED, TFT_DARKGREY, TFT_DARKGREEN,
     70                          TFT_BLUE, TFT_BLUE, TFT_BLUE,
     71                          TFT_BLUE, TFT_BLUE, TFT_BLUE,
     72                          TFT_BLUE, TFT_BLUE, TFT_BLUE,
     73                          TFT_BLUE, TFT_BLUE, TFT_BLUE
     74                         };
     75 
     76 // Invoke the TFT_eSPI button class and create all the button objects
     77 TFT_eSPI_Button key[15];
     78 
     79 //------------------------------------------------------------------------------------------
     80 
     81 void setup() {
     82   // Use serial port
     83   Serial.begin(9600);
     84 
     85   // Initialise the TFT screen
     86   tft.init();
     87 
     88   // Set the rotation before we calibrate
     89   tft.setRotation(1);
     90 
     91   // Calibrate the touch screen and retrieve the scaling factors
     92   touch_calibrate();
     93 
     94   // Clear the screen
     95   tft.fillScreen(TFT_BLACK);
     96 
     97   // Draw keypad background
     98   tft.fillRect(0, 0, 240, 320, TFT_DARKGREY);
     99 
    100   // Draw number display area and frame
    101   tft.fillRect(DISP_X, DISP_Y, DISP_W, DISP_H, TFT_BLACK);
    102   tft.drawRect(DISP_X, DISP_Y, DISP_W, DISP_H, TFT_WHITE);
    103 
    104   // Draw keypad
    105   drawKeypad();
    106 }
    107 
    108 //------------------------------------------------------------------------------------------
    109 
    110 void loop(void) {
    111   uint16_t t_x = 0, t_y = 0; // To store the touch coordinates
    112 
    113   // Pressed will be set true is there is a valid touch on the screen
    114   bool pressed = tft.getTouch(&t_x, &t_y);
    115 
    116   // / Check if any key coordinate boxes contain the touch coordinates
    117   for (uint8_t b = 0; b < 15; b++) {
    118     if (pressed && key[b].contains(t_x, t_y)) {
    119       key[b].press(true);  // tell the button it is pressed
    120     } else {
    121       key[b].press(false);  // tell the button it is NOT pressed
    122     }
    123   }
    124 
    125   // Check if any key has changed state
    126   for (uint8_t b = 0; b < 15; b++) {
    127 
    128     if (b < 3) tft.setFreeFont(LABEL1_FONT);
    129     else tft.setFreeFont(LABEL2_FONT);
    130 
    131     if (key[b].justReleased()) key[b].drawButton();     // draw normal
    132 
    133     if (key[b].justPressed()) {
    134       key[b].drawButton(true);  // draw invert
    135 
    136       // if a numberpad button, append the relevant # to the numberBuffer
    137       if (b >= 3) {
    138         if (numberIndex < NUM_LEN) {
    139           numberBuffer[numberIndex] = keyLabel[b][0];
    140           numberIndex++;
    141           numberBuffer[numberIndex] = 0; // zero terminate
    142         }
    143         status(""); // Clear the old status
    144       }
    145 
    146       // Del button, so delete last char
    147       if (b == 1) {
    148         numberBuffer[numberIndex] = 0;
    149         if (numberIndex > 0) {
    150           numberIndex--;
    151           numberBuffer[numberIndex] = 0;//' ';
    152         }
    153         status(""); // Clear the old status
    154       }
    155 
    156       if (b == 2) {
    157         status("Sent value to serial port");
    158         Serial.println(numberBuffer);
    159       }
    160       // we dont really check that the text field makes sense
    161       // just try to call
    162       if (b == 0) {
    163         status("Value cleared");
    164         numberIndex = 0; // Reset index to 0
    165         numberBuffer[numberIndex] = 0; // Place null in buffer
    166       }
    167 
    168       // Update the number display field
    169       tft.setTextDatum(TL_DATUM);        // Use top left corner as text coord datum
    170       tft.setFreeFont(&FreeSans18pt7b);  // Choose a nicefont that fits box
    171       tft.setTextColor(DISP_TCOLOR);     // Set the font colour
    172 
    173       // Draw the string, the value returned is the width in pixels
    174       int xwidth = tft.drawString(numberBuffer, DISP_X + 4, DISP_Y + 12);
    175 
    176       // Now cover up the rest of the line up by drawing a black rectangle.  No flicker this way
    177       // but it will not work with italic or oblique fonts due to character overlap.
    178       tft.fillRect(DISP_X + 4 + xwidth, DISP_Y + 1, DISP_W - xwidth - 5, DISP_H - 2, TFT_BLACK);
    179 
    180       delay(10); // UI debouncing
    181     }
    182   }
    183 }
    184 
    185 //------------------------------------------------------------------------------------------
    186 
    187 void drawKeypad()
    188 {
    189   // Draw the keys
    190   for (uint8_t row = 0; row < 5; row++) {
    191     for (uint8_t col = 0; col < 3; col++) {
    192       uint8_t b = col + row * 3;
    193 
    194       if (b < 3) tft.setFreeFont(LABEL1_FONT);
    195       else tft.setFreeFont(LABEL2_FONT);
    196 
    197       key[b].initButton(&tft, KEY_X + col * (KEY_W + KEY_SPACING_X),
    198                         KEY_Y + row * (KEY_H + KEY_SPACING_Y), // x, y, w, h, outline, fill, text
    199                         KEY_W, KEY_H, TFT_WHITE, keyColor[b], TFT_WHITE,
    200                         keyLabel[b], KEY_TEXTSIZE);
    201       key[b].drawButton();
    202     }
    203   }
    204 }
    205 
    206 //------------------------------------------------------------------------------------------
    207 
    208 void touch_calibrate()
    209 {
    210   uint16_t calData[5];
    211   uint8_t calDataOK = 0;
    212 
    213   // check file system exists
    214   if (!SPIFFS.begin()) {
    215     Serial.println("Formating file system");
    216     SPIFFS.format();
    217     SPIFFS.begin();
    218   }
    219 
    220   // check if calibration file exists and size is correct
    221   if (SPIFFS.exists(CALIBRATION_FILE)) {
    222     if (REPEAT_CAL)
    223     {
    224       // Delete if we want to re-calibrate
    225       SPIFFS.remove(CALIBRATION_FILE);
    226     }
    227     else
    228     {
    229       File f = SPIFFS.open(CALIBRATION_FILE, "r");
    230       if (f) {
    231         if (f.readBytes((char *)calData, 14) == 14)
    232           calDataOK = 1;
    233         f.close();
    234       }
    235     }
    236   }
    237 
    238   if (calDataOK && !REPEAT_CAL) {
    239     // calibration data valid
    240     tft.setTouch(calData);
    241   } else {
    242     // data not valid so recalibrate
    243     tft.fillScreen(TFT_BLACK);
    244     tft.setCursor(20, 0);
    245     tft.setTextFont(2);
    246     tft.setTextSize(1);
    247     tft.setTextColor(TFT_WHITE, TFT_BLACK);
    248 
    249     tft.println("Touch corners as indicated");
    250 
    251     tft.setTextFont(1);
    252     tft.println();
    253 
    254     if (REPEAT_CAL) {
    255       tft.setTextColor(TFT_RED, TFT_BLACK);
    256       tft.println("Set REPEAT_CAL to false to stop this running again!");
    257     }
    258 
    259     tft.calibrateTouch(calData, TFT_MAGENTA, TFT_BLACK, 15);
    260 
    261     tft.setTextColor(TFT_GREEN, TFT_BLACK);
    262     tft.println("Calibration complete!");
    263 
    264     // store data
    265     File f = SPIFFS.open(CALIBRATION_FILE, "w");
    266     if (f) {
    267       f.write((const unsigned char *)calData, 14);
    268       f.close();
    269     }
    270   }
    271 }
    272 
    273 //------------------------------------------------------------------------------------------
    274 
    275 // Print something in the mini status bar
    276 void status(const char *msg) {
    277   tft.setTextPadding(240);
    278   //tft.setCursor(STATUS_X, STATUS_Y);
    279   tft.setTextColor(TFT_WHITE, TFT_DARKGREY);
    280   tft.setTextFont(0);
    281   tft.setTextDatum(TC_DATUM);
    282   tft.setTextSize(1);
    283   tft.drawString(msg, STATUS_X, STATUS_Y);
    284 }
    285 
    286 //------------------------------------------------------------------------------------------
    287