ArduinoLibs
|
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 }