Reputation: 308
I have the following snipper to generate sound and in while loop, I want to change it dynamically so it creates different frequency sound during sound gerenation.
for(uint16_t i = 0; i < sample_N; i++)
{
dataI2S[i*2] = i*5000;
dataI2S[i*2 + 1] =i*5000;
}
HAL_I2S_Transmit_DMA(&hi2s3, (uint16_t *)dataI2S, sample_N*2);
while (1)
{
ps = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0);
HAL_I2S_Transmit_DMA(&hi2s3, (uint16_t *)dataI2S, sample_N*b);
b++;
if (b == 5)
b = 1;
if(ps){
generate();
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, ps);
} else {
stop();
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, 0);
}
}
It generates sound with only the first sample_N*b value. It does not change dynamically.
How can I change HAL_I2S_Transmit_DMA(&hi2s3, (uint16_t *)dataI2S, sample_N*b);
dynamically?
void DMA1_Stream5_IRQHandler(void) {
if(x % 2 == 1)
HAL_I2S_Transmit_DMA(&hi2s3, (uint16_t *)dataI2S, sample_N*2);
else
HAL_I2S_Transmit_DMA(&hi2s3, (uint16_t *)dataI2S2, sample_N2*2);
x++;
HAL_DMA_IRQHandler(&hdma_spi3_tx);
}
Upvotes: 4
Views: 650
Reputation: 2218
when you tell controller to transmit data over DMA it just registers your wish(instructions) and do not transmit anything while being inside HAL_I2S_Transmit_DMA function.
Your loop will do multiple iterations while single buffer gets transmitted by controller (in parallel to your code execution).
So telling controller to transmit new data while it is transmitting can cause side-effects.
You need to register interrupt handler which will tell you that transmission completed.
Then you need to register your subsequent "wish" again to sustain non-broken stream of data.
Usually it does not make sense to change data in the buffer while controller transmits them. Usually we use two buffers for transmission of real data:
You can either set global flag from interrupt handler and check for it in the loop (and initiate subsequent tx from your loop) or use message queue to pass messages from interrupt handler into your loop.
static void MX_I2S3_Init(void) {
...some code
hdma_spi3_tx.Instance = DMA1_Stream0;
HAL_NVIC_EnableIRQ(DMA1_Stream0_IRQn);
}
void DMA1_Stream0_IRQHandler(void) {
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, 1);
}
Upvotes: 5