mirror of
https://github.com/smartykit/apple1.git
synced 2024-09-27 11:56:44 +00:00
414 lines
10 KiB
PHP
414 lines
10 KiB
PHP
|
;******************************************************************************
|
||
|
; NTSC/PAL Video Generation Code (16MHZ System Clock)
|
||
|
;
|
||
|
; Originally designed and written by Daryl Rictor (c)2003-2004
|
||
|
;
|
||
|
; Modified by Grant Searle 2007-13
|
||
|
; - Multi size fonts
|
||
|
; - Now uses a single clock interrupt
|
||
|
; - Supports 40 chars or 80 chars per line
|
||
|
;******************************************************************************
|
||
|
|
||
|
push acc
|
||
|
push accH
|
||
|
push ZL
|
||
|
push ZH
|
||
|
push J
|
||
|
in J,SREG
|
||
|
push J
|
||
|
|
||
|
;Get exact sync with clock (remove jitter)
|
||
|
lds J, TCNT1L
|
||
|
cpi J, 0x14
|
||
|
breq clkSync0
|
||
|
cpi J, 0x15
|
||
|
breq clkSync1
|
||
|
cpi J, 0x16
|
||
|
breq clkSync2
|
||
|
cpi J, 0x17
|
||
|
breq clkSync3
|
||
|
cpi J, 0x18
|
||
|
breq clkSync4
|
||
|
nop
|
||
|
nop
|
||
|
nop
|
||
|
clkSync0:
|
||
|
nop
|
||
|
nop
|
||
|
nop
|
||
|
clkSync1:
|
||
|
nop
|
||
|
nop
|
||
|
nop
|
||
|
clkSync2:
|
||
|
nop
|
||
|
nop
|
||
|
nop
|
||
|
clkSync3:
|
||
|
nop
|
||
|
nop
|
||
|
nop
|
||
|
clkSync4:
|
||
|
|
||
|
; Timer now always 0x24 at this point
|
||
|
cbi portb, syncpin ; drop the csync pin
|
||
|
|
||
|
LINECHECK:
|
||
|
cpi vlineh, 0x00
|
||
|
brne NOTFIRST256
|
||
|
|
||
|
cpi vline, 0x04
|
||
|
brlo VSYNC ; no, wait for hsync end
|
||
|
rjmp CHECKTOPBLANK
|
||
|
|
||
|
VSYNC:
|
||
|
rjmp EOL ; line 0 is a VSYNC line, we're done
|
||
|
|
||
|
CHECKTOPBLANK:
|
||
|
cp vline, line1
|
||
|
brlo TOPBLANK
|
||
|
rjmp CHECKFIRSTLINE
|
||
|
|
||
|
TOPBLANK:
|
||
|
rjmp BLANK
|
||
|
|
||
|
CHECKFIRSTLINE:
|
||
|
cp vline, line1
|
||
|
brne CHECKLASTLINE
|
||
|
|
||
|
FIRSTLINE:
|
||
|
ldi chrln, 0x00 ; sync chrlin with first active line
|
||
|
rjmp DISPLAY
|
||
|
|
||
|
CHECKLASTLINE:
|
||
|
cpi chrln, 0xC8 ; have we passed line 200?
|
||
|
brlo DISPLAY ; no, get ready for active display line
|
||
|
rjmp BLANK
|
||
|
|
||
|
NOTFIRST256:
|
||
|
cpi chrln, 0xC8 ; have we passed line 200?
|
||
|
brlo DISPLAY ; no, get ready for active display line
|
||
|
|
||
|
cp vline, lastline
|
||
|
brne BLANK ; no, wait for hsync end
|
||
|
|
||
|
ldi vlineh, 0x00 ; yes, reset vert counters
|
||
|
ldi vline, 0x00 ;
|
||
|
cpi cursorClk, 0xff ;
|
||
|
breq vs1 ;
|
||
|
inc cursorClk ; inc cursor clock
|
||
|
vs1:
|
||
|
|
||
|
BLANK:
|
||
|
|
||
|
ldi chrln, 0xFF ; reset pointer
|
||
|
rjmp WAITSYNCEND ;
|
||
|
|
||
|
graphics:
|
||
|
ori ZH,0x28
|
||
|
rjmp WAITSYNCEND
|
||
|
|
||
|
DISPLAY:
|
||
|
mov J, chrln ; Get current display line
|
||
|
lsr J ; divide by 8
|
||
|
lsr J ;
|
||
|
lsr J ; J now contains the text line number (0..24)
|
||
|
|
||
|
; get attribute definition for current line
|
||
|
ldi XL, 0xD0
|
||
|
ldi XH, 0x08 ; set to start of attribute SRAM
|
||
|
add XL, J
|
||
|
ld currLineAtt,X
|
||
|
|
||
|
; set the SRAM character pointer (X) to the start of the current line (chrln)
|
||
|
ldi XL, 0x50 ; # chrs per line
|
||
|
mul XL, J ; multiply by chrs per line
|
||
|
ldi J, 0x01 ; offset to start of display
|
||
|
add R1, J
|
||
|
movw XL, R0 ; mov it to X reg
|
||
|
|
||
|
; set Z to point to base of font row
|
||
|
ldi ZL, 0x00 ; ZL=0, ASCII code will be added for each character
|
||
|
mov ZH, chrln ; ZH= current display line
|
||
|
andi ZH, 0x07 ; do ZH MOD 8
|
||
|
|
||
|
; If graphics then point to the graphics block font
|
||
|
sbrc currLineAtt,ATT_GRAPHICS
|
||
|
rjmp graphics
|
||
|
|
||
|
; Check if single or double height to be drawn
|
||
|
sbrc currLineAtt,ATT_DBL_TOP
|
||
|
lsr ZH ; If double height top then linecounter incremented at half speed
|
||
|
sbrc currLineAtt,ATT_DBL_BOTTOM
|
||
|
lsr ZH ; If double height bottom then linecounter incremented at half speed
|
||
|
sbrc currLineAtt,ATT_DBL_BOTTOM
|
||
|
ori ZH,0x04 ; Display bottom 4 lines if bottom of a double line
|
||
|
|
||
|
; Check if bold or normal font
|
||
|
sbrs currLineAtt,ATT_BOLD
|
||
|
ori ZH,0x20 ;0x20 (Normal) or 0x40 (Bold)
|
||
|
sbrc currLineAtt,ATT_BOLD
|
||
|
ori ZH,0x40 ;0x20 (Normal) or 0x40 (Bold)
|
||
|
|
||
|
; Check if 40 or 80 chars
|
||
|
sbrs currLineAtt,ATT_80_CHAR_PER_LINE
|
||
|
ori ZH, 0x10 ; add $1000 for offset to start of wide font table
|
||
|
|
||
|
WAITSYNCEND: ; else wait sync pulse end
|
||
|
lds J, TCNT1L ;
|
||
|
cpi J, 0x5A
|
||
|
brlo WAITSYNCEND ; no, look again
|
||
|
; Get exact sync with clock (remove jitter)
|
||
|
lds J, TCNT1L
|
||
|
cpi J, 0x5C
|
||
|
breq syncEnd0
|
||
|
cpi J, 0x5D
|
||
|
breq syncEnd1
|
||
|
cpi J, 0x5E
|
||
|
breq syncEnd2
|
||
|
cpi J, 0x5F
|
||
|
breq syncEnd3
|
||
|
cpi J, 0x60
|
||
|
breq syncEnd4
|
||
|
cpi J, 0x61
|
||
|
breq syncEnd5
|
||
|
cpi J, 0x62
|
||
|
breq HSYNCEND
|
||
|
nop
|
||
|
nop
|
||
|
nop
|
||
|
syncEnd0:
|
||
|
nop
|
||
|
nop
|
||
|
nop
|
||
|
syncEnd1:
|
||
|
nop
|
||
|
nop
|
||
|
nop
|
||
|
syncEnd2:
|
||
|
nop
|
||
|
nop
|
||
|
nop
|
||
|
syncEnd3:
|
||
|
nop
|
||
|
nop
|
||
|
nop
|
||
|
syncEnd4:
|
||
|
nop
|
||
|
nop
|
||
|
nop
|
||
|
syncEnd5:
|
||
|
nop
|
||
|
nop
|
||
|
nop
|
||
|
; Timer now always 0x72 at this point
|
||
|
HSYNCEND:
|
||
|
sbi portb, syncpin ; raise sync (approx 4.7uS hsync pulse)
|
||
|
cpi chrln, 0xFF ; are we on an active display line?
|
||
|
brne WAITVISIBLEPORTION ; yes, active display line
|
||
|
rjmp EOL ; no, blank line, we're done
|
||
|
|
||
|
WAITVISIBLEPORTION:
|
||
|
|
||
|
ldi J,0
|
||
|
leftBlank:
|
||
|
inc J
|
||
|
cpi J,42
|
||
|
brlo leftBlank
|
||
|
|
||
|
in J,PORTC ; read current port C
|
||
|
mov temp1s,J ; store in temp
|
||
|
andi J, 0xF7 ; Clear sh/ld bit
|
||
|
mov temp0s,J ; store in temp
|
||
|
|
||
|
; Check if 40 or 80 chars per line to be drawn
|
||
|
sbrs currLineAtt,ATT_80_CHAR_PER_LINE
|
||
|
rjmp DRAWLINE40
|
||
|
rjmp DRAWLINE80
|
||
|
|
||
|
DRAWLINE80:
|
||
|
;
|
||
|
; each line consists of 80 macro calls, each 8 clocks long. Here is the macro:
|
||
|
.macro DispChr
|
||
|
;
|
||
|
; gets the font byte of the current character and outputs it to the shift register
|
||
|
;
|
||
|
; 8 clocks
|
||
|
|
||
|
ld ZL, X+ ; 2 move curr chr in ZL
|
||
|
lpm J, Z ; 3 get font byte for current chr on curr line
|
||
|
out PORTD, J ; 1
|
||
|
out PORTC, temp0s ; 1 lower load pin
|
||
|
out PORTC, temp1s ; 1 raise load pin
|
||
|
.endmacro
|
||
|
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
|
||
|
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
DispChr ; display 1 chr
|
||
|
jmp EndOfChars
|
||
|
|
||
|
DRAWLINE40:
|
||
|
nop ; Exact sync with 80 char lines
|
||
|
;
|
||
|
; each line consists of 40 macro calls, each 16 clocks long. Here is the macro:
|
||
|
.macro DispChrWide
|
||
|
;
|
||
|
; gets the two font bytes of the current character and output them to the shift register
|
||
|
;
|
||
|
; 16 clocks
|
||
|
|
||
|
ld ZL, X+ ; 2 move curr chr in ZL
|
||
|
lpm J, Z ; 3 get left half font byte for current chr on curr line
|
||
|
out PORTD, J ; 1
|
||
|
out PORTC, temp0s ; 1 lower load pin
|
||
|
out PORTC, temp1s ; 1 raise load pin
|
||
|
|
||
|
ori ZH, 0x08 ; 1 get next font page
|
||
|
lpm J, Z ; 3 get right half font byte for current chr on curr line
|
||
|
andi ZH, 0xF7 ; 1 get back to first font page
|
||
|
out PORTD, J ; 1
|
||
|
out PORTC, temp0s ; 1 lower load pin
|
||
|
out PORTC, temp1s ; 1 raise load pin
|
||
|
|
||
|
.endmacro
|
||
|
|
||
|
DispChrWide ; display 1 wide chr
|
||
|
DispChrWide ; display 1 wide chr
|
||
|
DispChrWide ; display 1 wide chr
|
||
|
DispChrWide ; display 1 wide chr
|
||
|
DispChrWide ; display 1 wide chr
|
||
|
DispChrWide ; display 1 wide chr
|
||
|
DispChrWide ; display 1 wide chr
|
||
|
DispChrWide ; display 1 wide chr
|
||
|
DispChrWide ; display 1 wide chr
|
||
|
DispChrWide ; display 1 wide chr
|
||
|
DispChrWide ; display 1 wide chr
|
||
|
DispChrWide ; display 1 wide chr
|
||
|
DispChrWide ; display 1 wide chr
|
||
|
DispChrWide ; display 1 wide chr
|
||
|
DispChrWide ; display 1 wide chr
|
||
|
DispChrWide ; display 1 wide chr
|
||
|
DispChrWide ; display 1 wide chr
|
||
|
DispChrWide ; display 1 wide chr
|
||
|
DispChrWide ; display 1 wide chr
|
||
|
DispChrWide ; display 1 wide chr
|
||
|
DispChrWide ; display 1 wide chr
|
||
|
DispChrWide ; display 1 wide chr
|
||
|
DispChrWide ; display 1 wide chr
|
||
|
DispChrWide ; display 1 wide chr
|
||
|
DispChrWide ; display 1 wide chr
|
||
|
DispChrWide ; display 1 wide chr
|
||
|
DispChrWide ; display 1 wide chr
|
||
|
DispChrWide ; display 1 wide chr
|
||
|
DispChrWide ; display 1 wide chr
|
||
|
DispChrWide ; display 1 wide chr
|
||
|
DispChrWide ; display 1 wide chr
|
||
|
DispChrWide ; display 1 wide chr
|
||
|
DispChrWide ; display 1 wide chr
|
||
|
DispChrWide ; display 1 wide chr
|
||
|
DispChrWide ; display 1 wide chr
|
||
|
DispChrWide ; display 1 wide chr
|
||
|
DispChrWide ; display 1 wide chr
|
||
|
DispChrWide ; display 1 wide chr
|
||
|
DispChrWide ; display 1 wide chr
|
||
|
DispChrWide ; display 1 wide chr
|
||
|
|
||
|
EndOfChars:
|
||
|
inc chrln ; inc line counter
|
||
|
|
||
|
EOL: ; end of line, we're done
|
||
|
inc vline ; inc vertical line counter
|
||
|
brne eol1
|
||
|
inc vlineh ;
|
||
|
|
||
|
eol1:
|
||
|
pop J
|
||
|
out SREG,J
|
||
|
pop J
|
||
|
pop ZH
|
||
|
pop ZL
|
||
|
pop accH
|
||
|
pop acc
|
||
|
|
||
|
reti ; all done, go back to main program
|
||
|
|