wipy-upcd8544/upcd8544.py
2015-11-14 23:29:59 +01:00

182 lines
5.5 KiB
Python

# -*- coding: utf-8 -*-
"""
MicroPython PCD8544 driver
(for Nokia 5110 displays)
"""
__author__ = "Markus Birth"
__copyright__ = "Copyright 2015, Markus Birth"
__credits__ = ["Markus Birth"]
__license__ = "MIT"
__version__ = "1.0"
__maintainer__ ="Markus Birth"
__email__ = "markus@birth-online.de"
__status__ = "Production"
# Datasheet: https://www.sparkfun.com/datasheets/LCD/Monochrome/Nokia5110.pdf
# Inspiration from:
# - https://github.com/inaugurator/upyd5110
# - https://github.com/rm-hull/pcd8544/blob/master/src/lcd.py
#
# PINOUT
# WiPy/pyBoard display function
#
# 3V3 or any Pin => VCC 3.3V logic voltage (0=off, 1=on)
# MOSI => DIN data flow (Master out, Slave in)
# SCK => CLK SPI clock
# any Pin => RST Reset pin (0=reset, 1=normal)
# any Pin => CE Chip Enable (0=listen for input, 1=ignore input)
# any Pin => DC Data/Command (0=commands, 1=data)
# any Pin => LIGHT Light (0=on, 1=off)
# GND => GND
#
# pyBoard "Y" side
# SPI = pyb.SPI(1)
# RST = pyb.Pin('Y4')
# CE = pyb.Pin('Y5')
# DC = pyb.Pin('Y3')
# LIGHT = pyb.Pin('Y2')
# PWR = pyb.Pin('Y1')
#
# pyBoard "X" side
# SPI = pyb.SPI(2)
# RST = pyb.Pin('X4')
# CE = pyb.Pin('X5')
# DC = pyb.Pin('X3')
# LIGHT = pyb.Pin('X2')
# PWR = pyb.Pin('X1')
#
# WiPy (on Exp board, SD and User-LED jumper have to be removed!)
# SPI = machine.SPI(0) # GP14 (CLK) + GP16 (MOSI->DIN), User-LED jumper removed!
# RST = machine.Pin('GP24')
# CE = machine.Pin('GP12')
# DC = machine.Pin('GP22')
# LIGHT = machine.Pin('GP23')
# PWR = directly from 3V3 pin of the WiPy
try:
import pyb as machine
except:
# WiPy
import machine
import struct
import time
class PCD8544:
def __init__(self, spi, rst, ce, dc, light, pwr=None):
self.width = 84
self.height = 48
# init the SPI bus and pins
spi.init(spi.MASTER, baudrate=328125, bits=8, polarity=0, phase=1, firstbit=spi.MSB)
if "OUT_PP" in dir(rst):
# pyBoard style
rst.init(rst.OUT_PP, rst.PULL_NONE) # Reset line
ce.init(ce.OUT_PP, ce.PULL_NONE) # Chip Enable
dc.init(dc.OUT_PP, dc.PULL_NONE) # Data(1) / Command(0) mode
light.init(light.OUT_PP, light.PULL_NONE)
if pwr:
pwr.init(pwr.OUT_PP, pwr.PULL_NONE)
else:
# WiPy style
rst.init(rst.OUT, None)
ce.init(ce.OUT, None)
dc.init(dc.OUT, None)
light.init(light.OUT, None)
if pwr:
pwr.init(pwr.OUT, None)
self.spi = spi
self.rst = rst
self.ce = ce
self.dc = dc
self.light = light
self.pwr = pwr
self.light_off()
self.power_on()
self.ce.value(1) # set chip to disable (don't listen to input)
self.reset()
self.set_contrast(0xba)
self.clear()
def set_contrast(self, value):
""" set LCD voltage, i.e. contrast """
assert 0x80 <= value <= 0xff, "contrast value must be between 0x80 and 0xff"
self.command([0x21, 0x06, 0x14, value, 0x20, 0x0c])
# 0x21 - enter extended instruction set (H=1)
# 0x06 - set temperature coefficient 2
# 0x14 - set BIAS system to n=3 (recomm. mux rate 1:40/1:34)
# value - (80-ff) - set Vop (80 = 3.00V, ff = 10.68V), 8b seems to work (0x3b/d70: 3.00+(70*0.06)=7.2V)
# 0x20 - back to basic instruction set
# 0x0c - normal display mode
def position(self, x, y):
""" goto to column x in seg y """
assert 0 <= x <= 83, "x must be between 0 and 83"
assert 0 <= y <= 5, "y must be between 0 and 5"
self.command([x + 0x80, y + 0x40])
def clear(self):
""" clear screen """
self.position(0, 0)
self.data([0] * (self.height * self.width // 8))
self.position(0, 0)
def sleep_ms(self, mseconds):
try:
time.sleep_ms(mseconds)
except AttributeError:
machine.delay(mseconds)
def sleep_us(self, useconds):
try:
time.sleep_us(useconds)
except AttributeError:
machine.udelay(useconds)
def power_on(self):
if self.pwr:
self.pwr.value(1)
self.reset()
def reset(self):
""" issue reset impulse to reset the display """
self.rst.value(0) # RST on
self.sleep_us(100) # reset impulse has to be >100 ns and <100 ms
self.rst.value(1) # RST off
def power_off(self):
self.clear()
self.command([0x20, 0x08])
# 0x20 - basic instruction set
# 0x08 - set display to blank (doesn't delete contents)
self.sleep_ms(10)
if self.pwr:
self.pwr.value(0) # turn off power
def command(self, arr):
""" send bytes in command mode """
self.bitmap(arr, 0)
def data(self, arr):
""" send bytes in data mode """
self.bitmap(arr, 1)
def bitmap(self, arr, dc):
self.dc.value(dc)
buf = struct.pack('B'*len(arr), *arr)
self.ce.value(0) # set chip to listening/enable
try:
self.spi.send(buf)
except AttributeError:
self.spi.write(buf)
self.ce.value(1) # set chip to disable
def light_on(self):
self.light.value(0) # pull to GND
def light_off(self):
self.light.value(1) # set to HIGH