1 #include "wspr.hh"
2 #include <iostream>
3
4
isValid() const5 bool sdr::WSPRMessage::isValid() const {
6 char call[23], loc[23], pwr[23];
7
8 const char *ptr = msg, *call_ptr = msg;
9 for(; (*ptr)!=' ' ; ptr++) {}
10 strncpy(call, call_ptr, ptr-call_ptr);
11 call[ptr-call_ptr] = 0; ptr++;
12
13 const char *loc_ptr = ptr;
14 for(; (*ptr)!=' '; ptr++) {}
15 strncpy(loc, loc_ptr, ptr-loc_ptr);
16 loc[ptr-loc_ptr] = 0; ptr++;
17
18 const char *pwr_ptr = ptr;
19 for(; (*ptr)!=' '; ptr++) {}
20 strncpy(pwr, pwr_ptr, ptr-pwr_ptr);
21 pwr[ptr-pwr_ptr] = 0;
22
23 return (4 == strlen(loc)) || (6 == strlen(loc));
24 }
25
26 std::string
callsign() const27 sdr::WSPRMessage::callsign() const {
28 char call[23];
29
30 const char *ptr = msg, *call_ptr = msg;
31 for(; (*ptr)!=' ' ; ptr++) {}
32 strncpy(call, call_ptr, ptr-call_ptr);
33 call[ptr-call_ptr] = 0;
34
35 return call;
36 }
37
38
39 std::string
locator() const40 sdr::WSPRMessage::locator() const {
41 char loc[23];
42
43 const char *ptr = msg;
44 for(; (*ptr)!=' ' ; ptr++) {}
45 ptr++;
46
47 const char *loc_ptr = ptr;
48 for(; (*ptr)!=' '; ptr++) {}
49 strncpy(loc, loc_ptr, ptr-loc_ptr);
50 loc[ptr-loc_ptr] = 0;
51 return loc;
52 }
53
power() const54 int sdr::WSPRMessage::power() const {
55 char pwr[23];
56
57 const char *ptr = msg;
58 for(; (*ptr)!=' ' ; ptr++) {} ptr++;
59 for(; (*ptr)!=' ' ; ptr++) {} ptr++;
60
61 const char *pwr_ptr = ptr;
62 for(; (*ptr)!=' '; ptr++) {}
63 strncpy(pwr, pwr_ptr, ptr-pwr_ptr);
64 pwr[ptr-pwr_ptr] = 0;
65
66 return atoi(pwr);
67 }
68
powerW() const69 float sdr::WSPRMessage::powerW() const {
70 char pwr[23];
71
72 const char *ptr = msg;
73 for(; (*ptr)!=' ' ; ptr++) {} ptr++;
74 for(; (*ptr)!=' ' ; ptr++) {} ptr++;
75
76 const char *pwr_ptr = ptr;
77 for(; (*ptr)!=' '; ptr++) {}
78 strncpy(pwr, pwr_ptr, ptr-pwr_ptr);
79 pwr[ptr-pwr_ptr] = 0;
80
81 return std::pow(10, atof(pwr)/10)/1000;
82 }
83
84
85 /*
86 * This function is basically a C re-implementation of the mept162 Fortran routine of the
87 * original WSPR code.
88 */
89 void
wspr_decode(const Buffer<int16_t> & in,std::list<WSPRMessage> & msgs,double Fbfo)90 sdr::wspr_decode(const Buffer<int16_t> &in, std::list<WSPRMessage> &msgs, double Fbfo)
91 {
92 float psd[513]; // Average power spectrum (+/- 256, incl 0, hence 256 + 1 + 256 elments)
93 for (int i=0; i<513; i++) { psd[i] = 0; }
94
95 cmplx_t *c2 = new cmplx_t[65536];
96 for (int i=0; i<65536; i++) { c2[i].re=0; c2[i].im=0;}
97
98 int npts=in.size(), nbfo=Fbfo, jz;
99 mix162_(reinterpret_cast<int16_t *>(in.data()), &npts, &nbfo, c2, &jz, psd);
100
101 float sstf[5*275]; // 5x275 - column major
102 int kz = 0; // (out) The number of signal candidates found
103 jz = 45000;
104 sync162_(c2, &jz, psd, sstf, &kz);
105
106 if (0 >= kz) { delete[] c2; return; }
107
108 cmplx_t *c3 = new cmplx_t[45000];
109 cmplx_t *c4 = new cmplx_t[45000];
110
111 // For every candidate found
112 for (int k=0; k<kz; k++)
113 {
114 float snrsync = sstf[5*k+0];
115 float snrx = sstf[5*k+1];
116 float dtx = sstf[5*k+2];
117 float dfx = sstf[5*k+3];
118 float drift = sstf[5*k+4];
119
120 // Fix frequency drift, store result into c3
121 float a[5] = { -dfx, float(-0.5*drift), 0.0, 0.0, 0.0 };
122 int jz = 45000;
123 for (int i=0; i<45000; i++) { c3[i].re=0; c3[i].im=0; }
124 twkfreq_(c2, c3, &jz, a);
125
126 // Decode signal
127 char message[22];
128 for (size_t i=0; i<22; i++) { message[i] = 0; }
129
130 int minsync = 1; int nsync = round(snrsync);
131 if (nsync < 0) { nsync = 0; }
132
133 float minsnr = -33; int nsnrx = round(snrx);
134 if (nsnrx < minsnr) { nsnrx = minsnr; }
135 if ((nsync < minsync) || (nsnrx < minsnr)) {
136 continue;
137 }
138
139 float dt = 1./375;
140 for (int idt=0; idt<=128; idt++) {
141 int ii = (idt+1)/2;
142 if (idt%2) { ii = -ii; }
143 int i1 = round((dtx+2.0)/dt) + ii-1; // Start index for synced symbols.
144 for (int i=0; i<45000; i++) { c4[i].re=0; c4[i].im=0; }
145 if (i1 >= 0) {
146 for (int i=i1; i<jz; i++) { c4[i-i1] = c3[i]; }
147 } else {
148 for (int i=0; i<(jz+i1-1); i++) { c4[i+2-i1] = c3[i]; }
149 }
150 int ncycles=0, nerr=0;
151 int metric[512]; int nc4=45000;
152 decode162_(c4, &nc4, message, &ncycles, metric, &nerr);
153 // Check message and store in list
154 if (strncmp(" ", message, 6) && strncmp("000AAA", message, 6)) {
155 WSPRMessage msg;
156 msg.df = dfx; msg.dt = dtx; msg.snr = snrx;
157 memcpy(msg.msg, message, 22);
158 msgs.push_back(msg);
159 break;
160 }
161 }
162 }
163
164 delete[] c3;
165 delete[] c4;
166 }
167
168
169 double
loc_dist(const std::string & loc_a,const std::string & loc_b)170 sdr::loc_dist(const std::string &loc_a, const std::string &loc_b) {
171 int Dmiles, Dkm, nAz=0, nEl=0, nHotAz, nHotABetter;
172 double utch=0;
173 char locA[6]; char locB[6];
174 for (size_t i=0; i<6; i++) { locA[i] = locB[i] = ' '; }
175 memcpy(locA, loc_a.c_str(), std::min(size_t(6),loc_a.size()));
176 memcpy(locB, loc_b.c_str(), std::min(size_t(6),loc_b.size()));
177 azdist_(locA, locB, &utch, &nAz, &nEl, &Dmiles, &Dkm, &nHotAz, &nHotABetter);
178 return Dkm;
179 }
180
181 void
loc2deg(const std::string & loc,float & lon,float & lat)182 sdr::loc2deg(const std::string &loc, float &lon, float &lat) {
183 char grid[6];
184 memcpy(grid, " ", 6);
185 memcpy(grid, loc.c_str(), std::min(size_t(6), loc.length()));
186 grid2deg_(grid, &lon, &lat);
187 }
188
189 std::string
deg2loc(float lon,float lat)190 sdr::deg2loc(float lon, float lat) {
191 char grid[6];
192 memcpy(grid, " ", 6);
193 deg2grid_(&lon, &lat, grid);
194 return grid;
195 }
196