/ adafruit_epd / il0398.py
il0398.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.il0398` - Adafruit IL0398 - ePaper display driver
 24  ====================================================================================
 25  CircuitPython driver for Adafruit IL0398 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  _IL0398_PANEL_SETTING = const(0x00)
 38  _IL0398_POWER_SETTING = const(0x01)
 39  _IL0398_POWER_OFF = const(0x02)
 40  _IL0398_POWER_OFF_SEQUENCE = const(0x03)
 41  _IL0398_POWER_ON = const(0x04)
 42  _IL0398_POWER_ON_MEASURE = const(0x05)
 43  _IL0398_BOOSTER_SOFT_START = const(0x06)
 44  _IL0398_DEEP_SLEEP = const(0x07)
 45  _IL0398_DTM1 = const(0x10)
 46  _IL0398_DATA_STOP = const(0x11)
 47  _IL0398_DISPLAY_REFRESH = const(0x12)
 48  _IL0398_DTM2 = const(0x13)
 49  _IL0398_PDTM1 = const(0x14)
 50  _IL0398_PDTM2 = const(0x15)
 51  _IL0398_PDRF = const(0x16)
 52  _IL0398_LUT1 = const(0x20)
 53  _IL0398_LUTWW = const(0x21)
 54  _IL0398_LUTBW = const(0x22)
 55  _IL0398_LUTWB = const(0x23)
 56  _IL0398_LUTBB = const(0x24)
 57  _IL0398_PLL = const(0x30)
 58  _IL0398_CDI = const(0x50)
 59  _IL0398_RESOLUTION = const(0x61)
 60  _IL0398_GETSTATUS = const(0x71)
 61  _IL0398_VCM_DC_SETTING = const(0x82)
 62  
 63  
 64  class Adafruit_IL0398(Adafruit_EPD):
 65      """driver class for Adafruit IL0373 ePaper display breakouts"""
 66  
 67      # pylint: disable=too-many-arguments
 68      def __init__(
 69          self, width, height, spi, *, cs_pin, dc_pin, sramcs_pin, rst_pin, busy_pin
 70      ):
 71          super(Adafruit_IL0398, self).__init__(
 72              width, height, spi, cs_pin, dc_pin, sramcs_pin, rst_pin, busy_pin
 73          )
 74  
 75          self._buffer1_size = int(width * height / 8)
 76          self._buffer2_size = int(width * height / 8)
 77  
 78          if sramcs_pin:
 79              self._buffer1 = self.sram.get_view(0)
 80              self._buffer2 = self.sram.get_view(self._buffer1_size)
 81          else:
 82              self._buffer1 = bytearray((width * height) // 8)
 83              self._buffer2 = bytearray((width * height) // 8)
 84          # since we have *two* framebuffers - one for red and one for black
 85          # we dont subclass but manage manually
 86          self._framebuf1 = adafruit_framebuf.FrameBuffer(
 87              self._buffer1, width, height, buf_format=adafruit_framebuf.MHMSB
 88          )
 89          self._framebuf2 = adafruit_framebuf.FrameBuffer(
 90              self._buffer2, width, height, buf_format=adafruit_framebuf.MHMSB
 91          )
 92          self.set_black_buffer(0, True)
 93          self.set_color_buffer(1, True)
 94          # pylint: enable=too-many-arguments
 95  
 96      def begin(self, reset=True):
 97          """Begin communication with the display and set basic settings"""
 98          if reset:
 99              self.hardware_reset()
100          self.power_down()
101  
102      def busy_wait(self):
103          """Wait for display to be done with current task, either by polling the
104          busy pin, or pausing"""
105          if self._busy:
106              while not self._busy.value:
107                  # self.command(_IL0398_GETSTATUS)
108                  time.sleep(0.01)
109          else:
110              time.sleep(0.5)
111  
112      def power_up(self):
113          """Power up the display in preparation for writing RAM and updating"""
114          self.hardware_reset()
115          self.busy_wait()
116  
117          self.command(_IL0398_BOOSTER_SOFT_START, bytearray([0x17, 0x17, 0x17]))
118          self.command(_IL0398_POWER_ON)
119  
120          self.busy_wait()
121          time.sleep(0.2)
122  
123          self.command(_IL0398_PANEL_SETTING, bytearray([0x0F]))
124          _b0 = (self._width >> 8) & 0xFF
125          _b1 = self._width & 0xFF
126          _b2 = (self._height >> 8) & 0xFF
127          _b3 = self._height & 0xFF
128          self.command(_IL0398_RESOLUTION, bytearray([_b0, _b1, _b2, _b3]))
129          time.sleep(0.05)
130  
131      def power_down(self):
132          """Power down the display - required when not actively displaying!"""
133          self.command(_IL0398_CDI, bytearray([0xF7]))
134          self.command(_IL0398_POWER_OFF)
135          self.busy_wait()
136          self.command(_IL0398_DEEP_SLEEP, bytearray([0xA5]))
137  
138      def update(self):
139          """Update the display from internal memory"""
140          self.command(_IL0398_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(_IL0398_DTM1, end=False)
152          if index == 1:
153              return self.command(_IL0398_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