Медиасистема для Toyota Prius (часть 2)

    Продолжение проекта по замене медиасистемы Toyota Prius.

    В этой статье — PHY, Transport, и доставка пакетов до хост-девайса, которую наконец-то удалось проверить на реальной родной голове приуса.

    Быстро сказка сказывается, да не быстро дело делается. Сегодня продолжаю затяжной проект по переделке медиасистемы в Prius, начатый 2 года назад.

    Исторический оффтоп
    На самом деле — адаптер USB-AVC физически собран достаточно давно, и пакеты принимать он тоже научился намного раньше. Но у меня были сомнения относительно его поведения на реальной шине, а проверить возможности не было, т.к. тащить и подключать в машину конструкцию ноут+отладчик+плата — просто не было ни времени, ни желания.

    Но случилось так, что доблестные дорожные службы, так тщательно спонсируемые мной во время прохождения ТО, забыли починить тормоза в МАЗе, и моему приусу пришлось вырабатывать дополнительное тормозное усилие для уборочной техники.

    Ну, а пока он стоит в покраске, я снял с него голову, и проверил PHY-часть схемы.

    Итак, с самого начала. Копаясь в интернете на предмет адаптеров к AVC-LAN, я очень часто видел решения, похожие на вот такое. И в обсуждении нередко проскакивают вот такие комментарии:
    Честно говоря не очень хорошо работает, точнее не со всеми головами хорошо работает.

    Пока идеально читается шина на какой-то старинной магнитоле со Spacio 99 года.
    Я изначально настроен принципиально против того, чтобы делать «как нибудь», и решения с конструктивно заложенной нестабильностью меня не устраивают.
    Будем повторять путь реверс-инженеринга шины. Поехали.

    Первым делом, подключаемся к шине на живом авто, и снимаем осциллограммы:


    Начало пачки.


    Биты где-то в середине, крупнее.


    Что-то очень похожее на ACK.

    Чуть подробнее про эту странную ступеньку — ниже.

    Скрины осциллограмм делал уже из сохраненных данных, во время снятия не сразу обратил внимание на диапазон по напряжению, в котором снимал данные. А когда обратил — пришлось спускаться в машину еще раз, чтобы убедиться, что из ума не выжил. Да-да, размах дифференциальной шины — всего лишь 200мВ (!!!).

    Дальше идем в даташит на применяемый коллегами ST485, и видим там следующее:



    Вот, собственно, и нашелся корень всех бед, из-за которых приходится играться с резисторами, и молить канифольных богов, чтобы преобразователь заработал на конкретной машине. Работать рядом с пороговыми значениями — зло. Но еще интереснее то, что для AVC-LAN, которая по физике своей — клон какой-то IE-Bus от NEC — по своей спецификации (ссылка будет чуть дальше) считает активным состоянием напряжение выше 120мВ, при том, что ST485 имеет право считать все, что меньше 200мВ — нулем. Ну, то есть, если из-за производственных отклонений ST485 будет иметь пороговый уровень чуть ниже, а на шине для запаса появится чуть выше нормы (допускается до 6-ти вольт), то, конечно, ST485 сможет принять такой сигнал. И эти производственные неточности — единственное, что заставляет устройства с ST485 в составе иногда работать. Разумеется, закладывать такое счастье в разработку мы не будем.

    Второе имеющееся решение на базе того же ST485 и операционного усилителя мне не понравилось обилием компонентов. Ну, в 21-м же веке живем, в конце концов.

    Решение:
    Для AVC-LAN существуют специальные преобразователи. Но мне не удалось достать их по приемлемой для этого девайса цене. На помощь снова пришел братский Китай, где была обнаружена HA12240FP, у которой разница напряжений для восприятия лог. «1» по даташиту составляет 80..110 мВ. Это позволит нашей шине выставить активный уровень с почти двукратным запасом. Устраивает.

    Рожаем схему на упомянутом в первой части STM32F103:


    UPD: Схема рождалась в спешке, в ней — ошибка. Питание драйверов шины нужно заводить от 5В. Если так, как на схеме — у них повышается диф. порог, и принимаются не все пакеты.

    Все просто до примитивизма, думаю, в описании не нуждается. За исключением, разве что, того факта, что выбор ног для RX1/2 — не случаен, и первая версия схемы потребовала «доработки напильником», чтобы завести сигналы на входы захвата/сравнения, ибо именно его я хочу использовать для измерения длины импульса. Альтернативные решения — поллинг и прерывание по изменению состояния проигрывают по точности и сложности программной реализации. Плюс — хотелось бы параллельного приема минимум с двух линий (в «голове» их — вообще три), а при совпадении фронтов на двух можно попрощаться с мыслью о сколь-нибудь приемлемой точности, если не использовать захват/сравнение.

    Дальнейший разбор данных в пакет хорошо расписан тут. Но, учитывая, что ссылки — штука непостоянная, вкратце повторюсь здесь:

    • Шина дифференциальная, тут пишут про трактовку уровней лог. «1» при <20mV, лог. «0» — >110mV.
    • Длина бита — 40мкс, первые 20 мкс — всегда «0», последние 7 мкс — всегда «1», посредине — значение бита.


      ну и светофорчик:


    • Стартовый бит — длиннее 180 мкс
    • В конце некоторых частей пакета следует бит подтверждения (ACK). Осциллограмма получилась очень «говорящей», и я ее чуть-чуть разукрасил:



      Принцип передачи ACK-бита очень похож на тот, что происходит в Dallas 1-wire, только тут у нас два провода, и драйверы, похоже, токовые. Потому на рисунке видно, как в т. 1 мастер начинает передачу битового фрейма, переводя линию в активный уровень «0» (то есть, подавая на нее напряжение), почти сразу же в т.2 подключается ведомый, тоже форсируя шину в активный уровень, и их усилия складываются, повышая напряжение вдвое. В т.3 видно, что мастер отпускает шину в неактивный уровень (1), но ее продолжает удерживать ведомый, и только его усилиями напряжение на шине остается в активном нуле, и на последних 7мкс шина освобождается, возвращаясь в неактивную лог. «1».

    Что ж… с физическим уровнем разобрались, схему нарисовали, плату развели. Получилось что-то вот такое:





    Печатная плата вышла несколько неудачно, и не потому, что не получился QR-код в шелкографии. В ней есть ошибка в схеме (на схеме выше я ее уже исправил) в части выбора ног для RX, и разведено три драйвера линии. В процессе написания и отладки программы я понял, что хорошо, если удастся запустить устойчиво хотя бы два. Да больше и не нужно.

    Что ж… девайс получился простым и эффективным, при этом конструктивная проблема с несоответствием уровней решена.

    Далее в программе:

    1. Прошивка для контроллера этого преобразователя. Забегая вперед скажу, что пришлось отказаться от идеи с составным девайсом. Причины две: * в приехавшей магнитоле нет необходимости добавлять кнопки по USB — кнопки резистивные как с руля, так и на панели, есть нативный способ их «обучить» и назначить. Проще пойти этим путем. * Испытания на разных версиях Андроида показали, что более или менее адекватно андроид с составными девайсами работает в версии 8, в 6-й я сильно не разбирался, а с 4.4 определенно имеются проблемы. Когда драйвер андроида открывает клавиатуру составного устройства, он блокирует устройство целиком, и больше ничего на нем октрыть невозможно.
    2. Андроид-монитор для полного реверса логики шины. Если кто-то силен в Андроид и Котлин — буду признателен за возможность консультаций. Это робкие попытки освоения всего и сразу, потому в репозиторий по ссылке без ново-пассита не заходить :)


    UPD: исправил временные данные: вместо мкс были мс.
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

    Комментарии 2

      0
      А я бы все же реализовывал эту штуку через поллинг. Причем многократный. Заводим прерывание периодом эдак в 1 мс, ловим надежный фронт (была лог.1, а последние 2-3 тика лог.0), считаем оставшиеся 18 тиков вслепую, затем 13 тиков считываем значение на входе, после возвращаемся к первому состоянию. Смотрим что насчитали за 13 тиков. Если 6 или меньше — был 0. Если 7 или больше — была 1. На конечных автоматах такая штука делается элементарно и читается достаточно легко. Впихнуть 3 таких автомата в обработчик — тоже несложно и толстым он не станет, зато помехоустойчивость будет сильно лучше варианта с ловлей значения в одной точке через capture/compare.
        0
        1. спасибо за коммент, благодаря ему заметил ошибку: длинна битов была указана в мс, хотя реально — мкс. Исправил.
        2. В связи с этим: поллинг на таких временах уест все процессорное время, если его вообще хватит. Сейчас раскочегаренный на 72 МГц STM при приеме пакетов окло 20..30% времени находится в прерывании. Да, прерывание сложноватое, но поллинг каждую мкс со входом-выходом, плюс расчеты, плюс параллельный анализ, т.к. надо ж и ACK-и (аж от три за заголовок, плюс на каждый байт данных) выдать, когда нужно… в общем, думаю, не хватит времени.
        3. Насчет надежности — не думаю, что это лучше. Шум на шине (имхо) лучше воспринимать, как ошибку, а не пытаться вытряхнуть из него «что-то»: контроль целостности весьма примитивный, и словить что-нибудь ненужное слишком легко. Используя capture я получу битый пакет, не отдам ACK или дождусь следующего широковещательного, но это лучше, чем принять откровенную чушь. Т.е. при capture я увижу, что в процессе приема на шине были импульсные помехи. И это важно.

        ЗЫ: в физическом мире, кстати, я уже принимаю пакеты в андроид-приложение с шины. Там прилично повторяющихся пакетов, которые выглядят подозрительно «реверсабельными». Сейчас надо дописать на досуге еще одну Activity, чтобы те пакеты, которые уже можно классифицировать, отображать там, и не засорять лог. И покататься-понаблюдать. Если есть желание, опыт и время — могу сбросить лог. Потому как в реверсе я не сильно опытен (пока) :)

      Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

      Самое читаемое