[sky9x/Taranis] Audio mixer!

This commit is contained in:
bsongis@gmail.com
2013-06-15 16:18:08 +00:00
parent 46ae2e434a
commit f79e2aba4f
12 changed files with 524 additions and 576 deletions
+23 -41
View File
@@ -36,33 +36,22 @@
#include "../../opentx.h"
uint32_t currentFrequency = 0;
uint32_t getFrequency()
void setSampleRate(uint32_t frequency)
{
return currentFrequency;
}
register Tc *ptc ;
register uint32_t timer ;
void setFrequency(uint32_t frequency)
{
if (currentFrequency != frequency) {
currentFrequency = frequency;
timer = Master_frequency / (8 * frequency) ; // MCK/8 and 100 000 Hz
if (timer > 65535)
timer = 65535 ;
if (timer < 2)
timer = 2 ;
register Tc *ptc ;
register uint32_t timer ;
timer = Master_frequency / (8 * frequency) ; // MCK/8 and 100 000 Hz
if (timer > 65535)
timer = 65535 ;
if (timer < 2)
timer = 2 ;
ptc = TC0 ; // Tc block 0 (TC0-2)
ptc->TC_CHANNEL[1].TC_CCR = TC_CCR0_CLKDIS ; // Stop clock
ptc->TC_CHANNEL[1].TC_RC = timer ; // 100 000 Hz
ptc->TC_CHANNEL[1].TC_RA = timer >> 1 ;
ptc->TC_CHANNEL[1].TC_CCR = 5 ; // Enable clock and trigger it (may only need trigger)
}
ptc = TC0 ; // Tc block 0 (TC0-2)
ptc->TC_CHANNEL[1].TC_CCR = TC_CCR0_CLKDIS ; // Stop clock
ptc->TC_CHANNEL[1].TC_RC = timer ; // 100 000 Hz
ptc->TC_CHANNEL[1].TC_RA = timer >> 1 ;
ptc->TC_CHANNEL[1].TC_CCR = 5 ; // Enable clock and trigger it (may only need trigger)
}
// Start TIMER1 at 100000Hz, used for DACC trigger
@@ -108,29 +97,22 @@ void dacInit()
dacptr->DACC_CDR = 2048 ; // Half amplitude
// Data for PDC must NOT be in flash, PDC needs a RAM source.
dacFill(Sine_values, 50/*100 samples*/);
dacptr->DACC_PTCR = DACC_PTCR_TXTEN ;
NVIC_EnableIRQ(DACC_IRQn) ;
}
bool dacQueue(AudioBuffer *buffer)
{
dacStart();
return false;
}
extern "C" void DAC_IRQHandler()
{
// Data for PDC must NOT be in flash, PDC needs a RAM source.
if (audioQueue.state == AUDIO_PLAYING_WAV) {
if (nextAudioData) {
DACC->DACC_TNPR = CONVERT_PTR(nextAudioData);
DACC->DACC_TNCR = nextAudioSize;
nextAudioData = NULL;
}
else {
dacStop();
}
}
else if (audioQueue.state == AUDIO_PLAYING_TONE){
DACC->DACC_TNPR = CONVERT_PTR(Sine_values);
DACC->DACC_TNCR = 50 ; // words, 100 16 bit values
AudioBuffer *nextBuffer = audioQueue.getNextFilledBuffer();
if (nextBuffer) {
DACC->DACC_TNPR = CONVERT_PTR(nextBuffer->data);
DACC->DACC_TNCR = nextBuffer->size/2;
}
else {
dacStop();
+1 -32
View File
@@ -40,11 +40,7 @@
void audioInit( void ) ;
void audioEnd( void ) ;
void setFrequency( uint32_t frequency ) ;
uint32_t getFrequency();
extern uint16_t *nextAudioData;
extern uint16_t nextAudioSize;
void setSampleRate( uint32_t frequency ) ;
inline void dacStart()
{
@@ -61,31 +57,4 @@ inline void dacStop()
#define VOLUME_LEVEL_DEF 12
void setVolume(uint8_t volume);
inline void dacFill(uint16_t *data, uint16_t size)
{
register Dacc *dacptr = DACC;
dacptr->DACC_TPR = CONVERT_PTR(data);
dacptr->DACC_TNPR = CONVERT_PTR(data);
dacptr->DACC_TCR = size; // words
dacptr->DACC_TNCR = size; // words
}
inline uint16_t dacQueue(uint16_t *data, uint16_t size)
{
register Dacc *dacptr = DACC;
if (dacptr->DACC_ISR & DACC_ISR_TXBUFE) {
dacptr->DACC_TPR = CONVERT_PTR(data);
dacptr->DACC_TCR = size;
return size;
}
else if (dacptr->DACC_TNCR == 0) {
dacptr->DACC_TNPR = CONVERT_PTR(data);
dacptr->DACC_TNCR = size;
return size;
}
else {
return 0;
}
}
#endif
+2 -2
View File
@@ -78,8 +78,8 @@
#define RESUME_PPMIN_INTERRUPT() TIMSK3 |= (1<<ICIE3)
#define TIMER_AUDIO_VECT TIMER4_OVF_vect
#define SET_TIMER_AUDIO_CTRL() TCCR4B = (0b111 << CS20)
#define PAUSE_AUDIO_INTERRUPT() TIMSK4 &= ~(1<<OCIE4A)
#define RESUME_AUDIO_INTERRUPT() TIMSK4 |= (1<<OCIE4A)
#define PAUSE_AUDIO_INTERRUPT() TIMSK4 &= ~(1<<TOIE4)
#define RESUME_AUDIO_INTERRUPT() TIMSK4 |= (1<<TOIE4)
#else
#define TIMER_16KHZ_VECT TIMER0_OVF_vect
#define COUNTER_16KHZ TCNT0
+35 -26
View File
@@ -37,25 +37,15 @@
#include "../../opentx.h"
bool dacIdle = true;
uint32_t currentFrequency = 0;
uint32_t getFrequency()
void setSampleRate(uint32_t frequency)
{
return currentFrequency;
}
register uint32_t timer = (PERI1_FREQUENCY * TIMER_MULT_APB1) / frequency - 1 ; // MCK/8 and 100 000 Hz
void setFrequency(uint32_t frequency)
{
if (currentFrequency != frequency) {
currentFrequency = frequency;
register uint32_t timer = (PERI1_FREQUENCY * TIMER_MULT_APB1) / frequency - 1 ; // MCK/8 and 100 000 Hz
TIM6->CR1 &= ~TIM_CR1_CEN ;
TIM6->CNT = 0 ;
TIM6->ARR = limit<uint32_t>(2, timer, 65535) ;
TIM6->CR1 |= TIM_CR1_CEN ;
}
TIM6->CR1 &= ~TIM_CR1_CEN ;
TIM6->CNT = 0 ;
TIM6->ARR = limit<uint32_t>(2, timer, 65535) ;
TIM6->CR1 |= TIM_CR1_CEN ;
}
// Start TIMER6 at 100000Hz, used for DAC trigger
@@ -87,24 +77,42 @@ void dacInit()
DMA1_Stream5->CR &= ~DMA_SxCR_EN ; // Disable DMA
DMA1->HIFCR = DMA_HIFCR_CTCIF5 | DMA_HIFCR_CHTIF5 | DMA_HIFCR_CTEIF5 | DMA_HIFCR_CDMEIF5 | DMA_HIFCR_CFEIF5 ; // Write ones to clear bits
DMA1_Stream5->CR = DMA_SxCR_CHSEL_0 | DMA_SxCR_CHSEL_1 | DMA_SxCR_CHSEL_2 | DMA_SxCR_PL_0 |
DMA_SxCR_MSIZE_0 | DMA_SxCR_PSIZE_0 | DMA_SxCR_MINC | DMA_SxCR_DIR_0 | DMA_SxCR_CIRC ;
DMA_SxCR_MSIZE_0 | DMA_SxCR_PSIZE_0 | DMA_SxCR_MINC | DMA_SxCR_DIR_0 | DMA_SxCR_CIRC ;
DMA1_Stream5->PAR = CONVERT_PTR(&DAC->DHR12R1);
DMA1_Stream5->M0AR = CONVERT_PTR(Sine_values);
// DMA1_Stream5->M0AR = CONVERT_PTR(Sine_values);
DMA1_Stream5->FCR = 0x05 ; //DMA_SxFCR_DMDIS | DMA_SxFCR_FTH_0 ;
DMA1_Stream5->NDTR = 100 ;
// DMA1_Stream5->NDTR = 100 ;
DAC->DHR12R1 = 2010 ;
DAC->SR = DAC_SR_DMAUDR1 ; // Write 1 to clear flag
DAC->CR = DAC_CR_TEN1 | DAC_CR_EN1 ; // Enable DAC
NVIC_SetPriority( DMA1_Stream5_IRQn, 2 ) ; // High priority interrupt
NVIC_EnableIRQ(TIM6_DAC_IRQn) ;
NVIC_SetPriority(DMA1_Stream5_IRQn, 2) ; // High priority interrupt
NVIC_EnableIRQ(TIM6_DAC_IRQn) ; // TODO needed?
NVIC_EnableIRQ(DMA1_Stream5_IRQn) ;
}
bool dacQueue(AudioBuffer *buffer)
{
if (dacIdle) {
dacIdle = false;
DMA1_Stream5->CR &= ~DMA_SxCR_EN ; // Disable DMA channel
DMA1->HIFCR = DMA_HIFCR_CTCIF5 | DMA_HIFCR_CHTIF5 | DMA_HIFCR_CTEIF5 | DMA_HIFCR_CDMEIF5 | DMA_HIFCR_CFEIF5 ; // Write ones to clear bits
DMA1_Stream5->M0AR = CONVERT_PTR(buffer->data);
DMA1_Stream5->NDTR = buffer->size;
DMA1_Stream5->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE ; // Enable DMA channel and interrupt
DAC->SR = DAC_SR_DMAUDR1 ; // Write 1 to clear flag
DAC->CR |= DAC_CR_EN1 | DAC_CR_DMAEN1 ; // Enable DAC
return true;
}
else {
return false;
}
}
// Sound routines
void audioInit()
{
dacInit() ;
dacInit();
}
void audioEnd()
@@ -129,13 +137,14 @@ extern "C" void DMA1_Stream5_IRQHandler()
DMA1_Stream5->CR &= ~DMA_SxCR_TCIE ; // Stop interrupt
DMA1->HIFCR = DMA_HIFCR_CTCIF5 | DMA_HIFCR_CHTIF5 | DMA_HIFCR_CTEIF5 | DMA_HIFCR_CDMEIF5 | DMA_HIFCR_CFEIF5 ; // Write ones to clear flags
DMA1_Stream5->CR &= ~DMA_SxCR_EN ; // Disable DMA channel
if (nextAudioData) {
DMA1_Stream5->M0AR = CONVERT_PTR(nextAudioData);
DMA1_Stream5->NDTR = nextAudioSize*2;
AudioBuffer *nextBuffer = audioQueue.getNextFilledBuffer();
if (nextBuffer) {
DMA1_Stream5->M0AR = CONVERT_PTR(nextBuffer->data);
DMA1_Stream5->NDTR = nextBuffer->size;
DMA1->HIFCR = DMA_HIFCR_CTCIF5 | DMA_HIFCR_CHTIF5 | DMA_HIFCR_CTEIF5 | DMA_HIFCR_CDMEIF5 | DMA_HIFCR_CFEIF5 ; // Write ones to clear bits
DMA1_Stream5->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE ; // Enable DMA channel
DAC->SR = DAC_SR_DMAUDR1; // Write 1 to clear flag
nextAudioData = NULL;
}
else {
dacIdle = true;
+1 -29
View File
@@ -40,12 +40,9 @@
extern void audioInit( void ) ;
extern void audioEnd( void ) ;
extern void setFrequency( uint32_t frequency ) ;
extern uint32_t getFrequency();
extern void setSampleRate(uint32_t frequency);
extern bool dacIdle;
extern uint16_t *nextAudioData;
extern uint16_t nextAudioSize;
inline void dacStart()
{
@@ -60,31 +57,6 @@ inline void dacStop()
DMA1_Stream5->CR &= ~DMA_SxCR_CIRC ;
}
inline void dacFill(uint16_t *data, uint16_t size)
{
DMA1_Stream5->CR &= ~DMA_SxCR_EN; // Disable DMA channel
DMA1_Stream5->M0AR = CONVERT_PTR(data);
DMA1_Stream5->NDTR = size*2;
}
inline uint16_t dacQueue(uint16_t *data, uint16_t size)
{
if (dacIdle) {
dacIdle = false;
DMA1_Stream5->CR &= ~DMA_SxCR_EN ; // Disable DMA channel
DMA1->HIFCR = DMA_HIFCR_CTCIF5 | DMA_HIFCR_CHTIF5 | DMA_HIFCR_CTEIF5 | DMA_HIFCR_CDMEIF5 | DMA_HIFCR_CFEIF5 ; // Write ones to clear bits
DMA1_Stream5->M0AR = CONVERT_PTR(data);
DMA1_Stream5->NDTR = size*2;
DMA1_Stream5->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE ; // Enable DMA channel and interrupt
DAC->SR = DAC_SR_DMAUDR1 ; // Write 1 to clear flag
DAC->CR |= DAC_CR_EN1 | DAC_CR_DMAEN1 ; // Enable DAC
return size;
}
else {
return 0;
}
}
#define VOLUME_LEVEL_MAX 23
#define VOLUME_LEVEL_DEF 12
static const int8_t volumeScale[VOLUME_LEVEL_MAX+1] =