HDMI 4-Channel Oscilloscope Demo

245

Comments

  • Here is the updated scope program with delayed compensation:
    '*************************************************
    '*  Use DDS to demonstrate 4-Channel SCOPE mode  *
    '*************************************************
    
    CON		scp_base	= 52		'must be a multiple of 4, 1st pin is level-triggered input
    		dds_base	= 48		'must be a multiple of 4, connect these pins to scop_base pins
    		hdmi_base	= 32		'must be a multiple of 8
    
    		trigger_level	= $90		'scope trigger level
    		arm_level	= $70		'scope arm level
    		scope_filter	= 0		'scope filter: 0 = 68-tap, 1 = 45-tap, 2 = 28-tap
    
    		dds_freq	= 500_000.0	'nominal DDS frequency (without FM'ing)
    
    		freq		= 250_000_000.0	'system clock frequency must be 250 MHz for HDMI
    
    		buffer		= $1000		'sample buffer (4 KB)		
    		bitmap		= buffer+$1000	'HDMI bitmap (300 KB)
    
    DAT		org
    
                    hubset  ##%1_000001_0000011000_1111_10_00       'config PLL, 20MHz/2*25*1 = 250MHz
                    waitx   ##20_000_000 / 200                      'allow crystal+PLL 5ms to stabilize
                    hubset  ##%1_000001_0000011000_1111_10_11       'switch to PLL
    
    		setq	##($7FFFF - @end_of_pgm)/4		'clear hub RAM
    		wrlong	#0,##@end_of_pgm
    
    		coginit	#2,##@pgm_dds		'launch DDS
    		coginit	#1,##@pgm_scp		'launch Scope
    		coginit	#0,##@pgm_hdmi		'launch HDMI
    
    
    '*********
    '*  DDS  *
    '*********
    
    DAT		org
    
    pgm_dds		cogid	x			'init DAC pins for this cog's DAC channels
    		setnib	dacmode,x,#2
    		wrpin	dacmode,#3<<6+dds_base
    		dirh	#3<<6+dds_base
    
    ' Make sine/triangle/sawtooth/square patterns in LUT
    
    		mov	z,#$1FF			'make 512-sample DDS table in LUT
    
    .lut		shl	z,#32-9			'channel 0 = sine
    		qrotate	#127,z
    		shr	z,#32-9
    		getqy	y
    
    		mov	x,z			'channel 1 = triangle
    		testb	x,#8	wc
    	if_c	not	x
    		xor	x,#$80
    		setbyte	y,x,#1
    
    		mov	x,z			'channel 2 = sawtooth
    		shr	x,#1
    		xor	x,#$80
    		setbyte	y,x,#2
    
    		setbyte	y,#$81,#3		'channel 3 = square
    	if_c	setbyte	y,#$7F,#3
    
    		wrlut	y,z			'write square:sawtooth:triangle:sine into LUT
    
    		djnf	z,#.lut			'loop until 512 samples
    
    ' Output DDS patterns and slowly FM
    
    		xcont	dds_d,dds_s		'issue perpetual DDS/Goertzel command
    
    .loop		qrotate	##3_000_000,x		'slowly FM the signals
    		getqy	y
    		add	y,xfreq
    		setxfrq	y
    		add	x,#100
    		jmp	#.loop
    
    ' Data
    
    dacmode		long	%0000_0000_000_10110_00000000_01_00000_0		'DAC mode, cog DAC channels
    
    xfreq		long	round(dds_freq/freq * 65536.0 * 32768.0)		'streamer frequency value
    
    dds_d		long	%1111_1111_0000_0111<<16 + $FFFF			'DDS/Goertzel mode, continuous
    dds_s		long	%0000_0000_000_000000000				'DDS/Goertzel mode, no input
    
    x		res	1
    y		res	1
    z		res	1
    
    
    '***********
    '*  Scope  *
    '***********
    '
    DAT		org
    
    pgm_scp		wrpin	.scpmode,#3<<6+scp_base	'init ADC/scope pins
    		wxpin	.scp_x,#3<<6+scp_base
    		dirh	#3<<6+scp_base
    
    		setscp	#1<<6 + scp_base	'enable scope channels
    
    		setse1	#%001<<6 + scp_base	'set SE1 event to first scope pin trigger
    
    		setxfrq	##$2000_0000		'set streamer NCO frequency to sample every 4th clock
    
    
    ' Capture waveforms before and after trigger
    
    .loop		wrfast	#$1000/64,##buffer	'set wrfast to wrap 1k-sample circular buffer of 4 scope channels
    
    		xinit	.scp_d,#0		'issue 4-ADC8 capture command
    
    		waitx	##320*4			'allow time to fill first half of buffer
    
    		akpin	#scp_base		'acknowledge trigger pin to clear
    		pollse1				'clear any old trigger event
    		akpin	#scp_base		'acknowledge trigger pin to clear
    		waitse1				'wait for new trigger event
    
    		getptr	.x			'capture write pointer, reflects trigger point
    
    		waitx	##320*4			'allow time to fill second half of buffer
    
    		xstop				'stop streamer, ~640 samples gathered within 1k sample buffer
    
    
    		sub	.x,##320*4		'determine start of buffer so that trigger point is in the middle
    		and	.x,##$0FFC
    		or	.x,##buffer
    
    		rdfast	#$1000/64,##buffer	'set rdfast to wrap 1k-sample buffer
    
    .scan		getptr	.y			'advance to starting sample (320 samples before trigger)
    		cmp	.y,.x	wz
    	if_nz	rflong	.p
    	if_nz	jmp	#.scan
    
    
    ' Dim existing pixels in bitmap
    
    		loc	ptra,#bitmap
    		mov	.y,#480
    
    .dimline	setq2	#640/4-1		'read in 640 pixels
    		rdlong	0,ptra
    
    		mov	ptrb,#0
    
    		rep	@.r,#640/4		'dim 640 rgbi8 pixels
    		rdlut	.p,ptrb
    		mov	.q,.p
    		and	.q,.rgbmasks
    		not	.p
    		or	.p,.rgbmasks
    		addpix	.p,.incbytes
    		not	.p
    		or	.p,.q
    		wrlut	.p,ptrb++
    .r
    		setq2	#640/4-1		'write back 640 pixels
    		wrlong	0,ptra++
    
    		djnz	.y,#.dimline
    
    ' Plot waveforms
    
    		mov	.x,#0
    		rflong	.p
    
    .xloop		mov	.d,.i			'get samples to compute deltas from
    		mov	.i,.p
    '		mov	.n,.p
    		rflong	.p			'get 4-channel sample
    
    		getbyte	.da,.i,#3		'perform compensation
    		getbyte	.j,.d,#3
    		sub	.da,.j
    		muls	.da,.scale
    		sar	.da,#8
    
    		getbyte	.db,.i,#2
    		getbyte	.j,.d,#2
    		sub	.db,.j
    		muls	.db,.scale
    		sar	.db,#8
    
    		getbyte	.fa,.p,#3
    		sub	.fa,.db
    		rolbyte	.k,.fa,#0
    
    		getbyte	.fb,.p,#2
    		sub	.fb,.da
    		rolbyte	.k,.fb,#0
    
    
    		getbyte	.da,.i,#1
    		getbyte	.j,.d,#1
    		sub	.da,.j
    		muls	.da,.scale
    		sar	.da,#8
    
    		getbyte	.db,.i,#0
    		getbyte	.j,.d,#0
    		sub	.db,.j
    		muls	.db,.scale
    		sar	.db,#8
    
    		getbyte	.fa,.p,#1
    		sub	.fa,.db
    		rolbyte	.k,.fa,#0
    
    		getbyte	.fb,.p,#0
    		sub	.fb,.da
    		rolbyte	.k,.fb,#0
    
    
    
    		mov	.q,#480			'plot channel 3 first
    
    		rep	@.plot,#4		'ready to plot 4 channels
    		getbyte	.y,.k,#3		'get sample
    		shr	.y,#1			'divide by 2 to fit screen
    		subr	.y,.q			'flip and vertically position
    		mul	.y,.xsize		'get bitmap pixel address
    		add	.y,.x
    		add	.y,.bitmap
    		wrbyte	.color,.y		'plot pixel
    		shl	.k,#8			'ready next sample
    		sub	.q,#117			'ready next vertical position
    		ror	.color,#8		'ready next color
    .plot
    		incmod	.x,.xlimit	wc	'loop until all pixels plotted
    	if_nc	jmp	#.xloop
    
    ' Plot trigger level marker
    
    		mov	.y,.scp_x		'get trigger level
    		shr	.y,#9
    		subr	.y,#128
    		mul	.y,.xsize
    		add	.y,#320-9
    		add	.y,.bitmap
    		setq	#4-1
    		wrlong	##$FFFFFFFF,.y		'white marker
    
    ' Toggle P56 for a speed indicator, then loop
    
    		drvnot	#56
    
    		jmp	#.loop			'loop
    
    ' Data
    
    .scpmode	long	%0000_0000_000_100011_0000000_00_11010_0	'ADC/scope mode
    
    .scp_d		long	%1111_0000_1000_0110<<16 + $FFFF		'DDS/Goertzel mode
    .scp_x		long	(trigger_level & $FC)<<8 + (arm_level & $FC) + scope_filter
    .rgbmasks	long	$E0E0E0E0
    .incbytes	long	$01010101
    
    .xlimit		long	640-1
    .xsize		long	640
    .bitmap		long	bitmap
    
    .color		long	$5F_BF_DF_1F	'initial trace colors
    
    .scale		long	200/2
    
    .x		res	1
    .y		res	1
    .p		res	1
    .d		res	1
    .q		res	1
    .k		res	1
    .j		res	1
    .i		res	1
    .n		res	1
    .da		res	1
    .db		res	1
    .fa		res	1
    .fb		res	1
    
    
    
    '*********************************
    '*  HDMI 640 x 480 x 8bpp rgbi8  *
    '*********************************
    
    DAT             org
    
    pgm_hdmi        setcmod #$100                   'enable HDMI mode
                    drvl    #7<<6 + hdmi_base       'enable HDMI pins
                    wrpin   ##%111001<<8,#7<<6 + hdmi_base  'set 1.5k low drive on HDMI pins
    
                    setxfrq ##$0CCCCCCC+1           'set streamer freq to 1/10th clk (25 MHz)
    
                    rdfast  ##640*480/64,##bitmap   'set rdfast to wrap on 300KB bitmap
    
    ' Field loop
    
    .field          mov     .hsync0,.sync_000       'vsync off
                    mov     .hsync1,.sync_001
    
                    callpa  #10,#.blank             'top blanks
    
                    mov     .i,#480                 'set visible lines
    .line           call    #.hsync                 'do horizontal sync
                    xcont   .m_rf,#0                'do visible line
                    djnz    .i,#.line               'another line?
    
                    callpa  #33,#.blank             'bottom blanks
    
                    mov     .hsync0,.sync_002       'vsync on
                    mov     .hsync1,.sync_003
    
                    callpa  #2,#.blank              'vertical sync blanks
    
                    jmp     #.field                 'loop
    
    ' Subroutines
    
    .blank          call    #.hsync                 'blank lines
                    xcont   .m_vi,.hsync0
            _ret_   djnz    pa,#.blank
    
    .hsync          xcont   .m_bs,.hsync0           'horizontal sync
                    xzero   .m_sn,.hsync1
            _ret_   xcont   .m_bv,.hsync0
    
    ' Data
    
    .sync_000       long    %1101010100_1101010100_1101010100_10    '
    .sync_001       long    %1101010100_1101010100_0010101011_10    '        hsync
    .sync_002       long    %1101010100_1101010100_0101010100_10    'vsync
    .sync_003       long    %1101010100_1101010100_1010101011_10    'vsync + hsync
    
    .m_bs           long    $70810000 + hdmi_base<<17 + 16          'before sync
    .m_sn           long    $70810000 + hdmi_base<<17 + 96          'sync
    .m_bv           long    $70810000 + hdmi_base<<17 + 48          'before visible
    .m_vi           long    $70810000 + hdmi_base<<17 + 640         'visible
    .m_rf           long    $B0830000 + hdmi_base<<17 + 640         'visible rfbyte luma8
    
    .hsync0         res     1
    .hsync1         res     1
    
    .i		res	1
    
    
    end_of_pgm
    
  • cgraceycgracey Posts: 11,954
    edited 2019-11-25 - 12:14:19
    Tubular wrote: »
    wow that really cleaned up nicely

    Thanks for suggesting a math solution. It wasn't occurring to me that something could be done in software. I was only thinking about hardware.

    This technique is good enough for SCOPE mode, but for high-resolution conversions, some pin-use considerations are going to be necessary.
  • Hi

    This is amazing.
    So that clears up crosstalk or induced noise within the unit but- I wonder- (because I don't understand exactly what you've done!)- how does this effect a genuine noisy signal? and you want to see the noise?

    Dave
  • tritonium wrote: »
    Hi

    This is amazing.
    So that clears up crosstalk or induced noise within the unit but- I wonder- (because I don't understand exactly what you've done!)- how does this effect a genuine noisy signal? and you want to see the noise?

    Dave

    That noise would still be there. This just removes what the other signal is contributing.
  • Would a load resistor at the input to these pins change anything?
    Prop Info and Apps: http://www.rayslogic.com/
  • Some mathematical musings: the 2-sample delay compensation is a simple 2nd-order digital filter, which is precisely what is needed because the problem is a 2nd-order one, namely the rate of change of the slope of the adjacent input. Unwanted effects are seen when there is a discontinuity in the slope. A 1-sample delay should be insufficient and a 3-sample one should not be any better than 2-sample.

    A possible change to the software would be to fix the frequency and sweep the compensation scale to find the sweet spot, or sweep both at the same time.
    Formerly known as TonyB
  • Sadly, this fix only works for low-impedance signals coming into the ADC pins.
  • roglohrogloh Posts: 1,695
    edited 2019-11-25 - 22:57:04
    Is there a simple way to see the raw signals in this display (non-windowed)? I know it would be noisier but it would be interesting to see the response reduce as the frequency is increased. Perhaps this window averaging might be causing the relatively slow displayed slew rate for square and sawtooth waveforms.
  • rogloh wrote: »
    Is there a simple way to see the raw signals in this display (non-windowed)? I know it would be noisier but it would be interesting to see the response reduce as the frequency is increased. Perhaps this window averaging might be causing the relatively slow displayed slew rate for square and sawtooth waveforms.

    The filter has 68 taps that the ADC bits must pass through. That's a bandwidth limiter, plus there's the roll-off of the analog front end of the ADC. I really want to redesign the ADC to give it more bits, make it independent of modes, and clean up the MUX problem. Just cutting away the PinB selection would solve the worst problem.
  • Ok. I can see the response reduce when I increase this line up towards 3 MHz. Square wave amplitude holds up for the longest, which makes sense if its output voltage remains at the extremities longer.

    E.g
    dds_freq = 3000_000.0 'nominal DDS frequency (without FM'ing)

    The windowing/filter stuff really seems to impact the displayed slew rate.

    At the original lower frequency I would have naively expected a waveform as something looking like Figure3 from this link below, but I guess all the extra front end processing does more than that.

    https://sound-au.com/articles/squarewave.htm
  • rogloh wrote: »
    Ok. I can see the response reduce when I increase this line up towards 3 MHz. Square wave amplitude holds up for the longest, which makes sense if its output voltage remains at the extremities longer.

    E.g
    dds_freq = 3000_000.0 'nominal DDS frequency (without FM'ing)

    The windowing/filter stuff really seems to impact the displayed slew rate.

    At the original lower frequency I would have naively expected a waveform as something looking like Figure3 from this link below, but I guess all the extra front end processing does more than that.

    https://sound-au.com/articles/squarewave.htm

    Figure 3 is what the ADC analog front end sees, but the 68-tap filter absolutely limits slew.
  • You can always use the streamer to record the raw sigma delta bitstream, then apply whatever filter you like (try different numbers of taps, etc)

    Its just nice that the scope mode does so much work for you.
  • The scope_filter constant in the program could be changed to switch from 68 to 45 or 28 taps.
    Formerly known as TonyB
  • Yes that 28 tap version does improve the apparent slew rate.
  • cgraceycgracey Posts: 11,954
    edited 2019-11-26 - 18:57:06
    I've found a way to fix the ADC crosstalk problem by cutting a trace on metal layer 2 to eliminate PinB from getting into the ADC's input resistor array, where it mixes (accidentally) with PinA. This would be possible to work into the next wafers at minimal cost. It would also mean that you could not use the ADC on the adjacent pin, but only on the pin, itself. Probably, nobody would care about this. It's way more important that each pin's ADC can work independently, without coupling unwanted signal from its adjacent pin.

    The bigger problem would be reworking our I/O test program that runs on ON's wafer prober, since it uses PinB-to-ADC mode. I'm looking into that now.

    Meanwhile, here is the fix:


    ADC_PinB_Cut.png


    1662 x 1195 - 148K
  • RaymanRayman Posts: 9,945
    edited 2019-11-26 - 19:03:42
    Does just using one pin in a pair solve this issue in the current silicon?

    Also, is there any advantage to having the pair of pins tied to the same analog signal?

    This doesn't sound like the kind of issue that is worth redoing the silicon, to me anyway...
    Prop Info and Apps: http://www.rayslogic.com/
  • cgraceycgracey Posts: 11,954
    edited 2019-11-26 - 19:20:31
    Rayman wrote: »
    Does just using one pin in a pair solve this issue in the current silicon?

    Also, is there any advantage to having the pair of pins tied to the same analog signal?

    This doesn't sound like the kind of issue that is worth redoing the silicon, to me anyway...

    Using just one pin, and making sure the other pin is QUIET, will do the job. Or, tying your analog signal to both pins, in which case you can get an extra bit of resolution.

    If we do this, it may only be a $5k mask charge for either M2 or VIA2. It doesn't impact wafer delivery, as they are weeks away from processing the metal layers.


    1127 x 850 - 170K
  • Price is right. But, I'd be afraid of doing a full scale production run with untested masks...
    Will OnSemi verify that the change won't mess anything up?
    Prop Info and Apps: http://www.rayslogic.com/
  • jmgjmg Posts: 14,152
    cgracey wrote: »
    Using just one pin, and making sure the other pin is QUIET, will do the job. Or, tying your analog signal to both pins, in which case you can get an extra bit of resolution.

    If we do this, it may only be a $5k mask charge for either M2 or VIA2. It doesn't impact wafer delivery, as they are weeks away from processing the metal layers.

    It's common for MCUs to have 'rules' around their ADC pins, around quietest pins/crosstalk etc, and some specify switching to IDLE during ADC conversion for lowest noise...
    I'm with Rayman, not sure this is worth the risk/benefit.

  • Looking at this from ST makes me think it's a common problem...

    Also, these two pins are likely to have coupling issues due to the traces leading away from MCU as well.
    For that reason, you probably want to use only one of a pair of pins anyway..
    674 x 734 - 69K
    Prop Info and Apps: http://www.rayslogic.com/
  • Still a fan of being bold, and eliminating errata when it makes sense.

    Okay, so how much of a predicted effect does this mask change have on the crosstalk? Will it eliminate it, or will there still be some crosstalk like it gets reduced by 25% but still there?
    Because if there is still going to be some immediately noticeable crosstalk, and the solution is still a software fix, the mask change doesn't solve anything and is just extra time and money.

    And risk. What onsemi can do on their end, is not throw away the old mask(s). Try a run with the new masks, change your test program, pass testing, ship.
    Or fail, and if it's a bad or misaligned mask onsemi will fix it and try again. Or given some other unforeseen effect, you go back to the old mask.
  • Sounds like this could become a HUGE amount of time for many people in the chain to spend on something that can be solved in no time at all by simply using non-pairs, or even non-group pins, with the current mask. Not to mention opportunity cost, as you'll be distracted from Spin2/etc..

    Did you find some really compelling reason to consider the mod ?

    Otherwise, what you said above "Or, tying your analog signal to both pins, in which case you can get an extra bit of resolution.".....

    That seems like a fine reason to keep your design as-is, and document that recommendation as a feature.
    Seems like that's a good feature to me: Joined pairs for highest resolution, alternate pins for medium resolution, and adjoining pins for lower resolution.
  • VonSzarvas wrote: »
    Seems like that's a good feature to me: Joined pairs for highest resolution, alternate pins for medium resolution, and adjoining pins for lower resolution.
    Yes, agree.

    The difference between theory and practice is that, in theory, there is no difference between theory and practice, but in practice, there is.
  • pmrobert wrote: »
    VonSzarvas wrote: »
    Seems like that's a good feature to me: Joined pairs for highest resolution, alternate pins for medium resolution, and adjoining pins for lower resolution.
    Yes, agree.

    This works for me too. And there is a software fix also.
    My Prop boards: P8XBlade2 , RamBlade , CpuBlade , TriBlade
    P1 Prop OS (also see Sphinx, PropDos, PropCmd, Spinix)
    Website: www.clusos.com
    P1: Tools (Index) , Emulators (Index) , ZiCog (Z80)
    P2: Tools & Code , Tricks & Traps
  • But SETSCP/GETSCP work on a 4-pin block and if one pin in a pair is unused or both tied together it will be 2-channel, not 4-channel, and half the data will be wasted?
    Formerly known as TonyB
  • cgraceycgracey Posts: 11,954
    edited 2019-11-26 - 21:42:42
    Aside from a single layer mask expense, I would just need to rewrite the test program to not use that pin B mode. I'm looking at that right now. It's really not that complicated, but makes the scope modes work like they're supposed to.

    The risk of making this change is extremely low. It just takes some time for me to rewrite the test program.
  • Don't worry about it, Chip. The software improvement is enough..

  • What happens when you drive pairs of pins in differential mode? Do you get an added crosstalk on one pin and a subtracted crosstalk on the other? Remember, sigma delta conversion is notorious for out of band oscillations, like those period 7 "1011011" patterns that are so hard to suppress. But of course; if you could get an equal and opposite effect which cancels out around the problem "codes" then the achievable bandwidth goes up, I'm tempted to say - exponentially; maybe speaking figuratively or maybe not - because there is a type of "modulator" known as a "Weaver" modulator, that for example is used to make SSB signals by first modulating an audio signal with a 1.5 kilohertz pair of carriers, i.e. for SSB speech. Really, its just an analog implementation of the first stage of Cooley-Tukey FFT using ring modulators, but because it turns, let's say a 3kHz bandwidth audio signal into four 1.5 kHz bandwidth signals, you get the effect of doubling the A to D bandwidth if you follow the Weaver with a set of modulators instead of upconverting to an SSB carrier frequency. Or you can get 10 or 20 Mhz. bandwidth from a 5 to 10 Mhz. oscilloscope front end, or double that if you cascade a pair of Weaver filters. So if the is a silver lining among the clouds of grey, it is that if you have ever looked at the schematic of a 555, or 741 or an analog three terminal regulator, especially those three terminal regulators; because they have to use the ratio of a set or set of matched resistors to compare to junction intrinsic (Ebers-Moll equation again?) characteristic of two different junctions, so as to be able to use a bizarre arrangement of logarithmic convertors to compensate for temperature and produce a constant output voltage. Which means, likewise, if there is an exact - very precisely controlled amount of parasitic crosstalk that can be perfectly cancelled in software among the pins, then it is possible to exactly compensate for gain differences in the internal and external circuity, in addition to computing the cross-talk cancellation factor, which is also the "chopper" factor if you are doing instrumentation like EEG, EKG, etc., and you need near ZERO dc offset and near ZERO drift and as complete 1/f cancellation when you compare the summation of "count bits" on each of the pins with the filter outputs.
  • How much crosstalk is there between non-paired pins? There is likely still some from the pcb and package. Digital outputs have a low impedance and probably aren't a good representation of an analog source. Maybe 50 ohms from digital output to ADC, or use a reduced drive mode.
    James https://github.com/SaucySoliton/

    Invention is the Science of Laziness
  • How much crosstalk is there between non-paired pins? There is likely still some from the pcb and package. Digital outputs have a low impedance and probably aren't a good representation of an analog source. Maybe 50 ohms from digital output to ADC, or use a reduced drive mode.

    Very little between non-paired pins, but between paired pins, the crosstalk is at about -24dB, which is really high, about 4 bits down.
Sign In or Register to comment.