I'm quite intrigued by this challenge, and I think I do have an answer, which is of course entirely theoretical... but let me try to say a bit more.
AndersNielsen wrote:
BigEd wrote:
I wasn't thinking of counting edges within fixed time slots, but taking the times that edges happen, until a byte's worth of time has been accumulated, and then resampling the implied signal at the right times for the baud rate. In effect, a software UART.
Seems to me we're all missing each other by a few bits here.. so please correct me. I think I get BigEd's idea - sample 8/1200ths worth of data and then putting everything in place retrospectively..
The problem I still have with Bell 202 here is that if your frequency -> UART implementation relies on counting edges, the error will in fact accumulate on the "edge counting side" - not on the UART side.
I've pasted a 1200Hz square wave under the attached data here to illustrate the issue - one of these bits only have a single zero-crossing, and it's not easy to see which one. (The data in question is the sample from Wiki)
I think the reason demodulating from your diagram looks challenging is that the 1200bps boundaries you've drawn are imposed from outside - they don't come from the data, or more specifically, from its zero-crossings.
Let's see if I can do a worked example, and see if that works out in any useful way.
You've drawn a regularly-sampled analogue signal incoming. I'm going to use the ticks from that as if they were timer counts, and just look for zero crossings. I'm counting by hand so there might be some mistakes, but I expect this idea not to be too sensitive to that - it's the same as a slightly fast tape, if I undercount.
First zero crossing at sample 2.
Next at 12. Then at 22. Then 35.
Then at 53. Then 69. Then 79, and then I lost count...
... but it's clear that the high frequency crosses zero every 10 samples.
So, with that data collected from timer readings, driven from polling loops or edge-sensitive interrupts, we want to construct some idea of the frequencies. Or, rather, the wavelengths.
It takes two zero crossings to make one wavelength, but note that we don't know how the signal might transition between low tone and high tone. It might even have discontinuity. But all we need are two things: an estimated time of a bit-cell transition, and then the presence or absence of a high tone. We don't actually care too much about the low tone for this purpose.
Here's the series again: 2, 12, 22, 35, 53, 69, 79, 89, ...
So the half-periods are the differences: 10, 10, 13, 18, 16, 10, 10, 10, 10, ...
So the full periods are (in a sense) one of two possibilities:
- starting at time 2, wavelengths of 20, 31, 34, 26, 20, 20, 20, ...
or
- starting at time 12, wavelengths of 23, 34, 20, 20, 20, 20, ...
and what we want is the timestamp which estimates when the high tone stopped (and became a low tone)
If the nominal period of high tone is 20, we could choose 24 as a threshold for the longest period we're prepared to call high.
So the 23 period which starts at time 12 and ends at time 35 counts as high.
And the 31 period which starts at time 22 does not count - we'll call it low.
So, we say that we've found a low-to-high transition at time 35.
Now we can sample our capture at subsequent mid-points of bit cells, indexed from time 35, or time 35 less one bit-time, which is 40 units on this scale.
So the sampling should be done at time 15, 55, 95, and so on.
Now we look again at our zero-crossing records and estimated wavelengths, at those times, and ask the question "is this within a high tone"
Time 15... yep, that's within a reconstructed 20-long wave
Time 55... nope, that's within a 34-long wave
Time 95... yep, that within a 20-long wave
So, that's my sketch of how we get from timestamps of zero-crossings, to estimated bit cell boundaries, and reconstructed wavelengths, which we can sample at bit cell midpoints.
It might well be that a simpler approach which only sees rising edges (or falling edges) would work just as well, but that's working with less information, and we've already lost a lot by turning our signal into a square wave.
As you note, it might be that you can use a single input and keep switching between rising and falling edge triggering.
It might be that analogue circuitry to detect either edge and emit a short pulse on the zero crossing wouldn't be too hard to mark.
Note that DC bias in the signal, or asymmetry in rising and falling rates, might push the timings of zero crossings in one direction or another.
When pre-processing difficult tape captures, I've found it useful to apply a high-pass filter to remove DC bias, and hum, and also to boost the two expected data-carrying frequencies.