RSeries astromech firmware
CommandScreenDisplay.h
Go to the documentation of this file.
1 #ifndef CommandScreenDisplay_h
2 #define CommandScreenDisplay_h
3 
4 #include "ReelTwo.h"
5 #include "menus/CommandScreen.h"
7 
9 //
10 // Command screen handler for SSD 1306 using a rotary dial for events
11 //
13 
14 template <typename COMMAND_DISPLAY>
16 {
17 public:
18  CommandScreenDisplay(COMMAND_DISPLAY& display, PinManager &pinManager, bool (*init)(void) = nullptr) :
20  fDial(pinManager, PIN_ENCODER_A,
21  PIN_ENCODER_B,
22  BUTTON_UP,
23  BUTTON_LEFT,
24  BUTTON_DOWN,
25  BUTTON_RIGHT,
26  BUTTON_IN,
27  // TODO: Investigate. Performs significantly
28  // better without interrupts.
29  false),
30  fInitProc(init)
31  {
32  resetDisplay();
33  }
34 
35  bool begin()
36  {
37  return (fInitProc != nullptr) ? fInitProc() : true;
38  }
39 
40  virtual void wakeDevice() override
41  {
42  fDisplay.wakeDevice();
43  }
44 
45  virtual void sleepDevice() override
46  {
47  fDisplay.sleepDevice();
48  invertDisplay(false);
49  clearDisplay();
50  display();
51  switchToScreen(kMainScreen);
52  }
53 
54  inline void invertDisplay(bool invert)
55  {
56  #ifdef USE_SMQ
57  fInvert = invert;
58  #endif
59  fDisplay.invertDisplay(invert);
60  }
61 
62  inline void clearDisplay()
63  {
64  #ifdef USE_SMQ
65  fClearDisplay = true;
66  #endif
67  fDisplay.clearDisplay();
68  }
69 
70  inline void setTextSize(int siz)
71  {
72  #ifdef USE_SMQ
73  fTextSize = siz;
74  #endif
75  fDisplay.setTextSize(siz);
76  }
77 
78  inline void getTextBounds(const char *string, int16_t x, int16_t y,
79  int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h)
80  {
81  fDisplay.getTextBounds(string, x, y, x1, y1, w, h);
82  }
83 
84  void setRotation(uint8_t r)
85  {
86  fDisplay.setRotation(r);
87  }
88 
89  void setTextColor(uint16_t c)
90  {
91  fDisplay.setTextColor(c);
92  }
93 
94  void setCursor(uint8_t x, uint8_t y)
95  {
96  #ifdef USE_SMQ
97  fX = x;
98  fY = y;
99  #endif
100  fDisplay.setCursor(x, y);
101  }
102 
103  void print(String text)
104  {
105  #ifdef USE_SMQ
106  fString += text;
107  #endif
108  fDisplay.print(text);
109  }
110 
111  void println(unsigned val)
112  {
113  #ifdef USE_SMQ
114  fString += String("\n") + String(val);
115  #endif
116  fDisplay.println(val);
117  }
118 
119  void println(String text)
120  {
121  #ifdef USE_SMQ
122  fString += String("\n") + text;
123  #endif
124  fDisplay.println(text);
125  }
126 
127  void display()
128  {
129  fDisplay.display();
130  // #ifdef USE_SMQ
131  // if (SMQ::sendTopic("LCD", "Remote"))
132  // {
133  // SMQ::send_uint8("x", fX);
134  // SMQ::send_uint8("y", fY);
135  // SMQ::send_boolean("invert", fInvert);
136  // SMQ::send_boolean("centered", fCentered);
137  // SMQ::send_uint8("size", fTextSize);
138  // SMQ::send_string("text", fString.c_str());
139  // SMQ::sendEnd();
140  // resetDisplay();
141  // }
142  // #endif
143  }
144 
145  void drawTextCentered(String text)
146  {
147  int16_t x1, y1;
148  uint16_t w = 0, h;
149  fDisplay.getTextBounds(text, 0, 0, &x1, &y1, &w, &h);
150  fDisplay.setCursor(SCREEN_WIDTH / 2 - w / 2, 0);
151  fDisplay.print(text);
152  #ifdef USE_SMQ
153  fCentered = true;
154  fString = text;
155  #endif
156  }
157 
158  void remoteDialEvent(long newValue, long oldValue)
159  {
160  #ifdef USE_SMQ
161  fNewDialValue = newValue;
162  #endif
163  }
164 
165  void remoteButtonEvent(uint8_t id, bool pressed, bool repeat)
166  {
167  #ifdef USE_SMQ
168  fButtonID = id;
169  fButtonPressed = pressed;
170  fButtonRepeat = repeat;
171  #endif
172  }
173 
175  {
176  #ifdef USE_SMQ
177  setEnabled(true);
178  fRemoteActive = true;
179  #endif
180  }
181 
182  virtual bool handleEvent() override
183  {
184  bool ret = false;
185  #ifdef USE_SMQ
186  if (fRemoteActive)
187  {
188  switchToScreen(kMainScreen);
189  fRemoteActive = false;
190  }
191  #endif
192  CommandScreen* currentScr = current();
193  if (currentScr != nullptr)
194  {
195  #ifdef USE_SMQ
196  if (fDialValue != fNewDialValue || fButtonID != 0)
197  {
198  // Reset the screen blanking timer if the encoder changed
199  // or if any of the buttons are currently pressed
200  ret = true;
201  }
202  if (fDialValue != fNewDialValue)
203  {
204  currentScr->buttonDial(fNewDialValue, fDialValue);
205  fDialValue = fNewDialValue;
206  }
207  if (fButtonID)
208  {
209  if (fButtonID == 1 && fButtonPressed)
210  currentScr->buttonUpPressed();
211  if (fButtonID == 2 && fButtonPressed)
212  currentScr->buttonLeftPressed();
213  if (fButtonID == 3 && fButtonPressed)
214  currentScr->buttonDownPressed();
215  if (fButtonID == 4 && fButtonPressed)
216  currentScr->buttonRightPressed();
217  if (fButtonID == 5 && fButtonPressed)
218  currentScr->buttonInPressed();
219  if (fLastScreenID == currentScr->ID())
220  {
221  if (fButtonID == 1 && !fButtonPressed)
222  currentScr->buttonUpReleased();
223  if (fButtonID == 2 && !fButtonPressed)
224  currentScr->buttonLeftReleased();
225  if (fButtonID == 3 && !fButtonPressed)
226  currentScr->buttonDownReleased();
227  if (fButtonID == 4 && !fButtonPressed)
228  currentScr->buttonRightReleased();
229  if (fButtonID == 5 && !fButtonPressed)
230  currentScr->buttonInReleased();
231  }
232  fLastScreenID = currentScr->ID();
233  }
234  else if (fLastScreenID == currentScr->ID())
235  {
236  if (fButtonID == 1 && fButtonPressed && fButtonRepeat)
237  {
238  currentScr->buttonUpPressed(true);
239  }
240  else if (fButtonID == 2 && fButtonPressed && fButtonRepeat)
241  {
242  currentScr->buttonLeftPressed(true);
243  }
244  else if (fButtonID == 3 && fButtonPressed && fButtonRepeat)
245  {
246  currentScr->buttonDownPressed(true);
247  }
248  else if (fButtonID == 4 && fButtonPressed && fButtonRepeat)
249  {
250  currentScr->buttonRightPressed(true);
251  }
252  else if (fButtonID == 5 && fButtonPressed && fButtonRepeat)
253  {
254  currentScr->buttonInPressed(true);
255  }
256  }
257  #endif
258  unsigned keyRepeatRate = currentScr->getKeyRepeatRate();
259  if (keyRepeatRate == 0)
260  keyRepeatRate = KEY_REPEAT_RATE_MS;
261  if (fDial.hasChanged() || fDial.getButtonPressedMask() != 0)
262  {
263  // Reset the screen blanking timer if the encoder changed
264  // or if any of the buttons are currently pressed
265  if (isSleeping())
266  {
267  fSkipButtonReleased = true;
268  return true;
269  }
270  ret = true;
271  }
272  if (fDial.hasChanged())
273  {
274  long dialValue = -fDial.getValue();
275  currentScr->buttonDial(dialValue, fDialValue);
276  fDialValue = dialValue;
277  }
279  {
281  fSkipButtonReleased = false;
282  return true;
283  }
285  {
286  if (fDial.isButtonPressed(BUTTON_UP))
287  currentScr->buttonUpPressed();
288  if (fDial.isButtonPressed(BUTTON_LEFT))
289  currentScr->buttonLeftPressed();
290  if (fDial.isButtonPressed(BUTTON_DOWN))
291  currentScr->buttonDownPressed();
292  if (fDial.isButtonPressed(BUTTON_RIGHT))
293  currentScr->buttonRightPressed();
294  if (fDial.isButtonPressed(BUTTON_IN))
295  currentScr->buttonInPressed();
296  if (fLastScreenID == currentScr->ID())
297  {
298  if (fDial.isButtonReleased(BUTTON_UP))
299  currentScr->buttonUpReleased();
300  if (fDial.isButtonReleased(BUTTON_LEFT))
301  currentScr->buttonLeftReleased();
302  if (fDial.isButtonReleased(BUTTON_DOWN))
303  currentScr->buttonDownReleased();
304  if (fDial.isButtonReleased(BUTTON_RIGHT))
305  currentScr->buttonRightReleased();
306  if (fDial.isButtonReleased(BUTTON_IN))
307  currentScr->buttonInReleased();
308  }
309  fLastKeyEvent = millis();
310  fLastScreenID = currentScr->ID();
311  }
312  else if (fLastScreenID == currentScr->ID())
313  {
314  if (fDial.isButtonPressed(BUTTON_UP))
315  {
316  if (fLastKeyEvent + keyRepeatRate < millis())
317  {
318  currentScr->buttonUpPressed(true);
319  fLastKeyEvent = millis();
320  }
321  }
322  else if (fDial.isButtonPressed(BUTTON_LEFT))
323  {
324  if (fLastKeyEvent + keyRepeatRate < millis())
325  {
326  currentScr->buttonLeftPressed(true);
327  fLastKeyEvent = millis();
328  }
329  }
330  else if (fDial.isButtonPressed(BUTTON_DOWN))
331  {
332  if (fLastKeyEvent + keyRepeatRate < millis())
333  {
334  currentScr->buttonDownPressed(true);
335  fLastKeyEvent = millis();
336  }
337  }
338  else if (fDial.isButtonPressed(BUTTON_RIGHT))
339  {
340  if (fLastKeyEvent + keyRepeatRate < millis())
341  {
342  currentScr->buttonRightPressed(true);
343  fLastKeyEvent = millis();
344  }
345  }
346  else if (fDial.isButtonPressed(BUTTON_IN))
347  {
348  if (fLastKeyEvent + keyRepeatRate < millis())
349  {
350  currentScr->buttonInPressed(true);
351  fLastKeyEvent = millis();
352  }
353  }
354  }
355  }
356  #ifdef USE_SMQ
357  fButtonID = 0;
358  fButtonPressed = false;
359  fButtonRepeat = false;
360  fDialValue = fNewDialValue;
361  #endif
362  return ret;
363  }
364 
365  COMMAND_DISPLAY& fDisplay;
367  bool (*fInitProc)(void);
368  long fDialValue = 0;
369  uint32_t fLastKeyEvent = 0;
370  ScreenID fLastScreenID = kInvalid;
371  bool fSkipButtonReleased = false;
372 #ifdef USE_SMQ
373  long fNewDialValue = 0;
374  uint8_t fButtonID = 0;
375  bool fRemoteActive = false;
376  bool fButtonPressed = false;
377  bool fButtonRepeat = false;
378  bool fInvert;
379  bool fClearDisplay;
380  bool fCentered;
381  String fString;
382  uint8_t fX;
383  uint8_t fY;
384  uint8_t fTextSize;
385 #endif
386  inline void resetDisplay()
387  {
388  #ifdef USE_SMQ
389  fInvert = false;
390  fClearDisplay = false;
391  fTextSize = 0;
392  fCentered = false;
393  fString = "";
394  fX = 0;
395  fY = 0;
396  #endif
397  }
398 };
399 #endif
CommandScreenDisplay::display
void display()
Definition: CommandScreenDisplay.h:127
CommandScreen
Definition: CommandScreen.h:273
CommandScreenDisplay::setTextColor
void setTextColor(uint16_t c)
Definition: CommandScreenDisplay.h:89
CommandScreenDisplay::fLastKeyEvent
uint32_t fLastKeyEvent
Definition: CommandScreenDisplay.h:369
CommandScreen::buttonLeftPressed
virtual void buttonLeftPressed(bool repeat=false)
Definition: CommandScreen.h:328
CommandScreenDisplay::fLastScreenID
ScreenID fLastScreenID
Definition: CommandScreenDisplay.h:370
CommandScreen.h
CommandScreenHandler::switchToScreen
void switchToScreen(ScreenID id, bool popStack=true)
Definition: CommandScreen.h:175
CommandScreenDisplay::wakeDevice
virtual void wakeDevice() override
Definition: CommandScreenDisplay.h:40
ReelTwo.h
CommandScreenDisplay::getTextBounds
void getTextBounds(const char *string, int16_t x, int16_t y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h)
Definition: CommandScreenDisplay.h:78
CommandScreenHandler::current
CommandScreen * current()
Definition: CommandScreen.h:154
CommandScreenDisplay::CommandScreenDisplay
CommandScreenDisplay(COMMAND_DISPLAY &display, PinManager &pinManager, bool(*init)(void)=nullptr)
Definition: CommandScreenDisplay.h:18
AnoRotaryEncoder.h
CommandScreen::buttonInReleased
virtual void buttonInReleased()
Definition: CommandScreen.h:336
CommandScreenDisplay::sleepDevice
virtual void sleepDevice() override
Definition: CommandScreenDisplay.h:45
CommandScreenDisplay::println
void println(String text)
Definition: CommandScreenDisplay.h:119
AnoRotaryEncoder::getButtonPressedMask
uint8_t getButtonPressedMask() const
Definition: AnoRotaryEncoder.h:50
CommandScreenDisplay
Definition: CommandScreenDisplay.h:15
AnoRotaryEncoder
Definition: AnoRotaryEncoder.h:7
CommandScreenDisplay::clearDisplay
void clearDisplay()
Definition: CommandScreenDisplay.h:62
CommandScreenDisplay::drawTextCentered
void drawTextCentered(String text)
Definition: CommandScreenDisplay.h:145
CommandScreenHandler
Definition: CommandScreen.h:147
AnoRotaryEncoder::isButtonReleased
bool isButtonReleased(byte pin) const
Definition: AnoRotaryEncoder.h:71
RotaryEncoder::getValue
long getValue()
Returns current value.
Definition: RotaryEncoder.h:102
CommandScreenDisplay::fDialValue
long fDialValue
Definition: CommandScreenDisplay.h:368
CommandScreenHandler::setEnabled
void setEnabled(bool enabled)
Definition: CommandScreen.h:236
CommandScreenDisplay::resetDisplay
void resetDisplay()
Definition: CommandScreenDisplay.h:386
CommandScreenDisplay::fDial
AnoRotaryEncoder fDial
Definition: CommandScreenDisplay.h:366
CommandScreenDisplay::remoteActive
void remoteActive()
Definition: CommandScreenDisplay.h:174
CommandScreen::buttonRightPressed
virtual void buttonRightPressed(bool repeat=false)
Definition: CommandScreen.h:330
CommandScreenDisplay::setRotation
void setRotation(uint8_t r)
Definition: CommandScreenDisplay.h:84
CommandScreenDisplay::setCursor
void setCursor(uint8_t x, uint8_t y)
Definition: CommandScreenDisplay.h:94
CommandScreenDisplay::invertDisplay
void invertDisplay(bool invert)
Definition: CommandScreenDisplay.h:54
CommandScreenDisplay::remoteButtonEvent
void remoteButtonEvent(uint8_t id, bool pressed, bool repeat)
Definition: CommandScreenDisplay.h:165
CommandScreen::buttonLeftReleased
virtual void buttonLeftReleased()
Definition: CommandScreen.h:333
CommandScreen::ID
ScreenID ID() const
Definition: CommandScreen.h:286
CommandScreenDisplay::remoteDialEvent
void remoteDialEvent(long newValue, long oldValue)
Definition: CommandScreenDisplay.h:158
CommandScreenHandler::isSleeping
bool isSleeping() const
Definition: CommandScreen.h:223
CommandScreen::getKeyRepeatRate
unsigned getKeyRepeatRate() const
Definition: CommandScreen.h:319
CommandScreen::buttonDial
virtual void buttonDial(long newValue, long oldValue=0)
Definition: CommandScreen.h:337
CommandScreen::buttonUpPressed
virtual void buttonUpPressed(bool repeat=false)
Definition: CommandScreen.h:327
PinManager
Definition: PinManager.h:6
CommandScreenDisplay::handleEvent
virtual bool handleEvent() override
Definition: CommandScreenDisplay.h:182
RotaryEncoder::hasChanged
bool hasChanged()
Returns true if value has changed since last animated event.
Definition: RotaryEncoder.h:94
CommandScreenDisplay::print
void print(String text)
Definition: CommandScreenDisplay.h:103
CommandScreenDisplay::fDisplay
COMMAND_DISPLAY & fDisplay
Definition: CommandScreenDisplay.h:365
CommandScreenDisplay::println
void println(unsigned val)
Definition: CommandScreenDisplay.h:111
CommandScreen::buttonDownReleased
virtual void buttonDownReleased()
Definition: CommandScreen.h:334
CommandScreen::buttonUpReleased
virtual void buttonUpReleased()
Definition: CommandScreen.h:332
AnoRotaryEncoder::isButtonPressed
bool isButtonPressed(byte pin) const
Definition: AnoRotaryEncoder.h:61
CommandScreen::buttonRightReleased
virtual void buttonRightReleased()
Definition: CommandScreen.h:335
CommandScreen::buttonInPressed
virtual void buttonInPressed(bool repeat=false)
Definition: CommandScreen.h:331
CommandScreen::buttonDownPressed
virtual void buttonDownPressed(bool repeat=false)
Definition: CommandScreen.h:329
CommandScreenDisplay::fInitProc
bool(* fInitProc)(void)
Definition: CommandScreenDisplay.h:367
CommandScreenDisplay::setTextSize
void setTextSize(int siz)
Definition: CommandScreenDisplay.h:70
CommandScreenDisplay::fSkipButtonReleased
bool fSkipButtonReleased
Definition: CommandScreenDisplay.h:371
AnoRotaryEncoder::hasButtonStateChanged
bool hasButtonStateChanged() const
Definition: AnoRotaryEncoder.h:45
CommandScreenDisplay::begin
bool begin()
Definition: CommandScreenDisplay.h:35