diff --git a/micropython/examples/tufty2040/game.py b/micropython/examples/tufty2040/awesome_game.py similarity index 100% rename from micropython/examples/tufty2040/game.py rename to micropython/examples/tufty2040/awesome_game.py diff --git a/micropython/examples/tufty2040/buttons.py b/micropython/examples/tufty2040/button_test.py similarity index 100% rename from micropython/examples/tufty2040/buttons.py rename to micropython/examples/tufty2040/button_test.py diff --git a/micropython/examples/tufty2040/main.py b/micropython/examples/tufty2040/main.py new file mode 100644 index 00000000..f8c56e19 --- /dev/null +++ b/micropython/examples/tufty2040/main.py @@ -0,0 +1,151 @@ +from picographics import PicoGraphics, DISPLAY_TUFTY_2040, PEN_RGB332 +from os import listdir +import time +import gc +from pimoroni import Button + +display = PicoGraphics(display=DISPLAY_TUFTY_2040, pen_type=PEN_RGB332, rotate=180) + + +def hsv_to_rgb(h, s, v): + if s == 0.0: + return v, v, v + i = int(h * 6.0) + f = (h * 6.0) - i + p = v * (1.0 - s) + q = v * (1.0 - s * f) + t = v * (1.0 - s * (1.0 - f)) + v = int(v * 255) + t = int(t * 255) + p = int(p * 255) + q = int(q * 255) + i = i % 6 + if i == 0: + return v, t, p + if i == 1: + return q, v, p + if i == 2: + return p, v, t + if i == 3: + return p, q, v + if i == 4: + return t, p, v + if i == 5: + return v, p, q + + +def get_applications(): + # fetch a list of the applications that are stored in the filesystem + applications = [] + for file in listdir(): + if file.endswith(".py") and file != "main.py": + # convert the filename from "something_or_other.py" to "Something Or Other" + # via weird incantations and a sprinkling of voodoo + title = " ".join([v[:1].upper() + v[1:] for v in file[:-3].split("_")]) + + applications.append( + { + "file": file, + "title": title + } + ) + + # sort the application list alphabetically by title and return the list + return sorted(applications, key=lambda x: x["title"]) + + +def launch_application(application): + for k in locals().keys(): + if k not in ("gc", "file", "badger_os"): + del locals()[k] + + gc.collect() + + __import__(application["file"]) + + +applications = get_applications() + +button_up = Button(22, invert=False) +button_down = Button(6, invert=False) +button_a = Button(7, invert=False) + +display.set_backlight(1.0) + +WHITE = display.create_pen(255, 255, 255) +BLACK = display.create_pen(0, 0, 0) +RED = display.create_pen(200, 0, 0) + + +def text(text, x, y, pen, s): + display.set_pen(pen) + display.text(text, x, y, -1, s) + + +selected_item = 2 +scroll_position = 2 +target_scroll_position = 2 + +selected_pen = display.create_pen(255, 255, 255) +unselected_pen = display.create_pen(80, 80, 100) +background_pen = display.create_pen(50, 50, 70) +shadow_pen = display.create_pen(0, 0, 0) + +while True: + t = time.ticks_ms() / 1000.0 + + if button_up.read(): + target_scroll_position -= 1 + target_scroll_position = target_scroll_position if target_scroll_position >= 0 else len(applications) - 1 + + if button_down.read(): + target_scroll_position += 1 + target_scroll_position = target_scroll_position if target_scroll_position < len(applications) else 0 + + if button_a.read(): + launch_application(applications[selected_item]) + + display.set_pen(background_pen) + display.clear() + + scroll_position += (target_scroll_position - scroll_position) / 5 + + grid_size = 40 + for y in range(0, 240 / grid_size): + for x in range(0, 320 / grid_size): + h = x + y + int(t * 5) + h = h / 50.0 + r, g, b = hsv_to_rgb(h, .5, 1) + + display.set_pen(display.create_pen(r, g, b)) + display.rectangle(x * grid_size, y * grid_size, grid_size, grid_size) + + # work out which item is selected (closest to the current scroll position) + selected_item = round(target_scroll_position) + + start = time.ticks_ms() + + for list_index, application in enumerate(applications): + distance = list_index - scroll_position + + text_size = 4 if selected_item == list_index else 3 + + # center text horixontally + title_width = display.measure_text(application["title"], text_size) + text_x = int(160 - title_width / 2) + + row_height = text_size * 5 + 20 + + # center list items vertically + text_y = int(120 + distance * row_height - (row_height / 2)) + + # draw the text, selected item brightest and with shadow + if selected_item == list_index: + text(application["title"], text_x + 1, text_y + 1, shadow_pen, text_size) + + text_pen = selected_pen if selected_item == list_index else unselected_pen + text(application["title"], text_x, text_y, text_pen, text_size) + + start = time.ticks_ms() + + display.update() diff --git a/micropython/examples/tufty2040/namebadge.py b/micropython/examples/tufty2040/name_badge.py similarity index 100% rename from micropython/examples/tufty2040/namebadge.py rename to micropython/examples/tufty2040/name_badge.py diff --git a/micropython/examples/tufty2040/s4m_ur4i-pirate-characters.rgb332 b/micropython/examples/tufty2040/s4m_ur4i-pirate-characters.rgb332 new file mode 100644 index 00000000..5c93e9ba Binary files /dev/null and b/micropython/examples/tufty2040/s4m_ur4i-pirate-characters.rgb332 differ diff --git a/micropython/examples/tufty2040/s4m_ur4i-pirate-tilemap.rgb332 b/micropython/examples/tufty2040/s4m_ur4i-pirate-tilemap.rgb332 new file mode 100644 index 00000000..1fabfa95 Binary files /dev/null and b/micropython/examples/tufty2040/s4m_ur4i-pirate-tilemap.rgb332 differ diff --git a/micropython/examples/tufty2040/scrolltext.py b/micropython/examples/tufty2040/scrolltext.py deleted file mode 100644 index 9a57ca3f..00000000 --- a/micropython/examples/tufty2040/scrolltext.py +++ /dev/null @@ -1,46 +0,0 @@ -import time -import math -from picographics import PicoGraphics, DISPLAY_TUFTY_2040 - -display = PicoGraphics(display=DISPLAY_TUFTY_2040) - -display.set_backlight(1.0) - -WHITE = display.create_pen(255, 255, 255) -BLACK = display.create_pen(0, 0, 0) - -# Reads name from file, and then closes the file. -try: - file = open("message.txt", "r") - message = file.readline() - file.close() -except OSError: - message = "CREATE MESSAGE.TXT IN THONNY :)" - -message_length = display.measure_text(message, 10) - -while True: - t = 0 # counter - x = 320 # Starting position of message, begins just off screen. - offset = 10 - - # How many loops it will take to scroll the whole message plus a little extra margin. - scroll = (message_length / offset) + 30 - - while t < scroll: - step = t + t - y = int(80 + math.sin(step / 5) * 30) - h = 100 + math.sin(step / 5) * 100 - - x -= offset - - display.set_pen(WHITE) - display.clear() - - display.set_pen(BLACK) - display.text(message, x, y, message_length, 10) - display.update() - - time.sleep(0.02) - - t += 1 diff --git a/micropython/examples/tufty2040/sketchy_sketch.py b/micropython/examples/tufty2040/sketchy_sketch.py new file mode 100644 index 00000000..18398aa2 --- /dev/null +++ b/micropython/examples/tufty2040/sketchy_sketch.py @@ -0,0 +1,83 @@ +import time +from pimoroni import Button +from picographics import PicoGraphics, DISPLAY_TUFTY_2040, PEN_RGB332 + +display = PicoGraphics(display=DISPLAY_TUFTY_2040, pen_type=PEN_RGB332, rotate=180) + +# Tufty constants +A = 7 +B = 8 +C = 15 +UP = 22 +DOWN = 6 +LED = 25 + +WIDTH, HEIGHT = 320, 240 +display.set_backlight(1.0) + +# Buttons +button_a = Button(7, invert=False) +button_b = Button(8, invert=False) +button_c = Button(9, invert=False) +button_up = Button(22, invert=False) +button_down = Button(6, invert=False) + + +def draw_area(): + display.set_pen(display.create_pen(200, 0, 0)) + display.clear() + + display.set_pen(display.create_pen(255, 215, 0)) + display.text("Sketchy-Sketch", 90, 5, 0, 2) + + # draw main surface + display.set_pen(display.create_pen(205, 205, 205)) + display.rectangle(25, 25, 270, 180) + + # draw knobs + display.set_pen(display.create_pen(150, 50, 50)) + display.circle(25 + 5, 225 + 5, 20) + display.circle(295 + 5, 225 + 5, 20) + display.set_pen(display.create_pen(255, 255, 255)) + display.circle(25 - 1, 225 - 1, 16) + display.circle(295 - 1, 225 - 1, 16) + display.set_pen(display.create_pen(155, 155, 155)) + display.circle(25 + 1, 225 + 1, 16) + display.circle(295 + 1, 225 + 1, 16) + display.set_pen(display.create_pen(205, 205, 205)) + display.circle(25, 225, 15) + display.circle(295, 225, 15) + + +# start position for drawing cursor +position_x = 160 +position_y = 110 + +# draw the sketchy sketch +draw_area() + +while True: + # check for user input and update cursor position as needed + if button_c.raw() and position_x < 290: + position_x += 1 + + if button_a.raw() and position_x > 30: + position_x -= 1 + + if button_up.raw() and position_y > 30: + position_y -= 1 + + if button_down.raw() and position_y < 200: + position_y += 1 + + if button_b.raw(): + draw_area() + + # draw the line + display.set_pen(display.create_pen(50, 50, 50)) + display.circle(position_x, position_y, 2) + + # update the screen contents + display.update() + + time.sleep(0.005) diff --git a/micropython/examples/tufty2040/sketchysketch.py b/micropython/examples/tufty2040/sketchysketch.py deleted file mode 100644 index 1964edd2..00000000 --- a/micropython/examples/tufty2040/sketchysketch.py +++ /dev/null @@ -1,89 +0,0 @@ -import time -from pimoroni import Button -from picographics import PicoGraphics, DISPLAY_TUFTY_2040 - -display = PicoGraphics(display=DISPLAY_TUFTY_2040) - -# Tufty constants -A = 7 -B = 8 -C = 15 -UP = 22 -DOWN = 6 -LED = 25 - -WIDTH, HEIGHT = display.get_bounds() -display.set_backlight(1.0) - -# Buttons -button_a = Button(7, invert=False) -button_b = Button(8, invert=False) -button_c = Button(9, invert=False) -button_up = Button(22, invert=False) -button_down = Button(6, invert=False) - -# Pens -WHITE = display.create_pen(255, 255, 255) -BLACK = display.create_pen(0, 0, 0) -RED = display.create_pen(200, 0, 0) -YELLOW = display.create_pen(255, 215, 0) - - -def draw_area(): - display.set_pen(RED) - display.clear() - - display.set_pen(YELLOW) - display.text("Sketchy-Sketch", 90, 5, 0, 2) - display.set_pen(WHITE) - display.circle(55, 215, 15) - display.circle(260, 215, 15) - display.rectangle(10, 25, 300, 170) - display.update() - - -position_x = 15 -position_y = 30 - -last_x = 15 -last_y = 30 - -draw_area() - -while True: - display.set_pen(0) - - if button_c.raw(): - if position_x < 308: - last_x = position_x - last_y = position_y - position_x += 2 - - if button_a.raw(): - if position_x > 12: - last_x = position_x - last_y = position_y - position_x -= 2 - - if button_up.raw(): - if position_y > 26: - last_x = position_x - last_y = position_y - position_y -= 2 - - if button_down.raw(): - if position_y < 193: - last_x = position_x - last_y = position_y - position_y += 2 - - if button_b.raw(): - draw_area() - position_x = 15 - position_y = 30 - last_x = 15 - last_y = 30 - - display.line(last_x, last_y, position_x, position_y) - display.update() - time.sleep(0.01) diff --git a/micropython/examples/tufty2040/textwave.py b/micropython/examples/tufty2040/textwave.py deleted file mode 100644 index ffa90fc4..00000000 --- a/micropython/examples/tufty2040/textwave.py +++ /dev/null @@ -1,48 +0,0 @@ -import math -import time -from picographics import PicoGraphics, DISPLAY_TUFTY_2040 - -display = PicoGraphics(display=DISPLAY_TUFTY_2040) - -WIDTH, HEIGHT = 320, 240 -display.set_backlight(1.0) - -WHITE = display.create_pen(255, 255, 255) -BLACK = display.create_pen(0, 0, 0) - -display.set_pen(WHITE) -display.clear() -display.update() - -message = "HELLO WORLD!" - - -def calculate_text_size(text): - size = 20 - width = display.measure_text(text, size) - while width > 280 and size > 1: - size -= 1 - width = display.measure_text(text, size) - - return size - - -size = calculate_text_size(message) -length = len(message) - -while True: - display.set_pen(WHITE) - display.clear() - display.set_pen(BLACK) - - t = time.ticks_ms() / 10 / size - - left = int((WIDTH - ((length - 1) * size * 6)) / 2) - top = 120 - int((size * 6) / 2) - - for i in range(length): - step = t + i - y = top - math.sin(step / length * math.pi) * 10 - display.text(message[i], left + (i * size * 6), int(y), 0, size) - - display.update() diff --git a/micropython/examples/tufty2040/wavy_message.py b/micropython/examples/tufty2040/wavy_message.py new file mode 100644 index 00000000..c9777423 --- /dev/null +++ b/micropython/examples/tufty2040/wavy_message.py @@ -0,0 +1,64 @@ +from picographics import PicoGraphics, DISPLAY_TUFTY_2040, PEN_RGB332 +import math +import time + +display = PicoGraphics(display=DISPLAY_TUFTY_2040, pen_type=PEN_RGB332, rotate=180) + + +# convert a hue, saturation, and value into rgb values +def hsv_to_rgb(h, s, v): + if s == 0.0: + return v, v, v + i = int(h * 6.0) + f = (h * 6.0) - i + p, q, t = v * (1.0 - s), v * (1.0 - s * f), v * (1.0 - s * (1.0 - f)) + v, t, p, q = int(v * 255), int(t * 255), int(p * 255), int(q * 255) + i = i % 6 + if i == 0: + return v, t, p + if i == 1: + return q, v, p + if i == 2: + return p, v, t + if i == 3: + return p, q, v + if i == 4: + return t, p, v + if i == 5: + return v, p, q + + +display.set_backlight(1.0) + +message = "Tufty 2040 is a hackable, programmable badge with a TFT LCD colour display, powered by the Raspberry Pi RP2040!" +text_size = 10 +message_width = display.measure_text(message, text_size) + +x_scroll = 0 + +while 1: + t = time.ticks_ms() / 1000.0 + display.set_pen(display.create_pen(50, 50, 50)) + display.clear() + + x_scroll -= 10 + if x_scroll < -(message_width + 320 + 100): + x_scroll = 0 + + # for each character we'll calculate a position and colour, then draw it + for i in range(0, len(message)): + cx = int(x_scroll + (i * text_size * 5.5)) + cy = int(80 + math.sin(t * 10 + i) * 20) + + # to speed things up we only bother doing the hardware if the character will be visible on screen + if cx > -50 and cx < 320: + # draw a shadow for the character + display.set_pen(display.create_pen(0, 0, 0)) + display.text(message[i], cx + 15, cy + 15, -1, text_size) + + # generate a rainbow colour that cycles with time + r, g, b = hsv_to_rgb(i / 10 + t / 5, 1, 1) + display.set_pen(display.create_pen(r, g, b)) + display.text(message[i], cx, cy, -1, text_size) + + display.update()