Locking on to a square wave signal with minimum oversampling I'm designing a device that will have an IR photodiode connected to a low power microcontroller's ADC pin. At times, another device will be transmitting a 48KHz square wave, and I'd like to be able to detect when that is the case entirely in software, as well as being able to detect individual high and low transitions.

My understanding is that a PLL is the correct solution to this problem. However, I have extremely limited DSP knowledge, so I have a fuzzy idea at best on how to actually implement this in software, and much of the documentation available goes well over my head with a lot of domain specific terminology. This is further complicated by the low power nature of the microcontroller - I have limited processor cycles available, and thus I'd like to sample as infrequently as possible while still reliably locking on to the signal. If it helps, the sampling timer can be adjusted to match the observed frequency of the input signal.

Can anyone suggest an approach to this that is as straightforward and understandable as possible, while also minimizing CPU resources consumed?
One partial answer to my own question is to use the Goertzel algorithm instead of a PLL. The Goertzel algorithm makes it possible to trivially determine the power of a particular frequency; it won't provide the phase, however.

The Goertzel algorithm can be implemented quite trivially using a multiplication and two additions per sample; the sampling rate need only be a minimum of twice the frequency of the signal to be detected. Determining the amplitude of the signal from the Goertzel algorithm's output requires four more multiplies and two more additions.

Since the multiplication in the main part of the Goertzel algorithm is by a constant factor of 2 * cos(2 * pi * w), where w is the number of samples per cycle, one multiplication can be eliminated entirely by sampling at 6 times the target frequency, making 2 * cos(2 * pi * 1/6) = 1.