# Layout reference

Layouts describe how widgets are arranged on the screen. They live on the SD
card as `cfg/layout/<name>.jsonc`. When you edit a layout file over USB mass
storage, the instrument re-validates and applies it the next time the SD card
is re-inserted.

## Layout file structure

```jsonc
{
  "widgets": [
    {
      "label": "Average Vario",          // optional, shown above the widget
      "position": [x, y],                 // grid cells, top-left corner
      "size":     [w, h],                 // grid cells
      "border":   true,                   // optional, draw widget border
      "frameSkip": 0,                     // optional, update throttling

      "content": [
        {
          "type":   "value",              // widget type (see below)
          "source": "vario.average",      // value source (see below)
          "action": "unitToggle",         // optional interaction
          /* content-type-specific params */
          "precision": 1
        }
      ]
    }
  ]
}
```

A widget can have multiple content entries (e.g. a vario value stacked with a
vertical meter). Top-level `label` accepts an array, in which case the label
cycles through alternates driven by widget state.

## Widget types

| `type`            | Purpose                                                          |
|-------------------|------------------------------------------------------------------|
| `value`           | Numeric value, unit-aware. Default for almost every source.      |
| `meter.vertical`  | Bar-style analog vario meter.                                    |
| `duration`        | Formats a seconds value as `HH:MM:SS` / `MM:SS`.                 |
| `direction`       | Converts a degrees value to a compass string.                    |
| `thermalAssist`   | Bird's-eye view of the flight trace / thermal core.              |

### Common parameters

| Parameter   | Where  | Meaning                                                    |
|-------------|--------|------------------------------------------------------------|
| `border`    | widget | Draw a 1px border around the widget cell.                  |
| `frameSkip` | widget | Skip N frames between content redraws (perf/battery).      |
| `label`     | source | Override the displayed label for a `value`.                |
| `unit`      | source | Override the unit suffix.                                  |
| `scale`     | source | Multiply the raw value by this before display.             |
| `offset`    | source | Add this to the raw value before `scale` is applied.       |

### Text-based widgets — extra params

Apply to `value`, `duration`, and `direction`.

| Parameter     | Meaning                                                               |
|---------------|-----------------------------------------------------------------------|
| `maxFontSize` | Cap on the auto-selected font line height, in pixels. `0` (default) lets the widget pick the largest font that fits. Use to keep a value from dominating its cell. |

### `value` — extra params

| Parameter   | Meaning                                  |
|-------------|------------------------------------------|
| `precision` | Fractional digits (default varies).      |

### `direction` — extra params

| Parameter   | Meaning                                                      |
|-------------|--------------------------------------------------------------|
| `precision` | `1` → 4 points (N/E/S/W), `2` → 8 points (default), `3` → 16 points, `4` → 16 points with dash grouping. |

### `meter.vertical` — extra params

No widget-specific parameters; the meter auto-switches scale to imperial when
its `source` is `vario.*.imperial`.

### `thermalAssist` — extra params

| Parameter          | Default | Meaning                                                       |
|--------------------|---------|---------------------------------------------------------------|
| `range`            | 200     | Visible range (shorter axis), metres.                         |
| `rangeHint`        | 100     | Radius of the reference ring, metres.                         |
| `varioOffset`      | 0       | Offset added to vario before dot sizing.                      |
| `varioScale`       | 1       | Multiplier for dot size vs. vario value.                      |
| `windCompensation` | 1       | Strength of wind-drift compensation.                          |
| `windArrowSize`    | 0       | Wind arrow length in pixels. `0` auto-scales with wind speed (10–30 px). |
| `align`            | 0       | `0` GNSS course, `1` last sample, `2` last sample + wind, `3` north-up. |

### QNH-specific params (`value` + baro-altitude source)

| Parameter   | Meaning                                                     |
|-------------|-------------------------------------------------------------|
| `qnh`       | QNH in hPa used for altitude; writable via `qnhAdjust`.     |
| `qnhIndex`  | Slot index in the saved QNH array (0…9).                    |

### Dummy source params (debug / previews)

Used only with `source: "dummy"`.

| Parameter       | Default | Meaning                                                |
|-----------------|---------|--------------------------------------------------------|
| `dummy.period`  | 5       | Waveform period in seconds.                            |
| `dummy.offset`  | 0       | Phase offset (0…1).                                    |
| `dummy.min`     | 0       | Minimum value.                                         |
| `dummy.max`     | 100     | Maximum value.                                         |
| `dummy.shape`   | 0       | `-1` off, `0` saw, `1` triangle, `2` ease, `3` sine.   |

## Value sources

Most sensor values have `.metric` / `.imperial` variants — the bare name is an
alias for `.metric`. Use the unit-suffixed names when you need a specific
unit regardless of user settings.

### Vario

| Source                                 | Unit             | Notes                                             |
|----------------------------------------|------------------|---------------------------------------------------|
| `vario.instant[.metric]`               | m/s              | Instantaneous filtered vario.                     |
| `vario.instant.imperial`               | 100 ft/min       |                                                   |
| `vario.digital[.metric]`               | m/s              | Damped vario for digital display.                 |
| `vario.digital.imperial`               | 100 ft/min       |                                                   |
| `vario.average[.metric]`               | m/s              | Rolling-average vario.                            |
| `vario.average.imperial`               | 100 ft/min       |                                                   |
| `vario.glide`                          | 1:x              | Glide ratio; NaN when not moving forward.         |
| `vario.glide-or-average[.metric]`      | 1:x / m/s        | Shows glide while gliding, else average.          |
| `vario.glide-or-average.imperial`      | 1:x / 100 ft/min |                                                   |

### Barometric

| Source                           | Unit   | Notes                               |
|----------------------------------|--------|-------------------------------------|
| `baro.pressure`                  | hPa    |                                     |
| `baro.temperature`               | °C     |                                     |
| `baro.altitude[.m\|.metric]`     | m      | QNH-adjusted; uses slot `qnhIndex`. |
| `baro.altitude[.ft\|.imperial]`  | ft     | QNH-adjusted.                       |
| `baro.altitude.fl`               | FL     | Flight level, QNE (1013.25).        |

### GNSS

| Source                                 | Unit   | Notes                                         |
|----------------------------------------|--------|-----------------------------------------------|
| `gnss.altitude[.m\|.metric]`           | m      | Raw GNSS altitude.                            |
| `gnss.altitude[.ft\|.imperial]`        | ft     |                                               |
| `gnss.altitude.fl`                     | FL     |                                               |
| `gnss.heading`                         | deg    | Course over ground.                           |
| `gnss.latitude`                        | °      | Current latitude, magnitude only; unit is `N`/`S` per sign. |
| `gnss.longitude`                       | °      | Current longitude, magnitude only; unit is `E`/`W` per sign. |
| `gnss.groundspeed[.kmh\|.kph\|.metric]`| km/h   |                                               |
| `gnss.groundspeed[.mph\|.imperial]`    | mph    |                                               |
| `gnss.groundspeed.knots`               | kt     |                                               |
| `gnss.ground[.m\|.metric]`             | m      | Terrain elevation (AGL baseline).             |
| `gnss.ground[.ft\|.imperial]`          | ft     |                                               |
| `gnss.agl[.m\|.metric]`                | m      | Height above terrain.                         |
| `gnss.agl[.ft\|.imperial]`             | ft     |                                               |
| `gnss.ground-gradient`                 | —      | Terrain slope (unit-less ratio).              |
| `gnss.wind.speed[.mps]`                | m/s    |                                               |
| `gnss.wind.speed.fts`                  | ft/s   |                                               |
| `gnss.wind.speed[.kmh\|.kph\|.metric]` | km/h   |                                               |
| `gnss.wind.speed[.mph\|.imperial]`     | mph    |                                               |
| `gnss.wind.speed.knots`                | kt     |                                               |
| `gnss.wind.direction`                  | deg    | Meteorological convention.                    |
| `gnss.airspeed[.kmh\|.kph\|.metric]`   | km/h   | Estimated true airspeed (ground + wind).      |
| `gnss.airspeed[.mph\|.imperial]`       | mph    |                                               |
| `gnss.airspeed.knots`                  | kt     |                                               |

### Flight

| Source                                     | Unit | Notes                                                              |
|--------------------------------------------|------|--------------------------------------------------------------------|
| `flight.duration`                          | s    | Time since flight start (NaN when not flying).                     |
| `flight.duration.last`                     | s    | Duration of the last / current flight.                             |
| `flight.thermal.gain[.m\|.metric]`         | m    | Altitude gained in the current thermal (or the last one after exit). |
| `flight.thermal.gain[.ft\|.imperial]`      | ft   |                                                                    |

### Display voltages (diagnostics)

`lcd.vgh`, `lcd.vgl`, `lcd.vshp`, `lcd.vslp`, `lcd.vshn`, `lcd.vsln`,
`lcd.vsip`, `lcd.vskp`, `lcd.vsin`, `lcd.vskn` — paired with the `adjust`
action to calibrate the display.

### Preview / testing

| Source  | Notes                                                         |
|---------|---------------------------------------------------------------|
| `dummy` | Configurable waveform for previewing layouts without sensors. |

## Actions

Actions receive button events when the widget is focused.

| `action`        | Keys                 | Effect                                                          |
|-----------------|----------------------|-----------------------------------------------------------------|
| `qnhAdjust`     | Up / Down            | ±2 hPa on the bound QNH slot.                                   |
| `qnhAdjust`     | Next                 | Toggle metric / imperial unit.                                  |
| `unitToggle`    | Next                 | Toggle metric / imperial unit.                                  |
| `adjust`        | Up / Down            | Nudge the source's `$adjust` parameter (e.g. LCD voltages).     |
| `flightControl` | Next                 | Toggle flight-active state (manual start / stop).               |
| `dummyToggle`   | Up / Down            | Cycle `dummy.shape` (off / saw / triangle / ease / sine).       |
