Great build. have multiple faces!

pull/156/head
Michael-Paul Moore 2022-04-13 09:43:59 -07:00
parent 85bd057625
commit 94c962247e
15 changed files with 403 additions and 158 deletions

View File

@ -1,20 +0,0 @@
// Self
#include "DateTimeWatchFace.h"
// Fonts
#include <Fonts/FreeMonoBold9pt7b.h>
void CDateTimeWatchFace::Draw(CWatchyExpanded::ADisplay& display, const tmElements_t& time)
{
CTimeWatchFace::Draw(display, time);
m_currentLocalTime.tm_wday = time.Wday - 1;
m_currentLocalTime.tm_year = time.Year + 1970 - 1900;
m_currentLocalTime.tm_mon = time.Month - 1;
m_currentLocalTime.tm_mday = time.Day;
char buffer[32];
strftime(buffer, sizeof(buffer), "%a %b %d, %Y", &m_currentLocalTime);
display.print(buffer);
display.println();
};

View File

@ -1,17 +0,0 @@
#pragma once
// Time
#include <TimeLib.h>
// Expanded
#include "WatchFace.h"
#include "WatchyExpanded.h"
// Faces
#include "TimeWatchFace.h"
class CDateTimeWatchFace : public CTimeWatchFace
{
public:
void Draw(CWatchyExpanded::ADisplay& display, const tmElements_t& time) override;
};

39
src/DateWatchFace.cpp Normal file
View File

@ -0,0 +1,39 @@
// Self
#include "DateWatchFace.h"
// Fonts
#include <Fonts/FreeMonoBold9pt7b.h>
// Time
#include <TimeLib.h>
void CDateWatchFace::Draw(CWatchyExpanded& expanded)
{
StartDraw(expanded.Display());
CTimeWatchFace::DrawInternal(expanded);
DrawInternal(expanded);
};
void CDateWatchFace::StartDraw(CWatchyExpanded::ADisplay& display)
{
display.setFullWindow();
display.fillScreen(GxEPD_BLACK);
display.setFont(&FreeMonoBold9pt7b);
display.setCursor(0, 15);
};
void CDateWatchFace::DrawInternal(CWatchyExpanded& expanded)
{
CWatchyExpanded::ADisplay& display = expanded.Display();
tmElements_t& time = expanded.Time();
m_currentLocalTime.tm_wday = time.Wday - 1;
m_currentLocalTime.tm_year = time.Year + 1970 - 1900;
m_currentLocalTime.tm_mon = time.Month - 1;
m_currentLocalTime.tm_mday = time.Day;
char buffer[32];
strftime(buffer, sizeof(buffer), "%a %b %d, %Y", &m_currentLocalTime);
display.print(buffer);
display.println();
};

17
src/DateWatchFace.h Normal file
View File

@ -0,0 +1,17 @@
#pragma once
// Expanded
#include "WatchFace.h"
#include "WatchyExpanded.h"
// Faces
#include "TimeWatchFace.h"
class CDateWatchFace : public CTimeWatchFace
{
public:
void Draw(CWatchyExpanded& expanded) override;
void StartDraw(CWatchyExpanded::ADisplay& display);
void DrawInternal(CWatchyExpanded& expanded);
};

68
src/SyncNTP.cpp Normal file
View File

@ -0,0 +1,68 @@
// Self
#include "SyncNTP.h"
// GxEPD2
#include <GxEPD2_BW.h>
// Fonts
#include <Fonts/FreeMonoBold9pt7b.h>
// WiFi
#include <WiFi.h>
// Watchy
#include "WatchyRTC.h"
// NTP
#include <NTPClient.h>
CSyncNTP::CSyncNTP(CWatchyExpanded& expanded) : CWatchyApp(expanded) {}
const char* CSyncNTP::Name() const
{
return "SyncNTP";
}
void CSyncNTP::Work()
{
CWatchyExpanded::ADisplay& display = m_expanded.Display();
display.setFullWindow();
display.fillScreen(GxEPD_BLACK);
display.setFont(&FreeMonoBold9pt7b);
display.setTextColor(GxEPD_WHITE);
display.setCursor(0, 10);
display.println("Syncing NTP...");
display.display(false); //full refresh
if(m_expanded.ConnectWiFi())
{
if (!SyncNTP(3600 * -7, 3600, "pool.ntp.org"))
display.println("Failed to Sync NTP!");
else
display.println("Synced to NTP!");
WiFi.mode(WIFI_OFF);
btStop();
}
else
{
display.println("WiFi Not Configured.");
}
display.display(true); //full refresh
delay(3000);
}
//NTP sync - call after connecting to WiFi and remember to turn it back off
bool CSyncNTP::SyncNTP(long gmt, int dst, String ntpServer)
{
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, ntpServer.c_str(), gmt);
timeClient.begin();
if(!timeClient.forceUpdate())
return false; //NTP sync failed
tmElements_t tm;
breakTime((time_t)timeClient.getEpochTime(), tm);
m_expanded.RTC().set(tm);
return true;
}

16
src/SyncNTP.h Normal file
View File

@ -0,0 +1,16 @@
#pragma once
// Epanded
#include "WatchyApp.h"
class CSyncNTP : public CWatchyApp
{
public:
CSyncNTP(CWatchyExpanded& expanded);
const char* Name() const override;
void Work() override;
private:
bool SyncNTP(long gmt, int dst, String ntpServer);
};

View File

@ -4,13 +4,25 @@
// Fonts
#include <Fonts/FreeMonoBold9pt7b.h>
void CTimeWatchFace::Draw(CWatchyExpanded::ADisplay& display, const tmElements_t& time)
void CTimeWatchFace::Draw(CWatchyExpanded& expanded)
{
CWatchyExpanded::ADisplay& display = expanded.Display();
StartDraw(display);
DrawInternal(expanded);
};
void CTimeWatchFace::StartDraw(CWatchyExpanded::ADisplay& display)
{
display.setFullWindow();
display.fillScreen(GxEPD_BLACK);
display.setFont(&FreeMonoBold9pt7b);
display.setCursor(0, 15);
};
void CTimeWatchFace::DrawInternal(CWatchyExpanded& expanded)
{
CWatchyExpanded::ADisplay& display = expanded.Display();
tmElements_t& time = expanded.Time();
m_currentLocalTime.tm_hour = time.Hour;
m_currentLocalTime.tm_min = time.Minute;
m_currentLocalTime.tm_sec = time.Second;

View File

@ -10,7 +10,10 @@
class CTimeWatchFace : public CWatchFace
{
public:
void Draw(CWatchyExpanded::ADisplay& display, const tmElements_t& time) override;
virtual void Draw(CWatchyExpanded& expanded) override;
void StartDraw(CWatchyExpanded::ADisplay& display);
void DrawInternal(CWatchyExpanded& expanded);
protected:
tm m_currentLocalTime;

View File

@ -10,6 +10,5 @@ class CWatchFace
{
public:
CWatchFace() = default;
//override this method for different watch faces
virtual void Draw(CWatchyExpanded::ADisplay& display, const tmElements_t& time) = 0;
virtual void Draw(CWatchyExpanded& expanded) = 0; //override this method for different watch faces
};

5
src/WatchyApp.cpp Normal file
View File

@ -0,0 +1,5 @@
// Self
#include "WatchyApp.h"
CWatchyApp::CWatchyApp(CWatchyExpanded& expanded) : m_expanded(expanded) {}

View File

@ -1,7 +1,15 @@
#pragma once
// Expanded
#include "WatchyExpanded.h"
class CWatchyApp
{
public:
CWatchyApp(CWatchyExpanded& expanded);
virtual const char* Name() const = 0;
virtual void Work() = 0;
protected:
CWatchyExpanded& m_expanded;
};

View File

@ -8,14 +8,24 @@
// Faces
#include "TimeWatchFace.h"
#include "DateTimeWatchFace.h"
#include "DateWatchFace.h"
// Apps
#include "SyncNTP.h"
// Fonts
#include <Fonts/FreeMonoBold9pt7b.h>
// WiFi
#include <WiFi.h>
RTC_DATA_ATTR SExpandedData g_data;
CWatchyExpanded::CWatchyExpanded() : m_display(GxEPD2_154_D67(wcd::cs, wcd::dc, wcd::reset, wcd::busy)), m_data(g_data)
{
AddWatchFace(new CTimeWatchFace);
AddWatchFace(new CDateTimeWatchFace);
AddWatchFace(new CDateWatchFace);
AddApp(new CSyncNTP(*this));
}
void CWatchyExpanded::AddWatchFace(CWatchFace* pFace)
@ -23,6 +33,11 @@ void CWatchyExpanded::AddWatchFace(CWatchFace* pFace)
m_faces.push_back(pFace);
}
void CWatchyExpanded::AddApp(CWatchyApp* pApp)
{
m_apps.push_back(pApp);
}
void CWatchyExpanded::Run()
{
const esp_sleep_wakeup_cause_t wakeup_reason = esp_sleep_get_wakeup_cause(); //get wake up reason
@ -37,7 +52,7 @@ void CWatchyExpanded::Run()
switch (wakeup_reason)
{
case ESP_SLEEP_WAKEUP_EXT0: //RTC Alarm
if(m_guiState == wc::kWatchFace_State)
if(m_data.m_guiState == SExpandedData::guiState::face)
m_UpdateWatchFace = true;
break;
case ESP_SLEEP_WAKEUP_EXT1: //button Press
@ -50,11 +65,37 @@ void CWatchyExpanded::Run()
if (m_UpdateWatchFace)
{
m_rtc.read(m_currentTime);
UpdateScreen(false); // full update
UpdateScreen(true); // full update
}
DeepSleep();
}
CWatchyExpanded::ADisplay& CWatchyExpanded::Display()
{
return m_display;
}
WatchyRTC& CWatchyExpanded::RTC()
{
return m_rtc;
}
tmElements_t& CWatchyExpanded::Time()
{
return m_currentTime;
}
bool CWatchyExpanded::ConnectWiFi()
{
//WiFi not setup, you can also use hard coded credentials with WiFi.begin(SSID,PASS);
if(wl_status_t::WL_CONNECT_FAILED == WiFi.begin())
return false;
WiFi.waitForConnectResult();
return true;
}
void CWatchyExpanded::Init()
{
if (!m_data.m_init)
@ -73,33 +114,62 @@ void CWatchyExpanded::DisplayBusyCallback(const void*)
void CWatchyExpanded::UpdateScreen(const bool partial_update)
{
m_display.setFullWindow();
m_currentTime.Month = 4;
m_faces[m_data.m_face % m_faces.size()]->Draw(m_display, m_currentTime);
m_faces[m_data.m_face % m_faces.size()]->Draw(*this);
m_display.display(partial_update); //partial refresh
m_guiState = wc::kWatchFace_State;
m_data.m_guiState = SExpandedData::guiState::face;
}
void CWatchyExpanded::DeepSleep()
{
m_display.hibernate();
m_data.m_init = false;
m_rtc.clearAlarm(); //resets the alarm flag in the RTC
m_rtc.clearAlarm(); // resets the alarm flag in the RTC
for(int i = 0; i < 40; ++i) // Set pins 0-39 to input to avoid power leaking out
pinMode(i, INPUT);
esp_sleep_enable_ext0_wakeup(wc::rtc_pin, 0); //enable deep sleep wake on RTC interrupt
esp_sleep_enable_ext1_wakeup(wc::btn_pin_mask, ESP_EXT1_WAKEUP_ANY_HIGH); //enable deep sleep wake on button press
esp_sleep_enable_ext0_wakeup(wcp::rtc_pin, 0); //enable deep sleep wake on RTC interrupt
esp_sleep_enable_ext1_wakeup(wcp::btn_pin_mask, ESP_EXT1_WAKEUP_ANY_HIGH); //enable deep sleep wake on button press
esp_deep_sleep_start();
}
void CWatchyExpanded::HandleButtonPress()
{
const uint64_t kWakeupBit = esp_sleep_get_ext1_wakeup_status();
if (kWakeupBit & wc::up_btn_mask)
BackFace();
else if (kWakeupBit & wc::down_btn_mask)
ForwardFace();
if (m_data.m_guiState == SExpandedData::guiState::face)
{
if (kWakeupBit & wcp::up_btn_mask)
BackFace();
else if (kWakeupBit & wcp::down_btn_mask)
ForwardFace();
else if (kWakeupBit & wcp::menu_btn_mask)
Menu();
}
else if (m_data.m_guiState == SExpandedData::guiState::menu)
{
if (kWakeupBit & wcp::back_btn_mask)
{
m_data.m_guiState = SExpandedData::guiState::face;
m_UpdateWatchFace = true;
}
else if (kWakeupBit & wcp::menu_btn_mask)
{
m_apps[m_data.menu % m_apps.size()]->Work();
}
}
}
void CWatchyExpanded::Menu()
{
m_display.setFullWindow();
m_display.fillScreen(GxEPD_BLACK);
m_display.setFont(&FreeMonoBold9pt7b);
m_display.setCursor(0, 15);
for (const CWatchyApp* pApp : m_apps)
m_display.println(pApp->Name());
m_data.m_guiState = SExpandedData::guiState::menu;
m_display.display(true);
}
void CWatchyExpanded::BackFace()
@ -131,3 +201,11 @@ uint16_t CWatchyExpanded::_readRegister(uint8_t address, uint8_t reg, uint8_t *d
data[++i] = Wire.read();
return 0;
}
float CWatchyExpanded::BatteryVoltage()
{
if(m_rtc.rtcType == DS3231)
return analogReadMilliVolts(wcp::batt_adc_pin) / 1000.0f * 2.0f; // Battery voltage goes through a 1/2 divider.
else
return analogReadMilliVolts(wcp::batt_adc_pin) / 1000.0f * 2.0f;
}

View File

@ -23,28 +23,48 @@ struct SExpandedData
{
bool m_init = true;
std::uint8_t m_face = 0;
enum guiState : std::uint8_t
{
face,
menu
} m_guiState = guiState::face;
std::uint8_t m_menuItem = 0;
};
class CWatchyExpanded
{
public:
using ADisplay = GxEPD2_BW<GxEPD2_154_D67, GxEPD2_154_D67::HEIGHT>;
CWatchyExpanded();
void AddWatchFace(CWatchFace* pFace);
void AddApp(CWatchyApp* pApp);
void Init();
void Run();
using ADisplay = GxEPD2_BW<GxEPD2_154_D67, GxEPD2_154_D67::HEIGHT>;
bool ConnectWiFi();
ADisplay& Display();
WatchyRTC& RTC();
tmElements_t& Time();
float BatteryVoltage();
private:
static void DisplayBusyCallback(const void*);
void UpdateScreen(const bool fullUpdate);
void DeepSleep();
void HandleButtonPress();
void BackFace();
void ForwardFace();
void Menu();
void _bmaConfig();
static uint16_t _readRegister(uint8_t address, uint8_t reg, uint8_t *data, uint16_t len);
@ -53,7 +73,7 @@ class CWatchyExpanded
ADisplay m_display;
tmElements_t m_currentTime;
std::int8_t m_guiState = 0;
WatchyRTC m_rtc;
SExpandedData& m_data;
bool m_UpdateWatchFace = false;

View File

@ -1,118 +1,122 @@
#include "WatchyRTC.h"
WatchyRTC::WatchyRTC()
: rtc_ds(false) {}
: rtc_ds(false) {}
void WatchyRTC::init(){
byte error;
Wire.beginTransmission(RTC_DS_ADDR);
error = Wire.endTransmission();
if(error == 0){
rtcType = DS3231;
}else{
Wire.beginTransmission(RTC_PCF_ADDR);
error = Wire.endTransmission();
if(error == 0){
rtcType = PCF8563;
}else{
//RTC Error
}
}
void WatchyRTC::init()
{
byte error;
Wire.beginTransmission(RTC_DS_ADDR);
error = Wire.endTransmission();
if(error == 0)
{
rtcType = DS3231;
}
else
{
Wire.beginTransmission(RTC_PCF_ADDR);
error = Wire.endTransmission();
if(error == 0)
rtcType = PCF8563;
}
}
void WatchyRTC::config(String datetime){ //String datetime format is YYYY:MM:DD:HH:MM:SS
if(rtcType == DS3231){
_DSConfig(datetime);
}else{
_PCFConfig(datetime);
}
if(rtcType == DS3231){
_DSConfig(datetime);
}else{
_PCFConfig(datetime);
}
}
void WatchyRTC::clearAlarm(){
if(rtcType == DS3231){
rtc_ds.alarm(ALARM_2);
}else{
int nextAlarmMinute = 0;
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
rtc_pcf.setAlarm(nextAlarmMinute, 99, 99, 99);
}
void WatchyRTC::clearAlarm()
{
if(rtcType == DS3231)
{
rtc_ds.alarm(ALARM_2);
}
else
{
rtc_pcf.clearAlarm(); //resets the alarm flag in the RTC
int nextAlarmMinute = rtc_pcf.getMinute();
nextAlarmMinute = (nextAlarmMinute == 59) ? 0 : (nextAlarmMinute + 1); //set alarm to trigger 1 minute from now
rtc_pcf.setAlarm(nextAlarmMinute, 99, 99, 99);
}
}
void WatchyRTC::read(tmElements_t &tm){
if(rtcType == DS3231){
rtc_ds.read(tm);
}else{
tm.Year = y2kYearToTm(rtc_pcf.getYear());
tm.Month = rtc_pcf.getMonth();
tm.Day = rtc_pcf.getDay();
tm.Wday = rtc_pcf.getWeekday() + 1; //TimeLib & DS3231 has Wday range of 1-7, but PCF8563 stores day of week in 0-6 range
tm.Hour = rtc_pcf.getHour();
tm.Minute = rtc_pcf.getMinute();
tm.Second = rtc_pcf.getSecond();
}
if(rtcType == DS3231){
rtc_ds.read(tm);
}else{
tm.Year = y2kYearToTm(rtc_pcf.getYear());
tm.Month = rtc_pcf.getMonth();
tm.Day = rtc_pcf.getDay();
tm.Wday = rtc_pcf.getWeekday() + 1; //TimeLib & DS3231 has Wday range of 1-7, but PCF8563 stores day of week in 0-6 range
tm.Hour = rtc_pcf.getHour();
tm.Minute = rtc_pcf.getMinute();
tm.Second = rtc_pcf.getSecond();
}
}
void WatchyRTC::set(tmElements_t tm){
if(rtcType == DS3231){
time_t t = makeTime(tm);
rtc_ds.set(t);
}else{
time_t t = makeTime(tm); //make and break to calculate tm.Wday
breakTime(t, tm);
//day, weekday, month, century(1=1900, 0=2000), year(0-99)
rtc_pcf.setDate(tm.Day, tm.Wday - 1, tm.Month, 0, tmYearToY2k(tm.Year)); //TimeLib & DS3231 has Wday range of 1-7, but PCF8563 stores day of week in 0-6 range
//hr, min, sec
rtc_pcf.setTime(tm.Hour, tm.Minute, tm.Second);
clearAlarm();
}
if(rtcType == DS3231){
time_t t = makeTime(tm);
rtc_ds.set(t);
}else{
time_t t = makeTime(tm); //make and break to calculate tm.Wday
breakTime(t, tm);
//day, weekday, month, century(1=1900, 0=2000), year(0-99)
rtc_pcf.setDate(tm.Day, tm.Wday - 1, tm.Month, 0, tmYearToY2k(tm.Year)); //TimeLib & DS3231 has Wday range of 1-7, but PCF8563 stores day of week in 0-6 range
//hr, min, sec
rtc_pcf.setTime(tm.Hour, tm.Minute, tm.Second);
clearAlarm();
}
}
uint8_t WatchyRTC::temperature(){
if(rtcType == DS3231){
return rtc_ds.temperature();
}else{
return 255; //error
}
if(rtcType == DS3231){
return rtc_ds.temperature();
}else{
return 255; //error
}
}
void WatchyRTC::_DSConfig(String datetime){ //String datetime is YYYY:MM:DD:HH:MM:SS
if(datetime != ""){
tmElements_t tm;
tm.Year = CalendarYrToTm(_getValue(datetime, ':', 0).toInt()); //YYYY - 1970
tm.Month = _getValue(datetime, ':', 1).toInt();
tm.Day = _getValue(datetime, ':', 2).toInt();
tm.Hour = _getValue(datetime, ':', 3).toInt();
tm.Minute = _getValue(datetime, ':', 4).toInt();
tm.Second = _getValue(datetime, ':', 5).toInt();
time_t t = makeTime(tm);
rtc_ds.set(t);
}
//https://github.com/JChristensen/DS3232RTC
rtc_ds.squareWave(SQWAVE_NONE); //disable square wave output
rtc_ds.setAlarm(ALM2_EVERY_MINUTE, 0, 0, 0, 0); //alarm wakes up Watchy every minute
rtc_ds.alarmInterrupt(ALARM_2, true); //enable alarm interrupt
if(datetime != ""){
tmElements_t tm;
tm.Year = CalendarYrToTm(_getValue(datetime, ':', 0).toInt()); //YYYY - 1970
tm.Month = _getValue(datetime, ':', 1).toInt();
tm.Day = _getValue(datetime, ':', 2).toInt();
tm.Hour = _getValue(datetime, ':', 3).toInt();
tm.Minute = _getValue(datetime, ':', 4).toInt();
tm.Second = _getValue(datetime, ':', 5).toInt();
time_t t = makeTime(tm);
rtc_ds.set(t);
}
//https://github.com/JChristensen/DS3232RTC
rtc_ds.squareWave(SQWAVE_NONE); //disable square wave output
rtc_ds.setAlarm(ALM2_EVERY_MINUTE, 0, 0, 0, 0); //alarm wakes up Watchy every minute
rtc_ds.alarmInterrupt(ALARM_2, true); //enable alarm interrupt
}
void WatchyRTC::_PCFConfig(String datetime){ //String datetime is YYYY:MM:DD:HH:MM:SS
if(datetime != ""){
tmElements_t tm;
tm.Year = CalendarYrToTm(_getValue(datetime, ':', 0).toInt()); //YYYY - 1970
tm.Month = _getValue(datetime, ':', 1).toInt();
tm.Day = _getValue(datetime, ':', 2).toInt();
tm.Hour = _getValue(datetime, ':', 3).toInt();
tm.Minute = _getValue(datetime, ':', 4).toInt();
tm.Second = _getValue(datetime, ':', 5).toInt();
time_t t = makeTime(tm); //make and break to calculate tm.Wday
breakTime(t, tm);
//day, weekday, month, century(1=1900, 0=2000), year(0-99)
rtc_pcf.setDate(tm.Day, tm.Wday - 1, tm.Month, 0, tmYearToY2k(tm.Year)); //TimeLib & DS3231 has Wday range of 1-7, but PCF8563 stores day of week in 0-6 range
//hr, min, sec
rtc_pcf.setTime(tm.Hour, tm.Minute, tm.Second);
}
//on POR event, PCF8563 sets month to 0, which will give an error since months are 1-12
clearAlarm();
if(datetime != ""){
tmElements_t tm;
tm.Year = CalendarYrToTm(_getValue(datetime, ':', 0).toInt()); //YYYY - 1970
tm.Month = _getValue(datetime, ':', 1).toInt();
tm.Day = _getValue(datetime, ':', 2).toInt();
tm.Hour = _getValue(datetime, ':', 3).toInt();
tm.Minute = _getValue(datetime, ':', 4).toInt();
tm.Second = _getValue(datetime, ':', 5).toInt();
time_t t = makeTime(tm); //make and break to calculate tm.Wday
breakTime(t, tm);
//day, weekday, month, century(1=1900, 0=2000), year(0-99)
rtc_pcf.setDate(tm.Day, tm.Wday - 1, tm.Month, 0, tmYearToY2k(tm.Year)); //TimeLib & DS3231 has Wday range of 1-7, but PCF8563 stores day of week in 0-6 range
//hr, min, sec
rtc_pcf.setTime(tm.Hour, tm.Minute, tm.Second);
}
//on POR event, PCF8563 sets month to 0, which will give an error since months are 1-12
clearAlarm();
}
String WatchyRTC::_getValue(String data, char separator, int index)
@ -122,11 +126,11 @@ String WatchyRTC::_getValue(String data, char separator, int index)
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;
}
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]) : "";

View File

@ -30,9 +30,6 @@
namespace watchy_config
{
// Menu
constexpr std::int8_t kWatchFace_State{-1};
namespace display
{
// Display
@ -46,16 +43,32 @@ constexpr std::uint8_t reset{9};
constexpr std::uint8_t busy{19};
};
namespace pins
{
// RTC pins
constexpr gpio_num_t rtc_pin{GPIO_NUM_27};
#define ARDUINO_WATCHY_V20 1
#if defined (ARDUINO_WATCHY_V10)
constexpr std::uint64_t up_btn_mask{GPIO_SEL_32};
#elif defined (ARDUINO_WATCHY_V15)
constexpr std::uint64_t up_btn_mask{GPIO_SEL_32};
#elif defined (ARDUINO_WATCHY_V20)
constexpr std::uint64_t up_btn_mask{GPIO_SEL_35};
constexpr std:: uint8_t batt_adc_pin{34};
#endif
// btn pins & masks
constexpr std::uint64_t menu_btn_mask{GPIO_SEL_26};
constexpr std::uint64_t back_btn_mask{GPIO_SEL_25};
constexpr std::uint64_t up_btn_mask{GPIO_SEL_32};
constexpr std::uint64_t down_btn_mask{GPIO_SEL_4};
constexpr std::uint64_t btn_pin_mask{menu_btn_mask|back_btn_mask|up_btn_mask|down_btn_mask};
};
};
namespace wc = watchy_config;
namespace wcd = watchy_config::display;
namespace wcp = watchy_config::pins;