diff --git a/.claude/skills/jeti-voice/SKILL.md b/.claude/skills/jeti-voice/SKILL.md new file mode 100644 index 0000000..d4958dc --- /dev/null +++ b/.claude/skills/jeti-voice/SKILL.md @@ -0,0 +1,142 @@ +--- +name: jeti-voice +description: Generate spoken voice callouts (WAV files) for a JETI Lua app in this repo with Piper's "Amy" voice, so every app sounds the same. Use this whenever an app needs new speech or audio files: callouts, announcements, warnings, alarms, "say X when Y", voice prompts for a switch, or regenerating/changing an existing app's voice. Also use it when wiring those files into an app (playFile, file checks, fallbacks) or into the transmitter's Sounds on event, and for the license credits the voice requires. +--- + +# JETI voice callouts + +Every app in this repo speaks with one voice: Piper text-to-speech with the +US English **"Amy"** model (`en_US-amy-medium`). Speed Gauge (`AG-SpdGa`), +Flameout Alarm (`AG-FlmOt`) and Throttle Setup Wizard (`AG-TrbSt`) all use +it. New callouts should too, so a pilot hears one consistent system. + +The generators live in `tools/voice/`. They share `make_voice.py`'s helpers; +each app has its own small script. Read `tools/voice/README.md` for the +history and options of the existing ones. + +## 1. Decide the phrases + +For each callout, settle: + +- **The words**, short and unambiguous over engine noise. Two to four words + is typical ("Turbine off", "Engine relit"). +- **The file name**: 8.3, e.g. `TurbOff.wav`. JETI names are short, and if + the pilot will pick the file in a transmitter menu, the name should say + what it is. +- **The delivery**: + - *Calm* (announcements, confirmations): no effects. Speed 1.5 suits + timed callouts that must be short (Speed Gauge's numbers, Flameout's + announcements); for single switch callouts Aaron preferred **1.15** + (`make_turbine.py`). When in doubt, generate a few speeds into a + scratch folder and let the user pick by ear. + - *Urgent* (alarms): pitch-up, presence boost and compression, optionally + with a lock tone and fixed-length cycles. Example: `make_flameout.py`. +- **A length limit** for the self-check, from how the app uses it (e.g. a + switch callout should end before the next flick: about 1.5 s; Speed + Gauge's numbers must fit 1.3 s). +- **Where it plays**: from the app (`system.playFile`), or by the + transmitter's *Sounds on event* (the app only copies the files to + `/Audio`, see section 5). + +Agree these with the user before generating; they'll listen to the result. + +## 2. Write the generator + +Create `tools/voice/make_.py` by copying the closest existing script: + +- `make_turbine.py`: the minimal template (a list of phrases, calm pace, + `CREDITS.txt`, a length self-check). Start here for most apps. +- `make_flameout.py`: urgent delivery (filters, compressor), a synthesized + tone, and assembling exact-length cycles. + +Keep these conventions, which the existing scripts share: + +- MIT header (`Copyright (c) 2026 Aaron George`, `SPDX-License-Identifier: + MIT`) and a docstring naming the files it writes and the spec/FR they + serve. +- Import the helpers from `make_voice.py` (`synthesize`, `trim`, + `normalize`, `resample`, `write_wav`, `write_text`, `PEAK`) by adding + `tools/voice` to `sys.path`. **Don't modify `make_voice.py`**: Speed + Gauge's 512 files depend on it. +- Arguments: `--model` (required), `--out` (default + `src/Apps/AG-xxxxx`), `--rate` (default 22050), and `--speed` if the + pace may need tuning. +- Output: mono, 16-bit, 22.05 kHz WAV, trimmed of silence (20 ms kept), + peak-normalized to −1 dBFS. The DS-24 II plays this format (verified + with Speed Gauge, 2026-10-03). +- Write `CREDITS.txt` into the output folder (copy the text from an + existing script and change the app name and the list of processing). +- Self-check at the end: every file exists and fits its length limit. + Exit 1 on failure. +- Files go in the app's own asset folder, `src/Apps/AG-xxxxx/` + (constitution V). Code refers to them as `/Apps/AG-xxxxx/`. + +Check it compiles: `python -m py_compile tools/voice/make_.py`. + +## 3. Generate + +Piper is installed from `tools/voice/requirements.txt` +(`python -m pip install -r tools/voice/requirements.txt`). The voice model +is **not** in the repo: `en_US-amy-medium.onnx` and its `.onnx.json` live +in a folder outside it (download from Hugging Face, +`rhasspy/piper-voices`, `en/en_US/amy/medium/`). Ask the user for the path +if you don't know it, then run: + +```powershell +python tools/voice/make_.py --model C:\path\to\en_US-amy-medium.onnx +``` + +Piper varies slightly between runs. If a length check fails, raise +`--speed` a little (e.g. 1.55) rather than loosening the limit. + +## 4. Review and commit + +- **The user listens on the PC first.** Same voice and pace as the other + apps? Only they can approve it; leave that task unticked until they do. +- **Commit the generated files** with the app (they're part of the + install). They are licensed **CC BY-SA 4.0**, not MIT. +- **Credit the voice everywhere constitution VIII requires**: the asset + folder's `CREDITS.txt`, `CREDITS.md` (add a section for the app), the + README's app section, and the app's own settings or info screen (a + `FONT_MINI` line such as "Voice: Piper, Amy (CC BY-SA 4.0)."). +- Add a section for the new script to `tools/voice/README.md`. + +## 5. Use the files in the app + +**Played by the app** (Speed Gauge, Flameout Alarm): + +- `system.playFile("/Apps/AG-xxxxx/file.wav", AUDIO_QUEUE)` or + `AUDIO_IMMEDIATE` for alarms (it cuts in over other speech). Foreground + playback is WAV only. +- **Check the files exist in `init()`**, not per play: `io.open` the + absolute path, then the same path without its leading "/" (the JETI + Studio emulator needs relative paths; the transmitter takes absolute + ones). Close what you open. +- **If files are missing, degrade quietly**: skip the callout or fall back + (Flameout uses beeps), and say so on the settings screen. Never error. + +**Played by the transmitter's Sounds on event** (Throttle Setup Wizard): + +- The app never plays them. It copies them from its asset folder to + `/Audio` on the pilot's request (JETI's audio picker lists `/Audio` and + `/Audio/`), never overwriting an existing file, in small chunks + across `loop()` calls, verifying the size and deleting a bad copy. Then + it opens the menu with `system.openExternal(":soundEvent")` and says what + to assign. See `src/Apps/AG-TrbSt.lua` (Voice callouts) and research R15 + in `specs/002-turbine-throttle-setup/research.md`. +- This keeps callouts working after the app is removed from the model, and + existing assignments stay visible in JETI's own menu. + +## 6. Test where sound actually plays + +The JETI Studio emulator plays **no** Lua audio (`playFile` is silent; the +Emulated Telemetry app just prints a line). So: + +- In the emulator, check only the logic: file found / missing messages, + which file would play. +- On the transmitter, check that each file plays, sounds right, and isn't + cut off, and (for Sounds on event) that the picker lists the files. + These are MANUAL tasks for the user. + +Record anything new about playback or file handling in +`docs/jeti-api-notes.md`. diff --git a/.gitignore b/.gitignore index a4e05a2..044856f 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,7 @@ venv/ # Local JETI Studio test source (tools/publish/make_apps_json.py --local) Apps.local.json + +# Model files copied from the transmitter (contain transmitter and receiver IDs) +docs/examples/models/ +docs/examples/*.jsn diff --git a/CLAUDE.md b/CLAUDE.md index df94b99..0030053 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -17,6 +17,7 @@ other work. Remove an item once he says it's done. | App (menu name) | Script | Spec | Based on | | --- | --- | --- | --- | | Speed Gauge | `src/Apps/AG-SpdGa.lua` | `specs/001-speed-gauge/` | DFM Speed Announcer (Dave McQueeney, MIT) | +| Throttle Setup Wizard | `src/Apps/AG-TrbSt.lua` | `specs/002-turbine-throttle-setup/` | original | | Flameout Alarm | `src/Apps/AG-FlmOt.lua` | `specs/003-flameout-alarm/` | original | Keep this table current when an app is added. @@ -52,6 +53,9 @@ or shorten an existing credit or license notice. structure. - `src/Apps/lib/`: shared modules. Check here before writing a helper another app may already have. +- Voice callouts or other speech files: follow the `jeti-voice` skill + (`.claude/skills/jeti-voice/`) so every app uses the same Piper "Amy" + voice, file format and credits. ## Layout and naming (constitution V and VII) diff --git a/CREDITS.md b/CREDITS.md index 882d561..be06ca9 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -103,6 +103,22 @@ from Thomas Ekdahl's Jeti ECU telemetry app ([thomasekdahlN/jeti](https://github.com/thomasekdahlN/jeti)), which was studied for facts only; none of its code is used. +## Throttle Setup Wizard voice callouts — Piper and the "Amy" voice + +Throttle Setup Wizard (`AG-TrbSt`) is original work; no code comes from +another app. Its optional switch callouts, "Turbine off" and "Turbine on", +use the same **Piper** engine and **"Amy"** (`en_US-amy-medium`) voice +model by **Mycroft / Rhasspy** as Speed Gauge's voice, credited above, +generated by [`tools/voice/make_turbine.py`](tools/voice/README.md) at the +same calm pace (sped up, trimmed and peak-normalized). + +The generated files are in +[`src/Apps/AG-TrbSt/`](src/Apps/AG-TrbSt/) and are licensed **CC BY-SA 4.0** +(Amy model), not MIT; that folder's `CREDITS.txt` carries the attribution. +The app copies them to the transmitter's `/Audio` folder only when the pilot +asks, for use in the transmitter's Sounds on event. No Piper code is part of +this repository or of the app. + ## JETI model official demos [`docs/examples/jeti-demos/`](docs/examples/jeti-demos/) holds unmodified demos diff --git a/README.md b/README.md index 11f988a..c123960 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,7 @@ spec-driven workflow (GitHub Spec Kit + Claude Code) in VS Code. | --- | --- | --- | --- | --- | | Speed Gauge | [`AG-SpdGa.lua`](src/Apps/AG-SpdGa.lua) | Released (0.3.0) | [001](specs/001-speed-gauge/spec.md) | DFM Speed Announcer by Dave McQueeney (MIT) | | Flameout Alarm | [`AG-FlmOt.lua`](src/Apps/AG-FlmOt.lua) | Released (0.1.0) | [003](specs/003-flameout-alarm/spec.md) | Original | +| Throttle Setup Wizard | [`AG-TrbSt.lua`](src/Apps/AG-TrbSt.lua) | Released (0.1.0) | [002](specs/002-turbine-throttle-setup/spec.md) | Original | ### Screenshots @@ -26,6 +27,14 @@ Taken on a DS-24 II transmitter. Flameout Alarm showing the red FLAMEOUT alarm at 0 RPM Flameout Alarm disarmed at 35,000 RPM +**Throttle Setup Wizard:** a guided step, verify passed, +the summary. Full guide: +[Throttle Setup Wizard](docs/apps/throttle-setup-wizard.md). + +Throttle Setup Wizard guided step 2: Throttle-Cut output value -100% +Throttle Setup Wizard Verify: all four passed +Throttle Setup Wizard Summary: setup complete with measured values + ### Speed Gauge Speaks your model's airspeed, warns of stall and overspeed, and shows a @@ -187,6 +196,41 @@ The sounds in `src/Apps/AG-FlmOt/` are generated with [`tools/voice/make_flameout.py`](tools/voice/README.md) and licensed CC BY-SA 4.0, not MIT. Install = `AG-FlmOt.lua` plus the `AG-FlmOt/` folder. +### Throttle Setup Wizard + +Sets up a turbine's throttle on **one two-position safety switch**: **CUT** +(Throttle Cut, engine off) or **RUN** (Throttle Idle, the engine may run). +It's simpler and safer than the old habit of clicking the throttle trim down +to stop and up to arm; Xicoy's manual warns that digital trims cause an +unstable idle and a slow emergency shutdown. + +The app guides the transmitter's own setup and then **proves it** by +measuring the throttle signal: + +- **One recommended setup:** Max negative/positive −80/80, Throttle-Idle + offset 20%, Throttle-Cut output value **−100%** (**−125% for Xicoy**). + Tested with KingTech, Swiwin and Xicoy ECUs; should work with most others. +- **Guided setup:** five steps with the exact values, each with an **Open** + button that jumps to the transmitter menu. +- **Verify:** an output check, then the four switch/stick positions, + including CUT with the stick at full. Each failure names the setting to + fix. +- **Failsafe:** the receiver's throttle output on **Out OFF**, confirmed by a + hand test before the setup counts as complete. +- **Optional voice callouts** "Turbine off" / "Turbine on", copied to the + transmitter's voice folder for its Sounds on Event. + +**It only reads and instructs.** It can't change any setting (constitution +I): the pilot makes each change. Use it on the bench with the engine unable +to start, remove it from the model once the setup passes, and **always +re-learn the ECU** (Teach RC) afterwards. Full guide, including the setup by +hand: [Throttle Setup Wizard](docs/apps/throttle-setup-wizard.md). + +The voice files in `src/Apps/AG-TrbSt/` are generated with +[`tools/voice/make_turbine.py`](tools/voice/README.md) and licensed CC BY-SA +4.0, not MIT. Install = `AG-TrbSt.lua` plus the `AG-TrbSt/` folder. Tested on +the DS-24 II; older DC/DS transmitters should work but are untested. + ## Install with JETI Studio 1. In JETI Studio open **File → Configuration**, and add this line to the @@ -201,8 +245,8 @@ The sounds in `src/Apps/AG-FlmOt/` are generated with Each app installs exactly its released version (its files come from the release tag). Descriptions: [Speed Gauge](docs/apps/speed-gauge.md), -[Flameout Alarm](docs/apps/flameout-alarm.md) (in JETI Studio once its -`Apps.json` entry is published). +[Flameout Alarm](docs/apps/flameout-alarm.md), +[Throttle Setup Wizard](docs/apps/throttle-setup-wizard.md). For maintainers: after tagging a release, run `python tools/publish/make_apps_json.py`, commit `Apps.json` and merge it to diff --git a/docs/apps/img/throttle-setup-wizard-cut-100.png b/docs/apps/img/throttle-setup-wizard-cut-100.png new file mode 100644 index 0000000..f5521e4 Binary files /dev/null and b/docs/apps/img/throttle-setup-wizard-cut-100.png differ diff --git a/docs/apps/img/throttle-setup-wizard-cut-125-xicoy.png b/docs/apps/img/throttle-setup-wizard-cut-125-xicoy.png new file mode 100644 index 0000000..113f510 Binary files /dev/null and b/docs/apps/img/throttle-setup-wizard-cut-125-xicoy.png differ diff --git a/docs/apps/img/throttle-setup-wizard-cut-idle.png b/docs/apps/img/throttle-setup-wizard-cut-idle.png new file mode 100644 index 0000000..2030480 Binary files /dev/null and b/docs/apps/img/throttle-setup-wizard-cut-idle.png differ diff --git a/docs/apps/img/throttle-setup-wizard-failsafe-out-off.png b/docs/apps/img/throttle-setup-wizard-failsafe-out-off.png new file mode 100644 index 0000000..abb394b Binary files /dev/null and b/docs/apps/img/throttle-setup-wizard-failsafe-out-off.png differ diff --git a/docs/apps/img/throttle-setup-wizard-guide-1.png b/docs/apps/img/throttle-setup-wizard-guide-1.png new file mode 100644 index 0000000..4a4ad95 Binary files /dev/null and b/docs/apps/img/throttle-setup-wizard-guide-1.png differ diff --git a/docs/apps/img/throttle-setup-wizard-guide-2.png b/docs/apps/img/throttle-setup-wizard-guide-2.png new file mode 100644 index 0000000..99a0902 Binary files /dev/null and b/docs/apps/img/throttle-setup-wizard-guide-2.png differ diff --git a/docs/apps/img/throttle-setup-wizard-guide-3.png b/docs/apps/img/throttle-setup-wizard-guide-3.png new file mode 100644 index 0000000..a44ae41 Binary files /dev/null and b/docs/apps/img/throttle-setup-wizard-guide-3.png differ diff --git a/docs/apps/img/throttle-setup-wizard-guide-4.png b/docs/apps/img/throttle-setup-wizard-guide-4.png new file mode 100644 index 0000000..9ac43ab Binary files /dev/null and b/docs/apps/img/throttle-setup-wizard-guide-4.png differ diff --git a/docs/apps/img/throttle-setup-wizard-guide-5.png b/docs/apps/img/throttle-setup-wizard-guide-5.png new file mode 100644 index 0000000..183030e Binary files /dev/null and b/docs/apps/img/throttle-setup-wizard-guide-5.png differ diff --git a/docs/apps/img/throttle-setup-wizard-home.png b/docs/apps/img/throttle-setup-wizard-home.png new file mode 100644 index 0000000..619eaee Binary files /dev/null and b/docs/apps/img/throttle-setup-wizard-home.png differ diff --git a/docs/apps/img/throttle-setup-wizard-icon.png b/docs/apps/img/throttle-setup-wizard-icon.png new file mode 100644 index 0000000..ea0bcfd Binary files /dev/null and b/docs/apps/img/throttle-setup-wizard-icon.png differ diff --git a/docs/apps/img/throttle-setup-wizard-rx-config.png b/docs/apps/img/throttle-setup-wizard-rx-config.png new file mode 100644 index 0000000..a8d4bb0 Binary files /dev/null and b/docs/apps/img/throttle-setup-wizard-rx-config.png differ diff --git a/docs/apps/img/throttle-setup-wizard-setup-inputs.png b/docs/apps/img/throttle-setup-wizard-setup-inputs.png new file mode 100644 index 0000000..4a712e9 Binary files /dev/null and b/docs/apps/img/throttle-setup-wizard-setup-inputs.png differ diff --git a/docs/apps/img/throttle-setup-wizard-sound-events.png b/docs/apps/img/throttle-setup-wizard-sound-events.png new file mode 100644 index 0000000..2405459 Binary files /dev/null and b/docs/apps/img/throttle-setup-wizard-sound-events.png differ diff --git a/docs/apps/img/throttle-setup-wizard-summary.png b/docs/apps/img/throttle-setup-wizard-summary.png new file mode 100644 index 0000000..555a66c Binary files /dev/null and b/docs/apps/img/throttle-setup-wizard-summary.png differ diff --git a/docs/apps/img/throttle-setup-wizard-switch.jpg b/docs/apps/img/throttle-setup-wizard-switch.jpg new file mode 100644 index 0000000..d502578 Binary files /dev/null and b/docs/apps/img/throttle-setup-wizard-switch.jpg differ diff --git a/docs/apps/img/throttle-setup-wizard-verify-check.png b/docs/apps/img/throttle-setup-wizard-verify-check.png new file mode 100644 index 0000000..ce8fe5d Binary files /dev/null and b/docs/apps/img/throttle-setup-wizard-verify-check.png differ diff --git a/docs/apps/img/throttle-setup-wizard-verify-passed.png b/docs/apps/img/throttle-setup-wizard-verify-passed.png new file mode 100644 index 0000000..f537c6e Binary files /dev/null and b/docs/apps/img/throttle-setup-wizard-verify-passed.png differ diff --git a/docs/apps/img/throttle-setup-wizard-verify-ready.png b/docs/apps/img/throttle-setup-wizard-verify-ready.png new file mode 100644 index 0000000..2a9808f Binary files /dev/null and b/docs/apps/img/throttle-setup-wizard-verify-ready.png differ diff --git a/docs/apps/img/throttle-setup-wizard-voice-callouts.png b/docs/apps/img/throttle-setup-wizard-voice-callouts.png new file mode 100644 index 0000000..eee1015 Binary files /dev/null and b/docs/apps/img/throttle-setup-wizard-voice-callouts.png differ diff --git a/docs/apps/throttle-setup-wizard.html b/docs/apps/throttle-setup-wizard.html new file mode 100644 index 0000000..09abe43 --- /dev/null +++ b/docs/apps/throttle-setup-wizard.html @@ -0,0 +1,69 @@ + + + + + Throttle Setup Wizard + + +

Throttle Setup Wizard

+

Set up a turbine's throttle on one safety switch, and + prove it works before the engine ever starts. For the + DS-24 II / DC-24 II.

+ Verify: all four passed +

One switch instead of the trim

+

Many pilots still stop and arm their turbine by clicking the + throttle trim fully down and up. Xicoy's manual warns that digital + trims cause an unstable idle and a delay in shutting the engine off. + One two-position safety switch is simpler and safer: + CUT (Throttle Cut, engine off) or RUN (Throttle Idle, + the engine may run). You only have to set it up correctly once, and + that's what this app is for.

+

What the app does for you

+
    +
  • Proof, not assumption: measures the real throttle + signal with the switch at CUT and RUN and the stick at idle and + full, and shows pass or fail.
  • +
  • Tests the dangerous case: switch at CUT with the stick + at full must stay at cut.
  • +
  • Tells you what to fix: e.g. "Switch RUN gave cut: + reverse the switch assignment", "Full off by +40 us: check Max + positive".
  • +
  • The right values for your ECU: Max negative/positive + -80/80, Throttle-Idle offset 20%, Throttle-Cut output value -100% + (-125% for Xicoy). Tested with KingTech, Swiwin and Xicoy.
  • +
  • Opens each menu for you from the guided steps.
  • +
  • Failsafe isn't forgotten: you confirm a hand test + before the setup is called complete.
  • +
  • Optional voice callouts: "Turbine off" and "Turbine + on" for the transmitter's Sounds on Event.
  • +
+ Guided setup step 2: Throttle-Cut output value +

Read and instruct only. The app can't change any setting: + you make each change, it tells you exactly what and proves it worked. + Use it on the bench with the engine unable to start (fuel off or ECU + unplugged). Once the setup passes, remove the app from the model and + always re-learn your ECU (Teach RC).

+

Using it

+
    +
  1. Add AG-TrbSt in Applications - User Applications, + then open Throttle Setup Wizard.
  2. +
  3. Setup inputs: choose the safety switch and the throttle + stick (assign it as proportional, P), put the switch at CUT and + the stick at idle and press Learn. Choose the throttle + output and your ECU (Xicoy or Other).
  4. +
  5. Guided setup: five steps with the exact values and an + Open button for each menu.
  6. +
  7. Verify, then the failsafe hand test and the + summary.
  8. +
+

Version: 0.1.0

+

Compatibility: DC/DS-24II, firmware 6.x. Older DC/DS + transmitters should work but are untested.

+

Voice callouts: Piper text-to-speech with the "Amy" voice by + Mycroft / Rhasspy; the sound files are licensed CC BY-SA 4.0. + Throttle Setup Wizard: MIT license, Copyright (c) 2026 Aaron + George.

+

Full guide, source and credits: + github.com/Flazzarious/jeti-lua-apps

+ + diff --git a/docs/apps/throttle-setup-wizard.md b/docs/apps/throttle-setup-wizard.md new file mode 100644 index 0000000..cf9f37b --- /dev/null +++ b/docs/apps/throttle-setup-wizard.md @@ -0,0 +1,279 @@ +# Throttle Setup Wizard + +Set up a turbine's throttle on one **safety switch**, and **prove it works** +before the engine ever starts. For the JETI **DS-24 II / DC-24 II**. + +![Other Model Options with Throttle Cut and Throttle Idle on the same switch](img/throttle-setup-wizard-cut-idle.png) + +## One switch instead of the trim + +Many pilots still start and stop their turbine the old way: **throttle trim +fully down to stop, trim fully up to arm and idle**, clicking the digital +trim up and down every flight. It works, but it's slow, easy to get wrong, +and slow to shut down in an emergency. Xicoy's manual warns that digital +trims cause an **unstable idle and a delay in shutting off the engine**, +and tells you to use the transmitter's throttle cut switch instead. + +The JETI way is simpler and safer: **one two-position safety switch**. + +- **CUT**: Throttle Cut, engine off. The stick does nothing. +- **RUN**: Throttle Idle, the engine may run. The stick goes from idle to + full. + +One flick stops the engine, every time, wherever the stick and trim are. +All you have to do is **set up that switch correctly once**. That's the +part people find tricky, and that's what this app is for. + +## What the app does for you + +You make each change on the transmitter; the app tells you exactly what to +enter, opens the right menu, and then **checks the result by measuring the +throttle signal**. Even if you set everything up by hand (or the model is +already set up), run its check: + +1. **Proof, not assumption.** It measures the real throttle signal with the + switch at CUT and RUN and the stick at idle and full, and shows pass or + fail against your targets. A setup that looks right in the menus can + still be wrong, such as a switch assigned the wrong way round. +2. **It tests the dangerous case.** With the switch at CUT and the stick at + full, the throttle must stay at cut. That is the failure that matters + most, and it's easy never to check. +3. **It tells you what to fix.** Not just "fail", but which setting: + "Switch RUN gave cut: reverse the switch assignment", "Full off by + +40 us: check Max positive", "Throttle reversed: check servo reverse", + "Output doesn't move: choose the throttle output". +4. **Accurate readings.** It waits until the stick is fully at the end and + held still, then averages the signal, so a stick at 95% doesn't give a + false result. +5. **The right values for your ECU.** One proven setup, the same for every + model: only the Throttle-Cut value changes, −125% for Xicoy (which + wants idle well clear of cut) and −100% for everything else. No + guesswork, no trial and error. +6. **Failsafe isn't forgotten.** It won't call the setup complete until you + confirm a hand test of failsafe, the one safety setting no transmitter + can measure. +7. **A record.** The summary keeps the switch, ECU type, measured values and + date for the model, and clears itself if you change the setup. +8. **The same check every time.** Every new model gets the same check, the + same way, in a couple of minutes. + +The app **can't change any setting itself**: the JETI Lua interface can +only read and open menus, and changing a turbine's throttle from an app +would be unsafe. Once the setup passes, remove the app from the model. +Nothing at flight time depends on it. + +**Bench use only.** Make sure the engine can't start while you set up or +check: fuel off, or the ECU unplugged from the engine. + +## Using the app + +1. Add **AG-TrbSt** in *Applications → User Applications*, then open + **Throttle Setup Wizard** in *Applications*. +2. **Setup inputs:** choose your safety switch and your throttle stick + (assign it as **proportional, P**), put the switch at CUT and the stick + at idle (down) and press **Learn**. Choose the throttle output and your + ECU: **Xicoy**, or **Other** for everything else. Other has been tested + with KingTech and Swiwin ECUs and should work with most others. +3. **Guided setup:** five steps, each with the exact values and an **Open** + button for the right menu. Skip this if the model is already set up. +4. **Verify:** follow the prompts for each switch and stick position. +5. **Failsafe:** test it by hand and confirm. The summary then shows + "Setup complete" and the next step: remove the app, then **re-learn your + ECU** (Teach RC). +6. **Voice callouts (optional):** see step 7 below. + +### Screens + +Home: Setup complete, verified 2026-10-10, with links to Setup inputs, Guided setup, Verify, Summary and Voice callouts +Setup inputs: engine warning, safety switch Sf at CUT (+100%), throttle stick P4 at idle (-100%), throttle output O1 + +*Home after a completed setup, and Setup inputs showing the safety switch +at CUT and the stick at idle, live.* + +Guided setup step 1 of 5: Servo Setup, Max negative -80%, Max positive 80%, leave the limits at -125/125% +Guided setup step 2 of 5: Other Model Options, Throttle Cut, Throttle-Cut output value -100% +Guided setup step 3 of 5: Throttle Idle on the same switch at RUN, Throttle-Idle offset 20% +Guided setup step 4 of 5: receiver Fail-Safe enabled 1.5s, throttle OutPin mode Out OFF +Guided setup step 5 of 5: use a JETI 2-position locking switch within easy reach + +*Guided setup: five steps, each with the exact value to enter and an +**Open** button that jumps to that menu.* + +Verify, output check: switch RUN (not cut), stick idle then full; Do: now move the stick fully up +Verify: 4 of 4 Full, all four passed, press Next +Summary: setup complete, safety switch Sf, ECU Other (cut -100%), targets 1100/1200/1900, measured 1100/1100/1202/1900, next: remove the app and re-learn the ECU + +*Verify: each test shows what it needs (Set), where your switch and stick +are now (Now) and what to do (Do). Then the summary, with the measured +values and the next step.* + +## The setup by hand + +One setup for every turbine. Only the **Throttle-Cut output value** +depends on the ECU: + +| Setting | Xicoy | Other ECUs | +| --- | --- | --- | +| Max negative / Max positive | −80% / 80% | −80% / 80% | +| Throttle-Cut output value | **−125%** | **−100%** | +| Throttle-Idle offset | 20% | 20% | +| Signal: cut / idle / full | 1000 / 1200 / 1900 µs | 1100 / 1200 / 1900 µs | + +**Other ECUs:** tested with **KingTech** and **Swiwin**, and should work +with most other ECUs that learn their throttle range from the receiver +(JetCat, JetCentral and others). **Xicoy** asks for idle at 15–30% of the +cut-to-full range, so it gets −125%, which puts idle at 22%. + +You need a **two-position switch** for the safety switch. A **JETI +two-position locking switch** for the DS-24 II is highly recommended: you +have to pull the lever out before it will flip, so it can't be bumped to +RUN on the bench or knocked to CUT in flight. Fit it where you can reach it +fast in an emergency, and don't use it for anything else. + +![The short silver locking switch SF, used as the throttle safety switch, next to SE on a DS-24 II](img/throttle-setup-wizard-switch.jpg) + +*Example: the short silver locking switch **SF** as the safety switch, +shown in RUN (Throttle Cut off, engine allowed to run).* + +### 1. Throttle travel + +*Model → Servo Setup*, then choose your throttle output in **Servo No.** +(e.g. "Throttle (1)" or "Engine 1 (1)"): + +| Setting | Value | +| --- | --- | +| Max negative (low end) | −80% | +| Max positive (high end) | 80% | + +Leave **Max negative limit** and **Max positive limit** at their defaults +(−125% / 125%), **Subtrim** at 0% and **Reverse** at No. + +### 2. Throttle Cut (CUT position) + +*Advanced Properties → Other Model Options → Throttle Cut*: + +1. Select **Throttle-Cut switch**. When asked to move a switch, move your + safety switch **to the position you want for CUT**. That position now + activates Throttle Cut. +2. Set **Throttle-Cut output value** to **−100%**, or **−125%** for a + Xicoy ECU. + +Throttle Cut on switch Sf with output value -100%, for most ECUs +Throttle Cut on switch Sf with output value -125%, for Xicoy ECUs + +*Left: −100% for most ECUs. Right: −125% for Xicoy. The ✓ next to +Throttle-Cut switch means the switch is at CUT right now.* + +### 3. Throttle Idle (RUN position) + +Same screen, *Throttle Idle*: + +1. Select **Throttle-Idle switch**. Move the **same switch to the other + position (RUN)**. +2. Set **Throttle-Idle offset** to **20%**. + +**Check it:** with the switch in RUN, the screen shows **✓** next to +Throttle-Idle switch and **✗** next to Throttle-Cut switch. Flip to CUT and +they swap. If both show the same mark, one of them was assigned in the +wrong position: assign it again. + +Leave the throttle trim centered (or turned off for throttle): the switch +now does the trim's old job. + +### 4. Failsafe + +If the receiver loses the transmitter's signal (out of range, a flat +transmitter battery, interference), it must not keep the throttle where it +was. The ECU has to see the signal disappear, so it can shut the engine +down. + +*Model → Device Explorer → your receiver (e.g. REX12A) → Configuration → +Fail-Safe*: + +1. **Fail-Safe**: **Enabled**. Leave **Fail-Safe Delay** at **1.5s** unless + your ECU's manual says otherwise. +2. Find the **OutPin** your ECU's throttle lead is plugged into (usually + the same number as the throttle output, e.g. **OutPin 1**). +3. Set its **Mode** to **Out OFF** (no pulse). With no signal, the ECU + runs its own shutdown. This is the simplest and safest choice. + - *Never leave the throttle on **Hold***: the engine would stay at + whatever throttle it had when the link was lost. + - *Don't use **Fail-Safe** mode with **Value 0%***: 0% is mid-throttle + (1500 µs). + +REX12A Configuration menu with Fail-Safe selected +REX12A Fail-Safe screen: Fail-Safe Enabled, delay 1.5s, OutPin 1 mode Out OFF + +*The receiver's Configuration menu, and its Fail-Safe screen with the +throttle on OutPin 1 set to Out OFF.* + +Then **test it**: ECU powered, fuel off, switch the transmitter off. The +ECU must report signal loss. + +### 5. Check the signal + +On the servo monitor the throttle should read: + +| Switch | Stick | Other ECUs | Xicoy | +| --- | --- | --- | --- | +| CUT | down | −80% (1100 µs) | −100% (1000 µs) | +| CUT | **up** | **−80% (1100 µs)** | **−100% (1000 µs)** (cut ignores the stick) | +| RUN | down | −60% (1200 µs) | −60% (1200 µs) | +| RUN | up | +80% (1900 µs) | +80% (1900 µs) | + +Or let the app do this for you: that's its **Verify** step. + +### 6. Teach the ECU + +Run your ECU's radio learning ("Teach RC", "Radio setup") and follow its +prompts for cut, idle and full: switch at CUT for cut, RUN with the stick +down for idle, RUN with the stick up for full. **Always do this** after +setting up or changing these values, even if the ECU was taught before. + +### 7. Voice callouts (optional) + +Hear **"Turbine off"** when you flip the safety switch to CUT and +**"Turbine on"** when you flip it to RUN. The transmitter plays them +itself, so they keep working after you remove the app. + +1. In the app, open **Voice callouts** and press **Copy**. It puts + `TurbOff.wav` and `TurbOn.wav` in the card's voice folder for your + language (e.g. `/Audio/en`), where JETI looks for voice files. Files + already there are never replaced. +2. Press **Open** to go to *Sounds on Event*. Press **+** twice to add + **two lines**, one for each switch position: + 1. **Switch**: choose it and move your safety switch to **CUT**. + **File**: `TURBOFF.WAV`. + 2. **Switch**: choose it and move the same switch to **RUN**. + **File**: `TURBON.WAV`. + + The transmitter shows the file names in capitals. Next to each switch, + **✓** means that line's position is active right now and **✗** that it + isn't: with the switch at CUT, the TURBOFF line shows ✓. +3. If you already have callouts for this switch, you'll see them there: + keep them, swap in these files, or use your own. + +The app's Voice callouts screen: voice folder /Audio/en, TurbOff.wav yes, TurbOn.wav yes +Sounds on Event with two lines on switch Sf: TURBON.WAV and TURBOFF.WAV + +*Left: the app after copying (both files "yes", so Copy is greyed out). +Right: Sounds on Event with both lines. The switch is at CUT, so the +TURBOFF line shows ✓.* + +The callouts use the same voice as the author's Speed Gauge and Flameout +Alarm apps. + +## Credits and licenses + +Throttle Setup Wizard: MIT license, Copyright (c) 2026 Aaron George. + +Voice callouts: generated with **Piper** text-to-speech using the voice +model **"Amy"** by Mycroft / Rhasspy. The sound files (in +`/Apps/AG-TrbSt/`, and the copies in `/Audio/`) are licensed +**CC BY-SA 4.0**. + +Xicoy's advice on digital trims is from the Xicoy TurboJet Engines User +Manual (v1.5, 2024); idle ranges from the Xicoy and KingTech manuals. + +Source, full credits and license texts: +[github.com/Flazzarious/jeti-lua-apps](https://github.com/Flazzarious/jeti-lua-apps) diff --git a/docs/drafts/turbine-throttle-setup.md b/docs/drafts/turbine-throttle-setup.md new file mode 100644 index 0000000..32e9e8f --- /dev/null +++ b/docs/drafts/turbine-throttle-setup.md @@ -0,0 +1,220 @@ +# Draft spec input: Turbine Throttle Setup + +**Status:** Pre-spec draft (2026-10-01). Not yet run through Spec Kit. +**Next step:** run `/speckit-specify` with the *Feature description* below, +then bring in the *Success criteria* and *Edge cases* sections, and feed the +*Open questions / research* items to `/speckit-clarify`. + +Proposed script name: `AG-TrbSt.lua` (menu name "Turbine Throttle Setup"). +Confirm the name before release; constitution V makes filenames permanent. + +--- + +## Feature description (paste into `/speckit-specify`) + +Turbine Throttle Setup is a one-time setup wizard app for the Jeti DS-24 II. + +**Problem.** Setting up a turbine throttle on Jeti has to be done exactly +right, and mistakes are dangerous. The setup covers endpoints, Throttle Cut +and Throttle Idle on one two-position safety switch, and failsafe. Pilots want +a guided setup that proves the result. + +**Goal.** The wizard walks the user through the native transmitter setup, then +checks the live throttle output in every switch and stick state. When it is +done, the app is no longer needed. The user then moves on to the ECU's +"learn transmitter" (Teach RC) phase. If the targets already match what the +ECU expects, that phase can be skipped. + +**Setup inputs.** + +- Two-position switch, and which position is OFF. +- Throttle stick. +- Throttle servo output. +- Target pulse widths. Defaults are cut 1100 us, idle 1200 us and + full 1900 us, and all three are editable. + +**Behavior.** + +1. Instruction steps, one per screen. Each screen shows the value to enter for + the user's targets and has an "Open menu" button + (`system.openExternal`) that jumps to the right transmitter menu: + 1. Throttle channel endpoints, default +/-80% (`":servoSetup"`). + 2. Throttle Cut on the selected switch and position, value -100% + (`":otherProps"`). + 3. Throttle Idle on the same switch, opposite position, offset 20% + (`":otherProps"`). + 4. Throttle failsafe OFF or -125%, which gives about 1000 us or no pulse + (`":devExplorer"`). + 5. A recommendation to use a locking safety switch in an easy-to-reach + position. +2. Verify mode. The app prompts for each state and reads the throttle servo + output with `system.getInputs("O")`: + - Switch OFF, stick at idle: should read the cut target. + - Switch OFF, stick at full: should still read the cut target, because + cut overrides the stick. + - Switch ON, stick at idle: should read the idle target. + - Switch ON, stick at full: should read the full target. + + Each state gets pass or fail within a tolerance. +3. Failsafe step. The app cannot read failsafe settings. The user must test + failsafe by hand (Tx off, ECU sees signal loss and shuts down) and confirm + before the wizard reports complete. +4. Summary screen listing the values set, with a reminder that the app can + now be removed from the model. + +**Constraints.** + +- The Jeti Lua API can't write model settings. The user makes every change by + hand; the app only instructs and verifies. +- The app never drives any output. It never calls `system.registerControl`, + `system.setControl` or `system.setProperty` (constitution I). +- Nothing at flight time depends on the app. +- The app installs standalone. It needs only `AG-TrbSt.lua` and, if it has + assets, its own `AG-TrbSt/` folder. It must not depend on any other app in + this repo, including Speed Gauge. If it uses a shared module from + `src/Apps/lib/`, the plan must list that module, and the install + instructions and any release package must include it. + +--- + +## Reference: the manual setup (from Aaron) + +This is the proven manual procedure the wizard automates the guidance for: + +1. Set the throttle channel endpoints to +/-80. +2. Assign Throttle Cut to a 2-position switch, in whichever position you want + the turbine OFF. +3. Set the Throttle Cut value to -100%. +4. Assign Throttle Idle to the same switch, in the position you want the + turbine to idle. +5. Set the Throttle Idle offset to 20%. +6. Set the throttle failsafe to OFF or -125% and verify that it works. + +With these settings, the throttle channel outputs: + +- 1100 us with the switch in Throttle Cut; +- 1200 us in Throttle Idle; +- 1900 us at full throttle. + +Failsafe must be 1000 us (or anything outside the normal range) or no pulse, +so the ECU recognizes signal loss and shuts down. The servo monitor shows the +throttle in microseconds: press F3 twice. + +These values match the Spektrum-era throttle positions all of Aaron's ECUs +were already set up with. That let him skip Teach RC. Other values work too, +as long as the user understands exactly what they're doing. + +Use a locking 2-position safety switch, mounted where it's easy to reach in an +emergency. + +--- + +## Success criteria + +- **SC-001.** Someone who has never set up a Jeti turbine throttle can go from + opening the app to a fully verified setup in under 10 minutes, without any + other manual. +- **SC-002.** All four verify states (cut at idle stick, cut at full stick, + idle, full) report PASS only when the measured throttle output is within + ±10 us of target. The tolerance is editable from 5 to 25 us. +- **SC-003.** The values the app shows agree with the transmitter's servo + monitor (us view) within ±5 us for 100% of readings in calibration testing, + in both the emulator and on the DS-24 II. +- **SC-004.** Any single setup fault is reported as FAIL, naming the failing + state, in 100% of seeded-fault tests. Faults covered: wrong switch, reversed + switch direction, cut not overriding full stick, wrong endpoint, wrong idle + offset, wrong output selected. +- **SC-005.** The wizard never reports "Setup complete" unless all four verify + states passed AND the user confirmed a manual failsafe test. +- **SC-006.** For any target values the user enters, the endpoint, cut value + and idle offset shown on the instruction screens produce those targets + within ±10 us when entered as shown. +- **SC-007.** After the app is removed from the model, all four throttle states + produce the same outputs as before. The setup has no runtime dependence on + the app. +- **SC-008.** The app never changes any transmitter output or setting. To + check: servo outputs and the model file are unchanged after running the app + with no user edits. +- **SC-009.** On a transmitter with no other AG- apps installed, copying only + the app's files (plus any listed lib modules) to `/Apps` is enough for it + to load and complete a full setup and verify run. + +## Edge cases + +- **Switch assigned backwards** (cut and idle swapped). Verify fails at the + cut state with a clear message, e.g. "Switch position OFF produced idle; + reverse the switch assignment." +- **Cut doesn't override the stick** (the output rises with the stick while + the switch is OFF). The cut / full-stick state fails, and the message + points to the Throttle Cut assignment. +- **Asymmetric or wrong endpoints** (e.g. full reads 1940 us). The full state + fails and shows the expected and measured values. +- **Wrong servo output selected** (the output doesn't move with the stick). + The app detects no change between idle and full and asks the user to + re-select the output before verifying. +- **Throttle reversed on the channel** (full reads low). The app detects this + and points to servo reverse. +- **Stick not fully at idle or full during a step.** The app waits until the + stick is at the end of its travel and steady before sampling. +- **Throttle trim not centered, or digital trim active.** The app warns that + trim offsets shift readings and asks the user to center the trim. +- **Flight modes with different throttle settings.** The app verifies the + current flight mode only and warns that other modes are not checked. +- **Out-of-range targets.** The app blocks targets where cut ≥ idle, + idle ≥ full, or any value is outside 900–2100 us, and explains why. +- **Failsafe confirmation skipped or declined.** The setup stays + "Incomplete" and says why. +- **Model already has a throttle setup.** The user can run verify-only mode + without going through the instructions. + +--- + +## Open questions / research (feed to `/speckit-clarify` and the plan) + +1. **us mapping.** How does the `system.getInputs("O")` value (-1..1) map + to microseconds? Calibrate against the servo monitor (F3 twice) in the + JETI Studio emulator and on the transmitter. Known data point: endpoints of + ±80% give 1100 and 1900 us. +2. **Return from `openExternal`.** The call returns immediately. It is not + documented what happens when the user backs out of the opened menu: do + they return to the wizard, and does the form keep its step? Test in the + emulator. Save wizard progress with `pSave` so the wizard can resume + either way. +3. **Exact menu labels.** Confirm on firmware 6.x the exact wording and + location of the Throttle Cut / Throttle Idle fields under + `":otherProps"`, and of receiver failsafe under `":devExplorer"`, so the + on-screen instructions match. +4. **Firmware 6.x API changes.** The latest public release notes found cover + up to 5.06 (June 2021) and show no Lua function that writes model + settings. The repo targets firmware 6.03/6.04. Check the 6.x release + notes (JETI Studio firmware updater) for any new Lua API before finalizing + the plan. If anything new appears, update `docs/jeti-api-notes.md` and + `types/jeti.lua`. +5. **Stub check.** `types/jeti.lua` already declares `system.openExternal`, + `system.getInputs`, `system.createSwitch` and `system.getSwitchInfo`. + Confirm that the `getInputs` stub documents the `O1`–`O24` servo output + codes. + +## Research findings so far (2026-10-01) + +- **The Lua API can't write model programming.** JETI DC/DS Lua API v1.5 has + no functions for servo travel or endpoints, trims, Throttle Cut/Idle, mixes, + logical switches or failsafe. The only things it can change are the app's + own registered controls and a few system properties (wireless mode, + volumes, backlight). Both are off-limits here under constitution I. +- **The API can read servo outputs.** `system.getInputs` accepts `O1`–`O24` + and returns values in -1..1. +- **The API can open transmitter menus.** `system.openExternal` (since + firmware 5.01) opens named menus, including `":servoSetup"`, + `":otherProps"` (described as "Other model options (throttle cut etc.)"), + `":devExplorer"` and `":servoTest"`. +- **Release notes 3.00–5.06** list every Lua addition: switch info, log + variables, backplate inputs, vario, audio redirect, `openExternal`, + `createSwitch`, file I/O. None of them modify model settings. + +### Sources + +- [JETI DC/DS Lua API v1.5 (PDF)](https://github.com/JETImodel/Lua-Apps/blob/master/Doc/JETI%20DCDS_Lua_API_1.5.pdf) +- [JETI Release Notes EN, firmware 3.00–5.06](https://jetiforum.de/media/kunena/attachments/46/ReleaseNotes_EN.pdf) +- [Firmware 5.02 – Highlights And Notes (RC-Thoughts)](https://rc-thoughts.com/2019/12/firmware-5-02-highlights-and-notes/index.html) +- [JETI DS-24 II product page](https://www.jetimodel.com/katalog/duplex-ds-24-ii-gray-lacquer-us-1.htm) diff --git a/docs/jeti-api-notes.md b/docs/jeti-api-notes.md index a389d95..07040d8 100644 --- a/docs/jeti-api-notes.md +++ b/docs/jeti-api-notes.md @@ -186,6 +186,15 @@ the emulator's numbers above: filename. Renaming = losing its telemetry windows and settings. - `require "mod"` looks in `/Apps/lib/mod.lua`, `/Apps/lib/mod/init.lua`, `/Apps/mod.lua`, `/Apps/mod/init.lua`. +- Pilots' own voice files live in `/Audio/` (e.g. `/Audio/en`); + `/Audio` itself holds JETI's system sounds (`T_*.wav`) and the language + folders (Aaron's DS-24 II card, 2026-10-10). Put files meant for the + transmitter's voice pickers (Sounds on event) in `/Audio/`, using + `system.getLocale()` for ``. +- **Copying files with Jeti's `io` works**: `io.read(f, 2048)` / + `io.write(f, data)` in chunks copied two WAVs from `/Apps/AG-TrbSt` to + `/Audio/en` byte-exact (sizes match), and Sounds on event could pick them + (transmitter, 2026-10-10, Throttle Setup Wizard). - Audio: relative paths resolve under `/Audio` and `/Audio/`. Foreground playback (`AUDIO_IMMEDIATE`, `AUDIO_QUEUE`) is WAV only; background accepts MP3. @@ -233,6 +242,19 @@ The app file returns a table: `init`, `loop`, `destroy` (5.00+), `author`, - `system.getInputs("P1","SA",...)` returns raw controls in −1..1 (up to 8). - For user-assigned switches, store a SwitchItem from `form.addInputbox` and read it with `system.getInputsVal(item)`. +- `form.addInputbox(item, true, ...)` only *allows* a proportional control: + the pilot still has to choose proportional (P) in the assignment dialog. + Assigned as a switch, a stick reads only its switched states. Check + `system.getSwitchInfo(item).proportional` (transmitter, 2026-10-10, + Throttle Setup Wizard). +- `system.openExternal(":servoSetup")` and `(":otherProps")` open Servo + Setup and Other Model Options over the app's form; Esc returns to the + same form screen (transmitter, 2026-10-10). +- `getInputs("O")` is the final output after Throttle Cut / Idle, and + isn't clipped at ±1: ±125% travel reads correctly (transmitter, + 2026-10-10). +- `system.getInputs("O")` reads servo outputs: a ±100% travel throttle + read 1000–2000 µs as `1500 + 500 * v` (transmitter, 2026-10-10). ## Forms @@ -241,6 +263,14 @@ The app file returns a table: `init`, `loop`, `destroy` (5.00+), `author`, - Component functions return an index used with `form.setValue`, `form.getValue`, `form.setProperties`. - `form.setButton(n, text, state)` labels F1–F5 (max 7 chars, or `":icon"`). +- **Key codes are bit flags** (emulator 6.04, 2026-10-10, Turbine Throttle + Setup): `KEY_1` 1, `KEY_2` 2, `KEY_3` 4, `KEY_4` 8, `KEY_5` 16, `KEY_ESC` + 32, `KEY_ENTER` 64, `KEY_RELEASED` −2147483648 (0x80000000). The key + handler also gets a `KEY_RELEASED` after each press. +- **F5, ESC and power close the form** unless the key handler calls + `form.preventDefault()`. Links (`form.addLink`) are chosen with the + rotary press (`KEY_ENTER`); pressing F5 on a link closes the app's form + instead. - `form.question(...)` blocks the calling code until answered, so never call it from `loop()` in flight. diff --git a/specs/002-turbine-throttle-setup/assets/safety-switch-sf.jpg b/specs/002-turbine-throttle-setup/assets/safety-switch-sf.jpg new file mode 100644 index 0000000..8c302ff Binary files /dev/null and b/specs/002-turbine-throttle-setup/assets/safety-switch-sf.jpg differ diff --git a/specs/002-turbine-throttle-setup/checklists/requirements.md b/specs/002-turbine-throttle-setup/checklists/requirements.md new file mode 100644 index 0000000..d489c34 --- /dev/null +++ b/specs/002-turbine-throttle-setup/checklists/requirements.md @@ -0,0 +1,40 @@ +# Specification Quality Checklist: Turbine Throttle Setup + +**Purpose**: Validate specification completeness and quality before proceeding to planning +**Created**: 2026-10-09 +**Feature**: [spec.md](../spec.md) + +## Content Quality + +- [x] No implementation details (languages, frameworks, APIs) +- [x] Focused on user value and business needs +- [x] Written for non-technical stakeholders +- [x] All mandatory sections completed + +## Requirement Completeness + +- [x] No [NEEDS CLARIFICATION] markers remain +- [x] Requirements are testable and unambiguous +- [x] Success criteria are measurable +- [x] Success criteria are technology-agnostic (no implementation details) +- [x] All acceptance scenarios are defined +- [x] Edge cases are identified +- [x] Scope is clearly bounded +- [x] Dependencies and assumptions identified + +## Feature Readiness + +- [x] All functional requirements have clear acceptance criteria +- [x] User scenarios cover primary flows +- [x] Feature meets measurable outcomes defined in Success Criteria +- [x] No implementation details leak into specification + +## Notes + +- The spec names transmitter concepts (servo monitor, Throttle Cut, Throttle + Idle, failsafe, menus) because they are the user's domain, not + implementation choices. API facts that bound the scope (no setting writes, + outputs readable, menus openable) are kept in Assumptions. +- No [NEEDS CLARIFICATION] markers: the draft and Aaron's reference setup + answered the scope questions. Five research items remain for + `/speckit-clarify` and `/speckit-plan` (Assumptions → Open research items). diff --git a/specs/002-turbine-throttle-setup/contracts/screens.md b/specs/002-turbine-throttle-setup/contracts/screens.md new file mode 100644 index 0000000..4436120 --- /dev/null +++ b/specs/002-turbine-throttle-setup/contracts/screens.md @@ -0,0 +1,119 @@ +# Contract: Screens + +One form, registered under `MENU_APPS` as "Throttle Setup Wizard". Each +screen is rebuilt with `form.reinit(1)`; the app's `cur` picks which +screen. Screens are built from form components only +(research R9). Text lines are ≤ 32 characters. Live labels update from +`loop()` only while the form is open, at most every 200 ms, and only when +the text changes. + +F-key labels are ≤ 7 characters. + +## 1. Home + +- Status: "Not verified" / "Incomplete - failsafe not confirmed" / + "Setup complete 2026-10-10" (data-model). +- Links: "Setup inputs", "Guided setup", "Verify", "Summary", "Voice + callouts (optional)". Guided setup and Verify are disabled until setup is + complete. Summary is disabled while `res = 0`. Voice callouts is always + available. +- No device check: on older transmitters, features the firmware lacks are + hidden (R13). + +## 2. Setup inputs (FR-001 to FR-005a) + +| Row | Component | Notes | +| --- | --- | --- | +| Warning | two labels | "ENGINE MUST NOT BE ABLE TO START" / "(fuel off or ECU unplugged)" (FR-023) | +| Safety switch | inputbox, not proportional | live: "CUT" / "RUN" / "middle" / "not learned", plus raw percent, e.g. "CUT (-100%)" | +| Throttle stick | inputbox, proportional | live: "idle" / "full" / "middle" / "not learned", plus raw percent, e.g. "middle (+3%)" | +| Learn | label + F3 "Learn" | "Switch to CUT, stick to idle," / "then press Learn menu button." Stores `offSg`, `idlSg` (R5) | +| Throttle output | selectbox "--", "O1".."O24" | hint: "Output (O1-O24) the ECU's" / "throttle lead is plugged into." | +| Signal now | label | live: "1102 us" / "choose output" / "no signal"; hint "Pulse width the ECU gets now." | +| ECU | selectbox "--", "Xicoy", "Other" | starts at "--" (not chosen); hints "Xicoy: Throttle-Cut -125%." / "Other: Throttle-Cut -100%." / "Tested with KingTech and Swiwin;" / "should work with most others." | +| Targets | label | "Targets: 1100 / 1200 / 1900 us" (or 1000 for Xicoy; "--" until chosen) | +| Tolerance | intbox 5–25, step 1 | "+/- 10 us" | + +- F-keys: F1 "Back", F2 "Servo" (opens `:servoSetup`), F3 "Learn", F4 + "Other" (opens `:otherProps`). F2 and F4 are hidden without + `system.openExternal`. They stay on this screen permanently (Aaron, + 2026-10-10), as shortcuts alongside the guide's Open buttons. +- Choosing a new switch or stick clears `offSg`/`idlSg` (learn again). +- **FR-005a:** while `res > 0`, the first change on this screen asks + `form.question("Clear saved result?", "Changing setup means it must be", + "verified again.")`. No puts the value back. Yes sets `res = 0`, clears + `meas` and `when`, and allows further changes without asking again. +- Learn refusals: "Stick must be proportional (P)." (`getSwitchInfo(stk) + .proportional == false`), "Use a two-position switch" (switch near 0) + and "Move the stick fully to idle" (|v| < 0.95). +- Under the stick row: hint "Assign it as proportional (P)." + +## 3. Guided setup (FR-006 to FR-012) + +Title "Step n of 5". F1 "Back", F3 "Open" (hidden for step 5 or when +`openExternal` is missing), F5 "Next" ("Verify" on step 5). Each step +shows the menu path and exact values from +[settings-math.md](settings-math.md). Menu names are confirmed on +firmware 6.x in task 1 (spec research item 3) and changed here if needed. + +| Step | Menu (Open) | Content | +| --- | --- | --- | +| 1 Endpoints | `:servoSetup` | "Servo Setup > Servo No.:" / "your throttle output." / "Max negative: -80%" / "Max positive: 80%" / "Leave the limits at -125/125%." | +| 2 Throttle Cut | `:otherProps` | "Other Model Options >" / "Throttle Cut" / "Throttle-Cut switch: choose it" / "and move the switch to CUT." / "Throttle-Cut output value: -100%" ("-125%" for Xicoy, with "(Xicoy)") | +| 3 Throttle Idle | `:otherProps` | "Other Model Options >" / "Throttle Idle" / "Throttle-Idle switch: same" / "switch, moved to RUN." / "Throttle-Idle offset: 20%" / "Check: in RUN, Idle shows a" / "tick and Cut a cross." | +| 4 Failsafe | `:devExplorer` | "Device Explorer > receiver >" / "Configuration > Fail-Safe:" / "Fail-Safe: Enabled, 1.5s." / "Throttle OutPin mode: Out OFF." / "Never Hold: the engine would" / "stay at its last throttle." / "Test it by hand at the end." (FR-010) | +| 5 Safety switch | none | "Use a JETI 2-position locking" / "switch: pull the lever to flip," / "so it can't be bumped." / "Fit it within easy reach." / "Don't use it for anything else." (FR-011) | + +- The step is saved to `gStep` on every change (FR-009). +- From Home, "Verify" skips the guide entirely (FR-012). + +## 4. Verify + +See [verify.md](verify.md). Rows: standing lines, the prompt and phase +line, four result rows, and the diagnosis (two lines). + +## 5. Failsafe confirmation (User Story 3) + +- Text: "With the ECU powered and fuel" / "OFF, switch the transmitter off." / + "Does the ECU show signal loss?" +- F1 "Not yet": leaves `res = 1` and goes to Summary showing "Incomplete - + failsafe not confirmed". +- F5 "Yes": `res = 2`, goes to Summary. + +## 7. Voice callouts (optional, User Story 4, FR-026 to FR-029) + +Reached from a Home link "Voice callouts (optional)" and from the guide's +last step. Rows: + +- "Say 'Turbine off' at CUT and" / "'Turbine on' at RUN, using the" / + "transmitter's Sounds on event." +- "Voice folder: /Audio/en" (from `system.getLocale()`), then a status + line per file: "yes" / "no" / "copying..." / "failed: read|create| + write|size a/b". +- If the app's own files are missing: "Voice files not installed." and no + Copy button (FR-027). +- Instructions: "Then press Open. In Sounds on" / "Event press + twice: one line" / + "per switch position." / "1. Switch: move safety switch" / " to CUT. File: TURBOFF.WAV" / + "2. Switch: move it to RUN." / " File: TURBON.WAV" / "Keep any callouts you already" / + "have, or use your own files." Labels from the transmitter's "Sounds on + Event" screen (columns Switch / File / Delay / Repeat, F3 "+" adds a line, + file names shown in capitals; `Screen017.png`). Sounds on event needs one + line per position; the app can't add them (research R15). +- Credit: "Voice: Piper, Amy (CC BY-SA 4.0)." (FONT_MINI, FR-029) + +F-keys: F1 "Back", F2 "Copy" (shown only when a file is missing from +the voice folder and the app's own files exist; asks `form.question("Copy voice +files?")` first), F3 "Open" (`:soundEvent`). F5 is not used. + +## 6. Summary (FR-020) + +- Status line (as Home). +- "Safety switch: