STM32F103 minimal synth

What are you developing?
User avatar
Rick Kimball
Posts: 1056
Joined: Tue Apr 28, 2015 1:26 am
Location: Eastern NC, US
Contact:

Re: STM32F103 minimal synth

Post by Rick Kimball » Fri Mar 24, 2017 9:15 pm

ChrisMicro wrote:Did you see, I used your code for the fast pin access:
https://github.com/ChrisMicro/BluePillS ... GPIOPort.h

Do you want to have any special copyright text?
I did see that. Once you use it you own it ; ) I just threw that code into the public domain as an example. Have at it.
-rick

victor_pv
Posts: 1737
Joined: Mon Apr 27, 2015 12:12 pm

Re: STM32F103 minimal synth

Post by victor_pv » Sat Mar 25, 2017 4:36 pm

To add a bit to this thread:
Yes you can use PWM output to generate a wave. I did a dirty port of the TMRPCM library that works ok so far and does that.
You can use interrupts to reload the timers registers, and you can use DMA.
My library is in github in an old version with a few bugs. There is a tread about a ZX tape player where I was helping Buleste use it, and posted some of the bugs I found, but haven't uploaded the corrections to github yet.
Further I worked on using DMA rather than interrupts to reload the timer compare registers, and that reduced CPU usage quite a bit. That is not uploaded anywhere yet. I got it working a couple of weeks ago and haven't had much time yet to clean up and upload.
Once I clean it up and upload it I will post in the libraries section. You can take the parts that set the timer registers and play the samples and use it for anything else other than wav files.

ChrisMicro
Posts: 308
Joined: Fri Mar 24, 2017 4:51 pm
Location: Germany

Re: STM32F103 minimal synth

Post by ChrisMicro » Sat Mar 25, 2017 7:47 pm

Once I clean it up and upload it I will post in the libraries section.
Helo Viktor,

that sounds very interesting. When do you think the library is online?
Here is an application note from ST which could be probably very useful:
http://www.st.com/en/embedded-software/ ... dithr.html

Meanwhile I will add more samples with the software sigma delta DAC.

victor_pv
Posts: 1737
Joined: Mon Apr 27, 2015 12:12 pm

Re: STM32F103 minimal synth

Post by victor_pv » Sun Mar 26, 2017 7:56 pm

ChrisMicro wrote:
Once I clean it up and upload it I will post in the libraries section.
Helo Viktor,

that sounds very interesting. When do you think the library is online?
Here is an application note from ST which could be probably very useful:
http://www.st.com/en/embedded-software/ ... dithr.html

Meanwhile I will add more samples with the software sigma delta DAC.
It's probably going to take me a few weeks to clean and document it, so I have just uploaded the current working files to a fork:
https://github.com/victorpv/Arduino_STM ... m-with-DMA

The last 2 commits in that fork include the necessary files. There are 2 new functions in the timer.h file, for enabling and disabling DMA request on timer update events. I have sent Roger a separate pull request for that file so hopefully he just adds them to the core.
The TMRpcm files are nasty, I commented out big chunks of the original library but didn't delete them to use them as reference. I have not clue how timers work in the AVR, so I needed all that reference while writing my code. Then there are some commented out sections of my own code from testing this and that.

The parts that interest you are where it sets the PINs, timer and DMA devices. Once it's set the DMA will go in circular mode until stopped. You may want to change that to a double buffer, but I thought I'd rather have a sample block repeat than silence, like it happens on a normal computer when it's too slow to reload the sound card buffers and stutters.

Any way, the library if you haven't used TMRpcm in the arduinos goes like this:
It opens a wav file from sdcard. At that point will read the file properties (sample rate, bits per sample, and channels). With that it will set the Timer device to reload at the right rate.
From that point on, a function will reload the buffer. In my case, the 2 buffers are contiguous, and the DMA controller generates an interrupt at half transfer (first buffer just complete playing and can be reloaded) and at full transfer (second buffer (or second half) completed playing and can be reloaded).
The ISR in my case will not reload the buffers, just mark which one is empty, because I used it under RTOS, and I prefered to have a short ISR, and then a task in low priority in the RTOS is waiting for any buffer to be empty to call the refilling function.
I set the timers to have 8 bits resolution. They reload after around 256 cycles (with the pre-scaler set to the appropiate value), both calculated to approximate as best as possible the sample rate of the wav file.


I hope you understand the code, if not, ask me questions.

ChrisMicro
Posts: 308
Joined: Fri Mar 24, 2017 4:51 pm
Location: Germany

Re: STM32F103 minimal synth

Post by ChrisMicro » Mon Mar 27, 2017 8:09 am

It's probably going to take me a few weeks to clean and document it, so I have just uploaded the current working files to a fork:
Thank you very much for posting the code. I would have a first little question:
Which Pins on the STM32F103 can be used for sound output? I assume that we can't use PB12 because there is no connection to the timer units.
Would it make sense to say that PB0 is used in general for sound output? And for later uses: Is it possible to have a stereo PWM? Let's say the second channel on PB1?

ChrisMicro
Posts: 308
Joined: Fri Mar 24, 2017 4:51 pm
Location: Germany

Re: STM32F103 minimal synth

Post by ChrisMicro » Tue Mar 28, 2017 8:56 am

Now I have changed the speaker pin in all files to PB0 to be prepared for future use of the PWM.

Image

victor_pv
Posts: 1737
Joined: Mon Apr 27, 2015 12:12 pm

Re: STM32F103 minimal synth

Post by victor_pv » Tue Mar 28, 2017 2:14 pm

ChrisMicro wrote:Now I have changed the speaker pin in all files to PB0 to be prepared for future use of the PWM.

Image
Remember if you want to use DMA, you have to match the DMA channel with the Timer peripheral in that pin.
In my code I only used Channels 1 and 2 of the timers for left and right channels, but you should be able to use any single channel, just adapt the DMA settings to do the transfer to the right register. The Timers have a special register to be used when you want to update several CCR with 1 DMA request That's the one I was using, since I used 2 channels, but you can do the transfer directly to a CCR, just need some different settings.

ChrisMicro
Posts: 308
Joined: Fri Mar 24, 2017 4:51 pm
Location: Germany

Re: STM32F103 minimal synth

Post by ChrisMicro » Tue Mar 28, 2017 3:11 pm

I saw this in your code and my conclusion was that you are using PB0.

Code: Select all

	extern byte speakerPin = 0;
	extern byte speakerPin2 = 0;
    extern uint8_t CSPin = 0;
	extern uint16 resolution = 0;
	extern uint8 repetition = 0;
	extern byte lastSpeakPin = 0;
So, is PB0 a usable pin in your code? I want to connect it always to the same pin. It shall not be configurable.

victor_pv
Posts: 1737
Joined: Mon Apr 27, 2015 12:12 pm

Re: STM32F103 minimal synth

Post by victor_pv » Tue Mar 28, 2017 4:16 pm

ChrisMicro wrote:I saw this in your code and my conclusion was that you are using PB0.

Code: Select all

	extern byte speakerPin = 0;
	extern byte speakerPin2 = 0;
    extern uint8_t CSPin = 0;
	extern uint16 resolution = 0;
	extern uint8 repetition = 0;
	extern byte lastSpeakPin = 0;
So, is PB0 a usable pin in your code? I want to connect it always to the same pin. It shall not be configurable.
Sorry that's just the default values. The sketch using it sets the values for the speaker pins to what I want to use.
Currently I have tested the following:
DMA Mode: Timer 4, ch1 and ch2 (default pins for that, whichever they are).
Interrupt Mode: Both Timer 4 and Timer 1, ch1 & ch2, default pins for those timer channels.

You should be able to use any Timer, but those are the ones I tested to avoid conflicts of the pins used for the timers VS other peripherals, and the DMA channels used by the Timer vs other peripherals. Since i use both SPI1 and SPI2.

Since a DMA channel should only be used for 1 peripheral at a time, this is why I only tested Timer4 with DMA:

Timer2 Update event uses the same channel as SPI1_RX, which was I'm using in DMA mode, so I could not test DMA mode for Timer 2.
Timer3 Update event uses the same channel as SPI1_TX, which I was also using with DMA, so I could not test DMA in timer3.
Timer1 Update event uses the same channel as SPI2_TX, which I was also using, so I could not test it, but if you dont use SPI2 in DMA mode, you can use DMA with Timer1.

Timer4 uses channel7, which I was not using for anything else, so I could use DMA with that Timer, and I was not using the pins for ch1 & ch2, so I could use them.

I do not remember if the code currently can configure DMA for any Timer device, but if not, that should be an easy addition, so you can use it with other Timers.

EDIT:
To give more background.
The timers can generate events on each individual channels, but since the channels will trip at different times depending the value loaded to them (PWM values), I could not use ch1 or ch2 events, so that's why I use the Timer update event. When the timer overflows, it generates an update, and starts again from 0. At that moment the DMA or ISR will reload the values to both channels at once.
Since I dont use DMA or interrupts with the channels events (remember only with the Timer update event), the code could use any of the channels arbitrarily with little modification. I just decided to use ch1 & ch2, but can use any combination of channels from the timer. If using the DMA and more than 1 channel, then need to be consecutive, so if using 2 channels you could use ch1&ch2, or ch2&ch3, or ch3&ch4. Similar if you wanted to use 3 or 4 channels.

ChrisMicro
Posts: 308
Joined: Fri Mar 24, 2017 4:51 pm
Location: Germany

Re: STM32F103 minimal synth

Post by ChrisMicro » Wed Mar 29, 2017 6:06 am

DMA Mode: Timer 4, ch1 and ch2 (default pins for that, whichever they are).
So this would mean

T4C1 ==> PB6
T4C2 ==> PB7

on the BluePill STM32F130 in the picture above. Right?

Post Reply