Close
0%
0%

Keeping Time with Turing

Decoding WWVB with a Turing Machine

Public Chat
Similar projects worth following
423 views
0 followers
Making a self-setting clock by decoding the WWVB signal with a TTL Turing machine.

The real purpose of the project is to develop a pair of reusable modules. One module for time acquisition and another for basic computation, in the form of a Turing machine.

This time module tunes in to the WWVB signal at 60kHz and outputs an encoded digital stream. At the moment, the antenna is little more than a coiled up ethernet cable with a capacitor soldered to each end. Really, that's all it is. The signal from the antenna is amplified by a complementary transistor pair in a folded cascode configuration and passed on to an op-amp analog filter and an op-amp rectifier. A comparator then decides whether the WWVB carrier is at its high amplitude or low amplitude.

The pulse width modulated time signal triggers a 74x221  and a 555 oscillator to control a 74x93 counter. The 555 oscillates at 10Hz, and the 221's time interval is about 0.9 seconds. The result is that the counter will show a final count of 2, 5, or 8 before being reset. (Let's disregard noise in the signal, for now.) Those values correspond to 0.2, 0.5 and 0.8 second modulation durations that are transmitted. A miniscule amount processing can turn that stream of digits in to the current time and date.

The Turing machine decoder is nearing completion, so there's only an overview for now. The 'tape' consists of an 8 bit up/down counter and a 256x4 SRAM. Those 4 bits are combined with 8 'state' bits held in a latch. Four bits are available to select the time zone offset, daylight saving flag, and display options. One last bit is used to select a high or low address in an EPROM. The 16 bit output then updates the state, writes a new value to the tape, and selects which data source (WWVB or tape) is in use.

WWVB-Z8.JPG

It's working. Here a Z8 is used to decode and display the time on an ISD2010 LED dot-matrix.

JPEG Image - 197.52 kB - 03/29/2021 at 19:50

Preview

WWVB-Receiver.JPG

A close-up look at the working receiver. Not shown is the Z8 working as decoder and display driver.

JPEG Image - 142.53 kB - 03/29/2021 at 19:50

Preview

  • 1 × am93422 Memory ICs / Static RAM (SRAM)
  • 1 × am27c010 Memory ICs / PROMs, OTP PROMs
  • 1 × 74hct646 Logic ICs / Receivers, Transceivers
  • 1 × 74hct273 Electronic Components / Misc. Electronic Components
  • 1 × 74hct257 Logic ICs / Decoders, Encoders, Multiplexers, Demultiplexers

View all 13 components

  • Cosine, it goes to zero

    Darrin B06/08/2026 at 01:57 0 comments

    Seems that I should brush up on my trig. identities. I was so pleased to eliminate one multiply by using a three to one frequency to sample rate ratio that I did not bother to see what four to one could do. Until today. At four to one, a lot of the equation disappears. Two multiplies and one add are gone!

    // variable initialization
    coeff = 2.0 * cos(2.0 * PI * ((FREQ / SAMPLE_RATE)))
    
    // in the processing loop:
    result = prev[0] * prev[0] + prev[1] * prev[1] - (coeff * prev[0] *sprev[1])
    

    The "coeff" variable initializes to zero (more likely, epsilon), so that line goes away. In the loop, the entire subtract part of the line disappears, leaving an easy a^2 + b^2.

    With the number crunching so minimized, this is the approach I will use in this project. Having an independent divide by six section, a 7492 will be useful. Has anyone ever seen one? Rather than a chain of 7474s, I'll skip straight to the PLD. The necessary division does not fit in a 16V8, but with the help of a 7474, I have a circuit to test until the 22V10s arrive.

    The one-chip wonder circuit has been steadily improving, most recently reaching S9+36 while tuned to WWVB. This iteration also has a wide(-ish) band output stage and Quisk was showing two signals in addition to WWVB. One is at 69.2 KHz and is either east or west of my location. The other signal appears every three seconds just long enough for a beep-beep and then it is gone for three more seconds.

  • Almost wireless: 1/8300 wavelength antenna

    Darrin B06/03/2026 at 20:27 0 comments

    The One Chip Wonder circuit has been performing so well, that I began to move on to detecting and digitizing the signal. Diode envelope detector? Nope, not quite enough input level. Op-amp precision rectifier circuit? Well, there was something at the output, but I couldn't figure out what it meant. I recorded some audio with audacity and checked the FFT of the signal. Nothing unexpected, a 2500-ish Hz tone and noise. Ok, a tone decoder then. Not quite. The tone is always present, sometimes at full amplitude, somethines reduced. The output went high, and then stayed there. What now? Well, we could number crunch an FFT for 0.1 seconds of signal ten times a second... Umm, no. Enter the Goertzel Filter, think of it as a simplified FFT that only returns the result for one frequency. A miniscule amout of code later, and pre-recorded .WAV files are turning in to square waves with mind blowingly perfect 0.2, 0.5, or 0.8 second intervals. This is what I want!

    Simple as the calculation is, I wondered if strategically chosen frequencies could simplify things further. Sure enough. When the sample rate is six times the frequency being tested, a term usually called "coefficient" becomes 1.0000, this eliminates most of the multiply operations entirely. Sweeeeet! After crunching some numbers, I arrived at 2.4 kHz for the frequency and 14.4 kHz for the sample rate. That would put the oscillator at 57.6 kHz to tune in WWVB's 60 kHz. That will work, but I would have to order an ADC because the ADC0804 in the parts bin won't quite handle the needed 14.4 kHz sample rate. Looking again at the algorithm, a sample rate that is just three times the frequency sought turns the coefficient value in to -1. Still no multiplies and we just swap subtract and add operations. So, frequency 2.4 kHz, sample rate 7.2 kHz, and oscillator 57.6 kHz. Do these numbers look familiar to you? They're baud rates! I can use a baud rate generator crystal (1.8432 MHz) and flip-flops to derive all of the frequencies needed to run the system.

    With a crystal controlled frequency source, I can use a very narrow bandpass filter to home in on the 2400 Hz difference frequency coming from the mixer. But what sort of mixer this time? The final stage of the oscillator divider is a 74LS74 with its' handy complementary outputs, I have an idea. Unlike previous circuits, what if we switch to ground rather than effectively floating the signal path with a "OFF" switch or MOSFET?

    Here is the new circuit:

    Quisk is reporting up to S9+31 with the ethernet cable loop antenna. It is easy to see the 1s, 0s and marks in the Audacity captures. Swapping the loop for a 60 cm. piece of wire (1/8300 wavelength) drops the signal to S9+21 with very good audibility. I think it might be time to stop using bits of wire and go look for a normal sort of antenna.

  • A one chip wonder

    Darrin B05/05/2026 at 18:01 0 comments

    Radio is such a rabbit hole. I fiddled with the GAL based RCDR (R-C Defined Radio) for a few weeks, learning, sometimes re-learning, interesting things along the way. Since the GAL could not directly switch the antenna signal, it seemed to be overkill for a simple receiver. So, I rebuilt the receiver with just TTL devices, a pair of XOR gates for the oscillator and a 7476 J-K flip-flop for the quadrature divider. I still used the 4066 switch, but it was soon replaced with MOSFETs and later, diodes. Still, the circuit looked excessive for the task.

    The first thing to go was the decoding and processing of the quadrature signal, it is not needed for the CW signal. That means that there is one less op-amp and half as many switches/MOSFETs/diodes needed. A good start. Hold on, op-amps can oscillate, do I really need the XORs? Nope, they are gone. One less chip!

    Since the Q signal is no longer being used, do we really need to generate it? Nope. That removes the divide by four, so no more flip-flops. All that remains is a dual op-amp and switch chip. Sayonara switches, you are diodes now. The op-amp is the last chip standing. We have a winner!

    If a dual op-amp is all that is needed to form the core of a receiver, what could another pair of op-amps, from the quad package version, bring to the party?

    Read more »

  • A New Low In Radio?

    Darrin B04/07/2026 at 20:54 0 comments

    For this log entry, I was planning to write about using a GAL and an op-amp to create the WWVB receiver with just two chips. Not quite, it turns out the inputs of the GAL are buffered to permit an input singal to be used throughout the device while appearing as a single TTL load to the outside world.

    With that plan out the window, a new one was devised. Configure one cell as a buffer and another as an inverter. These two cells are used to create a resistor-capacitor fixed frequency oscillator. Adjust R1, R2 and C to oscillate at four times the frequency that we are interested in. For WWVB that would be 240kHz, easy peasy. (See Stupid PLD Tricks later in the project logs.) Next up, use two more cells to create a two bit Johnson counter or, if you look at it sideways, it becomes a quadrature clock divider. Do you see where we are going now? If not, here are a couple of relevant Hack-A-Day articles:

    https://hackaday.com/2024/03/19/breadboard-sdr-doesnt-need-much/

    https://hackaday.com/2021/04/19/a-superheterodyne-receiver-with-a-74xx-twist/#comment-6341125

    The remaining cells are decoded I and Q signals, with a handy active high/active low Mode selector. Formatted for GALasm, it looks like this:

    BufOut =  BufIn;
    InvOut = /InvIn;
    I.R = /Q;
    Q.R = I;
    Y0 = I * Q * Mode + /I * /Mode + /Q * /Mode;
    Y1 = /I * Q * Mode + I * /Mode + /Q * /Mode;
    Y2 = /I * /Q * Mode + I * /Mode + Q * /Mode;
    Y3 = I * /Q * Mode + /I * /Mode + Q * /Mode;

    Once things were programmed, connected, powered and a suitable RC was selected, I was rewarded with beeping. Digital chips can make a receiver. Far out!

  • Thawing a project

    Darrin B02/02/2024 at 20:37 0 comments

    With the Well Well project nearing completion, this project is beginning it's move off of the back burner. It began with a few ideas for the input stage, but lately the display is on my mind. At the moment, the leading candidate for the display is a set of dot-matrix LED modules that have been languishing in my parts heap for many years.

    Though a decimal display (0-9) is all that would be needed for the clock's display, hexadecimal output (0-9, A-F) would be helpful for debugging the Turing machine. One or another form of programmable memory(EPROM, Flash) would make short work of building a display driver, but it would be very under utilized. The smallest EPROM I have is a second sourced Intel 1702 with a 1973 date code, and it has more than twice the storage needed (along with some odd voltage requirements). What else could be used here?

    That's right, another PLD enters the project, could a 16V8 be used as a dot matrix display controller? Almost, but not entirely, though altering the font may make it possible. Rather than try my hand at font re-design, I looked at the 22V10 device. It didn't just fit, there looked to be enough space to upgrade to hexadecimal. Again it would almost fit in the device, but a few of the unused outputs could be used in a wired-OR configuration. Wait a second, I forgot that I made the logic equations around using an active-low output. What if, I rearranged the equations one more time by moving that NOT? With a simple reassignment of output pins, a hexadecimal row driver fits in a single 22V10! I now have a one chip per digit row driver without external OR-ing and there may even be space left over for a few more symbols.

    With the row driver handled, on to the column driver. At first glance, we'll need an oscillator (555), a counter (7490), a row selector (74138), and a little bit of logic to reset the counter (7400). Ok, I could probably drop the 555 by creatively using part of the 7400 as the oscillator. Not bad, just three chips to cycle through the five row selects. Oh hell, another PLD? In Stupid PLD Tricks I use two cells of a 16V8 as an oscillator, now use five of the remaining cells as a one-hot five bit counter. Column selector done!

    That was was easy, wasn't it? Maybe adding PWM brightness control would be a challenge.

  • Stupid PLD Tricks?

    Darrin B07/21/2021 at 15:11 0 comments

    Early on, I chose quadrature clock to control the system. It would yield a 50% duty cycle, lots of useful timing states and, in a typical implementation, the complements of both timing signals. While I was working out the gating arrangements for the various latches, write lines, and other control signals, I noticed that state sequence of the clock was identical to that of a Johnson counter. Those are synchronous counters that can be implemented in a typical PLD, with plenty logic cells remaining for other uses.

    Reducing the chip count on a protoboard is always welcome, add in some re-programmable logic (in case I goofed up DeMorganizing) and I see a win. There's one last chip that may be merged in to the GAL16V8 that I had in mind, a 74HCT00 that is mostly used as the clock oscillator. Can I make a GAL be its' own clock source?

    The flip-flop in the output cell of the GAL-V chips can be bypassed, allowing an output to act as an ordinary logic device. Looking at a few oscillator schematics, most could be implemented with inverters or inverter and buffer combinations. After a trial, or two, it occurred to me to upgrade the inverter and buffer to XOR gates. Now I have selectable invert or non-inverting inputs for both devices, by simply moving a jumper to VCC or Gnd, respectively.

    An appnote from OnSemi provided some useful insight in to building the oscillator. The first few attempts didn't work, but then one variation began to oscillate when I powered down the circuit. Some poking and prodding later... Oh, right gate input current. The gate input isn't the gate, it's the source terminal. Check the datasheet, the input leakage is up to 100uA, with a 0.8V logic threshold. Drop a 7.5k resistor in there, it starts up every time! The only rant is that the duty cycle is around 40%, but connecting the oscillator output to the clock input of the same GAL to drive the registered outputs of the counter will clean that up.

    It is an odd looking thing, but it is a adjustable frequency oscillator and quadrature clock divider that uses just 4 cells of a PLD. I wasn't planning to make this a PLD centric project, they're just so handy.

  • Parts shortage?

    Darrin B06/26/2021 at 17:10 0 comments

    Prototyping with pulled parts has pitfalls. I needed one more 555 to test a GAL16V8[1] based counter. Why GAL based? My preferred sources didn't have any 74x469 or '491s in stock, and I've been meaning to fool around with some GALs. Considering the parts I tend to favor, it's odd that I don't have any sort of ROM burner laying around. No matter, that's what the Z8 dev board is for. Between GALasm and ATFBlast docs, I built a working programmer. I cheated a bit, though. First, I didn't bother with proper logic level interfacing, and I used the SPI port for the serial data transfers (reverse the bit order). After a bit of learning, problem solving, debugging, and DeMorgan-izing, I had a counter ready for testing. The output was gibberish. Back one step, more code, debugging, more de-coupling capacitors, WinCUPL, test cases, Re-Morgan-izing, and now hair-pulling. About one month of this passes, but a simplified counter has just one error in the count. It is jumping from 255 to 1, despite the LSB term being:

    Q0.D=/Q0;

    How can this be? I hooked up flip-flop, an XOR gate, and a few LEDs, just to watch this last clock cycle. The problem disappeared. The flip-flop output should match the output of the Q0 output of the GAL with the XOR lighting a LED when it doesn't. It never lit. Check again. Still working. The other LED? It is on the high-side of the 555's output. Take it out, and the bug returns! I've never seen a 555 with an open-collector output before. My parts shortage has an open. Just goes to show that one can never have enough 555s.

    I'll have to keep this 555 handy, could be helpful should I ever need to reverse-engineer a locked GAL16.

    Just a few changes to the down-counting logic, and now I have an 8 bit up/down counter that mostly fits in a single GAL16V8. All it needs is an external pair of Wired-OR and a pair of Wired-AND gates to fit in a breadboard friendly 12 pin wide footprint.

  • Interlude and Here's a Hack

    Darrin B04/03/2021 at 17:19 0 comments

    Just as I begin building the Turing machine part of this project, I get an insight in to how to better balance the bias voltages in the folded cascode input stage. After a quick recalculation of the voltages and currents, SPICE is reporting nearly 70dB gain at 60kHz. Oh my. I may need that AGC circuit, after all.

    With the digital clocking logic built, I began to build the 'tape' part of the system. The plan was to use a 16 bit up/down counter to pluck a value from an SRAM chip. Nope, no 8 bit up/down counter chips on hand. Sadly, there is only one 4 bit up/down counter chip in the stash. (Even looked over some old mother boards.) Implement a counter with gates and flip-flops? Madness!

    Since the result is derived from the input, would an EPROM be a solution? Each 8 bit value would require 2 values, one would be "up", the other "down". Using a 74x273 latch to hold the previous output of the EPROM, a new clock pulse to the latch would latch a new value based on the status of the up/down signal. This could work.

  • Got Time

    Darrin B03/26/2021 at 16:57 0 comments

    A better antenna, folded cascode input amplifier, and a little bit of code yields the current time!

    The antenna is simply 4 turns of unshielded, twisted pair cat-3 wrapped in a 40 cm. (15 in.) loop, held together with wire twist-ties. The individual wires are connected to form 28-turn continuous loop, in parallel with a 0.01uF capacitor to tune the loop to 60kHz. The remaining 4 turns are made in to a second loop, where one end is the input to the receiver and the other is connected to an end of the 28-turn loop and ground.

    As I twiddled with the simulation of the new input amplifier, the gain was heading toward 40dB, not bad for a 2N3904 / 2N3906 pair. When build time came, the constant-current source in the simulated circuit was replaced with a resistor on the breadboard, with little change in performance.

    Trading the full-wave rectifier for a half-wave with a peak detector allows for even more gain. During testing, I had to dial the signal generator to the minimum output to not have clipping at the peak detector. Neither my oscilloscope nor voltmeter could measure the input signal.

    Turning the peak detector's output in to a nice 3.3V logic was quite an exercise. Initially, I used a fixed threshold, which worked well enough. Considering the varying nature of the input signal, a variable threshold for the comparator seemed to be necessary. A few days in that rabbit-hole, and things are no better. Finally, I settled on using a simple resistor-capacitor, with a long time constant, to provide the varying input for the comparator.

    Here is the current design, with a handy output for 3.3V logic:

    I'm still considering turning the gain up little more, along with adding a gain control circuit to the mix. That's for another time, I want to build a Turing machine!

  • Staying Grounded

    Darrin B03/20/2021 at 19:26 0 comments

    Turns out that what I thought would be a quick test, became anything but. After writing a preliminary WWVB decoder and display driver, I hitched the receiver up to a Z8 dev-board. Suddenly, there is no signal. Eventually, I worked out that the scope gave the receiver a very nice earth ground, and that using a 5V wall-wart for power took that ground away.

    Because I am prototyping this on a solderless breadboard, I understood that the circuit's behavior would be a bit off from the calculated value. With the signal at 60kHz and using relatively low resistance values in the filter, a few picofarads shouldn't make a huge difference, right? There was some, so a few changes were made and some more gain was found.

    There still remains to choose an antenna. A long-wire antenna is usually the easiest to implement, until one realizes that the wavelength of a 60kHz signal is 5km. Yeah, that's over 3 miles of wire! The Mountain House is on a fair-sized patch of nowhere, but even a quarter-wave would go way out of bounds. A ferrite rod from an A.M. radio could be pressed in to service, but would need re-winding. That could be a lot of effort for an insufficient result. A promising alternative is a loop antenna, specifically a "small" loop. The definition of small in this context appears to be an antenna that is less than 10% of the wavelength. I'm starting with 100 m. of wire...

View all 12 project logs

Enjoy this project?

Share

Discussions

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates