]> Devi Nivas Git - smartwatch.git/commitdiff
Add button support
authorAdvaith Menon <noreply-git@bp4k.net>
Sat, 22 Nov 2025 22:36:15 +0000 (17:36 -0500)
committerAdvaith Menon <noreply-git@bp4k.net>
Sun, 23 Nov 2025 04:27:00 +0000 (23:27 -0500)
* Add button debouncing library
* Print out single click and double click
  via ESP-IDF

.gitignore
main/CMakeLists.txt
main/goldeloxSerial.c
main/goldeloxSerial.h
main/hello_world_main.c
main/idf_component.yml [new file with mode: 0644]
main/task_button.c [new file with mode: 0644]
main/task_button.h [new file with mode: 0644]
main/task_lcd.c
main/task_lcd.h

index ee59353c1c2d59aba96e5c3994259138ba58ce94..a43c2061ea00198654b60216af8deed2b8c9347d 100644 (file)
@@ -16,3 +16,5 @@ pytest_embedded_log/
 
 # idf-component-manager output
 dependencies.lock
+
+managed_components/
index e300e74f23f09a66ad101f215c4cb5b8b15a2bdc..80ac6566f59600376dacfd4571665b6bc9a812b6 100644 (file)
@@ -1,7 +1,7 @@
 idf_component_register(SRCS "hello_world_main.c"
                             "goldeloxSerial.c"
                             "task_lcd.c"
+                            "task_button.c"
                        INCLUDE_DIRS "."
                        PRIV_REQUIRES esp_driver_gpio
-                                     esp_driver_uart
-                       INCLUDE_DIRS "")
+                                     esp_driver_uart)
index d4d72874728c97dc3f4101460163b785bc7a23ab..79f8f7c7725cd7994dc7ee35f59ece1ebe42e3fe 100644 (file)
@@ -1302,3 +1302,26 @@ gl_err_t gl_init(gl_display_t *disp, gl_serif_t *serif) {
 //     return;
 // }
 
+void gl_reset2(gl_display_t *disp) {
+    int k, tSave;
+    unsigned char ch;
+    //gl_word_t    nBaud;
+
+    TimeLimit4D = 2000;
+
+    tSave = TimeLimit4D;
+    TimeLimit4D = 500;
+    for (k = 0 ; k < 10 ; k++)
+    {
+        ch = 'X';
+        disp->serif->write_tx((void *)&ch, 1);
+        disp->serif->flush_tx(TimeLimit4D);
+        if (ReadSerPort(disp->serif, &ch, 1) == -1)
+            break;
+        if (ch == 0x15)
+            break ;
+    }
+    TimeLimit4D = tSave;
+
+    disp->serif->flush_rx();
+}
index eb073af2e0defab674a81c58428a10107b8c5ae1..7407696b96cfdcedad54f123c93014990a046f3a 100644 (file)
@@ -232,6 +232,7 @@ gl_word_t gl_joystick(gl_display_t *display) ;
 gl_word_t gl_peekB(gl_display_t *display, gl_word_t  Address) ;
 gl_word_t gl_peekW(gl_display_t *display, gl_word_t  Address) ;
 
+void gl_reset2(gl_display_t *);
 
 
 
index a823780ea2fcf599809f41b587ff30dcdb28c3ed..eb152a49abdf5b440a3dc1388344b903a5b4bdb1 100644 (file)
@@ -13,6 +13,7 @@
 
 #include "pins.h"
 #include "task_lcd.h"
+#include "task_button.h"
 
 
 
@@ -47,6 +48,10 @@ void app_main(void)
 
     gpio_dump_io_configuration(stdout, (1ULL << PIN_VIBRATOR) | (1ULL << PIN_BUTTON_RED));
 
+    /* initialize the buttons */
+    gt_btn_setup();
+
+    /* start the main gui thread  which starts all else */
     lcd_task();
 
     /*
diff --git a/main/idf_component.yml b/main/idf_component.yml
new file mode 100644 (file)
index 0000000..45aceb1
--- /dev/null
@@ -0,0 +1,17 @@
+## IDF Component Manager Manifest File
+dependencies:
+  ## Required IDF version
+  idf:
+    version: '>=4.1.0'
+  # # Put list of dependencies here
+  # # For components maintained by Espressif:
+  # component: "~1.0.0"
+  # # For 3rd party components:
+  # username/component: ">=1.0.0,<2.0.0"
+  # username2/component2:
+  #   version: "~1.0.0"
+  #   # For transient dependencies `public` flag can be set.
+  #   # `public` flag doesn't have an effect dependencies of the `main` component.
+  #   # All dependencies of `main` are public by default.
+  #   public: true
+  espressif/button: '*'
diff --git a/main/task_button.c b/main/task_button.c
new file mode 100644 (file)
index 0000000..4d46c23
--- /dev/null
@@ -0,0 +1,90 @@
+#include "freertos/FreeRTOS.h"
+#include "iot_button.h"
+#include "button_gpio.h"
+#include "esp_log.h"
+
+#include "pins.h"
+
+#include "task_button.h"
+
+/* globals */
+
+extern QueueHandle_t gt_btnq;
+
+
+static struct gt_btn_msg_t btn_evts[10] = {
+    {GT_BTN_WHITE, BUTTON_SINGLE_CLICK},
+    {GT_BTN_WHITE, BUTTON_DOUBLE_CLICK},
+    {GT_BTN_GREEN, BUTTON_SINGLE_CLICK},
+    {GT_BTN_GREEN, BUTTON_DOUBLE_CLICK},
+    {GT_BTN_YELLOW, BUTTON_SINGLE_CLICK},
+    {GT_BTN_YELLOW, BUTTON_DOUBLE_CLICK},
+    {GT_BTN_BLUE, BUTTON_SINGLE_CLICK},
+    {GT_BTN_BLUE, BUTTON_DOUBLE_CLICK},
+    {GT_BTN_RED, BUTTON_SINGLE_CLICK},
+    {GT_BTN_RED, BUTTON_DOUBLE_CLICK},
+};
+
+
+static const char* TAG = "task_button";
+
+
+/* local fn definitions */
+
+
+static void button_all_cb(void *, void *);
+
+
+/* ========================================================================== */
+void gt_btn_setup(void) {
+    uint8_t i;
+
+    const button_config_t btn_cfg_all = {0};
+
+    const button_gpio_config_t btn_gpio_cfg[5] = {
+        {
+            .gpio_num = PIN_BUTTON_WHITE,
+            .active_level = 0
+        },
+        {
+            .gpio_num = PIN_BUTTON_GREEN,
+            .active_level = 0
+        },
+        {
+            .gpio_num = PIN_BUTTON_YELLOW,
+            .active_level = 0
+        },
+        {
+            .gpio_num = PIN_BUTTON_BLUE,
+            .active_level = 0
+        },
+        {
+            .gpio_num = PIN_BUTTON_RED,
+            .active_level = 0
+        }
+    };
+    button_handle_t gpio_btn[5] = {NULL, NULL, NULL, NULL, NULL};
+
+    /* create buttons */
+    for (i = 0; i < NUM_BUTTONS; ++i) {
+        ESP_ERROR_CHECK(iot_button_new_gpio_device(
+                    &btn_cfg_all, &btn_gpio_cfg[i], &gpio_btn[i]));
+    }
+
+
+    /* register callbacks */
+    for (i = 0; i < NUM_EVENTS; ++i) {
+        ESP_ERROR_CHECK(iot_button_register_cb(gpio_btn[btn_evts[i].btn],
+                    btn_evts[i].evt,
+                    NULL,
+                    &button_all_cb,
+                    &btn_evts[i]));
+    }
+}
+
+
+void button_all_cb(void *arg, void *user_data) {
+    struct gt_btn_msg_t *msg = (struct gt_btn_msg_t*) user_data;
+    ESP_LOGI(TAG, "Button pressed");
+    ESP_LOGI(TAG, "The selected event: %d; and event %d", msg->btn, msg->evt);
+}
diff --git a/main/task_button.h b/main/task_button.h
new file mode 100644 (file)
index 0000000..afb98ec
--- /dev/null
@@ -0,0 +1,37 @@
+/**
+ * @file task_button.h
+ * @brief Creates a queue to deal with button inputs.
+ */
+
+#pragma once
+
+#ifndef __TASK_BUTTON_H__
+#define __TASK_BUTTON_H__
+#include "freertos/FreeRTOS.h"
+#include "iot_button.h"
+
+#define NUM_BUTTONS 5
+#define NUM_EVENTS 10
+extern QueueHandle_t gt_btnq;
+
+
+enum gt_btn_t {
+    GT_BTN_WHITE = 0,
+    GT_BTN_GREEN,
+    GT_BTN_YELLOW,
+    GT_BTN_BLUE,
+    GT_BTN_RED
+};
+
+
+struct gt_btn_msg_t {
+    enum gt_btn_t btn;
+    button_event_t evt;
+};
+
+
+/**
+ * @brief Setup button interrupts.
+ */
+void gt_btn_setup(void);
+#endif
index 933bf8f784e0290b9a5fab08a9511d97b0c1529a..3d1cf1c30be55e27da955d8f70624753293d2dea 100644 (file)
@@ -7,11 +7,15 @@
 
 #include "Goldelox_const4D.h"
 #include "goldeloxSerial.h"
+#include "esp_system.h"
 
 #include "task_lcd.h"
 #include "pins.h"
 
 const uart_port_t uart_num = UART_NUM_1;
+int g_time = 0;
+
+gl_display_t *error_disp = NULL;
 
 
 void lcd_clock_draw_face(gl_display_t *);
@@ -19,6 +23,7 @@ void lcd_clock_draw_hand(gl_display_t *, uint16_t, uint16_t, uint8_t, gl_word_t)
 gl_word_t txt_strw(gl_display_t *, char *);
 
 
+
 int write_tx(const void *data, size_t sz) {
     return uart_write_bytes(uart_num, data, sz);
 }
@@ -70,6 +75,20 @@ void slower_baud() {
     ESP_ERROR_CHECK(uart_param_config(uart_num, &uart_config));
 }
 
+int Callback4DImpl (int, unsigned char) {
+    if (error_disp && g_time % 3 == 0) {
+        printf("resetting uLCD...\n");
+        ESP_ERROR_CHECK(gpio_set_level(PIN_ULCD_RESET, 0));
+        vTaskDelay(100 / portTICK_PERIOD_MS);
+        ESP_ERROR_CHECK(gpio_set_level(PIN_ULCD_RESET, 1));
+        gl_reset2(error_disp);
+        //gl_setbaudWait(error_disp, BAUD_600000, &faster_baud);
+    }
+    if (g_time > 9)
+        esp_restart();
+    g_time++;
+    return 10;
+}
 /* ================================================================= */
 
 void lcd_task(void) {
@@ -77,6 +96,8 @@ void lcd_task(void) {
     const int uart_buffer_size = UART_HW_FIFO_LEN(uart_num) + 4;
     QueueHandle_t uart_queue;
 
+    Callback4D = &Callback4DImpl;
+
     gl_serif_t serif_ulcd = {
         .write_tx = write_tx,
         .read_rx = read_rx,
@@ -113,10 +134,13 @@ void lcd_task(void) {
 
     gl_init(&disp, &serif_ulcd);
 
+    //error_disp = &disp;
+
     /* change baud rate */
     gl_setbaudWait(&disp, BAUD_600000, &faster_baud);
     lcd_boot_flash(&disp);
-    lcd_clock_loop(&disp);
+    //lcd_clock_loop(&disp);
+    lcd_homepage_loop(&disp);
 }
 
 
@@ -159,7 +183,10 @@ void lcd_boot_flash(gl_display_t *disp) {
     gl_putstr(disp, (uint8_t *) "Anish &");
     gl_txt_MoveCursor(disp, 11, 10);
     gl_putstr(disp, (uint8_t *) "Advaith");
-    vTaskDelay(pdMS_TO_TICKS(2000));
+    ESP_ERROR_CHECK(gpio_set_level(PIN_VIBRATOR, 1));
+    vTaskDelay(pdMS_TO_TICKS(500));
+    ESP_ERROR_CHECK(gpio_set_level(PIN_VIBRATOR, 0));
+    vTaskDelay(pdMS_TO_TICKS(1500));
 }
 
 
@@ -177,7 +204,7 @@ void lcd_clock_loop(gl_display_t *disp) {
                 tm / (60 * 60) % 12,
                 tm / 60 % 60,
                 (tm / (60 * 60) % 24 > 12) ? "PM" : "AM");
-        gl_txt_Italic(disp, 1);
+        /*gl_txt_Italic(disp, 1);*/
         uint16_t chw = txt_strw(disp, txt);
         gl_gfx_MoveTo(disp, (LCD_WIDTH / 2) - (chw / 2), (LCD_HEIGHT / 2)
                 + (CLOCKSCR_CIRCRAD / 2));
@@ -202,11 +229,14 @@ void lcd_clock_loop(gl_display_t *disp) {
 
 
 void lcd_homepage_loop(gl_display_t *disp) {
+    uint8_t num_rows = 3;
+    uint8_t num_cols = 2;
+    uint8_t num_padd = APPSCR_PAD;
     gl_gfx_BGcolour(disp, BLACK);
     gl_gfx_Cls(disp);
 
-    for (uint8_t i = 0; i < APPSCR_RCNUM; ++i) {
-        for (uint8_t j = 0; j < APPSCR_RCNUM; ++j) {
+    for (uint8_t i = 0; i < num_rows; ++i) {
+        for (uint8_t j = 0; j < num_cols; ++j) {
             /*
             printf("adding %d, %d [%d|%d|%d|%d]\n",
                     i + 1, j + 1,
@@ -219,8 +249,19 @@ void lcd_homepage_loop(gl_display_t *disp) {
                     APPSCR_TOPCALCH(j + 1) + APPSCR_PADCALCH(0),
                     WHITE);
                     */
+            gl_gfx_RectangleFilled(disp,
+                    APPSCR_TOPCALCVW(num_cols, num_padd, j + 1),
+                    APPSCR_TOPCALCVH(num_rows, num_padd, i + 1),
+                    APPSCR_TOPCALCVW(num_cols, num_padd, j + 1)
+                        + APPSCR_PADCALCVW(num_cols, num_padd),
+                    APPSCR_TOPCALCVH(num_rows, num_padd, i + 1)
+                        + APPSCR_PADCALCVH(num_rows, num_padd),
+                    WHITE);
         }
     }
+    lcd_clock_loop(disp);
+    while(1)
+        vTaskDelay(pdMS_TO_TICKS(1000));
 }
 
 
index a6cde84a5f4cc8a4e5225c3671ef979d00cfa939..9bee7abd5072fadedb012a247bb9e0cf7b64ddb3 100644 (file)
@@ -28,8 +28,8 @@
 #define APPSCR_TOPCALCH(x) ((x) * APPSCR_PAD) + (((x) - 1) * APPSCR_PADCALCH(0))
 
 /* v stands for variale */
-#define APPSCR_PADCALCVW(n, pad) (LCD_WIDTH - (n)  * (pad))
-#define APPSCR_PADCALCVH(n, pad) (LCD_HEIGHT - (n)  * (pad))
+#define APPSCR_PADCALCVW(n, pad) (LCD_WIDTH - (n)  * (pad)) / (n)
+#define APPSCR_PADCALCVH(n, pad) (LCD_HEIGHT - (n)  * (pad)) / (n)
 #define APPSCR_TOPCALCVW(n, pad, x) ((x) * (pad)) + \
     (((x) - 1) * APPSCR_PADCALCVW(n, pad))
 #define APPSCR_TOPCALCVH(n, pad, x) ((x) * (pad)) + \