Keyboard and Number Pad library for ILI9341_t3 Displays.

KrisKasprzak

Well-known member
All,

If you have never needed to capture user input such as IP address, user names, filenames, and passwords, this library does it all. This easy to implement library is the perfect component for your Teensy projects with TFT LCD touchscreens (320x240 displays). The two classes include a full keyboard and a number pad. The Keyboard has upper/lower case, all special characters, and hidden character display for masking input. The number pad has decimals, negative signs, max / min support, and also supports hidden display characters.

Dependencies are
  • ILI9341_t3 display library
  • XPT2046_Touchscreen touch library
  • ILI9341_t3_Controls library


Watch the YouTube Video
https://youtu.be/PrSxA_QEzuk


Get the libraries here
Keyboard / Number Pad
https://github.com/KrisKasprzak/ILI9341_t3_Keypad

Controls library
https://github.com/KrisKasprzak/ILI9341_t3_controls


Happy typing!
 
Perfect timing thank you Kris. Current project based on ILI9341_t3_Controls and 18 encoders has evolved into a fully functional Roland JV-1080 and JV-2080 synth editor / controller and targets three connected synths. Currently playing with bells and whistles.

ILI9341_t3_Keypad caught my eye as a potential learning curve candidate to edit Patch names.

Looking at the Keyboard example, compiler complains about

Code:
/ILI9341_t3_PrintScreen_SdFat.h:163:2 error 'File" was not declared in this scope
File   bmpFile;

/ILI9341_t3_PrintScreen_SdFat.h:184:2 error bmp'File" was not declared in this scope
bmpFile = sd.open(FileName, FILE_READ);
Keen to make it work and dive in.
 
rats... I forgot to remove my screen capturing utility before uploading.

PS, i'd love to see a few screen shots or your UI as I'm always curious to what people are doing with the controls lib.


example fixed and include here

Code:
// required libraries
#include "ILI9341_t3.h"  // high speed display that ships with Teensy
#include "font_Arial.h"  // custom fonts that ships with ILI9341_t3.h
#include <font_ArialBold.h>
#include <ILI9341_t3_Controls.h>
#include <ILI9341_t3_Keypad.h>
#include <XPT2046_Touchscreen.h>

// pins for LED and select button on encoder
#define CS_PIN 10
#define DC_PIN 9
#define T_CS 0
#define T_IRQ 1
#define SD_CS A0
// easy way to include fonts but change globally
#define FONT_BUTTON Arial_16  // font for keypad buttons

int BtnX = 0, BtnY = 0;
int i = 0;

// you know the drill
// use the second one, this is a mod I made to the lib
ILI9341_t3 Display(CS_PIN, DC_PIN, 240, 320, 8);  //Display object
// ILI9341_t3 Display(CS_PIN, DC_PIN, 8);  //Display object

XPT2046_Touchscreen Touch(T_CS, T_IRQ);
TS_Point p;

// create some UI buttons
Button ShowPassword(&Display);
Button ShowNumberPad(&Display);
Button ShowKeyboard(&Display);

// create some keypad objects
NumberPad PasswordInput(&Display, &Touch);
NumberPad MyNumberPad(&Display, &Touch);
Keyboard MyKeyboard(&Display, &Touch);



void setup() {

  Serial.begin(9600);

  // while ((millis() > 5000) || (!Serial)) {}

  // fire up the display
  Display.begin();
  Display.setRotation(1);

  Touch.begin();
  Touch.setRotation(1);

  Display.fillScreen(ILI9341_BLACK);

  ShowPassword.init(160, 50, 150, 50, ILI9341_NAVY, ILI9341_BLUE, ILI9341_WHITE, ILI9341_BLACK, "Password", 0, 0, FONT_BUTTON);
  ShowNumberPad.init(160, 120, 150, 50, ILI9341_NAVY, ILI9341_BLUE, ILI9341_WHITE, ILI9341_BLACK, "Number pad", 0, 0, FONT_BUTTON);
  ShowKeyboard.init(160, 190, 150, 50, ILI9341_NAVY, ILI9341_BLUE, ILI9341_WHITE, ILI9341_BLACK, "Keyboard", 0, 0, FONT_BUTTON);

  // initialize the numberpad object
  // let's simulate a password control (pure numbers only)
  PasswordInput.init(ILI9341_BLACK, ILI9341_WHITE, ILI9341_BLUE, ILI9341_NAVY, ILI9341_WHITE, ILI9341_CYAN, ILI9341_YELLOW, FONT_BUTTON);
  PasswordInput.hideInput();
  PasswordInput.enableDecimal(false);
  PasswordInput.enableNegative(false);
  PasswordInput.setInitialText("Enter password");

  // initialize the numberpad object
  // simulate a good old fashioned number input
  MyNumberPad.init(ILI9341_BLACK, ILI9341_WHITE, ILI9341_BLUE, ILI9341_NAVY, ILI9341_WHITE, ILI9341_CYAN, ILI9341_YELLOW, FONT_BUTTON);
  // optional methods
  // MyNumberPad.enableDecimal(bool State); // disable / enable decimal point (enabled by default)
  // MyNumberPad.enableNegative(bool State); // disable / enable negative sign (enabled by default)
  // MyNumberPad.setMinMax(float MininumValue, float MaximumValue); // want bound checks?
  // use the value property to set the initial value if desired
  MyNumberPad.value = 3.14159;

  // initialize the keyboard object
  // simulate a good old fashioned keyboard
  MyKeyboard.init(ILI9341_BLACK, ILI9341_WHITE, ILI9341_BLUE, ILI9341_NAVY, ILI9341_WHITE, ILI9341_CYAN, ILI9341_YELLOW, FONT_BUTTON);
  // optional methods
  // MyKeyboard.setDisplayColor(uint16_t TextColor, uint16_t BackColor); change colors
  // MyKeyboard.hideInput(); // for expanded password input
  // MyKeyboard.setInitialText(const char *Text); // maybe show and ip address format
  // MyKeyboard.setInitialText("IP 111.222.333.444");
  // optional to populate the input box
  // strcpy(MyKeyboard.data, "TEXT");

  drawMenu();

}

void drawMenu() {
  Display.fillScreen(ILI9341_BLACK);
  ShowPassword.draw();
  ShowNumberPad.draw();
  ShowKeyboard.draw();
  delay(500);
}

void loop() {

  if (Touch.touched()) {

    ProcessTouch();

    if (ProcessButtonPress(ShowPassword)) {
      Display.fillScreen(ILI9341_BLACK);
      PasswordInput.getInput();

      Display.fillScreen(ILI9341_BLACK);
      Display.setTextColor(ILI9341_WHITE, ILI9341_BLACK);
      Display.setCursor(40, 50);
      Display.print("PasswordInput.value is: ");
      Display.setCursor(40, 100);
      Display.print((uint32_t)PasswordInput.value);
      Display.setCursor(40, 200);
      Display.print("Pass screen to continue.");
      PasswordInput.value = 0;
      while (!Touch.touched()) {
      }
      drawMenu();
    }
    if (ProcessButtonPress(ShowNumberPad)) {
      Display.fillScreen(ILI9341_BLACK);
      MyNumberPad.getInput();

      Display.fillScreen(ILI9341_BLACK);
      Display.setTextColor(ILI9341_WHITE, ILI9341_BLACK);
      Display.setCursor(40, 50);
      Display.print("MyNumberPad.value is: ");
      Display.setCursor(40, 100);
      Display.print(MyNumberPad.value);
      Display.setCursor(40, 200);
      Display.print("Pass screen to continue.");
      MyNumberPad.value = 0;
      while (!Touch.touched()) {
      }
      drawMenu();
    }
    if (ProcessButtonPress(ShowKeyboard)) {
      Display.fillScreen(ILI9341_BLACK);
      MyKeyboard.getInput();

      Display.fillScreen(ILI9341_BLACK);
      Display.setTextColor(ILI9341_WHITE, ILI9341_BLACK);
      Display.setCursor(40, 50);
      Display.print("MyKeyboard.data is: ");
      Display.setCursor(40, 100);
      Display.print(MyKeyboard.data);
      Display.setCursor(40, 200);
      Display.print("Pass screen to continue.");

      MyKeyboard.data[0] = '\0';
      //strcpy(MyKeyboard.data, ' ');
      while (!Touch.touched()) {
      }
      drawMenu();
    }
  }
}

void ProcessTouch() {

  if (Touch.touched()) {
    p = Touch.getPoint();
    BtnX = p.x;
    BtnY = p.y;

#ifdef debug
    Serial.print(" real coordinates:");
    Serial.print(BtnX);
    Serial.print(" ,");
    Serial.print(BtnY);
#endif

    // different displays may require reversing last 2 args
    BtnX = map(p.x, 3975, 169, 0, 320);
    BtnY = map(p.y, 3850, 304, 0, 240);

#ifdef debug
    Serial.print(" , Mapped coordinates:");
    Serial.print(BtnX);
    Serial.print(" ,");
    Serial.println(BtnY);
    Display.fillCircle(BtnX, BtnY, 2, ILI9341_RED);
#endif
  }
}

bool ProcessButtonPress(Button TheButton) {

  if (TheButton.press(BtnX, BtnY)) {

    TheButton.draw(B_PRESSED);
    while (Touch.touched()) {
      if (TheButton.press(BtnX, BtnY)) {

        TheButton.draw(B_PRESSED);
      } else {
        TheButton.draw(B_RELEASED);
        return false;
      }
      ProcessTouch();
    }

    TheButton.draw(B_RELEASED);
    return true;
  }
  return false;
}
 
Thank you Kris. Got the Simple to show itself, no touch yet so more fiddling after a good night's sleep.

Running on a T3.5 dev board which has dual row header for display, one for XP2046, the other for Utouch so will dig in and get Utouch to talk to it then re-hash it for dynamic inits to hack into main project.
 
I used to use UTouch but stopped since it does not support Teensy 4.0. Do you need 2 touch drivers because of this lib? If so adding support so you can use this keypad lib with UTouch should be possible. Give me a day or so and I'll see if I can get UTouch working.
 
No rush. I'd settled on using Utouch because it's less noisy and more accurate than XP2046.
Ditched the idea of using Touch to manipulate Synth parameters like the whole purpose here is to put knobs on it. In reality this project really needs a T4 but V2 hardware and the means to build is out of reach atm.

Will play with it and figure how to implement it.
 
UTouch now supported. I have added a new .h and .cpp, there is an example on usage.

Note the rotation control for UTouch seems limited, so you may have to fondle the screen mapping code in the ProcessTouch() in the .cpp file.
 
Up and running, thank you.. Thinking that first use-case will be to edit 12 character Patch names, changed line 73 in ILI9431_t3_Keypad_Utouch.h to

Code:
#define MAX_KEYBOARD_CHARS 12
Kbd.jpg

The string of asterisks appear when you type more than MAX_KEYBOARD_CHARS. Then hit Done and code locks up.

Does not happen in Number pad.

Small teething issue otherwise looks pretty interesting.

Couple of thoughts:-
Visible cursor attached to left and right buttons. Ok space is tight, maybe Done can shrink to fit right of M. Leave top row where it is, yank out Cancel and drop the keyboard proper one row then there's a whole row 2 to play with or some such.
 
Back
Top