/* File name: wsprsim.c (first committed to wsjtx June 13, 2015) */ #include #include #include #include #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(" \" FK52UD 33\"\n"); printf("Options:\n"); printf(" -c (print channel symbols)\n"); printf(" -d (print packed data with zero tail - 11 bytes)\n"); 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; int i, c, printchannel=0, writec2=0; float snr=50.0; char *message, *c2filename; c2filename=malloc(sizeof(char)*15); // message length is 22 characters message=malloc(sizeof(char)*23); strcpy(c2filename,"000000_0001.c2"); while ( (c = getopt(argc, argv, "cdo:s:")) !=-1 ) { switch (c) { case 'c': printchannel=1; break; case 'd': printdata=1; break; case 'o': c2filename = optarg; writec2=1; break; case 's': snr = (float)atoi(optarg); break; } } if( optind+1 > argc ) { usage(); return 0; } else { message=argv[optind]; } unsigned char channel_symbols[162]; get_wspr_channel_symbols(message, channel_symbols); 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; } float f0, t0; f0=0.0; t0=1.0; add_signal_vector(f0, t0, snr, channel_symbols, isig, qsig); if( writec2) { // write a .c2 file double carrierfreq=10.1387; int wsprtype=2; printf("Writing %s\n",c2filename); writec2file(c2filename, wsprtype, carrierfreq, isig, qsig); } return 1; }