PiClock project

This commit is contained in:
2024-01-03 09:59:59 +01:00
parent edc186dbd4
commit ca21954980
9 changed files with 1737 additions and 0 deletions

119
ht16k33/ht16k33.py Normal file
View File

@@ -0,0 +1,119 @@
class HT16K33:
"""
A simple, generic driver for the I2C-connected Holtek HT16K33 controller chip.
This release supports MicroPython and CircuitPython
Bus: I2C
Author: Tony Smith (@smittytone)
License: MIT
Copyright: 2023
"""
# *********** CONSTANTS **********
HT16K33_GENERIC_DISPLAY_ON = 0x81
HT16K33_GENERIC_DISPLAY_OFF = 0x80
HT16K33_GENERIC_SYSTEM_ON = 0x21
HT16K33_GENERIC_SYSTEM_OFF = 0x20
HT16K33_GENERIC_DISPLAY_ADDRESS = 0x00
HT16K33_GENERIC_CMD_BRIGHTNESS = 0xE0
HT16K33_GENERIC_CMD_BLINK = 0x81
# *********** PRIVATE PROPERTIES **********
i2c = None
address = 0
brightness = 15
flash_rate = 0
# *********** CONSTRUCTOR **********
def __init__(self, i2c, i2c_address):
assert 0x00 <= i2c_address < 0x80, "ERROR - Invalid I2C address in HT16K33()"
self.i2c = i2c
self.address = i2c_address
self.power_on()
# *********** PUBLIC METHODS **********
def set_blink_rate(self, rate=0):
"""
Set the display's flash rate.
Only four values (in Hz) are permitted: 0, 2, 1, and 0,5.
Args:
rate (int): The chosen flash rate. Default: 0Hz (no flash).
"""
assert rate in (0, 0.5, 1, 2), "ERROR - Invalid blink rate set in set_blink_rate()"
self.blink_rate = rate & 0x03
self._write_cmd(self.HT16K33_GENERIC_CMD_BLINK | rate << 1)
def set_brightness(self, brightness=15):
"""
Set the display's brightness (ie. duty cycle).
Brightness values range from 0 (dim, but not off) to 15 (max. brightness).
Args:
brightness (int): The chosen flash rate. Default: 15 (100%).
"""
if brightness < 0 or brightness > 15: brightness = 15
self.brightness = brightness
self._write_cmd(self.HT16K33_GENERIC_CMD_BRIGHTNESS | brightness)
def draw(self):
"""
Writes the current display buffer to the display itself.
Call this method after updating the buffer to update
the LED itself.
"""
self._render()
def update(self):
"""
Alternative for draw() for backwards compatibility
"""
self._render()
def clear(self):
"""
Clear the buffer.
Returns:
The instance (self)
"""
for i in range(0, len(self.buffer)): self.buffer[i] = 0x00
return self
def power_on(self):
"""
Power on the controller and display.
"""
self._write_cmd(self.HT16K33_GENERIC_SYSTEM_ON)
self._write_cmd(self.HT16K33_GENERIC_DISPLAY_ON)
def power_off(self):
"""
Power on the controller and display.
"""
self._write_cmd(self.HT16K33_GENERIC_DISPLAY_OFF)
self._write_cmd(self.HT16K33_GENERIC_SYSTEM_OFF)
# ********** PRIVATE METHODS **********
def _render(self):
"""
Write the display buffer out to I2C
"""
buffer = bytearray(len(self.buffer) + 1)
buffer[1:] = self.buffer
buffer[0] = 0x00
self.i2c.writeto(self.address, bytes(buffer))
def _write_cmd(self, byte):
"""
Writes a single command to the HT16K33. A private method.
"""
self.i2c.writeto(self.address, bytes([byte]))

View File

@@ -0,0 +1,162 @@
# Import the base class
from ht16k33.ht16k33 import HT16K33
class HT16K33SegmentBig(HT16K33):
"""
Micro/Circuit Python class for the Adafruit 1.2-in 4-digit,
7-segment LED matrix backpack and equivalent Featherwing.
Bus: I2C
Author: Tony Smith (@smittytone)
License: MIT
Copyright: 2023
"""
# *********** CONSTANTS **********
HT16K33_SEGMENT_COLON_ROW = 0x04
HT16K33_SEGMENT_MINUS_CHAR = 0x10
HT16K33_SEGMENT_DEGREE_CHAR = 0x11
HT16K33_SEGMENT_SPACE_CHAR = 0x13
COLON_CENTRE = 0x02
COLON_LEFT_UPPER = 0x04
COLON_LEFT_LOWER = 0x08
COLON_LEFT = 0x0C
DECIMAL_POINT = 0x10
# The positions of the segments within the buffer
POS = (0, 2, 6, 8)
# Bytearray of the key alphanumeric characters we can show:
# 0-9, A-F, minus, degree
CHARSET = b'\x3F\x06\x5B\x4F\x66\x6D\x7D\x07\x7F\x6F\x5F\x7C\x58\x5E\x7B\x71\x40\x63\x00'
# *********** CONSTRUCTOR **********
def __init__(self, i2c, i2c_address=0x70):
self.buffer = bytearray(16)
self.point_pattern = 0x00
super(HT16K33SegmentBig, self).__init__(i2c, i2c_address)
# *********** PUBLIC METHODS **********
def set_colon(self, pattern=0x02):
"""
Set or unset the segment LED display's colon and decimal point lights.
This method updates the display buffer, but does not send the buffer to the display itself.
Call 'draw()' to render the buffer on the display.
Args:
patter (int) An integer indicating which elements to light (OR the values required). Default: 0x00
0x00: no colon
0x02: centre colon
0x04: left colon, lower dot
0x08: left colon, upper dot
0x10: decimal point (upper)
Returns:
The instance (self)
"""
# Bail on incorrect pattern values
assert 0 <= pattern < 0x1F, "ERROR - bad patter passed to set_colon()"
self.point_pattern = pattern
self.buffer[self.HT16K33_SEGMENT_COLON_ROW] = pattern
return self
def set_glyph(self, glyph, digit=0):
"""
Present a user-defined character glyph at the specified digit.
Glyph values are 8-bit integers representing a pattern of set LED segments.
The value is calculated by setting the bit(s) representing the segment(s) you want illuminated.
Bit-to-segment mapping runs clockwise from the top around the outside of the matrix; the inner segment is bit 6:
0
_
5 | | 1
| |
- <----- 6
4 | | 2
| _ |
3
This method updates the display buffer, but does not send the buffer to the display itself.
Call 'update()' to render the buffer on the display.
Args:
glyph (int): The glyph pattern.
digit (int): The digit to show the glyph. Default: 0 (leftmost digit).
Returns:
The instance (self)
"""
# Bail on incorrect row numbers or character values
assert 0 <= digit < 4, "ERROR - Invalid digit (0-3) set in set_glyph()"
assert 0 <= glyph < 0x80, "ERROR - Invalid glyph (0x00-0xFF) set in set_glyph()"
self.buffer[self.POS[digit]] = glyph & 0x7F
return self
def set_number(self, number, digit=0):
"""
Present single decimal value (0-9) at the specified digit.
This method updates the display buffer, but does not send the buffer to the display itself.
Call 'update()' to render the buffer on the display.
Args:
number (int): The number to show.
digit (int): The digit to show the number. Default: 0 (leftmost digit).
Returns:
The instance (self)
"""
# Bail on incorrect row numbers or character values
assert 0 <= digit < 4, "ERROR - Invalid digit (0-3) set in set_number()"
assert 0 <= number < 10, "ERROR - Invalid value (0-9) set in set_number()"
return self.set_character(str(number), digit)
def set_character(self, char, digit=0):
"""
Present single alphanumeric character at the specified digit.
Only characters from the class' character set are available:
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d ,e, f, -.
Other characters can be defined and presented using 'set_glyph()'.
This method updates the display buffer, but does not send the buffer to the display itself.
Call 'draw()' to render the buffer on the display.
Args:
char (string): The character to show.
digit (int): The digit to show the number. Default: 0 (leftmost digit).
has_dot (bool): Whether the decimal point to the right of the digit should be lit. Default: False.
Returns:
The instance (self)
"""
# Bail on incorrect row numbers
assert 0 <= digit < 4, "ERROR - Invalid digit set in set_character()"
char = char.lower()
char_val = 0xFF
if char == "deg":
char_val = self.HT16K33_SEGMENT_DEGREE_CHAR
elif char == '-':
char_val = self.HT16K33_SEGMENT_MINUS_CHAR
elif char == ' ':
char_val = self.HT16K33_SEGMENT_SPACE_CHAR
elif char in 'abcdef':
char_val = ord(char) - 87
elif char in '0123456789':
char_val = ord(char) - 48
# Bail on incorrect character values
assert char_val != 0xFF, "ERROR - Invalid char string set in set_character()"
self.buffer[self.POS[digit]] = self.CHARSET[char_val]
return self