Цифровой выход S/PDIF на FPGA

ToslinkЗдравствуйте! Сегодня я расскажу о протоколе передачи цифрового звука по интерфейсу S/PDIF и покажу, как его можно реализовать на FPGA с использованием языка описания Verilog HDL.

Я новичек в мире FPGA, поэтому приведенные коды на Verilog могут быть неоптимальными. Строго не судите.

S/PDIF разработан на основе профессионального стандарта AES/EBU, но отличия несущественны и, как мы увидим далее, заключаются лишь в «ином» значении сервисных битов. Разъемы тоже отличаются, но это уже чисто маркетинговые игры.
S/PDIF (IEC 958) первоначально применялся в CD/MiniDisc плеерах, но впоследствии его стали использовать в качестве основного способа соединения аудио компонентов. S/PDIF чисто цифровой интерфейс, поддерживающий одностороннюю передачу данных. В качестве среды передачи используется либо коаксиальный кабель, либо оптический.
S/PDIF поддерживает разные частоты дискретизации. Для того, чтобы по одному кабелю передать и данные и тактовый сигнал, используют Biphase Mark Code (Манчестерское кодирование) – разновидность фазовой модуляции.
Посмотрите на пример ниже:

BMC

Как видите, логическая единица кодируется двумя фронтами («переходами через ноль»), а логический ноль — одним.
Для синхронизации используются специальные последовательности ячеек (cells), называемые Заголовками (Preamble).
Данные передаются блоками, каждый блок разделен на 192 кадра, кадр делится на два (если канала два) суб-кадра — по одному на канал. Я изобразил структуру на рисунке:

S/PDIF блок

Каждый суб-кадр начинается с заголовка для синхронизации. Заголовки бывают 3-х типов — B, W и M заголовки. Блок всегда начинается с суб-кадра с B-заголовком, который содержит информацию канала А (левого). M-заголовок также маркирует суб-кадр с информацией о канале А (левом), но никогда не является началом блока. W-заголовок маркирует суб-кадр с информацией о канеле Б (правом), в случае, если каналов больше двух, то W-заголовок может маркировать другие каналы, но только не канал А.

Таблица заголовков

Подскажите, как по-нашему сказать «cell». Понятно, что прямой перевод — ячейка. Но как-то это не звучит. Поэтому я так и буду называть их — cells.

В нормальном S/PDIF потоке данных вне зависимости от их значения, никогда не возникнет ложных заголовочных последовательностей.
После заголовка идут 24 бита информации (20-и битный сэмпл и 4 бита дополнительной информации, но сэмпл также может быть 24-х битным). И 4 сервисных бита.
  • Бит V – Validity. Бит корректности. Если он взведен, то ресивер не должен использовать этот сэмпл.
  • Бит U – User data. Тут содержится какая-либо Manufacturer-specific информация.
  • Бит C – Channel status. См. Ниже.
  • Бит P – Бит четности. Вычисляется для текущего сэмпла вместе с битами V/U/C.
Так как блок состоит из 384 суб-кадров, то в одном блоке можно передать 48 байт сервисной информации (в бите Channel Status), но из-за того, что в двух суб-кадрах эти биты всегда одинаковые, то мы имеем 24 эффективных байта. Структура показана в таблице:

Биты Channel Status

Оставшиеся биты зарезервированы.
Теперь давайте создадим передатчик S/PDIF. Реализовать его на микроконтроллере в принципе можно. Но в данном случае мы имеем критичное к времени выполнения приложение, и возникшее в неудобный момент прерывание приведет к сильному увеличению джиттера (дрожанию фазы). Поэтому такие задачи лучше всего реализуются на FPGA, что мы и будем делать.
При реализации я не ставил перед собой цель создать полноценный S/PDIF трансмиттер, учитывающий все особенности, поэтому допустил ряд упрощений (конечно на работоспособность это не повлияло). Я хотел показать, насколько просто подобные задачи реализуются в железе и как производители за такие (как оказалось) элементарные функции накручивают цену на конечные продукты.
В качестве языка описания используем Verilog HDL.
Я буду использовать плату от TerasIC Technologies DE2-115 с Cyclone IV FPGA на борту. В качестве источника выступает плеер сотового телефона, аналоговый сигнал будет оцифрован кодеком WM8731, который установлен на этой плате.
Кодек отдает оцифрованные данные по интерфейсу I2S, а конфигурируется по шине I2C. В этой статье я не буду описывать работу с этим кодеком и процедуру извлечения данных левого/правого каналов (i2s de-serializer), так как это материал отдельной статьи.
Частоту дискретизации выберем 48 кГц, разрядность сэмпла 16 бит.
Теперь надо придумать, как мы будет выводить кодированный поток SP/DIF. Паять что-либо мне неохота, поэтому я выбираю оптический способ. А в качестве оптического трансмиттера я буду использовать самый обычный красный светодиод на плате. Да-да, вы не ослышались — обычный светодиод. Они прекрасно работают на мегагерцовых частотах!

Тактовая частота генератора S/PDIF равна 2 * 64 * 48 000 = 6.144 МГц. Несущая — 3.07 МГц.
Итак, какие сигналы будут у модуля:

  1. Вход тактовой (несущей) частоты;
  2. Данные левого канала (16 бит);
  3. Данные правого канала (16 бит);
  4. Выход — запрос новых сэмплов;
  5. Выход кодированного сигнала BMC.

module spdif_out (clock,
                        left_in,
                        right_in,
                        next,
                        spdif);


Создадим два счетчика, один 6-битный будут переполняющийся от 0 до 63 — счетчик битов в суб-кадре. И второй 9-битный от 0 до 383 — счетчик суб-кадров в блоке.

// переполняющийся счетчик битов (0..63)
reg [5:0] bit_cnt; always @(posedge clock) bit_cnt <= bit_cnt + 1'b1;
 
// счетчик суб-кадров (0..383)
reg [8:0] subFrame_cnt;


Счетчик суб-кадров будем увеличивать на заднем фронте тактового сигнала. При обнулении счетчика битов (начало нового суб-кадра) будем формировать этот самый кадр в 64-х битном векторе subFrame.
Сервисный бит Channel status оставим в покое, пусть они будут равны 0 для всех суб-кадров. Ресивер не обидится, просто поток будет с «пометкой» защиты от копирования.
Теперь организуем выбор каналов. Смотрите, если суб-кадр нечетный, то это левый канал (А), а если четный — правый (Б).

// сэмпл
wire [15:0] sample = subFrame_cnt[0] ? left_in : right_in;


По такому же принципу надо выбрать Заголовок (Preamble).

// заголовок суб-кадра (B - M - W Preamble)
wire [7:0] preamble = (subFrame_cnt == 9'd383) ? 8'b10011100 : (subFrame_cnt[0] ? 8'b10010011 : 8'b10010110);


Поговорим немного о том, как лучше всего организовать BMC кодирование. Есть такой метод, который, если я не ошибаюсь, называется NRZI (Non-Return-to-Zero Inverted), когда лог. единица кодируется изменением уровня, а 0 — без изменений. Для простоты давайте рассмотрим пример.

Пусть нам надо «закодировать» два бита 0 0. Мы разрядим их единицами и получим последовательность 1010. Теперь, последовательно выпоняем операции инвертирования над значением последней cell. Берем старший бит из нашей последовательности 1010. Если он имеет значение 1, то инвертируем предыдущий cell, если 0, то оставляем, потом делаем то же самое со следующим битом. Получаем:

NRZI BMC

Инвертирование проще выполнять операцией исключающее или:

// BMC кодер
always @(posedge clock) spdif <= spdif ^ subFrame[63];

Теперь согласно выбранному алгоритму и формату суб-кадра нужно собрать 64 бита воедино.

// собираем суб-кадр    
        subFrame = {preamble, 16'b1010101010101010,
                                          1'b1, sample[0],  1'b1, sample[1],  1'b1, sample[2],  1'b1, sample[3],
                                          1'b1, sample[4],  1'b1, sample[5],  1'b1, sample[6],  1'b1, sample[7],
                                          1'b1, sample[8],  1'b1, sample[9],  1'b1, sample[10], 1'b1, sample[11],
                                          1'b1, sample[12], 1'b1, sample[13], 1'b1, sample[14], 1'b1, sample[15],
                                          1'b1, 1'b0,       1'b1, 1'b0,       1'b1, 1'b0,       1'b1, parity};
                                          //      V                 U                 C                 P

Бит четности вычисляется так:

// вычисление бита четности
        parity = sample[0] ^ sample[1] ^ sample[2] ^ sample[3] ^
                    sample[4] ^ sample[5] ^ sample[6] ^ sample[7] ^
                    sample[8] ^ sample[9] ^ sample[10] ^ sample[11] ^
                    sample[12] ^ sample[13] ^ sample[14] ^ sample[15];

И теперь приведу код полностью:

module spdif_out (clock,
                        left_in,
                        right_in,
                        next,
                        spdif);
                         
// тактовый вход
input clock;
 
// данные левого канала
input [15:0] left_in;
 
// данные правого канала
input [15:0] right_in;
                         
// предоставить следующий сэмпл
output next; // тут не используется 
 
// сигнал S/PDIF
output reg spdif;
 
// бит четности
reg parity;
 
// суб-кадр
reg [63:0] subFrame;
                         
// переполняющийся счетчик битов (0..63)
reg [5:0] bit_cnt; always @(posedge clock) bit_cnt <= bit_cnt + 1'b1;
 
// счетчик суб-кадров (0..383)
reg [8:0] subFrame_cnt;
 
// триггерный сигнал следующего суб-кадра
wire subFrame_trig = (bit_cnt == 6'b0);
 
// заголовок суб-кадра (B - M - W Preamble)
wire [7:0] preamble = (subFrame_cnt == 9'd383) ? 8'b10011100 : (subFrame_cnt[0] ? 8'b10010011 : 8'b10010110);
 
// сэмпл
wire [15:0] sample = subFrame_cnt[0] ? left_in : right_in;
 
// подготовка нового суб-кадра
always @(negedge clock)
begin
    if (subFrame_trig)
    begin
        // вычисление бита четности
        parity = sample[0] ^ sample[1] ^ sample[2] ^ sample[3] ^
                    sample[4] ^ sample[5] ^ sample[6] ^ sample[7] ^
                    sample[8] ^ sample[9] ^ sample[10] ^ sample[11] ^
                    sample[12] ^ sample[13] ^ sample[14] ^ sample[15];
             
        // собираем суб-кадр    
        subFrame = {preamble, 16'b1010101010101010,
                                          1'b1, sample[0],  1'b1, sample[1],  1'b1, sample[2],  1'b1, sample[3],
                                          1'b1, sample[4],  1'b1, sample[5],  1'b1, sample[6],  1'b1, sample[7],
                                          1'b1, sample[8],  1'b1, sample[9],  1'b1, sample[10], 1'b1, sample[11],
                                          1'b1, sample[12], 1'b1, sample[13], 1'b1, sample[14], 1'b1, sample[15],
                                          1'b1, 1'b0,       1'b1, 1'b0,       1'b1, 1'b0,       1'b1, parity};
                                          //      V                 U                 C                 P
                     
        // счетчик суб-кадров
        if (subFrame_cnt == 9'd383) // 192*2-1
            subFrame_cnt <= 0;
        else
            subFrame_cnt <= subFrame_cnt + 1'b1;
    end
        else
            subFrame <= subFrame << 1'b1; // сдивиг влево на выход
                                           
end
                         
// BMC кодер
always @(posedge clock) spdif <= spdif ^ subFrame[63];
                         
endmodule


Вот и весь код!

Ниже я приведу захваченные анализатором три суб-кадра (начало блока) с работающего устройства:

S/PDIF signal
Приложен в полном размере.

Синтезируем и заливаем в плату. В качестве ресивера выступит Yamaha RX-V2500. Оно работает — смотрим видео на YouTube!

Файлы в топике: real_signal.gif

Комментарии (67)

RSS свернуть / развернуть
Спасибо. Сам занимаюсь подобной проблемой. Только у меня вход + сигма-дельта цап.
0
  • avatar
  • letni
  • 04 декабря 2012, 19:26
Очень интересно! Напишите пожалуйста потом статью про SPDIF вход, поиск заголовков?
0
реализовал вход, закончу проект — выложу все вместе с тестами :)
0
Эта статья, сама по себе, какбэ не представляет интереса. Вот если будет продолжение с описанием всего проекта, тогда да, начинающим пригодится.
0
Ну кому как. Я что-то не находил вменяемого описания протокола на русском языке.
А модуль верилоговский вполне себе рабочий. Нет особого смысла выкладывать весь проект, так как платы у всех разные.
0
Эта статья, сама по себе, какбэ не представляет интереса.
Зря Вы так, как по мне – то интересная статья. Автору, однозначно, большое спасибо.
+3
Автор статьи допустил серьезную ошибку! У него не мигает светодиод, а это -10 к интересу. + отсутствует код мигалки, а лучше RGB мигалки.
+2
Да, это реальный просчет автора :) Ну, зато, хоть мигает на FPGA.
0
Статья полезная. Она подогревает интерес к FPGA в сообществе. Как правильно заметил автор, некоторые вещи проще и правильнее реализовать на логике а не на программном уровне.
Вопросы автору: сколько ресурсов потребовала реализация? Если делать отдельное устройство, то в какую FPGA влезет?
0
Конкретно блок SPDIF занял 92 LE. Полностью проект чуть больше 200 LE.
Думаю влезет в самый маленький MAX II какой-нибудь EPM240. Но мне очень сложно судить, особого опыта нет.

Кстати, конкретно SPDIF модуль можно уменьшить, если чуть оптимизировать- не выделять 64-битный вектор.
0
бляяяяяя, как же я тебе завидую, что у тебя есть нормальная отладочная плата…
0
Я купил ее напрямую у производителя. По студенческой цене (помог друг), но даже с такой ценой ($300) долго не мог решить — выбрать DE0-Nano или эту. Сейчас очень доволен, даже жалею, что не купил и Nano тоже. А теперь уже поздно- за доставку ведь второй раз платить :(
0
Сколько стоила доставка?
0
Уже точно не вспомню, но достаточно дорого, даже для FedEx и DHL дорого. Долларов 60 около того.
Я от WaveShare DHL-ем заказывал, там тоже из Тайваня шло (видимо склад), так за такой же вес взяли всего 30.
0
Не совсем в тему…
Просьба сильно не пинать — в этом вопросе я совсем деревянный, но! Можно ли с помощью ПЛИС реализовать, скажем, мост S/PDIF->UART, или I2S->UART, и влезет ли это дело в какую-нибудь MAX II, например?..
0
можно, но для чего? Битрейты далеко не низкие.
0
(закатывая глаза) Для пропихновения по радиоканалу например… 48 кГц, 16 бит стерео…
Бред, конечно, но все-же!
Согласен, стоимость разработки (да и самой ПЛИС) превзойдет стоимость готового китайского решения.
0
Для пропихновения по радиоканалу например… 48 кГц, 16 бит стерео…
Бред, конечно, но все-же!

Почему берд – предать по радиоканалу оцифрованный звук (48 кГц, 16 бит стерео) не является проблемой (при наличии радиоканала с соответствующей пропускной способностью).
Просто данное решение не имеет (напрямую) к этому отношения.

А что именно Вы хотите реализовать?
0
Некий универсальный модуль, комбайн, если хотите! Чтобы и беспроводные наушники, и WiFi-Internet radio и PMP в одном флаконе…
0
— Постойте, Изя! Что ви делаете?
— А разве вы не видите? Таки вешаюсь, конечно!
— Но зачем же за ноги??!
— За шею пробовал — таки дышать трудно!!!
0
:)

Чем Вас не устраивают готовые/существующие решения для

«беспроводные наушники, и WiFi-Internet radio …»

Можно придумать свое решение, свой протокол. Передать по радиоканалу поток в 48000*16*2 бит/с не является проблемой. Но какой смысл изобретать очередной велосипед? ИМХО, лучше использовать стандартизированное решение.
0
Готовые есть и много! Но вот чтобы и сеть, и звук в одном флаконе…
0
основная проблема будет с синхронизацией. цифровые обертки использовать совершенно недопустимо. даже спдиф как таковой имеет проблему с джиттером. какая она будет, если использовать пакетные протоколы — подумать страшно.
0
Почему недопустимо? Всегда можно запхнуть что-то одно в другое, при этом, конечно, нужно иметь запас по проускной способности. А синхронизация, в случае SPDIF, не представляет сложности — клок с фиксированной частотой. FIFO потребуется с расчетом на несколько фреймов и делов-то.
0
Это реальное время, скорость «подачи» данных по SPDIF постоянна — буфер не поможет.
Клок-то фиксированный, но генерируется на другой системе и он «будет убегать» относительно генератора, который тактирует UART. Короче проблемы синхронизаци есть.
0
У кодеков I2S не зря есть «режим DSP», когда поток непрерывно идет, а в I2S есть «лишние» два бита. Так легче синхронизировать. А синхронизировать с UART все наверное можно, но я согласен с xar.
0
Всегда есть оверсемплинг и техника восстановления клока. Реалтайма, ясное дело, не получится — сигнал будет задержан по времени, но это не всегда проблема, хотя может быть и недопустимо в некоторых приложениях. Понятное дело, что лучше использовать синхронный канал передачи данных.
0
Так я и имею ввиду, что все это порождает проблемы, и задача не такая простая как кажется.
0
почитайте про проблему джиттера в аудио цапах. проблема в общем то не в самом тактировании, а в фазовых сдвигах.
0
да-да, прошу прощения, я не так выразился.
0
TOSLink это тоже среда передачи данных, и проблема джиттера неизбежна. Все равно на принимающей стороне нужно восстанавливать клок. Если завернуть пакеты в другие и передать их по асинхронному каналу, ситуация ухудшится, но это не значит, что невозможно восстановить клок с джиттером в пределах нормы. Бывают ситуации, когда этого не избежать, не всегда есть возможность организовать синхронный канал передачи.
0
Ну если пофиг на задержку, сделать буфер, асинхронный канал заведомо шире, на другой стороне тоже буфер. Тогда проблемы нет. Просто разговор начался с SPDIF -> UART. Без буферов в реалтайм будет жесть.
0
Без буферов в реалтайм из пакетов — ваще не бывает. Без достачно большого FIFO — невозможно. Нужно поместить в буер не менее 1, а лучше 2 фрейма и только после этого начинать «вынимать» данные, чтоб избежать ситуации «underflow».
0
Задержка при передаче audio не проблема, если слушать музыку с плейера, но вот если смотреть фильм или телек, то прийдется задерживать видео. Кстати в большинстве тюнеров с SPDIF такая функция есть, ибо невозможно заранее знать, какую задержку вносит внешняя аудиосистема со всеми ее DSP.
0
Просто увидел знакомые слова «ПЛИС», «S/PDIF»… и воспаленный моск выдал идею! Всего-то… А вылилось в целую дискуссию! :)
Про проблемы реализации изначально даже не думалось, но вот что обертка, выполненная в железе (ПЛИС) однозначно лучше программной — это факт. В какой-нить спартан или вертекс запросто можно уместить и это, и еще какой-никакой процессор для обслуживания другой периферии. Вопрос цены и целесообразности — это уже другой вопрос.
0
Кроме задержки при преобразованиях туда-сюда будут еще задержки «на транспорте»! Поток? Что поток? Вдул его в оптоволокно или в медь и что там на другом конце провода происходит — никого не волнует! Ни тебе коррекции, ни проверки на ошибки, а если и побилось даже пару байт при передаче — все равно не услышишь. А если в качестве транспорта — Wi-Fi, или даже дешевый NRF24xxx — тут тебе полный набор проверок! Задержка еще та! И удержать ее в каких-то заданных пределах вряд ли получится… Какая уж тут синхронизация? Вопчем, бесполезная это затея.
0
но вот если смотреть фильм или телек, то прийдется задерживать видео
Оно и само по себе задерживается. Насчет ТВ не скажу, но монитор запросто может задерживать вывод картинки на полсотни мс.
0
В этой статье сделано без буфера, но это частный случай.
Возможно скоро напишу про вывод audio wavform на монитор на этой плате (проект есть, просто статью писать надо время найти). Там конечно буфер есть.
0
Если кого обидел — прошу прощения. Я просто хотел намекнуть автору, чтоб описал весь проект, тк подобных статей о FPGA практически нет. Простите мой мрачный английски юмор :) Автор — однозначно молодец!
0
Не в обиде :).
Так там описывать нечего. Кроме модуля SPDIF в проекте только I2S десериалайзер и конфигуратор кодека, все. Но я подумал, что это лучше в другой статье описать, ведь не обязательно аналог оцифровывать (не у всех на платах есть кодеки), можно аудиоданные и с флэша читать, да мало ли вариантов.
0
OMG! Ногти крашеные?
0
  • avatar
  • Kasym
  • 05 декабря 2012, 10:14
Я все думал, когда же кто-то скажет :). Это жена мне помогала, а я видео снимал.
0
а я и не заметил :)
0
… аналоговый сигнал будет оцифрован кодеком WM8731, который установлен на этой плате. Кодек отдает оцифрованные данные по интерфейсу I2S, а конфигурируется по шине I2C. В этой статье я не буду описывать работу с этим кодеком и процедуру извлечения данных левого/правого каналов (i2s de-serializer), так как это материал отдельной статьи.

Ждём отдельной статьи.)
+1
Аудиофилы вешаются, глядя на этот теплый ламповыйсветодиодный звук. Если дать мощный ИК диод, да чувствительные фототранзисторы как приемники можно передавать качественный звук без кабелей. В каждый динамик сателлит по S/PDIF декодеру и селектору канала (а в сабвуфер вместо декодера осиновый кол, ибо я их ненавижу и стремлюсь уничтожить)…
0
. Если дать мощный ИК диод, да чувствительные фототранзисторы
И все пульты в радиусе действия будут надежно заглушены.
0
А нельзя ли купить ИК немного другого диапазона? Пульты имеют узкополосный фильтр.
0
«Немного другого» — это какого? 10мкм?) Насколько я знаю, частотная селекция пока что используется только для оптоволокна. Обычные ИК-приемники хорошо реагируют на весь диапазон, покрываемый ИК диодами, да и достаточно сильным видимым излучением тоже забиваются. Фильтрация по частоте модуляции тоже не очень спасает.
0
Без модуляции, кстати, нестабильно будет работать. Да и на такой частоте (период уже в пределах так сказать размера комнаты :) ) переотражения все испортят.
0
Если хотите без цифровой звук без проводов, то 2.4GHz передатчик + приемник(и) Вам в помощь. Я думаю, найдутся готовые решения с интерфейсом I2S
0
Вот нагуглил за 5 сек. www.nordicsemi.com/eng/Products/2.4GHz-RF/nRF24Z1
0
Маникюр????
0
А где можно почитать более-менее полные доки на SPDIF? ЧТобы там была описана и передача многоканального звука, в том числе и со сжатием.
0
  • avatar
  • Vga
  • 05 декабря 2012, 23:04
www.epanorama.net/documents/audio/spdif.html
Насчет DD, DTS и прочего, скорее всего — нигде, тк все покрыто копирастией. Там типа закрытый клуб и попасть туда непросто (недешево).
0
Есть же открытые кодеки всего этого дела. Значит и какая-то инфа должны быть — тыреная, реверсированная, еще какая.
0
Боюсь с доками совсем будет плохо. Dolby очень жадная контора, за все роялти хочет, даже за значек. Именно поэтому много дешевых IP-боксов не имеют декодеров. Проблема в покупке лицензии за неадекватные деньги. Правда есть хакерские прошивки, но это уже не в рамках закона. Даже Creative выключила поддержку DD и DTS в своих последних картах, но лекарство, как всегда, нашлось :)
0
Даже Creative выключила поддержку DD и DTS в своих последних картах, но лекарство, как всегда, нашлось :)
А там-то она зачем, есть же AC-3 Filter и FFDSHOW?
0
Аппаратный декодер зачем? Ну по крайней мере он там есть, и почему бы его не использовать? Нужно немножко в дровах поковыряться, чтоб все заработало. Просто креативу стало западло бабло долбикам слюнявить, вот они и заблокировали декодеры в дровах.
0
А где можно конкретней почитать про это? У меня как раз Creative X-Fi XtremeGamer.
Хотя интересней было бы включить AC-3 кодирование для SPDIF'а, для вывода многоканального звука, обработанного самой карточкой (т.е. наложение всяких там ЕАХ-эффектов в играх и т.д.), на колонки.
0
Вот vbkesha.prgr.org/ товарисч занимается
0
Можно посмотреть исходники Libdca, эту библиотеку использует VLC плеер для декодирования DTS.
0
к сожалению мест, где можно посмотреть становится все меньше. Я тут тюнер разрабатывал с DD, так вот, чтоб получить возможность его выпускать
1.нужно подписать кучу всяких бумажек, NDA, итп
2.найти завод, который имеет лицензию Dolby на производство. Есть еще ограничение на продажу в странах ЮВА и восточной Европы. Если хотите продавать в Америку или западную Европу, то лицензия будет стоить еще в РАЗЫ дороже, и найти такой завод в Китае уже проблематично…
После того, как эти 2 пункта выполнены, мне отдали скомпиленный микрокод, который я смог вставить в тюнер и разрешили покупку партии микросхем, где DD был разрешен. Ни о каких исходниках не может быть и речи. Обложили со всех сторон, короче :(
0
про работу с WM8731 напишете как-нибудь? Просто тоже предстоит с ним разбираться (ADC -> DSP -> DAC), хотелось бы меньше шишек набить. Точно такая же плата лежит, ждет своей очереди, но из-за коптера пришлось немножко на нее подзабить (
+1
Я постараюсь. Просто времени не много свободного. Но там не сложно на самом деле, думаю, если вы сможете DSP реализовать, то работу с этим кодеком вообще с закрытыми глазами. После подачи питания кодек в power-дауне. Конфигурируется 11-ю регистрами по I2C.
0
А можно по S/PDIF передавать дополнительную информацию для управления устройством? вкл/выкл и громкость?
0
этот фрагмент:
// вычисление бита четности
        parity = sample[0] ^ sample[1] ^ sample[2] ^ sample[3] ^
                    sample[4] ^ sample[5] ^ sample[6] ^ sample[7] ^
                    sample[8] ^ sample[9] ^ sample[10] ^ sample[11] ^
                    sample[12] ^ sample[13] ^ sample[14] ^ sample[15];


можно записать изящнее с помощью унарного оператора:
parity = ^ sample[0];
0
  • avatar
  • Doka
  • 09 февраля 2016, 13:33
поправка:
parity = ^ sample[0:15];
0
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.