1// SPDX-License-Identifier: GPL-2.0-only
2// Copyright (c) 2026-present FERS Contributors (see AUTHORS.md).
4export type DechirpMode = 'none' | 'physical' | 'ideal';
5export type DechirpReferenceSource = 'attached' | 'transmitter' | 'custom';
7export type DechirpReference =
8 | { source: 'attached' }
9 | { source: 'transmitter'; transmitter_name?: string }
10 | { source: 'custom'; waveform_name?: string };
12export type ReceiverFmcwModeConfig = {
13 dechirp_mode?: DechirpMode;
14 dechirp_reference?: DechirpReference;
15 if_sample_rate?: number;
16 if_filter_bandwidth?: number;
17 if_filter_transition_width?: number;
20export type FmcwIfChainConfig = Pick<
21 ReceiverFmcwModeConfig,
22 'if_sample_rate' | 'if_filter_bandwidth' | 'if_filter_transition_width'
25export const DECHIRP_MODE_OPTIONS: ReadonlyArray<{
29 { value: 'none', label: 'None' },
30 { value: 'physical', label: 'Physical' },
31 { value: 'ideal', label: 'Ideal' },
34export const DECHIRP_REFERENCE_SOURCE_OPTIONS: ReadonlyArray<{
35 value: DechirpReferenceSource;
38 { value: 'attached', label: 'Attached' },
39 { value: 'transmitter', label: 'Transmitter' },
40 { value: 'custom', label: 'Custom Waveform' },
43const DECHIRP_MODES = new Set<DechirpMode>(['none', 'physical', 'ideal']);
44const DECHIRP_REFERENCE_SOURCES = new Set<DechirpReferenceSource>([
50export const FMCW_WAVEFORM_TYPES = [
56export type FmcwWaveformType = (typeof FMCW_WAVEFORM_TYPES)[number];
58export function isFmcwWaveformType(
59 waveformType: string | undefined
60): waveformType is FmcwWaveformType {
61 return FMCW_WAVEFORM_TYPES.includes(waveformType as FmcwWaveformType);
64export function isRecord(value: unknown): value is Record<string, unknown> {
65 return typeof value === 'object' && value !== null && !Array.isArray(value);
68export function isDechirpMode(value: unknown): value is DechirpMode {
69 return typeof value === 'string' && DECHIRP_MODES.has(value as DechirpMode);
72export function isDechirpReferenceSource(
74): value is DechirpReferenceSource {
76 typeof value === 'string' &&
77 DECHIRP_REFERENCE_SOURCES.has(value as DechirpReferenceSource)
81export function getDechirpMode(config: unknown): DechirpMode {
82 if (!isRecord(config)) {
85 return isDechirpMode(config.dechirp_mode) ? config.dechirp_mode : 'none';
88export function getDechirpReferenceSource(
90): DechirpReferenceSource {
91 if (!isRecord(reference)) {
94 return isDechirpReferenceSource(reference.source)
99export function getFmcwIfChainConfig(config: unknown): FmcwIfChainConfig {
100 if (!isRecord(config)) {
104 const ifChainConfig: FmcwIfChainConfig = {};
105 if (typeof config.if_sample_rate === 'number') {
106 ifChainConfig.if_sample_rate = config.if_sample_rate;
108 if (typeof config.if_filter_bandwidth === 'number') {
109 ifChainConfig.if_filter_bandwidth = config.if_filter_bandwidth;
111 if (typeof config.if_filter_transition_width === 'number') {
112 ifChainConfig.if_filter_transition_width =
113 config.if_filter_transition_width;
115 return ifChainConfig;
118export function createDechirpReference(
119 source: DechirpReferenceSource,
120 currentReference?: unknown
122 const current = isRecord(currentReference) ? currentReference : {};
129 ...(typeof current.transmitter_name === 'string'
130 ? { transmitter_name: current.transmitter_name }
136 ...(typeof current.waveform_name === 'string'
137 ? { waveform_name: current.waveform_name }
143export function normalizeFmcwModeConfig(
145): ReceiverFmcwModeConfig {
146 if (!isRecord(config)) {
150 const dechirpMode = getDechirpMode(config);
151 if (dechirpMode === 'none') {
155 const reference = createDechirpReference(
156 getDechirpReferenceSource(config.dechirp_reference),
157 config.dechirp_reference
161 dechirp_mode: dechirpMode,
162 dechirp_reference: reference,
163 ...getFmcwIfChainConfig(config),
167export function createFmcwModeConfig(
168 dechirpMode: DechirpMode,
169 currentConfig?: unknown
170): ReceiverFmcwModeConfig {
171 if (dechirpMode === 'none') {
175 const current = normalizeFmcwModeConfig(currentConfig);
177 dechirp_mode: dechirpMode,
179 current.dechirp_reference ?? createDechirpReference('attached'),
180 ...getFmcwIfChainConfig(current),