Axoloti as a 5U Module


#21

maybe our math is wrong. in the example above @johannes uses 168000000 and 21 which divided by each other gives him the 8mhz. so the second number is maybe not the pwm period? since he writes it is 128 cycles.

on what do you base your math?


#22

i also tried to put the stuff in a loop like this (in k-rate):

int j;
for(j=0;j<BUFSIZE;j++){
pwmEnableChannel(&PWMD3, 0, (pwmcnt_t)(inlet_pa6[j]>=0?inlet_pa6[j]>>23:0));
pwmEnableChannel(&PWMD3, 1, (pwmcnt_t)(inlet_pa7[j]>=0?inlet_pa7[j]>>23:0));
pwmEnableChannel(&PWMD3, 2, (pwmcnt_t)(inlet_pb0[j]>=0?inlet_pb0[j]>>23:0));
pwmEnableChannel(&PWMD3, 3, (pwmcnt_t)(inlet_pb1[j]>=0?inlet_pb1[j]>>23:0));
}

but i get the same aliasing. i think we are doing something wrong with the period setting. because as i said, in johannes code example he uses 21 to get 127 steps...


#23

(about the potential of hacking extra audio outputs without extra hardware...)

Looping over the BUFSIZE will not schedule the pwm duty cycle changes on corresponding sample-interval timing.

In Axoloti firmware, there is no code that is scheduled synchronously with the audio sample clock, only at 16-sample buffers, and it is the responsibility of the DMA engine and I2S (SAI) peripheral to transmit the audio data to the audio converter, synchronously to the sample clock.

In order to make PWM duty cycle changes synchronously to the audio sample clock, one approach is to enable an interrupt (an EXTI interrupt on PE4 or PI11 should work as interrupt source).
In the interrupt service routine, read the next sample value from a (double) buffer and set the pwm duty cycle. This requires firmware hacking! An object could then write audio data in that double buffer.
A better (more acceptable) solution would be to set up a DMA stream to the timer, that avoids interrupts consuming precious time. But I'm afraid there is no suitable DMA channel left, or no suitable source to synchronize DMA.

Rather than using PWM out for lofi audio, I'd suggest to use the on-chip DACs. Same story, gpio/out/analog only schedules at k-rate, looping it does not make it schedule at audio-rate. The bad solution: write the DAC register from within an audio-rate interrupt. The good solution: configure conversions to be triggered by the audio clock (refer to chapter "14.3.6 DAC trigger selection" in stmicro's RM0090 reference manual, and use DMA to copy data to the DAC. The only DMA streams that can be mapped to DAC1 and DAC2 are DMA1stream5 and DMA1stream6 (according to chapter "10.3.3 Channel selection" in RM0090), while those are already assigned to I2C on user-gpio pins. So since DMA is not available, need to use interrupts to copy data to the DAC's.

In summary, quite an effort and the result will still have significant side effects. And I fear the audio quality would still be disappointing.


#24

thanks for the in-depth answer. "disappointing" audio quality as in 8-bit pwm would be the point of the idea :slight_smile: at least for me. i like it very much for aggressive bass sounds.

if there is ever time to make such a hack in the firmware, that would be much appreciated, but this is clearly out of my reach for now.


#25

@johannes Thanks for the answer. I suspected it wasn't easy :slight_smile:

By the way I'm doing another strange thing that almost works OK. I'm using a digital output as a Square/PWM oscillator by sending the output of a PWM oscillator objet to PC0. I get about 3 octaves of an usable Square/PWM signal. It's a bit unstable, but it works (I'm using it as second VCO in companion of my Yusynth VCO).
Is there a (easy) way to improve stability and octave range, or it's a case like the audio to PWM out.
Thanks


PWM on non-PWM digital outputs experiment
#26

Oh if you want a PWM square wave on an extra output...
you could probably tune PWM outputs to an audio frequency and use them as true PWM DCO's.
The disadvantage is that the audio output will only be available on corresponding gpio pins, not as an outlet in a patch.

This wouldn't be quite as complicated in coding as adding a lofi pwm dac output.

If you can make sense of the chapters about the timers in the RM0090 reference manual.
You can access for instance the TIM8_CR1 register as TIM8->CR1 in init or k-rate-code.

Please do not use any other timer than TIM3, TIM4, TIM5 and TIM8 if possible.

Should be fun for modularists: 4 extra DCO's. Additionally there might also be a way to hard-sync one DCO to another cfr. chapter "18.3.14 Timers and external trigger synchronization" in RM0090.


#27

Thanks @johannes!!!
I think that the necesary coding skills are way over my capabilty (right now), but is good to know it could be done :slight_smile:


#28

Awesome project, great work! Thanks also for sharing implementation details and schematics :smiley:


#29

Look amazing, thanks for sharing.

I'm doing a similar thing with a banana synth I'm building. For my CV inputs, I'm thinking of doing it a little differently, by adding the potentiometers as separate ADC in's on the axoloi. That way I can scale the CV input in software or programs the pot's for different functions.

For the analog audio input, do you attenuate it?
For the analog audio output, I think you have a 4x gain. Does that give you approximately +/- 5v levels on the out?


#30

For the audio output I measured 2.3Vpp at the Axoloti output, so I used a gain of 4.3 so at the module output I have 9.89Vpp (almost +/- 5V).

For the input I measured a max of 4Vpp before saturation, so I attenuated the input by 2/5. I used a pasive resistor divider with a 68K and a 47K resistors, that gives me an attenuation of 0.408 and an input impedance of 115K.
Is not in the schematics because I mounted the resistors in a small perfboard near the jacks...