@$(NRFUTIL) dfu genpkg --dev-type 0x0052 --application $(OUTHEX) \
$(OUTDFU)
+cleancpp:
+ @echo " CLEAN"
+ @rm -f $(OBJ) $(OUTELF) $(OUTHEX) $(OUTDFU)
+
clean:
@echo " CLEAN"
@rm -f $(OBJ) $(OUTELF) $(OUTHEX) $(OUTDFU)
#include <bluefruit.h>
-#include "sharp.hpp"
#include "rtc.hpp"
+#include "sharp.hpp"
+#include "widget.hpp"
BLEUart bleuart;
Bluefruit.Advertising.start(0); // 0 = Don't stop advertising after n seconds
Serial.println(F("Ready."));
- Sharp::setScreen(RTC::showTime);
+ Sharp::addWidget<TimeWidget>();
+ Sharp::addWidget<NotificationWidget>("Welcome to smartwatch");
}
void loop(void)
void handlePacket(void)
{
char buf[64];
- char *p = buf;
- do {
- *p++ = bleuart.read();
- } while (bleuart.available());
- *p = '\0';
+ unsigned int i;
+ for (i = 0; bleuart.available() && i < 63; i++)
+ buf[i] = bleuart.read();
+ buf[i] = '\0';
switch (buf[0]) {
case 'L':
- RTC::setMessage(buf + 1);
+ //RTC::setMessage(buf + 1);
break;
case 'T':
- Serial.println("Setting time!");
+ Sharp::addWidget<NotificationWidget>("Time updated");
RTC::setTicks(std::atoi(buf + 1) * 60);
break;
default:
nrf_drv_rtc_t RTC::rtc = NRF_DRV_RTC_INSTANCE(2);
unsigned int RTC::rtcCount = 0;
-char RTC::message[16] = "";
-
void RTC::begin(void)
{
//Initialize RTC instance
nrf_drv_rtc_enable(&rtc);
}
-void RTC::showTime(Display& display)
-{
- static unsigned int oldTicks = 0;
- if (auto t = rtcCount; t != oldTicks) {
- oldTicks = t;
-
- display.setCursor(0, 10);
- display.printf("%2d:%02d:%02d", t / 3600, (t % 3600) / 60,
- t % 60);
- if (*message != '\0') {
- display.setCursor(0, 100);
- display.printf("%-16s", message);
- }
- }
-}
-
void RTC::handler([[maybe_unused]] nrf_drv_rtc_int_type_t int_type)
{
static unsigned char counter = 0;
+#ifndef RTC_HPP_
+#define RTC_HPP_
+
#include <rtc/nrf_drv_rtc.h>
#include "sharp.hpp"
static nrf_drv_rtc_t rtc;
static unsigned int rtcCount;
- static char message[16];
-
public:
static void begin(void);
rtcCount = t;
}
- static void showTime(Display& display);
-
- inline static void setMessage(const char *s) {
- strncpy(message, s, 16);
- }
-
private:
static void handler(nrf_drv_rtc_int_type_t type);
};
+#endif // RTC_HPP_
+
#include "sharp.hpp"
#include "rtc.hpp"
+constexpr unsigned int SHARP_WIDTH = 144;
+constexpr unsigned int SHARP_HEIGHT = 168;
+
constexpr unsigned int SHARP_SCK = 12;
constexpr unsigned int SHARP_MOSI = 13;
constexpr unsigned int SHARP_SS = 14;
-Adafruit_SharpMem Sharp::display(SHARP_SCK, SHARP_MOSI, SHARP_SS, 144, 168);
+Adafruit_SharpMem Sharp::display(SHARP_SCK, SHARP_MOSI, SHARP_SS, SHARP_WIDTH,
+ SHARP_HEIGHT);
TaskHandle_t Sharp::taskHandle;
-bool Sharp::holdRendering = false;
-RenderFunc Sharp::currentScreen;
-
-#define BLACK 0
-#define WHITE 1
+std::vector<Widget *> Sharp::widgets;
void Sharp::begin(void)
{
+ widgets.reserve(10);
display.begin();
display.clearDisplay();
display.setTextSize(3);
void Sharp::updateTask([[maybe_unused]] void *arg)
{
- static auto old = RTC::ticks();
while (1) {
- do {
- delay(300);
- } while (holdRendering);
+ unsigned int y = 0;
+ for (auto& w : widgets) {
+ w->render(display, y);
+ y += w->getHeight();
+ display.drawFastHLine(0, y + 1, SHARP_WIDTH, BLACK);
+ y += 3;
+ if (y >= SHARP_HEIGHT)
+ break;
+ }
- if (currentScreen)
- currentScreen(display);
display.refresh();
+ delay(300);
}
}
#define SHARP_HPP_
#include "sharp/Adafruit_SharpMem.h"
+#include "widget.hpp"
-#include <functional>
+#include <vector>
-using RenderFunc = std::function<void(Adafruit_GFX&)>;
-using Display = Adafruit_GFX;
+#define BLACK 0
+#define WHITE 1
class Sharp {
private:
static Adafruit_SharpMem display;
static TaskHandle_t taskHandle;
- static bool holdRendering;
-
- static RenderFunc currentScreen;
+ static std::vector<Widget *> widgets;
public:
static void begin(void);
- inline static void pause(void) {
- holdRendering = true;
- }
-
- inline static void unpause(void) {
- holdRendering = false;
- }
-
- inline static void setScreen(const RenderFunc& rf) {
- currentScreen = rf;
+ template<class T, typename... Args>
+ inline static void addWidget(Args... args) {
+ widgets.emplace_back(new T(args...));
}
private:
--- /dev/null
+#include "rtc.hpp"
+#include "widget.hpp"
+
+void TimeWidget::render(Adafruit_GFX& display, unsigned int ypos)
+{
+ if (auto t = RTC::ticks(); t != prevTicks) {
+ prevTicks = t;
+ display.setTextSize(3);
+ display.setCursor(0, ypos + 4);
+ display.printf("%2d:%02d:%02d", t / 3600, (t % 3600) /
+ 60, t % 60);
+ }
+}
+
+void NotificationWidget::render(Adafruit_GFX& display, unsigned int ypos)
+{
+ display.setTextSize(2);
+ display.setCursor(0, ypos);
+ display.printf("%-36s", message);
+}
--- /dev/null
+#ifndef WIDGET_HPP_
+#define WIDGET_HPP_
+
+class Adafruit_GFX;
+
+#include <cstring>
+
+class Widget {
+private:
+ unsigned int height;
+public:
+ constexpr Widget(unsigned int _height = 0)
+ : height(_height) {}
+
+ inline unsigned int getHeight(void) const {
+ return height;
+ }
+
+ virtual void render(Adafruit_GFX& display, unsigned int ypos) = 0;
+
+protected:
+ inline void setHeight(unsigned int _height) {
+ height = _height;
+ }
+};
+
+class TimeWidget : public Widget {
+private:
+ unsigned int prevTicks;
+
+public:
+ constexpr TimeWidget(void)
+ : Widget(30), prevTicks(0) {}
+
+ void render(Adafruit_GFX& display, unsigned int ypos) final;
+};
+
+class NotificationWidget : public Widget {
+private:
+ char message[36];
+
+public:
+ NotificationWidget(const char *msg)
+ : Widget(48) {
+ unsigned int i;
+ for (i = 0; msg[i] != '\0' && i < 35; i++)
+ message[i] = msg[i];
+ message[i] = '\0';
+ setHeight(16 * (i / 12 + 1));
+ }
+
+ void render(Adafruit_GFX& display, unsigned int ypos) final;
+};
+#endif // WIDGET_HPP_