# tm1637.py
# TM1637 MicroPython driver by S. H. and modified for Pico

from machine import Pin
from time import sleep_us, sleep_ms

_SEGMENTS = bytearray(b'\x3f\x06\x5b\x4f\x66\x6d\x7d\x07\x7f\x6f\x77\x7c\x39\x5e\x79\x71')  # 0-9,A,b,C,d,E,F

class TM1637:
    def __init__(self, clk, dio):
        self.clk = clk
        self.dio = dio
        self.clk.init(Pin.OUT)
        self.dio.init(Pin.OUT)
        self.brightness = 7
        self.on = True

    def _start(self):
        self.dio.init(Pin.OUT)
        self.dio.value(0)
        sleep_us(2)

    def _stop(self):
        self.dio.init(Pin.OUT)
        self.dio.value(0)
        sleep_us(2)
        self.clk.value(1)
        sleep_us(2)
        self.dio.value(1)

    def _write_byte(self, b):
        for i in range(8):
            self.clk.value(0)
            self.dio.value((b >> i) & 1)
            sleep_us(3)
            self.clk.value(1)
            sleep_us(3)

        self.clk.value(0)
        self.dio.init(Pin.IN)
        self.clk.value(1)
        sleep_us(3)
        self.clk.value(0)
        self.dio.init(Pin.OUT)

    def encode_digit(self, digit):
        return _SEGMENTS[digit & 0x0f]

    def display(self, data):
        self._start()
        self._write_byte(0x40)
        self._stop()

        self._start()
        self._write_byte(0xc0)
        for byte in data:
            self._write_byte(byte)
        self._stop()

        self._start()
        control = 0x88 | (self.brightness & 0x07)
        if not self.on:
            control = 0x80
        self._write_byte(control)
        self._stop()

    def numbers(self, minutes, seconds):
        m1 = minutes // 10
        m2 = minutes % 10
        s1 = seconds // 10
        s2 = seconds % 10
        data = bytearray([
            self.encode_digit(m1),
            self.encode_digit(m2) | 0x80,  # Add colon
            self.encode_digit(s1),
            self.encode_digit(s2)
        ])
        self.display(data)

    def show_raw(self, data):  # Accept 4 raw segment bytes
        self.display(data)

    def clear(self):
        self.display(bytearray([0, 0, 0, 0]))
