Teensy Convolution SDR (Software Defined Radio)

Thanks Frank B.
It is within a few Hz at 1 MHz and 30 MHz both. I'm happy with that. I've thought about hooking up one of my little GPS boards to give it a precise 1 Hz clock. Then I can run a fixed clock out of the Si5351 into a Teensy pin and set it up as a counter. Then measure the error once per second and use that to keep the frequency calibrated.
 
I am working my way through the code and figuring it out bit by bit. There is a lot of stuff in there!
One thing that I am confused about is that the sampling rate can be set up to 256kHz. But the PCM1808 spec sheet is only rated to 96kHz. Are you pushing the chip beyond its specified limit or am I misunderstanding something? My receiver works with sampling rates up to 256kHz but not at 256kHz. The noise level goes up above S9 at 256kHz sampling.
And, have you tried more than 16 bit resolution? Just curious if you have tried to push it above that. I put separate power supply regulators and filtering on each circuit, and double layer shielding to keep the TFT and Teensy noise out of the detector/ADC. I can set a signal to be barely heard at 16 bits and then switch to 14 or 15 bits and it is no longer detectable, so I think that I am getting the full 16 bit resolution with my crude test.
Thanks,
Bill
 
Bill, thanks for the hint on the sample rate. I changed from 256K to 192K and I have very good FM reception - made a huge impact. I had the same overwhelming noise level on FM at 256K sample rate. Also attached a small, wide-band, 10dB RF amplifier before the front-end and that gives an enjoyably good reception.
 
Hey Les
Happy to accidentally help. :) I was playing with the different bandwidths and noticed that the 256k didn’t work but the 192k works fine. Trying to figure that out. The chip is only rated for a sample rate of 96 kHz so maybe this setting is the clock frequency for the PCM1808? I’m planning to dig into the code when I get some time.
Bill
 
Frank, Les, Bill,

I will check what difference the calibration factor makes in my build. But I remember that using a linear equation of the form y = factor * x + constant worked better than just using constant. I use a 27MHz TCXO instead of the regular crystal for the Si5351 though.

Sorry, its my fault that I did not realize that the problems associated with WFM reception in fact relate to the codec not being able to support our absurdely high sample rate ;-).

Yes, the code does considerably OVERCLOCK the ADC in the codec that you use (i.e. it provides master clock frequencies to the codec that the codec does not officially support). This makes it possible to have larger spectrum display bandwidth and also (more important) to use a high sample rate for WFM Rx. If I remember correctly, this is also stated in the readme at the beginning of the .ino-file [and of course this overclocking could kill your codec, so noone will take any responsibility for that ;-)]

Try using different sample rates for WFM, change the constant WFM_SAMPLE_RATE to a figure that works for your specific codec [192000.0f or 234375.0f].

I had no problem overclocking my PCM1808a to 256000sps sample rate, but it seems from your reports, that I was very lucky that it really worked . . .

Also it seems, overclocking can produce noise and unwanted high alias frequencies, so it may depend on your very specific codec part, which sample rate works best for your WFM reception.

The menu entry "bit" was an experimental feature, because I wanted to know with how many bits a radio station could sound nice [and it was very interesting to see, that you can listen to a radio station in reasonable quality with 5 bit or lower resolution :)]

Bill, I am not sure whether your experiment shows that your system can really take advantage of a whole 16 bit dynamic range (=96dB). Maybe you can copy a station with 16 bit, but not with 14/15 bit setting, but with the same setting a louder station will totally overload your ADC? But I am totally open to convincing arguments/experiments for this!

73 de Frank DD4WH
 
Hi Frank.

Thanks for the explanation!

I don't know why there should be a linear calibration factor. If the reference frequency is corrected, everything "should" fall into place. But some of these chips play weird tricks so who knows?

I put my PCM1808a board on the other side of a shield so had to run the I2C bus around the shield with some short coax cables. That could be my issue with not getting 256kHz to work. But my setup seems to work fine at 192kHz. I might try it with wires instead of coax to see if the capacitance of the cables is my bottleneck. Or better yet, make a PC board with super short traces!
I am impressed that you are getting 256kHz with a 96kHz chip! I would not have expected you could more than double the rated frequency. TI makes solid chips :)

I agree that my experiment is not too meaningful. But if I can barely hear a signal at 16 bits and not at 15 bits, it might mean that I have full 16 bit resolution. But you are right, the volume level changes and I might just be hearing the volume decrease. I want to see how many real bits of resolution I have -- I went to great lengths to keep the noise out of the ADC and am curious to see how well I did. I should put a dummy load on the antenna port and see where the noise level sits. Your observation is really interesting that 5 bits provides reasonable audio quality. But be careful! The audiophiles may start yelling at you for such audio blasphemy :) 24+ bits or nothing you know :-0
I think the bit experiment is quite useful. I started to try to figure out how to take the code work above 16 bits but got a bit lost due to my inadequate C coding ability. I'll keep working on it. More bits = more dynamic range so naturally I want to push it to find the limit. I'm interested in pushing the performance of this radio to see how far we can go.

I haven't written any C code for maybe 15 years so am trying to relearn it. I used to be pretty good at it but I have forgotten sooo much. Most of my programming in the past ten years has been data analysis in MATLAB. I have the full DSP, Signal Processing, electronics, and RF toolboxes if you ever need me to design or test any filters or perform analysis or whatever. I'd be happy to help with that. MATLAB makes it easy with the toolboxes. Maybe you have it already? I did a bunch of vibration analysis for large telescopes and this required me to write my own high-dynamic-range FFT routines with windows that had sideband lobes down more than 200dB. We were measuring vibration of less than 1nm in the presence of other vibration frequencies that were more than 1 mm. I really enjoy this stuff and my only frustration is my crappy coding skills in C. I'm determined to get back up to speed and have some fun with this. SDRs are fascinating! All that stuff we used to try to do in the analog domain with mediocre results.

Okay... I'm off on a tangent again.
Thanks for your help Frank. I really appreciate all the hard work you put into this and your willingness to help us newbies.

73 de Bill WH7U
 
Bill,
here is an example of an SDR built with the AD8333:
https://www.helitron.de/dj0abr/german/technik/dds/sdrrx.htm

The builder states that it works very well, but it needs a lot of preamp gain, because the AD8333 only delivers 4.7dB of gain [and the QSDs which we use, typically have 26 to 40dB of gain after the switching IC].
For that reason, you then will have to build a high end preamp with high gain AND a huge IP3 . . . so, you will need a very very good analog preselection directly after the antenna and before the preamp . . .

Concerning the "bit resolution", I personally think it would be better to measure the "dynamic range" of the whole system:
* use 50 Ohm resistor instead of an antenna
* "measure" the noise level in 500Hz bandwidth
* insert a signal of defined (high) signal level into the antenna input
* measure the largest signal level without compression / desensibilization in 500Hz bandwidth
* and the difference between the two measurements is the dynamic range of the whole SDR system
* if you can achieve 16 bit == 96dB, your system will be high end quality, I think :)

Thanks for your offer to do filter calculations in MATLAB!

One thing I once tried in MATLAB was to calculate large COMPLEX FIR filter coeffs with minimum phase response.
From my memory:
* my MATLAB version did not provide any means of calculating coefficients for complex minimum phase FIR filters
* when I calculated real coefficients, it took MATLAB about 30 minutes to calculate a filter response for 4096 coefficients
Maybe your MATLAB version does better ?
 
Hi Frank,
I see what you mean about the AD8333. That is not as great as it first appeared. I have spent a great deal of time trying to find a quadrature detector chip that is a little faster than the one we are using. The Potato Chips fit the bill, but I tried to get some and they are not currently available. I finally concluded that I would need to build it from discrete FETs, which would not be too hard, but I don't have the equipment to test and optimize the design at home. I miss having a fully equipped RF shop!

I think your dynamic range test sounds is the way to go. I don't need more dynamic range than 96dB that my goal here was to have bragging rights as in "the receiver I built has better dynamic range than your $4000 receiver". :) Not necessary but fun.

Do you have a filter in mind that you want me to try out? I have made many filters and never had them take very long, but they didn't usually have 4096 coefficients. I'll give it a try.
 
The PCM1808 works for me with 256kHz. I tried to go even higher but only a few kHz above that, it stopped working.
The SNR and other values might be much worse than with 98Khz. But with FM this does not matter much, as the absolute analog values are not important.
The quality is quite good - IF you have a strong signal.
 
Frank B. Thanks for checking on that. I'm going to experiment some more with my setup to see if I just have a lazy chip or I'm doing something wrong. I still need to replace the caps in my receiver to get my bandwidth opened up - that might be part of my issue.
 
Filter4096coeff.jpg
@DD4WH
Hi Frank,

I spent way too much time fooling with MATLAB today. Making FIR filters is easy. Making linear phase FIR filters is a bit trickier but still easy. Making minimum phase FIR filters took me a long time to figure out, but now I have a methodology that works.

I made a 4096 coefficient minimum phase FIR filter - see the attached photo. It does take about 20 minutes to generate. For less than 500 coefficients it only takes a second or two so there is a huge slowdown when going above 1000 coefficients or so.

I can also generate ARM-M C code straight from MATLAB for the filters. I got this working too - it is pretty interesting. It does generate a whole pile of C and header files for one simple filter which seems annoying. But it works!
73,
Bill WH7U
 
The PCM1808 works for me with 256kHz. I tried to go even higher but only a few kHz above that, it stopped working.
The SNR and other values might be much worse than with 98Khz. But with FM this does not matter much, as the absolute analog values are not important.
The quality is quite good - IF you have a strong signal.

Hi Frank B,
I checked again a little more carefully. At 256kHz sample rate, my S meter is almost at max with noise, so I didn't think it was working. But you are right. I can hear signals. I don't have any strong WFM stations near me so I tried it at 7MHz and the signals are there - I just can't see them on the spectrum display because it is overloaded.
Bill
 
...I have spent a great deal of time trying to find a quadrature detector chip that is a little faster than the one we are using. The Potato Chips fit the bill, but I tried to get some and they are not currently available.
...

At the Potato online shop you can get some of there bus-switches

https://www.ebay.com/str/potatosemi/GHz-Bus-Switch/_i.html?_storecat=19786622

Where is the problem? The 74LVC4066 is also available at some shops. These chips are good for RF frequencies up to 70MHz and more!

I think the RF Front-end from PA0RWE

https://pa0rwe.nl/wp-content/uploads/2019/03/sdr_frontend_schematic.jpg

is a good design for that, but change the Coilcraft transformer to a 1:4 type, that is a better match to the Ron of the QSD switches and gives 6dB more RF performance. No, I don‘t have this RF Front-end to test this, but I think this.
 
Last edited:
hi Karlchen,
I was trying to get the Potato chips from the Potato distributor listed on their website and the distributor told me they didn't have stock. I didn't know there was an online shop. I am going to order some! Thanks for the tip!

The PA0RWE is a nice board. I like the simplicity of it. The only thing I might have done differently is to put a separate 3.3V regulator on the analog circuits. See my previous rants regarding this subject ;-)

I agree that the 74LVC4066 is a great chip. According to the data sheet, the typical t-on time is 2.5 ns and the t-off time is 3.4 ns which is very fast.

Here is what I have been thinking about when I should have been sleeping... In this mixer circuit, if I have my receiver set to my maximum (non-multiplied) frequency of 50 MHz, the clock period is 20 ns (1/50 MHz). So the quadrature switches are each on for 1/4 of each 20 ns period. This means that each switch is on for 5 ns and off for 15 ns (I'm ignoring the second set of four switches but they are doing exactly the same thing). But when I consider the delays in the 74LVC4066, my switches turn on faster than they it turn off (typical of FETs due to their gate capacitance). Say we start a timer when the first switch turns on at t=0 ns. The first switch should turn off at t=5 ns and at the same time, the second switch should turn on. But the first switch actually turns on at t=2.5 ns and turns off at t=8.4 ns (5 ns + 3.4 ns). The second switch turns on at 7.5 ns (5 ns + 2.5 ns). So during the time between 7.5 ns and 8.4 ns both switches are on! This happens four times each period so we have two switches on for a total time of 0.9*4 ns = 3.6 ns during the period. This is 18% of the period.

But all the above is not exactly true either, because the switches don't switch instantly but are in a transition state between on and off so who knows what they are really doing? Acting like some strange reactance instead of switches I expect. So the impedance is going to halve while both switches are on at the same time (four times per period) and we will get these impedance induced current blips at 4X the clock frequency but with a period of 0.9 ns due to the impedance blips. This weird 200 MHz pulse chain will have strong harmonics at 200 MHz and somewhere around 243.9 MHz and 1.11 GHz (1/5ns, 1/(5-0.9 ns), 1/0.9 ns). These will almost certainly find some way to alias back down and cause trouble with birdies that move past quickly when tuning around the lower frequencies. And I see a lot of these types of birdies in my radio. But this is just a guess because imperfect mixer switching typically exhibits this kind of behavior. Every frequency mixes with every other frequency and every sum and difference frequency mixes with every other sum and difference frequency and it turns into a real mess of frequencies. But my experience is mainly with diode mixers so I don't know how much of all this applies because a QSD is really not a mixer in the true sense.

I might try and find the time to model this to determine what the real-world effect of these delta-delays are on mixer performance - I really don't know. It might be insignificant and I might be making this all up. But I think it might be an improvement to have much faster switching times so we don't have to worry about it and besides that, the Potato chips only costs a couple of extra dollars - easy fix.
 
@WH7U: not sure how the sample & hold in the Tayloe frontend will react exactly. You made a lot of good points there.

I am not sure -however- about the causes for your birdies, the cause might be related to missing frontend filtering. Probably you already use an analog lowpass filter for your frontend, which suppresses the 3rd harmonic by at least 50 or 60dB? If you dont, you will see a lot of birdies.

The Tayloe mixer is driven by a local oscillator SQUARE WAVE (from the Si5351) which contains many odd harmonics (3rd harmonic with amplitude 1/3 = 0.33, 5th harmonic with amplitude 1/5 = 0.2 and so on . . . the classic Fourier series). That means, the suppression of the odd harmonics in the Tayloe frontend is VERY WEAK.
For the 1st harmonic (which is what we want!), it is 0.9dB, which is pretty excellent ! We want very low attenuation for the fundamental
For the 3rd harmonic, it is 20 * log10(0.3333) = -9.6dB, which is pretty desastrous ! We want much higher attenuation for this unwanted signal
for the 5th harmonic, it is 20 * log10(0.2) = -14dB, which is pretty desastrous ! We want much higher attenuation for this unwanted signal

For a receive example at 7100 kHz, this means, that EVERY Tayloe mixer also receives at 3 * 7100kHz = 21300kHz [but with a suppression of 9.6dB] AND at 35500kHz [with 14dB suppression] and so on for all odd harmonics

If we assume that we want a medium quality RX, we would certainly want to attenuate the odd harmonics by at least 50dB (for a high quality receiver, we would certainly want even higher attenuation).
This means we need at least 40dB of analog lowpass filter attenuation already at three times of the receive frequency.
If you do not install any analog frontend filtering in a Tayloe frontend, you will end up with a receiver that receives at every odd harmonic (=many many birdies), which can be very annoying and irritating especially in the lower HAM bands or especially in the broadcast bands, where attenuating the third harmonic of a 100kW broadcast station by only 9.6dB will surely not be enough.

So, a set of analog frontend lowpass filters would have to suppress frequencies at 3x the RX frequency with at least 40dB, better more!

For VHF, we use this property of the Tayloe for our purpose. We need a highpass / or bandpass filter for 87MHz-108MHz and tune the receiver to one third the frequency. That means we receive the third harmonic (which has an amplitude of 1/3 of the fundamental in a square wave), however with about 10dB attenuation (because 20 * log10 (0.333) is -9.6dB)

But I am pretty sure, most Teensy Convolution SDR builders already have this kind of strict analog lowpass filtering for HF and highpass/bandpass filtering for VHF already built into their frontends. Otherwise you cannot expect good receive results.
 
View attachment 21058
@DD4WH
Hi Frank,

I spent way too much time fooling with MATLAB today. Making FIR filters is easy. Making linear phase FIR filters is a bit trickier but still easy. Making minimum phase FIR filters took me a long time to figure out, but now I have a methodology that works.

I made a 4096 coefficient minimum phase FIR filter - see the attached photo. It does take about 20 minutes to generate. For less than 500 coefficients it only takes a second or two so there is a huge slowdown when going above 1000 coefficients or so.

I can also generate ARM-M C code straight from MATLAB for the filters. I got this working too - it is pretty interesting. It does generate a whole pile of C and header files for one simple filter which seems annoying. But it works!
73,
Bill WH7U

Excellent! Thanks a lot for trying this and sorry to see it took so much of your time. Thats pretty close to my experience. It took my computer even 50% longer for the computation. However, I did not find a way to compute complex coefficients with MATLAB.

I finally found the previous discussion on this again (it is sometimes hard for me to find specific topics in the forum, but maybe my search terms were not accurate enough): https://forum.pjrc.com/threads/5726...ltering-with-Teensy-4-0-and-audio-board/page3

I think the goal of being able to compute minimum phase coeffs for complex filters is not possible with the Teensy and the task of precomputing coeffs is not possible with the standard tools of MATLAB, because there is no standard code for complex coeffs. And maybe it is not so important to lower the latency for a receiver, however when it comes to a transceiver and the ability to perform high speed QSK, it could become an issue. At the moment, the Teensy Convolution SDR has a minimum latency of 2048 samples (for the 1024-point-FFT with 50% overlap) * decimation-by-8 at a standard sample rate of 96ksps --> 2048 * 8 / 96000 = 171 millisec plus codec latency
 
Excellent! Thanks a lot for trying this and sorry to see it took so much of your time. Thats pretty close to my experience. It took my computer even 50% longer for the computation. However, I did not find a way to compute complex coefficients with MATLAB.

I finally found the previous discussion on this again (it is sometimes hard for me to find specific topics in the forum, but maybe my search terms were not accurate enough): https://forum.pjrc.com/threads/5726...ltering-with-Teensy-4-0-and-audio-board/page3

I think the goal of being able to compute minimum phase coeffs for complex filters is not possible with the Teensy and the task of precomputing coeffs is not possible with the standard tools of MATLAB, because there is no standard code for complex coeffs. And maybe it is not so important to lower the latency for a receiver, however when it comes to a transceiver and the ability to perform high speed QSK, it could become an issue. At the moment, the Teensy Convolution SDR has a minimum latency of 2048 samples (for the 1024-point-FFT with 50% overlap) * decimation-by-8 at a standard sample rate of 96ksps --> 2048 * 8 / 96000 = 171 millisec plus codec latency

Hey Frank. No problem on all the time it took. I'm learning and having fun with this stuff.
I am planning to dig into this filtering business a bit more. It may take time because I have to juggle work/fun.
I have been reading through the forum and getting up to speed, but I still don't have a block diagram etched into my brain. Sorry if I ask dumb questions.
1st dumb question: Are we using high or low IF?
2nd dumb question: I am 95% sure that I can generate the complex low latency FIR filters. But these long filters don't seem very efficient. Does it make more sense for me to create a complex bandpass decimator?
I am trying to figure out where to start the development. I'm thinking Fs=96kHz and a center frequency of Fs/4. Maybe a bandwidth of 3kHz to start? But maybe I'm going down the wrong road here because you need wider bandwidth for the display? I'm not sure if the I-Q filter is in that signal path.
Anyhow... off to a meeting. I'll try and work on this later.
73, WH7U
 
@DD4WH
Hi Frank,
I read the chapter in my DSP book on FFT convolution. I don't have the Lyons book but I do have "Digital Signal Processing" by Steven W. Smith. I also have the standard Oppenheim/Schafer book you list in your references.
Then I worked my way through the code. I think I understand what you are doing now.

Using my neophyte C coding knowledge, here is what I think you are doing:
You buffer the I and Q signals from the codec at whatever the sample rate is
You decimate them by 4 and then 2 (for a total of 8)

In the Digital Convolution section of the code:
you do all the buffer management stuff
you don't have the Nuttall window working so you don't window the buffer
you perform a complex FFT
there is an autotune thing I haven't figured out
you zero either the I or Q buffer to get LSB or USB (I didn't know that worked) or you do nothing for the other demodulators
you apply the complex filter with a 512 coeff FIR complex filter kernel
you apply a notch if it is enabled
you perform the ifft

It looks like the filter kernel is created in "calc_cplx_FIR_coeffs" and is a low pass windowed sinc filter using a Blackman-Nuttall window but you slide it up for a bandpass filter. Is that right? That is a neat trick for making a variable band pass filter.
 
Then I worked my way through the code. I think I understand what you are doing now.
Using my neophyte C coding knowledge, here is what I think you are doing:
You buffer the I and Q signals from the codec at whatever the sample rate is
You decimate them by 4 and then 2 (for a total of 8)

In the Digital Convolution section of the code:
you do all the buffer management stuff
you don't have the Nuttall window working so you don't window the buffer
you perform a complex FFT
there is an autotune thing I haven't figured out
you zero either the I or Q buffer to get LSB or USB (I didn't know that worked) or you do nothing for the other demodulators
you apply the complex filter with a 512 coeff FIR complex filter kernel
you apply a notch if it is enabled
you perform the ifft

It looks like the filter kernel is created in "calc_cplx_FIR_coeffs" and is a low pass windowed sinc filter using a Blackman-Nuttall window but you slide it up for a bandpass filter. Is that right? That is a neat trick for making a variable band pass filter.

Bill, exactly, you got it, excellent!

Some further comments on the signal flow:

* I & Q samples coming in with user-defined sample rate (as an example, lets take 96ksps)
* spectrum display (256-point FFT) can display a maximum bandwidth of 96kHz and runs at the original sample rate
* I & Q phase and amplitude are being automatically corrected by the algorithm of Moseley & Slump (so there is no need to tweak I & Q in hardware!)
* S-meter / signal level is calculated from the results of the spectrum display FFT bin magnitudes
* frequency translation by sample rate / 4, thus the IF is at 24kHz
* the desired signal is now at baseband, but still @96ksps
* decimation-by-8 in two steps (to lower the needs for steep anti-alias lowpass filters)
* now I & Q are in 12ksps sample rate [and thus the audio bandwidth is restricted to some figure lower than 6kHz]
* 512-point-FFT works in 12ksps sample rate
* the complex-multiply uses complex FIR filter coefficients [you are right, the function calc_cplx_FIR_coeffs calculates a lowpass and shifts this until we have the desired BANDPASS, IIRC, the window used is a Blackman-Harris 4-term window with a maximum sidelobe suppression of > 100dB]
* and now comes the magic: because we calculate a COMPLEX bandpass, the coefficients already contain the Hilbert transform to suppress the opposite sideband! So there is NO need to delete bins or add/subtract in order to obtain LSB or USB. Just define the bandpass, so that it cuts out the desired sideband and you are done and the opposite sideband is already suppressed (because we corrected I & Q, sideband suppression can reach 60-65dB!)
* frequency domain manual notch filter [very quick and dirty: cuts out bins]
* 512-point inverse FFT in 12ksps sample rate
* AGC (in the low sample rate to save processor cycles)
* digital mode decoders (EFR, RTTY)
* DEMODULATION: do nothing for SSB
* DEMODULATION: calculate magnitude from I & Q for AM
* DEMODULATION: calculate atan2 (Q,I) for narrowband FM [not yet implemented !]
* DEMODULATION: synchronous AM contains another Hilbert transform and a PLL
* auto-notch LMS-algorithm
* LMS noise reduction
* frequency domain noise reduction for weak signals [two different algorithms]
* CW decoding/RTTY decoding
* interpolation-by-8 in two steps (for the same reason stated above)

Thats it . . .
 
I recreated the filter kernel in calc_cplx_FIR_coeffs in MATLAB and plotted the response. I see now how it is a Hilbert filter and Bandpass filter both.
DD4WH_Filter.jpg
This is for 96 kHz sampling rate, decimation by 8, and an IF frequency of 24 kHz (that gets decimated down to 3 kHz). I set the bandwidth from 0.1 to 0.4 (normalized) which is 9600 Hz to 38400 Hz in input frequency and 1200 Hz to 4800 Hz in the baseband frequency.
 
Ok Frank. I figured out how to make complex bandpass filters. After fruitless research and less-fruitless experimentation, it is actually embarrassingly trivial. I don't know why this information is so hard to find. I can't find any good reference material on complex filters - just a bunch of unhelpful info on fancy multi-stage decimating filters which we don't need because the Teensy handles the decimation. Maybe you know of a decent reference?

Anyhow, here is how it is done:

1. Create a regular low-pass filter.
2. Create a vector of integers that run from 0:N, where N is the number of coefficients.
3. Take the low-pass numerator coefficients and scalar multiply the whole lot by e^(j*nFc*pi*(0:N)).
Where: nFc is the normalized frequency shift that you desire and (0:N) is that vector you created in step 2.

In Matlab the command is this:
cpx_coeffs = coeffs .* exp(j*nFc*pi*(0:N))

This creates a center-frequency-tunable complex bandpass filter. If the low-pass filter you started with is minimum phase, then the complex filter is also minimum phase (from my experiments so far).
I still need to figure out if any random low-pass filter will work. I don't know, but I suspect it may need a particular phase response to act the part of the Hilbert filter. I will do some more messing around tomorrow.

73,
Bill WH7U
 
Back
Top