19 декабря 2013

Поздравление по гиковски, без написания дров

Настройка Linux*nix


Прочитал статью «Создание собственных драйверов под Linux» от камрада dlinyj и загорелся идеей озвученной в конце статьи. А именно

Сейчас ничего не мешает заплатить на месяц 500 рублей (а если скинемся, сумма будет совсем мелкой), и арендовать сервак на виртуалке. Туда поставить программулину, которая будет рассылать сообщения. Либо jabber либо какие-то другие способы (да хоть nc и telnet всё сделать). А на компе поставить приёмник этих сообщений. И на Новый Год все мы будем иметь поздравления.


И принял решение таки влиться в общую тусовку, получить и отправить своё гиковское поздравление. Искать LPT-порт на своем ноутбуке я не стал, знаю, что его нет. Зато вспомнил, что несколько лет назад делал дисплей подключаемый к COM-порту. Точнее не совсем к СОМ-порту, это переходник USB-to-UART, о котором dlinyj говорил в этом посте «UART и с чем его едят». В результате было принято решение сделать на нём.



Железо



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

Внешний вид платы

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

СхемаПолный размер

Ничего сложного. И у каждого радиолюбителя наверняка представленный набор элементов. Я даже больше, чем уверен, что каждый, кто работал с контроллерами AVR имеет хотя бы одну такую платку, только с чутка другими схемами. FT232RL можно заменить на MAX232 (с соответствующим обвесом) или использовать готовый USB-UART переходник. Транзистор на подсветке, так же не обязателен (это схема управления подсветкой). Можно её с лёгкостью заменить просто подсоединением к земле.

Тем кто является счастливым владельцем отладочной платы PinBoard v1 от DIHALT даже искать и паять ничего не придется. Все необходимое уже есть.


PinBoard v1

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


Arduino

Осознав, что с аппаратной частью у меня все хорошо (и даже избыточно) я перешел к написанию прошивки для имеющегося микроконтроллера. В моем случае это Atmega 16, но в целом это не имеет большого значения.

Софт!



Библиотеки для работы с LCD у меня уже имелись, код для инициализации был выдернут из старого проекта и довольно банален. Была попытка использовать библиотеку от проекта камрада dlinyj, но видимо от количества вызовов-перевызовов функций у контроллера срывало стек, и работало всё нестабильно. В результате я решил таки всё сделать на своей библиотеке.
Целиком код приводить не буду, каждый сможет посмотреть в исходниках весь проект. Остановлюсь на ключевых моментах.

Во первых, надо описать пины для подключения дисплея, они описываются в файле hd44780_hw.h
#include "hd44780_hw.h"  //describe LCD PINS connection


Скорость работы UART была выбрана 9600. Так сложилось исторически, и не спрашивайте почему.

#define baudrate 9600L


Вся инициализация “железа” идёт в функции HwInit. Инициализации всего ничего:

//HW initialisation 
void HwInit(void)
{
	//InitUSART
	UBRRL = LO(bauddivider);
	UBRRH = HI(bauddivider);
	UCSRA = 0;
	UCSRB = 1<<RXEN|1<<TXEN|1<<RXCIE|0<<TXCIE;
	UCSRC = 1<<URSEL|1<<UCSZ0|1<<UCSZ1;
 	sei();//разрешаем прерывания
	//InitLCD	
	lcd_init(LCD_DISP_ON);
	lcd_clrscr();
}


Осноная задача — это обработка ESC-последовательностей, которую я нагло взял у Длиного, а он соответственно взял у Michael McLellan в его проекте lptlcd. Сам обработчик вынесен в esc.c, а мы же вызываем ту же самую функцию handleInput, которая и парсит наш запрос. Вызыв этой функции идёт в обработчике прерывания по приёму UARTa

//UART interapt
ISR(USART_RXC_vect)
{
	handleInput(UDR);
	return;
}


Каждый байт, пришедший в UART, вызывает прерывание. И в обработчике прерывания мы берём и скармливаем функции handleInput.

Эта функция мало чем отличается от аналогичной функции в проекте драйвера на lpt-порт. Разве, что были заменены функции установки в позицию экрана, очистки экрана и вывода символа на экран на функции из моей библиотеки. Плюс так же убрана функция вывода пасхалки, т.к. она работает только на четырёхстрочном экране и с библиотеками Длиного, а у нас иная либа да и экранчик всего 16х2. Ну из неприятного, пока не реализована функция загрузки своих шрифтов. Там пока стоит заглушка.

Тестируем



Компилируем. Для сборки я пользуюсь AVR Studio версии 4 + avr-toolchain (3.3.0.710). Прошиваем. Пока у нас идёт прошивка, еще раз взглянем на используемые ESC-последовательности. Цитирую текст исходной статьи.

Итак, управляющие последовательности, для нашего экрана:

  • \033 = Отправка ESC-последовательности, с которой начинаются команды
  • [A = Переместить курсор на одну строку вверх
  • [B = Переместить курсор на одну строку вниз
  • [C = Сдвинуть курсор на одну позицию вправо
  • [D = Сдвинуть курсор на одну позицию влево
  • [H = Переместить курсор в левый верхний угол — домой (позиция 0,0)
  • [J = Очистить всё, НЕ возвращает курсор домой!
  • [K = Стирает до конца строки, НЕ возвращает курсор домой!
  • [M = Новая карта символов (ДЗ — объяснить зачем!)
  • [Y = Позиция Y (см. FAQ ниже)
  • [X = Позиция X (см. FAQ ниже)
  • [R = CGRAM Выбор ячейки памяти
  • [V = Прокрутка включена
  • [W = Прокрутка вылючена
  • [b = Подсветка включена-выключена (у нас работать не будет).


Другие полезные команды, работают без префикса \033!

  • \r = Возврат каретки (возвращают курсор в позицию 0 на текущей линии!)
  • \n = Новая линия
  • \t = Табуляция (по умолчанию 3 символа)



Я так же настоятельно рекомендую вернуться ещё раз к оригинальной статье habrahabr.ru/post/206148 и посмотреть FAQ с картинкам — примеры их применения.
Цепляем свежепрошитый контроллер к порту USB, и видим, коммандой dmesg, что у нас в системе появилось новое устройство:

/dev/ttyUSB0


И даём следующую команду:

 echo -en "\033[H\033[J   Happy GEEEKS\r\n Happy New Year"  > /dev/ttyUSB0


И в результате получаем совершенно новогоднее поздравление от гиков:


Поздравление по ГИКОВСКИ!!!

Ну и ставший уже традиционным скрипт вывода времени так же работает:

while true; do     echo -en "\033[H`date +\"%d.%m.%Y\"` \r\n`date +%r`" > /dev/ttyUSB0 ;    sleep 1s; done



Гик-часы

А как же PinBoard V1?



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

#define LCD_DATA_PIN_D7  PA6	/* arbitrary pin for LCD data line D7 */
#define LCD_DATA_PIN_D6  PA5	/* arbitrary pin for LCD data line D6 */
#define LCD_DATA_PIN_D5  PA4	/* arbitrary pin for LCD data line D5 */
#define LCD_DATA_PIN_D4  PA3	/* arbitrary pin for LCD data line D4 */

#define LCD_DATA_PINR_D7 PINA	/* input pin register for LCD data line D7 */
#define LCD_DATA_PINR_D6 PINA	/* input pin register for LCD data line D6 */
#define LCD_DATA_PINR_D5 PINA	/* input pin register for LCD data line D5 */
#define LCD_DATA_PINR_D4 PINA	/* input pin register for LCD data line D4 */

#define LCD_DATA_DDR_D7 DDRA	/* ddr for LCD data line D7 */
#define LCD_DATA_DDR_D6 DDRA	/* ddr for LCD data line D6 */
#define LCD_DATA_DDR_D5 DDRA	/* ddr for LCD data line D5 */
#define LCD_DATA_DDR_D4 DDRA	/* ddr for LCD data line D4 */

#define LCD_DATA_PORT_D7 PORTA	/* port for LCD data line D7 */
#define LCD_DATA_PORT_D6 PORTA	/* port for LCD data line D6 */
#define LCD_DATA_PORT_D5 PORTA	/* port for LCD data line D5 */
#define LCD_DATA_PORT_D4 PORTA	/* port for LCD data line D4 */

#define LCD_RS_DDR       DDRA   /* ddr for RS line */
#define LCD_RS_PORT      PORTA  /* port for RS line */
#define LCD_RS_PIN       PA0
#define LCD_RW_DDR       DDRA  /* ddr for RW line */
#define LCD_RW_PORT      PORTA  /* port for RW line */
#define LCD_RW_PIN       PA1
#define LCD_E_DDR        DDRA  /* ddr for Enable line */
#define LCD_E_PORT       PORTA  /* port for Enable line */



Сохраняем, компилируем и прошиваем результат в пинборд и выполняем следующую команду:

echo -en "\033[H033[JSpasibo DiHalt" > /dev/ttyUSB0 



Поблагодарим автора платы!

Зачем всё это нужно?



Если мы оторвёмся от хабра и посмотрим на календарь, то ВНЕЗАПНО обнаружим, что до Нового Года осталось 10 дней. А ведь хочется праздника не только с роднёй, но и паяльно-виртуального! Вот для того всё это и затевается.
Товарищ dlinyj создал группу, кто хочет поздравить друг-друга по гиковски. Прямо сейчас там народ думает над серверно-клиенской частью. Она пока ещё, к сожалению, не готова. Но мы надеемся, что если ты подключишься к нам, то мы обязательно всё доведём до ума! Если у тебя есть дисплей, и ты хочешь быть в тусовке, то вступай туда. Это не несёт никакой коммерции или личной выгоды, просто добрые поздравления с новым годом на экране.

Тем у кого экрана все же нет, а поздравления по гиковски получать хочется, расстраиваться рано. ESC-последовательности работают и в обычной консоли. Так что выводя сообщения на экран, всё будет работать

Например, если выполнить команду:
while true; do     echo -en "\033[H`date +\"%d.%m.%Y\"` \r\n`date +%r`" ;    sleep 1s; done


Убирая перенаправление вывода не стоит забывать про очистку экрана. Иначе получим интересный эффект:


Часы прямо в консоли

Чтобы такого не было, следует перед while добавить команду clear;. Теперь будет всё выглядеть так:

 clear; while true; do     echo -en "\033[H`date +\"%d.%m.%Y\"` \r\n`date +%r`" ;    sleep 1s; done



Консоль, вместо дисплея

Итоги



Хочется создать атмосферу праздника, а для праздника нужны друзья. Где ж ещё гику искать друзей, кроме своих? Поэтому возможно и мы выбираем столь экзотический способ поздравить друг-друга с Новым Годом!

Ссылки для скачивания:



Исходники для моей платы и Пинборда можно скачать тут
Теги:linuxuartlcdgeek pornhappy new yearhd44780сделай сам
Хабы: Настройка Linux *nix
+38
17,5k 71
Комментарии 40
Лучшие публикации за сутки