Skip to content

Instantly share code, notes, and snippets.

@ntavish
Created April 15, 2019 21:56
Show Gist options
  • Save ntavish/6f96b3c97068556687a89d84803e0de9 to your computer and use it in GitHub Desktop.
Save ntavish/6f96b3c97068556687a89d84803e0de9 to your computer and use it in GitHub Desktop.
import board
import digitalio
import time
import busio
from adafruit_bus_device.spi_device import SPIDevice
EPD_WIDTH = 200
EPD_HEIGHT = 200
PANEL_SETTING = 0x00
POWER_SETTING = 0x01
POWER_OFF = 0x02
POWER_OFF_SEQUENCE_SETTING = 0x03
POWER_ON = 0x04
POWER_ON_MEASURE = 0x05
BOOSTER_SOFT_START = 0x06
DEEP_SLEEP = 0x07
DATA_START_TRANSMISSION_1 = 0x10
DATA_STOP = 0x11
DISPLAY_REFRESH = 0x12
DATA_START_TRANSMISSION_2 = 0x13
PLL_CONTROL = 0x30
TEMPERATURE_SENSOR_COMMAND = 0x40
TEMPERATURE_SENSOR_CALIBRATION = 0x41
TEMPERATURE_SENSOR_WRITE = 0x42
TEMPERATURE_SENSOR_READ = 0x43
VCOM_AND_DATA_INTERVAL_SETTING = 0x50
LOW_POWER_DETECTION = 0x51
TCON_SETTING = 0x60
TCON_RESOLUTION = 0x61
SOURCE_AND_GATE_START_SETTING = 0x62
GET_STATUS = 0x71
AUTO_MEASURE_VCOM = 0x80
VCOM_VALUE = 0x81
VCM_DC_SETTING_REGISTER = 0x82
PROGRAM_MODE = 0xA0
ACTIVE_PROGRAM = 0xA1
READ_OTP_DATA = 0xA2
lut_vcom0 = bytearray([
0x0E, 0x14, 0x01, 0x0A, 0x06, 0x04, 0x0A, 0x0A,
0x0F, 0x03, 0x03, 0x0C, 0x06, 0x0A, 0x00
])
lut_w = bytearray([
0x0E, 0x14, 0x01, 0x0A, 0x46, 0x04, 0x8A, 0x4A,
0x0F, 0x83, 0x43, 0x0C, 0x86, 0x0A, 0x04
])
lut_b = bytearray([
0x0E, 0x14, 0x01, 0x8A, 0x06, 0x04, 0x8A, 0x4A,
0x0F, 0x83, 0x43, 0x0C, 0x06, 0x4A, 0x04
])
lut_g1 = bytearray([
0x8E, 0x94, 0x01, 0x8A, 0x06, 0x04, 0x8A, 0x4A,
0x0F, 0x83, 0x43, 0x0C, 0x06, 0x0A, 0x04
])
lut_g2 = bytearray([
0x8E, 0x94, 0x01, 0x8A, 0x06, 0x04, 0x8A, 0x4A,
0x0F, 0x83, 0x43, 0x0C, 0x06, 0x0A, 0x04
])
lut_vcom1 = bytearray([
0x03, 0x1D, 0x01, 0x01, 0x08, 0x23, 0x37, 0x37,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
])
lut_red0 = bytearray([
0x83, 0x5D, 0x01, 0x81, 0x48, 0x23, 0x77, 0x77,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
])
lut_red1 = bytearray([
0x03, 0x1D, 0x01, 0x01, 0x08, 0x23, 0x37, 0x37,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
])
led = digitalio.DigitalInOut(board.L)
led.direction = digitalio.Direction.OUTPUT
busy = digitalio.DigitalInOut(board.BUSY)
res = digitalio.DigitalInOut(board.RES)
dc = digitalio.DigitalInOut(board.DC)
eink_en = digitalio.DigitalInOut(board.EINK_EN)
cs = digitalio.DigitalInOut(board.CS)
comm_port = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO)
device = SPIDevice(comm_port, cs)
# for framebuffer
frame_black = bytearray(round(EPD_WIDTH * EPD_HEIGHT / 8))
frame_red = bytearray(round(EPD_WIDTH * EPD_HEIGHT / 8))
def epd_send_cmd(cmd):
dc.value = 0
with device as bus_device:
bus_device.write(bytes([cmd]))
def epd_send_data(data):
dc.value = 1
with device as bus_device:
bus_device.write(bytes([data]))
def epd_wait_until_idle():
while True:
if busy.value != 0:
break
time.sleep(0.1)
led.value = ~led.value
def epd_set_lut_bw():
epd_send_cmd(0x20) #g vcom
for count in range(15):
epd_send_data(lut_vcom0[count])
epd_send_cmd(0x21) #g ww --
for count in range(15):
epd_send_data(lut_w[count])
epd_send_cmd(0x22) #g bw r
for count in range(15):
epd_send_data(lut_b[count])
epd_send_cmd(0x23) #g wb w
for count in range(15):
epd_send_data(lut_g1[count])
epd_send_cmd(0x24) #g bb b
for count in range(15):
epd_send_data(lut_g2[count])
def epd_set_lut_red():
epd_send_cmd(0x25)
for count in range(15):
epd_send_data(lut_vcom1[count])
epd_send_cmd(0x26)
for count in range(15):
epd_send_data(lut_red0[count])
epd_send_cmd(0x27)
for count in range(15):
epd_send_data(lut_red1[count])
def epd_reset():
res.value = 0
time.sleep(0.2)
res.value = 1
time.sleep(0.2)
def epd_display_frame():
epd_send_cmd(DATA_START_TRANSMISSION_1)
time.sleep(0.2)
for i in range(EPD_HEIGHT * EPD_WIDTH / 8):
temp = 0x00
for bit in range(4):
if ((frame_black[i] & (0x80 >> bit)) != 0):
temp |= 0xC0 >> (bit * 2)
epd_send_data(temp)
temp = 0x00
for bit in range(4, 8):
if ((frame_black[i] & (0x80 >> bit)) != 0):
temp |= 0xC0 >> ((bit - 4) * 2)
epd_send_data(temp)
time.sleep(0.2)
epd_send_cmd(DATA_START_TRANSMISSION_2)
time.sleep(0.2)
for i in range(EPD_HEIGHT * EPD_WIDTH / 8):
epd_send_data(frame_red[i])
time.sleep(0.2)
epd_send_cmd(DISPLAY_REFRESH)
epd_wait_until_idle()
def epd_init():
epd_reset()
epd_send_cmd(POWER_SETTING)
epd_send_data(0x07)
epd_send_data(0x00)
epd_send_data(0x08)
epd_send_data(0x00)
epd_send_cmd(BOOSTER_SOFT_START)
epd_send_data(0x07)
epd_send_data(0x07)
epd_send_data(0x07)
epd_send_cmd(POWER_ON)
epd_wait_until_idle()
epd_send_cmd(PANEL_SETTING)
epd_send_data(0xcf)
epd_send_cmd(VCOM_AND_DATA_INTERVAL_SETTING)
epd_send_data(0x17)
epd_send_cmd(PLL_CONTROL)
epd_send_data(0x39)
epd_send_cmd(TCON_RESOLUTION)
epd_send_data(0xC8)
epd_send_data(0x00)
epd_send_data(0xC8)
epd_send_cmd(VCM_DC_SETTING_REGISTER)
epd_send_data(0x30)
epd_set_lut_bw()
epd_set_lut_red()
time.sleep(0.2)
def paint_clear(fb, colored):
if colored:
val = 0x00
else:
val = 0xff
for i in range(len(fb)):
fb[i] = val
def epd_sleep():
epd_send_cmd(VCOM_AND_DATA_INTERVAL_SETTING)
epd_send_data(0x17)
epd_send_cmd(VCM_DC_SETTING_REGISTER) #to solve Vcom drop
epd_send_data(0x00)
epd_send_cmd(POWER_SETTING) #power setting
epd_send_data(0x02) #gate switch to external
epd_send_data(0x00)
epd_send_data(0x00)
epd_send_data(0x00)
epd_wait_until_idle()
epd_send_cmd(POWER_OFF)
def epaper_pins_off():
busy.direction = digitalio.Direction.OUTPUT
res.direction = digitalio.Direction.OUTPUT
dc.direction = digitalio.Direction.OUTPUT
cs.direction = digitalio.Direction.OUTPUT
eink_en.direction = digitalio.Direction.OUTPUT
res.value = 0
dc.value = 0
cs.value = 0
eink_en.value = 1
def epaper_pins_init():
busy.direction = digitalio.Direction.INPUT
res.direction = digitalio.Direction.OUTPUT
res.value = 0
dc.direction = digitalio.Direction.OUTPUT
dc.value = 0
cs.direction = digitalio.Direction.OUTPUT
cs.value = 0
time.sleep(0.1)
eink_en.direction = digitalio.Direction.OUTPUT
eink_en.value = 1
def epaper_on():
time.sleep(0.5)
eink_en.value = 0
time.sleep(0.5)
def epaper_off():
time.sleep(0.5)
eink_en.value = 1
def paint_draw_pixel(fb, x, y, colored):
if (x < 0 or x >= EPD_WIDTH or y < 0 or y >= EPD_HEIGHT):
return
if (colored):
fb[int((x + y * EPD_WIDTH) / 8)] &= ~(0x80 >> (x % 8))
else:
fb[int((x + y * EPD_WIDTH) / 8)] |= 0x80 >> (x % 8)
def paint_circle(fb, x, y, radius, colored):
# Bresenham algorithm
x_pos = -radius
y_pos = 0
err = 2 - 2 * radius
e2 = 0
while True:
paint_draw_pixel(fb, x - x_pos, y + y_pos, colored)
paint_draw_pixel(fb, x + x_pos, y + y_pos, colored)
paint_draw_pixel(fb, x + x_pos, y - y_pos, colored)
paint_draw_pixel(fb, x - x_pos, y - y_pos, colored)
e2 = err
if (e2 <= y_pos):
y_pos = y_pos + 1
err = err + y_pos * 2 + 1
if(-x_pos == y_pos and e2 <= x_pos):
e2 = 0
if (e2 > x_pos):
x_pos = x_pos + 1
err = err + x_pos * 2 + 1
if x_pos > 0:
break
epaper_pins_init()
epaper_on()
epd_init()
paint_clear(frame_black, False)
paint_clear(frame_red, False)
for i in range(0, 100, 8):
paint_circle(frame_black, 100, 100, i, True)
paint_circle(frame_red, 100, 100, i+4, True)
epd_display_frame()
epd_sleep()
while True:
led.value = True
time.sleep(0.5)
led.value = False
time.sleep(0.01)
print("Hello, world!")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment