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 = [
55export type FmcwWaveformType = (typeof FMCW_WAVEFORM_TYPES)[number];
57export function isFmcwWaveformType(
58 waveformType: string | undefined
59): waveformType is FmcwWaveformType {
60 return FMCW_WAVEFORM_TYPES.includes(waveformType as FmcwWaveformType);
63export function isRecord(value: unknown): value is Record<string, unknown> {
64 return typeof value === 'object' && value !== null && !Array.isArray(value);
67export function isDechirpMode(value: unknown): value is DechirpMode {
68 return typeof value === 'string' && DECHIRP_MODES.has(value as DechirpMode);
71export function isDechirpReferenceSource(
73): value is DechirpReferenceSource {
75 typeof value === 'string' &&
76 DECHIRP_REFERENCE_SOURCES.has(value as DechirpReferenceSource)
80export function getDechirpMode(config: unknown): DechirpMode {
81 if (!isRecord(config)) {
84 return isDechirpMode(config.dechirp_mode) ? config.dechirp_mode : 'none';
87export function getDechirpReferenceSource(
89): DechirpReferenceSource {
90 if (!isRecord(reference)) {
93 return isDechirpReferenceSource(reference.source)
98export function getFmcwIfChainConfig(config: unknown): FmcwIfChainConfig {
99 if (!isRecord(config)) {
103 const ifChainConfig: FmcwIfChainConfig = {};
104 if (typeof config.if_sample_rate === 'number') {
105 ifChainConfig.if_sample_rate = config.if_sample_rate;
107 if (typeof config.if_filter_bandwidth === 'number') {
108 ifChainConfig.if_filter_bandwidth = config.if_filter_bandwidth;
110 if (typeof config.if_filter_transition_width === 'number') {
111 ifChainConfig.if_filter_transition_width =
112 config.if_filter_transition_width;
114 return ifChainConfig;
117export function createDechirpReference(
118 source: DechirpReferenceSource,
119 currentReference?: unknown
121 const current = isRecord(currentReference) ? currentReference : {};
128 ...(typeof current.transmitter_name === 'string'
129 ? { transmitter_name: current.transmitter_name }
135 ...(typeof current.waveform_name === 'string'
136 ? { waveform_name: current.waveform_name }
142export function normalizeFmcwModeConfig(
144): ReceiverFmcwModeConfig {
145 if (!isRecord(config)) {
149 const dechirpMode = getDechirpMode(config);
150 if (dechirpMode === 'none') {
154 const reference = createDechirpReference(
155 getDechirpReferenceSource(config.dechirp_reference),
156 config.dechirp_reference
160 dechirp_mode: dechirpMode,
161 dechirp_reference: reference,
162 ...getFmcwIfChainConfig(config),
166export function createFmcwModeConfig(
167 dechirpMode: DechirpMode,
168 currentConfig?: unknown
169): ReceiverFmcwModeConfig {
170 if (dechirpMode === 'none') {
174 const current = normalizeFmcwModeConfig(currentConfig);
176 dechirp_mode: dechirpMode,
178 current.dechirp_reference ?? createDechirpReference('attached'),
179 ...getFmcwIfChainConfig(current),