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

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

The newest version!
package com.diozero.devices.sandpit;

/*-
 * #%L
 * Organisation: diozero
 * Project:      diozero - Core
 * Filename:     WaveshareEink75b.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 com.diozero.api.DigitalInputDevice;
import com.diozero.api.DigitalOutputDevice;
import com.diozero.util.SleepUtil;

/**
 * 7.5" Datasheet:
 * https://www.waveshare.com/wiki/File:7.5inch-e-paper-specification.pdf 7.5" V2
 * Datasheet:
 * https://www.waveshare.com/w/upload/6/60/7.5inch_e-Paper_V2_Specification.pdf
 * https://www.waveshare.com/wiki/7.5inch_e-Paper_HAT
 *
 * Code: https://github.com/waveshare/e-Paper
 *
 * OTP: One Time Programmable memory, not programmed into registers by the
 * driver SW for this controller. LUT: Waveform Look Up Table
 */
public class WaveshareEink75b extends WaveshareEink {
	private static final byte PANEL_SETTING_REG = 0x00;
	private static final byte POWER_SETTING_REG = 0x01;
	private static final byte POWER_OFF_REG = 0x02;
	private static final byte POWER_OFF_SEQ_REG = 0x03;
	private static final byte POWER_ON_REG = 0x04;
	private static final byte POWER_ON_MEAS_REG = 0x05;
	private static final byte BOOSTER_SOFT_START_REG = 0x06;
	private static final byte DEEP_SLEEP_REG = 0x07;
	// K/W or OLD pixel data
	private static final byte DISP_START_TRANS_REG = 0x10;
	private static final byte DATA_STOP_REG = 0x11;
	private static final byte DISPLAY_REFRESH_REG = 0x12;
	// Red or NEW pixel data
	private static final byte DISP2_START_TRANS_REG = 0x13;
	private static final byte DUAL_SPI_REG = 0x15;
	private static final byte AUTO_SEQ_REG = 0x17;
	private static final byte VCOM_AND_DATA_INT_REG = 0x50;
	private static final byte TCON_REG = 0x60;
	// Resolution
	private static final byte TRES_REG = 0x61;
	private static final byte REVISION_REG = 0x70;
	private static final byte I2C_STATUS_FLAG_REG = 0x71;

	public WaveshareEink75b(int controller, int chipSelect, DigitalOutputDevice reset,
			DigitalOutputDevice dataOrCommand, DigitalInputDevice busy) {
		super(Model._7x5V2, controller, chipSelect, reset, dataOrCommand, busy);
	}

	@Override
	protected void init() {
		reset();

		commandAndData(BOOSTER_SOFT_START_REG, new byte[] { 0x17, 0x17, 0x27, 0x17 });

		// datasheet p20:
		// commandAndData(POWER_SETTING_REG, new byte[] { 0x07, 0x17, 0x3f, 0x3f });
		// data[0] - example: 0x07 (board disabled and internal power)
		// bit[4]: Border. 0: border disabled (default), 1: border enabled
		// bit[2:0] Power source. 1: internal power, 0: external power source
		// data[1] - example: 0x07 or data sheet 0x17 (fast VCOM slew)
		// bit[7]: OTP power selection (0: external, 1: internal)
		// bit[4]: VCOM_SLEW. 0: slow, 1: fast
		// bit[2:0]: VG_LVL. Voltage level 9,10,11,12,17,18,19,20v
		// data[2] - example 0x3f (15v)
		// bit[5:0] VDH_LVL. Voltage increments of 0.2v from 2.4v to 15v
		// data[3] VDL_LVL[5:0] 0x3f (-15v)
		// data[4] VDHR_LVL[5:0] - not set
		// Power setting: VGH=20V, VGL=-20V; VDH=15V, VDL=-15V
		commandAndData(POWER_SETTING_REG, new byte[] { 0x07, 0x07, 0x3f, 0x3f });

		// Power on
		command(POWER_ON_REG);
		SleepUtil.sleepMillis(100);
		readBusy();

		// [5] REG: LUT selection. 0: LUT from OTP (default), 1: LUT from register
		// [4] KW/R: Black / White / Red.
		// 0: Pixel with Black/White/Red, KWR mode. (Default)
		// 1: Pixel with Black/White, KW mode.
		// [3] UD: Gate scan direction. 0: Scan down, 1: Scan up (default)
		// [2] SHL: Source Shift Direction. 0: Shift left, 1: Shift right (default)
		// [1] SHD_N: Booster Switch. 0: Booster OFF, 1: Booster ON (default)
		// [0] RST_N: Soft Rest. 0: Reset, 1: No effect (default)
		// Example 0x1f -> 0b00011111 (LUT: OTP, KW, Scan up/right, boost on)
		// LUT Reg/B&W: 0x3f, LUT Reg/BW&R: 0x2f, LUT OTP/B&W: 0x1f, LUT OTP/BW&R: 0x0f
		commandAndData(PANEL_SETTING_REG, (byte) 0x1f);

		// Resolution: Source 800 (0x03, 0x20), Gate 480 (0x01, 0xe0)
		// HRES[9:3]: Horizontal resolution / 8. (value range 1..100)
		// VRES[9:0]: Vertical resolution. (value range 1..600)
		// Last active source = HRES[9:3] * 8 - 1
		// Last active gate = VRES[9:0] - 1
		// 0x320 == HRES[9:3] 0b1100100000 == HRES[6:0] 0b1100100 == 100
		// data[0] HRES[9:8]
		// data[1] HRES[7:3]
		// 0x1e0 == VRES[9:0] 0b111100000 == 480
		// data[2] VRES[9:8]
		// data[3] VRES[7:0]
		int hres = model.getHeight();
		int vres = model.getWidth();
		// commandAndData(TRES_REG, new byte[] { 0x03, 0x20, 0x01, (byte) 0xe0 });
		commandAndData(TRES_REG, new byte[] { (byte) ((hres >> 8) & 0x03), (byte) (hres & 0xf8),
				(byte) ((vres >> 8) & 0x03), (byte) (vres & 0xff) });

		// data[0] Dual SPI mode
		// [5] MM_EN: MM input pin definition enable. 0: disable, 1: enable
		// [4] DUSPI_EN: Dual SPI mode enable. 0: disable, 1: enable
		commandAndData(DUAL_SPI_REG, (byte) 0x00);

		// data[0] Non-overlap period of Gate and Source
		// [7:4] S2G[3:0]: Source to Gate.
		// [3:0] G2S[3:0]: Gate to Source.
		// 0..15 increments of 4 period units (4..64)
		// 1 period unit = 667 nS. Default for both is 0b0010 (12 == 8 uS)
		commandAndData(TCON_REG, (byte) 0x22);

		// VCOM and Data interval Setting - Set Interval between VCOM and Data
		// data[0] example 0x10
		// [7] BDZ: Border Hi-Z control. 0: disabled (default), 1: enabled
		// [5:4] BDV[1:0]: Border LUT selection.
		// [3] N2OCP Copy frame data from NEW data to OLD data enable control after
		// display refresh with NEW/OLD in KW mode. 0: disabled, 1: enabled
		// [1:0] DDX[1:0]: Data polarity.
		// data[1] example 0x07 (default)
		// CDI[3:0]: VCOM and data interval. 0 (17) to 15 (2)
		commandAndData(VCOM_AND_DATA_INT_REG, new byte[] { 0x10, 0x07 });
	}

	@Override
	protected void sleep() {
		command(POWER_OFF_REG);
		readBusy();
		commandAndData(DEEP_SLEEP_REG, (byte) 0xa5);

		SleepUtil.sleepMillis(2_000);
	}

	@Override
	protected void clear() {
		byte[] buf = new byte[model.getWidth() * model.getHeight()];
		commandAndData(DISP_START_TRANS_REG, buf);
		commandAndData(DISP2_START_TRANS_REG, buf);
		command(DISPLAY_REFRESH_REG);
		SleepUtil.sleepMillis(100);
		readBusy();
	}

	@Override
	protected void readBusy() {
		do {
			command((byte) 0x71);
			SleepUtil.sleepMillis(1);
		} while (!busy.getValue());
		SleepUtil.sleepMillis(200);
	}

	@Override
	protected void getRevision() {
		command(REVISION_REG);
		dataOrCommand.on();
		// PROD_REV[23:0], LUT_REV[23:0], CHIP_REV[7:0]
		byte[] buffer = new byte[3 + 3 + 1];
		buffer = device.writeAndRead(buffer);
		prodRev = (buffer[0] & 0xff) << 16 | (buffer[1] & 0xff) << 8 | (buffer[2] & 0xff);
		lutRev = (buffer[3] & 0xff) << 16 | (buffer[4] & 0xff) << 8 | (buffer[5] & 0xff);
		// Should be fixed at 0b00001100
		chipRev = buffer[6] & 0xff;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy