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:
|
main:
|
||||||
ldi r16, 0x30 ; port B, pin 4 and 5 as output
|
ldi r16, 0x30 ; port B, pin 4 and 5 as output
|
||||||
sts DDRB, r16
|
sts DDRB, r16
|
||||||
|
cbi IO(DDRD), 2 ; port D, pin 2 and 3 as input
|
||||||
; set interrupt vectors at address 0x0, not bootloader
|
cbi IO(DDRD), 3
|
||||||
; 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
|
; init variables
|
||||||
ldi r16, 0
|
ldi r16, 0
|
||||||
@ -35,85 +19,68 @@ main:
|
|||||||
ldi r16, 1
|
ldi r16, 1
|
||||||
sts line, r16
|
sts line, r16
|
||||||
|
|
||||||
|
cli ; global interrupt disable
|
||||||
|
|
||||||
call setup_c
|
call setup_c
|
||||||
|
|
||||||
sei ; global interrupt enable
|
wait_next_line:
|
||||||
|
in r16, IO(PIND)
|
||||||
1:
|
andi r16, 0x08
|
||||||
call loop_c
|
brne wait_next_line
|
||||||
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
|
; if (line >= VERTICAL_OFFSET), then enter
|
||||||
lds r30, line ; +12
|
lds r30, line ; +2, 2
|
||||||
lds r31, line + 1 ; +14
|
lds r31, line + 1 ; +2, 4
|
||||||
adiw z, 1 ; +16
|
adiw z, 1 ; +2, 6
|
||||||
sts line, r30 ; +18
|
sts line, r30 ; +2, 8
|
||||||
sts line + 1, r31 ; +20
|
sts line + 1, r31 ; +2, 10
|
||||||
cpi r31, 0 ; +21
|
cpi r31, 0 ; +1, 11
|
||||||
brne enter ; +22, +23
|
brne enter ; +2, 13
|
||||||
cpi r30, VERTICAL_OFFSET ; +23
|
cpi r30, VERTICAL_OFFSET ; TODO timing bad at 256 lines
|
||||||
brlo int_horizontal_sync_end ; +24
|
brsh enter
|
||||||
|
jmp horizontal_line_end
|
||||||
|
*/
|
||||||
|
|
||||||
enter:
|
enter:
|
||||||
; here, +23 or +24 cycles have passed since horizontal sync
|
; here, +13 cycles have passed since horizontal sync
|
||||||
; so, there are still ~168 cycles before first useful data
|
; so, there are still (192 - 13) = 179 cycles before first useful data
|
||||||
ldi r31, 0
|
ldi r31, 64 ; approx
|
||||||
sts TCNT0, r31
|
1:
|
||||||
ldi r31, HORIZONTAL_OFFSET ; set counter TOP
|
dec r31 ; 1
|
||||||
sts OCR0A, r31
|
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
|
; here we are at the beginning of the visible line
|
||||||
push r31
|
ldi r31, 16
|
||||||
in r31, IO(SREG)
|
1:
|
||||||
push r31
|
dec r31
|
||||||
push r30
|
brne 1b
|
||||||
push r29
|
|
||||||
|
|
||||||
; turn off interrupt
|
sbi IO(PORTB), 5
|
||||||
lds r31, TIMSK0
|
|
||||||
andi r31, 0xfd ; mask disable interrupt timer A
|
|
||||||
sts TIMSK0, r31
|
|
||||||
|
|
||||||
; draw things
|
sbi IO(PORTB), 4
|
||||||
ldi r30, lo8(line_buffer)
|
|
||||||
ldi r31, hi8(line_buffer)
|
|
||||||
|
|
||||||
.rept LINE_BUFFER_SIZE
|
|
||||||
ld r29, z+
|
|
||||||
out IO(PORTB), r29
|
|
||||||
nop
|
nop
|
||||||
.endr
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
cbi IO(PORTB), 4
|
||||||
|
|
||||||
pop r29
|
# ; draw things
|
||||||
pop r30
|
# ldi r30, lo8(line_buffer)
|
||||||
pop r31
|
# ldi r31, hi8(line_buffer)
|
||||||
out IO(SREG), r31
|
|
||||||
pop r31
|
|
||||||
reti
|
|
||||||
|
|
||||||
|
#.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
|
.global int_vertical_sync
|
||||||
int_vertical_sync:
|
int_vertical_sync:
|
||||||
push r31
|
push r31
|
||||||
@ -139,4 +106,4 @@ int_vertical_sync_end:
|
|||||||
pop r31
|
pop r31
|
||||||
reti
|
reti
|
||||||
|
|
||||||
|
*/
|
||||||
|
17
main.c
17
main.c
@ -7,23 +7,13 @@ volatile uint16_t frame;
|
|||||||
volatile uint16_t line;
|
volatile uint16_t line;
|
||||||
volatile char line_buffer[LINE_BUFFER_SIZE];
|
volatile char line_buffer[LINE_BUFFER_SIZE];
|
||||||
|
|
||||||
ISR(INT0_vect, ISR_NAKED) {
|
void setup_c() {
|
||||||
asm("jmp int_vertical_sync");
|
for (int i = 0; i < LINE_BUFFER_SIZE; ++i) {
|
||||||
|
line_buffer[i] = (i > 50 && i < 100) ? '1' : 'A';
|
||||||
}
|
}
|
||||||
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 % 2) ? 0x0 : 0xff;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
void loop_c() {
|
void loop_c() {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
@ -53,3 +43,4 @@ void loop_c() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user