It's easy to use the Sharp Memory Display with CircuitPython and the Adafruit CircuitPython SharpMemoryDisplay module. This module allows you to easily write Python code to control the display.

You can use this display with a computer that has GPIO and Python thanks to Adafruit_Blinka, our CircuitPython-for-Python compatibility library.

To demonstrate the usage, we'll initialize the library and use Python code to control the display from the board's Python REPL.

Since we are running full CPython on our Linux/computer, we can take advantage of the powerful Pillow image drawing library to handle text, shapes, graphics, etc. Pillow is a gold standard in image and graphics handling, you can read about all it can do here.

Initialization

First need to initialize the SPI bus. To do that, run the following commands:

Download: file
import board
import busio
import digitalio
import adafruit_sharpmemorydisplay

spi = busio.SPI(board.SCK, MOSI=board.MOSI)
scs = digitalio.DigitalInOut(board.D6) # inverted chip select

display = adafruit_sharpmemorydisplay.SharpMemoryDisplay(spi, scs, 144, 168)

The last three parameters to the initializer are the pins connected to the display's CS line, width and height in that order.  Again make sure to use the right pin names as you have wired up to your board!

Example Code

"""
This demo will fill the screen with white, draw a black box on top
and then print Hello World! in the center of the display

This example is for use on (Linux) computers that are using CPython with
Adafruit Blinka to support CircuitPython libraries. CircuitPython does
not support PIL/pillow (python imaging library)!
"""

import board
import busio
import digitalio
from PIL import Image, ImageDraw, ImageFont
import adafruit_sharpmemorydisplay

# Colors
BLACK = 0
WHITE = 255

# Parameters to Change
BORDER = 5
FONTSIZE = 10

spi = busio.SPI(board.SCK, MOSI=board.MOSI)
scs = digitalio.DigitalInOut(board.D6) # inverted chip select

#display = adafruit_sharpmemorydisplay.SharpMemoryDisplay(spi, scs, 96, 96)
display = adafruit_sharpmemorydisplay.SharpMemoryDisplay(spi, scs, 144, 168)

# Clear display.
display.fill(1)
display.show()

# Create blank image for drawing.
# Make sure to create image with mode '1' for 1-bit color.
image = Image.new('1', (display.width, display.height))

# Get drawing object to draw on image.
draw = ImageDraw.Draw(image)

# Draw a black background
draw.rectangle((0, 0, display.width, display.height), outline=BLACK, fill=BLACK)

# Draw a smaller inner rectangle
draw.rectangle((BORDER, BORDER, display.width - BORDER - 1, display.height - BORDER - 1),
               outline=WHITE, fill=WHITE)

# Load a TTF font.
font = ImageFont.truetype('/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf', FONTSIZE)

# Draw Some Text
text = "Hello World!"
(font_width, font_height) = font.getsize(text)
draw.text((display.width//2 - font_width//2, display.height//2 - font_height//2),
          text, font=font, fill=BLACK)

# Display image
display.image(image)
display.show()

Let's take a look at the sections of code one by one. We start by importing the board so that we can access the pin definitions, busio so we can initialize SPI, digitalio, several PIL modules for Image Drawing, and the adafruit_sharpmemorydisplay driver.

Download: file
import board
import busio
import digitalio
from PIL import Image, ImageDraw, ImageFont
import adafruit_sharpmemorydisplay

To make it easy to keep track of which numbers represent which colors, we define some colors near the top.

Download: file
# Colors
BLACK = 0
WHITE = 255

In order to make it easy to change display sizes, we'll define a few variables in one spot here. We have the border size and font size, which we will explain a little further below.

Download: file
BORDER = 5
FONTSIZE = 10

Next we set the SPI object to the board's SPI with busio.SPI(). We also define some Pins that will be used for the display and initialize the display. See the initialization section above for more details. By default, the initializer for the 144x168 display is uncommented because that's what we currently have in the store. If you had the 96x96 pixel version of the screen, you could use the other initializer instead.

Download: file
spi = busio.SPI(board.SCK, MOSI=board.MOSI)
dc = digitalio.DigitalInOut(board.D6) # data/command
cs = digitalio.DigitalInOut(board.CE0) # Chip select
reset = digitalio.DigitalInOut(board.D5) # reset

#display = adafruit_sharpmemorydisplay.SharpMemoryDisplay(spi, scs, 96, 96)
display = adafruit_sharpmemorydisplay.SharpMemoryDisplay(spi, scs, 144, 168)

Next we clear the display in case it was initialized with any random artifact data.

Download: file
# Clear display.
display.fill(0)
display.show()

Next, we need to initialize PIL to create a blank image to draw on. Think of it as a virtual canvas. Since this is a monochrome display, we set it up for 1-bit color, meaning a pixel is either white or black. We can make use of the display's width and height properties as well.

Download: file
# Create blank image for drawing.
# Make sure to create image with mode '1' for 1-bit color.
image = Image.new('1', (display.width, display.height))

# Get drawing object to draw on image.
draw = ImageDraw.Draw(image)

Now we start the actual drawing. Here we are telling it we want to draw a rectangle from (0,0), which is the upper left, to the full width and height of the display. We want it both filled in and having an outline of black, so we pass BLACK for both values.

Download: file
# Draw a black background
draw.rectangle((0, 0, display.width, display.height), outline=BLACK, fill=BLACK)

If we ran the code now, it would still show a blank display because we haven't told python to use our virtual canvas yet. You can skip to the end if you would like to see how to do that. This is what our canvas currently looks like in memory.

Next we will create a smaller white rectangle. The easiest way to do this is to draw another rectangle a little smaller than the full screen with no fill or outline and place it in a specific location. In this case, we will create a rectangle that is 5 pixels smaller on each side. This is where the BORDER variable comes into use. It makes calculating the size of the second rectangle much easier. We want the starting coordinate, which consists of the first two parameters, to be our BORDER value. Then for the next two parameters, which are our ending coordinates, we want to subtract our border value from the width and height. Also, because this is a zero-based coordinate system, we also need to subtract 1 from each number. Again, we set the fill and outline to WHITE.

Download: file
# Draw a smaller inner rectangle
draw.rectangle((BORDER, BORDER, display.width - BORDER - 1, display.height - BORDER - 1),
               outline=WHITE, fill=WHITE)

Here's what our virtual canvas looks like in memory.

Now drawing text with PIL is pretty straightforward. First we start by setting the font to the default system text. After that we define our text and get the size of the text. We're grabbing the size that it would render at so that we can calculate the center position. Finally, we take the font size and screen size to calculate the position we want to draw the text at and it appears in the center of the screen.

Download: file
# Load a TTF font.
font = ImageFont.truetype('/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf', FONTSIZE)

# Draw Some Text
text = "Hello World!"
(font_width, font_height) = font.getsize(text)
draw.text((display.width//2 - font_width//2, display.height//2 - font_height//2),
          text, font=font, fill=BLACK)

Finally, we need to display our virtual canvas to the display and we do that with 2 commands. First we set the image to the screen, then we tell it to show the image.

Download: file
# Display image
display.image(image)
display.show()
Don't forget you MUST call display.image(image) and display.show() to actually display the graphics. The display takes a while to draw so cluster all your drawing functions into the buffer (fast) and then display them once to the display (slow)

Here's what the final output should look like.

This guide was first published on Jun 22, 2013. It was last updated on Jun 22, 2013. This page (Python Usage) was last updated on Jan 17, 2020.