sensorium / Mozzi

sound synthesis library for Arduino
https://sensorium.github.io/Mozzi/
GNU Lesser General Public License v2.1
1.06k stars 185 forks source link

Add "STM32duino" port #181

Closed tfry-git closed 1 year ago

tfry-git commented 1 year ago

Yeah, the label is confusing, but that isn't my fault...

Seeing that the libmaple-based generic STM32 cores no longer seem actively maintained, here is a - basic(!) - port to the more official port, that is now using the stm32duino label. (Original motivation was that I wanted to add auto-builds for STM32, but found out, the currently supported core is not even available via the BoardsManager).

See enclosed changes to README.md for details. Importantly, analog is not implemented.

tfry-git commented 1 year ago

Note: Compilation failure in the auto-builds appears to result from the system trying to build the "previous" version of the sketches from master, for comparison, which fails, for obvious reasons. So this should not be something to worry about.

tomcombriat commented 1 year ago

Got indeed a bit confused at first but the edits to the readme help a lot, what a mess…

I still have some systems running on bluePill, will try to test them soon with both the old port and the new one (not sure it is supposed to work with this one thought).

tfry-git commented 1 year ago

It should work with the BluePill, indeed (tested on that), but be prepared that the upload procedure is all different between the two ports. (In theory, this one is supposed to work with "Maple Bootloader", but I did not get that to work).

tomcombriat commented 1 year ago

Hello!

I have not really followed what was happening here so I was wondering what was the working state of this? I have stopped using STM32s (for now) on new projects because of the difficulty to find hardware, but I still have some old projects that use that and are still in use. I will probably try to re-compile them with this new port (and the old one).

Any idea which one is the most efficient?

tfry-git commented 1 year ago

I'm finished with this PR for now. Definitely ready for testing. I tested the basics on my old BluePill, but also on an STM32F411 black pill.

In theory the "maple" core is more efficient, but this one has much broader support. It definitely runs on many more boards, and there are probably more libraries for peripherals.

As a matter of fact, since this is based on STMs HAL (hardware abstraction library), it may actually be possible to take the analog read code of this one and use it on the giga. I have not tested that, so far, though.

tomcombriat commented 1 year ago

Nice! I will probably try soon for an update of these synths! It was fairly borderline in terms of processing power so it should be fairly clear to see how the (new) stm32duino performs in comparison.

I actually have some blackpills (never used) lying around, might be the occasion!

tomcombriat commented 1 year ago

Hei! Just posting this while it is fresh.

In the following "new" refers to the STM32duino port (backed by ST) and "old" refers the Arduino_STM32, originated by Clarke, based on libmaple.

Quickly tested the new and the old version.

Found a small problem when trying to compile the new one with a user-defined audioOutput function. I have committed a PR #189.

On the new, I managed to get sound out on this old hardware, but not clean every time. I have not tested Mozzi examples yet, it might be something else.

The old version compiles fine but I don't manage to get MIDI to work yet (not related to Mozzi). Will try to test the barebones more carefully soon! Actually can't even get Serial.print to work, I have to check what changed during the update…

tomcombriat commented 1 year ago

Hello! Just to try to narrow down what could be the problem here, @tfry-git did you managed to get Mozzi to work with stevstrong's core? For some reason, and whatever the config (EXTERNAL_AUDIO_OUTPUT activated or not), defaultAudioOutput() is never called. Hence I obviously suspect the timer, but cannot get my finger on what is wrong…

tfry-git commented 1 year ago

Hello! Just to try to narrow down what could be the problem here, @tfry-git did you managed to get Mozzi to work with stevstrong's core?

Well, back in the day, I did, obviously. I am not 100% sure that I actually tested again, though. I did check compilation still worked, and stumbled across a compilation error, there (prompting the two small changes in MozziGuts_impl_STM32.cpp). I may have assumed those to be trivial, however...

For some reason, and whatever the config (EXTERNAL_AUDIO_OUTPUT activated or not), defaultAudioOutput() is never called. Hence I obviously suspect the timer, but cannot get my finger on what is wrong…

Perhaps, instead of lines 88 to 95 you could activate line 86? Just to check, whether the problem is in the timer setup, somehow?

As another idea, perhaps try another timer instance? Perhaps timer 2 is now used for something in the core?

tomcombriat commented 1 year ago

Thanks for inputs!

As another idea, perhaps try another timer instance? Perhaps timer 2 is now used for something in the core?

That's one of the first thing I tried, alongside changing the channel of the interrupt, to not avail so far…

Perhaps, instead of lines 88 to 95 you could activate line 86? Just to check, whether the problem is in the timer setup, somehow?

Just tried but that does not resolve the issue either…

I have focused more on the legacy port so far because of a piece of hardware that I am using quite frequently and that was "bulletproof" in terms of hardware. I will try to have the courage (tomorrow) to review the changes that have been made to the Timers since Clarke's time…

tomcombriat commented 1 year ago

Hello! My previous fix on this PR was not correct, I allowed myself to push a correct one straight on this branch, hope that is okay! We might want to clean up the history before merging though…

Also reporting: could not get things to work with stevstrong fork of Arduino_STM32. But got some example working with the repo it was based on from Roger Clark (which was the one we were using before). Could not find any obvious change from the fork in the HardwareTimer class except for a few move back and forth between the header and the cpp file, but did not look it up completely (there are 293 commits difference after all…). If you have the same, I suggest changing the Readme to point to Roger Clark port instead of Stevstrong.

My old hardware still does not work as before (at least there is something coming out though, but not stable) but I wonder if it is not caused by another update in another library. Interestingly, the symptoms are quite close between Clark library (maple) and STM32duino. I will not dig up more today, but I would really like to know where the error is coming from (especially if it is coming from Mozzi or not…). Best,

tomcombriat commented 1 year ago

Hi! Quickly reporting: seems to work quite well with the two ports (using Roger Clark's for the legacy one, did not give much try to SteveStrong's one, which also seems to have been stalled for some time). Therefor, I suggest making the Readme pointing to that port.

Performances are a bit lower on the new STM32duino (especially because overclocking is not possible), but nothing dramatic.


Just while being here, and because I know some people are quite knowledgeable in C++: I had problems with my old sketches because:

#define POLYPHONY 4
Oscil<COS2048_NUM_CELLS, AUDIO_RATE> aCarrier[POLYPHONY] = { Oscil<COS2048_NUM_CELLS, AUDIO_RATE>(COS2048_DATA)};

used to work. But not anymore (at least when using Arduino Ide 2.0). It compiles thought but not all oscillators are actually initialized.

Now I need to do:

#define POLYPHONY 4
Oscil<COS2048_NUM_CELLS, AUDIO_RATE> aCarrier[POLYPHONY] = { Oscil<COS2048_NUM_CELLS, AUDIO_RATE>(COS2048_DATA),Oscil<COS2048_NUM_CELLS, AUDIO_RATE>(COS2048_DATA),Oscil<COS2048_NUM_CELLS, AUDIO_RATE>(COS2048_DATA),Oscil<COS2048_NUM_CELLS, AUDIO_RATE>(COS2048_DATA)};

which is not ideal obviously because POLYPHONY is not easily changeable anymore.

I have read that my previous method was actually not in the standard, where it is said that you can only initialize all elements to 0 with a single initializer. Is there a way to do that more cleanly while being statically allocated I wonder?

tfry-git commented 1 year ago

Hi! Quickly reporting: seems to work quite well with the two ports (using Roger Clark's for the legacy one, did not give much try to SteveStrong's one, which also seems to have been stalled for some time). Therefor, I suggest making the Readme pointing to that port.

Fair enough. I'll try to do some testing myself, with the "old" cores, but may take me a couple of days. Sure, both cores seem stalled, but stevstrong's is the one more visible on stm32duino.com, ATM, so - if possible - that seems preferable.

I may have lost track a little: The symptom there was that you did not get any output at all, presumably due to a problem with the timer, right?

Performances are a bit lower on the new STM32duino (especially because overclocking is not possible), but nothing dramatic.

And so the problems you reported about the "new" port, earlier, are essentially due to lack of performance, correct?


I have read that my previous method was actually not in the standard, where it is said that you can only initialize all elements to 0 with a single initializer. Is there a way to do that more cleanly while being statically allocated I wonder?

Statically, I guess you can't indeed (https://stackoverflow.com/questions/201101/how-to-initialize-all-members-of-an-array-to-the-same-value). But perhaps you can just use

#define POLYPHONY 4
Oscil<COS2048_NUM_CELLS, AUDIO_RATE> aCarrier[POLYPHONY];

void setup() {
  for (int i = 0; i < POLYPHONY; ++i) aCarrier[i].setTable(COS2048_DATA);
  [...]
}
tomcombriat commented 1 year ago

I may have lost track a little: The symptom there was that you did not get any output at all, presumably due to a problem with the timer, right?

Yes, I did not go ultra deep into debugging this but it seems the defaultAudioOutput which then branch to standard PWM or a user-defined audioOutput is never called. Hence I would suspect that the timer which is supposed to call it is never firing. Looked a bit in the changes in the Timer source codes between the two cores but did not find anything obvious. Could also be an installation problem here.

And so the problems you reported about the "new" port, earlier, are essentially due to lack of performance, correct?

Mostly was an error on my side (this static definition used to work, so I got a bit confused why it would not anymore. As you pointed out this is not in the standard but the fact that it was working before did not help figuring out the problem, thanks for the suggestion by the way!). Except for that, there is a slight performance drop from my tests. The fact that you cannot overclock the chip with STM32duino core does not help of course.

tfry-git commented 1 year ago

I can finally confirm that Stev Strong's core seems bugged, here (I cannot even get a simple pwmWrite() example to work, entirely without Mozzi). Reverted the recommendation back to Roger Clark's core.