AlexandreRouma / SDRPlusPlus

Cross-Platform SDR Software
GNU General Public License v3.0
4.03k stars 556 forks source link

Hermes Lite 2 #1036

Closed frspin closed 8 months ago

frspin commented 1 year ago

Is hermes_source module usable with Hermes Lite 2? For now I am unable to discovery my HL2 with sdr++.

Regards Franco Spinelli IW2DHW

AlexandreRouma commented 1 year ago

It is usable, in fact it's the only hermes that the module is compatible with. On my network the hermes is always detected so some more details on your network might be needed.

AlexandreRouma commented 1 year ago

ignore the label, above, clicked at the wrong place

frspin commented 1 year ago

Il 07/04/23 14:17, AlexandreRouma ha scritto:

It is usable, in fact it's the only hermes that the module is compatible with. On my network the hermes is always detected so some more details on your network might be needed.

My HL2 is correctly discovered from Quisk, SparkSDR and linhpsdr. It is connected to a LAN with DHCP using a switch where is connected also my PC.

Now I am away from my PC but, if I know the correct configuration for HL2 in SDR++, I can try to configure it "by hand" bypassing discovery.

Regards

Franco Spinelli IW2DHW

AlexandreRouma commented 1 year ago

You can't really connect manually to a device atm, you'd need to modify the code.

One difference I see is I think my HL2 is setup with a static IP. I don't see exactly how this could be problematic though.

Something else to check: What operating system are you using? how many network interfaces do you have on your PC? etc

frspin commented 1 year ago

Il 11/04/23 01:25, AlexandreRouma ha scritto:

You can't really connect manually to a device atm, you'd need to modify the code.

One difference I see is I /think/ my HL2 is setup with a static IP. I don't see exactly how this could be problematic though.

Yes. I suppose there is a problem in discovery step.

Something else to check: What operating system are you using? how many network interfaces do you have on your PC? etc

I am using Ubuntu 22.04 up-to-date. My PC have only one network interface and HL2 get IP from my DHPC server where I have reserved an IP for HL2 in the range of DHCP addresses.

Regards

Franco Spinelli IW2DHW

qrp73 commented 1 year ago

hermes_source discovery is broken. It doesn't works on Raspberry Pi 4. There are several mistakes in the code which prevents Hermes device detection.

1) missing mandatory SO_BROADCAST option set for socket before bind call. Without this option it won't send broadcast message. It can be fixed by adding the following code in core/src/utils/net.cpp, method openudp(const Address& raddr, const Address& laddr):

// Create socket
        SockHandle_t s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);

        // set option SO_BROADCAST
        int broadcastEnable = 1;
        if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &broadcastEnable, sizeof(broadcastEnable)) == -1) {
            closeSocket(s);
            throw std::runtime_error("Could not set SO_BROADCAST option");
            return NULL;
        }
        // set option SO_REUSEADDR
        int reuseEnable = 1;
        if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &reuseEnable, sizeof(reuseEnable)) == -1) {
            closeSocket(s);
            throw std::runtime_error("Could not set SO_REUSEADDR option");
            return NULL;
        }
        // Bind socket to local port
        if (bind(s, (sockaddr*)&laddr.addr, sizeof(sockaddr_in))) {
            closeSocket(s);
            throw std::runtime_error("Could not bind socket");
            return NULL;
        }

2) there is mistake with timeout set in core/src/utils/net.cpp, method, method recv(uint8_t data, size_t maxLen, bool forceLen, int timeout, Address dest). This bug leads to unstable detection, if response has some delay it won't be detected at all. It can be fixed in the following way:

                tv.tv_sec = timeout / 1000;
                tv.tv_usec = (timeout-tv.tv_sec*1000) * 1000;

the same fix should be applied to method Listener::accept(Address* dest, int timeout).

3) There is needs to change code which sends discovery packet in the file source_modules/hermes_source/src/hermes.cpp method discover():

        discoveryPkt[2] = METIS_PKT_DISCOVER;

        net::Address baddr("255.255.255.255", 1024);
        for (int i = 0; i < HERMES_METIS_REPEAT; i++) {
            sock->send(discoveryPkt, sizeof(discoveryPkt), &baddr);
        }

#if 0
        // Get interface list
        auto ifaces = net::listInterfaces();

        // Send the packet 5 times to make sure it's received
        for (const auto& [name, iface] : ifaces) {
            net::Address baddr(iface.broadcast, 1024);
            for (int i = 0; i < HERMES_METIS_REPEAT; i++) {
                sock->send(discoveryPkt, sizeof(discoveryPkt), &baddr);
            }
        }
#endif

        std::vector<Info> devices;
        while (true) {

Applying these fixes leads to stable detection. Could you please apply it to the latest version?

There is also something wrong with stream receiving, it is periodically interrupted for some unknown reason, so the sound is periodically interrupted. It needs further investigation...

frspin commented 1 year ago

Il 02/09/23 19:32, qrp73 ha scritto:

hermes_source discovery is broken. It doesn't works on Raspberry Pi 4. There are several mistakes in the code which prevents Hermes device detection.

  1. missing mandatory SO_BROADCAST option set for socket before bind call. Without this option it won't send broadcast message. It can be fixed by adding the following code in core/src/utils/net.cpp, method openudp(const Address& raddr, const Address& laddr):

|// Create socket SockHandle_t s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); // set option SO_BROADCAST int broadcastEnable = 1; if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &broadcastEnable, sizeof(broadcastEnable)) == -1) { closeSocket(s); throw std::runtime_error("Could not set SO_BROADCAST option"); return NULL; } // set option SO_REUSEADDR int reuseEnable = 1; if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &reuseEnable, sizeof(reuseEnable)) == -1) { closeSocket(s); throw std::runtime_error("Could not set SO_REUSEADDR option"); return NULL; } // Bind socket to local port if (bind(s, (sockaddr*)&laddr.addr, sizeof(sockaddr_in))) { closeSocket(s); throw std::runtime_error("Could not bind socket"); return NULL; } |

  1. there is mistake with timeout set in core/src/utils/net.cpp, method, method recv(uint8_t data, size_t maxLen, bool forceLen, int timeout, Address dest). This bug leads to unstable detection, if response has some delay it won't be detected at all. It can be fixed in the following way:

|tv.tv_sec = timeout / 1000; tv.tv_usec = (timeout-tv.tv_sec1000) 1000; |

the same fix should be applied to method Listener::accept(Address* dest, int timeout).

  1. There is needs to change code which sends discovery packet in the file source_modules/hermes_source/src/hermes.cpp method discover():

|discoveryPkt[2] = METIS_PKT_DISCOVER; net::Address baddr("255.255.255.255", 1024); for (int i = 0; i < HERMES_METIS_REPEAT; i++) { sock->send(discoveryPkt, sizeof(discoveryPkt), &baddr); } #if 0 // Get interface list auto ifaces = net::listInterfaces(); // Send the packet 5 times to make sure it's received for (const auto& [name, iface] : ifaces) { net::Address baddr(iface.broadcast, 1024); for (int i = 0; i < HERMES_METIS_REPEAT; i++) { sock->send(discoveryPkt, sizeof(discoveryPkt), &baddr); } } #endif std::vector devices; while (true) { |

Applying these fixes leads to stable detection. Could you please apply it to the latest version?

Done and now my HL2 is detected and working

There is also something wrong with stream receiving, it is periodically interrupted for some unknown reason, so the sound is periodically interrupted. It needs further investigation...

I can confirm this. Please send other changes when ready to test mods for this problem.

Regards

Franco Spinelli IW2DHW

qrp73 commented 1 year ago

Probably stream jerks happens due to small buffers. I'm not sure exactly, because I rewrite almost all protocol code before get good result, so I decided to write separate hpsdr_source module. I'm working with non standard HPSDR speed, and I'm worried that Raspberry Pi 4 with SDR++ will be unable to handle 1 MHz bandwidth 24-bit stream. But actually it can and do it very well even with FM demodulator for 200 kHz bandwidth :)

To fix issue with low buffer size I'm using 8192 samples buffer and also I added set option SO_RCVBUF = 16 MB for core/src/utils/net.cpp method openudp(const Address& raddr, const Address& laddr):

        // set option SO_RCVBUF = 16 MB
        int receiveBufferSize = 16*1024*1024;
        if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &receiveBufferSize, sizeof(receiveBufferSize)) != 0) {
            closeSocket(s);
            throw std::runtime_error("Could not set SO_RCVBUF option");
            return NULL;
        }

        // Bind socket to local port
        if (bind(s, (sockaddr*)&laddr.addr, sizeof(sockaddr_in))) {

this option helps to reduce packet drops due to system lags, because default buffer is just 212992 bytes which is not enough for continuous HPSDR stream

frspin commented 1 year ago

Il 04/09/23 06:42, qrp73 ha scritto:

Probably stream jerks happens due to small buffers. I'm not sure exactly, because I was rewrite almost all protocol code before get good result, so I decided to write separate hpsdr_source module. I'm working with non standard HPSDR speed, and I'm worried that Raspberry Pi 4 with SDR++ will be unable to handle 1 MHz badwidth 24-bit stream. But actually it can and do it very well even with FM demodulator for 200 kHz bandwidth :)

To fix issue with low buffer size I'm using 8192 samples buffer and also I added set option SO_RCVBUF = 16 MB for core/src/utils/net.cpp method openudp(const Address& raddr, const Address& laddr):

|// set option SO_RCVBUF = 16 MB int receiveBufferSize = 1610241024; if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &receiveBufferSize, sizeof(receiveBufferSize)) != 0) { closeSocket(s); throw std::runtime_error("Could not set SO_RCVBUF option"); return NULL; } // Bind socket to local port if (bind(s, (sockaddr*)&laddr.addr, sizeof(sockaddr_in))) { |

this option helps to reduce packet drops due to system lags, because default buffer is just 212992 bytes which is not enough for continuous HPSDR stream

Applied your mods and now reception is good.

Regards

Franco Spinelli IW2DHW

AlexandreRouma commented 8 months ago

every issue mentioned here should be fixed, reopen if not.