prop/lib/microwaveprop/propagation/mode_thresholds.ex
Graham McIntire d67186176f
fix: resolve all dialyzer type errors across project (46→0 project errors)
Type spec fixes:
- duct_usable_* return boolean→float (delegate to duct_usable_for_band)
- sanitize/1 spec includes :unicode error tuples
- match_delete/1 broadened from :ets.match_spec()
- telemetry_event local type replaces :telemetry.event/0
- wgrib2 parse_lon_val_segment corrected to tuple spec
- preloaded Ecto assoc types in get_mission/get_contact! specs

Unmatched returns:
- _ = prefix on Task.start, Oban.insert, Repo.query!, PubSub.subscribe,
  :ets.new, and if-expression returns across 18 files

Pattern match fixes:
- markdown: restructure acc!=[] guard as direct pattern match
- path_compute/pskr/skewt_location_resolver: remove dead clauses
- calibrate.aprs_144: remove unreachable format_float catch-all
- unused.ex: suppress MapSet.union no_opaque

Also: remove unused unicode_util_compat from mix.lock
2026-06-08 17:51:13 -05:00

35 lines
934 B
Elixir

defmodule Microwaveprop.Propagation.ModeThresholds do
@moduledoc """
Required-SNR thresholds (dB) for the modes the rover planner supports.
The rover predicts a per-link SNR margin; subtracting the mode's required
SNR yields "dB above decode threshold". Numbers come from the rover spec —
SSB needs full quieting, CW pulls signals well below the noise floor, and
Q65 modes go deeper still.
"""
@thresholds %{
ssb: 0.0,
cw: -18.0,
q65_60a: -24.0,
q65_120b: -26.0
}
@modes [
{:ssb, "SSB"},
{:cw, "CW"},
{:q65_60a, "Q65-60A"},
{:q65_120b, "Q65-120B"}
]
@type mode :: :ssb | :cw | :q65_60a | :q65_120b
@spec required_snr_db(mode()) :: float()
def required_snr_db(mode) when is_map_key(@thresholds, mode), do: Map.fetch!(@thresholds, mode)
@spec modes() :: [{mode(), String.t()}]
def modes, do: @modes
@spec default_mode() :: :ssb
def default_mode, do: :ssb
end