ArduinoLibs
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Groups Pages
LCD.cpp
1 /*
2  * Copyright (C) 2012 Southern Storm Software, Pty Ltd.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included
12  * in all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20  * DEALINGS IN THE SOFTWARE.
21  */
22 
23 #include "LCD.h"
24 #include <avr/pgmspace.h>
25 #if defined(ARDUINO) && ARDUINO >= 100
26 #include <Arduino.h>
27 #else
28 #include <WProgram.h>
29 #endif
30 
31 #define LCD_BACK_LIGHT 3 // Default LCD backlight is on D3
32 #define LCD_BUTTON_PIN A0 // Button state is on A0
33 
34 #define DEBOUNCE_DELAY 10 // Delay in ms to debounce buttons
35 
130 void LCD::init()
131 {
132  // The Freetronics display is 16x2.
133  begin(16, 2);
134 
135  // Configure the backlight pin, but don't activate it yet in
136  // case the application sets it to something else during setup().
137  // Initialization will be forced in the first call to getButton().
138  _backlightPin = LCD_BACK_LIGHT;
139  backlightInit = false;
140 
141  // Initialise button input.
142  pinMode(LCD_BUTTON_PIN, INPUT);
143  digitalWrite(LCD_BUTTON_PIN, LOW);
144  prevButton = LCD_BUTTON_NONE;
145  debounceButton = LCD_BUTTON_NONE;
146  lastDebounce = 0;
147  eatRelease = false;
148 
149  // Initialize screen saver.
150  timeout = 0;
151  lastRestore = millis();
152  screenSaved = false;
153  mode = DisplayOff;
154 }
155 
182 void LCD::setBacklightPin(uint8_t pin)
183 {
184  if (_backlightPin != pin) {
185  if (backlightInit) {
186  // Restore the previous backlight pin to input, floating.
187  pinMode(_backlightPin, INPUT);
188  digitalWrite(_backlightPin, LOW);
189 
190  // Need to re-initialize the backlight at the earliest opportunity.
191  backlightInit = false;
192  }
193  _backlightPin = pin;
194  }
195 }
196 
207 {
209  pinMode(_backlightPin, OUTPUT);
210  digitalWrite(_backlightPin, HIGH);
211  screenSaved = false;
212  backlightInit = true;
213  lastRestore = millis();
214 }
215 
224 {
225  if (mode == DisplayOff)
227  pinMode(_backlightPin, OUTPUT);
228  digitalWrite(_backlightPin, LOW);
229  screenSaved = true;
230  backlightInit = true;
231 }
232 
269 {
270  if (this->mode != mode) {
271  this->mode = mode;
272  if (screenSaved)
273  noDisplay();
274  else
275  display();
276  }
277 }
278 
294 void LCD::enableScreenSaver(int timeoutSecs)
295 {
296  if (timeoutSecs < 0)
297  timeout = 0;
298  else
299  timeout = ((unsigned long)timeoutSecs) * 1000;
300  display();
301 }
302 
309 {
310  timeout = 0;
311  display();
312 }
313 
321 // Button mapping table generated by genlookup.c
322 static unsigned char const buttonMappings[] PROGMEM = {
323  2, 0, 0, 0, 3, 0, 0, 0, 0, 4, 4, 0, 0, 0, 0, 1,
324  1, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0
325 };
326 #define mapButton(value) (pgm_read_byte(&(buttonMappings[(value) >> 5])))
327 
354 {
355  // Initialize the backlight for the first time if necessary.
356  if (!backlightInit)
357  display();
358 
359  // Read the currently pressed button.
360  int button = mapButton(analogRead(LCD_BUTTON_PIN));
361 
362  // Debounce the button state.
363  unsigned long currentTime = millis();
364  if (button != debounceButton)
365  lastDebounce = currentTime;
366  debounceButton = button;
367  if ((currentTime - lastDebounce) < DEBOUNCE_DELAY)
368  button = prevButton;
369 
370  // Process the button event if the state has changed.
371  if (prevButton == LCD_BUTTON_NONE && button != LCD_BUTTON_NONE) {
372  prevButton = button;
373  if (screenSaved) {
374  // Button pressed when screen saver active.
375  if (mode == BacklightOnSelect) {
376  // Turn on the back light only if Select was pressed.
377  if (button == LCD_BUTTON_SELECT) {
378  pinMode(_backlightPin, OUTPUT);
379  digitalWrite(_backlightPin, HIGH);
380  screenSaved = false;
381  backlightInit = true;
382  }
383  } else if (mode == DisplayOff) {
384  display();
385  eatRelease = true;
386  return LCD_BUTTON_NONE;
387  } else {
388  display();
389  }
390  } else if (mode == BacklightOnSelect && button != LCD_BUTTON_SELECT) {
391  eatRelease = false;
392  return button;
393  }
394  eatRelease = false;
395  lastRestore = currentTime;
396  return button;
397  } else if (prevButton != LCD_BUTTON_NONE && button == LCD_BUTTON_NONE) {
398  button = -prevButton;
399  prevButton = LCD_BUTTON_NONE;
400  lastRestore = currentTime;
401  if (eatRelease) {
402  eatRelease = false;
403  return LCD_BUTTON_NONE;
404  }
405  return button;
406  } else {
407  if (!screenSaved && prevButton == LCD_BUTTON_NONE &&
408  timeout != 0 && (currentTime - lastRestore) >= timeout)
409  noDisplay(); // Activate screen saver.
410  return LCD_BUTTON_NONE;
411  }
412 }