Shop OBEX P1 Docs P2 Docs Learn Events
ADC driver for Spin2 with filtered Sinc2 and Sinc3 modes — Parallax Forums

ADC driver for Spin2 with filtered Sinc2 and Sinc3 modes

RaymanRayman Posts: 14,744
edited 2023-06-12 21:36 in Propeller 2

Here's my attempt at a more featured ADC driver for Spin2.
This is adapted from my ADC.h C version...

Warning: DO NOT APPLY 5V to P2 I/O Pins (or you'll break them). 3.3V is kind of the recommended max. input.

Update: Added a simpler version

Comments

  • evanhevanh Posts: 16,027

    If wanting to test behaviour of full numerical range then use 3x gain instead of 1x gain.

  • RaymanRayman Posts: 14,744

    The high gain modes are interesting …
    Seems like you want external circuitry to use them to bat advantage…

  • RaymanRayman Posts: 14,744

    Just added a simpler version of the driver that assumes 1X and max. samples.

  • evanhevanh Posts: 16,027
    edited 2023-06-16 13:42

    Looking at your Sinc3 sampling routine, it works but, from reading your comments, I'll mention that x is not an accumulator. It's a double-differential - Matching two of the smartpin's accumulators. (There is a third pair of accumulate-differentiate that is done as a trick in the smartpin so RDPIN isn't directly reading from an accumulator either. All up this makes it a third-order filter, hence the Sinc3 naming.)

    As such there is no need to clear the working variables beforehand. x is overwritten on every pass. diff1 and diff2 only hold one prior value each. Completely finite memories.

    Here's a shortened and slightly optimised routine with updated comments:

    PUB RawSinc3(pin, mode, period):x | diff1,diff2  'for 1X gain, use (P_LOCAL_A|P_ADC_1X|P_ADC), period can be between 16 and 512
    'return ADC sample from Sinc3 filtering mode
    
            pinstart( pin, mode, %10_0000, period ) 'start smartpin in Sinc3 filter mode
            mode := pin | %001_000000  'SE1 trigger on pin's IN rising
            org
                    SETSE1  mode
    
                    REP     @.rend, #5          'number of decimations, need at least 5
                    WAITSE1                     'wait for decimation interval
                    RDPIN   x, pin              'get SINC3 decimation (one diff already done by smartpin)
                    SUB     x, diff1            'compute sample
                    ADD     diff1, x            'update diff1 value
                    SUB     x, diff2            'compute sample
                    ADD     diff2, x            'update diff2 value
    .rend
                    ZEROX   x, #26              'trim to 27-bit sample, matching smartpin accumulators
            end
    
  • evanhevanh Posts: 16,027
    edited 2023-06-16 16:21

    An intro:

    The custom ADC hardware at the pin converts to synchronous PDM (Pulse Density Modulation), AKA bitstream. This is further converted to PCM (Pulse Code Modulation), AKA samples, in the associated smartpin using SincN filtering. Software handles the decimating when in "filter" modes.

    Decimating places a burden on software similar to serial port handlers. It requires the software to retrieve consecutively timed data (the decimations) to build a coherent sample. The benefit of higher filter orders is faster settling and higher numerical resolution. Sadly, analogue noise floor isn't great in the Prop2's ADC hardware. But an external bitstream ADC could be attached allowing more customisable outcomes.

    A pipeline of samples (done in software) can come from each successive decimation as long as the bitstream is unbroken. Therefore, the bitstream ADC cannot be recalibrated without the software also refilling the pipeline. This only matters for instrumentation uses where the DC level needs accuracy. Audio, for example, needs no recalibrations.

  • RaymanRayman Posts: 14,744

    Thanks @evanh Glad you were able to look at this.

  • evanhevanh Posts: 16,027
    edited 2023-06-18 05:40

    We can illustrate a Sinc1 function using smartpin counter mode P_COUNT_HIGHS, %01111 AND !Y[0] = Count A-input highs.

    When setting smartpin's X = 0 then Z is a plain gated accumulator, it never resets. By reading Z you've created a decimation. To get a PCM sample from this requires subtracting the prior decimation, AKA deriving the differential or delta. So you need to have stored a copy of the prior decimation. You also need to know the duration between decimations for any of this to have meaning.

    When setting smartpin's X > 0 then Z returns the delta of accumulation for the prior timed period. And holds it until a new delta is produced. This effects a direct PCM sample via a Sinc1 filter, no further processing required. The sampling timing is preset in X.

Sign In or Register to comment.