diff options
-rw-r--r-- | src/fl2k_iq.c | 586 |
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; } |