Example #1
0
def _on_boot_(app_name=None, *app_args, **app_kws):
    __init_dict()
    # >>>> init screen <<<<
    import hal_screen
    hal_screen.init()
    hal_screen.get_framebuffer().fill(0)
    render_boot_image()
    # >>>> init <<<<
    # init your need.
    # import hal_keypad, hal_buzz, hal_led, hal_battery
    # hal_keypad.init()
    # hal_buzz.init()
    # hal_led.init()
    # hal_battery.init()
    # >>>> start <<<<
    if app_name != None:
        boot_app, args, kws = app_name, app_args, app_kws
    else:
        boot_app, args, kws = get_boot_app()
    clear_boot_app()
    clear_boot_image()
    clear_temporary_dir()
    if isinstance(boot_app, str) and boot_app != "":
        # app.clear_boot_app()
        gc.collect()
        run_app(boot_app, *args, **kws)
    else:
        call_component('app_selector')
    print("Program ended, entering REPL mode when running on Play32.")
    usys.exit(0)
Example #2
0
def main(app_name, *args, **kws):
    screen.init()
    keypad.init()
    network_helper.deactive_all()
    screen.get_framebuffer().fill(0)
    screen.get_framebuffer().text("FTP MODE", 0, 0, COLOR_WHITE)
    screen.refresh()
    utime.sleep_ms(1000)
    try:
        ap = network_helper.ap("Play32AP", "12345678")
        wlan = network_helper.connect()
    except Exception as e:
        import usys
        usys.print_exception(e)
        screen.get_framebuffer().fill(0)
        screen.get_framebuffer().text("Error...", 0, 0, COLOR_WHITE)
        screen.get_framebuffer().text("Restart...", 0, 16, COLOR_WHITE)
        screen.refresh()
        utime.sleep_ms(2000)
        return
    wlan_connected = wlan.isconnected()

    def start():
        frame = screen.get_framebuffer()
        frame.fill(0)
        frame.text("\"B\" EXIT", 0, 0, COLOR_WHITE)
        frame.text("-WIFI:", 0, 8, COLOR_WHITE)
        frame.text("Play32AP", 0, 16, COLOR_WHITE)
        frame.text("-PASSWD:", 0, 24, COLOR_WHITE)
        frame.text("12345678", 0, 32, COLOR_WHITE)
        frame.text("-Port 21", 0, 40, COLOR_WHITE)
        frame.text(ap.ifconfig()[0], 0, 48, COLOR_WHITE)
        if wlan.isconnected():
            frame.text(wlan.ifconfig()[0], 0, 56, COLOR_WHITE)
        screen.refresh()
        # uftpd.restart()

    start()
    _loop = True
    while _loop:
        for event in keypad.get_key_event():
            event_type, key = keypad.parse_key_event(event)
            if event_type == keypad.EVENT_KEY_PRESS:
                if key == keypad.KEY_B:
                    # uftpd.stop()
                    wlan.disconnect()
                    wlan.active(False)
                    ap.active(False)
                    _loop = False  # exit
        if wlan.isconnected() != wlan_connected:
            wlan_connected = wlan.isconnected()
            start()
        utime.sleep_ms(100)
    network_helper.deactive_all()
Example #3
0
def render_boot_image():
    boot_image_path = get_boot_image()
    if boot_image_path == None:
        import hal_screen
        hal_screen.refresh()
        boot_image_path = DEFAULT_BOOT_ICON
    if boot_image_path != "":
        from graphic import framebuf_helper
        import framebuf, hal_screen
        if boot_image_path == DEFAULT_BOOT_ICON:
            from buildin_resource.image.play32_icon import PLAY32_ICON_DATA
            iw, ih, idata = PLAY32_ICON_DATA
        else:
            from graphic import pbm
            with open(boot_image_path, 'rb') as ifile:
                iw, ih, _, idata = pbm.read_image(ifile)[:4]
        image = framebuf.FrameBuffer(idata, iw, ih, framebuf.MONO_HLSB)
        image = framebuf_helper.ensure_same_format(
            image, framebuf_helper.MONO_HLSB, iw, ih, hal_screen.get_format(),
            framebuf_helper.get_white_color(hal_screen.get_format()))
        sw, sh = hal_screen.get_size()
        frame = hal_screen.get_framebuffer()
        frame.fill(0)
        frame.blit(image, (sw - iw) // 2, (sh - ih) // 2, 0)
        hal_screen.refresh()
        del idata, image, iw, ih, sw, sh
        return True
    return False
Example #4
0
def render_loading():
    frame = hal_screen.get_framebuffer()
    frame.fill(0)
    width_text = FNT_W * len("loading")
    FONT_8.draw_on_frame("loading", frame, (SCR_W - width_text) // 2,
                         (SCR_H - FNT_H) // 2, COLOR_WHITE)
    hal_screen.refresh()
Example #5
0
def render_point_app():
    frame = hal_screen.get_framebuffer()
    frame.fill(0)
    if app_pointer < 0:
        FONT_8.draw_on_frame("No Apps.", frame, 0, 0, COLOR_WHITE)
        FONT_8.draw_on_frame("Press B to enter FTP mode.", frame, 0, 8,
                             COLOR_WHITE, SCR_W, SCR_H - 8)
        hal_screen.refresh()
        return
    app_name = app_list[app_pointer]
    display_name, _, display_icon = get_app_info(app_name)
    # draw arrows
    offset_x_arrows_right = SCR_W - FNT_W
    FONT_8.draw_on_frame("<", frame, 0, 24, COLOR_WHITE)
    FONT_8.draw_on_frame(">", frame, offset_x_arrows_right, 24, COLOR_WHITE)
    # draw app_name
    if len(display_name) > MAX_NAME_LENGTH:
        display_name = display_name[:MAX_NAME_LENGTH]
    width_display_name = FNT_W * len(display_name)
    offset_x_display_name = (SCR_W - width_display_name) // 2
    FONT_8.draw_on_frame(display_name, frame, offset_x_display_name, 56,
                         COLOR_WHITE)
    # draw icon
    offset_x_icon = (SCR_W - ICON_SIZE_W) // 2
    frame.blit(display_icon, offset_x_icon, 0)
Example #6
0
def render_battery_level():
    frame = hal_screen.get_framebuffer()
    battery_level = str(battery.get_battery_level())
    width_battery_level = FNT_W * len(battery_level)
    offset_x_battery_level = SCR_W - width_battery_level
    width_clear = FNT_W * 3  # 100 battery
    offset_x_clear = SCR_W - width_clear
    frame.fill_rect(offset_x_clear, 0, width_clear, FNT_H, 0)
    FONT_8.draw_on_frame(battery_level, frame, offset_x_battery_level, 0,
                         COLOR_WHITE)
Example #7
0
 def start():
     frame = screen.get_framebuffer()
     frame.fill(0)
     frame.text("\"B\" EXIT", 0, 0, COLOR_WHITE)
     frame.text("-WIFI:", 0, 8, COLOR_WHITE)
     frame.text("Play32AP", 0, 16, COLOR_WHITE)
     frame.text("-PASSWD:", 0, 24, COLOR_WHITE)
     frame.text("12345678", 0, 32, COLOR_WHITE)
     frame.text("-Port 21", 0, 40, COLOR_WHITE)
     frame.text(ap.ifconfig()[0], 0, 48, COLOR_WHITE)
     if wlan.isconnected():
         frame.text(wlan.ifconfig()[0], 0, 56, COLOR_WHITE)
     screen.refresh()
Example #8
0
def dialog_gen(text="", title="", text_yes="OK", text_no="OK"):
    WHITE = get_white_color(hal_screen.get_format())
    SW, SH = hal_screen.get_size()
    F8 = get_font_8px()
    FW, FH = F8.get_font_size()
    TITLE_H = FH if title else 0
    TEXT_H = SH - FH - TITLE_H
    if isinstance(text, str):
        paged_text = PagedText(text, SW, TEXT_H, FW, FH)
    else:
        paged_text = None
    redraw = True
    while True:
        for event in hal_keypad.get_key_event():
            etype, ekey = parse_key_event(event)
            if etype != EVENT_KEY_PRESS:
                continue
            if ekey == KEY_A or ekey == KEY_B:
                yield ekey == KEY_A
            if ekey == KEY_LEFT or ekey == KEY_UP:
                paged_text.page_up()
                redraw = True
            if ekey == KEY_RIGHT or ekey == KEY_DOWN:
                paged_text.page_down()
                redraw = True
        if redraw:
            with cpu_speed_context(FAST):
                frame = hal_screen.get_framebuffer()
                frame.fill(0)
                # draw title
                if TITLE_H > 0:
                    draw_label_header(frame, 0, 0, SW, TITLE_H, F8, WHITE,
                                      title)
                # draw text
                if callable(text):
                    text(frame, 0, TITLE_H, SW, TEXT_H, F8, WHITE)
                else:
                    paged_text.draw(frame, 0, TITLE_H, SW, TEXT_H, F8, WHITE)
                # draw button
                draw_buttons_at_last_line(frame, SW, SH, F8, WHITE, text_yes,
                                          text_no)
                redraw = False
                hal_screen.refresh()
        yield None
Example #9
0
from micropython import const
from play32sys import path, network_helper
from net import microftpd
from graphic import framebuf_console, framebuf_helper, abmfont
import utime, uos, usys, uhashlib, machine
# screen console
import hal_screen, hal_keypad
hal_screen.init()
hal_keypad.init()
FONT_8X4 = abmfont.FontDrawSmallAscii()
WHITE = framebuf_helper.get_white_color(hal_screen.get_format())
SCR_W, SCR_H = hal_screen.get_size()
console = framebuf_console.Console(
    hal_screen.get_framebuffer(),
    SCR_W,
    SCR_H,
    font_draw=FONT_8X4,
    color=WHITE,
    display_update_fun=lambda: hal_screen.refresh())

FRAMEMEWORK_PACK_PATH = "/tmp/framework.pack"
FRAMEMEWORK_PACK_HASH_PATH = "/tmp/framework.pack.sha256"
TYPE_FILE = const(0X00)
TYPE_DIR = const(0X01)
BUFFER_SIZE = const(4096)


def start_ftp():
    ap = network_helper.ap("Play32AP", "12345678")
    utime.sleep(1.0)
    ip = ap.ifconfig()[0]
Example #10
0
def input_slide_gen(title="",
                    text_yes="OK",
                    text_no="CANCEL",
                    slide_start=0,
                    slide_size=100):
    assert slide_start >= 0
    WHITE = get_white_color(hal_screen.get_format())
    SW, SH = hal_screen.get_size()
    F8 = get_font_8px()
    FW, FH = F8.get_font_size()
    TITLE_H = FH if title else 0
    H_SLIDE_H = (SH - FH - TITLE_H) // 2
    SLIDE_W = SW - FW - FW
    value = slide_start
    redraw = True
    while True:
        for event in hal_keypad.get_key_event():
            etype, ekey = parse_key_event(event)
            if etype != EVENT_KEY_PRESS:
                continue
            if ekey == KEY_A or ekey == KEY_B:
                yield value if ekey == KEY_A else -1 - value
            if ekey == KEY_UP or ekey == KEY_DOWN:
                value += int(slide_size *
                             0.1) if ekey == KEY_UP else -int(slide_size * 0.1)
                value = max(slide_start, value)
                value = min(slide_start + slide_size, value)
                redraw = True
            if ekey == KEY_LEFT or ekey == KEY_RIGHT:
                value += 1 if ekey == KEY_RIGHT else -1
                value = max(slide_start, value)
                value = min(slide_start + slide_size, value)
                redraw = True
        if redraw:
            with cpu_speed_context(FAST):
                frame = hal_screen.get_framebuffer()
                frame.fill(0)
                # draw title
                if TITLE_H > 0:
                    draw_label_header(frame, 0, 0, SW, TITLE_H, F8, WHITE,
                                      title)
                # draw slide text
                t = str(value)
                tw = len(t) * FW
                offset_x = (SW - tw) // 2
                offset_y = ((H_SLIDE_H - FH) // 2) + TITLE_H
                F8.draw_on_frame(t, frame, offset_x, offset_y, WHITE, SW, FH)
                # draw slide
                offset_y = ((H_SLIDE_H - FH) // 2) + H_SLIDE_H + TITLE_H
                ava_w = SLIDE_W - 4
                bar_w = int(ava_w * (value / slide_size))
                bar_w = min(ava_w, bar_w)
                bar_w = max(1, bar_w)
                frame.rect(FW, offset_y, SLIDE_W, FH, WHITE)
                frame.fill_rect(FW + 2, offset_y + 2, bar_w, FH - 4, WHITE)
                # draw button
                draw_buttons_at_last_line(frame, SW, SH, F8, WHITE, text_yes,
                                          text_no)
                redraw = False
                hal_screen.refresh()
        yield None
Example #11
0
def input_text_gen(text="", title="Edit Text"):
    # test
    # im = InputMethod(get_input_dict())
    # for c in b"long":
    #     im.input_byte(c)
    # print(im.all_words())
    # test end
    WHITE = get_white_color(hal_screen.get_format())
    SW, SH = hal_screen.get_size()
    F8 = get_font_8px()
    FW, FH = F8.get_font_size()
    EDIT_TEXT_H = SH - (FH * 7)
    frame = hal_screen.get_framebuffer()
    kbdl_piy = _KBD_PINYIN()
    kbdl_txt = _KBD_TEXT(text.replace("\n", ""))
    kbdl_spc = _KBD_OPTION(_SPECIAL_C)
    kbdl_num = _KBD_LINE(_KBD_C_1)
    kbdl_a2n = _KBD_LINE(_KBD_C_2)
    kbdl_o2z = _KBD_LINE(_KBD_C_3)
    kbdl_sym = _KBD_LINE(_KBD_C_4)
    kbdl_mod = _KBD_OPTION(_MODE_C)
    kbd_list = [
        kbdl_txt,
        kbdl_spc,
        kbdl_num,
        kbdl_a2n,
        kbdl_o2z,
        kbdl_sym,
        kbdl_mod,
    ]
    redraw = True
    refresh = False
    focus_line = 0
    focus_col = 0
    # init
    kbdl_spc.change_op(1)
    focus_col = kbd_list[focus_line].set_focus(focus_col)
    kbd_line_size = len(kbd_list)
    mode = 0  # 0: a 1: A 2: δΈ­
    while True:
        action_code = None
        for event in hal_keypad.get_key_event():
            etype, ekey = parse_key_event(event)
            if etype != EVENT_KEY_PRESS:
                continue
            if ekey == KEY_A:
                kbd = kbd_list[focus_line]
                if isinstance(kbd, _KBD_LINE):
                    action_code = kbd.get_focused_text()
                elif isinstance(kbd, _KBD_OPTION) and kbd != kbdl_mod:
                    action_code = kbd.get_focused_text()
                elif isinstance(kbd, _KBD_PINYIN):
                    # select word
                    for v in kbdl_piy.select_word_gen():
                        yield None
                        if v == None:
                            continue
                        if len(v) > 0:
                            kbdl_txt.insert(v)
                        break
                    redraw = True
                    # select word end
            if ekey == KEY_B:
                kbd = kbd_list[focus_line]
                if isinstance(kbd, (_KBD_TEXT, _KBD_PINYIN, _KBD_LINE)):
                    action_code = _SPECIAL_C[0]  # delete
            if ekey == KEY_LEFT or ekey == KEY_RIGHT:
                off = 1 if ekey == KEY_RIGHT else -1
                kbd = kbd_list[focus_line]
                if isinstance(kbd, _KBD_TEXT):
                    kbd.move_cursor(off)
                elif isinstance(kbd, _KBD_LINE):
                    focus_col = kbd.set_focus(focus_col + off)
                elif isinstance(kbd, _KBD_OPTION):
                    kbd.change_op(off)
                    if kbd == kbdl_mod:  # special
                        action_code = kbd.get_focused_text()
            if ekey == KEY_UP or ekey == KEY_DOWN:
                off = 1 if ekey == KEY_DOWN else -1
                newf = focus_line + off
                # newf = max(newf, 0)
                # newf = min(newf, kbd_line_size - 1)
                newf = newf % kbd_line_size
                if newf != focus_line:
                    kbd_list[focus_line].set_focus(None)
                    kbd_list[newf].set_focus(focus_col)
                    focus_line = newf
        # process action
        if isinstance(action_code, str):
            # print(action_code)
            if action_code.startswith("mode:"):
                if mode == 2:
                    # from mode 2
                    kbd_list[2] = kbdl_num
                    kbdl_num.redraw()
                if action_code == _MODE_C[2]:
                    mode = 2
                elif action_code == _MODE_C[1]:
                    mode = 1
                else:
                    mode = 0
                if mode == 2:
                    # to mode 2
                    kbd_list[2] = kbdl_piy
                    kbdl_piy.redraw()
            elif action_code == _SPECIAL_C[-1]:
                # confirm
                yield kbdl_txt.get_text()
            elif action_code == _SPECIAL_C[0]:
                # delete
                if mode == 2 and kbdl_piy.can_delete():
                    kbdl_piy.delete()
                else:
                    kbdl_txt.delete()
            else:
                # insert
                if mode == 2:
                    if action_code == " ":
                        # select word
                        for v in kbdl_piy.select_word_gen():
                            yield None
                            if v == None:
                                continue
                            if len(v) > 0:
                                kbdl_txt.insert(v)
                            break
                        redraw = True
                        # select word end
                    else:
                        kbdl_piy.insert(action_code)
                elif mode == 1:
                    try:
                        kbdl_txt.insert(action_code.upper())
                    except:
                        kbdl_txt.insert(action_code)
                else:
                    kbdl_txt.insert(action_code)
        # draw all element
        if redraw:
            with cpu_speed_context(FAST):
                frame.fill(0)
                draw_label_header(frame, 0, 0, SW, FH, F8, WHITE, title)
                refresh = True
        for i in range(len(kbd_list)):
            if kbd_list[i] == kbdl_txt:
                refresh |= kbdl_txt.draw(frame, 0, FH, SW, EDIT_TEXT_H, F8,
                                         WHITE, redraw)
                continue
            base_y = SH - FH * (kbd_line_size - i)
            refresh |= kbd_list[i].draw(frame, 0, base_y, SW, FH, F8, WHITE,
                                        redraw)
        redraw = False
        if refresh:
            with cpu_speed_context(FAST):
                hal_screen.refresh()
                refresh = False
        yield None
Example #12
0
def progress_gen(text="", title="", progress=None):
    WHITE = get_white_color(hal_screen.get_format())
    SW, SH = hal_screen.get_size()
    F8 = get_font_8px()
    FW, FH = F8.get_font_size()
    TITLE_H = FH if title else 0
    TEXT_H = SH - FH - TITLE_H
    BAR_AW = SW - 4
    BAR_AH = FH - 4
    if isinstance(text, str):
        paged_text = PagedText(text, SW, TEXT_H, FW, FH)
    else:
        paged_text = None
    running_offset = 0.0
    running_t = ticks_ms()
    while True:
        if isinstance(progress, (int, float)):
            inf = False
            if isinstance(progress, int):
                progress = progress / 100.0
        else:
            inf = True
        for event in hal_keypad.get_key_event():
            etype, ekey = parse_key_event(event)
            if etype != EVENT_KEY_PRESS:
                continue
            if ekey == KEY_LEFT or ekey == KEY_UP:
                paged_text.page_up()
                redraw = True
            if ekey == KEY_RIGHT or ekey == KEY_DOWN:
                paged_text.page_down()
                redraw = True
        # draw
        frame = hal_screen.get_framebuffer()
        frame.fill(0)
        # draw title
        if TITLE_H > 0:
            draw_label_header(frame, 0, 0, SW, TITLE_H, F8, WHITE, title)
        # draw text
        if callable(text):
            text(frame, 0, TITLE_H, SW, TEXT_H, F8, WHITE)
        else:
            paged_text.draw(frame, 0, TITLE_H, SW, TEXT_H, F8, WHITE)
        # draw progress bar
        base_y = TEXT_H + TITLE_H
        frame.rect(0, base_y, SW, FH, WHITE)
        if not inf:
            bar_w = int(BAR_AW * progress)
            bar_w = min(BAR_AW, bar_w)
            bar_w = max(1, bar_w)
            frame.fill_rect(2, base_y + 2, bar_w, BAR_AH, WHITE)
        else:
            now = ticks_ms()
            diff = ticks_diff(now, running_t)
            running_t = now
            running_offset = running_offset + diff * 32 / 1_000  # 32 pixel/sec
            while running_offset > FW:
                running_offset -= FW
            p_bottom = SH - 1
            off_x = FW // 2
            for x in range(-FW - FW, SW, FW):
                x += int(running_offset)
                frame.line(x, p_bottom, x + off_x, base_y, WHITE)
            frame.rect(1, base_y + 1, SW - 2, FH - 2, 0)
        frame.pixel(0, base_y, 0)
        frame.pixel(SW - 1, base_y, 0)
        frame.pixel(0, SH - 1, 0)
        frame.pixel(SW - 1, SH - 1, 0)
        hal_screen.refresh()
        progress = (yield None)
Example #13
0
def select_list_gen(title="", options=[], text_yes="OK", text_no="CANCEL"):
    WHITE = get_white_color(hal_screen.get_format())
    SW, SH = hal_screen.get_size()
    F8 = get_font_8px()
    FW, FH = F8.get_font_size()
    OP_SIZE = len(options)
    SCROLL_BAR_W = 4 if OP_SIZE > 1 else 0
    LIST_AREA_W = SW - SCROLL_BAR_W
    LIST_AREA_H = SH - FH - FH
    LIST_PAGE_SIZE = LIST_AREA_H // FH
    LIST_OFFSET_X = (LIST_AREA_W % FW) // 2
    if OP_SIZE > 0:
        paged_text = PagedText(options[0],
                               LIST_AREA_W,
                               FH,
                               FW,
                               FH,
                               style_inline=True)
    else:
        paged_text = PagedText("", LIST_AREA_W, FH, FW, FH, style_inline=True)
    pointer = 0
    redraw = True
    while True:
        for event in hal_keypad.get_key_event():
            etype, ekey = parse_key_event(event)
            if etype != EVENT_KEY_PRESS:
                continue
            if ekey == KEY_A or ekey == KEY_B:
                yield pointer if ekey == KEY_A and OP_SIZE > 0 else -1 - pointer
            if ekey == KEY_LEFT:
                paged_text.page_up()
                redraw = True
            if ekey == KEY_RIGHT:
                paged_text.page_down()
                redraw = True
            if OP_SIZE > 0 and (ekey == KEY_UP or ekey == KEY_DOWN):
                pointer += 1 if ekey == KEY_DOWN else -1
                pointer %= OP_SIZE
                paged_text = PagedText(options[pointer],
                                       LIST_AREA_W,
                                       FH,
                                       FW,
                                       FH,
                                       style_inline=True)
                redraw = True
        if redraw:
            with cpu_speed_context(FAST):
                frame = hal_screen.get_framebuffer()
                frame.fill(0)
                # draw title
                draw_label_header(frame, 0, 0, SW, FH, F8, WHITE, title)
                # draw options
                page = pointer // LIST_PAGE_SIZE
                for i in range(OP_SIZE):
                    if i // LIST_PAGE_SIZE != page:
                        continue
                    offset_y = FH + FH * (i % LIST_PAGE_SIZE)
                    if i == pointer:
                        frame.fill_rect(0, offset_y, LIST_AREA_W, FH, WHITE)
                        paged_text.draw(frame, 0, offset_y, LIST_AREA_W, FH,
                                        F8, 0)
                    else:
                        F8.draw_on_frame(options[i], frame, LIST_OFFSET_X,
                                         offset_y, WHITE, LIST_AREA_W, FH)
                # draw scroll bar
                if SCROLL_BAR_W > 0:
                    area_h = LIST_AREA_H - 4
                    scroll_h = max(int(area_h / OP_SIZE), 1)
                    scroll_start = int(pointer * area_h / OP_SIZE)
                    frame.fill_rect(SW - 3, FH + scroll_start + 2, 2, scroll_h,
                                    WHITE)
                    frame.hline(SW - 4, FH, 4, WHITE)
                    frame.hline(SW - 4, FH + LIST_AREA_H - 1, 4, WHITE)
                # draw button
                draw_buttons_at_last_line(frame, SW, SH, F8, WHITE, text_yes,
                                          text_no)
                redraw = False
                hal_screen.refresh()
        yield None
Example #14
0
def select_menu_gen(text="",
                    title="",
                    options=[],
                    text_yes="OK",
                    text_no="CANCEL"):
    WHITE = get_white_color(hal_screen.get_format())
    SW, SH = hal_screen.get_size()
    F8 = get_font_8px()
    FW, FH = F8.get_font_size()
    TITLE_H = FH if title else 0
    TEXT_H = SH - FH - FH - TITLE_H
    OP_SIZE = len(options)
    if isinstance(text, str):
        paged_text = PagedText(text, SW, TEXT_H, FW, FH)
    else:
        paged_text = None
    pointer = 0
    redraw = True
    while True:
        for event in hal_keypad.get_key_event():
            etype, ekey = parse_key_event(event)
            if etype != EVENT_KEY_PRESS:
                continue
            if ekey == KEY_A or ekey == KEY_B:
                yield pointer if ekey == KEY_A and OP_SIZE > 0 else -1 - pointer
            if ekey == KEY_UP:
                paged_text.page_up()
                redraw = True
            if ekey == KEY_DOWN:
                paged_text.page_down()
                redraw = True
            if OP_SIZE > 0 and ekey == KEY_LEFT:
                pointer -= 1
                pointer %= OP_SIZE
                redraw = True
            if OP_SIZE > 0 and ekey == KEY_RIGHT:
                pointer += 1
                pointer %= OP_SIZE
                redraw = True
        if redraw:
            with cpu_speed_context(FAST):
                frame = hal_screen.get_framebuffer()
                frame.fill(0)
                # draw title
                if TITLE_H > 0:
                    draw_label_header(frame, 0, 0, SW, TITLE_H, F8, WHITE,
                                      title)
                # draw text
                if callable(text):
                    text(frame, 0, TITLE_H, SW, TEXT_H, F8, WHITE)
                else:
                    paged_text.draw(frame, 0, TITLE_H, SW, TEXT_H, F8, WHITE)
                # draw options
                if OP_SIZE > 0:
                    draw_label_nav(frame, 0, TEXT_H + TITLE_H, SW, FH, F8,
                                   WHITE, options[pointer])
                # draw button
                draw_buttons_at_last_line(frame, SW, SH, F8, WHITE, text_yes,
                                          text_no)
                redraw = False
                hal_screen.refresh()
        yield None