#include #include "macro.h" #include "const.h" .data frame: .word 0 line: .word 0 .text .global main main: ldi r16, 0x30 ; port B, pin 4 and 5 as output sts DDRB, r16 ; 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, 0x01 ; CTC[2] mode, no prescaler 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 sei ; global interrupt enable 1: 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 ; 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 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 lds r31, frame andi r31, 0x70 cpi r31, 0 breq 2f 1: dec r31 brne 1b 2: sbi IO(PORTB), 4 nop nop nop nop nop nop nop nop nop nop cbi IO(PORTB), 4 pop r31 out IO(SREG), r31 pop r31 reti .global int_vertical_sync int_vertical_sync: push r31 in r31, IO(SREG) push r31 push r30 lds r31, frame + 1 lds r30, frame adiw z, 1 sts frame + 1, r31 sts frame, r30 ldi r30, 1 ldi r31, 0 sts line, r30 sts line + 1, r31 int_vertical_sync_end: pop r30 pop r31 out IO(SREG), r31 pop r31 reti