Перейти к содержанию

Написание Драйвера Для Lcd Дисплеев Алгоритма Брезенхема.


Arthur

Рекомендуемые сообщения

Короче посетила меня идея (с таблеткой эспумезана), имеется дисплей MT-12864A-2FLA по сути он ничем наверное не отличается от LGM12641BS1R у них такие же контроллеры стоят. Рисовать растр, согласитесь это занимает очень много места в памяти микроконтроллера. И задумался я написать драйвер для него (аля векторная графика), задаю точку 1 и точку 2 а он чертит сам мне линию. Алгоритмы уже есть, написаны за долго до меня, за основу взял алгоритм Брезенхема. Написать программу это пол беды, столкнулся я с такой проблемой, ведь дисплей по сути разбит на два сектора (кристалла) по 64 столбца. и если допусти мне надо поставить одну точку в одном кристалле а другую в другом, программа то расчитает мне точки линии, но как мне сделать перенос с одного кристалла на другой?

Дальше еще думаю, как быстро он будет делать расчёты. всех точек. и на сколько быстро он прочертит одну линию.

Конечно я лезу в дебри если честно и наверника уже есть такие дисплеи со встроенным контроллером, которому эту программу не надо писать, и дисплею нужно лишь подать координаты двух точек (графический контроллер) но я пока такие дисплеи не нашёл, может не там искал.

Ссылка на комментарий
Поделиться на другие сайты

Реклама: ООО ТД Промэлектроника, ИНН: 6659197470, Тел: 8 (800) 1000-321

Перед выводом каждой точки придётся определять, в какую половинку нужно отправить точку со всеми вытекающими.

Анализировать придётся так - сначала определяем в какую половинку должен попадать байт. За это, получается, отвечает 6-ой бит координаты X (при отсчёте от нуля, предпоследний бит байта). Он равен нулю - когда координата меньше или равно 63, и равен 1, если координата больше 63. Затем если этот бит 0 - нужно включить кристалл 1, и затем сразу вычислять адрес байта, с каким предстоит работать, если же бит равен 1 - то тогда нужно включить кристалл 2, затем вычесть из координаты X число 64 (или обнулить тот же 6 бит) и тем же самым куском, что и в первом случае - вычислять адрес байта.

Быстродействие у векторной графики уж очень медленное здесь получится. Но место под хранение данных сэкономит (а вот под программу. которая это рисует - вряд ли)

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

И это только под вывод точки. Если вы для просчёта линии будете использовать плавающую точку, тоже минус в быстродействие. Но конечно интересно, какое в итоге будет быстродейтсвие. Векторная графика даёт широкие возможности для анимации, и если быстродействия хватало бы, то было бы интересно.

Ссылка на комментарий
Поделиться на другие сайты

20% скидка на весь каталог электронных компонентов в ТМ Электроникс!

Акция "Лето ближе - цены ниже", успей сделать выгодные покупки!

Плюс весь апрель действует скидка 10% по промокоду APREL24 + 15% кэшбэк и бесплатная доставка!

Перейти на страницу акции

Реклама: ООО ТМ ЭЛЕКТРОНИКС, ИНН: 7806548420, info@tmelectronics.ru, +7(812)4094849

я так понял быстродействие вычислений будет зависить от быстродействия мозгов микроконтроллера, а я так понял это у Atmega8 (16MHz), а если взять сразу микроконтроллер пошустрее. Есть ли такие среди AVR или PIC???

Ссылка на комментарий
Поделиться на другие сайты

Выбираем схему BMS для корректной работы литий-железофосфатных (LiFePO4) аккумуляторов

 Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ, также как и для других, очень важен контроль процесса заряда и разряда, а специализированных микросхем для этого вида аккумуляторов не так много. Инженеры КОМПЭЛ подготовили список имеющихся микросхем и возможных решений от разных производителей. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

Быстродействие вычислений будет зависить не только от частоты чипа, но и от его математических аппаратных возможностей.

По этому вопрос, типа "быстро или медленно будет выполняться задача" - некорректный. Нужно просто брать и пробовать. Ну и, естественно, многое ещё зависит от программиста - как он реализует ту или иную задачу.

Ссылка на комментарий
Поделиться на другие сайты

Одну и ту же формулу можно программно прописать весьма и весьма по-разному. Так что выход один - лапками писать, спрашивая у головы.

Я не раздаю удочки. Я продаю рыбу.

Ссылка на комментарий
Поделиться на другие сайты

Анализировать придётся так
Ну да, вычисления вести в непрерывном поле 256х256 точек, потом

if((X & (1<<6))==0)PutPixel0(X,Y);else PutPixel1(X &~(1<<6),Y), где PutPixel0, PutPixel1 - процедуры рисования в 1 и 2 кристалле.

Для контроллера это будет довольно быстро.

а вот под программу. которая это рисует - вряд ли
Когда я учил ATmega8 общаться с дисплеем от Nokia2650 (132х132х12бит), влезало не только рисование линий, кругов и квадратов, но даже примитивная 3D-анимация (вращающаяся пирамида, кажется), но там использовались числа с плавающей точкой, так что работало довольно медленно. Впрочем, удалось сделать это не слишком заметным. Это была демонстрационная программа, так что оптимизировать не стал.
быстродействие вычислений будет зависить от быстродействия мозгов микроконтроллера
У меня быстродействие упиралось либо в операции с плавающей точкой (что вполне естественно), либо в общение с дисплеем. Там была особенность - протокол SPI, 9 бит, тогда как контроллер умеет только 8-битный. К тому же для вывода линии использовалась последовательность точек, а это около 9 команд.

Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз.

Часть моих наработок.

Ссылка на комментарий
Поделиться на другие сайты

а вот под программу. которая это рисует - вряд ли
Когда я учил ATmega8 общаться с дисплеем от Nokia2650 (132х132х12бит), влезало не только рисование линий, кругов и квадратов, но даже примитивная 3D-анимация (вращающаяся пирамида, кажется)....

Вы комментируя, нарушили контекст. Речь шла об экономии места при векторном подходе в сравнении с растровым. По экономии на памяти данных вектор выигрывает, а вот по памяти кода - нет. В любом случае программа вывода растра будет компактней и быстрее, чем любая векторная. А то что векторная программа куда то влазиет или нет - это уже другой вопрос.

И не забываем, что кроме рисования вектора там ещё что-то может быть запрограммировано, и не исключена ситуация, что векторный подход может создать проблемы со свободной памятью.

Ссылка на комментарий
Поделиться на другие сайты

Векторный - едва ли. Наверное, забыл упомянуть, почему выбрал векторный подход: в контроллере не хватит памяти даже на одну картинку: 132*132*1.5=26136 байт из 9.5 кБайт контроллера (считая EEPROM и ОЗУ). А вот векторные алгоритмы вполне влезли. 3D-графика, правда, заняла едва ли не всю память, но это из-за обработки чисел с плавающей точкой и решения в лоб. А в финальное устройство влезли и рисования линий, кругов и прямоугольников, плюс вывод текста и vusb.

Но в целом да, зависит от задачи и реализации: если рисовать пейзажи или хотя бы иконки, даже символы алфавита, растровое хранение будет удобнее (хотя можно поковыряться с алгоритмами сжатия), а если схематичные рисунки из полутора примитивов или анимация - векторная.

Вы комментируя, нарушили контекст.
Цитату я взял скорее чтобы указать, на что конкретно отвечаю. Если выбрал неудачно - извиняюсь.
В любом случае программа вывода растра будет компактней и быстрее, чем любая векторная.
Не совсем: если использовать алгоритмы сжатия, которые тоже работают с растром, код может получиться куда больше.

Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз.

Часть моих наработок.

Ссылка на комментарий
Поделиться на другие сайты

Ну эт да. Если есть сжатие растра, то объём несомненно вырастет, особенно если алгоритм непростой. Хотя у меня есть подозрения, что даже такой алгоритм будет компактнее вектора, т.к. в сжатии чб-растров не так много возможностей.... но утверждать не буду, поскольку не пробовал. Когда столкнулся с этим, ради простоты поставил внешнюю eeprom и использовал растр без сжатия. Хотя и стараюсь избегать лишних корпусов.

Ссылка на комментарий
Поделиться на другие сайты

а я всё думаю) что я мужу) ведь речь идет не о каких либо миллионах пикселей а всего навсего о 128 на 64 экранчике)))) там погрешность не будет играть значимой роли мне кажется) поэтому можно формулу Брезенхема закопать)))

Ссылка на комментарий
Поделиться на другие сайты

Там как раз погрешность будет играть роль, сдвиг на пиксель это же целых 1,5% высоты! Ну и насколько я понимаю, этот алгоритм быстрее и компактнее, чем большинство самописных, так что надо не закапывать, а осваивать.

ради простоты поставил внешнюю eeprom
Наверное, оно добавило не только простоты, но и универсальности: какое бы ни было сжатие, во флеш (а тем более EEPROM) контроллера много не запихнется.

Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз.

Часть моих наработок.

Ссылка на комментарий
Поделиться на другие сайты

о какой погрешности может идти речь на поле 128 на 64 пикселей на 0,01?))) я одного только не пойму) у меня в ступор ввел этот алгоритм Брезенхема, Линию вправо и вниз понятно. Линию вправо и вверх тоже, Вверх влево и Вверх вправо тоже.. А вот как сделать в обратное направление) т.е. влево и вниз влево и вверх. Вниз и влево вниз и вправо, так и не понял)

Ссылка на комментарий
Поделиться на другие сайты

А поменять местами аргументы не интересно? Чем отличается линия вправо-вверх от линии влево-вниз?

Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз.

Часть моих наработок.

Ссылка на комментарий
Поделиться на другие сайты

ради простоты поставил внешнюю eeprom

Наверное, оно добавило не только простоты, но и универсальности

Вообще благодаря внешней удалось сделать лучше, чем планировалось. А затраты (трудовые) на установку ещё одного корпуса не такие и большие.

у меня в ступор ввел этот алгоритм Брезенхема

Могу предложить более понятный алгоритм :) Правда он используется на мощных платформах, в частности в расчёте прямолинейных траекторий объектов в 3D графике. Но 3-ю координату можно откинуть, а вместо объекта предполагать точку. Вся математика в виде двухмерных векторов

Вектор s - стартовая координата линии, вектор e - конечная координата линии.

Вычисляем вектор, соответствующий линии

lv=e-s

Кроме того, что этот вектор есть по сути описание линии, он также указывает направление от точки старта в сторону точки завершения линии. Поэтому из него можно сделать дельта-вектор или вектор приращения - для этого необходимо нормализовать вектор - длина нормализованного вектора всегда равна единице - но направление сохраняется. Процедура нормализации вектора - каждый компонент вектора разделить на длину этого вектора:

lv_len = sqr(lv.x^2+ lv.y^2) //Вычисляем длину вектора
lv.x = x / lv_len //Нормализуем компоненты вектора
lv.y = y / lv_len

Теперь lv - это есть дельта-вектор длиной в единицу и описывающий направление линии от точки старта к точке завершения и он же идеальные дельта-вектор или вектор приращения.

Осталось только организовать цикл - начинаем со стартовой точки и пользуясь дельта-вектором двигаемся вдоль траектории и тыкаем точки до тех пор, пока не встретимся с конечной координатой:

cv=s //Устанавливаем текущий вектор на стартовую точку
while int(cv) <> int(e){ //Контроль попадания в конечную точку
PutPixel(cv) //Вывод пиксела
cv=cv+lv //Сдвиг текущей точки вдоль траектории
}

Как то так, вроде ничего не перепутал. Не уверен, что такой подход для МК годится, но он весьма прост сам по себе - чистая математика, никаких условий и отзеркаливаний - знаки в дельта-векторе сами по себе выходят в нужном направлении.

Изменено пользователем tcoder
Ссылка на комментарий
Поделиться на другие сайты

* контроль попадания в конечную точку лучше заменить на подсчёт прорисованных пикселов. Длина вектора lv (lv_len) по сути содержит, сколько точек надо прорисовать, и в данном случае можно использовать цикл for, или считать в while кол-во итераций...

Вот экзешник (сваял побыстрому), демонстрирующий работу этого алгоритма:

DrawLine.zip

Водить мышью по окну - будет чертить линию из центра окна к курсору с помощью алгоритма, описанного выше. Особенно можно обратить внимание на параметры дельта-вектора в зависимости от угла линии. Также интересным является число дважды прорисованных пикселей из общего их числа. Ещё при некоторых углах заметна некоторая узловатость - интересный эффект однако - видимо математическая ошибка присутствует в какой то степени.

Изменено пользователем tcoder
Ссылка на комментарий
Поделиться на другие сайты

Для контроллера это не лучший алгоритм, разве что нормализовать не на 1 а на 128 например.

Вот такой алгоритм работает у меня:

был в заготовке общения с дисплеем, написанной Goncharenko Valery and Chiper

void nlcd_Line(unsigned char x0, unsigned char y0, unsigned char x1, unsigned char y1, int color)

{

int dy = y1 - y0;

int dx = x1 - x0;

int stepx, stepy;

if (dy < 0) { dy = -dy; stepy = -1; } else { stepy = 1; }

if (dx < 0) { dx = -dx; stepx = -1; } else { stepx = 1; }

dy <<= 1; // dy is now 2*dy

dx <<= 1; // dx is now 2*dx

nlcd_Pixel(x0, y0, color);

if (dx > dy)

{

int fraction = dy - (dx >> 1); // same as 2*dy - dx

while (x0 != x1)

{

if (fraction >= 0)

{

y0 += stepy;

fraction -= dx; // same as fraction -= 2*dx

}

x0 += stepx;

fraction += dy; // same as fraction -= 2*dy

nlcd_Pixel(x0, y0, color);

}

}

else

{

int fraction = dx - (dy >> 1);

while (y0 != y1)

{

if (fraction >= 0)

{

x0 += stepx;

fraction -= dy;

}

y0 += stepy;

fraction += dx;

nlcd_Pixel(x0, y0, color);

}

}

}

Все достаточно просто - выбирается ось, проекция на которую отрезка будет больше (например, Х). Счетчик оси (х) идет от начальной точки до конечной (от х0 до х1). Дополнительная переменная на каждом шаге увеличивается на длину меньшей проекции. Если эта переменная положительная - увеличивается счетчие меньшей оси (у) и от нее отнимается большая проекция, из-за чего она тут же становится отрицательной. И, разумеется, на каждом шаге ставится точка.

Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз.

Часть моих наработок.

Ссылка на комментарий
Поделиться на другие сайты

Для контроллера это не лучший алгоритм

Эт да, я на это указал. Спектр применения его ограничен на МК, особенно если используется подход с беспрерывным независимым "рендером". Больше он подойдёт для систем, где есть аппаратная поддержка плавающей точки или вычислений с векторами. Кстати, интересный вопрос, есть ли хоть один МК, у которого есть аппаратная поддержка вычислений с плавающей точкой...

Приведённый алгоритм мне знаком, хотя я несколько в другом виде его использовал, но этот хитрее малость... а суть та же.

Тут меня ещё одна мысль посетила: насколько возможно в подобных алгоритмах отказаться от поточечного вывода, и пытаться воздействовать сразу на байт.... т.е. устанавливать сразу несколько бит, если вдруг часть точек в ряд выстроится в нужном месте... но что-то мне подсказывает, что "овчинка выделки не стоит".

Ссылка на комментарий
Поделиться на другие сайты

АРМы какие-нибудь может и поддерживают.

Устанавливать несколько бит одновременно? Для этого должен быть участок горизонтальной или вертикальной прямой соответствующей длины, ориентация зависит от дисплея. Навскидку, длина такой последовательности - котангенс угла наклона линии. Для последовательности хотя бы из 5 точек (навскидку, для меньшего числа заморачиваться не стоит) это около 10 градусов. Много там будет линий с меньшими углами наклона? Стоят ли они дополнительного кода и памяти?

Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз.

Часть моих наработок.

Ссылка на комментарий
Поделиться на другие сайты

:unknw: Увы, это только мысли. Возможно есть не тригонометрическое решение - например пока координата X не изменяется - не выводить пиксел, а набивать его в байт (сдвиг-наложение), и потом, как только реальные координаты выйдут за пределы данного байта - производить вывод байта.... соответственно тут смешние уровней получается - придётся отслеживать и координаты и адрес вывода. Теоретически это может получится... практически... надо подумать на досуге)
Ссылка на комментарий
Поделиться на другие сайты

А поменять местами аргументы не интересно? Чем отличается линия вправо-вверх от линии влево-вниз?

минус на плюс поменять могу. но вот обратно по оси икс в минус не могу организовать.

Ссылка на комментарий
Поделиться на другие сайты

Возможно есть не тригонометрическое решение
Тригонометрическое это только для оценки: если вероятность любой линии одинакова, то последовательности хотя бы из 5 точек будут встречаться в одной линии из 9 (90/10). Нет, если предполагается рисовать много почти горизонтальных линий оно может и оправдано, но в общем случае - едва ли. Не-тригонометрически длина отрезка, параллельного оси координат будет примерно равна отношению проекций на эти оси.
А поменять местами аргументы не интересно? Чем отличается линия вправо-вверх от линии влево-вниз?
Имелось в виду примерно вот что:

if(x0>x1){temp=x0; x0=x1; x1=temp; temp=y0; y0=y1; y1=temp;}

//далее основной код

Либо, как в коде из 16 поста, можно ввести отдельные переменные для знака приращения по разным осям.

Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз.

Часть моих наработок.

Ссылка на комментарий
Поделиться на другие сайты

При таком лобовом подходе чем не устраивает универсальная формула, вариации которой используются аж в 4 вариантах, хотя достаточно одного.

y=(y2-y1)*(x-x1)/(x2-x1)+y1 если |x2-x1|>|y2-y1|, счетчик x [x1...x2], неважно что больше

x=(x2-x1)*(y-y1)/(y2-y1)+x1 если |x2-x1|<|y2-y1|, счетчик у [y1...y2], неважно что больше

Или какая-то религия запрещает считать в сторону уменьшения а не увеличения

for(i=10;i>0;i--)?

Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз.

Часть моих наработок.

Ссылка на комментарий
Поделиться на другие сайты

Ну радует что осенило :-)

Вообще-то контроллерам тяжко работать с числами с плавающей точкой и делением. Ради интереса можете глянуть в какое ассемблерное колдовство они разворачиваются. Для "драйвера ЖК дисплея" (LCD-дисплей - тавтология) такой прямолинейный алгоритм все же не подходит. Тем более в варианте из 8 отдельных формул.

Хотя если на дисплее таки появятся вожделенные линии, возможно это добавит мотивации не бросать дело на полпути.

Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз.

Часть моих наработок.

Ссылка на комментарий
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.
Примечание: Ваш пост будет проверен модератором, прежде чем станет видимым.

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

×   Вставлено с форматированием.   Восстановить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

Загрузка...
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...