sigmaN 0 29 августа, 2016 Опубликовано 29 августа, 2016 · Жалоба 1) результат вычислений получается float, для вывода на ЦАП, естественно, преобразую его к int - теряется дробная часть, это нормально?Корректнее наверно тут использвоать округление вместо простого отбрасывания дробной части http://www.cplusplus.com/reference/cmath/ceil/ 2) Отрицательные значения. Я подаю на вход фильтра белый шум, 24-битный. Соответственно, после фильтра у меня тоже должно получаться 24-битный результат. Но! Отрицательные значения в процессоре - это инвертированное положительное число + 1. А для ЦАП отрицательное значение получается простой инверсией положительного числа.Что это за ЦАП то такой у вас? Прям с двухполярным питанием и честной выдачей наружу напряжения ниже нуля? Очень сомневаюсь. Регистр ЦАПа скорее всего беззнаковый от 0 до скольки там разрадность позволяет. А потому за 0 надобно принять половинку разрядности ЦАПа. Если он например 16ти разрядный, то за 0 надо принять половинку 2^16 / 2 = 32768 Таким образом получившиеся после фильтра циферки перед передачей в ЦАП надо приготовить. У вас будет еще одна задачка если в процессе цифровой обработки получились космические цифры, которые в диапазон ЦАПа(-32768 до +32767) не влазят. Что с этим делать это решать вам(зависит от задачи). Например можно организовать нормализацию https://ru.wikipedia.org/wiki/%D0%9D%D0%BE%...%83%D0%BA%D0%B0 или компрессию динамического диапазона https://ru.wikipedia.org/wiki/%D0%9A%D0%BE%...%B0%D0%BB%D0%B0 Хорошей идеей было бы на выходе тракте цифровой обработки сигнала сделать так, чтобы данные были представлены числами от -1 до 1. Т.е. нормализовать их. Тогда вы будете знать, что 1 это максимальный уровень, а -1 минимальный. "Вписать" такой сигнал в нужный диапазон значений можно будет простым умножением на константу. В общем потом, когда ваши данные так или иначе укладываются в диапазон ЦАПа(-32768 до +32767) применяете тот самый виртуальный 0. DAC_REGISTER = 32768 + filter_data; И не надо заморачиваться как там это будет посчитано и как в системе хранится отрицательное значение. Тестировать там какие-то биты в данном случае - дичайший говнокод. 3) Мне коэффициенты надо с компьютера передавать, а они у меня float теперь. Учитывая, что большинство машин сейчас уважают IEEE 754 стандарт ваш хак с вычленением байт конечно будет работать, но назвать этот подход правильным нельзя. Если делать правильно и портабельно, то в том числе передают даже в виде строки. sprintf() на стороне передатчика, sscanf() на стороне приемника :) Либо определяйтесь, что между компьютером и устройством коэффициенты передаются в формате с фиксированной точкой, чтобы всё было чётко определено и задокументировано. Еше стоит учесть, что бывают машины с разным порядком байт https://ru.wikipedia.org/wiki/%D0%9F%D0%BE%...%82%D0%BE%D0%B2 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dima1060 0 30 августа, 2016 Опубликовано 30 августа, 2016 · Жалоба Корректнее наверно тут использвоать округление вместо простого отбрасывания дробной части http://www.cplusplus.com/reference/cmath/ceil/ Нашел в интернете округление - просто прибавление 0.5 к float. Жалко с отрицательными не прокатит, там надо вычитать, снова if надо городить Что это за ЦАП то такой у вас? Прям с двухполярным питанием и честной выдачей наружу напряжения ниже нуля? Очень сомневаюсь. Регистр ЦАПа скорее всего беззнаковый от 0 до скольки там разрадность позволяет. А потому за 0 надобно принять половинку разрядности ЦАПа. Если он например 16ти разрядный, то за 0 надо принять половинку 2^16 / 2 = 32768 Таким образом получившиеся после фильтра циферки перед передачей в ЦАП надо приготовить. У вас будет еще одна задачка если в процессе цифровой обработки получились космические цифры, которые в диапазон ЦАПа(-32768 до +32767) не влазят. Что с этим делать это решать вам(зависит от задачи). Например можно организовать нормализацию https://ru.wikipedia.org/wiki/%D0%9D%D0%BE%...%83%D0%BA%D0%B0 или компрессию динамического диапазона https://ru.wikipedia.org/wiki/%D0%9A%D0%BE%...%B0%D0%BB%D0%B0 Хорошей идеей было бы на выходе тракте цифровой обработки сигнала сделать так, чтобы данные были представлены числами от -1 до 1. Т.е. нормализовать их. Тогда вы будете знать, что 1 это максимальный уровень, а -1 минимальный. "Вписать" такой сигнал в нужный диапазон значений можно будет простым умножением на константу. В общем потом, когда ваши данные так или иначе укладываются в диапазон ЦАПа(-32768 до +32767) применяете тот самый виртуальный 0. DAC_REGISTER = 32768 + filter_data; И не надо заморачиваться как там это будет посчитано и как в системе хранится отрицательное значение. Тестировать там какие-то биты в данном случае - дичайший говнокод. ЦАП - CS4344, пробовал на AD1852. Ни в том ни в другом даташите не нашел, как же представлять отрицательные числа. Но это как то должно наверно быть обозначено? Для AD1852 написал тестовую синусоиду, сначала я не парился, думал, что максимальное отрицательное значение - это 0х000000. Проверил - какая то фигулька получилась, а не синусоида. Потом вот просто начал инвертировать положительные значения - получилась синусоида, размах вроде как и должен быть. А для CS4344 я просто подал тот же массив - получилась синусоида, ну и хорошо. А вообще мне интересно, как обозначается в доке, каким способом кодируется отрицательные значения в ЦАП? Учитывая, что большинство машин сейчас уважают IEEE 754 стандарт ваш хак с вычленением байт конечно будет работать, но назвать этот подход правильным нельзя. Если делать правильно и портабельно, то в том числе передают даже в виде строки. sprintf() на стороне передатчика, sscanf() на стороне приемника :) Либо определяйтесь, что между компьютером и устройством коэффициенты передаются в формате с фиксированной точкой, чтобы всё было чётко определено и задокументировано. Еше стоит учесть, что бывают машины с разным порядком байт https://ru.wikipedia.org/wiki/%D0%9F%D0%BE%...%82%D0%BE%D0%B2 Да мне главное правильно собрать float из байтов на микроконтроллере. А разобрать его на компе - чисто для проверки. Хотя зачем, я могу даже сразу вручную разобрать все нужные float-ы на байты, на этом сайте http://floatingpoint.ru/online/dec2float.php Хранить и передавать в виде байт. Тем более коэффициенты у меня все уже вычислены. Наверно так будет наиболее надежно)) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sigmaN 0 30 августа, 2016 Опубликовано 30 августа, 2016 · Жалоба Нашел в интернете округление - просто прибавление 0.5 к float. Жалко с отрицательными не прокатит, там надо вычитать, снова if надо городить Именно так. А вообще мне интересно, как обозначается в доке, каким способом кодируется отрицательные значения в ЦАП? Ну какие могут быть отрицательные значения при однополярном питании? В принципе я вам направление для мысли дал. Разбирайтесь.... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ig_z 0 30 августа, 2016 Опубликовано 30 августа, 2016 · Жалоба Ну какие могут быть отрицательные значения при однополярном питании? TC использует аудио цап ацп. Сейчас они все двуполярные по коду и однополярные по питанию. В ацп даже цифровой фильтр на несколько гц встраивают, чтобы фильтровать смещение нуля (аналоговое, как я понимаю). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sigmaN 0 30 августа, 2016 Опубликовано 30 августа, 2016 · Жалоба Не знал, не знал. Ну тогда даташит на ЦАП в помощь ТСу )))) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dima1060 0 30 августа, 2016 Опубликовано 30 августа, 2016 · Жалоба Вот я смотрю даташиты на оба ЦАП и не нахожу даже упоминания про то какие данные отправлять и как кодируется отрицательный диапазон... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dima1060 0 31 августа, 2016 Опубликовано 31 августа, 2016 · Жалоба Нашел ответ на свой вопрос The AD1852 accepts serial audio data in MSB first, twos-complement format. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sigmaN 0 1 сентября, 2016 Опубликовано 1 сентября, 2016 · Жалоба Ну вот, значит отрицательные числа представлены так-же как и в процессоре осталось только разобраться с MSB first... B в MSB имеется ввиду Bit или Byte? если Byte то получается Big Endian, а проц у вас Little endian.... https://ru.wikipedia.org/wiki/%D0%9F%D0%BE%...%82%D0%BE%D0%B2 Может быть поэтому во время эксперимента у вас не получалась синусоида.... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ig_z 0 1 сентября, 2016 Опубликовано 1 сентября, 2016 · Жалоба если Byte то получается Big Endian, а проц у вас Little endian.... Это забота аппаратного аудио интерфейса в процессоре, если ТС его использует. Более вероятна проблема выбора 32 бит данных через 16 бит порты в некоторых "оптимизированных" платформах Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dima1060 0 5 сентября, 2016 Опубликовано 5 сентября, 2016 · Жалоба Сделал полосовые фильтры, проверил - все нормально. А с режекторным какая то засада, не понимаю, где может быть ошибка? Делаю вот так: struct { float a0; float a1; float a2; float b1; float b2; int k; int k1; int k2; float X[4]; float Y[4]; int Y1; } NotchedFilter; в прерывании I2S //выдаю данные hsai_BlockA1.Instance->DR = noise.NotchedFilter.Y1; hsai_BlockA1.Instance->DR = noise.NotchedFilter.Y1; //считаю следующий отсчет // noise.NotchedFilter.Y[noise.NotchedFilter.k] = noise.NotchedFilter.a2*noise.NotchedFilter.X[noise.NotchedFilter.k2] + // noise.NotchedFilter.a1*noise.NotchedFilter.X[noise.NotchedFilter.k1] + noise.NotchedFilter.a0*noise.NotchedFilter.X[noise.NotchedFilter.k] - // noise.NotchedFilter.b1*noise.NotchedFilter.Y[noise.NotchedFilter.k1] - noise.NotchedFilter.b2*noise.NotchedFilter.Y[noise.NotchedFilter.k2]; noise.NotchedFilter.Y[noise.NotchedFilter.k] = noise.NotchedFilter.a2*(noise.NotchedFilter.X[noise.NotchedFilter.k2] + noise.NotchedFilter.X[noise.NotchedFilter.k]) + noise.NotchedFilter.a1*(noise.NotchedFilter.X[noise.NotchedFilter.k1] - noise.NotchedFilter.Y[noise.NotchedFilter.k1]) - noise.NotchedFilter.b2*noise.NotchedFilter.Y[noise.NotchedFilter.k2]; noise.NotchedFilter.Y1 = noise.NotchedFilter.Y[noise.NotchedFilter.k];//оптимизировал а0=а2, а1=b1 noise.NotchedFilter.k = (noise.NotchedFilter.k + 1)&BUFFMASK; noise.NotchedFilter.k1 = (noise.NotchedFilter.k - 1)&BUFFMASK;//посчитали индекс Xk-1 noise.NotchedFilter.k2 = (noise.NotchedFilter.k - 2)&BUFFMASK;//посчитали индекс Xk-2 что тут может быть не так? проверил под отладкой - k меняется как и должно, сам посчитал один отсчет - сошлось с показанием процессора. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dima1060 0 6 сентября, 2016 Опубликовано 6 сентября, 2016 · Жалоба Как то так получается, что при подаче на вход режекторного фильтра 24-битного числа, на выходе получается зашкал. Все нормально фильтрует, если подавать на вход 22-битное число или сдвигать на 2 результат. Может кто-нибудь подсказать, как такое может получиться? В матлабе у фильтра никакого усиления нет. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться