Generating PASM IIR digital filters using Python (scipy.signal library).

This is something I've posted a rudimentary version of before, but as an aside, and I've been improving and enhancing the code recently.

The python scipy.signal library has lots of stuff for designing digital filters easily. I've put together some code to generate PASM implementations of IIR (infinite impulse response) digital filters using this. The code also uses matplotlib the Python plotting library to show the response of the filter too. You can specify a bit depth for the coefficients to speed up and reduce the size of the generated code.

There are some problems still for some filters, the code to gather zeroes and poles into stages is decided ropey for edge cases, but many things work.

I've used one of the examples (band_pass_2) on my Prop audio board (it has I2S ADC and DAC so can handle 24 bit audio sampled at 48kHz) to show the actual performance matches the calculated performance well (~90 dB S/N).

(The slight slope on the passband is due to my spectrum analyzer's tracking generator AC coupled output dropping in amplitude below about 15kHz)

The main graphs displayed show response in magnitude and phase and impulse and step responses:

There is also a complex filter mode, demonstrated by one of the examples.

Have fun!



  • 5 Comments sorted by Date Added Votes
  • I should mention that that example filter was basically generated in Python with one function call:
    z, p, g = ellip (8, ripple_dB, stop_band_dB, [cut1/nyquist, cut2/nyquist], btype = 'bandpass', analog = False, output = 'zpk')
  • And the bulk of the generated code is multipling by constant coefficients done as a series of shifts, adds, subs:
    coeff3_b1                                ' value += t * -0.956665 [ +0.f4e80 hex ]
                    sub     value, t
                    sar     t, #4
                    add     value, t
                    sar     t, #2
                    sub     value, t
                    sar     t, #2
                    sub     value, t
                    sar     t, #3
                    add     value, t
                    sar     t, #2
                    sub     value, t
    coeff3_b1_ret   ret                      ' 48 cycles (I2S: 0.488 us, standard: 0.600 us) 12 instructs
  • For complex filters you have to explicitly place the poles and zeroes assymetrically in the Z-plane
    (I take a low pass filter and rotate all the zeroes and poles around the origin in the example to make
    a single-sideband band-pass quadrature filter).

    The graph plots for a complex filter show the negative frequency domain as well and the impulse/step
    responses in quadrature

  • BTW that audio board I mentioned uses some old Wolfson micro chips I've had for a while (they seem to have gone out of business AFAICT), the WM8524G DAC and WM8783GED ADC:
    The crystal is 6.144MHz which allows standard I2S 48kSPS and 96kSPS - puts the system clock up to over 98MHz.

    Separate 3.3V regulators power the digital and analog supplies.

    A single cog (plus one timer on the main cog) can drive the ADC and DAC at 48kSPS with enough cycles to spare to estimate incoming dB and apply a power-of-two scale factor to the outgoing samples.

    I'm using the board to verify and experiment with digital filtering and processing of audio using the prop.
  • 98MHz overclocking provided you decouple the prop correctly. You seem to have done this. My RamBlade runs at 104MHz without any problems and I have tried 108MHz too which didn't give any problems but not tested as much. My P8XBlade2 is clocked at 96MHz using a 12MHz xtal without problems. I wanted to do software USB but just haven't completed it.

    Anyway, your board looks nice. Pity about the ADC chips EOL.
    My Prop boards: P8XBlade2, RamBlade, CpuBlade, TriBlade
    Prop OS (also see Sphinx, PropDos, PropCmd, Spinix)
    Prop Tools (Index) , Emulators (Index) , ZiCog (Z80)
Sign In or Register to comment.