joan2937 / pigpio

pigpio is a C library for the Raspberry which allows control of the General Purpose Input Outputs (GPIO).
The Unlicense
1.43k stars 403 forks source link

Restore the PCM and PWM clock original states after using waves #567

Open dspinellis opened 1 year ago

dspinellis commented 1 year ago

Currently it appears that PCM and PWM clocks are taken over and not restored when using waves. Ideally, gpioTerminate should restore these clocks. My understanding is that this could be done by saving clkReg[clkDiv] before the call to initClock(0) and restoring it through calls to initHWClk.

dspinellis commented 1 year ago

I'm preparing a pull request to address this. @joan2937 can you please have a quick look at https://github.com/dspinellis/pigpio/commit/93f127f53d1ab37dfba7842f932c76ee6ca91cb0 to check if it's in the right direction? This is still work in progress.

Currently the code is structured to save the hardware state of the five clocks, PWM, and PCM before modifying it, and to restore the saved state when gpioNotifyClose() gets called, which is also called from the Python stop() method.

dspinellis commented 1 year ago

Most recent work is at https://github.com/dspinellis/pigpio/tree/fix-567-pm-state. Saving and restoring seems to work, and all original tests pass. I am currently looking at ways to add unit tests.

guymcswain commented 1 year ago

Please explain the problem you encountered that motivated you to request this change.

dspinellis commented 1 year ago

The issue is now correctly linked in the initial description and reproduced below.

The following example program sends a short pulse on GPIO 14 using pigpio.

import pigpio

pi = pigpio.pi() # connect to Pi

pi.wave_add_new()
pi.set_mode(14, pigpio.OUTPUT)

wf=[]
wf.append(pigpio.pulse(1 << 14, 0, 500))
wf.append(pigpio.pulse(0, 1 << 14, 800))

pi.wave_clear()
pi.wave_add_generic(wf)
wid = pi.wave_create()
pi.wave_send_once(wid)

while pi.wave_tx_busy():
  pass

pi.wave_clear()
pi.stop()

Even after terminating pigpiod, the sound from IQaudio sounds garbled: played intermittently at a high speed with vlc or sounding like white noise with speaker_test. Killing and rerunning pigpiod doesn't help. Only a reboot fixes the problem. Running pigpiod without running the program, or configuring pigpio without using its wave functionality doesn't create a problem.

As explained in the answer to the corresponding Raspberry Pi StackExchange question, "pigpio takes over the PWM and PCM clocks when you use waves, and there is no provision made by pigpio to restore the clocks to the previous state."