diff --git a/.github/workflows/core_build.yml b/.github/workflows/core_build.yml
deleted file mode 100644
index b0dc41d3b3..0000000000
--- a/.github/workflows/core_build.yml
+++ /dev/null
@@ -1,121 +0,0 @@
-name: Core Build
-
-on:
-  push:
-    branches: [ "master" ]
-  pull_request:
-    branches: [ "master" ]
-  workflow_dispatch: # manual trigger
-
-jobs:
-  setup:
-    runs-on: ubuntu-latest
-    outputs:
-      vortex_version_major: ${{ steps.set_version.outputs.vortex_version_major }}
-      vortex_version_minor: ${{ steps.set_version.outputs.vortex_version_minor }}
-      vortex_build_number: ${{ steps.set_version.outputs.vortex_build_number }}
-      vortex_version_number: ${{ steps.set_version.outputs.vortex_version_number }}
-    steps:
-      - uses: actions/checkout@v4
-        with:
-          fetch-depth: 0 # Fetches all history for all branches and tags
-      - name: Determine Version and Build Number
-        id: set_version
-        run: |
-          # Fetch all tags
-          git fetch --depth=1 origin +refs/tags/*:refs/tags/*
-          # Get the latest tag that matches the branch suffix
-          LATEST_TAG=$(git tag --list | grep -E "^[[:digit:]]+\.[[:digit:]]+\$" | sort -V | tail -n1)
-          if [ -z "$LATEST_TAG" ]; then
-            echo "No matching tags found. Setting default version."
-            VERSION_MAJOR="0"
-            VERSION_MINOR="1"
-            BUILD_NUMBER="0"
-          else
-            echo "Found latest tag: $LATEST_TAG"
-            VERSION_MAJOR=$(echo $LATEST_TAG | cut -d. -f1)
-            VERSION_MINOR=$(echo $LATEST_TAG | cut -d. -f2)
-            BUILD_NUMBER=$(git rev-list --count $LATEST_TAG..HEAD)
-          fi
-          FULL_VERSION="$VERSION_MAJOR.$VERSION_MINOR.$BUILD_NUMBER"
-          echo "vortex_version_major=$VERSION_MAJOR" >> $GITHUB_OUTPUT
-          echo "vortex_version_minor=$VERSION_MINOR" >> $GITHUB_OUTPUT
-          echo "vortex_build_number=$BUILD_NUMBER" >> $GITHUB_OUTPUT
-          echo "vortex_version_number=$FULL_VERSION" >> $GITHUB_OUTPUT
-          echo "Version Number: $FULL_VERSION"
-
-  test:
-    needs: setup
-    runs-on: ubuntu-latest
-    steps:
-    - name: Checkout current repository
-      uses: actions/checkout@v3
-    - name: Update Package Lists
-      run: sudo apt-get update
-    - name: Install Dependencies
-      run: sudo apt-get install valgrind g++ make --fix-missing
-    - name: Build
-      run: |
-        export VORTEX_VERSION_MAJOR=${{ needs.setup.outputs.vortex_version_major }}
-        export VORTEX_VERSION_MINOR=${{ needs.setup.outputs.vortex_version_minor }}
-        export VORTEX_BUILD_NUMBER=${{ needs.setup.outputs.vortex_build_number }}
-        export VORTEX_VERSION_NUMBER=${{ needs.setup.outputs.vortex_version_number }}
-        make -j
-      working-directory: VortexEngine
-    - name: Set execute permissions for test script
-      run: chmod +x ./runtests.sh
-      working-directory: VortexEngine/tests
-    - name: Run general tests
-      run: ./runtests.sh --general
-      working-directory: VortexEngine/tests
-
-  wasm:
-    needs: [setup, test]
-    runs-on: ubuntu-latest
-    steps:
-    - name: Checkout current repository
-      uses: actions/checkout@v3
-    - name: Update Package Lists
-      run: sudo apt-get update
-    - name: Install Emscripten
-      run: |
-        sudo apt install -y cmake python3
-        git clone https://github.com/emscripten-core/emsdk.git
-        cd emsdk
-        ./emsdk install latest
-        ./emsdk activate latest
-      working-directory: VortexEngine/VortexLib
-    - name: Build Webassembly
-      run: |
-        source ./emsdk/emsdk_env.sh
-        export VORTEX_VERSION_MAJOR=${{ needs.setup.outputs.vortex_version_major }}
-        export VORTEX_VERSION_MINOR=${{ needs.setup.outputs.vortex_version_minor }}
-        export VORTEX_BUILD_NUMBER=${{ needs.setup.outputs.vortex_build_number }}
-        export VORTEX_VERSION_NUMBER=${{ needs.setup.outputs.vortex_version_number }}
-        make -j wasm
-      working-directory: VortexEngine/VortexLib
-
-  docs:
-    needs: [setup, test, wasm]
-    runs-on: ubuntu-latest
-    if: github.ref == 'refs/heads/master'
-    steps:
-    - name: Checkout current repository
-      uses: actions/checkout@v3
-    - name: Update Package Lists
-      run: sudo apt-get update
-    - name: Install Dependencies
-      run: sudo apt-get install doxygen graphviz texlive --fix-missing
-    - name: Checkout doxygen-awesome
-      run: git clone https://github.com/jothepro/doxygen-awesome-css.git doxygen-awesome-css
-    - name: Generate Documentation
-      run: |
-        mkdir -p docs/core
-        doxygen Doxyfile
-        echo "Listing contents of docs/core:"
-        ls -R docs/core || echo "No files found in docs/core"
-    - name: Upload Doxygen Documentation as Artifact
-      uses: actions/upload-artifact@v4
-      with:
-        name: doxygen-docs-core
-        path: docs/core
diff --git a/.github/workflows/handle_build.yml b/.github/workflows/handle_build.yml
new file mode 100644
index 0000000000..89df2b76b7
--- /dev/null
+++ b/.github/workflows/handle_build.yml
@@ -0,0 +1,183 @@
+name: Handle Build
+
+on:
+  push:
+    branches: [ "handle" ]
+  pull_request:
+    branches: [ "handle" ]
+  workflow_dispatch: # manual trigger
+
+jobs:
+  setup:
+    runs-on: ubuntu-latest
+    outputs:
+      vortex_version_major: ${{ steps.set_version.outputs.vortex_version_major }}
+      vortex_version_minor: ${{ steps.set_version.outputs.vortex_version_minor }}
+      vortex_build_number: ${{ steps.set_version.outputs.vortex_build_number }}
+      vortex_version_number: ${{ steps.set_version.outputs.vortex_version_number }}
+    steps:
+      - uses: actions/checkout@v4
+        with:
+          fetch-depth: 0 # Fetches all history for all branches and tags
+      - name: Determine Version and Build Number
+        id: set_version
+        run: |
+          BRANCH_SUFFIX="h"
+          # Fetch all tags
+          git fetch --depth=1 origin +refs/tags/*:refs/tags/*
+          # Get the latest tag that matches the branch suffix
+          LATEST_TAG=$(git tag --list "*${BRANCH_SUFFIX}" | sort -V | tail -n1)
+          if [ -z "$LATEST_TAG" ]; then
+            echo "No matching tags found. Setting default version."
+            VERSION_MAJOR="0"
+            VERSION_MINOR="1"
+            BUILD_NUMBER="0"
+          else
+            echo "Found latest tag: $LATEST_TAG"
+            VERSION_NUMBER=$(echo $LATEST_TAG | sed "s/${BRANCH_SUFFIX}//g")
+            VERSION_MAJOR=$(echo $VERSION_NUMBER | cut -d. -f1)
+            VERSION_MINOR=$(echo $VERSION_NUMBER | cut -d. -f2)
+            BUILD_NUMBER=$(git rev-list --count $LATEST_TAG..HEAD)
+          fi
+          FULL_VERSION="$VERSION_MAJOR.$VERSION_MINOR.$BUILD_NUMBER"
+          echo "vortex_version_major=$VERSION_MAJOR" >> $GITHUB_OUTPUT
+          echo "vortex_version_minor=$VERSION_MINOR" >> $GITHUB_OUTPUT
+          echo "vortex_build_number=$BUILD_NUMBER" >> $GITHUB_OUTPUT
+          echo "vortex_version_number=$FULL_VERSION" >> $GITHUB_OUTPUT
+          echo "Version Number: $FULL_VERSION"
+
+  test:
+    needs: setup
+    runs-on: ubuntu-latest
+    steps:
+      - name: Checkout current repository
+        uses: actions/checkout@v4
+      - name: Update Package Lists
+        run: sudo apt-get update
+      - name: Install Dependencies
+        run: sudo apt-get install valgrind g++ make --fix-missing
+      - name: Build
+        run: |
+          export VORTEX_VERSION_MAJOR=${{ needs.setup.outputs.vortex_version_major }}
+          export VORTEX_VERSION_MINOR=${{ needs.setup.outputs.vortex_version_minor }}
+          export VORTEX_BUILD_NUMBER=${{ needs.setup.outputs.vortex_build_number }}
+          export VORTEX_VERSION_NUMBER=${{ needs.setup.outputs.vortex_version_number }}
+          make -j
+        working-directory: VortexEngine
+      - name: Set execute permissions for test script
+        run: chmod +x ./runtests.sh
+        working-directory: VortexEngine/tests
+      - name: Run general tests
+        run: ./runtests.sh --general
+        working-directory: VortexEngine/tests
+
+  embedded:
+    needs: [setup, test]
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v4
+      - name: Set up Python
+        uses: actions/setup-python@v5
+        with:
+          python-version: '3.x'
+      - name: Install Dependencies
+        run: make install
+      - name: Build Binary
+        run: |
+          export VORTEX_VERSION_MAJOR=${{ needs.setup.outputs.vortex_version_major }}
+          export VORTEX_VERSION_MINOR=${{ needs.setup.outputs.vortex_version_minor }}
+          export VORTEX_BUILD_NUMBER=${{ needs.setup.outputs.vortex_build_number }}
+          export VORTEX_VERSION_NUMBER=${{ needs.setup.outputs.vortex_version_number }}
+          make build
+      - name: Archive production artifacts
+        uses: actions/upload-artifact@v4
+        with:
+          name: embedded firmware
+          path: |
+            build/VortexEngine.ino.bin
+            build/VortexEngine.ino.elf
+            build/VortexEngine.ino.map
+            build/VortexEngine.ino.hex
+            build/VortexEngine.ino.uf2
+      - name: Archive production artifacts for deployment
+        uses: actions/upload-artifact@v4
+        with:
+          name: firmware-artifact
+          path: build/VortexEngine.ino.uf2
+
+  wasm:
+    needs: [setup, test, embedded]
+    runs-on: ubuntu-latest
+    steps:
+      - name: Checkout current repository
+        uses: actions/checkout@v4
+      - name: Update Package Lists
+        run: sudo apt-get update
+      - name: Install Emscripten
+        run: |
+          sudo apt install -y cmake python3
+          git clone https://github.com/emscripten-core/emsdk.git
+          cd emsdk
+          ./emsdk install latest
+          ./emsdk activate latest
+        working-directory: VortexEngine/VortexLib
+      - name: Build Webassembly
+        run: |
+          source ./emsdk/emsdk_env.sh
+          export VORTEX_VERSION_MAJOR=${{ needs.setup.outputs.vortex_version_major }}
+          export VORTEX_VERSION_MINOR=${{ needs.setup.outputs.vortex_version_minor }}
+          export VORTEX_BUILD_NUMBER=${{ needs.setup.outputs.vortex_build_number }}
+          export VORTEX_VERSION_NUMBER=${{ needs.setup.outputs.vortex_version_number }}
+          make -j wasm
+        working-directory: VortexEngine/VortexLib
+
+  docs:
+    needs: [setup, test, embedded, wasm]
+    runs-on: ubuntu-latest
+    if: github.ref == 'refs/heads/handle'
+    steps:
+      - name: Checkout current repository
+        uses: actions/checkout@v4
+      - name: Update Package Lists
+        run: sudo apt-get update
+      - name: Install Dependencies
+        run: sudo apt-get install doxygen graphviz texlive --fix-missing
+      - name: Checkout doxygen-awesome
+        run: git clone https://github.com/jothepro/doxygen-awesome-css.git doxygen-awesome-css
+      - name: Generate Documentation
+        run: |
+          mkdir -p docs/handle
+          doxygen Doxyfile
+          echo "Listing contents of docs/handle:"
+          ls -R docs/handle || echo "No files found in docs/handle"
+      - name: Upload Doxygen Documentation as Artifact
+        uses: actions/upload-artifact@v4
+        with:
+          name: doxygen-docs-handle
+          path: docs/handle
+
+  deploy:
+    needs: [setup, test, embedded, wasm, docs]
+    runs-on: ubuntu-latest
+    if: github.ref == 'refs/heads/handle'
+    steps:
+      - uses: actions/checkout@v4
+      - uses: actions/download-artifact@v4
+        with:
+          name: firmware-artifact
+          path: build
+      - name: Rename and Deploy Firmware
+        run: |
+          DEVICE_TYPE="handle"
+          VERSIONED_FILENAME="VortexEngine-${DEVICE_TYPE}-${{ needs.setup.outputs.vortex_version_number }}.uf2"
+          mv build/VortexEngine.ino.uf2 build/$VERSIONED_FILENAME
+          echo "Version is ${{ needs.setup.outputs.vortex_version_number }}"
+          echo "Filename is is $VERSIONED_FILENAME"
+          curl -X POST \
+            -F "file=@build/$VERSIONED_FILENAME" \
+            -F "device=$DEVICE_TYPE" \
+            -F "version=${{ needs.setup.outputs.vortex_version_number }}" \
+            -F "category=firmware" \
+            -F "clientApiKey=${{ secrets.VORTEX_COMMUNITY_API_KEY }}" \
+            https://vortex.community/firmware/upload
+
diff --git a/Doxyfile b/Doxyfile
index 9db6ecc800..0a6fc800b5 100644
--- a/Doxyfile
+++ b/Doxyfile
@@ -32,7 +32,7 @@ DOXYFILE_ENCODING      = UTF-8
 # title of most generated pages and in a few other places.
 # The default value is: My Project.
 
-PROJECT_NAME           = "Vortex Engine"
+PROJECT_NAME           = "Vortex Handle"
 
 # The PROJECT_NUMBER tag can be used to enter a project or revision number. This
 # could be handy for archiving the generated documentation or if some version
@@ -58,7 +58,7 @@ PROJECT_LOGO           =
 # entered, it will be relative to the location where doxygen was started. If
 # left blank the current directory will be used.
 
-OUTPUT_DIRECTORY       = docs/core
+OUTPUT_DIRECTORY       = docs/handle
 
 # If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
 # directories (in 2 levels) under the output directory of each output format and
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000000..c9a16662ae
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,70 @@
+.PHONY: all install build upload clean compute_version
+
+ARDUINO_CLI = ./bin/arduino-cli --verbose
+BOARD = adafruit:samd:adafruit_trinket_m0
+PORT = /dev/ttyACM0
+PROJECT_NAME = VortexEngine/VortexEngine.ino
+BUILD_PATH = build
+CONFIG_FILE = $(HOME)/.arduino15/arduino-cli.yaml
+
+# The branch/tag suffix for this device
+BRANCH_SUFFIX=h
+
+DEFINES=\
+	-D VORTEX_VERSION_MAJOR=$(VORTEX_VERSION_MAJOR) \
+	-D VORTEX_VERSION_MINOR=$(VORTEX_VERSION_MINOR) \
+	-D VORTEX_BUILD_NUMBER=$(VORTEX_BUILD_NUMBER) \
+	-D VORTEX_VERSION_NUMBER=$(VORTEX_VERSION_NUMBER)
+
+# Default target
+all: build
+
+update-index:
+	$(ARDUINO_CLI) core update-index
+
+install:
+	sudo apt-get update
+	sudo apt-get install -y build-essential
+	mkdir -p $(HOME)/.arduino15
+	if ! command -v $(ARDUINO_CLI) &> /dev/null ; then \
+		curl -fsSL https://raw.githubusercontent.com/arduino/arduino-cli/master/install.sh | sudo sh ; \
+	fi
+	echo 'board_manager: \n  additional_urls: \n    - https://adafruit.github.io/arduino-board-index/package_adafruit_index.json' | sudo tee $(CONFIG_FILE)
+	$(ARDUINO_CLI) core update-index --config-file $(CONFIG_FILE)
+	if ! $(ARDUINO_CLI) core list --config-file $(CONFIG_FILE) | grep -q '$(BOARD)' ; then \
+		$(ARDUINO_CLI) core install adafruit:samd --config-file $(CONFIG_FILE) ; \
+	fi
+	wget https://raw.githubusercontent.com/microsoft/uf2/master/utils/uf2conv.py
+	wget https://raw.githubusercontent.com/microsoft/uf2/master/utils/uf2families.json
+	chmod +x uf2conv.py uf2families.json
+	chmod +x rewrite_trinket_source.sh
+	./rewrite_trinket_source.sh
+
+build: compute_version
+	$(ARDUINO_CLI) compile --fqbn $(BOARD) $(PROJECT_NAME) \
+		--config-file $(CONFIG_FILE) \
+		--build-path $(BUILD_PATH) \
+		--build-property compiler.cpp.extra_flags="$(DEFINES)" \
+		--build-property compiler.c.extra_flags="$(DEFINES)"
+	python3 uf2conv.py -c -b 0x2000 build/VortexEngine.ino.bin -o build/VortexEngine.ino.uf2
+	@echo "== Success building Handle v$(VORTEX_VERSION_NUMBER) =="
+
+upload:
+	$(ARDUINO_CLI) upload -p $(PORT) --fqbn $(BOARD) $(PROJECT_NAME) --config-file $(CONFIG_FILE)
+
+core-list:
+	$(ARDUINO_CLI) core list
+
+clean:
+	rm -rf $(BUILD_PATH)
+
+# calculate the version number of the build
+compute_version:
+	$(eval LATEST_TAG ?= $(shell git fetch --depth=1 origin +refs/tags/*:refs/tags/* &> /dev/null && git tag --list "*$(BRANCH_SUFFIX)" | sort -V | tail -n1))
+	$(eval VORTEX_VERSION_MAJOR ?= $(shell echo $(LATEST_TAG) | cut -d. -f1))
+	$(eval VORTEX_VERSION_MINOR ?= $(shell echo $(LATEST_TAG) | sed 's/$(BRANCH_SUFFIX)$$//' | cut -d. -f2))
+	$(eval VORTEX_BUILD_NUMBER ?= $(shell git rev-list --count $(LATEST_TAG)..HEAD))
+	$(eval VORTEX_VERSION_MAJOR := $(if $(VORTEX_VERSION_MAJOR),$(VORTEX_VERSION_MAJOR),0))
+	$(eval VORTEX_VERSION_MINOR := $(if $(VORTEX_VERSION_MINOR),$(VORTEX_VERSION_MINOR),1))
+	$(eval VORTEX_BUILD_NUMBER := $(if $(VORTEX_BUILD_NUMBER),$(VORTEX_BUILD_NUMBER),0))
+	$(eval VORTEX_VERSION_NUMBER := $(VORTEX_VERSION_MAJOR).$(VORTEX_VERSION_MINOR).$(VORTEX_BUILD_NUMBER))
diff --git a/VortexEngine/VortexCLI/Makefile b/VortexEngine/VortexCLI/Makefile
index b4b2f2b541..71af9945fb 100644
--- a/VortexEngine/VortexCLI/Makefile
+++ b/VortexEngine/VortexCLI/Makefile
@@ -19,6 +19,9 @@ RANLIB=ranlib
 
 CFLAGS=-O2 -g -Wall
 
+# The branch/tag suffix for this device
+BRANCH_SUFFIX=h
+
 # compiler defines
 DEFINES=\
 	-D VORTEX_LIB \
@@ -135,9 +138,9 @@ clean:
 
 # calculate the version number of the build
 compute_version:
-	$(eval LATEST_TAG ?= $(shell git fetch --depth=1 origin +refs/tags/*:refs/tags/* &> /dev/null && git tag --list | grep --invert-match '[a-zA-Z]' | sort -V | tail -n1))
+	$(eval LATEST_TAG ?= $(shell git fetch --depth=1 origin +refs/tags/*:refs/tags/* &> /dev/null && git tag --list "*$(BRANCH_SUFFIX)" | sort -V | tail -n1))
 	$(eval VORTEX_VERSION_MAJOR ?= $(shell echo $(LATEST_TAG) | cut -d. -f1))
-	$(eval VORTEX_VERSION_MINOR ?= $(shell echo $(LATEST_TAG) | cut -d. -f2))
+	$(eval VORTEX_VERSION_MINOR ?= $(shell echo $(LATEST_TAG) | sed 's/$(BRANCH_SUFFIX)$$//' | cut -d. -f2))
 	$(eval VORTEX_BUILD_NUMBER ?= $(shell git rev-list --count $(LATEST_TAG)..HEAD))
 	$(eval VORTEX_VERSION_MAJOR := $(if $(VORTEX_VERSION_MAJOR),$(VORTEX_VERSION_MAJOR),0))
 	$(eval VORTEX_VERSION_MINOR := $(if $(VORTEX_VERSION_MINOR),$(VORTEX_VERSION_MINOR),1))
diff --git a/VortexEngine/VortexEngine.ino b/VortexEngine/VortexEngine.ino
new file mode 100644
index 0000000000..014b37a8af
--- /dev/null
+++ b/VortexEngine/VortexEngine.ino
@@ -0,0 +1,15 @@
+#include <Arduino.h>
+
+#include "src/VortexEngine.h"
+
+void setup()
+{
+  if (!VortexEngine::init()) {
+    // uhoh
+  }
+}
+
+void loop()
+{
+  VortexEngine::tick();
+}
diff --git a/VortexEngine/VortexLib/Makefile b/VortexEngine/VortexLib/Makefile
index 98900f08b8..b3923ddeee 100644
--- a/VortexEngine/VortexLib/Makefile
+++ b/VortexEngine/VortexLib/Makefile
@@ -24,6 +24,9 @@ ifndef WASM
 CFLAGS += -g
 endif
 
+# The branch/tag suffix for this device
+BRANCH_SUFFIX=h
+
 # compiler defines
 DEFINES=\
 	-D VORTEX_LIB \
@@ -146,9 +149,9 @@ clean:
 
 # calculate the version number of the build
 compute_version:
-	$(eval LATEST_TAG ?= $(shell git fetch --depth=1 origin +refs/tags/*:refs/tags/* &> /dev/null && git tag --list | grep --invert-match '[a-zA-Z]' | sort -V | tail -n1))
+	$(eval LATEST_TAG ?= $(shell git fetch --depth=1 origin +refs/tags/*:refs/tags/* &> /dev/null && git tag --list "*$(BRANCH_SUFFIX)" | sort -V | tail -n1))
 	$(eval VORTEX_VERSION_MAJOR ?= $(shell echo $(LATEST_TAG) | cut -d. -f1))
-	$(eval VORTEX_VERSION_MINOR ?= $(shell echo $(LATEST_TAG) | cut -d. -f2))
+	$(eval VORTEX_VERSION_MINOR ?= $(shell echo $(LATEST_TAG) | sed 's/$(BRANCH_SUFFIX)$$//' | cut -d. -f2))
 	$(eval VORTEX_BUILD_NUMBER ?= $(shell git rev-list --count $(LATEST_TAG)..HEAD))
 	$(eval VORTEX_VERSION_MAJOR := $(if $(VORTEX_VERSION_MAJOR),$(VORTEX_VERSION_MAJOR),0))
 	$(eval VORTEX_VERSION_MINOR := $(if $(VORTEX_VERSION_MINOR),$(VORTEX_VERSION_MINOR),1))
diff --git a/VortexEngine/VortexLib/VortexLib.cpp b/VortexEngine/VortexLib/VortexLib.cpp
index 09e5e61c77..71c20f972f 100644
--- a/VortexEngine/VortexLib/VortexLib.cpp
+++ b/VortexEngine/VortexLib/VortexLib.cpp
@@ -212,13 +212,6 @@ EMSCRIPTEN_BINDINGS(Vortex) {
     .value("LED_0", LedPos::LED_0)
     .value("LED_1", LedPos::LED_1)
     .value("LED_2", LedPos::LED_2)
-    .value("LED_3", LedPos::LED_3)
-    .value("LED_4", LedPos::LED_4)
-    .value("LED_5", LedPos::LED_5)
-    .value("LED_6", LedPos::LED_6)
-    .value("LED_7", LedPos::LED_7)
-    .value("LED_8", LedPos::LED_8)
-    .value("LED_9", LedPos::LED_9)
     .value("LED_COUNT", LedPos::LED_COUNT)
     .value("LED_LAST", LedPos::LED_LAST)
     .value("LED_ALL", LedPos::LED_ALL)
diff --git a/VortexEngine/appmain.cpp b/VortexEngine/appmain.cpp
deleted file mode 100644
index a80363ed5b..0000000000
--- a/VortexEngine/appmain.cpp
+++ /dev/null
@@ -1,10 +0,0 @@
-#include "src/VortexEngine.h"
-
-int main()
-{
-  VortexEngine::init();
-  for (;;) {
-    VortexEngine::tick();
-  }
-  return 0;
-}
diff --git a/VortexEngine/src/Buttons/Button.cpp b/VortexEngine/src/Buttons/Button.cpp
index e565dbbb5c..51466ff02d 100644
--- a/VortexEngine/src/Buttons/Button.cpp
+++ b/VortexEngine/src/Buttons/Button.cpp
@@ -8,6 +8,10 @@
 #include "VortexLib.h"
 #endif
 
+#ifdef VORTEX_EMBEDDED
+#include <Arduino.h>
+#endif
+
 Button::Button() :
   m_pinNum(0),
   m_pressTime(0),
@@ -46,12 +50,19 @@ bool Button::init(uint8_t pin)
   m_longClick = false;
 
   m_pinNum = pin;
+#ifdef VORTEX_EMBEDDED
+  pinMode(m_pinNum, INPUT_PULLUP);
+#endif
   return true;
 }
 
 bool Button::check()
 {
+#ifdef VORTEX_EMBEDDED
+  return (digitalRead(m_pinNum) == 0);
+#else
   return (Vortex::vcallbacks()->checkPinHook(m_pinNum) == 0);
+#endif
 }
 
 void Button::update()
diff --git a/VortexEngine/src/Leds/LedTypes.h b/VortexEngine/src/Leds/LedTypes.h
index 6fa687a0f2..b1f6760f19 100644
--- a/VortexEngine/src/Leds/LedTypes.h
+++ b/VortexEngine/src/Leds/LedTypes.h
@@ -16,13 +16,6 @@ enum LedPos : uint8_t
   LED_0 = LED_FIRST,
   LED_1,
   LED_2,
-  LED_3,
-  LED_4,
-  LED_5,
-  LED_6,
-  LED_7,
-  LED_8,
-  LED_9,
 
   // the number of entries above
   LED_COUNT,
@@ -63,6 +56,10 @@ enum LedPos : uint8_t
   // LED_ODDS = (LED_COUNT + 3),
 };
 
+// some helpers for microlight code
+#define LED_TIP LED_0
+#define LED_TOP LED_1
+
 enum Pair : uint8_t
 {
   PAIR_FIRST = 0,
@@ -70,16 +67,26 @@ enum Pair : uint8_t
   // one pair for each pair of leds, adjust this to be 2x the LED_COUNT
   PAIR_0 = PAIR_FIRST,
   PAIR_1,
-  PAIR_2,
-  PAIR_3,
-  PAIR_4,
 
   PAIR_COUNT,
   PAIR_LAST = (PAIR_COUNT - 1),
 };
 
 // Compile-time check on the number of pairs and leds
-static_assert(LED_COUNT == (PAIR_COUNT * 2), "Incorrect number of Pairs for Leds! Adjust the Led enum or Pair enum to match");
+// The handle only has 3 leds so the pair check is a little offset
+static_assert(LED_COUNT == ((PAIR_COUNT * 2) - 1), "Incorrect number of Pairs for Leds! Adjust the Led enum or Pair enum to match");
+
+// backwards compatibility for multi led patterns
+#define LED_3 LED_0
+#define LED_4 LED_1
+#define LED_5 LED_2
+#define LED_6 LED_0
+#define LED_7 LED_1
+#define LED_8 LED_2
+#define LED_9 LED_0
+#define PAIR_2 PAIR_0
+#define PAIR_3 PAIR_1
+#define PAIR_4 PAIR_0
 
 // check if an led is even or odd
 #define isEven(pos) ((pos % 2) == 0)
@@ -159,6 +166,9 @@ inline LedPos ledmapGetNextLed(LedMap map, LedPos pos)
 #define MAP_PAIR_EVEN_EVENS (MAP_PAIR_EVEN(PAIR_3) | MAP_PAIR_EVEN(PAIR_1))
 #define MAP_PAIR_EVEN_ODDS (MAP_PAIR_ODD(PAIR_3) | MAP_PAIR_ODD(PAIR_1))
 
+// ledmap of the side leds
+#define MAP_SIDES (MAP_LED(LED_0) | MAP_LED(LED_2))
+
 // set a single led
 inline void ledmapSetLed(LedMap &map, LedPos pos)
 {
diff --git a/VortexEngine/src/Leds/Leds.cpp b/VortexEngine/src/Leds/Leds.cpp
index 0d1dd4c400..ab558e76f0 100644
--- a/VortexEngine/src/Leds/Leds.cpp
+++ b/VortexEngine/src/Leds/Leds.cpp
@@ -12,6 +12,49 @@
 #include "../../VortexLib/VortexLib.h"
 #endif
 
+#ifdef VORTEX_EMBEDDED
+#include <SPI.h>
+#define ONBOARD_LED_SCK 8
+#define ONBOARD_LED_MOSI 7
+static void transfer(uint8_t byte)
+{
+  uint8_t startbit = 0x80;
+  bool lastmosi = !(byte & startbit);
+  for (uint8_t b = startbit; b != 0; b = b >> 1) {
+    delayMicroseconds(4);
+    bool towrite = byte & b;
+    if (lastmosi != towrite) {
+      digitalWrite(ONBOARD_LED_MOSI, towrite);
+      lastmosi = towrite;
+    }
+    digitalWrite(ONBOARD_LED_SCK, HIGH);
+    delayMicroseconds(4);
+    digitalWrite(ONBOARD_LED_SCK, LOW);
+  }
+}
+static void turnOffOnboardLED()
+{
+  // spi device begin
+  pinMode(ONBOARD_LED_SCK, OUTPUT);
+  digitalWrite(ONBOARD_LED_SCK, LOW);
+  pinMode(ONBOARD_LED_MOSI, OUTPUT);
+  digitalWrite(ONBOARD_LED_MOSI, HIGH);
+
+  // Begin transaction, setting SPI frequency
+  static const SPISettings mySPISettings(8000000, MSBFIRST, SPI_MODE0);
+  SPI.beginTransaction(mySPISettings);
+  for (uint8_t i = 0; i < 4; i++) {
+    transfer(0x00); // begin frame
+  }
+  transfer(0xFF); //  Pixel start
+  for (uint8_t i = 0; i < 3; i++) {
+    transfer(0x00); // R,G,B
+  }
+  transfer(0xFF); // end frame
+  SPI.endTransaction();
+}
+#endif
+
 // global brightness
 uint8_t Leds::m_brightness = DEFAULT_BRIGHTNESS;
 // array of led color values
@@ -19,6 +62,10 @@ RGBColor Leds::m_ledColors[LED_COUNT] = { RGB_OFF };
 
 bool Leds::init()
 {
+#ifdef VORTEX_EMBEDDED
+  turnOffOnboardLED();
+  SPI.begin();
+#endif
 #ifdef VORTEX_LIB
   Vortex::vcallbacks()->ledsInit(m_ledColors, LED_COUNT);
 #endif
@@ -27,6 +74,9 @@ bool Leds::init()
 
 void Leds::cleanup()
 {
+#ifdef VORTEX_EMBEDDED
+  SPI.end();
+#endif
   for (uint8_t i = 0; i < LED_COUNT; ++i) {
     m_ledColors[i].clear();
   }
@@ -260,6 +310,27 @@ void Leds::holdAll(RGBColor col)
 
 void Leds::update()
 {
+#ifdef VORTEX_EMBEDDED
+  // the transaction prevents this from interfering with other communications
+  // on the pins that are used for SPI, for example IR is on pin 2
+  static const SPISettings mySPISettings(12000000, MSBFIRST, SPI_MODE0);
+  SPI.beginTransaction(mySPISettings);
+  // Double start frame, normally 4, idk why it's double
+  for (uint8_t i = 0; i < 8; i++) {
+    SPI.transfer(0);
+  }
+  // Adjust brightness to 5 bits
+  uint8_t adjustedBrightness = 0b11100000 | ((m_brightness >> 3) & 0b00011111);
+  // LED frames
+  for (LedPos pos = LED_FIRST; pos < LED_COUNT; pos++) {
+    SPI.transfer(adjustedBrightness);     // brightness
+    SPI.transfer(m_ledColors[pos].blue);  // blue
+    SPI.transfer(m_ledColors[pos].green); // green
+    SPI.transfer(m_ledColors[pos].red);   // red
+  }
+  // don't need to end the SPI frame apparently, just end transaction
+  SPI.endTransaction();
+#endif
 #ifdef VORTEX_LIB
   Vortex::vcallbacks()->ledsShow();
 #endif
diff --git a/VortexEngine/src/Log/Log.cpp b/VortexEngine/src/Log/Log.cpp
index 19877548da..c79ff42b06 100644
--- a/VortexEngine/src/Log/Log.cpp
+++ b/VortexEngine/src/Log/Log.cpp
@@ -11,12 +11,27 @@
 #include "VortexLib.h"
 #endif
 
+#ifdef VORTEX_EMBEDDED
+#include <Arduino.h>
+#endif
+
 #if LOGGING_LEVEL > 0
 void InfoMsg(const char *msg, ...)
 {
+#ifdef VORTEX_EMBEDDED
+  if (!SerialComs::isConnected()) {
+    return;
+  }
+#endif
   va_list list;
   va_start(list, msg);
+#ifdef VORTEX_EMBEDDED
+  char buf[2048] = {0};
+  vsnprintf(buf, sizeof(buf), msg, list);
+  Serial.println(buf);
+#else
   Vortex::printlog(NULL, NULL, 0, msg, list);
+#endif
   va_end(list);
 }
 #endif
@@ -24,9 +39,22 @@ void InfoMsg(const char *msg, ...)
 #if LOGGING_LEVEL > 1
 void ErrorMsg(const char *func, const char *msg, ...)
 {
+#ifdef VORTEX_EMBEDDED
+  if (!SerialComs::isConnected()) {
+    return;
+  }
+#endif
   va_list list;
   va_start(list, msg);
+#ifdef VORTEX_EMBEDDED
+  char fmt[2048] = {0};
+  snprintf(fmt, sizeof(fmt), "%s(): %s", func, msg);
+  char buf[2048] = {0};
+  vsnprintf(buf, sizeof(buf), fmt, list);
+  Serial.println(buf);
+#else
   Vortex::printlog(NULL, func, 0, msg, list);
+#endif
   va_end(list);
 }
 #endif
@@ -34,6 +62,11 @@ void ErrorMsg(const char *func, const char *msg, ...)
 #if LOGGING_LEVEL > 2
 void DebugMsg(const char *file, const char *func, int line, const char *msg, ...)
 {
+#ifdef VORTEX_EMBEDDED
+  if (!SerialComs::isConnected()) {
+    return;
+  }
+#endif
   va_list list;
   va_start(list, msg);
   const char *ptr = file + strlen(file);
@@ -46,7 +79,15 @@ void DebugMsg(const char *file, const char *func, int line, const char *msg, ...
     }
     ptr--;
   }
+#ifdef VORTEX_EMBEDDED
+  char fmt[2048] = {0};
+  snprintf(fmt, sizeof(fmt), "%s:%d %s(): %s", file, line, func, msg);
+  char buf[2048] = {0};
+  vsnprintf(buf, sizeof(buf), fmt, list);
+  Serial.println(buf);
+#else
   Vortex::printlog(file, func, line, msg, list);
+#endif
   va_end(list);
 }
 #endif
diff --git a/VortexEngine/src/Menus/Menu.cpp b/VortexEngine/src/Menus/Menu.cpp
index 007e48f408..a760a65683 100644
--- a/VortexEngine/src/Menus/Menu.cpp
+++ b/VortexEngine/src/Menus/Menu.cpp
@@ -131,28 +131,16 @@ void Menu::nextBulbSelection()
       // do not allow multi led to select anything else
       //break;
     }
+    m_targetLeds = MAP_SIDES;
+    break;
+  case MAP_SIDES:
     m_targetLeds = MAP_LED(LED_FIRST);
     break;
   case MAP_LED(LED_LAST):
-    m_targetLeds = MAP_PAIR_EVENS;
-    break;
-  case MAP_PAIR_EVENS:
-    m_targetLeds = MAP_PAIR_ODDS;
-    break;
-  case MAP_PAIR_ODDS:
-    m_targetLeds = MAP_LED(LED_MULTI);
-    break;
-  case MAP_LED(LED_MULTI):
     m_targetLeds = MAP_LED_ALL;
     break;
   default: // LED_FIRST through LED_LAST
-    // do not allow multi led to select anything else
-    if (cur->isMultiLed()) {
-      //m_targetLeds = MAP_LED_ALL;
-      //break;
-    }
-    // iterate as normal
-    m_targetLeds = MAP_LED(((ledmapGetFirstLed(m_targetLeds) + 1) % (LED_COUNT + 1)));
+    m_targetLeds = MAP_LED((ledmapGetFirstLed(m_targetLeds) + 1) % (LED_COUNT));
     break;
   }
 }
diff --git a/VortexEngine/src/Menus/MenuList/ColorSelect.cpp b/VortexEngine/src/Menus/MenuList/ColorSelect.cpp
index 7cab9abd3a..6591c0af19 100644
--- a/VortexEngine/src/Menus/MenuList/ColorSelect.cpp
+++ b/VortexEngine/src/Menus/MenuList/ColorSelect.cpp
@@ -233,7 +233,6 @@ void ColorSelect::showSelection(ColorSelectState mode)
     return;
   case STATE_PICK_HUE2:
     hue = m_targetHue1 * (255 / 4) + (m_curSelection * (255 / 16));
-    Leds::setIndex(LED_1, RGB_WHITE0);
     // force sat at hue level2
     sat = 255;
     break;
@@ -244,7 +243,7 @@ void ColorSelect::showSelection(ColorSelectState mode)
     val = vals[m_curSelection];
     break;
   }
-  Leds::setMap(MAP_PAIR_EVENS, HSVColor(hue, sat, val));
+  Leds::setAll(HSVColor(hue, sat, val));
 }
 
 void ColorSelect::showFullSet(uint8_t offMs, uint8_t onMs)
@@ -258,6 +257,7 @@ void ColorSelect::showFullSet(uint8_t offMs, uint8_t onMs)
   if ((now % offOnMs) < MS_TO_TICKS(onMs)) {
     Leds::setAll(m_colorset.get((now / offOnMs) % numCols));
   }
+  Leds::setIndex(LED_1, 0x001000);
 }
 
 bool ColorSelect::isValidLedSelection(LedMap selection) const
diff --git a/VortexEngine/src/Menus/MenuList/EditorConnection.cpp b/VortexEngine/src/Menus/MenuList/EditorConnection.cpp
index 09f882be27..cef14bacf8 100644
--- a/VortexEngine/src/Menus/MenuList/EditorConnection.cpp
+++ b/VortexEngine/src/Menus/MenuList/EditorConnection.cpp
@@ -172,7 +172,7 @@ void EditorConnection::handleState()
     // parse the receive buffer for any commands from the editor
     handleCommand();
     // watch for disconnects
-    if (!SerialComs::isConnected()) {
+    if (!SerialComs::isConnectedReal()) {
       Leds::holdAll(RGB_RED);
       leaveMenu(true);
     }
diff --git a/VortexEngine/src/Menus/MenuList/ModeSharing.cpp b/VortexEngine/src/Menus/MenuList/ModeSharing.cpp
index e3391c1df2..6df36dbcd2 100644
--- a/VortexEngine/src/Menus/MenuList/ModeSharing.cpp
+++ b/VortexEngine/src/Menus/MenuList/ModeSharing.cpp
@@ -16,7 +16,9 @@
 ModeSharing::ModeSharing(const RGBColor &col, bool advanced) :
   Menu(col, advanced),
   m_sharingMode(ModeShareState::SHARE_RECEIVE),
-  m_timeOutStartTime(0)
+  m_timeOutStartTime(0),
+  m_lastSendTime(0),
+  m_shouldEndSend(false)
 {
 }
 
@@ -78,6 +80,14 @@ void ModeSharing::onShortClick()
     beginSendingIR();
     DEBUG_LOG("Switched to send mode");
     break;
+  case ModeShareState::SHARE_SEND_IR:
+    if (!IRSender::isSending()) {
+      beginReceivingIR();
+      DEBUG_LOG("Switched to send mode");
+    } else {
+      m_shouldEndSend = true;
+    }
+    break;
   default:
     break;
   }
@@ -115,12 +125,14 @@ void ModeSharing::beginSendingIR()
     return;
   }
   m_sharingMode = ModeShareState::SHARE_SEND_IR;
+  Leds::clearAll();
+  Leds::update();
   // initialize it with the current mode data
   IRSender::loadMode(Modes::curMode());
   // send the first chunk of data, leave if we're done
   if (!IRSender::send()) {
-    // when send has completed, stores time that last action was completed to calculate interval between sends
-    beginReceivingIR();
+    // just set the last time and wait
+    m_lastSendTime = Time::getCurtime();
   }
 }
 
@@ -140,11 +152,19 @@ void ModeSharing::continueSendingIR()
 {
   // if the sender isn't sending then nothing to do
   if (!IRSender::isSending()) {
+    if (m_lastSendTime && m_lastSendTime < (Time::getCurtime() + MS_TO_TICKS(350))) {
+      if (m_shouldEndSend) {
+        beginReceivingIR();
+        m_shouldEndSend = false;
+      } else {
+        beginSendingIR();
+      }
+    }
     return;
   }
   if (!IRSender::send()) {
-    // when send has completed, stores time that last action was completed to calculate interval between sends
-    beginReceivingIR();
+    // just set the last time and wait
+    m_lastSendTime = Time::getCurtime();
   }
 }
 
@@ -193,7 +213,8 @@ void ModeSharing::showSendModeVL()
 void ModeSharing::showSendModeIR()
 {
   // show a dim color when not sending
-  Leds::clearAll();
+  Leds::setIndex(LED_1, RGB_CYAN1);
+  Leds::setIndex(LED_2, RGB_CYAN1);
 }
 
 void ModeSharing::showReceiveMode()
diff --git a/VortexEngine/src/Menus/MenuList/ModeSharing.h b/VortexEngine/src/Menus/MenuList/ModeSharing.h
index dc5adf2357..df2d0fe6c1 100644
--- a/VortexEngine/src/Menus/MenuList/ModeSharing.h
+++ b/VortexEngine/src/Menus/MenuList/ModeSharing.h
@@ -38,6 +38,10 @@ class ModeSharing : public Menu
 
   // the start time when checking for timing out
   uint32_t m_timeOutStartTime;
+  uint32_t m_lastSendTime;
+
+  // whether to end the next send and go back to receive
+  bool m_shouldEndSend;
 };
 
 #endif
diff --git a/VortexEngine/src/Modes/DefaultModes.cpp b/VortexEngine/src/Modes/DefaultModes.cpp
index a0f4be8b7c..08cd08439e 100644
--- a/VortexEngine/src/Modes/DefaultModes.cpp
+++ b/VortexEngine/src/Modes/DefaultModes.cpp
@@ -6,7 +6,14 @@
 // the gloveset upon factory reset
 const default_mode_entry default_modes[MAX_MODES] = {
   {
-    PATTERN_DOPS, 5, {
+    PATTERN_VORTEX, MAP_LED_ALL, 5, {
+      RGB_RED,
+      RGB_GREEN,
+      RGB_BLUE,
+      0xABAA00,
+      0x5500AB
+    },
+    PATTERN_VORTEX, MAP_LED_NONE, 5, {
       RGB_RED,
       RGB_GREEN,
       RGB_BLUE,
@@ -14,41 +21,176 @@ const default_mode_entry default_modes[MAX_MODES] = {
       0x5500AB
     }
   },
+
   {
-    PATTERN_GHOSTCRUSH, 5, {
-      RGB_WHITE,
-      RGB_WHITE,
-      RGB_OFF,
-      0x700000,
-      RGB_OFF,
+    PATTERN_GAPCYCLE, MAP_LED_ALL, 4, {
+      0x00553A,
+      0x00CFFF,
+      0x55001D,
+      0x551200
+    },
+    PATTERN_GAPCYCLE, MAP_LED_NONE, 4, {
+      HSV(114, 255, 43),
+      HSV(159, 255, 128),
+      HSV(240, 255, 43),
+      HSV(9, 255, 43)
     }
   },
+
   {
-    PATTERN_WARPWORM, 2, {
-      RGB_GREEN,
-      0x26004B,
+    PATTERN_TRACER, MAP_PAIR_EVENS, 3, {
+      0x62007F,
+      0x62007F,
+      0x33FE00
+    },
+    PATTERN_BLENDSTROBE, MAP_PAIR_ODDS, 8, {
+      0xFF0019,
+      0x553600,
+      0xABFF00,
+      0x005502,
+      0x00FFBA,
+      0x003155,
+      0x1E00FF,
+      0x460055
     }
   },
+
   {
-    PATTERN_PULSISH, 3, {
-      0x00AB55,
-      0x8D1C55,
-      0x00001C
+    PATTERN_BLENDSTROBEGAP, MAP_PAIR_EVENS, 8, {
+      0xFFAE00,
+      0x3D5500,
+      0x1BFF00,
+      0x00552A,
+      0x00E7FF,
+      0x001955,
+      0x4E00FF,
+      0x4e0055
+    },
+    PATTERN_GHOSTCRUSH, MAP_PAIR_ODDS, 8, {
+      0xFFAE00,
+      0x3D5500,
+      0x1BFF00,
+      0x00552A,
+      0x00E7FF,
+      0x001955,
+      0x4E00FF,
+      0x4e0055
     }
   },
 
   {
-    PATTERN_ZIGZAG, 6, {
-      RGB_OFF,
-      0x56D400,
-      0x5500AB,
-      RGB_OFF,
-      RGB_RED,
-      0x700000
+    PATTERN_BLENDSTROBE, MAP_PAIR_EVENS, 6, {
+      0x554A00,
+      0x554A00,
+      0x00AA90,
+      0x00AA90,
+      0xD200FF,
+      0xD200FF
+    },
+    PATTERN_DOUBLEDOPS, MAP_PAIR_ODDS, 8, {
+      0xFF0033,
+      0xFF0033,
+      0xDB2F00,
+      0xB76B00,
+      0x938D00,
+      0x4A6F00,
+      0x164B00,
+      0x002702
     }
   },
+
   {
-    PATTERN_STROBE, 8, {
+    PATTERN_CHASER, MAP_LED_ALL, 5, {
+      0x9FFF00,
+      0x00FF66,
+      0x009FFF,
+      0x5A00FF,
+      0xFF009F
+    },
+    PATTERN_CHASER, MAP_LED_NONE, 5, {
+      HSV(0, 0, 255),
+      HSV(0, 0, 255),
+      HSV(0, 0, 0),
+      HSV(140, 255, 170),
+      HSV(0, 0, 0)
+    }
+  },
+
+  {
+    PATTERN_METEOR, MAP_LED_ALL, 5, {
+      0x00AA90,
+      0x00B1FF,
+      0x300055,
+      0xFF002D,
+      0x541B00
+    },
+    PATTERN_METEOR, MAP_LED_NONE, 5, {
+      HSV(0, 0, 255),
+      HSV(0, 0, 255),
+      HSV(0, 0, 0),
+      HSV(170, 255, 170),
+      HSV(0, 0, 0)
+    }
+  },
+
+  {
+    PATTERN_DRIP, MAP_LED_ALL, 5, {
+      0x0000FF,
+      0x400055,
+      0x54000B,
+      0x525400,
+      0x26AA00
+    },
+    PATTERN_DRIP, MAP_LED_NONE, 5, {
+      HSV(0, 0, 255),
+      HSV(0, 0, 255),
+      HSV(0, 0, 0),
+      HSV(200, 255, 170),
+      HSV(0, 0, 0)
+    }
+  },
+
+  {
+    PATTERN_HYPERSTROBE, MAP_LED_ALL, 2, {
+      0xFFF600,
+      0x000880
+    },
+    PATTERN_HYPERSTROBE, MAP_LED_NONE, 5, {
+      HSV(0, 0, 255),
+      HSV(0, 0, 255),
+      HSV(0, 0, 0),
+      HSV(230, 255, 170),
+      HSV(0, 0, 0)
+    }
+  },
+
+  {
+    PATTERN_SPARKLETRACE, MAP_LED_ALL, 6, {
+      0x003755,
+      0x003755,
+      0xAA0072,
+      0xAA0072,
+      0xA5FF00,
+      0xA5FF00
+    },
+    PATTERN_SPARKLETRACE, MAP_LED_NONE, 5, {
+      HSV(0, 0, 255),
+      HSV(0, 0, 255),
+      HSV(0, 0, 0),
+      HSV(0, 255, 170),
+      HSV(0, 0, 0)
+    }
+  },
+
+  {
+    PATTERN_DASHDOPS, MAP_LED_ALL, 5, {
+      0xE2E7FF,
+      0x010015,
+      0x13090E,
+      0x010015,
+      0xE2E7FF
+    },
+    PATTERN_DASHDOPS, MAP_LED_NONE, 8, {
       0xD4002B,
       RGB_OFF,
       0x0056AA,
@@ -59,15 +201,9 @@ const default_mode_entry default_modes[MAX_MODES] = {
       RGB_OFF
     }
   },
+
   {
-    PATTERN_SNOWBALL, 3, {
-      0x170600,
-      0x00840A,
-      0x12002A
-    }
-  },
-  {
-    PATTERN_ULTRADOPS, 8, {
+    PATTERN_ULTRADOPS, MAP_LED_ALL, 8, {
       0x1C0000,
       0x4B2600,
       0xABAA00,
@@ -76,30 +212,30 @@ const default_mode_entry default_modes[MAX_MODES] = {
       0x00001C,
       0x26004B,
       0x13000A
-    }
-  },
-  {
-    PATTERN_VORTEX, 4, {
-      0xAA0055,
-      0x7070C5,
-      0x0A0013,
-      0x1C8E55,
-    }
-  },
-  {
-    PATTERN_VORTEXWIPE, 8, {
-      RGB_RED,
-      0x00001C,
-      0x00001C,
-      0x00001C,
-      0x00001C,
-      0x00001C,
-      0x00001C,
+    },
+    PATTERN_ULTRADOPS, MAP_LED_NONE, 8, {
+      0x1C0000,
+      0x4B2600,
+      0xABAA00,
+      0x001C00,
+      0x00130A,
       0x00001C,
+      0x26004B,
+      0x13000A
     }
   },
+
   {
-    PATTERN_GHOSTCRUSH, 7, {
+    PATTERN_GHOSTCRUSH, MAP_LED_ALL, 7, {
+      0x26004B,
+      RGB_OFF,
+      RGB_GREEN,
+      RGB_WHITE,
+      RGB_GREEN,
+      RGB_OFF,
+      0x26004B,
+    },
+    PATTERN_GHOSTCRUSH, MAP_LED_NONE, 7, {
       0x26004B,
       RGB_OFF,
       RGB_GREEN,
@@ -109,15 +245,14 @@ const default_mode_entry default_modes[MAX_MODES] = {
       0x26004B,
     }
   },
+
   {
-    PATTERN_VORTEXWIPE, 3, {
-      0x00AB55,
-      0x7F0081,
-      0xAA381C,
-    }
-  },
-  {
-    PATTERN_COMPLEMENTARY_BLEND, 3, {
+    PATTERN_COMPLEMENTARY_BLEND, MAP_LED_ALL, 3, {
+      RGB_RED,
+      RGB_GREEN,
+      RGB_BLUE
+    },
+    PATTERN_COMPLEMENTARY_BLEND, MAP_LED_NONE, 3, {
       RGB_RED,
       RGB_GREEN,
       RGB_BLUE
diff --git a/VortexEngine/src/Modes/DefaultModes.h b/VortexEngine/src/Modes/DefaultModes.h
index 888e4fb7bf..a854ed65b6 100644
--- a/VortexEngine/src/Modes/DefaultModes.h
+++ b/VortexEngine/src/Modes/DefaultModes.h
@@ -3,13 +3,19 @@
 
 #include "../Patterns/Patterns.h"
 #include "../VortexConfig.h"
+#include "../Leds/LedTypes.h"
 
 // structure of the entries in the default modes array
 struct default_mode_entry
 {
   PatternID patternID;
+  LedMap map;
   uint8_t numColors;
   uint32_t cols[MAX_COLOR_SLOTS];
+  PatternID patternID2;
+  LedMap map2;
+  uint8_t numColors2;
+  uint32_t cols2[MAX_COLOR_SLOTS];
 };
 
 // exposed global array of default modes
diff --git a/VortexEngine/src/Modes/Modes.cpp b/VortexEngine/src/Modes/Modes.cpp
index a81a6d72db..2b96c53745 100644
--- a/VortexEngine/src/Modes/Modes.cpp
+++ b/VortexEngine/src/Modes/Modes.cpp
@@ -390,8 +390,16 @@ bool Modes::setDefaults()
   // add each default mode with each of the given colors
   for (uint8_t i = 0; i < num_default_modes; ++i) {
     const default_mode_entry &def = default_modes[i];
-    Colorset set(def.numColors, def.cols);
-    addMode(def.patternID, nullptr, &set);
+    Colorset set1(def.numColors, def.cols);
+    if (isMultiLedPatternID(def.patternID)) {
+      addMode(def.patternID, nullptr, &set1);
+    } else {
+      Mode tempMode;
+      tempMode.setPatternMap(def.map, def.patternID, nullptr, &set1);
+      Colorset set2(def.numColors2, def.cols2);
+      tempMode.setPatternMap(def.map2, def.patternID2, nullptr, &set2);
+      addMode(&tempMode);
+    }
   }
   return true;
 }
diff --git a/VortexEngine/src/Serial/Serial.cpp b/VortexEngine/src/Serial/Serial.cpp
index 5079e80455..e22067e1d5 100644
--- a/VortexEngine/src/Serial/Serial.cpp
+++ b/VortexEngine/src/Serial/Serial.cpp
@@ -3,6 +3,7 @@
 #include "../Serial/ByteStream.h"
 #include "../Time/TimeControl.h"
 #include "../Time/Timings.h"
+#include "../Menus/Menus.h"
 #include "../Log/Log.h"
 
 #include "../VortexEngine.h"
@@ -12,14 +13,19 @@
 #include <stdio.h>
 #endif
 
+#ifdef VORTEX_EMBEDDED
+#include <Arduino.h>
+#endif
+
 bool SerialComs::m_serialConnected = false;
 uint32_t SerialComs::m_lastCheck = 0;
+uint32_t SerialComs::m_lastConnected = 0;
 
 // init serial
 bool SerialComs::init()
 {
   // Try connecting serial ?
-  //checkSerial();
+  checkSerial();
   return true;
 }
 
@@ -29,9 +35,33 @@ void SerialComs::cleanup()
 
 bool SerialComs::isConnected()
 {
+#ifdef VORTEX_EMBEDDED
+  if (!Serial) {
+    m_serialConnected = false;
+    return false;
+  }
+  if (!isConnectedReal()) {
+    return false;
+  }
+#endif
   return m_serialConnected;
 }
 
+bool SerialComs::isConnectedReal()
+{
+#ifdef VORTEX_EMBEDDED
+  uint32_t now = Time::getCurtime();
+  if (!Serial.usb.connected()) {
+    m_lastConnected = now;
+  } else {
+    if (m_lastConnected && (now - m_lastConnected) > 1800) {
+      return false;
+    }
+  }
+#endif
+  return true;
+}
+
 // check for any serial connection or messages
 bool SerialComs::checkSerial()
 {
@@ -40,6 +70,9 @@ bool SerialComs::checkSerial()
     // already connected
     return true;
   }
+  if (m_serialConnected) {
+    return isConnectedReal();
+  }
   uint32_t now = Time::getCurtime();
   // don't check for serial too fast
   if (m_lastCheck && (now - m_lastCheck) < MAX_SERIAL_CHECK_INTERVAL) {
@@ -54,17 +87,22 @@ bool SerialComs::checkSerial()
   Vortex::vcallbacks()->serialBegin(SERIAL_BAUD_RATE);
 #else
   // This will check if the serial communication is open
-  if (!Serial.available()) {
+  if (!Serial) {
     // serial is not connected
     return false;
   }
-  // Begin serial communications
+  // Begin serial communications (turns out this is actually a NO-OP in trinket source)
   Serial.begin(SERIAL_BAUD_RATE);
+  if (Menus::curMenuID() != MENU_EDITOR_CONNECTION) {
+    // directly open the editor connection menu because we are connected to USB serial
+    Menus::openMenu(MENU_EDITOR_CONNECTION);
+  }
 #endif
 #endif
   // serial is now connected
   m_serialConnected = true;
-  return true;
+  // rely on the low level 'real' connection now
+  return isConnectedReal();
 }
 
 void SerialComs::write(const char *msg, ...)
diff --git a/VortexEngine/src/Serial/Serial.h b/VortexEngine/src/Serial/Serial.h
index 0121b5bbb0..7ce393361f 100644
--- a/VortexEngine/src/Serial/Serial.h
+++ b/VortexEngine/src/Serial/Serial.h
@@ -17,6 +17,9 @@ class SerialComs
   // whether serial is initialized
   static bool isConnected();
 
+  // why do I need this
+  static bool isConnectedReal();
+
   // check for any serial connection or messages
   static bool checkSerial();
 
@@ -36,6 +39,7 @@ class SerialComs
   // whether serial communications are initialized
   static bool m_serialConnected;
   static uint32_t m_lastCheck;
+  static uint32_t m_lastConnected;
 };
 
 #endif
diff --git a/VortexEngine/src/Storage/Storage.cpp b/VortexEngine/src/Storage/Storage.cpp
index 357cc6bd3c..a9c51fb41b 100644
--- a/VortexEngine/src/Storage/Storage.cpp
+++ b/VortexEngine/src/Storage/Storage.cpp
@@ -9,7 +9,7 @@
 #include "../Log/Log.h"
 
 #ifdef VORTEX_LIB
-#include "../VortexLib/VortexLib.h"
+#include "VortexLib.h"
 #endif
 
 #ifndef VORTEX_EMBEDDED
@@ -29,6 +29,13 @@ std::string Storage::m_storageFilename;
 #define STORAGE_FILENAME DEFAULT_STORAGE_FILENAME
 #endif
 
+#ifdef VORTEX_EMBEDDED
+#include <Arduino.h>
+#define PAGE_SIZE 64
+__attribute__((__aligned__(256)))
+const uint8_t _storagedata[(STORAGE_SIZE+255)/256*256] = { };
+#endif
+
 uint32_t Storage::m_lastSaveSize = 0;
 
 Storage::Storage()
@@ -69,7 +76,52 @@ bool Storage::write(uint16_t slot, ByteStream &buffer)
   // just in case
   buffer.recalcCRC();
 #ifdef VORTEX_EMBEDDED
-  // implement device storage here
+  // the target slot to store in
+  uint32_t storage_slot = (uint32_t)_storagedata + (slot * MAX_MODE_SIZE);
+
+  // Number of rows to erase for one slot
+  uint16_t rows_to_erase = MAX_MODE_SIZE / (PAGE_SIZE * 4);
+  // Erase only the rows containing the slot
+  for (uint16_t i = 0; i < rows_to_erase; ++i) {
+    // Set the address for the row to erase
+    NVMCTRL->ADDR.reg = (uint32_t)(storage_slot + (i * PAGE_SIZE * 4)) / 2;
+    // Execute the erase command
+    NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_ER;
+    // Wait for the erase operation to complete
+    while (!NVMCTRL->INTFLAG.bit.READY) {}
+  }
+
+  // set the last save size
+  m_lastSaveSize = buffer.size();
+
+  // write out the buffer to storage
+  // Calculate data boundaries
+  uint32_t size = (buffer.rawSize() + 3) / 4;
+  volatile uint32_t *dst_addr = (volatile uint32_t *)storage_slot;
+  const uint8_t *src_addr = (uint8_t *)buffer.rawData();
+
+  // Disable automatic page write
+  NVMCTRL->CTRLB.bit.MANW = 1;
+
+  // Do writes in pages
+  while (size) {
+    // Execute "PBC" Page Buffer Clear
+    NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_PBC;
+    while (NVMCTRL->INTFLAG.bit.READY == 0) {}
+
+    // Fill page buffer
+    uint32_t i;
+    for (i = 0; i < (PAGE_SIZE / 4) && size; i++) {
+      *dst_addr = *(uint32_t *)(src_addr);
+      src_addr += sizeof(uint32_t);
+      dst_addr++;
+      size--;
+    }
+
+    // Execute "WP" Write Page
+    NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_WP;
+    while (NVMCTRL->INTFLAG.bit.READY == 0) {}
+  }
 #elif defined(_WIN32)
   HANDLE hFile = CreateFile(STORAGE_FILENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
   if (hFile == INVALID_HANDLE_VALUE) {
@@ -118,7 +170,8 @@ bool Storage::read(uint16_t slot, ByteStream &buffer)
     return false;
   }
 #ifdef VORTEX_EMBEDDED
-  // implement device storage here
+  // read directly into the raw data of the byte array
+  memcpy(buffer.rawData(), (const void *)(_storagedata + (slot * MAX_MODE_SIZE)), size);
 #elif defined(_WIN32)
   HANDLE hFile = CreateFile(STORAGE_FILENAME, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
   if (hFile == INVALID_HANDLE_VALUE) {
diff --git a/VortexEngine/src/Time/TimeControl.cpp b/VortexEngine/src/Time/TimeControl.cpp
index 8493deb667..4a7a374041 100644
--- a/VortexEngine/src/Time/TimeControl.cpp
+++ b/VortexEngine/src/Time/TimeControl.cpp
@@ -9,6 +9,10 @@
 
 #include "../Leds/Leds.h"
 
+#ifdef VORTEX_EMBEDDED
+#include <Arduino.h>
+#endif
+
 #if !defined(_WIN32) || defined(WASM)
 #include <unistd.h>
 #include <time.h>
@@ -190,7 +194,7 @@ uint32_t Time::microseconds()
 
 void Time::delayMicroseconds(uint32_t us)
 {
-#ifdef _WIN32
+#if defined(VORTEX_EMBEDDED) || defined(_WIN32)
   uint32_t newtime = microseconds() + us;
   while (microseconds() < newtime) {
     // busy loop
diff --git a/VortexEngine/src/VortexConfig.h b/VortexEngine/src/VortexConfig.h
index e0af0570e4..05ea50e272 100644
--- a/VortexEngine/src/VortexConfig.h
+++ b/VortexEngine/src/VortexConfig.h
@@ -38,7 +38,7 @@
 
 // the engine flavour, this should change for each device/flavour
 // of the engine that branches off from the main indefinitely
-#define VORTEX_NAME "Core"
+#define VORTEX_NAME "Handle"
 
 // the full name of this build for ex:
 //    Vortex Engine v1.0 'Igneous' (built Tue Jan 31 19:03:55 2023)
@@ -57,8 +57,8 @@
 
 // Menu Trigger Threshold (in milliseconds)
 //
-// How long the button must be held to trigger menu selection and
-// begin blinking the first menu color
+// How long the button must be held to trigger ring menu and begin
+// filling the first menu color
 #define MENU_TRIGGER_TIME     1000
 
 // Short Click Threshold (in milliseconds)
@@ -176,7 +176,7 @@
 // This should not be set to 0, it should be a specific maximum for
 // each separate device
 //
-#define MAX_MODES             13
+#define MAX_MODES             14
 
 // Default Tickrate in Ticks Per Second (TPS)
 //
diff --git a/VortexEngine/src/VortexEngine.cpp b/VortexEngine/src/VortexEngine.cpp
index 3addef3007..1b133fa72a 100644
--- a/VortexEngine/src/VortexEngine.cpp
+++ b/VortexEngine/src/VortexEngine.cpp
@@ -169,6 +169,9 @@ void VortexEngine::runMainLogic()
     return;
   }
 
+  // check if the device has been plugged in
+  SerialComs::checkSerial();
+
   // if the menus are open and running then just return
   if (Menus::run()) {
     return;
diff --git a/VortexEngine/src/Wireless/IRReceiver.cpp b/VortexEngine/src/Wireless/IRReceiver.cpp
index 47ec50ef4d..19f83e1b50 100644
--- a/VortexEngine/src/Wireless/IRReceiver.cpp
+++ b/VortexEngine/src/Wireless/IRReceiver.cpp
@@ -9,6 +9,10 @@
 #include "../Modes/Mode.h"
 #include "../Log/Log.h"
 
+#ifdef VORTEX_EMBEDDED
+#include <Arduino.h>
+#endif
+
 BitStream IRReceiver::m_irData;
 IRReceiver::RecvState IRReceiver::m_recvState = WAITING_HEADER_MARK;
 uint32_t IRReceiver::m_prevTime = 0;
@@ -17,6 +21,9 @@ uint32_t IRReceiver::m_previousBytes = 0;
 
 bool IRReceiver::init()
 {
+#ifdef VORTEX_EMBEDDED
+  pinMode(IR_RECEIVER_PIN, INPUT_PULLUP);
+#endif
   m_irData.init(IR_RECV_BUF_SIZE);
   return true;
 }
@@ -83,12 +90,18 @@ bool IRReceiver::receiveMode(Mode *pMode)
 
 bool IRReceiver::beginReceiving()
 {
+#ifdef VORTEX_EMBEDDED
+  attachInterrupt(digitalPinToInterrupt(IR_RECEIVER_PIN), IRReceiver::recvPCIHandler, CHANGE);
+#endif
   resetIRState();
   return true;
 }
 
 bool IRReceiver::endReceiving()
 {
+#ifdef VORTEX_EMBEDDED
+  detachInterrupt(digitalPinToInterrupt(IR_RECEIVER_PIN));
+#endif
   resetIRState();
   return true;
 }
diff --git a/VortexEngine/src/Wireless/IRSender.cpp b/VortexEngine/src/Wireless/IRSender.cpp
index 1d127a1978..5ec181188c 100644
--- a/VortexEngine/src/Wireless/IRSender.cpp
+++ b/VortexEngine/src/Wireless/IRSender.cpp
@@ -11,6 +11,10 @@
 #include "VortexLib.h"
 #endif
 
+#ifdef VORTEX_EMBEDDED
+#include <Arduino.h>
+#endif
+
 // the serial buffer for the data
 ByteStream IRSender::m_serialBuf;
 // a bit walker for the serial data
@@ -30,8 +34,15 @@ uint32_t IRSender::m_blockSize = 0;
 // write total
 uint32_t IRSender::m_writeCounter = 0;
 
+#if defined(VORTEX_EMBEDDED)
+// Timer used for PWM, is initialized in initpwm()
+Tcc *IR_TCCx;
+#endif
+
 bool IRSender::init()
 {
+  // initialize the IR device
+  initPWM();
   return true;
 }
 
@@ -111,6 +122,8 @@ void IRSender::beginSend()
   m_isSending = true;
   DEBUG_LOGF("[%zu] Beginning send size %u (blocks: %u remainder: %u blocksize: %u)",
     Time::microseconds(), m_size, m_numBlocks, m_remainder, m_blockSize);
+  // init sender before writing, is this necessary here? I think so
+  initPWM();
   // wakeup the other receiver with a very quick mark/space
   sendMark(50);
   sendSpace(100);
@@ -144,6 +157,9 @@ void IRSender::sendMark(uint16_t time)
 #ifdef VORTEX_LIB
   // send mark timing over socket
   Vortex::vcallbacks()->infraredWrite(true, time);
+#else
+  startPWM();
+  Time::delayMicroseconds(time);
 #endif
 }
 
@@ -152,6 +168,80 @@ void IRSender::sendSpace(uint16_t time)
 #ifdef VORTEX_LIB
   // send space timing over socket
   Vortex::vcallbacks()->infraredWrite(false, time);
+#else
+  stopPWM();
+  Time::delayMicroseconds(time);
+#endif
+}
+
+// shamelessly stolen from IRLib2, thanks
+void IRSender::initPWM()
+{
+#if defined(VORTEX_EMBEDDED)
+  // initialize the output pin
+  pinMode(IR_SEND_PWM_PIN, OUTPUT);
+  digitalWrite(IR_SEND_PWM_PIN, LOW);
+  // setup the PWM
+  uint8_t port = g_APinDescription[IR_SEND_PWM_PIN].ulPort; // 0
+  uint8_t pin = g_APinDescription[IR_SEND_PWM_PIN].ulPin;   // 8
+  ETCChannel IR_TCC_Channel = TCC0_CH0;
+  int8_t IR_PER_EorF = PORT_PMUX_PMUXE_E;
+  //println();Serial.print("Port:"); Serial.print(port,DEC); Serial.print(" Pin:"); Serial.println(pin,DEC);
+  // Enable the port multiplexer for the PWM channel on pin
+  PORT->Group[port].PINCFG[pin].bit.PMUXEN = 1;
+
+  // Connect the TCC timer to the port outputs - port pins are paired odd PMUXO and even PMUXEII
+  // F & E peripherals specify the timers: TCC0, TCC1 and TCC2
+  PORT->Group[port].PMUX[pin >> 1].reg |= IR_PER_EorF;
+
+//  pinPeripheral (IR_SEND_PWM_PIN,PIO_TIMER_ALT);
+  // Feed GCLK0 to TCC0 and TCC1
+  REG_GCLK_CLKCTRL = GCLK_CLKCTRL_CLKEN |       // Enable GCLK0 to TCC0 and TCC1
+                     GCLK_CLKCTRL_GEN_GCLK0 |   // Select GCLK0
+                     GCLK_CLKCTRL_ID_TCC0_TCC1; // Feed GCLK0 to TCC0 and TCC1
+  while (GCLK->STATUS.bit.SYNCBUSY);            // Wait for synchronization
+
+  // Normal (single slope) PWM operation: timers countinuously count up to PER
+  // register value and then is reset to 0
+  IR_TCCx = (Tcc*) GetTC(IR_TCC_Channel);
+  IR_TCCx->WAVE.reg |= TCC_WAVE_WAVEGEN_NPWM;   // Setup single slope PWM on TCCx
+  while (IR_TCCx->SYNCBUSY.bit.WAVE);           // Wait for synchronization
+
+  // Each timer counts up to a maximum or TOP value set by the PER register,
+  // this determines the frequency of the PWM operation.
+  uint32_t cc = F_CPU/(38*1000) - 1;
+  IR_TCCx->PER.reg = cc;      // Set the frequency of the PWM on IR_TCCx
+  while(IR_TCCx->SYNCBUSY.bit.PER);
+
+  // The CCx register value corresponds to the pulsewidth in microseconds (us)
+  // Set the duty cycle of the PWM on TCC0 to 33%
+  IR_TCCx->CC[GetTCChannelNumber(IR_TCC_Channel)].reg = cc/3;
+  while (IR_TCCx->SYNCBUSY.reg & TCC_SYNCBUSY_MASK);
+  //while(IR_TCCx->SYNCBUSY.bit.CC3);
+
+  // Enable IR_TCCx timer but do not turn on PWM yet. Will turn it on later.
+  IR_TCCx->CTRLA.reg |= TCC_CTRLA_PRESCALER_DIV1;     // Divide GCLK0 by 1
+  while (IR_TCCx->SYNCBUSY.bit.ENABLE);
+  IR_TCCx->CTRLA.reg &= ~TCC_CTRLA_ENABLE;            //initially off will turn on later
+  while (IR_TCCx->SYNCBUSY.bit.ENABLE);
+#endif
+}
+
+void IRSender::startPWM()
+{
+#if defined(VORTEX_EMBEDDED)
+  // start the PWM
+  IR_TCCx->CTRLA.reg |= TCC_CTRLA_ENABLE;
+  while (IR_TCCx->SYNCBUSY.bit.ENABLE);
+#endif
+}
+
+void IRSender::stopPWM()
+{
+#if defined(VORTEX_EMBEDDED)
+  // stop the PWM
+  IR_TCCx->CTRLA.reg &= ~TCC_CTRLA_ENABLE;
+  while (IR_TCCx->SYNCBUSY.bit.ENABLE);
 #endif
 }
 
diff --git a/VortexEngine/src/Wireless/IRSender.h b/VortexEngine/src/Wireless/IRSender.h
index 8f65fa7048..d8e9df30eb 100644
--- a/VortexEngine/src/Wireless/IRSender.h
+++ b/VortexEngine/src/Wireless/IRSender.h
@@ -34,6 +34,11 @@ class IRSender
   // send a mark/space by turning PWM on/off
   static void sendMark(uint16_t time);
   static void sendSpace(uint16_t time);
+  // Pulse-Width Modulator (IR Transmitter)
+  static void initPWM();
+  // turn the IR transmitter on/off in realtime
+  static void startPWM();
+  static void stopPWM();
 
   // the serial buffer for the data
   static ByteStream m_serialBuf;
diff --git a/VortexEngine/src/Wireless/VLConfig.h b/VortexEngine/src/Wireless/VLConfig.h
index 2ee8490d67..00438aea9a 100644
--- a/VortexEngine/src/Wireless/VLConfig.h
+++ b/VortexEngine/src/Wireless/VLConfig.h
@@ -8,7 +8,7 @@
 // Whether to enable the Visible Light system as a whole
 //
 #define VL_ENABLE_SENDER          1
-#define VL_ENABLE_RECEIVER        1
+#define VL_ENABLE_RECEIVER        0
 
 // the size of IR blocks in bits
 #define VL_DEFAULT_BLOCK_SIZE 256
diff --git a/VortexEngine/tests/tests_general.tar.gz b/VortexEngine/tests/tests_general.tar.gz
index 5c0e6df188..1dce74787f 100644
Binary files a/VortexEngine/tests/tests_general.tar.gz and b/VortexEngine/tests/tests_general.tar.gz differ
diff --git a/rewrite_trinket_source.sh b/rewrite_trinket_source.sh
new file mode 100644
index 0000000000..989304938b
--- /dev/null
+++ b/rewrite_trinket_source.sh
@@ -0,0 +1,45 @@
+#!/bin/bash
+
+FILE_PATH="$HOME/.arduino15/packages/adafruit/hardware/samd/1.7.16/cores/arduino/USB/CDC.cpp"
+
+# Check if the file exists
+if [ ! -f "$FILE_PATH" ]; then
+    echo "Error: File does not exist."
+    exit 1
+fi
+# Read the specific line and check its content
+CURRENT_LINE=$(sed -n '258p' "$FILE_PATH")
+
+if [ "$CURRENT_LINE" != "	delay(10);" ]; then
+  if [ "$CURRENT_LINE" != "	\/\/delay(10);" ]; then
+    echo "No changes made: line 258 does not match the expected content."
+    exit 1
+  fi
+  echo "No changes made: line 258 has already been modified."
+else
+  # Replace the content of line 258
+  sed -i '258s/.*/	\/\/delay(10);/' "$FILE_PATH"
+  echo "Line 258, a delay(10), has been commented out in: [$FILE_PATH]"
+fi
+
+# =============================================================================================
+
+FILE_PATH2="$HOME/.arduino15/packages/adafruit/hardware/samd/1.7.16/cores/arduino/USB/USBAPI.h"
+# Check if the file exists
+if [ ! -f "$FILE_PATH2" ]; then
+    echo "Error: File does not exist."
+    exit 1
+fi
+# Read the specific line and check its content
+CURRENT_LINE=$(sed -n '182p' "$FILE_PATH2")
+if [ "$CURRENT_LINE" != "private:" ]; then
+  if [ "$CURRENT_LINE" != "\/\/private:" ]; then
+    echo "No changes made: line 182 does not match the expected content."
+    exit 1
+  fi
+  echo "No changes made: line 182 has already been modified."
+else
+  # replace the content of line
+  sed -i '182s/.*/\/\/private:/' "$FILE_PATH2"
+  echo "Line 182, private: has been commented out in: [$FILE_PATH2]"
+fi