#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Keypad.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>
#include <Adafruit_FT6206.h>
#define TFT_CS 10
#define TFT_DC A2
#define TFT_RST A3
#define LED_GRN A0
#define LED_RED A1
const byte ROWS = 4;
const byte COLS = 4;
char keys[ROWS][COLS] = {{'1','2','3','A'},{'4','5','6','B'},{'7','8','9','C'},{'*','0','#','D'}};
byte rowPins[ROWS] = {9, 8, 7, 6};
byte colPins[COLS] = {5, 4, 3, 2};
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
LiquidCrystal_I2C lcd(0x27, 16, 2);
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);
Adafruit_FT6206 ctp = Adafruit_FT6206();
enum State { MERCHANT_ENTRY, ID_PHASE, ACCOUNT_SEL, PIN_PHASE };
State currentState = MERCHANT_ENTRY;
// --- MULTI-USER DATA ---
int currentUser = 0;
String userNames[] = {"Tapish Chahera", "Simran Chawla"};
String userBanks[2][5] = {
{"SBI 4894", "PNB 7930", "HDFC 4689", "ICICI 1122", "AXIS 9901"},
{"KOTAK 2210", "INDUS 5543", "YES 9090", "BOB 3321", "UCO 1199"}
};
const int totalBanks = 5;
int scrollIndex = 0;
String amount = "";
String selectedBank = "";
int pinTaps = 0;
int failMode = 0;
float totalSales = 0;
bool sosActive = false;
unsigned long lastTouch = 0;
void setup() {
pinMode(LED_GRN, OUTPUT);
pinMode(LED_RED, OUTPUT);
lcd.init(); lcd.backlight();
tft.begin(); tft.setRotation(0);
// FIX: Lower threshold from 40 to 10 for "Feather Touch" sensitivity
ctp.begin(10);
resetSystem();
}
void resetSystem() {
currentState = MERCHANT_ENTRY;
amount = ""; pinTaps = 0; failMode = 0; selectedBank = ""; scrollIndex = 0;
sosActive = false;
digitalWrite(LED_GRN, LOW); digitalWrite(LED_RED, LOW);
lcd.clear();
lcd.print("Enter Amount:");
lcd.setCursor(0, 1); lcd.print("Rs. ");
// IDLE STATE: Dark Grey Outline
tft.fillScreen(ILI9341_BLACK);
tft.drawEllipse(120, 160, 50, 80, 0x5AEB); // Static Outline
tft.drawEllipse(120, 160, 49, 79, 0x5AEB); // Thicker line
}
// --- OPTIMIZED ANIMATION FUNCTION ---
void scanFingerEffect(uint16_t color) {
// Loop from center to outside
for (int r = 0; r <= 50; r+=3) { // Step by 3 for faster animation
// Use Integer Math (r * 1.6 is roughly r * 8 / 5)
int ry = (r * 8) / 5;
// Draw concentric ovals
tft.drawEllipse(120, 160, r, ry, color);
tft.drawEllipse(120, 160, r+1, ry+1, color); // Double line for fill density
}
}
void updateBankList() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(String(scrollIndex + 1) + "." + userBanks[currentUser][scrollIndex]);
if (scrollIndex + 1 < totalBanks) {
lcd.setCursor(0, 1);
lcd.print(String(scrollIndex + 2) + "." + userBanks[currentUser][scrollIndex + 1]);
}
}
void loop() {
// 1. Handle Keypad Inputs
KeyState kstate = keypad.getState();
char key = keypad.getKey();
if (kstate == HOLD) {
char lastKey = keypad.key[0].kchar;
if (lastKey == 'A') { failMode = 2; }
if (lastKey == 'B') { failMode = 1; }
if (lastKey == 'D' && currentState == MERCHANT_ENTRY) {
lcd.clear(); lcd.print("TOTAL SALES:");
lcd.setCursor(0,1); lcd.print("Rs. " + String(totalSales, 2));
delay(3000); resetSystem();
}
}
if (key == '*') sosActive = true;
if (key == 'B' && currentState == MERCHANT_ENTRY) currentUser = !currentUser;
if (currentState == MERCHANT_ENTRY) {
if (key >= '0' && key <= '9') {
amount += key;
lcd.setCursor(4, 1); lcd.print(amount);
}
else if (key == 'A') {
amount = "";
lcd.setCursor(4, 1); lcd.print(" ");
}
else if (key == '#') {
if (amount.toFloat() > 2000) {
lcd.clear(); lcd.print("LIMIT EXCEEDED!");
lcd.setCursor(0,1); lcd.print("Max Rs. 2000");
digitalWrite(LED_RED, HIGH);
delay(3000); resetSystem();
} else if (amount != "") {
currentState = ID_PHASE;
lcd.clear(); lcd.print("Place Finger on");
lcd.setCursor(0, 1); lcd.print("Scanner...");
tft.fillScreen(ILI9341_BLACK);
tft.drawEllipse(120, 160, 50, 80, ILI9341_CYAN);
tft.drawEllipse(120, 160, 49, 79, ILI9341_CYAN);
}
}
}
else if (currentState == ACCOUNT_SEL) {
if (key == 'D' && scrollIndex < totalBanks - 2) { scrollIndex++; updateBankList(); }
if (key == 'C' && scrollIndex > 0) { scrollIndex--; updateBankList(); }
if (key >= '1' && key <= '9') {
int choice = (key - '0') - 1;
if (choice < totalBanks) {
selectedBank = userBanks[currentUser][choice];
currentState = PIN_PHASE;
lcd.clear(); lcd.print("Selected: " + selectedBank.substring(0,6));
lcd.setCursor(0, 1); lcd.print("Tap Pattern Now");
tft.fillScreen(ILI9341_BLACK);
tft.drawEllipse(120, 160, 50, 80, ILI9341_YELLOW);
tft.drawEllipse(120, 160, 49, 79, ILI9341_YELLOW);
}
}
}
// --- 2. FIXED TOUCH LOGIC ---
if (ctp.touched()) {
// CRITICAL FIX: Always retrieve the point to clear the interrupt/register
TS_Point p = ctp.getPoint();
// Only process if enough time has passed (Debounce)
if (millis() - lastTouch > 250) { // Fast 250ms debounce
lastTouch = millis();
// LOGIC: Check state
if (currentState == ID_PHASE) {
scanFingerEffect(ILI9341_CYAN);
if (failMode == 2) {
lcd.clear(); lcd.print("ACCESS DENIED");
lcd.setCursor(0,1); lcd.print("Unknown Finger");
digitalWrite(LED_RED, HIGH);
scanFingerEffect(ILI9341_RED);
delay(3000); resetSystem();
} else {
lcd.clear(); lcd.print("WELCOME:");
lcd.setCursor(0, 1); lcd.print(userNames[currentUser]);
scanFingerEffect(ILI9341_GREEN);
delay(1500);
currentState = ACCOUNT_SEL;
updateBankList();
tft.fillScreen(ILI9341_BLACK);
tft.drawEllipse(120, 160, 50, 80, ILI9341_WHITE);
}
}
else if (currentState == PIN_PHASE) {
pinTaps++;
if (pinTaps == 1) { lcd.setCursor(0, 1); lcd.print(" "); }
lcd.setCursor(0, 1); lcd.print("PIN: ");
for(int i=0; i<pinTaps; i++) lcd.print("*");
scanFingerEffect(ILI9341_WHITE);
tft.fillScreen(ILI9341_BLACK);
tft.drawEllipse(120, 160, 50, 80, ILI9341_YELLOW);
if (pinTaps == 4) {
lcd.clear();
if (failMode == 1) {
lcd.print("TXN FAILED");
lcd.setCursor(0,1); lcd.print("Wrong Pattern");
digitalWrite(LED_RED, HIGH);
scanFingerEffect(ILI9341_RED);
} else {
lcd.print("PAYMENT SUCCESS");
totalSales += amount.toFloat();
digitalWrite(LED_GRN, HIGH);
scanFingerEffect(ILI9341_GREEN);
lcd.setCursor(0,1);
if (sosActive) lcd.print("SOS ALERT SENT!");
else lcd.print("Ref: " + String(random(1000,9999)));
}
delay(4000); resetSystem();
}
}
}
}
}Loading
ili9341-cap-touch
ili9341-cap-touch