Горячее
Лучшее
Свежее
Подписки
Сообщества
Блоги
Эксперты
Войти
Забыли пароль?
или продолжите с
Создать аккаунт
Я хочу получать рассылки с лучшими постами за неделю
или
Восстановление пароля
Восстановление пароля
Получить код в Telegram
Войти с Яндекс ID Войти через VK ID
Создавая аккаунт, я соглашаюсь с правилами Пикабу и даю согласие на обработку персональных данных.
ПромокодыРаботаКурсыРекламаИгрыПополнение Steam
Пикабу Игры +1000 бесплатных онлайн игр
Классическая игра в аркадном стиле для любителей ретро-игр. Защитите космический корабль с Печенькой (и не только) на борту, проходя уровни.

Arkanoid Pikabu

Арканоид, Аркады, Веселая

Играть

Топ прошлой недели

  • AlexKud AlexKud 40 постов
  • unimas unimas 13 постов
  • hapaevilya hapaevilya 2 поста
Посмотреть весь топ

Лучшие посты недели

Рассылка Пикабу: отправляем самые рейтинговые материалы за 7 дней 🔥

Нажимая кнопку «Подписаться на рассылку», я соглашаюсь с Правилами Пикабу и даю согласие на обработку персональных данных.

Спасибо, что подписались!
Пожалуйста, проверьте почту 😊

Помощь Кодекс Пикабу Команда Пикабу Моб. приложение
Правила соцсети О рекомендациях О компании
Промокоды Биг Гик Промокоды Lamoda Промокоды МВидео Промокоды Яндекс Директ Промокоды Отелло Промокоды Aroma Butik Промокоды Яндекс Путешествия Постила Футбол сегодня
0 просмотренных постов скрыто
ShuricU
ShuricU
1 год назад

Orange PI PC: Установка операционной системы (Android, Ubuntu)⁠⁠

В этом видео показан процесс установки операционных систем Ubuntu, Android на одноплатный компьютер Orange Pi PC.

В этом видео показан процесс установки операционных систем Ubuntu, Android на одноплатный компьютер Orange Pi PC.

Ссылка на образы операционных систем

http://www.orangepi.org/html/serviceAndSupport/index.html

логин и пароль на OS ubuntu: user: root , password: orangepi

Ссылка на группу где Вы можете задать вопросы об Orange Pi PC, а также технические вопросы

https://vk.com/public211863062

Ссылки на программы, которые используются в этом видео

https://www.7-zip.org

https://www.balena.io/etcher/

https://chinagadgetsreviews.com/download-latest-version-of-p...

https://www.sdcard.org/downloads/formatter/sd-memory-card-fo...

Все программы, Вы используете на свой страх и риск

Показать полностью
Linux Raspberry pi Orange pi Orange Android Гаджеты Видео YouTube
4
5670
monobogdan
monobogdan
1 год назад
TECHNO BROTHER

Сам себе Linux смартфон: Как я выкинул Android и написал свою прошивку с нуля⁠⁠

Сам себе Linux смартфон: Как я выкинул Android и написал свою прошивку с нуля Гаджеты, Смартфон, Телефон, Покупка, Китайцы, Fly, Моддинг, Программирование, 2D, Своими руками, Одноплатный компьютер, Raspberry pi, Orange pi, Инженерия, Электроника, Android, Linux, Unix, iPhone, Мобильные телефоны, Видео, Без звука, YouTube, Длиннопост



К огромному сожалению, старые смартфоны всё чаще и чаще находят своё пристанище в мусорном баке. К прошлым, надежным «друзьям» действует исключительно потребительское отношение — чуть устарел и сразу выкинули, словно это ненужный мусор. И ведь люди даже не хотят попытаться придумать какое-либо применение гаджетам прошлых лет! Отчасти, это вина корпораций — Google намеренно тормозит и добивает довольно шустрые девайсы. Отчасти — вина программистов, которые преследуют исключительно бизнес-задачи и не думают об оптимизации приложений совсем. В один день я почувствовал себя Тайлером Дёрденом от мира IT и решил бросить вызов проприетарщине: написать свою прошивку для уже существующего смартфона с нуля. А дабы задачка была ещё интереснее, я выбрал очень распространенную и дешевую модель из 2012 года — Fly IQ245 (цена на барахолках — 200-300 рублей). Кроме того, у этого телефона есть сразу несколько внешних шин, к которым можно подключить компьютер или микроконтроллер, что даёт возможность использовать его в качестве ультрадешевого одноплатника для DIY-проектов. Получилось ли у меня реализовать свои хотелки? Читайте в статье!

Мотивация


Честно сказать, идея попытаться реализовать свою прошивку мне пришла ещё давно. Однако, дабы не завлекать опытного читателя кликбейтом, я сразу поясню, в чём заключается «прошивка с нуля»:

  1. Мы всё ещё используем Linux: в качестве ядра мы продолжаем использовать образ Linux, предоставленный нам производителем. Написание прошивки полностью с нуля заняло бы очень много времени (особенно без схемы на устройство). Однако, мы вообще не загружаем Android никаким образом.

  2. Мы не используем библиотеки AOSP: наша прошивка без необходимости не использует никаких библиотек уже имеющегося образа Android. Вся работа с железом происходит с помощью низкоуровневого API Linux. Это значит, что отрисовка графики, звук, управление ресурсами и питанием ложится полностью на нас.

  3. Прошивка может запускать только нативные программы: да, это тоже камень в сторону Android. Изначально, наша прошивка умеет запускать только нативные программы, написанные на C. Причём она экспортирует собственное C API — дабы приложения могли использовать всю мощь нашего смартфона в виде простого и понятного набора методов.

Сам себе Linux смартфон: Как я выкинул Android и написал свою прошивку с нуля Гаджеты, Смартфон, Телефон, Покупка, Китайцы, Fly, Моддинг, Программирование, 2D, Своими руками, Одноплатный компьютер, Raspberry pi, Orange pi, Инженерия, Электроника, Android, Linux, Unix, iPhone, Мобильные телефоны, Видео, Без звука, YouTube, Длиннопост



Проектов по выкидыванию Android из, собственно, Android-смартфонов как минимум несколько: UBPorts — бывший Ubuntu Touch, FireFox OS и его наследник Kai OS и конечно же, postmarketOS. Отчасти можно сюда отнести и Sailfish OS — но там образы имеются в основном на смартфоны от Sony. Все эти проекты объединяет сложность портирования и невозможность их завести на устройствах без исходного кода ядра. Даже если у вас есть исходный код ядра, но, например, устройство использует ядро 2.6 — навряд-ли вы сможете завести современный дистрибутив на нём.

Другой вопрос в том, что можно использовать полу-baremetal подход, когда от Linux берется практически минимальный функционал. Всё, что мы имеем — busybox, libc и низкоуровневый доступ к железу, благодаря API самого ядра. Как под это всё программировать — я рассказывал впрошлойстатье. Этот же подход мы будем использовать и сейчас — как иллюстрация реального применения подобного способа.

Итак, что наша прошивка должна уметь:

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

  • Уметь звонить и работать с модемом: общение с модемом происходит посредством AT-команд — общепринятого в индустрии стандарта. Однако в случае нашего устройства, есть м-а-а-а-ленький нюанс, о котором я расскажу позже.

  • Иметь механизм приложений: мы ведь не будем хардкодить все «экраны» в прошивке в виде кучи стейтов, верно? Для этого у нас должен быть простой и понятный механизм слинкованных с прошивкой приложений.

  • Обрабатывать ввод: обработка тачскрина и жестов — это задача подсистемы ввода.

  • Реализовывать анимированный UI: здесь всё очевидно, наша прошивка должна иметь готовые элементы пользовательского интерфейса для будущих приложений: кнопки, текстовые поля и т. д. О деталях реализации этой подсистемы, я расскажу ниже (а реализовал я её очень необычно для такой системы).


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

Аппаратная часть


В качестве смартфона для нашего проекта, я выбрал популярную бюджетную модель из 2012 года — Fly IQ245 Wizard. Это простенький китайский смартфон, который работал на базе популярного в прошлом 2G-чипсета: MediaTek MT6573, да и стоил около 2х тысяч рублей новым. Однако вот в чём суть: мне удалось заставить работать «медиатековский» модем и даже позвонить с него на свой основной телефон, но… только ввод и вывод данных из звукового тракта модема происходит через звуковую подсистему Android — к которой доступа у нас нет!

Сам себе Linux смартфон: Как я выкинул Android и написал свою прошивку с нуля Гаджеты, Смартфон, Телефон, Покупка, Китайцы, Fly, Моддинг, Программирование, 2D, Своими руками, Одноплатный компьютер, Raspberry pi, Orange pi, Инженерия, Электроника, Android, Linux, Unix, iPhone, Мобильные телефоны, Видео, Без звука, YouTube, Длиннопост



Именно поэтому, мы идём на очень хитрый и занимательный костыль: мы распаяем внешний модем сами! В качестве радиомодуля у нас выступит модуль SIM800 от компании SIMCOM. И даже он очень близок к нашему смартфону в аппаратном плане: ведь в основе этого модуля лежит популярнейший чипсет из кнопочников тех лет: MediaTek MT6261D. Преимущество SIM800 в его цене — он стоит пару сотен рублей, так что по карману выбор модема не влияет.

Сам себе Linux смартфон: Как я выкинул Android и написал свою прошивку с нуля Гаджеты, Смартфон, Телефон, Покупка, Китайцы, Fly, Моддинг, Программирование, 2D, Своими руками, Одноплатный компьютер, Raspberry pi, Orange pi, Инженерия, Электроника, Android, Linux, Unix, iPhone, Мобильные телефоны, Видео, Без звука, YouTube, Длиннопост


На весу паять крайне неудобно. В финальном варианте перепаяю нормально.

Но как его подключать? SIM800 общается с другими устройствами посредством протокола UART — универсальный асинхронный приемо-передатчик. И вот тут мы включаем смекалочку. Разбираем устройство и видим то, что я пытаюсь долгое время донести до моих читателей — аж два канала UART: один практически посередине, второй справа. Нам нужны пятачки TXD4 и RXD4:

Сам себе Linux смартфон: Как я выкинул Android и написал свою прошивку с нуля Гаджеты, Смартфон, Телефон, Покупка, Китайцы, Fly, Моддинг, Программирование, 2D, Своими руками, Одноплатный компьютер, Raspberry pi, Orange pi, Инженерия, Электроника, Android, Linux, Unix, iPhone, Мобильные телефоны, Видео, Без звука, YouTube, Длиннопост



Обычно на этот канал UART летят логи ядра, которые можно без проблем отключить минорной правкой U-Boot в HEX-редакторе. Впрочем, модем никак не реагирует на «мусор» из консоли и просто отвечает ошибками — хватит лишь очистить буфер сообщений для того, чтобы все работало нормально. Подпаиваемся к UART'у с помощью преобразователя — у меня оным выступает ESP32 с выпаянным чипом.

Сам себе Linux смартфон: Как я выкинул Android и написал свою прошивку с нуля Гаджеты, Смартфон, Телефон, Покупка, Китайцы, Fly, Моддинг, Программирование, 2D, Своими руками, Одноплатный компьютер, Raspberry pi, Orange pi, Инженерия, Электроника, Android, Linux, Unix, iPhone, Мобильные телефоны, Видео, Без звука, YouTube, Длиннопост
Сам себе Linux смартфон: Как я выкинул Android и написал свою прошивку с нуля Гаджеты, Смартфон, Телефон, Покупка, Китайцы, Fly, Моддинг, Программирование, 2D, Своими руками, Одноплатный компьютер, Raspberry pi, Orange pi, Инженерия, Электроника, Android, Linux, Unix, iPhone, Мобильные телефоны, Видео, Без звука, YouTube, Длиннопост


Увидели логи? Замечательно, пора попытаться что-то отправить на ПК и с ПК. UART работают без тактовых сигналов и зависит исключительно от старт/стоп битов и бодрейта, который на устройствах MediaTek равен 921600. TXD4 и RXD4 обнаруживаются в системе на консоли/dev/ttyMT3. Пробуем что-то отправить: всё работает!

Сам себе Linux смартфон: Как я выкинул Android и написал свою прошивку с нуля Гаджеты, Смартфон, Телефон, Покупка, Китайцы, Fly, Моддинг, Программирование, 2D, Своими руками, Одноплатный компьютер, Raspberry pi, Orange pi, Инженерия, Электроника, Android, Linux, Unix, iPhone, Мобильные телефоны, Видео, Без звука, YouTube, Длиннопост



Вот теперь-то можно подключить наш внешний модем и попытаться пообщаться с ним, отправив тестовую командуAT. Модем отвечаетOK! На этот раз я работаю с смартфоном из режимаFactory mode— практически тоже самое, что и режим recovery, но позволяющий, например, получить доступ к камере устройства. Простая и понятная схема, поясняющая что и куда подключать:

Сам себе Linux смартфон: Как я выкинул Android и написал свою прошивку с нуля Гаджеты, Смартфон, Телефон, Покупка, Китайцы, Fly, Моддинг, Программирование, 2D, Своими руками, Одноплатный компьютер, Raspberry pi, Orange pi, Инженерия, Электроника, Android, Linux, Unix, iPhone, Мобильные телефоны, Видео, Без звука, YouTube, Длиннопост



На этом модификация аппаратной частипоказакончена. Пора переходить к реализации софта! Я решил разделить материал на каждый модуль, который я реализовывал — дабы вам был понятен процесс разработки и отладки прошивки!

Заставляем смартфон запускать нашу прошивку


На этот раз я решил загружать смартфон из режима рекавери. Однако никто не мешает в будущем просто прошить раздел recovery вместо boot и получить прямую загрузку прямо в нашу прошивку. Время такой загрузки будет заниматься ~3-4 секунды с холодного старта. Очень даже ничего.

Сам себе Linux смартфон: Как я выкинул Android и написал свою прошивку с нуля Гаджеты, Смартфон, Телефон, Покупка, Китайцы, Fly, Моддинг, Программирование, 2D, Своими руками, Одноплатный компьютер, Raspberry pi, Orange pi, Инженерия, Электроника, Android, Linux, Unix, iPhone, Мобильные телефоны, Видео, Без звука, YouTube, Длиннопост



Я взял уже готовый образ TWRP для своего смартфона и пропатчил его, дабы сам рекавери не мешал своим интерфейсом. Для этого я распаковал образ recovery.img с помощью MtkImgTools и убрал в init.rc запуск службы /sbin/recovery. После этого, я залил прошивку обратно на устройство и получил подобную свободу действий — консоль через USB и чистый холст в виде смартфона! Старые смартфоны на чипсетах MediaTek шьются через USB только после замыкания тест-поинта — на моем аппарате его местонахождение очевидно. Замыкаем контакты между собой, подключаем смартфон без АКБ к ПК и ждем прошивки:

Сам себе Linux смартфон: Как я выкинул Android и написал свою прошивку с нуля Гаджеты, Смартфон, Телефон, Покупка, Китайцы, Fly, Моддинг, Программирование, 2D, Своими руками, Одноплатный компьютер, Raspberry pi, Orange pi, Инженерия, Электроника, Android, Linux, Unix, iPhone, Мобильные телефоны, Видео, Без звука, YouTube, Длиннопост



Теперь можно деплоить программы! Важный нюанс: в отличии от Makefile из прошлой статьи, для Android 2.3 параметр -fPIE нужно убрать — иначе динамический линкер (/sbin/linker) будет вылетать в segmentation fault.

Сам себе Linux смартфон: Как я выкинул Android и написал свою прошивку с нуля Гаджеты, Смартфон, Телефон, Покупка, Китайцы, Fly, Моддинг, Программирование, 2D, Своими руками, Одноплатный компьютер, Raspberry pi, Orange pi, Инженерия, Электроника, Android, Linux, Unix, iPhone, Мобильные телефоны, Видео, Без звука, YouTube, Длиннопост

❯ Графическая подсистема


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

Сам себе Linux смартфон: Как я выкинул Android и написал свою прошивку с нуля Гаджеты, Смартфон, Телефон, Покупка, Китайцы, Fly, Моддинг, Программирование, 2D, Своими руками, Одноплатный компьютер, Raspberry pi, Orange pi, Инженерия, Электроника, Android, Linux, Unix, iPhone, Мобильные телефоны, Видео, Без звука, YouTube, Длиннопост



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

В случае с этим устройством (и большинством старых устройств), формат пикселя оказался RGB565 — т. е. 5 бит красный, 6 бит синий, 5 бит зеленый. Конвертация форматов пикселей всегда была занозой в заднице для программных рендереров, поскольку занимает дополнительное время, которое обратно зависимо от размера дисплея. Изначально я решил выделить буфер в том же формате, что и фреймбуфер, но затем решил сделать классический и самый портативный формат — RGB888 (24х-битный цвет), а при копировании кадра на экран, на лету делать преобразования цвета:

Сам себе Linux смартфон: Как я выкинул Android и написал свою прошивку с нуля Гаджеты, Смартфон, Телефон, Покупка, Китайцы, Fly, Моддинг, Программирование, 2D, Своими руками, Одноплатный компьютер, Raspberry pi, Orange pi, Инженерия, Электроника, Android, Linux, Unix, iPhone, Мобильные телефоны, Видео, Без звука, YouTube, Длиннопост

Очень важный нюанс, который я не упомянул в предыдущей статье: на устройствах прошлых лет для обновления фреймбуфера необходимо послать структуру var_screeninfo, где хотя бы что-то изменено, иначе никаких изменений мы не увидим. Этот же костыль используется в родном recovery для отрисовки, а судя по исходникам драйвера fb, «правильный» способ обновить экран — послать драйверу ioctl (который я пока что не пробовал).

После того, как я смог управлять дисплеем, я решил загрузить и отобразить какую-нибудь картинку. Пусть это будут обои для нашей прошивки:

Сам себе Linux смартфон: Как я выкинул Android и написал свою прошивку с нуля Гаджеты, Смартфон, Телефон, Покупка, Китайцы, Fly, Моддинг, Программирование, 2D, Своими руками, Одноплатный компьютер, Raspberry pi, Orange pi, Инженерия, Электроника, Android, Linux, Unix, iPhone, Мобильные телефоны, Видео, Без звука, YouTube, Длиннопост

Загрузчик TGA сильно не поменялся: я таскаю его в неизменном виде из проекта в проект. Он поддерживает любые форматы пикселя, кроме палитровых, но я его искусственн ограничиваю на RGB888 и RGBA8888 — для поддержки обычных картинок и картинок с альфа-каналом. После этого, я написал не очень шустрые, но достаточно универсальные методы для отрисовки картинок. Для больших участков кода, я буду использовать pastebin, поскольку на Пикабу до сих пор не добавили ни подсветки синтаксиса, не нормальный перенос форматирования табов :(

__inline void __ClipPrimitive(CFrameBuffer* fbDesc, int* dw, int* dh){ if - Pastebin.com

PutPixel желательно заинлайнить в будущем. В целом, сама отрисовка работает достаточно быстро, но поскольку рендеринг выполняется на ЦПУ — рано или поздно мы упремся в количество картинок на экране. Есть некоторые оптимизации: например, непрозрачные картинки можно просто коприовать сканлайнами прямо в задний буфер.

Сразу же реализовываем методы для рисования шрифтов: они у нас будут совсем простенькими — только моноширинные (все символы имеют одинаковую ширину) и растровыми (для каждого размера придется «запекать» несколько шрифтов). Для этого я написал маленькую программку, которая рисует виндовые шрифты прямо в наш самопальный формат:

Сам себе Linux смартфон: Как я выкинул Android и написал свою прошивку с нуля Гаджеты, Смартфон, Телефон, Покупка, Китайцы, Fly, Моддинг, Программирование, 2D, Своими руками, Одноплатный компьютер, Raspberry pi, Orange pi, Инженерия, Электроника, Android, Linux, Unix, iPhone, Мобильные телефоны, Видео, Без звука, YouTube, Длиннопост

Формат примитивнейший:

1 байт говорит нам о размере шрифта и далее идут 255 изображений символов. Да, это не очень эффективно т.к попадают пустые символы из ASCII-таблицы, но в будущем это можно поправить.

Прозрачность в символах обеспечивает фоновый цвет Magena — ярко-розовый. Я не стал делать дополнительный альфа-канал, т. к. иначе будут серьезные лаги при выводе большого количества текста.

Теперь у нас есть отображение картинок и текста! Что с этим можно сделать?

❯ Обработка ввода

Сам себе Linux смартфон: Как я выкинул Android и написал свою прошивку с нуля Гаджеты, Смартфон, Телефон, Покупка, Китайцы, Fly, Моддинг, Программирование, 2D, Своими руками, Одноплатный компьютер, Raspberry pi, Orange pi, Инженерия, Электроника, Android, Linux, Unix, iPhone, Мобильные телефоны, Видео, Без звука, YouTube, Длиннопост
Сам себе Linux смартфон: Как я выкинул Android и написал свою прошивку с нуля Гаджеты, Смартфон, Телефон, Покупка, Китайцы, Fly, Моддинг, Программирование, 2D, Своими руками, Одноплатный компьютер, Raspberry pi, Orange pi, Инженерия, Электроника, Android, Linux, Unix, iPhone, Мобильные телефоны, Видео, Без звука, YouTube, Длиннопост

Пока что здесь не хватает обработки «хардварных» кнопок — домой, меню, назад и т. п. Однако в будущем это всё можно реализовать!

❯ Анимация


Не забыл я и про анимации. Ну кому с такими ресурсами нужен неанимированный топорный интерфейс? Пусть лучше будет анимированный, пусть и примитивный!

Аниматор напоминает оный из ранних версий Android: он имеет фиксированный набор свойств, которые умеет интерполировать в промежутках определенного времени. Если простыми словами: то он оперирует линейными отрезками времени a и b, в промежутке которых мы имеем значение «прогресса» — которое даёт нам результат от 0.0f (начало анимации) до 1.0f (конец анимации). Пока время тикает до необходимого интервала (duration), аниматор интерполирует заранее назначенные ему поля до нужных значений.

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

Сам себе Linux смартфон: Как я выкинул Android и написал свою прошивку с нуля Гаджеты, Смартфон, Телефон, Покупка, Китайцы, Fly, Моддинг, Программирование, 2D, Своими руками, Одноплатный компьютер, Raspberry pi, Orange pi, Инженерия, Электроника, Android, Linux, Unix, iPhone, Мобильные телефоны, Видео, Без звука, YouTube, Длиннопост


❯ Модем


Как я уже говорил раннее, работа с модемом происходит посредством AT-команд. Лучше всего обрабатывать ввод-вывод модема из отдельного потока, поскольку он может отвечать довольно медленно и тормозить UI-поток основной программы, вызывая лаги. В SIM800 уже реализован весь GSM-стек, в том числе декодирование и вывод звука через встроенный усилитель с фильтром — остается только подключить динамики и микрофон от нашего телефона. Пока что я подсобрал аудиотракт на том, что было под рукой — микрофон от нерабочего смартфона и динамик от планшета, но для проверки этого хватает:

Сам себе Linux смартфон: Как я выкинул Android и написал свою прошивку с нуля Гаджеты, Смартфон, Телефон, Покупка, Китайцы, Fly, Моддинг, Программирование, 2D, Своими руками, Одноплатный компьютер, Raspberry pi, Orange pi, Инженерия, Электроника, Android, Linux, Unix, iPhone, Мобильные телефоны, Видео, Без звука, YouTube, Длиннопост

Важный нюанс: по умолчанию, tty-устройства в Linux работают по терминальному принципу — т. е. дробят транзакции по символу окончания строки (\n), имеют ограниченный буфер и т. д. Для нормальной работы в условиях модема — когда фактически длина ответа неизвестна, а в сам ответ могут «вклиниваться» Unsolicited-команды (своеобразные флаги о состоянии от модема, которые могут прийти в произвольное время — т. е. при входящем звонке, модем начнёт флудить RING в терминал), необходимо иметь возможность точно прочитать весь буфер до конца и парсить данные «по месту». Для этого используется raw-режим терминала:

tcgetattr(modemFd, &tio);

tio.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);

tio.c_oflag &= ~(OPOST);

tio.c_cflag |= (CS8);

tio.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);

tcsetattr(modemFd, TCSAFLUSH, &tio);

После чего можно запросить состояние модема:

Сам себе Linux смартфон: Как я выкинул Android и написал свою прошивку с нуля Гаджеты, Смартфон, Телефон, Покупка, Китайцы, Fly, Моддинг, Программирование, 2D, Своими руками, Одноплатный компьютер, Raspberry pi, Orange pi, Инженерия, Электроника, Android, Linux, Unix, iPhone, Мобильные телефоны, Видео, Без звука, YouTube, Длиннопост

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

void CModem::Dial(char* number){ if(strlen(number) > 32) return; cha - Pastebin.com

Пытаемся позвонить с помощью метода Dial и видим, что всё работает! Это очень круто! А теперь, конечно же, самое время переходить к реализации того, чего вы ждали — пользовательского интерфейса!

❯ Главный экран


К выбору концепции для интерфейса, я поступил максимально просто — «слизал» дизайн первых версий iOS. Как по мне, это одни из самых красивых версий iOS вообще — все эти приятные градиенты и переливания. Конечно, я не так крут, как инженеры Apple, да и мощного UI-фреймворка у меня пока что нет, поэтому я приступил к реализации с «минимальным» функционалом.

Сам себе Linux смартфон: Как я выкинул Android и написал свою прошивку с нуля Гаджеты, Смартфон, Телефон, Покупка, Китайцы, Fly, Моддинг, Программирование, 2D, Своими руками, Одноплатный компьютер, Raspberry pi, Orange pi, Инженерия, Электроника, Android, Linux, Unix, iPhone, Мобильные телефоны, Видео, Без звука, YouTube, Длиннопост



Начал я с разделения главного экрана на модули и продумывания архитектуры основного «лаунчера». У нас есть статусбар, который рисуется поверх всех приложений, полка с приложениями — AppDrawer и сами экраны приложений, унаследованные от суперкласса CScreen.

class CScreen{protected: CAnimator* windowAnimator;public: CScreen(); - Pastebin.com

На данный момент, отрисовка достаточно примитивная: сначала рисуются фоновые обои, затем, если нет никаких активных экранов — AppDrawer и в самом конце рисуется статусбар и всевозможные оверлеи.

void CLauncher::DrawAppDrawer(){ for(int i = 0; i < sizeof(Apps) / sizeof(CA - Pastebin.com

Практически сразу я решил обкатать анимационную «систему» и добавить первые анимашки — выезжающий статусбар и анимация а-ля айфон:

animator = new CAnimator();

animator->SetTranslation(0, -imFiller->Height, 0, 0);

animator->Run();

Выглядит симпатичненько. Если я смогу поднять хардварный GLES, то это получится сделать в разы плавнее и шустрее — не хуже айфонов тех лет! Реализация самого статусбара примитивненькая, но вполне рабочая:

gLauncher->Graphics->DrawImage(imFiller, animator->X, animator->Y);

gLauncher->Graphics->DrawImage(imBattery[(int)gLauncher->PowerManager->GetBatteryLevel()], imFiller->Width - imBattery[0]->Width - 5, animator->Y + 5);

char timeFmt[64];

time_t _time = time(0);

tm* _localTime = localtime(&_time);

strftime((char*)&timeFmt,

sizeof(timeFmt), "%R", _localTime);

gLauncher->Graphics->DrawString(gLauncher->Font, (char*)&timeFmt, 0, 0);

Кроме этого, я сразу же реализовал предварительный механизм приложений в системе — пока что они слинкованы статически с основным лаунчером. Для этого есть структура CAppDesc, которая содержит минимально-необходимую информацию для показа информации о приложении и фабрику для создания его основного экрана.

Обратите внимание на удобство примененного подхода Immediate GUI. Нам понадобился новый элемент интерфейса, который описывает кнопку номеронабирателя? Мы просто реализовываем ещё один метод, который берет за основу стандартную кнопку и дорисовывает к ней текст. Всё крайне просто и понятно, хотя на данный момент слишком захардкожено. :)

❯ Звоним!


Пришло время совершить первый звонок с нашей по настоящему кастомной прошивки. Набираем номерок и…

Сам себе Linux смартфон: Как я выкинул Android и написал свою прошивку с нуля Гаджеты, Смартфон, Телефон, Покупка, Китайцы, Fly, Моддинг, Программирование, 2D, Своими руками, Одноплатный компьютер, Raspberry pi, Orange pi, Инженерия, Электроника, Android, Linux, Unix, iPhone, Мобильные телефоны, Видео, Без звука, YouTube, Длиннопост



Да, всё работает и мы без проблем можем дозвониться :)

❯ Заключение


Конечно же, это далеко не весь функционал, необходимый любому современному смартфону. Здесь много чего еще нужно реализовать хотя бы для соответствия уровню бюджетных кнопочных телефонов: телефонную книгу, поддержку СМС/ММС, мультимедийный функционал с играми. Однако начало уже положено и самая необходимая часть модулей реализована. Этот проект очень занимательный для меня и я горд, что смог не на словах, а на деле показать вам, моим читателям, возможности моддинга совершенно NoName-устройств, без каких либо опознавательных знаков…

Моя задача заключается в том, чтобы показать вам возможности использования старых телефонов не только в потребительских, но и в гиковских DIY-сферах. Судите сами: огромный классный дисплей, емкостной тачскрин, готовый звук, камера — и всё это за каких-то пару сотен рублей. Главное показать людям, как всю эту мощь использовать в своих целях и делать совершенно новые устройства из существующих, а не выбрасывать их на помойку!
Сейчас смартфоны, подобные Fly из этого поста стоят копейки, а портировать на них прошивку можно без каких-либо трудностей. Я очень надеюсь, что после этого поста читатели попытаются сделать что-то своё из старых смартфонов, благо свои наработки я выкладываю на GitHub!

Показать полностью 23 2
[моё] Гаджеты Смартфон Телефон Покупка Китайцы Fly Моддинг Программирование 2D Своими руками Одноплатный компьютер Raspberry pi Orange pi Инженерия Электроника Android Linux Unix iPhone Мобильные телефоны Видео Без звука YouTube Длиннопост
442
2021
monobogdan
monobogdan
1 год назад
TECHNO BROTHER

Подключаем дисплей к любому одноплатнику с SPI: Большой мануал о поиске экранчиков для ваших проектов⁠⁠

Подключаем дисплей к любому одноплатнику с SPI: Большой мануал о поиске экранчиков для ваших проектов Linux, Полезное, Гаджеты, C++, Своими руками, Программирование, Графика, 2D, Покупка, Orange Pi, Raspberry Pi, Одноплатный компьютер, Драйвер, Дисплей, Разработка, Длиннопост



Сейчас появилось достаточно много различных дешевых одноплатников с очень достойными характеристиками, которые вполне можно назвать экономичными и портативными. Однако очень часто встает вопрос вывода изображения на дисплей: к сожалению, в подобные устройства обычно ставят урезанные версии чипсетов без видеовыхода на обычные матрицы. Конечно в них практически всегда есть HDMI, но это совершенно не выход для портативного устройства: прожорливый чип скалера будет очень негативно влиять на время работы от АКБ. Да и сами подобные дисплеи очень дорогие: почти 2.000 рублей за матрицу со скалером — это действительно бьет по карману. Сегодня я расскажу Вам о существующих протоколах для дисплеев, подскажу, как применить экранчики от старых навигаторов/мобильников и мы подключим с вами SPI-дисплей к одноплатнику без видеовыхода. Причем мы реализуем как просто библиотеку, которая позволяет выводить произвольную графику из ваших программ, так
и службу, которая будет напрямую копировать данные из фреймбуфера и преобразовывать в формат для нашего дисплея. Интересно? Тогда жду вас в статье!

Предисловие


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

  • MIPI DSI — дифференциальный многоканальный LVDS протокол. Если говорить совсем условно — то это эдакий быстрый низковольтный SPI, который для передачи одного байта использует минимум 4 линии — D+, D-, CLK+, CLK-, где фактических линии две, но для подавления помех используются доп. линии инвертированной полярности, из которых затем вычитаются положительные. Этот протокол позволяет подключать дисплеи очень высокого разрешения и используется практически во всех современных смартфонах. Насколько мне известно, такие дисплеи имеют собственную видеопамять размером с буфер кадра (т.е для 1920х1080х3 дисплея — ~5мб).

  • TTL/RGB — относительно простой для реализации протокол, очень похож на VGA, но по сути является цифровым: для передачи пикселей используются отдельные линии — например, 5 битов красного, 6 битов синего и 5 битов зеленого (RGB565). Не требует инициализации и обычно не имеет системы команд — пиксели синхронизируются с помощью тактовых сигналов HSYNC/VSYNC. Эти крайне дешевые дисплеи можно встретить на старых китайских игровых консолях, планшетах (до 720p) и автомобильных навигаторах (о них ниже), а также КПК (но на них даташиты найти сложнее). На МК и одноплатниках их использовать можно, но для этого нужно большое кол-во пинов (~18). У таких дисплеев нет собственной памяти, поэтому обновлять картинку нужно всегда, иначе будет белый дисплей. Есть еще аналоговая разновидность, практически 1 в 1 похожая на VGA, используется в ранних автомобильных телевизорах — но ей управлять сложнее из-за кучи различных тактовых сигналов.

  • 8080 — 8 или 16-битная параллельная шина, именно этот протокол использовали большинство телефонов в середине-конце нулевых, а его 16-битная разновидность использовалась в ультрадешевых китайских смартфонах начала 2010-х (Fly Jazz, Explay N1, Fly Era Nano 1, Fly Wizard — дисплеи всех этих копеечных на вторичке телефонов можно использовать и в своих проектах!). Занимает минимум 11 пинов — 8 на данные, 2 на сигналы RD/WR (он определяет, хотим ли мы сейчас что-то прочитать или записать) и 1 DC (определяет, куда мы пишем данные — в регистры, или в видеопамять). Такие дисплеи имеют собственную ОЗУ, поэтому необязательно гонять в них данные постоянно.

  • SPI — популярный протокол, который используется и в DIY-проектах и возможно в китайских старых MP3-плеерах (информация пока не точная). Отличается тем, что требует всего 3 пина для подключения — MOSI (данные), CLK (тактовая частота) и DC (имеет ту же роль, что и в 8080 дисплеях). Он гораздо предпочтительнее для использования в домашних проектах, поскольку хардварный SPI есть во многих микроконтроллерах/одноплатниках, а частенько к нему в комплект идёт DMA, позволяя разгрузить процессор. Кроме того, эти дисплеи использовали в телефонах начала нулевых — Nokia и Siemens точно использовала именно их. Причём у Siemens сами пины не на шлейфе, а «прижимаются» — бери да подпаивайся, только бустер подсветки до 12в придётся сделать.

  • I2C — редкий протокол для дисплеев из-за медлительности. Сейчас используется в недорогих OLED-модулях низкого разрешения, использовался в мобильниках самого начала нулевых (Ericsson) и Motorola C350.


Я не стал упоминать «большие» протоколы типа HDMI или eDP — они так или иначе, в физическом плане близки к MIPI DSI. Как видите — протоколов много и самых разных, соответственно и дисплеи нужно искать в разных местах. Дешевые DIY-дисплеи можно найти за довольно разумные деньги на алике — 1.8" матрицы на момент написания статьи стоили ~200 рублей, 2.4 — ~400 рублей, 3.5 и выше — от 700 рублей и выше. Пичем Вы вольны выбирать интерфейс — кому-то удобнее SPI, кому-то удобнее 8080. Я лично выбрал SPI — поскольку он есть в «хардварном» виде на большинстве одноплатников и доступен для программирования как из обычного пользовательского режима (т.е можно пользоваться шиной из обычной программы), так и из драйверов.

Где найти дисплеи?


Однако есть способ найти дисплеи «бесплатно» — из старых и нерабочих устройств. Например, из автомобильных навигаторов. Недавно читатель с DTF предложил заслать с 10-ок подобных девайсов, я конечно же согласился! Что самое приятное в них — так это то, что дисплеи там обычно стандартизированы — как по размерам, так и по шлейфу. Суть вот в чем: китайские компании довольно долго производили 4" дисплеи с разрешением 480x232 и резистивным тачскрином.

Подключаем дисплей к любому одноплатнику с SPI: Большой мануал о поиске экранчиков для ваших проектов Linux, Полезное, Гаджеты, C++, Своими руками, Программирование, Графика, 2D, Покупка, Orange Pi, Raspberry Pi, Одноплатный компьютер, Драйвер, Дисплей, Разработка, Длиннопост



Поэтому Вы практически на 100% можете быть уверены, что один дисплей подойдет к другому навигатору и покажет картинку (а если нет — то открываем даташит на дисплей и корректируем тайминги). Эти дисплеи используютTTL/RGBпротокол, поэтому для того, чтобы с ними работать, вам понадобится либо много свободных пинов, либо превратить микроконтроллер в видеоконтроллер (Raspberry Pi Pico/ESP32 должен с этим справиться без проблем). Большинство из этих дисплеев работает в 16-битном режиме, т.е до 65536 цветов. Ниже прилагаю распиновку к ним:

Подключаем дисплей к любому одноплатнику с SPI: Большой мануал о поиске экранчиков для ваших проектов Linux, Полезное, Гаджеты, C++, Своими руками, Программирование, Графика, 2D, Покупка, Orange Pi, Raspberry Pi, Одноплатный компьютер, Драйвер, Дисплей, Разработка, Длиннопост



Для более удобно подключения, можно использоватьтакиеbreakout-платы для 40-пин шлейфов. Я себе заказал несколько, в том числе и для паябельных шлейфов от старых мобилок. Стоят на алике копейки — в среднем, 100 рублей за 5 плат (берите 40 пин/0.5мм).

Подключаем дисплей к любому одноплатнику с SPI: Большой мануал о поиске экранчиков для ваших проектов Linux, Полезное, Гаджеты, C++, Своими руками, Программирование, Графика, 2D, Покупка, Orange Pi, Raspberry Pi, Одноплатный компьютер, Драйвер, Дисплей, Разработка, Длиннопост



На некоторых одноплатниках уже есть готовый 40-пин коннектор для подключения ваших дисплеев. Большинство из них базируется на базе чипсетов AllWinner F1C100s/F1C200s/V3s и экран работает там «из коробки», за исключением тачскрина (с ним надо повозиться), известные мне — Lctech Pi, MangoPi (извиняюсь за плохое качество фото, это с моего сайд-проекта):

Подключаем дисплей к любому одноплатнику с SPI: Большой мануал о поиске экранчиков для ваших проектов Linux, Полезное, Гаджеты, C++, Своими руками, Программирование, Графика, 2D, Покупка, Orange Pi, Raspberry Pi, Одноплатный компьютер, Драйвер, Дисплей, Разработка, Длиннопост



Если Вам нужен маленький дисплей, то можно взять оный от старого нерабочего кнопочного телефона. Из самых простых — Siemens C65, S65, M65, A55, A65. Эти дисплеи работают по протоколу SPI и к ним легко подпаяться. Как еще один из вариантов — дисплей от «народного» Motorola C350, который работает через интерфейс SPI, но требует 12-битного формата на цвет:

Подключаем дисплей к любому одноплатнику с SPI: Большой мануал о поиске экранчиков для ваших проектов Linux, Полезное, Гаджеты, C++, Своими руками, Программирование, Графика, 2D, Покупка, Orange Pi, Raspberry Pi, Одноплатный компьютер, Драйвер, Дисплей, Разработка, Длиннопост



Обратите внимание, что для этих дисплеев нужно самому мастерить бустер подсветки: от 3.7в они не заведутся. Сименсовским дисплеям нужно 12в — связано это с тем, что светодиоды в подсветке подключены последовательно, дабы уменьшить потребление. Если есть желание — можно разобрать модуль и перепаять светодиоды параллельно, но «кушать» такая сборка будет ощутимо, проще взять step-up преобразователь до 12В с алика за пару соток.

MIPI дисплеи можно достать из копеечных старых смартфонов ZTE/Lenovo/МТС/Билайн и.т.п. Предпочтительнее здесь именно именитые бренды, поскольку и ZTE и Lenovo делятся исходниками прошивки — так что можно будет найти команды инициализации и самому запустить дисплей. Кроме инициализации дисплея, там же можно будет найти и драйвер тачскрина — обычно они общаются по протоколу I2C и при очень большом желании, можно будет заставит работать и его.

Подключаем дисплей к любому одноплатнику с SPI: Большой мануал о поиске экранчиков для ваших проектов Linux, Полезное, Гаджеты, C++, Своими руками, Программирование, Графика, 2D, Покупка, Orange Pi, Raspberry Pi, Одноплатный компьютер, Драйвер, Дисплей, Разработка, Длиннопост



Для работы с ними, я также рекомендую Breakout-платы, а схему на коннектор дисплея можно найти в сервисмануале или схеме устройства (если таковой имеется для вашего смартфона). Для Lenovo подобные ищутся без проблем, но для топовых Samsung S2/S3/S4 с крутыми OLED-дисплеями за MIPI-дисплеи придётся забыть, т.к схем в открытом доступе нет.

Подключаем дисплей к любому одноплатнику с SPI: Большой мануал о поиске экранчиков для ваших проектов Linux, Полезное, Гаджеты, C++, Своими руками, Программирование, Графика, 2D, Покупка, Orange Pi, Raspberry Pi, Одноплатный компьютер, Драйвер, Дисплей, Разработка, Длиннопост



8080 дисплеи можно достать из старых китайских «кнопочников». Ищите те модели, на которые есть сервис-мануал (Fly DS124 и другие модели, некоторые Explay), тогда Вы сможете прочесть ID дисплея из регистра 0x0 (вида 0x9325/0x7739 и.т.п), найти даташит на интересующий вас контроллер и использовать его в своем проекте. В этих дисплеях самое приятное — паябельный шлейф и подсветка 5в, которая будет работать и на 3.7в, но немного тусклее.

Подключаем дисплей к любому одноплатнику с SPI: Большой мануал о поиске экранчиков для ваших проектов Linux, Полезное, Гаджеты, C++, Своими руками, Программирование, Графика, 2D, Покупка, Orange Pi, Raspberry Pi, Одноплатный компьютер, Драйвер, Дисплей, Разработка, Длиннопост



Если же Вам хотелось бы экранчик побольше, с разрешением 480x320, то смотрите в сторону очень дешевых мобильников из начала 2010х — Explay N1, Fly Jazz, Fly Wizard. Вполне может быть так, что у Вас лежит подобный девайс будучи разбитым или утопленным, а дисплей остался. Кстати, если вдруг у вас лежит один из подобных ультрадешевых китайчиков, но вам они не нужны — пишите в ЛС, есть идеи для проектов с ними.

Подключаем дисплей к любому одноплатнику с SPI: Большой мануал о поиске экранчиков для ваших проектов Linux, Полезное, Гаджеты, C++, Своими руками, Программирование, Графика, 2D, Покупка, Orange Pi, Raspberry Pi, Одноплатный компьютер, Драйвер, Дисплей, Разработка, Длиннопост



Обратите внимание, что эти дисплеи используют 18-битный физический интерфейс, но для программного доступа должно хватать 16-бит. Кроме того, на этом шлейфе есть пин IM0 — он отвечает за установку режима работы контроллера дисплея. Если бы у нас был еще IM1 и IM2, то мы могли бы хоть режим SPI установить, но в данном случае, мы можем установить либо 8-битный режим, либо 16-битный. Можете отследить пин IM0 на шлейфе и если он идет к обвязке, где предположительно разрывается/соединяется IM1/IM2, то можете попробовать разорвать/кинуть на них высокий уровень. Насчет подсветки на таких дисплеях пока что не знаю. Если распиновки на телефон нет, то поищите диагностические пятачки под коннектором, с осциллографом или даже просто тестером можно попытаться найти распиновку.

Подключаем дисплей к любому одноплатнику с SPI: Большой мануал о поиске экранчиков для ваших проектов Linux, Полезное, Гаджеты, C++, Своими руками, Программирование, Графика, 2D, Покупка, Orange Pi, Raspberry Pi, Одноплатный компьютер, Драйвер, Дисплей, Разработка, Длиннопост

От слов к делу — userspace часть


На этом предлагаю перейти к практической реализации нашего драйвера дисплея. Как я уже говорил, реализовать его можно двумя способами: в виде user-space библиотеки для вывода картинки из обычных программ, так и kernel-mode драйвер, который будет реализовать framebuffer, что позволит выводить туда и X Window System, и SDL — что душе угодно.

У каждого подхода есть плюсы и минусы. Перечисляю их:

  • Универсальность: Библиотека сможет выводить только ту картинку, которая формирует для нее программа. Однако, она может это делать максимально эффективным для этого образом, да и никто не мешает написать сервис, который будет копировать из /dev/fb0 картинку на наш дисплей (однако это лишняя нагрузка на процессор), китайцы так и делают.

  • Производительность: Kernel-mode драйвер может быть теоретически быстрее, хотя по факту вся SPI-подсистема Linux выделен в удобный spidev.

  • Стабильность: По понятным причинам, User-space библиотека будет куда стабильнее драйвера и не крашнет систему в случае ошибки.


Работать мы будем с простеньким 1.8" дисплеем, который имеет разрешение 128x160, работает на контроллере ST7739.

В качестве одноплатника я взял Orange Pi One. Брал я его на вторичке за 1.000 рублей, однако продавец меня порадовал и положил не один, а два девайса — в благодарность за статьи о Orange Pi 3G IoT :) Сейчас старые модели RPi и Orange Pi (но не их Mini и Zero версии) стоят копейки.

Подключаем дисплей к любому одноплатнику с SPI: Большой мануал о поиске экранчиков для ваших проектов Linux, Полезное, Гаджеты, C++, Своими руками, Программирование, Графика, 2D, Покупка, Orange Pi, Raspberry Pi, Одноплатный компьютер, Драйвер, Дисплей, Разработка, Длиннопост



Накатываем систему на флэшку (я выбрал Debian с ядром 3.4 — то которое еще не имело поддержки DeviceTree) и идем изучать гребенку:

Подключаем дисплей к любому одноплатнику с SPI: Большой мануал о поиске экранчиков для ваших проектов Linux, Полезное, Гаджеты, C++, Своими руками, Программирование, Графика, 2D, Покупка, Orange Pi, Raspberry Pi, Одноплатный компьютер, Драйвер, Дисплей, Разработка, Длиннопост



Видим SPI? Он нам и нужен! Подключаем питание дисплея (3.3В на VCC, 5В на LED и не забываем землю), подключаем сигнальные линии (SCK — CLK, SDA — MOSI, A0 и RESET — цепляем на произвольный GPIO, на котором «ничего нет», я выбрал PA10 и PA20 пины). Если SPI Вам нужен только для дисплея, то можно просто поставить перемычку между CS и землей. Оставлять его «в воздухе» нельзя — иначе дисплей не будет работать.

Подключаем дисплей к любому одноплатнику с SPI: Большой мануал о поиске экранчиков для ваших проектов Linux, Полезное, Гаджеты, C++, Своими руками, Программирование, Графика, 2D, Покупка, Orange Pi, Raspberry Pi, Одноплатный компьютер, Драйвер, Дисплей, Разработка, Длиннопост



Если подключили все верно, то при включении одноплатника, Вы увидите подсветку.
Теперь для того, чтобы им управлять, нам нужно получить доступ к шине SPI и проинициализировать контроллер. Для этого убеждаемся в том, что у нас есть spidev в каталоге /dev/, где spidev0.0 — первый контроллер SPI с первой линией CS, spidev0.1 — первый контроллер SPI с второй линией CS. У OrangePi One в стоке он только один — а для CS предлагается использовать sysfs. Кроме этого, нам нужно «экспортировать» из задать направлением пинам, которые мы будем использовать для сигналов RESET и DC. Для этого пишем номера пинов на гребенке прямо в устройство /sys/class/gpio/export, например так:

echo 10 > /sys/class/gpio/export

echo 20 > /sys/class/gpio/export

echo out > /sys/class/gpio/gpio20/direction

echo out > /sys/class/gpio/gpio10/direction

Обратите внимание, что в свежих версиях ядра появилось нормальное API для доступа к GPIO из userspace, управлять пинами через sysfs — в какой-то степени считается плохим тоном.

Открываем устройство как обычный файл:

fd = open("/dev/spidev0.0", O_RDWR | O_NONBLOCK);

dcFd = open("/sys/class/gpio/gpio10/value", O_RDWR);

resetFd = open("/sys/class/gpio/gpio20/value", O_RDWR);

И отправляем контроллер дисплея в RESET:

gpHelperSetState(resetFd, 0);

usleep(250000); // 250ms

gpHelperSetState(resetFd, 1);

После этого, реализовываем методы для передачи данных через SPI. В Linux, общение через эту шину идёт посредством транзакции, причем размер одной транзакции ограничен конкретным SPI-контроллером. В случае AllWinner, тут от 64, до 128 байт. Для каждой транзакции можно установить тактовую частоту — AllWinner поддерживает до ~100мгц.

void CLCM::Command(unsigned char cmd) {

spi_ioc_transfer tf;

memset(&tf, 0, sizeof(tf));

tf.bits_per_word = 8;

tf.len = 1;

tf.speed_hz = 64000000;

tf.tx_buf = (unsigned long)&cmd;

gpHelperSetState(dcFd, 0);

if(ioctl(fd, SPI_IOC_MESSAGE(1), &tf) < 0) LOG("SPI transfer failed\n");

}

void CLCM::Data(unsigned char data) {

spi_ioc_transfer tf;

memset(&tf, 0, sizeof(tf));

tf.bits_per_word = 8;

tf.len = 1;

tf.speed_hz = 64000000;

tf.tx_buf = (unsigned long)&data;

gpHelperSetState(dcFd, 1);

if(ioctl(fd, SPI_IOC_MESSAGE(1), &tf) < 0) LOG("SPI transfer failed\n");

}

Теперь нам нужно инициализировать дисплей. Для этого, нужно передать ему несколько команд, которые задают настройки развертки, поворота, внутренние настройки цветности и.т.п:

Линк на Pastebin, т.к код инита слишком большой.

Для передачи фреймбуфера, мы реализовываем отдельный метод, который разобьёт его на транзакции. В нашем случае, фреймбуфер занимает 128 * 160 * 2 = 40960 байт, делим на 64, получаем 640 транзакций на передачу одного кадра


void
CLCM::Bitmap(void* data, int len) {

gpHelperSetState(dcFd, 1);

for(int i = 0; i < len / 64; i++) {

spi_ioc_transfer tf; memset(&tf, 0, sizeof(tf));

tf.bits_per_word = 8;

tf.len = 64;

tf.speed_hz = 32000000;

tf.tx_buf = (unsigned long)data;

data += 64;

if(ioctl(fd, SPI_IOC_MESSAGE(1), &tf) < 0) LOG("SPI transfer failed\n");

}

}


Компилируем нашу программу, запускаем и видим: на дисплее появился мусор, а это значит, что он успешно проинициализирован. Если у Вас всё равно белый дисплей — смотрите подключение и убедитесь, что подключили сигнальные линии RESET/DC куда надо. После инициализации, на DC должен быть логический 0 (0В), на RESET — логический 1 (3.3В).

Пишем простенький загрузчик TGA и выводим картинку на экран:

CImage* img = CImage::FromFile("test.tga");

if(img) Bitmap(img->RGB, img->Width * img->Height * 2);


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

Выводим фреймбуфер на экран


Это всё конечно замечательно, однако зачастую есть необходимость отображать картинку, которые рисуют другие программы — X Window System, или, например, порт эмулятора денди на SDL1.2. Для этого, нам нужен способ выводить на наш дисплейчик то, что рисуется в главный фреймбуфер — /dev/fb0. И для этого, у нас есть целых два способа:

  • Реализация kernel-mode драйвера фреймбуфера: Это правильный вариант, однако при условии отсутствия dts, придется «подвигать» родной драйвер на другой фреймбуфер, либо перенастраивать уже имеющееся окружение на /dev/fb1.

  • Служба-прослойка, которая копирует фреймбуфер и вручную рисует на наш дисплей Этот способ я подсмотрел у китайцев: именно он реализован в драйвере дешевых дисплеев для Raspberry Pi. В целом, если так подумать, то это действительно довольно простой, портативный (не зависящий от версии ядра) и шустрый метод.


Именно второй способ мы и выберем в силу его некоторой диковинности. Фреймбуфер Linux имеет одну очень приятную особенность: он способен сам выполнять преобразования формата пикселей и динамически менять размер рабочего пространства. Мы можем просто попросить драйвер установить комфортный для нашего дисплея режим (128x160), цветность (RGB565) и читать уже готовые битмапы, по необходимости пересылая их на дисплей.

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

struct CLCM {

char* name;

int width,

height;

void(*init)();

void(*presentBuffer)(void* buf);

};

CLCM lcm7735

{

.name = "ST7735",

.width = 128,

.height = 160,

.init = &st7735Init,

.presentBuffer = &st7735Bitmap

};

CLCM* lcmList[] = { &lcm7735 };


Теперь у нашей службы есть некоторая гибкость. Захотели — поставили дисплей на базе ILI9341, захотели — на базе ILI9325, достаточно лишь портировать код инициализации.

Открываем всем необходимые устройства и назначаем нашему фреймбуферу желаемое разрешение. Обратите внимание, что мы можем весь буфер кадра отобразить в наш процесс с помощью mmap: это гораздо быстрее и экономичнее к памяти, чем выделять отдельный буфер под read/write.

bool setupFrameBuffer() {

LOG("Open framebuffer device");

fbDevice = open("/dev/fb0", O_RDWR);

if(!fbDevice) {

LOG("Failed to open primary framebuffer");

return false;

}

ioctl(fbDevice, FBIOGET_VSCREENINFO, &fbVar);

fbVar.xres = lcm->width;

fbVar.yres = lcm->height;

if(ioctl(fbDevice, FBIOPUT_VSCREENINFO, &fbVar) < 0) {

LOG("Unable to set framebuffer size :c");

return false;

}

ioctl(fbDevice, FBIOGET_VSCREENINFO, &fbVar); // Get yet another time for test

LOGF("Parent FB: %ix%i %i-bits", fbVar.xres, fbVar.yres, fbVar.bits_per_pixel);

ioctl(fbDevice, FBIOGET_FSCREENINFO, &fbFix);

fbMem = (char*)mmap(0, fbFix.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fbDevice, 0);

buf = (unsigned short*)malloc(lcm->width * lcm->height * 2);

if(!fbMem) {

LOG("mmap failed");

return false;

}

return true;

}


К сожалению, в случае с OrangePi, мне не удалось запросить драйвер обрабатывать картинку в формате RGB565, поэтому для вывода пришлось выделять внешний буфер, где мы на лету конвертируем картинку из 32х-битного RGB в 16-битный.

__inline unsigned short lcmTo565(unsigned int r, unsigned int g, unsigned int b) {

short ret = ((r & 0b11111000) << 8) | ((g & 0b11111100) << 3) | (b >> 3);

return bswap_16(ret);

}



Ну и переходим, собственно, к копированию фреймбуфера на наш дисплей:

void lcmCopyFramebuffer() {

int bpp = fbVar.bits_per_pixel / 8;

for(int i = 0; i < lcm->width; i++) {

for(int j = 0; j < lcm->height; j++) {

unsigned char* rgbData = (unsigned char*)&fbMem[(j * fbFix.line_length) + (i * bpp)];

buf[j * lcm->width + i] = lcmTo565(rgbData[0], rgbData[1], rgbData[2]);

}

}

lcm->presentBuffer(buf); }


Да, это вся программа. Тестируем наш результат:



Работает! Теперь если мы захотим запустить, например, эмуляторы, или вывести иксы на внешний экранчик — то мы смоежм сделать это без каких либо проблем.

Заключение


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

Даже с практический точки зрения нет никаких проблем в том, чтобы подключить дисплейчик даже к устройствам, где подобный видеовыход и не предусмотрен. Надеюсь этот подробный материал окажется полезным моим читателям. Само собой, я создал репозиторий на гитхабе и запушил туда все наработки из сегодняшней статьи.

Показать полностью 14
[моё] Linux Полезное Гаджеты C++ Своими руками Программирование Графика 2D Покупка Orange Pi Raspberry Pi Одноплатный компьютер Драйвер Дисплей Разработка Длиннопост
130
2
Kj3015
1 год назад
TECHNO BROTHER

Вопрос по аудио плееру⁠⁠

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

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

Посмотрел что можно сделать и в голову пришла идея взять расп пи, поставит дак, установить volumino и чтоб каждый через web интерфейс мог добавлять в плейлист что хочет. Глянул по цене что будет, да оно тоже самое что купить Node 2i, что тоже не очень айс, как бы за эти деньги + еще труд можно и самому на телефоне добавлять в плейлист.

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

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

[моё] Аудио Плеер Raspberry pi Текст
24
440
monobogdan
monobogdan
2 года назад
TECHNO BROTHER

Сам себе игровая консоль: как я сделал свой «тетрис» с нуля. Что происходит, когда программист встречается с железом?⁠⁠

Сам себе игровая консоль: как я сделал свой «тетрис» с нуля. Что происходит, когда программист встречается с железом? Гаджеты, Gamedev, Разработка, Своими руками, Raspberry pi, Самоделки, Железо, 2D, Игры, Консоли, Видео, Без звука, Длиннопост, Авторская неделя на Пикабу



Я, как и многие мои читатели, очень люблю игры. Уже довольно обширное число моих статей было посвящено ремонту и моддингу самых разных игровых консолей — как китайских «нонеймов», так и брендовых PSP и PS Vita! Однако, меня тянет к железу не только желание отремонтировать и поставить в строй «устаревшие» девайсы, но и мания делать и созидать что-то своё! А ещё я очень люблю программировать игры и графику сам. Недавно я загорелся идеей разработать с нуля свой портативный «тетрис»: от схемы и разводки платы, до написания прошивки и игр под нее. Что получается, когда программист, который поставил электронику практически во главе своей жизни, пытается сделать свое устройство? Читайте в статье!

❯ Как я к этому вообще пришел?


Проекты разработки самодельных игровых приставок стали очень популярны к нашему времени. Если раньше embedded-разработка была достаточно дорогой и доступной лишь для избранных, то сейчас на рынке можно найти все что хочешь — и мощные микроконтроллеры с кучей периферии за 300 рублей, и готовые дисплейные модули по 250 рублей, и макетные платы с удобными dupont коннекторами за весьма скромные деньги.

Сам себе игровая консоль: как я сделал свой «тетрис» с нуля. Что происходит, когда программист встречается с железом? Гаджеты, Gamedev, Разработка, Своими руками, Raspberry pi, Самоделки, Железо, 2D, Игры, Консоли, Видео, Без звука, Длиннопост, Авторская неделя на Пикабу



Собрать свой гаджет в пределах одной-двух тысяч рублей стало вполне реальным. Люди собирают себе самые разные устройства, а игровые приставки — одна из самых популярных тем. Однако, для многих людей, которые только начинают знакомится с миром embedded-электроники, собрать консоль в своем корпусе с Raspberry Pi на борту и RetroPie в качестве оболочки — за счастье.

Сам себе игровая консоль: как я сделал свой «тетрис» с нуля. Что происходит, когда программист встречается с железом? Гаджеты, Gamedev, Разработка, Своими руками, Raspberry pi, Самоделки, Железо, 2D, Игры, Консоли, Видео, Без звука, Длиннопост, Авторская неделя на Пикабу


Однако есть определенная категория электронщиков, к которой отношусь и я — нам нужно делать всё с нуля! Свои проекты я стараюсь реализовывать на самопальных фреймворках/движках, точно также я мыслю и в подходе электроники — ну не могу я использовать чужие решения и стараюсь разобраться в вопросе сам. За моей спиной есть весьма интересные демки. Например, это моя игрушка с незамысловатым названием «ралли-кубок ТАЗов», которую я написал за неделю с нуля (рендерер, звук, ввод, редактор уровней — все свое) в 2022 году:

Сам себе игровая консоль: как я сделал свой «тетрис» с нуля. Что происходит, когда программист встречается с железом? Гаджеты, Gamedev, Разработка, Своими руками, Raspberry pi, Самоделки, Железо, 2D, Игры, Консоли, Видео, Без звука, Длиннопост, Авторская неделя на Пикабу


Вот так, с любовью программировать игры, я и пришел к мысли сделать свою консоль, так как вижу её именно я. Только без чужих библиотек и наработок, но не прям уж bare metal. Сел я и начал думать, на чём же мы будем строить наш игровой девайс!

❯ Из чего будем делать?


Как я уже говорил выше, в наше время выбор железа для создания своих девайсов большой — тут и мощные микроконтроллеры/одноплатники, по производительности сравнимые с телефонами 2005-2006 годов, и различная периферия — аж глаза разбегаются. Однако проектировать будущую консоль нужно исходя из некоторых требований.

Характеристики моего девайса следующие:

  1. Процессор: двухядерный ARM микроконтроллер RP2040 на частоте 133мгц, построенный на архитектуре Cortex-M3. Сам процессор распаян на плате Raspberry Pi Pico.

  2. ОЗУ: 260 килобайт SRAM, встроена в процессор. Немного, но если грамотно распоряжаться ресурсами — то хватит.

  3. ПЗУ: 2Мб SPI Flash-памяти, также распаяны на плате.

  4. Дисплей: 1.8" TFT-матрица с разрешением 128x160. Выбор разрешения обусловлен производительностью будущей консоли — процессор банально не сможет заполнять матрицу с относительно высоким разрешением.

  5. Ввод: 6 кнопок, 4 из которых — направление, 2 — действий. В будущем могут добавиться еще несколько.

  6. Звук: динамик. Пока не знаю, с чего рулить будем — возможно, возьмем «железный» ШИМ-контроллер процессора, а возможно прикрутим внешний ЦАП с i2s.

  7. Питание: 3.7в аккумулятор BL-4C. Да, да, тот самый с Nokia и современных кнопочников! Аккумулятора, емкостью в 800мАч должно хватать хотя-бы на 4-5 часов игры. При этом зарядка АКБ обеспечивается модулем TP4056.


Весьма неплохо для самоделки, согласны? Как я уже говорил раннее, эти характеристики примерно соответствуют мобильным телефонам 2004-2006 годов — Nokia 6600, Sony Ericsson K510i, Samsung D800. Отличие лишь в ОЗУ (в телефонах её 2-4 мегабайта) и периферийных модулях типа контроллера дисплея.

Сам себе игровая консоль: как я сделал свой «тетрис» с нуля. Что происходит, когда программист встречается с железом? Гаджеты, Gamedev, Разработка, Своими руками, Raspberry pi, Самоделки, Железо, 2D, Игры, Консоли, Видео, Без звука, Длиннопост, Авторская неделя на Пикабу


На фото E398 — мобилка 2004 года выпуска, но она здесь не просто так. :)

Важную пометку нужно сделать касательно дисплеев: эти 1.8" матрицы бывают приходят с «синевой» — это не железная проблема и не совсем брак. Сам контроллер в дисплея в них сильно греется (хотя токоограничивающий резистор стоит) и негативно влияет на клей, из-за чего матрицы отклеивается от подсветки и слои поляризации начинают «синить» картинку. Лечится проклееванием подложки матрицы суперклеем.

Сам себе игровая консоль: как я сделал свой «тетрис» с нуля. Что происходит, когда программист встречается с железом? Гаджеты, Gamedev, Разработка, Своими руками, Raspberry pi, Самоделки, Железо, 2D, Игры, Консоли, Видео, Без звука, Длиннопост, Авторская неделя на Пикабу



RPi Pico я решил выбрать, поскольку информации про них достаточно мало, характеристики хорошие и пока что никто особо ничего на них не делал, тем более в рунете. А ещё у них очень удобное и простое SDK, практически bare-metal. ESP32, например, работает на FreeRTOS и имеет кучу библиотек, здесь же API простое и понятное.

Сам себе игровая консоль: как я сделал свой «тетрис» с нуля. Что происходит, когда программист встречается с железом? Гаджеты, Gamedev, Разработка, Своими руками, Raspberry pi, Самоделки, Железо, 2D, Игры, Консоли, Видео, Без звука, Длиннопост, Авторская неделя на Пикабу



Закупаем все необходимое и начинаем творить!

❯ Графика


В первую очередь нам нужно подключить дисплей и что-нибудь на него вывести. Заодно и SPI погоняем на незнакомом чипсете, благо работа с ним очень простая — задаем конфигурацию пинам (gpio_set_function), настраиваем SPI-контроллер и можно посылать данные.

Сам себе игровая консоль: как я сделал свой «тетрис» с нуля. Что происходит, когда программист встречается с железом? Гаджеты, Gamedev, Разработка, Своими руками, Raspberry pi, Самоделки, Железо, 2D, Игры, Консоли, Видео, Без звука, Длиннопост, Авторская неделя на Пикабу


SPI у RP2040 работает на частоте вплоть до ~60мгц — это достойная скорость передачи, в том числе и для быстрого вывода графики. На самом деле, SPI даже предпочтительнее чем параллельный 8080-интерфейс для использования в микроконтроллерах: дело не только в количестве занимаемых пинов, но и в возможности использования DMA!

В подобных проектах всегда нужно делать так, чтобы дисплей можно было при необходимости поменять, а желательно вообще научить работать его с несколькими контроллерами: разные дисплеи одной диагонали могут использовать разные контроллеры. В моём случае, этоST7735. Для разрешений 240x320 используются ILI9325, ILI9341, ST7789. Команды инициализации дисплея честно позаимствованы, но именно в этом нет ничего зазорного — сама система команд относительно стандартизирована, отличается лишь первичная настройка питания, гамма-коррекции и т. д — часто init sequence вставляет сам производитель в даташит.

Сам себе игровая консоль: как я сделал свой «тетрис» с нуля. Что происходит, когда программист встречается с железом? Гаджеты, Gamedev, Разработка, Своими руками, Raspberry pi, Самоделки, Железо, 2D, Игры, Консоли, Видео, Без звука, Длиннопост, Авторская неделя на Пикабу



После инициализации дисплея пробуем что-нибудь вывести. Да, все работает без проблем. Пару важных нюансов: ST7735 требует посаженный на землю CS, в воздухе его оставлять нельзя, как некоторые ILI (вы ведь навряд ли будете вешать несколько устройств на одну шину с дисплеем, когда есть вторая?) и логическое состояние 1 на пине RESET (в воздухе и «на земле» он будет висеть в постоянном ресете).

Сам себе игровая консоль: как я сделал свой «тетрис» с нуля. Что происходит, когда программист встречается с железом? Гаджеты, Gamedev, Разработка, Своими руками, Raspberry pi, Самоделки, Железо, 2D, Игры, Консоли, Видео, Без звука, Длиннопост, Авторская неделя на Пикабу



Для полустатичной графики, можно обойтись лишь командами дисплея — например, тут есть удобные функции для заливки прямоугольников (setArea и пишем цвет без остановки) или скроллинга. Сделано это для более слабых микроконтроллеров. Нам они не подойдут — выделяем память под фреймбуфер/бэкбуфер и настраиваем канал DMA для разгрузки процессора в процессе передачи данных:

Сам себе игровая консоль: как я сделал свой «тетрис» с нуля. Что происходит, когда программист встречается с железом? Гаджеты, Gamedev, Разработка, Своими руками, Raspberry pi, Самоделки, Железо, 2D, Игры, Консоли, Видео, Без звука, Длиннопост, Авторская неделя на Пикабу



Саму картинку подготавливает процессор: именно он рисует картинки и он же делает их прозрачными. На него ложится основная работа, однако мы можем ему помочь разгрузиться, если отдадим передачу уже подготовленного кадра на дисплей на DMA (Direct Memory Access) — устройство в микроконтроллере, которое позволяет процессору настроить параметры передачи данных, а DMA их будет сам копировать из памяти или в память. Таким образом, можно реализовать асинхронное копирование нескольких блоков ОЗУ, или, как в моем случае — передачу буфера кадра на дисплей, пока процессор готовит следующий. Чем больше разрешение — тем больше эффекта от DMA!

Сам себе игровая консоль: как я сделал свой «тетрис» с нуля. Что происходит, когда программист встречается с железом? Гаджеты, Gamedev, Разработка, Своими руками, Raspberry pi, Самоделки, Железо, 2D, Игры, Консоли, Видео, Без звука, Длиннопост, Авторская неделя на Пикабу



Кроме того, важно выбрать формат цвета для нашего дисплея: я выбрал 2-х байтный RGB565 (5 бит красный, 6 бит зеленый, 5 бит синий). Это экономичный формат который выглядит красивее палитровой графики и кушает не так уж и много драгоценной памяти. Кроме того, на данный момент мы умеем отрисовывать изображения произвольных размеров с прозрачностью — вместо альфа-канала здесь используется так называемый colorkey — концепция, очень близкая к хромакею, только она берет в качестве трафарета конкретный цвет. В нашем случае это «255 0 255» (ярко розовый).

Сам себе игровая консоль: как я сделал свой «тетрис» с нуля. Что происходит, когда программист встречается с железом? Гаджеты, Gamedev, Разработка, Своими руками, Raspberry pi, Самоделки, Железо, 2D, Игры, Консоли, Видео, Без звука, Длиннопост, Авторская неделя на Пикабу



Общая производительность рендерера порадовала: он легко осилит около сотни-двух различных спрайтов с адекватной производительностью, в зависимости от их размера. Но для такого разрешения экрана и будущих игр — это неплохой результат!

❯ Ввод


Теперь нам нужно как-то управлять нашим девайсом. Для этого пора сделать реализовать геймпад: в рамках этой статьи, я собрал его на макетке.

Сам себе игровая консоль: как я сделал свой «тетрис» с нуля. Что происходит, когда программист встречается с железом? Гаджеты, Gamedev, Разработка, Своими руками, Raspberry pi, Самоделки, Железо, 2D, Игры, Консоли, Видео, Без звука, Длиннопост, Авторская неделя на Пикабу



Кидаем общий минус на все кнопки, а второй вывод размыкателя кидаем на соответствующие пины GPIO. Я выбрал предпоследние т. к. на них ничего важного не висит, текущая конфигурация занимает 6 пинов. На фото выглядит не очень красиво — на то она и макетка.

Сам себе игровая консоль: как я сделал свой «тетрис» с нуля. Что происходит, когда программист встречается с железом? Гаджеты, Gamedev, Разработка, Своими руками, Raspberry pi, Самоделки, Железо, 2D, Игры, Консоли, Видео, Без звука, Длиннопост, Авторская неделя на Пикабу



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

Сам себе игровая консоль: как я сделал свой «тетрис» с нуля. Что происходит, когда программист встречается с железом? Гаджеты, Gamedev, Разработка, Своими руками, Raspberry pi, Самоделки, Железо, 2D, Игры, Консоли, Видео, Без звука, Длиннопост, Авторская неделя на Пикабу

Есть ещё способ реализации больших клавиатур и геймпадов: когда все кнопки вешаются на пару линий, где на выходе каждой кнопки есть резистор определенного номинала. ЦАП микроконтроллера считывает это значение (допустим — 1024 это вверх, а 2048 — вниз) и таким образом определяет текущую нажатую кнопку. Таким раньше любили промышлять китайцы, из-за чего нельзя было нажать одновременно вверх и вправо, или вниз и влево и т. п.

Сам себе игровая консоль: как я сделал свой «тетрис» с нуля. Что происходит, когда программист встречается с железом? Гаджеты, Gamedev, Разработка, Своими руками, Raspberry pi, Самоделки, Железо, 2D, Игры, Консоли, Видео, Без звука, Длиннопост, Авторская неделя на Пикабу

❯ Пишем игру


Теперь у нас есть минимально-необходимая основа для написания игры. Первой игрой для своей консоли я решил написать классический шутер в космосе — летаем на кораблике и сбиваем врагов, попутно уворачиваясь от их пулек. Заодно проверим консоль на стабильность.
Писать я её решил в классическом C-стиле, как и принято в embedded-мире: без std и тем более stl, без ООП и виртуальных методов, аллокаций по минимуму. В общем, примерно как писали игры под GBA! В первую очередь, подготавливаем спрайты нашей игры, прямо в пейнте, а затем конвертируем их в представление обычного массива байтов в виде header-файла. На первых порах это удобнее, чем делать свой ассет-пул:

Сам себе игровая консоль: как я сделал свой «тетрис» с нуля. Что происходит, когда программист встречается с железом? Гаджеты, Gamedev, Разработка, Своими руками, Raspberry pi, Самоделки, Железо, 2D, Игры, Консоли, Видео, Без звука, Длиннопост, Авторская неделя на Пикабу



Архитектуру я организовал в виде нескольких подфункций, каждая из которых занимается своим стейтом (world/menu) и своими объектами (playerUpdate) и их отдельные версии для отрисовки. Сами игровые объекты я описал в виде структур, а центральным объектом сделал CWorld.

Сам себе игровая консоль: как я сделал свой «тетрис» с нуля. Что происходит, когда программист встречается с железом? Гаджеты, Gamedev, Разработка, Своими руками, Raspberry pi, Самоделки, Железо, 2D, Игры, Консоли, Видео, Без звука, Длиннопост, Авторская неделя на Пикабу


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

Сам себе игровая консоль: как я сделал свой «тетрис» с нуля. Что происходит, когда программист встречается с железом? Гаджеты, Gamedev, Разработка, Своими руками, Raspberry pi, Самоделки, Железо, 2D, Игры, Консоли, Видео, Без звука, Длиннопост, Авторская неделя на Пикабу



Единственные аллокации, что я использовал — это для пулов с пулями, и с врагами. Оба пула четко ограничены — до 8 врагов на экране, и до 16 пулек — вполне хватает. Динамические аллокации помогли мне найти серьезную ошибку в коде — в один из моментов игра просто валилась с Out Of Memory. После того, как я немного поменял условия и делал аллокейты тех же самых объектов каждый кадр — игра переставала крашится. Причина оказалась простая — невнимательность (вместо >= было >), по итогу при отрисовке спрайтов за пределами экрана, программа сама начинала портить вунтренние структуры аллокатара и самой игры (проявлялось в глюках и телепортациях). После фикса, все заработало как нужно. :)


Ну и для основной части геймплея с выстрелами и столкновениями, я предусмотрел несколько функций, которые спавнят игровые объекты и сами управляют пулом. Противники обновляются как обычно, для коллизий используется AABB (axis aligned bounding box, ну или его 2D-подмножество в виде rect vs rect).

Сам себе игровая консоль: как я сделал свой «тетрис» с нуля. Что происходит, когда программист встречается с железом? Гаджеты, Gamedev, Разработка, Своими руками, Raspberry pi, Самоделки, Железо, 2D, Игры, Консоли, Видео, Без звука, Длиннопост, Авторская неделя на Пикабу



По итогу, у нас получилось простенькая, но рабочая игрушка, которая без проблем работала почти все время, что я писал этот материал, а значит устройство работает стабильно. И я очень горд, что у меня получилось сделать рабочий прототип своего собственного гаджета!

Сам себе игровая консоль: как я сделал свой «тетрис» с нуля. Что происходит, когда программист встречается с железом? Гаджеты, Gamedev, Разработка, Своими руками, Raspberry pi, Самоделки, Железо, 2D, Игры, Консоли, Видео, Без звука, Длиннопост, Авторская неделя на Пикабу



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

Сам себе игровая консоль: как я сделал свой «тетрис» с нуля. Что происходит, когда программист встречается с железом? Гаджеты, Gamedev, Разработка, Своими руками, Raspberry pi, Самоделки, Железо, 2D, Игры, Консоли, Видео, Без звука, Длиннопост, Авторская неделя на Пикабу

❯ Заключение


Полная цена сборки прототипа составила:

  • Raspberry Pi Pico — 557 рублей (но я брал на Яндекс Маркете, на «алике» дешевле — около 300 рублей).

  • Дисплей — 380 рублей, заказывал на «алике».

  • Макетка — 80 рублей, в местном радиомагазине.

  • Кнопки. По 5 или 10 рублей штучка, пусть будет 60 рублей.


По итогу, прототип мне обошелся в 1077 рублей. Бюджетненько, да, с учетом того, что можно сделать еще дешевле? Я тут так подумал, у меня есть желание развивать и поддерживать консоль в будущем и под консоль уже можно делать что-то своё… может, если вам будет интересно, делать их на заказ? Соберу вам по себестоимости (до 1.000 рублей) + доставка, если хочется попрограммировать под что-то маленькое, но самому паять не хочется. Мне было бы очень приятно. Пишите в личку или комменты, если вас заинтересовало бы такое! :)

Сам себе игровая консоль: как я сделал свой «тетрис» с нуля. Что происходит, когда программист встречается с железом? Гаджеты, Gamedev, Разработка, Своими руками, Raspberry pi, Самоделки, Железо, 2D, Игры, Консоли, Видео, Без звука, Длиннопост, Авторская неделя на Пикабу



Весь процесс разработки этого девайса занял у меня всего несколько дней. Я и до этого понимал концепцию работы 2D-графики на видеокартах прошлого века, поэтому ничего особо нового я для себя не открыл. Однако, я попробовал свои силы в разработке игровых девайсов, которые могут приносить удовольствие — как ментальное от самого процесса сборки и программирования, так и физическое от осознания того, что игра на нем работает. :)

Однако, это далеко не конец проекта! У нас ещё много работы: нужно развести и протравить полноценную плату, реализовать звук и API для сторонних игр, придумать корпус и распечатать его 3D-принтере. Кстати, я ведь обещал что скоро будут и другие интересные проекты с 3D-принтером: как минимум, мы доделаем предыдущий проект игровой консоли из планшета с нерабочим тачскрином и RPi Pico.

Пост подготовлен при поддержке TimeWeb Cloud. Подписывайтесь на меня и @Timeweb.Cloud, чтобы не пропускать новые статьи каждую неделю!

Показать полностью 23 1
[моё] Гаджеты Gamedev Разработка Своими руками Raspberry pi Самоделки Железо 2D Игры Консоли Видео Без звука Длиннопост Авторская неделя на Пикабу
34
1482
monobogdan
monobogdan
2 года назад
TECHNO BROTHER

Мы сделали вам плату, а дальше вы сами: Доводим дешевый одноплатник за "косарь" до ума!⁠⁠

Мы сделали вам плату, а дальше вы сами: Доводим дешевый одноплатник за "косарь" до ума! Гаджеты, Смартфон, Программирование, IT, Orange Pi, Одноплатный компьютер, Linux, Android, Raspberry pi, Минипк, Дешево, Покупка, Моддинг, Своими руками, Embedded, Длиннопост, Авторская неделя на Пикабу



В прошлой статье, мы с вами рассмотрели на что способен одноплатный компьютер, который стоит всего 1.000 рублей. Как мы выяснили, перспективы у данного девайса весьма неплохие, однако по факту, Orange Pi продаёт практически голую железку, которую нужно дорабатывать самому. Да, тут есть Ubuntu/Fedora, да, тут выведена гребенка с I2C/SPI — однако из коробки это всё работает криво-косо, либо не работает совсем. Даже обещанные шины SPI/I2C фактически не доступны в системе «из коробки». Материалов о доработке этого одноплатника в сети мало, поэтому я решил довести его до ума сам и поделится с вами — в том числе, готовыми бинарными образами! Интересно, на что способен доработанный одноплатник по цене ящика пива? :)

Над чем будем работать

В прошлой статье, мы с вами определились с потенциальными перспективами такого устройства. По цене 3х ESP32, производитель предлагает нам два полноценных вычислительных ARM-ядра, 256 мегабайт оперативной памяти, 512 мегабайт встроенной NAND-памяти, контроллер питания с возможностью работы от литий-ионных АКБ и 3G модем. Но в бочке меда нашлась ложка дегтя: никто не собирался это всё поддерживать и Orange Pi практически сразу «забили» на поддержку устройства, ограничившись портом Debian/Ubuntun на устройство.

Мы сделали вам плату, а дальше вы сами: Доводим дешевый одноплатник за "косарь" до ума! Гаджеты, Смартфон, Программирование, IT, Orange Pi, Одноплатный компьютер, Linux, Android, Raspberry pi, Минипк, Дешево, Покупка, Моддинг, Своими руками, Embedded, Длиннопост, Авторская неделя на Пикабу



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

Ко всему прочему, в Linux не работает GSM-стек. Да, совсем. Производитель даже не стал кооперироваться с MediaTek, чтобы попытаться реализовать работу с модемом на уровне системы. А ведь фактически, вся работа с модемом происходит лишь на уровне AT-команд. Так в чем же проблема была?

Мы сделали вам плату, а дальше вы сами: Доводим дешевый одноплатник за "косарь" до ума! Гаджеты, Смартфон, Программирование, IT, Orange Pi, Одноплатный компьютер, Linux, Android, Raspberry pi, Минипк, Дешево, Покупка, Моддинг, Своими руками, Embedded, Длиннопост, Авторская неделя на Пикабу



Со всем этим мне и предстоит разобраться! Клонируем репозиторий с исходниками ядра и бежим собирать!

Собираем ядро. I2C и SPI.

Вместо типичного Buildroot, Orange Pi использует свою собственную простую систему сборки на shell-скриптах: в качестве тулчейна используется уже готовый linaro. Отчасти, это связано с самими чипами, на которых работают их устройства — MediaTek, например, не использует Mainline ядро и в процессе сборке имеет ещё кучу шагов для подготовки финального образа. Там даже menuconfig не работает и все изменения приходится делать в уже сгенерированной когда-то конфигурации.

Клонируем репозиторий с системой сборки и запускаем скрипт:

git clone https://github.com/orangepi-xunlong/OrangePi_Build cd OrangePi_Build ./Build_OrangePi.sh

Мы сделали вам плату, а дальше вы сами: Доводим дешевый одноплатник за "косарь" до ума! Гаджеты, Смартфон, Программирование, IT, Orange Pi, Одноплатный компьютер, Linux, Android, Raspberry pi, Минипк, Дешево, Покупка, Моддинг, Своими руками, Embedded, Длиннопост, Авторская неделя на Пикабу



Выбираем нашу плату — 3G IoT и ждем, пока система сборки фактически скачает все необходимое для сборки — исходный код ядра, папки external (драйвера, загрузчик и порт linux MediaTek). Обратите внимание, OrangePi даже систему сборки завязали на конкретной версии системы: только Ubuntu 18.04, но на самом деле, ядро соберется без проблем практически где угодно. После того, как все было скачано, переходим в папку с скриптом сборки и запускаем скрипт сборки:

cd ../OrangePi3G_iot/
./build.sh


А нет, не запускаем — скрипт жалуется на то, что не может поставить некоторые пакеты. Не беда — ставим bsdtar и python minimal вручную и идем править код скрипта. Находится в он scripts/general.sh: убираем оттуда устаревшие имена пакетов.

Мы сделали вам плату, а дальше вы сами: Доводим дешевый одноплатник за "косарь" до ума! Гаджеты, Смартфон, Программирование, IT, Orange Pi, Одноплатный компьютер, Linux, Android, Raspberry pi, Минипк, Дешево, Покупка, Моддинг, Своими руками, Embedded, Длиннопост, Авторская неделя на Пикабу



После этого, компиляция ядра должна пройти успешно. Обратите внимание на версию вашей платы — те, что продают сейчас — именно A. Если пытаться подкинуть им ядро для B, то они будут уходить в kernel panic из-за отсутствия eMMC.

Мы сделали вам плату, а дальше вы сами: Доводим дешевый одноплатник за "косарь" до ума! Гаджеты, Смартфон, Программирование, IT, Orange Pi, Одноплатный компьютер, Linux, Android, Raspberry pi, Минипк, Дешево, Покупка, Моддинг, Своими руками, Embedded, Длиннопост, Авторская неделя на Пикабу



Если mkbootimg будет жаловаться на libstdc++6, то ставим его x86 версию из репозиториев.

Готовое ядро будет лежать вoutput/kernel/boot.img, которое можно прошить на устройство. С одним маленьким нюансом — оно рассчитано на загрузку из внутренней памяти, которой критически мало для дистрибутива Linux! У нас нет boot_sd.img, который есть в оригинальном дистрибутиве. Попытка разобрать образ стандартным AndImgTool не увенчалась успехом — рамдиск встроен прямо в образ zImage, а не отдельно, как это обычно бывает у Android-образов.

Мы сделали вам плату, а дальше вы сами: Доводим дешевый одноплатник за "косарь" до ума! Гаджеты, Смартфон, Программирование, IT, Orange Pi, Одноплатный компьютер, Linux, Android, Raspberry pi, Минипк, Дешево, Покупка, Моддинг, Своими руками, Embedded, Длиннопост, Авторская неделя на Пикабу



Покопавшись в скриптах сборки, я так и не понял логику создания boot_sd, ничего связанного с sd я не нашел даже grep'ом по всей папке. Ну что-ж, тогда попробуем обходным путем: скомпилируем нужные драйвера в виде загружаемых модулей (ko). Идём в наш конфиг, расположенный в linux/arch/arm/configs/3giot_defconfig и меняем CONFIG_I2C_CHARDEV и CONFIG_SPI_SPIDEV на m. Пояснение: y заставит систему сборки скомпоновать драйвер статически с ядром, а m выделит его в виде отдельного модуля ko, который затем можно загрузить черезinsmod.

Мы сделали вам плату, а дальше вы сами: Доводим дешевый одноплатник за "косарь" до ума! Гаджеты, Смартфон, Программирование, IT, Orange Pi, Одноплатный компьютер, Linux, Android, Raspberry pi, Минипк, Дешево, Покупка, Моддинг, Своими руками, Embedded, Длиннопост, Авторская неделя на Пикабу



Снова собираем ядро, на этот раз компиляция занимает не больше минуты. Нужные нам файлы появятся в linux/drivers/spi/spidev.ko и linux/drivers/i2c/i2c-d-ev.ko. Переносим их на хост-пк, а затем и на само устройство с помощью SSH:

Мы сделали вам плату, а дальше вы сами: Доводим дешевый одноплатник за "косарь" до ума! Гаджеты, Смартфон, Программирование, IT, Orange Pi, Одноплатный компьютер, Linux, Android, Raspberry pi, Минипк, Дешево, Покупка, Моддинг, Своими руками, Embedded, Длиннопост, Авторская неделя на Пикабу



Загружаем модули ядра:

insmod i2c-dev.ko


И та-дам! Целых две i2c шины появилось в системе (/dev/i2c-0, /dev/i2c-1). Устанавливаем i2c-tools и идем проверять с помощью i2cdetect: первая шина полностью свободна под наши проекты, а на второй по некоторым адресам висит периферия (FM-радио как вариант):

Мы сделали вам плату, а дальше вы сами: Доводим дешевый одноплатник за "косарь" до ума! Гаджеты, Смартфон, Программирование, IT, Orange Pi, Одноплатный компьютер, Linux, Android, Raspberry pi, Минипк, Дешево, Покупка, Моддинг, Своими руками, Embedded, Длиннопост, Авторская неделя на Пикабу



I2C теперь точно работает! Но как насчет SPI?

insmod spidev.ko
Device or resource busy.



Увы! spidev нельзя подгружать динамически, только статически линковать с ядром, чего мы сделать пока не можем. Однако техническая возможность заставить работать SPI есть: например, написать свой драйвер, который транслирует команды из юзерспейса в SPI API, которое работает на уровне ядра.

GPIO

В прошлой статье, я вкратце рассказал, как работать с gpio из user-space на уровне терминала. Однако, большинство разработчиков потенциально будет пользоваться нативным API для GPIO — ну не всерьез же им парсить вывод состояния в консоль? Поэтому я решил написать крошечную библиотеку для работы с GPIO, такую же простую, как и DigitalWrite/DigitalRead!

Давайте сначала разберемся, как именно работать с драйвером GPIO. Для этого открываем исходники ядра и смотрим внимательно, что нам предлагает драйвер: в нашем случае, это вызовы IOCTL, да еще и простые и понятные. Это просто отлично! Я написал single-header библиотеку минут за 10: без проверки ошибок, но работоспособная.

void gpioInit();

void gpioSetDir(int num, byte dir);

byte gpioGetDir(int num);

void gpioWrite(int num, byte value);

byte gpioGetState(int num); byte gpioRead(int num);

void gpioSetPullState(int num, byte enabled, byte up);



Пример использования (141 — крайний пин на гребенке):

#define GPIO_IMPL

#include "gpio.h"

#include <stdio.h>

void testPin(int pin)

{

printf("Pin state %i is %i\n", pin, gpioGetState(pin));

gpioSetDir(pin, 1);

gpioWrite(pin, 0);

printf("Pin state %i is %i\n", pin, gpioGetState(pin));

gpioWrite(pin, 1);

printf("Pin state %i is %i\n", pin, gpioGetState(pin));

}

int main(int argc, char** argv) {

gpioInit();

testPin(141);

}

Мы сделали вам плату, а дальше вы сами: Доводим дешевый одноплатник за "косарь" до ума! Гаджеты, Смартфон, Программирование, IT, Orange Pi, Одноплатный компьютер, Linux, Android, Raspberry pi, Минипк, Дешево, Покупка, Моддинг, Своими руками, Embedded, Длиннопост, Авторская неделя на Пикабу



Модем

Скажу сразу: пока что завести модем мне не удалось, но я активно работаю над этим. В этой части статьи я распишу свои находки и догадки касательно модемов на чипах MediaTek.

В устройствах MediaTek, драйвер для общения с GPS, A-GPS и модемом один — ccci, судя по всему cross chip communication interface. Именно ccci создает устройства, с в которые поступает вход с микрофона и выход на динамики, а также он создает управляющие интерфейсы для общения с различными модулями этого SoC.

При старте ядра, ccci создаёт много устройств — ccci_ioctl, ccci_ipc, ccci_fs и самое нужное нам —ttyC0/ttyC1/ttyC2— в зависимости от количества СИМ-карт в системе. Кроме ccci, в системе есть некий 6620_launcher — бинарник, который загружает прошивку Wi-Fi и gsm0710muxd — специальный сервис, который позволяет в GPRS-сетях одновременно разговаривать и сидеть в интернете.

На смартфонах MTK есть factory mode — так называемый тестовый режим, который гоняют на заводах. Вы, вероятно, когда-то видели китайские меню похожее на рекавери — это и есть factory mode. Из этого режима можно дозвонится в 911 и активировать модем без запуска Android и RIL. Как это работает? Идём читать исходники ядра!

В factory-режиме, для каждого теста, программа активирует модем заново. Для этого есть функции тестового режима для работы с AT-командами и для инициализации модема. Сначала, она открывает терминал /dev/ttyC0 — именно там происходит общение с модемом с помощью AT-команд:

Мы сделали вам плату, а дальше вы сами: Доводим дешевый одноплатник за "косарь" до ума! Гаджеты, Смартфон, Программирование, IT, Orange Pi, Одноплатный компьютер, Linux, Android, Raspberry pi, Минипк, Дешево, Покупка, Моддинг, Своими руками, Embedded, Длиннопост, Авторская неделя на Пикабу



После этого, программа выводит модем из режима сна с помощью команды «AT+ESLP=0», инициализирует СИМ-карту с помощью команды «AT+ESIMS» и задает режим работы с помощью «AT+EFUN=1» и «AT+CREG=1». После этого, модем начинает искать сеть и доступен для обычного общения с помощью AT-команд. Однако, написав тестовую софтину для общения с модемом из под Debian, я получал ошибки вида Device not found. Почему? Пока не знаю. Однако я продолжаю изучать данный вопрос!

Заключение

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

К счастью, довести гаджет до ума мы смогли своими силами. Весьма странно, что такой крупный и уважаемый производитель как Orange Pi, банально решил «забить» на поддержку собственного устройства. И я лично считаю, что не стоит закидывать в долгий ящик их тем читателям, которые купили когда-то себе подобный девайс и забили, смирившись с отсутствием гайдов.

Немного энтузиазма, опыта и видения будущего проекта — и все получится :)

Показать полностью 11
[моё] Гаджеты Смартфон Программирование IT Orange Pi Одноплатный компьютер Linux Android Raspberry pi Минипк Дешево Покупка Моддинг Своими руками Embedded Длиннопост Авторская неделя на Пикабу
149
miayuyu
miayuyu
2 года назад

Как мне их продать?⁠⁠

Как мне их продать? Raspberry pi, Продажа, Нужен совет
Как мне их продать? Raspberry pi, Продажа, Нужен совет
Показать полностью 2
Raspberry pi Продажа Нужен совет
25
Партнёрский материал Реклама
specials
specials

Только каждый третий пикабушник доходит до конца⁠⁠

А сможете ли вы уложить теплый пол, как супермонтажник?

Проверить

Ремонт Теплый пол Текст
7
Nird.d
Nird.d
2 года назад
Home Assistant

MQTT не видит больше 12 устройств⁠⁠

Добрый день.

Прошу помощи. С какого-то момента MQTT перестал определять больше 12 zigbee устройств. Удаляю интеграцию, создаю заново, находит снова 12 но других. Сначала думал дело в стике, купил свежий Sonoff история та же. HA в докере на ubuntu сервере. В качестве железа - малинка 3В. Версия HA 2023.07.2 На какой-то старой версии, точно поддерживалось 18 устройств. Может кто сталкивался с таким? Похоже на какое-то ограничение, но в какую сторону копать - не пойму.

Ubuntu Raspberry pi Компьютерная помощь Текст
5
Посты не найдены
О нас
О Пикабу Контакты Реклама Сообщить об ошибке Сообщить о нарушении законодательства Отзывы и предложения Новости Пикабу Мобильное приложение RSS
Информация
Помощь Кодекс Пикабу Команда Пикабу Конфиденциальность Правила соцсети О рекомендациях О компании
Наши проекты
Блоги Работа Промокоды Игры Курсы
Партнёры
Промокоды Биг Гик Промокоды Lamoda Промокоды Мвидео Промокоды Яндекс Директ Промокоды Отелло Промокоды Aroma Butik Промокоды Яндекс Путешествия Постила Футбол сегодня
На информационном ресурсе Pikabu.ru применяются рекомендательные технологии