Created
May 14, 2026 16:04
-
-
Save bradmartin333/d7588e39345da6c838b0a98e5414c3a6 to your computer and use it in GitHub Desktop.
RP2040 TM1637 60FPS timecode
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import board | |
| import digitalio | |
| import time | |
| import touchio | |
| from adafruit_debouncer import Button | |
| # Update these pins to match your wiring. | |
| TM1637_CLK_PIN = board.GP3 | |
| TM1637_DIO_PIN = board.GP4 | |
| DISPLAY_VSS_PIN = board.GP5 | |
| TOUCH_THRESHOLD_OFFSET = 1000 | |
| TOUCH_PIN_CANDIDATES = ("GP12", "A1", "A2", "TOUCH1", "TOUCH2") | |
| FPS = 60 | |
| FRAME_PERIOD = 1.0 / FPS | |
| class TM1637: | |
| SEGMENTS = { | |
| " ": 0x00, | |
| "-": 0x40, | |
| "0": 0x3F, | |
| "1": 0x06, | |
| "2": 0x5B, | |
| "3": 0x4F, | |
| "4": 0x66, | |
| "5": 0x6D, | |
| "6": 0x7D, | |
| "7": 0x07, | |
| "8": 0x7F, | |
| "9": 0x6F, | |
| } | |
| def __init__(self, clk_pin, dio_pin, brightness=7): | |
| self._clk = digitalio.DigitalInOut(clk_pin) | |
| self._dio = digitalio.DigitalInOut(dio_pin) | |
| self._clk.direction = digitalio.Direction.OUTPUT | |
| self._dio.direction = digitalio.Direction.OUTPUT | |
| self._clk.value = True | |
| self._dio.value = True | |
| self.set_brightness(brightness) | |
| def set_brightness(self, brightness): | |
| if brightness < 0: | |
| brightness = 0 | |
| if brightness > 7: | |
| brightness = 7 | |
| self._brightness = brightness | |
| def _delay(self): | |
| time.sleep(0.000005) | |
| def _start(self): | |
| self._dio.value = True | |
| self._clk.value = True | |
| self._delay() | |
| self._dio.value = False | |
| def _stop(self): | |
| self._clk.value = False | |
| self._delay() | |
| self._dio.value = False | |
| self._delay() | |
| self._clk.value = True | |
| self._delay() | |
| self._dio.value = True | |
| def _write_byte(self, value): | |
| for _ in range(8): | |
| self._clk.value = False | |
| self._dio.value = bool(value & 0x01) | |
| self._delay() | |
| self._clk.value = True | |
| self._delay() | |
| value >>= 1 | |
| # ACK cycle | |
| self._clk.value = False | |
| self._dio.value = True | |
| self._delay() | |
| self._clk.value = True | |
| self._delay() | |
| self._clk.value = False | |
| def write_raw(self, data): | |
| self._start() | |
| self._write_byte(0x40) | |
| self._stop() | |
| self._start() | |
| self._write_byte(0xC0) | |
| for b in data: | |
| self._write_byte(b) | |
| self._stop() | |
| self._start() | |
| self._write_byte(0x88 | self._brightness) | |
| self._stop() | |
| def show_number(self, number): | |
| number %= 10000 | |
| text = "{:04d}".format(number) | |
| self.write_raw([self.SEGMENTS[ch] for ch in text]) | |
| def try_touch_button(): | |
| last_error = "No supported touch pins found on this board" | |
| for pin_name in TOUCH_PIN_CANDIDATES: | |
| pin = getattr(board, pin_name, None) | |
| if pin is None: | |
| continue | |
| try: | |
| touch = touchio.TouchIn(pin) | |
| touch.threshold = touch.raw_value + TOUCH_THRESHOLD_OFFSET | |
| return Button(touch, value_when_pressed=True), pin_name, None | |
| except Exception as exc: | |
| last_error = "%s: %s" % (pin_name, exc) | |
| return None, None, last_error | |
| def setup_display_vss(): | |
| vss = digitalio.DigitalInOut(DISPLAY_VSS_PIN) | |
| vss.direction = digitalio.Direction.OUTPUT | |
| vss.value = True | |
| return vss | |
| def main(): | |
| display_vss = setup_display_vss() | |
| brightness = 7 | |
| display = TM1637(TM1637_CLK_PIN, TM1637_DIO_PIN, brightness=brightness) | |
| touch_button, touch_pin_name, touch_error = try_touch_button() | |
| print("Display VSS pin %s driven HIGH" % DISPLAY_VSS_PIN) | |
| if touch_button is None: | |
| print("Touch input unavailable: %s" % touch_error) | |
| else: | |
| print("Touch input active on %s" % touch_pin_name) | |
| counter = 0 | |
| next_frame = time.monotonic() | |
| display.show_number(counter) | |
| while True: | |
| now = time.monotonic() | |
| if touch_button is not None: | |
| touch_button.update() | |
| if touch_button.rose: | |
| brightness = (brightness + 1) % 8 | |
| display.set_brightness(brightness) | |
| display.show_number(counter) | |
| print("Brightness:", brightness) | |
| continue | |
| if now >= next_frame: | |
| frames_elapsed = int((now - next_frame) / FRAME_PERIOD) + 1 | |
| counter += frames_elapsed | |
| next_frame += frames_elapsed * FRAME_PERIOD | |
| display.show_number(counter) | |
| else: | |
| time.sleep(0.001) | |
| main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment