/ 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]))