|
@ -61,6 +61,7 @@ def main():
|
|||
cmd_parser.add_argument('-b', '--baudrate', default=115200, help='the baud rate of the serial device')
|
||||
cmd_parser.add_argument('-v', '--verbose', action='store_true', help='adds more output')
|
||||
cmd_parser.add_argument('--skip-wifi', action='store_true', help='does not sync wifi.json')
|
||||
cmd_parser.add_argument('--bootstrapped-apps', action='store_true', help='[Sync] only bootstrapped apps by default')
|
||||
cmd_parser.add_argument('--print_resources', action='store_true', help='prints resources in json')
|
||||
cmd_parser.add_argument('--boot', help='defines which app to boot into after reboot')
|
||||
cmd_parser.add_argument('--run', help='like run, but after a sync')
|
||||
|
@ -120,9 +121,17 @@ def main():
|
|||
pyboard_util.hard_reset(args)
|
||||
|
||||
if command == "sync":
|
||||
paths = args.paths if len(args.paths) else None
|
||||
if args.bootstrapped_apps:
|
||||
for k,val in list(resources.items()):
|
||||
if val.get("type", None) == "app":
|
||||
if not k in paths and not val.get("bootstrapped", False):
|
||||
if args.verbose:
|
||||
print("Removing app '{0}' from sync list".format(k))
|
||||
del resources[k]
|
||||
|
||||
if args.clean:
|
||||
sync.clean(args)
|
||||
paths = args.paths if len(args.paths) else None
|
||||
synced_resources = sync.sync(args, paths, resources, args.verbose, args.skip_wifi)
|
||||
|
||||
if (command in ["reset", "sync"]) or run_tests:
|
||||
|
|
|
@ -2,3 +2,5 @@
|
|||
__pycache__
|
||||
wifi*.json
|
||||
config.json
|
||||
cmd.exe.lnk
|
||||
tilda_tools.bat
|
|
@ -1,9 +1,9 @@
|
|||
"""3d rotating polyhedra. 2016 badge competition winner, ported for 2018!"""
|
||||
|
||||
___name___ = "3D Spin"
|
||||
___title___ = "3D Spin"
|
||||
___license___ = "MIT"
|
||||
___categories___ = ["Demo"]
|
||||
___dependencies___ = ["app", "ugfx_helper", "random", "sleep", "buttons"]
|
||||
___dependencies___ = ["app", "ugfx_helper", "sleep", "buttons"]
|
||||
|
||||
import ugfx
|
||||
from tilda import Buttons
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
"""DevRant Client for TiLDA-MK4
|
||||
"""
|
||||
___name___ = "DevRant"
|
||||
___license___ = "MIT"
|
||||
___dependencies___ = ["app", "wifi", "http", "ugfx_helper"]
|
||||
___categories___ = ["Other"]
|
||||
___launchable___ = True
|
||||
|
||||
import ugfx, wifi, http, json, utime, ugfx_helper, dialogs, app
|
||||
|
||||
char_ln = 25
|
||||
ln_pg = 19
|
||||
|
||||
def loop():
|
||||
skip = 0
|
||||
while True:
|
||||
ugfx.clear(ugfx.html_color(0x544c6d))
|
||||
data= json.loads(http.get("https://devrant.com/api/devrant/rants?app=3&sort=top&range=day&limit=1&skip="+str(skip)).raise_for_status().content)["rants"][0]
|
||||
|
||||
text=data["text"].split(" ")
|
||||
screens = [[]]
|
||||
line = ""
|
||||
screen = 0
|
||||
for word in text:
|
||||
if len(line+word)+1 >= char_ln:
|
||||
if len(screens[screen]) >= ln_pg:
|
||||
screen+=1
|
||||
screens.append([])
|
||||
screens[screen].append(line)
|
||||
line=word
|
||||
else:
|
||||
line = line + " " + word
|
||||
if len(screens[screen]) < ln_pg:
|
||||
screens[screen].append(line)
|
||||
else:
|
||||
screens.append([line])
|
||||
|
||||
|
||||
hold=True
|
||||
page = 0
|
||||
while hold:
|
||||
ugfx.clear(ugfx.html_color(0x544c6d))
|
||||
ugfx.area(0,0,240,35,ugfx.html_color(0x41476d))
|
||||
ugfx.text(5,5,str(data["score"])+"++ " + data["user_username"] + ":",ugfx.BLACK)
|
||||
|
||||
ugfx.text(5,20,"Page: " + str(page+1) + "/" + str(len(screens)),ugfx.BLACK)
|
||||
count = 0
|
||||
for line in screens[page]:
|
||||
ugfx.text(5,35+count*15,line,ugfx.BLACK)
|
||||
count+=1
|
||||
hold_btn = True
|
||||
while hold_btn:
|
||||
if tilda.Buttons.is_pressed(tilda.Buttons.BTN_Menu):
|
||||
return
|
||||
if tilda.Buttons.is_pressed(tilda.Buttons.BTN_A):
|
||||
skip += 1
|
||||
hold_btn = False
|
||||
hold = False
|
||||
while tilda.Buttons.is_pressed(tilda.Buttons.BTN_A):
|
||||
utime.sleep_ms(10)
|
||||
if tilda.Buttons.is_pressed(tilda.Buttons.JOY_Right):
|
||||
if page < len(screens)-1:
|
||||
page += 1
|
||||
hold_btn = False
|
||||
while tilda.Buttons.is_pressed(tilda.Buttons.JOY_Right):
|
||||
utime.sleep_ms(10)
|
||||
if tilda.Buttons.is_pressed(tilda.Buttons.JOY_Left):
|
||||
if page > 0:
|
||||
page -= 1
|
||||
hold_btn = False
|
||||
while tilda.Buttons.is_pressed(tilda.Buttons.JOY_Left):
|
||||
utime.sleep_ms(10)
|
||||
|
||||
|
||||
ugfx_helper.init()
|
||||
ugfx.clear()
|
||||
ugfx.text(5,5, "DevRant for the TiLDA Mk4", ugfx.BLACK)
|
||||
ugfx.text(5, 40, "Connecting To WIFI", ugfx.BLACK)
|
||||
wifi.connect()
|
||||
ugfx.text(5, 40, "Connecting To WIFI", ugfx.WHITE)
|
||||
loop()
|
||||
app.restart_to_default()
|
|
@ -1,6 +1,6 @@
|
|||
""" starts an LED party on your badge
|
||||
"""
|
||||
___name___ = "LED Party (Party Party)"
|
||||
___title___ = "LED Party (Party Party)"
|
||||
___license___ = "MIT"
|
||||
___dependencies___ = ["wifi", "http", "ugfx_helper", "sleep"]
|
||||
___categories___ = ["LEDs"]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
"""A simple homescreen diplaying an avatar from an url and the user's name"""
|
||||
|
||||
___name___ = "Avatar Homescreen"
|
||||
___title___ = "Avatar Homescreen"
|
||||
___license___ = "WTFPL"
|
||||
___categories___ = ["Homescreens"]
|
||||
___dependencies___ = ["homescreen", "wifi", "http", "sleep", "app", "buttons"]
|
||||
|
|
|
@ -13,6 +13,7 @@ ___bootstrapped___ = True
|
|||
import ugfx_helper, os, database, wifi, app, ospath
|
||||
from dialogs import *
|
||||
from lib.badge_store import BadgeStore
|
||||
from app import *
|
||||
|
||||
### VIEWS ###
|
||||
|
||||
|
@ -29,10 +30,10 @@ def clear():
|
|||
|
||||
def show_categories():
|
||||
clear()
|
||||
with WaitingMessage():
|
||||
with WaitingMessage(title=title, text="Loading categories..."):
|
||||
menu_items = [{"title": c, "category": c} for c in store.get_categories()]
|
||||
|
||||
option = prompt_option(menu_items, none_text="Back", text="Categories", title=title)
|
||||
option = prompt_option(menu_items, none_text="Back", title="Install: Categories")
|
||||
|
||||
if option:
|
||||
show_apps(option["category"])
|
||||
|
@ -43,51 +44,70 @@ def show_apps(c):
|
|||
clear()
|
||||
menu_items = [{"title": a, "app": a} for a in store.get_apps(c)]
|
||||
|
||||
option = prompt_option(menu_items, none_text="Back", title=title)
|
||||
option = prompt_option(menu_items, none_text="Back", title="Install: " + c)
|
||||
|
||||
if option:
|
||||
show_app(option["app"])
|
||||
show_app(option["app"],c)
|
||||
else:
|
||||
return
|
||||
show_categories()
|
||||
|
||||
def show_app(a):
|
||||
def show_app(a,c):
|
||||
clear()
|
||||
with WaitingMessage():
|
||||
with WaitingMessage(title=title, text="Loading app description..."):
|
||||
app_info = store.get_app(a)
|
||||
|
||||
install = prompt_boolean(app_info["description"], title=a, true_text="Install", false_text="Back")
|
||||
|
||||
# Try to get the 'title' key from app_info, falling back to the value of a if not present
|
||||
name = app_info.get("title", a)
|
||||
desc = app_info["description"].strip()
|
||||
app_text = """App:\n{}\n\nDescription:\n{}""".format(name, desc)
|
||||
install = prompt_boolean(app_text , title="Install App", true_text="Install", false_text="Back")
|
||||
|
||||
if install:
|
||||
with WaitingMessage(title="Installing %s" % a, text="Please wait...") as message:
|
||||
installers = store.install(_get_current_apps() + [a])
|
||||
app_text = "App:\n{}\n\n".format(name)
|
||||
with WaitingMessage(title="Installing App...", text="%sGetting ready..." % app_text) as message:
|
||||
installers = store.install([a])
|
||||
n = len(installers)
|
||||
for i, installer in enumerate(installers):
|
||||
message.text = "%s (%s/%s)" % (installer.path, i + 1, n)
|
||||
message.text = "%s%s (%s/%s)" % (app_text + "Downloading files...\n\n", installer.path, i + 1, n)
|
||||
installer.download()
|
||||
app.uncache_apps()
|
||||
|
||||
notice("App %s has been successfully installed" % a, title=title, close_text="Back")
|
||||
launch = prompt_boolean(
|
||||
"%sSuccessfully installed.\n\nPress A to launch the app.\n\nPress B to list more \"%s\" apps." % (app_text, c), title="Install Success!", true_text="Launch", false_text="Back")
|
||||
if (launch):
|
||||
for app_obj in get_apps():
|
||||
if app_obj.name == a:
|
||||
app_obj.boot()
|
||||
else:
|
||||
show_apps(c)
|
||||
else:
|
||||
show_apps(c)
|
||||
|
||||
|
||||
def show_update():
|
||||
clear()
|
||||
update = prompt_boolean("Do you want to update all apps on this badge?", title="Update", true_text="OK", false_text="Back")
|
||||
update = prompt_boolean("Do you want to update all apps on this badge?", title="Update all Apps", true_text="OK", false_text="Back")
|
||||
if update:
|
||||
clear()
|
||||
with WaitingMessage(title=title, text="Please wait...") as message:
|
||||
with WaitingMessage(title=title, text="Getting updates...") as message:
|
||||
update_text = "Downloading files:"
|
||||
installers = store.install(_get_current_apps())
|
||||
n = len(installers)
|
||||
for i, installer in enumerate(installers):
|
||||
message.text = "%s (%s/%s)" % (installer.path, i + 1, n)
|
||||
message.text = "%s\n\n%s (%s/%s)" % (update_text, installer.path, i + 1, n)
|
||||
installer.download()
|
||||
notice("Your badge has been successfully updated", title=title, close_text="Back")
|
||||
notice("Your badge has been successfully updated.", title="Update Success!", close_text="Back")
|
||||
|
||||
def show_remove():
|
||||
clear()
|
||||
app_to_remove = prompt_option(_get_current_apps(), none_text="Back", text="Select App to remove")
|
||||
app_to_remove = prompt_option(_get_current_apps(), title="Remove App...", none_text="Back", text="Select an App to remove.")
|
||||
if app_to_remove:
|
||||
ospath.recursive_rmdir(app_to_remove)
|
||||
app.uncache_apps()
|
||||
notice("%s has been removed" % app_to_remove, title=title, close_text="Back")
|
||||
|
||||
app_text = """App:\n{}""".format(app_to_remove)
|
||||
notice("\"%s\"\n\nThe app has now been removed." % app_text, title="Remove Success!", close_text="Back")
|
||||
|
||||
def main_menu():
|
||||
while True:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
"""This app creates a real EMF badge experience"""
|
||||
|
||||
___name___ = "EMF 2018 badge simulator"
|
||||
___title___ = "EMF 2018 badge simulator"
|
||||
___license___ = "MIT"
|
||||
___categories___ = ["EMF"]
|
||||
___dependencies___ = ["sleep", "app"]
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
"""An NTP time app"""
|
||||
___name___ = "NTP time"
|
||||
|
||||
___title___ = "NTP time"
|
||||
___license___ = "MIT"
|
||||
___dependencies___ = ["ntp", "wifi", "app"]
|
||||
___categories___ = ["EMF"]
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
Get up to date information on what's in stock at The Robot Arms!
|
||||
"""
|
||||
___name___ = "beer"
|
||||
___title___ = "beer"
|
||||
___license___ = "MIT"
|
||||
___dependencies___ = ["app", "sleep", "wifi", "http", "ugfx_helper"]
|
||||
___categories___ = ["EMF"]
|
||||
|
|
|
@ -0,0 +1,208 @@
|
|||
"""Simple brainfuck (an esoteric programming language) interpreter.
|
||||
|
||||
Runs very slowly... prints sierpinski triangle"""
|
||||
|
||||
___name___ = "bf interpreter"
|
||||
___license___ = "MIT"
|
||||
___dependencies___ = ["sleep", "app"]
|
||||
___categories___ = ["Other"]
|
||||
|
||||
import ugfx, os, time, sleep, app
|
||||
from tilda import Buttons
|
||||
from time import sleep_ms
|
||||
|
||||
# initialize screen
|
||||
ugfx.init()
|
||||
ugfx.clear()
|
||||
|
||||
ugfx.set_default_font(ugfx.FONT_TITLE)
|
||||
|
||||
|
||||
Prog="""
|
||||
+>-[>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>++[-]->>>>+>>>+>>>+>>>+>>>+>
|
||||
>>+>>>+>>>+>>>++[-<+]-<<<<+<<++++[->++++++++<]<++[------>+<]>++<<+[--->++<]>++
|
||||
<<-[--->+<]>------<+[-<+]-<[>>+[->+]-<[-]<<[-]+++[>[-]++++++++++.[-]+++[>+[>>+<<
|
||||
-]>>[<<++[-<+]->++[->+]->-]<<+[-<+]->-[-[-[-[-[-[-[-[->>>]>>>]>>>]>>>]>>>]>>>]>>
|
||||
>]>>>]>>>>>>>>>>>>>>>>>>>>> > > > > > > > > > > > > >>>>>>>>>>[+[-<+]-<<<<<<.>>>
|
||||
>>>>]>[+[-<+]-<<<< <<<.>>>>>>>>]>[+[-
|
||||
<+]-<<<<<<<<.>>> tic tac toe >>>>>>]+[-<+]-<<
|
||||
<<<.>>>-]<-]+++ to play: type a number (1 to 9) to +++++++.[-]<<<<
|
||||
<<[<<<<<<<<<<<+ place an X at that grid location [--->++<]>+++.[
|
||||
->+++++++<]>.++ ++++.-[---->+<]
|
||||
>+++.---[->+++<] [ http://mitxela.com/ ] >.+++[->++++<]>+
|
||||
.+++++.-[->+++++<] >.[--->+<]>-.+[-<+
|
||||
]-<[-]>>>>]<[<<<<<<<++++[++++>---<]>+.[++++>---<]>-.+++[->+++<]>++.+[--->+<]>+.+
|
||||
[---->+<]>+++.[--->+<]>-.[-]+[-<+]-<[-]>>>>]<[<<<<<<<<<<+[--->++<]>+++.[->++++++
|
||||
+<]>.++++++.-[---->+<]>+++.++++++[->++<]>.+[--->+<]>.++++.++++[->+++<]>.--[--->+
|
||||
<]>.[--->+<]>-.+[-<+]-<[-]>>>>]<+[-<+]-<[>>->>>>>>+[-<<<<[-]<<[-]>>>>-[>>[-]+<<+
|
||||
<[-]<[-]<[-]<[-]-[----->+<]>---<,>[-<->]<[>>+>+<<<-]>>[<<+>>-]+++++++++[->-[<<]>
|
||||
]>>-]<<<<[-]>>>>[-]+<<<<<<[>>+>+<<<-]>>[<<+>>-]>>]>>-<<<[-]<<[<->-]<-[-[-[-[-[-[
|
||||
-[-[->>>]>>>]>>>]>>>]>>>]>>>]>>>]>>>]]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>[->++[-<+]->>>>>[>>>[>>>[+[-<+]-<<<<<<<<<[-]++[->+]->]]]+[-<+]->>>>>>>>>>>>>>[>
|
||||
>>[>>>[+[-<+]-<<<<<<<<<[-]++[->+]->]]]+[-<+]->>>>>>>>>>>>>>>>>>>>>>>[>>>[>>>[+[-
|
||||
<+]-<<<<<<<<<[-]++[->+]->]]]+[-<+]->>>>>[>>>>>>>>>[>>>>>>>>>[+[-<+]-<<<<<<<<<[-]
|
||||
++[->+]->]]]+[-<+]->>>>>>>>[>>>>>>>>>[>>>>>>>>>[+[-<+]-<<<<<<<<<[-]++[->+]->]]]+
|
||||
[-<+]->>>>>>>>>>>[>>>>>>>>>[>>>>>>>>>[+[-<+]-<<<<<<<<<[-]++[->+]->]]]+[-<+]->>>>
|
||||
>[>>>>>>>>>>>>[>>>>>>>>>>>>[+[-<+]-<<<<<<<<<[-]++[->+]->]]]+[-<+]->>>>>>>>>>>[>>
|
||||
>>>>[>>>>>>[+[-<+]-<<<<<<<<<[-]++[->+]->]]]+[-<+]-<<<<<<<<<-[++[->+]-<<<<<<<<<<[
|
||||
-]++[->+]->>>>[+[-<+]-<<<<<<<<<<[-]+[->+]->]+[-<+]->>>>>>>[+[-<+]-<<<<<<<<<<[-]+
|
||||
[->+]->]+[-<+]->>>>>>>>>>[+[-<+]-<<<<<<<<<<[-]+[->+]->]+[-<+]->>>>>>>>>>>>>[+[-<
|
||||
+]-<<<<<<<<<<[-]+[->+]->]+[-<+]->>>>>>>>>>>>>>>>[+[-<+]-<<<<<<<<<<[-]+[->+]->]+[
|
||||
-<+]->>>>>>>>>>>>>>>>>>>[+[-<+]-<<<<<<<<<<[-]+[->+]->]+[-<+]->>>>>>>>>>>>>>>>>>>
|
||||
>>>[+[-<+]-<<<<<<<<<<[-]+[->+]->]+[-<+]->>>>>>>>>>>>>>>>>>>>>>>>>[+[-<+]-<<<<<<<
|
||||
<<<[-]+[->+]->]+[-<+]->>>>>>>>>>>>>>>>>>>>>>>>>>>>[+[-<+]-<<<<<<<<<<[-]+[->+]->]
|
||||
+[-<+]-<<[-]>[-]+>>>>>>[>>>[>>[+[-<+]-<[-]<[-]++++[->+]->]]]>+[-<+]->>>>>[>>[>>>
|
||||
>[+[-<+]-<[-]<[-]+++[->+]->]]]>+[-<+]->>>>[>>>>[>>>[+[-<+]-<[-]<[-]++[->+]->]]]>
|
||||
+[-<+]->>>>>>>>>>>>>>[>>>[>>[+[-<+]-<[-]<[-]+++++++[->+]->]]]>+[-<+]->>>>>>>>>>>
|
||||
>>>[>>[>>>>[+[-<+]-<[-]<[-]++++++[->+]->]]]>+[-<+]->>>>>>>>>>>>>[>>>>[>>>[+[-<+]
|
||||
-<[-]<[-]+++++[->+]->]]]>+[-<+]->>>>>>>>>>>>>>>>>>>>>>>[>>>[>>[+[-<+]-<[-]<[-]++
|
||||
++++++++[->+]->]]]>+[-<+]->>>>>>>>>>>>>>>>>>>>>>>[>>[>>>>[+[-<+]-<[-]<[-]+++++++
|
||||
++[->+]->]]]>+[-<+]->>>>>>>>>>>>>>>>>>>>>>[>>>>[>>>[+[-<+]-<[-]<[-]++++++++[->+]
|
||||
->]]]>+[-<+]->>>>>[>>>>>>>>>[>>>>>>>>[+[-<+]-<[-]<[-]++++++++[->+]->]]]>+[-<+]->
|
||||
>>>>[>>>>>>>>[>>>>>>>>>>[+[-<+]-<[-]<[-]+++++[->+]->]]]>+[-<+]->>>>[>>>>>>>>>>[>
|
||||
>>>>>>>>[+[-<+]-<[-]<[-]++[->+]->]]]>+[-<+]->>>>>>>>[>>>>>>>>>[>>>>>>>>[+[-<+]-<
|
||||
[-]<[-]+++++++++[->+]->]]]>+[-<+]->>>>>>>>[>>>>>>>>[>>>>>>>>>>[+[-<+]-<[-]<[-]++
|
||||
++++[->+]->]]]>+[-<+]->>>>>>>[>>>>>>>>>>[>>>>>>>>>[+[-<+]-<[-]<[-]+++[->+]->]]]>
|
||||
+[-<+]->>>>>>>>>>>[>>>>>>>>>[>>>>>>>>[+[-<+]-<[-]<[-]++++++++++[->+]->]]]>+[-<+]
|
||||
->>>>>>>>>>>[>>>>>>>>[>>>>>>>>>>[+[-<+]-<[-]<[-]+++++++[->+]->]]]>+[-<+]->>>>>>>
|
||||
>>>[>>>>>>>>>>[>>>>>>>>>[+[-<+]-<[-]<[-]++++[->+]->]]]>+[-<+]->>>>>[>>>>>>>>>>>>
|
||||
[>>>>>>>>>>>[+[-<+]-<[-]<[-]++++++++++[->+]->]]]>+[-<+]->>>>[>>>>>>>>>>>>>[>>>>>
|
||||
>>>>>>>[+[-<+]-<[-]<[-]++[->+]->]]]>+[-<+]->>>>>>>>>>>[>>>>>>[>>>>>[+[-<+]-<[-]<
|
||||
[-]++++++++[->+]->]]]>+[-<+]->>>>>>>>>>[>>>>>>>[>>>>>>[+[-<+]-<[-]<[-]++++[->+]-
|
||||
>]]]>+[-<+]->>>>>>[>>>[>[+[-<+]-<[-]<[-]++++[->+]->]]]>+[-<+]->>>>>>[>[>>>>>[+[-
|
||||
<+]-<[-]<[-]+++[->+]->]]]>+[-<+]->>>>[>>>>>[>>>[+[-<+]-<[-]<[-]++[->+]->]]]>+[-<
|
||||
+]->>>>>>>>>>>>>>>[>>>[>[+[-<+]-<[-]<[-]+++++++[->+]->]]]>+[-<+]->>>>>>>>>>>>>>>
|
||||
[>[>>>>>[+[-<+]-<[-]<[-]++++++[->+]->]]]>+[-<+]->>>>>>>>>>>>>[>>>>>[>>>[+[-<+]-<
|
||||
[-]<[-]+++++[->+]->]]]>+[-<+]->>>>>>>>>>>>>>>>>>>>>>>>[>>>[>[+[-<+]-<[-]<[-]++++
|
||||
++++++[->+]->]]]>+[-<+]->>>>>>>>>>>>>>>>>>>>>>>>[>[>>>>>[+[-<+]-<[-]<[-]++++++++
|
||||
+[->+]->]]]>+[-<+]->>>>>>>>>>>>>>>>>>>>>>[>>>>>[>>>[+[-<+]-<[-]<[-]++++++++[->+]
|
||||
->]]]>+[-<+]->>>>>>[>>>>>>>>>[>>>>>>>[+[-<+]-<[-]<[-]++++++++[->+]->]]]>+[-<+]->
|
||||
>>>>>[>>>>>>>[>>>>>>>>>>>[+[-<+]-<[-]<[-]+++++[->+]->]]]>+[-<+]->>>>[>>>>>>>>>>>
|
||||
[>>>>>>>>>[+[-<+]-<[-]<[-]++[->+]->]]]>+[-<+]->>>>>>>>>[>>>>>>>>>[>>>>>>>[+[-<+]
|
||||
-<[-]<[-]+++++++++[->+]->]]]>+[-<+]->>>>>>>>>[>>>>>>>[>>>>>>>>>>>[+[-<+]-<[-]<[-
|
||||
]++++++[->+]->]]]>+[-<+]->>>>>>>[>>>>>>>>>>>[>>>>>>>>>[+[-<+]-<[-]<[-]+++[->+]->
|
||||
]]]>+[-<+]->>>>>>>>>>>>[>>>>>>>>>[>>>>>>>[+[-<+]-<[-]<[-]++++++++++[->+]->]]]>+[
|
||||
-<+]->>>>>>>>>>>>[>>>>>>>[>>>>>>>>>>>[+[-<+]-<[-]<[-]+++++++[->+]->]]]>+[-<+]->>
|
||||
>>>>>>>>[>>>>>>>>>>>[>>>>>>>>>[+[-<+]-<[-]<[-]++++[->+]->]]]>+[-<+]->>>>>>[>>>>>
|
||||
>>>>>>>[>>>>>>>>>>[+[-<+]-<[-]<[-]++++++++++[->+]->]]]>+[-<+]->>>>[>>>>>>>>>>>>>
|
||||
>[>>>>>>>>>>>>[+[-<+]-<[-]<[-]++[->+]->]]]>+[-<+]->>>>>>>>>>>>[>>>>>>[>>>>[+[-<+
|
||||
]-<[-]<[-]++++++++[->+]->]]]>+[-<+]->>>>>>>>>>[>>>>>>>>[>>>>>>[+[-<+]-<[-]<[-]++
|
||||
++[->+]->]]]>+[-<+]-<[>>+[-<+]->>>>>>>>>>>>>>>>>>>>>>>>>>>>[+[-<+]-<[-]<[-]+++++
|
||||
+++++[->+]->]+[-<+]->>>>>>>>>>>>>>>>>>>>>>[+[-<+]-<[-]<[-]++++++++[->+]->]+[-<+]
|
||||
->>>>>>>>>>[+[-<+]-<[-]<[-]++++[->+]->]+[-<+]->>>>[+[-<+]-<[-]<[-]++[->+]->]+[-<
|
||||
+]->>>>>>>>>>>>>>>>>>>>>>>>>[+[-<+]-<[-]<[-]+++++++++[->+]->]+[-<+]->>>>>>>>>>>>
|
||||
>>>>>>>[+[-<+]-<[-]<[-]+++++++[->+]->]+[-<+]->>>>>>>>>>>>>[+[-<+]-<[-]<[-]+++++[
|
||||
->+]->]+[-<+]->>>>>>>[+[-<+]-<[-]<[-]+++[->+]->]+[-<+]->>>>>>>>>>>>>>>>[+[-<+]-<
|
||||
[-]<[-]++++++[->+]->]+[-<+]->]>>+[-<+]-<<<<[+[->+]->>>>>>>>>>>>>>>>>[+[-<+]-<[-]
|
||||
<[-]++[->+]->]+[-<+]->]>>>>+[-<+]-<<[>>>+[-<+]-<[-]<[+[-<+]->++[->+]-<<-]+[-<+]-
|
||||
>-[-[-[-[-[-[-[-[->>>]>>>]>>>]>>>]>>>]>>>]>>>]>>>]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>->>++[-<+]->]>>>>+[-<+]-<<[-]>>>+[-<+]-<<<<[-]>>>>>+[-<+]->>>>>>[>>
|
||||
>[>>>[+[-<+]-<<<<<<<<<<<[-]++[->+]->]]]+[-<+]->>>>>>>>>>>>>>>[>>>[>>>[+[-<+]-<<<
|
||||
<<<<<<<<[-]++[->+]->]]]+[-<+]->>>>>>>>>>>>>>>>>>>>>>>>[>>>[>>>[+[-<+]-<<<<<<<<<<
|
||||
<[-]++[->+]->]]]+[-<+]->>>>>>[>>>>>>>>>[>>>>>>>>>[+[-<+]-<<<<<<<<<<<[-]++[->+]->
|
||||
]]]+[-<+]->>>>>>>>>[>>>>>>>>>[>>>>>>>>>[+[-<+]-<<<<<<<<<<<[-]++[->+]->]]]+[-<+]-
|
||||
>>>>>>>>>>>>[>>>>>>>>>[>>>>>>>>>[+[-<+]-<<<<<<<<<<<[-]++[->+]->]]]+[-<+]->>>>>>[
|
||||
>>>>>>>>>>>>[>>>>>>>>>>>>[+[-<+]-<<<<<<<<<<<[-]++[->+]->]]]+[-<+]->>>>>>>>>>>>[>
|
||||
>>>>>[>>>>>>[+[-<+]-<<<<<<<<<<<[-]++[->+]->]]]+[-<+]-<[-]]++[->+]->]+[-<+]-<+[
|
||||
-<+]-<]>>+[->+]->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+[-[-]<+]-<+[-[-]<+]-<+>]
|
||||
"""
|
||||
|
||||
|
||||
|
||||
# Hello World
|
||||
#Prog="++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++."
|
||||
|
||||
# Sierpinski
|
||||
Prog="""
|
||||
++++++++[>+>++++<<-]>++>>+<[-[>>+<<-]+>>]>+[
|
||||
-<<<[
|
||||
->[+[-]+>++>>>-<<]<[<]>>++++++[<<+++++>>-]+<<++.[-]<<
|
||||
]>.>+[>>]>+
|
||||
]"""
|
||||
|
||||
|
||||
|
||||
|
||||
buf=""
|
||||
def output(t):
|
||||
global buf
|
||||
buf+=t
|
||||
buf=buf[-(16*80):]
|
||||
ugfx.clear()
|
||||
lines=buf.split("\n")
|
||||
lines=lines[-16:]
|
||||
for i,v in enumerate(lines):
|
||||
ugfx.text(5,i*20+5, v+" ", ugfx.BLACK)
|
||||
|
||||
lastpushed=0
|
||||
def pushed(n):
|
||||
global Tape, TP, waiting
|
||||
if (waiting):
|
||||
output(n+" \n")
|
||||
Tape[TP]=ord(n)
|
||||
waiting=False
|
||||
|
||||
|
||||
|
||||
Buttons.enable_interrupt(Buttons.BTN_1, lambda button_id:pushed("1"), on_press=True, on_release=False)
|
||||
Buttons.enable_interrupt(Buttons.BTN_2, lambda button_id:pushed("2"), on_press=True, on_release=False)
|
||||
Buttons.enable_interrupt(Buttons.BTN_3, lambda button_id:pushed("3"), on_press=True, on_release=False)
|
||||
Buttons.enable_interrupt(Buttons.BTN_4, lambda button_id:pushed("4"), on_press=True, on_release=False)
|
||||
Buttons.enable_interrupt(Buttons.BTN_5, lambda button_id:pushed("5"), on_press=True, on_release=False)
|
||||
Buttons.enable_interrupt(Buttons.BTN_6, lambda button_id:pushed("6"), on_press=True, on_release=False)
|
||||
Buttons.enable_interrupt(Buttons.BTN_7, lambda button_id:pushed("7"), on_press=True, on_release=False)
|
||||
Buttons.enable_interrupt(Buttons.BTN_8, lambda button_id:pushed("8"), on_press=True, on_release=False)
|
||||
Buttons.enable_interrupt(Buttons.BTN_9, lambda button_id:pushed("9"), on_press=True, on_release=False)
|
||||
Buttons.enable_interrupt(Buttons.BTN_0, lambda button_id:pushed("0"), on_press=True, on_release=False)
|
||||
|
||||
|
||||
|
||||
output("Loading...")
|
||||
|
||||
|
||||
|
||||
|
||||
waiting=False
|
||||
Prog+='\0'
|
||||
Tape=[0]*256
|
||||
PP=-1
|
||||
TP=0
|
||||
while True:
|
||||
if (waiting):
|
||||
sleep_ms(200)
|
||||
else:
|
||||
PP=PP+1
|
||||
if (PP>=len(Prog)):
|
||||
waiting=True
|
||||
output("END!")
|
||||
elif (Prog[PP]=="+"):
|
||||
Tape[TP]=Tape[TP]+1
|
||||
elif (Prog[PP] =="-"):
|
||||
Tape[TP]=Tape[TP]-1
|
||||
elif (Prog[PP] ==">"):
|
||||
TP=TP+1
|
||||
elif (Prog[PP] =="<"):
|
||||
TP=TP-1
|
||||
elif (Prog[PP] =="."):
|
||||
output(chr(Tape[TP]))
|
||||
elif (Prog[PP] ==","):
|
||||
waiting=True
|
||||
elif (Prog[PP] =="["):
|
||||
if (Tape[TP]==0):
|
||||
depth=1
|
||||
while (depth>0):
|
||||
PP=PP+1
|
||||
if (Prog[PP]=="]"):
|
||||
depth = depth - 1
|
||||
if (Prog[PP]=="["):
|
||||
depth = depth + 1
|
||||
elif (Prog[PP] =="]"):
|
||||
if (Tape[TP]!=0):
|
||||
depth=1
|
||||
while (depth>0):
|
||||
PP=PP-1
|
||||
if (Prog[PP]=="]"):
|
||||
depth = depth + 1
|
||||
if (Prog[PP]=="["):
|
||||
depth = depth - 1
|
||||
|
|
@ -0,0 +1,141 @@
|
|||
"""App to use the badge as a (handset profile only) bluetooth speaker"""
|
||||
|
||||
___name___ = "Bluetooth Speaker"
|
||||
___license___ = "MIT"
|
||||
___dependencies___ = ["ugfx_helper", "sim800", "dialogs", "buttons", "app"]
|
||||
___categories___ = ["Sound"]
|
||||
|
||||
|
||||
import ugfx_helper, ugfx
|
||||
import app
|
||||
import sim800
|
||||
from dialogs import *
|
||||
import buttons
|
||||
|
||||
BLUETOOTH_NAME = "BadgeSpeaker"
|
||||
|
||||
g_paired = False
|
||||
|
||||
|
||||
def pairing_dialog(scan_timeout_s=10):
|
||||
''' Show BLE devices to pair with and connect. Returns True if paired, False if failed '''
|
||||
waiting_message = WaitingMessage("Scanning for bluetooth devices for %s seconds"%scan_timeout_s, "Scanning")
|
||||
|
||||
|
||||
devices = sim800.btscan(int(scan_timeout_s * 1000))
|
||||
|
||||
waiting_message.destroy()
|
||||
|
||||
# List format is [id, name, addr, rssi]. FIXME: Only returns 1 item?
|
||||
try:
|
||||
devices_prompts = [{'title': v[1], 'id': v[0]} for v in devices]
|
||||
except TypeError: #Only one device found. #TODO: Not very neat
|
||||
devices_prompts = [{'title':devices[1] ,'id':devices[0]},]
|
||||
|
||||
#TODO: Fix non printable chars in device names
|
||||
|
||||
option = prompt_option(devices_prompts, title="Devices Found", select_text="Select", none_text="Rescan")
|
||||
|
||||
if option:
|
||||
sim800.btpair(option['id'])
|
||||
passcode = sim800.btparingpasscode()
|
||||
correct_passcode = prompt_boolean(passcode, title="Started connection from other device?", font=FONT_MEDIUM_BOLD)
|
||||
|
||||
if correct_passcode:
|
||||
sim800.btpairconfirm() #TODO: 4 number passcodes?
|
||||
return True
|
||||
|
||||
else:
|
||||
sim800.btpairreject()
|
||||
return False
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def pairing_callback(param):
|
||||
''' Callback for incoming pairing request '''
|
||||
global g_paired
|
||||
accept = prompt_boolean("Accept pairing request from %s"%param, title="Incoming pairing")
|
||||
if accept:
|
||||
sim800.btpairconfirm(0000)
|
||||
# Check if we did pair
|
||||
if len(sim800.btpaired()) > 1:
|
||||
g_paired = True
|
||||
else:
|
||||
sim800.btpairreject()
|
||||
|
||||
|
||||
def set_simple_pairing():
|
||||
''' Set pairing mode to 4 digit pin, default 0000 '''
|
||||
sim800.command("AT+BTPAIRCFG=1,0000", 1000, "OK") # TODO: Error checking?
|
||||
|
||||
|
||||
#Initialise
|
||||
ugfx_helper.init()
|
||||
ugfx.init()
|
||||
ugfx.clear()
|
||||
|
||||
ugfx.text(5,5, "Powering Up SIM800", ugfx.BLACK)
|
||||
sim800.poweron()
|
||||
ugfx.clear()
|
||||
|
||||
ugfx.text(5,5, "Enabling Bluetooth", ugfx.BLACK)
|
||||
sim800.btpoweron()
|
||||
sim800.btname(BLUETOOTH_NAME)
|
||||
sim800.poweroff()
|
||||
sim800.poweron()
|
||||
sim800.btpoweron() # Needs a full cycle to have an effect
|
||||
sim800.btvisible(True)
|
||||
|
||||
# Set pairing mode
|
||||
set_simple_pairing()
|
||||
|
||||
ugfx.text(5,20, "Addr: %s " % sim800.btaddress(), ugfx.BLACK)
|
||||
ugfx.text(5,35, "Name: %s " % sim800.btname(), ugfx.BLACK)
|
||||
ugfx.clear()
|
||||
|
||||
# Register pairings callback
|
||||
sim800.registercallback("+BTPAIRING:", pairing_callback)
|
||||
|
||||
clear_pairing = prompt_boolean("Delete all bluetooth pairings?",title="Clear Pairings?", true_text="Yes", false_text="No")
|
||||
|
||||
if clear_pairing:
|
||||
sim800.btunpair(0) #0 = clear every pairing
|
||||
|
||||
# Start main loop
|
||||
ugfx.clear()
|
||||
ugfx.Label(5,5, 220, 200, "Connect to %s \n Passcode = 0000 \n Press menu to exit" % BLUETOOTH_NAME)
|
||||
|
||||
connected = True
|
||||
|
||||
while(True):
|
||||
|
||||
# Check for pairing button
|
||||
if (buttons.is_triggered(buttons.Buttons.BTN_1)):
|
||||
pairing_dialog()
|
||||
|
||||
# Check for exit button
|
||||
if (buttons.is_triggered(buttons.Buttons.BTN_Menu)):
|
||||
sim800.btpoweroff()
|
||||
app.restart_to_default()
|
||||
|
||||
num_connections = len(sim800.btconnected())
|
||||
|
||||
if (connected == False) and (num_connections > 0): # Gained connection
|
||||
ugfx.area(0,220,240,320, ugfx.BLACK) #Blank bottom of screen
|
||||
print(sim800.btconnected())
|
||||
sim800.speakervolume(100)
|
||||
sim800.btvoicevolume(100)
|
||||
ugfx.set_default_font(ugfx.FONT_TITLE)
|
||||
ugfx.text(5,230,"CONNECTED!", ugfx.GREEN)
|
||||
ugfx.set_default_font(ugfx.FONT_SMALL)
|
||||
connected = True
|
||||
|
||||
elif (connected == True) and (num_connections == 0): # Lost connection
|
||||
ugfx.area(0,220,240,320, ugfx.BLACK) #Blank bottom of screen
|
||||
ugfx.set_default_font(ugfx.FONT_TITLE)
|
||||
ugfx.text(5,230,"DISCONNECTED", ugfx.RED)
|
||||
ugfx.set_default_font(ugfx.FONT_SMALL)
|
||||
connected = False
|
||||
|
||||
sleep.wfi()
|
|
@ -1,9 +1,9 @@
|
|||
"""Breakout!"""
|
||||
|
||||
___name___ = "Breakout"
|
||||
___title___ = "Breakout"
|
||||
___license___ = "MIT"
|
||||
___categories___ = ["Games"]
|
||||
___dependencies___ = ["app", "ugfx_helper", "random", "buttons"]
|
||||
___dependencies___ = ["app", "ugfx_helper", "buttons"]
|
||||
|
||||
from tilda import Buttons
|
||||
import ugfx, ugfx_helper, dialogs
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
"""Scan for and display nearby bluetooth devices"""
|
||||
|
||||
___name___ = "Bluetooth Scan"
|
||||
___title___ = "Bluetooth Scan"
|
||||
___license___ = "MIT"
|
||||
___dependencies___ = ["sleep", "app", "sim800"]
|
||||
___categories___ = ["Other", "System"]
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
''' Random card generator, includes Base Set, The First Expansion, The Second Expansion, The Third Expansion, The Fourth Expansion, The Fifth Expansion, The Sixth Expansion, Green Box Expansion, 90s Nostalgia Pack, Box Expansion, Fantasy Pack, Food Pack, Science Pack and World Wide Web Pack '''
|
||||
|
||||
___name___ = "Cards Against EMF"
|
||||
___license___ = ["MIT"]
|
||||
___dependencies___ = ["ugfx_helper", "sleep"]
|
||||
___categories___ = ["Games"]
|
||||
___bootstrapped___ = False # Whether or not apps get downloaded on first install. Defaults to "False", mostly likely you won't have to use this at all.
|
||||
|
||||
import ugfx, json, random
|
||||
|
||||
from tilda import Buttons
|
||||
from app import restart_to_default
|
||||
|
||||
ugfx.init()
|
||||
ugfx.clear()
|
||||
ugfx.text(10, 10, "CARDS AGAINST EMF", ugfx.BLACK)
|
||||
ugfx.text(10, 40, "A for a question", ugfx.BLACK)
|
||||
ugfx.text(10, 60, "B for an answer", ugfx.BLACK)
|
||||
ugfx.text(10, 80, "MENU to exit", ugfx.BLACK)
|
||||
|
||||
b=ugfx.Style()
|
||||
b.set_background(ugfx.BLACK)
|
||||
b.set_enabled([ugfx.WHITE, ugfx.BLACK, ugfx.BLACK, ugfx.BLACK]) # sets the style for when something is enabled
|
||||
w=ugfx.Style()
|
||||
w.set_background(ugfx.WHITE)
|
||||
|
||||
with open("cards_against_emf/cards.json") as data:
|
||||
d = json.load(data)
|
||||
|
||||
def get_black():
|
||||
x = random.randint(1, 320)
|
||||
ugfx.clear(ugfx.html_color(0x000000))
|
||||
text = str(d["blackCards"][x]["text"])
|
||||
ugfx.Label(0, 0, 240, 400, text, style=b)
|
||||
|
||||
def get_white():
|
||||
y = random.randint(1, 1271)
|
||||
ugfx.clear(ugfx.html_color(0xffffff))
|
||||
text = str(d["whiteCards"][y])
|
||||
ugfx.Label(0, 0, 240, 400, text, style=w)
|
||||
|
||||
Buttons.enable_interrupt(
|
||||
Buttons.BTN_A,
|
||||
lambda button_id:get_black(),
|
||||
on_press=True,
|
||||
on_release=False)
|
||||
|
||||
Buttons.enable_interrupt(
|
||||
Buttons.BTN_B,
|
||||
lambda button_id:get_white(),
|
||||
on_press=True,
|
||||
on_release=False)
|
||||
|
||||
Buttons.enable_interrupt(
|
||||
Buttons.BTN_Menu,
|
||||
lambda button_id:restart_to_default(),
|
||||
on_press=True,
|
||||
on_release=False)
|
|
@ -3,7 +3,7 @@ Clone of the default homescreen for the Tilda Mk4.
|
|||
Shows the EMF homescreen and a picture loaded on the badge alternately.
|
||||
"""
|
||||
|
||||
___name___ = "Custom Image Home"
|
||||
___title___ = "Custom Image Home"
|
||||
___license___ = "MIT"
|
||||
___categories___ = ["Homescreens"]
|
||||
___dependencies___ = ["homescreen", "shared/logo.png", "shared/sponsors.png"]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
"""This is a dowsing rod for WiFi APs"""
|
||||
|
||||
___name___ = "Dowsing Rod"
|
||||
___title___ = "Dowsing Rod"
|
||||
___license___ = "MIT"
|
||||
___dependencies___ = ["sleep", "app", "wifi", "sim800"]
|
||||
___categories___ = ["EMF", "System"]
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
emfcampqueer theme by ganbariley
|
||||
"""
|
||||
|
||||
___name___ = "EMFCamp Rainbow Homescreen"
|
||||
___title___ = "EMFCamp Rainbow Homescreen"
|
||||
___license___ = "MIT"
|
||||
___categories___ = ["Homescreens"]
|
||||
___dependencies___ = ["homescreen"]
|
||||
|
@ -12,6 +12,12 @@ ___bootstrapped___ = False
|
|||
import ugfx
|
||||
from homescreen import *
|
||||
import time
|
||||
from tilda import Buttons
|
||||
from machine import Pin
|
||||
from machine import Neopix
|
||||
|
||||
torch = Pin(Pin.GPIO_FET)
|
||||
neo = Neopix()
|
||||
|
||||
# Padding for name
|
||||
intro_height = 30
|
||||
|
@ -26,6 +32,8 @@ logo_width = 56
|
|||
# Maximum length of name before downscaling
|
||||
max_name = 8
|
||||
|
||||
torch_on = False
|
||||
|
||||
# Background stuff
|
||||
init()
|
||||
ugfx.clear(ugfx.html_color(0x800080))
|
||||
|
@ -82,4 +90,13 @@ while True:
|
|||
if value_battery:
|
||||
text += "Battery: %s%%" % int(value_battery)
|
||||
status.text(text)
|
||||
if Buttons.is_pressed(Buttons.BTN_Star):
|
||||
if torch_on:
|
||||
torch_on = False
|
||||
torch.off()
|
||||
neo.display([0,0])
|
||||
else:
|
||||
torch_on = True
|
||||
torch.on()
|
||||
neo.display([0xffffff,0xffffff])
|
||||
sleep_or_exit(0.5)
|
||||
|
|
|
@ -4,7 +4,7 @@ Similar to the default homescreen, but the
|
|||
background is the enby flag. Based on Pride Flag Homescreen by marekventur
|
||||
"""
|
||||
|
||||
___name___ = "Enby"
|
||||
___title___ = "Enby"
|
||||
___license___ = "MIT"
|
||||
___categories___ = ["Homescreens"]
|
||||
___dependencies___ = ["homescreen", "app"]
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
"""Game of Life"""
|
||||
|
||||
___name___ = "Conway game of life"
|
||||
___title___ = "Conway game of life"
|
||||
___license___ = "MIT"
|
||||
___categories___ = ["Games"]
|
||||
___dependencies___ = ["app", "ugfx_helper", "random", "sleep", "buttons"]
|
||||
___dependencies___ = ["app", "ugfx_helper", "sleep", "buttons"]
|
||||
|
||||
import app, ugfx, ugfx_helper, buttons, sleep, time, random
|
||||
from tilda import Buttons
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
"""This is a simple hello world app"""
|
||||
|
||||
___name___ = "Hello World"
|
||||
___title___ = "Hello World"
|
||||
___license___ = "MIT"
|
||||
___dependencies___ = ["sleep", "app"]
|
||||
___categories___ = ["EMF"]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
"""Camp Holland app
|
||||
"""
|
||||
___name___ = "Holland"
|
||||
"""Camp Holland app"""
|
||||
|
||||
___title___ = "Holland"
|
||||
___license___ = "MIT"
|
||||
___dependencies___ = ["app", "sim800", "ugfx_helper"]
|
||||
___categories___ = ["Villages"]
|
||||
|
@ -98,6 +98,9 @@ freq = {
|
|||
"B": 4938,
|
||||
"C2": 5322,
|
||||
}
|
||||
|
||||
def cbButtonMenu(button_id):
|
||||
restart_to_default()
|
||||
|
||||
def cbButtonCall(button_id):
|
||||
sim800.speakervolume(100)
|
||||
|
@ -155,6 +158,12 @@ def cbButtonHash(button_id):
|
|||
global vip
|
||||
vip = False
|
||||
ugfx.display_image(0, 0, "holland/brenno.png")
|
||||
|
||||
Buttons.enable_interrupt(
|
||||
Buttons.BTN_Menu,
|
||||
cbButtonMenu,
|
||||
on_press=True,
|
||||
on_release=False);
|
||||
|
||||
Buttons.enable_interrupt(
|
||||
Buttons.BTN_Call,
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
"""This app connects to the Hologram service via GPRS displays recieved data on the screen and sets the neopixles"""
|
||||
|
||||
___title___ = "Hologram Demo"
|
||||
___license___ = "MIT"
|
||||
___dependencies___ = ["app", "sim800"]
|
||||
___categories___ = ["EMF", "System"]
|
||||
___bootstrapped___ = False
|
||||
|
||||
#import ugfx, os, time, sleep, app, sim800
|
||||
|
||||
import ugfx, app, sim800
|
||||
import os
|
||||
from tilda import Buttons
|
||||
from time import sleep
|
||||
from machine import Neopix
|
||||
|
||||
|
||||
n = Neopix()
|
||||
|
||||
ugfx.init()
|
||||
ugfx.clear()
|
||||
ugfx.set_default_font(ugfx.FONT_FIXED)
|
||||
|
||||
|
||||
def callback(data):
|
||||
payload=data.decode("utf-8")
|
||||
ugfx.Label(5, 100, 240, 15, payload)
|
||||
colour = int(payload)
|
||||
n.display([colour,colour])
|
||||
|
||||
print('Launching Hologram Demo')
|
||||
ugfx.Label(5, 20, 240, 15, "Starting....")
|
||||
sim800.setup_gprs()
|
||||
ugfx.Label(5, 20, 240, 15, "GPRS Ready")
|
||||
sim800.connect_gprs('hologram')
|
||||
ugfx.Label(5, 40, 240, 15, "GPRS Connected")
|
||||
sim800.start_server(4010, callback)
|
||||
ugfx.Label(5, 60, 240, 15, "Server Started")
|
||||
|
||||
|
||||
ugfx.Label(5, 300, 240, 15, "** Hold A or B or MENU to exit **")
|
||||
|
||||
|
||||
while (not Buttons.is_pressed(Buttons.BTN_A)) and (not Buttons.is_pressed(Buttons.BTN_B)) and (not Buttons.is_pressed(Buttons.BTN_Menu)):
|
||||
sleep(2)
|
||||
|
||||
ugfx.clear()
|
||||
ugfx.Label(5, 20, 240, 15, "Stopping....")
|
||||
sim800.stop_server()
|
||||
sim800.stop_gprs()
|
||||
app.restart_to_default()
|
After Width: | Height: | Size: 14 KiB |
|
@ -0,0 +1,125 @@
|
|||
"""Default homescreen
|
||||
|
||||
Hackedup awful code for a london aerospace themed badge
|
||||
"""
|
||||
|
||||
___name___ = "Aerospace Badge"
|
||||
___license___ = "MIT"
|
||||
___categories___ = ["Homescreens"]
|
||||
___dependencies___ = ["homescreen", "wifi", "http", "ugfx_helper", "sleep"]
|
||||
___launchable___ = False
|
||||
|
||||
import ugfx, random, time, wifi, http, math
|
||||
from tilda import LED, Buttons
|
||||
from machine import Neopix
|
||||
from homescreen import *
|
||||
import time
|
||||
|
||||
|
||||
cycle = 0
|
||||
#colourList = [0xff0000,0x00ff00]
|
||||
colourList = [0xFF0000, 0xFFFFFF, 0x00FF00, 0x0000FF, 0xFFF000, 0xD800FF, 0xFF008F, 0x00FFF7]
|
||||
|
||||
n = Neopix()
|
||||
|
||||
# We ❤️ our sponsors
|
||||
ugfx.display_image(0, 0, "home_aerospace/aerospace-logo.png")
|
||||
wait = 5
|
||||
while wait:
|
||||
wait-=1
|
||||
sleep_or_exit(0.5)
|
||||
|
||||
def ledChange():
|
||||
colourNum1 = colourList[random.randint(0,len(colourList)-1)]
|
||||
colourNum2 = colourList[random.randint(0,len(colourList)-1)]
|
||||
while colourNum1 == colourNum2:
|
||||
colourNum2 = colourList[random.randint(0,len(colourList)-1)]
|
||||
n.display([colourNum1,colourNum2])
|
||||
|
||||
|
||||
# Padding for name
|
||||
intro_height = 30
|
||||
intro_text = "London Aerospace"
|
||||
intro_width = 200
|
||||
intro_position_left = 0
|
||||
name_height = 60
|
||||
status_height = 30
|
||||
info_height = 30
|
||||
tick = 0
|
||||
logo_path = "home_aerospace/aerospace-logo.png"
|
||||
logo_height = 250
|
||||
logo_width = 250
|
||||
aerospace_text = "London Aerospace Yo"
|
||||
|
||||
# Maximum length of name before downscaling
|
||||
max_name = 8
|
||||
|
||||
# Background stuff
|
||||
init()
|
||||
ugfx.clear(ugfx.html_color(0xFFFFFF))
|
||||
|
||||
# Colour stuff
|
||||
style = ugfx.Style()
|
||||
style.set_enabled([ugfx.BLACK, ugfx.html_color(0xFFFFFF), ugfx.html_color(0xFFFFFF), ugfx.html_color(0xFFFFFF)])
|
||||
style.set_background(ugfx.html_color(0xFFFFFF))
|
||||
ugfx.set_default_style(style)
|
||||
|
||||
# Draw for people to see
|
||||
ugfx.orientation(90)
|
||||
# Logo stuff
|
||||
ugfx.display_image(
|
||||
int((ugfx.width() - logo_width) / 2),
|
||||
int((ugfx.height() - logo_height) / 2 - 20),
|
||||
logo_path
|
||||
)
|
||||
|
||||
# Draw introduction
|
||||
ugfx.set_default_font(ugfx.FONT_TITLE)
|
||||
intro_object = ugfx.Label(0, ugfx.height() - name_height - intro_height, ugfx.width(), intro_height, intro_text, justification=ugfx.Label.CENTER)
|
||||
# Process name
|
||||
name_setting = name("Set your name in the settings app")
|
||||
if len(name_setting) <= max_name:
|
||||
ugfx.set_default_font(ugfx.FONT_NAME)
|
||||
else:
|
||||
ugfx.set_default_font(ugfx.FONT_MEDIUM_BOLD)
|
||||
# Draw name
|
||||
ugfx.Label(0, ugfx.height() - name_height, ugfx.width(), name_height, name_setting, justification=ugfx.Label.CENTER)
|
||||
|
||||
|
||||
|
||||
# Draw for wearer to see
|
||||
ugfx.orientation(270)
|
||||
# Title
|
||||
ugfx.set_default_font(ugfx.FONT_TITLE)
|
||||
# info
|
||||
|
||||
ugfx.set_default_font(ugfx.FONT_SMALL)
|
||||
status = ugfx.Label(0, ugfx.height() - 30, ugfx.width(), status_height, "", justification=ugfx.Label.CENTER)
|
||||
status.text('BATTERY INCOMING')
|
||||
|
||||
# update loop
|
||||
while True:
|
||||
text = "";
|
||||
|
||||
if math.fmod(tick, 100) == 0:
|
||||
value_wifi_strength = wifi_strength()
|
||||
value_battery = battery()
|
||||
if value_wifi_strength:
|
||||
text += "Wi-Fi: %s%%, " % int(value_wifi_strength)
|
||||
if value_battery:
|
||||
text += "Battery: %s%%" % int(value_battery)
|
||||
status.text(text)
|
||||
tick +=1
|
||||
|
||||
# if intro_position_left > -intro_width:
|
||||
# intro_position_left -= 1
|
||||
# intro_object.x(
|
||||
# intro_position_left
|
||||
# )
|
||||
# else:
|
||||
# intro_object.x(0)
|
||||
# intro_position_left = 0
|
||||
|
||||
ledChange()
|
||||
|
||||
sleep_or_exit(0.05)
|
|
@ -5,7 +5,7 @@ It gets automatically installed when a badge is
|
|||
newly activated or reset.
|
||||
"""
|
||||
|
||||
___name___ = "Homescreen (Default)"
|
||||
___title___ = "Homescreen (Default)"
|
||||
___license___ = "MIT"
|
||||
___categories___ = ["Homescreens"]
|
||||
___dependencies___ = ["homescreen", "shared/logo.png", "shared/sponsors.png"]
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
This is a modified version of the default homescreen that allows you to set a callsign
|
||||
"""
|
||||
|
||||
___name___ = "Amateur Radio Homescreen"
|
||||
___title___ = "Amateur Radio Homescreen"
|
||||
___license___ = "MIT"
|
||||
___categories___ = ["Homescreens"]
|
||||
___dependencies___ = ["homescreen"]
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
"""Default homescreen
|
||||
|
||||
This is the default homescreen for the Tilda Mk4.
|
||||
It gets automatically installed when a badge is
|
||||
newly activated or reset.
|
||||
"""
|
||||
|
||||
___title___ = "Homescreen (PyCon)"
|
||||
___license___ = "MIT"
|
||||
___categories___ = ["Homescreens"]
|
||||
___dependencies___ = ["homescreen"]
|
||||
___launchable___ = False
|
||||
___bootstrapped___ = True
|
||||
|
||||
import ugfx
|
||||
from homescreen import *
|
||||
import time
|
||||
from tilda import Buttons
|
||||
|
||||
init()
|
||||
|
||||
# Padding for name
|
||||
intro_height = 30
|
||||
intro_text = "Hi! I'm"
|
||||
name_height = 60
|
||||
status_height = 20
|
||||
info_height = 30
|
||||
logo_path = "home_pycon/python_single.png"
|
||||
logo_height = 82
|
||||
logo_width = 55
|
||||
|
||||
# Maximum length of name before downscaling
|
||||
max_name = 8
|
||||
|
||||
# Background stuff
|
||||
bg_color = 0xfecb2f
|
||||
ugfx.clear(ugfx.html_color(bg_color))
|
||||
|
||||
# Colour stuff
|
||||
style = ugfx.Style()
|
||||
style.set_enabled([ugfx.BLACK, ugfx.html_color(bg_color), ugfx.html_color(bg_color), ugfx.html_color(bg_color)])
|
||||
style.set_background(ugfx.html_color(bg_color))
|
||||
ugfx.set_default_style(style)
|
||||
|
||||
# Draw for people to see
|
||||
ugfx.orientation(90)
|
||||
|
||||
# Logo stuff
|
||||
ugfx.display_image(
|
||||
int((ugfx.width() - logo_width) / 2),
|
||||
int((ugfx.height() - logo_height) / 2),
|
||||
logo_path
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
# Draw introduction
|
||||
ugfx.set_default_font(ugfx.FONT_TITLE)
|
||||
ugfx.Label(0, ugfx.height() - name_height - intro_height, ugfx.width(), intro_height, intro_text, justification=ugfx.Label.CENTER)
|
||||
# Process name
|
||||
name_setting = name("Set your name in the settings app")
|
||||
if len(name_setting) <= max_name:
|
||||
ugfx.set_default_font(ugfx.FONT_NAME)
|
||||
else:
|
||||
ugfx.set_default_font(ugfx.FONT_MEDIUM_BOLD)
|
||||
# Draw name
|
||||
ugfx.Label(0, ugfx.height() - name_height, ugfx.width(), name_height, name_setting, justification=ugfx.Label.CENTER)
|
||||
|
||||
|
||||
|
||||
# Draw for wearer to see
|
||||
ugfx.orientation(270)
|
||||
# Title
|
||||
ugfx.set_default_font(ugfx.FONT_TITLE)
|
||||
ugfx.Label(0, ugfx.height() - info_height * 2, ugfx.width(), info_height, "TiLDA Mk4", justification=ugfx.Label.CENTER)
|
||||
# info
|
||||
ugfx.Label(0, ugfx.height() - info_height, ugfx.width(), info_height, "Long Press MENU", justification=ugfx.Label.CENTER)
|
||||
|
||||
ugfx.set_default_font(ugfx.FONT_SMALL)
|
||||
status = ugfx.Label(0, ugfx.height() - info_height * 2 - status_height, ugfx.width(), status_height, "", justification=ugfx.Label.CENTER)
|
||||
|
||||
# update loop
|
||||
while True:
|
||||
text = "";
|
||||
value_wifi_strength = wifi_strength()
|
||||
value_battery = battery()
|
||||
if value_wifi_strength:
|
||||
text += "Wi-Fi: %s%%, " % int(value_wifi_strength)
|
||||
if value_battery:
|
||||
text += "Battery: %s%%" % int(value_battery)
|
||||
status.text(text)
|
||||
sleep_or_exit(0.5)
|
After Width: | Height: | Size: 963 B |
|
@ -3,7 +3,7 @@
|
|||
This is the Stratum 0 flavored homescreen for the Tilda Mk4.
|
||||
"""
|
||||
|
||||
___name___ = "Homescreen (Stratum 0)"
|
||||
___title___ = "Homescreen (Stratum 0)"
|
||||
___license___ = "MIT"
|
||||
___categories___ = ["Homescreens"]
|
||||
___dependencies___ = ["homescreen"]
|
||||
|
|
|
@ -5,7 +5,7 @@ Press 0 to go back to normal or 8 to show the flag.
|
|||
Hold * to activate all LEDs for use as a torch.
|
||||
"""
|
||||
|
||||
___name___ = "Homescreen (Trans)"
|
||||
___title___ = "Homescreen (Trans)"
|
||||
___license___ = "MIT"
|
||||
___categories___ = ["Homescreens"]
|
||||
___dependencies___ = ["homescreen", "shared/logo.png"]
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
"""Launcher for apps currently installed"""
|
||||
|
||||
___name___ = "Launcher"
|
||||
___title___ = "Launcher"
|
||||
___license___ = "MIT"
|
||||
___categories___ = ["System"]
|
||||
___categories___ = ["System", "Launcher"]
|
||||
___dependencies___ = ["dialogs", "app", "ugfx_helper"]
|
||||
___launchable___ = False
|
||||
___bootstrapped___ = True
|
||||
|
|
|
@ -34,6 +34,9 @@ class BadgeStore:
|
|||
def install(self, apps):
|
||||
return self._create_installers(self._call("install", {"apps": ",".join(apps)}))
|
||||
|
||||
def update(self, apps):
|
||||
return self._create_installers(self._call("update", {"apps": ",".join(apps)}))
|
||||
|
||||
def bootstrap(self):
|
||||
return self._create_installers(self._call("bootstrap"))
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ Values can be anything json can store, including a dict
|
|||
Usage:
|
||||
|
||||
import database
|
||||
with database.open() as db:
|
||||
with database.Database() as db:
|
||||
print(db.get("hello", "default"))
|
||||
db.set("foo", "world")
|
||||
db.delete("bar")
|
||||
|
|
|
@ -41,18 +41,30 @@ def prompt_boolean(text, title="TiLDA", true_text="Yes", false_text="No", font=F
|
|||
window = ugfx.Container(5, 5, width, height)
|
||||
window.show()
|
||||
ugfx.set_default_font(font)
|
||||
window.text(5, 10, title, TILDA_COLOR)
|
||||
window.line(0, 30, width, 30, ugfx.BLACK)
|
||||
window.text(5, 5, title, TILDA_COLOR)
|
||||
window.line(0, 25, width, 25, ugfx.BLACK)
|
||||
|
||||
if false_text:
|
||||
true_text = "A: " + true_text
|
||||
false_text = "B: " + false_text
|
||||
|
||||
ugfx.set_default_font(font)
|
||||
label = ugfx.Label(5, 30, width - 10, height - 80, text = text, parent=window)
|
||||
label = ugfx.Label(5, 30, width - 10, height - 80, text = text, parent=window, justification=4)
|
||||
|
||||
ugfx.set_default_font(FONT_MEDIUM_BOLD)
|
||||
button_yes = ugfx.Button(5, height - 40, width // 2 - 15 if false_text else width - 15, 30 , true_text, parent=window)
|
||||
button_no = ugfx.Button(width // 2 + 5, height - 40, width // 2 - 15, 30 , false_text, parent=window) if false_text else None
|
||||
button_yes = ugfx.Button(5, height - 40, width // 2 - 10 if false_text else width - 15, 30 , true_text, parent=window)
|
||||
button_no = ugfx.Button(width // 2, height - 40, width // 2 - 10, 30 , false_text, parent=window) if false_text else None
|
||||
|
||||
# Find newlines in label text to scroll.
|
||||
def find_all(a_str, sub):
|
||||
start = 0
|
||||
while True:
|
||||
start = a_str.find(sub, start)
|
||||
if start == -1: return
|
||||
yield start + 1 # Trap: \n becomes a single character, not 2.
|
||||
start += len(sub) # use start += 1 to find overlapping matches
|
||||
new_line_pos = [0] + list(find_all(text, '\n'))
|
||||
text_scroll_offset = 0
|
||||
|
||||
try:
|
||||
#button_yes.attach_input(ugfx.BTN_A,0) # todo: re-enable once working
|
||||
|
@ -64,6 +76,16 @@ def prompt_boolean(text, title="TiLDA", true_text="Yes", false_text="No", font=F
|
|||
sleep.wfi()
|
||||
if buttons.is_triggered(buttons.Buttons.BTN_A): return True
|
||||
if buttons.is_triggered(buttons.Buttons.BTN_B): return False
|
||||
# Allow scrolling by new lines.
|
||||
if buttons.is_triggered(buttons.Buttons.JOY_Down):
|
||||
if text_scroll_offset < len(new_line_pos)-1:
|
||||
text_scroll_offset = text_scroll_offset + 1
|
||||
label.text(text[new_line_pos[text_scroll_offset]:])
|
||||
|
||||
if buttons.is_triggered(buttons.Buttons.JOY_Up):
|
||||
if (text_scroll_offset > 0):
|
||||
text_scroll_offset=text_scroll_offset - 1
|
||||
label.text(text[new_line_pos[text_scroll_offset]:])
|
||||
|
||||
finally:
|
||||
window.hide()
|
||||
|
@ -129,7 +151,7 @@ def handle_keypad(edit, numeric):
|
|||
buttons.Buttons.BTN_6: ["m", "n", "o", "6"],
|
||||
buttons.Buttons.BTN_7: ["p", "q", "r", "s", "7"],
|
||||
buttons.Buttons.BTN_8: ["t", "u", "v", "8"],
|
||||
buttons.Buttons.BTN_9: ["w", "x", "y", "9"],
|
||||
buttons.Buttons.BTN_9: ["w", "x", "y", "z", "9"],
|
||||
buttons.Buttons.BTN_Hash: ["#"],
|
||||
buttons.Buttons.BTN_Star: ["*", "+"],
|
||||
}
|
||||
|
@ -167,9 +189,10 @@ def prompt_option(options, index=0, text = None, title=None, select_text="OK", n
|
|||
window = ugfx.Container(5, 5, ugfx.width() - 10, ugfx.height() - 10)
|
||||
window.show()
|
||||
|
||||
|
||||
list_y = 30
|
||||
if title:
|
||||
window.text(5, 10, title, TILDA_COLOR)
|
||||
window.text(5, 5, title, TILDA_COLOR)
|
||||
window.line(0, 25, ugfx.width() - 10, 25, ugfx.BLACK)
|
||||
list_y = 30
|
||||
if text:
|
||||
|
@ -179,14 +202,23 @@ def prompt_option(options, index=0, text = None, title=None, select_text="OK", n
|
|||
else:
|
||||
window.text(5, 10, text, ugfx.BLACK)
|
||||
|
||||
options_list = ugfx.List(5, list_y, ugfx.width() - 25, 260 - list_y, parent = window)
|
||||
options_list = ugfx.List(5, list_y, ugfx.width() - 24, 265 - list_y, parent = window)
|
||||
options_list.disable_draw()
|
||||
|
||||
optnum = 1
|
||||
for option in options:
|
||||
if isinstance(option, dict) and option["title"]:
|
||||
options_list.add_item(option["title"])
|
||||
title = option["title"]
|
||||
else:
|
||||
options_list.add_item(str(option))
|
||||
title = str(option)
|
||||
|
||||
if optnum < 11:
|
||||
# mod 10 to make 10th item numbered 0
|
||||
options_list.add_item("{}: {}".format((optnum % 10),title))
|
||||
else:
|
||||
options_list.add_item(" {}".format(title))
|
||||
optnum = optnum + 1
|
||||
|
||||
options_list.enable_draw()
|
||||
options_list.selected_index(index)
|
||||
|
||||
|
@ -195,7 +227,7 @@ def prompt_option(options, index=0, text = None, title=None, select_text="OK", n
|
|||
none_text = "B: " + none_text
|
||||
|
||||
button_select = ugfx.Button(5, ugfx.height() - 50, 105 if none_text else 200, 30 , select_text, parent=window)
|
||||
button_none = ugfx.Button(117, ugfx.height() - 50, 105, 30 , none_text, parent=window) if none_text else None
|
||||
button_none = ugfx.Button(116, ugfx.height() - 50, 105, 30 , none_text, parent=window) if none_text else None
|
||||
|
||||
try:
|
||||
while True:
|
||||
|
@ -260,9 +292,9 @@ class WaitingMessage:
|
|||
def __init__(self, text="Please Wait...", title="TiLDA"):
|
||||
self.window = ugfx.Container(30, 30, ugfx.width() - 60, ugfx.height() - 60)
|
||||
self.window.show()
|
||||
self.window.text(5, 10, title, TILDA_COLOR)
|
||||
self.window.line(0, 30, ugfx.width() - 60, 30, ugfx.BLACK)
|
||||
self.label = ugfx.Label(5, 40, self.window.width() - 10, ugfx.height() - 40, text = text, parent=self.window)
|
||||
self.window.text(5, 5, title, TILDA_COLOR)
|
||||
self.window.line(0, 25, ugfx.width() - 60, 25, ugfx.BLACK)
|
||||
self.label = ugfx.Label(5, 40, self.window.width() - 15, ugfx.height() - 40, text = text, parent=self.window)
|
||||
|
||||
# Indicator to show something is going on
|
||||
#self.indicator = ugfx.Label(ugfx.width() - 100, 0, 20, 20, text = "...", parent=self.window)
|
||||
|
|
|
@ -17,7 +17,7 @@ They also *may*:
|
|||
"""
|
||||
|
||||
___license___ = "MIT"
|
||||
___dependencies___ = ["database", "buttons", "random", "app", "sleep", "ugfx_helper", "wifi", "sim800"]
|
||||
___dependencies___ = ["database", "buttons", "app", "sleep", "ugfx_helper", "wifi", "sim800"]
|
||||
|
||||
import database, ugfx, random, buttons, tilda, sleep, ugfx_helper, wifi, time, sim800
|
||||
from app import App
|
||||
|
@ -51,7 +51,13 @@ def sleep_or_exit(interval = 0.5):
|
|||
# todo: do this better - check button multiple times and sleep for only a short while
|
||||
if buttons.is_triggered(tilda.Buttons.BTN_Menu):
|
||||
clean_up()
|
||||
App("launcher").boot()
|
||||
launcher = "launcher"
|
||||
try:
|
||||
with open("default_launcher.txt", "r") as dl:
|
||||
launcher=dl.readline()
|
||||
except OSError:
|
||||
pass
|
||||
App(launcher).boot()
|
||||
sleep.sleep(interval)
|
||||
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ import machine
|
|||
# (date(2000, 1, 1) - date(1900, 1, 1)).days * 24*60*60
|
||||
NTP_DELTA = 3155673600
|
||||
# With Mk3 Firmware an IP address string works 5%, hangs at socket.socket(..) 95%, could be a bug in 2016 upython?
|
||||
NTP_HOSTS = ["ntp-gps.emf.camp", "0.emfbadge.pool.ntp.org", "1.emfbadge.pool.ntp.org", "2.emfbadge.pool.ntp.org", "3.emfbadge.pool.ntp.org"]
|
||||
NTP_HOSTS = ["0.emfbadge.pool.ntp.org", "1.emfbadge.pool.ntp.org", "2.emfbadge.pool.ntp.org", "3.emfbadge.pool.ntp.org"]
|
||||
NTP_PORT = 123
|
||||
|
||||
def get_NTP_time():
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
"""Library to generate random numbers
|
||||
|
||||
Warning! Don't use this for anything important, it's probably biased
|
||||
"""
|
||||
|
||||
___license___ = "MIT"
|
||||
|
||||
# todo: simplify this by using "urandom"
|
||||
import os
|
||||
|
||||
_bigrand_bytes = 10
|
||||
_bigrand_max = pow(256, _bigrand_bytes)
|
||||
|
||||
def _bigrand():
|
||||
"""generates a random number between 0 (incl) and _bigrand_max (excl)"""
|
||||
base = 0
|
||||
for b in os.urandom(_bigrand_bytes):
|
||||
base = (base << 8) + b
|
||||
return base
|
||||
|
||||
def random():
|
||||
"""Return the next random floating point number in the range [0.0, 1.0)."""
|
||||
return _bigrand() / _bigrand_max
|
||||
|
||||
def randrange(start, stop=None):
|
||||
"""Return a randomly selected element from range(start, stop)"""
|
||||
if stop is None:
|
||||
stop = start
|
||||
start = 0
|
||||
return start + (_bigrand() * (stop - start) // _bigrand_max)
|
||||
|
||||
def randint(start, stop):
|
||||
"""Return a random integer N such that a <= N <= b."""
|
||||
return randrange(start, stop + 1)
|
||||
|
||||
def shuffle(seq):
|
||||
"""Shuffle the sequence x in place."""
|
||||
l = len(seq)
|
||||
for i in range(l):
|
||||
j = randrange(l)
|
||||
seq[i], seq[j] = seq[j], seq[i]
|
|
@ -25,6 +25,7 @@ dirtybuffer = False # Flag if the buffer could have residual end of reresponsesp
|
|||
|
||||
# A list of callback functions
|
||||
callbacks = []
|
||||
server_callback = None
|
||||
|
||||
# Globals for remembering callback data
|
||||
clip = ""
|
||||
|
@ -105,6 +106,12 @@ def processcallbacks(line):
|
|||
# Check for Bluetooth pairing request
|
||||
if line.startswith("+BTPAIRING:"):
|
||||
btpairing = line[11:].strip()
|
||||
# Handle TCP Server Data
|
||||
if line.startswith("+RECEIVE"):
|
||||
dlen = int(line.split(",")[2].rstrip(":"))+1
|
||||
payload = uart.read(dlen)
|
||||
if server_callback:
|
||||
micropython.schedule(server_callback, payload[1:])
|
||||
# Check for app callbacks
|
||||
for entry in callbacks:
|
||||
if line.startswith(entry[0]):
|
||||
|
@ -847,6 +854,28 @@ def callbuttonpressed_internal(nullparam=None):
|
|||
def endbuttonpressed_internal(nullparam=None):
|
||||
hangup()
|
||||
|
||||
#GPRS and TCP server functions
|
||||
|
||||
def setup_gprs():
|
||||
command("AT+CIPSHUT", response_timeout=60000, custom_endofdata="SHUT OK")
|
||||
command("AT+CGATT?", response_timeout=10000)
|
||||
command("AT+CIPMUX=1", response_timeout=10000)
|
||||
|
||||
def connect_gprs(apn):
|
||||
command("AT+CSTT=\""+apn+"\"", response_timeout=10000)
|
||||
command("AT+CIICR", response_timeout=10000)
|
||||
command("AT+CIFSR")
|
||||
|
||||
def stop_gprs():
|
||||
command("AT+CIPSHUT", response_timeout=60000, custom_endofdata="SHUT OK")
|
||||
|
||||
def start_server(port, callback):
|
||||
global server_callback
|
||||
server_callback = callback
|
||||
command("AT+CIPSERVER=1,"+str(port), response_timeout=10000)
|
||||
|
||||
def stop_server():
|
||||
command("AT+CIPSERVER=0", response_timeout=10000)
|
||||
|
||||
# Startup...
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
"""Tests for random lib"""
|
||||
|
||||
___license___ = "MIT"
|
||||
___dependencies___ = ["upip:unittest", "random"]
|
||||
___dependencies___ = ["upip:unittest"]
|
||||
|
||||
import unittest
|
||||
from random import *
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
"""View images from the EMF 2018 time-lapse camera
|
||||
"""
|
||||
___name___ = "Lobster Vision"
|
||||
___title___ = "Lobster Vision"
|
||||
___license___ = "MIT"
|
||||
___dependencies___ = ["app", "dialogs", "wifi", "buttons", "http", "ugfx_helper"]
|
||||
___categories___ = ["Other"]
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
Learn your personal lucky melody.
|
||||
"""
|
||||
|
||||
___name___ = "lucky_melody_machine"
|
||||
___title___ = "Lucky Melody Machine"
|
||||
___license___ = "WTFPL"
|
||||
___dependencies___ = ["app", "buttons", "dialogs", "speaker", "sleep", "ugfx_helper"]
|
||||
___categories___ = ["Sound"]
|
||||
|
|
|
@ -5,7 +5,7 @@ Gracefully reboot into main menu on Menu Press.
|
|||
Replay Track when user pushes a button.
|
||||
"""
|
||||
|
||||
___name___ = "Mario Theme"
|
||||
___title___ = "Mario Theme"
|
||||
___license___ = ""
|
||||
___categories___ = ["Sound"]
|
||||
___dependencies___ = ["speaker", "buttons", "ugfx_helper", "app", "wifi", "http", "sleep" ]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
"""Enables mass storage mode in a safe way"""
|
||||
|
||||
___name___ = "Mass Storage Enabler"
|
||||
___title___ = "Mass Storage Enabler"
|
||||
___license___ = "MIT"
|
||||
___dependencies___ = ["dialogs", "ugfx_helper"]
|
||||
___categories___ = ["EMF"]
|
||||
|
@ -11,12 +11,18 @@ import ugfx, tilda, ugfx_helper, dialogs, app, time
|
|||
ugfx_helper.init()
|
||||
ugfx.clear()
|
||||
|
||||
print("enabling USB storage...")
|
||||
tilda.storage_enable_usb()
|
||||
time.sleep(1)
|
||||
print("DONE")
|
||||
with dialogs.WaitingMessage(title="Mass Storage Enabled", text="You can now use the badge like a USB key.\nPlease safely eject afterwards. This app will close automatically."):
|
||||
print("Waiting for USB mass storage to be unmounted...")
|
||||
tilda.storage_disable_usb()
|
||||
user_agreed = dialogs.prompt_boolean("Note: enabling mass storage is slightly risky, as the badge may end up factory "
|
||||
"resetting even if you safely eject it. Do you want to continue?")
|
||||
|
||||
if user_agreed:
|
||||
print("enabling USB storage...")
|
||||
tilda.storage_enable_usb()
|
||||
time.sleep(1)
|
||||
print("DONE")
|
||||
with dialogs.WaitingMessage(title="Mass Storage Enabled", text="You can now use the badge like a USB key.\nPlease safely eject afterwards. This app will close automatically."):
|
||||
print("Waiting for USB mass storage to be unmounted...")
|
||||
tilda.storage_disable_usb()
|
||||
print("DONE")
|
||||
app.restart_to_default()
|
||||
else:
|
||||
app.restart_to_default()
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
"""This app tests all the onboard sensors and system info"""
|
||||
|
||||
___name___ = "Memobadge"
|
||||
___title___ = "Memobadge"
|
||||
___license___ = "MIT"
|
||||
___dependencies___ = ["app", "sim800", "sleep", "ugfx_helper"]
|
||||
___categories___ = ["Sound"]
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
"""Nyan Cat Animation! Rotate the screen with 'A'."""
|
||||
|
||||
___name___ = "nyan"
|
||||
___license___ = "MIT"
|
||||
___dependencies___ = ["sleep", "app", "ugfx_helper",
|
||||
"shared/nyan/0.png",
|
||||
"shared/nyan/1.png",
|
||||
"shared/nyan/2.png",
|
||||
"shared/nyan/3.png",
|
||||
"shared/nyan/4.png",
|
||||
"shared/nyan/5.png"]
|
||||
|
||||
___categories___ = ["Homescreens", "Other"]
|
||||
|
||||
import ugfx_helper, os, wifi, ugfx, http, time, sleep, app
|
||||
from tilda import Buttons
|
||||
|
||||
# initialize screen
|
||||
ugfx_helper.init()
|
||||
ugfx.clear(ugfx.BLACK)
|
||||
|
||||
ugfx.backlight(100)
|
||||
|
||||
n = 0
|
||||
r = 270
|
||||
while True:
|
||||
ugfx.display_image( 0, 90, "shared/nyan/{}.png".format(n) )
|
||||
n = (n+1) % 6
|
||||
sleep.sleep_ms(10)
|
||||
|
||||
if Buttons.is_pressed(Buttons.BTN_B):
|
||||
break
|
||||
elif Buttons.is_pressed(Buttons.BTN_A):
|
||||
r = (r + 180) % 360
|
||||
ugfx.clear(ugfx.BLACK)
|
||||
ugfx.orientation(r)
|
||||
|
||||
ugfx.clear()
|
||||
app.restart_to_default()
|
After Width: | Height: | Size: 4.2 KiB |
After Width: | Height: | Size: 4.3 KiB |
After Width: | Height: | Size: 4.2 KiB |
After Width: | Height: | Size: 4.0 KiB |
After Width: | Height: | Size: 4.2 KiB |
After Width: | Height: | Size: 4.2 KiB |
After Width: | Height: | Size: 4.1 KiB |
After Width: | Height: | Size: 4.4 KiB |
After Width: | Height: | Size: 4.4 KiB |
After Width: | Height: | Size: 4.4 KiB |
After Width: | Height: | Size: 4.4 KiB |
After Width: | Height: | Size: 4.7 KiB |
|
@ -0,0 +1,80 @@
|
|||
"""Nyan cat
|
||||
"""
|
||||
___name___ = "Nyan"
|
||||
___license___ = "MIT"
|
||||
___dependencies___ = ["app", "homescreen", "ugfx_helper"]
|
||||
___categories___ = ["Homescreens"]
|
||||
___bootstrapped___ = False
|
||||
|
||||
from app import *
|
||||
import ugfx
|
||||
from homescreen import *
|
||||
import ugfx_helper
|
||||
import machine
|
||||
|
||||
from tilda import Buttons
|
||||
from machine import Neopix
|
||||
|
||||
ext = False
|
||||
bkl = False
|
||||
|
||||
intro_text = "Hi! I'm"
|
||||
name_height = 70
|
||||
intro_height = 30
|
||||
max_name = 8
|
||||
|
||||
def cbButtonA(button_id):
|
||||
global bkl
|
||||
bkl = False
|
||||
|
||||
def cbButtonB(button_id):
|
||||
global ext
|
||||
ext = True
|
||||
|
||||
frame = 0
|
||||
|
||||
def force_backlight():
|
||||
if ugfx.backlight() == 0:
|
||||
ugfx.power_mode(ugfx.POWER_ON)
|
||||
ugfx.backlight(100)
|
||||
|
||||
ugfx_helper.init()
|
||||
ugfx.clear()
|
||||
|
||||
ugfx.orientation(180)
|
||||
force_backlight()
|
||||
|
||||
|
||||
|
||||
#everything from here onwards is unknown
|
||||
# Colour stuff
|
||||
style = ugfx.Style()
|
||||
style.set_enabled([ugfx.WHITE,ugfx.html_color(0x003265),ugfx.html_color(0x003265),ugfx.html_color(0x003265)])
|
||||
style.set_background(ugfx.html_color(0x003265))
|
||||
ugfx.set_default_style(style)
|
||||
ugfx.orientation(90)
|
||||
|
||||
# Draw for people to see
|
||||
ugfx.orientation(90)
|
||||
# Draw introduction
|
||||
ugfx.set_default_font(ugfx.FONT_TITLE)
|
||||
ugfx.Label(0, ugfx.height() - name_height - intro_height, ugfx.width(), intro_height, intro_text, justification=ugfx.Label.CENTER)
|
||||
# Process name
|
||||
name_setting = name("Set your name in the settings app")
|
||||
if len(name_setting) <= max_name:
|
||||
ugfx.set_default_font(ugfx.FONT_NAME)
|
||||
else:
|
||||
ugfx.set_default_font(ugfx.FONT_MEDIUM_BOLD)
|
||||
# Draw name
|
||||
ugfx.Label(0, ugfx.height() - name_height, ugfx.width(), name_height, name_setting, justification=ugfx.Label.CENTER)
|
||||
|
||||
i = 0
|
||||
while True:
|
||||
strimage = 'nyan/frame_'+str(i)+'_delay-0.07s.gif'
|
||||
ugfx.display_image(0, 0, strimage)
|
||||
i = i + 1
|
||||
if i > 11:
|
||||
i = 0
|
||||
sleep_or_exit(0.5)
|
||||
|
||||
app.restart_to_default()
|
|
@ -0,0 +1,145 @@
|
|||
"""
|
||||
Orbs Game: Set your name and see the scores
|
||||
"""
|
||||
___name___ = "Orbs Game"
|
||||
___license___ = "MIT"
|
||||
___dependencies___ = ["app", "dialogs", "sim800", "ugfx_helper"]
|
||||
___categories___ = ["Games"]
|
||||
___bootstrapped___ = True
|
||||
|
||||
from app import *
|
||||
from dialogs import *
|
||||
import utime
|
||||
import ugfx
|
||||
import ugfx_helper
|
||||
from orbs.umqtt.simple import MQTTClient
|
||||
import network
|
||||
from machine import mem32
|
||||
import wifi
|
||||
wifi.connect()
|
||||
|
||||
ugfx_helper.init()
|
||||
ugfx.clear()
|
||||
broker='151.216.207.139'
|
||||
mqtt_username='orbs'
|
||||
mqtt_password='orbs123'
|
||||
scoretext=""
|
||||
|
||||
MACAddress=str(mem32[0x400fef20]) + str(mem32[0x400fef24]) + str(mem32[0x400fef28]) + str(mem32[0x400fef2C])
|
||||
regOK=False
|
||||
regFAILED=False
|
||||
|
||||
def mqtt_connect():
|
||||
client = MQTTClient(MACAddress,broker, user=mqtt_username, password=mqtt_password)
|
||||
client.set_callback(sub_cb)
|
||||
connected=False
|
||||
try:
|
||||
client.connect()
|
||||
connected=True
|
||||
except Exception as err:
|
||||
connected=False
|
||||
if (connected):
|
||||
return client
|
||||
else:
|
||||
return False
|
||||
|
||||
def sub_cb(topic,msg):
|
||||
global regOK
|
||||
global regFAILED
|
||||
global scoretext
|
||||
try:
|
||||
(t1,t2,t3,targetBadge,messageType)=topic.decode('utf-8').split('/')
|
||||
strmsg=msg.decode('utf-8')
|
||||
if messageType=="regok":
|
||||
regOK=True
|
||||
if messageType=="regerror":
|
||||
regFAILED=True
|
||||
if messageType=="scores":
|
||||
scoretext=msg
|
||||
except:
|
||||
return
|
||||
|
||||
|
||||
def update_token(token):
|
||||
lb=open("token.txt","w")
|
||||
lb.write(token)
|
||||
lb.close()
|
||||
|
||||
def do_gettoken():
|
||||
notice("Enter your RFID token ID digits only. Get it right!", title="Orbs Game")
|
||||
token=prompt_text("Enter token:")
|
||||
if len(token)==8 or len(token)==14 or len(token)==20:
|
||||
return token
|
||||
else:
|
||||
notice("Invalid token", title="Orbs Game")
|
||||
return ""
|
||||
|
||||
def do_register(client):
|
||||
playername=prompt_text("Enter name:")
|
||||
playername=playername.replace(",",".")
|
||||
regOK==False
|
||||
regFAILED==False
|
||||
if len(playername)>3:
|
||||
client.publish("/registration/from/" + MACAddress + "/name",mytoken + "," + playername)
|
||||
notice("Name request sent")
|
||||
client.check_msg()
|
||||
if regOK==True:
|
||||
notice("Registration completed")
|
||||
if regFAILED==True:
|
||||
notice("Registration failed")
|
||||
else:
|
||||
notice("Name too short")
|
||||
|
||||
def get_token():
|
||||
try:
|
||||
lb=open("token.txt","r")
|
||||
token=lb.readline()
|
||||
lb.close()
|
||||
if token=="":
|
||||
token=do_gettoken()
|
||||
except:
|
||||
token=""
|
||||
if token=="":
|
||||
token=do_gettoken()
|
||||
return token
|
||||
|
||||
def do_showscores(client):
|
||||
client.publish("/registration/from/" + MACAddress + "/score",mytoken)
|
||||
notice("Requested scores")
|
||||
client.check_msg()
|
||||
if len(scoretext)>0:
|
||||
(playername,playerscore,rank,redscore,greenscore,bluescore)=scoretext.decode('utf-8').split(',')
|
||||
notice("Player: " + playername + chr(13) + "Score: " + playerscore + chr(13) + "Rank: " + rank)
|
||||
notice("Red Score: " + redscore + chr(13) + "Green Score: " + greenscore + chr(13) + "Blue Score: " + bluescore)
|
||||
else:
|
||||
notice("Failed to get scores")
|
||||
|
||||
mqttclient=mqtt_connect()
|
||||
while (not mqttclient):
|
||||
utime.sleep(2)
|
||||
mqttclient=mqtt_connect()
|
||||
mqttclient.subscribe(topic='/badge/to/' + MACAddress + '/#')
|
||||
#mqttclient.subscribe(topic='/scoreboard/to/all/#')
|
||||
mytoken=get_token()
|
||||
if len(mytoken)==0:
|
||||
notice("Token required",title="Orbs Game")
|
||||
try:
|
||||
mqttclient.close()
|
||||
except:
|
||||
restart_to_default()
|
||||
restart_to_default()
|
||||
update_token(mytoken)
|
||||
|
||||
|
||||
menuset = []
|
||||
menuset.append({ "title" : "Register", "index" : 1 })
|
||||
menuset.append({ "title" : "Scores", "index" : 2 })
|
||||
|
||||
while True:
|
||||
selection = prompt_option(menuset, text="Orbs Game", select_text="Select", none_text="Exit")
|
||||
if (not selection):
|
||||
restart_to_default()
|
||||
elif (selection["index"]==1):
|
||||
do_register(mqttclient)
|
||||
elif (selection["index"]==2):
|
||||
do_showscores(mqttclient)
|
|
@ -0,0 +1,43 @@
|
|||
import utime
|
||||
from . import simple
|
||||
|
||||
class MQTTClient(simple.MQTTClient):
|
||||
|
||||
DELAY = 2
|
||||
DEBUG = False
|
||||
|
||||
def delay(self, i):
|
||||
utime.sleep(self.DELAY)
|
||||
|
||||
def log(self, in_reconnect, e):
|
||||
if self.DEBUG:
|
||||
if in_reconnect:
|
||||
print("mqtt reconnect: %r" % e)
|
||||
else:
|
||||
print("mqtt: %r" % e)
|
||||
|
||||
def reconnect(self):
|
||||
i = 0
|
||||
while 1:
|
||||
try:
|
||||
return super().connect(False)
|
||||
except OSError as e:
|
||||
self.log(True, e)
|
||||
i += 1
|
||||
self.delay(i)
|
||||
|
||||
def publish(self, topic, msg, retain=False, qos=0):
|
||||
while 1:
|
||||
try:
|
||||
return super().publish(topic, msg, retain, qos)
|
||||
except OSError as e:
|
||||
self.log(False, e)
|
||||
self.reconnect()
|
||||
|
||||
def wait_msg(self):
|
||||
while 1:
|
||||
try:
|
||||
return super().wait_msg()
|
||||
except OSError as e:
|
||||
self.log(False, e)
|
||||
self.reconnect()
|
|
@ -0,0 +1,204 @@
|
|||
import usocket as socket
|
||||
import ustruct as struct
|
||||
from ubinascii import hexlify
|
||||
|
||||
class MQTTException(Exception):
|
||||
pass
|
||||
|
||||
class MQTTClient:
|
||||
|
||||
def __init__(self, client_id, server, port=0, user=None, password=None, keepalive=0,
|
||||
ssl=False, ssl_params={}):
|
||||
if port == 0:
|
||||
port = 8883 if ssl else 1883
|
||||
self.client_id = client_id
|
||||
self.sock = None
|
||||
self.server = server
|
||||
self.port = port
|
||||
self.ssl = ssl
|
||||
self.ssl_params = ssl_params
|
||||
self.pid = 0
|
||||
self.cb = None
|
||||
self.user = user
|
||||
self.pswd = password
|
||||
self.keepalive = keepalive
|
||||
self.lw_topic = None
|
||||
self.lw_msg = None
|
||||
self.lw_qos = 0
|
||||
self.lw_retain = False
|
||||
|
||||
def _send_str(self, s):
|
||||
self.sock.write(struct.pack("!H", len(s)))
|
||||
self.sock.write(s)
|
||||
|
||||
def _recv_len(self):
|
||||
n = 0
|
||||
sh = 0
|
||||
while 1:
|
||||
b = self.sock.read(1)[0]
|
||||
n |= (b & 0x7f) << sh
|
||||
if not b & 0x80:
|
||||
return n
|
||||
sh += 7
|
||||
|
||||
def set_callback(self, f):
|
||||
self.cb = f
|
||||
|
||||
def set_last_will(self, topic, msg, retain=False, qos=0):
|
||||
assert 0 <= qos <= 2
|
||||
assert topic
|
||||
self.lw_topic = topic
|
||||
self.lw_msg = msg
|
||||
self.lw_qos = qos
|
||||
self.lw_retain = retain
|
||||
|
||||
def connect(self, clean_session=True):
|
||||
self.sock = socket.socket()
|
||||
addr = socket.getaddrinfo(self.server, self.port)[0][-1]
|
||||
self.sock.connect(addr)
|
||||
if self.ssl:
|
||||
import ussl
|
||||
self.sock = ussl.wrap_socket(self.sock, **self.ssl_params)
|
||||
premsg = bytearray(b"\x10\0\0\0\0\0")
|
||||
msg = bytearray(b"\x04MQTT\x04\x02\0\0")
|
||||
|
||||
sz = 10 + 2 + len(self.client_id)
|
||||
msg[6] = clean_session << 1
|
||||
if self.user is not None:
|
||||
sz += 2 + len(self.user) + 2 + len(self.pswd)
|
||||
msg[6] |= 0xC0
|
||||
if self.keepalive:
|
||||
assert self.keepalive < 65536
|
||||
msg[7] |= self.keepalive >> 8
|
||||
msg[8] |= self.keepalive & 0x00FF
|
||||
if self.lw_topic:
|
||||
sz += 2 + len(self.lw_topic) + 2 + len(self.lw_msg)
|
||||
msg[6] |= 0x4 | (self.lw_qos & 0x1) << 3 | (self.lw_qos & 0x2) << 3
|
||||
msg[6] |= self.lw_retain << 5
|
||||
|
||||
i = 1
|
||||
while sz > 0x7f:
|
||||
premsg[i] = (sz & 0x7f) | 0x80
|
||||
sz >>= 7
|
||||
i += 1
|
||||
premsg[i] = sz
|
||||
|
||||
self.sock.write(premsg, i + 2)
|
||||
self.sock.write(msg)
|
||||
#print(hex(len(msg)), hexlify(msg, ":"))
|
||||
self._send_str(self.client_id)
|
||||
if self.lw_topic:
|
||||
self._send_str(self.lw_topic)
|
||||
self._send_str(self.lw_msg)
|
||||
if self.user is not None:
|
||||
self._send_str(self.user)
|
||||
self._send_str(self.pswd)
|
||||
resp = self.sock.read(4)
|
||||
assert resp[0] == 0x20 and resp[1] == 0x02
|
||||
if resp[3] != 0:
|
||||
raise MQTTException(resp[3])
|
||||
return resp[2] & 1
|
||||
|
||||
def disconnect(self):
|
||||
self.sock.write(b"\xe0\0")
|
||||
self.sock.close()
|
||||
|
||||
def ping(self):
|
||||
self.sock.write(b"\xc0\0")
|
||||
|
||||
def publish(self, topic, msg, retain=False, qos=0):
|
||||
pkt = bytearray(b"\x30\0\0\0")
|
||||
pkt[0] |= qos << 1 | retain
|
||||
sz = 2 + len(topic) + len(msg)
|
||||
if qos > 0:
|
||||
sz += 2
|
||||
assert sz < 2097152
|
||||
i = 1
|
||||
while sz > 0x7f:
|
||||
pkt[i] = (sz & 0x7f) | 0x80
|
||||
sz >>= 7
|
||||
i += 1
|
||||
pkt[i] = sz
|
||||
#print(hex(len(pkt)), hexlify(pkt, ":"))
|
||||
self.sock.write(pkt, i + 1)
|
||||
self._send_str(topic)
|
||||
if qos > 0:
|
||||
self.pid += 1
|
||||
pid = self.pid
|
||||
struct.pack_into("!H", pkt, 0, pid)
|
||||
self.sock.write(pkt, 2)
|
||||
self.sock.write(msg)
|
||||
if qos == 1:
|
||||
while 1:
|
||||
op = self.wait_msg()
|
||||
if op == 0x40:
|
||||
sz = self.sock.read(1)
|
||||
assert sz == b"\x02"
|
||||
rcv_pid = self.sock.read(2)
|
||||
rcv_pid = rcv_pid[0] << 8 | rcv_pid[1]
|
||||
if pid == rcv_pid:
|
||||
return
|
||||
elif qos == 2:
|
||||
assert 0
|
||||
|
||||
def subscribe(self, topic, qos=0):
|
||||
assert self.cb is not None, "Subscribe callback is not set"
|
||||
pkt = bytearray(b"\x82\0\0\0")
|
||||
self.pid += 1
|
||||
struct.pack_into("!BH", pkt, 1, 2 + 2 + len(topic) + 1, self.pid)
|
||||
#print(hex(len(pkt)), hexlify(pkt, ":"))
|
||||
self.sock.write(pkt)
|
||||
self._send_str(topic)
|
||||
self.sock.write(qos.to_bytes(1, "little"))
|
||||
while 1:
|
||||
op = self.wait_msg()
|
||||
if op == 0x90:
|
||||
resp = self.sock.read(4)
|
||||
#print(resp)
|
||||
assert resp[1] == pkt[2] and resp[2] == pkt[3]
|
||||
if resp[3] == 0x80:
|
||||
raise MQTTException(resp[3])
|
||||
return
|
||||
|
||||
# Wait for a single incoming MQTT message and process it.
|
||||
# Subscribed messages are delivered to a callback previously
|
||||
# set by .set_callback() method. Other (internal) MQTT
|
||||
# messages processed internally.
|
||||
def wait_msg(self):
|
||||
res = self.sock.read(1)
|
||||
self.sock.setblocking(True)
|
||||
if res is None:
|
||||
return None
|
||||
if res == b"":
|
||||
raise OSError(-1)
|
||||
if res == b"\xd0": # PINGRESP
|
||||
sz = self.sock.read(1)[0]
|
||||
assert sz == 0
|
||||
return None
|
||||
op = res[0]
|
||||
if op & 0xf0 != 0x30:
|
||||
return op
|
||||
sz = self._recv_len()
|
||||
topic_len = self.sock.read(2)
|
||||
topic_len = (topic_len[0] << 8) | topic_len[1]
|
||||
topic = self.sock.read(topic_len)
|
||||
sz -= topic_len + 2
|
||||
if op & 6:
|
||||
pid = self.sock.read(2)
|
||||
pid = pid[0] << 8 | pid[1]
|
||||
sz -= 2
|
||||
msg = self.sock.read(sz)
|
||||
self.cb(topic, msg)
|
||||
if op & 6 == 2:
|
||||
pkt = bytearray(b"\x40\x02\0\0")
|
||||
struct.pack_into("!H", pkt, 2, pid)
|
||||
self.sock.write(pkt)
|
||||
elif op & 6 == 4:
|
||||
assert 0
|
||||
|
||||
# Checks whether a pending message from server is available.
|
||||
# If not, returns immediately with None. Otherwise, does
|
||||
# the same processing as wait_msg.
|
||||
def check_msg(self):
|
||||
self.sock.setblocking(False)
|
||||
return self.wait_msg()
|
|
@ -2,7 +2,7 @@
|
|||
'''
|
||||
|
||||
___author___ = 'Skybound - ECS'
|
||||
___name___ = 'Party'
|
||||
___title___ = 'Party'
|
||||
___license___ = 'MIT'
|
||||
___categories___ = ['LEDs']
|
||||
___bootstrapped___ = False
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
"""Phone app for baic calling functions
|
||||
"""
|
||||
___name___ = "Phone"
|
||||
___title___ = "Phone"
|
||||
___license___ = "MIT"
|
||||
___dependencies___ = ["app", "dialogs", "sim800", "ugfx_helper"]
|
||||
___categories___ = ["System"]
|
||||
|
|
|
@ -0,0 +1,220 @@
|
|||
"""Pong!"""
|
||||
|
||||
___name___ = "Pong"
|
||||
___license___ = "WTFPL"
|
||||
___categories___ = ["Games"]
|
||||
___dependencies___ = ["dialogs", "app", "ugfx_helper", "sleep", "buttons"]
|
||||
|
||||
import math, ugfx, ugfx_helper, random, sleep, buttons, time
|
||||
from tilda import Buttons
|
||||
|
||||
ugfx_helper.init()
|
||||
|
||||
SCREEN_WIDTH = ugfx.width()
|
||||
SCREEN_HEIGHT = ugfx.height()
|
||||
|
||||
bgColor = ugfx.BLACK
|
||||
ballColor = ugfx.html_color(0x00FF00)
|
||||
paddleColor = ugfx.html_color(0x00FF00)
|
||||
netColor = ugfx.html_color(0x00FF00)
|
||||
|
||||
class Paddle():
|
||||
height = 6
|
||||
width = 60
|
||||
|
||||
moveSpeed = 4
|
||||
|
||||
needsRedraw = True
|
||||
|
||||
def __init__(self, type):
|
||||
self.type = type
|
||||
|
||||
self.x = SCREEN_WIDTH/2
|
||||
self.previousX = self.x
|
||||
|
||||
if type == 0:
|
||||
self.y = self.height/2
|
||||
else:
|
||||
self.y = SCREEN_HEIGHT - (self.height/2)
|
||||
|
||||
def draw(self):
|
||||
if self.needsRedraw:
|
||||
ugfx.area(int(self.previousX-self.width/2),int(self.y-self.height/2),int(self.width),int(self.height),bgColor)
|
||||
self.needsRedraw = False
|
||||
|
||||
ugfx.area(int(self.x-self.width/2),int(self.y-self.height/2),int(self.width),int(self.height),paddleColor)
|
||||
|
||||
def update(self):
|
||||
if self.type == 1:
|
||||
if Buttons.is_pressed(Buttons.BTN_Hash):
|
||||
self.needsRedraw = True
|
||||
self.previousX = self.x
|
||||
self.x += self.moveSpeed
|
||||
|
||||
if Buttons.is_pressed(Buttons.BTN_Star):
|
||||
self.needsRedraw = True
|
||||
self.previousX = self.x
|
||||
self.x -= self.moveSpeed
|
||||
if self.type == 0:
|
||||
if Buttons.is_pressed(Buttons.BTN_3):
|
||||
self.needsRedraw = True
|
||||
self.previousX = self.x
|
||||
self.x += self.moveSpeed
|
||||
if Buttons.is_pressed(Buttons.BTN_1):
|
||||
self.needsRedraw = True
|
||||
self.previousX = self.x
|
||||
self.x -= self.moveSpeed
|
||||
|
||||
if self.x + self.width/2 > SCREEN_WIDTH:
|
||||
self.x = SCREEN_WIDTH - self.width/2
|
||||
|
||||
if self.x -self.width/2 < 0:
|
||||
self.x = self.width/2
|
||||
|
||||
class Ball():
|
||||
size = 10
|
||||
|
||||
x = 0
|
||||
y = 0
|
||||
|
||||
yDeathOffset = 5+3
|
||||
|
||||
def __init__(self):
|
||||
self.x = random.randint(30,SCREEN_WIDTH-30)
|
||||
|
||||
self.y = SCREEN_HEIGHT/2
|
||||
|
||||
self.vX = 3
|
||||
|
||||
if random.randrange(2) == 1:
|
||||
self.vY = 3
|
||||
else:
|
||||
self.vY = -3
|
||||
|
||||
self.previousX = self.x
|
||||
self.previousY = self.y
|
||||
|
||||
self.dead = False
|
||||
|
||||
def draw(self):
|
||||
ugfx.area(int(self.previousX-self.size/2),int(self.previousY-self.size/2),int(self.size),int(self.size),bgColor)
|
||||
ugfx.area(int(self.x-self.size/2),int(self.y-self.size/2),int(self.size),int(self.size),ballColor)
|
||||
|
||||
def update(self, topPaddle, bottomPaddle):
|
||||
self.previousX = self.x
|
||||
self.previousY = self.y
|
||||
|
||||
self.x += self.vX
|
||||
self.y += self.vY
|
||||
|
||||
if self.x > SCREEN_WIDTH:
|
||||
self.x = SCREEN_WIDTH
|
||||
self.vX = -self.vX
|
||||
|
||||
if self.x < 0:
|
||||
self.x = 0
|
||||
self.vX = -self.vX
|
||||
|
||||
if self.y > (SCREEN_HEIGHT - self.yDeathOffset):
|
||||
if (self.x > (bottomPaddle.x - bottomPaddle.width/2)) and (self.x < (bottomPaddle.x + bottomPaddle.width/2)):
|
||||
self.y = SCREEN_HEIGHT - self.yDeathOffset
|
||||
self.vY = -self.vY
|
||||
bottomPaddle.needsRedraw = True
|
||||
else:
|
||||
self.dead = True
|
||||
|
||||
|
||||
if self.y < self.yDeathOffset:
|
||||
if (self.x > (topPaddle.x - topPaddle.width/2)) and (self.x < (topPaddle.x + topPaddle.width/2)):
|
||||
self.y = self.yDeathOffset
|
||||
self.vY = -self.vY
|
||||
topPaddle.needsRedraw = True
|
||||
else:
|
||||
self.dead = True
|
||||
|
||||
def isDead(self):
|
||||
return self.dead
|
||||
|
||||
def one_round():
|
||||
ball = Ball()
|
||||
topPaddle = Paddle(0)
|
||||
bottomPaddle = Paddle(1)
|
||||
|
||||
ugfx.clear(bgColor)
|
||||
ugfx.backlight(100)
|
||||
|
||||
ugfx.set_default_font(ugfx.FONT_TITLE)
|
||||
|
||||
while True:
|
||||
topPaddle.update()
|
||||
bottomPaddle.update()
|
||||
ball.update(topPaddle, bottomPaddle)
|
||||
|
||||
if ball.isDead():
|
||||
if(ball.y > SCREEN_HEIGHT/2):
|
||||
return [1,0]
|
||||
else:
|
||||
return [0,1]
|
||||
|
||||
topPaddle.draw()
|
||||
bottomPaddle.draw()
|
||||
ball.draw()
|
||||
|
||||
#draw the net
|
||||
for i in range(0,7):
|
||||
ugfx.area(int(i*2*SCREEN_WIDTH/13), int(SCREEN_HEIGHT/2-1), int(SCREEN_WIDTH/13), 3, netColor)
|
||||
|
||||
ugfx.orientation(0)
|
||||
ugfx.text(130, 0, "%d " % (points[0]),netColor)
|
||||
ugfx.text(170, 0, "%d " % (points[1]),netColor)
|
||||
ugfx.orientation(270)
|
||||
|
||||
time.sleep_ms(1)
|
||||
|
||||
minScore = 9
|
||||
|
||||
points = [0,0]
|
||||
playing = 1
|
||||
while playing:
|
||||
points[0] = 0
|
||||
points[1] = 0
|
||||
|
||||
while (points[0] < minScore) and (points[1] < minScore):
|
||||
score = one_round()
|
||||
|
||||
points[0] = points[0] + score[0]
|
||||
points[1] = points[1] + score[1]
|
||||
|
||||
ugfx.area(0,0,ugfx.width(),ugfx.height(),0)
|
||||
|
||||
ugfx.orientation(90)
|
||||
ugfx.set_default_font(ugfx.FONT_TITLE)
|
||||
ugfx.text(30, 138, "GAME ",ballColor)
|
||||
ugfx.text(30, 158, "OVER ",ballColor)
|
||||
|
||||
ugfx.set_default_font(ugfx.FONT_SMALL)
|
||||
ugfx.text(70, 220, "Score: %d - %d " % (points[0], points[1]), ballColor)
|
||||
ugfx.text(36, 260, "Press A to play again ", ballColor)
|
||||
ugfx.text(40, 280, "Press MENU to quit " , ballColor)
|
||||
|
||||
ugfx.orientation(270)
|
||||
ugfx.set_default_font(ugfx.FONT_TITLE)
|
||||
ugfx.text(30, 138, "GAME ",ballColor)
|
||||
ugfx.text(30, 158, "OVER ",ballColor)
|
||||
|
||||
ugfx.set_default_font(ugfx.FONT_SMALL)
|
||||
ugfx.text(70, 220, "Score: %d - %d " % (points[1], points[0]), ballColor)
|
||||
ugfx.text(36, 260, "Press A to play again ", ballColor)
|
||||
ugfx.text(40, 280, "Press MENU to quit ", ballColor)
|
||||
|
||||
while True:
|
||||
sleep.wfi()
|
||||
if buttons.is_triggered(Buttons.BTN_A):
|
||||
break
|
||||
|
||||
if buttons.is_triggered(Buttons.BTN_Menu):
|
||||
playing = 0
|
||||
break
|
||||
|
||||
app.restart_to_default()
|
||||
|
After Width: | Height: | Size: 28 KiB |
After Width: | Height: | Size: 15 KiB |
|
@ -0,0 +1,58 @@
|
|||
"""Praise the Horse or Worship the Melon, directly from your badge
|
||||
"""
|
||||
___name___ = "Praise Horse! Worship Melon!"
|
||||
___license___ = "MIT"
|
||||
___dependencies___ = ["app","wifi", "buttons", "ugfx_helper"]
|
||||
___categories___ = ["Other"]
|
||||
|
||||
import ugfx, wifi, utime, ugfx_helper, buttons
|
||||
from tilda import Buttons
|
||||
import random
|
||||
from app import App
|
||||
|
||||
|
||||
def loading_screen():
|
||||
logo = 'praise_horse_worship_melon/loading.gif'
|
||||
ugfx.area(0,0,ugfx.width(),ugfx.height(),0xFFFF)
|
||||
ugfx.display_image(2,2,logo)
|
||||
ugfx.set_default_font(ugfx.FONT_SMALL)
|
||||
ugfx.text(60, 145, "Praise Horse (A)", ugfx.GREY)
|
||||
ugfx.text(55, 305, "Worship Melon (B)", ugfx.GREY)
|
||||
|
||||
def show_screen(type=None):
|
||||
if type == "horse":
|
||||
img = "praise_horse_worship_melon/horse.gif"
|
||||
color = ugfx.RED
|
||||
text = "HORSE!"
|
||||
elif type == "melon":
|
||||
img = "praise_horse_worship_melon/melon.gif"
|
||||
color = ugfx.BLUE
|
||||
text = "MELON!"
|
||||
else:
|
||||
return
|
||||
|
||||
ugfx.area(0,0,ugfx.width(),ugfx.height(), color)
|
||||
ugfx.display_image(0, 0,img)
|
||||
ugfx.set_default_font(ugfx.FONT_MEDIUM_BOLD)
|
||||
for y_offset in range(8):
|
||||
ugfx.Label(0, 42 * y_offset, ugfx.width(), 20, text, parent=None, style=None, justification=ugfx.Label.CENTER)
|
||||
utime.sleep_ms(100)
|
||||
|
||||
utime.sleep_ms(1000)
|
||||
loading_screen()
|
||||
|
||||
def start():
|
||||
ugfx_helper.init()
|
||||
loading_screen()
|
||||
utime.sleep_ms(2000)
|
||||
return True
|
||||
|
||||
running = start()
|
||||
while running:
|
||||
if buttons.is_triggered(Buttons.BTN_A):
|
||||
show_screen(type='horse')
|
||||
if buttons.is_triggered(Buttons.BTN_B):
|
||||
show_screen(type='melon')
|
||||
if buttons.is_triggered(Buttons.BTN_Menu):
|
||||
App("launcher").boot()
|
||||
utime.sleep_ms(30)
|
After Width: | Height: | Size: 31 KiB |
104
pride/main.py
|
@ -4,15 +4,17 @@ Similar to the default homescreen, but the
|
|||
background is the pride flag.
|
||||
"""
|
||||
|
||||
___name___ = "Pride"
|
||||
___title___ = "Pride"
|
||||
___license___ = "MIT"
|
||||
___categories___ = ["Homescreens"]
|
||||
___dependencies___ = ["homescreen", "app"]
|
||||
___dependencies___ = ["homescreen", "app", "buttons"]
|
||||
|
||||
|
||||
from app import restart_to_default
|
||||
import ugfx
|
||||
import homescreen
|
||||
from tilda import Buttons
|
||||
import buttons
|
||||
|
||||
|
||||
homescreen.init()
|
||||
|
@ -25,56 +27,94 @@ info_height = 20
|
|||
# Maximum length of name before downscaling
|
||||
max_name = 8
|
||||
|
||||
# Orientation for other people to see
|
||||
ugfx.orientation(90)
|
||||
flags = {
|
||||
'LGBT': [0xE70000, 0xFF8C00, 0xFFEF00, 0x00811F, 0x0044FF, 0x760089],
|
||||
'Non-Binary': [0xFFF433, 0xFFFFFF, 0x9B59D0, 0x000000],
|
||||
'Trans': [0x5BCEFA, 0xF5A9B8, 0xFFFFFF, 0xF5A9B8, 0x5BCEFA],
|
||||
'Asexual': [0x000000, 0xA3A3A3, 0xFFFFFF, 0x800080],
|
||||
'Bisexual': [0xFF0080, 0xFF0080, 0xA349A4, 0x0000FF, 0x0000FF],
|
||||
'Pansexual': [0xFF218E, 0xFCD800, 0x0194FC]
|
||||
}
|
||||
|
||||
# Pride flag colours
|
||||
colours = [0xE70000, 0xFF8C00, 0xFFEF00, 0x00811F, 0x0044FF, 0x760089]
|
||||
|
||||
# Draw each "band" of colour in the flag
|
||||
colour_width = ugfx.width() / len(colours)
|
||||
for num, colour in enumerate(colours):
|
||||
width_loc = int(num * colour_width)
|
||||
ugfx.area(width_loc, 0, int(colour_width), 320, ugfx.html_color(colour))
|
||||
def draw_flag(colours):
|
||||
# Orientation for other people to see
|
||||
ugfx.orientation(90)
|
||||
|
||||
# Message to display
|
||||
prefix_message = "Hi I'm"
|
||||
# Draw each "band" of colour in the flag
|
||||
colour_width = ugfx.width() / len(colours)
|
||||
for num, colour in enumerate(colours):
|
||||
width_loc = int(num * colour_width)
|
||||
flag_height = ugfx.height() - (name_height + info_height)
|
||||
ugfx.area(width_loc, info_height, int(colour_width), flag_height, ugfx.html_color(colour))
|
||||
|
||||
ugfx.set_default_font(ugfx.FONT_NAME)
|
||||
|
||||
# Calc center of screen
|
||||
center = (int(ugfx.width() / 2), int(ugfx.height() / 2))
|
||||
# Can't use label since the background covers the flag
|
||||
ugfx.text(50, center[1] + name_height, prefix_message, ugfx.WHITE)
|
||||
def draw_name():
|
||||
# Orientation for other people to see
|
||||
ugfx.orientation(90)
|
||||
|
||||
# Process name
|
||||
given_name = homescreen.name("Set your name in the settings app")
|
||||
if len(given_name) <= max_name:
|
||||
ugfx.set_default_font(ugfx.FONT_NAME)
|
||||
else:
|
||||
ugfx.set_default_font(ugfx.FONT_MEDIUM_BOLD)
|
||||
# Draw name
|
||||
ugfx.Label(0, ugfx.height() - name_height, ugfx.width(), name_height, given_name, justification=ugfx.Label.CENTER)
|
||||
|
||||
# Process name
|
||||
given_name = homescreen.name("Set your name in the settings app")
|
||||
if len(given_name) <= max_name:
|
||||
ugfx.set_default_font(ugfx.FONT_NAME)
|
||||
else:
|
||||
ugfx.set_default_font(ugfx.FONT_MEDIUM_BOLD)
|
||||
# Draw name
|
||||
ugfx.Label(0, ugfx.height() - name_height, ugfx.width(), name_height, given_name, justification=ugfx.Label.CENTER)
|
||||
|
||||
|
||||
# Draw for the user to see
|
||||
ugfx.orientation(270)
|
||||
ugfx.set_default_font(ugfx.FONT_SMALL)
|
||||
def draw_user_info():
|
||||
# Draw for the user to see
|
||||
ugfx.orientation(270)
|
||||
# Calc width center of screen
|
||||
center_width = int(ugfx.width() / 2)
|
||||
ugfx.set_default_font(ugfx.FONT_SMALL)
|
||||
|
||||
# WiFi/Battery update loop
|
||||
while True:
|
||||
ugfx.area(0, ugfx.height() - info_height, ugfx.width(), info_height, ugfx.WHITE)
|
||||
|
||||
wifi_strength_value = homescreen.wifi_strength()
|
||||
if wifi_strength_value:
|
||||
wifi_message = 'WiFi: %s%%' % int(wifi_strength_value)
|
||||
wifi_text = ugfx.text(center[0], ugfx.height() - info_height, wifi_message, ugfx.BLACK)
|
||||
ugfx.text(center_width, ugfx.height() - info_height, wifi_message, ugfx.BLACK)
|
||||
|
||||
battery_value = homescreen.battery()
|
||||
if battery_value:
|
||||
battery_message = 'Battery: %s%%' % int(battery_value)
|
||||
battery_text = ugfx.text(0, ugfx.height() - info_height, battery_message, ugfx.BLACK)
|
||||
ugfx.text(0, ugfx.height() - info_height, battery_message, ugfx.BLACK)
|
||||
|
||||
|
||||
# Set variables for WiFi/Battery loop
|
||||
selection_change = True
|
||||
flag_names = list(flags.keys())
|
||||
selection = flag_names.index('LGBT')
|
||||
|
||||
# WiFi/Battery update loop
|
||||
draw_name()
|
||||
while True:
|
||||
# Buttons will cycle when it reaches either side of the list
|
||||
if buttons.is_pressed(Buttons.JOY_Left):
|
||||
if selection > 0:
|
||||
selection -= 1
|
||||
else:
|
||||
selection = len(flags) - 1
|
||||
selection_change = True
|
||||
|
||||
elif buttons.is_pressed(Buttons.JOY_Right):
|
||||
if selection < len(flags) - 1:
|
||||
selection += 1
|
||||
else:
|
||||
selection = 0
|
||||
selection_change = True
|
||||
|
||||
# Only triggers if the selection has changed
|
||||
if selection_change:
|
||||
draw_flag(flags[flag_names[selection]])
|
||||
selection_change = False
|
||||
|
||||
# Redraw time-sensitive info on each iteration
|
||||
draw_user_info()
|
||||
homescreen.sleep_or_exit(1.5)
|
||||
|
||||
restart_to_default()
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
; Windows USB CDC ACM Setup File
|
||||
; Based on INF files which were:
|
||||
; Copyright (c) 2000 Microsoft Corporation
|
||||
; Copyright (C) 2007 Microchip Technology Inc.
|
||||
; Likely to be covered by the MLPL as found at:
|
||||
; <http://msdn.microsoft.com/en-us/cc300389.aspx#MLPL>.
|
||||
|
||||
[Version]
|
||||
Signature="$Windows NT$"
|
||||
Class=Ports
|
||||
ClassGuid={4D36E978-E325-11CE-BFC1-08002BE10318}
|
||||
Provider=%MFGNAME%
|
||||
LayoutFile=layout.inf
|
||||
DriverVer=03/11/2010,5.1.2600.3
|
||||
|
||||
[Manufacturer]
|
||||
%MFGNAME%=DeviceList, NTamd64
|
||||
|
||||
[DestinationDirs]
|
||||
DefaultDestDir=12
|
||||
|
||||
;---------------------------------------------------------------------
|
||||
; Windows 2000/XP/Server2003/Vista/Server2008/7 - 32bit Sections
|
||||
|
||||
[DriverInstall.nt]
|
||||
include=mdmcpq.inf
|
||||
CopyFiles=DriverCopyFiles.nt
|
||||
AddReg=DriverInstall.nt.AddReg
|
||||
|
||||
[DriverCopyFiles.nt]
|
||||
usbser.sys,,,0x20
|
||||
|
||||
[DriverInstall.nt.AddReg]
|
||||
HKR,,DevLoader,,*ntkern
|
||||
HKR,,NTMPDriver,,usbser.sys
|
||||
HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider"
|
||||
|
||||
[DriverInstall.nt.Services]
|
||||
AddService=usbser, 0x00000002, DriverService.nt
|
||||
|
||||
[DriverService.nt]
|
||||
DisplayName=%SERVICE%
|
||||
ServiceType=1
|
||||
StartType=3
|
||||
ErrorControl=1
|
||||
ServiceBinary=%12%\usbser.sys
|
||||
|
||||
;---------------------------------------------------------------------
|
||||
; Windows XP/Server2003/Vista/Server2008/7 - 64bit Sections
|
||||
|
||||
[DriverInstall.NTamd64]
|
||||
include=mdmcpq.inf
|
||||
CopyFiles=DriverCopyFiles.NTamd64
|
||||
AddReg=DriverInstall.NTamd64.AddReg
|
||||
|
||||
[DriverCopyFiles.NTamd64]
|
||||
usbser.sys,,,0x20
|
||||
|
||||
[DriverInstall.NTamd64.AddReg]
|
||||
HKR,,DevLoader,,*ntkern
|
||||
HKR,,NTMPDriver,,usbser.sys
|
||||
HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider"
|
||||
|
||||
[DriverInstall.NTamd64.Services]
|
||||
AddService=usbser, 0x00000002, DriverService.NTamd64
|
||||
|
||||
[DriverService.NTamd64]
|
||||
DisplayName=%SERVICE%
|
||||
ServiceType=1
|
||||
StartType=3
|
||||
ErrorControl=1
|
||||
ServiceBinary=%12%\usbser.sys
|
||||
|
||||
;---------------------------------------------------------------------
|
||||
; Vendor and Product ID Definitions
|
||||
|
||||
[SourceDisksFiles]
|
||||
[SourceDisksNames]
|
||||
[DeviceList]
|
||||
%DESCRIPTION%=DriverInstall, USB\VID_f055&PID_9800&MI_00, USB\VID_f055&PID_9800&MI_01
|
||||
|
||||
[DeviceList.NTamd64]
|
||||
%DESCRIPTION%=DriverInstall, USB\VID_f055&PID_9800&MI_00, USB\VID_f055&PID_9800&MI_01
|
||||
|
||||
;---------------------------------------------------------------------
|
||||
; String Definitions
|
||||
|
||||
[Strings]
|
||||
MFGFILENAME="pybcdc"
|
||||
MFGNAME="Micro Python"
|
||||
DESCRIPTION="Pyboard USB Comm Port"
|
||||
SERVICE="USB Serial Driver"
|
|
@ -1,6 +1,6 @@
|
|||
"""Helps to test incoming PRs"""
|
||||
|
||||
___name___ = "PR Review Helper"
|
||||
___title___ = "PR Review Helper"
|
||||
___license___ = "MIT"
|
||||
___categories___ = ["System"]
|
||||
___dependencies___ = ["dialogs", "app", "ugfx_helper", "badge_store", "http", "stack_nav", "wifi"]
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
""" Flashes random colours on your screen
|
||||
"" By Pez (@Pezmc)
|
||||
"""
|
||||
___name___ = "Screen Party"
|
||||
___title___ = "Screen Party"
|
||||
___license___ = "MIT"
|
||||
___dependencies___ = ["ugfx_helper", "sleep", "random"]
|
||||
___dependencies___ = ["ugfx_helper", "sleep"]
|
||||
___categories___ = ["Homescreens"]
|
||||
___bootstrapped___ = False
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
Annoy your friends! Annoy your enemies! Annoy yourself! Maybe (maybe) make music!
|
||||
"""
|
||||
|
||||
___name___ = "Sequencer"
|
||||
___title___ = "Sequencer"
|
||||
___license___ = "MIT"
|
||||
___categories___ = ["Sound"]
|
||||
___dependencies___ = ["speaker", "buttons", "ugfx_helper", "app", "shared/sequencer_info.png"]
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
"""Happy accidents or unplanned, fortunate discoveries."""
|
||||
|
||||
___name___ = "serendipity"
|
||||
___license___ = "MIT"
|
||||
___dependencies___ = ["sleep", "app", "ugfx_helper"]
|
||||
___categories___ = ["Villages"]
|
||||
|
||||
import ugfx_helper, os, wifi, ugfx, http, time, sleep, app
|
||||
from tilda import Buttons
|
||||
|
||||
# initialize screen
|
||||
ugfx_helper.init()
|
||||
ugfx.clear(ugfx.BLACK)
|
||||
|
||||
img = [ugfx.Image("serendipity/sun.png"),
|
||||
ugfx.Image("serendipity/world.png")]
|
||||
|
||||
ugfx.backlight(100)
|
||||
|
||||
n = 0
|
||||
ugfx.display_image( 0, 0, img[n] )
|
||||
|
||||
while True:
|
||||
|
||||
if Buttons.is_pressed(Buttons.BTN_B):
|
||||
break
|
||||
elif Buttons.is_pressed(Buttons.BTN_A):
|
||||
n = (n+1) % 2
|
||||
ugfx.display_image( 0, 0, img[n] )
|
||||
|
||||
ugfx.clear()
|
||||
app.restart_to_default()
|
After Width: | Height: | Size: 22 KiB |
After Width: | Height: | Size: 50 KiB |
|
@ -11,7 +11,7 @@ Todo:
|
|||
|
||||
"""
|
||||
|
||||
___name___ = "Settings"
|
||||
___title___ = "Settings"
|
||||
___license___ = "MIT"
|
||||
___dependencies___ = ["dialogs", "ugfx_helper", "database", "app", "stack_nav", "wifi"]
|
||||
___categories___ = ["System"]
|
||||
|
@ -33,12 +33,19 @@ def settings_startup_app(state):
|
|||
def settings_wifi(state):
|
||||
wifi.choose_wifi()
|
||||
|
||||
def settings_launcher(state):
|
||||
apps = app.get_apps("Launcher")
|
||||
selection = prompt_option([{"title": a.title, "app": a} for a in apps], text="Select App:", none_text="Back", title="Set default launcher")
|
||||
if selection:
|
||||
app.write_launch_file(selection["app"].name, "default_launcher.txt")
|
||||
|
||||
def settings_main(state):
|
||||
return selection({
|
||||
"Homescreen Name": change_database_string("Set your name", "homescreen.name"),
|
||||
"Homescreen Callsign": change_database_string("Set your callsign", "homescreen.callsign"),
|
||||
"Wifi": settings_wifi,
|
||||
"Startup app": settings_startup_app,
|
||||
"Default Launcher": settings_launcher,
|
||||
"Badge Store": settings_badge_store
|
||||
}, none_text="Exit")
|
||||
|
||||
|
|
|
@ -0,0 +1,187 @@
|
|||
"""Settlers of Catan game board generator"""
|
||||
|
||||
___name___ = "settlers"
|
||||
___license___ = "MIT"
|
||||
___dependencies___ = ["ugfx_helper", "sleep"]
|
||||
___categories___ = ["Games"]
|
||||
___bootstrapped___ = False
|
||||
|
||||
import random, ugfx, ugfx_helper, math, time, buttons
|
||||
from app import App, restart_to_default
|
||||
from tilda import Buttons
|
||||
|
||||
ugfx_helper.init()
|
||||
ugfx.clear(ugfx.BLACK)
|
||||
|
||||
"""
|
||||
This was an experiment in drawing hexagons. Some notes:
|
||||
|
||||
Screen coords are x,y values that locate pixels on the physical display:
|
||||
|
||||
0,0 → → 240,0
|
||||
↓ ↓
|
||||
0,320 → 240,320
|
||||
|
||||
Hex coords are x,y,z values that locate the relative positions of hexagons:
|
||||
|
||||
0,1,-1
|
||||
-1,1,0 ↖ ↑ ↗ 1,0,-1
|
||||
0,0,0
|
||||
-1,0,1 ↙ ↓ ↘ 1,-1,0
|
||||
0,-1,1
|
||||
|
||||
Converting between the two systems can be done by multiplying the x and y
|
||||
coordinates against a matrix. When converting to hex coords, the z value
|
||||
can be computed from the new x and y values because x + y + z must always
|
||||
equal zero.
|
||||
|
||||
"""
|
||||
|
||||
class Hex:
|
||||
# Constant matrix used to convert from hex coords to screen coords
|
||||
matrix = [3.0 * 0.5, 0.0, math.sqrt(3.0) * 0.5, math.sqrt(3.0)]
|
||||
|
||||
# The screen coordinate to use as the origin for hex coordinates,
|
||||
# the centre of hex 0,0,0 will be at this coordinate
|
||||
origin = [math.ceil(ugfx.width() / 2), math.ceil(ugfx.height() / 2)]
|
||||
|
||||
# Size in pixels of the hex, from the centre point to each corner
|
||||
size = 22
|
||||
|
||||
# Possible kinds of resource and the colour it should be rendered
|
||||
kinds = {
|
||||
0: ugfx.html_color(0xd4e157), # Sheep
|
||||
1: ugfx.html_color(0xffc107), # Wheat
|
||||
2: ugfx.html_color(0x993300), # Wood
|
||||
3: ugfx.html_color(0xff0000), # Brick
|
||||
4: ugfx.html_color(0x757575), # Ore
|
||||
5: ugfx.html_color(0xffee55), # Desert (nothing)
|
||||
}
|
||||
|
||||
# Transformations for how to get to the neighbouring hexes
|
||||
directions = {
|
||||
0: [-1, 1, 0], # South West
|
||||
1: [0, 1, -1], # South
|
||||
2: [1, 0, -1], # South East
|
||||
3: [1, -1, 0], # North East
|
||||
4: [0, -1, 1], # North
|
||||
5: [-1, 0, 1], # North West
|
||||
}
|
||||
|
||||
def __init__(self, coords, kind, number, robber):
|
||||
"""Create a new hex at the given hex coordinates, of the given kind of resource"""
|
||||
# Validate coords
|
||||
assert len(coords) == 3, 'Invalid number of hexagon coordinates'
|
||||
assert coords[0] + coords[1] + coords[2] == 0, 'Invalid hexagon coordinate values'
|
||||
self.coords = coords
|
||||
|
||||
# The kind of resource hosted by this hex
|
||||
self.kind = kind
|
||||
|
||||
# The dice roll required to win this resource
|
||||
self.number = number
|
||||
|
||||
# Whether this hex contains the robber
|
||||
self.robber = robber
|
||||
|
||||
# Compute the screen coordinates of the centre of the hex
|
||||
self.centre = Hex.to_screen_coords(self.coords[0], self.coords[1])
|
||||
|
||||
# Generate screen coordinates for each of the corners of the hex
|
||||
self.corners = []
|
||||
for i in range(0, 6):
|
||||
angle = 2.0 * math.pi * (0 - i) / 6
|
||||
offset = [Hex.size * math.cos(angle), Hex.size * math.sin(angle)]
|
||||
self.corners.append([round(self.centre[0] + offset[0]), round(self.centre[1] + offset[1])])
|
||||
|
||||
@staticmethod
|
||||
def to_screen_coords(x, y):
|
||||
"""Returns screen coordinates computed from the given hex coordinates"""
|
||||
newX = (Hex.matrix[0] * x + Hex.matrix[1] * y) * Hex.size
|
||||
newY = (Hex.matrix[2] * x + Hex.matrix[3] * y) * Hex.size
|
||||
return [newX + Hex.origin[0], newY + Hex.origin[1]]
|
||||
|
||||
@staticmethod
|
||||
def get_neighbouring_hex_coords(coords, direction):
|
||||
return [a + b for a, b in zip(coords, Hex.directions[direction])]
|
||||
|
||||
def draw(self):
|
||||
"""Draw the hexagon to the screen"""
|
||||
ugfx.fill_polygon(0, 0, self.corners, Hex.kinds[self.kind])
|
||||
text_offset = Hex.size * 0.5
|
||||
if self.robber:
|
||||
ugfx.text(round(self.centre[0] - text_offset), round(self.centre[1] - text_offset), "Rb ", ugfx.BLACK)
|
||||
else:
|
||||
if self.kind != 5:
|
||||
ugfx.text(round(self.centre[0] - text_offset), round(self.centre[1] - text_offset), "{} ".format(self.number), ugfx.BLACK)
|
||||
|
||||
def clear(self):
|
||||
ugfx.fill_polygon(0, 0, self.corners, ugfx.BLACK)
|
||||
|
||||
|
||||
def board_setup(resources, numbers):
|
||||
"""Generate a random game board"""
|
||||
|
||||
# Two rings of hexes around the centre
|
||||
radius = 2
|
||||
# Choose a starting hex on the outermost ring of hexes
|
||||
choice = random.randrange(0, 6)
|
||||
coords = [0, 0, 0]
|
||||
for i in range(radius):
|
||||
coords = [a + b for a, b in zip(coords, Hex.directions[choice])]
|
||||
|
||||
# Copy lists so we can edit them with impunity
|
||||
r_copy = resources.copy()
|
||||
n_copy = numbers.copy()
|
||||
|
||||
hexes = []
|
||||
while radius > 0:
|
||||
# From the starting hex, go radius hexes in each of the 6 directions
|
||||
for i in list(range((choice + 2) % 6, 6)) + list(range(0, (choice + 2) % 6)):
|
||||
for j in range(radius):
|
||||
# The resources are picked at random from the list
|
||||
resource = r_copy.pop(random.randrange(0, len(r_copy)))
|
||||
# But the dice roll numbers are picked in order, unless it's
|
||||
# the desert in which case that is always 7
|
||||
if resource == 5:
|
||||
number = 7
|
||||
else:
|
||||
number = n_copy.pop(0)
|
||||
hexes.append(Hex(coords, resource, number, number == 7))
|
||||
coords = Hex.get_neighbouring_hex_coords(coords, i)
|
||||
|
||||
# Go into the next ring of hexes (opposite direction of starting choice)
|
||||
coords = Hex.get_neighbouring_hex_coords(coords, (choice + 3) % 6)
|
||||
radius = radius - 1
|
||||
resource = r_copy.pop()
|
||||
if resource == 5:
|
||||
number = 7
|
||||
else:
|
||||
number = n_copy.pop(0)
|
||||
hexes.append(Hex(coords, resource, number, number == 7))
|
||||
return hexes
|
||||
|
||||
|
||||
# List of resources (pre-randomised to combat the not-very random number
|
||||
# generator) and dice rolls (these have a strict order) for 2-4 player games
|
||||
resources = [4, 0, 1, 4, 4, 2, 5, 3, 2, 1, 2, 2, 1, 0, 3, 0, 3, 1, 0]
|
||||
numbers = [5, 2, 6, 3, 8, 10, 9, 12, 11, 4, 8, 10, 9, 4, 5, 6, 3, 11]
|
||||
|
||||
def draw():
|
||||
hexes = board_setup(resources, numbers)
|
||||
for h in hexes:
|
||||
h.clear()
|
||||
time.sleep_ms(100)
|
||||
h.draw()
|
||||
|
||||
ugfx.text(5, 5, 'Press A to generate another ', ugfx.WHITE)
|
||||
draw()
|
||||
|
||||
# Main Loop
|
||||
while True:
|
||||
if buttons.is_triggered(tilda.Buttons.BTN_A):
|
||||
draw()
|
||||
elif buttons.is_triggered(tilda.Buttons.BTN_Menu):
|
||||
break
|
||||
time.sleep_ms(5)
|
||||
restart_to_default()
|
After Width: | Height: | Size: 843 B |
After Width: | Height: | Size: 766 B |
After Width: | Height: | Size: 755 B |
After Width: | Height: | Size: 766 B |
After Width: | Height: | Size: 756 B |
After Width: | Height: | Size: 773 B |
|
@ -1,6 +1,6 @@
|
|||
"""SMS app for reading and sending messages
|
||||
"""
|
||||
___name___ = "SMS"
|
||||
___title___ = "SMS"
|
||||
___license___ = "MIT"
|
||||
___dependencies___ = ["app", "dialogs", "sim800", "ugfx_helper"]
|
||||
___categories___ = ["System"]
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
"""Snake!"""
|
||||
|
||||
___name___ = "Snake"
|
||||
___title___ = "Snake"
|
||||
___license___ = "MIT"
|
||||
___categories___ = ["Games"]
|
||||
___dependencies___ = ["dialogs", "app", "ugfx_helper", "random", "sleep", "buttons"]
|
||||
___dependencies___ = ["dialogs", "app", "ugfx_helper", "sleep", "buttons"]
|
||||
|
||||
import math, ugfx, ugfx_helper, random, sleep, buttons
|
||||
import app, math, ugfx, ugfx_helper, random, sleep, buttons
|
||||
from tilda import Buttons
|
||||
|
||||
ugfx_helper.init()
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
'''
|
||||
A small N channel music player a la 8088 MPH
|
||||
(Demo is only two channels)
|
||||
|
||||
By Molive^SLP
|
||||
'''
|
||||
|
||||
___name___ = "Arp Music Player"
|
||||
___title___ = "Arp Music Player"
|
||||
___license___ = "WTFPL"
|
||||
___dependencies___ = ["ugfx_helper", "speaker"]
|
||||
___categories___ = ["Demo","Sound"]
|
||||
|
||||
import speaker
|
||||
import utime
|
||||
|
||||
from app import restart_to_default
|
||||
from tilda import Buttons
|
||||
|
||||
channels = [ #Supports up to n simultaneous channels.
|
||||
#Each channel will loop it's data independently from the others
|
||||
[ #and channels do not need the same length of data in them.
|
||||
('F4',2), #No. of channels is decided on startup, and all channels are running at any one time.
|
||||
('D#4',2),
|
||||
('D4',2),
|
||||
('C#4',1),
|
||||
('D#4',1),
|
||||
],
|
||||
|
||||
##[
|
||||
##('A#3',4),
|
||||
##],
|
||||
|
||||
##[
|
||||
##('C4',4),
|
||||
##],
|
||||
|
||||
[
|
||||
('F5',0.125),
|
||||
('G#5',0.25),
|
||||
('F5',0.125),
|
||||
('A#5',0.25),
|
||||
('F5',0.125),
|
||||
('C6',0.25),
|
||||
('F5',0.125),
|
||||
('A#5',0.25),
|
||||
('F5',0.25),
|
||||
('G#5',0.25),
|
||||
],
|
||||
|
||||
]
|
||||
|
||||
def prt(s):
|
||||
ugfx.clear()
|
||||
ugfx.text(5,5,str(s),0)
|
||||
|
||||
import ugfx
|
||||
ugfx.init()
|
||||
|
||||
prt("RUNNING SOUND TEST")
|
||||
|
||||
utime.sleep(1)
|
||||
|
||||
prt("Use menu to reboot")
|
||||
|
||||
speaker.enabled(True)
|
||||
|
||||
channel_waits = [ #Add more of these to increase the max channel count
|
||||
[-1,utime.ticks_ms()],
|
||||
[-1,utime.ticks_ms()],
|
||||
[-1,utime.ticks_ms()],
|
||||
[-1,utime.ticks_ms()],
|
||||
]
|
||||
|
||||
current_channel = 0
|
||||
|
||||
while True: #Main awesome loop which handles all music channels. Can handle and arbitrary amount, but lags at high numbers.
|
||||
for channel in channels:
|
||||
##print(channel_waits[current_channel][1]) #Uncomment some of these for more debug info :P
|
||||
if channel_waits[current_channel][1] == 0 or channel_waits[current_channel][1] <= utime.ticks_ms():
|
||||
print("CHANGING CHANNEL "+str(current_channel))
|
||||
channel_waits[current_channel][0] += 1
|
||||
if channel_waits[current_channel][0] == len(channel):
|
||||
channel_waits[current_channel][0] = 0
|
||||
channel_waits[current_channel][1] += (channels[current_channel][channel_waits[current_channel][0]][1]*1000.0)
|
||||
speaker.note(channel[channel_waits[current_channel][0]][0])
|
||||
##print(channel[channel_waits[current_channel][0]])
|
||||
if Buttons.is_pressed(Buttons.BTN_Menu):
|
||||
print("BAIL BAIL BAIL")
|
||||
restart_to_default()
|
||||
current_channel += 1
|
||||
if current_channel == len(channels):
|
||||
current_channel = 0
|
||||
##print(current_channel)
|
||||
utime.sleep(0.03) #Decrease this for more accurate but weirder arps. Comment it out for insane madness
|
||||
|
||||
restart_to_default()
|
|
@ -0,0 +1,118 @@
|
|||
"""Launcher for apps currently installed"""
|
||||
|
||||
___name___ = "Speed Launcher"
|
||||
___license___ = "WTFPL"
|
||||
___categories___ = ["System", "Launcher"]
|
||||
___dependencies___ = ["app", "ugfx_helper"]
|
||||
___launchable___ = False
|
||||
___bootstrapped___ = False
|
||||
|
||||
import ugfx_helper, ugfx, math, buttons
|
||||
from app import *
|
||||
from tilda import Buttons
|
||||
|
||||
APPS_PER_PAGE = 12
|
||||
EMF_PURPLE = 0x800080
|
||||
|
||||
ugfx_helper.init()
|
||||
ugfx.clear(ugfx.html_color(EMF_PURPLE))
|
||||
|
||||
ugfx.set_default_font(ugfx.FONT_SMALL)
|
||||
style = ugfx.Style()
|
||||
style.set_enabled([ugfx.WHITE, ugfx.html_color(EMF_PURPLE), ugfx.html_color(EMF_PURPLE), ugfx.html_color(EMF_PURPLE)])
|
||||
style.set_background(ugfx.html_color(EMF_PURPLE))
|
||||
ugfx.set_default_style(style)
|
||||
|
||||
loadMsg = ugfx.Label(0, 90, ugfx.width(), 20, "Loading apps...", justification=ugfx.Label.CENTER)
|
||||
|
||||
# Load apps in a colourList
|
||||
all_apps = [{"title": a.title, "app": a} for a in get_apps()]
|
||||
|
||||
# Sort apps by alphabetical order
|
||||
all_apps.sort(key=lambda a: a['title'])
|
||||
total_pages = math.ceil(len(all_apps) / APPS_PER_PAGE)
|
||||
|
||||
ugfx.clear(ugfx.html_color(EMF_PURPLE))
|
||||
|
||||
keypad = [
|
||||
Buttons.BTN_1,
|
||||
Buttons.BTN_2,
|
||||
Buttons.BTN_3,
|
||||
Buttons.BTN_4,
|
||||
Buttons.BTN_5,
|
||||
Buttons.BTN_6,
|
||||
Buttons.BTN_7,
|
||||
Buttons.BTN_8,
|
||||
Buttons.BTN_9,
|
||||
Buttons.BTN_Star,
|
||||
Buttons.BTN_0,
|
||||
Buttons.BTN_Hash
|
||||
]
|
||||
|
||||
keypadLabels = [
|
||||
"1",
|
||||
"2",
|
||||
"3",
|
||||
"4",
|
||||
"5",
|
||||
"6",
|
||||
"7",
|
||||
"8",
|
||||
"9",
|
||||
"*",
|
||||
"0",
|
||||
"#"
|
||||
]
|
||||
|
||||
def showPage():
|
||||
global current_page
|
||||
# avoid out of bounds errors
|
||||
current_page = max(1, min(current_page, total_pages))
|
||||
|
||||
start = (current_page - 1) * APPS_PER_PAGE
|
||||
end = start + APPS_PER_PAGE
|
||||
apps_on_current_page = all_apps[start:end]
|
||||
|
||||
# Refresh page
|
||||
ugfx.clear(ugfx.html_color(EMF_PURPLE))
|
||||
|
||||
# Write current page number and arrows
|
||||
ugfx.Label(0, 20, ugfx.width(), 20, "Page {} of {}".format(current_page, total_pages), justification=ugfx.Label.CENTER)
|
||||
|
||||
if current_page > 1:
|
||||
ugfx.fill_polygon(10, 16, [[0, 10], [15, 20], [15, 0]], ugfx.WHITE)
|
||||
|
||||
if current_page < total_pages:
|
||||
ugfx.fill_polygon(ugfx.width() - 30, 16, [[0, 0], [15, 10], [0, 20]], ugfx.WHITE)
|
||||
|
||||
# Write app numbers and names
|
||||
i = 0
|
||||
yOffset = 45
|
||||
xOffset = 0
|
||||
for a in apps_on_current_page:
|
||||
# xOffset = (i % 3) * 8 # offset lines to match the physical layout of the keypad
|
||||
ugfx.area(20 + xOffset, yOffset + 2, 20, 20, ugfx.WHITE)
|
||||
ugfx.text(23 + xOffset, yOffset + 3, keypadLabels[i] + " ", EMF_PURPLE)
|
||||
|
||||
ugfx.Label(46 + xOffset, yOffset + 3, ugfx.width(), 20, a['title'], justification=ugfx.Label.LEFT)
|
||||
yOffset = yOffset + 22
|
||||
i = i + 1
|
||||
|
||||
while True:
|
||||
for key in keypad:
|
||||
keyIndex = keypad.index(key)
|
||||
if buttons.is_pressed(key) and (keyIndex < len(apps_on_current_page)):
|
||||
apps_on_current_page[keyIndex]['app'].boot()
|
||||
break
|
||||
|
||||
if buttons.is_triggered(Buttons.JOY_Right) and (current_page is not total_pages):
|
||||
current_page = current_page + 1
|
||||
return
|
||||
if buttons.is_triggered(Buttons.JOY_Left) and (current_page is not 1):
|
||||
current_page = current_page - 1
|
||||
return
|
||||
|
||||
current_page = 1
|
||||
|
||||
while True:
|
||||
showPage()
|
|
@ -1,6 +1,6 @@
|
|||
"""A big "thank you" to all our Sponsors who made this year's badge possible!"""
|
||||
|
||||
___name___ = "Sponsors"
|
||||
___title___ = "Sponsors"
|
||||
___license___ = "MIT"
|
||||
___dependencies___ = ["wifi", "http", "ugfx_helper", "sleep", "app"]
|
||||
___categories___ = ["EMF"]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
"""A home screen with squares that spin"""
|
||||
|
||||
___name___ = "Squares home"
|
||||
___title___ = "Squares home"
|
||||
___license___ = "MIT"
|
||||
___dependencies___ = ["sleep", "app", "ugfx_helper", "buttons", "homescreen"]
|
||||
___categories___ = ["Homescreens"]
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
Will play music, maybe
|
||||
"""
|
||||
|
||||
___name___ = "Play Music"
|
||||
___title___ = "Star Wars Music"
|
||||
___license___ = "MIT"
|
||||
___categories___ = ["Sound"]
|
||||
___dependencies___ = ["speaker", "shared/sw.png", "buttons"]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
"""Read stories from twentythreemillionstories.org"""
|
||||
|
||||
___name___ = "twenty-three million stories"
|
||||
___title___ = "twenty-three million stories"
|
||||
___license___ = "MIT"
|
||||
___categories___ = ["Other"]
|
||||
___dependencies___ = [ "app", "dialogs", "http", "ugfx_helper", "sleep" ]
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
Todo: fix this, it doesn't work at at the moment
|
||||
"""
|
||||
|
||||
___name___ = "Synthesizers"
|
||||
___title___ = "Synthesizers"
|
||||
___license___ = "MIT"
|
||||
___categories___ = ["Sound"]
|
||||
___dependencies___ = ["speaker", "buttons", "ugfx_helper", "app"]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
"""This app tests all the onboard sensors and system info"""
|
||||
|
||||
___name___ = "System Info"
|
||||
___title___ = "System Info"
|
||||
___license___ = "MIT"
|
||||
___dependencies___ = ["sleep", "app", "sim800"]
|
||||
___categories___ = ["EMF", "System"]
|
||||
|
@ -9,6 +9,7 @@ ___bootstrapped___ = True
|
|||
#import ugfx, os, time, sleep, app, sim800
|
||||
|
||||
import ugfx, app, sim800
|
||||
import os
|
||||
from tilda import Buttons
|
||||
from tilda import Sensors
|
||||
from machine import ADC
|
||||
|
@ -38,6 +39,8 @@ else:
|
|||
|
||||
ugfx.Label(5, 185, 240, 15, simversion)
|
||||
|
||||
ugfx.Label(5, 215, 240, 30, "Badge firmware version:\n{}".format(os.uname().version))
|
||||
|
||||
ugfx.Label(5, 300, 240, 15, "** Hold A or B or MENU to exit **")
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
@echo off
|
||||
python "%CD%/.development\tilda_tools.py" %*
|
|
@ -1,6 +1,6 @@
|
|||
"""This app goes with the Torch Tutorial"""
|
||||
|
||||
___name___ = "Tilda Torch"
|
||||
___title___ = "Tilda Torch"
|
||||
___license___ = "MIT"
|
||||
___dependencies___ = ["sleep", "app"]
|
||||
___categories___ = ["EMF"]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
""" Tildr Dating
|
||||
"""
|
||||
___name___ = "Tildr Dating"
|
||||
___title___ = "Tildr Dating"
|
||||
___license___ = "MIT"
|
||||
___dependencies___ = ["wifi", "http", "ugfx_helper", "sleep", "dialogs", "sim800", "database"]
|
||||
___categories___ = ["Other"]
|
||||
|
|