![](https://habrastorage.org/webt/y6/4s/iz/y64sizbg2xy31bltlws6l9rqvnk.png)
Чёрт возьми! Я не мог оставить без внимания тот факт, что мой предыдущий дурацкий проект получил настолько живой отклик. Вряд ли мне когда-либо удастся превзойти такое соотношение приложенных усилий и полученных за них «интернет-очков». Дурацкий, глупый и бесцельный — похоже, это мои дежурные слова. А что станет наиглупейшим апгрейдом для глупейшего дисплея, как ни придание ему вида а-ля стимпанк? Но в моём представлении это никак не цепляние к шляпе покрашенных в золото шестерёнок. Если я говорю стимпанк, то подразумеваю фрезерованную латунь и накатку.
Зацените видео изготовления и демонстрации работы:
Как обычно, музыкальным сопровождением стала собственная композиция, которая в высоком качестве доступна на моей странице bandcamp.
Сборка
За исключением USB-светильника, от которого я отрезал гибкую металлическую стойку, все детали были изготовлены из подручных средств. Меня невероятно порадовало воплощение изначальной задумки (латунного HDMI DDC-дисплея на гибкой стойке) в готовый прототип буквально на следующий день.
Сначала я сделал быстрые наброски в OpenSCAD, чтобы соблюсти размеры, и затем ещё раз, чтобы оценить, как будет смотреться фаска. Саму фаску я сделал неуклюжим образом с помощью вычитания куба, поскольку вряд ли в OpenSCAD есть что-то более подходящее, а переделка в «нормальном» пакете CAD заняла бы куда больше времени, чем простое копирование.
![](https://habrastorage.org/webt/ai/er/ij/aierijvjc0cwwh4tkx24el75hyq.png)
В отношении разъёма меня интересовал лишь нужный диаметр накатки и то, окажется ли достаточным паз, сделанный торцевой фрезой на 6мм. Обозначенные красным цилиндры указывают крайние точки паза.
![](https://habrastorage.org/webt/kn/sg/5h/knsg5hjeo0qvqd-grqwtna_qzaq.png)
Собрать разъём наверняка можно было и пограмотнее, например, стянув его мелкими винтами через резьбовые отверстия, но я решил обойтись литым соединением с помощью термоклея, просто потому что так интереснее.
![](https://habrastorage.org/webt/12/v3/yk/12v3ykyz_dzft_ljg0pvkw3ijo4.jpeg)
Изначально я планировал использовать для сборки блока дисплея винты поменьше. В моём миниатюрном наборе резьбонарезных инструментов есть метчики вплоть до M1.0, но подходящих винтов под такие отверстия у меня не было. Я нашёл несколько M1.6, но они оказались слишком короткими (можно, конечно, было сделать углубление, но при зарисовке в OpenSCAD такой вариант смотрелся не очень), поэтому я взял винты M2.
![](https://habrastorage.org/webt/if/ot/ml/ifotml-6zddlpm9uvwwu78y-vic.jpeg)
Причиной нанесения «патины» стало то, что после спайки блока дисплея он отличался цветом от свежевыточенного разъёма. Думаю, что со временем изделие обрело бы монотонный латунный цвет, но я решил ускорить процесс, повторно обработав детали горелкой.
Немало времени я раздумывал над тем, какой длины сделать гибкую стойку. Очень хотелось, чтобы она была максимально короткой, как показано в раннем макете:
![](https://habrastorage.org/webt/al/7b/am/al7bamruxc95yfn-huoegexkr1w.jpeg)
Этой длины точь-в-точь бы хватило для сгибания под 90°, что даже немного забавно и приумножает общую бессмысленность проекта. Но в итоге я решил сделать стойку чуть длиннее, чтобы можно было изменять её направление. Напомню, что она с каждой стороны вклеена, и свободно вращаться не может, поэтому укороченный её вариант также ограничивает возможность вращения дисплея.
![](https://habrastorage.org/webt/bu/vh/la/buvhlazsarnevhzeziopuojdqjo.png)
![](https://habrastorage.org/webt/uc/rd/ep/ucrdepje8lnz_xlowaxlkaqx7ks.png)
«Стимпанк» хорош тем, что вам не обязательно подчищать места пайки — неряшливые потёки флюса только приукрашают общий вид.
![](https://habrastorage.org/webt/tt/zh/yt/ttzhytig5hy79dljj_ccs24pwne.png)
Дополнительные фото
![](https://habrastorage.org/r/w1560/webt/jc/pz/kp/jcpzkpusi3mct3ccl91ujlkk07e.png)
![](https://habrastorage.org/r/w1560/webt/y6/4s/iz/y64sizbg2xy31bltlws6l9rqvnk.png)
![](https://habrastorage.org/r/w1560/webt/t7/-l/pz/t7-lpzzgkfjwlbqu65ypbshwe_i.png)
![](https://habrastorage.org/r/w780q1/webt/4n/co/cp/4ncocpiiah3qg_fpu5f_ud4a9x8.jpeg)
![](https://habrastorage.org/webt/jc/pz/kp/jcpzkpusi3mct3ccl91ujlkk07e.png)
![](https://habrastorage.org/webt/y6/4s/iz/y64sizbg2xy31bltlws6l9rqvnk.png)
![](https://habrastorage.org/webt/t7/-l/pz/t7-lpzzgkfjwlbqu65ypbshwe_i.png)
![](https://habrastorage.org/webt/4n/co/cp/4ncocpiiah3qg_fpu5f_ud4a9x8.jpeg)
На снимках можно видеть, что дисплей не совсем точно отцентрован в оправе. Я очень старался не повредить его хрупкий экран, поэтому оставил по кругу полумиллиметровый зазор. В итоге дисплей в случае прикосновения может немного соскальзывать. В реальности это не особо заметно, но при близком рассмотрении прямо бросается в глаза. Это можно исправить, разобрав корпус и закрепив дисплей двухсторонним скотчем либо добавив по краям подложку.
![](https://habrastorage.org/webt/kn/hl/gv/knhlgvvkq2lse9h0ypkdsozlpx4.jpeg)
Доработка драйвера
Если вы всё ещё читаете, то наверняка в ожидании чего-то более интеллектуального.
Сперва должен упомянуть evdi, на который мне указали вскоре после публикации первой статьи про DDC OLED. Я этот инструмент не испытывал, но он похож именно на то, что я искал — виртуальный интерфейс дисплея как раз для подобного применения.
DDC-порт моего ноутбука работает на 100КГц. Это около 10КБ/с, включая начальный и стоп-биты. И если учесть, что для полноценного обновления дисплея требуется 1КБ, то теоретически максимальная скорость кадров составит около 10 в секунду.
А с учётом дополнительной нагрузки на однопоточный скрипт Python получается и того меньше, поскольку операции записи, блокировки, а также захвата изображения, и перестановки бит — занимают какое-то время. Очевидно, что дисплей может делать отрисовку намного быстрее. Даже если забыть о параллельном интерфейсе для SSD1306, в ином сценарии мы бы могли запустить I2C на 400КГц. Однако в случае с DDC наши возможности весьма ограничены.
Вместо этого, я сделаю то, чего делать не собирался — обновлю скрипт, чтобы он передавал только изменения.
Сложностей это вызвать не должно. Единственные неудобства могут быть связаны разве что с причудами SSD1306. После перестановки бит мы передаём полный килобайт данных для каждого кадра. Контроллер настроен так, чтобы при достижении конца строки продолжать со следующей.
К сожалению, для позиционирования указателя нет простого способа. Если мы хотим пропустить первые N байт, то нужно перенастроить область отрисовки. В результате при достижении конца строки очередная будет начинаться с первого столбца области отрисовки, а не продолжаться с первого столбца дисплея. При изменении области отрисовки указатель всегда возвращается в верхний левый угол её прямоугольника.
![](https://habrastorage.org/webt/1w/j9/m-/1wj9m-4sufye42xty0racehm-t4.png)
Перенастройка области отрисовки добавляет к вычислительной нагрузке около 8 байт, поскольку переопределять эту область приходится при каждом достижении конца страницы, за исключением случаев, когда очередная строка должна начинаться в том же столбце. Также важно помнить, что если перерисовке подлежит весь кадр, то это не должно занимать больше времени, чем в случае оригинального драйвера.
Я довёл этот процесс до удовлетворительного состояния, хотя его определённо можно оптимизировать. В частности, если изменяется лишь небольшой прямоугольник изображения, это нужно обнаруживать и отправлять только одну команду переопределения области отрисовки.
Даже если первые столбцы не будут одинаковы для каждой изменившейся строки, они будут смещены в пределах всего нескольких байт относительно друг друга, и мы сможем добиться общей экономии, очертив эту область прямоугольником и передав новые данные только для неё.
К сожалению, это подразумевает разделение исходных данных таким образом, который может легко вызвать путаницу. Если на дисплее изменятся два небольших прямоугольника, то нам придётся передавать байты не по порядку.
Вместо этого, я пошёл простым путём: «Если очередные N байт не изменяются, и N больше стоимости двойного переопределения, пропустить эти байты».
Заметьте, что при включённом дизеринге одно только это не особо ускоряет отрисовку. Метод
.convert(1)
, используемый для преобразования изображений, позволяет выбирать между дизерингом Флойда-Стейнберга и его отсутствием. Если он включён, то всё, что находится справа внизу любого изменения, вероятно, также изменится, поскольку нарушится структура дизеринга. Эффективнее здесь сработает более простой алгоритм, но всё же лучше будет применить дизеринг до отрисовки курсора мыши. В результате он хотя бы будет реагировать на её перемещение, а остальная часть экрана вместо того, чтобы пульсировать, останется неподвижной.В качестве ещё одной доработки репозитория я добавил скрипт-обёртку для обнаружения I2C-устройства по имени, а не изменчивому номеру, и для автоматической установки/сброса настроек xrandr.
На этом проект завершается. Общая продолжительность заснятого видео составила около трёх с половиной часов. При этом его монтаж в двадцатиминутный ролик занял ещё больше времени.
![](https://habrastorage.org/webt/ou/g5/kh/oug5kh6sjydt9llengsiebnp40w.png)