реклама на сайте
подробности

 
 
> Нужно оптимизировать код, Есть идеи как?
skyled
сообщение Jan 20 2011, 14:56
Сообщение #1


Местный
***

Группа: Участник
Сообщений: 217
Регистрация: 11-06-10
Пользователь №: 57 868



Есть такой кусок кода:
Код
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. Это возможно? А можно это как-то оформить ассемблерной вставкой? Спасибо.
Go to the top of the page
 
+Quote Post
3 страниц V   1 2 3 >  
Start new topic
Ответов (1 - 36)
rezident
сообщение Jan 20 2011, 15:07
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Проверку pgm==0 из каждого условия уберите, сделав проверку один раз и при выполнении ее сбрасывайте все биты одним чохом. Остальные проверки можно попробовать сделать в виде цикла с табличным преобразованием результата.
Go to the top of the page
 
+Quote Post
codier
сообщение Jan 20 2011, 15:14
Сообщение #3


Участник
*

Группа: Участник
Сообщений: 29
Регистрация: 21-01-05
Пользователь №: 2 113



Жуть sm.gif

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

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

Сообщение отредактировал codier - Jan 20 2011, 15:20
Go to the top of the page
 
+Quote Post
skyled
сообщение Jan 20 2011, 15:21
Сообщение #4


Местный
***

Группа: Участник
Сообщений: 217
Регистрация: 11-06-10
Пользователь №: 57 868



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

Цитата(codier @ Jan 20 2011, 18:14) *
Жуть sm.gif

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

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

Формирует 14 каналов програмного ШИМ в соответствии с табличкой логарифмического изменения яркости светодиода.
Go to the top of the page
 
+Quote Post
codier
сообщение Jan 20 2011, 15:26
Сообщение #5


Участник
*

Группа: Участник
Сообщений: 29
Регистрация: 21-01-05
Пользователь №: 2 113



А нельзя pgm_read_byte(&brightness[pwm_ch[1]]) делать 1 раз при смене уставки ШИМ-а? Или уставка меняется каждый период и смысла нет? Тогда условие упростится до (pwm > pwm_ch[1])
Go to the top of the page
 
+Quote Post
skyled
сообщение Jan 20 2011, 15:47
Сообщение #6


Местный
***

Группа: Участник
Сообщений: 217
Регистрация: 11-06-10
Пользователь №: 57 868



Цитата(codier @ Jan 20 2011, 18:26) *
А нельзя pgm_read_byte(&brightness[pwm_ch[1]]) делать 1 раз при смене уставки ШИМ-а? Или уставка меняется каждый период и смысла нет? Тогда условие упростится до (pwm > pwm_ch[1])

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

Сообщение отредактировал skyled - Jan 20 2011, 15:50
Go to the top of the page
 
+Quote Post
follow_me
сообщение Jan 20 2011, 18:03
Сообщение #7


Частый гость
**

Группа: Участник
Сообщений: 182
Регистрация: 4-11-10
Пользователь №: 60 646



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

1 << 0 = 1
1 << 1 = 2 и тд

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

Сообщение отредактировал follow_me - Jan 20 2011, 18:14
Go to the top of the page
 
+Quote Post
777777
сообщение Jan 20 2011, 18:08
Сообщение #8


Профессионал
*****

Группа: Участник
Сообщений: 1 091
Регистрация: 25-07-07
Из: Саратов
Пользователь №: 29 357



Цитата(follow_me @ Jan 20 2011, 21:03) *
избавьтесь от операций сдвига это забирает один так

1 << 0 = 1
1 << 1 = 2 и тд

А ты оттранслируй и посмотри. Чисто из любопытства. sm.gif
Go to the top of the page
 
+Quote Post
follow_me
сообщение Jan 20 2011, 18:40
Сообщение #9


Частый гость
**

Группа: Участник
Сообщений: 182
Регистрация: 4-11-10
Пользователь №: 60 646



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

что лежит в pwm ?
что возвращает pgm_read_byte() ?

как я понимаю brightness[] это собственно табличка логорифмического преобразования а pwm_ch[] это то значение которое мы получили ?
Go to the top of the page
 
+Quote Post
smk
сообщение Jan 20 2011, 19:09
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 2 246
Регистрация: 17-03-05
Из: Украина, Киев
Пользователь №: 3 446



Цитата(follow_me @ Jan 20 2011, 20:40) *
pwm>pgm_read_byte(&brightness[pwm_ch[7]])

что лежит в pwm ?
что возвращает pgm_read_byte() ?

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

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


--------------------
Живи днем так, чтобы ночью ты спал спокойно.
Go to the top of the page
 
+Quote Post
follow_me
сообщение Jan 20 2011, 20:32
Сообщение #11


Частый гость
**

Группа: Участник
Сообщений: 182
Регистрация: 4-11-10
Пользователь №: 60 646



Цитата(smk @ Jan 20 2011, 21:09) *
совершенно верно.

меня с точки зрения оптимизации волнует больше что возвращает 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 - Jan 20 2011, 23:09
Go to the top of the page
 
+Quote Post
777777
сообщение Jan 21 2011, 07:18
Сообщение #12


Профессионал
*****

Группа: Участник
Сообщений: 1 091
Регистрация: 25-07-07
Из: Саратов
Пользователь №: 29 357



Еще можно для оптимизации вытащить brightness из флэш и поместить в ОЗУ. К нему обращение будет немного быстрее.
Go to the top of the page
 
+Quote Post
codier
сообщение Jan 21 2011, 07:38
Сообщение #13


Участник
*

Группа: Участник
Сообщений: 29
Регистрация: 21-01-05
Пользователь №: 2 113



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 - Jan 21 2011, 07:46
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Jan 21 2011, 08:54
Сообщение #14


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



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

#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 такта - попробуйте работоспособность, листинг на вид рабочий, больше не разбирался.
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Jan 21 2011, 14:01
Сообщение #15


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Цитата(777777 @ Jan 21 2011, 10:18) *
Еще можно для оптимизации вытащить brightness из флэш и поместить в ОЗУ. К нему обращение будет немного быстрее.

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


Цитата(_Pasha @ Jan 21 2011, 11:54) *
В таком (страшненьком) виде (-О2) - уже 317 тактов на меге 8
При -О3 дало 192 такта

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


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
follow_me
сообщение Jan 21 2011, 15:34
Сообщение #16


Частый гость
**

Группа: Участник
Сообщений: 182
Регистрация: 4-11-10
Пользователь №: 60 646



В циклах кстати для приращения итератора стоит использовать ++i вместо i++ т.к. i++ выполняется за 3 такта а ++i за 1 итого выходит что только на итераторе 2* n итераций

хотя опять же нужно смотреть как такое оптимизирует оптимизатор
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Jan 21 2011, 18:50
Сообщение #17


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(demiurg_spb @ Jan 21 2011, 18:01) *
А при -Оs сколько?

тоже где-то 317-325 было

Цитата(follow_me @ Jan 21 2011, 19:34) *
В циклах кстати для ...

Это, как и предпочтения do{}while вместо for() - суетная часть. Где-то работает, где-то компилер умнее. Я вот, недавно бодаясь с МСС18, прогнулся так, что было стыдно. Потом перестал это делать - результат оказался хуже на 2-3 процента. Оно не надо.
Go to the top of the page
 
+Quote Post
defunct
сообщение Jan 23 2011, 22:41
Сообщение #18


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Концептуально можно ускорить код - если вместо проверки каждого канала в каждом "Loop'e" таймера, организовать всего 14+1 прерываний от таймера за период в 256 тиков. (Где 14 прерываний соответствуют 14-ти каналам PWM, 15-ое - сброс всех каналов в исходное состояние).
Итого для 8-ми битной глубины у вас будет не 256 прерываний за период длительностью меньше 300 тактов на обработку каждого,
а всего 14+1 с ресурсом 256 * 300 / 15 = 5120 тактов на каждое. Если время срабатывания расчитывать на цикл вперед, то обработчики прерывания будут очень короткими.

Программировать время следующего срабатывания каждого из прерываний можно например при сбросе всех каналов в исходное состояние.
код сведется к чему-то такому:

Код
Timer_CompA_ISR()
{
    turn_off( CurrentChan++ );

    if (CurrentChan > MAX_CHAN_COUNT)
    {
        CurrentChan = 0;
        return;
    }

    OCRA = ChanGetLifeTime( CurrentChan );
}


Timer_OvrISR()
{
    // врубить все
    turn_on( AllChannels );

    // посчитать такт отключения каждого из каналов (время "жизни")
    UpdateLifeTime( ... );

    // отсортировать каналы по времени жизни по-возрастанию
    SortChannelsByTimeAscending( ... );
}


А можно и в основном цикле программы. Обработка частных случаев (кода время жизни нескольких каналов будет совадать) тоже большого труда не составит:

Код
Timer_CompA_ISR()
{
    turn_off( CurrentChan++ );

    if (CurrentChan > MAX_CHAN_COUNT)
    {
        CurrentChan = 0;
        return;
    }

    if (OCRA == ChanGetLifeTime( CurrentChannel ) )
        Timer_CompA_ISR();  // запустить сл. канал прямо сейчас (лучше всего rjmp'ом)
    else
        OCRA = ChanGetLifeTime( CurrentChan );  // проапдейтить таймер на прерывание в нужное время
}
Go to the top of the page
 
+Quote Post
skyled
сообщение Jan 24 2011, 14:55
Сообщение #19


Местный
***

Группа: Участник
Сообщений: 217
Регистрация: 11-06-10
Пользователь №: 57 868



Навскидку разумное зерно есть. Надо бдумать. А не получится ли, что за счет сортировки будет "шило на мыло"?
Go to the top of the page
 
+Quote Post
pokos
сообщение Jan 24 2011, 15:05
Сообщение #20


Местный
***

Группа: Участник
Сообщений: 270
Регистрация: 29-06-06
Пользователь №: 18 445



У меня на 3 канала было вот так сделано:
Код
// Timer 0 overflow interrupt service routine
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
// Reinitialize Timer 0 value
TCNT0=256-39+4;
//PWM-----------------------
pwr_cnt++;
if (red_a>pwr_cnt)
    { PORTD.7=1;}
else
    {PORTD.7=0;};
    
if (green_a>pwr_cnt)
    {PORTD.6=1;}
else
    {PORTD.6=0;};
    
if (blue_a>pwr_cnt)
    {PORTD.5=1;}
else
    {PORTD.5=0;};
}

Оттранслировалось в:
_timer0_ovf_isr:
    RCALL __SAVEISR
;      49 // Reinitialize Timer 0 value
;      50 TCNT0=256-39+4;
    LDI  R30,LOW(221)
    OUT  0x32,R30
;      51 //PWM-----------------------
;      52 pwr_cnt++;
    LDS  R30,_pwr_cnt
    SUBI R30,-LOW(1)
    STS  _pwr_cnt,R30
;      53 if (red_a>pwr_cnt) {PORTD.7=1;}
    LDS  R26,_red_a
    CP   R30,R26
    BRSH _0x2B
    SBI  0x12,7
;      54 else {PORTD.7=0;};
    RJMP _0x2C
_0x2B:
    CBI  0x12,7
_0x2C:
;      55 if (green_a>pwr_cnt) {PORTD.6=1;}
    LDS  R30,_pwr_cnt
    LDS  R26,_green_a
    CP   R30,R26
    BRSH _0x2D
    SBI  0x12,6
;      56 else {PORTD.6=0;};
    RJMP _0x2E
_0x2D:
    CBI  0x12,6
_0x2E:
;      57 if (blue_a>pwr_cnt) {PORTD.5=1;}
    LDS  R30,_pwr_cnt
    LDS  R26,_blue_a
    CP   R30,R26
    BRSH _0x2F
    SBI  0x12,5
;      58 else {PORTD.5=0;};
    RJMP _0x30
_0x2F:
    CBI  0x12,5
_0x30:
;      59 }
    RCALL __LOADISR
    RETI


Сообщение отредактировал pokos - Jan 24 2011, 15:21
Go to the top of the page
 
+Quote Post
defunct
сообщение Jan 24 2011, 16:22
Сообщение #21


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(skyled @ Jan 24 2011, 16:55) *
А не получится ли, что за счет сортировки будет "шило на мыло"?

Должен быть выигрышь однозначно - если это будет сортировка массива из 14-ти указателей на цикл вперед.
И сортировать лучше не в прерывании, а в основном цикле программы.
Go to the top of the page
 
+Quote Post
pokos
сообщение Jan 24 2011, 17:37
Сообщение #22


Местный
***

Группа: Участник
Сообщений: 270
Регистрация: 29-06-06
Пользователь №: 18 445



Цитата(defunct @ Jan 24 2011, 19:22) *
Должен быть выигрышь однозначно...

Выигрыш будет, если забить на разницу между каналами меньше времени обработки прерывания. Если не забивать, то там ещё тот гемор получается. С соответствующей потерей бытродействия, понятно.
Поэтому, я просто уменьшил разрядность ШИМа до 6-ти, когда понадобилось моргать быстрее. На глаз это уменьшение было слабо заметно (в моём случае, понятно).
Go to the top of the page
 
+Quote Post
skyled
сообщение Jan 25 2011, 10:11
Сообщение #23


Местный
***

Группа: Участник
Сообщений: 217
Регистрация: 11-06-10
Пользователь №: 57 868



Тут выяснилось, что еще вот эта конструкция кушает невообразимое число тактов.
Код
for(unsigned char i=0;i<14;i++)
        {
            if((a & (1<<i))&(b & (1<<i))) {pwm_ch[i]=255;}//1и1
            if((a & (1<<i))&(!(b & (1<<i)))) {pwm_ch[i]=255;}//1и0
            if((!(a & (1<<i)))&(b & (1<<i))) {pwm_ch[i]=0;}//0и1
            if((!(a & (1<<i)))&(!(b & (1<<i)))) {pwm_ch[i]=0;}//0и0
        }

Даже если уменьшить разрядность ШИМ втрое... уже и не знаю как и быть.
Go to the top of the page
 
+Quote Post
kolobok0
сообщение Jan 25 2011, 10:15
Сообщение #24


практикующий тех. волшебник
*****

Группа: Участник
Сообщений: 1 190
Регистрация: 9-09-05
Пользователь №: 8 417



Цитата(pokos @ Jan 24 2011, 18:05) *
Код
...Оттранслировалось в:
_timer0_ovf_isr:
    RCALL __SAVEISR
....
    RCALL __LOADISR
    RETI


А теперь в азм листинге проставте тайминги. Только колл-рэт у вас 8 тактов. итого 16 ненужных тактов в плюсе. я не говорю у же о повторе одного и того же действия подряд аж 3 раза sm.gif юзается один порт. результат = обнуление определённых пинов. и если необходимая переменная больше ... то выставляем в единичку. Вам подсказать как три пина одновременно можно обнулить? sm.gif кстати можно не засовывать сразу в порт результат. ну надеюсь "куда копать" показал. думаю можно уложиться в 20-30 тактов. если в ущерб регистров - то и того меньше. короче говоря оптимизировать вагон и маленькую тележку можно ышо.

хотите оптимально - пишите на азм-е.
оптимизатор может "оптимизнуть" готовые функции из библиотеки - на 5+, а вот логику - тут уж сильно зависит от опыта того кто писал оптимизатор и за сколько вы его купили.

чиссо ИМХО:
собственно если пишите в одни руки, доводите проекты до коммерческого ума - то юзать выше чем азм не совсем в струю.

удачи вам
(круглый)
Go to the top of the page
 
+Quote Post
_Bill
сообщение Jan 25 2011, 10:46
Сообщение #25


Местный
***

Группа: Участник
Сообщений: 416
Регистрация: 18-04-06
Из: Челябинск
Пользователь №: 16 219



Цитата(pokos @ Jan 24 2011, 19:05) *
У меня на 3 канала было вот так сделано:
Код
// Timer 0 overflow interrupt service routine
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
// Reinitialize Timer 0 value
TCNT0=256-39+4;
//PWM-----------------------
pwr_cnt++;
if (red_a>pwr_cnt)
    { PORTD.7=1;}
else
    {PORTD.7=0;};
    
if (green_a>pwr_cnt)
    {PORTD.6=1;}
else
    {PORTD.6=0;};
    
if (blue_a>pwr_cnt)
    {PORTD.5=1;}
else
    {PORTD.5=0;};
}

Попробуйте так
Код
// Timer 0 overflow interrupt service routine
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
char _tmp;
// Reinitialize Timer 0 value
TCNT0=256-39+4;
//PWM-----------------------
_tmp = ++pwr_cnt;
if (red_a > _tmp)
    { PORTD.7=1;}
else
    {PORTD.7=0;};
    
if (green_a > _tmp)
    {PORTD.6=1;}
else
    {PORTD.6=0;};
    
if (blue_a > _tmp)
    {PORTD.5=1;}
else
    {PORTD.5=0;};
}
Go to the top of the page
 
+Quote Post
pokos
сообщение Jan 25 2011, 11:39
Сообщение #26


Местный
***

Группа: Участник
Сообщений: 270
Регистрация: 29-06-06
Пользователь №: 18 445



Цитата(kolobok0 @ Jan 25 2011, 13:15) *
А теперь в азм листинге проставте тайминги.

Проставлял, было дело. Преехал на IAR по этому поводу.
Цитата
...Вам подсказать как три пина одновременно можно обнулить?

Спасибо, я в курсе. А как одновременно обнулить 14 пинов, не подскажете? Которые в разных портах. И чтобы при этом максимальный коэф. заполнения был ровно 1? Займитесь на досуге этими вопросами, увидите, что моё решение не самое плохое.
Цитата
хотите оптимально - пишите на азм-е.

Не хочу писать на Асме, надоело. Оптимально - это когда задача выполнена за требуемое время. Потому и не хочу.

Цитата(_Bill @ Jan 25 2011, 13:46) *
Попробуйте так
..._tmp = ++pwr_cnt;...

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

Цитата(skyled @ Jan 25 2011, 13:11) *
Тут выяснилось, что еще вот эта конструкция кушает невообразимое число тактов.

Само собой. Индексация в массиве - это конь прожорливый. Цикл развернуть в линиию, указатель на массив сделать отдельным. Инкрементировать его. Помнится, IAR такие вещи правильно оптимизировал. Попробуйте.
И я не очень понимаю, зачем этот странный наворот со сдвигами. В чём его цель?


Сообщение отредактировал pokos - Jan 25 2011, 11:34
Go to the top of the page
 
+Quote Post
xemul
сообщение Jan 25 2011, 11:52
Сообщение #27



*****

Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731



Цитата(skyled @ Jan 25 2011, 13:11) *
Тут выяснилось, что еще вот эта конструкция кушает невообразимое число тактов.
Код
for(unsigned char i=0;i<14;i++)
        {
            if((a & (1<<i))&(b & (1<<i))) {pwm_ch[i]=255;}//1и1
            if((a & (1<<i))&(!(b & (1<<i)))) {pwm_ch[i]=255;}//1и0
            if((!(a & (1<<i)))&(b & (1<<i))) {pwm_ch[i]=0;}//0и1
            if((!(a & (1<<i)))&(!(b & (1<<i)))) {pwm_ch[i]=0;}//0и0
        }

Даже если уменьшить разрядность ШИМ втрое... уже и не знаю как и быть.

имхо, у Вас попутаны ! и ~.
Эта жуть приводится к
Код
for(unsigned char i=0, unsigned int tmp = 1; i<14; i++)
{
   if(a & tmp) pwm_ch[i]=255; //1и1, 1и0
   else pwm_ch[i]=0; //0и1, 0и0
   tmp <<= 1;
}

Можете ещё пооптимизировать в сторону unsigned char tmp = 1; и (high) a, (low) a (или как оно там в винавре)
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jan 25 2011, 12:16
Сообщение #28


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



QUOTE (skyled @ Jan 25 2011, 12:11) *
Тут выяснилось, что еще вот эта конструкция кушает невообразимое число тактов.
Мама!
1) Вы на каждой итерации делаете сдвиг единицы на i разрядов. Для процессора без аппаратного сдвигателя это очень накладная операция.
2) Вы используете двоичное "И" (&) вместо логического (&&).
3) заметьте, что у вас результат не зависит от значения b
CODE
uint8_t *ptr = &pwm_ch[13];
for(uint16_t mask = (1<<13); mask; mask >>= 1)
{
    if(a & mask)
        *ptr-- = 255;
    else
        *ptr-- = 0;
}


P.S. Ой, xemul уже то же самое написал. Возможно, у него код даже лучше.
P.P.S. ! и ~ у него не попутаны.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
pokos
сообщение Jan 25 2011, 20:30
Сообщение #29


Местный
***

Группа: Участник
Сообщений: 270
Регистрация: 29-06-06
Пользователь №: 18 445



Чото не могу найти в закромах финальные исходники того случая. А было там 12 каналов ШИМ по 6 разрядов. Успевало ещё два фильтра второго порядка плюс херитель постоянной составляющей и АРУ. Но на Цоде Визион это не успевало. Только на ИАР.
У ШИМа был принцип, что я изложил в сообщении 26. Сортировку и уменьшение колва прерываний пробовал. При минимальных зазорах мерцает неприятно.
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Jan 25 2011, 21:07
Сообщение #30


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(kolobok0 @ Jan 25 2011, 13:15) *
хотите оптимально - пишите на азм-е.
оптимизатор может "оптимизнуть" готовые функции из библиотеки - на 5+, а вот логику - тут уж сильно зависит от опыта того кто писал оптимизатор и за сколько вы его купили.


Поздно! Вот годика 4 назад, когда еще было много проблем с сями, тогда бы это звучало серьезно. Сейчас - увы.

Цитата(Сергей Борщ @ Jan 25 2011, 15:16) *
Мама!

crying.gif

Цитата(skyled @ Jan 25 2011, 13:11) *
Тут выяснилось, что еще вот эта конструкция кушает невообразимое число тактов.

Ара щто ти здэляль со мной? Йа плакаль, перед женщин стидно..
Go to the top of the page
 
+Quote Post
kolobok0
сообщение Jan 25 2011, 22:00
Сообщение #31


практикующий тех. волшебник
*****

Группа: Участник
Сообщений: 1 190
Регистрация: 9-09-05
Пользователь №: 8 417



Цитата(_Pasha @ Jan 26 2011, 00:07) *
...Вот годика 4 назад...


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

удачи вам
(круглый)
ЗЫ
всё конечно же зависит от задачи. в своё время приходилось писать и аля шарп технологию под 4051 кристал. но то так было задумано sm.gif
Go to the top of the page
 
+Quote Post
xemul
сообщение Jan 26 2011, 14:06
Сообщение #32



*****

Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731



Цитата(Сергей Борщ @ Jan 25 2011, 15:16) *
P.P.S. ! и ~ у него не попутаны.

Замена ! на ~ без каких-либо ещё изменений даст лучший код на выходе.
Замена посерёдке & на && добавит логичности сорцу и код тоже не ухудшит.
А ненужный битово-логический замес, устроенный skyled'ом, не даёт ничего, кроме головняка оптимизатору.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jan 26 2011, 18:39
Сообщение #33


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



QUOTE (xemul @ Jan 26 2011, 16:06) *
Замена ! на ~ без каких-либо ещё изменений даст лучший код на выходе.
Да, естественно. Он сведется к циклу pwm[i] = 255. Ибо X & (1<<i) дает либо 0, либо 1<<i, !(X & (1<<i)) имеет результат 1 или 0, а вот ~(X & (1<<i)) даст либо int из всех единиц, либо из всех единиц кроме i-го разряда, что в обоих случаях true.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Jan 27 2011, 04:15
Сообщение #34


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(kolobok0 @ Jan 26 2011, 01:00) *
или Вы чиссо по животным в вакууме специализируетесь?

cranky.gif Ну почитайте мои посты, в конце концов. Йа не лублу вакуум.
Go to the top of the page
 
+Quote Post
defunct
сообщение Feb 1 2011, 12:51
Сообщение #35


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(_Pasha @ Jan 27 2011, 06:15) *
cranky.gif Ну почитайте мои посты, в конце концов. Йа не лублу вакуум.

Ни один компилятор не даст такой эффективный код, какой может сделать __опытный__ асм программист.
Это аксиома. Неопытному же писать на асм противопоказано - т.к. напишет хуже чем компилятор сделает.
Обработчик прерывания всей той чухни из первого поста на асм занял бы не больше 100 тактов с условием применения регистровых переменных.
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Feb 1 2011, 16:37
Сообщение #36


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(defunct @ Feb 1 2011, 15:51) *
Ни один компилятор не даст такой эффективный код, какой может сделать __опытный__ асм программист.

Проблема в интенсивном использовании компилятором(winavr) инструкций lds/sts - это раз.
192 такта при -О3(см. в начале темы) - целиком за счет разворачивания цикла. Это два. Там около 490 байт заняло оно, забыл тогда сказать.
Там на регистровые переменные тоже не особо разбежишься - надо использовать ldd/std
А по Вашему предложению - автор если собрался его реализовать, все-таки интересно, во сколько циклов оно встанет.
sm.gif Извините за словесный понос.
Go to the top of the page
 
+Quote Post
defunct
сообщение Feb 2 2011, 02:24
Сообщение #37


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(_Pasha @ Feb 1 2011, 18:37) *
А по Вашему предложению - автор если собрался его реализовать, все-таки интересно, во сколько циклов оно встанет.

Ресурсоемкость кода сократиться в 18 раз только за счет того что прерываний стало в 18 раз меньше, плюс ресурсоемкость самих обработчиков сократится еще в 10 раз за счет того что обрабатываются не все 14, а только 1 канал. Итого на 2 порядка меньше от посчитанных Вами 190 тактов )
На асм писать не предлагаю - здесь нет в этом нужды.

Цитата
Там на регистровые переменные тоже не особо разбежишься - надо использовать ldd/std

ldd/std определенно пользовать не надо.
Массив 14-ти каналов разместить в регистрах, благо в AVR их аж 16 лишних. sm.gif
обработчик прерывания банально пишем 5 команд и копипастим 14 раз:

mov - 1 такт
lpm - 3
cp - 1
brlo вместе с cbi/sbi - 2 такта.
Итого на асм 1 + (1 + 3 + 1 + 2) * 14 = 99 тактов решением в лоб. ;>
Go to the top of the page
 
+Quote Post

3 страниц V   1 2 3 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 21st July 2025 - 08:28
Рейтинг@Mail.ru


Страница сгенерированна за 0.01797 секунд с 7
ELECTRONIX ©2004-2016