//Hardware: keypad touch tft 320x240 adafruit feather 2.4" and teensy 3.2 feather adapter
#include "Adafruit_GFX.h"
#include "Adafruit_ILI9341.h"
#include <Adafruit_STMPE610.h>
#include <EEPROM.h>
#if defined (__AVR_ATmega32U4__) || defined(ARDUINO_SAMD_FEATHER_M0) || defined (__AVR_ATmega328P__) || \
defined(ARDUINO_SAMD_ZERO) || defined(__SAMD51__) || defined(__SAM3X8E__) || defined(ARDUINO_NRF52840_FEATHER)
#define STMPE_CS 6
#define TFT_CS 9
#define TFT_DC 10
#define SD_CS 5
#endif
#ifdef TEENSYDUINO
#define TFT_DC 10
#define TFT_CS 4
#define STMPE_CS 3
#define SD_CS 8
#endif
// Use hardware SPI (on Uno, #13, #12, #11) and the above for CS/DC
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);
// The STMPE610 uses hardware SPI on the shield,
Adafruit_STMPE610 ts = Adafruit_STMPE610(STMPE_CS);
// This is calibration data for the raw touch data to the screen coordinates 320x240 feather
#define TS_MINX 150
#define TS_MINY 130
#define TS_MAXX 3800
#define TS_MAXY 3750
/******************* UI details */
#define BUTTON_X 40
#define BUTTON_Y 100
#define BUTTON_W 60
#define BUTTON_H 30
#define BUTTON_SPACING_X 20
#define BUTTON_SPACING_Y 20
#define BUTTON_TEXTSIZE 2
// text box where numbers go
#define TEXT_X 10
#define TEXT_Y 10
#define TEXT_W 220
#define TEXT_H 50
#define TEXT_TSIZE 3
#define TEXT_TCOLOR ILI9341_MAGENTA
// the data (code #) we store in the textfield
#define TEXT_LEN 12
char textfield[TEXT_LEN + 1] = "";
uint8_t textfield_i = 0;
//int tempPin = 0; //the ADC pin
//int printPin = 2; //the print button pin
//int erasePin = 1; //the erase button pin
int address = 0; //EEPROM address counter
void printTextfield();
void clearEEPROM();
void writeTextfield();
float conv_coeff = 0.0; //coefficient for converting from 0-1024 to 0-5 range
// status txt line
#define STATUS_X 10
#define STATUS_Y 65
#define STATUS_BOOT_X 18
#define STATUS_BOOT_Y 25
/* create 15 buttons, in classic candybar phone style */
char buttonlabels[15][5] = {"ENTR", "CLR1", "VOID", "1", "2", "3", "4", "5", "6", "7", "8", "9", "*", "0", "#" };
uint16_t buttoncolors[15] = {ILI9341_DARKGREEN, ILI9341_RED, ILI9341_RED,
ILI9341_BLUE, ILI9341_BLUE, ILI9341_BLUE,
ILI9341_BLUE, ILI9341_BLUE, ILI9341_BLUE,
ILI9341_BLUE, ILI9341_BLUE, ILI9341_BLUE,
ILI9341_DARKGREY, ILI9341_BLUE, ILI9341_DARKGREY
};
Adafruit_GFX_Button buttons[15];
// Print something in the mini status bar with either flashstring
void status(const __FlashStringHelper *msg) {
tft.fillRect(STATUS_X, STATUS_Y, 240, 8, ILI9341_BLACK);
tft.setCursor(STATUS_X, STATUS_Y);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(1);
tft.print(msg);
}
// or charstring
void status(char *msg) {
tft.fillRect(STATUS_X, STATUS_Y, 240, 8, ILI9341_BLACK);
tft.setCursor(STATUS_X, STATUS_Y);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(1);
tft.print(msg);
}
void statusBoot(const __FlashStringHelper *msg) {
tft.fillRect(STATUS_BOOT_X, STATUS_BOOT_Y, 205, 20, ILI9341_BLACK);
tft.setCursor(STATUS_BOOT_X, STATUS_BOOT_Y);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
tft.print(msg);
}
void statusBoot(char *msg) {
tft.fillRect( STATUS_BOOT_X, STATUS_BOOT_Y, 205, 20, ILI9341_BLACK);
tft.setCursor(STATUS_BOOT_X, STATUS_BOOT_Y);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
tft.print(msg);
}
String password = "0000"; //Variable to store the current password
String tempPassword = ""; //Variable to store the input password
//int doublecheck; //Check twice the new passoword
//boolean armed = false; //Variable for system state (armed:true / unarmed:false)
//boolean input_pass; //Variable for input password (correct:true / wrong:false)
//boolean storedPassword = true;
//boolean changedPassword = false;
//boolean checkPassword = false;
//int i = 1; //variable to index an array
void setup() {
Serial.begin(115200);
Serial.println("KEYPADLOCK");
// clear the screen
tft.begin();
//tft.setRotation(0);
tft.fillScreen(ILI9341_BLACK);
// eep touchscreen not found?
if (!ts.begin()) {
Serial.println("Couldn't start touchscreen controller");
while (1);
}
Serial.println("Touchscreen started");
// create buttons
for (uint8_t row = 0; row < 5; row++) {
for (uint8_t col = 0; col < 3; col++) {
buttons[col + row * 3].initButton(&tft, BUTTON_X + col * (BUTTON_W + BUTTON_SPACING_X),
BUTTON_Y + row * (BUTTON_H + BUTTON_SPACING_Y), // x, y, w, h, outline, fill, text
BUTTON_W, BUTTON_H, ILI9341_WHITE, buttoncolors[col + row * 3], ILI9341_WHITE,
buttonlabels[col + row * 3], BUTTON_TEXTSIZE);
buttons[col + row * 3].drawButton();
}
}
// create 'text field'
tft.drawRect(TEXT_X, TEXT_Y, TEXT_W, TEXT_H, ILI9341_WHITE);
for (int i = 0; i < 5; i++) {
statusBoot(F("RESTRICTED ACCESS"));
delay(500);
clearText();
delay(100);
}
conv_coeff = 5.0 / 1024.0;
//conv_coeff = 1;//find the coefficient to do the conversion
}
void loop(void) {
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) {
p.x = map(p.x, TS_MINX, TS_MAXX, tft.width(), 0);
p.y = map(p.y, TS_MINY, TS_MAXY, 0, tft.height());
Serial.print("("); Serial.print(p.x); Serial.print(", ");
Serial.print(p.y); Serial.print(", ");
Serial.print(p.z); Serial.println(") ");
}
// go thru all the buttons, checking if they were pressed
for (uint8_t b = 0; b < 15; b++) {
if (buttons[b].contains(p.x, p.y)) {
//Serial.print("Pressing: "); Serial.println(b);
buttons[b].press(true); // tell the button it is pressed
} else {
buttons[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 < 15; b++) {
if (buttons[b].justReleased()) {
// Serial.print("Released: "); Serial.println(b);
buttons[b].drawButton(); // draw normal
}
if (buttons[b].justPressed()) {
clearText();
buttons[b].drawButton(true); // draw invert!
// if a numberpad button, append the relevant # to the textfield
if (b >= 3) {
if (textfield_i < TEXT_LEN) {
textfield[textfield_i] = buttonlabels[b][0];
textfield_i++;
textfield[textfield_i] = 0; // zero terminate
}
}
if (b == 12) {
clearEEPROM();
delay(2000);
}
if (b == 14) {
printTextfield();
delay(2000);
}
// clr button! delete char
if (b == 1) {
status(F("CLEARING LAST DIGIT..."));
textfield[textfield_i] = 0;
if ( textfield_i <= 0) {
textfield_i = 0;
}
else {
if (textfield > 0) {
textfield_i--;
textfield[textfield_i] = ' ';
}
}
}
// update the current text field
Serial.println(textfield);
tft.setCursor(TEXT_X + 2, TEXT_Y + 10);
tft.setTextColor(TEXT_TCOLOR, ILI9341_BLACK);
tft.setTextSize(TEXT_TSIZE);
tft.print(textfield);
//clear all characters
if ((b == 2) && (textfield > 0)) {
status(F("CLEARING FULL CODE..."));
for (int i = 0; i < 13 ; i++) {
if ( textfield_i <= 0) {
textfield_i = 0;
}
else {
textfield_i-- ;
textfield[textfield_i] = ' ';
}
}
}
// update the current text field
Serial.println(textfield);
tft.setCursor(TEXT_X + 2, TEXT_Y + 10);
tft.setTextColor(TEXT_TCOLOR, ILI9341_BLACK);
tft.setTextSize(TEXT_TSIZE);
tft.print(textfield);
// enter code for verification
if (b == 0) {
tempPassword = textfield;
if (tempPassword == password) {
status(F("ACCESS GRANTED..."));
Serial.print("ACCESS GRANTED CODE: "); Serial.print(textfield);
tft.setCursor(TEXT_X + 2, TEXT_Y + 10);
tft.setTextColor( ILI9341_BLUE, ILI9341_BLACK);
tft.setTextSize(TEXT_TSIZE);
tft.print(textfield);
writeTextfield();////eeprom
delay(250);
if (textfield > 0) {
for (int i = 0; i < 13 ; i++) {
if ( textfield_i <= 0) {
textfield_i = 0;
}
else {
textfield_i-- ;
textfield[textfield_i] = ' ';
}
}
}
Serial.print(textfield);
tft.setCursor(TEXT_X + 2, TEXT_Y + 10);
tft.setTextColor(TEXT_TCOLOR, ILI9341_BLACK);
tft.setTextSize(TEXT_TSIZE);
tft.print(textfield);
for (int i = 0; i < 5; i++) {
clearText();
delay(100);
statusBoot(F(" LIDAR ACTIVATED"));
delay(500);
}
}
else {
status(F("CONFIRMING CODE....ACCESS DENIED"));
Serial.print("CONFIRMING CODE....ACCESS DENIED");
delay(500);
//clear all characters
if (textfield > 0) {
status(F("CLEARING FULL CODE..."));
for (int i = 0; i < 13 ; i++) {
if ( textfield_i <= 0) {
textfield_i = 0;
}
else {
textfield_i-- ;
textfield[textfield_i] = ' ';
}
}
}
Serial.print(textfield);
tft.setCursor(TEXT_X + 2, TEXT_Y + 10);
tft.setTextColor(TEXT_TCOLOR, ILI9341_BLACK);
tft.setTextSize(TEXT_TSIZE);
tft.print(textfield);
}
}
delay(100); // UI debouncing
}
}
}
void clearText() {
tft.fillRect( STATUS_BOOT_X, STATUS_BOOT_Y, 205, 20, ILI9341_BLACK);
}
void printTextfield()
{
for (int i = 0 ; i < EEPROM.length() ; i++) {
byte value = EEPROM.read(i); //read EEPROM data at address i
if (value != 0) //skip "empty" addresses
{
float newCode = value;
Serial.println(newCode);
}
}
}
void clearEEPROM()
{
for (int i = 0 ; i < EEPROM.length() ; i++) {
if (EEPROM.read(i) != 0) //skip already "empty" addresses
{
EEPROM.write(i, 0); //write 0 to address i
}
}
Serial.println("EEPROM erased");
address = 0; //reset address counter
}
void writeTextfield()
{
byte value = textfield;//this is the key step, I know I can't just use 'textfield'
EEPROM.write(address, value);//write value to current address counter address, like string to int?
Serial.println();
Serial.print("Code value stored at address ");
Serial.print(address); Serial.print(": ");
Serial.println(value);
address++; //increment address counter
if (address == EEPROM.length()) //check if address counter has reached the end of EEPROM
{
address = 0; //if yes: reset address counter
}
}