SVN r8748
This commit is contained in:
@@ -1,3 +1,2 @@
|
||||
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
|
||||
use, intrinsic :: iso_c_binding, only: c_int, c_loc, c_int8_t, c_bool, c_short
|
||||
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")
|
||||
use, intrinsic :: iso_c_binding, only: c_short, c_ptr, c_int
|
||||
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:
|
||||
! 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.
|
||||
|
||||
! 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
|
||||
+7
-2
@@ -4,6 +4,7 @@
|
||||
|
||||
#include <QString>
|
||||
#include <QByteArray>
|
||||
#include <QDebug>
|
||||
|
||||
#include "pimpl_impl.hpp"
|
||||
|
||||
@@ -88,9 +89,13 @@ namespace NetworkMessage
|
||||
*parent >> type >> id_;
|
||||
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_;
|
||||
@@ -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