I don't know. What I'll have to do first is describe it in text. A diagram would just make it click in people's minds much faster.
Examples are always good, as are formula for things like Baud Dividers and PWM Period and Duty.
A single maths equation can replace a whole paragraph which users will all interpret slightly differently.
I my DOCs I make the Maths equations copy/pastable into a common calculator ( I use CCalc)
Still testing, but I wanted to post some pictures.
Each Prop2 pin has an 8-bit monotonic DAC (every increase in value results in an increase in voltage). To get more than 8 bits of resolution, they can be PWM'd or dithered between adjacent steps on each clock. This oversampling can give you another 8 bits of resolution, averaged over 256 clock cycles. So, the smart pins can take 16-bit samples and modulate the 8-bit DACs to increase their resolution. These DACs settle to their native 8 bits resolution in about 3ns, as they are 120 ohms. There are actually two DACs per pin, a 120-ohm and a 1000-ohm. There are also internal pull-down resistors to offer more impedance/voltage tradeoffs:
1000 ohms at 3.3V
300 ohms at 1.0V
120 ohms at 3.3V
75 ohms at 2.0V (becomes 1.0V when plugged into a 75-ohm device, like a TV or VGA monitor)
On the Prop123 board, there are 75-ohm video DACs which work best loaded with 75 ohms to ground. I made 75-ohm jacks to plug into the RCA connectors.
Here is a picture of the smart pin outputting 16-bit pwm'd values, spanning three levels of the bottom of the 8-bit DACs (1.0V/256 = 3.9mV/step). Note that the scale is 10mV/division. I went into averaging mode on the scope to make it easier to see:
Here is a picture of the smart pin using pseudo-random dithering, where N / N+1 is decided on each clock, raising the oversampling frequency to the clock rate:
The difference between these two modes, aside from the obvious, is that the PWM, while maybe needing more filtering, is more linear, due to only 2 transitions, max, per 256 clocks, while the dithering mode causes transitions so frequently that slightly-off rise/fall times will likely introduce some non-monotonic performance. One great thing about dithering is that you don't need to respect a 256n sample clock. You can update the sample at any time with immediate results.
Lastly, here is a full-scale pseudo-random DAC mode that updates on every clock. Used as a noise source, and run through the same pin's ADC, you'll have true random numbers in the LSB(s) of the conversions:
Note the time scale. These transistions are really fast, and even though they are deterministic (being from a 32-bit LFSR, from which each pin receives a differently-ordered and -inverted tap set), they will jumble the jebeezers out of the ADC, giving reign to imperfections inside the converter, from which real randomness will come.
I've been testing today, and I've made a few minor improvements. Looking good, so far.
You could include the test code cases, commented, as part of the Documentation ?
How does Timer-Capture and continual SPI streaming like for i2s testing look ?
I've been testing today, and I've made a few minor improvements. Looking good, so far.
You could include the test code cases, commented, as part of the Documentation ?
How does Timer-Capture and continual SPI streaming like for i2s testing look ?
I'm not there yet.
For the first picture in my post above, here is the code:
dat org 'cog program
pinmode pm,#1 'enable DAC pwm mode in smart pin 1
pinsetx #$100,#1 'set 256 clocks per sample
mov dira,#%11 'enable smart pin 1 and scope trigger pin 0
setedg #%01_000001 'trigger on rising smart pin 1
.again waitedg 'wait for new sample period
pinack #1 'acknowledge smart pin 1
shl x,#4 'update sample (coarse steps for viewing)
pinsety x,#1
shr x,#4
incmod x,#$30 wc 'inc/modulus sample
setbc outa,#0 'pulse pin 0 if new sawtooth cycle
clrb outa,#0
jmp #.again
pm long %1_00__00011__0_000_0_000__00_0__10100_00000000
x long 0
Gorgeous! The second (dither) one I don't understand how come it is so fine. I'm guessing it's a lot better than the scope can show.
That's all via the Prop-123's DAC outputs right? Is the real thing likely to be different? Also, is there a slope limit for either of the 16-bit modes? And any idea of settling speed of the dither mode?
Gorgeous! The second (dither) one I don't understand how come it is so fine. I'm guessing it's a lot better than the scope can show.
That's all via the Prop-123's DAC outputs right? Is the real thing likely to be different? Also, is there a slope limit for either of the 16-bit modes? And any idea of settling speed of the dither mode?
That's right off the DACs on the Prop123 board. The real thing will span 0 to 3.3V, instead of 0 to 1.0V. For the DAC PWM mode, you need to pick some multiple of 256 clocks for your sample update. For the DAC dither mode, you can update it as fast as you want. It will get within 8 bits in 3ns and average out to something probably less than 16 bits over the next 256 clocks, if you give it that much time before updating it. The dither mode rapidly modulates the lower 8 bits of the sample between adjacent DAC levels, whereas the PWM mode transitions between adjacent DAC levels twice in 256 clocks.
I just tested the triangle PWM mode. I compiled for 16 smart pins, so that I could try a bunch at once.
Smart pins are in 'reset' when their DIR bit is low. That's a good time to configure them with the PINMODE instruction. When their DIR is brought high, they start to operate. By bringing multiple smart pins out of reset simultaneously, by writing highs to DIRA or DIRB, they are all synchronized and will remain so, in the case of PWM modes, which are deterministic. PWM sample values are double-buffered, so once a pin alerts you that it just grabbed the buffered sample by raising its IN signal, you have the whole frame period to write a new sample, before it is grabbed and used. In cases of synchronized PWM pins, you can go about updating them all, and when the current frame is done, all PWMs will grab the new samples simultaneously.
In this picture, I had pins 1 through 15 outputting staggered values in triangle PWM mode, while pin 0 served as a scope trigger. I animated the values, but you can't see that in a picture:
Thanks to you guys for bringing up this triangle PWM concept!
Here's the code that runs this:
dat org 'cog program
mov x,#15
.init pinmode pm,x 'enable triangle pwm mode in smart pins 1..15
pinsetx fr,x 'set frame size and timebase
djnz x,#.init
mov dira,##$FFFF 'enable smart pins 1..15 and scope trigger pin 0
setedg #%01_000001 'trigger on rising smart pin 1
.again
mov x,#15 'update samples in smart pins
.update altd x,#pwms
pinsety pwms,x
altd x,#pwms
incmod pwms,lim
djnz x,#.update
waitedg 'wait for new sample period
pinack #1 'acknowledge smart pin 1
xor outa,#1 'make scope trigger
xor outa,#1
jmp #.again 'loop
pm long %1_00__01000__0_000_0_000__00_0__00000_00000000
fr long 8000<<16 + 1 '8000 counts per frame, count on every clock
lim long 8000
x long 0
pwms long 0*500
long 1*500
long 2*500
long 3*500
long 4*500
long 5*500
long 6*500
long 7*500
long 8*500
long 9*500
long 10*500
long 11*500
long 12*500
long 13*500
long 14*500
long 15*500
Here's a picture of the same program, but with sawtooth PWM mode, instead of triangle. This mode has three options:
1) normal
2) don't start next frame if A-input is high
3) don't start next frame if A-input is high, plus cancel pulse early if B-input goes high
The last two are for switch-mode power supplies.
(2) is for voltage feedback, where another pulse isn't done until voltage drops below some threshold. Each pin can compare its input to an internal high-impedance 8-bit DAC, and this can constitute the A-input. In such a case, a resistor voltage divider would be used to get the fractional supply voltage into the A-input pin.
(3) is like (2), but adds a pulse-shortening feature where if, during the high pulse, the B-input goes high, the pulse is cancelled early, but the frame time still finishes out. Again, a DAC+comparator can be used in another pin to see if a shunt resistor junction gets too high, indicating saturation is nearly achieved, so the pulse can be cancelled earlier than its max time allowance.
You can tell in these PWM pictures where the smart pin indicated 'done' on each cycle. Just look at the bottom trace. I had to jigger these triangle and sawtooth circuits around quite a bit to get things properly oriented. The sawtooth PWM needed to start with high output in order to support the switch-mode power supply modes.
In every PWM mode, you supply a frame size 1..65535 (0 is effectively 65536). You also supply a time base that sets how many clocks to count before stepping the frame counter (1= every clock). Then, you supply samples. If the sample is 0, the output will always be low. If the sample is the frame size or greater, the output will always be high. The frame counter runs between 1 and the frame size for sawtooth PWM, then repeats. In the case of triangle PWM, the frame counter runs from the frame size down to 1, then from 1 back up to the frame size, and repeats.
I just tested the triangle PWM mode. I compiled for 16 smart pins, so that I could try a bunch at once.
.... a pin alerts you that it just grabbed the buffered sample by raising its IN signal
Nice plots, and the handshake is cool.
Is there a current trip/regulate feature (usually abort that cycle's output on Pin signal) ?
I see mention in sawtooth PWM, so guess that is also in triangle too ?
A good test framework for Capture, is a Reciprocal Frequency Counter.
This has 2 x 32 bit counters, that capture on the same edge.
One counter is Time (SysCLK/N clocked), and the other is Cycles (Fin clocked)
The Arm-capture is done at a relatively slow rate, 10ms to 1000ms, and when Armed, the next Fin edge triggers both Time & Cycles captures, once. (ie Capture is always whole cycles, rounds up in time to the next Fin edge)
This trigger element can be as simple as a D-FF with CLK and RS signals, or anything that HW triggers and SW clears.
I'm not sure is this will need 2 Pin cells, or 3, with the 3rd one providing D-FF emulation ? (hopefully 2)
This will give 0.5Hz to 40MHz type dynamic range, with no range-select needed & many of these can manage from one COG.
Where less dynamic range is tolerable, designs can capture Time after /M Fin Cycles, and /M is chosen to give a useful period read rate. eg 1MHz in may capture every 4096 edges, for a 4.096ms update rate.
At 80MHz this update is ~3ppm LSB
A variant of this captures Fin Cycles count, after a fixed time, but this has low precision at low frequencies, tho it does give Hz rather than Period result.
Timer Interval A-B :
Capture side is simple - Chosen Pin edge loads time.
This does need to be Arm-capture as a pair, so you know you have a single-span time from A to B & it should work down to very narrow 1 SysCLK wide pulses.
Some systems give the option to Clear-On-capture, others capture without clear, and the user subtracts previous value.
I like the look of the dithered output.
Should be good for audio, right?
Maybe COG can also interpolate between values to reduce step noise...
Isn't that what the dithering is doing ?
The 8b DAC is going to set some limits on Audio Quality, as the LSBs are not going to be all the same size.
That means dithering can be good for feedback and interpolate cases, but SINAD is going to be set by the 8b DAC.
Your right, that doesn't make any sense for 16-bit samples.
Could be used on 8-bit samples though.
If the data rate was 44kHz, you could update in between samples with the average of nearest samples...
Your right, that doesn't make any sense for 16-bit samples.
Could be used on 8-bit samples though.
If the data rate was 44kHz, you could update in between samples with the average of nearest samples...
I think dithering would help idle-noise for example & would help DAC sweep designs where 1 in 256 is too coarse.
An external ADC could be used to check DAC.
Are you saying calibrate the DAC for better performance ?
That could certainly be tried, and it would then depend how much that drifted with Temp/Time/Vcc.
12 bits seems to be fairly routine on MCUs these days, which could indicate stability levels.
Will the streamer be able to take advantage of the fact that smartpins can now output 16 bit dithered analog, or will they still only be able to do 8 bits?
Maybe, instead of modifying the streamer to have 16 bit modes, the smartpins could be made to get the bottom 8 bits from their B-pin, but that sounds like it would be a lot of muxes. Then, the streamer could be told to output the top 8 bits to one pin and the bottom 8 to another, using one of the modes that already exists, and then a smartpin could put two 8 bit values together.
EDIT: Or could you modify the streamer to be able to feed its output to pinsety or pinsetx?
That is likely to need a 16 bit DAC. This new feature should perform better than 8 bits will.
The i2s DACs are quite cheap, under 50c, and they give 24b Audio.
Hopefully, the Smart Pins will eventually be able to talk i2s (mono or stereo) in 16/24/32 formats.
At audio speeds, it almost doesn't matter, but nice to have, right?
For a lot of things, 8+ bits will work great. If one massages the audio, 8 bits can surprise.
And good grief, a ton of channels! Might be fun to combine both. Have main audio on a good DAC and use the many channels to do some immersion type audio. All sorts of fun tricks possible here.
Exactly. Even though it's 8+bits, depending on how all these modes work, having that many channels could make for some really interesting audio + user input type scenarios.
Comments
Examples are always good, as are formula for things like Baud Dividers and PWM Period and Duty.
A single maths equation can replace a whole paragraph which users will all interpret slightly differently.
I my DOCs I make the Maths equations copy/pastable into a common calculator ( I use CCalc)
I think at least two smart pins should fit. I'll know soon.
I've been testing today, and I've made a few minor improvements. Looking good, so far.
Each Prop2 pin has an 8-bit monotonic DAC (every increase in value results in an increase in voltage). To get more than 8 bits of resolution, they can be PWM'd or dithered between adjacent steps on each clock. This oversampling can give you another 8 bits of resolution, averaged over 256 clock cycles. So, the smart pins can take 16-bit samples and modulate the 8-bit DACs to increase their resolution. These DACs settle to their native 8 bits resolution in about 3ns, as they are 120 ohms. There are actually two DACs per pin, a 120-ohm and a 1000-ohm. There are also internal pull-down resistors to offer more impedance/voltage tradeoffs:
1000 ohms at 3.3V
300 ohms at 1.0V
120 ohms at 3.3V
75 ohms at 2.0V (becomes 1.0V when plugged into a 75-ohm device, like a TV or VGA monitor)
On the Prop123 board, there are 75-ohm video DACs which work best loaded with 75 ohms to ground. I made 75-ohm jacks to plug into the RCA connectors.
Here is a picture of the smart pin outputting 16-bit pwm'd values, spanning three levels of the bottom of the 8-bit DACs (1.0V/256 = 3.9mV/step). Note that the scale is 10mV/division. I went into averaging mode on the scope to make it easier to see:
Here is a picture of the smart pin using pseudo-random dithering, where N / N+1 is decided on each clock, raising the oversampling frequency to the clock rate:
The difference between these two modes, aside from the obvious, is that the PWM, while maybe needing more filtering, is more linear, due to only 2 transitions, max, per 256 clocks, while the dithering mode causes transitions so frequently that slightly-off rise/fall times will likely introduce some non-monotonic performance. One great thing about dithering is that you don't need to respect a 256n sample clock. You can update the sample at any time with immediate results.
Lastly, here is a full-scale pseudo-random DAC mode that updates on every clock. Used as a noise source, and run through the same pin's ADC, you'll have true random numbers in the LSB(s) of the conversions:
Note the time scale. These transistions are really fast, and even though they are deterministic (being from a 32-bit LFSR, from which each pin receives a differently-ordered and -inverted tap set), they will jumble the jebeezers out of the ADC, giving reign to imperfections inside the converter, from which real randomness will come.
You could include the test code cases, commented, as part of the Documentation ?
How does Timer-Capture and continual SPI streaming like for i2s testing look ?
I'm not there yet.
For the first picture in my post above, here is the code:
That's all via the Prop-123's DAC outputs right? Is the real thing likely to be different? Also, is there a slope limit for either of the 16-bit modes? And any idea of settling speed of the dither mode?
That's right off the DACs on the Prop123 board. The real thing will span 0 to 3.3V, instead of 0 to 1.0V. For the DAC PWM mode, you need to pick some multiple of 256 clocks for your sample update. For the DAC dither mode, you can update it as fast as you want. It will get within 8 bits in 3ns and average out to something probably less than 16 bits over the next 256 clocks, if you give it that much time before updating it. The dither mode rapidly modulates the lower 8 bits of the sample between adjacent DAC levels, whereas the PWM mode transitions between adjacent DAC levels twice in 256 clocks.
Smart pins are in 'reset' when their DIR bit is low. That's a good time to configure them with the PINMODE instruction. When their DIR is brought high, they start to operate. By bringing multiple smart pins out of reset simultaneously, by writing highs to DIRA or DIRB, they are all synchronized and will remain so, in the case of PWM modes, which are deterministic. PWM sample values are double-buffered, so once a pin alerts you that it just grabbed the buffered sample by raising its IN signal, you have the whole frame period to write a new sample, before it is grabbed and used. In cases of synchronized PWM pins, you can go about updating them all, and when the current frame is done, all PWMs will grab the new samples simultaneously.
In this picture, I had pins 1 through 15 outputting staggered values in triangle PWM mode, while pin 0 served as a scope trigger. I animated the values, but you can't see that in a picture:
Thanks to you guys for bringing up this triangle PWM concept!
Here's the code that runs this:
1) normal
2) don't start next frame if A-input is high
3) don't start next frame if A-input is high, plus cancel pulse early if B-input goes high
The last two are for switch-mode power supplies.
(2) is for voltage feedback, where another pulse isn't done until voltage drops below some threshold. Each pin can compare its input to an internal high-impedance 8-bit DAC, and this can constitute the A-input. In such a case, a resistor voltage divider would be used to get the fractional supply voltage into the A-input pin.
(3) is like (2), but adds a pulse-shortening feature where if, during the high pulse, the B-input goes high, the pulse is cancelled early, but the frame time still finishes out. Again, a DAC+comparator can be used in another pin to see if a shunt resistor junction gets too high, indicating saturation is nearly achieved, so the pulse can be cancelled earlier than its max time allowance.
You can tell in these PWM pictures where the smart pin indicated 'done' on each cycle. Just look at the bottom trace. I had to jigger these triangle and sawtooth circuits around quite a bit to get things properly oriented. The sawtooth PWM needed to start with high output in order to support the switch-mode power supply modes.
In every PWM mode, you supply a frame size 1..65535 (0 is effectively 65536). You also supply a time base that sets how many clocks to count before stepping the frame counter (1= every clock). Then, you supply samples. If the sample is 0, the output will always be low. If the sample is the frame size or greater, the output will always be high. The frame counter runs between 1 and the frame size for sawtooth PWM, then repeats. In the case of triangle PWM, the frame counter runs from the frame size down to 1, then from 1 back up to the frame size, and repeats.
Nice pictures Chip.
This looks perfect.
The pictures are great!! we'll probally attract a new group that's into electronic art
For me seeing the pictures sure explains allot that I would probally have difficulty understanding just from a list of options.
Anyone remember the Prop 1 ADC DAC examples
http://forums.parallax.com/discussion/84176/adc-and-dac-example
Is there a current trip/regulate feature (usually abort that cycle's output on Pin signal) ?
I see mention in sawtooth PWM, so guess that is also in triangle too ?
WTG Chip!
A good test framework for Capture, is a Reciprocal Frequency Counter.
This has 2 x 32 bit counters, that capture on the same edge.
One counter is Time (SysCLK/N clocked), and the other is Cycles (Fin clocked)
The Arm-capture is done at a relatively slow rate, 10ms to 1000ms, and when Armed, the next Fin edge triggers both Time & Cycles captures, once. (ie Capture is always whole cycles, rounds up in time to the next Fin edge)
This trigger element can be as simple as a D-FF with CLK and RS signals, or anything that HW triggers and SW clears.
I'm not sure is this will need 2 Pin cells, or 3, with the 3rd one providing D-FF emulation ? (hopefully 2)
This will give 0.5Hz to 40MHz type dynamic range, with no range-select needed & many of these can manage from one COG.
Where less dynamic range is tolerable, designs can capture Time after /M Fin Cycles, and /M is chosen to give a useful period read rate. eg 1MHz in may capture every 4096 edges, for a 4.096ms update rate.
At 80MHz this update is ~3ppm LSB
A variant of this captures Fin Cycles count, after a fixed time, but this has low precision at low frequencies, tho it does give Hz rather than Period result.
Timer Interval A-B :
Capture side is simple - Chosen Pin edge loads time.
This does need to be Arm-capture as a pair, so you know you have a single-span time from A to B & it should work down to very narrow 1 SysCLK wide pulses.
Some systems give the option to Clear-On-capture, others capture without clear, and the user subtracts previous value.
Should be good for audio, right?
Maybe COG can also interpolate between values to reduce step noise...
Isn't that what the dithering is doing ?
The 8b DAC is going to set some limits on Audio Quality, as the LSBs are not going to be all the same size.
That means dithering can be good for feedback and interpolate cases, but SINAD is going to be set by the 8b DAC.
Could be used on 8-bit samples though.
If the data rate was 44kHz, you could update in between samples with the average of nearest samples...
An external ADC could be used to check DAC.
Are you saying calibrate the DAC for better performance ?
That could certainly be tried, and it would then depend how much that drifted with Temp/Time/Vcc.
12 bits seems to be fairly routine on MCUs these days, which could indicate stability levels.
8 bits is somewhat close to 50db s/n. Just blasting 16 bit samples should deliver better noise floor. I'll bet audible distortion is similar.
Can't wait to try it out!
Maybe, instead of modifying the streamer to have 16 bit modes, the smartpins could be made to get the bottom 8 bits from their B-pin, but that sounds like it would be a lot of muxes. Then, the streamer could be told to output the top 8 bits to one pin and the bottom 8 to another, using one of the modes that already exists, and then a smartpin could put two 8 bit values together.
EDIT: Or could you modify the streamer to be able to feed its output to pinsety or pinsetx?
Hopefully, the Smart Pins will eventually be able to talk i2s (mono or stereo) in 16/24/32 formats.
For a lot of things, 8+ bits will work great. If one massages the audio, 8 bits can surprise.
And good grief, a ton of channels! Might be fun to combine both. Have main audio on a good DAC and use the many channels to do some immersion type audio. All sorts of fun tricks possible here.