Fix multi frequencies issue

master
F5OEO 2023-01-24 12:20:34 +01:00
rodzic bc4a1e3f97
commit 58a6fc6375
1 zmienionych plików z 562 dodań i 447 usunięć

427
wspr.cpp
Wyświetl plik

@ -17,6 +17,7 @@
// ha7ilm: added RPi2 support based on a patch to PiFmRds by Cristophe
// Jacquet and Richard Hirst: http://git.io/vn7O9
// F5OEO : adapt to librpitx for cleaner spectrum
#include <stdio.h>
#include <string.h>
@ -46,15 +47,17 @@
#include <sys/timex.h>
#include "librpitx/src/librpitx.h"
clkgpio *clk = NULL;
ngfmdmasync *ngfmtest = NULL;
#define ABORT(a) exit(a)
// Used for debugging
#define MARK std::cout << "Currently in file: " << __FILE__ << " line: " << __LINE__ << std::endl
typedef enum {WSPR,TONE} mode_type;
typedef enum
{
WSPR,
TONE
} mode_type;
// WSRP nominal symbol time
#define WSPR_SYMTIME (8192.0 / 12000.0)
@ -64,22 +67,22 @@ typedef enum {WSPR,TONE} mode_type;
#define WSPR15_RAND_OFFSET 8
// Disable the PWM clock and wait for it to become 'not busy'.
void disable_clock() {
void disable_clock()
{
}
// Turn on TX
void txon() {
void txon()
{
// ACCESS_BUS_ADDR(PADS_GPIO_0_27_BUS) = 0x5a000018 + 7; //16mA +10.6dBm
disable_clock();
}
// Turn transmitter on
void txoff() {
void txoff()
{
disable_clock();
}
@ -98,13 +101,13 @@ void txSym(
const double &f_pwm_clk,
struct PageInfo instrs[],
struct PageInfo &constPage,
int & bufPtr
) {
int &bufPtr)
{
}
// Turn off (reset) DMA engine
void unSetupDMA(){
void unSetupDMA()
{
txoff();
}
@ -112,18 +115,17 @@ void unSetupDMA(){
// Truncate at bit lsb. i.e. set all bits less than lsb to zero.
double bit_trunc(
const double &d,
const int & lsb
) {
const int &lsb)
{
return floor(d / pow(2.0, lsb)) * pow(2.0, lsb);
}
// Convert string to uppercase
void to_upper(
char *str
) {
while(*str) {
char *str)
{
while (*str)
{
*str = toupper(*str);
str++;
}
@ -134,8 +136,8 @@ void wspr(
const char *call,
const char *l_pre,
const char *dbm,
unsigned char* symbols
) {
unsigned char *symbols)
{
// pack prefix in nadd, call in n1, grid, dbm in n2
char *c, buf[16];
strncpy(buf, call, 16);
@ -143,34 +145,49 @@ void wspr(
to_upper(c);
unsigned long ng, nadd = 0;
if(strchr(c, '/')){ //prefix-suffix
if (strchr(c, '/'))
{ // prefix-suffix
nadd = 2;
int i = strchr(c, '/') - c; // stroke position
int n = strlen(c) - i - 1; // suffix len, prefix-call len
c[i] = '\0';
if(n==1) ng=60000-32768+(c[i+1]>='0'&&c[i+1]<='9'?c[i+1]-'0':c[i+1]==' '?38:c[i+1]-'A'+10); // suffix /A to /Z, /0 to /9
if(n==2) ng=60000+26+10*(c[i+1]-'0')+(c[i+2]-'0'); // suffix /10 to /99
if(n>2){ // prefix EA8/, right align
ng=(i<3?36:c[i-3]>='0'&&c[i-3]<='9'?c[i-3]-'0':c[i-3]-'A'+10);
ng=37*ng+(i<2?36:c[i-2]>='0'&&c[i-2]<='9'?c[i-2]-'0':c[i-2]-'A'+10);
ng=37*ng+(i<1?36:c[i-1]>='0'&&c[i-1]<='9'?c[i-1]-'0':c[i-1]-'A'+10);
if(ng<32768) nadd=1; else ng=ng-32768;
if (n == 1)
ng = 60000 - 32768 + (c[i + 1] >= '0' && c[i + 1] <= '9' ? c[i + 1] - '0' : c[i + 1] == ' ' ? 38
: c[i + 1] - 'A' + 10); // suffix /A to /Z, /0 to /9
if (n == 2)
ng = 60000 + 26 + 10 * (c[i + 1] - '0') + (c[i + 2] - '0'); // suffix /10 to /99
if (n > 2)
{ // prefix EA8/, right align
ng = (i < 3 ? 36 : c[i - 3] >= '0' && c[i - 3] <= '9' ? c[i - 3] - '0'
: c[i - 3] - 'A' + 10);
ng = 37 * ng + (i < 2 ? 36 : c[i - 2] >= '0' && c[i - 2] <= '9' ? c[i - 2] - '0'
: c[i - 2] - 'A' + 10);
ng = 37 * ng + (i < 1 ? 36 : c[i - 1] >= '0' && c[i - 1] <= '9' ? c[i - 1] - '0'
: c[i - 1] - 'A' + 10);
if (ng < 32768)
nadd = 1;
else
ng = ng - 32768;
c = c + i + 1;
}
}
int i=(isdigit(c[2])?2:isdigit(c[1])?1:0); //last prefix digit of de-suffixed/de-prefixed callsign
int i = (isdigit(c[2]) ? 2 : isdigit(c[1]) ? 1
: 0); // last prefix digit of de-suffixed/de-prefixed callsign
int n = strlen(c) - i - 1; // 2nd part of call len
unsigned long n1;
n1=(i<2?36:c[i-2]>='0'&&c[i-2]<='9'?c[i-2]-'0':c[i-2]-'A'+10);
n1=36*n1+(i<1?36:c[i-1]>='0'&&c[i-1]<='9'?c[i-1]-'0':c[i-1]-'A'+10);
n1 = (i < 2 ? 36 : c[i - 2] >= '0' && c[i - 2] <= '9' ? c[i - 2] - '0'
: c[i - 2] - 'A' + 10);
n1 = 36 * n1 + (i < 1 ? 36 : c[i - 1] >= '0' && c[i - 1] <= '9' ? c[i - 1] - '0'
: c[i - 1] - 'A' + 10);
n1 = 10 * n1 + c[i] - '0';
n1 = 27 * n1 + (n < 1 ? 26 : c[i + 1] - 'A');
n1 = 27 * n1 + (n < 2 ? 26 : c[i + 2] - 'A');
n1 = 27 * n1 + (n < 3 ? 26 : c[i + 3] - 'A');
// if(rand() % 2) nadd=0;
if(!nadd){
if (!nadd)
{
// Copy locator locally since it is declared const and we cannot modify
// its contents in-place.
char l[4];
@ -180,7 +197,8 @@ void wspr(
}
int p = atoi(dbm); // EIRP in dBm={0,3,7,10,13,17,20,23,27,30,33,37,40,43,47,50,53,57,60}
int corr[] = {0, -1, 1, 0, -1, 2, 1, 0, -1, 1};
p=p>60?60:p<0?0:p+corr[p%10];
p = p > 60 ? 60 : p < 0 ? 0
: p + corr[p % 10];
unsigned long n2 = (ng << 7) | (p + 64 + nadd);
// pack n1,n2,zero-tail into 50 bits
@ -195,22 +213,25 @@ void wspr(
0,
0,
0,
0
};
0};
// convolutional encoding K=32, r=1/2, Layland-Lushbaugh polynomials
int k = 0;
int j, s;
int nstate = 0;
unsigned char symbol[176];
for(j=0;j!=sizeof(packed);j++){
for(i=7;i>=0;i--){
for (j = 0; j != sizeof(packed); j++)
{
for (i = 7; i >= 0; i--)
{
unsigned long poly[2] = {0xf2d05351L, 0xe4613c47L};
nstate = (nstate << 1) | ((packed[j] >> i) & 1);
for(s=0;s!=2;s++){ //convolve
for (s = 0; s != 2; s++)
{ // convolve
unsigned long n = nstate & poly[s];
int even = 0; // even := parity(n)
while(n){
while (n)
{
even = 1 - even;
n = n & (n - 1);
}
@ -228,11 +249,13 @@ void wspr(
0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1,
0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0,
0, 0};
for(i=0;i!=162;i++){
for (i = 0; i != 162; i++)
{
// j0 := bit reversed_values_smaller_than_161[i]
unsigned char j0;
p = -1;
for(k=0;p!=i;k++){
for (k = 0; p != i; k++)
{
for (j = 0; j != 8; j++) // j0:=bit_reverse(k)
j0 = ((k >> j) & 1) | (j0 << 1);
if (j0 < 162)
@ -244,20 +267,23 @@ void wspr(
// Wait for the system clock's minute to reach one second past 'minute'
void wait_every(
int minute
) {
int minute)
{
time_t t;
struct tm *ptm;
for(;;){
for (;;)
{
time(&t);
ptm = gmtime(&t);
if((ptm->tm_min % minute) == 0 && ptm->tm_sec == 0) break;
if ((ptm->tm_min % minute) == 0 && ptm->tm_sec == 0)
break;
usleep(1000);
}
usleep(1000000); // wait another second
}
void print_usage() {
void print_usage()
{
std::cout << "Usage:" << std::endl;
std::cout << " wspr [options] callsign locator tx_pwr_dBm f1 <f2> <f3> ..." << std::endl;
std::cout << " OR" << std::endl;
@ -313,8 +339,8 @@ void parse_commandline(
double &test_tone,
bool &no_delay,
mode_type &mode,
int & terminate
) {
int &terminate)
{
// Default values
ppm = 0;
self_cal = true;
@ -335,10 +361,10 @@ void parse_commandline(
{"offset", no_argument, 0, 'o'},
{"test-tone", required_argument, 0, 't'},
{"no-delay", no_argument, 0, 'n'},
{0, 0, 0, 0}
};
{0, 0, 0, 0}};
while (true) {
while (true)
{
/* getopt_long stores the option index here. */
int option_index = 0;
int c = getopt_long(argc, argv, "hp:sfrx:ot:n",
@ -346,7 +372,8 @@ void parse_commandline(
if (c == -1)
break;
switch (c) {
switch (c)
{
char *endp;
case 0:
// Code should only get here if a long option was given a non-null
@ -360,7 +387,8 @@ void parse_commandline(
break;
case 'p':
ppm = strtod(optarg, &endp);
if ((optarg==endp)||(*endp!='\0')) {
if ((optarg == endp) || (*endp != '\0'))
{
std::cerr << "Error: could not parse ppm value" << std::endl;
ABORT(-1);
}
@ -376,11 +404,13 @@ void parse_commandline(
break;
case 'x':
terminate = strtol(optarg, &endp, 10);
if ((optarg==endp)||(*endp!='\0')) {
if ((optarg == endp) || (*endp != '\0'))
{
std::cerr << "Error: could not parse termination argument" << std::endl;
ABORT(-1);
}
if (terminate<1) {
if (terminate < 1)
{
std::cerr << "Error: termination parameter must be >= 1" << std::endl;
ABORT(-1);
}
@ -391,7 +421,8 @@ void parse_commandline(
case 't':
test_tone = strtod(optarg, &endp);
mode = TONE;
if ((optarg==endp)||(*endp!='\0')) {
if ((optarg == endp) || (*endp != '\0'))
{
std::cerr << "Error: could not parse test tone frequency" << std::endl;
ABORT(-1);
}
@ -405,24 +436,27 @@ void parse_commandline(
default:
ABORT(-1);
}
}
// Parse the non-option parameters
unsigned int n_free_args = 0;
while (optind<argc) {
while (optind < argc)
{
// Check for callsign, locator, tx_power
if (n_free_args==0) {
if (n_free_args == 0)
{
callsign = argv[optind++];
n_free_args++;
continue;
}
if (n_free_args==1) {
if (n_free_args == 1)
{
locator = argv[optind++];
n_free_args++;
continue;
}
if (n_free_args==2) {
if (n_free_args == 2)
{
tx_power = argv[optind++];
n_free_args++;
continue;
@ -430,49 +464,89 @@ void parse_commandline(
// Must be a frequency
// First see if it is a string.
double parsed_freq;
if (!strcasecmp(argv[optind],"LF")) {
if (!strcasecmp(argv[optind], "LF"))
{
parsed_freq = 137500.0;
} else if (!strcasecmp(argv[optind],"LF-15")) {
}
else if (!strcasecmp(argv[optind], "LF-15"))
{
parsed_freq = 137612.5;
} else if (!strcasecmp(argv[optind],"MF")) {
}
else if (!strcasecmp(argv[optind], "MF"))
{
parsed_freq = 475700.0;
} else if (!strcasecmp(argv[optind],"MF-15")) {
}
else if (!strcasecmp(argv[optind], "MF-15"))
{
parsed_freq = 475812.5;
} else if (!strcasecmp(argv[optind],"160m")) {
}
else if (!strcasecmp(argv[optind], "160m"))
{
parsed_freq = 1838100.0;
} else if (!strcasecmp(argv[optind],"160m-15")) {
}
else if (!strcasecmp(argv[optind], "160m-15"))
{
parsed_freq = 1838212.5;
} else if (!strcasecmp(argv[optind],"80m")) {
}
else if (!strcasecmp(argv[optind], "80m"))
{
parsed_freq = 3594100.0;
} else if (!strcasecmp(argv[optind],"60m")) {
}
else if (!strcasecmp(argv[optind], "60m"))
{
parsed_freq = 5288700.0;
} else if (!strcasecmp(argv[optind],"40m")) {
}
else if (!strcasecmp(argv[optind], "40m"))
{
parsed_freq = 7040100.0;
} else if (!strcasecmp(argv[optind],"30m")) {
}
else if (!strcasecmp(argv[optind], "30m"))
{
parsed_freq = 10140200.0;
} else if (!strcasecmp(argv[optind],"20m")) {
}
else if (!strcasecmp(argv[optind], "20m"))
{
parsed_freq = 14097100.0;
} else if (!strcasecmp(argv[optind],"17m")) {
}
else if (!strcasecmp(argv[optind], "17m"))
{
parsed_freq = 18106100.0;
} else if (!strcasecmp(argv[optind],"15m")) {
}
else if (!strcasecmp(argv[optind], "15m"))
{
parsed_freq = 21096100.0;
} else if (!strcasecmp(argv[optind],"12m")) {
}
else if (!strcasecmp(argv[optind], "12m"))
{
parsed_freq = 24926100.0;
} else if (!strcasecmp(argv[optind],"10m")) {
}
else if (!strcasecmp(argv[optind], "10m"))
{
parsed_freq = 28126100.0;
} else if (!strcasecmp(argv[optind],"6m")) {
}
else if (!strcasecmp(argv[optind], "6m"))
{
parsed_freq = 50294500.0;
} else if (!strcasecmp(argv[optind],"4m")) {
}
else if (!strcasecmp(argv[optind], "4m"))
{
parsed_freq = 70092500.0;
} else if (!strcasecmp(argv[optind],"2m")) {
}
else if (!strcasecmp(argv[optind], "2m"))
{
parsed_freq = 144490500.0;
} else if (!strcasecmp(argv[optind],"70cm")) {
}
else if (!strcasecmp(argv[optind], "70cm"))
{
parsed_freq = 432300500.0;
} else {
}
else
{
// Not a string. See if it can be parsed as a double.
char *endp;
parsed_freq = strtod(argv[optind], &endp);
if ((optarg==endp)||(*endp!='\0')) {
if ((optarg == endp) || (*endp != '\0'))
{
std::cerr << "Error: could not parse transmit frequency: " << argv[optind] << std::endl;
ABORT(-1);
}
@ -486,21 +560,28 @@ void parse_commandline(
transform(locator.begin(), locator.end(), locator.begin(), ::toupper);
// Check consistency among command line options.
if (ppm&&self_cal) {
if (ppm && self_cal)
{
std::cout << "Warning: ppm value is being ignored!" << std::endl;
ppm = 0.0;
}
if (mode==TONE) {
if ((callsign!="")||(locator!="")||(tx_power!="")||(center_freq_set.size()!=0)||random_offset) {
if (mode == TONE)
{
if ((callsign != "") || (locator != "") || (tx_power != "") || (center_freq_set.size() != 0) || random_offset)
{
std::cerr << "Warning: callsign, locator, etc. are ignored when generating test tone" << std::endl;
}
random_offset = 0;
if (test_tone<=0) {
if (test_tone <= 0)
{
std::cerr << "Error: test tone frequency must be positive" << std::endl;
ABORT(-1);
}
} else {
if ((callsign=="")||(locator=="")||(tx_power=="")||(center_freq_set.size()==0)) {
}
else
{
if ((callsign == "") || (locator == "") || (tx_power == "") || (center_freq_set.size() == 0))
{
std::cerr << "Error: must specify callsign, locator, dBm, and at least one frequency" << std::endl;
std::cerr << "Try: wspr --help" << std::endl;
ABORT(-1);
@ -508,44 +589,59 @@ void parse_commandline(
}
// Print a summary of the parsed options
if (mode==WSPR) {
if (mode == WSPR)
{
std::cout << "WSPR packet contents:" << std::endl;
std::cout << " Callsign: " << callsign << std::endl;
std::cout << " Locator: " << locator << std::endl;
std::cout << " Power: " << tx_power << " dBm" << std::endl;
std::cout << "Requested TX frequencies:" << std::endl;
std::stringstream temp;
for (unsigned int t=0;t<center_freq_set.size();t++) {
for (unsigned int t = 0; t < center_freq_set.size(); t++)
{
temp << std::setprecision(6) << std::fixed;
temp << " " << center_freq_set[t] / 1e6 << " MHz" << std::endl;
}
std::cout << temp.str();
temp.str("");
if (self_cal) {
if (self_cal)
{
temp << " NTP will be used to periodically calibrate the transmission frequency" << std::endl;
} else if (ppm) {
}
else if (ppm)
{
temp << " PPM value to be used for all transmissions: " << ppm << std::endl;
}
if (terminate>0) {
if (terminate > 0)
{
temp << " TX will stop after " << terminate << " transmissions." << std::endl;
} else if (repeat) {
}
else if (repeat)
{
temp << " Transmissions will continue forever until stopped with CTRL-C" << std::endl;
}
if (random_offset) {
if (random_offset)
{
temp << " A small random frequency offset will be added to all transmissions" << std::endl;
}
if (temp.str().length()) {
if (temp.str().length())
{
std::cout << "Extra options:" << std::endl;
std::cout << temp.str();
}
std::cout << std::endl;
} else {
}
else
{
std::stringstream temp;
temp << std::setprecision(6) << std::fixed << "A test tone will be generated at frequency " << test_tone / 1e6 << " MHz" << std::endl;
std::cout << temp.str();
if (self_cal) {
if (self_cal)
{
std::cout << "NTP will be used to calibrate the tone frequency" << std::endl;
} else if (ppm) {
}
else if (ppm)
{
std::cout << "PPM value to be used to generate the tone: " << ppm << std::endl;
}
std::cout << std::endl;
@ -554,8 +650,8 @@ void parse_commandline(
// Call ntp_adjtime() to obtain the latest calibration coefficient.
void update_ppm(
double & ppm
) {
double &ppm)
{
struct timex ntx;
int status;
double ppm_new;
@ -563,16 +659,21 @@ void update_ppm(
ntx.modes = 0; /* only read */
status = ntp_adjtime(&ntx);
if (status != TIME_OK) {
if (status != TIME_OK)
{
// cerr << "Error: clock not synchronized" << std::endl;
// return;
}
ppm_new = (double)ntx.freq / (double)(1 << 16); /* frequency scale */
if (abs(ppm_new)>200) {
if (abs(ppm_new) > 200)
{
std::cerr << "Warning: absolute ppm value is greater than 200 and is being ignored!" << std::endl;
} else {
if (ppm!=ppm_new) {
}
else
{
if (ppm != ppm_new)
{
std::cout << " Obtained new ppm value: " << ppm_new << std::endl;
}
ppm = ppm_new;
@ -582,7 +683,8 @@ void update_ppm(
/* Return 1 if the difference is negative, otherwise 0. */
// From StackOverflow:
// http://stackoverflow.com/questions/1468596/c-programming-calculate-elapsed-time-in-milliseconds-unix
int timeval_subtract(struct timeval *result, struct timeval *t2, struct timeval *t1) {
int timeval_subtract(struct timeval *result, struct timeval *t2, struct timeval *t1)
{
long int diff = (t2->tv_usec + 1000000 * t2->tv_sec) - (t1->tv_usec + 1000000 * t1->tv_sec);
result->tv_sec = diff / 1000000;
result->tv_usec = diff % 1000000;
@ -590,7 +692,8 @@ int timeval_subtract(struct timeval *result, struct timeval *t2, struct timeval
return (diff < 0);
}
void timeval_print(struct timeval *tv) {
void timeval_print(struct timeval *tv)
{
char buffer[30];
time_t curtime;
@ -601,25 +704,34 @@ void timeval_print(struct timeval *tv) {
printf("%s.%03ld", buffer, (tv->tv_usec + 500) / 1000);
}
// Called when exiting or when a signal is received.
void cleanup() {
if(clk!=NULL) {delete clk;clk=NULL;}
if(ngfmtest!=NULL) {delete ngfmtest;ngfmtest=NULL;}
void cleanup()
{
if (clk != NULL)
{
delete clk;
clk = NULL;
}
if (ngfmtest != NULL)
{
delete ngfmtest;
ngfmtest = NULL;
}
}
// Called when a signal is received. Automatically calls cleanup().
void cleanupAndExit(int sig) {
void cleanupAndExit(int sig)
{
std::cerr << "Exiting with error; caught signal: " << sig << std::endl;
cleanup();
ABORT(-1);
}
int main(const int argc, char * const argv[]) {
int main(const int argc, char *const argv[])
{
// catch all signals (like ctrl+c, ctrl+z, ...) to ensure DMA is disabled
for (int i = 0; i < 64; i++) {
for (int i = 0; i < 64; i++)
{
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_handler = cleanupAndExit;
@ -627,9 +739,6 @@ int main(const int argc, char * const argv[]) {
}
atexit(cleanup);
// Initialize the RNG
srand(time(NULL));
@ -660,14 +769,11 @@ int main(const int argc, char * const argv[]) {
test_tone,
no_delay,
mode,
terminate
);
terminate);
int nbands = center_freq_set.size();
if (mode==TONE) {
if (mode == TONE)
{
if (clk == NULL)
clk = new clkgpio;
clk->SetAdvancedPllMode(true);
@ -690,10 +796,12 @@ int main(const int argc, char * const argv[]) {
clk->SetCenterFrequency(test_tone, 100);
clk->enableclk(4);
clk->SetFrequency(000);
while(true) usleep(1000000);
while (true)
usleep(1000000);
// Should never get here...
} else {
}
else
{
// WSPR mode
// Create WSPR symbols
@ -713,19 +821,21 @@ int main(const int argc, char * const argv[]) {
std::cout << "Ready to transmit (setup complete)..." << std::endl;
int band = 0;
int n_tx = 0;
for(;;) {
for (;;)
{
// Calculate WSPR parameters for this transmission
double center_freq_desired;
center_freq_desired = center_freq_set[band];
bool wspr15 =
(center_freq_desired > 137600 && center_freq_desired < 137625) || \
(center_freq_desired > 475800 && center_freq_desired < 475825) || \
(center_freq_desired > 137600 && center_freq_desired < 137625) ||
(center_freq_desired > 475800 && center_freq_desired < 475825) ||
(center_freq_desired > 1838200 && center_freq_desired < 1838225);
double wspr_symtime = (wspr15) ? 8.0 * WSPR_SYMTIME : WSPR_SYMTIME;
double tone_spacing = 1.0 / wspr_symtime;
// Add random offset
if ((center_freq_desired!=0)&&random_offset) {
if ((center_freq_desired != 0) && random_offset)
{
center_freq_desired += (2.0 * rand() / ((double)RAND_MAX + 1.0) - 1.0) * (wspr15 ? WSPR15_RAND_OFFSET : WSPR_RAND_OFFSET);
}
@ -736,31 +846,38 @@ int main(const int argc, char * const argv[]) {
std::cout << temp.str();
// Wait for WSPR transmission window to arrive.
if (no_delay) {
if (no_delay)
{
std::cout << " Transmitting immediately (not waiting for WSPR window)" << std::endl;
} else {
}
else
{
std::cout << " Waiting for next WSPR transmission window..." << std::endl;
wait_every((wspr15) ? 15 : 2);
}
// Update crystal calibration information
if (self_cal) {
if (self_cal)
{
update_ppm(ppm);
}
// Create the DMA table for this center frequency
std::vector<double> dma_table_freq;
double center_freq_actual;
if (center_freq_desired) {
if (center_freq_desired)
{
center_freq_actual = center_freq_desired;
} else {
}
else
{
center_freq_actual = center_freq_desired;
}
// Send the message!
// std::cout << "TX started!" << std::endl;
if (center_freq_actual){
if (center_freq_actual)
{
// Print a status message right before transmission begins.
struct timeval tvBegin, tvEnd, tvDiff;
gettimeofday(&tvBegin, NULL);
@ -776,13 +893,11 @@ int main(const int argc, char * const argv[]) {
int FifoSize = 40000;
bool usePWMSample = false;
static float *FreqPWM = NULL;
if(ngfmtest==NULL)
{
//New modulator and tx on
ngfmtest = new ngfmdmasync(center_freq_actual, SR, 14, FifoSize, true);
FreqPWM = (float *)malloc(Upsample * sizeof(float));
}
else
ngfmtest->enableclk(4);
double FreqResolution = ngfmtest->GetFrequencyResolution();
double RealFreq = ngfmtest->GetRealFrequency(0);
@ -790,7 +905,6 @@ int main(const int argc, char * const argv[]) {
{
fprintf(stderr, "Freq resolution=%f - Tone spacing =%f Erreur tuning=%f\n", FreqResolution, tone_spacing, RealFreq);
usePWMSample = true;
}
for (int i = 0; i < 162; i++)
@ -817,41 +931,42 @@ int main(const int argc, char * const argv[]) {
{
FreqPWM[j] = tone_freq;
}
}
ngfmtest->SetFrequencySamples(FreqPWM, Upsample);
}
n_tx++;
// Turn transmitter off
ngfmtest->disableclk(4);
delete ngfmtest;
ngfmtest = NULL;
free(FreqPWM);
// End timestamp
gettimeofday(&tvEnd, NULL);
std::cout << " TX ended at: ";
timeval_print(&tvEnd);
timeval_subtract(&tvDiff, &tvEnd, &tvBegin);
printf(" (%ld.%03ld s)\n", tvDiff.tv_sec, (tvDiff.tv_usec + 500) / 1000);
} else {
}
else
{
std::cout << " Skipping transmission" << std::endl;
usleep(1000000);
}
// Advance to next band
band = (band + 1) % nbands;
if ((band==0)&&!repeat) {
if ((band == 0) && !repeat)
{
break;
}
if ((terminate>0)&&(n_tx>=terminate)) {
if ((terminate > 0) && (n_tx >= terminate))
{
break;
}
}
}
return 0;
}