Shop OBEX P1 Docs P2 Docs Learn Events
16bit DAC and PWM — Parallax Forums

16bit DAC and PWM

Would like to test both of these but I haven't worked with FlexBASIC for some time. Can someone please provide an example.

Cheers,

Craig

Comments

  • JonnyMacJonnyMac Posts: 9,378
    edited 2025-07-15 15:42

    FlexBASIC for the P2 has a pinstart() function -- same as in Spin2. I don't use FlexBASIC but here's how I do those things in Spin2 (should translate if FlexBASIC honors Spin2 constant values).

    DAC

      ' start DAC
      ' - 3.3v output
      ' - 16 bits using dithering
    
      pinstart(dacpin, p_dac_dither_pwm | p_dac_990r_3v | p_oe, 256, 0)
    

    The output range is $0000..$FF00 (if I'm wrong I'm sure Ada will excoriate as they often do). Use wypin(dacpin, value) to update the DAC.

    PWM is a little more involved, but given your experience and FlexBASIC support of pinstart(), wrpin(), wxpin(), and wypin() you should be able to make use of the attached PWM object file.

    You can find the constants associated with smart pins in this document:
    -- https://docs.google.com/document/d/16qVkmA6Co5fUNKJHF6pBfGfDupuRwDtf-wyieh_fbqw

  • MicksterMickster Posts: 2,812

    @JonnyMac

    Oh, my hero :D
    ChatGPT was a million miles off.

    Many thanks, Jon. It's the real DAC that interests me the most. Worked instantly :+1:

    ' --- Constants ---
    CONST dacpin = 16
    
          pinstart(dacpin, p_dac_dither_pwm + p_dac_990r_3v + p_oe, 256, 0)
    
          wypin(dacpin, &hff00)
    
  • evanhevanh Posts: 16,585

    That mode is very good. The Prop2 DACs have very high fidelity for 8-bit DACs.

    However, and this applies to that DAC + dither smartpin mode, I've come to realise that, for cleanest analogue reproduction, filtered PDM dithering is superior to filtered PWM dithering. The filter can be faster response for same noise level. Chip had it right on the Prop1 all along.

  • evanhevanh Posts: 16,585
    edited 2025-07-16 01:41

    Actually, pondering what could be done to produce a PDM dithered DAC output I see two options:

    • Setup the PDM smartpin logic mode (P_NCO_DUTY) then route that to its DAC via BitDAC pin mode. Limited to 4-bit DAC levels.
    • Dynamically build the PDM dither pattern in LutRAMHubRAM (LutRAM would hold the two 8-bit levels being dithered) and drive a DAC with the streamer. Limited to one channel per Cog. Err, this one can do a pin group of four DACs, nice. But they're interleaved, like RGB colours.
  • MicksterMickster Posts: 2,812

    @evanh said:
    That mode is very good. The Prop2 DACs have very high fidelity for 8-bit DACs.

    However, and this applies to that DAC + dither smartpin mode, I've come to realise that, for cleanest analogue reproduction, filtered PDM dithering is superior to filtered PWM dithering. The filter can be faster response for same noise level. Chip had it right on the Prop1 all along.

    Yeah, I remember that and @Bean realized the same.
    This is only for motor command and I realize that it's huge overkill for the type of stuff I do. Heck, I still have systems with 8 bit PWM-to-analog, almost no LPF and one needs to grab the motor shaft to be sure that the servo is holding position. I'm being a bit silly in that I'm shooting for a (pointless) spec' purely for specmanship :)

  • Wuerfel_21Wuerfel_21 Posts: 5,405
    edited 2025-07-15 22:08

    @JonnyMac said:
    The output range is $0000..$FF00 (if I'm wrong I'm sure Ada will excoriate as they often do). Use wypin(dacpin, value) to update the DAC.

    That is correct. Do note that $FF01..$FFFF are valid values, they just get clamped down. This also means the logical center is $7F80.

    @Mickster said:
    ChatGPT was a million miles off.

    *taps the sign*

  • evanhevanh Posts: 16,585
    edited 2025-07-16 13:33

    LOL, very creative. Love it!

    Late edit: Found this pertinent news item on LLMs not living up to the hype - https://www.theregister.com/2025/07/15/sec_risk_factors_ai/

  • evanhevanh Posts: 16,585
    edited 2025-07-16 04:01

    To make a PDM dither function using the streamer I think the streamer can be left looping on a small amount of hubRAM for a given dither level. Unlike the VGA drivers, it hopefully won't require the cog to interact again until next change in level. It'll be much like setting the real DAC.

    I might just have to do a proof of concept ... EDIT: Doh! Still can't do it without a dedicated cog - The streamer uses the FIFO! Hubexec is a no-go. :(

    EDIT2: The unmanaged looping won't work either. PDM relies on arbitrary loop length. Which can't be achieved by the FIFO length. Only the Cog can manage it.

    So down to one channel consuming a whole cog - That's depressing. I'm feeling that "not worth the effort" mood.

    EDIT3: I suppose, if the NCO divider was to be used, say a 1 MHz dither resolution, instead of full sysclock frequency ... that should allow using the streamer looping on a fixed length and therefore autonomously. Unattended loop length without hubRAM is 32 bits (5-bit dither) so combined makes a 13-bit DAC.

    An NCO smartpin can do it at full sysclock. It could be setup for 9 bits on top of the 4-bit bitDAC mode to produce the same 13 bits. All 64 pins potentially.

    Hehe, of course, the DAC+PWM at 16-bits is probably just as good.

  • MicksterMickster Posts: 2,812
    edited 2025-07-16 07:31

    @Wuerfel_21 said:

    @JonnyMac said:
    The output range is $0000..$FF00 (if I'm wrong I'm sure Ada will excoriate as they often do). Use wypin(dacpin, value) to update the DAC.

    That is correct. Do note that $FF01..$FFFF are valid values, they just get clamped down. This also means the logical center is $7F80.

    Couldn't be better. For my 20V range (+/- 10V), I was planning to limit to +/- ~9.99V and that's exactly what the $FF00 clamp limits to. B):+1:

  • MicksterMickster Posts: 2,812

    @JonnyMac

    Hi Jon,

    It looks to me that your PWM is similar to what I have always had in FlexBasic in that there is the trade-off between frequency and resolution. Isn't there a P_DAC_DITHER_PWM solution to provide 16-bit PWM at a higher frequency?

    Cheers,

    Craig

  • evanhevanh Posts: 16,585
    edited 2025-07-16 12:39

    The 256 value (256 is lowest permitted) in the parameters means a PWM cycle time of 256 sysclock ticks. So something close to 1 MHz update rate. Is that not enough?

  • MicksterMickster Posts: 2,812

    @evanh said:
    The 256 value (256 is lowest permitted) in the parameters means a PWM cycle time of 256 sysclock ticks. So something close to 1 MHz update rate. Is that not enough?

    :D Only looking for 20KHz to 30KHz :D
    Clearly, I have some studying to do :)

  • JonnyMacJonnyMac Posts: 9,378

    @Mickster said:
    @JonnyMac

    Hi Jon,

    It looks to me that your PWM is similar to what I have always had in FlexBasic in that there is the trade-off between frequency and resolution. Isn't there a P_DAC_DITHER_PWM solution to provide 16-bit PWM at a higher frequency?

    Cheers,

    Craig

    TBH, I don't know. My PWM object is used for LED dimming and motor speed control -- very simple stuff; I'm not using it to generate analog values.

  • MicksterMickster Posts: 2,812

    @JonnyMac said:

    TBH, I don't know. My PWM object is used for LED dimming and motor speed control -- very simple stuff; I'm not using it to generate analog values.

    No worries. I can get 16bits but the frequency is only 2.8KHz at my CPU speed. Only a quick check because the true DAC is what I am more interested in :+1:

Sign In or Register to comment.