Added hackrf_transfer option -w to received file with Wav/RIFF Header and automatic name compatible with SDR#
This commit is contained in:
@ -27,6 +27,7 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
@ -44,6 +45,7 @@
|
|||||||
|
|
||||||
#define FREQ_ONE_MHZ (1000000)
|
#define FREQ_ONE_MHZ (1000000)
|
||||||
|
|
||||||
|
#define DEFAULT_FREQ_HZ (900000000ull) /* 900MHz */
|
||||||
#define FREQ_MIN_HZ (30000000ull) /* 30MHz */
|
#define FREQ_MIN_HZ (30000000ull) /* 30MHz */
|
||||||
#define FREQ_MAX_HZ (6000000000ull) /* 6000MHz */
|
#define FREQ_MAX_HZ (6000000000ull) /* 6000MHz */
|
||||||
|
|
||||||
@ -60,6 +62,68 @@
|
|||||||
#define sleep(a) Sleep( (a*1000) )
|
#define sleep(a) Sleep( (a*1000) )
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* WAVE or RIFF WAVE file format containing IQ 2x8bits data for HackRF compatible with SDR# Wav IQ file */
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char groupID[4]; /* "RIFF" */
|
||||||
|
uint32_t size; /* File size + 8bytes */
|
||||||
|
char riffType[4]; /* WAVE */
|
||||||
|
} t_WAVRIFF_hdr;
|
||||||
|
|
||||||
|
#define FormatID "fmt " /* chunkID for Format Chunk. NOTE: There is a space at the end of this ID. */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char chunkID[4]; /* "fmt " */
|
||||||
|
uint32_t chunkSize; /* 16 fixed */
|
||||||
|
|
||||||
|
uint16_t wFormatTag; /* 1 fixed */
|
||||||
|
uint16_t wChannels; /* 2 fixed */
|
||||||
|
uint32_t dwSamplesPerSec; /* Freq Hz sampling */
|
||||||
|
uint32_t dwAvgBytesPerSec; /* Freq Hz sampling x 2 */
|
||||||
|
uint16_t wBlockAlign; /* 2 fixed */
|
||||||
|
uint16_t wBitsPerSample; /* 8 fixed */
|
||||||
|
} t_FormatChunk;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char chunkID[4]; /* "data" */
|
||||||
|
uint32_t chunkSize; /* Size of data in bytes */
|
||||||
|
/* Samples I(8bits) then Q(8bits), I, Q ... */
|
||||||
|
} t_DataChunk;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
t_WAVRIFF_hdr hdr;
|
||||||
|
t_FormatChunk fmt_chunk;
|
||||||
|
t_DataChunk data_chunk;
|
||||||
|
} t_wav_file_hdr;
|
||||||
|
|
||||||
|
t_wav_file_hdr wave_file_hdr =
|
||||||
|
{
|
||||||
|
/* t_WAVRIFF_hdr */
|
||||||
|
{
|
||||||
|
"RIFF", /* groupID */
|
||||||
|
0, /* size to update later */
|
||||||
|
"WAVE"
|
||||||
|
},
|
||||||
|
/* t_FormatChunk */
|
||||||
|
{
|
||||||
|
"fmt ", /* char chunkID[4]; */
|
||||||
|
16, /* uint32_t chunkSize; */
|
||||||
|
1, /* uint16_t wFormatTag; 1 fixed */
|
||||||
|
2, /* uint16_t wChannels; 2 fixed */
|
||||||
|
0, /* uint32_t dwSamplesPerSec; Freq Hz sampling to update later */
|
||||||
|
0, /* uint32_t dwAvgBytesPerSec; Freq Hz sampling x 2 to update later */
|
||||||
|
2, /* uint16_t wBlockAlign; 2 fixed */
|
||||||
|
8, /* uint16_t wBitsPerSample; 8 fixed */
|
||||||
|
},
|
||||||
|
/* t_DataChunk */
|
||||||
|
{
|
||||||
|
"data", /* char chunkID[4]; */
|
||||||
|
0, /* uint32_t chunkSize; to update later */
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t bandwidth_hz;
|
uint32_t bandwidth_hz;
|
||||||
} max2837_ft_t;
|
} max2837_ft_t;
|
||||||
@ -192,6 +256,8 @@ FILE* fd = NULL;
|
|||||||
volatile uint32_t byte_count = 0;
|
volatile uint32_t byte_count = 0;
|
||||||
|
|
||||||
bool receive = false;
|
bool receive = false;
|
||||||
|
bool receive_wav = false;
|
||||||
|
|
||||||
bool transmit = false;
|
bool transmit = false;
|
||||||
struct timeval time_start;
|
struct timeval time_start;
|
||||||
struct timeval t_start;
|
struct timeval t_start;
|
||||||
@ -272,6 +338,7 @@ int tx_callback(hackrf_transfer* transfer) {
|
|||||||
|
|
||||||
static void usage() {
|
static void usage() {
|
||||||
printf("Usage:\n");
|
printf("Usage:\n");
|
||||||
|
printf("\t-w # Receive data into file with WAV header and automatic name.\n");
|
||||||
printf("\t-r <filename> # Receive data into file.\n");
|
printf("\t-r <filename> # Receive data into file.\n");
|
||||||
printf("\t-t <filename> # Transmit data from file.\n");
|
printf("\t-t <filename> # Transmit data from file.\n");
|
||||||
printf("\t[-f set_freq_hz] # Set Freq in Hz between [%lluMHz, %lluMHz[.\n", FREQ_MIN_HZ/FREQ_ONE_MHZ, FREQ_MAX_HZ/FREQ_ONE_MHZ);
|
printf("\t[-f set_freq_hz] # Set Freq in Hz between [%lluMHz, %lluMHz[.\n", FREQ_MIN_HZ/FREQ_ONE_MHZ, FREQ_MAX_HZ/FREQ_ONE_MHZ);
|
||||||
@ -289,15 +356,28 @@ void sigint_callback_handler(int signum)
|
|||||||
do_exit = true;
|
do_exit = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define PATH_FILE_MAX_LEN (FILENAME_MAX)
|
||||||
|
#define DATE_TIME_MAX_LEN (32)
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
int opt;
|
int opt;
|
||||||
|
char path_file[PATH_FILE_MAX_LEN];
|
||||||
|
char date_time[DATE_TIME_MAX_LEN];
|
||||||
const char* path = NULL;
|
const char* path = NULL;
|
||||||
int result;
|
int result;
|
||||||
|
time_t rawtime;
|
||||||
|
struct tm * timeinfo;
|
||||||
|
long int file_pos;
|
||||||
|
|
||||||
while( (opt = getopt(argc, argv, "r:t:f:a:s:n:b:")) != EOF )
|
while( (opt = getopt(argc, argv, "wr:t:f:a:s:n:b:")) != EOF )
|
||||||
{
|
{
|
||||||
result = HACKRF_SUCCESS;
|
result = HACKRF_SUCCESS;
|
||||||
switch( opt ) {
|
switch( opt )
|
||||||
|
{
|
||||||
|
case 'w':
|
||||||
|
receive_wav = true;
|
||||||
|
break;
|
||||||
|
|
||||||
case 'r':
|
case 'r':
|
||||||
receive = true;
|
receive = true;
|
||||||
path = optarg;
|
path = optarg;
|
||||||
@ -335,6 +415,7 @@ int main(int argc, char** argv) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
printf("unknown argument '-%c %s'\n", opt, optarg);
|
||||||
usage();
|
usage();
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
@ -360,6 +441,10 @@ int main(int argc, char** argv) {
|
|||||||
usage();
|
usage();
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
}else
|
||||||
|
{
|
||||||
|
/* Use default freq */
|
||||||
|
freq_hz = DEFAULT_FREQ_HZ;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( amp ) {
|
if( amp ) {
|
||||||
@ -400,17 +485,28 @@ int main(int argc, char** argv) {
|
|||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( (transmit == false) && (receive == receive_wav) )
|
||||||
|
{
|
||||||
|
printf("receive -r and receive_wav -w options are mutually exclusive\n");
|
||||||
|
usage();
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( receive_wav == false )
|
||||||
|
{
|
||||||
if( transmit == receive )
|
if( transmit == receive )
|
||||||
{
|
{
|
||||||
if( transmit == true )
|
if( transmit == true )
|
||||||
{
|
{
|
||||||
fprintf(stderr, "receive and transmit options are mutually exclusive\n");
|
printf("receive -r and transmit -t options are mutually exclusive\n");
|
||||||
} else {
|
} else
|
||||||
fprintf(stderr, "specify either transmit or receive option\n");
|
{
|
||||||
|
printf("specify either transmit -t or receive -r or receive_wav -w option\n");
|
||||||
}
|
}
|
||||||
usage();
|
usage();
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if( receive ) {
|
if( receive ) {
|
||||||
transceiver_mode = TRANSCEIVER_MODE_RX;
|
transceiver_mode = TRANSCEIVER_MODE_RX;
|
||||||
@ -420,8 +516,20 @@ int main(int argc, char** argv) {
|
|||||||
transceiver_mode = TRANSCEIVER_MODE_TX;
|
transceiver_mode = TRANSCEIVER_MODE_TX;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( receive_wav )
|
||||||
|
{
|
||||||
|
time (&rawtime);
|
||||||
|
timeinfo = localtime (&rawtime);
|
||||||
|
transceiver_mode = TRANSCEIVER_MODE_RX;
|
||||||
|
/* File format HackRF Year(2013), Month(11), Day(28), Hour Min Sec+Z, Freq kHz, IQ.wav */
|
||||||
|
strftime(date_time, DATE_TIME_MAX_LEN, "%Y%m%d_%H%M%S", timeinfo);
|
||||||
|
snprintf(path_file, PATH_FILE_MAX_LEN, "HackRF_%sZ_%ukHz_IQ.wav", date_time, (uint32_t)(freq_hz/(1000ull)) );
|
||||||
|
path = path_file;
|
||||||
|
printf("Receive wav file: %s\n", path);
|
||||||
|
}
|
||||||
|
|
||||||
if( path == NULL ) {
|
if( path == NULL ) {
|
||||||
fprintf(stderr, "specify a path to a file to transmit/receive\n");
|
printf("specify a path to a file to transmit/receive\n");
|
||||||
usage();
|
usage();
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
@ -452,6 +560,12 @@ int main(int argc, char** argv) {
|
|||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Write Wav header */
|
||||||
|
if( receive_wav )
|
||||||
|
{
|
||||||
|
fwrite(&wave_file_hdr, 1, sizeof(t_wav_file_hdr), fd);
|
||||||
|
}
|
||||||
|
|
||||||
signal(SIGINT, &sigint_callback_handler);
|
signal(SIGINT, &sigint_callback_handler);
|
||||||
signal(SIGILL, &sigint_callback_handler);
|
signal(SIGILL, &sigint_callback_handler);
|
||||||
signal(SIGFPE, &sigint_callback_handler);
|
signal(SIGFPE, &sigint_callback_handler);
|
||||||
@ -487,7 +601,6 @@ int main(int argc, char** argv) {
|
|||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( freq ) {
|
|
||||||
printf("call hackrf_set_freq(%llu Hz/%llu MHz)\n", freq_hz, (freq_hz/FREQ_ONE_MHZ) );
|
printf("call hackrf_set_freq(%llu Hz/%llu MHz)\n", freq_hz, (freq_hz/FREQ_ONE_MHZ) );
|
||||||
result = hackrf_set_freq(device, freq_hz);
|
result = hackrf_set_freq(device, freq_hz);
|
||||||
if( result != HACKRF_SUCCESS ) {
|
if( result != HACKRF_SUCCESS ) {
|
||||||
@ -495,7 +608,6 @@ int main(int argc, char** argv) {
|
|||||||
usage();
|
usage();
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if( amp ) {
|
if( amp ) {
|
||||||
printf("call hackrf_set_amp_enable(%u)\n", amp_enable);
|
printf("call hackrf_set_amp_enable(%u)\n", amp_enable);
|
||||||
@ -580,6 +692,19 @@ int main(int argc, char** argv) {
|
|||||||
|
|
||||||
if(fd != NULL)
|
if(fd != NULL)
|
||||||
{
|
{
|
||||||
|
if( receive_wav )
|
||||||
|
{
|
||||||
|
/* Get size of file */
|
||||||
|
file_pos = ftell(fd);
|
||||||
|
/* Update Wav Header */
|
||||||
|
wave_file_hdr.hdr.size = file_pos+8;
|
||||||
|
wave_file_hdr.fmt_chunk.dwSamplesPerSec = sample_rate_hz;
|
||||||
|
wave_file_hdr.fmt_chunk.dwAvgBytesPerSec = wave_file_hdr.fmt_chunk.dwSamplesPerSec*2;
|
||||||
|
wave_file_hdr.data_chunk.chunkSize = file_pos - sizeof(t_wav_file_hdr);
|
||||||
|
/* Overwrite header with updated data */
|
||||||
|
rewind(fd);
|
||||||
|
fwrite(&wave_file_hdr, 1, sizeof(t_wav_file_hdr), fd);
|
||||||
|
}
|
||||||
fclose(fd);
|
fclose(fd);
|
||||||
fd = NULL;
|
fd = NULL;
|
||||||
printf("fclose(fd) done\n");
|
printf("fclose(fd) done\n");
|
||||||
|
Reference in New Issue
Block a user