diff --git a/preload/apps/card10_nickname/__init__.py b/preload/apps/card10_nickname/__init__.py index d38523fbf5d5ffd31b040e77797ede286cf30c4f..24b7f7b19b1925b54b7a8bc1e3d65943ac4e9605 100644 --- a/preload/apps/card10_nickname/__init__.py +++ b/preload/apps/card10_nickname/__init__.py @@ -1,12 +1,3 @@ -""" -Improvement ideas -- animations - - dvd - - rainbow - - led control - - fade effekt -- led nick writing -""" import utime import display import leds @@ -18,10 +9,63 @@ import os FILENAME = 'nickname.txt' FILENAME_ADV = 'nickname.json' -ANIM_TYPES = ['none', 'led', 'fade', 'gay'] +ANIM_TYPES = ['none', 'led', 'fade', 'gay', 'rainbow', 'rnd_led'] + + +def wheel(pos): + """ + Taken from https://badge.team/projects/rainbow_name + Input a value 0 to 255 to get a color value. + The colours are a transition r - g - b - back to r. + :param pos: input position + :return: rgb value + """ + if pos < 0: + return 0, 0, 0 + if pos > 255: + pos -= 255 + if pos < 85: + return int(255 - pos * 3), int(pos * 3), 0 + if pos < 170: + pos -= 85 + return 0, int(255 - pos * 3), int(pos * 3) + pos -= 170 + return int(pos * 3), 0, int(255 - (pos * 3)) + + +def random_rgb(): + """ + Generates a random RGB value + :return: RGB array + """ + rgb = [] + for i in range(0, 3): + rand = int.from_bytes(os.urandom(1), 'little') + if rand > 255: + rand = 255 + rgb.append(rand) + return rgb + + +def blink_led(led): + """ + Turns off leds, blinks given led for 100ms + can be used as an indicator + :param led: led to blink + """ + leds.clear() + utime.sleep(0.1) + leds.set(led, [255, 0, 0]) + utime.sleep(0.1) + leds.clear() def render_error(err1, err2): + """ + Function to render two lines of text (each max 11 chars). Useful to display error messages + :param err1: line one + :param err2: line two + """ with display.open() as disp: disp.clear() disp.print(err1, posx=80 - round(len(err1) / 2 * 14), posy=18) @@ -30,7 +74,44 @@ def render_error(err1, err2): disp.close() +def get_bat_color(bat): + """ + Function determines the color of the battery indicator. Colors can be set in config. + Voltage threshold's are currently estimates as voltage isn't that great of an indicator for + battery charge. + :param bat: battery config tuple (boolean: indicator on/off, array: good rgb, array: ok rgb, array: bad rgb) + :return: false if old firmware, RGB color array otherwise + """ + try: + v = os.read_battery() + if v > 3.8: + return bat[1] + if v > 3.6: + return bat[2] + return bat[3] + except AttributeError: + return False + + +def render_battery(disp, bat): + """ + Adds the battery indicator to the display. Does not call update or clear so it can be used in addition to + other display code. + :param disp: open display + :param bat: battery config tuple (boolean: indicator on/off, array: good rgb, array: ok rgb, array: bad rgb) + """ + c = get_bat_color(bat) + if not c: + return + disp.rect(140, 2, 155, 9, filled=True, col=c) + disp.rect(155, 4, 157, 7, filled=True, col=c) + + def get_time(): + """ + Generates a nice timestamp in format hh:mm:ss from the devices localtime + :return: timestamp + """ timestamp = '' if utime.localtime()[3] < 10: timestamp = timestamp + '0' @@ -45,6 +126,10 @@ def get_time(): def toggle_rockets(state): + """ + Turns all rocked LEDs on or off. + :param state: True=on, False=off + """ brightness = 15 if not state: brightness = 0 @@ -53,14 +138,28 @@ def toggle_rockets(state): leds.set_rocket(2, brightness) -def render_nickname(title, sub, fg, bg, fg_sub, bg_sub, main_bg): - anim = 0 +def render_nickname(title, sub, fg, bg, fg_sub, bg_sub, main_bg, mode, bat): + """ + Main function to render the nickname on screen. + Pretty ugly but not time for cleanup right now (and some APIs missing) + :param title: first row of text + :param sub: second row of text + :param fg: tuple of (day, night) rgb for title text color + :param bg: tuple of (day, night) rgb for title background color + :param fg_sub: tuple of (day, night) rgb for subtitle text color + :param bg_sub: tuple of (day, night) rgb for subtitle background color + :param main_bg: tuple of (day, night) rgb for general background color + :param mode: default animation to start in (index of ANIM_TYPES array) + :param bat: battery config tuple (boolean: indicator on/off, array: good rgb, array: ok rgb, array: bad rgb) + """ + anim = mode posy = 30 if sub != '': posy = 18 r = 255 g = 0 b = 0 + rainbow_led_pos = 0 r_sub = sub last_btn_poll = utime.time() - 2 while True: @@ -68,7 +167,7 @@ def render_nickname(title, sub, fg, bg, fg_sub, bg_sub, main_bg): if sub == '#time': r_sub = get_time() dark = 0 - if light_sensor.get_reading() < 40: + if light_sensor.get_reading() < 30: dark = 1 r_fg_color = fg[dark] r_bg_color = bg[dark] @@ -85,24 +184,26 @@ def render_nickname(title, sub, fg, bg, fg_sub, bg_sub, main_bg): anim = anim + 1 if anim >= len(ANIM_TYPES): anim = 0 + blink_led(0) if pressed & buttons.BOTTOM_LEFT != 0: anim = anim - 1 if anim < 0: anim = len(ANIM_TYPES) - 1 + blink_led(0) # Animations if ANIM_TYPES[anim] == 'fade': sleep = 0.1 leds.clear() toggle_rockets(False) if r > 0 and b == 0: - r = r - 1 - g = g + 1 + r -= 1 + g += 1 if g > 0 and r == 0: - g = g - 1 - b = b + 1 + g -= 1 + b += 1 if b > 0 and g == 0: - r = r + 1 - b = b - 1 + r += 1 + b -= 1 r_bg = [r, g, b] r_bg_color = r_bg r_bg_sub_color = r_bg @@ -116,14 +217,36 @@ def render_nickname(title, sub, fg, bg, fg_sub, bg_sub, main_bg): else: leds.clear() toggle_rockets(False) + if ANIM_TYPES[anim] == 'rnd_led': + if dark == 1: + for i in range(0, 11): + leds.prep(i, random_rgb()) + leds.update() + leds.dim_top(4) + toggle_rockets(True) + else: + leds.clear() + toggle_rockets(False) if ANIM_TYPES[anim] == 'gay': toggle_rockets(False) leds.gay(0.4) + if ANIM_TYPES[anim] == 'rainbow': + for i in range(0, 11): + lr, lg, lb = wheel(rainbow_led_pos + i * 3) + leds.prep(i, [lr, lg, lb]) + rainbow_led_pos += 1 + if rainbow_led_pos > 255: + rainbow_led_pos = 0 + leds.update() + leds.dim_top(3) + toggle_rockets(True) if ANIM_TYPES[anim] == 'none': leds.clear() toggle_rockets(False) with display.open() as disp: disp.rect(0, 0, 160, 80, col=r_bg, filled=True) + if bat[0]: + render_battery(disp, bat) disp.print(title, fg=r_fg_color, bg=r_bg_color, posx=80 - round(len(title) / 2 * 14), posy=posy) if r_sub != '': disp.print(r_sub, fg=r_fg_sub_color, bg=r_bg_sub_color, posx=80 - round(len(r_sub) / 2 * 14), posy=42) @@ -133,11 +256,19 @@ def render_nickname(title, sub, fg, bg, fg_sub, bg_sub, main_bg): def get_key(json, key, default): + """ + Gets a defined key from a json object or returns a default if the key cant be found + :param json: json object to search key in + :param key: key to search for + :param default: default to return if no key is found + :return: + """ try: return json[key] except KeyError: return default + leds.clear() with display.open() as disp: disp.clear().update() @@ -150,6 +281,12 @@ if FILENAME_ADV in os.listdir("."): # parse config nick = get_key(c, 'nickname', 'no nick') sub = get_key(c, 'subtitle', '') + mode = get_key(c, 'mode', 0) + # battery + battery_show = get_key(c, 'battery', True) + battery_c_good = get_key(c, 'battery_color_good', [0, 230, 00]) + battery_c_ok = get_key(c, 'battery_color_ok', [255, 215, 0]) + battery_c_bad = get_key(c, 'battery_color_bad', [255, 0, 0]) # daytime values background = get_key(c, 'background', [0, 0, 0]) fg_color = get_key(c, 'fg_color', [255, 255, 255]) @@ -165,7 +302,8 @@ if FILENAME_ADV in os.listdir("."): # render nickname render_nickname(nick, sub, (fg_color, fg_color_night), (bg_color, bg_color_night), (fg_sub_color, fg_sub_color_night), (bg_sub_color, bg_sub_color_night), - (background, background_night)) + (background, background_night), mode, + (battery_show, battery_c_good, battery_c_ok, battery_c_bad)) except ValueError: render_error('invalid', 'json') else: diff --git a/preload/apps/card10_nickname/metadata.json b/preload/apps/card10_nickname/metadata.json index 2323731badeabe7aaa4f58d1a88e0c1eb1a6c979..1ea15481e9545587513f40c8b40f109166f67f35 100644 --- a/preload/apps/card10_nickname/metadata.json +++ b/preload/apps/card10_nickname/metadata.json @@ -1 +1 @@ -{"name":"Card10 Nickname","description":"Nickname app for the card10 badge\r\n\r\nEverything you need can be found here: https:\/\/github.com\/vabene1111\/card10-nickname","category":"graphics","author":"vabene1111","revision":4} \ No newline at end of file +{"name":"Card10 Nickname","description":"Nickname app for the card10 badge\r\n\r\nEverything you need can be found here: https:\/\/github.com\/vabene1111\/card10-nickname","category":"graphics","author":"vabene1111","revision":8} \ No newline at end of file