Software developer with 7 years building software end to end — from C firmware running on STM32 and NXP LPC microcontrollers, through C#/WPF desktop applications, to Python/FastAPI services with React front-ends. Principal author of 29 repositories and 4,600+ commits across 33 projects, with a track record of taking tools from first commit to signed installer: unit tests, CI pipelines, documentation and release included. Since 2025 I have worked AI-assisted, and my two most recent tools were delivered that way end to end: I decide what the system has to do, encode the conventions the assistant works under in repository instruction files, review every generated diff before it is committed, test every build by hand and direct the fixes until the behaviour is right — the code in those two is AI-generated; the specification, the testing and the accountability are mine. Came into software from silicon-level design and verification work, so hardware is not a black box. Outside work I run a Proxmox homelab managed entirely as code — Terraform/Terragrunt and Ansible provisioning a dozen self-hosted services behind a reverse proxy — which is where the Linux, networking and infrastructure-as-code experience comes from.
The group's longest-running project and largest codebase. WPF/MVVM Excel ribbon add-in for test plans, cases, executions and evidence, backed by SharePoint lists and a local Entity Framework cache. Rebuilt from a prototype into a maintainable architecture and sustained through a four-year refactor: per-entity EF controllers replaced with generics, an event-based notification layer decoupling views from viewmodels, PropertyChanged handlers migrated to ICommand bindings, and a full WiX installer.
Full-stack platform for OCR-processing and searching engineering documents and instrument captures, delivered against formal TDD/FSD design documents. FastAPI backend with pluggable OCR engines, PostgreSQL full-text search, React 19 search client, privacy-preserving Microsoft 365 authentication where credentials never leave the identity provider, batch upload with provenance, and load-test suites covering search, smoke, stress and upload scenarios. Shipped with nginx site configuration, a TLS setup guide and systemd units. The code was AI-generated with GitHub Copilot agent mode, as were the TDD/FSD documents drafted to my requirements; the requirements and architecture, the instruction files constraining the assistant, review of every diff before commit, hands-on testing of every build and the defect-and-fix cycles are mine.
Python utility keeping qualified tool environments and source-file databases synchronised across engineering workstations. Self-contained Windows EXE and Linux/macOS installers requiring no repository checkout and no elevated privileges; command-level logging on test execution for traceability; version override tables; safe backup and re-locking of read-only shell configuration. CI matrix across Python 3.12 and 3.13. The code was AI-generated with GitHub Copilot agent mode under a self-authored SKILLS.md instruction file, and the requirements and validation documents were drafted to my specification; I set what the tool had to do, reviewed every diff before commit, tested each build by hand on real Windows, Linux and macOS workstations and directed the fixes until behaviour was correct.
Firmware for an automated stress-test rig across three repositories. TFT touchscreen state machine (designed and documented with its state diagram), continuous and burst test modes, waveform generation, rotary-switch input, and a WiFi module that emails engineers when a fault occurs during unattended overnight runs. Resolved a timing defect by making I²C transmission run parallel to waveform generation, eliminating bus-induced frequency error; reworked NVIC interrupt priority to clear I²C blocking and added a bit-bang SPI path.
WPF GUI paired with C/C++ firmware for a USB bridge, providing register access, live telemetry and configuration persistence — the most pull-request-heavy project in the portfolio (118 PRs). Continuous burst reader and ADC parser with dynamically scaled live graphing, interrupt field handling, drag-and-drop CSV state save/load with backward compatibility, and an emulator project allowing the GUI to be developed and tested without hardware.
Rather than hand-coding a form per register, the GUI is generated dynamically from register definitions, keeping the tool adaptable as specifications changed. Multi-setting concurrent burst reads, sequence register controls, write/read lockout while monitoring is active, and a mock USB layer so interface and plotting could be verified without hardware.
One shared codebase serving five device variants, each with its own register map, installer, versioning and user manual. Focused on reusable, model-bound custom controls: fader and balance controls with hex input validation, interface-based field binding, press-and-hold continuous increment, and a sound-control configuration window with input validation.
Automated quality-assurance system driving an NXP LPC board over USB CDC with an Arduino harness. Configurable I²C byte-count command with tests, shift-register flushing to prevent stale readback, bus-lock recovery, and SCT/PWM configuration fixes for reliable duty-cycle control. Includes a protocol-compliant microcontroller emulator for hardware-free testing, a gRPC test-management client, and Microsoft Graph notifications replacing SMTP mail.
Reverse-engineered existing board behaviour, derived and validated the correct forward-voltage-to-temperature formula against measured hardware, and built a repeatable end-to-end voltage-to-ADC calibration workflow with multi-board support. Refactored for dependency injection and interfaces with mocks and a test command, then fronted with a WPF event-driven UI. Used in production to calibrate 10 boards.
Verification software handling USB firmware loading, register map management and profile data parsing. Changed error handling to surface all exceptions rather than only the first, making verification failures diagnosable; restructured the send path so it could be substituted from outside the main project for unit testing; added unit tests and a code-coverage pipeline.
The shared model layer consumed across the group's test tooling: entity models, a local Entity Framework database, and bidirectional SharePoint list synchronisation. Generic base models and a common data interface enabling generic operations across every model, state detection (new/modified/unchanged), image and file transfer handling, packaged as a NuGet library.
Automation-friendly counterpart to the Excel add-in: upload, dump, copy and update of test plans, cases, steps, results and evidence. Copy operations across parent/child entities with correct ordering and attribution, XML dump, record locking and version columns. Migrated to .NET 8 with single-file publishing, maintained through semantic versioning to 1.5.1.1.
Also: instrument automation utilities migrated from legacy SICL/NI-GPIB to modern VISA for oscilloscope capture and thermal-chamber sweeps; a net/pin check generator for EDA support; a general-purpose I²C tool; EEPROM production tooling; a device scripting application; and release-engineering installers.
Terraform/Terragrunt and Ansible codebase provisioning and configuring a Proxmox homelab: LXC containers and cloud-init VMs, per-container ZFS datasets, DNS, a Caddy reverse proxy issuing Let's Encrypt certificates over the Cloudflare DNS-01 challenge, and a dozen self-hosted services (Gitea, PostgreSQL, Vaultwarden, Immich, Jellyfin, OpenCloud, ntfy and others) reached from outside through a tunnel to a public VPS. A single infrastructure.yml is the one source of truth for every instance and IP; a Python generator derives the Ansible inventory from it so the provisioning and configuration layers cannot drift. Both layers enforce recovery after a power event — Terraform sets start_on_boot, Ansible writes a native systemd unit and asserts it is enabled, after finding that Docker Compose restart policies alone do not survive a host reboot. Ran a security audit over the repo and remediated what it found: an API token cached in Terragrunt state, credentials passed as URL query parameters, a default database password, and a tunnel secret embedded in a systemd unit. The code here was AI-generated; the architecture decisions, conventions, review, deployment and debugging are mine — boot races, silent listen-address binds, a credential that lived in two unlinked places, Intel GPU passthrough for transcoding in an unprivileged LXC.