All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.diozero.devices.HD44780Lcd Maven / Gradle / Ivy

There is a newer version: 1.4.0
Show newest version
package com.diozero.devices;

/*
 * #%L
 * Organisation: diozero
 * Project:      Device I/O Zero - Core
 * Filename:     HD44780Lcd.java  
 * 
 * This file is part of the diozero project. More information about this project
 * can be found at http://www.diozero.com/
 * %%
 * Copyright (C) 2016 - 2020 diozero
 * %%
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 * #L%
 */

import java.io.Closeable;
import java.util.HashMap;
import java.util.Map;

import com.diozero.api.I2CConstants;
import com.diozero.internal.provider.I2CDeviceFactoryInterface;
import com.diozero.internal.provider.mcp23xxx.MCP23xxx;
import com.diozero.util.DeviceFactoryHelper;
import com.diozero.util.RuntimeIOException;
import com.diozero.util.SleepUtil;

/**
 * 

* LCD with HD44780 controller.
* Code based on * this Raspberry-Pi Spy article, Python code. *

*

* Another source of information: https://gist.github.com/DenisFromHR/cc863375a6e19dce359d. *

*

* HD44780 Datasheet. *

*/ public class HD44780Lcd implements Closeable { private static final boolean DEFAULT_BACKLIGHT_STATE = true; /* * Instructions: * Instruction | RS | RW | DB7 | DB6 | DB5 | DB4 | DB3 | DB2 | DB1 | DB0 | Description | Exec Time * ------------+----+----+-----+-----+-----+-----+-----+-----+-----+-----+------------------------------+---------- * Clear | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | Clears entire display and | * display | | | | | | | | | | | sets DDRAM address 0 in | * | | | | | | | | | | | address counter. | * ------------+----+----+-----+-----+-----+-----+-----+-----+-----+-----+------------------------------+---------- * Return | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | - | Sets DDRAM address 0 in | 1.52ms * home | | | | | | | | | | | address counter. Also | * | | | | | | | | | | | returns display from being | * | | | | | | | | | | | shifted to original position.| * | | | | | | | | | | | DDRAM contents remain | * | | | | | | | | | | | unchanged. | * ------------+----+----+-----+-----+-----+-----+-----+-----+-----+-----+------------------------------+---------- * Entry mode | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | I/D | S | Sets cursor move direction | 37us * set | | | | | | | | | | | and specifies display shift. | * | | | | | | | | | | | These operations are | * | | | | | | | | | | | performed during data write | * | | | | | | | | | | | and read. | * ------------+----+----+-----+-----+-----+-----+-----+-----+-----+-----+------------------------------+---------- * Display on/ | 0 | 0 | 0 | 0 | 0 | 0 | 1 | D | C | B | Sets entire display (D) on/ | 37us * off control | | | | | | | | | | | off, cursor on/off (C), and | * | | | | | | | | | | | blinking of cursor position | * | | | | | | | | | | | character (B). | * ------------+----+----+-----+-----+-----+-----+-----+-----+-----+-----+------------------------------+---------- * Cursor or | 0 | 0 | 0 | 0 | 0 | 1 | S/C | R/L | - | - | Moves cursor and shifts | 37us * display | | | | | | | | | | | display without changing | * shift | | | | | | | | | | | DDRAM contents. | * ------------+----+----+-----+-----+-----+-----+-----+-----+-----+-----+------------------------------+---------- * Function | 0 | 0 | 0 | 0 | 1 | DL | N | F | - | - | Sets interface data length | 37us * set | | | | | | | | | | | (DL), number of display lines| * | | | | | | | | | | | (N), and character font (F). | * ------------+----+----+-----+-----+-----+-----+-----+-----+-----+-----+------------------------------+---------- * Set CGRAM | 0 | 0 | 0 | 1 | ACG | ACG | ACG | ACG | ACG | ACG | Sets CGRAM address. | 37us * address | | | | | | | | | | | CGRAM data is sent and | * | | | | | | | | | | | received after this setting. | * ------------+----+----+-----+-----+-----+-----+-----+-----+-----+-----+------------------------------+---------- * Set DDRAM | 0 | 0 | 1 | ADD | ADD | ADD | ADD | ADD | ADD | ADD | Sets DDRAM address. | 37us * address | | | | | | | | | | | DDRAM data is sent and | * | | | | | | | | | | | received after this setting. | * ------------+----+----+-----+-----+-----+-----+-----+-----+-----+-----+------------------------------+---------- * Write data | 1 | 0 | d | d | d | d | d | d | d | d | Writes data into DDRAM or | 37us * to CG or | | | | | | | | | | | CGRAM. | * DDRAM | | | | | | | | | | | | * ------------+----+----+-----+-----+-----+-----+-----+-----+-----+-----+------------------------------+---------- * Read data | 1 | 1 | d | d | d | d | d | d | d | d | Reads data from DDRAM or | 37us * from CG or | | | | | | | | | | | CGRAM. | * DDRAM | | | | | | | | | | | | * ------------+----+----+-----+-----+-----+-----+-----+-----+-----+-----+------------------------------+---------- * DDRAM = Display Data RAM. * CGRAM = Character Generator RAM. */ /** Clears entire display and sets DDRAM address 0 in address counter. */ private static final byte INST_CLEAR_DISPLAY = 0x01; /** Sets DDRAM address 0 in address counter. * Also returns display from being shifted to original position. * DDRAM contents remain unchanged. */ private static final byte INST_RETURN_HOME = 0x02; /** Sets cursor move direction and specifies display shift. * These operations are performed during data write and read. */ private static final byte INST_ENTRY_MODE_SET = 0x04; /** Sets entire display (D) on/off, cursor on/off (C), and blinking of cursor position character (B). */ private static final byte INST_DISPLAY_CONTROL = 0x08; /** Moves cursor and shifts display without changing DDRAM contents. */ private static final byte INST_CURSOR_DISPLAY_SHIFT = 0x10; /** Perform the function at the head of the program before executing any instructions (except for the * read busy flag and address instruction). From this point, the function set instruction cannot be * executed unless the interface data length is changed. */ private static final byte INST_FUNCTION_SET = 0x20; /** Sets CGRAM address. CGRAM data is sent and received after this setting. */ private static final byte INST_SET_CGRAM_ADDR = 0x40; /** Sets DDRAM address. DDRAM data is sent and received after this setting. */ private static final byte INST_SET_DDRAM_ADDR = (byte) 0x80; // Flags for INST_ENTRY_MODE_SET /** Cursor increment/decrement control, 1=increment, 0=decrement. * The cursor or blinking moves to the right when incremented by 1 and to the left when decremented by 1. */ private static final byte EMS_CURSOR_INCREMENT = 0x02; private static final byte EMS_CURSOR_DECREMENT = 0x00; /** Display shift control, 1=on, 0=off. * Shifts the entire display either to the right (I/D = 0) or to the left (I/D = 1) when S is 1. * If S is 1, it will seem as if the cursor does not move but the display does. * The display does not shift if S is 0. */ private static final byte EMS_DISPLAY_SHIFT_ON = 0x01; private static final byte EMS_DISPLAY_SHIFT_OFF = 0x00; // Flags for INST_DISPLAY_CONTROL /** Display on/off, 1=on, 0=off. */ private static final byte DC_DISPLAY_ON = 0x04; private static final byte DC_DISPLAY_OFF = 0x00; /** Cursor on/off, 1=on, 0=off. */ private static final byte DC_CURSOR_ON = 0x02; private static final byte DC_CURSOR_OFF = 0x00; /** Cursor blink control, 1=blink, 0=no blink. */ private static final byte DC_BLINK_ON = 0x01; private static final byte DC_BLINK_OFF = 0x00; // Flags for INST_CURSOR_DISPLAY_SHIFT /** Shift the displayed text, 1=right, 0=left. */ private static final byte CDS_DISPLAY_SHIFT = 0x08; private static final byte CDS_CURSOR_MOVE = 0x00; /** Shift the cursor, 1=right, 0=left. */ private static final byte CDS_SHIFT_RIGHT = 0x04; private static final byte CDS_SHIFT_LEFT = 0x00; // Flags for INST_FUNCTION_SET /** Data is sent or received in 8-bit lengths (DB7 to DB0) when DL is 1, * and in 4-bit lengths (DB7 to DB4) when DL is 0. */ private static final byte FS_DATA_LENGTH_8BIT = 0x10; private static final byte FS_DATA_LENGTH_4BIT = 0x00; /** Sets the number of display lines. 1=2 lines, 0=1 line. */ private static final byte FS_DISPLAY_2LINES = 0x08; private static final byte FS_DISPLAY_1LINE = 0x00; /** Sets the character font. 1=5x10 dots (32 character fonts), 0=5x8 dots (208 character fonts). * For some 1 line displays you can select a 10 pixel high font. */ private static final byte FS_CHAR_FONT_5X10DOTS = 0x04; private static final byte FS_CHAR_FONT_5X8DOTS = 0x00; // For 2-row LCDs private static final byte[] ROW_OFFSETS_2ROWS = { 0x00, 0x40 }; // For 20x4 LCDs private static final byte[] ROW_OFFSETS_20x4 = { 0x00, 0x40, 20, 0x40 + 20 }; // For 16x4 LCDs - special memory map layout private static final byte[] ROW_OFFSETS_16x4 = { 0, 0x40, 16, 0x40 + 16 }; private LcdConnection lcdConnection; private boolean dataInHighNibble; private int registerSelectDataMask; //private int dataReadMask; private int enableMask; private int backlightOnMask; private boolean backlightEnabled; private int columns; private int rows; private boolean characterFont5x8; private boolean displayOn; private boolean cursorEnabled; private boolean blinkEnabled; private boolean increment; private boolean shiftDisplay; private byte[] rowOffsets; public HD44780Lcd(LcdConnection lcdConnection, int columns, int rows) { if (rows == 2) { rowOffsets = ROW_OFFSETS_2ROWS; } else if (rows == 4) { if (columns == 16) { rowOffsets = ROW_OFFSETS_16x4; } else if (columns == 20) { rowOffsets = ROW_OFFSETS_20x4; } } if (rowOffsets == null) { throw new IllegalArgumentException(columns + "x" + rows + " LCDs not supported"); } if (rows < 1 || rows > rowOffsets.length) { throw new IllegalArgumentException( "Invalid number of rows (" + rows + "), must be 1.." + rowOffsets.length); } this.columns = columns; this.rows = rows; backlightEnabled = DEFAULT_BACKLIGHT_STATE; characterFont5x8 = true; this.lcdConnection = lcdConnection; dataInHighNibble = lcdConnection.isDataInHighNibble(); registerSelectDataMask = 1 << lcdConnection.getRegisterSelectBit(); //dataReadMask = 1 << lcdConnection.getDataReadWriteBit(); enableMask = 1 << lcdConnection.getEnableBit(); backlightOnMask = 1 << lcdConnection.getBacklightBit(); // Initialise the display. From p45/46 of the datasheet: // https://www.sparkfun.com/datasheets/LCD/HD44780.pdf // If the power supply conditions for correctly operating the internal reset // circuit are not met, initialisation by instructions becomes necessary. // Need to do this 3 times for the 4-bit interface (p46) // Function set (Interface is 8 bits long). write4Bits(true, (byte) (INST_FUNCTION_SET | FS_DATA_LENGTH_8BIT)); // Wait for more than 4.1 ms SleepUtil.sleepMillis(4); // Function set (Interface is 8 bits long). write4Bits(true, (byte) (INST_FUNCTION_SET | FS_DATA_LENGTH_8BIT)); // Wait for more than 100us //SleepUtil.sleepMicros(100); SleepUtil.busySleep(100_000); // Function set (Interface is 8 bits long). write4Bits(true, (byte) (INST_FUNCTION_SET | FS_DATA_LENGTH_8BIT)); // Now set it to 4-bit mode write4Bits(true, (byte) (INST_FUNCTION_SET | FS_DATA_LENGTH_4BIT)); // Function set: 4-bit data length, lines & character font as requested writeInstruction((byte) (INST_FUNCTION_SET | FS_DATA_LENGTH_4BIT | (rows == 1 ? FS_DISPLAY_1LINE : FS_DISPLAY_2LINES) | (characterFont5x8 ? FS_CHAR_FONT_5X8DOTS : FS_CHAR_FONT_5X10DOTS) )); // Display On, Cursor on, Blink on displayControl(true, true, true); // Cursor increment, display shift off entryModeControl(true, false); // Clear display clear(); } private void writeInstruction(byte data) { writeByte(true, data); } private void writeData(byte data) { writeByte(false, data); } private void writeByte(boolean instruction, byte data) { // High bits first write4Bits(instruction, (byte) (data & 0xF0)); // Low bits last write4Bits(instruction, (byte) (data << 4)); } private void write4Bits(boolean instruction, byte value) { if (! dataInHighNibble) { value = (byte) ((value >> 4) & 0x0F); } byte data = (byte) (value | (instruction ? 0 : registerSelectDataMask) | (backlightEnabled ? backlightOnMask : 0)); lcdConnection.write((byte) (data | enableMask)); // 50us delay enough? //SleepUtil.sleepMicros(50); SleepUtil.busySleep(50_000); lcdConnection.write((byte) (data & ~enableMask)); // 50us delay enough? //SleepUtil.sleepMicros(50); SleepUtil.busySleep(50_000); } public int getColumnCount() { return columns; } public int getRowCount() { return rows; } public boolean isBacklightEnabled() { return backlightEnabled; } public HD44780Lcd setBacklightEnabled(boolean backlightEnabled) { this.backlightEnabled = backlightEnabled; writeByte(true, (byte) 0); return this; } public HD44780Lcd setCursorPosition(int column, int row) { if (column < 0 || column >= columns) { throw new IllegalArgumentException("Invalid column (" + column + "), must be 0.." + (column - 1)); } if (row < 0 || row >= rows) { throw new IllegalArgumentException("Invalid row (" + row + "), must be 0.." + (rows - 1)); } writeInstruction((byte) (INST_SET_DDRAM_ADDR | (column + rowOffsets[row]))); return this; } public HD44780Lcd setCharacter(int column, int row, char character) { setCursorPosition(column, row); writeData((byte) character); return this; } /** * Send string to display * @param row Row number (starts at 0) * @param text Text to display * @return This object instance */ public HD44780Lcd setText(int row, String text) { if (row < 0 || row >= rows) { throw new IllegalArgumentException("Invalid row (" + row + "), must be 0.." + (rows - 1)); } // Trim the string to the length of the column if (text.length() >= columns) text = text.substring(0, columns); // Set the cursor position to the start of the specified row setCursorPosition(0, row); for (byte b : text.getBytes()) { writeData(b); } return this; } public HD44780Lcd addText(String text) { for (byte b : text.getBytes()) { writeData(b); } return this; } public HD44780Lcd addText(char character) { writeData((byte) character); return this; } public HD44780Lcd addText(int code) { writeData((byte) code); return this; } /** * Clear the display * @return This object instance */ public HD44780Lcd clear() { writeInstruction(INST_CLEAR_DISPLAY); // Seem to have to wait after clearing the display, encounter strange errors otherwise SleepUtil.sleepMillis(1); return this; } /** * Return the cursor to the home position * @return This object instance */ public HD44780Lcd returnHome() { writeInstruction(INST_RETURN_HOME); return this; } /** * Control text entry mode. * @param increment * The cursor or blinking moves to the right when incremented * by 1 and to the left when decremented by 1. * @param shiftDisplay * Shifts the entire display either to the right (I/D = 0) or * to the left (I/D = 1) when true. The display does not shift * if false. If true, it will seem as if the cursor does not * move but the display does. * @return This object instance */ public HD44780Lcd entryModeControl(boolean increment, boolean shiftDisplay) { this.increment = increment; this.shiftDisplay = shiftDisplay; writeInstruction((byte) (INST_ENTRY_MODE_SET | (increment ? EMS_CURSOR_INCREMENT : EMS_CURSOR_DECREMENT) | (shiftDisplay ? EMS_DISPLAY_SHIFT_ON : EMS_DISPLAY_SHIFT_OFF) )); return this; } public HD44780Lcd autoscrollOn() { entryModeControl(true, true); return this; } public HD44780Lcd autoscrollOff() { entryModeControl(true, false); return this; } public boolean isIncrementOn() { return increment; } public boolean isShiftDisplayOn() { return shiftDisplay; } public HD44780Lcd displayControl(boolean displayOn, boolean cursorEnabled, boolean blinkEnabled) { this.displayOn = displayOn; this.cursorEnabled = cursorEnabled; this.blinkEnabled = blinkEnabled; writeInstruction((byte) (INST_DISPLAY_CONTROL | (displayOn ? DC_DISPLAY_ON : DC_DISPLAY_OFF) | (cursorEnabled ? DC_CURSOR_ON : DC_CURSOR_OFF) | (blinkEnabled ? DC_BLINK_ON : DC_BLINK_OFF) )); return this; } public HD44780Lcd displayOn() { return displayControl(true, cursorEnabled, blinkEnabled); } public HD44780Lcd displayOff() { return displayControl(false, cursorEnabled, blinkEnabled); } public HD44780Lcd cursorOn() { return displayControl(displayOn, true, blinkEnabled); } public HD44780Lcd cursorOff() { return displayControl(displayOn, false, blinkEnabled); } public HD44780Lcd blinkOn() { return displayControl(displayOn, true, true); } public HD44780Lcd blinkOff() { return displayControl(displayOn, cursorEnabled, false); } public boolean isCursorEnabled() { return cursorEnabled; } public boolean isBlinkEnabled() { return blinkEnabled; } /** * Cursor or display shift shifts the cursor position or display to the right * or left without writing or reading display data. This function is used to * correct or search the display. In a 2-line display, the cursor moves to * the second line when it passes the 40th digit of the first line. Note that * the first and second line displays will shift at the same time. * When the displayed data is shifted repeatedly each line moves only horizontally. * The second line display does not shift into the first line position. * @param displayShift * Shift the display if true, the cursor if false. * @param shiftRight * Shift to the right if true, to the left if false. * @return This object instance */ public HD44780Lcd cursorOrDisplayShift(boolean displayShift, boolean shiftRight) { writeInstruction((byte) (INST_CURSOR_DISPLAY_SHIFT | (displayShift ? CDS_DISPLAY_SHIFT : CDS_CURSOR_MOVE) | (shiftRight ? CDS_SHIFT_RIGHT : CDS_SHIFT_LEFT) )); return this; } public HD44780Lcd shiftDisplayRight() { cursorOrDisplayShift(true, true); return this; } public HD44780Lcd shiftDisplayLeft() { cursorOrDisplayShift(true, false); return this; } public HD44780Lcd moveCursorRight() { cursorOrDisplayShift(false, true); return this; } public HD44780Lcd moveCursorLeft() { cursorOrDisplayShift(false, false); return this; } public HD44780Lcd createChar(int location, byte[] charMap) { /* In the character generator RAM, the user can rewrite character patterns by program. * For 5?8 dots, eight character patterns can be written, and for 5?10 dots, * four character patterns can be written. */ if (characterFont5x8) { if (location < 0 || location >= 8) { throw new IllegalArgumentException("Invalid location (" + location + ") , must be 0..7"); } if (charMap.length != 8) { throw new IllegalArgumentException("Invalid charMap length (" + charMap.length + ") , must be 8"); } } else { if (location < 0 || location >= 4) { throw new IllegalArgumentException("Invalid location (" + location + ") , must be 0..3"); } if (charMap.length != 10) { throw new IllegalArgumentException("Invalid charMap length (" + charMap.length + ") , must be 10"); } } writeInstruction((byte) (INST_SET_CGRAM_ADDR | (location<<3))); //SleepUtil.sleepMicros(100); SleepUtil.busySleep(100_000); for (int i=0; i CHARACTERS = new HashMap<>(); static { CHARACTERS.put("0", new byte[] { 0xe, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0xe }); CHARACTERS.put("1", new byte[] { 0x2, 0x6, 0xe, 0x6, 0x6, 0x6, 0x6 }); CHARACTERS.put("2", new byte[] { 0xe, 0x1b, 0x3, 0x6, 0xc, 0x18, 0x1f }); CHARACTERS.put("3", new byte[] { 0xe, 0x1b, 0x3, 0xe, 0x3, 0x1b, 0xe }); CHARACTERS.put("4", new byte[] { 0x3, 0x7, 0xf, 0x1b, 0x1f, 0x3, 0x3 }); CHARACTERS.put("5", new byte[] { 0x1f, 0x18, 0x1e, 0x3, 0x3, 0x1b, 0xe }); CHARACTERS.put("6", new byte[] { 0xe, 0x1b, 0x18, 0x1e, 0x1b, 0x1b, 0xe }); CHARACTERS.put("7", new byte[] { 0x1f, 0x3, 0x6, 0xc, 0xc, 0xc, 0xc }); CHARACTERS.put("8", new byte[] { 0xe, 0x1b, 0x1b, 0xe, 0x1b, 0x1b, 0xe }); CHARACTERS.put("9", new byte[] { 0xe, 0x1b, 0x1b, 0xf, 0x3, 0x1b, 0xe }); CHARACTERS.put("10", new byte[] { 0x17, 0x15, 0x15, 0x15, 0x17, 0x0, 0x1f }); CHARACTERS.put("11", new byte[] { 0xa, 0xa, 0xa, 0xa, 0xa, 0x0, 0x1f }); CHARACTERS.put("12", new byte[] { 0x17, 0x11, 0x17, 0x14, 0x17, 0x0, 0x1f }); CHARACTERS.put("13", new byte[] { 0x17, 0x11, 0x13, 0x11, 0x17, 0x0, 0x1f }); CHARACTERS.put("14", new byte[] { 0x15, 0x15, 0x17, 0x11, 0x11, 0x0, 0x1f }); CHARACTERS.put("15", new byte[] { 0x17, 0x14, 0x17, 0x11, 0x17, 0x0, 0x1f }); CHARACTERS.put("16", new byte[] { 0x17, 0x14, 0x17, 0x15, 0x17, 0x0, 0x1f }); CHARACTERS.put("17", new byte[] { 0x17, 0x11, 0x12, 0x12, 0x12, 0x0, 0x1f }); CHARACTERS.put("18", new byte[] { 0x17, 0x15, 0x17, 0x15, 0x17, 0x0, 0x1f }); CHARACTERS.put("19", new byte[] { 0x17, 0x15, 0x17, 0x11, 0x17, 0x0, 0x1f }); CHARACTERS.put("circle", new byte[] { 0x0, 0xe, 0x11, 0x11, 0x11, 0xe, 0x0 }); CHARACTERS.put("cdot", new byte[] { 0x0, 0xe, 0x11, 0x15, 0x11, 0xe, 0x0 }); CHARACTERS.put("donut", new byte[] { 0x0, 0xe, 0x1f, 0x1b, 0x1f, 0xe, 0x0 }); CHARACTERS.put("ball", new byte[] { 0x0, 0xe, 0x1f, 0x1f, 0x1f, 0xe, 0x0 }); CHARACTERS.put("square", new byte[] { 0x0, 0x1f, 0x11, 0x11, 0x11, 0x1f, 0x0 }); CHARACTERS.put("sdot", new byte[] { 0x0, 0x1f, 0x11, 0x15, 0x11, 0x1f, 0x0 }); CHARACTERS.put("fbox", new byte[] { 0x0, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x0 }); CHARACTERS.put("sbox", new byte[] { 0x0, 0x0, 0xe, 0xa, 0xe, 0x0, 0x0 }); CHARACTERS.put("sfbox", new byte[] { 0x0, 0x0, 0xe, 0xe, 0xe, 0x0, 0x0 }); CHARACTERS.put("bigpointerright", new byte[] { 0x8, 0xc, 0xa, 0x9, 0xa, 0xc, 0x8 }); CHARACTERS.put("bigpointerleft", new byte[] { 0x2, 0x6, 0xa, 0x12, 0xa, 0x6, 0x2 }); CHARACTERS.put("arrowright", new byte[] { 0x8, 0xc, 0xa, 0x9, 0xa, 0xc, 0x8 }); CHARACTERS.put("arrowleft", new byte[] { 0x2, 0x6, 0xa, 0x12, 0xa, 0x6, 0x2 }); CHARACTERS.put("ascprogress1", new byte[] { 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 }); CHARACTERS.put("ascprogress2", new byte[] { 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18 }); CHARACTERS.put("ascprogress3", new byte[] { 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c }); CHARACTERS.put("ascprogress4", new byte[] { 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e }); CHARACTERS.put("fullprogress", new byte[] { 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f }); CHARACTERS.put("descprogress1", new byte[] { 1, 1, 1, 1, 1, 1, 1, 1 }); CHARACTERS.put("descprogress2", new byte[] { 3, 3, 3, 3, 3, 3, 3, 3 }); CHARACTERS.put("descprogress3", new byte[] { 7, 7, 7, 7, 7, 7, 7, 7 }); CHARACTERS.put("descprogress4", new byte[] { 15, 15, 15, 15, 15, 15, 15, 15 }); CHARACTERS.put("ascchart1", new byte[] { 31, 0, 0, 0, 0, 0, 0, 0 }); CHARACTERS.put("ascchart2", new byte[] { 31, 31, 0, 0, 0, 0, 0, 0 }); CHARACTERS.put("ascchart3", new byte[] { 31, 31, 31, 0, 0, 0, 0, 0 }); CHARACTERS.put("ascchart4", new byte[] { 31, 31, 31, 31, 0, 0, 0, 0 }); CHARACTERS.put("ascchart5", new byte[] { 31, 31, 31, 31, 31, 0, 0, 0 }); CHARACTERS.put("ascchart6", new byte[] { 31, 31, 31, 31, 31, 31, 0, 0 }); CHARACTERS.put("ascchart7", new byte[] { 31, 31, 31, 31, 31, 31, 31, 0 }); CHARACTERS.put("descchart1", new byte[] { 0, 0, 0, 0, 0, 0, 0, 31 }); CHARACTERS.put("descchart2", new byte[] { 0, 0, 0, 0, 0, 0, 31, 31 }); CHARACTERS.put("descchart3", new byte[] { 0, 0, 0, 0, 0, 31, 31, 31 }); CHARACTERS.put("descchart4", new byte[] { 0, 0, 0, 0, 31, 31, 31, 31 }); CHARACTERS.put("descchart5", new byte[] { 0, 0, 0, 31, 31, 31, 31, 31 }); CHARACTERS.put("descchart6", new byte[] { 0, 0, 31, 31, 31, 31, 31, 31 }); CHARACTERS.put("descchart7", new byte[] { 0, 31, 31, 31, 31, 31, 31, 31 }); CHARACTERS.put("borderleft1", new byte[] { 1, 1, 1, 1, 1, 1, 1, 1 }); CHARACTERS.put("borderleft2", new byte[] { 3, 2, 2, 2, 2, 2, 2, 3 }); CHARACTERS.put("borderleft3", new byte[] { 7, 4, 4, 4, 4, 4, 4, 7 }); CHARACTERS.put("borderleft4", new byte[] { 15, 8, 8, 8, 8, 8, 8, 15 }); CHARACTERS.put("borderleft5", new byte[] { 31, 16, 16, 16, 16, 16, 16, 31 }); CHARACTERS.put("bordertopbottom5", new byte[] { 31, 0, 0, 0, 0, 0, 0, 31 }); CHARACTERS.put("borderright1", new byte[] { 16, 16, 16, 16, 16, 16, 16, 16 }); CHARACTERS.put("borderright2", new byte[] { 24, 8, 8, 8, 8, 8, 8, 24 }); CHARACTERS.put("borderright3", new byte[] { 28, 4, 4, 4, 4, 4, 4, 28 }); CHARACTERS.put("borderright4", new byte[] { 30, 2, 2, 2, 2, 2, 2, 30 }); CHARACTERS.put("borderright5", new byte[] { 31, 1, 1, 1, 1, 1, 1, 31 }); CHARACTERS.put("box1", new byte[] { 3, 3, 3, 0, 0, 0, 0 }); CHARACTERS.put("box2", new byte[] { 24, 24, 24, 0, 0, 0, 0 }); CHARACTERS.put("box3", new byte[] { 27, 27, 27, 0, 0, 0, 0 }); CHARACTERS.put("box4", new byte[] { 0, 0, 0, 0, 3, 3, 3 }); CHARACTERS.put("box5", new byte[] { 3, 3, 3, 0, 3, 3, 3 }); CHARACTERS.put("box6", new byte[] { 24, 24, 24, 0, 3, 3, 3 }); CHARACTERS.put("box7", new byte[] { 27, 27, 27, 0, 3, 3, 3 }); CHARACTERS.put("box8", new byte[] { 0, 0, 0, 0, 24, 24, 24 }); CHARACTERS.put("box9", new byte[] { 3, 3, 3, 0, 24, 24, 24 }); CHARACTERS.put("box10", new byte[] { 24, 24, 24, 0, 24, 24, 24 }); CHARACTERS.put("box11", new byte[] { 27, 27, 27, 0, 24, 24, 24 }); CHARACTERS.put("box12", new byte[] { 0, 0, 0, 0, 27, 27, 27 }); CHARACTERS.put("box13", new byte[] { 3, 3, 3, 0, 27, 27, 27 }); CHARACTERS.put("box14", new byte[] { 24, 24, 24, 0, 27, 27, 27 }); CHARACTERS.put("box15", new byte[] { 27, 27, 27, 0, 27, 27, 27 }); CHARACTERS.put("euro", new byte[] { 3, 4, 30, 8, 30, 8, 7 }); CHARACTERS.put("cent", new byte[] { 0, 0, 14, 17, 16, 21, 14, 8 }); CHARACTERS.put("speaker", new byte[] { 1, 3, 15, 15, 15, 3, 1 }); CHARACTERS.put("sound", new byte[] { 8, 16, 0, 24, 0, 16, 8 }); CHARACTERS.put("x", new byte[] { 0, 27, 14, 4, 14, 27, 0 }); CHARACTERS.put("target", new byte[] { 0, 10, 17, 21, 17, 10, 0 }); CHARACTERS.put("pointerright", new byte[] { 0, 8, 12, 14, 12, 8, 0 }); CHARACTERS.put("pointerup", new byte[] { 0, 0, 4, 14, 31, 0, 0 }); CHARACTERS.put("pointerleft", new byte[] { 0, 2, 6, 14, 6, 2, 0 }); CHARACTERS.put("pointerdown", new byte[] { 0, 0, 31, 14, 4, 0, 0 }); CHARACTERS.put("arrowne", new byte[] { 0, 15, 3, 5, 9, 16, 0 }); CHARACTERS.put("arrownw", new byte[] { 0, 30, 24, 20, 18, 1, 0 }); CHARACTERS.put("arrowsw", new byte[] { 0, 1, 18, 20, 24, 30, 0 }); CHARACTERS.put("arrowse", new byte[] { 0, 16, 9, 5, 3, 15, 0 }); CHARACTERS.put("dice1", new byte[] { 0, 0, 0, 4, 0, 0, 0 }); CHARACTERS.put("dice2", new byte[] { 0, 16, 0, 0, 0, 1, 0 }); CHARACTERS.put("dice3", new byte[] { 0, 16, 0, 4, 0, 1, 0 }); CHARACTERS.put("dice4", new byte[] { 0, 17, 0, 0, 0, 17, 0 }); CHARACTERS.put("dice5", new byte[] { 0, 17, 0, 4, 0, 17, 0 }); CHARACTERS.put("dice6", new byte[] { 0, 17, 0, 17, 0, 17, 0 }); CHARACTERS.put("bell", new byte[] { 4, 14, 14, 14, 31, 0, 4 }); CHARACTERS.put("smile", new byte[] { 0, 10, 0, 17, 14, 0, 0 }); CHARACTERS.put("note", new byte[] { 2, 3, 2, 14, 30, 12, 0 }); CHARACTERS.put("clock", new byte[] { 0, 14, 21, 23, 17, 14, 0 }); CHARACTERS.put("heart", new byte[] { 0, 10, 31, 31, 31, 14, 4, 0 }); CHARACTERS.put("duck", new byte[] { 0, 12, 29, 15, 15, 6, 0 }); CHARACTERS.put("check", new byte[] { 0, 1, 3, 22, 28, 8, 0 }); CHARACTERS.put("retarrow", new byte[] { 1, 1, 5, 9, 31, 8, 4 }); CHARACTERS.put("runninga", new byte[] { 6, 6, 5, 14, 20, 4, 10, 17 }); CHARACTERS.put("runningb", new byte[] { 6, 6, 4, 14, 14, 4, 10, 10 }); CHARACTERS.put("space_invader", new byte[] { 0x00, 0x0e, 0x15, 0x1f, 0x0a, 0x04, 0x0a, 0x11 }); CHARACTERS.put("smilie", new byte[] { 0x00, 0x00, 0x0a, 0x00, 0x00, 0x11, 0x0e, 0x00 }); CHARACTERS.put("frownie", new byte[] { 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0e, 0x11 }); } public static byte[] get(String code) { return CHARACTERS.get(code); } } public static interface LcdConnection extends Closeable { void write(byte values); boolean isDataInHighNibble(); int getBacklightBit(); int getEnableBit(); int getDataReadWriteBit(); int getRegisterSelectBit(); @Override void close() throws RuntimeIOException; } public static class PiFaceCadLcdConnection implements LcdConnection { private static final int CHIP_SELECT = 1; private static final int ADDRESS = 0; private static final int PORT = 1; /* * MCP23S17 GPIOB to HD44780 pin map * PH_PIN_D4 = 0 * PH_PIN_D5 = 1 * PH_PIN_D6 = 2 * PH_PIN_D7 = 3 * PH_PIN_ENABLE = 4 * PH_PIN_RW = 5 * PH_PIN_RS = 6 * PH_PIN_LED_EN = 7 */ // Register select (0: instruction, 1:data) private static final byte REGISTER_SELECT_BIT = 6; // Select read or write (0: Write, 1: Read). private static final byte DATA_READ_WRITE_BIT = 5; // Enable bit, starts read/write. private static final byte ENABLE_BIT = 4; // Backlight control bit (1=on, 0=off) private static final int BACKLIGHT_BIT = 7; private MCP23S17 mcp23s17; private boolean dataInHighNibble = false; private int registerSelectBit = REGISTER_SELECT_BIT; private int dataReadWriteBit = DATA_READ_WRITE_BIT; private int enableBit = ENABLE_BIT; private int backlightBit = BACKLIGHT_BIT; public PiFaceCadLcdConnection(int controller) { mcp23s17 = new MCP23S17(controller, CHIP_SELECT, ADDRESS, MCP23xxx.INTERRUPT_GPIO_NOT_SET); // All output mcp23s17.setDirections(PORT, (byte) 0); } @Override public void write(byte values) { //byte new_values = (byte) ((values >> 4) & 0x0f); //new_values |= values << 4; mcp23s17.setValues(PORT, values); } @Override public void close() throws RuntimeIOException { mcp23s17.close(); } @Override public boolean isDataInHighNibble() { return dataInHighNibble; } @Override public int getRegisterSelectBit() { return registerSelectBit; } @Override public int getDataReadWriteBit() { return dataReadWriteBit; } @Override public int getEnableBit() { return enableBit; } @Override public int getBacklightBit() { return backlightBit; } } public static class PCF8574LcdConnection implements LcdConnection { // Default I2C device address for the PCF8574 public static final int DEFAULT_DEVICE_ADDRESS = 0x27; private static final int PORT = 0; /* * Default PCF8574 GPIO to HD44780 pin map * PH_PIN_RS = 0 * PH_PIN_RW = 1 * PH_PIN_ENABLE = 2 * PH_PIN_LED_EN = 3 * PH_PIN_D4 = 4 * PH_PIN_D5 = 5 * PH_PIN_D6 = 6 * PH_PIN_D7 = 7 */ // Register select (0: instruction, 1:data) private static final byte REGISTER_SELECT_BIT = 0; // Select read or write (0: Write, 1: Read). private static final byte DATA_READ_WRITE_BIT = 1; // Enable bit, starts read/write. private static final byte ENABLE_BIT = 2; // Backlight control bit (1=on, 0=off) private static final int BACKLIGHT_BIT = 3; private PCF8574 pcf8574; private boolean dataInHighNibble = true; private int registerSelectBit = REGISTER_SELECT_BIT; private int dataReadWriteBit = DATA_READ_WRITE_BIT; private int enableBit = ENABLE_BIT; private int backlightBit = BACKLIGHT_BIT; public PCF8574LcdConnection(int controller) { this(controller, DEFAULT_DEVICE_ADDRESS); } public PCF8574LcdConnection(int controller, int deviceAddress) { this(DeviceFactoryHelper.getNativeDeviceFactory(), controller, deviceAddress); } public PCF8574LcdConnection(I2CDeviceFactoryInterface deviceFactory, int controller, int deviceAddress) { pcf8574 = new PCF8574(deviceFactory, controller, deviceAddress, I2CConstants.ADDR_SIZE_7, I2CConstants.DEFAULT_CLOCK_FREQUENCY); } @Override public void write(byte values) { pcf8574.setValues(PORT, values); } @Override public boolean isDataInHighNibble() { return dataInHighNibble; } @Override public int getRegisterSelectBit() { return registerSelectBit; } @Override public int getDataReadWriteBit() { return dataReadWriteBit; } @Override public int getEnableBit() { return enableBit; } @Override public int getBacklightBit() { return backlightBit; } @Override public void close() throws RuntimeIOException { pcf8574.close(); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy