Jump to content

    

ЖКИ на основе SED1520

Никак не соображу как лучше рисовать символы.

Сейчас работаю следующим образом:

1. Есть массив, в котором лежат все символы в виде {0x00, 0xFF, 0xFF, 0xAA, 0x84, 0xFF и т.д.}. Символ размером 8x6(высота, ширина). То есть для 10 символов получается массив из 60 байт.

2. Есть массив структур. В структуре лежит сам символ и индекс, с которого этот символ начинается в массиве описанном выше.

При вызове функции вывода символа на экран (например printf('A')), ищу в массиве структур нужный мне символ, беру из этой структуры индекс, с которого начинается символ в массиве и последовательно вывожу 6 байт символа.

Может кто-нибудь знает способ проще и быстрее? :)

Share this post


Link to post
Share on other sites
Может кто-нибудь знает способ проще и быстрее? :)
Раз размер символов фиксирован - достаточно умножить код символа на размер и прибавить к адресу начала массива. Если массивов несколько - то под каждый может быть структура с размером символа и указателем на начало массива.

Share this post


Link to post
Share on other sites
Раз размер символов фиксирован - достаточно умножить код символа на размер и прибавить к адресу начала массива.

"код символа" - имеется ввиду ascii-код? Если да, то для массива в котором хранятся цифры 0-9 и буквы А-Я(в порядке возрастания кодов) нужно будет сделать одну промежуточную операцию: если рисуем цифру, то из кода символа нужно вычесть код '0', а если букву, то вычесть код 'А'. Затем уже умножаем получившееся число на размер символа - это и есть индекс начала символа в массиве. Или я не прав?

Share this post


Link to post
Share on other sites
"код символа" - имеется ввиду ascii-код? Если да, то для массива в котором хранятся цифры 0-9 и буквы А-Я(в порядке возрастания кодов) нужно будет сделать одну промежуточную операцию: если рисуем цифру, то из кода символа нужно вычесть код '0', а если букву, то вычесть код 'А'. Затем уже умножаем получившееся число на размер символа - это и есть индекс начала символа в массиве. Или я не прав?

Заполните всю кодовую таблицу для 256 символов, цифры и буквы уравняются в правах :)

Тогда не нужно ничего анализировать.

Чуть больше места в памяти, но будет быстрее работать.

А если сделать матрицу 8*8 (все равно нужны промежутки между символами), расположить таблицу по адресу с 11 младшими нулевыми разрядами и заменить перемножение на сдвиг и логическое сложение, все будет просто летать, как на Пентиуме :biggrin:

Share this post


Link to post
Share on other sites
А если сделать матрицу 8*8 (все равно нужны промежутки между символами), расположить таблицу по адресу с 11 младшими нулевыми разрядами и заменить перемножение на сдвиг и логическое сложение, все будет просто летать, как на Пентиуме :biggrin:

Сам хотел сделать 8*8, но экрана не хватит для всей информации :(

Размер экрана 120*32, разница в 5 символов получается.

А что значит "расположить таблицу по адресу с 11 младшими нулевыми разрядами"? То есть положить в память, например по адресу 0x800?

PS. пишу на Си под msp430

Share this post


Link to post
Share on other sites
А что значит "расположить таблицу по адресу с 11 младшими нулевыми разрядами"? То есть положить в память, например по адресу 0x800?

PS. пишу на Си под msp430

Если 8 байтов не получается, то тогда нет смысла, остается умножение:

 

unsigned char * a = table_pointer+ ((unsigned int) my_char)*6;
SendToLcd(*a);
a++;
SendToLcd(*a);
a++;
SendToLcd(*a);
a++;
SendToLcd(*a);
a++;
SendToLcd(*a);
a++;
SendToLcd(*a);
a++;

 

Сделайте SendToLcd() pragma inline forced, и будет максимальное быстродействие.

Share this post


Link to post
Share on other sites
Никак не соображу как лучше рисовать символы.

Может кто-нибудь знает способ проще и быстрее? :)

Я использую для рисования библиотеку uc-GUI или отдельные её части (на небольших платформах типа AVR).

В частности для шрифтов есть специальные утилитки, позволяющие создавать по-пиксельные изображения любых шрифтов (в т.ч. разных размеров, bold, italic)... Я использую все структуры, которые используются в uc-GUI, тем самым достигается легкость в использовании шрифтов различных размеров и типов (пропорциональные и моноширинные).. Для пропорциональных шрифтов в структуры специально закладывается отступ для каждого символа..

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

Если вас заинтересуют подробности, утилиты, некоторые исходники... пишите в PM :)

Share this post


Link to post
Share on other sites
Сделайте SendToLcd() pragma inline forced, и будет максимальное быстродействие.

Спасибо за помощь, так и сделаю.

Share this post


Link to post
Share on other sites

Вот, что у меня получилось. Дельные комментарии приветствуются :)

#ifndef lcd_header
#define lcd_header

#include <msp430x16x.h>
#include "symbols.h"
#include "mytypes.h"

uChar lcd_CurrColumn; // текущий столбец LCD-дисплея
uChar lcd_CurrPage;	 // текущая страница LCD-дисплея

//P4
#define lcd_Data			P4OUT
#define lcd_ImageOff			0xAE // выключить изображение
#define lcd_ImageOn			0xAF // включить изображение
#define lcd_StaticControlOn	0xA4 // включить статическое управление
#define lcd_StaticControlOff	0xA5 // выключить ---//---
#define lcd_Reset			0xE2 // сброс
#define lcd_SetStartString		0xC0 // установить начальную строку
#define lcd_SetPage			0xB8 // установить страницу
#define lcd_SetColumn		0x00 // установить столбец
//P6
#define lcd_Control			P6OUT
#define lcd_A0				BIT4
#define lcd_RW				BIT5
#define lcd_E1				BIT6
#define lcd_E2				BIT7
#define lcd_E12				0xC0

/// Функция посылки комманды на LCD-дисплей.
/// cmd - комманда, посылаемая дисплею.
/// param нужен только для установки начальной строки, страницы и столбца;
/// в остальных случаях он не используется.
/// Значения начальной строки могут быть 0-31,
/// страницы 0-3, столбца 0-119.
///
void LcdSendCommand(uChar cmd, uChar param)
{
lcd_Control &= ~(lcd_A0 + lcd_RW); // подаем на входы A0 и RW низкий уровень

switch(cmd) // записываем комманду в ОЗУ дисплея
{
case lcd_SetStartString:/* начальная строка */
	lcd_Data = (cmd | param);
	lcd_Control |= lcd_E12;  // разрешаем выполнение
	lcd_Control &= ~lcd_E12; // для обоих частей экрана
	break;

case lcd_SetPage:/* страница */
	lcd_Data = (cmd | param);
	lcd_CurrPage = param;	 // устанавливаем новую текущую страницу
	lcd_Control |= lcd_E12;  // разрешаем выполнение
	lcd_Control &= ~lcd_E12; // для обоих частей экрана
	break;

case lcd_SetColumn:/* столбец */
	if(param <= 59)		 			// если столбец < 60,
	{
		lcd_Data = (cmd | param);
		lcd_Control |= lcd_E1;		// то выполняем для левой части
		lcd_Control &= ~lcd_E1;
	}
	else									// иначе
	{
		lcd_Data = (cmd | (param - 60));
		lcd_Control |= lcd_E2;		// выполняем для правой части
		lcd_Control &= ~lcd_E2;
	}
	lcd_CurrColumn = param;			// устанавливаем новый текущий столбец
	break;

default:/* остальные комманды */
	lcd_Data = cmd;
	lcd_Control |= lcd_E12;  // разрешаем выполнение
	lcd_Control &= ~lcd_E12; // для обоих частей экрана
	break;
}

}; /* LcdSendCommand() */

/// Функция посылки данных на LCD-дисплей.
/// data - 8 бит данных.
///
#pragma inline=forced
void LcdSendData(uChar *data)
{
lcd_Control |= lcd_A0; // высокий уровень на A0
lcd_Control &= ~lcd_RW;// низкий уровень на RW
lcd_Data = *data;		  // записываем данные в ОЗУ дисплея	

/* рисуем на нужной половине экрана */
if(lcd_CurrColumn <= 59)
{ lcd_Control |= lcd_E1; lcd_Control &= ~lcd_E1; }	
else
{ lcd_Control |= lcd_E2; lcd_Control &= ~lcd_E2; }		

}; /* LcdSendData() */

/// Функция рисования символа на дисплее.
/// symb - символ, который нужно нарисовать.
///
void LcdPutChar(uChar symb)
{
for(uChar i = 0; i < 6; i++)
{
	LcdSendData(&symb_array[(symb * 6) + i]);
	lcd_CurrColumn++;				// увеличиваем счетчик столбца

	if(lcd_CurrColumn == 60)	// если кончилась левая половина экрана
		LcdSendCommand(lcd_SetColumn, lcd_CurrColumn);

	if(lcd_CurrColumn == 120)	// если столбец выехал за правую половину экрана
	{
		lcd_CurrColumn = 0;		// обнуляем столбец
		lcd_CurrPage++;			// и переходим на след страницу

		if(lcd_CurrPage > 3)		// если страница >3, то переходим на верхнюю
			lcd_CurrPage = 0;

		LcdSendCommand(lcd_SetPage, lcd_CurrPage);	 // устанавливаем новую
		LcdSendCommand(lcd_SetColumn, lcd_CurrColumn);// страницу и столбец
	}
}

}; /* LcdPutChar() */

/// Функция вывода строки текста на экран.
/// str - указатель на строку, которую нужно вывести.
///
#pragma inline=forced
void LcdPutText(uChar *str)
{
while(*str)
	LcdPutChar(*str++);

}; /* LcdPutText() */

/// Функция очистки LCD-дисплея.
///
#pragma inline=forced
void LcdClearScreen()
{
LcdSendCommand(lcd_SetColumn, 0); // устанавливаем столбец
LcdSendCommand(lcd_SetPage, 0);	 // и страницу в 0
uChar tmp[] = "                    "; // 20 пробелов, чтобы
for(uChar i = 0; i < 4; i++)			  // зарисвать 4 строки
	LcdPutText(tmp); // зарисовываем весь экран пробелами

}; /* LcdClearScreen() */

/// Функция инициализации LCD-дисплея
///
#pragma inline=forced
void InitLcd()
{
LcdSendCommand(lcd_SetStartString, 0);
LcdClearScreen();
LcdSendCommand(lcd_ImageOn, 0);

}; /* InitLcd() */

#endif /* lcd_header */

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this