diff --git a/rtlsdr_wsprd.c b/rtlsdr_wsprd.c index db305e6..dd7ae71 100644 --- a/rtlsdr_wsprd.c +++ b/rtlsdr_wsprd.c @@ -37,22 +37,16 @@ #include #include #include -#include +#include // #include #include #include -#include #include -#include "rtlsdr_wsprd.h" -#include "wsprd.h" - -/* TODO - - multispot report in one post - - post zero spot if nothing found - - fft & snr sort fix -*/ +#include "./rtlsdr_wsprd.h" +#include "./wsprd.h" +/* Sampling definition for RTL devices */ #define SIGNAL_LENGHT 116 #define SIGNAL_SAMPLE_RATE 375 #define SAMPLING_RATE 2400000 @@ -89,20 +83,9 @@ struct dongle_state dongle; /* Callback for each buffer received */ -static void rtlsdr_callback(unsigned char *samples, uint32_t samples_count, void *ctx) { - int8_t *sigIn = (int8_t*) samples; - uint32_t sigLenght = samples_count; - - static uint32_t decimationIndex=0; - - /* CIC buffers */ - static int32_t Ix1,Ix2,Qx1,Qx2; - static int32_t Iy1,It1y,It1z,Qy1,Qt1y,Qt1z; - static int32_t Iy2,It2y,It2z,Qy2,Qt2y,Qt2z; - - /* FIR compensation filter buffers */ - static float firI[32], firQ[32]; - +static void rtlsdr_callback(unsigned char *samples, + uint32_t samples_count, + void *ctx) { /* FIR compensation filter coefs Using : Octave/MATLAB code for generating compensation FIR coefficients URL : https://github.com/WestCoastDSP/CIC_Octave_Matlab @@ -110,20 +93,33 @@ static void rtlsdr_callback(unsigned char *samples, uint32_t samples_count, void const static float zCoef[33] = { -0.0027772683, -0.0005058826, 0.0049745750, -0.0034059318, -0.0077557814, 0.0139375423, 0.0039896935, -0.0299394142, - 0.0162250643, 0.0405130860, -0.0580746013, -0.0272104968, - 0.1183705475, -0.0306029022, -0.2011241667, 0.1615898423, - 0.5000000000, - 0.1615898423, -0.2011241667, -0.0306029022, 0.1183705475, + 0.0162250643, 0.0405130860, -0.0580746013, -0.0272104968, + 0.1183705475, -0.0306029022, -0.2011241667, 0.1615898423, + 0.5000000000, + 0.1615898423, -0.2011241667, -0.0306029022, 0.1183705475, -0.0272104968, -0.0580746013, 0.0405130860, 0.0162250643, -0.0299394142, 0.0039896935, 0.0139375423, -0.0077557814, -0.0034059318, 0.0049745750, -0.0005058826, -0.0027772683 }; - float Isum,Qsum; + + int8_t *sigIn = (int8_t*)samples; + uint32_t sigLenght = samples_count; + static uint32_t decimationIndex = 0; + + /* CIC buffers */ + static int32_t Ix1, Ix2, Qx1, Qx2; + static int32_t Iy1, It1y, It1z, Qy1, Qt1y, Qt1z; + static int32_t Iy2, It2y, It2z, Qy2, Qt2y, Qt2z; + + /* FIR compensation filter buffers */ + static float firI[32], firQ[32]; + + float Isum, Qsum; /* Convert unsigned to signed */ - for(uint32_t i=0; itm_year + 1900, gtm->tm_mon + 1, gtm->tm_mday, gtm->tm_hour, gtm->tm_min, gtm->tm_sec, - dec_results[i].snr, dec_results[i].dt, dec_results[i].freq, - (int)dec_results[i].drift, dec_results[i].call, dec_results[i].loc, dec_results[i].pwr); + gtm->tm_year + 1900, + gtm->tm_mon + 1, + gtm->tm_mday, + gtm->tm_hour, + gtm->tm_min, + gtm->tm_sec, + dec_results[i].snr, + dec_results[i].dt, + dec_results[i].freq, + (int)dec_results[i].drift, + dec_results[i].call, + dec_results[i].loc, + dec_results[i].pwr); curl = curl_easy_init(); - if(curl) { + if (curl) { curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_NOBODY, 1); res = curl_easy_perform(curl); - if(res != CURLE_OK) - fprintf(stderr, "curl_easy_perform() failed: %s\n",curl_easy_strerror(res)); + if (res != CURLE_OK) + fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); curl_easy_cleanup(curl); } } if (n_results == 0) { - - time_t rawtime; - time ( &rawtime ); - struct tm *gtm = gmtime(&rawtime); - - printf("No spot %04d-%02d-%02d %02d:%02dz\n", - gtm->tm_year + 1900, gtm->tm_mon + 1, gtm->tm_mday, gtm->tm_hour, gtm->tm_min); - } + printf("No spot %04d-%02d-%02d %02d:%02dz\n", + gtm->tm_year + 1900, + gtm->tm_mon + 1, + gtm->tm_mday, + gtm->tm_hour, + gtm->tm_min); + } } static void *wsprDecoder(void *arg) { /* WSPR decoder use buffers of 45000 samples (hardcoded) (120 sec max @ 375sps = 45000 samples) + Real = 375 * 116 = 43500 + FIXME with SIGNAL_LENGHT * SIGNAL_SAMPLE_RATE ?? */ static float iSamples[45000]= {0}; static float qSamples[45000]= {0}; static uint32_t samples_len; - int32_t n_results=0; + int32_t n_results = 0; while (!rx_state.exit_flag) { pthread_mutex_lock(&dec.ready_mutex); pthread_cond_wait(&dec.ready_cond, &dec.ready_mutex); pthread_mutex_unlock(&dec.ready_mutex); - if(rx_state.exit_flag) // Abord case, final sig + if (rx_state.exit_flag) + /* Abord case, final sig */ break; /* Lock the buffer access and make a local copy */ @@ -309,12 +324,11 @@ static void *wsprDecoder(void *arg) { memcpy(dec_options.date, rx_options.date, sizeof(rx_options.date)); memcpy(dec_options.uttime, rx_options.uttime, sizeof(rx_options.uttime)); - /* DEBUG -- Save samples */ + /* DEBUG -- Save samples HERE */ /* Search & decode the signal */ wspr_decode(iSamples, qSamples, samples_len, dec_options, dec_results, &n_results); postSpots(n_results); - } pthread_exit(NULL); } @@ -328,19 +342,20 @@ double atofs(char *s) { len = strlen(s); last = s[len-1]; s[len-1] = '\0'; + switch (last) { - case 'g': - case 'G': - suff *= 1e3; - case 'm': - case 'M': - suff *= 1e3; - case 'k': - case 'K': - suff *= 1e3; - suff *= atof(s); - s[len-1] = last; - return suff; + case 'g': + case 'G': + suff *= 1e3; + case 'm': + case 'M': + suff *= 1e3; + case 'k': + case 'K': + suff *= 1e3; + suff *= atof(s); + s[len-1] = last; + return suff; } s[len-1] = last; return atof(s); @@ -352,12 +367,12 @@ int32_t parse_u64(char* s, uint64_t* const value) { char* s_end; uint64_t u64_value; - if( strlen(s) > 2 ) { - if( s[0] == '0' ) { - if( (s[1] == 'x') || (s[1] == 'X') ) { + if (strlen(s) > 2) { + if (s[0] == '0') { + if ( (s[1] == 'x') || (s[1] == 'X') ) { base = 16; s += 2; - } else if( (s[1] == 'b') || (s[1] == 'B') ) { + } else if ( (s[1] == 'b') || (s[1] == 'B') ) { base = 2; s += 2; } @@ -366,7 +381,7 @@ int32_t parse_u64(char* s, uint64_t* const value) { s_end = s; u64_value = strtoull(s, &s_end, base); - if( (s != s_end) && (*s_end == 0) ) { + if ( (s != s_end) && (*s_end == 0) ) { *value = u64_value; return 1; } else { @@ -378,7 +393,7 @@ int32_t parse_u64(char* s, uint64_t* const value) { /* Reset flow control variable & decimation variables */ void initSampleStorage() { rx_state.decode_flag = false; - rx_state.iqIndex=0; + rx_state.iqIndex = 0; } @@ -431,7 +446,7 @@ int32_t readfile(float *iSamples, float *qSamples, char *filename) { return 1; } - for(int32_t i=0; i 49) rx_options.gain = 49; rx_options.gain *= 10; break; - case 'a': // Auto gain + case 'a': // Auto gain rx_options.autogain = atoi(optarg); if (rx_options.autogain < 0) rx_options.autogain = 0; if (rx_options.autogain > 1) rx_options.autogain = 1; break; - case 'o': // Fine frequency correction + case 'o': // Fine frequency correction rx_options.shift = atoi(optarg); break; case 'p': rx_options.ppm = atoi(optarg); break; - case 'u': // Upconverter frequency + case 'u': // Upconverter frequency rx_options.upconverter = (uint32_t)atofs(optarg); break; - case 'd': // Direct Sampling + case 'd': // Direct Sampling rx_options.directsampling = (uint32_t)atofs(optarg); break; - case 'n': // Stop after n iterations + case 'n': // Stop after n iterations rx_options.maxloop = (uint32_t)atofs(optarg); break; - case 'i': // Select the device to use + case 'i': // Select the device to use rx_options.device = (uint32_t)atofs(optarg); break; - case 'H': // Decoder option, use a hastable + case 'H': // Decoder option, use a hastable dec_options.usehashtable = 1; break; - case 'Q': // Decoder option, faster + case 'Q': // Decoder option, faster dec_options.quickmode = 1; break; - case 'S': // Decoder option, single pass mode (same as original wsprd) + case 'S': // Decoder option, single pass mode (same as original wsprd) dec_options.subtraction = 0; dec_options.npasses = 1; break; @@ -665,7 +683,7 @@ int main(int argc, char** argv) { fprintf(stderr, "Found %d device(s):\n", rtl_count); - for (uint32_t i=0; itm_year + 1900, gtm->tm_mon + 1, gtm->tm_mday, gtm->tm_hour, gtm->tm_min); printf(" Callsign : %s\n", dec_options.rcall); printf(" Locator : %s\n", dec_options.rloc); printf(" Dial freq. : %d Hz\n", rx_options.dialfreq); printf(" Real freq. : %d Hz\n", rx_options.realfreq); printf(" PPM factor : %d\n", rx_options.ppm); - if(rx_options.autogain) + if (rx_options.autogain) printf(" Auto gain : enable\n"); else printf(" Gain : %d dB\n", rx_options.gain/10); @@ -770,7 +790,6 @@ int main(int argc, char** argv) { uint32_t uwait = 120000000 - usec; printf("Wait for time sync (start in %d sec)\n\n", uwait/1000000); printf(" Date Time(z) SNR DT Freq Dr Call Loc Pwr\n"); - /* Spot : 2021-03-03 10:00:00 -10.96 0.09 7.040130 0 DL4TOM JN59 33 */ /* Prepare a low priority param for the decoder thread */ struct sched_param param; @@ -798,18 +817,18 @@ int main(int argc, char** argv) { usec = sec * 1000000 + lTime.tv_usec; uwait = 120000000 - usec + 10000; // Adding 10ms, to be sure to reach this next minute usleep(uwait); - //printf("SYNC! RX started\n"); /* Use the Store the date at the begin of the frame */ - time ( &rawtime ); + time(&rawtime); gtm = gmtime(&rawtime); - sprintf(rx_options.date,"%02d%02d%02d", gtm->tm_year - 100, gtm->tm_mon + 1, gtm->tm_mday); - sprintf(rx_options.uttime,"%02d%02d", gtm->tm_hour, gtm->tm_min); + // FIXME: Complier warning about mixing int & date + snprintf(rx_options.date, sizeof(rx_options.date), "%02d%02d%02d", gtm->tm_year - 100, gtm->tm_mon + 1, gtm->tm_mday); + snprintf(rx_options.uttime, sizeof(rx_options.uttime), "%02d%02d", gtm->tm_hour, gtm->tm_min); /* Start to store the samples */ initSampleStorage(); - while( (rx_state.exit_flag == false) && + while ( (rx_state.exit_flag == false) && (rx_state.iqIndex < (SIGNAL_LENGHT * SIGNAL_SAMPLE_RATE) ) ) { usleep(250000); } diff --git a/rtlsdr_wsprd.h b/rtlsdr_wsprd.h index 0f28e86..91c7427 100644 --- a/rtlsdr_wsprd.h +++ b/rtlsdr_wsprd.h @@ -33,9 +33,9 @@ #ifndef bool - typedef uint32_t bool; - #define true 1 - #define false 0 + typedef uint32_t bool; + #define true 1 + #define false 0 #endif @@ -81,5 +81,4 @@ void initrx_options(); void sigint_callback_handler(int signum); void usage(void); int32_t readfile(float *iSamples, float *qSamples, char *filename); -int32_t writefile(float *iSamples, float *qSamples, char *filename, - uint32_t type, double freq); \ No newline at end of file +int32_t writefile(float *iSamples, float *qSamples, char *filename, uint32_t type, double freq);