/ adafruit_epd / ssd1675.py
ssd1675.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.ssd1675` - 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 _SSD1675_DRIVER_CONTROL = const(0x01) 38 _SSD1675_GATE_VOLTAGE = const(0x03) 39 _SSD1675_SOURCE_VOLTAGE = const(0x04) 40 _SSD1675_DEEP_SLEEP = const(0x10) 41 _SSD1675_DATA_MODE = const(0x11) 42 _SSD1675_SW_RESET = const(0x12) 43 _SSD1675_HV_READY = const(0x14) 44 _SSD1675_VCI_READY = const(0x15) 45 _SSD1675_TEMP_WRITE = const(0x1A) 46 _SSD1675_MASTER_ACTIVATE = const(0x20) 47 _SSD1675_DISP_CTRL1 = const(0x21) 48 _SSD1675_DISP_CTRL2 = const(0x22) 49 _SSD1675_WRITE_RAM1 = const(0x24) 50 _SSD1675_WRITE_RAM2 = const(0x26) 51 _SSD1675_WRITE_VCOM = const(0x2C) 52 _SSD1675_READ_OTP = const(0x2D) 53 _SSD1675_WRITE_LUT = const(0x32) 54 _SSD1675_WRITE_DUMMY = const(0x3A) 55 _SSD1675_WRITE_GATELINE = const(0x3B) 56 _SSD1675_WRITE_BORDER = const(0x3C) 57 _SSD1675_SET_RAMXPOS = const(0x44) 58 _SSD1675_SET_RAMYPOS = const(0x45) 59 _SSD1675_SET_RAMXCOUNT = const(0x4E) 60 _SSD1675_SET_RAMYCOUNT = const(0x4F) 61 _SSD1675_SET_ANALOGBLOCK = const(0x74) 62 _SSD1675_SET_DIGITALBLOCK = const(0x7E) 63 _LUT_DATA = b"\x80`@\x00\x00\x00\x00\x10` \x00\x00\x00\x00\x80`@\x00\x00\x00\x00\x10` \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x03\x00\x00\x02\t\t\x00\x00\x02\x03\x03\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x15A\xa820\n" # pylint: disable=line-too-long 64 65 66 class Adafruit_SSD1675(Adafruit_EPD): 67 """driver class for Adafruit SSD1675 ePaper display breakouts""" 68 69 # pylint: disable=too-many-arguments 70 def __init__( 71 self, width, height, spi, *, cs_pin, dc_pin, sramcs_pin, rst_pin, busy_pin 72 ): 73 super(Adafruit_SSD1675, self).__init__( 74 width, height, spi, cs_pin, dc_pin, sramcs_pin, rst_pin, busy_pin 75 ) 76 stride = width 77 if stride % 8 != 0: 78 stride += 8 - stride % 8 79 80 self._buffer1_size = int(stride * height / 8) 81 self._buffer2_size = self._buffer1_size 82 83 if sramcs_pin: 84 self._buffer1 = self.sram.get_view(0) 85 self._buffer2 = self.sram.get_view(self._buffer1_size) 86 else: 87 self._buffer1 = bytearray(self._buffer1_size) 88 self._buffer2 = bytearray(self._buffer2_size) 89 # since we have *two* framebuffers - one for red and one for black 90 # we dont subclass but manage manually 91 self._framebuf1 = adafruit_framebuf.FrameBuffer( 92 self._buffer1, 93 width, 94 height, 95 stride=stride, 96 buf_format=adafruit_framebuf.MHMSB, 97 ) 98 self._framebuf2 = adafruit_framebuf.FrameBuffer( 99 self._buffer2, 100 width, 101 height, 102 stride=stride, 103 buf_format=adafruit_framebuf.MHMSB, 104 ) 105 self.set_black_buffer(0, True) 106 self.set_color_buffer(0, True) 107 # pylint: enable=too-many-arguments 108 109 def begin(self, reset=True): 110 """Begin communication with the display and set basic settings""" 111 if reset: 112 self.hardware_reset() 113 self.power_down() 114 115 def busy_wait(self): 116 """Wait for display to be done with current task, either by polling the 117 busy pin, or pausing""" 118 if self._busy: 119 while self._busy.value: 120 time.sleep(0.01) 121 else: 122 time.sleep(0.5) 123 124 def power_up(self): 125 """Power up the display in preparation for writing RAM and updating""" 126 self.hardware_reset() 127 time.sleep(0.1) 128 self.busy_wait() 129 130 self.command(_SSD1675_SW_RESET) 131 self.busy_wait() 132 133 # set analog block control 134 self.command(_SSD1675_SET_ANALOGBLOCK, bytearray([0x54])) 135 # set digital block control 136 self.command(_SSD1675_SET_DIGITALBLOCK, bytearray([0x3B])) 137 138 # driver output control 139 self.command(_SSD1675_DRIVER_CONTROL, bytearray([0xFA, 0x01, 0x00])) 140 # Data entry sequence 141 self.command(_SSD1675_DATA_MODE, bytearray([0x03])) 142 # Set ram X start/end postion 143 self.command(_SSD1675_SET_RAMXPOS, bytearray([0x00, 0x0F])) 144 # Set ram Y start/end postion 145 self.command(_SSD1675_SET_RAMYPOS, bytearray([0, 0, 0xF9, 0])) 146 # Border color 147 self.command(_SSD1675_WRITE_BORDER, bytearray([0x03])) 148 # Vcom Voltage 149 self.command(_SSD1675_WRITE_VCOM, bytearray([0x70])) 150 # Set gate voltage 151 self.command(_SSD1675_GATE_VOLTAGE, _LUT_DATA[70:71]) 152 # Set gate voltage 153 self.command(_SSD1675_SOURCE_VOLTAGE, _LUT_DATA[71:74]) 154 # Set dummy line period 155 self.command(_SSD1675_WRITE_DUMMY, _LUT_DATA[74:75]) 156 # Set gate line width 157 self.command(_SSD1675_WRITE_GATELINE, _LUT_DATA[75:76]) 158 # LUT 159 self.command(_SSD1675_WRITE_LUT, _LUT_DATA[0:70]) 160 161 self.command(_SSD1675_SET_RAMXCOUNT, bytearray([0])) 162 # Set RAM Y address counter 163 self.command(_SSD1675_SET_RAMYCOUNT, bytearray([0xF9, 0])) 164 165 self.busy_wait() 166 167 def power_down(self): 168 """Power down the display - required when not actively displaying!""" 169 self.command(_SSD1675_DEEP_SLEEP, bytearray([0x01])) 170 time.sleep(0.1) 171 172 def update(self): 173 """Update the display from internal memory""" 174 self.command(_SSD1675_DISP_CTRL2, bytearray([0xC7])) 175 self.command(_SSD1675_MASTER_ACTIVATE) 176 self.busy_wait() 177 if not self._busy: 178 time.sleep(3) # wait 3 seconds 179 180 def write_ram(self, index): 181 """Send the one byte command for starting the RAM write process. Returns 182 the byte read at the same time over SPI. index is the RAM buffer, can be 183 0 or 1 for tri-color displays.""" 184 if index == 0: 185 return self.command(_SSD1675_WRITE_RAM1, end=False) 186 if index == 1: 187 return self.command(_SSD1675_WRITE_RAM2, end=False) 188 raise RuntimeError("RAM index must be 0 or 1") 189 190 def set_ram_address(self, x, y): # pylint: disable=unused-argument, no-self-use 191 """Set the RAM address location, not used on this chipset but required by 192 the superclass""" 193 self.command(_SSD1675_SET_RAMXCOUNT, bytearray([x])) 194 self.command(_SSD1675_SET_RAMYCOUNT, bytearray([y, y >> 8]))