Skip to content

Commit

Permalink
Merge pull request #9 from alexranaldi/0.88
Browse files Browse the repository at this point in the history
0.88
  • Loading branch information
alexranaldi authored Oct 17, 2023
2 parents 413e6cc + 6602c55 commit 81b6416
Show file tree
Hide file tree
Showing 20 changed files with 1,790 additions and 844 deletions.
13 changes: 13 additions & 0 deletions CHANGELOG.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
0.88
Enhancement: FT8 - support Fox/Hound messages. This will increase the number of FT8 spots significantly if you skim the DX frequencies when an expedition is going on!
Enhancement: JS8 - support for some JS8 message formats. Requires JS8Call to be installed.
Enhancement: Supports SOTAmat FT8 messages (Resolves https://github.com/alexranaldi/CWSL_DIGI/issues/6)
Fix: use hostname instead of IP Address when connecting to WSPRNet and PSK Reporter. This resolves the ongoing issue with 0.86 and earlier being unable to contact WSPRNet.
Fix: FST4 and FST4W decoding bugs that prevented successful decoding in many cases.
Fix: several bugs in callsign handling and bad callsign detection.
Fix: Improve PSK Reporter connection reliability.

0.87
Support for JS8 mode - experimental!
Fixes for FST4 and FST4W

0.86
Support for FST4 and FST4W modes
Change PSK Reporter handling to allow re-spotting with band changes
Expand Down
Binary file modified CWSL_DIGI.exe
Binary file not shown.
23 changes: 14 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Overview #

CWSL_DIGI uses the [CWSL](https://github.com/HrochL/CWSL) utility to decode WSJT-X digital modes including FT8, FT4, JT65, WSPR, and others, and sends spots to [PSK Reporter](https://www.pskreporter.info/pskmap.html), [Reverse Beacon Network](https://www.reversebeacon.net/), and [WSPRNet](https://www.wsprnet.org/drupal/wsprnet/map). CWSL_DIGI was developed by W2AXR, with testing and feedback from WZ7I, W3OA, 9V1RM, N4ZR and K9IMM.
CWSL_DIGI uses the [CWSL](https://github.com/HrochL/CWSL) utility to decode WSJT-X digital modes including FT8, FT4, JT65, WSPR, FST4, FST4W, and JS8 and sends spots to [PSK Reporter](https://www.pskreporter.info/pskmap.html), [Reverse Beacon Network](https://www.reversebeacon.net/), and [WSPRNet](https://www.wsprnet.org/drupal/wsprnet/map). CWSL_DIGI was developed by W2AXR, with testing and feedback from WZ7I, W3OA, 9V1RM, N4ZR, K9IMM and MM3NDH.

With CWSL_DIGI, [CW Skimmer Server](http://www.dxatlas.com/SkimServer/), and an appropriate SDR (such as a [Red Pitaya](https://redpitaya.com/red-pitaya-for-radio-amateurs-sdr/) or [QS1R](https://www.ab9il.net/software-defined-radio/sdr2.html)), is possible to decode CW and multiple digital modes across multiple bands, all simultaneously.

Expand All @@ -11,20 +11,25 @@ CWSL_DIGI is released under the GNU GENERAL PUBLIC LICENSE, Version 3.

# Latest Release #

The latest version is 0.86 - [Download Windows 64-bit zip](https://github.com/alexranaldi/CWSL_DIGI/archive/refs/tags/0.86.zip)

Notable enhancements in 0.86 include
1. Support for FST4 and FST4W modes
2. Change PSK Reporter handling, re-spotting within 120s with band changes
The latest version is 0.88 - [Download Windows 64-bit zip](https://github.com/alexranaldi/CWSL_DIGI/archive/refs/tags/0.88.zip)

Notable changes in 0.88 include:
Enhancement: FT8 - support Fox/Hound messages. This will increase the number of FT8 spots significantly if you skim the DX frequencies when an expedition is going on!
Enhancement: JS8 - support for some JS8 message formats. Requires JS8Call to be installed.
Enhancement: Supports SOTAmat FT8 messages (Resolves https://github.com/alexranaldi/CWSL_DIGI/issues/6)
Fix: use hostname instead of IP Address when connecting to WSPRNet and PSK Reporter. This resolves the ongoing issue with 0.86 and earlier being unable to contact WSPRNet.
Fix: FST4 and FST4W decoding bugs that prevented successful decoding in many cases.
Fix: several bugs in callsign handling and bad callsign detection.
Fix: Improve PSK Reporter connection reliability.
## Installation ##

1. Install and configure [CW Skimmer Server](http://www.dxatlas.com/SkimServer/). The detailed steps can be found on the CW Skimmer Server website.
2. Install [CWSL](https://github.com/HrochL/CWSL). Configure it with CW Skimmer Server. The detailed steps can be found on the CWSL page.
3. Install the latest [Microsoft Visual Studio 2022 redistributable](https://aka.ms/vs/17/release/vc_redist.x64.exe). This may not be required if your computer is up to date.
4. Download the latest release of CWSL_DIGI. See download link above. Unzip into a folder of your choice. e.g., C:\CWSL_DIGI
5. Configure CWSL_DIGI by editing the config.ini file. This step is required. See the detailed Configuration section below.
6. Start CWSL_DIGI by running CWSL_DIGI.exe.
4. Install the [Intel Fortran redistributable](https://drive.google.com/drive/folders/1pk99ruANXTd_87oLce2L32H2V-P6dAFn?usp=drive_link). This may not be required if your computer is up to date.
5. Download the latest release of CWSL_DIGI. See download link above. Unzip into a folder of your choice. e.g., C:\CWSL_DIGI
6. Configure CWSL_DIGI by editing the config.ini file. This step is required. See the detailed Configuration section below.
7. Start CWSL_DIGI by running CWSL_DIGI.exe.

## Configuration ##

Expand Down
21 changes: 19 additions & 2 deletions config.ini
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# For use with CWSL_DIGI v0.86
# For use with CWSL_DIGI v0.88

### INSTRUCTIONS
# Lines beginning with a # are a comment and are ignored by CWSL_DIGI.
Expand Down Expand Up @@ -28,7 +28,7 @@ gridsquare=AB01xy
[decoders]
# The set of decoders. Each line is one decoder of at least "frequency mode"
# frequency is in Hz
# mode is FT4, FT8, WSPR, Q65-30, or JT65
# mode is FT4, FT8, WSPR, Q65-30, JT65 or JS8
# frequency, mode
# e.g., 14074000 FT8
# frequency, mode, sharedmem
Expand All @@ -53,6 +53,7 @@ gridsquare=AB01xy
#decoder=28180000 FT4
#decoder=28074000 FT8
#decoder=28076000 JT65
#decoder=28078000 JS8

# 12m
#decoder=24919000 FT4
Expand All @@ -64,6 +65,7 @@ gridsquare=AB01xy
#decoder=21094600 WSPR
#decoder=21074000 FT8
#decoder=21076000 JT65
#decoder=21078000 JS8

# 17m
#decoder=18104600 WSPR
Expand All @@ -77,19 +79,22 @@ gridsquare=AB01xy
#decoder=14080000 FT4
#decoder=14074000 FT8
#decoder=14076000 JT65
#decoder=14078000 JS8

# 30m
#decoder=10140000 FT4
#decoder=10138700 WSPR
#decoder=10136000 FT8
#decoder=10131000 FT8
#decoder=10138000 JT65
#decoder=10130000 JS8

# 40m
#decoder=7074000 FT8
#decoder=7047500 FT4
#decoder=7038600 WSPR
#decoder=7076000 JT65
#decoder=7078000 JS8

# 60m
#decoder=5357000 FT8
Expand All @@ -101,6 +106,7 @@ gridsquare=AB01xy
#decoder=3573000 FT8
#decoder=3568600 WSPR
#decoder=3570000 JT65
#decoder=3578000 JS8

# 80m Korea
#decoder=3547000 FT8
Expand All @@ -110,6 +116,9 @@ gridsquare=AB01xy
#decoder=1840000 FT4
#decoder=1838000 JT65
#decoder=1836600 WSPR
#decoder=1836800 FST4W-120
#decoder=1839000 FST4-60
#decoder=1839000 FST4-120

# 160m Korea
#decoder=1810000 FT8
Expand Down Expand Up @@ -151,6 +160,7 @@ binpath=C:\WSJT\wsjtx\bin
# the lifespan of solid state drives.
# WSPR decoders always use wave files regardless of this setting, as the
# WSJT-X WSPR decoder does not provide a shared memory interface.
# JS8 decoders always use wave files.
#transfermethod=shmem

# Highest decode frequency per decoder in Hz
Expand Down Expand Up @@ -212,6 +222,13 @@ binpath=C:\WSJT\wsjtx\bin
#wsprcycles=3000


[js8call]

# To use JS8 decoders, the program JS8CALL must be installed and this option must
# be set to the location of js8.exe
#binpath=C:\Program Files (x86)\js8call\bin


[reporting]
# This section contains settings for controlling reporting to spotting networks
# including PSK Reporter, Reverse Beacon Network (RBN) and WSPRNet.
Expand Down
49 changes: 37 additions & 12 deletions source/CWSL_DIGI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ along with CWSL_DIGI.If not, see < https://www.gnu.org/licenses/>.

// This work is based on: https://github.com/HrochL/CWSL

#include <windows.h>

// stdio and conio used for _kbhit() and _getch()
#include <stdio.h>
Expand All @@ -41,20 +40,17 @@ along with CWSL_DIGI.If not, see < https://www.gnu.org/licenses/>.
#include <limits>
#include <memory>

#include "mmreg.h"

#include <algorithm>
#include <cctype>
#include <locale>
#include <unordered_map>

# pragma comment(lib, "Ws2_32.lib")

#include "SharedMemory.h"

std::atomic_bool syncThreadTerminateFlag = false;

#include "CWSL_DIGI.hpp"
#include "mmreg.h"

#include "OutputHandler.hpp"
#include "Instance.hpp"
Expand All @@ -71,6 +67,8 @@ std::atomic_bool syncThreadTerminateFlag = false;
#include "ScreenPrinter.hpp"
#include "Decoder.hpp"

#include "SharedMemory.h"

std::string badMessageLogFile = "";

std::string decodesFileName;
Expand Down Expand Up @@ -524,7 +522,9 @@ void reportStats(std::shared_ptr<Stats> statsHandler, std::shared_ptr<ScreenPrin
// Main function
int main(int argc, char **argv)
{
std::cout << PROGRAM_NAME + " " + PROGRAM_VERSION << " by W2AXR" << std::endl;
std::string compilationDate = __DATE__;
std::string compilationTime = __TIME__;
std::cout << PROGRAM_NAME + " " + PROGRAM_VERSION << " by W2AXR, compiled " << compilationDate << " " << compilationTime << std::endl;
std::cout << "License: GNU GENERAL PUBLIC LICENSE, Version 3" << std::endl;
std::cout << "Please run " + PROGRAM_NAME + " --help for syntax" << std::endl;
std::cout << "Press CONTROL + C to terminate" << std::endl;
Expand Down Expand Up @@ -563,6 +563,7 @@ int main(int argc, char **argv)
("wsjtx.maxdataage", po::value<int>(), "Max data age to decode, in seconds, default 300")
("wsjtx.wsprcycles", po::value<int>(), "WSPR decoder cycles per bit. default 3000")
("wsjtx.transfermethod", po::value<std::string>(), "either wavfile or shmem, default shmem")
("js8call.binpath", po::value<std::string>(), "JS8Call bin folder path - required for JS8 Mode")
("logging.statsreportinginterval", po::value<int>(), "how often to report decoder statistics in seconds, default 300")
("logging.decodesfile", po::value<std::string>(), "file name for decode text log")
("logging.logreports", po::value<bool>(), "log each handled report, default true")
Expand Down Expand Up @@ -666,12 +667,16 @@ int main(int argc, char **argv)

// Parse radio settings
bool bUseExtioDLL = false;

// Future functionality...?
/*
std::string extioPath;
if (vm.count("radio.extiodll")) {
extioPath = vm["radio.extiodll"].as<std::string>();
printer->print("ExtIO DLL path: " + extioPath);
bUseExtioDLL = true;
}
*/

int SMNumber = -1;
if (vm.count("radio.sharedmem")) {
Expand Down Expand Up @@ -708,6 +713,7 @@ int main(int argc, char **argv)

int numFT4Decoders = 0;
int numFT8Decoders = 0;
int numJS8Decoders = 0;
int numWSPRDecoders = 0;
int numQ65_30Decoders = 0;
int numJT65Decoders = 0;
Expand Down Expand Up @@ -741,6 +747,9 @@ int main(int argc, char **argv)
else if (mode == "FT8") {
numFT8Decoders++;
}
else if (mode == "JS8") {
numJS8Decoders++;
}
else if (mode == "WSPR") {
numWSPRDecoders++;
}
Expand Down Expand Up @@ -794,13 +803,16 @@ int main(int argc, char **argv)
}
int smnum = SMNumber;
if (bUseExtioDLL) {
// Future functionality...?
/*
printer->info("Loading Extio DLL library: " + extioPath);
HMODULE extioModH = LoadLibraryA(extioPath.c_str());
if (!extioModH) {
printer->err("Error loading Extio DLL");
return EXIT_FAILURE;
}
printer->info("Loaded Extio DLL library");
*/
}
else {
if (decoderVecLine.size() >= 3) {
Expand Down Expand Up @@ -846,7 +858,7 @@ int main(int argc, char **argv)
decoderburden = vm["wsjtx.decoderburden"].as<float>();
printer->print("Decoder Burden specified as: " + std::to_string(decoderburden));
}
const float nd1 = static_cast<float>(numFT4Decoders + numFT8Decoders + numQ65_30Decoders) * (1.0f/5.0f); // 1 per 5 ft4/ft8/Q65
const float nd1 = static_cast<float>(numFT4Decoders + numFT8Decoders + numQ65_30Decoders + numJS8Decoders) * (1.0f/5.0f); // 1 per 5 ft4/ft8/Q65/JS8
const float nd2 = static_cast<float>(numWSPRDecoders) * (1.0f/3.0f); // 1 per 3 wspr
const float nd3 = static_cast<float>(numJT65Decoders) * (1.0f / 3.0f); // 1 per 3 JT-65
const float nd4 = static_cast<float>(numFST4WDecoders) * (1.0f / 3.0f); // 1 per 3 FST4W
Expand Down Expand Up @@ -895,16 +907,30 @@ int main(int argc, char **argv)
}
printer->print("Using path for wav files: " + wavPath);

std::string binPath = "";
std::string binPathX = "";
if (vm.count("wsjtx.binpath")) {
binPath = vm["wsjtx.binpath"].as<std::string>();
binPathX = vm["wsjtx.binpath"].as<std::string>();
}
else {
printer->err("Missing wsjtx.binpath input argument!");
cleanup();
return EXIT_FAILURE;
}

std::string binPathJS = "";
if (vm.count("js8call.binpath")) {
binPathJS = vm["js8call.binpath"].as<std::string>();
}
else {
printer->debug("js8call.binpath input argument not specified");
if (numJS8Decoders) {
printer->err("Missing js8call.binpath input argument!");
cleanup();
return EXIT_FAILURE;
}
}


bool keepWavFiles = false;
if (vm.count("wsjtx.keepwav")) {
keepWavFiles = vm["wsjtx.keepwav"].as<bool>();
Expand Down Expand Up @@ -1008,7 +1034,6 @@ int main(int argc, char **argv)

// Parse reporting options


reporter = nullptr;
if (vm.count("reporting.pskreporter")) {
usePSKReporter = vm["reporting.pskreporter"].as<bool>();
Expand Down Expand Up @@ -1053,7 +1078,7 @@ int main(int argc, char **argv)
}
}

decoderPool = std::make_shared<DecoderPool>(transferMethod, keepWavFiles, printJT9Output, numJT9Instances, maxWSPRDInstances, numjt9threads, decodedepth, wsprCycles, highestDecodeFreq, binPath, maxDataAge, wavPath, printer, outputHandler);
decoderPool = std::make_shared<DecoderPool>(transferMethod, keepWavFiles, printJT9Output, numJT9Instances, maxWSPRDInstances, numjt9threads, decodedepth, wsprCycles, highestDecodeFreq, binPathX, binPathJS, maxDataAge, wavPath, printer, outputHandler);
const bool decStat = decoderPool->init();
if (!decStat) {
cleanup();
Expand Down Expand Up @@ -1107,7 +1132,7 @@ int main(int argc, char **argv)
// create time signalling threads

std::thread ft8SignalThread;
if (numFT8Decoders) {
if (numFT8Decoders || numJS8Decoders) {
ft8SignalThread = std::thread(&waitForTimeFT8, printer, std::ref(preds.ft8Preds));
ft8SignalThread.detach();
}
Expand Down
39 changes: 36 additions & 3 deletions source/CWSL_DIGI.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,24 @@ along with CWSL_DIGI. If not, see < https://www.gnu.org/licenses/>.
#include <condition_variable>
#include <atomic>
#include <memory>
#include <fstream>

#include "CWSL_DIGI_Types.hpp"
#include "ScreenPrinter.hpp"

#include <winsock2.h>
#include <ws2tcpip.h>
#include "windows.h"
# pragma comment(lib, "ws2_32")

static const std::string PROGRAM_NAME = "CWSL_DIGI";
static const std::string PROGRAM_VERSION = "0.86";
static const std::string PROGRAM_VERSION = "0.88";

constexpr float Q65_30_PERIOD = 30.0f;
constexpr float FT8_PERIOD = 15.0f;
constexpr float FT4_PERIOD = 7.5f;
constexpr float WSPR_PERIOD = 120.0f;
constexpr float JT65_PERIOD = 60.0f;
constexpr float JS8_PERIOD = 15.0f;

constexpr size_t Wave_SR = 12000;
constexpr size_t SSB_BW = 6000;
Expand All @@ -59,6 +65,9 @@ static inline float getRXPeriod(const std::string& mode) {
if (mode == "FT8") {
return FT8_PERIOD;
}
else if (mode == "JS8") {
return JS8_PERIOD;
}
else if (mode == "FT4") {
return FT4_PERIOD;
}
Expand Down Expand Up @@ -145,4 +154,28 @@ static inline bool isModeFST4(const std::string& in) {

static inline bool isModeFST4W(const std::string& in) {
return in.compare(0, 6, "FST4W-") == 0;
}
}

// chatgpt generated code, for the win
static inline std::string GetSocketError() {
int error = WSAGetLastError();
if (error == 0) {
return "No error";
}

LPVOID errorMsg = NULL;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
error,
0,
(LPSTR)&errorMsg,
0,
NULL
);

std::string ret(static_cast<char*>(errorMsg));
LocalFree(errorMsg);

return ret;
}
Loading

0 comments on commit 81b6416

Please sign in to comment.