Added to MDx tone generator driver a function to interrupt an audio stream before its natural completion

replace/e411ed636248236b0fb6203a3785d0ba788aafd7
Silvano Seva 2021-06-17 12:23:02 +02:00
rodzic 7b5e98bbca
commit db3efb21be
2 zmienionych plików z 52 dodań i 27 usunięć

Wyświetl plik

@ -49,15 +49,15 @@ static const uint8_t sineTable[] =
static const uint32_t baseSineFreq = 35;
uint32_t toneTableIndex = 0; /* Current sine table index for CTCSS generator */
uint32_t toneTableIncr = 0; /* CTCSS sine table index increment per tick */
uint32_t toneTableIndex = 0; // Current sine table index for CTCSS generator
uint32_t toneTableIncr = 0; // CTCSS sine table index increment per tick
uint32_t beepTableIndex = 0; /* Current sine table index for "beep" generator */
uint32_t beepTableIncr = 0; /* "beep" sine table index increment per tick */
uint32_t beepTimerCount = 0; /* Downcounter for timed "beep" */
uint8_t beepVolume = 0; /* "beep" volume level */
uint32_t beepTableIndex = 0; // Current sine table index for "beep" generator
uint32_t beepTableIncr = 0; // "beep" sine table index increment per tick
uint32_t beepTimerCount = 0; // Downcounter for timed "beep"
uint8_t beepVolume = 0; // "beep" volume level
bool tonesLocked = false; /* If true tone channel is in use by FSK/playback */
bool tonesLocked = false; // If true tone channel is in use by FSK/playback
using namespace miosix;
Thread *dmaWaiting = 0;
@ -88,7 +88,7 @@ void __attribute__((used)) TIM8_TRG_COM_TIM14_IRQHandler()
}
}
/* Shutdown timers if both compare channels are inactive */
// Shutdown timers if both compare channels are inactive
if((TIM3->CCER & (TIM_CCER_CC2E | TIM_CCER_CC3E)) == 0)
{
TIM3->CR1 &= ~TIM_CR1_CEN;
@ -140,13 +140,13 @@ void toneGen_init()
TIM3->ARR = 0xFF;
TIM3->PSC = 2;
TIM3->CCMR1 = TIM_CCMR1_OC2M_2 /* CH2 in PWM mode 1, preload enabled */
TIM3->CCMR1 = TIM_CCMR1_OC2M_2 // CH2 in PWM mode 1, preload enabled
| TIM_CCMR1_OC2M_1
| TIM_CCMR1_OC2PE;
TIM3->CCMR2 = TIM_CCMR2_OC3M_2 /* The same for CH3 */
TIM3->CCMR2 = TIM_CCMR2_OC3M_2 // The same for CH3
| TIM_CCMR2_OC3M_1
| TIM_CCMR2_OC3PE;
TIM3->CR1 |= TIM_CR1_ARPE; /* Enable auto preload on reload */
TIM3->CR1 |= TIM_CR1_ARPE; // Enable auto preload on reload
/*
* TIM14 configuration:
@ -206,7 +206,7 @@ void toneGen_beepOn(const float beepFreq, const uint8_t volume,
const uint32_t duration)
{
{
/* Do not generate "beep" if the PWM channel is busy, critical section */
// Do not generate "beep" if the PWM channel is busy, critical section
FastInterruptDisableLock dLock;
if(tonesLocked) return;
}
@ -249,7 +249,7 @@ void toneGen_playAudioStream(const uint16_t* buf, const size_t len,
if((buf == NULL) || (len == 0) || (sampleRate == 0)) return;
{
/* Critical section to avoid race conditions on "tonesLocked" */
// Critical section to avoid race conditions on "tonesLocked"
FastInterruptDisableLock dLock;
tonesLocked = true;
beepTimerCount = 0;
@ -277,26 +277,26 @@ void toneGen_playAudioStream(const uint16_t* buf, const size_t len,
DMA1_Stream2->NDTR = len;
DMA1_Stream2->PAR = ((uint32_t) &(TIM3->CCR3));
DMA1_Stream2->M0AR = ((uint32_t) buf);
DMA1_Stream2->CR = DMA_SxCR_CHSEL_0 /* Channel 1 */
| DMA_SxCR_PL /* Very high priority */
| DMA_SxCR_MSIZE_0 /* 16 bit source size */
| DMA_SxCR_PSIZE_0 /* 16 bit destination size */
| DMA_SxCR_MINC /* Increment source pointer */
| DMA_SxCR_DIR_0 /* Memory to peripheral */
| DMA_SxCR_TCIE /* Transfer complete interrupt */
| DMA_SxCR_TEIE /* Transfer error interrupt */
| DMA_SxCR_EN; /* Enable transfer */
DMA1_Stream2->CR = DMA_SxCR_CHSEL_0 // Channel 1
| DMA_SxCR_PL // Very high priority
| DMA_SxCR_MSIZE_0 // 16 bit source size
| DMA_SxCR_PSIZE_0 // 16 bit destination size
| DMA_SxCR_MINC // Increment source pointer
| DMA_SxCR_DIR_0 // Memory to peripheral
| DMA_SxCR_TCIE // Transfer complete interrupt
| DMA_SxCR_TEIE // Transfer error interrupt
| DMA_SxCR_EN; // Enable transfer
NVIC_ClearPendingIRQ(DMA1_Stream2_IRQn);
NVIC_SetPriority(DMA1_Stream2_IRQn, 10);
NVIC_EnableIRQ(DMA1_Stream2_IRQn);
/* Enable compare channel */
// Enable compare channel
TIM3->CCR3 = 0;
TIM3->CCER |= TIM_CCER_CC3E;
TIM3->CR1 |= TIM_CR1_CEN;
/* Start timer */
// Start timer for DMA transfer triggering
TIM7->CR1 = TIM_CR1_CEN;
/*
@ -315,7 +315,7 @@ void toneGen_playAudioStream(const uint16_t* buf, const size_t len,
} while(dmaWaiting);
}
/* End of transfer, turn off TIM7 and DMA */
// End of transfer, turn off TIM7 and DMA
TIM7->CR1 = 0;
TIM3->CCER &= ~TIM_CCER_CC3E;
@ -323,11 +323,29 @@ void toneGen_playAudioStream(const uint16_t* buf, const size_t len,
RCC->APB1ENR &= ~RCC_APB1ENR_TIM7EN;
__DSB();
/* Finally, unlock tones */
// Finally, unlock tones
FastInterruptDisableLock dLock;
tonesLocked = false;
}
void toneGen_stopAudioStream()
{
// Critical section to avoid race conditions
FastInterruptDisableLock dLock;
// Stop DMA triggering timer and TIM3 compare channel
TIM7->CR1 = 0;
TIM3->CCER &= ~TIM_CCER_CC3E;
// Shut down TIM7 and DMA
RCC->AHB1ENR &= ~RCC_AHB1ENR_DMA1EN;
RCC->APB1ENR &= ~RCC_APB1ENR_TIM7EN;
// Unlock tones and wake up the thread waiting for completion
tonesLocked = false;
if(dmaWaiting) dmaWaiting->IRQwakeup();
}
bool toneGen_toneStatus()
{
/*

Wyświetl plik

@ -101,7 +101,8 @@ void toneGen_encodeAFSK1200(const uint8_t *buf, const size_t len);
/**
* Reproduce an audio stream, sending audio stream to both the speaker and the
* rtx baseband IC.
* This function blocks the execution flow until all data has been sent.
* This function blocks the execution flow until all data has been sent or the
* reproduction is interrupted by calling the corresponding function.
*
* WARNING: the underlying peripheral accepts ONLY 16 bit transfers, while the
* PWM resolution is 8 bit. Thus, the sample buffer MUST be of uint16_t elements
@ -115,6 +116,12 @@ void toneGen_encodeAFSK1200(const uint8_t *buf, const size_t len);
void toneGen_playAudioStream(const uint16_t *buf, const size_t len,
const uint32_t sampleRate);
/**
* Interrupt the ongoing reproduction of an audio stream, also making the
* toneGen_playAudioStream return to the caller.
*/
void toneGen_stopAudioStream();
/**
* Get the current status of the "beep"/AFSK/audio generator stage.
*