Вывод картинок на дисплей Nokia 1616

В продолжение поста Подключение дисплея Nokia 1616 на примере LPC1343 займемся выводом на дисплей картинок.

Вывод упакованного изображения

Упакованное изображение будет самого простого формата. Вначале идет один байт количества повторений, а за ним по 3 байта данные о цвете. Если старший бит байта повторений 1, то цвет надо повторить N+1 раз. Если же старший бит нулевой, то дальше без дублирований перечислены N+1 пикселей. В обоих случаях N – младшие 7 бит от байта повторений. такой формат легко распаковать, и он не требует много памяти. Худший случай будет, когда ни один пиксель не повторяется – размер увеличиться где-то на 1% (1 байт на каждые 128 пикселей), что вполне терпимо.

Конечно, можно было и по 2 байта на пиксель сохранять, или палитру добавить, но это вы при желании сделаете и сами. А я приведу свой пример:

void DrawImage(const uint8_t *data, uint16_t len)
{
	uint8_t n;
	uint8_t r, g, b;
	while(len > 3) {
		n = *data;
		len--; data++;
		if(n & 0x80) {
			// Повторение одного пикселей одного цвета
			n = (n & 0x7f) + 1;
			r = data[0];
			g = data[1];
			b = data[2];
			len -= 3; data += 3;
			while(n--) {
				NextPoint(RGB(r, g, b));
			}
		} else {
			// Пиксели разного цвета
			n = (n) + 1;
			while(n-- && len >= 3) {
				r = data[0];
				g = data[1];
				b = data[2];
				len -= 3; data += 3;
				NextPoint(RGB(r, g, b));
			}

		}
	}
}

Данная функция предполагает, что область вывода была установлена зарание. Это позволяет провести настройку области вывода, а затем порциями отдавать само изображение (полезно при чтении данных с SD карточки или приеме по UART/USB. Единственное, порция данных должна содержать целое число блоков.

Вызывается так:

uint8_t img[] = { 0x84, 0xFF, 0x00, 0xFF, // 5 пикселей фиолетового цвета
    0x02, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00 // 3 пикселя синий, зелёный, красный
};
BeginDraw(30, 30, 4, 2);
DrawImage(img, sizeof(img));
// ... дополнительные вызовы DrawImage если надо
EndDraw();

фотографии не приведу, бо пиксели не видно на снимках с китайской мобилы :)

Скорость вывода на 9МГц получилась порядка ~24 кадров в секунду.

Как ни странно, но в итоге вывод картинок мне не пригодился (ну лень мне было логотип на дисплей создавать). Собственно этим и объясняется явная недоработка и необходимость отдельной установки границ вывода. Однака тестовые примеры были, о чем осталось память:
Вывод изображений

Вывод иконок

Иконки для дисплея
По сути, иконка это такое же изображение, только в моем случае оно ограничено двумя цветами и размером всегда 8х8 пикселей. Это многое нам упрощает, включая их создание. Так, приведённый набор был создан просто в паинте, а затем просто переведен из двоичной системы в шестнадцатиричную. В итоге получаем следующий код:

// Константы номеров иконок
#define ICON_CLOCK	0
#define ICON_CONNECT	1
#define ICON_DISK	2
#define ICON_FLASH	3
#define ICON_HEART	4
#define ICON_HEART3	5
#define ICON_LAN	6
#define ICON_MAIL	7
#define ICON_SOUND	8
#define ICON_POWER	9
#define ICON_PRINTER	10
#define ICON_RECIVE	11
#define ICON_SEND	12
#define ICON_STATUS	13
#define ICON_WAN	14
#define ICON_WLAN	15
#define ICON_WIRELESS	16
#define ICON_POINT	17
#define ICON_NOCONNECT	18

const uint8_t icons8x8[] = {
		0x3C, 0x42, 0x91, 0x95, 0x99, 0x81, 0x42, 0x3C,	// clock
		0x50, 0x50, 0xF8, 0x89, 0x8A, 0x72, 0x24, 0x18,	// connect
		0x3C, 0x5A, 0xA5, 0xDB, 0xDB, 0xA5, 0x5A, 0x3C,	// disk
		0x2A, 0x2A, 0xFF, 0x81, 0xC1, 0xFF, 0x2A, 0x2A,	// flash
		0x66, 0xDB, 0x81, 0x81, 0xC3, 0x42, 0x24, 0x18,	// heart
		0x24, 0x7E, 0x9F, 0xBF, 0xFF, 0x7E, 0x3C, 0x18,	// heart2
		0x7E, 0x42, 0x42, 0x42, 0x7E, 0x00, 0xFF, 0xFF,	// lan
		0x00, 0xFF, 0xC3, 0xA5, 0x99, 0x81, 0xFF, 0x00,	// mail
		0x19, 0x3A, 0xE8, 0xCB, 0xC8, 0xEA, 0x39, 0x18,	// music
		0x18, 0x18, 0x5A, 0x99, 0x99, 0x99, 0x42, 0x3C,	// power
		0x3C, 0x24, 0xFF, 0xFF, 0xC3, 0xC3, 0xFF, 0xFF,	// printer
		0x18, 0x18, 0x18, 0x18, 0xFF, 0x7E, 0x3C, 0x18,	// recive
		0x18, 0x3C, 0x7E, 0xFF, 0x18, 0x18, 0x18, 0x18,	// send
		0x3C, 0x42, 0x99, 0xBD, 0xBD, 0x81, 0x42, 0x3C,	// status
		0x18, 0x34, 0x28, 0x18, 0x66, 0xD5, 0xAB, 0x66,	// wan
		0x18, 0x99, 0xDB, 0x7E, 0x3C, 0x18, 0x18, 0x18,	// wireless
		0x30, 0x64, 0xC9, 0xDA, 0xDA, 0xC9, 0x64, 0x30,	// wireless2
		0x00, 0x00, 0x18, 0x3C, 0x3C, 0x18, 0x00, 0x00,	// point
		0x52, 0x54, 0xF8, 0x99, 0xAA, 0x72, 0xA4, 0x18,	// disconnect
};

Следующие функции на самом деле были созданы для вывода текста, но т.к. иконки у нас тоже двуцветные, то почему бы не объединить похожие сущности?

uint32_t colorFace;		// цвет текста/пера
uint32_t colorGround;		// цвет фона/заливки

void SetFaceColor(uint32_t color) {
	colorFace = color;
}
void SetGroundColor(uint32_t color) {
	colorGround = color;
}

Ну и собственно Вывод иконки получается до безобразия простым. Но в данном случае область отображения мы выставляем сами. Далее просто последовательно прозодим по битам иконки и выбираем один из двух цветов для вывода.

void DrawIcon8x8(int16_t x, int16_t y, uint8_t id)
{
	if(id >= sizeof(icons8x8)/8) return;
	const uint8_t *data = &icons8x8[info->icon * 8];
	if(!data) return;
	// Установка области вывода
	if(BeginDraw(x, y, 8, 8)) {
		uint8_t i, j, mask;
		for(i = 0; i < 8; ++i) {
			mask = *data++;
			for(j = 0; j < 8; ++j) {
				NextPoint( (mask & 0x80) ? colorFace : colorGround );
				mask<<=1;
			}
		}
		EndDraw();
	}
}

Вызов функций элементарный

SetFaceColor(ox00FF00FF); // иконка фиолетового цвета
SetGroundColor(0x00FFFFFF); // белый фон
DrawIcon(0, 152, ICON_CONNECT);
SetFaceColor(ox0000FF00); // иконка зелёного цвета
DrawIcon(10, 152, ICON_RECIVE);

К сожалению сии 64 пикселя так же трудно рассмотреть на полученных фотографиях. Поблагодарим нашего спонсора - магазин китайских телефонов. :)

При работе на 9МГц в теории получится ~7000 иконок в секунду. Практических замеров не будет, с меня хватило замеров с дисплеем 6100. Для него теория с практикой на 4МГц различалась не более процента (всё изображение попадает на экран, в итоге отсечение отключается и упор идет в шину SPI).

< Предидущая Следующая >
Hosted by uCoz