From d70bcdf1ebb411d27b597f5d51b76ef977f9d2cd Mon Sep 17 00:00:00 2001 From: Stuart Longland Date: Mon, 9 Dec 2024 12:32:36 +1000 Subject: [PATCH 1/2] vis, modespec: Handle VIS codes that use odd parity There are a couple of exceptions to the even parity rule: - Robot 12 monochrome - Wraase SC-2 60 So use an 8th bit to encode that information in the table. This is in line with KB4YZ's VIS header reference. --- common.h | 2 ++ modespec.c | 35 +++++++++++++++++++++++------------ vis.c | 29 +++++++++++++++++++++-------- 3 files changed, 46 insertions(+), 20 deletions(-) diff --git a/common.h b/common.h index 471c170..3e0c7c5 100644 --- a/common.h +++ b/common.h @@ -15,6 +15,8 @@ extern guchar *StoredLum; extern pthread_t thread1; extern guchar VISmap[]; +#define VIS_PARITY_ODD (1 << 7) + typedef struct _FFTStuff FFTStuff; struct _FFTStuff { double *in; diff --git a/modespec.c b/modespec.c index ff9d7b4..8d73111 100644 --- a/modespec.c +++ b/modespec.c @@ -371,15 +371,26 @@ _ModeSpec ModeSpec[] = { * */ -// 0 1 2 3 4 5 6 7 8 9 A B C D E F - -guchar VISmap[] = { 0, 0, R8BW, 0, R24, 0, R12BW,0, R36, 0, R24BW,0, R72, 0, 0, 0, // 0 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1 - M4, 0, 0, 0, M3, 0, 0, 0, M2, 0, 0, 0, M1, 0, 0, 0, // 2 - 0, 0, 0, 0, 0, 0, 0, W2180,S2, 0, 0, 0, S1, 0, 0, W2120, // 3 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, SDX, 0, 0, 0, // 4 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, PD50,PD290,PD120, // 5 - PD180,PD240,PD160,PD90,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 6 - 0, P3, P5, P7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; // 7 - -// 0 1 2 3 4 5 6 7 8 9 A B C D E F +// 0 1 2 3 4 5 6 7 8 9 A B C D E F + +guchar VISmap[] = { + // Normal (even) parity + 0, 0, R8BW, 0, R24, 0, 0, 0, R36, 0, R24BW,0, R72, 0, 0, 0, // 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1 + M4, 0, 0, 0, M3, 0, 0, 0, M2, 0, 0, 0, M1, 0, 0, 0, // 2 + 0, 0, 0, 0, 0, 0, 0, W2180,S2, 0, 0, 0, S1, 0, 0, W2120, // 3 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, SDX, 0, 0, 0, // 4 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, PD50,PD290,PD120, // 5 + PD180,PD240,PD160,PD90,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 6 + 0, P3, P5, P7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 7 + // Inverted (odd) parity + 0, 0, 0, 0, 0, 0, R12BW,0, 0, 0, 0, 0, 0, 0, 0, 0, // 8 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // A + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // B + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // C + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // D + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // E + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; // F + +// 0 1 2 3 4 5 6 7 8 9 A B C D E F diff --git a/vis.c b/vis.c index 6f7eb26..0adf3bd 100644 --- a/vis.c +++ b/vis.c @@ -7,6 +7,14 @@ #include "common.h" +/* Handle selection of the VIS mode in the GUI */ +static void onGotVis(guchar VIS) { + gdk_threads_enter(); + gtk_combo_box_set_active (GTK_COMBO_BOX(gui.combo_mode), VISmap[VIS]-1); + gtk_spin_button_set_value (GTK_SPIN_BUTTON(gui.spin_shift), CurrentPic.HedrShift); + gdk_threads_leave(); +} + /* * * Detect VIS & frequency shift @@ -113,19 +121,24 @@ guchar GetVIS () { Parity = Bit[0] ^ Bit[1] ^ Bit[2] ^ Bit[3] ^ Bit[4] ^ Bit[5] ^ Bit[6]; - if (VISmap[VIS] == R12BW) Parity = !Parity; - if (Parity != ParityBit) { - printf(" Parity fail\n"); - gotvis = FALSE; + // Maybe this mode uses odd parity? + printf(" Parity inconclusive, trying odd parity\n"); + if (VISmap[VIS | VIS_PARITY_ODD] == UNKNOWN) { + // Nope! + printf(" Parity fail\n"); + gotvis = FALSE; + } else { + // Yep, that was it. Inverted parity. + VIS |= VIS_PARITY_ODD; + onGotVis(VIS); + break; + } } else if (VISmap[VIS] == UNKNOWN) { printf(" Unknown VIS\n"); gotvis = FALSE; } else { - gdk_threads_enter(); - gtk_combo_box_set_active (GTK_COMBO_BOX(gui.combo_mode), VISmap[VIS]-1); - gtk_spin_button_set_value (GTK_SPIN_BUTTON(gui.spin_shift), CurrentPic.HedrShift); - gdk_threads_leave(); + onGotVis(VIS); break; } } From 5b668cac2cb9caf24aa9f76531e3f87a43656912 Mon Sep 17 00:00:00 2001 From: Stuart Longland Date: Mon, 9 Dec 2024 12:34:35 +1000 Subject: [PATCH 2/2] modespec, slowrx UI: Add Wraase SC-2 60 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is reverse-engineered from QSSTV by first implementing an encoder for it that QSSTV's W260 decoder agreed with… *then* using the specifications determined to implement the decoder in `slowrx`. Aside from an occasional horizontal offset (which seems to be a common issue with all modes… might be related to "where" in the 1024-sample FFT frame the SSTV image is first seen), it seems to agree with QSSTV's decoding of the same reference audio sample. --- common.h | 12 ++++++------ modespec.c | 19 +++++++++++++++++-- slowrx.ui | 1 + 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/common.h b/common.h index 3e0c7c5..c7af27f 100644 --- a/common.h +++ b/common.h @@ -95,12 +95,12 @@ extern PicMeta CurrentPic; // SSTV modes enum { UNKNOWN=0, - M1, M2, M3, M4, - S1, S2, SDX, - R72, R36, R24, R24BW, R12BW, R8BW, - PD50, PD90, PD120, PD160, PD180, PD240, PD290, - P3, P5, P7, - W2120, W2180 + M1, M2, M3, M4, + S1, S2, SDX, + R72, R36, R24, R24BW, R12BW, R8BW, + PD50, PD90, PD120, PD160, PD180, PD240, PD290, + P3, P5, P7, + W260, W2120, W2180 }; // Color encodings diff --git a/modespec.c b/modespec.c index 8d73111..5ff0059 100644 --- a/modespec.c +++ b/modespec.c @@ -204,7 +204,22 @@ _ModeSpec ModeSpec[] = { .NumLines = 120, .LineHeight = 2, .ColorEnc = BW }, - + + [W260] = { + // Reverse-engineered by taking half the W2120 pixel time as an educated guess then + // tweaking the generated image timings until QSSTV decoded them without slant. -- VK4MSL + .Name = "Wraase SC-2 60", + .ShortName = "W260", + .SyncTime = 5.5225e-3, + .PorchTime = 0.0e-3, + .SeptrTime = 0.5e-3, + .PixelTime = 0.2425859375e-3, + .LineTime = 240.405e-3, + .ImgWidth = 320, + .NumLines = 256, + .LineHeight = 1, + .ColorEnc = RGB }, + [W2120] = { // KB4YZ, 1999 .Name = "Wraase SC-2 120", .ShortName = "W2120", @@ -387,7 +402,7 @@ guchar VISmap[] = { 0, 0, 0, 0, 0, 0, R12BW,0, 0, 0, 0, 0, 0, 0, 0, 0, // 8 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // A - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // B + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, W260, 0, 0, 0, 0, // B 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // C 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // D 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // E diff --git a/slowrx.ui b/slowrx.ui index 85e5d62..8125b7e 100644 --- a/slowrx.ui +++ b/slowrx.ui @@ -638,6 +638,7 @@ Pasokon P3 Pasokon P5 Pasokon P7 + Wraase SC-2 60 Wraase SC-2 120 Wraase SC-2 180