AT91SAM3X: порт SSC в режиме приемника-мастера I2S
Добавил(а) Денис Оксин
Поставил перед собой задачу - передавать по сети Ethernet звук от микрофона. Устройство должно быть простым (не компьютер), и вопрос хотелось решить с минимальными усилиями, опираясь на готовые популярные встраиваемые платформы.
[Выбор платы и процессора]
Выбор пал на платформу Arduino по следующим причинам: макетные платы весьма доступны по цене, среда разработки бесплатна, специализированные аппаратные средства разработки не требуются. Поначалу задача казалась несложной, поскольку раньше работал с 8-битными микроконтроллерами PIC, и Arduino должна быть, как обещали разработчики, максимально дружественна для новичков.
Просмотрев доступные у китайцев Arduino-подобные платы, заказал Arduino Due R3 на процессоре SAM3X8E ARM Cortex-M3 [1].
У выбранного процессора должна быть достаточная для решения задачи производительность, есть встроенный быстрый АЦП, интерфейс SSC с поддержкой I2S, контроллер DMA. К этой плате можно подключать стандартные шилды Arduino. Для Ethernet дополнительно заказал Keyestudio W5100 Ethernet Shield [2].
Опыта работы в Arduino IDE было очень мало, поэтому решил начать с простого - подергать ножками GPIO, научиться опрашивать АЦП.
[Подключение аналогового микрофона]
Первые эксперименты с Arduino IDE прошли на удивление удачно. Удалось задействовать несколько портов в качестве цифровых входов-выходов и один порт в качестве аналогового входа. Ethernet-шилд заработал сразу, библиотека от производителя устанавливается штатным образом, все функции работают – получение адреса по DHCP, настройка фиксированного IP адреса, отправка и получение UDP пакетов, TCP соединения. Вызовы сетевых функций и обработчики прерываний не мешают друг-другу.
Дело дошло до оцифровки звука с микрофона. Решил начать с простого – для ввода звука воспользоваться встроенным АЦП, и потренироваться с передачей данных по Ethernet. Для формирования выборок понадобился аппаратный таймер для опроса АЦП с заданной частотой. Однако оказалось, что воспользоваться в Arduino IDE таймером задача не из тривиальных. Внятной документации по функциям таймеров нет. Пришлось изучать исходники библиотек, искать примеры в Интернете. С таймерами помог ресурс [4]. Со сторожевым таймером возникли проблемы. Выяснилось, что разработчики Arduino IDE убрали поддержку WatchDog. К счастью, решение нашлось на форуме Arduino [5].
Стало понятно, почему многие разработчики ругают платформу Arduino - стандартные задачи решаются просто, однако если нужно что-то большее, то сразу наваливается куча проблем - то нет библиотеки, то библиотеки начинают конфликтовать друг с другом. Тем, кто не боится читать даташиты, в Atmel Studio было бы намного удобнее - легче доступ к аппаратуре и планирование ресурсов, сам определяешь, как что должно работать. Никто не будет выпиливать необходимые вещи, не нужно будет вручную определять системные константы по документации на процессор, документация будет нормальной, будут нормальные примеры проектов.
Удалось реализовать опрос АЦП с двойной буферизацией и передачу UDP-пакетов тестовому приложению на PC.
[Сервер, принимающий пакеты UDP]
Тест-программа PC написана в среде Visual Studio 2010 на языке C#. Это сетевой сервер, который прослушивает UDP порт 8266. Микроконтроллер ARM подключается к серверу по его IP и этому номеру порта. Для упрощения обмен данными идет только в одном направлении - звуковые данные передаются от микроконтроллера ARM серверу PC. Скриншот приложения, которое принимает и озвучивает пакеты UDP:
Соотношение сигнал/шум аналогового микрофона не удовлетворило моим требованиям. Следующий логичный шаг - освоить SSC (Synchronous Serial Controller) процессора для подключения микрофона с интерфейсом I2S (SPH0645).
[Подключение цифрового микрофона с интерфейсом I2S]
Платка микрофона SPH0645:
Интерфейс SSC и Arduino Due R3:
Мнемоника
Описание сигнала
Микрофон SPH0645LM4H
Порт SAM3X8E
Периф. SAM3X8E
Порт Arduino
RF
Синхроимпульс кадра приемника (вход микрофона)
LRCL (WS)
PB17
A
A8
RD
Данные приемника (выход микрофона)
DOUT (DATA)
PB18
A9
RK
Такты приемника (вход микрофона)
BCLK (CLK)
PB19
A10
TK
Такты передатчика
PA14
B
23
TF
Синхроимпульс кадра передатчика
PA15
24
TD
Данные передатчика
PA16
A0
Подключение микрофона SPH0645 к SSC:
При написании кода SSC/I2S снова возникли проблемы с библиотеками Arduino IDE. Поддержка I2S есть только для серии MKR с процессорами семейства SAM D21 Cortex-M0. Про SSC вообще ни слова. В Интернете каких-то примеров реальной работы с SSC практически нет.
По стандартной документации для запуска SSC необходимо следующее:
1. Настроить используемые выводы с помощью контроллера PIO, поскольку по умолчанию они настроены на другой функционал. 2. Включить тактирование SSC программированием контроллера PMC. 3. Написать обработчик прерывания SSC. 4. Настроить и разрешить прерывания от SSC.
Набор параметров у SSC весьма приличный, что сильно усложняет его правильную настройку. При выборе параметров SSC я руководствовался документацией на процессор [1], документацией на микрофон SPH0645 [3], описанием шины I2S [6], проектом-примером из Atmel Studio SSC_UNIT_TEST для процессора SAM3X. Из приборов был только мультиметр с функцией частотомера (до 30 кГц).
Разобраться с правильной настройкой периферии PIO получилось не сразу. В режиме зацикливания на себя SSC принимает и отправляет, но при переключении в нормальный рабочий режим мультиметр показывает, что часть выходов просто висят в воздухе без подтяжки к нулю или питанию. Оказалось, что это тоже особенности Arduino IDE. Библиотеки и константы есть, но не так просто найти, где они описаны. Покопавшись в исходниках платформы, нашел как правильно использовать функции управления периферией.
В результате довольно долгого процесса подбора параметров SSC удалось получить нужные частоты на выводах RK и RF, но данных с микрофона не наблюдалось. По всей видимости, какие-то из параметров сигналов не нравились микрофону и данные он отдавать не хотел. По показаниям мультиметра на шине DOUT микрофона наблюдались стабильные ноль вольт.
После более внимательного поиска в Интернете наткнулся на статью [7], где были раскрыты некоторые любопытные моменты, которые явным образом в документации Atmel не описаны. В результате удалось более осмысленно уточнить параметры, и всё заработало. Выражаю благодарность автору за столь подробное описание особенностей работы SSC.
voidSSC_Handler(void)
{
uint32_t ul_ssc_sr;
uint32_t ul_data;
// Проверка готовности данных:
ul_ssc_sr = ssc_get_status(SSC);
if(ul_ssc_sr & SSC_SR_RXRDY)
{
// Если данные готовы, то они обрабатываются. Чтобы избежать вложенных// вызовов, до окончания обработки отключаются прерывания.// Теоретически это может вызвать потери отдельных фреймов, // для звука не страшно.
ssc_disable_interrupt(SSC, SSC_IDR_RXRDY);
// Выборка данных:
ssc_read(SSC, &ul_data);
// Обнуление младших 14 бит:
analogValue = ul_data &0xFFFFC000;
// Сдвиг делением на 14 бит, чтобы сохранить знак:
analogValue = analogValue /0x4000;
// Компенсация смещением (подобрано опытным путем):
analogValue +=7295; // correct DC offset// Далее данные складываются в активный буфер для последующей// отправки по сети:// ...// Разрешение прерываний:
ssc_enable_interrupt(SSC, SSC_IER_RXRDY);
}
}
Как выглядит получившийся макет:
Качество звука цифрового микрофона оказалось намного лучше. Особенно порадовало соотношение сигнал/шум в сравнении с аналоговыми микрофонами, с которыми удалось поэкспериментировать – электретные, MEMS, с обычным операционным усилителем и специализированными микросхемами.
В планах освоить прямой доступ к памяти (DMA) для ускорения обработки. Текущая реализация не тянет частоты выборок выше 44000 Гц.
[Общие выводы]
Если рассматривать Arduino только для макетирования, то это просто замечательная вещь, причем приятно доступная по цене. Выбор разнообразных шилдов также не может не радовать. Однако после ознакомления с Arduino IDE и платы Due R3 выяснилось, что библиотеки для SAM3X разработчиками Arduino IDE попросту отсутствуют – поддержка реализована на уровне совместимости с платой Due на базе Mega328P, никаких SSC, I2S, DMAC. Банальные таймеры, WatchDog не реализованы (или разобраться непросто). Работать с портами GPIO процессора даже как цифровыми входами-выходами просто так не получится – нужно сначала настроить порты ввода-вывода с помощью PIO контроллера.
Не знаю, в чем именно проблема – или Arduino в принципе предназначена только для обучения и мигания светодиодами, или это была неудачная плата, которая не была удостоена должным вниманием разработчиков библиотек. На второй вариант намекает тот факт, что новые актуальные платы выпускаются с процессорами SAM D21. Расстраивает отсутствие документации на встроенные библиотечные функции, нет нормальных примеров проектов с использованием таймеров, счетчиков, прерываний, DMA.
Семейство SAM3X в любом случае заинтересовало. Планирую приобрести нормальный программатор, чтобы можно было работать с Atmel Studio. Atmel Studio это и привычный для меня интерфейс Visual Studio, и доступ к огромной библиотеке примеров, и поддержка отладчиков. После 8-битных PIC и uC эта среда выглядит просто замечательно. Отладчик тоже хочется - буду искать, выбирать. Для таких задач процессор SAM3X, конечно, избыточен. Но для макетирования на столе это очень удобная система с богатым набором периферии. К сожалению, не нашел готовых плат Ethernet, использующих встроенный в этот процессор MAC-контроллер. Из неприятностей – заказать у итальянцев нельзя (в Россию не отправляют), при этом в местных магазинах новых современных плат нет ни в наличии, ни в каталоге. Планирую посмотреть поближе на MKR WiFi 1010 v2 [8].
Исходный код всех проектов можно скачать по ссылке [9].
[Ссылки]
1. SAM3X8E ARM Cortex-M3 site:microchip.com. 2. Keyestudio W5100 Ethernet Shield site:keyestudio.com. 3. Adafruit I2S MEMS Microphone Breakout SPH0645LM4H site:adafruit.com. 4. Arduino Due Timers site:ko7m.blogspot.com 5. Arduino Forum > Products > Arduino Due > Watchdog timer site:forum.arduino.cc. 6. I2S Wikipedia site:wikipedia.org. 7. AT91SAM7X256: работа с портом SSC. 8. Arduino MKR WiFi 1010 site:arduino.cc. 9. 190331SSC-I2C-AT91SAM3X.zip - архив с исходным кодом проектов, документация.