code.py
  1  # SPDX-FileCopyrightText: 2019 Noe Ruiz for Adafruit Industries
  2  #
  3  # SPDX-License-Identifier: MIT
  4  
  5  import digitalio
  6  import busio
  7  import board
  8  from adafruit_epd.epd import Adafruit_EPD
  9  from adafruit_epd.il0373 import Adafruit_IL0373
 10  
 11  # create the spi device and pins we will need
 12  spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO)
 13  ecs = digitalio.DigitalInOut(board.D9)
 14  dc = digitalio.DigitalInOut(board.D10)
 15  srcs = None
 16  rst = None
 17  busy = None
 18  
 19  # give them all to our driver
 20  print("Creating display")
 21  display = Adafruit_IL0373(104, 212, spi,         # 2.13" Tri-color display
 22                            cs_pin=ecs, dc_pin=dc, sramcs_pin=srcs,
 23                            rst_pin=rst, busy_pin=busy)
 24  
 25  display.rotation = 3
 26  
 27  FILENAME = "blinka.bmp"
 28  
 29  def read_le(s):
 30      # as of this writting, int.from_bytes does not have LE support, DIY!
 31      result = 0
 32      shift = 0
 33      for byte in bytearray(s):
 34          result += byte << shift
 35          shift += 8
 36      return result
 37  
 38  class BMPError(Exception):
 39      pass
 40  
 41  def display_bitmap(epd, filename):
 42      # pylint: disable=too-many-locals, too-many-branches
 43      try:
 44          f = open("/" + filename, "rb")
 45      except OSError:
 46          print("Couldn't open file")
 47          return
 48  
 49      print("File opened")
 50      try:
 51          if f.read(2) != b'BM':  # check signature
 52              raise BMPError("Not BitMap file")
 53  
 54          bmpFileSize = read_le(f.read(4))
 55          f.read(4)  # Read & ignore creator bytes
 56  
 57          bmpImageoffset = read_le(f.read(4))  # Start of image data
 58          headerSize = read_le(f.read(4))
 59          bmpWidth = read_le(f.read(4))
 60          bmpHeight = read_le(f.read(4))
 61          flip = True
 62  
 63          print("Size: %d\nImage offset: %d\nHeader size: %d" %
 64                (bmpFileSize, bmpImageoffset, headerSize))
 65          print("Width: %d\nHeight: %d" % (bmpWidth, bmpHeight))
 66  
 67          if read_le(f.read(2)) != 1:
 68              raise BMPError("Not singleplane")
 69          bmpDepth = read_le(f.read(2))  # bits per pixel
 70          print("Bit depth: %d" % (bmpDepth))
 71          if bmpDepth != 24:
 72              raise BMPError("Not 24-bit")
 73          if read_le(f.read(2)) != 0:
 74              raise BMPError("Compressed file")
 75  
 76          print("Image OK! Drawing...")
 77  
 78          rowSize = (bmpWidth * 3 + 3) & ~3  # 32-bit line boundary
 79  
 80          for row in range(bmpHeight):  # For each scanline...
 81              if flip:  # Bitmap is stored bottom-to-top order (normal BMP)
 82                  pos = bmpImageoffset + (bmpHeight - 1 - row) * rowSize
 83              else:  # Bitmap is stored top-to-bottom
 84                  pos = bmpImageoffset + row * rowSize
 85  
 86              # print ("seek to %d" % pos)
 87              f.seek(pos)
 88              rowdata = f.read(3*bmpWidth)
 89              for col in range(bmpWidth):
 90                  b, g, r = rowdata[3*col:3*col+3]  # BMP files store RGB in BGR
 91                  if r < 0x80 and g < 0x80 and b < 0x80:
 92                      epd.pixel(col, row, Adafruit_EPD.BLACK)
 93                  elif r >= 0x80 and g >= 0x80 and b >= 0x80:
 94                      pass  # epd.pixel(row, col, Adafruit_EPD.WHITE)
 95                  elif r >= 0x80:
 96                      epd.pixel(col, row, Adafruit_EPD.RED)
 97      except OSError:
 98          print("Couldn't read file")
 99      except BMPError as e:
100          print("Failed to parse BMP: " + e.args[0])
101      finally:
102          f.close()
103      print("Finished drawing")
104  
105  # clear the buffer
106  display.fill(Adafruit_EPD.WHITE)
107  display_bitmap(display, FILENAME)
108  display.display()