SVN r8748
This commit is contained in:
@@ -1,3 +1,2 @@
|
|||||||
TAGS
|
TAGS
|
||||||
tags
|
tags
|
||||||
.svn
|
|
||||||
|
|||||||
@@ -1,166 +0,0 @@
|
|||||||
/* ALIST-TO-PCHK.C - Convert a parity check matrix to alist format. */
|
|
||||||
|
|
||||||
/* Copyright (c) 1995-2012 by Radford M. Neal.
|
|
||||||
*
|
|
||||||
* Permission is granted for anyone to copy, use, modify, and distribute
|
|
||||||
* these programs and accompanying documents for any purpose, provided
|
|
||||||
* this copyright notice is retained and prominently displayed, and note
|
|
||||||
* is made of any changes made to these programs. These programs and
|
|
||||||
* documents are distributed without any warranty, express or implied.
|
|
||||||
* As the programs were written for research purposes only, they have not
|
|
||||||
* been tested to the degree that would be advisable in any important
|
|
||||||
* application. All use of these programs is entirely at the user's own
|
|
||||||
* risk.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <math.h>
|
|
||||||
|
|
||||||
#include "alloc.h"
|
|
||||||
#include "open.h"
|
|
||||||
#include "mod2sparse.h"
|
|
||||||
#include "mod2dense.h"
|
|
||||||
#include "mod2convert.h"
|
|
||||||
#include "rcode.h"
|
|
||||||
|
|
||||||
|
|
||||||
void usage(void);
|
|
||||||
|
|
||||||
|
|
||||||
/* MAIN PROGRAM. */
|
|
||||||
|
|
||||||
int main
|
|
||||||
( int argc,
|
|
||||||
char **argv
|
|
||||||
)
|
|
||||||
{
|
|
||||||
char *alist_file, *pchk_file;
|
|
||||||
FILE *af, *pf;
|
|
||||||
int mxrw, mxcw;
|
|
||||||
int *rw, *cw;
|
|
||||||
int i, j, k;
|
|
||||||
mod2entry *e;
|
|
||||||
int trans;
|
|
||||||
int nozeros;
|
|
||||||
int last;
|
|
||||||
|
|
||||||
trans = 0;
|
|
||||||
nozeros = 0;
|
|
||||||
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
if (argc>1 && strcmp(argv[1],"-t")==0)
|
|
||||||
{ trans = 1;
|
|
||||||
argc -= 1;
|
|
||||||
argv += 1;
|
|
||||||
}
|
|
||||||
else if (argc>1 && strcmp(argv[1],"-z")==0)
|
|
||||||
{ nozeros = 1;
|
|
||||||
argc -= 1;
|
|
||||||
argv += 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (argc!=3)
|
|
||||||
{ usage();
|
|
||||||
}
|
|
||||||
|
|
||||||
pchk_file = argv[1];
|
|
||||||
alist_file = argv[2];
|
|
||||||
|
|
||||||
read_pchk(pchk_file);
|
|
||||||
|
|
||||||
if (trans)
|
|
||||||
{ mod2sparse *HT;
|
|
||||||
HT = H;
|
|
||||||
H = mod2sparse_allocate(N,M);
|
|
||||||
mod2sparse_transpose(HT,H);
|
|
||||||
M = mod2sparse_rows(H);
|
|
||||||
N = mod2sparse_cols(H);
|
|
||||||
}
|
|
||||||
|
|
||||||
af = open_file_std(alist_file,"wb");
|
|
||||||
|
|
||||||
if (af==NULL)
|
|
||||||
{ fprintf(stderr,"Can't create alist file: %s\n",alist_file);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(af,"%d %d\n",M,N);
|
|
||||||
|
|
||||||
rw = (int *) chk_alloc (M, sizeof *rw);
|
|
||||||
mxrw = 0;
|
|
||||||
|
|
||||||
for (i = 0; i<M; i++)
|
|
||||||
{ rw[i] = mod2sparse_count_row(H,i);
|
|
||||||
if (rw[i]>mxrw)
|
|
||||||
{ mxrw = rw[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cw = (int *) chk_alloc (N, sizeof *cw);
|
|
||||||
mxcw = 0;
|
|
||||||
|
|
||||||
for (j = 0; j<N; j++)
|
|
||||||
{ cw[j] = mod2sparse_count_col(H,j);
|
|
||||||
if (cw[j]>mxcw)
|
|
||||||
{ mxcw = cw[j];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(af,"%d %d\n",mxrw,mxcw);
|
|
||||||
|
|
||||||
for (i = 0; i<M; i++)
|
|
||||||
{ fprintf(af,"%d%c",rw[i],i==M-1?'\n':' ');
|
|
||||||
}
|
|
||||||
|
|
||||||
for (j = 0; j<N; j++)
|
|
||||||
{ fprintf(af,"%d%c",cw[j],j==N-1?'\n':' ');
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i<M; i++)
|
|
||||||
{ e = mod2sparse_first_in_row(H,i);
|
|
||||||
last = 0;
|
|
||||||
for (k = 0; !last; k++)
|
|
||||||
{ last = nozeros ? k==rw[i]-1 : k==mxrw-1;
|
|
||||||
fprintf (af, "%d%c", mod2sparse_at_end(e)?0:mod2sparse_col(e)+1,
|
|
||||||
last?'\n':' ');
|
|
||||||
if (!mod2sparse_at_end(e))
|
|
||||||
{ e = mod2sparse_next_in_row(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (j = 0; j<N; j++)
|
|
||||||
{ e = mod2sparse_first_in_col(H,j);
|
|
||||||
last = 0;
|
|
||||||
for (k = 0; !last; k++)
|
|
||||||
{ last = nozeros ? k==cw[j]-1 : k==mxcw-1;
|
|
||||||
fprintf (af, "%d%c", mod2sparse_at_end(e)?0:mod2sparse_row(e)+1,
|
|
||||||
last?'\n':' ');
|
|
||||||
if (!mod2sparse_at_end(e))
|
|
||||||
{ e = mod2sparse_next_in_col(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ferror(af) || fclose(af)!=0)
|
|
||||||
{ fprintf(stderr,"Error writing to alist file %s\n",alist_file);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* PRINT USAGE MESSAGE AND EXIT. */
|
|
||||||
|
|
||||||
void usage(void)
|
|
||||||
{ fprintf(stderr,"Usage: pchk-to-alist [ -t ] [ -z ] pchk-file alist-file\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
+17
@@ -1,6 +1,23 @@
|
|||||||
module crc
|
module crc
|
||||||
use, intrinsic :: iso_c_binding, only: c_int, c_loc, c_int8_t, c_bool, c_short
|
use, intrinsic :: iso_c_binding, only: c_int, c_loc, c_int8_t, c_bool, c_short
|
||||||
interface
|
interface
|
||||||
|
|
||||||
|
function crc14 (data, length) bind (C, name="crc14")
|
||||||
|
use, intrinsic :: iso_c_binding, only: c_short, c_ptr, c_int
|
||||||
|
implicit none
|
||||||
|
integer (c_short) :: crc14
|
||||||
|
type (c_ptr), value :: data
|
||||||
|
integer (c_int), value :: length
|
||||||
|
end function crc14
|
||||||
|
|
||||||
|
function crc14_check (data, length) bind (C, name="crc16_check")
|
||||||
|
use, intrinsic :: iso_c_binding, only: c_bool, c_ptr, c_int
|
||||||
|
implicit none
|
||||||
|
logical (c_bool) :: crc14_check
|
||||||
|
type (c_ptr), value :: data
|
||||||
|
integer (c_int), value :: length
|
||||||
|
end function crc14_check
|
||||||
|
|
||||||
function crc12 (data, length) bind (C, name="crc12")
|
function crc12 (data, length) bind (C, name="crc12")
|
||||||
use, intrinsic :: iso_c_binding, only: c_short, c_ptr, c_int
|
use, intrinsic :: iso_c_binding, only: c_short, c_ptr, c_int
|
||||||
implicit none
|
implicit none
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,76 @@
|
|||||||
|
// Status=review
|
||||||
|
.Main Window:
|
||||||
|
- Select *FT8* on the *Mode* menu.
|
||||||
|
- Set Tx and Rx frequencies to 1200 Hz.
|
||||||
|
- Double-click on *Erase* to clear both text windows.
|
||||||
|
|
||||||
|
.Wide Graph Settings:
|
||||||
|
|
||||||
|
- *Bins/Pixel* = 4, *Start* = 200 Hz, *N Avg* = 2
|
||||||
|
- Adjust the width of the Wide Graph window so that the upper
|
||||||
|
frequency limit is approximately 2600 Hz.
|
||||||
|
|
||||||
|
.Open a Wave File:
|
||||||
|
|
||||||
|
- Select *File | Open* and navigate to
|
||||||
|
+...\save\samples\FT8\170709_135615.wav+. The waterfall and decoded
|
||||||
|
text window should look something like the following screen shots:
|
||||||
|
|
||||||
|
[[X15]]
|
||||||
|
image::170709_135615.wav.png[align="left",alt="Wide Graph Decode 170709_135615"]
|
||||||
|
|
||||||
|
image::ft8_decodes.png[align="left"]
|
||||||
|
|
||||||
|
- Click with the mouse anywhere on the waterfall display. The green Rx
|
||||||
|
frequency marker will jump to your selected frequency, and the Rx
|
||||||
|
frequency control on the main window will be updated accordingly.
|
||||||
|
|
||||||
|
- Do the same thing with the *Shift* key held down. Now the red Tx
|
||||||
|
frequency marker and its associated control on the main window will
|
||||||
|
follow your frequency selections.
|
||||||
|
|
||||||
|
- Do the same thing with the *Ctrl* key held down. Now the both colored
|
||||||
|
markers and both spinner controls will follow your selections.
|
||||||
|
|
||||||
|
- Double-clicking at any frequency on the waterfall does all the
|
||||||
|
things just described and also invokes the decoder in a small range
|
||||||
|
around the Rx frequency. To decode a particular signal, double-click
|
||||||
|
near the left edge of its waterfall trace.
|
||||||
|
|
||||||
|
- Now double-click on any of the the lines of decoded text in the main
|
||||||
|
window. All three lines will show the same behavior, setting Rx
|
||||||
|
frequency to that of the selected message and leaving Tx frequency
|
||||||
|
unchanged. To change both Rx and Tx frequencies, hold *Ctrl* down
|
||||||
|
when double-clicking.
|
||||||
|
|
||||||
|
NOTE: To avoid QRM from competing callers, it is frequently desirable
|
||||||
|
to answer a CQ on a different frequency from that of the CQing
|
||||||
|
station. The same is true when you tail-end another QSO. Choose a Tx
|
||||||
|
frequency that appears to be not in use.
|
||||||
|
|
||||||
|
NOTE: Keyboard shortcuts *Shift+F11* and *Shift+F12* provide an easy
|
||||||
|
way to move your Tx frequency down or up in 60 Hz steps.
|
||||||
|
|
||||||
|
NOTE: Further helpful tips on FT8 operating procedures are available
|
||||||
|
{ft8_tips}. Thanks to ZL2IFB!
|
||||||
|
|
||||||
|
.FT8 DXpedition Mode:
|
||||||
|
|
||||||
|
This special operating mode enables DXpeditions to make FT8 QSOs at
|
||||||
|
very high rates. Both stations must use _WSJT-X_ Version 1.9 or
|
||||||
|
later. Detailed operating instructions for {ft8_DXped} are available
|
||||||
|
online. Do not try to use DXpedition mode without reading these
|
||||||
|
instructions carefully!
|
||||||
|
|
||||||
|
IMPORTANT: FT8 DXpedition mode is intended for use by rare-entity
|
||||||
|
DXpeditions and other unusual circumstances in which sustained QSO
|
||||||
|
rates well above 100/hour are expected. Do not use the multi-signal
|
||||||
|
capability unless you satisfy this requirement, and do not use
|
||||||
|
DXpedition Mode in the conventional FT8 sub-bands. If you are
|
||||||
|
contemplating operation as Fox using DXpedition Mode, find a suitable
|
||||||
|
dial frequency consistent with regional band plans and publicize it
|
||||||
|
for the operators you hope to work. Remember that on-the-air signal
|
||||||
|
frequencies will be higher than the dial frequency by up to 4 kHz.
|
||||||
|
|
||||||
|
IMPORTANT: When finished with this Tutorial, don't forget to re-enter
|
||||||
|
your own callsign as *My Call* on the *Settings | General* tab.
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
subroutine encode174(message,codeword)
|
||||||
|
! Encode an 87-bit message and return a 174-bit codeword.
|
||||||
|
! The generator matrix has dimensions (87,87).
|
||||||
|
! The code is a (174,87) regular ldpc code with column weight 3.
|
||||||
|
! The code was generated using the PEG algorithm.
|
||||||
|
! After creating the codeword, the columns are re-ordered according to
|
||||||
|
! "colorder" to make the codeword compatible with the parity-check matrix
|
||||||
|
!
|
||||||
|
|
||||||
|
include "ldpc_174_87_params.f90"
|
||||||
|
|
||||||
|
integer*1 codeword(N)
|
||||||
|
integer*1 gen(M,K)
|
||||||
|
integer*1 itmp(N)
|
||||||
|
integer*1 message(K)
|
||||||
|
integer*1 pchecks(M)
|
||||||
|
logical first
|
||||||
|
data first/.true./
|
||||||
|
|
||||||
|
save first,gen
|
||||||
|
|
||||||
|
if( first ) then ! fill the generator matrix
|
||||||
|
gen=0
|
||||||
|
do i=1,M
|
||||||
|
do j=1,11
|
||||||
|
read(g(i)( (j-1)*2+1:(j-1)*2+2 ),"(Z2)") istr
|
||||||
|
do jj=1, 8
|
||||||
|
icol=(j-1)*8+jj
|
||||||
|
if( icol .le. 87 ) then
|
||||||
|
if( btest(istr,8-jj) ) gen(i,icol)=1
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
enddo
|
||||||
|
enddo
|
||||||
|
first=.false.
|
||||||
|
endif
|
||||||
|
|
||||||
|
do i=1,M
|
||||||
|
nsum=0
|
||||||
|
do j=1,K
|
||||||
|
nsum=nsum+message(j)*gen(i,j)
|
||||||
|
enddo
|
||||||
|
pchecks(i)=mod(nsum,2)
|
||||||
|
enddo
|
||||||
|
itmp(1:M)=pchecks
|
||||||
|
itmp(M+1:N)=message(1:K)
|
||||||
|
codeword(colorder+1)=itmp(1:N)
|
||||||
|
|
||||||
|
return
|
||||||
|
end subroutine encode174
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,180 +0,0 @@
|
|||||||
48 128
|
|
||||||
12 4
|
|
||||||
11 11 11 11 11 11 11 11 11 11 11 11 11 10 11 11 11 10 10 11 10 11 10 11 10 10 10 10 10 11 10 12 11 11 10 11 11 11 11 11 10 10 11 10 10 11 11 10
|
|
||||||
4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
|
|
||||||
1 13 26 38 51 62 75 86 99 111 124 0
|
|
||||||
2 13 27 39 49 63 76 87 100 112 121 0
|
|
||||||
3 14 27 40 52 64 74 88 101 104 123 0
|
|
||||||
2 15 28 41 53 65 77 89 102 113 125 0
|
|
||||||
4 16 26 41 54 66 71 90 101 114 122 0
|
|
||||||
5 15 29 40 55 67 78 91 98 110 126 0
|
|
||||||
6 17 30 42 56 63 79 90 103 115 124 0
|
|
||||||
7 18 25 43 56 68 80 87 104 113 122 0
|
|
||||||
7 13 29 44 52 69 81 92 102 114 127 0
|
|
||||||
8 14 29 42 57 66 77 86 97 116 119 0
|
|
||||||
9 19 26 45 56 69 76 93 97 110 128 0
|
|
||||||
9 14 28 46 54 68 82 91 99 112 118 0
|
|
||||||
8 20 31 47 49 69 78 88 105 109 124 0
|
|
||||||
1 20 32 42 52 70 76 94 106 117 0 0
|
|
||||||
10 15 33 48 52 62 80 93 100 118 119 0
|
|
||||||
11 18 31 39 48 67 83 94 97 114 125 0
|
|
||||||
12 15 34 37 49 64 73 85 99 116 127 0
|
|
||||||
2 21 25 45 55 64 83 92 103 119 0 0
|
|
||||||
4 22 33 46 55 65 84 86 107 108 0 0
|
|
||||||
11 16 27 45 53 70 79 95 107 111 126 0
|
|
||||||
6 13 33 45 57 68 85 96 101 120 0 0
|
|
||||||
12 17 25 38 58 67 76 96 107 118 123 0
|
|
||||||
5 18 30 44 59 71 77 93 106 120 0 0
|
|
||||||
6 20 28 43 50 72 83 86 95 121 127 0
|
|
||||||
11 23 28 38 59 73 81 88 108 115 0 0
|
|
||||||
10 19 32 49 60 67 75 89 101 108 0 0
|
|
||||||
5 22 27 48 54 69 73 96 103 113 0 0
|
|
||||||
12 23 35 47 50 62 79 97 106 122 0 0
|
|
||||||
3 18 26 47 53 61 82 85 98 108 0 0
|
|
||||||
9 22 31 41 58 60 72 87 106 115 116 0
|
|
||||||
10 16 30 50 58 65 73 91 104 109 0 0
|
|
||||||
10 24 36 41 57 61 78 94 103 111 123 127
|
|
||||||
4 17 29 43 59 74 85 89 109 112 128 0
|
|
||||||
3 21 34 38 60 63 77 95 105 114 128 0
|
|
||||||
7 24 37 46 53 71 74 96 105 110 0 0
|
|
||||||
6 19 34 47 51 70 81 91 100 123 125 0
|
|
||||||
2 24 31 40 56 66 81 84 95 118 120 0
|
|
||||||
1 14 30 37 48 72 78 92 107 122 128 0
|
|
||||||
3 23 24 42 55 68 75 93 109 121 125 0
|
|
||||||
12 22 32 43 51 71 82 88 102 119 126 0
|
|
||||||
1 23 36 44 58 64 80 90 110 112 0 0
|
|
||||||
7 19 35 40 59 65 82 90 111 117 0 0
|
|
||||||
9 17 36 39 50 66 75 92 105 117 126 0
|
|
||||||
4 21 35 39 57 70 80 98 99 115 0 0
|
|
||||||
8 25 33 37 54 60 79 94 98 121 0 0
|
|
||||||
8 16 34 46 61 62 83 87 102 117 120 0
|
|
||||||
11 21 32 44 61 72 74 84 100 113 124 0
|
|
||||||
5 20 35 36 51 63 84 89 104 116 0 0
|
|
||||||
1 14 38 41
|
|
||||||
2 4 18 37
|
|
||||||
3 29 34 39
|
|
||||||
5 19 33 44
|
|
||||||
6 23 27 48
|
|
||||||
7 21 24 36
|
|
||||||
8 9 35 42
|
|
||||||
10 13 45 46
|
|
||||||
11 12 30 43
|
|
||||||
15 26 31 32
|
|
||||||
16 20 25 47
|
|
||||||
17 22 28 40
|
|
||||||
1 2 9 21
|
|
||||||
3 10 12 38
|
|
||||||
4 6 15 17
|
|
||||||
5 20 31 46
|
|
||||||
7 22 33 43
|
|
||||||
8 16 23 29
|
|
||||||
11 26 36 42
|
|
||||||
13 14 24 48
|
|
||||||
18 34 44 47
|
|
||||||
19 27 30 40
|
|
||||||
25 28 39 41
|
|
||||||
32 35 37 39
|
|
||||||
8 18 22 45
|
|
||||||
1 5 11 29
|
|
||||||
2 3 20 27
|
|
||||||
4 12 24 25
|
|
||||||
6 9 10 33
|
|
||||||
7 23 31 38
|
|
||||||
13 16 30 37
|
|
||||||
14 26 40 47
|
|
||||||
15 19 21 45
|
|
||||||
17 34 36 46
|
|
||||||
28 42 44 48
|
|
||||||
32 41 43 48
|
|
||||||
17 35 38 45
|
|
||||||
1 22 25 34
|
|
||||||
2 16 43 44
|
|
||||||
3 6 37 42
|
|
||||||
4 5 30 32
|
|
||||||
7 10 14 39
|
|
||||||
8 24 33 40
|
|
||||||
9 23 41 47
|
|
||||||
11 18 20 21
|
|
||||||
12 19 35 46
|
|
||||||
13 28 29 36
|
|
||||||
15 16 27 38
|
|
||||||
2 13 17 26
|
|
||||||
24 28 31 43
|
|
||||||
1 36 40 48
|
|
||||||
3 9 14 15
|
|
||||||
4 20 29 35
|
|
||||||
5 12 27 45
|
|
||||||
6 18 19 39
|
|
||||||
7 8 11 37
|
|
||||||
10 21 32 44
|
|
||||||
22 30 31 41
|
|
||||||
23 25 33 42
|
|
||||||
26 30 34 45
|
|
||||||
29 32 46 47
|
|
||||||
1 15 28 46
|
|
||||||
2 7 34 48
|
|
||||||
3 17 18 41
|
|
||||||
4 19 31 42
|
|
||||||
5 10 37 43
|
|
||||||
6 16 22 26
|
|
||||||
8 12 21 39
|
|
||||||
9 11 13 27
|
|
||||||
14 20 36 44
|
|
||||||
5 23 35 40
|
|
||||||
24 30 38 47
|
|
||||||
17 25 27 31
|
|
||||||
3 33 35 47
|
|
||||||
1 26 39 43
|
|
||||||
2 11 14 22
|
|
||||||
4 10 23 34
|
|
||||||
6 13 32 38
|
|
||||||
7 20 28 45
|
|
||||||
8 15 41 44
|
|
||||||
9 25 36 37
|
|
||||||
12 29 40 42
|
|
||||||
16 18 24 46
|
|
||||||
19 37 47 48
|
|
||||||
17 21 29 33
|
|
||||||
1 10 19 24
|
|
||||||
2 8 30 46
|
|
||||||
3 13 25 40
|
|
||||||
4 26 33 48
|
|
||||||
5 7 41 42
|
|
||||||
6 12 31 36
|
|
||||||
9 18 38 43
|
|
||||||
11 15 23 39
|
|
||||||
14 16 32 45
|
|
||||||
20 24 34 37
|
|
||||||
21 22 27 35
|
|
||||||
10 11 16 28
|
|
||||||
6 29 44 45
|
|
||||||
1 12 17 44
|
|
||||||
2 15 36 47
|
|
||||||
3 5 21 26
|
|
||||||
4 9 40 46
|
|
||||||
7 18 27 32
|
|
||||||
3 8 31 48
|
|
||||||
13 34 35 43
|
|
||||||
14 23 28 30
|
|
||||||
19 20 22 38
|
|
||||||
19 25 26 29
|
|
||||||
13 31 33 39
|
|
||||||
6 11 35 41
|
|
||||||
1 20 32 42
|
|
||||||
2 12 33 41
|
|
||||||
4 8 27 47
|
|
||||||
5 9 16 34
|
|
||||||
7 25 30 44
|
|
||||||
10 17 30 48
|
|
||||||
14 42 43 46
|
|
||||||
12 15 22 37
|
|
||||||
10 15 18 40
|
|
||||||
21 23 37 46
|
|
||||||
2 24 39 45
|
|
||||||
5 8 28 38
|
|
||||||
3 22 32 36
|
|
||||||
1 7 13 47
|
|
||||||
4 16 36 39
|
|
||||||
6 20 40 43
|
|
||||||
9 17 24 32
|
|
||||||
11 33 34 38
|
|
||||||
Binary file not shown.
@@ -0,0 +1,52 @@
|
|||||||
|
subroutine filt8(f0,nslots,width,wave)
|
||||||
|
|
||||||
|
parameter (NFFT=180000,NH=NFFT/2)
|
||||||
|
real wave(NFFT)
|
||||||
|
real x(NFFT)
|
||||||
|
real s1(0:NH)
|
||||||
|
real s2(0:NH)
|
||||||
|
complex cx(0:NH)
|
||||||
|
equivalence (x,cx)
|
||||||
|
|
||||||
|
x=wave
|
||||||
|
call four2a(x,NFFT,1,-1,0) !r2c
|
||||||
|
df=12000.0/NFFT
|
||||||
|
fa=f0 - 0.5*6.25
|
||||||
|
fb=f0 + 7.5*6.25 + (nslots-1)*60.0
|
||||||
|
ia2=nint(fa/df)
|
||||||
|
ib1=nint(fb/df)
|
||||||
|
ia1=nint(ia2-width/df)
|
||||||
|
ib2=nint(ib1+width/df)
|
||||||
|
pi=4.0*atan(1.0)
|
||||||
|
do i=ia1,ia2
|
||||||
|
fil=(1.0 + cos(pi*df*(i-ia2)/width))/2.0
|
||||||
|
cx(i)=fil*cx(i)
|
||||||
|
enddo
|
||||||
|
do i=ib1,ib2
|
||||||
|
fil=(1.0 + cos(pi*df*(i-ib1)/width))/2.0
|
||||||
|
cx(i)=fil*cx(i)
|
||||||
|
enddo
|
||||||
|
cx(0:ia1-1)=0.
|
||||||
|
cx(ib2+1:)=0.
|
||||||
|
|
||||||
|
call four2a(cx,nfft,1,1,-1) !c2r
|
||||||
|
wave=x/nfft
|
||||||
|
|
||||||
|
!###
|
||||||
|
if(nslots.ne.99) return
|
||||||
|
x=wave
|
||||||
|
call four2a(x,NFFT,1,-1,0) !r2c
|
||||||
|
do i=0,NH
|
||||||
|
s1(i)=real(cx(i))**2 + aimag(cx(i))**2
|
||||||
|
enddo
|
||||||
|
nadd=20
|
||||||
|
call smo(s1,NH+1,s2,nadd)
|
||||||
|
do i=0,NH
|
||||||
|
freq=i*df
|
||||||
|
write(29,3101) freq,db(s2(i)) - 72.0
|
||||||
|
3101 format(2f12.3)
|
||||||
|
enddo
|
||||||
|
!###
|
||||||
|
|
||||||
|
return
|
||||||
|
end subroutine filt8
|
||||||
@@ -0,0 +1,544 @@
|
|||||||
|
program wspr5d
|
||||||
|
|
||||||
|
! Decode WSPR-LF data read from *.c5 or *.wav files.
|
||||||
|
|
||||||
|
! WSPR-LF is a potential WSPR-like mode intended for use at LF and MF.
|
||||||
|
! It uses an LDPC (300,60) code, OQPSK modulation, and 5 minute T/R sequences.
|
||||||
|
!
|
||||||
|
! Still to do: find and decode more than one signal in the specified passband.
|
||||||
|
|
||||||
|
! include 'wsprlf_params.f90'
|
||||||
|
|
||||||
|
parameter (NDOWN=30)
|
||||||
|
parameter (KK=60)
|
||||||
|
parameter (ND=300)
|
||||||
|
parameter (NS=109)
|
||||||
|
parameter (NR=3)
|
||||||
|
parameter (NN=NR+NS+ND)
|
||||||
|
parameter (NSPS0=8640)
|
||||||
|
parameter (NSPS=16)
|
||||||
|
parameter (N2=2*NSPS)
|
||||||
|
parameter (NZ=NSPS*NN)
|
||||||
|
parameter (NZ400=288*NN)
|
||||||
|
parameter (NMAX=300*12000)
|
||||||
|
|
||||||
|
character arg*8,message*22,cbits*50,infile*80,fname*16,datetime*11
|
||||||
|
character*120 data_dir
|
||||||
|
complex csync(0:NZ-1) !Sync symbols only, from cbb
|
||||||
|
complex c400(0:NZ400-1) !Complex waveform
|
||||||
|
complex c(0:NZ-1) !Complex waveform
|
||||||
|
complex cd(0:NZ-1) !Complex waveform
|
||||||
|
complex ca(0:NZ-1) !Complex waveform
|
||||||
|
complex zz,zzsum
|
||||||
|
real*8 fMHz
|
||||||
|
real rxdata(ND),llr(ND) !Soft symbols
|
||||||
|
real pp(32) !Shaped pulse for OQPSK
|
||||||
|
real sbits(412),softbits(9)
|
||||||
|
real fpks(20)
|
||||||
|
integer id(NS+ND) !NRZ values (+/-1) for Sync and Data
|
||||||
|
integer isync(48) !Long sync vector
|
||||||
|
integer ib13(13) !Barker 13 code
|
||||||
|
integer ihdr(11)
|
||||||
|
integer*8 n8
|
||||||
|
integer*2 iwave(NMAX) !Generated full-length waveform
|
||||||
|
integer*1 idat(7)
|
||||||
|
integer*1 decoded(KK),apmask(ND),cw(ND)
|
||||||
|
integer*1 hbits(412),bits(13)
|
||||||
|
logical reset
|
||||||
|
data ib13/1,1,1,1,1,-1,-1,1,1,-1,1,-1,1/
|
||||||
|
|
||||||
|
nargs=iargc()
|
||||||
|
if(nargs.lt.2) then
|
||||||
|
print*,'Usage: wspr5d [-a <data_dir>] [-f fMHz] file1 [file2 ...]'
|
||||||
|
go to 999
|
||||||
|
endif
|
||||||
|
iarg=1
|
||||||
|
data_dir="."
|
||||||
|
call getarg(iarg,arg)
|
||||||
|
if(arg(1:2).eq.'-a') then
|
||||||
|
call getarg(iarg+1,data_dir)
|
||||||
|
iarg=iarg+2
|
||||||
|
endif
|
||||||
|
call getarg(iarg,arg)
|
||||||
|
if(arg(1:2).eq.'-f') then
|
||||||
|
call getarg(iarg+1,arg)
|
||||||
|
read(arg,*) fMHz
|
||||||
|
iarg=iarg+2
|
||||||
|
endif
|
||||||
|
|
||||||
|
open(13,file=trim(data_dir)//'/ALL_WSPR.TXT',status='unknown', &
|
||||||
|
position='append')
|
||||||
|
maxn=8 !Default value
|
||||||
|
twopi=8.0*atan(1.0)
|
||||||
|
fs=NSPS*12000.0/NSPS0 !Sample rate
|
||||||
|
dt=1.0/fs !Sample interval (s)
|
||||||
|
tt=NSPS*dt !Duration of "itone" symbols (s)
|
||||||
|
ts=2*NSPS*dt !Duration of OQPSK symbols (s)
|
||||||
|
baud=1.0/tt !Keying rate for "itone" symbols (baud)
|
||||||
|
txt=NZ*dt !Transmission length (s)
|
||||||
|
|
||||||
|
do i=1,32 !Half-sine pulse shape
|
||||||
|
pp(i)=sin(0.5*(i-1)*twopi/(32))
|
||||||
|
enddo
|
||||||
|
n8=z'cbf089223a51'
|
||||||
|
do i=1,48
|
||||||
|
isync(i)=-1
|
||||||
|
if(iand(n8,1).eq.1) isync(i)=1
|
||||||
|
n8=n8/2
|
||||||
|
enddo
|
||||||
|
|
||||||
|
! Define array id() for sync symbols
|
||||||
|
id=0
|
||||||
|
do j=1,48 !First group of 48
|
||||||
|
id(2*j-1)=2*isync(j)
|
||||||
|
enddo
|
||||||
|
do j=1,13 !Barker 13 code
|
||||||
|
id(j+96)=2*ib13(j)
|
||||||
|
enddo
|
||||||
|
do j=1,48 !Second group of 48
|
||||||
|
id(2*j+109)=2*isync(j)
|
||||||
|
enddo
|
||||||
|
|
||||||
|
csync=0.
|
||||||
|
do j=1,205
|
||||||
|
if(abs(id(j)).eq.2) then
|
||||||
|
ia=nint((j-0.5)*N2)
|
||||||
|
ib=ia+N2-1
|
||||||
|
csync(ia:ib)=pp*id(j)/abs(id(j))
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
|
||||||
|
do ifile=iarg,nargs
|
||||||
|
call getarg(ifile,infile)
|
||||||
|
open(10,file=infile,status='old',access='stream')
|
||||||
|
j1=index(infile,'.c5')
|
||||||
|
j2=index(infile,'.wav')
|
||||||
|
if(j1.gt.0) then
|
||||||
|
read(10,end=999) fname,ntrmin,fMHz,c400
|
||||||
|
read(fname(8:11),*) nutc
|
||||||
|
write(datetime,'(i11)') nutc
|
||||||
|
else if(j2.gt.0) then
|
||||||
|
read(10,end=999) ihdr,iwave
|
||||||
|
read(infile(j2-4:j2-1),*) nutc
|
||||||
|
datetime=infile(j2-11:j2-1)
|
||||||
|
call wspr5_downsample(iwave,c400)
|
||||||
|
else
|
||||||
|
print*,'Wrong file format?'
|
||||||
|
go to 999
|
||||||
|
endif
|
||||||
|
close(10)
|
||||||
|
|
||||||
|
fa=100.0
|
||||||
|
fb=150.0
|
||||||
|
fs400=400.0
|
||||||
|
call getfc1(c400,fs400,fa,fb,fc1,xsnr) !First approx for freq
|
||||||
|
npeaks=5
|
||||||
|
call getfc2(c400,npeaks,fs400,fc1,fpks) !Refined freq
|
||||||
|
|
||||||
|
! do idf=1,npeaks ! consider the top npeak peaks
|
||||||
|
do idf=1,1 ! for genie-aided sync
|
||||||
|
fc1=125.0 ! genie provided
|
||||||
|
fc2=0.0 ! from the genie
|
||||||
|
! fc2=fpks(idf)
|
||||||
|
call downsample(c400,fc1+fc2,cd)
|
||||||
|
s2=sum(cd*conjg(cd))/(16*412)
|
||||||
|
cd=cd/sqrt(s2)
|
||||||
|
do is=0,0 ! dt search range is zeroed for genie-aided sync
|
||||||
|
idt=is/2
|
||||||
|
if( mod(is,2).eq. 1 ) idt=-(is+1)/2
|
||||||
|
xdt=real(22+idt)/22.222 - 1.0
|
||||||
|
ca=cshift(cd,22+idt)
|
||||||
|
zzsum=0.0
|
||||||
|
do iseq=3,4
|
||||||
|
if(iseq.eq.4) then
|
||||||
|
k=1-2*3
|
||||||
|
nseq=9
|
||||||
|
istep=3*4
|
||||||
|
else
|
||||||
|
k=1-2*iseq
|
||||||
|
nseq=iseq*3
|
||||||
|
istep=iseq*4
|
||||||
|
endif
|
||||||
|
do i=1,408,istep
|
||||||
|
j=(i+1)*16
|
||||||
|
if(iseq.eq.4) then
|
||||||
|
! phase=-1.18596900
|
||||||
|
! For now, average complex corr. coeffs over the entire frame to
|
||||||
|
! estimate phase
|
||||||
|
phase=atan2(imag(zzsum),real(zzsum))
|
||||||
|
k=k+3*2
|
||||||
|
call mskcohdet(nseq,ca(j),pp,id(k),softbits,phase)
|
||||||
|
else
|
||||||
|
k=k+iseq*2
|
||||||
|
call mskseqdet(nseq,ca(j),pp,id(k),softbits,1,zz)
|
||||||
|
zzsum=zzsum+zz
|
||||||
|
endif
|
||||||
|
sbits(i+1)=softbits(1)
|
||||||
|
sbits(i+2)=softbits(2)
|
||||||
|
if( id(k+1) .ne. 0 ) sbits(i+2)=id(k+1)*25
|
||||||
|
sbits(i+3)=softbits(3)
|
||||||
|
if( iseq .ge. 2 ) then
|
||||||
|
sbits(i+5)=softbits(4)
|
||||||
|
sbits(i+6)=softbits(5)
|
||||||
|
if( id(k+3) .ne. 0 ) sbits(i+6)=id(k+3)*25
|
||||||
|
sbits(i+7)=softbits(6)
|
||||||
|
if( iseq .ge. 3 ) then
|
||||||
|
sbits(i+9)=softbits(7)
|
||||||
|
sbits(i+10)=softbits(8)
|
||||||
|
if( id(k+5) .ne. 0 ) sbits(i+10)=id(k+5)*25
|
||||||
|
sbits(i+11)=softbits(9)
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
j=1
|
||||||
|
do i=1,205
|
||||||
|
if( abs(id(i)) .ne. 2 ) then
|
||||||
|
rxdata(j)=sbits(2*i-1)
|
||||||
|
j=j+1
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
do i=1,204
|
||||||
|
rxdata(j)=sbits(2*i)
|
||||||
|
j=j+1
|
||||||
|
enddo
|
||||||
|
rxav=sum(rxdata)/ND
|
||||||
|
rx2av=sum(rxdata*rxdata)/ND
|
||||||
|
rxsig=sqrt(rx2av-rxav*rxav)
|
||||||
|
rxdata=rxdata/rxsig
|
||||||
|
sigma=1.20
|
||||||
|
llr=2*rxdata/(sigma*sigma)
|
||||||
|
apmask=0
|
||||||
|
max_iterations=40
|
||||||
|
|
||||||
|
ifer=0
|
||||||
|
call bpdecode300(llr,apmask,max_iterations,decoded,niterations,cw)
|
||||||
|
! niterations will be equal to the Hamming distance between hard received word and the codeword
|
||||||
|
nhardmin=0
|
||||||
|
if(niterations.lt.0) call osd300(llr,apmask,5,decoded,cw,nhardmin,dmin)
|
||||||
|
if(nhardmin.gt.0) niterations=nhardmin
|
||||||
|
nbadcrc=0
|
||||||
|
call chkcrc10(decoded,nbadcrc)
|
||||||
|
if(nbadcrc.ne.0) ifer=1
|
||||||
|
|
||||||
|
if( ifer.eq.0 ) then
|
||||||
|
write(cbits,1200) decoded(1:50)
|
||||||
|
1200 format(50i1)
|
||||||
|
read(cbits,1202) idat
|
||||||
|
1202 format(6b8,b2)
|
||||||
|
idat(7)=ishft(idat(7),6)
|
||||||
|
call wqdecode(idat,message,itype)
|
||||||
|
nsnr=nint(xsnr)
|
||||||
|
! freq=fMHz + 1.d-6*(fc1+fc2)
|
||||||
|
freq=fc1+fc2
|
||||||
|
nfdot=0
|
||||||
|
write(13,1210) datetime,0,nsnr,xdt,freq,message,nfdot
|
||||||
|
1210 format(a11,2i4,f6.2,f12.7,2x,a22,i3)
|
||||||
|
write(*,1212) datetime(8:11),nsnr,xdt,freq,nfdot,message,'*',idf,nseq,is,iseq,niterations
|
||||||
|
!1212 format(a4,i4,f5.1,f11.6,i3,2x,a22,a1,i3,i3,i3,i4)
|
||||||
|
1212 format(a4,i4,f8.3,f8.3,i3,2x,a22,a1,i3,i3,i3,i3,i4)
|
||||||
|
goto 888
|
||||||
|
endif
|
||||||
|
enddo !iseq
|
||||||
|
enddo
|
||||||
|
enddo
|
||||||
|
888 continue
|
||||||
|
enddo
|
||||||
|
|
||||||
|
write(*,1120)
|
||||||
|
1120 format("<DecodeFinished>")
|
||||||
|
|
||||||
|
999 end program wspr5d
|
||||||
|
|
||||||
|
subroutine getmetric(ib,ps,xmet)
|
||||||
|
real ps(0:511)
|
||||||
|
xm1=0
|
||||||
|
xm0=0
|
||||||
|
do i=0,511
|
||||||
|
if( iand(i/ib,1) .eq. 1 .and. ps(i) .gt. xm1 ) xm1=ps(i)
|
||||||
|
if( iand(i/ib,1) .eq. 0 .and. ps(i) .gt. xm0 ) xm0=ps(i)
|
||||||
|
enddo
|
||||||
|
xmet=xm1-xm0
|
||||||
|
return
|
||||||
|
end subroutine getmetric
|
||||||
|
|
||||||
|
subroutine mskseqdet(ns,cdat,pp,bsync,softbits,ncoh,zz)
|
||||||
|
!
|
||||||
|
! Detect sequences of 3, 6, or 9 bits (ns).
|
||||||
|
! Sync bits are assumed to be known.
|
||||||
|
!
|
||||||
|
complex cdat(16*12),cbest(16*12),cideal(16*12)
|
||||||
|
complex cdf(16*12),cfac,zz
|
||||||
|
real cm(0:511),cmbest(0:511)
|
||||||
|
real pp(32),softbits(9)
|
||||||
|
integer bit(13),bestbits(13),sgn(13)
|
||||||
|
integer bsync(7)
|
||||||
|
|
||||||
|
twopi=8.0*atan(1.0)
|
||||||
|
dt=30.0*18.0/12000.0
|
||||||
|
cmax=0;
|
||||||
|
fbest=0.0;
|
||||||
|
np=2**ns-1
|
||||||
|
idfmax=40
|
||||||
|
if( ncoh .eq. 1 ) idfmax=0
|
||||||
|
do idf=0,idfmax
|
||||||
|
if( mod(idf,2).eq.0 ) deltaf=idf/2*0.02
|
||||||
|
if( mod(idf,2).eq.1 ) deltaf=-(idf+1)/2*0.02
|
||||||
|
dphi=twopi*deltaf*dt
|
||||||
|
cfac=cmplx(cos(dphi),sin(dphi))
|
||||||
|
cdf=1.0
|
||||||
|
do i=2,16*(ns-1)
|
||||||
|
cdf(i)=cdf(i-1)*cfac
|
||||||
|
enddo
|
||||||
|
|
||||||
|
cm=0
|
||||||
|
ibflag=0
|
||||||
|
do i=0,np
|
||||||
|
bit(1)=(bsync(1)+2)/4
|
||||||
|
bit(2)=iand(i/(2**(ns-1)),1)
|
||||||
|
bit(3)=iand(i/(2**(ns-2)),1)
|
||||||
|
if( bsync(2).ne.0 ) then ! force the barker bits
|
||||||
|
bit(3)=(bsync(2)+2)/4
|
||||||
|
endif
|
||||||
|
bit(4)=iand(i/(2**(ns-3)),1)
|
||||||
|
bit(5)=(bsync(3)+2)/4
|
||||||
|
|
||||||
|
if( ns .ge. 6 ) then
|
||||||
|
bit(6)=iand(i/(2**(ns-4)),1)
|
||||||
|
bit(7)=iand(i/(2**(ns-5)),1)
|
||||||
|
if( bsync(4).ne.0 ) then ! force the barker bits
|
||||||
|
bit(7)=(bsync(4)+2)/4
|
||||||
|
endif
|
||||||
|
bit(8)=iand(i/(2**(ns-6)),1)
|
||||||
|
bit(9)=(bsync(5)+2)/4
|
||||||
|
if( ns .eq. 9 ) then
|
||||||
|
bit(10)=iand(i/4,1)
|
||||||
|
bit(11)=iand(i/2,1)
|
||||||
|
if( bsync(6).ne.0 ) then ! force the barker bits
|
||||||
|
bit(11)=(bsync(6)+2)/4
|
||||||
|
endif
|
||||||
|
bit(12)=iand(i/1,1)
|
||||||
|
bit(13)=(bsync(7)+2)/4
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
sgn=2*bit-1
|
||||||
|
cideal(1:16) =cmplx(sgn(1)*pp(17:32),sgn(2)*pp(1:16))
|
||||||
|
cideal(17:32) =cmplx(sgn(3)*pp(1:16),sgn(2)*pp(17:32))
|
||||||
|
cideal(33:48) =cmplx(sgn(3)*pp(17:32),sgn(4)*pp(1:16))
|
||||||
|
cideal(49:64) =cmplx(sgn(5)*pp(1:16),sgn(4)*pp(17:32))
|
||||||
|
if( ns .ge. 6 ) then
|
||||||
|
cideal(65:80) =cmplx(sgn(5)*pp(17:32),sgn(6)*pp(1:16))
|
||||||
|
cideal(81:96) =cmplx(sgn(7)*pp(1:16),sgn(6)*pp(17:32))
|
||||||
|
cideal(97:112) =cmplx(sgn(7)*pp(17:32),sgn(8)*pp(1:16))
|
||||||
|
cideal(113:128)=cmplx(sgn(9)*pp(1:16),sgn(8)*pp(17:32))
|
||||||
|
if( ns .eq. 9 ) then
|
||||||
|
cideal(129:144) =cmplx(sgn(9)*pp(17:32),sgn(10)*pp(1:16))
|
||||||
|
cideal(145:160) =cmplx(sgn(11)*pp(1:16),sgn(10)*pp(17:32))
|
||||||
|
cideal(161:176) =cmplx(sgn(11)*pp(17:32),sgn(12)*pp(1:16))
|
||||||
|
cideal(177:192)=cmplx(sgn(13)*pp(1:16),sgn(12)*pp(17:32))
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
cideal=cideal*cdf
|
||||||
|
cm(i)=abs(sum(cdat(1:64*ns/3)*conjg(cideal(1:64*ns/3))))/1.e3
|
||||||
|
if( cm(i) .gt. cmax ) then
|
||||||
|
ibflag=1
|
||||||
|
cmax=cm(i)
|
||||||
|
bestbits=bit
|
||||||
|
cbest=cideal
|
||||||
|
fbest=deltaf
|
||||||
|
zz=sum(cdat*conjg(cbest))/1.e3
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
if( ibflag .eq. 1 ) then ! new best found
|
||||||
|
cmbest=cm
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
softbits=0.0
|
||||||
|
call getmetric(1,cmbest,softbits(ns))
|
||||||
|
call getmetric(2,cmbest,softbits(ns-1))
|
||||||
|
call getmetric(4,cmbest,softbits(ns-2))
|
||||||
|
if( ns .ge. 6 ) then
|
||||||
|
call getmetric(8,cmbest,softbits(ns-3))
|
||||||
|
call getmetric(16,cmbest,softbits(ns-4))
|
||||||
|
call getmetric(32,cmbest,softbits(ns-5))
|
||||||
|
if( ns .eq. 9 ) then
|
||||||
|
call getmetric(64,cmbest,softbits(3))
|
||||||
|
call getmetric(128,cmbest,softbits(2))
|
||||||
|
call getmetric(256,cmbest,softbits(1))
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
end subroutine mskseqdet
|
||||||
|
|
||||||
|
subroutine mskcohdet(ns,cdat,pp,bsync,softbits,phase)
|
||||||
|
!
|
||||||
|
! Coherent demodulate blocks of 9 bits (ns).
|
||||||
|
!
|
||||||
|
complex cdat(16*12),crot(16*12)
|
||||||
|
real pp(32),softbits(9)
|
||||||
|
|
||||||
|
np=2**ns-1
|
||||||
|
|
||||||
|
softbits=0.0
|
||||||
|
crot=cdat*cmplx(cos(phase),-sin(phase))
|
||||||
|
softbits(1)=sum(imag(crot(1:32)*pp))
|
||||||
|
softbits(2)=sum(real(crot(17:48)*pp))
|
||||||
|
softbits(3)=sum(imag(crot(33:64)*pp))
|
||||||
|
softbits(4)=sum(imag(crot(65:96)*pp))
|
||||||
|
softbits(5)=sum(real(crot(81:112)*pp))
|
||||||
|
softbits(6)=sum(imag(crot(97:128)*pp))
|
||||||
|
softbits(7)=sum(imag(crot(129:160)*pp))
|
||||||
|
softbits(8)=sum(real(crot(145:176)*pp))
|
||||||
|
softbits(9)=sum(imag(crot(161:192)*pp))
|
||||||
|
softbits=softbits/64.
|
||||||
|
end subroutine mskcohdet
|
||||||
|
|
||||||
|
subroutine downsample(ci,f0,co)
|
||||||
|
parameter(NI=412*288,NO=NI/18)
|
||||||
|
complex ci(0:NI-1),ct(0:NI-1)
|
||||||
|
complex co(0:NO-1)
|
||||||
|
|
||||||
|
df=400.0/NI
|
||||||
|
ct=ci
|
||||||
|
call four2a(ct,NI,1,-1,1) !c2c FFT to freq domain
|
||||||
|
i0=nint(f0/df)
|
||||||
|
co=0.0
|
||||||
|
co(0)=ct(i0)
|
||||||
|
! b=3.0 !optimized for sequence detection
|
||||||
|
b=6.0
|
||||||
|
do i=1,NO/2
|
||||||
|
arg=(i*df/b)**2
|
||||||
|
filt=exp(-arg)
|
||||||
|
co(i)=ct(i0+i)*filt
|
||||||
|
co(NO-i)=ct(i0-i)*filt
|
||||||
|
enddo
|
||||||
|
co=co/NO
|
||||||
|
call four2a(co,NO,1,1,1) !c2c FFT back to time domain
|
||||||
|
return
|
||||||
|
end subroutine downsample
|
||||||
|
|
||||||
|
subroutine getfc1(c,fs,fa,fb,fc1,xsnr)
|
||||||
|
|
||||||
|
! include 'wsprlf_params.f90'
|
||||||
|
parameter (NZ=288*412)
|
||||||
|
parameter (NSPS=288)
|
||||||
|
parameter (N2=2*NSPS)
|
||||||
|
parameter (NFFT1=16*NSPS)
|
||||||
|
parameter (NH1=NFFT1/2)
|
||||||
|
|
||||||
|
complex c(0:NZ-1) !Complex waveform
|
||||||
|
complex c2(0:NFFT1-1) !Short spectra
|
||||||
|
real s(-NH1+1:NH1) !Coarse spectrum
|
||||||
|
nspec=NZ/N2
|
||||||
|
df1=fs/NFFT1
|
||||||
|
s=0.
|
||||||
|
do k=1,nspec
|
||||||
|
ia=(k-1)*N2
|
||||||
|
ib=ia+N2-1
|
||||||
|
c2(0:N2-1)=c(ia:ib)
|
||||||
|
c2(N2:)=0.
|
||||||
|
call four2a(c2,NFFT1,1,-1,1)
|
||||||
|
do i=0,NFFT1-1
|
||||||
|
j=i
|
||||||
|
if(j.gt.NH1) j=j-NFFT1
|
||||||
|
s(j)=s(j) + real(c2(i))**2 + aimag(c2(i))**2
|
||||||
|
enddo
|
||||||
|
enddo
|
||||||
|
! call smo121(s,NFFT1)
|
||||||
|
smax=0.
|
||||||
|
ipk=0
|
||||||
|
fc1=0.
|
||||||
|
ia=nint(fa/df1)
|
||||||
|
ib=nint(fb/df1)
|
||||||
|
do i=ia,ib
|
||||||
|
f=i*df1
|
||||||
|
if(s(i).gt.smax) then
|
||||||
|
smax=s(i)
|
||||||
|
ipk=i
|
||||||
|
fc1=f
|
||||||
|
endif
|
||||||
|
! write(51,3001) f,s(i),db(s(i))
|
||||||
|
! 3001 format(f10.3,e12.3,f10.3)
|
||||||
|
enddo
|
||||||
|
|
||||||
|
! The following is for testing SNR calibration:
|
||||||
|
sp3n=(s(ipk-1)+s(ipk)+s(ipk+1)) !Sig + 3*noise
|
||||||
|
base=(sum(s)-sp3n)/(NFFT1-3.0) !Noise per bin
|
||||||
|
psig=sp3n-3*base !Sig only
|
||||||
|
pnoise=(2500.0/df1)*base !Noise in 2500 Hz
|
||||||
|
xsnr=db(psig/pnoise)
|
||||||
|
xsnr=xsnr+5.0
|
||||||
|
return
|
||||||
|
end subroutine getfc1
|
||||||
|
|
||||||
|
subroutine getfc2(c,npeaks,fs,fc1,fpks)
|
||||||
|
|
||||||
|
! include 'wsprlf_params.f90'
|
||||||
|
parameter (NZ=288*412)
|
||||||
|
parameter (NSPS=288)
|
||||||
|
parameter (N2=2*NSPS)
|
||||||
|
parameter (NFFT1=16*NSPS)
|
||||||
|
parameter (NH1=NFFT1/2)
|
||||||
|
|
||||||
|
complex c(0:NZ-1) !Complex waveform
|
||||||
|
complex cs(0:NZ-1) !For computing spectrum
|
||||||
|
real a(5)
|
||||||
|
real freqs(413),sp2(413),fpks(npeaks)
|
||||||
|
integer pkloc(1)
|
||||||
|
|
||||||
|
df=fs/NZ
|
||||||
|
baud=fs/NSPS
|
||||||
|
a(1)=-fc1
|
||||||
|
a(2:5)=0.
|
||||||
|
call twkfreq1(c,NZ,fs,a,cs) !Mix down by fc1
|
||||||
|
|
||||||
|
! Filter, square, then FFT to get refined carrier frequency fc2.
|
||||||
|
call four2a(cs,NZ,1,-1,1) !To freq domain
|
||||||
|
|
||||||
|
ia=nint(0.75*baud/df)
|
||||||
|
cs(ia:NZ-1-ia)=0. !Save only freqs around fc1
|
||||||
|
! do i=1,NZ/2
|
||||||
|
! filt=1/(1+((i*df)**2/(0.50*baud)**2)**8)
|
||||||
|
! cs(i)=cs(i)*filt
|
||||||
|
! cs(NZ+1-i)=cs(NZ+1-i)*filt
|
||||||
|
! enddo
|
||||||
|
call four2a(cs,NZ,1,1,1) !Back to time domain
|
||||||
|
cs=cs/NZ
|
||||||
|
cs=cs*cs !Square the data
|
||||||
|
call four2a(cs,NZ,1,-1,1) !Compute squared spectrum
|
||||||
|
! Find two peaks separated by baud
|
||||||
|
pmax=0.
|
||||||
|
fc2=0.
|
||||||
|
! ja=nint(0.3*baud/df)
|
||||||
|
ja=nint(0.5*baud/df)
|
||||||
|
k=1
|
||||||
|
sp2=0.0
|
||||||
|
do j=-ja,ja
|
||||||
|
f2=j*df
|
||||||
|
ia=nint((f2-0.5*baud)/df)
|
||||||
|
if(ia.lt.0) ia=ia+NZ
|
||||||
|
ib=nint((f2+0.5*baud)/df)
|
||||||
|
p=real(cs(ia))**2 + aimag(cs(ia))**2 + &
|
||||||
|
real(cs(ib))**2 + aimag(cs(ib))**2
|
||||||
|
if(p.gt.pmax) then
|
||||||
|
pmax=p
|
||||||
|
fc2=0.5*f2
|
||||||
|
endif
|
||||||
|
freqs(k)=0.5*f2
|
||||||
|
sp2(k)=p
|
||||||
|
k=k+1
|
||||||
|
! write(52,1200) f2,p,db(p)
|
||||||
|
!1200 format(f10.3,2f15.3)
|
||||||
|
enddo
|
||||||
|
|
||||||
|
do i=1,npeaks
|
||||||
|
pkloc=maxloc(sp2)
|
||||||
|
ipk=pkloc(1)
|
||||||
|
fpks(i)=freqs(ipk)
|
||||||
|
ipk0=max(1,ipk-2)
|
||||||
|
ipk1=min(413,ipk+2)
|
||||||
|
! ipk0=ipk
|
||||||
|
! ipk1=ipk
|
||||||
|
sp2(ipk0:ipk1)=0.0
|
||||||
|
enddo
|
||||||
|
return
|
||||||
|
end subroutine getfc2
|
||||||
@@ -0,0 +1,523 @@
|
|||||||
|
#include "widegraph.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QSettings>
|
||||||
|
#include "ui_widegraph.h"
|
||||||
|
#include "commons.h"
|
||||||
|
#include "Configuration.hpp"
|
||||||
|
#include "MessageBox.hpp"
|
||||||
|
#include "SettingsGroup.hpp"
|
||||||
|
#include "moc_widegraph.cpp"
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
auto user_defined = QObject::tr ("User Defined");
|
||||||
|
float swide[MAX_SCREENSIZE];
|
||||||
|
}
|
||||||
|
|
||||||
|
WideGraph::WideGraph(QSettings * settings, QWidget *parent) :
|
||||||
|
QDialog(parent),
|
||||||
|
ui(new Ui::WideGraph),
|
||||||
|
m_settings (settings),
|
||||||
|
m_palettes_path {":/Palettes"},
|
||||||
|
m_ntr0 {0},
|
||||||
|
m_n {0},
|
||||||
|
m_bHaveTransmitted {false}
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
|
||||||
|
setWindowTitle (QApplication::applicationName () + " - " + tr ("Wide Graph"));
|
||||||
|
setWindowFlags (Qt::WindowCloseButtonHint | Qt::WindowMinimizeButtonHint);
|
||||||
|
setMaximumWidth (MAX_SCREENSIZE);
|
||||||
|
setMaximumHeight (880);
|
||||||
|
|
||||||
|
ui->widePlot->setCursor(Qt::CrossCursor);
|
||||||
|
ui->widePlot->setMaximumHeight(800);
|
||||||
|
ui->widePlot->setCurrent(false);
|
||||||
|
|
||||||
|
connect(ui->widePlot, SIGNAL(freezeDecode1(int)),this,
|
||||||
|
SLOT(wideFreezeDecode(int)));
|
||||||
|
|
||||||
|
connect(ui->widePlot, SIGNAL(setFreq1(int,int)),this,
|
||||||
|
SLOT(setFreq2(int,int)));
|
||||||
|
|
||||||
|
{
|
||||||
|
//Restore user's settings
|
||||||
|
SettingsGroup g {m_settings, "WideGraph"};
|
||||||
|
restoreGeometry (m_settings->value ("geometry", saveGeometry ()).toByteArray ());
|
||||||
|
ui->widePlot->setPlotZero(m_settings->value("PlotZero", 0).toInt());
|
||||||
|
ui->widePlot->setPlotGain(m_settings->value("PlotGain", 0).toInt());
|
||||||
|
ui->widePlot->setPlot2dGain(m_settings->value("Plot2dGain", 0).toInt());
|
||||||
|
ui->widePlot->setPlot2dZero(m_settings->value("Plot2dZero", 0).toInt());
|
||||||
|
ui->zeroSlider->setValue(ui->widePlot->plotZero());
|
||||||
|
ui->gainSlider->setValue(ui->widePlot->plotGain());
|
||||||
|
ui->gain2dSlider->setValue(ui->widePlot->plot2dGain());
|
||||||
|
ui->zero2dSlider->setValue(ui->widePlot->plot2dZero());
|
||||||
|
int n = m_settings->value("BinsPerPixel",2).toInt();
|
||||||
|
m_bFlatten=m_settings->value("Flatten",true).toBool();
|
||||||
|
m_bRef=m_settings->value("UseRef",false).toBool();
|
||||||
|
ui->cbFlatten->setChecked(m_bFlatten);
|
||||||
|
ui->widePlot->setFlatten(m_bFlatten,m_bRef);
|
||||||
|
ui->cbRef->setChecked(m_bRef);
|
||||||
|
ui->widePlot->setBreadth(m_settings->value("PlotWidth",1000).toInt());
|
||||||
|
ui->bppSpinBox->setValue(n);
|
||||||
|
m_nsmo=m_settings->value("SmoothYellow",1).toInt();
|
||||||
|
ui->smoSpinBox->setValue(m_nsmo);
|
||||||
|
m_Percent2DScreen=m_settings->value("Percent2D",30).toInt();
|
||||||
|
m_waterfallAvg = m_settings->value("WaterfallAvg",5).toInt();
|
||||||
|
ui->waterfallAvgSpinBox->setValue(m_waterfallAvg);
|
||||||
|
ui->widePlot->setWaterfallAvg(m_waterfallAvg);
|
||||||
|
ui->widePlot->setCurrent(m_settings->value("Current",false).toBool());
|
||||||
|
ui->widePlot->setCumulative(m_settings->value("Cumulative",true).toBool());
|
||||||
|
ui->widePlot->setLinearAvg(m_settings->value("LinearAvg",false).toBool());
|
||||||
|
ui->widePlot->setReference(m_settings->value("Reference",false).toBool());
|
||||||
|
if(ui->widePlot->current()) ui->spec2dComboBox->setCurrentIndex(0);
|
||||||
|
if(ui->widePlot->cumulative()) ui->spec2dComboBox->setCurrentIndex(1);
|
||||||
|
if(ui->widePlot->linearAvg()) ui->spec2dComboBox->setCurrentIndex(2);
|
||||||
|
if(ui->widePlot->Reference()) ui->spec2dComboBox->setCurrentIndex(3);
|
||||||
|
int nbpp=m_settings->value("BinsPerPixel",2).toInt();
|
||||||
|
ui->widePlot->setBinsPerPixel(nbpp);
|
||||||
|
ui->sbPercent2dPlot->setValue(m_Percent2DScreen);
|
||||||
|
ui->widePlot->setStartFreq(m_settings->value("StartFreq",0).toInt());
|
||||||
|
ui->fStartSpinBox->setValue(ui->widePlot->startFreq());
|
||||||
|
m_waterfallPalette=m_settings->value("WaterfallPalette","Default").toString();
|
||||||
|
m_userPalette = WFPalette {m_settings->value("UserPalette").value<WFPalette::Colours> ()};
|
||||||
|
m_fMinPerBand = m_settings->value ("FminPerBand").toHash ();
|
||||||
|
setRxRange ();
|
||||||
|
ui->controls_widget->setVisible(!m_settings->value("HideControls",false).toBool());
|
||||||
|
ui->cbControls->setChecked(!m_settings->value("HideControls",false).toBool());
|
||||||
|
}
|
||||||
|
|
||||||
|
int index=0;
|
||||||
|
for (QString const& file:
|
||||||
|
m_palettes_path.entryList(QDir::NoDotAndDotDot |
|
||||||
|
QDir::System | QDir::Hidden |
|
||||||
|
QDir::AllDirs | QDir::Files,
|
||||||
|
QDir::DirsFirst)) {
|
||||||
|
QString t=file.mid(0,file.length()-4);
|
||||||
|
ui->paletteComboBox->addItem(t);
|
||||||
|
if(t==m_waterfallPalette) ui->paletteComboBox->setCurrentIndex(index);
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
ui->paletteComboBox->addItem (user_defined);
|
||||||
|
if (user_defined == m_waterfallPalette) ui->paletteComboBox->setCurrentIndex(index);
|
||||||
|
readPalette ();
|
||||||
|
}
|
||||||
|
|
||||||
|
WideGraph::~WideGraph ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void WideGraph::closeEvent (QCloseEvent * e)
|
||||||
|
{
|
||||||
|
saveSettings ();
|
||||||
|
QDialog::closeEvent (e);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WideGraph::saveSettings() //saveSettings
|
||||||
|
{
|
||||||
|
SettingsGroup g {m_settings, "WideGraph"};
|
||||||
|
m_settings->setValue ("geometry", saveGeometry ());
|
||||||
|
m_settings->setValue ("PlotZero", ui->widePlot->plotZero());
|
||||||
|
m_settings->setValue ("PlotGain", ui->widePlot->plotGain());
|
||||||
|
m_settings->setValue ("Plot2dGain", ui->widePlot->plot2dGain());
|
||||||
|
m_settings->setValue ("Plot2dZero", ui->widePlot->plot2dZero());
|
||||||
|
m_settings->setValue ("PlotWidth", ui->widePlot->plotWidth ());
|
||||||
|
m_settings->setValue ("BinsPerPixel", ui->bppSpinBox->value ());
|
||||||
|
m_settings->setValue ("SmoothYellow", ui->smoSpinBox->value ());
|
||||||
|
m_settings->setValue ("Percent2D",m_Percent2DScreen);
|
||||||
|
m_settings->setValue ("WaterfallAvg", ui->waterfallAvgSpinBox->value ());
|
||||||
|
m_settings->setValue ("Current", ui->widePlot->current());
|
||||||
|
m_settings->setValue ("Cumulative", ui->widePlot->cumulative());
|
||||||
|
m_settings->setValue ("LinearAvg", ui->widePlot->linearAvg());
|
||||||
|
m_settings->setValue ("Reference", ui->widePlot->Reference());
|
||||||
|
m_settings->setValue ("BinsPerPixel", ui->widePlot->binsPerPixel ());
|
||||||
|
m_settings->setValue ("StartFreq", ui->widePlot->startFreq ());
|
||||||
|
m_settings->setValue ("WaterfallPalette", m_waterfallPalette);
|
||||||
|
m_settings->setValue ("UserPalette", QVariant::fromValue (m_userPalette.colours ()));
|
||||||
|
m_settings->setValue("Flatten",m_bFlatten);
|
||||||
|
m_settings->setValue("UseRef",m_bRef);
|
||||||
|
m_settings->setValue ("HideControls", ui->controls_widget->isHidden ());
|
||||||
|
m_settings->setValue ("FminPerBand", m_fMinPerBand);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WideGraph::drawRed(int ia, int ib)
|
||||||
|
{
|
||||||
|
ui->widePlot->drawRed(ia,ib,swide);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WideGraph::dataSink2(float s[], float df3, int ihsym, int ndiskdata) //dataSink2
|
||||||
|
{
|
||||||
|
static float splot[NSMAX];
|
||||||
|
int nbpp = ui->widePlot->binsPerPixel();
|
||||||
|
|
||||||
|
//Average spectra over specified number, m_waterfallAvg
|
||||||
|
if (m_n==0) {
|
||||||
|
for (int i=0; i<NSMAX; i++)
|
||||||
|
splot[i]=s[i];
|
||||||
|
} else {
|
||||||
|
for (int i=0; i<NSMAX; i++)
|
||||||
|
splot[i] += s[i];
|
||||||
|
}
|
||||||
|
m_n++;
|
||||||
|
|
||||||
|
if (m_n>=m_waterfallAvg) {
|
||||||
|
for (int i=0; i<NSMAX; i++)
|
||||||
|
splot[i] /= m_n; //Normalize the average
|
||||||
|
m_n=0;
|
||||||
|
int i=int(ui->widePlot->startFreq()/df3 + 0.5);
|
||||||
|
int jz=5000.0/(nbpp*df3);
|
||||||
|
if(jz>MAX_SCREENSIZE) jz=MAX_SCREENSIZE;
|
||||||
|
m_jz=jz;
|
||||||
|
for (int j=0; j<jz; j++) {
|
||||||
|
float ss=0.0;
|
||||||
|
float smax=0;
|
||||||
|
for (int k=0; k<nbpp; k++) {
|
||||||
|
float sp=splot[i++];
|
||||||
|
ss += sp;
|
||||||
|
smax=qMax(smax,sp);
|
||||||
|
}
|
||||||
|
// swide[j]=nbpp*smax;
|
||||||
|
swide[j]=nbpp*ss;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Time according to this computer
|
||||||
|
qint64 ms = QDateTime::currentMSecsSinceEpoch() % 86400000;
|
||||||
|
int ntr = (ms/1000) % m_TRperiod;
|
||||||
|
if((ndiskdata && ihsym <= m_waterfallAvg) || (!ndiskdata && ntr<m_ntr0)) {
|
||||||
|
float flagValue=1.0e30;
|
||||||
|
if(m_bHaveTransmitted) flagValue=2.0e30;
|
||||||
|
for(int i=0; i<MAX_SCREENSIZE; i++) {
|
||||||
|
swide[i] = flagValue;
|
||||||
|
}
|
||||||
|
for(int i=0; i<NSMAX; i++) {
|
||||||
|
splot[i] = flagValue;
|
||||||
|
}
|
||||||
|
m_bHaveTransmitted=false;
|
||||||
|
}
|
||||||
|
m_ntr0=ntr;
|
||||||
|
ui->widePlot->draw(swide,true,false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WideGraph::on_bppSpinBox_valueChanged(int n) //bpp
|
||||||
|
{
|
||||||
|
ui->widePlot->setBinsPerPixel(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WideGraph::on_waterfallAvgSpinBox_valueChanged(int n) //Navg
|
||||||
|
{
|
||||||
|
m_waterfallAvg = n;
|
||||||
|
ui->widePlot->setWaterfallAvg(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WideGraph::keyPressEvent(QKeyEvent *e) //F11, F12
|
||||||
|
{
|
||||||
|
switch(e->key())
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
case Qt::Key_F11:
|
||||||
|
n=11;
|
||||||
|
if(e->modifiers() & Qt::ControlModifier) n+=100;
|
||||||
|
emit f11f12(n);
|
||||||
|
break;
|
||||||
|
case Qt::Key_F12:
|
||||||
|
n=12;
|
||||||
|
if(e->modifiers() & Qt::ControlModifier) n+=100;
|
||||||
|
emit f11f12(n);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
QDialog::keyPressEvent (e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WideGraph::setRxFreq(int n) //setRxFreq
|
||||||
|
{
|
||||||
|
ui->widePlot->setRxFreq(n);
|
||||||
|
ui->widePlot->draw(swide,false,false);
|
||||||
|
}
|
||||||
|
|
||||||
|
int WideGraph::rxFreq() //rxFreq
|
||||||
|
{
|
||||||
|
return ui->widePlot->rxFreq();
|
||||||
|
}
|
||||||
|
|
||||||
|
int WideGraph::nStartFreq() //nStartFreq
|
||||||
|
{
|
||||||
|
return ui->widePlot->startFreq();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WideGraph::wideFreezeDecode(int n) //wideFreezeDecode
|
||||||
|
{
|
||||||
|
emit freezeDecode2(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WideGraph::setRxRange ()
|
||||||
|
{
|
||||||
|
ui->widePlot->setRxRange (Fmin ());
|
||||||
|
ui->widePlot->DrawOverlay();
|
||||||
|
ui->widePlot->update();
|
||||||
|
}
|
||||||
|
|
||||||
|
int WideGraph::Fmin() //Fmin
|
||||||
|
{
|
||||||
|
return "60m" == m_rxBand ? 0 : m_fMinPerBand.value (m_rxBand, 2500).toUInt ();
|
||||||
|
}
|
||||||
|
|
||||||
|
int WideGraph::Fmax() //Fmax
|
||||||
|
{
|
||||||
|
return std::min(5000,ui->widePlot->Fmax());
|
||||||
|
}
|
||||||
|
|
||||||
|
int WideGraph::fSpan()
|
||||||
|
{
|
||||||
|
return ui->widePlot->fSpan ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WideGraph::setPeriod(int ntrperiod, int nsps) //SetPeriod
|
||||||
|
{
|
||||||
|
m_TRperiod=ntrperiod;
|
||||||
|
m_nsps=nsps;
|
||||||
|
ui->widePlot->setNsps(ntrperiod, nsps);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WideGraph::setTxFreq(int n) //setTxFreq
|
||||||
|
{
|
||||||
|
emit setXIT2(n);
|
||||||
|
ui->widePlot->setTxFreq(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WideGraph::setMode(QString mode) //setMode
|
||||||
|
{
|
||||||
|
m_mode=mode;
|
||||||
|
ui->fSplitSpinBox->setEnabled(m_mode=="JT9+JT65");
|
||||||
|
ui->widePlot->setMode(mode);
|
||||||
|
ui->widePlot->DrawOverlay();
|
||||||
|
ui->widePlot->update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WideGraph::setSubMode(int n) //setSubMode
|
||||||
|
{
|
||||||
|
m_nSubMode=n;
|
||||||
|
ui->widePlot->setSubMode(n);
|
||||||
|
ui->widePlot->DrawOverlay();
|
||||||
|
ui->widePlot->update();
|
||||||
|
}
|
||||||
|
void WideGraph::setModeTx(QString modeTx) //setModeTx
|
||||||
|
{
|
||||||
|
m_modeTx=modeTx;
|
||||||
|
ui->widePlot->setModeTx(modeTx);
|
||||||
|
ui->widePlot->DrawOverlay();
|
||||||
|
ui->widePlot->update();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Current-Cumulative-Yellow
|
||||||
|
void WideGraph::on_spec2dComboBox_currentIndexChanged(const QString &arg1)
|
||||||
|
{
|
||||||
|
ui->widePlot->setCurrent(false);
|
||||||
|
ui->widePlot->setCumulative(false);
|
||||||
|
ui->widePlot->setLinearAvg(false);
|
||||||
|
ui->widePlot->setReference(false);
|
||||||
|
ui->smoSpinBox->setEnabled(false);
|
||||||
|
if(arg1=="Current") ui->widePlot->setCurrent(true);
|
||||||
|
if(arg1=="Cumulative") ui->widePlot->setCumulative(true);
|
||||||
|
if(arg1=="Linear Avg") {
|
||||||
|
ui->widePlot->setLinearAvg(true);
|
||||||
|
ui->smoSpinBox->setEnabled(true);
|
||||||
|
}
|
||||||
|
if(arg1=="Reference") {
|
||||||
|
ui->widePlot->setReference(true);
|
||||||
|
}
|
||||||
|
replot();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WideGraph::on_fSplitSpinBox_valueChanged(int n) //fSplit
|
||||||
|
{
|
||||||
|
if (m_rxBand != "60m") m_fMinPerBand[m_rxBand] = n;
|
||||||
|
setRxRange ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WideGraph::setFreq2(int rxFreq, int txFreq) //setFreq2
|
||||||
|
{
|
||||||
|
emit setFreq3(rxFreq,txFreq);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WideGraph::setDialFreq(double d) //setDialFreq
|
||||||
|
{
|
||||||
|
ui->widePlot->setDialFreq(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WideGraph::setRxBand (QString const& band)
|
||||||
|
{
|
||||||
|
m_rxBand = band;
|
||||||
|
if ("60m" == m_rxBand)
|
||||||
|
{
|
||||||
|
ui->fSplitSpinBox->setEnabled (false);
|
||||||
|
ui->fSplitSpinBox->setValue (0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ui->fSplitSpinBox->setValue (m_fMinPerBand.value (band, 2500).toUInt ());
|
||||||
|
ui->fSplitSpinBox->setEnabled (m_mode=="JT9+JT65");
|
||||||
|
}
|
||||||
|
ui->widePlot->setRxBand(band);
|
||||||
|
setRxRange ();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void WideGraph::on_fStartSpinBox_valueChanged(int n) //fStart
|
||||||
|
{
|
||||||
|
ui->widePlot->setStartFreq(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WideGraph::readPalette () //readPalette
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (user_defined == m_waterfallPalette)
|
||||||
|
{
|
||||||
|
ui->widePlot->setColours (WFPalette {m_userPalette}.interpolate ());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ui->widePlot->setColours (WFPalette {m_palettes_path.absoluteFilePath (m_waterfallPalette + ".pal")}.interpolate());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (std::exception const& e)
|
||||||
|
{
|
||||||
|
MessageBox::warning_message (this, tr ("Read Palette"), e.what ());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WideGraph::on_paletteComboBox_activated (QString const& palette) //palette selector
|
||||||
|
{
|
||||||
|
m_waterfallPalette = palette;
|
||||||
|
readPalette();
|
||||||
|
replot();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WideGraph::on_cbFlatten_toggled(bool b) //Flatten On/Off
|
||||||
|
{
|
||||||
|
m_bFlatten=b;
|
||||||
|
if(m_bRef and m_bFlatten) {
|
||||||
|
m_bRef=false;
|
||||||
|
ui->cbRef->setChecked(false);
|
||||||
|
}
|
||||||
|
ui->widePlot->setFlatten(m_bFlatten,m_bRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WideGraph::on_cbRef_toggled(bool b)
|
||||||
|
{
|
||||||
|
m_bRef=b;
|
||||||
|
if(m_bRef and m_bFlatten) {
|
||||||
|
m_bFlatten=false;
|
||||||
|
ui->cbFlatten->setChecked(false);
|
||||||
|
}
|
||||||
|
ui->widePlot->setFlatten(m_bFlatten,m_bRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WideGraph::on_cbControls_toggled(bool b)
|
||||||
|
{
|
||||||
|
ui->controls_widget->setVisible(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WideGraph::on_adjust_palette_push_button_clicked (bool) //Adjust Palette
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (m_userPalette.design ())
|
||||||
|
{
|
||||||
|
m_waterfallPalette = user_defined;
|
||||||
|
ui->paletteComboBox->setCurrentText (m_waterfallPalette);
|
||||||
|
readPalette ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (std::exception const& e)
|
||||||
|
{
|
||||||
|
MessageBox::warning_message (this, tr ("Read Palette"), e.what ());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WideGraph::flatten() //Flatten
|
||||||
|
{
|
||||||
|
return m_bFlatten;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WideGraph::useRef() //Flatten
|
||||||
|
{
|
||||||
|
return m_bRef;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WideGraph::replot()
|
||||||
|
{
|
||||||
|
if(ui->widePlot->scaleOK()) ui->widePlot->replot();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WideGraph::on_gainSlider_valueChanged(int value) //Gain
|
||||||
|
{
|
||||||
|
ui->widePlot->setPlotGain(value);
|
||||||
|
replot();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WideGraph::on_zeroSlider_valueChanged(int value) //Zero
|
||||||
|
{
|
||||||
|
ui->widePlot->setPlotZero(value);
|
||||||
|
replot();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WideGraph::on_gain2dSlider_valueChanged(int value) //Gain2
|
||||||
|
{
|
||||||
|
ui->widePlot->setPlot2dGain(value);
|
||||||
|
if(ui->widePlot->scaleOK ()) {
|
||||||
|
ui->widePlot->draw(swide,false,false);
|
||||||
|
if(m_mode=="QRA64") ui->widePlot->draw(swide,false,true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WideGraph::on_zero2dSlider_valueChanged(int value) //Zero2
|
||||||
|
{
|
||||||
|
ui->widePlot->setPlot2dZero(value);
|
||||||
|
if(ui->widePlot->scaleOK ()) {
|
||||||
|
ui->widePlot->draw(swide,false,false);
|
||||||
|
if(m_mode=="QRA64") ui->widePlot->draw(swide,false,true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WideGraph::setTol(int n) //setTol
|
||||||
|
{
|
||||||
|
ui->widePlot->setTol(n);
|
||||||
|
ui->widePlot->DrawOverlay();
|
||||||
|
ui->widePlot->update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WideGraph::on_smoSpinBox_valueChanged(int n)
|
||||||
|
{
|
||||||
|
m_nsmo=n;
|
||||||
|
}
|
||||||
|
|
||||||
|
int WideGraph::smoothYellow()
|
||||||
|
{
|
||||||
|
return m_nsmo;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WideGraph::setWSPRtransmitted()
|
||||||
|
{
|
||||||
|
m_bHaveTransmitted=true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WideGraph::setVHF(bool bVHF)
|
||||||
|
{
|
||||||
|
ui->widePlot->setVHF(bVHF);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WideGraph::on_sbPercent2dPlot_valueChanged(int n)
|
||||||
|
{
|
||||||
|
m_Percent2DScreen=n;
|
||||||
|
ui->widePlot->SetPercent2DScreen(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WideGraph::setRedFile(QString fRed)
|
||||||
|
{
|
||||||
|
ui->widePlot->setRedFile(fRed);
|
||||||
|
}
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
// Status=review
|
||||||
|
The following controls appear just under the decoded text windows on
|
||||||
|
the main screen:
|
||||||
|
|
||||||
|
//.Main UI
|
||||||
|
image::main-ui-controls.png[align="center",width=650,alt="Main UI Controls"]
|
||||||
|
|
||||||
|
* When *CQ only* is checked, only messages from stations calling CQ will
|
||||||
|
be displayed in the left text panel.
|
||||||
|
|
||||||
|
* *Log QSO* raises a dialog window pre-filled with known information
|
||||||
|
about a QSO you have nearly completed. You can edit or add to this
|
||||||
|
information before clicking *OK* to log the QSO. If you check *Prompt
|
||||||
|
me to log QSO* on the *Settings -> Reporting* tab, the program will
|
||||||
|
raise the confirmation screen automatically when you send a message
|
||||||
|
containing +73+. *Start Date* and *Start Time* are set when you click
|
||||||
|
to send the *Tx 2* or *Tx 3* message, and backed up by one or two
|
||||||
|
sequence lengths, respectively. (Note that the actual start time may
|
||||||
|
have been earlier if repeats of early transmissions were required.)
|
||||||
|
End date and time are set when the *Log QSO* screen is invoked.
|
||||||
|
|
||||||
|
//.Log QSO Window
|
||||||
|
image::log-qso.png[align="center",alt="Log QSO"]
|
||||||
|
|
||||||
|
* *Stop* will terminate normal data acquisition in case you want to
|
||||||
|
freeze the waterfall or open and explore a previously recorded audio
|
||||||
|
file.
|
||||||
|
|
||||||
|
* *Monitor* toggles normal receive operation on or off. This button
|
||||||
|
is highlighted in green when the _WSJT-X_ is receiving. If you are
|
||||||
|
using CAT control, toggling *Monitor* OFF relinquishes control of the
|
||||||
|
rig; if *Monitor returns to last used frequency* is selected on the
|
||||||
|
*Settings | General* tab, toggling *Monitor* back ON will return to
|
||||||
|
the original frequency.
|
||||||
|
|
||||||
|
* *Erase* clears the right-hand decoded text window.
|
||||||
|
Double-clicking *Erase* clears both text windows.
|
||||||
|
|
||||||
|
TIP: Right-clicking on either text window brings up a context menu
|
||||||
|
with several options (including *Erase*) which operate on that window
|
||||||
|
alone.
|
||||||
|
|
||||||
|
* *Clear Avg* is present only in modes that support message averaging.
|
||||||
|
It provides a way to erase the accumulating information, thus
|
||||||
|
preparing to start a new average.
|
||||||
|
|
||||||
|
* *Decode* tells the program to repeat the decoding procedure at the
|
||||||
|
Rx frequency (green marker on waterfall scale), using the most recently
|
||||||
|
completed sequence of received data.
|
||||||
|
|
||||||
|
* *Enable Tx* toggles automatic T/R sequencing mode on or off and
|
||||||
|
highlights the button in red when ON. A transmission will start at
|
||||||
|
the beginning of the selected (odd or even) sequence, or immediately
|
||||||
|
if appropriate. Toggling the button to OFF during a transmission
|
||||||
|
allows the current transmission to finish.
|
||||||
|
|
||||||
|
* *Halt Tx* terminates a transmission immediately and disables
|
||||||
|
automatic T/R sequencing.
|
||||||
|
|
||||||
|
* *Tune* toggles the program into Tx mode and generates an unmodulated
|
||||||
|
carrier at the specified Tx frequency (red marker on waterfall scale).
|
||||||
|
This process is useful for adjusting an antenna tuner or tuning an
|
||||||
|
amplifier. The button is highlighted in red while *Tune* is active.
|
||||||
|
Toggle the button a second time or click *Halt Tx* to terminate the
|
||||||
|
*Tune* process. Note that activating *Tune* interrupts a receive
|
||||||
|
sequence and will prevent decoding during that sequence.
|
||||||
|
|
||||||
|
* Uncheck the box *Menus* to make the top-of-window menus disappear,
|
||||||
|
leaving more vertical space for decoded messages.
|
||||||
@@ -0,0 +1,320 @@
|
|||||||
|
program jt9
|
||||||
|
|
||||||
|
! Decoder for JT9. Can run stand-alone, reading data from *.wav files;
|
||||||
|
! or as the back end of wsjt-x, with data placed in a shared memory region.
|
||||||
|
|
||||||
|
use options
|
||||||
|
use prog_args
|
||||||
|
use, intrinsic :: iso_c_binding
|
||||||
|
use FFTW3
|
||||||
|
use timer_module, only: timer
|
||||||
|
use timer_impl, only: init_timer, fini_timer
|
||||||
|
use readwav
|
||||||
|
|
||||||
|
include 'jt9com.f90'
|
||||||
|
|
||||||
|
integer(C_INT) iret
|
||||||
|
type(wav_header) wav
|
||||||
|
real*4 s(NSMAX)
|
||||||
|
character c
|
||||||
|
character(len=500) optarg, infile
|
||||||
|
character wisfile*80
|
||||||
|
!### ndepth was defined as 60001. Why???
|
||||||
|
integer :: arglen,stat,offset,remain,mode=0,flow=200,fsplit=2700, &
|
||||||
|
fhigh=4000,nrxfreq=1500,ntrperiod=1,ndepth=1,nexp_decode=0
|
||||||
|
logical :: read_files = .true., tx9 = .false., display_help = .false.
|
||||||
|
type (option) :: long_options(25) = [ &
|
||||||
|
option ('help', .false., 'h', 'Display this help message', ''), &
|
||||||
|
option ('shmem',.true.,'s','Use shared memory for sample data','KEY'), &
|
||||||
|
option ('tr-period', .true., 'p', 'Tx/Rx period, default MINUTES=1', &
|
||||||
|
'MINUTES'), &
|
||||||
|
option ('executable-path', .true., 'e', &
|
||||||
|
'Location of subordinate executables (KVASD) default PATH="."', &
|
||||||
|
'PATH'), &
|
||||||
|
option ('data-path', .true., 'a', &
|
||||||
|
'Location of writeable data files, default PATH="."', 'PATH'), &
|
||||||
|
option ('temp-path', .true., 't', &
|
||||||
|
'Temporary files path, default PATH="."', 'PATH'), &
|
||||||
|
option ('lowest', .true., 'L', &
|
||||||
|
'Lowest frequency decoded (JT65), default HERTZ=200', 'HERTZ'), &
|
||||||
|
option ('highest', .true., 'H', &
|
||||||
|
'Highest frequency decoded, default HERTZ=4007', 'HERTZ'), &
|
||||||
|
option ('split', .true., 'S', &
|
||||||
|
'Lowest JT9 frequency decoded, default HERTZ=2700', 'HERTZ'), &
|
||||||
|
option ('rx-frequency', .true., 'f', &
|
||||||
|
'Receive frequency offset, default HERTZ=1500', 'HERTZ'), &
|
||||||
|
option ('patience', .true., 'w', &
|
||||||
|
'FFTW3 planing patience (0-4), default PATIENCE=1', 'PATIENCE'), &
|
||||||
|
option ('fft-threads', .true., 'm', &
|
||||||
|
'Number of threads to process large FFTs, default THREADS=1', &
|
||||||
|
'THREADS'), &
|
||||||
|
option ('jt65', .false., '6', 'JT65 mode', ''), &
|
||||||
|
option ('jt9', .false., '9', 'JT9 mode', ''), &
|
||||||
|
option ('ft8', .false., '8', 'FT8 mode', ''), &
|
||||||
|
option ('jt4', .false., '4', 'JT4 mode', ''), &
|
||||||
|
option ('qra64', .false., 'q', 'QRA64 mode', ''), &
|
||||||
|
option ('sub-mode', .true., 'b', 'Sub mode, default SUBMODE=A', 'A'), &
|
||||||
|
option ('depth', .true., 'd', &
|
||||||
|
'JT9 decoding depth (1-3), default DEPTH=1', 'DEPTH'), &
|
||||||
|
option ('tx-jt9', .false., 'T', 'Tx mode is JT9', ''), &
|
||||||
|
option ('my-call', .true., 'c', 'my callsign', 'CALL'), &
|
||||||
|
option ('my-grid', .true., 'G', 'my grid locator', 'GRID'), &
|
||||||
|
option ('his-call', .true., 'x', 'his callsign', 'CALL'), &
|
||||||
|
option ('his-grid', .true., 'g', 'his grid locator', 'GRID'), &
|
||||||
|
option ('experience-decode', .true., 'X', &
|
||||||
|
'experience based decoding flags (1..n), default FLAGS=0', &
|
||||||
|
'FLAGS') ]
|
||||||
|
|
||||||
|
type(dec_data), allocatable :: shared_data
|
||||||
|
character(len=20) :: datetime=''
|
||||||
|
character(len=12) :: mycall='K1ABC', hiscall='W9XYZ'
|
||||||
|
character(len=6) :: mygrid='', hisgrid='EN37'
|
||||||
|
common/patience/npatience,nthreads
|
||||||
|
common/decstats/ntry65a,ntry65b,n65a,n65b,num9,numfano
|
||||||
|
data npatience/1/,nthreads/1/
|
||||||
|
|
||||||
|
nsubmode = 0
|
||||||
|
|
||||||
|
do
|
||||||
|
call getopt('hs:e:a:b:r:m:p:d:f:w:t:9864qTL:S:H:c:G:x:g:X:', &
|
||||||
|
long_options,c,optarg,arglen,stat,offset,remain,.true.)
|
||||||
|
if (stat .ne. 0) then
|
||||||
|
exit
|
||||||
|
end if
|
||||||
|
select case (c)
|
||||||
|
case ('h')
|
||||||
|
display_help = .true.
|
||||||
|
case ('s')
|
||||||
|
read_files = .false.
|
||||||
|
shm_key = optarg(:arglen)
|
||||||
|
case ('e')
|
||||||
|
exe_dir = optarg(:arglen)
|
||||||
|
case ('a')
|
||||||
|
data_dir = optarg(:arglen)
|
||||||
|
case ('b')
|
||||||
|
nsubmode = ichar (optarg(:1)) - ichar ('A')
|
||||||
|
case ('t')
|
||||||
|
temp_dir = optarg(:arglen)
|
||||||
|
case ('m')
|
||||||
|
read (optarg(:arglen), *) nthreads
|
||||||
|
case ('p')
|
||||||
|
read (optarg(:arglen), *) ntrperiod
|
||||||
|
case ('d')
|
||||||
|
read (optarg(:arglen), *) ndepth
|
||||||
|
case ('f')
|
||||||
|
read (optarg(:arglen), *) nrxfreq
|
||||||
|
case ('L')
|
||||||
|
read (optarg(:arglen), *) flow
|
||||||
|
case ('S')
|
||||||
|
read (optarg(:arglen), *) fsplit
|
||||||
|
case ('H')
|
||||||
|
read (optarg(:arglen), *) fhigh
|
||||||
|
case ('q')
|
||||||
|
mode = 164
|
||||||
|
case ('4')
|
||||||
|
mode = 4
|
||||||
|
case ('6')
|
||||||
|
if (mode.lt.65) mode = mode + 65
|
||||||
|
case ('9')
|
||||||
|
if (mode.lt.9.or.mode.eq.65) mode = mode + 9
|
||||||
|
case ('8')
|
||||||
|
mode = 8
|
||||||
|
case ('T')
|
||||||
|
tx9 = .true.
|
||||||
|
case ('w')
|
||||||
|
read (optarg(:arglen), *) npatience
|
||||||
|
case ('c')
|
||||||
|
read (optarg(:arglen), *) mycall
|
||||||
|
case ('G')
|
||||||
|
read (optarg(:arglen), *) mygrid
|
||||||
|
case ('x')
|
||||||
|
read (optarg(:arglen), *) hiscall
|
||||||
|
case ('g')
|
||||||
|
read (optarg(:arglen), *) hisgrid
|
||||||
|
case ('X')
|
||||||
|
read (optarg(:arglen), *) nexp_decode
|
||||||
|
end select
|
||||||
|
end do
|
||||||
|
|
||||||
|
if (display_help .or. stat .lt. 0 &
|
||||||
|
.or. (.not. read_files .and. remain .gt. 0) &
|
||||||
|
.or. (read_files .and. remain .lt. 1)) then
|
||||||
|
|
||||||
|
print *, 'Usage: jt9 [OPTIONS] file1 [file2 ...]'
|
||||||
|
print *, ' Reads data from *.wav files.'
|
||||||
|
print *, ''
|
||||||
|
print *, ' jt9 -s <key> [-w patience] [-m threads] [-e path] [-a path] [-t path]'
|
||||||
|
print *, ' Gets data from shared memory region with key==<key>'
|
||||||
|
print *, ''
|
||||||
|
print *, 'OPTIONS:'
|
||||||
|
print *, ''
|
||||||
|
do i = 1, size (long_options)
|
||||||
|
call long_options(i) % print (6)
|
||||||
|
end do
|
||||||
|
go to 999
|
||||||
|
endif
|
||||||
|
|
||||||
|
iret=fftwf_init_threads() !Initialize FFTW threading
|
||||||
|
|
||||||
|
! Default to 1 thread, but use nthreads for the big ones
|
||||||
|
call fftwf_plan_with_nthreads(1)
|
||||||
|
|
||||||
|
! Import FFTW wisdom, if available
|
||||||
|
wisfile=trim(data_dir)//'/jt9_wisdom.dat'// C_NULL_CHAR
|
||||||
|
iret=fftwf_import_wisdom_from_filename(wisfile)
|
||||||
|
|
||||||
|
ntry65a=0
|
||||||
|
ntry65b=0
|
||||||
|
n65a=0
|
||||||
|
n65b=0
|
||||||
|
num9=0
|
||||||
|
numfano=0
|
||||||
|
|
||||||
|
if (.not. read_files) then
|
||||||
|
call jt9a() !We're running under control of WSJT-X
|
||||||
|
go to 999
|
||||||
|
endif
|
||||||
|
|
||||||
|
allocate(shared_data)
|
||||||
|
nflatten=0
|
||||||
|
|
||||||
|
do iarg = offset + 1, offset + remain
|
||||||
|
call get_command_argument (iarg, optarg, arglen)
|
||||||
|
infile = optarg(:arglen)
|
||||||
|
call wav%read (infile)
|
||||||
|
nfsample=wav%audio_format%sample_rate
|
||||||
|
i1=index(infile,'.wav')
|
||||||
|
if(i1.lt.1) i1=index(infile,'.WAV')
|
||||||
|
if(infile(i1-5:i1-5).eq.'_') then
|
||||||
|
read(infile(i1-4:i1-1),*,err=1) nutc
|
||||||
|
else
|
||||||
|
read(infile(i1-6:i1-1),*,err=1) nutc
|
||||||
|
endif
|
||||||
|
go to 2
|
||||||
|
1 nutc=0
|
||||||
|
2 nsps=0
|
||||||
|
if(ntrperiod.eq.1) then
|
||||||
|
nsps=6912
|
||||||
|
shared_data%params%nzhsym=181
|
||||||
|
else if(ntrperiod.eq.2) then
|
||||||
|
nsps=15360
|
||||||
|
shared_data%params%nzhsym=178
|
||||||
|
else if(ntrperiod.eq.5) then
|
||||||
|
nsps=40960
|
||||||
|
shared_data%params%nzhsym=172
|
||||||
|
else if(ntrperiod.eq.10) then
|
||||||
|
nsps=82944
|
||||||
|
shared_data%params%nzhsym=171
|
||||||
|
else if(ntrperiod.eq.30) then
|
||||||
|
nsps=252000
|
||||||
|
shared_data%params%nzhsym=167
|
||||||
|
endif
|
||||||
|
if(nsps.eq.0) stop 'Error: bad TRperiod'
|
||||||
|
|
||||||
|
kstep=nsps/2
|
||||||
|
k=0
|
||||||
|
nhsym0=-999
|
||||||
|
npts=(60*ntrperiod-6)*12000
|
||||||
|
if(iarg .eq. offset + 1) then
|
||||||
|
call init_timer (trim(data_dir)//'/timer.out')
|
||||||
|
call timer('jt9 ',0)
|
||||||
|
endif
|
||||||
|
|
||||||
|
shared_data%id2=0 !??? Why is this necessary ???
|
||||||
|
|
||||||
|
do iblk=1,npts/kstep
|
||||||
|
k=iblk*kstep
|
||||||
|
if(mode.eq.8 .and. k.gt.179712) exit
|
||||||
|
call timer('read_wav',0)
|
||||||
|
read(unit=wav%lun,end=3) shared_data%id2(k-kstep+1:k)
|
||||||
|
go to 4
|
||||||
|
3 call timer('read_wav',1)
|
||||||
|
print*,'EOF on input file ',infile
|
||||||
|
exit
|
||||||
|
4 call timer('read_wav',1)
|
||||||
|
nhsym=(k-2048)/kstep
|
||||||
|
if(nhsym.ge.1 .and. nhsym.ne.nhsym0) then
|
||||||
|
if(mode.eq.9 .or. mode.eq.74) then
|
||||||
|
! Compute rough symbol spectra for the JT9 decoder
|
||||||
|
ingain=0
|
||||||
|
call timer('symspec ',0)
|
||||||
|
nminw=1
|
||||||
|
call symspec(shared_data,k,ntrperiod,nsps,ingain,nminw,pxdb, &
|
||||||
|
s,df3,ihsym,npts8,pxdbmax)
|
||||||
|
call timer('symspec ',1)
|
||||||
|
endif
|
||||||
|
nhsym0=nhsym
|
||||||
|
if(nhsym.ge.181) exit
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
close(unit=wav%lun)
|
||||||
|
shared_data%params%nutc=nutc
|
||||||
|
shared_data%params%ndiskdat=.true.
|
||||||
|
shared_data%params%ntr=60
|
||||||
|
shared_data%params%nfqso=nrxfreq
|
||||||
|
shared_data%params%newdat=.true.
|
||||||
|
shared_data%params%npts8=74736
|
||||||
|
shared_data%params%nfa=flow
|
||||||
|
shared_data%params%nfsplit=fsplit
|
||||||
|
shared_data%params%nfb=fhigh
|
||||||
|
shared_data%params%ntol=20
|
||||||
|
shared_data%params%kin=64800
|
||||||
|
shared_data%params%nzhsym=181
|
||||||
|
shared_data%params%ndepth=ndepth
|
||||||
|
shared_data%params%lft8apon=.true.
|
||||||
|
shared_data%params%ljt65apon=.true.
|
||||||
|
shared_data%params%napwid=75
|
||||||
|
shared_data%params%dttol=3.
|
||||||
|
|
||||||
|
! shared_data%params%minsync=0 !### TEST ONLY
|
||||||
|
! shared_data%params%nfqso=1500 !### TEST ONLY
|
||||||
|
! mycall="G3WDG " !### TEST ONLY
|
||||||
|
! hiscall="VK7MO " !### TEST ONLY
|
||||||
|
! hisgrid="QE37 " !### TEST ONLY
|
||||||
|
if(mode.eq.164 .and. nsubmode.lt.100) nsubmode=nsubmode+100
|
||||||
|
|
||||||
|
shared_data%params%naggressive=0
|
||||||
|
shared_data%params%n2pass=2
|
||||||
|
! shared_data%params%nranera=8 !### ntrials=10000
|
||||||
|
shared_data%params%nranera=6 !### ntrials=3000
|
||||||
|
shared_data%params%nrobust=.false.
|
||||||
|
shared_data%params%nexp_decode=nexp_decode
|
||||||
|
shared_data%params%mycall=transfer(mycall,shared_data%params%mycall)
|
||||||
|
shared_data%params%mygrid=transfer(mygrid,shared_data%params%mygrid)
|
||||||
|
shared_data%params%hiscall=transfer(hiscall,shared_data%params%hiscall)
|
||||||
|
shared_data%params%hisgrid=transfer(hisgrid,shared_data%params%hisgrid)
|
||||||
|
if (tx9) then
|
||||||
|
shared_data%params%ntxmode=9
|
||||||
|
else
|
||||||
|
shared_data%params%ntxmode=65
|
||||||
|
end if
|
||||||
|
if (mode.eq.0) then
|
||||||
|
shared_data%params%nmode=65+9
|
||||||
|
else
|
||||||
|
shared_data%params%nmode=mode
|
||||||
|
end if
|
||||||
|
shared_data%params%nsubmode=nsubmode
|
||||||
|
datetime="2013-Apr-16 15:13" !### Temp
|
||||||
|
shared_data%params%datetime=transfer(datetime,shared_data%params%datetime)
|
||||||
|
if(mode.eq.9 .and. fsplit.ne.2700) shared_data%params%nfa=fsplit
|
||||||
|
call multimode_decoder(shared_data%ss,shared_data%id2,shared_data%params,nfsample)
|
||||||
|
enddo
|
||||||
|
|
||||||
|
call timer('jt9 ',1)
|
||||||
|
call timer('jt9 ',101)
|
||||||
|
|
||||||
|
999 continue
|
||||||
|
! Output decoder statistics
|
||||||
|
call fini_timer ()
|
||||||
|
! open (unit=12, file=trim(data_dir)//'/timer.out', status='unknown', position='append')
|
||||||
|
! write(12,1100) n65a,ntry65a,n65b,ntry65b,numfano,num9
|
||||||
|
!1100 format(58('-')/' JT65_1 Tries_1 JT65_2 Tries_2 JT9 Tries'/ &
|
||||||
|
! 58('-')/6i8)
|
||||||
|
|
||||||
|
! Save wisdom and free memory
|
||||||
|
iret=fftwf_export_wisdom_to_filename(wisfile)
|
||||||
|
call four2a(a,-1,1,1,1)
|
||||||
|
call filbig(a,-1,1,0.0,0,0,0,0,0) !used for FFT plans
|
||||||
|
call fftwf_cleanup_threads()
|
||||||
|
call fftwf_cleanup()
|
||||||
|
end program jt9
|
||||||
@@ -1,200 +0,0 @@
|
|||||||
/************************************************************************/
|
|
||||||
/* */
|
|
||||||
/* Free software: Progressive edge-growth (PEG) algorithm */
|
|
||||||
/* Created by Xiaoyu Hu */
|
|
||||||
/* Evangelos Eletheriou */
|
|
||||||
/* Dieter Arnold */
|
|
||||||
/* IBM Research, Zurich Research Lab., Switzerland */
|
|
||||||
/* */
|
|
||||||
/* The C++ sources files have been compiled using xlC compiler */
|
|
||||||
/* at IBM RS/6000 running AIX. For other compilers and platforms,*/
|
|
||||||
/* minor changes might be needed. */
|
|
||||||
/* */
|
|
||||||
/* Bug reporting to: xhu@zurich.ibm.com */
|
|
||||||
/**********************************************************************/
|
|
||||||
|
|
||||||
////
|
|
||||||
// Modified by F. P. Beekhof; 2008 / 08 / 19
|
|
||||||
////
|
|
||||||
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <cstring>
|
|
||||||
#include <string>
|
|
||||||
#include <iostream>
|
|
||||||
#include <iomanip>
|
|
||||||
#include <fstream>
|
|
||||||
#include <cmath>
|
|
||||||
#include <vector>
|
|
||||||
#include "BigGirth.h"
|
|
||||||
#include "Random.h"
|
|
||||||
#include "CyclesOfGraph.h"
|
|
||||||
|
|
||||||
const double EPS = 1e-6;
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
void usage()
|
|
||||||
{
|
|
||||||
cout<<"*******************************************************************************************"<<endl;
|
|
||||||
cout<<" Usage Reminder: MainPEG -numM M -numN N -codeName CodeName -degFileName DegFileName " <<endl;
|
|
||||||
cout<<" option: -sglConcent SglConcent " <<endl;
|
|
||||||
cout<<" sglConcent==0 ----- strictly concentrated parity-check " <<endl;
|
|
||||||
cout<<" degree distribution (including regular graphs)" <<endl;
|
|
||||||
cout<<" sglConcent==1 ----- Best-effort concentrated (DEFAULT) " <<endl;
|
|
||||||
cout<<" option: -tgtGirth TgtGirth " <<endl;
|
|
||||||
cout<<" TgtGirth==4, 6 ...; if very large, then greedy PEG (DEFAULT) " <<endl;
|
|
||||||
cout<<" IF sglConcent==0, TgtGirth is recommended to be set relatively small" <<endl;
|
|
||||||
cout<<" option: -q " <<endl;
|
|
||||||
cout<<" Quiet mode. Produces less output to the screen. " <<endl;
|
|
||||||
cout<<" option: -outputMode <0,1,2> " <<endl;
|
|
||||||
cout<<" Specifies output format. " <<endl;
|
|
||||||
cout<<" '0': H in compressed format (default) " <<endl;
|
|
||||||
cout<<" '1': H in un-compressed format " <<endl;
|
|
||||||
cout<<" '2': G and H in compressed format " <<endl;
|
|
||||||
cout<<" " <<endl;
|
|
||||||
cout<<" Remarks: File CodeName stores the generated PEG Tanner graph. The first line contains"<<endl;
|
|
||||||
cout<<" the block length, N. The second line defines the number of parity-checks, M."<<endl;
|
|
||||||
cout<<" The third line defines the number of columns of the compressed parity-check "<<endl;
|
|
||||||
cout<<" matrix. The following M lines are then the compressed parity-check matrix. "<<endl;
|
|
||||||
cout<<" Each of the M rows contains the indices (1 ... N) of 1's in the compressed "<<endl;
|
|
||||||
cout<<" row of parity-check matrix. If not all column entries are used, the column "<<endl;
|
|
||||||
cout<<" is filled up with 0's. "<<endl;
|
|
||||||
cout<<" "<<endl;
|
|
||||||
cout<<" If both G and H are in the output, (outMode 2), the first line contains"<<endl;
|
|
||||||
cout<<" N, the 2nd line K, the number of message bits, the 3rd line M, the 4th line"<<endl;
|
|
||||||
cout<<" contains the number of rows of the compressed generator matrix; the 5th"<<endl;
|
|
||||||
cout<<" defines the number of columns of the compressed parity-check matrix. The"<<endl;
|
|
||||||
cout<<" format of G is almost like that of H, but vertical -- i.e. the padding"<<endl;
|
|
||||||
cout<<" zeroes are on the bottom. "<<endl;
|
|
||||||
|
|
||||||
cout<<" "<<endl;
|
|
||||||
cout<<" File DegFileName is the input file to specify the degree distribution (node "<<endl;
|
|
||||||
cout<<" perspective). The first line contains the number of various degrees. The second"<<endl;
|
|
||||||
cout<<" defines the row vector of degree sequence in the increasing order. The vector"<<endl;
|
|
||||||
cout<<" of fractions of the corresponding degree is defined in the last line. "<<endl;
|
|
||||||
cout<<" "<<endl;
|
|
||||||
cout<<" A log file called 'leftHandGirth.dat' will also be generated and stored in the"<<endl;
|
|
||||||
cout<<" current directory, which gives the girth of the left-hand subgraph of j, where"<<endl;
|
|
||||||
cout<<" 1<=j<=N. The left-hand subgraph of j is defined as all the edges emanating from"<<endl;
|
|
||||||
cout<<" bit nodes {1 ... j} and their associated nodes. "<<endl;
|
|
||||||
cout<<" "<<endl;
|
|
||||||
cout<<" The last point is, when strictly concentrated parity-check degree distribution"<<endl;
|
|
||||||
cout<<" is invoked, i.e. sglConcent==0, the girth might be weaken to some extent as "<<endl;
|
|
||||||
cout<<" compared to the generic PEG algorithm. "<<endl;
|
|
||||||
cout<<"**********************************************************************************************"<<endl;
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char * argv[]){
|
|
||||||
int sglConcent=1; // default to non-strictly concentrated parity-check distribution
|
|
||||||
int targetGirth=100000; // default to greedy PEG version
|
|
||||||
std::string codeName, degFileName;
|
|
||||||
int M = -1, N = -1;
|
|
||||||
bool verbose = true;
|
|
||||||
|
|
||||||
const int OUTPUT_MODE_H_COMPRESSED = 0;
|
|
||||||
const int OUTPUT_MODE_H = 1;
|
|
||||||
const int OUTPUT_MODE_G_H_COMPRESSED = 2;
|
|
||||||
int output_mode = OUTPUT_MODE_H_COMPRESSED; // default
|
|
||||||
|
|
||||||
if (argc<9) {
|
|
||||||
usage();
|
|
||||||
}else {
|
|
||||||
for(int i=1;i<argc;++i){
|
|
||||||
if (strcmp(argv[i], "-numM")==0) {
|
|
||||||
if (++i >= argc) usage();
|
|
||||||
M=atoi(argv[i]);
|
|
||||||
} else if(strcmp(argv[i], "-numN")==0) {
|
|
||||||
if (++i >= argc) usage();
|
|
||||||
N=atoi(argv[i]);
|
|
||||||
} else if(strcmp(argv[i], "-codeName")==0) {
|
|
||||||
if (++i >= argc) usage();
|
|
||||||
codeName = argv[i];
|
|
||||||
} else if(strcmp(argv[i], "-degFileName")==0) {
|
|
||||||
if (++i >= argc) usage();
|
|
||||||
degFileName = argv[i];
|
|
||||||
} else if(strcmp(argv[i], "-sglConcent")==0) {
|
|
||||||
if (++i >= argc) usage();
|
|
||||||
sglConcent=atoi(argv[i]);
|
|
||||||
} else if(strcmp(argv[i], "-tgtGirth")==0) {
|
|
||||||
if (++i >= argc) usage();
|
|
||||||
targetGirth=atoi(argv[i]);
|
|
||||||
} else if(strcmp(argv[i], "-outputMode")==0) {
|
|
||||||
if (++i >= argc) usage();
|
|
||||||
output_mode=atoi(argv[i]);
|
|
||||||
} else if(strcmp(argv[i], "-q")==0) {
|
|
||||||
verbose=false;
|
|
||||||
} else{
|
|
||||||
usage();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (M == -1 || N == -1) {
|
|
||||||
cout<<"Error: M or N not specified!"<<endl;
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
if (M>N) {
|
|
||||||
cout<<"Error: M must be smaller than N!"<<endl;
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<int> degSeq(N);
|
|
||||||
|
|
||||||
ifstream infn(degFileName.c_str());
|
|
||||||
if (!infn) {cout << "\nCannot open file " << degFileName << endl; exit(-1); }
|
|
||||||
int m;
|
|
||||||
infn >>m;
|
|
||||||
std::vector<int> deg(m);
|
|
||||||
std::vector<double> degFrac(m);
|
|
||||||
for(int i=0;i<m;i++) infn>>deg[i];
|
|
||||||
for(int i=0;i<m;i++) infn>>degFrac[i];
|
|
||||||
infn.close();
|
|
||||||
double dtmp=0.0;
|
|
||||||
for(int i=0;i<m;i++) dtmp+=degFrac[i];
|
|
||||||
cout.setf(ios::fixed, ios::floatfield);
|
|
||||||
if(abs(dtmp-1.0)>EPS) {
|
|
||||||
cout.setf(ios::fixed, ios::floatfield);
|
|
||||||
cout <<"\n Invalid degree distribution (node perspective): sum != 1.0 but "<<setprecision(10)<<dtmp<<endl; exit(-1);
|
|
||||||
}
|
|
||||||
for(int i=1;i<m;++i) degFrac[i]+=degFrac[i-1];
|
|
||||||
for(int i=0;i<N;++i) {
|
|
||||||
dtmp=double(i)/double(N);
|
|
||||||
int j;
|
|
||||||
for(j=m-1;j>=0;--j) {
|
|
||||||
if(dtmp>degFrac[j]) break;
|
|
||||||
}
|
|
||||||
if(dtmp<degFrac[0]) degSeq[i]=deg[0];
|
|
||||||
else degSeq[i]=deg[j+1];
|
|
||||||
}
|
|
||||||
|
|
||||||
BigGirth bigGirth(M, N, °Seq[0], codeName.c_str(),
|
|
||||||
sglConcent, targetGirth, verbose);
|
|
||||||
|
|
||||||
switch(output_mode)
|
|
||||||
{
|
|
||||||
case OUTPUT_MODE_H_COMPRESSED: bigGirth.writeToFile_Hcompressed(); break;
|
|
||||||
case OUTPUT_MODE_H: // different output format
|
|
||||||
bigGirth.writeToFile_Hmatrix(); break;
|
|
||||||
case OUTPUT_MODE_G_H_COMPRESSED:
|
|
||||||
// different output format: including generator matrix (compressed)
|
|
||||||
bigGirth.writeToFile(); break;
|
|
||||||
default:
|
|
||||||
cout << "Error: invalid output mode specified." << endl << endl;
|
|
||||||
usage();
|
|
||||||
}
|
|
||||||
|
|
||||||
//computing local girth distribution
|
|
||||||
|
|
||||||
if (verbose && N<10000) {
|
|
||||||
cout<<" Now computing the local girth on the global Tanner graph setting. "<<endl;
|
|
||||||
cout<<" might take a bit long time. Please wait ... "<<endl;
|
|
||||||
bigGirth.loadH();
|
|
||||||
CyclesOfGraph cog(M, N, bigGirth.H);
|
|
||||||
cog.getCyclesTable();
|
|
||||||
cog.printCyclesTable();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
!subroutine symspec65(dd,npts,ss,nqsym,savg)
|
||||||
|
subroutine symspec65(dd,npts,nqsym,savg)
|
||||||
|
|
||||||
|
! Compute JT65 symbol spectra at quarter-symbol steps
|
||||||
|
|
||||||
|
parameter (NFFT=8192)
|
||||||
|
parameter (NSZ=3413) !NFFT*5000/12000
|
||||||
|
parameter (MAXHSYM=322)
|
||||||
|
parameter (MAXQSYM=552)
|
||||||
|
real*8 hstep
|
||||||
|
real*4 dd(npts)
|
||||||
|
! real*4 ss(MAXHSYM,NSZ)
|
||||||
|
real*4 ss(MAXQSYM,NSZ)
|
||||||
|
real*4 savg(NSZ)
|
||||||
|
real*4 x(NFFT)
|
||||||
|
real*4 w(NFFT)
|
||||||
|
complex c(0:NFFT/2)
|
||||||
|
logical first
|
||||||
|
common/refspec/dfref,ref(NSZ)
|
||||||
|
equivalence (x,c)
|
||||||
|
data first/.true./
|
||||||
|
save /refspec/,first,w
|
||||||
|
common/sync/ss
|
||||||
|
|
||||||
|
hstep=2048.d0*12000.d0/11025.d0 !half-symbol = 2229.116 samples
|
||||||
|
qstep=hstep/2.0 !quarter-symbol = 1114.558 samples
|
||||||
|
nsps=nint(2*hstep)
|
||||||
|
df=12000.0/NFFT
|
||||||
|
nhsym=(npts-NFFT)/hstep
|
||||||
|
nqsym=(npts-NFFT)/qstep
|
||||||
|
savg=0.
|
||||||
|
fac1=1.e-3
|
||||||
|
|
||||||
|
if(first) then
|
||||||
|
! Compute the FFT window
|
||||||
|
! width=0.25*nsps
|
||||||
|
do i=1,NFFT
|
||||||
|
! z=(i-NFFT/2)/width
|
||||||
|
w(i)=1
|
||||||
|
if(i.gt.4458) w(i)=0
|
||||||
|
! w(i)=exp(-z*z)
|
||||||
|
enddo
|
||||||
|
first=.false.
|
||||||
|
endif
|
||||||
|
|
||||||
|
do j=1,nqsym
|
||||||
|
i0=(j-1)*qstep
|
||||||
|
x=fac1*w*dd(i0+1:i0+NFFT)
|
||||||
|
call four2a(c,NFFT,1,-1,0) !r2c forward FFT
|
||||||
|
do i=1,NSZ
|
||||||
|
s=real(c(i))**2 + aimag(c(i))**2
|
||||||
|
ss(j,i)=s
|
||||||
|
savg(i)=savg(i)+s
|
||||||
|
enddo
|
||||||
|
enddo
|
||||||
|
savg=savg/nhsym
|
||||||
|
|
||||||
|
! call flat65(ss,nhsym,MAXQSYM,NSZ,ref) !Flatten the 2d spectrum, saving
|
||||||
|
call flat65(ss,nqsym,MAXQSYM,NSZ,ref) !Flatten the 2d spectrum, saving
|
||||||
|
dfref=df ! the reference spectrum ref()
|
||||||
|
savg=savg/ref
|
||||||
|
! do j=1,nhsym
|
||||||
|
do j=1,nqsym
|
||||||
|
ss(j,1:NSZ)=ss(j,1:NSZ)/ref
|
||||||
|
enddo
|
||||||
|
|
||||||
|
return
|
||||||
|
end subroutine symspec65
|
||||||
@@ -0,0 +1,231 @@
|
|||||||
|
#include "adif.h"
|
||||||
|
|
||||||
|
#include <QFile>
|
||||||
|
#include <QTextStream>
|
||||||
|
#include <QDateTime>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
/*
|
||||||
|
<CALL:4>W1XT<BAND:3>20m<FREQ:6>14.076<GRIDSQUARE:4>DM33<MODE:4>JT65<RST_RCVD:3>-21<RST_SENT:3>-14<QSO_DATE:8>20110422<TIME_ON:6>041712<TIME_OFF:6>042435<TX_PWR:1>4<COMMENT:34>1st JT65A QSO. Him: mag loop 20W<STATION_CALLSIGN:6>VK3ACF<MY_GRIDSQUARE:6>qf22lb<eor>
|
||||||
|
<CALL:6>IK1SOW<BAND:3>20m<FREQ:6>14.076<GRIDSQUARE:4>JN35<MODE:4>JT65<RST_RCVD:3>-19<RST_SENT:3>-11<QSO_DATE:8>20110422<TIME_ON:6>052501<TIME_OFF:6>053359<TX_PWR:1>3<STATION_CALLSIGN:6>VK3ACF<MY_GRIDSQUARE:6>qf22lb<eor>
|
||||||
|
<CALL:6:S>W4ABC> ...
|
||||||
|
*/
|
||||||
|
|
||||||
|
void ADIF::init(QString const& filename)
|
||||||
|
{
|
||||||
|
_filename = filename;
|
||||||
|
_data.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QString ADIF::extractField(QString const& record, QString const& fieldName) const
|
||||||
|
{
|
||||||
|
int fieldNameIndex = record.indexOf ('<' + fieldName + ':', 0, Qt::CaseInsensitive);
|
||||||
|
if (fieldNameIndex >=0)
|
||||||
|
{
|
||||||
|
int closingBracketIndex = record.indexOf('>',fieldNameIndex);
|
||||||
|
int fieldLengthIndex = record.indexOf(':',fieldNameIndex); // find the size delimiter
|
||||||
|
int dataTypeIndex = -1;
|
||||||
|
if (fieldLengthIndex >= 0)
|
||||||
|
{
|
||||||
|
dataTypeIndex = record.indexOf(':',fieldLengthIndex+1); // check for a second : indicating there is a data type
|
||||||
|
if (dataTypeIndex > closingBracketIndex)
|
||||||
|
dataTypeIndex = -1; // second : was found but it was beyond the closing >
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((closingBracketIndex > fieldNameIndex) && (fieldLengthIndex > fieldNameIndex) && (fieldLengthIndex< closingBracketIndex))
|
||||||
|
{
|
||||||
|
int fieldLengthCharCount = closingBracketIndex - fieldLengthIndex -1;
|
||||||
|
if (dataTypeIndex >= 0)
|
||||||
|
fieldLengthCharCount -= 2; // data type indicator is always a colon followed by a single character
|
||||||
|
QString fieldLengthString = record.mid(fieldLengthIndex+1,fieldLengthCharCount);
|
||||||
|
int fieldLength = fieldLengthString.toInt();
|
||||||
|
if (fieldLength > 0)
|
||||||
|
{
|
||||||
|
QString field = record.mid(closingBracketIndex+1,fieldLength);
|
||||||
|
return field;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void ADIF::load()
|
||||||
|
{
|
||||||
|
_data.clear();
|
||||||
|
QFile inputFile(_filename);
|
||||||
|
if (inputFile.open(QIODevice::ReadOnly))
|
||||||
|
{
|
||||||
|
QTextStream in(&inputFile);
|
||||||
|
QString buffer;
|
||||||
|
bool pre_read {false};
|
||||||
|
int end_position {-1};
|
||||||
|
|
||||||
|
// skip optional header record
|
||||||
|
do
|
||||||
|
{
|
||||||
|
buffer += in.readLine () + '\n';
|
||||||
|
if (buffer.startsWith (QChar {'<'})) // denotes no header
|
||||||
|
{
|
||||||
|
pre_read = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
end_position = buffer.indexOf ("<EOH>", 0, Qt::CaseInsensitive);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (!in.atEnd () && !pre_read && end_position < 0);
|
||||||
|
if (!pre_read) // found header
|
||||||
|
{
|
||||||
|
buffer.remove (0, end_position + 5);
|
||||||
|
}
|
||||||
|
while (buffer.size () || !in.atEnd ())
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
end_position = buffer.indexOf ("<EOR>", 0, Qt::CaseInsensitive);
|
||||||
|
if (!in.atEnd () && end_position < 0)
|
||||||
|
{
|
||||||
|
buffer += in.readLine () + '\n';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (!in.atEnd () && end_position < 0);
|
||||||
|
int record_length {end_position >= 0 ? end_position + 5 : -1};
|
||||||
|
auto record = buffer.left (record_length).trimmed ();
|
||||||
|
auto next_record = buffer.indexOf (QChar {'<'}, record_length);
|
||||||
|
buffer.remove (0, next_record >=0 ? next_record : buffer.size ());
|
||||||
|
record = record.mid (record.indexOf (QChar {'<'}));
|
||||||
|
add (extractField (record, "CALL")
|
||||||
|
, extractField (record, "BAND")
|
||||||
|
, extractField (record, "MODE")
|
||||||
|
, extractField (record, "QSO_DATE"));
|
||||||
|
}
|
||||||
|
inputFile.close ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ADIF::add(QString const& call, QString const& band, QString const& mode, QString const& date)
|
||||||
|
{
|
||||||
|
QSO q;
|
||||||
|
q.call = call;
|
||||||
|
q.band = band;
|
||||||
|
q.mode = mode;
|
||||||
|
q.date = date;
|
||||||
|
if (q.call.size ())
|
||||||
|
{
|
||||||
|
_data.insert(q.call,q);
|
||||||
|
// qDebug() << "Added as worked:" << call << band << mode << date;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// return true if in the log same band and mode (where JT65 == JT9)
|
||||||
|
bool ADIF::match(QString const& call, QString const& band, QString const& mode) const
|
||||||
|
{
|
||||||
|
QList<QSO> qsos = _data.values(call);
|
||||||
|
if (qsos.size()>0)
|
||||||
|
{
|
||||||
|
QSO q;
|
||||||
|
foreach(q,qsos)
|
||||||
|
{
|
||||||
|
if ( (band.compare(q.band,Qt::CaseInsensitive) == 0)
|
||||||
|
|| (band=="")
|
||||||
|
|| (q.band==""))
|
||||||
|
{
|
||||||
|
if (
|
||||||
|
(
|
||||||
|
((mode.compare("JT65",Qt::CaseInsensitive)==0) ||
|
||||||
|
(mode.compare("JT9",Qt::CaseInsensitive)==0) ||
|
||||||
|
(mode.compare("FT8",Qt::CaseInsensitive)==0))
|
||||||
|
&&
|
||||||
|
((q.mode.compare("JT65",Qt::CaseInsensitive)==0) ||
|
||||||
|
(q.mode.compare("JT9",Qt::CaseInsensitive)==0) ||
|
||||||
|
(q.mode.compare("FT8",Qt::CaseInsensitive)==0))
|
||||||
|
)
|
||||||
|
|| (mode.compare(q.mode,Qt::CaseInsensitive)==0)
|
||||||
|
|| (mode=="")
|
||||||
|
|| (q.mode=="")
|
||||||
|
)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<QString> ADIF::getCallList() const
|
||||||
|
{
|
||||||
|
QList<QString> p;
|
||||||
|
QMultiHash<QString,QSO>::const_iterator i = _data.constBegin();
|
||||||
|
while (i != _data.constEnd())
|
||||||
|
{
|
||||||
|
p << i.key();
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int ADIF::getCount() const
|
||||||
|
{
|
||||||
|
return _data.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray ADIF::QSOToADIF(QString const& hisCall, QString const& hisGrid, QString const& mode
|
||||||
|
, QString const& rptSent, QString const& rptRcvd, QDateTime const& dateTimeOn
|
||||||
|
, QDateTime const& dateTimeOff, QString const& band, QString const& comments
|
||||||
|
, QString const& name, QString const& strDialFreq, QString const& m_myCall
|
||||||
|
, QString const& m_myGrid, QString const& m_txPower, QString const& operator_call)
|
||||||
|
{
|
||||||
|
QString t;
|
||||||
|
t = "<call:" + QString::number(hisCall.length()) + ">" + hisCall;
|
||||||
|
t += " <gridsquare:" + QString::number(hisGrid.length()) + ">" + hisGrid;
|
||||||
|
t += " <mode:" + QString::number(mode.length()) + ">" + mode;
|
||||||
|
t += " <rst_sent:" + QString::number(rptSent.length()) + ">" + rptSent;
|
||||||
|
t += " <rst_rcvd:" + QString::number(rptRcvd.length()) + ">" + rptRcvd;
|
||||||
|
t += " <qso_date:8>" + dateTimeOn.date().toString("yyyyMMdd");
|
||||||
|
t += " <time_on:6>" + dateTimeOn.time().toString("hhmmss");
|
||||||
|
t += " <qso_date_off:8>" + dateTimeOff.date().toString("yyyyMMdd");
|
||||||
|
t += " <time_off:6>" + dateTimeOff.time().toString("hhmmss");
|
||||||
|
t += " <band:" + QString::number(band.length()) + ">" + band;
|
||||||
|
t += " <freq:" + QString::number(strDialFreq.length()) + ">" + strDialFreq;
|
||||||
|
t += " <station_callsign:" + QString::number(m_myCall.length()) + ">" +
|
||||||
|
m_myCall;
|
||||||
|
t += " <my_gridsquare:" + QString::number(m_myGrid.length()) + ">" +
|
||||||
|
m_myGrid;
|
||||||
|
if (m_txPower != "")
|
||||||
|
t += " <tx_pwr:" + QString::number(m_txPower.length()) +
|
||||||
|
">" + m_txPower;
|
||||||
|
if (comments != "")
|
||||||
|
t += " <comment:" + QString::number(comments.length()) +
|
||||||
|
">" + comments;
|
||||||
|
if (name != "")
|
||||||
|
t += " <name:" + QString::number(name.length()) +
|
||||||
|
">" + name;
|
||||||
|
if (operator_call!="")
|
||||||
|
t+=" <operator:" + QString::number(operator_call.length()) +
|
||||||
|
">" + operator_call;
|
||||||
|
return t.toLatin1 ();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// open ADIF file and append the QSO details. Return true on success
|
||||||
|
bool ADIF::addQSOToFile(QByteArray const& ADIF_record)
|
||||||
|
{
|
||||||
|
QFile f2(_filename);
|
||||||
|
if (!f2.open(QIODevice::Text | QIODevice::Append))
|
||||||
|
return false;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
QTextStream out(&f2);
|
||||||
|
if (f2.size()==0)
|
||||||
|
out << "WSJT-X ADIF Export<eoh>" << endl; // new file
|
||||||
|
|
||||||
|
out << ADIF_record << " <eor>" << endl;
|
||||||
|
f2.close();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
@@ -0,0 +1,126 @@
|
|||||||
|
Quick Start for DXpedition Mode
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
|
These notes are intended for operators already familiar with WSJT-X
|
||||||
|
and FT8 mode. QSOs between the Dxpedition ("Fox") and other stations
|
||||||
|
("Hounds") are completed with as little as one transmission per Hound,
|
||||||
|
as in the following examples:
|
||||||
|
|
||||||
|
----------------------------------------------------------------------------
|
||||||
|
Fox (300-600 Hz) Hounds
|
||||||
|
----------------------------------------------------------------------------
|
||||||
|
1. CQ KH1DX AJ10
|
||||||
|
2. KH1DX K1ABC FN42, KH1DX W9XYZ EN37, ...
|
||||||
|
3. K1ABC KH1DX -13
|
||||||
|
4. KH1DX K1ABC R-11
|
||||||
|
5. K1ABC RR73; W9XYZ <KH1DX> -17
|
||||||
|
6. KH1DX W9XYZ R-16
|
||||||
|
7. W9XYZ RR73; G4AAA <KH1DX> -09
|
||||||
|
8. ...
|
||||||
|
----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Everybody sets dial frequency to an agreed number and uses CAT control
|
||||||
|
with Split Operation (either *Rig* or *Fake It*). Fox transmits up to
|
||||||
|
5 signals simultaneously, at audio frequencies 300, 360, ... 540
|
||||||
|
Hz. Hounds make initial calls (e.g., line 2 above) anywhere in the
|
||||||
|
range 1000 - 4000 Hz. They send "R+rpt" 350 Hz above the frequency
|
||||||
|
where Fox called them.
|
||||||
|
|
||||||
|
|
||||||
|
INSTRUCTIONS FOR FOX
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
1. Start WSJT-X in FT8 mode. Select *Fox* on the *Settings ->
|
||||||
|
Advanced tab*. On the main window, check *Tx even/1st*, *Auto Seq*,
|
||||||
|
and *Hold Tx Freq*; uncheck *Call 1st*. Set *Tx 300 Hz* and select
|
||||||
|
Tab 3.
|
||||||
|
|
||||||
|
2. In Fox mode the left window (called "Band Activity" in normal FT8
|
||||||
|
mode) is labeled "Stations calling DXpedition <MyCall>". It will be
|
||||||
|
filled with a sorted list of calling Hounds. You can sort by Call,
|
||||||
|
Grid, S/N, Distance, or Random order by using the comboBox at top
|
||||||
|
right of Tab 3. You can limit the displayed Hound callsigns to those
|
||||||
|
no stronger than *Max dB*. Fox might use this feature to discourage
|
||||||
|
Hounds from engaging in a QRO arms race.
|
||||||
|
|
||||||
|
3. *N Slots* sets the number of simultaneous Fox signals to be used.
|
||||||
|
Fox carries out as many as *N Slots* QSOs simultaneously.
|
||||||
|
|
||||||
|
4. *Repeats* sets the maximum number of repeat transmissions of the
|
||||||
|
same message. A QSO is aborted when this number would be exceeded.
|
||||||
|
|
||||||
|
5. The *CQ* comboBox on Tab 3 offers a selection of directed CQ
|
||||||
|
messages. *Reset* clears the QSO queue.
|
||||||
|
|
||||||
|
6. The Fox operator's main task is to select Hounds to be called and
|
||||||
|
worked. The text box on Tab 3 holds the "QSO queue": a list of Hound
|
||||||
|
calls to be worked. Hit Enter to select the top callsign from the
|
||||||
|
sorted list of callers (left window), or double-click on any
|
||||||
|
particular call. Either actiion moves that Hound into the "QSO
|
||||||
|
queue".
|
||||||
|
|
||||||
|
7. The right window displays decodes of signals below 1000 Hz.
|
||||||
|
Normally these should include only Hound messages containing "R+rpt"
|
||||||
|
and Fox's own transmissions.
|
||||||
|
|
||||||
|
8. To get things started, toggle *Enable Tx* to red. If a Hound call
|
||||||
|
is available in the QSO queue, that station will be called. If the
|
||||||
|
QSO queue is empty, Fox calls CQ.
|
||||||
|
|
||||||
|
9. If you're using Nslots = 2 or higher, your signal no longer has
|
||||||
|
a constant envelope. To avoid producing intermod sidebands you need
|
||||||
|
to ensure linearity in your Tx system. One way to get things about right
|
||||||
|
is to use the WSJT-X *Tune* button to generate a pure tone. Reduce the
|
||||||
|
Tx audio level until your power output decreases by 10% or so. Use this
|
||||||
|
level for your Fox transmissions.
|
||||||
|
|
||||||
|
NOTE: If you are generating Nslots signals, the average power in each one
|
||||||
|
will be 1/Nslots^2 of its normal value for single-signal transmissions.
|
||||||
|
|
||||||
|
Nslots Relative dB
|
||||||
|
-------------------
|
||||||
|
1 0
|
||||||
|
2 -6
|
||||||
|
3 -9.5
|
||||||
|
4 -12
|
||||||
|
5 -14
|
||||||
|
|
||||||
|
|
||||||
|
The following features are not yet implemented for Fox:
|
||||||
|
|
||||||
|
1. Enforce all required settings
|
||||||
|
2. Tx message timeout
|
||||||
|
3. Manual abort of selected QSO
|
||||||
|
4. All Tx and Rx messages to all.txt
|
||||||
|
5. Additional sort criteria for Hound calls
|
||||||
|
6. Selectable timeout for keeping Hounds in the sorted list
|
||||||
|
7. Display number of active callers
|
||||||
|
8. Display QSO rate
|
||||||
|
|
||||||
|
|
||||||
|
INSTRUCTIONS FOR HOUND
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
1. Start WSJT-X in FT8 mode. Select *Hound* On the *Settings ->
|
||||||
|
Advanced* tab. On the main window check *Auto Seq* and uncheck *Tx
|
||||||
|
even/1st*, *Call 1st*, and *Hold Tx Freq*. Set *Tx nnnn Hz* to some
|
||||||
|
frequency between 1000 and 4000 Hz, and select *Tab 1*. Enter Fox's
|
||||||
|
callsign and locator in DX Call and DX Grid, select Tx1, and start
|
||||||
|
*Monitor*.
|
||||||
|
|
||||||
|
2. When you have copied Fox, hit *Enable Tx* to call him. You may
|
||||||
|
keep calling until he answers. You may wish to move your TxFreq
|
||||||
|
around, hoping to find a clear calling frequency.
|
||||||
|
|
||||||
|
3. When you are called by Fox with a signal report, your next
|
||||||
|
transmission will automatically be sent as Tx3 ("R+rpt"). When Fox
|
||||||
|
receives that message he responds with "RR73", and your QSO is
|
||||||
|
complete!
|
||||||
|
|
||||||
|
|
||||||
|
The following features are not yet implemented for Hound:
|
||||||
|
|
||||||
|
1. Force all required settings
|
||||||
|
2. React properly to directed CQs from Fox
|
||||||
|
3. Disable Tx2, 4, 5, 6
|
||||||
|
4. For Tx1, enforce TxFreq >= 1000 Hz
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
program twq
|
||||||
|
|
||||||
|
character*22 msg0,msg
|
||||||
|
integer*1 data0(11)
|
||||||
|
|
||||||
|
open(10,file='wqmsg.txt',status='old')
|
||||||
|
write(*,1000)
|
||||||
|
1000 format(4x,'Encoded message',9x,'Decoded as',12x,'itype'/55('-'))
|
||||||
|
|
||||||
|
do line=1,9999
|
||||||
|
read(10,*,end=999) msg0
|
||||||
|
call wqenc(msg0,itype,data0)
|
||||||
|
call wqdec(data0,msg,ntype)
|
||||||
|
write(*,1100) line,msg0,msg,ntype
|
||||||
|
1100 format(i2,'.',1x,a22,2x,a22,i3)
|
||||||
|
enddo
|
||||||
|
|
||||||
|
999 end program twq
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
128
|
|
||||||
56
|
|
||||||
10
|
|
||||||
1 15 30 44 58 71 84 100 115 0
|
|
||||||
2 16 31 44 59 72 86 101 116 0
|
|
||||||
3 17 31 45 60 73 87 102 117 0
|
|
||||||
2 18 32 46 58 73 85 103 112 0
|
|
||||||
4 19 32 47 61 74 88 104 118 0
|
|
||||||
5 20 33 48 62 75 88 105 116 0
|
|
||||||
6 19 34 49 63 76 89 105 119 0
|
|
||||||
7 15 27 45 64 77 88 106 120 0
|
|
||||||
8 15 35 50 59 75 90 107 121 127
|
|
||||||
7 21 33 51 65 73 91 108 114 0
|
|
||||||
9 22 30 46 59 78 92 99 122 0
|
|
||||||
9 19 35 52 60 71 93 109 120 0
|
|
||||||
10 20 31 53 63 79 93 107 123 0
|
|
||||||
11 15 36 53 66 78 85 110 124 0
|
|
||||||
8 23 37 49 67 71 86 111 118 0
|
|
||||||
12 22 34 54 68 80 94 109 114 0
|
|
||||||
1 24 34 52 65 75 87 97 123 0
|
|
||||||
13 25 29 43 69 81 85 100 121 128
|
|
||||||
12 17 38 55 63 82 90 101 125 0
|
|
||||||
11 26 39 47 56 76 95 106 117 0
|
|
||||||
2 27 40 49 69 74 94 108 117 0
|
|
||||||
4 16 30 55 64 76 91 103 126 0
|
|
||||||
13 17 28 47 65 80 96 111 124 126
|
|
||||||
6 18 36 51 70 83 94 111 121 0
|
|
||||||
13 16 34 48 57 82 95 112 120 127
|
|
||||||
6 28 40 48 58 79 90 113 122 0
|
|
||||||
5 27 41 46 67 83 91 109 127 0
|
|
||||||
14 16 42 54 63 78 97 100 118 0
|
|
||||||
13 27 39 52 70 84 90 114 118 0
|
|
||||||
10 22 42 47 64 81 98 110 116 0
|
|
||||||
11 22 29 55 60 84 97 108 111 127
|
|
||||||
5 26 37 55 57 74 96 98 128 0
|
|
||||||
3 21 35 54 62 82 98 104 113 0
|
|
||||||
14 21 43 50 68 77 93 110 117 0
|
|
||||||
9 24 33 56 69 72 89 110 112 0
|
|
||||||
12 26 42 53 62 73 89 99 121 0
|
|
||||||
10 25 35 41 57 76 97 101 122 0
|
|
||||||
10 18 39 44 66 77 99 102 119 0
|
|
||||||
3 29 40 44 61 83 93 106 125 0
|
|
||||||
4 23 39 45 65 85 89 107 113 0
|
|
||||||
6 26 30 43 61 80 86 108 123 0
|
|
||||||
7 19 31 57 69 83 99 113 124 0
|
|
||||||
3 24 37 43 66 84 92 105 120 126
|
|
||||||
2 24 38 50 70 71 88 102 122 0
|
|
||||||
1 20 32 51 68 81 86 102 124 0
|
|
||||||
12 23 41 51 59 74 87 106 115 0
|
|
||||||
14 28 37 46 62 72 95 114 115 125
|
|
||||||
1 28 41 49 61 82 92 103 116 128
|
|
||||||
7 25 38 56 60 75 98 103 115 0
|
|
||||||
8 29 33 45 58 78 96 109 119 0
|
|
||||||
4 25 36 54 67 77 96 105 123 0
|
|
||||||
14 20 38 52 66 80 91 104 112 128
|
|
||||||
8 18 42 56 68 79 87 104 125 0
|
|
||||||
9 23 40 53 70 81 95 101 126 0
|
|
||||||
11 21 32 48 67 72 94 107 119 0
|
|
||||||
5 17 36 50 64 79 92 100 0 0
|
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
@@ -0,0 +1,31 @@
|
|||||||
|
<table cellpadding=5>
|
||||||
|
<tr>
|
||||||
|
<th align="right">Click on</th>
|
||||||
|
<th align="left">Action</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td align="right">Waterfall:</td>
|
||||||
|
<td><b>Click</b> to set Rx frequency.<br/>
|
||||||
|
<b>Shift-click</b> to set Tx frequency.<br/>
|
||||||
|
<b>Ctrl-click</b> or <b>Right-click</b> to set Rx and Tx frequencies.<br/>
|
||||||
|
<b>Double-click</b> to also decode at Rx frequency.<br/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td align="right">Decoded text:</td>
|
||||||
|
<td><b>Double-click</b> to copy second callsign to Dx Call,<br/>
|
||||||
|
locator to Dx Grid, change Rx and Tx frequency to<br/>
|
||||||
|
decoded signal's frequency, and generate standard<br/>
|
||||||
|
messages.<br/>
|
||||||
|
If <b>Hold Tx Freq</b> is checked or first callsign in message<br/>
|
||||||
|
is your own call, Tx frequency is not changed unless <br/>
|
||||||
|
<b>Ctrl</b> is held down.<br/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td align="right">Erase button:</td>
|
||||||
|
<td><b>Click</b> to erase QSO window.<br/>
|
||||||
|
<b>Double-click</b> to erase QSO and Band Activity windows.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
#ifndef BOOST_THREAD_THREAD_HPP
|
||||||
|
#define BOOST_THREAD_THREAD_HPP
|
||||||
|
|
||||||
|
// thread.hpp
|
||||||
|
//
|
||||||
|
// (C) Copyright 2007-8 Anthony Williams
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See
|
||||||
|
// accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
// http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
|
||||||
|
#include <boost/thread/thread_only.hpp>
|
||||||
|
#include <boost/thread/detail/thread_group.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,124 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
# These tests investigate what happens when the wrong model is used for
|
|
||||||
# decoding. A (1800,1000) LDPC code with 3 check per bit is used.
|
|
||||||
# Testing is done by transmitting random messages. Decoding is done using
|
|
||||||
# a maximum of 100 iterations of probability propagation.
|
|
||||||
#
|
|
||||||
# The first set of tests compares decoding of messages sent through an
|
|
||||||
# AWGN channel using the correct AWGN model with sigma=0.90 to decoding
|
|
||||||
# using AWGN models with incorrect values for sigma and to decoding
|
|
||||||
# using AWLN models with varying width parameters for the logistic noise
|
|
||||||
# distribution.
|
|
||||||
#
|
|
||||||
# A second set of tests compares decoding of messages sent through an
|
|
||||||
# AWLN channel using the correct AWLN model with width=0.50 to decoding
|
|
||||||
# using AWLN models with incorrect values for width and to decoding
|
|
||||||
# using AWGN models with varying sigma parameters.
|
|
||||||
|
|
||||||
set -e # Stop if an error occurs
|
|
||||||
set -v # Echo commands as they are read
|
|
||||||
|
|
||||||
make-ldpc ex-wrong-model.pchk 1000 1800 1 evenboth 3 no4cycle
|
|
||||||
make-gen ex-wrong-model.pchk ex-wrong-model.gen dense
|
|
||||||
rand-src ex-wrong-model.src 1 800x1000
|
|
||||||
encode ex-wrong-model.pchk ex-wrong-model.gen ex-wrong-model.src \
|
|
||||||
ex-wrong-model.enc
|
|
||||||
|
|
||||||
# FIRST SET OF TESTS, TRANSMITTING THROUGH AWGN CHANNEL WITH SIGMA=0.90
|
|
||||||
|
|
||||||
transmit ex-wrong-model.enc ex-wrong-model.rec 1 awgn 0.90
|
|
||||||
|
|
||||||
# DECODING WITH CORRECT AWGN NOISE MODEL, SIGMA=0.90
|
|
||||||
|
|
||||||
decode ex-wrong-model.pchk ex-wrong-model.rec - awgn 0.90 prprp 100 \
|
|
||||||
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
|
|
||||||
|
|
||||||
# DECODING WITH AWGN NOISE MODEL, SIGMA=0.95
|
|
||||||
|
|
||||||
decode ex-wrong-model.pchk ex-wrong-model.rec - awgn 0.95 prprp 100 \
|
|
||||||
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
|
|
||||||
|
|
||||||
# DECODING WITH AWGN NOISE MODEL, SIGMA=0.85
|
|
||||||
|
|
||||||
decode ex-wrong-model.pchk ex-wrong-model.rec - awgn 0.85 prprp 100 \
|
|
||||||
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
|
|
||||||
|
|
||||||
# DECODING WITH AWLN NOISE MODEL, WIDTH=0.40
|
|
||||||
|
|
||||||
decode ex-wrong-model.pchk ex-wrong-model.rec - awln 0.40 prprp 100 \
|
|
||||||
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
|
|
||||||
|
|
||||||
# DECODING WITH AWLN NOISE MODEL, WIDTH=0.45
|
|
||||||
|
|
||||||
decode ex-wrong-model.pchk ex-wrong-model.rec - awln 0.45 prprp 100 \
|
|
||||||
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
|
|
||||||
|
|
||||||
# DECODING WITH AWLN NOISE MODEL, WIDTH=0.50
|
|
||||||
|
|
||||||
decode ex-wrong-model.pchk ex-wrong-model.rec - awln 0.50 prprp 100 \
|
|
||||||
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
|
|
||||||
|
|
||||||
# DECODING WITH AWLN NOISE MODEL, WIDTH=0.55
|
|
||||||
|
|
||||||
decode ex-wrong-model.pchk ex-wrong-model.rec - awln 0.55 prprp 100 \
|
|
||||||
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
|
|
||||||
|
|
||||||
# DECODING WITH AWLN NOISE MODEL, WIDTH=0.60
|
|
||||||
|
|
||||||
decode ex-wrong-model.pchk ex-wrong-model.rec - awln 0.60 prprp 100 \
|
|
||||||
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
|
|
||||||
|
|
||||||
# DECODING WITH AWLN NOISE MODEL, WIDTH=0.65
|
|
||||||
|
|
||||||
decode ex-wrong-model.pchk ex-wrong-model.rec - awln 0.65 prprp 100 \
|
|
||||||
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
|
|
||||||
|
|
||||||
# SECOND SET OF TESTS, TRANSMITTING THROUGH AWLN CHANNEL WITH WIDTH=0.50
|
|
||||||
|
|
||||||
transmit ex-wrong-model.enc ex-wrong-model.rec 1 awln 0.50
|
|
||||||
|
|
||||||
# DECODING WITH CORRECT AWLN NOISE MODEL, WIDTH=0.50
|
|
||||||
|
|
||||||
decode ex-wrong-model.pchk ex-wrong-model.rec - awln 0.50 prprp 100 \
|
|
||||||
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
|
|
||||||
|
|
||||||
# DECODING WITH AWLN NOISE MODEL, WIDTH=0.55
|
|
||||||
|
|
||||||
decode ex-wrong-model.pchk ex-wrong-model.rec - awln 0.55 prprp 100 \
|
|
||||||
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
|
|
||||||
|
|
||||||
# DECODING WITH AWLN NOISE MODEL, WIDTH=0.45
|
|
||||||
|
|
||||||
decode ex-wrong-model.pchk ex-wrong-model.rec - awln 0.45 prprp 100 \
|
|
||||||
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
|
|
||||||
|
|
||||||
# DECODING WITH AWGN NOISE MODEL, SIGMA=0.80
|
|
||||||
|
|
||||||
decode ex-wrong-model.pchk ex-wrong-model.rec - awgn 0.80 prprp 100 \
|
|
||||||
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
|
|
||||||
|
|
||||||
# DECODING WITH AWGN NOISE MODEL, SIGMA=0.85
|
|
||||||
|
|
||||||
decode ex-wrong-model.pchk ex-wrong-model.rec - awgn 0.85 prprp 100 \
|
|
||||||
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
|
|
||||||
|
|
||||||
# DECODING WITH AWGN NOISE MODEL, SIGMA=0.90
|
|
||||||
|
|
||||||
decode ex-wrong-model.pchk ex-wrong-model.rec - awgn 0.90 prprp 100 \
|
|
||||||
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
|
|
||||||
|
|
||||||
# DECODING WITH AWGN NOISE MODEL, SIGMA=0.95
|
|
||||||
|
|
||||||
decode ex-wrong-model.pchk ex-wrong-model.rec - awgn 0.95 prprp 100 \
|
|
||||||
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
|
|
||||||
|
|
||||||
# DECODING WITH AWGN NOISE MODEL, SIGMA=1.00
|
|
||||||
|
|
||||||
decode ex-wrong-model.pchk ex-wrong-model.rec - awgn 1.00 prprp 100 \
|
|
||||||
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
|
|
||||||
|
|
||||||
# DECODING WITH AWGN NOISE MODEL, SIGMA=1.05
|
|
||||||
|
|
||||||
decode ex-wrong-model.pchk ex-wrong-model.rec - awgn 1.05 prprp 100 \
|
|
||||||
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
|
|
||||||
@@ -0,0 +1,365 @@
|
|||||||
|
subroutine osd174(llr,apmask,ndeep,decoded,cw,nhardmin,dmin)
|
||||||
|
!
|
||||||
|
! An ordered-statistics decoder for the (174,87) code.
|
||||||
|
!
|
||||||
|
include "ldpc_174_87_params.f90"
|
||||||
|
|
||||||
|
integer*1 apmask(N),apmaskr(N)
|
||||||
|
integer*1 gen(K,N)
|
||||||
|
integer*1 genmrb(K,N),g2(N,K)
|
||||||
|
integer*1 temp(K),m0(K),me(K),mi(K),misub(K),e2sub(N-K),e2(N-K),ui(N-K)
|
||||||
|
integer*1 r2pat(N-K)
|
||||||
|
integer indices(N),nxor(N)
|
||||||
|
integer*1 cw(N),ce(N),c0(N),hdec(N)
|
||||||
|
integer*1 decoded(K)
|
||||||
|
integer indx(N)
|
||||||
|
real llr(N),rx(N),absrx(N)
|
||||||
|
logical first,reset
|
||||||
|
data first/.true./
|
||||||
|
save first,gen
|
||||||
|
|
||||||
|
if( first ) then ! fill the generator matrix
|
||||||
|
gen=0
|
||||||
|
do i=1,M
|
||||||
|
do j=1,22
|
||||||
|
read(g(i)(j:j),"(Z1)") istr
|
||||||
|
do jj=1, 4
|
||||||
|
irow=(j-1)*4+jj
|
||||||
|
if( btest(istr,4-jj) ) gen(irow,i)=1
|
||||||
|
enddo
|
||||||
|
enddo
|
||||||
|
enddo
|
||||||
|
do irow=1,K
|
||||||
|
gen(irow,M+irow)=1
|
||||||
|
enddo
|
||||||
|
first=.false.
|
||||||
|
endif
|
||||||
|
|
||||||
|
! Re-order received vector to place systematic msg bits at the end.
|
||||||
|
rx=llr(colorder+1)
|
||||||
|
apmaskr=apmask(colorder+1)
|
||||||
|
|
||||||
|
! Hard decisions on the received word.
|
||||||
|
hdec=0
|
||||||
|
where(rx .ge. 0) hdec=1
|
||||||
|
|
||||||
|
! Use magnitude of received symbols as a measure of reliability.
|
||||||
|
absrx=abs(rx)
|
||||||
|
call indexx(absrx,N,indx)
|
||||||
|
|
||||||
|
! Re-order the columns of the generator matrix in order of decreasing reliability.
|
||||||
|
do i=1,N
|
||||||
|
genmrb(1:K,i)=gen(1:K,indx(N+1-i))
|
||||||
|
indices(i)=indx(N+1-i)
|
||||||
|
enddo
|
||||||
|
|
||||||
|
! Do gaussian elimination to create a generator matrix with the most reliable
|
||||||
|
! received bits in positions 1:K in order of decreasing reliability (more or less).
|
||||||
|
do id=1,K ! diagonal element indices
|
||||||
|
do icol=id,K+20 ! The 20 is ad hoc - beware
|
||||||
|
iflag=0
|
||||||
|
if( genmrb(id,icol) .eq. 1 ) then
|
||||||
|
iflag=1
|
||||||
|
if( icol .ne. id ) then ! reorder column
|
||||||
|
temp(1:K)=genmrb(1:K,id)
|
||||||
|
genmrb(1:K,id)=genmrb(1:K,icol)
|
||||||
|
genmrb(1:K,icol)=temp(1:K)
|
||||||
|
itmp=indices(id)
|
||||||
|
indices(id)=indices(icol)
|
||||||
|
indices(icol)=itmp
|
||||||
|
endif
|
||||||
|
do ii=1,K
|
||||||
|
if( ii .ne. id .and. genmrb(ii,id) .eq. 1 ) then
|
||||||
|
genmrb(ii,1:N)=ieor(genmrb(ii,1:N),genmrb(id,1:N))
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
exit
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
enddo
|
||||||
|
|
||||||
|
g2=transpose(genmrb)
|
||||||
|
|
||||||
|
! The hard decisions for the K MRB bits define the order 0 message, m0.
|
||||||
|
! Encode m0 using the modified generator matrix to find the "order 0" codeword.
|
||||||
|
! Flip various combinations of bits in m0 and re-encode to generate a list of
|
||||||
|
! codewords. Return the member of the list that has the smallest Euclidean
|
||||||
|
! distance to the received word.
|
||||||
|
|
||||||
|
hdec=hdec(indices) ! hard decisions from received symbols
|
||||||
|
m0=hdec(1:K) ! zero'th order message
|
||||||
|
absrx=absrx(indices)
|
||||||
|
rx=rx(indices)
|
||||||
|
apmaskr=apmaskr(indices)
|
||||||
|
|
||||||
|
call mrbencode(m0,c0,g2,N,K)
|
||||||
|
nxor=ieor(c0,hdec)
|
||||||
|
nhardmin=sum(nxor)
|
||||||
|
dmin=sum(nxor*absrx)
|
||||||
|
|
||||||
|
cw=c0
|
||||||
|
ntotal=0
|
||||||
|
nrejected=0
|
||||||
|
|
||||||
|
if(ndeep.eq.0) goto 998 ! norder=0
|
||||||
|
if(ndeep.gt.5) ndeep=5
|
||||||
|
if( ndeep.eq. 1) then
|
||||||
|
nord=1
|
||||||
|
npre1=0
|
||||||
|
npre2=0
|
||||||
|
nt=40
|
||||||
|
ntheta=12
|
||||||
|
elseif(ndeep.eq.2) then
|
||||||
|
nord=1
|
||||||
|
npre1=1
|
||||||
|
npre2=0
|
||||||
|
nt=40
|
||||||
|
ntheta=12
|
||||||
|
elseif(ndeep.eq.3) then
|
||||||
|
nord=1
|
||||||
|
npre1=1
|
||||||
|
npre2=1
|
||||||
|
nt=40
|
||||||
|
ntheta=12
|
||||||
|
ntau=14
|
||||||
|
elseif(ndeep.eq.4) then
|
||||||
|
nord=2
|
||||||
|
npre1=1
|
||||||
|
npre2=0
|
||||||
|
nt=40
|
||||||
|
ntheta=12
|
||||||
|
ntau=19
|
||||||
|
elseif(ndeep.eq.5) then
|
||||||
|
nord=2
|
||||||
|
npre1=1
|
||||||
|
npre2=1
|
||||||
|
nt=40
|
||||||
|
ntheta=12
|
||||||
|
ntau=19
|
||||||
|
endif
|
||||||
|
|
||||||
|
do iorder=1,nord
|
||||||
|
misub(1:K-iorder)=0
|
||||||
|
misub(K-iorder+1:K)=1
|
||||||
|
iflag=K-iorder+1
|
||||||
|
do while(iflag .ge.0)
|
||||||
|
if(iorder.eq.nord .and. npre1.eq.0) then
|
||||||
|
iend=iflag
|
||||||
|
else
|
||||||
|
iend=1
|
||||||
|
endif
|
||||||
|
do n1=iflag,iend,-1
|
||||||
|
mi=misub
|
||||||
|
mi(n1)=1
|
||||||
|
if(any(iand(apmaskr(1:K),mi).eq.1)) cycle
|
||||||
|
ntotal=ntotal+1
|
||||||
|
me=ieor(m0,mi)
|
||||||
|
if(n1.eq.iflag) then
|
||||||
|
call mrbencode(me,ce,g2,N,K)
|
||||||
|
e2sub=ieor(ce(K+1:N),hdec(K+1:N))
|
||||||
|
e2=e2sub
|
||||||
|
nd1Kpt=sum(e2sub(1:nt))+1
|
||||||
|
d1=sum(ieor(me(1:K),hdec(1:K))*absrx(1:K))
|
||||||
|
else
|
||||||
|
e2=ieor(e2sub,g2(K+1:N,n1))
|
||||||
|
nd1Kpt=sum(e2(1:nt))+2
|
||||||
|
endif
|
||||||
|
if(nd1Kpt .le. ntheta) then
|
||||||
|
call mrbencode(me,ce,g2,N,K)
|
||||||
|
nxor=ieor(ce,hdec)
|
||||||
|
if(n1.eq.iflag) then
|
||||||
|
dd=d1+sum(e2sub*absrx(K+1:N))
|
||||||
|
else
|
||||||
|
dd=d1+ieor(ce(n1),hdec(n1))*absrx(n1)+sum(e2*absrx(K+1:N))
|
||||||
|
endif
|
||||||
|
if( dd .lt. dmin ) then
|
||||||
|
dmin=dd
|
||||||
|
cw=ce
|
||||||
|
nhardmin=sum(nxor)
|
||||||
|
nd1Kptbest=nd1Kpt
|
||||||
|
endif
|
||||||
|
else
|
||||||
|
nrejected=nrejected+1
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
! Get the next test error pattern, iflag will go negative
|
||||||
|
! when the last pattern with weight iorder has been generated.
|
||||||
|
call nextpat(misub,k,iorder,iflag)
|
||||||
|
enddo
|
||||||
|
enddo
|
||||||
|
|
||||||
|
if(npre2.eq.1) then
|
||||||
|
reset=.true.
|
||||||
|
ntotal=0
|
||||||
|
do i1=K,1,-1
|
||||||
|
do i2=i1-1,1,-1
|
||||||
|
ntotal=ntotal+1
|
||||||
|
mi(1:ntau)=ieor(g2(K+1:K+ntau,i1),g2(K+1:K+ntau,i2))
|
||||||
|
call boxit(reset,mi(1:ntau),ntau,ntotal,i1,i2)
|
||||||
|
enddo
|
||||||
|
enddo
|
||||||
|
|
||||||
|
ncount2=0
|
||||||
|
ntotal2=0
|
||||||
|
reset=.true.
|
||||||
|
! Now run through again and do the second pre-processing rule
|
||||||
|
misub(1:K-nord)=0
|
||||||
|
misub(K-nord+1:K)=1
|
||||||
|
iflag=K-nord+1
|
||||||
|
do while(iflag .ge.0)
|
||||||
|
me=ieor(m0,misub)
|
||||||
|
call mrbencode(me,ce,g2,N,K)
|
||||||
|
e2sub=ieor(ce(K+1:N),hdec(K+1:N))
|
||||||
|
do i2=0,ntau
|
||||||
|
ntotal2=ntotal2+1
|
||||||
|
ui=0
|
||||||
|
if(i2.gt.0) ui(i2)=1
|
||||||
|
r2pat=ieor(e2sub,ui)
|
||||||
|
778 continue
|
||||||
|
call fetchit(reset,r2pat(1:ntau),ntau,in1,in2)
|
||||||
|
if(in1.gt.0.and.in2.gt.0) then
|
||||||
|
ncount2=ncount2+1
|
||||||
|
mi=misub
|
||||||
|
mi(in1)=1
|
||||||
|
mi(in2)=1
|
||||||
|
if(sum(mi).lt.nord+npre1+npre2.or.any(iand(apmaskr(1:K),mi).eq.1)) cycle
|
||||||
|
me=ieor(m0,mi)
|
||||||
|
call mrbencode(me,ce,g2,N,K)
|
||||||
|
nxor=ieor(ce,hdec)
|
||||||
|
dd=sum(nxor*absrx)
|
||||||
|
if( dd .lt. dmin ) then
|
||||||
|
dmin=dd
|
||||||
|
cw=ce
|
||||||
|
nhardmin=sum(nxor)
|
||||||
|
endif
|
||||||
|
goto 778
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
call nextpat(misub,K,nord,iflag)
|
||||||
|
enddo
|
||||||
|
endif
|
||||||
|
|
||||||
|
998 continue
|
||||||
|
! Re-order the codeword to place message bits at the end.
|
||||||
|
cw(indices)=cw
|
||||||
|
hdec(indices)=hdec
|
||||||
|
decoded=cw(M+1:N)
|
||||||
|
cw(colorder+1)=cw ! put the codeword back into received-word order
|
||||||
|
return
|
||||||
|
end subroutine osd174
|
||||||
|
|
||||||
|
subroutine mrbencode(me,codeword,g2,N,K)
|
||||||
|
integer*1 me(K),codeword(N),g2(N,K)
|
||||||
|
! fast encoding for low-weight test patterns
|
||||||
|
codeword=0
|
||||||
|
do i=1,K
|
||||||
|
if( me(i) .eq. 1 ) then
|
||||||
|
codeword=ieor(codeword,g2(1:N,i))
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
return
|
||||||
|
end subroutine mrbencode
|
||||||
|
|
||||||
|
subroutine nextpat(mi,k,iorder,iflag)
|
||||||
|
integer*1 mi(k),ms(k)
|
||||||
|
! generate the next test error pattern
|
||||||
|
ind=-1
|
||||||
|
do i=1,k-1
|
||||||
|
if( mi(i).eq.0 .and. mi(i+1).eq.1) ind=i
|
||||||
|
enddo
|
||||||
|
if( ind .lt. 0 ) then ! no more patterns of this order
|
||||||
|
iflag=ind
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
ms=0
|
||||||
|
ms(1:ind-1)=mi(1:ind-1)
|
||||||
|
ms(ind)=1
|
||||||
|
ms(ind+1)=0
|
||||||
|
if( ind+1 .lt. k ) then
|
||||||
|
nz=iorder-sum(ms)
|
||||||
|
ms(k-nz+1:k)=1
|
||||||
|
endif
|
||||||
|
mi=ms
|
||||||
|
do i=1,k ! iflag will point to the lowest-index 1 in mi
|
||||||
|
if(mi(i).eq.1) then
|
||||||
|
iflag=i
|
||||||
|
exit
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
return
|
||||||
|
end subroutine nextpat
|
||||||
|
|
||||||
|
subroutine boxit(reset,e2,ntau,npindex,i1,i2)
|
||||||
|
integer*1 e2(1:ntau)
|
||||||
|
integer indexes(4000,2),fp(0:525000),np(4000)
|
||||||
|
logical reset
|
||||||
|
common/boxes/indexes,fp,np
|
||||||
|
|
||||||
|
if(reset) then
|
||||||
|
patterns=-1
|
||||||
|
fp=-1
|
||||||
|
np=-1
|
||||||
|
sc=-1
|
||||||
|
indexes=-1
|
||||||
|
reset=.false.
|
||||||
|
endif
|
||||||
|
|
||||||
|
indexes(npindex,1)=i1
|
||||||
|
indexes(npindex,2)=i2
|
||||||
|
ipat=0
|
||||||
|
do i=1,ntau
|
||||||
|
if(e2(i).eq.1) then
|
||||||
|
ipat=ipat+ishft(1,ntau-i)
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
|
||||||
|
ip=fp(ipat) ! see what's currently stored in fp(ipat)
|
||||||
|
if(ip.eq.-1) then
|
||||||
|
fp(ipat)=npindex
|
||||||
|
else
|
||||||
|
do while (np(ip).ne.-1)
|
||||||
|
ip=np(ip)
|
||||||
|
enddo
|
||||||
|
np(ip)=npindex
|
||||||
|
endif
|
||||||
|
return
|
||||||
|
end subroutine boxit
|
||||||
|
|
||||||
|
subroutine fetchit(reset,e2,ntau,i1,i2)
|
||||||
|
integer indexes(4000,2),fp(0:525000),np(4000)
|
||||||
|
integer lastpat
|
||||||
|
integer*1 e2(ntau)
|
||||||
|
logical reset
|
||||||
|
common/boxes/indexes,fp,np
|
||||||
|
save lastpat,inext
|
||||||
|
|
||||||
|
if(reset) then
|
||||||
|
lastpat=-1
|
||||||
|
reset=.false.
|
||||||
|
endif
|
||||||
|
|
||||||
|
ipat=0
|
||||||
|
do i=1,ntau
|
||||||
|
if(e2(i).eq.1) then
|
||||||
|
ipat=ipat+ishft(1,ntau-i)
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
index=fp(ipat)
|
||||||
|
|
||||||
|
if(lastpat.ne.ipat .and. index.gt.0) then ! return first set of indices
|
||||||
|
i1=indexes(index,1)
|
||||||
|
i2=indexes(index,2)
|
||||||
|
inext=np(index)
|
||||||
|
elseif(lastpat.eq.ipat .and. inext.gt.0) then
|
||||||
|
i1=indexes(inext,1)
|
||||||
|
i2=indexes(inext,2)
|
||||||
|
inext=np(inext)
|
||||||
|
else
|
||||||
|
i1=-1
|
||||||
|
i2=-1
|
||||||
|
inext=-1
|
||||||
|
endif
|
||||||
|
lastpat=ipat
|
||||||
|
return
|
||||||
|
end subroutine fetchit
|
||||||
|
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
subroutine decode65b(s2,nflip,nadd,mode65,ntrials,naggressive,ndepth, &
|
||||||
|
mycall,hiscall,hisgrid,nQSOProgress,ljt65apon,nexp_decode,nqd, &
|
||||||
|
nft,qual, &
|
||||||
|
nhist,decoded)
|
||||||
|
|
||||||
|
use jt65_mod
|
||||||
|
real s2(66,126)
|
||||||
|
real s3(64,63)
|
||||||
|
logical ltext,ljt65apon
|
||||||
|
character decoded*22
|
||||||
|
character mycall*12,hiscall*12,hisgrid*6
|
||||||
|
save
|
||||||
|
|
||||||
|
if(nqd.eq.-99) stop !Silence compiler warning
|
||||||
|
do j=1,63
|
||||||
|
k=mdat(j) !Points to data symbol
|
||||||
|
if(nflip.lt.0) k=mdat2(j)
|
||||||
|
do i=1,64
|
||||||
|
s3(i,j)=s2(i+2,k)
|
||||||
|
enddo
|
||||||
|
enddo
|
||||||
|
|
||||||
|
call extract(s3,nadd,mode65,ntrials,naggressive,ndepth,nflip,mycall, &
|
||||||
|
hiscall,hisgrid,nQSOProgress,ljt65apon,nexp_decode,ncount, &
|
||||||
|
nhist,decoded,ltext,nft,qual)
|
||||||
|
|
||||||
|
! Suppress "birdie messages" and other garbage decodes:
|
||||||
|
if(decoded(1:7).eq.'000AAA ') ncount=-1
|
||||||
|
if(decoded(1:7).eq.'0L6MWK ') ncount=-1
|
||||||
|
if(nflip.lt.0 .and. ltext) ncount=-1
|
||||||
|
if(ncount.lt.0) then
|
||||||
|
nft=0
|
||||||
|
decoded=' '
|
||||||
|
endif
|
||||||
|
|
||||||
|
return
|
||||||
|
end subroutine decode65b
|
||||||
@@ -1,415 +0,0 @@
|
|||||||
/* MAKE-LDPC.C - Make a Low Density Parity Check code's parity check matrix. */
|
|
||||||
|
|
||||||
/* Copyright (c) 1995-2012 by Radford M. Neal and Peter Junteng Liu.
|
|
||||||
*
|
|
||||||
* Permission is granted for anyone to copy, use, modify, and distribute
|
|
||||||
* these programs and accompanying documents for any purpose, provided
|
|
||||||
* this copyright notice is retained and prominently displayed, and note
|
|
||||||
* is made of any changes made to these programs. These programs and
|
|
||||||
* documents are distributed without any warranty, express or implied.
|
|
||||||
* As the programs were written for research purposes only, they have not
|
|
||||||
* been tested to the degree that would be advisable in any important
|
|
||||||
* application. All use of these programs is entirely at the user's own
|
|
||||||
* risk.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <math.h>
|
|
||||||
|
|
||||||
#include "rand.h"
|
|
||||||
#include "alloc.h"
|
|
||||||
#include "intio.h"
|
|
||||||
#include "open.h"
|
|
||||||
#include "mod2sparse.h"
|
|
||||||
#include "mod2dense.h"
|
|
||||||
#include "mod2convert.h"
|
|
||||||
#include "rcode.h"
|
|
||||||
#include "distrib.h"
|
|
||||||
|
|
||||||
|
|
||||||
/* METHODS FOR CONSTRUCTING CODES. */
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{ Evencol, /* Uniform number of bits per column, with number specified */
|
|
||||||
Evenboth /* Uniform (as possible) over both columns and rows */
|
|
||||||
} make_method;
|
|
||||||
|
|
||||||
|
|
||||||
void make_ldpc (int, make_method, distrib *, int);
|
|
||||||
int *column_partition (distrib *, int);
|
|
||||||
void usage (void);
|
|
||||||
|
|
||||||
|
|
||||||
/* MAIN PROGRAM. */
|
|
||||||
|
|
||||||
int main
|
|
||||||
( int argc,
|
|
||||||
char **argv
|
|
||||||
)
|
|
||||||
{
|
|
||||||
make_method method;
|
|
||||||
char *file, **meth;
|
|
||||||
int seed, no4cycle;
|
|
||||||
distrib *d;
|
|
||||||
char junk;
|
|
||||||
FILE *f;
|
|
||||||
|
|
||||||
/* Look at initial arguments. */
|
|
||||||
|
|
||||||
if (!(file = argv[1])
|
|
||||||
|| !argv[2] || sscanf(argv[2],"%d%c",&M,&junk)!=1 || M<=0
|
|
||||||
|| !argv[3] || sscanf(argv[3],"%d%c",&N,&junk)!=1 || N<=0
|
|
||||||
|| !argv[4] || sscanf(argv[4],"%d%c",&seed,&junk)!=1)
|
|
||||||
{ usage();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Look at the arguments specifying the method for producing the code. */
|
|
||||||
|
|
||||||
meth = argv+5;
|
|
||||||
|
|
||||||
if (!meth[0]) usage();
|
|
||||||
|
|
||||||
no4cycle = 0;
|
|
||||||
|
|
||||||
if (strcmp(meth[0],"evencol")==0 || strcmp(meth[0],"evenboth")==0)
|
|
||||||
{ method = strcmp(meth[0],"evencol")==0 ? Evencol : Evenboth;
|
|
||||||
if (!meth[1])
|
|
||||||
{ usage();
|
|
||||||
}
|
|
||||||
d = distrib_create(meth[1]);
|
|
||||||
if (d==0)
|
|
||||||
{ usage();
|
|
||||||
}
|
|
||||||
if (meth[2])
|
|
||||||
{ if (strcmp(meth[2],"no4cycle")==0)
|
|
||||||
{ no4cycle = 1;
|
|
||||||
if (meth[3])
|
|
||||||
{ usage();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ usage();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ usage();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check for some problems. */
|
|
||||||
|
|
||||||
if (distrib_max(d)>M)
|
|
||||||
{ fprintf(stderr,
|
|
||||||
"At least one checks per bit (%d) is greater than total checks (%d)\n",
|
|
||||||
distrib_max(d), M);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (distrib_max(d)==M && N>1 && no4cycle)
|
|
||||||
{ fprintf(stderr,
|
|
||||||
"Can't eliminate cycles of length four with this many checks per bit\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Make the parity check matrix. */
|
|
||||||
|
|
||||||
make_ldpc(seed,method,d,no4cycle);
|
|
||||||
|
|
||||||
/* Write out the parity check matrix. */
|
|
||||||
|
|
||||||
f = open_file_std(file,"wb");
|
|
||||||
if (f==NULL)
|
|
||||||
{ fprintf(stderr,"Can't create parity check file: %s\n",file);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
intio_write(f,('P'<<8)+0x80);
|
|
||||||
|
|
||||||
if (ferror(f) || !mod2sparse_write(f,H) || fclose(f)!=0)
|
|
||||||
{ fprintf(stderr,"Error writing to parity check file %s\n",file);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* PRINT USAGE MESSAGE AND EXIT. */
|
|
||||||
|
|
||||||
void usage(void)
|
|
||||||
{ fprintf(stderr,"Usage: make-ldpc pchk-file n-checks n-bits seed method\n");
|
|
||||||
fprintf(stderr,"Method: evencol checks-per-col [ \"no4cycle\" ]\n");
|
|
||||||
fprintf(stderr," or: evencol checks-distribution [ \"no4cycle\" ]\n");
|
|
||||||
fprintf(stderr," or: evenboth checks-per-col [ \"no4cycle\" ]\n");
|
|
||||||
fprintf(stderr," or: evenboth checks-distribution [ \"no4cycle\" ]\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* CREATE A SPARSE PARITY-CHECK MATRIX. Of size M by N, stored in H. */
|
|
||||||
|
|
||||||
void make_ldpc
|
|
||||||
( int seed, /* Random number seed */
|
|
||||||
make_method method, /* How to make it */
|
|
||||||
distrib *d, /* Distribution list specified */
|
|
||||||
int no4cycle /* Eliminate cycles of length four? */
|
|
||||||
)
|
|
||||||
{
|
|
||||||
mod2entry *e, *f, *g, *h;
|
|
||||||
int added, uneven, elim4, all_even, n_full, left;
|
|
||||||
int i, j, k, t, z, cb_N;
|
|
||||||
int *part, *u;
|
|
||||||
|
|
||||||
rand_seed(10*seed+1);
|
|
||||||
|
|
||||||
H = mod2sparse_allocate(M,N);
|
|
||||||
part = column_partition(d,N);
|
|
||||||
|
|
||||||
/* Create the initial version of the parity check matrix. */
|
|
||||||
|
|
||||||
switch (method)
|
|
||||||
{
|
|
||||||
case Evencol:
|
|
||||||
{
|
|
||||||
z = 0;
|
|
||||||
left = part[z];
|
|
||||||
|
|
||||||
for (j = 0; j<N; j++)
|
|
||||||
{ while (left==0)
|
|
||||||
{ z += 1;
|
|
||||||
if (z>distrib_size(d))
|
|
||||||
{ abort();
|
|
||||||
}
|
|
||||||
left = part[z];
|
|
||||||
}
|
|
||||||
for (k = 0; k<distrib_num(d,z); k++)
|
|
||||||
{ do
|
|
||||||
{ i = rand_int(M);
|
|
||||||
} while (mod2sparse_find(H,i,j));
|
|
||||||
mod2sparse_insert(H,i,j);
|
|
||||||
}
|
|
||||||
left -= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case Evenboth:
|
|
||||||
{
|
|
||||||
cb_N = 0;
|
|
||||||
for (z = 0; z<distrib_size(d); z++)
|
|
||||||
{ cb_N += distrib_num(d,z) * part[z];
|
|
||||||
}
|
|
||||||
|
|
||||||
u = chk_alloc (cb_N, sizeof *u);
|
|
||||||
|
|
||||||
for (k = cb_N-1; k>=0; k--)
|
|
||||||
{ u[k] = k%M;
|
|
||||||
}
|
|
||||||
|
|
||||||
uneven = 0;
|
|
||||||
t = 0;
|
|
||||||
z = 0;
|
|
||||||
left = part[z];
|
|
||||||
|
|
||||||
for (j = 0; j<N; j++)
|
|
||||||
{
|
|
||||||
while (left==0)
|
|
||||||
{ z += 1;
|
|
||||||
if (z>distrib_size(d))
|
|
||||||
{ abort();
|
|
||||||
}
|
|
||||||
left = part[z];
|
|
||||||
}
|
|
||||||
|
|
||||||
for (k = 0; k<distrib_num(d,z); k++)
|
|
||||||
{
|
|
||||||
for (i = t; i<cb_N && mod2sparse_find(H,u[i],j); i++) ;
|
|
||||||
|
|
||||||
if (i==cb_N)
|
|
||||||
{ uneven += 1;
|
|
||||||
do
|
|
||||||
{ i = rand_int(M);
|
|
||||||
} while (mod2sparse_find(H,i,j));
|
|
||||||
mod2sparse_insert(H,i,j);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ do
|
|
||||||
{ i = t + rand_int(cb_N-t);
|
|
||||||
} while (mod2sparse_find(H,u[i],j));
|
|
||||||
mod2sparse_insert(H,u[i],j);
|
|
||||||
u[i] = u[t];
|
|
||||||
t += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
left -= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (uneven>0)
|
|
||||||
{ fprintf(stderr,"Had to place %d checks in rows unevenly\n",uneven);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default: abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add extra bits to avoid rows with less than two checks. */
|
|
||||||
|
|
||||||
added = 0;
|
|
||||||
|
|
||||||
for (i = 0; i<M; i++)
|
|
||||||
{ e = mod2sparse_first_in_row(H,i);
|
|
||||||
if (mod2sparse_at_end(e))
|
|
||||||
{ j = rand_int(N);
|
|
||||||
e = mod2sparse_insert(H,i,j);
|
|
||||||
added += 1;
|
|
||||||
}
|
|
||||||
e = mod2sparse_first_in_row(H,i);
|
|
||||||
if (mod2sparse_at_end(mod2sparse_next_in_row(e)) && N>1)
|
|
||||||
{ do
|
|
||||||
{ j = rand_int(N);
|
|
||||||
} while (j==mod2sparse_col(e));
|
|
||||||
mod2sparse_insert(H,i,j);
|
|
||||||
added += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (added>0)
|
|
||||||
{ fprintf(stderr,
|
|
||||||
"Added %d extra bit-checks to make row counts at least two\n",
|
|
||||||
added);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add extra bits to try to avoid problems with even column counts. */
|
|
||||||
|
|
||||||
n_full = 0;
|
|
||||||
all_even = 1;
|
|
||||||
for (z = 0; z<distrib_size(d); z++)
|
|
||||||
{ if (distrib_num(d,z)==M)
|
|
||||||
{ n_full += part[z];
|
|
||||||
}
|
|
||||||
if (distrib_num(d,z)%2==1)
|
|
||||||
{ all_even = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (all_even && N-n_full>1 && added<2)
|
|
||||||
{ int a;
|
|
||||||
for (a = 0; added+a<2; a++)
|
|
||||||
{ do
|
|
||||||
{ i = rand_int(M);
|
|
||||||
j = rand_int(N);
|
|
||||||
} while (mod2sparse_find(H,i,j));
|
|
||||||
mod2sparse_insert(H,i,j);
|
|
||||||
}
|
|
||||||
fprintf(stderr,
|
|
||||||
"Added %d extra bit-checks to try to avoid problems from even column counts\n",
|
|
||||||
a);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Eliminate cycles of length four, if asked, and if possible. */
|
|
||||||
|
|
||||||
if (no4cycle)
|
|
||||||
{
|
|
||||||
elim4 = 0;
|
|
||||||
|
|
||||||
for (t = 0; t<10; t++)
|
|
||||||
{ k = 0;
|
|
||||||
for (j = 0; j<N; j++)
|
|
||||||
{ for (e = mod2sparse_first_in_col(H,j);
|
|
||||||
!mod2sparse_at_end(e);
|
|
||||||
e = mod2sparse_next_in_col(e))
|
|
||||||
{ for (f = mod2sparse_first_in_row(H,mod2sparse_row(e));
|
|
||||||
!mod2sparse_at_end(f);
|
|
||||||
f = mod2sparse_next_in_row(f))
|
|
||||||
{ if (f==e) continue;
|
|
||||||
for (g = mod2sparse_first_in_col(H,mod2sparse_col(f));
|
|
||||||
!mod2sparse_at_end(g);
|
|
||||||
g = mod2sparse_next_in_col(g))
|
|
||||||
{ if (g==f) continue;
|
|
||||||
for (h = mod2sparse_first_in_row(H,mod2sparse_row(g));
|
|
||||||
!mod2sparse_at_end(h);
|
|
||||||
h = mod2sparse_next_in_row(h))
|
|
||||||
{ if (mod2sparse_col(h)==j)
|
|
||||||
{ do
|
|
||||||
{ i = rand_int(M);
|
|
||||||
} while (mod2sparse_find(H,i,j));
|
|
||||||
mod2sparse_delete(H,e);
|
|
||||||
mod2sparse_insert(H,i,j);
|
|
||||||
elim4 += 1;
|
|
||||||
k += 1;
|
|
||||||
goto nextj;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
nextj: ;
|
|
||||||
}
|
|
||||||
if (k==0) break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (elim4>0)
|
|
||||||
{ fprintf(stderr,
|
|
||||||
"Eliminated %d cycles of length four by moving checks within column\n",
|
|
||||||
elim4);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (t==10)
|
|
||||||
{ fprintf(stderr,
|
|
||||||
"Couldn't eliminate all cycles of length four in 10 passes\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* PARTITION THE COLUMNS ACCORDING TO THE SPECIFIED PROPORTIONS. It
|
|
||||||
may not be possible to do this exactly. Returns a pointer to an
|
|
||||||
array of integers containing the numbers of columns corresponding
|
|
||||||
to the entries in the distribution passed. */
|
|
||||||
|
|
||||||
int *column_partition
|
|
||||||
( distrib *d, /* List of proportions and number of check-bits */
|
|
||||||
int n /* Total number of columns to partition */
|
|
||||||
)
|
|
||||||
{
|
|
||||||
double *trunc;
|
|
||||||
int *part;
|
|
||||||
int cur, used;
|
|
||||||
int i, j;
|
|
||||||
|
|
||||||
trunc = chk_alloc (distrib_size(d), sizeof(double));
|
|
||||||
part = chk_alloc (distrib_size(d), sizeof(int));
|
|
||||||
|
|
||||||
used = 0;
|
|
||||||
for (i = 0; i<distrib_size(d); i++)
|
|
||||||
{ cur = floor(distrib_prop(d,i)*n);
|
|
||||||
part[i] = cur;
|
|
||||||
trunc[i] = distrib_prop(d,i)*n - cur;
|
|
||||||
used += cur;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (used>n)
|
|
||||||
{ abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
while (used<n)
|
|
||||||
{ cur = 0;
|
|
||||||
for (j = 1; j<distrib_size(d); j++)
|
|
||||||
{ if (trunc[j]>trunc[cur])
|
|
||||||
{ cur = j;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
part[cur] += 1;
|
|
||||||
used += 1;
|
|
||||||
trunc[cur] = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(trunc);
|
|
||||||
return part;
|
|
||||||
}
|
|
||||||
Binary file not shown.
@@ -1,371 +0,0 @@
|
|||||||
<HTML><HEAD>
|
|
||||||
|
|
||||||
<TITLE> Creating a Parity Check Matrix </TITLE>
|
|
||||||
|
|
||||||
</HEAD><BODY>
|
|
||||||
|
|
||||||
|
|
||||||
<H1> Creating a Parity Check Matrix </H1>
|
|
||||||
|
|
||||||
<P>This software deals only with linear block codes for binary (ie,
|
|
||||||
modulo-2, GF(2)) vectors. The set of valid codewords for a linear
|
|
||||||
code can be specified by giving a <I>parity check matrix</I>,
|
|
||||||
<B>H</B>, with <I>M</I> rows and <I>N</I> columns. The valid
|
|
||||||
codewords are the vectors, <B>x</B>, of length <I>N</I>, for which
|
|
||||||
<B>Hx</B>=<B>0</B>, where all arithmetic is done modulo-2. Each row
|
|
||||||
of <B>H</B> represents a parity check on a subset of the bits in
|
|
||||||
<B>x</B>; all these parity checks must be satisfied for <B>x</B> to be
|
|
||||||
a codeword. Note that the parity check matrix for a given code (ie,
|
|
||||||
for a given set of valid codewords) is not unique, even after
|
|
||||||
eliminating rows of <B>H</B> that are redundant because they are
|
|
||||||
linear combinations of other rows.
|
|
||||||
|
|
||||||
<P>This software stores parity check matrices in files in a sparse
|
|
||||||
format. These parity-check files are <I>not</I> human-readable
|
|
||||||
(except by using the <A HREF="#print-pchk"><TT>print-pchk</TT></A>
|
|
||||||
program). However, they <I>are</I> readable on a machine with a
|
|
||||||
different architecture than they were written on.
|
|
||||||
|
|
||||||
<P>Some LDPC software by David MacKay and others uses the
|
|
||||||
<A HREF="http://www.inference.phy.cam.ac.uk/mackay/codes/alist.html">alist
|
|
||||||
format</A> for parity check matrices. Two programs for converting
|
|
||||||
between this format and the format for sparse parity check matrices
|
|
||||||
used by this software are provided.
|
|
||||||
|
|
||||||
|
|
||||||
<A NAME="ldpc"><H2>Methods for constructing LDPC codes</H2></A>
|
|
||||||
|
|
||||||
<P>This software is primarily intended for experimentation with Low
|
|
||||||
Density Parity Check (LDPC) codes. These codes can be constructed by
|
|
||||||
various methods, which generally involve some random selection of
|
|
||||||
where to put 1s in a parity check matrix. Any such method for
|
|
||||||
constructing LDPC codes will have the property that it produces parity
|
|
||||||
check matrices in which the number of 1s in a column is approximately
|
|
||||||
the same (perhaps on average) for any size parity check matrix. For a
|
|
||||||
given code rate, these matrices therefore become increasingly sparse
|
|
||||||
as the length of a codeword, and hence the number of parity checks,
|
|
||||||
increases.
|
|
||||||
|
|
||||||
<P>Many methods for constructing LDPC matrices are described in the
|
|
||||||
<A HREF="refs.html">references</A>. Two simple methods are currently
|
|
||||||
implemented by this software, both of which operate according to the
|
|
||||||
following scheme:
|
|
||||||
<OL>
|
|
||||||
<LI> Create a preliminary parity check matrix by one of the methods.
|
|
||||||
<LI> Add 1s to the parity check matrix in order to avoid rows that have no
|
|
||||||
1s in them, and hence are redundant, or which have only one 1 in them,
|
|
||||||
in which case the corresponding codeword bits will always be zero.
|
|
||||||
The places within such a row to add these 1s are selected randomly.
|
|
||||||
<LI> If the preliminary parity check matrix constructed in step (1) had
|
|
||||||
an even number of 1s in each column, add further 1s to avoid the problem
|
|
||||||
that this will cause the rows to add to zero, and hence at least
|
|
||||||
one check will be redundant. Up to two 1s are added (since it is also
|
|
||||||
undesirable for the sum of the rows to have only one 1 in it), at
|
|
||||||
positions selected randomly from the entire matrix. However, the
|
|
||||||
number of 1s to add in this step is reduced by the number already added
|
|
||||||
in step (2). (Note that although redundant checks are not disastrous,
|
|
||||||
they are better avoided; see the discussion of <A HREF="dep-H.html">linear
|
|
||||||
dependence in parity check matrices</A>.)
|
|
||||||
<LI> If requested, try to eliminate
|
|
||||||
situations where a pair of columns both have 1s in a particular pair of
|
|
||||||
rows, which correspond to cycles of length four in the factor graph of
|
|
||||||
the parity check matrix. When such a situation is detected, one of the
|
|
||||||
1s involved is moved randomly within its column. This continues until
|
|
||||||
no such situations remain, or until 10 passes over all columns have
|
|
||||||
failed to eliminate all such situations.
|
|
||||||
</OL>
|
|
||||||
|
|
||||||
<P>The <I>evencol</I> method is the simplest way of performing step
|
|
||||||
(1) of the above procedure. For each column of the parity check
|
|
||||||
matrix, independently, it places a specified number of 1s in positions
|
|
||||||
selected uniformly at random, with the only constraint being that
|
|
||||||
these 1s be in distinct rows. Note that despite the name, the columns
|
|
||||||
do not have to have the same number of 1s - a distribution over
|
|
||||||
several values for the number of 1s in a column can be specified
|
|
||||||
instead. Such codes with different-weight columns are sometimes
|
|
||||||
better than codes in which every column has the same weight.
|
|
||||||
|
|
||||||
<P>The <I>evenboth</I> method also puts a specified number of 1s in
|
|
||||||
each column, but it tries as well to keep the numbers of 1s in the
|
|
||||||
rows approximately the same. Initially, it creates indicators for all
|
|
||||||
the 1s that will be required, and assigns these 1s to rows as evenly
|
|
||||||
as it can, favouring earlier rows if an exactly even split is not
|
|
||||||
possible. It then assigns 1s to successive columns by selecting
|
|
||||||
randomly, without replacement, from this initial supply of 1s, subject
|
|
||||||
only to the constraint that the 1s assigned to a column must be in
|
|
||||||
distinct rows. If at some point it is impossible to put the required
|
|
||||||
number of 1s in a column by picking from the 1s remaining, a 1 is set
|
|
||||||
in that column without reference to other columns, creating a possible
|
|
||||||
unevenness.
|
|
||||||
|
|
||||||
<P>Note that regardless of how evenly 1s are distributed in the
|
|
||||||
preliminary parity check matrix created in step (1), steps (2) and (3)
|
|
||||||
can make the numbers of 1s in the both rows and columns be uneven, and
|
|
||||||
step (4), if done, can make the numbers of 1s in rows be uneven.
|
|
||||||
|
|
||||||
|
|
||||||
<P><A NAME="make-pchk"><HR><B>make-pchk</B>: Make a parity check
|
|
||||||
matrix by explicit specification.
|
|
||||||
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
make-pchk <I>pchk-file n-checks n-bits row</I>:<I>col ...</I>
|
|
||||||
</PRE></BLOCKQUOTE>
|
|
||||||
|
|
||||||
<P>Creates a file named <TT><I>pchk-file</I></TT> in
|
|
||||||
which it stores a parity check matrix with <TT><I>n-checks</I></TT>
|
|
||||||
rows and <TT><I>n-bits</I></TT> columns. This parity check matrix
|
|
||||||
consists of all 0s except for 1s at the <I>row</I>:<I>col</I>
|
|
||||||
positions listed. Rows and columns are numbered starting at zero.
|
|
||||||
This program is intended primarily for testing and demonstration
|
|
||||||
purposes.
|
|
||||||
|
|
||||||
<P><B>Example:</B> The well-known Hamming code with codewords of
|
|
||||||
length <I>N</I>=7 and with <I>M</I>=3 parity checks can be can be
|
|
||||||
created as follows:
|
|
||||||
<UL><PRE>
|
|
||||||
<LI>make-pchk ham7.pchk 3 7 0:0 0:3 0:4 0:5 1:1 1:3 1:4 1:6 2:2 2:4 2:5 2:6
|
|
||||||
</PRE></UL>
|
|
||||||
|
|
||||||
|
|
||||||
<P><A NAME="alist-to-pchk"><HR><B>alist-to-pchk</B>: Convert a parity
|
|
||||||
check matrix from alist format to the sparse matrix format used by
|
|
||||||
this software.
|
|
||||||
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
alist-to-pchk [ -t ] <I>alist-file pchk-file</I>
|
|
||||||
</PRE></BLOCKQUOTE>
|
|
||||||
|
|
||||||
<P>Converts a parity check matrix in
|
|
||||||
<A HREF="http://www.inference.phy.cam.ac.uk/mackay/codes/alist.html">alist
|
|
||||||
format</A> stored in the file named <TT><I>alist-file</I></TT> to
|
|
||||||
the sparse matrix format used by this software, storing it in the
|
|
||||||
file named <TT><I>pchk-file</I></TT>.
|
|
||||||
|
|
||||||
<P>If the <B>-t</B> option is given, the transpose of the parity check
|
|
||||||
matrix in <TT><I>alist-file</I></TT> is stored in the
|
|
||||||
<TT><I>pchk-file</I></TT>.
|
|
||||||
|
|
||||||
<P>Any zeros indexes in the alist file are ignored, so that alist files
|
|
||||||
with zero padding (as required in the specification) are accepted,
|
|
||||||
but files without this zero padding are also accepted. Newlines
|
|
||||||
are ignored by <TT>alist-to-pchk</TT>, so no error is reported if
|
|
||||||
the set of indexes in a row or column description are not those
|
|
||||||
on a single line.
|
|
||||||
|
|
||||||
|
|
||||||
<P><A NAME="pchk-to-alist"><HR><B>pchk-to-alist</B>: Convert a parity
|
|
||||||
check matrix to alist format.
|
|
||||||
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
pchk-to-alist [ -t ] [ -z ] <I>pchk-file alist-file</I>
|
|
||||||
</PRE></BLOCKQUOTE>
|
|
||||||
|
|
||||||
<P>Converts a parity check matrix stored in the sparse matrix format
|
|
||||||
used by this software, in the file named <TT><I>pchk-file</I></TT>, to
|
|
||||||
the <A
|
|
||||||
HREF="http://www.inference.phy.cam.ac.uk/mackay/codes/alist.html">alist
|
|
||||||
format</A>, storing it in the file named <TT><I>alist-file</I></TT>.
|
|
||||||
|
|
||||||
<P>If the <B>-t</B> option is given, the transpose of the parity check
|
|
||||||
matrix is converted to alist format.
|
|
||||||
|
|
||||||
<P>If the number of 1s is not
|
|
||||||
the same for each row or each column, the alist format specification
|
|
||||||
says that the list of indexes of 1s for each row or column should
|
|
||||||
be padded with zeros to the maximum number of indexes. By default,
|
|
||||||
<TT>pchk-to-alist</TT> does this, but output of these 0s can be
|
|
||||||
suppressed by specifying the <B>-z</B> option. (The <TT>alist-to-pchk</TT>
|
|
||||||
program will accept alist files produced with or without the <B>-z</B>
|
|
||||||
option.)
|
|
||||||
|
|
||||||
|
|
||||||
<P><A NAME="print-pchk"><HR><B>print-pchk</B>: Print a parity check matrix.
|
|
||||||
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
print-pchk [ -d ] [ -t ] <I>pchk-file</I>
|
|
||||||
</PRE></BLOCKQUOTE>
|
|
||||||
|
|
||||||
<P>Prints a human-readable representation of the parity check matrix stored
|
|
||||||
in <TT><I>pchk-file</I></TT>.
|
|
||||||
The <B>-d</B> option causes the matrix to be printed in a dense
|
|
||||||
format, even though parity check matrices are always stored in the
|
|
||||||
file in a sparse format. If the <B>-t</B> option is present, what is
|
|
||||||
printed is the transpose of the parity check matrix.
|
|
||||||
|
|
||||||
<P>The sparse display format consists of one line for every row of the
|
|
||||||
matrix, consisting of the row number, a colon, and the column numbers
|
|
||||||
at which 1s are located (possibly none). Row and columns numbers
|
|
||||||
start at zero. No attempt is made to wrap long lines.
|
|
||||||
|
|
||||||
<P>The dense display is the obvious array of 0s and 1s. Long lines
|
|
||||||
are not wrapped.
|
|
||||||
|
|
||||||
<P><B>Example</B>: The parity check matrix for the Hamming code created
|
|
||||||
by the example for <A HREF="#make-pchk"><TT>make-pchk</TT></A> would print
|
|
||||||
as follows:
|
|
||||||
<UL><PRE>
|
|
||||||
<LI>print-pchk ham7.pchk
|
|
||||||
|
|
||||||
Parity check matrix in ham7.pchk (sparse format):
|
|
||||||
|
|
||||||
0: 0 3 4 5
|
|
||||||
1: 1 3 4 6
|
|
||||||
2: 2 4 5 6
|
|
||||||
|
|
||||||
<LI>print-pchk -d ham7.pchk
|
|
||||||
|
|
||||||
Parity check matrix in ham7.pchk (dense format):
|
|
||||||
|
|
||||||
1 0 0 1 1 1 0
|
|
||||||
0 1 0 1 1 0 1
|
|
||||||
0 0 1 0 1 1 1
|
|
||||||
</PRE></UL>
|
|
||||||
|
|
||||||
|
|
||||||
<P><A NAME="make-ldpc"><HR><B>make-ldpc</B>: Make a low density parity
|
|
||||||
check matrix, by random generation.
|
|
||||||
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
make-ldpc <I>pchk-file n-checks n-bits seed method</I>
|
|
||||||
</PRE>
|
|
||||||
<BLOCKQUOTE>
|
|
||||||
where <TT><I>method</I></TT> is one of the following:
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
evencol <I>checks-per-col</I> [ no4cycle ]
|
|
||||||
|
|
||||||
evencol <I>checks-distribution</I> [ no4cycle ]
|
|
||||||
|
|
||||||
evenboth <I>checks-per-col</I> [ no4cycle ]
|
|
||||||
|
|
||||||
evenboth <I>checks-distribution</I> [ no4cycle ]
|
|
||||||
</PRE></BLOCKQUOTE>
|
|
||||||
</BLOCKQUOTE>
|
|
||||||
</BLOCKQUOTE>
|
|
||||||
|
|
||||||
<P>Creates a Low Density Parity Check matrix with
|
|
||||||
<TT><I>n-checks</I></TT> rows and <TT><I>n-bits</I></TT> columns. The
|
|
||||||
parity check matrix will be generated pseudo-randomly by the indicated
|
|
||||||
method, using a pseudo-random number stream determined by <TT><I>seed</I></TT>.
|
|
||||||
The actual random number seed used is 10 times <TT><I>seed</I></TT> plus 1,
|
|
||||||
so as to avoid using the same stream as any of the other programs.
|
|
||||||
|
|
||||||
<P>Two methods are currently available for creating the LDPC matrix,
|
|
||||||
specified by <TT>evencol</TT> or <TT>evenboth</TT>. Both methods
|
|
||||||
produce a matrix in which the number of 1s in each column is
|
|
||||||
approximately <TT><I>checks-per-col</I></TT>, or varies from column
|
|
||||||
to column according the the <TT><I>checks-distribution</I></TT>.
|
|
||||||
The <TT>evenboth</TT> method also tries to make the number of checks per row be
|
|
||||||
approximately uniform; if this is not achieved, a message saying that
|
|
||||||
how many bits were placed unevenly is displayed on standard error.
|
|
||||||
|
|
||||||
<P>For both methods, the <TT>no4cycle</TT> option will cause cycles of
|
|
||||||
length four in the factor graph representation of the code to be
|
|
||||||
eliminated (if possible). A message is displayed on standard error if
|
|
||||||
this is not achieved.
|
|
||||||
|
|
||||||
<P>A <TT><I>checks-distribution</I></TT> has the form
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
<I>prop</I>x<I>count</I>/<I>prop</I>x<I>count</I>/...
|
|
||||||
</PRE></BLOCKQUOTE>
|
|
||||||
Here, <TT><I>prop</I></TT> is a proportion of columns that have the
|
|
||||||
associated <TT><I>count</I></TT>. The proportions need not sum to one,
|
|
||||||
since they will be automatically normalized. For example, <TT>0.3x4/0.2x5</TT>
|
|
||||||
specifies that 60% of the columns will contain four 1s and 40% will
|
|
||||||
contain five 1s.
|
|
||||||
|
|
||||||
<P>See the <A HREF="#ldpc">discussion above</A> for more details
|
|
||||||
on how these methods construct LDPC matrices.
|
|
||||||
|
|
||||||
<P><B>Example 1:</B> The <TT>make-ldpc</TT> command below creates
|
|
||||||
a 20 by 40 low density parity check matrix with three 1s per
|
|
||||||
column and six 1s per row, using random seed 1. The matrix
|
|
||||||
is then printed in sparse format
|
|
||||||
using <A HREF="#print-pchk">print-pchk</A>.
|
|
||||||
<UL><PRE>
|
|
||||||
<LI>make-ldpc ldpc.pchk 20 40 1 evenboth 3
|
|
||||||
<LI>print-pchk ldpc.pchk
|
|
||||||
|
|
||||||
Parity check matrix in ldpc.pchk (sparse format):
|
|
||||||
|
|
||||||
0: 10 14 18 27 38 39
|
|
||||||
1: 2 3 5 11 27 30
|
|
||||||
2: 15 19 20 21 24 26
|
|
||||||
3: 2 4 25 28 32 38
|
|
||||||
4: 7 9 12 22 33 34
|
|
||||||
5: 5 6 21 22 26 32
|
|
||||||
6: 1 4 13 24 25 28
|
|
||||||
7: 1 14 28 29 30 36
|
|
||||||
8: 11 13 22 23 32 37
|
|
||||||
9: 6 8 13 20 31 33
|
|
||||||
10: 0 3 24 29 31 38
|
|
||||||
11: 7 12 15 16 17 23
|
|
||||||
12: 3 16 29 34 35 39
|
|
||||||
13: 0 8 10 18 36 37
|
|
||||||
14: 6 11 18 20 35 39
|
|
||||||
15: 0 7 14 16 25 37
|
|
||||||
16: 2 4 9 19 30 31
|
|
||||||
17: 5 9 10 17 19 23
|
|
||||||
18: 8 15 17 21 26 27
|
|
||||||
19: 1 12 33 34 35 36
|
|
||||||
</PRE></UL>
|
|
||||||
|
|
||||||
<P><B>Example 2:</B> The two <TT>make-ldpc</TT> commands
|
|
||||||
below both create a 20 by 40 low density parity check matrix with 30%
|
|
||||||
of columns with two 1s, 60% of columns with three 1s, and 10% of
|
|
||||||
columns with seven 1s. The transpose of the parity check matrix
|
|
||||||
is then printed in sparse format.
|
|
||||||
<UL><PRE>
|
|
||||||
<LI>make-ldpc ldpc.pchk 20 40 1 evenboth 0.3x2/0.6x3/0.1x7
|
|
||||||
<LI>make-ldpc ldpc.pchk 20 40 1 evenboth 3x2/6x3/1x7
|
|
||||||
<LI>print-pchk -t ldpc.pchk
|
|
||||||
|
|
||||||
Transpose of parity check matrix in ldpc.pchk (sparse format):
|
|
||||||
|
|
||||||
0: 13 16
|
|
||||||
1: 9 18
|
|
||||||
2: 1 10
|
|
||||||
3: 3 15
|
|
||||||
4: 4 14
|
|
||||||
5: 14 17
|
|
||||||
6: 4 5
|
|
||||||
7: 1 8
|
|
||||||
8: 0 4
|
|
||||||
9: 9 14
|
|
||||||
10: 5 8
|
|
||||||
11: 6 16
|
|
||||||
12: 2 12 19
|
|
||||||
13: 3 17 18
|
|
||||||
14: 2 16 17
|
|
||||||
15: 2 11 18
|
|
||||||
16: 12 13 19
|
|
||||||
17: 7 13 18
|
|
||||||
18: 2 5 11
|
|
||||||
19: 10 12 14
|
|
||||||
20: 1 8 16
|
|
||||||
21: 10 18 19
|
|
||||||
22: 3 6 17
|
|
||||||
23: 7 11 12
|
|
||||||
24: 1 2 19
|
|
||||||
25: 0 6 7
|
|
||||||
26: 5 8 15
|
|
||||||
27: 1 4 7
|
|
||||||
28: 6 13 19
|
|
||||||
29: 3 4 11
|
|
||||||
30: 3 8 17
|
|
||||||
31: 4 5 9
|
|
||||||
32: 0 10 15
|
|
||||||
33: 7 11 13
|
|
||||||
34: 8 12 19
|
|
||||||
35: 0 2 10
|
|
||||||
36: 0 5 9 11 15 17 18
|
|
||||||
37: 0 1 2 6 7 14 16
|
|
||||||
38: 0 1 3 9 12 13 15
|
|
||||||
39: 3 6 9 10 14 15 16
|
|
||||||
</PRE></UL>
|
|
||||||
|
|
||||||
<HR>
|
|
||||||
|
|
||||||
<A HREF="index.html">Back to index for LDPC software</A>
|
|
||||||
|
|
||||||
</BODY></HTML>
|
|
||||||
|
|
||||||
@@ -1,89 +0,0 @@
|
|||||||
<HTML><HEAD>
|
|
||||||
|
|
||||||
<TITLE> Modules Used in LDPC Programs </TITLE>
|
|
||||||
|
|
||||||
</HEAD><BODY>
|
|
||||||
|
|
||||||
|
|
||||||
<H1> Modules Used in LDPC Programs </H1>
|
|
||||||
|
|
||||||
You may need to familiarize yourself with the modules documented here
|
|
||||||
in order to <A HREF="modify.html">modify the LDPC programs</A>.
|
|
||||||
These modules may also be useful for other purposes.
|
|
||||||
|
|
||||||
<P>Click on the title of a module below for general information, or on
|
|
||||||
specific routines for detailed documentation.
|
|
||||||
|
|
||||||
<P><A HREF="mod2dense.html">Dense modulo-2 matrix routines</A>:
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
<A HREF="mod2dense.html#dimension-sec"><I>Dimension macros:</I> mod2dense_rows mod2dense_cols</A>
|
|
||||||
|
|
||||||
<I><A HREF="mod2dense.html#alloc-sec">Allocation:</A> <A HREF="mod2dense.html#copy-clear-sec">Copy/Clear:</A> <A HREF="mod2dense.html#input-output-sec">Input/Output:</A> <A HREF="mod2dense.html#elementary-sec">Elementary ops:</A></I>
|
|
||||||
|
|
||||||
<A HREF="mod2dense.html#allocate">mod2dense_allocate</A> <A HREF="mod2dense.html#clear">mod2dense_clear</A> <A HREF="mod2dense.html#print">mod2dense_print</A> <A HREF="mod2dense.html#get">mod2dense_get</A>
|
|
||||||
<A HREF="mod2dense.html#free">mod2dense_free</A> <A HREF="mod2dense.html#copy">mod2dense_copy</A> <A HREF="mod2dense.html#write">mod2dense_write</A> <A HREF="mod2dense.html#set">mod2dense_set</A>
|
|
||||||
<A HREF="mod2dense.html#copyrows">mod2dense_copyrows</A> <A HREF="mod2dense.html#read">mod2dense_read</A> <A HREF="mod2dense.html#flip">mod2dense_flip</A>
|
|
||||||
<A HREF="mod2dense.html#copycols">mod2dense_copycols</A>
|
|
||||||
|
|
||||||
<I><A HREF="mod2dense.html#arith-sec">Matrix arithmetic:</A> <A HREF="mod2dense.html#invert-sec">Matrix inversion:</A></I>
|
|
||||||
|
|
||||||
<A HREF="mod2dense.html#transpose">mod2dense_transpose</A> <A HREF="mod2dense.html#invert">mod2dense_invert</A>
|
|
||||||
<A HREF="mod2dense.html#add">mod2dense_add</A> <A HREF="mod2dense.html#forcibly_invert">mod2dense_forcibly_invert</A>
|
|
||||||
<A HREF="mod2dense.html#multiply">mod2dense_multiply</A> <A HREF="mod2dense.html#invert_selected">mod2dense_invert_selected</A>
|
|
||||||
<A HREF="mod2dense.html#equal">mod2dense_equal</A>
|
|
||||||
</PRE></BLOCKQUOTE>
|
|
||||||
|
|
||||||
<P><A HREF="mod2sparse.html">Sparse modulo-2 matrix routines</A>:
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
<A HREF="mod2sparse.html#dimension-sec"><I>Dimension macros:</I> mod2sparse_rows mod2sparse_cols</A>
|
|
||||||
|
|
||||||
<A HREF="mod2sparse.html#traversal-sec"><I>Traversal macros:</I> mod2sparse_first_in_row mod2sparse_next_in_row ...</A>
|
|
||||||
|
|
||||||
<I><A HREF="mod2sparse.html#alloc-sec">Allocation:</A> <A HREF="mod2sparse.html#copy-clear-sec">Copy/Clear:</A> <A HREF="mod2sparse.html#input-output-sec">Input/Output:</A> <A HREF="mod2sparse.html#elementary-sec">Elementary ops:</A></I>
|
|
||||||
|
|
||||||
<A HREF="mod2sparse.html#allocate">mod2sparse_allocate</A> <A HREF="mod2sparse.html#clear">mod2sparse_clear</A> <A HREF="mod2sparse.html#print">mod2sparse_print</A> <A HREF="mod2sparse.html#find">mod2sparse_find</A>
|
|
||||||
<A HREF="mod2sparse.html#free">mod2sparse_free</A> <A HREF="mod2sparse.html#copy">mod2sparse_copy</A> <A HREF="mod2sparse.html#write">mod2sparse_write</A> <A HREF="mod2sparse.html#insert">mod2sparse_insert</A>
|
|
||||||
<A HREF="mod2sparse.html#copyrows">mod2sparse_copyrows</A> <A HREF="mod2sparse.html#read">mod2sparse_read</A> <A HREF="mod2sparse.html#delete">mod2sparse_delete</A>
|
|
||||||
<A HREF="mod2sparse.html#copycols">mod2sparse_copycols</A>
|
|
||||||
|
|
||||||
<I><A HREF="mod2sparse.html#arith-sec">Matrix arithmetic:</A> <A HREF="mod2sparse.html#row-col-ops-sec">Row/Column ops:</A> <A HREF="mod2sparse.html#lu-decomp-sec">LU decomposition:</A></I>
|
|
||||||
|
|
||||||
<A HREF="mod2sparse.html#transpose">mod2sparse_transpose</A> <A HREF="mod2sparse.html#count_row">mod2sparse_count_row</A> <A HREF="mod2sparse.html#decomp">mod2sparse_decomp</A>
|
|
||||||
<A HREF="mod2sparse.html#add">mod2sparse_add</A> <A HREF="mod2sparse.html#count_col">mod2sparse_count_col</A> <A HREF="mod2sparse.html#forward_sub">mod2sparse_forward_sub</A>
|
|
||||||
<A HREF="mod2sparse.html#multiply">mod2sparse_multiply</A> <A HREF="mod2sparse.html#add_row">mod2sparse_add_row</A> <A HREF="mod2sparse.html#backward_sub">mod2sparse_backward_sub</A>
|
|
||||||
<A HREF="mod2sparse.html#mulvec">mod2sparse_mulvec</A> <A HREF="mod2sparse.html#add_col">mod2sparse_add_col</A>
|
|
||||||
<A HREF="mod2sparse.html#equal">mod2sparse_equal</A>
|
|
||||||
</PRE>
|
|
||||||
<A HREF="sparse-LU.html">Discussion of sparse LU decomposition methods.</A>
|
|
||||||
</BLOCKQUOTE>
|
|
||||||
|
|
||||||
<P><A HREF="mod2convert.html">Modulo-2 matrix sparse/dense conversion</A>:
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
<A HREF="mod2convert.html#sparse_to_dense">mod2sparse_to_dense</A>
|
|
||||||
<A HREF="mod2convert.html#dense_to_sparse">mod2dense_to_sparse</A>
|
|
||||||
</PRE></BLOCKQUOTE>
|
|
||||||
|
|
||||||
<P><A HREF="rand.html">Random variate generation routines</A>:
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
<I><A HREF="rand.html#get-set-sec">Set/Get state:<A> <A HREF="rand.html#uniform-sec">Uniform:</A> <A HREF="rand.html#discrete-sec">Discrete:</A> <A HREF="rand.html#continuous-sec">Continuous:</A></I>
|
|
||||||
|
|
||||||
<A HREF="rand.html#seed">rand_seed</A> <A HREF="rand.html#uniform">rand_uniform</A> <A HREF="rand.html#int">rand_int</A> <A HREF="rand.html#gaussian">rand_gaussian</A>
|
|
||||||
<A HREF="rand.html#get_state">rand_get_state</A> <A HREF="rand.html#uniopen">rand_uniopen</A> <A HREF="rand.html#pickd">rand_pickd</A> <A HREF="rand.html#logistic">rand_logistic</A>
|
|
||||||
<A HREF="rand.html#use_state">rand_use_state</A> <A HREF="rand.html#pickf">rand_pickf</A> <A HREF="rand.html#cauchy">rand_cauchy</A>
|
|
||||||
<A HREF="rand.html#poisson">rand_poisson</A> <A HREF="rand.html#gamma">rand_gamma</A>
|
|
||||||
<A HREF="rand.html#permutation">rand_permutation</A> <A HREF="rand.html#exp">rand_exp</A>
|
|
||||||
<A HREF="rand.html#beta">rand_beta</A>
|
|
||||||
</PRE></BLOCKQUOTE>
|
|
||||||
|
|
||||||
<P>Each of the modules above has a test program, called
|
|
||||||
<TT><I>module</I>-test</TT>. These programs are compiled by the command
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
make tests
|
|
||||||
</PRE></BLOCKQUOTE>
|
|
||||||
See the source files for these test programs for further information.
|
|
||||||
|
|
||||||
<HR>
|
|
||||||
|
|
||||||
<A HREF="index.html">Back to index for LDPC software</A>
|
|
||||||
|
|
||||||
</BODY></HTML>
|
|
||||||
@@ -1,342 +0,0 @@
|
|||||||
<HTML><HEAD>
|
|
||||||
|
|
||||||
<TITLE> Decoding Received Blocks </TITLE>
|
|
||||||
|
|
||||||
|
|
||||||
</HEAD><BODY>
|
|
||||||
|
|
||||||
<H1> Decoding Received Blocks </H1>
|
|
||||||
|
|
||||||
Transmitted codewords are decoded from the received data on the basis
|
|
||||||
of the <I>likelihood</I> of the possible codewords, which is the
|
|
||||||
probability of receiving the data that was actually received if the
|
|
||||||
codeword is question were the one that was sent. This software
|
|
||||||
presently deals only with memoryless channels, in which the noise is
|
|
||||||
independent from bit to bit. For such a channel, the likelihood
|
|
||||||
factorizes into a product of likelihoods for each bit.
|
|
||||||
|
|
||||||
For decoding purposes, all that matters is the relative likelihood
|
|
||||||
for a bit to be 1 versus 0. This is captured by the <I>likelihood
|
|
||||||
ratio</I> in favour of a 1, which is P(data | bit is 1) / P(data |
|
|
||||||
bit is 0).
|
|
||||||
|
|
||||||
<P>For a Binary Symmetric Channel with error probability <I>p</I>,
|
|
||||||
the likelihood ratio in favour of a 1 bit is as follows:
|
|
||||||
<BLOCKQUOTE>
|
|
||||||
If the received data was +1: (1-<I>p</I>) / <I>p</I><BR>
|
|
||||||
If the received data was -1: <I>p</I> / (1-<I>p</I>)
|
|
||||||
</BLOCKQUOTE>
|
|
||||||
For an Additive White Gaussian Noise channel, with signals of +1 for a 1 bit
|
|
||||||
and or -1 for a 0 bit, and with noise standard deviation <I>s</I>, the
|
|
||||||
likelihood ratio in favour of a 1 bit when data <I>y</I> was received is
|
|
||||||
<BLOCKQUOTE>
|
|
||||||
exp ( 2y / s<SUP><SMALL>2</SMALL></SUP> )
|
|
||||||
</BLOCKQUOTE>
|
|
||||||
For an Additive White Logistic Noise channel, the corresponding
|
|
||||||
likelihood ratio is
|
|
||||||
<I>d</I><SUB><SMALL>1</SMALL></SUB>/<I>d</I><SUB><SMALL>0</SMALL></SUB>,
|
|
||||||
where
|
|
||||||
<I>d</I><SUB><SMALL>1</SMALL></SUB>=<I>e</I><SUB><SMALL>1</SMALL></SUB>
|
|
||||||
/ (1+<I>e</I><SUB><SMALL>1</SMALL></SUB>)<SUP><SMALL>2</SMALL></SUP> and
|
|
||||||
<I>d</I><SUB><SMALL>0</SMALL></SUB>=<I>e</I><SUB><SMALL>0</SMALL></SUB>
|
|
||||||
/ (1+<I>e</I><SUB><SMALL>0</SMALL></SUB>)<SUP><SMALL>2</SMALL></SUP>,
|
|
||||||
with <I>e</I><SUB><SMALL>1</SMALL></SUB>=exp(-(<I>y</I>-1)/<I>w</I>) and
|
|
||||||
<I>e</I><SUB><SMALL>0</SMALL></SUB>=exp(-(<I>y</I>+1)/<I>w</I>).
|
|
||||||
<BLOCKQUOTE> </BLOCKQUOTE>
|
|
||||||
|
|
||||||
<P>It is usual to consider codewords to be equally likely <I>a
|
|
||||||
priori</I>. This is reasonable if the source messages are all equally
|
|
||||||
likely (any source redundancy being ignored, or remove by a
|
|
||||||
preliminary data compression stage), provided that the mapping from
|
|
||||||
source messages to codewords is onto. Decoding can then be done using
|
|
||||||
only the parity check matrix defining the codewords, without reference
|
|
||||||
to the generator matrix defining the mapping from source messages to
|
|
||||||
codewords. Note that the condition that this mapping be onto isn't
|
|
||||||
true with this software in the atypical case where the code is defined
|
|
||||||
by a parity check matrix with redundant rows; see the discussion of <A
|
|
||||||
HREF="dep-H.html">linear dependence in parity check matrices</A>.
|
|
||||||
This minor complication is mostly ignored here, except by the exhaustive
|
|
||||||
enumeration decoding methods.
|
|
||||||
|
|
||||||
<P>Assuming equal <I>a priori</I> probabilities for codewords, the
|
|
||||||
probability of correctly decoding an entire codeword is minimized by
|
|
||||||
picking the codeword with the highest likelihood. One might instead
|
|
||||||
wish to decode each bit to the value that is most probable. This
|
|
||||||
minimizes the bit error rate, but is not in general guaranteed to lead
|
|
||||||
a decoding for each block to the most probable complete codeword;
|
|
||||||
indeed, the decoding may not be a codeword at all. Minimizing the bit
|
|
||||||
error rate seems nevertheless to be the most sensible objective,
|
|
||||||
unless block boundaries have some significance in a wider context.
|
|
||||||
|
|
||||||
<P>Optimal decoding by either criterion is infeasible for general
|
|
||||||
linear codes when messages are more than about 20 or 30 bits in
|
|
||||||
length. The fundamental advantage of Low Density Parity Check codes
|
|
||||||
is that good (though not optimal) decodings can be obtained by methods
|
|
||||||
such as probability propagation, described next.
|
|
||||||
|
|
||||||
<A NAME="prprp"><H2>Decoding by probability propagation</H2></A>
|
|
||||||
|
|
||||||
<P>The probability propagation algorithm was originally devised by
|
|
||||||
Robert Gallager in the early 1960's and later reinvented by David
|
|
||||||
MacKay and myself. It can be seen as an instance of the sum-product
|
|
||||||
algorithm for inference on factor graphs, and as an instance of belief
|
|
||||||
propagation in probabilistic networks. See the <A
|
|
||||||
HREF="refs.html">references</A> for details. Below, I give a fairly
|
|
||||||
intuitive description of the algorithm.
|
|
||||||
|
|
||||||
<P>The algorithm uses only the parity check matrix for the code, whose
|
|
||||||
columns correspond to codeword bits, and whose rows correspond to
|
|
||||||
parity checks, and the likelihood ratios for the bits derived from the
|
|
||||||
data. It aims to find the probability of each bit of the transmitted
|
|
||||||
codeword being 1, though the results of the algorithm are in general
|
|
||||||
only approximate.
|
|
||||||
|
|
||||||
<P>The begin, information about each bit of the codeword derived from
|
|
||||||
the received data for that bit alone is expressed as a <I>probability
|
|
||||||
ratio</I>, the probability of the bit being 1 divided by the
|
|
||||||
probability of the bit being 0. This probability ratio is equal to
|
|
||||||
the likelihood ratio (see above) for that bit, since 0 and 1 are
|
|
||||||
assumed to be equally likely <I>a priori</I>. As the algorithm
|
|
||||||
progresses, these probability ratios will be modified to take account
|
|
||||||
of information obtained from other bits, in conjunction with the
|
|
||||||
requirement that the parity checks be satisfied. To avoid double
|
|
||||||
counting of information, for every bit, the algorithm maintains a
|
|
||||||
separate probability ratio for each parity check that that bit
|
|
||||||
participates in, giving the probability for that bit to be 1 versus 0
|
|
||||||
based only on information derived from <I>other</I> parity checks,
|
|
||||||
along with the data received for the bit.
|
|
||||||
|
|
||||||
<P>For each parity check, the algorithm maintains separate
|
|
||||||
<I>likelihood ratios</I> (analogous to, but distinct from, the
|
|
||||||
likelihood ratios based on received data), for every bit that
|
|
||||||
participates in that parity check. These ratios give the probability
|
|
||||||
of that parity check being satisfied if the bit in question is 1
|
|
||||||
divided by the probability of the check being satisfied if the bit is
|
|
||||||
0, taking account of the probabilities of each of the <I>other</I>
|
|
||||||
bits participating in this check being 1, as derived from the
|
|
||||||
probability ratios for these bits with respect to this check.
|
|
||||||
|
|
||||||
<P>The algorithm alternates between recalculating the likelihood
|
|
||||||
ratios for each check, which are stored in the <B>lr</B> fields of the
|
|
||||||
parity check matrix entries, and recalculating the probability ratios
|
|
||||||
for each bit, which are stored in the <B>pr</B> fields of the entries
|
|
||||||
in the sparse matrix representation of the parity check matrix. (See
|
|
||||||
the documentation on <A HREF="mod2sparse.html#rep">representation of
|
|
||||||
sparse matrices</A> for details on these entries.)
|
|
||||||
|
|
||||||
<P>Recalculating the likelihood ratio for a check with respect to some
|
|
||||||
bit may appear time consuming, requiring that all possible
|
|
||||||
combinations of values for the other bits participating in the check
|
|
||||||
be considered. Fortunately, there is a short cut. One can calculate
|
|
||||||
<BLOCKQUOTE>
|
|
||||||
<I>t</I>
|
|
||||||
= product of [ 1 / (1+<I>p<SUB><SMALL>i</SMALL></SUB></I>)
|
|
||||||
- <I>p<SUB><SMALL>i</SMALL></SUB></I> /
|
|
||||||
(1+<I>p<SUB><SMALL>i</SMALL></SUB></I>) ]
|
|
||||||
= product of [ 2 / (1+<I>p<SUB><SMALL>i</SMALL></SUB></I>) - 1 ]
|
|
||||||
</BLOCKQUOTE>
|
|
||||||
where the product is over the probability ratios
|
|
||||||
<I>p<SUB><SMALL>i</SMALL></SUB></I> for the other bits participating
|
|
||||||
in this check. Factor <I>i</I> in this product is equal to probability
|
|
||||||
of bit <I>i</I> being 0 minus the probability that it is 1. The terms
|
|
||||||
in the expansion of this product (in the first form above) correspond to
|
|
||||||
possible combinations of values for the other bits, with the result that
|
|
||||||
<I>t</I> will be the probability of the check being satisfied if the bit
|
|
||||||
in question is 0 minus the probability if the bit in question is 1. The
|
|
||||||
likelihood ratio for this check with respect to the bit in question can then
|
|
||||||
be calculated as (1-<I>t</I>)/(1+<I>t</I>).
|
|
||||||
|
|
||||||
<P>For a particular check, the product above differs for different
|
|
||||||
bits, with respect to which we wish to calculate a likelihood ratio,
|
|
||||||
only in that for each bit the factor corresponding to that bit is left
|
|
||||||
out. We can calculate all these products easily by ordering the bits
|
|
||||||
arbitrarily, computing running products of the factor for the first
|
|
||||||
bit, the factors for the first two bits, etc., and also running
|
|
||||||
products of the factor for the last bit, the factors for the last two
|
|
||||||
bits, etc. Multiplying the running product of the factors up to
|
|
||||||
<I>i</I>-1 by the running product of the factors from <I>i</I>+1 on
|
|
||||||
gives the product needed for bit <I>i</I>. The second form of the
|
|
||||||
factors above is used, as it requires less computation, and is still
|
|
||||||
well defined even if some ratios are infinite.
|
|
||||||
|
|
||||||
<P>To recalculate the probability ratio for a bit with respect to a
|
|
||||||
check, all that is need is to multiply together the likelihood ratio
|
|
||||||
for this bit derived from the received data (see above), and the
|
|
||||||
current values of the likelihood ratios for all the <I>other</I>
|
|
||||||
checks that this bit participates in, with respect to this bit. To
|
|
||||||
save time, these products are computed by combining forward and
|
|
||||||
backward products, similarly to the method used for likelihood ratios.
|
|
||||||
|
|
||||||
<P>By including likelihood ratios from all checks, a similar
|
|
||||||
calculation produces the current probability ratio for the bit to be 1
|
|
||||||
versus 0 based on all information that has propagated to the bit so
|
|
||||||
far. This ratio can be thresholded at one to produce the current best
|
|
||||||
guess as to whether this bit is a 1 or a 0.
|
|
||||||
|
|
||||||
<P>The hope is that this algorithm will eventually converge to a state
|
|
||||||
where these bit probabilities give a near-optimal decoding. This is
|
|
||||||
does not always occur, but the algorithm behaves well enough to
|
|
||||||
produce very good results at rates approaching (though not yet
|
|
||||||
reaching) the theoretical Shannon limit.
|
|
||||||
|
|
||||||
|
|
||||||
<P><A NAME="decode"><HR><B>decode</B>: Decode blocks of received data
|
|
||||||
into codewords.
|
|
||||||
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
decode [ -f ] [ -t | -T ] <I>pchk-file received-file decoded-file</I> [ <I>bp-file</I> ] <I>channel method</I>
|
|
||||||
</PRE>
|
|
||||||
<BLOCKQUOTE>
|
|
||||||
where <TT><I>channel</I></TT> is one of:
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
bsc <I>error-probability</I>
|
|
||||||
|
|
||||||
awgn <I>standard-deviation</I>
|
|
||||||
|
|
||||||
awln <I>width</I>
|
|
||||||
</PRE></BLOCKQUOTE>
|
|
||||||
and <TT><I>method</I></TT> is one of:
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
enum-block <TT><I>gen-file</I></TT>
|
|
||||||
|
|
||||||
enum-bit <TT><I>gen-file</I></TT>
|
|
||||||
|
|
||||||
prprp <TT>[-]<I>max-iterations</I></TT>
|
|
||||||
</PRE></BLOCKQUOTE>
|
|
||||||
</BLOCKQUOTE>
|
|
||||||
</BLOCKQUOTE>
|
|
||||||
|
|
||||||
<P>Decodes the blocks in <TT><I>received-file</I></TT>, which are
|
|
||||||
assumed to be have been received through the specified channel. The
|
|
||||||
results written to <TT><I>decoded-file</I></TT> are the specified
|
|
||||||
decoding method's guesses as to what bits were sent through the
|
|
||||||
channel, given what was received. The probability of each bit being a
|
|
||||||
1, as judged by the decoding method being used, is written to
|
|
||||||
<TT><I>bp-file</I></TT>, if given.
|
|
||||||
|
|
||||||
<P>A newline is output at the end of each block written to
|
|
||||||
<TT><I>decoded-file</I></TT> and <TT><I>bp-file</I></TT>. Newlines in
|
|
||||||
<TT><I>received-file</I></TT> are ignored. A warning is displayed on
|
|
||||||
standard error if the number of bits in <TT><I>received-file</I></TT>
|
|
||||||
is not a multiple of the block length.
|
|
||||||
|
|
||||||
<P>A summary is displayed on standard error, giving the total number
|
|
||||||
of blocks decoded, the number of blocks that decoded to valid
|
|
||||||
codewords, the average number of iterations of the decoding algorithm
|
|
||||||
used, and the percent of bits that were changed from the values one
|
|
||||||
would guess for them based just on their individual likelihood ratios.
|
|
||||||
|
|
||||||
<P>If the <B>-t</B> option is given, a line of information regarding each block
|
|
||||||
decoded is written to standard output, preceded by a line of headers.
|
|
||||||
The information for each block is as follows:
|
|
||||||
<BLOCKQUOTE>
|
|
||||||
<TABLE>
|
|
||||||
<tr align="left" valign="top">
|
|
||||||
<td> <B>block</B> </td>
|
|
||||||
<td>The number of the block, from zero</td></tr>
|
|
||||||
<tr align="left" valign="top">
|
|
||||||
<td> <B>iterations</B> </td>
|
|
||||||
<td>The number of "iterations" used in decoding. What exactly an iteration
|
|
||||||
is depends on the decoding method used (see
|
|
||||||
<A HREF="decode-detail.html">here</A>).</td></tr>
|
|
||||||
<tr align="left" valign="top">
|
|
||||||
<td> <B>valid</B> </td>
|
|
||||||
<td>Has the value 1 if the decoding is a valid codeword, 0 if not.</td></tr>
|
|
||||||
<tr align="left" valign="top">
|
|
||||||
<td> <B>changed</B> </td>
|
|
||||||
<td>The number of bits in the decoding that differ from the bit that would
|
|
||||||
be chosen based just on the likelihood ratio for that bit. Bits whose
|
|
||||||
likelihood ratios are exactly one contribute 0.5 to this count.</td></tr>
|
|
||||||
</TABLE>
|
|
||||||
</BLOCKQUOTE>
|
|
||||||
The file produced is is suitable for
|
|
||||||
reading into the S-Plus or R statistics packages, with a command such as
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
data <- read.table(<I>file</I>,header=T)
|
|
||||||
</PRE></BLOCKQUOTE>
|
|
||||||
|
|
||||||
<P>If instead the <B>-T</B> option is given, detailed information on
|
|
||||||
the process of decoding each block will be written to standard output.
|
|
||||||
For a description, see the <A HREF="decode-detail.html">documentation
|
|
||||||
on detailed decoding trace information</A>.
|
|
||||||
|
|
||||||
<P>The type of channel that is assumed is specified after the file
|
|
||||||
name arguments. This may currently be either <TT>bsc</TT> (or
|
|
||||||
<TT>BSC</TT>) for the Binary Symmetric Channel, or <TT>awgn</TT> (or
|
|
||||||
<TT>AWGN</TT>) for the Additive White Gaussian Noise channel, or
|
|
||||||
<TT>awln</TT> (or <TT>AWLN</TT>) for the Additive White Logistic Noise
|
|
||||||
channel. The channel type is followed by an argument specifying the
|
|
||||||
assumed characteristics of the channel, as follows:
|
|
||||||
<BLOCKQUOTE>
|
|
||||||
<P>BSC: The probability that a bit will be flipped by noise - ie, the
|
|
||||||
probability that the bit received is an error.
|
|
||||||
|
|
||||||
<P>AWGN: The standard deviation of the Gaussian noise added to the
|
|
||||||
encodings of the bits.
|
|
||||||
|
|
||||||
<P>AWLN: The width parameter of the logistic distribution for the noise
|
|
||||||
that is added to the encodings of the bits.
|
|
||||||
</BLOCKQUOTE>
|
|
||||||
See the description of <A HREF="channel.html">channel transmission</A>
|
|
||||||
for more about these channels.
|
|
||||||
|
|
||||||
<P>Following the channel specification is a specification of the
|
|
||||||
decoding method to use. The <TT>enum-block</TT> and <TT>enum-bit</TT>
|
|
||||||
methods find the optimal decoding by exhaustive enumeration of
|
|
||||||
codewords derived from all possible source messages. They differ in
|
|
||||||
that <TT>enum-block</TT> decodes to the most likely codeword, whereas
|
|
||||||
<TT>enum-bit</TT> decodes to the bits that are individually most
|
|
||||||
probable. These methods require that a file containing a
|
|
||||||
representation of a generator matrix be given, to allow enumeration of
|
|
||||||
codewords. If the parity check matrix has no redundant rows, any
|
|
||||||
valid generator matrix will give the same decoding (except perhaps if
|
|
||||||
there is a tie). If redundant rows exist, the generator matrix should
|
|
||||||
specify the same set of message bits as the generator matrix that was
|
|
||||||
used for the actual encoding, since the redundancy will lead to some
|
|
||||||
codeword bits being fixed at zero (see <A HREF="dep-H.html">linear
|
|
||||||
dependence in parity check matrices</A>).
|
|
||||||
|
|
||||||
<P>The <TT>prprp</TT> decoding method decodes using <A
|
|
||||||
HREF="#prprp">probability propagation</A>. The maximum number of
|
|
||||||
iterations of probability propagation to do is given following
|
|
||||||
<TT>prprp</TT>. If a minus sign precedes this number, the maximum
|
|
||||||
number of iterations is always done. If no minus sign is present, the
|
|
||||||
algorithm stops once the tentative decoding, based on bit-by-bit
|
|
||||||
probabilities, is a valid codeword. Note that continuing to the
|
|
||||||
maximum number of iterations will usually result in
|
|
||||||
at least slightly different bit probabilities (written to
|
|
||||||
<TT><I>bp-file</I></TT> if specified), and could conceivably change
|
|
||||||
the decoding compared to stopping at the first valid codeword, or
|
|
||||||
result in a failure to decode to a valid codeword even though one was
|
|
||||||
found earlier.
|
|
||||||
|
|
||||||
<P>If the <B>-f</B> option is given, output to <TT><I>decoded-file</I></TT>
|
|
||||||
is flushed after each block. This allows one to use decode as a server,
|
|
||||||
reading blocks to decode from a named pipe, and writing the decoded block
|
|
||||||
to another named pipe.
|
|
||||||
|
|
||||||
|
|
||||||
<P><A NAME="extract"><HR><B>extract</B>: Extract the message bits from a block.
|
|
||||||
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
extract <I>gen-file decoded-file extracted-file</I>
|
|
||||||
</PRE></BLOCKQUOTE>
|
|
||||||
|
|
||||||
<P>Given a file of codewords in <TT><I>decoded-file</I></TT> (usually,
|
|
||||||
decoded blocks output by <A HREF="#decode"><TT>decode</TT></A>), and a
|
|
||||||
generator matrix from <TT><I>gen-file</I></TT> (needed only to
|
|
||||||
determine where the message bits are located in a codeword), this
|
|
||||||
program writes the message bits extracted from these codewords to the
|
|
||||||
file <TT><I>extracted-file</I></TT>.
|
|
||||||
|
|
||||||
<P>A newline is output at the end of each block written to
|
|
||||||
<TT><I>extracted-file</I></TT>. Newlines in
|
|
||||||
<TT><I>decoded-file</I></TT> are ignored. A warning is displayed on
|
|
||||||
standard error if the number of bits in <TT><I>decoded-file</I></TT>
|
|
||||||
is not a multiple of the block length.
|
|
||||||
|
|
||||||
<HR>
|
|
||||||
|
|
||||||
<A HREF="index.html">Back to index for LDPC software</A>
|
|
||||||
|
|
||||||
</BODY></HTML>
|
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
// -*- Mode: C++ -*-
|
||||||
|
#ifndef LogQSO_H
|
||||||
|
#define LogQSO_H
|
||||||
|
|
||||||
|
#ifdef QT5
|
||||||
|
#include <QtWidgets>
|
||||||
|
#else
|
||||||
|
#include <QtGui>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
#include <QScopedPointer>
|
||||||
|
#include <QDateTime>
|
||||||
|
|
||||||
|
#include "Radio.hpp"
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class LogQSO;
|
||||||
|
}
|
||||||
|
|
||||||
|
class QSettings;
|
||||||
|
class Configuration;
|
||||||
|
class QByteArray;
|
||||||
|
|
||||||
|
class LogQSO : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit LogQSO(QString const& programTitle, QSettings *, Configuration const *, QWidget *parent = 0);
|
||||||
|
~LogQSO();
|
||||||
|
void initLogQSO(QString const& hisCall, QString const& hisGrid, QString mode,
|
||||||
|
QString const& rptSent, QString const& rptRcvd, QDateTime const& dateTimeOn,
|
||||||
|
QDateTime const& dateTimeOff,
|
||||||
|
Radio::Frequency dialFreq, QString const& myCall, QString const& myGrid,
|
||||||
|
bool noSuffix, bool toRTTY, bool dBtoComments, bool bFox, QString const& opCall);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void accept();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void acceptQSO (QDateTime const& QSO_date_off, QString const& call, QString const& grid
|
||||||
|
, Radio::Frequency dial_freq, QString const& mode
|
||||||
|
, QString const& rpt_sent, QString const& rpt_received
|
||||||
|
, QString const& tx_power, QString const& comments
|
||||||
|
, QString const& name, QDateTime const& QSO_date_on, QString const& operator_call
|
||||||
|
, QString const& my_call, QString const& my_grid, QByteArray const& ADIF);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void hideEvent (QHideEvent *);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void loadSettings ();
|
||||||
|
void storeSettings () const;
|
||||||
|
|
||||||
|
QScopedPointer<Ui::LogQSO> ui;
|
||||||
|
QSettings * m_settings;
|
||||||
|
Configuration const * m_config;
|
||||||
|
QString m_txPower;
|
||||||
|
QString m_comments;
|
||||||
|
Radio::Frequency m_dialFreq;
|
||||||
|
QString m_myCall;
|
||||||
|
QString m_myGrid;
|
||||||
|
QDateTime m_dateTimeOn;
|
||||||
|
QDateTime m_dateTimeOff;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // LogQSO_H
|
||||||
@@ -0,0 +1,524 @@
|
|||||||
|
module jt65_decode
|
||||||
|
|
||||||
|
integer, parameter :: NSZ=3413, NZMAX=60*12000
|
||||||
|
|
||||||
|
type :: jt65_decoder
|
||||||
|
procedure(jt65_decode_callback), pointer :: callback => null()
|
||||||
|
contains
|
||||||
|
procedure :: decode
|
||||||
|
end type jt65_decoder
|
||||||
|
|
||||||
|
! Callback function to be called with each decode
|
||||||
|
abstract interface
|
||||||
|
subroutine jt65_decode_callback(this,sync,snr,dt,freq,drift, &
|
||||||
|
nflip,width,decoded,ft,qual,nsmo,nsum,minsync)
|
||||||
|
|
||||||
|
import jt65_decoder
|
||||||
|
implicit none
|
||||||
|
class(jt65_decoder), intent(inout) :: this
|
||||||
|
real, intent(in) :: sync
|
||||||
|
integer, intent(in) :: snr
|
||||||
|
real, intent(in) :: dt
|
||||||
|
integer, intent(in) :: freq
|
||||||
|
integer, intent(in) :: drift
|
||||||
|
integer, intent(in) :: nflip
|
||||||
|
real, intent(in) :: width
|
||||||
|
character(len=22), intent(in) :: decoded
|
||||||
|
integer, intent(in) :: ft
|
||||||
|
integer, intent(in) :: qual
|
||||||
|
integer, intent(in) :: nsmo
|
||||||
|
integer, intent(in) :: nsum
|
||||||
|
integer, intent(in) :: minsync
|
||||||
|
|
||||||
|
end subroutine jt65_decode_callback
|
||||||
|
end interface
|
||||||
|
|
||||||
|
contains
|
||||||
|
|
||||||
|
subroutine decode(this,callback,dd0,npts,newdat,nutc,nf1,nf2,nfqso, &
|
||||||
|
ntol,nsubmode,minsync,nagain,n2pass,nrobust,ntrials,naggressive, &
|
||||||
|
ndepth,emedelay,clearave,mycall,hiscall,hisgrid,nexp_decode, &
|
||||||
|
nQSOProgress,ljt65apon)
|
||||||
|
|
||||||
|
! Process dd0() data to find and decode JT65 signals.
|
||||||
|
|
||||||
|
use jt65_mod
|
||||||
|
use timer_module, only: timer
|
||||||
|
|
||||||
|
include 'constants.f90'
|
||||||
|
|
||||||
|
class(jt65_decoder), intent(inout) :: this
|
||||||
|
procedure(jt65_decode_callback) :: callback
|
||||||
|
real, intent(in) :: dd0(NZMAX),emedelay
|
||||||
|
integer, intent(in) :: npts, nutc, nf1, nf2, nfqso, ntol &
|
||||||
|
, nsubmode, minsync, n2pass, ntrials, naggressive, ndepth &
|
||||||
|
, nexp_decode, nQSOProgress
|
||||||
|
logical, intent(in) :: newdat, nagain, nrobust, clearave, ljt65apon
|
||||||
|
character(len=12), intent(in) :: mycall, hiscall
|
||||||
|
character(len=6), intent(in) :: hisgrid
|
||||||
|
|
||||||
|
real dd(NZMAX)
|
||||||
|
real ss(552,NSZ)
|
||||||
|
real savg(NSZ)
|
||||||
|
real a(5)
|
||||||
|
character*22 decoded,decoded0,avemsg,deepave
|
||||||
|
type candidate
|
||||||
|
real freq
|
||||||
|
real dt
|
||||||
|
real sync
|
||||||
|
real flip
|
||||||
|
end type candidate
|
||||||
|
type(candidate) ca(300)
|
||||||
|
type accepted_decode
|
||||||
|
real freq
|
||||||
|
real dt
|
||||||
|
real sync
|
||||||
|
character*22 decoded
|
||||||
|
end type accepted_decode
|
||||||
|
type(accepted_decode) dec(50)
|
||||||
|
logical :: first_time,prtavg,single_decode,bVHF
|
||||||
|
|
||||||
|
integer h0(0:11),d0(0:11)
|
||||||
|
real r0(0:11)
|
||||||
|
common/decstats/ntry65a,ntry65b,n65a,n65b,num9,numfano
|
||||||
|
common/steve/thresh0
|
||||||
|
common/sync/ss
|
||||||
|
|
||||||
|
! 0 1 2 3 4 5 6 7 8 9 10 11
|
||||||
|
data h0/41,42,43,43,44,45,46,47,48,48,49,49/
|
||||||
|
data d0/71,72,73,74,76,77,78,80,81,82,83,83/
|
||||||
|
|
||||||
|
! 0 1 2 3 4 5 6 7 8 9 10 11
|
||||||
|
data r0/0.70,0.72,0.74,0.76,0.78,0.80,0.82,0.84,0.86,0.88,0.90,0.90/
|
||||||
|
data nutc0/-999/,nfreq0/-999/,nsave/0/
|
||||||
|
save
|
||||||
|
|
||||||
|
this%callback => callback
|
||||||
|
first_time=newdat
|
||||||
|
dd=dd0
|
||||||
|
ndecoded=0
|
||||||
|
|
||||||
|
if(nsubmode.ge.100) then
|
||||||
|
! This is QRA64 mode
|
||||||
|
mode64=2**(nsubmode-100)
|
||||||
|
!###
|
||||||
|
! open(60,file='qra64_data.bin',access='stream',position='append')
|
||||||
|
! write(60) dd,npts,nutc,nf1,nf2,nfqso,ntol,mode64,minsync,ndepth, &
|
||||||
|
! mycall,hiscall,hisgrid
|
||||||
|
! close(60)
|
||||||
|
!###
|
||||||
|
call qra64a(dd,npts,nutc,nf1,nf2,nfqso,ntol,mode64,minsync,ndepth, &
|
||||||
|
emedelay,mycall,hiscall,hisgrid,sync,nsnr,dtx,nfreq,decoded,nft)
|
||||||
|
if (associated(this%callback)) then
|
||||||
|
ndrift=0
|
||||||
|
nflip=1
|
||||||
|
width=1.0
|
||||||
|
nsmo=0
|
||||||
|
nqual=0
|
||||||
|
call this%callback(sync,nsnr,dtx,nfreq,ndrift, &
|
||||||
|
nflip,width,decoded,nft,nqual,nsmo,1,minsync)
|
||||||
|
end if
|
||||||
|
go to 900
|
||||||
|
endif
|
||||||
|
|
||||||
|
single_decode=iand(nexp_decode,32).ne.0 .or. nagain
|
||||||
|
bVHF=iand(nexp_decode,64).ne.0
|
||||||
|
|
||||||
|
if( bVHF ) then
|
||||||
|
nvec=ntrials
|
||||||
|
npass=1
|
||||||
|
if(n2pass.gt.1) npass=2
|
||||||
|
else
|
||||||
|
nvec=1000
|
||||||
|
if(ndepth.eq.1) then
|
||||||
|
npass=2
|
||||||
|
nvec=100
|
||||||
|
elseif(ndepth.eq.2) then
|
||||||
|
npass=2
|
||||||
|
nvec=1000
|
||||||
|
else
|
||||||
|
npass=4
|
||||||
|
nvec=1000
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
do ipass=1,npass
|
||||||
|
first_time=.true.
|
||||||
|
if(ipass.eq.1) then !First-pass parameters
|
||||||
|
thresh0=2.5
|
||||||
|
nsubtract=1
|
||||||
|
nrob=0
|
||||||
|
elseif( ipass.eq.2 ) then !Second-pass parameters
|
||||||
|
thresh0=2.0
|
||||||
|
nsubtract=1
|
||||||
|
nrob=0
|
||||||
|
elseif( ipass.eq.3 ) then
|
||||||
|
thresh0=2.0
|
||||||
|
nsubtract=1
|
||||||
|
nrob=0
|
||||||
|
elseif( ipass.eq.4 ) then
|
||||||
|
thresh0=2.0
|
||||||
|
nsubtract=0
|
||||||
|
nrob=1
|
||||||
|
endif
|
||||||
|
if(npass.eq.1) then
|
||||||
|
nsubtract=0
|
||||||
|
thresh0=2.0
|
||||||
|
endif
|
||||||
|
|
||||||
|
call timer('symsp65 ',0)
|
||||||
|
ss=0.
|
||||||
|
call symspec65(dd,npts,nqsym,savg) !Get normalized symbol spectra
|
||||||
|
call timer('symsp65 ',1)
|
||||||
|
nfa=nf1
|
||||||
|
nfb=nf2
|
||||||
|
|
||||||
|
!### Q: should either of the next two uses of "single_decode" be "bVHF" instead?
|
||||||
|
if(single_decode .or. (bVHF .and. ntol.lt.1000)) then
|
||||||
|
nfa=max(200,nfqso-ntol)
|
||||||
|
nfb=min(4000,nfqso+ntol)
|
||||||
|
thresh0=1.0
|
||||||
|
endif
|
||||||
|
df=12000.0/8192.0 !df = 1.465 Hz
|
||||||
|
if(bVHF) then
|
||||||
|
ia=max(1,nint(nfa/df)-ntol)
|
||||||
|
ib=min(NSZ,nint(nfb/df)+ntol)
|
||||||
|
nz=ib-ia+1
|
||||||
|
call lorentzian(savg(ia),nz,a)
|
||||||
|
baseline=a(1)
|
||||||
|
amp=a(2)
|
||||||
|
f0=(a(3)+ia-1)*df
|
||||||
|
width=a(4)*df
|
||||||
|
endif
|
||||||
|
|
||||||
|
ncand=0
|
||||||
|
call timer('sync65 ',0)
|
||||||
|
call sync65(nfa,nfb,naggressive,ntol,nqsym,ca,ncand,nrob,bVHF)
|
||||||
|
call timer('sync65 ',1)
|
||||||
|
|
||||||
|
! If a candidate was found within +/- ntol of nfqso, move it into ca(1).
|
||||||
|
call fqso_first(nfqso,ntol,ca,ncand)
|
||||||
|
if(single_decode) then
|
||||||
|
if(ncand.eq.0) ncand=1
|
||||||
|
if(abs(ca(1)%freq - f0).gt.width) width=2*df !### ??? ###
|
||||||
|
endif
|
||||||
|
|
||||||
|
mode65=2**nsubmode
|
||||||
|
nflip=1
|
||||||
|
nqd=0
|
||||||
|
decoded=' '
|
||||||
|
decoded0=""
|
||||||
|
freq0=0.
|
||||||
|
prtavg=.false.
|
||||||
|
if(.not.nagain) nsum=0
|
||||||
|
if(clearave) then
|
||||||
|
nsum=0
|
||||||
|
nsave=0
|
||||||
|
endif
|
||||||
|
|
||||||
|
if(bVHF) then
|
||||||
|
! Be sure to search for shorthand message at nfqso +/- ntol
|
||||||
|
if(ncand.lt.300) ncand=ncand+1
|
||||||
|
ca(ncand)%sync=5.0
|
||||||
|
ca(ncand)%dt=2.5
|
||||||
|
ca(ncand)%freq=nfqso
|
||||||
|
endif
|
||||||
|
do icand=1,ncand
|
||||||
|
sync1=ca(icand)%sync
|
||||||
|
dtx=ca(icand)%dt
|
||||||
|
freq=ca(icand)%freq
|
||||||
|
if(bVHF) then
|
||||||
|
flip=ca(icand)%flip
|
||||||
|
nflip=flip
|
||||||
|
endif
|
||||||
|
if(sync1.lt.float(minsync)) nflip=0
|
||||||
|
if(ipass.eq.1) ntry65a=ntry65a + 1
|
||||||
|
if(ipass.eq.2) ntry65b=ntry65b + 1
|
||||||
|
call timer('decod65a',0)
|
||||||
|
nft=0
|
||||||
|
nspecial=0
|
||||||
|
call decode65a(dd,npts,first_time,nqd,freq,nflip,mode65,nvec, &
|
||||||
|
naggressive,ndepth,ntol,mycall,hiscall,hisgrid,nQSOProgress, &
|
||||||
|
ljt65apon,nexp_decode,bVHF,sync2,a,dtx,nft,nspecial,qual, &
|
||||||
|
nhist,nsmo,decoded)
|
||||||
|
if(nspecial.eq.2) decoded='RO'
|
||||||
|
if(nspecial.eq.3) decoded='RRR'
|
||||||
|
if(nspecial.eq.4) decoded='73'
|
||||||
|
call timer('decod65a',1)
|
||||||
|
if(sync1.lt.float(minsync) .and. &
|
||||||
|
decoded.eq.' ') nflip=0
|
||||||
|
if(nft.ne.0) nsum=1
|
||||||
|
|
||||||
|
nhard_min=param(1)
|
||||||
|
nrtt1000=param(4)
|
||||||
|
ntotal_min=param(5)
|
||||||
|
nsmo=param(9)
|
||||||
|
|
||||||
|
nfreq=nint(freq+a(1))
|
||||||
|
ndrift=nint(2.0*a(2))
|
||||||
|
if(bVHF) then
|
||||||
|
xtmp=10**((sync1+16.0)/10.0) ! sync comes to us in dB
|
||||||
|
s2db=1.1*db(xtmp)+1.4*(dB(width)-4.3)-52.0
|
||||||
|
! s2db=sync1 - 30.0 + db(width/3.3) !### VHF/UHF/microwave
|
||||||
|
if(nspecial.gt.0) s2db=sync2
|
||||||
|
else
|
||||||
|
s2db=10.0*log10(sync2) - 35 !### Empirical (HF)
|
||||||
|
endif
|
||||||
|
nsnr=nint(s2db)
|
||||||
|
if(nsnr.lt.-30) nsnr=-30
|
||||||
|
if(nsnr.gt.-1) nsnr=-1
|
||||||
|
nftt=0
|
||||||
|
|
||||||
|
!********* DOES THIS STILL WORK WHEN NFT INCLUDES # OF AP SYMBOLS USED??
|
||||||
|
if(nft.ne.1 .and. iand(ndepth,16).eq.16 .and. (.not.prtavg)) then
|
||||||
|
! Single-sequence FT decode failed, so try for an average FT decode.
|
||||||
|
if(nutc.ne.nutc0 .or. abs(nfreq-nfreq0).gt.ntol) then
|
||||||
|
! This is a new minute or a new frequency, so call avg65.
|
||||||
|
nutc0=nutc
|
||||||
|
nfreq0=nfreq
|
||||||
|
nsave=nsave+1
|
||||||
|
nsave=mod(nsave-1,64)+1
|
||||||
|
call avg65(nutc,nsave,sync1,dtx,nflip,nfreq,mode65,ntol, &
|
||||||
|
ndepth,nagain,ntrials,naggressive,clearave,neme,mycall, &
|
||||||
|
hiscall,hisgrid,nftt,avemsg,qave,deepave,nsum,ndeepave, &
|
||||||
|
nQSOProgress,ljt65apon)
|
||||||
|
nsmo=param(9)
|
||||||
|
nqave=qave
|
||||||
|
|
||||||
|
if (associated(this%callback) .and. nsum.ge.2) then
|
||||||
|
call this%callback(sync1,nsnr,dtx-1.0,nfreq,ndrift, &
|
||||||
|
nflip,width,avemsg,nftt,nqave,nsmo,nsum,minsync)
|
||||||
|
prtavg=.true.
|
||||||
|
end if
|
||||||
|
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
if(nftt.eq.1) then
|
||||||
|
! nft=1
|
||||||
|
decoded=avemsg
|
||||||
|
go to 5
|
||||||
|
endif
|
||||||
|
n=naggressive
|
||||||
|
rtt=0.001*nrtt1000
|
||||||
|
if(nft.lt.2 .and. minsync.ge.0 .and. nspecial.eq.0) then
|
||||||
|
if(nhard_min.gt.50) cycle
|
||||||
|
if(nhard_min.gt.h0(n)) cycle
|
||||||
|
if(ntotal_min.gt.d0(n)) cycle
|
||||||
|
if(rtt.gt.r0(n)) cycle
|
||||||
|
endif
|
||||||
|
|
||||||
|
5 continue
|
||||||
|
if(decoded.eq.decoded0 .and. abs(freq-freq0).lt. 3.0 .and. &
|
||||||
|
minsync.ge.0) cycle !Don't display dupes
|
||||||
|
if(decoded.ne.' ' .or. minsync.lt.0) then
|
||||||
|
if(nsubtract.eq.1) then
|
||||||
|
call timer('subtr65 ',0)
|
||||||
|
call subtract65(dd,npts,freq,dtx)
|
||||||
|
call timer('subtr65 ',1)
|
||||||
|
endif
|
||||||
|
|
||||||
|
ndupe=0 ! de-dedupe
|
||||||
|
do i=1, ndecoded
|
||||||
|
if(decoded==dec(i)%decoded) then
|
||||||
|
ndupe=1
|
||||||
|
exit
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
if(ndupe.ne.1 .and. sync1.ge.float(minsync)) then
|
||||||
|
if(ipass.eq.1) n65a=n65a + 1
|
||||||
|
if(ipass.eq.2) n65b=n65b + 1
|
||||||
|
if(ndecoded.lt.50) ndecoded=ndecoded+1
|
||||||
|
dec(ndecoded)%freq=freq+a(1)
|
||||||
|
dec(ndecoded)%dt=dtx
|
||||||
|
dec(ndecoded)%sync=sync2
|
||||||
|
dec(ndecoded)%decoded=decoded
|
||||||
|
nqual=min(qual,9999.0)
|
||||||
|
|
||||||
|
if (associated(this%callback)) then
|
||||||
|
call this%callback(sync1,nsnr,dtx-1.0,nfreq,ndrift, &
|
||||||
|
nflip,width,decoded,nft,nqual,nsmo,1,minsync)
|
||||||
|
end if
|
||||||
|
endif
|
||||||
|
decoded0=decoded
|
||||||
|
freq0=freq
|
||||||
|
if(decoded0.eq.' ') decoded0='*'
|
||||||
|
endif
|
||||||
|
enddo !Candidate loop
|
||||||
|
if(ipass.eq.2 .and. ndecoded.lt.1) exit
|
||||||
|
enddo !Multiple-pass loop
|
||||||
|
900 return
|
||||||
|
end subroutine decode
|
||||||
|
|
||||||
|
subroutine avg65(nutc,nsave,snrsync,dtxx,nflip,nfreq,mode65,ntol,ndepth, &
|
||||||
|
nagain, ntrials,naggressive,clearave,neme,mycall,hiscall,hisgrid,nftt, &
|
||||||
|
avemsg,qave,deepave,nsum,ndeepave,nQSOProgress,ljt65apon)
|
||||||
|
|
||||||
|
! Decodes averaged JT65 data
|
||||||
|
|
||||||
|
use jt65_mod
|
||||||
|
parameter (MAXAVE=64)
|
||||||
|
character*22 avemsg,deepave,deepbest
|
||||||
|
character mycall*12,hiscall*12,hisgrid*6
|
||||||
|
character*1 csync,cused(64)
|
||||||
|
logical nagain
|
||||||
|
integer iused(64)
|
||||||
|
! Accumulated data for message averaging
|
||||||
|
integer iutc(MAXAVE)
|
||||||
|
integer nfsave(MAXAVE)
|
||||||
|
integer nflipsave(MAXAVE)
|
||||||
|
real s1b(-255:256,126)
|
||||||
|
real s1save(-255:256,126,MAXAVE)
|
||||||
|
real s2(66,126)
|
||||||
|
real s3save(64,63,MAXAVE)
|
||||||
|
real s3b(64,63)
|
||||||
|
real s3c(64,63)
|
||||||
|
real dtsave(MAXAVE)
|
||||||
|
real syncsave(MAXAVE)
|
||||||
|
logical first,clearave,ljt65apon
|
||||||
|
data first/.true./
|
||||||
|
save
|
||||||
|
|
||||||
|
if(first .or. clearave) then
|
||||||
|
iutc=-1
|
||||||
|
nfsave=0
|
||||||
|
dtdiff=0.2
|
||||||
|
first=.false.
|
||||||
|
s3save=0.
|
||||||
|
s1save=0.
|
||||||
|
nsave=1 !### ???
|
||||||
|
! Silence compiler warnings
|
||||||
|
if(nagain .and. ndeepave.eq.-99 .and. neme.eq.-99) stop
|
||||||
|
endif
|
||||||
|
|
||||||
|
do i=1,64
|
||||||
|
if(iutc(i).lt.0) exit
|
||||||
|
if(nutc.eq.iutc(i) .and. abs(nfreq-nfsave(i)).le.ntol) go to 10
|
||||||
|
enddo
|
||||||
|
|
||||||
|
! Save data for message averaging
|
||||||
|
iutc(nsave)=nutc
|
||||||
|
syncsave(nsave)=snrsync
|
||||||
|
dtsave(nsave)=dtxx
|
||||||
|
nfsave(nsave)=nfreq
|
||||||
|
nflipsave(nsave)=nflip
|
||||||
|
s1save(-255:256,1:126,nsave)=s1
|
||||||
|
s3save(1:64,1:63,nsave)=s3a
|
||||||
|
|
||||||
|
10 syncsum=0.
|
||||||
|
dtsum=0.
|
||||||
|
nfsum=0
|
||||||
|
nsum=0
|
||||||
|
s1b=0.
|
||||||
|
s3b=0.
|
||||||
|
s3c=0.
|
||||||
|
|
||||||
|
do i=1,MAXAVE !Consider all saved spectra
|
||||||
|
cused(i)='.'
|
||||||
|
if(iutc(i).lt.0) cycle
|
||||||
|
if(mod(iutc(i),2).ne.mod(nutc,2)) cycle !Use only same (odd/even) seq
|
||||||
|
if(abs(dtxx-dtsave(i)).gt.dtdiff) cycle !DT must match
|
||||||
|
if(abs(nfreq-nfsave(i)).gt.ntol) cycle !Freq must match
|
||||||
|
if(nflip.ne.nflipsave(i)) cycle !Sync type (*/#) must match
|
||||||
|
s3b=s3b + s3save(1:64,1:63,i)
|
||||||
|
s1b=s1b + s1save(-255:256,1:126,i)
|
||||||
|
syncsum=syncsum + syncsave(i)
|
||||||
|
dtsum=dtsum + dtsave(i)
|
||||||
|
nfsum=nfsum + nfsave(i)
|
||||||
|
cused(i)='$'
|
||||||
|
nsum=nsum+1
|
||||||
|
iused(nsum)=i
|
||||||
|
enddo
|
||||||
|
if(nsum.lt.64) iused(nsum+1)=0
|
||||||
|
|
||||||
|
syncave=0.
|
||||||
|
dtave=0.
|
||||||
|
fave=0.
|
||||||
|
if(nsum.gt.0) then
|
||||||
|
syncave=syncsum/nsum
|
||||||
|
dtave=dtsum/nsum
|
||||||
|
fave=float(nfsum)/nsum
|
||||||
|
endif
|
||||||
|
|
||||||
|
do i=1,nsave
|
||||||
|
csync='*'
|
||||||
|
if(nflipsave(i).lt.0.0) csync='#'
|
||||||
|
write(14,1000) cused(i),iutc(i),syncsave(i),dtsave(i)-1.0,nfsave(i),csync
|
||||||
|
1000 format(a1,i5.4,f6.1,f6.2,i6,1x,a1)
|
||||||
|
enddo
|
||||||
|
if(nsum.lt.2) go to 900
|
||||||
|
|
||||||
|
nftt=0
|
||||||
|
df=1378.125/512.0
|
||||||
|
|
||||||
|
! Do the smoothing loop
|
||||||
|
qualbest=0.
|
||||||
|
minsmo=0
|
||||||
|
maxsmo=0
|
||||||
|
if(mode65.ge.2) then
|
||||||
|
minsmo=nint(width/df)
|
||||||
|
maxsmo=2*minsmo
|
||||||
|
endif
|
||||||
|
nn=0
|
||||||
|
do ismo=minsmo,maxsmo
|
||||||
|
if(ismo.gt.0) then
|
||||||
|
do j=1,126
|
||||||
|
call smo121(s1b(-255,j),512)
|
||||||
|
if(j.eq.1) nn=nn+1
|
||||||
|
if(nn.ge.4) then
|
||||||
|
call smo121(s1b(-255,j),512)
|
||||||
|
if(j.eq.1) nn=nn+1
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
endif
|
||||||
|
|
||||||
|
do i=1,66
|
||||||
|
jj=i
|
||||||
|
if(mode65.eq.2) jj=2*i-1
|
||||||
|
if(mode65.eq.4) then
|
||||||
|
ff=4*(i-1)*df - 355.297852
|
||||||
|
jj=nint(ff/df)+1
|
||||||
|
endif
|
||||||
|
s2(i,1:126)=s1b(jj,1:126)
|
||||||
|
enddo
|
||||||
|
|
||||||
|
do j=1,63
|
||||||
|
k=mdat(j) !Points to data symbol
|
||||||
|
if(nflip.lt.0) k=mdat2(j)
|
||||||
|
do i=1,64
|
||||||
|
s3c(i,j)=4.e-5*s2(i+2,k)
|
||||||
|
enddo
|
||||||
|
enddo
|
||||||
|
|
||||||
|
nadd=nsum*ismo
|
||||||
|
call extract(s3c,nadd,mode65,ntrials,naggressive,ndepth,nflip,mycall, &
|
||||||
|
hiscall,hisgrid,nQSOProgress,ljt65apon,nexp_decode,ncount,nhist, &
|
||||||
|
avemsg,ltext,nftt,qual)
|
||||||
|
if(nftt.eq.1) then
|
||||||
|
nsmo=ismo
|
||||||
|
param(9)=nsmo
|
||||||
|
go to 900
|
||||||
|
else if(nftt.eq.2) then
|
||||||
|
if(qual.gt.qualbest) then
|
||||||
|
deepbest=avemsg
|
||||||
|
qualbest=qual
|
||||||
|
nnbest=nn
|
||||||
|
nsmobest=ismo
|
||||||
|
nfttbest=nftt
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
|
||||||
|
if(nfttbest.eq.2) then
|
||||||
|
avemsg=deepbest !### ???
|
||||||
|
deepave=deepbest
|
||||||
|
qave=qualbest
|
||||||
|
nsmo=nsmobest
|
||||||
|
param(9)=nsmo
|
||||||
|
nftt=nfttbest
|
||||||
|
endif
|
||||||
|
900 continue
|
||||||
|
|
||||||
|
return
|
||||||
|
end subroutine avg65
|
||||||
|
|
||||||
|
end module jt65_decode
|
||||||
+1
-1
@@ -54,7 +54,7 @@ subroutine genwspr5(msg,msgsent,itone)
|
|||||||
|
|
||||||
! Message structure:
|
! Message structure:
|
||||||
! I channel: R1 48*(S1+D1) S13 48*(D1+S1) R1
|
! I channel: R1 48*(S1+D1) S13 48*(D1+S1) R1
|
||||||
! Q channel: R1 D109 R1
|
! Q channel: R1 D204 R1
|
||||||
! Generate QPSK with no offset, then shift the y array to get OQPSK.
|
! Generate QPSK with no offset, then shift the y array to get OQPSK.
|
||||||
|
|
||||||
! I channel:
|
! I channel:
|
||||||
@@ -0,0 +1,272 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>Astro</class>
|
||||||
|
<widget class="QWidget" name="Astro">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>359</width>
|
||||||
|
<height>342</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
|
<property name="sizeConstraint">
|
||||||
|
<enum>QLayout::SetFixedSize</enum>
|
||||||
|
</property>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QWidget" name="doppler_widget" native="true">
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">* {
|
||||||
|
font-weight: normal;
|
||||||
|
}</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox">
|
||||||
|
<property name="title">
|
||||||
|
<string>Doppler tracking</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
|
<item>
|
||||||
|
<widget class="QRadioButton" name="rbFullTrack">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p>One station does all Doppler shift correction, their QSO partner receives and transmits on the sked frequency.</p><p>If the rig does not accept CAT QSY commands while transmitting a single correction is applied for the whole transmit period.</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Full Doppler to DX Grid</string>
|
||||||
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QRadioButton" name="rbOwnEcho">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p>Transmit takes place on sked frequency and receive frequency is corrected for own echoes. </p><p>This mode can be used for calling CQ, or when using Echo mode.</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Own Echo</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QRadioButton" name="rbConstFreqOnMoon">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p>Both stations correct for Doppler shift such that they would be heard on the moon at the sked frequency.</p><p>If the rig does not accept CAT QSY commands while transmitting a single correction is applied for the whole transmit period.</p><p>Use this option also for Echo mode.</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Constant frequency on Moon</string>
|
||||||
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QRadioButton" name="rbOnDxEcho">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p>DX station announces their TX Freq, which is entered as the Sked Freq. Correction applied to RX and TX so you appear on the DX's station's own echo Freq.</p><p>If the rig does not accept CAT QSY commands while transmitting a single correction is applied for the whole transmit period.</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>On DX Echo</string>
|
||||||
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QRadioButton" name="rbCallDx">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p>Tune radio manually and select this mode to put your echo on the same frequency.</p><p>If the rig does not accept CAT QSY commands while transmitting a single correction is applied for the whole transmit period.</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Call DX</string>
|
||||||
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QRadioButton" name="rbNoDoppler">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p>No Doppler shift correction is applied. This may be used when the QSO partner does full Doppler correction to your grid square.</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>None</string>
|
||||||
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox_3">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="title">
|
||||||
|
<string>Sked frequency</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout_2" columnstretch="0,1">
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QLabel" name="sked_tx_frequency_label">
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">* {
|
||||||
|
font-family: Courier;
|
||||||
|
font-size: 12pt;
|
||||||
|
font-weight: bold;
|
||||||
|
}</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>0</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QLabel" name="sked_frequency_label">
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">* {
|
||||||
|
font-family: Courier;
|
||||||
|
font-size: 12pt;
|
||||||
|
font-weight: bold;
|
||||||
|
}</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>0</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">* {
|
||||||
|
font-family: Courier;
|
||||||
|
font-size: 12pt;
|
||||||
|
font-weight: bold;
|
||||||
|
}</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Rx:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">* {
|
||||||
|
font-family: Courier;
|
||||||
|
font-size: 12pt;
|
||||||
|
font-weight: bold;
|
||||||
|
}</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Tx:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0" colspan="2">
|
||||||
|
<widget class="QLabel" name="label_3">
|
||||||
|
<property name="text">
|
||||||
|
<string><html><head/><body><p>Press and hold the CTRL key to adjust the sked frequency manually with the rig's VFO dial or enter frequency directly into the band entry field on the main window.</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="textFormat">
|
||||||
|
<enum>Qt::AutoText</enum>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
|
</property>
|
||||||
|
<property name="wordWrap">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="verticalSpacer_2">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||||
|
<item alignment="Qt::AlignHCenter">
|
||||||
|
<widget class="QLabel" name="text_label">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">* {
|
||||||
|
font-family: Courier;
|
||||||
|
font-size: 12pt;
|
||||||
|
font-weight: bold;
|
||||||
|
}</string>
|
||||||
|
</property>
|
||||||
|
<property name="frameShadow">
|
||||||
|
<enum>QFrame::Sunken</enum>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Astro Data</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
|
</property>
|
||||||
|
<property name="margin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="cbDopplerTracking">
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true"/>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Doppler tracking</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
subroutine foxfilt(nslots,nfreq,width,wave)
|
||||||
|
|
||||||
|
parameter (NN=79,ND=58,KK=87,NSPS=4*1920)
|
||||||
|
parameter (NWAVE=NN*NSPS,NFFT=614400,NH=NFFT/2)
|
||||||
|
real wave(NWAVE)
|
||||||
|
real x(NFFT)
|
||||||
|
complex cx(0:NH)
|
||||||
|
equivalence (x,cx)
|
||||||
|
|
||||||
|
x(1:NWAVE)=wave
|
||||||
|
x(NWAVE+1:)=0.
|
||||||
|
call four2a(x,NFFT,1,-1,0) !r2c
|
||||||
|
df=48000.0/NFFT
|
||||||
|
fa=nfreq - 0.5*6.25
|
||||||
|
fb=nfreq + 7.5*6.25 + (nslots-1)*60.0
|
||||||
|
ia2=nint(fa/df)
|
||||||
|
ib1=nint(fb/df)
|
||||||
|
ia1=nint(ia2-width/df)
|
||||||
|
ib2=nint(ib1+width/df)
|
||||||
|
pi=4.0*atan(1.0)
|
||||||
|
do i=ia1,ia2
|
||||||
|
fil=(1.0 + cos(pi*df*(i-ia2)/width))/2.0
|
||||||
|
cx(i)=fil*cx(i)
|
||||||
|
enddo
|
||||||
|
do i=ib1,ib2
|
||||||
|
fil=(1.0 + cos(pi*df*(i-ib1)/width))/2.0
|
||||||
|
cx(i)=fil*cx(i)
|
||||||
|
enddo
|
||||||
|
cx(0:ia1-1)=0.
|
||||||
|
cx(ib2+1:)=0.
|
||||||
|
|
||||||
|
call four2a(cx,nfft,1,1,-1) !c2r
|
||||||
|
wave=x(1:NWAVE)/nfft
|
||||||
|
|
||||||
|
return
|
||||||
|
end subroutine foxfilt
|
||||||
@@ -0,0 +1,468 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>LogQSO</class>
|
||||||
|
<widget class="QDialog" name="LogQSO">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>377</width>
|
||||||
|
<height>257</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_11">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>10</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Click OK to confirm the following QSO:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="lab1">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>10</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Call</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="call"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="lab2">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>10</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Start</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QDateTimeEdit" name="start_date_time">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="displayFormat">
|
||||||
|
<string>dd/MM/yyyy HH:mm:ss</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="lab2_3">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>10</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>End</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QDateTimeEdit" name="end_date_time">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="displayFormat">
|
||||||
|
<string>dd/MM/yyyy HH:mm:ss</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="lab4">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>10</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Mode</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="mode">
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>70</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="lab5">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>10</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Band</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="band">
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>50</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_7">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="lab6">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>10</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Rpt Sent</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="sent">
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>50</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_8">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="lab7">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>10</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Rpt Rcvd</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="rcvd">
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>50</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_9">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="lab8">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>10</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Grid</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="grid">
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>70</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_10">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="lab9">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>10</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Name</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="name">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_6">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="text">
|
||||||
|
<string>Tx power</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="txPower"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="cbTxPower">
|
||||||
|
<property name="text">
|
||||||
|
<string>Retain</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="lab10">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>10</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Comments</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="comments">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="cbComments">
|
||||||
|
<property name="text">
|
||||||
|
<string>Retain</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="operatorLabel">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>10</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Operator</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="loggedOperator">
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>300</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="verticalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QDialogButtonBox" name="buttonBox">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="standardButtons">
|
||||||
|
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<tabstops>
|
||||||
|
<tabstop>call</tabstop>
|
||||||
|
<tabstop>start_date_time</tabstop>
|
||||||
|
<tabstop>end_date_time</tabstop>
|
||||||
|
<tabstop>mode</tabstop>
|
||||||
|
<tabstop>band</tabstop>
|
||||||
|
<tabstop>sent</tabstop>
|
||||||
|
<tabstop>rcvd</tabstop>
|
||||||
|
<tabstop>grid</tabstop>
|
||||||
|
<tabstop>name</tabstop>
|
||||||
|
<tabstop>txPower</tabstop>
|
||||||
|
<tabstop>cbTxPower</tabstop>
|
||||||
|
<tabstop>comments</tabstop>
|
||||||
|
<tabstop>cbComments</tabstop>
|
||||||
|
</tabstops>
|
||||||
|
<resources/>
|
||||||
|
<connections>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>accepted()</signal>
|
||||||
|
<receiver>LogQSO</receiver>
|
||||||
|
<slot>accept()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>248</x>
|
||||||
|
<y>254</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>157</x>
|
||||||
|
<y>274</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>rejected()</signal>
|
||||||
|
<receiver>LogQSO</receiver>
|
||||||
|
<slot>reject()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>316</x>
|
||||||
|
<y>260</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>286</x>
|
||||||
|
<y>274</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
</connections>
|
||||||
|
</ui>
|
||||||
@@ -1,266 +0,0 @@
|
|||||||
/* RAND-TEST.C - Program to test random number generators. */
|
|
||||||
|
|
||||||
/* Copyright (c) 1995-2012 by Radford M. Neal.
|
|
||||||
*
|
|
||||||
* Permission is granted for anyone to copy, use, modify, and distribute
|
|
||||||
* these programs and accompanying documents for any purpose, provided
|
|
||||||
* this copyright notice is retained and prominently displayed, and note
|
|
||||||
* is made of any changes made to these programs. These programs and
|
|
||||||
* documents are distributed without any warranty, express or implied.
|
|
||||||
* As the programs were written for research purposes only, they have not
|
|
||||||
* been tested to the degree that would be advisable in any important
|
|
||||||
* application. All use of these programs is entirely at the user's own
|
|
||||||
* risk.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/* Usage:
|
|
||||||
|
|
||||||
rand-test seed generator { parameters } / sample-size [ low high bins ]
|
|
||||||
|
|
||||||
Using the seed given, tests the random number generator identified by
|
|
||||||
the second argument, for the parameter values specified. The possible
|
|
||||||
generators and required parameters are as follows:
|
|
||||||
|
|
||||||
uniform Uniform from [0,1)
|
|
||||||
uniopen Uniform from (0,1)
|
|
||||||
int n Uniform from the set { 0, 1, ..., (n-1) }
|
|
||||||
gaussian From Gaussian with mean zero and unit variance
|
|
||||||
exp From exponential with mean one
|
|
||||||
cauchy From Cauchy centred at zero with unit width
|
|
||||||
gamma alpha From Gamma with shape parameter (and mean) alpha
|
|
||||||
beta a b From Beta with parameters a and b
|
|
||||||
|
|
||||||
The size of the sample to use is also specified. The program reports
|
|
||||||
the mean and variance of the sample. A histogram is also printed if a
|
|
||||||
low and high range and number of bins are for it are specified.
|
|
||||||
|
|
||||||
These tests are not really adequate to detect subtle forms of bias due
|
|
||||||
to use of pseudo-random numbers, but are hopefully good enough to find
|
|
||||||
most programming errors.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <math.h>
|
|
||||||
|
|
||||||
#include "rand.h"
|
|
||||||
|
|
||||||
|
|
||||||
#define Max_bins 1000 /* Maximum number of histogram bins */
|
|
||||||
|
|
||||||
static void usage (void);
|
|
||||||
|
|
||||||
|
|
||||||
/* MAIN PROGRAM. */
|
|
||||||
|
|
||||||
main
|
|
||||||
( int argc,
|
|
||||||
char **argv
|
|
||||||
)
|
|
||||||
{
|
|
||||||
int seed, sample_size, bins, np;
|
|
||||||
double low, high;
|
|
||||||
char *generator;
|
|
||||||
double p1, p2;
|
|
||||||
|
|
||||||
double mean, variance;
|
|
||||||
double tmean, tvariance;
|
|
||||||
int undef_mean, undef_variance;
|
|
||||||
|
|
||||||
int count[Max_bins];
|
|
||||||
int under, over;
|
|
||||||
|
|
||||||
char **ap;
|
|
||||||
double x;
|
|
||||||
int i, n;
|
|
||||||
|
|
||||||
bins = 0;
|
|
||||||
|
|
||||||
if (argc<5) usage();
|
|
||||||
|
|
||||||
if ((seed = atoi(argv[1]))==0 && strcmp(argv[1],"0")!=0) usage();
|
|
||||||
|
|
||||||
generator = argv[2];
|
|
||||||
|
|
||||||
if (strcmp(generator,"uniform")==0) np = 0;
|
|
||||||
else if (strcmp(generator,"uniopen")==0) np = 0;
|
|
||||||
else if (strcmp(generator,"int")==0) np = 1;
|
|
||||||
else if (strcmp(generator,"poisson")==0) np = 1;
|
|
||||||
else if (strcmp(generator,"gaussian")==0) np = 0;
|
|
||||||
else if (strcmp(generator,"exp")==0) np = 0;
|
|
||||||
else if (strcmp(generator,"cauchy")==0) np = 0;
|
|
||||||
else if (strcmp(generator,"gamma")==0) np = 1;
|
|
||||||
else if (strcmp(generator,"beta")==0) np = 2;
|
|
||||||
else
|
|
||||||
{ fprintf(stderr,"Unknown generator: %s\n",generator);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
ap = argv+3;
|
|
||||||
|
|
||||||
if (np>0)
|
|
||||||
{ if (*ap==0 || (p1 = atof(*ap++))<=0) usage();
|
|
||||||
}
|
|
||||||
if (np>1)
|
|
||||||
{ if (*ap==0 || (p2 = atof(*ap++))<=0) usage();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*ap==0 || strcmp(*ap++,"/")!=0) usage();
|
|
||||||
|
|
||||||
if (*ap==0 || (sample_size = atoi(*ap++))<=0) usage();
|
|
||||||
|
|
||||||
if (*ap!=0)
|
|
||||||
{ low = atof(*ap++);
|
|
||||||
if (*ap==0) usage();
|
|
||||||
high = atof(*ap++);
|
|
||||||
if (high<=low) usage();
|
|
||||||
if (*ap==0 || (bins = atoi(*ap++))<=0) usage();
|
|
||||||
if (bins>Max_bins)
|
|
||||||
{ fprintf(stderr,"Too many histogram bins\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*ap!=0) usage();
|
|
||||||
|
|
||||||
printf("\nTest of %s(",generator);
|
|
||||||
if (np>0) printf("%.4f",p1);
|
|
||||||
if (np>1) printf(",%.4f",p2);
|
|
||||||
printf(") generator using sample of size %d with seed %d\n\n",
|
|
||||||
sample_size, seed);
|
|
||||||
|
|
||||||
undef_mean = undef_variance = 0;
|
|
||||||
|
|
||||||
if (strcmp(generator,"uniform")==0)
|
|
||||||
{ tmean = 0.5;
|
|
||||||
tvariance = 1.0/12.0;
|
|
||||||
}
|
|
||||||
else if (strcmp(generator,"uniopen")==0)
|
|
||||||
{ tmean = 0.5;
|
|
||||||
tvariance = 1.0/12.0;
|
|
||||||
}
|
|
||||||
else if (strcmp(generator,"int")==0)
|
|
||||||
{ tmean = (p1-1)/2;
|
|
||||||
tvariance = p1*p1/3.0 - p1/2.0 + 1/6.0 - tmean*tmean;
|
|
||||||
}
|
|
||||||
else if (strcmp(generator,"poisson")==0)
|
|
||||||
{ tmean = p1;
|
|
||||||
tvariance = p1;
|
|
||||||
}
|
|
||||||
else if (strcmp(generator,"gaussian")==0)
|
|
||||||
{ tmean = 0;
|
|
||||||
tvariance = 1;
|
|
||||||
}
|
|
||||||
else if (strcmp(generator,"exp")==0)
|
|
||||||
{ tmean = 1;
|
|
||||||
tvariance = 1;
|
|
||||||
}
|
|
||||||
else if (strcmp(generator,"cauchy")==0)
|
|
||||||
{ undef_mean = 1;
|
|
||||||
undef_variance = 1;
|
|
||||||
}
|
|
||||||
else if (strcmp(generator,"gamma")==0)
|
|
||||||
{ tmean = p1;
|
|
||||||
tvariance = p1;
|
|
||||||
}
|
|
||||||
else if (strcmp(generator,"beta")==0)
|
|
||||||
{ tmean = p1 / (p1+p2);
|
|
||||||
tvariance = (p1*p2) / ((p1+p2)*(p1+p2)*(p1+p2+1));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
mean = 0;
|
|
||||||
variance = 0;
|
|
||||||
|
|
||||||
if (bins>0)
|
|
||||||
{ for (i = 0; i<bins; i++) count[i] = 0;
|
|
||||||
under = over = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
rand_seed(seed);
|
|
||||||
|
|
||||||
for (n = 0; n<sample_size; n++)
|
|
||||||
{
|
|
||||||
if (strcmp(generator,"uniform")==0) x = rand_uniform();
|
|
||||||
else if (strcmp(generator,"uniopen")==0) x = rand_uniopen();
|
|
||||||
else if (strcmp(generator,"int")==0) x = rand_int((int)p1);
|
|
||||||
else if (strcmp(generator,"poisson")==0) x = rand_poisson(p1);
|
|
||||||
else if (strcmp(generator,"gaussian")==0) x = rand_gaussian();
|
|
||||||
else if (strcmp(generator,"exp")==0) x = rand_exp();
|
|
||||||
else if (strcmp(generator,"cauchy")==0) x = rand_cauchy();
|
|
||||||
else if (strcmp(generator,"gamma")==0) x = rand_gamma(p1);
|
|
||||||
else if (strcmp(generator,"beta")==0) x = rand_beta(p1,p2);
|
|
||||||
else abort();
|
|
||||||
|
|
||||||
mean += x;
|
|
||||||
variance += x*x;
|
|
||||||
|
|
||||||
if (bins>0)
|
|
||||||
{ if (x<low)
|
|
||||||
{ under += 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ i = (int) ((x-low)/((high-low)/bins));
|
|
||||||
if (i>=bins)
|
|
||||||
{ over += 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ count[i] += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mean /= sample_size;
|
|
||||||
variance /= sample_size;
|
|
||||||
variance -= mean*mean;
|
|
||||||
|
|
||||||
printf("Sample mean: %.4f",mean);
|
|
||||||
if (undef_mean)
|
|
||||||
{ printf(" (true value: undefined)\n");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ printf(" (true value: %.4f)\n",tmean);
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("Sample variance: %.4f",variance);
|
|
||||||
if (undef_variance)
|
|
||||||
{ printf(" (true value: undefined)\n");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ printf(" (true value: %.4f)\n",tvariance);
|
|
||||||
}
|
|
||||||
printf("\n");
|
|
||||||
|
|
||||||
if (bins!=0)
|
|
||||||
{ printf("Histogram:\n");
|
|
||||||
printf(" under : %8d %.5f\n\n",
|
|
||||||
under, (double)under / sample_size);
|
|
||||||
for (i = 0; i<bins; i++)
|
|
||||||
{ printf(" %10.4f - %10.4f : %8d %.5f\n",
|
|
||||||
i*(high-low)/bins + low, (i+1)*(high-low)/bins + low,
|
|
||||||
count[i], (double)count[i] / sample_size);
|
|
||||||
}
|
|
||||||
printf("\n over : %8d %.5f\n",
|
|
||||||
over, (double)over / sample_size);
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* PRINT USAGE MESSAGE AND EXIT. */
|
|
||||||
|
|
||||||
static void usage (void)
|
|
||||||
{
|
|
||||||
fprintf(stderr,
|
|
||||||
"Usage: rand-test seed generator { parameters } / sample-size [ low high bins ]\n");
|
|
||||||
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
@@ -1,100 +0,0 @@
|
|||||||
<HTML><HEAD>
|
|
||||||
|
|
||||||
<TITLE> Support Programs </TITLE>
|
|
||||||
|
|
||||||
</HEAD><BODY>
|
|
||||||
|
|
||||||
|
|
||||||
<H1> Support Programs </H1>
|
|
||||||
|
|
||||||
The following programs provide support for testing and performance
|
|
||||||
assessment.
|
|
||||||
|
|
||||||
|
|
||||||
<P><A NAME="rand-src"><HR><B>rand-src</B>: Generate random message bits.
|
|
||||||
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
rand-src <I>source-file seed n-bits</I>
|
|
||||||
</PRE></BLOCKQUOTE>
|
|
||||||
|
|
||||||
<P>Creates a file of random messages bits called
|
|
||||||
<TT><I>source-file</I></TT>, which is suitable for testing the
|
|
||||||
correctness and performance of other programs. The bits in the file
|
|
||||||
are independent, and are equally likely to be 0 or 1. They are
|
|
||||||
generated pseudo-randomly based on <TT><I>seed</I></TT>. The actual
|
|
||||||
random number seed used will be <TT><I>seed</I></TT> times 10 plus 2,
|
|
||||||
so that the stream of pseudo-random numbers will not be the same as
|
|
||||||
any that might have been used by another program.
|
|
||||||
|
|
||||||
<P>The <TT><I>n-bits</I></TT> argument specifies the number of bits to
|
|
||||||
produce. It can be a single number, or it can consist of a block size
|
|
||||||
and a number of blocks, written with <TT>x</TT> separating these
|
|
||||||
numbers, with no spaces. Each block is written as a single line, with
|
|
||||||
the bits in the block represented by the characters '0' and '1', with
|
|
||||||
no intervening spaces. If the bit count is given by a single number,
|
|
||||||
the block size is assumed to be one.
|
|
||||||
|
|
||||||
<P><B>Example:</B> The following command produces a file containing
|
|
||||||
3 blocks, each consisting of 15 random bits, produced using the pseudo-random
|
|
||||||
number stream identified by the <TT><I>seed</I></TT> of 17:
|
|
||||||
<UL><PRE>
|
|
||||||
<LI>rand-src rsrc 17 15x3
|
|
||||||
</PRE></UL>
|
|
||||||
The contents of the file <TT>rsrc</TT> after this command might be something
|
|
||||||
like the following:
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
111011000110000
|
|
||||||
010010110010111
|
|
||||||
100000000000111
|
|
||||||
</BLOCKQUOTE></PRE>
|
|
||||||
|
|
||||||
|
|
||||||
<P><A NAME="verify"><HR><B>verify</B>: Verify that decoded blocks are
|
|
||||||
codewords, and that they match the source.
|
|
||||||
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
verify [ -t ] <I>pchk-file decoded-file</I> [ <I>gen-file</I> [ <I>source-file</I> ] ]
|
|
||||||
</PRE></BLOCKQUOTE>
|
|
||||||
|
|
||||||
<P>Checks whether or not the blocks in <TT><I>decoded-file</I></TT>
|
|
||||||
are codewords, according to the parity check matrix in
|
|
||||||
<TT><I>pchk-file</I></TT>. If <TT><I>gen-file</I></TT> is specified,
|
|
||||||
the message bits of the blocks are also checked against the
|
|
||||||
corresponding blocks of <TT><I>source-file</I></TT>, or against zero
|
|
||||||
if <TT><I>source-file</I></TT> is not given. (Normally, one would
|
|
||||||
leave out <TT><I>source-file</I></TT> only if the <A
|
|
||||||
HREF="channel.html#transmit"><TT>transmit</TT></A> command was used
|
|
||||||
with an argument specifying that zeros are to be transmitted, rather
|
|
||||||
than a file of encoded data.)
|
|
||||||
|
|
||||||
<P>A summary of the results is displayed on standard error, giving the
|
|
||||||
total numbers of blocks, the number with parity check errors, and, if
|
|
||||||
<TT><I>gen-file</I></TT> was specified, the number of blocks with
|
|
||||||
source errors and the number with errors of both kinds. If
|
|
||||||
<TT><I>gen-file</I></TT> was specified, a second
|
|
||||||
summary line displays the bit error rate from
|
|
||||||
comparing the decoded message bits with the true message bits (zeros
|
|
||||||
if no <TT><I>source file</I></TT> was given).
|
|
||||||
|
|
||||||
<P>If the <B>-t</B> option is given, block-by-block results are
|
|
||||||
printed on standard output in two or three columns, giving the block
|
|
||||||
number (from zero), the number of parity check errors for that block,
|
|
||||||
and the number of errors in source bits. The last column is omitted
|
|
||||||
if <TT><I>gen-file</I></TT> is not specified. The columns are
|
|
||||||
preceded by a line of headers, so the file is suitable for reading
|
|
||||||
into the S-Plus or R statistics packages, with a command such as
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
data <- read.table(<I>file</I>,header=T)
|
|
||||||
</PRE></BLOCKQUOTE>
|
|
||||||
|
|
||||||
<P>Warning messages are displayed on standard error if the number of
|
|
||||||
bits in <TT><I>decoded-file</I></TT> is not a multiple of the block
|
|
||||||
length, or if <TT><I>source-file</I></TT> is too short. Newlines
|
|
||||||
in these files are ignored, even though they would normally occur
|
|
||||||
at the ends of blocks.
|
|
||||||
|
|
||||||
<HR>
|
|
||||||
|
|
||||||
<A HREF="index.html">Back to index for LDPC software</A>
|
|
||||||
|
|
||||||
</BODY></HTML>
|
|
||||||
@@ -0,0 +1,495 @@
|
|||||||
|
#include "MessageServer.hpp"
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
#include <QUdpSocket>
|
||||||
|
#include <QString>
|
||||||
|
#include <QTimer>
|
||||||
|
#include <QHash>
|
||||||
|
|
||||||
|
#include "Radio.hpp"
|
||||||
|
#include "NetworkMessage.hpp"
|
||||||
|
#include "qt_helpers.hpp"
|
||||||
|
|
||||||
|
#include "pimpl_impl.hpp"
|
||||||
|
|
||||||
|
#include "moc_MessageServer.cpp"
|
||||||
|
|
||||||
|
class MessageServer::impl
|
||||||
|
: public QUdpSocket
|
||||||
|
{
|
||||||
|
Q_OBJECT;
|
||||||
|
|
||||||
|
public:
|
||||||
|
impl (MessageServer * self, QString const& version, QString const& revision)
|
||||||
|
: self_ {self}
|
||||||
|
, version_ {version}
|
||||||
|
, revision_ {revision}
|
||||||
|
, port_ {0u}
|
||||||
|
, clock_ {new QTimer {this}}
|
||||||
|
{
|
||||||
|
// register the required types with Qt
|
||||||
|
Radio::register_types ();
|
||||||
|
|
||||||
|
connect (this, &QIODevice::readyRead, this, &MessageServer::impl::pending_datagrams);
|
||||||
|
connect (this, static_cast<void (impl::*) (SocketError)> (&impl::error)
|
||||||
|
, [this] (SocketError /* e */)
|
||||||
|
{
|
||||||
|
Q_EMIT self_->error (errorString ());
|
||||||
|
});
|
||||||
|
connect (clock_, &QTimer::timeout, this, &impl::tick);
|
||||||
|
clock_->start (NetworkMessage::pulse * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
enum StreamStatus {Fail, Short, OK};
|
||||||
|
|
||||||
|
void leave_multicast_group ();
|
||||||
|
void join_multicast_group ();
|
||||||
|
void parse_message (QHostAddress const& sender, port_type sender_port, QByteArray const& msg);
|
||||||
|
void tick ();
|
||||||
|
void pending_datagrams ();
|
||||||
|
StreamStatus check_status (QDataStream const&) const;
|
||||||
|
void send_message (QDataStream const& out, QByteArray const& message, QHostAddress const& address, port_type port)
|
||||||
|
{
|
||||||
|
if (OK == check_status (out))
|
||||||
|
{
|
||||||
|
writeDatagram (message, address, port);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Q_EMIT self_->error ("Error creating UDP message");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageServer * self_;
|
||||||
|
QString version_;
|
||||||
|
QString revision_;
|
||||||
|
port_type port_;
|
||||||
|
QHostAddress multicast_group_address_;
|
||||||
|
static BindMode constexpr bind_mode_ = ShareAddress | ReuseAddressHint;
|
||||||
|
struct Client
|
||||||
|
{
|
||||||
|
Client () = default;
|
||||||
|
Client (QHostAddress const& sender_address, port_type const& sender_port)
|
||||||
|
: sender_address_ {sender_address}
|
||||||
|
, sender_port_ {sender_port}
|
||||||
|
, negotiated_schema_number_ {2} // not 1 because it's broken
|
||||||
|
, last_activity_ {QDateTime::currentDateTime ()}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
Client (Client const&) = default;
|
||||||
|
Client& operator= (Client const&) = default;
|
||||||
|
|
||||||
|
QHostAddress sender_address_;
|
||||||
|
port_type sender_port_;
|
||||||
|
quint32 negotiated_schema_number_;
|
||||||
|
QDateTime last_activity_;
|
||||||
|
};
|
||||||
|
QHash<QString, Client> clients_; // maps id to Client
|
||||||
|
QTimer * clock_;
|
||||||
|
};
|
||||||
|
|
||||||
|
MessageServer::impl::BindMode constexpr MessageServer::impl::bind_mode_;
|
||||||
|
|
||||||
|
#include "MessageServer.moc"
|
||||||
|
|
||||||
|
void MessageServer::impl::leave_multicast_group ()
|
||||||
|
{
|
||||||
|
if (!multicast_group_address_.isNull () && BoundState == state ())
|
||||||
|
{
|
||||||
|
leaveMulticastGroup (multicast_group_address_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageServer::impl::join_multicast_group ()
|
||||||
|
{
|
||||||
|
if (BoundState == state ()
|
||||||
|
&& !multicast_group_address_.isNull ())
|
||||||
|
{
|
||||||
|
if (IPv4Protocol == multicast_group_address_.protocol ()
|
||||||
|
&& IPv4Protocol != localAddress ().protocol ())
|
||||||
|
{
|
||||||
|
close ();
|
||||||
|
bind (QHostAddress::AnyIPv4, port_, bind_mode_);
|
||||||
|
}
|
||||||
|
if (!joinMulticastGroup (multicast_group_address_))
|
||||||
|
{
|
||||||
|
multicast_group_address_.clear ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageServer::impl::pending_datagrams ()
|
||||||
|
{
|
||||||
|
while (hasPendingDatagrams ())
|
||||||
|
{
|
||||||
|
QByteArray datagram;
|
||||||
|
datagram.resize (pendingDatagramSize ());
|
||||||
|
QHostAddress sender_address;
|
||||||
|
port_type sender_port;
|
||||||
|
if (0 <= readDatagram (datagram.data (), datagram.size (), &sender_address, &sender_port))
|
||||||
|
{
|
||||||
|
parse_message (sender_address, sender_port, datagram);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageServer::impl::parse_message (QHostAddress const& sender, port_type sender_port, QByteArray const& msg)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// message format is described in NetworkMessage.hpp
|
||||||
|
//
|
||||||
|
NetworkMessage::Reader in {msg};
|
||||||
|
|
||||||
|
auto id = in.id ();
|
||||||
|
if (OK == check_status (in))
|
||||||
|
{
|
||||||
|
if (!clients_.contains (id))
|
||||||
|
{
|
||||||
|
auto& client = (clients_[id] = {sender, sender_port});
|
||||||
|
QByteArray client_version;
|
||||||
|
QByteArray client_revision;
|
||||||
|
|
||||||
|
if (NetworkMessage::Heartbeat == in.type ())
|
||||||
|
{
|
||||||
|
// negotiate a working schema number
|
||||||
|
in >> client.negotiated_schema_number_;
|
||||||
|
if (OK == check_status (in))
|
||||||
|
{
|
||||||
|
auto sn = NetworkMessage::Builder::schema_number;
|
||||||
|
client.negotiated_schema_number_ = std::min (sn, client.negotiated_schema_number_);
|
||||||
|
|
||||||
|
// reply to the new client informing it of the
|
||||||
|
// negotiated schema number
|
||||||
|
QByteArray message;
|
||||||
|
NetworkMessage::Builder hb {&message, NetworkMessage::Heartbeat, id, client.negotiated_schema_number_};
|
||||||
|
hb << NetworkMessage::Builder::schema_number // maximum schema number accepted
|
||||||
|
<< version_.toUtf8 () << revision_.toUtf8 ();
|
||||||
|
if (impl::OK == check_status (hb))
|
||||||
|
{
|
||||||
|
writeDatagram (message, client.sender_address_, client.sender_port_);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Q_EMIT self_->error ("Error creating UDP message");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// we don't care if this fails to read
|
||||||
|
in >> client_version >> client_revision;
|
||||||
|
}
|
||||||
|
Q_EMIT self_->client_opened (id, QString::fromUtf8 (client_version),
|
||||||
|
QString::fromUtf8 (client_revision));
|
||||||
|
}
|
||||||
|
clients_[id].last_activity_ = QDateTime::currentDateTime ();
|
||||||
|
|
||||||
|
//
|
||||||
|
// message format is described in NetworkMessage.hpp
|
||||||
|
//
|
||||||
|
switch (in.type ())
|
||||||
|
{
|
||||||
|
case NetworkMessage::Heartbeat:
|
||||||
|
//nothing to do here as time out handling deals with lifetime
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NetworkMessage::Clear:
|
||||||
|
Q_EMIT self_->clear_decodes (id);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NetworkMessage::Status:
|
||||||
|
{
|
||||||
|
// unpack message
|
||||||
|
Frequency f;
|
||||||
|
QByteArray mode;
|
||||||
|
QByteArray dx_call;
|
||||||
|
QByteArray report;
|
||||||
|
QByteArray tx_mode;
|
||||||
|
bool tx_enabled {false};
|
||||||
|
bool transmitting {false};
|
||||||
|
bool decoding {false};
|
||||||
|
qint32 rx_df {-1};
|
||||||
|
qint32 tx_df {-1};
|
||||||
|
QByteArray de_call;
|
||||||
|
QByteArray de_grid;
|
||||||
|
QByteArray dx_grid;
|
||||||
|
bool watchdog_timeout {false};
|
||||||
|
QByteArray sub_mode;
|
||||||
|
bool fast_mode {false};
|
||||||
|
in >> f >> mode >> dx_call >> report >> tx_mode >> tx_enabled >> transmitting >> decoding
|
||||||
|
>> rx_df >> tx_df >> de_call >> de_grid >> dx_grid >> watchdog_timeout >> sub_mode
|
||||||
|
>> fast_mode;
|
||||||
|
if (check_status (in) != Fail)
|
||||||
|
{
|
||||||
|
Q_EMIT self_->status_update (id, f, QString::fromUtf8 (mode), QString::fromUtf8 (dx_call)
|
||||||
|
, QString::fromUtf8 (report), QString::fromUtf8 (tx_mode)
|
||||||
|
, tx_enabled, transmitting, decoding, rx_df, tx_df
|
||||||
|
, QString::fromUtf8 (de_call), QString::fromUtf8 (de_grid)
|
||||||
|
, QString::fromUtf8 (dx_grid), watchdog_timeout
|
||||||
|
, QString::fromUtf8 (sub_mode), fast_mode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NetworkMessage::Decode:
|
||||||
|
{
|
||||||
|
// unpack message
|
||||||
|
bool is_new {true};
|
||||||
|
QTime time;
|
||||||
|
qint32 snr;
|
||||||
|
float delta_time;
|
||||||
|
quint32 delta_frequency;
|
||||||
|
QByteArray mode;
|
||||||
|
QByteArray message;
|
||||||
|
bool low_confidence {false};
|
||||||
|
bool off_air {false};
|
||||||
|
in >> is_new >> time >> snr >> delta_time >> delta_frequency >> mode
|
||||||
|
>> message >> low_confidence >> off_air;
|
||||||
|
if (check_status (in) != Fail)
|
||||||
|
{
|
||||||
|
Q_EMIT self_->decode (is_new, id, time, snr, delta_time, delta_frequency
|
||||||
|
, QString::fromUtf8 (mode), QString::fromUtf8 (message)
|
||||||
|
, low_confidence, off_air);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NetworkMessage::WSPRDecode:
|
||||||
|
{
|
||||||
|
// unpack message
|
||||||
|
bool is_new {true};
|
||||||
|
QTime time;
|
||||||
|
qint32 snr;
|
||||||
|
float delta_time;
|
||||||
|
Frequency frequency;
|
||||||
|
qint32 drift;
|
||||||
|
QByteArray callsign;
|
||||||
|
QByteArray grid;
|
||||||
|
qint32 power;
|
||||||
|
bool off_air {false};
|
||||||
|
in >> is_new >> time >> snr >> delta_time >> frequency >> drift >> callsign >> grid >> power
|
||||||
|
>> off_air;
|
||||||
|
if (check_status (in) != Fail)
|
||||||
|
{
|
||||||
|
Q_EMIT self_->WSPR_decode (is_new, id, time, snr, delta_time, frequency, drift
|
||||||
|
, QString::fromUtf8 (callsign), QString::fromUtf8 (grid)
|
||||||
|
, power, off_air);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NetworkMessage::QSOLogged:
|
||||||
|
{
|
||||||
|
QDateTime time_off;
|
||||||
|
QByteArray dx_call;
|
||||||
|
QByteArray dx_grid;
|
||||||
|
Frequency dial_frequency;
|
||||||
|
QByteArray mode;
|
||||||
|
QByteArray report_sent;
|
||||||
|
QByteArray report_received;
|
||||||
|
QByteArray tx_power;
|
||||||
|
QByteArray comments;
|
||||||
|
QByteArray name;
|
||||||
|
QDateTime time_on; // Note: LOTW uses TIME_ON for their +/- 30-minute time window
|
||||||
|
QByteArray operator_call;
|
||||||
|
QByteArray my_call;
|
||||||
|
QByteArray my_grid;
|
||||||
|
in >> time_off >> dx_call >> dx_grid >> dial_frequency >> mode >> report_sent >> report_received
|
||||||
|
>> tx_power >> comments >> name >> time_on >> operator_call >> my_call >> my_grid;
|
||||||
|
if (check_status (in) != Fail)
|
||||||
|
{
|
||||||
|
Q_EMIT self_->qso_logged (id, time_off, QString::fromUtf8 (dx_call), QString::fromUtf8 (dx_grid)
|
||||||
|
, dial_frequency, QString::fromUtf8 (mode), QString::fromUtf8 (report_sent)
|
||||||
|
, QString::fromUtf8 (report_received), QString::fromUtf8 (tx_power)
|
||||||
|
, QString::fromUtf8 (comments), QString::fromUtf8 (name), time_on
|
||||||
|
, QString::fromUtf8 (operator_call), QString::fromUtf8 (my_call)
|
||||||
|
, QString::fromUtf8 (my_grid));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NetworkMessage::Close:
|
||||||
|
Q_EMIT self_->client_closed (id);
|
||||||
|
clients_.remove (id);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NetworkMessage::LoggedADIF:
|
||||||
|
{
|
||||||
|
QByteArray ADIF;
|
||||||
|
in >> ADIF;
|
||||||
|
if (check_status (in) != Fail)
|
||||||
|
{
|
||||||
|
Q_EMIT self_->logged_ADIF (id, ADIF);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
// Ignore
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Q_EMIT self_->error ("MessageServer warning: invalid UDP message received");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (std::exception const& e)
|
||||||
|
{
|
||||||
|
Q_EMIT self_->error (QString {"MessageServer exception: %1"}.arg (e.what ()));
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
Q_EMIT self_->error ("Unexpected exception in MessageServer");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageServer::impl::tick ()
|
||||||
|
{
|
||||||
|
auto now = QDateTime::currentDateTime ();
|
||||||
|
auto iter = std::begin (clients_);
|
||||||
|
while (iter != std::end (clients_))
|
||||||
|
{
|
||||||
|
if (now > (*iter).last_activity_.addSecs (NetworkMessage::pulse))
|
||||||
|
{
|
||||||
|
Q_EMIT self_->clear_decodes (iter.key ());
|
||||||
|
Q_EMIT self_->client_closed (iter.key ());
|
||||||
|
iter = clients_.erase (iter); // safe while iterating as doesn't rehash
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
++iter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto MessageServer::impl::check_status (QDataStream const& stream) const -> StreamStatus
|
||||||
|
{
|
||||||
|
auto stat = stream.status ();
|
||||||
|
StreamStatus result {Fail};
|
||||||
|
switch (stat)
|
||||||
|
{
|
||||||
|
case QDataStream::ReadPastEnd:
|
||||||
|
result = Short;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case QDataStream::ReadCorruptData:
|
||||||
|
Q_EMIT self_->error ("Message serialization error: read corrupt data");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case QDataStream::WriteFailed:
|
||||||
|
Q_EMIT self_->error ("Message serialization error: write error");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
result = OK;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageServer::MessageServer (QObject * parent, QString const& version, QString const& revision)
|
||||||
|
: QObject {parent}
|
||||||
|
, m_ {this, version, revision}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageServer::start (port_type port, QHostAddress const& multicast_group_address)
|
||||||
|
{
|
||||||
|
if (port != m_->port_
|
||||||
|
|| multicast_group_address != m_->multicast_group_address_)
|
||||||
|
{
|
||||||
|
m_->leave_multicast_group ();
|
||||||
|
if (impl::BoundState == m_->state ())
|
||||||
|
{
|
||||||
|
m_->close ();
|
||||||
|
}
|
||||||
|
m_->multicast_group_address_ = multicast_group_address;
|
||||||
|
auto address = m_->multicast_group_address_.isNull ()
|
||||||
|
|| impl::IPv4Protocol != m_->multicast_group_address_.protocol () ? QHostAddress::Any : QHostAddress::AnyIPv4;
|
||||||
|
if (port && m_->bind (address, port, m_->bind_mode_))
|
||||||
|
{
|
||||||
|
m_->port_ = port;
|
||||||
|
m_->join_multicast_group ();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_->port_ = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageServer::reply (QString const& id, QTime time, qint32 snr, float delta_time
|
||||||
|
, quint32 delta_frequency, QString const& mode
|
||||||
|
, QString const& message_text, bool low_confidence, quint8 modifiers)
|
||||||
|
{
|
||||||
|
auto iter = m_->clients_.find (id);
|
||||||
|
if (iter != std::end (m_->clients_))
|
||||||
|
{
|
||||||
|
QByteArray message;
|
||||||
|
NetworkMessage::Builder out {&message, NetworkMessage::Reply, id, (*iter).negotiated_schema_number_};
|
||||||
|
out << time << snr << delta_time << delta_frequency << mode.toUtf8 ()
|
||||||
|
<< message_text.toUtf8 () << low_confidence << modifiers;
|
||||||
|
m_->send_message (out, message, iter.value ().sender_address_, (*iter).sender_port_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageServer::replay (QString const& id)
|
||||||
|
{
|
||||||
|
auto iter = m_->clients_.find (id);
|
||||||
|
if (iter != std::end (m_->clients_))
|
||||||
|
{
|
||||||
|
QByteArray message;
|
||||||
|
NetworkMessage::Builder out {&message, NetworkMessage::Replay, id, (*iter).negotiated_schema_number_};
|
||||||
|
m_->send_message (out, message, iter.value ().sender_address_, (*iter).sender_port_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageServer::halt_tx (QString const& id, bool auto_only)
|
||||||
|
{
|
||||||
|
auto iter = m_->clients_.find (id);
|
||||||
|
if (iter != std::end (m_->clients_))
|
||||||
|
{
|
||||||
|
QByteArray message;
|
||||||
|
NetworkMessage::Builder out {&message, NetworkMessage::HaltTx, id, (*iter).negotiated_schema_number_};
|
||||||
|
out << auto_only;
|
||||||
|
m_->send_message (out, message, iter.value ().sender_address_, (*iter).sender_port_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageServer::free_text (QString const& id, QString const& text, bool send)
|
||||||
|
{
|
||||||
|
auto iter = m_->clients_.find (id);
|
||||||
|
if (iter != std::end (m_->clients_))
|
||||||
|
{
|
||||||
|
QByteArray message;
|
||||||
|
NetworkMessage::Builder out {&message, NetworkMessage::FreeText, id, (*iter).negotiated_schema_number_};
|
||||||
|
out << text.toUtf8 () << send;
|
||||||
|
m_->send_message (out, message, iter.value ().sender_address_, (*iter).sender_port_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageServer::location (QString const& id, QString const& loc)
|
||||||
|
{
|
||||||
|
auto iter = m_->clients_.find (id);
|
||||||
|
if (iter != std::end (m_->clients_))
|
||||||
|
{
|
||||||
|
QByteArray message;
|
||||||
|
NetworkMessage::Builder out {&message, NetworkMessage::Location, id, (*iter).negotiated_schema_number_};
|
||||||
|
out << loc.toUtf8 ();
|
||||||
|
m_->send_message (out, message, iter.value ().sender_address_, (*iter).sender_port_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageServer::highlight_callsign (QString const& id, QString const& callsign
|
||||||
|
, QColor const& bg, QColor const& fg, bool last_only)
|
||||||
|
{
|
||||||
|
auto iter = m_->clients_.find (id);
|
||||||
|
if (iter != std::end (m_->clients_))
|
||||||
|
{
|
||||||
|
QByteArray message;
|
||||||
|
NetworkMessage::Builder out {&message, NetworkMessage::HighlightCallsign, id, (*iter).negotiated_schema_number_};
|
||||||
|
out << callsign.toUtf8 () << bg << fg << last_only;
|
||||||
|
m_->send_message (out, message, iter.value ().sender_address_, (*iter).sender_port_);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,154 @@
|
|||||||
|
integer, parameter:: N=204, K=68, M=N-K
|
||||||
|
character*17 g(136)
|
||||||
|
integer colorder(N)
|
||||||
|
data g/ & !parity generator matrix for (204,68) code
|
||||||
|
"2de7435fd27c0031d", &
|
||||||
|
"f331b40671e20ea80", &
|
||||||
|
"48bd3f8cb9a24392f", &
|
||||||
|
"d4ed71c935162aa2a", &
|
||||||
|
"c437a3284ec58bce7", &
|
||||||
|
"35a806dd5be35627c", &
|
||||||
|
"396e797c33a4739a6", &
|
||||||
|
"768f331a59c15487b", &
|
||||||
|
"c214eac24ae5e1732", &
|
||||||
|
"0b5c53ff3a6da1192", &
|
||||||
|
"99624981d2703fb97", &
|
||||||
|
"e9f5447ef7f1ff6af", &
|
||||||
|
"bd8c730f0cfdf0727", &
|
||||||
|
"26f61e63e1e098f7f", &
|
||||||
|
"ef826566137b6526f", &
|
||||||
|
"af0e4fa251e9b4926", &
|
||||||
|
"75974a8b2a24292c5", &
|
||||||
|
"71caf0f2cd10f6d4f", &
|
||||||
|
"b1103f1f26e6898b7", &
|
||||||
|
"67ceb7d6f490da64f", &
|
||||||
|
"ee0e8fbefec23008a", &
|
||||||
|
"11cc2227e8bd676ca", &
|
||||||
|
"6e71626ba1e278046", &
|
||||||
|
"005d28da267e50e13", &
|
||||||
|
"a9ae4a130aaba8219", &
|
||||||
|
"d8ab72e0158d0da70", &
|
||||||
|
"56009d42b37bd66ff", &
|
||||||
|
"c39a75eca99b0e996", &
|
||||||
|
"6886de0bf7c0bf4bb", &
|
||||||
|
"1046cd8f64162f7b5", &
|
||||||
|
"da0f15843ac21e3a5", &
|
||||||
|
"e9bf9cd19f3db3913", &
|
||||||
|
"2fb9cb42d650f47a7", &
|
||||||
|
"a2b6c5a378fa75a65", &
|
||||||
|
"41a88f3cd60b79d6c", &
|
||||||
|
"fcf175794cc3ac96a", &
|
||||||
|
"8677a3447d40a9f71", &
|
||||||
|
"97a1f08c250b4bf12", &
|
||||||
|
"0168f090a1df6e8ea", &
|
||||||
|
"418a06bf372cc67d9", &
|
||||||
|
"0f17b880c1ff51239", &
|
||||||
|
"b2afd6d585deb961b", &
|
||||||
|
"60298ac5b58dbeee0", &
|
||||||
|
"8350c03c40119feff", &
|
||||||
|
"b29c964a8accf6af4", &
|
||||||
|
"9b46f036a5c178b5d", &
|
||||||
|
"917398bff051c300a", &
|
||||||
|
"5e52c03b2f8c5128c", &
|
||||||
|
"beae6c33c87ba38ab", &
|
||||||
|
"20843f7b056a02ebf", &
|
||||||
|
"66690d65acd9de598", &
|
||||||
|
"8f025841af5b54331", &
|
||||||
|
"b43cd869d3be2c3db", &
|
||||||
|
"c9c342fe63c18df50", &
|
||||||
|
"d331b40671e28ea80", &
|
||||||
|
"62406a0f4947e6ce9", &
|
||||||
|
"d67b1495883b22e1b", &
|
||||||
|
"734534c372408895b", &
|
||||||
|
"d88750e33d9677dcd", &
|
||||||
|
"6f96964da55138687", &
|
||||||
|
"80bee98bb75d50ef2", &
|
||||||
|
"c428ef3e3f06f4c56", &
|
||||||
|
"b1a1499b125883a35", &
|
||||||
|
"ac892d4b37fa9e395", &
|
||||||
|
"458dbda0f95ab11a5", &
|
||||||
|
"6f93c9e95b1094eed", &
|
||||||
|
"2e370d713914f848e", &
|
||||||
|
"758806dd5be35627c", &
|
||||||
|
"8c52e01caec798b49", &
|
||||||
|
"c286cc25bae3669cf", &
|
||||||
|
"87c56fb895c100884", &
|
||||||
|
"e89cb1376a18fd911", &
|
||||||
|
"156ffe5f30dc354e0", &
|
||||||
|
"f20d0b121d6a6b3ee", &
|
||||||
|
"7db08891b491a95d2", &
|
||||||
|
"191fac548d5077bdf", &
|
||||||
|
"023a37d7ea5660bbc", &
|
||||||
|
"6781668b363fee682", &
|
||||||
|
"bbfaf262cab7370da", &
|
||||||
|
"feea557965b7e474f", &
|
||||||
|
"c094eb223e1d305b8", &
|
||||||
|
"2be051abdd5beea35", &
|
||||||
|
"0790449880fda9d00", &
|
||||||
|
"f9029a39ec869e7b4", &
|
||||||
|
"5a29f48926ec9a552", &
|
||||||
|
"e0463306dc1470f87", &
|
||||||
|
"9251058334d790f86", &
|
||||||
|
"3019e1d4578e8a4dc", &
|
||||||
|
"887e46631502fa111", &
|
||||||
|
"c25fcd7a42465d326", &
|
||||||
|
"cf64bcc1056b555c4", &
|
||||||
|
"3e71c0fe5f0ad733b", &
|
||||||
|
"11055ec43b076e5b2", &
|
||||||
|
"3440f64dfa3c30a96", &
|
||||||
|
"2b73885b4d3299f60", &
|
||||||
|
"2e71627ba1e268046", &
|
||||||
|
"ad23743d5e6e5b80c", &
|
||||||
|
"c9757b05f29bfdc10", &
|
||||||
|
"f7112bea739247b51", &
|
||||||
|
"3664062387998b2b1", &
|
||||||
|
"90897a3b8785aefba", &
|
||||||
|
"29e126e3201fc1d46", &
|
||||||
|
"96c9001c84d5257fc", &
|
||||||
|
"067723447d40a9f71", &
|
||||||
|
"1a019cc68f7511402", &
|
||||||
|
"4bd48eb2330032763", &
|
||||||
|
"d139a5da936b37647", &
|
||||||
|
"765ab46a4dec5f04f", &
|
||||||
|
"706f475ad19b91955", &
|
||||||
|
"1755c988fa8a55e5c", &
|
||||||
|
"2fd9ed5777eb01d6a", &
|
||||||
|
"bec27d85b954d3fe8", &
|
||||||
|
"7135a3b92c45b3f8d", &
|
||||||
|
"353237872f002163a", &
|
||||||
|
"e31e4a97aef10c729", &
|
||||||
|
"da527d5e1cbc4edb6", &
|
||||||
|
"6e33cdede17c3207e", &
|
||||||
|
"ef2d2062e84dc401f", &
|
||||||
|
"8217c84c50c1bf833", &
|
||||||
|
"12ffbac7b2219c9e0", &
|
||||||
|
"3729178706f66881f", &
|
||||||
|
"2fdd748c382a608a1", &
|
||||||
|
"dd0a00076f9dcec73", &
|
||||||
|
"46b1d37bced447035", &
|
||||||
|
"7316f33a9c05ef178", &
|
||||||
|
"152c39a6de8954cc3", &
|
||||||
|
"16efffb7b62e12ba3", &
|
||||||
|
"9d9ec2bb467affd83", &
|
||||||
|
"467723445d40a9f61", &
|
||||||
|
"87994762b3bf50697", &
|
||||||
|
"b1bfa5b51526dde9b", &
|
||||||
|
"b0a6a19d709a96148", &
|
||||||
|
"990d567c0aba31a14", &
|
||||||
|
"171f190792461b1e0", &
|
||||||
|
"166011c27d2b6b8a4", &
|
||||||
|
"170c15831244ae73e"/
|
||||||
|
|
||||||
|
data colorder/ &
|
||||||
|
0, 1, 2, 3, 4, 5, 47, 6, 7, 8, 9, 10, 11, 12, 58, 55, 13, &
|
||||||
|
14, 15, 46, 17, 18, 60, 19, 20, 21, 22, 23, 24, 25, 57, 26, 27, 49, &
|
||||||
|
28, 52, 65, 16, 50, 73, 59, 68, 63, 29, 30, 31, 32, 51, 62, 56, 66, &
|
||||||
|
45, 33, 34, 53, 67, 35, 36, 37, 61, 69, 54, 38, 71, 82, 39, 77, 80, &
|
||||||
|
83, 78, 84, 48, 41, 85, 40, 64, 75, 96, 74, 72, 76, 86, 87, 89, 90, &
|
||||||
|
79, 70, 92, 99, 93,101, 95,100, 97, 94, 42, 98,103,105,102, 43,104, &
|
||||||
|
88, 44,106, 81,107,110,108,111,112,109,113,114,117,118,116,121,115, &
|
||||||
|
119,122,120,125,129,124,127,126,128, 91,123,133,131,130,134,135,137, &
|
||||||
|
136,132,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152, &
|
||||||
|
153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169, &
|
||||||
|
170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186, &
|
||||||
|
187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203/
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
// Forward declaration of the circular buffer and its adaptor.
|
||||||
|
|
||||||
|
// Copyright (c) 2003-2008 Jan Gaspar
|
||||||
|
|
||||||
|
// Use, modification, and distribution is subject to the Boost Software
|
||||||
|
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
// http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
|
||||||
|
// See www.boost.org/libs/circular_buffer for documentation.
|
||||||
|
|
||||||
|
#if !defined(BOOST_CIRCULAR_BUFFER_FWD_HPP)
|
||||||
|
#define BOOST_CIRCULAR_BUFFER_FWD_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <boost/config.hpp>
|
||||||
|
#if !defined(BOOST_NO_STD_ALLOCATOR)
|
||||||
|
#include <memory>
|
||||||
|
#else
|
||||||
|
#include <vector>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace boost {
|
||||||
|
|
||||||
|
#if !defined(BOOST_NO_STD_ALLOCATOR)
|
||||||
|
#define BOOST_CB_DEFAULT_ALLOCATOR(T) std::allocator<T>
|
||||||
|
#else
|
||||||
|
#define BOOST_CB_DEFAULT_ALLOCATOR(T) BOOST_DEDUCED_TYPENAME std::vector<T>::allocator_type
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template <class T, class Alloc = BOOST_CB_DEFAULT_ALLOCATOR(T)>
|
||||||
|
class circular_buffer;
|
||||||
|
|
||||||
|
template <class T, class Alloc = BOOST_CB_DEFAULT_ALLOCATOR(T)>
|
||||||
|
class circular_buffer_space_optimized;
|
||||||
|
|
||||||
|
#undef BOOST_CB_DEFAULT_ALLOCATOR
|
||||||
|
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
#endif // #if !defined(BOOST_CIRCULAR_BUFFER_FWD_HPP)
|
||||||
@@ -1,719 +0,0 @@
|
|||||||
<HTML><HEAD>
|
|
||||||
|
|
||||||
<TITLE> Sparse Modulo-2 Matrix Routines </TITLE>
|
|
||||||
|
|
||||||
</HEAD><BODY>
|
|
||||||
|
|
||||||
|
|
||||||
<H1> Sparse Modulo-2 Matrix Routines </H1>
|
|
||||||
|
|
||||||
<P>This module implements operations on matrices in which the elements
|
|
||||||
are all 0 or 1, with addition and multiplication being done modulo 2.
|
|
||||||
The matrices are represented by doubly-linked lists of entries
|
|
||||||
representing the elements in each row and column that are 1s, with
|
|
||||||
other elements being assumed to be zero.
|
|
||||||
|
|
||||||
<P>This is an appropriate representation when the matrices are sparse
|
|
||||||
(ie, 0s are much more frequent that 1s). Matrices in which 0s and 1s
|
|
||||||
are about equally likely may be better handled with the <A
|
|
||||||
HREF="mod2dense.html">dense modulo-2 matrix routines</A>. Matrices
|
|
||||||
can be converted between these two formats using the <A
|
|
||||||
HREF="mod2convert.html">module-2 matrix conversion routines</A>.
|
|
||||||
|
|
||||||
<P>All procedures in this module display an error message on standard
|
|
||||||
error and terminate the program if passed an invalid argument (indicative
|
|
||||||
of a programming error), or if memory cannot be allocated. Errors from
|
|
||||||
invalid contents of a file result in an error code being returned to the
|
|
||||||
caller, with no message being printed by this module.
|
|
||||||
|
|
||||||
|
|
||||||
<A NAME="rep"><H2>Representation of sparse matrices</H2></A>
|
|
||||||
|
|
||||||
<P>This module represents a non-zero element of a matrix (which must have
|
|
||||||
the value 1, since these are modulo-2 matrices) by a node of type
|
|
||||||
<TT>mod2entry</TT>, which contains the row and column of the element,
|
|
||||||
pointers to the next non-zero elements above and below in its column
|
|
||||||
and to the left and the right in its row, and two double-precision
|
|
||||||
floating-point numbers called <B>pr</B> and <B>lr</B>, which are
|
|
||||||
of no significance to this module, but which are used by the routines
|
|
||||||
for <A HREF="decoding.html#prprp">decoding LDPC codes by probability
|
|
||||||
propagation</A>.
|
|
||||||
|
|
||||||
<P>The <TT>mod2sparse</TT> type represents a matrix. It records the
|
|
||||||
number of rows and columns in the matrix, and contains arrays of
|
|
||||||
pointers to the <TT>mod2entry</TT> structures for the first non-zero
|
|
||||||
element in each row and the first non-zero element in each column.
|
|
||||||
|
|
||||||
<P>Matrices must be created by the <A
|
|
||||||
HREF="#allocate"><TT>mod2sparse_allocate</TT></A> procedure, which
|
|
||||||
returns a pointer to a <TT>mod2sparse</TT> structure. When a matrix
|
|
||||||
is no longer needed, the space it occupies can be freed with <A
|
|
||||||
HREF="#free"><TT>mod2sparse_free</TT></A>. Elements within a matrix,
|
|
||||||
represented by <TT>mod2entry</TT> nodes, are allocated as needed, and
|
|
||||||
if deleted, they will be reused for new elements within the same
|
|
||||||
matrix. The space they occupy is not reusable for other matrices or
|
|
||||||
other purposes until the entire matrix is either freed, with <A
|
|
||||||
HREF="#free"><TT>mod2sparse_free</TT></A>, or cleared to all zeros,
|
|
||||||
with <A HREF="#clear"><TT>mod2sparse_clear</TT></A>, or used as
|
|
||||||
the result matrix for copying or arithmetic operations.
|
|
||||||
|
|
||||||
|
|
||||||
<P><B>Header files required</B>:
|
|
||||||
<TT>mod2sparse.h</TT>
|
|
||||||
|
|
||||||
|
|
||||||
<A NAME="dimension-sec">
|
|
||||||
<P><HR>
|
|
||||||
<CENTER><BIG>Dimension Macros</BIG></CENTER>
|
|
||||||
</A>
|
|
||||||
|
|
||||||
<HR>The following macros take a pointer to a mod2sparse structure as their
|
|
||||||
argument, and return the number of rows or the number of columns in
|
|
||||||
the matrix pointed to, which will have been fixed when the matrix was
|
|
||||||
created with <A HREF="#allocate">mod2sparse_allocate</A>:
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
mod2sparse_rows(m) /* Returns the number of rows in m */
|
|
||||||
|
|
||||||
mod2sparse_cols(m) /* Returns the number of columns in m */
|
|
||||||
</PRE></BLOCKQUOTE>
|
|
||||||
|
|
||||||
|
|
||||||
<A NAME="traversal-sec">
|
|
||||||
<P><HR>
|
|
||||||
<CENTER><BIG>Traversal Macros</BIG></CENTER>
|
|
||||||
</A>
|
|
||||||
|
|
||||||
<HR>The following macros are used to move around a sparse matrix by
|
|
||||||
following the pointers from one non-zero element to the next or
|
|
||||||
previous non-zero element in the same row or column. If such a
|
|
||||||
movement takes one beyond the last or before first entry in a row or
|
|
||||||
column, or if one tries to find the first or last non-zero entry in a
|
|
||||||
row or column that has no non-zero entries, the entry returned will be
|
|
||||||
a special one that can be identified using the
|
|
||||||
<TT>mod2sparse_at_end</TT> macro. If one is already at this special
|
|
||||||
entry, moving further wraps one around to the first or last entry.
|
|
||||||
|
|
||||||
<P>The macros for finding the first or last entry in a row or column
|
|
||||||
take as their arguments a pointer to the matrix (<TT>mod2sparse
|
|
||||||
*</TT>) and a row or column index, starting at zero. The other macros
|
|
||||||
take as their arguments a pointer to an entry (<TT>mod2entry *</TT>)
|
|
||||||
within some matrix.
|
|
||||||
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
mod2sparse_first_in_row(m,i) /* Returns the first entry in row i of m */
|
|
||||||
mod2sparse_first_in_col(m,j) /* Returns the first entry in column j of m */
|
|
||||||
|
|
||||||
mod2sparse_last_in_row(m,i) /* Returns the last entry in row i of m */
|
|
||||||
mod2sparse_last_in_col(m,j) /* Returns the last entry in column j of m */
|
|
||||||
|
|
||||||
mod2sparse_next_in_row(e) /* Returns the entry after e in its row */
|
|
||||||
mod2sparse_next_in_col(e) /* Returns the entry after e in its column */
|
|
||||||
|
|
||||||
mod2sparse_prev_in_row(e) /* Returns the entry before e in its row */
|
|
||||||
mod2sparse_prev_in_col(e) /* Returns the entry before e in its col */
|
|
||||||
|
|
||||||
mod2sparse_row(e) /* Returns the row index of entry e */
|
|
||||||
mod2sparse_col(e) /* Returns the column index of entry e */
|
|
||||||
|
|
||||||
mod2sparse_at_end(e) /* Returns 1 if e is a special entry obtained
|
|
||||||
by moving past the end, returns 0 otherwise */
|
|
||||||
</PRE></BLOCKQUOTE>
|
|
||||||
|
|
||||||
|
|
||||||
<A NAME="alloc-sec">
|
|
||||||
<P><HR>
|
|
||||||
<CENTER><BIG>Allocating and Freeing Sparse Modulo-2 Matrices</BIG></CENTER>
|
|
||||||
</A>
|
|
||||||
|
|
||||||
|
|
||||||
<A NAME="allocate"><HR><B>mod2sparse_allocate</B>:
|
|
||||||
Allocate space for a sparse module-2 matrix.</A>
|
|
||||||
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
mod2sparse *mod2sparse_allocate
|
|
||||||
( int n_rows, /* Number of rows in matrix */
|
|
||||||
int n_cols /* Number of columns in matrix */
|
|
||||||
)
|
|
||||||
</PRE></BLOCKQUOTE>
|
|
||||||
|
|
||||||
Allocates space for a matrix with the given number of rows and
|
|
||||||
columns, and returns a pointer to it. The matrix will initially
|
|
||||||
be all zero.
|
|
||||||
|
|
||||||
<P>If there is not enough memory available, a message is displayed on
|
|
||||||
standard error and the program is terminated. The matrix should be
|
|
||||||
freed with <A HREF="#free"><TT>mod2sparse_free</TT></A> once it is no
|
|
||||||
longer in use.
|
|
||||||
|
|
||||||
<P><A NAME="free"><HR><B>mod2sparse_free</B>:
|
|
||||||
Free the space occupied by a sparse module-2 matrix.</A>
|
|
||||||
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
void mod2sparse_free
|
|
||||||
( mod2sparse *m /* Pointer to matrix to free */
|
|
||||||
)
|
|
||||||
</PRE></BLOCKQUOTE>
|
|
||||||
|
|
||||||
Frees the space occupied by the matrix for re-use. The pointer passed
|
|
||||||
should not be used afterward. Note that space for the individual matrix
|
|
||||||
elements (but not the matrix as a whole) is also freed when <A
|
|
||||||
HREF="#clear"><TT>mod2sparse_clear</TT></A> is called, or the matrix
|
|
||||||
is used as the destination for other operations.
|
|
||||||
|
|
||||||
|
|
||||||
<A NAME="copy-clear-sec">
|
|
||||||
<P><HR>
|
|
||||||
<CENTER><BIG>Copying and Clearing Sparse Modulo-2 Matrices</BIG></CENTER>
|
|
||||||
</A>
|
|
||||||
|
|
||||||
<A NAME="clear"><HR><B>mod2sparse_clear</B>:
|
|
||||||
Set all elements of a matrix to zero.</A>
|
|
||||||
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
void mod2sparse_clear
|
|
||||||
( mod2sparse *m /* Pointer to matrix to clear */
|
|
||||||
)
|
|
||||||
</PRE></BLOCKQUOTE>
|
|
||||||
|
|
||||||
Sets all of the elements of the matrix passed to 0. The space occupied
|
|
||||||
by the previous non-zero elements is freed for use in other matrices, or
|
|
||||||
other purposes. The matrix itself is not freed, however. To do that,
|
|
||||||
use <A HREF="#free"><TT>mod2sparse_free</TT></A>.
|
|
||||||
|
|
||||||
|
|
||||||
<P><A NAME="copy"><HR><B>mod2sparse_copy</B>:
|
|
||||||
Copy the contents of one matrix to another.</A>
|
|
||||||
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
void mod2sparse_copy
|
|
||||||
( mod2sparse *m /* Pointer to matrix to copy from */
|
|
||||||
mod2sparse *r /* Pointer to matrix to receive data */
|
|
||||||
)
|
|
||||||
</PRE></BLOCKQUOTE>
|
|
||||||
|
|
||||||
Copies the contents of the first matrix passed, <B>m</B>, to the
|
|
||||||
second matrix passed, <B>r</B>, which must already have been
|
|
||||||
allocated, and must have at least as many rows and columns as the
|
|
||||||
first. If <B>r</B> is larger than <B>m</B>, its elements that have
|
|
||||||
row or column indexes greater than the dimension of <B>m</B> are set
|
|
||||||
to zeros.
|
|
||||||
|
|
||||||
<P>The space occupied by the previous non-zero entries of <B>r</B> is
|
|
||||||
freed for general use (which may include being reused immediately for
|
|
||||||
the copies of the entries in <B>m</B>).
|
|
||||||
|
|
||||||
|
|
||||||
<P><A NAME="copyrows"><HR><B>mod2sparse_copyrows</B>:
|
|
||||||
Copy selected rows from one matrix to another.</A>
|
|
||||||
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
void mod2sparse_copyrows
|
|
||||||
( mod2sparse *m, /* Pointer to matrix to copy rows from */
|
|
||||||
mod2sparse *r, /* Pointer to matrix in which to store data */
|
|
||||||
int *rows /* Indexes of rows, numbered from 0 */
|
|
||||||
)
|
|
||||||
</PRE></BLOCKQUOTE>
|
|
||||||
|
|
||||||
Copies selected rows of the first matrix, <B>m</B>, to the second
|
|
||||||
matrix, <B>r</B>, which must already have been allocated, and which
|
|
||||||
must have at least as many columns as <B>m</B>. The indexes of the
|
|
||||||
rows to copy are given in order as an array of length the same as
|
|
||||||
the number of rows in <B>r</B>; duplicates are allowed. Row
|
|
||||||
indexes start at 0. These rows are copied to <B>r</B>, with the
|
|
||||||
row indexed by the first entry in <B>rows</B> going to the
|
|
||||||
first row of <B>r</B>, and so forth. If <B>r</B> has more columns than
|
|
||||||
<B>m</B>, the extra entries in each row are set to zeros.
|
|
||||||
|
|
||||||
<P>The space occupied by the previous non-zero entries of <B>r</B> is
|
|
||||||
freed for general use (which may include being reused immediately for
|
|
||||||
the copies of the entries in <B>m</B>).
|
|
||||||
|
|
||||||
|
|
||||||
<P><A NAME="copycols"><HR><B>mod2sparse_copycols</B>:
|
|
||||||
Copy selected columns from one matrix to another.</A>
|
|
||||||
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
void mod2sparse_copycols
|
|
||||||
( mod2sparse *m, /* Pointer to matrix to copy columns from */
|
|
||||||
mod2sparse *r, /* Pointer to matrix in which to store data */
|
|
||||||
int *cols /* Indexes of columns, numbered from 0 */
|
|
||||||
)
|
|
||||||
</PRE></BLOCKQUOTE>
|
|
||||||
|
|
||||||
Copies selected columns of the first matrix, <B>m</B>, to the second
|
|
||||||
matrix, <B>r</B>, which must already have been allocated, and which
|
|
||||||
must have at least as many rows as <B>m</B>. The indexes of the
|
|
||||||
columns to copy are given in order as an array of length the same as
|
|
||||||
the number of columns in <B>r</B>; duplicates are allowed. Column
|
|
||||||
indexes start at 0. These columns are copied to <B>r</B>, with the
|
|
||||||
column indexed by the first entry in <B>cols</B> going to the
|
|
||||||
first column of <B>r</B>, and so forth. If <B>r</B> has more rows than
|
|
||||||
<B>m</B>, the extra entries in each column are set to zeros.
|
|
||||||
|
|
||||||
<P>The space occupied by the previous non-zero entries of <B>r</B> is
|
|
||||||
freed for general use (which may include being reused immediately for
|
|
||||||
the copies of the entries in <B>m</B>).
|
|
||||||
|
|
||||||
|
|
||||||
<A NAME="input-output-sec">
|
|
||||||
<P><HR>
|
|
||||||
<CENTER><BIG>Input and Output of Sparse Modulo-2 Matrices</BIG></CENTER>
|
|
||||||
</A>
|
|
||||||
|
|
||||||
<A NAME="print"><HR><B>mod2sparse_print</B>:
|
|
||||||
Print a sparse modulo-2 matrix in human-readable form.</A>
|
|
||||||
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
void mod2sparse_print
|
|
||||||
( FILE *f, /* File to print to */
|
|
||||||
mod2sparse *m /* Pointer to matrix to print */
|
|
||||||
)
|
|
||||||
</PRE></BLOCKQUOTE>
|
|
||||||
|
|
||||||
The matrix is printed on standard output with one line of output per row,
|
|
||||||
of the form
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
<I>row</I>: <I>col col col ...</I>
|
|
||||||
</PRE></BLOCKQUOTE>
|
|
||||||
where <I>row</I> is the index of the row, and the <I>col</I> entries are
|
|
||||||
the indexes of columns that are non-zero in that row. Row and column
|
|
||||||
indexes start at zero. Rows with no entries are printed with no column
|
|
||||||
indexes after the colon. The number of columns is not indicated in the output.
|
|
||||||
|
|
||||||
<P><A NAME="write"><HR><B>mod2sparse_write</B>:
|
|
||||||
Write a sparse modulo-2 matrix to a file in machine-readable format.</A>
|
|
||||||
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
int mod2sparse_write
|
|
||||||
( FILE *f, /* File to write data to */
|
|
||||||
mod2sparse *m /* Pointer to matrix write out */
|
|
||||||
)
|
|
||||||
</PRE></BLOCKQUOTE>
|
|
||||||
|
|
||||||
Writes a machine-readable representation the sparse matrix <B>m</B> to
|
|
||||||
the file <B>f</B>. The file should have been opened in binary mode
|
|
||||||
(with a "b" in the mode passed to fopen). The contents written will
|
|
||||||
not be text, and will not be human-readable. Other binary data may
|
|
||||||
precede or follow the data for the matrix written.
|
|
||||||
|
|
||||||
<P>The data written to the file starts with the number of rows and the
|
|
||||||
number of columns. Following this are negative integers giving row
|
|
||||||
indexes (starting at 1), which apply until the next row index, and
|
|
||||||
positive integers giving column indexes (starting at 1) for a non-zero
|
|
||||||
entry in the matrix. The data should be readable by <A
|
|
||||||
HREF="#read"><TT>mod2sparse_read</TT></A> even on a machine with a
|
|
||||||
different byte-ordering.
|
|
||||||
|
|
||||||
<P>The value returned by <TT>mod2sparse_write</TT> is one if the
|
|
||||||
operation was successful, zero if an error of some sort occurred.
|
|
||||||
|
|
||||||
<P><A NAME="read"><HR><B>mod2sparse_read</B>:
|
|
||||||
Read a sparse modulo-2 matrix from a file.</A>
|
|
||||||
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
mod2sparse *mod2sparse_read
|
|
||||||
( FILE *f, /* File to read data from */
|
|
||||||
)
|
|
||||||
</PRE></BLOCKQUOTE>
|
|
||||||
|
|
||||||
Reads a sparse modulo-2 matrix from the file <B>f</B>. This file
|
|
||||||
should have been opened in binary mode (with a "b" in the mode passed
|
|
||||||
to fopen). The contents of the file at the point when
|
|
||||||
<TT>mod2sparse_read</TT> is called should have been written by <A
|
|
||||||
HREF="#write"><TT>mod2sparse_write</TT></A>. Other binary data may
|
|
||||||
precede or follow this data.
|
|
||||||
|
|
||||||
<P>The value returned is a pointer to the matrix read, for which space
|
|
||||||
will have been allocated by <TT>mod2sparse_read</TT>, or zero if an
|
|
||||||
error occurred (either an error reading the file, or data not in the
|
|
||||||
right format).
|
|
||||||
|
|
||||||
|
|
||||||
<A NAME="elementary-sec">
|
|
||||||
<P><HR>
|
|
||||||
<CENTER><BIG>Elementary Operations on Sparse Modulo-2 Matrices</BIG></CENTER>
|
|
||||||
</A>
|
|
||||||
|
|
||||||
<A NAME="find"><HR><B>mod2sparse_find</B>:
|
|
||||||
Look for an entry at a given row and column.</A>
|
|
||||||
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
mod2entry *mod2sparse_find
|
|
||||||
( mod2sparse *m, /* Matrix in which to look for entry */
|
|
||||||
int row, /* Row index (from 0) */
|
|
||||||
int col /* Column index (from 0) */
|
|
||||||
)
|
|
||||||
</PRE></BLOCKQUOTE>
|
|
||||||
|
|
||||||
Looks for an entry at the given row and column in the matrix <B>m</B>,
|
|
||||||
representing a non-zero element (ie, one with value 1). Returns a
|
|
||||||
pointer to this entry if it exists, or zero (a null pointer) if it
|
|
||||||
does not exist (ie, if that element of the matrix has value 0).
|
|
||||||
|
|
||||||
<P>The search strategy is to first look at the end of the row and the
|
|
||||||
end of the column. The entry might be found at one of these two
|
|
||||||
places, or it might be determinable from these end entries that no
|
|
||||||
entry exists at the given row and column. Otherwise, searches are
|
|
||||||
done from the start of the row and the start of the column, in
|
|
||||||
parallel, until an entry with the given row and column are found, or
|
|
||||||
until it can be determined that such an entry does not exist.
|
|
||||||
Searching in parallel ensures that the operation will be fast if
|
|
||||||
either the row is sparse or the column is sparse.
|
|
||||||
|
|
||||||
<P><A NAME="insert"><HR><B>mod2sparse_insert</B>:
|
|
||||||
Insert an entry at a given row and column.</A>
|
|
||||||
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
mod2entry *mod2sparse_insert
|
|
||||||
( mod2sparse *m, /* Matrix in which to insert an entry */
|
|
||||||
int row, /* Row index (from 0) */
|
|
||||||
int col /* Column index (from 0) */
|
|
||||||
)
|
|
||||||
</PRE></BLOCKQUOTE>
|
|
||||||
|
|
||||||
Adds a new entry (representing an element with value 1) at the given
|
|
||||||
row and column position in the matrix <B>m</B>. If such an entry
|
|
||||||
already exists, nothing is done (this is not considered to be an
|
|
||||||
error). The new (or existing) entry is returned as the value of
|
|
||||||
this procedure.
|
|
||||||
|
|
||||||
<P>The search strategy is to first look at the end of the row for an
|
|
||||||
existing entry or for the place where the new entry belongs. If this
|
|
||||||
fails, the row is searched from the beginning. If an existing entry
|
|
||||||
is found, it is returned. Otherwise, a new entry is created, it is
|
|
||||||
inserted in its correct place in the row, and it is inserted in its
|
|
||||||
correct place in its column, once again by first looking at the end,
|
|
||||||
and then if required searching from the beginning.
|
|
||||||
|
|
||||||
<P>The effect of this strategy is that a sparse matrix can be efficiently
|
|
||||||
created by either adding entries in increasing order by row and column or in
|
|
||||||
decreasing order by row and column.
|
|
||||||
|
|
||||||
<P><A NAME="delete"><HR><B>mod2sparse_delete</B>:
|
|
||||||
Delete an entry from a sparse modulo-2 matrix.</A>
|
|
||||||
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
void mod2sparse_delete
|
|
||||||
( mod2sparse *m, /* Matrix in which to delete an entry */
|
|
||||||
mod2entry *e /* Entry to delete - MUST be in m */
|
|
||||||
)
|
|
||||||
</PRE></BLOCKQUOTE>
|
|
||||||
|
|
||||||
Deletes the entry <B>e</B> from the sparse matrix <B>m</B>, which
|
|
||||||
effectively sets to zero the element of the matrix that this entry
|
|
||||||
corresponded to. The entry is freed for future use in the same
|
|
||||||
matrix, but not (immediately, at least) for use in other matrices, or
|
|
||||||
generally. The pointer to this entry should not be used again once
|
|
||||||
it is deleted.
|
|
||||||
|
|
||||||
<P>The time required for this operation does not depend on how many
|
|
||||||
entries are currently in the matrix.
|
|
||||||
|
|
||||||
<P><B>Warning:</B> It is an error if <B>e</B> is not an entry of
|
|
||||||
<B>m</B>. This error is not currently diagnosed, but doing this may
|
|
||||||
cause serious problems, as it may lead later to entries for <B>m</B>
|
|
||||||
being erroneously freed when the matrix to which <B>e</B> properly
|
|
||||||
belongs is freed.
|
|
||||||
|
|
||||||
<A NAME="arith-sec">
|
|
||||||
<P><HR>
|
|
||||||
<CENTER><BIG>Sparse Modulo-2 Matrix Arithmetic and Comparison</BIG></CENTER>
|
|
||||||
</A>
|
|
||||||
|
|
||||||
<A NAME="transpose"><HR><B>mod2sparse_transpose</B>:
|
|
||||||
Compute the transpose of a sparse modulo-2 matrix.</A>
|
|
||||||
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
void mod2sparse_transpose
|
|
||||||
( mod2sparse *m, /* Matrix to compute transpose of */
|
|
||||||
mod2sparse *r /* Result of transpose operation */
|
|
||||||
)
|
|
||||||
</PRE></BLOCKQUOTE>
|
|
||||||
|
|
||||||
Stores the transpose of its first argument, <B>m</B>, in the matrix
|
|
||||||
pointed to by its second argument, <B>r</B>, which must already have
|
|
||||||
been allocated, and which must have as many rows as <B>m</B> has
|
|
||||||
columns, and as many columns as <B>m</B> has rows. The two matrices
|
|
||||||
<B>m</B> and <B>r</B> must not be the same (ie, the two pointers
|
|
||||||
passed must be different).
|
|
||||||
|
|
||||||
<P>The space occupied by the previous non-zero entries of <B>r</B> is
|
|
||||||
freed for general use.
|
|
||||||
|
|
||||||
<P><A NAME="add"><HR><B>mod2sparse_add</B>:
|
|
||||||
Add two sparse modulo-2 matrices.</A>
|
|
||||||
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
void mod2sparse_add
|
|
||||||
( mod2sparse *m1, /* Left operand of add */
|
|
||||||
mod2sparse *m2, /* Right operand of add */
|
|
||||||
mod2sparse *r /* Place to store result of add */
|
|
||||||
)
|
|
||||||
</PRE></BLOCKQUOTE>
|
|
||||||
|
|
||||||
Adds matrices <B>m1</B> and <B>m2</B>, storing the result in the
|
|
||||||
matrix pointed to by <B>r</B>. All three matrices must have the same
|
|
||||||
numbers of rows and columns. It is permissible for <B>r</B> to be the
|
|
||||||
same as <B>m1</B> and/or <B>m2</B>. Neither of the first two matrices is
|
|
||||||
changed by this procedure (unless they are the same as <B>r</B>).
|
|
||||||
|
|
||||||
<P>The space occupied by the previous non-zero entries of <B>r</B> is
|
|
||||||
freed for general use.
|
|
||||||
|
|
||||||
|
|
||||||
<P><A NAME="multiply"><HR><B>mod2sparse_multiply</B>:
|
|
||||||
Multiply two sparse modulo-2 matrices.</A>
|
|
||||||
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
void mod2sparse_multiply
|
|
||||||
( mod2sparse *m1, /* Left operand of multiply */
|
|
||||||
mod2sparse *m2, /* Right operand of multiply */
|
|
||||||
mod2sparse *r /* Place to store result of multiply */
|
|
||||||
)
|
|
||||||
</PRE></BLOCKQUOTE>
|
|
||||||
|
|
||||||
Does a matrix multiplication of <B>m1</B> by <B>m2</B>, and stores the
|
|
||||||
result in the matrix pointed to by <B>r</B>. The matrices must have
|
|
||||||
compatible numbers of rows and columns. Neither of the first two
|
|
||||||
matrices is changed by this procedure. The result matrix, <B>r</B>,
|
|
||||||
must not be the same as either <B>m1</B> or <B>m2</B>.
|
|
||||||
|
|
||||||
<P>The space occupied by the previous non-zero entries of <B>r</B> is
|
|
||||||
freed for general use.
|
|
||||||
|
|
||||||
<P><A NAME="mulvec"><HR><B>mod2sparse_mulvec</B>:
|
|
||||||
Multiply a vector by a sparse modulo-2 matrix.</A>
|
|
||||||
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
void mod2sparse_mulvec
|
|
||||||
( mod2sparse *m, /* Pointer to matrix to multiply by, M rows, N columns */
|
|
||||||
char *u, /* Pointer to unpacked vector to multiply, N long */
|
|
||||||
char *v /* Pointer to unpacked result vector, M long */
|
|
||||||
)
|
|
||||||
</PRE></BLOCKQUOTE>
|
|
||||||
|
|
||||||
Multiplies the vector <B>u</B> on the left by the sparse modulo-2
|
|
||||||
matrix <B>m</B>, storing the result in <B>v</B>. Both <B>u</B> and
|
|
||||||
<B>v</B> are modulo-2 vectors, but are stored unpacked, with one bit
|
|
||||||
per char. Any non-zero value in <B>u</B> is equivalent to '1'.
|
|
||||||
The vectors <B>u</B> and <B>v</B> must not overlap.
|
|
||||||
|
|
||||||
<P><A NAME="equal"><HR><B>mod2sparse_equal</B>:
|
|
||||||
Check whether two sparse modulo-2 matrices are equal.</A>
|
|
||||||
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
int mod2sparse_equal
|
|
||||||
( mod2sparse *m1, /* Pointers to the two matrices */
|
|
||||||
mod2sparse *m2 /* to compare */
|
|
||||||
)
|
|
||||||
</PRE></BLOCKQUOTE>
|
|
||||||
|
|
||||||
Returns one if every element of <B>m1</B> is equal to the
|
|
||||||
corresponding element of <B>m2</B>, and otherwise returns zero. The
|
|
||||||
two matrices must have the same number of rows and the same number of
|
|
||||||
columns.
|
|
||||||
|
|
||||||
|
|
||||||
<A NAME="row-col-ops-sec">
|
|
||||||
<P><HR>
|
|
||||||
<CENTER><BIG>Row/Column Operations on Sparse Modulo-2 Matrices</BIG>
|
|
||||||
</CENTER></A>
|
|
||||||
|
|
||||||
<A NAME="count_row"><HR><B>mod2sparse_count_row</B>:
|
|
||||||
Count the number of 1s in a row of a sparse matrix.</A>
|
|
||||||
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
int mod2sparse_count_row
|
|
||||||
( mod2sparse *m, /* Pointer to matrix */
|
|
||||||
int row /* Index of row to count (from 0) */
|
|
||||||
)
|
|
||||||
</PRE></BLOCKQUOTE>
|
|
||||||
|
|
||||||
Returns the number of 1s in the given row of the matrix, by counting
|
|
||||||
the number of entries in that row.
|
|
||||||
|
|
||||||
<P><A NAME="count_col"><HR><B>mod2sparse_count_col</B>:
|
|
||||||
Count the number of 1s in a column of a sparse matrix.</A>
|
|
||||||
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
int mod2sparse_count_col
|
|
||||||
( mod2sparse *m, /* Pointer to matrix */
|
|
||||||
int col /* Index of column to count (from 0) */
|
|
||||||
)
|
|
||||||
</PRE></BLOCKQUOTE>
|
|
||||||
|
|
||||||
Returns the number of 1s in the given column of the matrix, by counting
|
|
||||||
the number of entries in that column.
|
|
||||||
|
|
||||||
<P><A NAME="add_row"><HR><B>mod2sparse_add_row</B>:
|
|
||||||
Add a row to a row of a sparse matrix.</A>
|
|
||||||
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
void mod2sparse_add_row
|
|
||||||
( mod2sparse *m1, /* Matrix containing row to add to */
|
|
||||||
int row1, /* Index in this matrix of row to add to */
|
|
||||||
mod2sparse *m2, /* Matrix containing row to add from */
|
|
||||||
int row2 /* Index in this matrix of row to add from */
|
|
||||||
)
|
|
||||||
</PRE></BLOCKQUOTE>
|
|
||||||
|
|
||||||
Modifies the row with index <B>row1</B> in the matrix <B>m1</B> by
|
|
||||||
adding to that row the row with index <B>row2</B> in the matrix
|
|
||||||
<B>m2</B>. The matrix <B>m1</B> must have at least as many columns as
|
|
||||||
<B>m2</B>. This operation is performed by inserting entries into the
|
|
||||||
row of <B>m1</B> at positions where they exist in the row of <B>m2</B>
|
|
||||||
but not in the row of <B>m1</B>, and deleting entries in the row of
|
|
||||||
<B>m1</B> that exist in the same position in the row of <B>m2</B>.
|
|
||||||
The matrix <B>m2</B> is not modified.
|
|
||||||
|
|
||||||
<P><A NAME="add_col"><HR><B>mod2sparse_add_col</B>:
|
|
||||||
Add a column to a column of a sparse matrix.</A>
|
|
||||||
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
void mod2sparse_add_col
|
|
||||||
( mod2sparse *m1, /* Matrix containing column to add to */
|
|
||||||
int col1, /* Index in this matrix of col to add to */
|
|
||||||
mod2sparse *m2, /* Matrix containing column to add from */
|
|
||||||
int col2 /* Index in this matrix of column to add from */
|
|
||||||
)
|
|
||||||
</PRE></BLOCKQUOTE>
|
|
||||||
|
|
||||||
Modifies the column with index <B>col1</B> in the matrix <B>m1</B> by
|
|
||||||
adding to that column the column with index <B>col2</B> in the matrix
|
|
||||||
<B>m2</B>. The matrix <B>m1</B> must have at least as many rows as
|
|
||||||
<B>m2</B>. This operation is performed by inserting entries into the
|
|
||||||
column of <B>m1</B> at positions where they exist in the column of
|
|
||||||
<B>m2</B> but not in the column of <B>m1</B>, and deleting entries in
|
|
||||||
the column of <B>m1</B> that exist in the same position in the column
|
|
||||||
of <B>m2</B>. The matrix <B>m2</B> is not modified.
|
|
||||||
|
|
||||||
|
|
||||||
<A NAME="lu-decomp-sec">
|
|
||||||
<P><HR>
|
|
||||||
<CENTER><BIG>LU Decomposition of Sparse Modulo-2 Matrices</BIG></CENTER>
|
|
||||||
</A>
|
|
||||||
|
|
||||||
<A NAME="decomp"><HR><B>mod2sparse_decomp</B>:
|
|
||||||
Find an LU decomposition of a sparse modulo-2 (sub-)matrix.</A>
|
|
||||||
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
int mod2sparse_decomp
|
|
||||||
( mod2sparse *A, /* Matrix to find LU decomposition within, M by N */
|
|
||||||
int K, /* Size of sub-matrix to find LU decomposition of */
|
|
||||||
mod2sparse *L, /* Matrix in which L is stored, M by K */
|
|
||||||
mod2sparse *U, /* Matrix in which U is stored, K by N */
|
|
||||||
int *rows, /* Array where row indexes are stored, M long */
|
|
||||||
int *cols, /* Array where column indexes are stored, N long */
|
|
||||||
mod2sparse_strategy strategy, /* Strategy to follow in picking rows/columns */
|
|
||||||
int abandon_number, /* Number of columns to abandon at some point */
|
|
||||||
int abandon_when /* When to abandon these columns */
|
|
||||||
)
|
|
||||||
</PRE></BLOCKQUOTE>
|
|
||||||
|
|
||||||
<P>Takes as input a matrix, <B>A</B>, having <I>M</I> rows and
|
|
||||||
<I>N</I> columns, and an integer <I>K</I>. Finds an LU decomposition
|
|
||||||
of a <I>K</I> by <I>K</I> sub-matrix of <B>A</B>. The decomposition
|
|
||||||
is stored in the matrix <B>L</B>, with <I>M</I> rows and <I>K</I>
|
|
||||||
columns, and the matrix <B>U</B>, with <I>K</I> rows and <I>N</I>
|
|
||||||
columns. The product of <B>L</B> and <B>U</B> will be equal to the
|
|
||||||
<I>K</I> by <I>K</I> submatrix of <B>A</B> obtained by taking only
|
|
||||||
rows and columns that are given in the first <I>K</I> elements of the
|
|
||||||
<B>rows</B> and <B>cols</B> arrays, which are set by this procedure,
|
|
||||||
with this sub-matrix distributed over the original <I>M</I> rows and
|
|
||||||
<I>N</I> columns. Furthermore, the ordering of the row and column
|
|
||||||
indexes in these arrays will be set so that if the rows of <B>L</B>
|
|
||||||
and the columns of <B>U</B> were rearranged in this order, <B>L</B>
|
|
||||||
would be lower triangular, with zeros in rows past row <I>K</I>, and
|
|
||||||
<B>U</B> would be upper triangular, with zeros in columns past column
|
|
||||||
<I>K</I>. The <B>rows</B> array is <I>M</I> long, and the <B>cols</B>
|
|
||||||
array is <I>N</I> long. The elements in both arrays after the first
|
|
||||||
<I>K</I> contain the indexes of the rows and columns not selected to
|
|
||||||
be part of the sub-matrix of <B>A</B>, in arbitrary order.
|
|
||||||
|
|
||||||
<P>The rows and columns of <B>A</B> are selected in order to try to
|
|
||||||
make the LU decomposition as sparse as possible, using the strategy
|
|
||||||
identified by the <B>strategy</B>, <B>abandon_number</B>, and
|
|
||||||
<B>abandon_when</B> parameters. The possible strategies are
|
|
||||||
<TT>Mod2sparse_first</TT>, <TT>Mod2sparse_mincol</TT>, and
|
|
||||||
<TT>Mod2sparse_minprod</TT>. If <B>abandon_number</B> is greater than
|
|
||||||
zero, it is possible that the matrix will appear to have linearly
|
|
||||||
dependent rows when it actually does not. See the <A
|
|
||||||
HREF="sparse-LU.html">discussion of sparse LU decomposition
|
|
||||||
methods</A> for details about these strategies.
|
|
||||||
|
|
||||||
<P>If <B>A</B> is not of rank <I>K</I> or more, <B>L</B> will contain
|
|
||||||
some number less than <I>K</I> of non-zero columns, and <B>U</B> will
|
|
||||||
contain an equal number of non-zero rows. The entries in the
|
|
||||||
<B>rows</B> and <B>cols</B> arrays for the extra zero rows or columns
|
|
||||||
will be arbitrary (but valid). The number of extra zero columns is
|
|
||||||
returned as the value of this procedure (hence a return value of zero
|
|
||||||
indicates that a <I>K</I> by <I>K</I> sub-matrix of full rank was
|
|
||||||
found).
|
|
||||||
|
|
||||||
<P>The matrix <B>A</B> is not altered. The previous contents of
|
|
||||||
<B>L</B> and <B>U</B> are cleared.
|
|
||||||
|
|
||||||
<P><A NAME="forward_sub"><HR><B>mod2sparse_forward_sub</B>:
|
|
||||||
Solve a lower-triangular system by forward substitution.</A>
|
|
||||||
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
int mod2sparse_forward_sub
|
|
||||||
( mod2sparse *L, /* Matrix that is lower triangular after reordering */
|
|
||||||
int *rows, /* Array of indexes (from 0) of rows for new order */
|
|
||||||
char *x, /* Vector on right of equation, also reordered */
|
|
||||||
char *y /* Place to store solution */
|
|
||||||
)
|
|
||||||
</PRE></BLOCKQUOTE>
|
|
||||||
|
|
||||||
<P>Solves the system of equations <B>Ly</B>=<B>x</B> for <B>y</B> by
|
|
||||||
forward substitution, based on <B>L</B> being lower triangular after
|
|
||||||
its rows are reordered according to the given index array. The
|
|
||||||
vectors <B>x</B> and <B>y</B> are stored unpacked, one bit per
|
|
||||||
character. If <B>L</B> is <I>M</I> by <I>K</I>, then <B>x</B> should
|
|
||||||
be <I>M</I> long, but only the <I>K</I> bits indexed by <B>rows</B>
|
|
||||||
are looked at. The solution vector, <B>y</B>, must be <I>K</I> long.
|
|
||||||
Only <I>K</I> rows of <B>L</B> are used, as also determined by the
|
|
||||||
<I>K</I> indexes in the <B>rows</B> argument. If <B>rows</B> is null,
|
|
||||||
the first <I>K</I> rows of <B>L</B> and the first <I>K</I> elements of
|
|
||||||
<B>x</B> are used.
|
|
||||||
|
|
||||||
<P>If the matrix <B>L</B> does not have 1s on its diagonal (after row
|
|
||||||
rearrangement), there may be no solution, depending on what <B>x</B>
|
|
||||||
is. If no solution exists, this procedure returns zero, otherwise it
|
|
||||||
returns one. Any arbitrary bits in the solution are set to zero.
|
|
||||||
|
|
||||||
<P><A NAME="backward_sub"><HR><B>mod2sparse_backward_sub</B>:
|
|
||||||
Solve an upper-triangular system by backward substitution.</A>
|
|
||||||
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
int mod2sparse_backward_sub
|
|
||||||
( mod2sparse *U, /* Matrix that is upper triangular after reordering */
|
|
||||||
int *cols, /* Array of indexes (from 0) of columns for new order */
|
|
||||||
char *y, /* Vector on right of equation */
|
|
||||||
char *z /* Place to store solution, also reordered */
|
|
||||||
)
|
|
||||||
</PRE></BLOCKQUOTE>
|
|
||||||
|
|
||||||
<P>Solves <B>Uz</B>=<B>y</B> for <B>z</B> by backward substitution,
|
|
||||||
based on <B>U</B> being upper triangular after its columns are
|
|
||||||
reordered according to the given index array. The vectors <B>y</B>
|
|
||||||
and <B>z</B> are stored unpacked, one bit per character. If <B>U</B>
|
|
||||||
is <I>K</I> by <I>N</I>, then the solution vector, <I>z</I>, should be
|
|
||||||
<I>N</I> long, but only the <I>K</I> bits indexed by <B>cols</B> are
|
|
||||||
set. The vector <B>y</B> must be <I>K</I> long. Only <I>K</I> columns
|
|
||||||
of <B>U</B> are used, as also determined by the <I>K</I> indexes in
|
|
||||||
the <B>cols</B> argument. The other columns of <B>U</B> must be zero
|
|
||||||
(this is not checked, but is necessary for the method used to work).
|
|
||||||
If <B>cols</B> is null, the first <I>K</I> columns of <B>U</B> and the
|
|
||||||
first <I>K</I> elements of <B>z</B> are used.
|
|
||||||
|
|
||||||
<P>If the matrix <B>U</B> does not have 1s on its diagonal (after
|
|
||||||
column rearrangement) there may be no solution, depending on what y
|
|
||||||
is. If no solution exists, this procedure returns zero, otherwise it
|
|
||||||
returns one. Any arbitrary bits in the solution are set to zero.
|
|
||||||
|
|
||||||
<HR>
|
|
||||||
|
|
||||||
<A HREF="index.html">Back to index for LDPC software</A>
|
|
||||||
|
|
||||||
</BODY></HTML>
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
2
|
|
||||||
3 4
|
|
||||||
.9 .1
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
# GCC Makefile for: PEG-ECC by Xiao-Yu Hu.
|
|
||||||
# http://www.inference.phy.cam.ac.uk/mackay/PEG_ECC.html
|
|
||||||
#
|
|
||||||
# Tested with on Linux 2.4 and 2.6 (i686) with
|
|
||||||
# GCC versions 3.2.2, 3.3.5 and GNU Make version 3.80.
|
|
||||||
#
|
|
||||||
# Simeon Miteff <simeon@up.ac.za>
|
|
||||||
# Thu May 12 12:38:41 SAST 2005
|
|
||||||
|
|
||||||
PROGRAM = MainPEG
|
|
||||||
OBJECTS = MainPEG.o Random.o CyclesOfGraph.o BigGirth.o
|
|
||||||
|
|
||||||
CXX = g++
|
|
||||||
CXXFLAGS = -g -ansi -pedantic -Wno-deprecated -Wall -O2
|
|
||||||
#CXXFLAGS = -g -ansi -pedantic -Wall -march=native -ftree-vectorize -O3
|
|
||||||
|
|
||||||
.SUFFIXES: .o .C
|
|
||||||
|
|
||||||
all: ${OBJECTS}
|
|
||||||
$(CXX) -o ${PROGRAM} ${OBJECTS}
|
|
||||||
|
|
||||||
.C.o: $<
|
|
||||||
$(CXX) ${CXXFLAGS} -c $< -o $@
|
|
||||||
|
|
||||||
.PHONY : clean
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -f ${OBJECTS} ${PROGRAM} *~ *.log
|
|
||||||
|
|
||||||
@@ -0,0 +1,125 @@
|
|||||||
|
subroutine symspec(shared_data,k,ntrperiod,nsps,ingain,nminw,pxdb,s, &
|
||||||
|
df3,ihsym,npts8,pxdbmax)
|
||||||
|
|
||||||
|
! Input:
|
||||||
|
! k pointer to the most recent new data
|
||||||
|
! ntrperiod T/R sequence length, minutes
|
||||||
|
! nsps samples per symbol, at 12000 Hz
|
||||||
|
! ndiskdat 0/1 to indicate if data from disk
|
||||||
|
! nb 0/1 status of noise blanker (off/on)
|
||||||
|
! nbslider NB setting, 0-100
|
||||||
|
|
||||||
|
! Output:
|
||||||
|
! pxdb raw power (0-90 dB)
|
||||||
|
! s() current spectrum for waterfall display
|
||||||
|
! ihsym index number of this half-symbol (1-184) for 60 s modes
|
||||||
|
|
||||||
|
! jt9com
|
||||||
|
! ss() JT9 symbol spectra at half-symbol steps
|
||||||
|
! savg() average spectra for waterfall display
|
||||||
|
|
||||||
|
use, intrinsic :: iso_c_binding, only: c_int, c_short, c_float, c_char
|
||||||
|
include 'jt9com.f90'
|
||||||
|
|
||||||
|
type(dec_data) :: shared_data
|
||||||
|
real*4 w3(MAXFFT3)
|
||||||
|
real*4 s(NSMAX)
|
||||||
|
real*4 ssum(NSMAX)
|
||||||
|
real*4 xc(0:MAXFFT3-1)
|
||||||
|
real*4 tmp(NSMAX)
|
||||||
|
complex cx(0:MAXFFT3/2)
|
||||||
|
integer nch(7)
|
||||||
|
|
||||||
|
common/spectra/syellow(NSMAX),ref(0:3456),filter(0:3456)
|
||||||
|
data k0/99999999/,nfft3z/0/
|
||||||
|
data nch/1,2,4,9,18,36,72/
|
||||||
|
equivalence (xc,cx)
|
||||||
|
save
|
||||||
|
|
||||||
|
if(ntrperiod.eq.-999) stop !Silence compiler warning
|
||||||
|
nfft3=16384 !df=12000.0/16384 = 0.732422
|
||||||
|
jstep=nsps/2 !Step size = half-symbol in id2()
|
||||||
|
if(k.gt.NMAX) go to 900
|
||||||
|
if(k.lt.2048) then !(2048 was nfft3) (Any need for this ???)
|
||||||
|
ihsym=0
|
||||||
|
go to 900 !Wait for enough samples to start
|
||||||
|
endif
|
||||||
|
|
||||||
|
if(nfft3.ne.nfft3z) then
|
||||||
|
! Compute new window
|
||||||
|
pi=4.0*atan(1.0)
|
||||||
|
width=0.25*nsps
|
||||||
|
do i=1,nfft3
|
||||||
|
z=(i-nfft3/2)/width
|
||||||
|
w3(i)=exp(-z*z)
|
||||||
|
enddo
|
||||||
|
nfft3z=nfft3
|
||||||
|
endif
|
||||||
|
|
||||||
|
if(k.lt.k0) then !Start a new data block
|
||||||
|
ja=0
|
||||||
|
ssum=0.
|
||||||
|
ihsym=0
|
||||||
|
if(.not. shared_data%params%ndiskdat) shared_data%id2(k+1:)=0 !Needed to prevent "ghosts". Not sure why.
|
||||||
|
endif
|
||||||
|
gain=10.0**(0.1*ingain)
|
||||||
|
sq=0.
|
||||||
|
pxmax=0.;
|
||||||
|
do i=k0+1,k
|
||||||
|
x1=shared_data%id2(i)
|
||||||
|
if (abs(x1).gt.pxmax) pxmax = abs(x1);
|
||||||
|
sq=sq + x1*x1
|
||||||
|
enddo
|
||||||
|
pxdb = 0.
|
||||||
|
if(sq.gt.0.0) pxdb=10*log10(sq/(k-k0))
|
||||||
|
pxdbmax=0.
|
||||||
|
if(pxmax.gt.0) pxdbmax = 20*log10(pxmax)
|
||||||
|
|
||||||
|
k0=k
|
||||||
|
ja=ja+jstep !Index of first sample
|
||||||
|
|
||||||
|
fac0=0.1
|
||||||
|
do i=0,nfft3-1 !Copy data into cx
|
||||||
|
j=ja+i-(nfft3-1)
|
||||||
|
xc(i)=0.
|
||||||
|
if(j.ge.1 .and.j.le.NMAX) xc(i)=fac0*shared_data%id2(j)
|
||||||
|
enddo
|
||||||
|
ihsym=ihsym+1
|
||||||
|
|
||||||
|
! xc(0:nfft3-1)=w3(1:nfft3)*xc(0:nfft3-1) !Apply window w3
|
||||||
|
call four2a(xc,nfft3,1,-1,0) !Real-to-complex FFT
|
||||||
|
|
||||||
|
df3=12000.0/nfft3 !JT9-1: 0.732 Hz = 0.42 * tone spacing
|
||||||
|
iz=min(NSMAX,nint(5000.0/df3))
|
||||||
|
fac=(1.0/nfft3)**2
|
||||||
|
do i=1,iz
|
||||||
|
j=i-1
|
||||||
|
if(j.lt.0) j=j+nfft3
|
||||||
|
sx=fac*(real(cx(j))**2 + aimag(cx(j))**2)
|
||||||
|
if(ihsym.le.184) shared_data%ss(ihsym,i)=sx
|
||||||
|
ssum(i)=ssum(i) + sx
|
||||||
|
s(i)=1000.0*gain*sx
|
||||||
|
enddo
|
||||||
|
|
||||||
|
shared_data%savg=ssum/ihsym
|
||||||
|
|
||||||
|
if(mod(ihsym,10).eq.0) then
|
||||||
|
mode4=nch(nminw+1)
|
||||||
|
nsmo=min(10*mode4,150)
|
||||||
|
nsmo=4*nsmo
|
||||||
|
call flat1(shared_data%savg,iz,nsmo,syellow)
|
||||||
|
if(mode4.ge.2) call smo(syellow,iz,tmp,mode4)
|
||||||
|
if(mode4.ge.2) call smo(syellow,iz,tmp,mode4)
|
||||||
|
syellow(1:250)=0.
|
||||||
|
ia=500./df3
|
||||||
|
ib=2700.0/df3
|
||||||
|
smin=minval(syellow(ia:ib))
|
||||||
|
smax=maxval(syellow(1:iz))
|
||||||
|
syellow=(50.0/(smax-smin))*(syellow-smin)
|
||||||
|
where(syellow<0) syellow=0.
|
||||||
|
endif
|
||||||
|
|
||||||
|
900 npts8=k/8
|
||||||
|
|
||||||
|
return
|
||||||
|
end subroutine symspec
|
||||||
+6
-1
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QByteArray>
|
#include <QByteArray>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
#include "pimpl_impl.hpp"
|
#include "pimpl_impl.hpp"
|
||||||
|
|
||||||
@@ -88,10 +89,14 @@ namespace NetworkMessage
|
|||||||
*parent >> type >> id_;
|
*parent >> type >> id_;
|
||||||
if (type >= maximum_message_type_)
|
if (type >= maximum_message_type_)
|
||||||
{
|
{
|
||||||
throw std::runtime_error {"Unrecognized message type"};
|
qDebug () << "Unrecognized message type:" << type << "from id:" << id_;
|
||||||
|
type_ = maximum_message_type_;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
type_ = static_cast<Type> (type);
|
type_ = static_cast<Type> (type);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
quint32 schema_;
|
quint32 schema_;
|
||||||
Type type_;
|
Type type_;
|
||||||
@@ -1,431 +0,0 @@
|
|||||||
|
|
||||||
PART 1:
|
|
||||||
|
|
||||||
Matrix m1:
|
|
||||||
|
|
||||||
0: 0
|
|
||||||
1: 1
|
|
||||||
2: 2 3
|
|
||||||
3: 3
|
|
||||||
4: 4
|
|
||||||
5: 5
|
|
||||||
6: 6
|
|
||||||
7: 7
|
|
||||||
8: 8
|
|
||||||
9: 9
|
|
||||||
10: 10 38
|
|
||||||
11: 11
|
|
||||||
12: 12
|
|
||||||
13: 13
|
|
||||||
14: 14
|
|
||||||
15: 15
|
|
||||||
16: 16
|
|
||||||
17: 17
|
|
||||||
18: 18
|
|
||||||
19: 19
|
|
||||||
20: 20
|
|
||||||
21: 21
|
|
||||||
22: 22
|
|
||||||
23: 23
|
|
||||||
24: 24
|
|
||||||
25: 25
|
|
||||||
26: 26
|
|
||||||
27: 27
|
|
||||||
28: 28
|
|
||||||
29: 29
|
|
||||||
30: 30
|
|
||||||
31: 31
|
|
||||||
32: 32
|
|
||||||
33: 33
|
|
||||||
34: 4 34
|
|
||||||
|
|
||||||
Matrix m2, as read from file. Should be same as m1 above.
|
|
||||||
|
|
||||||
0: 0
|
|
||||||
1: 1
|
|
||||||
2: 2 3
|
|
||||||
3: 3
|
|
||||||
4: 4
|
|
||||||
5: 5
|
|
||||||
6: 6
|
|
||||||
7: 7
|
|
||||||
8: 8
|
|
||||||
9: 9
|
|
||||||
10: 10 38
|
|
||||||
11: 11
|
|
||||||
12: 12
|
|
||||||
13: 13
|
|
||||||
14: 14
|
|
||||||
15: 15
|
|
||||||
16: 16
|
|
||||||
17: 17
|
|
||||||
18: 18
|
|
||||||
19: 19
|
|
||||||
20: 20
|
|
||||||
21: 21
|
|
||||||
22: 22
|
|
||||||
23: 23
|
|
||||||
24: 24
|
|
||||||
25: 25
|
|
||||||
26: 26
|
|
||||||
27: 27
|
|
||||||
28: 28
|
|
||||||
29: 29
|
|
||||||
30: 30
|
|
||||||
31: 31
|
|
||||||
32: 32
|
|
||||||
33: 33
|
|
||||||
34: 4 34
|
|
||||||
|
|
||||||
Test of equality of m1 & m2 (should be 1): 1
|
|
||||||
|
|
||||||
Matrix m3, copied from m1 above.
|
|
||||||
|
|
||||||
0: 0
|
|
||||||
1: 1
|
|
||||||
2: 2 3
|
|
||||||
3: 3
|
|
||||||
4: 4
|
|
||||||
5: 5
|
|
||||||
6: 6
|
|
||||||
7: 7
|
|
||||||
8: 8
|
|
||||||
9: 9
|
|
||||||
10: 10 38
|
|
||||||
11: 11
|
|
||||||
12: 12
|
|
||||||
13: 13
|
|
||||||
14: 14
|
|
||||||
15: 15
|
|
||||||
16: 16
|
|
||||||
17: 17
|
|
||||||
18: 18
|
|
||||||
19: 19
|
|
||||||
20: 20
|
|
||||||
21: 21
|
|
||||||
22: 22
|
|
||||||
23: 23
|
|
||||||
24: 24
|
|
||||||
25: 25
|
|
||||||
26: 26
|
|
||||||
27: 27
|
|
||||||
28: 28
|
|
||||||
29: 29
|
|
||||||
30: 30
|
|
||||||
31: 31
|
|
||||||
32: 32
|
|
||||||
33: 33
|
|
||||||
34: 4 34
|
|
||||||
|
|
||||||
Test of equality of m1 & m3 (should be 1): 1
|
|
||||||
|
|
||||||
Matrix m3 again, should now be all zeros.
|
|
||||||
|
|
||||||
0:
|
|
||||||
1:
|
|
||||||
2:
|
|
||||||
3:
|
|
||||||
4:
|
|
||||||
5:
|
|
||||||
6:
|
|
||||||
7:
|
|
||||||
8:
|
|
||||||
9:
|
|
||||||
10:
|
|
||||||
11:
|
|
||||||
12:
|
|
||||||
13:
|
|
||||||
14:
|
|
||||||
15:
|
|
||||||
16:
|
|
||||||
17:
|
|
||||||
18:
|
|
||||||
19:
|
|
||||||
20:
|
|
||||||
21:
|
|
||||||
22:
|
|
||||||
23:
|
|
||||||
24:
|
|
||||||
25:
|
|
||||||
26:
|
|
||||||
27:
|
|
||||||
28:
|
|
||||||
29:
|
|
||||||
30:
|
|
||||||
31:
|
|
||||||
32:
|
|
||||||
33:
|
|
||||||
34:
|
|
||||||
|
|
||||||
Test of equality of m1 & m3 (should be 0): 0
|
|
||||||
|
|
||||||
|
|
||||||
PART 2:
|
|
||||||
|
|
||||||
Transpose of m1.
|
|
||||||
|
|
||||||
0: 0
|
|
||||||
1: 1
|
|
||||||
2: 2
|
|
||||||
3: 2 3
|
|
||||||
4: 4 34
|
|
||||||
5: 5
|
|
||||||
6: 6
|
|
||||||
7: 7
|
|
||||||
8: 8
|
|
||||||
9: 9
|
|
||||||
10: 10
|
|
||||||
11: 11
|
|
||||||
12: 12
|
|
||||||
13: 13
|
|
||||||
14: 14
|
|
||||||
15: 15
|
|
||||||
16: 16
|
|
||||||
17: 17
|
|
||||||
18: 18
|
|
||||||
19: 19
|
|
||||||
20: 20
|
|
||||||
21: 21
|
|
||||||
22: 22
|
|
||||||
23: 23
|
|
||||||
24: 24
|
|
||||||
25: 25
|
|
||||||
26: 26
|
|
||||||
27: 27
|
|
||||||
28: 28
|
|
||||||
29: 29
|
|
||||||
30: 30
|
|
||||||
31: 31
|
|
||||||
32: 32
|
|
||||||
33: 33
|
|
||||||
34: 34
|
|
||||||
35:
|
|
||||||
36:
|
|
||||||
37:
|
|
||||||
38: 10
|
|
||||||
39:
|
|
||||||
|
|
||||||
Matrix m1 after adding rows 2 and 12 and 3 to 10.
|
|
||||||
|
|
||||||
0: 0
|
|
||||||
1: 1
|
|
||||||
2: 2 3
|
|
||||||
3: 3
|
|
||||||
4: 4
|
|
||||||
5: 5
|
|
||||||
6: 6
|
|
||||||
7: 7
|
|
||||||
8: 8
|
|
||||||
9: 9
|
|
||||||
10: 2 10 12 38
|
|
||||||
11: 11
|
|
||||||
12: 12
|
|
||||||
13: 13
|
|
||||||
14: 14
|
|
||||||
15: 15
|
|
||||||
16: 16
|
|
||||||
17: 17
|
|
||||||
18: 18
|
|
||||||
19: 19
|
|
||||||
20: 20
|
|
||||||
21: 21
|
|
||||||
22: 22
|
|
||||||
23: 23
|
|
||||||
24: 24
|
|
||||||
25: 25
|
|
||||||
26: 26
|
|
||||||
27: 27
|
|
||||||
28: 28
|
|
||||||
29: 29
|
|
||||||
30: 30
|
|
||||||
31: 31
|
|
||||||
32: 32
|
|
||||||
33: 33
|
|
||||||
34: 4 34
|
|
||||||
|
|
||||||
Matrix m1 after further adding column 34 to 0.
|
|
||||||
|
|
||||||
0: 0
|
|
||||||
1: 1
|
|
||||||
2: 2 3
|
|
||||||
3: 3
|
|
||||||
4: 4
|
|
||||||
5: 5
|
|
||||||
6: 6
|
|
||||||
7: 7
|
|
||||||
8: 8
|
|
||||||
9: 9
|
|
||||||
10: 2 10 12 38
|
|
||||||
11: 11
|
|
||||||
12: 12
|
|
||||||
13: 13
|
|
||||||
14: 14
|
|
||||||
15: 15
|
|
||||||
16: 16
|
|
||||||
17: 17
|
|
||||||
18: 18
|
|
||||||
19: 19
|
|
||||||
20: 20
|
|
||||||
21: 21
|
|
||||||
22: 22
|
|
||||||
23: 23
|
|
||||||
24: 24
|
|
||||||
25: 25
|
|
||||||
26: 26
|
|
||||||
27: 27
|
|
||||||
28: 28
|
|
||||||
29: 29
|
|
||||||
30: 30
|
|
||||||
31: 31
|
|
||||||
32: 32
|
|
||||||
33: 33
|
|
||||||
34: 0 4 34
|
|
||||||
|
|
||||||
|
|
||||||
PART 3:
|
|
||||||
|
|
||||||
Matrix s0.
|
|
||||||
|
|
||||||
0:
|
|
||||||
1: 3 4
|
|
||||||
2: 0
|
|
||||||
3: 1
|
|
||||||
4:
|
|
||||||
|
|
||||||
Matrix s1.
|
|
||||||
|
|
||||||
0:
|
|
||||||
1: 3 5
|
|
||||||
2:
|
|
||||||
3: 0 1 6
|
|
||||||
4:
|
|
||||||
|
|
||||||
Matrix s2.
|
|
||||||
|
|
||||||
0: 0
|
|
||||||
1: 1
|
|
||||||
2:
|
|
||||||
3:
|
|
||||||
4:
|
|
||||||
5: 1 2 3
|
|
||||||
6:
|
|
||||||
|
|
||||||
Maxtrix s1 times unpacked vector ( 1 0 0 1 0 1 0 ).
|
|
||||||
|
|
||||||
( 0 0 0 1 0 )
|
|
||||||
|
|
||||||
Sum of s0 and s1.
|
|
||||||
|
|
||||||
0:
|
|
||||||
1: 4 5
|
|
||||||
2: 0
|
|
||||||
3: 0 6
|
|
||||||
4:
|
|
||||||
|
|
||||||
Product of s1 and s2.
|
|
||||||
|
|
||||||
0:
|
|
||||||
1: 1 2 3
|
|
||||||
2:
|
|
||||||
3: 0 1
|
|
||||||
4:
|
|
||||||
|
|
||||||
Tried to find (1,2), actually found: (1,2)
|
|
||||||
|
|
||||||
Above matrix with (1,2) cleared.
|
|
||||||
|
|
||||||
0:
|
|
||||||
1: 1 3
|
|
||||||
2:
|
|
||||||
3: 0 1
|
|
||||||
4:
|
|
||||||
|
|
||||||
Tried to find (1,1), actually found: (1,1)
|
|
||||||
|
|
||||||
Matrix with (1,1) cleared as well.
|
|
||||||
|
|
||||||
0:
|
|
||||||
1: 3
|
|
||||||
2:
|
|
||||||
3: 0 1
|
|
||||||
4:
|
|
||||||
|
|
||||||
|
|
||||||
PART 4:
|
|
||||||
|
|
||||||
Matrix s1.
|
|
||||||
|
|
||||||
0: 3 5
|
|
||||||
1: 1 6
|
|
||||||
2: 0
|
|
||||||
3: 1 2
|
|
||||||
4: 0 2
|
|
||||||
5: 6
|
|
||||||
|
|
||||||
LU decomposition (returned value was 0).
|
|
||||||
|
|
||||||
L=
|
|
||||||
0: 3
|
|
||||||
1: 1
|
|
||||||
2: 0
|
|
||||||
3: 1 2
|
|
||||||
4: 0 2 4
|
|
||||||
5:
|
|
||||||
|
|
||||||
U=
|
|
||||||
0: 0
|
|
||||||
1: 1 6
|
|
||||||
2: 2 6
|
|
||||||
3: 3
|
|
||||||
4: 6
|
|
||||||
|
|
||||||
cols: 0 1 2 3 6 5 4
|
|
||||||
rows: 2 1 3 0 4 5
|
|
||||||
|
|
||||||
Product of L and U.
|
|
||||||
|
|
||||||
0: 3
|
|
||||||
1: 1 6
|
|
||||||
2: 0
|
|
||||||
3: 1 2
|
|
||||||
4: 0 2
|
|
||||||
5:
|
|
||||||
|
|
||||||
Solution of Ly=x with x from ( 0 1 1 0 1 0 ) according to rows selected.
|
|
||||||
|
|
||||||
1 1 1 0 1
|
|
||||||
|
|
||||||
Returned value from forward_sub was 1
|
|
||||||
|
|
||||||
Solution of Uz=y.
|
|
||||||
|
|
||||||
1 0 0 0 0 0 1
|
|
||||||
|
|
||||||
Returned value from backward_sub was 1
|
|
||||||
|
|
||||||
|
|
||||||
PART 5:
|
|
||||||
|
|
||||||
Matrix m1:
|
|
||||||
|
|
||||||
0: 3
|
|
||||||
1: 1
|
|
||||||
2: 2
|
|
||||||
3: 0
|
|
||||||
|
|
||||||
Matrix m2, copyrows of m1 in order 3,1,2,0 (should be identity)
|
|
||||||
|
|
||||||
0: 0
|
|
||||||
1: 1
|
|
||||||
2: 2
|
|
||||||
3: 3
|
|
||||||
|
|
||||||
Matrix m3, copycols of m1 in order 3,1,2,0 (should be identity)
|
|
||||||
|
|
||||||
0: 0
|
|
||||||
1: 1
|
|
||||||
2: 2
|
|
||||||
3: 3
|
|
||||||
|
|
||||||
|
|
||||||
DONE WITH TESTS.
|
|
||||||
@@ -1,80 +0,0 @@
|
|||||||
/* MOD2CONVERT-TEST. C - Program to test mod2convert module. */
|
|
||||||
|
|
||||||
/* Copyright (c) 1995-2012 by Radford M. Neal.
|
|
||||||
*
|
|
||||||
* Permission is granted for anyone to copy, use, modify, and distribute
|
|
||||||
* these programs and accompanying documents for any purpose, provided
|
|
||||||
* this copyright notice is retained and prominently displayed, and note
|
|
||||||
* is made of any changes made to these programs. These programs and
|
|
||||||
* documents are distributed without any warranty, express or implied.
|
|
||||||
* As the programs were written for research purposes only, they have not
|
|
||||||
* been tested to the degree that would be advisable in any important
|
|
||||||
* application. All use of these programs is entirely at the user's own
|
|
||||||
* risk.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/* Correct output for this program is saved in the file mod2convert-test-out */
|
|
||||||
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <math.h>
|
|
||||||
|
|
||||||
#include "mod2dense.h"
|
|
||||||
#include "mod2sparse.h"
|
|
||||||
#include "mod2convert.h"
|
|
||||||
#include "rand.h"
|
|
||||||
|
|
||||||
#define Rows 40 /* Dimensions of matrix to use in test */
|
|
||||||
#define Cols 13
|
|
||||||
|
|
||||||
#define N 100 /* Number of bits to set in test matrix (some may be
|
|
||||||
duplicates, leading to fewer 1's in matrix */
|
|
||||||
|
|
||||||
main(void)
|
|
||||||
{
|
|
||||||
mod2sparse *sm1, *sm2;
|
|
||||||
mod2dense *dm1, *dm2;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
sm1 = mod2sparse_allocate(Rows,Cols);
|
|
||||||
sm2 = mod2sparse_allocate(Rows,Cols);
|
|
||||||
|
|
||||||
dm1 = mod2dense_allocate(Rows,Cols);
|
|
||||||
dm2 = mod2dense_allocate(Rows,Cols);
|
|
||||||
|
|
||||||
printf("\nCreating sparse matrix.\n");
|
|
||||||
fflush(stdout);
|
|
||||||
|
|
||||||
for (i = 0; i<N; i++)
|
|
||||||
{ mod2sparse_insert(sm1,rand_int(Rows),rand_int(Cols));
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("Converting from sparse to dense.\n");
|
|
||||||
fflush(stdout);
|
|
||||||
|
|
||||||
mod2sparse_to_dense(sm1,dm1);
|
|
||||||
|
|
||||||
printf("Converting back to dense again.\n");
|
|
||||||
fflush(stdout);
|
|
||||||
|
|
||||||
mod2dense_to_sparse(dm1,sm2);
|
|
||||||
|
|
||||||
printf("Testing for equality of two sparse matrices: %s.\n",
|
|
||||||
mod2sparse_equal(sm1,sm2) ? "OK" : "NOT OK");
|
|
||||||
fflush(stdout);
|
|
||||||
|
|
||||||
printf("Converting to dense once again.\n");
|
|
||||||
fflush(stdout);
|
|
||||||
|
|
||||||
mod2sparse_to_dense(sm2,dm2);
|
|
||||||
|
|
||||||
printf("Testing for equality of two dense matrices: %s.\n",
|
|
||||||
mod2dense_equal(dm1,dm2) ? "OK" : "NOT OK");
|
|
||||||
fflush(stdout);
|
|
||||||
|
|
||||||
printf("\nDONE WITH TESTS.\n");
|
|
||||||
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
/* CHANNEL.H - Declarations regarding channels. */
|
|
||||||
|
|
||||||
/* Copyright (c) 1995-2012 by Radford M. Neal.
|
|
||||||
*
|
|
||||||
* Permission is granted for anyone to copy, use, modify, and distribute
|
|
||||||
* these programs and accompanying documents for any purpose, provided
|
|
||||||
* this copyright notice is retained and prominently displayed, and note
|
|
||||||
* is made of any changes made to these programs. These programs and
|
|
||||||
* documents are distributed without any warranty, express or implied.
|
|
||||||
* As the programs were written for research purposes only, they have not
|
|
||||||
* been tested to the degree that would be advisable in any important
|
|
||||||
* application. All use of these programs is entirely at the user's own
|
|
||||||
* risk.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/* TYPES OF CHANNEL, AND CHANNEL PARAMETERS. The global variables declared
|
|
||||||
here are located in channel.c. */
|
|
||||||
|
|
||||||
typedef enum { BSC, AWGN, AWLN } channel_type;
|
|
||||||
|
|
||||||
extern channel_type channel; /* Type of channel */
|
|
||||||
|
|
||||||
extern double error_prob; /* Error probability for BSC */
|
|
||||||
extern double std_dev; /* Noise standard deviation for AWGN */
|
|
||||||
extern double lwidth; /* Width of noise distributoin for AWLN */
|
|
||||||
|
|
||||||
|
|
||||||
/* PROCEDURES TO DO WITH CHANNELS. */
|
|
||||||
|
|
||||||
int channel_parse (char **, int);
|
|
||||||
void channel_usage (void);
|
|
||||||
@@ -1,254 +0,0 @@
|
|||||||
/* VERIFY.C - Verify encoded or decoded blocks. */
|
|
||||||
|
|
||||||
/* Copyright (c) 1995-2012 by Radford M. Neal.
|
|
||||||
*
|
|
||||||
* Permission is granted for anyone to copy, use, modify, and distribute
|
|
||||||
* these programs and accompanying documents for any purpose, provided
|
|
||||||
* this copyright notice is retained and prominently displayed, and note
|
|
||||||
* is made of any changes made to these programs. These programs and
|
|
||||||
* documents are distributed without any warranty, express or implied.
|
|
||||||
* As the programs were written for research purposes only, they have not
|
|
||||||
* been tested to the degree that would be advisable in any important
|
|
||||||
* application. All use of these programs is entirely at the user's own
|
|
||||||
* risk.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <math.h>
|
|
||||||
|
|
||||||
#include "alloc.h"
|
|
||||||
#include "blockio.h"
|
|
||||||
#include "open.h"
|
|
||||||
#include "mod2sparse.h"
|
|
||||||
#include "mod2dense.h"
|
|
||||||
#include "mod2convert.h"
|
|
||||||
#include "rcode.h"
|
|
||||||
#include "check.h"
|
|
||||||
|
|
||||||
void usage(void);
|
|
||||||
|
|
||||||
|
|
||||||
/* MAIN PROGRAM. */
|
|
||||||
|
|
||||||
int main
|
|
||||||
( int argc,
|
|
||||||
char **argv
|
|
||||||
)
|
|
||||||
{
|
|
||||||
char *coded_file, *source_file;
|
|
||||||
char *pchk_file, *gen_file;
|
|
||||||
int table;
|
|
||||||
|
|
||||||
char *sblk, *cblk, *chks;
|
|
||||||
int seof, ceof;
|
|
||||||
int srcerr, chkerr, bit_errs;
|
|
||||||
int i, n;
|
|
||||||
FILE *srcf, *codef;
|
|
||||||
|
|
||||||
int tot_srcerrs, tot_chkerrs, tot_botherrs, tot_undeterrs, tot_good;
|
|
||||||
|
|
||||||
/* Look at arguments. */
|
|
||||||
|
|
||||||
table = 0;
|
|
||||||
if (argc>1 && strcmp(argv[1],"-t")==0)
|
|
||||||
{ table = 1;
|
|
||||||
argc -= 1;
|
|
||||||
argv += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (argc<3 || argc>5) usage();
|
|
||||||
|
|
||||||
if (!(pchk_file = argv[1])
|
|
||||||
|| !(coded_file = argv[2]))
|
|
||||||
{ usage();
|
|
||||||
}
|
|
||||||
|
|
||||||
gen_file = 0;
|
|
||||||
source_file = 0;
|
|
||||||
|
|
||||||
if (argv[3])
|
|
||||||
{ gen_file = argv[3];
|
|
||||||
if (argv[4])
|
|
||||||
{ source_file = argv[4];
|
|
||||||
if (argv[5])
|
|
||||||
{ usage();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((strcmp(pchk_file,"-")==0)
|
|
||||||
+ (strcmp(coded_file,"-")==0)
|
|
||||||
+ (source_file!=0 && strcmp(source_file,"-")==0)
|
|
||||||
+ (gen_file!=0 && strcmp(gen_file,"-")==0) > 1)
|
|
||||||
{ fprintf(stderr,"Can't read more than one stream from standard input\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read parity check file. */
|
|
||||||
|
|
||||||
read_pchk(pchk_file);
|
|
||||||
|
|
||||||
if (N<=M)
|
|
||||||
{ fprintf(stderr,
|
|
||||||
"Number of bits (%d) should be greater than number of checks (%d)\n",N,M);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read generator matrix file, if given, up to the point of finding
|
|
||||||
out which are the message bits. */
|
|
||||||
|
|
||||||
if (gen_file!=0)
|
|
||||||
{ read_gen(gen_file,1,0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Open coded file to check. */
|
|
||||||
|
|
||||||
codef = open_file_std(coded_file,"r");
|
|
||||||
if (codef==NULL)
|
|
||||||
{ fprintf(stderr,"Can't open coded file: %s\n",coded_file);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Open source file to verify against, if given. */
|
|
||||||
|
|
||||||
if (source_file!=0)
|
|
||||||
{
|
|
||||||
srcf = open_file_std(source_file,"r");
|
|
||||||
if (srcf==NULL)
|
|
||||||
{ fprintf(stderr,"Can't open source file: %s\n",source_file);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sblk = chk_alloc (N-M, sizeof *sblk);
|
|
||||||
cblk = chk_alloc (N, sizeof *cblk);
|
|
||||||
chks = chk_alloc (M, sizeof *chks);
|
|
||||||
|
|
||||||
/* Print header for table. */
|
|
||||||
|
|
||||||
if (table)
|
|
||||||
{ if (gen_file!=0)
|
|
||||||
{ printf(" block chkerrs srcerrs\n");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ printf(" block chkerrs\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Verify successive blocks. */
|
|
||||||
|
|
||||||
tot_srcerrs = 0;
|
|
||||||
tot_chkerrs = 0;
|
|
||||||
tot_botherrs = 0;
|
|
||||||
tot_undeterrs = 0;
|
|
||||||
tot_good = 0;
|
|
||||||
|
|
||||||
bit_errs = 0;
|
|
||||||
|
|
||||||
seof = 0;
|
|
||||||
ceof = 0;
|
|
||||||
|
|
||||||
for (n = 0; ; n++)
|
|
||||||
{
|
|
||||||
/* Read block from coded file. */
|
|
||||||
|
|
||||||
if (blockio_read(codef,cblk,N)==EOF)
|
|
||||||
{ ceof = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read block from source file, if given. */
|
|
||||||
|
|
||||||
if (source_file!=0 && !ceof && !seof)
|
|
||||||
{ if (blockio_read(srcf,sblk,N-M)==EOF)
|
|
||||||
{ fprintf(stderr,"Warning: Not enough source blocks (only %d)\n",n);
|
|
||||||
seof = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Stop if end of received file. */
|
|
||||||
|
|
||||||
if (ceof) break;
|
|
||||||
|
|
||||||
/* Check that received block is a code word, and if not find the number of
|
|
||||||
parity check errors. */
|
|
||||||
|
|
||||||
chkerr = check(H,cblk,chks);
|
|
||||||
|
|
||||||
/* Check against source block, if provided, or against zeros, if
|
|
||||||
the generator matrix was provided but no source file. */
|
|
||||||
|
|
||||||
if (gen_file!=0)
|
|
||||||
{ srcerr = 0;
|
|
||||||
if (source_file!=0 && !seof)
|
|
||||||
{ for (i = M; i<N; i++)
|
|
||||||
{ if (cblk[cols[i]]!=sblk[i-M])
|
|
||||||
{ srcerr += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (source_file==0)
|
|
||||||
{ for (i = M; i<N; i++)
|
|
||||||
{ if (cblk[cols[i]]!=0)
|
|
||||||
{ srcerr += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bit_errs += srcerr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Print table entry. */
|
|
||||||
|
|
||||||
if (table)
|
|
||||||
{ if (gen_file!=0)
|
|
||||||
{ printf("%6d %7d %7d\n",n,chkerr,srcerr);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ printf("%6d %7d\n",n,chkerr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Increment totals. */
|
|
||||||
|
|
||||||
if (chkerr) tot_chkerrs += 1;
|
|
||||||
if (gen_file!=0 && (source_file==0 || !seof))
|
|
||||||
{ if (srcerr) tot_srcerrs += 1;
|
|
||||||
if (srcerr && chkerr) tot_botherrs += 1;
|
|
||||||
if (srcerr && (chkerr==0) ) tot_undeterrs += 1;
|
|
||||||
if ((srcerr==0) && (chkerr==0) ) tot_good += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Write final statistics to standard error. Flush standard output
|
|
||||||
first to avoid mixing of output. */
|
|
||||||
|
|
||||||
fflush(stdout);
|
|
||||||
|
|
||||||
if (gen_file!=0)
|
|
||||||
{ fprintf(stderr,
|
|
||||||
"Block counts: tot %d, with chk errs %d, with src errs %d, both %d\n",
|
|
||||||
n, tot_chkerrs, tot_srcerrs, tot_botherrs, tot_undeterrs);
|
|
||||||
fprintf(stderr,
|
|
||||||
"Total good frames: %d Total undetected errors: %d\n",
|
|
||||||
tot_good, tot_undeterrs);
|
|
||||||
fprintf(stderr,
|
|
||||||
"Bit error rate (on message bits only): %.3e\n",
|
|
||||||
(double)bit_errs/(n*(N-M)));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ fprintf (stderr,
|
|
||||||
"Block counts: tot %d, with chk errs %d\n", n, tot_chkerrs);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* PRINT USAGE MESSAGE AND EXIT. */
|
|
||||||
|
|
||||||
void usage(void)
|
|
||||||
{ fprintf(stderr,
|
|
||||||
"Usage: verify [ -t ] pchk-file decoded-file [ gen-file [ source-file ] ]\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,480 @@
|
|||||||
|
subroutine ft8b(dd0,newdat,nQSOProgress,nfqso,nftx,ndepth,lapon,lapcqonly, &
|
||||||
|
napwid,lsubtract,nagain,iaptype,mycall12,mygrid6,hiscall12,bcontest, &
|
||||||
|
sync0,f1,xdt,xbase,apsym,nharderrors,dmin,nbadcrc,ipass,iera,msg37,xsnr)
|
||||||
|
|
||||||
|
use crc
|
||||||
|
use timer_module, only: timer
|
||||||
|
include 'ft8_params.f90'
|
||||||
|
parameter(NP2=2812)
|
||||||
|
character*37 msg37
|
||||||
|
character message*22,msgsent*22
|
||||||
|
character*12 mycall12,hiscall12
|
||||||
|
character*6 mycall6,mygrid6,hiscall6,c1,c2
|
||||||
|
character*87 cbits
|
||||||
|
logical bcontest
|
||||||
|
real a(5)
|
||||||
|
real s1(0:7,ND),s2(0:7,NN),s1sort(8*ND)
|
||||||
|
real ps(0:7),psl(0:7)
|
||||||
|
real bmeta(3*ND),bmetb(3*ND),bmetap(3*ND)
|
||||||
|
real llr(3*ND),llra(3*ND),llr0(3*ND),llr1(3*ND),llrap(3*ND) !Soft symbols
|
||||||
|
real dd0(15*12000)
|
||||||
|
integer*1 decoded(KK),decoded0(KK),apmask(3*ND),cw(3*ND)
|
||||||
|
integer*1 msgbits(KK)
|
||||||
|
integer apsym(KK)
|
||||||
|
integer mcq(28),mde(28),mrrr(16),m73(16),mrr73(16)
|
||||||
|
integer itone(NN)
|
||||||
|
integer indxs1(8*ND)
|
||||||
|
integer icos7(0:6),ip(1)
|
||||||
|
integer nappasses(0:5) !Number of decoding passes to use for each QSO state
|
||||||
|
integer naptypes(0:5,4) ! (nQSOProgress, decoding pass) maximum of 4 passes for now
|
||||||
|
integer*1, target:: i1hiscall(12)
|
||||||
|
complex cd0(3200)
|
||||||
|
complex ctwk(32)
|
||||||
|
complex csymb(32)
|
||||||
|
logical first,newdat,lsubtract,lapon,lapcqonly,nagain
|
||||||
|
equivalence (s1,s1sort)
|
||||||
|
data icos7/2,5,6,0,4,1,3/
|
||||||
|
data mcq/1,1,1,1,1,0,1,0,0,0,0,0,1,0,0,0,0,0,1,1,0,0,0,1,1,0,0,1/
|
||||||
|
data mrrr/0,1,1,1,1,1,1,0,1,1,0,0,1,1,1,1/
|
||||||
|
data m73/0,1,1,1,1,1,1,0,1,1,0,1,0,0,0,0/
|
||||||
|
data mde/1,1,1,1,1,1,1,1,0,1,1,0,0,1,0,0,0,0,0,1,1,1,0,1,0,0,0,1/
|
||||||
|
data mrr73/0,0,0,0,0,0,1,0,0,0,0,1,0,1,0,1/
|
||||||
|
data first/.true./
|
||||||
|
save nappasses,naptypes
|
||||||
|
|
||||||
|
if(first) then
|
||||||
|
mcq=2*mcq-1
|
||||||
|
mde=2*mde-1
|
||||||
|
mrrr=2*mrrr-1
|
||||||
|
m73=2*m73-1
|
||||||
|
mrr73=2*mrr73-1
|
||||||
|
nappasses(0)=2
|
||||||
|
nappasses(1)=2
|
||||||
|
nappasses(2)=2
|
||||||
|
nappasses(3)=4
|
||||||
|
nappasses(4)=4
|
||||||
|
nappasses(5)=3
|
||||||
|
|
||||||
|
! iaptype
|
||||||
|
!------------------------
|
||||||
|
! 1 CQ ??? ???
|
||||||
|
! 2 MyCall ??? ???
|
||||||
|
! 3 MyCall DxCall ???
|
||||||
|
! 4 MyCall DxCall RRR
|
||||||
|
! 5 MyCall DxCall 73
|
||||||
|
! 6 MyCall DxCall RR73
|
||||||
|
! 7 ??? DxCall ???
|
||||||
|
|
||||||
|
naptypes(0,1:4)=(/1,2,0,0/)
|
||||||
|
naptypes(1,1:4)=(/2,3,0,0/)
|
||||||
|
naptypes(2,1:4)=(/2,3,0,0/)
|
||||||
|
naptypes(3,1:4)=(/3,4,5,6/)
|
||||||
|
naptypes(4,1:4)=(/3,4,5,6/)
|
||||||
|
naptypes(5,1:4)=(/3,1,2,0/)
|
||||||
|
first=.false.
|
||||||
|
endif
|
||||||
|
|
||||||
|
max_iterations=30
|
||||||
|
nharderrors=-1
|
||||||
|
fs2=12000.0/NDOWN
|
||||||
|
dt2=1.0/fs2
|
||||||
|
twopi=8.0*atan(1.0)
|
||||||
|
delfbest=0.
|
||||||
|
ibest=0
|
||||||
|
|
||||||
|
call timer('ft8_down',0)
|
||||||
|
call ft8_downsample(dd0,newdat,f1,cd0) !Mix f1 to baseband and downsample
|
||||||
|
call timer('ft8_down',1)
|
||||||
|
|
||||||
|
i0=nint((xdt+0.5)*fs2) !Initial guess for start of signal
|
||||||
|
smax=0.0
|
||||||
|
do idt=i0-8,i0+8 !Search over +/- one quarter symbol
|
||||||
|
call sync8d(cd0,idt,ctwk,0,sync)
|
||||||
|
if(sync.gt.smax) then
|
||||||
|
smax=sync
|
||||||
|
ibest=idt
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
xdt2=ibest*dt2 !Improved estimate for DT
|
||||||
|
|
||||||
|
! Now peak up in frequency
|
||||||
|
i0=nint(xdt2*fs2)
|
||||||
|
smax=0.0
|
||||||
|
do ifr=-5,5 !Search over +/- 2.5 Hz
|
||||||
|
delf=ifr*0.5
|
||||||
|
dphi=twopi*delf*dt2
|
||||||
|
phi=0.0
|
||||||
|
do i=1,32
|
||||||
|
ctwk(i)=cmplx(cos(phi),sin(phi))
|
||||||
|
phi=mod(phi+dphi,twopi)
|
||||||
|
enddo
|
||||||
|
call sync8d(cd0,i0,ctwk,1,sync)
|
||||||
|
if( sync .gt. smax ) then
|
||||||
|
smax=sync
|
||||||
|
delfbest=delf
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
a=0.0
|
||||||
|
a(1)=-delfbest
|
||||||
|
call twkfreq1(cd0,NP2,fs2,a,cd0)
|
||||||
|
xdt=xdt2
|
||||||
|
f1=f1+delfbest !Improved estimate of DF
|
||||||
|
|
||||||
|
call sync8d(cd0,i0,ctwk,2,sync)
|
||||||
|
|
||||||
|
j=0
|
||||||
|
do k=1,NN
|
||||||
|
i1=ibest+(k-1)*32
|
||||||
|
csymb=cmplx(0.0,0.0)
|
||||||
|
if( i1.ge.1 .and. i1+31 .le. NP2 ) csymb=cd0(i1:i1+31)
|
||||||
|
call four2a(csymb,32,1,-1,1)
|
||||||
|
s2(0:7,k)=abs(csymb(1:8))/1e3
|
||||||
|
enddo
|
||||||
|
|
||||||
|
! sync quality check
|
||||||
|
is1=0
|
||||||
|
is2=0
|
||||||
|
is3=0
|
||||||
|
do k=1,7
|
||||||
|
ip=maxloc(s2(:,k))
|
||||||
|
if(icos7(k-1).eq.(ip(1)-1)) is1=is1+1
|
||||||
|
ip=maxloc(s2(:,k+36))
|
||||||
|
if(icos7(k-1).eq.(ip(1)-1)) is2=is2+1
|
||||||
|
ip=maxloc(s2(:,k+72))
|
||||||
|
if(icos7(k-1).eq.(ip(1)-1)) is3=is3+1
|
||||||
|
enddo
|
||||||
|
! hard sync sum - max is 21
|
||||||
|
nsync=is1+is2+is3
|
||||||
|
if(nsync .le. 6) then ! bail out
|
||||||
|
nbadcrc=1
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
j=0
|
||||||
|
do k=1,NN
|
||||||
|
if(k.le.7) cycle
|
||||||
|
if(k.ge.37 .and. k.le.43) cycle
|
||||||
|
if(k.gt.72) cycle
|
||||||
|
j=j+1
|
||||||
|
s1(0:7,j)=s2(0:7,k)
|
||||||
|
enddo
|
||||||
|
|
||||||
|
call indexx(s1sort,8*ND,indxs1)
|
||||||
|
xmeds1=s1sort(indxs1(nint(0.5*8*ND)))
|
||||||
|
s1=s1/xmeds1
|
||||||
|
|
||||||
|
do j=1,ND
|
||||||
|
i4=3*j-2
|
||||||
|
i2=3*j-1
|
||||||
|
i1=3*j
|
||||||
|
! Max amplitude
|
||||||
|
ps=s1(0:7,j)
|
||||||
|
r1=max(ps(1),ps(3),ps(5),ps(7))-max(ps(0),ps(2),ps(4),ps(6))
|
||||||
|
r2=max(ps(2),ps(3),ps(6),ps(7))-max(ps(0),ps(1),ps(4),ps(5))
|
||||||
|
r4=max(ps(4),ps(5),ps(6),ps(7))-max(ps(0),ps(1),ps(2),ps(3))
|
||||||
|
bmeta(i4)=r4
|
||||||
|
bmeta(i2)=r2
|
||||||
|
bmeta(i1)=r1
|
||||||
|
bmetap(i4)=r4
|
||||||
|
bmetap(i2)=r2
|
||||||
|
bmetap(i1)=r1
|
||||||
|
! Max log metric
|
||||||
|
psl=log(ps)
|
||||||
|
r1=max(psl(1),psl(3),psl(5),psl(7))-max(psl(0),psl(2),psl(4),psl(6))
|
||||||
|
r2=max(psl(2),psl(3),psl(6),psl(7))-max(psl(0),psl(1),psl(4),psl(5))
|
||||||
|
r4=max(psl(4),psl(5),psl(6),psl(7))-max(psl(0),psl(1),psl(2),psl(3))
|
||||||
|
bmetb(i4)=r4
|
||||||
|
bmetb(i2)=r2
|
||||||
|
bmetb(i1)=r1
|
||||||
|
|
||||||
|
! Metric for Cauchy noise
|
||||||
|
! r1=log(ps(1)**3+ps(3)**3+ps(5)**3+ps(7)**3)- &
|
||||||
|
! log(ps(0)**3+ps(2)**3+ps(4)**3+ps(6)**3)
|
||||||
|
! r2=log(ps(2)**3+ps(3)**3+ps(6)**3+ps(7)**3)- &
|
||||||
|
! log(ps(0)**3+ps(1)**3+ps(4)**3+ps(5)**3)
|
||||||
|
! r4=log(ps(4)**3+ps(5)**3+ps(6)**3+ps(7)**3)- &
|
||||||
|
! log(ps(0)**3+ps(1)**3+ps(2)**3+ps(3)**3)
|
||||||
|
! Metric for AWGN, no fading
|
||||||
|
! bscale=2.5
|
||||||
|
! b0=bessi0(bscale*ps(0))
|
||||||
|
! b1=bessi0(bscale*ps(1))
|
||||||
|
! b2=bessi0(bscale*ps(2))
|
||||||
|
! b3=bessi0(bscale*ps(3))
|
||||||
|
! b4=bessi0(bscale*ps(4))
|
||||||
|
! b5=bessi0(bscale*ps(5))
|
||||||
|
! b6=bessi0(bscale*ps(6))
|
||||||
|
! b7=bessi0(bscale*ps(7))
|
||||||
|
! r1=log(b1+b3+b5+b7)-log(b0+b2+b4+b6)
|
||||||
|
! r2=log(b2+b3+b6+b7)-log(b0+b1+b4+b5)
|
||||||
|
! r4=log(b4+b5+b6+b7)-log(b0+b1+b2+b3)
|
||||||
|
|
||||||
|
if(nQSOProgress .eq. 0 .or. nQSOProgress .eq. 5) then
|
||||||
|
! When bits 88:115 are set as ap bits, bit 115 lives in symbol 39 along
|
||||||
|
! with no-ap bits 116 and 117. Take care of metrics for bits 116 and 117.
|
||||||
|
if(j.eq.39) then ! take care of bits that live in symbol 39
|
||||||
|
if(apsym(28).lt.0) then
|
||||||
|
bmetap(i2)=max(ps(2),ps(3))-max(ps(0),ps(1))
|
||||||
|
bmetap(i1)=max(ps(1),ps(3))-max(ps(0),ps(2))
|
||||||
|
else
|
||||||
|
bmetap(i2)=max(ps(6),ps(7))-max(ps(4),ps(5))
|
||||||
|
bmetap(i1)=max(ps(5),ps(7))-max(ps(4),ps(6))
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
! When bits 116:143 are set as ap bits, bit 115 lives in symbol 39 along
|
||||||
|
! with ap bits 116 and 117. Take care of metric for bit 115.
|
||||||
|
! if(j.eq.39) then ! take care of bit 115
|
||||||
|
! iii=2*(apsym(29)+1)/2 + (apsym(30)+1)/2 ! known values of bits 116 & 117
|
||||||
|
! if(iii.eq.0) bmetap(i4)=ps(4)-ps(0)
|
||||||
|
! if(iii.eq.1) bmetap(i4)=ps(5)-ps(1)
|
||||||
|
! if(iii.eq.2) bmetap(i4)=ps(6)-ps(2)
|
||||||
|
! if(iii.eq.3) bmetap(i4)=ps(7)-ps(3)
|
||||||
|
! endif
|
||||||
|
|
||||||
|
! bit 144 lives in symbol 48 and will be 1 if it is set as an ap bit.
|
||||||
|
! take care of metrics for bits 142 and 143
|
||||||
|
if(j.eq.48) then ! bit 144 is always 1
|
||||||
|
bmetap(i4)=max(ps(5),ps(7))-max(ps(1),ps(3))
|
||||||
|
bmetap(i2)=max(ps(3),ps(7))-max(ps(1),ps(5))
|
||||||
|
endif
|
||||||
|
|
||||||
|
! bit 154 lives in symbol 52 and will be 0 if it is set as an ap bit
|
||||||
|
! take care of metrics for bits 155 and 156
|
||||||
|
if(j.eq.52) then ! bit 154 will be 0 if it is set as an ap bit.
|
||||||
|
bmetap(i2)=max(ps(2),ps(3))-max(ps(0),ps(1))
|
||||||
|
bmetap(i1)=max(ps(1),ps(3))-max(ps(0),ps(2))
|
||||||
|
endif
|
||||||
|
|
||||||
|
enddo
|
||||||
|
|
||||||
|
call normalizebmet(bmeta,3*ND)
|
||||||
|
call normalizebmet(bmetb,3*ND)
|
||||||
|
call normalizebmet(bmetap,3*ND)
|
||||||
|
|
||||||
|
scalefac=2.83
|
||||||
|
llr0=scalefac*bmeta
|
||||||
|
llr1=scalefac*bmetb
|
||||||
|
llra=scalefac*bmetap ! llr's for use with ap
|
||||||
|
apmag=scalefac*(maxval(abs(bmetap))*1.01)
|
||||||
|
|
||||||
|
! pass #
|
||||||
|
!------------------------------
|
||||||
|
! 1 regular decoding
|
||||||
|
! 2 erase 24
|
||||||
|
! 3 erase 48
|
||||||
|
! 4 ap pass 1
|
||||||
|
! 5 ap pass 2
|
||||||
|
! 6 ap pass 3
|
||||||
|
! 7 ap pass 4, etc.
|
||||||
|
|
||||||
|
if(lapon) then
|
||||||
|
if(.not.lapcqonly) then
|
||||||
|
npasses=4+nappasses(nQSOProgress)
|
||||||
|
else
|
||||||
|
npasses=5
|
||||||
|
endif
|
||||||
|
else
|
||||||
|
npasses=4
|
||||||
|
endif
|
||||||
|
|
||||||
|
do ipass=1,npasses
|
||||||
|
|
||||||
|
llr=llr0
|
||||||
|
if(ipass.eq.2) llr=llr1
|
||||||
|
if(ipass.eq.3) llr(1:24)=0.
|
||||||
|
if(ipass.eq.4) llr(1:48)=0.
|
||||||
|
if(ipass.le.4) then
|
||||||
|
apmask=0
|
||||||
|
llrap=llr
|
||||||
|
iaptype=0
|
||||||
|
endif
|
||||||
|
|
||||||
|
if(ipass .gt. 4) then
|
||||||
|
if(.not.lapcqonly) then
|
||||||
|
iaptype=naptypes(nQSOProgress,ipass-4)
|
||||||
|
else
|
||||||
|
iaptype=1
|
||||||
|
endif
|
||||||
|
if(iaptype.ge.3 .and. (abs(f1-nfqso).gt.napwid .and. abs(f1-nftx).gt.napwid) ) cycle
|
||||||
|
if(iaptype.eq.1 .or. iaptype.eq.2 ) then ! AP,???,???
|
||||||
|
apmask=0
|
||||||
|
apmask(88:115)=1 ! first 28 bits are AP
|
||||||
|
apmask(144)=1 ! not free text
|
||||||
|
llrap=llr
|
||||||
|
if(iaptype.eq.1) llrap(88:115)=apmag*mcq
|
||||||
|
if(iaptype.eq.2) llrap(88:115)=apmag*apsym(1:28)
|
||||||
|
llrap(116:117)=llra(116:117)
|
||||||
|
llrap(142:143)=llra(142:143)
|
||||||
|
llrap(144)=-apmag
|
||||||
|
endif
|
||||||
|
if(iaptype.eq.3) then ! mycall, dxcall, ???
|
||||||
|
apmask=0
|
||||||
|
apmask(88:115)=1 ! mycall
|
||||||
|
apmask(116:143)=1 ! hiscall
|
||||||
|
apmask(144)=1 ! not free text
|
||||||
|
llrap=llr
|
||||||
|
llrap(88:143)=apmag*apsym(1:56)
|
||||||
|
llrap(144)=-apmag
|
||||||
|
endif
|
||||||
|
if(iaptype.eq.4 .or. iaptype.eq.5 .or. iaptype.eq.6) then
|
||||||
|
apmask=0
|
||||||
|
apmask(88:115)=1 ! mycall
|
||||||
|
apmask(116:143)=1 ! hiscall
|
||||||
|
apmask(144:159)=1 ! RRR or 73 or RR73
|
||||||
|
llrap=llr
|
||||||
|
llrap(88:143)=apmag*apsym(1:56)
|
||||||
|
if(iaptype.eq.4) llrap(144:159)=apmag*mrrr
|
||||||
|
if(iaptype.eq.5) llrap(144:159)=apmag*m73
|
||||||
|
if(iaptype.eq.6) llrap(144:159)=apmag*mrr73
|
||||||
|
endif
|
||||||
|
if(iaptype.eq.7) then ! ???, dxcall, ???
|
||||||
|
apmask=0
|
||||||
|
apmask(116:143)=1 ! hiscall
|
||||||
|
apmask(144)=1 ! not free text
|
||||||
|
llrap=llr
|
||||||
|
llrap(115)=llra(115)
|
||||||
|
llrap(116:143)=apmag*apsym(29:56)
|
||||||
|
llrap(144)=-apmag
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
cw=0
|
||||||
|
call timer('bpd174 ',0)
|
||||||
|
call bpdecode174(llrap,apmask,max_iterations,decoded,cw,nharderrors, &
|
||||||
|
niterations)
|
||||||
|
call timer('bpd174 ',1)
|
||||||
|
dmin=0.0
|
||||||
|
if(ndepth.eq.3 .and. nharderrors.lt.0) then
|
||||||
|
ndeep=3
|
||||||
|
if(abs(nfqso-f1).le.napwid .or. abs(nftx-f1).le.napwid) then
|
||||||
|
if((ipass.eq.3 .or. ipass.eq.4) .and. .not.nagain) then
|
||||||
|
ndeep=3
|
||||||
|
else
|
||||||
|
ndeep=4
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
if(nagain) ndeep=5
|
||||||
|
call timer('osd174 ',0)
|
||||||
|
call osd174(llrap,apmask,ndeep,decoded,cw,nharderrors,dmin)
|
||||||
|
call timer('osd174 ',1)
|
||||||
|
endif
|
||||||
|
nbadcrc=1
|
||||||
|
message=' '
|
||||||
|
xsnr=-99.0
|
||||||
|
if(count(cw.eq.0).eq.174) cycle !Reject the all-zero codeword
|
||||||
|
if(nharderrors.ge.0 .and. nharderrors+dmin.lt.60.0 .and. &
|
||||||
|
.not.(sync.lt.2.0 .and. nharderrors.gt.35) .and. &
|
||||||
|
.not.(ipass.gt.2 .and. nharderrors.gt.39) .and. &
|
||||||
|
.not.(ipass.eq.4 .and. nharderrors.gt.30) &
|
||||||
|
) then
|
||||||
|
call chkcrc12a(decoded,nbadcrc)
|
||||||
|
else
|
||||||
|
nharderrors=-1
|
||||||
|
cycle
|
||||||
|
endif
|
||||||
|
i3bit=4*decoded(73) + 2*decoded(74) + decoded(75)
|
||||||
|
iFreeText=decoded(57)
|
||||||
|
if(nbadcrc.eq.0) then
|
||||||
|
decoded0=decoded
|
||||||
|
if(i3bit.eq.1) decoded(57:)=0
|
||||||
|
call extractmessage174(decoded,message,ncrcflag)
|
||||||
|
decoded=decoded0
|
||||||
|
! This needs fixing for messages with i3bit=1:
|
||||||
|
call genft8(message,mygrid6,bcontest,i3bit,msgsent,msgbits,itone)
|
||||||
|
if(lsubtract) call subtractft8(dd0,itone,f1,xdt2)
|
||||||
|
xsig=0.0
|
||||||
|
xnoi=0.0
|
||||||
|
do i=1,79
|
||||||
|
xsig=xsig+s2(itone(i),i)**2
|
||||||
|
ios=mod(itone(i)+4,7)
|
||||||
|
xnoi=xnoi+s2(ios,i)**2
|
||||||
|
enddo
|
||||||
|
xsnr=0.001
|
||||||
|
if(xnoi.gt.0 .and. xnoi.lt.xsig) xsnr=xsig/xnoi-1.0
|
||||||
|
xsnr=10.0*log10(xsnr)-27.0
|
||||||
|
xsnr2=db(xsig/xbase - 1.0) - 32.0
|
||||||
|
if(.not.nagain) xsnr=xsnr2
|
||||||
|
if(xsnr .lt. -24.0) xsnr=-24.0
|
||||||
|
|
||||||
|
if(i3bit.eq.1) then
|
||||||
|
do i=1,12
|
||||||
|
i1hiscall(i)=ichar(hiscall12(i:i))
|
||||||
|
enddo
|
||||||
|
icrc10=crc10(c_loc(i1hiscall),12)
|
||||||
|
write(cbits,1001) decoded
|
||||||
|
1001 format(87i1)
|
||||||
|
read(cbits,1002) ncrc10,nrpt
|
||||||
|
1002 format(56x,b10,b6)
|
||||||
|
irpt=nrpt-30
|
||||||
|
i1=index(message,' ')
|
||||||
|
i2=index(message(i1+1:),' ') + i1
|
||||||
|
c1=message(1:i1)//' '
|
||||||
|
c2=message(i1+1:i2)//' '
|
||||||
|
|
||||||
|
if(ncrc10.eq.icrc10) msg37=c1//' RR73; '//c2//' <'// &
|
||||||
|
trim(hiscall12)//'> '
|
||||||
|
if(ncrc10.ne.icrc10) msg37=c1//' RR73; '//c2//' <...> '
|
||||||
|
|
||||||
|
! msg37=c1//' RR73; '//c2//' <...> '
|
||||||
|
write(msg37(35:37),1010) irpt
|
||||||
|
1010 format(i3.2)
|
||||||
|
if(msg37(35:35).ne.'-') msg37(35:35)='+'
|
||||||
|
|
||||||
|
iz=len(trim(msg37))
|
||||||
|
do iter=1,10 !Collapse multiple blanks
|
||||||
|
ib2=index(msg37(1:iz),' ')
|
||||||
|
if(ib2.lt.1) exit
|
||||||
|
msg37=msg37(1:ib2)//msg37(ib2+2:)
|
||||||
|
iz=iz-1
|
||||||
|
enddo
|
||||||
|
else
|
||||||
|
msg37=message//' '
|
||||||
|
endif
|
||||||
|
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
|
||||||
|
return
|
||||||
|
end subroutine ft8b
|
||||||
|
|
||||||
|
subroutine normalizebmet(bmet,n)
|
||||||
|
real bmet(n)
|
||||||
|
|
||||||
|
bmetav=sum(bmet)/real(n)
|
||||||
|
bmet2av=sum(bmet*bmet)/real(n)
|
||||||
|
var=bmet2av-bmetav*bmetav
|
||||||
|
if( var .gt. 0.0 ) then
|
||||||
|
bmetsig=sqrt(var)
|
||||||
|
else
|
||||||
|
bmetsig=sqrt(bmet2av)
|
||||||
|
endif
|
||||||
|
bmet=bmet/bmetsig
|
||||||
|
return
|
||||||
|
end subroutine normalizebmet
|
||||||
|
|
||||||
|
|
||||||
|
function bessi0(x)
|
||||||
|
! From Numerical Recipes
|
||||||
|
real bessi0,x
|
||||||
|
double precision p1,p2,p3,p4,p5,p6,p7,q1,q2,q3,q4,q5,q6,q7,q8,q9,y
|
||||||
|
save p1,p2,p3,p4,p5,p6,p7,q1,q2,q3,q4,q5,q6,q7,q8,q9
|
||||||
|
data p1,p2,p3,p4,p5,p6,p7/1.0d0,3.5156229d0,3.0899424d0,1.2067492d0, &
|
||||||
|
0.2659732d0,0.360768d-1,0.45813d-2/
|
||||||
|
data q1,q2,q3,q4,q5,q6,q7,q8,q9/0.39894228d0,0.1328592d-1, &
|
||||||
|
0.225319d-2,-0.157565d-2,0.916281d-2,-0.2057706d-1, &
|
||||||
|
0.2635537d-1,-0.1647633d-1,0.392377d-2/
|
||||||
|
|
||||||
|
if (abs(x).lt.3.75) then
|
||||||
|
y=(x/3.75)**2
|
||||||
|
bessi0=p1+y*(p2+y*(p3+y*(p4+y*(p5+y*(p6+y*p7)))))
|
||||||
|
else
|
||||||
|
ax=abs(x)
|
||||||
|
y=3.75/ax
|
||||||
|
bessi0=(exp(ax)/sqrt(ax))*(q1+y*(q2+y*(q3+y*(q4 &
|
||||||
|
+y*(q5+y*(q6+y*(q7+y*(q8+y*q9))))))))
|
||||||
|
endif
|
||||||
|
return
|
||||||
|
end function bessi0
|
||||||
|
|
||||||
@@ -0,0 +1,254 @@
|
|||||||
|
program ldpcsim300
|
||||||
|
|
||||||
|
! End-to-end test of the (300,60)/crc10 encoder and decoders.
|
||||||
|
|
||||||
|
use crc
|
||||||
|
use packjt
|
||||||
|
|
||||||
|
parameter(NRECENT=10)
|
||||||
|
character*12 recent_calls(NRECENT)
|
||||||
|
character*8 arg
|
||||||
|
integer*1, allocatable :: codeword(:), decoded(:), message(:)
|
||||||
|
integer*1, target:: i1Msg8BitBytes(9)
|
||||||
|
integer*1, target:: i1Dec8BitBytes(9)
|
||||||
|
integer*1 msgbits(60)
|
||||||
|
integer*1 apmask(300)
|
||||||
|
integer*1 cw(300)
|
||||||
|
integer*2 checksum
|
||||||
|
integer colorder(300)
|
||||||
|
integer nerrtot(300),nerrdec(300),nmpcbad(60)
|
||||||
|
logical checksumok,fsk,bpsk
|
||||||
|
real*8, allocatable :: rxdata(:)
|
||||||
|
real, allocatable :: llr(:)
|
||||||
|
real dllr(300),llrd(300)
|
||||||
|
|
||||||
|
data colorder/ &
|
||||||
|
0,1,2,3,4,5,6,7,8,9,10,11,123,12,13,14,15,16,17,18, &
|
||||||
|
19,20,21,22,23,24,25,138,26,145,27,28,29,30,31,32,33,34,35,36, &
|
||||||
|
37,154,38,39,40,41,42,43,44,144,46,47,48,49,50,51,52,53,143,54, &
|
||||||
|
125,56,57,58,124,59,120,140,157,160,55,60,61,62,156,162,141,64,65,153, &
|
||||||
|
181,183,66,170,67,68,69,130,70,164,71,72,73,74,75,63,76,77,135,78, &
|
||||||
|
79,80,176,169,82,83,84,167,180,85,136,158,129,166,175,142,134,146,121,165, &
|
||||||
|
88,89,192,90,45,91,92,93,182,189,94,95,96,173,81,97,98,178,122,126, &
|
||||||
|
132,99,100,152,186,193,101,102,151,103,104,172,159,168,150,190,147,148,201,107, &
|
||||||
|
205,177,108,198,197,174,127,109,185,110,202,87,199,171,179,187,139,137,106,131, &
|
||||||
|
206,194,112,149,155,113,128,184,196,86,114,203,212,195,208,105,188,161,163,191, &
|
||||||
|
200,209,214,204,115,218,133,111,207,117,213,216,211,217,116,215,219,220,210,221, &
|
||||||
|
118,222,223,225,224,228,226,229,231,227,233,119,234,235,232,230,237,239,236,238, &
|
||||||
|
240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259, &
|
||||||
|
260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279, &
|
||||||
|
280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299/
|
||||||
|
|
||||||
|
do i=1,NRECENT
|
||||||
|
recent_calls(i)=' '
|
||||||
|
enddo
|
||||||
|
nerrtot=0
|
||||||
|
nerrdec=0
|
||||||
|
nmpcbad=0 ! Used to collect the number of errors in the message+crc part of the codeword
|
||||||
|
|
||||||
|
nargs=iargc()
|
||||||
|
if(nargs.ne.4) then
|
||||||
|
print*,'Usage: ldpcsim niter ndeep #trials s '
|
||||||
|
print*,'eg: ldpcsim 100 4 1000 0.84'
|
||||||
|
print*,'If s is negative, then value is ignored and sigma is calculated from SNR.'
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
call getarg(1,arg)
|
||||||
|
read(arg,*) max_iterations
|
||||||
|
call getarg(2,arg)
|
||||||
|
read(arg,*) ndeep
|
||||||
|
call getarg(3,arg)
|
||||||
|
read(arg,*) ntrials
|
||||||
|
call getarg(4,arg)
|
||||||
|
read(arg,*) s
|
||||||
|
|
||||||
|
fsk=.false.
|
||||||
|
bpsk=.true.
|
||||||
|
|
||||||
|
! don't count crc bits as data bits
|
||||||
|
N=300
|
||||||
|
K=60
|
||||||
|
! scale Eb/No for a (300,50) code
|
||||||
|
rate=real(50)/real(N)
|
||||||
|
|
||||||
|
write(*,*) "rate: ",rate
|
||||||
|
write(*,*) "niter= ",max_iterations," s= ",s
|
||||||
|
|
||||||
|
allocate ( codeword(N), decoded(K), message(K) )
|
||||||
|
allocate ( rxdata(N), llr(N) )
|
||||||
|
|
||||||
|
! The message should be packed into the first 7 bytes
|
||||||
|
i1Msg8BitBytes(1:6)=85
|
||||||
|
i1Msg8BitBytes(7)=64
|
||||||
|
! The CRC will be put into the last 2 bytes
|
||||||
|
i1Msg8BitBytes(8:9)=0
|
||||||
|
checksum = crc10 (c_loc (i1Msg8BitBytes), 9)
|
||||||
|
! For reference, the next 3 lines show how to check the CRC
|
||||||
|
i1Msg8BitBytes(8)=checksum/256
|
||||||
|
i1Msg8BitBytes(9)=iand (checksum,255)
|
||||||
|
checksumok = crc10_check(c_loc (i1Msg8BitBytes), 9)
|
||||||
|
if( checksumok ) write(*,*) 'Good checksum'
|
||||||
|
write(*,*) i1Msg8BitBytes(1:9)
|
||||||
|
|
||||||
|
mbit=0
|
||||||
|
do i=1, 7
|
||||||
|
i1=i1Msg8BitBytes(i)
|
||||||
|
do ibit=1,8
|
||||||
|
mbit=mbit+1
|
||||||
|
msgbits(mbit)=iand(1,ishft(i1,ibit-8))
|
||||||
|
enddo
|
||||||
|
enddo
|
||||||
|
i1=i1Msg8BitBytes(8) ! First 2 bits of crc10 are LSB of this byte
|
||||||
|
do ibit=1,2
|
||||||
|
msgbits(50+ibit)=iand(1,ishft(i1,ibit-2))
|
||||||
|
enddo
|
||||||
|
i1=i1Msg8BitBytes(9) ! Now shift in last 8 bits of the CRC
|
||||||
|
do ibit=1,8
|
||||||
|
msgbits(52+ibit)=iand(1,ishft(i1,ibit-8))
|
||||||
|
enddo
|
||||||
|
|
||||||
|
write(*,*) 'message'
|
||||||
|
write(*,'(9(8i1,1x))') msgbits
|
||||||
|
|
||||||
|
call encode300(msgbits,codeword)
|
||||||
|
call init_random_seed()
|
||||||
|
call sgran()
|
||||||
|
|
||||||
|
write(*,*) 'codeword'
|
||||||
|
write(*,'(38(8i1,1x))') codeword
|
||||||
|
|
||||||
|
write(*,*) "Es/N0 SNR2500 ngood nundetected nbadcrc sigma"
|
||||||
|
do idb = 20,-16,-1
|
||||||
|
!do idb = -16, -16, -1
|
||||||
|
db=idb/2.0-1.0
|
||||||
|
! sigma=1/sqrt( 2*rate*(10**(db/10.0)) ) ! to make db represent Eb/No
|
||||||
|
sigma=1/sqrt( 2*(10**(db/10.0)) ) ! db represents Es/No
|
||||||
|
ngood=0
|
||||||
|
nue=0
|
||||||
|
nbadcrc=0
|
||||||
|
nberr=0
|
||||||
|
do itrial=1, ntrials
|
||||||
|
! Create a realization of a noisy received word
|
||||||
|
do i=1,N
|
||||||
|
if( bpsk ) then
|
||||||
|
rxdata(i) = 2.0*codeword(i)-1.0 + sigma*gran()
|
||||||
|
elseif( fsk ) then
|
||||||
|
if( codeword(i) .eq. 1 ) then
|
||||||
|
r1=(1.0 + sigma*gran())**2 + (sigma*gran())**2
|
||||||
|
r2=(sigma*gran())**2 + (sigma*gran())**2
|
||||||
|
elseif( codeword(i) .eq. 0 ) then
|
||||||
|
r2=(1.0 + sigma*gran())**2 + (sigma*gran())**2
|
||||||
|
r1=(sigma*gran())**2 + (sigma*gran())**2
|
||||||
|
endif
|
||||||
|
rxdata(i)=0.35*(sqrt(r1)-sqrt(r2))
|
||||||
|
! rxdata(i)=0.35*(exp(r1)-exp(r2))
|
||||||
|
! rxdata(i)=0.12*(log(r1)-log(r2))
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
nerr=0
|
||||||
|
do i=1,N
|
||||||
|
if( rxdata(i)*(2*codeword(i)-1.0) .lt. 0 ) nerr=nerr+1
|
||||||
|
enddo
|
||||||
|
if(nerr.ge.1) nerrtot(nerr)=nerrtot(nerr)+1
|
||||||
|
nberr=nberr+nerr
|
||||||
|
|
||||||
|
! Correct signal normalization is important for this decoder.
|
||||||
|
rxav=sum(rxdata)/N
|
||||||
|
rx2av=sum(rxdata*rxdata)/N
|
||||||
|
rxsig=sqrt(rx2av-rxav*rxav)
|
||||||
|
rxdata=rxdata/rxsig
|
||||||
|
! To match the metric to the channel, s should be set to the noise standard deviation.
|
||||||
|
! For now, set s to the value that optimizes decode probability near threshold.
|
||||||
|
! The s parameter can be tuned to trade a few tenth's dB of threshold for an order of
|
||||||
|
! magnitude in UER
|
||||||
|
if( s .lt. 0 ) then
|
||||||
|
ss=sigma
|
||||||
|
else
|
||||||
|
ss=s
|
||||||
|
endif
|
||||||
|
|
||||||
|
llr=2.0*rxdata/(ss*ss)
|
||||||
|
apmask=0
|
||||||
|
! max_iterations is max number of belief propagation iterations
|
||||||
|
call bpdecode300(llr, apmask, max_iterations, decoded, niterations, cw)
|
||||||
|
if( (niterations .lt. 0) .and. (ndeep .ge. 0) ) then
|
||||||
|
call osd300(llr, apmask, ndeep, decoded, cw, nhardmin, dmin)
|
||||||
|
niterations=nhardmin
|
||||||
|
endif
|
||||||
|
n2err=0
|
||||||
|
do i=1,N
|
||||||
|
if( cw(i)*(2*codeword(i)-1.0) .lt. 0 ) n2err=n2err+1
|
||||||
|
enddo
|
||||||
|
!write(*,*) nerr,niterations,n2err
|
||||||
|
damp=0.75
|
||||||
|
ndither=0
|
||||||
|
if( niterations .lt. 0 ) then
|
||||||
|
do i=1, ndither
|
||||||
|
do in=1,N
|
||||||
|
dllr(in)=damp*gran()
|
||||||
|
enddo
|
||||||
|
llrd=llr+dllr
|
||||||
|
call bpdecode300(llrd, apmask, max_iterations, decoded, niterations, cw)
|
||||||
|
if( niterations .ge. 0 ) exit
|
||||||
|
enddo
|
||||||
|
endif
|
||||||
|
|
||||||
|
! If the decoder finds a valid codeword, niterations will be .ge. 0.
|
||||||
|
if( niterations .ge. 0 ) then
|
||||||
|
! Check the CRC
|
||||||
|
do ibyte=1,6
|
||||||
|
itmp=0
|
||||||
|
do ibit=1,8
|
||||||
|
itmp=ishft(itmp,1)+iand(1,decoded((ibyte-1)*8+ibit))
|
||||||
|
enddo
|
||||||
|
i1Dec8BitBytes(ibyte)=itmp
|
||||||
|
enddo
|
||||||
|
i1Dec8BitBytes(7)=decoded(49)*128+decoded(50)*64
|
||||||
|
! Need to pack the received crc into bytes 8 and 9 for crc10_check
|
||||||
|
i1Dec8BitBytes(8)=decoded(51)*2+decoded(52)
|
||||||
|
i1Dec8BitBytes(9)=decoded(53)*128+decoded(54)*64+decoded(55)*32+decoded(56)*16
|
||||||
|
i1Dec8BitBytes(9)=i1Dec8BitBytes(9)+decoded(57)*8+decoded(58)*4+decoded(59)*2+decoded(60)*1
|
||||||
|
ncrcflag=0
|
||||||
|
if( crc10_check( c_loc( i1Dec8BitBytes ), 9 ) ) ncrcflag=1
|
||||||
|
|
||||||
|
if( ncrcflag .ne. 1 ) then
|
||||||
|
nbadcrc=nbadcrc+1
|
||||||
|
endif
|
||||||
|
nueflag=0
|
||||||
|
|
||||||
|
nerrmpc=0
|
||||||
|
do i=1,K ! find number of errors in message+crc part of codeword
|
||||||
|
if( msgbits(i) .ne. decoded(i) ) then
|
||||||
|
nueflag=1
|
||||||
|
nerrmpc=nerrmpc+1
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
if(nerrmpc.ge.1) nmpcbad(nerrmpc)=nmpcbad(nerrmpc)+1 ! This histogram should inform our selection of CRC poly
|
||||||
|
if( ncrcflag .eq. 1 .and. nueflag .eq. 0 ) then
|
||||||
|
ngood=ngood+1
|
||||||
|
if(nerr.ge.1) nerrdec(nerr)=nerrdec(nerr)+1
|
||||||
|
else if( ncrcflag .eq. 1 .and. nueflag .eq. 1 ) then
|
||||||
|
nue=nue+1;
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
snr2500=db+10*log10(1.389/2500.0)
|
||||||
|
pberr=real(nberr)/(real(ntrials*N))
|
||||||
|
write(*,"(f4.1,4x,f5.1,1x,i8,1x,i8,1x,i8,8x,f5.2,8x,e10.3)") db,snr2500,ngood,nue,nbadcrc,ss,pberr
|
||||||
|
|
||||||
|
enddo
|
||||||
|
|
||||||
|
open(unit=23,file='nerrhisto.dat',status='unknown')
|
||||||
|
do i=1,120
|
||||||
|
write(23,'(i4,2x,i10,i10,f10.2)') i,nerrdec(i),nerrtot(i),real(nerrdec(i))/real(nerrtot(i)+1e-10)
|
||||||
|
enddo
|
||||||
|
close(23)
|
||||||
|
open(unit=25,file='nmpcbad.dat',status='unknown')
|
||||||
|
do i=1,60
|
||||||
|
write(25,'(i4,2x,i10)') i,nmpcbad(i)
|
||||||
|
enddo
|
||||||
|
close(25)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
end program ldpcsim300
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
subroutine slope(y,npts,xpk)
|
||||||
|
|
||||||
|
! Remove best-fit slope from data in y(i). When fitting the straight line,
|
||||||
|
! ignore the peak around xpk +/- 4 bins
|
||||||
|
|
||||||
|
real y(npts)
|
||||||
|
|
||||||
|
sumw=0.
|
||||||
|
sumx=0.
|
||||||
|
sumy=0.
|
||||||
|
sumx2=0.
|
||||||
|
sumxy=0.
|
||||||
|
sumy2=0.
|
||||||
|
do i=1,npts
|
||||||
|
if(abs(i-xpk).gt.4.0) then
|
||||||
|
sumw=sumw + 1.0
|
||||||
|
x=i
|
||||||
|
sumx=sumx + x
|
||||||
|
sumy=sumy + y(i)
|
||||||
|
sumx2=sumx2 + x*x
|
||||||
|
sumxy=sumxy + x*y(i)
|
||||||
|
sumy2=sumy2 + y(i)**2
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
|
||||||
|
delta=sumw*sumx2 - sumx**2
|
||||||
|
a=(sumx2*sumy - sumx*sumxy) / delta
|
||||||
|
b=(sumw*sumxy - sumx*sumy) / delta
|
||||||
|
|
||||||
|
sq=0.
|
||||||
|
do i=1,npts
|
||||||
|
y(i)=y(i)-(a + b*i)
|
||||||
|
if(abs(i-xpk).gt.4.0) sq=sq + y(i)**2
|
||||||
|
enddo
|
||||||
|
rms=sqrt(sq/(sumw-4.0))
|
||||||
|
y=y/rms
|
||||||
|
|
||||||
|
return
|
||||||
|
end subroutine slope
|
||||||
|
|
||||||
@@ -0,0 +1,310 @@
|
|||||||
|
#include "ClientWidget.hpp"
|
||||||
|
|
||||||
|
#include <QRegExp>
|
||||||
|
#include <QColor>
|
||||||
|
|
||||||
|
#include "MaidenheadLocatorValidator.hpp"
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
//QRegExp message_alphabet {"[- A-Za-z0-9+./?]*"};
|
||||||
|
QRegExp message_alphabet {"[- @A-Za-z0-9+./?#<>]*"};
|
||||||
|
QRegularExpression cq_re {"(CQ|CQDX|QRZ)[^A-Z0-9/]+"};
|
||||||
|
|
||||||
|
void update_dynamic_property (QWidget * widget, char const * property, QVariant const& value)
|
||||||
|
{
|
||||||
|
widget->setProperty (property, value);
|
||||||
|
widget->style ()->unpolish (widget);
|
||||||
|
widget->style ()->polish (widget);
|
||||||
|
widget->update ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ClientWidget::IdFilterModel::IdFilterModel (QString const& client_id)
|
||||||
|
: client_id_ {client_id}
|
||||||
|
, rx_df_ (-1)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant ClientWidget::IdFilterModel::data (QModelIndex const& proxy_index, int role) const
|
||||||
|
{
|
||||||
|
if (role == Qt::BackgroundRole)
|
||||||
|
{
|
||||||
|
switch (proxy_index.column ())
|
||||||
|
{
|
||||||
|
case 8: // message
|
||||||
|
{
|
||||||
|
auto message = QSortFilterProxyModel::data (proxy_index).toString ();
|
||||||
|
if (base_call_re_.pattern ().size ()
|
||||||
|
&& message.contains (base_call_re_))
|
||||||
|
{
|
||||||
|
return QColor {255,200,200};
|
||||||
|
}
|
||||||
|
if (message.contains (cq_re))
|
||||||
|
{
|
||||||
|
return QColor {200, 255, 200};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4: // DF
|
||||||
|
if (qAbs (QSortFilterProxyModel::data (proxy_index).toInt () - rx_df_) <= 10)
|
||||||
|
{
|
||||||
|
return QColor {255, 200, 200};
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return QSortFilterProxyModel::data (proxy_index, role);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ClientWidget::IdFilterModel::filterAcceptsRow (int source_row
|
||||||
|
, QModelIndex const& source_parent) const
|
||||||
|
{
|
||||||
|
auto source_index_col0 = sourceModel ()->index (source_row, 0, source_parent);
|
||||||
|
return sourceModel ()->data (source_index_col0).toString () == client_id_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClientWidget::IdFilterModel::de_call (QString const& call)
|
||||||
|
{
|
||||||
|
if (call != call_)
|
||||||
|
{
|
||||||
|
beginResetModel ();
|
||||||
|
if (call.size ())
|
||||||
|
{
|
||||||
|
base_call_re_.setPattern ("[^A-Z0-9]*" + Radio::base_callsign (call) + "[^A-Z0-9]*");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
base_call_re_.setPattern (QString {});
|
||||||
|
}
|
||||||
|
call_ = call;
|
||||||
|
endResetModel ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClientWidget::IdFilterModel::rx_df (int df)
|
||||||
|
{
|
||||||
|
if (df != rx_df_)
|
||||||
|
{
|
||||||
|
beginResetModel ();
|
||||||
|
rx_df_ = df;
|
||||||
|
endResetModel ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
QString make_title (QString const& id, QString const& version, QString const& revision)
|
||||||
|
{
|
||||||
|
QString title {id};
|
||||||
|
if (version.size ())
|
||||||
|
{
|
||||||
|
title += QString {" v%1"}.arg (version);
|
||||||
|
}
|
||||||
|
if (revision.size ())
|
||||||
|
{
|
||||||
|
title += QString {" (%1)"}.arg (revision);
|
||||||
|
}
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ClientWidget::ClientWidget (QAbstractItemModel * decodes_model, QAbstractItemModel * beacons_model
|
||||||
|
, QString const& id, QString const& version, QString const& revision
|
||||||
|
, QListWidget const * calls_of_interest, QWidget * parent)
|
||||||
|
: QDockWidget {make_title (id, version, revision), parent}
|
||||||
|
, id_ {id}
|
||||||
|
, calls_of_interest_ {calls_of_interest}
|
||||||
|
, decodes_proxy_model_ {id_}
|
||||||
|
, decodes_table_view_ {new QTableView}
|
||||||
|
, beacons_table_view_ {new QTableView}
|
||||||
|
, message_line_edit_ {new QLineEdit}
|
||||||
|
, grid_line_edit_ {new QLineEdit}
|
||||||
|
, decodes_stack_ {new QStackedLayout}
|
||||||
|
, auto_off_button_ {new QPushButton {tr ("&Auto Off")}}
|
||||||
|
, halt_tx_button_ {new QPushButton {tr ("&Halt Tx")}}
|
||||||
|
, de_label_ {new QLabel}
|
||||||
|
, mode_label_ {new QLabel}
|
||||||
|
, fast_mode_ {false}
|
||||||
|
, frequency_label_ {new QLabel}
|
||||||
|
, dx_label_ {new QLabel}
|
||||||
|
, rx_df_label_ {new QLabel}
|
||||||
|
, tx_df_label_ {new QLabel}
|
||||||
|
, report_label_ {new QLabel}
|
||||||
|
, columns_resized_ {false}
|
||||||
|
{
|
||||||
|
// set up widgets
|
||||||
|
decodes_proxy_model_.setSourceModel (decodes_model);
|
||||||
|
decodes_table_view_->setModel (&decodes_proxy_model_);
|
||||||
|
decodes_table_view_->verticalHeader ()->hide ();
|
||||||
|
decodes_table_view_->hideColumn (0);
|
||||||
|
decodes_table_view_->horizontalHeader ()->setStretchLastSection (true);
|
||||||
|
|
||||||
|
auto form_layout = new QFormLayout;
|
||||||
|
form_layout->addRow (tr ("Free text:"), message_line_edit_);
|
||||||
|
form_layout->addRow (tr ("Temporary grid:"), grid_line_edit_);
|
||||||
|
message_line_edit_->setValidator (new QRegExpValidator {message_alphabet, this});
|
||||||
|
grid_line_edit_->setValidator (new MaidenheadLocatorValidator {this});
|
||||||
|
connect (message_line_edit_, &QLineEdit::textEdited, [this] (QString const& text) {
|
||||||
|
Q_EMIT do_free_text (id_, text, false);
|
||||||
|
});
|
||||||
|
connect (message_line_edit_, &QLineEdit::editingFinished, [this] () {
|
||||||
|
Q_EMIT do_free_text (id_, message_line_edit_->text (), true);
|
||||||
|
});
|
||||||
|
connect (grid_line_edit_, &QLineEdit::editingFinished, [this] () {
|
||||||
|
Q_EMIT location (id_, grid_line_edit_->text ());
|
||||||
|
});
|
||||||
|
|
||||||
|
auto decodes_page = new QWidget;
|
||||||
|
auto decodes_layout = new QVBoxLayout {decodes_page};
|
||||||
|
decodes_layout->setContentsMargins (QMargins {2, 2, 2, 2});
|
||||||
|
decodes_layout->addWidget (decodes_table_view_);
|
||||||
|
decodes_layout->addLayout (form_layout);
|
||||||
|
|
||||||
|
auto beacons_proxy_model = new IdFilterModel {id_};
|
||||||
|
beacons_proxy_model->setSourceModel (beacons_model);
|
||||||
|
beacons_table_view_->setModel (beacons_proxy_model);
|
||||||
|
beacons_table_view_->verticalHeader ()->hide ();
|
||||||
|
beacons_table_view_->hideColumn (0);
|
||||||
|
beacons_table_view_->horizontalHeader ()->setStretchLastSection (true);
|
||||||
|
|
||||||
|
auto beacons_page = new QWidget;
|
||||||
|
auto beacons_layout = new QVBoxLayout {beacons_page};
|
||||||
|
beacons_layout->setContentsMargins (QMargins {2, 2, 2, 2});
|
||||||
|
beacons_layout->addWidget (beacons_table_view_);
|
||||||
|
|
||||||
|
decodes_stack_->addWidget (decodes_page);
|
||||||
|
decodes_stack_->addWidget (beacons_page);
|
||||||
|
|
||||||
|
// stack alternative views
|
||||||
|
auto content_layout = new QVBoxLayout;
|
||||||
|
content_layout->setContentsMargins (QMargins {2, 2, 2, 2});
|
||||||
|
content_layout->addLayout (decodes_stack_);
|
||||||
|
|
||||||
|
// set up controls
|
||||||
|
auto control_button_box = new QDialogButtonBox;
|
||||||
|
control_button_box->addButton (auto_off_button_, QDialogButtonBox::ActionRole);
|
||||||
|
control_button_box->addButton (halt_tx_button_, QDialogButtonBox::ActionRole);
|
||||||
|
connect (auto_off_button_, &QAbstractButton::clicked, [this] (bool /* checked */) {
|
||||||
|
Q_EMIT do_halt_tx (id_, true);
|
||||||
|
});
|
||||||
|
connect (halt_tx_button_, &QAbstractButton::clicked, [this] (bool /* checked */) {
|
||||||
|
Q_EMIT do_halt_tx (id_, false);
|
||||||
|
});
|
||||||
|
content_layout->addWidget (control_button_box);
|
||||||
|
|
||||||
|
// set up status area
|
||||||
|
auto status_bar = new QStatusBar;
|
||||||
|
status_bar->addPermanentWidget (de_label_);
|
||||||
|
status_bar->addPermanentWidget (mode_label_);
|
||||||
|
status_bar->addPermanentWidget (frequency_label_);
|
||||||
|
status_bar->addPermanentWidget (dx_label_);
|
||||||
|
status_bar->addPermanentWidget (rx_df_label_);
|
||||||
|
status_bar->addPermanentWidget (tx_df_label_);
|
||||||
|
status_bar->addPermanentWidget (report_label_);
|
||||||
|
content_layout->addWidget (status_bar);
|
||||||
|
connect (this, &ClientWidget::topLevelChanged, status_bar, &QStatusBar::setSizeGripEnabled);
|
||||||
|
|
||||||
|
// set up central widget
|
||||||
|
auto content_widget = new QFrame;
|
||||||
|
content_widget->setFrameStyle (QFrame::StyledPanel | QFrame::Sunken);
|
||||||
|
content_widget->setLayout (content_layout);
|
||||||
|
setWidget (content_widget);
|
||||||
|
// setMinimumSize (QSize {550, 0});
|
||||||
|
setFeatures (DockWidgetMovable | DockWidgetFloatable);
|
||||||
|
setAllowedAreas (Qt::BottomDockWidgetArea);
|
||||||
|
setFloating (true);
|
||||||
|
|
||||||
|
// connect up table view signals
|
||||||
|
connect (decodes_table_view_, &QTableView::doubleClicked, this, [this] (QModelIndex const& index) {
|
||||||
|
Q_EMIT do_reply (decodes_proxy_model_.mapToSource (index), QApplication::keyboardModifiers () >> 24);
|
||||||
|
});
|
||||||
|
|
||||||
|
// tell new client about calls of interest
|
||||||
|
for (int row = 0; row < calls_of_interest_->count (); ++row)
|
||||||
|
{
|
||||||
|
Q_EMIT highlight_callsign (id_, calls_of_interest_->item (row)->text (), QColor {Qt::blue}, QColor {Qt::yellow});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ClientWidget::~ClientWidget ()
|
||||||
|
{
|
||||||
|
for (int row = 0; row < calls_of_interest_->count (); ++row)
|
||||||
|
{
|
||||||
|
// tell client to forget calls of interest
|
||||||
|
Q_EMIT highlight_callsign (id_, calls_of_interest_->item (row)->text ());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClientWidget::update_status (QString const& id, Frequency f, QString const& mode, QString const& dx_call
|
||||||
|
, QString const& report, QString const& tx_mode, bool tx_enabled
|
||||||
|
, bool transmitting, bool decoding, qint32 rx_df, qint32 tx_df
|
||||||
|
, QString const& de_call, QString const& de_grid, QString const& dx_grid
|
||||||
|
, bool watchdog_timeout, QString const& sub_mode, bool fast_mode)
|
||||||
|
{
|
||||||
|
if (id == id_)
|
||||||
|
{
|
||||||
|
fast_mode_ = fast_mode;
|
||||||
|
decodes_proxy_model_.de_call (de_call);
|
||||||
|
decodes_proxy_model_.rx_df (rx_df);
|
||||||
|
de_label_->setText (de_call.size () >= 0 ? QString {"DE: %1%2"}.arg (de_call)
|
||||||
|
.arg (de_grid.size () ? '(' + de_grid + ')' : QString {}) : QString {});
|
||||||
|
mode_label_->setText (QString {"Mode: %1%2%3%4"}
|
||||||
|
.arg (mode)
|
||||||
|
.arg (sub_mode)
|
||||||
|
.arg (fast_mode && !mode.contains (QRegularExpression {R"(ISCAT|MSK144)"}) ? "fast" : "")
|
||||||
|
.arg (tx_mode.isEmpty () || tx_mode == mode ? "" : '(' + tx_mode + ')'));
|
||||||
|
frequency_label_->setText ("QRG: " + Radio::pretty_frequency_MHz_string (f));
|
||||||
|
dx_label_->setText (dx_call.size () >= 0 ? QString {"DX: %1%2"}.arg (dx_call)
|
||||||
|
.arg (dx_grid.size () ? '(' + dx_grid + ')' : QString {}) : QString {});
|
||||||
|
rx_df_label_->setText (rx_df >= 0 ? QString {"Rx: %1"}.arg (rx_df) : "");
|
||||||
|
tx_df_label_->setText (tx_df >= 0 ? QString {"Tx: %1"}.arg (tx_df) : "");
|
||||||
|
report_label_->setText ("SNR: " + report);
|
||||||
|
update_dynamic_property (frequency_label_, "transmitting", transmitting);
|
||||||
|
auto_off_button_->setEnabled (tx_enabled);
|
||||||
|
halt_tx_button_->setEnabled (transmitting);
|
||||||
|
update_dynamic_property (mode_label_, "decoding", decoding);
|
||||||
|
update_dynamic_property (tx_df_label_, "watchdog_timeout", watchdog_timeout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClientWidget::decode_added (bool /*is_new*/, QString const& client_id, QTime /*time*/, qint32 /*snr*/
|
||||||
|
, float /*delta_time*/, quint32 /*delta_frequency*/, QString const& /*mode*/
|
||||||
|
, QString const& /*message*/, bool /*low_confidence*/, bool /*off_air*/)
|
||||||
|
{
|
||||||
|
if (client_id == id_ && !columns_resized_)
|
||||||
|
{
|
||||||
|
decodes_stack_->setCurrentIndex (0);
|
||||||
|
decodes_table_view_->resizeColumnsToContents ();
|
||||||
|
columns_resized_ = true;
|
||||||
|
}
|
||||||
|
decodes_table_view_->scrollToBottom ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClientWidget::beacon_spot_added (bool /*is_new*/, QString const& client_id, QTime /*time*/, qint32 /*snr*/
|
||||||
|
, float /*delta_time*/, Frequency /*delta_frequency*/, qint32 /*drift*/
|
||||||
|
, QString const& /*callsign*/, QString const& /*grid*/, qint32 /*power*/
|
||||||
|
, bool /*off_air*/)
|
||||||
|
{
|
||||||
|
if (client_id == id_ && !columns_resized_)
|
||||||
|
{
|
||||||
|
decodes_stack_->setCurrentIndex (1);
|
||||||
|
beacons_table_view_->resizeColumnsToContents ();
|
||||||
|
columns_resized_ = true;
|
||||||
|
}
|
||||||
|
beacons_table_view_->scrollToBottom ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClientWidget::clear_decodes (QString const& client_id)
|
||||||
|
{
|
||||||
|
if (client_id == id_)
|
||||||
|
{
|
||||||
|
columns_resized_ = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "moc_ClientWidget.cpp"
|
||||||
@@ -0,0 +1,243 @@
|
|||||||
|
set (LANGUAGES
|
||||||
|
en
|
||||||
|
)
|
||||||
|
|
||||||
|
set (common_SRCS
|
||||||
|
common/communication.adoc
|
||||||
|
common/license.adoc
|
||||||
|
common/links.adoc
|
||||||
|
)
|
||||||
|
|
||||||
|
set (UG_SRCS
|
||||||
|
docinfo.html
|
||||||
|
docinfo.xml
|
||||||
|
acknowledgements.adoc
|
||||||
|
astro_data.adoc
|
||||||
|
config-details.adoc
|
||||||
|
controls-functions-center.adoc
|
||||||
|
controls-functions-left.adoc
|
||||||
|
controls-functions-main-window.adoc
|
||||||
|
controls-functions-menus.adoc
|
||||||
|
controls-functions-messages.adoc
|
||||||
|
controls-functions-status-bar.adoc
|
||||||
|
controls-functions-wide-graph.adoc
|
||||||
|
cooperating-programs.adoc
|
||||||
|
decoder_notes.adoc
|
||||||
|
faq.adoc
|
||||||
|
font-sizes.adoc
|
||||||
|
install-from-source.adoc
|
||||||
|
install-linux.adoc
|
||||||
|
install-mac.adoc
|
||||||
|
install-windows.adoc
|
||||||
|
introduction.adoc
|
||||||
|
measurement_tools.adoc
|
||||||
|
protocols.adoc
|
||||||
|
logging.adoc
|
||||||
|
make-qso.adoc
|
||||||
|
measurement_tools.adoc
|
||||||
|
new_features.adoc
|
||||||
|
platform-dependencies.adoc
|
||||||
|
protocols.adoc
|
||||||
|
settings-advanced.adoc
|
||||||
|
settings-audio.adoc
|
||||||
|
settings-colors.adoc
|
||||||
|
settings-frequencies.adoc
|
||||||
|
settings-general.adoc
|
||||||
|
settings-radio.adoc
|
||||||
|
settings-reporting.adoc
|
||||||
|
settings-txmacros.adoc
|
||||||
|
support.adoc
|
||||||
|
system-requirements.adoc
|
||||||
|
transceiver-setup.adoc
|
||||||
|
tutorial-example1.adoc
|
||||||
|
tutorial-example2.adoc
|
||||||
|
tutorial-example3.adoc
|
||||||
|
tutorial-main-window.adoc
|
||||||
|
tutorial-wide-graph-settings.adoc
|
||||||
|
utilities.adoc
|
||||||
|
vhf-features.adoc
|
||||||
|
wsjtx-main.adoc
|
||||||
|
wspr.adoc
|
||||||
|
)
|
||||||
|
|
||||||
|
set (UG_IMGS
|
||||||
|
images/130610_2343-wav-80.png
|
||||||
|
images/170709_135615.wav.png
|
||||||
|
images/AstroData_2.png
|
||||||
|
images/Astronomical_data.png
|
||||||
|
images/auto-seq.png
|
||||||
|
images/band-settings.png
|
||||||
|
images/colors.png
|
||||||
|
images/config-menu.png
|
||||||
|
images/decode-menu.png
|
||||||
|
images/decodes.png
|
||||||
|
images/download_samples.png
|
||||||
|
images/echo_144.png
|
||||||
|
images/file-menu.png
|
||||||
|
images/FreqCal.png
|
||||||
|
images/FreqCal_Graph.png
|
||||||
|
images/FreqCal_Results.png
|
||||||
|
images/freemsg.png
|
||||||
|
images/ft8_decodes.png
|
||||||
|
images/help-menu.png
|
||||||
|
images/JT4F.png
|
||||||
|
images/JT65B.png
|
||||||
|
images/keyboard-shortcuts.png
|
||||||
|
images/MSK144.png
|
||||||
|
images/QRA64.png
|
||||||
|
images/WSPR_WideGraphControls.png
|
||||||
|
images/WSPR_1a.png
|
||||||
|
images/WSPR_2.png
|
||||||
|
images/jtalert.png
|
||||||
|
images/keyboard-shortcuts.png
|
||||||
|
images/log-qso.png
|
||||||
|
images/MacAppMenu.png
|
||||||
|
images/main-ui.png
|
||||||
|
images/main-ui-controls.png
|
||||||
|
images/misc-controls-center.png
|
||||||
|
images/misc-main-ui.png
|
||||||
|
images/mode-menu.png
|
||||||
|
images/new-msg-box.png
|
||||||
|
images/psk-reporter.png
|
||||||
|
images/r3666-config-screen-80.png
|
||||||
|
images/r3666-main-ui-80.png
|
||||||
|
images/r4148-txmac-ui.png
|
||||||
|
images/RadioTab.png
|
||||||
|
images/reporting.png
|
||||||
|
images/save-menu.png
|
||||||
|
images/settings-advanced.png
|
||||||
|
images/settings-audio.png
|
||||||
|
images/settings-frequencies.png
|
||||||
|
images/settings-general.png
|
||||||
|
images/setup-menu.png
|
||||||
|
images/special-mouse-commands.png
|
||||||
|
images/status-bar-a.png
|
||||||
|
images/tools-menu.png
|
||||||
|
images/traditional-msg-box.png
|
||||||
|
images/tx-macros.png
|
||||||
|
images/VHF_controls.png
|
||||||
|
images/view-menu.png
|
||||||
|
images/wide-graph-controls.png
|
||||||
|
|
||||||
|
)
|
||||||
|
|
||||||
|
find_program (ASCIIDOCTOR_EXECUTABLE NAMES asciidoctor)
|
||||||
|
if (NOT ASCIIDOCTOR_EXECUTABLE)
|
||||||
|
message (FATAL_ERROR "asciidoctor is required to build the documentation
|
||||||
|
|
||||||
|
Building the documenation may optionally be turned off by setting the CMake
|
||||||
|
option WSJT_GENERATE_DOCS to OFF.")
|
||||||
|
endif (NOT ASCIIDOCTOR_EXECUTABLE)
|
||||||
|
|
||||||
|
find_program (FOPUB_EXECUTABLE NAMES fopub)
|
||||||
|
|
||||||
|
include (CMakeParseArguments)
|
||||||
|
|
||||||
|
# generate a document from asciidoc text files(s)
|
||||||
|
#
|
||||||
|
# HTML - generate an HTML document
|
||||||
|
# PDF - generate a PDF document
|
||||||
|
# SOURCE - top level asciidoc file
|
||||||
|
# ASCIIDOCTOR_OPTIONS - asciidoctor command options
|
||||||
|
# DEPENDS - dependent files
|
||||||
|
function (document)
|
||||||
|
cmake_parse_arguments (_args "HTML" "SOURCE;LANG;OUTPUT" "ASCIIDOCTOR_OPTIONS;PDF;DEPENDS" ${ARGN})
|
||||||
|
get_filename_component (_source_path ${_args_SOURCE} PATH)
|
||||||
|
get_filename_component (_source_name ${_args_SOURCE} NAME)
|
||||||
|
get_filename_component (_output_name_we ${_args_SOURCE} NAME_WE)
|
||||||
|
|
||||||
|
# HTML
|
||||||
|
if (${_args_HTML})
|
||||||
|
set (_html_file ${CMAKE_CURRENT_BINARY_DIR}/${_output_name_we}_${lang}.html)
|
||||||
|
add_custom_command (
|
||||||
|
OUTPUT ${_html_file}
|
||||||
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${_source_path}/${lang}
|
||||||
|
COMMAND ${ASCIIDOCTOR_EXECUTABLE} ${_args_ASCIIDOCTOR_OPTIONS}
|
||||||
|
-b html5
|
||||||
|
-a VERSION_MAJOR=${WSJTX_VERSION_MAJOR}
|
||||||
|
-a VERSION_MINOR=${WSJTX_VERSION_MINOR}
|
||||||
|
-a VERSION_PATCH=${WSJTX_VERSION_PATCH}
|
||||||
|
-a VERSION=${wsjtx_VERSION}
|
||||||
|
--out-file=${_html_file} ${_source_name}
|
||||||
|
DEPENDS ${_args_DEPENDS}
|
||||||
|
COMMENT "Generating ${_html_file}"
|
||||||
|
)
|
||||||
|
list (APPEND _output_files ${_html_file})
|
||||||
|
endif (${_args_HTML})
|
||||||
|
|
||||||
|
# PDF
|
||||||
|
if (_args_PDF AND EXISTS ${FOPUB_EXECUTABLE})
|
||||||
|
set (_docbook_file ${CMAKE_CURRENT_BINARY_DIR}/${_output_name_we}_${lang}.xml)
|
||||||
|
set (_pdf_file_we ${CMAKE_CURRENT_BINARY_DIR}/${_output_name_we}_${lang})
|
||||||
|
if (${lang} MATCHES "^(en|es|fr)$") # en-us, fr-ca and es-{mx,co} use US-Letter or equivalent
|
||||||
|
set (_usl_commands
|
||||||
|
COMMAND ${FOPUB_EXECUTABLE} ARGS ${_docbook_file} ${_args_PDF} -param paper.type USLetter
|
||||||
|
COMMAND ${CMAKE_COMMAND} ARGS -E rename ${_pdf_file_we}.pdf '${_pdf_file_we} \(USLetter\).pdf'
|
||||||
|
)
|
||||||
|
list (APPEND _output_files "${_pdf_file_we} (USLetter).pdf")
|
||||||
|
endif ()
|
||||||
|
list (APPEND _output_files "${_pdf_file_we}.pdf")
|
||||||
|
add_custom_command (
|
||||||
|
OUTPUT ${_docbook_file} ${_output_files}
|
||||||
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${_source_path}/${lang}
|
||||||
|
COMMAND ${ASCIIDOCTOR_EXECUTABLE} ARGS ${_args_ASCIIDOCTOR_OPTIONS}
|
||||||
|
-b docbook
|
||||||
|
-a data-uri!
|
||||||
|
-a VERSION_MAJOR=${WSJTX_VERSION_MAJOR}
|
||||||
|
-a VERSION_MINOR=${WSJTX_VERSION_MINOR}
|
||||||
|
-a VERSION_PATCH=${WSJTX_VERSION_PATCH}
|
||||||
|
-a VERSION=${wsjtx_VERSION}
|
||||||
|
-D ${CMAKE_CURRENT_BINARY_DIR}
|
||||||
|
-o ${_docbook_file} ${_source_name}
|
||||||
|
${_usl_commands}
|
||||||
|
COMMAND ${FOPUB_EXECUTABLE} ARGS ${_docbook_file} ${_args_PDF} -param paper.type A4
|
||||||
|
COMMAND ${CMAKE_COMMAND} ARGS -E rename ${_pdf_file_we}.pdf '${_pdf_file_we}.pdf'
|
||||||
|
DEPENDS ${_args_DEPENDS}
|
||||||
|
COMMENT "Generating ${_output_files}"
|
||||||
|
)
|
||||||
|
endif (_args_PDF AND EXISTS ${FOPUB_EXECUTABLE})
|
||||||
|
|
||||||
|
set (${_args_OUTPUT} ${_output_files} PARENT_SCOPE)
|
||||||
|
endfunction (document)
|
||||||
|
|
||||||
|
set (htmls)
|
||||||
|
set (pdfs)
|
||||||
|
foreach (lang ${LANGUAGES})
|
||||||
|
set (_sources)
|
||||||
|
foreach (_src ${UG_SRCS} ${UG_IMGS})
|
||||||
|
list (APPEND _sources "user_guide/${lang}/${_src}")
|
||||||
|
endforeach ()
|
||||||
|
document(
|
||||||
|
HTML
|
||||||
|
SOURCE user_guide/wsjtx-main.adoc
|
||||||
|
LANG "${lang}"
|
||||||
|
OUTPUT html
|
||||||
|
ASCIIDOCTOR_OPTIONS -d book -a data-uri -a toc=left -a max-width=1024px
|
||||||
|
DEPENDS ${common_SRCS} ${_sources}
|
||||||
|
)
|
||||||
|
document(
|
||||||
|
PDF -param body.font.master 11 -param body.font.family "'Noto Sans, Helvetica, sans-serif'" -param title.font.family "'Noto Serif, Times New Roman, serif'" -param page.margin.inner 1cm -param page.margin.outer 1cm -param page.margin.top 0.75cm -param page.margin.bottom 0.5cm -param generate.toc 0
|
||||||
|
SOURCE user_guide/wsjtx-main.adoc
|
||||||
|
LANG "${lang}"
|
||||||
|
OUTPUT pdf
|
||||||
|
ASCIIDOCTOR_OPTIONS -d book
|
||||||
|
DEPENDS ${common_SRCS} ${_sources}
|
||||||
|
)
|
||||||
|
list (APPEND htmls "${html}")
|
||||||
|
list (APPEND pdfs "${pdf}")
|
||||||
|
endforeach ()
|
||||||
|
|
||||||
|
add_custom_target (docs ALL DEPENDS ${htmls} ${pdfs})
|
||||||
|
|
||||||
|
foreach (_html ${htmls})
|
||||||
|
get_filename_component (_path ${_html} PATH)
|
||||||
|
get_filename_component (_nwe ${_html} NAME_WE)
|
||||||
|
get_filename_component (_ext ${_html} EXT)
|
||||||
|
string (REGEX REPLACE "_en$" "" _nwe ${_nwe})
|
||||||
|
install (FILES
|
||||||
|
${_html}
|
||||||
|
DESTINATION ${CMAKE_INSTALL_DOCDIR}
|
||||||
|
RENAME ${_nwe}-${wsjtx_VERSION}${_ext}
|
||||||
|
#COMPONENT runtime
|
||||||
|
)
|
||||||
|
endforeach ()
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
#
|
||||||
|
# Internal file for GetGitRevisionDescription.cmake
|
||||||
|
#
|
||||||
|
# Requires CMake 2.6 or newer (uses the 'function' command)
|
||||||
|
#
|
||||||
|
# Original Author:
|
||||||
|
# 2009-2010 Ryan Pavlik <rpavlik@iastate.edu> <abiryan@ryand.net>
|
||||||
|
# http://academic.cleardefinition.com
|
||||||
|
# Iowa State University HCI Graduate Program/VRAC
|
||||||
|
#
|
||||||
|
# Copyright Iowa State University 2009-2010.
|
||||||
|
# Distributed under the Boost Software License, Version 1.0.
|
||||||
|
# (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
# http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
|
||||||
|
set(HEAD_HASH)
|
||||||
|
|
||||||
|
file(READ "@HEAD_FILE@" HEAD_CONTENTS LIMIT 1024)
|
||||||
|
|
||||||
|
string(STRIP "${HEAD_CONTENTS}" HEAD_CONTENTS)
|
||||||
|
if(HEAD_CONTENTS MATCHES "ref")
|
||||||
|
# named branch
|
||||||
|
string(REPLACE "ref: " "" HEAD_REF "${HEAD_CONTENTS}")
|
||||||
|
if(EXISTS "@GIT_DIR@/${HEAD_REF}")
|
||||||
|
configure_file("@GIT_DIR@/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY)
|
||||||
|
else()
|
||||||
|
configure_file("@GIT_DIR@/packed-refs" "@GIT_DATA@/packed-refs" COPYONLY)
|
||||||
|
file(READ "@GIT_DATA@/packed-refs" PACKED_REFS)
|
||||||
|
if(${PACKED_REFS} MATCHES "([0-9a-z]*) ${HEAD_REF}")
|
||||||
|
set(HEAD_HASH "${CMAKE_MATCH_1}")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
# detached HEAD
|
||||||
|
configure_file("@GIT_DIR@/HEAD" "@GIT_DATA@/head-ref" COPYONLY)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT HEAD_HASH)
|
||||||
|
file(READ "@GIT_DATA@/head-ref" HEAD_HASH LIMIT 1024)
|
||||||
|
string(STRIP "${HEAD_HASH}" HEAD_HASH)
|
||||||
|
endif()
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
128
|
|
||||||
48
|
|
||||||
12
|
|
||||||
1 13 26 38 51 62 75 86 99 111 124 0
|
|
||||||
2 13 27 39 49 63 76 87 100 112 121 0
|
|
||||||
3 14 27 40 52 64 74 88 101 104 123 0
|
|
||||||
2 15 28 41 53 65 77 89 102 113 125 0
|
|
||||||
4 16 26 41 54 66 71 90 101 114 122 0
|
|
||||||
5 15 29 40 55 67 78 91 98 110 126 0
|
|
||||||
6 17 30 42 56 63 79 90 103 115 124 0
|
|
||||||
7 18 25 43 56 68 80 87 104 113 122 0
|
|
||||||
7 13 29 44 52 69 81 92 102 114 127 0
|
|
||||||
8 14 29 42 57 66 77 86 97 116 119 0
|
|
||||||
9 19 26 45 56 69 76 93 97 110 128 0
|
|
||||||
9 14 28 46 54 68 82 91 99 112 118 0
|
|
||||||
8 20 31 47 49 69 78 88 105 109 124 0
|
|
||||||
1 20 32 42 52 70 76 94 106 117 0 0
|
|
||||||
10 15 33 48 52 62 80 93 100 118 119 0
|
|
||||||
11 18 31 39 48 67 83 94 97 114 125 0
|
|
||||||
12 15 34 37 49 64 73 85 99 116 127 0
|
|
||||||
2 21 25 45 55 64 83 92 103 119 0 0
|
|
||||||
4 22 33 46 55 65 84 86 107 108 0 0
|
|
||||||
11 16 27 45 53 70 79 95 107 111 126 0
|
|
||||||
6 13 33 45 57 68 85 96 101 120 0 0
|
|
||||||
12 17 25 38 58 67 76 96 107 118 123 0
|
|
||||||
5 18 30 44 59 71 77 93 106 120 0 0
|
|
||||||
6 20 28 43 50 72 83 86 95 121 127 0
|
|
||||||
11 23 28 38 59 73 81 88 108 115 0 0
|
|
||||||
10 19 32 49 60 67 75 89 101 108 0 0
|
|
||||||
5 22 27 48 54 69 73 96 103 113 0 0
|
|
||||||
12 23 35 47 50 62 79 97 106 122 0 0
|
|
||||||
3 18 26 47 53 61 82 85 98 108 0 0
|
|
||||||
9 22 31 41 58 60 72 87 106 115 116 0
|
|
||||||
10 16 30 50 58 65 73 91 104 109 0 0
|
|
||||||
10 24 36 41 57 61 78 94 103 111 123 127
|
|
||||||
4 17 29 43 59 74 85 89 109 112 128 0
|
|
||||||
3 21 34 38 60 63 77 95 105 114 128 0
|
|
||||||
7 24 37 46 53 71 74 96 105 110 0 0
|
|
||||||
6 19 34 47 51 70 81 91 100 123 125 0
|
|
||||||
2 24 31 40 56 66 81 84 95 118 120 0
|
|
||||||
1 14 30 37 48 72 78 92 107 122 128 0
|
|
||||||
3 23 24 42 55 68 75 93 109 121 125 0
|
|
||||||
12 22 32 43 51 71 82 88 102 119 126 0
|
|
||||||
1 23 36 44 58 64 80 90 110 112 0 0
|
|
||||||
7 19 35 40 59 65 82 90 111 117 0 0
|
|
||||||
9 17 36 39 50 66 75 92 105 117 126 0
|
|
||||||
4 21 35 39 57 70 80 98 99 115 0 0
|
|
||||||
8 25 33 37 54 60 79 94 98 121 0 0
|
|
||||||
8 16 34 46 61 62 83 87 102 117 120 0
|
|
||||||
11 21 32 44 61 72 74 84 100 113 124 0
|
|
||||||
5 20 35 36 51 63 84 89 104 116 0 0
|
|
||||||
@@ -0,0 +1,160 @@
|
|||||||
|
/*
|
||||||
|
#Sov Mil Order of Malta: 15: 28: EU: 41.90: -12.43: -1.0: 1A:
|
||||||
|
#1A;
|
||||||
|
#Spratly Islands: 26: 50: AS: 9.88: -114.23: -8.0: 1S:
|
||||||
|
#1S,9M0,BV9S;
|
||||||
|
#Monaco: 14: 27: EU: 43.73: -7.40: -1.0: 3A:
|
||||||
|
#3A;
|
||||||
|
#Heard Island: 39: 68: AF: -53.08: -73.50: -5.0: VK0H:
|
||||||
|
#=VK0IR;
|
||||||
|
#Macquarie Island: 30: 60: OC: -54.60: -158.88: -10.0: VK0M:
|
||||||
|
#=VK0KEV;
|
||||||
|
#Cocos-Keeling: 29: 54: OC: -12.15: -96.82: -6.5: VK9C:
|
||||||
|
#AX9C,AX9Y,VH9C,VH9Y,VI9C,VI9Y,VJ9C,VJ9Y,VK9C,VK9Y,VL9C,VL9Y,VM9C,VM9Y,
|
||||||
|
#VN9C,VN9Y,VZ9C,VZ9Y,=VK9AA;
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "countrydat.h"
|
||||||
|
#include <QFile>
|
||||||
|
#include <QTextStream>
|
||||||
|
#include <QDebug>
|
||||||
|
#include "Radio.hpp"
|
||||||
|
|
||||||
|
void CountryDat::init(const QString filename)
|
||||||
|
{
|
||||||
|
_filename = filename;
|
||||||
|
_data.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString CountryDat::_extractName(const QString line) const
|
||||||
|
{
|
||||||
|
int s1 = line.indexOf(':');
|
||||||
|
if (s1>=0)
|
||||||
|
{
|
||||||
|
QString name = line.mid(0,s1);
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
void CountryDat::_removeBrackets(QString &line, const QString a, const QString b) const
|
||||||
|
{
|
||||||
|
int s1 = line.indexOf(a);
|
||||||
|
while (s1 >= 0)
|
||||||
|
{
|
||||||
|
int s2 = line.indexOf(b);
|
||||||
|
line = line.mid(0,s1) + line.mid(s2+1,-1);
|
||||||
|
s1 = line.indexOf(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList CountryDat::_extractPrefix(QString &line, bool &more) const
|
||||||
|
{
|
||||||
|
line = line.remove(" \n");
|
||||||
|
line = line.replace(" ","");
|
||||||
|
|
||||||
|
_removeBrackets(line,"(",")");
|
||||||
|
_removeBrackets(line,"[","]");
|
||||||
|
_removeBrackets(line,"<",">");
|
||||||
|
_removeBrackets(line,"~","~");
|
||||||
|
|
||||||
|
int s1 = line.indexOf(';');
|
||||||
|
more = true;
|
||||||
|
if (s1 >= 0)
|
||||||
|
{
|
||||||
|
line = line.mid(0,s1);
|
||||||
|
more = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList r = line.split(',');
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CountryDat::load()
|
||||||
|
{
|
||||||
|
_data.clear();
|
||||||
|
_countryNames.clear(); //used by countriesWorked
|
||||||
|
|
||||||
|
QFile inputFile(_filename);
|
||||||
|
if (inputFile.open(QIODevice::ReadOnly))
|
||||||
|
{
|
||||||
|
QTextStream in(&inputFile);
|
||||||
|
while ( !in.atEnd() )
|
||||||
|
{
|
||||||
|
QString line1 = in.readLine();
|
||||||
|
if ( !in.atEnd() )
|
||||||
|
{
|
||||||
|
QString line2 = in.readLine();
|
||||||
|
|
||||||
|
QString name = _extractName(line1);
|
||||||
|
if (name.length()>0)
|
||||||
|
{
|
||||||
|
QString continent=line1.mid(36,2);
|
||||||
|
QString principalPrefix=line1.mid(69,4);
|
||||||
|
int i1=principalPrefix.indexOf(":");
|
||||||
|
if(i1>0) principalPrefix=principalPrefix.mid(0,i1);
|
||||||
|
name += "; " + principalPrefix + "; " + continent;
|
||||||
|
_countryNames << name;
|
||||||
|
bool more = true;
|
||||||
|
QStringList prefixs;
|
||||||
|
while (more)
|
||||||
|
{
|
||||||
|
QStringList p = _extractPrefix(line2,more);
|
||||||
|
prefixs += p;
|
||||||
|
if (more)
|
||||||
|
line2 = in.readLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString p;
|
||||||
|
foreach(p,prefixs)
|
||||||
|
{
|
||||||
|
if (p.length() > 0)
|
||||||
|
_data.insert(p,name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inputFile.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// return country name else ""
|
||||||
|
QString CountryDat::find(QString call) const
|
||||||
|
{
|
||||||
|
call = call.toUpper ();
|
||||||
|
|
||||||
|
// check for exact match first
|
||||||
|
if (_data.contains ("=" + call))
|
||||||
|
{
|
||||||
|
return fixup (_data.value ("=" + call), call);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto prefix = Radio::effective_prefix (call);
|
||||||
|
auto match_candidate = prefix;
|
||||||
|
while (match_candidate.size () >= 1)
|
||||||
|
{
|
||||||
|
if (_data.contains (match_candidate))
|
||||||
|
{
|
||||||
|
return fixup (_data.value (match_candidate), prefix);
|
||||||
|
}
|
||||||
|
match_candidate = match_candidate.left (match_candidate.size () - 1);
|
||||||
|
}
|
||||||
|
return QString {};
|
||||||
|
}
|
||||||
|
|
||||||
|
QString CountryDat::fixup (QString country, QString const& call) const
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// deal with special rules that cty.dat does not cope with
|
||||||
|
//
|
||||||
|
|
||||||
|
// KG4 2x1 and 2x3 calls that map to Gitmo are mainland US not Gitmo
|
||||||
|
if (call.startsWith ("KG4") && call.size () != 5 && call.size () != 3)
|
||||||
|
{
|
||||||
|
country.replace ("Guantanamo Bay; KG4; NA", "United States; K; NA");
|
||||||
|
}
|
||||||
|
return country;
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
subroutine packprop(k,muf,ccur,cxp,n1)
|
||||||
|
|
||||||
|
! Pack propagation indicators into a 21-bit number.
|
||||||
|
|
||||||
|
! k k-index, 0-9; 10="N/A"
|
||||||
|
! muf muf, 2-60 MHz; 0=N/A, 1="none", 61=">60 MHz"
|
||||||
|
! ccur up to two current events, each indicated by single
|
||||||
|
! or double letter.
|
||||||
|
! cxp zero or one expected event, indicated by single or
|
||||||
|
! double letter
|
||||||
|
|
||||||
|
character ccur*4,cxp*2
|
||||||
|
|
||||||
|
j=ichar(ccur(1:1))-64
|
||||||
|
if(j.lt.0) j=0
|
||||||
|
n1=j
|
||||||
|
do i=2,4
|
||||||
|
if(ccur(i:i).eq.' ') go to 10
|
||||||
|
if(ccur(i:i).eq.ccur(i-1:i-1)) then
|
||||||
|
n1=n1+26
|
||||||
|
else
|
||||||
|
j=ichar(ccur(i:i))-64
|
||||||
|
if(j.lt.0) j=0
|
||||||
|
n1=53*n1 + j
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
|
||||||
|
10 j=ichar(cxp(1:1))-64
|
||||||
|
if(j.lt.0) j=0
|
||||||
|
if(cxp(2:2).eq.cxp(1:1)) j=j+26
|
||||||
|
n1=53*n1 + j
|
||||||
|
n1=11*n1 + k
|
||||||
|
n1=62*n1 + muf
|
||||||
|
|
||||||
|
return
|
||||||
|
end subroutine packprop
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
# Copyright (C) 2002-2003 David Abrahams.
|
||||||
|
# Copyright (C) 2002-2003 Vladimir Prus.
|
||||||
|
# Copyright (C) 2003,2007 Rene Rivera.
|
||||||
|
# Use, modification and distribution are subject to the
|
||||||
|
# Boost Software License, Version 1.0. (See accompanying file
|
||||||
|
# LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
|
||||||
|
# This is the initial file loaded by Boost Jam when run from any Boost library
|
||||||
|
# folder. It allows us to choose which Boost Build installation to use for
|
||||||
|
# building Boost libraries. Unless explicitly selected using a command-line
|
||||||
|
# option, the version included with the Boost library distribution is used (as
|
||||||
|
# opposed to any other Boost Build version installed on the user's sytem).
|
||||||
|
|
||||||
|
BOOST_ROOT = $(.boost-build-file:D) ;
|
||||||
|
BOOST_BUILD = [ MATCH --boost-build=(.*) : $(ARGV) ] ;
|
||||||
|
BOOST_BUILD ?= tools/build/src ;
|
||||||
|
boost-build $(BOOST_BUILD) ;
|
||||||
@@ -0,0 +1,148 @@
|
|||||||
|
subroutine foxgen()
|
||||||
|
|
||||||
|
! Called from MainWindow::foxTxSequencer() to generate the Tx waveform in
|
||||||
|
! FT8 Fox mode. The Tx message can contain up to 5 "slots", each carrying
|
||||||
|
! its own FT8 signal.
|
||||||
|
|
||||||
|
! Encoded messages can be of the form "HoundCall FoxCall rpt" (a standard FT8
|
||||||
|
! message with i3bit=0) or "HoundCall_1 RR73; HoundCall_2 <FoxCall> rpt",
|
||||||
|
! a new message type with i3bit=1. The waveform is generated with
|
||||||
|
! fsample=48000 Hz; it is compressed to reduce the PEP-to-average power ratio,
|
||||||
|
! with (currently disabled) filtering afterware to reduce spectral growth.
|
||||||
|
|
||||||
|
! Input message information is provided in character array cmsg(5), in
|
||||||
|
! common/foxcom/. The generated wave(NWAVE) is passed back in the same
|
||||||
|
! common block.
|
||||||
|
|
||||||
|
use crc
|
||||||
|
parameter (NN=79,ND=58,KK=87,NSPS=4*1920)
|
||||||
|
parameter (NWAVE=NN*NSPS,NFFT=614400,NH=NFFT/2)
|
||||||
|
character*40 cmsg
|
||||||
|
character*22 msg,msgsent
|
||||||
|
character*6 mygrid
|
||||||
|
character*87 cbits
|
||||||
|
character*88 cb88
|
||||||
|
logical bcontest
|
||||||
|
integer itone(NN)
|
||||||
|
integer icos7(0:6)
|
||||||
|
integer*1 msgbits(KK),codeword(3*ND),msgbits2
|
||||||
|
integer*1, target:: i1Msg8BitBytes(11)
|
||||||
|
integer*1, target:: mycall
|
||||||
|
real x(NFFT)
|
||||||
|
real*8 dt,twopi,f0,fstep,dfreq,phi,dphi
|
||||||
|
complex cx(0:NH)
|
||||||
|
common/foxcom/wave(NWAVE),nslots,nfreq,i3bit(5),cmsg(5),mycall(12)
|
||||||
|
common/foxcom2/itone2(NN),msgbits2(KK)
|
||||||
|
equivalence (x,cx),(y,cy)
|
||||||
|
data icos7/2,5,6,0,4,1,3/ !Costas 7x7 tone pattern
|
||||||
|
|
||||||
|
bcontest=.false.
|
||||||
|
fstep=60.d0
|
||||||
|
dfreq=6.25d0
|
||||||
|
dt=1.d0/48000.d0
|
||||||
|
twopi=8.d0*atan(1.d0)
|
||||||
|
mygrid=' '
|
||||||
|
irpt=0
|
||||||
|
nplot=0
|
||||||
|
wave=0.
|
||||||
|
|
||||||
|
do n=1,nslots
|
||||||
|
i3b=i3bit(n)
|
||||||
|
if(i3b.eq.0) then
|
||||||
|
msg=cmsg(n)(1:22) !Standard FT8 message
|
||||||
|
else
|
||||||
|
i1=index(cmsg(n),' ') !Special Fox message
|
||||||
|
i2=index(cmsg(n),';')
|
||||||
|
i3=index(cmsg(n),'<')
|
||||||
|
i4=index(cmsg(n),'>')
|
||||||
|
msg=cmsg(n)(1:i1)//cmsg(n)(i2+1:i3-2)//' '
|
||||||
|
read(cmsg(n)(i4+2:i4+4),*) irpt
|
||||||
|
endif
|
||||||
|
call genft8(msg,mygrid,bcontest,0,msgsent,msgbits,itone)
|
||||||
|
! print*,'Foxgen:',n,cmsg(n),msgsent
|
||||||
|
|
||||||
|
if(i3b.eq.1) then
|
||||||
|
icrc10=crc10(c_loc(mycall),12)
|
||||||
|
nrpt=irpt+30
|
||||||
|
write(cbits,1001) msgbits(1:56),icrc10,nrpt,i3b,0
|
||||||
|
1001 format(56b1.1,b10.10,b6.6,b3.3,b12.12)
|
||||||
|
read(cbits,1002) msgbits
|
||||||
|
1002 format(87i1)
|
||||||
|
|
||||||
|
cb88=cbits//'0'
|
||||||
|
read(cb88,1003) i1Msg8BitBytes(1:11)
|
||||||
|
1003 format(11b8)
|
||||||
|
icrc12=crc12(c_loc(i1Msg8BitBytes),11)
|
||||||
|
|
||||||
|
write(cbits,1001) msgbits(1:56),icrc10,nrpt,i3b,icrc12
|
||||||
|
read(cbits,1002) msgbits
|
||||||
|
|
||||||
|
call encode174(msgbits,codeword) !Encode the test message
|
||||||
|
|
||||||
|
! Message structure: S7 D29 S7 D29 S7
|
||||||
|
itone(1:7)=icos7
|
||||||
|
itone(36+1:36+7)=icos7
|
||||||
|
itone(NN-6:NN)=icos7
|
||||||
|
k=7
|
||||||
|
do j=1,ND
|
||||||
|
i=3*j -2
|
||||||
|
k=k+1
|
||||||
|
if(j.eq.30) k=k+7
|
||||||
|
itone(k)=codeword(i)*4 + codeword(i+1)*2 + codeword(i+2)
|
||||||
|
enddo
|
||||||
|
endif
|
||||||
|
|
||||||
|
! Make copies of itone() and msgbits() for ft8sim
|
||||||
|
itone2=itone
|
||||||
|
msgbits2=msgbits
|
||||||
|
f0=nfreq + fstep*(n-1)
|
||||||
|
phi=0.d0
|
||||||
|
k=0
|
||||||
|
do j=1,NN
|
||||||
|
f=f0 + dfreq*itone(j)
|
||||||
|
dphi=twopi*f*dt
|
||||||
|
do ii=1,NSPS
|
||||||
|
k=k+1
|
||||||
|
phi=phi+dphi
|
||||||
|
xphi=phi
|
||||||
|
wave(k)=wave(k)+sin(xphi)
|
||||||
|
enddo
|
||||||
|
enddo
|
||||||
|
enddo
|
||||||
|
kz=k
|
||||||
|
|
||||||
|
peak1=maxval(abs(wave))
|
||||||
|
wave=wave/peak1
|
||||||
|
! call plotspec(1,wave) !Plot the spectrum
|
||||||
|
|
||||||
|
! Apply compression
|
||||||
|
! rms=sqrt(dot_product(wave,wave)/kz)
|
||||||
|
! wave=wave/rms
|
||||||
|
! do i=1,NWAVE
|
||||||
|
! wave(i)=h1(wave(i))
|
||||||
|
! enddo
|
||||||
|
! peak2=maxval(abs(wave))
|
||||||
|
! wave=wave/peak2
|
||||||
|
|
||||||
|
! call plotspec(2,wave) !Plot the spectrum
|
||||||
|
|
||||||
|
width=50.0
|
||||||
|
call foxfilt(nslots,nfreq,width,wave)
|
||||||
|
peak3=maxval(abs(wave))
|
||||||
|
wave=wave/peak3
|
||||||
|
|
||||||
|
! nadd=1000
|
||||||
|
! j=0
|
||||||
|
! do i=1,NWAVE,nadd
|
||||||
|
! sx=dot_product(wave(i:i+nadd-1),wave(i:i+nadd-1))
|
||||||
|
! j=j+1
|
||||||
|
! write(30,3001) j,sx/nadd
|
||||||
|
!3001 format(i8,f12.6)
|
||||||
|
! enddo
|
||||||
|
|
||||||
|
! call plotspec(3,wave) !Plot the spectrum
|
||||||
|
|
||||||
|
return
|
||||||
|
end subroutine foxgen
|
||||||
|
|
||||||
|
! include 'plotspec.f90'
|
||||||
@@ -0,0 +1,119 @@
|
|||||||
|
// -*- Mode: C++ -*-
|
||||||
|
#ifndef WIDEGRAPH_H
|
||||||
|
#define WIDEGRAPH_H
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
|
#include <QScopedPointer>
|
||||||
|
#include <QDir>
|
||||||
|
#include <QHash>
|
||||||
|
#include <QVariant>
|
||||||
|
#include "WFPalette.hpp"
|
||||||
|
|
||||||
|
#define MAX_SCREENSIZE 2048
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class WideGraph;
|
||||||
|
}
|
||||||
|
|
||||||
|
class QSettings;
|
||||||
|
class Configuration;
|
||||||
|
|
||||||
|
class WideGraph : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit WideGraph(QSettings *, QWidget *parent = 0);
|
||||||
|
~WideGraph ();
|
||||||
|
|
||||||
|
void dataSink2(float s[], float df3, int ihsym, int ndiskdata);
|
||||||
|
void setRxFreq(int n);
|
||||||
|
int rxFreq();
|
||||||
|
int nStartFreq();
|
||||||
|
int Fmin();
|
||||||
|
int Fmax();
|
||||||
|
int fSpan();
|
||||||
|
void saveSettings();
|
||||||
|
void setFsample(int n);
|
||||||
|
void setPeriod(int ntrperiod, int nsps);
|
||||||
|
void setTxFreq(int n);
|
||||||
|
void setMode(QString mode);
|
||||||
|
void setSubMode(int n);
|
||||||
|
void setModeTx(QString modeTx);
|
||||||
|
bool flatten();
|
||||||
|
bool useRef();
|
||||||
|
void setTol(int n);
|
||||||
|
int smoothYellow();
|
||||||
|
void setRxBand (QString const& band);
|
||||||
|
void setWSPRtransmitted();
|
||||||
|
void drawRed(int ia, int ib);
|
||||||
|
void setVHF(bool bVHF);
|
||||||
|
void setRedFile(QString fRed);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void freezeDecode2(int n);
|
||||||
|
void f11f12(int n);
|
||||||
|
void setXIT2(int n);
|
||||||
|
void setFreq3(int rxFreq, int txFreq);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void wideFreezeDecode(int n);
|
||||||
|
void setFreq2(int rxFreq, int txFreq);
|
||||||
|
void setDialFreq(double d);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void keyPressEvent (QKeyEvent *e) override;
|
||||||
|
void closeEvent (QCloseEvent *) override;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void on_waterfallAvgSpinBox_valueChanged(int arg1);
|
||||||
|
void on_bppSpinBox_valueChanged(int arg1);
|
||||||
|
void on_spec2dComboBox_currentIndexChanged(const QString &arg1);
|
||||||
|
void on_fSplitSpinBox_valueChanged(int n);
|
||||||
|
void on_fStartSpinBox_valueChanged(int n);
|
||||||
|
void on_paletteComboBox_activated(const QString &palette);
|
||||||
|
void on_cbFlatten_toggled(bool b);
|
||||||
|
void on_cbRef_toggled(bool b);
|
||||||
|
void on_cbControls_toggled(bool b);
|
||||||
|
void on_adjust_palette_push_button_clicked (bool);
|
||||||
|
void on_gainSlider_valueChanged(int value);
|
||||||
|
void on_zeroSlider_valueChanged(int value);
|
||||||
|
void on_gain2dSlider_valueChanged(int value);
|
||||||
|
void on_zero2dSlider_valueChanged(int value);
|
||||||
|
void on_smoSpinBox_valueChanged(int n);
|
||||||
|
void on_sbPercent2dPlot_valueChanged(int n);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void readPalette ();
|
||||||
|
void setRxRange ();
|
||||||
|
void replot();
|
||||||
|
|
||||||
|
QScopedPointer<Ui::WideGraph> ui;
|
||||||
|
|
||||||
|
QSettings * m_settings;
|
||||||
|
QDir m_palettes_path;
|
||||||
|
WFPalette m_userPalette;
|
||||||
|
QHash<QString, QVariant> m_fMinPerBand;
|
||||||
|
|
||||||
|
qint32 m_waterfallAvg;
|
||||||
|
qint32 m_TRperiod;
|
||||||
|
qint32 m_nsps;
|
||||||
|
qint32 m_ntr0;
|
||||||
|
qint32 m_fMax;
|
||||||
|
qint32 m_nSubMode;
|
||||||
|
qint32 m_nsmo;
|
||||||
|
qint32 m_Percent2DScreen;
|
||||||
|
qint32 m_jz=MAX_SCREENSIZE;
|
||||||
|
qint32 m_n;
|
||||||
|
|
||||||
|
bool m_bFlatten;
|
||||||
|
bool m_bRef;
|
||||||
|
bool m_bHaveTransmitted; //Set true at end of a WSPR transmission
|
||||||
|
|
||||||
|
QString m_rxBand;
|
||||||
|
QString m_mode;
|
||||||
|
QString m_modeTx;
|
||||||
|
QString m_waterfallPalette;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // WIDEGRAPH_H
|
||||||
@@ -0,0 +1,299 @@
|
|||||||
|
program jt65sim
|
||||||
|
|
||||||
|
! Generate simulated JT65 data for testing WSJT-X
|
||||||
|
|
||||||
|
use wavhdr
|
||||||
|
use packjt
|
||||||
|
use options
|
||||||
|
parameter (NMAX=54*12000) ! = 648,000 @12kHz
|
||||||
|
parameter (NFFT=10*65536,NH=NFFT/2)
|
||||||
|
type(hdr) h !Header for .wav file
|
||||||
|
integer*2 iwave(NMAX) !Generated waveform
|
||||||
|
integer*4 itone(126) !Channel symbols (values 0-65)
|
||||||
|
integer dgen(12) !Twelve 6-bit data symbols
|
||||||
|
integer sent(63) !RS(63,12) codeword
|
||||||
|
real*4 xnoise(NMAX) !Generated random noise
|
||||||
|
real*4 dat(NMAX) !Generated real data
|
||||||
|
complex cdat(NMAX) !Generated complex waveform
|
||||||
|
complex cspread(0:NFFT-1) !Complex amplitude for Rayleigh fading
|
||||||
|
complex z
|
||||||
|
real*8 f0,dt,twopi,phi,dphi,baud,fsample,freq,sps
|
||||||
|
character msg*22,fname*11,csubmode*1,c,optarg*500,numbuf*32
|
||||||
|
! character call1*5,call2*5
|
||||||
|
logical :: display_help=.false.,seed_prngs=.true.
|
||||||
|
type (option) :: long_options(12) = [ &
|
||||||
|
option ('help',.false.,'h','Display this help message',''), &
|
||||||
|
option ('sub-mode',.true.,'m','sub mode, default MODE=A','MODE'), &
|
||||||
|
option ('num-sigs',.true.,'n','number of signals per file, default SIGNALS=10','SIGNALS'), &
|
||||||
|
option ('f0',.true.,'F','base frequency offset, default F0=1500.0','F0'), &
|
||||||
|
option ('doppler-spread',.true.,'d','Doppler spread, default SPREAD=0.0','SPREAD'), &
|
||||||
|
option ('time-offset',.true.,'t','Time delta, default SECONDS=0.0','SECONDS'), &
|
||||||
|
option ('num-files',.true.,'f','Number of files to generate, default FILES=1','FILES'), &
|
||||||
|
option ('no-prng-seed',.false.,'p','Do not seed PRNGs (use for reproducible tests)',''), &
|
||||||
|
option ('strength',.true.,'s','S/N in dB (2500Hz reference b/w), default SNR=0','SNR'), &
|
||||||
|
option ('11025',.false.,'S','Generate at 11025Hz sample rate, default 12000Hz',''), &
|
||||||
|
option ('gain-offset',.true.,'G','Gain offset in dB, default GAIN=0dB','GAIN'), &
|
||||||
|
option ('message',.true.,'M','Message text','Message') ]
|
||||||
|
|
||||||
|
integer nprc(126) !Sync pattern
|
||||||
|
data nprc/1,0,0,1,1,0,0,0,1,1,1,1,1,1,0,1,0,1,0,0, &
|
||||||
|
0,1,0,1,1,0,0,1,0,0,0,1,1,1,0,0,1,1,1,1, &
|
||||||
|
0,1,1,0,1,1,1,1,0,0,0,1,1,0,1,0,1,0,1,1, &
|
||||||
|
0,0,1,1,0,1,0,1,0,1,0,0,1,0,0,0,0,0,0,1, &
|
||||||
|
1,0,0,0,0,0,0,0,1,1,0,1,0,0,1,0,1,1,0,1, &
|
||||||
|
0,1,0,1,0,0,1,1,0,0,1,0,0,1,0,0,0,0,1,1, &
|
||||||
|
1,1,1,1,1,1/
|
||||||
|
|
||||||
|
! Default parameters:
|
||||||
|
csubmode='A'
|
||||||
|
mode65=1
|
||||||
|
nsigs=10
|
||||||
|
bf0=1500.
|
||||||
|
fspread=0.
|
||||||
|
xdt=0.
|
||||||
|
snrdb=0.
|
||||||
|
nfiles=1
|
||||||
|
nsample_rate=12000
|
||||||
|
gain_offset=0.
|
||||||
|
msg="K1ABC W9XYZ EN37"
|
||||||
|
|
||||||
|
do
|
||||||
|
call getopt('hm:n:F:d:t:f:ps:SG:M:',long_options,c,optarg,narglen,nstat,noffset,nremain,.true.)
|
||||||
|
if( nstat .ne. 0 ) then
|
||||||
|
exit
|
||||||
|
end if
|
||||||
|
select case (c)
|
||||||
|
case ('h')
|
||||||
|
display_help = .true.
|
||||||
|
case ('m')
|
||||||
|
read (optarg(:narglen), *) csubmode
|
||||||
|
if(csubmode.eq.'A') mode65=1
|
||||||
|
if(csubmode.eq.'B') mode65=2
|
||||||
|
if(csubmode.eq.'C') mode65=4
|
||||||
|
case ('n')
|
||||||
|
read (optarg(:narglen), *,err=10) nsigs
|
||||||
|
case ('F')
|
||||||
|
read (optarg(:narglen), *,err=10) bf0
|
||||||
|
case ('d')
|
||||||
|
read (optarg(:narglen), *,err=10) fspread
|
||||||
|
case ('t')
|
||||||
|
read (optarg(:narglen), *) numbuf
|
||||||
|
if (numbuf(1:1) == '\') then !'\'
|
||||||
|
read (numbuf(2:), *,err=10) xdt
|
||||||
|
else
|
||||||
|
read (numbuf, *,err=10) xdt
|
||||||
|
end if
|
||||||
|
case ('f')
|
||||||
|
read (optarg(:narglen), *,err=10) nfiles
|
||||||
|
case ('p')
|
||||||
|
seed_prngs=.false.
|
||||||
|
case ('s')
|
||||||
|
read (optarg(:narglen), *) numbuf
|
||||||
|
if (numbuf(1:1) == '\') then !'\'
|
||||||
|
read (numbuf(2:), *,err=10) snrdb
|
||||||
|
else
|
||||||
|
read (numbuf, *,err=10) snrdb
|
||||||
|
end if
|
||||||
|
case ('S')
|
||||||
|
nsample_rate=11025
|
||||||
|
case ('G')
|
||||||
|
read (optarg(:narglen), *) numbuf
|
||||||
|
if (numbuf(1:1) == '\') then !'\'
|
||||||
|
read (numbuf(2:), *, err=10) gain_offset
|
||||||
|
else
|
||||||
|
read (numbuf, *, err=10) gain_offset
|
||||||
|
end if
|
||||||
|
case ('M')
|
||||||
|
read (optarg(:narglen), '(A)',err=10) msg
|
||||||
|
write(*,*) msg
|
||||||
|
end select
|
||||||
|
cycle
|
||||||
|
10 display_help=.true.
|
||||||
|
print *, 'Optional argument format error for option -', c
|
||||||
|
end do
|
||||||
|
|
||||||
|
if(display_help .or. nstat.lt.0 .or. nremain.ge.1) then
|
||||||
|
print *, ''
|
||||||
|
print *, 'Usage: jt65sim [OPTIONS]'
|
||||||
|
print *, ''
|
||||||
|
print *, ' Generate one or more simulated JT65 signals in .WAV file(s)'
|
||||||
|
print *, ''
|
||||||
|
print *, 'Example: jt65sim -m B -n 10 -d 0.2 -s \\-24.5 -t 0.0 -f 4'
|
||||||
|
print *, ''
|
||||||
|
print *, 'OPTIONS: NB Use \ (\\ on *nix shells) to escape -ve arguments'
|
||||||
|
print *, ''
|
||||||
|
do i = 1, size (long_options)
|
||||||
|
call long_options(i) % print (6)
|
||||||
|
end do
|
||||||
|
go to 999
|
||||||
|
endif
|
||||||
|
|
||||||
|
if (seed_prngs) then
|
||||||
|
call init_random_seed() ! seed Fortran RANDOM_NUMBER generator
|
||||||
|
call sgran() ! see C rand generator (used in gran)
|
||||||
|
end if
|
||||||
|
|
||||||
|
rms=100. * 10. ** (gain_offset / 20.)
|
||||||
|
|
||||||
|
fsample=nsample_rate !Sample rate (Hz)
|
||||||
|
dt=1.d0/fsample !Sample interval (s)
|
||||||
|
twopi=8.d0*atan(1.d0)
|
||||||
|
npts=54*nsample_rate !Total samples in .wav file
|
||||||
|
baud=11025.d0/4096.d0 !Keying rate
|
||||||
|
sps=real(nsample_rate)/baud !Samples per symbol, at fsample=NSAMPLE_RATE Hz
|
||||||
|
nsym=126 !Number of channel symbols
|
||||||
|
h=default_header(nsample_rate,npts)
|
||||||
|
dfsig=2000.0/nsigs !Freq spacing between sigs in file (Hz)
|
||||||
|
|
||||||
|
do ifile=1,nfiles !Loop over requested number of files
|
||||||
|
write(fname,1002) ifile !Output filename
|
||||||
|
1002 format('000000_',i4.4)
|
||||||
|
open(10,file=fname//'.wav',access='stream',status='unknown')
|
||||||
|
|
||||||
|
xnoise=0.
|
||||||
|
cdat=0.
|
||||||
|
if(snrdb.lt.90) then
|
||||||
|
do i=1,npts
|
||||||
|
xnoise(i)=gran() !Generate gaussian noise
|
||||||
|
enddo
|
||||||
|
endif
|
||||||
|
|
||||||
|
do isig=1,nsigs !Generate requested number of sigs
|
||||||
|
if(mod(nsigs,2).eq.0) f0=bf0 + dfsig*(isig-0.5-nsigs/2)
|
||||||
|
if(mod(nsigs,2).eq.1) f0=bf0 + dfsig*(isig-(nsigs+1)/2)
|
||||||
|
xsnr=snrdb
|
||||||
|
if(snrdb.eq.0.0) xsnr=-19 - isig
|
||||||
|
if(csubmode.eq.'B' .and. snrdb.eq.0.0) xsnr=-21 - isig
|
||||||
|
if(csubmode.eq.'C' .and. snrdb.eq.0.0) xsnr=-21 - isig
|
||||||
|
|
||||||
|
!###
|
||||||
|
! call1="K1ABC"
|
||||||
|
! ic3=65+mod(isig-1,26)
|
||||||
|
! ic2=65+mod((isig-1)/26,26)
|
||||||
|
! ic1=65
|
||||||
|
! call2="W9"//char(ic1)//char(ic2)//char(ic3)
|
||||||
|
! write(msg,1010) call1,call2,nint(xsnr)
|
||||||
|
!1010 format(a5,1x,a5,1x,i3.2)
|
||||||
|
!###
|
||||||
|
call packmsg(msg,dgen,itype,.false.) !Pack message into 12 six-bit bytes
|
||||||
|
call rs_encode(dgen,sent) !Encode using RS(63,12)
|
||||||
|
call interleave63(sent,1) !Interleave channel symbols
|
||||||
|
call graycode65(sent,63,1) !Apply Gray code
|
||||||
|
|
||||||
|
k=0
|
||||||
|
do j=1,nsym !Insert sync and data into itone()
|
||||||
|
if(nprc(j).eq.0) then
|
||||||
|
k=k+1
|
||||||
|
itone(j)=sent(k)+2
|
||||||
|
else
|
||||||
|
itone(j)=0
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
|
||||||
|
bandwidth_ratio=2500.0/(fsample/2.0)
|
||||||
|
sig=sqrt(2*bandwidth_ratio)*10.0**(0.05*xsnr)
|
||||||
|
if(xsnr.gt.90.0) sig=1.0
|
||||||
|
write(*,1020) ifile,isig,f0,csubmode,xsnr,xdt,fspread,msg
|
||||||
|
1020 format(i4,i4,f10.3,2x,a1,2x,f5.1,f6.2,f5.1,1x,a22)
|
||||||
|
|
||||||
|
phi=0.d0
|
||||||
|
dphi=0.d0
|
||||||
|
k=nsample_rate + xdt*nsample_rate !Start audio at t = xdt + 1.0 s
|
||||||
|
isym0=-99
|
||||||
|
do i=1,npts !Add this signal into cdat()
|
||||||
|
isym=floor(i/sps)+1
|
||||||
|
if(isym.gt.nsym) exit
|
||||||
|
if(isym.ne.isym0) then
|
||||||
|
freq=f0 + itone(isym)*baud*mode65
|
||||||
|
dphi=twopi*freq*dt
|
||||||
|
isym0=isym
|
||||||
|
endif
|
||||||
|
phi=phi + dphi
|
||||||
|
if(phi.gt.twopi) phi=phi-twopi
|
||||||
|
xphi=phi
|
||||||
|
z=cmplx(cos(xphi),sin(xphi))
|
||||||
|
k=k+1
|
||||||
|
if(k.ge.1) cdat(k)=cdat(k) + sig*z
|
||||||
|
enddo
|
||||||
|
enddo
|
||||||
|
|
||||||
|
if(fspread.ne.0) then !Apply specified Doppler spread
|
||||||
|
df=real(nsample_rate)/nfft
|
||||||
|
twopi=8*atan(1.0)
|
||||||
|
cspread(0)=1.0
|
||||||
|
cspread(NH)=0.
|
||||||
|
|
||||||
|
! The following options were added 3/15/2016 to make the half-power tone
|
||||||
|
! widths equal to the requested Doppler spread. (Previously we effectively
|
||||||
|
! used b=1.0 and Gaussian shape, which made the tones 1.665 times wider.)
|
||||||
|
! b=2.0*sqrt(log(2.0)) !Gaussian (before 3/15/2016)
|
||||||
|
! b=2.0 !Lorenzian 3/15 - 3/27
|
||||||
|
b=6.0 !Lorenzian 3/28 onward
|
||||||
|
|
||||||
|
do i=1,NH
|
||||||
|
f=i*df
|
||||||
|
x=b*f/fspread
|
||||||
|
z=0.
|
||||||
|
a=0.
|
||||||
|
if(x.lt.3.0) then !Cutoff beyond x=3
|
||||||
|
! a=sqrt(exp(-x*x)) !Gaussian
|
||||||
|
a=sqrt(1.111/(1.0+x*x)-0.1) !Lorentzian
|
||||||
|
call random_number(r1)
|
||||||
|
phi1=twopi*r1
|
||||||
|
z=a*cmplx(cos(phi1),sin(phi1))
|
||||||
|
endif
|
||||||
|
cspread(i)=z
|
||||||
|
z=0.
|
||||||
|
if(x.lt.50.0) then
|
||||||
|
call random_number(r2)
|
||||||
|
phi2=twopi*r2
|
||||||
|
z=a*cmplx(cos(phi2),sin(phi2))
|
||||||
|
endif
|
||||||
|
cspread(NFFT-i)=z
|
||||||
|
enddo
|
||||||
|
|
||||||
|
do i=0,NFFT-1
|
||||||
|
f=i*df
|
||||||
|
if(i.gt.NH) f=(i-nfft)*df
|
||||||
|
s=real(cspread(i))**2 + aimag(cspread(i))**2
|
||||||
|
! write(13,3000) i,f,s,cspread(i)
|
||||||
|
!3000 format(i5,f10.3,3f12.6)
|
||||||
|
enddo
|
||||||
|
! s=real(cspread(0))**2 + aimag(cspread(0))**2
|
||||||
|
! write(13,3000) 1024,0.0,s,cspread(0)
|
||||||
|
|
||||||
|
call four2a(cspread,NFFT,1,1,1) !Transform to time domain
|
||||||
|
|
||||||
|
sum=0.
|
||||||
|
do i=0,NFFT-1
|
||||||
|
p=real(cspread(i))**2 + aimag(cspread(i))**2
|
||||||
|
sum=sum+p
|
||||||
|
enddo
|
||||||
|
avep=sum/NFFT
|
||||||
|
fac=sqrt(1.0/avep)
|
||||||
|
cspread=fac*cspread !Normalize to constant avg power
|
||||||
|
cdat(1:npts)=cspread(1:npts)*cdat(1:npts) !Apply Rayleigh fading
|
||||||
|
|
||||||
|
! do i=0,NFFT-1
|
||||||
|
! p=real(cspread(i))**2 + aimag(cspread(i))**2
|
||||||
|
! write(14,3010) i,p,cspread(i)
|
||||||
|
!3010 format(i8,3f12.6)
|
||||||
|
! enddo
|
||||||
|
|
||||||
|
endif
|
||||||
|
|
||||||
|
dat=aimag(cdat) + xnoise !Add the generated noise
|
||||||
|
if(snrdb.lt.90.0) then
|
||||||
|
dat=rms*dat(1:npts)
|
||||||
|
else
|
||||||
|
datpk=maxval(abs(dat(1:npts)))
|
||||||
|
fac=32766.9/datpk
|
||||||
|
dat(1:npts)=fac*dat(1:npts)
|
||||||
|
endif
|
||||||
|
if(any(abs(dat(1:npts)).gt.32767.0)) print*,"Warning - data will be clipped."
|
||||||
|
iwave(1:npts)=nint(dat(1:npts))
|
||||||
|
write(10) h,iwave(1:npts) !Save the .wav file
|
||||||
|
close(10)
|
||||||
|
enddo
|
||||||
|
|
||||||
|
999 end program jt65sim
|
||||||
@@ -0,0 +1,186 @@
|
|||||||
|
White Paper: FT8 for DXpeditions
|
||||||
|
-----------------------------------
|
||||||
|
Joe Taylor, K1JT - October 27, 2017
|
||||||
|
|
||||||
|
Assumptions:
|
||||||
|
|
||||||
|
1. WSJT-X will have two distinct options that enable the maximum-rate
|
||||||
|
QSO exchanges described below. Fox must select "Fox"; all Hounds must
|
||||||
|
select "Hound".
|
||||||
|
|
||||||
|
2. There will be an announced basic dial frequency for each band, say
|
||||||
|
f0=14082 kHz for 20m. This is the basic Channel.
|
||||||
|
|
||||||
|
3. Fox always transmits in the 1st sequence, 200-800 Hz above f0.
|
||||||
|
|
||||||
|
4. Hounds call in 2nd sequence, 1000-5000 Hz above f0. Hounds
|
||||||
|
transmitting below f0+1000 Hz will not be answered.
|
||||||
|
|
||||||
|
5. If found necessary, additional Channels may be defined in which
|
||||||
|
Hounds can transmit. (However, I suggest that CQ-by-call-area may
|
||||||
|
be easier to implement and use; and the software could be made to
|
||||||
|
prevent Hounds in the wrong area from transmitting.)
|
||||||
|
|
||||||
|
6. Ideally, Fox and Hounds should all use CAT control configured with
|
||||||
|
*Split Operation* set to *Rig* or *Fake It*, and transceiver dial
|
||||||
|
frequencies should best be calibrated to within a few Hz. (WSJT-X
|
||||||
|
provides tools that make this fairly easy to do.)
|
||||||
|
|
||||||
|
|
||||||
|
When Fox is running a pileup, QSOs will look something like the
|
||||||
|
following exchanges. Here I've assumed the Fox callsign is KH1DX,
|
||||||
|
his locator AJ10:
|
||||||
|
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
Fox Hounds
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
1. CQ KH1DX AJ10
|
||||||
|
2. KH1DX K1ABC FN42, KH1DX W9XYZ EN37, ...
|
||||||
|
3. K1ABC KH1DX -13
|
||||||
|
4. KH1DX K1ABC R-11
|
||||||
|
5. K1ABC RR73; W9XYZ <KH1DX> -17
|
||||||
|
6. ... no copy from W9XYZ ...
|
||||||
|
7. W9XYZ KH1DX -17
|
||||||
|
8. ... no copy from W9XYZ ...
|
||||||
|
9. G4AAA KH1DX -11
|
||||||
|
10. KH1DX G4AAA R-03
|
||||||
|
11. G4AAA RR73; DL3BBB <KH1DX> -12
|
||||||
|
12. KH1DX DL3BBB R-09
|
||||||
|
13. DL3BBB RR73; DE <KH1DX>
|
||||||
|
14. ...
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
|
||||||
|
All messages except those containing "<...>" are standard FT8 messages
|
||||||
|
(i3bit=0, iFreeText=0). Hounds transmit only standard messages.
|
||||||
|
|
||||||
|
Fox transmits standard messages and also special messages with
|
||||||
|
i3bit=1. The special messages contain a callsign whose completed QSO
|
||||||
|
is being acknowledged; a callsign for the next station to be worked; a
|
||||||
|
hash code corresponding to the Fox callsign; and a signal report.
|
||||||
|
Users will see the Fox callsign enclosed in angle brackets, <KH1DX>.
|
||||||
|
The 72-bit message payload contains two 28-bit callsigns, a 10-bit
|
||||||
|
hash code, and a 6-bit signal report. If no call has been queued up
|
||||||
|
by Fox for the next QSO, the acknowledgment message takes the
|
||||||
|
abbreviated form shown in line 13 above.
|
||||||
|
|
||||||
|
When a Hound receives a message with i3bit=1, the decoder interprets
|
||||||
|
the remaining 72 bits as described above. If the 10-bit hash code
|
||||||
|
matches that for Fox's callsign, the message is displayed as in the
|
||||||
|
QSO exchanges shown above. Otherwise the message is considered a
|
||||||
|
false decode and is not displayed.
|
||||||
|
|
||||||
|
|
||||||
|
Station Setup and Operation for FOX
|
||||||
|
-----------------------------------
|
||||||
|
|
||||||
|
A wide Rx bandwidth (up to 5 kHz) is selected. The basic dial
|
||||||
|
frequency is set 1 kHz above f0 (thus 14083 kHz in my example) and the
|
||||||
|
audio TxFreq somewhere between -200 and -800 Hz. (Yes, negative
|
||||||
|
numbers are OK. *Split Operation* will reset the Tx dial frequency as
|
||||||
|
needed and will keep the generated Tx audio frequency between 1500 and
|
||||||
|
2000 Hz.) Hounds with audio TxFreq set to N Hz will be received by Fox
|
||||||
|
at N-1000 Hz.
|
||||||
|
|
||||||
|
WSJT-X at Fox will maintain and display a list of all decoded Hounds
|
||||||
|
calling Fox in the past 2 to 4 Rx cycles. The list might look
|
||||||
|
something like this (but typically will be much longer):
|
||||||
|
|
||||||
|
----------------------------
|
||||||
|
Call Grid Rpt Freq
|
||||||
|
----------------------------
|
||||||
|
AA2UK FM29 -11 240
|
||||||
|
AD9H EN61 +02 1260
|
||||||
|
K0TPP EM48 -15 1980
|
||||||
|
N2BJ EN61 +11 540
|
||||||
|
N4NDR EL98 -17 4620
|
||||||
|
NX4E EM70 +00 3780
|
||||||
|
ON3LA JN29 -10 3300
|
||||||
|
PD9BG JO21 -21 2100
|
||||||
|
PJ4/KA1XYZ FK60 -07 1020
|
||||||
|
VE1SKY FN74 +03 1620
|
||||||
|
WB2REM EL97 -13 3060
|
||||||
|
...
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
Fox can choose to have the list sorted on any column.
|
||||||
|
|
||||||
|
Fox selects a Hound to call next by clicking on a line. Or he can hit
|
||||||
|
"F1" to have the program select a caller according to one of these
|
||||||
|
criteria (maybe others as well?):
|
||||||
|
|
||||||
|
- Weakest caller
|
||||||
|
- Strongest caller
|
||||||
|
- Strongest one below -N dB (with N selectable)
|
||||||
|
- Choose a call at random
|
||||||
|
- Random choice with S/N between snrMin and snrMax dB.
|
||||||
|
|
||||||
|
After a particular Hound has been called, Fox's Auto-Sequencer looks
|
||||||
|
for a response containing "R+rpt" originating from that same callsign.
|
||||||
|
If such a message is received, Fox's next transmission will be the
|
||||||
|
special "acknowledge-and-call-next" type, with i3bit=1. If the
|
||||||
|
expected message is not received, as in example line 6 above, the
|
||||||
|
report is sent to the same station again. If the second attempt fails
|
||||||
|
and another Hound callsign has been queued up, the QSO is aborted and
|
||||||
|
the next Hound is called.
|
||||||
|
|
||||||
|
|
||||||
|
Station Setup and Operation for Hounds
|
||||||
|
--------------------------------------
|
||||||
|
|
||||||
|
Dial frequency is set to f0, 14082 kHz in my example. Rx bandwidth and
|
||||||
|
displayed range on the Wide Graph can be anything convenient, say 200
|
||||||
|
to 2600 Hz. (Signal from Fox will be expected between 200 and 800
|
||||||
|
Hz.) Enter callsign and locator of Fox on WSJT-X main window as *DX
|
||||||
|
Call* and *DX Grid*. Choose a TxFreq offset of 1000 + 60*N for some N
|
||||||
|
in the range 1 to 80 (maybe even higher?). Move TxFreq as desired,
|
||||||
|
hoping to find a clear slot, by using Shift+F11 and Shift+F12.
|
||||||
|
|
||||||
|
- Hit F1 to call Fox in your next Tx sequence. Yes, you must hit F1
|
||||||
|
repeatedly, in order to keep calling.
|
||||||
|
|
||||||
|
- The Auto-sequencer will watch for a decoded message that contains
|
||||||
|
"MyCall DXcall rpt" or "MyCall <DXcall> rpt". When one of these is
|
||||||
|
received, your next transmission will be "DXcall MyCall R+rpt",
|
||||||
|
sent automatically.
|
||||||
|
|
||||||
|
- After you send the "R+rpt" message, AutoSeq will watch for a
|
||||||
|
message that starts with "MyCall RR73; ...". When that is
|
||||||
|
received, you're in his log, and you'll be prompted to log the QSO.
|
||||||
|
|
||||||
|
Random thoughts
|
||||||
|
---------------
|
||||||
|
|
||||||
|
Fox's decoder has access to signals in a 4 kHz (maybe even 5 kHz?)
|
||||||
|
window. At 60 Hz intervals, that's enough for around 65 (or 80?)
|
||||||
|
non-overlapping Hound signals. If the pileup becomes too deep, more
|
||||||
|
spectrum might be used; but note that WSJT-X can't access more than 5
|
||||||
|
kHz at one time. A better solution might be for Fox to call "CQ n
|
||||||
|
KH1DX AJ10", where n is a single digit indicating call area. The
|
||||||
|
decoder could then limit the list of eligible calls to those in the
|
||||||
|
specified call area. After decoding such a CQ, the software at Hound
|
||||||
|
could refuse to transmit unless MyCall falls in the specified call
|
||||||
|
area. (Other special CQ formats can be imagined that would limit the
|
||||||
|
eligible Hound callsigns even further.)
|
||||||
|
|
||||||
|
We haven't thought much, yet, about logging issues for Fox. I imagine
|
||||||
|
we could do what's necessary to join a N1MM+ logging network, if that's
|
||||||
|
deemed desirable.
|
||||||
|
|
||||||
|
A few questions:
|
||||||
|
|
||||||
|
Q1: Should the Auto-Sequencer allow for other cases in which a QSO has
|
||||||
|
been initiated by Fox, but one of next two messages is not copied by
|
||||||
|
either Fox or Hound? For example, what if K1ABC does not copy message
|
||||||
|
#5? Should he keep sending his message "KH1DX K1ABC R-11" ? If Fox
|
||||||
|
receives this message again, should he acknowledge again? And poor
|
||||||
|
W9XYZ, who never received an acknowledgment, will probably keep
|
||||||
|
sending "KH1DX W9XYZ R-19", or whatever. If Fox eventually copies the
|
||||||
|
message, should the program remember that W9XYZ had been called, and
|
||||||
|
thus send him an acknowledgment?
|
||||||
|
|
||||||
|
Q2: Should we provide a stack for several to-be-called callsigns,
|
||||||
|
rather than just one? Should re-ordering of calls in the stack be
|
||||||
|
permitted?
|
||||||
|
|
||||||
|
Q3: Can we handle WSJT-X "Type 1" and "Type 2" compound callsigns, for
|
||||||
|
Hounds?
|
||||||
@@ -0,0 +1,286 @@
|
|||||||
|
program wsprlfsim
|
||||||
|
|
||||||
|
! Simulate characteristics of a potential "WSPR-LF" mode using LDPC (300,60)
|
||||||
|
! code, OQPSK modulation, and 5 minute T/R sequences.
|
||||||
|
|
||||||
|
! Reception and Demodulation algorithm:
|
||||||
|
! 1. Compute coarse spectrum; find fc1 = approx carrier freq
|
||||||
|
! 2. Mix from fc1 to 0; LPF at +/- 0.75*R
|
||||||
|
! 3. Square, FFT; find peaks near -R/2 and +R/2 to get fc2
|
||||||
|
! 4. Mix from fc2 to 0
|
||||||
|
! 5. Fit cb13 (central part of csync) to c -> lag, phase
|
||||||
|
! 6. Fit complex ploynomial for channel equalization
|
||||||
|
! 7. Get soft bits from equalized data
|
||||||
|
|
||||||
|
include 'wsprlf_params.f90'
|
||||||
|
|
||||||
|
! Q: Would it be better for central Sync array to use both I and Q channels?
|
||||||
|
|
||||||
|
character*8 arg
|
||||||
|
complex cbb(0:NZ-1) !Complex baseband waveform
|
||||||
|
complex csync(0:NZ-1) !Sync symbols only, from cbb
|
||||||
|
complex c(0:NZ-1) !Complex waveform
|
||||||
|
complex c0(0:NZ-1) !Complex waveform
|
||||||
|
complex c1(0:NZ-1) !Complex waveform
|
||||||
|
complex zz(NS+ND) !Complex symbol values (intermediate)
|
||||||
|
complex z
|
||||||
|
real xnoise(0:NZ-1) !Generated random noise
|
||||||
|
real ynoise(0:NZ-1) !Generated random noise
|
||||||
|
real rxdata(ND),llr(ND) !Soft symbols
|
||||||
|
real pp(2*NSPS) !Shaped pulse for OQPSK
|
||||||
|
real a(5) !For twkfreq1
|
||||||
|
real aa(20),bb(20) !Fitted polyco's
|
||||||
|
real t(11)
|
||||||
|
character*12 label(11)
|
||||||
|
integer*8 count0,count1,count2,count3,clkfreq
|
||||||
|
integer nc(11)
|
||||||
|
integer id(NS+ND) !NRZ values (+/-1) for Sync and Data
|
||||||
|
integer ierror(NS+ND)
|
||||||
|
integer icw(NN)
|
||||||
|
integer itone(NN)
|
||||||
|
integer*1 msgbits(KK),decoded(KK),apmask(ND),cw(ND)
|
||||||
|
! integer*1 codeword(ND)
|
||||||
|
data msgbits/0,0,1,0,0,1,1,1,1,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,1,1,0,0,0,1, &
|
||||||
|
1,1,1,0,1,1,1,1,1,1,1,0,0,1,0,0,1,1,0,1,1,0,1,0,1,1,0,0,1,1/
|
||||||
|
data label/'genwsprlf','twkfreq1 a','watterson','noise gen','getfc1w', &
|
||||||
|
'getfc2w','twkfreq1 b','xdt loop','cpolyfitw','msksoftsym', &
|
||||||
|
'bpdecode300'/
|
||||||
|
|
||||||
|
nargs=iargc()
|
||||||
|
if(nargs.ne.6) then
|
||||||
|
print*,'Usage: wsprlfsim f0(Hz) delay(ms) fspread(Hz) maxn iters snr(dB)'
|
||||||
|
print*,'Example: wsprlfsim 0 0 0 5 10 -20'
|
||||||
|
print*,'Set snr=0 to cycle through a range'
|
||||||
|
go to 999
|
||||||
|
endif
|
||||||
|
call getarg(1,arg)
|
||||||
|
read(arg,*) f0 !Generated carrier frequency
|
||||||
|
call getarg(2,arg)
|
||||||
|
read(arg,*) delay !Delta_t (ms) for Watterson model
|
||||||
|
call getarg(3,arg)
|
||||||
|
read(arg,*) fspread !Fspread (Hz) for Watterson model
|
||||||
|
call getarg(4,arg)
|
||||||
|
read(arg,*) maxn !Max nterms for polyfit
|
||||||
|
call getarg(5,arg)
|
||||||
|
read(arg,*) iters !Iterations at each SNR
|
||||||
|
call getarg(6,arg)
|
||||||
|
read(arg,*) snrdb !Specified SNR_2500
|
||||||
|
|
||||||
|
nc=0
|
||||||
|
twopi=8.0*atan(1.0)
|
||||||
|
fs=NSPS*12000.0/NSPS0 !Sample rate = 22.2222... Hz
|
||||||
|
dt=1.0/fs !Sample interval (s)
|
||||||
|
tt=NSPS*dt !Duration of "itone" symbols (s)
|
||||||
|
ts=2*NSPS*dt !Duration of OQPSK symbols (s)
|
||||||
|
baud=1.0/tt !Keying rate for "itone" symbols (baud)
|
||||||
|
txt=NZ*dt !Transmission length (s)
|
||||||
|
bandwidth_ratio=2500.0/(fs/2.0)
|
||||||
|
write(*,1000) fs,f0,delay,fspread,maxn,baud,3*baud,txt,iters
|
||||||
|
1000 format('fs:',f10.3,' f0:',f5.1,' Delay:',f4.1,' fSpread:',f5.2, &
|
||||||
|
' maxn:',i3,/'Baud:',f8.3,' BW:',f5.1,' TxT:',f6.1,' iters:',i4/)
|
||||||
|
write(*,1004)
|
||||||
|
1004 format(/' SNR sync data ser ber fer fsigma tsigma', &
|
||||||
|
' tsec'/68('-'))
|
||||||
|
|
||||||
|
do i=1,N2 !Half-sine pulse shape
|
||||||
|
pp(i)=sin(0.5*(i-1)*twopi/(2*NSPS))
|
||||||
|
enddo
|
||||||
|
|
||||||
|
t=0.
|
||||||
|
call system_clock(count0,clkfreq)
|
||||||
|
call genwsprlf(msgbits,id,icw,cbb,csync,itone)!Generate baseband waveform
|
||||||
|
call system_clock(count1,clkfreq)
|
||||||
|
t(1)=float(count1-count0)/float(clkfreq)
|
||||||
|
nc(1)=nc(1)+1
|
||||||
|
do i=0,NZ-1
|
||||||
|
write(40,4001) i,cbb(i),csync(i)
|
||||||
|
4001 format(i8,4f12.6)
|
||||||
|
enddo
|
||||||
|
|
||||||
|
call system_clock(count0,clkfreq)
|
||||||
|
a=0.
|
||||||
|
a(1)=f0
|
||||||
|
call twkfreq1(cbb,NZ,fs,a,c0) !Mix baseband to specified frequency
|
||||||
|
call system_clock(count1,clkfreq)
|
||||||
|
t(2)=float(count1-count0)/float(clkfreq)
|
||||||
|
nc(2)=nc(2)+1
|
||||||
|
|
||||||
|
isna=-20
|
||||||
|
isnb=-40
|
||||||
|
if(snrdb.ne.0.0) then
|
||||||
|
isna=nint(snrdb)
|
||||||
|
isnb=isna
|
||||||
|
endif
|
||||||
|
do isnr=isna,isnb,-1 !Loop over SNR range
|
||||||
|
if(isna.ne.isnb) snrdb=isnr
|
||||||
|
sig=sqrt(bandwidth_ratio) * 10.0**(0.05*snrdb)
|
||||||
|
if(snrdb.gt.90.0) sig=1.0
|
||||||
|
nhard=0
|
||||||
|
nhardsync=0
|
||||||
|
nfe=0
|
||||||
|
sqf=0.
|
||||||
|
sqt=0.
|
||||||
|
|
||||||
|
call system_clock(count2,clkfreq)
|
||||||
|
do iter=1,iters !Loop over requested iterations
|
||||||
|
c=c0
|
||||||
|
write(*,*) 'iter ',iter
|
||||||
|
call system_clock(count0,clkfreq)
|
||||||
|
if(delay.ne.0.0 .or. fspread.ne.0.0) then
|
||||||
|
call watterson(c,NZ,fs,delay,fspread)
|
||||||
|
endif
|
||||||
|
call system_clock(count1,clkfreq)
|
||||||
|
t(3)=t(3)+float(count1-count0)/float(clkfreq)
|
||||||
|
nc(3)=nc(3)+1
|
||||||
|
|
||||||
|
call system_clock(count0,clkfreq)
|
||||||
|
c=sig*c !Scale to requested SNR
|
||||||
|
if(snrdb.lt.90) then
|
||||||
|
do i=0,NZ-1 !Generate gaussian noise
|
||||||
|
xnoise(i)=gran()
|
||||||
|
ynoise(i)=gran()
|
||||||
|
enddo
|
||||||
|
c=c + cmplx(xnoise,ynoise) !Add AWGN noise
|
||||||
|
endif
|
||||||
|
call system_clock(count1,clkfreq)
|
||||||
|
t(4)=t(4)+float(count1-count0)/float(clkfreq)
|
||||||
|
nc(4)=nc(4)+1
|
||||||
|
|
||||||
|
call system_clock(count0,clkfreq)
|
||||||
|
call getfc1w(c,fs,fc1) !First approx for freq
|
||||||
|
call system_clock(count1,clkfreq)
|
||||||
|
t(5)=t(5)+float(count1-count0)/float(clkfreq)
|
||||||
|
nc(5)=nc(5)+1
|
||||||
|
write(*,*) 'fc1 ',fc1
|
||||||
|
call system_clock(count0,clkfreq)
|
||||||
|
call getfc2w(c,csync,fs,fc1,fc2,fc3) !Refined freq
|
||||||
|
write(*,*) 'fc1,fc2,fc3 ',fc1,fc2,fc3
|
||||||
|
call system_clock(count1,clkfreq)
|
||||||
|
t(6)=t(6)+float(count1-count0)/float(clkfreq)
|
||||||
|
nc(6)=nc(6)+1
|
||||||
|
sqf=sqf + (fc1+fc2-f0)**2
|
||||||
|
|
||||||
|
call system_clock(count0,clkfreq)
|
||||||
|
!NB: Measured performance is about equally good using fc2 or fc3 here:
|
||||||
|
a(1)=-(fc1+fc2)
|
||||||
|
a(2:5)=0.
|
||||||
|
call twkfreq1(c,NZ,fs,a,c) !Mix c down by fc1+fc2
|
||||||
|
call system_clock(count1,clkfreq)
|
||||||
|
t(7)=t(7)+float(count1-count0)/float(clkfreq)
|
||||||
|
nc(7)=nc(7)+1
|
||||||
|
|
||||||
|
! The following may not be necessary?
|
||||||
|
! z=sum(c(3088:3503)*cb13)/208.0 !Get phase from Barker 13 vector
|
||||||
|
! z0=z/abs(z)
|
||||||
|
! c=c*conjg(z0)
|
||||||
|
|
||||||
|
call system_clock(count0,clkfreq)
|
||||||
|
!---------------------------------------------------------------- DT
|
||||||
|
! Not presently used:
|
||||||
|
amax=0.
|
||||||
|
jpk=0
|
||||||
|
iaa=0
|
||||||
|
ibb=NZ-1
|
||||||
|
do j=-20*NSPS,20*NSPS,NSPS/8
|
||||||
|
ia=j
|
||||||
|
ib=NZ-1+j
|
||||||
|
if(ia.lt.0) then
|
||||||
|
ia=0
|
||||||
|
iaa=-j
|
||||||
|
else
|
||||||
|
iaa=0
|
||||||
|
endif
|
||||||
|
if(ib.gt.NZ-1) then
|
||||||
|
ib=NZ-1
|
||||||
|
ibb=NZ-1-j
|
||||||
|
endif
|
||||||
|
z=sum(c(ia:ib)*conjg(csync(iaa:ibb)))
|
||||||
|
if(abs(z).gt.amax) then
|
||||||
|
amax=abs(z)
|
||||||
|
jpk=j
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
xdt=jpk/fs
|
||||||
|
sqt=sqt + xdt**2
|
||||||
|
call system_clock(count1,clkfreq)
|
||||||
|
t(8)=t(8)+float(count1-count0)/float(clkfreq)
|
||||||
|
nc(8)=nc(8)+1
|
||||||
|
|
||||||
|
!-----------------------------------------------------------------
|
||||||
|
|
||||||
|
nterms=maxn
|
||||||
|
c1=c
|
||||||
|
do itry=1,20
|
||||||
|
idf=itry/2
|
||||||
|
if(mod(itry,2).eq.0) idf=-idf
|
||||||
|
nhard0=0
|
||||||
|
nhardsync0=0
|
||||||
|
ifer=1
|
||||||
|
a(1)=idf*0.00085
|
||||||
|
a(2:5)=0.
|
||||||
|
call system_clock(count0,clkfreq)
|
||||||
|
call twkfreq1(c1,NZ,fs,a,c) !Mix c1 into c
|
||||||
|
call cpolyfitw(c,pp,id,maxn,aa,bb,zz,nhs)
|
||||||
|
call system_clock(count1,clkfreq)
|
||||||
|
t(9)=t(9)+float(count1-count0)/float(clkfreq)
|
||||||
|
nc(9)=nc(9)+1
|
||||||
|
|
||||||
|
call system_clock(count0,clkfreq)
|
||||||
|
call msksoftsymw(zz,aa,bb,id,nterms,ierror,rxdata,nhard0,nhardsync0)
|
||||||
|
call system_clock(count1,clkfreq)
|
||||||
|
t(10)=t(10)+float(count1-count0)/float(clkfreq)
|
||||||
|
nc(10)=nc(10)+1
|
||||||
|
|
||||||
|
if(nhardsync0.gt.35) cycle
|
||||||
|
rxav=sum(rxdata)/ND
|
||||||
|
rx2av=sum(rxdata*rxdata)/ND
|
||||||
|
rxsig=sqrt(rx2av-rxav*rxav)
|
||||||
|
rxdata=rxdata/rxsig
|
||||||
|
ss=0.84
|
||||||
|
llr=2.0*rxdata/(ss*ss)
|
||||||
|
apmask=0
|
||||||
|
max_iterations=40
|
||||||
|
ifer=0
|
||||||
|
call system_clock(count0,clkfreq)
|
||||||
|
call bpdecode300(llr,apmask,max_iterations,decoded,niterations,cw)
|
||||||
|
call system_clock(count1,clkfreq)
|
||||||
|
t(11)=t(11)+float(count1-count0)/float(clkfreq)
|
||||||
|
nc(11)=nc(11)+1
|
||||||
|
nbadcrc=0
|
||||||
|
if(niterations.ge.0) call chkcrc10(decoded,nbadcrc)
|
||||||
|
if(niterations.lt.0 .or. count(msgbits.ne.decoded).gt.0 .or. &
|
||||||
|
nbadcrc.ne.0) ifer=1
|
||||||
|
if(ifer.eq.0) exit
|
||||||
|
enddo !Freq dither loop
|
||||||
|
nhard=nhard+nhard0
|
||||||
|
nhardsync=nhardsync+nhardsync0
|
||||||
|
nfe=nfe+ifer
|
||||||
|
if(nhardsync0+nhard0+niterations+ifer.gt.0) write(42,1045) snrdb, &
|
||||||
|
nhardsync0,nhard0,niterations,ifer,xdt
|
||||||
|
1045 format(f6.1,4i6,f8.2)
|
||||||
|
enddo
|
||||||
|
call system_clock(count3,clkfreq)
|
||||||
|
tsec=float(count3-count2)/float(clkfreq)
|
||||||
|
|
||||||
|
fsigma=sqrt(sqf/iters)
|
||||||
|
tsigma=sqrt(sqt/iters)
|
||||||
|
ser=float(nhardsync)/(NS*iters)
|
||||||
|
ber=float(nhard)/(ND*iters)
|
||||||
|
fer=float(nfe)/iters
|
||||||
|
write(*,1050) snrdb,nhardsync,nhard,ser,ber,fer,fsigma,tsigma,tsec
|
||||||
|
1050 format(f6.1,2i7,2f8.4,f7.3,2f8.2f8.3)
|
||||||
|
enddo
|
||||||
|
|
||||||
|
write(*,1060) NS*iters,ND*iters
|
||||||
|
1060 format(68('-')/6x,2i7)
|
||||||
|
|
||||||
|
write(*,1065)
|
||||||
|
1065 format(/'Timing sec frac calls'/39('-'))
|
||||||
|
do i=1,11
|
||||||
|
write(*,1070) label(i),t(i),t(i)/sum(t),nc(i)
|
||||||
|
1070 format(a12,2f9.3,i8)
|
||||||
|
enddo
|
||||||
|
write(*,1072) sum(t),1.0
|
||||||
|
1072 format(39('-')/12x,2f10.3)
|
||||||
|
|
||||||
|
999 end program wsprlfsim
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
#ifndef MESSAGEAVERAGING_H
|
||||||
|
#define MESSAGEAVERAGING_H
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
|
class QSettings;
|
||||||
|
class QFont;
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class MessageAveraging;
|
||||||
|
}
|
||||||
|
|
||||||
|
class MessageAveraging : public QWidget
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit MessageAveraging(QSettings *, QFont const&, QWidget * parent = 0);
|
||||||
|
~MessageAveraging();
|
||||||
|
void displayAvg(QString const&);
|
||||||
|
void changeFont (QFont const&);
|
||||||
|
void foxLogSetup();
|
||||||
|
void foxLabCallers(int n);
|
||||||
|
void foxLabQueued(int n);
|
||||||
|
void foxLabRate(int n);
|
||||||
|
void foxAddLog(QString logLine);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void closeEvent (QCloseEvent *) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void read_settings ();
|
||||||
|
void write_settings ();
|
||||||
|
void setContentFont (QFont const&);
|
||||||
|
QSettings * settings_;
|
||||||
|
QString m_title_;
|
||||||
|
qint32 m_nLogged_;
|
||||||
|
|
||||||
|
QScopedPointer<Ui::MessageAveraging> ui;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // MESSAGEAVERAGING_H
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
subroutine packtext2(msg,n1,ng)
|
||||||
|
|
||||||
|
character*8 msg
|
||||||
|
real*8 dn
|
||||||
|
character*41 c
|
||||||
|
data c/'0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ +./?'/
|
||||||
|
|
||||||
|
dn=0.
|
||||||
|
do i=1,8
|
||||||
|
do j=1,41
|
||||||
|
if(msg(i:i).eq.c(j:j)) go to 10
|
||||||
|
enddo
|
||||||
|
j=37
|
||||||
|
10 j=j-1 !Codes should start at zero
|
||||||
|
dn=41.d0*dn + j
|
||||||
|
enddo
|
||||||
|
|
||||||
|
ng=mod(dn,32768.d0)
|
||||||
|
n1=(dn-ng)/32768.d0
|
||||||
|
|
||||||
|
return
|
||||||
|
end subroutine packtext2
|
||||||
@@ -0,0 +1,248 @@
|
|||||||
|
// Debug support for the circular buffer library.
|
||||||
|
|
||||||
|
// Copyright (c) 2003-2008 Jan Gaspar
|
||||||
|
|
||||||
|
// Use, modification, and distribution is subject to the Boost Software
|
||||||
|
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
// http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
|
||||||
|
#if !defined(BOOST_CIRCULAR_BUFFER_DEBUG_HPP)
|
||||||
|
#define BOOST_CIRCULAR_BUFFER_DEBUG_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if BOOST_CB_ENABLE_DEBUG
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
#if defined(BOOST_NO_STDC_NAMESPACE)
|
||||||
|
namespace std {
|
||||||
|
using ::memset;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // BOOST_CB_ENABLE_DEBUG
|
||||||
|
namespace boost {
|
||||||
|
|
||||||
|
namespace cb_details {
|
||||||
|
|
||||||
|
#if BOOST_CB_ENABLE_DEBUG
|
||||||
|
|
||||||
|
// The value the uninitialized memory is filled with.
|
||||||
|
const int UNINITIALIZED = 0xcc;
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline void do_fill_uninitialized_memory(T* data, std::size_t size_in_bytes) BOOST_NOEXCEPT {
|
||||||
|
std::memset(static_cast<void*>(data), UNINITIALIZED, size_in_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline void do_fill_uninitialized_memory(T& /*data*/, std::size_t /*size_in_bytes*/) BOOST_NOEXCEPT {
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class debug_iterator_registry;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\class debug_iterator_base
|
||||||
|
\brief Registers/unregisters iterators into the registry of valid iterators.
|
||||||
|
|
||||||
|
This class is intended to be a base class of an iterator.
|
||||||
|
*/
|
||||||
|
class debug_iterator_base {
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Members
|
||||||
|
|
||||||
|
//! Iterator registry.
|
||||||
|
mutable const debug_iterator_registry* m_registry;
|
||||||
|
|
||||||
|
//! Next iterator in the iterator chain.
|
||||||
|
mutable const debug_iterator_base* m_next;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Construction/destruction
|
||||||
|
|
||||||
|
//! Default constructor.
|
||||||
|
debug_iterator_base();
|
||||||
|
|
||||||
|
//! Constructor taking the iterator registry as a parameter.
|
||||||
|
debug_iterator_base(const debug_iterator_registry* registry);
|
||||||
|
|
||||||
|
//! Copy constructor.
|
||||||
|
debug_iterator_base(const debug_iterator_base& rhs);
|
||||||
|
|
||||||
|
//! Destructor.
|
||||||
|
~debug_iterator_base();
|
||||||
|
|
||||||
|
// Methods
|
||||||
|
|
||||||
|
//! Assign operator.
|
||||||
|
debug_iterator_base& operator = (const debug_iterator_base& rhs);
|
||||||
|
|
||||||
|
//! Is the iterator valid?
|
||||||
|
bool is_valid(const debug_iterator_registry* registry) const;
|
||||||
|
|
||||||
|
//! Invalidate the iterator.
|
||||||
|
/*!
|
||||||
|
\note The method is const in order to invalidate const iterators, too.
|
||||||
|
*/
|
||||||
|
void invalidate() const;
|
||||||
|
|
||||||
|
//! Return the next iterator in the iterator chain.
|
||||||
|
const debug_iterator_base* next() const;
|
||||||
|
|
||||||
|
//! Set the next iterator in the iterator chain.
|
||||||
|
/*!
|
||||||
|
\note The method is const in order to set a next iterator to a const iterator, too.
|
||||||
|
*/
|
||||||
|
void set_next(const debug_iterator_base* it) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Helpers
|
||||||
|
|
||||||
|
//! Register self as a valid iterator.
|
||||||
|
void register_self();
|
||||||
|
|
||||||
|
//! Unregister self from valid iterators.
|
||||||
|
void unregister_self();
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\class debug_iterator_registry
|
||||||
|
\brief Registry of valid iterators.
|
||||||
|
|
||||||
|
This class is intended to be a base class of a container.
|
||||||
|
*/
|
||||||
|
class debug_iterator_registry {
|
||||||
|
|
||||||
|
//! Pointer to the chain of valid iterators.
|
||||||
|
mutable const debug_iterator_base* m_iterators;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Methods
|
||||||
|
|
||||||
|
//! Default constructor.
|
||||||
|
debug_iterator_registry() : m_iterators(0) {}
|
||||||
|
|
||||||
|
//! Register an iterator into the list of valid iterators.
|
||||||
|
/*!
|
||||||
|
\note The method is const in order to register iterators into const containers, too.
|
||||||
|
*/
|
||||||
|
void register_iterator(const debug_iterator_base* it) const {
|
||||||
|
it->set_next(m_iterators);
|
||||||
|
m_iterators = it;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Unregister an iterator from the list of valid iterators.
|
||||||
|
/*!
|
||||||
|
\note The method is const in order to unregister iterators from const containers, too.
|
||||||
|
*/
|
||||||
|
void unregister_iterator(const debug_iterator_base* it) const {
|
||||||
|
const debug_iterator_base* previous = 0;
|
||||||
|
for (const debug_iterator_base* p = m_iterators; p != it; previous = p, p = p->next()) {}
|
||||||
|
remove(it, previous);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Invalidate every iterator pointing to the same element as the iterator passed as a parameter.
|
||||||
|
template <class Iterator>
|
||||||
|
void invalidate_iterators(const Iterator& it) {
|
||||||
|
const debug_iterator_base* previous = 0;
|
||||||
|
for (const debug_iterator_base* p = m_iterators; p != 0; p = p->next()) {
|
||||||
|
if (((Iterator*)p)->m_it == it.m_it) {
|
||||||
|
p->invalidate();
|
||||||
|
remove(p, previous);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
previous = p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Invalidate all iterators except an iterator poining to the same element as the iterator passed as a parameter.
|
||||||
|
template <class Iterator>
|
||||||
|
void invalidate_iterators_except(const Iterator& it) {
|
||||||
|
const debug_iterator_base* previous = 0;
|
||||||
|
for (const debug_iterator_base* p = m_iterators; p != 0; p = p->next()) {
|
||||||
|
if (((Iterator*)p)->m_it != it.m_it) {
|
||||||
|
p->invalidate();
|
||||||
|
remove(p, previous);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
previous = p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Invalidate all iterators.
|
||||||
|
void invalidate_all_iterators() {
|
||||||
|
for (const debug_iterator_base* p = m_iterators; p != 0; p = p->next())
|
||||||
|
p->invalidate();
|
||||||
|
m_iterators = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Helpers
|
||||||
|
|
||||||
|
//! Remove the current iterator from the iterator chain.
|
||||||
|
void remove(const debug_iterator_base* current,
|
||||||
|
const debug_iterator_base* previous) const {
|
||||||
|
if (previous == 0)
|
||||||
|
m_iterators = m_iterators->next();
|
||||||
|
else
|
||||||
|
previous->set_next(current->next());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Implementation of the debug_iterator_base methods.
|
||||||
|
|
||||||
|
inline debug_iterator_base::debug_iterator_base() : m_registry(0), m_next(0) {}
|
||||||
|
|
||||||
|
inline debug_iterator_base::debug_iterator_base(const debug_iterator_registry* registry)
|
||||||
|
: m_registry(registry), m_next(0) {
|
||||||
|
register_self();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline debug_iterator_base::debug_iterator_base(const debug_iterator_base& rhs)
|
||||||
|
: m_registry(rhs.m_registry), m_next(0) {
|
||||||
|
register_self();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline debug_iterator_base::~debug_iterator_base() { unregister_self(); }
|
||||||
|
|
||||||
|
inline debug_iterator_base& debug_iterator_base::operator = (const debug_iterator_base& rhs) {
|
||||||
|
if (m_registry == rhs.m_registry)
|
||||||
|
return *this;
|
||||||
|
unregister_self();
|
||||||
|
m_registry = rhs.m_registry;
|
||||||
|
register_self();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool debug_iterator_base::is_valid(const debug_iterator_registry* registry) const {
|
||||||
|
return m_registry == registry;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void debug_iterator_base::invalidate() const { m_registry = 0; }
|
||||||
|
|
||||||
|
inline const debug_iterator_base* debug_iterator_base::next() const { return m_next; }
|
||||||
|
|
||||||
|
inline void debug_iterator_base::set_next(const debug_iterator_base* it) const { m_next = it; }
|
||||||
|
|
||||||
|
inline void debug_iterator_base::register_self() {
|
||||||
|
if (m_registry != 0)
|
||||||
|
m_registry->register_iterator(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void debug_iterator_base::unregister_self() {
|
||||||
|
if (m_registry != 0)
|
||||||
|
m_registry->unregister_iterator(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // #if BOOST_CB_ENABLE_DEBUG
|
||||||
|
|
||||||
|
} // namespace cb_details
|
||||||
|
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
#endif // #if !defined(BOOST_CIRCULAR_BUFFER_DEBUG_HPP)
|
||||||
@@ -0,0 +1,172 @@
|
|||||||
|
program ft8sim
|
||||||
|
|
||||||
|
! Generate simulated data for a 15-second HF/6m mode using 8-FSK.
|
||||||
|
! Output is saved to a *.wav file.
|
||||||
|
|
||||||
|
use wavhdr
|
||||||
|
include 'ft8_params.f90' !Set various constants
|
||||||
|
parameter (NWAVE=NN*NSPS)
|
||||||
|
type(hdr) h !Header for .wav file
|
||||||
|
character arg*12,fname*17
|
||||||
|
character msg40*40,msg*22,msgsent*22,msg0*22
|
||||||
|
character*6 mygrid6
|
||||||
|
logical bcontest
|
||||||
|
complex c0(0:NMAX-1)
|
||||||
|
complex c(0:NMAX-1)
|
||||||
|
real wave(NMAX)
|
||||||
|
integer itone(NN)
|
||||||
|
integer*1 msgbits(KK)
|
||||||
|
integer*2 iwave(NMAX) !Generated full-length waveform
|
||||||
|
data mygrid6/'EM48 '/
|
||||||
|
|
||||||
|
! Get command-line argument(s)
|
||||||
|
nargs=iargc()
|
||||||
|
if(nargs.ne.8) then
|
||||||
|
print*,'Usage: ft8sim "message" nsig|f0 DT fdop del width nfiles snr'
|
||||||
|
print*,'Examples: ft8sim "K1ABC W9XYZ EN37" 1500.0 0.0 0.1 1.0 0 10 -18'
|
||||||
|
print*,' ft8sim "K1ABC W9XYZ EN37" 10 0.0 0.1 1.0 25 10 -18'
|
||||||
|
print*,' ft8sim "K1ABC W9XYZ EN37" 25 0.0 0.1 1.0 25 10 -18'
|
||||||
|
print*,' ft8sim "K1ABC RR73; W9XYZ <KH1/KH7Z> -11" 300 0 0 0 25 1 -10'
|
||||||
|
print*,'Make nfiles negative to invoke 72-bit contest mode.'
|
||||||
|
go to 999
|
||||||
|
endif
|
||||||
|
call getarg(1,msg40) !Message to be transmitted
|
||||||
|
call getarg(2,arg)
|
||||||
|
read(arg,*) f0 !Frequency (only used for single-signal)
|
||||||
|
call getarg(3,arg)
|
||||||
|
read(arg,*) xdt !Time offset from nominal (s)
|
||||||
|
call getarg(4,arg)
|
||||||
|
read(arg,*) fspread !Watterson frequency spread (Hz)
|
||||||
|
call getarg(5,arg)
|
||||||
|
read(arg,*) delay !Watterson delay (ms)
|
||||||
|
call getarg(6,arg)
|
||||||
|
read(arg,*) width !Filter transition width (Hz)
|
||||||
|
call getarg(7,arg)
|
||||||
|
read(arg,*) nfiles !Number of files
|
||||||
|
call getarg(8,arg)
|
||||||
|
read(arg,*) snrdb !SNR_2500
|
||||||
|
nsig=1
|
||||||
|
if(f0.lt.100.0) then
|
||||||
|
nsig=f0
|
||||||
|
f0=1500
|
||||||
|
endif
|
||||||
|
|
||||||
|
bcontest=nfiles.lt.0
|
||||||
|
nfiles=abs(nfiles)
|
||||||
|
twopi=8.0*atan(1.0)
|
||||||
|
fs=12000.0 !Sample rate (Hz)
|
||||||
|
dt=1.0/fs !Sample interval (s)
|
||||||
|
tt=NSPS*dt !Duration of symbols (s)
|
||||||
|
baud=1.0/tt !Keying rate (baud)
|
||||||
|
bw=8*baud !Occupied bandwidth (Hz)
|
||||||
|
txt=NZ*dt !Transmission length (s)
|
||||||
|
bandwidth_ratio=2500.0/(fs/2.0)
|
||||||
|
sig=sqrt(2*bandwidth_ratio) * 10.0**(0.05*snrdb)
|
||||||
|
if(snrdb.gt.90.0) sig=1.0
|
||||||
|
txt=NN*NSPS/12000.0
|
||||||
|
|
||||||
|
! Source-encode, then get itone()
|
||||||
|
if(index(msg40,';').le.0) then
|
||||||
|
i3bit=0
|
||||||
|
msg=msg40(1:22)
|
||||||
|
call genft8(msg,mygrid6,bcontest,i3bit,msgsent,msgbits,itone)
|
||||||
|
write(*,1000) f0,xdt,txt,snrdb,bw,msgsent
|
||||||
|
1000 format('f0:',f9.3,' DT:',f6.2,' TxT:',f6.1,' SNR:',f6.1, &
|
||||||
|
' BW:',f4.1,2x,a22)
|
||||||
|
else
|
||||||
|
call foxgen_wrap(msg40,msgbits,itone)
|
||||||
|
write(*,1001) f0,xdt,txt,snrdb,bw,msg40
|
||||||
|
1001 format('f0:',f9.3,' DT:',f6.2,' TxT:',f6.1,' SNR:',f6.1, &
|
||||||
|
' BW:',f4.1,2x,a40)
|
||||||
|
endif
|
||||||
|
|
||||||
|
write(*,1030) msgbits(1:56)
|
||||||
|
1030 format(/'Call1: ',28i1,' Call2: ',28i1)
|
||||||
|
write(*,1032) msgbits(57:72),msgbits(73:75),msgbits(76:87)
|
||||||
|
1032 format('Grid: ',16i1,' 3Bit: ',3i1,' CRC12: ',12i1)
|
||||||
|
write(*,1034) itone
|
||||||
|
1034 format(/'Channel symbols:'/79i1/)
|
||||||
|
|
||||||
|
msg0=msg
|
||||||
|
do ifile=1,nfiles
|
||||||
|
c=0.
|
||||||
|
do isig=1,nsig
|
||||||
|
c0=0.
|
||||||
|
if(nsig.eq.2) then
|
||||||
|
if(index(msg,'R-').gt.0) f0=500
|
||||||
|
i1=index(msg,' ')
|
||||||
|
msg(i1+4:i1+4)=char(ichar('A')+isig-1)
|
||||||
|
if(isig.eq.2) then
|
||||||
|
f0=f0+100
|
||||||
|
endif
|
||||||
|
call genft8(msg,mygrid6,bcontest,i3bit,msgsent,msgbits,itone)
|
||||||
|
endif
|
||||||
|
if(nsig.eq.25) then
|
||||||
|
f0=(isig+2)*100.0
|
||||||
|
else if(nsig.eq.50) then
|
||||||
|
msg=msg0
|
||||||
|
f0=1000.0 + (isig-1)*60.0
|
||||||
|
i1=index(msg,' ')
|
||||||
|
i2=index(msg(i1+1:),' ') + i1
|
||||||
|
msg(i1+2:i1+2)=char(ichar('0')+mod(isig-1,10))
|
||||||
|
msg(i1+3:i1+3)=char(ichar('A')+mod(isig-1,26))
|
||||||
|
msg(i1+4:i1+4)=char(ichar('A')+mod(isig-1,26))
|
||||||
|
msg(i1+5:i1+5)=char(ichar('A')+mod(isig-1,26))
|
||||||
|
write(msg(i2+3:i2+4),'(i2.2)') isig-1
|
||||||
|
if(ifile.ge.2 .and. isig.eq.ifile-1) then
|
||||||
|
write(msg(i2+1:i2+4),1002) -isig
|
||||||
|
1002 format('R',i3.2)
|
||||||
|
f0=600.0 + mod(isig-1,5)*60.0
|
||||||
|
endif
|
||||||
|
call genft8(msg,mygrid6,bcontest,i3bit,msgsent,msgbits,itone)
|
||||||
|
endif
|
||||||
|
k=-1 + nint((xdt+0.5+0.01*gran())/dt)
|
||||||
|
! k=-1 + nint((xdt+0.5)/dt)
|
||||||
|
ia=k+1
|
||||||
|
phi=0.0
|
||||||
|
do j=1,NN !Generate complex waveform
|
||||||
|
dphi=twopi*(f0+itone(j)*baud)*dt
|
||||||
|
do i=1,NSPS
|
||||||
|
k=k+1
|
||||||
|
phi=mod(phi+dphi,twopi)
|
||||||
|
if(k.ge.0 .and. k.lt.NMAX) c0(k)=cmplx(cos(phi),sin(phi))
|
||||||
|
enddo
|
||||||
|
enddo
|
||||||
|
if(fspread.ne.0.0 .or. delay.ne.0.0) call watterson(c0,NMAX,fs,delay,fspread)
|
||||||
|
c=c+sig*c0
|
||||||
|
enddo
|
||||||
|
ib=k
|
||||||
|
wave=real(c)
|
||||||
|
peak=maxval(abs(wave(ia:ib)))
|
||||||
|
rms=sqrt(dot_product(wave(ia:ib),wave(ia:ib))/NWAVE)
|
||||||
|
nslots=1
|
||||||
|
if(width.gt.0.0) call filt8(f0,nslots,width,wave)
|
||||||
|
|
||||||
|
if(snrdb.lt.90) then
|
||||||
|
do i=1,NMAX !Add gaussian noise at specified SNR
|
||||||
|
xnoise=gran()
|
||||||
|
! wave(i)=wave(i) + xnoise
|
||||||
|
! if(i.ge.ia .and. i.le.ib) write(30,3001) i,wave(i)/peak
|
||||||
|
!3001 format(i8,f12.6)
|
||||||
|
wave(i)=wave(i) + xnoise
|
||||||
|
enddo
|
||||||
|
endif
|
||||||
|
|
||||||
|
fac=32767.0
|
||||||
|
rms=100.0
|
||||||
|
if(snrdb.ge.90.0) iwave(1:NMAX)=nint(fac*wave)
|
||||||
|
if(snrdb.lt.90.0) iwave(1:NMAX)=nint(rms*wave)
|
||||||
|
|
||||||
|
h=default_header(12000,NMAX)
|
||||||
|
write(fname,1102) ifile
|
||||||
|
1102 format('000000_',i6.6,'.wav')
|
||||||
|
open(10,file=fname,status='unknown',access='stream')
|
||||||
|
write(10) h,iwave !Save to *.wav file
|
||||||
|
close(10)
|
||||||
|
write(*,1110) ifile,xdt,f0,snrdb,fname
|
||||||
|
1110 format(i4,f7.2,f8.2,f7.1,2x,a17)
|
||||||
|
enddo
|
||||||
|
|
||||||
|
999 end program ft8sim
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
0; 0; 0
|
||||||
|
0; 0; 9
|
||||||
|
0; 0; 21
|
||||||
|
0; 0; 34
|
||||||
|
0; 0; 45
|
||||||
|
0; 0; 57
|
||||||
|
0; 0; 67
|
||||||
|
0; 0; 77
|
||||||
|
0; 0; 86
|
||||||
|
0; 0; 94
|
||||||
|
0; 12;101
|
||||||
|
0; 23;106
|
||||||
|
0; 35;110
|
||||||
|
0; 46;113
|
||||||
|
0; 57;115
|
||||||
|
0; 68;115
|
||||||
|
0; 78;114
|
||||||
|
0; 88;112
|
||||||
|
0; 97;108
|
||||||
|
0;106;103
|
||||||
|
0;114; 97
|
||||||
|
0;122; 90
|
||||||
|
0;129; 81
|
||||||
|
0;136; 72
|
||||||
|
0;141; 62
|
||||||
|
0;146; 51
|
||||||
|
0;151; 39
|
||||||
|
11;154; 27
|
||||||
|
29;157; 15
|
||||||
|
46;158; 2
|
||||||
|
63;159; 0
|
||||||
|
79;159; 0
|
||||||
|
96;159; 0
|
||||||
|
111;157; 0
|
||||||
|
127;155; 0
|
||||||
|
142;152; 0
|
||||||
|
156;148; 0
|
||||||
|
169;143; 0
|
||||||
|
182;138; 0
|
||||||
|
193;131; 0
|
||||||
|
204;124; 0
|
||||||
|
214;117; 0
|
||||||
|
223;109; 0
|
||||||
|
231;100; 0
|
||||||
|
238; 91; 0
|
||||||
|
244; 81; 0
|
||||||
|
248; 71; 0
|
||||||
|
252; 60; 5
|
||||||
|
254; 50; 19
|
||||||
|
255; 38; 33
|
||||||
|
255; 47; 47
|
||||||
|
255; 61; 61
|
||||||
|
255; 75; 75
|
||||||
|
255; 90; 90
|
||||||
|
255;105;105
|
||||||
|
255;121;121
|
||||||
|
255;138;138
|
||||||
|
255;156;156
|
||||||
|
255;175;175
|
||||||
|
255;196;196
|
||||||
|
255;218;218
|
||||||
|
255;243;243
|
||||||
|
255;255;255
|
||||||
|
255;255;255
|
||||||
|
255;255;255
|
||||||
Binary file not shown.
@@ -0,0 +1,87 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>wf_palette_design_dialog</class>
|
||||||
|
<widget class="QDialog" name="wf_palette_design_dialog">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>219</width>
|
||||||
|
<height>209</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Palette Designer</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QTableWidget" name="colour_table_widget">
|
||||||
|
<property name="contextMenuPolicy">
|
||||||
|
<enum>Qt::CustomContextMenu</enum>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p>Double click a color to edit it.</p><p>Right click to insert or delete colors.</p><p>Colors at the top represent weak signals</p><p>and colors at the bottom represent strong</p><p>signals. You can have up to 256 colors.</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="selectionMode">
|
||||||
|
<enum>QAbstractItemView::NoSelection</enum>
|
||||||
|
</property>
|
||||||
|
<property name="columnCount">
|
||||||
|
<number>1</number>
|
||||||
|
</property>
|
||||||
|
<attribute name="horizontalHeaderVisible">
|
||||||
|
<bool>false</bool>
|
||||||
|
</attribute>
|
||||||
|
<attribute name="horizontalHeaderStretchLastSection">
|
||||||
|
<bool>true</bool>
|
||||||
|
</attribute>
|
||||||
|
<column/>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QDialogButtonBox" name="button_box">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="standardButtons">
|
||||||
|
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections>
|
||||||
|
<connection>
|
||||||
|
<sender>button_box</sender>
|
||||||
|
<signal>accepted()</signal>
|
||||||
|
<receiver>wf_palette_design_dialog</receiver>
|
||||||
|
<slot>accept()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>248</x>
|
||||||
|
<y>254</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>157</x>
|
||||||
|
<y>274</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
<connection>
|
||||||
|
<sender>button_box</sender>
|
||||||
|
<signal>rejected()</signal>
|
||||||
|
<receiver>wf_palette_design_dialog</receiver>
|
||||||
|
<slot>reject()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>316</x>
|
||||||
|
<y>260</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>286</x>
|
||||||
|
<y>274</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
</connections>
|
||||||
|
</ui>
|
||||||
@@ -1,237 +0,0 @@
|
|||||||
#include "CyclesOfGraph.h"
|
|
||||||
|
|
||||||
NodesOfGraph::NodesOfGraph(void) { parityConnections=NULL;symbolConnections=NULL;
|
|
||||||
}
|
|
||||||
NodesOfGraph::~NodesOfGraph(void) {
|
|
||||||
delete [] parityConnections;
|
|
||||||
delete [] symbolConnections;
|
|
||||||
delete [] symbolMapping;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void NodesOfGraph::setParityConnections(int num, int *value) {
|
|
||||||
numOfParityConnections=num;
|
|
||||||
parityConnections=new int[num];
|
|
||||||
for(int i=0;i<numOfParityConnections;i++){
|
|
||||||
parityConnections[i]=value[i];
|
|
||||||
//cout<<parityConnections[i]<<" ";
|
|
||||||
}
|
|
||||||
//cout<<endl;
|
|
||||||
}
|
|
||||||
void NodesOfGraph::setSymbolConnections(int num, int *value) {
|
|
||||||
numOfSymbolConnections=num;
|
|
||||||
symbolConnections=new int[num];
|
|
||||||
for(int i=0;i<numOfSymbolConnections;i++){
|
|
||||||
symbolConnections[i]=value[i];
|
|
||||||
//cout<<symbolConnections[i]<<" ";
|
|
||||||
}
|
|
||||||
//cout<<endl;
|
|
||||||
}
|
|
||||||
void NodesOfGraph::setSymbolMapping(int num, int *value) {
|
|
||||||
numOfSymbolMapping=num;
|
|
||||||
//cout<<num<<endl;
|
|
||||||
symbolMapping=new int[num];
|
|
||||||
for(int i=0;i<numOfSymbolMapping;i++){
|
|
||||||
symbolMapping[i]=value[i];
|
|
||||||
//cout<<symbolMapping[i]<<" ";
|
|
||||||
}
|
|
||||||
//cout<<endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
CyclesOfGraph::CyclesOfGraph(int mm, int n, int *(*h)){
|
|
||||||
int i, j, k, m, index;
|
|
||||||
M=mm;
|
|
||||||
N=n;
|
|
||||||
H=h;
|
|
||||||
|
|
||||||
tmp=new int [N];
|
|
||||||
med=new int [N];
|
|
||||||
tmpCycles=new int [N];
|
|
||||||
cyclesTable=new int [N];
|
|
||||||
nodesOfGraph=new NodesOfGraph [N];
|
|
||||||
|
|
||||||
//cout<<M<<" "<<N<<endl;
|
|
||||||
/*
|
|
||||||
for(i=0;i<M;i++){
|
|
||||||
for(j=0;j<N;j++)
|
|
||||||
cout<<H[i][j]<<" ";
|
|
||||||
cout<<endl;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
for(i=0;i<N;i++){
|
|
||||||
index=0;
|
|
||||||
for(j=0;j<M;j++){
|
|
||||||
if(H[j][i]==1){
|
|
||||||
tmp[index]=j;
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
nodesOfGraph[i].setSymbolConnections(index, tmp);
|
|
||||||
}
|
|
||||||
for(i=0;i<M;i++){
|
|
||||||
index=0;
|
|
||||||
for(j=0;j<N;j++){
|
|
||||||
if(H[i][j]==1){
|
|
||||||
tmp[index]=j;
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
nodesOfGraph[i].setParityConnections(index, tmp);
|
|
||||||
}
|
|
||||||
for(i=0;i<N;i++){
|
|
||||||
index=0;
|
|
||||||
for(j=0;j<nodesOfGraph[i].numOfSymbolConnections;j++){
|
|
||||||
for(k=0;k<nodesOfGraph[nodesOfGraph[i].symbolConnections[j]].numOfParityConnections;k++){
|
|
||||||
int t=0;
|
|
||||||
for(m=0;m<index;m++){
|
|
||||||
if(nodesOfGraph[nodesOfGraph[i].symbolConnections[j]].parityConnections[k]==tmp[m]){
|
|
||||||
t=1; break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(nodesOfGraph[nodesOfGraph[i].symbolConnections[j]].parityConnections[k]==i) t=1;
|
|
||||||
if(t==0) {
|
|
||||||
tmp[index]=nodesOfGraph[nodesOfGraph[i].symbolConnections[j]].parityConnections[k];
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
nodesOfGraph[i].setSymbolMapping(index, tmp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CyclesOfGraph::~CyclesOfGraph(void){
|
|
||||||
delete [] tmp;
|
|
||||||
tmp=NULL;
|
|
||||||
delete [] med;
|
|
||||||
med=NULL;
|
|
||||||
delete [] tmpCycles;
|
|
||||||
tmpCycles=NULL;
|
|
||||||
delete [] cyclesTable;
|
|
||||||
cyclesTable=NULL;
|
|
||||||
delete [] nodesOfGraph;
|
|
||||||
nodesOfGraph=NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CyclesOfGraph::getCyclesTable(void) {
|
|
||||||
int i, j, k, m, n, t, imed;
|
|
||||||
for(i=0;i<N;i++){
|
|
||||||
//special handlement for nodes having only one or zero connections
|
|
||||||
if(nodesOfGraph[i].numOfSymbolConnections<=1) {
|
|
||||||
cyclesTable[i]=2*N;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for(j=0;j<nodesOfGraph[i].numOfSymbolConnections-1;j++){ //-1 because the graph is undirected
|
|
||||||
for(k=0;k<nodesOfGraph[nodesOfGraph[i].symbolConnections[j]].numOfParityConnections;k++){
|
|
||||||
tmp[k]=nodesOfGraph[nodesOfGraph[i].symbolConnections[j]].parityConnections[k];
|
|
||||||
//cout<<tmp[k]<<" ";
|
|
||||||
}
|
|
||||||
//cout<<endl;
|
|
||||||
int cycles=2;
|
|
||||||
int index=nodesOfGraph[nodesOfGraph[i].symbolConnections[j]].numOfParityConnections;
|
|
||||||
LOOP:
|
|
||||||
imed=0;
|
|
||||||
for(k=0;k<index;k++){
|
|
||||||
if(tmp[k]==i) continue;
|
|
||||||
//cout<<"k="<<k<<" "<<tmp[k]<<endl;
|
|
||||||
for(m=0;m<nodesOfGraph[tmp[k]].numOfSymbolConnections;m++){
|
|
||||||
for(n=0;n<nodesOfGraph[i].numOfSymbolConnections;n++){
|
|
||||||
if((n!=j)&&(nodesOfGraph[tmp[k]].symbolConnections[m]==nodesOfGraph[i].symbolConnections[n])){
|
|
||||||
cycles+=2;
|
|
||||||
goto OUTLOOP;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for(m=0;m<nodesOfGraph[tmp[k]].numOfSymbolMapping;m++){
|
|
||||||
t=0;
|
|
||||||
for(int l=0;l<imed;l++) {
|
|
||||||
if(nodesOfGraph[tmp[k]].symbolMapping[m]==med[l]){
|
|
||||||
t=1; break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(t==0){
|
|
||||||
med[imed]=nodesOfGraph[tmp[k]].symbolMapping[m];
|
|
||||||
//cout<<med[imed]<<endl;
|
|
||||||
imed++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
index=imed;//cout<<index<<" "<<endl;
|
|
||||||
for(k=0;k<index;k++) {
|
|
||||||
tmp[k]=med[k];//cout<<tmp[k]<<" ";
|
|
||||||
}
|
|
||||||
//cout<<"j="<<j<<endl;
|
|
||||||
cycles+=2;
|
|
||||||
if(cycles>=2*N) //dead lock
|
|
||||||
goto OUTLOOP;
|
|
||||||
else
|
|
||||||
goto LOOP;
|
|
||||||
OUTLOOP:
|
|
||||||
tmpCycles[j]=cycles;
|
|
||||||
}
|
|
||||||
//for(j=0;j<nodesOfGraph[i].numOfSymbolConnections-1;j++) cout<<tmpCycles[j]<<" ";
|
|
||||||
//cout<<endl;
|
|
||||||
cyclesTable[i]=tmpCycles[0];
|
|
||||||
for(j=1;j<nodesOfGraph[i].numOfSymbolConnections-1;j++){
|
|
||||||
if(cyclesTable[i]>tmpCycles[j])
|
|
||||||
cyclesTable[i]=tmpCycles[j];
|
|
||||||
}
|
|
||||||
//OUTPUT cycles per symbol node
|
|
||||||
//cout<<"i="<<i<<" "<<cyclesTable[i]<<endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int CyclesOfGraph::girth(void) {
|
|
||||||
int girth=2*N;
|
|
||||||
for(int i=0;i<N;i++)
|
|
||||||
if(girth>cyclesTable[i]) girth=cyclesTable[i];
|
|
||||||
return(girth);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CyclesOfGraph::printCyclesTable(void){
|
|
||||||
using namespace std;
|
|
||||||
int i, temp[20];
|
|
||||||
/*
|
|
||||||
for(i=0;i<N;i++)
|
|
||||||
cout<<cyclesTable[i]<<" ";
|
|
||||||
cout<<endl;
|
|
||||||
*/
|
|
||||||
for(i=0;i<20;i++) temp[i]=0;
|
|
||||||
for(i=0;i<N;i++){
|
|
||||||
if(cyclesTable[i]==4) temp[0]++;
|
|
||||||
else if(cyclesTable[i]==6) temp[1]++;
|
|
||||||
else if(cyclesTable[i]==8) temp[2]++;
|
|
||||||
else if(cyclesTable[i]==10) temp[3]++;
|
|
||||||
else if(cyclesTable[i]==12) temp[4]++;
|
|
||||||
else if(cyclesTable[i]==14) temp[5]++;
|
|
||||||
else if(cyclesTable[i]==16) temp[6]++;
|
|
||||||
else if(cyclesTable[i]==18) temp[7]++;
|
|
||||||
else if(cyclesTable[i]==20) temp[8]++;
|
|
||||||
else if(cyclesTable[i]==22) temp[9]++;
|
|
||||||
else if(cyclesTable[i]==24) temp[10]++;
|
|
||||||
else if(cyclesTable[i]==26) temp[11]++;
|
|
||||||
else if(cyclesTable[i]==28) temp[12]++;
|
|
||||||
else if(cyclesTable[i]==30) temp[13]++;
|
|
||||||
else {
|
|
||||||
cout<<"Wrong cycles calculation "<<cyclesTable[i]<<endl;
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cout<<endl;
|
|
||||||
cout<<"Num of Nodes with local girth 4: "<< temp[0]<<endl;
|
|
||||||
cout<<"Num of Nodes with local girth 6: "<< temp[1]<<endl;
|
|
||||||
cout<<"Num of Nodes with local girth 8: "<< temp[2]<<endl;
|
|
||||||
cout<<"Num of Nodes with local girth 10: "<< temp[3]<<endl;
|
|
||||||
cout<<"Num of Nodes with local girth 12: "<< temp[4]<<endl;
|
|
||||||
cout<<"Num of Nodes with local girth 14: "<< temp[5]<<endl;
|
|
||||||
cout<<"Num of Nodes with local girth 16: "<< temp[6]<<endl;
|
|
||||||
cout<<"Num of Nodes with local girth 18: "<< temp[7]<<endl;
|
|
||||||
cout<<"Num of Nodes with local girth 20: "<< temp[8]<<endl;
|
|
||||||
cout<<"Num of Nodes with local girth 22: "<< temp[9]<<endl;
|
|
||||||
cout<<"Num of Nodes with local girth 24: "<< temp[10]<<endl;
|
|
||||||
cout<<"Num of Nodes with local girth 26: "<< temp[11]<<endl;
|
|
||||||
cout<<"Num of Nodes with local girth 28: "<< temp[12]<<endl;
|
|
||||||
cout<<"Num of Nodes with local girth 30: "<< temp[13]<<endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,147 +0,0 @@
|
|||||||
/* MOD2SPARSE.H - Interface to module for handling sparse mod2 matrices. */
|
|
||||||
|
|
||||||
/* Copyright (c) 1995-2012 by Radford M. Neal.
|
|
||||||
*
|
|
||||||
* Permission is granted for anyone to copy, use, modify, and distribute
|
|
||||||
* these programs and accompanying documents for any purpose, provided
|
|
||||||
* this copyright notice is retained and prominently displayed, and note
|
|
||||||
* is made of any changes made to these programs. These programs and
|
|
||||||
* documents are distributed without any warranty, express or implied.
|
|
||||||
* As the programs were written for research purposes only, they have not
|
|
||||||
* been tested to the degree that would be advisable in any important
|
|
||||||
* application. All use of these programs is entirely at the user's own
|
|
||||||
* risk.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/* This module implements operations on sparse matrices of mod2 elements
|
|
||||||
(bits, with addition and multiplication being done modulo 2).
|
|
||||||
|
|
||||||
All procedures in this module display an error message on standard
|
|
||||||
error and terminate the program if passed an invalid argument (indicative
|
|
||||||
of a programming error), or if memory cannot be allocated. Errors from
|
|
||||||
invalid contents of a file result in an error code being returned to the
|
|
||||||
caller, with no message being printed by this module.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/* DATA STRUCTURES USED TO STORE A SPARSE MATRIX. Non-zero entries (ie, 1s)
|
|
||||||
are represented by nodes that are doubly-linked both by row and by column,
|
|
||||||
with the headers for these lists being kept in arrays. Nodes are allocated
|
|
||||||
in blocks to reduce time and space overhead. Freed nodes are kept for
|
|
||||||
reuse in the same matrix, rather than being freed for other uses, except
|
|
||||||
that they are all freed when the matrix is cleared to all zeros by the
|
|
||||||
mod2sparse_clear procedure, or copied into by mod2sparse_copy.
|
|
||||||
|
|
||||||
Direct access to these structures should be avoided except in low-level
|
|
||||||
routines. Use the macros and procedures defined below instead. */
|
|
||||||
|
|
||||||
typedef struct mod2entry /* Structure representing a non-zero entry, or
|
|
||||||
the header for a row or column */
|
|
||||||
{
|
|
||||||
int row, col; /* Row and column indexes of this entry, starting
|
|
||||||
at 0, and with -1 for a row or column header */
|
|
||||||
|
|
||||||
struct mod2entry *left, *right, /* Pointers to entries adjacent in row */
|
|
||||||
*up, *down; /* and column, or to headers. Free */
|
|
||||||
/* entries are linked by 'left'. */
|
|
||||||
|
|
||||||
double pr, lr; /* Probability and likelihood ratios - not used */
|
|
||||||
/* by the mod2sparse module itself */
|
|
||||||
} mod2entry;
|
|
||||||
|
|
||||||
#define Mod2sparse_block 10 /* Number of entries to block together for
|
|
||||||
memory allocation */
|
|
||||||
|
|
||||||
typedef struct mod2block /* Block of entries allocated all at once */
|
|
||||||
{
|
|
||||||
struct mod2block *next; /* Next block that has been allocated */
|
|
||||||
|
|
||||||
mod2entry entry[Mod2sparse_block]; /* Entries in this block */
|
|
||||||
|
|
||||||
} mod2block;
|
|
||||||
|
|
||||||
typedef struct /* Representation of a sparse matrix */
|
|
||||||
{
|
|
||||||
int n_rows; /* Number of rows in the matrix */
|
|
||||||
int n_cols; /* Number of columns in the matrix */
|
|
||||||
|
|
||||||
mod2entry *rows; /* Pointer to array of row headers */
|
|
||||||
mod2entry *cols; /* Pointer to array of column headers */
|
|
||||||
|
|
||||||
mod2block *blocks; /* Blocks that have been allocated */
|
|
||||||
mod2entry *next_free; /* Next free entry */
|
|
||||||
|
|
||||||
} mod2sparse;
|
|
||||||
|
|
||||||
|
|
||||||
/* MACROS TO GET AT ELEMENTS OF A SPARSE MATRIX. The 'first', 'last', 'next',
|
|
||||||
and 'prev' macros traverse the elements in a row or column. Moving past
|
|
||||||
the first/last element gets one to a header element, which can be identified
|
|
||||||
using the 'at_end' macro. Macros also exist for finding out the row
|
|
||||||
and column of an entry, and for finding out the dimensions of a matrix. */
|
|
||||||
|
|
||||||
#define mod2sparse_first_in_row(m,i) ((m)->rows[i].right) /* Find the first */
|
|
||||||
#define mod2sparse_first_in_col(m,j) ((m)->cols[j].down) /* or last entry in */
|
|
||||||
#define mod2sparse_last_in_row(m,i) ((m)->rows[i].left) /* a row or column */
|
|
||||||
#define mod2sparse_last_in_col(m,j) ((m)->cols[j].up)
|
|
||||||
|
|
||||||
#define mod2sparse_next_in_row(e) ((e)->right) /* Move from one entry to */
|
|
||||||
#define mod2sparse_next_in_col(e) ((e)->down) /* another in any of the four */
|
|
||||||
#define mod2sparse_prev_in_row(e) ((e)->left) /* possible directions */
|
|
||||||
#define mod2sparse_prev_in_col(e) ((e)->up)
|
|
||||||
|
|
||||||
#define mod2sparse_at_end(e) ((e)->row<0) /* See if we've reached the end */
|
|
||||||
|
|
||||||
#define mod2sparse_row(e) ((e)->row) /* Find out the row or column index */
|
|
||||||
#define mod2sparse_col(e) ((e)->col) /* of an entry (indexes start at 0) */
|
|
||||||
|
|
||||||
#define mod2sparse_rows(m) ((m)->n_rows) /* Get the number of rows or columns*/
|
|
||||||
#define mod2sparse_cols(m) ((m)->n_cols) /* in a matrix */
|
|
||||||
|
|
||||||
|
|
||||||
/* POSSIBLE LU DECOMPOSITION STRATEGIES. For use with mod2sparse_decomp. */
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{ Mod2sparse_first,
|
|
||||||
Mod2sparse_mincol,
|
|
||||||
Mod2sparse_minprod
|
|
||||||
} mod2sparse_strategy;
|
|
||||||
|
|
||||||
|
|
||||||
/* PROCEDURES TO MANIPULATE SPARSE MATRICES. */
|
|
||||||
|
|
||||||
mod2sparse *mod2sparse_allocate (int, int);
|
|
||||||
void mod2sparse_free (mod2sparse *);
|
|
||||||
|
|
||||||
void mod2sparse_clear (mod2sparse *);
|
|
||||||
void mod2sparse_copy (mod2sparse *, mod2sparse *);
|
|
||||||
void mod2sparse_copyrows (mod2sparse *, mod2sparse *, int *);
|
|
||||||
void mod2sparse_copycols (mod2sparse *, mod2sparse *, int *);
|
|
||||||
|
|
||||||
void mod2sparse_print (FILE *, mod2sparse *);
|
|
||||||
int mod2sparse_write (FILE *, mod2sparse *);
|
|
||||||
mod2sparse *mod2sparse_read (FILE *);
|
|
||||||
|
|
||||||
mod2entry *mod2sparse_find (mod2sparse *, int, int);
|
|
||||||
mod2entry *mod2sparse_insert (mod2sparse *, int, int);
|
|
||||||
void mod2sparse_delete (mod2sparse *, mod2entry *);
|
|
||||||
|
|
||||||
void mod2sparse_transpose (mod2sparse *, mod2sparse *);
|
|
||||||
void mod2sparse_add (mod2sparse *, mod2sparse *, mod2sparse *);
|
|
||||||
void mod2sparse_multiply (mod2sparse *, mod2sparse *, mod2sparse *);
|
|
||||||
void mod2sparse_mulvec (mod2sparse *, char *, char *);
|
|
||||||
|
|
||||||
int mod2sparse_equal (mod2sparse *, mod2sparse *);
|
|
||||||
|
|
||||||
int mod2sparse_count_row (mod2sparse *, int);
|
|
||||||
int mod2sparse_count_col (mod2sparse *, int);
|
|
||||||
|
|
||||||
void mod2sparse_add_row (mod2sparse *, int, mod2sparse *, int);
|
|
||||||
void mod2sparse_add_col (mod2sparse *, int, mod2sparse *, int);
|
|
||||||
|
|
||||||
int mod2sparse_decomp (mod2sparse *, int, mod2sparse *, mod2sparse *,
|
|
||||||
int *, int *, mod2sparse_strategy, int, int);
|
|
||||||
|
|
||||||
int mod2sparse_forward_sub (mod2sparse *, int *, char *, char *);
|
|
||||||
int mod2sparse_backward_sub (mod2sparse *, int *, char *, char *);
|
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
@ECHO OFF
|
||||||
|
|
||||||
|
REM Copyright (C) 2009 Vladimir Prus
|
||||||
|
REM
|
||||||
|
REM Distributed under the Boost Software License, Version 1.0.
|
||||||
|
REM (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
|
||||||
|
ECHO Building Boost.Build engine
|
||||||
|
if exist ".\tools\build\src\engine\bin.ntx86\b2.exe" del tools\build\src\engine\bin.ntx86\b2.exe
|
||||||
|
if exist ".\tools\build\src\engine\bin.ntx86\bjam.exe" del tools\build\src\engine\bin.ntx86\bjam.exe
|
||||||
|
if exist ".\tools\build\src\engine\bin.ntx86_64\b2.exe" del tools\build\src\engine\bin.ntx86_64\b2.exe
|
||||||
|
if exist ".\tools\build\src\engine\bin.ntx86_64\bjam.exe" del tools\build\src\engine\bin.ntx86_64\bjam.exe
|
||||||
|
pushd tools\build\src\engine
|
||||||
|
|
||||||
|
call .\build.bat %* > ..\..\..\..\bootstrap.log
|
||||||
|
@ECHO OFF
|
||||||
|
|
||||||
|
popd
|
||||||
|
|
||||||
|
if exist ".\tools\build\src\engine\bin.ntx86\bjam.exe" (
|
||||||
|
copy .\tools\build\src\engine\bin.ntx86\b2.exe . > nul
|
||||||
|
copy .\tools\build\src\engine\bin.ntx86\bjam.exe . > nul
|
||||||
|
goto :bjam_built)
|
||||||
|
|
||||||
|
if exist ".\tools\build\src\engine\bin.ntx86_64\bjam.exe" (
|
||||||
|
copy .\tools\build\src\engine\bin.ntx86_64\b2.exe . > nul
|
||||||
|
copy .\tools\build\src\engine\bin.ntx86_64\bjam.exe . > nul
|
||||||
|
goto :bjam_built)
|
||||||
|
|
||||||
|
goto :bjam_failure
|
||||||
|
|
||||||
|
:bjam_built
|
||||||
|
|
||||||
|
REM Ideally, we should obtain the toolset that build.bat has
|
||||||
|
REM guessed. However, it uses setlocal at the start and does not
|
||||||
|
REM export BOOST_JAM_TOOLSET, and I don't know how to do that
|
||||||
|
REM properly. Default to msvc for now.
|
||||||
|
set toolset=msvc
|
||||||
|
|
||||||
|
ECHO import option ; > project-config.jam
|
||||||
|
ECHO. >> project-config.jam
|
||||||
|
ECHO using %toolset% ; >> project-config.jam
|
||||||
|
ECHO. >> project-config.jam
|
||||||
|
ECHO option.set keep-going : false ; >> project-config.jam
|
||||||
|
ECHO. >> project-config.jam
|
||||||
|
|
||||||
|
ECHO.
|
||||||
|
ECHO Bootstrapping is done. To build, run:
|
||||||
|
ECHO.
|
||||||
|
ECHO .\b2
|
||||||
|
ECHO.
|
||||||
|
ECHO To adjust configuration, edit 'project-config.jam'.
|
||||||
|
ECHO Further information:
|
||||||
|
ECHO.
|
||||||
|
ECHO - Command line help:
|
||||||
|
ECHO .\b2 --help
|
||||||
|
ECHO.
|
||||||
|
ECHO - Getting started guide:
|
||||||
|
ECHO http://boost.org/more/getting_started/windows.html
|
||||||
|
ECHO.
|
||||||
|
ECHO - Boost.Build documentation:
|
||||||
|
ECHO http://www.boost.org/build/doc/html/index.html
|
||||||
|
|
||||||
|
goto :end
|
||||||
|
|
||||||
|
:bjam_failure
|
||||||
|
|
||||||
|
ECHO.
|
||||||
|
ECHO Failed to build Boost.Build engine.
|
||||||
|
ECHO Please consult bootstrap.log for further diagnostics.
|
||||||
|
ECHO.
|
||||||
|
ECHO You can try to obtain a prebuilt binary from
|
||||||
|
ECHO.
|
||||||
|
ECHO http://sf.net/project/showfiles.php?group_id=7586^&package_id=72941
|
||||||
|
ECHO.
|
||||||
|
ECHO Also, you can file an issue at http://svn.boost.org
|
||||||
|
ECHO Please attach bootstrap.log in that case.
|
||||||
|
|
||||||
|
goto :end
|
||||||
|
|
||||||
|
:end
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
subroutine unpackpfx(ng,call1)
|
||||||
|
|
||||||
|
character*12 call1
|
||||||
|
character*3 pfx
|
||||||
|
|
||||||
|
if(ng.lt.60000) then
|
||||||
|
! Add-on prefix of 1 to 3 characters
|
||||||
|
n=ng
|
||||||
|
do i=3,1,-1
|
||||||
|
nc=mod(n,37)
|
||||||
|
if(nc.ge.0 .and. nc.le.9) then
|
||||||
|
pfx(i:i)=char(nc+48)
|
||||||
|
else if(nc.ge.10 .and. nc.le.35) then
|
||||||
|
pfx(i:i)=char(nc+55)
|
||||||
|
else
|
||||||
|
pfx(i:i)=' '
|
||||||
|
endif
|
||||||
|
n=n/37
|
||||||
|
enddo
|
||||||
|
call1=pfx//'/'//call1
|
||||||
|
if(call1(1:1).eq.' ') call1=call1(2:)
|
||||||
|
if(call1(1:1).eq.' ') call1=call1(2:)
|
||||||
|
else
|
||||||
|
! Add-on suffix, one character
|
||||||
|
i1=index(call1,' ')
|
||||||
|
nc=ng-60000
|
||||||
|
if(nc.ge.0 .and. nc.le.9) then
|
||||||
|
call1=call1(:i1-1)//'/'//char(nc+48)
|
||||||
|
else if(nc.ge.10 .and. nc.le.35) then
|
||||||
|
call1=call1(:i1-1)//'/'//char(nc+55)
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
return
|
||||||
|
end subroutine unpackpfx
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
128
|
|
||||||
48
|
|
||||||
9
|
|
||||||
1 17 34 51 66 81 99 111 124
|
|
||||||
2 18 35 50 67 82 100 112 125
|
|
||||||
3 19 36 52 68 82 101 111 126
|
|
||||||
2 20 36 51 69 83 102 113 127
|
|
||||||
4 19 37 53 66 84 103 114 128
|
|
||||||
5 21 38 54 70 85 92 114 0
|
|
||||||
6 22 39 55 66 85 96 110 0
|
|
||||||
7 23 32 56 71 86 103 115 0
|
|
||||||
8 20 40 55 72 86 104 116 0
|
|
||||||
9 19 41 57 73 87 105 116 0
|
|
||||||
10 24 36 56 74 88 105 117 125
|
|
||||||
10 17 33 47 75 89 106 118 128
|
|
||||||
11 21 42 51 76 87 107 119 0
|
|
||||||
1 25 40 58 74 84 107 113 0
|
|
||||||
12 22 42 49 77 90 108 118 125
|
|
||||||
13 26 43 59 68 89 104 120 124
|
|
||||||
13 22 44 57 75 91 109 113 0
|
|
||||||
12 23 37 46 78 88 107 112 0
|
|
||||||
3 27 34 60 65 87 109 118 0
|
|
||||||
6 27 45 61 79 89 98 112 0
|
|
||||||
14 28 34 62 72 92 106 112 127
|
|
||||||
8 27 42 59 71 92 110 121 126
|
|
||||||
15 20 46 57 79 93 101 115 124
|
|
||||||
9 29 45 62 74 94 108 121 0
|
|
||||||
8 30 38 63 73 95 109 111 128
|
|
||||||
16 29 47 64 69 96 109 117 126
|
|
||||||
16 23 48 63 76 94 110 116 125
|
|
||||||
7 25 39 52 70 97 106 117 124
|
|
||||||
4 26 45 63 67 83 90 119 123
|
|
||||||
15 28 39 50 76 88 103 121 123
|
|
||||||
15 26 33 58 65 97 102 122 0
|
|
||||||
14 31 47 52 77 81 93 116 0
|
|
||||||
14 24 37 61 71 82 99 122 0
|
|
||||||
4 31 40 54 80 91 106 115 122
|
|
||||||
5 32 41 58 77 98 104 117 0
|
|
||||||
9 18 49 65 79 85 104 119 128
|
|
||||||
10 30 43 60 69 84 108 115 123
|
|
||||||
1 18 43 48 73 91 98 114 127
|
|
||||||
3 21 46 64 67 86 108 113 0
|
|
||||||
5 24 48 55 75 93 107 120 126
|
|
||||||
2 32 44 62 80 95 99 114 0
|
|
||||||
16 28 41 59 80 83 100 118 0
|
|
||||||
11 33 35 53 72 96 105 111 0
|
|
||||||
11 25 44 60 78 90 100 120 122
|
|
||||||
6 31 35 56 70 95 102 121 0
|
|
||||||
12 17 50 54 68 94 105 119 0
|
|
||||||
13 29 38 53 78 97 110 123 0
|
|
||||||
7 30 49 61 64 81 101 120 127
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
# Example of a (2000,1000) LDPC code with 3 checks per bit and 6 bits per
|
|
||||||
# check, tested on Additive White Gaussian Noise channels with noise standard
|
|
||||||
# deviations varying from 0.80 to 0.95.
|
|
||||||
#
|
|
||||||
# Testing is done by transmitting random messages, which is safer (though
|
|
||||||
# slower) than using only zero messages. Decoding is done using a maximum
|
|
||||||
# of 250 iterations of probability propagation.
|
|
||||||
|
|
||||||
set -e # Stop if an error occurs
|
|
||||||
set -v # Echo commands as they are read
|
|
||||||
|
|
||||||
make-ldpc ex-ldpc36-1000a.pchk 1000 2000 1 evenboth 3 no4cycle
|
|
||||||
make-gen ex-ldpc36-1000a.pchk ex-ldpc36-1000a.gen dense
|
|
||||||
rand-src ex-ldpc36-1000a.src 1 1000x100
|
|
||||||
encode ex-ldpc36-1000a.pchk ex-ldpc36-1000a.gen ex-ldpc36-1000a.src \
|
|
||||||
ex-ldpc36-1000a.enc
|
|
||||||
|
|
||||||
# NOISE STANDARD DEVIATION 0.80, Eb/N0 = 1.94 dB
|
|
||||||
|
|
||||||
transmit ex-ldpc36-1000a.enc ex-ldpc36-1000a.rec 1 awgn 0.80
|
|
||||||
decode ex-ldpc36-1000a.pchk ex-ldpc36-1000a.rec ex-ldpc36-1000a.dec awgn 0.80\
|
|
||||||
prprp 250
|
|
||||||
verify ex-ldpc36-1000a.pchk ex-ldpc36-1000a.dec ex-ldpc36-1000a.gen \
|
|
||||||
ex-ldpc36-1000a.src
|
|
||||||
|
|
||||||
# NOISE STANDARD DEVIATION 0.85, Eb/N0 = 1.41 dB
|
|
||||||
|
|
||||||
transmit ex-ldpc36-1000a.enc ex-ldpc36-1000a.rec 1 awgn 0.85
|
|
||||||
decode ex-ldpc36-1000a.pchk ex-ldpc36-1000a.rec ex-ldpc36-1000a.dec awgn 0.85\
|
|
||||||
prprp 250
|
|
||||||
verify ex-ldpc36-1000a.pchk ex-ldpc36-1000a.dec ex-ldpc36-1000a.gen \
|
|
||||||
ex-ldpc36-1000a.src
|
|
||||||
|
|
||||||
# NOISE STANDARD DEVIATION 0.90, Eb/N0 = 0.92 dB
|
|
||||||
|
|
||||||
transmit ex-ldpc36-1000a.enc ex-ldpc36-1000a.rec 1 awgn 0.90
|
|
||||||
decode ex-ldpc36-1000a.pchk ex-ldpc36-1000a.rec ex-ldpc36-1000a.dec awgn 0.90\
|
|
||||||
prprp 250
|
|
||||||
verify ex-ldpc36-1000a.pchk ex-ldpc36-1000a.dec ex-ldpc36-1000a.gen \
|
|
||||||
ex-ldpc36-1000a.src
|
|
||||||
|
|
||||||
# NOISE STANDARD DEVIATION 0.95, Eb/N0 = 0.45 dB
|
|
||||||
|
|
||||||
transmit ex-ldpc36-1000a.enc ex-ldpc36-1000a.rec 1 awgn 0.95
|
|
||||||
decode ex-ldpc36-1000a.pchk ex-ldpc36-1000a.rec ex-ldpc36-1000a.dec awgn 0.95\
|
|
||||||
prprp 250
|
|
||||||
verify ex-ldpc36-1000a.pchk ex-ldpc36-1000a.dec ex-ldpc36-1000a.gen \
|
|
||||||
ex-ldpc36-1000a.src
|
|
||||||
@@ -1,87 +0,0 @@
|
|||||||
<HTML><HEAD>
|
|
||||||
|
|
||||||
<TITLE> Examples of LDPC Program Usage </TITLE>
|
|
||||||
|
|
||||||
</HEAD><BODY>
|
|
||||||
|
|
||||||
|
|
||||||
<H1> Examples of LDPC Program Usage </H1>
|
|
||||||
|
|
||||||
<P>Below, are some command files containing examples of the use of
|
|
||||||
the <A HREF="progs.html">LDPC programs</A>, together with the output I
|
|
||||||
obtained for these examples. Output on other machines might
|
|
||||||
conceivably be slightly different, due to different round-off errors.
|
|
||||||
The <A HREF="run-examples"><TT>run-examples</TT></A> script runs all the example
|
|
||||||
scripts and compares their output with the outputs that I obtained (on
|
|
||||||
a Pentium machine).
|
|
||||||
|
|
||||||
<P><A HREF="ex-ham7b">ex-ham7b</A>,
|
|
||||||
output in <A HREF="ex-ham7b-out">ex-ham7b-out</A>
|
|
||||||
<BLOCKQUOTE>
|
|
||||||
A (7,4) Hamming code used with a BSC.
|
|
||||||
Demonstrates encoding of random messages and decoding to minimize
|
|
||||||
bit error rate by exhaustive enumeration.
|
|
||||||
</BLOCKQUOTE>
|
|
||||||
|
|
||||||
<P><A HREF="ex-ham7a">ex-ham7a</A>,
|
|
||||||
output in <A HREF="ex-ham7a-out">ex-ham7a-out</A>
|
|
||||||
<BLOCKQUOTE>
|
|
||||||
A (7,4) Hamming code used with an AWGN channel. Tested using zero messages.
|
|
||||||
Decoded by exhaustive enumeration to minimize either block or bit error rate,
|
|
||||||
and by probability propagation.
|
|
||||||
</BLOCKQUOTE>
|
|
||||||
|
|
||||||
<P><A HREF="ex-dep">ex-dep</A>,
|
|
||||||
output in <A HREF="ex-dep-out">ex-dep-out</A>
|
|
||||||
<BLOCKQUOTE>
|
|
||||||
Examples of how parity check matrices with linearly dependent rows (ie,
|
|
||||||
redundant parity checks) are handled. This is probably not of
|
|
||||||
great interest to most users.
|
|
||||||
</BLOCKQUOTE>
|
|
||||||
|
|
||||||
<P><A HREF="ex-ldpc-encode">ex-ldpc-encode</A>,
|
|
||||||
output in <A HREF="ex-ldpc-encode-out">ex-ldpc-encode-out</A>
|
|
||||||
<BLOCKQUOTE>
|
|
||||||
Encodes messages with an LDPC code using sparse, dense, and mixed
|
|
||||||
representations of the generator matrix.
|
|
||||||
</BLOCKQUOTE>
|
|
||||||
|
|
||||||
<P><A HREF="ex-ldpc36-1000a">ex-ldpc36-1000a</A>,
|
|
||||||
output in <A HREF="ex-ldpc36-1000a-out">ex-ldpc36-1000a-out</A>
|
|
||||||
<BLOCKQUOTE>
|
|
||||||
A (2000,1000) LDPC code with 3 checks per bit and 6 bits per check.
|
|
||||||
Three encoding methods are tried out, and the code is
|
|
||||||
tested on an AWGN channel at various noise levels, using random messages.
|
|
||||||
</BLOCKQUOTE>
|
|
||||||
|
|
||||||
<P><A HREF="ex-ldpc36-5000a">ex-ldpc36-5000a</A>,
|
|
||||||
output in <A HREF="ex-ldpc36-5000a-out">ex-ldpc36-5000a-out</A>
|
|
||||||
<BLOCKQUOTE>
|
|
||||||
A (10000,5000) LDPC code with 3 checks per bit and 6 bits per check.
|
|
||||||
Tested on an AWGN channel at various noise levels, using random messages.
|
|
||||||
Pipes are used to avoid creating lots of files.
|
|
||||||
</BLOCKQUOTE>
|
|
||||||
|
|
||||||
<P><A HREF="ex-ldpcvar-5000a">ex-ldpcvar-5000a</A>,
|
|
||||||
output in <A HREF="ex-ldpcvar-5000a-out">ex-ldpcvar-5000a-out</A>
|
|
||||||
<BLOCKQUOTE>
|
|
||||||
A (10000,5000) LDPC code with the number of checks per bit varying from 2 to 7.
|
|
||||||
Tested on an AWGN channel at various noise levels, using random messages.
|
|
||||||
Pipes are used to avoid creating lots of files. Performance is better than
|
|
||||||
for the code above in which the number of checks is the same for all bits.
|
|
||||||
</BLOCKQUOTE>
|
|
||||||
|
|
||||||
<P><A HREF="ex-wrong-model">ex-wrong-model</A>,
|
|
||||||
output in <A HREF="ex-wrong-model-out">ex-wrong-model-out</A>
|
|
||||||
<BLOCKQUOTE>
|
|
||||||
Tests what happens when messages are decoded using the wrong noise
|
|
||||||
model, including using the right type of model but with the wrong
|
|
||||||
noise level, and using the wrong type of model (ie, using an AWLN model
|
|
||||||
for messages transmitted through an AWGN channel, or vice versa).
|
|
||||||
</BLOCKQUOTE>
|
|
||||||
|
|
||||||
<HR>
|
|
||||||
|
|
||||||
<A HREF="index.html">Back to index for LDPC software</A>
|
|
||||||
|
|
||||||
</BODY></HTML>
|
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
module jt65_test
|
||||||
|
|
||||||
|
! Test the JT65 decoder for WSJT-X
|
||||||
|
|
||||||
|
implicit none
|
||||||
|
|
||||||
|
public :: test
|
||||||
|
integer, parameter, public :: NZMAX=60*12000
|
||||||
|
integer, public :: nft
|
||||||
|
|
||||||
|
contains
|
||||||
|
|
||||||
|
subroutine test (dd,nutc,nflow,nfhigh,nfqso,ntol,nsubmode,n2pass,nrobust &
|
||||||
|
,ntrials,naggressive,ndepth,mycall,hiscall,hisgrid,nexp_decode, &
|
||||||
|
nQSOProgress,ljt65apon)
|
||||||
|
use timer_module, only: timer
|
||||||
|
use jt65_decode
|
||||||
|
implicit none
|
||||||
|
|
||||||
|
include 'constants.f90'
|
||||||
|
real, intent(in) :: dd(NZMAX)
|
||||||
|
integer, intent(in) :: nutc, nflow, nfhigh, nfqso, ntol, nsubmode, n2pass &
|
||||||
|
, ntrials, naggressive, ndepth, nexp_decode, nQSOProgress
|
||||||
|
logical, intent(in) :: nrobust,ljt65apon
|
||||||
|
character(len=12), intent(in) :: mycall, hiscall
|
||||||
|
character(len=6), intent(in) :: hisgrid
|
||||||
|
type(jt65_decoder) :: my_decoder
|
||||||
|
logical nclearave !### Should be a dummy arg?
|
||||||
|
nclearave=.false.
|
||||||
|
|
||||||
|
call timer('jt65a ',0)
|
||||||
|
call my_decoder%decode(my_callback,dd,npts=52*12000,newdat=.true., &
|
||||||
|
nutc=nutc,nf1=nflow,nf2=nfhigh,nfqso=nfqso,ntol=ntol, &
|
||||||
|
nsubmode=nsubmode, minsync=-1,nagain=.false.,n2pass=n2pass, &
|
||||||
|
nrobust=nrobust,ntrials=ntrials,naggressive=naggressive, &
|
||||||
|
ndepth=ndepth,emedelay=0.0,clearave=nclearave,mycall=mycall, &
|
||||||
|
hiscall=hiscall,hisgrid=hisgrid,nexp_decode=nexp_decode, &
|
||||||
|
nQSOProgress=nQSOProgress,ljt65apon=ljt65apon)
|
||||||
|
call timer('jt65a ',1)
|
||||||
|
end subroutine test
|
||||||
|
|
||||||
|
subroutine my_callback (this,sync,snr,dt,freq,drift,nflip,width, &
|
||||||
|
decoded,ft,qual,smo,sum,minsync)
|
||||||
|
use jt65_decode
|
||||||
|
implicit none
|
||||||
|
|
||||||
|
class(jt65_decoder), intent(inout) :: this
|
||||||
|
real, intent(in) :: sync
|
||||||
|
integer, intent(in) :: snr
|
||||||
|
real, intent(in) :: dt
|
||||||
|
integer, intent(in) :: freq
|
||||||
|
integer, intent(in) :: drift
|
||||||
|
integer, intent(in) :: nflip
|
||||||
|
real, intent(in) :: width
|
||||||
|
character(len=22), intent(in) :: decoded
|
||||||
|
integer, intent(in) :: ft
|
||||||
|
integer, intent(in) :: qual
|
||||||
|
integer, intent(in) :: smo
|
||||||
|
integer, intent(in) :: sum
|
||||||
|
integer, intent(in) :: minsync
|
||||||
|
|
||||||
|
integer nwidth
|
||||||
|
real t
|
||||||
|
|
||||||
|
if(minsync+nflip+qual.eq.-9999) stop !Silence compiler warning
|
||||||
|
t=max(0.0,width*width-7.2)
|
||||||
|
nwidth=max(nint(sqrt(t)),2)
|
||||||
|
!### deal with nflip here! ###
|
||||||
|
!### also single_decode, csync, etc... ###
|
||||||
|
write(*,1012) nint(sync),snr,dt,freq,drift,nwidth, &
|
||||||
|
decoded,ft,sum,smo
|
||||||
|
1012 format(i4,i5,f6.2,i5,i4,i3,1x,a22,' JT65',3i3)
|
||||||
|
nft=ft
|
||||||
|
call flush(6)
|
||||||
|
|
||||||
|
end subroutine my_callback
|
||||||
|
|
||||||
|
end module jt65_test
|
||||||
@@ -0,0 +1,409 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Copyright (C) 2005, 2006 Douglas Gregor.
|
||||||
|
# Copyright (C) 2006 The Trustees of Indiana University
|
||||||
|
#
|
||||||
|
# Distributed under the Boost Software License, Version 1.0.
|
||||||
|
# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
|
||||||
|
# boostinspect:notab - Tabs are required for the Makefile.
|
||||||
|
|
||||||
|
BJAM=""
|
||||||
|
TOOLSET=""
|
||||||
|
BJAM_CONFIG=""
|
||||||
|
BUILD=""
|
||||||
|
PREFIX=/usr/local
|
||||||
|
EPREFIX=
|
||||||
|
LIBDIR=
|
||||||
|
INCLUDEDIR=
|
||||||
|
LIBS=""
|
||||||
|
PYTHON=python
|
||||||
|
PYTHON_VERSION=
|
||||||
|
PYTHON_ROOT=
|
||||||
|
ICU_ROOT=
|
||||||
|
|
||||||
|
# Handle case where builtin shell version of echo command doesn't
|
||||||
|
# support -n. Use the installed echo executable if there is one
|
||||||
|
# rather than builtin version to ensure -n is supported.
|
||||||
|
ECHO=`which echo`
|
||||||
|
if test "x$ECHO" = x; then
|
||||||
|
ECHO=echo
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Internal flags
|
||||||
|
flag_no_python=
|
||||||
|
flag_icu=
|
||||||
|
flag_show_libraries=
|
||||||
|
|
||||||
|
for option
|
||||||
|
do
|
||||||
|
case $option in
|
||||||
|
|
||||||
|
-help | --help | -h)
|
||||||
|
want_help=yes ;;
|
||||||
|
|
||||||
|
-prefix=* | --prefix=*)
|
||||||
|
PREFIX=`expr "x$option" : "x-*prefix=\(.*\)"`
|
||||||
|
;;
|
||||||
|
|
||||||
|
-exec-prefix=* | --exec-prefix=*)
|
||||||
|
EPREFIX=`expr "x$option" : "x-*exec-prefix=\(.*\)"`
|
||||||
|
;;
|
||||||
|
|
||||||
|
-libdir=* | --libdir=*)
|
||||||
|
LIBDIR=`expr "x$option" : "x-*libdir=\(.*\)"`
|
||||||
|
;;
|
||||||
|
|
||||||
|
-includedir=* | --includedir=*)
|
||||||
|
INCLUDEDIR=`expr "x$option" : "x-*includedir=\(.*\)"`
|
||||||
|
;;
|
||||||
|
|
||||||
|
-show-libraries | --show-libraries )
|
||||||
|
flag_show_libraries=yes
|
||||||
|
;;
|
||||||
|
|
||||||
|
-with-bjam=* | --with-bjam=* )
|
||||||
|
BJAM=`expr "x$option" : "x-*with-bjam=\(.*\)"`
|
||||||
|
;;
|
||||||
|
|
||||||
|
-with-icu | --with-icu )
|
||||||
|
flag_icu=yes
|
||||||
|
;;
|
||||||
|
|
||||||
|
-with-icu=* | --with-icu=* )
|
||||||
|
flag_icu=yes
|
||||||
|
ICU_ROOT=`expr "x$option" : "x-*with-icu=\(.*\)"`
|
||||||
|
;;
|
||||||
|
|
||||||
|
-without-icu | --without-icu )
|
||||||
|
flag_icu=no
|
||||||
|
;;
|
||||||
|
|
||||||
|
-with-libraries=* | --with-libraries=* )
|
||||||
|
library_list=`expr "x$option" : "x-*with-libraries=\(.*\)"`
|
||||||
|
if test "$library_list" != "all"; then
|
||||||
|
old_IFS=$IFS
|
||||||
|
IFS=,
|
||||||
|
for library in $library_list
|
||||||
|
do
|
||||||
|
LIBS="$LIBS --with-$library"
|
||||||
|
|
||||||
|
if test $library = python; then
|
||||||
|
requested_python=yes
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
IFS=$old_IFS
|
||||||
|
|
||||||
|
if test "x$requested_python" != xyes; then
|
||||||
|
flag_no_python=yes
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
|
||||||
|
-without-libraries=* | --without-libraries=* )
|
||||||
|
library_list=`expr "x$option" : "x-*without-libraries=\(.*\)"`
|
||||||
|
old_IFS=$IFS
|
||||||
|
IFS=,
|
||||||
|
for library in $library_list
|
||||||
|
do
|
||||||
|
LIBS="$LIBS --without-$library"
|
||||||
|
|
||||||
|
if test $library = python; then
|
||||||
|
flag_no_python=yes
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
IFS=$old_IFS
|
||||||
|
;;
|
||||||
|
|
||||||
|
-with-python=* | --with-python=* )
|
||||||
|
PYTHON=`expr "x$option" : "x-*with-python=\(.*\)"`
|
||||||
|
;;
|
||||||
|
|
||||||
|
-with-python-root=* | --with-python-root=* )
|
||||||
|
PYTHON_ROOT=`expr "x$option" : "x-*with-python-root=\(.*\)"`
|
||||||
|
;;
|
||||||
|
|
||||||
|
-with-python-version=* | --with-python-version=* )
|
||||||
|
PYTHON_VERSION=`expr "x$option" : "x-*with-python-version=\(.*\)"`
|
||||||
|
;;
|
||||||
|
|
||||||
|
-with-toolset=* | --with-toolset=* )
|
||||||
|
TOOLSET=`expr "x$option" : "x-*with-toolset=\(.*\)"`
|
||||||
|
;;
|
||||||
|
|
||||||
|
-*)
|
||||||
|
{ echo "error: unrecognized option: $option
|
||||||
|
Try \`$0 --help' for more information." >&2
|
||||||
|
{ (exit 1); exit 1; }; }
|
||||||
|
;;
|
||||||
|
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if test "x$want_help" = xyes; then
|
||||||
|
cat <<EOF
|
||||||
|
\`./bootstrap.sh' prepares Boost for building on a few kinds of systems.
|
||||||
|
|
||||||
|
Usage: $0 [OPTION]...
|
||||||
|
|
||||||
|
Defaults for the options are specified in brackets.
|
||||||
|
|
||||||
|
Configuration:
|
||||||
|
-h, --help display this help and exit
|
||||||
|
--with-bjam=BJAM use existing Boost.Jam executable (bjam)
|
||||||
|
[automatically built]
|
||||||
|
--with-toolset=TOOLSET use specific Boost.Build toolset
|
||||||
|
[automatically detected]
|
||||||
|
--show-libraries show the set of libraries that require build
|
||||||
|
and installation steps (i.e., those libraries
|
||||||
|
that can be used with --with-libraries or
|
||||||
|
--without-libraries), then exit
|
||||||
|
--with-libraries=list build only a particular set of libraries,
|
||||||
|
describing using either a comma-separated list of
|
||||||
|
library names or "all"
|
||||||
|
[all]
|
||||||
|
--without-libraries=list build all libraries except the ones listed []
|
||||||
|
--with-icu enable Unicode/ICU support in Regex
|
||||||
|
[automatically detected]
|
||||||
|
--without-icu disable Unicode/ICU support in Regex
|
||||||
|
--with-icu=DIR specify the root of the ICU library installation
|
||||||
|
and enable Unicode/ICU support in Regex
|
||||||
|
[automatically detected]
|
||||||
|
--with-python=PYTHON specify the Python executable [python]
|
||||||
|
--with-python-root=DIR specify the root of the Python installation
|
||||||
|
[automatically detected]
|
||||||
|
--with-python-version=X.Y specify the Python version as X.Y
|
||||||
|
[automatically detected]
|
||||||
|
|
||||||
|
Installation directories:
|
||||||
|
--prefix=PREFIX install Boost into the given PREFIX
|
||||||
|
[/usr/local]
|
||||||
|
--exec-prefix=EPREFIX install Boost binaries into the given EPREFIX
|
||||||
|
[PREFIX]
|
||||||
|
|
||||||
|
More precise control over installation directories:
|
||||||
|
--libdir=DIR install libraries here [EPREFIX/lib]
|
||||||
|
--includedir=DIR install headers here [PREFIX/include]
|
||||||
|
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
test -n "$want_help" && exit 0
|
||||||
|
|
||||||
|
# TBD: Determine where the script is located
|
||||||
|
my_dir="."
|
||||||
|
|
||||||
|
# Determine the toolset, if not already decided
|
||||||
|
if test "x$TOOLSET" = x; then
|
||||||
|
guessed_toolset=`$my_dir/tools/build/src/engine/build.sh --guess-toolset`
|
||||||
|
case $guessed_toolset in
|
||||||
|
acc | darwin | gcc | como | mipspro | pathscale | pgi | qcc | vacpp )
|
||||||
|
TOOLSET=$guessed_toolset
|
||||||
|
;;
|
||||||
|
|
||||||
|
intel-* )
|
||||||
|
TOOLSET=intel
|
||||||
|
;;
|
||||||
|
|
||||||
|
mingw )
|
||||||
|
TOOLSET=gcc
|
||||||
|
;;
|
||||||
|
|
||||||
|
sun* )
|
||||||
|
TOOLSET=sun
|
||||||
|
;;
|
||||||
|
|
||||||
|
* )
|
||||||
|
# Not supported by Boost.Build
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -f config.log
|
||||||
|
|
||||||
|
# Build bjam
|
||||||
|
if test "x$BJAM" = x; then
|
||||||
|
$ECHO -n "Building Boost.Build engine with toolset $TOOLSET... "
|
||||||
|
pwd=`pwd`
|
||||||
|
(cd "$my_dir/tools/build/src/engine" && ./build.sh "$TOOLSET") > bootstrap.log 2>&1
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo
|
||||||
|
echo "Failed to build Boost.Build build engine"
|
||||||
|
echo "Consult 'bootstrap.log' for more details"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
cd "$pwd"
|
||||||
|
arch=`cd $my_dir/tools/build/src/engine && ./bootstrap/jam0 -d0 -f build.jam --toolset=$TOOLSET --toolset-root= --show-locate-target && cd ..`
|
||||||
|
BJAM="$my_dir/tools/build/src/engine/$arch/b2"
|
||||||
|
echo "tools/build/src/engine/$arch/b2"
|
||||||
|
cp "$BJAM" .
|
||||||
|
cp "$my_dir/tools/build/src/engine/$arch/bjam" .
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
# TBD: Turn BJAM into an absolute path
|
||||||
|
|
||||||
|
# If there is a list of libraries
|
||||||
|
if test "x$flag_show_libraries" = xyes; then
|
||||||
|
cat <<EOF
|
||||||
|
|
||||||
|
The following Boost libraries have portions that require a separate build
|
||||||
|
and installation step. Any library not listed here can be used by including
|
||||||
|
the headers only.
|
||||||
|
|
||||||
|
The Boost libraries requiring separate building and installation are:
|
||||||
|
EOF
|
||||||
|
$BJAM -d0 --show-libraries | grep '^[[:space:]]*-'
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Setup paths
|
||||||
|
if test "x$EPREFIX" = x; then
|
||||||
|
EPREFIX="$PREFIX"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "x$LIBDIR" = x; then
|
||||||
|
LIBDIR="$EPREFIX/lib"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "x$INCLUDEDIR" = x; then
|
||||||
|
INCLUDEDIR="$PREFIX/include"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Find Python
|
||||||
|
if test "x$flag_no_python" = x; then
|
||||||
|
result=`$PYTHON -c "exit" > /dev/null 2>&1`
|
||||||
|
if [ "$?" -ne "0" ]; then
|
||||||
|
flag_no_python=yes
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "x$flag_no_python" = x; then
|
||||||
|
if test "x$PYTHON_VERSION" = x; then
|
||||||
|
$ECHO -n "Detecting Python version... "
|
||||||
|
PYTHON_VERSION=`$PYTHON -c "import sys; print (\"%d.%d\" % (sys.version_info[0], sys.version_info[1]))"`
|
||||||
|
echo $PYTHON_VERSION
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "x$PYTHON_ROOT" = x; then
|
||||||
|
$ECHO -n "Detecting Python root... "
|
||||||
|
PYTHON_ROOT=`$PYTHON -c "import sys; print(sys.prefix)"`
|
||||||
|
echo $PYTHON_ROOT
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Configure ICU
|
||||||
|
$ECHO -n "Unicode/ICU support for Boost.Regex?... "
|
||||||
|
if test "x$flag_icu" != xno; then
|
||||||
|
if test "x$ICU_ROOT" = x; then
|
||||||
|
COMMON_ICU_PATHS="/usr /usr/local /sw"
|
||||||
|
for p in $COMMON_ICU_PATHS; do
|
||||||
|
if test -r $p/include/unicode/utypes.h; then
|
||||||
|
ICU_ROOT=$p
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if test "x$ICU_ROOT" = x; then
|
||||||
|
echo "not found."
|
||||||
|
else
|
||||||
|
BJAM_CONFIG="$BJAM_CONFIG -sICU_PATH=$ICU_ROOT"
|
||||||
|
echo "$ICU_ROOT"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
BJAM_CONFIG="$BJAM_CONFIG -sICU_PATH=$ICU_ROOT"
|
||||||
|
echo "$ICU_ROOT"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "disabled."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Backup the user's existing project-config.jam
|
||||||
|
JAM_CONFIG_OUT="project-config.jam"
|
||||||
|
if test -r "project-config.jam"; then
|
||||||
|
counter=1
|
||||||
|
|
||||||
|
while test -r "project-config.jam.$counter"; do
|
||||||
|
counter=`expr $counter + 1`
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "Backing up existing Boost.Build configuration in project-config.jam.$counter"
|
||||||
|
mv "project-config.jam" "project-config.jam.$counter"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Generate user-config.jam
|
||||||
|
echo "Generating Boost.Build configuration in project-config.jam..."
|
||||||
|
cat > project-config.jam <<EOF
|
||||||
|
# Boost.Build Configuration
|
||||||
|
# Automatically generated by bootstrap.sh
|
||||||
|
|
||||||
|
import option ;
|
||||||
|
import feature ;
|
||||||
|
|
||||||
|
# Compiler configuration. This definition will be used unless
|
||||||
|
# you already have defined some toolsets in your user-config.jam
|
||||||
|
# file.
|
||||||
|
if ! $TOOLSET in [ feature.values <toolset> ]
|
||||||
|
{
|
||||||
|
using $TOOLSET ;
|
||||||
|
}
|
||||||
|
|
||||||
|
project : default-build <toolset>$TOOLSET ;
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# - Python configuration
|
||||||
|
if test "x$flag_no_python" = x; then
|
||||||
|
cat >> project-config.jam <<EOF
|
||||||
|
|
||||||
|
# Python configuration
|
||||||
|
import python ;
|
||||||
|
if ! [ python.configured ]
|
||||||
|
{
|
||||||
|
using python : $PYTHON_VERSION : $PYTHON_ROOT ;
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "x$ICU_ROOT" != x; then
|
||||||
|
cat >> project-config.jam << EOF
|
||||||
|
|
||||||
|
path-constant ICU_PATH : $ICU_ROOT ;
|
||||||
|
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
|
||||||
|
cat >> project-config.jam << EOF
|
||||||
|
|
||||||
|
# List of --with-<library> and --without-<library>
|
||||||
|
# options. If left empty, all libraries will be built.
|
||||||
|
# Options specified on the command line completely
|
||||||
|
# override this variable.
|
||||||
|
libraries = $LIBS ;
|
||||||
|
|
||||||
|
# These settings are equivivalent to corresponding command-line
|
||||||
|
# options.
|
||||||
|
option.set prefix : $PREFIX ;
|
||||||
|
option.set exec-prefix : $EPREFIX ;
|
||||||
|
option.set libdir : $LIBDIR ;
|
||||||
|
option.set includedir : $INCLUDEDIR ;
|
||||||
|
|
||||||
|
# Stop on first error
|
||||||
|
option.set keep-going : false ;
|
||||||
|
EOF
|
||||||
|
|
||||||
|
cat << EOF
|
||||||
|
|
||||||
|
Bootstrapping is done. To build, run:
|
||||||
|
|
||||||
|
./b2
|
||||||
|
|
||||||
|
To adjust configuration, edit 'project-config.jam'.
|
||||||
|
Further information:
|
||||||
|
|
||||||
|
- Command line help:
|
||||||
|
./b2 --help
|
||||||
|
|
||||||
|
- Getting started guide:
|
||||||
|
http://www.boost.org/more/getting_started/unix-variants.html
|
||||||
|
|
||||||
|
- Boost.Build documentation:
|
||||||
|
http://www.boost.org/build/doc/html/index.html
|
||||||
|
|
||||||
|
EOF
|
||||||
@@ -0,0 +1,147 @@
|
|||||||
|
subroutine genmsk144(msg0,mygrid,ichk,bcontest,msgsent,i4tone,itype)
|
||||||
|
! s8 + 48bits + s8 + 80 bits = 144 bits (72ms message duration)
|
||||||
|
!
|
||||||
|
! Encode an MSK144 message
|
||||||
|
! Input:
|
||||||
|
! - msg0 requested message to be transmitted
|
||||||
|
! - ichk if ichk=1, return only msgsent
|
||||||
|
! if ichk.ge.10000, set imsg=ichk-10000 for short msg
|
||||||
|
! - msgsent message as it will be decoded
|
||||||
|
! - i4tone array of audio tone values, 0 or 1
|
||||||
|
! - itype message type
|
||||||
|
! 1 = standard message "Call_1 Call_2 Grid/Rpt"
|
||||||
|
! 2 = type 1 prefix
|
||||||
|
! 3 = type 1 suffix
|
||||||
|
! 4 = type 2 prefix
|
||||||
|
! 5 = type 2 suffix
|
||||||
|
! 6 = free text (up to 13 characters)
|
||||||
|
! 7 = short message "<Call_1 Call2> Rpt"
|
||||||
|
|
||||||
|
use iso_c_binding, only: c_loc,c_size_t
|
||||||
|
use packjt
|
||||||
|
use hashing
|
||||||
|
character*22 msg0
|
||||||
|
character*22 message !Message to be generated
|
||||||
|
character*22 msgsent !Message as it will be received
|
||||||
|
character*6 mygrid
|
||||||
|
integer*4 i4Msg6BitWords(13) !72-bit message as 6-bit words
|
||||||
|
integer*4 i4tone(144) !
|
||||||
|
integer*1, target:: i1Msg8BitBytes(10) !80 bits represented in 10 bytes
|
||||||
|
integer*1 codeword(128) !Encoded bits before re-ordering
|
||||||
|
integer*1 msgbits(80) !72-bit message + 8-bit hash
|
||||||
|
integer*1 bitseq(144) !Tone #s, data and sync (values 0-1)
|
||||||
|
integer*1 i1hash(4)
|
||||||
|
integer*1 s8(8)
|
||||||
|
logical bcontest
|
||||||
|
real*8 pp(12)
|
||||||
|
real*8 xi(864),xq(864),pi,twopi
|
||||||
|
data s8/0,1,1,1,0,0,1,0/
|
||||||
|
equivalence (ihash,i1hash)
|
||||||
|
logical first
|
||||||
|
data first/.true./
|
||||||
|
save
|
||||||
|
|
||||||
|
if(first) then
|
||||||
|
first=.false.
|
||||||
|
nsym=128
|
||||||
|
pi=4.0*atan(1.0)
|
||||||
|
twopi=8.*atan(1.0)
|
||||||
|
do i=1,12
|
||||||
|
pp(i)=sin((i-1)*pi/12)
|
||||||
|
enddo
|
||||||
|
endif
|
||||||
|
|
||||||
|
if(msg0(1:1).eq.'@') then !Generate a fixed tone
|
||||||
|
read(msg0(2:5),*,end=1,err=1) nfreq !at specified frequency
|
||||||
|
go to 2
|
||||||
|
1 nfreq=1000
|
||||||
|
2 i4tone(1)=nfreq
|
||||||
|
else
|
||||||
|
message=msg0
|
||||||
|
do i=1,22
|
||||||
|
if(ichar(message(i:i)).eq.0) then
|
||||||
|
message(i:)=' '
|
||||||
|
exit
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
|
||||||
|
do i=1,22 !Strip leading blanks
|
||||||
|
if(message(1:1).ne.' ') exit
|
||||||
|
message=message(i+1:)
|
||||||
|
enddo
|
||||||
|
|
||||||
|
if(message(1:1).eq.'<') then
|
||||||
|
call genmsk40(message,msgsent,ichk,i4tone,itype)
|
||||||
|
if(itype.lt.0) go to 999
|
||||||
|
i4tone(41)=-40
|
||||||
|
go to 999
|
||||||
|
endif
|
||||||
|
|
||||||
|
call packmsg(message,i4Msg6BitWords,itype,bcontest) !Pack into 12 6-bit bytes
|
||||||
|
call unpackmsg(i4Msg6BitWords,msgsent,bcontest,mygrid) !Unpack to get msgsent
|
||||||
|
|
||||||
|
if(ichk.eq.1) go to 999
|
||||||
|
i4=0
|
||||||
|
ik=0
|
||||||
|
im=0
|
||||||
|
do i=1,12
|
||||||
|
nn=i4Msg6BitWords(i)
|
||||||
|
do j=1, 6
|
||||||
|
ik=ik+1
|
||||||
|
i4=i4+i4+iand(1,ishft(nn,j-6))
|
||||||
|
i4=iand(i4,255)
|
||||||
|
if(ik.eq.8) then
|
||||||
|
im=im+1
|
||||||
|
i1Msg8BitBytes(im)=i4
|
||||||
|
ik=0
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
enddo
|
||||||
|
|
||||||
|
ihash=nhash(c_loc(i1Msg8BitBytes),int(9,c_size_t),146)
|
||||||
|
ihash=2*iand(ihash,32767) !Generate the 8-bit hash
|
||||||
|
i1Msg8BitBytes(10)=i1hash(1) !Hash code to byte 10
|
||||||
|
|
||||||
|
mbit=0
|
||||||
|
do i=1, 10
|
||||||
|
i1=i1Msg8BitBytes(i)
|
||||||
|
do ibit=1,8
|
||||||
|
mbit=mbit+1
|
||||||
|
msgbits(mbit)=iand(1,ishft(i1,ibit-8))
|
||||||
|
enddo
|
||||||
|
enddo
|
||||||
|
|
||||||
|
call encode_msk144(msgbits,codeword)
|
||||||
|
|
||||||
|
!Create 144-bit channel vector:
|
||||||
|
!8-bit sync word + 48 bits + 8-bit sync word + 80 bits
|
||||||
|
bitseq=0
|
||||||
|
bitseq(1:8)=s8
|
||||||
|
bitseq(9:56)=codeword(1:48)
|
||||||
|
bitseq(57:64)=s8
|
||||||
|
bitseq(65:144)=codeword(49:128)
|
||||||
|
bitseq=2*bitseq-1
|
||||||
|
|
||||||
|
xq(1:6)=bitseq(1)*pp(7:12) !first bit is mapped to 1st half-symbol on q
|
||||||
|
do i=1,71
|
||||||
|
is=(i-1)*12+7
|
||||||
|
xq(is:is+11)=bitseq(2*i+1)*pp
|
||||||
|
enddo
|
||||||
|
xq(864-5:864)=bitseq(1)*pp(1:6) !last half symbol
|
||||||
|
do i=1,72
|
||||||
|
is=(i-1)*12+1
|
||||||
|
xi(is:is+11)=bitseq(2*i)*pp
|
||||||
|
enddo
|
||||||
|
! Map I and Q to tones.
|
||||||
|
i4tone=0
|
||||||
|
do i=1,72
|
||||||
|
i4tone(2*i-1)=(bitseq(2*i)*bitseq(2*i-1)+1)/2;
|
||||||
|
i4tone(2*i)=-(bitseq(2*i)*bitseq(mod(2*i,144)+1)-1)/2;
|
||||||
|
enddo
|
||||||
|
endif
|
||||||
|
|
||||||
|
! Flip polarity
|
||||||
|
i4tone=-i4tone+1
|
||||||
|
|
||||||
|
999 return
|
||||||
|
end subroutine genmsk144
|
||||||
@@ -1,224 +0,0 @@
|
|||||||
|
|
||||||
# CODE 1
|
|
||||||
|
|
||||||
make-pchk ex-dep.pchk 4 6 0:0 0:5 3:1 3:2
|
|
||||||
print-pchk -d ex-dep.pchk
|
|
||||||
|
|
||||||
Parity check matrix in ex-dep.pchk (dense format):
|
|
||||||
|
|
||||||
1 0 0 0 0 1
|
|
||||||
0 0 0 0 0 0
|
|
||||||
0 0 0 0 0 0
|
|
||||||
0 1 1 0 0 0
|
|
||||||
|
|
||||||
echo 00011011 >ex-dep.src
|
|
||||||
|
|
||||||
# SPARSE REPRESENTATION
|
|
||||||
|
|
||||||
make-gen ex-dep.pchk ex-dep.gen sparse
|
|
||||||
Note: Parity check matrix has 2 redundant checks
|
|
||||||
Number of 1s per check in L is 0.8, U is 0.5, B is 0.2, total is 1.5
|
|
||||||
print-gen -d ex-dep.gen
|
|
||||||
|
|
||||||
Generator matrix in ex-dep.gen (sparse representation):
|
|
||||||
|
|
||||||
Column order (message bits at end):
|
|
||||||
|
|
||||||
5 2 1 3 4 0
|
|
||||||
|
|
||||||
Row order:
|
|
||||||
|
|
||||||
0 3 2 1
|
|
||||||
|
|
||||||
L:
|
|
||||||
|
|
||||||
1 0 0 0
|
|
||||||
0 0 0 0
|
|
||||||
0 0 0 0
|
|
||||||
0 1 0 0
|
|
||||||
|
|
||||||
U:
|
|
||||||
|
|
||||||
0 0 0 0 0 1
|
|
||||||
0 1 1 0 0 0
|
|
||||||
0 0 0 0 0 0
|
|
||||||
0 0 0 0 0 0
|
|
||||||
|
|
||||||
encode ex-dep.pchk ex-dep.gen ex-dep.src ex-dep.enc; cat ex-dep.enc
|
|
||||||
Encoded 4 blocks, source block size 2, encoded block size 6
|
|
||||||
000000
|
|
||||||
100001
|
|
||||||
000010
|
|
||||||
100011
|
|
||||||
verify ex-dep.pchk ex-dep.enc ex-dep.gen ex-dep.src
|
|
||||||
Block counts: tot 4, with chk errs 0, with src errs 0, both 0
|
|
||||||
Bit error rate (on message bits only): 0.000e+00
|
|
||||||
|
|
||||||
# DENSE REPRESENTATION
|
|
||||||
|
|
||||||
make-gen ex-dep.pchk ex-dep.gen dense
|
|
||||||
Note: Parity check matrix has 2 redundant checks
|
|
||||||
Number of 1s per check in Inv(A) X B is 0.2
|
|
||||||
print-gen -d ex-dep.gen
|
|
||||||
|
|
||||||
Generator matrix in ex-dep.gen (dense representation):
|
|
||||||
|
|
||||||
Column order (message bits at end):
|
|
||||||
|
|
||||||
0 1 2 3 4 5
|
|
||||||
|
|
||||||
Inv(A) X B:
|
|
||||||
|
|
||||||
0 1
|
|
||||||
0 0
|
|
||||||
0 0
|
|
||||||
0 0
|
|
||||||
|
|
||||||
encode ex-dep.pchk ex-dep.gen ex-dep.src ex-dep.enc; cat ex-dep.enc
|
|
||||||
Encoded 4 blocks, source block size 2, encoded block size 6
|
|
||||||
000000
|
|
||||||
100001
|
|
||||||
000010
|
|
||||||
100011
|
|
||||||
verify ex-dep.pchk ex-dep.enc ex-dep.gen ex-dep.src
|
|
||||||
Block counts: tot 4, with chk errs 0, with src errs 0, both 0
|
|
||||||
Bit error rate (on message bits only): 0.000e+00
|
|
||||||
|
|
||||||
# MIXED REPRESENTATION
|
|
||||||
|
|
||||||
make-gen ex-dep.pchk ex-dep.gen mixed
|
|
||||||
Note: Parity check matrix has 2 redundant checks
|
|
||||||
Number of 1s per check in Inv(A) is 0.5, in B is 0.2, total is 0.8
|
|
||||||
print-gen -d ex-dep.gen
|
|
||||||
|
|
||||||
Generator matrix in ex-dep.gen (mixed representation):
|
|
||||||
|
|
||||||
Column order (message bits at end):
|
|
||||||
|
|
||||||
0 1 2 3 4 5
|
|
||||||
|
|
||||||
Inv(A):
|
|
||||||
|
|
||||||
1 0 0 0
|
|
||||||
0 0 0 1
|
|
||||||
0 0 0 0
|
|
||||||
0 0 0 0
|
|
||||||
|
|
||||||
encode ex-dep.pchk ex-dep.gen ex-dep.src ex-dep.enc; cat ex-dep.enc
|
|
||||||
Encoded 4 blocks, source block size 2, encoded block size 6
|
|
||||||
000000
|
|
||||||
100001
|
|
||||||
000010
|
|
||||||
100011
|
|
||||||
verify ex-dep.pchk ex-dep.enc ex-dep.gen ex-dep.src
|
|
||||||
Block counts: tot 4, with chk errs 0, with src errs 0, both 0
|
|
||||||
Bit error rate (on message bits only): 0.000e+00
|
|
||||||
|
|
||||||
# CODE 2
|
|
||||||
|
|
||||||
make-pchk ex-dep.pchk 4 5 0:0 0:1 1:1 1:2 2:0 2:2 3:3 3:4
|
|
||||||
print-pchk -d ex-dep.pchk
|
|
||||||
|
|
||||||
Parity check matrix in ex-dep.pchk (dense format):
|
|
||||||
|
|
||||||
1 1 0 0 0
|
|
||||||
0 1 1 0 0
|
|
||||||
1 0 1 0 0
|
|
||||||
0 0 0 1 1
|
|
||||||
|
|
||||||
echo 01 >ex-dep.src
|
|
||||||
|
|
||||||
# SPARSE REPRESENTATION
|
|
||||||
|
|
||||||
make-gen ex-dep.pchk ex-dep.gen sparse
|
|
||||||
Note: Parity check matrix has 1 redundant checks
|
|
||||||
Number of 1s per check in L is 1.0, U is 1.2, B is 0.5, total is 2.8
|
|
||||||
print-gen -d ex-dep.gen
|
|
||||||
|
|
||||||
Generator matrix in ex-dep.gen (sparse representation):
|
|
||||||
|
|
||||||
Column order (message bits at end):
|
|
||||||
|
|
||||||
4 1 2 3 0
|
|
||||||
|
|
||||||
Row order:
|
|
||||||
|
|
||||||
3 0 1 2
|
|
||||||
|
|
||||||
L:
|
|
||||||
|
|
||||||
0 1 0 0
|
|
||||||
0 1 1 0
|
|
||||||
0 0 1 0
|
|
||||||
1 0 0 0
|
|
||||||
|
|
||||||
U:
|
|
||||||
|
|
||||||
0 0 0 1 1
|
|
||||||
0 1 0 0 0
|
|
||||||
0 0 1 0 0
|
|
||||||
0 0 0 0 0
|
|
||||||
|
|
||||||
encode ex-dep.pchk ex-dep.gen ex-dep.src ex-dep.enc; cat ex-dep.enc
|
|
||||||
Encoded 2 blocks, source block size 1, encoded block size 5
|
|
||||||
00000
|
|
||||||
11100
|
|
||||||
verify ex-dep.pchk ex-dep.enc ex-dep.gen ex-dep.src
|
|
||||||
Block counts: tot 2, with chk errs 0, with src errs 0, both 0
|
|
||||||
Bit error rate (on message bits only): 0.000e+00
|
|
||||||
|
|
||||||
# DENSE REPRESENTATION
|
|
||||||
|
|
||||||
make-gen ex-dep.pchk ex-dep.gen dense
|
|
||||||
Note: Parity check matrix has 1 redundant checks
|
|
||||||
Number of 1s per check in Inv(A) X B is 0.2
|
|
||||||
print-gen -d ex-dep.gen
|
|
||||||
|
|
||||||
Generator matrix in ex-dep.gen (dense representation):
|
|
||||||
|
|
||||||
Column order (message bits at end):
|
|
||||||
|
|
||||||
0 1 3 2 4
|
|
||||||
|
|
||||||
Inv(A) X B:
|
|
||||||
|
|
||||||
0
|
|
||||||
0
|
|
||||||
1
|
|
||||||
0
|
|
||||||
|
|
||||||
encode ex-dep.pchk ex-dep.gen ex-dep.src ex-dep.enc; cat ex-dep.enc
|
|
||||||
Encoded 2 blocks, source block size 1, encoded block size 5
|
|
||||||
00000
|
|
||||||
00011
|
|
||||||
verify ex-dep.pchk ex-dep.enc ex-dep.gen ex-dep.src
|
|
||||||
Block counts: tot 2, with chk errs 0, with src errs 0, both 0
|
|
||||||
Bit error rate (on message bits only): 0.000e+00
|
|
||||||
|
|
||||||
# MIXED REPRESENTATION
|
|
||||||
|
|
||||||
make-gen ex-dep.pchk ex-dep.gen mixed
|
|
||||||
Note: Parity check matrix has 1 redundant checks
|
|
||||||
Number of 1s per check in Inv(A) is 1.0, in B is 0.2, total is 1.2
|
|
||||||
print-gen -d ex-dep.gen
|
|
||||||
|
|
||||||
Generator matrix in ex-dep.gen (mixed representation):
|
|
||||||
|
|
||||||
Column order (message bits at end):
|
|
||||||
|
|
||||||
0 1 3 2 4
|
|
||||||
|
|
||||||
Inv(A):
|
|
||||||
|
|
||||||
1 1 0 0
|
|
||||||
0 1 0 0
|
|
||||||
0 0 0 1
|
|
||||||
0 0 0 0
|
|
||||||
|
|
||||||
encode ex-dep.pchk ex-dep.gen ex-dep.src ex-dep.enc; cat ex-dep.enc
|
|
||||||
Encoded 2 blocks, source block size 1, encoded block size 5
|
|
||||||
00000
|
|
||||||
00011
|
|
||||||
verify ex-dep.pchk ex-dep.enc ex-dep.gen ex-dep.src
|
|
||||||
Block counts: tot 2, with chk errs 0, with src errs 0, both 0
|
|
||||||
Bit error rate (on message bits only): 0.000e+00
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,61 @@
|
|||||||
|
#ifndef WSJTX_CONFIG_H__
|
||||||
|
#define WSJTX_CONFIG_H__
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define WSJTX_VERSION_MAJOR @WSJTX_VERSION_MAJOR@
|
||||||
|
#define WSJTX_VERSION_MINOR @WSJTX_VERSION_MINOR@
|
||||||
|
#define WSJTX_VERSION_PATCH @WSJTX_VERSION_PATCH@
|
||||||
|
|
||||||
|
#cmakedefine CMAKE_INSTALL_DATAROOTDIR "@CMAKE_INSTALL_DATAROOTDIR@"
|
||||||
|
#cmakedefine CMAKE_INSTALL_DOCDIR "@CMAKE_INSTALL_DOCDIR@"
|
||||||
|
#cmakedefine CMAKE_INSTALL_DATADIR "@CMAKE_INSTALL_DATADIR@"
|
||||||
|
#cmakedefine CMAKE_PROJECT_NAME "@CMAKE_PROJECT_NAME@"
|
||||||
|
#cmakedefine PROJECT_MANUAL "@PROJECT_MANUAL@"
|
||||||
|
#cmakedefine PROJECT_HOMEPAGE "@PROJECT_HOMEPAGE@"
|
||||||
|
#cmakedefine PROJECT_MANUAL_DIRECTORY_URL "@PROJECT_MANUAL_DIRECTORY_URL@"
|
||||||
|
#cmakedefine PROJECT_SAMPLES_URL "@PROJECT_SAMPLES_URL@"
|
||||||
|
#cmakedefine PROJECT_SUMMARY_DESCRIPTION "@PROJECT_SUMMARY_DESCRIPTION@"
|
||||||
|
|
||||||
|
#cmakedefine01 WSJT_SHARED_RUNTIME
|
||||||
|
#cmakedefine01 WSJT_QDEBUG_TO_FILE
|
||||||
|
#cmakedefine01 WSJT_QDEBUG_IN_RELEASE
|
||||||
|
#cmakedefine01 WSJT_TRACE_CAT
|
||||||
|
#cmakedefine01 WSJT_TRACE_CAT_POLLS
|
||||||
|
#cmakedefine01 WSJT_HAMLIB_TRACE
|
||||||
|
#cmakedefine01 WSJT_HAMLIB_VERBOSE_TRACE
|
||||||
|
#cmakedefine01 WSJT_SOFT_KEYING
|
||||||
|
#cmakedefine01 WSJT_ENABLE_EXPERIMENTAL_FEATURES
|
||||||
|
#cmakedefine01 WSJT_RIG_NONE_CAN_SPLIT
|
||||||
|
|
||||||
|
#define WSJTX_STRINGIZE1(x) #x
|
||||||
|
#define WSJTX_STRINGIZE(x) WSJTX_STRINGIZE1(x)
|
||||||
|
|
||||||
|
/* consistent UNICODE behaviour */
|
||||||
|
#ifndef UNICODE
|
||||||
|
# undef _UNICODE
|
||||||
|
#else
|
||||||
|
# ifndef _UNICODE
|
||||||
|
# define _UNICODE
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* typedef for consistent gfortran ABI for charlen type hidden arguments */
|
||||||
|
#if __GNUC__ > 7
|
||||||
|
#ifdef __cplusplus
|
||||||
|
#include <cstddef>
|
||||||
|
#else
|
||||||
|
#include <stddef.h>
|
||||||
|
#endif
|
||||||
|
typedef size_t fortran_charlen_t;
|
||||||
|
#else
|
||||||
|
typedef int fortran_charlen_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
9
|
|
||||||
2 3 4 6 7 8 9 19 20
|
|
||||||
0.457827 0.323775 0.0214226 0.0592851 0.0389015 0.0248109 0.00884569
|
|
||||||
0.0176697 0.04746251
|
|
||||||
@@ -1,82 +0,0 @@
|
|||||||
<HTML><HEAD>
|
|
||||||
|
|
||||||
<TITLE> Installing the LDPC Software </TITLE>
|
|
||||||
|
|
||||||
</HEAD><BODY>
|
|
||||||
|
|
||||||
<H1> Installing the LDPC Software </H1>
|
|
||||||
|
|
||||||
The LDPC software is written in C, and may well work with any C
|
|
||||||
compiler, though it has been tested only with gcc, in Unix and Linux
|
|
||||||
environments, and in the <A HREF="http://www.cygwin.com">Cygwin</A>
|
|
||||||
Unix-like environment that runs under Microsoft Windows. The
|
|
||||||
installation instructions below assume that you are using a Unix-like
|
|
||||||
system.
|
|
||||||
|
|
||||||
<P>All the software, including the documentation you are viewing here,
|
|
||||||
is contained in a tar file, which you can download by clicking one
|
|
||||||
of the options below:
|
|
||||||
<BLOCKQUOTE>
|
|
||||||
<A HREF="http://www.cs.utoronto.ca/~radford/ftp/LDPC-yyyy-mm-dd/LDPC-yyyy-mm-dd.tar">Tar
|
|
||||||
file of LDPC software</A> (0.9 Megabytes)<BR>
|
|
||||||
<A HREF="http://www.cs.utoronto.ca/~radford/ftp/LDPC-yyyy-mm-dd/LDPC-yyyy-mm-dd.tar.gz">Gzipped
|
|
||||||
tar file of LDPC software</A> (0.4 Megabytes)
|
|
||||||
</BLOCKQUOTE>
|
|
||||||
|
|
||||||
<P>Once you obtain the tar file (and uncompress it with gunzip if
|
|
||||||
necessary), you should extract the files with the following Unix command:
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
tar xf LDPC-yyyy-mm-dd.tar
|
|
||||||
</PRE></BLOCKQUOTE>
|
|
||||||
This will create a source directory called <TT>LDPC-yyyy-mm-dd</TT>, and place
|
|
||||||
all the source, documentation, and other files in this directory.
|
|
||||||
|
|
||||||
<P>If you prefer for this directory to be called something else,
|
|
||||||
rename it <B>now</B>, before compiling the programs, since the file
|
|
||||||
<TT>randfile</TT> in this directory, containing natural random numbers,
|
|
||||||
is accessed according to its path when the programs were compiled.
|
|
||||||
|
|
||||||
<P>Once the tar command above has finished, you should change into the
|
|
||||||
newly-created directory, and type
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
make
|
|
||||||
</PRE></BLOCKQUOTE>
|
|
||||||
If all goes well, this should compile all the programs (except for some
|
|
||||||
test programs, which can be compiled with <TT>make test</TT>). You
|
|
||||||
may want to edit the file <TT>Makefile</TT> before running <TT>make</TT>
|
|
||||||
in order to change compilation options, such as the optimization level.
|
|
||||||
|
|
||||||
<P>You can run the programs from this source directory, or you can copy
|
|
||||||
them to some other directory by running the <TT>LDPC-install</TT>
|
|
||||||
shell file. For instance, to install them in a bin directory in your
|
|
||||||
home directory, do the following:
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
./LDPC-install $HOME/bin
|
|
||||||
</PRE></BLOCKQUOTE>
|
|
||||||
|
|
||||||
<P>The source directory contains a copy of all the HTML files
|
|
||||||
documenting the software, such as the one you are reading now, with
|
|
||||||
the file <TT>index.html</TT> being the starting point. It is best to
|
|
||||||
use this local copy when referring to the documentation, rather than
|
|
||||||
get it off the web, since that is faster and also insures that the
|
|
||||||
documentation is for the version that you are using. Just tell your
|
|
||||||
browser to open the URL
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
file:<I>path-to-software</I>/index.html
|
|
||||||
</PRE></BLOCKQUOTE>
|
|
||||||
where <TT><I>path-to-software</I></TT> is the full path (starting with "/")
|
|
||||||
to the directory where you've put the software.
|
|
||||||
|
|
||||||
<P>The command
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
make clean
|
|
||||||
</PRE></BLOCKQUOTE>
|
|
||||||
will remove all the compiled programs, as well as the files created when
|
|
||||||
the <A HREF="examples.html">examples</A> are run, and <TT>core</TT>, if it
|
|
||||||
exists.
|
|
||||||
|
|
||||||
<HR>
|
|
||||||
|
|
||||||
<A HREF="index.html">Back to index for LDPC software</A>
|
|
||||||
|
|
||||||
</BODY></HTML>
|
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
#ifndef FASTGRAPH_H
|
||||||
|
#define FASTGRAPH_H
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
|
#include <QScopedPointer>
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class FastGraph;
|
||||||
|
}
|
||||||
|
|
||||||
|
class QSettings;
|
||||||
|
|
||||||
|
class FastGraph : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit FastGraph(QSettings *, QWidget *parent = 0);
|
||||||
|
~FastGraph ();
|
||||||
|
|
||||||
|
void plotSpec(bool diskData, int UTCdisk);
|
||||||
|
void saveSettings();
|
||||||
|
void setTRPeriod(int n);
|
||||||
|
void setMode(QString mode);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void fastPick(int x0, int x1, int y);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void on_gainSlider_valueChanged(int value);
|
||||||
|
void on_zeroSlider_valueChanged(int value);
|
||||||
|
void on_greenZeroSlider_valueChanged(int value);
|
||||||
|
void on_pbAutoLevel_clicked();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void closeEvent (QCloseEvent *) override;
|
||||||
|
void keyPressEvent( QKeyEvent *e ) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QSettings * m_settings;
|
||||||
|
float m_ave;
|
||||||
|
qint32 m_TRperiod;
|
||||||
|
|
||||||
|
QScopedPointer<Ui::FastGraph> ui;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern float fast_green[703];
|
||||||
|
extern int fast_jh;
|
||||||
|
|
||||||
|
#endif // FASTGRAPH_H
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
program contest72
|
||||||
|
|
||||||
|
use packjt
|
||||||
|
integer dat(12)
|
||||||
|
logical text,bcontest,ok
|
||||||
|
character*22 msg,msg0,msg1
|
||||||
|
character*72 ct1,ct2
|
||||||
|
character*12 callsign1,callsign2
|
||||||
|
character*1 c0
|
||||||
|
character*42 c
|
||||||
|
character*6 mygrid
|
||||||
|
data c/'0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ +-./?'/
|
||||||
|
data bcontest/.true./
|
||||||
|
data mygrid/"EM48 "/
|
||||||
|
|
||||||
|
! itype Message Type
|
||||||
|
!--------------------
|
||||||
|
! 1 Standardd message
|
||||||
|
! 2 Type 1 prefix
|
||||||
|
! 3 Type 1 suffix
|
||||||
|
! 4 Type 2 prefix
|
||||||
|
! 5 Type 2 suffix
|
||||||
|
! 6 Free text
|
||||||
|
! -1 Does not decode correctly
|
||||||
|
|
||||||
|
nargs=iargc()
|
||||||
|
if(nargs.eq.0) open(10,file='contest_msgs.txt',status='old')
|
||||||
|
|
||||||
|
nn=0
|
||||||
|
do imsg=1,9999
|
||||||
|
if(nargs.eq.1) then
|
||||||
|
if(imsg.gt.1) exit
|
||||||
|
call getarg(1,msg0)
|
||||||
|
else
|
||||||
|
read(10,1001,end=999) msg0
|
||||||
|
1001 format(a22)
|
||||||
|
endif
|
||||||
|
msg=msg0
|
||||||
|
call packmsg(msg,dat,itype,bcontest)
|
||||||
|
call unpackmsg(dat,msg1,bcontest,mygrid)
|
||||||
|
ok=msg1.eq.msg0
|
||||||
|
if(msg0.eq.' ') then
|
||||||
|
write(*,1002)
|
||||||
|
else
|
||||||
|
if(jt_c2(1:1).eq.'W') msg0=' '//msg0(1:20)
|
||||||
|
nn=nn+1
|
||||||
|
write(*,1002) nn,msg0,ok,jt_itype,jt_nc1,jt_nc2,jt_ng,jt_k1,jt_k2
|
||||||
|
1002 format(i1,'. ',a22,L2,i2,2i10,i6,2i8)
|
||||||
|
if(index(msg1,' 73 ').gt.4) nn=0
|
||||||
|
endif
|
||||||
|
if(.not.ok) print*,msg0,msg1
|
||||||
|
if(itype.lt.0 .or. itype.eq.6) cycle
|
||||||
|
|
||||||
|
if(msg(1:3).eq.'CQ ') then
|
||||||
|
m=2
|
||||||
|
write(ct1,1010) dat
|
||||||
|
1010 format(12b6.6)
|
||||||
|
! write(*,1014) ct1
|
||||||
|
!1014 format(a72)
|
||||||
|
cycle
|
||||||
|
endif
|
||||||
|
|
||||||
|
i1=index(msg,'<')
|
||||||
|
if(i1.eq.1) then
|
||||||
|
m=0
|
||||||
|
cycle
|
||||||
|
endif
|
||||||
|
|
||||||
|
if(i.ge.5) then
|
||||||
|
m=3
|
||||||
|
cycle
|
||||||
|
endif
|
||||||
|
|
||||||
|
if(msg(1:6).eq.'73 CQ ') then
|
||||||
|
m=4
|
||||||
|
cycle
|
||||||
|
endif
|
||||||
|
|
||||||
|
call packmsg(msg,dat,itype,.false.)
|
||||||
|
write(ct1,1010) dat
|
||||||
|
call packtext(msg,nc1,nc2,ng,.false.,'')
|
||||||
|
! write(ct2,1012) nc1,nc2,ng+32768
|
||||||
|
!1012 format(2b28.28,b16.16)
|
||||||
|
! write(*,1014) ct1
|
||||||
|
! write(*,1014) ct2
|
||||||
|
! write(*,1014)
|
||||||
|
enddo
|
||||||
|
|
||||||
|
999 end program contest72
|
||||||
@@ -0,0 +1,200 @@
|
|||||||
|
#ifndef TRANSCEIVER_FACTORY_HPP__
|
||||||
|
#define TRANSCEIVER_FACTORY_HPP__
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QMap>
|
||||||
|
|
||||||
|
#include "Transceiver.hpp"
|
||||||
|
|
||||||
|
#include "qt_helpers.hpp"
|
||||||
|
|
||||||
|
class QString;
|
||||||
|
class QThread;
|
||||||
|
class QDir;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Transceiver Factory
|
||||||
|
//
|
||||||
|
class TransceiverFactory
|
||||||
|
: public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_ENUMS (DataBits StopBits Handshake PTTMethod TXAudioSource SplitMode)
|
||||||
|
|
||||||
|
public:
|
||||||
|
//
|
||||||
|
// Capabilities of a Transceiver that can be determined without
|
||||||
|
// actually instantiating one, these are for use in Configuration
|
||||||
|
// GUI behaviour determination
|
||||||
|
//
|
||||||
|
struct Capabilities
|
||||||
|
{
|
||||||
|
enum PortType {none, serial, network, usb};
|
||||||
|
|
||||||
|
explicit Capabilities (int model_number = 0
|
||||||
|
, PortType port_type = none
|
||||||
|
, bool has_CAT_PTT = false
|
||||||
|
, bool has_CAT_PTT_mic_data = false
|
||||||
|
, bool has_CAT_indirect_serial_PTT = false
|
||||||
|
, bool asynchronous = false)
|
||||||
|
: model_number_ {model_number}
|
||||||
|
, port_type_ {port_type}
|
||||||
|
, has_CAT_PTT_ {has_CAT_PTT}
|
||||||
|
, has_CAT_PTT_mic_data_ {has_CAT_PTT_mic_data}
|
||||||
|
, has_CAT_indirect_serial_PTT_ {has_CAT_indirect_serial_PTT}
|
||||||
|
, asynchronous_ {asynchronous}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int model_number_;
|
||||||
|
PortType port_type_;
|
||||||
|
bool has_CAT_PTT_;
|
||||||
|
bool has_CAT_PTT_mic_data_;
|
||||||
|
bool has_CAT_indirect_serial_PTT_; // OmniRig controls RTS/DTR via COM interface
|
||||||
|
bool asynchronous_;
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// Dictionary of Transceiver types Capabilities
|
||||||
|
//
|
||||||
|
typedef QMap<QString, Capabilities> Transceivers;
|
||||||
|
|
||||||
|
//
|
||||||
|
// various Transceiver parameters
|
||||||
|
//
|
||||||
|
enum DataBits {seven_data_bits = 7, eight_data_bits, default_data_bits};
|
||||||
|
Q_ENUM (DataBits)
|
||||||
|
enum StopBits {one_stop_bit = 1, two_stop_bits, default_stop_bits};
|
||||||
|
Q_ENUM (StopBits)
|
||||||
|
enum Handshake {handshake_default, handshake_none, handshake_XonXoff, handshake_hardware};
|
||||||
|
Q_ENUM (Handshake)
|
||||||
|
enum PTTMethod {PTT_method_VOX, PTT_method_CAT, PTT_method_DTR, PTT_method_RTS};
|
||||||
|
Q_ENUM (PTTMethod)
|
||||||
|
enum TXAudioSource {TX_audio_source_front, TX_audio_source_rear};
|
||||||
|
Q_ENUM (TXAudioSource)
|
||||||
|
enum SplitMode {split_mode_none, split_mode_rig, split_mode_emulate};
|
||||||
|
Q_ENUM (SplitMode)
|
||||||
|
|
||||||
|
TransceiverFactory ();
|
||||||
|
~TransceiverFactory ();
|
||||||
|
|
||||||
|
static char const * const basic_transceiver_name_; // dummy transceiver is basic model
|
||||||
|
|
||||||
|
//
|
||||||
|
// fetch all supported rigs as a list of name and model id
|
||||||
|
//
|
||||||
|
Transceivers const& supported_transceivers () const;
|
||||||
|
|
||||||
|
// supported model queries
|
||||||
|
Capabilities::PortType CAT_port_type (QString const& name) const; // how to talk to CAT
|
||||||
|
bool has_CAT_PTT (QString const& name) const; // can be keyed via CAT
|
||||||
|
bool has_CAT_PTT_mic_data (QString const& name) const; // Tx audio port is switchable via CAT
|
||||||
|
bool has_CAT_indirect_serial_PTT (QString const& name) const; // Can PTT via CAT port use DTR or RTS (OmniRig for example)
|
||||||
|
bool has_asynchronous_CAT (QString const& name) const; // CAT asynchronous rather than polled
|
||||||
|
|
||||||
|
struct ParameterPack
|
||||||
|
{
|
||||||
|
QString rig_name; // from supported_transceivers () key
|
||||||
|
QString serial_port; // serial port device name or empty
|
||||||
|
QString network_port; // hostname:port or empty
|
||||||
|
QString usb_port; // [vid[:pid[:vendor[:product]]]]
|
||||||
|
int baud;
|
||||||
|
DataBits data_bits;
|
||||||
|
StopBits stop_bits;
|
||||||
|
Handshake handshake;
|
||||||
|
bool force_dtr;
|
||||||
|
bool dtr_high; // to power interface
|
||||||
|
bool force_rts;
|
||||||
|
bool rts_high; // to power interface
|
||||||
|
PTTMethod ptt_type; // "CAT" | "DTR" | "RTS" | "VOX"
|
||||||
|
TXAudioSource audio_source; // some rigs allow audio routing
|
||||||
|
// to Mic/Data connector
|
||||||
|
SplitMode split_mode; // how to support split TX mode
|
||||||
|
QString ptt_port; // serial port device name or special
|
||||||
|
// value "CAT"
|
||||||
|
int poll_interval; // in seconds for interfaces that
|
||||||
|
// require polling for state changes
|
||||||
|
|
||||||
|
bool operator == (ParameterPack const& rhs) const
|
||||||
|
{
|
||||||
|
return rhs.rig_name == rig_name
|
||||||
|
&& rhs.serial_port == serial_port
|
||||||
|
&& rhs.network_port == network_port
|
||||||
|
&& rhs.usb_port == usb_port
|
||||||
|
&& rhs.baud == baud
|
||||||
|
&& rhs.data_bits == data_bits
|
||||||
|
&& rhs.stop_bits == stop_bits
|
||||||
|
&& rhs.handshake == handshake
|
||||||
|
&& rhs.force_dtr == force_dtr
|
||||||
|
&& rhs.dtr_high == dtr_high
|
||||||
|
&& rhs.force_rts == force_rts
|
||||||
|
&& rhs.rts_high == rts_high
|
||||||
|
&& rhs.ptt_type == ptt_type
|
||||||
|
&& rhs.audio_source == audio_source
|
||||||
|
&& rhs.split_mode == split_mode
|
||||||
|
&& rhs.ptt_port == ptt_port
|
||||||
|
&& rhs.poll_interval == poll_interval
|
||||||
|
;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// make a new Transceiver instance
|
||||||
|
//
|
||||||
|
// cat_port, cat_baud, cat_data_bits, cat_stop_bits, cat_handshake,
|
||||||
|
// cat_dtr_control, cat_rts_control are only relevant to interfaces
|
||||||
|
// that are served by Hamlib
|
||||||
|
//
|
||||||
|
// PTT port and to some extent ptt_type are independent of interface
|
||||||
|
// type
|
||||||
|
//
|
||||||
|
std::unique_ptr<Transceiver> create (ParameterPack const&, QThread * target_thread = nullptr);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Transceivers transceivers_;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline
|
||||||
|
bool operator != (TransceiverFactory::ParameterPack const& lhs, TransceiverFactory::ParameterPack const& rhs)
|
||||||
|
{
|
||||||
|
return !(lhs == rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// boilerplate routines to make enum types useable and debuggable in
|
||||||
|
// Qt
|
||||||
|
//
|
||||||
|
#if QT_VERSION < 0x050500
|
||||||
|
Q_DECLARE_METATYPE (TransceiverFactory::DataBits);
|
||||||
|
Q_DECLARE_METATYPE (TransceiverFactory::StopBits);
|
||||||
|
Q_DECLARE_METATYPE (TransceiverFactory::Handshake);
|
||||||
|
Q_DECLARE_METATYPE (TransceiverFactory::PTTMethod);
|
||||||
|
Q_DECLARE_METATYPE (TransceiverFactory::TXAudioSource);
|
||||||
|
Q_DECLARE_METATYPE (TransceiverFactory::SplitMode);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined (QT_NO_DEBUG_STREAM)
|
||||||
|
ENUM_QDEBUG_OPS_DECL (TransceiverFactory, DataBits);
|
||||||
|
ENUM_QDEBUG_OPS_DECL (TransceiverFactory, StopBits);
|
||||||
|
ENUM_QDEBUG_OPS_DECL (TransceiverFactory, Handshake);
|
||||||
|
ENUM_QDEBUG_OPS_DECL (TransceiverFactory, PTTMethod);
|
||||||
|
ENUM_QDEBUG_OPS_DECL (TransceiverFactory, TXAudioSource);
|
||||||
|
ENUM_QDEBUG_OPS_DECL (TransceiverFactory, SplitMode);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ENUM_QDATASTREAM_OPS_DECL (TransceiverFactory, DataBits);
|
||||||
|
ENUM_QDATASTREAM_OPS_DECL (TransceiverFactory, StopBits);
|
||||||
|
ENUM_QDATASTREAM_OPS_DECL (TransceiverFactory, Handshake);
|
||||||
|
ENUM_QDATASTREAM_OPS_DECL (TransceiverFactory, PTTMethod);
|
||||||
|
ENUM_QDATASTREAM_OPS_DECL (TransceiverFactory, TXAudioSource);
|
||||||
|
ENUM_QDATASTREAM_OPS_DECL (TransceiverFactory, SplitMode);
|
||||||
|
|
||||||
|
ENUM_CONVERSION_OPS_DECL (TransceiverFactory, DataBits);
|
||||||
|
ENUM_CONVERSION_OPS_DECL (TransceiverFactory, StopBits);
|
||||||
|
ENUM_CONVERSION_OPS_DECL (TransceiverFactory, Handshake);
|
||||||
|
ENUM_CONVERSION_OPS_DECL (TransceiverFactory, PTTMethod);
|
||||||
|
ENUM_CONVERSION_OPS_DECL (TransceiverFactory, TXAudioSource);
|
||||||
|
ENUM_CONVERSION_OPS_DECL (TransceiverFactory, SplitMode);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
=== New in Version 1.9
|
||||||
|
|
||||||
|
For quick reference, here's a short list of features and capabilities
|
||||||
|
added to _WSJT-X_ since Version 1.8.0:
|
||||||
|
|
||||||
|
- New *FT8 DXpedition Mode* to facilitate high QSO rates in pileup
|
||||||
|
situations
|
||||||
|
|
||||||
|
- Decoding improvements for JT65 mode, including _a priori_ (AP)
|
||||||
|
decoding when VHF/UHF/Microwave features are enabled
|
||||||
|
|
||||||
|
- Optional Auto-Sequencing in JT4, JT9, and JT65 when VHF/UHF/Microwave features are enabled
|
||||||
|
|
||||||
|
- Better suppression of low-confidence false decodes generated by AP
|
||||||
|
decoding in FT8 mode
|
||||||
|
|
||||||
|
- Improved decoding performance for WSPR mode, especially effective at LF and MF
|
||||||
|
|
||||||
|
- Minor adjustments to auto-sequencing behavior
|
||||||
|
|
||||||
|
- More flexible Doppler control features for EME
|
||||||
|
|
||||||
|
- Improved waterfall sensitivity for very weak signals
|
||||||
|
|
||||||
|
- Automatic real-time forwarding of logged information to _N1MM Logger+_
|
||||||
|
|
||||||
|
- Expanded and improved UDP messages sent to companion programs
|
||||||
|
|
||||||
|
- Bug fixes and other minor tweaks to user interface
|
||||||
|
|
||||||
|
=== Documentation Conventions
|
||||||
|
|
||||||
|
In this manual the following icons call attention to particular types
|
||||||
|
of information:
|
||||||
|
|
||||||
|
NOTE: *Notes* containing information that may be of interest to
|
||||||
|
particuar classes of users.
|
||||||
|
|
||||||
|
TIP: *Tips* on program features or capabilities that might otherwise be
|
||||||
|
overlooked.
|
||||||
|
|
||||||
|
IMPORTANT: *Warnings* about usage that could lead to undesired
|
||||||
|
consequences.
|
||||||
|
|
||||||
|
=== How You Can Contribute
|
||||||
|
|
||||||
|
_WSJT-X_ is part of an open-source project released under the
|
||||||
|
{gnu_gpl} (GPL). If you have programming or documentation skills or
|
||||||
|
would like to contribute to the project in other ways, please make
|
||||||
|
your interests known to the development team. The project's
|
||||||
|
source-code repository can be found at {devsvn}, and most
|
||||||
|
communication among the developers takes place on the email reflector
|
||||||
|
{devmail}. Bug reports and suggestions for new features, improvements
|
||||||
|
to the _WSJT-X_ User Guide, etc., may also be sent to the
|
||||||
|
{wsjt_yahoo_group} email reflector. You must join the relevant group
|
||||||
|
before posting to either email list.
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
Type 1 Prefixes:
|
||||||
|
|
||||||
|
1A 1S 3A 3B6 3B8 3B9 3C 3C0 3D2 3D2C 3D2R 3DA 3V 3W 3X
|
||||||
|
3Y 3YB 3YP 4J 4L 4S 4U1I 4U1U 4W 4X 5A 5B 5H 5N 5R
|
||||||
|
5T 5U 5V 5W 5X 5Z 6W 6Y 7O 7P 7Q 7X 8P 8Q 8R
|
||||||
|
9A 9G 9H 9J 9K 9L 9M2 9M6 9N 9Q 9U 9V 9X 9Y A2
|
||||||
|
A3 A4 A5 A6 A7 A9 AP BS7 BV BV9 BY C2 C3 C5 C6
|
||||||
|
C9 CE CE0X CE0Y CE0Z CE9 CM CN CP CT CT3 CU CX CY0 CY9
|
||||||
|
D2 D4 D6 DL DU E3 E4 EA EA6 EA8 EA9 EI EK EL EP
|
||||||
|
ER ES ET EU EX EY EZ F FG FH FJ FK FKC FM FO
|
||||||
|
FOA FOC FOM FP FR FRG FRJ FRT FT5W FT5X FT5Z FW FY M MD
|
||||||
|
MI MJ MM MU MW H4 H40 HA HB HB0 HC HC8 HH HI HK
|
||||||
|
HK0A HK0M HL HM HP HR HS HV HZ I IS IS0 J2 J3 J5
|
||||||
|
J6 J7 J8 JA JDM JDO JT JW JX JY K KG4 KH0 KH1 KH2
|
||||||
|
KH3 KH4 KH5 KH5K KH6 KH7 KH8 KH9 KL KP1 KP2 KP4 KP5 LA LU
|
||||||
|
LX LY LZ OA OD OE OH OH0 OJ0 OK OM ON OX OY OZ
|
||||||
|
P2 P4 PA PJ2 PJ7 PY PY0F PT0S PY0T PZ R1F R1M S0 S2 S5
|
||||||
|
S7 S9 SM SP ST SU SV SVA SV5 SV9 T2 T30 T31 T32 T33
|
||||||
|
T5 T7 T8 T9 TA TF TG TI TI9 TJ TK TL TN TR TT
|
||||||
|
TU TY TZ UA UA2 UA9 UK UN UR V2 V3 V4 V5 V6 V7
|
||||||
|
V8 VE VK VK0H VK0M VK9C VK9L VK9M VK9N VK9W VK9X VP2E VP2M VP2V VP5
|
||||||
|
VP6 VP6D VP8 VP8G VP8H VP8O VP8S VP9 VQ9 VR VU VU4 VU7 XE XF4
|
||||||
|
XT XU XW XX9 XZ YA YB YI YJ YK YL YN YO YS YU
|
||||||
|
YV YV0 Z2 Z3 ZA ZB ZC4 ZD7 ZD8 ZD9 ZF ZK1N ZK1S ZK2 ZK3
|
||||||
|
ZL ZL7 ZL8 ZL9 ZP ZS ZS8 KC4 E5
|
||||||
|
|
||||||
|
Type 1 Suffixes: /0 /1 /2 /3 /4 /5 /6 /7 /8 /9 /A /P
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
/* INTIO.H - Interface for reading and writing integers one byte at a time. */
|
|
||||||
|
|
||||||
/* Copyright (c) 1995-2012 by Radford M. Neal.
|
|
||||||
*
|
|
||||||
* Permission is granted for anyone to copy, use, modify, and distribute
|
|
||||||
* these programs and accompanying documents for any purpose, provided
|
|
||||||
* this copyright notice is retained and prominently displayed, and note
|
|
||||||
* is made of any changes made to these programs. These programs and
|
|
||||||
* documents are distributed without any warranty, express or implied.
|
|
||||||
* As the programs were written for research purposes only, they have not
|
|
||||||
* been tested to the degree that would be advisable in any important
|
|
||||||
* application. All use of these programs is entirely at the user's own
|
|
||||||
* risk.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int intio_read (FILE *); /* Read an integer */
|
|
||||||
void intio_write (FILE *, int); /* Write an integer */
|
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
subroutine msk144decodeframe(c,softbits,msgreceived,nsuccess,recent_calls,nrecent)
|
||||||
|
! use timer_module, only: timer
|
||||||
|
|
||||||
|
parameter (NSPM=864)
|
||||||
|
character*22 msgreceived
|
||||||
|
character*12 recent_calls(nrecent)
|
||||||
|
complex cb(42)
|
||||||
|
complex cfac,cca,ccb
|
||||||
|
complex c(NSPM)
|
||||||
|
integer*1 decoded(80)
|
||||||
|
integer s8(8),hardbits(144)
|
||||||
|
real*8 dt, fs, pi, twopi
|
||||||
|
real cbi(42),cbq(42)
|
||||||
|
real pp(12)
|
||||||
|
real softbits(144)
|
||||||
|
real llr(128)
|
||||||
|
logical first
|
||||||
|
data first/.true./
|
||||||
|
data s8/0,1,1,1,0,0,1,0/
|
||||||
|
save first,cb,fs,pi,twopi,dt,s8,pp
|
||||||
|
|
||||||
|
if(first) then
|
||||||
|
! define half-sine pulse and raised-cosine edge window
|
||||||
|
pi=4d0*datan(1d0)
|
||||||
|
twopi=8d0*datan(1d0)
|
||||||
|
fs=12000.0
|
||||||
|
dt=1.0/fs
|
||||||
|
|
||||||
|
do i=1,12
|
||||||
|
angle=(i-1)*pi/12.0
|
||||||
|
pp(i)=sin(angle)
|
||||||
|
enddo
|
||||||
|
|
||||||
|
! define the sync word waveforms
|
||||||
|
s8=2*s8-1
|
||||||
|
cbq(1:6)=pp(7:12)*s8(1)
|
||||||
|
cbq(7:18)=pp*s8(3)
|
||||||
|
cbq(19:30)=pp*s8(5)
|
||||||
|
cbq(31:42)=pp*s8(7)
|
||||||
|
cbi(1:12)=pp*s8(2)
|
||||||
|
cbi(13:24)=pp*s8(4)
|
||||||
|
cbi(25:36)=pp*s8(6)
|
||||||
|
cbi(37:42)=pp(1:6)*s8(8)
|
||||||
|
cb=cmplx(cbi,cbq)
|
||||||
|
first=.false.
|
||||||
|
endif
|
||||||
|
|
||||||
|
nsuccess=0
|
||||||
|
msgreceived=' '
|
||||||
|
|
||||||
|
! Estimate carrier phase.
|
||||||
|
cca=sum(c(1:1+41)*conjg(cb))
|
||||||
|
ccb=sum(c(1+56*6:1+56*6+41)*conjg(cb))
|
||||||
|
cfac=ccb*conjg(cca)
|
||||||
|
phase0=atan2(imag(cca+ccb),real(cca+ccb))
|
||||||
|
|
||||||
|
! Remove phase error - want constellation rotated so that sample points lie on I/Q axes
|
||||||
|
cfac=cmplx(cos(phase0),sin(phase0))
|
||||||
|
c=c*conjg(cfac)
|
||||||
|
|
||||||
|
! matched filter -
|
||||||
|
softbits(1)=sum(imag(c(1:6))*pp(7:12))+sum(imag(c(864-5:864))*pp(1:6))
|
||||||
|
softbits(2)=sum(real(c(1:12))*pp)
|
||||||
|
do i=2,72
|
||||||
|
softbits(2*i-1)=sum(imag(c(1+(i-1)*12-6:1+(i-1)*12+5))*pp)
|
||||||
|
softbits(2*i)=sum(real(c(7+(i-1)*12-6:7+(i-1)*12+5))*pp)
|
||||||
|
enddo
|
||||||
|
|
||||||
|
! sync word hard error weight is used as a discriminator for
|
||||||
|
! frames that have reasonable probability of decoding
|
||||||
|
hardbits=0
|
||||||
|
do i=1,144
|
||||||
|
if( softbits(i) .ge. 0.0 ) then
|
||||||
|
hardbits(i)=1
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
nbadsync1=(8-sum( (2*hardbits(1:8)-1)*s8 ) )/2
|
||||||
|
nbadsync2=(8-sum( (2*hardbits(1+56:8+56)-1)*s8 ) )/2
|
||||||
|
nbadsync=nbadsync1+nbadsync2
|
||||||
|
if( nbadsync .gt. 4 ) then
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
! normalize the softsymbols before submitting to decoder
|
||||||
|
sav=sum(softbits)/144
|
||||||
|
s2av=sum(softbits*softbits)/144
|
||||||
|
ssig=sqrt(s2av-sav*sav)
|
||||||
|
softbits=softbits/ssig
|
||||||
|
|
||||||
|
sigma=0.75
|
||||||
|
llr(1:48)=softbits(9:9+47)
|
||||||
|
llr(49:128)=softbits(65:65+80-1)
|
||||||
|
llr=2.0*llr/(sigma*sigma)
|
||||||
|
|
||||||
|
max_iterations=10
|
||||||
|
! call timer('bpdec144 ',0)
|
||||||
|
call bpdecode144(llr,max_iterations,decoded,niterations)
|
||||||
|
! call timer('bpdec144 ',1)
|
||||||
|
if( niterations .ge. 0.0 ) then
|
||||||
|
call extractmessage144(decoded,msgreceived,nhashflag,recent_calls,nrecent)
|
||||||
|
if( nhashflag .gt. 0 ) then !Hash codes match, so print it
|
||||||
|
nsuccess=1
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
return
|
||||||
|
end subroutine msk144decodeframe
|
||||||
@@ -0,0 +1,175 @@
|
|||||||
|
program wsprdpsksim
|
||||||
|
|
||||||
|
! Generate simulated data for a 2-minute "WSPR-DPSK" mode. Output is saved
|
||||||
|
! to a *.c2 or *.wav file.
|
||||||
|
|
||||||
|
use wavhdr
|
||||||
|
include 'wsprdpsk_params.f90' !Set various constants
|
||||||
|
parameter (NMAX=120*12000)
|
||||||
|
type(hdr) hwav !Header for .wav file
|
||||||
|
character arg*12,fname*16
|
||||||
|
character msg*22,msgsent*22
|
||||||
|
complex c0(0:NMAX/NDOWN-1)
|
||||||
|
complex c(0:NMAX/NDOWN-1)
|
||||||
|
complex c0wav(0:NMAX-1)
|
||||||
|
complex cwav(0:NMAX-1)
|
||||||
|
real*8 fMHz
|
||||||
|
integer imessage(NN)
|
||||||
|
integer*2 iwave(NMAX) !Generated full-length waveform
|
||||||
|
|
||||||
|
! Get command-line argument(s)
|
||||||
|
nargs=iargc()
|
||||||
|
if(nargs.ne.8) then
|
||||||
|
print*,'Usage: wsprdpsksim "message" f0 DT fsp del nwav nfiles snr'
|
||||||
|
print*,'Example: wsprdpsksim "K1ABC FN42 30" 50 0.0 0.1 1.0 1 10 -33'
|
||||||
|
go to 999
|
||||||
|
endif
|
||||||
|
call getarg(1,msg) !Message to be transmitted
|
||||||
|
call getarg(2,arg)
|
||||||
|
read(arg,*) f0 !Freq relative to WSPR-band center (Hz)
|
||||||
|
call getarg(3,arg)
|
||||||
|
read(arg,*) xdt !Time offset from nominal (s)
|
||||||
|
call getarg(4,arg)
|
||||||
|
read(arg,*) fspread !Watterson frequency spread (Hz)
|
||||||
|
call getarg(5,arg)
|
||||||
|
read(arg,*) delay !Watterson delay (ms)
|
||||||
|
call getarg(6,arg)
|
||||||
|
read(arg,*) nwav !1 for *.wav file, 0 for *.c2 file
|
||||||
|
call getarg(7,arg)
|
||||||
|
read(arg,*) nfiles !Number of files
|
||||||
|
call getarg(8,arg)
|
||||||
|
read(arg,*) snrdb !SNR_2500
|
||||||
|
|
||||||
|
twopi=8.0*atan(1.0)
|
||||||
|
pi=twopi/2.0
|
||||||
|
fs=12000.0/NDOWN
|
||||||
|
dt=1.0/fs !Sample interval (s)
|
||||||
|
tt=NSPS*dt !Duration of "itone" symbols (s)
|
||||||
|
baud=1.0/tt !Keying rate for "itone" symbols (baud)
|
||||||
|
txt=NZ*dt !Transmission length (s)
|
||||||
|
bandwidth_ratio=2500.0/(fs/2.0)
|
||||||
|
sig=sqrt(bandwidth_ratio) * 10.0**(0.05*snrdb)
|
||||||
|
if(snrdb.gt.90.0) sig=1.0
|
||||||
|
txt=NN*NSPS0/12000.0
|
||||||
|
|
||||||
|
call genwsprdpsk(msg,msgsent,imessage) !Encode the message, get itone
|
||||||
|
imessage=2*imessage-1
|
||||||
|
write(*,1000) f0,xdt,txt,snrdb,fspread,delay,nfiles,msgsent
|
||||||
|
1000 format('f0:',f9.3,' DT:',f6.2,' txt:',f6.1,' SNR:',f6.1, &
|
||||||
|
' fspread:',f6.1,' delay:',f6.1,' nfiles:',i3,2x,a22)
|
||||||
|
|
||||||
|
|
||||||
|
beta=1.0 ! excess bandwidth
|
||||||
|
if(nwav.eq.0) then
|
||||||
|
df=fs/(NMAX/NDOWN) !
|
||||||
|
c=0
|
||||||
|
bw=(1+beta)*baud/2.0
|
||||||
|
bf=(1-beta)*baud/2.0
|
||||||
|
iw=bw/df
|
||||||
|
if=bf/df
|
||||||
|
c(0:if-1)=1.0
|
||||||
|
if(iw.gt.if) then
|
||||||
|
do i=if,iw
|
||||||
|
c(i)=((1.0+cos(pi*(i-if)/(iw-if)))/2.0)**0.5
|
||||||
|
enddo
|
||||||
|
endif
|
||||||
|
c(NMAX/NDOWN-1:NMAX/NDOWN-iw:-1)=c(1:iw)
|
||||||
|
|
||||||
|
istart=xdt/dt
|
||||||
|
c0=0.0
|
||||||
|
do i=1,NN
|
||||||
|
c0(istart+(i-1)*200)=imessage(i)
|
||||||
|
enddo
|
||||||
|
call four2a(c0,NMAX/NDOWN,1,1,1)
|
||||||
|
c0=c0*conjg(c)
|
||||||
|
ic=f0/df
|
||||||
|
c0=cshift(c0,ic)
|
||||||
|
call four2a(c0,NMAX/NDOWN,1,-1,1)
|
||||||
|
xx=sum(abs(c0(istart:istart+NN*200-1)**2))/(NN*200)
|
||||||
|
c0=c0/sqrt(xx)
|
||||||
|
|
||||||
|
call sgran()
|
||||||
|
do ifile=1,nfiles
|
||||||
|
c=c0
|
||||||
|
if( fspread .ne. 0.0 .or. delay .ne. 0.0 ) then
|
||||||
|
call watterson(c,NMAX/NDOWN,fs,delay,fspread)
|
||||||
|
endif
|
||||||
|
c=c*sig
|
||||||
|
if(snrdb.lt.90) then
|
||||||
|
do i=0,NMAX/NDOWN-1 !Add gaussian noise at specified SNR
|
||||||
|
xnoise=gran()
|
||||||
|
ynoise=gran()
|
||||||
|
c(i)=c(i) + cmplx(xnoise,ynoise)
|
||||||
|
enddo
|
||||||
|
endif
|
||||||
|
snrtest=sum(abs(c(istart:istart+NN*200-1)**2))/(NN*200)/2.0-1.0
|
||||||
|
write(*,*) 'sample SNR: ',10*log10(snrtest)+10*log10(0.4/2.5)
|
||||||
|
write(fname,1100) ifile
|
||||||
|
1100 format('000000_',i4.4,'.c2')
|
||||||
|
open(10,file=fname,status='unknown',access='stream')
|
||||||
|
fMHz=10.1387d0
|
||||||
|
nmin=2
|
||||||
|
write(10) fname,nmin,fMHz,c !Save to *.c2 file
|
||||||
|
close(10)
|
||||||
|
enddo
|
||||||
|
else
|
||||||
|
fs=12000.0
|
||||||
|
df=fs/NMAX
|
||||||
|
dt=1/fs
|
||||||
|
bandwidth_ratio=2500.0/(fs/2.0)
|
||||||
|
sig=sqrt(2*bandwidth_ratio) * 10.0**(0.05*snrdb)
|
||||||
|
if(snrdb.gt.90.0) sig=1.0
|
||||||
|
cwav=0
|
||||||
|
bw=(1+beta)*baud/2.0
|
||||||
|
bf=(1-beta)*baud/2.0
|
||||||
|
iw=bw/df
|
||||||
|
if=bf/df
|
||||||
|
cwav(0:if-1)=1.0
|
||||||
|
if(iw.gt.if) then
|
||||||
|
do i=if,iw
|
||||||
|
cwav(i)=((1.0+cos(pi*(i-if)/(iw-if)))/2.0)**0.5
|
||||||
|
enddo
|
||||||
|
endif
|
||||||
|
cwav(NMAX-1:NMAX-iw:-1)=cwav(1:iw)
|
||||||
|
|
||||||
|
istart=xdt/dt
|
||||||
|
c0wav=0.0
|
||||||
|
do i=1,NN
|
||||||
|
c0wav(istart+(i-1)*200*NDOWN)=imessage(i)
|
||||||
|
enddo
|
||||||
|
call four2a(c0wav,NMAX,1,1,1)
|
||||||
|
c0wav=c0wav*conjg(cwav)
|
||||||
|
ic=f0/df
|
||||||
|
c0wav=cshift(c0wav,-ic)
|
||||||
|
call four2a(c0wav,NMAX,1,-1,1)
|
||||||
|
xx=sum(abs(c0wav(istart:istart+NN*200*NDOWN-1))**2)/(NN*200*NDOWN)
|
||||||
|
c0wav=c0wav/sqrt(xx)
|
||||||
|
write(*,*) 'Peak power: ',maxval(abs(c0wav)**2)
|
||||||
|
write(*,*) 'Average power: ',sum(abs(c0wav(istart:istart+NN*200*NDOWN-1))**2)/(NN*200*NDOWN)
|
||||||
|
call sgran()
|
||||||
|
do ifile=1,nfiles
|
||||||
|
cwav=c0wav
|
||||||
|
if( fspread .ne. 0.0 .or. delay .ne. 0.0 ) then
|
||||||
|
call watterson(cwav,NMAX,fs,delay,fspread)
|
||||||
|
endif
|
||||||
|
cwav=cwav*sig
|
||||||
|
if(snrdb.lt.90) then
|
||||||
|
do i=1,NMAX !Add gaussian noise at specified SNR
|
||||||
|
xnoise=gran()
|
||||||
|
iwave(i)=100*(real(cwav(i-1)) + xnoise)
|
||||||
|
enddo
|
||||||
|
endif
|
||||||
|
snrtest=sum(real(iwave(istart:istart+NN*200*NDOWN-1)**2)/(NN*200*NDOWN))/100.0**2-1
|
||||||
|
write(*,*) 'sample SNR: ',10*log10(snrtest)+10*log10(6.0/2.5)
|
||||||
|
hwav=default_header(12000,NMAX)
|
||||||
|
write(fname,1102) ifile
|
||||||
|
1102 format('000000_',i4.4,'.wav')
|
||||||
|
open(10,file=fname,status='unknown',access='stream')
|
||||||
|
write(10) hwav,iwave !Save to *.wav file
|
||||||
|
close(10)
|
||||||
|
enddo
|
||||||
|
endif
|
||||||
|
write(*,1110) ifile,xdt,f0,snrdb,fname
|
||||||
|
1110 format(i4,f7.2,f8.2,f7.1,2x,a16)
|
||||||
|
|
||||||
|
999 end program wsprdpsksim
|
||||||
Binary file not shown.
@@ -0,0 +1,94 @@
|
|||||||
|
#ifndef WSJTX_UDP_CLIENT_WIDGET_MODEL_HPP__
|
||||||
|
#define WSJTX_UDP_CLIENT_WIDGET_MODEL_HPP__
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QSortFilterProxyModel>
|
||||||
|
#include <QString>
|
||||||
|
#include <QRegularExpression>
|
||||||
|
#include <QtWidgets>
|
||||||
|
|
||||||
|
#include "MessageServer.hpp"
|
||||||
|
|
||||||
|
class QAbstractItemModel;
|
||||||
|
class QModelIndex;
|
||||||
|
class QColor;
|
||||||
|
|
||||||
|
using Frequency = MessageServer::Frequency;
|
||||||
|
|
||||||
|
class ClientWidget
|
||||||
|
: public QDockWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit ClientWidget (QAbstractItemModel * decodes_model, QAbstractItemModel * beacons_model
|
||||||
|
, QString const& id, QString const& version, QString const& revision
|
||||||
|
, QListWidget const * calls_of_interest, QWidget * parent = nullptr);
|
||||||
|
~ClientWidget ();
|
||||||
|
|
||||||
|
bool fast_mode () const {return fast_mode_;}
|
||||||
|
|
||||||
|
Q_SLOT void update_status (QString const& id, Frequency f, QString const& mode, QString const& dx_call
|
||||||
|
, QString const& report, QString const& tx_mode, bool tx_enabled
|
||||||
|
, bool transmitting, bool decoding, qint32 rx_df, qint32 tx_df
|
||||||
|
, QString const& de_call, QString const& de_grid, QString const& dx_grid
|
||||||
|
, bool watchdog_timeout, QString const& sub_mode, bool fast_mode);
|
||||||
|
Q_SLOT void decode_added (bool is_new, QString const& client_id, QTime, qint32 snr
|
||||||
|
, float delta_time, quint32 delta_frequency, QString const& mode
|
||||||
|
, QString const& message, bool low_confidence, bool off_air);
|
||||||
|
Q_SLOT void beacon_spot_added (bool is_new, QString const& client_id, QTime, qint32 snr
|
||||||
|
, float delta_time, Frequency delta_frequency, qint32 drift
|
||||||
|
, QString const& callsign, QString const& grid, qint32 power
|
||||||
|
, bool off_air);
|
||||||
|
Q_SLOT void clear_decodes (QString const& client_id);
|
||||||
|
|
||||||
|
Q_SIGNAL void do_reply (QModelIndex const&, quint8 modifier);
|
||||||
|
Q_SIGNAL void do_halt_tx (QString const& id, bool auto_only);
|
||||||
|
Q_SIGNAL void do_free_text (QString const& id, QString const& text, bool);
|
||||||
|
Q_SIGNAL void location (QString const& id, QString const& text);
|
||||||
|
Q_SIGNAL void highlight_callsign (QString const& id, QString const& call
|
||||||
|
, QColor const& bg = QColor {}, QColor const& fg = QColor {}
|
||||||
|
, bool last_only = false);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString id_;
|
||||||
|
QListWidget const * calls_of_interest_;
|
||||||
|
class IdFilterModel final
|
||||||
|
: public QSortFilterProxyModel
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
IdFilterModel (QString const& client_id);
|
||||||
|
|
||||||
|
void de_call (QString const&);
|
||||||
|
void rx_df (int);
|
||||||
|
|
||||||
|
QVariant data (QModelIndex const& proxy_index, int role = Qt::DisplayRole) const override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool filterAcceptsRow (int source_row, QModelIndex const& source_parent) const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString client_id_;
|
||||||
|
QString call_;
|
||||||
|
QRegularExpression base_call_re_;
|
||||||
|
int rx_df_;
|
||||||
|
} decodes_proxy_model_;
|
||||||
|
QTableView * decodes_table_view_;
|
||||||
|
QTableView * beacons_table_view_;
|
||||||
|
QLineEdit * message_line_edit_;
|
||||||
|
QLineEdit * grid_line_edit_;
|
||||||
|
QStackedLayout * decodes_stack_;
|
||||||
|
QAbstractButton * auto_off_button_;
|
||||||
|
QAbstractButton * halt_tx_button_;
|
||||||
|
QLabel * de_label_;
|
||||||
|
QLabel * mode_label_;
|
||||||
|
bool fast_mode_;
|
||||||
|
QLabel * frequency_label_;
|
||||||
|
QLabel * dx_label_;
|
||||||
|
QLabel * rx_df_label_;
|
||||||
|
QLabel * tx_df_label_;
|
||||||
|
QLabel * report_label_;
|
||||||
|
bool columns_resized_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,196 +0,0 @@
|
|||||||
64 128
|
|
||||||
9 4
|
|
||||||
8 8 8 8 9 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 8 8 8 8 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 9 8 8 8 8 8 8 8
|
|
||||||
4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
|
|
||||||
1 17 33 50 67 83 98 114 0
|
|
||||||
2 18 34 50 68 84 99 115 0
|
|
||||||
3 19 35 51 69 85 100 115 0
|
|
||||||
4 20 36 52 70 86 101 115 0
|
|
||||||
2 20 35 53 71 87 102 113 128
|
|
||||||
5 21 33 54 64 88 103 116 0
|
|
||||||
6 19 37 55 72 89 98 117 0
|
|
||||||
7 22 38 56 73 90 96 116 0
|
|
||||||
8 23 34 57 72 91 104 118 0
|
|
||||||
7 24 39 58 74 84 100 119 0
|
|
||||||
9 22 40 59 74 92 105 120 0
|
|
||||||
9 25 41 55 75 91 106 114 0
|
|
||||||
10 25 36 51 67 74 107 121 0
|
|
||||||
11 22 36 54 72 93 102 122 0
|
|
||||||
12 25 42 60 76 89 103 123 0
|
|
||||||
8 26 38 51 77 93 105 124 0
|
|
||||||
13 27 40 61 77 94 99 119 0
|
|
||||||
13 17 43 54 73 85 108 124 0
|
|
||||||
1 28 40 62 71 84 108 125 0
|
|
||||||
12 29 38 53 67 86 108 126 0
|
|
||||||
14 28 43 51 78 94 96 117 0
|
|
||||||
11 17 42 62 79 92 104 126 0
|
|
||||||
4 29 39 57 65 87 109 116 0
|
|
||||||
2 27 38 55 78 79 107 127 0
|
|
||||||
13 24 44 53 66 83 103 117 0
|
|
||||||
15 30 43 55 67 90 105 128 0
|
|
||||||
6 22 45 48 78 88 106 119 0
|
|
||||||
14 25 33 63 65 73 99 118 0
|
|
||||||
6 31 46 64 80 95 102 125 0
|
|
||||||
5 18 37 65 79 94 110 113 0
|
|
||||||
14 23 44 59 71 88 111 123 0
|
|
||||||
13 32 47 62 70 91 109 128 0
|
|
||||||
15 23 41 56 76 95 112 0 0
|
|
||||||
11 29 41 47 68 69 105 117 0
|
|
||||||
10 30 37 64 73 86 111 119 0
|
|
||||||
5 32 45 60 69 96 101 127 0
|
|
||||||
15 24 48 62 65 96 97 115 0
|
|
||||||
3 23 42 64 77 83 109 0 0
|
|
||||||
16 18 40 52 69 89 102 112 0
|
|
||||||
9 20 49 63 76 94 109 121 0
|
|
||||||
15 20 33 66 77 84 110 127 0
|
|
||||||
10 21 44 60 80 82 112 126 0
|
|
||||||
16 26 41 58 81 92 107 125 0
|
|
||||||
3 27 48 59 82 95 110 118 0
|
|
||||||
10 27 49 57 71 89 101 124 0
|
|
||||||
4 26 42 61 68 90 100 122 0
|
|
||||||
6 26 44 50 75 85 101 118 0
|
|
||||||
7 28 37 47 66 76 82 114 0
|
|
||||||
12 19 43 52 80 88 104 121 0
|
|
||||||
2 31 47 56 75 93 108 123 0
|
|
||||||
1 31 36 59 81 87 104 124 0
|
|
||||||
3 32 39 50 81 97 106 121 0
|
|
||||||
12 24 34 54 79 90 98 120 0
|
|
||||||
1 19 49 56 82 92 103 122 0
|
|
||||||
7 21 35 61 70 93 106 125 0
|
|
||||||
14 18 46 60 70 97 107 122 0
|
|
||||||
8 31 39 61 63 86 98 127 128
|
|
||||||
4 28 34 45 75 97 110 126 0
|
|
||||||
16 30 45 63 72 95 100 113 0
|
|
||||||
8 21 48 52 74 87 111 114 0
|
|
||||||
9 32 46 58 68 83 113 123 0
|
|
||||||
11 30 46 53 81 91 99 116 0
|
|
||||||
5 29 49 58 78 85 112 120 0
|
|
||||||
16 17 35 57 66 80 111 120 0
|
|
||||||
1 19 51 54
|
|
||||||
2 5 24 50
|
|
||||||
3 38 44 52
|
|
||||||
4 23 46 58
|
|
||||||
6 30 36 63
|
|
||||||
7 27 29 47
|
|
||||||
8 10 48 55
|
|
||||||
9 16 57 60
|
|
||||||
11 12 40 61
|
|
||||||
13 35 42 45
|
|
||||||
14 22 34 62
|
|
||||||
15 20 49 53
|
|
||||||
17 18 25 32
|
|
||||||
21 28 31 56
|
|
||||||
26 33 37 41
|
|
||||||
39 43 59 64
|
|
||||||
1 18 22 64
|
|
||||||
2 30 39 56
|
|
||||||
3 7 49 54
|
|
||||||
4 5 40 41
|
|
||||||
6 42 55 60
|
|
||||||
8 11 14 27
|
|
||||||
9 31 33 38
|
|
||||||
10 25 37 53
|
|
||||||
12 13 15 28
|
|
||||||
16 43 46 47
|
|
||||||
17 24 44 45
|
|
||||||
19 21 48 58
|
|
||||||
20 23 34 63
|
|
||||||
26 35 59 62
|
|
||||||
29 50 51 57
|
|
||||||
32 36 52 61
|
|
||||||
1 6 28 41
|
|
||||||
2 9 53 58
|
|
||||||
3 5 55 64
|
|
||||||
4 13 14 51
|
|
||||||
7 30 35 48
|
|
||||||
8 16 20 24
|
|
||||||
10 23 52 57
|
|
||||||
11 17 19 39
|
|
||||||
12 33 34 43
|
|
||||||
15 22 38 46
|
|
||||||
18 21 26 49
|
|
||||||
25 31 42 47
|
|
||||||
27 36 58 59
|
|
||||||
29 56 61 62
|
|
||||||
32 34 48 50
|
|
||||||
27 37 44 60
|
|
||||||
40 45 54 63
|
|
||||||
1 2 47 52
|
|
||||||
3 13 16 21
|
|
||||||
4 39 49 60
|
|
||||||
5 20 25 62
|
|
||||||
6 14 18 53
|
|
||||||
7 12 24 26
|
|
||||||
8 33 50 54
|
|
||||||
9 23 45 64
|
|
||||||
10 43 61 63
|
|
||||||
11 31 44 51
|
|
||||||
15 36 42 56
|
|
||||||
17 46 55 57
|
|
||||||
19 22 32 37
|
|
||||||
28 40 57 59
|
|
||||||
6 29 35 38
|
|
||||||
23 28 30 37
|
|
||||||
25 41 48 64
|
|
||||||
1 13 20 26
|
|
||||||
2 34 46 61
|
|
||||||
3 34 36 39
|
|
||||||
4 32 55 56
|
|
||||||
5 19 31 45
|
|
||||||
7 9 14 59
|
|
||||||
8 18 28 35
|
|
||||||
10 11 13 60
|
|
||||||
12 47 50 58
|
|
||||||
15 33 40 48
|
|
||||||
16 17 38 41
|
|
||||||
21 24 27 63
|
|
||||||
22 24 30 53
|
|
||||||
29 42 49 64
|
|
||||||
43 51 52 62
|
|
||||||
42 44 48 54
|
|
||||||
1 25 38 61
|
|
||||||
2 10 19 41
|
|
||||||
3 18 47 63
|
|
||||||
4 20 35 57
|
|
||||||
5 23 51 60
|
|
||||||
6 27 31 49
|
|
||||||
7 15 39 45
|
|
||||||
8 26 46 53
|
|
||||||
9 12 32 62
|
|
||||||
11 22 43 54
|
|
||||||
14 16 50 55
|
|
||||||
17 21 30 40
|
|
||||||
29 33 44 59
|
|
||||||
8 21 36 37
|
|
||||||
37 52 56 58
|
|
||||||
1 7 53 57
|
|
||||||
2 17 28 62
|
|
||||||
3 10 46 59
|
|
||||||
4 36 45 47
|
|
||||||
5 14 29 39
|
|
||||||
6 15 25 54
|
|
||||||
9 22 49 51
|
|
||||||
11 16 26 34
|
|
||||||
12 27 52 55
|
|
||||||
13 24 43 56
|
|
||||||
18 19 20 50
|
|
||||||
23 32 38 40
|
|
||||||
30 41 44 58
|
|
||||||
31 35 60 64
|
|
||||||
33 39 42 63
|
|
||||||
5 30 59 61
|
|
||||||
1 12 48 60
|
|
||||||
2 3 4 37
|
|
||||||
6 8 23 62
|
|
||||||
7 21 25 34
|
|
||||||
9 28 44 47
|
|
||||||
10 17 27 35
|
|
||||||
11 53 63 64
|
|
||||||
13 40 49 52
|
|
||||||
14 46 54 56
|
|
||||||
15 31 50 61
|
|
||||||
16 18 45 51
|
|
||||||
19 29 43 55
|
|
||||||
20 22 42 58
|
|
||||||
24 36 41 57
|
|
||||||
5 26 32 57
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
/* DISTRIB.H - Interface to module for handling distributions over numbers. */
|
|
||||||
|
|
||||||
/* Copyright (c) 1995-2012 by Radford M. Neal and Peter Junteng Liu.
|
|
||||||
*
|
|
||||||
* Permission is granted for anyone to copy, use, modify, and distribute
|
|
||||||
* these programs and accompanying documents for any purpose, provided
|
|
||||||
* this copyright notice is retained and prominently displayed, and note
|
|
||||||
* is made of any changes made to these programs. These programs and
|
|
||||||
* documents are distributed without any warranty, express or implied.
|
|
||||||
* As the programs were written for research purposes only, they have not
|
|
||||||
* been tested to the degree that would be advisable in any important
|
|
||||||
* application. All use of these programs is entirely at the user's own
|
|
||||||
* risk.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/* DATA STRUCTURES USED TO STORE A DISTRIBUTION LIST. Entries in the list
|
|
||||||
* (distrib_entry) are stored in an array (distrib->list[]). */
|
|
||||||
|
|
||||||
typedef struct distrib_entry
|
|
||||||
{ int num; /* A positive number */
|
|
||||||
double prop; /* Proportion for this number */
|
|
||||||
} distrib_entry;
|
|
||||||
|
|
||||||
typedef struct distrib
|
|
||||||
{ struct distrib_entry *list; /* The list of numbers and proportions */
|
|
||||||
int size; /* Number of entries in the list */
|
|
||||||
} distrib;
|
|
||||||
|
|
||||||
|
|
||||||
/* MACROS TO ACCESS ELEMENTS OF A DISTRIBUTION LIST. Note that indexes for
|
|
||||||
entries start at 0. */
|
|
||||||
|
|
||||||
#define distrib_num(d,i) \
|
|
||||||
((d)->list[i].num) /* The number for the i'th entry */
|
|
||||||
|
|
||||||
#define distrib_prop(d,i) \
|
|
||||||
((d)->list[i].prop) /* The i'th entry's proportion [probability] */
|
|
||||||
|
|
||||||
#define distrib_size(d) \
|
|
||||||
((d)->size) /* The length of the list (integer) */
|
|
||||||
|
|
||||||
|
|
||||||
/* PROCEDURES FOR DISTRIBUTION LISTS. */
|
|
||||||
|
|
||||||
distrib *distrib_create (char *);
|
|
||||||
void distrib_free (distrib *);
|
|
||||||
|
|
||||||
int distrib_max(distrib *);
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user