# Import the base class from ht16k33 import HT16K33 class HT16K33Segment(HT16K33): """ Micro/Circuit Python class for the Adafruit 0.56-in 4-digit, 7-segment LED matrix backpack and equivalent Featherwing. Bus: I2C Author: Tony Smith (@smittytone) License: MIT Copyright: 2024 """ # *********** CONSTANTS ********** HT16K33_SEGMENT_COLON_ROW = 0x04 HT16K33_SEGMENT_MINUS_CHAR = 0x10 HT16K33_SEGMENT_DEGREE_CHAR = 0x11 HT16K33_SEGMENT_SPACE_CHAR = 0x12 # 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, space 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.is_rotated = False super(HT16K33Segment, self).__init__(i2c, i2c_address) # *********** PUBLIC METHODS ********** def rotate(self): """ Rotate/flip the segment display. Returns: The instance (self) """ self.is_rotated = not self.is_rotated return self def set_colon(self, is_set=True): """ Set or unset the display's central colon symbol. 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: isSet (bool): Whether the colon is lit (True) or not (False). Default: True. Returns: The instance (self) """ self.buffer[self.HT16K33_SEGMENT_COLON_ROW] = 0x02 if is_set is True else 0x00 return self def set_glyph(self, glyph, digit=0, has_dot=False): """ 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). 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 or character values assert 0 <= digit < 4, "ERROR - Invalid digit (0-3) set in set_glyph()" assert 0 <= glyph < 0x80, "ERROR - Invalid glyph (0x00-0x80) set in set_glyph()" self.buffer[self.POS[digit]] = glyph if has_dot is True: self.buffer[self.POS[digit]] |= 0x80 return self def set_number(self, number, digit=0, has_dot=False): """ 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). 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 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, has_dot) def set_character(self, char, digit=0, has_dot=False): """ 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 'update()' 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] if has_dot is True: self.buffer[self.POS[digit]] |= 0x80 return self def draw(self): """ Writes the current display buffer to the display itself. Call this method after updating the buffer to update the LED itself. Rotation handled here. """ if self.is_rotated: # Swap digits 0,3 and 1,2 a = self.buffer[self.POS[0]] self.buffer[self.POS[0]] = self.buffer[self.POS[3]] self.buffer[self.POS[3]] = a a = self.buffer[self.POS[1]] self.buffer[self.POS[1]] = self.buffer[self.POS[2]] self.buffer[self.POS[2]] = a # Rotate each digit for i in range(0, 4): a = self.buffer[self.POS[i]] b = (a & 0x07) << 3 c = (a & 0x38) >> 3 a &= 0xC0 self.buffer[self.POS[i]] = (a | b | c) self._render()