fm_LiquidCrystal_I2C.cpp 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. // ---------------------------------------------------------------------------
  2. // Created by Francisco Malpartida on 20/08/11.
  3. // Copyright 2011 - Under creative commons license 3.0:
  4. // Attribution-ShareAlike CC BY-SA
  5. //
  6. // This software is furnished "as is", without technical support, and with no
  7. // warranty, express or implied, as to its usefulness for any purpose.
  8. //
  9. // Thread Safe: No
  10. // Extendable: Yes
  11. //
  12. // @file fm_LiquidCrystal_I2C.c
  13. // This file implements a basic liquid crystal library that comes as standard
  14. // in the Arduino SDK but using an I2C IO extension board.
  15. //
  16. // @brief
  17. // This is a basic implementation of the LiquidCrystal library of the
  18. // Arduino SDK. The original library has been reworked in such a way that
  19. // this class implements the all methods to command an fm_LCD based
  20. // on the Hitachi HD44780 and compatible chipsets using I2C extension
  21. // backpacks such as the I2CLCDextraIO with the PCF8574* I2C IO Expander ASIC.
  22. //
  23. // The functionality provided by this class and its base class is identical
  24. // to the original functionality of the Arduino LiquidCrystal library.
  25. //
  26. //
  27. //
  28. // @author F. Malpartida - fmalpartida@gmail.com
  29. // ---------------------------------------------------------------------------
  30. //#if (ARDUINO < 100)
  31. //#include <WProgram.h>
  32. //#else
  33. #include <Arduino.h>
  34. //#endif
  35. //#include <inttypes.h>
  36. //#include "fm_I2CIO.h"
  37. #include "fm_LiquidCrystal_I2C.h"
  38. // CONSTANT definitions
  39. // ---------------------------------------------------------------------------
  40. // flags for backlight control
  41. /*!
  42. @defined
  43. @abstract LCD_NOBACKLIGHT
  44. @discussion NO BACKLIGHT MASK
  45. */
  46. #define LCD_NOBACKLIGHT 0x00
  47. /*!
  48. @defined
  49. @abstract LCD_BACKLIGHT
  50. @discussion BACKLIGHT MASK used when backlight is on
  51. */
  52. #define LCD_BACKLIGHT 0xFF
  53. // Default library configuration parameters used by class constructor with
  54. // only the I2C address field.
  55. // ---------------------------------------------------------------------------
  56. /*!
  57. @defined
  58. @abstract Enable bit of the fm_LCD
  59. @discussion Defines the IO of the expander connected to the fm_LCD Enable
  60. */
  61. #define EN 6 // Enable bit
  62. /*!
  63. @defined
  64. @abstract Read/Write bit of the fm_LCD
  65. @discussion Defines the IO of the expander connected to the fm_LCD Rw pin
  66. */
  67. #define RW 5 // Read/Write bit
  68. /*!
  69. @defined
  70. @abstract Register bit of the fm_LCD
  71. @discussion Defines the IO of the expander connected to the fm_LCD Register select pin
  72. */
  73. #define RS 4 // Register select bit
  74. /*!
  75. @defined
  76. @abstract fm_LCD dataline allocation this library only supports 4 bit fm_LCD control
  77. mode.
  78. @discussion D4, D5, D6, D7 fm_LCD data lines pin mapping of the extender module
  79. */
  80. #define D4 0
  81. #define D5 1
  82. #define D6 2
  83. #define D7 3
  84. // CONSTRUCTORS
  85. // ---------------------------------------------------------------------------
  86. fm_LiquidCrystal_I2C::fm_LiquidCrystal_I2C( uint8_t lcd_Addr )
  87. {
  88. config(lcd_Addr, EN, RW, RS, D4, D5, D6, D7);
  89. }
  90. fm_LiquidCrystal_I2C::fm_LiquidCrystal_I2C(uint8_t lcd_Addr, uint8_t backlighPin,
  91. t_backlighPol pol = POSITIVE)
  92. {
  93. config(lcd_Addr, EN, RW, RS, D4, D5, D6, D7);
  94. setBacklightPin(backlighPin, pol);
  95. }
  96. fm_LiquidCrystal_I2C::fm_LiquidCrystal_I2C(uint8_t lcd_Addr, uint8_t En, uint8_t Rw,
  97. uint8_t Rs)
  98. {
  99. config(lcd_Addr, En, Rw, Rs, D4, D5, D6, D7);
  100. }
  101. fm_LiquidCrystal_I2C::fm_LiquidCrystal_I2C(uint8_t lcd_Addr, uint8_t En, uint8_t Rw,
  102. uint8_t Rs, uint8_t backlighPin,
  103. t_backlighPol pol = POSITIVE)
  104. {
  105. config(lcd_Addr, En, Rw, Rs, D4, D5, D6, D7);
  106. setBacklightPin(backlighPin, pol);
  107. }
  108. fm_LiquidCrystal_I2C::fm_LiquidCrystal_I2C(uint8_t lcd_Addr, uint8_t En, uint8_t Rw,
  109. uint8_t Rs, uint8_t d4, uint8_t d5,
  110. uint8_t d6, uint8_t d7 )
  111. {
  112. config(lcd_Addr, En, Rw, Rs, d4, d5, d6, d7);
  113. }
  114. fm_LiquidCrystal_I2C::fm_LiquidCrystal_I2C(uint8_t lcd_Addr, uint8_t En, uint8_t Rw,
  115. uint8_t Rs, uint8_t d4, uint8_t d5,
  116. uint8_t d6, uint8_t d7, uint8_t backlighPin,
  117. t_backlighPol pol = POSITIVE )
  118. {
  119. config(lcd_Addr, En, Rw, Rs, d4, d5, d6, d7);
  120. setBacklightPin(backlighPin, pol);
  121. }
  122. // PUBLIC METHODS
  123. // ---------------------------------------------------------------------------
  124. //
  125. // begin
  126. void fm_LiquidCrystal_I2C::begin(uint8_t cols, uint8_t lines, uint8_t dotsize)
  127. {
  128. init(); // Initialise the I2C expander interface
  129. fm_LCD::begin ( cols, lines, dotsize );
  130. }
  131. // User commands - users can expand this section
  132. //----------------------------------------------------------------------------
  133. // Turn the (optional) backlight off/on
  134. //
  135. // setBacklightPin
  136. void fm_LiquidCrystal_I2C::setBacklightPin ( uint8_t value, t_backlighPol pol = POSITIVE )
  137. {
  138. _backlightPinMask = ( 1 << value );
  139. _polarity = pol;
  140. setBacklight(BACKLIGHT_OFF);
  141. }
  142. //
  143. // setBacklight
  144. void fm_LiquidCrystal_I2C::setBacklight( uint8_t value )
  145. {
  146. // Check if backlight is available
  147. // ----------------------------------------------------
  148. if ( _backlightPinMask != 0x0 )
  149. {
  150. // Check for polarity to configure mask accordingly
  151. // ----------------------------------------------------------
  152. if (((_polarity == POSITIVE) && (value > 0)) ||
  153. ((_polarity == NEGATIVE ) && ( value == 0 )))
  154. {
  155. _backlightStsMask = _backlightPinMask & LCD_BACKLIGHT;
  156. }
  157. else
  158. {
  159. _backlightStsMask = _backlightPinMask & LCD_NOBACKLIGHT;
  160. }
  161. _i2cio.write( _backlightStsMask );
  162. }
  163. }
  164. // PRIVATE METHODS
  165. // ---------------------------------------------------------------------------
  166. //
  167. // init
  168. int fm_LiquidCrystal_I2C::init()
  169. {
  170. int status = 0;
  171. // initialize the backpack IO expander
  172. // and display functions.
  173. // ------------------------------------------------------------------------
  174. if ( _i2cio.begin ( _Addr ) == 1 )
  175. {
  176. _i2cio.portMode ( OUTPUT ); // Set the entire IO extender to OUTPUT
  177. _displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS;
  178. status = 1;
  179. _i2cio.write(0); // Set the entire port to LOW
  180. }
  181. return ( status );
  182. }
  183. //
  184. // config
  185. void fm_LiquidCrystal_I2C::config (uint8_t lcd_Addr, uint8_t En, uint8_t Rw, uint8_t Rs,
  186. uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7 )
  187. {
  188. _Addr = lcd_Addr;
  189. _backlightPinMask = 0;
  190. _backlightStsMask = LCD_NOBACKLIGHT;
  191. _polarity = POSITIVE;
  192. _En = ( 1 << En );
  193. _Rw = ( 1 << Rw );
  194. _Rs = ( 1 << Rs );
  195. // Initialise pin mapping
  196. _data_pins[0] = ( 1 << d4 );
  197. _data_pins[1] = ( 1 << d5 );
  198. _data_pins[2] = ( 1 << d6 );
  199. _data_pins[3] = ( 1 << d7 );
  200. }
  201. // low level data pushing commands
  202. //----------------------------------------------------------------------------
  203. //
  204. // send - write either command or data
  205. void fm_LiquidCrystal_I2C::send(uint8_t value, uint8_t mode)
  206. {
  207. // No need to use the delay routines since the time taken to write takes
  208. // longer that what is needed both for toggling and enable pin an to execute
  209. // the command.
  210. if (mode == LCD_MODE_4BIT)
  211. {
  212. write4bits( (value & 0x0F), LCD_SEND_CMD );
  213. }
  214. else
  215. {
  216. write4bits( (value >> 4), mode );
  217. write4bits( (value & 0x0F), mode);
  218. }
  219. }
  220. //
  221. // write4bits
  222. void fm_LiquidCrystal_I2C::write4bits ( uint8_t value, uint8_t mode )
  223. {
  224. uint8_t pinMapValue = 0;
  225. // Map the value to fm_LCD pin mapping
  226. // --------------------------------
  227. for ( uint8_t i = 0; i < 4; i++ )
  228. {
  229. if ( ( value & 0x1 ) == 1 )
  230. {
  231. pinMapValue |= _data_pins[i];
  232. }
  233. value = ( value >> 1 );
  234. }
  235. // Is it a command or data
  236. // -----------------------
  237. if ( mode == LCD_SEND_DATA )
  238. {
  239. mode = _Rs;
  240. }
  241. pinMapValue |= mode | _backlightStsMask;
  242. pulseEnable ( pinMapValue );
  243. }
  244. //
  245. // pulseEnable
  246. void fm_LiquidCrystal_I2C::pulseEnable (uint8_t data)
  247. {
  248. //Serial.print('d');
  249. //Serial.print(data);
  250. //Serial.print(';');
  251. #if 0
  252. _i2cio.write (data | _En); // En HIGH
  253. wait(200);
  254. _i2cio.write (data & ~_En); // En LOW
  255. wait(200);
  256. #else
  257. _i2cio.write (data | _En); // En HIGH
  258. _i2cio.write (data & ~_En); // En LOW
  259. #endif
  260. }
  261. void fm_LiquidCrystal_I2C::wait(uint16_t us)
  262. {
  263. //Serial.print('w');
  264. //Serial.print(us);
  265. //Serial.print(';');
  266. #if 0
  267. delayMicroseconds( us );
  268. #else
  269. _i2cio.wait(us);
  270. #endif
  271. }