В далёком 2005 году телефоны Siemens C75 и ME75 били рекорды популярности в бюджетном секторе благодаря привлекательному внешнему виду и демократичной цене.
Привлекал внимание и TFT-дисплейчик, имеющий разрешение 132×176 пикселей и палитру в 65536 цветов.
И вот, благодаря своей былой популярности, найти такие телефоны даже спустя 7-8 лет не представляет труда, и сегодня я поделюсь своими наработками, которые могут помочь использовать дисплеи данных телефонов в своих конструкциях.
Скажу сразу – данный дисплей мне очень понравился – миниатюрный, яркий и красочный, поэтому было решено продумать библиотеку для работы с ним по максимуму, т.к. при разработке своих устройств, из пары десятков индикаторов от различных старых телефонов, предпочтение отдаю именно ему.
В телефонах Siemens C75 и ME75 можно обнаружить два типа применяемых индикаторов — LPH9157-2 (с зелёным текстолитом) и некий ALPS (по крайней мере, под таким именем он фигурирует в Internet-ресурсах). Данный индикатор имеет жёлтый текстолит. В моей коллекции такой присутствует лишь в единичном экземпляре, поэтому написание библиотеки для работы с ним (увы!) в мои ближайшие планы пока не входит.
Дисплеи LPH9157-2 и ALPS:
Распиновка дисплея LPH9157-2:
1. CS – Chip Select. При установке в «0» контроллер дисплея принимает информацию;
2. RESET – вывод для сброса контроллера;
3. RS – вывод для определения типа передаваемых данных («0» — команда, «1» — данные);
4. SYNC – вывод для синхронизации с VGA-камерой (нам он не нужен);
5. CLK – вывод тактового сигнала для передачи данных;
6. DAT – вывод передачи данных;
7. 2,9V – к источнику питания;
8. GND – общий провод (земля);
9. VBOOST – вывод анодов светодиодов подсветки;
10. LIGHT DISP – вывод катодов светодиодов подсветки (к GND).
Схема подключения дисплея:
Резистор R7 подбирается с учётом необходимой яркости подсветки.
Для подключения дисплея к микроконтроллеру, можно собрать небольшую плату согласования уровней напряжения и оформить дисплей в виде модуля, подобно примеру в предыдущей статье. Но для желающих придать своей разработке более презентабельный вид, поделюсь печатной платой, на которой дисплей крепится в металлической рамке, снятой с платы телефона. Эту рамку, на первый взгляд крепко припаянную к основанию платы телефона, на деле легко снять с помощью скальпеля:
Оба варианта печатных плат для согласования дисплея с контроллером прилагаются в архиве.
Дисплей LPH9157-2 поддерживает три цветовые палитры: 256 цветов (8 бит на пиксель), 4096 (12 бит на пиксель) и 65536 цветов (16 бит на пиксель), в библиотеке же реализовано 2 палитры — 256 и 65536 цветов. Хотя работа с 8-ми битной палитрой предпочтительнее при небольшой частоте работы контроллера, в данном дисплее цвета в этом случае получаются очень бледными.
Datasheet на контроллер для дисплея LPH9157-2 найти не удалось, однако на глаза попался пример инициализации с подробным описанием команд, что уже было достаточно для начала экспериментов. Из команд инициализации особый интерес представляет команда Memory Access Control (36h), т.к. она позволяет задавать, с помощью следующего за ней байта данных, направление заполнения области дисплея.
В этом байте данных нас интересуют старшие 3 бита: 0bVHRXXXXX, где V – отвечает за направление заполнения по вертикали (0 — сверху-вниз, 1 — снизу-вверх), H — заполнение по горизонтали (0 — слева-направо, 1 — справа-налево), R – позволяет менять местами строки и столбцы.
Как видно из рисунка, вместе с изменением направления заполнения области дисплея, меняется и начальная позиция осей x и y.
Этого уже достаточно, чтобы при выводе текстовой информации обеспечивать программным образом поворот текста на 90º, 180º и 270º.
А почему же тогда, для правильного отображения текста, при его повороте на 90º, и 270º, не использовать возможность поменять строки и столбцы местами, чего можно добиться, устанавливая бит R в «1»?
Вот и я так подумал сначала, однако эксперимент с дисплеем показал, что фактическая область для отображения информации в этом случае ограничивается, как показано на рисунке красным цветом.
Потому, совместить быстрый вывод текстовой информации (предварительно задавая ту область дисплея, где предполагается изобразить символ) с возможностью изменения направления отображения текста невозможно. И, в угоду универсальности библиотеки, было решено пожертвовать скоростью вывода текстовой информации, что можно заметить при выводе большого текстового массива при малой частоте кварца микроконтроллера.
При выводе символа, функцией Send_Symbol (задаётся цвет символа и цвет фона) предварительно задаётся та область экрана, где будет отображён один байт из пяти, формирующих изображение (в библиотеке используется шрифт 5х8 пикселей). Изображение символа с помощью функции Send_Symbol_Shadow (без задаваемого цвета фона) – попиксельное.
С целью отображения на дисплее большого объёма текстовой информации, в библиотеке я использовал шрифт 5х8 пикселей, который, при увеличении масштаба изображения, немного напоминает такое течение в изобразительном искусстве, как кубизм. Вы можете использовать любой другой шрифт большего размера , для этого вам необходимо переработать функции Send_Symbol и Send_Symbol_Shadow под себя и учесть ширину символа в функциях LCD_Puts, LCD_Putsf, LCD_Puts_Shadow и LCD_Putsf_Shadow.
//===============================================================
// Функция прорисовки символа на дисплее
//===============================================================
void Send_Symbol (char symbol, char x, char y, int t_color, int b_color, char zoom_width, char zoom_height, int rot)
{
unsigned char temp_symbol, a, b, zw, zh, mask;
if (symbol>127) symbol-=64; //Убираем отсутствующую часть таблицы ASCII
for ( a = 0; a < 5; a++) //Перебираю 5 байт, составляющих символ
{
temp_symbol = font_5x8[symbol-32][a];
zw = 0;
while(zw != zoom_width) //Вывод байта выполняется zw раз
{
mask=0x01;
switch(rot) //Предварительно задаём область дисплея, где будет выводиться 1 байт из 5, формирующих символ
{
case 0: case 180: SetArea( x+zw, x+zw, y, y+(zoom_height*8)-1 ); break;
case 90: case 270: SetArea( x, x+(zoom_height*8)-1, y+zw, y+zw ); break;
}
LCD_RS = 1; //Передаются данные
for ( b = 0; b < 8; b++ ) //Цикл перебирания 8 бит байта
{
zh = zoom_height; //в zoom_height раз увеличится высота символа
while(zh != 0) //Вывод пикселя выполняется z раз
{
if (temp_symbol&mask)
{
#ifdef _8_BIT_COLOR //(8-ми битовая цветовая палитра (256 цветов))
Send_to_lcd( DAT, t_color ); //Данные — задаём цвет пикселя
#else //(16-ти битовая цветовая палитра (65536 цветов))
Send_to_lcd( DAT, (t_color >> 8) ); Send_to_lcd( DAT, t_color );
#endif
}
else
{
#ifdef _8_BIT_COLOR //(8-ми битовая цветовая палитра (256 цветов))
Send_to_lcd( DAT, b_color ); //Данные — задаём цвет пикселя
#else //(16-ти битовая цветовая палитра (65536 цветов))
Send_to_lcd( DAT, (b_color >> 8) ); Send_to_lcd( DAT, b_color );
#endif
}
zh—;
}
mask<<=1; //Смещаю содержимое mask на 1 бит влево;
}
zw++;
}
switch(rot)
{
case 0: case 180: x=x+zoom_width; break; //Получить адрес начального пикселя по оси x для вывода очередного байта
case 90: case 270: y=y+zoom_width; break; //Получить адрес начального пикселя по оси y для вывода очередного байта
}
}
}
//===============================================================
// Функция вывода одного символа ASCII-кода (из файла Symbols.h)
//===============================================================
void LCD_Putchar(char symbol, char x, char y, int t_color, int b_color, char zoom_width, char zoom_height, int rot)
{
unsigned char m;
if(zoom_width == 0) zoom_width = 1;
if(zoom_height == 0) zoom_height = 1;
switch (rot)
{
case 0: //Начальный адрес осей Х и У — левый верхний угол дисплея
Send_Symbol( symbol, x, y, t_color, b_color, zoom_width, zoom_height, rot);
break;
//================================
case 90:
m=y; y=x; x=m;
Send_to_lcd(CMD, 0x36);
Send_to_lcd(DAT, 0x40); //Начальный адрес осей Х и У — правый верхний угол дисплея
Send_Symbol( symbol, x, y, t_color, b_color, zoom_width, zoom_height, rot);
Send_to_lcd(CMD, 0x36);
Send_to_lcd(DAT, 0x00);
break;
//================================
case 180:
Send_to_lcd(CMD, 0x36);
Send_to_lcd(DAT, 0xC0); //Начальный адрес осей Х и У — правый нижний угол дисплея
Send_Symbol( symbol, x, y, t_color, b_color, zoom_width, zoom_height, rot);
Send_to_lcd(CMD, 0x36);
Send_to_lcd(DAT, 0x00);
break;
//================================
case 270:
m=y; y=x; x=m;
Send_to_lcd(CMD, 0x36);
Send_to_lcd(DAT, 0x80); //Начальный адрес осей Х и У — левый нижний угол дисплея
Send_Symbol( symbol, x, y, t_color, b_color, zoom_width, zoom_height, rot);
Send_to_lcd(CMD, 0x36);
Send_to_lcd(DAT, 0x00);
break;
//================================
default:
Send_to_lcd(CMD, 0x36);
Send_to_lcd(DAT, 0x00); //Начальный адрес осей Х и У — левый верхний угол дисплея
Send_Symbol( symbol, x, y, t_color, b_color, zoom_width, zoom_height, rot);
Send_to_lcd(CMD, 0x36);
Send_to_lcd(DAT, 0x00);
//================================
};
}
Также, при использовании библиотеки, следует иметь ввиду, что при запуске дисплея, начало адреса осей X и Y – левый верхний угол, а при изменении направления вывода текста или изображения (90º, 180º, 270º), осью X всегда будет считаться сторона над верхней частью выводимого текста или изображения.
Библиотека (для CodeVisionAVR) работы с LPH9157-2 содержит следующие функции (приведены лишь пользовательские функции!):
1. void LCD_init ()
Инициализация дисплея.
2. void Put_Pixel (char x, char y, unsigned int color)
Функция вывода точки (пикселя). x и y – координаты экрана, где будет отображён пиксель цветом color.
3. void LCD_Putchar (char symbol, char x, char y, int t_color, int b_color, char zoom_width, char zoom_height, int rot)
Функция вывода одного символа ASCII-кода. Данная функция рассчитана на вывод символов размером 5х8 пикселей, библиотека которых находится в файле Symbols.h. symbol – выводимый на экран символ в ASCII-кодировке; x и y – начальная координата вывода символа; t_color – цвет пикселя; b_color – цвет фона; переменные zoom_width и zoom_height увеличивают символ на экране в указанное число раз; rot – угол поворота текста (0º , 90º, 180º, 270º).
4. void LCD_Putchar_Shadow (char symbol, char x, char y, int t_color, char zoom_width, char zoom_height, int rot)
То же, что и 3, лишь без цвета фона.
5. void LCD_Puts(char *str, int x, int y, int t_color, int b_color, char zoom_width, char zoom_height, int rot)
Функция вывода строки, расположенной в ram-памяти микроконтроллера. В отличие от библиотеки для LPH8731-3C, для вывода строки задаётся не номер строки и столбца, на которые предполагаемо разбит экран, а адреса начальных пикселей x и y.
6. void LCD_Puts_Shadow (char *str, int x, int y, int t_color, char zoom_width, char zoom_height, int rot)
То же, что и 5, лишь без цвета фона.
7. void LCD_Putsf(flash char *str, int x, int y, int t_color, int b_color, char zoom_width, char zoom_height, int rot)
Функция вывода строки, расположенной во flash-памяти микроконтроллера.
8. void LCD_Putsf_Shadow (flash char *str, int x, int y, int t_color, char zoom_width, char zoom_height, int rot)
То же, что и 7, лишь без цвета фона.
9. void LCD_FillScreen (unsigned int color)
Функция заливки экрана цветом color.
10. void LCD_Output_image (char x, char y, char width, char height, flash char *img, int rot)
Функция вывода картинки. x и y начальная позиция выводимого на экран изображения; width и height – ширина и высота изображения (в пикселях); *img – указатель на массив данных, составляющих изображение; rot – угол поворота изображения (0º , 90º, 180º, 270º). Данная функция предполагает, что массив данных изображения расположен во flash-памяти микроконтроллера. Для преобразования необходимого вам изображения в массив, содержащий цвет пикселей, можно воспользоваться программами Image2Lcd или Nokia Image Creator, которые несложно найти на просторах интернета. Единственное требование – направление вывода массива изображения должно выполняться слева-направо, сверху-вниз! При использовании 16-ти битной палитры, при преобразовании изображения в массив типа char, обязательно старший байт должен идти первым!
11. void LCD_DrawLine (char x1, char y1, char x2, char y2, int color)
Нарисовать линию. x1 и y1 – начальная позиция линии; x2 и y2 – конечная позиция линии.
12. void LCD_DrawRect (char x1, char y1, char width, char height, char size, int color)
Нарисовать рамку. size — толщина рамки.
13. void LCD_FillRect (char x1, char y1, char width, char height, int color);
Нарисовать прямоугольник.
14. void LCD_DrawCircle (char xcenter, char ycenter, char rad, int color);
Нарисовать окружность. rad – радиус окружности в пикселях.
15. void LCD_FillCircle (char xcenter, char ycenter, char rad, int color);
Нарисовать круг, заполненный цветом color.
16. void LCD_DrawTriangle (char x1, char y1, char x2, char y2, char x3, char y3, int color)
Нарисовать контуры треугольника.
17. void LCD_FillTriangle (char x1, char y1, char x2, char y2, char x3, char y3, int color)
Нарисовать треугольник, заполненный цветом color.
В самом начале библиотеки, если объявлен макрос _8_BIT_COLOR, то цветовая палитра дисплея будет составлять 256 цветов, иначе — 65536 цветов. Макрос _GEOMETRICAL позволяет использовать функции вывода линии, рамки, прямоугольника, окружности, круга и треугольника.
Прикрепленные файлы:
- LPH9157-2.rar (7 Кб)
- LPH91572-Платы под ЛУТ.rar (40 Кб)