Class: Denko::Display::HD44780

Inherits:
Object
  • Object
show all
Includes:
Behaviors::MultiPin
Defined in:
lib/denko/display/hd44780.rb

Constant Summary collapse

LCD_CLEARDISPLAY =

Commands

0x01
LCD_RETURNHOME =
0x02
LCD_ENTRYMODESET =
0x04
LCD_DISPLAYCONTROL =
0x08
LCD_CURSORSHIFT =
0x10
LCD_FUNCTIONSET =
0x20
LCD_SETCGRAMADDR =
0x40
LCD_SETDDRAMADDR =
0x80
LCD_ENTRYRIGHT =

Flags for display entry mode

0x00
LCD_ENTRYLEFT =
0x02
LCD_ENTRYSHIFTINCREMENT =
0x01
LCD_ENTRYSHIFTDECREMENT =
0x00
LCD_DISPLAYON =

Flags for display on/off control

0x04
LCD_DISPLAYOFF =
0x00
LCD_CURSORON =
0x02
LCD_CURSOROFF =
0x00
LCD_BLINKON =
0x01
LCD_BLINKOFF =
0x00
LCD_DISPLAYMOVE =

Flags for display/cursor shift

0x08
LCD_CURSORMOVE =
0x00
LCD_MOVERIGHT =
0x04
LCD_MOVELEFT =
0x00
LCD_8BITMODE =

Flags for function set

0x10
LCD_4BITMODE =
0x00
LCD_2LINE =
0x08
LCD_1LINE =
0x00
LCD_5x10DOTS =
0x04
LCD_5x8DOTS =
0x00
CONTROL_TOGGLES =

Create a #key_on and #key_off method for each feature in this hash, using the constant in the value to send a control signal.

Eg. #display_on and #display_off.

{
  display: LCD_DISPLAYON,
  cursor: LCD_CURSORON,
  blink: LCD_BLINKON,
}

Instance Attribute Summary

Attributes included from Behaviors::MultiPin

#pin, #pins, #proxies

Attributes included from Behaviors::Component

#board

Instance Method Summary collapse

Methods included from Behaviors::MultiPin

#before_initialize, #convert_pins, #proxy_pin, #proxy_states, #require_pin, #require_pins

Methods included from Behaviors::Component

#initialize, #micro_delay

Methods included from Behaviors::State

#initialize, #state

Instance Method Details

#after_initialize(options = {}) ⇒ Object



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'lib/denko/display/hd44780.rb', line 65

def after_initialize(options={})
  super(options)
  
  # Default to 16x2 display if no options given.
  @columns = options[:columns] || 16
  @rows    = options[:rows]    || 2
  
  # Create a fuction set byte to set up the LCD. These defaults equal 0x00.
  @function = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS

  # Set 8-bit mode in the mask if d0-d3 are present.
  if (d0 && d1 && d2 && d3)
    @bits          = 8
    @function |= LCD_8BITMODE
  else
    @bits = 4
  end

  # Set 2 line (row) mode if needed.
  @function |= LCD_2LINE if (@rows > 1)

  # Some 1 line displays can use a 5x10 font.
  @function |= LCD_5x10DOTS if options[:tall_font] && (@rows == 1)
  
  # Offset memory address when moving cursor.
  # Row 2 always starts at memory address 0x40.
  # For 4 line LCDs:
  #   Row 3 is immediately after row 1, +16 or 20 bytes, depending on columns.
  #   Row 4 is immediately after row 2, +16 or 20 bytes, depending on columns.
  @row_offsets = [0x00, 0x40, 0x00+@columns, 0x40+@columns]
  
  # Wait 50ms for power to be > 2.7V, then pull everything low.
  micro_delay(50000)
  enable.low; rs.low; rw.low if rw

  # Start in 4-bit mode.
  if @bits == 4
    # Keep setting 8-bit mode until ready.
    command(0x03); micro_delay(4500)
    command(0x03); micro_delay(4500)
    command(0x03); micro_delay(150)
    
    # Set 4-bit mode.
    command(0x02)
    
  # Or start in 8 bit mode.
  else
    command(LCD_FUNCTIONSET | @function)
    micro_delay(4500)
    command(LCD_FUNCTIONSET | @function)
    micro_delay(150)
    command(LCD_FUNCTIONSET | @function)
  end
  
  # Set functions (lines, font size, etc.).
  command(LCD_FUNCTIONSET | @function)

  # Start with cursor off and no cursor blink.
  @control = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF
  display_on
  clear
  
  # Set entry mode defaults.
  @mode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT
  command(LCD_ENTRYMODESET | @mode)
  
  # Need this small delay to avoid garbage data on startup.
  sleep 0.05
end

#autoscroll_offObject



199
200
201
202
# File 'lib/denko/display/hd44780.rb', line 199

def autoscroll_off
  @mode &= ~LCD_ENTRYSHIFTINCREMENT;
  command(LCD_ENTRYMODESET | @mode);
end

#autoscroll_onObject



194
195
196
197
# File 'lib/denko/display/hd44780.rb', line 194

def autoscroll_on
  @mode |= LCD_ENTRYSHIFTINCREMENT;
  command(LCD_ENTRYMODESET | @mode);
end

#clearObject



135
136
137
138
# File 'lib/denko/display/hd44780.rb', line 135

def clear
  command(LCD_CLEARDISPLAY)
  micro_delay(2000)
end

#command(byte) ⇒ Object



211
212
213
# File 'lib/denko/display/hd44780.rb', line 211

def command(byte)
  send(byte, board.low)
end

#create_char(location, bitmap) ⇒ Object

Define custom characters as bitmaps.



205
206
207
208
209
# File 'lib/denko/display/hd44780.rb', line 205

def create_char(location, bitmap)
  location &= 0x7
  command(LCD_SETCGRAMADDR | (location << 3))
  bitmap.each { |byte| write byte }
end

#homeObject



140
141
142
143
# File 'lib/denko/display/hd44780.rb', line 140

def home
  command(LCD_RETURNHOME)
  micro_delay(2000)
end

#initialize_pins(options = {}) ⇒ Object



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/denko/display/hd44780.rb', line 49

def initialize_pins(options={})
  # All the required pins.
  [:rs, :enable, :d4, :d5, :d6, :d7].each do |symbol|
    proxy_pin(symbol, DigitalIO::Output)
  end
  
  # If any of d0-d3 was given, make them all non-optional.
  lower_bits_optional = (self.pins.keys & [:d0, :d1, :d2, :d3]).empty?
  [:d0, :d1, :d2, :d3].each do |symbol|
    proxy_pin(symbol, DigitalIO::Output, optional: lower_bits_optional)
  end
  
  # RW pin is mostly hard-wired to ground, but can given.
  proxy_pin(:rw, DigitalIO::Output, optional: true)
end

#left_to_rightObject



176
177
178
179
# File 'lib/denko/display/hd44780.rb', line 176

def left_to_right
  @mode |= LCD_ENTRYLEFT
  command(LCD_ENTRYMODESET | @mode)
end


152
153
154
# File 'lib/denko/display/hd44780.rb', line 152

def print(text)
  text.each_byte { |b| write b }
end

#pulse_enableObject



256
257
258
259
260
261
262
263
# File 'lib/denko/display/hd44780.rb', line 256

def pulse_enable
  enable.low
  micro_delay 1
  enable.high
  micro_delay 1
  enable.low
  micro_delay 100
end

#right_to_leftObject



181
182
183
184
# File 'lib/denko/display/hd44780.rb', line 181

def right_to_left
  @mode &= ~LCD_ENTRYLEFT
  command(LCD_ENTRYMODESET | @mode)
end

#scroll_leftObject



186
187
188
# File 'lib/denko/display/hd44780.rb', line 186

def scroll_left
  command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT)
end

#scroll_rightObject



190
191
192
# File 'lib/denko/display/hd44780.rb', line 190

def scroll_right
  command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT)
end

#send(byte, rs_level) ⇒ Object



219
220
221
222
223
224
225
226
227
228
229
# File 'lib/denko/display/hd44780.rb', line 219

def send(byte, rs_level)
  # RS pin goes low to send commands, high to send data.
  rs.write(rs_level) unless rs.state == rs_level
  rw.low if rw
  
  # Get the byte as a string of 0s and 1s, LSBFIRST.
  bits_from_byte = byte.to_s(2).rjust(8, "0").reverse
  
  # Write bits depending on connection.
  @bits == 8 ? write8(bits_from_byte) : write4(bits_from_byte)
end

#set_cursor(col, row) ⇒ Object Also known as: move_to



145
146
147
148
149
# File 'lib/denko/display/hd44780.rb', line 145

def set_cursor(col, row)
  # Limit to the highest row, 0 indexed.
  row = (@rows - 1) if row > (@rows - 1)
  command(LCD_SETDDRAMADDR | (col + @row_offsets[row]))
end

#write(byte) ⇒ Object



215
216
217
# File 'lib/denko/display/hd44780.rb', line 215

def write(byte)
  send(byte, board.high)
end

#write4(bits) ⇒ Object



231
232
233
234
235
236
237
238
239
240
241
242
# File 'lib/denko/display/hd44780.rb', line 231

def write4(bits)
  d4.write bits[4].to_i
  d5.write bits[5].to_i
  d6.write bits[6].to_i
  d7.write bits[7].to_i
  pulse_enable
  d4.write bits[0].to_i
  d5.write bits[1].to_i
  d6.write bits[2].to_i
  d7.write bits[3].to_i
  pulse_enable
end

#write8(bits) ⇒ Object



244
245
246
247
248
249
250
251
252
253
254
# File 'lib/denko/display/hd44780.rb', line 244

def write8(bits)
  d0.write bits[0].to_i
  d1.write bits[1].to_i
  d2.write bits[2].to_i
  d3.write bits[3].to_i
  d4.write bits[4].to_i
  d5.write bits[5].to_i
  d6.write bits[6].to_i
  d7.write bits[7].to_i
  pulse_enable
end