Быстрый OLED на SPI 1306
- Войдите на сайт для отправки комментариев
Допиливал/модернизировал быстрый GPS логгер на меге2560 (до 20 Гц пишет) который делал два/три года назад, и решил добавить вывод нескольких значений на дисплей. Нужно затратить как можно меньше времени на вывод данных на дисплей, чтобы парсить данные и писать на SD. Поиск решения в сети, нашел сравнение популярных библиотек для OLED, и простой код вывода данных в память контроллера OLED 1306 от Julian's https://www.youtube.com/watch?v=lkWZuAnHa2Y (только символы без графики). Вывод примерно 50шт символов занял у меня около 60 миллисекунд. Затем нашел в сети замену функции shiftout на более быстрый код. Коряво всё объединил, и получилось выводить примерно 50 символов за 19 миллисекунд. Может кому пригодиться мой черновик https://yadi.sk/d/d_DzbelvxjHJL
Удачи.
дак тут недавно мерялись, 1000 символов за порядка 100мс выводили, я как раз на примере OLED 1306 делал, причем по i2c которая как бы медленей SPI. Выкиньте те либы нафиг, их пишут жаждущие славы криворукие тупицы. Начали разбиратся с экраном - уже хороше, продолжайте и получите высокую скорость.
Из интереса глянул код. В общем неплохо, но:
1. В сетапе многократный oledWriteCmd некрасив. Его параметры в массив и циклом перебирать и выполнять oledWriteCmd
2. Для ускорения в oledWriteData убрать uint8_t bitData, bitNotData; uint8_t bitClock, bitNotClock; volatile uint8_t *outData; volatile uint8_t *outClock; Эти переменные инициализируются на основе констант PIN_SDIN и PIN_SCLK. Сделать все это константными выражениями, тогда изменение состояния пина будет однобайтной командой и скорость вырастит раза в 3-4. В помощь:
Если использовать USART MSPI, получается намного быстрее, благодаря наличию буфера передатчика, в отличии от обычного SPI.
И если выводить символы не по точкам, а сразу матрицу, то на порядок быстрее получится.
Я вот так делал. Но до шрифтов не добрался еще. https://github.com/vpetryaev/ST7735
Если использовать USART MSPI, получается намного быстрее, благодаря наличию буфера передатчика, в отличии от обычного SPI.
USART ценный ресурс, и без того в хазяйстве пригодится, а так как делал ТС на любые пины прицепили и ОК. Скорости порядка 10тыс символов в сек врядли мало будет для такого экрана.
И если выводить символы не по точкам, а сразу матрицу, то на порядок быстрее получится.
Так там и не по точкам сделано. По точкам это очень плохо. Особенно если подумать и понять что перед выводом по точкам прийдется еще и очищать область вывода. Т.е. вывод по сути проводится 2 раза, сразу чистим потом выводим по точкам. Но авторы популярных либы не парятся "мелочами" ((
Так никто не мешает USART использовать по очереди в разных целях )
Я уже пытался со шрифтами играться. Но памяти мало. Хочу попробовать потоковую обработку через SD карточку сделать. Идея в том, чтобы в оперативке держать не весь фонт, а только ширину символов. И выводить символы не по порядку их следования в строке, а по порядку их в фонте на SD. То есть, строку любой длины выводим за время, необходимое для считывания фонта с SD, плюс время на вывод прямоугольных блоков с матрицей.
///USART использовать по очереди в разных целях
не... пасиба. А если во время вывода на экран начнут данные поступать, то как?
Тут вобще сталкиваюсь с тем что лучше иметь на шине только одно устройство. Повесил на i2c eeprom и экран. Одна из задач - построить график на экране по точкам из eeprom, до 500 точек. Буфера конечно не хватает. Ну походу и решил что буду брать по точке из памяти, обсчитывать и выводить. Но не подумал что прийдется каждый раз инициализировать чтение заново, т.к. шину надо освобождать для вывода на экран. Облом, тормозня сразу пошла, еще и eeprom 100КГц . Прийдется вторую i2c подымать, чтоб каждое устройство на своей висело. Благо на любые 2 пина цепону.
Тормозить будет. Особенно если SD с файловой системой. А зачем шрифты в оперативку? Все в PROGMEM как ТС и сделал.
/// строку любой длины выводим за время, необходимое для считывания фонта с SD
Время считывания фонта зависит от числа символов в нем, считать все символы из него будет дольше чем только несколько нужных для короткой строки.
Как по моему, если нужен вывод с изысками в шрифтах - все изыски в битмапы, их уже можно и на SD, а собственно через шрифты только изменчивую часть, т.е. цифры. Получим шрифты на 10 (ну 12 если с "-" и ".") символов и несколько битмапов.
Время считывания фонта зависит от числа символов в нем, считать все символы из него будет дольше чем только несколько нужных для короткой строки.
Это не верно, в случае SD карты. В случае NOR флеш будет так, как Вы думаете. В случае NAND будет считан полностью сектор. И размер этого сектора никак не связан с сектором FAT. На больших по объему флешках он может оказаться мегабайтного размера.
И это не считая время, на позиционирование и прочий служебный обмен с SD картой.
В итоге, считать последовательно весь фонт с SD окажется в десятки (если не в сотни) раз быстрее, чем считывать его посимвольно случайным образом. Мне сейчас гуглить некогда, но можете сами поискать по "sd card read access time". Обнаружите, что редко какая карта запрос на чтение любой длины (хоть 1 байт) обработает быстрее, чем за 1 миллисекунду. Но за ту же 1 миллисекунду почти любая карточка легко выдаст килобайт.
То есть, при размере фонта 6х8 время на чтение одного символа (8 байт) будет всего на 1мс меньше (в два раза), чем время на чтение 128 символов (1Кбайт). А значит, строку длинее двух символов быстрее вывести читая фонт последовательно одной командой к карте, чем тремя командами по символам.
Время считывания фонта зависит от числа символов в нем, считать все символы из него будет дольше чем только несколько нужных для короткой строки.
Это не верно, в случае SD карты. В случае NOR флеш будет так, как Вы думаете. В случае NAND будет считан полностью сектор. И размер этого сектора никак не связан с сектором FAT. На больших по объему флешках он может оказаться мегабайтного размера.
NOR/NAND/MLR/СССР - до задницы. Узкое место шина и сюрпризы контроллера карты, для которого SPI вобще опциональная фишка.
И это не считая время, на позиционирование и прочий служебный обмен с SD картой.
А надо считать все. Стартует она очень медлено. И по каталогам лазит не быстро.
В итоге, считать последовательно весь фонт с SD окажется в десятки (если не в сотни) раз быстрее, чем считывать его посимвольно случайным образом. Мне сейчас гуглить некогда, но можете сами поискать по "sd card read access time". Обнаружите, что редко какая карта запрос на чтение любой длины (хоть 1 байт) обработает быстрее, чем за 1 миллисекунду. Но за ту же 1 миллисекунду почти любая карточка легко выдаст килобайт.
Куда выдаст?
Скажите а Вы сами с картой работали (не в смысле в фотоаппарат вставить, а в смысле контроллер запрограмировать чтоб пообщатся с ней), или все впечатления на основе нагугленого? Судя по изложеному то только теория. Коротко о практике. У SD вобще есть 2 режима: быстрій и spi. Причем второй - опционально. Цифры из рекламы - то быстрый, где используют несколько линий (видели наверно сколько контактов у карты?). Мне не встречались ардуиновские платы расширения где этот быстрый разведен. Потому то не для нас. А с spi возможны разные варианты - от того что карта его вобще не поддерживает (а может и поддерживает, но никто не разобрал как) до относительно стабильной работы на частоте до 2МГц. У меня так завелась. Кстати в либе SD обявлена константа для 4Мгц, но нигде не используется))). Может в новых версиях допилят. На какой реально заведется карта определяется в процессе инициализации, от разработчика не зависит. Но если Вы расчитуете получать данные на таких скоростях данные - облом. Первые данные на запрос могут прийти когда бог на душу положит. Подробней - например здесь https://electronix.ru/forum/lofiversion/index.php/t65967.html
<0.5ms – 4562197;
<1.0ms - 52698;
<2.0ms - 4683;
<5.0ms - 2;
<10 ms - 1;
<20 ms - 18;
<50 ms - 1971;
>50 ms - 4;
max - 59.9 ms
Карта непрерывно читается. Измеряется время ожидания начала данных. После тире указано число случаев для данного диапазона.
Для этой карты было 4 случая, когда данные были не готовы дольше 50 мс. Максимальное время ожидания почти 60 мс.
Самая беда в том, что чтение начинает тормозить в среднем по 46 мс но на протяжении секунды:
<+40:44.3ms-12147>
<+50:44.1ms-12123>
<+40:44.2ms-12139>
<+50:44.1ms-12113>
<+50:44.1ms-12091>
<+40:44.1ms-12111>
<+50:43.9ms-12057>
<+50:47.4ms-13023>
<+50:43.8ms-12001>
<+40:45.8ms-12577>
<+50:45.8ms-12573>
<+70:45.5ms-12501>
<+50:45.7ms-12541>
<+40:45.7ms-12551>
<+50:45.4ms-12467>
<+70:46.0ms-12649>
<+40:45.8ms-12573>
<+50:46.3ms-12711>
<+30:26.5ms-7271>
<+40:27.5ms-7541>
Тут формат такое <реальное время или смещение в мс от последнего события : время ожидания данных - число байт переданных в карту до момента ответа>
Затем тот килобайт о котором вы пишите будет теоретически, т.е. по максимуму передаватся 8-10мсек при 1МГц шине. Что уже какбы больше вывода строки из нескольких десятка символов, что обесценивает идею.
На практике еще хуже - потому что ФС, фрагментация, посторонние прерывания и т.д . Не буду писать о всех особенностях буферизации и передачи - я их не знаю. Но знаю что при выводе на экран 320х240 заранее подготовленого bmp (размер и цвет - как надо) потоковая передача, экран на 8 битной шине картинка выводится на взгляд около секунды, может немного больше, т.е. все теже ~8мсек на килобайт. Но это на spi 2МГц. Получается ФС и пр., кроме фрагментации т.к. свежеформатированая карта, сожрало 50% скорости.
ПС. Как вывод. Фонты на карте - плохая идея.
ППС. Еще мой тестовый скетч делал следующее, при запуске выводил содержимое корневого каталога, после чего в цикле выводил картинки из него. Все. А весил 25КБайт. Вся память ушла на поддержку ФС, там в либе исходников более 100КБайт. Так что экономия памяти боком вылезет))
Logik, а зачем в демагогию ударятся?
При чем тут 1МГц, если речь шла о достижении максимальной скорости? И та же Ардуина позволяет работать на 8МГц.
Зачем приплетать интерфейсы, кроме SPI, которые на МК мы все равно не сможем использовать?
При чем тут "Надо считать все", если Вы сами утверждали, что "считать все символы из него будет дольше чем только несколько нужных для короткой строки. "?
Как вообще понимать фразу "NOR/NAND/MLR/СССР - до задницы. Узкое место шина и сюрпризы контроллера карты", если первое самым непосредственным образом влияет на последнее.
А шина у нас с МК всегда SPI и узким местом она будет только при последовательном чтении данных с карты. При случайном чтении нескольких байт из разных мест Вы в SPI точно не упретесь. Я же писал выше: "редко какая карта запрос на чтение любой длины (хоть 1 байт) обработает быстрее, чем за 1 миллисекунду. Но за ту же 1 миллисекунду почти любая карточка легко выдаст килобайт." А уж килобайт по SPI на 8МГц скушать не сложно.
Прийдите, пожалуйста в себя, прекратите растекаться мыслею по древу вместо того, чтобы писать по теме, или я Вам отвечать не буду.
При чем тут 1МГц, если речь шла о достижении максимальной скорости? И та же Ардуина позволяет работать на 8МГц.
Карта не позволяет. Или не любая позволяет, мне таких не попадалось чтоб 8МГц читали, и люди не упоминают. И библиотека. И личный опыт. Я ж вроде все ясно писал.
Зачем приплетать интерфейсы, кроме SPI, которые на МК мы все равно не сможем использовать?
При чем тут "Надо считать все",
При этом "И это не считая время, на ...." Надо считать все. Вы хотяб подумали о том что прийдется инициировать запись в экран для каждого символа строки отдельно в разных местах строки. Причем использовать буфер для матрицы, т.к. одинаковые символы в строке могут быть. И все это тоже время. Его тоже надо считать. И факт того что либы в флеше занимают 25КБайт (ну пусть 20 в чистом виде) при экономии 1,5КБайт на шрифтах тоже надо учитывать ;)
Как вообще понимать фразу "NOR/NAND/MLR/СССР - до задницы. Узкое место шина и сюрпризы контроллера карты", если первое самым непосредственным образом влияет на последнее.
Очевидно как бы быстро не работало железо внутри карты, мы не получим данные быстрей чем шина даст.
А шина у нас с МК всегда SPI и узким местом она будет только при последовательном чтении данных с карты. При случайном чтении нескольких байт из разных мест Вы в SPI точно не упретесь.
Бред. Карта при работе по интерфейсу SD обеспечивает скорость рандомного доступа намного выше чем обеспечивает SPI. Узкое место таки SPI. И почему "нескольких байт из разных мест" байты матрицы символа идут последовательно, весь файл фонта в одном блоке.
Я же писал выше: "редко какая карта запрос на чтение любой длины (хоть 1 байт) обработает быстрее, чем за 1 миллисекунду. Но за ту же 1 миллисекунду почти любая карточка легко выдаст килобайт." А уж килобайт по SPI на 8МГц скушать не сложно.
Все несложно если не делать и не думать. То что Вы выше писали - только Ваша точка зрения ничем не подкрепленная и основывающаяся невесть на чем. Я Вам ссылку дал там вопрос обсосан с всех сторон. Нету там стабильности, может и <0,5мсек а может затупить и на 50мсек и так тупить секунду. Но вам больше по духу маниловщина. В общем сделаете - посмотрим.
... или я Вам отвечать не буду.
"Скажите а Вы сами с картой работали (не в смысле в фотоаппарат вставить, а в смысле контроллер запрограмировать чтоб пообщатся с ней), или все впечатления на основе нагугленого?"
В следующие выходные закончу переписывать SD Library, тогда выложу результаты. Сейчас на дачу еду колеса менять. Некогда.
У Logik сегоня день генерации хэлоуин-бреда. Он явно сегодня чемпион по ХайльГитлеру. )))))))))))))))))))
Осталось подтянуть в тему а5021 и Архата. И торжественное заседание шестой палаты можно считать открытым. ))))))))))))
Хотите результата? Юзайте нормальные МК на переписаной ФатФс от Чена. Ну или СПИ флэш память. Тогда вообще всё с максимальной теоретической совпадать будет. И нехрен на МК-инвалидах с ИДЕ-инвалидом пенять на инвалид-результат.