⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 videodvm.asm

📁 Video-DVM is a very cheap DVM that shows how an output as complex as a videocomposite signal can be
💻 ASM
📖 第 1 页 / 共 2 页
字号:

;****************************************************************************
;* SCREEN MAKEUP JUMP STRUCTURE
;* This compare and jump table determines the appearence of the display
;* at each step, the current line number is examinated to decide
;* which display routine to use
;****************************************************************************

BUILDSCREEN:
	;it's time to decide what to display, depending on current line
	
	cpi     RowsDivFour, 278/4	;from line 268 on, blank display
	brlo    _A
	rjmp    VOIDLINE        

_A:     cpi     RowsDivFour, 254/4	;at line 244, display minimum
	brlo    _A2
	ldi     Arg1, 3
	mov     CharHeight, Arg1
	mov     PrintCD, ADCLowMin
	mov     PrintAB, ADCHighMin
	ldi     Arg1, 9
	rjmp    DISPLAYDIGITS

_A2:    cpi     RowsDivFour, 234/4	
	brlo    _A1
	rjmp    VOIDLINE        

_A1:    cpi     RowsDivFour, 210/4	;at line 220, display maximum
	brlo    _B
	ldi     Arg1, 3
	mov     CharHeight, Arg1
	mov     PrintCD, ADCLowMax
	mov     PrintAB, ADCHighMax
	ldi     Arg1, 10
	rjmp    DISPLAYDIGITS

_B:     cpi     RowsDivFour, 182/4
	brlo    _C
	rjmp    VOIDLINE        

_C:     cpi     RowsDivFour, 178/4
	brlo    _C2
	ldi     Arg1, 26
	nop
	rjmp    DISPLAY_FINERULER

_C2:     cpi     RowsDivFour, 174/4
	brlo    _D 
	ldi     Arg1, 25
_C1:    rjmp    DISPLAY_COARSERULER

_D:     cpi     RowsDivFour, 150/4
	brlo    _E
	ldi     Arg1, 24
	rjmp    DISPLAYBAR

_E:     cpi     RowsDivFour, 146/4
	brlo    _F 
	ldi     Arg1, 23
	rjmp    DISPLAY_COARSERULER

_F:     cpi     RowsDivFour, 125/4
	brlo    _G
	rjmp    VOIDLINE


_G:     cpi     RowsDivFour, 45/4
	brlo    VOIDLINE
	mov     PrintCD, ADCLow
	mov     PrintAB, ADCHigh
	ldi     Arg1, 10
	mov     CharHeight, Arg1
	ldi     Arg1, 1
	rjmp    DISPLAYDIGITS

VOIDLINE:     
	clr     Arg4            ;reset pixel mask
	rjmp    TIMER_EXIT


				     
;****************************************************************************
;* ON SCREEN DISPLAY ROUTINES
;****************************************************************************


DISPLAYDIGITS:
	dec     Arg1               	;delay loop for alignment purpose
	brne    DISPLAYDIGITS		;this is the "print" routine
	
	tst     CurrHeight		;that prints a ROW of pixels
	breq    _7			;according to the buffer PrintAB-CD
	nop				;and the height specified in CharHeight
	rjmp    _8
_7:     mov     CurrHeight, CharHeight
	lsl     Arg4
_8:     skipne
	inc     Arg4
	
	ldi     Arg3, 0b00010000      	;set decimal point position mask
	sbis    PinB, DPSel1Bit		;if jumper 1 closed
	lsl     Arg3			;shift decimal point mask one place
	sbis    PinB, DPSel2Bit		;if jumper 2 closed
	lsl     Arg3			;shift decimal point two places
	sbis    PinB, DPSel2Bit
	lsl     Arg3
	sbis    PinB, DPSel3Bit		;if jumper 3 closed
	lsl     Arg3			;shift decimal point one place
	mov     PointPosition, Arg3	;
	
	mov     Arg3, PrintAB		;load single charachters in Arg3
	swap    Arg3			;and call the display charachter
	rcall   DISPLAYCHAR		;routine: character A
	mov     Arg3, PrintAB        	;then charachter B
	rcall   DISPLAYCHAR
	mov     Arg3, PrintCD 		;then character C
	swap    Arg3
	rcall   DISPLAYCHAR
	mov     Arg3, PrintCD        	;then caharacter D
	rcall   DISPLAYCHAR
	ldi     Arg3, 10        	;after characters ABCD, display the
	rcall   DISPLAYCHAR		;measurement units character, too
	
	dec     CurrHeight		;decrease the height counter
	rjmp    DISPLAYLINERESTART      ;end line

;****************************************************************************
;* DISPLAYCHAR: prints on screen the row set by Arg4 of the character Arg3
;* Character matrix is 5 x 7 dots, and is stored by column in eeprom
;* Arg3= character to display
;* Arg4 = mask for vertical pixel selection
;****************************************************************************
INSERTPOINT:                            ;insert decimal point between digits
	mov     PointPosition, Arg3     ;Save character to print 
	ldi     Arg3, 60                ;substitute it with point
	ldi     Arg2, 2                 ;preload reduced width
	rjmp    DISPLAYCOLUMN           ;go print it

DISPLAYCHAR:
	andi    Arg3, 0b00001111        ;clear high nibble
	lsl     PointPosition		;if point insertion request
	brcs    INSERTPOINT		;go swapoing the charachter with dot
	mov     Arg1, Arg3              ;otherwise if point not requested
	lsl     Arg1                    ;multiply character by 5
	lsl     Arg1                    ;to get offset in font table
	add     Arg3, Arg1              ;now Arg3 is the table offset
	ldi     Arg2, 5                 ;Arg2 = column number
DISPLAYCOLUMN:        
	out     EEAR,  Arg3             ;set eeprom address register
	sbi     EECR, 0                 ;send read command
	in      Arg1, EEDR              ;read font table in EEPROM
	and     Arg1, Arg4              ;mask unwanted pixels
	skipeq                          ;according to table
	sbi     PortD, VideoBit         ;turn pixel on or...
	skipne
	cbi     PortD, VideoBit         ;...turn pixel off
	inc     Arg3                    ;next column in table
	dec     Arg2                    ;if not last column
	brne    DISPLAYCOLUMN           ;then display next one
					;otherwise this is the
	doublenop                       ;last pixel, waste time...
	doublenop
	doublenop
	ldi     Arg1, 0                 ;
	cpi     Arg3, 61                ;if table offset > 60 (point done)
	mov     Arg3, PointPosition     ;then restore character saved in PointPosition
	skiplo                          ;(if point inserted reset PointPosition)
	mov     PointPosition, Arg1     ;(dont use clear, test pending)
	cbi     PortD, VideoBit         ;turn pixel off
	brsh    DISPLAYCHAR             ;and go print it
	
	ret                             ;else exit

;****************************************************************************
;* DISPLAYBAR: builds the analog bar display. The bar has a resolution
;* of 128 steps, each step takes 4 clock cycles to display.
;* The bar lenght is 32 uS.
;****************************************************************************

DISPLAYBAR:
	dec     Arg1                    ;delay loop to align ruler and bar
	brne    DISPLAYBAR
	
	ldi     Arg1, 0b01111111
	and     Arg1, BarLenght
	ldi     Arg2, 0b01111111
	eor     Arg2, Arg1

	;wait for ruler start position
	;Arg1 Value/8; Arg2=127-Value/8-1
	tst     Arg1
	breq    BLACKBAR
	sbi     PortD, VideoBit
WHITEBAR:        
	dec     Arg1
	nop
	brne    WHITEBAR
BLACKBAR:
	cbi     PortD, VideoBit
	nop
	rjmp    WAITBAREND              ;waste time
WAITBAREND:        
	dec     Arg2
	nop
	brge    WAITBAREND
	rjmp    DISPLAYLINERESTART


;****************************************************************************
;* DISPLAY RULER ROUTINES: the coarse ruler has 10 tiks, the fine one 
;* has 100 ticks, calibrated for input range from 0=0 to 4000=100
;****************************************************************************

DISPLAY_COARSERULER:

	dec     Arg1                    ;delay loop to align ruler to bar
	brne    DISPLAY_COARSERULER

	ldi     Arg1, 11                ;load ticks counter
	ldi     Arg2, 11                ;amount of black between ticks
	in      Arg4, PortD             ;Arg4 = actual output (tick off)
	mov     Arg3, Arg4
	sbr     Arg3, EXP2(VideoBit)    ;Arg3 = output with tick on

COARSETICK:                             ;for Arg1 = 1 to 11   
	out     PortD, Arg3             ;       make a tick 1 pixel wide
	out     PortD, Arg4             ;       (sbi would take 2 cycles) 
BLACKSPACE:        
	dec     Arg2                    ;       for Arg2 = 1 to 11
	nop                             ;               wait 4 cycles
	brne    BLACKSPACE              ;       next
	ldi     Arg2, 11                ;   (reload tick spacing)
	dec     Arg1                    ;   (this takes another 4 cycles)
	nop                             ;   
	brne    COARSETICK              ;next tick
	rjmp    DISPLAYLINERESTART

DISPLAY_FINERULER:

	dec     Arg1                    ;delay loop to align ruler to bar
	brne    DISPLAY_FINERULER

	ldi     Arg1, 101               ;load ticks counter
	in      Arg4, PortD             ;Arg4 = actual output (tick off)
	mov     Arg3, Arg4
	sbr     Arg3, EXP2(VideoBit)    ;Arg3 = output with tick on

FINETICK:                               ;for Arg1 = 1 to 101   
	out     PortD, Arg3             ;       make a tick 1 pixel wide
	out     PortD, Arg4             ;       (sbi would take 2 cycles) 
	dec     Arg1                    ;
	brne    FINETICK                ;next
	rjmp    DISPLAYLINERESTART


;****************************************************************************
;* Official line exit point for all display routines
;****************************************************************************

DISPLAYLINERESTART:
	ldi     Arg1, EXP2(TOV0)        ;clear timer overflow bit
	out     TIFR, Arg1              ;
	rjmp	WAITNEWLINE
	
	;set				;T flag tells that we are going to sleep
	;sei
	;sleep				;sleep until awaken by timer interrupt
	;nop
	;cli
	;clt				;with T flag low, subsequent 
	;rjmp NEWLINE                    ;jump directly to another video line,
					
	
;****************************************************************************
;* BIN_BCD:  Transforms binary data in Main1-2 to Main3-4
;* Works from 0 to 9999 - Argument in Main1-2 is destroyed
;****************************************************************************

BIN_BCD:
	clr     Main3
	clr     Main4
MORE_THOUSANDS:  
	cpi     Main2, HIGH(1000)	;argument > 1000?
	brlo    HUNDREDS
	brne    DEC_1000
	cpi     Main1, LOW(1000)
	brlo    HUNDREDS
DEC_1000:				;yes, then add 1 to thousands digit
	inc     Main4			;and subtract 1000 to argument
	subi    Main1,  LOW(1000)
	sbci    Main2, HIGH(1000)
	rjmp    MORE_THOUSANDS		;repeat until argument > 1000

HUNDREDS:
	swap    Main4
MORE_HUNDREDS:        			;argument > 100?
	cpi     Main2, HIGH(100)
	brlo    TENS
	brne    DEC_100
	cpi     Main1, LOW(100)
	brlo    TENS
DEC_100:				;yes, then add 1 to hundreds digit 
	inc     Main4			;and subtract 100 to argument
	subi    Main1,  LOW(100)
	sbci    Main2, HIGH(100)
	rjmp    MORE_HUNDREDS		;repeat until argument > 100
	
TENS:
MORE_TENS:
	cpi     Main1, 10		;argument > 10?
	brlo    UNITS			;yes, then add 1 to tens counter
	inc     Main3			;and subtract 10 to argument
	subi    Main1, 10
	rjmp    MORE_TENS		;repeat until argument > 10
UNITS:
	swap    Main3			;now argument is reduced to units...
	add     Main3, Main1            ;add units to result
	ret


;****************************************************************************
;* SENDSERIAL: sends byte Main1 to serial line
;* Uses Main2 and Main3; Main1 is destroyed
;****************************************************************************

SENDSERIAL:
	ldi     Main2, 0b00000001       ;load stop bit
	lsl     Main1                   ;add start bit
	rol     Main2                   ;to get the bit image of RS232 word
	ldi     Main3, BAUDRATE         ;bit time (in video lines)
	sbr     MiscFlags, EXP2(SerialReqBit)   ;request interrupt servicing
WAITTX:
	sbrc    MiscFlags, SerialReqBit ;wait for interrupt acknowledge
	rjmp    WAITTX
	ret

SERIALDRIVER:                           ;called once a line
	sbrs    MiscFlags, SerialReqBit ;is serial tx pending?
	rjmp    EXITSERIALDRIVER        ;no, exit routine
	dec     Main3                   ;yes, decrease bit interval timer
	doublenop                       ;time balancing
	brne    EXITSERIALDRIVER        ;is it time to send another bit?   
	ldi     Main3, BAUDRATE         ;yes, reload bit timer 
	lsr     Main2                   ;shift buffer into carry
	ror     Main1
	skipcc
	cbi     PortD, RS232Bit         ;send ONE
	skipcs
	sbi     PortD, RS232Bit         ;send ZERO
	cpi     Main1, 0                ;if buffer = 0x0000, done
	cpc     Main2, Main1
	skipne
	cbr     MiscFlags, EXP2(SerialReqBit)   ;acknowledge caller
	nop                             ;time balancing
EXITSERIALDRIVER:
	ret
		     
;****************************************************************************
;*  READADC: reads ADC channel specified by Main1 into Main3-4
;*  Range is 0-4096. Uses Main2
;****************************************************************************

.MACRO  ADC_CLOCKPULSE
					;makes a clock pulse: implemented
					;as macro because stack is exausted
	sbi     PortD, SCLKBit          ;SCLK high
.SET    _nextstep = PC+1                ;wait at least 200 nS
	rjmp    _nextstep
.SET    _nextstep = PC+1
	rjmp    _nextstep
	cbi     PortD, SCLKBit          ;SCLK low
.ENDMACRO


READADC:
	cbi     PortD, SCLKBit          ;clear the clock line
	cbi     PortD, CSBit            ;chip-select the ADC
	swap    Main1                   ;setup ADC commmand word
	andi    Main1, 0b01110000       ;(unipolar, single ended conversion
	ori     Main1, 0b10001110       ;with internal clocking)
	ldi     Main2, 50
	ldi     Main2,8                 ;prepare bit counter

ADC_SENDCOMMAND:
	rol     Main1                   ;shift out 8-bit command
	skipcc
	sbi     PortD, DINBit           ;set output pin accordingly
	skipcs
	cbi     PortD, DINBit
	ADC_CLOCKPULSE                  ;start a clock pulse (macro does 
	dec     Main2                   ;not need stack space)
	brne    ADC_SENDCOMMAND         ;loop untils all the 8 bits sent
	
	ldi     Main2, 50               ;setup wait time
_WAITLOOP:                              ;wait 12.5 uS to allow conversion ends
	dec     Main2
	nop                             ;waste time
	brne    _WAITLOOP
	clr     Main3                   ;clear result (high byte will be overwritten)
	ldi     Main2, 13               ;shift in 10+2 bit result plus one more clock
ADC_RECEIVEDATA:
	ADC_CLOCKPULSE                  ;clock the ADC for next bit
	clc                             ;carry cleared
	sbic    PinB, DOUTBit           ;if ADC data pin is high, set carry
	sec
	rol     Main3                   ;shift carry into data buffer
	rol     Main4
	dec     Main2
	brne    ADC_RECEIVEDATA         ;repeat until all bits read
	sbi     PortD, CSBit            ;release ADC chip select
	ret



⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -