ArduinoLibs
LCD.cpp
00001 /*
00002  * Copyright (C) 2012 Southern Storm Software, Pty Ltd.
00003  *
00004  * Permission is hereby granted, free of charge, to any person obtaining a
00005  * copy of this software and associated documentation files (the "Software"),
00006  * to deal in the Software without restriction, including without limitation
00007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
00008  * and/or sell copies of the Software, and to permit persons to whom the
00009  * Software is furnished to do so, subject to the following conditions:
00010  *
00011  * The above copyright notice and this permission notice shall be included
00012  * in all copies or substantial portions of the Software.
00013  *
00014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00015  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00017  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00018  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
00019  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
00020  * DEALINGS IN THE SOFTWARE.
00021  */
00022 
00023 #include "LCD.h"
00024 #include <avr/pgmspace.h>
00025 #if defined(ARDUINO) && ARDUINO >= 100
00026 #include <Arduino.h>
00027 #else
00028 #include <WProgram.h>
00029 #endif
00030 
00031 #define LCD_BACK_LIGHT          3        // Default LCD backlight is on D3
00032 #define LCD_BUTTON_PIN          A0       // Button state is on A0
00033 
00034 #define DEBOUNCE_DELAY          10      // Delay in ms to debounce buttons
00035 
00130 void LCD::init()
00131 {
00132     // The Freetronics display is 16x2.
00133     begin(16, 2);
00134 
00135     // Configure the backlight pin, but don't activate it yet in
00136     // case the application sets it to something else during setup().
00137     // Initialization will be forced in the first call to getButton().
00138     _backlightPin = LCD_BACK_LIGHT;
00139     backlightInit = false;
00140 
00141     // Initialise button input.
00142     pinMode(LCD_BUTTON_PIN, INPUT);
00143     digitalWrite(LCD_BUTTON_PIN, LOW);
00144     prevButton = LCD_BUTTON_NONE;
00145     debounceButton = LCD_BUTTON_NONE;
00146     lastDebounce = 0;
00147     eatRelease = false;
00148 
00149     // Initialize screen saver.
00150     timeout = 0;
00151     lastRestore = millis();
00152     screenSaved = false;
00153     mode = DisplayOff;
00154 }
00155 
00182 void LCD::setBacklightPin(uint8_t pin)
00183 {
00184     if (_backlightPin != pin) {
00185         if (backlightInit) {
00186             // Restore the previous backlight pin to input, floating.
00187             pinMode(_backlightPin, INPUT);
00188             digitalWrite(_backlightPin, LOW);
00189 
00190             // Need to re-initialize the backlight at the earliest opportunity.
00191             backlightInit = false;
00192         }
00193         _backlightPin = pin;
00194     }
00195 }
00196 
00206 void LCD::display()
00207 {
00208     LiquidCrystal::display();
00209     pinMode(_backlightPin, OUTPUT);
00210     digitalWrite(_backlightPin, HIGH);
00211     screenSaved = false;
00212     backlightInit = true;
00213     lastRestore = millis();
00214 }
00215 
00223 void LCD::noDisplay()
00224 {
00225     if (mode == DisplayOff)
00226         LiquidCrystal::noDisplay();
00227     pinMode(_backlightPin, OUTPUT);
00228     digitalWrite(_backlightPin, LOW);
00229     screenSaved = true;
00230     backlightInit = true;
00231 }
00232 
00268 void LCD::setScreenSaverMode(ScreenSaverMode mode)
00269 {
00270     if (this->mode != mode) {
00271         this->mode = mode;
00272         if (screenSaved)
00273             noDisplay();
00274         else
00275             display();
00276     }
00277 }
00278 
00294 void LCD::enableScreenSaver(int timeoutSecs)
00295 {
00296     if (timeoutSecs < 0)
00297         timeout = 0;
00298     else
00299         timeout = ((unsigned long)timeoutSecs) * 1000;
00300     display();
00301 }
00302 
00308 void LCD::disableScreenSaver()
00309 {
00310     timeout = 0;
00311     display();
00312 }
00313 
00321 // Button mapping table generated by genlookup.c
00322 static prog_uint8_t const buttonMappings[] PROGMEM = {
00323     2, 0, 0, 0, 3, 0, 0, 0, 0, 4, 4, 0, 0, 0, 0, 1,
00324     1, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0
00325 };
00326 #define mapButton(value) (pgm_read_byte(&(buttonMappings[(value) >> 5])))
00327 
00353 int LCD::getButton()
00354 {
00355     // Initialize the backlight for the first time if necessary.
00356     if (!backlightInit)
00357         display();
00358 
00359     // Read the currently pressed button.
00360     int button = mapButton(analogRead(LCD_BUTTON_PIN));
00361 
00362     // Debounce the button state.
00363     unsigned long currentTime = millis();
00364     if (button != debounceButton)
00365         lastDebounce = currentTime;
00366     debounceButton = button;
00367     if ((currentTime - lastDebounce) < DEBOUNCE_DELAY)
00368         button = prevButton;
00369 
00370     // Process the button event if the state has changed.
00371     if (prevButton == LCD_BUTTON_NONE && button != LCD_BUTTON_NONE) {
00372         prevButton = button;
00373         if (screenSaved) {
00374             // Button pressed when screen saver active.
00375             if (mode == BacklightOnSelect) {
00376                 // Turn on the back light only if Select was pressed.
00377                 if (button == LCD_BUTTON_SELECT) {
00378                     pinMode(_backlightPin, OUTPUT);
00379                     digitalWrite(_backlightPin, HIGH);
00380                     screenSaved = false;
00381                     backlightInit = true;
00382                 }
00383             } else if (mode == DisplayOff) {
00384                 display();
00385                 eatRelease = true;
00386                 return LCD_BUTTON_NONE;
00387             } else {
00388                 display();
00389             }
00390         } else if (mode == BacklightOnSelect && button != LCD_BUTTON_SELECT) {
00391             eatRelease = false;
00392             return button;
00393         }
00394         eatRelease = false;
00395         lastRestore = currentTime;
00396         return button;
00397     } else if (prevButton != LCD_BUTTON_NONE && button == LCD_BUTTON_NONE) {
00398         button = -prevButton;
00399         prevButton = LCD_BUTTON_NONE;
00400         lastRestore = currentTime;
00401         if (eatRelease) {
00402             eatRelease = false;
00403             return LCD_BUTTON_NONE;
00404         }
00405         return button;
00406     } else {
00407         if (!screenSaved && prevButton == LCD_BUTTON_NONE &&
00408                 timeout != 0 && (currentTime - lastRestore) >= timeout)
00409             noDisplay();    // Activate screen saver.
00410         return LCD_BUTTON_NONE;
00411     }
00412 }
 All Classes Files Functions Variables Typedefs Enumerations Enumerator