Simple Sound Player: аудио -вывод ШИМ, с DMA, без прерывания таймера

Стивестронг
Солнце 29 октября 2017 г. 9:20 утра
У меня есть проект, в котором мне нужен некоторые короткие звуковые эффекты, не читая файлы wav с SD -карты.

Для вывода звука ШИМ текущие решения используют Timer Interrupt для обновления нового значения в реестре вывода Compare.
В этой версии используется DMA (канал 7), запускаемое событием Timer (4), чтобы сделать то же самое, поэтому у процессора есть достаточно времени для выполнения других задач.
Спикер на PB6 (таймер 4 Ch 1).
Прерывания не используются, хотя можно использовать конец передачи DMA, чтобы сделать что -то.

РЕДАКТИРОВАТЬ: - Я добавил возможность использовать прерывание DMA. Для этого просто включить определение в строке 10.

В этом примере используется полконочный файл WAV (преобразован в C -код) с 8 -битным разрешением, скоростью отбора проб 16 кГц, хранящейся во флэш -ной (~ 8 КБ данных).
Прескалер и регистры предварительной нагрузки таймера оптимизированы, чтобы максимально взглянуть на выходной сигнал для получения 0-255.

Веселиться.

Необходимы патчи:
https: // github.com/rogerclarkmelbourne/ ... 2/тяга/366
https: // github.com/rogerclarkmelbourne/ ... 2/тяга/367

[Викторина: что говорит звук?]

Rogerclark
Солнце 29 октября 2017 г. 9:57 вечера
Спасибо, Стив...

Это работает на F103?

Стивестронг
Солнце 29 октября 2017 г. 22:21
Да, он работает на синей таблетке.
Это может быть адаптировано и для F4, часть DMA требует некоторых изменений для этого.

Rogerclark
Пн 30 октября 2017 г. 12:33
Спасибо

Я попробую, когда получу свободное время

Chismicro
Пн 30 октября 2017 г. 15:04
Некоторое время назад я также сделал какой -то звукорепет. для STM32F103 в универсальном репо.
У него нет DMA, но качество звука было в порядке.
Это всего лишь синусоидальная волна, но может быть легко расширить для игры в WAV.

Стивестронг
Пн 30 октября 2017 г. 15:11
Да, я это видел, а также примеры Delta-Sigma Bluepill.
Однако по этим примерам я до сих пор не понимаю, как вы преобразуете частоту выборки в Bit Toptourtent.
Это очень помогло бы, если бы вы могли сделать хотя бы ручной написанной схемой принципа работы (не для чистой дельта-сигмы, а всей концепции).

В любом случае, основной момент здесь в том, что мой пример делает НЕТ Используйте таймер ISR, только DMA. ;)

Chismicro
Пн 30 октября 2017 г. 15:53
В любом случае, главное здесь заключается в том, что мой пример не использует таймер ISR, только DMA. Да, это хорошая идея использовать DMA, чтобы избежать обработки нагрузки.
Если бы он был доступен ранее, я бы использовал ваш пример ;-)

Стивестронг
Пн 30 октября 2017 г. 16:17
У меня были еще несколько мыслей об этом.

Уровень аудиосигнала, заданный значением выборки WAV, на самом деле является циклом Duty Pwm.
Теперь желательно переместить базовую частоту ШИМ из отбора проб в верхнюю частоту, чтобы избежать нарушения частоты ШИМ на аудио.
Вот почему хорошие ЦАП ШИМ используют частоты 140 кГц и выше.

Я думаю, что мы могли бы сделать тот же трюк, по крайней мере, для 8 -битных сигналов разрешения, используя SPI.
Вывод массива из 8 x 32 -битных слов (= 256 бит) с высокой тактовой частотой мы могли бы моделировать тот же рабочий цикл аудиосигнала.
При каждом тикаре частоты звука мы просто должны обновить значения массива соответственно до требуемого рабочего цикла.
Используя SPI1 с часами 36 МГц, мы могли бы достичь 36 МГц / 256 = 140.Базовая частота базовой частоты 625 кГц для 8 -битного разрешения.

Я попробую это.

Chismicro
Пн 30 октября 2017 г., 17:57
Я думаю, что ухо не слышит частоты выше 20 кГц. Поэтому частоты ШИМ выше 20 кГц всегда достаточно.
У этого могут быть и другие причины, когда они используют 140 кГц в аудио-DACS ШИМ.
Но что действительно важно: резолюция. Чем больше битов, тем лучше.

В Библиотека Моззи Чтобы увеличить разрешение ЦАП.
Можете ли вы записать результаты ваших различных реализаций DAC и разместить их где -нибудь?

Стивестронг
Пн 30 октября 2017 г. 18:25
Причиной увеличения частоты ШИМ является уменьшение искажений, см.: http: // www.OpenMusicLabs.com/Learning/D ... Цем.1.HTML, Глава 4. Итак, если у вас есть носитель 30 кГц, и вы создаете тон 5 кГц, у вас будут сигналы на 30 кГц +/- 5 кГц, 10 кГц, 15 кГц и т. Д.

Chismicro
Вт 31 октября 2017 г. 6:55 утра
Причиной увеличения частоты ШИМ является уменьшение искажений, см.: http: // www.OpenMusicLabs.com/Learning/D ... Цем.1.HTML, глава 4. Это действительно лучшая ссылка, которую я когда -либо видел по этой теме. Спасибо .

Даже Блюпилл упоминается. : D

Rogerclark
Вт 31 октября 2017 г. 9:09
Стив

Я запустил ваши патчи вручную, чтобы они оба произошли в одном и том же коммите

https: // github.com/rogerclarkmelbourne/ ... B6315FED04

Стивестронг
Вт 31 октября 2017 г. 9:12
ОК, спасибо.

Тем временем мне удалось генерировать сигнал ШИМ 70 кГц с использованием MOSI (SPI2), но в настоящее время в сигнале иногда есть сбой, я пытаюсь выяснить, откуда он исходит. В теории этого не должно быть там : mrgreen:

Rogerclark
Вт 31 октября 2017 г. 9:18 утра
прохладный

victor_pv
Вт 31 октября 2017 г. 20:36
Как примечание, на F1 я занимался 8 -битным разрешением, а ШИМ работал на максимуме около 132 кГц (3 x 44.1), и не слышат никакого шума, и добавление фильтра RC не изменил звук вообще.
Я также использовал DMA, вызванный таймером в моей последней версии, и использование DMA ISR для перезагрузки буфера из SDCAR Все, что я думаю, потребовалось менее 20% процессора для чтения файла и переформатирования образцов (2 канала, 8 бит, из какого -либо формата в файле), в F1 при 72 МГц.

Я вижу основное различие в том, что вы делаете, заключается в том, что вы используете класс Hardwaretimer, и после нескольких ревизий я решил пропустить его и просто использовать функции таймера Libmaple, и что я вижу повторяющийся счетчик, чтобы получить 3 -кратную частоту. Вы должны посмотреть на это, это функция в режиме Timer DMA, в котором вместо того, чтобы отправлять запрос DMA каждый раз, когда перезагружается таймер, вы можете устанавливать ряд повторений.
Таким образом, поскольку вы используете только 8 бит разрешения, как и я, вы можете запустить таймер намного быстрее, но использовать значение повторения для вывода одной и той же образца n раз. При 16 кГц, с базовой частотой 72 МГц, вы можете запустить таймер 17.В 5 раз быстрее и до сих пор получают 8 бит разрешения в ШИМ:
(72000000 /16000) / 17.5 = 257.1
Вы должны использовать целые числа в значении повторения, чтобы вы могли установить его на 18, 17 или другие значения и вычислить значение максимальной амплитуды, которое вы можете использовать (250 Arr в 18 повторениях). Я думаю, ты понял идею.

Стивестронг
Ср. 01 ноября 2017 г. 8:57 утра
Виктор, действительно, кажется хорошей идеей использовать функцию передачи DMA Burst Timers.
Я читал об этом, но не мог себе представить, что это хорошо для. Теперь это имеет смысл ;)

Если я установите Прескалер только на коэффициент того, что установлено сейчас (в основном делясь на целое число), я могу умножить частоту ШИМ, сохраняя разрешение. Умный.

Я стараюсь использовать как можно больше функций, потому что кажется, что они предлагают широкий масштаб возможностей настройки.
Теперь, когда Роджер включил DMA включить/отключить функции, он стал еще более мощным.

Моя процедура настройки таймера выглядит так: void TIMER_Setup() { pinMode(SPEAKER_PIN, PWM); // activate output timer.pause(); // try to set the reload register to a value as close as possible to 256 // to get full range audio 0 - 3.3V for 0 - 255 PWM values (8 bit resolution) uint32_t prescaler = F_CPU/SAMPLING_RATE_HZ/256; timer.setPrescaleFactor(prescaler); uint32_t overflow = F_CPU/SAMPLING_RATE_HZ/prescaler; timer.setOverflow(overflow); timer.enableDMA(0); // for update event use channel 0 }

Rogerclark
Ср. 01 ноября 2017 г. 9:21
Стив

Я попробовал код, и я слышу что -то, исходящее от динамика, который я прикрепил через конденсатор 100NF, но это очень тихо, и смотреть на мой логический анализатор, форма волны - это не то, что я ожидал.

Я вижу квадратную волну 16 кГц, и на падающем краю каждой половины цикла я вижу всплеск более высоких частотных квадратных волн при 50 МГц !

Поэтому я отключил динамик, и я вижу что -то другое, так что, похоже, просто подключение через конденсатор к динамику - не очень хорошая идея

Что вы подключились к PIN -колонну ?

эн.глин. Используете ли вы фильтр RC и подключаетесь к усилителю ?

Стивестронг
Ср. 01 ноября 2017 г. 9:45 утра
В настоящее время у меня есть простой пьезо -зуммер (без электроники) подключен.
Да, звук относительно тихий, хотя аудио волна имеет амплитуду на 90%.
Но я не могу объяснить шипы на падении краев, это, вероятно, связано с использованием динамика с конденсатором.
Я бы порекомендовал использовать динамик либо напрямую (для динамиков с 8 или более), либо последовательно с резистором.
Я также положил фильтр RC для ввода небольшого усилителя, но, поскольку у меня нет динамика, я не могу его использовать. Но аудиосигнал после RC (2K2 & 150NF) очень гладко.

Rogerclark
Ср. 01 ноября 2017 г. 10:00 утра
Я только что попробовал небольшой усилитель через горшок 5K и конденсатор, но я просто получаю серию кликов

Попробую завтра пьезо

Стивестронг
Ср. 01 ноября 2017 г. 10:29
Виктор,
Как я понимаю, я понимаю, передача TEAR TIMER DMA не может быть использована для повторного вывода одного и того же значения в тот же реестр таймера, но для отправки всплеска значений в определенное количество последовательных реестр таймера.
Поэтому, если я хочу обновить CCR1 и CCR2 в той же передаче DMA, то я могу установить длину взрыва на 2, а затем я могу иметь стерео -сигнал ШИМ на выходе CC1 и CC2, где образцы читаются в одном выстреле (взрыв) на DMA из последовательных мест памяти.

Я думаю, что единственный способ многократно отправлять такое же значение в CCR1 - это умножить его на программное обеспечение. Установите размер буфера DMA на (скажем,) 17 и заполните его тем же значением выборки, запускаемое таймером, установленным 17x частота образца (Ex. 16 кГц*17). Этот буфер DMA должен быть обновлен с новым значением выборки в следующий период выборки (Ex. 16 кГц).
Или, может быть, используя только 4 -кратный множитель, преобразовать линейный буфер
Abcde...
к
AAAABBBBCCCCDDDDDEEEE...
Это то, что вы сделали (с 3 -кратным множителем)?

Или я полностью неправильно понял?

victor_pv
Ср. 01 ноября 2017 г. 13:14
Это другая особенность, чем взрыв.
Во время взрыва вы можете обновить несколько регистров таймера одновременно, потому что таймер будет генерировать несколько запросов DMA вместо одного.
Функция повторения больше похожа на противоположность (хотя оба можно использовать вместе), таймер достигнет значения перезагрузки несколько раз, если он генерирует один запрос.
Это так:

Содержание памяти:
Abcde

Действия таймера (если установлено, например, для 3 повторений):
Таймер генерирует DMA для загрузки первого значения "A".
Таймер считается до «А», не генерирует запрос DMA и снова начинает считать
Таймер считается до «А» во второй раз, не генерирует запрос DMA и снова начинает считать.
Таймер считается до «А» в течение периода времени, теперь генерирует запросы DMA для загрузки «B»
Таймер считается до «B», аналогично 3 раза, и только в третьем генерирует событие DMA и загружает «C»
Таймер считается до «C» 3 раза, а на третьем выпуске DMA загружается "D"
...
Все это время, когда происходит сравнение событий таймер, так что вы получаете свой сигнал ШИМ с вашим рабочим циклом, приведенным к значениям, но вы получаете его 3 раза, прежде чем он загрузит следующий.

Эффект заключается в том, что вы можете установить ARR, который производит в 3 раза вашу частоту) 3 - это просто пример, IR все зависит от того, какая частота и сколько бит или разрешения вы хотите использовать для PWM). Частота составляла 16 кГц в примере, вы можете настроить ARR на получение частоты 48 кГц, поэтому тот же импульс ШИМ будет создан 3 раза, а затем загрузите следующее значение и создайте импульс 3 раза. Обязанность ШИМ - это желание, которое вы хотели, поскольку это связь между ARR и сравнением таймера, но частота в 3 раза выше, поэтому ваш шум сконцентрирован на гораздо более высокой частоте и проще в фильтровании.

В таблице DataShet объясняется это лучше меня, извините, я не слишком хорош в объяснении этого. Раздел называется «счетчик повторения» в справочном руководстве. Это раздел 14.3.3, страница 305.

РЕДАКТИРОВАТЬ: Для справки, это мой старый код, прежде чем добавить материал DMA, но он использует тот же регистр повторения (RCR)
Здесь рассчитывается значение (выше, чем для нескольких нормальных частот, но может быть рассчитано на лету с теми же результатами, и оно делает для необычных частот):
https: // github.com/vicopropv/arduino_stm ... #L339-L344
Здесь установлено значение:
https: // github.com/vicopropv/arduino_stm ... см.CPP#L94

Я надеюсь, что формула для расчета его, и справочное руководство облегчит понимание, мой код довольно неприятен, особенно этот файл.

Стивестронг
Ср. 01 ноября 2017 г. 13:54
Ах, спасибо, я понял о «счетчике повторения».
Я не мог найти его, потому что я искал таймеры общего назначения, у них нет этой функции, только у продвинутых (TIM1 и 8).
Это означает, что вы ограничены Timer1, сравнивая выводы канала (и переигрывающие). Но это не так важно.

Rogerclark
Ср. 01 ноября 2017 г., 19:55
Стив

Можете ли вы кратко объяснить, как опубликованный вами код, должен работать ?

От просмотра кода OU, я думаю, что вы используете DMA для управления таймером PWM.
DMA отправляет значения из массива (которые являются данными из файла WAV)

Это, по -видимому, меняет пропорцию ШИМ.

Однако я, кажется, не получаю результат.

Если я подключу наушники с 16 Ом (ушной зал) через резистор 330 Ом, я могу услышать что -то вроде слова «Привет», но когда я смотрю на штифт с помощью логического анализатора, я вижу очень форму волны, где Падающий Edige из -за выходного шарика, по -видимому, имеет импульс квадратных волн 50 МГц.
Я думаю, что это должно быть звон, вызванное индуктивностью говорящего.

Другая вещь, которую я заметил, это то, что значения в массиве WAV, похоже, не имеют очень широкого диапазона.
Они 8 -битные, 16 или 32 -битные значения ?

Я изначально думал, что это 8 бит, но мне нужно сделать чек, так как они могут быть 16 битами.

Стивестронг
Ср. 01 ноября 2017 г., 19:59
Это 8 -битные значения.
И поздравляю, вы решили тест :) , это действительно сказанное Hello Word.

Событие обновления Timer 4 запускает DMA, который записывает значения выборки WAV в регистр CCR1. Вот и все.

Rogerclark
Ср. 01 ноября 2017 г., 8:01 вечера
Вы нормализовали файл wav, чтобы получить максимальный диапазон 8 -битных значений?

Стивестронг
Ср. 01 ноября 2017 г. 20:05
Нет. Я был доволен оригинальной амплитудой, которая имела 80%.

Rogerclark
Ср. 01 ноября 2017 г. 20:08
ХОРОШО

Я сделаю еще несколько тестов.

Rogerclark
Ср. 01 ноября 2017 г. 20:16
КСТАТИ.

Таблица синуса в коде все еще работает?


Я пытался включить это, но не получил тон

Редактировать.

Синусоидальная таблица просто немного нажимает

Я не думаю, что для меня все работает так же, как и для вас :-(

Я прикреплю свой логический анализатор и посмотрю на PWM PIN PB6

Редактировать 2.

Я обнаружил, что мой пьезо был немного неисправным. Я попытался просто использовать DigitalWrite, чтобы сделать тон, и он не очень хорошо работал.

Я нашел свободное соединение внутри пьезо и работает немного лучше, но я думаю, что мне может потребоваться подключить пьезо между VCC и PB6, а не на земле и PB6, так как это может остановить щелчок.


Однако я думаю, что прямая связь между выборкой данных WAV и ШИМ не идеальна, так как ей нужно много образцов, чтобы получить хороший аудио. Вероятно, 48 кГц или выше будет лучше.



КСТАТИ.

Вы использовали это для создания данных

http: // ccgi.CJSEYMOUR.плюс.com/wavtocode/wavtocode.htm

Стивестронг
Ср. 01 ноября 2017 г., 21:14
Таблица синуса должна работать, но его длина действительно короткая, больше, чем щелчок не сердечный. Но это можно увидеть с помощью прицела ;)

Другой щелчок связан с уровнем уровня звука внезапным прыжком от устойчивого (низкого или высокого) до среднего уровня, когда он начинает играть.
Этого можно избежать, исчез.

Да, это конвертер. Но между тем я думаю, что это можно сгенерировать с помощью HXD (hex editor), открыть файл и сохранить как код.

Аудио имеет более высокое качество мыши при выборке с 48 кГц. Но это был быстрый тест для проверки качества коротких образцов, которые должны вписаться в Flash.

Редактировать
Параллельно я оцениваю функции тона, вы, вероятно, наблюдали, когда я толкнул PR. Но это другая история.

Rogerclark
Ср. 01 ноября 2017 г. 11:48
Привет, Стив

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

Одна вещь, которую я заметил с тоном, что он не работал на булавке, который вы используете, я.E PB6

Я не уверен, почему это.

Я думаю, что в идеале библиотека тон должна работать над всеми булавками, даже если мы должны сделать ее блокировкой, но это другое дело.

tone (), notone ()