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

com.diozero.devices.sandpit.BareLcd Maven / Gradle / Ivy

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

/*-
 * #%L
 * Organisation: diozero
 * Project:      diozero - Core
 * Filename:     BareLcd.java
 * 
 * This file is part of the diozero project. More information about this project
 * can be found at https://www.diozero.com/.
 * %%
 * Copyright (C) 2016 - 2021 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.nio.charset.StandardCharsets;

import com.diozero.api.DeviceInterface;
import com.diozero.api.DigitalOutputDevice;
import com.diozero.api.RuntimeIOException;
import com.diozero.util.SleepUtil;

public class BareLcd implements DeviceInterface {
	/** 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_5X8DOTS = 0x00;

	private static final byte[] rowOffsets = { 0x00, 0x40 };

	private final DigitalOutputDevice[] pins;
	private final DigitalOutputDevice registerSelect;
	private final DigitalOutputDevice enable;
	private boolean blinkEnabled;
	private boolean cursorEnabled;
	private boolean displayOn;

	public BareLcd(int d4, int d5, int d6, int d7, int rs, int e) {
		this.pins = new DigitalOutputDevice[] { new DigitalOutputDevice(d4), new DigitalOutputDevice(d5),
				new DigitalOutputDevice(d6), new DigitalOutputDevice(d7) };

		this.registerSelect = new DigitalOutputDevice(rs);
		this.enable = new DigitalOutputDevice(e);

		// init
		registerSelect.setValue(false);
		write4Bits((byte) (INST_FUNCTION_SET | FS_DATA_LENGTH_8BIT));
		SleepUtil.sleepMillis(5);
		write4Bits((byte) (INST_FUNCTION_SET | FS_DATA_LENGTH_8BIT));
		sleepMicros(120);
		write4Bits((byte) (INST_FUNCTION_SET | FS_DATA_LENGTH_8BIT));
		write4Bits((byte) (INST_FUNCTION_SET | FS_DATA_LENGTH_4BIT));

		sendCommand((byte) (INST_FUNCTION_SET | FS_DATA_LENGTH_4BIT | FS_DISPLAY_2LINES | FS_CHAR_FONT_5X8DOTS));

		setDisplay(true, true, true);

		sendCommand((byte) (INST_ENTRY_MODE_SET | EMS_CURSOR_INCREMENT | EMS_DISPLAY_SHIFT_OFF));
		sendCommand(INST_SET_DDRAM_ADDR);

		clear();
	}

	public void setDisplay(boolean on, boolean cursor, boolean blink) {
		this.displayOn = on;
		this.cursorEnabled = cursor;
		this.blinkEnabled = blink;

		sendCommand((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)));
	}

	public void clear() {
		sendCommand(INST_CLEAR_DISPLAY);
		SleepUtil.sleepMillis(1);
	}

	public void cursorHome() {
		sendCommand(INST_RETURN_HOME);
		SleepUtil.sleepMillis(1);
	}

	public void setCursorPosition(int row, int col) {
		sendCommand((byte) (INST_SET_DDRAM_ADDR | (col + rowOffsets[row])));
	}

	public void setCharacter(int row, int col, char c) {
		setCursorPosition(row, col);
		addText(c);
	}

	public void addText(String s) {
		for (byte b : s.getBytes(StandardCharsets.UTF_8)) {
			System.out.println(b);
			sendData(b);
		}
	}

	public void addText(char c) {
		sendData((byte) c);
	}

	public void cursorOn() {
		setDisplay(displayOn, true, blinkEnabled);
	}

	public void cursorOff() {
		setDisplay(displayOn, false, blinkEnabled);
	}

	private void sendCommand(byte value) {
		writeByte(false, value);
	}

	private void sendData(byte value) {
		writeByte(true, value);
	}

	private void writeByte(boolean data, byte value) {
		registerSelect.setValue(data);
		write4Bits((byte) (value >> 4));
		write4Bits(value);
	}

	private void write4Bits(byte value) {
		for (int i = 0; i < 4; i++) {
			pins[i].setValue(((value >> i) & 0x01) != 0);
		}

		enable.off();
		sleepMicros(1);
		enable.on();
		sleepMicros(1);
		enable.off();
		sleepMicros(100);
	}

	private void sleepMicros(int micros) {
		SleepUtil.busySleep(micros * 1000L);
	}

	@Override
	public void close() throws RuntimeIOException {
		for (DigitalOutputDevice device : pins) {
			device.close();
		}
		registerSelect.close();
		enable.close();
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy