/ adafruit_epd / il0373.py
il0373.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.il0373` - Adafruit il0373 - ePaper display driver
 24  ====================================================================================
 25  CircuitPython driver for Adafruit il0373 display breakouts
 26  * Author(s): Dean Miller
 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  _IL0373_PANEL_SETTING = const(0x00)
 38  _IL0373_POWER_SETTING = const(0x01)
 39  _IL0373_POWER_OFF = const(0x02)
 40  _IL0373_POWER_OFF_SEQUENCE = const(0x03)
 41  _IL0373_POWER_ON = const(0x04)
 42  _IL0373_POWER_ON_MEASURE = const(0x05)
 43  _IL0373_BOOSTER_SOFT_START = const(0x06)
 44  _IL0373_DEEP_SLEEP = const(0x07)
 45  _IL0373_DTM1 = const(0x10)
 46  _IL0373_DATA_STOP = const(0x11)
 47  _IL0373_DISPLAY_REFRESH = const(0x12)
 48  _IL0373_DTM2 = const(0x13)
 49  _IL0373_PDTM1 = const(0x14)
 50  _IL0373_PDTM2 = const(0x15)
 51  _IL0373_PDRF = const(0x16)
 52  _IL0373_LUT1 = const(0x20)
 53  _IL0373_LUTWW = const(0x21)
 54  _IL0373_LUTBW = const(0x22)
 55  _IL0373_LUTWB = const(0x23)
 56  _IL0373_LUTBB = const(0x24)
 57  _IL0373_PLL = const(0x30)
 58  _IL0373_CDI = const(0x50)
 59  _IL0373_RESOLUTION = const(0x61)
 60  _IL0373_VCM_DC_SETTING = const(0x82)
 61  
 62  
 63  class Adafruit_IL0373(Adafruit_EPD):
 64      """driver class for Adafruit IL0373 ePaper display breakouts"""
 65  
 66      # pylint: disable=too-many-arguments
 67      def __init__(
 68          self, width, height, spi, *, cs_pin, dc_pin, sramcs_pin, rst_pin, busy_pin
 69      ):
 70          super(Adafruit_IL0373, self).__init__(
 71              width, height, spi, cs_pin, dc_pin, sramcs_pin, rst_pin, busy_pin
 72          )
 73  
 74          self._buffer1_size = int(width * height / 8)
 75          self._buffer2_size = int(width * height / 8)
 76  
 77          if sramcs_pin:
 78              self._buffer1 = self.sram.get_view(0)
 79              self._buffer2 = self.sram.get_view(self._buffer1_size)
 80          else:
 81              self._buffer1 = bytearray((width * height) // 8)
 82              self._buffer2 = bytearray((width * height) // 8)
 83          # since we have *two* framebuffers - one for red and one for black
 84          # we dont subclass but manage manually
 85          self._framebuf1 = adafruit_framebuf.FrameBuffer(
 86              self._buffer1, width, height, buf_format=adafruit_framebuf.MHMSB
 87          )
 88          self._framebuf2 = adafruit_framebuf.FrameBuffer(
 89              self._buffer2, width, height, buf_format=adafruit_framebuf.MHMSB
 90          )
 91          self.set_black_buffer(0, True)
 92          self.set_color_buffer(1, True)
 93          # pylint: enable=too-many-arguments
 94  
 95      def begin(self, reset=True):
 96          """Begin communication with the display and set basic settings"""
 97          if reset:
 98              self.hardware_reset()
 99          self.power_down()
100  
101      def busy_wait(self):
102          """Wait for display to be done with current task, either by polling the
103          busy pin, or pausing"""
104          if self._busy:
105              while not self._busy.value:
106                  time.sleep(0.01)
107          else:
108              time.sleep(0.5)
109  
110      def power_up(self):
111          """Power up the display in preparation for writing RAM and updating"""
112          self.hardware_reset()
113          self.busy_wait()
114  
115          self.command(_IL0373_POWER_SETTING, bytearray([0x03, 0x00, 0x2B, 0x2B, 0x09]))
116          self.command(_IL0373_BOOSTER_SOFT_START, bytearray([0x17, 0x17, 0x17]))
117          self.command(_IL0373_POWER_ON)
118  
119          self.busy_wait()
120          time.sleep(0.2)
121  
122          self.command(_IL0373_PANEL_SETTING, bytearray([0xCF]))
123          self.command(_IL0373_CDI, bytearray([0x37]))
124          self.command(_IL0373_PLL, bytearray([0x29]))
125          _b1 = self._width & 0xFF
126          _b2 = (self._height >> 8) & 0xFF
127          _b3 = self._height & 0xFF
128          self.command(_IL0373_RESOLUTION, bytearray([_b1, _b2, _b3]))
129          self.command(_IL0373_VCM_DC_SETTING, bytearray([0x0A]))
130          time.sleep(0.05)
131  
132      def power_down(self):
133          """Power down the display - required when not actively displaying!"""
134          self.command(_IL0373_CDI, bytearray([0x17]))
135          self.command(_IL0373_VCM_DC_SETTING, bytearray([0x00]))
136          self.command(_IL0373_POWER_OFF)
137  
138      def update(self):
139          """Update the display from internal memory"""
140          self.command(_IL0373_DISPLAY_REFRESH)
141          time.sleep(0.1)
142          self.busy_wait()
143          if not self._busy:
144              time.sleep(15)  # wait 15 seconds
145  
146      def write_ram(self, index):
147          """Send the one byte command for starting the RAM write process. Returns
148          the byte read at the same time over SPI. index is the RAM buffer, can be
149          0 or 1 for tri-color displays."""
150          if index == 0:
151              return self.command(_IL0373_DTM1, end=False)
152          if index == 1:
153              return self.command(_IL0373_DTM2, end=False)
154          raise RuntimeError("RAM index must be 0 or 1")
155  
156      def set_ram_address(self, x, y):  # pylint: disable=unused-argument, no-self-use
157          """Set the RAM address location, not used on this chipset but required by
158          the superclass"""
159          return  # on this chip it does nothing