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

Нужно оптимизировать код

Есть такой кусок кода:

if((pwm>pgm_read_byte(&brightness[pwm_ch[0]]))|(pwm==0)){pd &= ~(1<<0);}//1
        else {pd |= (1<<0);}
        if((pwm>pgm_read_byte(&brightness[pwm_ch[1]]))|(pwm==0)){pd &= ~(1<<1);}//2    
        else {pd |= (1<<1);}
        if((pwm>pgm_read_byte(&brightness[pwm_ch[2]]))|(pwm==0)){pa &= ~(1<<1);}//3
        else {pa |= (1<<1);}
        if((pwm>pgm_read_byte(&brightness[pwm_ch[3]]))|(pwm==0)){pa &= ~(1<<0);}//4
        else {pa |= (1<<0);}
        if((pwm>pgm_read_byte(&brightness[pwm_ch[4]]))|(pwm==0)){pd &= ~(1<<2);}//5
        else {pd |= (1<<2);}
        if((pwm>pgm_read_byte(&brightness[pwm_ch[5]]))|(pwm==0)){pd &= ~(1<<3);}//6
        else {pd |= (1<<3);}
        if((pwm>pgm_read_byte(&brightness[pwm_ch[6]]))|(pwm==0)){pd &= ~(1<<4);}//7
        else {pd |= (1<<4);}
        if((pwm>pgm_read_byte(&brightness[pwm_ch[7]]))|(pwm==0)){pd &= ~(1<<5);}//8
        else {pd |= (1<<5);}
        if((pwm>pgm_read_byte(&brightness[pwm_ch[8]]))|(pwm==0)){pb &= ~(1<<4);}//9
        else {pb |= (1<<4);}
        if((pwm>pgm_read_byte(&brightness[pwm_ch[9]]))|(pwm==0)){pb &= ~(1<<3);}//10
        else {pb |= (1<<3);}
        if((pwm>pgm_read_byte(&brightness[pwm_ch[10]]))|(pwm==0)){pb &= ~(1<<2);}//11
        else {pb |= (1<<2);}
        if((pwm>pgm_read_byte(&brightness[pwm_ch[11]]))|(pwm==0)){pb &= ~(1<<1);}//12
        else {pb |= (1<<1);}
        if((pwm>pgm_read_byte(&brightness[pwm_ch[12]]))|(pwm==0)){pb &= ~(1<<0);}//13
        else {pb |= (1<<0);}
        if((pwm>pgm_read_byte(&brightness[pwm_ch[13]]))|(pwm==0)){pd &= ~(1<<6);}//14
        else {pd |= (1<<6);}

Он обрабатывается за 345 тактов. Мне нужно менее 300. Это возможно? А можно это как-то оформить ассемблерной вставкой? Спасибо.

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


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

Проверку pgm==0 из каждого условия уберите, сделав проверку один раз и при выполнении ее сбрасывайте все биты одним чохом. Остальные проверки можно попробовать сделать в виде цикла с табличным преобразованием результата.

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


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

Жуть :)

 

А побитное или ("|") в условиях вместо логического ("||") применено осознанно?

 

Что этот код делает? Я так понимаю что-то типа конвертации grayscale в 2бит на какой-нить индикатор?

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

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


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

Спасибо за совет! Код действительно полегчал. Как я раньше этого не видел... А что Вы имели ввиду на счет табличного преобразования? Не совсем понимаю идею.

 

Жуть :)

 

А побитное или ("|") в условиях вместо логического ("||") применено осознанно?

 

Что этот код делает? Я так понимаю что-то типа конвертации grayscale в 2бит на какой-нить индикатор?

Формирует 14 каналов програмного ШИМ в соответствии с табличкой логарифмического изменения яркости светодиода.

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


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

А нельзя pgm_read_byte(&brightness[pwm_ch[1]]) делать 1 раз при смене уставки ШИМ-а? Или уставка меняется каждый период и смысла нет? Тогда условие упростится до (pwm > pwm_ch[1])

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


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

А нельзя pgm_read_byte(&brightness[pwm_ch[1]]) делать 1 раз при смене уставки ШИМ-а? Или уставка меняется каждый период и смысла нет? Тогда условие упростится до (pwm > pwm_ch[1])

Ну тут идея какая... ШИМ тикает 256 раз. В программе, откуда я этот кусок выдрал, значения могли меняться в любой момент времени. Во-вторых проверять нужно каждый тик на предмет выключить лампочку чтобы обеспечить глубину 8 бит. Да вобщемто уставка меняется не каждый период, но всеравно меняется. Так что деваться по сути всеравно некуда. Можно было бы выгрузить это в ОЗУ, но ОЗУ нет почти. Tiny2313.

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

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


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

избавьтесь от операций сдвига это забирает один так

 

1 << 0 = 1

1 << 1 = 2 и тд

 

хотя нифига это не даст :( компилятор умный это и сам при компиляции сделает

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

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


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

избавьтесь от операций сдвига это забирает один так

 

1 << 0 = 1

1 << 1 = 2 и тд

А ты оттранслируй и посмотри. Чисто из любопытства. :)

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


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

pwm>pgm_read_byte(&brightness[pwm_ch[7]])

 

что лежит в pwm ?

что возвращает pgm_read_byte() ?

 

как я понимаю brightness[] это собственно табличка логорифмического преобразования а pwm_ch[] это то значение которое мы получили ?

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


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

pwm>pgm_read_byte(&brightness[pwm_ch[7]])

 

что лежит в pwm ?

что возвращает pgm_read_byte() ?

 

как я понимаю brightness[] это собственно табличка логорифмического преобразования а pwm_ch[] это то значение которое мы получили ?

совершенно верно.

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


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

совершенно верно.

меня с точки зрения оптимизации волнует больше что возвращает pgm_read_byte

 

потому что очень большое чувство что можно там сократить до pgm_read_byte (pwm_ch[] ) или вообще привести к статичной табличке потому что у вас

результат прямо и однозначно зависит от значения которое лежит в pwm_ch[] значит и конечный результат можно предварительно вычислить и получить в виде val [pwm_ch[]] и тогда код сведется к красивому виду вроде

pb = (pwm > val[pwm_ch[]]) ? (pb & ~1) : (pb | 1);

а так как вы передаёте значения по ссылке то компилятор не сможет сделать этого за вас

 

UPD -----------------------------------------------------------------------------------------------------

Набросал небольшой кусочек кода , прошу общественность ногами не пинать , давно не писал на С сейчас пишу на языке более высокого уровня потому мог какие-то фенички оттуда утащить

#проверяем и сбрасываем сразу при нуле 
#два массива мапят порты (кто хочет можно массивом двумерных массивов , но по моему так проще)
#цикл проверки каналов и задания соответствующих значений (тут считается что автор пересчитал свой массивчик brightness до статических значений )
if ( pwm == 0 ) { pa |= 3; pb |= 31; pd |= 127; } else {
  int     log2phy[] = { pd, pd, pa, pa, pd, pd, pd, pd, pb, pb, pb, pb, pb, pd };
  char  log2val[] = {  1,  2,  2,  1,  4,  8, 16, 32, 16,  8,  4,  2,  1, 64 };
  for (int i = 0; i < 14; ++i ) 
   { log2phy[i] = (pwm > brightness[pwm_ch[i]]) ? (log2phy[i] & ~log2val[i]]) : (log2phy[i] | log2val[i]); }
}

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

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


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

Еще можно для оптимизации вытащить brightness из флэш и поместить в ОЗУ. К нему обращение будет немного быстрее.

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


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

2follow_me:

2777777:

 

Глянул искомый девайс:

2KB of In-System Self-Programmable Flash, 128 Bytes In-System Programmable EEPROM, 128 Bytes Internal SRAM

 

В принципе, зависит от задачи, но мне кажется, что лучше RAM не забивать лишними данными. По приведённому коду есть одно сомнение, оно же - идея для оптимизации. Надо чтобы для установки/сброса битов использовались инструкции SBR и CBR, а не логическая арифметика.

 

А вообще, ШИМ контроллер, хоть и программный должен ШИМ-ом заниматься, а не осуществлять ещё и логарифмические преобразования :-)

 

IMHO

 

UPD: Я имел ввиду SBI, CBI :-)

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

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


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

Все чаще и чаще наблюдаются жутковатые перлы. По теме:

#include <avr/io.h>
#include <avr/pgmspace.h>
PROGMEM char brightness[] = "888888888888888888888888888";

volatile unsigned char pwm;
volatile unsigned int pd;
volatile unsigned char pwm_ch[14];

int main(void)
{
if(pwm)
{
unsigned char *pwmch = &pwm_ch;
int d = 0;
 for(char i=0; i<14; i++)
 {
   unsigned int msk = 1;
   if(pwm <= pgm_read_byte(&brightness[*pwmch++])) pd |= msk;
   msk <<= 1;
 }
pd = d;
}
else
{
 pd = 0;
}
return 0;
}

В таком (страшненьком) виде (-О2) - уже 317 тактов на меге 8

Копнуть можно, если выровнять таблицу констант на границу 256 байт и упростить обращения к 16-битному pd |= msk;

 

 

Несколько апдейтов.

1. if(pwm <= pgm_read_byte(&brightness[*pwmch++])) pd |= msk; - конечно же надо

if(pwm <= pgm_read_byte(&brightness[*pwmch++])) d |= msk;

 

2. При -О3 дало 192 такта - попробуйте работоспособность, листинг на вид рабочий, больше не разбирался.

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


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

Еще можно для оптимизации вытащить brightness из флэш и поместить в ОЗУ. К нему обращение будет немного быстрее.

Ага 2 такта вместо 3 при косвенной - крутотень какая:-).

На общем фоне капля в море - даже и не заметишь (к примеру 150 или 151 так).

 

 

В таком (страшненьком) виде (-О2) - уже 317 тактов на меге 8

При -О3 дало 192 такта

А при -Оs сколько?

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


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

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

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

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

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

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

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

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

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

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