UHSDR/UHSDR-active-devel/mchf-eclipse/drivers/audio/softdds/softdds.c
2022-11-08 16:13:55 +01:00

158 lines
5.2 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 **
************************************************************************************/
// Credits - SDR cube!!!
// Common
#include "uhsdr_board.h"
#include "dds_table.h"
#include "softdds.h"
// Two Tone Dds
soft_dds_t dbldds[2];
uint32_t softdds_stepForSampleRate(float32_t freq, uint32_t samp_rate)
{
uint64_t freq64_shifted = freq * DDS_TBL_SIZE;
freq64_shifted <<= SOFTDDS_ACC_SHIFT;
uint64_t step = freq64_shifted / samp_rate;
return step;
}
/**
* Initialize softdds for given frequency and sample rate
*/
void softdds_setFreqDDS(soft_dds_t* softdds_p, float32_t freq, uint32_t samp_rate,uint8_t smooth)
{
// Reset accumulator, if need smooth tone
// transition, do not reset it (e.g. wspr)
if(smooth == false)
{
softdds_p->acc = 0;
}
// Calculate new step
softdds_p->step = softdds_stepForSampleRate(freq,samp_rate);
}
/**
* Initialize softdds for given frequency and sample rate
*/
void softdds_configRunIQ(float freq[2],uint32_t samp_rate,uint8_t smooth)
{
softdds_setFreqDDS(&dbldds[0],freq[0],samp_rate,smooth);
softdds_setFreqDDS(&dbldds[1],freq[1],samp_rate,smooth);
}
void softdds_genIQSingleTone(soft_dds_t* dds, float32_t *i_buff,float32_t *q_buff,uint16_t size)
{
for(uint16_t i = 0; i < size; i++)
{
// Calculate next sample
uint32_t k = softdds_nextSampleIndex(dds);
// Load I value (sin)
*i_buff = DDS_TABLE[k];
// -90 degrees shift (cos)
// Load Q value
*q_buff = DDS_TABLE[softdds_phase_shift90(k)];
// Next ptr
i_buff++;
q_buff++;
}
}
/*
* Generates the addition of two sinus frequencies as IQ data stream
* min/max value is +/-2^15-1
* Frequencies need to be configured using softdds_setfreq_dbl
*/
void softdds_genIQTwoTone(soft_dds_t* ddsA, soft_dds_t* ddsB, float *i_buff,float *q_buff,ushort size)
{
for(int i = 0; i < size; i++)
{
uint32_t k[2];
// Calculate next sample
k[0] = softdds_nextSampleIndex(ddsA);
k[1] = softdds_nextSampleIndex(ddsB);
// Load I value 0.5*(sin(a)+sin(b))
*i_buff = ((int32_t)DDS_TABLE[k[0]] + (int32_t)DDS_TABLE[k[1]])/2;
*q_buff = ((int32_t)DDS_TABLE[softdds_phase_shift90(k[0])] + (int32_t)DDS_TABLE[softdds_phase_shift90(k[1])])/2;
// Next ptr
i_buff++;
q_buff++;
}
}
/**
* Overlays an audio stream with a beep signal
* @param dds The previously initialized dds configuration
* @param buffer audio buffer of blockSize (mono/single channel) samples
* @param blockSize
* @param scaling scale the resulting sine wave with this factor
*/
void softdds_addSingleTone(soft_dds_t* dds_ptr, float32_t* buffer, const size_t blockSize, float32_t scaling)
{
for(int i=0; i < blockSize; i++) // transfer to DMA buffer and do conversion to INT
{
buffer[i] += (float32_t)softdds_nextSample(dds_ptr) * scaling; // load indexed sine wave value, adding it to audio, scaling the amplitude and putting it on "b" - speaker (ONLY)
}
}
/**
* Overlays an audio stream with a beep signal
* @param dds The previously initialized dds configuration
* @param buffer1 audio buffer of blockSize (mono/single channel) samples
* @param buffer2 audio buffer of blockSize (mono/single channel) samples
* @param blockSize
* @param scaling scale the resulting sine wave with this factor
*/
void softdds_addSingleToneToTwobuffers(soft_dds_t* dds_ptr, float32_t* buffer1, float32_t* buffer2, const size_t blockSize, float32_t scaling)
{
float32_t Tone;
for(int i=0; i < blockSize; i++) // transfer to DMA buffer and do conversion to INT
{
Tone=(float32_t) softdds_nextSample(dds_ptr) * scaling; // load indexed sine wave value, adding it to audio, scaling the amplitude and putting it on "b" - speaker (ONLY)
buffer1[i] += Tone;
buffer2[i] += Tone;
}
}
/*
* Generates the sinus frequencies as IQ data stream
* min/max value is +/-2^15-1
* Frequency needs to be configured using softdds_setfreq
*/
void softdds_runIQ(float32_t *i_buff,float32_t *q_buff,uint16_t size)
{
if (dbldds[1].step>0.0)
{
softdds_genIQTwoTone(&dbldds[0], &dbldds[1], i_buff, q_buff,size);
}
else
{
softdds_genIQSingleTone(&dbldds[0],i_buff,q_buff,size);
}
}