Графический дисплей LCD 12864 (128x64 пикселя) на ST7920

Дисплеи, датчики и прочие функциональные узлы, управляемые МК.
Аватара пользователя
WiseLord
Друг Кота
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск
Контактная информация:

Re: Графический дисплей LCD 12864 (128x64 пикселя) на ST7920

Сообщение WiseLord »

[uquote="slav0n",url="/forum/viewtopic.php?p=4101702#p4101702"]ну, и шо?[/uquote]Да ничего. Подход рабочий, но неэффективный. Если хватает ~10 FPS (украдём от озвученных ранее 13 немного на другой код помимо отрисовки) - то и хорошо.

Я и сам первоначально так же делал - обновлял из видеобуфера дисплей в конце главного цикла. Но можно буквально совсем немного переделать, то что уже есть - и станет намного шустрее всё.

У Вас там в любом случае есть код вроде такого:
Спойлер

Код: Выделить всё

write_display(char data)
{
      PORTB = data;
      strob();
      big_delay_us(60);
}

update_display()
{
  for (int i = 0; i < W; i++) {
    char cmd;
    // позиционирование
    WR = 0;
    write_display(cmd1);
    write_display(cmd2);
    write_display(cmd3);
    WR = 1;
    // посылка данных
    for (int i = 0; i < H / 8; i++) {
      index = ...;
      char data = buffer[index];
      write_display(data);
    }
}
Его очень легко переделать на конечный автомат, по сути сделав i, j статическими переменными. Так, чтобы каждый вызов update_display() посылал ровно один байт данных. Тогда, дёргая этот вызов из прерывания таймера раз в 60мкс и убрав в коде обычную задержку получим ровно то же самое по сути, только дисплей будет обновляться автоматически, без использования главного цикла. А задачей самого же главного цикла останется только подкладывание нужных байтов в видеобуфер.

P.S. Если интересно, применение озвученного подхода можно глянуть здесь: https://github.com/WiseLord/ampcontrol/ ... rc/display - файлы st7920.c/h.

То есть, весь конечный автомат построен на двух переменных (i, j). Переменная j на каждом прерывании таймера инкрементируется (от 0 до 31), записывая последовательно данные в выбранный ряд. Следующая фаза - j=32 - установка номера страницы, за который отвечает i. Следующая фаза j=33 - установка адреса начало страницы в ноль и сразу же перевод дисплея в режим чтения. Следующая фаза j = 34 - читается состояние на порту дисплея. Ну а дальше - переход в фазу 0 и всё по кругу - в выбранную страницу записывается пачка данных (32 байта) из буфера.

То есть, помимо того, что запись в дисплей идёт "в фоне", практически не задерживая главный цикл, наличие таймера позволяет параллельно регулировку яркости через ШИМ и периодом 34 * 60 = ~2мс (500Гц) опрашивать состояние ножек на линии данных дисплея. То есть, там ещё могут висеть до 8 кнопок (замыкающихся на землю через резистор)
Аватара пользователя
slav0n
Опытный кот
Сообщения: 882
Зарегистрирован: Ср дек 01, 2010 00:38:15
Откуда: Харьков
Контактная информация:

Re: Графический дисплей LCD 12864 (128x64 пикселя) на ST7920

Сообщение slav0n »

малі діти...
WiseLord писал(а):У Вас там в любом случае есть код вроде такого:
лично мой код вроде такого, самодостаточный, без статиков
не требует прерываний

Код: Выделить всё

void Screen_Update(void)
{
#ifdef ST7920
//ST7920
	for(u8 y=0; y<32; y++){	
		low_WrComDat(0x80 + y, 1);//com
		low_WrComDat(0x80 + 0, 1);//com
		u16 s = (y * 16) & 0x0180;//0b110000000
		
		const u8 mask = shift_1_left[y % 8];
		
		for(u8 x=0; x<32; x++){
			if(x == 16) s += 512;//0x0200
			u16 p = (x % 16) * 8 + s;
			u8 d = 0;
			u8 m = 0b10000000;
			for(u8 i=0; i<8; i++){
				if(VIDEObuf[p + i] & mask) d += m;
				m >>= 1;
			}
			
			low_WrComDat(d,0);//dat
		}
	}
#else
	//KS0108
	for(u8 y=0; y<8 ;y++){
		low_WrComDat(0xb8+y, LCD_CS1, 1), low_WrComDat(0x40, LCD_CS1, 1);
		
		for(u8 x=0; x<128; x++){
			if(x == 64) low_WrComDat(0xb8+y, LCD_CS2, 1), low_WrComDat(0x40, LCD_CS2, 1);
			low_WrComDat(VIDEObuf[y*128 + x], 0, 0);
		}
	}
#endif
}
ohmycode!
primuss3.com
Аватара пользователя
WiseLord
Друг Кота
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск
Контактная информация:

Re: Графический дисплей LCD 12864 (128x64 пикселя) на ST7920

Сообщение WiseLord »

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

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

P.S. Вот я попробовал на примере показать, как я бы постепенно (main1.c => main5.c) перешёл на возможность вызывать Ваш код так, чтобы задержка была не внутри него, а извне. Ну, или по таймеру в уже самом последнем варианте.

main1.c - исходный вариант

main2.c - добавляю фазы -2 и -1 для переменной x, чтобы единообразно отправлять low_WrComDat в одном цикле

main3.c - избавляюсь от внутреннего цикла по y, вынося его наружу, запоминая текущую фазу y в уже глобальной переменной (в принципе, её можно и внутри функции статической оставить)

main4.c - избавляюсь от внутреннего цикла по x, вынося его также наружу. Это позволяет также задержку изнутри low_WrComDat() вынести наружу.

Теперь ничто не мешает вызывать Screen_Update откуда угодно. Можно оставить как есть, полностью имитируя старое поведение (вызывать в конце главного цикла 34*32 раз) с задержками. Можно вызывать в конце главного цикла всего лишь 1 раз с одной задержкой - то есть, каждый проход главного цикла будет обеспечивать запись лишь 1 байта в экран (а команды или данных - конечный автомат на x/y сам разберётся), лишь с 1 задержкой на 60мкс

main5.c - а также можно теперь Screen_Update просто вызывать из прерывания таймера, вообще избавившись от любых задержек в главном цикле.
Вложения
testfb.7z
(1.26 КБ) 280 скачиваний
Последний раз редактировалось WiseLord Чт окт 07, 2021 11:46:30, всего редактировалось 1 раз.
Аватара пользователя
slav0n
Опытный кот
Сообщения: 882
Зарегистрирован: Ср дек 01, 2010 00:38:15
Откуда: Харьков
Контактная информация:

Re: Графический дисплей LCD 12864 (128x64 пикселя) на ST7920

Сообщение slav0n »

WiseLord писал(а):биты раскладывать на этапе записи в буфер, а читать сразу готовые байты последовательно из массива.
просто я тогда не стал заморачиваться и оставил организацию буфера как у KS0107, для универсальности.
В реале на паялке оно выдает 15 фпс, на спекруме конечно меньше, т.к. там идет активный обмен по кв.шине, но меня вполне устраивает
не вижу смысла переделывать, разве что для спортивного интереса
тем более, еще не измерена инерционность самого стекла
ohmycode!
primuss3.com
Аватара пользователя
WiseLord
Друг Кота
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск
Контактная информация:

Re: Графический дисплей LCD 12864 (128x64 пикселя) на ST7920

Сообщение WiseLord »

slav0n писал(а):не вижу смысла переделывать, разве что для спортивного интереса
Ну так в спортивном-то интересе самый смак. Мне и самому было бы интересно узнать, что из этого бы получилось, тем более что идею - что имнно и в каком порядке делать - для ST7920 я расписал. Для KS0108 принцип был бы тот же - постепенно избавиться от циклов, вынеся их переменные наружу.

Технически, до самого последнего момента (переноса в прерывание) всё должно отрабатывать фактически с той же скоростью (поскольку задержки всё ещё присутствуют), и только на последнем этапе ожидается резкий скачок FPS
Аватара пользователя
GoldenAndy
Поставщик валерьянки для Кота
Сообщения: 1925
Зарегистрирован: Чт июл 28, 2016 07:58:37
Откуда: Kyiv, UA
Контактная информация:

Re: Графический дисплей LCD 12864 (128x64 пикселя) на ST7920

Сообщение GoldenAndy »

Скачка ФПС не будет. Ибо 80 мкс на команду никуда не денутся.
А вот скачок idle - будет. И это хорошо.
А более правильно этот дисплей переводить на камушек с ДМА.
Я пробовал на СТМ - удобно. Хватает времени на всё.
А вообще - для большинства задач взаимодействия с пользователем и 10 фпс хватит. И времени на обработку действий юзера.
Или вообще - обновление только по требованию.
Возникло событие - перерисовали и обновили.
ИзображениеИзображение
Изображение
 
Telegram               Лучшая благодарность ->
[+]
Аватара пользователя
slav0n
Опытный кот
Сообщения: 882
Зарегистрирован: Ср дек 01, 2010 00:38:15
Откуда: Харьков
Контактная информация:

Re: Графический дисплей LCD 12864 (128x64 пикселя) на ST7920

Сообщение slav0n »

WiseLord писал(а):Ну так в спортивном-то интересе самый смак.
давай разложим по полкам запись-чтение видеобуфера.

мой вариант:
чтение - побитно
запись
знакогенератор - побайтно
графика - побитно

твой вариант:
чтение - побайтно
запись
знакогенератор - побитно
графика - побитно

при выводе текста никакой разницы.
выигрыш, казалось бы, при выводе графики, но, учитывая тормознутость матрицы, он тоже под вопросом.
ohmycode!
primuss3.com
Аватара пользователя
WiseLord
Друг Кота
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск
Контактная информация:

Re: Графический дисплей LCD 12864 (128x64 пикселя) на ST7920

Сообщение WiseLord »

GoldenAndy писал(а):Скачка ФПС не будет. Ибо 80 мкс на команду никуда не денутся.
Может, я не так выразился. Говоря о FPS, я имел в виду, сколько главных циклов в секунду может выполнять программа. Тут число вполне может поменяться с 15 на, например, 2000, если нет каких-то тяжёлых вычислений. Если есть (типа Фурье анализа того же) - может поменяться с 15 до, скажем например, 50.
А обновление дисплея - да, быстрее не станет. Но оно будет сконцентрировано не в одном месте (в конце главного цикла), а "размазано" равномерно по времени выполнения.
slav0n писал(а):при выводе текста никакой разницы.
выигрыш, казалось бы, при выводе графики, но, учитывая тормознутость матрицы, он тоже под вопросом.
В целом, да. Я просто на основании своего опыта рассуждаю, когда в проекте анализатора спектра такое небольшое, казалось бы, изменение в коде позволило раза в 2 увеличить FPS.
Грубо, если для обновления дисплея требуется 50мс, и на расчёты (Фурье) - те же 50мс, то Ваш подход даст 100мс общей задержки - т.е. обработка сигнала будет возможна только 10 раз в секунду. А обновление по таймеру как раз даст возможность обработать сигнал 20 раз в секунду, невзирая на то, насколько быстрый или медленный дисплей.
Аватара пользователя
slav0n
Опытный кот
Сообщения: 882
Зарегистрирован: Ср дек 01, 2010 00:38:15
Откуда: Харьков
Контактная информация:

Re: Графический дисплей LCD 12864 (128x64 пикселя) на ST7920

Сообщение slav0n »

прикинь, ЭТО пихать в прерывание каждые 60 мкс?..
тануегонах!

Код: Выделить всё

void Screen_Update(void)
{
	static u8 y = 0;
	static s8 x = -2;
	u16 s = (y * 16) & 0x0180;//0b110000000
	const u8 mask = shift_1_left[y % 8];
	u8 com = 1;
	u8 d = 0;
	if (x == -2) {
		d = 0x80 + y;//com
	} else if (x == -1) {
		d = 0x80 + 0;//com
	} else {
		com = 0;
		if (x == 16) s += 512;
		u16 p = (x % 16) * 8 + s;
		u8 m = 0b10000000;
		for (u8 i = 0; i < 8; i++) {
			if (VIDEObuf[p + i] & mask) d += m;
			m >>= 1;
		}
	}
	low_WrComDat(d, com);
	
	if (++x >= 32) {
		x = -2;
		++y; y %= 32;
	}
}
далеко и надолго
ohmycode!
primuss3.com
Аватара пользователя
WiseLord
Друг Кота
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск
Контактная информация:

Re: Графический дисплей LCD 12864 (128x64 пикселя) на ST7920

Сообщение WiseLord »

Почему я выше и писал про то, что читать из буфера желательно как можно проще - по байту. А все манипуляции битами отдать на запись в этот буфер.

Но даже и сейчас, то что есть, с циклом по битам, вполне успеет выполниться за несколько (до 10) микросекунд.
Аватара пользователя
slav0n
Опытный кот
Сообщения: 882
Зарегистрирован: Ср дек 01, 2010 00:38:15
Откуда: Харьков
Контактная информация:

Re: Графический дисплей LCD 12864 (128x64 пикселя) на ST7920

Сообщение slav0n »

зачем мне оно, если у меня на мега32 единственное прерывание ISR(TIMER0_OVF_vect) вызывается с периодом 0.781 ms
при этом: дисплей, 3 ШИМа, 2 ПИДа, энкодер, музыка... все работает
даже TIMER1 не задействован
ohmycode!
primuss3.com
Аватара пользователя
slav0n
Опытный кот
Сообщения: 882
Зарегистрирован: Ср дек 01, 2010 00:38:15
Откуда: Харьков
Контактная информация:

Re: Графический дисплей LCD 12864 (128x64 пикселя) на ST7920

Сообщение slav0n »

попробовал ЭТО, типа, оптимизировать, а компилятор совершенно не отреагировал на изменения

Код: Выделить всё

void Screen_Update(void)
{
	static u8 y = 0;
	static s8 x = -2;
	u16 s = (y * 16) & 0x0180;//0b110000000
	const u8 mask = shift_1_left[y % 8];
	u8 com = 1;
	u8 d = 0x80;
	if (x == -2) {
		d += y;//com
	} else if (x == -1) {
	//	d = 0x80 + 0;//com
	} else {
		com = 0;
		d = 0;
		if (x == 16) s += 512;
		u16 p = (x % 16) * 8 + s;
		u8 m = 0b10000000;
		for (u8 i = 0; i < 8; i++) {
			if (VIDEObuf[p + i] & mask) d += m;
			m >>= 1;
		}
	}
	low_WrComDat(d, com);
	
	if (++x >= 32) {
		x = -2;
		++y; y %= 32;
	}
}
Добавлено after 19 minutes 9 seconds:
а вот так, минус 12 байт бинарника

Код: Выделить всё

void Screen_Update(void)
{
	static u8 y = 0;
	static s8 x = -2;
	u16 s = (y * 16) & 0x0180;//0b110000000
	const u8 mask = shift_1_left[y % 8];
	u8 com = 1;
	u8 d = 0x80;
	if (x >= 0){
		com = 0;
		d = 0;
		if (x == 16) s += 512;
		u16 p = (x % 16) * 8 + s;
		u8 m = 0b10000000;
		for (u8 i = 0; i < 8; i++) {
			if (VIDEObuf[p + i] & mask) d += m;
			m >>= 1;
		}
	} else if (x == -2) {
		d += y;//com
	}
	low_WrComDat(d, com);
	
	if (++x >= 32) {
		x = -2;
		++y; y %= 32;
	}
}
Добавлено after 5 hours 18 minutes 56 seconds:
осталось позагонять в статики игрик икс зависимые переменные, но НАХУЯ?!!
ohmycode!
primuss3.com
Аватара пользователя
WiseLord
Друг Кота
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск
Контактная информация:

Re: Графический дисплей LCD 12864 (128x64 пикселя) на ST7920

Сообщение WiseLord »

Нет смысла. Для x и y нужно сохранять своё значение между вызовами функции, поэтому static. Остальные переменные всё равно через них рассчитываются, и делать ещё и их static смысла нет.
Аватара пользователя
slav0n
Опытный кот
Сообщения: 882
Зарегистрирован: Ср дек 01, 2010 00:38:15
Откуда: Харьков
Контактная информация:

Re: Графический дисплей LCD 12864 (128x64 пикселя) на ST7920

Сообщение slav0n »

ну, да
онлайн расчет указателя буфера все бессмысленнее и бессмысленнее и бессмысленнее...
ohmycode!
primuss3.com
Аватара пользователя
slav0n
Опытный кот
Сообщения: 882
Зарегистрирован: Ср дек 01, 2010 00:38:15
Откуда: Харьков
Контактная информация:

Re: Графический дисплей LCD 12864 (128x64 пикселя) на ST7920

Сообщение slav0n »

идея такая, размазываем вычислительные сопли по прерыванию

Код: Выделить всё

void Screen_Update(void)
{
    static u8 y = 0;
    static s8 x = -2;
    static u16 s = 0;
    static u8 mask = 1;
    u8 com = 1;
    u8 d = 0x80;
    if (x >= 0){
        com = 0;
        d = 0;
        if (x == 16) s += 512;
        u16 p = (x % 16) * 8 + s;
        u8 m = 0b10000000;
        for (u8 i = 0; i < 8; i++, m >>= 1) if (VIDEObuf[p++] & mask) d += m;
    } else if (x == -2) {
        d += y;//com
    }
    low_WrComDat(d, com);
    
    if (++x >= 32) {
        x = -2;
        ++y; y %= 32;
        s = (y * 16) & 0x0180;//0b110000000
        mask = 1 << (y % 8);
    }
} 
Добавлено after 1 hour 2 minutes 29 seconds:
бу
ohmycode!
primuss3.com
Аватара пользователя
WiseLord
Друг Кота
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск
Контактная информация:

Re: Графический дисплей LCD 12864 (128x64 пикселя) на ST7920

Сообщение WiseLord »

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

Но вообще оно у Вас, как я понимаю, в целом заработало? Именно при вызове из прерывания, а не основного цикла? Если да, то дало ли эффект видимый? Ведь ради этого всё затеивалось...
Аватара пользователя
slav0n
Опытный кот
Сообщения: 882
Зарегистрирован: Ср дек 01, 2010 00:38:15
Откуда: Харьков
Контактная информация:

Re: Графический дисплей LCD 12864 (128x64 пикселя) на ST7920

Сообщение slav0n »

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

Добавлено after 57 minutes 26 seconds:
ohmycode!
primuss3.com
NebelWefer
Грызет канифоль
Сообщения: 274
Зарегистрирован: Чт апр 16, 2009 14:23:59

Re: Графический дисплей LCD 12864 (128x64 пикселя) на ST7920

Сообщение NebelWefer »

Подскажите плз:
Начал разбираться с дисплеем сначала в текстовом режиме. Проблема в том, что все символы кроме иероглифов выводятся сразу по 2 в знакоместо 16х16. Можно ли как-то изменить сетку? Или иначе отрисовывать стандартные символы по одному?
Или это только в граф. режиме?

UDP: разобрался. лишний строб E приводил к задвоению всего и вся. :facepalm:
Аватара пользователя
DJ_URAN
Прорезались зубы
Сообщения: 220
Зарегистрирован: Вт авг 04, 2009 23:11:36
Откуда: Череповец

Re: Графический дисплей LCD 12864 (128x64 пикселя) на ST7920

Сообщение DJ_URAN »

Товарищи! Откопал дисплей 12832.
При попытке опознать, наткнулся на st7920. На моём выведена колодка 16 контактов с очень похожей распиновкой. Но есть отличие. Нет на плате подстроечника контрастности. Из мануала на контроллер нашел схему, где не используется удвоитель и все питается от VCC
Изображение
На моей плате все так же, кроме того, что все резисторы R1-R5 на 4.7 кОма (в мануале почему-то R3 указан 2к2), а также вместо R10 у меня установлен не потенциометр, а простой резистор и номинал его 51 Ом! Сигнал V0 с контроллера идёт и на этот резистор и на колодку на 3 контакт.
Пока не подключал дисплей к МК, но при подаче питания 5В все пиксели темные. Подсветка странная. Подавать 5В на нее побоялся, так как резистор там стоит 15 Ом всего. Пробовал на режиме диода замер сделать - ничего. Возможно, подсветка на нескольких последовательных диодах сделана.
Be sincere
aleksandr-zh
Сверлит текстолит когтями
Сообщения: 1278
Зарегистрирован: Пн июн 18, 2007 21:51:20

Re: Графический дисплей LCD 12864 (128x64 пикселя) на ST7920

Сообщение aleksandr-zh »

может кому пригодится: st7920 перевёрнутый, шрифты русский и английский. Компилятор Bascom 2.0.8.3
адресация по y - 0-7, по x парами!
прикрепляю файл шрифтов, так некоторые не нужные МНЕ символы заменены иными. Всё расписано внутри!
Символы только заглавные, для экономии памяти МК.

Добавлено after 2 minutes 58 seconds:
Прямой вывод, крупный шрифт 16*16 точек
Компилятор Баском 2.0.8.3
Вложения
14x14.zip
(5.75 КБ) 135 скачиваний
ST7920 перевёрнутый.zip
(4.47 КБ) 155 скачиваний
Ответить

Вернуться в «Периферия»