trezor-core/src/trezor/ui/__init__.py

131 lines
3.0 KiB
Python
Raw Normal View History

2017-06-07 10:06:26 -07:00
from micropython import const
import sys
2016-05-17 09:55:11 -07:00
import math
import utime
2017-06-14 09:47:38 -07:00
from trezorui import Display
2017-09-16 06:00:31 -07:00
from trezor import io
from trezor import loop
from trezor import res
2016-05-17 09:55:11 -07:00
2016-05-17 09:37:26 -07:00
display = Display()
2016-05-17 09:55:11 -07:00
2017-09-25 08:23:24 -07:00
# for desktop platforms, we need to refresh the display after each frame
2017-09-16 06:00:31 -07:00
if sys.platform != 'trezor':
loop.after_step_hook = display.refresh
2017-09-25 08:23:24 -07:00
# font styles
NORMAL = Display.FONT_NORMAL
BOLD = Display.FONT_BOLD
MONO = Display.FONT_MONO
2016-05-17 09:55:11 -07:00
2017-09-25 08:23:24 -07:00
# display width and height
SCREEN = const(240)
2016-05-17 09:55:11 -07:00
2017-09-25 08:23:24 -07:00
def lerpi(a: int, b: int, t: float) -> int:
return int(a + t * (b - a))
2016-05-17 09:55:11 -07:00
2017-03-20 13:40:53 -07:00
2017-09-25 08:23:24 -07:00
def rgb(r: int, g: int, b: int) -> int:
return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | ((b & 0xF8) >> 3)
def blend(ca: int, cb: int, t: float) -> int:
return rgb(
lerpi((ca >> 8) & 0xF8, (cb >> 8) & 0xF8, t),
lerpi((ca >> 3) & 0xFC, (cb >> 3) & 0xFC, t),
lerpi((ca << 3) & 0xF8, (cb << 3) & 0xF8, t))
2017-03-30 08:35:15 -07:00
2017-09-25 08:23:24 -07:00
from trezor.ui.style import *
2016-05-17 09:55:11 -07:00
2017-09-25 08:23:24 -07:00
def contains(area: tuple, pos: tuple) -> bool:
2016-05-17 09:55:11 -07:00
x, y = pos
ax, ay, aw, ah = area
return ax <= x <= ax + aw and ay <= y <= ay + ah
2017-09-25 08:23:24 -07:00
def rotate(pos: tuple) -> tuple:
r = display.orientation()
if r == 0:
return pos
x, y = pos
if r == 90:
return (y, 240 - x)
if r == 180:
return (240 - x, 240 - y)
if r == 270:
return (240 - y, x)
2016-05-17 09:55:11 -07:00
def pulse(delay: int):
2017-09-16 06:00:31 -07:00
while True:
# normalize sin from interval -1:1 to 0:1
yield 0.5 + 0.5 * math.sin(utime.ticks_us() / delay)
async def alert(count: int=3):
2017-09-16 06:00:31 -07:00
short_sleep = loop.sleep(20000)
long_sleep = loop.sleep(80000)
current = display.backlight()
for i in range(count * 2):
if i % 2 == 0:
display.backlight(BACKLIGHT_MAX)
2017-09-16 06:00:31 -07:00
yield short_sleep
else:
display.backlight(BACKLIGHT_NORMAL)
2017-09-16 06:00:31 -07:00
yield long_sleep
display.backlight(current)
async def backlight_slide(val: int, delay: int=20000, step: int=1):
2017-09-16 06:00:31 -07:00
sleep = loop.sleep(delay)
current = display.backlight()
for i in range(current, val, -step if current > val else step):
display.backlight(i)
2017-09-16 06:00:31 -07:00
await sleep
def layout(f):
delay = const(1000)
step = const(3)
async def inner(*args, **kwargs):
await backlight_slide(BACKLIGHT_DIM, delay, step)
slide = backlight_slide(BACKLIGHT_NORMAL, delay, step)
try:
loop.schedule(slide)
return await f(*args, **kwargs)
finally:
loop.close(slide)
return inner
2017-09-26 03:05:05 -07:00
def header(title: str, icon: bytes=ICON_RESET, fg: int=BG, bg: int=BG):
2017-09-16 06:00:31 -07:00
display.bar(0, 0, 240, 32, bg)
if icon is not None:
display.icon(8, 4, res.load(icon), fg, bg)
display.text(8 + 24 + 2, 24, title, BOLD, fg, bg)
2017-02-08 07:19:33 -08:00
class Widget:
def render(self):
pass
def touch(self, event, pos):
pass
def __iter__(self):
2017-09-16 06:00:31 -07:00
touch = loop.select(io.TOUCH)
result = None
while result is None:
2017-02-08 07:19:33 -08:00
self.render()
2017-09-16 06:00:31 -07:00
event, *pos = yield touch
2017-02-08 07:19:33 -08:00
result = self.touch(event, pos)
return result