You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: BUILDING.md
+48-19Lines changed: 48 additions & 19 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -3,37 +3,66 @@
3
3
This document walks through producing firmware binaries locally or inside the provided Docker wrapper. It mirrors the instructions that formerly lived in `README.md`.
4
4
5
5
## Prerequisites
6
-
- ARM GCC 10.3.1 toolchain available on `PATH`.
7
-
- GNU Make.
8
-
- Python 3 with the `crcmod` module (only required for generating the packed image).
9
-
- Optional: Docker (for the reproducible build helper).
6
+
- Docker (recommended path; covers the compiler, python tooling, lint, and tests).
7
+
- For native builds only: ARM GCC 10.3.1 toolchain on `PATH`, GNU Make, Python 3 with `crcmod`, plus optional `cppcheck` and `pytest`.
10
8
11
-
## Standard Build
12
-
1. From the repository root clean any prior objects so size measurements stay accurate:
9
+
## Docker Build (recommended)
10
+
`./compile-with-docker.sh` produces the most reproducible binaries by packaging the entire toolchain and CI flow inside the container image.
11
+
12
+
1. From the repository root:
13
+
```sh
14
+
./compile-with-docker.sh
15
+
```
16
+
2. The script builds the Docker image, runs `ci/run.sh` inside the container (cppcheck + pytest + firmware build), and drops artifacts to `compiled-firmware/` on your host:
17
+
-`compiled-firmware/loaner-firmware.bin`
18
+
-`compiled-firmware/loaner-firmware.packed.bin`
19
+
20
+
If the script fails, inspect the console output; lint or unit test failures abort the build so issues are caught before you publish a release.
21
+
22
+
## Native Build (optional)
23
+
When you already have the toolchain locally, you can mirror the Docker steps:
24
+
25
+
1. Clean previous objects:
13
26
```sh
14
27
make clean
15
28
```
16
-
2. Build the firmware:
29
+
2. Build the firmware (the `TARGET` name controls the output filename):
17
30
```sh
18
-
make
31
+
make TARGET=loaner-firmware
19
32
```
20
-
The default target emits `loaner-firmware.bin`. If Python with `crcmod` is installed you will also get `loaner-firmware.packed.bin`.
33
+
The above command produces `loaner-firmware.bin`. If Python with `crcmod` is installed you will also get `loaner-firmware.packed.bin`.
34
+
If you omit `TARGET=...` the files are named `firmware.bin` / `firmware.packed.bin`.
21
35
22
36
## Creating a Packed Binary Manually
23
-
If the packed image was not produced automatically, run:
37
+
If the packed image was not produced automatically (for example on a minimal native setup), run:
24
38
```sh
25
-
python3 fw-pack.py loaner-firmware.bin AUTHOR VERSION loaner-firmware.packed.bin
- Choose a short author tag (defaults to `LOANER`) and a concise version string so the radio UI stays tidy.
29
-
- The packed image is preferred for PC loader flashing because it carries the metadata required by Quansheng’s tool.
42
+
- The second argument is the version tag embedded in both the welcome screen and the packed metadata.
43
+
Keep it under 10 ASCII characters (the script rejects longer strings).
44
+
- The packed image is required for PC loader flashing because it carries the metadata Quansheng's tool expects.
30
45
31
-
## Reproducible Docker Build
32
-
The repo includes a helper that wraps the GCC 10.3.1 toolchain inside Docker:
33
-
```sh
34
-
./compile-with-docker.sh
35
-
```
36
-
Artifacts are written to `compiled-firmware/loaner-firmware*.bin`.
46
+
## Running Lint and Tests
47
+
-`./compile-with-docker.sh` already executes `ci/run.sh`, so every Docker build runs cppcheck, pytest, and the firmware build in one shot.
48
+
- If you are working natively, `ci/run.sh` reproduces the same flow: it runs `cppcheck` with the project's suppressions, executes the Python unit tests, and builds the firmware with `TARGET=loaner-firmware`.
49
+
- To run individual pieces, consult the script for the exact command switches, then invoke:
50
+
```sh
51
+
cppcheck ... # optional, mirrors the flags in ci/run.sh
52
+
pytest # runs tests/test_fw_pack.py
53
+
make clean
54
+
make TARGET=loaner-firmware
55
+
```
56
+
- Keep an eye on the binary size reported by `arm-none-eabi-size` at the end of the build when you toggle features.
37
57
38
58
## Feature Toggles
39
59
Feature flags live near the top of `Makefile` as `ENABLE_*` macros. Adjust them to control optional modules, then rebuild. Run `make clean` before comparing binary size after any toggle changes.
60
+
61
+
## Firmware Metadata and Releases
62
+
- A successful build leaves you with `firmware.bin` (raw) and, when Python and `crcmod` are available, `firmware.packed.bin`. The packed image is what Quansheng's loader validates.
63
+
- Use `fw-pack.py` to stamp a release tag into the packed image. The second argument becomes the welcome banner and metadata field:
A stripped-down Quansheng UV-K5/K6 firmware build intended for radios that get passed around as loaners.
5
-
This fork keeps the core reliability fixes from the community projects while removing advanced features that could let a borrower wander into settings you would rather keep locked down.
4
+
A stripped-down Quansheng UV-K5/K6 firmware build intended for radios that get passed around as loaners. This fork keeps the community reliability fixes while removing configuration rabbit holes so a first-time user can turn the knob, press PTT, and get on the air.
5
+
6
+
The project also gives COML/COMT staff a predictable path from the ICS-205 form to a radio codeplug: program the memories in CHIRP, flash the loaner binary, and the handset stays aligned with the paperwork.
6
7
7
8
> **Warning**
8
9
> Flashing third-party firmware is always at your own risk. Test on non-critical hardware first and confirm RF behaviour before handing units out.
9
10
10
11
## Quickstart
11
-
1. Download the latest `loaner-firmware.packed.bin` from the project releases (or build it yourself—see `BUILDING.md`).
12
+
1. Download the latest packed release (`loaner-firmware.packed.bin`) from the Releases page.
12
13
2. With the radio powered off, hold the **PTT** and the **top side key** while turning it on. The display should stay blank, indicating the bootloader is active.
13
14
3. Connect the USB cable, open Quansheng's PC programming tool, select *Firmware Update*, point it at the packed image, and start the transfer.
14
-
4. After the loader reports success, power the radio off and back on to confirm the loaner splash/version string.
15
-
16
-
## Firmware Versioning
17
-
- Update the root `VERSION` file before cutting a release; the build picks up that value automatically (fallbacks still work if a version is supplied on the `make` command line instead).
18
-
-`make` combines `AUTHOR_STRING` and the version token so the welcome screen and UART banner both show something like `LOANER 0.1.0`.
19
-
-`fw-pack.py` embeds the same 16-byte tag inside the packed image, letting web flashers verify the build metadata.
20
-
21
-
## Goals
22
-
- Keep radios in channel-only mode with predictable controls.
23
-
- Ship a clearly branded binary so volunteers know they are flashing the loaner image.
24
-
- Stay close to upstream bug fixes while documenting the custom pieces that matter for the loaner program.
25
-
26
-
## Notable Differences From Full Builds
27
-
- VFO access is fully disabled (menu item removed and EEPROM flag forced off).
28
-
- Long-press actions that could restore VFO/MR mode are stripped.
29
-
- Menu layout retains only what is required for the channel-only workflow.
30
-
- Default key text, version strings, and build artifacts are renamed to highlight the loaner focus.
31
-
- Number keys recall the first ten programmed MR channels directly; the legacy F+digit functions are disabled.
32
-
- Side buttons are fixed: the top selects VFO A, the bottom selects VFO B (short or long press).
33
-
- The physical menu key is disabled so borrowers cannot enter configuration screens.
34
-
- Main display always shows channel names instead of raw frequencies.
15
+
4. After the loader reports success, power the radio off and back on to confirm the welcome screen shows the release tag from the packed image.
16
+
5. Spin the channel knob and verify that the loaner channel names appear as expected.
17
+
18
+
## Design Goals
19
+
- Put channel-only handsets in the hands of volunteers who have minimal or no radio training.
20
+
- Give COML/COMT staff an efficient way to push an ICS-205 channel plan onto the radios using CHIRP.
21
+
- Track upstream bug fixes while documenting the toggles that keep the loaner build focused and predictable.
22
+
23
+
## Loaner Feature Highlights
24
+
- Channel knob only: the firmware boots into MR mode and ignores attempts to switch into VFO.
25
+
- Hardened menu: configuration items that could drift from the loaner plan are removed or disabled.
26
+
- Friendly prompts: welcome banner, battery indicator, and RSSI display identify the handset as a loaner and keep checks simple.
27
+
- Consistent keypad: digits recall the first ten memories, side buttons select the active VFO, and Menu is locked out.
28
+
29
+
## Programming Channel Plans With CHIRP
30
+
This build assumes the channel plan lives on your ICS-205. To move that plan into a radio:
31
+
32
+
1. Prepare the ICS-205 so each channel has a concise label (CHIRP shows up to seven characters by default).
33
+
2. Launch CHIRP, connect the radio, and use `Radio -> Download From Radio` once to confirm the driver handshake.
34
+
3. Use `File -> Import` to pull in either a CSV exported from your ICS-205 or an existing `.img` template. Map the columns to CHIRP's `Name`, `Frequency`, `Tone Mode`, and `Tone` fields.
35
+
4. Sort the memories into the order that matches your loaner numbering, then `File -> Save As` to keep the template for the next deployment.
36
+
5. Upload the plan with `Radio -> Upload To Radio`. After the radio reboots, rotate the channel knob and verify that the display shows the ICS-205 names.
37
+
6. Repeat for each handset; the standard workflow keeps the handset in channel mode, so operators only see the memories you defined.
38
+
39
+
Tip: Keep a CHIRP image with the baseline loaner plan in source control so teams can diff changes before distributing updates.
35
40
36
41
## Flashing
37
42
### Quansheng PC Loader (recommended)
38
43
1. Install Quansheng's UV-K5/K6 programming utility if it is not already on your workstation.
39
-
2. Copy `loaner-firmware.packed.bin` locally—the packed image carries the metadata the loader validates.
40
-
3. With the radio powered off, hold **PTT** + **top side key** and power it on to enter the firmware download mode (the screen remains blank).
44
+
2. Copy the packed binary locally - the metadata is required by Quansheng's loader.
45
+
3. With the radio powered off, hold **PTT** + **top side key** and power it on to enter firmware download mode (the screen remains blank).
41
46
4. Connect the USB cable (CH340 driver) and confirm the loader detects the serial port.
42
47
5. Choose *Firmware Update*, select the packed binary, and start the process. Do not disconnect power until the loader reports completion.
43
48
6. Power-cycle the radio and confirm the loaner splash/version text is displayed.
@@ -51,17 +56,16 @@ This fork keeps the core reliability fixes from the community projects while rem
51
56
```
52
57
4. Use `make debug` afterwards if you need an interactive OpenOCD session.
53
58
54
-
## Building From Source
55
-
Detailed build and packaging steps now live in `BUILDING.md`. Use that document when you need to regenerate or customize the binaries.
59
+
## Field Notes
60
+
- Carry one handset that stayed stock as a control; it helps confirm the loader steps when training new volunteers.
61
+
- Log which firmware release you flashed (the welcome banner shows the tag) alongside the ICS-205 so future updates are easy to track.
62
+
- If a user reports odd audio or RF behaviour, power cycle and reseat the battery first; the firmware keeps settings read-only so faults are usually hardware.
56
63
57
-
### Automated Checks
58
-
-`./compile-with-docker.sh` builds with the pinned toolchain and drops binaries under `compiled-firmware/`.
59
-
-`python3 ci/check_firmware.py` fails if code size grows past the loaner budget or if the branding banner changes unexpectedly.
60
-
-`python3 ci/test_chirp.py` confirms CHIRP compatibility. It verifies that the required `ENABLE_*` flags stay enabled, checks that CHIRP’s UV-K5 driver still whitelists the Loaner banner, and exercises the driver against the synthetic EEPROM image in `ci/synthetic_eeprom.bin` to ensure firmware options decode correctly.
64
+
## Need to Modify the Firmware?
65
+
All developer-facing build and packaging details live in `BUILDING.md`. Start there if you need to regenerate binaries or adjust feature toggles.
61
66
62
67
## Contributing
63
-
Open issues or PRs if you spot regressions that impact the loaner workflow.
64
-
When adding optional features, gate them behind new `ENABLE_*` toggles so the default build stays minimal.
68
+
Open issues or PRs if you spot regressions that impact the loaner workflow. Documentation updates (especially CHIRP workflows and loaner field notes) are welcome.
65
69
66
70
## Project Backlog Snapshot
67
71
-`docs/issues/issue-export.json` captures the high-level loaner backlog for offline reference.
@@ -71,8 +75,8 @@ When adding optional features, gate them behind new `ENABLE_*` toggles so the de
71
75
Based on the open-source efforts by DualTachyon, OneOfEleven, Fagci, and the wider UV-K5 community. This fork simply repackages their work for the loaner-radio use case.
72
76
73
77
## License
74
-
Licensed under the Apache License 2.0. See `LICENSE` for details.
75
-
Copyright 2023 Dual Tachyon
78
+
Licensed under the Apache License 2.0. See `LICENSE` for details.
79
+
Copyright 2023 Dual Tachyon
76
80
https://github.com/DualTachyon
77
81
78
82
Licensed under the Apache License, Version 2.0 (the "License");
@@ -81,8 +85,8 @@ You may obtain a copy of the License at
81
85
82
86
http://www.apache.org/licenses/LICENSE-2.0
83
87
84
-
Unless required by applicable law or agreed to in writing, software
85
-
distributed under the License is distributed on an "AS IS" BASIS,
86
-
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
87
-
See the License for the specific language governing permissions and
88
-
limitations under the License.
88
+
Unless required by applicable law or agreed to in writing, software
89
+
distributed under the License is distributed on an "AS IS" BASIS,
90
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
91
+
See the License for the specific language governing permissions and
0 commit comments