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

 
 
2 страниц V  < 1 2  
Reply to this topicStart new topic
> Закольцевать данные, программа на Си
x893
сообщение Jun 5 2014, 09:15
Сообщение #16


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

Группа: Свой
Сообщений: 1 333
Регистрация: 27-10-08
Из: Планета Земля
Пользователь №: 41 226



а может просто код посмотреть ?
1. http://c.learncodethehardway.org/book/ex44.html
2. https://code.mythtv.org/doxygen/ringbuffer_8c_source.html
и еще примерно 5000000 примеров

Сообщение отредактировал x893 - Jun 5 2014, 09:15
Go to the top of the page
 
+Quote Post
mempfis_
сообщение Jun 5 2014, 09:34
Сообщение #17


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

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



Цитата(megajohn @ Jun 5 2014, 15:34) *
автар перепутал байт
вместо "Тогда Ваш буффер будет занимать диапазон адресов 0xFF1000 - 0x001000"
читать "Тогда Ваш буффер будет занимать диапазон адресов 0x0010FF - 0x001000"

и далее, сам же запутался (или HumanEndian путает с HardwareEndian ) =)


beer.gif
Сознаюсь что ступил.
Диапазон адресов и правда будет 0x0010FF - 0x001000
В этом случае маску адресов не надо сдвигать на 12 бит.
Она должна быть 0x001000 | 0xFF т.е. равна максимальному адресу 0x0010FF
Всё остальное остаётся в силе - при наложении маски адрес автоматически закольцуется при превышении границы буффера.

топикстартеру
Может быть Вам стоит пересмотреть организацию буффера и сделать его по типу FIFO.
Тогда в этих извращениях не будет необходимости и подпрограмма считывания данных будет извлекать данные до опустошения буффера, а контролем перехода через границу буффера будет заниматься процедура извлечения байта/слова данных.
Go to the top of the page
 
+Quote Post
menzoda
сообщение Jun 5 2014, 15:17
Сообщение #18


Участник
*

Группа: Участник
Сообщений: 55
Регистрация: 13-09-12
Пользователь №: 73 530



Цитата(mempfis_ @ Jun 5 2014, 17:44) *
Тогда в этих извращениях не будет необходимости.

Да в них и так нет необходимости. Что все прицепились к этим маскам, выгоды никакой.
Go to the top of the page
 
+Quote Post
alexeyv
сообщение Jun 9 2014, 01:14
Сообщение #19


Местный
***

Группа: Участник
Сообщений: 298
Регистрация: 26-01-09
Из: Пермь
Пользователь №: 43 940



Цитата
Да в них и так нет необходимости. Что все прицепились к этим маскам, выгоды никакой.

Видать Вы не программировали микроконтроллеры.
Например, в обработчике прерывания необходимо выполнить работу как можно быстрее. Использование маски приводит к меньшему количеству кода и более быстрому выполнению.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jun 9 2014, 02:36
Сообщение #20


Гуру
******

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



Цитата(alexeyv @ Jun 9 2014, 08:24) *
Видать Вы не программировали микроконтроллеры.
Далеко не всегда даже в микроконтроллерах на счету каждый такт или байт. Зачастую сопровождаемый код или некратный степени двойки размер перевешивают.

Добавлено: знать такой прием, разумеется, полезно, но совать его везде "потому что микроконтроллер" абсолютно ни к чему.


--------------------
На любой вопрос даю любой ответ
"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
alexeyv
сообщение Jun 9 2014, 22:27
Сообщение #21


Местный
***

Группа: Участник
Сообщений: 298
Регистрация: 26-01-09
Из: Пермь
Пользователь №: 43 940



Цитата
но совать его везде "потому что микроконтроллер" абсолютно ни к чему.

Я не сую везде, и размеры буфера в основном степени двойки.
Конечно зависит от задачи, но программист должен представлять в какие инструкции, хотя бы примерно, будет компилироваться его код и к чему это приведет.
Обработка по маске - это всегда одинаковое постоянное время обработки данного участка кода. Длительность обработки по условию меняется в зависимости от ветки по которой пройдет исполнение.
Go to the top of the page
 
+Quote Post
menzoda
сообщение Jun 10 2014, 01:47
Сообщение #22


Участник
*

Группа: Участник
Сообщений: 55
Регистрация: 13-09-12
Пользователь №: 73 530



Как раз таки я прекрасно представляю, что будет в моем случае (ARM). В случае использования маски получиться одна инструкция AND, в случае использования условия мы получим CMP, IT и MOV, это если у нас Thumb2. Если же у нас ARM набор инструкций, то IT не будет. Выходит для распространенных МК на базе Cortex-M и ARM7 использование условия в худшем случае увеличит время исполнения на два такта, при этом время выполнения в обоих случаях будет постоянным. Так вот, какие бы оптимизации мы не пытались сделать, два такта - это НИЧТО. Они потонут в тактах, требуемых на вызов функции, на работу со стеком, на обращение к переменной в RAM. В конце-концов у нас тут не DSP, где пару тактов может и сделали бы погоду. Более простые МК на базе других архитектур могут сгенерировать на месте условия какой-нибудь условный переход. Да, в этом случае тактов будет больше, но опять же не настолько больше, чтобы на это обращать внимание.

Это называется переоптимизация. Я сам раньше грешил этим, но теперь отношусь к таким вещам попроще. В конце концов, если от увеличения времени исполнения участка кода всего на пару тактов программа перестает работать, или работает не правильно - то это явные архитектурные проблемы, означающие, что вы рассматриваете микробов через молоток. Нужны такты - есть всякие FPGA и DSP.

Go to the top of the page
 
+Quote Post
Genadi Zawidowsk...
сообщение Jun 12 2014, 20:37
Сообщение #23


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

Группа: Участник
Сообщений: 1 620
Регистрация: 22-06-07
Из: Санкт-Петербург, Россия
Пользователь №: 28 634



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

Недавно решал такую же проблему, только "заворот" указателя при использовании данных был недопустимым по потерям производительности.
В результате родился такой код с двойным размером буфера и дублированием данных - где всегда есть непрерывная область отсчётов.
Оптимизатор современных версий GCC очень качественно разворачивает такие конструкции.
Код
static float32_t filter_fir_rx_AUDIO(float32_t NewSample, int_fast8_t reset)
{
    enum { Ntap = Ntap_rx_AUDIO, NtapHalf = Ntap / 2 };
    float32_t v = 0.0f;            //output sample
    // буфер с сохраненными значениями сэмплов
    static float32_t x [Ntap * 2] = { 0.0f, }; // заставить расположить буфер в CCM
    static uint_fast16_t fir_stage = 0;

    if (reset != 0)
    {
        fir_stage = 0;
        memset(x, 0, sizeof x);
        return NewSample;
    }
    //shift the old samples
    fir_stage = (fir_stage == 0) ? (Ntap - 1) : (fir_stage - 1);
    //Calculate the new output
    x [fir_stage] = NewSample;
    x [fir_stage + Ntap] = NewSample;

    uint_fast16_t bh = fir_stage;            // Начало обрабатываемой части буфера
    uint_fast16_t bt = fir_stage + Ntap;    // Позиция за концом обрабатываемого буфера
    uint_fast16_t n = 0;
    while (n < NtapHalf)
    {    
        v += FIRCoef_rx_AUDIO [n ++] * (x [bh ++] + x [-- bt]);
    }
    // Выборка в середине буфера
    v += FIRCoef_rx_AUDIO [n] * x [bh];
    // Обеспечиваем масштабирование к ранее расчитанному усилению фильтра (1.0)
    return v * FIRScale_rx_AUDIO;
}


Сообщение отредактировал Genadi Zawidowski - Jun 12 2014, 20:43
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 26th July 2025 - 07:11
Рейтинг@Mail.ru


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