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:
giomba 2021-08-08 22:29:16 +02:00
parent 53da6b7171
commit d91201dcfd
2 changed files with 59 additions and 101 deletions

139
main.S
View File

@ -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
View File

@ -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() {
} }
} }
} }
*/