Compare commits

...

5 Commits

Author SHA1 Message Date
05f231d8ba Add documentation. 2022-11-04 21:44:20 +01:00
a5b5fb17c6 Code finalization for bouncing sprite. 2022-11-04 21:43:50 +01:00
b76ec5e498 Use 16bit TIMER1 to sweep more horizontally. 2022-11-04 21:43:45 +01:00
51fdaab28d Add bouncing sprite. First experiment. 2022-11-04 21:43:24 +01:00
aed259522b Fix comment. 2022-11-01 16:28:19 +01:00
5 changed files with 203 additions and 80 deletions

23
const.h
View File

@ -1,8 +1,21 @@
#pragma once #pragma once
#define VERTICAL_OFFSET 30 #define FRAME_SYSCLOCK_WIDTH 1024 // [sysclock]
#define HORIZONTAL_OFFSET 192 #define FRAME_LINE_HEIGHT 256 // [line]
#define LINE_BUFFER_SIZE 160
#define BLACK 0x00 #define BACK_PORCH_SYSCLOCK_OFFSET 80 // [sysclock]
#define WHITE 0xff #define FRONT_PORCH_SYSCLOCK_OFFSET 40 // [sysclock]
#define SPRITE_PIXEL_WIDTH 80 // [sysclock]
#define SPRITE_LINE_HEIGHT 64 // [line]
#define SYSCLOCK_PER_PIXEL 4
#define SPRITE_SYSCLOCK_WIDTH (SPRITE_PIXEL_WIDTH * SYSCLOCK_PER_PIXEL)
// Time spent from the horizontal sync pulse,
// to the first displayed dot.
// This is given as the sum of:
// + HSYNC_INT_TUNE
// + HSYNC_TIMER_TUNE
// + sysclock duration of "C" interrupt part
#define HSYNC_SYSCLOCK_TUNE 70 // [sysclock] (approx)

122
main.S
View File

@ -36,80 +36,82 @@ main_asm:
1: 1:
rjmp 1b rjmp 1b
.global int_horizontal_sync .global int_horizontal_sync_s
int_horizontal_sync: ; +3 int_horizontal_sync_s:
push r31 ; +5 push r31 ; +2
in r31, IO(SREG) ; +6, status register push r30 ; +2
push r31 ; +8
push r30 ; +10
; if (line >= VERTICAL_OFFSET), then enter ; load timer to trigger isr at the beginning of the visible scanline
lds r30, line ; +12 ; reset counter to 0
lds r31, line + 1 ; +14 ldi r31, 0 ; +1
adiw z, 1 ; +16 sts TCNT1H, r31 ; +2
sts line, r30 ; +18 sts TCNT1L, r31 ; +2
sts line + 1, r31 ; +20
cpi r31, 0 ; +21
breq enter ; +23
jmp int_horizontal_sync_end
enter: ; set counter TOP (MSB first!)
; here, +23 cycles have passed since horizontal sync lds r31, hpos + 1 ; +2
; so, there are still ~168 cycles before first useful data lds r30, hpos ; +2
ldi r31, 0 sts OCR1AH, r31 ; +2
sts TCNT0, r31 sts OCR1AL, r30 ; +2
ldi r31, HORIZONTAL_OFFSET ; set counter TOP
sts OCR0A, r31
ldi r31, 0x7 ; clear any pending interrupt ; clear any pending interrupt
sts TIFR0, r31 ldi r31, 0x7 ; +1
sts TIFR1, r31 ; +2
lds r31, TIMSK0 ; enable interrupt timer A
ori r31, 0x02 ; mask enable interrupt timer A lds r31, TIMSK1 ; +2
sts TIMSK0, r31 ori r31, 0x02 ; +1
sts TIMSK1, r31 ; +2
; total: 25
; HSYNC_INT_TUNE = 25
; this adds up for HSYNC_SYSCLOCK_TUNE
int_horizontal_sync_end:
pop r30 pop r30
pop r31 pop r31
out IO(SREG), r31 ret
pop r31
reti
.global int_timer_0 .global int_timer_1
int_timer_0: int_timer_1:
; here we are at the beginning of the visible line ; here we are at the beginning of the visible line
push r31 ; jmp (from C) ; +3
in r31, IO(SREG) push r31 ; +2
push r31 in r31, IO(SREG) ; +1
push r30 push r31 ; +2
push r29 push r30 ; +2
push r29 ; +2
push r25 ; +2
; turn off interrupt ; turn off interrupt
lds r31, TIMSK0 lds r31, TIMSK1 ; +2
andi r31, 0xfd ; mask disable interrupt timer A andi r31, 0xfd ; mask disable interrupt timer A, +1
sts TIMSK0, r31 sts TIMSK1, r31 ; +2
lds r31, show_image lds r31, show_image ; +2
cpi r31, 0x1 cpi r31, 0x1 ; +1
brne jump_table_return_address brne jump_table_return_address ; +1 (not taken)
lds zl, current_jump_table lds zl, current_jump_table ; +2
lds zh, current_jump_table + 1 lds zh, current_jump_table + 1 ; +2
; ldi zl, pm_lo8(line_jump_table_0) clr r0 ; +1
; ldi zh, pm_hi8(line_jump_table_0) lds r29, line ; +2
lds r25, vpos ; +2
sub r29, r25 ; +1
clr r0 add zl, r29 ; +1
lds r29, line adc zh, r0 ; +1
add zl, r29 add zl, r29 ; +1
adc zh, r0 adc zh, r0 ; +1
add zl, r29
adc zh, r0
ijmp ijmp ; +2
; total: 39
; HSYNC_TIMER_TUNE = 39
; this adds up for HSYNC_SYSCLOCK_TUNE
.global jump_table_return_address .global jump_table_return_address
jump_table_return_address: jump_table_return_address:
pop r25
pop r29 pop r29
pop r30 pop r30
pop r31 pop r31
@ -117,8 +119,8 @@ jump_table_return_address:
pop r31 pop r31
reti reti
.global int_vertical_sync .global int_vertical_sync_s
int_vertical_sync: int_vertical_sync_s:
push r31 push r31
in r31, IO(SREG) in r31, IO(SREG)
push zl push zl
@ -126,12 +128,6 @@ int_vertical_sync:
push yl push yl
push yh push yh
lds r31, frame + 1
lds r30, frame
adiw z, 1
sts frame + 1, r31
sts frame, r30
ldi r30, 1 ldi r30, 1
ldi r31, 0 ldi r31, 0
sts line, r30 sts line, r30

57
main.c
View File

@ -18,17 +18,55 @@ volatile uint16_t frame = 0;
volatile uint16_t line = 0xfe; volatile uint16_t line = 0xfe;
volatile uint8_t image = 0xff; volatile uint8_t image = 0xff;
ISR(INT0_vect, ISR_NAKED) { // horizontal and vertical position
// (and current increments)
// of bouncing sprite
volatile uint8_t vpos = 0;
volatile uint16_t hpos = 0;
volatile int8_t vinc = +1;
volatile int8_t hinc = +1;
// vertical sync interrupt // vertical sync interrupt
asm("jmp int_vertical_sync"); void int_vertical_sync_s(void);
ISR(INT0_vect) {
// count frames
frame += 1;
// move sprite
vpos += vinc;
hpos += hinc;
// invert bouncing direction
if (vpos == 0)
vinc = +1;
if (vpos == FRAME_LINE_HEIGHT - SPRITE_LINE_HEIGHT)
vinc = -1;
if (hpos == BACK_PORCH_SYSCLOCK_OFFSET)
hinc = +1;
if (hpos == FRAME_SYSCLOCK_WIDTH - SPRITE_SYSCLOCK_WIDTH -
FRONT_PORCH_SYSCLOCK_OFFSET - HSYNC_SYSCLOCK_TUNE)
hinc = -1;
int_vertical_sync_s();
} }
ISR(INT1_vect, ISR_NAKED) {
// horizontal sync interrupt // horizontal sync interrupt
asm("jmp int_horizontal_sync"); void int_horizontal_sync_s(void);
ISR(INT1_vect) {
// count lines
line += 1;
// we are past the last line of the sprite
if (line >= vpos + SPRITE_LINE_HEIGHT)
return;
if (line >= vpos)
int_horizontal_sync_s();
} }
ISR(TIMER0_COMPA_vect, ISR_NAKED) {
// back porch timer interrupt ISR(TIMER1_COMPA_vect, ISR_NAKED) {
asm("jmp int_timer_0"); // end-of back porch timer interrupt
asm("jmp int_timer_1");
} }
// external assembly main loop // external assembly main loop
@ -46,9 +84,8 @@ int main() {
EICRA = 0x0a; // external interrupt 0 and 1, falling edge EICRA = 0x0a; // external interrupt 0 and 1, falling edge
EIMSK = 0x03; // external interrupt 0 and 1, mask enable EIMSK = 0x03; // external interrupt 0 and 1, mask enable
TCCR0A = 0x02; // don't connect output pins to timer, CTC[1:0] mode TCCR1A = 0x00; // don't connect output pins to timer, CTC[1:0] mode
TCCR1B = 0x09; // CTC[3:2] mode, no prescaler
TCCR0B = 0x01; // CTC[2] mode, no prescaler
main_asm(); main_asm();
} }

77
samples/bouncing-logo.pbm Normal file
View File

@ -0,0 +1,77 @@
P1
# Created by GIMP version 2.10.32 PNM plug-in
80 64
0000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000111001110111011100011001110111
0100111010100010011000000000000000000000000000000010010100001001001010
0101000100010100001011001010010000000000000000000000000000001001010000
1001001010010100010001010000101010101001000000000000000000000000000000
1110011000100111001001011001100101000010100110111100000000000000000000
0000000000100101000010010010100101000100010100001010001010010000000000
0000000000000000000010010100001001001010010100010001010000101000101001
0000000000000000000000000000001001010000100100101001010001000101000010
1000101001000000000000000000000000000000100101110010010010011001000100
0100111010100010100101000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000
0000011001000011001110011100011000110011100011001000100111000101110000
0000000000000010000100010000100101001010010100001001010010110110100000
0100100000000000000000001000010001000010010100101001010000100101001010
1010100000010010000000000000000000101101000101101110011100100101011011
1001111010101001100001001000000000000000000010010100010010100001001010
0101001010010100101000100001000100100000000000000000001001010001001010
0001001010010100101001010010100010000100010010000000000000000000100101
0001001010000100101001010010100101001010001000010001001000000000000000
0000011001110011001000010010011000110010010100101000101110010100100000
0000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000100000000000000000000
0000000000000000000000000000000000000000000000000000000000001000000000
0000000000000000000000000000000000000000000000000000000000000000000000
0100000000000000000000000000000000000000000000000000000000000000000000
0000000000001000000000000000000000000000000000000000000000000000000000
0000000000000000000000010000000000000000000000000000000000000000000000
0000000000000000000000000000000000100000000000000000000000000000000000
0000000000000000000000000000000000000000000001000000111000000000000000
0000000000000000000000000000000000000000000000000000000010001110000000
0010000000000000000000000000000000000000000000000000000000000000000111
1000000000010000000000000000000000000000000000000000000000000000000000
0000000110000000000010000000000000000000000000000000000000000000000000
0000000000000000010100000000010000000000000000000000000000000000000000
0000000000000000000000000011001000000010000000000000000000000000000000
0000000000000000000000000000000000001000010000010000000000000000000000
0000000000000000000000000000000000000000000001100000100010000000000000
0000000000000000000000000000000000000000000000000000000100000001010000
0000000000000000000000000000000000000000000000000000000000000000010000
0000100000000000000000000000000000000000000000000000000000000000000000
0000010000000000000000001000000000000000000000000000000000000000000000
0000000000000001000000000000000000100000000000000000000000000000000000
0000000000000000000000000110000000000000000110000000000000000000000000
0000000000000000000000000000000000001000000000000000010000000000000000
0000000000000000000000000000000000000000000000110000000000000011000000
0000000000000000000000000000000000000000000000000000000001000000000000
0010000000000000000000000000000000000000000000000000000000000000000110
0000000000011000000000000000000000000000000000000000000000000000000000
0000000011100000000111000000000000000000000000000000000000000000000000
0000000000000000000011100001110000000000000000000000000000000000000000
0000000000000000000000000000000011111100000000000000000000000000000000
0000000000

BIN
samples/bouncing-logo.xcf Normal file

Binary file not shown.