'************************************* '* composite video to * '* VGA 640 x 480 x 8bpp grayscale * '* unsynchronized * '* VGA on pins 0-4 * '* * '* composite input and output * '* configurable * '* * '* demonstrates triangular window * '* using Goertzel hardware * '* also provides fractional * '* interpolation * '* * '* sampling frequency can be * '* adjusted to reduce roll rate * '* on the VGA output * '************************************* CON intensity = 80 '0..128 xtal = 20_000_000 dv = 2 mlt = 25 pdv = 1 clk = 1 << 24 | (dv-1) << 18 | (mlt-1) << 8 | (((pdv>>1)+15) & $F) << 4 fclk = xtal / dv * mlt / pdv ' fclk = 80_000_000.0 fpix = 25_000_000.0 fset = (fpix / fclk * 2.0) * float($4000_0000) vsync = 4 'vsync pin adcpin = 16+4 dacpin = 40 shift = 0 #0 start_cog adc_cog DAT org ' ' ' Setup ' hubset ##clk | %0000_01_00 'enable crystal+PLL, stay in 20MHz+ mode waitx ##20_000_000/100 'wait ~10ms for crystal+PLL to stabilize hubset ##clk | %0000_01_11 'now switch to PLL running rdfast ##640*480*1/64,##$1000 'set rdfast to wrap on bitmap setxfrq ##round(fset) 'set transfer frequency to 25MHz 'the next 4 lines may be commented out to bypass signal level scaling setcy ##intensity << 24 'r set colorspace for rgb setci ##intensity << 16 'g setcq ##intensity << 08 'b setcmod #%01_0_000_0 'enable colorspace conversion (may be commented out) wrpin dacmode_s,#0 'enable dac modes in pins 0..3 wrpin dacmode_c,#1 wrpin dacmode_c,#2 wrpin dacmode_c,#3 setnib dira,#%1111,#0 coginit #adc_cog,##@adc_boot ' Start the DAC cog ' ' ' Field loop ' field mov x,#23 'top blanks call #blank mov x,#480 'set visible lines line call #hsync 'do horizontal sync xcont m_rf,#15 'visible line djnz x,#line 'another line? mov x,#20 'bottom blanks call #blank drvnot #vsync 'sync on mov x,#2 'sync blanks call #blank drvnot #vsync 'sync off jmp #field 'loop ' ' ' Subroutines ' blank call #hsync 'blank lines xcont m_vi,#0 _ret_ djnz x,#blank hsync xcont m_bs,#0 'horizontal sync xzero m_sn,#1 _ret_ xcont m_bv,#0 ' ' ' Initialized data ' dacmode_s long %0000_0000_000_1011000000000_01_00000_0 'hsync is 123-ohm, 3.3V dacmode_c long %0000_0000_000_1011100000000_01_00000_0 'R/G/B are 75-ohm, 2.0V m_bs long $CF000000+16 'before sync m_sn long $CF000000+96 'sync m_bv long $CF000000+48 'before visible m_vi long $CF000000+640 'visible m_rf long $1F000000+640 'visible rfword rgb8 x res 1 y res 1 '1111111111111111111111111111111111111111111111111111111111111111111111111111 orgh org adc_boot long 0 mov az,#$7F 'make 128-sample trianglular table in lut sincos mov ax,az ' ax = rising slope mov ay,#$7F sub ay,az ' ay = falling slope setbyte ax,ay,#1 'copy byte 0 to 1 setword ax,ax,#1 'copy bytes 1,0 to 3,2 ' xor ax,##$8080 'make bytes 1,0 positive (not used, but could be) wrlut ax,az 'write yacc:xacc:X1:X0 into lut djnf az,#sincos 'make 128 samples ' set up I/O wrpin adcmode,#adcpin 'enable ADC pin (Goertzel may use gtzpin directly) wrfast ##640*525*1/64,##$1000 'set rdfast to wrap on bitmap ' Output scaling: max accumulator output is (b*h/2) * (2^31/(b*f)) ' h=127 , maximum value of window function ' b=256 , width/length of window function ' f= Goertzel NCO frequency ' b=number of clocks to get through the window ' ' output scale value z= m*f / ( b*h*2^23 ) ' maximum output value, m=127 ' scaled output range will be -127:127 because Goertzel ' hardware adds and subtracts depending on adc pin ' ' simplifies to z= f/(2^31) ' >>17 to fit f into 16 bits for SCAS ' SCAS provides >>14 of result mov az,f1 shr az,#17 ' 17 to prevent overflow, 16 to boost gain drvl #dacpin ' enable output setq f1 'ready frequency loop ' output ay group xcont m1,s1 'issue Goertzel command getxacc ax 'rising half of next sample add ay,0 'falling half of this sample scas ay,az ' mov dy,0 xor dy,#$80 'Convert signed byte to unsigned byte wfbyte dy setbyte xymode,dy,#1 'dac pin update wrpin xymode,#dacpin ' output ax group setq f1 'ready frequency xcont m1,s1 'issue Goertzel command getxacc ay 'rising half of next sample add ax,0 'falling half of this sample scas ax,az mov dy,0 xor dy,#$80 'Convert signed byte to unsigned byte wfbyte dy setbyte xymode,dy,#1 'dac pin update wrpin xymode,#dacpin jmp #loop 'loop xymode long %0000_0000_000_1011100000000_00_00000_0 'DAC for x,y scope output (0-2V) 'adcmode long %0000_0000_000_1001110000000_00_00000_0 'ADC input, 100x mode 'adcmode long %0000_0000_000_1001000000000_00_00000_0 'ADC input,3.16x mode adcmode long %0000_0000_000_1000110000000_00_00000_0 'ADC input, 1x mode dacmode long %0000_0000_000_1011000000000_01_00000_0 'Goertzel DAC, also used as ADC ' ( sample rate ) f1 long round( float($4000_0000)/((float(fclk)/2.0)/(15732.05*640.0)) ) m1 long %0000_0001<<24 + adcpin<<17 + 1 'Goertzel mode, DAC0 output, 1 overflow s1 long 2<<9 'Loop Size 128, offset 0 ax res 1 ay res 1 az res 1 lastx res 1 lasty res 1 dx res 1 dy res 1 synclevel res 1 ' ' ' Bitmap ' ' orgh $1000 'justify pixels at $1000 'fb_addr file "rose.gray"