Skip to content

Commit 18432cd

Browse files
committed
Examples: Adding tomato timer
1 parent 63808c1 commit 18432cd

File tree

1 file changed

+198
-0
lines changed

1 file changed

+198
-0
lines changed

examples/tomato.py

Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
import time
2+
from picovector import ANTIALIAS_BEST, PicoVector, Polygon, Transform
3+
from presto import Presto, Buzzer
4+
from touch import Button
5+
6+
presto = Presto(ambient_light=True)
7+
display = presto.display
8+
WIDTH, HEIGHT = display.get_bounds()
9+
10+
# Centre points for the display
11+
CX = WIDTH // 2
12+
CY = HEIGHT // 2
13+
14+
# We'll need this for the touch element of the screen
15+
touch = presto.touch
16+
17+
# Pico Vector
18+
vector = PicoVector(display)
19+
vector.set_antialiasing(ANTIALIAS_BEST)
20+
t = Transform()
21+
22+
vector.set_font("Roboto-Medium.af", 96)
23+
vector.set_font_letter_spacing(100)
24+
vector.set_font_word_spacing(100)
25+
vector.set_transform(t)
26+
27+
BLACK = display.create_pen(0, 0, 0)
28+
29+
# Setup the buzzer. The Presto piezo is on pin 43.
30+
buzzer = Buzzer(43)
31+
32+
33+
class Tomato(object):
34+
def __init__(self):
35+
36+
self.hue = 0
37+
self.background = display.create_pen_hsv(self.hue, 0.8, 1.0) # We'll use this one for the background.
38+
self.foreground = display.create_pen_hsv(self.hue, 0.5, 1.0) # Slightly lighter for foreground elements.
39+
self.text_colour = display.create_pen_hsv(self.hue, 0.2, 1.0)
40+
41+
# Time constants.
42+
# Feel free to change these to ones that work better for you.
43+
self.TASK = 25 * 60
44+
self.SHORT = 10 * 60
45+
self.LONG = 30 * 60
46+
47+
# How long the completion alert should be played (seconds)
48+
self.alert_duration = 2
49+
self.alert_start_time = 0
50+
51+
self.is_break_time = False
52+
self.start_time = 0
53+
self.tasks_complete = 0
54+
self.running = False
55+
self.paused = False
56+
self.time_elapsed = 0
57+
self.current_timer = self.TASK
58+
59+
# We'll use a rect with rounded corners for the background.
60+
self.background_rect = Polygon()
61+
self.background_rect.rectangle(0, 0, WIDTH, HEIGHT, (10, 10, 10, 10))
62+
63+
self.foreground_rect = Polygon()
64+
self.foreground_rect.rectangle(10, 10, WIDTH - 20, HEIGHT - 120, (10, 10, 10, 10))
65+
66+
# Touch button
67+
self.start_button = Button(CX - 56, HEIGHT - 75, CX - 2, 50)
68+
x, y, w, h = self.start_button.bounds
69+
self.start = Polygon()
70+
self.start.rectangle(x, y, w, h, (10, 10, 10, 10))
71+
self.start_shadow = Polygon()
72+
self.start_shadow.rectangle(x + 3, y + 3, w, h, (10, 10, 10, 10))
73+
74+
# Update the pens for the background, foreground and text elements based on the given hue.
75+
def update_pens(self, hue):
76+
self.hue = hue
77+
self.background = display.create_pen_hsv(self.hue, 0.8, 1.0)
78+
self.foreground = display.create_pen_hsv(self.hue, 0.5, 1.0)
79+
self.text_colour = display.create_pen_hsv(self.hue, 0.2, 1.0)
80+
81+
def draw(self):
82+
83+
# Clear the screen
84+
display.set_pen(BLACK)
85+
display.clear()
86+
87+
# Draw the background rect with rounded corners
88+
display.set_pen(self.background)
89+
vector.draw(self.background_rect)
90+
91+
# Draw the foreground rect, this is where we will show the time remaining.
92+
display.set_pen(self.foreground)
93+
vector.draw(self.foreground_rect)
94+
95+
# Draw the button with drop shadow
96+
vector.draw(self.start_shadow)
97+
display.set_pen(self.text_colour)
98+
vector.draw(self.start)
99+
100+
# Draw the button text, the text shown here depends on the current timer state
101+
vector.set_font_size(24)
102+
display.set_pen(self.foreground)
103+
104+
if not self.running:
105+
if self.is_break_time:
106+
vector.text("Start Break", self.start_button.bounds[0] + 8, self.start_button.bounds[1] + 33)
107+
else:
108+
vector.text("Start Task", self.start_button.bounds[0] + 12, self.start_button.bounds[1] + 33)
109+
elif self.running and self.paused:
110+
vector.text("Resume", self.start_button.bounds[0] + 22, self.start_button.bounds[1] + 33)
111+
else:
112+
vector.text("Pause", self.start_button.bounds[0] + 32, self.start_button.bounds[1] + 33)
113+
114+
display.set_pen(self.text_colour)
115+
text = self.return_string()
116+
vector.set_font_size(96)
117+
x, y, w, h = vector.measure_text(text, x=0, y=0, angle=None)
118+
tx = int(CX - (w // 2))
119+
ty = int(CY - (h // 2)) + 10
120+
vector.text(text, tx, ty)
121+
122+
def run(self):
123+
self.stop_buzzer()
124+
125+
if self.is_break_time:
126+
if self.tasks_complete < 4:
127+
self.current_timer = self.SHORT
128+
self.update_pens(0.55)
129+
else:
130+
self.current_timer = self.LONG
131+
self.update_pens(0.55)
132+
else:
133+
self.current_timer = self.TASK
134+
self.update_pens(0.0)
135+
136+
if not self.running:
137+
self.reset()
138+
self.running = True
139+
self.start_time = time.time()
140+
elif self.running and not self.paused:
141+
self.paused = True
142+
elif self.running and self.paused:
143+
self.paused = False
144+
self.start_time = time.time() - self.time_elapsed
145+
146+
def reset(self):
147+
self.start_time = 0
148+
self.time_elapsed = 0
149+
150+
def start_buzzer(self):
151+
self.alert_start_time = time.time()
152+
buzzer.set_tone(150)
153+
154+
def stop_buzzer(self):
155+
buzzer.set_tone(-1)
156+
self.alert_start_time = 0
157+
158+
def update(self):
159+
160+
if time.time() - self.alert_start_time >= self.alert_duration:
161+
self.stop_buzzer()
162+
163+
if self.running and not self.paused:
164+
165+
self.time_elapsed = time.time() - self.start_time
166+
167+
if self.time_elapsed >= self.current_timer:
168+
self.running = False
169+
self.start_buzzer()
170+
if not self.is_break_time:
171+
if self.tasks_complete < 4:
172+
self.tasks_complete += 1
173+
else:
174+
self.tasks_complete = 0
175+
self.is_break_time = not self.is_break_time
176+
177+
# Return the remaining time formatted in a string for displaying with vector text.
178+
def return_string(self):
179+
minutes, seconds = divmod(self.current_timer - self.time_elapsed, 60)
180+
return f"{minutes:02d}:{seconds:02d}"
181+
182+
def pressed(self):
183+
return self.start_button.is_pressed()
184+
185+
186+
# Create an instance of our timer object
187+
timer = Tomato()
188+
189+
while True:
190+
191+
if timer.pressed():
192+
while timer.pressed():
193+
touch.poll()
194+
timer.run()
195+
196+
timer.draw()
197+
timer.update()
198+
presto.update()

0 commit comments

Comments
 (0)