Timer tricks for decoding FSK, not quite working

Go To Last Post
9 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm work on a project that needs a "fallback" communication protocol, which will likely end up to be BFSK. The trick is to see if I can capture this entirely in software on the Xmega. The challenge is that the base frequencies are going to be quite fast, probably at least F_CPU/4 and maybe faster if possible.

Now, the trick I've dreamed up would seem to work in theory, but practice is being a little difficult. It seems I'm either misreading the datasheet about a key point, or there's something else going on that's not described properly.

My theory is this: timer #1 is free-running at F_CPU, but the input waveform is routed to an event that is configured with TC.CTRLD = TC_EVACT_RESTART_gc. What that does is cause the counter to start at zero and run up to the number of period of the incoming waveform, then start over.

Now, I set a compare channel to a value that's just above the expected period for the waveform I'm attempting to discriminate. For example, with F_CPU=32MHz and the incoming waveform at 1MHz, the counter should range from 0 to 31 and back, so I set CCA to 33 or 34.

Now, timer #2 is set up at some much slower rate, and what it does is check out the CCAIF bit. If the bit it set, that means the period of the waveform is *longer* than what I'm expecting at 1MHz, and thus the frequency is *higher* than that. If CCAIF is not set, the input freq is lower than that. After each timer #2 fire, it clears CCAIF for the next period.

Now, the theory is that CCAIF *latches* during every timer #2 period (currently 10mS for testing), so any single waveform period that's longer than expected will trigger it. Thus for every period I can determine if the frequency is higher or lower than the threshold, and CCAIF becomes the input bit to an oversampling serial receiver.

If I set CCA to 25, CCAIF should be set for every single sampling period. There are 10000 waveforms, every single one of which should bring the TC.CNT well past 25 and thus latch CCAIF on. However, that is *not* what's happening. I only find CCAIF on a fraction of the time, as if it's either not latching on, or being reset by something.

The best thing I can think would be resetting it would be the RESTART command triggered by the incoming event, which would defeat the purpose of the whole exercise.

The problem is that if this trick doesn't fly, I'll have to look into doing single-shot frequency capture at a very high oversampling ratio, which puts some pretty severe restrictions on the datarate. Alternately, I have the option of adding a PLL with lock detector (e.g. CD7046) and using the lock output as input to a USART, but that's a fair bit outside my expertise...

So, does anybody have any idea why it is that CCAIF isn't latching, or know of another technique that could work reasonably well in software? Or a straightforward example of somebody using a CD4046/7046 as an FSK discriminator?

Thanks!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Out of interest, what sort of baud rate are you planning to use?

Quebracho seems to be the hardest wood.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

John_A_Brown wrote:
Out of interest, what sort of baud rate are you planning to use?

Not sure yet, but nothing particularly fast. It's a fallback from the 4Mbps base rate if bus conditions are problematic, with the intent of making the necessary changes so it works again (e.g. receiver equalization, etc).

OTOH it should be fast enough to deal with the fact that there might be several dozen nodes on the bus that all need to be worked with before the main datarate can be tried again. 100Kbps would be a good start.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

How many periodes do you count on pr bit?
A simple way would be to count up on the input, and with the baud rate check the counter difference, the biggest problem would be the start sync.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

sparrow2 wrote:
How many periodes do you count on pr bit?
A simple way would be to count up on the input, and with the baud rate check the counter difference, the biggest problem would be the start sync.

True, and probably simpler. I've been tossing around ideas for using timers to trigger stuff to get higher speeds enough that I guess I kinda tossed that idea out earlier on, when I should just be getting over the baudrate issue and using simpler methods like that.

I still want to make use of a CCx channel to see if I can line up my oversampling sequence to the incoming bit offset, but that can be a single-shot interrupt on CCx detecting a transition to the lower of the two frequencies.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

(thinking out loud....)

Just had another idea, if a little bit of external hardware can be used:

Use the above trick where the incoming waveform RESTARTs a free-running timer. Instead of trying to latch a CC channel going over a given level, set it up with a compare output on a port pin. Set the CC somewhere between the two periods in question, which should generate two different duty cycles on the compare pin. Hook up an R/C filter to that pin, then drive the analog comparator from that. Set the AC's threshold between the two resultant duty cycles, and then jumper the AC's output pin into a USART Rx....

If you set the thresholds and R/C right, it could be a 100% "software-free" way to pull off basic FSK or OOK reception.

I'll see if I can start constructing such a beast here in a bit.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Perhaps you can use a U(S)ART to make and receive the data. If you get 1 or 2 (perhaps3) bit pr UART byte. I think you will need a 256 LUT to read the bits (more than 1 received byte will give the same result).
But again the sync of the start will be the key factor.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Your thinking aloud is interesting, and could work, but I think you need to get to the bottom of why your initial scheme failed, as I feel that you need to know exactly what effect the RESTART has.
If a baudrate of around 100K is required, I might look at a scheme that counts the input pulses. An interrupt(or possibly an event - it's a while since I attended that XMega seminar) could then reset the pulse counter and make a bit decision.

Please keep us posted on your progress, I always find this sort of thing(trying to use the hardware in a novel way) interesting.
Sorry I can't be more help.

Quebracho seems to be the hardest wood.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So I got the above trick to work to some degree, though I didn't tie it into a USART yet, because I don't have a quick means of switching the frequency at this point (the breakout board I'm using for the PLL/crystal ties the control pin rather than exposing it, that's *my* screwup).

The R/C filter I'm using is just cobbled together from a few spare parts floating on my desk, it could use a lot of tuning. But the VCC scaler in the comparator is just enough to get a reliable detection between even the relatively close frequencies of 4.0 and 4.08MHz (200MHz/50 and /49). The problem is the latency of detection, on the order of milliseconds, because of the R/C.

In real usage I'd be much more tempted to use a DAC channel than the VCC scaler though, since that gives 12-bit resolution instead of 6, and depending on conditions 6 would *very* easily not be enough.