Как работает кнопка Mute на Яндекс Станции. Подробный разбор логики и схем
- пятница, 15 марта 2024 г. в 00:00:15
Привет! На связи Геннадий «Крэйл» Круглов из команды, которая разрабатывает аппаратную часть Яндекс Станций. С кем-то из читателей Хабра мы уже могли познакомиться в рамках мероприятий Я.Железа, где делимся опытом разработки устройств.
Последние несколько лет мы с командой вынашивали идею публичного рассказа об устройстве отдельной взятой части наших умных колонок — кнопки Mute. Эта тема вызывает живой интерес, поскольку напрямую касается приватности. Мы часто говорили о том, что Mute отключает микрофоны физически, но как именно это происходит — не рассказывали. В итоге вопросы копились, но руки, как это обычно бывает, до статьи не доходили. Пожалуй, вернём сегодня этот должок.
В этом посте мы расскажем о нашем основном решении для кнопки Mute. Вы увидите, что у процессора устройства нет физической возможности управлять питанием микрофонов, а значит, обойти кнопку программным способом невозможно. Мы опубликуем схемы и расскажем, как они работают. Сначала на языке, который поймут коллеги-инженеры. В конце — резюмируем простыми словами для всех. Надеюсь, будет интересно и полезно.
Начнём с простого. Почему кнопка, а не хардкорный рубильник, размыкающий цепь питания? Ответ на поверхности. Кнопка в среднем надёжнее механически и лучше защищена от грязи и пыли. Кроме того, на большинстве наших Станций кнопка Mute выполняет ещё одну дополнительную функцию: если зажать её дольше пяти секунд, то настройки Станции сбрасываются. Ну и в дизайн устройства кнопка вписывается, конечно же, легче.
Идём дальше. Кнопка — это механический компонент. Главный вопрос: что делать с её сигналом? Проще и удобнее завести этот сигнал на процессор или микроконтроллер: он сможет отслеживать длительность нажатия, по короткому переключать состояние Mute, а по длинному — сбрасывать настройки. Но тогда поведение колонки в смысле отключения микрофонов будет зависеть от прошивки. Чтобы доказать, что у нас нет возможности менять поведение кнопки Mute, управление микрофонами реализовано без использования процессора/контроллера, на примитивных компонентах. Поэтому схема работы кнопки такая сложная. Если бы не эта необходимость, схема была бы проще в десятки раз, микрофоны всегда работали, а процессор просто не использовал их сигнал в режиме Mute.
Чтобы наш рассказ был более предметным, рассмотрим логику работы кнопки на примере наиболее популярных современных моделей Яндекс Станций.
Начнём с одной из самых популярных новинок прошлого года. Схема обвязки кнопки Mute на Станции Миди выглядит так:
Кстати, эта схема была опробована ещё в обновлённой Станции Мини (2021).
Прежде чем двигаться дальше, давайте вспомним таблицу истинности триггера:
Это скриншот из даташита. Строки первая и третья у нас не сработают, поскольку вход #PRE безальтернативно подтянут к питанию.
При включении питания конденсатор C249 разряжен, на затворах VT6, VT7, VT8 — ноль, поэтому:
VT6 закрыт, на линии MUTE_BUTTON логическая 1.
VT7 открыт, VT8 закрыт, так что заряжается батарея конденсаторов C250, C252, C254.
Далее через резистор R125 заряжается конденсатор C249. Он зарядится за время T = RC = 100к × 0,22 мкФ = 22 мс. После этого:
Открывается транзистор VT6 и подаёт 0 на линию MUTE_BUTTON.
Закрывается транзистор VT7, прекращается зарядка батареи конденсаторов.
Открывается транзистор VT8 и разряжает батарею конденсаторов.
После разрядки батареи конденсаторов закрывается транзистор VT9, через R130 начинает заряжаться конденсатор C253.
Таким образом, на входе #CLR-триггера какое-то время присутствует 0, и триггер сбрасывается: на выходе Q появляется 0 (поскольку #PRE всегда 1), на выходе #Q — 1. На входе D через 10 мс (R131 = 100k, C255 = 0,1 мкФ => T = RC = 10 мс) появится 1. Но вход CLK остаётся в 0, поэтому триггер не переключится. Чуть ниже по тексту для наглядности приведён график переключений.
На линии MICENR (выход Q) присутствует 0, поэтому MUTE_STATE будет 1, а на MLED — 0.
При нажатии кнопки Mute заряд перераспределяется между заряженным C249 и разряженным C251: поскольку ёмкость первого больше, на линии CLK появляется логическая 1. Она там ненадолго: конденсаторы разряжаются через R129 и разрядятся примерно за 0,3 мс.
Таким образом, на вход CLK будет подан короткий единичный импульс. Поскольку на входе D логическая 1, то триггер переключится: на Q появится 1, а на #Q — 0. Через 10 мс 0 с выхода #Q окажется на входе D, но это ничего не изменит, поскольку опять же нет фронта на входе CLK. На линии MIC_EN_R появится 1, на MUTE_STATE — 0, а на MLED — 1.
Вернёмся к левой части схемы. После того как конденсаторы C249+C251 будут разряжены:
Закрывается транзистор VT6, на линию MUTE_BUTTON подаётся 1.
Закрывается транзистор VT8, прекращается разрядка батареи конденсаторов.
Открывается транзистор VT7, начинается зарядка батареи конденсаторов.
Если кнопку держать дольше, то за это время успеет зарядиться батарея конденсаторов. Расчётное время зарядки до напряжения 0,7 от напряжения питания — 15 с (T = RC = (1 М + 100 к) × (4,7 мкФ × 3)). Однако в реальности транзистор откроется при меньшем напряжении, поэтому задержка тоже будет меньше — порядка 5 с.
Транзистор VT9 откроется, на входе #CLR появится 0, и триггер сбросится в исходное состояние с Q = 0 и #Q = 1. Соответствующие выходные цепи тоже вернутся в начало. Если же кнопку отпустить раньше, то батарея конденсаторов не успеет зарядиться. Через 22 мс после отпускания кнопки зарядится конденсатор C249, и тогда:
На линии MUTE_BUTTON снова окажется 0.
Батарея конденсаторов снова будет разряжена.
Состояние линий MUTE_STATE и MLED не изменится.
При следующем нажатии кнопки на входе CLK снова появится единичный импульс, но на этот раз на входе D будет уже 0. Таким образом, триггер снова переключится: на Q появится 0, а на #Q — 1. Линии MUTE_STATE и MLED изменят своё состояние соответственно.
Покажем переключения на графике:
Очевидно, что процессор не участвует в переключении состояния MUTE и никак не может повлиять на работу кнопки.
Давайте посмотрим, куда идут выходные линии. MUTE_BUTTON и MUTE_STATE идут на GPIO процессора. Это подключение нужно, чтобы софт мог понять, в каком состоянии находится кнопка, и в каком — подсистема микрофонов. Это нужно, например, чтобы при долгом нажатии начать процесс возврата к заводским настройкам.
Посмотрим на верхнеуровневую схему:
Ныряем глубже, внутрь квадратика справа внизу:
И ещё глубже:
GPIO процессора подключены к стокам транзисторов. Даже если эти GPIO переключить в режим выхода, подача логических сигналов на линии MUTE_BUTTON и MUTE_STATE не в состоянии переключить схему.
Теперь проследим путь линии MLED. Нырнём в верхний правый квадратик верхнеуровневой схемы:
Разъём X5 соединяет основную плату и плату микрофонов.
Вот плата микрофонов:
Сначала заглянем в квадратик Connector:
При 0 на MUTE_EN транзистор VT2 будет открыт, подавая питание +VDD_MIC, а при 1 — закрыт, и питание будет выключено. На верхнеуровневой схеме видно, что питание микрофонов идёт именно по цепи +VDD_MIC / +3V3_MIC.
Заглянем в квадратик Mics.SchDoc, просто чтобы не оставлять белых пятен:
А теперь — в квадратик LED_Driver_Alice.SchDoc:
Тут видно, что при 1 на MUTE_EN транзистор открыт и включены красные каналы светодиодов.
Схема обвязки кнопки в Станции 2 повторяет схему из Станции Миди, так что не будем на ней останавливаться:
Линии MHWEN и MSWDET подключены к GPIO процессора (опять же, процессор не в состоянии повлиять ими на схему переключения). А управляющий сигнал MLED поступает на плату микрофонов через шлейф.
Посмотрим на схему подсистемы микрофонов. Сначала общий вид:
Теперь схема подключения разъёма:
Посмотрим на схемы микрофона и светодиодов:
В правой части расположен транзистор VT1, который включает красные каналы светодиодов при логической 1 на затворе.
Как и написано: при логической 1 на MLED светодиоды светятся, а питание микрофонов отключено. И наоборот.
Тут схема триггера проще, поскольку у Станции Макс есть две кнопки и нет необходимости использовать кнопку MUTE для сброса к заводским настройкам.
При включении питания:
Конденсатор C18 заряжается через R16.
Конденсатор C17 заряжается через R20 за T = RC = 1 мкФ × 100 к = 100 мс. Триггер сбрасывается: на выходе Q появляется 0, а на #Q — 1.
Конденсатор C28 заряжается через R15 за T = RC = 0,1 мкФ × 100 к = 10 мс, и на входе D появляется логическая 1.
При нажатии на кнопку конденсатор C18 разряжается через R2 за T = RC = 0,1 мкФ × 1 к = 0,1 мс. На вход CLK подаётся единичный импульс. Поскольку на входе D — логическая 1, триггер переключается: на выходе Q появляется 1, а на #Q — 0. Через 10 мс на входе D появляется логический 0 с выхода #Q.
При отпускании кнопки конденсатор C18 зарядится через 10 мс, так что повторно кнопку следует нажимать не раньше:)
При повторном нажатии триггер снова переключится и сигналы MIC_EN и #MIC_EN поменяют свой уровень.
Заметим, что светодиоды VD1 и VD2 горят, когда на #MIC_EN присутствует высокий уровень, а на MIC_EN — низкий.
Сигнал MIC_EN подведён к разъёму, откуда далее идёт на GPIO процессора. Больше он нигде не используется. Процессор, даже переведя GPIO в режим выхода, не может никак переключить схему: триггер переключается только по CLK, а на него сигнал может подать только кнопка.
Для управления микрофонами используется сигнал #MIC_EN:
Здесь при логической 1 на #MIC_EN (микрофоны выключены) выключено питание микрофонов, а также запрещена работа буферов DD1 и DD2, которые подают тактирование на микрофоны:
Так что тут отключены и питание, и тактирование.
Итак, нажатие кнопки Mute отключает микрофоны без участия процессора и программного обеспечения: у них отключается питание, они перестают работать. Включить микрофоны обратно можно либо по кнопке Mute, либо через сброс питания всего устройства (грубо говоря, если выдернуть БП из розетки и воткнуть обратно). У процессора нет физической возможности управлять питанием микрофонов. Мы осознанно пошли на создание такой сложной схемы, чтобы добиться этого эффекта.
Описанные в статье решения применяются в наших колонках уже несколько лет, ими пользуются миллионы пользователей. Мы считаем такие масштабы хорошим бенчмарком. Тем не менее понимаем, что идеальных решений не бывает. И поэтому хотим напомнить, что Яндекс Станции участвуют в «Охоте за ошибками». Недавно мы подняли максимальную сумму вознаграждения за найденные в устройствах уязвимости до миллиона рублей. Верим, что это поможет проверить устройства с Алисой на прочность и сделать их ещё надёжнее.