Sunday, October 24, 2021

A CMOS FSK Modem

     While researching cassette storage, I found multiple different encodings, the most popular one being Frequency-shift Keying. It simply uses a high tone for a logical one, and a low tone for a zero. We'll be using the standard frequencies of 1,200Hz and 2,400Hz for our two tones.

FSK encoding - tutorialspoint

    Another choice we have to make is regarding phase. If we use two different oscillators for our tones, the phase will be inconsistent between them. This phase difference can cause a sharp "jump" in our output when we switch between them. The jump consists of extra harmonics that can complicate decoding, though they're actually utilized in a related encoding: "Phase-shift Keying".

Phase discontinuities (from Phase-shift keying) - Wikipedia

    If we instead change the pitch of a single oscillator, the phase will remain the same, and no extra harmonics will be created. This is called "continuous-phase" and it's the approach we'll be using.

The modulated signal is demonstrating continuous-phase - Wikipedia

    Another factor that can be important is where in the cycle the frequency change occurs. If we switch frequencies at a random point in a cycle, the length of the cycle can be anywhere between that of 1,200Hz and 2,400Hz (833-416uS). Some demodulators aren't affected by this, while some can be. In the interest of easy demodulation, we'll have a consistent switching point at the lowest extreme of the waveform.

Modulation

    So, how do we implement these features into a circuit? We can start with a simple oscillator built around a schmitt trigger. It works by charging a capacitor back and forth between two thresholds. The rate at which it charges/discharges defines the frequency, and that is set by the resistor/capacitor we select.

capacitor's charge, threshold(s), output - Wikipedia

    With our particular schmitt trigger, values of 66kΩ and 10nf give us 2,400Hz. If we can double either of these values, we'll get the other frequency we need, 1,200Hz. There are numerous ways of doing this with analog switches, FETs, etc. Here we will use a bipolar junction transistor to switch a 10nf capacitor in and out. When it's switched "in", it's in parallel with another 10nf capacitor giving an equivalent 20nf (for 1,200Hz). When it's switched "out", we're left with only the 10nf (for 2,400Hz). Now we have digital control over the frequency.

frequency switching simulation


    Notice that the frequency is switching in odd spots. In order to limit where in the cycle frequencies can shift, we add a D-type latch. It passes data through only when it sees a rising clock edge. We can use the square output of the schmitt oscillator to provide this clock edge, and the latch's output can control the frequency. This means the frequency can only change at the instant the oscillator begins to rise.

link to simulation

    Finally, we need to adapt the signal to something a cassette recorder can accept. We use the signal from the oscillator's capacitor, as it's close in amplitude to line level. We buffer it with an op-amp, since we don't want the cassette's input circuitry to load and disturb the capacitor's charging. Following that a capacitor and two resistors form a DC-removing highpass, as well as a voltage divider that gives us an additional mic-level output.

our completed modulator schematic

Demodulator

    Write-only memory isn't of much use, so let's work on reading. Some approaches use bandpass filters to determine if the signal contains a 1,200Hz tone or a 2,400Hz tone. We'll instead be detecting the difference in timing between peaks in the signal. This approach can detect frequency in as little as one cycle.
    
    Peaks can be a little tricky to detect, so we're actually going to convert our signal to a square wave, and measure between rising edges instead. After building our modulator oscillator, we have five schmitt triggers remaining. Just one will convert our signal to a square wave.
    We then highpass the square wave, and pass it through another schmitt trigger. This makes the pulses very narrow, benefiting the following stages. We'll call these pulses "edge-pulses".

square wave and pulse conversions (390Ω resistors model real schmitt outputs)

    Next, we add a monostable oscillator. It outputs a fixed-width pulse each time it gets triggered by the edge-pulses. This effectively extends the length of the edge-pulses. If we trigger it quickly enough, these extended pulses will overlap, and cease to be pulses. The output will instead be constant.
    The presence or absence of pulses is how we discriminate between frequencies. We can set the width (period) of the monostable output such that 1,200Hz will yield pulses, while 2,400Hz won't.

monostable 1

    This series of pulses isn't a very convenient signal to use for zero, so we'll convert it to a constant low signal instead.
    We can use the pulses to trigger a second monostable. If the period of this monostable is long enough, we will again have overlapping pulses that give us a constant low output.

    The period of this last monostable is somewhat critical as it impacts the maximum rate you can switch between high and low frequencies. The shorter the period, the faster the data can change. If it's too short though, there will be pulses in the zero signal. For this reason, we include a trim resistor that allows the period to be adjusted.

link to simulation

    Prior to this demodulation, we have a highpass, then a lowpassing amplifier. This brings the signal up to a level the schmitts can process, while also removing potential noise from outside the FSK range.

our complete demodulator schematic

    Combining the modulator and demodulator gives us the full modem.

a board layout


No comments:

Post a Comment