#include <stdio.h>
#include <inttypes.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_chip_info.h"
#include "esp_flash.h"
#include "esp_system.h"
#include "esp_log.h"
#include "driver/gpio.h"
#include "esp_mac.h"
#include <esp_timer.h> // Include for time measurements
#include <Adafruit_GFX.h> // Core graphics library
#include <Adafruit_ILI9341.h> // Display library
#define TFT_DC 2
#define TFT_CS 15
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);
#define WEATHER_BUTTON_PIN GPIO_NUM_5
#define HOME_BUTTON_PIN GPIO_NUM_17
#define LCD_CS 15
#define LCD_DC 2
#define LCD_RST 4
#define BACKGROUND_COLOR tft.color565(28, 78, 128)
#define TIME_COLOR ILI9341_MAGENTA
#define WEATHER_COLOR ILI9341_YELLOW
#define TEXT_COLOR ILI9341_WHITE
#define TIME_BOX_COLOR ILI9341_BLUE
#define WEATHER_BOX_COLOR tft.color565(126, 144, 154)
#define ICON_COLOR ILI9341_WHITE
// Sample time and weather values
const char* weather = "Sunny";
int temp = 25; // Celsius
//global variables
SemaphoreHandle_t xButtonSemaphore;
// Function prototypes
void IRAM_ATTR handleWeatherButton(void* arg);
void IRAM_ATTR handleHomeButton(void* arg);
void timeTask(void *pvParameters);
void weatherTask(void *pvParameters);
static volatile int seconds = 0;
enum Mode { HOME_MODE, WEATHER_MODE };
volatile Mode currentMode = HOME_MODE;
// Timing variables
esp_timer_handle_t timer;
uint64_t start_time, end_time;
void setup()
{
xButtonSemaphore = xSemaphoreCreateBinary();
tft.begin();
tft.setRotation(1); // Adjust rotation according to your setup
tft.fillScreen(ILI9341_BLACK);
drawUI();
// Resetting the pins
gpio_reset_pin(HOME_BUTTON_PIN);
gpio_reset_pin(WEATHER_BUTTON_PIN);
// Setting each pin as input
gpio_set_direction(WEATHER_BUTTON_PIN, GPIO_MODE_INPUT);
gpio_set_direction(HOME_BUTTON_PIN, GPIO_MODE_INPUT);
// Configuring GPIO pins
gpio_config_t io_conf = {
.pin_bit_mask = ((1ULL << WEATHER_BUTTON_PIN) | ((1ULL << HOME_BUTTON_PIN))),
.mode = GPIO_MODE_INPUT,
.pull_up_en = GPIO_PULLUP_ENABLE,
.pull_down_en = GPIO_PULLDOWN_DISABLE,
.intr_type = GPIO_INTR_NEGEDGE
};
gpio_config(&io_conf);
// Install ISR service
gpio_install_isr_service(0);
// Attach interrupt handlers
gpio_isr_handler_add(WEATHER_BUTTON_PIN, handleWeatherButton, NULL);
gpio_isr_handler_add(HOME_BUTTON_PIN, handleHomeButton, NULL);
// Create the time display task
xTaskCreate(timeTask, "Time Task", 2048, NULL, 1, NULL);
xTaskCreate(weatherTask, "Weather Task", 2048, NULL, 1, NULL);
xTaskCreate(updateDisplay, "Display Task", 2048, NULL, 1, NULL);
}
// Interrupt handler for the weather button
// Interrupt handler for the weather button
void IRAM_ATTR handleWeatherButton(void* arg) {
BaseType_t xHigherPriorityTaskWoken = pdFALSE; // Variable to track if a higher-priority task is woken
if (xSemaphoreGiveFromISR(xButtonSemaphore, &xHigherPriorityTaskWoken) == pdTRUE) {
currentMode = WEATHER_MODE;
}
// If a higher-priority task was woken, yield to it
if (xHigherPriorityTaskWoken == pdTRUE) {
portYIELD_FROM_ISR();
}
}
// Interrupt handler for the home button
void IRAM_ATTR handleHomeButton(void* arg) {
BaseType_t xHigherPriorityTaskWoken = pdFALSE; // Variable to track if a higher-priority task is woken
if (xSemaphoreGiveFromISR(xButtonSemaphore, &xHigherPriorityTaskWoken) == pdTRUE) {
currentMode = HOME_MODE;
}
// If a higher-priority task was woken, yield to it
if (xHigherPriorityTaskWoken == pdTRUE) {
portYIELD_FROM_ISR();
}
}
// Task to update the time on the home screen
void timeTask(void *pvParameters) {
while (1) {
start_time = esp_timer_get_time(); // Start time measurement
// Fetch current time (for demo purposes, we'll just use a counter)
seconds++;
// Delay 1 second for the next update
vTaskDelay(pdMS_TO_TICKS(1000));
end_time = esp_timer_get_time(); // End time measurement
}
}
void weatherTask(void *parameters){
while (1){
}
}
void updateDisplay(void *parameters) {
while (1) {
// Wait until a button press triggers the semaphore
if (xSemaphoreTake(xButtonSemaphore, portMAX_DELAY) == pdTRUE || currentMode == HOME_MODE) {
if (currentMode == HOME_MODE) {
drawTimeSection(); // Update time section
} else if (currentMode == WEATHER_MODE) {
drawWeatherSection(); // Update weather section
}
}
}
}
void drawUI() {
// Draw time section
drawTimeSection();
// Draw weather section
drawWeatherSection();
}
void drawTimeSection() {
// Draw rounded rectangle for time
tft.fillRoundRect(10, 10, tft.width() - 20, 100, 10, TIME_BOX_COLOR);
tft.drawRoundRect(10, 10, tft.width() - 20, 100, 10, ILI9341_WHITE);
// Draw clock icon (simple clock face)
tft.fillCircle(50, 60, 20, ICON_COLOR); // Moved right
tft.fillRect(48, 45, 4, 15, BACKGROUND_COLOR); // Hour hand
tft.fillRect(55, 55, 15, 4, BACKGROUND_COLOR); // Minute hand
// Display time (HH:MM)
tft.setTextColor(TEXT_COLOR);
tft.setTextSize(4);
tft.setCursor(120, 40);
tft.printf("%02d:%02d", seconds / 60, seconds % 60);
}
void drawWeatherSection() {
// Draw rounded rectangle for weather
tft.fillRoundRect(10, 130, tft.width() - 20, 100, 10, WEATHER_BOX_COLOR);
tft.drawRoundRect(10, 130, tft.width() - 20, 100, 10, ILI9341_WHITE);
// Draw a sun icon for weather
tft.fillCircle(50, 180, 20, ICON_COLOR); // Moved right
for (int i = 0; i < 360; i += 45) {
float rad = i * DEG_TO_RAD;
int x1 = 50 + cos(rad) * 25; // Adjusted to match new position
int x2 = 50 + cos(rad) * 35; // Adjusted to match new position
int y1 = 180 + sin(rad) * 25;
int y2 = 180 + sin(rad) * 35;
tft.drawLine(x1, y1, x2, y2, ICON_COLOR);
}
// Display weather description
tft.setTextColor(TEXT_COLOR);
tft.setTextSize(3);
tft.setCursor(120, 150);
tft.print("Weather:");
// Display temperature
tft.setTextSize(2);
tft.setCursor(120, 190);
tft.printf("%dC - %s", temp, weather);
}
void loop(){
}