diff --git a/Source/.codex b/Source/.codex new file mode 100644 index 0000000..e69de29 diff --git a/Source/bin/windowsSettings.ini b/Source/bin/windowsSettings.ini index 0009505..a7c66b6 100644 --- a/Source/bin/windowsSettings.ini +++ b/Source/bin/windowsSettings.ini @@ -1,3 +1,3 @@ [General] -geometry=@ByteArray(\x1\xd9\xd0\xcb\0\x3\0\0\0\0\0\0\0\0\0\0\0\0\a\x7f\0\0\x4\x19\0\0\0\x1\0\0\x1\x8f\0\0\x3 \0\0\x3\xe6\0\0\0\0\x2\0\0\0\a\x80\0\0\0\0\0\0\0\x17\0\0\a\x7f\0\0\x4\x18) -windowState=@ByteArray(\0\0\0\xff\0\0\0\0\xfd\0\0\0\x1\0\0\0\x1\0\0\0\xf5\0\0\x3@\xfc\x2\0\0\0\x5\xfb\0\0\0\x12\0R\0\x61\0\x64\0i\0o\0\x43\0t\0r\0l\0\0\0\0\0\xff\xff\xff\xff\0\0\0-\0\xff\xff\xff\xfb\0\0\0\x14\0S\0\x65\0r\0v\0\x65\0r\0\x43\0t\0r\0l\0\0\0\0\0\xff\xff\xff\xff\0\0\0-\0\xff\xff\xff\xfb\0\0\0\x12\0H\0P\0S\0\x44\0R\0\x43\0t\0r\0l\0\0\0\0\0\xff\xff\xff\xff\0\0\0-\0\xff\xff\xff\xfb\0\0\0\x12\0\x43\0h\0i\0r\0p\0\x43\0t\0r\0l\0\0\0\0\0\xff\xff\xff\xff\0\0\0-\0\xff\xff\xff\xfb\0\0\0\x16\0\x44\0i\0s\0p\0l\0\x61\0y\0\x43\0t\0r\0l\0\0\0\0\0\xff\xff\xff\xff\0\0\0-\0\xff\xff\xff\0\0\a\x80\0\0\x3@\0\0\0\x4\0\0\0\x4\0\0\0\b\0\0\0\b\xfc\0\0\0\x9a\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\x1\0\0\0\x18\0\x44\0i\0s\0p\0l\0\x61\0y\0P\0\x61\0n\0\x65\0l\x1\0\0\0\0\xff\xff\xff\xff\0\0\0\0\0\0\0\0\0\0\0\x2\0\0\0\x1\0\0\0\x16\0M\0\x61\0i\0n\0\x42\0u\0t\0t\0o\0n\0s\x1\0\0\0\0\xff\xff\xff\xff\0\0\0\0\0\0\0\0) +geometry=@ByteArray(\x1\xd9\xd0\xcb\0\x3\0\0\0\0\0\0\0\0\0\0\0\0\x3\x1f\0\0\x2W\0\0\0\0\0\0\0\0\0\0\x3\x1f\0\0\x2W\0\0\0\0\0\0\0\0\n\0\0\0\0\0\0\0\0\0\0\0\x3\x1f\0\0\x2W) +windowState=@ByteArray(\0\0\0\xff\0\0\0\0\xfd\0\0\0\x1\0\0\0\x1\0\0\0\xf5\0\0\x3@\xfc\x2\0\0\0\x5\xfb\0\0\0\x12\0R\0\x61\0\x64\0i\0o\0\x43\0t\0r\0l\0\0\0\0\0\xff\xff\xff\xff\0\0\0/\0\xff\xff\xff\xfb\0\0\0\x14\0S\0\x65\0r\0v\0\x65\0r\0\x43\0t\0r\0l\0\0\0\0\0\xff\xff\xff\xff\0\0\0/\0\xff\xff\xff\xfb\0\0\0\x12\0H\0P\0S\0\x44\0R\0\x43\0t\0r\0l\0\0\0\0\0\xff\xff\xff\xff\0\0\0/\0\xff\xff\xff\xfb\0\0\0\x12\0\x43\0h\0i\0r\0p\0\x43\0t\0r\0l\0\0\0\0\0\xff\xff\xff\xff\0\0\0/\0\xff\xff\xff\xfb\0\0\0\x16\0\x44\0i\0s\0p\0l\0\x61\0y\0\x43\0t\0r\0l\0\0\0\0\0\xff\xff\xff\xff\0\0\0/\0\xff\xff\xff\0\0\x3 \0\0\x1\x94\0\0\0\x4\0\0\0\x4\0\0\0\b\0\0\0\b\xfc\0\0\0\x9c\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\x1\0\0\0\x18\0\x44\0i\0s\0p\0l\0\x61\0y\0P\0\x61\0n\0\x65\0l\x1\0\0\0\0\xff\xff\xff\xff\0\0\0\0\0\0\0\0\0\0\0\x2\0\0\0\x1\0\0\0\x16\0M\0\x61\0i\0n\0\x42\0u\0t\0t\0o\0n\0s\x1\0\0\0\0\xff\xff\xff\xff\0\0\0\0\0\0\0\0) diff --git a/Source/cudaSDR.pri b/Source/cudaSDR.pri index 9bd73d5..07dce19 100644 --- a/Source/cudaSDR.pri +++ b/Source/cudaSDR.pri @@ -26,6 +26,7 @@ HEADERS += \ ./src/DataEngine/cusdr_dataIO.h \ ./src/DataEngine/cusdr_discoverer_P1.h \ ./src/DataEngine/cusdr_discoverer_P2.h \ + ./src/DataEngine/cusdr_protocol2_io.h \ ./src/DataEngine/cusdr_receiver.h \ ./src/DataEngine/soundout.h \ ./src/DataEngine/fractresampler.h \ @@ -102,6 +103,7 @@ HEADERS += \ ./src/DataEngine/cusdr_dataIO.h \ ./src/DataEngine/cusdr_discoverer_P1.h \ ./src/DataEngine/cusdr_discoverer_P2.h \ + ./src/DataEngine/cusdr_protocol2_io.h \ ./src/DataEngine/cusdr_receiver.h \ ./src/DataEngine/soundout.h \ ./src/DataEngine/fractresampler.h \ @@ -176,6 +178,7 @@ SOURCES += \ ./src/DataEngine/cusdr_dataIO.cpp \ ./src/DataEngine/cusdr_discoverer_P1.cpp \ ./src/DataEngine/cusdr_discoverer_P2.cpp \ + ./src/DataEngine/cusdr_protocol2_io.cpp \ ./src/DataEngine/cusdr_receiver.cpp \ ./src/DataEngine/soundout.cpp \ ./src/DataEngine/fractresampler.cpp \ @@ -245,6 +248,7 @@ SOURCES += \ ./src/DataEngine/cusdr_dataIO.cpp \ ./src/DataEngine/cusdr_discoverer_P1.cpp \ ./src/DataEngine/cusdr_discoverer_P2.cpp \ + ./src/DataEngine/cusdr_protocol2_io.cpp \ ./src/DataEngine/cusdr_receiver.cpp \ ./src/DataEngine/soundout.cpp \ ./src/DataEngine/fractresampler.cpp \ diff --git a/Source/cudaSDR.pro.user b/Source/cudaSDR.pro.user index 8a8617a..4f1b7b6 100644 --- a/Source/cudaSDR.pro.user +++ b/Source/cudaSDR.pro.user @@ -1,10 +1,10 @@ - + EnvironmentId - {9df2227e-2f94-4455-9fee-2b0603509b19} + {96b01fe1-0bbd-4672-be89-b23907511d36} ProjectExplorer.Project.ActiveTarget @@ -13,8 +13,8 @@ ProjectExplorer.Project.EditorSettings + true true - false true Cpp @@ -33,6 +33,7 @@ false 4 false + 0 80 true true @@ -49,7 +50,7 @@ true false 1 - true + false true true *.md, *.MD, Makefile @@ -69,7 +70,9 @@ true true + false + 0 true @@ -83,22 +86,24 @@ true + 0 ProjectExplorer.Project.Target.0 Desktop - Desktop Qt 5.15.2 MinGW 64-bit - Desktop Qt 5.15.2 MinGW 64-bit - qt.qt5.5152.win64_mingw81_kit + true + Qt 5.15.18 (Системная) + Qt 5.15.18 (Системная) + {f03c686f-a66c-435e-a263-3d02bc565002} 0 0 0 0 - C:\Users\karpe\Documents\source\cudaSDR\Source\build\Debug - C:/Users/karpe/Documents/source/cudaSDR/Source/build/Debug + ./build/%{Asciify:%{Kit:FileSystemName}-%{BuildConfig:Name}} + build/Qt_5_15_18-u041eu0442u043bu0430u0434u043au0430 true @@ -133,11 +138,46 @@ Отладка Qt4ProjectManager.Qt4BuildConfiguration + 0 + 0 + + + 0 + Развёртывание + Развёртывание + ProjectExplorer.BuildSteps.Deploy + + 1 + + false + ProjectExplorer.DefaultDeployConfiguration + + 1 + + true + true + 0 + true + + + 2 + + false + -e cpu-cycles --call-graph dwarf,4096 -F 250 + + ProjectExplorer.CustomExecutableRunConfiguration + + false + + true + true + %{RunConfig:Executable:Path} + + 1 2 - C:\Users\karpe\Documents\source\cudaSDR\Source\build\Release - C:/Users/karpe/Documents/source/cudaSDR/Source/build/Release + /home/vladimir/Документы/source/cudaSDR/Source true @@ -170,54 +210,47 @@ false - Выпуск + Выпуск (imported) Qt4ProjectManager.Qt4BuildConfiguration - 0 - 0 - - - 0 - C:\Users\karpe\Documents\source\cudaSDR\Source\build\Profile - C:/Users/karpe/Documents/source/cudaSDR/Source/build/Profile - - - true - QtProjectManager.QMakeBuildStep - false - + 0 + 0 + + + 0 + Развёртывание + Развёртывание + ProjectExplorer.BuildSteps.Deploy - - true - Qt4ProjectManager.MakeStep - - 2 - Сборка - Сборка - ProjectExplorer.BuildSteps.Build + 1 + + false + ProjectExplorer.DefaultDeployConfiguration - - - true - Qt4ProjectManager.MakeStep - clean - - 1 - Очистка - Очистка - ProjectExplorer.BuildSteps.Clean + 1 + + true + true + 0 + true + + + 2 + + false + -e cpu-cycles --call-graph dwarf,4096 -F 250 + + ProjectExplorer.CustomExecutableRunConfiguration + + false + + true + true + %{RunConfig:Executable:Path} - 2 - false - - false - - Профилирование - Qt4ProjectManager.Qt4BuildConfiguration + 1 0 - 0 - 0 - 3 + 2 0 @@ -236,17 +269,20 @@ true 0 true + 2 false - -e cpu-cycles --call-graph "dwarf,4096" -F 250 + -e cpu-cycles --call-graph dwarf,4096 -F 250 ProjectExplorer.CustomExecutableRunConfiguration false + true true + %{RunConfig:Executable:Path} 1 @@ -255,10 +291,6 @@ ProjectExplorer.Project.TargetCount 1 - - ProjectExplorer.Project.Updater.FileVersion - 22 - Version 22 diff --git a/Source/doc/openHPSDR Ethernet Protocol v4.3.docx b/Source/doc/openHPSDR Ethernet Protocol v4.3.docx new file mode 100644 index 0000000..7dba40c Binary files /dev/null and b/Source/doc/openHPSDR Ethernet Protocol v4.3.docx differ diff --git a/Source/src/DataEngine/cusdr_dataEngine.cpp b/Source/src/DataEngine/cusdr_dataEngine.cpp index 3ab684c..bc38049 100644 --- a/Source/src/DataEngine/cusdr_dataEngine.cpp +++ b/Source/src/DataEngine/cusdr_dataEngine.cpp @@ -88,6 +88,7 @@ DataEngine::DataEngine(QObject *parent) , m_hpsdrDevices(0) , m_configure(10) , m_timeout(5000) + , m_discoveryProtocol(1) , m_remainingTime(0) , m_RxFrequencyChange(0) , m_forwardPower(0) @@ -459,33 +460,32 @@ bool DataEngine::startDataEngineWithoutConnection() { bool DataEngine::findHPSDRDevices() { - if (!m_discoverer) createDiscoverer(); + for (int protocolVersion = 1; protocolVersion <= 2; ++protocolVersion) { - // HPSDR network IO thread - if (!startDiscoverer(QThread::NormalPriority)) { + m_discoveryProtocol = protocolVersion; + + if (!m_discoverer) + createDiscoverer(); + + if (!startDiscoverer(QThread::NormalPriority)) { + + io.networkIOMutex.lock(); + DATA_ENGINE_DEBUG << "HPSDR device discovery thread could not be started."; + io.networkIOMutex.unlock(); + return false; + } io.networkIOMutex.lock(); - DATA_ENGINE_DEBUG << "HPSDR device discovery thread could not be started."; - io.networkIOMutex.unlock(); - return false; - } - - io.networkIOMutex.lock(); - DATA_ENGINE_DEBUG << "HPSDR network device detection...please wait."; - set->setSystemMessage("HPSDR network device detection...please wait", 0); - io.devicefound.wait(&io.networkIOMutex); - - m_hpsdrDevices = set->getHpsdrNetworkDevices(); - if (m_hpsdrDevices == 0) { + DATA_ENGINE_DEBUG << "HPSDR network device detection...please wait."; + set->setSystemMessage("HPSDR network device detection...please wait", 0); + io.devicefound.wait(&io.networkIOMutex); + m_hpsdrDevices = set->getHpsdrNetworkDevices(); io.networkIOMutex.unlock(); stopDiscoverer(); - DATA_ENGINE_DEBUG << "no device found. HPSDR hardware powered? Network connection established?"; - set->setSystemMessage("no device found. HPSDR hardware powered? Network connection established?", 10000); - setSystemState(QSDR::HwIOError, m_hwInterface, m_serverMode, QSDR::DataEngineDown); - } - else { + if (m_hpsdrDevices == 0) + continue; emit clearSystemMessageEvent(); if (m_hpsdrDevices > 1) @@ -493,31 +493,35 @@ bool DataEngine::findHPSDRDevices() { QList metisList = set->getMetisCardsList(); DATA_ENGINE_DEBUG << "found " << metisList.count() << " network device(s)"; - - for (int i = 0; i < metisList.count(); i++) { + for (int i = 0; i < metisList.count(); i++) { DATA_ENGINE_DEBUG << "Device " << i << " @ " << qPrintable(metisList.at(i).ip_address.toString()) - //<< " [" << qPrintable((char *) &metisList.at(i).mac_address) << "]"; - << " [" << metisList.at(i).mac_address << "]"; + << " [" << metisList.at(i).mac_address << "]" + << " P" << metisList.at(i).protocolVersion; } io.hpsdrDeviceIPAddress = set->getCurrentMetisCard().ip_address; io.hpsdrDeviceName = set->getCurrentMetisCard().boardName; DATA_ENGINE_DEBUG << "using HPSDR network device at " << qPrintable(io.hpsdrDeviceIPAddress.toString()); - //Sleep(100); SleeperThread::msleep(100); - // stop the discovery thread - io.networkIOMutex.unlock(); - stopDiscoverer(); + if (set->getCurrentMetisCard().protocolVersion >= 2) { + io.hermesFW = set->getCurrentMetisCard().firmwareVersion; + set->setHermesVersion(io.hermesFW); + return true; + } - if (getFirmwareVersions()) return true; + if (getFirmwareVersions()) + return true; return false; } + DATA_ENGINE_DEBUG << "no device found. HPSDR hardware powered? Network connection established?"; + set->setSystemMessage("no device found. HPSDR hardware powered? Network connection established?", 10000); + setSystemState(QSDR::HwIOError, m_hwInterface, m_serverMode, QSDR::DataEngineDown); return false; } @@ -1434,7 +1438,10 @@ void DataEngine::disconnectDSPSlots() { void DataEngine::createDiscoverer() { - m_discoverer = new DiscovererP1(&io); + if (m_discoveryProtocol >= 2) + m_discoverer = new DiscovererP2(&io); + else + m_discoverer = new DiscovererP1(&io); m_discoveryThread = new QThreadEx(); m_discoverer->moveToThread(m_discoveryThread); diff --git a/Source/src/DataEngine/cusdr_dataEngine.h b/Source/src/DataEngine/cusdr_dataEngine.h index 55bc981..bf31c0f 100644 --- a/Source/src/DataEngine/cusdr_dataEngine.h +++ b/Source/src/DataEngine/cusdr_dataEngine.h @@ -47,9 +47,10 @@ #include "cusdr_dataIO.h" #include "cusdr_receiver.h" #include "cusdr_chirpProcessor.h" -#include "cusdr_audioReceiver.h" -#include "cusdr_discoverer_P1.h" -#include "Util/qcircularbuffer.h" +#include "cusdr_audioReceiver.h" +#include "cusdr_discoverer_P1.h" +#include "cusdr_discoverer_P2.h" +#include "Util/qcircularbuffer.h" #include "QtDSP/qtdsp_fft.h" #include "QtDSP/qtdsp_filter.h" #include "QtDSP/qtdsp_dualModeAverager.h" @@ -198,7 +199,7 @@ private: AudioEngine* m_audioEngine; AudioOutProcessor* m_audioOutProcessor; ChirpProcessor* m_chirpProcessor; - DiscovererP1* m_discoverer; + QObject* m_discoverer; QThreadEx* m_discoveryThread; QThreadEx* m_dataIOThread; @@ -256,9 +257,10 @@ private: int m_fwCount; int m_configure; int m_timeout; - int m_txFrame; - int m_bytes; - int m_remainingTime; + int m_txFrame; + int m_bytes; + int m_discoveryProtocol; + int m_remainingTime; int m_found; int m_RxFrequencyChange; int m_counter; diff --git a/Source/src/DataEngine/cusdr_dataIO.cpp b/Source/src/DataEngine/cusdr_dataIO.cpp index 29119a3..13575cd 100644 --- a/Source/src/DataEngine/cusdr_dataIO.cpp +++ b/Source/src/DataEngine/cusdr_dataIO.cpp @@ -27,6 +27,7 @@ #define LOG_DATAIO #include "cusdr_dataIO.h" +#include "cusdr_protocol2_io.h" #include "soundout.h" #if defined(Q_OS_WIN32) @@ -41,6 +42,7 @@ DataIO::DataIO(THPSDRParameter *ioData) , set(Settings::instance()) , io(ioData) , m_dataIOSocketOn(false) + , m_protocol2(0) , m_setNetworkDeviceHeader(true) , m_sequence(0) , m_oldSequence(-1) @@ -56,6 +58,7 @@ DataIO::DataIO(THPSDRParameter *ioData) , m_stopped(false) { m_dataIOSocket = 0; + m_protocol2 = new Protocol2DataPath(set, io, this); m_metisGetDataSignature.resize(3); m_metisGetDataSignature[0] = (char)0xEF; @@ -119,6 +122,9 @@ void DataIO::stop() { m_stopped = true; io->networkIOMutex.unlock(); + if (m_protocol2 && m_protocol2->isActive()) + m_protocol2->stop(); + if(m_pSoundCardOut) { SleeperThread::msleep(100); m_pSoundCardOut->Stop(); @@ -128,6 +134,11 @@ void DataIO::stop() { void DataIO::initDataReceiverSocket() { + if (m_protocol2 && m_protocol2->isActive()) { + m_dataIOSocketOn = m_protocol2->initSockets(); + return; + } + m_dataIOSocket = new QUdpSocket(); int newBufferSize; @@ -230,6 +241,9 @@ void DataIO::initDataReceiverSocket() { void DataIO::readDeviceData() { + if (m_protocol2 && m_protocol2->isActive()) + return; + while (m_dataIOSocket->hasPendingDatagrams()) { QMutexLocker locker(&io->networkIOMutex); @@ -357,6 +371,11 @@ void DataIO::readData() { void DataIO::sendInitFramesToNetworkDevice(int rx) { + if (m_protocol2 && m_protocol2->isActive()) { + m_protocol2->sendInitFramesToNetworkDevice(rx); + return; + } + QByteArray initDatagram; initDatagram.resize(1032); @@ -446,6 +465,11 @@ void DataIO::sendInitFramesToNetworkDevice(int rx) { void DataIO::networkDeviceStartStop(char value) { + if (m_protocol2 && m_protocol2->isActive()) { + m_protocol2->networkDeviceStartStop(value); + return; + } + TNetworkDevicecard metis = set->getCurrentMetisCard(); //QUdpSocket socket; @@ -517,6 +541,9 @@ void DataIO::sendAudio(u_char *buf) { void DataIO::writeData() { + if (m_protocol2 && m_protocol2->isActive()) + return; + if (m_setNetworkDeviceHeader) { m_outDatagram.resize(0); @@ -561,6 +588,9 @@ void DataIO::setManualSocketBufferSize(QObject *sender, bool value) { Q_UNUSED (sender) + if (m_protocol2 && m_protocol2->isActive()) + return; + m_manualBufferSize = value; DATAIO_DEBUG << "m_manualBufferSize to change = " << m_manualBufferSize; int socketBufferSize = 1032 * set->getSocketBufferSize(); @@ -601,6 +631,9 @@ void DataIO::setSocketBufferSize(QObject *sender, int value) { Q_UNUSED (sender) + if (m_protocol2 && m_protocol2->isActive()) + return; + int socketBufferSize = value * 1024; DATAIO_DEBUG << "m_socketBufferSize = " << value; @@ -621,6 +654,9 @@ void DataIO::setSampleRate(QObject *sender, int value) { Q_UNUSED(sender) + if (m_protocol2 && m_protocol2->isActive()) + return; + int bufferSize; io->networkIOMutex.lock(); switch (value) { diff --git a/Source/src/DataEngine/cusdr_dataIO.h b/Source/src/DataEngine/cusdr_dataIO.h index 3043799..6851189 100644 --- a/Source/src/DataEngine/cusdr_dataIO.h +++ b/Source/src/DataEngine/cusdr_dataIO.h @@ -36,8 +36,8 @@ //#include //#include -#include "cusdr_settings.h" -#include "soundout.h" +#include "cusdr_settings.h" +#include "soundout.h" #ifdef LOG_DATAIO # define DATAIO_DEBUG qDebug().nospace() << "DataIO::\t" @@ -46,7 +46,7 @@ #endif -class DataIO : public QObject { +class DataIO : public QObject { Q_OBJECT @@ -71,10 +71,11 @@ private slots: void setSocketBufferSize(QObject *sender, int value); void readDeviceData(); -private: - Settings* set; - QUdpSocket* m_dataIOSocket; - //QMutex m_mutex; +private: + Settings* set; + QUdpSocket* m_dataIOSocket; + class Protocol2DataPath* m_protocol2; + //QMutex m_mutex; QByteArray m_commandDatagram; QByteArray m_datagram; QByteArray m_wbDatagram; diff --git a/Source/src/DataEngine/cusdr_discoverer_P1.cpp b/Source/src/DataEngine/cusdr_discoverer_P1.cpp index 0d077eb..f6a0eb4 100644 --- a/Source/src/DataEngine/cusdr_discoverer_P1.cpp +++ b/Source/src/DataEngine/cusdr_discoverer_P1.cpp @@ -226,6 +226,8 @@ int DiscovererP1::findHPSDRDevices() { mcP1.boardID = no; mcP1.boardName = str; + mcP1.protocolVersion = 1; + mcP1.firmwareVersion = m_deviceDatagram.at(9) & 0xFF; io->networkIOMutex.lock(); DISCOVERER_DEBUG << "Device board ID: " << no; DISCOVERER_DEBUG << "Device is: " << qPrintable(str); diff --git a/Source/src/DataEngine/cusdr_discoverer_P2.cpp b/Source/src/DataEngine/cusdr_discoverer_P2.cpp index edfd41e..f46777b 100644 --- a/Source/src/DataEngine/cusdr_discoverer_P2.cpp +++ b/Source/src/DataEngine/cusdr_discoverer_P2.cpp @@ -44,6 +44,25 @@ DiscovererP2::~DiscovererP2() { TNetworkDevicecard mcP2; +namespace { + +static QString protocol2BoardName(int boardId) { + + switch (boardId) { + case 0: return "ATLAS"; + case 1: return "Hermes"; + case 2: return "Hermes"; + case 3: return "Angelia"; + case 4: return "Orion"; + case 5: return "Orion MkII"; + case 6: return "Hermes-Lite"; + case 10: return "Saturn"; + default: return QString("Protocol2-%1").arg(boardId); + } +} + +} + void DiscovererP2::initHPSDRDevice() { m_searchTime.start(); @@ -185,7 +204,11 @@ int DiscovererP2::findHPSDRDevices() { m_deviceDatagram.resize(socket.pendingDatagramSize()); socket.readDatagram(m_deviceDatagram.data(), m_deviceDatagram.size(), &mcP2.ip_address, &port); - if (m_deviceDatagram[0] == (char)0 && m_deviceDatagram[1] == (char)0 && m_deviceDatagram[2] == (char)0 && m_deviceDatagram[3] == (char)0) { + if (m_deviceDatagram.size() >= 14 && + m_deviceDatagram[0] == (char)0 && + m_deviceDatagram[1] == (char)0 && + m_deviceDatagram[2] == (char)0 && + m_deviceDatagram[3] == (char)0) { status = m_deviceDatagram[4] & 0xFF; if (status == 2 || status == 3) { @@ -196,29 +219,16 @@ int DiscovererP2::findHPSDRDevices() { io->networkIOMutex.lock(); DISCOVERER_DEBUG << "Device on protocol 2 found at " << qPrintable(mcP2.ip_address.toString()) << ":" << port << "; Mac addr: [" << mcP2.mac_address << "]"; - DISCOVERER_DEBUG << "Device protocol 2 code version: " << qPrintable(QString::number(m_deviceDatagram[13], 10)); + DISCOVERER_DEBUG << "Device protocol 2 code version: " << qPrintable(QString::number(m_deviceDatagram[13] & 0xFF, 10)); io->networkIOMutex.unlock(); device = m_deviceDatagram[11] & 0xFF; - QString str; - if (device == 0) - str = "ATLAS"; - else if (device == 1) - str = "HERMES_ANAN-10_100)"; - else if (device == 2) - str = "HERMES_ANAN_10E_100B)"; - else if (device == 3) - str = "ANGELA_ANAN_100D)"; - else if (device == 4) - str = "ORION_ANAN_200D)"; - else if (device == 5) - str = "ORION_Mk_II_ANAN-7_8000DLE)"; - else if (device == 6) { - str = "Hermes-Lite"; - } + QString str = protocol2BoardName(device); mcP2.boardID = device; mcP2.boardName = str; + mcP2.protocolVersion = m_deviceDatagram[12] & 0xFF; + mcP2.firmwareVersion = m_deviceDatagram[13] & 0xFF; io->networkIOMutex.lock(); DISCOVERER_DEBUG << "Protocol 2 device board ID: " << device; DISCOVERER_DEBUG << "Protocol 2 device is: " << qPrintable(str); @@ -274,20 +284,11 @@ void DiscovererP2::clear() { void DiscovererP2::shutdownHPSDRDevice() { - long sequence = 0; - QByteArray arr; - arr.resize(1444); - - arr[0] = sequence >> 24; - arr[1] = sequence >> 16; - arr[2] = sequence >> 8; - arr[3] = sequence; - arr[4] = 0; + QByteArray arr(1444, 0x00); QUdpSocket socket; QHostAddress addr = mcP2.ip_address; - if (socket.writeDatagram(arr, addr, HIGH_PRIORITY_FROM_HOST_PORT) < 0) { - DISCOVERER_DEBUG << "protocol 2 forced shutdown socket write failed."; - } + if (socket.writeDatagram(arr, addr, HIGH_PRIORITY_FROM_HOST_PORT) < 0) + DISCOVERER_DEBUG << "protocol 2 forced shutdown socket write failed."; } diff --git a/Source/src/DataEngine/cusdr_protocol2_io.cpp b/Source/src/DataEngine/cusdr_protocol2_io.cpp new file mode 100644 index 0000000..59f616d --- /dev/null +++ b/Source/src/DataEngine/cusdr_protocol2_io.cpp @@ -0,0 +1,439 @@ +/** +* @file cusdr_protocol2_io.cpp +* @brief openHPSDR Protocol 2 transport helper +*/ + +#define LOG_DATAIO + +#include "cusdr_protocol2_io.h" + +#ifdef LOG_DATAIO +# define PROTOCOL2_DEBUG qDebug().nospace() << "Protocol2::\t" +#else +# define PROTOCOL2_DEBUG nullDebug() +#endif + + +namespace { + +static const quint16 kProtocol2DdcSpecificPort = 1025; +static const quint16 kProtocol2HighPriorityToPcPort = 1025; +static const quint16 kProtocol2DdcAudioPort = 1028; +static const quint16 kProtocol2DucIqPort = 1029; +static const quint16 kProtocol2DdcBasePort = 1035; +static const int kProtocol2GeneralPacketSize = 60; +static const int kProtocol2HighPriorityPacketSize = 1444; +static const int kProtocol2StatusPacketMinSize = 31; + +} + + +Protocol2DataPath::Protocol2DataPath(Settings *settings, THPSDRParameter *ioData, QObject *parent) + : QObject(parent) + , set(settings) + , io(ioData) + , m_commandSocket(0) + , m_statusSocket(0) + , m_heartbeatTimer(0) + , m_running(false) + , m_generalSequence(0) + , m_ddcSequence(0) + , m_highPrioritySequence(0) +{ + m_legacyControlBytes = QByteArray(5, 0x00); +} + +Protocol2DataPath::~Protocol2DataPath() { + stop(); +} + +bool Protocol2DataPath::isActive() const { + return set->getCurrentMetisCard().protocolVersion >= 2; +} + +bool Protocol2DataPath::initSockets() { + + if (!isActive()) + return false; + + closeSockets(); + + const QHostAddress localAddress(set->getHPSDRDeviceLocalAddr()); + const quint16 discoveryPort = set->getMetisPort(); + const int receivers = qMax(1, set->getNumberOfReceivers()); + + m_commandSocket = new QUdpSocket(this); + if (!m_commandSocket->bind(localAddress, discoveryPort, QUdpSocket::DontShareAddress)) { + PROTOCOL2_DEBUG << "command socket bind failed on port " << discoveryPort; + closeSockets(); + return false; + } + + m_statusSocket = new QUdpSocket(this); + if (!m_statusSocket->bind(localAddress, kProtocol2HighPriorityToPcPort, QUdpSocket::DontShareAddress)) { + PROTOCOL2_DEBUG << "status socket bind failed on port " << kProtocol2HighPriorityToPcPort; + closeSockets(); + return false; + } + CHECKED_CONNECT( + m_statusSocket, + SIGNAL(readyRead()), + this, + SLOT(readStatusData())); + + m_ddcSampleBuffers.clear(); + m_ddcSockets.clear(); + for (int rx = 0; rx < receivers; ++rx) { + + QUdpSocket *socket = new QUdpSocket(this); + const quint16 port = kProtocol2DdcBasePort + rx; + if (!socket->bind(localAddress, port, QUdpSocket::DontShareAddress)) { + PROTOCOL2_DEBUG << "DDC socket bind failed on port " << port; + delete socket; + closeSockets(); + return false; + } + + CHECKED_CONNECT( + socket, + SIGNAL(readyRead()), + this, + SLOT(readDdcData())); + + m_ddcSockets.append(socket); + m_ddcSampleBuffers.append(QList()); + } + + m_heartbeatTimer = new QTimer(this); + m_heartbeatTimer->setInterval(100); + CHECKED_CONNECT( + m_heartbeatTimer, + SIGNAL(timeout()), + this, + SLOT(sendHeartbeat())); + + m_partialLegacyFrame.clear(); + m_partialLegacyFrame.reserve(BUFFER_SIZE); + m_legacyControlBytes.fill(0x00, 5); + m_running = false; + + PROTOCOL2_DEBUG << "sockets initialized for " << receivers << " receiver(s)."; + return true; +} + +void Protocol2DataPath::stop() { + + m_running = false; + + if (m_heartbeatTimer) + m_heartbeatTimer->stop(); + + if (m_commandSocket) + sendHighPriorityPacket(false); + + closeSockets(); +} + +void Protocol2DataPath::sendInitFramesToNetworkDevice(int rx) { + Q_UNUSED(rx) +} + +void Protocol2DataPath::networkDeviceStartStop(char value) { + + if (!m_commandSocket) + return; + + if (value == 0) { + m_running = false; + if (m_heartbeatTimer) + m_heartbeatTimer->stop(); + sendHighPriorityPacket(false); + return; + } + + sendGeneralPacket(); + sendDdcSpecificPacket(); + sendHighPriorityPacket(true); + + m_running = true; + if (m_heartbeatTimer) + m_heartbeatTimer->start(); +} + +void Protocol2DataPath::readStatusData() { + + while (m_statusSocket && m_statusSocket->hasPendingDatagrams()) { + + m_statusDatagram.resize(m_statusSocket->pendingDatagramSize()); + m_statusSocket->readDatagram(m_statusDatagram.data(), m_statusDatagram.size()); + + if (m_statusDatagram.size() >= kProtocol2StatusPacketMinSize) + updateLegacyControlBytes(m_statusDatagram); + } +} + +void Protocol2DataPath::readDdcData() { + + QUdpSocket *socket = qobject_cast(sender()); + const int rx = m_ddcSockets.indexOf(socket); + + if (rx < 0) + return; + + while (socket->hasPendingDatagrams()) { + + QByteArray datagram; + datagram.resize(socket->pendingDatagramSize()); + socket->readDatagram(datagram.data(), datagram.size()); + + if (datagram.size() < 16) + continue; + + const int bitsPerSample = ((quint8)datagram.at(12) << 8) | (quint8)datagram.at(13); + const int sampleCount = ((quint8)datagram.at(14) << 8) | (quint8)datagram.at(15); + const int payloadBytes = 16 + sampleCount * 6; + + if (bitsPerSample != 24 || datagram.size() < payloadBytes) + continue; + + for (int i = 0; i < sampleCount; ++i) { + + const char *sample = datagram.constData() + 16 + i * 6; + Protocol2IQSample iqSample; + iqSample.i = read24BitSample(sample); + iqSample.q = read24BitSample(sample + 3); + m_ddcSampleBuffers[rx].append(iqSample); + } + } + + tryProduceLegacyFrames(); +} + +void Protocol2DataPath::sendHeartbeat() { + + if (!m_running) + return; + + sendHighPriorityPacket(true); +} + +void Protocol2DataPath::closeSockets() { + + if (m_heartbeatTimer) { + delete m_heartbeatTimer; + m_heartbeatTimer = 0; + } + + foreach (QUdpSocket *socket, m_ddcSockets) { + socket->close(); + delete socket; + } + m_ddcSockets.clear(); + m_ddcSampleBuffers.clear(); + + if (m_statusSocket) { + m_statusSocket->close(); + delete m_statusSocket; + m_statusSocket = 0; + } + + if (m_commandSocket) { + m_commandSocket->close(); + delete m_commandSocket; + m_commandSocket = 0; + } + + m_partialLegacyFrame.clear(); +} + +void Protocol2DataPath::sendGeneralPacket() { + + QByteArray datagram(kProtocol2GeneralPacketSize, 0x00); + + datagram[0] = (m_generalSequence >> 24) & 0xFF; + datagram[1] = (m_generalSequence >> 16) & 0xFF; + datagram[2] = (m_generalSequence >> 8) & 0xFF; + datagram[3] = m_generalSequence & 0xFF; + datagram[4] = 0x00; + datagram[5] = (kProtocol2DdcSpecificPort >> 8) & 0xFF; + datagram[6] = kProtocol2DdcSpecificPort & 0xFF; + datagram[7] = (kProtocol2DucIqPort >> 8) & 0xFF; + datagram[8] = kProtocol2DucIqPort & 0xFF; + datagram[9] = (HIGH_PRIORITY_FROM_HOST_PORT >> 8) & 0xFF; + datagram[10] = HIGH_PRIORITY_FROM_HOST_PORT & 0xFF; + datagram[11] = (kProtocol2HighPriorityToPcPort >> 8) & 0xFF; + datagram[12] = kProtocol2HighPriorityToPcPort & 0xFF; + datagram[13] = (kProtocol2DdcAudioPort >> 8) & 0xFF; + datagram[14] = kProtocol2DdcAudioPort & 0xFF; + datagram[15] = (kProtocol2DucIqPort >> 8) & 0xFF; + datagram[16] = kProtocol2DucIqPort & 0xFF; + datagram[17] = (kProtocol2DdcBasePort >> 8) & 0xFF; + datagram[18] = kProtocol2DdcBasePort & 0xFF; + datagram[21] = (HIGH_PRIORITY_FROM_HOST_PORT >> 8) & 0xFF; + datagram[22] = HIGH_PRIORITY_FROM_HOST_PORT & 0xFF; + datagram[24] = 0x02; + datagram[26] = 0x10; + datagram[27] = 20; + datagram[28] = 32; + + if (m_commandSocket->writeDatagram(datagram, set->getCurrentMetisCard().ip_address, DEVICE_PORT) >= 0) + ++m_generalSequence; + else + PROTOCOL2_DEBUG << "general packet write failed."; +} + +void Protocol2DataPath::sendDdcSpecificPacket() { + + const int receivers = qMax(1, set->getNumberOfReceivers()); + QByteArray datagram(17 + receivers * 6, 0x00); + + datagram[0] = (m_ddcSequence >> 24) & 0xFF; + datagram[1] = (m_ddcSequence >> 16) & 0xFF; + datagram[2] = (m_ddcSequence >> 8) & 0xFF; + datagram[3] = m_ddcSequence & 0xFF; + datagram[4] = 0x01; + datagram[5] = io->ccTx.dither ? 0x01 : 0x00; + datagram[6] = io->ccTx.random ? 0x01 : 0x00; + + for (int rx = 0; rx < receivers; ++rx) { + + datagram[7 + rx / 8] = datagram.at(7 + rx / 8) | (1 << (rx % 8)); + + const int offset = 17 + rx * 6; + datagram[offset + 0] = 0x00; + datagram[offset + 1] = (io->samplerate >> 8) & 0xFF; + datagram[offset + 2] = io->samplerate & 0xFF; + datagram[offset + 3] = 0x00; + datagram[offset + 4] = 0x00; + datagram[offset + 5] = 24; + } + + if (m_commandSocket->writeDatagram(datagram, set->getCurrentMetisCard().ip_address, kProtocol2DdcSpecificPort) >= 0) + ++m_ddcSequence; + else + PROTOCOL2_DEBUG << "DDC specific packet write failed."; +} + +void Protocol2DataPath::sendHighPriorityPacket(bool run) { + + QByteArray datagram(kProtocol2HighPriorityPacketSize, 0x00); + const QList frequencies = set->getCtrFrequencies(); + const int receivers = qMax(1, set->getNumberOfReceivers()); + + datagram[0] = (m_highPrioritySequence >> 24) & 0xFF; + datagram[1] = (m_highPrioritySequence >> 16) & 0xFF; + datagram[2] = (m_highPrioritySequence >> 8) & 0xFF; + datagram[3] = m_highPrioritySequence & 0xFF; + datagram[4] = run ? 0x01 : 0x00; + + for (int rx = 0; rx < receivers; ++rx) { + + const quint32 encodedFrequency = encodeFrequency(frequencies.value(rx, frequencies.value(0, 0))); + const int offset = 9 + rx * 4; + + datagram[offset + 0] = (encodedFrequency >> 24) & 0xFF; + datagram[offset + 1] = (encodedFrequency >> 16) & 0xFF; + datagram[offset + 2] = (encodedFrequency >> 8) & 0xFF; + datagram[offset + 3] = encodedFrequency & 0xFF; + } + + if (m_commandSocket->writeDatagram(datagram, set->getCurrentMetisCard().ip_address, HIGH_PRIORITY_FROM_HOST_PORT) >= 0) + ++m_highPrioritySequence; + else + PROTOCOL2_DEBUG << "high priority packet write failed."; +} + +void Protocol2DataPath::updateLegacyControlBytes(const QByteArray &statusDatagram) { + + const uchar statusBits = (uchar)statusDatagram.at(4); + const uchar overloadBits = (uchar)statusDatagram.at(5); + + char control0 = 0x00; + if (statusBits & 0x01) control0 |= 0x01; + if (statusBits & 0x04) control0 |= 0x02; + if (statusBits & 0x02) control0 |= 0x04; + + m_legacyControlBytes[0] = control0; + m_legacyControlBytes[1] = (overloadBits & 0x01) ? 0x01 : 0x00; + m_legacyControlBytes[2] = 0x00; + m_legacyControlBytes[3] = 0x00; + m_legacyControlBytes[4] = (char)(set->getCurrentMetisCard().firmwareVersion & 0xFF); +} + +void Protocol2DataPath::tryProduceLegacyFrames() { + + const int receivers = qMax(1, set->getNumberOfReceivers()); + const int halfFrameSamples = samplesPerLegacyHalfFrame(); + + if (halfFrameSamples <= 0) + return; + + while (true) { + + bool hasEnoughData = true; + for (int rx = 0; rx < receivers; ++rx) { + if (rx >= m_ddcSampleBuffers.size() || m_ddcSampleBuffers[rx].size() < halfFrameSamples) { + hasEnoughData = false; + break; + } + } + + if (!hasEnoughData) + break; + + QByteArray halfFrame(BUFFER_SIZE / 2, 0x00); + int pos = 0; + halfFrame[pos++] = SYNC; + halfFrame[pos++] = SYNC; + halfFrame[pos++] = SYNC; + for (int i = 0; i < m_legacyControlBytes.size(); ++i) + halfFrame[pos++] = m_legacyControlBytes.at(i); + + for (int sampleIndex = 0; sampleIndex < halfFrameSamples; ++sampleIndex) { + for (int rx = 0; rx < receivers; ++rx) { + + const Protocol2IQSample sample = m_ddcSampleBuffers[rx].takeFirst(); + halfFrame[pos++] = (sample.i >> 16) & 0xFF; + halfFrame[pos++] = (sample.i >> 8) & 0xFF; + halfFrame[pos++] = sample.i & 0xFF; + halfFrame[pos++] = (sample.q >> 16) & 0xFF; + halfFrame[pos++] = (sample.q >> 8) & 0xFF; + halfFrame[pos++] = sample.q & 0xFF; + } + + halfFrame[pos++] = 0x00; + halfFrame[pos++] = 0x00; + } + + m_partialLegacyFrame += halfFrame; + if (m_partialLegacyFrame.size() == BUFFER_SIZE) { + if (!io->iq_queue.isFull()) + io->iq_queue.enqueue(m_partialLegacyFrame); + m_partialLegacyFrame.clear(); + } + } +} + +int Protocol2DataPath::samplesPerLegacyHalfFrame() const { + + const int receivers = qMax(1, set->getNumberOfReceivers()); + const int bytesPerSample = receivers * 6 + 2; + + return (BUFFER_SIZE / 2 - 8) / bytesPerSample; +} + +quint32 Protocol2DataPath::encodeFrequency(long frequency) const { + return (quint32)frequency; +} + +qint32 Protocol2DataPath::read24BitSample(const char *data) const { + + qint32 value = ((qint32)(quint8)data[0] << 16) | + ((qint32)(quint8)data[1] << 8) | + (qint32)(quint8)data[2]; + + if (value & 0x00800000) + value |= 0xFF000000; + + return value; +} diff --git a/Source/src/DataEngine/cusdr_protocol2_io.h b/Source/src/DataEngine/cusdr_protocol2_io.h new file mode 100644 index 0000000..0c38f1b --- /dev/null +++ b/Source/src/DataEngine/cusdr_protocol2_io.h @@ -0,0 +1,67 @@ +/** +* @file cusdr_protocol2_io.h +* @brief openHPSDR Protocol 2 transport helper +*/ + +#ifndef _CUSDR_PROTOCOL2_IO_H +#define _CUSDR_PROTOCOL2_IO_H + +#include "cusdr_settings.h" + +#include +#include +#include + +struct Protocol2IQSample { + qint32 i; + qint32 q; +}; + +class Protocol2DataPath : public QObject { + + Q_OBJECT + +public: + Protocol2DataPath(Settings *settings, THPSDRParameter *ioData, QObject *parent = 0); + ~Protocol2DataPath(); + + bool isActive() const; + bool initSockets(); + void stop(); + void sendInitFramesToNetworkDevice(int rx); + void networkDeviceStartStop(char value); + +private slots: + void readStatusData(); + void readDdcData(); + void sendHeartbeat(); + +private: + void closeSockets(); + void sendGeneralPacket(); + void sendDdcSpecificPacket(); + void sendHighPriorityPacket(bool run); + void updateLegacyControlBytes(const QByteArray &statusDatagram); + void tryProduceLegacyFrames(); + int samplesPerLegacyHalfFrame() const; + quint32 encodeFrequency(long frequency) const; + qint32 read24BitSample(const char *data) const; + +private: + Settings* set; + THPSDRParameter* io; + QUdpSocket* m_commandSocket; + QUdpSocket* m_statusSocket; + QList m_ddcSockets; + QList > m_ddcSampleBuffers; + QTimer* m_heartbeatTimer; + QByteArray m_partialLegacyFrame; + QByteArray m_statusDatagram; + QByteArray m_legacyControlBytes; + bool m_running; + quint32 m_generalSequence; + quint32 m_ddcSequence; + quint32 m_highPrioritySequence; +}; + +#endif // _CUSDR_PROTOCOL2_IO_H diff --git a/Source/src/cusdr_settings.h b/Source/src/cusdr_settings.h index 4ade040..f1a1772 100644 --- a/Source/src/cusdr_settings.h +++ b/Source/src/cusdr_settings.h @@ -483,6 +483,8 @@ typedef struct _networkDeviceCard { char mac_address[18]; int boardID; QString boardName; + int protocolVersion; + int firmwareVersion; } TNetworkDevicecard;