Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rffft params from filename #52

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .github/workflows/github-actions.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
name: GitHub Actions
run-name: Building and testing STRF
on: [push]
jobs:
GitHub-Actions:
runs-on: ubuntu-latest
steps:
- run: sudo apt install --no-install-recommends make gcc pgplot5 gfortran libpng-dev libx11-dev libgsl-dev libfftw3-dev libcmocka-dev libcmocka0
- name: Check out repository code
uses: actions/checkout@v3
- run: cd ${{ github.workspace }}
- run: make
- run: make tests
14 changes: 10 additions & 4 deletions Makefile.linux
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,19 @@ rftrack: rftrack.o rfio.o rftime.o rftrace.o sgdp4.o satutl.o deep.o ferror.o
rfplot: rfplot.o rftime.o rfio.o rftrace.o sgdp4.o satutl.o deep.o ferror.o rftles.o
gfortran -o rfplot rfplot.o rftime.o rfio.o rftrace.o sgdp4.o satutl.o deep.o ferror.o rftles.o $(LFLAGS)

rffft: rffft.o rftime.o
$(CC) -o rffft rffft.o rftime.o -lfftw3f -lm
rffft: rffft.o rffft_internal.o rftime.o
$(CC) -o rffft rffft.o rffft_internal.o rftime.o -lfftw3f -lm

.PHONY: clean install uninstall
tests/tests: tests/tests.o tests/tests_rffft_internal.o tests/tests_rftles.o rffft_internal.o rftles.o satutl.o ferror.o
$(CC) -Wall -o $@ $^ -lcmocka -lm

tests: tests/tests
./tests/tests

.PHONY: clean install uninstall tests

clean:
rm -f *.o
rm -f *.o tests/*.o
rm -f *~

install:
Expand Down
14 changes: 10 additions & 4 deletions Makefile.osx
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,19 @@ rftrack: rftrack.o rfio.o rftime.o rftrace.o sgdp4.o satutl.o deep.o ferror.o
rfplot: rfplot.o rftime.o rfio.o rftrace.o sgdp4.o satutl.o deep.o ferror.o versafit.o dsmin.o simplex.o rftles.o
$(CC) -o rfplot rfplot.o rftime.o rfio.o rftrace.o sgdp4.o satutl.o deep.o ferror.o versafit.o dsmin.o simplex.o rftles.o $(LFLAGS)

rffft: rffft.o rftime.o
$(CC) -o rffft rffft.o rftime.o -lfftw3f -lm $(LFLAGS)
rffft: rffft.o rffft_internal.o rftime.o
$(CC) -o rffft rffft.o rffft_internal.o rftime.o -lfftw3f -lm $(LFLAGS)

.PHONY: clean install uninstall
tests/tests: tests/tests.o tests/tests_rffft_internal.o tests/tests_rftles.o rffft_internal.o rftles.o satutl.o ferror.o
$(CC) -Wall -o $@ $^ -lcmocka -lm

tests: tests/tests
./tests/tests

.PHONY: clean install uninstall tests

clean:
rm -f *.o
rm -f *.o tests/*.o
rm -f *~

install:
Expand Down
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ Install
* Clone repository: `git clone https://github.com/cbassa/strf.git`
* Compile: `cd strf; make`
* Install (in `/usr/local`): `sudo make install`
* To build and run the unit tests, also install the cmocka dependencies: `sudo apt install libcmocka-dev libcmocka0` and then run `make tests`

Configure
---------
Expand Down Expand Up @@ -80,4 +81,8 @@ With I/Q recordings obtained from Gqrx:

**Gqrx** records complex samples into `raw` files. The filename contains date, time, center frequency and samplerate separated by underscores. Replace `YYYYMMDD` and `HHMMSS` by your actual time and respectively. Pay attention to insert an uppercase `T` between date and time in the time stamp parameter of the `rffft` command.

The output spectrograms can be viewed and analysed using `rfplot`.
Alternatively, with I/Q recordings from GQRX and SatDump, the `-P` option can be used to automatically extract the timestamp, format, frequency and samplerate from the filename:

./rffft -P -i gqrx_YYYYMMDD_HHMMSS_97400000_2000000_fc.raw

The output spectrograms can be viewed and analysed using `rfplot`.
14 changes: 10 additions & 4 deletions makefile
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,19 @@ rftrack: rftrack.o rfio.o rftime.o rftrace.o sgdp4.o satutl.o deep.o ferror.o
rfplot: rfplot.o rftime.o rfio.o rftrace.o sgdp4.o satutl.o deep.o ferror.o versafit.o dsmin.o simplex.o rftles.o
gfortran -o rfplot rfplot.o rftime.o rfio.o rftrace.o sgdp4.o satutl.o deep.o ferror.o versafit.o dsmin.o simplex.o rftles.o $(LFLAGS)

rffft: rffft.o rftime.o
$(CC) -o rffft rffft.o rftime.o -lfftw3f -lm
rffft: rffft.o rffft_internal.o rftime.o
$(CC) -o rffft rffft.o rffft_internal.o rftime.o -lfftw3f -lm

.PHONY: clean install uninstall
tests/tests: tests/tests.o tests/tests_rffft_internal.o tests/tests_rftles.o rffft_internal.o rftles.o satutl.o ferror.o
$(CC) -Wall -o $@ $^ -lcmocka -lm

tests: tests/tests
./tests/tests

.PHONY: clean install uninstall tests

clean:
rm -f *.o
rm -f *.o tests/*.o
rm -f *~

install:
Expand Down
22 changes: 19 additions & 3 deletions rffft.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
#include <sys/time.h>
#include "rftime.h"

#include "rffft_internal.h"

void usage(void)
{
printf("rffft: FFT RF observations\n\n");
Expand All @@ -27,6 +29,7 @@ void usage(void)
printf("-I Invert frequencies\n");
printf("-b Digitize output to bytes [off]\n");
printf("-q Quiet mode, no output [off]\n");
printf("-P Parse frequency, samplerate, format and start time from filename\n");
printf("-h This help\n");

return;
Expand All @@ -49,10 +52,11 @@ int main(int argc,char *argv[])
struct timeval start,end;
char tbuf[30],nfd[32],header[256]="";
int sign=1;
int parse_params_from_filename = 0;

// Read arguments
if (argc>1) {
while ((arg=getopt(argc,argv,"i:f:s:c:t:p:n:hm:F:T:bqR:o:IS:"))!=-1) {
while ((arg=getopt(argc,argv,"i:f:s:c:t:p:n:hm:F:T:bqR:o:IS:P"))!=-1) {
switch(arg) {

case 'i':
Expand Down Expand Up @@ -125,7 +129,12 @@ int main(int argc,char *argv[])
case 'I':
sign=-1;
break;


case 'P':
parse_params_from_filename = 1;
realtime=0;
break;

case 'h':
usage();
return 0;
Expand All @@ -140,9 +149,16 @@ int main(int argc,char *argv[])
return 0;
}

if (parse_params_from_filename != 0) {
if (rffft_params_from_filename(infname, &samp_rate, &freq, &informat, nfd) != 0) {
fprintf(stderr, "Error parsing parameters from filename\n");
exit(-1);
};
}

// Ensure integer number of spectra per subintegration
tint=ceil(fchan*tint)/fchan;

// Number of channels
nchan=(int) (samp_rate/fchan);

Expand Down
163 changes: 163 additions & 0 deletions rffft_internal.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
#include "rffft_internal.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libgen.h>


// Filename formats:
// - SatDump
// - 2023-08-05_08-02-00_16000000SPS_2274000000Hz.s8
// - 2023-08-05_18-02-45-534_16000000SPS_2284000000Hz.s16
// - 2023-08-05_18-02-45-1691258565.534000_16000000SPS_2284000000Hz.f32
// s8: char, s16 short int, f32 float.
// SatDump also supports .wav and compressed versions of s8/s16/f32 with .ziq
// extension. Those are not yet supported
// timestamp can have an added milliseconds field, configurable. This feature
// was broken during some time so files with this convention still exists.
// - GQRX:
// - gqrx_20230806_151838_428000000_200000_fc.raw
// format always float32
int rffft_params_from_filename(char * filename, double * samplerate, double * frequency, char * format, char * starttime) {
// Temp vars to hold parsed values
int p_year, p_month, p_day, p_hours, p_minutes, p_seconds, p_fractal_seconds;
int p_dummy_int;
double p_samplerate, p_frequency;
char p_format[16];
char p_dummy_string[128];
int parsed_tokens;

char * base_filename = basename(filename);

// Broken SatDump string with milliseconds activated
parsed_tokens = sscanf(
base_filename,
"%04d-%02d-%02d_%02d-%02d-%02d-%d.%06d_%lfSPS_%lfHz.%s",
&p_year,
&p_month,
&p_day,
&p_hours,
&p_minutes,
&p_seconds,
&p_dummy_int,
&p_fractal_seconds,
&p_samplerate,
&p_frequency,
p_format);

if (parsed_tokens == 11) {
*samplerate = p_samplerate;
*frequency = p_frequency;

if ((strlen(p_format) == 2) && (strncmp("s8", p_format, 2) == 0)) {
*format = 'c';
} else if ((strlen(p_format) == 3) && (strncmp("s16", p_format, 3) == 0)) {
*format = 'i';
} else if ((strlen(p_format) == 3) && (strncmp("f32", p_format, 3) == 0)) {
*format = 'f';
} else {
printf("Unsupported SatDump format %s\n", p_format);
return -1;
}

snprintf(starttime, 32, "%04d-%02d-%02dT%02d:%02d:%02d.%03d", p_year, p_month, p_day, p_hours, p_minutes, p_seconds, p_fractal_seconds / 1000);

return 0;
}

// SatDump string with milliseconds activated
parsed_tokens = sscanf(
base_filename,
"%04d-%02d-%02d_%02d-%02d-%02d-%03d_%lfSPS_%lfHz.%s",
&p_year,
&p_month,
&p_day,
&p_hours,
&p_minutes,
&p_seconds,
&p_fractal_seconds,
&p_samplerate,
&p_frequency,
p_format);

if (parsed_tokens == 10) {
*samplerate = p_samplerate;
*frequency = p_frequency;

if ((strlen(p_format) == 2) && (strncmp("s8", p_format, 2) == 0)) {
*format = 'c';
} else if ((strlen(p_format) == 3) && (strncmp("s16", p_format, 3) == 0)) {
*format = 'i';
} else if ((strlen(p_format) == 3) && (strncmp("f32", p_format, 3) == 0)) {
*format = 'f';
} else {
printf("Unsupported SatDump format %s\n", p_format);
return -1;
}

snprintf(starttime, 32, "%04d-%02d-%02dT%02d:%02d:%02d.%03d", p_year, p_month, p_day, p_hours, p_minutes, p_seconds, p_fractal_seconds);

return 0;
}

// SatDump string without milliseconds activated
parsed_tokens = sscanf(
base_filename,
"%04d-%02d-%02d_%02d-%02d-%02d_%lfSPS_%lfHz.%s",
&p_year,
&p_month,
&p_day,
&p_hours,
&p_minutes,
&p_seconds,
&p_samplerate,
&p_frequency,
p_format);

if (parsed_tokens == 9) {
*samplerate = p_samplerate;
*frequency = p_frequency;

if ((strlen(p_format) == 2) && (strncmp("s8", p_format, 2) == 0)) {
*format = 'c';
} else if ((strlen(p_format) == 3) && (strncmp("s16", p_format, 3) == 0)) {
*format = 'i';
} else if ((strlen(p_format) == 3) && (strncmp("f32", p_format, 3) == 0)) {
*format = 'f';
} else {
printf("Unsupported SatDump format %s\n", p_format);
return -1;
}

snprintf(starttime, 32, "%04d-%02d-%02dT%02d:%02d:%02d", p_year, p_month, p_day, p_hours, p_minutes, p_seconds);

return 0;
}

// GQRX
parsed_tokens = sscanf(
base_filename,
"gqrx_%04d%02d%02d_%02d%02d%02d_%lf_%lf_%s.raw",
&p_year,
&p_month,
&p_day,
&p_hours,
&p_minutes,
&p_seconds,
&p_frequency,
&p_samplerate,
p_dummy_string);

if (parsed_tokens == 9) {
*samplerate = p_samplerate;
*frequency = p_frequency;
*format = 'f';

snprintf(starttime, 32, "%04d-%02d-%02dT%02d:%02d:%02d", p_year, p_month, p_day, p_hours, p_minutes, p_seconds);

return 0;
}

return -1;
}
23 changes: 23 additions & 0 deletions rffft_internal.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#ifndef _RFFFT_INTERNAL_H
#define _RFFFT_INTERNAL_H

#include "sgdp4h.h"

#ifdef __cplusplus
extern "C" {
#endif

// input:
// filename: filename string to parse
// output:
// samplerate: parsed samplerate
// frequency: parsed frequency
// format: parsed sample format: char: 'c', int: 'i', float: 'f'
// starttime: parsed start time string formatted YYYY-MM-DDTHH:MM:SS.sss
int rffft_params_from_filename(char * filename, double * samplerate, double * frequency, char * format, char * starttime);

#ifdef __cplusplus
}
#endif

#endif /* _RFFFT_INTERNAL_H */
10 changes: 9 additions & 1 deletion rftles.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,14 @@ tles_t load_tles(char *tlefile) {
}
}

// Don't allocate anything if no entry found in file
if (num_elements == 0) {
fclose(file);
free(line);

return tles;
}

tles.orbits = (orbit_t *)calloc(num_elements, sizeof(orbit_t));

// Rewind and parse file
Expand All @@ -72,7 +80,7 @@ void free_tles(tles_t *tles) {
}

orbit_t *get_orbit_by_index(tles_t *tles, long index) {
if (tles) {
if (tles && (index < tles->number_of_elements)) {
return &(tles->orbits[index]);
}

Expand Down
Loading