videochargen/main.S

160 lines
2.9 KiB
ArmAsm
Raw Normal View History

#include <avr/io.h>
#include "macro.h"
2021-06-27 19:57:02 +00:00
#include "const.h"
.data
2021-06-27 19:57:02 +00:00
frame:
2021-06-28 19:38:39 +00:00
.word 0
line:
2021-06-28 19:38:39 +00:00
.word 0
.text
2021-06-27 19:57:02 +00:00
.global main
main:
ldi r16, 0x30 ; port B, pin 4 and 5 as output
sts DDRB, r16
2021-06-27 19:57:02 +00:00
; set interrupt vectors at address 0x0, not bootloader
; timing is important, see atmel datasheet
ldi r16, (1 << IVCE)
ldi r17, 0
out IO(MCUCR), r16
out IO(MCUCR), r17
ldi r16, 0xa ; external interrupt 0 and 1, falling edge
sts EICRA, r16
ldi r16, 0x3 ; external interrupt 0 and 1, mask enable
sts EIMSK, r16
ldi r16, 0x02 ; don't connect output pins to timer, CTC[1:0] mode
sts TCCR0A, r16
ldi r16, 0x03 ; CTC[2] mode, prescaler /64
sts TCCR0B, r16
; init variables
ldi r16, 0
sts frame, r16
sts frame + 1, r16
sts line + 1, r16
ldi r16, 1
sts line, r16
2021-06-27 19:57:02 +00:00
sei ; global interrupt enable
1:
2021-06-27 19:57:02 +00:00
rjmp 1b
.global int_horizontal_sync
int_horizontal_sync: ; +3
push r31 ; +5
in r31, IO(SREG) ; +6, status register
push r31 ; +8
push r30 ; +10
2021-06-28 19:38:39 +00:00
; if (line >= VERTICAL_OFFSET), then enter
lds r30, line ; +12
lds r31, line + 1 ; +14
adiw z, 1 ; +16
sts line, r30 ; +18
sts line + 1, r31 ; +20
cpi r31, 0 ; +21
brne enter ; +22, +23
cpi r30, VERTICAL_OFFSET ; +23
brlo int_horizontal_sync_end ; +24
2021-06-27 19:57:02 +00:00
enter:
; here, +23 or +24 cycles have passed since horizontal sync
; so, there are still ~168 cycles before first useful data
ldi r31, 0
sts TCNT0, r31
ldi r31, HORIZONTAL_OFFSET ; set counter TOP
sts OCR0A, r31
ldi r31, 0x7 ; clear any pending interrupt
sts TIFR0, r31
lds r31, TIMSK0
ori r31, 0x02 ; mask enable interrupt timer A
sts TIMSK0, r31
int_horizontal_sync_end:
pop r30
pop r31
out IO(SREG), r31
pop r31
reti
.global int_timer_0
int_timer_0:
; here we are at the beginning of the visible line
push r31
in r31, IO(SREG)
push r31
; turn off interrupt
lds r31, TIMSK0
andi r31, 0xfd ; mask disable interrupt timer A
sts TIMSK0, r31
; draw things
2021-06-27 19:57:02 +00:00
lds r31, frame
andi r31, 0x70
cpi r31, 0
2021-06-27 19:57:02 +00:00
breq 2f
1:
dec r31
2021-06-27 19:57:02 +00:00
brne 1b
2:
sbi IO(PORTB), 4
nop
cbi IO(PORTB), 4
nop
sbi IO(PORTB), 4
nop
cbi IO(PORTB), 4
nop
sbi IO(PORTB), 4
nop
cbi IO(PORTB), 4
nop
sbi IO(PORTB), 4
nop
cbi IO(PORTB), 4
2021-06-27 19:57:02 +00:00
pop r31
out IO(SREG), r31
pop r31
reti
.global int_vertical_sync
int_vertical_sync:
push r31
2021-06-27 19:57:02 +00:00
in r31, IO(SREG)
push r31
2021-06-28 19:38:39 +00:00
push r30
2021-06-27 19:57:02 +00:00
2021-06-28 19:38:39 +00:00
lds r31, frame + 1
lds r30, frame
adiw z, 1
sts frame + 1, r31
sts frame, r30
2021-06-27 19:57:02 +00:00
2021-06-28 19:38:39 +00:00
ldi r30, 1
ldi r31, 0
sts line, r30
sts line + 1, r31
2021-06-27 19:57:02 +00:00
int_vertical_sync_end:
2021-06-28 19:38:39 +00:00
pop r30
2021-06-27 19:57:02 +00:00
pop r31
out IO(SREG), r31
pop r31
reti