Skip to content

garyPenhook/cc5x-helper

Repository files navigation

cc5x-helper

Linux-native CC5X PIC workflow — pack-driven headers, managed #pragma config, CrossOver/Wine builds, and optional IPECMD flashing, all from one checked-in manifest.

CI License: MIT Python 3.12+ Interfaces: CLI · GUI · VS Code

cc5x-helper desktop GUI — Projects tab

Contents


cc5x-helper is a Linux-native replacement for the useful engineering workflows behind BKND's SETCC.EXE.

It is built for CC5X-target PIC families only:

  • PIC10F
  • PIC12F
  • PIC16F

The tool does not try to recreate the old Windows GUI. It replaces the parts that matter in practice:

  • device-pack discovery
  • pack-driven CC5X header generation
  • config-symbol discovery and managed #pragma config emission
  • manifest-based project state instead of opaque setcc.pxk
  • CrossOver/Wine-backed CC5X builds from Linux
  • optional device programming through MPLAB IPECMD (PICkit 4/5, SNAP, ICD4)
  • an optional MPLAB-free open-source flasher for the PICkit 4 (pk4prog/)
  • an optional desktop GUI and a VS Code extension

Why This Exists

SETCC.EXE is a Windows-only Borland/VCL application. It hides project state in setcc.pxk, depends on Microchip metadata layouts that have changed over time, and is awkward to automate on Linux.

This project takes the modern route:

  • prefer Microchip PIC DFP .atpack archives
  • normalize .PIC, .ini, and cfgdata into one device model
  • generate deterministic CC5X-style output
  • keep project state in source control
  • validate generated headers with the real CC5X.EXE

Requirements

Requirement Needed for Notes
Python ≥ 3.12 everything declared in pyproject.toml (requires-python = ">=3.12")
uv recommended install/runner manages the virtualenv, dependencies, and the bundled console scripts
CC5X compiler (CC5X.EXE) build, header validation proprietary, from B Knudsen Data (Norway). Not bundled — you supply it
Wine or CrossOver running the Windows CC5X.EXE on Linux invoked through a "runner" (see Setup)
Microchip device packs device discovery, header/config generation .atpack DFP archives, or an installed MPLAB X pack cache
MPLAB X / IPECMD + a PICkit the optional program command only needed if you flash hardware from this tool
PyQt6 ≥ 6.6 the optional desktop GUI installed via the gui extra

This repo does not bundle proprietary CC5X binaries or Microchip packs as tracked source files. You must obtain them separately and point the tool at them.


Installation

With uv (recommended)

git clone <this-repo> cc5x-helper
cd cc5x-helper

# Create the venv and install the project + runtime deps (e.g. defusedxml):
uv sync

# Include the GUI and/or dev (pytest, flake8) extras as needed:
uv sync --extra gui --extra dev

uv sync creates a project virtualenv and installs the two console entry points declared in pyproject.toml:

  • cc5x-helper → the CLI (cc5x_setcc_native:main)
  • cc5x-helper-gui → the desktop GUI (requires the gui extra)

Run them through uv run (no manual venv activation needed):

uv run cc5x-helper doctor
uv run cc5x-helper list-devices --family 16F
uv run --extra gui cc5x-helper-gui

One-off invocation without installing

uv run can fetch dependencies on the fly:

uv run --with defusedxml python tools/cc5x_setcc_native.py doctor

With pip (alternative)

python3 -m venv .venv && source .venv/bin/activate
pip install -e .            # base CLI
pip install -e ".[gui]"     # + desktop GUI
pip install -e ".[dev]"     # + pytest/flake8

The examples below use uv run cc5x-helper …. If you installed with pip and activated the venv, drop the uv run prefix and just call cc5x-helper …. You can always fall back to uv run python tools/cc5x_setcc_native.py ….


Setup

cc5x-helper discovers device metadata, the compiler, and a runner automatically, with environment-variable overrides for anything in a non-default location. Run doctor at any time to see what was found and what is still missing.

1. Provide the CC5X compiler

Obtain CC5X.EXE from B Knudsen Data and either:

  • place it at the default path cc5x_paid/CC5X/CC5X.EXE inside the repo, or
  • point at it explicitly with CC5X_COMPILER, or per-project with --compiler.
export CC5X_COMPILER="$HOME/tools/CC5X/CC5X.EXE"

2. Provide a runner (how the Windows compiler is launched)

The runner is the launcher that executes the Windows CC5X.EXE on Linux. It is a command template: the compiler path is inserted wherever you write the {compiler} placeholder. If the runner has no {compiler} placeholder it is treated as self-contained — i.e. it already knows which compiler to run — and only the CC5X options and the source file are appended. (This replaces an older rule that keyed off the runner's filename, so renaming a wrapper no longer changes behavior.)

Minimal Wine runner — Wine needs the compiler path, so include the placeholder (a bare wine runner without it fails with a clear "add the {compiler} placeholder" error):

uv run cc5x-helper build --project setcc-native.json --edition production --runner "wine {compiler}"

A pass-through wrapper script (forwards its arguments to Wine/CrossOver) also needs the compiler, so invoke it with the placeholder, e.g. ~/apps/cc5x-run.sh {compiler}:

#!/usr/bin/env bash
# Forward all CC5X arguments through Wine (or cxrun for a CrossOver bottle).
exec wine "$@"
# CrossOver example:
# exec /opt/cxoffice/bin/cxrun --bottle CC5X -- "$@"
chmod +x ~/apps/cc5x-run.sh
export CC5X_RUNNER="$HOME/apps/cc5x-run.sh {compiler}"

A self-contained wrapper that hard-codes the compiler path internally (like the default cc5x-run.sh, which runs 'C:\Program Files\...\CC5X.EXE' "$@") needs no placeholder — set the runner to just the script path.

With no CC5X_RUNNER set, the tool looks for cc5x-run.sh next to the installed package and one directory above it (install-relative, not a fixed path — so this works the same regardless of whose machine or home directory it's checked out into); the default CrossOver bottle is ~/.cxoffice/CC5X. Override either with the env vars or manifest fields if your layout differs.

3. Provide device packs

Point the tool at Microchip device-pack metadata using any of:

  • drop Microchip.*.atpack archives into ~/apps or ~/Downloads (scanned by default), or
  • set CC5X_ATPACK_DIRS to a :-separated list of directories holding .atpack files, or
  • rely on an installed MPLAB X pack cache (~/.mchp_packs/Microchip, or set CC5X_PACK_ROOTS / MPLABX_PACKS).
export CC5X_ATPACK_DIRS="$HOME/microchip/packs"

Packs go stale over time — see §6 for how to check for and pull in newer Microchip releases, including an opt-in daily auto-update timer.

4. (Optional) Set up programming

To flash hardware with the program command you need MPLAB X's ipecmd and a supported programmer (PICkit 4/5, SNAP, ICD4). IPECMD is auto-discovered under installed MPLAB X versions, or set CC5X_IPECMD:

export CC5X_IPECMD="/opt/microchip/mplabx/v6.30/mplab_platform/mplab_ipe/ipecmd.sh"

5. (Optional) Shrink a full MPLAB X install

This tool never touches the MPLAB X IDE itself — only mplab_platform/mplab_ipe (the ipecmd CLI), mplab_platform/bin (its launcher dependency, common-vars.sh), the bundled JRE under sys/java/…, and whichever packs/Microchip/<family>_DFP / <tool>_TP directories match your devices and programmer. A stock MPLAB X install is ~7GB; the pieces above are typically under 2GB.

scripts/prune_mplabx.sh deletes everything else in place (full IDE, MCC, docs, ARM packs, unused device families, unused programmer tool packs). Review it before running — it needs sudo since MPLAB X is usually root-owned, and it's destructive against a real install outside this repo.

sudo sh scripts/prune_mplabx.sh /opt/microchip/mplabx/v6.30

By default it keeps the PIC10F/PIC12F/PIC16F pack families this repo supports (PIC10-12Fxxx_DFP, PIC12-16F1xxx_DFP, PIC16F1xxxx_DFP, PIC16Fxxx_DFP) plus PICkit4_TP and PICkit5_TP. Before running it on a new machine:

  • Edit the PICkit4_TP PICkit5_TP keep-list in the script to match the programmer(s) you actually own (SNAPSnap_TP, ICD4ICD4_TP, etc. — list the exact directory names under packs/Microchip on your machine).

  • If you add support for a device outside PIC10F/PIC12F/PIC16F, add its pack family to the keep-list first, or the prune will delete metadata you need.

  • Do not relocate the pruned directory tree. ipecmd.sh and common-vars.sh hardcode the JRE path (sys/java/zulu8…) as an absolute path baked in at install time — pruning in place keeps that path valid; copying the result elsewhere breaks it unless you also patch those two scripts.

  • After pruning, confirm ipecmd still runs and doctor still reports the expected devices:

    /opt/microchip/mplabx/v6.30/mplab_platform/mplab_ipe/ipecmd.sh -P PIC16F1509 -TPPK4
    uv run cc5x-helper doctor

6. (Optional) Check for newer device packs

MPLAB X's bundled pack cache (or a manually downloaded .atpack) is a point-in-time snapshot; Microchip keeps publishing newer _DFP releases after you install. packs-check queries packs.download.microchip.com (read-only, network) for the latest published version of every pack family backing a locally discovered PIC10F/PIC12F/PIC16F device, and packs-update downloads (and SHA-256-verifies) any that are newer:

uv run cc5x-helper packs-check
uv run cc5x-helper packs-update            # downloads newer .atpack archives
uv run cc5x-helper packs-update --dry-run  # preview without downloading
uv run cc5x-helper packs-update --family PIC16F1xxxx_DFP --force  # re-fetch one family

Both commands only ever run when you invoke them directly — no other command makes a network call on its own. Downloads land in ~/.cc5x/atpacks by default (already included in --dest's default and in discover_atpack_dirs()'s scan list, so a fresh download is picked up immediately by every other command); set CC5X_ATPACK_DIRS first to redirect them elsewhere, or pass --dest.

Automatic updates (opt-in). To stop checking manually, install a systemd --user timer that runs packs-update once a day (no sudo; only installed if you run this):

scripts/install-packs-autoupdate-timer.sh

This writes ~/.config/systemd/user/cc5x-packs-update.{service,timer}, enables the timer (OnCalendar=daily, RandomizedDelaySec=30min, Persistent=true so a missed run catches up after the machine was off), and downloads newer packs the same way the manual command above does. Check on it with:

systemctl --user list-timers cc5x-packs-update.timer
journalctl --user -u cc5x-packs-update.service

Uninstall with systemctl --user disable --now cc5x-packs-update.timer.

Environment variables

Variable Purpose
CC5X_COMPILER Path to CC5X.EXE (overrides the default repo path)
CC5X_RUNNER Launcher used to run the Windows compiler (e.g. wine {compiler} or a wrapper script; a bare interpreter needs the {compiler} placeholder)
CC5X_ATPACK_DIRS :-separated dirs containing Microchip.*.atpack archives; packs-update also downloads to its first entry
CC5X_PACK_ROOTS / MPLABX_PACKS :-separated roots of unpacked <family>/<version>/… pack trees
CC5X_IPECMD Path to ipecmd.sh/ipecmd.exe for the program command

Verify readiness

uv run cc5x-helper doctor

doctor reports discovered pack/device counts, the selected runner and compiler (and whether they exist), CrossOver/Wine status, and an overall ready flag.


Usage — CLI

Discover what is locally available:

uv run cc5x-helper list-devices --family 10F --family 16F
uv run cc5x-helper doctor

Inspect a device from the installed packs:

uv run cc5x-helper describe-device --device PIC16F1509

Generate a CC5X-style header straight from pack metadata:

uv run cc5x-helper render-pack-header --device PIC16F1509

Render a managed config block from pack metadata:

uv run cc5x-helper render-pack-config --device PIC16F1509 --include-defaults

Project workflow

The checked-in replacement for setcc.pxk is setcc-native.json (see Manifest reference).

# 1. Create a manifest
uv run cc5x-helper project-init --device PIC16F1509

project-init defaults the build entry point to src/main.c and scaffolds it with a minimal, non-empty starter (#include the device header + an empty main()) if it doesn't already exist yet — never overwrites a file you've started editing. An empty source is not just unhelpful: CC5X's Wine binary exits non-zero on a 0-byte file with no diagnostic text at all, which looks like a silent crash.

# 2. Validate it
uv run cc5x-helper project-validate

# 3. Sync the chosen edition's config into the source file
uv run cc5x-helper sync-config --project setcc-native.json --edition production

# 4. Build from the manifest
uv run cc5x-helper build --project setcc-native.json --edition production

Inspect and edit the manifest from the CLI:

uv run cc5x-helper project-list-editions
uv run cc5x-helper project-show --edition production
uv run cc5x-helper project-edit --header-mode existing --header-path include/16F1509.H

# Manage an edition's config symbols and build options:
uv run cc5x-helper project-set-config --edition production --set FOSC=INTOSC --set WDTE=OFF
uv run cc5x-helper project-set-build-options --edition production --option -a
uv run cc5x-helper project-edit-edition --edition release --copy-from production

Mutation commands reject changes the validator would refuse (e.g. an empty config value) without writing the manifest. Other read commands include describe-device, list-config, list-pack-config, probe, intellisense, debug-stub (generate the CDL debug/trace stub + map for a project), debug-monitor (decode a CDL capture into a named, timestamped trace), and artifacts — run uv run cc5x-helper --help for the full list.

Add --dry-run to build to print the compiler command line without running it, or --timeout-seconds N to abort the compiler after N seconds.

Programming a device (optional)

# Program the device's hex image via a PICkit 4 (default tool).
# Device-modifying actions confirm first — see "Confirmation" below.
uv run cc5x-helper program --project setcc-native.json --edition production

# Other operations and tools
uv run cc5x-helper program --action verify --device PIC16F1509 --hex build/app.hex --tool PK5
uv run cc5x-helper program --action erase --device PIC16F1509 --dry-run

--action accepts program / verify / erase / blank-check; --tool accepts IPECMD -TP codes (PK4, PK5, SNAP, ICD4). Use --ipe-arg to pass raw IPECMD flags (e.g. --ipe-arg=-W2.5 to power the target), --dry-run to preview the command, and --timeout-seconds N to abort IPECMD after N seconds.

Confirmation for device-modifying actions. program and erase write to the chip, so they require explicit authorization before running (verify / blank-check and any --dry-run are read-only and never prompt):

  • In an interactive terminal you are prompted to type yes to proceed.
  • Pass --yes to authorize without a prompt (use this in scripts).
  • In --json mode or a non-interactive shell there is no prompt: the command returns a confirmation_required error unless --yes is given.

The GUI and VS Code extension pass --yes automatically after their own "writes to hardware" confirmation; generated VS Code tasks omit it and prompt in the integrated terminal.

Programming without MPLAB — pk4prog (open source)

pk4prog/ is a self-contained Go programmer that drives a PICkit 4 / Snap directly over USB — no MPLAB IPE, no ipecmd, no Microchip account. It speaks the PICkit 4's reverse-engineered GEN4 script protocol, with the PIC16 ICSP command sequences ported from Microchip's own DFP scripts (see pk4prog/references/).

cd pk4prog
go build -o pk4prog ./cmd/pk4prog
./pk4prog id                          # read device ID
./pk4prog program --hex firmware.hex  # auto-erase, program, verify

Default target is PIC16F17146; PIC16F18456 is selectable with --device. For the PIC16F17146 Curiosity Nano board — including programming over its on-board nEDBG debugger (via open-source pymcuprog) instead of a standalone PICkit 4 — see pk4prog/docs/curiosity-nano.md.

Status: the GEN4 transport and DFP-derived command sequences are implemented and unit-tested, but hardware bring-up against real silicon is still pending — see pk4prog/TODO.md. Prefer the IPECMD program command above for known-good flashing until bring-up is complete.


Usage — Desktop GUI

uv run --extra gui cc5x-helper-gui
# or, from a packaged binary:
./dist/cc5x-helper-gui

Inside the GUI:

  • Help → Help Contents or F1 for the full new-user help system.
  • Help → Help For Current Tab or Shift+F1 for context help.
  • Each main tab also has its own Help button, plus a persistent Help tab.

The GUI exposes the same workflow in three tabs:

  • Environment — run doctor and browse local device-pack coverage
  • Devices — probe/describe a device, list config symbols, render headers and config blocks
  • Projects — create/load manifests, edit project fields, manage editions, sync config, launch builds

If a Linux desktop session forces an incompatible Qt platform theme:

QT_QPA_PLATFORM=xcb uv run --extra gui cc5x-helper-gui

Usage — VS Code extension

A VS Code extension lives in vscode/cc5x-vscode. It builds and programs projects by shelling out to this helper and to IPECMD.

Build and install it locally:

cd vscode/cc5x-vscode
npm install
npm run compile        # or: npx @vscode/vsce package  → cc5x-vscode-0.1.0.vsix

Then install the .vsix via Extensions → … → Install from VSIX, or run the extension from VS Code's Extension Development Host (F5).

The extension activates when the workspace contains setcc-native.json and adds the CC5X: commands Doctor, Build, Program Device, Create Project, Select Device, Edit Config, Sync Config, Generate Header, Refresh IntelliSense, Generate VS Code Tasks, Refresh Artifacts, Open Artifact, plus status bar widgets for Doctor (readiness), Build, and Program Device (one click each). Program Device shows a modal "writes to hardware" confirmation before flashing.

IntelliSense support goes beyond quieting false positives: it generates a clang VFS overlay that redirects the editor's C/C++ parser to a stripped, standard-C copy of the device header (CC5X's char LATC @ 0x1A; address-binding syntax has no standard-C equivalent) so the editor gets real type information for every register — without touching the file CC5X actually compiles. On top of that, an independent case-mismatch check flags any identifier whose lowercase form matches a declared register/bit but whose case doesn't (e.g. latc vs. LATC, which CC5X treats as different, undeclared symbols) and offers a "Change to 'X'" quick fix in either direction.

Workspace Trust required. Because the extension runs the workspace-configured Python interpreter, helper script, and IPECMD, it only operates in trusted workspaces. In an untrusted folder the commands are disabled until you trust it.

Relevant settings (cc5x.*): pythonPath, helperPath, manifest, programmerTool, ipecmdPath, commandTimeoutSeconds. You can also generate .vscode/tasks.json from the CLI:

uv run cc5x-helper vscode-tasks --project setcc-native.json --tool PK4

Manifest reference (setcc-native.json)

project-init writes a manifest like this:

{
  "version": 1,
  "device": "PIC16F1509",
  "compiler": "/path/to/CC5X/CC5X.EXE",
  "runner": "wine {compiler}",
  "mplab_root": null,
  "header": { "mode": "generated", "path": "generated_headers/16F1509.H" },
  "config_source": "src/main.c",
  "main_source": "src/main.c",
  "build_options": [],
  "editions": {
    "debug":      { "config": {}, "build_options": [] },
    "production": { "config": {}, "build_options": [] }
  }
}
Field Meaning
device Target PIC (e.g. PIC16F1509)
compiler Path to CC5X.EXE (defaults from CC5X_COMPILER)
runner Launcher for the Windows compiler (e.g. wine {compiler}; a bare interpreter needs the {compiler} placeholder)
header.mode generated (pack-derived), supplied, or existing
header.path Header file path used/produced for the build
header.bit_name_format Optional generated-header bit naming: combined (default), long (REGISTER_BIT), or short (BIT)
config_source / main_source File that receives synced config / the build entry point
build_options Extra CC5X flags applied to every edition
editions Named build variants, each with its own config map and build_options

The manifest can name arbitrary executables (compiler, runner), so treat it as trusted input — only build from manifests you control.


Packaging — single-file Linux executables

Built with uv + PyInstaller:

bash tools/build_linux_executable.sh          # CLI  → dist/cc5x-helper
bash tools/build_linux_executable.sh gui      # GUI  → dist/cc5x-helper-gui

Equivalent direct commands (PyInstaller version pinned for reproducible builds — see PYINSTALLER_VERSION in the script for the current value):

uv run --python 3.13 --with pyinstaller==6.21.0 pyinstaller \
  --onefile --name cc5x-helper --paths tools tools/cc5x_setcc_native.py

# --extra gui is required: without it uv builds in an env where the GUI entrypoint's
# `import PyQt6` is unresolved and PyInstaller bundles no Qt runtime.
uv run --python 3.13 --extra gui --with pyinstaller==6.21.0 pyinstaller \
  --onefile --name cc5x-helper-gui --paths tools tools/cc5x_helper_gui.py

Testing & validation

Unit tests (pytest is configured in pyproject.toml):

uv run --extra dev pytest

Lint:

uv run --extra dev flake8 tools tests

Real-compiler header validation (needs a working compiler + runner):

uv run python tools/validate_generated_headers.py --json
uv run python tools/validate_generated_headers.py --all-shipped --json
uv run python tools/validate_generated_headers.py --all-packs --json

Supported scope

This project targets CC5X-supported device families only. It does not claim PIC18 support.

Compiler-validated generated headers currently exist for:

  • PIC10F200, PIC10F320, PIC10F322
  • PIC12F1501, PIC12F1840
  • PIC16F1509, PIC16F15244, PIC16F15313, PIC16F1789, PIC16F18325, PIC16F18446, PIC16F18857, PIC16F19195

Validation uses the real CC5X.EXE under CrossOver/Wine.

For BKND-header parity work, --all-shipped expands the gate to every shipped PIC10F/PIC12F/PIC16F device header found under cc5x_paid/CC5X, compiling both the generated header and the shipped-header control for each device. Its exit status gates generated-header success; shipped-control failures are still reported in the JSON/text output as third-party header diagnostics.

--all-packs goes further: it enumerates every PIC10F/PIC12F/PIC16F device discoverable in local packs (not just the BKND-shipped subset) and compiles a generated header for each. See SUPPORT_MATRIX.md for current results (309/311 devices).


Repository layout

  • tools — helper CLI, GUI, and library code
    • packs.py — pack discovery, version selection, device lookup
    • picmeta.py — normalized parsing of .PIC, .ini, cfgdata
    • headergen.py — CC5X-style header and config-section generation
    • project.pysetcc-native.json manifest model and validation
  • tests — unit tests for pack parsing and project manifests
  • pk4prog — MPLAB-free open-source PICkit 4/Snap flasher (Go; GEN4 protocol) for enhanced-midrange PIC16F1xxxx
  • vscode/cc5x-vscode — VS Code extension
  • NATIVE_SETCC.md — operator notes and command examples
  • SUPPORT_MATRIX.md — validated devices and current project boundaries

Limitations

  • The generated-header parity gate covers the BKND-shipped flash PIC10F/PIC12F/PIC16F headers that map to pack metadata; older OTP/EPROM 12C/16C headers remain outside the pack-driven generator scope.
  • The manifest workflow covers the useful persisted state from setcc.pxk, not every GUI preference.
  • This repo does not bundle proprietary CC5X binaries or Microchip packs as tracked source files.

Acknowledgments & credits

The CC5X C compiler and its companion tool SETCC are the work of, and Copyright © B Knudsen Data, Norway, 1992 – 2026. CC5X.EXE, SETCC.EXE, the CC5X device headers (*.h), and the CC5X C dialect are proprietary products of B Knudsen Data — all rights reserved by their author. See https://www.bknd.com/ for licensing and the official distribution.

cc5x-helper is an independent, unofficial Linux workflow that drives the CC5X toolchain. It is not produced, endorsed, or supported by B Knudsen Data, and it neither includes nor redistributes any B Knudsen Data software. You must obtain CC5X.EXE (and any CC5X headers you reference) directly from B Knudsen Data under their license terms; this project only invokes the compiler you supply.

"CC5X" and "SETCC" are used here solely to identify the compatible upstream tools.

The device metadata this tool consumes — MPLAB® X, the ipecmd/IPE tooling, the PICkit™ programmers, and the Device Family Pack (.atpack/_DFP) archives with their .PIC/.ini/cfgdata contents — are products of, and Copyright © Microchip Technology Inc. cc5x-helper neither includes nor redistributes any Microchip software or device packs; you must obtain them separately from Microchip under their license terms, and this project only reads the packs you supply. PIC®, PIC10/PIC12/PIC16, MPLAB®, PICkit™, MPLAB SNAP, and related marks are trademarks or registered trademarks of Microchip Technology Inc. in the U.S.A. and other countries. All trademarks are the property of their respective owners. This project is not affiliated with, endorsed by, or supported by Microchip Technology Inc.

The cc5x-helper source in this repository is licensed under the MIT LICENSE and does not extend to any third-party CC5X or Microchip components.

About

Linux-native CC5X toolchain for PIC10F/12F/16F — pack-driven headers, managed #pragma config, Wine builds, and IPECMD flashing (CLI · GUI · VS Code)

Topics

Resources

License

Stars

1 star

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors