Я долго колебался – писать эту статью или нет. Это решение нужно было принять — основываясь на плюсах и минусах. Минусы были в том, что я в принципе ничего нового не создал и не изготовил. Получилась лабораторная работа студента-программиста, и то нагло списанная у одногруппника для получения зачета.
Но и плюс был весомый – все же процедура конфигурирования если и описана где-то в сети, то либо поставляется автором в виде готового .bin или .hex файла для прошивки контроллера (определенной модели) и заточена под конкретную конструкцию и функционал. А так как Arduino – гибкая платформа и вполне доступна для таких «ламеров» как я, то любому желающему будет несложно «допилить» ее под себя.
И я решил – опишу свои движения, может кому-то это будет полезно.
Содержание статьи / Table Of Contents
Он ответил просто: «Бери пару, программу напишем!».
После такого смелого для меня утверждения, я не смог удержаться и сделал заказ на АК4399. Пока они спешили ко мне, я углубился в изучение материалов по ней. Что пишут люди, как используют. То, что я выяснил, немного шло в разрез с моими планами, но было более разумно.
Все дальнейшее описание будет основано на примере АК4399. Но контроллер можно использовать с любым другим ЦАП, поддерживающим программирование по SPI.
Итак. Нет смысла использовать ее в режиме моно – прирост качества будет небольщим. Больше внимания надо уделить питанию. Особенно питанию аналоговых выходов. Для этого монстры цапостроения используют малошумящие схемы стабилизаторов питания.
Также приветствуется и раздельное питание каналов.
Поэтому в процессе концепция поменялась.
Я не буду описывать ее здесь – это тема отдельной статьи, да и в принципе меняется только модуль ЦАП, а питание, цифровые входы и обработка мастерклока – остаются аналогичными моим предыдущим конструктивам. Например — ЦАП на сдвоенных РСМ1794. Я в нем выкинул модули ЦАП и выхлопа и заменил их на одну плату на АК4399. Поэтому она и получилась квадратной.
В процессе изучения даташита, возникла идея попробовать такую диковинку, как DSD.
Что это такое, можно прочитать в сети. Для меня же встала задача – как и откуда вытащить этот формат. Что это будет компьютер – это однозначно, но что компьютер должен еще и выдавать сигналы DSD – оказалось проблемой.
Недолгое изучение материалов по теме и выяснилось следующее:
Нужен USB интерфейс на базе процессора XMOS.
Мой текущий источник на базе Edel USB Interface не поддерживает нативно DSD, только DXD или DoP.
# накидал я тут терминов…
# я снова не буду описывать как передается DSD поверх I2S – это есть в сети и даташитах.
# что такое DoP и с чем его едят – тоже хорошо разжевано.
Моя проблема на тот момент – отсутствие источника USB to PCM/DSD. И я его нашел и купил – это Audiophonics XMOS USB interface.
Выбрал я его по следующим критериям: заявлена поддержка DSD на тех же ногах, что и у АК4399, то есть не потребуется мультиплексирование или отдельный разъем, поддержка внешнего тактирования, а также параллельная работа SPDIF выхода в режиме РСМ.
Минус только один – полное отсутствие какой-либо документации. Только надписи на плате и email производителя.
В общем к моменту приезда этой платы у меня был готов ЦАП с возможностью работы в хардварном режиме, а также с переключением в софтварный режим для конфигурации по SPI.
Списавшись с производителем, я все же разузнал, что и как надо правильно подключить к плате и как она должна работать. Вывел звук в режиме РСМ и мощное «ПШШШШШШШ» в режиме DSD.
Плата немного «допилена» по рекомендации производителя для приема внешнего MCLK от ЦАП — потому как они сами этот момент не проверяли, но в спецификации заявили.
Все это оформлено в отдельный корпус и с платы выведены нужные выходы для получения автономного источника.
Осталось дело за малым – программирование.
Мой товарищ- программист был занят по работе, поэтому весь процесс запуска прошел мимо него стороной.
Но собирать пыль очередному ЦАП на моем столе я не мог позволить – поэтому начал доставать Программиста:
— Ну что, какой мне контроллер купить? В чем будем
— У меня есть «ардуина»… Мега там какая-то, не помню, дома гляну – сказал Программист, и на два дня уехал по рабочим делам.
— Офигеть — сказал я, и на весь день погрузился в изучение матчасти.
Что такое «эта ваша ардуина» — я слышал, но не видел и не знал. Изучение матчасти немного прояснило ситуацию.
Но не до конца. Вариантов «ардуин» было так много, что я сначала просто не знал, за что схватиться. Во первых, никто и нигде не рассказывал, будет ли контроллер работать вне платы. Как залить этот самый «скетч» в чистый контроллер?
Ситуация стала меня напрягать все сильнее. Даже если мы запрограммим ее, то ставить большую отладочную плату внутрь ЦАП мне не улыбалось – просто не было места, разве что платы «мини», но и хотелось сделать свою плату под свою задачу.
Пинком под зад в выборе платы стала фраза Программиста:
— Заказывай ардуину в нете, у меня моя чего-то не шьется, загрузчик слетел похоже…
— Да, «Камазы» с водкой переворачиваются на нашей улице ежедневно, празднику нет конца – только и смог промолвить я в ответ.
Это еще ждать месяц, потом месяц будем программить такими темпами – короче слой пыли на новом ЦАП придется сметать лопатой. Будем разбираться своими силами или разбирать ЦАП. В общем поехал я в магазин наш местный на предмет приобретения «ардуины». Очень уж свербило и чесалось в одном месте.
И вот тут мне повезло. Мало того, что они были в магазине в наличии, так еще и можно было повыбирать. Встав в позу красной девицы на шоппинге, и игнорируя предложения продавца мне помочь (чем мне можно помочь, если я не знаю, что я хочу?), я тупил у витрины и понимал – надо принять решение! Вот вам хорошо это все читать, а мне было не весело!
Выбор пал на «Arduino UNO» на базе ATMega328 в корпусе DIP! В сокете моем любимом… Я уже тогда догадывался, что именно сокет спасет отца русской демократии. Не зря же он там установлен то?
На следующий день я задал вопрос монстру программирования:
— Ну что, я пробую SPI подключить?
— Не работает SPI на ардуине! Я пробовал! Пока не написал топорно перебором кода, не заработало – Программист был категоричен… Тут я добавлю, что он что-то там программил для SPI, поэтому слова его для меня были ударом по почкам.
— Завтра заеду к тебе – попробуем.
Ага, это до завтра я не буду спать… И есть… И, возможно, даже пить — в ожидании чуда? Что мне нужно именно SPI, я уже понял, изучая матчасть по запросу «Arduino+SPI». Но почему оно не работает то?
Хорошо, у меня есть плата Arduino, есть готовый к бою ЦАП, есть поддержка DSD.
Сам по себе процесс обмена данными не сложный и красиво разрисован в даташите:
Беру из примеров код инициализации SPI протокола, подключаю плату к компу, ставлю на стол осциллограф и начинаю программировать.
Сам по себе обмен по SPI подразумевает двунаправленную передачу данных. Если контроллер выдает данные, а устройство принимает их, то используется вывод контроллера MOSI — Master Output Slave Input. При чтении с устройства — MISO — Master Input Slave Output. АК4399 не поддерживает чтение — только запись.
Так же нужно выбрать, какой вывод будет отвечать за включение режима программирования — так называемый Slave Select. У АК4399 — это CSN.
По умолчанию у Arduino это вывод 10 (SS).
В общем соединить Arduino → AK4399 нужно так:
10 (SS) → (6)CSN
11 (MOSI) → (9)CDTI
13 (SCK) → (8)CCLK
Структура самого файла программы — «скетча» — тоже довольно проста. Сначала идет описание всех констант, библиотек, переменных, выводов и вводов. Все что нужно для инициализации системы.
Следом идет секция void setup {}.
В ней мы описываем режимы работы выходов, входов, флаги и константы, устанавливаемые при старте контроллера.
И главная секция void loop {}
Здесь размещается основной код. То, что исполняет контроллер в процессе работы. Из названия видно, что программа крутится в цикле.
Код оказался не сложным.
Начало.
Я решил не выходить за рамки примеров и обозначил данные, которые надо передать по SPI в явном виде, то есть в двоичном. «B» — binary. Так мне самому понятнее. Можно указать и шестнадцатеричный —, но склад ума не позволяет сходу переводить в уме форматы.
Если глянуть в даташит на АК4399, то видно, что в посылке идет сначала адрес, потом сами данные регистров.
Казалось бы в чем проблема — передавай 0010000000000111 и будет счастье.
Но контроллер может передать одной командой только 8 бит. Чтобы получить 16, нужно посылку делать из двух частей, и посылать эти части одну за другой. Сначала адрес, потом данные.
Продолжение.
Здесь описана секция setup.
Определяем пины. Нумерация как на плате Arduino.
Нога «0», например, конфигурируется как вход, на котором меняется логическое состояние от типа потока от источника- DSD или PCM.
Ноги «10,11,13» отданы под SPI, нога «12» — reset для ЦАП.
Далее идут режимы SPI.
SPI_MODE — режим передачи. Всего их 4. Отличия расписаны в документации.
MSBFIRST — порядок передачи бит.
SPI_CLOCK_DIV — скорость передачи. Значение определяется делением тактовой частоты на коэффициент (здесь «128» — самое медленное)
Продолжение.
Здесь сам процесс записи, начинается с SPI.begin (). Затем проверяется состояние входа «0» и происходит отправка той или иной посылки в ЦАП.
Подключаю осциллограф на 10 и 11 ногу ардуины.
То что я увидел на экране после загрузке «скетча» оказалось именно таким SPI, как нарисовано в даташите по АК4399.
Теперь перевожу АК4399 в режим serial. В таком виде по умолчанию она работает в режиме 24bit MSB justified, а это немного не подходит для моего режима 24bit I2S, что выдает мой источник. Ну да, звук есть, но с треском и шипением. Включаю «ардуину». Щелчок в наушниках и следом чистый звук!
YES!!! АК4399 явно отреагировала на мою посылку и переключилась в режим I2S!
Я себя представил в тот момент великим программистом! Чуть со стула не свалился от счастья!
А как там режим DSD. Это же самое интересное! Меняю тип вывода в настройках foobar2000, запускаю проигрывание. Источник переключается в режим DSD. Мощное «ПШШШШ» после включения ЦАП говорит о том, что поток дошел до ЦАП, но он его не понимает. Надо его перевести в DSD mode. Включаю «ардуину» — щелк, и голос Алана Парсона из наушников возвещает о моей победе над глупой железкой!
Да, время, деньги, силы потрачены не зря и что-то начало нарисовываться.
Теперь дело за малым – сделать так, чтоб контроллер менял режим по сигналу от источника. Для этого нужно код перенести в секцию void loop {}.
А она, как видно выше — у меня пустая…
Тупо перенести код туда не получилось, хоть компиляция и прошла успешно, но ожидаемой реакции ЦАП не было.
— А ты в курсе, что я могуч? — Написал я сообщение Программисту – SPI то у меня работает!
— Серьезно? Ну ты монстр! – он был явно удивлен.
— Но дальше я туплю, без тебя не справлюсь.
— Ладно, жди, завтра заеду.
Ну хорошо, результат уже есть, и пока я хожу по кругу, попробую, что еще может эта «ардуина». Подключил дисплей 16×2. Попробовал повыводить разные фразы и надписи. Работает.
С тем обилием примеров в сети — это оказалось проще, чем SPI.
Тут же родилась идея, сделать уже не просто конфигуратор, а полноценный модуль управления ЦАП с селектором входов и индикацией режимов работы.
Блок-схема:
И я начал рисовать схему и плату. В этот момент я не был уверен, что ATMega сможет работать вне платы Arduino, но изучив документацию — все же рискнул. Просто как обычно выяснилось — никто таких задач себе не ставил — просто использовал готовую плату Arduino.
↑ Схема модуля управления ЦАП с селектором входов и индикацией режимов работы
Идей сразу вылезло масса. Убрать галетник как селектор входов, индикация режимов само собой, и плюс к этому возможность измерения и выдачи на экран текущего значения частоты семплов для PCM и для DSD.
Я настолько сильно раскатал губу, что у меня закончились ноги у контроллера, заклинив намертво губозакаточный станок.
На схеме все ноги подписаны, IC2- конвертер уровней с 5В на 3,3В. Так как контроллер запитан от 5В, а в ЦАП питание мультиплексоров 3.3В — это просто необходимо.
Кварца на 16 МГц у меня не нашлось, ехать покупать было лень, зато нашлось несколько точных генераторов на 16.000000МГц, поэтому на схеме изображено два варианта. На плате тоже. Логические уровни для режимов PCM\DSD и Mute указаны возле соответствующих выводов.
Поискав в сети примеры измерения частоты, и поиграв с ними я понял, что в лоб эту задачу не решить. Через таймеры оно работает медленно, а через простой счет импульсов — большая погрешность.
Пока решив отложить это, я прикрутил кнопки и LED для переключения входов и индикации выходов. И сел в ожидании чуда, точнее приезда настоящего программиста.
Он, как и обещал, приехал на следующий день. Обвинив меня в некомпетентности
Оказалось, что для выборочной работы SPI, в зависимости от состояния ноги выбора режима, надо ввести так называемые «флаги». Проверяя которые в цикле, контроллер будет выполнять только тот код, что соответствует этим флагам.
↑ Итак, креатив попер!
Я буду давать небольшие пояснения.Ввели библиотеку для LCD дисплея. Добавили отдельно программирование режима MUTE. Ввели флаги. Здесь описание uint8_t простое число, которое присваивается каждому флагу. Флаги ввели для каждого режима работы, включая запись в дисплей. Но об этом ниже.
Здесь описан setup. Вместе с описанием выводов здесь задаются значения всех флагов, которые будут выставлены при старте. Обратите внимание — DSDFlag и MUTEFlag у нас задан значением 2, так как мы не знаем, что будет на входах PCM\DSD и MUTE при старте, и после чтения состояния соответствующих входов — отработает нужная процедура далее по тексту.
Больше всего я переживал, что контроллер вне платы Arduino не захочет включаться и работать, но все мои опасения оказались напрасными!
Осталось проверить работу кнопок.
А также корректную смену режимов.
И запихать девайс в корпус.
— Ну, а где частотомер? — спросит пытливый читатель.
Эта часть проекта зависит не от меня, поэтому буду ждать программиста. Пока код занимает 10% от объема памяти контроллера, поэтому его можно долго и упорно «допиливать». Будем отлаживать на готовом проекте, благо ничего менять в схеме и в оформлении не потребуется. Только прошивка —, а ее можно модифицировать как угодно.
↑ Итого
В заключении, чтобы повествование было полным, пару слов про звук.Ну что продукция АКМ мне нравилась издавна, я уже говорил. Мне вообще нравится их инженерный подход к делу. Очень детальный даташит, грамотная распиновка выводов, за исключением выходов, в одном канале приходится все время перекрещивать выходы, хороший, не утомляющий звук.
Но про DSD говорить пока рано, очень мало контента, и тот, что доступен, является, как правило, ремастерингом уже выпущенных на CD альбомах, это, например, сразу слышно даже по шуму мастер-ленты в начале и конце композиции. Но зато современная музыка, записанная уже на современном оборудовании звучит конечно очень ярко и насыщенно, но судить о преимуществах и недостатках пока мне сложно — мало материала отслушано.
Но похоже за этим форматом есть какое-то будущее, а значит иметь его поддержку в своем ЦАП не помешает.
↑ Файлы
Полный скетч программы и схема с платой здесь:20-04-2016 Обновил архив с новым именем скетча.
🎁datagor4490.7z 32.85 Kb ⇣ 200
Ну, а пока на этом все.
Просьба тем кто «в теме» не пинать ногами — это мой первый самостоятельный проект на МК и первое за много лет серьезное программирование.
Продолжение последует.
С уважением, Алексей.
Камрад, рассмотри датагорские рекомендации
🌼 Полезные и проверенные железяки, можно брать
Опробовано в лаборатории редакции или читателями.