работа с буфером экрана (ксроллинг)

doleynikov
Offline
Зарегистрирован: 30.01.2015

Приветствую!

Хочу сделать скролл экрана. организовал буффер:

     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];
    }
}

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ну, если x и y не перепутаны, то правильно. Вот только боюсь, скорость Вас не устроит.

doleynikov
Offline
Зарегистрирован: 30.01.2015

ну, какбы, да.

скорость можно за счет ассемблера или каких-то магических пассов с копированием участков памяти решить, но тут я полный профан, а учиться - долго ;-)

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

doleynikov пишет:

скорость можно за счет ассемблера или каких-то магических пассов с копированием участков памяти решить

Нельзя.

doleynikov
Offline
Зарегистрирован: 30.01.2015

НУ мне не нужно скроллить HD экран. У меня всего 14*6 знаков.

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

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

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

doleynikov пишет:

НУ мне не нужно скроллить HD экран. У меня всего 14*6 знаков.

Ну, не знаю, Вы попробуйте. Может Вас и устроит, чего нам тут сейчас воду в ступе-то толочь?

Если не устроит, надо думать о более хитрых алгоритмах. Например, визуально быстрее смотрится "через строчку", т.е. типа всё чётные, потом нечетные. И вообще, это общая идея - если скроллить "через N" строк, то визуально кажется быстрее. 

Надо делать, пробовать и смотреть.

doleynikov
Offline
Зарегистрирован: 30.01.2015

завтра попробую - на дивайсине проводок оторвался.

__Alexander
Offline
Зарегистрирован: 24.10.2012

у большинства дисплеев есть команда автоскрола.

doleynikov
Offline
Зарегистрирован: 30.01.2015

У PCD8544 - не нашел такой

__Alexander
Offline
Зарегистрирован: 24.10.2012

ааа, я думал что какой-то тфт. сорри.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

ой, погодите, так Вы собрались скроллить познаково или попиксельно? Если познаково, то проблем быть не должно.

Только знаете что, всё-таки Ваша программа формально правильна, но сильно неоптимально.

Сделайте так, расположите свой массив в памяти по строкам, т.е. чтобы в памяти шла сначала вся нулевая строка, потом вся первая строка, потом вся вторая и т.д.

Тогда цикл у Вас буде один (по строкам), а строки копируйте с помощью функции memcpy - так значительно быстрее.

MacSim
Offline
Зарегистрирован: 28.11.2012

я так понимаю вы шрифт (текст) выводите.

затирайте на текущем месте, выводите на новом изменив координату вывода. и по кругу.

doleynikov
Offline
Зарегистрирован: 30.01.2015

ЕвгенийП пишет:

расположите свой массив в памяти по строкам

Да, я уже дкмал об этом. Поэтому и массив с измерениями [y] [x], а не наоборот. Попробую.

doleynikov
Offline
Зарегистрирован: 30.01.2015

MacSim пишет:

я так понимаю вы шрифт (текст) выводите.

затирайте на текущем месте, выводите на новом изменив координату вывода. и по кругу.

А вот это интересно. не копировать строки, а хранить экранный номер строки и менять его в цикле. Нужно подумать.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

doleynikov пишет:

А вот это интересно. не копировать строки, а хранить экранный номер строки и менять его в цикле. Нужно подумать.

Если Вы имеете в виду что-то типа "кольцевого буфера строк", то да, так еще быстрее. Но это чуть более геморойно в программировании.

doleynikov
Offline
Зарегистрирован: 30.01.2015

ОК, вроде скролл получается. Я все-же копирую посимвольно, так как вывожу на экран в этом же цикле.

Осталось реализовать LF и CR, но что-то я запутался. Выпутываюсь пока. Получится - опубликую код для освистания.

doleynikov
Offline
Зарегистрирован: 30.01.2015

Фигня какая-то! не могу понять, что происходит. Скроллинг есть, но вывод служебных символов с кодами 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);
}

 

doleynikov
Offline
Зарегистрирован: 30.01.2015
Вот, на Жабе накидал приложеньице для проверки общего алгоритма - все скроллит.
Наверное придется перебирать мою схему, может какие-то аппаратные проблемы?

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);
}
   
}

 

doleynikov
Offline
Зарегистрирован: 30.01.2015

ВОт, я ее победил! Глупейшая ошибка в логике - делал очистку остатка строки при передаче 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);
}

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

С Победой!

doleynikov
Offline
Зарегистрирован: 30.01.2015