aboutsummaryrefslogtreecommitdiff
path: root/display.h
blob: 7a6031726fdd3b2517aa88417f2da693feddd180 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#pragma once
 
#define LILYGO_T5_V213 // needed for the display libraries 
 
#include <boards.h>
#include <GxEPD.h>
#include <GxGDEH0213B73/GxGDEH0213B73.h>  // screen model, probably correct 
#include <Fonts/FreeMonoBold9pt7b.h>
#include <GxIO/GxIO_SPI/GxIO_SPI.h>
#include <GxIO/GxIO.h>
 
#include "data.h"
 
class TimeStr {
private:
  char str[10];
 
  unsigned long cut(unsigned long &val, unsigned long max) {
    unsigned long ret = val/max;
    val %= max;
    return ret;
  }
public:
  TimeStr() :str("000:00:00"{}
 
  const char *format(unsigned long now_millis) {
    unsigned long now_s = now_millis/1000;
    unsigned long now_m = cut(now_s,60);
    unsigned long now_h = cut(now_m,60);
 
    str[0]='0' + cut(now_h,100);
    str[1]='0' + cut(now_h,10);
    str[2]='0' + now_h;
 
    str[4]='0' + cut(now_m,10);
    str[5]='0' + now_m;
 
    str[7]='0' + cut(now_s,10);
    str[8]='0' + now_s;
 
    return &str[0];
  }
};
 
/*
  most of this comes from
  https://github.com/Xinyuan-LilyGO/LilyGo-T5-Epaper-Series/blob/master/examples/GxEPD_Partial_Update_Example/GxEPD_Partial_Update_Example.ino
 */
class Display {
private:
  GxIO_Class io;
  GxEPD_Class display;
  TimeStr timeStr;
 
public:
  Display() :
    io(SPI, EPD_CS, EPD_DC, EPD_RSET),
    display(io, EPD_RSET, EPD_BUSY),
    timeStr()
  {}
 
  void start() {
    SPI.begin(EPD_SCLK, EPD_MISO, EPD_MOSI);
 
    display.init();
    display.setTextColor(GxEPD_BLACK);
    display.setRotation(3);
    display.setFont(&FreeMonoBold9pt7b);
    display.fillScreen(GxEPD_WHITE);
    display.update();
  }
 
  void show(const SensorData *data) {
    display.fillScreen(GxEPD_WHITE);
 
    display.setCursor(0,10);
    display.print("Co2 ");
    display.print(data->co2);
 
    display.setCursor(100,10);
    display.print("t");
    display.print(data->temperature,1);
 
    display.setCursor(160,10);
    display.print(" h");
    display.print(data->humidity,0);
    display.print("%");
 
    display.setCursor(0,30);
    display.println("   PM");
    // PM measurements include particles "up to" that size, but we 
    // want to display the values for *that* size 
    display.print(" 1.0 "); display.println(data->pm.mc_1p0,1);
    display.print(" 2.5 "); display.println(max(0.0f,data->pm.mc_2p5 - data->pm.mc_1p0),1);
    display.print(" 4.0 "); display.println(max(0.0f,data->pm.mc_4p0 - data->pm.mc_2p5),1);
    display.print("10.0 "); display.println(max(0.0f,data->pm.mc_10p0 - data->pm.mc_4p0),1);
 
    display.setCursor(120,30);
    display.print("Batt "); display.print(data->batteryVoltage);
 
    display.setCursor(0,120);
    display.print("Uptime ");
    display.print(timeStr.format(millis()));
 
    // "partial" update 
    display.updateWindow(00, GxEPD_WIDTH, GxEPD_HEIGHT, false);
 
    display.powerDown();
  }
 
  bool serialCommand(const String &tag, const String &command) {
    return false;
  }
};