/* * SPDX-License-Identifier: LicenseRef-CSSL-1.0 */ #include "cirdb_yaml.h" #include #include #include extern "C" { #include "common/utils/LOG/log.h" } static inline double dabs(double x) { return x < 0 ? -x : x; } int cirdb_yaml_scan(const char *yaml_path) { YAML::Node root; try { root = YAML::LoadFile(yaml_path); } catch (const YAML::Exception &e) { LOG_E(HW, "CIRDB YAML parse error in %s: %s\n", yaml_path, e.what()); return -1; } auto ents = root["entries"]; if (!ents || !ents.IsSequence()) { LOG_E(HW, "CIRDB YAML: missing or invalid 'entries' in %s\n", yaml_path); return -1; } int n = static_cast(ents.size()); LOG_I(HW, "CIRDB YAML: %d entries in %s\n", n, yaml_path); return n; } int cirdb_yaml_select(const cirdb_select_req_t *req, cirdb_entry_meta_t *out) { if (!req || !out || !req->yaml_path) { LOG_E(HW, "CIRDB YAML: invalid arguments to cirdb_yaml_select\n"); return -1; } YAML::Node root; try { root = YAML::LoadFile(req->yaml_path); } catch (const YAML::Exception &e) { LOG_E(HW, "CIRDB YAML parse error in %s: %s\n", req->yaml_path, e.what()); return -1; } auto ents = root["entries"]; if (!ents || !ents.IsSequence()) { LOG_E(HW, "CIRDB YAML: missing or invalid 'entries' in %s\n", req->yaml_path); return -1; } bool found = false; double best_cost = 1e300; cirdb_entry_meta_t best{}; // Determine if specific parameters are required bool want_specific_model = (req->want_model_id >= 0); bool want_specific_antennas = (req->want_tx > 0 && req->want_rx > 0); for (std::size_t i = 0; i < ents.size(); ++i) { const YAML::Node e = ents[i]; int pair_order = e["pair_order"].as(0); int model_id = e["model_id"].as(-1); // STRICT: model_id must match if specified if (want_specific_model && model_id != req->want_model_id) continue; int n_tx = e["n_tx"].as(0); int n_rx = e["n_rx"].as(0); // STRICT: antenna dimensions must match exactly if specified bool shape_ok = true; if (want_specific_antennas) { shape_ok = (n_tx == req->want_tx && n_rx == req->want_rx); bool shape_swap_ok = req->allow_shape_swap ? (n_tx == req->want_rx && n_rx == req->want_tx) : false; shape_ok = shape_ok || shape_swap_ok; if (!shape_ok) continue; // Skip entries with wrong antenna configuration } // STRICT: antenna dimensions must match exactly if specified if (want_specific_antennas) { if (n_tx != req->want_tx || n_rx != req->want_rx) continue; // Skip entries with wrong antenna configuration } float ds_ns = e["ds_ns"].as(0.0f); float sp = e["speed_mps"].as(0.0f); // FLEXIBLE: delay spread and speed - find closest match using cost function double cds = 0.0; double csp = 0.0; if (req->want_ds_ns > 0) cds = dabs((double)ds_ns - (double)req->want_ds_ns); if (req->want_speed_mps > 0) csp = dabs((double)sp - (double)req->want_speed_mps); double cost = (req->w_ds > 0 ? req->w_ds : 1.0) * cds + (req->w_speed > 0 ? req->w_speed : 0.2) * csp; if (!found || cost < best_cost) { best_cost = cost; found = true; best.model_id = model_id; best.n_tx = n_tx; best.n_rx = n_rx; best.L = e["L"].as(0); best.S = e["S"].as(0); best.fs_hz = e["fs_hz"].as(0.0); best.snapshot_dt_s = e["snapshot_dt_s"].as(0.0); best.ds_ns = ds_ns; best.speed_mps = sp; best.pair_order = pair_order; best.offset_bytes = e["offset_bytes"].as(0); best.nbytes = e["nbytes"].as(0); } } if (!found) return 0; *out = best; return 1; }