So I would like to try to modulate data using the direction of frequency sweep (a data bit of 1 would be an up sweep, and 0 a down sweep). Encoding my transmit signal is fairly easy, but i'm not sure how I would actually go about decoding the received signal. To help make things clear, please see the figure below where I have and 8 bit data stream, and the spectrogram of the transmitted and received signal. For this example my sampling frequency is $4000\textrm{ Hz}$, and my frequency sweeps are going from $0$ to $2000\textrm{ Hz}$

enter image description here

I've also added in a channel aspect the the figure above. My channel will be unkown, and will change from time to time (but will be constant during any single transmission). The figure below shows the channel response, which is just 2 stop bands.

enter image description here

In the first figure, I and can clearly see the patern of an up sweep and down sweep, but I'm not sure how I would go about actually decoding in an algorithm. I've done work with differential encoding (DPSK) and know how a method to sync and decode that kind of data, but i'm not quite sure where I would start here. The only think I could think of is to take over lapping FFT's and see which bins have the highest magnitude and try to track the direction from there.

Thanks for any input! Please let me know if I can clarify anything!


I tried using two matched filters as MBaz suggested such that my matched filter for my up sweep is $h$ = up sweep signal, in MATLAB it's chirp(time,startFreq,1,stopFreq). I'm then creating my matched filter output as seen below, where $y[n]$ is my output, and $x[n]$ is my received signal

$$y[n] = \sum_{i=0}^{\textrm{length}[h]} h[i]\star x[n+i]$$

I get the output as seen below, with thin spikes corresponding to the appropriate up and down sweeps. (note, it's hard to see, but there is a spike at the very beginning of the up sweep plot)

enter image description here

I'm hoping to get something similar to the bottom plot on the figure below, where the plot peaks at the end of the symbol, which could be used for syncing of the signal I believe.

enter image description here

  • 1
    $\begingroup$ My first approach would be to use two matched filters, and compare their outputs -- the largest output identifies the signal. $\endgroup$
    – MBaz
    Feb 8, 2017 at 17:48
  • 1
    $\begingroup$ there is an answer and an old paper that might be overkill for your application, but if you go the FFT route, there is a way to directly estimate the sweep rate (of which the sign is the sweep direction). $\endgroup$ Feb 8, 2017 at 18:55
  • $\begingroup$ @MBaz I tried to do a match filter, or at least what I thought was a match filter, but i'm only getting spikes when it detects a up sweep or down sweep. I was expecting more of a triangular graph, sort of like the picture seen here. Right now i'm correlating between my complete transmitted signal (all 8 bits) and my match filter $H=$ up freq sweep. so something like $y(n) = \sum_{i=0}^{length(H)} H(i) * x(n+i)$ where $y(t)$ is my match filter output, and $x(n)$ is my received signal. Should I be doing this another way? $\endgroup$ Feb 8, 2017 at 21:47
  • $\begingroup$ I can't say if your implementation is right, but as long as you get a larger spike from the appropriate matched filter, you should be fine? $\endgroup$
    – MBaz
    Feb 8, 2017 at 22:51
  • $\begingroup$ I was hoping to get a signal that have a somewhat linear slope, that would peak, or stay flat, which could then be used to sync the signal. a spike might work, but i'm worried that i won't know what threshold to use to detect it as a 1 or 0. Also, the spike i'm getting is very narrow. really only 1-2 samples. $\endgroup$ Feb 8, 2017 at 23:05

1 Answer 1


See below for a python matched filter implementation. I generate an up-chirp and down-chirp. Then, subsequently I filter this signal by two matched filters, each filter is matched to one signal shape. As you see, there are two very strong peaks in the matched filtering. The reason why there are two peaks instead of (what you expect) slowly growing and falling triangles is that the chirps create an orthogonal basis, i.e. two time-shifted chirps are orthogonal, i.e. the MF output is zero. (The chirps are only orthogonal for infinite-time, which we dont have here, so there is still some small non-zero MF output).

import scipy

Fs = 10000
t = np.arange(0, 2, 1/Fs)

f = 500*(2-t)

signal = np.sin(2*np.pi*f*t)  # generate an down- and upchirp

f_ax, t_ax, Sxx = scipy.signal.spectrogram(signal, Fs)

plt.pcolormesh(t_ax, f_ax, Sxx)

plt.plot(t, np.real(signal))

chirpDown = signal[:int(Fs)]  # extract both signal shapes from the signal
chirpUp = signal[int(Fs):]

rx = signal + 0*np.random.randn(*signal.shape)

# perform the matched filtering (this means convolving with the time-reversed sequence)
t_c = np.arange(0, 3, 1/Fs)[:-1]
plt.plot(t_c, np.convolve(chirpDown[::-1], rx))
plt.plot(t_c, np.convolve(chirpUp[::-1], rx));

enter image description here

So, in order to detect those peaks, you can select the maximum of the MF output for each symbol duration (in case you are not perfectly synchronized) and compare which MF had higher output. Then, you reset the maximum value and search the next symbol period. Alternatively, you can convolve the filter output with some triangle or Gaussian, to get wider peaks. For example, you can do the following to get an output similar to your posted figure:

triang = 1-abs(np.arange(-1,1,1/Fs))
# perform the matched filtering
t_c = np.arange(0, 3, 1/Fs)[:-1]
mf1 = np.convolve(chirpDown[::-1], rx)
mf2 = np.convolve(chirpUp[::-1], rx)
plt.plot(t_c, mf1)
plt.plot(t_c, mf2)

plt.plot(np.convolve(mf1-mf2, triang))

enter image description here


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.