/ adafruit_epd / ssd1675b.py
ssd1675b.py
1 # The MIT License (MIT) 2 # 3 # Copyright (c) 2018 Dean Miller for Adafruit Industries 4 # 5 # Permission is hereby granted, free of charge, to any person obtaining a copy 6 # of this software and associated documentation files (the "Software"), to deal 7 # in the Software without restriction, including without limitation the rights 8 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 # copies of the Software, and to permit persons to whom the Software is 10 # furnished to do so, subject to the following conditions: 11 # 12 # The above copyright notice and this permission notice shall be included in 13 # all copies or substantial portions of the Software. 14 # 15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 # THE SOFTWARE. 22 """ 23 `adafruit_epd.ssd1675b` - Adafruit SSD1675 - ePaper display driver 24 ==================================================================================== 25 CircuitPython driver for Adafruit SSD1675 display breakouts 26 * Author(s): Dean Miller, Ladyada 27 """ 28 29 import time 30 from micropython import const 31 import adafruit_framebuf 32 from adafruit_epd.epd import Adafruit_EPD 33 34 __version__ = "0.0.0-auto.0" 35 __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_EPD.git" 36 37 _SSD1675B_DRIVER_CONTROL = const(0x01) 38 _SSD1675B_GATE_VOLTAGE = const(0x03) 39 _SSD1675B_SOURCE_VOLTAGE = const(0x04) 40 _SSD1675B_INIT_SETTING = const(0x08) 41 _SSD1675B_INIT_WRITE_REG = const(0x09) 42 _SSD1675B_INIT_READ_REG = const(0x0A) 43 _SSD1675B_BOOSTER_SOFT_START = const(0x0C) 44 _SSD1675B_GATESCAN_START = const(0x0F) 45 _SSD1675B_DEEP_SLEEP = const(0x10) 46 _SSD1675B_DATA_MODE = const(0x11) 47 _SSD1675B_SW_RESET = const(0x12) 48 _SSD1675B_HV_READY = const(0x14) 49 _SSD1675B_VCI_READY = const(0x15) 50 _SSD1675B_TEMP_CONTROL = const(0x18) 51 _SSD1675B_TEMP_WRITE = const(0x1A) 52 _SSD1675B_TEMP_READ = const(0x1B) 53 _SSD1675B_EXTTEMP_WRITE = const(0x1C) 54 _SSD1675B_MASTER_ACTIVATE = const(0x20) 55 _SSD1675B_DISP_CTRL1 = const(0x21) 56 _SSD1675B_DISP_CTRL2 = const(0x22) 57 _SSD1675B_WRITE_RAM1 = const(0x24) 58 _SSD1675B_WRITE_RAM2 = const(0x26) 59 _SSD1675B_READ_RAM = const(0x27) 60 _SSD1675B_VCOM_SENSE = const(0x28) 61 _SSD1675B_VCOM_DURATION = const(0x29) 62 _SSD1675B_WRITE_VCOM_OTP = const(0x2A) 63 _SSD1675B_WRITE_VCOM_CTRL = const(0x2B) 64 _SSD1675B_WRITE_VCOM_REG = const(0x2C) 65 _SSD1675B_READ_OTP = const(0x2D) 66 _SSD1675B_READ_USERID = const(0x2E) 67 _SSD1675B_READ_STATUS = const(0x2F) 68 _SSD1675B_WRITE_WS_OTP = const(0x30) 69 _SSD1675B_LOAD_WS_OTP = const(0x31) 70 _SSD1675B_WRITE_LUT = const(0x32) 71 _SSD1675B_CRC_CALC = const(0x34) 72 _SSD1675B_CRC_READ = const(0x35) 73 _SSD1675B_PROG_OTP = const(0x36) 74 _SSD1675B_WRITE_DISPLAY_OPT = const(0x37) 75 _SSD1675B_WRITE_USERID = const(0x38) 76 _SSD1675B_OTP_PROGMODE = const(0x39) 77 _SSD1675B_WRITE_DUMMY = const(0x3A) 78 _SSD1675B_WRITE_GATELINE = const(0x3B) 79 _SSD1675B_WRITE_BORDER = const(0x3C) 80 _SSD1675B_SET_RAMXPOS = const(0x44) 81 _SSD1675B_SET_RAMYPOS = const(0x45) 82 _SSD1675B_AUTOWRITE_RED = const(0x46) 83 _SSD1675B_AUTOWRITE_BW = const(0x47) 84 _SSD1675B_SET_RAMXCOUNT = const(0x4E) 85 _SSD1675B_SET_RAMYCOUNT = const(0x4F) 86 _SSD1675B_SET_ANALOGBLOCK = const(0x74) 87 _SSD1675B_SET_DIGITALBLOCK = const(0x7E) 88 _SSD1675B_NOP = const(0xFF) 89 _LUT_DATA = b"\xa0\x90P\x00\x00\x00\x00\x00\x00\x00P\x90\xa0\x00\x00\x00\x00\x00\x00\x00\xa0\x90P\x00\x00\x00\x00\x00\x00\x00P\x90\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x0f\x00\x00\x00\x0f\x0f\x00\x00\x03\x0f\x0f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x15A\xa82P,\x0b" # pylint: disable=line-too-long 90 91 92 class Adafruit_SSD1675B(Adafruit_EPD): 93 """driver class for Adafruit SSD1675B ePaper display breakouts""" 94 95 # pylint: disable=too-many-arguments 96 def __init__( 97 self, width, height, spi, *, cs_pin, dc_pin, sramcs_pin, rst_pin, busy_pin 98 ): 99 super(Adafruit_SSD1675B, self).__init__( 100 width, height, spi, cs_pin, dc_pin, sramcs_pin, rst_pin, busy_pin 101 ) 102 stride = width 103 if stride % 8 != 0: 104 stride += 8 - stride % 8 105 106 self._buffer1_size = int(stride * height / 8) 107 self._buffer2_size = self._buffer1_size 108 109 if sramcs_pin: 110 self._buffer1 = self.sram.get_view(0) 111 self._buffer2 = self.sram.get_view(self._buffer1_size) 112 else: 113 self._buffer1 = bytearray(self._buffer1_size) 114 self._buffer2 = bytearray(self._buffer2_size) 115 # since we have *two* framebuffers - one for red and one for black 116 # we dont subclass but manage manually 117 self._framebuf1 = adafruit_framebuf.FrameBuffer( 118 self._buffer1, 119 width, 120 height, 121 stride=stride, 122 buf_format=adafruit_framebuf.MHMSB, 123 ) 124 self._framebuf2 = adafruit_framebuf.FrameBuffer( 125 self._buffer2, 126 width, 127 height, 128 stride=stride, 129 buf_format=adafruit_framebuf.MHMSB, 130 ) 131 self.set_black_buffer(0, True) 132 self.set_color_buffer(0, True) 133 # pylint: enable=too-many-arguments 134 135 def begin(self, reset=True): 136 """Begin communication with the display and set basic settings""" 137 if reset: 138 self.hardware_reset() 139 self.power_down() 140 141 def busy_wait(self): 142 """Wait for display to be done with current task, either by polling the 143 busy pin, or pausing""" 144 if self._busy: 145 while self._busy.value: 146 time.sleep(0.01) 147 else: 148 time.sleep(0.5) 149 150 def power_up(self): 151 """Power up the display in preparation for writing RAM and updating""" 152 self.hardware_reset() 153 time.sleep(0.1) 154 self.busy_wait() 155 156 self.command(_SSD1675B_SW_RESET) 157 self.busy_wait() 158 159 # set analog block control 160 self.command(_SSD1675B_SET_ANALOGBLOCK, bytearray([0x54])) 161 # set digital block control 162 self.command(_SSD1675B_SET_DIGITALBLOCK, bytearray([0x3B])) 163 164 self.command( 165 _SSD1675B_DRIVER_CONTROL, 166 bytearray([self._height - 1, (self._height - 1) >> 8, 0x00]), 167 ) 168 169 # Data entry sequence 170 self.command(_SSD1675B_DATA_MODE, bytearray([0x03])) 171 172 # Set ram X start/end postion 173 self.command(_SSD1675B_SET_RAMXPOS, bytearray([0x00, self._width // 8])) 174 # Set ram Y start/end postion 175 self.command( 176 _SSD1675B_SET_RAMYPOS, 177 bytearray([0x0, 0x0, self._height - 1, (self._height - 1) >> 8]), 178 ) 179 180 # Border color 181 self.command(_SSD1675B_WRITE_BORDER, bytearray([0x03])) 182 183 # Vcom Voltage 184 self.command(_SSD1675B_WRITE_VCOM_REG, bytearray([0x50])) 185 # Set gate voltage 186 self.command(_SSD1675B_GATE_VOLTAGE, _LUT_DATA[100:101]) 187 # Set source voltage 188 self.command(_SSD1675B_SOURCE_VOLTAGE, _LUT_DATA[101:104]) 189 # Set dummy line period 190 self.command(_SSD1675B_WRITE_DUMMY, _LUT_DATA[105:106]) 191 # Set gate line width 192 self.command(_SSD1675B_WRITE_GATELINE, _LUT_DATA[106:107]) 193 # LUT 194 self.command(_SSD1675B_WRITE_LUT, _LUT_DATA[0:100]) 195 196 # Set temperature control 197 # self.command(_SSD1675B_TEMP_CONTROL, bytearray([0x80])) 198 199 # Set RAM X address counter 200 self.command(_SSD1675B_SET_RAMXCOUNT, bytearray([0])) 201 # Set RAM Y address counter 202 self.command( 203 _SSD1675B_SET_RAMYCOUNT, 204 bytearray([self._height - 1, (self._height - 1) >> 8]), 205 ) 206 207 self.busy_wait() 208 209 def power_down(self): 210 """Power down the display - required when not actively displaying!""" 211 self.command(_SSD1675B_DEEP_SLEEP, bytearray([0x01])) 212 time.sleep(0.1) 213 214 def update(self): 215 """Update the display from internal memory""" 216 self.command(_SSD1675B_DISP_CTRL2, bytearray([0xC7])) 217 self.command(_SSD1675B_MASTER_ACTIVATE) 218 self.busy_wait() 219 if not self._busy: 220 time.sleep(3) # wait 3 seconds 221 222 def write_ram(self, index): 223 """Send the one byte command for starting the RAM write process. Returns 224 the byte read at the same time over SPI. index is the RAM buffer, can be 225 0 or 1 for tri-color displays.""" 226 if index == 0: 227 return self.command(_SSD1675B_WRITE_RAM1, end=False) 228 if index == 1: 229 return self.command(_SSD1675B_WRITE_RAM2, end=False) 230 raise RuntimeError("RAM index must be 0 or 1") 231 232 def set_ram_address(self, x, y): # pylint: disable=unused-argument, no-self-use 233 """Set the RAM address location, not used on this chipset but required by 234 the superclass""" 235 self.command(_SSD1675B_SET_RAMXCOUNT, bytearray([x])) 236 self.command(_SSD1675B_SET_RAMYCOUNT, bytearray([y, y >> 8]))