Внешний дисплей от Nokia 2760

Давно уже лежит у меня данный дисплей, но до сих пор на него времени всё не хватало. А задача для него то уже придумана и только и ждет воплощения. И вот все прочие дела наконец были отброшены и результат не заставил себя долго ждать.
Nokia 2760 LCD внешний

Сразу отвечу на вопрос: Даташита у меня НЕТ! Все работает и без него.

Характеристики

Как я уже писал, дисплей очень маленький и обладает следующими характеристиками:

  • Диагональ: 1 дюйм (20х16мм);
  • Разрешение заявленное: 96х68 пикселей (в телефоне заявлено 96х65 пикселей);
  • Размер: 24х24х3мм;
  • Глубина цвета: монохромный;
  • Подсветка: синяя (6-8В с резистором 47-300Ом);
  • Интерфейс: 3-х проводной SPI 9 бит;
  • Контроллер: ST7507 (Спасибо тов. WildCat);
  • Питание цифровой части: 1.8-3.3В;
  • Питание аналоговой части: 2.4-3.3В;

Не правда ли красавец? И по очень аппетитной цене.

Исходные данные

Очередной раз моя благодарность отправляется тов. Rossum’у, его поистине великий труд в изучении дисплеев очень помог.

Так же в данных одного из проектов был откопан моноширинный шрифт 5х7 который так же используется в дисплее от Nokia 3310.

Google же на этот раз дополнительной информации принес не много. Даташит так и не был найден. Жалко конечно, но зато есть возможность поковыряться самостоятельно.

Подключение

Распиновку дисплея можно узнать из Service Manual’а или же заглянув в проект NokiaSuperbreakout от Rossum’а:
Схема подключения внешнего дисплея от Nokia 2760

Разъем такой же как у Nokia 6100 (распиновка не совпадает!), и ответная часть находиться так же.

К своей LPCXpresso я подключил к SPI выводам: SCLK-SCK, MOSI-MOSI, CS-SSEL, RESET-MISO (а почему бы и нет?). Питание на подсветку завел с отдельного преобразователя на MC34063. Хотя на отражение (без подсветки) всё видно наверное даже лучше.

Настраиваем SPI на 9 бит

Инициализация SPI для дисплеев у меня кочует из проекта в проект практически без изменений, а я никак её не помещу в библиотеку (других учу, а сам этого не делаю):

void SPI_init() {	// Раздел 13.2 UM10375
    LPC_SYSCON->PRESETCTRL	&= ~(1<<0);
    LPC_SYSCON->PRESETCTRL	|= (1<<0);
    LPC_SYSCON->SYSAHBCLKCTRL	|= (1<<11);

    LPC_SSP->CPSR	= 0;	// отключим тактирование

    // Set P0.9 to SSP MOSI
    LPC_IOCON->PIO0_9	&= ~(7<<0);
    LPC_IOCON->PIO0_9	|= (1<<0);
    LPC_IOCON->PIO0_9	|= IOCON_COMMON_MODE_PULLUP;
    // Set 2.11 to SSP SCK (0.6 and 0.10 can also be used)
    LPC_IOCON->SCKLOC	= 1;
    LPC_IOCON->PIO2_11	&= ~(7<<0);
    LPC_IOCON->PIO2_11	|= (1<<0);
    LPC_IOCON->PIO2_11	|= IOCON_COMMON_MODE_PULLUP;
    // Set P0.2/SSEL to GPIO output and high
    LPC_IOCON->PIO0_2	&= ~(7<<0);
    LPC_IOCON->PIO0_2	|= (1<<0);
    LPC_IOCON->PIO0_2	|= IOCON_COMMON_MODE_PULLUP;
    LPC_GPIO0->DIR	|= 1<<2;
    LPC_GPIO0->DATA	|= 1<<2;

    LPC_SSP->CR0	=	( (8<<0)	// Размер данных 1000 - 9 бит
			 	| (0<<4)	// Формат фрейма 00 - SPI
			 	| (0<<6)	// Полярность 0 - низкий уровень м/у фрейм
			  	| (0<<7)	// Фаза 0 - по нарастанию
			  	| (8<<8)	// Делитель частоты шины на бит
			  	) ;

    LPC_SSP->CPSR	= 2;	// пердделитель 2-254 (кратно 2)

    LPC_SSP->CR1	= (1<<1);	// Разрешение работы 1 - разрешено
}

Эх, настроили на 9 бит и 4 МГц. Гм..., в теории должно быть FPS ~500. Что бы максимально приблизиться к этой цифре, передачу данных осуществляется в фоне:

void SPI_send(uint16_t value) {
    while ((LPC_SSP->SR & ((1<<1) | (1<<4))) != (1<<1)); 
    LPC_SSP->DR = value;
}

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

Инициализация дисплея

SPI нам нужен для дисплея, а дисплей перед общением с ним лучше сбросить. Сброс простецкий, но из-за криворукости лишний раз переключим функцию вывода SSEL:

void LCD_reset(void) {
    // Настройка для вывода Reset дисплея
    LPC_IOCON->PIO0_8	&= ~(7<<0);	// сброс текущей функции порта ввода-вывода
    LPC_IOCON->PIO0_8	|= IOCON_COMMON_MODE_PULLUP;
    LPC_GPIO0->DIR	|= 1<<8;
    LPC_GPIO0->DATA	|= 1<<8;
    // Настройка для вывода Select
    LPC_IOCON->PIO0_2	&= ~(7<<0);	// Временно отключаем спецфункцию вывода выбора SPI
    delay_ms(100);
    // Сброс дисплея
    LPC_GPIO0->DATA	&= ~(1<<2);	// ncs = 0
    LPC_GPIO0->DATA	&= ~(1<<8);	// nrst = 0
    delay_ms(100);
    LPC_GPIO0->DATA	|= 1<<8;	// nrst = 1
    LPC_GPIO0->DATA	|= 1<<2;	// ncs = 1
    delay_ms(100);
    // Возврат спецфункции
    LPC_IOCON->PIO0_2	|= (1<<0);	// использовать как вывод SSEL
}

Добавляем сюда инициализацию из NokiaSuperbreakout и получаем следующее:

void LCD_init()
{
	SPI_init();
	LCD_reset();
	SPI_send(0xE2);
	delay_ms(10);
	SPI_send(0xAF);
	SPI_send(0xA4);
	SPI_send(0x2F);
	SPI_send(0xB0);
	SPI_send(0x10);
	SPI_send(0x00);
}

После этого спокойно можно последовательно выводить данные на дисплей, как это делается в оригинале.

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

Вывод идет, так же как и для 3310, построчно столбиками по 8 пикселей, младший бит выводится вверху. Разница только в том, что 2760 инверсный: 0 соответствует черной точке, 1 её отсутствию. Последняя 9-я строка получается неполноценная. От неё доступны только младшие 4 бита.

Ну а раз работает всё так же, то возьмем вывод текста от 3310 для этого дисплея:

#include "font5x8.h"
void LCD_DrawChar(char c) {
	int i;
	unsigned char *ptr = &font[5*(unsigned int)c];
	for(i = 0; i < 5; i++) {
		SPI_send(0x100|~ptr[i]);
	}
	SPI_send(0x1FF); // пробел
}

void LCD_DrawString(const char *c) {
	while(*c) LCD_DrawChar(*c++);
}

Теперь весь дисплей можно заполнить символами. Что тоже нам не очень интересно, мы ведь привыкли указывать другим, что им делать. Так что без установки позиции курсора никуда:

void LCD_SetPos(uint8_t x, uint8_t row) {
	if(row > 9) row = 0;
	if(x > 96) x = 0;
	SPI_send(0xB0|(row));	// Номер строки
	SPI_send(0x10|(x>>4));	// Старшие 4 бита номера столбца
	SPI_send(0x0F&(x));	// Младшие 4 бита номера столбца
}

Конечно, для моноширинного шрифта было бы лучше позиционировать по ширине символа, что впрочем делается простым умножением.

Вот теперь пожалуй всё готово, можно пользоваться:
Внешний дисплей от Nokia 2760 в работе

Заключение

Дисплей оказался настолько простым в подключении, насколько и маленьким в размерах. При всём при этом он обладает довольно хорошим разрешением, что позволяет ему вместить большое количество информации (8 строк по 16 символов). Однако из-за этого мы получаем довольно мелкий текст (раза в 2 меньше 3310). Выход из этой ситуации естественно есть, достаточно просто взять шрифт крупнее.

Скорость вывода меня вполне устраивает, отклик дисплея в районе 0.2с (что по моему субъективному мнению быстрее, чем у 3310).

Потребление не замерял. Заявлено 0.5мА в активном режиме. Если для кого-то это принципиальный вопрос, то можете замерить сами.

Самая потребляющая часть – подсветка - может быть успешно отключена, на отражение видно прекрасно. Но её присутствие только в плюс дисплею в темное время.

В прикрепленном архиве отладочный проект. Вот несколько скринов его выполнения (2-х метровые файлы не поместили, так что только так):
Тест внешнего дисплея от Nokia 2760 (ASCII 0-127) Тест внешнего дисплея от Nokia 2760 (ASCII 128-255) Тест внешнего дисплея от Nokia 2760 (binary) Тест внешнего дисплея от Nokia 2760 (square)

Видео (качество не лучшее получилось).
<a href="http://www.youtube.com/watch?v=hUyNMtVn2Lw">Смотреть на YouTube: http://www.youtube.com/watch?v=hUyNMtVn2Lw</a>

Файлы: nokia2760.zip, DSC03013.JPG