Комментарии 71
голосую за вариант: замерить коэффициент нелинейных искажений и сигнал/шум у сего устройства
У какого из них? Первый вариант с i2s очень качественный. Второй вариант все рано нуждается в доработке схемотехники. В теории он весьма и весьма неплох. Да и на практике звучит у меня лучше чем встроенная в лаптопе карточка. Немного шумит за счёт плохой развязки питания, но это решаемый вопрос.
очень качественный
а как это оценить без измерений-то?
звучит у меня лучше чем встроенная в лаптопе карточка
даже PCM270x без внешнего цапа звучит лучше, чем встроенная
Измерений чего ? Откройте документацию на чип https://www.ti.com/lit/ds/symlink/pcm5102.pdf
и посмотрите , у них все померяно... Я вполне доверяю этой компании. Дайте нормальное питание и Вы в дамках. Тут как раз все просто.
Вот с сигма дельтой , без внешнего ЦАПа, надо повозиться. Попробую сделать внешний повторитель со стабильным питанием, я специально вывел с таймеров комплементарные сигналы с STM - ки.
"Дайте нормальное питание и Вы в дамках. Тут как раз все просто."
Возможно, кому-нибудь пригодится мой опыт: В pcm5102 имеется встроенный генератор отрицательного напряжения и для него устанавливаются два конденсатора (между 2 capp(+) и 4 capm(-) ногой и 5 vneg(-) и землёй(+). В скобках указана полярность). Так вот, в даташите их ёмкость рекомендована 2.2мкф. Этого довольно мало, и при двух каналах с выходным сопротивлением 1 кОм образуется некий жутко не линейный ФНЧ 2-го порядка с частотой среза примерно 140 Гц. Так вот, я бы рекомендовал заменить оба конденсатора на 10 мкф x 16в и применить в данном случае специализированные электролиты (мой личный выбор ELNA Silmic). На слух будет на порядок лучше. Эти конденсаторы - самое слабое место данной микросхемы. Так я "патчил" китайские цапы.
Спасибо, интересно. Может чипы левые? :)
Они вроде пишут , что 1 ком это минимально допустимое сопротивление нагрузки. Видимо замеры они делали на 10 ком нагрузки.
Посмотреть бы в RightMark Audio Analyzer что получилось.
Для этого нужен качественный АЦП. У меня такого нет. Сам процесс я могу просимулировать в матлабе например и померить результаты. На самом деле можно даже учесть времена переключения выходных ключей на stm -ке но не вижу такой необходимости. Меня вполне устраивает качество звука.
А я и не совсем против, снимайте. Повторяю "Меня вполне устраивает качество звука." за $3. Звучит на $30, как минимум :)
А как вы в SPI выводите четыре уровня?
При выходной частоте 101кГц выходной ФНЧ уже не ставили?
На F401 вроде есть QSPI. Можно было бы на него R2R лестницу повесить и иметь 16 уровней. Ну, или с таймерами пошаманить или даже с FSMC, просто выводя семплы на шину памяти.
Впрочем, гнать 84Мгц наружу да еще на параллельную шину не очень хорошая идея
Обожаю когда люди создают что-то на стыке разных областей. Описанный вами случай - из этой серии.
И ещё... спасибо вам огромное за real engineering - очень интересно!
Сам хотел спаять платку расширения для малинки чтобы 5.1 звук слушать, но так и не добрался до этого.
Pulse-density modulation не знаю как точно по русски
Возможно... Широтно-импульсная модуляция.
Не-a ... ШИМ (широтно импульсная) это PWM ( pulse width modulation ), дословно. Это все таки другая модуляция, похожая, но другая.
Тогда переводим дословно - импульсно-плотностная модуляция. :)
Хмм. Не импортозамещается :(
Из словаря:
Telecoms (En-Ru)
pulse-density modulation
импульсно-плотностная модуляция (для смягчения цифрового звука после декодирования в CD-проигрывателе фирмы Harman/Cardon)
Число-импульсная?
Переведено с английского языка. — Пульсационная модуляция, или PDM, является формой модуляции, используемой для представления аналогового сигнала с двоичным сигналом. Википедия (Английский язык)
Почему в микроконтроллерах нет аппаратного модуля sigma delta модулятора подобно pwm?
Встречал решение, где два канала таймера в режиме 8-бит ШИМ управлялись каждый своим байтом двухбайтного отсчёта и их отфильтрованные выходные напряжения складывались в пропорции 1/256. По способу с СДМ - подход с СДМ применительно к МК, конечно, инновационный, но искомый однобитовый поток можно получить напрямую из компа, изменив дескриптор формата, так, чтобы комп понимал, что устройство от него хочет. В этом случае хост будет отправлять не отсчёты PCM, а нужный перекодированный сигнал. Только для него понадобится, скорее всего, usb hs (привет в сторону stm32f723)
Встречал решение, где два канала таймера в
При работающем USB каналы даже одного таймера иногда расползаются. Писал об этом здесь https://habr.com/ru/post/523836/
Впрочем может я чтото не так делал
Только для него понадобится, скорее всего, usb hs
Достаточно FS - 12 Mbps . 2.884Mbps*2 это всего 5.768Mbps .
В этом случае хост будет отправлять не отсчёты PCM, а нужный перекодированный сигнал.
А фиг его знает, будет или нет. PCM - все операционки умеют выдавать.
Кроме того stm32f401 отлично справляется с перекодированием PCM в модифицированный на 8-9 бит СДМ на 300 кГц, такой вот виртуальный АЦП :). Я немного переделал выдачу звука на открытый сток - смотрите схему. Помеха от питания ушла в ноль. Земля, в отличие от питания, внутри чипа тихая, на нее работающий по SPI дисплей почти не влияет. Сейчас вообще все отлично работает, только немного код еще почищу.
Если формат DSD over PCM - то, все же, во-первых, нужен UAC2 в дескрипторе , а во-вторых, USB HS на физике, т.к., по стандарту этого формата один байт из каждых трёх служит маркером формата и попеременно маркером канала в составе данных в этом формате. А в дескрипторе при этом оставляем PCM.
Реализую похожее на FPGA. Только у меня это будет сразу усилитель D класса. Сильный упор на качество не делаю, но постараюсь сделать как можно качественнее, на сколько хватит ресурсов.
Несущую выбрал 384кГц, на эту частоту больше выбора силовых ключей. При этой частоте, разрядность ШИМ получается равной 9 битам (модулятор при этом просит около 200мГц). Больше сделать проблематично, так как от FPGA EP2C5T144C8N можно получить стабильную работу на частотах не более 260мГц. Другой ПЛИСины у меня пока нет, обкатываюсь на этой. Модулятор работает хорошо как в тестбенчах, так и в железе.
Исходный сигнал - 24 бит, 48кГц. АЦП - PCM1802. Просто потому что нашел ее в виде модуля на Али. До 384кГц довожу оверсемплингом, построенном на самопальном КИХ фильтре на 128 коэффициентов. КИХ тоже работает хорошо. Может работать на тактовой до 60МГц, но его можно еще ускорить, если конвейеризовать некоторые узкие места (в самом умножителе и между его выходом и сумматором. Мне лень было всовывать регистры между ними). Но текущей его производительности хватает и так с головой на 50 МГц. Однако, вместо Дельта-Сигмы я решил попробовать нойзшейпинг. Он точно так же должен сместить шум квантования вправо по спектру.
Из текущих проблем, чтобы впервые запустить это дело и проверить:
Переделать I2S интерфейс. Я его делал первым, попутно осваивая Verilog и технологии FPGA. Потому там сплошная асинхронщина. На выходных реализую синхронный дизайн этого модуля.
Разобраться с расчетом фильтра в петле ОС нойзшейпера. Можно попробовать сделать третьего порядка и вручную поиграться с коэффициентами, чтобы по получившейся импульсной характеристике провести анализ и определиться с методикой расчетов.
Ваш вариант с "многобитной" дельта-сигмой тоже попробую.
Ваш вариант с "многобитной" дельта-сигмой тоже попробую.
Будут результаты, поделитесь пжл...
Сделал Ваш вариант. Играет в принципе нормально, но чем больше каскадов ставлю последовательно (увеличиваю порядок модулятора), тем громче становится фоновый шум. По идее, он должен был смещаться за пределы слышимого диапазона, но пока что-то идет не так. Может где-то напортачил. Привожу главный кусок реализации модулятора 3 порядка на Verilog
Hidden text
// Data lines
wire[23:0] leftQuantizer;
wire[23:0] rightQuantizer;
// Delta 0
wire[23:0] left_delta_0 = leftNsIn - leftQuantizer;
wire[23:0] right_delta_0 = rightNsIn - rightQuantizer;
// Sigma 0
reg[23:0] left_sigma_0 = 0;
reg[23:0] right_sigma_0 = 0;
always @(posedge clock or posedge reset) begin
if(reset == 1'b1) begin
left_sigma_0 <= 0;
right_sigma_0 <= 0;
end else begin
if(integr_enable == 1'b1) begin
left_sigma_0 <= left_sigma_0 + left_delta_0;
right_sigma_0 <= right_sigma_0 + right_delta_0;
end
end
end
// Delta 1
wire[23:0] left_delta_1 = left_sigma_0 - leftQuantizer;
wire[23:0] right_delta_1 = right_sigma_0 - rightQuantizer;
// Sigma 1
reg[23:0] left_sigma_1 = 0;
reg[23:0] right_sigma_1 = 0;
always @(posedge clock or posedge reset) begin
if(reset == 1'b1) begin
left_sigma_1 <= 0;
right_sigma_1 <= 0;
end else begin
if(integr1_enable == 1'b1) begin
left_sigma_1 <= left_sigma_1 + left_delta_1;
right_sigma_1 <= right_sigma_1 + right_delta_1;
end
end
end
// Delta 2
wire[23:0] left_delta_2 = left_sigma_1 - leftQuantizer;
wire[23:0] right_delta_2 = right_sigma_1 - rightQuantizer;
// Sigma 2
reg[23:0] left_sigma_2 = 0;
reg[23:0] right_sigma_2 = 0;
always @(posedge clock or posedge reset) begin
if(reset == 1'b1) begin
left_sigma_2 <= 0;
right_sigma_2 <= 0;
end else begin
if(integr2_enable == 1'b1) begin
left_sigma_2 <= left_sigma_2 + left_delta_2;
right_sigma_2 <= right_sigma_2 + right_delta_2;
end
end
end
assign leftQuantizer = {left_sigma_2[23:15], 15'd0};
assign rightQuantizer = {right_sigma_2[23:15], 15'd0};
Управляется просто:
По приходу фронта на вход "data_valid", пришедшая выборка из апсемплера фиксируется во входных регистрах (в коде не приведены) leftNsIn и rightNsIn. Далее простая машина состояний по очереди раздает импульсы разрешения интеграторам, начиная с нулевого интегратора и заканчивая последним. После фиксирует результат в выходных регистрах.
Интересный проект. Я не специалист, но мне кажется, что с многобитной дельта-сигма модуляцией
компромисс между частотой отсчетов и количеством дискретных уровней
однозначно решается в пользу дискретных уровней. Потому что, при постоянном битрейте, уменьшая частоту линейно (в N раз), мы увеличиваем разрешение сигнала экспоненциально (в 2^N раз). Выходит, что при наличии у МК N свободных выводов можно снизить частоту дискретизации в 2^N/N раз и с помощью R-2R схемы получить сигнал того же качества.
У него (stm32f401) нет DMA на паралельный порт. Поэтому ничего не выйдет. В остальном Вы тоже не правы,
однозначно решается в пользу дискретных уровней
Это не так .Однозначно в пользу частоты семплирования. Почитайте документ от Analog Devices по ссылке в конце статьи , там все есть, про профиль шума.
Допустим что частота таимера F . Количество уровней N . Тогда частота отсчетов K=F/N.
Обьем передаваемой информации V = K*log2(N) . Подставляем V = F*log2(N)/N. Чем меньше N тем больше результат.
Спасибо за замечание. Просто возникла мысль, что с помощью того же количества бит можно передать больше информации, если биты будут иметь разные веса (равные степеням двойки). Если бы у МК был быстрый и дешёвый способ выводить 8-битное число в параллельный порт 328125 раз в секунду, то мы получили бы сигнал, аналогичный 1-битному на 84 МГц. Другое дело, что на данном МК делать прерывание с такой частотой не рационально.
Ну а при равных весах бит действительно верна формула:
Обьем передаваемой информации V = K*log2(N)
DMA на GPIO? Запрашивает таймер, адрес данных - в памяти, адрес периферии - gpiox->dr, копируется байт или слово двухбайтное.
Да ,я видел Application note AN4666, но на младших (f103) у меня не заработало.Не помню уже что за проблемы были, но не получилось. Впрочем я особо и не упирался.
В любом случае, предложенный мной способ для звука и лучше и тише , чем городить ЦАП руками на резисторах. Как минимум интереснее. А если мне нужен особо высококачественный ЦАП - то я его просто куплю
Есть занимательная appnote от ST на эту тему, cвою реализацию выложил тут:
Спасибо, посмотрю.
Жалко я не видел раньше этот апноте. Это тоже самое. Немного разные реализация собственно фильтра, у Вас с ST и у меня, но да это тоже самое. Я ведь написал , что изобрел велосипед, ничего нового...
К Вашему коду на гитхабе. Наушники надо развязывать через конденсатор, иначе будет плохо... Во первых постоянный ток через них шумит, а во вторых смещение добавляет нелинейных искажений
С h bridge я экспериментировал, так себе звук выходит.
у меня как раз h-bridge c выпотрошенными прошловековыми 'компьютерными' колонками в качестве нагрузки -- вполне приемлемо.
возможно, длительность deadtime была недостаточной.
А из чего можно сделать 8.1 звук на usb? использовал в свое время 5.2 наушники usb. Очень нравились. Фильмы HD на них отличались от стерео в заметно лучшую сторону. Разница в ощущениях у меня была такая же как при переходе от моно к стерео.
Я предполагаю, что любой процессинг на оба уха проще (и качественнее) делать на компьютере сотвествующим драйвером на лету. Просто поищите специальный драйвер, не знаю как под виндами, но на линуксе вклеить свой обработчик без проблем (вроде) . По идее - это смешивание каналов и свертка с некоторой специальной последовательностью (немного эха и тд) На этой стм-ке это весьма проблематично , она и так перегружена, можно добавить только несложный процессинг, вроде регулировки глубины стереоэффекта смешиванием сигнала каналов в фазе или противофазе. Или нужна стм-ка побыстрее(stm32f407 или stm32f7х ). Или добавить специальный чип вроде PT2387. Правда сильно подозреваю что он делает именно "регулировку глубины стереоэффекта смешиванием" , что можно легко делать и на стм
У меня были не предобработка звука, как делают многие производители. Я разбирал наушники, в каждом были честные 4 динамика, отдельно подключающиеся к микросхеме. Звук был честным 5.2 (в каждом ухе по отдельному динамику для низких частот). В винде определялись как звуковая плата с соответствующим выбором подключений. На мат.платах компьютеров звуковая микросхема подключается к USB или хитро как нить к чипсету? Мысли вырезать ножовкой кусок от старой мамки, восстановить питание и подключить. Имеет ли смысл вот в чем вопрос?
Что характерно есть похожая старая идея где вместо SPI как быстрый однобитовый ЦАП используется выход данных I2S - NoDAC. Тоже сдвигвый регистр но длиннее.
Код дельта-сигма кодирования битов на лету на удивление эффективен на ESP.
Ну я как бы таймеры в режиме PWM использую. Померил тут недавно, получил -82 dB и 0.07% искажений. На ESP так не получится, слишком шумная шина.
Вот они все по сути шумные, особенно если не обращать внимания на землю и развязывающие конденсаторы :) Да и кому в голову придёт питать выход от шумной линии.
82 дБ для PWM очень неплохо. Любопытно было бы взглянуть на данные по шуму и спектру 1 кГц синуса. Есть картинки?
Я их снес давно. Выложу на github когда найду(если) или перемерю. В той схеме , что на github-е искажения большие (около 2%) когда нагружены на наушники, за счет ассиметриии зарял-разряд , но не противные , так как четные. И для корректного измерения довольно много обвязки нужно, я ее собираю на макетке и потом разбираю.
Напрямую на пин ? Разве что если наушники высокоомные.
Всеже с буфером повеселее будет: https://github.com/earlephilhower/ESP8266Audio/issues/562
“Сигма дельта” или как сделать хорошую звуковую карту из STM32F401