Сообщество - TECHNO BROTHER
Добавить пост

TECHNO BROTHER

1 636 постов 12 517 подписчиков

Популярные теги в сообществе:

Домашний дымоуловитель

Много творческих людей, которые клеят, красят, паяют и при этом живут в небольших квартирах, сталкиваются с тем, что домашние часто ворчат, что мол пахнет, дымно и.т.д. Просмотрев рынок дымоуловителей я немного приохренел от цен. Получается что хорошую мощную, КОМПАКТНУЮ установку позволить себе может не каждый. Я просмотрел все бюджетные и не совсем модели. И решил сделать сам. Позвольте представить)

Домашний дымоуловитель Инженер-конструктор, Дымоуловитель, Длиннопост
Домашний дымоуловитель Инженер-конструктор, Дымоуловитель, Длиннопост
Домашний дымоуловитель Инженер-конструктор, Дымоуловитель, Длиннопост
Домашний дымоуловитель Инженер-конструктор, Дымоуловитель, Длиннопост
Домашний дымоуловитель Инженер-конструктор, Дымоуловитель, Длиннопост
Домашний дымоуловитель Инженер-конструктор, Дымоуловитель, Длиннопост
Домашний дымоуловитель Инженер-конструктор, Дымоуловитель, Длиннопост
Домашний дымоуловитель Инженер-конструктор, Дымоуловитель, Длиннопост

корпус из оцинкованной стали 0.7 мм.

Размеры 250х270х630. Внутри расположен блок с двумя съемными фильтрами (можно менять фильтры по мере их заполнения). Верхний фильтр от грубых частиц, нижний - угольный. Мотор мощностью 100 ватт, тихий и надежный. На корпусе расположен переключатель скорости. Также имеется гофрированная труба, растягивается до 2 метров.

Система проста и надежна как советский пылесос)

Домашний дымоуловитель Инженер-конструктор, Дымоуловитель, Длиннопост
Домашний дымоуловитель Инженер-конструктор, Дымоуловитель, Длиннопост
Домашний дымоуловитель Инженер-конструктор, Дымоуловитель, Длиннопост
Домашний дымоуловитель Инженер-конструктор, Дымоуловитель, Длиннопост
Домашний дымоуловитель Инженер-конструктор, Дымоуловитель, Длиннопост
Домашний дымоуловитель Инженер-конструктор, Дымоуловитель, Длиннопост
Домашний дымоуловитель Инженер-конструктор, Дымоуловитель, Длиннопост
Домашний дымоуловитель Инженер-конструктор, Дымоуловитель, Длиннопост
Домашний дымоуловитель Инженер-конструктор, Дымоуловитель, Длиннопост
Домашний дымоуловитель Инженер-конструктор, Дымоуловитель, Длиннопост
Домашний дымоуловитель Инженер-конструктор, Дымоуловитель, Длиннопост
Домашний дымоуловитель Инженер-конструктор, Дымоуловитель, Длиннопост
Домашний дымоуловитель Инженер-конструктор, Дымоуловитель, Длиннопост
Домашний дымоуловитель Инженер-конструктор, Дымоуловитель, Длиннопост

Название и логотип придумал за 2 минуты.

Конструктивная критика приветствуется !

Показать полностью 22

Подключаем дисплей к любому одноплатнику с 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

Ретропонедельник №109 Приставка селектор ПСКД-6М

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

Ретропонедельник №109 Приставка селектор ПСКД-6М Сделано в СССР, Электроника, Техника, Телевидение, Виртуальный музей, Длиннопост

Производитель - завод Сокол-АТС, всё еще живой.

Ретропонедельник №109 Приставка селектор ПСКД-6М Сделано в СССР, Электроника, Техника, Телевидение, Виртуальный музей, Длиннопост

Приставка нужна для приема ДМВ каналов если телевизор старый и не имеет блока приема ДМВ каналов, а показывает только метровые.

Ретропонедельник №109 Приставка селектор ПСКД-6М Сделано в СССР, Электроника, Техника, Телевидение, Виртуальный музей, Длиннопост

Разъемы выдраны с мясом. Разъем антенны откушен.

Ретропонедельник №109 Приставка селектор ПСКД-6М Сделано в СССР, Электроника, Техника, Телевидение, Виртуальный музей, Длиннопост

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

Ретропонедельник №109 Приставка селектор ПСКД-6М Сделано в СССР, Электроника, Техника, Телевидение, Виртуальный музей, Длиннопост
Ретропонедельник №109 Приставка селектор ПСКД-6М Сделано в СССР, Электроника, Техника, Телевидение, Виртуальный музей, Длиннопост

ВЧ блок на разъеме

Ретропонедельник №109 Приставка селектор ПСКД-6М Сделано в СССР, Электроника, Техника, Телевидение, Виртуальный музей, Длиннопост
Ретропонедельник №109 Приставка селектор ПСКД-6М Сделано в СССР, Электроника, Техника, Телевидение, Виртуальный музей, Длиннопост

Резисторы подстройки

Ретропонедельник №109 Приставка селектор ПСКД-6М Сделано в СССР, Электроника, Техника, Телевидение, Виртуальный музей, Длиннопост

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

Ретропонедельник №109 Приставка селектор ПСКД-6М Сделано в СССР, Электроника, Техника, Телевидение, Виртуальный музей, Длиннопост

Схема:

Ретропонедельник №109 Приставка селектор ПСКД-6М Сделано в СССР, Электроника, Техника, Телевидение, Виртуальный музей, Длиннопост

Модель ПСКД6 чуть отличается, есть отдельная крутилка подстройки

Ретропонедельник №109 Приставка селектор ПСКД-6М Сделано в СССР, Электроника, Техника, Телевидение, Виртуальный музей, Длиннопост
Ретропонедельник №109 Приставка селектор ПСКД-6М Сделано в СССР, Электроника, Техника, Телевидение, Виртуальный музей, Длиннопост
Показать полностью 12

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

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

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

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

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

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

Ретропонедельник №108. Фотоаппарат Зенит 16 полуавтомат

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

Ретропонедельник №108. Фотоаппарат Зенит 16 полуавтомат Сделано в СССР, Техника, Фотоаппарат, Пленочные фотоаппараты, Длиннопост
Ретропонедельник №108. Фотоаппарат Зенит 16 полуавтомат Сделано в СССР, Техника, Фотоаппарат, Пленочные фотоаппараты, Длиннопост
Ретропонедельник №108. Фотоаппарат Зенит 16 полуавтомат Сделано в СССР, Техника, Фотоаппарат, Пленочные фотоаппараты, Длиннопост
Ретропонедельник №108. Фотоаппарат Зенит 16 полуавтомат Сделано в СССР, Техника, Фотоаппарат, Пленочные фотоаппараты, Длиннопост
Ретропонедельник №108. Фотоаппарат Зенит 16 полуавтомат Сделано в СССР, Техника, Фотоаппарат, Пленочные фотоаппараты, Длиннопост
Ретропонедельник №108. Фотоаппарат Зенит 16 полуавтомат Сделано в СССР, Техника, Фотоаппарат, Пленочные фотоаппараты, Длиннопост
Ретропонедельник №108. Фотоаппарат Зенит 16 полуавтомат Сделано в СССР, Техника, Фотоаппарат, Пленочные фотоаппараты, Длиннопост
Ретропонедельник №108. Фотоаппарат Зенит 16 полуавтомат Сделано в СССР, Техника, Фотоаппарат, Пленочные фотоаппараты, Длиннопост
Ретропонедельник №108. Фотоаппарат Зенит 16 полуавтомат Сделано в СССР, Техника, Фотоаппарат, Пленочные фотоаппараты, Длиннопост
Ретропонедельник №108. Фотоаппарат Зенит 16 полуавтомат Сделано в СССР, Техника, Фотоаппарат, Пленочные фотоаппараты, Длиннопост

Фотоаппарат из коллекции Черненко А.

Показать полностью 10

Прокладка ELECROW для заказа плат из Китая в Россию

Вслед за JLCPCB.com и PCBWAY.com закрыла доставку в Россию и ELECROW,

Но оставила после себя прокладку в виде сайта близнеца PCBWave.

С Россией пока работают. Кому нужна рефералка на 5 баксов вот https://www.pcbwave.com/referral-program/MTMxajJ0/

Исходники закрыты, но мы не сдадимся: Пишем полностью нативное GUI-приложение под No-Name смартфон без Android

Исходники закрыты, но мы не сдадимся: Пишем полностью нативное GUI-приложение под No-Name смартфон без Android Гаджеты, Смартфон, Linux, Телефон, IT, Хакеры, Hacking, Программирование, Embedded, C++, Одноплатный компьютер, Nix, Unix, Ядро, Kernel, Android, Длиннопост



Для многих разработчиков приложений далеко не секрет, что экосистема Android не предполагает написание полностью нативных приложений: в этой платформе очень многое завязано на Java и без ART можно запустить только простые службы без какого-либо интерфейса. Однако, есть один способ писать практически под «голый» Linux, не перекомпилируя ядро и при этом пользоваться самыми интересными фишками устройства без оверхеда в виде тяжелого Android: ускорение 3D-графики (OpenGLES), микшер звука, ввод с различных устройств, OTG, Wi-Fi и если очень постараться — даже 3G. Это открывает множество разных интересных применений старым устройствам: «железо» смартфонов зачастую гораздо мощнее современных недорогих одноплатников. Сегодня я покажу вам, как написать и запустить программу, которая полностью написанное на C без Android, на No-Name Android-смартфоне практически без модификаций. Интересно? Жду вас в статье!

❯ Что нам нужно знать?


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

Исходники закрыты, но мы не сдадимся: Пишем полностью нативное GUI-приложение под No-Name смартфон без Android Гаджеты, Смартфон, Linux, Телефон, IT, Хакеры, Hacking, Программирование, Embedded, C++, Одноплатный компьютер, Nix, Unix, Ядро, Kernel, Android, Длиннопост


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

  1. Первичный загрузчик (BootROM) инициализирует какую-то часть периферии и загружает вторичный загрузчик (U-boot/LK).

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

  3. После загрузки ядра Linux и подключения ramdisk начинается выполнение процессов системы.


Как раз в третьем пункте и лежит ключ к способу, который будем использовать мы. Дело в том, что в смартфоне обычно есть несколько boot-разделов и у каждого свой образ ядра Linux со своим ramdisk. Первый из них — это знакомый моддерамboot.img, который отвечает за загрузку системы и инициализирует железо/монтирует разделы/подготавливает окружение к работе (.rc файлы) и запускает главный процесс Android —zygote. При этом используется собственная реализация init от Android.

Исходники закрыты, но мы не сдадимся: Пишем полностью нативное GUI-приложение под No-Name смартфон без Android Гаджеты, Смартфон, Linux, Телефон, IT, Хакеры, Hacking, Программирование, Embedded, C++, Одноплатный компьютер, Nix, Unix, Ядро, Kernel, Android, Длиннопост


Второй, не менее знакомый многим раздел —recovery, отвечает за так называемый режим восстановления, в котором мы можем сбросить данные до заводских настроек/очистить кэши или прошить кастомную прошивку. Вероятно, многие из вас замечали, насколько быстро ваш девайс загружает этот режим, гораздо быстрее, чем загрузка обычного Android. И именно в его реализацию нам нужнозаглянуть(я намеренно выбрал бранч версии 2.3 — т.е Gingerbread для простоты):

Исходники закрыты, но мы не сдадимся: Пишем полностью нативное GUI-приложение под No-Name смартфон без Android Гаджеты, Смартфон, Linux, Телефон, IT, Хакеры, Hacking, Программирование, Embedded, C++, Одноплатный компьютер, Nix, Unix, Ядро, Kernel, Android, Длиннопост


А recovery оказывается самой обычной нативной программой, написанной на C со своим небольшим фреймворком для работы с графикой и вводом. В процессе загрузки режима recovery, скрипт запускает одноименную программу в /sbin/, благодаря которому мы видим простую и понятную менюшку. Так почему бы не использовать этот раздел в своих целях и не написать какую-нибудь нативную программу самому?

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

❯ Подготавливаем окружение


В первую очередь, хотелось бы отметить, что программы под «голый» смартфон можно писать не только на C/C++. Нам доступен как минимум FPC, который довольно давно умеет компилировать голые бинарники под Android. Кроме того, мы можем портировать маленькие embedded-версии интерпретаторов таких языков, как lua, micropython и duktape (JS).

Однако в случае нативных программ, есть два важных правила, которые необходимо понимать. Во-первых, в Android используется собственную реализацию стандартной библиотеки libc — bionic, в то время как на десктопных дистрибутивах используется glibc. Между собой они не совместимы — именно поэтому вы не можете просто взять и запустить консольную программу для Raspberry Pi, например.

Исходники закрыты, но мы не сдадимся: Пишем полностью нативное GUI-приложение под No-Name смартфон без Android Гаджеты, Смартфон, Linux, Телефон, IT, Хакеры, Hacking, Программирование, Embedded, C++, Одноплатный компьютер, Nix, Unix, Ядро, Kernel, Android, Длиннопост


А второе правило заключается в том, что начиная с версии 4.1, Androidтребует, чтобы все нативные программы были скомпилированы в режиме -fPIE — т. е. выходной код должен не зависеть от адреса загрузки программы в виртуальную память. Для этого достаточно добавить ключ -fPIE, однако учтите, что если вы разрабатываете программу под Android 4.0 и ниже, то fPIE наоборот необходимо убрать — старые версии Androidнеподдерживают такой способ генерации кода и будут вылетать с Segmentation fault.

Для разработки нам понадобится ndk — там есть все необходимые заголовочники и компиляторы для нашей работы. Я используюndk r9c, поскольку в свежих версиях Google регулярно может что-то сломать.
ndk-build, к сожалению, здесь работать не будет, поэтому Makefile придется написать самому. Я составил полностью рабочий Makefile, который без проблем скомпилирует валидную программу, вам остаётся лишь поменять NDK_DIR.

NDK_DIR = D:/android-ndk-r11c/

TOOLCHAIN_DIR = $(NDK_DIR)toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64/bin/

GCC = $(TOOLCHAIN_DIR)arm-linux-androideabi-g++

PLAT_DIR = $(NDK_DIR)platforms/android-17/arch-arm/usr/

LINK_LIBS = -l:libEGL.so -l:libGLESv1_CM.so

OUTPUT_NAME = cmdprog

build:

$(GCC) -I $(PLAT_DIR)include/ -L $(PLAT_DIR)lib/ -fPIE -Wl,-dynamic-linker=/sbin/linker $(LINK_LIBS) -static -o $(OUTPUT_NAME) main.cpp micro2d.cpp


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

❯ Деплоим на устройство


Несмотря на то, что грузиться мы будем в режим recovery, нам всё равно будет доступен adb, через который мы сможем запускать и отлаживать нашу программу. Это очень удобно, однако по умолчанию adb включен только в TWRP, который нужно сначала найти или портировать под ваш девайс (на большинство старых брендовых устройств порты есть, на нонейм придется портировать самому — гайды есть в интернете). Под ваше устройство есть TWRP? Отлично, распаковываете recovery.img с помощью так называемой «кухни» (MTKImgTools как вариант):

Исходники закрыты, но мы не сдадимся: Пишем полностью нативное GUI-приложение под No-Name смартфон без Android Гаджеты, Смартфон, Linux, Телефон, IT, Хакеры, Hacking, Программирование, Embedded, C++, Одноплатный компьютер, Nix, Unix, Ядро, Kernel, Android, Длиннопост


Открываете init.recovery.service.rc и убираете оттуда запуск одноименной службы (можно просто оставить файл пустым).

Исходники закрыты, но мы не сдадимся: Пишем полностью нативное GUI-приложение под No-Name смартфон без Android Гаджеты, Смартфон, Linux, Телефон, IT, Хакеры, Hacking, Программирование, Embedded, C++, Одноплатный компьютер, Nix, Unix, Ядро, Kernel, Android, Длиннопост


Запаковываем образ обратно тем же MTKImgTools и прошиваем флэшером для вашего устройства — в моём случае, это SP Flash Tool (MediaTek):

Исходники закрыты, но мы не сдадимся: Пишем полностью нативное GUI-приложение под No-Name смартфон без Android Гаджеты, Смартфон, Linux, Телефон, IT, Хакеры, Hacking, Программирование, Embedded, C++, Одноплатный компьютер, Nix, Unix, Ядро, Kernel, Android, Длиннопост


Заходим в режим рекавери и видим зависшую заставку устройства и звук подключения устройства к ПК. Если у вас установлены драйвера, то вы сможете без проблем зайти в adb shell и попасть в терминал для управления устройством. Теперь можно закинуть программу — прямо в корень рамдиска (записывается программа в ОЗУ, но при переполнении, телефон уйдет в ребут — осторожнее с этим). Пишем:

adb push cmdprog /: adb shell chmod 777 cmdprog ./cmdprog


И видим результат. Наша программа запускается и работает!

Исходники закрыты, но мы не сдадимся: Пишем полностью нативное GUI-приложение под No-Name смартфон без Android Гаджеты, Смартфон, Linux, Телефон, IT, Хакеры, Hacking, Программирование, Embedded, C++, Одноплатный компьютер, Nix, Unix, Ядро, Kernel, Android, Длиннопост


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

❯ Выводим графику


Для вывода графики без оконных систем, мы будем использовать API фреймбуфера Linux, которое позволяет нам получить прямой доступ к массиву пикселей на экране. Однако учтите, что этот способ полностью программный и может оказаться тормозным для вашего приложения: скорость работы прямо-пропорциональна разрешению дисплея вашего устройства. Чем выше разрешение, тем ниже филлрейт. В моём случае, матрица была с разрешением 960x540, 32млн цветов, IPS — очень недурно, согласны?

Фреймбуфер Linux может работать с самыми разными форматами пикселя, имейте это ввиду. На некоторых устройствах может быть 16-битный формат (262 тысячи цветов, RGB565), на моём же оказался 32х-битный с выравниванием по строкам (имейте это также ввиду). 32х битный формат. Работать с ним легко: открываем устройство /dev/graphics/fb0, получаем параметры (разрешение, формат пикселя), делаем mmap для отображения буфера с пикселями на экране в память нашего процесса и выделяем второй буфер для двойной буферизации дабы избежать неприятных мерцаний.

void m2dAllocFrameBuffer()

{

fbDev = open(PRIMARY_FB, O_RDWR);

fb_var_screeninfo vInfo; fb_fix_screeninfo fInfo;

ioctl(fbDev, FBIOGET_VSCREENINFO, &vInfo);

ioctl(fbDev, FBIOGET_FSCREENINFO, &fInfo); fbDesc.width = vInfo.xres;

fbDesc.height = vInfo.yres;

fbDesc.pixels = (unsigned char*)mmap(0, fInfo.smem_len, PROT_WRITE, MAP_SHARED, fbDev, 0); f

bDesc.length = fInfo.smem_len; fbDesc.lineLength = fInfo.line_length;

backBuffer = (unsigned char*)malloc(fInfo.smem_len); memset(backBuffer, 128, fInfo.smem_len);

printf("Framebuffer is %s %ix%ix%i\n", (char*)&fInfo.id, fbDesc.width, fbDesc.height, vInfo.bits_per_pixel, fInfo.type);

}


Если не сделать предыдущий шаг и запускать нашу программу параллельно с recovery, то они обе будут пытаться друг друга «перекрыть» — эдакий race condition:

Исходники закрыты, но мы не сдадимся: Пишем полностью нативное GUI-приложение под No-Name смартфон без Android Гаджеты, Смартфон, Linux, Телефон, IT, Хакеры, Hacking, Программирование, Embedded, C++, Одноплатный компьютер, Nix, Unix, Ядро, Kernel, Android, Длиннопост


После этого пишем простенькие функции для блиттинга картинок (в том числе с альфа-блендингом). В инлайнах и критичных к скорости функциям лучше не делать условия на проверку границ нашего буфера — лучше «отрезать» ненужное еще на этапе просчета ширины/высоты:

__inline void pixelAt(int x, int y, byte r, byte g, byte b, float alpha)

{

if(x < 0 || y < 0 || x >= fbDesc.width || y >= fbDesc.height) return;

unsigned char* absPtr = &backBuffer[(y * fbDesc.lineLength) + (x * 4)];

if(alpha >= 0.99f)

{

absPtr[0] = b;

absPtr[1] = g;

absPtr[2] = r;

}

else {

absPtr[0] = (byte)(b * alpha + absPtr[0] * (1.0f - alpha));

absPtr[1] = (byte)(g * alpha + absPtr[1] * (1.0f - alpha));

absPtr[2] = (byte)(r * alpha + absPtr[2] * (1.0f - alpha));

} absPtr[3] = 255; }

for(int i = 0; i < image->height; i++)

{

for(int j = 0; j < image->width; j++)

{

byte* ptr = &image->pixels[((image->height - i) * image->width + j) * 3]; pixelAt(x + j, y + i, ptr[0], ptr[1], ptr[2], alpha);

}

}


И загрузчик TGA:

CImage* m2dLoadImage(char* fileName) {

FILE* f = fopen(fileName, "r");

printf("m2dLoadImage: Loading %s\n", fileName);

if(!f)

{

printf("m2dLoadImage: Failed to load %s\n", fileName);

return 0;

}

CTgaHeader hdr;

fread(&hdr, sizeof(hdr), 1, f);

if(hdr.paletteType)

{

printf("m2dLoadImage: Palette images are unsupported\n");

return 0;

}

if(hdr.bpp != 24) {

printf("m2dLoadImage: Unsupported BPP\n");

return 0;

}

byte* buf = (byte*)malloc(hdr.width * hdr.height * (hdr.bpp / 8));

assert(buf);

fread(buf, hdr.width * hdr.height * (hdr.bpp / 8), 1, f);

fclose(f);

CImage* ret = (CImage*)malloc(sizeof(CImage));

ret->width = hdr.width;

ret->height = hdr.height;

ret->pixels = buf;

printf("m2dLoadImage: Loaded %s %ix%i\n", fileName, ret->width, ret->height);

return ret;

}


И попробуем вывести картинку:

m2dInit();

test = m2dLoadImage("test.tga");

test2 = m2dLoadImage("habr.tga");

while(1)

{

m2dClear();

m2dDrawImage(test, 0, 0, 1.0f);

m2dDrawImage(test2, tsX - (test2->width / 2), tsY - (test2->height / 2), 0.5f);

m2dFlush();

}

Исходники закрыты, но мы не сдадимся: Пишем полностью нативное GUI-приложение под No-Name смартфон без Android Гаджеты, Смартфон, Linux, Телефон, IT, Хакеры, Hacking, Программирование, Embedded, C++, Одноплатный компьютер, Nix, Unix, Ядро, Kernel, Android, Длиннопост



Не забываем про порядок пикселей в TGA (BGR, вместо RGB), меняем канали b и r местами в pixelAt и наслаждаемся картинкой на большом и классном IPS-дисплее:

Исходники закрыты, но мы не сдадимся: Пишем полностью нативное GUI-приложение под No-Name смартфон без Android Гаджеты, Смартфон, Linux, Телефон, IT, Хакеры, Hacking, Программирование, Embedded, C++, Одноплатный компьютер, Nix, Unix, Ядро, Kernel, Android, Длиннопост
Исходники закрыты, но мы не сдадимся: Пишем полностью нативное GUI-приложение под No-Name смартфон без Android Гаджеты, Смартфон, Linux, Телефон, IT, Хакеры, Hacking, Программирование, Embedded, C++, Одноплатный компьютер, Nix, Unix, Ядро, Kernel, Android, Длиннопост


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

Есть вариант для быстрой и динамичной графики: использовать GLES, который без проблем доступен и из recovery. Однако, насколько мне известно (в исходники драйверов посмотреть не могу), указать фреймбуфер в качестве окна не получится, поэтому в качестве Surface для рендертаргета у нас будет служить Pixmap (так называемый off-screen rendering), которому нужно задать правильный формат пикселя (см. документацию EGL). Рисуем туда картинку с аппаратным ускорением и затем просто копируем в фреймбуфер с помощью memcpy.

❯ Обработка нажатий


Однако, ни о каких GUI-программах не идёт речь, если мы не умеет обрабатывать нажатия на экране с полноценным мультитачем! Благо, даже механизм обработки событий в Linux очень простой и приятный: мы точно также открываем устройство и просто читаем из него события в фиксированную структуру. Эта черта мне очень нравится в архитектуре Linux!

Каждое устройство, которое может передавать данные о нажатиях, находится в папке /dev/input/ и имеет имя вида event. Как узнать нужный нам event? Нам нужен mtk-tpd — реализация драйвера тачскрина от MediaTek (у вашего чипсета может быть по своему), для этого загружаемся в Android и пишем getevent. Он покажет доступные в системе устройства ввода — в моём случае, это event2:

Исходники закрыты, но мы не сдадимся: Пишем полностью нативное GUI-приложение под No-Name смартфон без Android Гаджеты, Смартфон, Linux, Телефон, IT, Хакеры, Hacking, Программирование, Embedded, C++, Одноплатный компьютер, Nix, Unix, Ядро, Kernel, Android, Длиннопост


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

// Open input device evDev = open(INPUT_EVENT_TPD, O_RDWR | O_NONBLOCK);


После этого, читаем события с помощью read и обрабатываем их. На устройствах с резистивным тачскрином, передается просто ABS_POSITION_X, на устройствах с поддержкой нескольких касаний — используетсяпротокол MT. Когда пользователь нажал на экран, посылается нажатие BTN_TOUCH с значением 1, а когда отпускает — соответственно BTN_TOUCH с значением 0. Разные драйверы тачскрина используют разные координатные системы (насколько я понял), в случае MediaTek — это абсолютные координаты на дисплее (вплоть до ширины и высоты). На данный момент, я реализовал поддержку только одного касания, но при желании можно добавить трекинг нескольких нажатий:

void m2dUpdateInput()

{

input_event ev;

int ret = 0;

while((ret = read(evDev, &ev, sizeof(input_event)) != -1))

{

if(ev.code == ABS_MT_POSITION_X) tsState.x = ev.value;

if(ev.code == ABS_MT_POSITION_Y) tsState.y = ev.value;

if(ev.code == BTN_TOUCH) tsState.isPressed = ev.value == 1;

}

tsState.cb(tsState.isPressed, tsState.x, tsState.y); }


Теперь мы можем «возить» логотип Хабра по всему экрану:

void onTouchUpdate(bool isTouching, int x, int y) {

if(isTouching)

{

tsX = x;

tsY = y;

}

}

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

printf("Test\n");

m2dInit();

test = m2dLoadImage("test.tga");

test2 = m2dLoadImage("habr.tga");

printf("Volume: %i %i\n", vol, muteState);

m2dAttachTouchCallback(&onTouchUpdate);

while(1) {

m2dUpdateInput();

m2dClear();

m2dDrawImage(test, 0, 0, 1.0f);

m2dDrawImage(test2, tsX - (test2->width / 2), tsY - (test2->height / 2), 0.5f);

m2dFlush();

}

return 0;

}

Исходники закрыты, но мы не сдадимся: Пишем полностью нативное GUI-приложение под No-Name смартфон без Android Гаджеты, Смартфон, Linux, Телефон, IT, Хакеры, Hacking, Программирование, Embedded, C++, Одноплатный компьютер, Nix, Unix, Ядро, Kernel, Android, Длиннопост



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

❯ Звук, модем и другие возможности


Для звука нам придётся использовать ALSA — поскольку эта подсистема звука сейчас используется в большинстве устройств на Linux. Судя по всему, тут есть режим эмуляции старого и удобного OSS, поскольку устройства /dev/snd/dsp присутствует. Однако, вывод в него какого либо PCM-потока не даёт ничего, поэтому нам пригодится ALSA-lib.

Другой вопрос касается модема и сети. И если Wi-Fi ещё можно поднять (wpa_supplicant можно взять из раздела /system/), то с модемом будут проблемы — нет единого протокола по общению с ним и кое-где, чтобы его заставить работать, нужно будет немного попотеть. Не стесняйтесь изучать исходники ядра (MediaTek охотно делится реализацией вообще всего — там и RIL, и драйвер общения с модемом) и смотреть интересующие вас фишки!

❯ Заключение


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

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

Показать полностью 14
TECHNO BROTHER

Организация подсветки рабочего места или как сделать управление освещением с помощью голоса

Недавно я сделал ремонт в мастерской и установил столешницу вплотную к подоконнику и у меня всплыл вопрос об освещении - рассказываю в видосе о том, какой вариант освещения я выбрал для себя.

Это мой первый длинный видос в ютубе, прошу сильно тапками не кидать))

Ниже текстовая версия видоса для тех, кто не любит смотреть видео.

Организация подсветки рабочего места или как сделать управление освещением с помощью голоса Электроника, Радиотехника, Радиолюбители, Электричество, Техника, Освещение, Рабочее место, Видео, YouTube, Длиннопост

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

Организация подсветки рабочего места или как сделать управление освещением с помощью голоса Электроника, Радиотехника, Радиолюбители, Электричество, Техника, Освещение, Рабочее место, Видео, YouTube, Длиннопост

Для себя я взял 2 широкоугольных прожектора с углом светораспределения на 60 градусов и один на 24. Процесс установки мега прост – сверлим 3 отверстия в стене и подводим питание к шинопроводу. Всё, после этого уже можно устанавливать сами светильники на место. Для этого достаточно просто вщёлкнуть светильник в шинопровод. 2 широкоугольных прожектора равномерно освещают рабочую зону, а направленный используется только для работы с мелкими деталями.

Организация подсветки рабочего места или как сделать управление освещением с помощью голоса Электроника, Радиотехника, Радиолюбители, Электричество, Техника, Освещение, Рабочее место, Видео, YouTube, Длиннопост

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

Организация подсветки рабочего места или как сделать управление освещением с помощью голоса Электроника, Радиотехника, Радиолюбители, Электричество, Техника, Освещение, Рабочее место, Видео, YouTube, Длиннопост

Для этой цели подойдет два варианта – либо модуль радиореле с пультом, либо модуль умного дома. Я буду использовать второй вариант, потому что управлять голосом мне нравится больше.

Организация подсветки рабочего места или как сделать управление освещением с помощью голоса Электроника, Радиотехника, Радиолюбители, Электричество, Техника, Освещение, Рабочее место, Видео, YouTube, Длиннопост

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

Организация подсветки рабочего места или как сделать управление освещением с помощью голоса Электроника, Радиотехника, Радиолюбители, Электричество, Техника, Освещение, Рабочее место, Видео, YouTube, Длиннопост

Далее переходим к настройке модуля. Для это потребуются 2 приложения - Smart Life и Умный дом. Для начала необходимо привязать модуль через приложение SmartLife - для этого входим в приложение и создаём аккаунт, далее по инструкции из приложения привязываем модуль к нему. После этого модуль будет доступен в приложении и с помощью него можно будет уже управлять устройством.

Организация подсветки рабочего места или как сделать управление освещением с помощью голоса Электроника, Радиотехника, Радиолюбители, Электричество, Техника, Освещение, Рабочее место, Видео, YouTube, Длиннопост

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

Организация подсветки рабочего места или как сделать управление освещением с помощью голоса Электроника, Радиотехника, Радиолюбители, Электричество, Техника, Освещение, Рабочее место, Видео, YouTube, Длиннопост

А теперь момент про стоимость. Вся система мне обошлась в районе 9000 рублей, ссылки на все используемые модули прикрепляю ниже:

https://vk.cc/cpQFIV - Широкоугольный прожектор
https://vk.cc/cpQFM7 - Точечный светильник
https://vk.cc/cpQFN7 - Шинопровод
https://vk.cc/cpQFOA - Модуль умного дома

Буду рад услышать конструктивную критику и пожелания. Знаю, что пикабу в этом плане никогда не подведёт)

Показать полностью 8
Отличная работа, все прочитано!