Skip to content

Instantly share code, notes, and snippets.

@georgelviv
Last active July 17, 2025 12:32
Show Gist options
  • Select an option

  • Save georgelviv/ce324a3385e3fc211bceaf51b53bfa34 to your computer and use it in GitHub Desktop.

Select an option

Save georgelviv/ce324a3385e3fc211bceaf51b53bfa34 to your computer and use it in GitHub Desktop.
Python lib for ST7735 display 128x160 driven by SPI for RPI5
# Based on https://github.com/pimoroni/st7735-python/blob/main/st7735/__init__.py
import numbers
import time
from gpiozero import OutputDevice
import numpy as np
import spidev
ST7735_NOP = 0x00
ST7735_SWRESET = 0x01
ST7735_RDDID = 0x04
ST7735_RDDST = 0x09
ST7735_SLPIN = 0x10
ST7735_SLPOUT = 0x11
ST7735_PTLON = 0x12
ST7735_NORON = 0x13
ST7735_INVOFF = 0x20
ST7735_INVON = 0x21
ST7735_DISPOFF = 0x28
ST7735_DISPON = 0x29
ST7735_CASET = 0x2A
ST7735_RASET = 0x2B
ST7735_RAMWR = 0x2C
ST7735_RAMRD = 0x2E
ST7735_PTLAR = 0x30
ST7735_MADCTL = 0x36
ST7735_COLMOD = 0x3A
ST7735_FRMCTR1 = 0xB1
ST7735_FRMCTR2 = 0xB2
ST7735_FRMCTR3 = 0xB3
ST7735_INVCTR = 0xB4
ST7735_DISSET5 = 0xB6
ST7735_PWCTR1 = 0xC0
ST7735_PWCTR2 = 0xC1
ST7735_PWCTR3 = 0xC2
ST7735_PWCTR4 = 0xC3
ST7735_PWCTR5 = 0xC4
ST7735_VMCTR1 = 0xC5
ST7735_RDID1 = 0xDA
ST7735_RDID2 = 0xDB
ST7735_RDID3 = 0xDC
ST7735_RDID4 = 0xDD
ST7735_GMCTRP1 = 0xE0
ST7735_GMCTRN1 = 0xE1
ST7735_PWCTR6 = 0xFC
# Colours for convenience
ST7735_BLACK = 0x0000 # 0b 00000 000000 00000
ST7735_BLUE = 0x001F # 0b 00000 000000 11111
ST7735_GREEN = 0x07E0 # 0b 00000 111111 00000
ST7735_RED = 0xF800 # 0b 11111 000000 00000
ST7735_CYAN = 0x07FF # 0b 00000 111111 11111
ST7735_MAGENTA = 0xF81F # 0b 11111 000000 11111
ST7735_YELLOW = 0xFFE0 # 0b 11111 111111 00000
ST7735_WHITE = 0xFFFF # 0b 11111 111111 11111
class ST7735(object):
CS = 0
PORT = 0
DC_PIN = 23
RST_PIN = 24
WIDTH = 128
HEIGHT = 160
def __init__(self, rotation=0, spi_speed_hz=4000000):
self._spi = spidev.SpiDev(self.PORT, self.CS)
self._spi.mode = 0
self._spi.lsbfirst = False
self._spi.max_speed_hz = spi_speed_hz
self._rotation = rotation
self._bl = None
self._rst = None
# Set DC as output.
self._dc = OutputDevice(self.DC_PIN)
self._rst = OutputDevice(self.RST_PIN)
self.reset()
self._init()
def send(self, data, is_data=True):
if is_data:
self._dc.on()
else:
self._dc.off()
if isinstance(data, numbers.Number):
data = [data & 0xFF]
self._spi.xfer3(data)
def display_off(self):
self.command(ST7735_DISPOFF)
def display_on(self):
self.command(ST7735_DISPON)
def sleep(self):
self.command(ST7735_SLPIN)
def wake(self):
self.command(ST7735_SLPOUT)
def command(self, data):
"""Write a byte or array of bytes to the display as command data."""
self.send(data, False)
def data(self, data):
"""Write a byte or array of bytes to the display as display data."""
self.send(data, True)
def reset(self):
"""Reset the display, if reset pin is connected."""
self._rst.on()
time.sleep(0.500)
self._rst.off()
time.sleep(0.500)
self._rst.on()
time.sleep(0.500)
def _init(self):
# Initialize the display.
self.command(ST7735_SWRESET) # Software reset
time.sleep(0.150) # delay 150 ms
self.command(ST7735_SLPOUT) # Out of sleep mode
time.sleep(0.500) # delay 500 ms
self.command(ST7735_FRMCTR1) # Frame rate ctrl - normal mode
self.data(0x01) # Rate = fosc/(1x2+40) * (LINE+2C+2D)
self.data(0x2C)
self.data(0x2D)
self.command(ST7735_FRMCTR2) # Frame rate ctrl - idle mode
self.data(0x01) # Rate = fosc/(1x2+40) * (LINE+2C+2D)
self.data(0x2C)
self.data(0x2D)
self.command(ST7735_FRMCTR3) # Frame rate ctrl - partial mode
self.data(0x01) # Dot inversion mode
self.data(0x2C)
self.data(0x2D)
self.data(0x01) # Line inversion mode
self.data(0x2C)
self.data(0x2D)
self.command(ST7735_INVCTR) # Display inversion ctrl
self.data(0x07) # No inversion
self.command(ST7735_PWCTR1) # Power control
self.data(0xA2)
self.data(0x02) # -4.6V
self.data(0x84) # auto mode
self.command(ST7735_PWCTR2) # Power control
self.data(0x0A) # Opamp current small
self.data(0x00) # Boost frequency
self.command(ST7735_PWCTR4) # Power control
# BCLK/2, Opamp current small & Medium low
self.data(0x8A)
self.data(0x2A)
self.command(ST7735_PWCTR5) # Power control
self.data(0x8A)
self.data(0xEE)
self.command(ST7735_VMCTR1) # Power control
self.data(0x0E)
self.command(ST7735_INVOFF) # Don't invert display
self.command(ST7735_MADCTL) # Memory access control (directions)
self.data(0xC0)
self.command(ST7735_COLMOD) # set color mode
self.data(0x05) # 16-bit color
self.command(ST7735_CASET) # Column addr set
self.data(0x00) # XSTART = 0
self.data(0x00)
self.data(0x00) # XEND = ROWS - height
self.data(self.WIDTH - 1)
self.command(ST7735_RASET) # Row addr set
self.data(0x00) # XSTART = 0
self.data(0x00)
self.data(0x00) # XEND = COLS - width
self.data(self.HEIGHT - 1)
self.command(ST7735_GMCTRP1) # Set Gamma
self.data(0x02)
self.data(0x1c)
self.data(0x07)
self.data(0x12)
self.data(0x37)
self.data(0x32)
self.data(0x29)
self.data(0x2d)
self.data(0x29)
self.data(0x25)
self.data(0x2B)
self.data(0x39)
self.data(0x00)
self.data(0x01)
self.data(0x03)
self.data(0x10)
self.command(ST7735_GMCTRN1) # Set Gamma
self.data(0x03)
self.data(0x1d)
self.data(0x07)
self.data(0x06)
self.data(0x2E)
self.data(0x2C)
self.data(0x29)
self.data(0x2D)
self.data(0x2E)
self.data(0x2E)
self.data(0x37)
self.data(0x3F)
self.data(0x00)
self.data(0x00)
self.data(0x02)
self.data(0x10)
self.command(ST7735_NORON) # Normal display on
time.sleep(0.10) # 10 ms
self.display_on()
time.sleep(0.100) # 100 ms
def set_window(self):
y0 = 0
x0 = 0
x1 = self.WIDTH - 1
y1 = self.HEIGHT - 1
self.command(ST7735_CASET) # Column addr set
self.data(x0 >> 8)
self.data(x0) # XSTART
self.data(x1 >> 8)
self.data(x1) # XEND
self.command(ST7735_RASET) # Row addr set
self.data(y0 >> 8)
self.data(y0) # YSTART
self.data(y1 >> 8)
self.data(y1) # YEND
self.command(ST7735_RAMWR) # write to RAM
def display(self, image):
self.set_window()
pixelbytes = list(self.image_to_data(image, self._rotation))
self.data(pixelbytes)
def image_to_data(self, image, rotation=0):
pb = np.rot90(np.array(image.convert('RGB')),
rotation // 90).astype('uint16')
color = ((pb[:, :, 0] & 0xF8) << 8) | (
(pb[:, :, 1] & 0xFC) << 3) | (pb[:, :, 2] >> 3)
return np.dstack(((color >> 8) & 0xFF, color & 0xFF)).flatten().tolist()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment