PINIO: update configurator for unified PINIO/PWM output#2579
Conversation
- outputMapping: detect PINIO outputs via specialLabels (firmware-assigned USER number) instead of timerOverrides cross-referencing; USER number derived directly from specialLabels value (2=USER1, 3=USER2, etc.) - mixer: label PINIO timer output mode as "PINIO / DUTY CYCLE" - logicConditions: rename condition 52 from "LED Pin PWM" to "PINIO PWM"; enable second operand (operandB = duty cycle, operandA = channel index) - transpiler: rename LED_PIN_PWM to PINIO_PWM throughout; update decompiler handler for two-operand pinioPwm(channel, duty) semantics
Fix operand order for backward compatibility: operandA=duty, operandB=pin (0=LED pin, 1=USER1, 2=USER2, ...). Old LED_PIN_PWM configs with operandA=duty and operandB=0 continue to work unchanged. Rename condition label to "PWM on pin" to reflect operand order. Add pwmOnPin(duty, pin) to JavaScript transpiler with full round-trip support (compile JS->LC and decompile LC->JS). Function name mirrors the "PWM on pin" label: duty first, then pin. Also fix transformBodyStatement to dispatch CallExpression nodes, which was silently dropping function calls in if-statement bodies. Add round-trip tests: compile, decompile, and JS->LC->JS for LED pin, USER1, and USER2.
- Fix LED label: use usageFlags (current assignment) instead of specialLabels (silkscreen), only label first pin on LED timer - Remove bogus servosToGo guard that prevented LED labels - Add TIM_USE_PINIO support so PINIO-overridden timer pins appear in the output count and get labeled in the function row - Remove leftover console.log debug statements
|
Three bugs fixed in the two-pass timer priority algorithm: 1. Motor numbering: getOutputTable() numbered motors by array index, so dedicated motors (Pass 0) showed wrong motor numbers. Now does a two-pass pre-numbering: dedicated MOTORS outputs first, then auto. 2. B-type overflow: Pass 1 was missing the firmware's guard to skip outputs with dedicated overrides. A MOTORS-overridden pin whose quota was already full could incorrectly fall through to servo assignment. Matches firmware's explicit continue guard. 3. Type mismatch: setTimerOverride() stored $select.val() as a string, but all comparisons in getTimerMap() used strict === against number constants. This silently disabled the entire two-pass algorithm in the live UI (unit tests used numbers directly and didn't catch it). Fixed with parseInt() at the entry point. Also add a change handler to timer override selects so the output mapping preview updates live without needing to save first. Add js/tests/outputMapping.test.mjs: 31 unit tests covering all timer override combinations (all-auto, dedicated motors, dedicated servos, mixed, overflow, interleaved, LED).
…m-output Combine PINIO output support (HEAD) with timer priority fixes (merged branch): - PINIO pre-assignment: outputs with specialLabels >= SPECIAL_LABEL_PINIO_BASE are assigned OUTPUT_TYPE_PINIO before the two-pass motor/servo loop, since PINIO identity comes from MSP specialLabels not from timer priority. - Two-pass priority, motor numbering, B-type overflow guard, parseInt fix, and live change handler all carried forward from fix/output-mapping-timer-priority.
|
Review Summary by QodoConsolidate PINIO/PWM output control with unified configurator support
WalkthroughsDescription• Consolidate PINIO/PWM output control into unified system - Rename LED Pin PWM condition to PWM on pin with dual operands - Enable second operand for duty cycle control (operandA=duty, operandB=pin) • Fix motor numbering to match firmware assignment order - Number motors in dedicated-first pass order, not physical array index - Add Pass 1 guard to prevent overflow dedicated outputs from being reassigned • Add PINIO output type support to output mapping - Detect PINIO outputs via specialLabels instead of timer overrides - Display correct USER number (USER1-USER4) in output mapping table - Add PINIO / DUTY CYCLE option to mixer timer output mode selector • Implement pwmOnPin(duty, pin) JavaScript transpiler function - Full round-trip support: compile JS→LC and decompile LC→JS - Backward compatible with old LED_PIN_PWM configurations Diagramflowchart LR
A["User selects<br/>PINIO/DUTY CYCLE<br/>in Mixer"] --> B["Timer override<br/>set to mode 4"]
B --> C["Output mapping<br/>detects via<br/>specialLabels"]
C --> D["Display USER1-4<br/>in output table"]
E["Programming tab<br/>PWM on pin condition"] --> F["operandA=duty<br/>operandB=pin"]
F --> G["Transpile to<br/>pwmOnPin JS function"]
G --> H["Firmware executes<br/>duty cycle control"]
File Changes1. js/logicConditionOperators.js
|
Code Review by Qodo
1. PINIO / DUTY CYCLE not localized
|
| '<option value=' + FC.OUTPUT_MAPPING.TIMER_OUTPUT_MODE_MOTORS + '' + (usageMode == FC.OUTPUT_MAPPING.TIMER_OUTPUT_MODE_MOTORS ? ' selected' : '')+ '>MOTORS</option>'+ | ||
| '<option value=' + FC.OUTPUT_MAPPING.TIMER_OUTPUT_MODE_SERVOS + '' + (usageMode == FC.OUTPUT_MAPPING.TIMER_OUTPUT_MODE_SERVOS ? ' selected' : '')+ '>SERVOS</option>'+ | ||
| '<option value=' + FC.OUTPUT_MAPPING.TIMER_OUTPUT_MODE_LED + '' + (usageMode == FC.OUTPUT_MAPPING.TIMER_OUTPUT_MODE_LED ? ' selected' : '')+ '>LED</option>'+ | ||
| '<option value=' + FC.OUTPUT_MAPPING.TIMER_OUTPUT_MODE_PINIO + '' + (usageMode == FC.OUTPUT_MAPPING.TIMER_OUTPUT_MODE_PINIO ? ' selected' : '')+ '>PINIO / DUTY CYCLE</option>'+ | ||
| '</select>' + | ||
| '<label for="timer-output-' + t + '">' + | ||
| '<span> Timer ' + (parseInt(t) + 1) + '</span>' + | ||
| '</label>' + |
There was a problem hiding this comment.
1. pinio / duty cycle not localized 📘 Rule violation ⚙ Maintainability
The new timer output mode option introduces hardcoded user-facing text in DOM HTML generation instead of using i18next data-i18n keys. This prevents proper localization and violates the project’s i18n requirements for UI text.
Agent Prompt
## Issue description
A new user-facing label (`PINIO / DUTY CYCLE`) is inserted into the DOM as a hardcoded string, which bypasses i18next localization.
## Issue Context
Per i18n requirements, UI strings should be represented using `data-i18n` attributes (and corresponding locale keys) so translations work consistently.
## Fix Focus Areas
- tabs/mixer.js[127-138]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
fd9388a
into
iNavFlight:maintenance-10.x




Problem
Users sometimes need PINIO that isn't natively provided by the board, or want to do duty-cycle based PWM.
Turning a pin on and off is of course easy to do technically, but INAV didn't provide a way for users to configure that.
As a workaround, a clever user who needed a a PINIO might discover INAV had a special-case PWM duty-cycle mode tied specifically to the LED strip pin — primarily used for camera control (OSD joystick).
A clever user could use the Programming tab to set 0% or 100% duty cycle — a roundabout approach to make a PINIO out of a little-known feature.
This was useful but very limited: only that one pin could do duty-cycle PWM.
Meanwhile, the PINIO subsystem (USER1–USER4 outputs, controllable via the Modes tab) provided clean on/off GPIO control, but only for the one or or two pins specifically chosen by the manufacturer.
Then we had another special case for the LED pin - it could be used as a regular PWM output for a servo or whatever. Lots of special cases, handled by special-case code paths.
Solution
This PR is the configurator side of consolidating duty-cycle PWM control into the PINIO subsystem and PWM pin assignment system (firmware PR: iNavFlight/inav#11375), making it available on any PWM-capable timer output — not just the LED pin, removing the special cases and allowing the user to assign these functions to any capable output pin.
Users can now:
No roundabout workarounds needed.
I expect a slight decrease in total lines of code by removing the special-case code paths and making it more general.
Testing
Notes
The
LED Pin PWMprogramming condition is renamed toPINIO PWM. The second operand (duty cycle) is now enabled —operandA= channel index,operandB= duty. Users with existingLED Pin PWMconditions will see them relabeled and will need to set the operands correctly.Companion firmware PR: iNavFlight/inav#11375