Вышла из строя стиральная машина (холодильник, микроволновка или еще что-то из бытовой техники)? Не торопитесь бежать в магазин покупать новую или искать мастера- в большинстве случаев неисправность можно устранить самостоятельно, сэкономив при этом не одну тысячу рублей. Конечно-же вся современная бытовая техника имеет довольно высокий уровень сложности, однако вместе с этим в ней предусмотрены и функции самодиагностики, что значительно упрощает ремонт
-->

МЕХЗАВОД|Ремонт бытовой техники и электроники cвоими руками

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.



Новая жизнь старого синтезатора.

Сообщений 1 страница 2 из 2

1

http://s4.uploads.ru/t/2zaNy.jpg
Несколько лет тому назад умер смертью храбрых мой старый синтезатор Yamaha PSR-GX76. Случилось это из-за того, что я по ошибке подключил к нему блок питания 24 В вместо положенных 12 В. В таком режиме синтезатор героически проработал несколько минут, после чего случился «пук», сопровождаемый аудиовизуальными спецэффектами и специфическим запахом и синтезатор больше не включался. С тех пор он пылился в коробке и ждал своего часа, который для него, наконец, настал. В нескольких статьях я расскажу как проходило движение от идеи вдохнуть в него новую жизнь до реализации и демонстрации полученных результатов.

Вскрытие

Типичный синтезатор состоит из нескольких основных частей: модуль звукогенератора (содержащий обычно микросхему самого звукогенератора и память с сэмплами инструментов), модуль аудио-усилителя и модуль, сканирующий клавиатурную матрицу синтезатора.
http://s3.uploads.ru/t/2LfMJ.jpg
Модуль усилителя звуковой частоты (совмещен с блоком питания)

http://s4.uploads.ru/t/QyKeZ.jpg
Модуль звукогенератора (видна память, сам звукогенератор на обратной стороне)

Вскрытие показало, что в моем синтезаторе разорвало на части стабилизатор напряжения питания, ответственный за подачу напряжения на микросхемы звукогенератора и сканера клавиатурной матрицы. Увы, замена стабилизатора на новый не принесла результатов. Дальнейший анализ показал, что обе микросхемы, по всей видимости, более не функционируют: присутствуют корректные сигналы сброса и тактового генератора, однако никаких признаков жизни со стороны самих микросхем не наблюдается. Поскольку данные микросхемы были произведены специально для синтезатора компанией Yamaha, то заменить их на новые не представлялось возможным, тем более, что модель уже старая. И тут мне пришла в голову идея вместо того, чтобы отремонтировать старый модуль звукогенератора, выкинуть его и сделать свой собственный, целиком и полностью настраиваемый, с Linux-ом и Wi-Fi'ем.

Выбор платформы — основы для нового синтезатора

Загоревшись этой идеей, я начал подбирать платформу, на базе которой будет создаваться новый «мозг» синтезатора. Начал поиски с относительно простых отладочных плат на STM32, так как изначальная идея была в реализации с нуля прошивки, реализующей синтез звуков. Критерием отбора являлось наличие как минимум нескольких десятков мегабайт памяти, слот для SD-карты, аудиовыход и возможность подключения LCD-дисплея. Затем возникла идея использовать что-то помощнее, и я вспомнил про валяющуюся без дела Raspberry Pi. Но она не подошла в итоге по нескольким причинам: отсутствие возможности без танцев с бубном «из коробки» подключить LCD-дисплей, отсутствие достаточного количества GPIO-пинов, сравнительно низкая частота процессора. Но к тому моменту я уже понял, что нужно двигаться в направлении Linux, потому что для него уже написано немало программных синтезаторов, и в частности, особо заинтересовавшие меня LinuxSampler и FluidSynth. Поэтому я продолжил поиски, уже отбросив «маломощные» платы на STM32, и спустя несколько часов непрерывных поисков я нашел ЕГО, и понял — это то, что нужно. Итак, в качестве платформы был выбран и приобретен в Китае мини-компьютер EmbedSky E8 miniPC, в комплекте с 4.3-дюймовым резистивным сенсорным LCD-дисплеем.

http://s9.uploads.ru/t/AHiJh.jpg
Технические характеристики его представлены в таблице, цена вопроса 48 долларов США:
Размеры 100х65х20 мм (без учета разъемов)
Процессор Samsung S5PV210 Cortex-A8 (1 ГГц)
Оперативная память 512 МБ *
EMMC Flash-память 4 ГБ
USB-порты 4 порта USB 2.0, 1 порт USB OTG
Аудио Вход/выход до 48 КГц, WM8960
HDMI HDMI 1.3 1080p@30 FPS
Ethernet 100 Mbit
Последовательный порт 3 порта 3.3V, один порт со стандартными уровнями RS232
Часы Поддержка часов реального времени (плюс батарейка)
Карта памяти Интерфейс для карты памяти SD
Кнопки 2 программируемые кнопки
Камера Специальный порт для подключения видеокамеры
Светодиоды 4 программируемых светодиода
IrDA Встроенный ИК-приемник
Дисплей 40-пин FPC для подключения LCD (поддержка резистивного и емкостного экрана)
50-пиновый разъем 17 линий GPIO, 4-х канальный ADC, SPI, 2 PWM, дополнительный интерфейс SD
* — объем доступной в системе памяти со стандартным ядром — около 390 Мб (в дальнейшем это ограничение было снято — детали в следующей статье).

Надо сказать, я был приятно поражен тем объемом документации, который поставляется на двух DVD-дисках вместе с мини-компьютером: на дисках присутствует полная принципиальная схема, документация на каждую используемую микросхему, включая полную документацию на процессор, руководство пользователя (на китайском, но все и так понятно) различные инструкции (например, по установке Ubuntu и даже по разработке с Qt). Кроме того, имеются исходные коды ядра Linux 3.0.8, исходный код системы Android, некоторого ПО от EmbedSky, GCC 4.4.3, исходный код Qt и еще много интересного. На плате предустановлено сразу две ОС — Linux и Android 4.0.4, выбор какую загружать осуществляется через загрузчик U-Boot. Android был мною безжалостно снесен, и вся имеющаяся eMMC Flash-память использована под простой Linux.

Стоит отметить, что изначально плата настроена на работу с емкостным экраном. Для того, чтобы переключить ее на резистивный интерфейс, необходимо перепаять две перемычки на обратной стороне платы рядом с LCD-разъемом. Собственно, это было первое, что я и сделал с платой после проверки ее работоспособности. Далее выяснилось, что образ Linux, зашитый в eMMC тоже по-умолчанию настроен на использование емкостного датчика. Убил несколько часов, копаясь в конфигах Qt и Tslib, но в итоге тач все-таки заработал как положено.

С платой поставляется Qt версии 4.5 — довольно старая версия. Я люблю все новое, поэтому для работы над своим проектом, я решил скомпилировать для ARM Qt последней версии 5, а поскольку много времени тратить на разработку тоже не очень хотелось, то дополнительно я решил, что буду все писать на Python, так что мне понадобилась также библиотека PyQt5. Процессор Samsung S5PV210 имеет встроенный 3D-ускоритель с поддержкой OpenGL ES 2.0, но, к сожалению, Samsung предоставляет драйвера для OpenGL только для ОС Android, поэтому использовать Qt 5 с поддержкой OpenGL ES не получилось (попытался скопировать нужные DLL с образа Android, но одна из библиотек имела зависимость от libhardware.so и далее до бесконечности), так что я остановился на LinuxFB в качестве платформы для вывода графики. С компиляцией Qt 5 особых проблем не возникло, за основу я взял конфиг для Raspberry Pi и вырезал все, что связано с OpenGL ES. Затем я собрал Python 2.7.6, используя инструкцию отсюда.

При сборке для ARM библиотеки PyQt5 возникла проблема — оказалось, что библиотека имеет зависимость от заголовков OpenGL даже если Qt была собрана без поддержки OpenGL. Пришлось пропатчить библиотеку так, чтобы убрать зависимость. Соответствующий патч был опубликован в списке рассылки PyQt. Возможность сборки без OpenGL будет также добавлена в upstream в ближайшее время. После сборки PyQt5 я успешно протестировал на устройстве примеры из поставки Qt, портированные на Python и распространяющиеся в составе PyQt.

http://sa.uploads.ru/t/cFANP.jpg
Мой графический интерфейс к LinuxSampler и FluidSynth, написанный на PyQt5

Далее последовала кросс-компиляция LinuxSampler и его зависимостей: libaudiofile, libfftw, libgig, libsndfile, libsamplerate. В libsndfile была обнаружена интересная фича, названная в коде библиотеки «Ultimate sanity check» — assert на то, что тип off_t имеет размер 8 байт. В моем случае это оказалось не так. К счастью, простое удаление этой “проверки на вменяемость” полностью решило проблему. Интересно, почему она делает эту проверку во время выполнения а, не прерывается на этапе configure — все равно ведь работать не будет, зачем тогда компилировать?

Дополнительно был скомпилирован JACK в качестве драйвера вывода звука для LinuxSampler. Для него потребовались патчи arm-timestamp.patch и atomic.patch отсюда. Также я компилировал с такими флагами для GCC, чтобы включить поддержку расширений NEON для ARM: -march=armv7-a -mtune=cortex-a8 -mfpu=neon -ffast-math -funsafe-math-optimizations -O3.

На данной стадии у меня работал JACK и LinuxSampler, через который я мог проигрывать MIDI-файлы с помощью jack-smf-player. Вместе с графическим интерфейсом (см. выше) был написан питоновский модуль для работы с LinuxSampler по протоколу LSCP, а также с помощью SWIG сгенерирован биндинг для libgig, которая позволяет загружать GIG-файлы, и, в частности, выяснить какие внутри есть инструменты, чтобы их можно было выбрать из списка в интерфейсе на Qt. Ближе к завершению проекта эти наработки, а также весь связанный с проектом оригинальный исходный код будет выложен на GitHub для всех желающих.

В следующей статье я расскажу:

    Как устроена клавиатурная матрица синтезатора
    Как я менял сгоревший МК сканера клавиатуры на ATmega, про прошивку прямо с платы, и как микроконтроллер общается с LinuxSampler
    Как я делал ядро с поддержкой Realtime Preemption на основе стокового и как решались многочисленные возникшие проблемы
    Как проходило общение с техподдержкой фирмы EmbedSky Tech
    Как удалось снизить задержку (latency) звука при нажатии на клавиши синтезатора с нескольких десятков до нескольких миллисекунд

Все описанные в этой и следующей статье манипуляции с незначительными отличиями можно проделать также и с использованием других подходящих ARM-платформ включая Raspberry Pi, для изготовления своего собственного универсального синтезатора из старой MIDI-клавиатуры. Из преимуществ последней можно отметить наличие более мощного аппаратного FPU и возможность сборки Qt 5 с поддержкой OpenGL ES 2.0.

2

Продолжение истории про старый сгоревший синтезатор, в который я пытаюсь вдохнуть новую жизнь путем полной замены железа, отвечающего за генерацию звука, на программный синтезатор, построенный на базе мини-компьютера EmbedSky E8 с Linux на борту. Как это часто бывает, между публикацией первой и второй части статьи прошло гораздо больше времени, чем планировалось, но, тем не менее, продолжим.

https://forumupload.ru/uploads/0019/8b/c2/2/923091.jpg

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

Клавиатурная матрица

Клавиатурная матрица синтезатора очень похожа на обычную клавиатурную матрицу, которые многие любители микроконтроллеров уже наверняка подключали к своим Arduino. Для каждой клавиши синтезатора на ней предусмотрено от одного (в наиболее дешевых моделях) до двух (в основной массе моделей) переключателей. С помощью двух расположенных рядом переключателей, один из которых при нажатии клавиши замыкается немного раньше другого, микроконтроллер может определить условную силу, а точнее скорость, с которой клавиша была нажата, чтобы впоследствии был воспроизведен звук соответствующей громкости. Выглядит это так:

https://forumupload.ru/uploads/0019/8b/c2/2/359713.jpg

На обратной стороне платы размещены диоды, которые предотвращают «ложное» считывание нажатых клавиш при одновременном нажатии нескольких клавиш. Вот фрагмент принципиальной схемы клавиатурной матрицы, на которой видны эти два переключателя и подсоединенные к ним диоды:
https://forumupload.ru/uploads/0019/8b/c2/2/381267.png

Чтобы просканировать матрицу, микроконтроллер последовательно подтягивает столбцы (выводы, помеченные как N) к питанию, и проверяет уровень на строках (выводы, помеченные как B). Если уровень какой-либо строки окажется высоким, значит соответствующая активному в данный момент сочетанию «столбец-строка» клавиша нажата. На схеме показана лишь часть клавиатуры — всего на ней 76 клавиш (13 строк и 6 х 2 колонок, что дает в сумме 156 возможных вариантов при сканировании матрицы и 25 используемых выводов микроконтроллера). Сканирование всей клавиатуры осуществляется несколько десятков раз в секунду и незаметно для исполнителя.

В моем синтезаторе микроконтроллером, ответственным за сканирование клавиатуры, изначально был 8-битный однократно программируемый микроконтроллер Hitachi HD63B05V0, работающий на частоте 8 МГц и имеющий 4 КБ ROM и 192 байта RAM памяти. К сожалению, данный контроллер оказался нерабочим после инцидента с питанием, описанного в начале первой статьи. Зато, к счастью, он оказался почти совместим по выводам с имеющимся у меня контроллером ATmega162, на который я его и заменил, перерезав и перепаяв всего лишь 2 дорожки на плате, одна из которых — это вывод RESET, оказавшийся совсем не в том месте, как у HD63B05V0.

Поскольку такое включение контроллера не позволяло мне воспользоваться встроенным UART (так как он тоже был на других выводах), то для вывода информации о нажатых клавишах я воспользовался этой односторонней (только запись) реализацией последовательного порта. Также в микроконтроллер был залит загрузчик TinySafeBoot, также использующий программную реализацию последовательного порта, для возможности будущего обновления прошивки. Поскольку в качестве языка для быстрой разработки всего высокоуровневого ПО синтезатора я выбрал Python + Qt5, то для TinySafeBoot я также написал модуль на Python, который позволяет считывать и записывать прошивку в микроконтроллер AVR. Сам микроконтроллер AVR подключен к последовательному порту UART1 на плате EmbedSky E8 и питается от напряжения 3.3V, чтобы избежать необходимости в преобразовании уровней.

Исходный код прошивки для AVR

Модуль на Python для TinySafeBoot

В качестве программатора для AVR я сначала использовал программатор на базе Launchpad MSP430, коих у меня имеется в наличии несколько штук, а затем это самодельное чудо (неплохо работающее, кстати), уступило место прибывшему из Китая программатору TL866CS MiniPro. Ощущения от нового программатора крайне положительные.

Очень подробно про устройство клавиатуры синтезатора и способы ее сканирования, включая один очень оригинальный способ сканирования через интерфейс микроконтроллера AVR для подключения внешней микросхемы ОЗУ рассказывается на сайте OpenMusicLabs

Приготовление ядра с поддержкой Realtime Preemption

Отчасти для получения большего контроля над планировщиком и снижения задержки (latency) при проигрывании звука, а отчасти из спортивного интереса, я решил использовать ядро с патчем PREEPMT RT, одной из основных особенностей которого является то, что прерывания также становятся «процессами», которые могут быть вытеснены планировщиком с учетом приоритета. Оригинальное ядро, поставляемое Samsung для процессора S5PV210, на базе которого построена система, базируется на ядре версии 3.0.8, судя по всему от Android. Ни один из патчей RT_PREEMPT, имеющихся на сайте проекта, предназначенных для данной версии ядра (3.0.8), не хотел накладываться на исходники без конфликтов, но в конце концов, разрешив все конфликты вручную, удалось наложить патч версии 3.0.8-rt23.

Из-за того, что в модифицированном таким образом ядре модифицированными также оказались такие базовые структуры, как spinlock и mutex, с ним перестали линковаться поставляемые в виде скомпилированных объектных файлов проприетарные драйверы некоторых периферийных устройств: видеокамер, контроллера ёмкостного тачскрина, и, что самое ужасное, аудиокодека. Вернемся к ним позже, а сейчас отключим их и попытаемся первый раз запустить плату со свежесобранным ядром реального времени и… получим моментальный kernel panic. Происходил он еще до запуска отладчика kgdb (который, как выяснилось позже, все равно не работал бы, даже если бы запустился), так что для отладки пришлось вставлять printf-ы в файл init/main.c, функцию start_kernel, чтобы определить место, в котором все рушится. Таким образом выяснилось, что последнее, что успевало сделать ядро, это вызвать функцию hrtimers_init(), инициализирующую таймеры высокого разрешения и их прерывания. Этот код зависит от конкретной платформы, и в нашем случае находится в arch/arm/plat-s5p/hr-time-rtc.c. Как я уже говорил, одной из основных особенностей ядра с патчем PREEMPT RT является то, что прерывания становятся потоками. Это возможно и в обычном ядре, но ядро с PREEMPT RT по-умолчанию пытается сделать таковыми почти все прерывания. Дальнейший анализ кода показал, что для работы этих потоков используется задача kthreadd_task, которая инициализируется в самом конце функции start_kernel — гораздо позже, чем происходит инициализация таймеров. Падение же происходило из-за того, что прерывание таймера ядро пыталось сделать потоковым, в то время как kthreadd_task еще NULL. Решается это установкой для отдельных прерываний, которые не стоит делать потоковыми ни при каких обстоятельствах, флага IRQF_NO_THREAD который и был добавлен к флагам прерывания таймера в hr-time-rtc.c. Ура! Ядро загрузилось, но это еще только начало…

Как я уже упоминал выше, одним из побочных эффектов стало то, что модуль, отвечающий за аудио ввод/вывод, перестал линковаться с новым ядром. Отчасти это было тем, что ядро с PREEMPT RT поддерживает (в версии 3.0.8) только механизм управления памятью SLAB, а изначально модуль был скомпилирован с включенным механизмом SLUB, который не поддерживается новым ядром. Однако, мне посчастливилось работать в Лаборатории Касперского, и я уговорил коллегу декомпилировать для меня файлы драйвера и кодека с помощью декомпилятора Hex-Rays для ARM, после чего удалось практически полностью воссоздать их исходный код. Практически — потому что в результате с «новым» драйвером аудиоинтерфейс стал определяться, однако из-за каких-то различий в низкоуровневой процедуре инициализации регистров микросхемы WM8960 звук проигрывался с артефактами. Какое-то время я пытался подправить свой драйвер, но потом выбрал более легкий путь — я отправил в техподдержку китайской компании EmbedSky Tech, где покупал мини-компьютер, свой патч с PREEMPT_RT, и попросил их скомпилировать для меня и выслать файлы аудиодрайвера. Ребята быстро откликнулись и прислали мне файлы, с которым звук, наконец, заработал как положено.

Кстати, пока я возился со своим декомпилированным драйвером, я обнаружил, что отладчик kgdb не работает ни с моим, ни с оригинальным ядром. Как выяснилось, для его работы требуется поддержка синхронного (polling) опроса последовательного порта, которая отсутствовала в драйвере последовательного порта Samsung (drivers/tty/serial/samsung.c). Я добавил в драйвер требуемую поддержку, основанную на этом патче, после чего отладчик заработал.

Копаем дальше. Вторым побочным эффектом нового ядра оказалась крайне низкая, с большими «лагами», скорость работы всех четырех многострадальных последовательных портов системы на кристалле S5PV210, в результате чего была невозможна нормальная работа в терминале через последовательный порт, а также не работала как положено перепрошивка контроллера AVR, опрашивающего клавиатуру синтезатора. Я долго пытался понять в чем причина, но заметил лишь то, что ввод каждого символа в терминале приводил к генерации нескольких миллионов прерываний последовательного порта — ядро, похоже, не спешило их обрабатывать. В итоге я решил эту проблему тем, что с помощью вышеупомянутого флага IRQF_NO_THREAD сделал все прерывания последовательных портов непотоковыми. Это решение вышло не очень красивым, потому что помимо драйвера Samsung пришлось внести изменения в файлы serial_core.c и serial_core.h, затрагивающие вообще все последовательные порты. Потому что в ядре с PREEMPT RT нельзя использовать spin_lock_t в драйверах, которые NO_THREAD, а нужно использовать raw_spinlock_t.

В оригинальном ядре, которое, как я говорил выше, поддерживает различные периферийные устройства, такие как видеокамеры, аппаратные кодеки, HDMI и т.д., из 512 МБ оперативной памяти было доступно лишь около 390 МБ, а остальное было зарезервировано для работы вышеуказанных устройств, причем всегда (даже если в процессе конфигурирования ядра они были отключены). Очень расточительно, особенно учитывая, что лишние 120 МБ оперативной памяти синтезатору очень даже не помешают для хранения сэмплов. Память резервировалась в файле arch/arm/mach-s5pv210/mach-tq210.c, который является главной точкой сбора всей информации о конфигурации и устройствах конкретной машины (в нашем случае — платы). Комментируем выделение памяти — вызов функции s5p_reserve_bootmem, и получаем 120 МБ дополнительной памяти для работы синтезатора.

Последнее изменение, которое было внесено в ядро, касалось минимального размера буфера для аудиоданных, который в оригинале был равен одной странице памяти, что при частоте дискретизации 44100 Гц, 2 канала по 16 бит давало примерно 20 мс — многовато. Это значение было изменено в файле sound/soc/samsung/dma.c на 128 байт, после чего минимальный размер буфера уменьшился до нескольких миллисекунд без ущерба стабильности и работоспособности.

Исходный код ядра с PREEMPT RT и всеми модификациями на GitHub

Как происходит общение микроконтроллера AVR с LinuxSampler

AVR подключен к последовательному порту платы мини-компьютера, и выплевывает в свой софтверный UART готовые MIDI-сообщения. Дабы избавить себя от необходимости писать драйверы, было принято решение использовать в качестве транспорта для всех аудио и MIDI-данных сервер JACK. Небольшое приложеньице на C подключается к последовательному порту, регистрирует себя в JACK как MIDI-OUT и начинает перенаправлять туда все полученные MIDI-сообщения, а JACK уже доставляет их в LinuxSampler. Дешево и сердито.

Исходный код приложения-моста между последовательным портом и JACK

Такое решение также позволяет проигрывать MIDI-файлы через JACK с помощью jack-smf-player, который я скомпилировал для ARM и WAV/MP3 через mplayer с поддержкой вывода звука в JACK.

Бонус

Благодаря комментарию nefelim4ag к предыдущему посту, я узнал про существование libhybris — библиотеки, которая позволяет использовать Android-драйвера в обычной Linux-системе. После некоторых танцев с бубнами, всех подробностей которых я, к сожалению, уже не помню, мне удалось завести libhybris в своей системе и пересобрать Qt 5 и PyQt5 с поддержкой OpenGL ES 2.0, EGLFS и Qt Quick 2.0. Теперь мой пользовательский интерфейс использует Qt Quick и выглядит в соответствии с последними модными тенденциями косит под Android 4.0.

https://forumupload.ru/uploads/0019/8b/c2/2/395402.png

Напоследок

Небольшое демо — пока только аудио, так как синтезатор сейчас находится в наполовину разобранном состоянии. Видео же будет в следующем посте, который родится скорее всего в августе, после того как приедет заказанная в Китае плата, соединяющая воедино все части синтезатора. Кроме того, следующий пост будет, скорее всего, посвящен уже не таким низкоуровневым манипуляциям с ядром, а процессу доведения до ума пользовательской части софта на PyQt5 и QtQuick и, конечно, демонстрации получившегося

Если кому-то интересно:
Список всего ПО, которое было кросс-компилировано для ARM

Если вам потребуется собрать что-то из этого списка и возникнут проблемы, я с удовольствием поделюсь опытом. Кроме того, многое из сказанного здесь справедливо для другой популярной платформы под названием FriendlyARM Tiny210, которая построена на базе того же самого процессора S5PV210 и, возможно, кому-то понадобится использовать с ней ядро реального времени.

https://habr.com/ru/post/224987/   - ссылка



Рейтинг форумов | Создать форум бесплатно