diff --git a/lib/qra/qra65/main.c b/lib/qra/qra65/main.c
index af68c791b..901749f03 100644
--- a/lib/qra/qra65/main.c
+++ b/lib/qra/qra65/main.c
@@ -1,58 +1,62 @@
-// main.c
-// QRA65 mode encode/decode test
-//
-// (c) 2016 - Nico Palermo, IV3NWV
-//
-// Thanks to Andrea Montefusco IW0HDV for his help on adapting the sources
-// to OSs other than MS Windows
-//
-// ------------------------------------------------------------------------------
-// This file is part of the qracodes project, a Forward Error Control
-// encoding/decoding package based on Q-ary RA (Repeat and Accumulate) LDPC codes.
-//
-// Files in this package:
-// main.c - this file
-// qra65.c/.h - qra65 mode encode/decoding functions
-//
-// ../qracodes/normrnd.{c,h} - random gaussian number generator
-// ../qracodes/npfwht.{c,h} - Fast Walsh-Hadamard Transforms
-// ../qracodes/pdmath.{c,h} - Elementary math on probability distributions
-// ../qracodes/qra12_63_64_irr_b.{c,h} - Tables for a QRA(12,63) irregular RA code over GF(64)
-// ../qracodes/qra13_64_64_irr_e.{c,h} - Tables for a QRA(13,64) irregular RA code " "
-// ../qracodes/qracodes.{c,h} - QRA codes encoding/decoding functions
-//
-// -------------------------------------------------------------------------------
-//
-// qracodes is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-// qracodes is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
+/*
+main.c
+QRA65 mode encode/decode test
-// You should have received a copy of the GNU General Public License
-// along with qracodes source distribution.
-// If not, see .
+(c) 2016 - Nico Palermo, IV3NWV
-// -----------------------------------------------------------------------------
+Thanks to Andrea Montefusco IW0HDV for his help on adapting the sources
+to OSs other than MS Windows
-// The code used by the QRA65 mode is the code:
-// QRA13_64_64_IRR_E: K=13 N=64 Q=64 irregular QRA code (defined in qra13_64_64_irr_e.{h,c})
-// This code has been designed to include a CRC as the 13th information symbol
-// and improve the code UER (Undetected Error Rate).
-// The CRC symbol is not sent along the channel (the codes are punctured) and the
-// resulting code is still a (12,63) code with an effective code rate of R = 12/63.
+------------------------------------------------------------------------------
+This file is part of the qracodes project, a Forward Error Control
+encoding/decoding package based on Q-ary RA (Repeat and Accumulate) LDPC codes.
-// ------------------------------------------------------------------------------
+Files in this package:
+ main.c - this file
+ qra65.c/.h - qra65 mode encode/decoding functions
-// OS dependent defines and includes --------------------------------------------
+ ../qracodes/normrnd.{c,h} - random gaussian number generator
+ ../qracodes/npfwht.{c,h} - Fast Walsh-Hadamard Transforms
+ ../qracodes/pdmath.{c,h} - Elementary math on probability distributions
+ ../qracodes/qra12_63_64_irr_b.{c,h} - Tables for a QRA(12,63) irregular RA
+ code over GF(64)
+ ../qracodes/qra13_64_64_irr_e.{c,h} - Tables for a QRA(13,64) irregular RA
+ code over GF(64)
+ ../qracodes/qracodes.{c,h} - QRA codes encoding/decoding functions
+
+-------------------------------------------------------------------------------
+
+ qracodes is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+ qracodes is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with qracodes source distribution.
+ If not, see .
+
+-----------------------------------------------------------------------------
+
+The code used by the QRA65 mode is the code: QRA13_64_64_IRR_E: K=13
+N=64 Q=64 irregular QRA code (defined in qra13_64_64_irr_e.{h,c}).
+
+This code has been designed to include a CRC as the 13th information
+symbol and improve the code UER (Undetected Error Rate). The CRC
+symbol is not sent along the channel (the codes are punctured) and the
+resulting code is still a (12,63) code with an effective code rate of
+R = 12/63.
+*/
+
+// OS dependent defines and includes ------------------------------------------
#if _WIN32 // note the underscore: without it, it's not msdn official!
- // Windows (x64 and x86)
- #include // required only for GetTickCount(...)
- #include // _beginthread
+// Windows (x64 and x86)
+#include // required only for GetTickCount(...)
+#include // _beginthread
#endif
#if __linux__
@@ -79,7 +83,7 @@ unsigned GetTickCount(void) {
#include "qra65.h"
#include "../qracodes/normrnd.h" // gaussian numbers generator
-// -----------------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
// channel types
#define CHANNEL_AWGN 0
@@ -87,19 +91,19 @@ unsigned GetTickCount(void) {
void printwordd(char *msg, int *x, int size)
{
- int k;
- printf("\n%s ",msg);
- for (k=0;k=0) { // decoded
+ printf("K1JT rx: received with apcode=%d %s\n",rc, decode_type[rc]);
+
+// Step 2a: K1JT replies to IV3NWV (with no grid)
+ printf("K1JT tx: IV3NWV K1JT\n");
+ encodemsg_jt65(x,CALL_IV3NWV,CALL_K1JT, GRID_BLANK);
+ qra65_encode(codec_k1jt, y, x);
+ rx = mfskchannel(y,channel_type,EbNodB);
+
+// Step 2b: IV3NWV attempts to decode [? ? ?], [IV3NWV ? ?] or [IV3NWV ?]
+ rc = qra65_decode(codec_iv3nwv, xdec,rx);
+ if (rc>=0) { // decoded
+ printf("IV3NWV rx: received with apcode=%d %s\n",rc, decode_type[rc]);
+
+// Step 3a: IV3NWV replies to K1JT with a 73
+ printf("IV3NWV tx: K1JT IV3NWV 73\n");
+ encodemsg_jt65(x,CALL_K1JT,CALL_IV3NWV, GRID_73);
+ qra65_encode(codec_iv3nwv, y, x);
+ rx = mfskchannel(y,channel_type,EbNodB);
+
+// Step 3b: K1JT attempts to decode [? ? ?] or [K1JT IV3NWV ?]
+ rc = qra65_decode(codec_k1jt, xdec,rx);
+ if (rc>=0) { // decoded
+ printf("K1JT rx: received with apcode=%d %s\n",rc, decode_type[rc]);
+
+// Step 4a: K1JT replies to IV3NWV with a 73
+ printf("K1JT tx: IV3NWV K1JT 73\n");
+ encodemsg_jt65(x,CALL_IV3NWV,CALL_K1JT, GRID_73);
+ qra65_encode(codec_k1jt, y, x);
rx = mfskchannel(y,channel_type,EbNodB);
- // K1JT attempts to decode
- rc = qra65_decode(codec_k1jt, xdec,rx);
+// Step 4b: IV3NWV attempts to decode [? ? ?], [IV3NWV ? ?], or [IV3NWV ?]
+ rc = qra65_decode(codec_iv3nwv, xdec,rx);
if (rc>=0) { // decoded
- printf("K1JT rx: received with apcode=%d %s\n",rc, decode_type[rc]);
- // K1JT replies to IV3NWV (with no grid)
- printf("K1JT tx: IV3NWV K1JT\n");
- encodemsg_jt65(x,CALL_IV3NWV,CALL_K1JT, GRID_BLANK);
- qra65_encode(codec_k1jt, y, x);
- rx = mfskchannel(y,channel_type,EbNodB);
-
- // IV3NWV attempts to decode
- rc = qra65_decode(codec_iv3nwv, xdec,rx);
- if (rc>=0) { // decoded
- printf("IV3NWV rx: received with apcode=%d %s\n",rc, decode_type[rc]);
- // IV3NWV replies to K1JT with a 73
- printf("IV3NWV tx: K1JT IV3NWV 73\n");
- encodemsg_jt65(x,CALL_K1JT,CALL_IV3NWV, GRID_73);
- qra65_encode(codec_iv3nwv, y, x);
- rx = mfskchannel(y,channel_type,EbNodB);
-
- // K1JT attempts to decode
- rc = qra65_decode(codec_k1jt, xdec,rx);
- if (rc>=0) { // decoded
- printf("K1JT rx: received with apcode=%d %s\n",rc, decode_type[rc]);
- // K1JT replies to IV3NWV with a 73
- printf("K1JT tx: IV3NWV K1JT 73\n");
- encodemsg_jt65(x,CALL_IV3NWV,CALL_K1JT, GRID_73);
- qra65_encode(codec_k1jt, y, x);
- rx = mfskchannel(y,channel_type,EbNodB);
-
- // IV3NWV attempts to decode
- rc = qra65_decode(codec_iv3nwv, xdec,rx);
- if (rc>=0) { // decoded
- printf("IV3NWV rx: received with apcode=%d %s\n",rc, decode_type[rc]);
- return 0;
- }
- }
- }
- }
- printf("the other party did not decode\n");
- return -1;
+ printf("IV3NWV rx: received with apcode=%d %s\n",rc, decode_type[rc]);
+ return 0;
+ }
+ }
+ }
+ }
+ printf("the other party did not decode\n");
+ return -1;
}
int test_proc_2(int channel_type, float EbNodB, int mode)
{
+/*
+Here we simulate the decoder of K1JT after K1JT has sent a msg [IV3NWV K1JT]
+and IV3NWV sends him the msg [K1JT IV3NWV JN66].
- // Here we simulate the decoder of K1JT after K1JT has sent a msg [IV3NWV K1JT]
- // and IV3NWV sends him the msg [K1JT IV3NWV JN66]
- // If mode=QRA_NOAP, K1JT decoder attempts to decode only msgs of type [? ? ?].
- // If mode=QRA_AUTOP, K1JT decoder will attempt to decode also the msgs [K1JT IV3NWV] and
- // [K1JT IV3NWV ?].
+If mode=QRA_NOAP, K1JT decoder attempts to decode only msgs of type [? ? ?].
- // In the case a decode is successful the return code of the qra65_decode function
- // indicates the amount of a-priori information required to decode the received message
- // accordingly to this table:
- // rc=0 [? ? ?] AP0
- // rc=1 [CQ ? ?] AP27
- // rc=2 [CQ ? ] AP44
- // rc=3 [CALL ? ?] AP29
- // rc=4 [CALL ? ] AP45
- // rc=5 [CALL CALL ?] AP57
- // The return code is <0 when decoding is unsuccessful
+If mode=QRA_AUTOP, K1JT decoder will attempt to decode also the msgs
+[K1JT IV3NWV] and [K1JT IV3NWV ?].
- // This test simulates the situation ntx times and reports how many times
- // a particular type decode among the above 6 cases succeded.
+In the case a decode is successful the return code of the qra65_decode function
+indicates the amount of a-priori information required to decode the received
+message according to this table:
- int x[QRA65_K], xdec[QRA65_K];
- int y[QRA65_N];
- float *rx;
- int rc,k;
+ rc=0 [? ? ?] AP0
+ rc=1 [CQ ? ?] AP27
+ rc=2 [CQ ? ] AP42
+ rc=3 [CALL ? ?] AP29
+ rc=4 [CALL ? ] AP44
+ rc=5 [CALL CALL ?] AP57
- int ndecok[6] = { 0, 0, 0, 0, 0, 0};
- int ntx = 100,ndec=0;
+The return code is <0 when decoding is unsuccessful
- qra65codec *codec_iv3nwv = qra65_init(mode,CALL_IV3NWV); // codec for IV3NWV
- qra65codec *codec_k1jt = qra65_init(mode,CALL_K1JT); // codec for K1JT
+This test simulates the situation ntx times and reports how many times
+a particular type decode among the above 6 cases succeded.
+*/
- // this will enable k1jt's decoder to look for iv3nwv calls
- encodemsg_jt65(x,CALL_IV3NWV,CALL_K1JT,GRID_BLANK);
- qra65_encode(codec_k1jt, y, x);
- printf("K1JT tx: IV3NWV K1JT\n");
+ int x[QRA65_K], xdec[QRA65_K];
+ int y[QRA65_N];
+ float *rx;
+ int rc,k;
- // iv3nwv reply to k1jt
- printf("IV3NWV tx: K1JT IV3NWV JN66\n");
- encodemsg_jt65(x,CALL_K1JT,CALL_IV3NWV,GRID_JN66);
- qra65_encode(codec_iv3nwv, y, x);
+ int ndecok[6] = { 0, 0, 0, 0, 0, 0};
+ int ntx = 100,ndec=0;
- printf("Simulating decodes by K1JT up to AP56 ...");
+ qra65codec *codec_iv3nwv = qra65_init(mode,CALL_IV3NWV); // codec for IV3NWV
+ qra65codec *codec_k1jt = qra65_init(mode,CALL_K1JT); // codec for K1JT
- for (k=0;k=0)
- ndecok[rc]++;
- }
- printf("\n");
+// This will enable K1JT's decoder to look for IV3NWV calls
+ encodemsg_jt65(x,CALL_IV3NWV,CALL_K1JT,GRID_BLANK);
+ qra65_encode(codec_k1jt, y, x);
+ printf("K1JT tx: IV3NWV K1JT\n");
- printf("Transimtted:%d - Decoded:\n",ntx);
- for (k=0;k<6;k++) {
- printf("%3d with %s\n",ndecok[k],decode_type[k]);
- ndec += ndecok[k];
- }
- printf("Total: %d/%d\n",ndec,ntx);
- printf("\n");
+ // IV3NWV reply to K1JT
+ printf("IV3NWV tx: K1JT IV3NWV JN66\n");
+ encodemsg_jt65(x,CALL_K1JT,CALL_IV3NWV,GRID_JN66);
+ qra65_encode(codec_iv3nwv, y, x);
- return 0;
+ printf("Simulating decodes by K1JT up to AP56 ...");
+
+ for (k=0;k=0)
+ ndecok[rc]++;
+ }
+ printf("\n");
+
+ printf("Transimtted:%d - Decoded:\n",ntx);
+ for (k=0;k<6;k++) {
+ printf("%3d with %s\n",ndecok[k],decode_type[k]);
+ ndec += ndecok[k];
+ }
+ printf("Total: %d/%d\n",ndec,ntx);
+ printf("\n");
+
+ return 0;
}
void syntax(void)
{
- printf("\nQRA65 Mode Tests\n");
- printf("2016, Nico Palermo - IV3NWV\n\n");
- printf("---------------------------\n\n");
- printf("Syntax: qra65 [-s] [-c] [-a] [-t] [-h]\n");
- printf("Options: \n");
- printf(" -s : set simulation SNR in 2500 Hz BW (default:-27.5 dB)\n");
- printf(" -c : set channel type 0=AWGN (default) 1=Rayleigh\n");
- printf(" -a : set decode type 0=NO_AP 1=AUTO_AP (default)\n");
- printf(" -t: 0=simulate seq of msgs between IV3NWV and K1JT (default)\n");
- printf(" 1=simulate K1JT receiving K1JT IV3NWV JN66\n");
- printf(" -h: this help\n");
+ printf("\nQRA65 Mode Tests\n");
+ printf("2016, Nico Palermo - IV3NWV\n\n");
+ printf("---------------------------\n\n");
+ printf("Syntax: qra65 [-s] [-c] [-a] [-t] [-h]\n");
+ printf("Options: \n");
+ printf(" -s : set simulation SNR in 2500 Hz BW (default:-27.5 dB)\n");
+ printf(" -c : set channel type 0=AWGN (default) 1=Rayleigh\n");
+ printf(" -a : set decode type 0=NO_AP 1=AUTO_AP (default)\n");
+ printf(" -t: 0=simulate seq of msgs between IV3NWV and K1JT (default)\n");
+ printf(" 1=simulate K1JT receiving K1JT IV3NWV JN66\n");
+ printf(" -h: this help\n");
}
int main(int argc, char* argv[])
{
- int k, rc, nok=0;
-
- float SNRdB = -27.5f;
- unsigned int channel = CHANNEL_AWGN;
- unsigned int mode = QRA_AUTOAP;
- unsigned int testtype=0;
- int nqso = 100;
-
- float EbNodB;
-
- // parse command line
- while(--argc) {
- argv++;
- if (strncmp(*argv,"-h",2)==0) {
- syntax();
- return 0;
- }
- else
- if (strncmp(*argv,"-a",2)==0) {
- mode = ( int)atoi((*argv)+2);
- if (mode>1) {
- printf("Invalid decoding mode\n");
- syntax();
- return -1;
- }
- }
- else
- if (strncmp(*argv,"-s",2)==0) {
- SNRdB = (float)atof((*argv)+2);
- if (SNRdB>0 || SNRdB<-40) {
- printf("SNR should be in the range [-40..0]\n");
- syntax();
- return -1;
- }
- }
- else
- if (strncmp(*argv,"-t",2)==0) {
- testtype = ( int)atoi((*argv)+2);
- if (testtype>1) {
- printf("Invalid test type\n");
- syntax();
- return -1;
- }
- }
- else
- if (strncmp(*argv,"-c",2)==0) {
- channel = ( int)atoi((*argv)+2);
- if (channel>CHANNEL_RAYLEIGH) {
- printf("Invalid channel type\n");
- syntax();
- return -1;
- }
- }
- else {
- printf("Invalid option\n");
- syntax();
- return -1;
- }
- }
-
- EbNodB = SNRdB+29.1f;
+ int k, rc, nok=0;
+ float SNRdB = -27.5f;
+ unsigned int channel = CHANNEL_AWGN;
+ unsigned int mode = QRA_AUTOAP;
+ unsigned int testtype=0;
+ int nqso = 100;
+ float EbNodB;
+// Parse the command line
+ while(--argc) {
+ argv++;
+ if (strncmp(*argv,"-h",2)==0) {
+ syntax();
+ return 0;
+ } else {
+ if (strncmp(*argv,"-a",2)==0) {
+ mode = ( int)atoi((*argv)+2);
+ if (mode>1) {
+ printf("Invalid decoding mode\n");
+ syntax();
+ return -1;
+ }
+ } else {
+ if (strncmp(*argv,"-s",2)==0) {
+ SNRdB = (float)atof((*argv)+2);
+ if (SNRdB>0 || SNRdB<-40) {
+ printf("SNR should be in the range [-40..0]\n");
+ syntax();
+ return -1;
+ }
+ } else {
+ if (strncmp(*argv,"-t",2)==0) {
+ testtype = ( int)atoi((*argv)+2);
+ if (testtype>1) {
+ printf("Invalid test type\n");
+ syntax();
+ return -1;
+ }
+ } else {
+ if (strncmp(*argv,"-c",2)==0) {
+ channel = ( int)atoi((*argv)+2);
+ if (channel>CHANNEL_RAYLEIGH) {
+ printf("Invalid channel type\n");
+ syntax();
+ return -1;
+ }
+ } else {
+ printf("Invalid option\n");
+ syntax();
+ return -1;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ EbNodB = SNRdB+29.1f;
+
#if defined(__linux__) || defined(__unix__)
- srand48(GetTickCount());
+ srand48(GetTickCount());
#endif
- if (testtype==0) {
- for (k=0;k.
+(c) 2016 - Nico Palermo, IV3NWV
-// -----------------------------------------------------------------------------
+-------------------------------------------------------------------------------
-// Code used in this sowftware release:
+ qracodes is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+ qracodes is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
-// QRA13_64_64_IRR_E: K=13 N=64 Q=64 irregular QRA code (defined in qra13_64_64_irr_e.h /.c)
+ You should have received a copy of the GNU General Public License
+ along with qracodes source distribution.
+ If not, see .
-// Codes with K=13 are designed to include a CRC as the 13th information symbol
-// and improve the code UER (Undetected Error Rate).
-// The CRC symbol is not sent along the channel (the codes are punctured) and the
-// resulting code is a (12,63) code
+-----------------------------------------------------------------------------
-// ------------------------------------------------------------------------------
+Code used in this sowftware release:
+
+QRA13_64_64_IRR_E: K=13 N=64 Q=64 irregular QRA code (defined in
+qra13_64_64_irr_e.h /.c)
+
+Codes with K=13 are designed to include a CRC as the 13th information symbol
+and improve the code UER (Undetected Error Rate).
+The CRC symbol is not sent along the channel (the codes are punctured) and the
+resulting code is a (12,63) code
+*/
+//----------------------------------------------------------------------------
#include
#include
@@ -41,304 +43,305 @@
// Code parameters of the QRA65 mode
#define QRA65_CODE qra_13_64_64_irr_e
-#define QRA65_NMSG 218 // this must much the value indicated in QRA65_CODE.NMSG
+#define QRA65_NMSG 218 // Must much value indicated in QRA65_CODE.NMSG
-#define QRA65_KC (QRA65_K+1) // information symbols crc included (as defined in the code)
-#define QRA65_NC (QRA65_N+1) // codeword length (as defined in the code)
-#define QRA65_NITER 100 // max number of iterations per decode
+#define QRA65_KC (QRA65_K+1) // Information symbols (crc included)
+#define QRA65_NC (QRA65_N+1) // Codeword length (as defined in the code)
+#define QRA65_NITER 100 // max number of iterations per decode
-
-
-// static functions declarations -------------------------------------------------
+// static functions declarations ----------------------------------------------
static int calc_crc6(const int *x, int sz);
-static void ix_mask(float *dst, const float *src, const int *mask, const int *x);
-static int qra65_do_decode(int *x, const float *pix, const int *ap_mask, const int *ap_x);
-
-// a-priori information masks for fields in jt65-like msgs -----------------------
+static void ix_mask(float *dst, const float *src, const int *mask,
+ const int *x);
+static int qra65_do_decode(int *x, const float *pix, const int *ap_mask,
+ const int *ap_x);
+// a-priori information masks for fields in JT65-like msgs --------------------
#define MASK_CQQRZ 0xFFFFFFC // CQ/QRZ calls common bits
#define MASK_CALL1 0xFFFFFFF
#define MASK_CALL2 0xFFFFFFF
#define MASK_GRIDFULL 0xFFFF
-#define MASK_GRIDBIT 0x8000 // b[15] is 0 for all the messages which are not text
-
-// -------------------------------------------------------------------------------
+#define MASK_GRIDBIT 0x8000 // b[15] is 1 for free text, 0 otherwise
+// ----------------------------------------------------------------------------
qra65codec *qra65_init(int flags, const int mycall)
{
- // Eb/No value for which we optimize the decoder metric
- const float EbNodBMetric = 2.8f;
- const float EbNoMetric = (float)pow(10,EbNodBMetric/10);
- const float R = 1.0f*(QRA65_KC)/(QRA65_NC);
+ // Eb/No value for which we optimize the decoder metric
+ const float EbNodBMetric = 2.8f;
+ const float EbNoMetric = (float)pow(10,EbNodBMetric/10);
+ const float R = 1.0f*(QRA65_KC)/(QRA65_NC);
- qra65codec *pcodec = (qra65codec*)malloc(sizeof(qra65codec));
+ qra65codec *pcodec = (qra65codec*)malloc(sizeof(qra65codec));
- if (!pcodec)
- return 0; // can't allocate memory
-
- pcodec->decEsNoMetric = 1.0f*QRA65_m*R*EbNoMetric;
- pcodec->apflags = flags;
+ if (!pcodec)
+ return 0; // can't allocate memory
- if (flags!=QRA_AUTOAP)
- return pcodec;
+ pcodec->decEsNoMetric = 1.0f*QRA65_m*R*EbNoMetric;
+ pcodec->apflags = flags;
- // initialize messages and mask for decoding with a-priori information
+ if (flags!=QRA_AUTOAP)
+ return pcodec;
- pcodec->apmycall = mycall;
- pcodec->apsrccall = 0;
+ // initialize messages and mask for decoding with a-priori information
- // encode CQ/QRZ messages and masks
- // NOTE: Here we handle only CQ and QRZ msgs
- // 'CQ nnn', 'CQ DX' and 'DE' msgs
- // will be handled by the decoder as messages with no a-priori knowledge
- encodemsg_jt65(pcodec->apmsg_cqqrz, CALL_CQ, 0, GRID_BLANK);
- encodemsg_jt65(pcodec->apmask_cqqrz, MASK_CQQRZ,0, MASK_GRIDBIT); // AP27 (26+1)
- encodemsg_jt65(pcodec->apmask_cqqrz_ooo, MASK_CQQRZ,0, MASK_GRIDFULL); // AP42 (26+16)
+ pcodec->apmycall = mycall;
+ pcodec->apsrccall = 0;
- // encode [mycall ? x] messages and set masks
- encodemsg_jt65(pcodec->apmsg_call1, mycall, 0, GRID_BLANK);
- encodemsg_jt65(pcodec->apmask_call1, MASK_CALL1, 0, MASK_GRIDBIT); // AP29 (28+1)
- encodemsg_jt65(pcodec->apmask_call1_ooo, MASK_CALL1, 0, MASK_GRIDFULL); // AP44 (28+16)
+ // encode CQ/QRZ messages and masks
+ // NOTE: Here we handle only CQ and QRZ msgs
+ // 'CQ nnn', 'CQ DX' and 'DE' msgs
+ // will be handled by the decoder as messages with no a-priori knowledge
+ encodemsg_jt65(pcodec->apmsg_cqqrz, CALL_CQ, 0, GRID_BLANK);
+ encodemsg_jt65(pcodec->apmask_cqqrz, MASK_CQQRZ,0, MASK_GRIDBIT); // AP27
+ encodemsg_jt65(pcodec->apmask_cqqrz_ooo, MASK_CQQRZ,0, MASK_GRIDFULL);// AP42
- // set mask for [mycall srccall ?] messages
- encodemsg_jt65(pcodec->apmask_call1_call2,MASK_CALL1, MASK_CALL2, MASK_GRIDBIT); // AP56 (28+28)
+ // encode [mycall ? x] messages and set masks
+ encodemsg_jt65(pcodec->apmsg_call1, mycall, 0, GRID_BLANK);
+ encodemsg_jt65(pcodec->apmask_call1, MASK_CALL1, 0, MASK_GRIDBIT); // AP29
+ encodemsg_jt65(pcodec->apmask_call1_ooo, MASK_CALL1,0, MASK_GRIDFULL);// AP44
- return pcodec;
+ // set mask for [mycall srccall ?] messages
+ encodemsg_jt65(pcodec->apmask_call1_call2,MASK_CALL1,MASK_CALL2,
+ MASK_GRIDBIT); // AP56
+ return pcodec;
}
void qra65_encode(qra65codec *pcodec, int *y, const int *x)
{
- int encx[QRA65_KC]; // encoder input buffer
- int ency[QRA65_NC]; // encoder output buffer
+ int encx[QRA65_KC]; // encoder input buffer
+ int ency[QRA65_NC]; // encoder output buffer
- int call1,call2,grid;
+ int call1,call2,grid;
- memcpy(encx,x,QRA65_K*sizeof(int)); // copy input to the encoder buffer
- encx[QRA65_K]=calc_crc6(encx,QRA65_K); // compute and add the crc symbol
+ memcpy(encx,x,QRA65_K*sizeof(int)); // Copy input to encoder buffer
+ encx[QRA65_K]=calc_crc6(encx,QRA65_K); // Compute and add crc symbol
+ qra_encode(&QRA65_CODE, ency, encx); // encode msg+crc using given QRA code
- qra_encode(&QRA65_CODE, ency, encx); // encode msg+crc using the given QRA code
+ // copy codeword to output puncturing the crc symbol
+ memcpy(y,ency,QRA65_K*sizeof(int)); // copy information symbols
+ memcpy(y+QRA65_K,ency+QRA65_KC,QRA65_C*sizeof(int)); // copy parity symbols
- // copy codeword to output puncturing the crc symbol
- memcpy(y,ency,QRA65_K*sizeof(int)); // copy the information symbols
- memcpy(y+QRA65_K,ency+QRA65_KC,QRA65_C*sizeof(int)); // copy the parity check symbols
+ if (pcodec->apflags!=QRA_AUTOAP)
+ return;
- if (pcodec->apflags!=QRA_AUTOAP)
- return;
+ // look if the msg sent is a std type message (bit15 of grid field = 0)
+ if ((x[9]&0x80)==1)
+ return; // no, it's a text message
- // look if the msg sent is a std type message (bit15 of grid field = 0)
- if ((x[9]&0x80)==1)
- return; // no, it's a text message
+ // It's a [call1 call2 grid] message
- // it's a [call1 call2 grid] message
-
- // we assume that call2 is our call (but we don't check it)
- // call1 the station callsign we are calling or indicates a general call (CQ/QRZ/etc..)
- decodemsg_jt65(&call1,&call2,&grid,x);
+ // We assume that call2 is our call (but we don't check it)
+ // call1 the station callsign we are calling or indicates a general call (CQ/QRZ/etc..)
+ decodemsg_jt65(&call1,&call2,&grid,x);
- if ((call1>=CALL_CQ && call1<=CALL_CQ999) || call1==CALL_CQDX || call1==CALL_DE) {
- // we are making a general call, so we still don't know who can reply us (srccall)
- // reset apsrccall to 0 so that the decoder won't look for [mycall srccall ?] msgs
- pcodec->apsrccall = 0;
- }
- else {
- // we are replying someone named call1
- // set apmsg_call1_call2 so that the decoder will attempt to decode [mycall call1 ?] msgs
- pcodec->apsrccall = call1;
- encodemsg_jt65(pcodec->apmsg_call1_call2, pcodec->apmycall, pcodec->apsrccall, 0);
- }
-
+ if ((call1>=CALL_CQ && call1<=CALL_CQ999) || call1==CALL_CQDX ||
+ call1==CALL_DE) {
+ // We are making a general call; don't know who might reply (srccall)
+ // Reset apsrccall to 0 so decoder won't look for [mycall srccall ?] msgs
+ pcodec->apsrccall = 0;
+ } else {
+ // We are replying to someone named call1
+ // Set apmsg_call1_call2 so decoder will try for [mycall call1 ?] msgs
+ pcodec->apsrccall = call1;
+ encodemsg_jt65(pcodec->apmsg_call1_call2, pcodec->apmycall,
+ pcodec->apsrccall, 0);
+ }
}
int qra65_decode(qra65codec *pcodec, int *x, const float *rxen)
{
- int k;
- float *srctmp, *dsttmp;
- float ix[QRA65_NC*QRA65_M]; // (depunctured) intrisic information to the decoder
- int rc;
+ int k;
+ float *srctmp, *dsttmp;
+ float ix[QRA65_NC*QRA65_M]; // (depunctured) intrisic information
+ int rc;
+
+ if (QRA65_NMSG!=QRA65_CODE.NMSG) // sanity check
+ return -16; // QRA65_NMSG define is wrong
- // sanity check
- if (QRA65_NMSG!=QRA65_CODE.NMSG)
- return -16; // QRA65_NMSG define is wrong
+ // compute symbols intrinsic probabilities from received energy observations
+ qra_mfskbesselmetric(ix, rxen, QRA65_m, QRA65_N,pcodec->decEsNoMetric);
- // compute symbols intrinsic probabilities from received energy observations
- qra_mfskbesselmetric(ix, rxen, QRA65_m, QRA65_N,pcodec->decEsNoMetric);
+ // de-puncture observations adding a uniform distribution for the crc symbol
- // de-puncture observations adding a uniform distribution for the crc symbol ----------
+ // move check symbols distributions one symbol towards the end
+ dsttmp = PD_ROWADDR(ix,QRA65_M, QRA65_NC-1); //Point to last symbol prob dist
+ srctmp = dsttmp-QRA65_M; // source is the previous pd
+ for (k=0;k=0) return 0; // successfull decode with AP0
- // attempt to decode without a-priori --------------------------------------------------
- rc = qra65_do_decode(x, ix, NULL, NULL);
- if (rc>=0) return 0; // successfull decode with 0 ap
+ if (pcodec->apflags!=QRA_AUTOAP) return rc; // rc<0 = unsuccessful decode
- if (pcodec->apflags!=QRA_AUTOAP) return rc; // rc<0 = unsuccessful decode
+ // Attempt to decode CQ calls
+ rc = qra65_do_decode(x,ix,pcodec->apmask_cqqrz, pcodec->apmsg_cqqrz); // AP27
+ if (rc>=0) return 1; // decoded [cq/qrz ? ?]
- // attempt to decode CQ calls
- rc = qra65_do_decode(x, ix, pcodec->apmask_cqqrz, pcodec->apmsg_cqqrz); // 27 bit AP
- if (rc>=0) return 1; // decoded [cq/qrz ? ?]
- rc = qra65_do_decode(x, ix, pcodec->apmask_cqqrz_ooo, pcodec->apmsg_cqqrz); // 44 bit AP
- if (rc>=0) return 2; // decoded [cq ? ooo]
+ rc = qra65_do_decode(x, ix, pcodec->apmask_cqqrz_ooo,
+ pcodec->apmsg_cqqrz); // AP42
+ if (rc>=0) return 2; // decoded [cq ? ooo]
- // attempt to decode calls directed to us (mycall)
- rc = qra65_do_decode(x, ix, pcodec->apmask_call1, pcodec->apmsg_call1); // 29 bit AP
- if (rc>=0) return 3; // decoded [mycall ? ?]
- rc = qra65_do_decode(x, ix, pcodec->apmask_call1_ooo, pcodec->apmsg_call1); // 45 bit AP
- if (rc>=0) return 4; // decoded [mycall ? ooo]
+ // attempt to decode calls directed to us (mycall)
+ rc = qra65_do_decode(x, ix, pcodec->apmask_call1,
+ pcodec->apmsg_call1); // AP29
+ if (rc>=0) return 3; // decoded [mycall ? ?]
- // if apsrccall is set attempt to decode [mycall srccall ?] msgs
- if (pcodec->apsrccall==0) return rc; // nothing more to do
+ rc = qra65_do_decode(x, ix, pcodec->apmask_call1_ooo,
+ pcodec->apmsg_call1); // AP44
+ if (rc>=0) return 4; // decoded [mycall ? ooo]
- rc = qra65_do_decode(x, ix, pcodec->apmask_call1_call2, pcodec->apmsg_call1_call2); // 57 bit AP
- if (rc>=0) return 5; // decoded [mycall srccall ?]
+ // if apsrccall is set attempt to decode [mycall srccall ?] msgs
+ if (pcodec->apsrccall==0) return rc; // nothing more to do
- return rc;
+ rc = qra65_do_decode(x, ix, pcodec->apmask_call1_call2,
+ pcodec->apmsg_call1_call2); // AP57
+ if (rc>=0) return 5; // decoded [mycall srccall ?]
+
+ return rc;
}
-// static functions definitions ----------------------------------------------------------------
+// Static functions definitions ----------------------------------------------
-// decode with given a-priori information
-static int qra65_do_decode(int *x, const float *pix, const int *ap_mask, const int *ap_x)
+// Decode with given a-priori information
+static int qra65_do_decode(int *x, const float *pix, const int *ap_mask,
+ const int *ap_x)
{
- int rc;
- const float *ixsrc;
- float ix_masked[QRA65_NC*QRA65_M]; // (masked) intrinsic information to the decoder
- float ex[QRA65_NC*QRA65_M]; // extrinsic information from the decoder
+ int rc;
+ const float *ixsrc;
+ float ix_masked[QRA65_NC*QRA65_M]; // Masked intrinsic information
+ float ex[QRA65_NC*QRA65_M]; // Extrinsic information from the decoder
- float v2cmsg[QRA65_NMSG*QRA65_M]; // buffers for the decoder messages
- float c2vmsg[QRA65_NMSG*QRA65_M];
- int xdec[QRA65_KC];
+ float v2cmsg[QRA65_NMSG*QRA65_M]; // buffers for the decoder messages
+ float c2vmsg[QRA65_NMSG*QRA65_M];
+ int xdec[QRA65_KC];
- if (ap_mask==NULL) { // no a-priori information
- ixsrc = pix; // intrinsic source is what passed as argument
- }
- else { // a-priori information provided
- // mask channel observations with a-priori
- ix_mask(ix_masked,pix,ap_mask,ap_x);
- ixsrc = ix_masked; // intrinsic source is the masked version
- }
+ if (ap_mask==NULL) { // no a-priori information
+ ixsrc = pix; // intrinsic source is what passed as argument
+ } else {
+ // a-priori information provided
+ // mask channel observations with a-priori
+ ix_mask(ix_masked,pix,ap_mask,ap_x);
+ ixsrc = ix_masked; // intrinsic source is the masked version
+ }
- // run the decoding algorithm
- rc = qra_extrinsic(&QRA65_CODE,ex,ixsrc,QRA65_NITER,v2cmsg,c2vmsg);
- if (rc<0)
- return -1; // no convergence in given iterations
+ // run the decoding algorithm
+ rc = qra_extrinsic(&QRA65_CODE,ex,ixsrc,QRA65_NITER,v2cmsg,c2vmsg);
+ if (rc<0)
+ return -1; // no convergence in given iterations
- // decode
- qra_mapdecode(&QRA65_CODE,xdec,ex,ixsrc);
+ // decode
+ qra_mapdecode(&QRA65_CODE,xdec,ex,ixsrc);
- // verify crc
- if (calc_crc6(xdec,QRA65_K)!=xdec[QRA65_K]) // crc doesn't match (detected error)
- return -2; // decoding was succesfull but crc doesn't match
+ // verify crc
+ if (calc_crc6(xdec,QRA65_K)!=xdec[QRA65_K]) // crc doesn't match (detected error)
+ return -2; // decoding was succesfull but crc doesn't match
- // success. copy decoded message to output buffer
- memcpy(x,xdec,QRA65_K*sizeof(int));
-
- return 0;
+ // success. copy decoded message to output buffer
+ memcpy(x,xdec,QRA65_K*sizeof(int));
+ return 0;
}
-// crc functions -------------------------------------------------------------------------------
+// crc functions --------------------------------------------------------------
// crc-6 generator polynomial
// g(x) = x^6 + a5*x^5 + ... + a1*x + a0
// g(x) = x^6 + x + 1
#define CRC6_GEN_POL 0x30 // MSB=a0 LSB=a5
-// g(x) = x^6 + x^2 + x + 1 (as suggested by Joe. See: https://users.ece.cmu.edu/~koopman/crc/)
+// g(x) = x^6 + x^2 + x + 1 (See: https://users.ece.cmu.edu/~koopman/crc/)
// #define CRC6_GEN_POL 0x38 // MSB=a0 LSB=a5. Simulation results are similar
static int calc_crc6(const int *x, int sz)
{
- // todo: compute it faster using a look up table
- int k,j,t,sr = 0;
- for (k=0;k>1) ^ CRC6_GEN_POL;
- else
- sr = (sr>>1);
- t>>=1;
- }
- }
- return sr;
+ // todo: compute it faster using a look up table
+ int k,j,t,sr = 0;
+ for (k=0;k>1) ^ CRC6_GEN_POL;
+ else
+ sr = (sr>>1);
+ t>>=1;
+ }
+ }
+ return sr;
}
-static void ix_mask(float *dst, const float *src, const int *mask, const int *x)
+static void ix_mask(float *dst, const float *src, const int *mask,
+ const int *x)
{
- // mask intrinsic information (channel observations) with a priori knowledge
+ // mask intrinsic information (channel observations) with a priori knowledge
- int k,kk, smask;
- float *row;
+ int k,kk, smask;
+ float *row;
- memcpy(dst,src,(QRA65_NC*QRA65_M)*sizeof(float));
+ memcpy(dst,src,(QRA65_NC*QRA65_M)*sizeof(float));
- for (k=0;k>22)&0x3F;
- y[1]= (call1>>16)&0x3F;
- y[2]= (call1>>10)&0x3F;
- y[3]= (call1>>4)&0x3F;
- y[4]= (call1<<2)&0x3F;
+ y[0]= (call1>>22)&0x3F;
+ y[1]= (call1>>16)&0x3F;
+ y[2]= (call1>>10)&0x3F;
+ y[3]= (call1>>4)&0x3F;
+ y[4]= (call1<<2)&0x3F;
- y[4] |= (call2>>26)&0x3F;
- y[5]= (call2>>20)&0x3F;
- y[6]= (call2>>14)&0x3F;
- y[7]= (call2>>8)&0x3F;
- y[8]= (call2>>2)&0x3F;
- y[9]= (call2<<4)&0x3F;
+ y[4] |= (call2>>26)&0x3F;
+ y[5]= (call2>>20)&0x3F;
+ y[6]= (call2>>14)&0x3F;
+ y[7]= (call2>>8)&0x3F;
+ y[8]= (call2>>2)&0x3F;
+ y[9]= (call2<<4)&0x3F;
- y[9] |= (grid>>12)&0x3F;
- y[10]= (grid>>6)&0x3F;
- y[11]= (grid)&0x3F;
+ y[9] |= (grid>>12)&0x3F;
+ y[10]= (grid>>6)&0x3F;
+ y[11]= (grid)&0x3F;
}
void decodemsg_jt65(int *call1, int *call2, int *grid, const int *x)
{
- int nc1, nc2, ng;
+ int nc1, nc2, ng;
- nc1 = x[4]>>2;
- nc1 |= x[3]<<4;
- nc1 |= x[2]<<10;
- nc1 |= x[1]<<16;
- nc1 |= x[0]<<22;
+ nc1 = x[4]>>2;
+ nc1 |= x[3]<<4;
+ nc1 |= x[2]<<10;
+ nc1 |= x[1]<<16;
+ nc1 |= x[0]<<22;
- nc2 = x[9]>>4;
- nc2 |= x[8]<<2;
- nc2 |= x[7]<<8;
- nc2 |= x[6]<<14;
- nc2 |= x[5]<<20;
- nc2 |= (x[4]&0x03)<<26;
+ nc2 = x[9]>>4;
+ nc2 |= x[8]<<2;
+ nc2 |= x[7]<<8;
+ nc2 |= x[6]<<14;
+ nc2 |= x[5]<<20;
+ nc2 |= (x[4]&0x03)<<26;
- ng = x[11];
- ng |= x[10]<<6;
- ng |= (x[9]&0x0F)<<12;
+ ng = x[11];
+ ng |= x[10]<<6;
+ ng |= (x[9]&0x0F)<<12;
- *call1 = nc1;
- *call2 = nc2;
- *grid = ng;
+ *call1 = nc1;
+ *call2 = nc2;
+ *grid = ng;
}
-
-
diff --git a/lib/qra/qra65/qra65.h b/lib/qra/qra65/qra65.h
index 25b4b4402..8521ffe2b 100644
--- a/lib/qra/qra65/qra65.h
+++ b/lib/qra/qra65/qra65.h
@@ -43,18 +43,18 @@
#define GRID_BLANK 0x7E91
typedef struct {
- float decEsNoMetric;
- int apflags;
- int apmycall;
- int apsrccall;
- int apmsg_cqqrz[12]; // [cq/qrz ? blank]
- int apmsg_call1[12]; // [mycall ? blank]
- int apmsg_call1_call2[12]; // [mycall srccall ?]
- int apmask_cqqrz[12];
- int apmask_cqqrz_ooo[12];
- int apmask_call1[12];
- int apmask_call1_ooo[12];
- int apmask_call1_call2[12];
+ float decEsNoMetric;
+ int apflags;
+ int apmycall;
+ int apsrccall;
+ int apmsg_cqqrz[12]; // [cq/qrz ? blank]
+ int apmsg_call1[12]; // [mycall ? blank]
+ int apmsg_call1_call2[12]; // [mycall srccall ?]
+ int apmask_cqqrz[12];
+ int apmask_cqqrz_ooo[12];
+ int apmask_call1[12];
+ int apmask_call1_ooo[12];
+ int apmask_call1_call2[12];
} qra65codec;
#ifdef __cplusplus
diff --git a/lib/qra/qra65/qra65_subs.c b/lib/qra/qra65/qra65_subs.c
index e5c7f2a06..46bddc125 100644
--- a/lib/qra/qra65/qra65_subs.c
+++ b/lib/qra/qra65/qra65_subs.c
@@ -11,20 +11,32 @@ void qra65_enc_(int x[], int y[])
qra65_encode(codec, y, x);
}
-void qra65_dec_(float r[], int xdec[], int* rc)
+void qra65_dec_(float r[], int* nmycall, int xdec[], int* rc)
{
// Return codes:
-// rc<0 no decode
+// rc=-16 failed sanity check
+// rc=-2 decoded, but crc check failed
+// rc=-1 no decode
// rc=0 [? ? ?] AP0 (decoding with no a-priori information)
// rc=1 [CQ ? ?] AP27
-// rc=2 [CQ ? ] AP44
+// rc=2 [CQ ? ] AP42
// rc=3 [CALL ? ?] AP29
-// rc=4 [CALL ? ] AP45
+// rc=4 [CALL ? ] AP44
// rc=5 [CALL CALL ?] AP57
- int ncall=0xf70c238; //K1ABC
- // int ncall=0x890c60c; //KA1ABC
- int i;
+ static int ncall0=0;
+ int ncall;
+ int x[63],y[12];
+
+ ncall = *nmycall;
qra65codec *codec = qra65_init(1,ncall); //codec for ncall
+/*
+ if(ncall != ncall0) {
+ memset(y,0,sizeof(y));
+ qra65_encode(codec, y, x);
+ printf("Updated codec %d\n",ncall);
+ }
+ ncall0=ncall;
+*/
*rc = qra65_decode(codec,xdec,r);
}
diff --git a/lib/qra/qra65/qra65sim.f90 b/lib/qra/qra65/qra65sim.f90
index fdb8ea70e..476c938a3 100644
--- a/lib/qra/qra65/qra65sim.f90
+++ b/lib/qra/qra65/qra65sim.f90
@@ -121,6 +121,8 @@ program qra65sim
h=default_header(12000,npts)
dfsig=2000.0/nsigs !Freq spacing between sigs in file (Hz)
+ print*,'A',nsigs,nfiles
+
do ifile=1,nfiles !Loop over requested number of files
write(fname,1002) ifile !Output filename
1002 format('000000_',i4.4)
@@ -146,9 +148,8 @@ program qra65sim
call packmsg(msg,dgen,itype) !Pack message into 12 six-bit bytes
call qra65_enc(dgen,sent) !Encode using QRA65
! call qra65_dec(sent,dgen,ierr) !Decode (### for test only ###)
-
- write(*,3001) sent
-3001 format(21i3)
+! write(*,3001) sent
+!3001 format(21i3)
k=0
do j=1,nsym !Insert sync and data into itone()