// // This file is part of Dire Wolf, an amateur radio packet TNC. // // Copyright (C) 2011, 2012, 2013, 2015, 2019 John Langner, WB2OSZ // // 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 . // /*------------------------------------------------------------------ * * Name: dsp.c * * Purpose: Generate the filters used by the demodulators. * *----------------------------------------------------------------*/ #include "direwolf.h" #include #include #include #include #include #include #include #include "audio.h" #include "fsk_demod_state.h" #include "fsk_gen_filter.h" #include "textcolor.h" #include "dsp.h" #define MIN(a,b) ((a)<(b)?(a):(b)) #define MAX(a,b) ((a)>(b)?(a):(b)) // Don't remove this. It serves as a reminder that an experiment is underway. #if defined(TUNE_MS_FILTER_SIZE) || defined(TUNE_MS2_FILTER_SIZE) || defined(TUNE_AGC_FAST) || defined(TUNE_LPF_BAUD) || defined(TUNE_PLL_LOCKED) || defined(TUNE_PROFILE) #define DEBUG1 1 // Don't remove this. #endif /*------------------------------------------------------------------ * * Name: window * * Purpose: Filter window shape functions. * * Inputs: type - BP_WINDOW_HAMMING, etc. * size - Number of filter taps. * j - Index in range of 0 to size-1. * * Returns: Multiplier for the window shape. * *----------------------------------------------------------------*/ float window (bp_window_t type, int size, int j) { float center; float w; center = 0.5 * (size - 1); switch (type) { case BP_WINDOW_COSINE: w = cos((j - center) / size * M_PI); //w = sin(j * M_PI / (size - 1)); break; case BP_WINDOW_HAMMING: w = 0.53836 - 0.46164 * cos((j * 2 * M_PI) / (size - 1)); break; case BP_WINDOW_BLACKMAN: w = 0.42659 - 0.49656 * cos((j * 2 * M_PI) / (size - 1)) + 0.076849 * cos((j * 4 * M_PI) / (size - 1)); break; case BP_WINDOW_FLATTOP: w = 1.0 - 1.93 * cos((j * 2 * M_PI) / (size - 1)) + 1.29 * cos((j * 4 * M_PI) / (size - 1)) - 0.388 * cos((j * 6 * M_PI) / (size - 1)) + 0.028 * cos((j * 8 * M_PI) / (size - 1)); break; case BP_WINDOW_TRUNCATED: default: w = 1.0; break; } return (w); } /*------------------------------------------------------------------ * * Name: gen_lowpass * * Purpose: Generate low pass filter kernel. * * Inputs: fc - Cutoff frequency as fraction of sampling frequency. * filter_size - Number of filter taps. * wtype - Window type, BP_WINDOW_HAMMING, etc. * lp_delay_fract - Fudge factor for the delay value. * * Outputs: lp_filter * * Returns: Signal delay thru the filter in number of audio samples. * *----------------------------------------------------------------*/ void gen_lowpass (float fc, float *lp_filter, int filter_size, bp_window_t wtype) { int j; float G; #if DEBUG1 text_color_set(DW_COLOR_DEBUG); dw_printf ("Lowpass, size=%d, fc=%.2f\n", filter_size, fc); dw_printf (" j shape sinc final\n"); #endif assert (filter_size >= 3 && filter_size <= MAX_FILTER_SIZE); for (j=0; j= 3 && filter_size <= MAX_FILTER_SIZE); for (j=0; j -0.001 && t < 0.001) { sinc = 1; } else { sinc = sinf(M_PI * t) / (M_PI * t); } if (fabsf(a * t) > 0.499 && fabsf(a * t) < 0.501) { window = M_PI / 4; } else { window = cos(M_PI * a * t) / ( 1 - powf(2 * a * t, 2)); // This made nicer looking waveforms for generating signal. //window = cos(M_PI * a * t); // Do we want to let it go negative? // I think this would happen when a > 0.5 / (filter width in symbol times) if (window < 0) { //printf ("'a' is too large for range of 't'.\n"); //window = 0; } } result = sinc * window; #if DEBUGRRC // t should vary from - to + half of filter size in symbols. // Result should be 1 at t=0 and 0 at all other integer values of t. printf ("%.3f, %.3f, %.3f, %.3f\n", t, sinc, window, result); #endif return (result); } // The Root Raised Cosine (RRC) low pass filter is suppposed to minimize Intersymbol Interference (ISI). void gen_rrc_lowpass (float *pfilter, int filter_taps, float rolloff, float samples_per_symbol) { int k; float t; for (k = 0; k < filter_taps; k++) { t = (k - ((filter_taps - 1.0) / 2.0)) / samples_per_symbol; pfilter[k] = rrc (t, rolloff); } // Scale it for unity gain. t = 0; for (k = 0; k < filter_taps; k++) { t += pfilter[k]; } for (k = 0; k < filter_taps; k++) { pfilter[k] = pfilter[k] / t; } } /* end dsp.c */