📄 videodvm.asm
字号:
;****************************************************************************
;* 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 + -