Комментарии 107
Хабр — торт.
Кто там минусовал за Длинного за картинку с Боромиром и «нельзя просто так написать статью за 5 часов»? Стыдитесь.
Не соглашусь только, что I2C назван так за использование двух проводников. Двойка там — это на самом деле не «два», а «квадрат», а само I2C — это Inter-Integrated Circuit, но это несущественная мелочь.
В остальном — преклоняюсь. Сам разбил бы статью на десяток коротких заметок длиной в полгода, и еще не факт, что удалось бы закончить.
Кто там минусовал за Длинного за картинку с Боромиром и «нельзя просто так написать статью за 5 часов»? Стыдитесь.

Спасибо. Эту статью, если учитывать создание девайса и написание программы, я писал 3 недели. И всё делалось только ради поста. Так что, за 5 часов такие статьи не пишутся.

Про i2c, для понимания сути работы — не имеет значения. Править текст не буду, а те кому нужно прочтут твой комментарий. Спасибо.
А у меня тут два вопроса
Все же с чего лучше начать i2c или spi?

И второй — Кто то игрался с e-ink? Зашел к китайцам, там их вагон и тележка, что выбрать непонятно.
P.S. Хотя думаю самое дешевое на поигратся.
I2C — шинная архитектура с адресацией, имеет смысл для низких скоростей когда на одной шине больше одного устройства, да даже два — сомнительное преимущество применения I2C.

SPI — считай синхронный UART с выведенными наружу выводами регистра. Да собственно, отличия от UART тоже есть и довольно существенные.
Очень подходит для высоких скоростей, организация шины возможна только адресация ложится на плечи ВАШЕГО протокола передачи, стандарта на который попросту не существует. Ну и организация такой шины — циклический регистр сдвига который нужно прокачать ВЕСЬ чтобы услышать ответ первого устройства, либо иметь N отдельных входов для N устройств на шине.
Поиграться i2c — очень даже. Есть даже приложения в линухе, которыми можно обмениватся байтиками по этой шине. Мне она нравится больше из-за простоты. SPI — слабо стандартизован, но весьма топорен и надёжен. В общем, изучать лучше сразу оба :)))
Просто думаю на i2c тут датчики разные вешать, думаю сразу можно и дисплей.
Сейчас вот заинтересовался e ink.
А что там у китайцев с елинком? Что-то ничего найти не могу, можно ссылку?
Ну я сам хотел бы ссылки :) Хочется экранчик небольшой. Но в основном продают запчасти для ebook.
Ааа, ну дык, всё импатентами закрыто. Низзя, а если можно, то стоит просто конских денег…
Ну, это ещё гуманно. У китайцев можно найти от 30 долларов.

Как-то смотрел девкит от eink… Вот там ценник был абсолютно не любительский, около 3 тысяч евро.
А где и как искать?

На ебееях, dx-х и прочих неприличных словах что-то как-то ничего не гуглица…
Плюсую, люто и бешено — ваш способ более расово верный!
У вас слишком древнее ядро просто.

man dmesg
       -w, --follow
              Wait for new messages. This feature is supported on systems with
              readable /dev/kmsg only (since kernel 3.5.0).
Ну-ну… Неделю назад систему поставил.
uname -a
Linux dlinyj 3.11.0-12-generic #19-Ubuntu SMP Wed Oct 9 16:12:00 UTC 2013 i686 i686 i686 GNU/Linux
Эт да…

dlinyj@dlinyj ~ $ dmesg -V
dmesg from util-linux 2.20.1


Но всё это говорит лишь о том, что мой вариант самый универсальный. Ибо часто приходится иметь дело со старыми ядрами, и древними утилитами.
> dmesg -c

Для него рут нужен:

:~$ dmesg -c
dmesg: klogctl failed: Operation not permitted

Да и не особо мне нравится идея буфер очищать.
Надо будет проделать с подобным LCD все то же самое, только без собственных драйверов и через USB в рамках статей про FT232H.
Получится в разы проще, но и в разы менее хардкорно.
Я тоже об этом думал, но я б написал драйвер дисплея для FT232H. Тем более, что на сайте ftdi лежат исходники драйверов. Их остаётся только немного поправить под свою задачу.

Не, если хотите работать с дисплеем только со своей программой, то да. Так-то получается универсальная консоль.
Тоже вариант, только лучше тогда сразу на основе libftdi, чтобы с лицензиями проблем не было.
без драйвера всеравно не выйдет, только это будет драйвер другого уровня — который будет использовать готовый драйвер от микросхемы для реализации функции вывода в порт, остальное останется неизменным — так или иначе работу с индикатором надо будет реализовывать.
Спасибо вам огромное. Я то думал что написать драйвер под линукс нериально сложно и простой смертный на такое не способен. Однако хотел посмотреть как это делается, а все руки не доходили, а тут такой пост просто чудо.
Как человек, драйвера не пищуший, но иногда читающий, хочу сказать, что самые большие драконы скрываются в высокопроизводительных подсистемах — блочные устройства, сеть и графика. Остальному чуть легче жить.
Два символа: [b
И 2 совета:
1. Поставь в свою IDE плагин для проверки орфографии в комментариях и строках
2. Не оставляй комментариев на русском, пожалей наших англоязычных товарищей

С меня конфетка ;) Куда высылать?
А слабо продемонстрировать работу? Даю подсказку, можно завести в консоли, заменив print_to_string на printf :)

1. Надо почитать как для geany это сделать.
2. Учту. Я думаю заморочится и перевести статью на английский.
Вышли тому, кто продемонстрирует на LCD, а то в консоли — это не спортивно.
Мой LCD сейчас на работе, а те, что доступны в «удаленной лаборатории» моего ПТУ, подключены к Stellaris Launchpad и Infineon XE167FM EasyKit, запуск Linux на которых — еще больший хардкор, а через мой драйвер дисплея это писать еще менее спортивно, чем в консоль.
Идея с сервером классная, если что, я с вами :)
p.s.
Похоже, что этого парня ждут приключения:
Забыл про пасхалку в тексте:
Заголовок
Трололо, проверка на внимательность.
Красивая статья, спасибо.
Пожалуйста, добавьте название структуры file_operations в определение её объекта:
static const struct lptlcd_fops = { .owner = THIS_MODULE, .read = dev_read, .write = dev_write, };
Ох, выпало. Спасибо. На будущее — присылайте такое личным сообщением. Я сейчас поправлю, а ваш комментарий станет не актуальным.
Спасибо) Вспомнил, как писал для этого контроллера мини-библиотеку (на C под 8051) и потом портировал её на AVR для домашнего проектика.

Кстати, встречал дисплеи с русскими буквами (естественно, только теми, которые нельзя заменить соответствующими латинскими). Естественно, необходимо писать тривиальный табличный маппер.

Стоит упомянуть, что дисплею на этом контроллере необходима относительная хитрая инициализация. Правда, в разных источниках описывается чуточку различная процедура:
один вариант
Несколько слов о процессе инициализации ЖКИ-модуля. Производитель контроллера рекомендует выполнять следующую последовательность действий для инициализации. Выдержать паузу не менее 15 мс между установлением рабочего напряжения питания (> 4,5 В) и выполнением каких-либо операций с контроллером. Первой операцией выполнить команду, выбирающую разрядность шины (это должна быть команда $30 независимо от того, какой разрядности интерфейс вы собираетесь использовать в дальнейшем), причем перед выполнением этой операции не проверять значение флага BF. Далее опять выдержать паузу не менее 4,1 мс и повторить команду выбора разрядности шины, причем перед подачей команды вновь не производить проверку флага BF. Следующим шагом необходимо вновь выдержать паузу, на этот раз 100 мкс, и в третий раз повторить команду установления разрядности шины, вновь без проверки BF. Эти три операции являются инициализирующими и призваны вывести контроллер в исходный режим работы (то есть перевести в режим работы с 8-ми разрядной шиной) из любого состояния. Следом за ними нормальным порядком (без выдерживания пауз, но с проверкой флага BF) выполняется инициализация режимов работы с выдачей инициализирующей последовательности, аналогичной указанной в таблице 7 (содержащей в том числе команду выбора необходимой разрядности шины).
Отсюда: www.gaw.ru/html.cgi/txt/lcd/chips/hd44780/start.htm

Ещё вариант: joshuagalloway.com/lcd.html
Кстати, встречал дисплеи с русскими буквами (естественно, только теми, которые нельзя заменить соответствующими латинскими). Естественно, необходимо писать тривиальный табличный маппер.


Ну вообще, в статье есть пример экрана с русскими буквами — это дисплей кофейного автомата. А мапер и в этом экране используется.
А на счёт пауз и прочего, всё реализовано в либе, я даже об этом как-то и не думал.
Про кофеавтоматы вспоминается Lavazza BLUE Zenith, которые стояли на работе.

У них глючило всё: монетоприемник (не признавал часть монет и банкнот с первого раза), диспенсеры (выдывал по 2-3 ложечки, но скоро заканчивались; выдавал второй стакан в заполненный первый), управляющий софт глючил (иногда наливал американо при любом выборе, повисал).
Там играет звук, но сейчас я динамик отпаял, потому что он меня достал
НЛО прилетело и опубликовало эту надпись здесь
Хорошо, но это сокрее исключение, ну и нет её в наличии наверняка. На офсайте ничего нет точно.
Черт, аж руки зачесались :) Спасибо за отличную статью, несмотря на некоторые грамматические и орфографические недочеты, она великолепна!
Спасибо! А недочёты можете прислать личкой, с удовольствием поправлю.
У дисплея не контроллер погиб, а резинки поотклеивались. Скорей всего влага попадала. Разбери его, протри спиртом контакты, собери и будет как новенький.
У дисплея не контроллер погиб, а резинки поотклеивались.


Я тоже так думал, но артефакты «играют» когда пальцем бляху сзади щупаешь. Это раз, а во вторых погиб он после вооооот такой искры статики с пальца, я это видел. Статика резику не отклеивает.
Как круто, спасибо за ссылку! Тут какой-то быстрый экран, у меня даже на видео видно как всё тормозит. Это максимальная скорость.

Перезагрузка шрифтов на лету, великолепно!
Обычный, просто сделано не на делаях, а на ожидании busy флага. Он реально очень быстр так то. И может цепляться как память практически.
Да аппаратно там понятно как можно сделать, проблема в том, что сама ЖК матрица лагает. Погляди как у меня долго перерисовывается каждый символ на видео. Скорость максимальная, дальше просто фарш…
Там ещё с экраном было забавное в категории Wild, демо на информаторе хельсинского метро. Экран потом около главного входа почетно стоял.
www.youtube.com/watch?v=XCO1I3zSwps
«while true; do sudo dmesg -c; sleep 1; done»
тогда уж watch -n 1 dmesg -c
ещё и подсвечивать изменения умеет
Объяснение такой махинации простое: udelay внутри ядра не может принимать значения больше тысячи

Используйте же тогда mdelay(), конечно если важны точные значения интервалов времени. Ограниченный диапазон значений udelay в том числе из-за особенностей реализации задержек, где не используется вся разрядная сетка для счетчика. Точно деталей не знаю.
НЛО прилетело и опубликовало эту надпись здесь
По идее он таковым и является. Но слишком мало символов для этого.
О как! Только ночью сегодня подумал, что мне охренеть как нужны USB-часы показывающие системное время ОС, а тут такая хорошая поделка.
Я вот тут подумал, может быть все же можно будет раскрыть вопрос про usb?
Я малость долек от этой темы (нет с com и lpt я справлюсь) но вот usb для меня темный лес.
>Я умышленно ушёл от USB, т.к. там достаточно много теории, подводных камней и прочего геморроя. Но вы вполне можете переписать данный модуль для USB-LPT-шнурков, типа таких

^_^
Ну когда-нить я напишу про дрова для USB… А пока можно выкатить статью, как сделать это на AVR…
Вообще, я хотел на 7-сегментных индикаторах сделать, и LPT порт у меня есть родной, на материнке. Так что это вроде как даже проще будет.
А я забавы ради изучал программирование под AVR, и подцепил к attiny2313 экранчик, реализовал переселку текста на МК по uart, а МК уже передает на экран, так что я тоже с компа могу на экранчик выводить новогоднее поздравление, вы только скажите как его забрать из интернета!
Можно, кстати без проблем перенести этот код в AVR. Просто при получении байта по UART, содержимое регистра UDR передавать в функцию handleInput (как раз в сути своей будет функция dev_write). Переписать задержки и сделать вывод ваш порт в функции:

void expanderWrite(unsigned char _data){                                        
    //outb(((_data) | _backlightval), BASEPORT); //x86 instruction rootfs!!!!!
    //outb_p(((_data) | _backlightval),BASEPORT); //x86 instruction kernel!!!!!
    //вот здесь надо делать вывод в ваш порт
}


И сделать функцию задержек:

int delayMicroseconds(int value)
{
  /usleep(value); 
   return 0; 
}


В gcc по моему есть delay. И далее так же можно тупо выводить данные перенаправляя вывод в СОМ-порт и будут рабоать ESC-последовательности.
А для вступления в тусовку, с сообщениями — надо вступить в группу :) см. ссылку внизу поста.
А помнишь мы не так давно обсуждали как писать дрова, и ты мне говорил, мол всё просто, а я ныл, что это гемморой :)))))
Ну да, и мясо ели с пивом вприкуску :) Я вроде тогда рассказывал как раз как я катал драйвер вот для такого же дисплея + подвязанной к нему через диоды матричной клавы. И для 1-вайр. И все это было уже > 10 лет назад, свистело и пердело на старенькой 486-ой матери, и стояла там еще неведомой редкости SSD-шка (как их щяс модно называть) DiskOnChip IDE на аж целых 16 мегабайт на которой гнездился линукс фром скретч :) А девайс так у меня и не удался тогда и как проект загнулся, т.к. я не смог побороть «магические» перезагрузки, которые походу возникали от хренового БП… Тогда, в 16 лет не смог осилить ту проблему :(
Блин, аж ностальгия пробила, вот были времена!
У меня вот такая штуковина есть: LCD2USB, давно уже собирал, подключается по usb.

image
Ахренительно 40х4. Думал таковых не бывает в природе. Ну осталось прослойку протокола написать между нашим и вашим :))))
Они на двух HD44780. Софтовая часть из-за этого становится менее приятной)
Если рассматривать конкретное устройство выше — то у него есть ещё внешний контроллер (какая-то AVR), которая с точки зрения софта на компе — единый дисплей.

Если смотреть на железо — там два почти независимых контроллера с 4хбитной шиной. И контроллер, использующий дисплей, выводит нужные части на разные HD44780. Т. е. общие d0-3, rs, rw, vcc, gnd, contrast и раздельные e1 и e2.
Т. е. общие d0-3, rs, rw, vcc, gnd, contrast и раздельные e1 и e2.


Собственно это меня и интересовало. Цена ещё у них кусается. За такие бабки проще с графическим разобраться. Тем более, что я прикидывал, что если взять экран 40х4, то он будет эквивалентен графическому:
40*6х4*9=240х36 (по пикселю добавил на пробел между символами).
У 40x4 дисплеев есть два дополнительных вывода E1 и E2, подавая лог. уровень на один из них, можно выводить символы на первую половину (20x4) или на вторую.
Есть еще старенький 20x8, там еще веселее — 4 отдельных чипа. Филипс — LM324.
Простите мое невежество.

static const struct file_operations lptlcd_fops = {
    .owner  = THIS_MODULE,
    .read   = dev_read,
    .write  = dev_write,
};


Что обозначают точки перед полями структуры? Для чего они?
Это синтаксис инициализации структур из ansi c 99. Так можно более наглядно и удобно инициализировать поля структур (в произвольном порядке, например).
Решил присоединиться к празднику жизни. Сегодня-завтра опубликую пост.

Возник вопрос при реализации (в описании vt100/vt52 не нашел): [X и [Y отличаются порядком аргументов?
Псот лучше всего будет опубликовать с сегодня на завтра в ночь :))))

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

echo -en "\033[Y\037\038Hello" > /dev/lptlcd

Выведет в нулевую позицию по Y и в первую по X
Этот вариант я увидел. У вас, кстати, опечатка: \038. Сам мало восьмиричной системой пользуюсь, так же ошибаюсь. Шестнадцатиричная как-то привычнее.

Реализовал в итоге так:
— ESC-Y[Y-координата+037][X-координата+037]
— ESC-X[X-координата+037][Y-координата+037]
Да… Опечатка, точняк. Нулевая позиция по Y будет 037+0=037, а первая по X 037+1=040

А шестнадцатиричная — да…
Как же просто работать с таким дисплеем по i2c на raspberry + wiringPi. По сути воткнул — и работает.
Ну, все функции, которые вы указали для ESC-последовательностей уже реализованы в wiringPi. Если уж так надо, то никто не мешает линейно парсить входную строку на наличие нужных кодов и вызывать соответствующие функции.
Вы мой код не смотрели? Я так и делаю. И поверьте, что i2c, что параллельный порт — никакой разницы.
Кстати, для справки, данный дисплей, который я юзаю в этом проекте изначально был i2c, потом платка была снята.
Сергей, хорошая статья. Рад, что Вы с таким увлечением занялись разработкой модулей ядра!
Многие мои друзья и знакомые крутят пальцем у виска или задаются вопросом: не жмёт ли мне череп, когда узнают, что я пишу драйвера под Linux.


Сочувствую :) У самого все более запущено — иногда приходится объяснять знакомым (когда те узнают, что я работаю программистом), что, нет, я не ломаю аккаунты Вконтакте, и вообще сфера деятельности как бы другая. «Ну тыжпрограммист...».
P.s. Сам также увлекаюсь разработкой под Linux kernel. Спасибо за статью, было интересно.
Спасибо. Я даже не знаю, будет ли код работать под современные ядра. Не проверял.
В современных (ну уже как несколько лет :) ) ядрах есть уже свой драйвер (drivers/auxdisplay/panel.c), а кто хочет научиться, тем как раз и впору будет понять как сделать forwardport.
Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.