А объединяет их моё безудержное желание идти своим путем там, куда нормальный разработчик и под дулом пистолета не сунется – это если кратко. А тем, кого данная аннотация не испугала, готов представить под катом развернутое описание того, как был проведен уникальный генетический эксперимент по скрещиванию перечисленных в заголовке сущностей, и что из этого вышло. Я – самоучка-многостаночник, т.е. и электронщик, и программист, и швец, и жнец (с дудой не вышло – слухом обделен). И, естественно, в моём анамнезе есть радиокружок и бегущие огни… Но к сути: автомат световых эффектов (бегущие огни) – это нечто, доводящее до истерики своим однообразием. Даже китайские гирлянды с десятком эффектов надоедают почти сразу. И, казалось бы, в то время, как космические автомобили бороздят просторы галактики, не сделать автомат световых эффектов, который был бы не так надоедлив – что может быть проще?! А вот попробуйте найти готовые решения – сумеете? Поскольку (см. первую строку статьи) изобретение велосипедов практически мой конёк, я даже искать не стал, а сразу приступил к. Итак, для гибкости применим микроконтроллер (кто б сомневался). Для красочности – «умные» светодиоды WS2812B (или подобные). Но что делать с неповторимостью эффектов? И тут все просто – надо сделать не жестко запрограммированные эффекты, а генерируемые динамически по определенным алгоритмам с элементами случайности. Вы подумали, что сейчас пойдет речь про микропитон (пардон, майкропайтон) и аппаратную Nucleo или другую ардуиноподобную штуку? Это не наш путь! Свой собственный интерпретируемый скриптовый язык – как вам?! А чтобы совсем было не скучно, то добавить поддержку microSD в качестве носителя этих самых скриптов. И микроконтроллер для пущего веселья взять «дохленький» (на «нормальном» и дурак сумеет). Только AVR, только хардкор! Итак, основа – atmega328P, схема, практически, из этого контроллера и состоит: Собственно, главное в моём велосипеде – это скриптовый алгоритмический язык. Скудные ресурсы выбранного контроллера не позволяют выполнять интерпретацию серьёзных языков типа того же микропитона, поэтому я придумал специализированный ассемблер. Собственно, от ассемблера у меня только трех- и двухбуквенные мнемоники команд и наличие в командах не более двух операндов, но функционально каждая мнемоника соответствует достаточно сложной функции, например, CLR очищает все внутренние переменные, а PNT реализует обновление до 254 светодиодов в гирлянде. Концептуально мой ассемблер – 8-битный, т.е. все переменные занимают физически 1 байт, отсюда ограничение на число светодиодов в гирлянде – не более 254 (один пал жертвой необходимости контролировать переполнение вычислений). Это достаточно много, если идет речь о гирлянде на ёлку, хотя, конечно, по сравнению с пиксельными дисплеями почти ничто… В распоряжении того, кто вздумает создать скрипт светового эффекта на моём ассемблере, есть 36 однобайтных переменных, любое количество которых может быть «назначено» массивом с доступом по индексу. Массив значений RGB-цвета каждого светодиода в гирлянде так же доступен, причем в особо экзотических случаях это пространство так же можно использовать для хранения промежуточных результатов вычислений (хотя это я погорячился – вряд ли такой самурай найдется среди живущих). Как я уже говорил, синтаксис для простоты интерпретации, очень ограниченный: все переменные и функции именуются двумя символами – ни больше, ни меньше, - это сделано для совместимости с записью чисел только в шестнадцатеричном формате. Т.е. интерпретатор, взяв два символа, не совпадающие ни с одной из мнемоник команд, может быть точно уверен, что это будет число (результат функции или значение переменной тоже число). В итоге любая переменная именуется V*, где вместо звездочки – одна из цифр или букв английского алфавита, а, например, функция генерации псевдослучайного числа – RD. Данный подход позволил, например, при описании RGB-цвета использовать такие варианты: FF003E— прямо заданный RGB цвет; RD0000— красный компонент случайный, а остальные обнулены; V1V2V3— RGB‑составляющие находятся, соответственно, в переменных V1, V2 и V3. Для косвенного обращения к массивам введено обозначение X* (звездочка имеет тот же смысл), что означает «взять значение из V* и использовать его в качестве номера ячейки в массиве для извлечения значения». Например, массив состоит из V0, V1 и V2, а переменная VJ используется в качестве индексной, тогда запись единицы в третий элемент массива будет реализован такими командами: VJ=02 XJ=01 (нумерация с нуля, поэтому для обращения к третьему элементу используем число 2). Математические действия поддерживаются в объеме «школьной арифметики» - сложение-вычитание, умножение-деление и взятие остатка от деления – вот и весь ассортимент, да и то с «нюансиком»: только вычитание может привести к переполнению результата, т.е. 0-1=255, в то время как все прочие арифметические действия никогда не переполняются (250+250=255). И формат мнемоники немного экзотический, например, эквивалент традиционной для Си записи V1 += V2 в моём языке выглядит проще: V1+V2, т.е. первый операнд всегда приемник результата. Так же есть ряд встроенных функций: генерация псевдослучайного числа, задержка, ввод аналогового сигнала и еще несколько других. Есть возможность организовать циклы с глубиной вложенности до 5 уровней, а также условное выполнение команд с той же глубиной вложенности. Команды могут записываться как по одной в строке, так и по несколько (ограничение на длину строки тоже 255 символов), между командами может быть любое количество символов-разделителей (пробелы, табуляции), но в тело самих команд не может содержать разделителей, т.е. запись V1=01 корректна, а V1 = 01 – недопустима. Вот чего нет, так это подпрограмм…  Для обновления гирлянды светодиодов имеется две команды: PNT (обновляет светодиоды и тут же возвращает управление) и WT=SS (обновляет светодиоды и затем ожидает SS «тиков» по 10 мс, тем самым задавая темп эффекта). Во время ожидания каждые 10 мс происходит автоматическое изменение яркости светодиодов, для чего предусмотрен особый параметр «затухание».  Предусмотрены и комментарии – любые символы, не распознанные, как корректная мнемоника языка, трактуются комментарием, т.е. игнорируются. Однако, следует признать, что комментарии, равно как и «любое количество разделителей», приводит к увеличению времени интерпретации команд, что для достаточно маломощного микроконтроллера может быть критично, т.е. все эти излишества не приветствуются. А теперь несколько примеров (с комментариями). Одинокий бегущий огонек красного цвета по всей длине гирлянды: В чем же фишка подобного описания эффекта? Да в гибкости! Если гирлянда состоит из 10 светодиодов, или из 50, или из 150 – скрипт будет один и тот же, и в каждом случае, добежав до конца гирлянды, красный огонек начнет сначала свой бег. Чисто аппаратными средствами такой эффект реализовать, по-моему, в принципе нереально. А теперь разнообразим эффект непредсказуемостью цвета. В сущности, вся модификация скрипта сведется к первой его строке: PC=RDRDRD, и все! Однако, случайно генерируемые таким способом цвета чаще всего будут достаточно бледными. Чтобы повысить сочность, будем формировать цвет огонька по правилу: RGB-составляющие могут принимать случайным образом значение только FF или 00, при том, что в цвете хотя бы одна составляющая должна быть равна FF. Сделать это можно таким циклом: Далее команды скрипта те же, что и ранее. Конечно, алгоритм получения случайного сочного цвета так себе, можно и получше придумать, но в формате этой статьи подобные экзерсисы неуместны. Упомянутая ранее возможность автоматически менять яркость светодиодов во время «ожидания» позволяет буквально парой команд реализовать весьма занятные эффекты, например: Сможете угадать, что делает вышеприведенный скрипт? Он реализует такой эффект: вся гирлянда плавно разгорается до максимума и затем так же плавно гаснет, причем каждый раз новым случайным цветом. Как видите, для плавного изменения яркости от минимума до максимума и наоборот, потребовалось всего одна команда WT (с нюансом – ранее был задан параметр «затухания»). Признаюсь, яркость меняется нелинейно… В общем, я надеюсь, идея языка и его применимости понятна. Есть в нем и несколько занятных фишек, например, предусмотрено 2 аналоговых входа, сигналы на которых можно использовать, как переменные в скриптах, а так же «матричный режим» для создания несложных 2D-эффектов (если гирлянду развесить определенным способом)… Но об этом, если кому интересно, лучше прочесть в хелпе к IDE, без которой создавать скрипты на этом языке оказалось затруднительно (хотя изначально задумка была – обойтись блокнотом Windows), ведь ни одна «нормальная» IDE, ни один отладчик не поддерживает это чудо… Вот и пришлось в придачу сделать собственную IDE, в которой можно и скрипт написать, и отладить его в «почти реальном времени» без реальной светодиодной гирлянды. Ссылка на IDE также в конце статьи. Ну и несколько деталей о внутреннем устройстве процесса интерпретации скриптов: Сразу после установки SD-карты считывается конфигурационный файл, в котором указан, сколько всего светодиодов в гирлянде, как именно эта гирлянда используется (т.е. в виде полоски 1D или матрицы 2D), сколько всего скриптов на карте и ряд других параметров. Затем выбирается один из имеющихся файлов для загрузки. Имя каждого файла – его номер (расширение фиксированное), т.е. 0.sc, 1.sc и т.д. Выбор очередного скрипта может быть либо случайным из имеющихся на карте, либо последовательным по их номерам. Поскольку для работы с SD-картой используется SPI-интерфейс, а внутреннее устройство Petit FatFS таково, что даже для чтения одного байта считывается целый сектор, чтение файлов – очень ресурсоёмкая операция, поэтому реализовано внутреннее кэширование считываемых данных. В частности, из-за этого длинные циклы могут быть очень медленными из-за необходимости постоянно подгружать команды с карты. Это, кстати, одна из причин отсутствия подрограмм. Считанные в кэш данные анализируются символ за символом, найденные команды тут же исполняются.  Постоянно контролируется время работы каждого скрипта и, если в конфигурации задан лимит времени работы одного скрипта, скрипт принудительно останавливается, после чего происходит выбор следующего. Если лимит времени не задан, скрипт с бесконечным циклом будет исполняться непрерывно вплоть до сброса устройства. В общем, такой вот светодиодный велоассемблер… Я не очень надеюсь снискать за это почет и уважение, но даже если смог кого только повеселить – и то хорошо! Хотя лично меня и моих близких данное поделие радует уже третий новый год. И если вы подумали, что никаких красивых эффектов на таком примитиве сделать невозможно, я категорически не соглашусь! Вот, например, небольшая симуляция-анимация эффекта «вращающейся радуги»: А скрипт этого эффекта вот такой: Обещанные исходники и IDE: Исходники Проект KiCad IDE  Самоучка