Skip to content

Commit acb48e7

Browse files
author
letherman255
committed
added lcd
1 parent 2196bca commit acb48e7

29 files changed

+684
-1870
lines changed

Diagrames/System overview.jpg

-110 KB
Loading
Binary file not shown.
759 Bytes
Binary file not shown.
Binary file not shown.
Binary file not shown.
+330
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,330 @@
1+
// A (fairly) literal port of Adafruit's Adafruit_CharLCDPlate.py module for Java and Pi4J (by Robert Savage: pi4j.com)
2+
// Ported by Douglas Otwell
3+
//
4+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
5+
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
6+
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
7+
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
8+
9+
// Python library for Adafruit RGB-backlit LCD plate for Raspberry Pi.
10+
// Written by Adafruit Industries. MIT license.
11+
12+
// This is essentially a complete rewrite, but the calling syntax
13+
// and constants are based on code from lrvick and LiquidCrystal.
14+
// lrvic - https://github.com/lrvick/raspi-hd44780/blob/master/hd44780.py
15+
// LiquidCrystal - https://github.com/arduino/Arduino/blob/master/libraries/LiquidCrystal/LiquidCrystal.cpp
16+
17+
package com.lcdfx.io;
18+
19+
import java.io.IOException;
20+
21+
import com.pi4j.io.i2c.I2CBus;
22+
import com.pi4j.io.i2c.I2CDevice;
23+
import com.pi4j.io.i2c.I2CFactory;
24+
25+
26+
public class AdafruitLcdPlate implements Lcd {
27+
static final int MCP23017_IOCON_BANK0 = 0x0A; // IOCON when Bank 0 active
28+
static final int MCP23017_IOCON_BANK1 = 0x15; // IOCON when Bank 1 active
29+
30+
// These are register addresses when in Bank 1 only:
31+
static final int MCP23017_GPIOA = 0x09;
32+
static final int MCP23017_GPIOB = 0x19;
33+
static final int MCP23017_IODIRB = 0x10;
34+
35+
static final int[] SHIFT_REVERSE = {
36+
0x00, 0x10, 0x08, 0x18,
37+
0x04, 0x14, 0x0C, 0x1C,
38+
0x02, 0x12, 0x0A, 0x1A,
39+
0x06, 0x16, 0x0E, 0x1E
40+
};
41+
42+
// LCD Commands
43+
public static final int LCD_CLEARDISPLAY = 0x01;
44+
public static final int LCD_RETURNHOME = 0x02;
45+
public static final int LCD_ENTRYMODESET = 0x04;
46+
public static final int LCD_DISPLAYCONTROL = 0x08;
47+
public static final int LCD_CURSORSHIFT = 0x10;
48+
public static final int LCD_FUNCTIONSET = 0x20;
49+
public static final int LCD_SETCGRAMADDR = 0x40;
50+
public static final int LCD_SETDDRAMADDR = 0x80;
51+
52+
// flags for display on/off control
53+
public static final int LCD_DISPLAYON = 0x04;
54+
public static final int LCD_DISPLAYOFF = 0x00;
55+
public static final int LCD_CURSORON = 0x02;
56+
public static final int LCD_CURSOROFF = 0x00;
57+
public static final int LCD_BLINKON = 0x01;
58+
public static final int LCD_BLINKOFF = 0x00;
59+
60+
// flags for display entry mode
61+
static final int LCD_ENTRYRIGHT = 0x00;
62+
static final int LCD_ENTRYLEFT = 0x02;
63+
static final int LCD_ENTRYSHIFTINCREMENT = 0x01;
64+
static final int LCD_ENTRYSHIFTDECREMENT = 0x00;
65+
66+
// flags for display/cursor shift
67+
static final int LCD_DISPLAYMOVE = 0x08;
68+
static final int LCD_CURSORMOVE = 0x00;
69+
static final int LCD_MOVERIGHT= 0x04;
70+
static final int LCD_MOVELEFT = 0x00;
71+
72+
// I2C is relatively slow. MCP output port states are cached
73+
// so we don't need to constantly poll-and-change bit states.
74+
private int portA = 0x00;
75+
private int portB = 0x00;
76+
private int ioDirB = 0x10;
77+
78+
private int displayShift = LCD_CURSORMOVE | LCD_MOVERIGHT;
79+
private int displayMode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT;
80+
private int displayControl = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF;
81+
82+
protected int[] rowOffsets =new int[] {0x00, 0x40, 0x14, 0x54};
83+
84+
85+
protected int rows;
86+
protected int columns;
87+
private I2CDevice device;
88+
89+
public AdafruitLcdPlate(I2CDevice device) throws IOException, InterruptedException
90+
{
91+
this.columns = 16;
92+
this.rows = 2;
93+
94+
95+
96+
// Set MCP23017 IOCON register to Bank 0 with sequential operation.
97+
// If chip is already set for Bank 0, this will just write to OLATB,
98+
// which won't seriously bother anything on the plate right now
99+
// (blue backlight LED will come on, but that's done in the next
100+
// step anyway).
101+
device.write(MCP23017_IOCON_BANK1, (byte) 0);
102+
103+
// Brute force reload ALL registers to known state. This also
104+
// sets up all the input pins, pull-ups, etc. for the Pi Plate.
105+
byte [] piPlateSetupRegisters = {
106+
0x3F, // IODIRA R+G LEDs=outputs, buttons=inputs
107+
(byte) ioDirB , // IODIRB LCD D7=input, Blue LED=output
108+
0x3F, // IPOLA Invert polarity on button inputs
109+
0x00, // IPOLB
110+
0x00, // GPINTENA Disable interrupt-on-change
111+
0x00, // GPINTENB
112+
0x00, // DEFVALA
113+
0x00, // DEFVALB
114+
0x00, // INTCONA
115+
0x00, // INTCONB
116+
0x00, // IOCON
117+
0x00, // IOCON
118+
0x3F, // GPPUA Enable pull-ups on buttons
119+
0x00, // GPPUB
120+
0x00, // INTFA
121+
0x00, // INTFB
122+
0x00, // INTCAPA
123+
0x00, // INTCAPB
124+
(byte) portA, // GPIOA
125+
(byte) portB, // GPIOB
126+
(byte) portA, // OLATA 0 on all outputs; side effect of
127+
(byte) portB // OLATB turning on R+G+B backlight LEDs.
128+
};
129+
device.write(0, piPlateSetupRegisters, 0, piPlateSetupRegisters.length);
130+
131+
// Switch to Bank 1 and disable sequential operation.
132+
// From this point forward, the register addresses do NOT match
133+
// the list immediately above. Instead, use the constants defined
134+
// at the start of the class. Also, the address register will no
135+
// longer increment automatically after this -- multi-byte
136+
// operations must be broken down into single-byte calls.
137+
device.write(MCP23017_IOCON_BANK0, (byte) 0xA0);
138+
139+
writeCmd(0x33); // Init
140+
writeCmd(0x32); // Init
141+
writeCmd(0x28); // 2 line 5x8 matrix
142+
writeCmd(LCD_CLEARDISPLAY);
143+
writeCmd(LCD_CURSORSHIFT | displayShift);
144+
writeCmd(LCD_ENTRYMODESET | displayMode);
145+
writeCmd(LCD_DISPLAYCONTROL | displayControl);
146+
writeCmd(LCD_RETURNHOME);
147+
}
148+
149+
public int getRowCount() {
150+
return rows;
151+
}
152+
153+
public int getColumnCount() {
154+
return columns;
155+
}
156+
157+
public void clear()
158+
{
159+
writeCmd(LCD_CLEARDISPLAY);
160+
}
161+
162+
public void setCursorHome()
163+
{
164+
writeCmd(LCD_RETURNHOME);
165+
}
166+
167+
public void setCursorPosition(int row, int column)
168+
{
169+
writeCmd(LCD_SETDDRAMADDR | (column + rowOffsets[row]));
170+
}
171+
172+
public void write(byte data)
173+
{
174+
try {
175+
pollWait();
176+
int bitmask = portB & 0x01; // Mask out PORTB LCD control bits
177+
bitmask |= 0x80; // Set data bit
178+
179+
byte[] bytes = ShiftAndMap4(bitmask, data);
180+
device.write(MCP23017_GPIOB, bytes, 0, 4);
181+
portB = bytes[3];
182+
} catch (IOException e) {
183+
e.printStackTrace();
184+
}
185+
}
186+
187+
private void writeCmd(int cmd)
188+
{
189+
try {
190+
pollWait();
191+
int bitmask = portB & 0x01; // Mask out PORTB LCD control bits
192+
193+
byte[] data = ShiftAndMap4(bitmask, cmd);
194+
device.write(MCP23017_GPIOB, data, 0, 4);
195+
portB = data[3];
196+
197+
// If a poll-worthy instruction was issued, reconfigure D7
198+
// pin as input to indicate need for polling on next call.
199+
if (cmd == LCD_CLEARDISPLAY || cmd == LCD_RETURNHOME) {
200+
ioDirB |= 0x10;
201+
device.write(MCP23017_IODIRB, (byte) ioDirB);
202+
}
203+
} catch (IOException e) {
204+
// TODO Auto-generated catch block
205+
e.printStackTrace();
206+
}
207+
}
208+
209+
public void write(int row, String string)
210+
{
211+
setCursorPosition(row, 0);
212+
write(string);
213+
}
214+
215+
public void write(String s)
216+
{
217+
int sLen = s.length();
218+
int bytesLen = 4 * sLen;
219+
if (sLen < 1) return;
220+
221+
try {
222+
223+
pollWait();
224+
int bitmask = portB & 0x01; // Mask out PORTB LCD control bits
225+
{bitmask |= 0x80;} // Set data bit
226+
227+
byte[] bytes = new byte[4 * sLen];
228+
for(int i=0; i<sLen; i++) {
229+
byte[] data = ShiftAndMap4(bitmask, s.charAt(i));
230+
for (int j=0; j<4; j++) {
231+
bytes[(i * 4) + j] = data[j];
232+
}
233+
}
234+
device.write(MCP23017_GPIOB, bytes, 0, bytesLen);
235+
portB = bytes[bytesLen - 1];
236+
} catch (IOException e) {
237+
// TODO Auto-generated catch block
238+
e.printStackTrace();
239+
}
240+
}
241+
242+
protected void pollWait() throws IOException
243+
{
244+
// The speed of LCD accesses is inherently limited by I2C through the
245+
// port expander. A 'well behaved program' is expected to poll the
246+
// LCD to know that a prior instruction completed. But the timing of
247+
// most instructions is a known uniform 37 mS. The enable strobe
248+
// can't even be twiddled that fast through I2C, so it's a safe bet
249+
// with these instructions to not waste time polling (which requires
250+
// several I2C transfers for reconfiguring the port direction).
251+
// The D7 pin is set as input when a potentially time-consuming
252+
// instruction has been issued (e.g. screen clear), as well as on
253+
// startup, and polling will then occur before more commands or data
254+
// are issued.
255+
256+
// If pin D7 is in input state, poll LCD busy flag until clear.
257+
if ((ioDirB & 0x10) != 0) {
258+
int lo = (portB & 0x01) | 0x40;
259+
int hi = lo | 0x20; // E=1 (strobe)
260+
device.write(MCP23017_GPIOB, (byte) lo);
261+
while (true) {
262+
device.write((byte) hi); // Strobe high (enable)
263+
int bits = device.read(); // First nybble contains busy state
264+
device.write(MCP23017_GPIOB, new byte[] {(byte) lo, (byte) hi, (byte) lo}, 0, 3); // Strobe low, high, low. Second nybble (A3) is ignored.
265+
if ((bits & 0x02) == 0) break; // D7=0, not busy
266+
}
267+
portB = lo;
268+
ioDirB &= 0xEF; // Polling complete, change D7 pin to output
269+
device.write(MCP23017_IODIRB, (byte) ioDirB);
270+
}
271+
}
272+
273+
protected byte[] ShiftAndMap4(int bitmask, int value)
274+
{
275+
// The LCD data pins (D4-D7) connect to MCP pins 12-9 (PORTB4-1), in
276+
// that order. Because this sequence is 'reversed,' a direct shift
277+
// won't work. This table remaps 4-bit data values to MCP PORTB
278+
// outputs, incorporating both the reverse and shift.
279+
int hi = bitmask | SHIFT_REVERSE[value >> 4];
280+
int lo = bitmask | SHIFT_REVERSE[value & 0x0F];
281+
282+
byte[] data = new byte[] { (byte) (hi | 0x20), (byte) hi, (byte) (lo | 0x20), (byte) lo};
283+
284+
return data;
285+
}
286+
287+
public void setCursor(boolean on) throws IOException
288+
{
289+
if (on) {
290+
displayControl |= LCD_CURSORON;
291+
} else {
292+
displayControl &= ~LCD_CURSORON;
293+
}
294+
writeCmd(LCD_DISPLAYCONTROL | displayControl);
295+
}
296+
297+
public void setDisplay(boolean on)
298+
{
299+
if (on) {
300+
displayControl |= LCD_DISPLAYON ;
301+
} else {
302+
displayControl &= ~LCD_DISPLAYON;
303+
}
304+
writeCmd(LCD_DISPLAYCONTROL | displayControl);
305+
}
306+
307+
public void setBacklight(int color)
308+
{
309+
int c = ~color;
310+
portA = (byte) ((portA & 0x3F) | ((c & 0x03) << 6));
311+
portB = (byte) ((portB & 0xFE) | ((c & 0x04) >> 2));
312+
// Has to be done as two writes because sequential operation is off.
313+
try {
314+
device.write(MCP23017_GPIOA, (byte) portA);
315+
device.write(MCP23017_GPIOB, (byte) portB);
316+
} catch (IOException ex) {
317+
// TODO Auto-generated catch block
318+
ex.printStackTrace();
319+
}
320+
}
321+
322+
public void shutdown()
323+
{
324+
clear();
325+
setDisplay(false);
326+
setBacklight(Lcd.BACKLIGHT_OFF);
327+
328+
}
329+
330+
}

pro/src/com/lcdfx/io/Lcd.java

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package com.lcdfx.io;
2+
3+
public interface Lcd {
4+
5+
public static final int BACKLIGHT_OFF = 0x00;
6+
public static final int BACKLIGHT_RED = 0x01;
7+
public static final int BACKLIGHT_GREEN = 0x02;
8+
public static final int BACKLIGHT_BLUE = 0x04;
9+
public static final int BACKLIGHT_YELLOW = BACKLIGHT_RED + BACKLIGHT_GREEN;
10+
public static final int BACKLIGHT_TEAL = BACKLIGHT_GREEN + BACKLIGHT_BLUE;
11+
public static final int BACKLIGHT_VIOLET = BACKLIGHT_RED + BACKLIGHT_BLUE;
12+
public static final int BACKLIGHT_WHITE = BACKLIGHT_RED + BACKLIGHT_GREEN + BACKLIGHT_BLUE;
13+
public static final int BACKLIGHT_ON = BACKLIGHT_RED + BACKLIGHT_GREEN + BACKLIGHT_BLUE;
14+
15+
int getRowCount();
16+
int getColumnCount();
17+
18+
void clear();
19+
20+
void setCursorHome();
21+
void setCursorPosition(int row, int column);
22+
23+
void write(String data);
24+
void write(int row, String data);
25+
void write(byte data);
26+
27+
void setDisplay(boolean on);
28+
void setBacklight(int color);
29+
30+
void shutdown();
31+
32+
}

0 commit comments

Comments
 (0)