|
Подмешивание в видеосигнал |
|
|
|
Dec 20 2007, 19:44
|
Частый гость
 
Группа: Новичок
Сообщений: 90
Регистрация: 19-12-07
Пользователь №: 33 459

|
Разбираюсь с АТмегой16, на этот раз экспериментирую с подмешиванием данных (хотя бы палочек-полосок) в композитный видео-сигнал. Перерыл все возможные гуглы, нашел несколько реализаций, нашел описание передачи видео-сигнала. Читал, смотрел, опять читал. С железом более-менее разобрался, принцип работы понятен. А вот с софтом не очень, не хватает познаний. Так что все рассуждения основываются на познаниях из мануалов "для чайников" Итак, купил LM1881, кварц 16 мгц, конденсаторы, резисторы, пару диодов. Подключил все это к меге16 - сигнал горизонтальной синхронизации на вход внешних прерываний INT0, вертикальной на INT1. Получается что прерывание по INT0 возникает в начале прорисовки каждой строки, а INT1 в начале каждого кадра (или полукадра, т.к. рисуется через строчку). Ногу PD7 сделал выходом и подключил обратно к центральной жиле видеокабеля через диод и сопротивление. Сделал счетчик строк, который прибавляет 1 при каждом INT0 и обнуляет при INT1. Посидел, подумал, написал... в прерывании INT0 ждем нужной строки, после чего ждем определенное время, включаем "питание" на PD7, опять ждем, выключаем питание. Получается горизонтальная линия определенной длины и с определенным смещением от левого края. Нарисуем крест. В обработчике INT0 условие - если строка не та, которая нам нужна, то ждем, включаем PD7 и сразу же выключаем (чтобы получить штрих с наименьшим размахом). Т.к. задержка в каждой строке одинаковая, должна получится ровная вертикальная линия. Но не получается :  Линия гуляет как бы лесенкой на всем протяжении. По логике получается, что временной интервал от начала прерывания до начала включения PD7 при одинаковых значениях получается разным  Фото стоп-кадра экрана прикрепил. Вот кусок кода с обработкой прерываний: Код // External Interrupt 0 service routine interrupt [EXT_INT0] void ext_int0_isr(void) { if (vert==150) { i=10; while(i--) { #asm("nop"); } PORTD.7=1; i=30; while(i--) { #asm("nop"); } PORTD.7=0; } else { i=20; while(i--) { #asm("nop"); } PORTD.7=1; PORTD.7=0; }
vert++; }
// External Interrupt 1 service routine interrupt [EXT_INT1] void ext_int1_isr(void) { // Place your code here vert=0; } Обучите, пожалуйста, чайника основным принципам правильного построения изображения на этой железной связке (LM1881 + atmega16). Для начала хотя бы прямых линий
Сообщение отредактировал idono - Dec 20 2007, 19:48
Эскизы прикрепленных изображений
|
|
|
|
|
 |
Ответов
|
Dec 21 2007, 09:23
|
Профессионал
    
Группа: Свой
Сообщений: 1 235
Регистрация: 14-05-05
Из: Санкт-Петербург
Пользователь №: 5 008

|
Цитата видимо процессор тратит много тактов на такие операции А вы посмотрите что у вас в асм листиге получилось, там же, небось еще и выборка из массива каждый раз делается, как вариант №1 осмелюсь предложить перед операцией собственно вывода сделать чтение нужного байта из массива в какую то переменную, а потом сдвигать виты только из этой переменной, примерно так: Код tmp = symbol[cur_line] PORTD.7=tmp & (1 << 0); // присваиваем порту вывода 1, если в нулевом бите symbol единица (т.е. включаем белый пиксел) PORTD.7=tmp & (1 << 1); // тоже, но проверяем первый бит PORTD.7=tmp & (1 << 2); // второй бит PORTD.7=tmp & (1 << 3); // и так далее PORTD.7=tmp & (1 << 4); PORTD.7=tmp & (1 << 5); PORTD.7=tmp & (1 << 6); PORTD.7=tmp & (1 << 7); возможно того же эффекта можно добиться используя оптимизацию по скорости компилятора. вариант №2, сделать аппаратный вывод битов, например через внешний регистр с параллельной загрузкой и последосательным выходом, можно попробовать для этой цели приспособить аппаратный SPI, который есть на МК. А еще, если есть свободный порт, например то же PORTD, то можно сделать так: Код PORTD = symbol[cur_line]; PORTD >>= 1; //и так 8 раз при этом все линии порта кроме младшей должны быть свободны а на выводе PORTD.0 мы получим последовательность битов, начиная от младшего, либо можно получить биты, начиная со старшего , если применить сдвиг в другую сторону, тогда последовательность будет выходить с PORTD.7
--------------------
|
|
|
|
|
Dec 21 2007, 09:55
|
Частый гость
 
Группа: Новичок
Сообщений: 90
Регистрация: 19-12-07
Пользователь №: 33 459

|
Чтение байта из массива перед выводом помогло, ширина символа сократилась примерно в полтора раза. Опимизация компилятора по скорости уменьшила символ еще на столько же! Спасибо за советы, GDI Теперь символ 8х12 выглядит вполне хорошо. Теперь попробую привязать готовый массив с шрифтом, дабы букву можно было оттуда выбирать и делать вывод
Эскизы прикрепленных изображений
|
|
|
|
|
Dec 21 2007, 16:32
|
Частый гость
 
Группа: Новичок
Сообщений: 90
Регистрация: 19-12-07
Пользователь №: 33 459

|
нарисовал из нулей массив цифр, написал функцию для прерывания. Старался делать все без массивов и циклов - при срабатывании прерывания, перед выводом делаю все вычисления, байты сравниваю и тп, потом в ряд идет вывод. Да условия перед этим выводом такой сложности, что вывод поспевает уже к концу отрисовки строки, только только 3 цифры успеваю вывести. Для теста я пробовал вывести на одну из строк показания с датчика температуры - впритык к максимальной загрузке меги, но получилось (результат прикрепил). Вот код (только основная проблемная часть) Код char symbol[13][12]={ { 0b00011000, // 0 0b00100100, 0b01000010, 0b01000010, 0b01000010, 0b01000010, 0b01000010, 0b01000010, 0b01000010, 0b01000010, 0b00100100, 0b00011000 }, ..... и так далее }
// External Interrupt 0 service routine interrupt [EXT_INT0] void ext_int0_isr(void) { //если текущая строка попадает в заданую область для 1го ряда цифр if (vert>start_line && vert<start_line+13) { drawing1=number1; //присваиваем переменным прорисовки цифр drawing значения каких-то параметров drawing2=number2; //в тесте параметров нет, поэтому значения просто присвоены выше drawing3=number3; state1=1; // флаг нахождения в нужном диапазоне для обработчика ниже } else { state1=0; } // случай со вторым рядом цифр if (vert>start_line2 && vert<start_line2+13) { drawing1=number5; drawing2=number6; drawing3=number7; state2=1; } else { state2=0; }
// случай с третьим рядом цифр if (vert>start_line3 && vert<start_line3+13) { drawing1=number9; drawing2=number10; drawing3=number11; state3=1; } else { state3=0; }
//если строка попадает в область прорисовки одного из 3х значений, то запускаем обработчик if (state1 || state2 || state3) { //вычисляем значение (0 или 1) каждого пиксела для всех 3х цифр в данной строке (тип переменной tmp - bit) tmp00 = symbol[drawing1][cur_line]& (0b10000000 >> 0); tmp01 = symbol[drawing1][cur_line]& (0b10000000 >> 1); tmp02 = symbol[drawing1][cur_line]& (0b10000000 >> 2); tmp03 = symbol[drawing1][cur_line]& (0b10000000 >> 3); tmp04 = symbol[drawing1][cur_line]& (0b10000000 >> 4); tmp05 = symbol[drawing1][cur_line]& (0b10000000 >> 5); tmp06 = symbol[drawing1][cur_line]& (0b10000000 >> 6); tmp07 = symbol[drawing1][cur_line]& (0b10000000 >> 7);
tmp10 = symbol[drawing2][cur_line]& (0b10000000 >> 0); tmp11 = symbol[drawing2][cur_line]& (0b10000000 >> 1); tmp12 = symbol[drawing2][cur_line]& (0b10000000 >> 2); tmp13 = symbol[drawing2][cur_line]& (0b10000000 >> 3); tmp14 = symbol[drawing2][cur_line]& (0b10000000 >> 4); tmp15 = symbol[drawing2][cur_line]& (0b10000000 >> 5); tmp16 = symbol[drawing2][cur_line]& (0b10000000 >> 6); tmp17 = symbol[drawing2][cur_line]& (0b10000000 >> 7); tmp20 = symbol[drawing3][cur_line]& (0b10000000 >> 0); tmp21 = symbol[drawing3][cur_line]& (0b10000000 >> 1); tmp22 = symbol[drawing3][cur_line]& (0b10000000 >> 2); tmp23 = symbol[drawing3][cur_line]& (0b10000000 >> 3); tmp24 = symbol[drawing3][cur_line]& (0b10000000 >> 4); tmp25 = symbol[drawing3][cur_line]& (0b10000000 >> 5); tmp26 = symbol[drawing3][cur_line]& (0b10000000 >> 6); tmp27 = symbol[drawing3][cur_line]& (0b10000000 >> 7); // и быстро выводим получившиеся значения с небольшой задержкой (промежутки между цифрами) PORTD.7=tmp00; PORTD.7=tmp01; PORTD.7=tmp02; PORTD.7=tmp03; PORTD.7=tmp04; PORTD.7=tmp05; PORTD.7=tmp06; PORTD.7=tmp07; delay_us(5); PORTD.7=tmp10; PORTD.7=tmp11; PORTD.7=tmp12; PORTD.7=tmp13; PORTD.7=tmp14; PORTD.7=tmp15; PORTD.7=tmp16; PORTD.7=tmp17; delay_us(5); PORTD.7=tmp20; PORTD.7=tmp21; PORTD.7=tmp22; PORTD.7=tmp23; PORTD.7=tmp24; PORTD.7=tmp25; PORTD.7=tmp26; PORTD.7=tmp27; cur_line++; } else { cur_line=0; }
vert++; }
// External Interrupt 1 service routine interrupt [EXT_INT1] void ext_int1_isr(void) { // Place your code here vert=0; } Кажется все эти просчеты &, сдвиги битов и выборы из 3х-мерного массива в количестве 24 штуки сильно грузят процессор. Так, что 3й символ успевает выскочить уже почти в конце строки. Просчеты для 4го символа вставить конечно уже некуда  Само собой разумеется, что алгоритм всех этих просчетов неверный. Хочется побольше информации на изображение наложить. Подскажите более правильный алгоритм побитового вывода байта из массива в порт, пожалуйста
Сообщение отредактировал idono - Dec 21 2007, 16:38
Эскизы прикрепленных изображений
|
|
|
|
|
Dec 21 2007, 17:17
|
Местный
  
Группа: Участник
Сообщений: 246
Регистрация: 4-12-06
Пользователь №: 23 101

|
ИМХО это большой героизм советского толка писать такое на С. Лучше на ассемблере - там эмулятор точно считает время, можно всё учесть и пользоваться всякими хитростями. Сам интересуюсь подобной штукой, поэтому интересно, что у Вас получится. Видел проект, где пикселы строки заносятся во все 32 регистра, а потом тупо сдвигаются. Для сдвига, подумалось мне, можно использовать один из последовательных интерфейсов, кажется TWI может подойти. Или использовать внешний регистр сдвига как external RAM. Насчёт дрожания. PLL к строчной синхронизации конечно желателен, но у нас есть разработка с пиксельной частотой 20 МГц, буквы не дрожат.
|
|
|
|
|
Dec 22 2007, 11:34
|
Частый гость
 
Группа: Новичок
Сообщений: 90
Регистрация: 19-12-07
Пользователь №: 33 459

|
Цитата(Maik-vs @ Dec 21 2007, 20:17)  ИМХО это большой героизм советского толка писать такое на С. Лучше на ассемблере - там эмулятор точно считает время, можно всё учесть и пользоваться всякими хитростями. Сам интересуюсь подобной штукой, поэтому интересно, что у Вас получится. Видел проект, где пикселы строки заносятся во все 32 регистра, а потом тупо сдвигаются. Для сдвига, подумалось мне, можно использовать один из последовательных интерфейсов, кажется TWI может подойти. Или использовать внешний регистр сдвига как external RAM. Насчёт дрожания. PLL к строчной синхронизации конечно желателен, но у нас есть разработка с пиксельной частотой 20 МГц, буквы не дрожат. Для меня скорее наоборот на ассемблере будет героизмом писать, т.к. я вообще в нем ничего не знаю  Так что пишу по мере возможностей на Си Расскажите, пожалуйста, про TWI и SPI применительно к моей задаче. Посмотрел проекты другие, там идет запись в какой-то SPDR, почитал даташит, мало чего понял. Если не сложно, напишите пример вывода хотя бы одного байта в строку с помощью этих технологий, попробую разобраться что к чему. Ну и надо попробовать вариант с выводом целого байта в свободный порт с последующим сдвигом, может это будет быстрее
|
|
|
|
Сообщений в этой теме
idono Подмешивание в видеосигнал Dec 20 2007, 19:44 PSP Прерывание не обрабатывается мгновенно, всегда про... Dec 20 2007, 21:19 rx3apf Цитата(PSP @ Dec 21 2007, 00:19) Прерыван... Dec 21 2007, 00:07  idono Вставил бесконечный цикл с idle(); в главной функц... Dec 21 2007, 07:02   alux Смотри на avrfreaks в последних проектах "AVG... Dec 21 2007, 07:48    idono Цитата(alux @ Dec 21 2007, 10:48) Смотри ... Dec 21 2007, 08:55 Serj78 на 16 мгц совершенно достаточно засыпать потом про... Dec 20 2007, 21:41 Т.Достоевский Цитата(Serj78 @ Dec 21 2007, 00:41) на 16... Dec 20 2007, 22:52 =VRA= Все это на раз делается даже без LM1881 Dec 20 2007, 23:41    rx3apf Цитата(Maik-vs @ Dec 21 2007, 20:17)... Dec 21 2007, 17:43     idono Сделал вариант с выводом байта целиком в порт с по... Dec 22 2007, 20:23 rezident Чтобы уменьшить джиттер и величину запаздываний вы... Dec 21 2007, 17:24 umup ЦитатаTWI - не лучший вариант. SPI - тоже
как раз... Dec 21 2007, 18:12 rx3apf Цитата(umup @ Dec 21 2007, 21:12) как раз... Dec 21 2007, 18:29  Rst7 Цитата(rx3apf @ Dec 21 2007, 20:29) Я же ... Dec 22 2007, 06:02 Rst7 ЦитатаПолучилась отличная реализация телеметрии дл... Dec 23 2007, 12:46 Xumuk Привет всем
Очень интересная тема, давно думал на... Dec 23 2007, 14:36  idono Xumuk, на схеме сразу бросается в глаза разрыв вид... Dec 23 2007, 18:23   Xumuk Цитата(idono @ Dec 23 2007, 20:23) Xumuk,... Dec 23 2007, 20:40    idono Цитата(Xumuk @ Dec 23 2007, 23:40) А можн... Dec 23 2007, 21:39     idono Объясните на пальцах, пожалуйста, как сделать выво... Jan 1 2008, 01:18 Т.Достоевский Только вертикальную скорость нужно отображать ввид... Dec 23 2007, 18:54 idono Цитата(Т.Достоевский @ Dec 23 2007, 21:54... Dec 23 2007, 19:27  Т.Достоевский Цитата(idono @ Dec 23 2007, 22:27) Не дум... Dec 23 2007, 19:40 HCHUNTER idono,
...от себя хотел добавить - обратите вним... Jan 1 2008, 07:39 Serj78 Idono,
Надо просто помнить, что SPI - фактически... Jan 1 2008, 11:09 HCHUNTER Цитата(Serj78 @ Jan 1 2008, 14:09) невозм... Jan 1 2008, 12:21  Xumuk Может целесообразно использовать 2 микроконтроллер... Jan 19 2008, 08:15 Algol HCHUNTER
А сколько вам необходимо ОЗУ? Может быть ... Jan 19 2008, 09:54 AndyBig ЦитатаМожет быть поставить внешную статическую рам... Jan 19 2008, 15:03
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|