работа с буфером экрана (ксроллинг)
- Войдите на сайт для отправки комментариев
Втр, 08/11/2016 - 16:41
Приветствую!
Хочу сделать скролл экрана. организовал буффер:
char screen[LCD_H][LCD_W];
теперь нужно сдвинуть экран вверх, освободив нижнюю строку. Как это лучше сделать?
Правимльно ли будет такое решение?:
for (int y=0; y<screen_H-1;y++)
{
for (int x=0;x<screen_W;x++)
{
screen[y][x]=screen[y+1][x];
}
}
Ну, если x и y не перепутаны, то правильно. Вот только боюсь, скорость Вас не устроит.
ну, какбы, да.
скорость можно за счет ассемблера или каких-то магических пассов с копированием участков памяти решить, но тут я полный профан, а учиться - долго ;-)
скорость можно за счет ассемблера или каких-то магических пассов с копированием участков памяти решить
Нельзя.
НУ мне не нужно скроллить HD экран. У меня всего 14*6 знаков.
Визуально можно ускорить если иметь попиксельную копию экрана в локальной памяти , да еще изменять только те пиксели, что несоответствуют друг другу, таким образом мы избавляемся от излишнего чтения из буфера экрана и "ненужных" записей в буфер, а эти операции как раз долгие.
НУ мне не нужно скроллить HD экран. У меня всего 14*6 знаков.
Ну, не знаю, Вы попробуйте. Может Вас и устроит, чего нам тут сейчас воду в ступе-то толочь?
Если не устроит, надо думать о более хитрых алгоритмах. Например, визуально быстрее смотрится "через строчку", т.е. типа всё чётные, потом нечетные. И вообще, это общая идея - если скроллить "через N" строк, то визуально кажется быстрее.
Надо делать, пробовать и смотреть.
завтра попробую - на дивайсине проводок оторвался.
у большинства дисплеев есть команда автоскрола.
У PCD8544 - не нашел такой
ааа, я думал что какой-то тфт. сорри.
ой, погодите, так Вы собрались скроллить познаково или попиксельно? Если познаково, то проблем быть не должно.
Только знаете что, всё-таки Ваша программа формально правильна, но сильно неоптимально.
Сделайте так, расположите свой массив в памяти по строкам, т.е. чтобы в памяти шла сначала вся нулевая строка, потом вся первая строка, потом вся вторая и т.д.
Тогда цикл у Вас буде один (по строкам), а строки копируйте с помощью функции memcpy - так значительно быстрее.
я так понимаю вы шрифт (текст) выводите.
затирайте на текущем месте, выводите на новом изменив координату вывода. и по кругу.
расположите свой массив в памяти по строкам
Да, я уже дкмал об этом. Поэтому и массив с измерениями [y] [x], а не наоборот. Попробую.
я так понимаю вы шрифт (текст) выводите.
затирайте на текущем месте, выводите на новом изменив координату вывода. и по кругу.
А вот это интересно. не копировать строки, а хранить экранный номер строки и менять его в цикле. Нужно подумать.
А вот это интересно. не копировать строки, а хранить экранный номер строки и менять его в цикле. Нужно подумать.
Если Вы имеете в виду что-то типа "кольцевого буфера строк", то да, так еще быстрее. Но это чуть более геморойно в программировании.
ОК, вроде скролл получается. Я все-же копирую посимвольно, так как вывожу на экран в этом же цикле.
Осталось реализовать LF и CR, но что-то я запутался. Выпутываюсь пока. Получится - опубликую код для освистания.
Фигня какая-то! не могу понять, что происходит. Скроллинг есть, но вывод служебных символов с кодами 10 и 13 корежит экран - появляется дубляж строк и зацикливание. Может поможете увидеть, где чего порыть?
// Terminal control #include <PCD85448266.h> #define LCD_W 14 #define LCD_H 6 PCD8544 lcd; int lcdX = 0; int lcdY = 0; char screen[LCD_H][LCD_W]; void host_display_scroll() { lcd.setCursor(0, lcdY); for (int i = 0; i < LCD_W; i++) { lcd.write(' '); } lcd.setCursor(0, 0); for (int y = 0; y < LCD_H - 1; y++) { for (int x = 0; x < LCD_W; x++) { screen[y][x] = screen[y + 1][x]; lcd.write(screen[y + 1][x]); } } } void host_display_write(char c) { if (c != 13 && c != 10) { if (lcdX >= LCD_W) { lcdX = 0; lcdY++; } if (lcdY >= LCD_H) { lcdY = LCD_H - 1; host_display_scroll(); lcd.setCursor(0, lcdY); } lcd.write(c); screen[lcdY][lcdX] = c; lcdX++; } else if (c == 10) { // ТУТ была досадная ошибка = вместо == lcdY++; if (lcdY >= LCD_H) { lcdY = LCD_H - 1; host_display_scroll(); // delay(1000); } lcd.setCursor(lcdX, lcdY); }//LF else if (c == 13) { // ТУТ была досадная ошибка = вместо == lcdX = 0; for (int i = 0; i < LCD_W; i++) { lcd.write(' '); lcd.setCursor(lcdX, lcdY); } }//CR } void host_display_init() { lcd.begin(84, 48); lcd.clear(); lcd.setCursor(0, 0); lcd.setContrast(40); }Вот, на Жабе накидал приложеньице для проверки общего алгоритма - все скроллит. Наверное придется перебирать мою схему, может какие-то аппаратные проблемы? package sctest; import java.awt.HeadlessException; import javax.swing.JFrame; import javax.swing.JTable; public class ScTest extends JFrame{ int LCD_W=14; int LCD_H= 6; int lcdX = 0; int lcdY = 5; // start from the bottom line. Then - scrollUp char[][] screen = new char[LCD_H][LCD_W]; static JTable sc=new JTable(6, 14); public ScTest() throws HeadlessException { this.add(sc); } public static void main(String[] args) { ScTest app=new ScTest(); app.setVisible(true); app.setSize(400, 400); app.host_display_write('1'); app.host_display_write('2'); app.host_display_write('3'); app.host_display_write('4'); app.host_display_write('5'); app.host_display_write('6'); app.host_display_write('7'); app.host_display_write('8'); app.host_display_write('9'); app.host_display_write('a'); app.host_display_write('b'); app.host_display_write('c'); app.host_display_write('d'); app.host_display_write('e'); app.host_display_write('f'); app.host_display_write('g'); app.host_display_write('h'); app.host_display_write('1'); app.host_display_write('2'); app.host_display_write('3'); app.host_display_write('4'); app.host_display_write('5'); app.host_display_write('6'); app.host_display_write('7'); app.host_display_write('8'); app.host_display_write('9'); app.host_display_write('a'); app.host_display_write('b'); app.host_display_write('c'); app.host_display_write('d'); app.host_display_write('e'); app.host_display_write('f'); app.host_display_write('g'); app.host_display_write('h'); app.host_display_write((char) 10); app.host_display_write((char) 13); app.host_display_write('3'); app.host_display_write('4'); app.host_display_write('5'); app.host_display_write('6'); app.host_display_write('7'); app.host_display_write('8'); app.host_display_write('9'); app.host_display_write('a'); app.host_display_write('b'); app.host_display_write('c'); app.host_display_write('d'); app.host_display_write('e'); app.host_display_write('f'); app.host_display_write('g'); app.host_display_write('h'); } public void outchar(char c) { sc.setValueAt(c, lcdY, lcdX); } public void host_display_clear_rest() { int ii=lcdX; for (int i = ii; i < LCD_W; i++) // clear the rest of line { lcdX=i; outchar(' '); screen[lcdY][i] = ' '; } lcdX=ii; //lcd.setCursor(lcdX, lcdY); //return cursor to original position } public void host_display_scroll() { //lcd.setCursor(0, 0); int xx = lcdX; int yy = lcdY; for (int y = 0; y < LCD_H - 1; y++) //move screen one line up { for (int x = 0; x < LCD_W; x++) { screen[y][x] = screen[y + 1][x]; lcdY=y;lcdX=x; outchar(screen[y + 1][x]); } } lcdX=xx; lcdY=yy; //lcd.setCursor(lcdX, lcdY); //return cursor to original position host_display_clear_rest(); } public void host_display_write(char c) { if (c != 13 && c != 10) // regular character { if (lcdX >= LCD_W) // is x-position out of the screen? { lcdX = 0; host_display_scroll(); } outchar(c); screen[lcdY][lcdX] = c; lcdX++; } else if (c == 10) { host_display_scroll(); }//LineFeed - next line else if (c == 13) { lcdX = 0; host_display_clear_rest(); }//CR - first position of current line //lcd.setCursor(lcdX, lcdY); } }ВОт, я ее победил! Глупейшая ошибка в логике - делал очистку остатка строки при передаче CR, а не LF!
вроде пока работает!
// Terminal control #include <PCD85448266.h> #define LCD_W 14 #define LCD_H 6 PCD8544 lcd; int lcdX = 0; int lcdY = 5; // start from the bottom line. Then - scrollUp char screen[LCD_H][LCD_W]; void host_outchar(char c) { lcd.write(c); // Serial.println("LCD("+String(lcdX)+","+String(lcdY)+"):"+(char)c); } void host_display_clear_rest() { lcd.setCursor(lcdX, lcdY); // cursor to original position for (int i = lcdX; i < LCD_W; i++) // clear the rest of line { host_outchar(' '); screen[lcdY][i] = ' '; } lcd.setCursor(lcdX, lcdY); //return cursor to original position // Serial.println("clear rest("+String(lcdX)+","+String(lcdY)+")"); } void host_display_scroll() { lcd.setCursor(0, 0); for (int y = 0; y < LCD_H - 1; y++) //move screen one line up { for (int x = 0; x < LCD_W; x++) { screen[y][x] = screen[y + 1][x]; host_outchar(screen[y + 1][x]); } } lcd.setCursor(lcdX, lcdY); //return cursor to original position host_display_clear_rest(); // Serial.println("scroll ("+String(lcdX)+","+String(lcdY)+")"); } void host_display_write(char c) { if (c != 13 && c != 10) // regular character { if (lcdX >= LCD_W) // is x-position out of the screen? { lcdX = 0; host_display_scroll(); } host_outchar(c); screen[lcdY][lcdX] = c; lcdX++; } else if (c == 10) { host_display_scroll(); // Serial.println("LF ("+String(lcdX)+","+String(lcdY)+")"); host_display_clear_rest(); }//LineFeed - next line else if (c == 13) { lcdX = 0; // Serial.println("CR ("+String(lcdX)+","+String(lcdY)+")"); }//CR - first position of current line lcd.setCursor(lcdX, lcdY); } void host_display_init() { lcd.begin(84, 48); lcd.clear(); lcd.setCursor(0, 0); lcd.setContrast(40); }С Победой!
Вот для чего это было ;-)
https://github.com/doleynikov/MySketchbook/tree/master/ttbasic_ESP8266