skyled 0 20 января, 2011 Опубликовано 20 января, 2011 · Жалоба Есть такой кусок кода: 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. Это возможно? А можно это как-то оформить ассемблерной вставкой? Спасибо. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
rezident 0 20 января, 2011 Опубликовано 20 января, 2011 · Жалоба Проверку pgm==0 из каждого условия уберите, сделав проверку один раз и при выполнении ее сбрасывайте все биты одним чохом. Остальные проверки можно попробовать сделать в виде цикла с табличным преобразованием результата. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
codier 0 20 января, 2011 Опубликовано 20 января, 2011 (изменено) · Жалоба Жуть :) А побитное или ("|") в условиях вместо логического ("||") применено осознанно? Что этот код делает? Я так понимаю что-то типа конвертации grayscale в 2бит на какой-нить индикатор? Изменено 20 января, 2011 пользователем codier Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
skyled 0 20 января, 2011 Опубликовано 20 января, 2011 · Жалоба Спасибо за совет! Код действительно полегчал. Как я раньше этого не видел... А что Вы имели ввиду на счет табличного преобразования? Не совсем понимаю идею. Жуть :) А побитное или ("|") в условиях вместо логического ("||") применено осознанно? Что этот код делает? Я так понимаю что-то типа конвертации grayscale в 2бит на какой-нить индикатор? Формирует 14 каналов програмного ШИМ в соответствии с табличкой логарифмического изменения яркости светодиода. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
codier 0 20 января, 2011 Опубликовано 20 января, 2011 · Жалоба А нельзя pgm_read_byte(&brightness[pwm_ch[1]]) делать 1 раз при смене уставки ШИМ-а? Или уставка меняется каждый период и смысла нет? Тогда условие упростится до (pwm > pwm_ch[1]) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
skyled 0 20 января, 2011 Опубликовано 20 января, 2011 (изменено) · Жалоба А нельзя pgm_read_byte(&brightness[pwm_ch[1]]) делать 1 раз при смене уставки ШИМ-а? Или уставка меняется каждый период и смысла нет? Тогда условие упростится до (pwm > pwm_ch[1]) Ну тут идея какая... ШИМ тикает 256 раз. В программе, откуда я этот кусок выдрал, значения могли меняться в любой момент времени. Во-вторых проверять нужно каждый тик на предмет выключить лампочку чтобы обеспечить глубину 8 бит. Да вобщемто уставка меняется не каждый период, но всеравно меняется. Так что деваться по сути всеравно некуда. Можно было бы выгрузить это в ОЗУ, но ОЗУ нет почти. Tiny2313. Изменено 20 января, 2011 пользователем skyled Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
follow_me 0 20 января, 2011 Опубликовано 20 января, 2011 (изменено) · Жалоба избавьтесь от операций сдвига это забирает один так 1 << 0 = 1 1 << 1 = 2 и тд хотя нифига это не даст :( компилятор умный это и сам при компиляции сделает Изменено 20 января, 2011 пользователем follow_me Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
777777 0 20 января, 2011 Опубликовано 20 января, 2011 · Жалоба избавьтесь от операций сдвига это забирает один так 1 << 0 = 1 1 << 1 = 2 и тд А ты оттранслируй и посмотри. Чисто из любопытства. :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
follow_me 0 20 января, 2011 Опубликовано 20 января, 2011 · Жалоба pwm>pgm_read_byte(&brightness[pwm_ch[7]]) что лежит в pwm ? что возвращает pgm_read_byte() ? как я понимаю brightness[] это собственно табличка логорифмического преобразования а pwm_ch[] это то значение которое мы получили ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
smk 0 20 января, 2011 Опубликовано 20 января, 2011 · Жалоба pwm>pgm_read_byte(&brightness[pwm_ch[7]]) что лежит в pwm ? что возвращает pgm_read_byte() ? как я понимаю brightness[] это собственно табличка логорифмического преобразования а pwm_ch[] это то значение которое мы получили ? совершенно верно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
follow_me 0 20 января, 2011 Опубликовано 20 января, 2011 (изменено) · Жалоба совершенно верно. меня с точки зрения оптимизации волнует больше что возвращает 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]); } } Изменено 20 января, 2011 пользователем follow_me Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
777777 0 21 января, 2011 Опубликовано 21 января, 2011 · Жалоба Еще можно для оптимизации вытащить brightness из флэш и поместить в ОЗУ. К нему обращение будет немного быстрее. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
codier 0 21 января, 2011 Опубликовано 21 января, 2011 (изменено) · Жалоба 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 :-) Изменено 21 января, 2011 пользователем codier Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_Pasha 0 21 января, 2011 Опубликовано 21 января, 2011 · Жалоба Все чаще и чаще наблюдаются жутковатые перлы. По теме: #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 такта - попробуйте работоспособность, листинг на вид рабочий, больше не разбирался. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
demiurg_spb 0 21 января, 2011 Опубликовано 21 января, 2011 · Жалоба Еще можно для оптимизации вытащить brightness из флэш и поместить в ОЗУ. К нему обращение будет немного быстрее. Ага 2 такта вместо 3 при косвенной - крутотень какая:-). На общем фоне капля в море - даже и не заметишь (к примеру 150 или 151 так). В таком (страшненьком) виде (-О2) - уже 317 тактов на меге 8 При -О3 дало 192 такта А при -Оs сколько? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться