c

А сегодня мы предадимся прекрасной техноереси и построим АНАЛОГОВОЕ МИДИ.

Ну ладно, не такое уж аналоговое. Но без вычислений. Хорошо-хорошо. Объясню по порядку.

Однажды в “сборке” спросили, есть ли какой-то простой способ превратить аналоговый клок в Midi Sync. И действительно, когда речь заходит о подобных вещах, на ум приходят сразу огромные и не очень процессоры и многофункциональные конвертеры и всякое такое, которые далеко не всегда делают то что нужно, и естественно стоят как чугунный мост.

Конечно это решается какой-нибудь завалявшейся под ножкой дивана ардуино нано. в стиле:

INT0_ISR:
  push r16
  in r16, SREG
  push r16

  ldi r16, 0xF8
  sts UDR0, r16
  pop r16
  out SREG, r16
  pop r16
  reti

Но это скуууууучно. и мы помещаем целый процессор для того чтобы воспроизвести один дрыг, по другому дрыгу извне.

Давайте решим это без лишних когитаторов в тракте.

Задача

Тезисно постановка задачи.

  • Извне приходит клок.
  • Выдаёт его аудиовыход.
  • Формат настраивается, ну который ppqn.
  • Длину импульса мы решительно не знаем.
  • Наличие DC в сигнале неизвестно. Но выше 5в оно не прыгнет.

В итоге мы настраиваем клок на формат 24ppqn - то есть 24 импульса за одну четвёртую ноту (четверть), ровно так как это в миди работает. Поэтому всё что нам остаётся - это по импульсу сформировать и отправить сообщение по миди.

Посмотрим что мы имеем. Сообщение для отправки импульса синхронизации - 0xf8. Это сообщение реального времени, поэтому оно не зависит от контекста и может приходить всегда в окружении любых других байт. То есть можем слать его и не беспокоиться больше ни о чём.

Формат отправки байта по UART может быть разным. Но для миди всегда один и тот же стандарт. начинается передача со стартового бита - 0, Затем передаются биты нашего сообщения от младшего (LSB) к старшему (MSB) а затем идёт стоп-бит, и это 1. Наше сообщение в двоичной системе выглядит так 11111000.

Поэтому полностью кадр будет выглядеть вот так:

      старт LSB  1   2   3   4   5   6  MSB стоп
  ┈┈┈┈┈┏━━━┳━━━┳━━━┳━━━┳━━━┳━━━┳━━━┳━━━┳━━━┳━━━┓┈┈┈┈┈
 1 ┊ 1 ┃ 0 ┃ 0 ┃ 0 ┃ 0 ┃ 1 ┃ 1 ┃ 1 ┃ 1 ┃ 1 ┃ 1 ┃ 1 ┊ 1
  ┈┈┈┈┈┗━━━┻━━━┻━━━┻━━━┻━━━┻━━━┻━━━┻━━━┻━━━┻━━━┛┈┈┈┈┈

Линия в состоянии покоя тоже имеет значение 1. И это очень удачная конфигурация. Нам не придётся формировать нужный нам байт в сдвиговом регистре и выталкивать из него всё в линию. Всё что нам нужно это просадить линию на 4 такта на частоте миди 31250 Гц.

Но есть одна неприятная сложность. Нам нужно выдерживать на протяжении всех передач единый клок. А внешние импульсы могут приходить вообще когда угодно. Поэтому надо будет придумать как подстроиться и синхронизироваться.

Но давайте начнём решать задачу кусками. Разделяй и властвуй.

План

  1. Построим генератор частоты для миди - 31250Гц
  2. Приведём входящий импульс во что-то стандартное и понятное
  3. Отправка самого сообщения. просадим в нули линию выхода на 4 такта
  4. Построим схему синхронизации
  5. Сделаем миди выход. и оформим питание всей схемы

Генератор частоты миди

Это самое простое. Есть прекрасная микросхема 4060. Это счётчик и генератор импульсов. Она нам позволит взять какую-то частоту и поделить её счётчиком до нужной нам. Мы возьмём кварц на 2Мгц и поделим его на 64. Это 6й бит счётчика. Как раз наши 31250 Гц

Подключение стандартное:

Генератор частоты миди

Нормализация импульса.

Здесь нам надо сделать 3 вещи. Нормализовать длину импульса. Если он слишком длинный, то превратить его в “иголку”. Убрать лишнее DC если оно есть. Убрать выбросы отрицательного напряжения.

Первые две потребности закроет простой RC фильтр высоких частот. Его конденсатор будет так же действовать как блокировщик DC. А возможные всплески отрицательного напряжения заблокируем диодом.

И поровняем фронты инвертором. Обычно ставят буфер, или два инвертора. Но с инвертированным дальше будет работать проще.

Нормализация импульса

Четыре нуля

Теперь сделаем блок, который отправляет 4 нуля в линию. Для этого нам понадобится классический десятичный счётчик. Заводим его с нашего клока 31250 Гц. А затем соединяем выход тройки Q3 с !CE. В такой конфигурации счётчик работает только когда на выходе не Q3. То есть он добегает с 0 до 3 и сам себя выключает. Но при этом остаётся возможность его сбросить через Reset. и он снова добежит до Q3 и остановится. Так и получаем наш выходной миди сигнал. Всегда единица. а после сброса 4 нуля.

Формирование сообщения

Синхронизация

Это вообще любимая тема всей цифровой электроники. Если увидите грустного фпгашника, подойдите и обнимите его. Потому что наверняка там домены не сходятся и он очень устал.

Но у нас попроще. Всё что нужно сделать. это зафиксировать входной очищенный импульс. и на ближайший восходящий фронт нашего миди клока отправить сообщение. Решается парой D триггеров. один фиксирует факт пришедшего сигнала, включает второй триггер, который по фронту нашего миди клока дёргает счётчик за сброс, а инвертированным сигналом сбрасывает первый D триггер в режим ожидания. И именно для них нам нужен инверсный импульс, потому что у стандартных D триггеров инвертированные входы Set и Reset.

Синхронизация

Выход и питание

На этом вся схема готова. осталось только правильно буферизовать выход. Мы использовали всего 1 инвертор и у нас их осталось 5 штук ещё.

Минималистичный сценарий: парой инвертеров буферизуем сигнал. Входы оставшихся трёх, обязательно подтягиваем или к земле или к питанию.

Но если нужно раздавать этот клок на несколько устройств сразу, то можно сделать до 4х выходов вот так.

По питанию. нужно 5в. Брать где угодно хоть с линк порта геймбоя хоть с usb. И обязательно как можно ближе к ногам питания каждой микросхемы повесить мелкий конденсатор.

Вот и всё.

Собрал симуляцию этой схемы в falstad‘е

Вот полная схема: Kickad PNG