pato-z80-home-computer/pat80-io-devices/composite-pal-adapter/software/avr-assembly/main.asm

172 lines
4.6 KiB
NASM
Raw Normal View History

; VIDEO COMPOSITE PAL IO DEVICE
2021-01-08 16:12:46 +01:00
;
2021-01-10 07:22:55 +01:00
; INTERFACING WITH PAT80:
; Use PortB as data port. Before writing anything, issue a read (pin RW HIGH) and check the busy pin on the data port.
; If the busy pin is high, retry reading until goes low. When the busy pin goes low, we have... TODO
2021-01-10 07:22:55 +01:00
;
; ELECTRONICALLY:
; The data port PB0 is tied to ground with a 1KOhm resistance. When the MC is busy drawing the screen, the data port is in
2021-01-10 07:22:55 +01:00
; high impedance state, so that avoids causing bus contention, but when read returns a 0bXXXXXXX0 byte. When the MC starts vsync,
; begins checking the port for data... TODO
;
2021-01-08 16:12:46 +01:00
; PINS:
; Video:
; Video pin: PA0 (pin 1) (but all PORTA is used)
; Sync pin: PC0 (pin 22)
; Communication:
; Data port is PORTB [INPUT]
; CLK (clock) signal is on PORTD0 [INPUT]
; RS (register select) on PORTD1 [INPUT]
; BUSY signal is on PORTD2 [OUTPUT]
; Debug:
; Debug hsync single pulse on pin: PC1 (pin 23) (may be disabled)
;
2021-01-19 08:36:01 +01:00
.include "m1284def.inc" ; Atmega 1280 device definition
2021-01-26 20:52:53 +01:00
; *** reserved registers ***
; Cursor Position
2021-02-16 08:57:15 +01:00
; POS_COLUMN (0-46) represents the character/chunk column
; POS_ROWP (0-255) represent the chunk row. The caracter row is POS_ROWP/FONT_HEIGHT
; POS_FINE represents fine position (bit inside coarse-position-pointed chunk) in graphic mode.
.def POS_COLUMN = r21
.def POS_ROWP = r20
.def POS_FINE = r24
2021-01-26 20:52:53 +01:00
; Internal registers
2021-01-17 10:58:04 +01:00
.def A = r0 ; accumulator
.def STATUS = r25 ; signal status (see STATUS TABLE)
;POS_COARSE = Y ; coarse position (aligned to character column)
2021-01-26 20:52:53 +01:00
;DRAWING_BYTE = X ; current position in framebuffer
.def LINE_COUNTER = r23
.def VG_HIGH_ACCUM = r22 ; an accumulator in high registers to be used only by video_generator in interrupt
.def HIGH_ACCUM = r16 ; an accumulator in high registers to be used outside of interrupts
; define constant
.equ VIDEO_PORT_OUT = PORTA ; Used all PORTA, but connected only PA0
.equ SYNC_PIN = PC0 ; Sync pin (pin 22)
.equ DEBUG_PIN = PC1 ; DEBUG: Single vertical sync pulse to trigger oscilloscope (pin 23)
.equ DATA_PORT_IN = PINB
.equ CLK_PIN = PD0
.equ RS_PIN = PD1
.equ BUSY_PIN = PD2
2021-01-06 00:19:15 +01:00
; memory
2021-01-26 20:52:53 +01:00
.equ FRAMEBUFFER = 0x0100
2021-02-20 17:02:13 +01:00
.equ FRAMEBUFFER_END = 0x2F00
.equ SCREEN_HEIGHT = 248
; start vector
.org 0x0000
2021-01-16 19:54:32 +01:00
rjmp main ; reset vector: jump to main label
.org 0x001E
2021-01-19 08:36:01 +01:00
rjmp on_tim1_ovf ; interrupt for timer 1 overflow (used by video generation)
2021-01-16 19:54:32 +01:00
.org 0x40
; main program
main:
2021-02-20 17:02:13 +01:00
; **** I/O SETUP ****
; pins setup
2021-01-06 00:19:15 +01:00
sbi DDRC, SYNC_PIN ; set pin as output
sbi DDRC, DEBUG_PIN ; set pin as output
sbi DDRC, BUSY_PIN ; set pin as output
cbi DDRD, CLK_PIN ; set pin as input
ldi HIGH_ACCUM, 0xFF
out DDRA, HIGH_ACCUM ; set port as output (contains video pin)
ldi HIGH_ACCUM, 0x00
out DDRB, HIGH_ACCUM ; set port as input (used as data bus)
2021-01-24 12:13:17 +01:00
2021-02-20 17:02:13 +01:00
; **** MEMORY SETUP ****
; clear ram
;*** Load data into ram ***
; Set X to 0x0100
2021-02-20 17:02:13 +01:00
; ldi XH, high(FRAMEBUFFER)
; ldi XL, low(FRAMEBUFFER)
; load_mem_loop:
; clr r17
; st X+, r17
; ; if reached the last framebuffer byte, exit cycle
; cpi XH, 0b00111110
; brne load_mem_loop ; if not 0, repeat h_picture_loop
; cpi XL, 0b11000000
; brne load_mem_loop ; if not 0, repeat h_picture_loop
2021-02-15 21:23:12 +01:00
2021-01-07 13:32:01 +01:00
2021-02-20 17:02:13 +01:00
; **** TIMERS AND DRAWING IMAGE ROUTINES SETUP ****
; Timer setup (use 16-bit counter TC1)
; The Power Reduction TC1 and TC3 bits in the Power Reduction Registers (PRR0.PRTIM1 and
; PRR1.PRTIM3) must be written to zero to enable the TC1 and TC3 module.
ldi HIGH_ACCUM, 0b00000000
sts PRR0, HIGH_ACCUM
2021-01-16 19:54:32 +01:00
; Set timer prescaler to 1:1
LDI HIGH_ACCUM,0b00000001
sts TCCR1B,HIGH_ACCUM
2021-01-16 19:54:32 +01:00
; Enambe timer1 overflow interrupt
LDI HIGH_ACCUM,0b00000001
STS TIMSK1,HIGH_ACCUM
2021-01-16 19:54:32 +01:00
; Enable interrupts globally
SEI
; Timer setup completed.
2021-02-20 17:02:13 +01:00
; **** MAIN ROUTINE ****
; Wait for data (it never exits)
; jmp comm_init
2021-02-15 21:23:12 +01:00
2021-02-20 17:02:13 +01:00
; draw example image
call draw_cat
2021-02-15 21:23:12 +01:00
; test draw character routine
2021-02-16 08:57:15 +01:00
call draw_carriage_return
call draw_carriage_return
call draw_carriage_return
2021-02-15 21:23:12 +01:00
call cursor_pos_home
2021-02-15 22:54:54 +01:00
ldi r18, 0x41
2021-02-15 21:23:12 +01:00
dctest:
draw_chars:
mov HIGH_ACCUM, r18
call draw_char
inc r18
2021-02-15 22:54:54 +01:00
cpi r18, 0x5B
2021-02-15 21:23:12 +01:00
brne dc_continue
2021-02-15 22:54:54 +01:00
ldi r18, 0x41
2021-02-16 08:57:15 +01:00
call draw_carriage_return
2021-02-15 21:23:12 +01:00
dc_continue:
; wait
ser r19
dc_wait_loop_1:
ser r20
dc_wait_loop_2:
dec r20
brne dc_wait_loop_2
dec r19
brne dc_wait_loop_1
brne draw_chars
jmp dctest
2021-02-20 17:02:13 +01:00
2021-02-15 21:23:12 +01:00
forever:
jmp forever
.include "video_generator.asm" ; Asyncronous timer-interrupt-based video generation
.include "character_generator.asm" ; Character generator
2021-02-20 17:02:13 +01:00
;.include "communication.asm" ; Communication with Pat80
.include "font.asm" ; Font face
2021-02-20 17:02:13 +01:00
.include "example_data/cat.asm" ; Cat image