pull/402/head
AlexandreRouma 2021-09-20 19:59:35 +02:00
rodzic 9ee0951874
commit 049fc77ff6
21 zmienionych plików z 37 dodań i 383 usunięć

Wyświetl plik

@ -11,25 +11,25 @@ endif()
option(OPT_OVERRIDE_STD_FILESYSTEM "Use a local version of std::filesystem on systems that don't have it yet" OFF)
# Sources
option(OPT_BUILD_AIRSPY_SOURCE "Build Airspy Source Module (Depedencies: libairspy)" ON)
option(OPT_BUILD_AIRSPYHF_SOURCE "Build Airspy HF+ Source Module (Depedencies: libairspyhf)" ON)
option(OPT_BUILD_BLADERF_SOURCE "Build BladeRF Source Module (Depedencies: libbladeRF)" OFF)
option(OPT_BUILD_AIRSPY_SOURCE "Build Airspy Source Module (Dependencies: libairspy)" ON)
option(OPT_BUILD_AIRSPYHF_SOURCE "Build Airspy HF+ Source Module (Dependencies: libairspyhf)" ON)
option(OPT_BUILD_BLADERF_SOURCE "Build BladeRF Source Module (Dependencies: libbladeRF)" OFF)
option(OPT_BUILD_FILE_SOURCE "Wav file source" ON)
option(OPT_BUILD_HACKRF_SOURCE "Build HackRF Source Module (Depedencies: libhackrf)" ON)
option(OPT_BUILD_LIMESDR_SOURCE "Build LimeSDR Source Module (Depedencies: liblimesuite)" OFF)
option(OPT_BUILD_SDDC_SOURCE "Build SDDC Source Module (Depedencies: libusb-1.0)" OFF)
option(OPT_BUILD_RTL_SDR_SOURCE "Build RTL-SDR Source Module (Depedencies: librtlsdr)" ON)
option(OPT_BUILD_HACKRF_SOURCE "Build HackRF Source Module (Dependencies: libhackrf)" ON)
option(OPT_BUILD_LIMESDR_SOURCE "Build LimeSDR Source Module (Dependencies: liblimesuite)" OFF)
option(OPT_BUILD_SDDC_SOURCE "Build SDDC Source Module (Dependencies: libusb-1.0)" OFF)
option(OPT_BUILD_RTL_SDR_SOURCE "Build RTL-SDR Source Module (Dependencies: librtlsdr)" ON)
option(OPT_BUILD_RTL_TCP_SOURCE "Build RTL-TCP Source Module (no dependencies required)" ON)
option(OPT_BUILD_SDRPLAY_SOURCE "Build SDRplay Source Module (Depedencies: libsdrplay)" OFF)
option(OPT_BUILD_SOAPY_SOURCE "Build SoapySDR Source Module (Depedencies: soapysdr)" ON)
option(OPT_BUILD_SDRPLAY_SOURCE "Build SDRplay Source Module (Dependencies: libsdrplay)" OFF)
option(OPT_BUILD_SOAPY_SOURCE "Build SoapySDR Source Module (Dependencies: soapysdr)" ON)
option(OPT_BUILD_SPYSERVER_SOURCE "Build SpyServer Source Module (no dependencies required)" ON)
option(OPT_BUILD_PLUTOSDR_SOURCE "Build PlutoSDR Source Module (Depedencies: libiio, libad9361)" ON)
option(OPT_BUILD_PLUTOSDR_SOURCE "Build PlutoSDR Source Module (Dependencies: libiio, libad9361)" ON)
# Sinks
option(OPT_BUILD_AUDIO_SINK "Build Audio Sink Module (Depedencies: rtaudio)" ON)
option(OPT_BUILD_PORTAUDIO_SINK "Build PortAudio Sink Module (Depedencies: portaudio)" OFF)
option(OPT_BUILD_AUDIO_SINK "Build Audio Sink Module (Dependencies: rtaudio)" ON)
option(OPT_BUILD_PORTAUDIO_SINK "Build PortAudio Sink Module (Dependencies: portaudio)" OFF)
option(OPT_BUILD_NETWORK_SINK "Build Audio Sink Module (no dependencies required)" ON)
option(OPT_BUILD_NEW_PORTAUDIO_SINK "Build the new PortAudio Sink Module (Depedencies: portaudio)" OFF)
option(OPT_BUILD_NEW_PORTAUDIO_SINK "Build the new PortAudio Sink Module (Dependencies: portaudio)" OFF)
# Decoders
option(OPT_BUILD_FALCON9_DECODER "Build the falcon9 live decoder (Dependencies: ffplay)" OFF)
@ -208,4 +208,4 @@ endif ()
# Create uninstall target
configure_file(${CMAKE_SOURCE_DIR}/cmake_uninstall.cmake ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake @ONLY)
add_custom_target(uninstall ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
add_custom_target(uninstall ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)

Wyświetl plik

@ -199,7 +199,7 @@ private:
if (count < 0) { return 0; }
// For debug purposes only...
// if (nBufferFrames != count) { spdlog::warn("Buffer size missmatch, wanted {0}, was asked for {1}", count, nBufferFrames); }
// if (nBufferFrames != count) { spdlog::warn("Buffer size mismatch, wanted {0}, was asked for {1}", count, nBufferFrames); }
// for (int i = 0; i < count; i++) {
// if (_this->stereoPacker.out.readBuf[i].l == NAN || _this->stereoPacker.out.readBuf[i].r == NAN) { spdlog::error("NAN in audio data"); }
// if (_this->stereoPacker.out.readBuf[i].l == INFINITY || _this->stereoPacker.out.readBuf[i].r == INFINITY) { spdlog::error("INFINITY in audio data"); }

Wyświetl plik

@ -344,7 +344,7 @@ private:
_this->streamingEnabled = true;
// Setup syncronous transfer
// Setup synchronous transfer
bladerf_sync_config(_this->openDev, BLADERF_RX_X1, BLADERF_FORMAT_SC16_Q11, 16, _this->bufferSize, 8, 3500);
// Enable streaming

Wyświetl plik

@ -56,7 +56,7 @@ If the module meets the code quality requirements, it may be added to the offici
# JSON Formatting
The ability to add new radio band allocation identifiers and color maps relies on JSON files. Proper formatting of these JSOn files is important for reference and readability. The folowing guides will show you how to properly format the JSON files for their respective uses.
The ability to add new radio band allocation identifiers and color maps relies on JSON files. Proper formatting of these JSOn files is important for reference and readability. The following guides will show you how to properly format the JSON files for their respective uses.
**IMPORTANT: JSON File cannot contain comments, there are only in this example for clarity**
@ -98,7 +98,7 @@ Please follow this guide to properly format the JSON files for custom color maps
"name": "Short name (has to fit in the menu)",
"author": "Name of the original/main creator of the color map",
"map": [
// These are the color codes, in hexidecimal (#RRGGBB) format, for the custom color scales for the waterfall. They must be entered as strings, not integers, with the hastag/pound-symbol proceeding the 6 digit number.
// These are the color codes, in hexadecimal (#RRGGBB) format, for the custom color scales for the waterfall. They must be entered as strings, not integers, with the hastag/pound-symbol proceeding the 6 digit number.
"#000020",
"#000030",
"#000050",

Wyświetl plik

@ -80,7 +80,7 @@ namespace dsp {
if (count_r < 0) { return -1; }
if (count_l != count_r) {
spdlog::warn("ChannelsToStereo block size missmatch");
spdlog::warn("ChannelsToStereo block size mismatch");
}
volk_32f_x2_interleave_32fc((lv_32fc_t*)out.writeBuf, _in_left->readBuf, _in_right->readBuf, count_l);

Wyświetl plik

@ -171,7 +171,7 @@ namespace dsp {
_c_2T = _c_1T;
_c_1T = _c_0T;
// Perfrom interpolation the same way as for float values
// Perform interpolation the same way as for float values
if (i < 7) {
volk_32fc_32f_dot_prod_32fc((lv_32fc_t*)&_p_0T, (lv_32fc_t*)&delay[i], INTERP_TAPS[(int)roundf(_mu * 128.0f)], 8);
}

Wyświetl plik

@ -1,345 +0,0 @@
#pragma once
#include <dsp/block.h>
namespace dsp {
class ComplexToStereo : public generic_block<ComplexToStereo> {
public:
ComplexToStereo() {}
ComplexToStereo(stream<complex_t>* in) { init(in); }
static_assert(sizeof(complex_t) == sizeof(stereo_t));
void init(stream<complex_t>* in) {
_in = in;
generic_block<ComplexToStereo>::registerInput(_in);
generic_block<ComplexToStereo>::registerOutput(&out);
generic_block<ComplexToStereo>::_block_init = true;
}
void setInput(stream<complex_t>* in) {
assert(generic_block<ComplexToStereo>::_block_init);
std::lock_guard<std::mutex> lck(generic_block<ComplexToStereo>::ctrlMtx);
generic_block<ComplexToStereo>::tempStop();
generic_block<ComplexToStereo>::unregisterInput(_in);
_in = in;
generic_block<ComplexToStereo>::registerInput(_in);
generic_block<ComplexToStereo>::tempStart();
}
int run() {
int count = _in->read();
if (count < 0) { return -1; }
memcpy(out.writeBuf, _in->readBuf, count * sizeof(complex_t));
_in->flush();
if (!out.swap(count)) { return -1; }
return count;
}
stream<stereo_t> out;
private:
stream<complex_t>* _in;
};
class ComplexToReal : public generic_block<ComplexToReal> {
public:
ComplexToReal() {}
ComplexToReal(stream<complex_t>* in) { init(in); }
void init(stream<complex_t>* in) {
_in = in;
generic_block<ComplexToReal>::registerInput(_in);
generic_block<ComplexToReal>::registerOutput(&out);
generic_block<ComplexToReal>::_block_init = true;
}
void setInput(stream<complex_t>* in) {
assert(generic_block<ComplexToReal>::_block_init);
std::lock_guard<std::mutex> lck(generic_block<ComplexToReal>::ctrlMtx);
generic_block<ComplexToReal>::tempStop();
generic_block<ComplexToReal>::unregisterInput(_in);
_in = in;
generic_block<ComplexToReal>::registerInput(_in);
generic_block<ComplexToReal>::tempStart();
}
int run() {
int count = _in->read();
if (count < 0) { return -1; }
volk_32fc_deinterleave_real_32f(out.writeBuf, (lv_32fc_t*)_in->readBuf, count);
_in->flush();
if (!out.swap(count)) { return -1; }
return count;
}
stream<float> out;
private:
stream<complex_t>* _in;
};
class ComplexToImag : public generic_block<ComplexToImag> {
public:
ComplexToImag() {}
ComplexToImag(stream<complex_t>* in) { init(in); }
void init(stream<complex_t>* in) {
_in = in;
generic_block<ComplexToImag>::registerInput(_in);
generic_block<ComplexToImag>::registerOutput(&out);
generic_block<ComplexToImag>::_block_init = true;
}
void setInput(stream<complex_t>* in) {
assert(generic_block<ComplexToImag>::_block_init);
std::lock_guard<std::mutex> lck(generic_block<ComplexToImag>::ctrlMtx);
generic_block<ComplexToImag>::tempStop();
generic_block<ComplexToImag>::unregisterInput(_in);
_in = in;
generic_block<ComplexToImag>::registerInput(_in);
generic_block<ComplexToImag>::tempStart();
}
int run() {
int count = _in->read();
if (count < 0) { return -1; }
volk_32fc_deinterleave_imag_32f(out.writeBuf, (lv_32fc_t*)_in->readBuf, count);
_in->flush();
if(!out.swap(count)) { return -1; }
return count;
}
stream<float> out;
private:
stream<complex_t>* _in;
};
class RealToComplex : public generic_block<RealToComplex> {
public:
RealToComplex() {}
RealToComplex(stream<float>* in) { init(in); }
~RealToComplex() {
if (!generic_block<RealToComplex>::_block_init) { return; }
generic_block<RealToComplex>::stop();
delete[] nullBuffer;
generic_block<RealToComplex>::_block_init = false;
}
void init(stream<float>* in) {
_in = in;
nullBuffer = new float[STREAM_BUFFER_SIZE];
memset(nullBuffer, 0, STREAM_BUFFER_SIZE * sizeof(float));
generic_block<RealToComplex>::registerInput(_in);
generic_block<RealToComplex>::registerOutput(&out);
generic_block<RealToComplex>::_block_init = true;
}
void setInput(stream<float>* in) {
assert(generic_block<RealToComplex>::_block_init);
std::lock_guard<std::mutex> lck(generic_block<RealToComplex>::ctrlMtx);
generic_block<RealToComplex>::tempStop();
generic_block<RealToComplex>::unregisterInput(_in);
_in = in;
generic_block<RealToComplex>::registerInput(_in);
generic_block<RealToComplex>::tempStart();
}
int run() {
int count = _in->read();
if (count < 0) { return -1; }
volk_32f_x2_interleave_32fc((lv_32fc_t*)out.writeBuf, _in->readBuf, nullBuffer, count);
_in->flush();
if (!out.swap(count)) { return -1; }
return count;
}
stream<complex_t> out;
private:
float* nullBuffer;
stream<float>* _in;
};
class Int16CToComplex : public generic_block<Int16CToComplex> {
public:
Int16CToComplex() {}
Int16CToComplex(stream<int16_t>* in) { init(in); }
void init(stream<int16_t>* in) {
_in = in;
generic_block<Int16CToComplex>::registerInput(_in);
generic_block<Int16CToComplex>::registerOutput(&out);
generic_block<Int16CToComplex>::_block_init = true;
}
void setInput(stream<int16_t>* in) {
assert(generic_block<Int16CToComplex>::_block_init);
std::lock_guard<std::mutex> lck(generic_block<Int16CToComplex>::ctrlMtx);
generic_block<Int16CToComplex>::tempStop();
generic_block<Int16CToComplex>::unregisterInput(_in);
_in = in;
generic_block<Int16CToComplex>::registerInput(_in);
generic_block<Int16CToComplex>::tempStart();
}
int run() {
int count = _in->read();
if (count < 0) { return -1; }
volk_16i_s32f_convert_32f((float*)out.writeBuf, _in->readBuf, 32768.0f, count * 2);
_in->flush();
if (!out.swap(count)) { return -1; }
return count;
}
stream<complex_t> out;
private:
stream<int16_t>* _in;
};
class ComplexToInt16C : public generic_block<ComplexToInt16C> {
public:
ComplexToInt16C() {}
ComplexToInt16C(stream<complex_t>* in) { init(in); }
void init(stream<complex_t>* in) {
_in = in;
generic_block<ComplexToInt16C>::registerInput(_in);
generic_block<ComplexToInt16C>::registerOutput(&out);
generic_block<ComplexToInt16C>::_block_init = true;
}
void setInput(stream<complex_t>* in) {
assert(generic_block<ComplexToInt16C>::_block_init);
std::lock_guard<std::mutex> lck(generic_block<ComplexToInt16C>::ctrlMtx);
generic_block<ComplexToInt16C>::tempStop();
generic_block<ComplexToInt16C>::unregisterInput(_in);
_in = in;
generic_block<ComplexToInt16C>::registerInput(_in);
generic_block<ComplexToInt16C>::tempStart();
}
int run() {
int count = _in->read();
if (count < 0) { return -1; }
volk_32f_s32f_convert_16i(out.writeBuf, (float*)_in->readBuf, 32768.0f, count * 2);
_in->flush();
if (!out.swap(count)) { return -1; }
return count;
}
stream<int16_t> out;
private:
stream<complex_t>* _in;
};
class Int16ToFloat : public generic_block<Int16ToFloat> {
public:
Int16ToFloat() {}
Int16ToFloat(stream<int16_t>* in) { init(in); }
void init(stream<int16_t>* in) {
_in = in;
generic_block<Int16ToFloat>::registerInput(_in);
generic_block<Int16ToFloat>::registerOutput(&out);
generic_block<Int16ToFloat>::_block_init = true;
}
void setInput(stream<int16_t>* in) {
assert(generic_block<Int16ToFloat>::_block_init);
std::lock_guard<std::mutex> lck(generic_block<Int16ToFloat>::ctrlMtx);
generic_block<Int16ToFloat>::tempStop();
generic_block<Int16ToFloat>::unregisterInput(_in);
_in = in;
generic_block<Int16ToFloat>::registerInput(_in);
generic_block<Int16ToFloat>::tempStart();
}
int run() {
int count = _in->read();
if (count < 0) { return -1; }
volk_16i_s32f_convert_32f(out.writeBuf, _in->readBuf, 32768.0f, count);
_in->flush();
if (!out.swap(count)) { return -1; }
return count;
}
stream<float> out;
private:
stream<int16_t>* _in;
};
class FloatToInt16 : public generic_block<FloatToInt16> {
public:
FloatToInt16() {}
FloatToInt16(stream<float>* in) { init(in); }
void init(stream<float>* in) {
_in = in;
generic_block<FloatToInt16>::registerInput(_in);
generic_block<FloatToInt16>::registerOutput(&out);
generic_block<FloatToInt16>::_block_init = true;
}
void setInput(stream<float>* in) {
assert(generic_block<FloatToInt16>::_block_init);
std::lock_guard<std::mutex> lck(generic_block<FloatToInt16>::ctrlMtx);
generic_block<FloatToInt16>::tempStop();
generic_block<FloatToInt16>::unregisterInput(_in);
_in = in;
generic_block<FloatToInt16>::registerInput(_in);
generic_block<FloatToInt16>::tempStart();
}
int run() {
int count = _in->read();
if (count < 0) { return -1; }
volk_32f_s32f_convert_16i(out.writeBuf, _in->readBuf, 32768.0f, count);
_in->flush();
if (!out.swap(count)) { return -1; }
return count;
}
stream<int16_t> out;
private:
stream<float>* _in;
};
}

Wyświetl plik

@ -8,7 +8,7 @@
#include <dsp/pll.h>
#include <dsp/clock_recovery.h>
#include <dsp/math.h>
#include <dsp/convertion.h>
#include <dsp/conversion.h>
#include <dsp/audio.h>
#include <dsp/stereo_fm.h>

Wyświetl plik

@ -173,7 +173,7 @@ namespace dsp {
int element = readBits(19, 6, _in->readBuf);
// If we've skipped or are on a non image element and there's data avilable, send it
// If we've skipped or are on a non image element and there's data available, send it
if ((element < lastElement || element > 55) && newImageData) {
newImageData = false;
for (int i = 0; i < 20; i++) {

Wyświetl plik

@ -74,7 +74,7 @@ namespace dsp {
Reshaper(stream<T>* in, int keep, int skip) { init(in, keep, skip); }
// NOTE: For some reason, the base class destrcutor doesn't get called.... this is a temporary fix I guess
// NOTE: For some reason, the base class destructor doesn't get called.... this is a temporary fix I guess
// I also don't check for _block_init for the exact sample reason, something's weird
~Reshaper() {
if (!generic_block<Reshaper<T>>::_block_init) { return; }

Wyświetl plik

@ -35,7 +35,7 @@ namespace icons {
bool load(std::string resDir) {
if (!std::filesystem::is_directory(resDir)) {
spdlog::error("Inavlid resource directory: {0}", resDir);
spdlog::error("Invalid resource directory: {0}", resDir);
return false;
}

Wyświetl plik

@ -13,7 +13,7 @@ namespace style {
bool loadFonts(std::string resDir) {
if (!std::filesystem::is_directory(resDir)) {
spdlog::error("Inavlid resource directory: {0}", resDir);
spdlog::error("Invalid resource directory: {0}", resDir);
return false;
}

Wyświetl plik

@ -245,7 +245,6 @@ namespace ImGui {
bool mouseClicked = ImGui::ButtonBehavior(ImRect(fftAreaMin, wfMax), GetID("WaterfallID"), &mouseHovered, &mouseHeld,
ImGuiButtonFlags_MouseButtonLeft | ImGuiButtonFlags_PressedOnClick);
bool draging = ImGui::IsMouseDragging(ImGuiMouseButton_Left) && ImGui::IsWindowFocused();
mouseInFFTResize = (dragOrigin.x > widgetPos.x && dragOrigin.x < widgetPos.x + widgetSize.x && dragOrigin.y >= widgetPos.y + newFFTAreaHeight - 2 && dragOrigin.y <= widgetPos.y + newFFTAreaHeight + 2);
mouseInFreq = IS_IN_AREA(dragOrigin, freqAreaMin, freqAreaMax);
mouseInFFT = IS_IN_AREA(dragOrigin, fftAreaMin, fftAreaMax);

Wyświetl plik

@ -102,7 +102,7 @@ void ModuleManager::createInstance(std::string name, std::string module) {
void ModuleManager::deleteInstance(std::string name) {
if (instances.find(name) == instances.end()) {
spdlog::error("Tried to remove non-existant instance '{0}'", name);
spdlog::error("Tried to remove non-existent instance '{0}'", name);
return;
}
onInstanceDelete.emit(name);

Wyświetl plik

@ -17,7 +17,7 @@ void SourceManager::registerSource(std::string name, SourceHandler* handler) {
void SourceManager::unregisterSource(std::string name) {
if (sources.find(name) == sources.end()) {
spdlog::error("Tried to unregister non existant source: {0}", name);
spdlog::error("Tried to unregister non existent source: {0}", name);
return;
}
onSourceUnregister.emit(name);
@ -40,7 +40,7 @@ std::vector<std::string> SourceManager::getSourceNames() {
void SourceManager::selectSource(std::string name) {
if (sources.find(name) == sources.end()) {
spdlog::error("Tried to select non existant source: {0}", name);
spdlog::error("Tried to select non existent source: {0}", name);
return;
}
if (selectedHandler != NULL) {

Wyświetl plik

@ -32,7 +32,7 @@ public:
void unbindHandler(EventHandler<T>* handler) {
if (std::find(handlers.begin(), handlers.end(), handler) == handlers.end()) {
spdlog::error("Tried to remove a non-existant event handler");
spdlog::error("Tried to remove a non-existent event handler");
return;
}
handlers.erase(std::remove(handlers.begin(), handlers.end(), handler), handlers.end());

Wyświetl plik

@ -302,7 +302,7 @@ namespace net {
Socket sock;
#ifdef _WIN32
// Initilize WinSock2
// Initialize WinSock2
if (!winsock_init) {
WSADATA wsa;
if (WSAStartup(MAKEWORD(2,2),&wsa)) {
@ -350,7 +350,7 @@ namespace net {
Socket listenSock;
#ifdef _WIN32
// Initilize WinSock2
// Initialize WinSock2
if (!winsock_init) {
WSADATA wsa;
if (WSAStartup(MAKEWORD(2,2),&wsa)) {
@ -416,7 +416,7 @@ namespace net {
Socket sock;
#ifdef _WIN32
// Initilize WinSock2
// Initialize WinSock2
if (!winsock_init) {
WSADATA wsa;
if (WSAStartup(MAKEWORD(2,2),&wsa)) {

Wyświetl plik

@ -1,6 +1,6 @@
#pragma once
#include <radio_demod.h>
#include <dsp/convertion.h>
#include <dsp/conversion.h>
#include <dsp/resampling.h>
#include <dsp/filter.h>
#include <dsp/audio.h>

Wyświetl plik

@ -56,7 +56,7 @@ There are currently no BSD packages, refer to [Building on Linux / BSD](https://
# Building on Windows
The prefered IDE is [VS Code](https://code.visualstudio.com/) in order to have similar development experience across platforms and to build with CMake using the command line.
The preferred IDE is [VS Code](https://code.visualstudio.com/) in order to have similar development experience across platforms and to build with CMake using the command line.
## Install dependencies
@ -144,7 +144,7 @@ Remember that these paths will be relative to the run directory.
If you choose to run SDR++ for development, you do not need this step.
First, copy over the exe and DLLs from `build/Release/` to `root_dev`.
Next you need to copy over all the modules that were compiled. To do so, copy the DLL file of the module (located in its build folder given below) to the `root_dev/modules` directory and other DLLs (that do not have the exact name of the modue) to the `root_dev` directory.
Next you need to copy over all the modules that were compiled. To do so, copy the DLL file of the module (located in its build folder given below) to the `root_dev/modules` directory and other DLLs (that do not have the exact name of the module) to the `root_dev` directory.
The modules built will be some of the following (Repeat the instructions above for all you wish to use):

Wyświetl plik

@ -584,7 +584,7 @@ private:
core::modComManager.callInterface(selectedRecorder, RECORDER_IFACE_CMD_START, NULL, NULL);
}
// Respond with a sucess
// Respond with a success
resp = "RPRT 0\n";
client->write(resp.size(), (uint8_t*)resp.c_str());
}

Wyświetl plik

@ -403,7 +403,7 @@
"end": 380000000
},
{
"name": "Satelitte militAviatione",
"name": "Satellite militaire",
"type": "military",
"start": 240000000,
"end": 270000000