From 7747dcc64574c9e32f2f97b4f5ed66ba70f89e30 Mon Sep 17 00:00:00 2001 From: SQFMI Date: Tue, 2 Jul 2024 00:50:47 -0400 Subject: [PATCH] Add support for Watchy V3 and fixed compilation errors with arduion-esp32 v3.0.x --- library.json | 2 +- library.properties | 2 +- src/BLE.cpp | 2 +- src/Display.cpp | 1 - src/Display.h | 2 + src/Watchy.cpp | 70 ++++++++++++++++++++++++----- src/Watchy.h | 23 +++++++++- src/Watchy32KRTC.cpp | 103 +++++++++++++++++++++++++++++++++++++++++++ src/Watchy32KRTC.h | 23 ++++++++++ src/config.h | 62 ++++++++++++++++++++------ 10 files changed, 258 insertions(+), 32 deletions(-) create mode 100644 src/Watchy32KRTC.cpp create mode 100644 src/Watchy32KRTC.h diff --git a/library.json b/library.json index 5c35af1..2f242fa 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "Watchy", - "version": "1.4.10", + "version": "1.4.11", "description": "Watchy - An Open Source E-Paper Watch by SQFMI", "authors": [ { diff --git a/library.properties b/library.properties index 49709c0..a2671cd 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Watchy -version=1.4.10 +version=1.4.11 author=SQFMI maintainer=SQFMI sentence=Watchy - An Open Source E-Paper Watch by SQFMI diff --git a/src/BLE.cpp b/src/BLE.cpp index 18a40cd..a916557 100644 --- a/src/BLE.cpp +++ b/src/BLE.cpp @@ -38,7 +38,7 @@ public: }; void otaCallback::onWrite(BLECharacteristic *pCharacteristic) { - std::string rxData = pCharacteristic->getValue(); + String rxData = pCharacteristic->getValue(); if (!updateFlag) { // If it's the first packet of OTA since bootup, begin OTA // Serial.println("Begin FW Update"); esp_ota_begin(esp_ota_get_next_update_partition(NULL), OTA_SIZE_UNKNOWN, diff --git a/src/Display.cpp b/src/Display.cpp index a2085db..3ef8d5d 100644 --- a/src/Display.cpp +++ b/src/Display.cpp @@ -15,7 +15,6 @@ // Link: https://github.com/sqfmi/Watchy #include "Display.h" -#include "config.h" RTC_DATA_ATTR bool displayFullInit = true; diff --git a/src/Display.h b/src/Display.h index 96bd786..dcb7248 100644 --- a/src/Display.h +++ b/src/Display.h @@ -17,6 +17,8 @@ #pragma once #include +#include "driver/gpio.h" +#include "config.h" class WatchyDisplay : public GxEPD2_EPD { diff --git a/src/Watchy.cpp b/src/Watchy.cpp index 8353011..7c60531 100644 --- a/src/Watchy.cpp +++ b/src/Watchy.cpp @@ -1,6 +1,12 @@ #include "Watchy.h" -WatchyRTC Watchy::RTC; +#ifdef ARDUINO_ESP32S3_DEV + Watchy32KRTC Watchy::RTC; + #define ACTIVE_LOW 0 +#else + WatchyRTC Watchy::RTC; + #define ACTIVE_LOW 1 +#endif GxEPD2_BW Watchy::display( WatchyDisplay{}); @@ -20,14 +26,22 @@ RTC_DATA_ATTR char lastSSID[30]; void Watchy::init(String datetime) { esp_sleep_wakeup_cause_t wakeup_reason; wakeup_reason = esp_sleep_get_wakeup_cause(); // get wake up reason - Wire.begin(SDA, SCL); // init i2c + #ifdef ARDUINO_ESP32S3_DEV + Wire.begin(WATCHY_V3_SDA, WATCHY_V3_SCL); // init i2c + #else + Wire.begin(SDA, SCL); // init i2c + #endif RTC.init(); // Init the display since is almost sure we will use it display.epd2.initWatchy(); switch (wakeup_reason) { + #ifdef ARDUINO_ESP32S3_DEV + case ESP_SLEEP_WAKEUP_TIMER: // RTC Alarm + #else case ESP_SLEEP_WAKEUP_EXT0: // RTC Alarm + #endif RTC.read(currentTime); switch (guiState) { case WATCHFACE_STATE: @@ -70,7 +84,18 @@ void Watchy::init(String datetime) { void Watchy::deepSleep() { display.hibernate(); RTC.clearAlarm(); // resets the alarm flag in the RTC + #ifdef ARDUINO_ESP32S3_DEV + esp_sleep_enable_ext1_wakeup( + BTN_PIN_MASK, + ESP_EXT1_WAKEUP_ANY_LOW); // enable deep sleep wake on button press + rtc_clk_32k_enable(true); + //rtc_clk_slow_freq_set(RTC_SLOW_FREQ_32K_XTAL); + struct tm timeinfo; + getLocalTime(&timeinfo); + int secToNextMin = 60 - timeinfo.tm_sec; + esp_sleep_enable_timer_wakeup(secToNextMin * uS_TO_S_FACTOR); + #else // Set GPIOs 0-39 to input to avoid power leaking out const uint64_t ignore = 0b11110001000000110000100111000010; // Ignore some GPIOs due to resets for (int i = 0; i < GPIO_NUM_MAX; i++) { @@ -83,6 +108,8 @@ void Watchy::deepSleep() { esp_sleep_enable_ext1_wakeup( BTN_PIN_MASK, ESP_EXT1_WAKEUP_ANY_HIGH); // enable deep sleep wake on button press + #endif + esp_deep_sleep_start(); } @@ -173,7 +200,7 @@ void Watchy::handleButtonPress() { if (millis() - lastTimeout > 5000) { timeout = true; } else { - if (digitalRead(MENU_BTN_PIN) == 1) { + if (digitalRead(MENU_BTN_PIN) == ACTIVE_LOW) { lastTimeout = millis(); if (guiState == MAIN_MENU_STATE) { // if already in menu, then select menu item @@ -205,7 +232,7 @@ void Watchy::handleButtonPress() { } else if (guiState == FW_UPDATE_STATE) { updateFWBegin(); } - } else if (digitalRead(BACK_BTN_PIN) == 1) { + } else if (digitalRead(BACK_BTN_PIN) == ACTIVE_LOW) { lastTimeout = millis(); if (guiState == MAIN_MENU_STATE) { // exit to watch face if already in menu @@ -217,7 +244,7 @@ void Watchy::handleButtonPress() { } else if (guiState == FW_UPDATE_STATE) { showMenu(menuIndex, false); // exit to menu if already in app } - } else if (digitalRead(UP_BTN_PIN) == 1) { + } else if (digitalRead(UP_BTN_PIN) == ACTIVE_LOW) { lastTimeout = millis(); if (guiState == MAIN_MENU_STATE) { // increment menu index menuIndex--; @@ -226,7 +253,7 @@ void Watchy::handleButtonPress() { } showFastMenu(menuIndex); } - } else if (digitalRead(DOWN_BTN_PIN) == 1) { + } else if (digitalRead(DOWN_BTN_PIN) == ACTIVE_LOW) { lastTimeout = millis(); if (guiState == MAIN_MENU_STATE) { // decrement menu index menuIndex++; @@ -323,6 +350,7 @@ void Watchy::showAbout() { display.print(voltage); display.println("V"); + #ifndef ARDUINO_ESP32S3_DEV display.print("Uptime: "); RTC.read(currentTime); time_t b = makeTime(bootTime); @@ -337,7 +365,9 @@ void Watchy::showAbout() { display.print(hours); display.print("h"); display.print(minutes); - display.println("m"); + display.println("m"); + #endif + if(WIFI_CONFIGURED){ display.print("SSID: "); display.println(lastSSID); @@ -379,11 +409,19 @@ void Watchy::setTime() { RTC.read(currentTime); + #ifdef ARDUINO_ESP32S3_DEV + uint8_t minute = currentTime.Minute; + uint8_t hour = currentTime.Hour; + uint8_t day = currentTime.Day; + uint8_t month = currentTime.Month; + uint8_t year = currentTime.Year; + #else int8_t minute = currentTime.Minute; int8_t hour = currentTime.Hour; int8_t day = currentTime.Day; int8_t month = currentTime.Month; int8_t year = tmYearToY2k(currentTime.Year); + #endif int8_t setIndex = SET_HOUR; @@ -398,13 +436,13 @@ void Watchy::setTime() { while (1) { - if (digitalRead(MENU_BTN_PIN) == 1) { + if (digitalRead(MENU_BTN_PIN) == ACTIVE_LOW) { setIndex++; if (setIndex > SET_DAY) { break; } } - if (digitalRead(BACK_BTN_PIN) == 1) { + if (digitalRead(BACK_BTN_PIN) == ACTIVE_LOW) { if (setIndex != SET_HOUR) { setIndex--; } @@ -412,7 +450,7 @@ void Watchy::setTime() { blink = 1 - blink; - if (digitalRead(DOWN_BTN_PIN) == 1) { + if (digitalRead(DOWN_BTN_PIN) == ACTIVE_LOW) { blink = 1; switch (setIndex) { case SET_HOUR: @@ -435,7 +473,7 @@ void Watchy::setTime() { } } - if (digitalRead(UP_BTN_PIN) == 1) { + if (digitalRead(UP_BTN_PIN) == ACTIVE_LOW) { blink = 1; switch (setIndex) { case SET_HOUR: @@ -519,7 +557,11 @@ void Watchy::setTime() { tmElements_t tm; tm.Month = month; tm.Day = day; + #ifdef ARDUINO_ESP32S3_DEV + tm.Year = year; + #else tm.Year = y2kYearToTm(year); + #endif tm.Hour = hour; tm.Minute = minute; tm.Second = 0; @@ -548,7 +590,7 @@ void Watchy::showAccelerometer() { unsigned long currentMillis = millis(); - if (digitalRead(BACK_BTN_PIN) == 1) { + if (digitalRead(BACK_BTN_PIN) == ACTIVE_LOW) { break; } @@ -693,12 +735,16 @@ weatherData Watchy::_getWeatherData(String cityID, String lat, String lon, Strin } float Watchy::getBatteryVoltage() { + #ifdef ARDUINO_ESP32S3_DEV + return analogReadMilliVolts(BATT_ADC_PIN) / 1000.0f * ADC_VOLTAGE_DIVIDER; + #else if (RTC.rtcType == DS3231) { return analogReadMilliVolts(BATT_ADC_PIN) / 1000.0f * 2.0f; // Battery voltage goes through a 1/2 divider. } else { return analogReadMilliVolts(BATT_ADC_PIN) / 1000.0f * 2.0f; } + #endif } uint8_t Watchy::getBoardRevision() { diff --git a/src/Watchy.h b/src/Watchy.h index d056d50..b7c7a89 100644 --- a/src/Watchy.h +++ b/src/Watchy.h @@ -12,11 +12,26 @@ #include #include "DSEG7_Classic_Bold_53.h" #include "Display.h" -#include "WatchyRTC.h" #include "BLE.h" #include "bma.h" #include "config.h" #include "esp_chip_info.h" +#ifdef ARDUINO_ESP32S3_DEV + #include "Watchy32KRTC.h" + #include "soc/rtc.h" + #include "soc/rtc_io_reg.h" + #include "soc/sens_reg.h" + #include "esp_sleep.h" + #include "rom/rtc.h" + #include "soc/soc.h" + #include "soc/rtc_cntl_reg.h" + #include "time.h" + #include "esp_sntp.h" + #define uS_TO_S_FACTOR 1000000ULL //Conversion factor for micro seconds to seconds + #define ADC_VOLTAGE_DIVIDER ((360.0f+100.0f)/360.0f) //Voltage divider at battery ADC +#else + #include "WatchyRTC.h" +#endif typedef struct weatherData { int8_t temperature; @@ -47,7 +62,11 @@ typedef struct watchySettings { class Watchy { public: - static WatchyRTC RTC; + #ifdef ARDUINO_ESP32S3_DEV + static Watchy32KRTC RTC; + #else + static WatchyRTC RTC; + #endif static GxEPD2_BW display; tmElements_t currentTime; watchySettings settings; diff --git a/src/Watchy32KRTC.cpp b/src/Watchy32KRTC.cpp new file mode 100644 index 0000000..02555b1 --- /dev/null +++ b/src/Watchy32KRTC.cpp @@ -0,0 +1,103 @@ +#include "Watchy32KRTC.h" + +Watchy32KRTC::Watchy32KRTC(){} + +void Watchy32KRTC::init() { + +} + +/* + + setenv("TZ", "", 1); + tzset(); + +*/ + +void Watchy32KRTC::config(String datetime) { // String datetime format is YYYY:MM:DD:HH:MM:SS + struct tm timeInfo; + memset(&timeInfo, 0, sizeof(timeInfo)); + + // Parse the time string + if (strptime(datetime.c_str(), "%Y:%m:%d:%H:%M:%S", &timeInfo) == NULL) { + // Failed to parse the time string + } + + // Convert tm to timeval + struct timeval tv; + tv.tv_sec = mktime(&timeInfo); + tv.tv_usec = 0; + + // Set the time using settimeofday + if (settimeofday(&tv, NULL) != 0) { + // Error setting the time + } +} + +void Watchy32KRTC::clearAlarm() { + +} + +void Watchy32KRTC::read(tmElements_t &tm) { + time_t now; + struct tm timeInfo; + time(&now); + // Set timezone to China Standard Time + //setenv("TZ", "CST-8", 1); + //tzset(); + localtime_r(&now, &timeInfo); + tm.Year = timeInfo.tm_year - 70; + tm.Month = timeInfo.tm_mon + 1; + tm.Day = timeInfo.tm_mday; + tm.Wday = timeInfo.tm_wday + 1; + tm.Hour = timeInfo.tm_hour; + tm.Minute = timeInfo.tm_min; + tm.Second = timeInfo.tm_sec; +} + +void Watchy32KRTC::set(tmElements_t tm) { + struct tm timeInfo; + timeInfo.tm_year = tm.Year + 70; + timeInfo.tm_mon = tm.Month - 1; + timeInfo.tm_mday = tm.Day; + timeInfo.tm_hour = tm.Hour; + timeInfo.tm_min = tm.Minute; + timeInfo.tm_sec = tm.Second; + + // Convert tm to timeval + struct timeval tv; + tv.tv_sec = mktime(&timeInfo); + tv.tv_usec = 0; + + // Set the time using settimeofday + if (settimeofday(&tv, NULL) != 0) { + // Error setting the time + } +} + +uint8_t Watchy32KRTC::temperature() { + return 0; +} + +String Watchy32KRTC::_getValue(String data, char separator, int index) { + int found = 0; + int strIndex[] = {0, -1}; + int maxIndex = data.length() - 1; + + for (int i = 0; i <= maxIndex && found <= index; i++) { + if (data.charAt(i) == separator || i == maxIndex) { + found++; + strIndex[0] = strIndex[1] + 1; + strIndex[1] = (i == maxIndex) ? i + 1 : i; + } + } + + return found > index ? data.substring(strIndex[0], strIndex[1]) : ""; +} + +void Watchy32KRTC::_timeval_to_tm(struct timeval *tv, struct tm *tm) { + // Get the seconds and microseconds from the timeval struct + time_t seconds = tv->tv_sec; + int microseconds = tv->tv_usec; + // Convert the seconds to a tm struct + *tm = *localtime(&seconds); +} \ No newline at end of file diff --git a/src/Watchy32KRTC.h b/src/Watchy32KRTC.h new file mode 100644 index 0000000..a0ae156 --- /dev/null +++ b/src/Watchy32KRTC.h @@ -0,0 +1,23 @@ +#ifndef WATCHY_32K_RTC_H +#define WATCHY_32K_RTC_H + +#include +#include +#include "config.h" + +class Watchy32KRTC { +public: + Watchy32KRTC(); + void init(); + void config(String datetime); //datetime format is YYYY:MM:DD:HH:MM:SS + void clearAlarm(); + void read(tmElements_t &tm); + void set(tmElements_t tm); + uint8_t temperature(); + +private: + String _getValue(String data, char separator, int index); + void _timeval_to_tm(struct timeval *tv, struct tm *tm); +}; + +#endif \ No newline at end of file diff --git a/src/config.h b/src/config.h index 22fa99c..2250337 100644 --- a/src/config.h +++ b/src/config.h @@ -2,16 +2,49 @@ #define CONFIG_H // Versioning -#define WATCHY_LIB_VER "1.4.10" +#define WATCHY_LIB_VER "1.4.11" //pins -#if !defined(ARDUINO_WATCHY_V10) && !defined(ARDUINO_WATCHY_V15) && !defined(ARDUINO_WATCHY_V20) +//#if !defined(ARDUINO_WATCHY_V10) && !defined(ARDUINO_WATCHY_V15) && !defined(ARDUINO_WATCHY_V20) -#pragma message "Please install the latest ESP32 Arduino Core (2.0.5+) and choose Watchy as the target board" -#pragma message "Hardware revision is not defined at the project level, please define in config.h. Defaulting to ARDUINO_WATCHY_V20" +//#pragma message "Please install the latest ESP32 Arduino Core (2.0.5+) and choose Watchy as the target board" +//#pragma message "Hardware revision is not defined at the project level, please define in config.h. Defaulting to ARDUINO_WATCHY_V20" -//Change to your board version -#define ARDUINO_WATCHY_V20 +#ifdef ARDUINO_ESP32S3_DEV //V3 + +#define WATCHY_V3_SDA 12 +#define WATCHY_V3_SCL 11 + +#define WATCHY_V3_SS 33 +#define WATCHY_V3_MOSI 48 +#define WATCHY_V3_MISO 46 +#define WATCHY_V3_SCK 47 + +#define MENU_BTN_PIN 7 +#define BACK_BTN_PIN 6 +#define UP_BTN_PIN 0 +#define DOWN_BTN_PIN 8 + +#define DISPLAY_CS 33 +#define DISPLAY_DC 34 +#define DISPLAY_RES 35 +#define DISPLAY_BUSY 36 +#define ACC_INT_1_PIN 14 +#define ACC_INT_2_PIN 13 +#define VIB_MOTOR_PIN 17 +#define BATT_ADC_PIN 9 +#define CHRG_STATUS_PIN 10 +#define USB_DET_PIN 21 +#define RTC_INT_PIN -1 //not used + +#define MENU_BTN_MASK (BIT(7)) +#define BACK_BTN_MASK (BIT(6)) +#define UP_BTN_MASK (BIT(0)) +#define DOWN_BTN_MASK (BIT(8)) +#define ACC_INT_MASK (BIT(14)) +#define BTN_PIN_MASK MENU_BTN_MASK|BACK_BTN_MASK|DOWN_BTN_MASK + +#else //V1,V1.5,V2 #define MENU_BTN_PIN 26 #define BACK_BTN_PIN 25 @@ -28,24 +61,24 @@ #if defined (ARDUINO_WATCHY_V10) #define UP_BTN_PIN 32 #define BATT_ADC_PIN 33 - #define UP_BTN_MASK GPIO_SEL_32 + #define UP_BTN_MASK (BIT(32)) #define RTC_TYPE 1 //DS3231 #elif defined (ARDUINO_WATCHY_V15) #define UP_BTN_PIN 32 #define BATT_ADC_PIN 35 - #define UP_BTN_MASK GPIO_SEL_32 + #define UP_BTN_MASK (BIT(32)) #define RTC_TYPE 2 //PCF8563 #elif defined (ARDUINO_WATCHY_V20) #define UP_BTN_PIN 35 #define BATT_ADC_PIN 34 - #define UP_BTN_MASK GPIO_SEL_35 + #define UP_BTN_MASK (BIT(35)) #define RTC_TYPE 2 //PCF8563 #endif -#define MENU_BTN_MASK GPIO_SEL_26 -#define BACK_BTN_MASK GPIO_SEL_25 -#define DOWN_BTN_MASK GPIO_SEL_4 -#define ACC_INT_MASK GPIO_SEL_14 +#define MENU_BTN_MASK (BIT(26)) +#define BACK_BTN_MASK (BIT(25)) +#define DOWN_BTN_MASK (BIT(4)) +#define ACC_INT_MASK (BIT(14)) #define BTN_PIN_MASK MENU_BTN_MASK|BACK_BTN_MASK|UP_BTN_MASK|DOWN_BTN_MASK #endif @@ -78,4 +111,5 @@ #define SOFTWARE_VERSION_PATCH 0 #define HARDWARE_VERSION_MAJOR 1 #define HARDWARE_VERSION_MINOR 0 -#endif + +#endif \ No newline at end of file