fix
This commit is contained in:
parent
14d983c840
commit
dde80e5696
62
Source/NEXT_STEPS.md
Normal file
62
Source/NEXT_STEPS.md
Normal file
@ -0,0 +1,62 @@
|
||||
# Next Steps
|
||||
|
||||
## Priority
|
||||
|
||||
1. Investigate Protocol 2 stop handling.
|
||||
2. Complete Protocol 2 Alex support for boards with `Alex1`.
|
||||
3. Continue UI cleanup for Protocol 2 specific hardware presentation.
|
||||
|
||||
## Immediate Issues To Debug
|
||||
|
||||
### Protocol 2 stop crash
|
||||
|
||||
- Re-test why the application crashes when the user presses `Stop` while working with a Protocol 2 device.
|
||||
- Re-verify why the Protocol 2 stop command may still not be correctly sent to the transceiver.
|
||||
- Check the shutdown path across:
|
||||
- `src/DataEngine/cusdr_dataEngine.cpp`
|
||||
- `src/DataEngine/cusdr_dataIO.cpp`
|
||||
- `src/DataEngine/cusdr_protocol2_io.cpp`
|
||||
- Already fixed one likely cause in `src/DataEngine/cusdr_protocol2_io.cpp`:
|
||||
- duplicate `P2 stop` send,
|
||||
- stop without `m_running`,
|
||||
- timer/socket signal disconnect before deletion.
|
||||
- Already fixed a second class of issues in `src/DataEngine/cusdr_dataEngine.cpp`:
|
||||
- `DataIO` control calls now go through `QMetaObject::invokeMethod(..., Qt::BlockingQueuedConnection)`,
|
||||
- so start/stop/init execute in the `DataIO` thread instead of the caller thread.
|
||||
- Already fixed a concrete `Protocol 2` destructor bug in `src/DataEngine/cusdr_dataIO.cpp`:
|
||||
- `m_dataIOSocketOn == true` with `m_dataIOSocket == 0` could dereference a null pointer during shutdown.
|
||||
- Already moved `CSoundOut` deletion out of `DataIO::stop()` and into the destructor to reduce timer/thread teardown issues.
|
||||
- Pay special attention to:
|
||||
- socket lifetime,
|
||||
- timer lifetime,
|
||||
- `QObject` ownership and deletion thread,
|
||||
- repeated stop calls,
|
||||
- `networkDeviceStartStop(0)`,
|
||||
- `Protocol2DataPath::stop()`,
|
||||
- `sendHighPriorityPacket(false)`,
|
||||
- whether the command socket is still valid when stop is triggered,
|
||||
- whether `DataIO` / `Protocol2DataPath` should be destroyed via `deleteLater()` in their own thread instead of direct delete from `DataEngine`,
|
||||
- whether the target `P2` board expects additional shutdown packets or repeated `run = 0` frames.
|
||||
|
||||
## Protocol 2 Functional Work
|
||||
|
||||
- Implement proper `Alex1/BPF2/RX2` handling for boards that support a second Alex register:
|
||||
- Orion MkII
|
||||
- SATURN / ANAN-G2
|
||||
- Use Appendix D from `doc/openHPSDR Ethernet Protocol v4.3.docx` to map the second Alex register bits correctly.
|
||||
- Consider extending Protocol 2 capability handling beyond board defaults where discovery returns more precise information.
|
||||
- Consider support for XML/full hardware description discovery replies for board `254/255`.
|
||||
|
||||
## UI Work
|
||||
|
||||
- Review UI areas that still assume `Metis/Hermes` semantics internally.
|
||||
- Make Protocol 2 model/capability presentation more explicit where useful:
|
||||
- selected model,
|
||||
- protocol version,
|
||||
- ADC/DDC count,
|
||||
- Alex availability.
|
||||
|
||||
## Reference
|
||||
|
||||
- Detailed log of completed work:
|
||||
- `WORKLOG_PROTOCOL2_2026-04-13.md`
|
||||
187
Source/WORKLOG_PROTOCOL2_2026-04-13.md
Normal file
187
Source/WORKLOG_PROTOCOL2_2026-04-13.md
Normal file
@ -0,0 +1,187 @@
|
||||
# cudaSDR Protocol 2 Worklog
|
||||
|
||||
Date: 2026-04-13
|
||||
|
||||
This file records the Protocol 2 related work completed in this repository so future sessions can quickly restore context.
|
||||
|
||||
## Implemented Earlier In This Session History
|
||||
|
||||
- Added separate openHPSDR Protocol 2 transport implementation:
|
||||
- `src/DataEngine/cusdr_protocol2_io.h`
|
||||
- `src/DataEngine/cusdr_protocol2_io.cpp`
|
||||
- Added separate Protocol 2 discovery implementation:
|
||||
- `src/DataEngine/cusdr_discoverer_P2.h`
|
||||
- `src/DataEngine/cusdr_discoverer_P2.cpp`
|
||||
- Wired Protocol 2 into the existing project flow without replacing Protocol 1.
|
||||
- Updated `DataIO` so it delegates network start/stop and receive path to the separate Protocol 2 module when the selected device reports `protocolVersion >= 2`.
|
||||
- Added Protocol 2 fallback search after Protocol 1 and fixed the `Search` button path so manual search also tries Protocol 2.
|
||||
- Added initial RX-only Alex support for Protocol 2:
|
||||
- General packet enables Alex.
|
||||
- High Priority packet sends `Alex 0`.
|
||||
- Filters switch automatically by band/frequency using existing Alex settings.
|
||||
|
||||
## Implemented Today
|
||||
|
||||
### 1. Device capability model for Protocol 2
|
||||
|
||||
- Extended `TNetworkDevicecard` in `src/cusdr_settings.h` with Protocol 2 specific fields:
|
||||
- `adcCount`
|
||||
- `ddcCount`
|
||||
- `dspClockHz`
|
||||
- `iqFormatFlags`
|
||||
- `phaseWords`
|
||||
- `hasAlex0`
|
||||
- `hasAlex1`
|
||||
|
||||
### 2. Separate board profile helper
|
||||
|
||||
- Added:
|
||||
- `src/DataEngine/cusdr_protocol2_profile.h`
|
||||
- `src/DataEngine/cusdr_protocol2_profile.cpp`
|
||||
- This helper maps Protocol 2 board ID to default hardware capabilities and human-readable model name.
|
||||
- It also provides a summary string for UI device lists.
|
||||
|
||||
### 3. Discovery improvements for Protocol 2
|
||||
|
||||
- Updated `src/DataEngine/cusdr_discoverer_P2.cpp` to:
|
||||
- use board profiles,
|
||||
- fill the new capability fields in `TNetworkDevicecard`,
|
||||
- parse extra discovery reply fields from the documentation:
|
||||
- byte 20: number of implemented DDCs,
|
||||
- byte 21: frequency vs phase word,
|
||||
- byte 22: supported IQ/endian formats.
|
||||
- Updated `src/DataEngine/cusdr_discoverer_P1.cpp` to initialize the new fields to safe defaults for Protocol 1 devices.
|
||||
|
||||
### 4. Protocol 2 initialization based on actual device profile
|
||||
|
||||
- Updated `src/DataEngine/cusdr_protocol2_io.cpp`:
|
||||
- fixed General packet bit handling,
|
||||
- enabled phase-word mode where required,
|
||||
- selected IQ format only when the discovery flags say it is supported,
|
||||
- used discovered/default ADC count in the DDC Specific packet,
|
||||
- routed DDCs across ADCs,
|
||||
- limited receiver count to hardware DDC count,
|
||||
- used board DSP clock to compute phase words,
|
||||
- preserved RX-only behavior.
|
||||
|
||||
### 5. Data engine behavior for Protocol 2 devices
|
||||
|
||||
- Updated `src/DataEngine/cusdr_dataEngine.cpp` so Protocol 2 devices:
|
||||
- are treated as modern integrated hardware instead of legacy Mercury/Penelope stacks,
|
||||
- automatically clamp receiver count to discovered DDC count,
|
||||
- publish Hermes firmware field from the Protocol 2 discovery result for existing UI/status paths,
|
||||
- enable Alex UI only if the selected Protocol 2 board profile says Alex is present.
|
||||
|
||||
### 6. UI modernization for Protocol 2 devices
|
||||
|
||||
- Updated `src/cusdr_networkWidget.cpp` so the device list shows a summary instead of only IP address.
|
||||
- Updated `src/GL/cusdr_oglDisplayPanel.h` and `src/GL/cusdr_oglDisplayPanel.cpp` so the top status display uses the real Protocol 2 model name instead of always showing `Hermes`.
|
||||
|
||||
### 7. Documentation-driven corrections made today
|
||||
|
||||
- Re-read local documentation:
|
||||
- `doc/openHPSDR Ethernet Protocol v4.3.docx`
|
||||
- Corrected Protocol 2 board naming and assumptions from the document:
|
||||
- board 1: `Hermes / ANAN-10/100`
|
||||
- board 2: `Hermes / ANAN-10E/100B`
|
||||
- board 5: `Orion MkII / ANAN-7/8000DLE`
|
||||
- board 10: `Saturn / ANAN-G2`
|
||||
- Corrected one important capability assumption:
|
||||
- board 2 no longer auto-enables Alex RX support, because the document indicates no Alex receive filters for that board.
|
||||
|
||||
## Build Status
|
||||
|
||||
- Full build completed successfully:
|
||||
- `make -j4`
|
||||
- Output binary:
|
||||
- `bin/cudaSDR`
|
||||
|
||||
## Additional Fix Applied Later Today
|
||||
|
||||
### Protocol 2 stop path hardening
|
||||
|
||||
- Investigated the stop path after a reported crash when pressing `Stop` with a Protocol 2 device.
|
||||
- Confirmed that the shutdown flow was effectively hitting Protocol 2 stop twice:
|
||||
- first through `DataEngine::stop() -> DataIO::networkDeviceStartStop(0)`,
|
||||
- then again through `DataIO::stop() -> Protocol2DataPath::stop()`.
|
||||
- Updated `src/DataEngine/cusdr_protocol2_io.cpp` so that:
|
||||
- `Protocol2DataPath::stop()` only sends the final `run = 0` High Priority packet if the path was actually running,
|
||||
- `networkDeviceStartStop(0)` returns immediately if Protocol 2 is already stopped,
|
||||
- `closeSockets()` explicitly disconnects timer and socket signals before deletion.
|
||||
- This removes the most obvious duplicate-stop race and reduces the chance of a timer/socket callback firing during teardown.
|
||||
- Build was re-checked after this fix:
|
||||
- `make -j4`
|
||||
- success
|
||||
|
||||
### Still needs runtime verification
|
||||
|
||||
- This stop-path fix is compile-verified but still needs validation on real Protocol 2 hardware.
|
||||
- If the transceiver still does not stop cleanly, the next thing to verify is whether the specific board expects more than a single `High Priority run = 0` packet before socket teardown.
|
||||
|
||||
## Additional Investigation And Fixes After Emulator Testing
|
||||
|
||||
### 1. Cross-thread DataIO control calls
|
||||
|
||||
- Emulator testing showed that Protocol 2 startup and shutdown were still unreliable.
|
||||
- Investigation found that `DataIO` is moved to its own `QThread`, but `DataEngine` was still calling these methods directly from another thread:
|
||||
- `sendInitFramesToNetworkDevice(...)`
|
||||
- `networkDeviceStartStop(...)`
|
||||
- `stop()`
|
||||
- Updated `src/DataEngine/cusdr_dataEngine.cpp` to route those calls through:
|
||||
- `QMetaObject::invokeMethod(..., Qt::BlockingQueuedConnection)`
|
||||
- This was done so the Protocol 2 sockets and timers are manipulated from the `DataIO` thread they belong to.
|
||||
|
||||
### 2. Additional Protocol 2 stop crash findings
|
||||
|
||||
- User logs then showed:
|
||||
- `QObject::killTimer: Timers cannot be stopped from another thread`
|
||||
- `QObject::~QObject: Timers cannot be stopped from another thread`
|
||||
- `DataEngine:: data IO thread not yet finished...`
|
||||
- This indicated there were still object-lifetime issues during teardown, not only packet-order issues.
|
||||
|
||||
### 3. DataIO destructor bug in Protocol 2 mode
|
||||
|
||||
- Found a concrete bug in `src/DataEngine/cusdr_dataIO.cpp`:
|
||||
- in Protocol 2 mode, `m_dataIOSocketOn` can be true while `m_dataIOSocket` is never created,
|
||||
- but `DataIO::~DataIO()` still dereferenced `m_dataIOSocket`.
|
||||
- Fixed destructor logic so the legacy socket is only closed/deleted when the pointer is valid.
|
||||
- This was a direct segfault candidate in Protocol 2 shutdown.
|
||||
|
||||
### 4. Sound output teardown issue
|
||||
|
||||
- Found that `DataIO::stop()` was stopping and deleting `CSoundOut` while Protocol 2 shutdown was already in progress.
|
||||
- Adjusted `src/DataEngine/cusdr_dataIO.cpp` so:
|
||||
- `DataIO::stop()` no longer deletes the sound object,
|
||||
- `CSoundOut` shutdown is deferred to `DataIO::~DataIO()`.
|
||||
- This was done to reduce cross-thread/timer teardown problems during the live stop sequence.
|
||||
|
||||
### Current status after these fixes
|
||||
|
||||
- Build re-checked successfully after each change:
|
||||
- `make -j4`
|
||||
- Protocol 2 stop handling is more robust than before, but user testing still shows there may be at least one remaining shutdown/lifetime issue.
|
||||
- Most likely next area:
|
||||
- final deletion order of `DataIO` / `Protocol2DataPath` and their child `QObject`s after `m_dataIOThread->quit()`.
|
||||
|
||||
## Known Limitations / Remaining Work
|
||||
|
||||
- Protocol 2 implementation is still RX-only.
|
||||
- Protocol 2 Alex support currently sends `Alex 0` only.
|
||||
- Boards with `Alex1` support such as Orion MkII / SATURN are not yet fully mapped to the second Alex register according to Appendix D.
|
||||
- Full XML or extended hardware-description discovery modes (`board 254/255`) are not implemented.
|
||||
- Wideband Protocol 2 path is still not integrated.
|
||||
- Some UI sections still conceptually assume old `Metis/Hermes` naming internally even though the visible device/model handling is now better.
|
||||
|
||||
## Good Starting Points For Next Session
|
||||
|
||||
- If continuing Protocol 2 work, read these files first:
|
||||
- `src/DataEngine/cusdr_protocol2_profile.cpp`
|
||||
- `src/DataEngine/cusdr_discoverer_P2.cpp`
|
||||
- `src/DataEngine/cusdr_protocol2_io.cpp`
|
||||
- `src/DataEngine/cusdr_dataEngine.cpp`
|
||||
- `src/cusdr_networkWidget.cpp`
|
||||
- `src/GL/cusdr_oglDisplayPanel.cpp`
|
||||
- For documentation reference, use:
|
||||
- `doc/openHPSDR Ethernet Protocol v4.3.docx`
|
||||
- Highest value next task:
|
||||
- implement proper `Alex1/BPF2/RX2` handling for Protocol 2 boards that support a second Alex register.
|
||||
@ -1,7 +1,7 @@
|
||||
[General]
|
||||
cudaSDR%20BETA=v0.3.2.13+
|
||||
cudaSDR%20BETA%20=v0.3.2.13+
|
||||
saved=\x43f\x43e\x43d\x435\x434\x435\x43b\x44c\x43d\x438\x43a 13 \x430\x43f\x440\x435\x43b\x44f 2026 20:08:53
|
||||
saved=\x43f\x43e\x43d\x435\x434\x435\x43b\x44c\x43d\x438\x43a 13 \x430\x43f\x440\x435\x43b\x44f 2026 22:06:20
|
||||
|
||||
[ChirpWSPR]
|
||||
chirpAmplitude=75
|
||||
@ -106,7 +106,7 @@ checkfw=false
|
||||
excalibur=false
|
||||
hardware=1
|
||||
interface=hermes
|
||||
mercury=true
|
||||
mercury=false
|
||||
penelope=false
|
||||
pennylane=false
|
||||
|
||||
@ -114,7 +114,7 @@ pennylane=false
|
||||
audio_port=15000
|
||||
hpsdr_local_ipAddress=192.168.122.1
|
||||
listen_port=11000
|
||||
metis_port=47257
|
||||
metis_port=48349
|
||||
server_ipAddress=192.168.122.1
|
||||
server_port=52685
|
||||
socketBufferSize=32
|
||||
@ -202,7 +202,7 @@ attenuatorGen=off
|
||||
audioVolume=73
|
||||
averaging=on
|
||||
averagingCnt=5
|
||||
centerFrequency=7096940
|
||||
centerFrequency=7055083
|
||||
clickVFO=on
|
||||
dBmPanScaleMax10cm=-10
|
||||
dBmPanScaleMax10m=-30
|
||||
@ -292,7 +292,7 @@ lastCenterFrequency23cm=902000000
|
||||
lastCenterFrequency2m=144000000
|
||||
lastCenterFrequency30m=10100000
|
||||
lastCenterFrequency33cm=902000000
|
||||
lastCenterFrequency40m=7096940
|
||||
lastCenterFrequency40m=7055083
|
||||
lastCenterFrequency5cm=902000000
|
||||
lastCenterFrequency60m=5260000
|
||||
lastCenterFrequency630m=472000
|
||||
@ -314,7 +314,7 @@ lastVfoFrequency23cm=902000000
|
||||
lastVfoFrequency2m=144000000
|
||||
lastVfoFrequency30m=10100000
|
||||
lastVfoFrequency33cm=902000000
|
||||
lastVfoFrequency40m=7116128
|
||||
lastVfoFrequency40m=7087913
|
||||
lastVfoFrequency5cm=902000000
|
||||
lastVfoFrequency60m=5260000
|
||||
lastVfoFrequency630m=472000
|
||||
@ -325,7 +325,7 @@ lastVfoFrequencyGen=22875900
|
||||
mouseWheelFreqStep=100
|
||||
panLocked=off
|
||||
panMode=FILLEDLINE
|
||||
vfoFrequency=7116128
|
||||
vfoFrequency=7087913
|
||||
waterfallMode=ENHANCED
|
||||
waterfallOffsetHi=20
|
||||
waterfallOffsetLo=-5
|
||||
|
||||
@ -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\x5@\0\0\x2\xff\0\0\0\0\0\0\0\0\0\0\x5@\0\0\x2\xff\0\0\0\0\0\0\0\0\n\0\0\0\0\0\0\0\0\0\0\0\x5@\0\0\x2\xff)
|
||||
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\x2<\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\x5\x41\0\0\x2<\0\0\0\x4\0\0\0\x4\0\0\0\b\0\0\0\b\xfc\0\0\0\x9e\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\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\x5@\0\0\x3\x1b\0\0\0\0\0\0\0\x1c\0\0\x5@\0\0\x3\x1b\0\0\0\0\0\0\0\0\n\0\0\0\0\0\0\0\0\x1c\0\0\x5@\0\0\x3\x1b)
|
||||
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\x2<\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\x5\x41\0\0\x2<\0\0\0\x4\0\0\0\x4\0\0\0\b\0\0\0\b\xfc\0\0\0\xa5\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\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)
|
||||
|
||||
1936
Source/cudaSDR.log
1936
Source/cudaSDR.log
File diff suppressed because it is too large
Load Diff
@ -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_profile.h \
|
||||
./src/DataEngine/cusdr_protocol2_io.h \
|
||||
./src/DataEngine/cusdr_receiver.h \
|
||||
./src/DataEngine/soundout.h \
|
||||
@ -103,6 +104,7 @@ HEADERS += \
|
||||
./src/DataEngine/cusdr_dataIO.h \
|
||||
./src/DataEngine/cusdr_discoverer_P1.h \
|
||||
./src/DataEngine/cusdr_discoverer_P2.h \
|
||||
./src/DataEngine/cusdr_protocol2_profile.h \
|
||||
./src/DataEngine/cusdr_protocol2_io.h \
|
||||
./src/DataEngine/cusdr_receiver.h \
|
||||
./src/DataEngine/soundout.h \
|
||||
@ -178,6 +180,7 @@ SOURCES += \
|
||||
./src/DataEngine/cusdr_dataIO.cpp \
|
||||
./src/DataEngine/cusdr_discoverer_P1.cpp \
|
||||
./src/DataEngine/cusdr_discoverer_P2.cpp \
|
||||
./src/DataEngine/cusdr_protocol2_profile.cpp \
|
||||
./src/DataEngine/cusdr_protocol2_io.cpp \
|
||||
./src/DataEngine/cusdr_receiver.cpp \
|
||||
./src/DataEngine/soundout.cpp \
|
||||
@ -248,6 +251,7 @@ SOURCES += \
|
||||
./src/DataEngine/cusdr_dataIO.cpp \
|
||||
./src/DataEngine/cusdr_discoverer_P1.cpp \
|
||||
./src/DataEngine/cusdr_discoverer_P2.cpp \
|
||||
./src/DataEngine/cusdr_protocol2_profile.cpp \
|
||||
./src/DataEngine/cusdr_protocol2_io.cpp \
|
||||
./src/DataEngine/cusdr_receiver.cpp \
|
||||
./src/DataEngine/soundout.cpp \
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE QtCreatorProject>
|
||||
<!-- Written by QtCreator 19.0.0, 2026-04-13T20:07:04. -->
|
||||
<!-- Written by QtCreator 19.0.0, 2026-04-13T20:38:08. -->
|
||||
<qtcreator>
|
||||
<data>
|
||||
<variable>EnvironmentId</variable>
|
||||
|
||||
@ -39,6 +39,7 @@
|
||||
// use WIDEBAND_PROCESSOR_DEBUG
|
||||
|
||||
#include "cusdr_dataEngine.h"
|
||||
#include "cusdr_protocol2_profile.h"
|
||||
|
||||
|
||||
/*!
|
||||
@ -62,6 +63,45 @@ static int firstTimeRxInit;
|
||||
static quint8 adc_rx1_4, adc_rx5_8, adc_rx9_16;
|
||||
static quint8 new_adc_rx1_4, new_adc_rx5_8, new_adc_rx9_16;
|
||||
|
||||
namespace {
|
||||
|
||||
bool invokeDataIOInitFrame(DataIO *dataIO, int rx) {
|
||||
|
||||
if (!dataIO)
|
||||
return false;
|
||||
|
||||
return QMetaObject::invokeMethod(
|
||||
dataIO,
|
||||
"sendInitFramesToNetworkDevice",
|
||||
Qt::BlockingQueuedConnection,
|
||||
Q_ARG(int, rx));
|
||||
}
|
||||
|
||||
bool invokeDataIOStartStop(DataIO *dataIO, char value) {
|
||||
|
||||
if (!dataIO)
|
||||
return false;
|
||||
|
||||
return QMetaObject::invokeMethod(
|
||||
dataIO,
|
||||
"networkDeviceStartStop",
|
||||
Qt::BlockingQueuedConnection,
|
||||
Q_ARG(char, value));
|
||||
}
|
||||
|
||||
bool invokeDataIOStop(DataIO *dataIO) {
|
||||
|
||||
if (!dataIO)
|
||||
return false;
|
||||
|
||||
return QMetaObject::invokeMethod(
|
||||
dataIO,
|
||||
"stop",
|
||||
Qt::BlockingQueuedConnection);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
DataEngine::DataEngine(QObject *parent)
|
||||
: QObject(parent)
|
||||
, set(Settings::instance())
|
||||
@ -509,6 +549,15 @@ bool DataEngine::findHPSDRDevices() {
|
||||
SleeperThread::msleep(100);
|
||||
|
||||
if (set->getCurrentMetisCard().protocolVersion >= 2) {
|
||||
const TNetworkDevicecard currentDevice = set->getCurrentMetisCard();
|
||||
set->setHPSDRHardware(1);
|
||||
set->setMercuryPresence(false);
|
||||
set->setPenelopePresence(false);
|
||||
set->setPennyLanePresence(false);
|
||||
set->setExcaliburPresence(false);
|
||||
set->setAlexPresence(currentDevice.hasAlex0 || currentDevice.hasAlex1);
|
||||
if (currentDevice.ddcCount > 0 && set->getNumberOfReceivers() > currentDevice.ddcCount)
|
||||
set->setReceivers(this, currentDevice.ddcCount);
|
||||
io.hermesFW = set->getCurrentMetisCard().firmwareVersion;
|
||||
set->setHermesVersion(io.hermesFW);
|
||||
return true;
|
||||
@ -586,10 +635,10 @@ bool DataEngine::getFirmwareVersions() {
|
||||
|
||||
// pre-conditioning
|
||||
for (int i = 0; i < io.receivers; i++)
|
||||
m_dataIO->sendInitFramesToNetworkDevice(i);
|
||||
invokeDataIOInitFrame(m_dataIO, i);
|
||||
|
||||
if (m_serverMode == QSDR::SDRMode)
|
||||
m_dataIO->networkDeviceStartStop(0x01); // 0x01 for starting Metis without wide band data
|
||||
invokeDataIOStartStop(m_dataIO, 0x01); // 0x01 for starting Metis without wide band data
|
||||
|
||||
m_networkDeviceRunning = true;
|
||||
setSystemState(QSDR::NoError, m_hwInterface, m_serverMode, QSDR::DataEngineUp);
|
||||
@ -992,12 +1041,12 @@ bool DataEngine::start() {
|
||||
|
||||
// pre-conditioning
|
||||
for (int i = 0; i < io.receivers; i++)
|
||||
m_dataIO->sendInitFramesToNetworkDevice(i);
|
||||
invokeDataIOInitFrame(m_dataIO, i);
|
||||
|
||||
if (m_serverMode == QSDR::SDRMode && set->getWidebandData())
|
||||
m_dataIO->networkDeviceStartStop(0x03); // 0x03 for starting the device with wide band data
|
||||
invokeDataIOStartStop(m_dataIO, 0x03); // 0x03 for starting the device with wide band data
|
||||
else
|
||||
m_dataIO->networkDeviceStartStop(0x01); // 0x01 for starting the device without wide band data
|
||||
invokeDataIOStartStop(m_dataIO, 0x01); // 0x01 for starting the device without wide band data
|
||||
|
||||
m_networkDeviceRunning = true;
|
||||
|
||||
@ -1022,7 +1071,7 @@ void DataEngine::stop() {
|
||||
setTimeStamp(this, false);
|
||||
|
||||
// stop the device
|
||||
m_dataIO->networkDeviceStartStop(0);
|
||||
invokeDataIOStartStop(m_dataIO, 0);
|
||||
m_networkDeviceRunning = false;
|
||||
DATA_ENGINE_DEBUG << "HPSDR device stopped";
|
||||
|
||||
@ -1577,7 +1626,7 @@ void DataEngine::stopDataIO() {
|
||||
|
||||
if (m_dataIOThread->isRunning()) {
|
||||
|
||||
m_dataIO->stop();
|
||||
invokeDataIOStop(m_dataIO);
|
||||
m_dataIOThread->quit();
|
||||
|
||||
while (!m_dataIOThread->isFinished()) {
|
||||
|
||||
@ -109,11 +109,17 @@ DataIO::DataIO(THPSDRParameter *ioData)
|
||||
|
||||
DataIO::~DataIO() {
|
||||
|
||||
if (m_dataIOSocketOn) {
|
||||
if (m_dataIOSocketOn && m_dataIOSocket) {
|
||||
m_dataIOSocket->close();
|
||||
delete m_dataIOSocket;
|
||||
m_dataIOSocket = 0;
|
||||
}
|
||||
|
||||
if (m_pSoundCardOut) {
|
||||
m_pSoundCardOut->Stop();
|
||||
delete m_pSoundCardOut;
|
||||
m_pSoundCardOut = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void DataIO::stop() {
|
||||
@ -125,11 +131,8 @@ void DataIO::stop() {
|
||||
if (m_protocol2 && m_protocol2->isActive())
|
||||
m_protocol2->stop();
|
||||
|
||||
if(m_pSoundCardOut) {
|
||||
if (m_pSoundCardOut)
|
||||
SleeperThread::msleep(100);
|
||||
m_pSoundCardOut->Stop();
|
||||
delete m_pSoundCardOut;
|
||||
}
|
||||
}
|
||||
|
||||
void DataIO::initDataReceiverSocket() {
|
||||
|
||||
@ -228,6 +228,13 @@ int DiscovererP1::findHPSDRDevices() {
|
||||
mcP1.boardName = str;
|
||||
mcP1.protocolVersion = 1;
|
||||
mcP1.firmwareVersion = m_deviceDatagram.at(9) & 0xFF;
|
||||
mcP1.adcCount = 0;
|
||||
mcP1.ddcCount = 0;
|
||||
mcP1.dspClockHz = 0;
|
||||
mcP1.iqFormatFlags = 0;
|
||||
mcP1.phaseWords = false;
|
||||
mcP1.hasAlex0 = false;
|
||||
mcP1.hasAlex1 = false;
|
||||
io->networkIOMutex.lock();
|
||||
DISCOVERER_DEBUG << "Device board ID: " << no;
|
||||
DISCOVERER_DEBUG << "Device is: " << qPrintable(str);
|
||||
|
||||
@ -28,6 +28,7 @@
|
||||
#define LOG_DISCOVERER
|
||||
|
||||
#include "cusdr_discoverer_P2.h"
|
||||
#include "cusdr_protocol2_profile.h"
|
||||
#include "Util/cusdr_buttons.h"
|
||||
|
||||
|
||||
@ -44,25 +45,6 @@ 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();
|
||||
@ -223,24 +205,40 @@ int DiscovererP2::findHPSDRDevices() {
|
||||
io->networkIOMutex.unlock();
|
||||
|
||||
device = m_deviceDatagram[11] & 0xFF;
|
||||
QString str = protocol2BoardName(device);
|
||||
const Protocol2BoardProfile profile = protocol2BoardProfile(device);
|
||||
QString str = profile.boardName;
|
||||
|
||||
mcP2.boardID = device;
|
||||
mcP2.boardName = str;
|
||||
mcP2.protocolVersion = m_deviceDatagram[12] & 0xFF;
|
||||
mcP2.firmwareVersion = m_deviceDatagram[13] & 0xFF;
|
||||
mcP2.adcCount = profile.adcCount;
|
||||
mcP2.ddcCount = profile.defaultDdcCount;
|
||||
mcP2.dspClockHz = profile.dspClockHz;
|
||||
mcP2.iqFormatFlags = 0;
|
||||
mcP2.phaseWords = profile.phaseWords;
|
||||
mcP2.hasAlex0 = profile.hasAlex0;
|
||||
mcP2.hasAlex1 = profile.hasAlex1;
|
||||
|
||||
if (m_deviceDatagram.size() >= 25) {
|
||||
mcP2.ddcCount = m_deviceDatagram[20] & 0xFF;
|
||||
mcP2.phaseWords = (m_deviceDatagram[21] & 0xFF) != 0;
|
||||
mcP2.iqFormatFlags = m_deviceDatagram[22] & 0xFF;
|
||||
}
|
||||
|
||||
io->networkIOMutex.lock();
|
||||
DISCOVERER_DEBUG << "Protocol 2 device board ID: " << device;
|
||||
DISCOVERER_DEBUG << "Protocol 2 device is: " << qPrintable(str);
|
||||
DISCOVERER_DEBUG << "Protocol 2 capabilities: "
|
||||
<< mcP2.adcCount << " ADC, "
|
||||
<< mcP2.ddcCount << " DDC, phaseWords="
|
||||
<< mcP2.phaseWords << ", iqFlags=0x"
|
||||
<< QString::number(mcP2.iqFormatFlags, 16);
|
||||
io->networkIOMutex.unlock();
|
||||
|
||||
m_deviceCards.append(mcP2);
|
||||
|
||||
str += " (";
|
||||
str += mcP2.ip_address.toString();
|
||||
str += ")";
|
||||
|
||||
set->addNetworkIOComboBoxEntry(str);
|
||||
set->addNetworkIOComboBoxEntry(protocol2DeviceSummary(mcP2));
|
||||
devicesFound++;
|
||||
}
|
||||
else {
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
#define LOG_DATAIO
|
||||
|
||||
#include "cusdr_protocol2_io.h"
|
||||
#include "cusdr_protocol2_profile.h"
|
||||
|
||||
#ifdef LOG_DATAIO
|
||||
# define PROTOCOL2_DEBUG qDebug().nospace() << "Protocol2::\t"
|
||||
@ -25,6 +26,17 @@ static const int kProtocol2GeneralPacketSize = 60;
|
||||
static const int kProtocol2HighPriorityPacketSize = 1444;
|
||||
static const int kProtocol2StatusPacketMinSize = 31;
|
||||
|
||||
int protocol2ReceiverCount(Settings *set) {
|
||||
|
||||
const TNetworkDevicecard device = set->getCurrentMetisCard();
|
||||
const int requestedReceivers = qMax(1, set->getNumberOfReceivers());
|
||||
|
||||
if (device.ddcCount > 0)
|
||||
return qMin(requestedReceivers, device.ddcCount);
|
||||
|
||||
return requestedReceivers;
|
||||
}
|
||||
|
||||
quint32 alexFilterWordForFrequency(Settings *set, long frequency, int currentBand) {
|
||||
|
||||
if (!set || !set->getAlexPresence())
|
||||
@ -128,7 +140,7 @@ bool Protocol2DataPath::initSockets() {
|
||||
|
||||
const QHostAddress localAddress(set->getHPSDRDeviceLocalAddr());
|
||||
const quint16 discoveryPort = set->getMetisPort();
|
||||
const int receivers = qMax(1, set->getNumberOfReceivers());
|
||||
const int receivers = protocol2ReceiverCount(set);
|
||||
|
||||
m_commandSocket = new QUdpSocket(this);
|
||||
if (!m_commandSocket->bind(localAddress, discoveryPort, QUdpSocket::DontShareAddress)) {
|
||||
@ -191,12 +203,13 @@ bool Protocol2DataPath::initSockets() {
|
||||
|
||||
void Protocol2DataPath::stop() {
|
||||
|
||||
const bool wasRunning = m_running;
|
||||
m_running = false;
|
||||
|
||||
if (m_heartbeatTimer)
|
||||
m_heartbeatTimer->stop();
|
||||
|
||||
if (m_commandSocket)
|
||||
if (wasRunning && m_commandSocket)
|
||||
sendHighPriorityPacket(false);
|
||||
|
||||
closeSockets();
|
||||
@ -212,6 +225,9 @@ void Protocol2DataPath::networkDeviceStartStop(char value) {
|
||||
return;
|
||||
|
||||
if (value == 0) {
|
||||
if (!m_running)
|
||||
return;
|
||||
|
||||
m_running = false;
|
||||
if (m_heartbeatTimer)
|
||||
m_heartbeatTimer->stop();
|
||||
@ -288,11 +304,13 @@ void Protocol2DataPath::sendHeartbeat() {
|
||||
void Protocol2DataPath::closeSockets() {
|
||||
|
||||
if (m_heartbeatTimer) {
|
||||
disconnect(m_heartbeatTimer, 0, this, 0);
|
||||
delete m_heartbeatTimer;
|
||||
m_heartbeatTimer = 0;
|
||||
}
|
||||
|
||||
foreach (QUdpSocket *socket, m_ddcSockets) {
|
||||
disconnect(socket, 0, this, 0);
|
||||
socket->close();
|
||||
delete socket;
|
||||
}
|
||||
@ -300,12 +318,14 @@ void Protocol2DataPath::closeSockets() {
|
||||
m_ddcSampleBuffers.clear();
|
||||
|
||||
if (m_statusSocket) {
|
||||
disconnect(m_statusSocket, 0, this, 0);
|
||||
m_statusSocket->close();
|
||||
delete m_statusSocket;
|
||||
m_statusSocket = 0;
|
||||
}
|
||||
|
||||
if (m_commandSocket) {
|
||||
disconnect(m_commandSocket, 0, this, 0);
|
||||
m_commandSocket->close();
|
||||
delete m_commandSocket;
|
||||
m_commandSocket = 0;
|
||||
@ -343,7 +363,21 @@ void Protocol2DataPath::sendGeneralPacket() {
|
||||
datagram[26] = 0x10;
|
||||
datagram[27] = 20;
|
||||
datagram[28] = 32;
|
||||
datagram[59] = set->getAlexPresence() ? 0x01 : 0x00;
|
||||
|
||||
const TNetworkDevicecard device = set->getCurrentMetisCard();
|
||||
if (device.phaseWords)
|
||||
datagram[37] = (char)((quint8)datagram.at(37) | 0x08);
|
||||
|
||||
if ((device.iqFormatFlags & 0x05) == 0x05)
|
||||
datagram[39] = 0x05;
|
||||
|
||||
if (device.boardID == 0)
|
||||
datagram[56] = qBound(0, protocol2ReceiverCount(set) - 1, 3);
|
||||
|
||||
if (device.hasAlex0)
|
||||
datagram[59] = (char)((quint8)datagram.at(59) | 0x01);
|
||||
if (device.hasAlex1)
|
||||
datagram[59] = (char)((quint8)datagram.at(59) | 0x02);
|
||||
|
||||
if (m_commandSocket->writeDatagram(datagram, set->getCurrentMetisCard().ip_address, DEVICE_PORT) >= 0)
|
||||
++m_generalSequence;
|
||||
@ -353,7 +387,8 @@ void Protocol2DataPath::sendGeneralPacket() {
|
||||
|
||||
void Protocol2DataPath::sendDdcSpecificPacket() {
|
||||
|
||||
const int receivers = qMax(1, set->getNumberOfReceivers());
|
||||
const TNetworkDevicecard device = set->getCurrentMetisCard();
|
||||
const int receivers = protocol2ReceiverCount(set);
|
||||
QByteArray datagram(17 + receivers * 6, 0x00);
|
||||
|
||||
datagram[0] = (m_ddcSequence >> 24) & 0xFF;
|
||||
@ -361,15 +396,22 @@ void Protocol2DataPath::sendDdcSpecificPacket() {
|
||||
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;
|
||||
const int adcCount = qMax(1, device.adcCount);
|
||||
datagram[4] = adcCount;
|
||||
|
||||
for (int adc = 0; adc < adcCount && adc < 8; ++adc) {
|
||||
if (io->ccTx.dither)
|
||||
datagram[5] = datagram.at(5) | (1 << adc);
|
||||
if (io->ccTx.random)
|
||||
datagram[6] = datagram.at(6) | (1 << adc);
|
||||
}
|
||||
|
||||
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 + 0] = (adcCount > 1) ? (rx % adcCount) : 0x00;
|
||||
datagram[offset + 1] = (io->samplerate >> 8) & 0xFF;
|
||||
datagram[offset + 2] = io->samplerate & 0xFF;
|
||||
datagram[offset + 3] = 0x00;
|
||||
@ -387,7 +429,7 @@ void Protocol2DataPath::sendHighPriorityPacket(bool run) {
|
||||
|
||||
QByteArray datagram(kProtocol2HighPriorityPacketSize, 0x00);
|
||||
const QList<long> frequencies = set->getCtrFrequencies();
|
||||
const int receivers = qMax(1, set->getNumberOfReceivers());
|
||||
const int receivers = protocol2ReceiverCount(set);
|
||||
const int currentReceiver = set->getCurrentReceiver();
|
||||
const int currentBand = (int)set->getCurrentHamBand(currentReceiver);
|
||||
const long currentVfoFrequency = set->getVfoFrequency(currentReceiver);
|
||||
@ -504,7 +546,13 @@ int Protocol2DataPath::samplesPerLegacyHalfFrame() const {
|
||||
}
|
||||
|
||||
quint32 Protocol2DataPath::encodeFrequency(long frequency) const {
|
||||
|
||||
const TNetworkDevicecard device = set->getCurrentMetisCard();
|
||||
if (!device.phaseWords)
|
||||
return (quint32)frequency;
|
||||
|
||||
const quint64 dspClock = (device.dspClockHz > 0) ? (quint64)device.dspClockHz : 122880000ULL;
|
||||
return (quint32)(((quint64)(quint32)frequency << 32) / dspClock);
|
||||
}
|
||||
|
||||
qint32 Protocol2DataPath::read24BitSample(const char *data) const {
|
||||
|
||||
140
Source/src/DataEngine/cusdr_protocol2_profile.cpp
Normal file
140
Source/src/DataEngine/cusdr_protocol2_profile.cpp
Normal file
@ -0,0 +1,140 @@
|
||||
/**
|
||||
* @file cusdr_protocol2_profile.cpp
|
||||
* @brief openHPSDR Protocol 2 board capability helpers
|
||||
*/
|
||||
|
||||
#include "cusdr_protocol2_profile.h"
|
||||
|
||||
namespace {
|
||||
|
||||
static Protocol2BoardProfile makeDefaultProfile(int boardId) {
|
||||
|
||||
Protocol2BoardProfile profile;
|
||||
profile.boardId = boardId;
|
||||
profile.boardName = "Protocol2 SDR";
|
||||
profile.adcCount = 1;
|
||||
profile.defaultDdcCount = 2;
|
||||
profile.dspClockHz = 122880000;
|
||||
profile.phaseWords = true;
|
||||
profile.hasAlex0 = true;
|
||||
profile.hasAlex1 = false;
|
||||
return profile;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Protocol2BoardProfile protocol2BoardProfile(int boardId) {
|
||||
|
||||
Protocol2BoardProfile profile = makeDefaultProfile(boardId);
|
||||
|
||||
switch (boardId) {
|
||||
|
||||
case 0:
|
||||
profile.boardName = "ATLAS";
|
||||
profile.adcCount = 4;
|
||||
profile.defaultDdcCount = 4;
|
||||
profile.dspClockHz = 122880000;
|
||||
profile.phaseWords = false;
|
||||
profile.hasAlex0 = true;
|
||||
profile.hasAlex1 = false;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
profile.boardName = "Hermes / ANAN-10/100";
|
||||
profile.adcCount = 1;
|
||||
profile.defaultDdcCount = 2;
|
||||
profile.dspClockHz = 122880000;
|
||||
profile.phaseWords = true;
|
||||
profile.hasAlex0 = true;
|
||||
profile.hasAlex1 = false;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
profile.boardName = "Hermes / ANAN-10E/100B";
|
||||
profile.adcCount = 1;
|
||||
profile.defaultDdcCount = 2;
|
||||
profile.dspClockHz = 122880000;
|
||||
profile.phaseWords = true;
|
||||
profile.hasAlex0 = false;
|
||||
profile.hasAlex1 = false;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
profile.boardName = "Angelia / ANAN-100D";
|
||||
profile.adcCount = 2;
|
||||
profile.defaultDdcCount = 4;
|
||||
profile.dspClockHz = 122880000;
|
||||
profile.phaseWords = true;
|
||||
profile.hasAlex0 = true;
|
||||
profile.hasAlex1 = false;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
profile.boardName = "Orion / ANAN-200D";
|
||||
profile.adcCount = 2;
|
||||
profile.defaultDdcCount = 4;
|
||||
profile.dspClockHz = 122880000;
|
||||
profile.phaseWords = true;
|
||||
profile.hasAlex0 = true;
|
||||
profile.hasAlex1 = false;
|
||||
break;
|
||||
|
||||
case 5:
|
||||
profile.boardName = "Orion MkII / ANAN-7/8000DLE";
|
||||
profile.adcCount = 2;
|
||||
profile.defaultDdcCount = 4;
|
||||
profile.dspClockHz = 122880000;
|
||||
profile.phaseWords = true;
|
||||
profile.hasAlex0 = true;
|
||||
profile.hasAlex1 = true;
|
||||
break;
|
||||
|
||||
case 6:
|
||||
profile.boardName = "Hermes Lite";
|
||||
profile.adcCount = 1;
|
||||
profile.defaultDdcCount = 2;
|
||||
profile.dspClockHz = 76800000;
|
||||
profile.phaseWords = true;
|
||||
profile.hasAlex0 = false;
|
||||
profile.hasAlex1 = false;
|
||||
break;
|
||||
|
||||
case 10:
|
||||
profile.boardName = "Saturn / ANAN-G2";
|
||||
profile.adcCount = 2;
|
||||
profile.defaultDdcCount = 4;
|
||||
profile.dspClockHz = 122880000;
|
||||
profile.phaseWords = true;
|
||||
profile.hasAlex0 = true;
|
||||
profile.hasAlex1 = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return profile;
|
||||
}
|
||||
|
||||
QString protocol2DeviceSummary(const TNetworkDevicecard &device) {
|
||||
|
||||
QString summary = device.boardName;
|
||||
|
||||
if (device.protocolVersion > 0)
|
||||
summary += QString(" P%1").arg(device.protocolVersion);
|
||||
|
||||
if (device.firmwareVersion > 0)
|
||||
summary += QString(" FW %1.%2").arg(device.firmwareVersion / 10).arg(device.firmwareVersion % 10);
|
||||
|
||||
if (device.adcCount > 0 || device.ddcCount > 0)
|
||||
summary += QString(" %1ADC/%2DDC").arg(device.adcCount).arg(device.ddcCount);
|
||||
|
||||
if (device.phaseWords)
|
||||
summary += " phase";
|
||||
|
||||
if (device.hasAlex0 || device.hasAlex1)
|
||||
summary += device.hasAlex1 ? " Alex0/1" : " Alex";
|
||||
|
||||
summary += QString(" (%1)").arg(device.ip_address.toString());
|
||||
return summary;
|
||||
}
|
||||
26
Source/src/DataEngine/cusdr_protocol2_profile.h
Normal file
26
Source/src/DataEngine/cusdr_protocol2_profile.h
Normal file
@ -0,0 +1,26 @@
|
||||
/**
|
||||
* @file cusdr_protocol2_profile.h
|
||||
* @brief openHPSDR Protocol 2 board capability helpers
|
||||
*/
|
||||
|
||||
#ifndef _CUSDR_PROTOCOL2_PROFILE_H
|
||||
#define _CUSDR_PROTOCOL2_PROFILE_H
|
||||
|
||||
#include "cusdr_settings.h"
|
||||
|
||||
struct Protocol2BoardProfile {
|
||||
|
||||
int boardId;
|
||||
const char* boardName;
|
||||
int adcCount;
|
||||
int defaultDdcCount;
|
||||
int dspClockHz;
|
||||
bool phaseWords;
|
||||
bool hasAlex0;
|
||||
bool hasAlex1;
|
||||
};
|
||||
|
||||
Protocol2BoardProfile protocol2BoardProfile(int boardId);
|
||||
QString protocol2DeviceSummary(const TNetworkDevicecard &device);
|
||||
|
||||
#endif // _CUSDR_PROTOCOL2_PROFILE_H
|
||||
@ -118,6 +118,7 @@ OGLDisplayPanel::OGLDisplayPanel(QWidget *parent)
|
||||
|
||||
setupConnections();
|
||||
setupTextstrings();
|
||||
setCurrentNetworkDevice(set->getCurrentMetisCard());
|
||||
|
||||
set10mhzSource(this, set->get10MHzSource());
|
||||
set122_88mhzSource(this, set->get122_8MHzSource());
|
||||
@ -281,6 +282,12 @@ void OGLDisplayPanel::setupConnections() {
|
||||
this,
|
||||
SLOT(setHermesVersion(int)));
|
||||
|
||||
CHECKED_CONNECT(
|
||||
set,
|
||||
SIGNAL(hpsdrNetworkDeviceChanged(TNetworkDevicecard)),
|
||||
this,
|
||||
SLOT(setCurrentNetworkDevice(TNetworkDevicecard)));
|
||||
|
||||
CHECKED_CONNECT(
|
||||
set,
|
||||
SIGNAL(alexPresenceChanged(bool)),
|
||||
@ -2745,6 +2752,20 @@ void OGLDisplayPanel::setMetisVersion(int value) {
|
||||
|
||||
}
|
||||
|
||||
void OGLDisplayPanel::setCurrentNetworkDevice(TNetworkDevicecard card) {
|
||||
|
||||
if (card.protocolVersion >= 2 && !card.boardName.isEmpty()) {
|
||||
m_hermesString = card.boardName + " ";
|
||||
m_hermesStringWidth = m_oglTextSmall->fontMetrics().width(m_hermesString);
|
||||
}
|
||||
else {
|
||||
m_hermesString = QString("Hermes ");
|
||||
m_hermesStringWidth = m_oglTextSmall->fontMetrics().width(m_hermesString);
|
||||
}
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
void OGLDisplayPanel::setExcaliburVersion(QObject *sender, int value) {
|
||||
|
||||
Q_UNUSED (sender)
|
||||
|
||||
@ -324,6 +324,7 @@ private slots:
|
||||
void setPenelopeVersion(int value);
|
||||
void setPennylaneVersion(int value);
|
||||
void setMetisVersion(int value);
|
||||
void setCurrentNetworkDevice(TNetworkDevicecard card);
|
||||
void setExcaliburVersion(QObject *sender, int value);
|
||||
void setAlexVersion(QObject *sender, int value);
|
||||
|
||||
|
||||
@ -36,6 +36,7 @@
|
||||
#include <QBoxLayout>
|
||||
|
||||
#include "cusdr_networkWidget.h"
|
||||
#include "DataEngine/cusdr_protocol2_profile.h"
|
||||
|
||||
|
||||
#define btn_height 15
|
||||
@ -502,7 +503,10 @@ void NetworkWidget::setNetworkDeviceList(QList<TNetworkDevicecard> list) {
|
||||
networkDeviceIPAdresses->clear();
|
||||
foreach (TNetworkDevicecard device, list) {
|
||||
|
||||
networkDeviceIPAdresses->addItem(device.ip_address.toString());
|
||||
if (device.protocolVersion >= 2)
|
||||
networkDeviceIPAdresses->addItem(protocol2DeviceSummary(device));
|
||||
else
|
||||
networkDeviceIPAdresses->addItem(QString("%1 (%2)").arg(device.boardName).arg(device.ip_address.toString()));
|
||||
networkDeviceIPAdresses->update();
|
||||
}
|
||||
}
|
||||
|
||||
@ -485,6 +485,13 @@ typedef struct _networkDeviceCard {
|
||||
QString boardName;
|
||||
int protocolVersion;
|
||||
int firmwareVersion;
|
||||
int adcCount;
|
||||
int ddcCount;
|
||||
int dspClockHz;
|
||||
int iqFormatFlags;
|
||||
bool phaseWords;
|
||||
bool hasAlex0;
|
||||
bool hasAlex1;
|
||||
|
||||
} TNetworkDevicecard;
|
||||
|
||||
|
||||
29
cudaSDR.log
Normal file
29
cudaSDR.log
Normal file
@ -0,0 +1,29 @@
|
||||
пн апр. 13 21:24:14 2026: ************************************************************************
|
||||
пн апр. 13 21:24:14 2026: Settings:: start at: пн апр. 13 21:24:14 2026
|
||||
пн апр. 13 21:24:14 2026: cudaSDR BETA
|
||||
пн апр. 13 21:24:15 2026: Settings:: Alex config: 4098
|
||||
пн апр. 13 21:24:15 2026: Settings:: reading done.
|
||||
пн апр. 13 21:24:15 2026: Init:: OpenGL found.
|
||||
пн апр. 13 21:24:15 2026: Init:: Framebuffer Objects found.
|
||||
пн апр. 13 21:24:15 2026: Init:: main window setup ...
|
||||
пн апр. 13 21:24:16 2026: MainWindow:: main window init done
|
||||
пн апр. 13 21:24:16 2026: MainWindow:: server ip from ini-file: "192.168.122.1"
|
||||
пн апр. 13 21:24:16 2026: MainWindow:: HPSDR device local ip from ini-file: "192.168.122.1"
|
||||
пн апр. 13 21:24:16 2026: MainWindow:: network interface "bridge0" :
|
||||
пн апр. 13 21:24:16 2026: MainWindow:: -> broadcast address: 172.16.2.255
|
||||
пн апр. 13 21:24:16 2026: MainWindow:: -> ip address: 172.16.2.99
|
||||
пн апр. 13 21:24:16 2026: MainWindow:: network interface "virbr0" :
|
||||
пн апр. 13 21:24:16 2026: MainWindow:: -> broadcast address: 192.168.122.255
|
||||
пн апр. 13 21:24:16 2026: MainWindow:: -> ip address: 192.168.122.1
|
||||
пн апр. 13 21:24:16 2026: MainWindow:: found 2 valid ip addresses.
|
||||
пн апр. 13 21:24:16 2026: MainWindow:: HPSDR network device interface set to: "virbr0"("192.168.122.1")
|
||||
пн апр. 13 21:24:16 2026: MainWindow:: HPSDR network device interface set to: "virbr0"("192.168.122.1")
|
||||
пн апр. 13 21:24:16 2026: MainWindow:: using ip address 192.168.122.1 for the server.
|
||||
пн апр. 13 21:24:16 2026: MainWindow:: using ip address 192.168.122.1 for connecting to a HPSDR device.
|
||||
пн апр. 13 21:24:16 2026: Init:: main window setup done.
|
||||
пн апр. 13 21:24:16 2026: Init:: current path: /home/vladimir/Документы/source/cudaSDR
|
||||
пн апр. 13 21:24:16 2026: Init:: fftw_wisdom does not exist - planning FFT...
|
||||
пн апр. 13 21:24:22 2026: planning FFT size 64 ...
|
||||
пн апр. 13 21:24:23 2026: planning FFT size 128 ...
|
||||
пн апр. 13 21:24:23 2026: planning FFT size 256 ...
|
||||
пн апр. 13 21:24:24 2026: planning FFT size 512 ...
|
||||
Loading…
Reference in New Issue
Block a user