From eba517239291033433a5f6f16be53cc9b89a3ae3 Mon Sep 17 00:00:00 2001 From: Felix Erckenbrecht Date: Sat, 2 Nov 2019 04:02:59 +0100 Subject: Include garage door opener (12 Bit code) --- src/fl2k_garage.c | 526 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 526 insertions(+) create mode 100644 src/fl2k_garage.c (limited to 'src/fl2k_garage.c') diff --git a/src/fl2k_garage.c b/src/fl2k_garage.c new file mode 100644 index 0000000..6eb0057 --- /dev/null +++ b/src/fl2k_garage.c @@ -0,0 +1,526 @@ +/* + * osmo-fl2k, turns FL2000-based USB 3.0 to VGA adapters into + * low cost DACs + * + * Copyright (C) 2019 by Felix Erckenbrecht + * + * based on fl2k_fm code by: + * Copyright (C) 2016-2018 by Steve Markgraf + * + * based on FM modulator code from VGASIG: + * Copyright (C) 2009 by Bartek Kania + * + * SPDX-License-Identifier: GPL-2.0+ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include + +#ifndef _WIN32 +#include +#include +#include +#else +#include +#include +#include +#include "getopt/getopt.h" +#endif + +#include +#include + +#include "osmo-fl2k.h" +#include "rds_mod.h" + +#define BUFFER_SAMPLES_SHIFT 16 +#define BUFFER_SAMPLES (1 << BUFFER_SAMPLES_SHIFT) +#define BUFFER_SAMPLES_MASK ((1 << BUFFER_SAMPLES_SHIFT)-1) + +#define AUDIO_BUF_SIZE 1024 + +#define BASEBAND_SAMPLES_PER_CHIP 3 +#define BASEBAND_WORD_BITS 12 +#define BASEBAND_CHIPS_PER_BIT 3 +#define BASEBAND_CHIPS_PER_WORD (BASEBAND_WORD_BITS * BASEBAND_CHIPS_PER_BIT) +#define BASEBAND_CHIPS_PER_SPACE BASEBAND_CHIPS_PER_WORD +#define BASEBAND_SPACE_HIGH_CHIPS 1 +#define BASEBAND_SPACE_LOW_CHIPS (BASEBAND_CHIPS_PER_SPACE - BASEBAND_SPACE_HIGH_CHIPS) + +fl2k_dev_t *dev = NULL; +int do_exit = 0; + +pthread_t fm_thread; +pthread_t am_thread; +pthread_mutex_t cb_mutex; +pthread_mutex_t fm_mutex; +pthread_mutex_t am_mutex; +pthread_cond_t cb_cond; +pthread_cond_t fm_cond; +pthread_cond_t am_cond; + +FILE *file; +int8_t *txbuf = NULL; +int8_t *ambuf = NULL; +int8_t *buf1 = NULL; +int8_t *buf2 = NULL; + +uint32_t samp_rate = 100000000; + +double mod_index = 0.9; +int carrier_freq = 40685000; +int carrier_per_signal; + +double *ampbuf; +double *slopebuf; +int writepos, readpos; + +void usage(void) +{ + fprintf(stderr, + "fl2k_garage, a garage door opener for FL2K VGA dongles\n\n" + "Usage:" + "\t[-d device index (default: 0)]\n" + "\t[-f carrier frequency (default: 40.685 MHz)]\n" + "\t[-c garage door code (12 Bit)]\n" + "\t[-b chip period in us (default 320 us)]\n" + "\t[-s samplerate in Hz (default: 100 MS/s)]\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(&fm_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(&fm_cond); +} +#endif + +/* DDS Functions */ + +#ifndef M_PI +# define M_PI 3.14159265358979323846 /* pi */ +# define M_PI_2 1.57079632679489661923 /* pi/2 */ +# define M_PI_4 0.78539816339744830962 /* pi/4 */ +# define M_1_PI 0.31830988618379067154 /* 1/pi */ +# define M_2_PI 0.63661977236758134308 /* 2/pi */ +#endif +#define DDS_2PI (M_PI * 2) /* 2 * Pi */ +#define DDS_3PI2 (M_PI_2 * 3) /* 3/2 * pi */ + +#define SIN_TABLE_ORDER 8 +#define SIN_TABLE_SHIFT (32 - SIN_TABLE_ORDER) +#define SIN_TABLE_LEN (1 << SIN_TABLE_ORDER) +#define ANG_INCR (0xffffffff / DDS_2PI) + +int16_t sine_table[SIN_TABLE_LEN]; +int sine_table_init = 0; + +typedef struct { + double sample_freq; + double freq; + unsigned long int phase; + unsigned long int phase_step; + double amplitude; + double ampslope; +} dds_t; + +static inline void dds_set_freq(dds_t *dds, double freq) +{ + dds->freq = freq; + dds->phase_step = (freq / dds->sample_freq) * 2 * M_PI * ANG_INCR; +} + +static inline void dds_set_amp(dds_t *dds, double amplitude, double ampslope) +{ + dds->amplitude = amplitude; + dds->ampslope = ampslope; +} + +dds_t dds_init(double sample_freq, double freq, double phase, double amp) +{ + 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 sine table, prescaled for 16 bit signed integer */ + if (!sine_table_init) { + double incr = 1.0 / (double)SIN_TABLE_LEN; + for (i = 0; i < SIN_TABLE_LEN; i++) + sine_table[i] = sin(incr * i * DDS_2PI) * 32767; + + sine_table_init = 1; + } + + return dds; +} + +static inline int8_t dds_real(dds_t *dds) +{ + int tmp; + int32_t amp; + + // advance dds generator + tmp = dds->phase >> SIN_TABLE_SHIFT; + dds->phase += dds->phase_step; + dds->phase &= 0xffffffff; + + amp = (int32_t)(dds->amplitude * 255) * sine_table[tmp]; + dds->amplitude += dds->ampslope; + + return (int8_t)(amp >> 16) ; +} + +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); +} + +/* Signal generation and some helpers */ + +/* Generate the radio signal using the pre-calculated amplitude information + * in the amp buffer */ +static void *am_worker(void *arg) +{ + register double freq; + register double tmp; + dds_t carrier; + int8_t *tmp_ptr; + uint32_t len = 0; + uint32_t readlen, remaining; + int buf_prefilled = 0; + + /* Prepare the oscillators */ + carrier = dds_init(samp_rate, carrier_freq, 1, 0); + + while (!do_exit) { + dds_set_amp(&carrier, ampbuf[readpos], slopebuf[readpos]); + readpos++; + readpos &= BUFFER_SAMPLES_MASK; + + /* check if we reach the end of the buffer */ + if ((len + carrier_per_signal) > FL2K_BUF_LEN) { + readlen = FL2K_BUF_LEN - len; + remaining = carrier_per_signal - readlen; + dds_real_buf(&carrier, &ambuf[len], readlen); + + if (buf_prefilled) { + /* swap buffers */ + tmp_ptr = ambuf; + ambuf = txbuf; + txbuf = tmp_ptr; + pthread_cond_wait(&cb_cond, &cb_mutex); + } + + dds_real_buf(&carrier, ambuf, remaining); + len = remaining; + + buf_prefilled = 1; + } else { + dds_real_buf(&carrier, &ambuf[len], carrier_per_signal); + len += carrier_per_signal; + } + + pthread_cond_signal(&am_cond); + } + + pthread_exit(NULL); +} + +static inline int writelen(int maxlen) +{ + int rp = readpos; + int len; + int r; + + if (rp < writepos) + rp += BUFFER_SAMPLES; + + len = rp - writepos; + + r = len > maxlen ? maxlen : len; + + return r; +} + +static inline int32_t modulate_sample_am(int lastwritepos, double lastamp, int16_t sample) +{ + double amp, slope; + + /* Calculate modulator amplitude at this point to lessen + * the calculations needed in the signal generator */ + amp = 1 - ((double)sample * mod_index); + + /* What we do here is calculate a linear "slope" from + the previous sample to this one. This is then used by + the modulator to gently increase/decrease the amplitude + with each sample without the need to recalculate + the dds parameters. In fact this gives us a very + efficient and pretty good interpolation filter. */ + slope = amp - lastamp; + slope /= carrier_per_signal; + slopebuf[lastwritepos] = slope; + ampbuf[writepos] = amp; + + return amp; +} + +void am_modulator(const int code_input) +{ + int counter = 0; + int code; + unsigned int i; + unsigned int b = 0; + size_t len; + int32_t lastamp = 0; + uint32_t lastwritepos = writepos; + int16_t sample = 0; + + /* + * 3*640 us = 1,92 ms pro Symbol + * 12 Symbole Daten (12 Bit) + * 11 Symbole Pause, 1 Symbol 1 (synch) + * + * 1 = __- + * 0 = _-- + */ + while (!do_exit) { + len = writelen(AUDIO_BUF_SIZE); + if (len > 1) { + if (len == 0) + do_exit = 1; + + for (i = 0; i < len; i++) { + if( ++b >= BASEBAND_SAMPLES_PER_CHIP ){ + b = 0; + if(counter < (BASEBAND_SPACE_LOW_CHIPS)){ + sample = 0; + } + else if(counter < (BASEBAND_CHIPS_PER_SPACE)){ + // synch symbol + sample = 1; + // reload code + code = code_input; + } + else{ + int m; + m = counter % BASEBAND_CHIPS_PER_BIT; + if(m == 0){ + sample = 0; + } + else if(m == 1){ + sample = (code & 1) ^ 1; + } + else{ + sample = 1; + code >>= 1; + } + } + if(++counter >= (BASEBAND_CHIPS_PER_SPACE + BASEBAND_CHIPS_PER_WORD)){ + counter = 0; + } + } + /* Modulate and buffer the sample */ + lastamp = modulate_sample_am(lastwritepos, lastamp, sample); + lastwritepos = writepos++; + writepos %= BUFFER_SAMPLES; + } + } else { + pthread_cond_wait(&fm_cond, &fm_mutex); + } + } +} + +void fl2k_callback(fl2k_data_info_t *data_info) +{ + if (data_info->device_error) { + fprintf(stderr, "Device error, exiting.\n"); + do_exit = 1; + pthread_cond_signal(&fm_cond); + } + + pthread_cond_signal(&cb_cond); + + data_info->sampletype_signed = 1; + data_info->r_buf = (char *)txbuf; +} + +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 code = 0; + int chiptime_us = 320; + +#ifndef _WIN32 + struct sigaction sigact, sigign; +#endif + + static struct option long_options[] = + { + {0, 0, 0, 0} + }; + + while (1) { + opt = getopt_long(argc, argv, "b:c:f:m:s:", long_options, &option_index); + /* end of options reached */ + if (opt == -1) + break; + + switch (opt) { + case 0: + break; + case 'b': + chiptime_us = atoi(optarg); + break; + case 'c': + code = atoi(optarg); + code &= 4095; + break; + case 'f': + carrier_freq = (uint32_t)atof(optarg); + break; + case 'm': + mod_index = atof(optarg); + break; + case 's': + samp_rate = (uint32_t)atof(optarg); + break; + default: + usage(); + break; + } + } + + if (argc < optind) { + usage(); + } + + /* allocate buffer */ + buf1 = malloc(FL2K_BUF_LEN); + buf2 = malloc(FL2K_BUF_LEN); + if (!buf1 || !buf2) { + fprintf(stderr, "malloc error!\n"); + exit(1); + } + + ambuf = buf1; + txbuf = buf2; + + /* Decoded audio */ + slopebuf = malloc(BUFFER_SAMPLES * sizeof(double)); + ampbuf = malloc(BUFFER_SAMPLES * sizeof(double)); + slopebuf = malloc(BUFFER_SAMPLES * sizeof(double)); + readpos = 0; + writepos = 1; + + fprintf(stderr, "Samplerate:\t%3.2f MHz\n", (double)samp_rate/1000000); + fprintf(stderr, "Carrier:\t%3.3f MHz\n", (double)carrier_freq/1000000); + fprintf(stderr, "Mod Index:\t%3.1f %%\n", + (double)(mod_index * 100)); + fprintf(stderr, "Chip period:\t%d us\n", chiptime_us); + + pthread_mutex_init(&cb_mutex, NULL); + pthread_mutex_init(&fm_mutex, NULL); + pthread_mutex_init(&am_mutex, NULL); + pthread_cond_init(&cb_cond, NULL); + pthread_cond_init(&fm_cond, NULL); + pthread_cond_init(&am_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(&am_thread, &attr, am_worker, NULL); + if (r < 0) { + fprintf(stderr, "Error spawning AM 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 */ + carrier_per_signal = (int)((double) samp_rate * chiptime_us/(1000000*BASEBAND_SAMPLES_PER_CHIP) + 0.5); + printf("Cps : %d\n", carrier_per_signal); +#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); +#else + SetConsoleCtrlHandler( (PHANDLER_ROUTINE) sighandler, TRUE ); +#endif + + am_modulator(code); + +out: + fl2k_close(dev); + + if (file != stdin) + fclose(file); + + free(ampbuf); + free(slopebuf); + free(buf1); + free(buf2); + + return 0; +} -- cgit v1.2.3 From 0a7da5e72a2cecfc63f45731b3cf46e89d00656d Mon Sep 17 00:00:00 2001 From: Felix Erckenbrecht Date: Sat, 2 Nov 2019 20:38:41 +0100 Subject: Precalculate baseband samples --- src/fl2k_garage.c | 92 ++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 57 insertions(+), 35 deletions(-) (limited to 'src/fl2k_garage.c') diff --git a/src/fl2k_garage.c b/src/fl2k_garage.c index 6eb0057..575c3ad 100644 --- a/src/fl2k_garage.c +++ b/src/fl2k_garage.c @@ -54,7 +54,7 @@ #define BUFFER_SAMPLES (1 << BUFFER_SAMPLES_SHIFT) #define BUFFER_SAMPLES_MASK ((1 << BUFFER_SAMPLES_SHIFT)-1) -#define AUDIO_BUF_SIZE 1024 +#define AUDIO_BUF_SIZE 4096 #define BASEBAND_SAMPLES_PER_CHIP 3 #define BASEBAND_WORD_BITS 12 @@ -63,6 +63,7 @@ #define BASEBAND_CHIPS_PER_SPACE BASEBAND_CHIPS_PER_WORD #define BASEBAND_SPACE_HIGH_CHIPS 1 #define BASEBAND_SPACE_LOW_CHIPS (BASEBAND_CHIPS_PER_SPACE - BASEBAND_SPACE_HIGH_CHIPS) +#define BASEBAND_CHIPS_TOTAL (BASEBAND_CHIPS_PER_SPACE + BASEBAND_CHIPS_PER_WORD) fl2k_dev_t *dev = NULL; int do_exit = 0; @@ -76,7 +77,9 @@ pthread_cond_t cb_cond; pthread_cond_t fm_cond; pthread_cond_t am_cond; -FILE *file; +int16_t *sample_buf; +int sample_buf_size; + int8_t *txbuf = NULL; int8_t *ambuf = NULL; int8_t *buf1 = NULL; @@ -313,6 +316,7 @@ void am_modulator(const int code_input) int32_t lastamp = 0; uint32_t lastwritepos = writepos; int16_t sample = 0; + int samplebuf_pos = 0; /* * 3*640 us = 1,92 ms pro Symbol @@ -329,36 +333,11 @@ void am_modulator(const int code_input) do_exit = 1; for (i = 0; i < len; i++) { - if( ++b >= BASEBAND_SAMPLES_PER_CHIP ){ - b = 0; - if(counter < (BASEBAND_SPACE_LOW_CHIPS)){ - sample = 0; - } - else if(counter < (BASEBAND_CHIPS_PER_SPACE)){ - // synch symbol - sample = 1; - // reload code - code = code_input; - } - else{ - int m; - m = counter % BASEBAND_CHIPS_PER_BIT; - if(m == 0){ - sample = 0; - } - else if(m == 1){ - sample = (code & 1) ^ 1; - } - else{ - sample = 1; - code >>= 1; - } - } - if(++counter >= (BASEBAND_CHIPS_PER_SPACE + BASEBAND_CHIPS_PER_WORD)){ - counter = 0; - } - } /* Modulate and buffer the sample */ + sample = sample_buf[samplebuf_pos++]; + if(samplebuf_pos >= BASEBAND_SAMPLES_PER_CHIP * BASEBAND_CHIPS_TOTAL){ + samplebuf_pos = 0; + } lastamp = modulate_sample_am(lastwritepos, lastamp, sample); lastwritepos = writepos++; writepos %= BUFFER_SAMPLES; @@ -369,6 +348,49 @@ void am_modulator(const int code_input) } } +void prepare_baseband(const int code_input, int16_t * sbuf){ + int counter; + int b; + int sample_no; + int16_t sample; + int msb_first_code; + + msb_first_code = 0; + // change to msb first and invert + for(b = 0;b<12;b++){ + msb_first_code |= code_input & (1<>= 1; + } + } + sbuf[counter * BASEBAND_SAMPLES_PER_CHIP + b] = sample; + } + } +} + void fl2k_callback(fl2k_data_info_t *data_info) { if (data_info->device_error) { @@ -453,6 +475,7 @@ int main(int argc, char **argv) slopebuf = malloc(BUFFER_SAMPLES * sizeof(double)); ampbuf = malloc(BUFFER_SAMPLES * sizeof(double)); slopebuf = malloc(BUFFER_SAMPLES * sizeof(double)); + sample_buf = malloc(BASEBAND_SAMPLES_PER_CHIP * BASEBAND_CHIPS_TOTAL); readpos = 0; writepos = 1; @@ -470,6 +493,8 @@ int main(int argc, char **argv) pthread_cond_init(&am_cond, NULL); pthread_attr_init(&attr); + prepare_baseband(code, sample_buf); + fl2k_open(&dev, (uint32_t)dev_index); if (NULL == dev) { fprintf(stderr, "Failed to open fl2k device #%d.\n", dev_index); @@ -495,7 +520,7 @@ int main(int argc, char **argv) /* Calculate needed constants */ carrier_per_signal = (int)((double) samp_rate * chiptime_us/(1000000*BASEBAND_SAMPLES_PER_CHIP) + 0.5); - printf("Cps : %d\n", carrier_per_signal); + printf("Cps :\t%d\n", carrier_per_signal); #ifndef _WIN32 sigact.sa_handler = sighandler; sigemptyset(&sigact.sa_mask); @@ -514,9 +539,6 @@ int main(int argc, char **argv) out: fl2k_close(dev); - if (file != stdin) - fclose(file); - free(ampbuf); free(slopebuf); free(buf1); -- cgit v1.2.3 From bb6d47bb0d3a77b889174fe2e9df223b540505c0 Mon Sep 17 00:00:00 2001 From: Felix Erckenbrecht Date: Sat, 2 Nov 2019 20:40:32 +0100 Subject: Precalculate baseband samples --- src/fl2k_garage.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/fl2k_garage.c') diff --git a/src/fl2k_garage.c b/src/fl2k_garage.c index 575c3ad..f1c41a4 100644 --- a/src/fl2k_garage.c +++ b/src/fl2k_garage.c @@ -475,7 +475,7 @@ int main(int argc, char **argv) slopebuf = malloc(BUFFER_SAMPLES * sizeof(double)); ampbuf = malloc(BUFFER_SAMPLES * sizeof(double)); slopebuf = malloc(BUFFER_SAMPLES * sizeof(double)); - sample_buf = malloc(BASEBAND_SAMPLES_PER_CHIP * BASEBAND_CHIPS_TOTAL); + sample_buf = malloc((BASEBAND_SAMPLES_PER_CHIP * BASEBAND_CHIPS_TOTAL) * sizeof(int16_t)); readpos = 0; writepos = 1; -- cgit v1.2.3 From 1574d2db000356d761316e1f0043051f511512bb Mon Sep 17 00:00:00 2001 From: Felix Erckenbrecht Date: Sat, 2 Nov 2019 21:02:06 +0100 Subject: Rename mutexes --- src/fl2k_garage.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) (limited to 'src/fl2k_garage.c') diff --git a/src/fl2k_garage.c b/src/fl2k_garage.c index f1c41a4..e3d462b 100644 --- a/src/fl2k_garage.c +++ b/src/fl2k_garage.c @@ -68,13 +68,10 @@ fl2k_dev_t *dev = NULL; int do_exit = 0; -pthread_t fm_thread; pthread_t am_thread; pthread_mutex_t cb_mutex; -pthread_mutex_t fm_mutex; pthread_mutex_t am_mutex; pthread_cond_t cb_cond; -pthread_cond_t fm_cond; pthread_cond_t am_cond; int16_t *sample_buf; @@ -117,7 +114,7 @@ sighandler(int signum) fprintf(stderr, "Signal caught, exiting!\n"); fl2k_stop_tx(dev); do_exit = 1; - pthread_cond_signal(&fm_cond); + pthread_cond_signal(&am_cond); return TRUE; } return FALSE; @@ -128,7 +125,7 @@ static void sighandler(int signum) fprintf(stderr, "Signal caught, exiting!\n"); fl2k_stop_tx(dev); do_exit = 1; - pthread_cond_signal(&fm_cond); + pthread_cond_signal(&am_cond); } #endif @@ -343,7 +340,7 @@ void am_modulator(const int code_input) writepos %= BUFFER_SAMPLES; } } else { - pthread_cond_wait(&fm_cond, &fm_mutex); + pthread_cond_wait(&am_cond, &am_mutex); } } } @@ -396,7 +393,7 @@ void fl2k_callback(fl2k_data_info_t *data_info) if (data_info->device_error) { fprintf(stderr, "Device error, exiting.\n"); do_exit = 1; - pthread_cond_signal(&fm_cond); + pthread_cond_signal(&am_cond); } pthread_cond_signal(&cb_cond); @@ -486,10 +483,8 @@ int main(int argc, char **argv) fprintf(stderr, "Chip period:\t%d us\n", chiptime_us); pthread_mutex_init(&cb_mutex, NULL); - pthread_mutex_init(&fm_mutex, NULL); pthread_mutex_init(&am_mutex, NULL); pthread_cond_init(&cb_cond, NULL); - pthread_cond_init(&fm_cond, NULL); pthread_cond_init(&am_cond, NULL); pthread_attr_init(&attr); -- cgit v1.2.3 From 6f8e7dc277ae1f7827d16a1da8c5d3817556ec42 Mon Sep 17 00:00:00 2001 From: Felix Erckenbrecht Date: Sun, 24 Nov 2019 01:19:11 +0100 Subject: Bugfix: Generate proper baseband - code was shifted by one bit --- src/fl2k_garage.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/fl2k_garage.c') diff --git a/src/fl2k_garage.c b/src/fl2k_garage.c index e3d462b..d50922e 100644 --- a/src/fl2k_garage.c +++ b/src/fl2k_garage.c @@ -355,8 +355,8 @@ void prepare_baseband(const int code_input, int16_t * sbuf){ msb_first_code = 0; // change to msb first and invert for(b = 0;b<12;b++){ - msb_first_code |= code_input & (1<>= 1; + if(b == BASEBAND_SAMPLES_PER_CHIP-1){ + msb_first_code >>= 1; + } } } sbuf[counter * BASEBAND_SAMPLES_PER_CHIP + b] = sample; -- cgit v1.2.3