1

I'm trying to play a note through the speaker of my board. Currently, I have an interrupt as follows:

void sampleISR(void) {
  static uint32_t phaseAcc = 0;
  phaseAcc += a; //this `a` is modified outside
  analogWrite(OUTR_PIN, phaseAcc);
}

It is attached in the setup() function as follows:

  TIM_TypeDef *Instance = TIM1;
  HardwareTimer *sampleTimer = new HardwareTimer(Instance);
  sampleTimer->setOverflow(22000, HERTZ_FORMAT);
  sampleTimer->attachInterrupt(sampleISR);
  sampleTimer->resume();

I am trying to use a DMA to reduce the strain on my CPU and also increase the sampling rate (making the 22000 bigger). I am trying to use this as my board supports it, however, I am conceptually confused as to what the transformation entails. Currently, I have an interrupt which modifies the analogWrite value to pin OUTR_PIN every 22000 samples. My current understanding is that a DMA is a tool that connects memory to peripherals or memory to memory, in such a way that data can be transferred without the need for the CPU to do it. However, I am uncertain as to what that means in the current context. Would I need to create a memory-to-periphery DMA where the source is memory (my phaseAcc variable and the output is a periphery (my OUTR_PIN?). I am not sure how I would go around doing this, or if what I described above is correct. I am trying to directly mimic the functionality described above.

I am using a board from the stm32 family.

Bula
  • 2,398
  • 5
  • 28
  • 54
  • 2
    DMA is useful when copying relative large amounts data from one memory location to another. – paladin Mar 11 '21 at 21:56
  • 1
    DMA is something your hardware has to support. It doesn't help the CPU at all unless there's other hardware that can take over. Your speaker is probably incapable of doing DMA. If doing something at ~22KHz is a "strain" on your CPU, what kind of CPU is this? Is it running <1MHz? If you have some kind of sound card you can dump raw audio into a buffer and have it play back automatically, sure, but if it's just a speaker hard-wired to some pins, nope. – tadman Mar 11 '21 at 22:27
  • *"Convert interrupts to DMA"* does not make sense. See https://stackoverflow.com/questions/25318145/dma-vs-interrupt-driven-i-o/38165400#38165400 To refer to "programmed I/O with interrupts" as simply "interrupts" is inaccurate and misleading. *"My current understanding is that a DMA is a tool ..."* -- DMA is a method. You need a DMA controller (i.e. a hardware device) in your system (or SoC) to perform DMA transfers. – sawdust Mar 11 '21 at 23:27
  • *"Would I need to create a memory-to-periphery DMA where the source is memory (my phaseAcc variable and the output is a periphery (my OUTR_PIN?)."* -- You would need to setup a DMA transfer where the source is a memory buffer (i.e. an array of values to transmit), and the destination is an input port of the DAC peripheral (not the speaker or analog output pin). The setup requires other arguments such as transfer size, transfer count, and the trigger mechanism for each transfer. – sawdust Mar 11 '21 at 23:41
  • Why is this tagged Arduino and STM32 both at once? Is there some Arduino spawn for STM32 too now? And why do you link Infineon/Cypress if you are using STM32 DMA? – Lundin Mar 12 '21 at 09:04

1 Answers1

0

To drive a speaker you normally use the DAC (digital to analog converter) with a PWM signal (pulse width modulation) On STM32 the DAC / PWM can be linked with DMA (Direct Memory Access), see i.e. HAL_TIM_PWM_Start_DMA from the HAL library, in https://deepbluembedded.com/stm32-dac-sine-wave-generation-stm32-dac-dma-timer-example/ and https://community.st.com/s/question/0D50X0000AAJMUVSQ5/start-pwm-with-dma-haltimpwmstartdma-results-in-hardfault is example code, however you should not drive a speaker with a pure sine wave

For details see also this Application Note : https://www.st.com/resource/en/application_note/cd00259245-audio-and-waveform-generation-using-the-dac-in-stm32-products-stmicroelectronics.pdf

To generate a desired waveform you have to adapt the waveform lookup table described in https://deepbluembedded.com/stm32-dac-sine-wave-generation-stm32-dac-dma-timer-example/

ralf htp
  • 9,149
  • 4
  • 22
  • 34