Quansheng UV-K5 · Volume 7
Quansheng UV-K5 Volume 7 — Channel Plans & Programming
CHIRP and the UV-K5 driver, the fork-specific modules, the EEPROM memory map, k5prog read/write, the CSV channel-plan layout, and a worked channel-plan build
7.1 About this Volume
Flashing (Volume 6) gives the radio new capabilities; programming gives it a job. A channel plan is the list of frequencies, tones, modes, and names the radio switches between on the belt — the thing that turns a bare receiver into “scan the local repeaters, the marine channels, and the airport approach.” This volume covers the two paths into the radio’s channel memory: CHIRP, the cross-platform GUI that most people use for bulk channel editing, and k5prog, the command-line EEPROM tool that is the right choice for backups and scripted plans.
A deliberate boundary: this is the programming mechanics volume — how channel data is laid out, read, edited, and written back. For the operational side of channel planning — which repeaters to load, how net schedules and CTCSS tones work, band-plan etiquette, licensing — the peer Scanners project (../Scanners/) is the depth reference, and this volume cross-references it rather than duplicating amateur-radio operation. What stays here is the hacking-adjacent material: the EEPROM memory map, the backup-before-you-break discipline, and the calibration region you must never overwrite.
Cross-references: Volume 6 covered flashing and the one-command EEPROM backup this volume depends on; Volume 4 compares the forks whose CHIRP modules §3 describes; the spectrum/RX-unlock material is in Volume 5.
7.2 CHIRP and the UV-K5 driver
CHIRP is the long-standing, open-source, cross-platform radio programmer. Its modern line, CHIRP-next (Python 3, continuously built), carries a Quansheng UV-K5 family driver that also covers the UV-K5(8) and UV-K6. CHIRP talks to the radio over the normal programming cable while the radio is running its firmware (this is not the bootloader path of Volume 6 — the radio is powered on normally).
CHIRP download-from-radio workflow:
1. Radio ON (normal mode), cable connected, radio in its idle/VFO screen.
2. CHIRP → Radio → Download From Radio.
3. Pick the serial port (CH340/CP2102/PL2303) and the model:
"Quansheng UV-K5 / UV-K5(8) / UV-K6".
4. CHIRP reads the whole EEPROM image and renders it as an editable memory grid.
5. Edit cells → Radio → Upload To Radio → CHIRP writes the channels back.
CHIRP presents the radio as a grid: one row per memory channel, columns for frequency, name, mode, tones, and so on (§6 lists them). Under the hood CHIRP is reading and writing the same EEPROM bytes k5prog touches (§5); the difference is presentation — a spreadsheet instead of a hex dump.
Note — use CHIRP-next, and keep it current. The UV-K5 driver and its handling of the custom firmwares evolve; the continuously-built CHIRP-next is the one that tracks them. The old stable “CHIRP legacy” builds predate much of this support. If a download reads garbage or the model is missing from the list, a stale CHIRP is the first suspect.
7.3 Fork-specific CHIRP modules (F4HWN / egzumer)
The complication the custom firmwares introduce: each fork adds settings beyond stock — extra RX modes, battery-display style, the spectrum/RX feature toggles of Volume 5, backlight behaviour — and those settings live in EEPROM regions the stock CHIRP driver does not know about. To expose them, the forks publish CHIRP driver modules (loadable .py driver plugins) tailored to that fork’s EEPROM layout.
Table 1 — 3. Fork-specific CHIRP modules (F4HWN / egzumer)
| Firmware | CHIRP support | What the fork module adds over the stock driver |
|---|---|---|
| Stock Quansheng | Built-in CHIRP-next UV-K5 driver | Channels, names, tones, basic settings |
| egzumer v0.22 | egzumer-provided CHIRP driver module | Channels + egzumer’s extended settings (band/scanlist flags, feature toggles) |
| F4HWN “Fusion” | F4HWN-provided CHIRP driver module | Channels + F4HWN’s extended settings (RX modes, SET menus, display options) |
Loading a fork CHIRP module:
1. Download the fork's CHIRP driver .py from its repo/release.
2. CHIRP-next → Help → Load Module (developer feature).
3. Select the .py → CHIRP gains that fork's radio model in the model picker.
4. Download From Radio using the fork model → the extended settings appear
on the Settings tabs.
Callout — match the module to the firmware on the radio. A fork’s CHIRP module assumes that fork’s EEPROM layout. Loading egzumer’s module against a radio running F4HWN (or the stock driver against a fork that moved settings) can mis-map the settings region. Channels are laid out compatibly enough that the stock driver usually reads them from any fork; it is the settings that are fork-specific. Rule of thumb: use the stock driver for channel edits, the matching fork module when you want the fork’s extra settings.
7.4 The EEPROM memory map at a high level
The UV-K5 keeps its channels, settings, and factory calibration in an external I²C EEPROM — on stock radios an 8 KiB part (64 kbit class). This is distinct from the MCU flash that holds firmware (Volume 6); flashing firmware and programming channels touch different memories on the same cable. The map below is the high-level community-reverse-engineered picture — enough to reason about what a tool is touching, not a byte-exact register sheet.
Table 2 — 4. The EEPROM memory map at a high level
| EEPROM region (approx.) | Contents | Safe to edit? |
|---|---|---|
Low region (0x0000…) | Channel RF data — 200 channels × 16 bytes: frequency, offset/duplex, CTCSS/DCS tones, modulation (FM/AM/SSB on capable forks), bandwidth, TX power, flags | Yes — this is what CHIRP/k5prog channel edits change |
| Mid region | Channel attributes (band index, scanlist membership) and channel names (one name block per channel) | Yes — names and scanlist flags |
| Settings region | Global settings: squelch, backlight, VFO state, DTMF, boot message, and fork-specific feature toggles | Yes, but fork-dependent (§3) |
High region (…0x1FFF) | Factory calibration — per-band TX power, squelch thresholds, RSSI/battery calibration, frequency/crystal trim | NO — never overwrite (§9) |
Two practical consequences:
- Channels and calibration share one 8 KiB chip. A full EEPROM backup (§5) captures both. That is why a pre-flash backup matters: it preserves calibration, which is unique to each physical radio and not downloadable.
- More channels = bigger EEPROM. Because the stock chip is only 8 KiB, the 200-channel ceiling is a storage limit, not a firmware limit. A known hardware mod (Volume 9) swaps in a larger EEPROM so a capable firmware can address far more channels. On the stock chip, 200 is the number.
Note — “high level” is deliberate. Exact offsets drift between firmware forks (each reorganises the settings region). Treat the region table as a map of what kind of data lives where, and let CHIRP/the fork module handle exact offsets. The one offset fact worth memorising is directional: calibration lives at the top of the EEPROM, and you leave it there (§9).
7.5 k5prog memory read and write
k5prog reads and writes the EEPROM over the normal (non-bootloader) serial protocol. It is the backup tool, the scripting tool, and the “I want the raw bytes” tool. The flags shown are representative; confirm exact syntax against the sq5bpf k5prog README.
# BACK UP the full EEPROM (channels + settings + calibration) to a file.
# Do this BEFORE your first flash (Vol 6 §9) and before any risky edit.
./k5prog -p /dev/ttyUSB0 -r -b eeprom_backup_$(date +%Y%m%d).raw
# RESTORE the EEPROM from a backup (recovers channels AND calibration).
./k5prog -p /dev/ttyUSB0 -w -b eeprom_backup_20261017.raw
# The radio is in NORMAL mode for EEPROM work (contrast: bootloader mode for -F firmware flashing, Vol 6).
Table 3 — The radio is in NORMAL mode for EEPROM work (contrast: bootloader mode for -F firmware flashing, Vol 6).
| Task | Tool of choice | Why |
|---|---|---|
| Bulk channel editing by hand | CHIRP | Spreadsheet UI, validation, named columns |
| Full backup / restore (incl. calibration) | k5prog | One command captures the whole 8 KiB as a file |
| Scripted / programmatic channel injection | k5prog or CHIRP’s Python API | Repeatable, no GUI; feed a generated CSV/image |
| Cloning a plan across several radios | Either | Read once, write to each (calibration differs — see §9) |
Callout — a backup is a single file. The entire radio’s channel memory, settings, and calibration fit in an 8 KiB file. Keep a dated backup per radio in version control or a notes folder. Recovering a radio to a known channel plan is then a single
-wwrite, and recovering calibration (the irreplaceable part) comes free with it.
7.6 The CSV channel-plan layout
CHIRP’s portable interchange format is CSV — a plain text row per channel. Exporting to CSV lets you edit a plan in a spreadsheet or generate it from a script (e.g. pull repeaters from a database and emit rows), then import it back. The columns that matter for a UV-K5 plan:
Table 4 — CHIRP's portable interchange format is CSV — a plain text row per channel. Exporting to CSV lets you edit a plan in a spreadsheet or generate it from a script (e.g. pull repeaters from a database and emit rows), then import it back. The columns that matter for a UV-K5 plan
| CSV column | Meaning | Example |
|---|---|---|
Location | Memory channel number (slot) | 1 |
Name | Channel label shown on the radio | W1AW |
Frequency | RX frequency (MHz) | 146.520000 |
Duplex | Offset direction for TX: +, -, or blank (simplex) | - |
Offset | Repeater offset (MHz) | 0.600000 |
Tone | Tone mode: Tone, TSQL, DTCS, or blank | TSQL |
rToneFreq / cToneFreq | CTCSS transmit / receive tone (Hz) | 100.0 |
DtcsCode | DCS code when Tone=DTCS | 023 |
Mode | Modulation: FM, NFM (narrow), AM, and USB/LSB/SSB on capable forks | FM |
TStep | Tuning step (kHz) | 12.5 |
Skip | Scan skip flag (S to skip) | (blank) |
Power | TX power level | High |
Comment | Free text (not stored on radio) | 2m calling |
Location,Name,Frequency,Duplex,Offset,Tone,rToneFreq,cToneFreq,DtcsCode,Mode,TStep,Skip,Power,Comment
1,Calling2m,146.520000,,,,88.5,88.5,023,FM,12.5,,High,2m simplex calling
2,Repeater,147.000000,+,0.600000,TSQL,100.0,100.0,023,FM,12.5,,High,example repeater
3,WX1,162.550000,,,,88.5,88.5,023,NFM,12.5,S,Low,NOAA weather RX only
4,Airband,118.100000,,,,88.5,88.5,023,AM,25.0,,Low,tower RX (AM mode, RX only)
Note — RX-only channels still need a sane TX setup. For receive-only entries (weather, airband, public-safety where legal to monitor), set a low TX power and/or mark them so you never key up on them. The modulation column is where the custom firmware earns its keep:
AMfor airband,SSBon forks that implement it (Volume 5) — modes the stock firmware cannot select.
7.7 Importing and exporting
CHIRP treats CSV, the radio, and its own .img files as interchangeable sources you move channels between:
┌──────────────┐ Download From Radio ┌──────────────┐
│ The radio │ ─────────────────────▶ │ CHIRP grid │
│ (EEPROM via │ ◀───────────────────── │ (in memory) │
│ the cable) │ Upload To Radio └──────┬───────┘
└──────────────┘ │
Import / Export CSV │ Save .img
▼
┌──────────────┐ ┌──────────────┐
│ plan.csv │ │ plan.img │
│ (spreadsheet/ │ │ (CHIRP native │
│ scriptable) │ │ EEPROM image)│
└──────────────┘ └──────────────┘
- Export CSV (
File → Export) to edit a plan outside CHIRP or generate it programmatically, then Import CSV (File → Import) back into a memory grid. - Save a
.imgto keep CHIRP’s native snapshot of the whole radio image (closer to the raw EEPROM than CSV, which only captures channel fields). - Cross-radio copy: import one radio’s CSV into another radio’s grid to clone a channel plan — but calibration is not carried this way, which is correct (§9).
Callout — CSV is channels,
.img/EEPROM-backup is everything. CSV captures the channel list and is the right format for editing and scripting. It does not capture calibration or every fork-specific setting. For a true backup use CHIRP’s.imgor ak5prog -rEEPROM dump (§5). Use the right one for the job: CSV to build a plan, EEPROM dump to protect the radio.
7.8 A worked example — building a channel plan
A realistic end-to-end build: produce a small plan in a spreadsheet, import it, and write it to the radio — preserving calibration throughout.
WORKED EXAMPLE — build & load a channel plan
─────────────────────────────────────────────────────────────
STEP 0 BACK UP FIRST (Vol 6 §9, this Vol §5):
./k5prog -p /dev/ttyUSB0 -r -b backup_before.raw
→ captures channels + calibration. If anything goes wrong, -w restores it.
STEP 1 AUTHOR the plan as CSV (§6). Build it in a spreadsheet or generate it:
- rows 1–30: local 2 m / 70 cm repeaters (Duplex/Offset/Tone per repeater)
- rows 31–40: simplex + calling channels (no offset)
- rows 41–50: RX-only monitoring (airband AM, weather NFM) — low power, Skip as wanted
Save as plan.csv.
STEP 2 LOAD into CHIRP:
- CHIRP-next → Radio → Download From Radio (get the radio's CURRENT image,
so you edit a real image rather than a blank one — preserves settings)
- File → Import → plan.csv → the channel rows populate the grid
- fix any cells CHIRP flags (tone mode mismatches, out-of-range freqs)
STEP 3 VERIFY in the grid:
- frequencies, offsets, tones, modes correct?
- RX-only channels marked / low power?
- names ≤ the radio's name length?
STEP 4 WRITE to the radio:
- Radio → Upload To Radio
- CHIRP writes the channel + settings regions; it does NOT touch calibration
STEP 5 CONFIRM on the radio:
- cycle through the new channels; check a known repeater opens with its tone
- run a scan across the scanlist to confirm skip flags behave
(Optional) Snapshot the finished plan: ./k5prog -p /dev/ttyUSB0 -r -b plan_loaded.raw
─────────────────────────────────────────────────────────────
Note — edit a downloaded image, not a blank one. Always
Download From Radiobefore importing a CSV, so your edits land on top of the radio’s current settings image. Importing a CSV into an empty document and uploading that can wipe settings you wanted to keep. The CSV carries channels; the downloaded image carries everything else.
For the content of a good plan — which repeaters, net times, tone conventions, scanning strategy, licensing — see the peer Scanners project (../Scanners/); this volume stops at the mechanics of getting a plan into the radio.
7.9 The calibration region — leave it alone
The top of the EEPROM holds factory calibration: per-band TX power tables, squelch thresholds, RSSI and battery calibration, and frequency/crystal trim. These values are measured and written per individual radio at the factory. They are not downloadable, not interchangeable between units, and not something a channel plan should ever touch.
Table 5 — 9. The calibration region — leave it alone
| Fact | Consequence |
|---|---|
| Calibration is per-radio and factory-measured | You cannot “get it back” from the internet; a backup is the only copy |
| It lives in the high EEPROM region | A full k5prog -r dump or CHIRP .img captures it; a CSV does not |
| CHIRP channel/settings uploads don’t touch it | Normal programming is safe; only a raw full-EEPROM write could clobber it |
| Custom firmware flashing (Vol 6) doesn’t touch it | Firmware is MCU flash; calibration is the separate EEPROM |
Hard rule. Never write a full EEPROM image from another radio onto this one, and never zero/erase the EEPROM wholesale. Both overwrite calibration with wrong or blank values, and the symptoms — off TX power, broken squelch, skewed S-meter, frequency error — look like a hardware fault but are self-inflicted. If you ever do clobber it, the
k5prog -wrestore from this radio’s own backup (§5) is the fix, which is the whole reason §8 Step 0 exists.
Callout — cloning plans is fine; cloning whole radios is not. Copying a channel plan between radios (via CSV, §7) is safe because CSV carries no calibration. Copying a full EEPROM image between radios is the mistake — it drags one radio’s calibration onto another. Clone plans, never raw images, across units.
7.10 Pitfalls and gotchas
Table 6 — 10. Pitfalls and gotchas
| Pitfall | Symptom | Fix |
|---|---|---|
| Stale CHIRP | UV-K5 model missing, or download reads garbage | Use current CHIRP-next, not legacy builds |
| Wrong fork module | Extended settings mis-mapped / nonsense values | Match the CHIRP module to the firmware; use the stock driver for channels |
| Imported CSV into a blank doc | Settings wiped after upload | Download From Radio first, import CSV onto that image, then upload |
| Overwrote calibration | Off TX power, bad squelch, skewed S-meter | k5prog -w restore from this radio’s own backup (§5, §9) |
| Cloned a full image across radios | Second radio mis-calibrated | Clone the plan (CSV), never the raw EEPROM image |
| Name too long | Channel name truncated on the radio | Keep names within the radio’s name-field length |
| TX enabled on RX-only channels | Risk of keying up out of band (Vol 10) | Mark monitoring channels, set low power, know which bands you may transmit on |
| No backup before editing | A bad write is unrecoverable | Always k5prog -r a dated backup first (§5, §8 Step 0) |
See Volume 6 for flashing and the pre-flash EEPROM backup this volume relies on, Volume 5 for the spectrum/RX-unlock features that make AM/SSB channels useful, Volume 4 for the fork comparison behind the CHIRP-module choice, and the peer Scanners project for channel-plan content and amateur-radio operation.
Comments (0)