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).
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.
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.
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.
@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
@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.
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.
@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.
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?
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?
@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?
Only looking for 20KHz to 30KHz
Clearly, I have some studying to do
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.
Comments
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
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
@JonnyMac
Oh, my hero
ChatGPT was a million miles off.
Many thanks, Jon. It's the real DAC that interests me the most. Worked instantly
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.
Actually, pondering what could be done to produce a PDM dithered DAC output I see two options:
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
That is correct. Do note that $FF01..$FFFF are valid values, they just get clamped down. This also means the logical center is $7F80.
*taps the sign*

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/
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.
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.

@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
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?
Clearly, I have some studying to do
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