From 0621774933d3d9e7d4a7b0177b5b8593f3c685a3 Mon Sep 17 00:00:00 2001 From: mchilli Date: Wed, 25 Oct 2023 17:06:14 +0200 Subject: [PATCH 1/6] change how settings load --- circuitpython/code.py | 88 +++++++++++++++++++------------------------ 1 file changed, 38 insertions(+), 50 deletions(-) diff --git a/circuitpython/code.py b/circuitpython/code.py index 359f069..283e512 100644 --- a/circuitpython/code.py +++ b/circuitpython/code.py @@ -25,56 +25,56 @@ SETTINGSFILE = "settings.json" # The file in which the settings are saved MACROFILE = "macros.json" # The file in which the macros are saved -SLEEPTIME = 2 # Time in seconds until the display turns off -KEYBOARDLAYOUT = "us" # Supported keyboard layouts: br, cz, da, de, es, fr, hu, it, po, sw, tr, uk, us -USEUNICODEFONT = False # Use a unicode bitmap font, which will increas the initial load time! + +SETTINGS = { + "sleeptime": 2, # Time in seconds until the display turns off + "keyboardlayout": "us", # Supported keyboard layouts: br, cz, da, de, es, fr, hu, it, po, sw, tr, uk, us + "useunicodefont": False, # Use a unicode bitmap font, which will increas the initial load time! +} try: with open(SETTINGSFILE, "r") as f: settings = json.load(f) - if "sleeptime" in settings: - SLEEPTIME = settings["sleeptime"] - if "keyboardlayout" in settings: - KEYBOARDLAYOUT = settings["keyboardlayout"] - if "useunicodefont" in settings: - USEUNICODEFONT = settings["useunicodefont"] + for key in SETTINGS: + if key in settings: + SETTINGS[key] = settings[key] except Exception: pass -if KEYBOARDLAYOUT == "br": +if SETTINGS["keyboardlayout"] == "br": from adafruit_hid.keyboard_layout_win_br import KeyboardLayout from adafruit_hid.keycode_win_br import Keycode -elif KEYBOARDLAYOUT == "cz": +elif SETTINGS["keyboardlayout"] == "cz": from adafruit_hid.keyboard_layout_win_cz import KeyboardLayout from adafruit_hid.keycode_win_cz import Keycode -elif KEYBOARDLAYOUT == "da": +elif SETTINGS["keyboardlayout"] == "da": from adafruit_hid.keyboard_layout_win_da import KeyboardLayout from adafruit_hid.keycode_win_da import Keycode -elif KEYBOARDLAYOUT == "de": +elif SETTINGS["keyboardlayout"] == "de": from adafruit_hid.keyboard_layout_win_de import KeyboardLayout from adafruit_hid.keycode_win_de import Keycode -elif KEYBOARDLAYOUT == "es": +elif SETTINGS["keyboardlayout"] == "es": from adafruit_hid.keyboard_layout_win_es import KeyboardLayout from adafruit_hid.keycode_win_es import Keycode -elif KEYBOARDLAYOUT == "fr": +elif SETTINGS["keyboardlayout"] == "fr": from adafruit_hid.keyboard_layout_win_fr import KeyboardLayout from adafruit_hid.keycode_win_fr import Keycode -elif KEYBOARDLAYOUT == "hu": +elif SETTINGS["keyboardlayout"] == "hu": from adafruit_hid.keyboard_layout_win_hu import KeyboardLayout from adafruit_hid.keycode_win_hu import Keycode -elif KEYBOARDLAYOUT == "it": +elif SETTINGS["keyboardlayout"] == "it": from adafruit_hid.keyboard_layout_win_it import KeyboardLayout from adafruit_hid.keycode_win_it import Keycode -elif KEYBOARDLAYOUT == "po": +elif SETTINGS["keyboardlayout"] == "po": from adafruit_hid.keyboard_layout_win_po import KeyboardLayout from adafruit_hid.keycode_win_po import Keycode -elif KEYBOARDLAYOUT == "sw": +elif SETTINGS["keyboardlayout"] == "sw": from adafruit_hid.keyboard_layout_win_sw import KeyboardLayout from adafruit_hid.keycode_win_sw import Keycode -elif KEYBOARDLAYOUT == "tr": +elif SETTINGS["keyboardlayout"] == "tr": from adafruit_hid.keyboard_layout_win_tr import KeyboardLayout from adafruit_hid.keycode_win_tr import Keycode -elif KEYBOARDLAYOUT == "uk": +elif SETTINGS["keyboardlayout"] == "uk": from adafruit_hid.keyboard_layout_win_uk import KeyboardLayout from adafruit_hid.keycode_win_uk import Keycode else: @@ -84,17 +84,18 @@ class MacroApp(): """ Main Class """ - def __init__(self) -> None: + def __init__(self, settings) -> None: self.macropad = MacroPad(layout_class=KeyboardLayout) self.macropad.display.auto_refresh = False self.macropad.display.brightness = 0.1 self.macropad.pixels.auto_write = False self.macropad.pixels.brightness = 0.1 + self.readonly = storage.getmount('/').readonly self.serial_data = usb_cdc.data self.serial_last_state = False - self.settings = self._init_settings() + self.settings = settings self.macros = self._init_macros() self.keys = self._init_keys() self.toolbar = self._init_toolbar() @@ -102,27 +103,14 @@ def __init__(self) -> None: self.show_homescreen() - def _init_settings(self) -> dict: - """ initiate the settings json file - - Returns: - dict: the json file as a dict - """ - try: - with open(SETTINGSFILE, "r") as f: - return json.load(f) - except OSError: - return { - "keyboardlayout": KEYBOARDLAYOUT, - "sleeptime": SLEEPTIME, - "useunicodefont": USEUNICODEFONT - } - def _save_settings(self) -> None: """ store the settings in the settingsfile """ + if self.readonly: + return False with open(SETTINGSFILE, "w") as f: f.write(json.dumps(self.settings, separators=(",", ":"))) + return True def _init_macros(self) -> list[dict]: """ initiate the macro json file @@ -148,8 +136,11 @@ def _init_macros(self) -> list[dict]: def _save_macros(self) -> None: """ store the macros in the macrofile """ + if self.readonly: + return False with open(MACROFILE, "w") as f: f.write(json.dumps(self.macros, separators=(",", ":"))) + return True def _init_keys(self) -> list[Key]: """ Initiate the keys and a display group for each key @@ -162,7 +153,7 @@ def _init_keys(self) -> list[Key]: for i in range(self.macropad.keys.key_count): label = Label( - font=load_font("/fonts/6x12.pcf") if USEUNICODEFONT else terminalio.FONT, + font=load_font("/fonts/6x12.pcf") if SETTINGS["useunicodefont"] else terminalio.FONT, text="", padding_top=1, padding_bottom=2, @@ -407,10 +398,9 @@ def _handle_serial_data(self, payload:str) -> dict: content = payload['content'] self.settings = content - try: - self._save_settings() + if self._save_settings(): response['ACK'] = 'Settings are set' - except OSError as e: + else: response['ERR'] = 'Cannot set settings because USB storage is enabled' return response @@ -434,10 +424,9 @@ def _handle_serial_data(self, payload:str) -> dict: return response elif command == 'save_macros': - try: - self._save_macros() + if self._save_macros(): response['ACK'] = 'Macros stored' - except OSError as e: + else: response['ERR'] = 'Cannot store macros because USB storage is enabled' return response @@ -486,7 +475,7 @@ def start(self) -> None: """ self.sleep_timer = time.monotonic() while True: - if not self.macropad.display_sleep and time.monotonic() - self.sleep_timer > SLEEPTIME: + if not self.macropad.display_sleep and time.monotonic() - self.sleep_timer > SETTINGS["sleeptime"]: self.macropad.display_sleep = True self.macropad.display.refresh() @@ -495,8 +484,7 @@ def start(self) -> None: if self.serial_last_state != self.serial_data.connected: self.serial_last_state = self.serial_data.connected if self.serial_data.connected: - readonly = storage.getmount('/').readonly - self._send_serial_data({'ACK': 'usbenabled', 'CONTENT': readonly }) + self._send_serial_data({'ACK': 'usbenabled', 'CONTENT': self.readonly }) if self.serial_data.connected: if self.serial_data.in_waiting > 0: @@ -528,5 +516,5 @@ def start(self) -> None: "content": self.encoder.on_decreased }) -app = MacroApp() +app = MacroApp(SETTINGS) app.start() \ No newline at end of file From 897cbb60d651513b5cd9692377b9dfce9fea8274 Mon Sep 17 00:00:00 2001 From: mchilli Date: Wed, 25 Oct 2023 17:08:10 +0200 Subject: [PATCH 2/6] add setting flip rotation --- circuitpython/code.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/circuitpython/code.py b/circuitpython/code.py index 283e512..3ae22fc 100644 --- a/circuitpython/code.py +++ b/circuitpython/code.py @@ -30,6 +30,7 @@ "sleeptime": 2, # Time in seconds until the display turns off "keyboardlayout": "us", # Supported keyboard layouts: br, cz, da, de, es, fr, hu, it, po, sw, tr, uk, us "useunicodefont": False, # Use a unicode bitmap font, which will increas the initial load time! + "fliprotation": False, # Flips the rotation of the device by 180 degrees } try: @@ -85,7 +86,7 @@ class MacroApp(): """ Main Class """ def __init__(self, settings) -> None: - self.macropad = MacroPad(layout_class=KeyboardLayout) + self.macropad = MacroPad(layout_class=KeyboardLayout, rotation=180 if SETTINGS["fliprotation"] else 0) self.macropad.display.auto_refresh = False self.macropad.display.brightness = 0.1 self.macropad.pixels.auto_write = False From 9a4ba36f22c104978064c99fe46ac04be456bad9 Mon Sep 17 00:00:00 2001 From: mchilli Date: Wed, 25 Oct 2023 17:09:09 +0200 Subject: [PATCH 3/6] add setting brightness --- circuitpython/code.py | 7 ++++--- circuitpython/utils/system.py | 33 +++++++++++++++++---------------- 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/circuitpython/code.py b/circuitpython/code.py index 3ae22fc..170fcd3 100644 --- a/circuitpython/code.py +++ b/circuitpython/code.py @@ -31,6 +31,7 @@ "keyboardlayout": "us", # Supported keyboard layouts: br, cz, da, de, es, fr, hu, it, po, sw, tr, uk, us "useunicodefont": False, # Use a unicode bitmap font, which will increas the initial load time! "fliprotation": False, # Flips the rotation of the device by 180 degrees + "brightness": 0.1 # Set the LCD and LED Brightness } try: @@ -88,9 +89,9 @@ class MacroApp(): def __init__(self, settings) -> None: self.macropad = MacroPad(layout_class=KeyboardLayout, rotation=180 if SETTINGS["fliprotation"] else 0) self.macropad.display.auto_refresh = False - self.macropad.display.brightness = 0.1 + self.macropad.display.brightness = SETTINGS["brightness"] self.macropad.pixels.auto_write = False - self.macropad.pixels.brightness = 0.1 + self.macropad.pixels.brightness = SETTINGS["brightness"] self.readonly = storage.getmount('/').readonly self.serial_data = usb_cdc.data @@ -285,7 +286,7 @@ def run_macro(self, item:dict, *args) -> None: if 'sys' in key: method = getattr(System, key['sys'], None) if method: - method(self.macropad) + method(self) self.macropad.keyboard.release_all() self.macropad.mouse.release_all() diff --git a/circuitpython/utils/system.py b/circuitpython/utils/system.py index 712c62e..23530d8 100644 --- a/circuitpython/utils/system.py +++ b/circuitpython/utils/system.py @@ -1,33 +1,34 @@ import microcontroller import supervisor -from adafruit_macropad import MacroPad USBENABLEDFILE = "usbenabled" class System(): - def enable_usb(macropad:MacroPad=None) -> None: + def enable_usb(app=None) -> None: try: with open(USBENABLEDFILE, "a") as f: pass System.hard_reset() except Exception: pass - def soft_reset(macropad:MacroPad=None) -> None: + def soft_reset(app=None) -> None: supervisor.reload() - def hard_reset(macropad:MacroPad=None) -> None: + def hard_reset(app=None) -> None: microcontroller.reset() - def decrease_brightness(macropad:MacroPad=None) -> None: - if macropad.display.brightness > 0: - brightness = round(macropad.display.brightness * 10) - macropad.display.brightness = (brightness - 1) / 10 - macropad.pixels.brightness = (brightness - 1) / 10 - macropad.pixels.show() + def decrease_brightness(app=None) -> None: + if app.macropad.display.brightness > 0: + brightness = (round(app.macropad.display.brightness * 10) - 1) / 10 + app.macropad.display.brightness = brightness + app.macropad.pixels.brightness = brightness + app.macropad.pixels.show() + app.settings["brightness"] = brightness - def increase_brightness(macropad:MacroPad=None) -> None: - if macropad.display.brightness < 1: - brightness = round(macropad.display.brightness * 10) - macropad.display.brightness = (brightness + 1) / 10 - macropad.pixels.brightness = (brightness + 1) / 10 - macropad.pixels.show() \ No newline at end of file + def increase_brightness(app=None) -> None: + if app.macropad.display.brightness < 1: + brightness = (round(app.macropad.display.brightness * 10) + 1) / 10 + app.macropad.display.brightness = brightness + app.macropad.pixels.brightness = brightness + app.macropad.pixels.show() + app.settings["brightness"] = brightness \ No newline at end of file From 1eb6ae6812ad96e08bba15287006cb9e965f6ce4 Mon Sep 17 00:00:00 2001 From: mchilli Date: Wed, 25 Oct 2023 17:10:23 +0200 Subject: [PATCH 4/6] add rotation and brightness to settings dialog --- webui/js/modules/classes/Dialogs.js | 47 +++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/webui/js/modules/classes/Dialogs.js b/webui/js/modules/classes/Dialogs.js index e840598..eb300cc 100644 --- a/webui/js/modules/classes/Dialogs.js +++ b/webui/js/modules/classes/Dialogs.js @@ -1536,6 +1536,46 @@ export class SettingsDialog extends BaseDialog { })), ], }), + utils.create({ + attributes: { + class: 'dialog-input-shorten', + }, + children: [ + utils.create({ + text: 'Flip Rotation: ', + }), + (DOM.fliprotation = utils.create({ + type: 'input', + attributes: { + type: 'checkbox', + }, + })), + ], + }), + utils.create({ + attributes: { + class: 'dialog-input-shorten', + }, + children: [ + utils.create({ + text: 'LCD/LED Brightness: ', + }), + (DOM.brightness = utils.create({ + type: 'input', + attributes: { + type: 'range', + min: 0, + max: 1, + step: 0.1, + }, + events: { + input: (event) => { + event.target.title = event.target.value; + }, + }, + })), + ], + }), ], }), utils.create({ @@ -1578,6 +1618,8 @@ export class SettingsDialog extends BaseDialog { DOM.keyboardlayout.disabled = this.readonly; DOM.sleeptime.disabled = this.readonly; DOM.useunicodefont.disabled = this.readonly; + DOM.fliprotation.disabled = this.readonly; + DOM.brightness.disabled = this.readonly; return DOM; } @@ -1597,6 +1639,8 @@ export class SettingsDialog extends BaseDialog { this.settings.keyboardlayout = this.DOM.keyboardlayout.value; this.settings.sleeptime = parseInt(this.DOM.sleeptime.value); this.settings.useunicodefont = this.DOM.useunicodefont.checked; + this.settings.fliprotation = this.DOM.fliprotation.checked; + this.settings.brightness = parseFloat(this.DOM.brightness.value); this.resolve({ dialogInstance: this, settings: this.settings }); this._removeFromParent(this.DOM.container); @@ -1615,6 +1659,9 @@ export class SettingsDialog extends BaseDialog { this.DOM.sleeptime.value = this.settings.sleeptime; this.DOM.useunicodefont.checked = this.settings.useunicodefont; + this.DOM.fliprotation.checked = this.settings.fliprotation; + this.DOM.brightness.value = this.settings.brightness; + this.DOM.brightness.title = this.settings.brightness; } } From 6456937e90ceeacb5601aa85a0febaa3256ea8bc Mon Sep 17 00:00:00 2001 From: mchilli Date: Wed, 25 Oct 2023 17:20:17 +0200 Subject: [PATCH 5/6] get rid of the instance setting variable --- circuitpython/code.py | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/circuitpython/code.py b/circuitpython/code.py index 170fcd3..5077f17 100644 --- a/circuitpython/code.py +++ b/circuitpython/code.py @@ -86,7 +86,7 @@ class MacroApp(): """ Main Class """ - def __init__(self, settings) -> None: + def __init__(self) -> None: self.macropad = MacroPad(layout_class=KeyboardLayout, rotation=180 if SETTINGS["fliprotation"] else 0) self.macropad.display.auto_refresh = False self.macropad.display.brightness = SETTINGS["brightness"] @@ -97,7 +97,6 @@ def __init__(self, settings) -> None: self.serial_data = usb_cdc.data self.serial_last_state = False - self.settings = settings self.macros = self._init_macros() self.keys = self._init_keys() self.toolbar = self._init_toolbar() @@ -105,13 +104,13 @@ def __init__(self, settings) -> None: self.show_homescreen() - def _save_settings(self) -> None: - """ store the settings in the settingsfile + def _save_settings(self, new_settings) -> None: + """ store the new settings in the settingsfile """ if self.readonly: return False with open(SETTINGSFILE, "w") as f: - f.write(json.dumps(self.settings, separators=(",", ":"))) + f.write(json.dumps(new_settings, separators=(",", ":"))) return True def _init_macros(self) -> list[dict]: @@ -389,7 +388,7 @@ def _handle_serial_data(self, payload:str) -> dict: if command == 'get_settings': response['ACK'] = 'settings' - response['CONTENT'] = self.settings + response['CONTENT'] = SETTINGS return response elif command == 'set_settings': @@ -398,9 +397,8 @@ def _handle_serial_data(self, payload:str) -> dict: return response content = payload['content'] - self.settings = content - if self._save_settings(): + if self._save_settings(content): response['ACK'] = 'Settings are set' else: response['ERR'] = 'Cannot set settings because USB storage is enabled' @@ -518,5 +516,5 @@ def start(self) -> None: "content": self.encoder.on_decreased }) -app = MacroApp(SETTINGS) +app = MacroApp() app.start() \ No newline at end of file From 992f4dfb96db13df98545600d85a9436b55af571 Mon Sep 17 00:00:00 2001 From: mchilli Date: Wed, 25 Oct 2023 17:39:34 +0200 Subject: [PATCH 6/6] update README --- README.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index cbdad05..6560468 100644 --- a/README.md +++ b/README.md @@ -11,13 +11,17 @@ This is an [Adafruit MacroPad](https://www.adafruit.com/product/5128) script tha - Make groups to organize your macros - Groups can store more macros or groups - Define encoder macros for different groups -- Set a display timeout to prevent burn-in -- Select a keyboard layout suitable for your language -- You can use a Unicode Font (but this increases the font loading time) - Choose colors for every single macro or group - You can have an almost infinite number of pages - Save your configurations locally by downloading it as a JSON file +- Device settings: + - Choose a keyboard layout suitable for your language + - Set a display timeout to prevent burn-in + - Use a Unicode Font **(increases the font loading time)** + - Flip the rotation of the device by 180 degrees + - Adjust the LCD and LED brightness + #### Installation: Flash circuitpython on to your macropad, following this [guide](https://learn.adafruit.com/adafruit-macropad-rp2040/circuitpython).