312 lines
11 KiB
C++
312 lines
11 KiB
C++
#include "main.h"
|
|
#include <chrono>
|
|
#include <csignal>
|
|
#include <cstring>
|
|
#include <fstream>
|
|
#include <functional>
|
|
#include <iostream>
|
|
#include <random>
|
|
#include <sstream>
|
|
#include <stack>
|
|
#include <string>
|
|
#include <thread>
|
|
#include <vector>
|
|
#include <iostream>
|
|
#include <optional>
|
|
#include "Psc_Cpp_Core/Base/JSON.h"
|
|
#include "Psc_Cpp_Core/Base/ThreadManager.h"
|
|
#include "Psc_Cpp_Core/Base/global_include.h"
|
|
#include "Psc_Cpp_Core/Shared_Memory/Shared_Memory.h"
|
|
#include "Psc_Cpp_Core/system/export.h"
|
|
#include "Psc_Cpp_Core/spdlog/export.h"
|
|
#include "Psc_Cpp_Core/Base/SM_RingBuffer.h"
|
|
#include "Dll_Global.h"
|
|
#include <string_view>
|
|
#ifndef ECAP_ADSB_PLAYBACK_SPEED_RATE
|
|
#define ECAP_ADSB_PLAYBACK_SPEED_RATE 20.0
|
|
#endif
|
|
#ifndef ECAP_ADSB_PLAYBACK_LOOP
|
|
#define ECAP_ADSB_PLAYBACK_LOOP 1
|
|
#endif
|
|
#ifndef ECAP_ADSB_PLAYBACK_USE_VIRTUAL_TIME
|
|
#define ECAP_ADSB_PLAYBACK_USE_VIRTUAL_TIME 1
|
|
#endif
|
|
#ifndef ECAP_ADSB_PLAYBACK_MAX_BATCH_LINES
|
|
#define ECAP_ADSB_PLAYBACK_MAX_BATCH_LINES 512
|
|
#endif
|
|
#ifndef ECAP_ADSB_PLAYBACK_FALLBACK_LINE_INTERVAL_SEC
|
|
#define ECAP_ADSB_PLAYBACK_FALLBACK_LINE_INTERVAL_SEC 0.02
|
|
#endif
|
|
std::vector<std::string> ddd = {
|
|
"1A 33 1A 1A F1 DA 08 2A 73 60 8D 78 12 0A EA 28 88 64 25 3C 08 33 22 41",
|
|
"1A 33 1A 1A F1 D9 13 EA E7 11 8D 78 1D 40 58 BF 41 E2 45 49 09 7B C8 24",
|
|
"1A 33 1A 1A F1 DA 08 2A 73 60 8D 78 12 0A EA 28 88 64 25 3C 08 33 22 41",
|
|
"1A 33 1A 1A F1 DA D4 35 F9 69 A0 00 15 BC C2 9E 14 F0 A8 00 00 DE E7 37",
|
|
"1A 33 1A 1A F1 DB 45 5D 1C 68 A0 00 15 BC FF DD 11 2B 60 04 DB 2F 06 E2",
|
|
"1A 33 1A 1A F1 DD 0F 74 3E 20 A0 00 15 BC EE 0A 13 30 20 37 FF A9 CE DC",
|
|
"1A 33 1A 1A F1 DD 50 97 59 30 8D 78 00 6C E1 1F 2E 00 00 00 00 09 43 55",
|
|
"1A 33 1A 1A F1 DD 73 6B 25 2B 8D 78 16 2D F8 33 00 06 00 49 B8 CF B0 D7",
|
|
"1A 33 1A 1A F1 DD F1 C2 C2 1D A0 00 15 BC 10 03 0A 80 ED 00 00 98 54 C8",
|
|
"1A 33 1A 1A F1 DE 62 E9 B6 2A A0 00 15 BC 10 03 0A 80 ED 00 00 98 54 C8",
|
|
"1A 33 1A 1A F1 DE B4 E1 1E 23 8D 79 A0 53 EA 3E C8 66 57 3C 08 71 74 65",
|
|
"1A 33 1A 1A F1 DF 17 8E 3F 5D 8D 78 00 6C 58 63 44 5B 32 CB 60 C5 DD 2E",
|
|
"1A 33 1A 1A F1 DF 3E 49 FD 76 A0 00 0E 3E A8 7A 23 26 E1 0C 22 4E D9 88",
|
|
"1A 33 1A 1A F1 DF AF 71 5F 6C A0 00 0E 3E A8 7A 23 26 E1 0C 22 4E D9 88",
|
|
"1A 33 1A 1A F1 E2 0A DD 76 2A A0 00 11 B1 B5 E8 00 30 AA 00 00 D5 D0 A3",
|
|
};
|
|
std::string get_absb() {
|
|
static size_t index = 0; // 静态变量用于保存当前读取位置
|
|
index++;
|
|
if (index == ddd.size()) {
|
|
index = 0;
|
|
}
|
|
return ddd[index];
|
|
}
|
|
class TextLineReader {
|
|
public:
|
|
struct Playback_Line {
|
|
std::string text;
|
|
double virtual_second{};
|
|
};
|
|
explicit TextLineReader(std::string_view file_path) {
|
|
load(file_path);
|
|
}
|
|
std::size_t read(char* buf, std::size_t len) {
|
|
if (lines_.empty() || len == 0) {
|
|
return 0;
|
|
}
|
|
std::string ret;
|
|
std::size_t count = 0;
|
|
while (count < ECAP_ADSB_PLAYBACK_MAX_BATCH_LINES) {
|
|
if (index_ >= lines_.size()) {
|
|
if (ECAP_ADSB_PLAYBACK_LOOP) {
|
|
reset();
|
|
}
|
|
else {
|
|
break;
|
|
}
|
|
}
|
|
if (!line_ready(lines_[index_])) {
|
|
break;
|
|
}
|
|
const auto& line = lines_[index_].text;
|
|
auto next_size = ret.size() + line.size() + 1;
|
|
if (!ret.empty() && next_size > len) {
|
|
break;
|
|
}
|
|
ret += line;
|
|
ret += '\n';
|
|
++index_;
|
|
++count;
|
|
if (!ECAP_ADSB_PLAYBACK_USE_VIRTUAL_TIME) {
|
|
break;
|
|
}
|
|
}
|
|
auto copy_size = ret.size();
|
|
if (copy_size > len) {
|
|
copy_size = len;
|
|
}
|
|
std::memcpy(buf, ret.data(), copy_size);
|
|
return copy_size;
|
|
}
|
|
void reset() {
|
|
index_ = 0;
|
|
true_start_time_ = clock::now();
|
|
start_virtual_second_ = lines_.empty() ? 0 : lines_.front().virtual_second;
|
|
}
|
|
std::size_t size() const {
|
|
return lines_.size();
|
|
}
|
|
bool empty() const {
|
|
return lines_.empty();
|
|
}
|
|
private:
|
|
using clock = std::chrono::steady_clock;
|
|
void load(std::string_view file_path) {
|
|
std::ifstream file{std::string(file_path)};
|
|
// std::cout << "抛出异常" << std::endl;
|
|
// throw std::runtime_error("222");
|
|
if (!file.is_open()) {
|
|
auto err = "Failed to open file: " + std::string(file_path);
|
|
std::cout << err << std::endl;
|
|
std::exit(895);
|
|
throw std::runtime_error(err);
|
|
}
|
|
std::string line;
|
|
std::optional<double> last_day_second;
|
|
std::uint64_t day_offset = 0;
|
|
std::size_t fallback_index = 0;
|
|
while (std::getline(file, line)) {
|
|
auto day_second = parse_day_second(line);
|
|
if (!day_second.has_value()) {
|
|
day_second = fallback_index * ECAP_ADSB_PLAYBACK_FALLBACK_LINE_INTERVAL_SEC;
|
|
}
|
|
if (last_day_second.has_value() && day_second.value() + 3600.0 < last_day_second.value()) {
|
|
++day_offset;
|
|
}
|
|
lines_.push_back({line, day_offset * 86400.0 + day_second.value()});
|
|
last_day_second = day_second;
|
|
++fallback_index;
|
|
}
|
|
reset();
|
|
}
|
|
bool line_ready(const Playback_Line& line) const {
|
|
if (!ECAP_ADSB_PLAYBACK_USE_VIRTUAL_TIME) {
|
|
return true;
|
|
}
|
|
return line.virtual_second <= current_virtual_second();
|
|
}
|
|
double current_virtual_second() const {
|
|
auto elapsed = std::chrono::duration<double>(clock::now() - true_start_time_).count();
|
|
return start_virtual_second_ + elapsed * ECAP_ADSB_PLAYBACK_SPEED_RATE;
|
|
}
|
|
static std::optional<double> parse_day_second(std::string_view line) {
|
|
auto bytes = parse_hex_bytes(line);
|
|
if (!bytes.has_value()) {
|
|
return std::nullopt;
|
|
}
|
|
auto packet = unescape_packet(bytes.value());
|
|
if (packet.size() < 8 || packet[0] != 0x1a) {
|
|
return std::nullopt;
|
|
}
|
|
std::uint64_t raw = 0;
|
|
for (std::size_t i = 2; i < 8; ++i) {
|
|
raw = (raw << 8) | packet[i];
|
|
}
|
|
auto daysec = static_cast<std::uint32_t>((raw >> 30) & 0x3ffff);
|
|
auto nanosec = static_cast<std::uint32_t>(raw & 0x3fffffff);
|
|
return daysec + nanosec / 1000000000.0;
|
|
}
|
|
static std::optional<std::vector<std::uint8_t>> parse_hex_bytes(std::string_view line) {
|
|
std::vector<std::uint8_t> ret;
|
|
int high = -1;
|
|
for (char ch : line) {
|
|
int value = hex_value(ch);
|
|
if (value < 0) {
|
|
if (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n') {
|
|
continue;
|
|
}
|
|
return std::nullopt;
|
|
}
|
|
if (high < 0) {
|
|
high = value;
|
|
}
|
|
else {
|
|
ret.push_back(static_cast<std::uint8_t>((high << 4) | value));
|
|
high = -1;
|
|
}
|
|
}
|
|
if (high >= 0) {
|
|
return std::nullopt;
|
|
}
|
|
return ret;
|
|
}
|
|
static int hex_value(char ch) {
|
|
if (ch >= '0' && ch <= '9') {
|
|
return ch - '0';
|
|
}
|
|
if (ch >= 'a' && ch <= 'f') {
|
|
return ch - 'a' + 10;
|
|
}
|
|
if (ch >= 'A' && ch <= 'F') {
|
|
return ch - 'A' + 10;
|
|
}
|
|
return -1;
|
|
}
|
|
static std::vector<std::uint8_t> unescape_packet(const std::vector<std::uint8_t>& bytes) {
|
|
std::vector<std::uint8_t> ret;
|
|
ret.reserve(bytes.size());
|
|
for (std::size_t i = 0; i < bytes.size(); ++i) {
|
|
ret.push_back(bytes[i]);
|
|
if (bytes[i] == 0x1a && i + 1 < bytes.size() && bytes[i + 1] == 0x1a) {
|
|
++i;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
private:
|
|
std::vector<Playback_Line> lines_;
|
|
std::size_t index_ = 0;
|
|
clock::time_point true_start_time_{clock::now()};
|
|
double start_virtual_second_ = 0;
|
|
};
|
|
std::size_t adsb_read(char* buf, std::size_t len) {
|
|
static TextLineReader reader(get_exe_dir() + "/ADS-B_195_0205.txt");
|
|
auto l = reader.read(buf, len);
|
|
/*static Frequency_Limit fl;
|
|
if (fl.test()) {
|
|
std::cout << "adsb_read" << VAR_STR_2(l, len) << std::endl;
|
|
}*/
|
|
return l;
|
|
}
|
|
int adsb_set_iq_cbk(iq_cbk_t recv_cbk, void* pusr) {
|
|
auto dg = Dll_Global::instance();
|
|
dg->recv_cbk = recv_cbk;
|
|
dg->puser = pusr;
|
|
dg->init_when_dll();
|
|
return 0;
|
|
}
|
|
int adsb_set_less_30Mhz_ddc_param(uint64_t cf_hz, uint64_t sf_hz, uint64_t bw_hz, int8_t sw) {
|
|
auto dg = Dll_Global::instance();
|
|
dg->center_freq = cf_hz;
|
|
dg->sample_rate = sf_hz; // 设置采样率
|
|
dg->band_width = bw_hz;
|
|
return 0;
|
|
}
|
|
int adsb_set_less_30Mhz_fft_param(uint64_t fftWin, uint64_t fftLen, int fftPeriod_ms, int8_t sw) {
|
|
auto dg = Dll_Global::instance();
|
|
dg->fft_point_number = fftLen;
|
|
dg->fft_period_ms = fftPeriod_ms;
|
|
dg->fft_win_type = (UHD_FFTWin)fftWin;
|
|
return 0;
|
|
}
|
|
int main() {
|
|
init_signal_config();
|
|
auto dg = Dll_Global::instance();
|
|
dg->init_when_exe();
|
|
bool debug = false;
|
|
auto mb = get_system_memory() / (1024 * 1024);
|
|
auto gb = mb / (1024);
|
|
std::cout << "当前系统的物理内存大小" << mb << " MB" << std::endl;
|
|
std::cout << "当前系统的物理内存大小" << gb << " GB" << std::endl;
|
|
dg->dtm.test_and_start_thread("dsp共享内存数据推送", [dg](std::atomic<bool>& running) {
|
|
bool debug = true;
|
|
while (running) {
|
|
auto list = dg->iq_memory_buffer.get_all();
|
|
// 释放内存池
|
|
Pool_Guard pg(&dg->iq_memory_buffer.pool, list);
|
|
if (debug && list.size() > 1000) {
|
|
static Frequency_Limit fl(1.0 / 60.0);
|
|
std::ostringstream oss;
|
|
oss << get_current_millisecond_timestamp() << " 警告: dsp共享内存数据推送数据过多 当前数据队列长度:" << list.size() <<
|
|
std::endl;
|
|
if (fl.test()) {
|
|
std::cout << oss.str() << std::endl;
|
|
}
|
|
}
|
|
if (list.empty()) {
|
|
std::this_thread::sleep_for(std::chrono::microseconds(1));
|
|
continue;
|
|
}
|
|
auto frame_number = list.size();
|
|
static Frequency_Limit fl(freq);
|
|
if (fl.test()) {
|
|
std::cout << dg->rb->state_str() << " dsp数据推送" << frame_number << "条" << std::endl;
|
|
}
|
|
for (int i = 0; i < frame_number; i++) {
|
|
auto buf = list[i];
|
|
dg->handle_2112(buf->data());
|
|
}
|
|
}
|
|
});
|
|
while (!stop_program) {
|
|
dg->handle_json_call();
|
|
}
|
|
if (stop_program == SIGINT) {
|
|
std::cout << "开始关闭所有子线程!" << std::endl;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|