Skip to content

Configuration Schema

greghulette edited this page Aug 6, 2026 · 4 revisions

Configuration Schema

This is the full structure of NaviCore's configuration object — the data payload of a GET_CONFIG reply and a SET_CONFIG command (see Serial JSON Protocol). It's also exactly what the config tool's Export produces and Import consumes. Field names and types here are taken straight from the firmware (rc_config.h).

You normally never hand-edit this — the config tool builds it for you. This page is for scripting, backups, and understanding an exported file.


Top-level object

{
  "txModel": 0,                 // 0 = Tandem X18, 1 = Twin X-Lite, 2 = Twin X20
  "threeAxisGimbals": false,    // X20 only: enables J5/J6 twist + stick-click slots 19/20
  "sbusOutEnabled": false,      // re-emit SBUS frames on the SBUS-OUT pin (off saves the passthrough tee)
  "boardType": 0,               // hardware pin profile: 0 = NaviCore v2 PCB, 1 = WCB HW 3.2
  "maeGateMs": 250,             // remote skip-if-running "busy" reply validity / fail-open window (ms)
  "tapWindowMs": 500,           // multi-tap detection window (ms); values < 100 are clamped up to the 500 ms default
  "matrixChannel": 7,           // SBUS channel carrying the button matrix
  "matrixDebounceFrames": 1,    // 1-4; raise on a noisy analog matrix
  "funcBindings": { "mode": 4 },// which switch selects mode (index; 4 = SE by default)
  "peerEvent":  {  },          // new-WCB-peer event: passive alert + action list
  "thresholds": [  ],          // matrix button PWM bands  (see below)
  "mappings":   {  },          // per-mode, per-button action lists
  "switches":   {  },          // SA-SJ channel + per-position actions
  "knobs":      {  },          // analog sources (knobs / sliders / gimbal axes)
  "hcrDest":    {  },          // global HCR destination
  "mp3Dest":    {  },          // global MP3 Trigger destination
  "dfpDest":    {  },          // global DFPlayer Mini destination
  "maestros":   [  ],          // 8 Maestro-location slots
  "wledSlots":  [  ],          // per-id WLED routing table
  "auxBaud":    {  },          // S3 / S4 / S5 / local-Maestro baud
  "smoothProfiles": [  ],      // 6 named Maestro speed/accel easing profiles
  "wcbNetwork": {  }           // ESP-NOW credentials
}

Any top-level key you omit in a SET_CONFIG is left unchanged on the board — so you can save just the branch you edited. (The config tool does exactly this: it diffs against the last load and ships only what changed.)


thresholds[] — matrix button bands

One entry per matrix slot (36 total). A button "presses" when the matrix channel's value lands in [minPwm, maxPwm]. All 36 slots decode, debounce, tap, and dispatch through the exact same path — the split is only about where they come from:

  • 1-20 — physical buttons drawn on the TX graphic.
  • 21 — the inert "Unassigned" sentinel (band 0/0 never matches; kept so the index math stays fixed).
  • 22-36 — 15 user-defined logical buttons: extra PWM bands on the same matrix channel, not tied to any physical control. They default inert (0/0) until you assign a band + actions in the config tool's Logical Buttons panel.
{ "id": 1, "label": "B1", "minPwm": 1799, "maxPwm": 1823 }
Field Type Meaning
id int 1-36 matrix slot number (1-21 physical, 22-36 logical)
label string display name ("B1", "T4 Left", "Logical 1", …)
minPwm / maxPwm int inclusive SBUS-value band; 0/0 = unassigned/inert

Calibration writes these for your radio. Slots 19/20 are the X20 stick-clicks; 21 is the inert Unassigned sentinel.


mappings{} — what each button does

Keyed by a composite string "<mode*100 + slot>":

  • "107"mode 1, slot 7
  • "312"mode 3, slot 12

Only buttons that have actions (or exclusive:true) are serialized.

"107": {
  "exclusive": false,           // false = cumulative tiers, true = only the matched tier
  "t1": [ <action>,  ],        // single-tap actions
  "t2": [ <action>,  ],        // double-tap
  "t3": [ <action>,  ],        // triple-tap
  "t1note": "open dome"         // optional per-tier caption (also t2note / t3note)
}

Each tier holds up to 5 actions, plus an optional t1note / t2note / t3note caption string (round-tripped for display, no runtime effect). See Action objects below. Exclusive vs. cumulative is explained in Config Tool Guide.


switches{} — SA–SJ

Keyed by switch label. A switch fires its position's actions when it changes to that position.

"SA": {
  "channel": 8,                 // 0 = unassigned
  "positions": 3,               // 2 or 3
  "p0": [ <action>,  ],        // actions for position 0 (down)
  "p1": [ <action>,  ],        // position 1 (mid, 3-pos only)
  "p2": [ <action>,  ],        // position 2 (up)
  "p0note": "lights off"        // optional per-position caption (also p1note / p2note)
}

Labels: SA SB SC SD SE SF SG SH SI SJ. Each position may also carry an optional p0note / p1note / p2note caption string.


knobs{} — analog sources

Keyed by label: S1 S2 LS RS S3 J1 J2 J3 J4 J5 J6. Each continuously maps its position to one or more outputs.

"S1": {
  "channel": 5,                 // 0 = unassigned
  "function": 1,                // 0 = none, 1 = Maestro pass-through, 2 = HCR volume
  "reverse": false,             // invert around centre
  "modeAware": false,           // ALWAYS emitted; true = outputs follow the mode switch (adds outputs2/outputs3)
  "modeSwitchOverride": -1,     // ALWAYS emitted; -1 = the global mode switch, else a switch index 0-7 (SA-SH)
  "outputs": [
    { "target": 3, "maestroCh": 5, "posMin": 4000, "posMax": 8000 }
  ]
}

modeAware and modeSwitchOverride are always present on every knob. Two more fields appear only when set: smoothProfile (int, smoothing-profile index 0-5; omitted when none/-1) and easeSwitchOverride (bool; emitted only when true — the switch's active easing then overrides this knob's own profile). When modeAware is true, the knob also carries outputs2 and outputs3 arrays (same shape as outputs) holding the mode-2 and mode-3 output sets; outputs is the mode-1 set.

outputs[] (up to 10 per source):

Field function:1 (Maestro) function:2 (HCR volume)
target Maestro slot 1-8 HCR audio chan 0=V, 1=A, 2=B
maestroCh servo channel 0-31 unused
posMin / posMax quarter-µs at SBUS min/max (e.g. 4000–8000) volume 0-99 at SBUS min/max
midClosed OPTIONAL bool — stick centre maps to posMin, so only the upper half of travel sweeps posMin→posMax (emitted only when true) unused
releaseIdleMs OPTIONAL — auto-release (de-energize) the servo after this many ms with no stick movement; 0/omitted = never unused

Action objects

Used inside mappings tiers (t1/t2/t3) and switch positions (p0/p1/p2). Every action may also carry "delay": <ms> (fired after the press) and "note": "<label>". The wcb_unicast, wcb_broadcast, and maestro types may additionally carry "skipRunning": true — the via-WCB Maestro skip-if-already-running gate (emitted only when set).

type Fields Notes
wcb_unicast target (WCB ID "1"–"20"), cmd one board
wcb_broadcast cmd all boards
maestro target (slot "1"–"8"), cmd location set in maestros[]; maestro_remote also accepted on input
maestro_local cmd legacy/local-only form
serial port ("S3"/"S4"), cmd CR appended on send
hcr fn, chan, track destination is global (hcrDest)
mp3 fn, track destination is global (mp3Dest)
dfplayer fn, chan, track destination is global (dfpDest)
wled cmd (;L<id>,<verb>) per-id routing is global (wledSlots); id 0 = lowest local slot. See WLED and HCR Audio
record cmd (clip name) toggle recording. See Record and Replay
play cmd (clip name), fn (loop: 0=once, 1=repeat) play a recorded clip
stop (none) stop recording (save) or playback

cmd formats and the fn/chan/track code tables are in Actions Reference.

// examples
{ "type": "wcb_broadcast", "cmd": ":PP100", "note": "dome spin" }
{ "type": "maestro", "target": "2", "cmd": "setTarget,5,6000", "delay": 600 }
{ "type": "hcr", "fn": 2, "chan": 0, "track": 80 }   // SetEmotion(Happy, 80)

Destinations & hardware

"hcrDest": { "transport": "serial", "port": "S3" }
// or:      { "transport": "wcb", "target": "5", "wcbPort": 2 }

"mp3Dest": { "transport": "serial", "port": "S4" }
// or:      { "transport": "wcb", "target": "2" }

"dfpDest": { "transport": "serial", "port": "S3" }   // the port must be at 9600 baud
// or:      { "transport": "wcb", "target": "2" }

"maestros": [                   // exactly 8 entries, slots 1-8
  { "type": 0, "device": 1 },   // type: 0 disabled / 1 local / 2 remote
                               // device: Pololu number 0-127 (Pololu protocol only — no compact-protocol support)
],

"auxBaud": { "S3": 9600, "S4": 38400, "S5": 9600, "maestro": 115200 },

"wcbNetwork": {                 // see [[WCB Network]] — changing these needs a reboot
  "macOct2": 0, "macOct3": 0,
  "password": "yourpw",
  "quantity": 4,
  "deviceId": 20,               // RC special-peer slot; leave at 20
  "channel": 1                  // ESP-NOW mesh WiFi channel 1-13 (must match every WCB); reboot to apply
}

⚠️ Over the Via WCB bridge the firmware ignores incoming wcbNetwork.deviceId / macOct2 / macOct3 / password / quantity — changing the transport you're riding on would cut you off. Edit those over direct USB. See WCB Network.


Clone this wiki locally