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

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

ну вот есть у вас 5 инструкций на пиксель, можно ещё сократить, наверное.

P0=W[P1++]

P0=P3+(P0<<1)

да и в собирании двух пикселей в одно 32х разрядное слово смысла особого нет. EBUI всё равно 16 бит.

если бы был дополнительный буфер во внутренней памяти, куда дма данные само подтаскивает, наверное, можно было бы ещё какой-нибудь один такт сэкономить, запараллелив запись одного пикселя с чтением следующего и/или P0=P3+(P0<<1), P2=P3+(P2<<1)

но всё равно чтение из sdrama в лучшем случае 1SCLK = 3-4CCLK, (если не лень встаньте, осциллографом на шину памяти и посмотрите сколько тактов реально такие одиночные чтения из sdram занимают)

а запись в дисплей по асинхронной шине 2-3SCLK = 6-12CCLK.

что толку оптимизировать эти 4 инструкции, если обращение чтение из памяти и запись в дисплей длится в несколько раз дольше 9-16 тактов.

как уже не раз говорил, заставьте дма перекладывать данные, тогда обработка палитры процессором будет идти параллельно с перекладыванием данных.

 

ps. у вас 16ти разрядный цвет в палитре и 16ти разрядный индекс цвета, в чем смысл?

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


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

что толку оптимизировать эти 4 инструкции, если обращение чтение из памяти и запись в дисплей длится в несколько раз дольше 9-16 тактов.

как уже не раз говорил, заставьте дма перекладывать данные, тогда обработка палитры процессором будет идти параллельно с перекладыванием данных.

 

Процессор разогнан до 550 МГц. Шина CCLK/3=183 МГц. SDRAM работает на 183 МГц с CAS latency =2. Кеш включен (для кода и данных).

Дисплей 7 тактов (setup + write + hold), в эквиваленте 183/7 = 26 МГц. Шина данных 16 бит.

 

да и в собирании двух пикселей в одно 32х разрядное слово смысла особого нет. EBUI всё равно 16 бит.

Обращение к 32 битам идет подряд как 2 раза по 16 бит, адрес+1.

Но та как адресов у контроллера дисплея нет (точнее есть и висит он на самом старшем адресном бите), инкремент адреса не мешает.

Это небольшой burst из двух коротких слов :)

 

Сделал 14 строк ассемблера на 4 пикселя.

Раньше было 11 строк на 2 пикселя.

Ппришлось попарить мозг, пока вышло так (задействовал конвеер Блекфина).

Пока не проверял в работе, но компилируется.

Эффективность кода возросла на 36%

 

 

#define PIXEL \
{ \
__asm__ volatile ("                 R0=W[P0++] (Z);"); \
__asm__ volatile ("R0=R0<<1      || R1=W[P0++] (Z);"); \
__asm__ volatile ("R1=R1<<1      || R2=W[P0++] (Z);"); \
__asm__ volatile ("R2=R2<<1      || R3=W[P0++] (Z);"); \
__asm__ volatile ("P3=R3                        ;"); \
__asm__ volatile ("P3=P5+(P3<<1)                ;"); \
__asm__ volatile ("R0=R0+R5 (NS) || R1.H=W[P3]  ;"); \
__asm__ volatile ("I0=R0                        ;"); \
__asm__ volatile ("R1=R1+R5 (NS) || R0.L=W[I0]  ;"); \
__asm__ volatile ("I1=R1                        ;"); \
__asm__ volatile ("R2=R2+R5 (NS) || R0.H=W[I1]  ;"); \
__asm__ volatile ("I2=R2                        ;"); \
__asm__ volatile ("R3=R3+R5 (NS) || R1.L=W[I2] || [P1]=R0 ;"); \
__asm__ volatile ("  [P1]=R1    ;"); \
\
} \

 

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

 

К сожалению объем графических данных не позволяет сделать буфер на строку во внутренней памяти + DMA. Потому что программу писал не я.

 

ps. у вас 16ти разрядный цвет в палитре и 16ти разрядный индекс цвета, в чем смысл?

 

Это эмуляция аркадных автоматов Capcom Play System 1/2, там палитра больше 256 цветов :)

 

Вот это детище портировал на BF533:

https://osdn.net/projects/mamespi/releases/2046 / https://www.zophar.net/mame/caname.html

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

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


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

буфер не обязательно на всю строку делать, 8-16-32 пикселя возможно уже вполне хватит чтобы успеть и данные пережевать и дма перенастроить.

главное чтобы не процессор занимался перекладыванием данных из регистра/внутренней памяти наружу.

 

Это эмуляция аркадных автоматов Capcom Play System 1/2, там палитра больше 256 цветов :)

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

 

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


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

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

 

Там очень хитрый буфер. И он "грязный", потому что по-очереди отрисовываются несколько спрайтовых плоскостей (видеосистема Capcom PlaySystem 1/2). Если преобразовывать палитру там, то боюсь всё замедлится в число раз, равное числу плоскостей.

 

буфер не обязательно на всю строку делать, 8-16-32 пикселя возможно уже вполне хватит чтобы успеть и данные пережевать и дма перенастроить.

главное чтобы не процессор занимался перекладыванием данных из регистра/внутренней памяти наружу.

 

Процессор к сожалению будет конвертить палитру, а DMA так же занимать шину во время транзакций.

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

 

Проверил работу процедуры. На практике вышло чуть-лучше. Но ненамного.

 

Вот код всей процедуры - пока не вычесал, затронут только внутренний цикл.

 

.section/DOUBLE32 program;

.extern _current_display;
.extern _palette_16bit_lookup

.global _dib_draw_window_asm;

_dib_draw_window_asm:
    [--SP] = (P5:3);
    P1.L = _current_display+4;
    P1.H = _current_display+4;
    P1 = [P1];
    P2 = 17600;
    P0 = 224;
    I0 = 0;
    I0.H = 8193;
    P1 = [P1 + 16];
    P5.L = _palette_16bit_lookup;
    P5.H = _palette_16bit_lookup;
    P4 = 4;
    P1 = P1 + P2;
    [SP + 12] = P1;
    LOOP CycleYL LC1 = P0;
CycleY:
    LOOP_BEGIN CycleYL;
    P1 = [SP + 12];
    P0 = 80;

    P3 = [P5];
        R5=P3;

    LOOP CycleXL LC0 = P0;
CycleX:
    LOOP_BEGIN CycleXL;
                     R0=W[P1 + 2] (Z)     ;
    R0=R0<<1      || R1=W[P1 ++ P4] (Z)   ;
    R1=R1<<1      || R2=W[P1 + 2] (Z)     ;
    R2=R2<<1      || R3=W[P1 ++ P4] (Z)   ;
    P0=R3                                 ;
    P0=P3+(P0<<1)                         ; //Preg read after write which requires 4 extra cycles
    R0=R0+R5 (NS) || R7.L=W[P0]           ;
    I1=R0                                 ;
    R1=R1+R5 (NS) || R6.H=W[I1]           ; //Dagreg read after write which requires 4 extra cycles
    I1=R1                                 ;
    R2=R2+R5 (NS) || R6.L=W[I1]           ; //Dagreg read after write which requires 4 extra cycles
    I1=R2                                 ;
    R3=R3+R5 (NS) || R7.H=W[I1] || [I0]=R6; //Dagreg read after write which requires 4 extra cycles
    [I0]=R7                               ;
    LOOP_END CycleXL;
.P35L13:
    P0 = [SP + 12];
    P1 = 1088;
    P1 = P0 + P1;                            //Preg read after write which requires 3 extra cycles
    [SP + 12] = P1;
    LOOP_END CycleYL;
.P35L14:
    (P5:3) = [SP++];
    RTS;

 

А вот это разочаровало:

//Preg read after write which requires 3 extra cycles

//Dagreg read after write which requires 4 extra cycles

 

Выходит вся оптимизация и конвеер лесом?? :wacko:

 

Пока получилось 35 - 40 FPS, в идеале должно быть 60 FPS (частота смены кадров NTSC)

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


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

Там очень хитрый буфер. И он "грязный", потому что по-очереди отрисовываются несколько спрайтовых плоскостей (видеосистема Capcom PlaySystem 1/2). Если преобразовывать палитру там, то боюсь всё замедлится в число раз, равное числу плоскостей.

когда данные не во внешней памяти, а уже в регистре то это преобразование занимает два такта.

ну и если взять в среднем, пиксель всё таки читается каждый кадр, а вот пишется думаю далеко не каждый.

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

 

Процессор к сожалению будет конвертить палитру, а DMA так же занимать шину во время транзакций.

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

Пока получилось 35 - 40 FPS, в идеале должно быть 60 FPS (частота смены кадров NTSC)

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

что такое цикл эмуляции?

вот есть у вас 15мс между кадрами при 60Гц, за это время надо успеть наэмулировать 15мс тактов приставки и отрисовать экран. какая разница в каком порядке.

320*240 / 26МГц = 3мс, это время в течении которого шина всё равно будет просто занята отрисовкой на экран, чтение из памяти гораздо быстрее можно не учитывать, так почему бы в эти 3мс процессору не заняться конвертированием цветов, ПАРАЛЛЕЛЬНО с выдачей, а не последовательно как сейчас. потому что ничего другого он всё равно без внешней шины делать не сможет.

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


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

когда данные не во внешней памяти, а уже в регистре то это преобразование занимает два такта.

ну и если взять в среднем, пиксель всё таки читается каждый кадр, а вот пишется думаю далеко не каждый.

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

 

 

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

что такое цикл эмуляции?

вот есть у вас 15мс между кадрами при 60Гц, за это время надо успеть наэмулировать 15мс тактов приставки и отрисовать экран. какая разница в каком порядке.

320*240 / 26МГц = 3мс, это время в течении которого шина всё равно будет просто занята отрисовкой на экран, чтение из памяти гораздо быстрее можно не учитывать, так почему бы в эти 3мс процессору не заняться конвертированием цветов, ПАРАЛЛЕЛЬНО с выдачей, а не последовательно как сейчас. потому что ничего другого он всё равно без внешней шины делать не сможет.

 

Весь цикл программы можно упрощенно представить так:

 

while(!Quit)
{
эмулируем...
рисуем...
}

 

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

В момент работы ДМА, процессор всеравно будет брать индексы из SDRAM, а это снова шина.

В итоге процессор и ДМА будут рвать шину по кускам.

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


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

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

В момент работы ДМА, процессор всеравно будет брать индексы из SDRAM, а это снова шина.

В итоге процессор и ДМА будут рвать шину по кускам.

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

и не обязательно буфер на всю строку.

0) завели два буфера по 64 байта.

 

1)настроили ДМА, чтобы забрать 32 точки из сдрама(ну или забрали руками, тут без разницы) в буфер №1

2)курим бамбук, так как без шины заняться нечем.

3)по получении данных отправили предыдущий буфер№2 из 32 точек на отрисовку через дма

4)пока дма перекладывает данные в дисплей, обрабатываем только что полученные данные в буфере№1.

5)как только старые данные ушли (обработка вроде бы должна закончиться гораздо быстрее, дисплею надо 21ССLK на пиксель, а процессор за 3-5 управиться должен из внутренней памяти), поменяли местами указатели на буферы

GOTO 1

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


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

0) завели два буфера по 64 байта.

1)настроили ДМА, чтобы забрать 32 точки из сдрама(ну или забрали руками, тут без разницы) в буфер №1

2)курим бамбук, так как без шины заняться нечем.

3)по получении данных отправили предыдущий буфер№2 из 32 точек на отрисовку через дма

4)пока дма перекладывает данные в дисплей, обрабатываем только что полученные данные в буфере№1.

5)как только старые данные ушли (обработка вроде бы должна закончиться гораздо быстрее у дисплею надо 21ССLK на пиксель, а процессор за 3-5 управиться должен из внутренней памяти), поменяли местами указатели на буферы

GOTO 1

 

Всё сделал как написали, работает исправно, но прироста скорости всёравно нет. Пробовал убрать dma_wait, скорость повышается, но экран отрисовывается на 1/4 и весь трясётся (что и понятно почему).

 

Попробую не ждать, а в обработчик прерывания засунуть вывод на дисплей через DMA.

 

Рабочий код ниже:

 

#ifndef __DMA_H__
#define __DMA_H__

//0xFF800000..0xFF803FFF //L1_DATA_A

#define NB 32

#define buf0 (0xFF803FC0-(NB<<1))
#define buf1 (0xFF803FE0- NB    )

#define DMA_INIT                         \
{                                        \
*pMDMA_S1_PERIPHERAL_MAP=0x0040;        \
*pMDMA_S1_X_COUNT=(NB>>1);              \
*pMDMA_S1_X_MODIFY=2;                   \
*pMDMA_S1_Y_COUNT=1;                    \
*pMDMA_S1_Y_MODIFY=0;                   \
*pMDMA_D1_PERIPHERAL_MAP=0x0040;        \
*pMDMA_D1_START_ADDR=(void*)&OLED_Data; \
*pMDMA_D1_X_COUNT=(NB>>1);              \
*pMDMA_D1_X_MODIFY=0;                   \
*pMDMA_D1_Y_COUNT=1;                    \
*pMDMA_D1_Y_MODIFY=0;                   \
}                                        \

#define DMA_SEND(buf)                  \
{                                      \
*pMDMA_S1_START_ADDR=(void*)buf;      \
*pMDMA_S1_CONFIG=WDSIZE_16|DMAEN;     \
*pMDMA_D1_CONFIG=WDSIZE_16|WNR|DMAEN; \
}                                      \

#define DMA_WAIT while(*pMDMA_D1_IRQ_STATUS&DMA_RUN);

#define MEMORY_COPY(dst,src)       \
{                                  \
register u16 i;                   \
register u32* d=(u32*)dst;        \
register u32* s=(u32*)src;        \
for(i=0;i<(NB>>2);i++) *d++=*s++; \
}                                  \

#define PALETTE_CONVERT(buf)                          \
{                                                     \
register u16 i;                                      \
register u16* c=(u16*)buf;                           \
for(i=0;i<(NB>>1);i++)*c++=palette_16bit_lookup[*c]; \
}                                                     \
#endif

 

void dib_draw_window_DMA(void)
{
register u16* src=(u16*)(((u32)current_display.game_bitmap->base)+17536+64);
register u16 y=DST_HEIGHT;

while(y--)
{
  register u16 x=(u16)SCR_WIDTH/(u16)NB;

  MEMORY_COPY(buf1,src)
  PALETTE_CONVERT(buf1)
  src+=(NB>>1);

  while(x--)
  {
   MEMORY_COPY(buf0,src)
   DMA_SEND(buf1)
   PALETTE_CONVERT(buf0)
   src+=(NB>>1);
   DMA_WAIT

   MEMORY_COPY(buf1,src)
   DMA_SEND(buf0)
   PALETTE_CONVERT(buf1)
   src+=(NB>>1);
   DMA_WAIT
  }

  src+=(SRC_PITCH-SCR_WIDTH-(NB>>1));
}
}

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


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

Всё сделал как написали, работает исправно, но прироста скорости всёравно нет. Пробовал убрать dma_wait, скорость повышается, но экран отрисовывается на 1/4 и весь трясётся (что и понятно почему).

Core Timer в руки и смотрите сколько тактов что исполняется. тормозит где-то ещё.

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

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

 

зы уже говорили про макросы.

inline void DMA_INIT(){

*pMDMA_S1_PERIPHERAL_MAP=0x0040;

...

}

ну вот абсолютно ничем не отличается, но выглядит не так безобразно.

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


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

Всё сделал как написали, работает исправно, но прироста скорости всёравно нет.

И не будет. Я писал выше почему.

 

зы уже говорили про макросы.

Да. Похоже - не в коня корм... :smile3046:

 

//Preg read after write which requires 3 extra cycles

//Dagreg read after write which requires 4 extra cycles

Выходит вся оптимизация и конвеер лесом?? :wacko:

Чтобы что-то оптимизировать, нужно сначала досконально изучить процессор. А у Вас знания - поверхностные.

Я тут уже несколько раз писал по stall-ы в c55x и почему они возникают. И вот именно в этих же точках c55xx вставил бы stall-ы, и похоже, что конвеер Blackfin работает аналогично.

На ядре C55xx нельзя вычислить значение на основном АЛУ (D-unit АЛУ) и тут же использовать его для вычисления адреса, так как действия эти выполняются на разных фазах конвеера (причём: вычисление адреса - на более ранней фазе). Если так сделать, то ядро вставит необходимое число stall-ов (остановок конвеера) для синхронизции фаз, что у Вас похоже и наблюдается.

Кроме этой, есть есть куча причин для вставки stall-ов. Пока не изучите полностью - не напишите ничего путнего. DSP-ядра - это не ARM, они в разы сложнее ARM-а.

Да и операций у Вас куча лишних - какие-то пересылки - зачем они? Надо изучать систему команд и искать решения с меньшим их кол-вом.

Вобщем оптимизации там - кот наплакал. Никакой скорости выполнения от такого кода ждать не приходится.

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


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

И не будет. Я писал выше почему.

Вобщем оптимизации там - кот наплакал. Никакой скорости выполнения от такого кода ждать не приходится.

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

на перекладывание точки в дисплей уходит 21 такт, который сейчас выполняется параллельно с вычислением палитры, а процессор потом почти всё время сидит сидит и ждёт while(*pMDMA_D1_IRQ_STATUS&DMA_RUN);

ну а то что fpsов мало получается - надо смотреть чем там ещё процессор занят.

переслать 320*240 при 26МГц это 3мс всего.

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


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

Сделал DMA по прерываниям. Буфер - 320 пикселов (одна строка) 640 байт в L1, уже сконверченная палитрой(тоже в L1). Даём DMA команду на отрисовку строки, а сами делаем дальше остальные вещи. Прерывание по окончанию пересылки строки снова запускает DMA для новой строки. И так пока экран не отрисуется весь.

 

Код что ниже - рабочий, удаось поднять общую скорость (отрисовка экрана + вся программа) на 15 FPS !!! :rolleyes:

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

 

Макросы использую, потому что 100% гарантия что с-инлайнится.

 

#define SRC_PITCH  544
#define DST_HEIGHT 224

#define SCR_WIDTH  320
#define SCR_HEIGHT 240

//0xFF800000..0xFF803FFF //L1_DATA_A

#define NB (SCR_WIDTH<<1)

#define L1_MEMORY 0xFF804000

#define L1_BUF (L1_MEMORY-NB)

#define DMA_INIT                         \
{                                        \
*pMDMA_S1_PERIPHERAL_MAP=0x0040;        \
*pMDMA_S1_START_ADDR=(void*)L1_BUF;     \
*pMDMA_S1_X_COUNT=(NB>>1);              \
*pMDMA_S1_X_MODIFY=2;                   \
*pMDMA_S1_Y_COUNT=1;                    \
*pMDMA_S1_Y_MODIFY=0;                   \
*pMDMA_D1_PERIPHERAL_MAP=0x0040;        \
*pMDMA_D1_START_ADDR=(void*)&OLED_Data; \
*pMDMA_D1_X_COUNT=(NB>>1);              \
*pMDMA_D1_X_MODIFY=0;                   \
*pMDMA_D1_Y_COUNT=1;                    \
*pMDMA_D1_Y_MODIFY=0;                   \
}                                        \

#define DMA_START                            \
{                                            \
*pMDMA_S1_CONFIG=WDSIZE_16|DMAEN;           \
*pMDMA_D1_CONFIG=WDSIZE_16|WNR|DMAEN|DI_EN; \
}                                            \

#define DMA_STOP                       \
{                                      \
*pMDMA_S1_CONFIG=0;                   \
*pMDMA_D1_CONFIG=0;                   \
}                                      \


extern struct mame_display current_display;

u16* src;

EX_INTERRUPT_HANDLER(DMA_ISR)
{
static u16 y=DST_HEIGHT;
*pMDMA_D1_IRQ_STATUS=1;
y--;
if(y)
{
  register u16* buf=(u16*)L1_BUF;
  register u16 i;
  for(i=0;i<(NB>>1);i++)*buf++=palette_16bit_lookup[*src++]; 
  src+=(SRC_PITCH-SCR_WIDTH);
  DMA_START
}
else
{
  y=DST_HEIGHT;
  DMA_STOP
}
}

void DMA_Init_Interrupt(void)
{
*pSIC_IMASK&=0xFFBFFFFF;                       //Disable MDMA1 interrupt
*pSIC_IAR2=(*pSIC_IAR2&0xF0FFFFFF)|0x06000000;
register_handler(ik_ivg13,DMA_ISR);
*pSIC_IMASK|=0x00400000;                       //Enable MDMA1 interrupt
}

int win_init_window(void)
{
        // disable win_old_scanlines if a win_blit_effect is active
        if (win_blit_effect != 0)
                win_old_scanlines = 0;

DMA_Init_Interrupt();
DMA_INIT

OLED_Clear(0x0000);

return 0;
}

void dib_draw_window_DMA(void)
{
OLED_Rectangle(0,(SCR_HEIGHT-DST_HEIGHT)>>1,SCR_WIDTH-1,((SCR_HEIGHT+DST_HEIGHT)>>1)-1);

src=(u16*)(((u32)current_display.game_bitmap->base)+17536+64);

register u16* buf=(u16*)L1_BUF;
register u16 i;
for(i=0;i<(NB>>1);i++)*buf++=palette_16bit_lookup[*src++]; 
src+=(SRC_PITCH-SCR_WIDTH);
DMA_START
}

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


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

Код что ниже - рабочий, удаось поднять общую скорость (отрисовка экрана + вся программа) на 15 FPS !!! :rolleyes:

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

И сколько получилось? 40+15 FPS? И это по 16-битной шине?? Это всё равно очень медленно.

Для справки: у меня в одном проекте тоже используется 320*240 LCD в режиме 16 бит/пиксел.

Вот только подключен он по SPI на SCLK=45МГц. И частота CPU гораздо ниже - 180МГц.

Картинка у меня изначально нарисована в формате 4 бит/пиксел. А процедура отображения фрагментами преобразует содержимое в 16-битные пикселы (тоже с помощью палитры) в промежуточный буфер и передаёт через DMA-SPI. И исходная картинка и промежуточный буфер у меня находятся во внутренней памяти МК.

Так вот - преобразование следующего фрагмента (процессором) успевает закончится до завершения передачи (через DMA-SPI) предыдущего фрагмента. И ещё процессору остаётся время успеть заняться другими делами между преобразованиями фрагментов.

Т.е. - если бы я непрерывно только гнал кадры на LCD с высоким приоритетом, то у меня получилось бы: 45000000/(320*240*16) ~ 36FPS

И это по однобитному SPI!

И никаких ухищрений по оптимизации в цикле преобразования точек через таблицу палитры я не делалал - простой цикл на си, без каких-либо разворачиваний чего-либо.

А у Вас вроде 16-битная шина и процессор гораздо мощнее - у Вас скорость передачи картинки должна быть во много раз выше чем у меня. А почему-то получается сравнимая скорость с моей. Как будто по SPI картинку передаёте.

Да и вообще если просто посчитать: 550МГц/(320*240) - получается, что каждую секунду у процессора есть > 7100 тактов CPU на обработку одной точки экрана. Т.е. - даже при частоте FPS=60ГЦ будет около 120тактов CPU на точку! Это не просто много, это очень много - процессор должен просто почти всё время просто отдыхать. А у Вас он ещё и не успевает. :wacko:

Какая-то у Вас там глобальная проблема в коде....

 

переслать 320*240 при 26МГц это 3мс всего.

Не понял - что за 26МГц?

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


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

Не понял - что за 26МГц?

системная частота SCLK = частота ядра CCLK / 3 = 550/3 = 180МГц.

цикл асинхронной шины 7 тактов со всеми setup/holdами или 26МГц.

 

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


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

системная частота SCLK = частота ядра CCLK / 3 = 550/3 = 180МГц.

цикл асинхронной шины 7 тактов со всеми setup/holdами или 26МГц.

А почему так много - 7 тактов/пересылка?

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

Даже в этом случае у процессора автора должно быть просто море времени на эту работу и преобразование должно занимать меньше времени чем передача кадра за 3мсек.

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


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

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

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

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

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

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

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

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

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

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