реклама на сайте
подробности

 
 
> Выкроить 4 такта в коде прерывания надо
Dikoy
сообщение Apr 4 2018, 10:25
Сообщение #1


Местный
***

Группа: Участник
Сообщений: 253
Регистрация: 4-03-09
Из: Богота, Колумбия
Пользователь №: 45 676



Мучаю исходник http://www.vga-avr.narod.ru/main_rus.html "Простой VGA/Видео адаптер"
В проекте есть прерывание, в котором выполняется горизонтальная и вертикальная синхронизации, а также настройки указателей отрисовки.
Прерывание это нормировано по тактам, даже в ветвлениях if-ов нопами выровнено время выполнения. Я не знаю зачем автор так сделал, но если добавить хоть 1 nop в любое место, то вся синхронизация падает.

Проблема в том, что автор использует для выдачи сигналов синхронизации команды PORTD = 4; и PORTD = 0;
Что, естественно, приводит к невозможности использовать порт D для чего бы то ни было ещё.
Вторая проблема - PORTD = 4 на самом деле означает не только установку третьего бита, но и сброс второго. Третий бит это вертикальная синхронизация, второй - горизонтальная. И происходить эта операция должна одновременно.

Я пробовал менять на
PORTD |= (1<<3);
PORTD &= ~(1<<2);
Но всё тут же падает и из-за не одновременности вывода сигналов, и из-за возросшего времени выполнения.
Не помогает также и замена на ассемблерные cbi/sbi.

Единственный вариант, который мне видится, это

char temp;
temp = PORTD;
temp |= (1<<3);
temp &= ~(1<<2);
PORTD = temp;

Но даже
char temp;
temp = PORTD;
Уже приводит к искажению картинки из-за увеличившегося времени выполнения прерывания.

В общем, с этим надо что-то делать... Либо соптимизировать прерывание и выкроить такты, либо управлять портом как-то иначе, например, через указатель, но сомневаюсь что по числу тактов будет выигрыш.

Вот текст прерывания:
CODE
//Global definitions for VGA render
#define vga_field_line_count 525 //standart VGA quantity lines
#define vga_symbols_per_row 20 //symbols quantity per horizontal
#define vga_row_count 20 //symbols quantity per vertical
#define vga_symbol_height 24 //rendered symbol height
#define TIMER_LIMIT 0xC3 //set count, One VGA line 31.77us

//All VGA sincronize made here..
SIGNAL(SIG_OVERFLOW0) {

TCNT0 = TIMER_LIMIT; //reload counter value 0xC3 //set count, One VGA line 31.77us
//******Syncronization Handler********

//Count number of lines
if (++linecount == vga_field_line_count) {
linecount = 0;
//clear pointers for render display buffer
raw_render = 0;
y_line_render = 0;
}

// Вертикальный и горизонтальный синхроимпульсы должны быть одновременно, поэтому дёргать битами порта раздельно по cbi/sbi не получится.
// кроме того, тело прерывания крайне чувствительно ко времени исполнения, и добавление любой команды сбивает синхронизацию.

//Make Vsync length 2 VGA lines
if ((linecount == 10 )||(linecount == 11 )) {
//Make here vertical syncronization & HSYNC syncro level on
PORTD = 0; //vsync_on
} else {
//.. & HSYNC syncro level on
PORTD = 4;// vsync_off


}

video_enable_flg = true;


if (linecount < 45) {
video_enable_flg = false;
//Add to avoid flickering at top display
NOP; // 15 nops
NOP;
NOP;
NOP;
NOP;
NOP;
NOP;
NOP;
NOP;
NOP;
NOP;
NOP;
NOP;
NOP;
NOP;

} else {
//Forming current string for rendering
if (++y_line_render == vga_symbol_height) {
raw_render++;
y_line_render = 0;
} else {
NOP; // 8 nops
NOP;
NOP;
NOP;
NOP;
NOP;
NOP;
NOP;
}

}

hsync_off; //HSYNC syncro level off sbi(PORTD,3)

//******Syncronization Handler********

}


Ассемблер:

CODE
//All VGA sincronize made here..
SIGNAL(SIG_OVERFLOW0) {
de4: 1f 92 push r1
de6: 0f 92 push r0
de8: 0f b6 in r0, 0x3f; 63
dea: 0f 92 push r0
dec: 11 24 eor r1, r1
dee: 2f 93 push r18
df0: 8f 93 push r24
df2: 9f 93 push r25
//unsigned char port_buffer;

TCNT0 = TIMER_LIMIT; //reload counter value
df4: 83 ec ldi r24, 0xC3; 195
df6: 82 bf out 0x32, r24; 50
//******Syncronization Handler********

//Count number of lines
if (++linecount == vga_field_line_count) {
df8: 80 91 77 00 lds r24, 0x0077
dfc: 90 91 78 00 lds r25, 0x0078
e00: 01 96 adiw r24, 0x01; 1
e02: 90 93 78 00 sts 0x0078, r25
e06: 80 93 77 00 sts 0x0077, r24
e0a: 80 91 77 00 lds r24, 0x0077
e0e: 90 91 78 00 lds r25, 0x0078
e12: 8d 50 subi r24, 0x0D; 13
e14: 92 40 sbci r25, 0x02; 2
e16: 41 f4 brne .+16; 0xe28 <__vector_11+0x44>
linecount = 0;
e18: 10 92 78 00 sts 0x0078, r1
e1c: 10 92 77 00 sts 0x0077, r1
//clear pointers for render display buffer
raw_render = 0;
e20: 10 92 73 03 sts 0x0373, r1
y_line_render = 0;
e24: 10 92 79 00 sts 0x0079, r1
// Вертикальный и горизонтальный синхроимпульсы должны быть одновременно, поэтому дёргать битами порта раздельно по cbi/sbi не получится.
// кроме того, тело прерывания крайне чувствительно ко времени исполнения, и добавление любой команды сбивает синхронизацию.
// я не смог победить этот глюк и использовал костыль с промежуточной переменной.

//Make Vsync length 2 VGA lines
if ((linecount == 10 )||(linecount == 11 )) {
e28: 80 91 77 00 lds r24, 0x0077
e2c: 90 91 78 00 lds r25, 0x0078
e30: 0a 97 sbiw r24, 0x0a; 10
e32: 31 f0 breq .+12; 0xe40 <__vector_11+0x5c>
e34: 80 91 77 00 lds r24, 0x0077
e38: 90 91 78 00 lds r25, 0x0078
e3c: 0b 97 sbiw r24, 0x0b; 11
e3e: 11 f4 brne .+4 ; 0xe44 <__vector_11+0x60>
//Make here vertical syncronization & HSYNC syncro level on
PORTD = 0; //vsync_on
e40: 12 ba out 0x12, r1; 18
e42: 02 c0 rjmp .+4 ; 0xe48 <__vector_11+0x64>
} else {
//.. & HSYNC syncro level on
PORTD = 4;// (PORTD | 0x04); //vsync_off
e44: 84 e0 ldi r24, 0x04; 4
e46: 82 bb out 0x12, r24; 18


}

video_enable_flg = true;
e48: 81 e0 ldi r24, 0x01; 1
e4a: 80 93 74 03 sts 0x0374, r24


if (linecount < 45) {
e4e: 80 91 77 00 lds r24, 0x0077
e52: 90 91 78 00 lds r25, 0x0078
e56: 8d 97 sbiw r24, 0x2d; 45
e58: 90 f4 brcc .+36; 0xe7e <__vector_11+0x9a>
video_enable_flg = false;
e5a: 10 92 74 03 sts 0x0374, r1
...
NOP;
NOP;
NOP;
NOP;
NOP;
NOP;
e7a: 00 00 nop
e7c: 19 c0 rjmp .+50; 0xeb0 <__vector_11+0xcc>

} else {
//Forming current string for rendering
if (++y_line_render == vga_symbol_height) {
e7e: 80 91 79 00 lds r24, 0x0079
e82: 8f 5f subi r24, 0xFF; 255
e84: 80 93 79 00 sts 0x0079, r24
e88: 80 91 79 00 lds r24, 0x0079
e8c: 88 31 cpi r24, 0x18; 24
e8e: 41 f4 brne .+16; 0xea0 <__vector_11+0xbc>
raw_render++;
e90: 80 91 73 03 lds r24, 0x0373
e94: 8f 5f subi r24, 0xFF; 255
e96: 80 93 73 03 sts 0x0373, r24
y_line_render = 0;
e9a: 10 92 79 00 sts 0x0079, r1
e9e: 08 c0 rjmp .+16; 0xeb0 <__vector_11+0xcc>
...
NOP;
}

}

hsync_off; //HSYNC syncro level off sbi(PORTD,3)
eb0: 93 9a sbi 0x12, 3; 18

//******Syncronization Handler********

}
eb2: 9f 91 pop r25
eb4: 8f 91 pop r24
eb6: 2f 91 pop r18
eb8: 0f 90 pop r0
eba: 0f be out 0x3f, r0; 63
ebc: 0f 90 pop r0
ebe: 1f 90 pop r1
ec0: 18 95 reti

00000ec2 <display_Mega>:


Сообщение отредактировал Dikoy - Apr 4 2018, 17:18
Причина редактирования: [codebox] для длинного кода. [code]-для короткого!!!
Go to the top of the page
 
+Quote Post



Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 19th July 2025 - 21:43
Рейтинг@Mail.ru


Страница сгенерированна за 0.01366 секунд с 7
ELECTRONIX ©2004-2016