2015-06-14 11:21:50 -04:00
|
|
|
/*
|
|
|
|
File name: wsprsim.c (first committed to wsjtx June 13, 2015)
|
|
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <math.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include "wsprsim_utils.h"
|
|
|
|
#include "wsprd_utils.h"
|
|
|
|
#include "fano.h"
|
|
|
|
|
|
|
|
int printdata=0;
|
|
|
|
|
|
|
|
void usage() {
|
|
|
|
printf("Usage: wsprsim [options] message\n");
|
|
|
|
printf(" message format: \"K1ABC FN42 33\"\n");
|
|
|
|
printf(" \"PJ4/K1ABC 33\"\n");
|
|
|
|
printf(" \"<PJ4/K1ABC> FK52UD 33\"\n");
|
|
|
|
printf("Options:\n");
|
|
|
|
printf(" -c (print channel symbols)\n");
|
|
|
|
printf(" -d (print packed data with zero tail - 11 bytes)\n");
|
2018-01-04 12:40:33 -05:00
|
|
|
printf(" -f x (-100 Hz < f < 100 Hz)\n");
|
2015-06-14 11:21:50 -04:00
|
|
|
printf(" -o filename (write a c2 file with this name)\n");
|
|
|
|
printf(" -s x (x is snr of signal that is written to .c2 file)\n");
|
|
|
|
printf("\n");
|
|
|
|
printf(" e.g. ./wsprsim -cds -28 -o 150613_1920.c2 \"K1ABC FN42 33\"\n");
|
|
|
|
printf(" then ./wsprd 150613_1920.c2\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
int add_signal_vector(float f0, float t0, float amp, unsigned char* symbols
|
|
|
|
, double* isig, double* qsig)
|
|
|
|
{
|
|
|
|
int i, j, ii, idelay;
|
|
|
|
double phi=0.0, twopidt, df, dt, dphi;
|
|
|
|
twopidt=8.0*atan(1.0)/375.0;
|
|
|
|
df=375.0/256.0;
|
|
|
|
dt=1/375.0;
|
|
|
|
idelay=t0/dt;
|
|
|
|
|
|
|
|
for (i=0; i<162; i++) {
|
|
|
|
dphi=twopidt*(f0 + ( (double)symbols[i]-1.5)*df );
|
|
|
|
for ( j=0; j<256; j++ ) {
|
|
|
|
ii=idelay+256*i+j;
|
|
|
|
isig[ii]=isig[ii]+amp*cos(phi);
|
|
|
|
qsig[ii]=qsig[ii]+amp*sin(phi);
|
|
|
|
phi=phi+dphi;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
char* tobinary(int x)
|
|
|
|
{
|
|
|
|
static char b[33];
|
|
|
|
b[0] = '\0';
|
|
|
|
|
|
|
|
long unsigned int z;
|
|
|
|
for (z = 0x80000000; z > 0; z >>= 1)
|
|
|
|
{
|
|
|
|
strcat(b, ((x & z) == z) ? "1" : "0");
|
|
|
|
}
|
|
|
|
|
|
|
|
return b;
|
|
|
|
}
|
|
|
|
|
|
|
|
double gaussrand()
|
|
|
|
{
|
|
|
|
static double V1, V2, S;
|
|
|
|
static int phase = 0;
|
|
|
|
double X;
|
|
|
|
|
|
|
|
if(phase == 0) {
|
|
|
|
do {
|
|
|
|
double U1 = (double)rand() / RAND_MAX;
|
|
|
|
double U2 = (double)rand() / RAND_MAX;
|
|
|
|
|
|
|
|
V1 = 2 * U1 - 1;
|
|
|
|
V2 = 2 * U2 - 1;
|
|
|
|
S = V1 * V1 + V2 * V2;
|
|
|
|
} while(S >= 1 || S == 0);
|
|
|
|
|
|
|
|
X = V1 * sqrt(-2 * log(S) / S);
|
|
|
|
} else
|
|
|
|
X = V2 * sqrt(-2 * log(S) / S);
|
|
|
|
|
|
|
|
phase = 1 - phase;
|
|
|
|
|
|
|
|
return X;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned long writec2file(char *c2filename, int trmin, double freq
|
|
|
|
, double *idat, double *qdat)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
float buffer[2*45000];
|
|
|
|
memset(buffer,0,sizeof(float)*2*45000);
|
|
|
|
FILE *fp;
|
|
|
|
|
|
|
|
fp = fopen(c2filename,"wb");
|
|
|
|
if( fp == NULL ) {
|
|
|
|
fprintf(stderr, "Could not open c2 file '%s'\n", c2filename);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
unsigned long nwrite = fwrite(c2filename,sizeof(char),14,fp);
|
|
|
|
nwrite = fwrite(&trmin, sizeof(int), 1, fp);
|
|
|
|
nwrite = fwrite(&freq, sizeof(double), 1, fp);
|
|
|
|
|
|
|
|
for(i=0; i<45000; i++) {
|
|
|
|
buffer[2*i]=idat[i];
|
|
|
|
buffer[2*i+1]=-qdat[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
nwrite = fwrite(buffer, sizeof(float), 2*45000, fp);
|
|
|
|
if( nwrite == 2*45000 ) {
|
|
|
|
return nwrite;
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//********************************************************************
|
|
|
|
int main(int argc, char *argv[])
|
|
|
|
{
|
|
|
|
extern char *optarg;
|
|
|
|
extern int optind;
|
2015-06-15 18:24:02 -04:00
|
|
|
int i, c, printchannel=0, writec2=0;
|
2015-06-14 11:21:50 -04:00
|
|
|
float snr=50.0;
|
2018-01-04 12:40:33 -05:00
|
|
|
float f0=0.0, t0=1.0;
|
2015-07-25 19:48:53 -04:00
|
|
|
char *message, *c2filename, *hashtab;
|
2015-06-15 18:24:02 -04:00
|
|
|
c2filename=malloc(sizeof(char)*15);
|
2015-07-25 19:48:53 -04:00
|
|
|
hashtab=malloc(sizeof(char)*32768*13);
|
|
|
|
memset(hashtab,0,sizeof(char)*32768*13);
|
2015-06-15 18:24:02 -04:00
|
|
|
|
2015-06-14 11:21:50 -04:00
|
|
|
// message length is 22 characters
|
|
|
|
message=malloc(sizeof(char)*23);
|
|
|
|
|
2015-06-15 18:24:02 -04:00
|
|
|
strcpy(c2filename,"000000_0001.c2");
|
2015-07-25 19:48:53 -04:00
|
|
|
|
|
|
|
srand(getpid());
|
|
|
|
|
2018-01-04 12:40:33 -05:00
|
|
|
while ( (c = getopt(argc, argv, "cdf:o:s:")) !=-1 ) {
|
2015-06-14 11:21:50 -04:00
|
|
|
switch (c) {
|
|
|
|
case 'c':
|
|
|
|
printchannel=1;
|
2015-06-15 18:24:02 -04:00
|
|
|
break;
|
2015-06-14 11:21:50 -04:00
|
|
|
case 'd':
|
|
|
|
printdata=1;
|
2015-06-15 18:24:02 -04:00
|
|
|
break;
|
2018-01-04 12:40:33 -05:00
|
|
|
case 'f':
|
|
|
|
f0 = atof(optarg);
|
2015-06-14 11:21:50 -04:00
|
|
|
case 'o':
|
|
|
|
c2filename = optarg;
|
2015-06-15 18:24:02 -04:00
|
|
|
writec2=1;
|
2015-06-14 11:21:50 -04:00
|
|
|
break;
|
|
|
|
case 's':
|
2018-01-01 20:16:13 -05:00
|
|
|
// snr = (float)atoi(optarg);
|
|
|
|
snr = atof(optarg);
|
2015-06-14 11:21:50 -04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if( optind+1 > argc ) {
|
|
|
|
usage();
|
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
message=argv[optind];
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned char channel_symbols[162];
|
2015-07-25 19:48:53 -04:00
|
|
|
get_wspr_channel_symbols(message, hashtab, channel_symbols);
|
2015-06-14 11:21:50 -04:00
|
|
|
|
|
|
|
if( printchannel ) {
|
|
|
|
printf("Channel symbols:\n");
|
|
|
|
for (i=0; i<162; i++) {
|
|
|
|
printf("%d ",channel_symbols[i]);
|
|
|
|
}
|
|
|
|
printf("\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
// add noise, then signal
|
|
|
|
double isig[45000], qsig[45000];
|
|
|
|
memset(isig,0,sizeof(double)*45000);
|
|
|
|
memset(qsig,0,sizeof(double)*45000);
|
|
|
|
|
|
|
|
if( snr < 40 ) {
|
|
|
|
// snr in 375Hz is 8.2 dB higher than in 2500 Hz.
|
|
|
|
snr=snr+8.2;
|
|
|
|
snr=pow(10,snr/20.0)*pow(2,0.5);
|
|
|
|
|
|
|
|
for (i = 0; i<45000; i++) {
|
|
|
|
isig[i]=isig[i]+gaussrand();
|
|
|
|
qsig[i]=qsig[i]+gaussrand();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
snr=1.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
add_signal_vector(f0, t0, snr, channel_symbols, isig, qsig);
|
2015-06-15 18:24:02 -04:00
|
|
|
if( writec2) {
|
2015-06-14 11:21:50 -04:00
|
|
|
// write a .c2 file
|
|
|
|
double carrierfreq=10.1387;
|
|
|
|
int wsprtype=2;
|
|
|
|
printf("Writing %s\n",c2filename);
|
|
|
|
writec2file(c2filename, wsprtype, carrierfreq, isig, qsig);
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|