Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change duty cycle of PIO Tone to 50% #2770

Merged
merged 2 commits into from
Jan 21, 2025

Conversation

magy00
Copy link
Contributor

@magy00 magy00 commented Jan 21, 2025

Move side-setting of pin one instruction up and replace jmp with .wrap to get a 50% duty cycle.

@magy00
Copy link
Contributor Author

magy00 commented Jan 21, 2025

Note that something like

.program tone
    .out 1
  .wrap_target
    pull noblock        // mov osr, (txfifo_is_empty ? x : txfifo)
    mov x, osr
  delay:
    jmp x--, delay
    mov pins, ~pins     // toggle pins (requires in_base == out_base)
    mov x, osr
    .wrap

would even be an instruction shorter (5 in total – but 5 instead of 3 cycles overhead for a square wave half-period, which shouldn't matter), and the two pio_sm_exec() are not necessary if a pio_sm_put() happens after pio_sm_init() but before pio_sm_set_enabled().

(With a .out 2 and these two outputs initialized opposite, this would also work as a differential output, i.e. louder piezo. I have not tested what would happen to the input values if the outputs would be overloaded but it's working so far.)

@Andy2No
Copy link
Contributor

Andy2No commented Jan 21, 2025

@magy00 Would it be possible to make a version that lets us set the mark/space ratio too, or just set the mark and space periods, to keep it simpler?

Is there a way to make sure the current cycle or half cycle completes before it loads a new value (to avoid a glitch), or does it do that anyway?

I've thought for a while that this is something the PIO modules would be good for, i.e. pulse width variable waveforms for music synthesis, if they can be made to do those two things, but I don't know enough about it to make a start.

@earlephilhower
Copy link
Owner

Neat. Tone was one of the first PIO programs I wrote and I think it was just 1 sysclk off in terms of duty cycle. For audio stuff, 1/133,000,000s didn't seem like an issue to me at the time. How'd you notice it was off by a sysclk?

BTW, nice job reducing the instruction count by 1.

@Andy2No it already works atomically, so glitch free. It basically pulls a counter load value, sets the output state, and counts down to 0 before pulling a new one (or the same one as before if not updated).

@earlephilhower earlephilhower merged commit b3d0ccc into earlephilhower:master Jan 21, 2025
26 checks passed
@magy00
Copy link
Contributor Author

magy00 commented Jan 22, 2025

How'd you notice it was off by a sysclk?

Well, I was looking at the source code (because I was doing the tone ringer emulation stuff mentioned above) and noticed that the duty factor was off by 1 and the frequency by 7 cycles (fine enough for audio but might also be useful for clock signal generation without the 200 kHz limit).

set the mark/space ratio

@Andy2No Perhaps adapt their PWM example?

@magy00 magy00 deleted the toneduty50 branch January 22, 2025 04:11
@Andy2No
Copy link
Contributor

Andy2No commented Jan 22, 2025

Cool. Thanks, @earlephilhower and @magy00

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants