1
0
mirror of https://github.com/mbirth/wipy-ussd1306.git synced 2024-12-25 22:44:06 +00:00

Initial import

This commit is contained in:
Markus Birth 2016-02-10 15:23:03 +01:00
commit 10bb48b95a
4 changed files with 210 additions and 0 deletions

21
LICENSE.md Normal file
View File

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2016 Markus Birth <markus@birth-online.de>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

6
README.md Normal file
View File

@ -0,0 +1,6 @@
ussd1306
========
MicroPython module for the SSD1306 OLED.
[Datasheet](doc/SSD1306.pdf)

BIN
doc/SSD1306.pdf Normal file

Binary file not shown.

183
ussd1306-i2c.py Normal file
View File

@ -0,0 +1,183 @@
# -*- coding: utf-8 -*-
"""
MicroPython SSD1306 I2C driver
"""
__author__ = "Markus Birth"
__copyright__ = "Copyright 2016, Markus Birth"
__credits__ = ["Markus Birth"]
__license__ = "MIT"
__version__ = "1.0"
__maintainer__ = "Markus Birth"
__email__ = "markus@birth-online.de"
__status__ = "Production"
# Datasheet: https://www.adafruit.com/datasheets/SSD1306.pdf
# Inspiration from:
# - https://github.com/khenderick/micropython-drivers/tree/master/ssd1306
#
# PINOUT
# WiPy/pyBoard display function
#
# 3V3 or any Pin => VCC 3.3V logic voltage (0=off, 1=on)
# SDA => SDM data
# SCL => SCL clock
# GND => GND
#
# WiPy (on Exp board, SD and User-LED jumper have to be removed!)
# PWR = directly from 3V3 pin of the WiPy
try:
import pyb as machine
except:
# WiPy
import machine
import struct
import time
class SSD1306:
ADDRESSING_HORIZ = 0x00
ADDRESSING_VERT = 0x01
ADDRESSING_PAGE = 0x02
POWER_UP = 0xaf
POWER_DOWN = 0xae
DISPLAY_BLANK = 0xae
DISPLAY_ALL = 0xa5
DISPLAY_NORMAL = [0xaf, 0xa4, 0xa6]
DISPLAY_INVERSE = 0xa7
DC_CMD = 0x80
DC_DATA = 0x40
def __init__(self, i2c, pwr=None, devid=0x3c):
self.width = 128
self.height = 64
self.devid = devid
self.power = self.POWER_DOWN
self.addressing = self.ADDRESSING_HORIZ
self.display_mode = self.DISPLAY_NORMAL
# init the I2C bus and pins
i2c.init(i2c.MASTER, baudrate=400000) # 400 kHz
if pwr:
if "OUT_PP" in dir(pwr):
# pyBoard style
pwr.init(pwr.OUT_PP, pwr_PULL_NONE)
else:
# WiPy style
pwr.init(pwr.OUT, None)
self.i2c = i2c
self.pwr = pwr
self.power_on()
# set disp off : 0xae
# set clock div : 0xd5, 0x80
# set multiplex : 0xa8, 0x3f (for 32px: 0x1f)
# set disp offset: 0xd3 0x00
# set start line : 0x40|0x00
# chargepump on : 0x8d, 0x14 (ext. VCC: 0x10)
# memory mode : 0x20, 0x00
# segment remap : 0xa0|0x10 (invalid value: 0xb0, maybe 0x01?)
# com scan dir : 0xc8 (decreasing, inc.: 0xc0)
# com pins : 0xda, 0x12 (for 32px: 0x02)
# contrast : 0x81, 0xff
# precharge : 0xd9, 0xf1 (ext. VCC: 0x22 = RESET)
# Vcom deselect : 0xdb, 0x40
# disp resume ram: 0xa4
# disp not invers: 0xa6
# set disp on : 0xaf
self.clear()
def set_power(self, power, set=True):
""" Sets the power mode of the LCD controller """
assert power in [self.POWER_UP, self.POWER_DOWN], "Power must be POWER_UP or POWER_DOWN."
self.power = power
self.command(power)
def set_adressing(self, addr):
""" Sets the adressing mode """
assert addr in [self.ADDRESSING_HORIZ, self.ADDRESSING_VERT, self.ADDRESSING_PAGE], "Addressing must be ADDRESSING_HORIZ, ADDRESSING_VERT or ADDRESSING_PAGE."
self.addressing = addr
self.command([0x20, addr])
def set_display(self, display_mode):
""" Sets display mode (blank, black, normal, inverse) """
assert display_mode in [self.DISPLAY_BLANK, self.DISPLAY_ALL, self.DISPLAY_NORMAL, self.DISPLAY_INVERSE], "Mode must be one of DISPLAY_BLANK, DISPLAY_ALL, DISPLAY_NORMAL or DISPLAY_INVERSE."
self.display_mode = display_mode
self.command([display_mode])
def set_contrast(self, value):
""" set OLED contrast """
assert 0x00 <= value <= 0xff, "Contrast value must be between 0x00 and 0xff"
self.command([0x81, value])
def position(self, x, y):
""" set cursor to page y, column x """
assert 0 <= x < self.width, "x must be between 0 and 127"
assert 0 <= y < self.height // 8, "y must be between 0 and 7"
self.command([0x20, 0x00, x, 0x21, 0x00, y])
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
# Defaults after reset:
# 1. Display is OFF
# 2. 128 x 64 Display Mode
# 3. Normal segment and display data column address and row address mapping (SEG0 mapped to
# address 00h and COM0 mapped to address 00h)
# 4. Shift register data clear in serial interface
# 5. Display start line is set at display RAM address 0
# 6. Column address counter is set at 0
# 7. Normal scan direction of the COM outputs
# 8. Contrast control register is set at 7Fh
# 9. Normal display mode (Equivalent to A4h command)
self.power = self.POWER_DOWN
self.addressing = self.ADDRESSING_HORIZ
self.display_mode = self.DISPLAY_NORMAL
def power_off(self):
self.clear()
self.set_power(self.POWER_DOWN)
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, self.DC_CMD)
def data(self, arr):
""" send bytes in data mode """
self.bitmap(arr, self.DC_DATA)
def bitmap(self, arr, dc):
arr = [dc] + arr
buf = struct.pack('B'*len(arr), *arr)
self.i2c.send(buf, addr=self.devid, timeout=5000)