Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Алгоритм или программная реализация попиксельной бегущей строки
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Программирование
011119xx
Нужен алгоритм или программная реализация попиксельной бегущей строки для вывода на дисплей разрешением 240х320. Длина строки в пикселях может быть больше 240. Используется шрифт, в котором символы имеют разную ширину. Бегущая строка должна двигаться по кругу по типу: "ая строка - Это бегу". В конце строки нужно вставлять символы разделения, например, " - ". Спасибо.
RabidRabbit
Алгоритм для примера.

1.
Конструируем требуемую строку.
Считаем её длину в пикселах (L), выделяем в памяти буфер размером <масксимальная_высота_символов> * L.
Рисуем всю строку в буфере.
2.
Копируем 240 столбцов из буфера на экран начиная с первого столбца буфера.
Пауза.
...
Копируем 240 столбцов из буфера на экран начиная со столбца L-240+1 буфера.
Пауза.
Копируем 239 столбцов из буфера на экран начиная со столбца L-240 буфера, следом 1 столбец начиная со столбца 1 буфера.
Пауза.
...
Копируем 1 столбец из буфера на экран начиная со столбца L буфера, следом 239 столбцов начиная со столбца 1 буфера.
Пауза.
3.
Переходим к пункту 2.
011119xx
Получается, если длина строки в пикселях 340, а высота шрифта 24 пикселя, то нужен буфер 8160 байт?
RabidRabbit
Ну, если не нужны буквы с попиксельной раскраской, можно выделить на точку 1 бит и получить 3 * 340 = 1020 байт sm.gif
011119xx
Мне такой подход совсем не по душе.
Вот то, что получилось у меня:
Код
void scrolling(char *Buffer, uint16_t *ScrlPos)
{
       char tmp[50];
    uint16_t bufferlen, len;
    uint16_t pos = *ScrlPos;
    uint8_t index = 0, offset = 0;

    bufferlen = string_width(Buffer);

    tmp[0] = 0;

    if(bufferlen > pos)
    {
        do
        {
            tmp[offset] = Buffer[offset];
            offset++;
        }while((string_width(tmp) - 1) < pos);
        offset--;
        tmp[offset] = 0;
        pos = *ScrlPos - string_width(tmp);
        memset(tmp, 0, sizeof(tmp));
        while(string_width(tmp) < (SCREEN_WIDTH + pos))
        {
            if((index + offset) >= strlen(Buffer))
                break;
            tmp[index] = Buffer[index + offset];
            index++;
        }
        tmp[index] = 0;
    }
    else
    {
        pos -= bufferlen;
        memset(tmp, 0, sizeof(tmp));
    }
        
    len = string_width(tmp);

    if(len < (SCREEN_WIDTH + pos))
    {
        tmp[index++] = (char)'-';
        tmp[index++] = (char)'-';
        tmp[index++] = (char)'-';
        tmp[index] = 0;

        len = string_width(tmp, NULL_PIXEL);

        if(len < (SCREEN_WIDTH + pos))
            offset = 0;
            while(string_width(tmp) < (SCREEN_WIDTH + pos))
            {
                tmp[index] = Buffer[offset];
                index++;
                offset++;
            }
            tmp[index] = 0;
    }

    string_print(tmp, pos);    

    *(ScrlPos)++;

    if(*ScrlPos > (bufferlen + string_width(" - ")))
        *ScrlPos = 0;            
}


Вызывается так:
Код
uint16_t pos_in_string;

scrolling("Длинная бегущая строка", &pos_in_string);
Сергей
011119xx Приведите пожалуйста код функции string_width
011119xx
Я использую несколько модифицированную функцию string_width.
Код
//----------------------------------------------------------------------------------------------
// Описание: Расчет ширины строки  
// Принимает: указатель на строку, интервал между символами    
// Возвращает: ширина строки  
//----------------------------------------------------------------------------------------------
uint16_t string_width(char *text, uint8_t ch_interval)
{
    char c;                    
    uint16_t i = 0;                

    while(c = *(text++))                       //Выполнять для всей строки
      {
           i += char_width(c);        //Расчет ширины символа
           i += ch_interval;                                //Учет межсимвольного пространства
      }
    i -= ch_interval;                       //Устранение межсимвольного пространства после последнего символа

    return(i);                                 //Возврат ширины строки
}
//----------------------------------------------------------------------------------------------

Функция char_width зависит от типа используемого шрифта.
Jenya7
тогда возникает вопрос - а что у нас char_width() sm.gif
zombi
Если озу экрана читается то делал бы так.
Сдвиг содержимого экрана на один пиксель влево и добавление справа одного очередного столбца символа.
Создал бы таблицу ширин всех символов и помнил бы номер выводимого символа в строке и номер последнего выведенного его столбца.
И буферов не надо.
011119xx
Цитата(Jenya7 @ Mar 12 2015, 14:08) *
тогда возникает вопрос - а что у нас char_width() sm.gif

Код
uint8_t char_width(uint8_t c)
{
    uint8_t codepage_index, char_index = 0;
    uint8_t codepage_count = font_pcodepage->cph.cprnum;
    uint16_t index = 0;
    pgsymbol_t p = font_psymbols;

    for(codepage_index = 0; codepage_index < codepage_count; codepage_index++)        //Выполнять для всех кодовых страниц
    {
        if((c >= font_pcodepage->cpr[codepage_index].min) &&                
           (c <= font_pcodepage->cpr[codepage_index].max))        //Если символ в кодовой странице, то
        {
            while(c > (font_pcodepage->cpr[codepage_index].min + index))    //Выполнять до нахождения символа
                index++;                                                            //Увеличение индекса  

            break;
           }
        else                                                                        //Иначе
            char_index += font_pcodepage->cpr[codepage_index].max - font_pcodepage->cpr[codepage_index].min + 1;    
    }

    char_index += index;                                                            //Индекс символа в шрифте

    p += char_index * ((font_symsize + 4) / 4);                                    //Указатель на символ

    return ((pgcsymbol_t) p)->sh.cxpix;                    //Возврат ширины символа
}
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.