From 11ca2361d79983dfd1ae1d627c4b591bf20b4ae6 Mon Sep 17 00:00:00 2001 From: Ray Morris Date: Mon, 8 Dec 2025 10:42:46 -0600 Subject: [PATCH 1/4] Add MSP2_INAV_LOGIC_CONDITIONS_CONFIGURED command Returns 8-byte bitmask indicating which logic conditions differ from defaults. Enables configurator optimization to reduce MSP requests from 64 to 1+N. --- src/main/fc/fc_msp.c | 23 +++++++++++++++++++++++ src/main/msp/msp_protocol_v2_inav.h | 1 + 2 files changed, 24 insertions(+) diff --git a/src/main/fc/fc_msp.c b/src/main/fc/fc_msp.c index 936c708030d..53daf9f524e 100644 --- a/src/main/fc/fc_msp.c +++ b/src/main/fc/fc_msp.c @@ -564,6 +564,29 @@ static bool mspFcProcessOutCommand(uint16_t cmdMSP, sbuf_t *dst, mspPostProcessF sbufWriteU32(dst, logicConditionGetValue(i)); } break; + case MSP2_INAV_LOGIC_CONDITIONS_CONFIGURED: + { + // Returns 8-byte bitmask where bit N = 1 if logic condition N is configured (non-default) + uint64_t mask = 0; + for (int i = 0; i < MAX_LOGIC_CONDITIONS; i++) { + const logicCondition_t *lc = logicConditions(i); + // Check if any field differs from default reset values + bool isConfigured = (lc->enabled != 0) || + (lc->activatorId != -1) || + (lc->operation != 0) || + (lc->operandA.type != LOGIC_CONDITION_OPERAND_TYPE_VALUE) || + (lc->operandA.value != 0) || + (lc->operandB.type != LOGIC_CONDITION_OPERAND_TYPE_VALUE) || + (lc->operandB.value != 0) || + (lc->flags != 0); + if (isConfigured) { + mask |= ((uint64_t)1 << i); + } + } + sbufWriteU32(dst, (uint32_t)(mask & 0xFFFFFFFF)); // Lower 32 bits + sbufWriteU32(dst, (uint32_t)((mask >> 32) & 0xFFFFFFFF)); // Upper 32 bits + } + break; case MSP2_INAV_GVAR_STATUS: for (int i = 0; i < MAX_GLOBAL_VARIABLES; i++) { sbufWriteU32(dst, gvGet(i)); diff --git a/src/main/msp/msp_protocol_v2_inav.h b/src/main/msp/msp_protocol_v2_inav.h index 696d426cd78..0b893916895 100755 --- a/src/main/msp/msp_protocol_v2_inav.h +++ b/src/main/msp/msp_protocol_v2_inav.h @@ -89,6 +89,7 @@ #define MSP2_INAV_MISC2 0x203A #define MSP2_INAV_LOGIC_CONDITIONS_SINGLE 0x203B +#define MSP2_INAV_LOGIC_CONDITIONS_CONFIGURED 0x203C // Returns 8-byte bitmask of non-default logic conditions #define MSP2_INAV_ESC_RPM 0x2040 #define MSP2_INAV_ESC_TELEM 0x2041 From b9a3b1d8d6ef4d3413729defeff9232701a7c19d Mon Sep 17 00:00:00 2001 From: Ray Morris Date: Thu, 11 Dec 2025 09:22:14 -0600 Subject: [PATCH 2/4] Docs: Update JavaScript programming documentation - Add PID controller output documentation (pid[0-3].output) - Add flight mode detection documentation (flight.mode.*) - Update sticky syntax to use variable assignment pattern - Update version history for INAV 9.0 - Fix API definitions summary for PID controllers --- .../JAVASCRIPT_PROGRAMMING_GUIDE.md | 87 +++++++++++++------ .../api_definitions_summary.md | 8 +- docs/javascript_programming/index.md | 20 +++-- 3 files changed, 79 insertions(+), 36 deletions(-) diff --git a/docs/javascript_programming/JAVASCRIPT_PROGRAMMING_GUIDE.md b/docs/javascript_programming/JAVASCRIPT_PROGRAMMING_GUIDE.md index 6609aa873b6..31352c61793 100644 --- a/docs/javascript_programming/JAVASCRIPT_PROGRAMMING_GUIDE.md +++ b/docs/javascript_programming/JAVASCRIPT_PROGRAMMING_GUIDE.md @@ -61,25 +61,26 @@ edge(() => flight.armTimer > 1000, { duration: 0 }, () => { --- ### Latching/Sticky Conditions -Use `sticky()` for conditions that latch ON and stay ON until reset: +Use `sticky()` for conditions that latch ON and stay ON until reset. Assign the result to a variable to use in conditions: ```javascript -const { flight, gvar, sticky } = inav; - -// Latches ON when RSSI < 30, stays ON until RSSI > 70 -sticky( - () => flight.rssi < 30, // ON condition - () => flight.rssi > 70, // OFF condition - () => { - override.vtx.power = 4; // Executes while latched - } -); +const { flight, gvar, sticky, override } = inav; + +// Create a latch: ON when RSSI < 30, OFF when RSSI > 70 +var rssiWarning = sticky({ + on: () => flight.rssi < 30, + off: () => flight.rssi > 70 +}); + +// Use the latch to control actions +if (rssiWarning) { + override.vtx.power = 4; // Max power while latched +} ``` **Parameters:** -- **onCondition**: When to latch ON -- **offCondition**: When to latch OFF -- **action**: What to do while latched +- **on**: Condition that latches ON +- **off**: Condition that latches OFF **Use when:** - Warning states that need manual reset @@ -172,17 +173,18 @@ if (flight.homeDistance <= 200) { ### Hysteresis/Deadband ```javascript -const { flight, gvar, sticky } = inav; +const { flight, gvar, sticky, override } = inav; // Turn ON at low voltage, turn OFF when recovered -sticky( - () => flight.cellVoltage < 330, // Warning threshold - () => flight.cellVoltage > 350, // Recovery threshold - () => { - override.throttleScale = 50; // Reduce throttle while in warning - gvar[0] = 1; // Warning flag - } -); +var lowVoltageWarning = sticky({ + on: () => flight.cellVoltage < 330, // Warning threshold + off: () => flight.cellVoltage > 350 // Recovery threshold +}); + +if (lowVoltageWarning) { + override.throttleScale = 50; // Reduce throttle while in warning + gvar[0] = 1; // Warning flag +} ``` --- @@ -201,11 +203,12 @@ sticky( ## Available Objects ```javascript -const { - flight, // Flight telemetry +const { + flight, // Flight telemetry (including flight.mode.*) override, // Override flight parameters rc, // RC channels gvar, // Global variables (0-7) + pid, // Programming PID outputs (pid[0-3].output) waypoint, // Waypoint navigation edge, // Edge detection sticky, // Latching conditions @@ -213,6 +216,40 @@ const { } = inav; ``` +### Flight Mode Detection + +Check which flight modes are currently active via `flight.mode.*`: + +```javascript +const { flight, gvar, override } = inav; + +if (flight.mode.poshold === 1) { + gvar[0] = 1; // Flag: in position hold +} + +if (flight.mode.rth === 1) { + override.vtx.power = 4; // Max power during RTH +} +``` + +**Available modes:** `failsafe`, `manual`, `rth`, `poshold`, `cruise`, `althold`, `angle`, `horizon`, `air`, `acro`, `courseHold`, `waypointMission`, `user1` through `user4` + +### PID Controller Outputs + +Read output values from the 4 programming PID controllers (configured in Programming PID tab): + +```javascript +const { pid, gvar, override } = inav; + +if (pid[0].output > 500) { + override.throttle = 1600; +} + +gvar[0] = pid[0].output; // Store for OSD display +``` + +**Available:** `pid[0].output` through `pid[3].output` + --- ## Tips diff --git a/docs/javascript_programming/api_definitions_summary.md b/docs/javascript_programming/api_definitions_summary.md index 710af423808..c5153c3950c 100644 --- a/docs/javascript_programming/api_definitions_summary.md +++ b/docs/javascript_programming/api_definitions_summary.md @@ -20,7 +20,7 @@ Contains ~40 flight parameters including: - **State**: isArmed, isAutoLaunch, isFailsafe - **Profile**: mixerProfile - **Navigation**: activeWpNumber, activeWpAction, courseToHome, gpsCourseOverGround -- **Modes** (nested): failsafe, manual, rth, poshold, althold, wp, gcs_nav, airmode, angle, horizon, cruise +- **Modes** (nested `flight.mode.*`): failsafe, manual, rth, poshold, cruise, althold, angle, horizon, air, acro, courseHold, waypointMission, user1-user4 ### 2. ✅ **override.js** - Flight Control Overrides (WRITABLE) **Source**: `src/main/programming/logic_condition.c` (OPERATION_OVERRIDE_*) @@ -63,9 +63,9 @@ Waypoint mission data: **Source**: `src/main/programming/pid.c` 4 PID controllers (pid[0] through pid[3]), each with: -- `configure()` method: setpoint, measurement, p, i, d, ff -- `output` property: Controller output -- `enabled` property: Controller state +- `output` property: Controller output value (read-only) + +Note: PID controller parameters (setpoint, measurement, gains) are configured in the Programming PID tab, not in JavaScript. The JavaScript code can only read the output values. ### 7. ✅ **helpers.js** - Math & Utility Functions **Source**: `src/main/programming/logic_condition.c` (OPERATION_*) diff --git a/docs/javascript_programming/index.md b/docs/javascript_programming/index.md index 272d344eb7a..e85e4b68817 100644 --- a/docs/javascript_programming/index.md +++ b/docs/javascript_programming/index.md @@ -175,6 +175,8 @@ Instructions for: - Variable management (global variables, let/var) - RC channel access and state detection - Flight parameter overrides +- Flight mode detection (`flight.mode.poshold`, `flight.mode.rth`, etc.) +- PID controller outputs (`pid[0-3].output`) - Waypoint navigation **JavaScript Features:** @@ -275,12 +277,16 @@ Read the [Testing Guide](TESTING_GUIDE.md) to understand the testing workflow, t ## Version History -**2025-11-25**: Complete implementation -- All INAV logic condition operations now supported +**INAV 9.0**: JavaScript programming introduced +- All INAV logic condition operations supported - RC channel state detection (LOW/MID/HIGH) - XOR/NAND/NOR logical operations -- APPROX_EQUAL comparison -- MAP_INPUT/MAP_OUTPUT scaling -- Comprehensive documentation - -**Last Updated**: 2025-11-25 +- Approximate equality with tolerance +- MAP_INPUT/MAP_OUTPUT scaling functions +- Timer and change detection functions +- Flight mode detection (`flight.mode.poshold`, `flight.mode.rth`, etc.) +- PID controller output access (`pid[0-3].output`) +- Named parameter syntax for sticky with variable assignment +- IntelliSense and real-time validation + +**Last Updated**: 2025-12-10 From dbc7c70efd10a472cee802d5eea20b9728e1016f Mon Sep 17 00:00:00 2001 From: Ray Morris Date: Thu, 11 Dec 2025 10:10:01 -0600 Subject: [PATCH 3/4] Restore callback syntax documentation for sticky() --- .../JAVASCRIPT_PROGRAMMING_GUIDE.md | 26 +++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/docs/javascript_programming/JAVASCRIPT_PROGRAMMING_GUIDE.md b/docs/javascript_programming/JAVASCRIPT_PROGRAMMING_GUIDE.md index 31352c61793..31c17116249 100644 --- a/docs/javascript_programming/JAVASCRIPT_PROGRAMMING_GUIDE.md +++ b/docs/javascript_programming/JAVASCRIPT_PROGRAMMING_GUIDE.md @@ -61,7 +61,9 @@ edge(() => flight.armTimer > 1000, { duration: 0 }, () => { --- ### Latching/Sticky Conditions -Use `sticky()` for conditions that latch ON and stay ON until reset. Assign the result to a variable to use in conditions: +Use `sticky()` for conditions that latch ON and stay ON until reset. + +**Option 1: Variable assignment syntax** (recommended when you need to reference the latch state): ```javascript const { flight, gvar, sticky, override } = inav; @@ -78,10 +80,30 @@ if (rssiWarning) { } ``` -**Parameters:** +**Option 2: Callback syntax** (simpler when actions are self-contained): + +```javascript +const { flight, sticky, override } = inav; + +// Latch ON when RSSI < 30, OFF when RSSI > 70 +sticky( + () => flight.rssi < 30, // ON condition + () => flight.rssi > 70, // OFF condition + () => { + override.vtx.power = 4; // Executes while latched + } +); +``` + +**Parameters (variable syntax):** - **on**: Condition that latches ON - **off**: Condition that latches OFF +**Parameters (callback syntax):** +- **onCondition**: When to latch ON +- **offCondition**: When to latch OFF +- **action**: What to do while latched + **Use when:** - Warning states that need manual reset - Hysteresis/deadband behavior From 2dad94039ac2152df26b368ed27e8721f0a7b37e Mon Sep 17 00:00:00 2001 From: Ray Morris Date: Sat, 13 Dec 2025 23:12:55 -0600 Subject: [PATCH 4/4] Docs: Add let/const variables and ternary operator documentation Added documentation for: - Let/const variables for compile-time named expressions - Ternary operator for conditional value assignment - Benefits and use cases for each feature - Examples showing practical usage These features improve code readability and maintainability by allowing developers to use meaningful variable names that preserve through compile/decompile cycles. --- .../JAVASCRIPT_PROGRAMMING_GUIDE.md | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/docs/javascript_programming/JAVASCRIPT_PROGRAMMING_GUIDE.md b/docs/javascript_programming/JAVASCRIPT_PROGRAMMING_GUIDE.md index 31c17116249..7dc55be4726 100644 --- a/docs/javascript_programming/JAVASCRIPT_PROGRAMMING_GUIDE.md +++ b/docs/javascript_programming/JAVASCRIPT_PROGRAMMING_GUIDE.md @@ -222,6 +222,55 @@ if (lowVoltageWarning) { --- +##Variables + +### Let/Const Variables + +Use `let` or `const` to define reusable expressions that are compiled into the logic: + +```javascript +const { flight, override } = inav; + +// Define reusable calculations +let distanceThreshold = 500; +let altitudeLimit = 100; +let combinedCondition = flight.homeDistance > distanceThreshold && flight.altitude > altitudeLimit; + +// Use in conditions +if (combinedCondition) { + override.vtx.power = 4; +} +``` + +**Benefits:** +- Makes code more readable with named values +- Compiler automatically optimizes duplicate expressions +- Variables preserve their custom names through compile/decompile cycles + +**Important:** `let`/`const` variables are **compile-time substituted**, not runtime variables. For runtime state, use `gvar[]`. + +### Ternary Operator + +Use ternary expressions for conditional values: + +```javascript +const { flight, override } = inav; + +// Assign based on condition +let throttleLimit = flight.cellVoltage < 330 ? 25 : 50; + +if (flight.cellVoltage < 350) { + override.throttleScale = throttleLimit; +} + +// Inline in expressions +override.vtx.power = flight.homeDistance > 500 ? 4 : 2; +``` + +**Use when:** You need conditional value assignment in a single expression. + +--- + ## Available Objects ```javascript