#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>
#include <Adafruit_FT6206.h>
#include <Keypad.h>
#include <WiFi.h>
// TFT display pins
#define TFT_CS 5
#define TFT_DC 2
#define TFT_RST 4
#define TFT_MOSI 23
#define TFT_CLK 18
#define TFT_MISO 19
// I2C pins for ESP32
#define SDA_PIN 21
#define SCL_PIN 22
// Screen dimensions
#define TFT_WIDTH 320
#define TFT_HEIGHT 240
// Keypad configuration
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] = {32, 33, 25, 26};
byte colPins[COLS] = {27, 14, 12, 13};
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
// Menu configuration
const int MENU_ROWS = 2;
const int MENU_COLS = 3;
const int BOX_PADDING = 10; // Padding around each box
const int BOX_WIDTH = (TFT_WIDTH / MENU_COLS) - BOX_PADDING * 2;
const int BOX_HEIGHT = (TFT_HEIGHT / MENU_ROWS) - BOX_PADDING * 2;
char boxes[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I'};
int currentMenuStart = 0;
int selectedBoxIndex = -1; // Start with no selection
bool isBoxSelected = false;
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);
Adafruit_FT6206 ts = Adafruit_FT6206();
// Coordinates for the refresh button
#define REFRESH_BUTTON_X 10
#define REFRESH_BUTTON_Y 200
#define REFRESH_BUTTON_W 100
#define REFRESH_BUTTON_H 30
// Coordinates for navigation buttons
#define BUTTON_SIZE 60
#define BUTTON_PADDING 20
#define UP_BUTTON_X (TFT_WIDTH / 2 - BUTTON_SIZE / 2)
#define UP_BUTTON_Y (TFT_HEIGHT / 2 - BUTTON_SIZE - BUTTON_PADDING)
#define DOWN_BUTTON_X (TFT_WIDTH / 2 - BUTTON_SIZE / 2)
#define DOWN_BUTTON_Y (TFT_HEIGHT / 2 + BUTTON_PADDING)
#define LEFT_BUTTON_X (TFT_WIDTH / 2 - BUTTON_SIZE - BUTTON_PADDING)
#define LEFT_BUTTON_Y (TFT_HEIGHT / 2 - BUTTON_SIZE / 2)
#define RIGHT_BUTTON_X (TFT_WIDTH / 2 + BUTTON_PADDING)
#define RIGHT_BUTTON_Y (TFT_HEIGHT / 2 - BUTTON_SIZE / 2)
// Typing mode and buffer
bool isCapital = false;
String typedText = "";
void setup() {
Serial.begin(115200);
// Initialize the TFT display
tft.begin();
tft.setRotation(1);
tft.fillScreen(ILI9341_BLACK);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
Wire.begin();
// Initialize the touch screen
if (!ts.begin(40)) {
Serial.println("Unable to start touchscreen.");
while (1);
}
// Display the initial menu
displayMenu();
}
void loop() {
if (ts.touched()) {
TS_Point p = ts.getPoint();
// Scale from 0->240 or 0->320 depending on rotation
p.x = map(p.x, 0, 240, 240, 0);
if (!isBoxSelected) {
handleMenuTouch(p.x, p.y); // Handle touch in menu
} else {
handleSelectedBoxTouch(p.x, p.y); // Handle touch on selected box
}
delay(200); // Debounce delay
}
// Handle keypad input when in typing mode
if (selectedBoxIndex == 1) {
char key = keypad.getKey();
if (key) {
handleKeypadInput(key);
}
}
}
void displayMenu() {
tft.fillScreen(ILI9341_BLACK);
int index = 0;
for (int row = 0; row < MENU_ROWS; row++) {
for (int col = 0; col < MENU_COLS; col++) {
if (currentMenuStart + index < sizeof(boxes)) {
int x = col * (BOX_WIDTH + BOX_PADDING * 2) + BOX_PADDING;
int y = row * (BOX_HEIGHT + BOX_PADDING * 2) + BOX_PADDING;
tft.fillRect(x, y, BOX_WIDTH, BOX_HEIGHT, ILI9341_BLUE);
tft.setCursor(x + BOX_WIDTH / 2 - 10, y + BOX_HEIGHT / 2 - 10);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(3);
tft.print(boxes[currentMenuStart + index]);
index++;
}
}
}
}
void handleMenuTouch(int x, int y) {
// Calculate column and row indices without adjusting for padding
int col = y / (BOX_WIDTH + BOX_PADDING);
int row = x / (BOX_HEIGHT + BOX_PADDING);
// Calculate the index of the selected box
int index = currentMenuStart + (row * MENU_COLS + col);
// Check if the index is valid and within the bounds of the menu items
if (index >= 0 && index < sizeof(boxes) && currentMenuStart + index < sizeof(boxes)) {
selectedBoxIndex = index;
selectBox();
}
}
void handleSelectedBoxTouch(int x, int y) {
if (isWithinButton(x, y)) {
scanAndIdentifyI2CDevices();
} else if (selectedBoxIndex == 2 && isWithinNavButton(x, y)) {
handleNavButtonTouch(x, y);
} else {
backToMenu();
}
}
bool isWithinButton(int x, int y) {
return (x >= REFRESH_BUTTON_X && x <= REFRESH_BUTTON_X + REFRESH_BUTTON_W &&
y >= REFRESH_BUTTON_Y && y <= REFRESH_BUTTON_Y + REFRESH_BUTTON_H);
}
bool isWithinNavButton(int x, int y) {
return (x >= UP_BUTTON_X && x <= UP_BUTTON_X + BUTTON_SIZE && y >= UP_BUTTON_Y && y <= UP_BUTTON_Y + BUTTON_SIZE) ||
(x >= DOWN_BUTTON_X && x <= DOWN_BUTTON_X + BUTTON_SIZE && y >= DOWN_BUTTON_Y && y <= DOWN_BUTTON_Y + BUTTON_SIZE) ||
(x >= LEFT_BUTTON_X && x <= LEFT_BUTTON_X + BUTTON_SIZE && y >= LEFT_BUTTON_Y && y <= LEFT_BUTTON_Y + BUTTON_SIZE) ||
(x >= RIGHT_BUTTON_X && x <= RIGHT_BUTTON_X + BUTTON_SIZE && y >= RIGHT_BUTTON_Y && y <= RIGHT_BUTTON_Y + BUTTON_SIZE);
}
void drawRefreshButton() {
tft.fillRect(REFRESH_BUTTON_X, REFRESH_BUTTON_Y, REFRESH_BUTTON_W, REFRESH_BUTTON_H, ILI9341_BLUE);
tft.setCursor(REFRESH_BUTTON_X + 10, REFRESH_BUTTON_Y + 7);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
tft.print("Refresh");
}
void drawNavButtons() {
tft.fillRect(UP_BUTTON_X, UP_BUTTON_Y, BUTTON_SIZE, BUTTON_SIZE, ILI9341_GREEN);
tft.fillRect(DOWN_BUTTON_X, DOWN_BUTTON_Y, BUTTON_SIZE, BUTTON_SIZE, ILI9341_GREEN);
tft.fillRect(LEFT_BUTTON_X, LEFT_BUTTON_Y, BUTTON_SIZE, BUTTON_SIZE, ILI9341_GREEN);
tft.fillRect(RIGHT_BUTTON_X, RIGHT_BUTTON_Y, BUTTON_SIZE, BUTTON_SIZE, ILI9341_GREEN);
tft.setCursor(UP_BUTTON_X + 20, UP_BUTTON_Y + 20);
tft.print("^");
tft.setCursor(DOWN_BUTTON_X + 20, DOWN_BUTTON_Y + 20);
tft.print("v");
tft.setCursor(LEFT_BUTTON_X + 20, LEFT_BUTTON_Y + 20);
tft.print("<");
tft.setCursor(RIGHT_BUTTON_X + 20, RIGHT_BUTTON_Y + 20);
tft.print(">");
}
void selectBox() {
if (selectedBoxIndex == 0) {
scanAndIdentifyI2CDevices();
} else if (selectedBoxIndex == 1) {
displayKeypadInterface();
} else if (selectedBoxIndex == 2) {
displayNavButtons();
}
}
void backToMenu() {
selectedBoxIndex = -1; // Reset selection
isBoxSelected = false;
displayMenu();
}
void displayNavButtons() {
tft.fillScreen(ILI9341_BLACK);
drawNavButtons();
isBoxSelected = true;
}
void displayKeypadInterface() {
// Clear the screen and display the Wi-Fi names
tft.fillScreen(ILI9341_BLACK);
tft.setCursor(10, 10);
tft.setTextSize(2);
tft.print("Wi-Fi Networks:");
int n = WiFi.scanNetworks();
if (n == 0) {
tft.setCursor(10, 50);
tft.print("No networks found");
} else {
for (int i = 0; i < n; ++i) {
tft.setCursor(10, 50 + i * 20);
tft.print(WiFi.SSID(i));
delay(10);
}
}
// Draw the text input box
tft.drawRect(10, 140, 300, 50, ILI9341_WHITE);
tft.setCursor(15, 155);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
tft.print(typedText);
isBoxSelected = true;
}
void handleKeypadInput(char key) {
if (key == '*') {
// Backspace
if (typedText.length() > 0) {
typedText.remove(typedText.length() - 1);
}
} else if (key == '#') {
// Clear the screen
typedText = "";
} else if (key == '0') {
// Space
typedText += " ";
} else if (key == '1') {
// Change mode (capital/small letters)
isCapital = !isCapital;
} else {
// Handle character input
char charToAdd = getCharForKey(key);
if (charToAdd != '\0') {
typedText += charToAdd;
}
}
// Update the display
tft.fillRect(15, 155, 300, 30, ILI9341_BLACK); // Clear the previous text
tft.setCursor(15, 155);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
tft.print(typedText);
}
char getCharForKey(char key) {
static unsigned long lastKeyPressTime = 0;
static char lastKeyPressed = '\0';
static int charIndex = 0;
unsigned long currentTime = millis();
char charToReturn = '\0';
if (key != lastKeyPressed || currentTime - lastKeyPressTime > 1000) {
lastKeyPressed = key;
charIndex = 0;
} else {
charIndex = (charIndex + 1) % 4;
}
lastKeyPressTime = currentTime;
switch (key) {
case '2':
charToReturn = isCapital ? "ABC2"[charIndex] : "abc2"[charIndex];
break;
case '3':
charToReturn = isCapital ? "DEF3"[charIndex] : "def3"[charIndex];
break;
case '4':
charToReturn = isCapital ? "GHI4"[charIndex] : "ghi4"[charIndex];
break;
case '5':
charToReturn = isCapital ? "JKL5"[charIndex] : "jkl5"[charIndex];
break;
case '6':
charToReturn = isCapital ? "MNO6"[charIndex] : "mno6"[charIndex];
break;
case '7':
charToReturn = isCapital ? "PQRS7"[charIndex] : "pqrs7"[charIndex];
break;
case '8':
charToReturn = isCapital ? "TUV8"[charIndex] : "tuv8"[charIndex];
break;
case '9':
charToReturn = isCapital ? "WXYZ9"[charIndex] : "wxyz9"[charIndex];
break;
default:
charToReturn = key;
break;
}
return charToReturn;
}
void handleNavButtonTouch(int x, int y) {
if (x >= UP_BUTTON_X && x <= UP_BUTTON_X + BUTTON_SIZE && y >= UP_BUTTON_Y && y <= UP_BUTTON_Y + BUTTON_SIZE) {
Serial.println("Up button pressed");
// Handle up button action
} else if (x >= DOWN_BUTTON_X && x <= DOWN_BUTTON_X + BUTTON_SIZE && y >= DOWN_BUTTON_Y && y <= DOWN_BUTTON_Y + BUTTON_SIZE) {
Serial.println("Down button pressed");
// Handle down button action
} else if (x >= LEFT_BUTTON_X && x <= LEFT_BUTTON_X + BUTTON_SIZE && y >= LEFT_BUTTON_Y && y <= LEFT_BUTTON_Y + BUTTON_SIZE) {
Serial.println("Left button pressed");
// Handle left button action
} else if (x >= RIGHT_BUTTON_X && x <= RIGHT_BUTTON_X + BUTTON_SIZE && y >= RIGHT_BUTTON_Y && y <= RIGHT_BUTTON_Y + BUTTON_SIZE) {
Serial.println("Right button pressed");
// Handle right button action
}
}
void scanAndIdentifyI2CDevices() {
byte error, address;
int deviceCount = 0;
// Clear the screen and prepare for display
tft.fillScreen(ILI9341_BLACK);
tft.setCursor(10, 10);
tft.setTextSize(3);
tft.print("Scanning I2C bus...");
delay(1000); // Delay for visibility
tft.fillScreen(ILI9341_BLACK);
// Known I2C addresses for specific devices
struct Device {
uint8_t address;
const char *name;
};
Device devices[] = {
{0x3C, "OLED Display"}, // OLED display
{0x27, "LCD Display"}, // LCD display with PCF8574 I/O expander
{0x50, "EEPROM (AT24C32)"}, // EEPROM memory
{0x68, "RTC Module"}, // RTC module
{0x76, "Barometric Sensor"}, // Barometric pressure sensor
{0x40, "Temperature Sensor"}, // Temperature sensor
{0x41, "Digital Potentiometer"},// Digital potentiometer
{0x48, "ADC (ADS1115)"}, // ADC (Analog-to-Digital Converter)
{0x60, "Accelerometer"}, // Accelerometer
{0x61, "Gyroscope"}, // Gyroscope
{0x68, "IMU (MPU6050)"}, // Inertial Measurement Unit
{0x70, "EEPROM (24AA02)"}, // EEPROM memory
{0x71, "IO Expander (MCP23017)"},// I/O Expander
{0x72, "IO Expander (MCP23008)"},// I/O Expander
{0x76, "Pressure Sensor (MS5611)"},// Pressure sensor
{0x77, "Pressure Sensor (BMP180)"},// Pressure sensor
{0x38, "TFT Display"},
{0x08, "Accelerometer (ADXL345)"}, // Accelerometer
{0x0C, "Gyroscope (L3GD20)"}, // Gyroscope
{0x18, "Temperature/Humidity Sensor (HTU21D)"}, // Temperature and Humidity Sensor
{0x1E, "Compass (HMC5883L)"}, // Magnetometer/Compass
{0x21, "Color Sensor (TCS34725)"}, // Color sensor
{0x23, "Lux Meter (TSL2561)"}, // Light sensor (Lux meter)
{0x29, "Ambient Light Sensor (LTR-559)"}, // Ambient light sensor
{0x39, "Ambient Light Sensor (VEML7700)"},// Ambient light sensor
{0x48, "ADC (ADS1115)"}, // Analog-to-Digital Converter
{0x50, "EEPROM (AT24C32)"}, // EEPROM memory
{0x57, "Proximity Sensor (VL6180X)"}, // Proximity sensor
{0x60, "Pressure Sensor (MS5611)"}, // Barometric pressure sensor
{0x68, "RTC Module (DS3231)"}, // Real-Time Clock module
{0x76, "Barometric Sensor (BMP280)"}, // Barometric pressure sensor
{0x77, "Pressure Sensor (BMP180)"}, // Pressure sensor
{0x78, "EEPROM (24AA02)"}, // EEPROM memory
{0x7A, "Temperature Sensor (TMP102)"}, // Temperature sensor
{0x7F, "IO Expander (PCF8574)"}, // I/O Expander
// Add more devices as needed
};
for (address = 1; address < 127; address++) {
Wire.beginTransmission(address);
error = Wire.endTransmission();
if (error == 0) {
// Device found, print address and name to TFT display
tft.setCursor(10, 10);
tft.setTextSize(3);
tft.print("Device Found");
tft.setCursor(10, 50 + deviceCount * 20);
tft.setTextSize(2);
tft.setTextColor(ILI9341_CYAN);
tft.print("0x");
if (address < 16) {
tft.print("0");
}
tft.print(address, HEX);
// Check if the found address matches known devices
bool identified = false;
for (int i = 0; i < sizeof(devices) / sizeof(devices[0]); i++) {
if (address == devices[i].address) {
tft.print(" - ");
tft.print(devices[i].name);
identified = true;
break;
}
}
if (!identified) {
tft.print(" - Unknown Device");
}
deviceCount++;
delay(500);
}
}
}