Tiny Ensemble - an Attiny85 powered chorus effect

Started by Ksander, October 27, 2023, 04:33:25 PM

Previous topic - Next topic

cordobes

In most 8-bit uC's you have 8-bit pwm channels, you cannot control the bits per channel, so the frequency is defined as a function of the system frequency / 2^8.
There is an improvement in using a 16-bit data, but you must be careful how to align the bits in each channel, and in the case of wanting a "centered" data, or 5 bits per PWM channel, you must perform a shift of both high and low bytes. To start, use 8 bits in pwm_low and 2 bits in pwm_high. The weighting of the resistors should be done based on the total bits of the channel, in the case of the attiny, 8 bits, and not on the data to be loaded.

And all our yesterdays have lighted fools the way to dusty death.
Out, out, brief candle! Life's but a walking shadow.

ElectricDruid

Quote from: cordobes on November 30, 2023, 07:59:13 AMIn most 8-bit uC's you have 8-bit pwm channels, you cannot control the bits per channel, so the frequency is defined as a function of the system frequency / 2^8.

Sorry, but that's just not true. Many/most chips offer a way to control the count length as well as the compare value. Including this one.

Ksander suggested how in their last post; you have to use an OCR to clear the timer when it gets to 31 (Clear Timer on Compare Match (CTC) Mode) and then you'd use another OCR to generate 5-bit PWM.
You can do this on both Timer0 and Timer1, so you've got two 5-bit PWMs available. This is important because (system frequency / 2^5) is eight times higher than (system frequency / 2^8) so our filtering improves massively and the sidebands get further from our signal.

Ksander, it occurred to me that one reason your output might go silent would be if the OCR value got *higher* than 31. In that case, the waveform would never switch on or off, so you'd get a solid DC level and no audio output.

Ksander

#62
This is what I gather from the datasheet (may be incorrect):

There are two timers in the Attiny85; Timer0 and Timer1. Timer 1 has an OCR1A register which sets behavior for pin OC1A (PB1), and OCR1B which sets behavior on pin OC1B (PB4), and then there is an OCR1C register which sets the TOP value for the counter. With setting bit CTC1 in the Timer 1 Counter Control Register TCCR1, you can clear the counter on a match with OCR1C. So I set OCR1C to 31, and then OCR1A/OCR1B to put out the five high or five low bits. As a test, per ElectricDruid's suggestion, I let both pins count up from 0 to 31, and monitored the output with my oscilloscope. OC1B nicely keeps counting up from 0 to 31, and OC1A does so as well for a second or two, and then the output becomes constant. I don't know why --yet. 

As an aside, the earlier version, where the 10-bit sample is spread out over four cycles works, but not in the Pitch Shifter (other topic), which can't keep up when the writing frequency becomes too high, so for that effect I want to explore this way of getting a higher bit rate.

Anyway, it looks like with your help, I'm getting closer :)

cordobes

What I wanted to say is that generally you cannot use the ducty cycle OCRA and OCRB registers for both PWM signals, the low byte and the high byte, as the OP posted, precisely because one of the comparisons must be done to modify the timer from 8 to 5 bits.
But I see that you have the OCRC register, so there is the solution.
And all our yesterdays have lighted fools the way to dusty death.
Out, out, brief candle! Life's but a walking shadow.

ElectricDruid

Quote from: cordobes on November 30, 2023, 11:27:46 AMWhat I wanted to say is that generally you cannot use the ducty cycle OCRA and OCRB registers for both PWM signals, the low byte and the high byte, as the OP posted, precisely because one of the comparisons must be done to modify the timer from 8 to 5 bits.
Ah, I see. Yes, that's true.

QuoteBut I see that you have the OCRC register, so there is the solution.
Yes, it looks like it. Loads of Output Compare Registers on that timer!

Ksander

Quote from: ElectricDruid on November 30, 2023, 03:56:14 AM...
If it's crashing, you'll have to take stuff out until it's simple enough that it works, and then put things back in until it breaks again, and then have a close look at whatever that last thing you put in was!


Taking this approach, I've taken out everything but the ISR to change the value written to the pins and the settings for getting 5-bit PWM's. I let OCR1B count down, and OCR1A count up. Lo and behold! It works, without crashing. So now it is time to add stuff bit by bit (as a figure of speech).

ElectricDruid

Quote from: Ksander on November 30, 2023, 12:59:53 PMLo and behold! It works, without crashing.

Now *that* is a step forward!

Believe me, I know how tedious and time-consuming this sort of low-level debugging can be. I've spent/wasted days of my life sometimes on things that turned out to be something really stupid, or something really obscure.

There's no substitute for being careful, logical, and methodical. If you take it step by step and make sure you're damn sure that what you think is happening is what's happening before you move to the next step, you can always track this stuff down. It's only a dumb chip, and we're smart monkeys!

Ksander

#67
I'm a dumb monkey too, but luckily quite persistent :)

Now I have a 16 bit variable count up to 1023 and then wrap to 0; divide the value over 5 high and 5 low bits, write these to the respective pins and sum them with resistors (along with a little filtering cap to ground). On the oscilloscope I see a beautifully smooth sloping line. This is so exciting  ;D

ElectricDruid


Ksander

#69
I added the ADC sampling and outputting 10-bit samples to the two PWM pins - it works (yay), in that decent audio comes out. However, the output is now flat: with a 440Hz test signal input, I measure about 403Hz at the output. The sampling and output frequency settings are identical to what they were before. That means, their frequencies should match (17.9kHz). I could of course correct for this by changing the output interrupt frequency OCR0A, but it doesn't make sense to me. Any idea why this might happen?

Edit: in the datasheet, it says that the phase locked loop/Fast PWM mode has an 'asynchronous' clock, so I tried disabling that, which means that the main clock is used for the PWM 8MHz instead of 64MHz.  This seems to work much better. But then I wonder. What is the PLL locked to exactly?

Edit 2: I also added using a rotary encoder to change the read and output to PWM rate (i.e. a 10-bit pitch shifter), and this works too without the IC freezing, although still the setting where in- and output frequencies should match doesn't... And the error doesn't scale linearly with OCR0A setting. Maybe I should move this stuff to the pitch shifter topic :)