1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198 | from machine import Pin, SPI
from utime import sleep, localtime
import ST7735
import config
# Initialize SPI and display
spi = machine.SPI(config.SPI_BUS,
sck=Pin(config.SPI_SCL_PIN),
mosi=Pin(config.SPI_SDA_PIN),
baudrate=8000000)
display = ST7735.ST7735(spi,
rst=config.SPI_RESET_PIN,
ce=config.SPI_CS_PIN,
dc=config.SPI_DC_PIN)
display.reset()
display.begin()
display.set_rotation(config.DISPLAY_ROTATION)
# Define colors using RGB565 format
BACKGROUND_COLOR = display.rgb_to_565(0, 0, 255) # Blue background
DIGIT_COLOR = display.rgb_to_565(255, 255, 255) # White for digits
TEXT_COLOR = display.rgb_to_565(255, 255, 0) # Yellow for text
# Previous state tracking
prev_date = ""
prev_hour_ten = -1
prev_hour_right = -1
prev_minute_ten = -1
prev_minute_right = -1
prev_second = -1
prev_am_pm = ""
screen_initialized = False
segmentMapping = [
#a, b, c, d, e, f, g
[1, 1, 1, 1, 1, 1, 0], # 0
[0, 1, 1, 0, 0, 0, 0], # 1
[1, 1, 0, 1, 1, 0, 1], # 2
[1, 1, 1, 1, 0, 0, 1], # 3
[0, 1, 1, 0, 0, 1, 1], # 4
[1, 0, 1, 1, 0, 1, 1], # 5
[1, 0, 1, 1, 1, 1, 1], # 6
[1, 1, 1, 0, 0, 0, 0], # 7
[1, 1, 1, 1, 1, 1, 1], # 8
[1, 1, 1, 1, 0, 1, 1] # 9
]
def day_to_str(day_num):
"""Convert a day number (0-6) to a three-letter day abbreviation."""
days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
if not 0 <= day_num <= 6:
raise ValueError("Day number must be between 0 and 6")
return days[day_num]
def month_to_str(month_num):
"""Convert a month number (1-12) to a three-letter month abbreviation."""
months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
if not 1 <= month_num <= 12:
raise ValueError("Month number must be between 1 and 12")
return months[month_num - 1]
def clear_digit_area(x, y, width, height, color):
"""Clear the area where a digit was previously drawn."""
display.draw_block(x, y, width, height, color)
def drawDigit(digit, x, y, width, height, thickness, color):
"""Draw a seven-segment digit on the display."""
if digit < 0:
return
# Clear the area first
clear_digit_area(x, y, width, height, BACKGROUND_COLOR)
segmentOn = segmentMapping[digit]
# Draw horizontal segments (top, middle, bottom)
for i in [0, 3, 6]:
if segmentOn[i]:
if i == 0: # top
yOffset = 0
elif i == 3: # bottom
yOffset = height - thickness
else: # middle
yOffset = height // 2 - thickness // 2
display.draw_block(x, y + yOffset, width, thickness, color)
# Draw vertical segments
for i in [1, 2, 4, 5]:
if segmentOn[i]:
if i == 1 or i == 5: # upper segments
startY = y
endY = y + height // 2
else: # lower segments
startY = y + height // 2
endY = y + height
xOffset = 0 if (i == 4 or i == 5) else width - thickness
display.draw_block(x + xOffset, startY, thickness, endY - startY, color)
def draw_colon(x, y, color):
"""Draw the blinking colon between hours and minutes."""
display.draw_block(x, y, 4, 4, color)
display.draw_block(x, y + 14, 4, 4, color)
def update_screen(year, month, day, hour, minute, second, weekday):
"""Update only the changing parts of the display."""
global prev_date, prev_hour_ten, prev_hour_right, prev_minute_ten
global prev_minute_right, prev_second, prev_am_pm, screen_initialized
# Initialize screen on first run
if not screen_initialized:
display.fill_screen(BACKGROUND_COLOR)
screen_initialized = True
# Calculate positions
left_margin = -15
y_offset = 30
digit_width = 32
digit_height = 50
digit_spacing = 42
digit_thickness = 6
# Convert 24-hour to 12-hour format
display_hour = hour if hour <= 12 else hour - 12
if display_hour == 0:
display_hour = 12
# Format date string
date_str = f"{day_to_str(weekday)} {month_to_str(month)} {day} {year}"
# Update date if changed
if date_str != prev_date:
display._color = TEXT_COLOR
# Clear previous date area
display.draw_block(4, 4, 160, 10, BACKGROUND_COLOR)
display.p_string(4, 4, date_str)
prev_date = date_str
# Split time into digits
hour_ten = display_hour // 10 if display_hour >= 10 else -1
hour_right = display_hour % 10
minute_ten = minute // 10
minute_right = minute % 10
# Update digits only if they've changed
if hour_ten != prev_hour_ten:
drawDigit(hour_ten, left_margin, y_offset, digit_width, digit_height, digit_thickness, DIGIT_COLOR)
prev_hour_ten = hour_ten
if hour_right != prev_hour_right:
drawDigit(hour_right, left_margin + digit_spacing, y_offset, digit_width, digit_height, digit_thickness, DIGIT_COLOR)
prev_hour_right = hour_right
if minute_ten != prev_minute_ten:
drawDigit(minute_ten, left_margin + 2*digit_spacing+10, y_offset, digit_width, digit_height, digit_thickness, DIGIT_COLOR)
prev_minute_ten = minute_ten
if minute_right != prev_minute_right:
drawDigit(minute_right, left_margin + 3*digit_spacing+10, y_offset, digit_width, digit_height, digit_thickness, DIGIT_COLOR)
prev_minute_right = minute_right
# Handle colon blinking - clear and redraw based on seconds
colon_x = left_margin + digit_spacing + digit_width + 8
colon_y = y_offset + 15
if second % 2:
draw_colon(colon_x, colon_y, DIGIT_COLOR)
else:
draw_colon(colon_x, colon_y, BACKGROUND_COLOR)
# Update AM/PM indicator if needed
am_pm_str = "PM" if hour >= 12 else "AM"
if am_pm_str != prev_am_pm:
display._color = TEXT_COLOR
display.draw_block(left_margin + 3*digit_spacing + digit_width, y_offset + 60, 20, 10, BACKGROUND_COLOR)
display.p_string(left_margin + 3*digit_spacing + digit_width, y_offset + 60, am_pm_str)
prev_am_pm = am_pm_str
# Update seconds display if changed
if second != prev_second:
display._color = TEXT_COLOR
display.draw_block(4, y_offset + digit_height + 10, 20, 10, BACKGROUND_COLOR)
display.p_string(4, y_offset + digit_height + 10, f"{second:02d}")
prev_second = second
# Main loop
while True:
now = localtime()
year = now[0]
month = now[1]
day = now[2]
hour = now[3]
minute = now[4]
second = now[5]
weekday = now[6]
update_screen(year, month, day, hour, minute, second, weekday)
sleep(0.1) # Shorter sleep for more responsive updates
|