Shop OBEX P1 Docs P2 Docs Learn Events
Need help with DAC / streamer configuration - Page 2 — Parallax Forums

Need help with DAC / streamer configuration

2»

Comments

  • evanhevanh Posts: 15,126
    edited 2018-10-22 05:34
    Hehe, okay, a non-DAC smartpin output mode, but with DAC mode set ... enables BIT_DAC on smartpin output. Eg:
    		DIRL  #tpin
    		WRPIN  ##%10111_DDDDDDDD_01_01000_0, #tpin  ' %01000 = PWM triangle smartpin
    		                                            ' %10111 = DAC mode: 2 volt range, 75 ohm
    		                                            ' %DDDDDDDD = DAC level for BIT_DAC = high
    		WXPIN  ##$100_0001, #tpin       ' PWM period = 256 clocks
    		WYPIN  #0, #tpin                ' Initial PWM level
    		DIRH  #tpin
    
    EDIT: Added 2 volt detail
  • evanhevanh Posts: 15,126
    Chip,
    Normally DAC mode %10111 sets a 2.0 volt output level. I'm assuming this is overridden by the BIT_DAC set level.

  • cgraceycgracey Posts: 14,133
    evanh wrote: »
    Chip,
    Normally DAC mode %10111 sets a 2.0 volt output level. I'm assuming this is overridden by the BIT_DAC set level.


    Nope. The smart pin doesn't control the internal pull down resistor, only the 8-bit DAC output value. If you set 2.0 volt mode, that's where it works.
  • evanhevanh Posts: 15,126
    Ah, of course, I confused level with range for a moment there.

  • evanhevanh Posts: 15,126
    edited 2019-12-09 18:59
    Maintained version now in tricks and traps topic - https://forums.parallax.com/discussion/comment/1452036/#Comment_1452036

    Okay, here's my attempt at transcribing the PAD_IO sheet into a mode list for the main Prop2 doc:
    %PPPPPPPPPPPPP: low-level pin control (engineering sample die)
    
    	common labelling of pin config bits
    		%C = clocked I/O (extra clock for IN and OUT)
    		%I = invert IN output
    		%O = invert OUT input
    		%HHH/LLL = digital out drive strength
    			000: Fast
    			001: 1k5R
    			010: 15kR
    			011: 150kR
    			100: 1mA
    			101: 100uA
    			110: 10uA
    			111: Float
    		PinA is specified pin number
    		PinB is PinA's odd/even pair
    
    	%0_VVV_CIOHHHLLL = Digital mode (default = %0000000000000)
    		DIR enables PinA digital output
    		%VVV = Digital config
    			000: IN = PinA logic, PinA output from OUT
    			001: IN = PinA logic, PinA output from IN
    			010: IN = PinB logic, PinA output from IN
    			011: IN = PinA schmitt, PinA output from OUT
    			100: IN = PinA schmitt, PinA output from IN
    			101: IN = PinB schmitt, PinA output from IN
    			110: IN = PinA > PinB comparator, PinA output from OUT
    			111: IN = PinA > PinB comparator, PinA output from IN
    
    	%100_VVV_OHHHLLL = ADC_MODE, first order sigma-delta
    		IN has bitstream, sysclock bitrate, for smartpin mode %01111 (Y=0)
    		OUT is PinA digital output, clocked
    		DIR enables PinA digital output
    		%VVV = ADC config
    			000: GIO, 1x (~5 volt range, centred on VIO/2)
    			001: VIO, 1x       "
    			010: PinB, 1x      "
    			011: PinA, 1x      "
    			100: PinA, 3.16x (~1.58 volt range, centred on VIO/2)
    			101: PinA, 10x   (~0.5 volt range, centred on VIO/2)
    			110: PinA, 31.6x (~0.158 volt range, centred on VIO/2)
    			111: PinA, 100x  (~0.05 volt range, centred on VIO/2)
    
    	%101_VV_DDDDDDDD = DAC_MODE (%TT = 00 and %MMMMM = 00000), 8-bit flash
    		OUT enables PinA ADC (config %011), sysclocked bitstream on IN
    		DIR enables PinA DAC output
    		%VV = PinA DAC config
    			00: 990 ohm, 3.3 volt range
    			01: 600 ohm, 2.0 volt range
    			10: 123.75 ohm, 3.3 volt range
    			11: 75 ohm, 2.0 volt range
    		%DDDDDDDD = DAC level
    
    		for %TT = %01 and %MMMMM = %00000, %101_VV_xxxxSSSS = COG_DAC mode
    			%SSSS = Cog/streamer select: sets DAC level (registered?)
    
    		for %00000 < %MMMMM < %00100 = SMART_DAC mode
    			DIR/IN are usual smartpin ctrl
    			%DDDDDDDD ignored, smartpin sets DAC level (registered?)
    
    		for %MMMMM >= %00100 or (%TT = %1x and %MMMMM = %00000) = BIT_DAC mode
    			OUT sets DAC level (clocked?, ADC disabled?, IN = ?)
    				0: 0 = GIO level
    				1: %DDDDDDDD
    
    	%11_VV_CDDDDDDDD = COMP_DAC comparator mode
    		DIR enables PinA digital output
    		%VV = Comparator config
    			00: IN = PinA > D, PinA driven by 1k5R from OUT
    			01: IN = PinA > D, PinA driven by 1k5R from !IN
    			10: IN = PinB > D, PinA driven by 1k5R from IN
    			11: IN = PinB > D, PinA driven by 1k5R from !IN
    		%DDDDDDDD = DAC level for internal analogue compare
    
    
    EDIT: Fixes already!
    23-10-2018: Fleshed out BIT_DAC mode
    24-10-2018: Tidy up labelling
    25-10-2018: Clarify ADC function in DAC_MODE
    1-11-2018: Add SMART_DAC mode and clocking details. Give unique identifier to cog/streamer select
    20-11-2018: Correct the smartpin mode number for capturing ADC bitstream
    25-11-2018: Reverse the update. Doh!
    26-12-2018: Typo, R -> % in BIT_DAC mode line. And stated for engineering sample.
    10-12-2019: Link to maintained version
  • Having started to play with smart pins on my 64000 today, one thing that would have helped me a lot
    would be a set of example P2ASM configurations for each mode (and major submode) in each section of the
    documentation, making clear what TT settings, OUT/DIR settings, PPPPP and MMM mode bits are relevant
    to that mode, and providing a working starting point for further experimentation. I seem to have spent far
    too long figuring out DAC and PWM modes by guesswork, and the interaction of DIRx/OUTx/TT fields
    seems to vary considerably with mode.

    On the plus side I'm impressed with the upload speed compared to the P1, and the convenience of not having
    to use any Spin to run a Pasm example - makes it a lot quicker and easier to try out P2ASM fragments. And
    ## is so incredibly handy!
  • evanhevanh Posts: 15,126
    Yeah, not much written so far on the mix'n'matching of sections in the WRPIN mode config. It didn't have as much flexibility in the FPGA.

  • kwinnkwinn Posts: 8,697
    Mark_T wrote: »
    Having started to play with smart pins on my 64000 today, one thing that would have helped me a lot
    would be a set of example P2ASM configurations for each mode (and major submode) in each section of the
    documentation, making clear what TT settings, OUT/DIR settings, PPPPP and MMM mode bits are relevant
    to that mode, and providing a working starting point for further experimentation. I seem to have spent far
    too long figuring out DAC and PWM modes by guesswork, and the interaction of DIRx/OUTx/TT fields
    seems to vary considerably with mode.

    On the plus side I'm impressed with the upload speed compared to the P1, and the convenience of not having
    to use any Spin to run a Pasm example - makes it a lot quicker and easier to try out P2ASM fragments. And
    ## is so incredibly handy!

    Can we hope that you have been making notes as you figure things out and contribute them to the documentation?
  • Yes, I'm keeping a working example for each mode, I'll be tidying them up into a looping example I suspect, still
    got to work on streaming modes :) 3-fold pipelined cordic -> dithered DAC mode was last nights example, looks pretty clean on spectrum analyzer.
  • Mark_TMark_T Posts: 1,981
    edited 2019-01-12 20:04
    Well today I worked on pipelined CORDIC again and have an example that does frequency-agile DDS using
    hub memory FIFO for setting the frequency word, and issues CORDIC rotate every 16 cycles to drive a
    smartpin in DAC dither mode. That's 10MSPS rate.
    '
    ' DDS using cordic -> DAC for P2 Eval board
    '
    ' Pipelined use of CORDIC cosine to generate samples to a DAC smartpin every 16 cycles, using a DDS step
    ' which reads its frequency long from hub every sample for full agility.
    '
    ' The main loop needs 2 instructions to interface the CORDIC engine, 1 to do phase increment, 1 to read
    ' frequency word, 2 to convert and write sample to DAC, and a JMP.  This takes at least 15 cycles as
    ' adding another NOP breaks the timing.  I'm not sure which instruction is > 2 cycles, perhaps its relative
    ' timing of CORDIC and FIFO/Smartpin windows?
    '
    ' Mark Tillotson
    CON
        OSCMODE = $010c3f04
        freq = 160_000_000
        
    	' various DAC smart pin modes
        dac  = %0000_0000_000_10100_00000000_00_00000_0
        prng = %0000_0000_000_10100_00000000_01_00001_0
        dither = %0000_0000_000_10100_00000000_01_00010_0    ' remember to wypin
        dither_pwm = %0000_0000_000_10100_00000000_01_00011_0 ' remember to wypin
    
        DACpin = 48   ' output pin
    
    OBJ
    
    VAR
        long  frq[16]    ' single RDFAST block
    
    PUB demo | i
        clkset (OSCMODE, freq)
        
        freq_addr := @frq
        i := 0
        repeat 16
          frq[i] := 20615843   ' 48kHz / 10MHz * 2^32
          i += 1
        i := 0
        cognew (@entry)
        repeat
            pausems(2)
            frq[i] += 10000    ' spin increments the frequency slowly.
            i += 1             ' since fast read cycles through at least one block of 16 longs, have to update all 16
            i &= 15            ' another P2ASM cog could synchronously update the block for full control
    
    
    ' note I tend to uppercase the exotic/timing-sensitive instructions
    
    DAT
                    org     0
    entry
                    WRPIN   ##dither_pwm, #DACpin   ' smartpin mode, can leave DIRB/OUTB as is for this one
    
    		RDFAST  ##1, freq_addr     ' need FIFO access to get a 2 cycle hub read in main loop
                    RFLONG  frequency          ' prime the FIFO
    
    	        mov     val, #4            ' queue 4 rotates (every 16 cycles) into CORDIC before pulling results
    setup
    		add     phase, frequency   ' DDS phase inc
                    QROTATE amplitude, phase   ' queue cosine
    		nop                        ' force 16 cycles, not 8, between entries
                    RFLONG  frequency
    		djnz    val, #setup
    
    ' 4 cosines in flight in CORDIC module, can start consuming them and outputting to DAC indefinitely
    ' in the main loop (16 cycles, so at 160MHz generates 10MSPS, Nyquist limit 5MHz
    loop
                    GETQX   val                ' signed 16 bit cosine value, fetch just in time
    		add     phase, frequency
                    QROTATE amplitude, phase
    		xor     val, signbit       ' need offset value for DAC
    		WYPIN   val, #DACpin
    		RFLONG  frequency          ' 2 cycle load of next frequency
    		jmp	#loop
    
    amplitude	long    $7FFF
    signbit         long    $8000
    phase           long    0
    freq_addr       long    0
    val             res     1
    frequency       res     1
    

    It shouldn't be hard to change the agile variable to be the amplitude, and then, with the help of a modulator code
    reading an ADC pin, to generate AM or FM signals upto 5MHz. I see a dynamic range just over 50dB on the spectrum
    analyzer.
  • evanhevanh Posts: 15,126
    edited 2019-01-18 04:07
    Nice.

    Got a question about Fastspin though: I can see freq[] array defined in hubRAM and the cog code fetching those values. But you are launching a separate cog with its own cog variables and RDFAST appears to get it's freq_addr from the Spin code at runtime. Is that a feature of filling it out, effectively self-modifying, so that it is copied into the cog upon COGINIT? I've never written any Spin code, is that something that could be done in the original Prop1 Spin?


    Couple of notes on the cordic loop:
    - RDFAST primes itself unless D[31] is set.
    - The "setup" loop is already 10 clocks long without any NOP.

    So the following is a little tidier even if it achieves no more.
    		RDFAST  ##1, freq_addr     ' need FIFO access to get a 2 cycle hub read in main loop
    	        mov     val, #4            ' queue 4 rotates (every 16 cycles) into CORDIC before pulling results
    setup
                    RFLONG  frequency
    		add     phase, frequency   ' DDS phase inc
                    QROTATE amplitude, phase   ' queue cosine
    		djnz    val, #setup
    
    ' 4 cosines in flight in CORDIC module, can start consuming them and outputting to DAC indefinitely
    ' in the main loop (16 cycles, so at 160MHz generates 10MSPS, Nyquist limit 5MHz
    loop
    		RFLONG  frequency          ' 2 cycle load of next frequency
    		add     phase, frequency
                    GETQX   val                ' signed 16 bit cosine value, fetch just in time
                    QROTATE amplitude, phase
    		xor     val, signbit       ' need offset value for DAC
    		WYPIN   val, #DACpin
    		jmp	#loop
    
  • evanhevanh Posts: 15,126
    There is a possibility that I've placed GETQ is too close to the QROTATE in the main loop. Moving it earlier still works:
    		RDFAST  ##1, freq_addr     ' need FIFO access to get a 2 cycle hub read in main loop
    	        mov     val, #4            ' queue 4 rotates (every 16 cycles) into CORDIC before pulling results
    setup
                    RFLONG  frequency
    		add     phase, frequency   ' DDS phase inc
                    QROTATE amplitude, phase   ' queue cosine
    		djnz    val, #setup
    
    ' 4 cosines in flight in CORDIC module, can start consuming them and outputting to DAC indefinitely
    ' in the main loop (16 cycles, so at 160MHz generates 10MSPS, Nyquist limit 5MHz
    loop
                    GETQX   val                ' signed 16 bit cosine value, fetch just in time
    		RFLONG  frequency          ' 2 cycle load of next frequency
    		add     phase, frequency
                    QROTATE amplitude, phase
    		xor     val, signbit       ' need offset value for DAC
    		WYPIN   val, #DACpin
    		jmp	#loop
    
  • evanhevanh Posts: 15,126
    And replacing the JMP with a REP will recover 4 clocks if there was a need for that.
  • evanh wrote: »
    Nice.

    Got a question about Fastspin though: I can see freq[] array defined in hubRAM and the cog code fetching those values. But you are launching a separate cog with its own cog variables and RDFAST appears to get it's freq_addr from the Spin code at runtime. Is that a feature of filling it out, effectively self-modifying, so that it is copied into the cog upon COGINIT? I've never written any Spin code, is that something that could be done in the original Prop1 Spin?
    I think that's my habit since BST gets the @operator wrong in DAT sections (or is that a feature?)


    Couple of notes on the cordic loop:
    - RDFAST primes itself unless D[31] is set.
    Ah, I just heeded the warnings about needing to be primed
    - The "setup" loop is already 10 clocks long without any NOP.
    Is this due to branch instructions taking more than 2 cycles?
    And replacing the JMP with a REP will recover 4 clocks if there was a need for that.
    Ah, that's a clever way round it.
  • evanhevanh Posts: 15,126
    Mark_T wrote: »
    evanh wrote: »
    - The "setup" loop is already 10 clocks long without any NOP.
    Is this due to branch instructions taking more than 2 cycles?

    yep, opposite timing order to the Prop1. Prop2 is four clocks if branch taken and two clocks if branch not taken. I think compensating for this change is the main reason Chip added the REP instruction.
  • evanhevanh Posts: 15,126
    edited 2019-01-18 11:50
    But be aware, REP does have restrictions. And not all were designed in. In this case though, it'll work fine.
  • Condensing a 4 stage pipeline to 2 and adding hundreds of new instructions without something giving would
    have been a miracle! Hopefully Chip's scheduled in a few months of sleep after the next silicon revision goes out!

    Yes, REP is tool without a safety guard, but worries me less than SKIP/SKIPF !
  • At last I've captured some spectra from my cordic dac output. I use 16bit random dither mode, which seems
    cleaner than pwm dither.

    Output tone is nominally 2.304MHz, sampled at 10MHz, so the image frequency of 7.696MHz is
    obvious in the first 10M span spectrum. Then I zoom in closer to the tone.

    Siglent SSA3021X analyzer - some of the broad sidebands may be the limiting phase noise of the SA itself, note.

    The 2nd harmonic of 4.608MHz is about 50dB down.

    SSA_190119045130.png
    SSA_190119045212.png
    SSA_190119045257.png
    SSA_190119045336.png
    SSA_190119045423.png
  • jmgjmg Posts: 15,140
    Mark_T wrote: »
    At last I've captured some spectra from my cordic dac output. I use 16bit random dither mode, which seems
    cleaner than pwm dither.

    Nice plots, did you check if any of those spurs wander with temperature ? (see other thread, where DAC spurs vary with temperature)

  • Mark_TMark_T Posts: 1,981
    edited 2019-01-18 23:27
    +/- 7kHz approx, see the PLL wobble thread... I haven't tested other pins to see if it varies yet.
Sign In or Register to comment.