; main.S ; ; This file is part of OSDY VideoCharGen ; a do-it-yourself on-screen-display image generator ; for superimposition of analog PAL signals ; #include #include "macro.h" #include "const.h" .data show_image: .byte 0x00 button_next_image: .byte 0x0 current_jump_table: .word 0x0 .text .global main_asm main_asm: ; init variables ldi r16, 0 sts show_image, r16 ; r0 always holds 0 clr r0 ; global interrupt enable sei ; endless loop 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 breq enter ; +23 jmp int_horizontal_sync_end enter: ; here, +23 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 push r30 push r29 ; turn off interrupt lds r31, TIMSK0 andi r31, 0xfd ; mask disable interrupt timer A sts TIMSK0, r31 lds r31, show_image cpi r31, 0x1 brne jump_table_return_address lds zl, current_jump_table lds zh, current_jump_table + 1 ; ldi zl, pm_lo8(line_jump_table_0) ; ldi zh, pm_hi8(line_jump_table_0) clr r0 lds r29, line add zl, r29 adc zh, r0 add zl, r29 adc zh, r0 ijmp .global jump_table_return_address jump_table_return_address: pop r29 pop r30 pop r31 out IO(SREG), r31 pop r31 reti .global int_vertical_sync int_vertical_sync: push r31 in r31, IO(SREG) push zl push zh push yl push yh 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 ; check button in r31, IO(PINB) andi r31, 0x08 breq check_if_released ldi r31, 1 sts button_next_image, r31 jmp int_vertical_sync_end check_if_released: lds r31, button_next_image cpi r31, 1 brne int_vertical_sync_end ; here button is released ; read transition mode in r31, IO(PINB) andi r31, 0x04 ; if transition mode == 1, then always show image ; Nice to have: maybe this can be written better. breq 1f ldi r31, 0 sts show_image, r31 1: lds r31, show_image cpi r31, 1 breq 1f ldi r31, 1 sts show_image, r31 rjmp 2f 1: ldi r31, 0 sts show_image, r31 rjmp end_button_release 2: ; show image ldi zl, pm_lo8(line_jump_table_0) ldi zh, pm_hi8(line_jump_table_0) clr yl lds yh, image inc yh sts image, yh add zh, yh add zh, yh sts current_jump_table, zl sts current_jump_table + 1, zh ldi r31, 0x01 sts show_image, r31 end_button_release: clr yl sts button_next_image, yl int_vertical_sync_end: pop yh pop yl pop zh pop zl out IO(SREG), r31 pop r31 reti