do using polling
actually this does not work, because polling requires: in andi brne which takes 4 clock cycles, that, on average, means a 2 clock offset, while interrupts occur during a rjmp, which takes 2 clocks, which means, on average, only 1 clock cycle of offset I am not interested in higher or lower overhead: I am just interested in minimizing its variance. Being late of a few clock cycles, is not a problem: it just means that the picture will be slightly shifted toward the right border; but, starting the picture 1 or 2 clock cycles before (on one line), and 1 or 2 clock cycles after, on another line, means that it just wiggles sligthly left and right
This commit is contained in:
parent
53da6b7171
commit
d91201dcfd
139
main.S
139
main.S
@ -8,24 +8,8 @@
|
||||
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
|
||||
cbi IO(DDRD), 2 ; port D, pin 2 and 3 as input
|
||||
cbi IO(DDRD), 3
|
||||
|
||||
; init variables
|
||||
ldi r16, 0
|
||||
@ -35,85 +19,68 @@ main:
|
||||
ldi r16, 1
|
||||
sts line, r16
|
||||
|
||||
cli ; global interrupt disable
|
||||
|
||||
call setup_c
|
||||
|
||||
sei ; global interrupt enable
|
||||
|
||||
1:
|
||||
call loop_c
|
||||
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
|
||||
|
||||
wait_next_line:
|
||||
in r16, IO(PIND)
|
||||
andi r16, 0x08
|
||||
brne wait_next_line
|
||||
/*
|
||||
; 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
|
||||
lds r30, line ; +2, 2
|
||||
lds r31, line + 1 ; +2, 4
|
||||
adiw z, 1 ; +2, 6
|
||||
sts line, r30 ; +2, 8
|
||||
sts line + 1, r31 ; +2, 10
|
||||
cpi r31, 0 ; +1, 11
|
||||
brne enter ; +2, 13
|
||||
cpi r30, VERTICAL_OFFSET ; TODO timing bad at 256 lines
|
||||
brsh enter
|
||||
jmp horizontal_line_end
|
||||
*/
|
||||
|
||||
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
|
||||
; here, +13 cycles have passed since horizontal sync
|
||||
; so, there are still (192 - 13) = 179 cycles before first useful data
|
||||
ldi r31, 64 ; approx
|
||||
1:
|
||||
dec r31 ; 1
|
||||
brne 1b ; 2
|
||||
|
||||
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
|
||||
ldi r31, 16
|
||||
1:
|
||||
dec r31
|
||||
brne 1b
|
||||
|
||||
; turn off interrupt
|
||||
lds r31, TIMSK0
|
||||
andi r31, 0xfd ; mask disable interrupt timer A
|
||||
sts TIMSK0, r31
|
||||
sbi IO(PORTB), 5
|
||||
|
||||
; draw things
|
||||
ldi r30, lo8(line_buffer)
|
||||
ldi r31, hi8(line_buffer)
|
||||
|
||||
.rept LINE_BUFFER_SIZE
|
||||
ld r29, z+
|
||||
out IO(PORTB), r29
|
||||
sbi IO(PORTB), 4
|
||||
nop
|
||||
.endr
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
cbi IO(PORTB), 4
|
||||
|
||||
pop r29
|
||||
pop r30
|
||||
pop r31
|
||||
out IO(SREG), r31
|
||||
pop r31
|
||||
reti
|
||||
# ; draw things
|
||||
# ldi r30, lo8(line_buffer)
|
||||
# ldi r31, hi8(line_buffer)
|
||||
|
||||
#.rept LINE_BUFFER_SIZE
|
||||
# ld r29, z+
|
||||
# out IO(PORTB), r29
|
||||
# nop
|
||||
#.endr
|
||||
|
||||
cbi IO(PORTB), 5
|
||||
|
||||
horizontal_line_end:
|
||||
jmp wait_next_line
|
||||
|
||||
|
||||
/*
|
||||
.global int_vertical_sync
|
||||
int_vertical_sync:
|
||||
push r31
|
||||
@ -139,4 +106,4 @@ int_vertical_sync_end:
|
||||
pop r31
|
||||
reti
|
||||
|
||||
|
||||
*/
|
||||
|
21
main.c
21
main.c
@ -7,23 +7,13 @@ volatile uint16_t frame;
|
||||
volatile uint16_t line;
|
||||
volatile char line_buffer[LINE_BUFFER_SIZE];
|
||||
|
||||
ISR(INT0_vect, ISR_NAKED) {
|
||||
asm("jmp int_vertical_sync");
|
||||
}
|
||||
ISR(INT1_vect, ISR_NAKED) {
|
||||
asm("jmp int_horizontal_sync");
|
||||
}
|
||||
ISR(TIMER0_COMPA_vect, ISR_NAKED) {
|
||||
asm("jmp int_timer_0");
|
||||
void setup_c() {
|
||||
for (int i = 0; i < LINE_BUFFER_SIZE; ++i) {
|
||||
line_buffer[i] = (i > 50 && i < 100) ? '1' : 'A';
|
||||
}
|
||||
}
|
||||
|
||||
void setup_c() {
|
||||
/*
|
||||
for (int i = 0; i < LINE_BUFFER_SIZE; ++i) {
|
||||
line_buffer[i] = (i % 2) ? 0x0 : 0xff;
|
||||
}
|
||||
*/
|
||||
}
|
||||
/*
|
||||
|
||||
void loop_c() {
|
||||
for (;;) {
|
||||
@ -53,3 +43,4 @@ void loop_c() {
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user