Если бы мне кто-то сказал, что я когда то буду заниматься программированием, я бы наверное покрутил пальцем у виска. Уж больно для меня это было фантастическим занятием, даже теоретически.
Но все оказалось сильно проще, чем я ожидал. Платформа Arduino позволила мне это не просто ощутить, но и создать что-то свое. Особенно при наличии в продаже массы готовых модулей. Я уже поигрался с метеостанцией, немного изучил модуль RTC, пощупал сенсоры СО и алкоголя, но все же основная задача стояла другая. После удачной работы с ЦАП на базе AK4399, был заказан ЦАП AK4490.
Это одна из новых разработок фирмы AKM. Там есть еще AK4495. Но была выбрана AK4490 из-за более широкого диапазона рабочих температур. Мой коллега — программист хотел попробовать ее применить в автомобиле. Я не любитель вкладывать деньги в автозвук, поэтому просто «упал на хвост» с целью пощупать ее для дома. В отличие от AK4399, AK4490 имеет мощный комплект настроек, который, я не уверен, может ли использоваться весь, по причине отсутствия надобности. Пять настроек цифрового фильтра, три режима работы в DSD, переключение полосы ФНЧ для DSD, какая-то магическая настройка Sound Control. В общем есть чего поковырять даже просто из интереса.
Содержание статьи / Table Of Contents
Поэтому был собран весь ЦАП с нуля.
Здесь я уже заранее не предусматривал работу AK4490 в «хардваре» режиме, поэтому включить и послушать, пока не готова программа, уже бы не получилось.
↑ Блок-схема
Чем дальше я влезал в даташит и описание регистров, тем сильнее становилась уверенность в том, что программа будет сильно сложнее, чем была у меня для управления AK4399.
Кнопок надо сильно больше.
Так как функции будут выбираться отдельно для режимов DSD и PCM, то придется вводить совсем другую логику. И программы и управления.
«По совету друзей(с)» было решено использовать энкодер. В этом случае лицевая панель не будет напоминать калькулятор и вообще это более практично.
Но, как в принципе всегда, здесь не обошлось без подводных камней.
Все дело в обработке энкодера контроллером.
Перед тем, как начинать думать над программой, нужно было сделать управление энкодером.
Те, кто когда то работал с МК, могут возразить — что тут сложного? А те, кто что-то делал на МК с чужими прошивками, особенно с применением энкодера, обратили внимание, что реакция контроллера на поворот энкодера несколько замедленная, а порой и вообще приходится ждать реакции. Все дело в том, что по разным причинам, контроллер не может сразу обработать состояние выводов энкодера и вывести нужный результат.
Чтоб все происходило мгновенно — нужно использовать прерывания.
Это «совет друга» - коллеги-программиста.
Что такое прерывание и с чем его надо есть — можно легко прочитать в сети.
Контроллер ATMega328 имеет два встроенных прерывания INT0 и INT1, которые жестко подключены к двум выводам: PD2 и PD3.
Поэтому пришлось немного изменить схему управляющего модуля. Ну и отказаться окончательно от измерения частоты семплов, как от бесперспективной затеи.
Теперь нужно написать программу.
Написать — это сказано сильно громко, скорее взять чужую программу и перепилить ее под свои нужды.
Так получилось, что мой товарищ программист был сильно занят, и помогал мне только советами и то по Скайпу. Поэтому пришлось в перерывах вникать во все самому и пробовать-пробовать-пробовать.
↑ 1. Логика
Изначально, идея была проста. Два режима — DSD и PCM.На каждый режим своя подпрограмма, в зависимости от логического уровня ноги DSD/PCM.
И уже в подпрограмме выбираются режимы работы, параметры, а потом все выводится на дисплей.
Поэтому логика такая:
Когда на ноге DSD/PCM логическая 1 — то включается режим РСМ, в котором возможно выбрать вход (I2S, Coaxial, Optical), режим работы ЦФ (Sharp roll-off filter, Slow roll-off filter, Short delay sharp roll off filter, Short delay slow roll off filter и Super Slow Roll-off Filter) , и далее Sound Control (1,2,3).
Выбор блоков данных осуществляется нажатием на штырь энкодера (центральная кнопка)
После выбора нужного режима состояние и тип данных сохраняются до нажатия кнопки или вращения энкодера.
Работа по циклу в обоих направлениях, то есть например 1-2-3 или 3-2-1.
А когда на ноге DSD/PCM появляется логический 0 от источника, то логика похожа.
Так как DSD передается по I2S, то выбор других входов не доступен.
Зато можно поменять DSD Sample Rate (2,8Мгц — DSD64, 5,6Мгц — DSD128 и 11,2Мгц — DSD256), затем частоту среза встроенного ФНЧ (50Кгц или 150Кгц) и как и в РСМ - Sound Control (1,2,3).
Когда я это все отрисовал на бумаге, я впал в депрессию...
Как это все программировать?
С чего начать?
На подсказки от программиста я не сильно надеялся, у него был другой взгляд на эти меню, да и времени мной заниматься было не много. Так бы мы пилили эту прошивку еще пару месяцев.
Я не могу так долго ждать!
Поэтому разобью задачу на части.
Начну править скетч.
Большую часть вытащил из старого, от AK4399.
Добавил много флагов, а почему — будет понятно далее.
Здесь же описаны счетчики для кнопки select и переменные для энкодера.
Секция setup тоже немного усложнилась.
Заданы все флаги, устанавливаемые при старте.
Названия флагов даны от сокращения названий режимов — так понятнее.
Распределены ноги, состояния, задан режим SPI и подключено прерывание на обе ноги энкодера.
↑ 2. Энкодер
Несомненно, основная задача всей программы — управление.А энкодер — главный инструмент. Пришлось лезть в сеть за примерами.
Используют энкодер в среде программирования по разному. Например мониторят состояние ног, к которым он подключен и анализируют это состояние программно. Используют одну ногу для прерывания, вторую как обычный вход и тоже анализируют. Ну и еще различные варианты.
Честно скажу — работа большинства из них мне не понравилась, а некоторые откровенно глючили. И я случайно наступил на понятие Код Грея (Gray Code). Этот код как нельзя лучше подходит для слежения за состоянием энкодера.
Детально его описывать — долго и нудно, просто можно сказать, что в данном случае отслеживаются четыре устойчивых состояния на ногах энкодера — 00,01,11,10.
И предполагается, что эти состояния меняются в строгой последовательности.
Таким образом можно отследить, куда крутим энкодер, а потом посчитать на сколько тактов.
ISR_ENC — подпрограмма обработки энкодера, вызвыаемая через прерывание.
Прерывание вызывается по изменению логического уровня (CHANGE) на ноге INT0 или INT1
Значение newpos — это как раз счетчик «щелчков» энкодера.
Следом идет секция loop
Здесь, в зависимости от логического уровня на ноге DSD/PCM управление передается соответствующей подпрограмме.
Они во многом похожи, поэтому расскажу на примере подпрограммы РСМ.
↑ 3. Флаги
Как я написал выше, при работе программы я использую флаги.Может это и криво. И косо. Но для меня — начинающего программиста — это пока что понятнее и проще, чем работать с eeprom или оперативкой напрямую.
Может потом...
Для каждого режима, состояния и значения есть свой флаг, поэтому их так много и описано в начале.
Зачем он вообще нужен?
Вкратце — чтоб не долбить ЦАП посылками и не обновлять экран с каждым циклом работы программы. Программа просто опрашивает флаги по циклу, и если они изменились, то отрабатывает процедуру, и снова возвращается к опросу флагов.
Начнем с MUTE.
Следует заметить, что в отличие от AK4399, AK4490 не имеет внешнего управления MUTE в режиме DSD.
Оно работает только тогда, когда в потоке прилетит 8192 пустых отсчета.
Тогда она сама уходит в MUTE. Этот процесс тоже настраиваем через регистры.
Но отдельной подпрограммы это не требует. MUTE есть только в РСМ.
А так как регистр SMUTE находится в одном блоке с регистром SD, который отвечает за режим ЦФ, то перед снятием или установкой сигнала MUTE проверяется режим ЦФ, точнее состояние бита SD.
То есть логика такая:
Проверяем флаг MUTEFlag, а затем проверяем наличие включенного или выключенного бита SD, затем отправляем посылку SPI . В зависимости от установленного режима ЦФ вводим и выводим ЦАП из MUTE с прежним состоянием ЦФ.
Затем меняем флаг MUTEFlag.
Таким образом процедура повторится всего один раз, до смены флага.
Далее следует процедура подсчета нажатий кнопки select.
Здесь все просто. Считаем нажатия.
Когда доходим до трех — возвращаемся в начало.
При каждой смене счетчика — ставим флаг для нужного режима.
То есть идем по кругу — INPUT Select — DF Select — Sound Control и далее снова на INPUT Select .
Передаем управление модулю опроса энкодера.
Здесь нам пригодится параметр newpos — о котором я писал выше в подпрограмме опроса энкодера.
Так получилось, что за один «щелчок» мой энкодер выдает 3,4,4,3,4,4 смены значений.
Такой вот странный глюк. Чисто механический. Поэтому значение newpos я делю на 4, чтоб получить число pos = 0-1-2-3 и так далее при повороте. Незначительное отклонение сглаживается делением до целого числа.
Для селектора входов нужно три значения, поэтому считаем 0-1-2, потом возвращаем на 0.
Если крутим в обратную сторону, то при значении pos= -1 выдаем значение 10, что при делении на 4 дает 2 с остатком и округляется до 2. То есть 0-2-1-0 и так далее.
Для выбора режима ЦФ нужно перебрать пять значений, поэтому счет будет 0-1-2-3-4-0.
Соответственно счетчик ставлю до 4х и значение newpos при pos= -1 уже будет 16.
И согласно значению pos ставим нужные флаги.
Все остальные блоки выбора режимов построены по аналогичной схеме, поэтому описывать их не буду — они есть в итоговом скетче.
↑ 4. Задание режимов работы
Сначала ставим ЦАП в режим РСМ I2S 24bit.Для того, чтобы задать тот или иной режим работы ЦАП, нужно отправить на него определенную посылку данных по SPI.
Поэтому каждый режим работы, режим ЦФ или режим SQ задается отдельной процедурой.
Они во многом похожи и отличаются только набором используемых флагов и набором передаваемых данных.
Логика работы включения режима РСМ:
Проверяем флаг DSDFlag.
Если он не равен единице, то на всякий случай загоняем reset, затем на всякий случай (вдруг она уже была в DSD) отключаем режим DSD, а потом задаем режим PCM I2S 24bit.
Далее подключаем вход I2S в селекторе, и расставляем флаги для нужных режимов работы.
Логика на примере установки режима ЦФ Super Slow.
Проверяем флаг PCMDFSSLOW на логическую единицу. Если до этого он не был равен единице, то отправляем набор посылок. Ставим регистр control2 по умолчанию, ставим регистр control3 по умолчанию, ставим регистр control4 по умолчанию (это предотвратит нахождение этих регистров в уже установленных значениях), а затем ставим регистр control4 ,бит SSLOW в состояние единицы.
После этого меняем флаг записи в дисплей — WRITELCDFlag.
Затем задаем значение временному флагу PCMDFSSLOW0 значение флага PCMDFSSLOW- он у нас отработал и повторно отработать не должен — равен единице.
И далее ставим значение флагов для остальных настроек ЦФ в нули, чтоб после установки ЦФ в режим Super Slow, они не попытались его поменять без моего ведома.
Для остальных настроек сделано аналогично.
Таким образом процедура записи по SPI отрабатывает однократно и не работает до повторной смены соответствующего ей флага.
↑ 5. Запись в дисплей
Тут у нас самый главный — флаг WRITELCDFlag.Если его не будет, то дисплей будет мерцать в такт работы подпрограммы рсм или dsd.
Это не красиво и напрягает.
Поэтому будем писать в дисплей только тогда, когда выставлен в единицу флаг WRITELCDFlag. И как только мы в дисплей чего-то написали — срочно ставить его в значение ноль.
Тогда цикл записи будет однократный, и до смены режима экран будет статичный.
В эту же процедуру включен выбор селектора входов — пишем в нужные ноги нужные нам нули или единицы, и сигнал идет либо с I2S входа, либо с SPDIF.
Ну в общем как-то так. Чего то взял с сети, чего то накумекал сам. Две недели неспешного ковыряния и можно проводить запуск и тестирование.
Можно заливать и пробовать. Что и было успешно сделано.
AK4490 отработала нормально смену режимов PCM/DSD. Не удивительно, ведь эти регистры одинаковы и для AK4399. Меняем или добавляем только остальное.
И это все надо проверить.
В принципе все работает, немного надо допилить меню, точнее поровнее расставить символы на индикаторе. Но это мелочи, главное теперь проверить функционал.
На тестирование был приглашен Программист, и незамедлительно прибыл с официальным визитом. Ради такого события можно отложить текущие дела. Скатав за ним слегка помятую ковровую дорожку и разогнав оркестр — приступили к тестированию.
Увидев мое кривое меню — товарищ Программист сказал, что это колхоз. Причем в фазе распада.
И надо делать не так.
Достал свой комп и, скатав себе мой тестовый скетч, начал активно переписывать управление меню.
В его понимании структура меню должна быть древовидной, по принципу файловой системы на компьютере.
Вход и выход в подпункты должны происходить при нажатии на энкодер, а смена режимов — его поворотом. Подтверждение — снова нажатие.
Я понимаю — так и надо по идее. Но вы представляете древовидную структуру меню на дисплее 16*2? Я нет. А он представлял! И почти допилил модуль для РСМ, с некоторыми глюками даже пытавшийся работать. Но так как время визита подходило к концу, то пришлось процесс свернуть.
- Ладно, я дома погляжу и допилю логику — сказал он мне и удалился.
- А когда ждать результат? - с надеждой сорокалетней девственницы спросил я.
- На днях, может в выходные! - донеслось до меня в щель закрывающейся двери из коридора.
- Супер. Снова ждать?
Но у меня есть мой исходный скетч, его и залью.
Пробное прослушивание показало что:
1. Я глухой.
2. Я глухой потому, что условия прослушивания на работе не сильно подходят для того, чтоб расслышать нюансы работы ЦФ.
3. Программа не работает и ЦФ не переключает.
Чтобы выяснить, какой из пунктов правильный, был снова вызван на следующий день с официальным визитом мой коллега-программист, прихвачен портативный DSO для слежения за обменом SPI, а также все имевшиеся в наличии наушники.
Пока Программист решал свои вопросы на работе, я пощупал обмен по SPI. Вроде все верно, работает и посылки идут. Идут разные и вроде даже- насколько можно разглядеть на экране DSO – соответствуют запрашиваемым режимам.
И вот наконец все собрались. Одев мои верные Beyerdynamic DT990, Программист стал вдумчиво переключать треки, режимы, ставить и снимать паузу.
Потом я предложил ему Beyerdynamic DT770. Процесс в точности повторился.
- У тебя нифига не работает! - вынес вердикт Программист, снимая наушники — Не может быть, что не слышно разницы, опять наверное накосячил где-то?
- Все проверил — SPI работает как надо — в тайне радуясь тому, что тут уже не один глухой, сказал ему я.
- Давай проверять!
Проверка не дала ничего. Вроде все верно. Но сомнения остались.
- Придется мне писать прогу с нуля! - сказал Программист — Чужой код всегда загадка!
- Я состарюсь раньше и выйду на пенсию, чем ты напишешь новый код — не остался в долгу я.
Но тут я вспомнил! Как проверяется отклик ЦФ и работа передискретизации? Конечно же осциллографом и тестовым сигналом!
Вот сейчас то мы все и увидим. Делаю стандартную синусоиду 1000Гц 0Дб.
Включаю вывод и начинаю переключать режимы ЦФ: Sharp roll-off, Slow roll-off , Short delay sharp roll off, Short delay slow roll off — на эране ничего не меняется:
Но как только я переключился в режим Super Slow Roll-off — картинка немного поменялась!
На синусоиде появились легкие «зубцы».
Что-то меняется однако!
А давайте ей дадим то-же, но прямоугольное!
Там точно будет видно!
Ставлю меандр 1000Гц 0Дб:
Sharp roll-off:
Красиво!
Slow roll-off:
Ага! Работает!
Short delay sharp roll off:
Еще интереснее!
Short delay slow roll off :
И в заключении Super Slow Roll-off:
Идеальный прямоугольник!
(здесь не обращайте внимание на порядок файлов на картинках — измеряли именно в том порядке, а записи в файл делали уже после).
- Ну и у кого тут программа не работает?
- Н-да, работает!
Теперь давай глянем работу передискретизатора. Запускаю синус 18000Гц 0Дб. Частота от балды, специально не выбиралась.
Sharp roll-off:
Нормально!
Slow roll-off:
Тут пошли пропуски.
Short delay sharp roll off:
Short delay slow roll off:
И в заключении Super Slow Roll-off:
УхЪ! Судя по всему, в режиме Super Slow Roll-off влияние ЦФ настолько минимизировано, что получается практически NOS вариант!
Идеально для любителей сравнить звучание с разными фильтрами и без оных.
Ну а теперь эксперимент номер два — поглядеть, что такое магическое «Sound Control Settings».
В даташите про это не сказано ничего, на сайте производителя тоже никак не упоминается.
Но что только мы не подавали на вход — не удалось увидеть разницу между режимами 1-2-3.
Это точно никак не связано с работой ЦФ. И на слух пока тоже не найдено заметных различий.
- Ладно, надо слушать в других условиях — сказал мне Программист.
- Сначала корпус надо запилить, а потом уже слушать — вяло возразил я.
- Но все равно твой тип меню неправильный! - он был непреклонен.
- Вот когда мы с тобой
К сожалению, работу в режиме DSD оценить приборами не получилось, нет ни тестового DSD диска, ни программы, способной сгенерить тестовый DSD сигнал. Буду полагаться на свои ощущения.
К тому же у меня не нашлось контента DSD, выше DSD64. Поэтому как отреагирует AK4490 на смену частоты потока — я не могу пока сказать. То есть смена режима не влияет никак на звук.
↑ Корпус и компоновка
Далее можно заняться и корпусом. Потому как программные доработки можно будет делать уже после полной сборки устройства.Энкодер поставил справа от дисплея, так удобнее крутить и видеть результат на экране.
Внутри ничего нового, расположение блоков как и в предыдущих конструкциях.
Ну и общий вид для истории.
Теперь можно ставить с стойку и слушать.
К сожалению, измерений и прочих графиков не будет...
Creative, использованный мной для измерений, пал смертью храбрых. Встроенный DC-DC для формирования отрицательного напряжения всех ОУ в АЦП сначала стал включаться через раз, а потом вообще перестал работать. Вот такой брак после окончания срока гарантии. Так что пока я без измерилки.
↑ В заключении - забавная проза жизни
Мой товарищ Программист пошел немного дальше, и все таки решил узнать, что за магическая настройка — Sound Control Settings. И как вполне нормальный человек, написал письмо в службу технической поддержки фирмы АКМ.В результате...
Да ладно, выдыхаем. Мы так и не узнали, что это такое. Зато возбудились маркетологи.
Письмо пришло уже не из техподдержки, а от человека с русской фамилией и уже на русском языке. Он потребовал указать — в какое устройство, в каком количестве и какого типа продукция АКМ планируется нами использоваться. И только после этого пообещал дать развернутый инженерный ответ.
Какая зависимость размера партии и особенности работы микросхемы — мы не поняли, но и уточнять не стали — мы же не массовый производитель и покупатель, что с нами делиться секретами то? К тому же я вспомнил истории с заказом образцов.
В общем видимо так и останемся мы в неведении — что же такое Sound Control.
Ну зато что-то получилось и даже работает.
По сути это просто модуль управления и может быть адаптирован под любой ЦАП с управлением по SPI. Достаточно только немного изменить программу.
↑ Файлы
Как всегда, схема и файлы здесь:🎁ak4490.7z 181.54 Kb ⇣ 255
↑ Постскриптум
Это цветные модули TFT: 2,4 дюйма 320*240 и 1,44 дюйма 128*160. Конечно не OLED, зато цена приемлемая.
Хочу пощупать и может что-то наваять, используя Arduino.
Ну а пока всё.
С уважением, Алексей.
Камрад, рассмотри датагорские рекомендации
🌼 Полезные и проверенные железяки, можно брать
Опробовано в лаборатории редакции или читателями.