Esempio n. 1
0
    def __init__(self, title="Enter account number", current_val='0'):
        super().__init__()
        self.title = add_label(title, scr=self, y=PADDING, style="title")

        self.note = add_label("Current account number: %s" % current_val,
                              scr=self,
                              style="hint")
        self.note.align(self.title, lv.ALIGN.OUT_BOTTOM_MID, 0, 5)

        self.kb = lv.btnm(self)
        self.kb.set_map(self.NUMERIC_CHARSET)
        self.kb.set_width(HOR_RES)
        self.kb.set_height(VER_RES // 2)
        self.kb.align(self, lv.ALIGN.IN_BOTTOM_MID, 0, 0)

        lbl = add_label('', style="title", scr=self)
        lbl.set_y(PADDING + 150)
        lbl.set_width(40)
        lbl.set_x(PADDING)

        self.ta = lv.ta(self)
        self.ta.set_text("")
        self.ta.set_width(HOR_RES - 2 * PADDING - 40)
        self.ta.set_x(PADDING + 40)
        self.ta.set_y(PADDING + 150)
        self.ta.set_cursor_type(lv.CURSOR.HIDDEN)
        self.ta.set_one_line(True)
        self.kb.set_event_cb(self.cb)
Esempio n. 2
0
    def __init__(self,
                 title="Enter your bip-39 password:"******"It is never stored on the device",
                 suggestion=""):
        super().__init__()
        self.title = add_label(title, scr=self, style="title")
        if note is not None:
            self.note = add_label(note, scr=self, style="hint")
            self.note.align(self.title, lv.ALIGN.OUT_BOTTOM_MID, 0, 5)

        self.kb = HintKeyboard(self)
        self.kb.set_map(type(self).CHARSET)
        self.kb.set_width(HOR_RES)
        self.kb.set_height(VER_RES // 3)
        self.kb.align(self, lv.ALIGN.IN_BOTTOM_MID, 0, 0)

        self.ta = lv.ta(self)
        self.ta.set_text(suggestion)
        # self.ta.set_pwd_mode(True)
        self.ta.set_width(HOR_RES - 2 * PADDING)
        self.ta.set_x(PADDING)
        self.ta.set_text_align(lv.label.ALIGN.CENTER)
        self.ta.set_y(PADDING + 150)
        # self.ta.set_cursor_type(lv.CURSOR.HIDDEN)
        self.ta.set_one_line(True)
        # self.ta.set_pwd_show_time(0)

        self.kb.set_event_cb(self.cb)
    def show_password_input(self):
        self.screen = lv.obj()
        self.wallet_paddword_screen_label = lv.label(self.screen)
        self.wallet_paddword_screen_label.set_text(
            "   Enter your recovery\nphrase password (if any)")
        self.wallet_paddword_screen_label.align(self.screen, lv.ALIGN.CENTER,
                                                0, -350)

        self.password_input = lv.ta(self.screen)
        self.password_input.set_one_line(True)
        self.password_input.set_text("")
        self.password_input.align(self.screen, lv.ALIGN.CENTER, 0, -275)

        self.password_back_button = lv.btn(self.screen)
        self.password_back_button.set_size(125, 60)
        self.password_back_button_label = lv.label(self.password_back_button)
        self.password_back_button_label.set_text("Back")
        self.password_back_button.align(self.screen, lv.ALIGN.CENTER, -100,
                                        -150)
        self.password_back_button.set_event_cb(
            self.handle_password_back_button)

        self.password_finish_button = lv.btn(self.screen)
        self.password_finish_button.set_size(150, 60)
        self.password_finish_button_label = lv.label(
            self.password_finish_button)
        self.password_finish_button_label.set_text("Finish")
        self.password_finish_button.align(self.screen, lv.ALIGN.CENTER, 100,
                                          -150)
        self.password_finish_button.set_event_cb(
            self.handle_password_finish_button)

        self.toggle_keyboard_button = lv.btn(self.screen)
        self.toggle_keyboard_button.set_size(230, 100)
        self.toggle_keyboard_button_label = lv.label(
            self.toggle_keyboard_button)
        self.toggle_keyboard_button_label.set_text(
            self.UPPER_CASE_KEYBOARD_SYMBOL)
        self.toggle_keyboard_button.align(self.screen, lv.ALIGN.CENTER, -118,
                                          50)
        self.toggle_keyboard_button.set_event_cb(
            self.handle_toggle_password_keyboard_button)

        self.backspace_button = lv.btn(self.screen)
        self.backspace_button.set_size(230, 100)
        self.backspace_button_label = lv.label(self.backspace_button)
        self.backspace_button_label.set_text("Bksp")
        self.backspace_button.align(self.screen, lv.ALIGN.CENTER, 118, 50)
        self.backspace_button.set_event_cb(
            self.handle_password_backspace_button)

        self.keyboard = lv.kb(self.screen)
        self.keyboard.set_height(300)
        self.keyboard.align(self.screen, lv.ALIGN.IN_BOTTOM_MID, 0, 0)
        self.keyboard.set_map(self.PASSWORD_KEYBOARD_MAP_LOWER_CASE)
        self.keyboard.set_ta(self.password_input)

        lv.scr_load(self.screen)
Esempio n. 4
0
 def __init__(self, parent, x, y, width, height):
     self.lv_obj = lv.ta(parent)
     self.x = x
     self.y = y
     self.width = width
     self.height = height
     self.lv_obj.set_size(self.width, self.height)
     self.lv_obj.set_pos(x, y)
     self.lv_obj.set_cursor_type(lv.CURSOR.NONE)
Esempio n. 5
0
    def __init__(self, title="Enter your PIN code", note=None, get_word=None, subtitle=None):
        super().__init__()
        self.title = add_label(title, scr=self, y=PADDING, style="title")
        if subtitle is not None:
            lbl = add_label(subtitle, scr=self, style="hint")
            lbl.set_recolor(True)
            lbl.align(self.title, lv.ALIGN.OUT_BOTTOM_MID, 0, 10)
        if note is not None:
            lbl = add_label(note, scr=self, style="hint")
            lbl.align(self.title, lv.ALIGN.OUT_BOTTOM_MID, 0, 180)
        self.get_word = get_word
        if get_word is not None:
            self.words = add_label(get_word(b""), scr=self)
            self.words.align(self.title, lv.ALIGN.OUT_BOTTOM_MID, 0, 210)
        btnm = lv.btnm(self)
        # shuffle numbers to make sure
        # no constant fingerprints left on screen
        buttons = ["%d" % i for i in range(0, 10)]
        btnmap = []
        for j in range(3):
            for i in range(3):
                v = rng.get_random_bytes(1)[0] % len(buttons)
                btnmap.append(buttons.pop(v))
            btnmap.append("\n")
        btnmap = btnmap + [lv.SYMBOL.CLOSE, buttons.pop(), lv.SYMBOL.OK, ""]
        btnm.set_map(btnmap)
        btnm.set_width(HOR_RES)
        btnm.set_height(HOR_RES)
        btnm.align(self, lv.ALIGN.IN_BOTTOM_MID, 0, 0)
        # increase font size
        style = lv.style_t()
        lv.style_copy(style, btnm.get_style(lv.btnm.STYLE.BTN_REL))
        style.text.font = lv.font_roboto_28
        # remove feedback on press to avoid sidechannels
        btnm.set_style(lv.btnm.STYLE.BTN_REL, style)
        btnm.set_style(lv.btnm.STYLE.BTN_PR, style)

        self.pin = lv.ta(self)
        self.pin.set_text("")
        self.pin.set_pwd_mode(True)
        style = lv.style_t()
        lv.style_copy(style, styles["theme"].style.ta.oneline)
        style.text.font = lv.font_roboto_28
        style.text.color = styles["theme"].style.scr.text.color
        style.text.letter_space = 15
        self.pin.set_style(lv.label.STYLE.MAIN, style)
        self.pin.set_width(HOR_RES - 2 * PADDING)
        self.pin.set_x(PADDING)
        self.pin.set_y(PADDING + 50)
        self.pin.set_cursor_type(lv.CURSOR.HIDDEN)
        self.pin.set_one_line(True)
        self.pin.set_text_align(lv.label.ALIGN.CENTER)
        self.pin.set_pwd_show_time(0)
        self.pin.align(btnm, lv.ALIGN.OUT_TOP_MID, 0, -150)

        btnm.set_event_cb(feed_rng(self.cb))
Esempio n. 6
0
    def show_set_password(self):
        self.screen = lv.obj()

        self.create_password_screen_label = lv.label(self.screen)
        self.create_password_screen_label.set_text("Set a password (optional)")
        self.create_password_screen_label.align(self.screen, lv.ALIGN.CENTER,
                                                0, -360)

        self.password_input = lv.ta(self.screen)
        self.password_input.set_one_line(True)
        self.password_input.set_text("")
        self.password_input.align(self.screen, lv.ALIGN.CENTER, 0, -285)

        self.submit_password_button = lv.btn(self.screen)
        self.submit_password_button.set_size(125, 60)
        self.submit_password_button.align(self.screen, lv.ALIGN.CENTER, 0,
                                          -220)
        self.submit_password_button.set_event_cb(
            self.handle_submit_password_button)
        self.submit_password_button_label = lv.label(
            self.submit_password_button)
        self.submit_password_button_label.set_text("Set")

        self.password_tips_label = lv.label(self.screen)
        self.password_tips_label.set_text(
            "-Avoid common passwords\n"
            "-Use at least 11 characters\n"
            "-Use letters, numbers and\nspecial characters")
        self.password_tips_label.align(self.screen, lv.ALIGN.CENTER, 0, -90)

        self.toggle_keyboard_button = lv.btn(self.screen)
        self.toggle_keyboard_button.set_size(230, 100)
        self.toggle_keyboard_button_label = lv.label(
            self.toggle_keyboard_button)
        self.toggle_keyboard_button_label.set_text(
            self.UPPER_CASE_KEYBOARD_SYMBOL)
        self.toggle_keyboard_button.align(self.screen, lv.ALIGN.CENTER, -118,
                                          50)
        self.toggle_keyboard_button.set_event_cb(
            self.handle_toggle_password_keyboard_button)

        self.backspace_button = lv.btn(self.screen)
        self.backspace_button.set_size(230, 100)
        self.backspace_button_label = lv.label(self.backspace_button)
        self.backspace_button_label.set_text("Bksp")
        self.backspace_button.align(self.screen, lv.ALIGN.CENTER, 118, 50)
        self.backspace_button.set_event_cb(
            self.handle_password_backspace_button)

        self.keyboard = lv.kb(self.screen)
        self.keyboard.set_height(300)
        self.keyboard.align(self.screen, lv.ALIGN.IN_BOTTOM_MID, 0, 0)
        self.keyboard.set_map(self.PASSWORD_KEYBOARD_MAP_LOWER_CASE)
        self.keyboard.set_ta(self.password_input)

        lv.scr_load(self.screen)
    def show_phrase_input(self):
        self.phrase_input_length = 0

        self.screen = lv.obj()

        self.recovery_phrase_length_screen_label = lv.label(self.screen)
        self.recovery_phrase_length_screen_label.set_text(
            "Recovery phrase word {page_number}/{recovery_phrase_target_length}"
            .format(page_number=len(self.recovery_phrase) + 1,
                    recovery_phrase_target_length=self.
                    recovery_phrase_target_length))
        self.recovery_phrase_length_screen_label.align(self.screen,
                                                       lv.ALIGN.CENTER, 0,
                                                       -350)

        self.recovery_phrase_input = lv.ta(self.screen)
        self.recovery_phrase_input.set_one_line(True)
        self.recovery_phrase_input.set_text("")
        self.recovery_phrase_input.set_max_length(16)
        self.recovery_phrase_input.align(self.screen, lv.ALIGN.CENTER, 0, -275)
        self.recovery_phrase_input.set_event_cb(
            self.handle_recovery_phrase_input_change)
        # need to keep track of this for the autocomplete
        self.autocompleted = False
        self.phrase_input_length = 0

        self.prev_recovery_phrase_word_button = lv.btn(self.screen)
        self.prev_recovery_phrase_word_button.set_size(125, 60)
        self.prev_recovery_phrase_word_button_label = lv.label(
            self.prev_recovery_phrase_word_button)
        self.prev_recovery_phrase_word_button_label.set_text("Back")
        self.prev_recovery_phrase_word_button.align(self.screen,
                                                    lv.ALIGN.CENTER, -100,
                                                    -150)
        self.prev_recovery_phrase_word_button.set_event_cb(
            self.handle_previous_recovery_phrase_word_button)

        self.next_recovery_phrase_word_button = lv.btn(self.screen)
        self.next_recovery_phrase_word_button.set_size(125, 60)
        self.next_recovery_phrase_word_button_label = lv.label(
            self.next_recovery_phrase_word_button)
        self.next_recovery_phrase_word_button_label.set_text("Next")
        self.next_recovery_phrase_word_button.align(self.screen,
                                                    lv.ALIGN.CENTER, 100, -150)
        self.next_recovery_phrase_word_button.set_state(BUTTON_DISABLED_STATE)
        self.next_recovery_phrase_word_button.set_event_cb(
            self.handle_next_recovery_phrase_word_button)

        self.keyboard = lv.kb(self.screen)
        self.keyboard.set_map(self.RECOVERY_PHRASE_KEYBOARD_MAP)
        self.keyboard.set_ta(self.recovery_phrase_input)

        lv.scr_load(self.screen)
Esempio n. 8
0
def ask_for_password(cb_continue, title="Enter your password (optional)"):
    scr = switch_to_new_screen()
    add_label(title, style="title")

    btnm = lv.btnm(scr)
    btnm.set_map(CHARSET)
    btnm.set_width(HOR_RES)
    btnm.set_height(VER_RES // 3)
    btnm.align(scr, lv.ALIGN.IN_BOTTOM_MID, 0, 0)

    ta = lv.ta(scr)
    ta.set_text("")
    # ta.set_pwd_mode(True)
    ta.set_width(HOR_RES - 2 * PADDING)
    ta.set_x(PADDING)
    ta.set_text_align(lv.label.ALIGN.CENTER)
    ta.set_y(PADDING + 150)
    ta.set_cursor_type(lv.CURSOR.HIDDEN)
    ta.set_one_line(True)

    # ta.set_pwd_show_time(0)
    def cb(obj, event):
        if event == lv.EVENT.RELEASED:
            c = obj.get_active_btn_text()
            if c is None:
                return
            if c[0] == lv.SYMBOL.LEFT:
                ta.del_char()
            elif c == lv.SYMBOL.UP or c == lv.SYMBOL.DOWN:
                for i, ch in enumerate(CHARSET):
                    if ch.isalpha():
                        if c == lv.SYMBOL.UP:
                            CHARSET[i] = CHARSET[i].upper()
                        else:
                            CHARSET[i] = CHARSET[i].lower()
                    elif ch == lv.SYMBOL.UP:
                        CHARSET[i] = lv.SYMBOL.DOWN
                    elif ch == lv.SYMBOL.DOWN:
                        CHARSET[i] = lv.SYMBOL.UP
                btnm.set_map(CHARSET)
            elif c == "#@":
                btnm.set_map(CHARSET_EXTRA)
            elif c == "aA":
                btnm.set_map(CHARSET)
            elif c[0] == lv.SYMBOL.CLOSE:
                ta.set_text("")
            elif c[0] == lv.SYMBOL.OK:
                cb_continue(ta.get_text())
                ta.set_text("")
            else:
                ta.add_text(c)

    btnm.set_event_cb(cb)
Esempio n. 9
0
def ask_for_derivation(cb_continue,
                       cb_back,
                       title="Enter desired derivation path"):
    scr = switch_to_new_screen()
    add_label(title, style="title")

    btnm = lv.btnm(scr)
    btnm.set_map(PATH_CHARSET)
    btnm.set_width(HOR_RES)
    btnm.set_height(VER_RES // 2)
    btnm.align(scr, lv.ALIGN.IN_BOTTOM_MID, 0, 0)

    lbl = add_label("m/", style="title")
    lbl.set_y(PADDING + 150)
    lbl.set_width(40)
    lbl.set_x(PADDING)

    ta = lv.ta(scr)
    ta.set_text("")
    ta.set_width(HOR_RES - 2 * PADDING - 40)
    ta.set_x(PADDING + 40)
    ta.set_y(PADDING + 150)
    ta.set_cursor_type(lv.CURSOR.HIDDEN)
    ta.set_one_line(True)

    @feed_rng
    def cb(obj, event):
        if event == lv.EVENT.RELEASED:
            c = obj.get_active_btn_text()
            if c is None:
                return
            if c == "Back":
                cb_back()
                ta.set_text("")
            if c[0] == lv.SYMBOL.LEFT:
                ta.del_char()
            elif c[0] == lv.SYMBOL.CLOSE:
                ta.set_text("")
            elif c[0] == lv.SYMBOL.OK:
                cb_continue("m/" + ta.get_text())
                ta.set_text("")
            elif c[0] == "h":
                ta.add_text("h/")
            else:
                ta.add_text(c)

    btnm.set_event_cb(cb)
Esempio n. 10
0
 def __init__(self):
     self.PrevPage = lv.disp_get_scr_act(lv_disp)
     self.CurPage = lv.obj()
     self.CurPage.set_size(320, 240)
     lv.disp_load_scr(self.CurPage)
     self.BtnValue = 1000
     self.Plus1Btn = lv.btn(self.CurPage)
     self.Plus1Btn.set_pos(10, 25)
     self.Plus1Btn.set_size(50, 40)
     self.Plus1Btn.set_event_cb(self.Plus1EventCB)
     self.Plus1Label = lv.label(self.Plus1Btn)
     self.Plus1Label.set_text("+1")
     self.Plus100Btn = lv.btn(self.CurPage)
     self.Plus100Btn.set_pos(10, 75)
     self.Plus100Btn.set_size(50, 40)
     self.Plus100Btn.set_event_cb(self.Plus100EventCB)
     self.Plus100Label = lv.label(self.Plus100Btn)
     self.Plus100Label.set_text("+100")
     self.Minus1Btn = lv.btn(self.CurPage)
     self.Minus1Btn.set_pos(10, 125)
     self.Minus1Btn.set_size(50, 40)
     self.Minus1Btn.set_event_cb(self.Minus1EventCB)
     self.Minus1Label = lv.label(self.Minus1Btn)
     self.Minus1Label.set_text("-1")
     self.Minus100Btn = lv.btn(self.CurPage)
     self.Minus100Btn.set_pos(10, 175)
     self.Minus100Btn.set_size(50, 40)
     self.Minus100Btn.set_event_cb(self.Minus100EventCB)
     self.Minus100Label = lv.label(self.Minus100Btn)
     self.Minus100Label.set_text("-100")
     self.ValueLable = lv.label(self.CurPage)
     self.ValueLable.set_text("Value:")
     self.ValueLable.set_align(lv.ALIGN.CENTER)
     self.ValueLable.set_pos(140, 110)
     self.ValueText = lv.ta(self.CurPage)
     self.ValueText.set_pos(190, 100)
     self.ValueText.set_size(100, 40)
     self.ValueText.set_text(str(self.BtnValue))
Esempio n. 11
0
    def __init__(self, title="Enter derivation path"):
        super().__init__()
        self.title = add_label(title, scr=self, y=PADDING, style="title")
        self.kb = lv.btnm(self)
        self.kb.set_map(type(self).PATH_CHARSET)
        self.kb.set_width(HOR_RES)
        self.kb.set_height(VER_RES // 2)
        self.kb.align(self, lv.ALIGN.IN_BOTTOM_MID, 0, 0)

        lbl = add_label("m/", style="title", scr=self)
        lbl.set_y(PADDING + 150)
        lbl.set_width(40)
        lbl.set_x(PADDING)

        self.ta = lv.ta(self)
        self.ta.set_text("")
        self.ta.set_width(HOR_RES - 2 * PADDING - 40)
        self.ta.set_x(PADDING + 40)
        self.ta.set_y(PADDING + 150)
        self.ta.set_cursor_type(lv.CURSOR.HIDDEN)
        self.ta.set_one_line(True)

        self.kb.set_event_cb(self.cb)
Esempio n. 12
0
else:
    with open(TOUCH_CALI_FILE, 'r') as f:
        param = ujson.load(f)
        touch_x0 = param['cal_x0']
        touch_x1 = param['cal_x1']
        touch_y0 = param['cal_y0']
        touch_y1 = param['cal_y1']

    touch = xpt2046(
        cs=TOUCH_CS,
        transpose=TFT_IS_PORTRAIT,
        cal_x0=touch_x0,
        cal_x1=touch_x1,
        cal_y0=touch_y0,
        cal_y1=touch_y1,
    )

    TOUCH_READY = 1  #表示已经配置好触摸参数

#############################################
###############     Textarea   ##############
#############################################

if TOUCH_READY:

    ta1 = lv.ta(lv.scr_act())
    ta1.set_size(200, 100)
    ta1.align(None, lv.ALIGN.CENTER, 0, 0)
    ta1.set_cursor_type(lv.CURSOR.BLOCK)
    ta1.set_text("A text in a Text Area")  # Set an initial text
Esempio n. 13
0
rel_style.body.radius = 0
rel_style.body.border.width = 1

lv.style_copy(pr_style, lv.style_btn_pr)
pr_style.body.radius = 0
pr_style.body.border.width = 1

# Create a keyboard and apply the styles
kb = lv.kb(lv.scr_act())
kb.set_cursor_manage(True)
kb.set_style(lv.kb.STYLE.BG, lv.style_transp_tight)
kb.set_style(lv.kb.STYLE.BTN_REL, rel_style)
kb.set_style(lv.kb.STYLE.BTN_PR, pr_style)

# Create a text area. The keyboard will write here
ta = lv.ta(lv.scr_act())
ta.align(None, lv.ALIGN.IN_TOP_MID, 0, 10)
ta.set_text("")

# Assign the text area to the keyboard
kb.set_ta(ta)

# **********************************
#   End your codes here.
# **********************************

def on_timer(timer):
    lv.tick_inc(5)

timer = Timer(Timer.TIMER0, Timer.CHANNEL0, mode = Timer.MODE_PERIODIC, period = 5, unit = Timer.UNIT_MS, callback = on_timer, arg = None)
Esempio n. 14
0
pr_style = lv.style_t()

lv.style_copy(rel_style, lv.style_btn_rel)
rel_style.body.radius = 0
rel_style.body.border.width = 1

lv.style_copy(pr_style, lv.style_btn_pr)
pr_style.body.radius = 0
pr_style.body.border.width = 1

# Create a keyboard and apply the styles
kb = lv.kb(scr1)
kb.set_cursor_manage(True)

# Create a text area. The keyboard will write here
ta = lv.ta(scr1)
ta.set_width(450)
ta.set_height(70)
ta.align(kb, lv.ALIGN.OUT_TOP_MID, 0, -10)
ta.set_text("")

# Assign the text area to the keyboard
kb.set_ta(ta)

# Create a style for the Preloader
style = lv.style_t()
lv.style_copy(style, lv.style_plain)
style.line.width = 10  # 10 px thick arc
style.line.color = lv.color_hex3(0x258)  # Blueish arc color

style.body.border.color = lv.color_hex3(0xBBB)  # Gray background color
Esempio n. 15
0
def ask_pin(first_time_usage, callback):
    scr = switch_to_new_screen()
    first_time_title = "Choose a PIN code"
    title = "Enter your PIN code"
    if first_time_usage:
        title = first_time_title
    title_lbl = add_label(title, y=PADDING, style="title")
    btnm = lv.btnm(scr)
    # shuffle numbers to make sure 
    # no constant fingerprints left on screen
    buttons = ["%d" % i for i in range(0,10)]
    btnmap = []
    for j in range(3):
        for i in range(3):
            v = rng.get_random_bytes(1)[0] % len(buttons)
            btnmap.append(buttons.pop(v))
        btnmap.append("\n")
    btnmap = btnmap+[lv.SYMBOL.CLOSE, buttons.pop(), lv.SYMBOL.OK, ""]
    btnm.set_map(btnmap)
    btnm.set_width(HOR_RES)
    btnm.set_height(HOR_RES)
    btnm.align(scr, lv.ALIGN.IN_BOTTOM_MID, 0, 0)
    # remove feedback on press to avoid sidechannels
    btnm.set_style(lv.btnm.STYLE.BTN_PR,btnm.get_style(lv.btnm.STYLE.BTN_REL))

    pin_lbl = lv.ta(scr)
    pin_lbl.set_text("")
    pin_lbl.set_pwd_mode(True)
    style = lv.style_t()
    lv.style_copy(style, styles["theme"].style.ta.oneline)
    style.text.font = lv.font_roboto_28
    style.text.color = lv.color_hex(0xffffff)
    style.text.letter_space = 15
    pin_lbl.set_style(lv.label.STYLE.MAIN, style)
    pin_lbl.set_width(HOR_RES-2*PADDING)
    pin_lbl.set_x(PADDING)
    pin_lbl.set_y(PADDING+50)
    pin_lbl.set_cursor_type(lv.CURSOR.HIDDEN)
    pin_lbl.set_one_line(True)
    pin_lbl.set_text_align(lv.label.ALIGN.CENTER)
    pin_lbl.set_pwd_show_time(0)

    instruct_txt = "Device tamper check.\nThese words should remain #ffffff the same every time#:"
    instruct_label = add_label(instruct_txt, 180, style="hint")
    instruct_label.set_recolor(True)
    antiphish_label = add_label(antiphishing_word(""), 250)
    Pin.read_counter()

    @feed_rng
    def cb(obj, event):
        nonlocal first_time_usage
        if event == lv.EVENT.RELEASED:
            c = obj.get_active_btn_text()
            if c is None:
                return
            if c == lv.SYMBOL.CLOSE:
                pin_lbl.set_text("")
                antiphish_label.set_text(antiphishing_word(""))
            elif c == lv.SYMBOL.OK:
                # FIXME: check PIN len
                Key.generate_key(pin_lbl.get_text());
                if first_time_usage:
                    Secret.save_secret(alert);
                    callback()
                else:
                    Pin.counter -= 1
                    Pin.save_counter(alert)
                    if Pin.is_pin_valid():
                        Pin.reset_counter(alert)
                        callback()
                    else:
                        instruct_label.set_text("#f07070 Wrong pin: %d/%d #" % (Pin.counter, Pin.ATTEMPTS_MAX))
                        if Pin.counter <= 0:
                            Factory_settings.restore(alert)
                            Secret.generate_secret()
                            alert("Security","Device has been factory reset!")
                            first_time_usage = True
                            title_lbl.set_text(first_time_title)
                            instruct_label.set_text(instruct_txt)
                pin_lbl.set_text("")
                antiphish_label.set_text(antiphishing_word(""))
            else:
                instruct_label.set_text(instruct_txt)
                pin_lbl.add_text(c)
                word = antiphishing_word(pin_lbl.get_text())
                antiphish_label.set_text(antiphish_label.get_text() + " " + word)

    btnm.set_event_cb(cb);
    def popup_pid_params(self):
        """
        The popup window of PID params settings
        """
        modal_style = lv.style_t()
        lv.style_copy(modal_style, lv.style_plain_color)
        modal_style.body.main_color = modal_style.body.grad_color = lv.color_make(
            0, 0, 0)
        modal_style.body.opa = lv.OPA._50
        bg = lv.obj(self.main_scr)
        bg.set_style(modal_style)
        bg.set_pos(0, 0)
        bg.set_size(self.main_scr.get_width(), self.main_scr.get_height())
        bg.set_opa_scale_enable(True)

        # init mbox and title
        popup_pid = lv.mbox(bg)
        popup_pid.set_text('Set PID Params')
        popup_pid.set_size(220, 300)
        popup_pid.align(bg, lv.ALIGN.CENTER, 0, 0)

        input_cont = lv.cont(popup_pid)
        input_cont.set_size(210, 180)

        def input_event_cb(ta, event):
            if event == lv.EVENT.CLICKED:
                self.current_input_placeholder = ta.get_placeholder_text()
                if self.current_input_placeholder == 'Set Offset':
                    popup_pid.align(bg, lv.ALIGN.CENTER, 0, -55)
                else:
                    popup_pid.align(bg, lv.ALIGN.CENTER, 0, 0)
                if kb.get_hidden():
                    kb.set_hidden(False)
                # Focus on the clicked text area
                kb.set_ta(ta)

        def keyboard_event_cb(event_kb, event):
            event_kb.def_event_cb(event)
            if event == lv.EVENT.CANCEL or event == lv.EVENT.APPLY:
                kb.set_hidden(True)
                if self.current_input_placeholder == 'Set Offset':
                    popup_pid.align(bg, lv.ALIGN.CENTER, 0, 0)

        # init keyboard
        kb = lv.kb(bg)
        kb.set_cursor_manage(True)
        kb.set_event_cb(keyboard_event_cb)
        lv.kb.set_mode(kb, lv.kb.MODE.NUM)
        rel_style = lv.style_t()
        pr_style = lv.style_t()
        lv.style_copy(rel_style, lv.style_btn_rel)
        rel_style.body.radius = 0
        rel_style.body.border.width = 1
        lv.style_copy(pr_style, lv.style_btn_pr)
        pr_style.body.radius = 0
        pr_style.body.border.width = 1
        kb.set_style(lv.kb.STYLE.BG, lv.style_transp_tight)
        kb.set_style(lv.kb.STYLE.BTN_REL, rel_style)
        kb.set_style(lv.kb.STYLE.BTN_PR, pr_style)

        # init text areas
        kp_input = lv.ta(input_cont)
        kp_input.set_text(str(self.pid_params.get('kp')))
        kp_input.set_placeholder_text('Set Kp')
        kp_input.set_accepted_chars('0123456789.+-')
        kp_input.set_one_line(True)
        kp_input.set_width(120)
        kp_input.align(input_cont, lv.ALIGN.IN_TOP_MID, 30, 20)
        kp_input.set_event_cb(input_event_cb)
        kp_label = lv.label(input_cont)
        kp_label.set_text("Kp: ")
        kp_label.align(kp_input, lv.ALIGN.OUT_LEFT_MID, 0, 0)
        pid_title_label = lv.label(input_cont)
        pid_title_label.set_text("PID Params:")
        pid_title_label.align(kp_input, lv.ALIGN.OUT_TOP_LEFT, -65, 0)

        ki_input = lv.ta(input_cont)
        ki_input.set_text(str(self.pid_params.get('ki')))
        ki_input.set_placeholder_text('Set Ki')
        ki_input.set_accepted_chars('0123456789.+-')
        ki_input.set_one_line(True)
        ki_input.set_width(120)
        ki_input.align(input_cont, lv.ALIGN.IN_TOP_MID, 30, 55)
        ki_input.set_event_cb(input_event_cb)
        ki_input.set_cursor_type(lv.CURSOR.LINE | lv.CURSOR.HIDDEN)
        ki_label = lv.label(input_cont)
        ki_label.set_text("Ki: ")
        ki_label.align(ki_input, lv.ALIGN.OUT_LEFT_MID, 0, 0)

        kd_input = lv.ta(input_cont)
        kd_input.set_text(str(self.pid_params.get('kd')))
        kd_input.set_placeholder_text('Set Kd')
        kd_input.set_accepted_chars('0123456789.+-')
        kd_input.set_one_line(True)
        kd_input.set_width(120)
        kd_input.align(input_cont, lv.ALIGN.IN_TOP_MID, 30, 90)
        kd_input.set_event_cb(input_event_cb)
        kd_input.set_cursor_type(lv.CURSOR.LINE | lv.CURSOR.HIDDEN)
        kd_label = lv.label(input_cont)
        kd_label.set_text("Kd: ")
        kd_label.align(kd_input, lv.ALIGN.OUT_LEFT_MID, 0, 0)

        temp_offset_input = lv.ta(input_cont)
        temp_offset_input.set_text(str(self.temp_offset))
        temp_offset_input.set_placeholder_text('Set Offset')
        temp_offset_input.set_accepted_chars('0123456789.+-')
        temp_offset_input.set_one_line(True)
        temp_offset_input.set_width(120)
        temp_offset_input.align(input_cont, lv.ALIGN.IN_TOP_MID, 30, 145)
        temp_offset_input.set_event_cb(input_event_cb)
        temp_offset_input.set_cursor_type(lv.CURSOR.LINE | lv.CURSOR.HIDDEN)
        temp_offset_label = lv.label(input_cont)
        temp_offset_label.set_text("Offset: ")
        temp_offset_label.align(temp_offset_input, lv.ALIGN.OUT_LEFT_MID, 0, 0)
        offset_title_label = lv.label(input_cont)
        offset_title_label.set_text("Temp Correction:")
        offset_title_label.align(temp_offset_input, lv.ALIGN.OUT_TOP_LEFT, -65,
                                 0)

        # set btns to mbox
        btns = ['Save', 'Cancel', '']
        popup_pid.add_btns(btns)

        lv.cont.set_fit(popup_pid, lv.FIT.NONE)
        mbox_style = popup_pid.get_style(popup_pid.STYLE.BTN_REL)
        popup_pid_style = lv.style_t()
        lv.style_copy(popup_pid_style, mbox_style)
        popup_pid_style.body.padding.bottom = 46
        popup_pid.set_style(popup_pid.STYLE.BTN_REL, popup_pid_style)
        popup_pid.set_size(220, 300)

        def event_handler(obj, event):
            if event == lv.EVENT.VALUE_CHANGED:
                active_btn_text = popup_pid.get_active_btn_text()
                if active_btn_text == 'Save':
                    kp_value = float(kp_input.get_text())
                    ki_value = float(ki_input.get_text())
                    kd_value = float(kd_input.get_text())
                    temp_offset_value = float(temp_offset_input.get_text())
                    self.config['pid'] = {
                        'kp': kp_value,
                        'ki': ki_value,
                        'kd': kd_value
                    }
                    self.config['sensor_offset'] = temp_offset_value
                    self.pid_params = self.config.get('pid')
                    self.temp_offset = self.config.get('sensor_offset')
                    # Save settings to config.json
                    with open('config.json', 'w') as f:
                        ujson.dump(self.config, f)
                    # Apply settings immediately
                    self.pid.reset(kp_value, ki_value, kd_value)
                    self.sensor.set_offset(temp_offset_value)
                bg.del_async()
                popup_pid.start_auto_close(5)

        popup_pid.set_event_cb(event_handler)
        popup_pid.align(bg, lv.ALIGN.CENTER, 0, 0)
        kb.set_ta(kp_input)
        kb.set_hidden(True)