Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Initial import from http://hg.bijland.net/fmalpartida/new-liquidcrystal

  • Loading branch information...
commit 8e72ab08bcc42b0f9fffec7e626d0f1584e050b8 0 parents
@marcmerlin authored
Showing with 16,737 additions and 0 deletions.
  1. +198 −0 I2CIO.cpp
  2. +150 −0 I2CIO.h
  3. +202 −0 LCD.cpp
  4. +402 −0 LCD.h
  5. +321 −0 LiquidCrystal.cpp
  6. +142 −0 LiquidCrystal.h
  7. +288 −0 LiquidCrystal_I2C.cpp
  8. +213 −0 LiquidCrystal_I2C.h
  9. +298 −0 LiquidCrystal_SR.cpp
  10. +166 −0 LiquidCrystal_SR.h
  11. +3 −0  README.import.txt
  12. +92 −0 docs/html/_i2_c_i_o_8cpp.html
  13. +282 −0 docs/html/_i2_c_i_o_8cpp_source.html
  14. +114 −0 docs/html/_i2_c_i_o_8h.html
  15. +149 −0 docs/html/_i2_c_i_o_8h_source.html
  16. +93 −0 docs/html/_l_c_d_8cpp.html
  17. +286 −0 docs/html/_l_c_d_8cpp_source.html
  18. +646 −0 docs/html/_l_c_d_8h.html
  19. +262 −0 docs/html/_l_c_d_8h_source.html
  20. +126 −0 docs/html/_liquid_crystal_8cpp.html
  21. +396 −0 docs/html/_liquid_crystal_8cpp_source.html
  22. +116 −0 docs/html/_liquid_crystal_8h.html
  23. +163 −0 docs/html/_liquid_crystal_8h_source.html
  24. +92 −0 docs/html/_liquid_crystal___i2_c_8cpp.html
  25. +372 −0 docs/html/_liquid_crystal___i2_c_8cpp_source.html
  26. +185 −0 docs/html/_liquid_crystal___i2_c_8h.html
  27. +175 −0 docs/html/_liquid_crystal___i2_c_8h_source.html
  28. +126 −0 docs/html/_liquid_crystal___s_r_8cpp.html
  29. +371 −0 docs/html/_liquid_crystal___s_r_8cpp_source.html
  30. +147 −0 docs/html/_liquid_crystal___s_r_8h.html
  31. +205 −0 docs/html/_liquid_crystal___s_r_8h_source.html
  32. +93 −0 docs/html/annotated.html
  33. BIN  docs/html/bc_s.png
  34. +95 −0 docs/html/class_i2_c_i_o-members.html
  35. +339 −0 docs/html/class_i2_c_i_o.html
  36. +113 −0 docs/html/class_l_c_d-members.html
  37. +815 −0 docs/html/class_l_c_d.html
  38. BIN  docs/html/class_l_c_d.png
  39. +117 −0 docs/html/class_liquid_crystal-members.html
  40. +480 −0 docs/html/class_liquid_crystal.html
  41. BIN  docs/html/class_liquid_crystal.png
  42. +118 −0 docs/html/class_liquid_crystal___i2_c-members.html
  43. +415 −0 docs/html/class_liquid_crystal___i2_c.html
  44. BIN  docs/html/class_liquid_crystal___i2_c.png
  45. +116 −0 docs/html/class_liquid_crystal___s_r-members.html
  46. +326 −0 docs/html/class_liquid_crystal___s_r.html
  47. BIN  docs/html/class_liquid_crystal___s_r.png
  48. +91 −0 docs/html/classes.html
  49. BIN  docs/html/closed.png
  50. +835 −0 docs/html/doxygen.css
  51. BIN  docs/html/doxygen.png
  52. +96 −0 docs/html/files.html
  53. +277 −0 docs/html/functions.html
  54. +257 −0 docs/html/functions_func.html
  55. +106 −0 docs/html/functions_vars.html
  56. +282 −0 docs/html/globals.html
  57. +273 −0 docs/html/globals_defs.html
  58. +93 −0 docs/html/globals_func.html
  59. +95 −0 docs/html/hierarchy.html
  60. +78 −0 docs/html/index.html
  61. +112 −0 docs/html/installdox
  62. +54 −0 docs/html/jquery.js
  63. BIN  docs/html/logoGoogle.jpg
  64. BIN  docs/html/nav_f.png
  65. BIN  docs/html/nav_h.png
  66. BIN  docs/html/open.png
  67. +56 −0 docs/html/search/all_5f.html
  68. +26 −0 docs/html/search/all_61.html
  69. +44 −0 docs/html/search/all_62.html
  70. +47 −0 docs/html/search/all_63.html
  71. +44 −0 docs/html/search/all_64.html
  72. +32 −0 docs/html/search/all_65.html
  73. +26 −0 docs/html/search/all_66.html
  74. +32 −0 docs/html/search/all_68.html
  75. +39 −0 docs/html/search/all_69.html
  76. +301 −0 docs/html/search/all_6c.html
  77. +50 −0 docs/html/search/all_6e.html
  78. +32 −0 docs/html/search/all_70.html
  79. +44 −0 docs/html/search/all_72.html
  80. +61 −0 docs/html/search/all_73.html
  81. +26 −0 docs/html/search/all_74.html
  82. +38 −0 docs/html/search/all_77.html
  83. +25 −0 docs/html/search/classes_69.html
  84. +40 −0 docs/html/search/classes_6c.html
  85. BIN  docs/html/search/close.png
  86. +26 −0 docs/html/search/defines_5f.html
  87. +26 −0 docs/html/search/defines_63.html
  88. +26 −0 docs/html/search/defines_64.html
  89. +32 −0 docs/html/search/defines_65.html
  90. +26 −0 docs/html/search/defines_66.html
  91. +212 −0 docs/html/search/defines_6c.html
  92. +32 −0 docs/html/search/defines_72.html
  93. +32 −0 docs/html/search/defines_73.html
  94. +26 −0 docs/html/search/defines_74.html
  95. +30 −0 docs/html/search/files_69.html
  96. +60 −0 docs/html/search/files_6c.html
  97. +26 −0 docs/html/search/functions_61.html
  98. +44 −0 docs/html/search/functions_62.html
  99. +44 −0 docs/html/search/functions_63.html
  100. +38 −0 docs/html/search/functions_64.html
  101. +26 −0 docs/html/search/functions_65.html
  102. +26 −0 docs/html/search/functions_68.html
  103. +26 −0 docs/html/search/functions_69.html
  104. +63 −0 docs/html/search/functions_6c.html
  105. +50 −0 docs/html/search/functions_6e.html
  106. +32 −0 docs/html/search/functions_70.html
  107. +32 −0 docs/html/search/functions_72.html
  108. +49 −0 docs/html/search/functions_73.html
  109. +38 −0 docs/html/search/functions_77.html
  110. BIN  docs/html/search/mag_sel.png
  111. +12 −0 docs/html/search/nomatches.html
  112. +240 −0 docs/html/search/search.css
  113. +736 −0 docs/html/search/search.js
  114. BIN  docs/html/search/search_l.png
  115. BIN  docs/html/search/search_m.png
  116. BIN  docs/html/search/search_r.png
  117. +50 −0 docs/html/search/variables_5f.html
  118. BIN  docs/html/tab_a.png
  119. BIN  docs/html/tab_b.png
  120. BIN  docs/html/tab_h.png
  121. BIN  docs/html/tab_s.png
  122. +59 −0 docs/html/tabs.css
  123. +76 −0 examples/HelloWorld_4bit/HelloWorld_4bit.pde
  124. +56 −0 examples/HelloWorld_i2c/HelloWorld_i2c.pde
  125. +37 −0 examples/SerialDisplay/SerialDisplay.pde
  126. +244 −0 examples/i2cLCDextraIO/i2cLCDextraIO.pde
  127. +307 −0 examples/i2cLCDextraIO_tempLeonardo/i2cLCDextraIO_tempLeonardo.ino
  128. +439 −0 examples/performanceLCD/performanceLCD.ino
  129. +39 −0 keywords.txt
198 I2CIO.cpp
@@ -0,0 +1,198 @@
+// ---------------------------------------------------------------------------
+// Created by Francisco Malpartida on 20/08/11.
+// Copyright 2011 - Under creative commons license 3.0:
+// Attribution-ShareAlike CC BY-SA
+//
+// This software is furnished "as is", without technical support, and with no
+// warranty, express or implied, as to its usefulness for any purpose.
+//
+// Thread Safe: No
+// Extendable: Yes
+//
+// @file I2CIO.h
+// This file implements a basic IO library using the PCF8574 I2C IO Expander
+// chip.
+//
+// @brief
+// Implement a basic IO library to drive the PCF8574* I2C IO Expander ASIC.
+// The library implements basic IO general methods to configure IO pin direction
+// read and write uint8_t operations and basic pin level routines to set or read
+// a particular IO port.
+//
+// This library is only compatible with Arduino's SDK version 1.0
+//
+// @version API 1.0.0
+//
+// @author F. Malpartida - fmalpartida@gmail.com
+// ---------------------------------------------------------------------------
+#if (ARDUINO < 100)
+#include <WProgram.h>
+#else
+#include <Arduino.h>
+#endif
+
+#include <inttypes.h>
+#include <../Wire/Wire.h>
+#include <I2CIO.h>
+
+// CLASS VARIABLES
+// ---------------------------------------------------------------------------
+
+
+// CONSTRUCTOR
+// ---------------------------------------------------------------------------
+I2CIO::I2CIO ( )
+{
+ _i2cAddr = 0x0;
+ _dirMask = 0xFF; // mark all as INPUTs
+ _shadow = 0x0; // no values set
+ _initialised = false;
+}
+
+// PUBLIC METHODS
+// ---------------------------------------------------------------------------
+
+//
+// begin
+int I2CIO::begin ( uint8_t i2cAddr )
+{
+ _i2cAddr = i2cAddr;
+
+ Wire.begin ( );
+
+ _initialised = Wire.requestFrom ( _i2cAddr, (uint8_t)1 );
+
+#if (ARDUINO < 100)
+ _shadow = Wire.receive ();
+#else
+ _shadow = Wire.read (); // Remove the byte read don't need it.
+#endif
+
+ return ( _initialised );
+}
+
+//
+// pinMode
+void I2CIO::pinMode ( uint8_t pin, uint8_t dir )
+{
+ if ( _initialised )
+ {
+ if ( OUTPUT == dir )
+ {
+ _dirMask &= ~( 1 << pin );
+ }
+ else
+ {
+ _dirMask |= ( 1 << pin );
+ }
+ }
+}
+
+//
+// portMode
+void I2CIO::portMode ( uint8_t dir )
+{
+
+ if ( _initialised )
+ {
+ if ( dir == INPUT )
+ {
+ _dirMask = 0xFF;
+ }
+ else
+ {
+ _dirMask = 0x00;
+ }
+ }
+}
+
+//
+// read
+uint8_t I2CIO::read ( void )
+{
+ uint8_t retVal = 0;
+
+ if ( _initialised )
+ {
+ Wire.requestFrom ( _i2cAddr, (uint8_t)1 );
+#if (ARDUINO < 100)
+ retVal = ( _dirMask & Wire.receive ( ) );
+#else
+ retVal = ( _dirMask & Wire.read ( ) );
+#endif
+
+ }
+ return ( retVal );
+}
+
+//
+// write
+int I2CIO::write ( uint8_t value )
+{
+ int status = 0;
+
+ if ( _initialised )
+ {
+ // Only write HIGH the values of the ports that have been initialised as
+ // outputs updating the output shadow of the device
+ _shadow = ( value & ~(_dirMask) );
+
+ Wire.beginTransmission ( _i2cAddr );
+#if (ARDUINO < 100)
+ Wire.send ( _shadow );
+#else
+ Wire.write ( _shadow );
+#endif
+ status = Wire.endTransmission ();
+ }
+ return ( (status == 0) );
+}
+
+//
+// digitalRead
+uint8_t I2CIO::digitalRead ( uint8_t pin )
+{
+ uint8_t pinVal = 0;
+
+ // Check if initialised and that the pin is within range of the device
+ // -------------------------------------------------------------------
+ if ( ( _initialised ) && ( pin <= 7 ) )
+ {
+ // Remove the values which are not inputs and get the value of the pin
+ pinVal = this->read() & _dirMask;
+ pinVal = ( pinVal >> pin ) & 0x01; // Get the pin value
+ }
+ return (pinVal);
+}
+
+//
+// digitalWrite
+int I2CIO::digitalWrite ( uint8_t pin, uint8_t level )
+{
+ uint8_t writeVal;
+ int status = 0;
+
+ // Check if initialised and that the pin is within range of the device
+ // -------------------------------------------------------------------
+ if ( ( _initialised ) && ( pin <= 7 ) )
+ {
+ // Only write to HIGH the port if the port has been configured as
+ // an OUTPUT pin. Add the new state of the pin to the shadow
+ writeVal = ( 1 << pin ) & ~_dirMask;
+ if ( level == HIGH )
+ {
+ _shadow |= writeVal;
+
+ }
+ else
+ {
+ _shadow &= ~writeVal;
+ }
+ status = this->write ( _shadow );
+ }
+ return ( status );
+}
+
+//
+// PRIVATE METHODS
+// ---------------------------------------------------------------------------
150 I2CIO.h
@@ -0,0 +1,150 @@
+// ---------------------------------------------------------------------------
+// Created by Francisco Malpartida on 20/08/11.
+// Copyright 2011 - Under creative commons license 3.0:
+// Attribution-ShareAlike CC BY-SA
+//
+// This software is furnished "as is", without technical support, and with no
+// warranty, express or implied, as to its usefulness for any purpose.
+//
+// Thread Safe: No
+// Extendable: Yes
+//
+// @file I2CIO.h
+// This file implements a basic IO library using the PCF8574 I2C IO Expander
+// chip.
+//
+// @brief
+// Implement a basic IO library to drive the PCF8574* I2C IO Expander ASIC.
+// The library implements basic IO general methods to configure IO pin direction
+// read and write uint8_t operations and basic pin level routines to set or read
+// a particular IO port.
+//
+// This library is only compatible with Arduino's SDK version 1.0
+//
+// @version API 1.0.0
+//
+// @author F. Malpartida - fmalpartida@gmail.com
+// ---------------------------------------------------------------------------
+
+#ifndef _I2CIO_H_
+#define _I2CIO_H_
+
+#include <inttypes.h>
+
+#define _I2CIO_VERSION "1.0.0"
+
+/*!
+ @class
+ @abstract I2CIO
+ @discussion Library driver to control PCF8574 based ASICs. Implementing
+ library calls to set/get port through I2C bus.
+ */
+
+class I2CIO
+{
+public:
+ /*!
+ @method
+ @abstract Constructor method
+ @discussion Class constructor constructor.
+ */
+ I2CIO ( );
+
+ /*!
+ @method
+ @abstract Initializes the device.
+ @discussion This method initializes the device allocating an I2C address.
+ This method is the first method that should be call prior to calling any
+ other method form this class. On initialization all pins are configured
+ as INPUT on the device.
+
+ @param i2cAddr: I2C Address where the device is located.
+ @result 1 if the device was initialized correctly, 0 otherwise
+ */
+ int begin ( uint8_t i2cAddr );
+
+ /*!
+ @method
+ @abstract Sets the mode of a particular pin.
+ @discussion Sets the mode of a particular pin to INPUT, OUTPUT. digitalWrite
+ has no effect on pins which are not declared as output.
+
+ @param pin[in] Pin from the I2C IO expander to be configured. Range 0..7
+ @param dir[in] Pin direction (INPUT, OUTPUT).
+ */
+ void pinMode ( uint8_t pin, uint8_t dir );
+
+ /*!
+ @method
+ @abstract Sets all the pins of the device in a particular direction.
+ @discussion This method sets all the pins of the device in a particular
+ direction. This method is useful to set all the pins of the device to be
+ either inputs or outputs.
+ @param dir[in] Direction of all the pins of the device (INPUT, OUTPUT).
+ */
+ void portMode ( uint8_t dir );
+
+ /*!
+ @method
+ @abstract Reads all the pins of the device that are configured as INPUT.
+ @discussion Reads from the device the status of the pins that are configured
+ as INPUT. During initialization all pins are configured as INPUTs by default.
+ Please refer to pinMode or portMode.
+
+ @param none
+ */
+ uint8_t read ( void );
+
+ /*!
+ @method
+ @abstract Read a pin from the device.
+ @discussion Reads a particular pin from the device. To read a particular
+ pin it has to be configured as INPUT. During initialization all pins are
+ configured as INPUTs by default. Please refer to pinMode or portMode.
+
+ @param pin[in] Pin from the port to read its status. Range (0..7)
+ @result Returns the pin status (HIGH, LOW) if the pin is configured
+ as an output, reading its value will always return LOW regardless of its
+ real state.
+ */
+ uint8_t digitalRead ( uint8_t pin );
+
+ /*!
+ @method
+ @abstract Write a value to the device.
+ @discussion Writes to a set of pins in the device. The value is the binary
+ representation of all the pins in device. The value written is masked with
+ the configuration of the direction of the pins; to change the state of
+ a particular pin with this method, such pin has to be configured as OUTPUT
+ using the portMode or pinMode methods. If no pins have been configured as
+ OUTPUTs this method will have no effect.
+
+ @param value[in] value to be written to the device.
+ @result 1 on success, 0 otherwise
+ */
+ int write ( uint8_t value );
+
+ /*!
+ @method
+ @abstract Writes a digital level to a particular pin.
+ @discussion Write a level to the indicated pin of the device. For this
+ method to have effect, the pin has to be configured as OUTPUT using the
+ pinMode or portMode methods.
+
+ @param pin[in] device pin to change level. Range (0..7).
+ @para level[in] logic level to set the pin at (HIGH, LOW).
+ @result 1 on success, 0 otherwise.
+ */
+ int digitalWrite ( uint8_t pin, uint8_t level );
+
+
+
+private:
+ uint8_t _shadow; // Shadow output
+ uint8_t _dirMask; // Direction mask
+ uint8_t _i2cAddr; // I2C address
+ bool _initialised; // Initialised object
+
+};
+
+#endif
202 LCD.cpp
@@ -0,0 +1,202 @@
+// ---------------------------------------------------------------------------
+// Created by Francisco Malpartida on 20/08/11.
+// Copyright 2011 - Under creative commons license 3.0:
+// Attribution-ShareAlike CC BY-SA
+//
+// This software is furnished "as is", without technical support, and with no
+// warranty, express or implied, as to its usefulness for any purpose.
+//
+// Thread Safe: No
+// Extendable: Yes
+//
+// @file HD44780.h
+// This file implements a basic liquid crystal library that comes as standard
+// in the Arduino SDK.
+//
+// @brief
+// This is a basic implementation of the HD44780 library of the
+// Arduino SDK. This library is a refactored version of the one supplied
+// in the Arduino SDK in such a way that it simplifies its extension
+// to support other mechanism to communicate to LCDs such as I2C, Serial.
+// The original library has been reworked in such a way that this will be
+// the base class implementing all generic methods to command an LCD based
+// on the Hitachi HD44780 and compatible chipsets.
+//
+// This base class is a pure abstract class and needs to be extended. As reference,
+// it has been extended to drive 4 and 8 bit mode control, LCDs and I2C extension
+// backpacks such as the I2CLCDextraIO using the PCF8574* I2C IO Expander ASIC.
+//
+//
+// This library is only compatible with Arduino's SDK version 1.0
+//
+// @version API 1.0.0
+//
+// @author F. Malpartida - fmalpartida@gmail.com
+// ---------------------------------------------------------------------------
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+
+#if (ARDUINO < 100)
+#include <WProgram.h>
+#else
+#include <Arduino.h>
+#endif
+#include <LCD.h>
+
+// CLASS CONSTRUCTORS
+// ---------------------------------------------------------------------------
+// Constructor
+LCD::LCD ()
+{
+
+}
+
+// PUBLIC METHODS
+// ---------------------------------------------------------------------------
+
+// Common LCD Commands
+// ---------------------------------------------------------------------------
+void LCD::clear()
+{
+ command(LCD_CLEARDISPLAY); // clear display, set cursor position to zero
+ delayMicroseconds(HOME_CLEAR_EXEC); // this command is time consuming
+}
+
+void LCD::home()
+{
+ command(LCD_RETURNHOME); // set cursor position to zero
+ delayMicroseconds(HOME_CLEAR_EXEC); // This command is time consuming
+}
+
+void LCD::setCursor(uint8_t col, uint8_t row)
+{
+ int row_offsetsDef[] = { 0x00, 0x40, 0x14, 0x54 }; // For regular LCDs
+ int row_offsetsLarge[] = { 0x00, 0x40, 0x10, 0x50 }; // For 16x4 LCDs
+
+ if ( row >= _numlines )
+ {
+ row = _numlines-1; // rows start at 0
+ }
+
+ // 16x4 LCDs have special memory map layout
+ // ----------------------------------------
+ if ( _cols == 16 && _numlines == 4 )
+ {
+ command(LCD_SETDDRAMADDR | (col + row_offsetsLarge[row]));
+ }
+ else
+ {
+ command(LCD_SETDDRAMADDR | (col + row_offsetsDef[row]));
+ }
+
+}
+
+// Turn the display on/off
+void LCD::noDisplay()
+{
+ _displaycontrol &= ~LCD_DISPLAYON;
+ command(LCD_DISPLAYCONTROL | _displaycontrol);
+}
+
+void LCD::display()
+{
+ _displaycontrol |= LCD_DISPLAYON;
+ command(LCD_DISPLAYCONTROL | _displaycontrol);
+}
+
+// Turns the underline cursor on/off
+void LCD::noCursor()
+{
+ _displaycontrol &= ~LCD_CURSORON;
+ command(LCD_DISPLAYCONTROL | _displaycontrol);
+}
+void LCD::cursor()
+{
+ _displaycontrol |= LCD_CURSORON;
+ command(LCD_DISPLAYCONTROL | _displaycontrol);
+}
+
+// Turns on/off the blinking cursor
+void LCD::noBlink()
+{
+ _displaycontrol &= ~LCD_BLINKON;
+ command(LCD_DISPLAYCONTROL | _displaycontrol);
+}
+
+void LCD::blink()
+{
+ _displaycontrol |= LCD_BLINKON;
+ command(LCD_DISPLAYCONTROL | _displaycontrol);
+}
+
+// These commands scroll the display without changing the RAM
+void LCD::scrollDisplayLeft(void)
+{
+ command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT);
+}
+
+void LCD::scrollDisplayRight(void) {
+ command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT);
+}
+
+// This is for text that flows Left to Right
+void LCD::leftToRight(void)
+{
+ _displaymode |= LCD_ENTRYLEFT;
+ command(LCD_ENTRYMODESET | _displaymode);
+}
+
+// This is for text that flows Right to Left
+void LCD::rightToLeft(void)
+{
+ _displaymode &= ~LCD_ENTRYLEFT;
+ command(LCD_ENTRYMODESET | _displaymode);
+}
+
+// This will 'right justify' text from the cursor
+void LCD::autoscroll(void)
+{
+ _displaymode |= LCD_ENTRYSHIFTINCREMENT;
+ command(LCD_ENTRYMODESET | _displaymode);
+}
+
+// This will 'left justify' text from the cursor
+void LCD::noAutoscroll(void)
+{
+ _displaymode &= ~LCD_ENTRYSHIFTINCREMENT;
+ command(LCD_ENTRYMODESET | _displaymode);
+}
+
+// Write to CGRAM of new characters
+void LCD::createChar(uint8_t location, uint8_t charmap[])
+{
+ location &= 0x7; // we only have 8 locations 0-7
+
+ command(LCD_SETCGRAMADDR | (location << 3));
+
+ for (int i=0; i<8; i++)
+ {
+ write(charmap[i]); // call the virtual write method
+ }
+}
+
+// General LCD commands - generic methods used by the rest of the commands
+// ---------------------------------------------------------------------------
+void LCD::command(uint8_t value)
+{
+ send(value, COMMAND);
+}
+
+#if (ARDUINO < 100)
+void LCD::write(uint8_t value)
+{
+ send(value, DATA);
+}
+#else
+size_t LCD::write(uint8_t value)
+{
+ send(value, DATA);
+ return 1; // assume OK
+}
+#endif
402 LCD.h
@@ -0,0 +1,402 @@
+// ---------------------------------------------------------------------------
+// Created by Francisco Malpartida on 20/08/11.
+// Copyright 2011 - Under creative commons license 3.0:
+// Attribution-ShareAlike CC BY-SA
+//
+// This software is furnished "as is", without technical support, and with no
+// warranty, express or implied, as to its usefulness for any purpose.
+//
+// Thread Safe: No
+// Extendable: Yes
+//
+// @file LiquidCrystal.h
+// This file implements a basic liquid crystal library that comes as standard
+// in the Arduino SDK.
+//
+// @brief
+// This is a basic implementation of the LiquidCrystal library of the
+// Arduino SDK. This library is a refactored version of the one supplied
+// in the Arduino SDK in such a way that it simplifies its extension
+// to support other mechanism to communicate to LCDs such as I2C, Serial.
+// The original library has been reworked in such a way that this will be
+// the base class implementing all generic methods to command an LCD based
+// on the Hitachi HD44780 and compatible chipsets.
+//
+// This base class is a pure abstract class and needs to be extended. As reference,
+// it has been extended to drive 4 and 8 bit mode control, LCDs and I2C extension
+// backpacks such as the I2CLCDextraIO using the PCF8574* I2C IO Expander ASIC.
+//
+//
+// This library is only compatible with Arduino's SDK version 1.0
+//
+// @version API 1.0.0
+//
+//
+// @author F. Malpartida - fmalpartida@gmail.com
+// ---------------------------------------------------------------------------
+#ifndef _LCD_H_
+#define _LCD_H_
+#include <inttypes.h>
+#include <Print.h>
+
+/*!
+ @defined
+ @abstract Enables disables fast waits for write operations for LCD
+ @discussion If defined, the library will avoid doing un-necessary waits.
+ this can be done, because the time taken by Arduino's slow digitalWrite
+ operations. If fast digitalIO operations, comment this line out or undefine
+ the mode.
+ */
+#define FAST_MODE
+
+/*!
+ @defined
+ @abstract All these definitions shouldn't be used unless you are writing
+ a driver.
+ @discussion All these definitions are for driver implementation only and
+ shouldn't be used by applications.
+ */
+// LCD Commands
+// ---------------------------------------------------------------------------
+#define LCD_CLEARDISPLAY 0x01
+#define LCD_RETURNHOME 0x02
+#define LCD_ENTRYMODESET 0x04
+#define LCD_DISPLAYCONTROL 0x08
+#define LCD_CURSORSHIFT 0x10
+#define LCD_FUNCTIONSET 0x20
+#define LCD_SETCGRAMADDR 0x40
+#define LCD_SETDDRAMADDR 0x80
+
+// flags for display entry mode
+// ---------------------------------------------------------------------------
+#define LCD_ENTRYRIGHT 0x00
+#define LCD_ENTRYLEFT 0x02
+#define LCD_ENTRYSHIFTINCREMENT 0x01
+#define LCD_ENTRYSHIFTDECREMENT 0x00
+
+// flags for display on/off and cursor control
+// ---------------------------------------------------------------------------
+#define LCD_DISPLAYON 0x04
+#define LCD_DISPLAYOFF 0x00
+#define LCD_CURSORON 0x02
+#define LCD_CURSOROFF 0x00
+#define LCD_BLINKON 0x01
+#define LCD_BLINKOFF 0x00
+
+// flags for display/cursor shift
+// ---------------------------------------------------------------------------
+#define LCD_DISPLAYMOVE 0x08
+#define LCD_CURSORMOVE 0x00
+#define LCD_MOVERIGHT 0x04
+#define LCD_MOVELEFT 0x00
+
+// flags for function set
+// ---------------------------------------------------------------------------
+#define LCD_8BITMODE 0x10
+#define LCD_4BITMODE 0x00
+#define LCD_2LINE 0x08
+#define LCD_1LINE 0x00
+#define LCD_5x10DOTS 0x04
+#define LCD_5x8DOTS 0x00
+
+#define LCD_4BIT 1
+#define LCD_8BIT 0
+
+// Define COMMAND and DATA LCD Rs
+// ---------------------------------------------------------------------------
+#define COMMAND 0
+#define DATA 1
+
+/*!
+ @defined
+ @abstract Defines the duration of the home and clear commands
+ @discussion This constant defines the time it takes for the home and clear
+ commands in the LCD - Time in microseconds.
+*/
+#define HOME_CLEAR_EXEC 2000
+
+class LCD : public Print
+{
+public:
+
+ /*!
+ @method
+ @abstract LiquidCrystal abstract constructor.
+ @discussion LiquidCrystal class abstract constructor needed to create
+ the base abstract class.
+ */
+ LCD ( );
+
+ /*!
+ @function
+ @abstract LCD initialization.
+ @discussion Initializes the LCD to a given size (col, row). This methods
+ initializes the LCD, therefore, it MUST be called prior to using any other
+ method from this class.
+
+ This method is pure abstract, it is dependent on each derived class from
+ this base class to implement the internals of how the LCD is initialized
+ and configured.
+
+ @param cols[in] the number of columns that the display has
+ @param rows[in] the number of rows that the display has
+ */
+#if (ARDUINO < 100)
+ virtual void begin(uint8_t cols, uint8_t rows, uint8_t charsize = LCD_5x8DOTS) { };
+#else
+ virtual void begin(uint8_t cols, uint8_t rows, uint8_t charsize = LCD_5x8DOTS) = 0;
+#endif
+
+ /*!
+ @function
+ @abstract Clears the LCD.
+ @discussion Clears the LCD screen and positions the cursor in the upper-left
+ corner.
+
+ This operation is time consuming for the LCD.
+
+ @param none
+ */
+ void clear();
+
+ /*!
+ @function
+ @abstract Sets the cursor to the upper-left corner.
+ @discussion Positions the cursor in the upper-left of the LCD.
+ That is, use that location in outputting subsequent text to the display.
+ To also clear the display, use the clear() function instead.
+
+ This operation is time consuming for the LCD.
+
+ @param none
+ */
+ void home();
+
+ /*!
+ @function
+ @abstract Turns off the LCD display.
+ @discussion Turns off the LCD display, without losing the text currently
+ being displayed on it.
+
+ @param none
+ */
+ void noDisplay();
+
+ /*!
+ @function
+ @abstract Turns on the LCD display.
+ @discussion Turns on the LCD display, after it's been turned off with
+ noDisplay(). This will restore the text (and cursor location) that was on
+ the display prior to calling noDisplay().
+
+ @param none
+ */
+ void display();
+
+ /*!
+ @function
+ @abstract Turns off the blinking of the LCD cursor.
+
+ @param none
+ */
+ void noBlink();
+
+ /*!
+ @function
+ @abstract Display the cursor of the LCD.
+ @discussion Display the blinking LCD cursor. If used in combination with
+ the cursor() function, the result will depend on the particular display.
+
+ @param none
+ */
+ void blink();
+
+ /*!
+ @function
+ @abstract Hides the LCD cursor.
+
+ @param none
+ */
+ void noCursor();
+
+ /*!
+ @function
+ @abstract Display the LCD cursor.
+ @discussion Display the LCD cursor: an underscore (line) at the location
+ where the next character will be written.
+
+ @param none
+ */
+ void cursor();
+
+ /*!
+ @function
+ @abstract Scrolls the contents of the display (text and cursor) one space
+ to the left.
+
+ @param none
+ */
+ void scrollDisplayLeft();
+
+ /*!
+ @function
+ @abstract Scrolls the contents of the display (text and cursor) one space
+ to the right.
+
+ @param none
+ */
+ void scrollDisplayRight();
+
+ /*!
+ @function
+ @abstract Set the direction for text written to the LCD to left-to-right.
+ @discussion Set the direction for text written to the LCD to left-to-right.
+ All subsequent characters written to the display will go from left to right,
+ but does not affect previously-output text.
+
+ This is the default configuration.
+
+ @param none
+ */
+ void leftToRight();
+
+ /*!
+ @function
+ @abstract Set the direction for text written to the LCD to right-to-left.
+ @discussion Set the direction for text written to the LCD to right-to-left.
+ All subsequent characters written to the display will go from right to left,
+ but does not affect previously-output text.
+
+ left-to-right is the default configuration.
+
+ @param none
+ */
+ void rightToLeft();
+
+ /*!
+ @function
+ @abstract Turns on automatic scrolling of the LCD.
+ @discussion Turns on automatic scrolling of the LCD. This causes each
+ character output to the display to push previous characters over by one
+ space. If the current text direction is left-to-right (the default),
+ the display scrolls to the left; if the current direction is right-to-left,
+ the display scrolls to the right.
+ This has the effect of outputting each new character to the same location on
+ the LCD.
+
+ @param none
+ */
+ void autoscroll();
+
+ /*!
+ @function
+ @abstract Turns off automatic scrolling of the LCD.
+ @discussion Turns off automatic scrolling of the LCD, this is the default
+ configuration of the LCD.
+
+ @param none
+ */
+ void noAutoscroll();
+
+ /*!
+ @function
+ @abstract Creates a custom character for use on the LCD.
+ @discussion Create a custom character (glyph) for use on the LCD.
+ Most chipsets only support up to eight characters of 5x8 pixels. Therefore,
+ this methods has been limited to locations (numbered 0 to 7).
+
+ The appearance of each custom character is specified by an array of eight
+ bytes, one for each row. The five least significant bits of each byte
+ determine the pixels in that row. To display a custom character on screen,
+ write()/print() its number, i.e. lcd.print (char(x)); // Where x is 0..7.
+
+ @param location[in] LCD memory location of the character to create
+ (0 to 7)
+ @param charmap[in] the bitmap array representing each row of the character.
+ */
+ void createChar(uint8_t location, uint8_t charmap[]);
+
+ /*!
+ @function
+ @abstract Position the LCD cursor.
+ @discussion Sets the position of the LCD cursor. Set the location at which
+ subsequent text written to the LCD will be displayed.
+
+ @param col[in] LCD column
+ @param row[in] LCD row - line.
+ */
+ void setCursor(uint8_t col, uint8_t row);
+
+
+ /*!
+ @function
+ @abstract Send a command to the LCD.
+ @discussion This method sends a command to the LCD by setting the Register
+ select line of the LCD.
+
+ This command shouldn't be used to drive the LCD, only to implement any other
+ feature that is not available on this library.
+
+ @param value[in] Command value to send to the LCD.
+ */
+ void command(uint8_t value);
+
+ /*!
+ @function
+ @abstract Writes to the LCD.
+ @discussion This method writes character to the LCD in the current cursor
+ position.
+
+ This is the virtual write method, implemented in the Print class, therefore
+ all Print class methods will end up calling this method.
+
+ @param value[in] Value to write to the LCD.
+ */
+#if (ARDUINO < 100)
+ virtual void write(uint8_t value);
+#else
+ virtual size_t write(uint8_t value);
+#endif
+
+
+ /*!
+ @function
+ @abstract Send a particular value to the LCD.
+ @discussion Sends a particular value to the LCD. This is a pure abstract
+ method, therefore, it is implementation dependent of each derived class how
+ to physically write to the LCD.
+
+ Users should never call this method.
+
+ @param value[in] Value to send to the LCD.
+ @result mode LOW - write to the LCD CGRAM, HIGH - write a command to
+ the LCD.
+ */
+#if (ARDUINO < 100)
+ virtual void send(uint8_t value, uint8_t mode) { };
+#else
+ virtual void send(uint8_t value, uint8_t mode) = 0;
+#endif
+
+#if (ARDUINO < 100)
+ using Print::write;
+#else
+ using Print::write;
+#endif
+
+protected:
+ // Internal LCD variables to control the LCD shared between all derived
+ // classes.
+ uint8_t _displayfunction; // LCD_5x10DOTS or LCD_5x8DOTS, LCD_4BITMODE or
+ // LCD_8BITMODE, LCD_1LINE or LCD_2LINE
+ uint8_t _displaycontrol; // LCD base control command LCD on/off, blink, cursor
+ // all commands are "ored" to its contents.
+ uint8_t _displaymode; // Text entry mode to the LCD
+ uint8_t _numlines; // Number of lines of the LCD, initialized with begin()
+ uint8_t _cols; // Number of columns in the LCD
+
+private:
+
+};
+
+#endif
321 LiquidCrystal.cpp
@@ -0,0 +1,321 @@
+// ---------------------------------------------------------------------------
+// Created by Francisco Malpartida on 20/08/11.
+// Copyright 2011 - Under creative commons license 3.0:
+// Attribution-ShareAlike CC BY-SA
+//LiquidCrystal
+// This software is furnished "as is", without technical support, and with no
+// warranty, express or implied, as to its usefulness for any purpose.
+//
+// Thread Safe: No
+// Extendable: Yes
+//
+// @file LiquidCrystal.cpp
+// This file implements a basic liquid crystal library that comes as standard
+// in the Arduino SDK.
+//
+// @brief
+// This is a basic implementation of the LiquidCrystal library of the
+// Arduino SDK. The original library has been reworked in such a way that
+// this class implements the all methods to command an LCD based
+// on the Hitachi HD44780 and compatible chipsets using the parallel port of
+// the LCD (4 bit and 8 bit).
+//
+// The functionality provided by this class and its base class is identical
+// to the original functionality of the Arduino LiquidCrystal library.
+//
+//
+// This library is only compatible with Arduino's SDK version 1.0
+//
+//
+// @author F. Malpartida - fmalpartida@gmail.com
+// ---------------------------------------------------------------------------
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+
+#if (ARDUINO < 100)
+#include <WProgram.h>
+#else
+#include <Arduino.h>
+#endif
+#include <LiquidCrystal.h>
+
+// STATIC helper routines
+// ---------------------------------------------------------------------------
+/*!
+ @function
+ @abstract waits for a given time in microseconds (compilation dependent).
+ @discussion Waits for a given time defined in microseconds depending on
+ the FAST_MODE define. If the FAST_MODE is defined the call will return
+ inmediatelly.
+ @param uSec[in] time in microseconds.
+ @result None
+*/
+inline static void waitUsec ( uint16_t uSec )
+{
+#ifndef FAST_MODE
+ delayMicroseconds ( uSec );
+#endif // FAST_MODE
+}
+
+// CONSTRUCTORS
+// ---------------------------------------------------------------------------
+LiquidCrystal::LiquidCrystal(uint8_t rs, uint8_t rw, uint8_t enable,
+ uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3,
+ uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7)
+{
+ init(LCD_8BIT, rs, rw, enable, d0, d1, d2, d3, d4, d5, d6, d7);
+}
+
+LiquidCrystal::LiquidCrystal(uint8_t rs, uint8_t enable,
+ uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3,
+ uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7)
+{
+ init(LCD_8BIT, rs, 255, enable, d0, d1, d2, d3, d4, d5, d6, d7);
+}
+
+LiquidCrystal::LiquidCrystal(uint8_t rs, uint8_t rw, uint8_t enable,
+ uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3)
+{
+ init(LCD_4BIT, rs, rw, enable, d0, d1, d2, d3, 0, 0, 0, 0);
+}
+
+LiquidCrystal::LiquidCrystal(uint8_t rs, uint8_t enable,
+ uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3)
+{
+ init(LCD_4BIT, rs, 255, enable, d0, d1, d2, d3, 0, 0, 0, 0);
+}
+
+// PRIVATE METHODS
+// ---------------------------------------------------------------------------
+
+// When the display powers up, it is configured as follows:
+//
+// 1. Display clear
+// 2. Function set:
+// DL = 1; 8-bit interface data
+// N = 0; 1-line display
+// F = 0; 5x8 dot character font
+// 3. Display on/off control:
+// D = 0; Display off
+// C = 0; Cursor off
+// B = 0; Blinking off
+// 4. Entry mode set:
+// I/D = 1; Increment by 1
+// S = 0; No shift
+//
+// Note, however, that resetting the Arduino doesn't reset the LCD, so we
+// can't assume that its in that state when a sketch starts (and the
+// LiquidCrystal constructor is called).
+// A call to begin() will reinitialize the LCD.
+//
+// init
+void LiquidCrystal::init(uint8_t fourbitmode, uint8_t rs, uint8_t rw, uint8_t enable,
+ uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3,
+ uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7)
+{
+ uint8_t i;
+
+ // Initialize the IO pins
+ // -----------------------
+
+ _rs_pin = rs;
+ _rw_pin = rw;
+ _enable_pin = enable;
+
+ _data_pins[0] = d0;
+ _data_pins[1] = d1;
+ _data_pins[2] = d2;
+ _data_pins[3] = d3;
+ _data_pins[4] = d4;
+ _data_pins[5] = d5;
+ _data_pins[6] = d6;
+ _data_pins[7] = d7;
+
+ // Initialize the IO port direction to OUTPUT
+ // ------------------------------------------
+
+ for ( i = 0; i < 4; i++ )
+ {
+ pinMode ( _data_pins[i], OUTPUT );
+ }
+
+ // Initialize the rest of the ports if it is an 8bit controlled LCD
+ // ----------------------------------------------------------------
+
+ if ( !fourbitmode )
+ {
+ for ( i = 4; i < 8; i++ )
+ {
+ pinMode ( _data_pins[i], OUTPUT );
+ }
+ }
+ pinMode(_rs_pin, OUTPUT);
+
+ // we can save 1 pin by not using RW. Indicate by passing 255 instead of pin#
+ if (_rw_pin != 255)
+ {
+ pinMode(_rw_pin, OUTPUT);
+ }
+
+ pinMode(_enable_pin, OUTPUT);
+
+ // Initialise displaymode functions to defaults: LCD_1LINE and LCD_5x8DOTS
+ // -------------------------------------------------------------------------
+ if (fourbitmode)
+ _displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS;
+ else
+ _displayfunction = LCD_8BITMODE | LCD_1LINE | LCD_5x8DOTS;
+}
+
+// PUBLIC METHODS
+// ---------------------------------------------------------------------------
+
+//
+// begin
+void LiquidCrystal::begin(uint8_t cols, uint8_t lines, uint8_t dotsize)
+{
+ if (lines > 1)
+ {
+ _displayfunction |= LCD_2LINE;
+ }
+ _numlines = lines;
+ _cols = cols;
+
+ // for some 1 line displays you can select a 10 pixel high font
+ // ------------------------------------------------------------
+ if ((dotsize != 0) && (lines == 1))
+ {
+ _displayfunction |= LCD_5x10DOTS;
+ }
+
+ // SEE PAGE 45/46 FOR INITIALIZATION SPECIFICATION!
+ // according to datasheet, we need at least 40ms after power rises above 2.7V
+ // before sending commands. Arduino can turn on way before 4.5V so we'll wait
+ // 50
+ // ---------------------------------------------------------------------------
+ delayMicroseconds(50000);
+
+ // Now we pull both RS and R/W low to begin commands
+ digitalWrite(_rs_pin, LOW);
+ digitalWrite(_enable_pin, LOW);
+
+ if (_rw_pin != 255)
+ {
+ digitalWrite(_rw_pin, LOW);
+ }
+
+ //put the LCD into 4 bit or 8 bit mode
+ // -------------------------------------
+ if (! (_displayfunction & LCD_8BITMODE))
+ {
+ // this is according to the hitachi HD44780 datasheet
+ // figure 24, pg 46
+
+ // we start in 8bit mode, try to set 4 bit mode
+ write4bits(0x03);
+ delayMicroseconds(4500); // wait min 4.1ms
+
+ // second try
+ write4bits(0x03);
+ delayMicroseconds(4500); // wait min 4.1ms
+
+ // third go!
+ write4bits(0x03);
+ delayMicroseconds(150);
+
+ // finally, set to 4-bit interface
+ write4bits(0x02);
+ }
+ else
+ {
+ // this is according to the hitachi HD44780 datasheet
+ // page 45 figure 23
+
+ // Send function set command sequence
+ command(LCD_FUNCTIONSET | _displayfunction);
+ delayMicroseconds(4500); // wait more than 4.1ms
+
+ // second try
+ command(LCD_FUNCTIONSET | _displayfunction);
+ delayMicroseconds(150);
+
+ // third go
+ command(LCD_FUNCTIONSET | _displayfunction);
+ }
+
+ // finally, set # lines, font size, etc.
+ command(LCD_FUNCTIONSET | _displayfunction);
+
+ // turn the display on with no cursor or blinking default
+ _displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF;
+ display();
+
+ // clear the LCD
+ clear();
+
+ // Initialize to default text direction (for romance languages)
+ _displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT;
+ // set the entry mode
+ command(LCD_ENTRYMODESET | _displaymode);
+
+}
+
+/************ low level data pushing commands **********/
+
+// send
+void LiquidCrystal::send(uint8_t value, uint8_t mode)
+{
+ digitalWrite( _rs_pin, mode );
+
+ // if there is a RW pin indicated, set it low to Write
+ // ---------------------------------------------------
+ if (_rw_pin != 255)
+ {
+ digitalWrite(_rw_pin, LOW);
+ }
+
+ if (_displayfunction & LCD_8BITMODE)
+ {
+ write8bits(value);
+ }
+ else
+ {
+ write4bits ( value >> 4 );
+ write4bits ( value );
+ }
+ waitUsec ( EXEC_TIME ); // wait for the command to execute by the LCD
+}
+
+//
+// pulseEnable
+void LiquidCrystal::pulseEnable(void)
+{
+ // There is no need for the delays, since the digitalWrite operation
+ // takes longer.
+ digitalWrite(_enable_pin, HIGH);
+ waitUsec(1); // enable pulse must be > 450ns
+ digitalWrite(_enable_pin, LOW);
+}
+
+//
+// write4bits
+void LiquidCrystal::write4bits(uint8_t value)
+{
+ for (uint8_t i = 0; i < 4; i++)
+ {
+ digitalWrite(_data_pins[i], (value >> i) & 0x01);
+ }
+ pulseEnable();
+}
+
+//
+// write8bits
+void LiquidCrystal::write8bits(uint8_t value)
+{
+ for (uint8_t i = 0; i < 8; i++)
+ {
+ digitalWrite(_data_pins[i], (value >> i) & 0x01);
+ }
+ pulseEnable();
+}
142 LiquidCrystal.h
@@ -0,0 +1,142 @@
+// ---------------------------------------------------------------------------
+// Created by Francisco Malpartida on 20/08/11.
+// Copyright 2011 - Under creative commons license 3.0:
+// Attribution-ShareAlike CC BY-SA
+//
+// This software is furnished "as is", without technical support, and with no
+// warranty, express or implied, as to its usefulness for any purpose.
+//
+// Thread Safe: No
+// Extendable: Yes
+//
+// @file LiquidCrystal.h
+// This file implements a basic liquid crystal library that comes as standard
+// in the Arduino SDK.
+//
+// @brief
+// This is a basic implementation of the LiquidCrystal library of the
+// Arduino SDK. The original library has been reworked in such a way that
+// this class implements the all methods to command an LCD based
+// on the Hitachi HD44780 and compatible chipsets using the parallel port of
+// the LCD (4 bit and 8 bit).
+//
+// The functionality provided by this class and its base class is identical
+// to the original functionality of the Arduino LiquidCrystal library.
+//
+//
+// This library is only compatible with Arduino's SDK version 1.0
+//
+//
+// @author F. Malpartida - fmalpartida@gmail.com
+// ---------------------------------------------------------------------------
+#ifndef LiquidCrystal_4bit_h
+#define LiquidCrystal_4bit_h
+
+#include <inttypes.h>
+#include <LCD.h>
+
+
+/*!
+ @defined
+ @abstract Command execution time on the LCD.
+ @discussion This defines how long a command takes to execute by the LCD.
+ The time is expressed in micro-seconds.
+*/
+#define EXEC_TIME 37
+
+class LiquidCrystal : public LCD
+{
+public:
+ /*!
+ @method
+ @abstract 8 bit LCD constructors.
+ @discussion Defines the pin assignment that the LCD will have.
+ The constructor does not initialize the LCD.
+ */
+ LiquidCrystal(uint8_t rs, uint8_t enable,
+ uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3,
+ uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7);
+ LiquidCrystal(uint8_t rs, uint8_t rw, uint8_t enable,
+ uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3,
+ uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7);
+
+ /*!
+ @method
+ @abstract 4 bit LCD constructors.
+ @discussion Defines the pin assignment that the LCD will have.
+ The constructor does not initialize the LCD.
+ */
+ LiquidCrystal(uint8_t rs, uint8_t rw, uint8_t enable,
+ uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3);
+ LiquidCrystal(uint8_t rs, uint8_t enable,
+ uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3);
+
+ /*!
+ @function
+ @abstract LCD initialization.
+ @discussion Initializes the LCD to a given size (col, row). This methods
+ initializes the LCD, therefore, it MUST be called prior to using any other
+ method from this class or parent class.
+
+ @param cols[in] the number of columns that the display has
+ @param rows[in] the number of rows that the display has
+ @param charsize: size of the characters of the LCD: LCD_5x8DOTS or
+ LCD_5x10DOTS.
+ */
+ virtual void begin(uint8_t cols, uint8_t rows, uint8_t charsize = LCD_5x8DOTS);
+
+ /*!
+ @function
+ @abstract Send a particular value to the LCD.
+ @discussion Sends a particular value to the LCD for writing to the LCD or
+ as an LCD command.
+
+ Users should never call this method.
+
+ @param value Value to send to the LCD.
+ @result mode LOW - write to the LCD CGRAM, HIGH - write a command to
+ the LCD.
+ */
+ virtual void send(uint8_t value, uint8_t mode);
+
+
+private:
+
+ /*!
+ @method
+ @abstract Initializes the LCD pin allocation
+ @discussion Initializes the LCD pin allocation and configuration.
+ */
+ void init(uint8_t fourbitmode, uint8_t rs, uint8_t rw, uint8_t enable,
+ uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3,
+ uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7);
+
+ /*!
+ @method
+ @abstract Writes an 8 bit value to the LCD.
+ @discussion Writes 8 bits to the LCD control data lines.
+ */
+ void write8bits(uint8_t value);
+
+ /*!
+ @method
+ @abstract Writes an 4 bit value to the LCD.
+ @discussion Writes 4 bits (the least significant) to the LCD control data lines.
+ */
+ void write4bits(uint8_t value);
+
+ /*!
+ @method
+ @abstract Pulse the LCD enable line (En).
+ @discussion Sends a pulse of 1 uS to the Enable pin to execute an command
+ or write operation.
+ */
+ void pulseEnable();
+
+ uint8_t _rs_pin; // LOW: command. HIGH: character.
+ uint8_t _rw_pin; // LOW: write to LCD. HIGH: read from LCD.
+ uint8_t _enable_pin; // activated by a HIGH pulse.
+ uint8_t _data_pins[8]; // Data pins.
+};
+
+#endif
288 LiquidCrystal_I2C.cpp
@@ -0,0 +1,288 @@
+// ---------------------------------------------------------------------------
+// Created by Francisco Malpartida on 20/08/11.
+// Copyright 2011 - Under creative commons license 3.0:
+// Attribution-ShareAlike CC BY-SA
+//
+// This software is furnished "as is", without technical support, and with no
+// warranty, express or implied, as to its usefulness for any purpose.
+//
+// Thread Safe: No
+// Extendable: Yes
+//
+// @file LiquidCrystal_I2C.c
+// This file implements a basic liquid crystal library that comes as standard
+// in the Arduino SDK but using an I2C IO extension board.
+//
+// @brief
+// This is a basic implementation of the LiquidCrystal library of the
+// Arduino SDK. The original library has been reworked in such a way that
+// this class implements the all methods to command an LCD based
+// on the Hitachi HD44780 and compatible chipsets using I2C extension
+// backpacks such as the I2CLCDextraIO with the PCF8574* I2C IO Expander ASIC.
+//
+// The functionality provided by this class and its base class is identical
+// to the original functionality of the Arduino LiquidCrystal library.
+//
+//
+// This library is only compatible with Arduino's SDK version 1.0
+//
+//
+// @author F. Malpartida - fmalpartida@gmail.com
+// ---------------------------------------------------------------------------
+#if (ARDUINO < 100)
+#include <WProgram.h>
+#else
+#include <Arduino.h>
+#endif
+#include <inttypes.h>
+#include <I2CIO.h>
+#include <LiquidCrystal_I2C.h>
+
+
+
+// When the display powers up, it is configured as follows:
+//
+// 1. Display clear
+// 2. Function set:
+// DL = 1; 8-bit interface data
+// N = 0; 1-line display
+// F = 0; 5x8 dot character font
+// 3. Display on/off control:
+// D = 0; Display off
+// C = 0; Cursor off
+// B = 0; Blinking off
+// 4. Entry mode set:
+// I/D = 1; Increment by 1
+// S = 0; No shift
+//
+// Note, however, that resetting the Arduino doesn't reset the LCD, so we
+// can't assume that its in that state when a sketch starts (and the
+// LiquidCrystal_I2C constructor is called).
+// A call to begin() will reinitialize the LCD.
+
+// CONSTRUCTORS
+// ---------------------------------------------------------------------------
+LiquidCrystal_I2C::LiquidCrystal_I2C( uint8_t lcd_Addr )
+{
+ _Addr = lcd_Addr;
+
+ _backlightval = LCD_NOBACKLIGHT;
+ _En = EN;
+ _Rw = RW;
+ _Rs = RS;
+
+ // Initialise default values data[0] pin 0, data[1] pin 1, ...
+ for ( uint8_t i = 0; i < 4; i++ )
+ {
+ _data_pins[i] = ( 1 << i );
+ }
+}
+
+LiquidCrystal_I2C::LiquidCrystal_I2C( uint8_t lcd_Addr, uint8_t En, uint8_t Rw,
+ uint8_t Rs)
+{
+ _Addr = lcd_Addr;
+
+ _backlightval = LCD_NOBACKLIGHT;
+ _En = ( 1 << En );
+ _Rw = ( 1 << Rw );
+ _Rs = ( 1 << Rs );
+
+ // Initialise default values data[0] pin 0, data[1] pin 1, ...
+ for ( uint8_t i = 0; i < 4; i++ )
+ {
+ _data_pins[i] = ( 1 << i );
+ }
+}
+
+LiquidCrystal_I2C::LiquidCrystal_I2C( uint8_t lcd_Addr, uint8_t En, uint8_t Rw,
+ uint8_t Rs, uint8_t d0, uint8_t d1,
+ uint8_t d2, uint8_t d3 )
+{
+ _Addr = lcd_Addr;
+
+ _backlightval = LCD_NOBACKLIGHT;
+ _En = ( 1 << En );
+ _Rw = ( 1 << Rw );
+ _Rs = ( 1 << Rs );
+
+ // Initialise pin mapping
+ _data_pins[0] = ( 1 << d0 );
+ _data_pins[1] = ( 1 << d1 );
+ _data_pins[2] = ( 1 << d2 );
+ _data_pins[3] = ( 1 << d3 );
+}
+
+// PRIVATE METHODS
+// ---------------------------------------------------------------------------
+
+//
+// init
+int LiquidCrystal_I2C::init()
+{
+ int status = 0;
+
+ // initialize the backpack IO expander
+ // and display functions.
+ // ------------------------------------------------------------------------
+ if ( _i2cio.begin ( _Addr ) == 1 )
+ {
+ _i2cio.portMode ( OUTPUT ); // Set the entire IO extender to OUTPUT
+ _displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS;
+ status = 1;
+ }
+ return ( status );
+}
+
+
+// PUBLIC METHODS
+// ---------------------------------------------------------------------------
+
+//
+// begin
+void LiquidCrystal_I2C::begin(uint8_t cols, uint8_t lines, uint8_t dotsize)
+{
+
+ init(); // Initialise the I2C expander interface
+
+ if (lines > 1)
+ {
+ _displayfunction |= LCD_2LINE;
+ }
+ _numlines = lines;
+ _cols = cols;
+
+ // for some 1 line displays you can select a 10 pixel high font
+ if ((dotsize != 0) && (lines == 1)) {
+ _displayfunction |= LCD_5x10DOTS;
+ }
+
+ // SEE PAGE 45/46 FOR INITIALIZATION SPECIFICATION!
+ // according to datasheet, we need at least 40ms after power rises above 2.7V
+ // before sending commands. Arduino can turn on way before 4.5V so we'll wait 50
+ delayMicroseconds(50000);
+
+ // Now we pull both RS and R/W low to begin commands
+ expanderWrite ( _backlightval ); // reset expander and turn backlight off (Bit 8 =1)
+ delay(1000);
+
+ //put the LCD into 4 bit mode
+ // this is according to the hitachi HD44780 datasheet
+ // figure 24, pg 46
+
+ // we start in 8bit mode, try to set 4 bit mode
+ write4bits ( 0x03, LOW );
+ delayMicroseconds(4500); // wait min 4.1ms
+
+ // second try
+ write4bits ( 0x03, LOW );
+ delayMicroseconds(4500); // wait min 4.1ms
+
+ // third go!
+ write4bits ( 0x03, LOW );
+ delayMicroseconds(150);
+
+ // finally, set to 4-bit interface
+ write4bits ( 0x02, LOW );
+
+
+ // set # lines, font size, etc.
+ command(LCD_FUNCTIONSET | _displayfunction);
+
+ // turn the display on with no cursor or blinking default
+ _displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF;
+ display();
+
+ // clear it off
+ clear();
+
+ // Initialize to default text direction (for roman languages)
+ _displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT;
+
+ // set the entry mode
+ command(LCD_ENTRYMODESET | _displaymode);
+
+ home();
+
+}
+
+
+// User commands - users can expand this section
+//----------------------------------------------------------------------------
+
+// Turn the (optional) backlight off/on
+void LiquidCrystal_I2C::noBacklight(void)
+{
+ _backlightval=LCD_NOBACKLIGHT;
+ expanderWrite(0);
+}
+
+void LiquidCrystal_I2C::backlight(void)
+{
+ _backlightval=LCD_BACKLIGHT;
+ expanderWrite(0);
+}
+
+// PRIVATE METHODS
+// ---------------------------------------------------------------------------
+
+// low level data pushing commands
+//----------------------------------------------------------------------------
+
+//
+// send - write either command or data
+void LiquidCrystal_I2C::send(uint8_t value, uint8_t mode)
+{
+ // No need to use the delay routines since the time taken to write takes
+ // longer that what is needed both for toggling and enable pin an to execute
+ // the command.
+ write4bits( (value >> 4), mode );
+ write4bits( (value & 0x0F), mode);
+}
+
+//
+// write4bits
+void LiquidCrystal_I2C::write4bits ( uint8_t value, uint8_t mode )
+{
+ uint8_t pinMapValue = 0;
+
+ // Map the value to LCD pin mapping
+ // --------------------------------
+ for ( uint8_t i = 0; i < 4; i++ )
+ {
+ if ( ( value & 0x1 ) == 1 )
+ {
+ pinMapValue |= _data_pins[i];
+ }
+ value = ( value >> 1 );
+ }
+
+ // Is it a command or data
+ // -----------------------
+ if ( mode == DATA )
+ {
+ mode = _Rs;
+ }
+
+ expanderWrite ( pinMapValue | mode );
+ pulseEnable ( pinMapValue | mode );
+}
+
+//
+// write4bits
+void LiquidCrystal_I2C::pulseEnable (uint8_t _data)
+{
+ expanderWrite (_data | _En); // En HIGH
+ expanderWrite(_data & ~_En); // En LOW
+}
+
+//
+// expanderWrite
+void LiquidCrystal_I2C::expanderWrite(uint8_t _data)
+{
+ _i2cio.write ( _data );
+}
+
+
+
+
213 LiquidCrystal_I2C.h
@@ -0,0 +1,213 @@
+// ---------------------------------------------------------------------------
+// Created by Francisco Malpartida on 20/08/11.
+// Copyright 2011 - Under creative commons license 3.0:
+// Attribution-ShareAlike CC BY-SA
+//
+// This software is furnished "as is", without technical support, and with no
+// warranty, express or implied, as to its usefulness for any purpose.
+//
+// Thread Safe: No
+// Extendable: Yes
+//
+// @file LiquidCrystal_I2C.h
+// This file implements a basic liquid crystal library that comes as standard
+// in the Arduino SDK but using an I2C IO extension board.
+//
+// @brief
+// This is a basic implementation of the LiquidCrystal library of the
+// Arduino SDK. The original library has been reworked in such a way that
+// this class implements the all methods to command an LCD based
+// on the Hitachi HD44780 and compatible chipsets using I2C extension
+// backpacks such as the I2CLCDextraIO with the PCF8574* I2C IO Expander ASIC.
+//
+// The functionality provided by this class and its base class is identical
+// to the original functionality of the Arduino LiquidCrystal library.
+//
+//
+// This library is only compatible with Arduino's SDK version 1.0
+//
+//
+// @author F. Malpartida - fmalpartida@gmail.com
+// ---------------------------------------------------------------------------
+#ifndef LiquidCrystal_I2C_h
+#define LiquidCrystal_I2C_h
+#include <inttypes.h>
+#include <Print.h>
+#include <I2CIO.h>
+#include <LCD.h>
+
+// flags for backlight control
+#define LCD_BACKLIGHT 0x00
+#define LCD_NOBACKLIGHT 0x80
+
+/*!
+ @warning These definitions will have to be changed should the IOExpander be
+ connected differently to this default.
+ */
+
+/*!
+ @defined
+ @abstract Enable bit of the LCD
+ @discussion Defines the IO of the expander connected to the LCD Enable
+ */
+#define EN B01000000 // Enable bit
+
+/*!
+ @defined
+ @abstract Read/Write bit of the LCD
+ @discussion Defines the IO of the expander connected to the LCD Rw pin
+ */
+#define RW B00100000 // Read/Write bit
+
+/*!
+ @defined
+ @abstract Register bit of the LCD
+ @discussion Defines the IO of the expander connected to the LCD Register select pin
+ */
+#define RS B00010000 // Register select bit
+
+
+class LiquidCrystal_I2C : public LCD
+{
+public:
+
+ /*!
+ @method
+ @abstract Class constructor.
+ @discussion Initializes class variables and defines the I2C address of the
+ LCD. The constructor does not initialize the LCD.
+
+ @param lcd_Addr[in] I2C address of the IO expansion module. For I2CLCDextraIO,
+ the address can be configured using the on board jumpers.
+ */
+ LiquidCrystal_I2C (uint8_t lcd_Addr);
+
+ /*!
+ @method
+ @abstract Class constructor.
+ @discussion Initializes class variables and defines the I2C address of the
+ LCD. The constructor does not initialize the LCD.
+
+ @param lcd_Addr[in] I2C address of the IO expansion module. For I2CLCDextraIO,
+ the address can be configured using the on board jumpers.
+ @param En[in] LCD En (Enable) pin connected to the IO extender module
+ @param Rw[in] LCD Rw (Read/write) pin connected to the IO extender module
+ @param Rs[in] LCD Rs (Reset) pin connected to the IO extender module
+ */
+ LiquidCrystal_I2C( uint8_t lcd_Addr, uint8_t En, uint8_t Rw, uint8_t Rs);
+
+
+ /*!
+ @method
+ @abstract Class constructor.
+ @discussion Initializes class variables and defines the I2C address of the
+ LCD. The constructor does not initialize the LCD.
+
+ @param lcd_Addr[in] I2C address of the IO expansion module. For I2CLCDextraIO,
+ the address can be configured using the on board jumpers.
+ @param En[in] LCD En (Enable) pin connected to the IO extender module
+ @param Rw[in] LCD Rw (Read/write) pin connected to the IO extender module
+ @param Rs[in] LCD Rs (Reset) pin connected to the IO extender module
+ @param d0[in] LCD data 0 pin map on IO extender module
+ @param d1[in] LCD data 1 pin map on IO extender module
+ @param d2[in] LCD data 2 pin map on IO extender module
+ @param d3[in] LCD data 3 pin map on IO extender module
+ */
+ LiquidCrystal_I2C( uint8_t lcd_Addr, uint8_t En, uint8_t Rw, uint8_t Rs,
+ uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3 );
+
+ /*!
+ @function
+ @abstract LCD initialization.
+ @discussion Initializes the LCD to a given size (col, row). This methods
+ initializes the LCD, therefore, it MUST be called prior to using any other
+ method from this class or parent class.
+
+ @param cols[in] the number of columns that the display has
+ @param rows[in] the number of rows that the display has
+ @param charsize[in] size of the characters of the LCD: LCD_5x8DOTS or
+ LCD_5x10DOTS.
+ */
+ virtual void begin(uint8_t cols, uint8_t rows, uint8_t charsize = LCD_5x8DOTS);
+
+ /*!
+ @function
+ @abstract Send a particular value to the LCD.
+ @discussion Sends a particular value to the LCD for writing to the LCD or
+ as an LCD command.
+
+ Users should never call this method.
+
+ @param value[in] Value to send to the LCD.
+ @param mode[in] DATA - write to the LCD CGRAM, COMMAND - write a
+ command to the LCD.
+ */
+ virtual void send(uint8_t value, uint8_t mode);
+
+ /*!
+ @function
+ @abstract Switch-off the LCD backlight.
+ @discussion Switch-off the LCD backlight, this method is not supported by
+ the I2CLCDextraIO, it needs an extra IO pin to drive the LCD backlight
+
+ @param none
+ */
+ void noBacklight();
+
+ /*!
+ @function
+ @abstract Switch-on the LCD backlight.
+ @discussion Switch-on the LCD backlight, this method is not supported by
+ the I2CLCDextraIO, it needs an extra IO pin to drive the LCD backlight
+
+ @param none
+ */
+ void backlight();
+
+
+private:
+
+ /*!
+ @method
+ @abstract Initializes the LCD class
+ @discussion Initializes the LCD class and IO expansion module.
+ */
+ int init();
+
+ /*!
+ @method
+ @abstract Writes an 4 bit value to the LCD.
+ @discussion Writes 4 bits (the least significant) to the LCD control data lines.
+ @param value[in] Value to write to the LCD
+ @param more[in] Value to distinguish between command and data.
+ COMMAND == command, DATA == data.
+ */
+ void write4bits(uint8_t value, uint8_t mode);
+
+ /*!
+ @method
+ @abstract Pulse the LCD enable line (En).
+ @discussion Sends a pulse of 1 uS to the Enable pin to execute an command
+ or write operation.
+ */
+ void pulseEnable(uint8_t);
+
+ /*!
+ @method
+ @abstract Writes to the expansion module.
+ @discussion Writes a byte to the IO expansion module. This will be applied
+ to all its outputs.
+ */
+ void expanderWrite(uint8_t);
+
+ uint8_t _Addr; // I2C Address of the IO expander
+ uint8_t _backlightval; // Backlight shadow value
+ I2CIO _i2cio; // I2CIO PCF8574* expansion module driver I2CLCDextraIO
+ uint8_t _En; // LCD expander word for enable pin
+ uint8_t _Rw; // LCD expander word for R/W pin
+ uint8_t _Rs; // LCD expander word for Register Select pin
+ uint8_t _data_pins[4]; // LCD data lines
+
+};
+
+#endif
298 LiquidCrystal_SR.cpp
@@ -0,0 +1,298 @@
+// ---------------------------------------------------------------------------
+// Created by Francisco Malpartida on 20/08/11.
+// Copyright 2011 - Under creative commons license 3.0:
+// Attribution-ShareAlike CC BY-SA
+//
+// This software is furnished "as is", without technical support, and with no
+// warranty, express or implied, as to its usefulness for any purpose.
+//
+// Thread Safe: No
+// Extendable: Yes
+//
+// @file LiquidCrystal_SR.h
+// Connects an LCD using 2 or 3 pins from the Arduino, via an 8-bit
+// ShiftRegister (SR from now on).
+//
+// @brief
+// This is a port of the ShiftRegLCD library from raron and ported to the
+// LCD library.
+//
+// The functionality provided by this class and its base class is identical
+// to the original functionality of the Arduino LiquidCrystal library and can
+// be used as such.
+//
+// Modified to work serially with the shiftOut() function, an 8-bit shiftregister
+// (SR) and an LCD in 4-bit mode.
+//
+// Shiftregister connection description (NEW as of 2009.07.27)
+//
+// Bit #0 - N/C - not connected, used to hold a zero
+// Bits #1 - N/C
+// Bit #2 - connects to RS (Register Select) on the LCD
+// Bits #3 - #6 from SR connects to LCD data inputs D4 - D7.
+// Bit #7 - is used to enabling the enable-puls (via a diode-resistor AND "gate")
+//
+// 2 or 3 Pins required from the Arduino for Data, Clock, and Enable (optional).
+// If not using Enable, the Data pin is used for the enable signal by defining
+// the same pin for Enable as for Data. Data and Clock outputs/pins goes to the
+// shiftregister.
+// LCD RW-pin hardwired to LOW (only writing to LCD). Busy Flag (BF, data bit D7)
+// is not read.
+//
+// Any shift register should do. I used 74LS164, for the reason that's what I
+// had at hand.
+//
+// Original project homepage: http://code.google.com/p/arduinoshiftreglcd/
+//
+// History
+// 2011.10.29 fmalpartida - adaption of the library to the LCD class hierarchy.
+// 2009.05.23 raron - but; based mostly (as in almost verbatim) on the
+// "official" LiquidCrystal library.
+// 2009.07.23 Incorporated some proper initialization routines
+// inspired (lets say copy-paste-tweaked) from LiquidCrystal library
+// improvements from LadyAda
+// 2009.07.25 raron - Fixed comments. I really messed up the comments before
+// posting this, so I had to fix it.
+// Also renamed a function, but no improvements or functional changes.
+// 2009.07.27 Thanks to an excellent suggestion from mircho at the Arduiono
+// playgrond forum, the number of wires now required is only two!
+// 2009.07.28 Mircho / raron - a new modification to the schematics, and a more
+// streamlined interface
+// 2009.07.30 raron - minor corrections to the comments. Fixed keyword highlights.
+// Fixed timing to datasheet safe.
+// 2011.07.02 Fixed a minor flaw in setCursor function. No functional change,
+// just a bit more memory efficient.
+// Thanks to CapnBry (from google code and github) who noticed it.
+// URL to his version of shiftregLCD:
+//https://github.com/CapnBry/HeaterMeter/commit/c6beba1b46b092ab0b33bcbd0a30a201fd1f28c1
+//
+//
+// This library is only compatible with Arduino's SDK version 1.0
+//
+//
+// @author F. Malpartida - fmalpartida@gmail.com
+// ---------------------------------------------------------------------------
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+
+#if (ARDUINO < 100)
+#include <WProgram.h>
+#else
+#include <Arduino.h>
+#endif
+#include <LiquidCrystal_SR.h>
+
+// When the display powers up, it is configured as follows:
+//
+// 1. Display clear
+// 2. Function set:
+// DL = 1; 8-bit interface data
+// N = 0; 1-line display
+// F = 0; 5x8 dot character font
+// 3. Display on/off control:
+// D = 0; Display off
+// C = 0; Cursor off
+// B = 0; Blinking off
+// 4. Entry mode set:
+// I/D = 1; Increment by 1
+// S = 0; No shift
+//
+// Note, however, that resetting the Arduino doesn't reset the LCD, so we
+// can't assume that its in that state when a sketch starts (and the
+// LiquidCrystal constructor is called).
+// A call to begin() will reinitialize the LCD.
+
+// STATIC helper routines
+// ---------------------------------------------------------------------------
+/*!
+ @function
+ @abstract waits for a given time in microseconds (compilation dependent).
+ @discussion Waits for a given time defined in microseconds depending on
+ the FAST_MODE define. If the FAST_MODE is defined the call will return
+ inmediatelly.
+ @param uSec[in] time in microseconds.
+ @result None
+ */
+inline static void waitUsec ( uint16_t uSec )
+{
+#ifndef FAST_MODE
+ delayMicroseconds ( uSec );
+#endif // FAST_MODE
+}
+
+
+// CONSTRUCTORS
+// ---------------------------------------------------------------------------
+// Assuming 1 line 8 pixel high font
+LiquidCrystal_SR::LiquidCrystal_SR ( uint8_t srdata, uint8_t srclock,
+ uint8_t enable )
+{
+ init ( srdata, srclock, enable, 1, 0 );
+}
+// Set nr. of lines, assume 8 pixel high font
+LiquidCrystal_SR::LiquidCrystal_SR ( uint8_t srdata, uint8_t srclock,
+ uint8_t enable, uint8_t lines )
+{
+ init ( srdata, srclock, enable, lines, 0 );
+}
+
+// Set nr. of lines and font
+LiquidCrystal_SR::LiquidCrystal_SR ( uint8_t srdata, uint8_t srclock,
+ uint8_t enable, uint8_t lines,
+ uint8_t font )
+{
+ init ( srdata, srclock, enable, lines, font );
+}
+
+
+// PRIVATE METHODS
+// ---------------------------------------------------------------------------
+
+//
+// init
+void LiquidCrystal_SR::init( uint8_t srdata, uint8_t srclock, uint8_t enable,
+ uint8_t lines, uint8_t font )
+{
+ // Initialise private variables
+ _two_wire = 0;
+ _srdata_pin = srdata;
+ _srclock_pin = srclock;
+ _enable_pin = enable;
+
+ if (enable == TWO_WIRE)
+ {
+ _enable_pin = _srdata_pin;
+ _two_wire = 1;
+ }
+
+ // Configure control pins as outputs
+ // ------------------------------------------------------------------------
+ pinMode(_srclock_pin, OUTPUT);
+ pinMode(_srdata_pin, OUTPUT);
+ pinMode(_enable_pin, OUTPUT);
+
+ _displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x10DOTS;
+}
+
+// PUBLIC METHODS
+// ---------------------------------------------------------------------------
+
+//
+// begin
+void LiquidCrystal_SR::begin(uint8_t cols, uint8_t lines, uint8_t dotsize)
+{
+
+ if (lines > 1)
+ {
+ _displayfunction |= LCD_2LINE;
+ }
+
+ _numlines = lines;
+ _cols = cols;
+
+ // for some 1 line displays you can select a 10 pixel high font
+ // ------------------------------------------------------------
+ if ((dotsize != 0) && (lines == 1))
+ {
+ _displayfunction |= LCD_5x10DOTS;
+ }
+
+ // SEE PAGE 45/46 FOR INITIALIZATION SPECIFICATION!
+ // according to datasheet, we need at least 40ms after power rises above 2.7V
+ // before sending commands. Arduino can turn on way before 4.5V so we'll wait
+ // 50
+ // ---------------------------------------------------------------------------
+ delayMicroseconds(50000);
+ init4bits(LCD_FUNCTIONSET | LCD_8BITMODE);
+ delayMicroseconds(4500); // wait more than 4.1ms
+
+ // Second try
+ init4bits(LCD_FUNCTIONSET | LCD_8BITMODE);
+ delayMicroseconds(150);
+ // Third go
+ init4bits(LCD_FUNCTIONSET | LCD_8BITMODE);
+
+ // And finally, set to 4-bit interface
+ init4bits(LCD_FUNCTIONSET | LCD_4BITMODE);
+
+ // Set # lines, font size, etc.
+ command(LCD_FUNCTIONSET | _displayfunction);
+ // Turn the display on with no cursor or blinking default
+ _displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF;
+ display();
+ // Clear it off
+ clear();
+ // Initialize to default text direction (for romance languages)
+ _displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT;
+ // set the entry mode
+ command(LCD_ENTRYMODESET | _displaymode);
+ home();
+
+}
+
+/************ low level data pushing commands **********/
+
+// send
+void LiquidCrystal_SR::send(uint8_t value, uint8_t mode)
+{
+ uint8_t val1, val2;
+
+ // If _two_wire - clear the shiftregister first.
+ // ----------------------------------------------
+ if ( _two_wire )
+ {
+ shiftOut ( _srdata_pin, _srclock_pin, MSBFIRST, 0x00 );
+ }
+ digitalWrite( _enable_pin, LOW );
+
+ mode = mode ? SR_RS_BIT : 0; // RS bit; LOW: command. HIGH: character.
+ val1 = mode | SR_EN_BIT | ((value >> 1) & 0x78); // upper nibble
+ val2 = mode | SR_EN_BIT | ((value << 3) & 0x78); // lower nibble
+
+ shiftOut ( _srdata_pin, _srclock_pin, MSBFIRST, val1 );
+
+ digitalWrite( _enable_pin, HIGH );
+ waitUsec( 1 ); // enable pulse must be >450ns
+ digitalWrite( _enable_pin, LOW );
+
+ // clear shiftregister
+ // ---------------------------
+ if ( _two_wire )
+ {
+ shiftOut ( _srdata_pin, _srclock_pin, MSBFIRST, 0x00 );
+ }
+ shiftOut ( _srdata_pin, _srclock_pin, MSBFIRST, val2 );
+
+ digitalWrite( _enable_pin, HIGH );
+ waitUsec( 1 ); // enable pulse must be >450ns
+ digitalWrite( _enable_pin, LOW );
+ waitUsec( 40 ); // commands need > 37us to settle
+}
+
+//
+// init4bits
+void LiquidCrystal_SR::init4bits(uint8_t value)
+{
+ uint8_t val1;
+
+ // clear shiftregister
+ // --------------------------
+ if ( _two_wire )
+ {
+ shiftOut ( _srdata_pin, _srclock_pin, MSBFIRST, 0x00 );
+ }
+ digitalWrite( _enable_pin, LOW );
+
+ val1 = SR_EN_BIT | ((value >> 1) & 0x78);
+ shiftOut ( _srdata_pin, _srclock_pin, MSBFIRST, val1 );
+
+ digitalWrite( _enable_pin, HIGH );
+ waitUsec( 1 ); // enable pulse must be >450ns
+ digitalWrite( _enable_pin, LOW );
+
+ waitUsec( 40 ); // commands need > 37us to settle
+}
+
+
+
166 LiquidCrystal_SR.h
@@ -0,0 +1,166 @@
+// ---------------------------------------------------------------------------
+// Created by Francisco Malpartida on 20/08/11.
+// Copyright 2011 - Under creative commons license 3.0:
+// Attribution-ShareAlike CC BY-SA
+//
+// This software is furnished "as is", without technical support, and with no
+// warranty, express or implied, as to its usefulness for any purpose.
+//
+// Thread Safe: No
+// Extendable: Yes
+//
+// @file LiquidCrystal_SR.h
+// Connects an LCD using 2 or 3 pins from the Arduino, via an 8-bit
+// ShiftRegister (SR from now on).
+//
+// @brief
+// This is a port of the ShiftRegLCD library from raron and ported to the
+// LCD library.
+//
+// The functionality provided by this class and its base class is identical
+// to the original functionality of the Arduino LiquidCrystal library and can
+// be used as such.
+//
+// Modified to work serially with the shiftOut() function, an 8-bit shiftregister
+// (SR) and an LCD in 4-bit mode.
+//
+// Shiftregister connection description (NEW as of 2009.07.27)
+//
+// Bit #0 - N/C - not connected, used to hold a zero
+// Bits #1 - N/C
+// Bit #2 - connects to RS (Register Select) on the LCD
+// Bits #3 - #6 from SR connects to LCD data inputs D4 - D7.
+// Bit #7 - is used to enabling the enable-puls (via a diode-resistor AND "gate")
+//
+// 2 or 3 Pins required from the Arduino for Data, Clock, and Enable (optional).
+// If not using Enable, the Data pin is used for the enable signal by defining
+// the same pin for Enable as for Data. Data and Clock outputs/pins goes to the
+// shiftregister.
+// LCD RW-pin hardwired to LOW (only writing to LCD). Busy Flag (BF, data bit D7)
+// is not read.
+//
+// Any shift register should do. I used 74LS164, for the reason that's what I
+// had at hand.
+//
+// Original project homepage: http://code.google.com/p/arduinoshiftreglcd/
+//
+// History
+// 2011.10.29 fmalpartida - adaption of the library to the LCD class hierarchy.
+// 2009.05.23 raron - but; based mostly (as in almost verbatim) on the
+// "official" LiquidCrystal library.
+// 2009.07.23 Incorporated some proper initialization routines
+// inspired (lets say copy-paste-tweaked) from LiquidCrystal library
+// improvements from LadyAda
+// 2009.07.25 raron - Fixed comments. I really messed up the comments before
+// posting this, so I had to fix it.
+// Also renamed a function, but no improvements or functional changes.
+// 2009.07.27 Thanks to an excellent suggestion from mircho at the Arduiono
+// playgrond forum, the number of wires now required is only two!
+// 2009.07.28 Mircho / raron - a new modification to the schematics, and a more
+// streamlined interface
+// 2009.07.30 raron - minor corrections to the comments. Fixed keyword highlights.
+// Fixed timing to datasheet safe.
+// 2011.07.02 Fixed a minor flaw in setCursor function. No functional change,
+// just a bit more memory efficient.
+// Thanks to CapnBry (from google code and github) who noticed it.
+// URL to his version of shiftregLCD:
+//https://github.com/CapnBry/HeaterMeter/commit/c6beba1b46b092ab0b33bcbd0a30a201fd1f28c1
+//
+//
+// This library is only compatible with Arduino's SDK version 1.0
+//
+//
+// @author F. Malpartida - fmalpartida@gmail.com
+// ---------------------------------------------------------------------------
+#ifndef _LIQUIDCRYSTAL_SR_
+#define _LIQUIDCRYSTAL_SR_
+
+#include <inttypes.h>
+#include <LCD.h>
+
+
+// two-wire indicator constant
+// ---------------------------------------------------------------------------
+#define TWO_WIRE 204
+#define SR_RS_BIT 0x04
+#define SR_EN_BIT 0x80
+
+class LiquidCrystal_SR : public LCD
+{
+public:
+ /*!
+ @method
+ @abstract LCD SHIFT REGISTER constructors.
+ @discussion Defines the pin assignment that the LCD will have.
+ The constructor does not initialize the LCD. Assuming 1 line 8 pixel high
+ font.
+
+ @param srdata[in] pin for shiftregister data line.
+ @param srclock[in] pin for shiftregister clock line.
+ @param enable[in] enable pin for the shiftregister.
+ */
+ LiquidCrystal_SR ( uint8_t srdata, uint8_t srclock, uint8_t enable );
+
+
+ // Set nr. of lines, assume 8 pixel high font
+ LiquidCrystal_SR ( uint8_t srdata, uint8_t srclock, uint8_t enable,
+ uint8_t lines );
+
+ // Set nr. of lines and font
+ LiquidCrystal_SR( uint8_t srdata, uint8_t srclock, uint8_t enable,
+ uint8_t lines, uint8_t font );
+
+
+ /*!
+ @function
+ @abstract LCD initialization.
+ @discussion Initializes the LCD to a given size (col, row). This methods
+ initializes the LCD, therefore, it MUST be called prior to using any other
+ method from this class or parent class.
+
+ @param cols[in] the number of columns that the display has
+ @param rows[in] the number of rows that the display has
+ @param charsize[in] size of the characters of the LCD: LCD_5x8DOTS or
+ LCD_5x10DOTS.
+ */
+ virtual void begin(uint8_t cols, uint8_t rows, uint8_t charsize = LCD_5x8DOTS);
+
+ /*!
+ @function
+ @abstract Send a particular value to the LCD.
+ @discussion Sends a particular value to the LCD for writing to the LCD or
+ as an LCD command using the shift register.
+
+ Users should never call this method.
+
+ @param value[in] Value to send to the LCD.
+ @result mode LOW - write to the LCD CGRAM, HIGH - write a command to
+ the LCD.
+ */
+ virtual void send(uint8_t value, uint8_t mode);
+
+
+private:
+
+ /*!
+ @method
+ @abstract Initializes the LCD pin allocation
+ @discussion Initializes the LCD pin allocation and configuration.
+ */