diff --git a/examples/fire_effect.py b/examples/fire_effect.py new file mode 100644 index 0000000..685775b --- /dev/null +++ b/examples/fire_effect.py @@ -0,0 +1,103 @@ +# ICON [[(-15.79, 3.95), (-15.51, 6.94), (-15.2, 8.26), (-14.43, 10.4), (-13.58, 12.02), (-12.32, 13.83), (-10.51, 15.74), (-10.45, 13.39), (-10.24, 12.17), (-9.76, 10.72), (-8.93, 9.16), (-7.48, 7.35), (0.0, 0.0), (7.44, 7.3), (8.46, 8.47), (9.71, 10.6), (10.17, 11.89), (10.45, 13.35), (10.48, 15.72), (11.66, 14.58), (12.93, 13.03), (14.38, 10.52), (15.19, 8.31), (15.58, 6.54), (15.79, 3.6), (15.52, 0.96), (15.02, -0.98), (13.97, -3.5), (12.52, -5.82), (11.06, -7.5), (9.95, -6.86), (8.36, -6.2), (7.17, -5.94), (5.4, -5.79), (3.33, -5.97), (0.91, -6.72), (-0.4, -7.44), (-1.72, -8.44), (-2.69, -9.42), (-3.63, -10.68), (-4.68, -12.85), (-5.19, -15.13), (-8.01, -12.51), (-9.15, -11.27), (-11.14, -8.83), (-12.74, -6.46), (-14.34, -3.25), (-15.11, -1.05), (-15.44, 0.4), (-15.79, 3.88)], [(0.0, 7.37), (-3.75, 11.05), (-4.84, 12.64), (-5.13, 13.52), (-5.19, 15.45), (-4.87, 16.57), (-4.1, 17.84), (-2.72, 19.0), (-1.72, 19.46), (-0.25, 19.73), (1.41, 19.55), (2.76, 18.97), (3.59, 18.31), (4.51, 17.22), (4.93, 16.41), (5.27, 14.67), (5.08, 13.28), (4.66, 12.27), (3.8, 11.1), (0.0, 7.37)], [(0.0, -25.0), (0.0, -16.32), (0.16, -14.97), (0.71, -13.6), (2.01, -12.15), (3.59, -11.32), (4.69, -11.09), (5.96, -11.09), (7.45, -11.49), (8.86, -12.49), (10.53, -14.47), (11.75, -13.73), (13.55, -12.39), (14.73, -11.32), (16.44, -9.43), (18.19, -6.83), (19.2, -4.86), (19.92, -3.02), (20.68, -0.12), (21.02, 2.7), (21.05, 4.41), (20.83, 7.19), (20.19, 10.17), (19.62, 11.85), (18.53, 14.16), (17.1, 16.38), (15.95, 17.8), (14.14, 19.64), (12.57, 20.94), (11.24, 21.85), (9.38, 22.91), (6.78, 23.96), (3.72, 24.71), (1.77, 24.94), (0.07, 25.0), (-2.09, 24.91), (-3.74, 24.7), (-6.22, 24.14), (-8.29, 23.4), (-9.62, 22.79), (-11.73, 21.54), (-13.32, 20.35), (-15.34, 18.46), (-17.53, 15.76), (-18.96, 13.32), (-20.09, 10.49), (-20.61, 8.46), (-20.98, 5.77), (-21.05, 4.01), (-20.88, 1.05), (-20.51, -1.2), (-20.05, -3.0), (-19.14, -5.6), (-18.27, -7.52), (-16.85, -10.04), (-15.43, -12.12), (-14.45, -13.38), (-12.26, -15.85), (-10.14, -17.92), (-8.54, -19.3), (-6.33, -21.03), (-3.0, -23.27), (-0.06, -24.97)]] +# NAME Fire Effect +# DESC Generated fire effect + +#import time +import random +from presto import Presto + +''' +A fire effect based on the Pimoroni Galatic Unicorn example +''' + +presto = Presto() +display = presto.display + +display_width, display_height = display.get_bounds() + +# Display is 240 x 240, calculations for flame effect swamp +# the CPU so cut it down to something more managable by +# having colours in blocks of 4 x 4 +display_width = display_width // 4 +display_height = display_height // 4 + +# The hotter the particle the higher the colour index used +fire_colours = [display.create_pen(0, 0, 0), # Background + display.create_pen(40, 40, 40), # Smoke + display.create_pen(255, 50, 0), + display.create_pen(255, 135, 36), + display.create_pen(255, 221, 73), + display.create_pen(255, 238, 127), + display.create_pen(255, 255, 180)] + + +def setup(): + global width, height, heat, fire_spawns, damping_factor + + width = display_width + 2 + height = display_height + 4 + heat = [[0.0 for y in range(height)] for x in range(width)] + fire_spawns = width // 4 + damping_factor = 0.97 + + +def update(): + # clear the bottom row and then add a new fire seed to it + for x in range(width): + heat[x][height - 1] = 0.0 + heat[x][height - 2] = 0.0 + + for c in range(fire_spawns): + x = random.randint(0, width - 4) + 2 + heat[x + 0][height - 1] += 1.0 + heat[x + 1][height - 1] += 1.0 + heat[x - 1][height - 1] += 1.0 + heat[x + 0][height - 2] += 1.0 + heat[x + 1][height - 2] += 1.0 + heat[x - 1][height - 2] += 1.0 + + for y in range(0, height - 2): + for x in range(1, width - 1): + # update this pixel by averaging the below pixels + average = ( + heat[x][y] + heat[x][y + 1] + heat[x][y + 2] + heat[x - 1][y + 1] + heat[x + 1][y + 1] + ) / 5.0 + + # damping factor to ensure flame tapers out towards the top of the displays + average *= damping_factor + + # update the heat map with our newly averaged value + heat[x][y] = average + + +def draw(): + for y in range(display_height): + for x in range(display_width): + value = heat[x + 1][y] + if value < 0.15: + display.set_pen(fire_colours[0]) + elif value < 0.25: + display.set_pen(fire_colours[1]) + elif value < 0.35: + display.set_pen(fire_colours[2]) + elif value < 0.4: + display.set_pen(fire_colours[3]) + elif value < 0.45: + display.set_pen(fire_colours[4]) + elif value < 0.60: + display.set_pen(fire_colours[5]) + else: + display.set_pen(fire_colours[6]) + # Drawing a rectangle much faster than drawing 16 individual pixels + display.rectangle(x * 4, y * 4, 4, 4) + + presto.update() + + +setup() + +while True: + + update() + + draw() \ No newline at end of file diff --git a/examples/word_time.py b/examples/word_time.py new file mode 100644 index 0000000..f5b8d5c --- /dev/null +++ b/examples/word_time.py @@ -0,0 +1,213 @@ +# ICON [[(6.59, 7.4), (9.39, 4.6), (1.99, -2.8), (1.99, -12.0), (-2.01, -12.0), (-2.01, -1.2), (6.59, 7.4)], [(-0.01, 18.0), (-2.77, 17.82), (-5.22, 17.33), (-6.81, 16.84), (-9.0, 15.88), (-10.82, 14.83), (-12.37, 13.73), (-13.38, 12.88), (-14.8, 11.47), (-16.53, 9.28), (-17.71, 7.33), (-18.44, 5.84), (-18.93, 4.56), (-19.44, 2.82), (-19.69, 1.62), (-19.93, -0.24), (-19.98, -3.03), (-19.82, -4.82), (-19.36, -7.14), (-18.78, -8.99), (-18.18, -10.41), (-16.87, -12.77), (-15.61, -14.52), (-14.53, -15.77), (-13.03, -17.19), (-11.75, -18.19), (-9.49, -19.6), (-7.63, -20.48), (-5.31, -21.29), (-2.8, -21.81), (-1.17, -21.97), (0.56, -22.0), (2.17, -21.89), (4.17, -21.57), (5.78, -21.15), (6.98, -20.74), (8.54, -20.07), (10.61, -18.95), (12.5, -17.62), (14.56, -15.73), (15.71, -14.38), (16.82, -12.81), (18.11, -10.45), (18.75, -8.94), (19.3, -7.26), (19.84, -4.56), (19.98, -2.76), (19.98, -1.18), (19.8, 0.82), (19.39, 2.89), (18.67, 5.12), (17.97, 6.73), (16.56, 9.2), (15.45, 10.7), (13.58, 12.69), (11.88, 14.09), (10.45, 15.06), (9.16, 15.79), (6.7, 16.87), (5.01, 17.38), (2.25, 17.88), (0.04, 18.0)], [(-0.01, -2.0)], [(-0.01, 14.0), (1.87, 13.9), (3.1, 13.72), (4.92, 13.27), (6.57, 12.65), (7.85, 12.0), (9.95, 10.56), (11.26, 9.38), (12.07, 8.51), (13.65, 6.4), (14.66, 4.51), (15.18, 3.17), (15.75, 0.9), (15.93, -0.48), (15.99, -2.41), (15.75, -4.87), (15.46, -6.25), (14.87, -8.01), (14.31, -9.23), (13.28, -10.95), (12.42, -12.08), (11.05, -13.55), (9.91, -14.56), (8.05, -15.86), (6.45, -16.69), (4.54, -17.39), (3.36, -17.68), (1.71, -17.92), (0.44, -18.0), (-1.44, -17.94), (-2.97, -17.75), (-5.29, -17.16), (-6.71, -16.59), (-8.07, -15.88), (-10.05, -14.49), (-11.32, -13.34), (-12.48, -12.07), (-13.2, -11.12), (-14.1, -9.69), (-14.72, -8.44), (-15.33, -6.79), (-15.77, -4.91), (-15.98, -3.05), (-16.0, -1.85), (-15.9, -0.04), (-15.44, 2.39), (-14.95, 3.89), (-14.24, 5.45), (-13.24, 7.08), (-12.22, 8.41), (-11.39, 9.31), (-10.07, 10.49), (-8.57, 11.58), (-7.27, 12.32), (-5.83, 12.96), (-4.11, 13.51), (-1.72, 13.91), (-0.06, 14.0)]] +# NAME Word Time +# DESC Time shown as words + +import time +import ntptime + +from presto import Presto +from touch import Button +from picovector import ANTIALIAS_BEST, PicoVector, Polygon + + +class button(): + def __init__(self, display, vector, text, bg, fg, x, y, h, w, r = 0): + self.display = display + self.vector = vector + self.text = text + self.bg = bg + self.fg = fg + self.button = Button(x, y, h, w) + self.polygon = Polygon() + self.polygon.rectangle(x, y, h, w, (r, r, r, r)) + + + def draw(self): + self.display.set_pen(self.bg) + self.vector.draw(self.polygon) + + self.vector.set_font_size(20) + self.display.set_pen(self.fg) + x_text, y_text, w_text, h_text = self.vector.measure_text(self.text) + x_offset = int((self.button.bounds[2] - w_text) / 2) + self.button.bounds[0] + y_offset = int(((self.button.bounds[3] - h_text) / 2) + self.button.bounds[1] + h_text) + self.vector.text(self.text, x_offset, y_offset) + + + def pressed(self): + return self.button.is_pressed() + + +def show_message(text): + display.set_pen(BLACK) + display.clear() + display.set_pen(WHITE) + display.text(f"{text}", 5, 10, WIDTH, 2) + presto.update() + + +def approx_time(hours, minutes): + nums = {0: "twelve", 1: "one", 2: "two", + 3: "three", 4: "four", 5: "five", 6: "six", + 7: "seven", 8: "eight", 9: "nine", 10: "ten", + 11: "eleven", 12: "twelve"} + + if hours == 12: + hours = 0 + if minutes >= 0 and minutes < 3: + return (nums[hours], "O'Clock", "") + elif minutes >= 3 and minutes < 8: + return ("five", "past", nums[hours]) + elif minutes >= 8 and minutes < 13: + return ("ten", "past", nums[hours]) + elif minutes >= 13 and minutes < 18: + return ("quarter", "past", nums[hours]) + elif minutes >= 18 and minutes < 23: + return ("twenty", "past", nums[hours]) + elif minutes >= 23 and minutes < 28: + return ("twenty five", "past", nums[hours]) + elif minutes >= 28 and minutes < 33: + return ("half", "past", nums[hours]) + elif minutes >= 33 and minutes < 38: + return ("twenty five", "to", nums[hours + 1]) + elif minutes >= 38 and minutes < 43: + return ("twenty", "to", nums[hours + 1]) + elif minutes >= 43 and minutes < 48: + return ("quarter", "to", nums[hours + 1]) + elif minutes >= 48 and minutes < 53: + return ("ten", "to", nums[hours + 1]) + elif minutes >=53 and minutes < 58: + return ("five", "to", nums[hours + 1]) + else: + return (nums[hours + 1], "O'Clock", "") + + +def update(): + + current_t = time.gmtime(time.time() + UTC_OFFSET * 3600) + time_phrase = approx_time(current_t[3] - 12 if current_t[3] > 12 else current_t[3], current_t[4]) + + print(current_t, time_phrase) + + return time_phrase + + +def draw(time_phrase): + display.set_font("bitmap8") + + display.set_pen(BLACK) + display.clear() + + default_x = 25 + x = default_x + y = 40 + + line_space = 40 + letter_space = 15 + margin = 25 + scale = 1 + spacing = 1 + + display.set_pen(WHITE) + + header = "IT IS ABOUT" + vector.set_font_size(25) + x_text, y_text, w_text, h_text = vector.measure_text(header) + x_offset = int((WIDTH - w_text) / 2) + vector.text(header, x_offset, y) + + y += line_space + 15 + vector.set_font_size(40) + for line in time_phrase: + line = line.upper() +# x_offset = int((WIDTH - display.measure_text(line, scale = 3, spacing = 3)) / 2) +# display.text(line, x_offset, y, WIDTH, scale = 3, spacing = 3) + x_text, y_text, w_text, h_text = vector.measure_text(line) + x_offset = int((WIDTH - w_text) / 2) + vector.text(line, x_offset, y) + y += line_space + + utc_plus_button.draw() + utc_minus_button.draw() + + presto.update() + +# Setup for the Presto display +presto = Presto() +display = presto.display +WIDTH, HEIGHT = display.get_bounds() +BLACK = display.create_pen(0, 0, 0) +WHITE = display.create_pen(200, 200, 200) + +vector = PicoVector(display) +vector.set_antialiasing(ANTIALIAS_BEST) + +vector.set_font("Roboto-Medium.af", 96) +vector.set_font_letter_spacing(100) +vector.set_font_word_spacing(100) + +# Clear the screen before the network call is made +display.set_pen(BLACK) +display.clear() +presto.update() + +show_message("Connecting...") + +try: + wifi = presto.connect() +except ValueError as e: + while True: + show_message(e) +except ImportError as e: + while True: + show_message(e) + +# Set the correct time using the NTP service. +try: + ntptime.settime() + ntp_time_set = time.time() +except OSError: + while True: + show_message("Unable to get time.\n\nCheck your network try again.") + +utc_plus_button = button(display, vector, 'UTC +', WHITE, BLACK, WIDTH - (WIDTH // 4), HEIGHT - 30, WIDTH // 4, 30, 5) +utc_minus_button = button(display, vector, 'UTC -', WHITE, BLACK, 0, HEIGHT - 30, WIDTH // 4, 30, 5) + +# Offset of zero, no daylight saving or region +UTC_OFFSET = 0 + +while True: + # Get a time checkpoint for multiple uses below + time_check = time.time() + + # Update the RTC once a day + if time_check - ntp_time_set > 60 * 60 * 24: + try: + ntptime.settime() + ntp_time_set = time.time() + except OSError: + # Report and carry on, RTC is probably going to be close to right for a long time + print("Unable to contact NTP server") + + # Update the screen + time_phrase = update() + draw(time_phrase) + + # 30 second tight loop to be responsive to button presses + while time_check + 30 >= time.time(): + presto.touch.poll() + update_needed = False + if utc_plus_button.pressed(): + while utc_plus_button.pressed(): + presto.touch.poll() + UTC_OFFSET += 1 + update_needed = True + if utc_minus_button.pressed(): + while utc_minus_button.pressed(): + presto.touch.poll() + UTC_OFFSET -= 1 + update_needed = True + # Redraw the screen if needed + if update_needed: + time_phrase = update() + draw(time_phrase) \ No newline at end of file