aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/fl2k_iq.c586
1 files changed, 293 insertions, 293 deletions
diff --git a/src/fl2k_iq.c b/src/fl2k_iq.c
index 49cd5f7..dde3bb8 100644
--- a/src/fl2k_iq.c
+++ b/src/fl2k_iq.c
@@ -95,43 +95,43 @@ int ignore_eof = 0;
void usage(void)
{
- fprintf(stderr,
- "fl2k_ampliphase, a special modulator for FL2K VGA dongles\n\n"
- "Usage:"
- "\t[-d device index (default: 0)]\n"
- "\t[-c center frequency (default: 1440 kHz)]\n"
- "\t[-i input baseband sample rate (default: 48000 Hz)]\n"
- "\t[-s samplerate in Hz (default: 96 MS/s)]\n"
- "\t[-t type of input: real/complex (default: real)\n"
- "\t input requirements: real - single channel (mono)\n"
- "\t complex - dual channel (stereo)\n"
- "\t[-w swap I & Q (invert spectrum)\n"
- "\t[-e ignore EOF\n"
- "\tfilename (use '-' to read from stdin)\n\n"
- );
- exit(1);
+ fprintf(stderr,
+ "fl2k_ampliphase, a special modulator for FL2K VGA dongles\n\n"
+ "Usage:"
+ "\t[-d device index (default: 0)]\n"
+ "\t[-c center frequency (default: 1440 kHz)]\n"
+ "\t[-i input baseband sample rate (default: 48000 Hz)]\n"
+ "\t[-s samplerate in Hz (default: 96 MS/s)]\n"
+ "\t[-t type of input: real/complex (default: real)\n"
+ "\t input requirements: real - single channel (mono)\n"
+ "\t complex - dual channel (stereo)\n"
+ "\t[-w swap I & Q (invert spectrum)\n"
+ "\t[-e ignore EOF\n"
+ "\tfilename (use '-' to read from stdin)\n\n"
+ );
+ exit(1);
}
#ifdef _WIN32
BOOL WINAPI
sighandler(int signum)
{
- if (CTRL_C_EVENT == signum) {
- fprintf(stderr, "Signal caught, exiting!\n");
- fl2k_stop_tx(dev);
- do_exit = 1;
- pthread_cond_signal(&iq_cond);
- return TRUE;
- }
- return FALSE;
+ if (CTRL_C_EVENT == signum) {
+ fprintf(stderr, "Signal caught, exiting!\n");
+ fl2k_stop_tx(dev);
+ do_exit = 1;
+ pthread_cond_signal(&iq_cond);
+ return TRUE;
+ }
+ return FALSE;
}
#else
static void sighandler(int signum)
{
- fprintf(stderr, "Signal caught, exiting!\n");
- fl2k_stop_tx(dev);
- do_exit = 1;
- pthread_cond_signal(&iq_cond);
+ fprintf(stderr, "Signal caught, exiting!\n");
+ fl2k_stop_tx(dev);
+ do_exit = 1;
+ pthread_cond_signal(&iq_cond);
}
#endif
@@ -164,32 +164,32 @@ struct trigonometric_table_S {
static struct trigonometric_table_S trig_table = { .initialized = 0 };
typedef struct {
- float sample_freq;
- float freq;
- /* instantaneous phase */
- unsigned long int phase;
- /* phase increment */
- unsigned long int phase_step;
-
- /* for phase modulation */
- long int phase_delta;
+ float sample_freq;
+ float freq;
+ /* instantaneous phase */
+ unsigned long int phase;
+ /* phase increment */
+ unsigned long int phase_step;
+
+ /* for phase modulation */
+ long int phase_delta;
long int phase_slope;
/* for amplitude modulation */
- complex float amplitude;
- complex float ampslope;
+ complex float amplitude;
+ complex float ampslope;
} dds_t;
static inline void dds_set_freq(dds_t *dds, float freq)
{
- dds->freq = freq;
- dds->phase_step = (freq / dds->sample_freq) * 2 * M_PI * ANG_INCR;
+ dds->freq = freq;
+ dds->phase_step = (freq / dds->sample_freq) * 2 * M_PI * ANG_INCR;
}
static inline void dds_set_amp(dds_t *dds, complex float amplitude, complex float ampslope)
{
- dds->amplitude = amplitude;
- dds->ampslope = ampslope;
+ dds->amplitude = amplitude;
+ dds->ampslope = ampslope;
}
static inline void dds_set_phase(dds_t *dds, long int phase_delta, long int phase_slope)
@@ -200,60 +200,60 @@ static inline void dds_set_phase(dds_t *dds, long int phase_delta, long int phas
dds_t dds_init(float sample_freq, float freq, float phase, float amp, enum waveform_E waveform )
{
- dds_t dds;
- int i;
-
- dds.sample_freq = sample_freq;
- dds.phase = phase * ANG_INCR;
- dds_set_freq(&dds, freq);
- dds_set_amp(&dds, amp, 0);
- /* Initialize quadrature table, prescaled for 16 bit signed integer */
- if (!trig_table.initialized) {
- float incr = 1.0 / (float)TRIG_TABLE_LEN;
- for (i = 0; i < TRIG_TABLE_LEN; i++){
- if(waveform == WF_SINE){
+ dds_t dds;
+ int i;
+
+ dds.sample_freq = sample_freq;
+ dds.phase = phase * ANG_INCR;
+ dds_set_freq(&dds, freq);
+ dds_set_amp(&dds, amp, 0);
+ /* Initialize quadrature table, prescaled for 16 bit signed integer */
+ if (!trig_table.initialized) {
+ float incr = 1.0 / (float)TRIG_TABLE_LEN;
+ for (i = 0; i < TRIG_TABLE_LEN; i++){
+ if(waveform == WF_SINE){
trig_table.quadrature[i]= sin(incr * i * DDS_2PI) * 32767;
trig_table.inphase[i] = cos(incr * i * DDS_2PI) * 32767;
- }
- else{
- /* rectangular / square output */
+ }
+ else{
+ /* rectangular / square output */
trig_table.quadrature[i]= sin(incr * i * DDS_2PI) >= 0 ? 32767 : -32767;
trig_table.inphase[i] = cos(incr * i * DDS_2PI) >= 0 ? 32767 : -32767;
- }
- }
+ }
+ }
- trig_table.initialized = 1;
- }
+ trig_table.initialized = 1;
+ }
- return dds;
+ return dds;
}
static inline int8_t dds_real(dds_t *dds)
{
- int tmp;
- int32_t amp_i, amp_q;
- int8_t amp8;
-
- // advance dds generator
- tmp = dds->phase >> TRIG_TABLE_SHIFT;
- dds->phase += dds->phase_step;
- dds->phase &= 0xffffffff;
-
- //amp = 255;
- amp_i = creal(dds->amplitude) * 23170.0; // 0..15, * 1/SQRT(2)
- amp_q = cimag(dds->amplitude) * 23170.0;
- amp_i = amp_i * trig_table.quadrature[tmp]; // 0..31, * 1/SQRT(2)
+ int tmp;
+ int32_t amp_i, amp_q;
+ int8_t amp8;
+
+ // advance dds generator
+ tmp = dds->phase >> TRIG_TABLE_SHIFT;
+ dds->phase += dds->phase_step;
+ dds->phase &= 0xffffffff;
+
+ //amp = 255;
+ amp_i = creal(dds->amplitude) * 23170.0; // 0..15, * 1/SQRT(2)
+ amp_q = cimag(dds->amplitude) * 23170.0;
+ amp_i = amp_i * trig_table.quadrature[tmp]; // 0..31, * 1/SQRT(2)
amp_q = amp_q * trig_table.inphase[tmp]; // 0..31, * 1/SQRT(2)
- amp8 = (int8_t) ((amp_i + amp_q) >> 24); // 0..31 >> 24 => 0..8
- dds->amplitude += dds->ampslope;
- return amp8;
+ amp8 = (int8_t) ((amp_i + amp_q) >> 24); // 0..31 >> 24 => 0..8
+ dds->amplitude += dds->ampslope;
+ return amp8;
}
static inline void dds_real_buf(dds_t *dds, int8_t *buf, int count)
{
- int i;
- for (i = 0; i < count; i++)
- buf[i] = dds_real(dds);
+ int i;
+ for (i = 0; i < count; i++)
+ buf[i] = dds_real(dds);
}
@@ -303,75 +303,75 @@ static inline void dds_complex_buf(dds_t *dds, int8_t *ibuf, int8_t *qbuf, int c
* in the amp buffer */
static void *iq_worker(void *arg)
{
- register float freq;
- register float tmp;
- dds_t base_signal;
- int8_t *tmp_ptr;
- uint32_t len = 0;
- uint32_t readlen, remaining;
- int buf_prefilled = 0;
-
- /* Prepare the oscillators */
- base_signal = dds_init(samp_rate, base_freq, 0, 1, WF_RECT);
-
- while (!do_exit) {
- // dds_set_amp(&base_signal, ampbuf[readpos], slopebuf[readpos]);
- /* phase modulate the oscillator */
- dds_set_phase(&base_signal, pdbuf[readpos], pdslopebuf[readpos]);
- readpos++;
- readpos &= BUFFER_SAMPLES_MASK;
-
- /* check if we reach the end of the buffer */
- if ((len + rf_to_baseband_sample_ratio) > FL2K_BUF_LEN) {
- readlen = FL2K_BUF_LEN - len;
- remaining = rf_to_baseband_sample_ratio - readlen;
- dds_complex_buf(&base_signal, &iambuf[len], &qambuf[len],readlen);
-
- if (buf_prefilled) {
- /* swap buffers */
- tmp_ptr = iambuf;
- iambuf = itxbuf;
- itxbuf = tmp_ptr;
+ register float freq;
+ register float tmp;
+ dds_t base_signal;
+ int8_t *tmp_ptr;
+ uint32_t len = 0;
+ uint32_t readlen, remaining;
+ int buf_prefilled = 0;
+
+ /* Prepare the oscillators */
+ base_signal = dds_init(samp_rate, base_freq, 0, 1, WF_RECT);
+
+ while (!do_exit) {
+ // dds_set_amp(&base_signal, ampbuf[readpos], slopebuf[readpos]);
+ /* phase modulate the oscillator */
+ dds_set_phase(&base_signal, pdbuf[readpos], pdslopebuf[readpos]);
+ readpos++;
+ readpos &= BUFFER_SAMPLES_MASK;
+
+ /* check if we reach the end of the buffer */
+ if ((len + rf_to_baseband_sample_ratio) > FL2K_BUF_LEN) {
+ readlen = FL2K_BUF_LEN - len;
+ remaining = rf_to_baseband_sample_ratio - readlen;
+ dds_complex_buf(&base_signal, &iambuf[len], &qambuf[len],readlen);
+
+ if (buf_prefilled) {
+ /* swap buffers */
+ tmp_ptr = iambuf;
+ iambuf = itxbuf;
+ itxbuf = tmp_ptr;
tmp_ptr = qambuf;
qambuf = qtxbuf;
qtxbuf = tmp_ptr;
- pthread_mutex_lock(&cb_mutex);
- pthread_cond_wait(&cb_cond, &cb_mutex);
- pthread_mutex_unlock(&cb_mutex);
- }
-
- dds_complex_buf(&base_signal, iambuf, qambuf, remaining);
- len = remaining;
-
- buf_prefilled = 1;
- } else {
- dds_complex_buf(&base_signal, &iambuf[len], &qambuf[len], rf_to_baseband_sample_ratio);
- len += rf_to_baseband_sample_ratio;
- }
- pthread_mutex_lock(&iq_mutex);
- pthread_cond_signal(&iq_cond);
- pthread_mutex_unlock(&iq_mutex);
- }
-
- pthread_exit(NULL);
+ pthread_mutex_lock(&cb_mutex);
+ pthread_cond_wait(&cb_cond, &cb_mutex);
+ pthread_mutex_unlock(&cb_mutex);
+ }
+
+ dds_complex_buf(&base_signal, iambuf, qambuf, remaining);
+ len = remaining;
+
+ buf_prefilled = 1;
+ } else {
+ dds_complex_buf(&base_signal, &iambuf[len], &qambuf[len], rf_to_baseband_sample_ratio);
+ len += rf_to_baseband_sample_ratio;
+ }
+ pthread_mutex_lock(&iq_mutex);
+ pthread_cond_signal(&iq_cond);
+ pthread_mutex_unlock(&iq_mutex);
+ }
+
+ pthread_exit(NULL);
}
static inline int writelen(int maxlen)
{
- int rp = readpos;
- int len;
- int r;
+ int rp = readpos;
+ int len;
+ int r;
- if (rp < writepos)
- rp += BUFFER_SAMPLES;
+ if (rp < writepos)
+ rp += BUFFER_SAMPLES;
- len = rp - writepos;
+ len = rp - writepos;
- r = len > maxlen ? maxlen : len;
+ r = len > maxlen ? maxlen : len;
- return r;
+ return r;
}
@@ -459,64 +459,64 @@ void ampliphase_modulator(enum inputType_E inputType)
void fl2k_callback(fl2k_data_info_t *data_info)
{
- if (data_info->device_error) {
- fprintf(stderr, "Device error, exiting.\n");
- do_exit = 1;
- pthread_mutex_lock(&iq_mutex);
- pthread_cond_signal(&iq_cond);
- pthread_mutex_unlock(&iq_mutex);
- }
-
- pthread_cond_signal(&cb_cond);
-
- data_info->sampletype_signed = 1;
- data_info->r_buf = (char *)itxbuf;
+ if (data_info->device_error) {
+ fprintf(stderr, "Device error, exiting.\n");
+ do_exit = 1;
+ pthread_mutex_lock(&iq_mutex);
+ pthread_cond_signal(&iq_cond);
+ pthread_mutex_unlock(&iq_mutex);
+ }
+
+ pthread_cond_signal(&cb_cond);
+
+ data_info->sampletype_signed = 1;
+ data_info->r_buf = (char *)itxbuf;
data_info->g_buf = (char *)qtxbuf;
}
int main(int argc, char **argv)
{
- int r, opt;
- uint32_t buf_num = 0;
- int dev_index = 0;
- pthread_attr_t attr;
- char *filename = NULL;
- int option_index = 0;
- int input_freq_specified = 0;
- enum inputType_E input_type = INP_REAL;
+ int r, opt;
+ uint32_t buf_num = 0;
+ int dev_index = 0;
+ pthread_attr_t attr;
+ char *filename = NULL;
+ int option_index = 0;
+ int input_freq_specified = 0;
+ enum inputType_E input_type = INP_REAL;
#ifndef _WIN32
- struct sigaction sigact, sigign;
+ struct sigaction sigact, sigign;
#endif
- static struct option long_options[] =
- {
- {0, 0, 0, 0}
- };
-
- while (1) {
- opt = getopt_long(argc, argv, "ewd:c:i:s:t:", long_options, &option_index);
-
- /* end of options reached */
- if (opt == -1)
- break;
-
- switch (opt) {
- case 0:
- break;
- case 'd':
- dev_index = (uint32_t)atoi(optarg);
- break;
- case 'c':
- base_freq = (uint32_t)atof(optarg);
- break;
- case 'i':
- input_freq = (uint32_t)atof(optarg);
- input_freq_specified = 1;
- break;
- case 's':
- samp_rate = (uint32_t)atof(optarg);
- break;
+ static struct option long_options[] =
+ {
+ {0, 0, 0, 0}
+ };
+
+ while (1) {
+ opt = getopt_long(argc, argv, "ewd:c:i:s:t:", long_options, &option_index);
+
+ /* end of options reached */
+ if (opt == -1)
+ break;
+
+ switch (opt) {
+ case 0:
+ break;
+ case 'd':
+ dev_index = (uint32_t)atoi(optarg);
+ break;
+ case 'c':
+ base_freq = (uint32_t)atof(optarg);
+ break;
+ case 'i':
+ input_freq = (uint32_t)atof(optarg);
+ input_freq_specified = 1;
+ break;
+ case 's':
+ samp_rate = (uint32_t)atof(optarg);
+ break;
case 't':
/* type */
if(strcasecmp(optarg, "complex") && strcasecmp(optarg, "real")){
@@ -525,53 +525,53 @@ int main(int argc, char **argv)
}
input_type = strcasecmp(optarg, "complex") == 0 ? INP_COMPLEX : INP_REAL;
break;
- case 'w':
- swap_iq = 1;
- break;
- case 'e':
- ignore_eof = 1;
- break;
- default:
- usage();
- break;
- }
- }
-
- if (argc <= optind) {
- usage();
- } else {
- filename = argv[optind];
- }
-
- if (dev_index < 0) {
- exit(1);
- }
-
- if (strcmp(filename, "-") == 0) { /* Read samples from stdin */
- file = stdin;
+ case 'w':
+ swap_iq = 1;
+ break;
+ case 'e':
+ ignore_eof = 1;
+ break;
+ default:
+ usage();
+ break;
+ }
+ }
+
+ if (argc <= optind) {
+ usage();
+ } else {
+ filename = argv[optind];
+ }
+
+ if (dev_index < 0) {
+ exit(1);
+ }
+
+ if (strcmp(filename, "-") == 0) { /* Read samples from stdin */
+ file = stdin;
#ifdef _WIN32
- _setmode(_fileno(stdin), _O_BINARY);
+ _setmode(_fileno(stdin), _O_BINARY);
#endif
- } else {
- file = fopen(filename, "rb");
- if (!file) {
- fprintf(stderr, "Failed to open %s\n", filename);
- return -ENOENT;
- }
- }
-
- /* allocate I buffer */
- buf1 = malloc(FL2K_BUF_LEN);
- buf2 = malloc(FL2K_BUF_LEN);
- if (!buf1 || !buf2) {
- fprintf(stderr, "malloc error!\n");
- exit(1);
- }
- iambuf = buf1;
- itxbuf = buf2;
+ } else {
+ file = fopen(filename, "rb");
+ if (!file) {
+ fprintf(stderr, "Failed to open %s\n", filename);
+ return -ENOENT;
+ }
+ }
+
+ /* allocate I buffer */
+ buf1 = malloc(FL2K_BUF_LEN);
+ buf2 = malloc(FL2K_BUF_LEN);
+ if (!buf1 || !buf2) {
+ fprintf(stderr, "malloc error!\n");
+ exit(1);
+ }
+ iambuf = buf1;
+ itxbuf = buf2;
/* allocate Q buffer */
- buf1 = malloc(FL2K_BUF_LEN);
+ buf1 = malloc(FL2K_BUF_LEN);
buf2 = malloc(FL2K_BUF_LEN);
if (!buf1 || !buf2) {
fprintf(stderr, "malloc error!\n");
@@ -581,78 +581,78 @@ int main(int argc, char **argv)
qtxbuf = buf2;
- /* Baseband buffer */
- slopebuf = malloc(BUFFER_SAMPLES * sizeof(float complex));
- ampbuf = malloc(BUFFER_SAMPLES * sizeof(float complex));
- pdbuf = malloc(BUFFER_SAMPLES * sizeof(long int));
+ /* Baseband buffer */
+ slopebuf = malloc(BUFFER_SAMPLES * sizeof(float complex));
+ ampbuf = malloc(BUFFER_SAMPLES * sizeof(float complex));
+ pdbuf = malloc(BUFFER_SAMPLES * sizeof(long int));
pdslopebuf = malloc(BUFFER_SAMPLES * sizeof(long int));
- readpos = 0;
- writepos = 1;
-
- fprintf(stdout, "Samplerate: %3.2f MHz\n", (float)samp_rate/1000000);
- fprintf(stdout, "Center frequency: %5.0f kHz\n", (float)base_freq/1000);
- if(swap_iq)
- fprintf(stdout, "Spectral inversion active.\n");
- if(ignore_eof)
- fprintf(stdout, "Ignoring EOF.\n");
-
- pthread_mutex_init(&cb_mutex, NULL);
- pthread_mutex_init(&iq_mutex, NULL);
- pthread_cond_init(&cb_cond, NULL);
- pthread_cond_init(&iq_cond, NULL);
- pthread_attr_init(&attr);
-
- fl2k_open(&dev, (uint32_t)dev_index);
- if (NULL == dev) {
- fprintf(stderr, "Failed to open fl2k device #%d.\n", dev_index);
- goto out;
- }
-
- r = pthread_create(&iq_thread, &attr, iq_worker, NULL);
- if (r < 0) {
- fprintf(stderr, "Error spawning IQ worker thread!\n");
- goto out;
- }
-
- pthread_attr_destroy(&attr);
- r = fl2k_start_tx(dev, fl2k_callback, NULL, 0);
-
- /* Set the sample rate */
- r = fl2k_set_sample_rate(dev, samp_rate);
- if (r < 0)
- fprintf(stderr, "WARNING: Failed to set sample rate. %d\n", r);
-
- /* read back actual frequency */
- samp_rate = fl2k_get_sample_rate(dev);
-
- /* Calculate needed constants */
- rf_to_baseband_sample_ratio = samp_rate / input_freq;
+ readpos = 0;
+ writepos = 1;
+
+ fprintf(stdout, "Samplerate: %3.2f MHz\n", (float)samp_rate/1000000);
+ fprintf(stdout, "Center frequency: %5.0f kHz\n", (float)base_freq/1000);
+ if(swap_iq)
+ fprintf(stdout, "Spectral inversion active.\n");
+ if(ignore_eof)
+ fprintf(stdout, "Ignoring EOF.\n");
+
+ pthread_mutex_init(&cb_mutex, NULL);
+ pthread_mutex_init(&iq_mutex, NULL);
+ pthread_cond_init(&cb_cond, NULL);
+ pthread_cond_init(&iq_cond, NULL);
+ pthread_attr_init(&attr);
+
+ fl2k_open(&dev, (uint32_t)dev_index);
+ if (NULL == dev) {
+ fprintf(stderr, "Failed to open fl2k device #%d.\n", dev_index);
+ goto out;
+ }
+
+ r = pthread_create(&iq_thread, &attr, iq_worker, NULL);
+ if (r < 0) {
+ fprintf(stderr, "Error spawning IQ worker thread!\n");
+ goto out;
+ }
+
+ pthread_attr_destroy(&attr);
+ r = fl2k_start_tx(dev, fl2k_callback, NULL, 0);
+
+ /* Set the sample rate */
+ r = fl2k_set_sample_rate(dev, samp_rate);
+ if (r < 0)
+ fprintf(stderr, "WARNING: Failed to set sample rate. %d\n", r);
+
+ /* read back actual frequency */
+ samp_rate = fl2k_get_sample_rate(dev);
+
+ /* Calculate needed constants */
+ rf_to_baseband_sample_ratio = samp_rate / input_freq;
#ifndef _WIN32
- sigact.sa_handler = sighandler;
- sigemptyset(&sigact.sa_mask);
- sigact.sa_flags = 0;
- sigign.sa_handler = SIG_IGN;
- sigaction(SIGINT, &sigact, NULL);
- sigaction(SIGTERM, &sigact, NULL);
- sigaction(SIGQUIT, &sigact, NULL);
- sigaction(SIGPIPE, &sigign, NULL);
+ sigact.sa_handler = sighandler;
+ sigemptyset(&sigact.sa_mask);
+ sigact.sa_flags = 0;
+ sigign.sa_handler = SIG_IGN;
+ sigaction(SIGINT, &sigact, NULL);
+ sigaction(SIGTERM, &sigact, NULL);
+ sigaction(SIGQUIT, &sigact, NULL);
+ sigaction(SIGPIPE, &sigign, NULL);
#else
- SetConsoleCtrlHandler( (PHANDLER_ROUTINE) sighandler, TRUE );
+ SetConsoleCtrlHandler( (PHANDLER_ROUTINE) sighandler, TRUE );
#endif
- ampliphase_modulator(input_type);
+ ampliphase_modulator(input_type);
-out:
- fl2k_close(dev);
+ out:
+ fl2k_close(dev);
- if (file != stdin)
- fclose(file);
+ if (file != stdin)
+ fclose(file);
- free(ampbuf);
- free(slopebuf);
- free(buf1);
- free(buf2);
+ free(ampbuf);
+ free(slopebuf);
+ free(buf1);
+ free(buf2);
- return 0;
+ return 0;
}