From b28d911c14b3533087d891995537552cdc842e96 Mon Sep 17 00:00:00 2001 From: RigglePrime <27156122+RigglePrime@users.noreply.github.com> Date: Tue, 8 Oct 2024 07:15:07 +0200 Subject: [PATCH 01/28] Fix country codes --- src/code.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/code.py b/src/code.py index 1250753..db85602 100644 --- a/src/code.py +++ b/src/code.py @@ -93,10 +93,10 @@ def get_substr(string, start, end): if command == "US": from adafruit_hid.keyboard_layout_us import KeyboardLayoutUS layout = KeyboardLayoutUS(kb) - elif command == "CRO": + elif command in ("SI", "HR", "BA"): from keyboard_layouts.keyboard_layout_win_cr import KeyboardLayout layout = KeyboardLayout(kb) - elif command == "UK": + elif command == "GB": from keyboard_layouts.keyboard_layout_win_uk import KeyboardLayout layout = KeyboardLayout(kb) elif command == "FR": @@ -123,7 +123,7 @@ def get_substr(string, start, end): elif command == "PO": from keyboard_layouts.keyboard_layout_win_po import KeyboardLayout layout = KeyboardLayout(kb) - elif command == "SW": + elif command == "SE": from keyboard_layouts.keyboard_layout_win_sw import KeyboardLayout layout = KeyboardLayout(kb) elif command == "TR": From 8e987f016d775a9c9a0b0438177c29349cb30117 Mon Sep 17 00:00:00 2001 From: RigglePrime <27156122+RigglePrime@users.noreply.github.com> Date: Tue, 8 Oct 2024 08:43:57 +0200 Subject: [PATCH 02/28] Merge layout with main script --- src/code.py | 83 ++++++++++++++++++++++-------------------------- src/layout.txt | 21 ------------ src/pico_usb.txt | 21 +++++++++++- 3 files changed, 58 insertions(+), 67 deletions(-) delete mode 100644 src/layout.txt diff --git a/src/code.py b/src/code.py index db85602..994ec4e 100644 --- a/src/code.py +++ b/src/code.py @@ -17,6 +17,9 @@ kb = Keyboard(usb_hid.devices) ms = Mouse(usb_hid.devices) +from adafruit_hid.keyboard_layout_us import KeyboardLayout +layout = KeyboardLayout(kb) + bt = digitalio.DigitalInOut(board.GP25) bt.direction = digitalio.Direction.INPUT bt.pull = digitalio.Pull.UP @@ -28,6 +31,41 @@ looping = False loop_pos = 0 +def change_layout(layout_id: str): + global layout + del KeyboardLayout + if layout_id == "US": + from adafruit_hid.keyboard_layout_us import KeyboardLayout + elif layout_id in ("SI", "HR", "BA"): + from keyboard_layouts.keyboard_layout_win_cr import KeyboardLayout + elif layout_id == "GB": + from keyboard_layouts.keyboard_layout_win_uk import KeyboardLayout + elif layout_id == "FR": + from keyboard_layouts.keyboard_layout_win_fr import KeyboardLayout + elif layout_id == "CZ": + from keyboard_layouts.keyboard_layout_win_cz import KeyboardLayout + elif layout_id == "BR": + from keyboard_layouts.keyboard_layout_win_br import KeyboardLayout + elif layout_id == "DE": + from keyboard_layouts.keyboard_layout_win_de import KeyboardLayout + elif layout_id == "ES": + from keyboard_layouts.keyboard_layout_win_es import KeyboardLayout + elif layout_id == "HU": + from keyboard_layouts.keyboard_layout_win_hu import KeyboardLayout + elif layout_id == "IT": + from keyboard_layouts.keyboard_layout_win_it import KeyboardLayout + elif layout_id == "PO": + from keyboard_layouts.keyboard_layout_win_po import KeyboardLayout + elif layout_id == "SE": + from keyboard_layouts.keyboard_layout_win_sw import KeyboardLayout + elif layout_id == "TR": + from keyboard_layouts.keyboard_layout_win_tr import KeyboardLayout + elif layout_id == "BE": + from keyboard_layouts.keyboard_layout_win_bene import KeyboardLayout + else: + raise Exception("Unknown keyboard layout") + layout = KeyboardLayout(kb) + def execute_command(function, command): if function == "DELAY": if command.isdigit(): @@ -87,51 +125,6 @@ def get_substr(string, start, end): return command try: - file = io.open("/layout.txt", "r") - line = file.readline() - command = get_substr(line, line.find("("), line.rfind(")")) - if command == "US": - from adafruit_hid.keyboard_layout_us import KeyboardLayoutUS - layout = KeyboardLayoutUS(kb) - elif command in ("SI", "HR", "BA"): - from keyboard_layouts.keyboard_layout_win_cr import KeyboardLayout - layout = KeyboardLayout(kb) - elif command == "GB": - from keyboard_layouts.keyboard_layout_win_uk import KeyboardLayout - layout = KeyboardLayout(kb) - elif command == "FR": - from keyboard_layouts.keyboard_layout_win_fr import KeyboardLayout - layout = KeyboardLayout(kb) - elif command == "CZ": - from keyboard_layouts.keyboard_layout_win_cz import KeyboardLayout - layout = KeyboardLayout(kb) - elif command == "BR": - from keyboard_layouts.keyboard_layout_win_br import KeyboardLayout - layout = KeyboardLayout(kb) - elif command == "DE": - from keyboard_layouts.keyboard_layout_win_de import KeyboardLayout - layout = KeyboardLayout(kb) - elif command == "ES": - from keyboard_layouts.keyboard_layout_win_es import KeyboardLayout - layout = KeyboardLayout(kb) - elif command == "HU": - from keyboard_layouts.keyboard_layout_win_hu import KeyboardLayout - layout = KeyboardLayout(kb) - elif command == "IT": - from keyboard_layouts.keyboard_layout_win_it import KeyboardLayout - layout = KeyboardLayout(kb) - elif command == "PO": - from keyboard_layouts.keyboard_layout_win_po import KeyboardLayout - layout = KeyboardLayout(kb) - elif command == "SE": - from keyboard_layouts.keyboard_layout_win_sw import KeyboardLayout - layout = KeyboardLayout(kb) - elif command == "TR": - from keyboard_layouts.keyboard_layout_win_tr import KeyboardLayout - layout = KeyboardLayout(kb) - elif command == "BE": - from keyboard_layouts.keyboard_layout_win_bene import KeyboardLayout - layout = KeyboardLayout(kb) file = io.open("/pico_usb.txt", "r") line = file.readline() while line != "": diff --git a/src/layout.txt b/src/layout.txt deleted file mode 100644 index aea7cf7..0000000 --- a/src/layout.txt +++ /dev/null @@ -1,21 +0,0 @@ -layout(CRO) - -# to change layout, edit the country layout in between the brackets. Example: layout(US) -# layouts generated using Circuitpython_Keyboard_Layouts -# check it out: https://github.com/Neradoc/Circuitpython_Keyboard_Layouts.git - -#current supported layouts: -# US - United States -# CRO - Croatia/Slovenia/Bosnia -# UK - United Kingdom -# FR - French -# CZ - Czechia -# BR - Brazil -# DE - Germany -# ES - Spain -# HU - Hungary -# IT - Italy -# PO - Poland -# SW - Sweden -# TR - Turkey -# BE - Belgium \ No newline at end of file diff --git a/src/pico_usb.txt b/src/pico_usb.txt index 1c42da4..3054614 100644 --- a/src/pico_usb.txt +++ b/src/pico_usb.txt @@ -1,5 +1,4 @@ # PicoUSB Payloads go in this file -# DO NOT FORGET to change your country keyboard layout in layout.txt! ###################################################################################### ### Commands: ### ### delay() - delays the execution for the number of seconds that is in ### @@ -21,6 +20,26 @@ ### loop() - forever loops everything after the loop command. Use loop only once. ### ###################################################################################### +# Current supported layouts: +# SI - Slovenia +# US - United States (default) +# GB - United Kingdom +# FR - French +# CZ - Czechia +# BR - Brazil +# DE - Germany +# ES - Spain +# HU - Hungary +# IT - Italy +# PO - Poland +# SE - Sweden +# TR - Turkey +# BE - Belgium +# CR - Croatia +# BA - Bosnia + +layout(US) + delay(1) press(windows + d) # minimizes all windows delay(1) From caa63a49bc44c8fa589c5df460db46f103a2a7d1 Mon Sep 17 00:00:00 2001 From: RigglePrime <27156122+RigglePrime@users.noreply.github.com> Date: Tue, 8 Oct 2024 09:07:14 +0200 Subject: [PATCH 03/28] Add a command whoops --- src/code.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/code.py b/src/code.py index 994ec4e..56198f8 100644 --- a/src/code.py +++ b/src/code.py @@ -70,6 +70,8 @@ def execute_command(function, command): if function == "DELAY": if command.isdigit(): time.sleep(float(command)) + elif function == "LAYOUT": + change_layout(command) elif function == "PRESS": command = command.split(" + ") for c in range(0, len(command), 1): From cc0e376a520cd020ad546845040ddb5d928d4d7e Mon Sep 17 00:00:00 2001 From: RigglePrime <27156122+RigglePrime@users.noreply.github.com> Date: Tue, 8 Oct 2024 09:11:32 +0200 Subject: [PATCH 04/28] Whitespace --- src/code.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/code.py b/src/code.py index 56198f8..70ae80d 100644 --- a/src/code.py +++ b/src/code.py @@ -118,7 +118,6 @@ def execute_command(function, command): cc.send(ConsumerControlCode.VOLUME_DECREMENT) elif command == "mute": cc.send(ConsumerControlCode.MUTE) - def get_substr(string, start, end): command = "" From 09ee0b37eb2d26362be3972efb301035fc3e2acd Mon Sep 17 00:00:00 2001 From: RigglePrime <27156122+RigglePrime@users.noreply.github.com> Date: Wed, 16 Oct 2024 14:06:38 +0200 Subject: [PATCH 05/28] Guard statement and custom exception --- src/code.py | 15 +++++++-------- src/exceptions.py | 3 +++ 2 files changed, 10 insertions(+), 8 deletions(-) create mode 100644 src/exceptions.py diff --git a/src/code.py b/src/code.py index 70ae80d..d7fd158 100644 --- a/src/code.py +++ b/src/code.py @@ -73,14 +73,13 @@ def execute_command(function, command): elif function == "LAYOUT": change_layout(command) elif function == "PRESS": - command = command.split(" + ") - for c in range(0, len(command), 1): - command[c] = command[c].upper() - if len(command) <= 6: - keys = [0] * len(command) - for idx in range(0, len(command), 1): - keys[idx] = getattr(Keycode, command[idx]) - kb.send(*keys) + command: list[str] = [x.strip().upper() for x in command.split("+")] + if len(command) > 6: + raise PicoKeyboardException("Too many keys pressed at once!") + keys = [0] * len(command) + for idx in range(0, len(command), 1): + keys[idx] = getattr(Keycode, command[idx]) + kb.send(*keys) elif function == "WRITE": layout.write(command) elif function == "HOLD": diff --git a/src/exceptions.py b/src/exceptions.py new file mode 100644 index 0000000..3c236f0 --- /dev/null +++ b/src/exceptions.py @@ -0,0 +1,3 @@ +class PicoLayoutException(Exception): pass +class PicoCommandException(Exception): pass +class PicoKeyboardException(Exception): pass From 33283df1f7a5e5ebd78d78666564886615f9c8d3 Mon Sep 17 00:00:00 2001 From: RigglePrime <27156122+RigglePrime@users.noreply.github.com> Date: Wed, 16 Oct 2024 14:06:54 +0200 Subject: [PATCH 06/28] Code formatting and more exceptions --- src/code.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/code.py b/src/code.py index d7fd158..da34520 100644 --- a/src/code.py +++ b/src/code.py @@ -13,6 +13,8 @@ from adafruit_hid.keycode import Keycode from adafruit_hid.mouse import Mouse +from exceptions import PicoCommandException, PicoLayoutException, PicoKeyboardException + cc = ConsumerControl(usb_hid.devices) kb = Keyboard(usb_hid.devices) ms = Mouse(usb_hid.devices) @@ -63,13 +65,12 @@ def change_layout(layout_id: str): elif layout_id == "BE": from keyboard_layouts.keyboard_layout_win_bene import KeyboardLayout else: - raise Exception("Unknown keyboard layout") + raise PicoLayoutException("Unknown keyboard layout") layout = KeyboardLayout(kb) -def execute_command(function, command): - if function == "DELAY": - if command.isdigit(): - time.sleep(float(command)) +def execute_command(function: str, command: str): + if function in ("DELAY", "SLEEP"): + time.sleep(float(command)) elif function == "LAYOUT": change_layout(command) elif function == "PRESS": @@ -117,6 +118,8 @@ def execute_command(function, command): cc.send(ConsumerControlCode.VOLUME_DECREMENT) elif command == "mute": cc.send(ConsumerControlCode.MUTE) + else: + raise PicoCommandException("Unknown command") def get_substr(string, start, end): command = "" @@ -125,7 +128,7 @@ def get_substr(string, start, end): return command try: - file = io.open("/pico_usb.txt", "r") + file: io.FileIO = io.open("/pico_usb.txt", "r") line = file.readline() while line != "": function = line.split("(",1)[0].upper() From ae50a3aff3d383be0e8a75dad240585aa004d1f7 Mon Sep 17 00:00:00 2001 From: RigglePrime <27156122+RigglePrime@users.noreply.github.com> Date: Wed, 16 Oct 2024 17:47:06 +0200 Subject: [PATCH 07/28] Rewrite loop --- src/code.py | 65 ++++++++++++++++++++++++++--------------------------- 1 file changed, 32 insertions(+), 33 deletions(-) diff --git a/src/code.py b/src/code.py index da34520..faa683d 100644 --- a/src/code.py +++ b/src/code.py @@ -30,9 +30,6 @@ led.direction = digitalio.Direction.OUTPUT led.value = True -looping = False -loop_pos = 0 - def change_layout(layout_id: str): global layout del KeyboardLayout @@ -121,37 +118,39 @@ def execute_command(function: str, command: str): else: raise PicoCommandException("Unknown command") -def get_substr(string, start, end): - command = "" - for idx in range(start+1, end): - command += string[idx] - return command try: - file: io.FileIO = io.open("/pico_usb.txt", "r") - line = file.readline() - while line != "": - function = line.split("(",1)[0].upper() - command = get_substr(line, line.find("("), line.rfind(")")) - if looping == False: - loop_pos += len(line) + loop_pos = 0 + loop_times = -1 + # It is a good idea to seek and constantly read instead + # of storing the whole file in RAM, as the file could + # potentially be bigger than our tiny RAM + file: io.TextIOWrapper = io.open("/pico_usb.txt", "r") + file.seek(0, 2) # Move to the end of the file + file_end = file.tell() + file.seek(0) + while line := file.readline(): + function = line.split(" ", 1) + if len(function) == 2: + function, command = function + else: + function = function[0] + command = None if function == "LOOP": - looping = True + loop_pos = file.tell() + if command: + loop_times = int(command.strip()) execute_command(function, command) - line = file.readline() - file.close() - file = io.open("/pico_usb.txt", "r") - while looping == True: - file.seek(loop_pos) - line = file.readline() - while line != "": - function = line.split("(",1)[0].upper() - command = get_substr(line, line.find("("), line.rfind(")")) - execute_command(function, command) - line = file.readline() - - file.close() - -except OSError as e: - print(e) -kb.release_all() + if loop_pos and file.tell() == file_end: + if not loop_times: + break + file.seek(loop_pos) + # Explicitly check if we set loop_times so we + # don't end up decrementing it and creating + # a huge number (could result in a crash) + if loop_times != -1: + loop_times -= 1 +finally: + kb.release_all() + if file: + file.close() From 675e5c08d645e718db46531562c572ae70c3cb24 Mon Sep 17 00:00:00 2001 From: RigglePrime <27156122+RigglePrime@users.noreply.github.com> Date: Wed, 16 Oct 2024 17:50:12 +0200 Subject: [PATCH 08/28] Fix --- src/code.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/code.py b/src/code.py index faa683d..42c0791 100644 --- a/src/code.py +++ b/src/code.py @@ -130,16 +130,16 @@ def execute_command(function: str, command: str): file_end = file.tell() file.seek(0) while line := file.readline(): - function = line.split(" ", 1) - if len(function) == 2: - function, command = function + line = line.split(" ", 1) + if len(line) == 2: + function, command = line else: - function = function[0] + function = line[0] command = None - if function == "LOOP": + if function.upper() == "LOOP": loop_pos = file.tell() if command: - loop_times = int(command.strip()) + loop_times = int(command) execute_command(function, command) if loop_pos and file.tell() == file_end: if not loop_times: From 98b0ce656790184560bedf5b8209e7d0265acca9 Mon Sep 17 00:00:00 2001 From: RigglePrime <27156122+RigglePrime@users.noreply.github.com> Date: Wed, 16 Oct 2024 17:56:43 +0200 Subject: [PATCH 09/28] Strip it --- src/code.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/code.py b/src/code.py index 42c0791..c522692 100644 --- a/src/code.py +++ b/src/code.py @@ -130,12 +130,13 @@ def execute_command(function: str, command: str): file_end = file.tell() file.seek(0) while line := file.readline(): - line = line.split(" ", 1) + line = line.rstrip('\n').split(" ", 1) if len(line) == 2: function, command = line else: function = line[0] command = None + function = function.strip().upper() if function.upper() == "LOOP": loop_pos = file.tell() if command: From dfd68823b0ebf31657e04dd45fbf5aa57aeef599 Mon Sep 17 00:00:00 2001 From: RigglePrime <27156122+RigglePrime@users.noreply.github.com> Date: Wed, 16 Oct 2024 18:02:52 +0200 Subject: [PATCH 10/28] Improve PRESS --- src/code.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/code.py b/src/code.py index c522692..ecd21d1 100644 --- a/src/code.py +++ b/src/code.py @@ -74,10 +74,7 @@ def execute_command(function: str, command: str): command: list[str] = [x.strip().upper() for x in command.split("+")] if len(command) > 6: raise PicoKeyboardException("Too many keys pressed at once!") - keys = [0] * len(command) - for idx in range(0, len(command), 1): - keys[idx] = getattr(Keycode, command[idx]) - kb.send(*keys) + kb.send(Keycode.__dict__[k] for k in command) elif function == "WRITE": layout.write(command) elif function == "HOLD": From f663edccb897cc05a07d5438c3ea6e9357a42fa3 Mon Sep 17 00:00:00 2001 From: RigglePrime <27156122+RigglePrime@users.noreply.github.com> Date: Wed, 16 Oct 2024 18:06:06 +0200 Subject: [PATCH 11/28] Better HOLD --- src/code.py | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/code.py b/src/code.py index ecd21d1..e17b0fd 100644 --- a/src/code.py +++ b/src/code.py @@ -78,14 +78,10 @@ def execute_command(function: str, command: str): elif function == "WRITE": layout.write(command) elif function == "HOLD": - command = command.split(" + ") - for c in range(0, len(command), 1): - command[c] = command[c].upper() - if len(command) <= 6: - keys = [0] * len(command) - for idx in range(0, len(command), 1): - keys[idx] = getattr(Keycode, command[idx]) - kb.press(*keys) + command = [x.strip().upper() for x in command.split("+")] + if len(command) > 6: + raise PicoKeyboardException("Too many keys held at once!") + kb.press(Keycode.__dict__[k] for k in command) elif function == "RELEASE": kb.release_all() elif function == "MOVE": From eea82c2a432f270c38f4ad09697e53406e1dd6f1 Mon Sep 17 00:00:00 2001 From: RigglePrime <27156122+RigglePrime@users.noreply.github.com> Date: Wed, 16 Oct 2024 18:06:15 +0200 Subject: [PATCH 12/28] Better MOVE --- src/code.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/code.py b/src/code.py index e17b0fd..cabf843 100644 --- a/src/code.py +++ b/src/code.py @@ -85,11 +85,8 @@ def execute_command(function: str, command: str): elif function == "RELEASE": kb.release_all() elif function == "MOVE": - command = command.split(", ") - pos = [0] * 2 - for i in range(0, len(command), 1): - pos[i] = int(command[i]) - ms.move(x=pos[0], y=-1*pos[1], wheel=0) + x, y = [int(a) for a in command.split(',')] + ms.move(x=x, y=-1*y, wheel=0) elif function == "SCROLL": ms.move(x=0, y=0, wheel=int(command)) elif function == "CLICK": From 97c77c18fbe0f8567f8f2ba5dc76cb494dab013d Mon Sep 17 00:00:00 2001 From: RigglePrime <27156122+RigglePrime@users.noreply.github.com> Date: Wed, 16 Oct 2024 18:07:19 +0200 Subject: [PATCH 13/28] Snarky comment --- src/code.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/code.py b/src/code.py index cabf843..c3d0f8f 100644 --- a/src/code.py +++ b/src/code.py @@ -90,6 +90,7 @@ def execute_command(function: str, command: str): elif function == "SCROLL": ms.move(x=0, y=0, wheel=int(command)) elif function == "CLICK": + command = command.lower() # We love consistency!! if command == "left": ms.click(Mouse.LEFT_BUTTON) elif command == "middle": From 332ec072bc8b7ef0be979bbb74d2a1b025330bb5 Mon Sep 17 00:00:00 2001 From: RigglePrime <27156122+RigglePrime@users.noreply.github.com> Date: Wed, 16 Oct 2024 18:08:45 +0200 Subject: [PATCH 14/28] Check for comment --- src/code.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/code.py b/src/code.py index c3d0f8f..ae1683a 100644 --- a/src/code.py +++ b/src/code.py @@ -66,6 +66,8 @@ def change_layout(layout_id: str): layout = KeyboardLayout(kb) def execute_command(function: str, command: str): + if function[0] == '#': + return if function in ("DELAY", "SLEEP"): time.sleep(float(command)) elif function == "LAYOUT": From f011e027c9589e58d1d5cc04aec94123f9146ec8 Mon Sep 17 00:00:00 2001 From: RigglePrime <27156122+RigglePrime@users.noreply.github.com> Date: Wed, 16 Oct 2024 18:13:24 +0200 Subject: [PATCH 15/28] Better volume --- src/code.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/code.py b/src/code.py index ae1683a..edb7483 100644 --- a/src/code.py +++ b/src/code.py @@ -100,14 +100,16 @@ def execute_command(function: str, command: str): elif command == "right": ms.click(Mouse.RIGHT_BUTTON) elif function == "VOLUME": - if command.isdigit(): - for vc in range(0, abs(int(command)), 1): - if int(command) > 0: - cc.send(ConsumerControlCode.VOLUME_INCREMENT) - elif int(command) < 0: - cc.send(ConsumerControlCode.VOLUME_DECREMENT) - elif command == "mute": + if command.lower() == "mute": cc.send(ConsumerControlCode.MUTE) + else: + amount = int(command) + to_send = ConsumerControlCode.VOLUME_INCREMENT + if amount < 0: + amount = -amount + to_send = ConsumerControlCode.VOLUME_DECREMENT + for _ in range(amount): + cc.send(to_send) else: raise PicoCommandException("Unknown command") From 0fcf43f73a65885ba6320ae4a1fc1bce281336ee Mon Sep 17 00:00:00 2001 From: RigglePrime <27156122+RigglePrime@users.noreply.github.com> Date: Wed, 16 Oct 2024 19:46:29 +0200 Subject: [PATCH 16/28] Add a replace --- src/code.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/code.py b/src/code.py index edb7483..5225b27 100644 --- a/src/code.py +++ b/src/code.py @@ -78,7 +78,7 @@ def execute_command(function: str, command: str): raise PicoKeyboardException("Too many keys pressed at once!") kb.send(Keycode.__dict__[k] for k in command) elif function == "WRITE": - layout.write(command) + layout.write(command.replace("\\n", "\n")) elif function == "HOLD": command = [x.strip().upper() for x in command.split("+")] if len(command) > 6: @@ -125,7 +125,7 @@ def execute_command(function: str, command: str): file_end = file.tell() file.seek(0) while line := file.readline(): - line = line.rstrip('\n').split(" ", 1) + line = line.rstrip('\r\n').split(" ", 1) if len(line) == 2: function, command = line else: From 9d5045708ea3b01c47415302d0cbcaf4c6d03082 Mon Sep 17 00:00:00 2001 From: RigglePrime <27156122+RigglePrime@users.noreply.github.com> Date: Wed, 16 Oct 2024 19:47:28 +0200 Subject: [PATCH 17/28] Add writefile --- src/code.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/code.py b/src/code.py index 5225b27..f1ab1b3 100644 --- a/src/code.py +++ b/src/code.py @@ -79,6 +79,8 @@ def execute_command(function: str, command: str): kb.send(Keycode.__dict__[k] for k in command) elif function == "WRITE": layout.write(command.replace("\\n", "\n")) + elif function == "WRITEFILE ": + layout.write(open(command, "r").read()) elif function == "HOLD": command = [x.strip().upper() for x in command.split("+")] if len(command) > 6: From b95abcadb66b4ced9f0c2898fe12d95b1c9778d6 Mon Sep 17 00:00:00 2001 From: RigglePrime <27156122+RigglePrime@users.noreply.github.com> Date: Wed, 16 Oct 2024 19:59:40 +0200 Subject: [PATCH 18/28] Update docs and demo --- README.md | 21 ++++++++++---------- src/pico_usb.txt | 50 ++++++++++++++++++++++++------------------------ 2 files changed, 36 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index 5dde3f2..290748d 100644 --- a/README.md +++ b/README.md @@ -47,16 +47,17 @@ That is it! Modify `pico_usb.txt` to change the functionality. See below to know **pico_usb.txt API:** -- delay() - waits for the specified amount of time before resuming execution. Example: delay(0.8) -- press() - presses one or more buttons once. For example to press enter, use `press(enter)`. To "select all", use `press(control + a)`. -- write() - sequentially presses many buttons in a row. example: `write(Hello world!)` -- hold() - presses and holds down one or more buttons until `release()` is called -- release() - releases **all** held keys -- move(x, y) - moves the mouse on the main display to the given location, from the current location as a reference. negative x = left, possitive x = right, negative y = down, possitive y = up. -- click(btn)- clicks the mouse. `btn` is the mouse button, options are left, right, middle -- scroll(x) - scrolls the mouse. Negative number scrolls down, possitive scroll up -- volume(x) - Modifies the system volume. Negative numbers move the volume slider down by x, possitive move it up by x. min volume = 0. max = 100. `volume(mute)` mutes the speakers. -- loop() - loops everything before this command +- delay - waits for the specified amount of time before resuming execution. Example: delay(0.8) +- press - presses one or more buttons once. For example to press enter, use `press enter`. To "select all", use `press control + a`. +- write - sequentially presses many buttons in a row. example: `write Hello world!` +- writefile - reads a file and uses the contents as keypresses. Make sure the file isn't too large (>100kB). example: `writefile commands.txt` +- hold - presses and holds down one or more buttons until `release()` is called +- release - releases **all** held keys +- move x, y - moves the mouse on the main display to the given location, from the current location as a reference. negative x = left, possitive x = right, negative y = down, possitive y = up. +- click btn - clicks the mouse. `btn` is the mouse button, options are left, right, middle +- scroll - scrolls the mouse. Negative number scrolls down, possitive scroll up +- volume x - Modifies the system volume. Negative numbers move the volume slider down by x, possitive move it up by x. min volume = 0. max = 100. `volume mute` mutes the speakers. +- loop - loops everything after this command up until the end of the file ## Development diff --git a/src/pico_usb.txt b/src/pico_usb.txt index 3054614..fcdb83b 100644 --- a/src/pico_usb.txt +++ b/src/pico_usb.txt @@ -1,23 +1,23 @@ # PicoUSB Payloads go in this file ###################################################################################### ### Commands: ### -### delay() - delays the execution for the number of seconds that is in ### +### delay - delays the execution for the number of seconds that is in ### ### between brackets, example: delay(0.8) ### -### press() - presses once, all together, one or more buttons. for example, ### +### press - presses once, all together, one or more buttons. for example, ### ### to press enter, use press(enter), to "select all", ### ### use press(control + a). ### -### write() - writes down anything that is written between the brackets. ### +### write - writes down anything that is written between the brackets. ### ### example: write(https://www.youtube.com/) ### -### hold() - holds down one or more buttons ### -### release() - releases all held keys (all) ### -### move(x, y) - moves the mouse on the main display to the given location, ### +### hold - holds down one or more buttons ### +### release - releases all held keys (all) ### +### move x, y - moves the mouse on the main display to the given location, ### ### from the current location as a reference. negative x = left, ### ### positive x = right, negative y = down, positive y = up. ### -### click(btn)- btn is the mouse button, options are left, right, middle ### -### scroll(x) - negative number scrolls down, possitive scrolls up ### -### volume(x) - negative number is volume down by x, positive volume up by x. ### +### click btn - btn is the mouse button, options are left, right, middle ### +### scroll x - negative number scrolls down, possitive scrolls up ### +### volume x - negative number is volume down by x, positive volume up by x. ### ### min volume = 0. max = 100. volume(mute) mutes the speakers. ### -### loop() - forever loops everything after the loop command. Use loop only once. ### +### loop - forever loops everything after the loop command. Use loop only once. ### ###################################################################################### # Current supported layouts: @@ -38,19 +38,19 @@ # CR - Croatia # BA - Bosnia -layout(US) +layout US -delay(1) -press(windows + d) # minimizes all windows -delay(1) -press(windows + r) # Run window -delay(2) -write(notepad) -press(enter) -delay(2) -write(Hello from PicoUSB!) -delay(1) -loop() -write(!) -move(5, 5) -delay(0.5) +delay 1 +press(gui + d) # minimizes all windows +delay 1 +press gui + r # Run window +delay 2 +write notepad +press enter +delay 2 +write Hello from PicoUSB! +delay 1 +loop +write ! +move 5, 5 +delay 0.5 From 8ba92199612e1cff74bad9884c04541eb6439b6c Mon Sep 17 00:00:00 2001 From: RigglePrime <27156122+RigglePrime@users.noreply.github.com> Date: Thu, 17 Oct 2024 02:25:49 +0200 Subject: [PATCH 19/28] Declutter boot --- src/boot.py | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/src/boot.py b/src/boot.py index bbcdf1b..e9148e1 100644 --- a/src/boot.py +++ b/src/boot.py @@ -25,23 +25,17 @@ storage.remount("/", readonly=False) m = storage.getmount("/") -m.label = "PicoUSB" -storage.remount("/", readonly=True) -storage.enable_usb_drive() +m.label = "KISTON" -time.sleep(0.1) #wait a bit so the button gets pulled up +time.sleep(0.05) # Wait a bit so the button gets pulled up if mode.value: storage.disable_usb_drive() else: - time.sleep(0.1) #check again after 100ms to see if the button is still pressed - if mode.value: - storage.disable_usb_drive() - else: - storage.enable_usb_drive() - microcontroller.on_next_reset(microcontroller.RunMode.SAFE_MODE) - microcontroller.reset() - + storage.remount("/", readonly=True) + storage.enable_usb_drive() + microcontroller.on_next_reset(microcontroller.RunMode.SAFE_MODE) + microcontroller.reset() # in case you screw up and disable usb drive without the ability to enable it, to enter safe mode write in shell: # import microcontroller From bc42ad053cac5adf3ce0cd12c7f6d28494957165 Mon Sep 17 00:00:00 2001 From: RigglePrime <27156122+RigglePrime@users.noreply.github.com> Date: Thu, 17 Oct 2024 02:26:13 +0200 Subject: [PATCH 20/28] Fixes --- src/code.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/code.py b/src/code.py index f1ab1b3..906ed0b 100644 --- a/src/code.py +++ b/src/code.py @@ -32,6 +32,7 @@ def change_layout(layout_id: str): global layout + global KeyboardLayout del KeyboardLayout if layout_id == "US": from adafruit_hid.keyboard_layout_us import KeyboardLayout @@ -76,16 +77,18 @@ def execute_command(function: str, command: str): command: list[str] = [x.strip().upper() for x in command.split("+")] if len(command) > 6: raise PicoKeyboardException("Too many keys pressed at once!") - kb.send(Keycode.__dict__[k] for k in command) - elif function == "WRITE": + kb.send(*(Keycode.__dict__[k] for k in command)) + elif function in ("WRITE", "WRITELN"): layout.write(command.replace("\\n", "\n")) - elif function == "WRITEFILE ": - layout.write(open(command, "r").read()) + if function == "WRITELN": + kb.press(layout._char_to_keycode('\n')) + elif function == "WRITEFILE": + layout.write(open(command, "r").read().replace("\r", "")) elif function == "HOLD": command = [x.strip().upper() for x in command.split("+")] if len(command) > 6: raise PicoKeyboardException("Too many keys held at once!") - kb.press(Keycode.__dict__[k] for k in command) + kb.press(*(Keycode.__dict__[k] for k in command)) elif function == "RELEASE": kb.release_all() elif function == "MOVE": @@ -127,6 +130,8 @@ def execute_command(function: str, command: str): file_end = file.tell() file.seek(0) while line := file.readline(): + if not line.strip(): + continue line = line.rstrip('\r\n').split(" ", 1) if len(line) == 2: function, command = line @@ -138,6 +143,7 @@ def execute_command(function: str, command: str): loop_pos = file.tell() if command: loop_times = int(command) + continue execute_command(function, command) if loop_pos and file.tell() == file_end: if not loop_times: From a54179a67dd70a3c5bc476bb500767d2339b0716 Mon Sep 17 00:00:00 2001 From: RigglePrime <27156122+RigglePrime@users.noreply.github.com> Date: Thu, 17 Oct 2024 02:26:18 +0200 Subject: [PATCH 21/28] Update docs --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 290748d..44eb338 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ That is it! Modify `pico_usb.txt` to change the functionality. See below to know **pico_usb.txt API:** - delay - waits for the specified amount of time before resuming execution. Example: delay(0.8) -- press - presses one or more buttons once. For example to press enter, use `press enter`. To "select all", use `press control + a`. +- press - presses one or more buttons once. For example to press enter, use `press enter`. To "select all", use `press control + a`. Press also causes the Pico to release all keys after being executed. - write - sequentially presses many buttons in a row. example: `write Hello world!` - writefile - reads a file and uses the contents as keypresses. Make sure the file isn't too large (>100kB). example: `writefile commands.txt` - hold - presses and holds down one or more buttons until `release()` is called From f3ac380835eab32a8c78f6321842b35584461efd Mon Sep 17 00:00:00 2001 From: RigglePrime <27156122+RigglePrime@users.noreply.github.com> Date: Thu, 17 Oct 2024 02:31:40 +0200 Subject: [PATCH 22/28] Forgot to change this one --- src/example.txt | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/src/example.txt b/src/example.txt index baedcde..45b522e 100644 --- a/src/example.txt +++ b/src/example.txt @@ -1,15 +1,21 @@ # dont forget to change your keyboard layout in layout.txt -delay(3) #on slower computers it is better to have bigger delays. I usually use delay(0.8) on my faster PC. -press(windows + d) # minimizes all windows -delay(2) -press(windows + e) # opens windows explorer on windows -delay(2) -press(control + l) # edit path/link. -delay(2) -write(https://youtu.be/dQw4w9WgXcQ) -delay(2) -press(enter) # Will open the default browser. -delay(2) -press(windows + d) # minimizes all windows -volume(100) +# on slower computers it is better to have bigger delays. I usually use delay(0.8) on my faster PC. +delay 3 +# minimizes all windows +press windows + d +delay 2 +# opens windows explorer on windows +press windows + e +delay 2 +# edit path/link. +press control + l +delay 2 +write https://youtu.be/dQw4w9WgXcQ +delay 2 +# Will open the default browser. +press enter +delay 2 +# minimizes all windows +press windows + d +volume 100 From b9e2a19b0f202e865d9256ce5769893bce42fa31 Mon Sep 17 00:00:00 2001 From: RigglePrime <27156122+RigglePrime@users.noreply.github.com> Date: Thu, 17 Oct 2024 02:34:00 +0200 Subject: [PATCH 23/28] e --- README.md | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 44eb338..627739a 100644 --- a/README.md +++ b/README.md @@ -42,22 +42,23 @@ That is it! Modify `pico_usb.txt` to change the functionality. See below to know - pico_usb.txt - here is where your executable pseudo-code is located. - layout.txt - here is where you select your keyboard layout. -- code.py - interpreter that executes your pesudo code. Free to modify. (1) -- boot.py - this code executes before the USB is recognised. Free to modify. (1) +- code.py - interpreter that executes your pesudo code. Free to modify. +- boot.py - this code executes before the USB is recognised. Free to modify. **pico_usb.txt API:** -- delay - waits for the specified amount of time before resuming execution. Example: delay(0.8) -- press - presses one or more buttons once. For example to press enter, use `press enter`. To "select all", use `press control + a`. Press also causes the Pico to release all keys after being executed. -- write - sequentially presses many buttons in a row. example: `write Hello world!` -- writefile - reads a file and uses the contents as keypresses. Make sure the file isn't too large (>100kB). example: `writefile commands.txt` -- hold - presses and holds down one or more buttons until `release()` is called -- release - releases **all** held keys -- move x, y - moves the mouse on the main display to the given location, from the current location as a reference. negative x = left, possitive x = right, negative y = down, possitive y = up. -- click btn - clicks the mouse. `btn` is the mouse button, options are left, right, middle -- scroll - scrolls the mouse. Negative number scrolls down, possitive scroll up -- volume x - Modifies the system volume. Negative numbers move the volume slider down by x, possitive move it up by x. min volume = 0. max = 100. `volume mute` mutes the speakers. -- loop - loops everything after this command up until the end of the file +- `#` - must be the first character in the line. That line will be ignored. +- `delay` - waits for the specified amount of time before resuming execution. Example: `delay 0.8` +- `press` - presses one or more buttons once. For example to press enter, use `press enter`. To "select all", use `press control + a`. Press also causes the Pico to release all keys after being executed. +- `write` - sequentially presses many buttons in a row. example: `write Hello world!` +- `writefile` - reads a file and uses the contents as keypresses. Make sure the file isn't too large (>100kB). example: `writefile commands.txt` +- `hold` - presses and holds down one or more buttons until `release` is called +- `release` - releases **all** held keys +- `move x, y` - moves the mouse on the main display to the given location, from the current location as a reference. negative x = left, possitive x = right, negative y = down, possitive y = up. +- `click btn` - clicks the mouse. `btn` is the mouse button, options are left, right, middle +- `scroll` - scrolls the mouse. Negative number scrolls down, possitive scroll up +- `volume x` - Modifies the system volume. Negative numbers move the volume slider down by x, possitive move it up by x. min volume = 0. max = 100. `volume mute` mutes the speakers. +- `loop` - loops everything after this command up until the end of the file ## Development From b9640eab57b89fc7ffe115ef4946f24f05613c95 Mon Sep 17 00:00:00 2001 From: RigglePrime <27156122+RigglePrime@users.noreply.github.com> Date: Thu, 17 Oct 2024 02:34:52 +0200 Subject: [PATCH 24/28] Rename back to PicoUSB No more dollar store KINGSTONE --- src/boot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/boot.py b/src/boot.py index e9148e1..5fd9fb8 100644 --- a/src/boot.py +++ b/src/boot.py @@ -25,7 +25,7 @@ storage.remount("/", readonly=False) m = storage.getmount("/") -m.label = "KISTON" +m.label = "PicoUSB" time.sleep(0.05) # Wait a bit so the button gets pulled up From bd74e7cfa48b14ae391673a9d07bd459387eae4c Mon Sep 17 00:00:00 2001 From: RigglePrime <27156122+RigglePrime@users.noreply.github.com> Date: Thu, 17 Oct 2024 02:38:48 +0200 Subject: [PATCH 25/28] Add docs for loop --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 627739a..223f2e9 100644 --- a/README.md +++ b/README.md @@ -59,6 +59,7 @@ That is it! Modify `pico_usb.txt` to change the functionality. See below to know - `scroll` - scrolls the mouse. Negative number scrolls down, possitive scroll up - `volume x` - Modifies the system volume. Negative numbers move the volume slider down by x, possitive move it up by x. min volume = 0. max = 100. `volume mute` mutes the speakers. - `loop` - loops everything after this command up until the end of the file +- `loop x` - same as loop but stops after x times ## Development From 98711e7efeb7e8b7d268cbfe9abc2887b65660cf Mon Sep 17 00:00:00 2001 From: RigglePrime <27156122+RigglePrime@users.noreply.github.com> Date: Thu, 17 Oct 2024 02:41:44 +0200 Subject: [PATCH 26/28] Change press to send --- src/code.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/code.py b/src/code.py index 906ed0b..8273b0c 100644 --- a/src/code.py +++ b/src/code.py @@ -81,7 +81,7 @@ def execute_command(function: str, command: str): elif function in ("WRITE", "WRITELN"): layout.write(command.replace("\\n", "\n")) if function == "WRITELN": - kb.press(layout._char_to_keycode('\n')) + kb.send(layout._char_to_keycode('\n')) elif function == "WRITEFILE": layout.write(open(command, "r").read().replace("\r", "")) elif function == "HOLD": From cbefc9a6f895e1cee89219a4e01459568294ccb6 Mon Sep 17 00:00:00 2001 From: RigglePrime <27156122+RigglePrime@users.noreply.github.com> Date: Thu, 17 Oct 2024 02:43:17 +0200 Subject: [PATCH 27/28] Spacing --- src/code.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/code.py b/src/code.py index 8273b0c..a41a2ac 100644 --- a/src/code.py +++ b/src/code.py @@ -30,6 +30,7 @@ led.direction = digitalio.Direction.OUTPUT led.value = True + def change_layout(layout_id: str): global layout global KeyboardLayout @@ -66,6 +67,7 @@ def change_layout(layout_id: str): raise PicoLayoutException("Unknown keyboard layout") layout = KeyboardLayout(kb) + def execute_command(function: str, command: str): if function[0] == '#': return From 90dcb1029cb0b3a538d1526c04f7790f7ec4772f Mon Sep 17 00:00:00 2001 From: RigglePrime <27156122+RigglePrime@users.noreply.github.com> Date: Thu, 17 Oct 2024 02:43:38 +0200 Subject: [PATCH 28/28] Remove unused imports --- src/code.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/code.py b/src/code.py index a41a2ac..b6010ff 100644 --- a/src/code.py +++ b/src/code.py @@ -1,6 +1,4 @@ import io -import os -import re import time import board import storage