AGirs
LedLcdManager.cpp
Go to the documentation of this file.
1 // Comment out if LCD is not wanted or needed. Except for needing some memory,
2 // it has otherwise no disadvantages.
3 // Remove for minimal memory footprint.
4 
5 // This should be taken from config.h, but the Arduino IDE does not seem
6 // to allow for this. User friendlyness taken to a new level...
7 // Adjust if needed
8 #if ! defined(ARDUINO_AVR_MICRO) & ! defined(ARDUINO_AVR_NANO)
9 #define LCD
10 #endif
11 
12 #include "LedLcdManager.h"
13 #include <string.h>
14 #include <avr/pgmspace.h>
15 
16 #ifdef LCD
17 LiquidCrystal_I2C *LedLcdManager::lcd;
18 #endif
19 
20 unsigned int LedLcdManager::row = 0U;
21 unsigned int LedLcdManager::column = 0U;
22 
23 milliseconds_t LedLcdManager::blinkTime = defaultBlinkTime;
24 unsigned long LedLcdManager::turnOffTime;
25 unsigned int LedLcdManager::lcdRows = 0;
26 unsigned int LedLcdManager::lcdColumns = 0;
27 
28 pin_t LedLcdManager::physicalLeds[maxLeds];
29 led_t LedLcdManager::logicalLeds[maxLeds];
30 bool LedLcdManager::shouldTimeOut[maxLeds];
31 
32 void LedLcdManager::setup(int8_t i2cAddress, uint8_t columns, uint8_t rows,
33  const pin_t physicalLeds_[], const led_t logicalLeds_[], const bool shouldTimeOut_[]) {
34  setupLcdI2c(i2cAddress, columns, rows);
35  setupPhysicalLeds(physicalLeds_);
36  setupLogicLeds(logicalLeds_);
37  setupShouldTimeOut(shouldTimeOut_);
38  disableTurnOffTime();
39 }
40 
41 bool LedLcdManager::setPhysicalLed(led_t physicalLed, LedState state) {
42  pin_t pin = physicalLeds[physicalLed-1];
43  if (pin == invalidPin)
44  return false;
45 
46  digitalWrite(pin, state == off ? LOW : HIGH);
47  if (state == blink)
49  return true;
50 }
51 
53  return value == NULL ? invalid
54  : strcmp(value, "on") == 0 ? on
55  : strcmp(value, "off") == 0 ? off
56  : strcmp(value, "blink") == 0 ? blink
57  : invalid;
58 }
59 
60 bool LedLcdManager::setLogicLed(led_t logicLed, LedState state) {
61  if (logicLed == invalidLed
62  || logicLed < 1
63  || logicLed > maxLeds
64  || state == invalid )
65  return false;
66 
67  led_t physicalLed = logicalLeds[logicLed - 1];
68  if (physicalLed == invalidLed)
69  return false;
70 
71  return setPhysicalLed(physicalLed, state);
72 }
73 
74 bool LedLcdManager::setupLogicLed(led_t logicLed, led_t physicalLed) {
75  if (physicalLed == invalidLed)
76  return false;
77 
78  logicalLeds[logicLed-1] = physicalLed;
79  return true;
80 }
81 
82 bool LedLcdManager::setupLogicLeds(const led_t logicalLeds_[maxLeds]) {
83  for (int i = 0; i < maxLeds; i++)
84  logicalLeds[i] = logicalLeds_ == NULL ? i+1 : logicalLeds_[i];
85  return true;
86 }
87 
88 void LedLcdManager::setupPhysicalLeds(const pin_t physicalLeds_[maxLeds]) {
89  for (int i = 0; i < maxLeds; i++) {
90  physicalLeds[i] = physicalLeds_ == NULL ? invalidPin : physicalLeds_[i];
91  if (physicalLeds[i] != invalidPin)
92  pinMode(physicalLeds[i], OUTPUT);
93  }
94 }
95 
96 void LedLcdManager::setupShouldTimeOut(const bool shouldTimeOut_[maxLeds]) {
97  for (int i = 0; i < maxLeds; i++)
98  shouldTimeOut[i] = shouldTimeOut_ == NULL ? true : shouldTimeOut_[i];
99 }
100 
101 void LedLcdManager::setupShouldTimeout(led_t logicLed, bool state) {
102  if (logicLed != invalidLed)
103  shouldTimeOut[logicLed-1] = state;
104 }
105 
106 void LedLcdManager::setupLcdI2c(int8_t i2cAddress __attribute__((unused)),
107  uint8_t columns __attribute__((unused)),
108  uint8_t rows __attribute__((unused))) {
109 #ifdef LCD
110  lcd = i2cAddress >= 0 ? new LiquidCrystal_I2C(static_cast<uint8_t>(i2cAddress), columns, rows) : nullptr;
111  if (lcd) {
112  lcdRows = rows;
113  lcdColumns = columns;
114  lcd->init();
115  }
116 #endif
117 }
118 
120  turnOffTime = millis() + blinkTime;
121 }
122 
123 void LedLcdManager::selfTest(const char *text) {
124  lcdPrint(text);
125  for (led_t i = 1; i <= maxLeds; i++)
126  setLogicLed(i, on);
127  delay(
128 #ifdef LCD
129  lcd ? selftestTimeWithLCD :
130 #endif
132  allOff(true);
133 }
134 
135 void LedLcdManager::selfTest(const __FlashStringHelper *text) {
136  lcdPrint(text);
137  for (led_t i = 1; i <= maxLeds; i++)
138  setLogicLed(i, on);
139  delay(
140 #ifdef LCD
141  lcd ? selftestTimeWithLCD :
142 #endif
144  allOff(true);
145 }
146 
148  if (millis() > turnOffTime)
149  allOff(false);
150 }
151 
152 void LedLcdManager::allOff(bool force) {
153 #ifdef LCD
154  if (lcd) {
155  lcd->noDisplay();
156  lcd->noBacklight();
157  }
158 #endif
159  for (led_t i = 1; i <= maxLeds; i++)
160  if (force || shouldTimeOut[i - 1])
161  setLogicLed(i, off);
162 
163  disableTurnOffTime();
164 }
165 
166 void LedLcdManager::disableTurnOffTime() {
167  turnOffTime = (unsigned long) -1;
168 }
169 
170 void LedLcdManager::lcdPrint(const __FlashStringHelper *pstr __attribute__ ((unused)), bool clear __attribute__ ((unused)), int x __attribute__ ((unused)), int y __attribute__ ((unused))) {
171 #ifdef LCD
172  if (!lcd)
173  return;
174  prepare(clear, x, y);
175  PGM_P p = reinterpret_cast<PGM_P>(pstr);
176  char c;
177  do {
178  c = pgm_read_byte(p++);
179  switch (c) {
180  case '\r':
181  case '\0':
182  break;
183  case '\n':
184  column = 0;
185  row++;
186  lcd->setCursor(column, row);
187  break;
188  default:
189  lcd->write(c);
190  }
191  } while (c != '\0');
192 
193  lcd->display();
194  lcd->backlight();
196 #endif
197 }
198 
199 void LedLcdManager::lcdPrint(const char* string __attribute__ ((unused)), bool clear __attribute__ ((unused)),
200  int x __attribute ((unused)), int y __attribute__ ((unused))) {
201 #ifdef LCD
202  if (!lcd)
203  return;
204  prepare(clear, x, y);
205  size_t len = strlen(string);
206  for (size_t i = 0; i < len; i++) {
207  char c = string[i];
208  switch (c) {
209  case '\r':
210  break;
211  case '\n':
212  column = 0;
213  row++;
214  lcd->setCursor(column, row);
215  break;
216  default:
217  lcd->write(c);
218  }
219  }
220  lcd->display();
221  lcd->backlight();
223 #endif
224 }
225 
226 void LedLcdManager::prepare(bool clear __attribute__((unused)), int x __attribute__((unused)), int y __attribute__((unused))) {
227 #ifdef LCD
228  if (x >= 0 && y >= 0) {
229  row = y;
230  column = x;
231  if (row > (unsigned int) lcdRows - 1 || column > (unsigned int) lcdColumns - 1) // outside of display
232  return;
233  lcd->setCursor(column, row);
234  }
235 
236  if (clear) {
237  row = 0U;
238  column = 0U;
239  lcd->clear();
240  }
241 #endif
242 }
#define LCD
uint8_t led_t
Definition: LedLcdManager.h:9
static void lcdPrint(const char *str, bool clear=true, int x=invalidLine, int y=invalidLine)
static constexpr int maxLeds
Definition: LedLcdManager.h:13
static void setupShouldTimeout(led_t logicLed, bool state)
static constexpr int selftestTimeWithLCD
Definition: LedLcdManager.h:20
static void allOff(bool force)
static constexpr led_t invalidLed
Definition: LedLcdManager.h:29
static bool setLogicLed(led_t logicLed, LedState state)
static LedState onOffBlinkParse(const char *value)
static constexpr int selftestTimeWithoutLCD
Definition: LedLcdManager.h:19
static bool setupLogicLed(led_t loginLed, led_t physicalLed)
static void setup(int8_t i2cAddress, uint8_t columns=defaultLcdColumns, uint8_t rows=defaultLcdRows, const pin_t physicalLeds[maxLeds]=NULL, const led_t logicalLeds[maxLeds]=NULL, const bool shouldTimeOut[maxLeds]=NULL)
Sets up the instance, to be called before using the instance.
static bool setupLogicLeds(const led_t array[maxLeds])
static void selfTest(const char *text)
static bool setPhysicalLed(led_t physicalLed, LedState state)
static void updateTurnOffTime()
static void checkTurnoff()
Turn off if it is due.
void noBacklight()
Turn the (optional) backlight off/on.
void setCursor(uint8_t, uint8_t)
void noDisplay()
Turn the display on/off (quickly)