diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f4c787f6..eb755019 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -31,8 +31,11 @@ list(APPEND SOURCE_FILES Logging/NrfLogger.cpp BlinkApp/BlinkApp.cpp DisplayApp/DisplayApp.cpp - DisplayApp/lcdfont70.c - DisplayApp/lcdfont14.c + DisplayApp/Fonts/lcdfont70.c + DisplayApp/Fonts/lcdfont14.c + DisplayApp/Screens/Screen.cpp + DisplayApp/Screens/Clock.cpp + DisplayApp/Screens/Message.cpp main.cpp drivers/St7789.cpp drivers/SpiMaster.cpp @@ -52,8 +55,11 @@ set(INCLUDE_FILES Logging/NrfLogger.h BlinkApp/BlinkApp.h DisplayApp/DisplayApp.h - DisplayApp/lcdfont70.h - DisplayApp/lcdfont14.h + DisplayApp/Fonts/lcdfont70.h + DisplayApp/Fonts/lcdfont14.h + DisplayApp/Screens/Screen.h + DisplayApp/Screens/Clock.h + DisplayApp/Screens/Message.h drivers/St7789.h drivers/SpiMaster.h Components/Gfx/Gfx.h diff --git a/src/Components/DateTime/DateTimeController.h b/src/Components/DateTime/DateTimeController.h index 632fafe6..9e7392cd 100644 --- a/src/Components/DateTime/DateTimeController.h +++ b/src/Components/DateTime/DateTimeController.h @@ -19,6 +19,8 @@ namespace Pinetime { uint8_t Hours() const { return hour; } uint8_t Minutes() const { return minute; } uint8_t Seconds() const { return second; } + + std::chrono::time_point CurrentDateTime() const { return currentDateTime; } private: uint16_t year = 0; Months month = Months::Unknown; diff --git a/src/Components/Gfx/Gfx.cpp b/src/Components/Gfx/Gfx.cpp index 50516f7d..9e680687 100644 --- a/src/Components/Gfx/Gfx.cpp +++ b/src/Components/Gfx/Gfx.cpp @@ -4,6 +4,9 @@ using namespace Pinetime::Components; Gfx::Gfx(Pinetime::Drivers::St7789 &lcd) : lcd{lcd} { +} + +void Gfx::Init() { lcd.Init(); } diff --git a/src/Components/Gfx/Gfx.h b/src/Components/Gfx/Gfx.h index bc450846..9bd07fee 100644 --- a/src/Components/Gfx/Gfx.h +++ b/src/Components/Gfx/Gfx.h @@ -11,6 +11,7 @@ namespace Pinetime { class Gfx { public: explicit Gfx(Drivers::St7789& lcd); + void Init(); void ClearScreen(); void DrawString(uint8_t x, uint8_t y, uint16_t color, const char* text, const FONT_INFO *p_font, bool wrap); void DrawChar(const FONT_INFO *font, uint8_t c, uint8_t *x, uint8_t y, uint16_t color); diff --git a/src/DisplayApp/DisplayApp.cpp b/src/DisplayApp/DisplayApp.cpp index f37cee98..3fa0749e 100644 --- a/src/DisplayApp/DisplayApp.cpp +++ b/src/DisplayApp/DisplayApp.cpp @@ -11,45 +11,22 @@ #include #include #include -#include -#include "../Version.h" using namespace Pinetime::Applications; -char const *DisplayApp::DaysString[] = { - "", - "MONDAY", - "TUESDAY", - "WEDNESDAY", - "THURSDAY", - "FRIDAY", - "SATURDAY", - "SUNDAY" -}; - -char const *DisplayApp::MonthsString[] = { - "", - "JAN", - "FEB", - "MAR", - "APR", - "MAY", - "JUN", - "JUL", - "AUG", - "SEP", - "OCT", - "NOV", - "DEC" -}; - DisplayApp::DisplayApp(Controllers::Battery &batteryController, Controllers::Ble &bleController, Controllers::DateTime &dateTimeController) : + spi{}, + lcd{new Drivers::St7789(spi, 18)}, + gfx{new Components::Gfx(*lcd.get()) }, batteryController{batteryController}, bleController{bleController}, - dateTimeController{dateTimeController} { + dateTimeController{dateTimeController}, + clockScreen{*(gfx.get())}/*, + messageScreen{*(gfx.get())}*/ { msgQueue = xQueueCreate(queueSize, itemSize); + currentScreen = &clockScreen; } void DisplayApp::Start() { @@ -83,38 +60,9 @@ void DisplayApp::InitHw() { params.pinMOSI = 3; params.pinSCK = 2; spi.Init(Drivers::SpiMaster::SpiModule::SPI0, params); + gfx->Init(); - lcd.reset(new Drivers::St7789(spi, 18)); - gfx.reset(new Components::Gfx(*lcd.get())); - gfx->ClearScreen(); - - uint8_t x = 7; - gfx->DrawChar(&largeFont, '0', &x, 78, 0xffff); - - x = 61; - gfx->DrawChar(&largeFont, '0', &x, 78, 0xffff); - - x = 94; - gfx->DrawChar(&largeFont, ':', &x, 78, 0xffff); - - x = 127; - gfx->DrawChar(&largeFont, '0', &x, 78, 0xffff); - - x = 181; - gfx->DrawChar(&largeFont, '0', &x, 78, 0xffff); - - gfx->DrawString(10, 0, 0x0000, "BLE", &smallFont, false); - gfx->DrawString(20, 180, 0xffff, "", &smallFont, false); - - char version[20]; - sprintf(version, "VERSION: %d.%d.%d", Version::Major(), Version::Minor(), Version::Patch()); - gfx->DrawString(20, 220, 0xffff, version, &smallFont, false); - - - currentChar[0] = 0; - currentChar[1] = 0; - currentChar[2] = 0; - currentChar[3] = 0; + currentScreen->Refresh(true); touchPanel.Init(); } @@ -159,10 +107,10 @@ void DisplayApp::Refresh() { case Messages::UpdateDateTime: break; case Messages::UpdateBleConnection: - bleConnectionUpdated = true; + clockScreen.SetBleConnectionState(bleController.IsConnected() ? Screens::Clock::BleConnectionStates::Connected : Screens::Clock::BleConnectionStates::NotConnected); break; case Messages::UpdateBatteryLevel: - batteryLevelUpdated = true; + clockScreen.SetBatteryPercentRemaining(batteryController.PercentRemaining()); break; case Messages::TouchEvent: if(state != States::Running) break; @@ -173,77 +121,18 @@ void DisplayApp::Refresh() { } void DisplayApp::RunningState() { - if (batteryLevelUpdated) { - char batteryChar[11]; - uint16_t newBatteryValue = batteryController.PercentRemaining(); - newBatteryValue = (newBatteryValue > 100) ? 100 : newBatteryValue; - newBatteryValue = (newBatteryValue < 0) ? 0 : newBatteryValue; + clockScreen.SetCurrentDateTime(dateTimeController.CurrentDateTime()); - batteryLevelUpdated = false; - sprintf(batteryChar, "BAT: %d%%", newBatteryValue); - gfx->DrawString((240 - 108), 0, 0xffff, batteryChar, &smallFont, false); + if(currentScreen != nullptr) { + currentScreen->Refresh(false); } - if (bleConnectionUpdated) { - bleConnectionUpdated = false; - uint16_t color = (bleController.IsConnected()) ? 0xffff : 0x0000; - gfx->DrawString(10, 0, color, "BLE", &smallFont, false); - } - - char minutesChar[3]; - sprintf(minutesChar, "%02d", dateTimeController.Minutes()); - - char hoursChar[3]; - sprintf(hoursChar, "%02d", dateTimeController.Hours()); - - uint8_t x = 7; - if (hoursChar[0] != currentChar[0]) { - gfx->DrawChar(&largeFont, hoursChar[0], &x, 78, 0xffff); - currentChar[0] = hoursChar[0]; - } - - x = 61; - if (hoursChar[1] != currentChar[1]) { - gfx->DrawChar(&largeFont, hoursChar[1], &x, 78, 0xffff); - currentChar[1] = hoursChar[1]; - } - - x = 127; - if (minutesChar[0] != currentChar[2]) { - gfx->DrawChar(&largeFont, minutesChar[0], &x, 78, 0xffff); - currentChar[2] = minutesChar[0]; - } - - x = 181; - if (minutesChar[1] != currentChar[3]) { - gfx->DrawChar(&largeFont, minutesChar[1], &x, 78, 0xffff); - currentChar[3] = minutesChar[1]; - } - - auto y = dateTimeController.Year(); - auto m = dateTimeController.Month(); - auto wd = dateTimeController.DayOfWeek(); - auto d = dateTimeController.Day(); - - if ((y != currentYear) || (m != currentMonth) || (wd != currentDayOfWeek) || (d != currentDay)) { - gfx->FillRectangle(0,180, 240, 15, 0x0000); - char dateStr[22]; - sprintf(dateStr, "%s %d %s %d", DayOfWeekToString(wd), d, MonthToString(m), y); - gfx->DrawString(10, 180, 0xffff, dateStr, &smallFont, false); - - currentYear = y; - currentMonth = m; - currentDayOfWeek = wd; - currentDay = d; - } -} - -const char *DisplayApp::MonthToString(Pinetime::Controllers::DateTime::Months month) { - return DisplayApp::MonthsString[static_cast(month)]; -} - -const char *DisplayApp::DayOfWeekToString(Pinetime::Controllers::DateTime::Days dayOfWeek) { - return DisplayApp::DaysString[static_cast(dayOfWeek)]; +// if(screenState) { +// currentScreen = &clockScreen; +// } else { +// currentScreen = &messageScreen; +// } +// screenState = !screenState; } diff --git a/src/DisplayApp/DisplayApp.h b/src/DisplayApp/DisplayApp.h index 8e92c7bb..b2a4128d 100644 --- a/src/DisplayApp/DisplayApp.h +++ b/src/DisplayApp/DisplayApp.h @@ -9,10 +9,11 @@ #include #include #include -#include "lcdfont14.h" +#include "Fonts/lcdfont14.h" #include "../drivers/Cst816s.h" #include - +#include +#include extern const FONT_INFO lCD_70ptFontInfo; @@ -39,15 +40,6 @@ namespace Pinetime { const FONT_INFO smallFont {lCD_14ptFontInfo.height, lCD_14ptFontInfo.startChar, lCD_14ptFontInfo.endChar, lCD_14ptFontInfo.spacePixels, lCD_14ptFontInfo.charInfo, lCD_14ptFontInfo.data}; void Refresh(); - static const char* MonthToString(Pinetime::Controllers::DateTime::Months month); - static const char* DayOfWeekToString(Pinetime::Controllers::DateTime::Days dayOfWeek); - - char currentChar[4]; - uint16_t currentYear = 1970; - Pinetime::Controllers::DateTime::Months currentMonth = Pinetime::Controllers::DateTime::Months::Unknown; - Pinetime::Controllers::DateTime::Days currentDayOfWeek = Pinetime::Controllers::DateTime::Days::Unknown; - uint8_t currentDay = 0; - States state = States::Running; void RunningState(); void IdleState(); @@ -59,14 +51,14 @@ namespace Pinetime { Pinetime::Controllers::Battery &batteryController; Pinetime::Controllers::Ble &bleController; Pinetime::Controllers::DateTime& dateTimeController; - bool bleConnectionUpdated = false; - bool batteryLevelUpdated = false; - - static char const *DaysString[]; - static char const *MonthsString[]; Pinetime::Drivers::Cst816S touchPanel; void OnTouchEvent(); + + Screens::Clock clockScreen; + Screens::Screen* currentScreen = nullptr; +// Screens::Message messageScreen; +// bool screenState = false; }; } } diff --git a/src/DisplayApp/lcdfont14.c b/src/DisplayApp/Fonts/lcdfont14.c similarity index 100% rename from src/DisplayApp/lcdfont14.c rename to src/DisplayApp/Fonts/lcdfont14.c diff --git a/src/DisplayApp/lcdfont14.h b/src/DisplayApp/Fonts/lcdfont14.h similarity index 100% rename from src/DisplayApp/lcdfont14.h rename to src/DisplayApp/Fonts/lcdfont14.h diff --git a/src/DisplayApp/lcdfont70.c b/src/DisplayApp/Fonts/lcdfont70.c similarity index 100% rename from src/DisplayApp/lcdfont70.c rename to src/DisplayApp/Fonts/lcdfont70.c diff --git a/src/DisplayApp/lcdfont70.h b/src/DisplayApp/Fonts/lcdfont70.h similarity index 74% rename from src/DisplayApp/lcdfont70.h rename to src/DisplayApp/Fonts/lcdfont70.h index 232dc891..80b5dc15 100644 --- a/src/DisplayApp/lcdfont70.h +++ b/src/DisplayApp/Fonts/lcdfont70.h @@ -1,5 +1,5 @@ // Font data for LCD 70pt -extern const uint_8 lCD_70ptBitmaps[]; +extern const uint8_t lCD_70ptBitmaps[]; extern const FONT_INFO lCD_70ptFontInfo; extern const FONT_CHAR_INFO lCD_70ptDescriptors[]; diff --git a/src/DisplayApp/Screens/Clock.cpp b/src/DisplayApp/Screens/Clock.cpp new file mode 100644 index 00000000..153f4f2e --- /dev/null +++ b/src/DisplayApp/Screens/Clock.cpp @@ -0,0 +1,133 @@ +#include +#include +#include +#include +#include "Clock.h" + +using namespace Pinetime::Applications::Screens; + +void Clock::Refresh(bool fullRefresh) { + if(fullRefresh) { + gfx.FillRectangle(0,0,240,240,0x0000); + currentChar[0] = 0; + currentChar[1] = 0; + currentChar[2] = 0; + currentChar[3] = 0; + auto dummy = currentDateTime.Get(); + } + + if (fullRefresh || batteryPercentRemaining.IsUpdated()) { + char batteryChar[11]; + auto newBatteryValue = batteryPercentRemaining.Get(); + newBatteryValue = (newBatteryValue > 100) ? 100 : newBatteryValue; + newBatteryValue = (newBatteryValue < 0) ? 0 : newBatteryValue; + + sprintf(batteryChar, "BAT: %d%%", newBatteryValue); + gfx.DrawString((240 - 108), 0, 0xffff, batteryChar, &smallFont, false); + } + + if (fullRefresh || bleState.IsUpdated()) { + uint16_t color = (bleState.Get() == BleConnectionStates::Connected) ? 0xffff : 0x0000; + gfx.DrawString(10, 0, color, "BLE", &smallFont, false); + } + + if(fullRefresh || currentDateTime.IsUpdated()) { + auto newDateTime = currentDateTime.Get(); + + auto dp = date::floor(newDateTime); + auto time = date::make_time(newDateTime-dp); + auto yearMonthDay = date::year_month_day(dp); + + auto year = (int)yearMonthDay.year(); + auto month = static_cast((unsigned)yearMonthDay.month()); + auto day = (unsigned)yearMonthDay.day(); + auto dayOfWeek = static_cast(date::weekday(yearMonthDay).iso_encoding()); + + auto hour = time.hours().count(); + auto minute = time.minutes().count(); + auto second = time.seconds().count(); + + char minutesChar[3]; + sprintf(minutesChar, "%02d", minute); + + char hoursChar[3]; + sprintf(hoursChar, "%02d", hour); + + uint8_t x = 7; + if (hoursChar[0] != currentChar[0]) { + gfx.DrawChar(&largeFont, hoursChar[0], &x, 78, 0xffff); + currentChar[0] = hoursChar[0]; + } + + x = 61; + if (hoursChar[1] != currentChar[1]) { + gfx.DrawChar(&largeFont, hoursChar[1], &x, 78, 0xffff); + currentChar[1] = hoursChar[1]; + } + + x = 127; + if (minutesChar[0] != currentChar[2]) { + gfx.DrawChar(&largeFont, minutesChar[0], &x, 78, 0xffff); + currentChar[2] = minutesChar[0]; + } + + x = 181; + if (minutesChar[1] != currentChar[3]) { + gfx.DrawChar(&largeFont, minutesChar[1], &x, 78, 0xffff); + currentChar[3] = minutesChar[1]; + } + + if ((year != currentYear) || (month != currentMonth) || (dayOfWeek != currentDayOfWeek) || (day != currentDay)) { + gfx.FillRectangle(0,180, 240, 15, 0x0000); + char dateStr[22]; + sprintf(dateStr, "%s %d %s %d", DayOfWeekToString(dayOfWeek), day, MonthToString(month), year); + gfx.DrawString(10, 180, 0xffff, dateStr, &smallFont, false); + + currentYear = year; + currentMonth = month; + currentDayOfWeek = dayOfWeek; + currentDay = day; + } + } + + if(fullRefresh || version.IsUpdated()) { + char version[20]; + sprintf(version, "VERSION: %d.%d.%d", Version::Major(), Version::Minor(), Version::Patch()); + gfx.DrawString(20, 220, 0xffff, version, &smallFont, false); + } +} + +const char *Clock::MonthToString(Pinetime::Controllers::DateTime::Months month) { + return Clock::MonthsString[static_cast(month)]; +} + +const char *Clock::DayOfWeekToString(Pinetime::Controllers::DateTime::Days dayOfWeek) { + return Clock::DaysString[static_cast(dayOfWeek)]; +} + +char const *Clock::DaysString[] = { + "", + "MONDAY", + "TUESDAY", + "WEDNESDAY", + "THURSDAY", + "FRIDAY", + "SATURDAY", + "SUNDAY" +}; + +char const *Clock::MonthsString[] = { + "", + "JAN", + "FEB", + "MAR", + "APR", + "MAY", + "JUN", + "JUL", + "AUG", + "SEP", + "OCT", + "NOV", + "DEC" +}; diff --git a/src/DisplayApp/Screens/Clock.h b/src/DisplayApp/Screens/Clock.h new file mode 100644 index 00000000..12dd8850 --- /dev/null +++ b/src/DisplayApp/Screens/Clock.h @@ -0,0 +1,65 @@ +#pragma once + +#include +#include +#include +#include "Screen.h" +#include +#include "../Fonts/lcdfont14.h" +#include "../Fonts/lcdfont70.h" +#include "../../Version.h" + +namespace Pinetime { + namespace Applications { + namespace Screens { + + template + class DirtyValue { + public: + explicit DirtyValue(T v) { value = v; } + explicit DirtyValue(T& v) { value = v; } + bool IsUpdated() const { return isUpdated; } + T& Get() { return value; this->isUpdated = false;} + + DirtyValue& operator=(const T& other) { + this->value = other; + this->isUpdated = true; + return *this; + } + private: + T value; + bool isUpdated = true; + }; + class Clock : public Screen{ + public: + enum class BleConnectionStates{ NotConnected, Connected}; + Clock(Components::Gfx& gfx) : Screen(gfx), currentDateTime{{}}, version {{}} {} + void Refresh(bool fullRefresh) override; + + void SetBatteryPercentRemaining(uint8_t percent) { batteryPercentRemaining = percent; } + void SetBleConnectionState(BleConnectionStates state) { bleState = state; } + void SetCurrentDateTime(const std::chrono::time_point& tp) { currentDateTime = tp;} + + private: + static const char* MonthToString(Pinetime::Controllers::DateTime::Months month); + static const char* DayOfWeekToString(Pinetime::Controllers::DateTime::Days dayOfWeek); + static char const *DaysString[]; + static char const *MonthsString[]; + + const FONT_INFO largeFont {lCD_70ptFontInfo.height, lCD_70ptFontInfo.startChar, lCD_70ptFontInfo.endChar, lCD_70ptFontInfo.spacePixels, lCD_70ptFontInfo.charInfo, lCD_70ptFontInfo.data}; + const FONT_INFO smallFont {lCD_14ptFontInfo.height, lCD_14ptFontInfo.startChar, lCD_14ptFontInfo.endChar, lCD_14ptFontInfo.spacePixels, lCD_14ptFontInfo.charInfo, lCD_14ptFontInfo.data}; + + char currentChar[4]; + uint16_t currentYear = 1970; + Pinetime::Controllers::DateTime::Months currentMonth = Pinetime::Controllers::DateTime::Months::Unknown; + Pinetime::Controllers::DateTime::Days currentDayOfWeek = Pinetime::Controllers::DateTime::Days::Unknown; + uint8_t currentDay = 0; + + DirtyValue batteryPercentRemaining {0}; + DirtyValue bleState {BleConnectionStates::NotConnected}; + DirtyValue> currentDateTime; + DirtyValue version; + }; + } + } +} diff --git a/src/DisplayApp/Screens/Message.cpp b/src/DisplayApp/Screens/Message.cpp new file mode 100644 index 00000000..2ade4349 --- /dev/null +++ b/src/DisplayApp/Screens/Message.cpp @@ -0,0 +1,14 @@ +#include +#include +#include +#include +#include "Message.h" + +using namespace Pinetime::Applications::Screens; + +void Message::Refresh(bool fullRefresh) { + if(fullRefresh) { + gfx.FillRectangle(0,0,240,240,0xffff); + gfx.DrawString(120, 10, 0x0000, "COUCOU", &smallFont, false); + } +} diff --git a/src/DisplayApp/Screens/Message.h b/src/DisplayApp/Screens/Message.h new file mode 100644 index 00000000..ac300faf --- /dev/null +++ b/src/DisplayApp/Screens/Message.h @@ -0,0 +1,26 @@ +#pragma once + +#include +#include +#include +#include "Screen.h" +#include +#include "../Fonts/lcdfont14.h" +#include "../Fonts/lcdfont70.h" +#include "../../Version.h" + +namespace Pinetime { + namespace Applications { + namespace Screens { + class Message : public Screen{ + public: + Message(Components::Gfx& gfx) : Screen(gfx) {} + void Refresh(bool fullRefresh) override; + + private: + const FONT_INFO largeFont {lCD_70ptFontInfo.height, lCD_70ptFontInfo.startChar, lCD_70ptFontInfo.endChar, lCD_70ptFontInfo.spacePixels, lCD_70ptFontInfo.charInfo, lCD_70ptFontInfo.data}; + const FONT_INFO smallFont {lCD_14ptFontInfo.height, lCD_14ptFontInfo.startChar, lCD_14ptFontInfo.endChar, lCD_14ptFontInfo.spacePixels, lCD_14ptFontInfo.charInfo, lCD_14ptFontInfo.data}; + }; + } + } +} diff --git a/src/DisplayApp/Screens/Screen.cpp b/src/DisplayApp/Screens/Screen.cpp new file mode 100644 index 00000000..1467df33 --- /dev/null +++ b/src/DisplayApp/Screens/Screen.cpp @@ -0,0 +1,2 @@ +#include "Screen.h" +using namespace Pinetime::Applications::Screens; \ No newline at end of file diff --git a/src/DisplayApp/Screens/Screen.h b/src/DisplayApp/Screens/Screen.h new file mode 100644 index 00000000..5e2fa43e --- /dev/null +++ b/src/DisplayApp/Screens/Screen.h @@ -0,0 +1,18 @@ +#pragma once + +#include + +namespace Pinetime { + namespace Applications { + namespace Screens { + class Screen { + public: + Screen(Components::Gfx& gfx) : gfx{gfx} {} + virtual void Refresh(bool fullRefresh) = 0; + + protected: + Components::Gfx& gfx; + }; + } + } +}