Указатели в функции
- Войдите на сайт для отправки комментариев
Понадобилась помощь.
Есть дисплей Nokia 1616. цветной 132х162 точки
Интерфейс 9бит SPI
Так как стандартный SPI 8 бит, первый бит бит передается ногодрыганьем, а остально по SPI
Все работает, но медленно
На данный момент скорость зарисовки всего дисплея одним цветом удалось поднять с 0,74 кадра/сек до 3,37 кадра/сек. больше улучшить не получается
я бы успокоился, но нашел библиотеку которая делает почти 18 кадров/сек
и там везде используются указатели
так как я с ними не умею работать, и чтение различной литературы особо ясности не добавило, прощу объяснить как сделать максимальное быстродействие
в основном коде происходит вызов функции, которая например рисует пиксель
в функцию передаем цвет 16бит и сколько раз рисовать
но когда просто передаем мы из одной ячейки оперативной памяти копируем в другую и обрабатываем
но с помощью указателей можно обрабатывать не копируя, а через указатель обратится к самому исходному числу
//============================================================================================== // Вывод на дисплей 8 бит данных или комманд //============================================================================================== void lcd_write(byte mode, byte c){ //dWrite(CS, 0); (mode)? dWrite(DAT, 1) : dWrite(DAT, 0); dWrite(CLK, 1); dWrite(CLK, 0); SPI_HW_ON; SPDR = c; SPI_HW_WAIT; SPI_HW_OFF; } //============================================================================================== // Вывод на дисплей 16 бит данных //============================================================================================== void lcd_write16(unsigned int dat){ lcd_write(DATA,dat>>8); lcd_write(DATA,dat); }
ну и в основной вызываем
Если нужно передать только одно число, то указатель не поможет. Указатель нужен, когда нужно передать множество чисел, расположенных в непрерывной области памяти. Можно исходить ихз следующей логики:
1. Передаем как число. Это значит это число и будет считано в регистр и использовано.
2. Передаем как указатель. Это значит, что указатель будет помещен в регистры, затем будет считано это число из памяти.
Либо я не понял Вашего вопроса.
Можно попробовать выделить в куче область видеопамяти где разные функции будут оперировать с общтми данными без копирования
Попробуйте для начала работаь только с глобальными переменными, вместо того, чтобы гонять их из функции в функцию. Если будет реальное улучшение быстродействия, то можно заменить все это на указатели в качестве параметров. У меня по крайней мере есть большие сомнения, что проблема решится именно указателями, тут наверняка еще и сам алгоритм в "быстрой" библиотеке просто очень хорошо оптимизирован.
всё упирается в SPI, где один бит ногодрыгание... это и есть ограничение... никаких 18 кадров/с быть не может. И кстати, у 1616 160 на 128 точек, а не та херня что вы написали.
__Alexander не знаешь лучше молчи. тебе код дать где это работает?
toly я уже честно сказать и не знаю, выложе исходный код где все быстро и сами увидите
там короче создается массив при заливке экране размеров в одну строку и из него через указатели выводят. наверно в этом дело
повырезал сколько получилось из либы лишнее, там было на 3 дисплея
CPP
H файл
и код для иде
Посмотрел немного...есть указатели, но по другому передать массив в функцию в С и нельзя. Например строка 145 в срр, тут два указателя на начало массивов байт, и отдельно их размер. Код в функции просто передвигает указатель чтобы читать данные, понятно, что это работает быстро, потому что действительно никакие данные в другой массив не копируются, работа идет с исходным массивом.
...для примера, выражение *data++ это данные из ячейки с адресом data, после чтения адрес сдвигается на одну ячейку (в нашем случае байт, т.к data объявлен как указатель на u8)
так массив в си и есть указатель.
Что я говорил, то в исходниках и есть. Непрерывная область передается указателем, одно число (8-16 бит) передается по значению.
я бы успокоился, но нашел библиотеку которая делает почти 18 кадров/сек
....
так как я с ними не умею работать, и чтение различной литературы особо ясности не добавило, прощу объяснить как сделать максимальное быстродействие
Я тут тоже игрался с SPI но совсем с другой стороны... SPI далеко не медленная штука :-)
В вашей ситуации могу сказать что скорее всего ваша проблема в том, что вызов функции это не толко джамп и ретурн, но еше и перераспределение регистров и запись на стек. Компилятор такая "странная" штука что при работе со стеком и регистрами ориентируется на оптимизацию каждой конкретной функции а не общей производительности.
Короче говоря если чистое время посылки Х а время на вызров функции Y, то общее время ( X + Y ) * N.
Если же передавать массив то формула почти не измениться ( X + Z ) * N, где Z это время на цикл прохода по массиву. Причем в зависимости от платформы и компилятора Z минимум в 3-4 а то и в 10-20 раз меньше чем Y. Улавливаете разнцицу ? но что еще более интересно что моя чуйка мне говорит, что X и Z это значения одного порядка, если у вас hardware SPI.....
Если вы перепишите свой код на использования inline а компилятор сможет это выполнить, вы сразу поймете в чем смысл жизни. Правда за inline приходится платить размером конечной программы, она растет как на дрожжах
kisoft как вы считаете реально ли происходит ускорение если сделать например как в этой библиотеке. создаем массив на строку и его указателями отправляем
gregoryl не понял что вы хотите сказать
кстати пока без использования указателей поднял частоту с 3,37 кадра/сек до 9,64 кадра/сек
дальше хочу ногодрыгать через прямое управление портов
не
а
что будет быстрее. но писать тяжело если честно. пока не заработало
__Alexander не знаешь лучше молчи. тебе код дать где это работает?
Спешл во ю. Вот я подключил к хмеге, где spi 16Мгц. Давай, затыкай мне рот.
Или с математикой плохо? Давай считать, по SPI на 16Мгц ардине (это 8 реальных) ты один байт + одно ногодрыгание передашь за 3 мксек. Итого 128*160*2(байта на цвет)*3мксек = 123 мсек. т.е за секунду можно выплюнуть 8 кадров. хоть с указателями, хоть с папой римским. это тупо максимум.
http://youtu.be/yJ9z7VrpfPQ
интересно. у меня сейчас без указателей частота обновления экрана 9,64кадра/сек. что я делаю неправильно?))) ведь это больше чем максимальные 8 кадров в сек
я же примерно прикинул. давайте точнее посчитаем.
скорость зависит от этого куска, правильно?
void SpiData(u8 d){
MOSI1;
SCK1;
SCK0;
SPI_HW_ON;
SPDR = d;
SPI_HW_WAIT;
SPI_HW_OFF;
}
чтобы быть более точным, то прогнал в симуляторе. итого 2.5 мксек вместе в вызовом и возвратом. чтобы вывести 40960 быйт надо 102 400 мксек, что составляет 9.8 кадра. Но никак не 18, согласитесь.
И еще не забывайте что это просто заливка двумя байтами, если надо картинку выводить, то ее надо откуда-то брать, а это уже скорость напополам смело можно делить.
да но ведь разговор идет о просто заливке. если это ускорить то ускорится весь вывод
вот я и спрашиваю как это удалось в той библиотеке. код выложил чтобы понять как это получилось. там все сделано на указателях, и так как без них пока больше не получается ускорить, сделал вывод что дело наверно в них
Уважаемый "jeka_tm" взял ваш пример с бибилеотеками, подключил экранчик nokia 1616 (MOSI 11, SCK 13, CS 10, reset 8) но нечего не происходит (только горит подсветка), подскажите что сделал не так.
P.S. подключал к ардуино мини про
вот рабочий вариант на хардварном SPI
http://yadi.sk/d/CXjuENmaEEwun
файл называется Nokia_1616_HARD
распакуйте в папку с вашими скетчами
reset подключить к 3.3В
Огромное спасибо "jeka_tm".
Теперь встал вопрос: как вывести графику- картинку и чем конвертировить, желательно примерчик, я только пятаюсь всё понять (я новичок в этом деле).
с sd карточки я не пробовал еще, а из флеша без проблемм
вот только памяти сжирает очень много
2байта на цвет*128ширина*160высота= 40960 байт. картинку для всего экрана даже в обычную ардуину не засунешь
нужно цеплять sd карточку. я планирую сделать, как только разберусь с форматом bmp или научусь пользовать функциями библиотеки sd, там уже вроде все реализовано
я конвертирую lcd-image-converter
про sd читал думаю проблем не возникнет. а вот про дисплее не совсем понятно, вроде по теории всо нормально а как применить не знаю, прошу помочь на примере вашего кода и вот этой картинки.
Картинка 16bit (R5G6B5) 16x16:
Вот к примеру что содержится в каждом блоке "0xffff", цвет ? Как эту информицию обработать.
Заранее спасибо.
в инициализации дисплея включен режим 16 бит. вот ваши каждые 2 байта это 1 пиксель
в коде есть функция создания области вывода LCD_Window
создаете область вывода с вашими размерами рисунка
а потом просто цикл и считываете поочередно все байты из массива и рисуете пиксель
только пиксель рисуете не командой LCD_Pixel, а просто передаете данные командой
lcd_write16(color); где color цвет пикселя. чтение из массива слева направо сверху вниз
с командой lcd_write16 будет быстрее немного
можно и LCD_Pixel использовать, но тогда каждой точке надо задавать координаты
а если точки идут подряд можно просто передавать цвет
ffff это цвет. в данном случае белый
т.е. как я понимаю в даном случае это двухмерный масив цветов 16х16 ?
е ещё вопрос как обьявить этот масив как int или byte, просто как я понимаю в тип byte не влезить цвет за раз а в int влезит.
и как правельно передавать значение функции допустем так ?:
Кстати а как изменить контрастность ?
И ещё вопрос посмотрел откоректированную вами библеотеку "Adafruit_ST7735" она очень похожа на тот код что вы дали (фрагментами), возможно ли её легко-быстро переделать под дисплей 1616 или есть подводные камни ?
unsigned int
что то вроде
контрастность особо не удалось изменить, а вам зачем? вроде хорошо работает дисплей
хотя можете даташит покурить на контроллер дисплея
конечно они похожи. ведь и там и там дисплей с 16 битным режимом цвета, размер дисплея, и почти одинаковый интерфейс
зачем переделывать? вообще можно, но я не хочу, в чем смысл если получится почти тоже самое что я дал вам
контрастность особо не удалось изменить, а вам зачем? вроде хорошо работает дисплей
у меня получается если смотреть на него от шлейфа в верх то нехрена не видно, а наоборот сильно перенасыщенно.
конечно они похожи. ведь и там и там дисплей с 16 битным режимом цвета, размер дисплея, и почти одинаковый интерфейс
зачем переделывать? вообще можно, но я не хочу, в чем смысл если получится почти тоже самое что я дал вам
просто там всё структурировано плюс уже готовые примеры есть и их не надо переделовать )))
P.S. нашёл ошибку (или я чегото не правельно делаю) но если перевернуть экран (90 градусов) то получаем по недействующему пикселю по X и Y. вышей из ситуации так:
сделал переменую: byte lcd_mode =0;
и изменил "LCD_Window":
интересно ваше мнение, я ошибаюсь или всё верно ?
насчет контрастности я такого не замечал, смотрел на дисплей первендикулярно в основном
да и изменение контрастности что даст? с одной приведете например в норму, с другой вообще фиг знает что получите. я бы оставил как есть. это вам не ips чтобы углы обзора были хорошие. если так важны углы обзора меняйте дисплей
так переделайте либу и радуйтесь. если не можете тут я вам не помогу. рабочую уже дал
структурируйте эту если что то не устраивает
насчет пикселей надо потестить. я вроде тоже такое замечал, потом как нибудь поправлю
а насчет изменений тестируйте. только or не оставляйте
а насчет изменений тестируйте. только or не оставляйте
Очень интересует почему нельза OR ? и вместо него поставить || ?
Спасибо большое за помощь вы очень сильно помогли, теперь буду подключать sd и работать с bmp (я как понял в нём изображение с заду на перед читать надо).
да пожалуйста
||
насчет bmp я пока не разобрался. если разберетесь киньте код
а зачем голый бмп заливать, если его можно подготовить в читабельный вид перед сбросом на карту.
я делал вот так. на делфи.
Думаю в наш век проблем с размером sd карты не возникнет, а bmp читать то легко, это просто таблица пиксель-RGB, мне просто удобно видеть наглядно когда я подготовливаю флешку на пк.
http://en.wikipedia.org/wiki/BMP_file_format
У меня вот проблема возникла с подключением LCD и SD одновременно, если есть какие нибудь примерчики или разьяснения (желательно подробней) буду очень рад.
читать bmp то легко, только преобразование в 5-6-5 будет забирать время. т.е. следовательно - падение fps.
но я впринцепе фильмы гонять не буду поэтому мне хватит заглаза.
есть программка Easy Graphic Converter
конвертирует в 16 битный формат. на форуме находил инфу что в 5-6-5. но не уверен
попробовал конвертировать. работает. но что там получается хз
Помогите запустить LCD и SD одновремено, всё кроме CS подключено паралельно. По отдельности всё работает.
Ну что никто не знает как переключатся между LCD и SD ?
этот код я делал чтобы выжать макс скорость отрисовки экрана, и для работы с sd и дисплеем не особо подходит. точнее подходит, но нужно один кусок поправить. точнее функцию lcd_write_cmd и lcd_write_dat
изменения одинаковые
а переключаться просто (наверно, я только теоретически догадываюсь). есть пинь SS вроде называется (обычно), короче выбор нужного устройства на SPI выбирая этот пин. и перидически переключаться между дисплеем и карточкой.
как именно это сделать думаю помогут более знающие люди. лешак может поможет, в программировании гораздо сильнее меня. я так начинающий
интересует как работать с файлом картинки сохраненной на SD. допустим один файл одна картинка. формат bmp. возможно уже сконвертированный в формат R5G6B5 (если программа конвертирует как надо)
интересует следующее. так как всю картинку считать оперативки не хватит, нужно по кускам. как это делает? скорее всего считывается например 500 байт а потом выводятся на дисплей и так далее пока не считается вся картинка
вопрос как считывать картинку с SD и как считывать по кускам файл
>вопрос как считывать картинку с SD
Вы одновременно работы SD и экрана уже добились?
нет. я к sd даже не приступал. точнее только считывал только инфу что карточке, и свобоное место
вот думаю как подступится
библиотека конечно есть, но что делать хз. код то готовый был
нет. я к sd даже не приступал. точнее только считывал только инфу что карточке, и свобоное место
Так вот это "считывал инфу на карточке" одноврменно с экраном или нет?
нет. вывод был через w5100 насколько помню
экран я отдельно запускал
нет. вывод был через w5100 насколько помню
экран я отдельно запускал
нет. вывод был через w5100 насколько помню
Ну в теории тут должно быть то же самое. Причем теорию вы сами озвучили выше :) Каждому свой SS пин и перед тем как работать с кем-то из них - включать его, а после - выключать.
Вначале добейтесь тупого:
1. Проинициализировать экран, и вывести на него, скажем цифру один.
2. Отклчить его SS
3. Проинициализировать SD (включив ее SS), что-нибудь с нее прочитать (ту же инфу) и отправить в Serial
4. Выключить SS sd-шки.
5. Включить SS экрана, вывести на него цифру два.
Ну вообщем если эти пункты удайтся пройти то можно сказать "они работают одновременно". Потом можно будет разбиратся как "читать по кускам" и т.п.
В качестве примера можно как раз про w5100 смотреть, там тоже "по очереди" с ними работают.
1. я уже сделал. библиотеку писал же, помогли конечно. но основное я. я туда и FFT выводил уже
2. это могу
3-5 попробую завтра
Так, шо-бы було... когда дойдете до bmp-шки читать, вот такая ссылочка нагуглилась: https://github.com/adafruit/Adafruit-SSD1331-OLED-Driver-Library-for-Arduino/blob/master/examples/bmp/bmp.pde там можно попытатся спионерить чтение, парсинг bmp-шки.
Только уже вывод самой точки на экран, на вызов вашей библиотеки подменить.
о спасибо. завтра будут пробывать. че то я железе зарылся в последнее время
ирония судьбы)))
о спасибо. завтра будут пробывать. че то я железе зарылся в последнее время
Не, не.... до этого еще далеко. У нас еще куча всего проверить будет... маленькими шагами. Только так.
Сделать 5 копипастов из 5-ти мест получить портянку на 15 пейждаунов, а потом пытаться разобраться "что же тут не так" - это не наш метод (ну по крайней мере такое - без меня).
а вам значит можно, а мне нельзя. так нечестно
а вам значит можно, а мне нельзя. так нечестно
Кто сказал что "мне можно"? Я ссылочку оставил что-бы "не потерялась" :)
А сам я тоже, только вначале по частям все проверить, потом начать добавлять по ОДНОЙ фишке.
Только малыми шагами, только так, только одно что-то за раз меняя.
Я вот сам бы ровно по тем же шагам что вам перечислил делал бы. Я вот с новым железом (с програмно части) тоже разбираюсь именно так.
Я ведь не имею вашего экрана... но вообщем-то не первый раз уже через форум разбирается-запускаем, именно пошагово, с железом которое никогда в руках не держал и не видел.
да я так, не спорю. сам бы так сделал. все собирался занятся этим вопросом. все откладывал
но с вашей поддержкой будет проще. не хватает знаний