Перейти к содержанию
    

BF, вывод видео на LCD

к BF532 на EBIU (банк 0) подсоединён TFT LCD шина 16 бит

 

в SDRAM есть буфер 512x512 точек. Одна точка - байт (индекс палитры)

 

в той же SDRAM есть массив палитры из 256 цветов (индекс палитры из буфера - номер цвета)

 

часть буфера 512x512 надо отрисовать в дисплей прямоугольником 320x240

 

код:

 

#pragma align 64
u8 BUFFER[512*512]; //байт - индекс цвета

#pragma align 64
u16 PALETTE[256]; //слово - код цвета отправляемый в LCD в формате 5:6:5 (номер ячейки - код цвета(cодержимое BUFFER))

#define Pixel4                          \
        o=*(u32*)B;                     \
        TFT_Data=PALETTE[ o     &0xFF]; \
        TFT_Data=PALETTE[(o>> 8)&0xFF]; \
        TFT_Data=PALETTE[(o>>16)&0xFF]; \
        TFT_Data=PALETTE[(o>>24)     ]; \
        B+=4;
              
void update_video(void)
{
int width =320;
int height =240;
u8* B=(u8*)(BUFFER+0x20);
register u32 x,y,o,o0=width>>6,o1=(512-width);
for(y=0;y<height;y++)
{
  for(x=0;x<o0;x++)
  {
   Pixel4
   Pixel4
   Pixel4
   Pixel4
   Pixel4
   Pixel4
   Pixel4
   Pixel4
   Pixel4
   Pixel4
   Pixel4
   Pixel4
   Pixel4
   Pixel4
   Pixel4
   Pixel4
  }
  B+=o1;
}
}

 

В асм-листинге это даёт(для одного Pixel4):

 

// line 223
    R1 = [P1++];
    R0 = R1.b (Z);
    P5 = R0;
    R0 = R1 >> 8;
    R0 = R0.b (Z);
    P4 = R0;
    R0 = R1 >> 16;
    R0 = R0.b (Z);
    P3 = R0;
    R0 = R1 >> 24;
    P5 = P2 + (P5<<1);
    [SP + 60] = R0;
    R0.L = W[P5];
    W[P0] = R0.L;                           // Use of volatile in loops precludes optimizations. 
    P5 = P2 + (P4<<1);
    R0.L = W[P5];
    W[P0] = R0.L;                           // Use of volatile in loops precludes optimizations. 
    P5 = P2 + (P3<<1);
    R0.L = W[P5];
    W[P0] = R0.L;                           // Use of volatile in loops precludes optimizations. 
    P5 = [SP + 60];
    // -- 3 stalls --
    P5 = P2 + (P5<<1);
    R0.L = W[P5];
    W[P0] = R0.L;                           // Use of volatile in loops precludes optimizations.

 

DMA имхо тут не прокатит, так как на дисплей идет не содержимое буфера (i), а палитра PALETTE

 

вопрос, можно ли быстрее сделать отрисовку на экран?

Изменено пользователем denebopetukius

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Как минимум перенести u16 PALETTE[256] в SRAM. Опять же читать и писать в SDRAM лучше не по байтовому указателю 2 раза по байту, а один раз по слову.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Как минимум перенести u16 PALETTE[256] в SRAM. Опять же читать и писать в SDRAM лучше не по байтовому указателю 2 раза по байту, а один раз по слову.

 

у меня кэш данных включен на 32 кб ( A+B )

а скрэтчпад для стека

 

в итоге внутреней срамы нет уже.

может что-нибуть выкинуть надо? например стек в SDRAM перенести? а в скрэтчпад PALETTE толкнуть...

 

в том куске кода который я дал - идет чтение по 4 байта - далее индексы идут на палитру

 

подскажите что не так?

возможно я вас не понял.

 

если можно то псевдокодом...

 

может в кешируемых страницах надо поменять?

у меня биты PLB_DIRTY и CPLB_LOCK установлены во всех страницах памяти

write-back включен для секции переменных и кода

а образ игры работает на чтение с write-throug кэшем

 

дисплей не кеширован

 

кстати, можно как-нибудь буферизовать дисплей? (как это в АРМ9 делалось)

Изменено пользователем denebopetukius

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Очень жаль, что TFT не подключен к PPI. Было бы просче.

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

 

А можно поставить BF533 в таком же корпусе. Всё отличие это дополнительно два DATASRAM по 16k без возможности задания как кэш. Тогда все буфера влезут во внутреннюю память SRAM.

Цена чуть больше. У нас примерно на 3$

Изменено пользователем boom

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

может что-нибуть выкинуть надо? например стек в SDRAM перенести? а в скрэтчпад PALETTE толкнуть...

Урежьте стек до 3.5К, и разместите PALETTE в скрэтчпаде

или

разместите PALETTE и BUFFER в разных банках SDRAM и сделайте банк с PALETTE некешируемым

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Основные потери производительности происходят именно из-за приведения буфера к палитре, так вот ставить его в другой банк SDRAM наверно не совсем поможет. Лучше действительно использовать 1 вариант с уменьщением стека или отключить один банк кэш и сделать его SRAM и разместить там палитру и какие нибудь ещё данные.

Также попробовать с тем что есть. Оптимизитровать количество обращений к памяти например, защёт увеличения разрадности обращения.

Наверно лучше так

#define Pixel4                          \
        o=*(u32*)B;                     \
        (u32*)TFT_Data=((PALETTE[ o     &0xFF]) | (PALETTE[(o>> 8)&0xFF] << 16)); \
        (u32*)TFT_Data=((PALETTE[ (o>>16)&0xFF]) | (PALETTE[(o>> 24)&0xFF] << 16)); \
        B+=4;

что сократит количество обращений при записи в TFT_Data в два раза.

а также сделать

u32 PALETTE[65536];
        o=*(u32*)B;                     \
        (u32*)TFT_Data=(PALETTE[ o     &0xFFFF]); \
        (u32*)TFT_Data=(PALETTE[ (o>>16)&0xFFFF]); \
        B+=4;

что ещё уменьшит количество обращений к памяти PALETTE, но увеличит размер таблицы.

Код сделан исходя из того, что (моё предположение) шина TFT 16 бит и TFT_Data это адрес асинхронной памяти к которому привязан дисплей.

Зависит от того как подключен TFT, если ему существенны изменения адреса, то такой вариант не прокатит, т.к. A1 = 0 при записи младшей части 32 битного слова, а А1 = 1 при записи старшей части. Если же Адрес А1 не существенен, то такой код должен работать, проверял ).

Изменено пользователем boom

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Исходя из описания на DT, которое я скачал с сайта автора, приведённый мной код должен работать, т.к. порт комманд и данных TFT лежит далеко друг от друга и адрес А1 не внесёт никакого влияния.

Изменено пользователем boom

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Основные потери производительности происходят именно из-за приведения буфера к палитре, так вот ставить его в другой банк SDRAM наверно не совсем поможет. Лучше действительно использовать 1 вариант с уменьщением стека или отключить один банк кэш и сделать его SRAM и разместить там палитру и какие нибудь ещё данные.

Первый вариант безусловно лучше. Но и второй должен дать прирост производительности - как минимум, за счет экономии на постоянном activate/precharge (и связанной с этим латентностью). Палитра ведь как раз помещается в одну строку SDRAM.

 

denebopetukius, для второго варианта также необходимо выравнять палитру по 512-байтовой границе.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Очень жаль, что TFT не подключен к PPI. Было бы просче.

 

спорный вопрос.

 

поставив дисплей на PPI, мы лишимся FIO (практически всех, ибо шина 16 бит)

а они нужны на Joystick и чипселекты SPI-устройств

 

мультиплексоры городить не хотелось бы.

 

да и не факт что быстрее было бы. Тем более отвлекаться через каждые 50/60 Гц

 

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

 

 

Наверно лучше так

#define Pixel4                          \
        o=*(u32*)B;                     \
        (u32*)TFT_Data=((PALETTE[ o     &0xFF]) | (PALETTE[(o>> 8)&0xFF] << 16)); \
        (u32*)TFT_Data=((PALETTE[ (o>>16)&0xFF]) | (PALETTE[(o>> 24)&0xFF] << 16)); \
        B+=4;

что сократит количество обращений при записи в TFT_Data в два раза.

 

Вариант дал прирост +11% на работу всей программы

Теперь звук "в особо тяжких играх" идет без хрипа

Но медленный темп сохранился (опять же - в некоторых играх)

 

а также сделать

u32 PALETTE[65536];
        o=*(u32*)B;                     \
        (u32*)TFT_Data=(PALETTE[ o     &0xFFFF]); \
        (u32*)TFT_Data=(PALETTE[ (o>>16)&0xFFFF]); \
        B+=4;

что ещё уменьшит количество обращений к памяти PALETTE, но увеличит размер таблицы.

 

Вариант оказался самым медленным!!!

Полагаю из-за того что PALETTE раздулась, выбор индекса зависит от картинки и близок к случайному.

Сильно засоряет кеш данных

 

Код сделан исходя из того, что (моё предположение) шина TFT 16 бит и TFT_Data это адрес асинхронной памяти к которому привязан дисплей.

Зависит от того как подключен TFT, если ему существенны изменения адреса, то такой вариант не прокатит, т.к. A1 = 0 при записи младшей части 32 битного слова, а А1 = 1 при записи старшей части. Если же Адрес А1 не существенен, то такой код должен работать, проверял ).

 

Ваши предположения абсолютно верные.

Адресный бит LCD завешан на A16

 

 

Но и второй должен дать прирост производительности - как минимум, за счет экономии на постоянном activate/precharge (и связанной с этим латентностью). Палитра ведь как раз помещается в одну строку SDRAM.

denebopetukius, для второго варианта также необходимо выравнять палитру по 512-байтовой границе.

 

Чуть не забыл сказать, для второго варианта палитру располагал в отдельном банке сдрам

пробовал WT и WB - нет разницы

 

кстати, во время работы, палитра может меняться! (запись)

 

палитра была выровнена на начало банка сдрам.

 

почему оказалось хуже?

 

что делать с битами CPLB: dirty и lock ?

 

---

пока оставил первый вариант, палитру толкнул в скрэтчпад, стек урезал

 

на всякий случай добавлю - что у приложения стартапа нет, в ldf-файле делается RESOLVE(main,0x4) вместо RESOLVE(start,0x4); KEEP(main)

 

 

u32 PALETTE[65536];

 

ещё непонятка: как и чем заполнять такую палитру?

 

в u16 PALETTE[256] всё просто PALETTE[i]=f( R,G,B ), а тут как? циклы гонять, каждый раз когда идет запись в палитру (она может меняться во время игры)

Изменено пользователем denebopetukius

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

в u16 PALETTE[256] всё просто PALETTE=f( R,G,B ), а тут как? циклы гонять, каждый раз когда идет запись в палитру (она может меняться во время игры)

 

u32 PALETTE[65536] формируется сразу на 2 пикселя. В старших 16 бит лежит один пиксель, в младших второй.

PALETTE=(f( R,G,B ) << 16) | (f( R,G,B )); поэтому и 65536 значений.

В итоге (u32*)TFT_Data=(PALETTE[ o &0xFFFF]); забирается из палитры 2 пикселя и передаётся в LCD. И если эту палитру ставить в SDRAM, то как говорил vik0 отключить кэш в данной области.

 

Можно попробовать подготовить несколько вариантов палитры и тупо менять, когда надо, указатель оной. Благо памяти много. Но это самый простой вариант и жрущий много памяти.

Изменено пользователем boom

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

к BF532 на EBIU (банк 0) подсоединён TFT LCD шина 16 бит

в SDRAM есть буфер 512x512 точек. Одна точка - байт (индекс палитры)

в той же SDRAM есть массив палитры из 256 цветов (индекс палитры из буфера - номер цвета)

часть буфера 512x512 надо отрисовать в дисплей прямоугольником 320x240

DMA имхо тут не прокатит, так как на дисплей идет не содержимое буфера (i), а палитра PALETTE

вопрос, можно ли быстрее сделать отрисовку на экран?

как тут уже подсказали перенести палитру в SRAM, и может быть завести буфер 320х240, в него сначала писать правильные цвета, а затем уже с помощью MDMA копировать в дисплей.

 

Ну а, наверное, совсем быстрый способ, это завести в SRAMe пару буферов размером на строку (512) и пару размером 320 слов, в первый из низ читать из SDRAMA через MDMA, в это время пересчитывать данные цветов из второго буфера который был заполнен ранее, и складывать в третий буфер (320 слов), который затем также через MDMA отправлять в дисплей, и пока он будет отправляться, работать с четвёртым. Во как.

 

Радость от этого всего в том, что все операции будут проводиться в быстром SRAMe, без медленных вылазок на внешнюю шину, а одновременно с этим, будет трудиться и MDMA, занимаясь перекладыванием данных, не отвлекая процессор.

 

спорный вопрос.

поставив дисплей на PPI, мы лишимся FIO (практически всех, ибо шина 16 бит)

а они нужны на Joystick и чипселекты SPI-устройств

мультиплексоры городить не хотелось бы.

да и не факт что быстрее было бы. Тем более отвлекаться через каждые 50/60 Гц

 

Было бы быстрее, так как сейчас и дисплей и SDRAM делят одну шину, и соответственно она занята сначала при чтении из SDRAM а потом при записи в дисплей. в случае с PPI это было бы только последовательное чтение SDRAMA.

и отвлекаться надо было бы на всего несоклько тактов, перезаписать пару регистров ДМА.

а недостаток ног можно было скомпенсировать добавив на spi какой-нибудь мелкий AVR.

 

Хотя вопрос действительно спорный.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

начал копать с другой стороны.

расковырял функцию рендеринга эмулятора - в тот самый буфер 512x512

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

 

сделал так что отрендерённая строка посылается сразу на дисплей (рендерятся все слои - спрайты/фон итп...)

буфер естественно уже 512x1 - расположил в скрэтчпаде!

 

скорость поднялась, но незначительно.

 

пробовал выводить без палитры напрямую - тоже не изменилось.

 

пробовал не выводить на дисплей ничего - слегка ускорилось но ненамного.

 

вывод - сам эмулятор CPU/coCPU/VDP/Sound уже хавает много ресурсов - более чем отрисовка экрана.

 

в настоящее время буфер 512x1 и палитра - в скрэтчпаде и не кешированы

Изменено пользователем denebopetukius

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...