683 lines
27 KiB
C
683 lines
27 KiB
C
/* -*- mode: c; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4; coding: utf-8 -*- */
|
|
/************************************************************************************
|
|
** **
|
|
** mcHF QRP Transceiver **
|
|
** K Atanassov - M0NKA 2014 **
|
|
** **
|
|
**---------------------------------------------------------------------------------**
|
|
** **
|
|
** File name: **
|
|
** Description: **
|
|
** Last Modified: **
|
|
** Licence: GNU GPLv3 **
|
|
************************************************************************************/
|
|
|
|
/* Define to prevent recursive inclusion -------------------------------------*/
|
|
#ifndef __AUDIO_DRIVER_H
|
|
#define __AUDIO_DRIVER_H
|
|
|
|
#include "uhsdr_board_config.h"
|
|
#include "uhsdr_types.h"
|
|
#include "arm_math.h"
|
|
#include "softdds.h"
|
|
#include "audio_filter.h"
|
|
|
|
#define IQ_SAMPLE_RATE_F ((float32_t)IQ_SAMPLE_RATE)
|
|
|
|
#define AUDIO_SAMPLE_RATE_F ((float32_t)AUDIO_SAMPLE_RATE)
|
|
|
|
|
|
|
|
#if defined(USE_32_IQ_BITS)
|
|
typedef int32_t iq_data_t;
|
|
#else
|
|
typedef int16_t iq_data_t;
|
|
#endif
|
|
|
|
#if defined(USE_32_AUDIO_BITS)
|
|
typedef int32_t audio_data_t;
|
|
#else
|
|
typedef int16_t audio_data_t;
|
|
#endif
|
|
|
|
|
|
typedef struct {
|
|
__packed audio_data_t l;
|
|
__packed audio_data_t r;
|
|
} AudioSample_t;
|
|
|
|
typedef struct {
|
|
__packed iq_data_t l;
|
|
__packed iq_data_t r;
|
|
} IqSample_t;
|
|
|
|
#ifdef USE_CONVOLUTION
|
|
typedef struct {
|
|
COMP samples[SAMPLE_BUFFER_SIZE];
|
|
} Sample_Buffer;
|
|
#endif
|
|
|
|
// -----------------------------
|
|
// FFT buffer, this is double the size of the length of the FFT used for spectrum display and waterfall spectrum
|
|
#ifdef USE_FFT_1024
|
|
#define FFT_IQ_BUFF_LEN 1024
|
|
#else
|
|
#define FFT_IQ_BUFF_LEN 512
|
|
#endif
|
|
#define SPEC_BUFF_LEN (FFT_IQ_BUFF_LEN/2)
|
|
|
|
// twice the number of samples in the each iq block buffer
|
|
// (which is half of the total dma buffer, since in each interrupt we get half of the total dma buffer)
|
|
#define IQ_BUFSZ (2*IQ_BLOCK_SIZE)
|
|
#define AUDIO_BUFSZ (2*AUDIO_BLOCK_SIZE)
|
|
|
|
// Audio filter
|
|
#define FIR_RXAUDIO_BLOCK_SIZE IQ_BLOCK_SIZE
|
|
#define FIR_RXAUDIO_NUM_TAPS 16 // maximum number of taps in the decimation and interpolation FIR filters
|
|
#define IIR_RXAUDIO_BLOCK_SIZE IQ_BLOCK_SIZE
|
|
#define IIR_RXAUDIO_NUM_STAGES_MAX 12 // we use a maximum stage number of 10 at the moment, so this is 12 just to be safe
|
|
//
|
|
#define CODEC_DEFAULT_GAIN 0x1F // Gain of line input to start with
|
|
#define ADC_CLIP_WARN_THRESHOLD 4096 // This is at least 12dB below the clipping threshold of the A/D converter itself
|
|
//
|
|
//
|
|
//
|
|
#define SCALING_FACTOR_IQ_PHASE_ADJUST 2000.0
|
|
#define SCALING_FACTOR_IQ_AMPLITUDE_ADJUST 2731.0
|
|
|
|
#define SAM_PLL_HILBERT_STAGES 7
|
|
|
|
|
|
#ifdef USE_TWO_CHANNEL_AUDIO
|
|
#define NUM_AUDIO_CHANNELS 2
|
|
#else
|
|
#define NUM_AUDIO_CHANNELS 1
|
|
#endif
|
|
|
|
typedef struct
|
|
{
|
|
|
|
// for SAM demodulation
|
|
// DX adjustments: zeta = 0.15, omegaN = 100.0
|
|
// very stable, but does not lock very fast
|
|
// standard settings: zeta = 1.0, omegaN = 250.0
|
|
// maybe user can choose between slow (DX), medium, fast SAM PLL
|
|
// zeta / omegaN
|
|
// DX = 0.2, 70
|
|
// medium 0.6, 200
|
|
// fast 1.2, 500
|
|
|
|
|
|
//pll
|
|
float32_t omega_min; // (2.0 * 3.141592653589793f * pll_fmin * DF / IQ_SAMPLE_RATE_F);
|
|
float32_t omega_max; //(2.0 * 3.141592653589793f * pll_fmax * DF / IQ_SAMPLE_RATE_F);
|
|
float32_t g1; //(1.0 - exp(-2.0 * omegaN * zeta * DF / IQ_SAMPLE_RATE_F));
|
|
float32_t g2; //(- g1 + 2.0 * (1 - exp(- omegaN * zeta * DF / IQ_SAMPLE_RATE_F)
|
|
// * cosf(omegaN * DF / IQ_SAMPLE_RATE_F * sqrtf(1.0 - zeta * zeta))));
|
|
|
|
//fade leveler
|
|
float32_t mtauR; //(exp(- DF / (IQ_SAMPLE_RATE_F * tauR))); //0.99948;
|
|
float32_t onem_mtauR;
|
|
float32_t mtauI; //(exp(- DF / (IQ_SAMPLE_RATE_F * tauI))); //0.99999255955;
|
|
float32_t onem_mtauI;
|
|
} demod_sam_param_t;
|
|
|
|
typedef struct
|
|
{
|
|
float32_t teta1;
|
|
float32_t teta2;
|
|
float32_t teta3;
|
|
float32_t teta1_old;
|
|
float32_t teta2_old;
|
|
float32_t teta3_old;
|
|
float32_t M_c1;
|
|
float32_t M_c2;
|
|
} iq_correction_data_t;
|
|
|
|
typedef float32_t audio_block_t[AUDIO_BLOCK_SIZE];
|
|
typedef float32_t iq_block_t[IQ_BLOCK_SIZE];
|
|
|
|
typedef struct
|
|
{
|
|
iq_block_t i_buffer;
|
|
iq_block_t q_buffer;
|
|
} iq_buffer_t;
|
|
|
|
|
|
typedef struct
|
|
{
|
|
// Stereo buffers
|
|
iq_buffer_t iq_buf;
|
|
float32_t agc_valbuf[IQ_BLOCK_SIZE]; // holder for "running" AGC value
|
|
|
|
audio_block_t a_buffer[2];
|
|
|
|
demod_sam_param_t sam;
|
|
iq_correction_data_t iq_corr;
|
|
} AudioDriverBuffer;
|
|
|
|
|
|
typedef struct
|
|
{
|
|
float sql_avg; // averaged squelch level (for FM)
|
|
bool squelched; // TRUE if FM receiver audio is to be squelched
|
|
|
|
float subaudible_tone_gen_freq; // frequency, in Hz, of currently-selected subaudible tone for generation
|
|
soft_dds_t subaudible_tone_dds;
|
|
|
|
soft_dds_t tone_burst_dds;
|
|
bool tone_burst_active; // this is TRUE if the tone burst is actively being generated
|
|
//
|
|
float subaudible_tone_det_freq; // frequency, in Hz, of currently-selected subaudible tone for detection
|
|
bool subaudible_tone_detected; // TRUE if subaudible tone has been detected
|
|
|
|
Goertzel goertzel[3];
|
|
#define FM_HIGH 0
|
|
#define FM_LOW 1
|
|
#define FM_CTR 2
|
|
|
|
} fm_conf_t;
|
|
|
|
typedef enum
|
|
{
|
|
SAM_SIDEBAND_BOTH = 0,
|
|
SAM_SIDEBAND_LSB,
|
|
SAM_SIDEBAND_USB,
|
|
#ifdef USE_TWO_CHANNEL_AUDIO
|
|
SAM_SIDEBAND_STEREO,
|
|
#endif
|
|
SAM_SIDEBAND_MAX
|
|
} sam_sideband_t;
|
|
|
|
|
|
typedef struct
|
|
{
|
|
#define DSP_NR_ENABLE 0x01 // DSP NR mode is on (| 1)
|
|
#define DSP_NR_POSTAGC_ENABLE 0x02 // DSP NR is to occur post AGC (| 2)
|
|
#define DSP_NOTCH_ENABLE 0x04 // DSP Notch mode is on (| 4)
|
|
#define DSP_NB_ENABLE 0x08 // DSP is to be displayed on screen instead of NB (| 8)
|
|
#define DSP_MNOTCH_ENABLE 0x10 // Manual Notch enabled
|
|
#define DSP_MPEAK_ENABLE 0x20 // Manual Peak enabled
|
|
#define DSP_ANR_ENABLE 0x40 // DSP ANR (Leak LMS) mode is on
|
|
|
|
uint8_t active; // Used to hold various aspects of DSP mode selection
|
|
uint8_t mode; // holds the mode chosen in the DSP
|
|
uint16_t mode_mask; // holds the DSP mode mask (to be chosen by virtual dsp keyboard)
|
|
uint8_t active_toggle; // holder used on the press-hold of button G2 to "remember" the previous setting
|
|
uint8_t nr_strength; // "Strength" of DSP Noise reduction - to be converted to "Mu" factor
|
|
#if defined (USE_LMS_AUTONOTCH)
|
|
uint8_t notch_numtaps;
|
|
uint8_t notch_mu;
|
|
// mu adjust of notch DSP LMS
|
|
uint8_t notch_delaybuf_len; // size of DSP notch delay buffer
|
|
#endif
|
|
uint8_t inhibit; // if != 0, DSP (NR, Notch) functions are inhibited. Used during power-up and switching
|
|
uint8_t nb_setting;
|
|
ulong notch_frequency; // frequency of the manual notch filter
|
|
ulong peak_frequency; // frequency of the manual peak filter
|
|
|
|
int bass_gain; // gain of the low shelf EQ filter
|
|
int treble_gain; // gain of the high shelf EQ filter
|
|
// int tx_bass_gain; // gain of the TX low shelf EQ filter
|
|
// int tx_treble_gain; // gain of the TX high shelf EQ filter
|
|
int tx_eq_gain[5]; // gain of the TX 5-bands EQ filter
|
|
|
|
} dsp_params_t;
|
|
|
|
// Audio driver publics
|
|
typedef struct AudioDriverState
|
|
{
|
|
//
|
|
// Lock audio filter flag
|
|
//
|
|
volatile bool af_disabled; // if TRUE, audio filtering is disabled (used during filter bandwidth changing, etc.)
|
|
volatile bool tx_filter_adjusting; // used to disable TX I/Q filter during phase adjustment
|
|
|
|
float codec_gain_calc; // spectrum gain value
|
|
|
|
bool adc_clip; // used to display warning in s meter
|
|
bool adc_half_clip; // used to control input gain and spectrum gain
|
|
bool adc_quarter_clip; // used to control input gain and spectrum gain
|
|
float peak_audio; // used for audio metering to detect the peak audio level
|
|
|
|
float alc_val; // "live" transmitter ALC value
|
|
float alc_decay; // decay rate (speed) of ALC
|
|
|
|
uchar decimation_rate; // current decimation/interpolation rate
|
|
uint32_t decimated_freq; // resulting decimated sample frequency (used in iq and audio processing)
|
|
|
|
fm_conf_t fm_conf; // configuration parameters for the fm demodulator
|
|
|
|
soft_dds_t beep; // this is the actively-used DDS tone word for the radio's beep generator
|
|
float beep_loudness_factor; // this is used to set the beep loudness
|
|
|
|
/* SAM */
|
|
// sam related output variables
|
|
int carrier_freq_offset;
|
|
|
|
// sam related configuration parameters, stored in config memory
|
|
int pll_fmax_int;
|
|
int zeta_int; // zeta * 100
|
|
int omegaN_int;
|
|
uint8_t fade_leveler; // boolean
|
|
// sam related operation parameters, not stored in config memory
|
|
sam_sideband_t sam_sideband; // 0 = both, 1 = LSB, 2 = USB
|
|
|
|
/* IQ Balance */
|
|
float32_t iq_phase_balance_rx;
|
|
float32_t iq_phase_balance_tx[IQ_TRANS_NUM];
|
|
|
|
ulong snap_carrier_freq; // used for passing the estimated carrier freq in SNAP mode to the print routine in UI_Driver
|
|
bool CW_signal; // if CW decoder is enabled and carrier snap is wanted, this indicates whenever a pulse is received
|
|
// only in that case, the carrier frequency is estimated and the display refreshed
|
|
} AudioDriverState;
|
|
|
|
void AudioManagement_CalcIQPhaseAdjust(uint32_t freq);
|
|
|
|
// S meter public
|
|
typedef struct SMeter
|
|
{
|
|
// configurable ALPHA = 1 - e^(-T/Tau)
|
|
// we use alpha config value scaling of 100, i.e. 100 => alpha = 1.00
|
|
// this construct permits us to use a single configuration store for both
|
|
// it looks rather complex but this is necessary to ensure type safety checks are working
|
|
union {
|
|
uint16_t alphaCombined;
|
|
struct
|
|
{
|
|
uint8_t DecayAlpha;
|
|
uint8_t AttackAlpha;
|
|
} alphaSplit;
|
|
} config;
|
|
|
|
// first/upper 8 bits is AttackAlpha
|
|
// second/lower 8 bits is DecayAlpha
|
|
#define SMETER_ALPHA_ATTACK_DEFAULT 50
|
|
#define SMETER_ALPHA_DECAY_DEFAULT 5
|
|
#define SMETER_ALPHA_MIN 1 // used for both alphas
|
|
#define SMETER_ALPHA_MAX 100 // used for both alphas
|
|
|
|
// averaged values, used for display
|
|
float32_t dbm;
|
|
float32_t dbmhz;
|
|
|
|
// current measurements, used for averaging
|
|
float32_t dbm_cur;
|
|
float32_t dbmhz_cur;
|
|
|
|
// internal variables for dbm low pass calculation
|
|
float32_t AttackAvedbm;
|
|
float32_t DecayAvedbm;
|
|
float32_t AttackAvedbmhz;
|
|
float32_t DecayAvedbmhz;
|
|
|
|
uint32_t s_count; // number of S steps, used for display and CAT level
|
|
} SMeter;
|
|
|
|
|
|
#define MAX_BASS 20
|
|
#define MIN_BASS -20
|
|
#define MAX_TREBLE 20
|
|
#define MIN_TREBLE -20
|
|
//#define MAX_TX_BASS 5
|
|
//#define MIN_TX_BASS -20
|
|
//#define MAX_TX_TREBLE 5
|
|
//#define MIN_TX_TREBLE -20
|
|
#define MAX_TX_EQ 20
|
|
#define MIN_TX_EQ -20
|
|
|
|
#define MIN_PEAK_NOTCH_FREQ 200
|
|
//
|
|
// AGC Time constants
|
|
// C. Turner, KA7OEI
|
|
//
|
|
#define AGC_KNEE 1000//4000 // ADC "knee" threshold for AGC action
|
|
//
|
|
#define AGC_KNEE_REF 1000
|
|
#define AGC_VAL_MAX_REF 131072//4096
|
|
#define POST_AGC_GAIN_SCALING_REF 1.333
|
|
|
|
#define AGC_ATTACK 0.033 // Attack time multiplier for AGC
|
|
//
|
|
#define AGC_FAST_DECAY 0.0002 // Decay rate multiplier for "Fast" AGC
|
|
#define AGC_MED_DECAY 0.00006 // Decay rate multiplier for "Medium" AGC
|
|
#define AGC_SLOW_DECAY 0.00001 // Decay rate for multiplier "Slow" AGC
|
|
//
|
|
#define AGC_ATTACK_FM 0.0033 // Attack time for FM (S-meter reading only)
|
|
#define AGC_DECAY_FM 0.0333 // Decay time for FM (S-meter reading only)
|
|
//
|
|
|
|
#define AGC_VAL_MIN 0.02 // Minimum AGC gain multiplier (e.g. gain reduction of 34dB)
|
|
//#define AGC_VAL_MAX 4096//1024 // Maximum AGC gain multiplier (e.g. gain multiplication of 60dB)
|
|
|
|
#define AGC_PREFILTER_MAXGAIN 5 // Scaling factor for RF gain adjustment (e.g. factor by which RFG will be multiplied to yield actual RFG multiplier
|
|
#define AGC_PREFILTER_MINGAIN 0.5 // Minimum "RFG" gain multiplier (e.g. gain reduction of 6 dB)
|
|
//
|
|
#define AGC_PREFILTER_HISIG_THRESHOLD 0.1 // Threshold at which adjustment of RFGAIN (pre-filter) gain adjustment will occur
|
|
#define AGC_PREFILTER_LOWSIG_THRESHOLD 1.0 // Threshold at which adjustment of RFGAIN (pre-filter) gain adjustment will occur
|
|
#define AGC_PREFILTER_ATTACK_RATE 0.0002 // Attack rate for RFG reduction
|
|
#define AGC_PREFILTER_DECAY_RATE 0.000002 // Decay rate for RFG gain recovery
|
|
//
|
|
#define AGC_PREFILTER_MAX_SIGNAL 1 // maximum level of pre-filtered signal
|
|
//
|
|
#define POST_AGC_GAIN_SCALING 1.333//0.333 // Used to rescale the post-filter audio level to a value suitable for the codec. This sets the line level output
|
|
// to approx. 1000mV peak-peak.
|
|
//
|
|
#define POST_AGC_GAIN_SCALING_DECIMATE_4 3.46 // Used to scale audio from the decimation/interpolation-by-4 process (based square root of decimation factor)
|
|
//
|
|
#define POST_AGC_GAIN_SCALING_DECIMATE_2 (POST_AGC_GAIN_SCALING_DECIMATE_4 * 0.6) // Scales audio from decimation/interpolation-by-2 process
|
|
//
|
|
#define AM_SCALING 1.0 // was 2.0 // Amount of gain multiplication to apply to audio and AGC to make recovery equal to that of SSB
|
|
#define AM_AUDIO_SCALING 1.4 // was 1.4 // Additional correction factor applied to audio demodulation to make amplitude equal to that of SSB demodulation
|
|
//
|
|
//#define AGC_GAIN_CAL 155000.0//22440 // multiplier value (linear, not DB) to calibrate the S-Meter reading to the AGC value
|
|
//
|
|
#define AUTO_RFG_DECREASE_LOCKOUT 1
|
|
#define AUTO_RFG_INCREASE_TIMER 5//10
|
|
//
|
|
//#define AGC_SLOW 0 // Mode setting for slow AGC
|
|
//#define AGC_MED 1 // Mode setting for medium AGC
|
|
//#define AGC_FAST 2 // Mode setting for fast AGC
|
|
//#define AGC_CUSTOM 3 // Mode setting for custom AGC
|
|
//#define AGC_OFF 4 // Mode setting for AGC off
|
|
//#define AGC_MAX_MODE 4 // Maximum for mode setting for AGC
|
|
//#define AGC_DEFAULT AGC_MED // Default!
|
|
//
|
|
//#define AGC_CUSTOM_MAX 30 // Maximum (slowest) setting for custom AGC
|
|
//#define AGC_CUSTOM_DEFAULT 12 // Default custom AGC setting (approx. equal to "medium")
|
|
//#define AGC_CUSTOM_FAST_WARNING 2 // Value at or below which setting the custom AGC is likely to degrade audio
|
|
//
|
|
#define MAX_RF_GAIN_MAX 30 // Maximum setting for "Max RF gain"
|
|
#define MAX_RF_GAIN_DEFAULT 10
|
|
|
|
// Noise blanker constants
|
|
#define MAX_NB_SETTING 15
|
|
#define NB_WARNING1_SETTING 7 // setting at or above which NB warning1 (yellow) is given
|
|
#define NB_WARNING2_SETTING 12 // setting at or above which NB warning2 (orange) is given
|
|
#define NB_WARNING3_SETTING 15 // setting at or above which NB warning3 (red) is given
|
|
|
|
// Values used for "custom" AGC settings
|
|
#define LINE_OUT_SCALING_FACTOR 10 // multiplication of audio for fixed LINE out level (nominally 1vpp)
|
|
//
|
|
#define LINE_IN_GAIN_RESCALE 20 // multiplier for line input gain
|
|
#define MIC_GAIN_RESCALE 2 // divisor for microphone gain setting
|
|
|
|
|
|
// ALC (Auto Level Control) for transmitter, constants
|
|
#define ALC_VAL_MAX 1 // Maximum ALC Value is 1 (e.g. it can NEVER amplify)
|
|
#define ALC_VAL_MIN 0.001 // Minimum ALC Value - it can provide up to 60dB of attenuation
|
|
#define ALC_ATTACK 0.1//0.033 // Attack time for the ALC's gain control
|
|
#define ALC_KNEE 30000 // The audio value threshold for the ALC operation
|
|
|
|
// Decay (release time) for ALC/Audio compressor
|
|
#define ALC_DECAY_MAX 20 // Maximum (slowest) setting for ALC decay
|
|
#define ALC_DECAY_DEFAULT 10 // Default custom ALC setting (approx. equal to AGC "medium")
|
|
|
|
// Audio post-filter (pre-alc) gain adjust. This effectively sets the min/max compression level.
|
|
#define ALC_POSTFILT_GAIN_MIN 1
|
|
#define ALC_POSTFILT_GAIN_MAX 25
|
|
#define ALC_POSTFILT_GAIN_DEFAULT 1
|
|
//
|
|
#define SSB_ALC_GAIN_CORRECTION 1.00 // This scales the output of the ALC for 100% modulation for SSB transmission
|
|
//
|
|
#define SSB_GAIN_COMP 1.133 // This compensates for slight differences in gain processing in the SSB algorithm (empirically derived)
|
|
//
|
|
#define AM_GAIN_COMP 1.133 // This compensates for slight differences in gain processing in the AM algorithm (empirically derived)
|
|
//
|
|
#define FREEDV_GAIN_COMP (20*SSB_GAIN_COMP)
|
|
|
|
// The following are calibration constants for AM (transmitter) modulation, carefully adjusted for proper D/A scaling to set
|
|
// maximum possible 95-100% AM modulation depth.
|
|
//
|
|
#define AM_ALC_GAIN_CORRECTION 0.23 // This scales the output of the ALC for 100% modulation with respect to the carrier level
|
|
#define AM_CARRIER_LEVEL 5100 // This sets the AM carrier level in DAC units, scaled for proper ALC operation and 100% modulation
|
|
//
|
|
// DO NOT change the above unless you know *EXACTLY* what you are doing! If you screw with these numbers, you WILL wreck the
|
|
// AM modulation!!! (No, I'm not kidding!)
|
|
|
|
// FM TX/RX
|
|
#define NUM_SUBAUDIBLE_TONES 56
|
|
#define FM_SUBAUDIBLE_TONE_OFF 0
|
|
|
|
// FM TX
|
|
|
|
#define FM_TONE_BURST_MAX 2
|
|
extern uint32_t fm_tone_burst_freq[FM_TONE_BURST_MAX+1];
|
|
|
|
#define FM_TONE_BURST_OFF 0
|
|
|
|
#define FM_TONE_BURST_DURATION 100 // duration, in 100ths of a second, of the tone burst
|
|
|
|
// FM RX
|
|
#define FM_SQUELCH_MAX 20 // maximum setting for FM squelch
|
|
#define FM_SQUELCH_DEFAULT 12 // default setting for FM squelch
|
|
#define FM_SUBAUDIBLE_GOERTZEL_WINDOW 400 // this sets the overall number of samples involved in the Goertzel decode windows (this value * "size/2")
|
|
|
|
|
|
#define MIN_BEEP_FREQUENCY 200 // minimum beep frequency in Hz
|
|
#define MAX_BEEP_FREQUENCY 3000 // maximum beep frequency in Hz
|
|
#define DEFAULT_BEEP_FREQUENCY 1000 // default beep frequency in Hz
|
|
|
|
#define BEEP_DURATION 2 // duration of beep in 100ths of a second
|
|
|
|
#define MAX_BEEP_LOUDNESS 21 // maximum setting for beep loudness
|
|
#define DEFAULT_BEEP_LOUDNESS 10 // default loudness for the keyboard beep
|
|
|
|
// Factors used in audio compressor adjustment limits
|
|
//
|
|
#define TX_AUDIO_COMPRESSION_MIN -1 // -1 = OFF
|
|
#define TX_AUDIO_COMPRESSION_MAX 13 // 0 = least compression, 12 = most, 13 = EEPROM values ("CUS" = CUSTOM) - custom selected by user
|
|
#define TX_AUDIO_COMPRESSION_SV 13
|
|
#define TX_AUDIO_COMPRESSION_DEFAULT 2
|
|
//
|
|
//
|
|
#define RX_DECIMATION_RATE_8KHZ 6 // Decimation/Interpolation rate in receive function for 8 kHz sample rate
|
|
#define RX_DECIMATION_RATE_12KHZ 4 // Decimation/Interpolation rate in receive function for 12 kHz sample rate
|
|
#define RX_DECIMATION_RATE_24KHZ 2 // Decimation/Interpolation rate in receive function for 24 kHz sample rate
|
|
#define RX_DECIMATION_RATE_48KHZ 1 // Deimcation/Interpolation rate in receive function for 48 kHz sample rate (e.g. no decimation!)
|
|
|
|
#define DSP_NR_STRENGTH_MIN 1
|
|
#define DSP_NR_STRENGTH_MAX 200 // Maximum menu setting for DSP "Strength"
|
|
#define DSP_NR_STRENGTH_STEP 5
|
|
#define DSP_NR_STRENGTH_DEFAULT 160 // Default setting
|
|
|
|
#ifdef USE_LMS_AUTONOTCH
|
|
//
|
|
// Automatic Notch Filter
|
|
//
|
|
#define LMS_NOTCH_DELAYBUF_SIZE_MAX 512
|
|
//
|
|
#define DSP_NOTCH_NUMTAPS_MAX 64//128
|
|
#define DSP_NOTCH_NUMTAPS_MIN 64
|
|
#define DSP_NOTCH_NUMTAPS_DEFAULT 64//96
|
|
//
|
|
#define DSP_NOTCH_BUFLEN_MIN 128//64//48 // minimum length of decorrelation buffer for the notch filter FIR
|
|
#define DSP_NOTCH_BUFLEN_MAX 128//192 // maximum decorrelation buffer length for the notch filter FIR
|
|
#define DSP_NOTCH_DELAYBUF_DEFAULT 128//104 // default decorrelation buffer length for the notch filter FIR
|
|
//
|
|
#define DSP_NOTCH_MU_MAX 40//40 // maximum "strength" (convergence) setting for the notch
|
|
#define DSP_NOTCH_MU_DEFAULT 10//25 // default convergence setting for the notch
|
|
#endif
|
|
|
|
typedef enum
|
|
{
|
|
DSP_SWITCH_OFF = 0,
|
|
DSP_SWITCH_NR,
|
|
DSP_SWITCH_ANR,
|
|
DSP_SWITCH_NOTCH,
|
|
DSP_SWITCH_NR_AND_NOTCH,
|
|
DSP_SWITCH_NOTCH_MANUAL,
|
|
DSP_SWITCH_PEAK_FILTER,
|
|
DSP_SWITCH_MAX, // bass & treble not used here
|
|
DSP_SWITCH_BASS = 98,
|
|
DSP_SWITCH_TREBLE = 99,
|
|
} dsp_mode_t;
|
|
|
|
typedef enum
|
|
{
|
|
ModeVK_SSB = 0,
|
|
ModeVK_CW,
|
|
ModeVK_AM,
|
|
ModeVK_SAM,
|
|
ModeVK_FM,
|
|
ModeVK_RTTY,
|
|
ModeVK_BPSK,
|
|
ModeVK_FDV,
|
|
ModeVK_SWITCH_MAX,
|
|
} ModeVK_t;
|
|
|
|
#define DSP_SWITCH_MODEMASK_ENABLE_MASK ((1<<DSP_SWITCH_MAX)-1)
|
|
#define DSP_SWITCH_MODEMASK_ENABLE_DEFAULT ((1<<DSP_SWITCH_MAX)-1)
|
|
#define DSP_SWITCH_MODEMASK_ENABLE_DSPOFF (1<<DSP_SWITCH_OFF)
|
|
|
|
//
|
|
#define AUDIO_DELAY_BUFSIZE (IQ_BUFSZ)*5 // Size of AGC delaying audio buffer - Must be a multiple of IQ_BUFSZ.
|
|
// This is divided by the decimation rate so that the time delay is constant.
|
|
|
|
|
|
#define FREQ_IQ_CONV_MODE_OFF 0 // No frequency conversion
|
|
#define FREQ_IQ_CONV_P6KHZ 1 // LO is 6KHz above receive frequency in RX mode
|
|
#define FREQ_IQ_CONV_M6KHZ 2 // LO is 6KHz below receive frequency in RX mode
|
|
#define FREQ_IQ_CONV_P12KHZ 3 // LO is 12KHz above receive frequency in RX mode
|
|
#define FREQ_IQ_CONV_M12KHZ 4 // LO is 12KHz below receive frequency in RX mode
|
|
#define FREQ_IQ_CONV_SLIDE 5 // LO slide frequency in RX mode
|
|
//
|
|
#define FREQ_IQ_CONV_MODE_DEFAULT FREQ_IQ_CONV_M12KHZ //FREQ_IQ_CONV_MODE_OFF
|
|
#define FREQ_IQ_CONV_MODE_MAX 5
|
|
|
|
// Public Audio
|
|
extern AudioDriverState ads;
|
|
extern SMeter sm;
|
|
|
|
extern AudioDriverBuffer adb;
|
|
|
|
typedef struct SnapCarrier
|
|
{
|
|
bool snap;
|
|
} SnapCarrier;
|
|
|
|
extern SnapCarrier sc;
|
|
|
|
|
|
|
|
|
|
#ifdef USE_LEAKY_LMS
|
|
#define LEAKYLMSDLINE_SIZE 256 //512 // was 256 //2048 // dline_size
|
|
// 1024 funktioniert nicht
|
|
typedef struct
|
|
{// Automatic noise reduction
|
|
// Variable-leak LMS algorithm
|
|
// taken from (c) Warren Pratts wdsp library 2016
|
|
// GPLv3 licensed
|
|
// #define DLINE_SIZE 256 //512 //2048 // dline_size
|
|
int16_t n_taps; // = 64; //64; // taps
|
|
int16_t delay; // = 16; //16; // delay
|
|
int dline_size; // = LEAKYLMSDLINE_SIZE;
|
|
//int ANR_buff_size = FFT_length / 2.0;
|
|
int position;// = 0;
|
|
float32_t two_mu;// = 0.0001; typical: 0.001 to 0.000001 = 1000 to 1 -> div by 1000000 // two_mu --> "gain"
|
|
uint32_t two_mu_int;
|
|
float32_t gamma;// = 0.1; typical: 1.000 to 0.001 = 1000 to 1 -> div by 1000 // gamma --> "leakage"
|
|
uint32_t gamma_int;
|
|
float32_t lidx;// = 120.0; // lidx
|
|
float32_t lidx_min;// = 0.0; // lidx_min
|
|
float32_t lidx_max;// = 200.0; // lidx_max
|
|
float32_t ngamma;// = 0.001; // ngamma
|
|
float32_t den_mult;// = 6.25e-10; // den_mult
|
|
float32_t lincr;// = 1.0; // lincr
|
|
float32_t ldecr;// = 3.0; // ldecr
|
|
//int ANR_mask = ANR_dline_size - 1;
|
|
int mask;// = DLINE_SIZE - 1;
|
|
int in_idx;// = 0;
|
|
float32_t d [LEAKYLMSDLINE_SIZE];
|
|
float32_t w [LEAKYLMSDLINE_SIZE];
|
|
uint8_t on;// = 0;
|
|
uint8_t notch;// = 0;
|
|
} lLMS;
|
|
|
|
extern lLMS leakyLMS;
|
|
#endif
|
|
|
|
// TODO: Discuss to drop 16 bit I2S support. Would simplify the incoming/outgoing data handling. We could
|
|
// align all scalings accordingly and would not have most of the ugly stuff below
|
|
// FIXME: This is ugly: The STM32F4 returns 32bit reads from 16 bit peripherals such as the SPI/I2S
|
|
// with the two half words in "mixed endian" instead of the wanted "little endian". This is documented in
|
|
// the data sheet, so the only thing we can do is to swap the halfwords. This is in fact a single ror16 operation
|
|
// if the compiler is smart enough to detect what we want.
|
|
|
|
|
|
// these constants are used to adjust the 32 bit integer samples to represent the same levels as if we sample 16 bit integers,
|
|
// effectively "shifting" them down or up.
|
|
// FIXME: switch to 16 bit extended mode for 16 bit samples will eliminate the need for this at the expense of
|
|
// using the same DMA memory (two times the memory true 16 bit values take, in our case this is 2*(2*(IQ_BLOCK_SIZE*2samples*2bytes) = 512 bytes)
|
|
#ifdef USE_32_IQ_BITS
|
|
#define IQ_BIT_SHIFT 16
|
|
#define IQ_BIT_SCALE_DOWN (0.0000152587890625)
|
|
#else
|
|
#define IQ_BIT_SHIFT 0
|
|
#define IQ_BIT_SCALE_DOWN (1.0)
|
|
#endif
|
|
#define IQ_BIT_SCALE_UP (1<<IQ_BIT_SHIFT)
|
|
#define IQ_BIT_SCALE_DOWN24 (0.0039)
|
|
|
|
#ifdef USE_32_AUDIO_BITS
|
|
#define AUDIO_BIT_SHIFT 16
|
|
#define AUDIO_BIT_SCALE_DOWN (0.0000152587890625)
|
|
#else
|
|
#define AUDIO_BIT_SHIFT 0
|
|
#define AUDIO_BIT_SCALE_DOWN (1.0)
|
|
#endif
|
|
#define AUDIO_BIT_SCALE_UP (1<<AUDIO_BIT_SHIFT)
|
|
|
|
// we have to swap them only if we are having 32bit values from/to I2S and an STM32F4
|
|
#if defined(STM32F4) && defined(USE_32_IQ_BITS)
|
|
static inline int32_t I2S_correctHalfWord(const int32_t word)
|
|
{
|
|
uint32_t uWord = (uint32_t)word;
|
|
return uWord >> 16 | uWord << 16;
|
|
}
|
|
|
|
static inline int16_t I2S_IqSample_2_Int16(const iq_data_t sample) { return (I2S_correctHalfWord(sample)) >> IQ_BIT_SHIFT; }
|
|
static inline int16_t I2S_AudioSample_2_Int16(const iq_data_t sample) { return (I2S_correctHalfWord(sample)) >> IQ_BIT_SHIFT; }
|
|
static inline iq_data_t I2S_Int16_2_IqSample(const int16_t sample) { return (I2S_correctHalfWord(sample << IQ_BIT_SHIFT)); }
|
|
static inline iq_data_t I2S_Int16_2_AudioSample(const int16_t sample) { return (I2S_correctHalfWord(sample << IQ_BIT_SHIFT)); }
|
|
|
|
#else
|
|
#define I2S_correctHalfWord(a) (a)
|
|
|
|
#if defined(USE_32_IQ_BITS)
|
|
static inline int16_t I2S_IqSample_2_Int16(const iq_data_t sample) { return sample >> 16; }
|
|
static inline iq_data_t I2S_Int16_2_IqSample(const int16_t sample) { return sample << 16; }
|
|
#else
|
|
static inline int16_t I2S_IqSample_2_Int16(const iq_data_t sample) { return sample; }
|
|
static inline iq_data_t I2S_Int16_2_IqSample(const int16_t sample) { return sample; }
|
|
#endif
|
|
#if defined(USE_32_AUDIO_BITS)
|
|
static inline int16_t I2S_AudioSample_2_Int16(const iq_data_t sample) { return sample >> 16; }
|
|
static inline iq_data_t I2S_Int16_2_AudioSample(const int16_t sample) { return sample << 16; }
|
|
#else
|
|
static inline int16_t I2S_AudioSample_2_Int16(const iq_data_t sample) { return sample; }
|
|
static inline iq_data_t I2S_Int16_2_AudioSample(const int16_t sample) { return sample; }
|
|
#endif
|
|
#endif
|
|
|
|
|
|
// Exports
|
|
void AudioDriver_Init(void);
|
|
void AudioDriver_SetProcessingChain(uint8_t dmod_mode, bool reset_dsp_nr);
|
|
int32_t AudioDriver_GetTranslateFreq(void);
|
|
void AudioDriver_SetSamPllParameters (void);
|
|
|
|
void AudioDriver_I2SCallback(AudioSample_t *audio, IqSample_t *iq, AudioSample_t *audioDst, int16_t size);
|
|
void AudioDriver_CalcPeakEQ(float32_t coeffs[5], float32_t f0, float32_t q, float32_t gain, float32_t FS);
|
|
|
|
void AudioDriver_CalcLowShelf(float32_t coeffs[5], float32_t f0, float32_t S, float32_t gain, float32_t FS);
|
|
void AudioDriver_CalcHighShelf(float32_t coeffs[5], float32_t f0, float32_t S, float32_t gain, float32_t FS);
|
|
void AudioDriver_CalcBandpass(float32_t coeffs[5], float32_t f0, float32_t FS);
|
|
void AudioDriver_SetBiquadCoeffs(float32_t* coeffsTo,const float32_t* coeffsFrom);
|
|
|
|
void AudioDriver_IQPhaseAdjust(uint16_t txrx_mode, float32_t* i_buffer, float32_t* q_buffer, const uint16_t blockSize);
|
|
void AudioDriver_AgcWdsp_Set(void);
|
|
|
|
#endif
|