Question

I have almost completed my open source DCF77 decoder project. It all started out when I noticed that the standard (Arduino) DCF77 libraries perform very poorly on noisy signals. Especially I was never able to get the time out of the decoders when the antenna was close to the computer or when my washing machine was running.

My first approach was to add a (digital) exponential filter + trigger to the incoming signal.

Although this improved the situation significantly, it was still not really good. Then I started to read some standard books on digital signal processing and especially the original works of Claude Elwood Shannon. My conclusion was that the proper approach would be to not "decode" the signal at all because it is (except for leap seconds) completely known a priori. Instead it would be more appropriate to match the received data to a locally synthesized signal and just determine the proper phase. This in turn would reduce the effective bandwidth by some orders of magnitude and thus reduce the noise significantly.

Phase detection implies the need for fast convolution. The standard approach for efficient convolution is of course the fast Fourier transform. However I am implementing for the Arduino / Atmega 328. Thus I have only 2k RAM. So instead of the straightforward approach with FFT, I started stacking matched phase locked loop filters. I documented the different project stages here:

I searched the internet quite extensively and found no similar approach. Still I wonder if there are similar (and maybe better) implementations. Or if there exist research on this kind of signal reconstruction.

What I am not searching for: designing optimized codes for getting close to the Shannon limit. I am also not searching for information on the superimposed PRNG code on DCF77. I also do not need hints on "matched filters" as my current implementation is an approximation of a matched filter. Specific hints on Viterbi Decoders or Trellis approaches are not what I am searching for - unless they address the issue of tight CPU and RAM constraints.

What I am searching for: are there any descriptions / implementations of other non-trivial algorithms for decoding signals like DCF77, with limited CPU and RAM in the presence of significant noise? Maybe in some books or papers from the pre internet era?

Was it helpful?

Solution 2

The reference to matched filters by Ollie B. is not what I was asking for. I already covered this before in my blog.

However by now I received a very good hint by private mail. There exists a paper "Performance Analysis and Receiver Architectures of DCF77 Radio-Controlled Clocks" by Daniel Engeler. This is the kind of stuff I am searching for.

With further searches starting from the Engeler paper I found the following German patents DE3733966A1 - Anordnung zum Empfang stark gestoerter Signale des Senders dcf-77 and DE4219417C2 - Schmalbandempfänger für Datensignale.

OTHER TIPS

Have you considered using a chip matched filter to perform your convolution?

http://en.wikipedia.org/wiki/Matched_filter

They are almost trivially easy to implement, as each chip / bit period can be implemented as a n add subtract delay line ( use a circular buffer )

A simple one for a square wave (will also work, but less optimal with other waveforms) of unknown sequence (but known frequency) can be implemented something like this:

// Filter class
template <int samples_per_bit>
class matchedFilter(
   public:
      // constructor
      matchedFilter() : acc(0) {};

      // destructor
      ~matchedFilter() {};

      int filterInput(int next_sample){
        int temp;
        temp = sample_buffer.insert(nextSample);
        temp -= next_sample;
        temp -= result_buffer.insert(temp);
        return temp;
      };

   private:
     int acc;
     CircularBuffer<samples_per_bit> sample_buffer;
     CircularBuffer<samples_per_bit> result_buffer;
);

// Circular buffer
template <int length>
class CircularBuffer(
   public:
      // constructor
      CircularBuffer() : element(0) {
         buffer.fill(0);
      };
      // destructor
      ~CircularBuffer(){};

      int insert(int new_element){
        int temp;
        temp = array[element_pos];
        array[element_pos] = new_element;
        element_pos += 1;
        if (element_pos == length){
           element_pos = 0;
        };
        return temp;
      }

   private:
      std::array<int, length> buffer;
      int element_pos;
);

As you can see, resource wise, this is relatively trivial. It there is a specific waveform you're after, you can cascade these together to give a longer correlation.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top