Оглавление:

Синтезатор лазерной арфы на Zybo Board: 10 шагов (с изображениями)
Синтезатор лазерной арфы на Zybo Board: 10 шагов (с изображениями)

Видео: Синтезатор лазерной арфы на Zybo Board: 10 шагов (с изображениями)

Видео: Синтезатор лазерной арфы на Zybo Board: 10 шагов (с изображениями)
Видео: Laserharp II Jean Michel Jarre 2024, Июль
Anonim
Синтезатор лазерной арфы на Zybo Board
Синтезатор лазерной арфы на Zybo Board

В этом уроке мы создадим полностью функциональную лазерную арфу с использованием ИК-датчиков с последовательным интерфейсом, что позволит пользователю изменять настройку и тон инструмента. Эта арфа станет римейком старинного инструмента 21 века. Система была создана с использованием платы разработки Xilinx Zybo вместе с Vivado Design Suites. Что вам понадобится для реализации проекта:

  • 12 ИК-датчиков и излучателей (можно использовать больше или меньше в зависимости от количества струн)
  • Плата для разработки Zybo Zynq-7000
  • Бесплатная ОСРВ
  • Дизайнерский люкс Vivado
  • Провод (для подключения датчиков к плате)
  • 3 куска трубы из ПВХ ((2) 18 дюймов и (1) 8 дюймов)
  • 2 отвода из ПВХ

Шаг 1. Получите демо-версию Zybo DMA Audio от Digilent

Часть этого проекта, связанная с FPGA, в основном основана на демонстрационном проекте, который можно найти здесь. Он использует прямой доступ к памяти для отправки данных непосредственно из памяти, в которую процессор может записывать через поток AXI в аудиоблок I2S. Следующие шаги помогут вам запустить и запустить демонстрационный аудиопроект DMA:

  1. Может потребоваться новая версия файла платы для платы Zybo. Следуйте этим инструкциям, чтобы получить новые файлы досок для Vivado.
  2. Выполните шаги 1 и 2 в инструкциях на этой странице, чтобы открыть демонстрационный проект в Vivado. Используйте метод Vivado, а не аппаратную передачу SDK.
  3. Вы можете получить сообщение о том, что некоторые из ваших IP-блоков должны быть обновлены. Если это так, выберите «Показать статус IP», а затем на вкладке «Статус IP» выберите все устаревшие IP-адреса и нажмите «Обновить выбранные». Когда он закончится и появится окно с вопросом, хотите ли вы создать выходной продукт, нажмите «Создать». Если вы получили критическое предупреждающее сообщение, игнорируйте его.
  4. Переключитесь с дизайна на вкладку источников в Vivado, чтобы увидеть исходные файлы. Щелкните правой кнопкой мыши дизайн блока «design_1» и выберите «Create HDL Wrapper». При появлении запроса выберите «скопировать созданную оболочку, чтобы пользователь мог редактировать». Будет сгенерирован файл-оболочка для проекта.
  5. Теперь, когда те критические шаги, которые почему-то были упущены в другом руководстве, выполнены, вы можете вернуться к ранее связанному руководству и продолжить с шага 4 до конца и убедиться, что демонстрационный проект работает правильно. Если у вас нет возможности ввести звук для записи, просто сделайте запись в наушниках и слушайте 5-10 секундный нечеткий звук, когда вы нажимаете кнопку воспроизведения. Если при нажатии кнопки воспроизведения что-то выходит из разъема для наушников, вероятно, он работает правильно.

Шаг 2. Внесите некоторые изменения в Vivado

Внесите некоторые изменения в Vivado
Внесите некоторые изменения в Vivado

Итак, теперь у вас работает демонстрация звука DMA от Digilent, но это еще не конечная цель. Поэтому нам нужно вернуться к Vivado и внести некоторые изменения, чтобы наши датчики можно было подключить к заголовкам PMOD, и мы могли использовать их значение на стороне программного обеспечения.

  1. Откройте блок-схему в Vivado.
  2. Создайте блок GPIO, щелкнув правой кнопкой мыши в пустом месте на блок-диаграмме и выбрав «Добавить IP» в меню. Найдите и выберите «AXI GPIO».
  3. Дважды щелкните новый блок IP и в окне повторной настройки IP перейдите на вкладку конфигурации IP. Выберите все входы и установите ширину на двенадцать, так как у нас будет 12 «струн» на нашей арфе и, следовательно, потребуется 12 датчиков. Если вы хотите использовать меньше или больше датчиков, отрегулируйте это число соответствующим образом. Также установите разрешение прерывания.
  4. Щелкните правой кнопкой мыши новый блок IP GPIO и выберите «запустить автоматизацию подключения». Установите флажок AXI и нажмите "ОК". Это должно автоматически подключить интерфейс AXI, но оставить выходы блока неподключенными.
  5. Чтобы освободить место для дополнительного прерывания, дважды щелкните блок IP xlconcat_0 и измените количество портов с 4 на 5. Затем вы можете подключить вывод ip2intc_irpt из нового блока GPIO к новому неиспользуемому порту в блоке xlconcat.
  6. Щелкните правой кнопкой мыши выход «GPIO» нового IP-блока GPIO и выберите «Сделать внешним». Найдите, где идет линия, и нажмите на маленький боковой пятиугольник, и слева должно открыться окно, в котором вы можете изменить имя. Измените название на «ДАТЧИКИ». Важно использовать то же имя, если вы хотите, чтобы предоставляемый нами файл ограничений работал, иначе вам придется изменить имя в файле ограничений.
  7. Вернувшись на вкладку источников, найдите файл ограничений и замените его тем, который мы предоставили. Вы можете либо заменить файл, либо просто скопировать содержимое нашего файла ограничений и вставить его поверх содержимого старого. Одна из важных вещей, которую делает наш файл ограничений, - это включение подтягивающих резисторов в заголовках PMOD. Это необходимо для конкретных датчиков, которые мы использовали, однако не все датчики одинаковы. Если для ваших датчиков требуются понижающие резисторы, вы можете изменить каждый экземпляр «set_property PULLUP true» на «set_property PULLDOWN true». Если для них требуется резистор другого номинала, чем тот, который установлен на плате, вы можете удалить эти линии и использовать внешние резисторы. Имена контактов находятся в комментариях в файле ограничений, и они соответствуют меткам на первой диаграмме в Zybo Schematics. страницу, которую можно найти здесь. Если вы хотите использовать разные выводы pmod, просто сопоставьте имена в файле ограничений с метками в схеме. Мы используем заголовки PMOD JE и JD и используем по шесть контактов данных на каждом, опуская контакты 1 и 7. Эта информация важна при подключении ваших датчиков. Как показано на схеме, контакты 6 и 12 на PMODS имеют VCC, а контакты 5 и 11 заземлены.
  8. Восстановите оболочку HDL, как раньше, и скопируйте и перезапишите старую. Когда это будет сделано, сгенерируйте битовый поток и экспортируйте оборудование, как раньше, и перезапустите SDK. Если вас спросят, хотите ли вы заменить старый файл оборудования, ответ будет положительным. Вероятно, лучше всего закрыть SDK при экспорте оборудования, чтобы оно было должным образом заменено.
  9. Запустите SDK.

Шаг 3. Запустите FreeRTOS

Следующим шагом будет запуск FreeRTOS на плате Zybo.

  1. Если у вас еще нет копии, загрузите FreeRTOS здесь и извлеките файлы.
  2. Импортируйте демо FreeRTOS Zynq, расположенное в FreeRTOSv9.0.0 / FreeRTOS / Demo / CORTEX_A9_Zynq_ZC702 / RTOSDemo. Процесс импорта почти такой же, как и для другого демонстрационного проекта, однако, поскольку демонстрация FreeRTOS Zynq полагается на другие файлы в папке FreeRTOS, вы не должны копировать файлы в свою рабочую область. Вместо этого вы должны поместить всю папку FreeRTOS в папку вашего проекта.
  3. Создайте новый пакет поддержки платы, перейдя в «файл» -> «новый» -> «пакет поддержки платы». Убедитесь, что выбран автономный режим, и нажмите «Готово». Через мгновение появится всплывающее окно, установите флажок рядом с lwip141 (это предотвратит сбой компиляции одной из демонстраций FreeRTOS) и нажмите OK. После этого щелкните правой кнопкой мыши проект RTOSdemo и перейдите в «Свойства», перейдите на вкладку «Ссылки проекта» и установите флажок рядом с новым созданным вами bsp. Надеюсь, это будет признано, но иногда Xilinx SDK может показаться странным в подобных вещах. Если после этого шага вы все еще получаете сообщение об отсутствии xparameters.h или что-то в этом роде, попробуйте повторить этот шаг и, возможно, выйти и перезапустить SDK.

Шаг 4: Добавьте код лазерной арфы

Теперь, когда FreeRTOS импортирован, вы можете перенести файлы из проекта лазерной арфы в демонстрацию FreeRTOS.

  1. Создайте новую папку в папке src в демо FreeRTOS и скопируйте и вставьте все предоставленные файлы c, кроме main.c, в эту папку.
  2. Замените RTOSDemo main.c предоставленным main.c.
  3. Если все сделано правильно, вы сможете запустить код лазерной арфы на этом этапе. В целях тестирования кнопка ввода, которая использовалась в демонстрационном проекте DMA, теперь используется для воспроизведения звуков без подключенных датчиков (будет работать любая из четырех основных кнопок). Он будет воспроизводить струну каждый раз, когда вы ее нажимаете, и циклически перебирает все струны в системе за несколько нажатий. Подключите наушники или динамики к разъему для наушников на плате Zybo и убедитесь, что вы слышите звуки струн, проходящие сквозь них, когда вы нажимаете кнопку.

Шаг 5: О коде

Многие из вас, читающие этот учебник, вероятно, здесь, чтобы узнать, как настроить звук или использовать DMA для чего-то другого или для создания другого музыкального инструмента. По этой причине следующие несколько разделов посвящены описанию того, как предоставленный код работает в сочетании с ранее описанным оборудованием для получения рабочего аудиовыхода с использованием DMA. Если вы понимаете, зачем нужны фрагменты кода, вы сможете настроить их под то, что вы хотите создать.

Прерывания

Сначала я упомяну, как в этом проекте создаются прерывания. Как мы это сделали, мы сначала создали структуру таблицы векторов прерываний, которая отслеживает идентификатор, обработчик прерывания и ссылку на устройство для каждого прерывания. Идентификаторы прерывания взяты из xparameters.h. Обработчик прерывания - это функция, которую мы написали для DMA и GPIO, а прерывание I2C исходит от драйвера Xlic I2C. Ссылка на устройство указывает на экземпляры каждого устройства, которые мы инициализируем в другом месте. Ближе к концу функции _init_audio цикл проходит по каждому элементу таблицы векторов прерываний и вызывает две функции, XScuGic_Connect () и XScuGic_Enable () для подключения и разрешения прерываний. Они ссылаются на xInterruptController, который по умолчанию является контроллером прерываний, созданным в FreeRTOS main.c. По сути, мы прикрепляем каждое из наших прерываний к этому контроллеру прерываний, который уже был создан для нас FreeRTOS.

DMA

Код инициализации DMA начинается в lh_main.c. Сначала объявляется статический экземпляр структуры XAxiDma. Затем он настраивается в функции _init_audio (). Сначала вызывается функция configure из демонстрационного проекта, которая находится в dma.c. Это довольно хорошо задокументировано и взято прямо из демо. Затем подключается и активируется прерывание. Для этого проекта требуется только прерывание от ведущего к ведомому, потому что все данные отправляются DMA контроллеру I2S. Если вы хотите записать звук, вам также понадобится прерывание от ведомого к ведущему. Прерывание от ведущего к ведомому вызывается, когда DMA завершает отправку любых данных, которые вы ему приказали отправить. Это прерывание невероятно важно для нашего проекта, потому что каждый раз, когда DMA завершает отправку одного буфера аудиосэмплов, он должен немедленно начать отправку следующего буфера, иначе между отправками возникнет звуковая задержка. Внутри функции dma_mm2s_ISR () вы можете увидеть, как мы обрабатываем прерывание. Важная часть находится ближе к концу, где мы используем xSemaphoreGiveFromISR () и portYIELD_FROM_ISR (), чтобы уведомить _audio_task () о том, что он может инициировать следующую передачу DMA. Мы отправляем постоянные аудиоданные путем чередования двух буферов. Когда один буфер передается в блок I2C, значения другого буфера вычисляются и сохраняются. Затем, когда от DMA поступает прерывание, активный буфер переключается, и начинает передаваться последний записанный буфер, в то время как ранее переданный буфер начинает перезаписываться новыми данными. Ключевая часть функции _audio_task - это место, где вызывается fnAudioPlay (). fnAudioPlay () принимает экземпляр DMA, длину буфера и указатель на буфер, из которого будут передаваться данные. Несколько значений отправляются в регистры I2S, чтобы он знал, что поступают новые образцы. Затем вызывается XAxiDma_SimpleTransfer (), чтобы инициировать передачу.

I2S Аудио

audio.c и audio.h - это места, где происходит инициализация I2S. Код инициализации I2S - довольно распространенный фрагмент кода, плавающий в разных местах, вы можете найти небольшие вариации из других источников, но этот должен работать. Это довольно хорошо задокументировано и не требует особых изменений для проекта арфы. Демонстрация звука DMA, из которой оно пришло, имеет функции переключения на микрофонный или линейный входы, так что вы можете использовать их, если вам нужна эта функциональность.

Звуковой синтез

Чтобы описать, как работает синтез звука, я собираюсь перечислить каждую из моделей звука, использованных при разработке, которые привели к окончательному методу, поскольку он даст вам представление о том, почему это делается именно так.

Метод 1: один период значений синуса вычисляется для каждой строки на соответствующей частоте для музыкальной ноты этой строки и сохраняется в массиве. Например, длина массива будет периодом синусоидальной волны в отсчетах, который равен количеству отсчетов / цикл. Если частота дискретизации составляет 48 кГц, а частота нот - 100 Гц, то 48 000 отсчетов в секунду и 100 циклов в секунду приводят к 4800 отсчетам за такт, а длина массива будет 4800 отсчетов и будет содержать значения одного полного период синусоидальной волны. Когда строка воспроизводится, буфер аудиосэмплов заполняется путем взятия значения из массива синусоидальных волн и помещения его в аудиобуфер в качестве выборки, а затем увеличения индекса в массиве синусоидальных волн, чтобы использовать наш предыдущий пример на протяжении всего курса. из 4800 отсчетов один цикл синусоидальной волны помещается в звуковой буфер. Для индекса массива используется операция по модулю, так что он всегда находится между 0 и длиной, и когда индекс массива превышает определенный порог (например, 2-секундные выборки), строка отключается. Чтобы воспроизводить несколько строк одновременно, отслеживайте индекс массива каждой строки отдельно и складывайте значение из синусоидальной волны каждой строки вместе, чтобы получить каждую выборку.

Метод 2: Чтобы создать более музыкальный тон, мы начнем с предыдущей модели и добавим гармоники к каждой основной частоте. Частоты гармоник - это частоты, кратные основной частоте. В отличие от случая, когда две несвязанные частоты суммируются, что приводит к одновременному воспроизведению двух разных звуков, когда гармоники складываются вместе, он продолжает звучать как один звук, но с другим тоном. Для этого каждый раз, когда мы добавляем значение синусоидальной волны в местоположении (индекс массива% длины массива) к аудиосэмплу, мы также добавляем (2 * индекс массива% длина массива) и (3 * индекс массива% длина массива) и т. д. для любого количества желаемых гармоник. Эти перемноженные индексы будут пересекать синусоидальную волну на частотах, кратных исходной частоте. Чтобы обеспечить больший контроль тона, значения каждой гармоники умножаются на переменную, которая представляет количество этой гармоники в общем звуке. Например, основная синусоида может иметь все значения, умноженные на 6, чтобы сделать ее более важным фактором в общем звуке, в то время как 5-я гармоника может иметь множитель 1, что означает, что ее значения вносят гораздо меньший вклад в общий звук.

Метод 3: Хорошо, теперь у нас есть очень приятный тон нот, но все еще есть довольно серьезная проблема: они играют с фиксированной громкостью в течение фиксированной продолжительности. Чтобы звучать как настоящий инструмент, громкость струны должна плавно затухать с течением времени. Для этого массив заполняется значениями экспоненциально убывающей функции. Теперь, когда создаются аудиосэмплы, звук, исходящий из каждой строки, вычисляется, как в предыдущем методе, но перед добавлением к аудиосэмплу он умножается на значение индекса массива этих строк в массиве функции экспоненциального затухания. Это заставляет звук плавно рассеиваться с течением времени. Когда индекс массива достигает конца массива распада, строка останавливается.

Метод 4: Этот последний шаг - это то, что действительно придает звукам струн их реалистичное звучание. Раньше они казались приятными, но четко синтезированными. Чтобы попытаться лучше имитировать реальную струну арфы, каждой гармонике назначается разная скорость затухания. В настоящих струнах при первом ударе по струне присутствует большое количество высокочастотных гармоник, которые создают звук ощипывания, который мы ожидаем от струны. Эти высокочастотные гармоники очень кратковременно составляют основную часть звука, звук ударяемой струны, но они очень быстро затухают по мере того, как преобладают более медленные гармоники. Матрица затухания создается для каждого номера гармоники, используемого в синтезе звука, каждая со своей скоростью затухания. Теперь каждую гармонику можно независимо умножить на значение соответствующего ей массива распада в индексе массива строки и добавить к звуку.

В целом синтез звука интуитивно понятен, но требует больших вычислений. Одновременное сохранение всего струнного звука в памяти заняло бы слишком много памяти, но вычисление синусоидальной волны и экспоненциальной функции между каждым кадром заняло бы слишком много времени, чтобы не отставать от скорости воспроизведения звука. В коде используется ряд уловок для ускорения вычислений. Вся математика, за исключением начального создания таблиц синусоидального и экспоненциального затухания, выполняется в целочисленном формате, что требует распределения доступного числового пространства в 24-битном аудиовыходе. Например, таблица синусов имеет амплитуду 150, поэтому она является гладкой, но не настолько большой, чтобы в сумме несколько строк, сыгранных вместе, могли составлять более 24 битов. Точно так же экспоненциальные значения таблицы умножаются на 80 перед округлением до целых чисел и сохранением. Веса гармоник могут принимать дискретные значения от 0 до 10. Кроме того, все выборки фактически удваиваются, а синусоидальные волны индексируются двойками, что снижает частоту дискретизации вдвое. Это ограничивает максимальную воспроизводимую частоту, но было необходимо для достаточно быстрого расчета текущего количества струн и гармоник.

Создание этой звуковой модели и ее использование потребовало значительных усилий со стороны процессора, и было бы невероятно сложно заставить ее работать на стороне fpga с нуля во временных рамках этого проекта (представьте, что вам нужно воссоздавать битовый поток каждые раз кусок verilog был изменен для проверки звука). Тем не менее, выполнение этого на fpga, вероятно, могло бы быть лучшим способом сделать это, возможно, устранив проблему неспособности достаточно быстро вычислить сэмплы и разрешив больше строк, гармоник и даже звуковых эффектов или других задач, которые будут выполняться на сторона процессора.

Шаг 6: Подключение датчиков

Подключение датчиков
Подключение датчиков

Для создания струн мы использовали инфракрасные датчики разрывного луча, которые обнаруживают, когда играет струна. Заказывали наши датчики по следующей ссылке. Датчики имеют провод питания, заземления и передачи данных, в то время как эмиттеры имеют только провод питания и заземления. Мы использовали контакты 3,3 В и заземления от разъемов PMOD для питания как эмиттеров, так и датчиков. Для питания всех датчиков и излучателей необходимо подключить все датчики и излучатель параллельно. Каждый провод данных от датчиков должен быть подключен к собственному выводу модуля pmod.

Шаг 7: конструирование скелета

Построение скелета
Построение скелета

Чтобы создать форму арфы, три части используются в качестве каркаса, на котором размещаются датчики и излучатели. На одном из двух 18-дюймовых отрезков трубы из ПВХ выровняйте датчики и излучатели в попеременном порядке на расстоянии 1,5 дюйма друг от друга, а затем приклейте их к трубе. На другой 18-дюймовой трубе из ПВХ выровняйте датчики и излучатели в чередующемся порядке, но не забудьте сместить порядок (то есть, если первая труба имела датчик первым, вторая должна иметь сначала излучатель, и наоборот). Необходимо припаять более длинные провода к проводам данных, питания и заземления, чтобы обеспечить их доступ к плате.

Шаг 8: Строительство деревянного фасада

Строительство деревянного экстерьера
Строительство деревянного экстерьера

Этот шаг не является обязательным, но настоятельно рекомендуется. Деревянный внешний вид арфы не только красиво выглядит, но и защищает датчики и провода от повреждений. Деревянный каркас может быть создан полым прямоугольным кольцом из дерева. Внутри прямоугольника должно быть отверстие размером не менее 1-1 / 2 дюйма для установки трубы и каркаса датчика. Как только рама будет построена, просверлите два отверстия, которые позволят выводить провода от датчика и излучателей, чтобы соединить их с платой.

* Примечание. Рекомендуется добавить точки доступа, чтобы можно было снимать и вставлять каркас трубы в случае необходимости ремонта или небольших корректировок.

Шаг 9: Собираем все вместе

Собираем все вместе
Собираем все вместе

После того, как все предыдущие шаги выполнены, пришло время построить арфу. Сначала поместите каркас трубы внутрь деревянного фасада. Затем подключите провода датчиков и эмиттеров в правильное место на плате. Затем откройте SDK и нажмите кнопку отладки, чтобы запрограммировать плату. После того, как плата запрограммирована, подключите пару наушников или динамик. В зависимости от того, какой датчик попадает в какой порт pmod, струны вашей арфы, вероятно, с самого начала выйдут из строя. Поскольку при таком большом количестве проводов бывает сложно определить, какой провод к какому датчику идет, мы включили способ сопоставления номеров строк для прерывания позиций битов в программном обеспечении. Найдите «static int sensor_map [NUM_STRINGS]» и настройте значения в массиве до тех пор, пока строки не будут воспроизводиться от наименьшего к наибольшему по порядку.

Меню можно использовать, открыв последовательный терминал (например, RealTerm) и установив скорость передачи данных на 115200, а дисплей - на ANSI. В меню можно перемещаться, используя клавиши w и s для перемещения вверх и вниз и клавиши a и d для изменения значений.

Шаг 10: ОТКАЗАТЬСЯ

После того, как арфа полностью заработает. Овладейте арфой и слушайте сладкий звук собственной музыки!

Рекомендуемые: