Add accelerometer interrupts and option to update the watch face less frequently

This commit is contained in:
Lewis Jackson 2023-05-30 03:21:16 +03:00
parent 6609a3ab13
commit ca117ea3fc
6 changed files with 112 additions and 14 deletions

View file

@ -1,6 +1,7 @@
#include "WatchFace.h" #include "WatchFace.h"
#include "SevenSegment.h" #include "SevenSegment.h"
#include <cmath> #include <cmath>
#include <Fonts/FreeSans9pt7b.h>
RTC_DATA_ATTR bool WatchFace::m_menuSetup = false; RTC_DATA_ATTR bool WatchFace::m_menuSetup = false;
RTC_DATA_ATTR bool WatchFace::m_inMenu = false; RTC_DATA_ATTR bool WatchFace::m_inMenu = false;
@ -62,6 +63,16 @@ void WatchFace::HandleButtonPress(uint64_t buttonMask)
} }
} }
void WatchFace::HandleDoubleTap()
{
ShowWatchFace(true);
}
void WatchFace::HandleTilt()
{
ShowWatchFace(true);
}
void WatchFace::DrawWatchFace(bool partialRefresh) void WatchFace::DrawWatchFace(bool partialRefresh)
{ {
if (m_inMenu) { if (m_inMenu) {
@ -130,10 +141,15 @@ void WatchFace::SetupVolatileMenuStuff()
1 // pageNum 1 // pageNum
}, },
{ {
"Set TZ", // title "Set Timezone", // title
nullptr, // callback nullptr, // callback
2 // pageNum 2 // pageNum
}, },
{
"Reset Steps", // title
nullptr, // callback
3 // pageNum
},
{ {
"Back", // title "Back", // title
nullptr, // callback nullptr, // callback
@ -191,6 +207,24 @@ void WatchFace::SetupVolatileMenuStuff()
0 // pageNum 0 // pageNum
} }
}, },
},
{
0, // backPageNum
"RESET STEPS", // title
ALIGNMENT_CENTER, // titleAlignment
"Confirm?", // body
{ // Menu items
{
"No", // title
nullptr, // callback
0 // pageNum
},
{
"Yes", // title
std::bind(&WatchFace::MenuConfirmResetSteps, this), // callback
0 // pageNum
}
}
} }
}; };
@ -229,3 +263,14 @@ void WatchFace::MenuTimeZoneSelected(int tzOffset)
DrawWatchFace(false); DrawWatchFace(false);
} }
} }
void WatchFace::MenuConfirmResetSteps()
{
ResetSteps();
if (m_inMenu) {
m_inMenu = false;
m_menu.Reset();
DrawWatchFace(false);
}
}

View file

@ -8,6 +8,8 @@ class WatchFace : public Watchy
public: public:
void Setup() override; // Called after hardware is set up void Setup() override; // Called after hardware is set up
void HandleButtonPress(uint64_t buttonMask) override; void HandleButtonPress(uint64_t buttonMask) override;
void HandleDoubleTap() override;
void HandleTilt() override;
void DrawWatchFace(bool partialRefresh = false) override; void DrawWatchFace(bool partialRefresh = false) override;
private: private:
@ -21,4 +23,5 @@ private:
void MenuExited(); void MenuExited();
void MenuNTPSyncSelected(); void MenuNTPSyncSelected();
void MenuTimeZoneSelected(int tzOffset); void MenuTimeZoneSelected(int tzOffset);
void MenuConfirmResetSteps();
}; };

View file

@ -1,11 +1,11 @@
#include "Watchy.h" #include "Watchy.h"
#include "bma423.h"
WatchyDisplayBase Watchy::m_displayBase; WatchyDisplayBase Watchy::m_displayBase;
WatchyDisplay Watchy::m_display(Watchy::m_displayBase); WatchyDisplay Watchy::m_display(Watchy::m_displayBase);
WatchyRTC Watchy::m_RTC; WatchyRTC Watchy::m_RTC;
RTC_DATA_ATTR BMA423 Watchy::m_sensor; RTC_DATA_ATTR BMA423 Watchy::m_sensor;
RTC_DATA_ATTR bool g_displayFullInit = true; RTC_DATA_ATTR bool g_displayFullInit = true;
Watchy::Watchy() Watchy::Watchy()
@ -35,8 +35,28 @@ void Watchy::Init()
} }
case ESP_SLEEP_WAKEUP_EXT1: case ESP_SLEEP_WAKEUP_EXT1:
{ {
// Button press
uint64_t wakeupBit = esp_sleep_get_ext1_wakeup_status(); uint64_t wakeupBit = esp_sleep_get_ext1_wakeup_status();
if (wakeupBit & ACC_INT_MASK) {
m_sensor.getINT();
uint8_t irqMask = m_sensor.getIRQMASK();
if(irqMask & BMA423_TILT_INT) {
HandleTilt();
}
if(irqMask & BMA423_WAKEUP_INT) {
HandleDoubleTap();
}
m_sensor.getINT();
} else if (wakeupBit & BTN_PIN_MASK) {
// Button press
HandleButtonPress(wakeupBit);
break;
}
// Button press
HandleButtonPress(wakeupBit); HandleButtonPress(wakeupBit);
break; break;
} }
@ -75,7 +95,7 @@ void Watchy::DeepSleep()
} }
esp_sleep_enable_ext0_wakeup((gpio_num_t)RTC_INT_PIN, 0); // enable deep sleep wake on RTC interrupt esp_sleep_enable_ext0_wakeup((gpio_num_t)RTC_INT_PIN, 0); // enable deep sleep wake on RTC interrupt
esp_sleep_enable_ext1_wakeup( esp_sleep_enable_ext1_wakeup(
BTN_PIN_MASK, BTN_PIN_MASK | ACC_INT_MASK,
ESP_EXT1_WAKEUP_ANY_HIGH); ESP_EXT1_WAKEUP_ANY_HIGH);
esp_deep_sleep_start(); esp_deep_sleep_start();
} }
@ -103,6 +123,16 @@ float Watchy::GetBatteryVoltage()
return analogReadMilliVolts(BATT_ADC_PIN) / 1000.0f * 2.0f; return analogReadMilliVolts(BATT_ADC_PIN) / 1000.0f * 2.0f;
} }
uint64_t Watchy::GetSteps()
{
return m_sensor.getCounter();
}
void Watchy::ResetSteps()
{
m_sensor.resetStepCounter();
}
void Watchy::ConnectWiFi() void Watchy::ConnectWiFi()
{ {
if(WiFi.begin(WIFI_SSID, WIFI_PASS) == WL_CONNECT_FAILED) { if(WiFi.begin(WIFI_SSID, WIFI_PASS) == WL_CONNECT_FAILED) {
@ -233,7 +263,6 @@ void Watchy::BmaConfig()
// Enable BMA423 accelerometer // Enable BMA423 accelerometer
// Warning : Need to use feature, you must first enable the accelerometer // Warning : Need to use feature, you must first enable the accelerometer
// Warning : Need to use feature, you must first enable the accelerometer
m_sensor.enableAccel(); m_sensor.enableAccel();
struct bma4_int_pin_config config; struct bma4_int_pin_config config;
@ -263,11 +292,13 @@ void Watchy::BmaConfig()
m_sensor.enableFeature(BMA423_WAKEUP, true); m_sensor.enableFeature(BMA423_WAKEUP, true);
// Reset steps // Reset steps
m_sensor.resetStepCounter(); //m_sensor.resetStepCounter();
// Turn on feature interrupt // Turn on feature interrupt
m_sensor.enableStepCountInterrupt(); //m_sensor.enableStepCountInterrupt();
if (WAKE_ON_ACCEL_EVENTS) {
m_sensor.enableTiltInterrupt(); m_sensor.enableTiltInterrupt();
// It corresponds to isDoubleClick interrupt
m_sensor.enableWakeupInterrupt(); m_sensor.enableWakeupInterrupt();
} }
}

View file

@ -16,6 +16,8 @@ public:
void DeepSleep(); void DeepSleep();
void VibeMotor(uint8_t intervalMs = 100, uint8_t length = 20); void VibeMotor(uint8_t intervalMs = 100, uint8_t length = 20);
float GetBatteryVoltage(); float GetBatteryVoltage();
uint64_t GetSteps();
void ResetSteps();
void ConnectWiFi(); void ConnectWiFi();
void SyncNTPTime(); void SyncNTPTime();
void DisconnectWiFi(); void DisconnectWiFi();
@ -26,9 +28,13 @@ public:
// Called after hardware is setup // Called after hardware is setup
virtual void Setup() = 0; virtual void Setup() = 0;
virtual void HandleButtonPress(uint64_t buttonMask) = 0; virtual void HandleButtonPress(uint64_t buttonMask) = 0;
virtual void HandleDoubleTap() {}
virtual void HandleTilt() {}
virtual void DrawWatchFace(bool partialRefresh = false) = 0; virtual void DrawWatchFace(bool partialRefresh = false) = 0;
protected: protected:
static void DisplayBusyCallback(const void *); static void DisplayBusyCallback(const void *);

View file

@ -17,9 +17,19 @@ void WatchyRTC::config(String datetime) { // String datetime format is YYYY:MM:D
void WatchyRTC::clearAlarm() { void WatchyRTC::clearAlarm() {
int nextAlarmMinute = 0; int nextAlarmMinute = 0;
rtc_pcf.clearAlarm(); // resets the alarm flag in the RTC rtc_pcf.clearAlarm(); // resets the alarm flag in the RTC
nextAlarmMinute = rtc_pcf.getMinute();
nextAlarmMinute = (nextAlarmMinute == 59) ? 0 : (nextAlarmMinute + 1); // set alarm to trigger 1 minute from now int second = rtc_pcf.getSecond();
rtc_pcf.setAlarm(nextAlarmMinute, 99, 99, 99); int minute = rtc_pcf.getMinute();
int hour = rtc_pcf.getHour();
minute += UPDATE_INTERVAL;
if (minute >= 60) {
hour += minute / 60;
minute = minute % 60;
}
rtc_pcf.setAlarm(minute, hour, 99, 99);
} }
void WatchyRTC::read(tmElements_t & tm, int offsetInSeconds) void WatchyRTC::read(tmElements_t & tm, int offsetInSeconds)

View file

@ -29,3 +29,6 @@
#define TZ_OFFSET 3600 * 3 #define TZ_OFFSET 3600 * 3
#define NTP_SERVER "pool.ntp.org" #define NTP_SERVER "pool.ntp.org"
#define UPDATE_INTERVAL 1
#define WAKE_ON_ACCEL_EVENTS false