diff --git a/doc/mainpage.dox b/doc/mainpage.dox index 3792842b..14f48b4a 100644 --- a/doc/mainpage.dox +++ b/doc/mainpage.dox @@ -34,10 +34,10 @@ For more information on these libraries, to report bugs, or to suggest improvements, please contact the author Rhys Weatherley via email. -\section main_LCD Freetronics LCD Shield +\section main_LCD LCD Shield \li LCD class to manage the extended features of the Freetronics -LCD shield. +and DFRobot LCD shields. \li Form and Field classes to build simple property sheet UI's on LCD displays. \li \ref lcd_hello_world "Hello World" example for the Freetronics LCD shield. \li \ref lcd_form "Form" example for LCD displays. diff --git a/libraries/LCD/LCD.cpp b/libraries/LCD/LCD.cpp index 7582b2bf..b6d6b49c 100644 --- a/libraries/LCD/LCD.cpp +++ b/libraries/LCD/LCD.cpp @@ -28,7 +28,7 @@ #include #endif -#define LCD_BACK_LIGHT 3 // LCD backlight is on D3 +#define LCD_BACK_LIGHT 3 // Default LCD backlight is on D3 #define LCD_BUTTON_PIN A0 // Button state is on A0 #define DEBOUNCE_DELAY 10 // Delay in ms to debounce buttons @@ -73,10 +73,25 @@ * generic button has been pressed with button > 0 and if a * generic button has been released with button < 0. * - * See the \ref lcd_hello_world "Hello World" example for more - * information on using the LCD class. + * \section lcd_dfrobot Support for DFRobot LCD Shield * - * \sa Form + * The DFRobot LCD Shield + * is almost identical to the Freetronics shield, except it uses pin 10 for + * the back light instead of pin 3. This can be specified in the + * application's setup() function: + * + * \code + * LCD lcd; + * + * void setup() { + * lcd.setBacklightPin(10); + * } + * \endcode + * + * The back light pin is configured for output the first time the + * application calls getButton(). + * + * \sa Form, \ref lcd_hello_world "Hello World Example" */ /** @@ -117,9 +132,11 @@ void LCD::init() // The Freetronics display is 16x2. begin(16, 2); - // Set the LCD back light to be initially on. - pinMode(LCD_BACK_LIGHT, OUTPUT); - digitalWrite(LCD_BACK_LIGHT, HIGH); + // Configure the backlight pin, but don't activate it yet in + // case the application sets it to something else during setup(). + // Initialization will be forced in the first call to getButton(). + _backlightPin = LCD_BACK_LIGHT; + backlightInit = false; // Initialise button input. pinMode(LCD_BUTTON_PIN, INPUT); @@ -136,6 +153,47 @@ void LCD::init() mode = DisplayOff; } +/** + * \fn uint8_t LCD::backlightPin() const + * \brief Returns the pin that is being used to control the back light. + * The default is 3. + * + * \sa setBacklightPin() + */ + +/** + * \brief Sets the back light \a pin for the LCD shield. + * + * The DFRobot LCD Shield uses pin 10 for the back light instead of pin 3: + * + * \code + * LCD lcd; + * + * void setup() { + * lcd.setBacklightPin(10); + * } + * \endcode + * + * The back light pin is configured for output the next time the + * application calls getButton(). + * + * \sa backlightPin() + */ +void LCD::setBacklightPin(uint8_t pin) +{ + if (_backlightPin != pin) { + if (backlightInit) { + // Restore the previous backlight pin to input, floating. + pinMode(_backlightPin, INPUT); + digitalWrite(_backlightPin, LOW); + + // Need to re-initialize the backlight at the earliest opportunity. + backlightInit = false; + } + _backlightPin = pin; + } +} + /** * \brief Turns on the display of text on the LCD and the back light. * @@ -148,8 +206,10 @@ void LCD::init() void LCD::display() { LiquidCrystal::display(); - digitalWrite(LCD_BACK_LIGHT, HIGH); + pinMode(_backlightPin, OUTPUT); + digitalWrite(_backlightPin, HIGH); screenSaved = false; + backlightInit = true; lastRestore = millis(); } @@ -164,8 +224,10 @@ void LCD::noDisplay() { if (mode == DisplayOff) LiquidCrystal::noDisplay(); - digitalWrite(LCD_BACK_LIGHT, LOW); + pinMode(_backlightPin, OUTPUT); + digitalWrite(_backlightPin, LOW); screenSaved = true; + backlightInit = true; } /** @@ -290,6 +352,10 @@ static prog_uint8_t const buttonMappings[] PROGMEM = { */ int LCD::getButton() { + // Initialize the backlight for the first time if necessary. + if (!backlightInit) + display(); + // Read the currently pressed button. int button = mapButton(analogRead(LCD_BUTTON_PIN)); @@ -309,8 +375,10 @@ int LCD::getButton() if (mode == BacklightOnSelect) { // Turn on the back light only if Select was pressed. if (button == LCD_BUTTON_SELECT) { - digitalWrite(LCD_BACK_LIGHT, HIGH); + pinMode(_backlightPin, OUTPUT); + digitalWrite(_backlightPin, HIGH); screenSaved = false; + backlightInit = true; } } else if (mode == DisplayOff) { display(); diff --git a/libraries/LCD/LCD.h b/libraries/LCD/LCD.h index 7d02c312..fba683c3 100644 --- a/libraries/LCD/LCD.h +++ b/libraries/LCD/LCD.h @@ -50,6 +50,9 @@ public: LCD() : LiquidCrystal(8, 9, 4, 5, 6, 7) { init(); } LCD(uint8_t pin9) : LiquidCrystal(8, pin9, 4, 5, 6, 7) { init(); } + uint8_t backlightPin() const { return _backlightPin; } + void setBacklightPin(uint8_t pin); + void display(); void noDisplay(); @@ -70,6 +73,8 @@ public: int getButton(); private: + uint8_t _backlightPin; + bool backlightInit; int prevButton; int debounceButton; unsigned long timeout;