Второй звуковой модуль наконец-то заработал как надо

Внутри — широко известный в узких кругах Ketron SD2 + усилитель звука, собранный на TDA8543T. Тот усилитель, который уже имеется на плате Ketron-а, не выдаёт громкость, достаточную для того, чтобы комфортно играть, управляя громкостью с помощью меха. Пришлось прикрутить альтернативный усилитель, который я могу рекомендовать для совместного использования с платой Ketron SD2.

Про сам Ketron SD2 могу сказать, что он хорош. Но недостаточно хорош, для того, чтобы занять место моего основного звукового модуля. Основным модулем у меня пока остаётся ATEMP Pro.DX.

Вот мои наблюдения:

  • Аккордеоновых звуков здесь больше, чем в Pro.DX. И их звучание вполне хорошее для правой руки.
  • Но ни один из этих звуков я не могу поставить на бас или на аккорды. Совершенно не то пальто. (А в Pro.DX хороших звуков для баса и аккордов аж два.)
  • В Кетроне нет звука чистого баяна. А в Pro.DX есть, причём очень натурально звучащий (здесь — пример звучания).
  • Выбор органных звуков имеется, но их звучание не такое разнообразное, как у Pro.DX.
  • Зато в Кетроне есть специальный режим «орган Хаммонда». Это, конечно, плюс. Это позволяет (комбинируя специальным образом настроенный звук Хамонда со звуком аккордеона) получить звук, очень похожий на тот, что частенько использует Людовик Бейер на своём баяне Roland.
  • Звуки медных духовых мне в Кетроне в целом не очень нравятся. Недостаточно натурально звучат, имеются электронные призвуки. Хотя 2-3 звука можно использовать.
  • Саксофоны я ещё не решил где лучше — в Кетроне или в Pro.DX.
  • Скрипки достаточно натурально звучат и в Кетроне, и в Pro.DX.
  • Электромеханические фортепиано всякие (т.е. разновидности Rhodes) я пока детально не слушал. Пока не могу сказать, где их звуки лучше.
  • Если нужны звуки джазового контрабаса, на котором играют пальцами, то вам однозначно нужен Pro.DX. В Кетроне таких двуков нет, а в АТемпе их два, и они прекрасны.
  • Бас-гитары я пока не решил, где лучше.

Такие дела.

Рис. 1

Про северное полушарие

Увидел здесь.

И поэтому все американские претензии на Гренландию и вообще любые телодвижения на Севере — это не что-то далёкое. Это то, что происходит на нашем заднем дворе.

И туда, между прочим, лезут жулики!

Рис. 1

Программные таймеры в FreeRTOS

А вот программные таймеры FreeRTOS-овские меня немножечко разочаровали.

Для реализации таймерных callback-функций есть серьезные ограничения: они должны быть быстрыми и ни в коем случае не должны входить в состояние блокировки (например ожидание мьютекса). То есть там практически такие же ограничения, как и для функций обработчиков прерываний.

С одной стороны, оно понятно, почему так (следствие способа реализации этих самых таймеров). А с другой стороны — доставляет неудобства, т.к. фактически действия «по таймеру» приходится делать не в самой callback-функции таймера, а где-то ещё.

Ну хорошо.

Для моих целей пришлось сделать класс-обертку для реализации моей версии таймеров. У меня единственной задачей таймера является в нужный момент установить нужные флажки в указанной «группе событий» (термин FreeRTOS) — и всё. А уже другая задача будет ждать соответствующего флажка и при его обнаружении делать всё что надо. (На слух всё это звучит «не очень», но реализация получилась довольно удобная и довольно универсальная.)

В результате от «таймеров на millis()» я избавился везде, где это было целесообразно. При этом код, как ни странно, стал более простым и более понятным.

Рис. 1 КДПВ

Переезд на FreeRTOS закончен

Всего получилось 15 задач.

И все эти задачи раньше приходилось реализовывать вручную, на стандартных костылях Arduino-style (функции tick(), «таймеры на millis()» и всё остальное, в результате чего код становился трудно читаемым).

С переходом на нормальные задачи код стал заметно проще. Всем ардуинщикам очень рекомендую по возможности перебираться на FreeRTOS. Благо, она есть для всего уже.

Рис. 1

Интересное про FreeRTOS & RP2040

Стало мне вдруг интересно, раскидывает ли FreeRTOS задачи по разным ядрам контроллера (в RP2040 их два).

Проделал лабораторную работу.

В баяне V3 у меня сейчас используется 11 задач. Я в них добавил кусочек кода, который выставляет флажок в разных местах, в зависимости от того, на каком ядре выполняется задача. Ну и сделал вывод флажков на экранчик.

Оказывается, оно действительно использует оба ядра. Причём не так, что задачи запускаются на конкретном ядре, и потом на нём остаются. Они вполне себе могут перемещаться между ядрами. Видимо, в зависимости от загрузки ядер в каждый конкретный момент.

Очень интересно это всё.

Рис. 1 КДПВ

Обязательный довесок к схеме…

…если RP2040 используется в роли SPI-slave.

Если этот буфер не добавлять, то Rp2040 не даст остальным SPI-slave устройствам, подключенным к той же SPI шине, нормально обмениваться данными. Даже если одно из этих «остальных» SPI-slave устройств — это ещё один RP2040.

Проверено.

Рис. 1

Лекарство найдено

В общем, лекарство от обозначенной в предыдущей заметке болезни выглядит так (см. рис. 1).

В разрыв SPI-цепей CS и MISO впаивается вот такая «пилюля» (асинхронный буфер с 3-мя состояниями выхода). И переводит линию MISO в Z-состояние когда CS = 1.

Надо только в термоусадку эту страсть спрятать.

Рис. 1

P.S. Спрятал — см. рис. 2

Рис. 2

P.P.S. Вторая пилюля, запаянная на шлейф левой клавиатуры, тоже работает как ожидалось: обе клавиатурные RP2040 не мешают друг другу (до того они не работали вместе на одной шине SPI) и не конфликтуют с SD-картой.

Осталось немного

Я тут потихоньку перевожу прошивку своего баяна на FreeRTOS. Начинал с самого простого и очевидного и продвигался по мере роста сложности задачи.

Вчера оформил в виде отдельной задачи проигрывание MIDI-файлов автоаккомпанемента. Понятно, что в результате эта проигрывалка оказалась написана не так, как если бы её с нуля писать под FreeRTOS — в этом случае наверняка что-то было бы по-другому. Но я решил революций не устраивать, и вместо полного переписывания сделал адаптацию.

В соответствующем классе, в отличие от всех остальных, которые уже были переведены на FreeRTOS, хранится довольно много данных (всякие настройки, стейт-машины, всякие вспомогательные данные и т.п.). Наружу из класса торчат публичные функции-члены, с помощью которых внешняя задача управляет процессом (запускает, останавливает, меняет т емп, меняет мелодию и т.п.). С точки зрения класса этого проигрывателя, управляющие воздействия — это изменение внутренних данных. А есть ещё сама задача проигрывания MIDI-файла. Она эти самые внутренние данные «использует». Раньше, когда весь код баяна выполнятся в контексте одной задачи (главный цикл loop()), управляющие воздействия не конфликтовали с проигрыванием, т.к. выполнялись последовательно — т.е. сначала, при необходимости, что-то менялось во внутренних данных (например менялся темп воспроизведения), а затем проходила очередная итерация воспроизведения, которая использовала уже измененные данные.

А тут управляющие воздействия будут проводиться в контексте другой задачи, т.е. может оказаться так, что внутренние потроха могут измениться в момент их использования функцией проигрывания. Т.е. появляется новый ресурс — «потроха MIDI-проигрывателя», доступ к которому в каждый момент времени должна иметь только одна задача. Т.е. потроха проигрывателя нужно просто защитить мьютексом. Так оно и было сделано.

Работает.

Рис. 1

Обе платы клавиатур заработали, но есть нюанс

И правая половина работает, и левая (справа и слева на рис. 1 соответственно).

Нюанс заключается в том, что каждая половина может принимать и отправлять сообщения только тогда, когда от центрального модуля отключена другая. Не живут они обе на шине SPI одновременно.

Похоже, что чуда не произошло, и известная проблема с SPI-slave устройставми на RP2040 проявилась в полный рост. (RP2040, работая как SPI-slave, не переводит линию MISO в Z-состояние, когда SPI интерфейс неактивен.) Ничего не поделаешь, надо с этой проблемой бороться.

Придётся делать дополнительные мини-платы «SPI адаптеров» для правой и левой плат. И лепить на них асинхронные буферы с тремя состояниями на выходе. Знать бы про это заранее — я бы на самих платах такие буферы предусмотрел. Там дел-то на 3 копейки, и подключение элементарное.

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

Рис. 1

Снова о FreeRTOS

Находясь под впечатлением от написания прошивки для платы активной клавиатуры под FreeRTOS, я решил, что и прошивку центральной платы тоже надо переводить на FreeRTOS, чтобы всё было «по красоте».

И хороший момент заключается в том, что переход можно делать постепенно, модуль за модулем. Потому что FreeRTOS-ное хозяйство отлично уживается с тем, что написано в традиционном «ардуинном» фреймворке.

Вот сегодня, например, я перевел на FreeRTOS-ные рельсы модуль драйвера SPI клавиатуры (т.е. клавиатуры, которая умеет присылать нажатия с измеренной velocity). А основная логика, включая автоаккомпанемент, продолжает нормально работать по-старому.

Так что баянчик будет переезжать на новую платформу в комфортных условиях.

И вообще, я теперь фанат FreeRTOS. Она прекрасна.

Рис. 1 КДПВ