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

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

The newest version!
package com.diozero.devices;

/*-
 * #%L
 * Organisation: diozero
 * Project:      diozero - Core
 * Filename:     LcdInterface.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 - 2024 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.util.Collection;
import java.util.HashMap;
import java.util.Map;

import com.diozero.api.DeviceInterface;
import com.diozero.util.StringUtil;

/**
 * Abstraction for LCD devices: provides common functionality that can be "chained" together
 * to provide a fluent-style interface.
 */
public interface LcdInterface> extends DeviceInterface {
    int getColumnCount();

    /**
     * Checks to see if the requested column is out of range.
     *
     * @param column the column
     */
    default void columnCheck(int column) {
        if (column < 0 || column >= getColumnCount()) {
            throw new IllegalArgumentException("Invalid column (" + column + "), must be 0.." + (getColumnCount() - 1));
        }
    }

    int getRowCount();

    /**
     * Checks to see if the requested row is out of bounds.
     *
     * @param row the row
     */
    default void rowCheck(int row) {
        if (row < 0 || row >= getRowCount()) {
            throw new IllegalArgumentException("Invalid row (" + row + "), must be 0.." + (getRowCount() - 1));
        }
    }

    boolean isBacklightEnabled();

    L setBacklightEnabled(boolean backlightEnabled);

    L setCursorPosition(int column, int row);

    /**
     * Sets a character on the display at a specific location.
     * @param column the column
     * @param row the row
     * @param character the character
     * @return this
     */
    default L setCharacter(int column, int row, char character) {
        setCursorPosition(column, row);
        return addText(character);
    }

    /**
     * Writes the text to the display, starting at the home position. Newlines ({@code '\n'})
     * will wrap text to the next line. Excessive characters and lines are trimmed.
     * Shorter lines are padded to fill the display.
     *
     * @param text Text to display
     * @return this
     */
    default L displayText(String text) {
        String[] splitText = text.split("\n");
        int minRows = Math.min(getRowCount(), splitText.length);
        for (int i = 0; i < minRows; i++) {
            setText(i, StringUtil.pad(splitText[i], getColumnCount()));
        }
        return (L)this;
    }

    /**
     * Send string to display, truncated to fit.
     *
     * @param row  Row number (starts at 0)
     * @param text Text to display
     * @return this
     */
    default L setText(int row, String text) {
        rowCheck(row);

        int columns = getColumnCount();
        int l = text.length();

        // Trim the string to the length of the column
        String textToSend = l > columns ? text.substring(0, columns) : text;

        // Set the cursor position to the start of the specified row
        setCursorPosition(0, row);
        return addText(textToSend);
    }

    /**
     * Add the string to the display at the current position.
     *
     * @param text the text
     * @return this
     */
    default L addText(String text) {
        for (byte character : text.getBytes()) {
            addText((char)character);
        }
        return (L)this;
    }

    /**
     * Add a character (e.g. alphanumeric) to the display at the current position.
     * Typically, this advances the cursor position by 1 in the set direction.
     *
     * @param character the text character
     * @return this
     */
    L addText(char character);

    /**
     * Add a special character to the display at the current position.
     * Typically, this advances the cursor position by 1 in the set direction.
     *
     * @param code the character code
     * @return this
     * @see #createChar(int, byte[])
     */
    L addText(int code);

    /**
     * Clear the display
     *
     * @return this
     */
    L clear();

    /**
     * Return the cursor to the home position
     *
     * @return this
     */
    L returnHome();

    /**
     * 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
     */
    L entryModeControl(boolean increment, boolean shiftDisplay);

    L autoscrollOn();

    L autoscrollOff();

    boolean isIncrementOn();

    boolean isShiftDisplayOn();

    L displayControl(boolean displayOn, boolean cursorEnabled, boolean blinkEnabled);

    L displayOn();

    L displayOff();

    L cursorOn();

    L cursorOff();

    L blinkOn();

    L blinkOff();

    boolean isCursorEnabled();

    boolean isBlinkEnabled();

    /**
     * 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
     */    L cursorOrDisplayShift(boolean displayShift, boolean shiftRight);

    L shiftDisplayRight();

    L shiftDisplayLeft();

    L moveCursorRight();

    L moveCursorLeft();

    /**
     * Upload a bit-map of a "special character" to the specified location.
     *
     * @param location the location/code for this character
     * @param charMap  the bit-map for the character (one byte per "lines" in the dot matrix)
     * @return this
     * @see Characters
     * @see #addText(int)
     */
    L createChar(int location, byte[] charMap);

    class Characters {
        private static final Map 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});
        }

        /**
         * Get the specs for the specified character
         *
         * @param name the name of the character
         * @return the uploadable byte-spec
         */
        public static byte[] get(String name) {
            return CHARACTERS.get(name);
        }

        /**
         * @return the names of the defined characters
         */
        public static Collection getCharacters() {
            return CHARACTERS.keySet();
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy