<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Alexey Bolshakov</title>
    <description>The latest articles on DEV Community by Alexey Bolshakov (@ua3mqj).</description>
    <link>https://dev.to/ua3mqj</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3831248%2F7b0c6671-cae6-45c2-97a8-0fa75341b7a2.jpg</url>
      <title>DEV Community: Alexey Bolshakov</title>
      <link>https://dev.to/ua3mqj</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ua3mqj"/>
    <language>en</language>
    <item>
      <title>FMix: пакетный менеджер для Forth</title>
      <dc:creator>Alexey Bolshakov</dc:creator>
      <pubDate>Mon, 18 May 2026 23:12:43 +0000</pubDate>
      <link>https://dev.to/ua3mqj/fmix-pakietnyi-mieniedzhier-dlia-forth-o3p</link>
      <guid>https://dev.to/ua3mqj/fmix-pakietnyi-mieniedzhier-dlia-forth-o3p</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzf2rgkhcmxfwn1m9zoy4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzf2rgkhcmxfwn1m9zoy4.png" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;В современных языках программирования мы почти всегда ожидаем, что рядом с языком будет удобный инструмент для работы с проектом.&lt;/p&gt;

&lt;p&gt;В Elixir есть &lt;a href="https://hexdocs.pm/mix/Mix.html" rel="noopener noreferrer"&gt;Mix&lt;/a&gt;. В Rust есть &lt;a href="https://doc.rust-lang.org/cargo/" rel="noopener noreferrer"&gt;Cargo&lt;/a&gt;. В Ruby есть &lt;a href="https://bundler.io/" rel="noopener noreferrer"&gt;Bundler&lt;/a&gt; и &lt;a href="https://rubygems.org/" rel="noopener noreferrer"&gt;RubyGems&lt;/a&gt;. В Haskell есть &lt;a href="https://www.haskell.org/cabal/" rel="noopener noreferrer"&gt;Cabal&lt;/a&gt; и &lt;a href="https://docs.haskellstack.org/" rel="noopener noreferrer"&gt;Stack&lt;/a&gt;. В JavaScript есть &lt;a href="https://www.npmjs.com/" rel="noopener noreferrer"&gt;npm&lt;/a&gt;, &lt;a href="https://pnpm.io/" rel="noopener noreferrer"&gt;pnpm&lt;/a&gt; и &lt;a href="https://yarnpkg.com/" rel="noopener noreferrer"&gt;Yarn&lt;/a&gt;. В Go есть &lt;a href="https://go.dev/ref/mod" rel="noopener noreferrer"&gt;modules&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Мы привыкли, что можно создать проект одной командой, описать зависимости в одном файле, подтянуть их из сети, запустить тесты, собрать релиз. Это кажется базовой частью экосистемы, а не отдельной роскошью.&lt;/p&gt;

&lt;p&gt;Но у старых языков программирования часто другая история.&lt;/p&gt;

&lt;p&gt;Когда многие из них создавались, такой подход ещё не был стандартом. Код распространялся иначе, проекты были устроены иначе, а экосистемы развивались без привычных сегодня package managers и build tools.&lt;/p&gt;

&lt;p&gt;И это до сих пор чувствуется.&lt;/p&gt;

&lt;h2&gt;
  
  
  Почему я задумался об этом
&lt;/h2&gt;

&lt;p&gt;Для одного из своих проектов я использую &lt;a href="https://forth-standard.org/" rel="noopener noreferrer"&gt;Forth&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Forth — очень интересный язык. Минималистичный, прямой, необычный. В нём есть что-то очень привлекательное: ты находишься близко к вычислениям, близко к стеку, близко к самому железу вычислительной машины (которую иногда я делаю сам).&lt;/p&gt;

&lt;p&gt;Но когда я начал писать на Forth что-то более-менее похожее на проект, мне быстро стало не хватать привычных вещей:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;создать новый проект;&lt;/li&gt;
&lt;li&gt;описать зависимости;&lt;/li&gt;
&lt;li&gt;скачать зависимости;&lt;/li&gt;
&lt;li&gt;запускать тесты;&lt;/li&gt;
&lt;li&gt;иметь понятную структуру проекта;&lt;/li&gt;
&lt;li&gt;подключать библиотеки из Git;&lt;/li&gt;
&lt;li&gt;не держать всё вручную в голове.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Да, можно использовать git submodules, можно копировать файлы руками, можно придумывать свои соглашения. Но для меня это не очень удобный путь. Я хотел что-то ближе к тому, к чему привык в современных языках.&lt;/p&gt;

&lt;p&gt;Я нашёл библиотеку &lt;code&gt;f.4th&lt;/code&gt;, связанную с &lt;a href="https://theforth.net/" rel="noopener noreferrer"&gt;theforth.net&lt;/a&gt;. Это полезный инструмент, но у него другой подход: библиотеки и версии хранятся на своём сервере.&lt;/p&gt;

&lt;p&gt;Мне же хотелось уметь подтягивать зависимости прямо из Git-репозиториев. Например, указать GitHub URL, ветку или тег, и получить библиотеку в проект.&lt;/p&gt;

&lt;p&gt;Так появилась идея сделать &lt;code&gt;fmix&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Что такое FMix
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;fmix&lt;/code&gt; — это небольшой build tool и package tool для Forth, вдохновлённый Elixir Mix.&lt;/p&gt;

&lt;p&gt;Репозиторий: &lt;a href="https://github.com/VitaSound/fmix" rel="noopener noreferrer"&gt;github.com/VitaSound/fmix&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Он не пытается быть большим фреймворком. Его задача проще: дать Forth-проекту минимальный набор привычных инструментов.&lt;/p&gt;

&lt;p&gt;Сейчас &lt;code&gt;fmix&lt;/code&gt; умеет:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;fmix new example
fmix packages.get
fmix &lt;span class="nb"&gt;test
&lt;/span&gt;fmix version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;То есть можно создать новый пакет, подтянуть зависимости, запустить тесты и посмотреть версию инструмента.&lt;/p&gt;

&lt;h2&gt;
  
  
  Создание проекта
&lt;/h2&gt;

&lt;p&gt;Новый проект создаётся так:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;fmix new example
&lt;span class="nb"&gt;cd &lt;/span&gt;example
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;После этого появляется базовая структура проекта:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;example/
  example.4th
  package.4th
  README.md
  tests/
  forth-packages/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;package.4th&lt;/code&gt; — это файл описания пакета. В нём указывается имя, версия, лицензия, основной файл и зависимости.&lt;/p&gt;

&lt;p&gt;Пример:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;forth-package
    key-value name example
    key-value version 0.1.0
    key-value license COPL
    key-value description example
    key-value main example.4th

    key-list dependencies f git https://github.com/VitaSound/f tag 0.2.4
    key-list dependencies ttester git https://github.com/VitaSound/ttester tag 1.1.0
end-forth-package
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Мне нравится, что сам файл тоже написан в стиле Forth. Это не JSON, не YAML и не TOML, а маленький декларативный Forth-формат.&lt;/p&gt;

&lt;h2&gt;
  
  
  Зависимости из Git
&lt;/h2&gt;

&lt;p&gt;Главная причина, по которой я начал делать &lt;code&gt;fmix&lt;/code&gt;, — это зависимости из Git.&lt;/p&gt;

&lt;p&gt;В &lt;code&gt;package.4th&lt;/code&gt; можно указать зависимость так:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;key-list dependencies ftest git https://github.com/VitaSound/ftest.git branch main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Или так, если нужна конкретная версия через tag:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;key-list dependencies ftest git https://github.com/VitaSound/ftest.git tag 0.1.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;После этого достаточно выполнить:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;fmix packages.get
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Зависимости будут установлены в локальную папку проекта:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;./forth-packages/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Структура позволяет хранить разные версии одной библиотеки рядом друг с другом:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;forth-packages/
  f/
    0.2.4/
  ttester/
    1.1.0/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Подключать зависимость можно обычным &lt;code&gt;require&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;require ./forth-packages/f/0.2.4/f.4th
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Поддержка theforth.net
&lt;/h2&gt;

&lt;p&gt;Хотя мне хотелось Git-зависимостей, я не хотел полностью отказываться от существующей экосистемы.&lt;/p&gt;

&lt;p&gt;Поэтому &lt;code&gt;fmix&lt;/code&gt; также умеет работать с пакетами из &lt;code&gt;theforth.net&lt;/code&gt; через &lt;code&gt;f.4th&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Например:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;key-list dependencies f 0.2.4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Таким образом, в одном проекте можно использовать и Git-зависимости, и пакеты из &lt;code&gt;theforth.net&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fweufktv2vbz4o7gwjo9y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fweufktv2vbz4o7gwjo9y.png" alt=" " width="800" height="485"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Тесты
&lt;/h2&gt;

&lt;p&gt;Ещё одна базовая вещь, которой мне не хватало, — запуск тестов.&lt;/p&gt;

&lt;p&gt;В &lt;code&gt;fmix&lt;/code&gt; есть команда:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;fmix &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Она запускает тесты из директории &lt;code&gt;tests/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Можно запустить и конкретный файл:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;fmix &lt;span class="nb"&gt;test &lt;/span&gt;tests/some_test.4th
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Для тестов используется &lt;code&gt;ttester&lt;/code&gt;. Если &lt;code&gt;ttester&lt;/code&gt; есть в зависимостях проекта, &lt;code&gt;fmix&lt;/code&gt; берёт его из &lt;code&gt;./forth-packages&lt;/code&gt;. Если нет — использует версию из установленного &lt;code&gt;FMIX_HOME&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Для меня это важно: тесты должны запускаться одной командой. Даже если проект маленький.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvyyz5hya9p3s0n5amsx1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvyyz5hya9p3s0n5amsx1.png" alt=" " width="800" height="488"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Что было исправлено в последних версиях
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;fmix&lt;/code&gt; пережил уже несколько поколений изменений.&lt;/p&gt;

&lt;p&gt;Первые версии я писал сам. Но я не очень сильный Forth-разработчик, поэтому многие вещи давались тяжело. Одну крупную переработку я сделал с помощью Gemini. Последнюю версию я уже доводил с помощью Cursor.&lt;/p&gt;

&lt;p&gt;В последних релизах было исправлено довольно много практических проблем.&lt;/p&gt;

&lt;p&gt;Появился GitHub Actions CI: workflow собирает &lt;a href="https://www.gnu.org/software/gforth/" rel="noopener noreferrer"&gt;GForth&lt;/a&gt; 0.7.9 из исходников и запускает:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gforth fmix.4th &lt;span class="nt"&gt;-e&lt;/span&gt; version
gforth fmix.4th &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Позже появился release pipeline: при push version tag автоматически создаётся GitHub Release, а текст релиза берётся из файла &lt;code&gt;.github/RELEASE_NOTES_X.Y.Z.md&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Также были исправлены проблемы с путями. Раньше часть логики была завязана на &lt;code&gt;PWD&lt;/code&gt;, теперь проект определяется через текущую директорию запуска. Это важно, потому что &lt;code&gt;FMIX_HOME&lt;/code&gt; указывает на установленный &lt;code&gt;fmix&lt;/code&gt;, а команды должны работать с текущим проектом.&lt;/p&gt;

&lt;p&gt;Были исправлены ошибки при установке зависимостей:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;git clone&lt;/code&gt; теперь проверяет результат;&lt;/li&gt;
&lt;li&gt;неуспешные shell-команды завершают GForth с exit code &lt;code&gt;1&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;перед &lt;code&gt;git clone&lt;/code&gt; создаются родительские директории;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;git fetch&lt;/code&gt; и &lt;code&gt;checkout&lt;/code&gt; выполняются так, чтобы ошибка не маскировалась;&lt;/li&gt;
&lt;li&gt;для Git-команд используется &lt;code&gt;GIT_TERMINAL_PROMPT=0&lt;/code&gt;, чтобы команда не зависала в non-interactive окружении.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ещё одна важная вещь — валидация входных данных. &lt;code&gt;fmix&lt;/code&gt; проверяет имена пакетов, версии, пути, Git URL и Git refs перед тем, как вызывать &lt;code&gt;cp&lt;/code&gt;, &lt;code&gt;sed&lt;/code&gt; или &lt;code&gt;git&lt;/code&gt;. Это не сложная система escaping, а простой whitelist, но он отсекает пробелы, &lt;code&gt;;&lt;/code&gt;, &lt;code&gt;$&lt;/code&gt;, backticks, pipes и другие shell metacharacters.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi1g0sbihdd7kuag5sk9p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi1g0sbihdd7kuag5sk9p.png" alt=" " width="680" height="699"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Неожиданная проблема: терминал
&lt;/h2&gt;

&lt;p&gt;Отдельная история была с терминалом. Перед тем, как пользоваться командой &lt;code&gt;fmix&lt;/code&gt; в консоли, ее нужно прописать как alias.&lt;/p&gt;

&lt;p&gt;Так вот при запуске через простой alias вроде:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;fmix&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'gforth "$FMIX_HOME/fmix.4th" -e'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;после выполнения команд терминал иногда оставался в плохом состоянии. На prompt появлялись странные символы вроде:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0c0c
[?2004l
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Особенно это проявлялось в WSL.&lt;/p&gt;

&lt;p&gt;В версии &lt;code&gt;0.4.4&lt;/code&gt; я перешёл на launcher script &lt;code&gt;bin/fmix&lt;/code&gt;. Он восстанавливает TTY после команд, сбрасывает bracketed paste mode и немного очищает накопившийся ввод из &lt;code&gt;/dev/tty&lt;/code&gt;. На самом деле все эти вещи я бы точно не разрешил самостоятельно. Я терпеливо помогал нейросети раз за разом пробовать некоторые гипотезы, чтобы исправить эту проблему. В отличие от тех ИИ, что я пробовал раньше, в этот раз я только один раз решил прервать ИИ и создать новый контекст, потому что она как будто зациклилась в бесконечном исправлении.&lt;/p&gt;

&lt;p&gt;Однако, получилось и теперь вместо alias рекомендуется использовать:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;FMIX_HOME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/fmix"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$FMIX_HOME&lt;/span&gt;&lt;span class="s2"&gt;/bin:&lt;/span&gt;&lt;span class="nv"&gt;$PATH&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;И запускать просто:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;fmix
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Установка
&lt;/h2&gt;

&lt;p&gt;Сейчас установка выглядит так:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/VitaSound/fmix.git ~/fmix
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Затем нужно добавить в shell config (например .bashrc):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;FMIX_HOME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/fmix"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$FMIX_HOME&lt;/span&gt;&lt;span class="s2"&gt;/bin:&lt;/span&gt;&lt;span class="nv"&gt;$PATH&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;После этого команда начнет работать прямо в консоли:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;fmix version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Важно: сейчас &lt;code&gt;fmix&lt;/code&gt; рассчитан на Linux, Git, sed, cp и &lt;a href="https://www.gnu.org/software/gforth/" rel="noopener noreferrer"&gt;GForth&lt;/a&gt; 0.7.9.&lt;/p&gt;

&lt;p&gt;Я не рекомендую использовать GForth более ранних версий и версию из &lt;a href="https://snapcraft.io/" rel="noopener noreferrer"&gt;Snap&lt;/a&gt;. Snap запускает программы в изолированном окружении, из-за чего текущая директория и пути могут не совпадать с тем, что ожидает shell session. Это ломает команды вроде &lt;code&gt;new&lt;/code&gt; и &lt;code&gt;packages.get&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Лучше использовать GForth из apt, локальную сборку или tarball с &lt;a href="https://www.gnu.org/software/gforth/" rel="noopener noreferrer"&gt;официальной страницы GForth&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Зачем это всё
&lt;/h2&gt;

&lt;p&gt;Мне кажется, что старым языкам очень нужны такие инструменты, чтобы соответсвовать современным реалиям. &lt;/p&gt;

&lt;p&gt;Не обязательно огромные. Не обязательно идеальные. Но хотя бы такие, которые закрывают базовые сценарии.  Когда у языка есть удобный инструмент вокруг проектов, он становится дружелюбнее.&lt;/p&gt;

&lt;p&gt;Новому человеку проще попробовать язык. Опытному пользователю проще начать новый проект. Библиотеки проще переиспользовать. Тесты проще запускать.&lt;/p&gt;

&lt;p&gt;Это не меняет сам язык, но меняет опыт работы с ним. Позволяет взять старый инструмент в новые проекты.&lt;/p&gt;

&lt;p&gt;В случае Forth это особенно интересно. Forth часто воспринимается как что-то старое, странное и нишевое. Но, возможно, часть этой «старости» находится не только в языке, а в отсутствии привычной современной обвязки.&lt;/p&gt;

&lt;p&gt;Если добавить удобные инструменты, язык может ощущаться совсем иначе.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fuser-attachments%2Fassets%2F87d7e8ac-94fd-4a4a-a9a8-3a32c658714f" class="article-body-image-wrapper"&gt;&lt;img width="720" height="480" alt="programming-languages-personified-fmix" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fuser-attachments%2Fassets%2F87d7e8ac-94fd-4a4a-a9a8-3a32c658714f"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Что дальше
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;fmix&lt;/code&gt; пока маленький и экспериментальный.&lt;/p&gt;

&lt;p&gt;Сейчас он умеет создавать пакеты, подтягивать зависимости из Git и &lt;code&gt;theforth.net&lt;/code&gt;, запускать тесты.&lt;/p&gt;

&lt;p&gt;В будущем хочется улучшать совместимость, добавить документацию, и, возможно, добавить больше команд вокруг разработки Forth-пакетов.&lt;/p&gt;

&lt;p&gt;Но уже сейчас мне стало гораздо удобнее работать над своими Forth-проектами. Но это уже совсем другая история&lt;/p&gt;

&lt;h2&gt;
  
  
  Ссылки
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/VitaSound/fmix" rel="noopener noreferrer"&gt;FMix on GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.gnu.org/software/gforth/" rel="noopener noreferrer"&gt;GForth&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://theforth.net/" rel="noopener noreferrer"&gt;theforth.net&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/TG9541/stm8ef" rel="noopener noreferrer"&gt;STM8 eForth&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://t.me/forthchat" rel="noopener noreferrer"&gt;[NF] Forth-like languages, язык Форт&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://t.me/ruforth" rel="noopener noreferrer"&gt;[TF] Форт и общение фортеров&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>forth</category>
      <category>opensource</category>
      <category>tooling</category>
      <category>ai</category>
    </item>
    <item>
      <title>FMix: a package manager for Forth</title>
      <dc:creator>Alexey Bolshakov</dc:creator>
      <pubDate>Mon, 18 May 2026 23:12:32 +0000</pubDate>
      <link>https://dev.to/ua3mqj/fmix-a-package-manager-for-forth-37ld</link>
      <guid>https://dev.to/ua3mqj/fmix-a-package-manager-for-forth-37ld</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F30cyxshvkhfj37m9mioa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F30cyxshvkhfj37m9mioa.png" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In modern programming languages, we almost always expect the language to come with a convenient tool for working with projects.&lt;/p&gt;

&lt;p&gt;Elixir has &lt;a href="https://hexdocs.pm/mix/Mix.html" rel="noopener noreferrer"&gt;Mix&lt;/a&gt;. Rust has &lt;a href="https://doc.rust-lang.org/cargo/" rel="noopener noreferrer"&gt;Cargo&lt;/a&gt;. Ruby has &lt;a href="https://bundler.io/" rel="noopener noreferrer"&gt;Bundler&lt;/a&gt; and &lt;a href="https://rubygems.org/" rel="noopener noreferrer"&gt;RubyGems&lt;/a&gt;. Haskell has &lt;a href="https://www.haskell.org/cabal/" rel="noopener noreferrer"&gt;Cabal&lt;/a&gt; and &lt;a href="https://docs.haskellstack.org/" rel="noopener noreferrer"&gt;Stack&lt;/a&gt;. JavaScript has &lt;a href="https://www.npmjs.com/" rel="noopener noreferrer"&gt;npm&lt;/a&gt;, &lt;a href="https://pnpm.io/" rel="noopener noreferrer"&gt;pnpm&lt;/a&gt; and &lt;a href="https://yarnpkg.com/" rel="noopener noreferrer"&gt;Yarn&lt;/a&gt;. Go has &lt;a href="https://go.dev/ref/mod" rel="noopener noreferrer"&gt;modules&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We are used to being able to create a project with one command, describe dependencies in one file, fetch them from the network, run tests, and prepare a release. It feels like a basic part of the ecosystem, not a luxury.&lt;/p&gt;

&lt;p&gt;But older programming languages often have a different story.&lt;/p&gt;

&lt;p&gt;When many of them were created, this approach was not yet a standard expectation. Code was distributed differently, projects were structured differently, and ecosystems grew without the package managers and build tools we now take for granted.&lt;/p&gt;

&lt;p&gt;And you can still feel it today.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I Started Thinking About This
&lt;/h2&gt;

&lt;p&gt;For one of my projects I use &lt;a href="https://forth-standard.org/" rel="noopener noreferrer"&gt;Forth&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Forth is a very interesting language. It is minimalistic, direct, and unusual. There is something very attractive about it: you are close to computation, close to the stack, and close to the actual hardware of the computer, which I sometimes build myself.&lt;/p&gt;

&lt;p&gt;But when I started writing something in Forth that looked more or less like a project, I quickly began missing the usual things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;creating a new project;&lt;/li&gt;
&lt;li&gt;describing dependencies;&lt;/li&gt;
&lt;li&gt;downloading dependencies;&lt;/li&gt;
&lt;li&gt;running tests;&lt;/li&gt;
&lt;li&gt;having a clear project structure;&lt;/li&gt;
&lt;li&gt;connecting libraries from Git;&lt;/li&gt;
&lt;li&gt;not having to keep everything manually in my head.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Yes, you can use git submodules, copy files by hand, or invent your own conventions. But for me, this is not a very convenient path. I wanted something closer to what I am used to in modern languages.&lt;/p&gt;

&lt;p&gt;I found the &lt;code&gt;f.4th&lt;/code&gt; library, which is connected to &lt;a href="https://theforth.net/" rel="noopener noreferrer"&gt;theforth.net&lt;/a&gt;. It is a useful tool, but it follows a different approach: library code and versions are stored on its own server.&lt;/p&gt;

&lt;p&gt;I wanted to be able to pull dependencies directly from Git repositories. For example, specify a GitHub URL, a branch or a tag, and get the library into the project.&lt;/p&gt;

&lt;p&gt;That is how the idea for &lt;code&gt;fmix&lt;/code&gt; appeared.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is FMix
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;fmix&lt;/code&gt; is a small build tool and package tool for Forth, inspired by Elixir Mix.&lt;/p&gt;

&lt;p&gt;Repository: &lt;a href="https://github.com/VitaSound/fmix" rel="noopener noreferrer"&gt;github.com/VitaSound/fmix&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It does not try to be a large framework. Its goal is simpler: to give a Forth project a minimal set of familiar tools.&lt;/p&gt;

&lt;p&gt;Right now &lt;code&gt;fmix&lt;/code&gt; can do this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;fmix new example
fmix packages.get
fmix &lt;span class="nb"&gt;test
&lt;/span&gt;fmix version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In other words, you can create a new package, fetch dependencies, run tests, and check the tool version.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a Project
&lt;/h2&gt;

&lt;p&gt;A new project is created like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;fmix new example
&lt;span class="nb"&gt;cd &lt;/span&gt;example
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that, you get a basic project structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;example/
  example.4th
  package.4th
  README.md
  tests/
  forth-packages/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;package.4th&lt;/code&gt; is the package description file. It contains the name, version, license, main file, and dependencies.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;forth-package
    key-value name example
    key-value version 0.1.0
    key-value license COPL
    key-value description example
    key-value main example.4th

    key-list dependencies f git https://github.com/VitaSound/f tag 0.2.4
    key-list dependencies ttester git https://github.com/VitaSound/ttester tag 1.1.0
end-forth-package
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I like that the file itself is also written in a Forth-like style. It is not JSON, YAML, or TOML. It is a tiny declarative Forth format.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dependencies from Git
&lt;/h2&gt;

&lt;p&gt;The main reason I started making &lt;code&gt;fmix&lt;/code&gt; was Git dependencies.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;package.4th&lt;/code&gt;, you can define a dependency like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;key-list dependencies ftest git https://github.com/VitaSound/ftest.git branch main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or like this, if you need a specific version via a tag:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;key-list dependencies ftest git https://github.com/VitaSound/ftest.git tag 0.1.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that, you only need to run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;fmix packages.get
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dependencies will be installed into the local project directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;./forth-packages/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This structure makes it possible to keep different versions of the same library side by side:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;forth-packages/
  f/
    0.2.4/
  ttester/
    1.1.0/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can include a dependency with the usual &lt;code&gt;require&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;require ./forth-packages/f/0.2.4/f.4th
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Support for theforth.net
&lt;/h2&gt;

&lt;p&gt;Although I wanted Git dependencies, I did not want to completely abandon the existing ecosystem.&lt;/p&gt;

&lt;p&gt;So &lt;code&gt;fmix&lt;/code&gt; can also work with packages from &lt;code&gt;theforth.net&lt;/code&gt; through &lt;code&gt;f.4th&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;key-list dependencies f 0.2.4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This means one project can use both Git dependencies and packages from &lt;code&gt;theforth.net&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0rcr8nz7uo6p8j4kevur.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0rcr8nz7uo6p8j4kevur.png" alt=" " width="800" height="485"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Tests
&lt;/h2&gt;

&lt;p&gt;Another basic thing I was missing was running tests.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;fmix&lt;/code&gt; has this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;fmix &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It runs tests from the &lt;code&gt;tests/&lt;/code&gt; directory.&lt;/p&gt;

&lt;p&gt;You can also run a specific file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;fmix &lt;span class="nb"&gt;test &lt;/span&gt;tests/some_test.4th
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tests use &lt;code&gt;ttester&lt;/code&gt;. If &lt;code&gt;ttester&lt;/code&gt; exists in the project dependencies, &lt;code&gt;fmix&lt;/code&gt; loads it from &lt;code&gt;./forth-packages&lt;/code&gt;. If not, it uses the version from the installed &lt;code&gt;FMIX_HOME&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For me, this matters: tests should run with one command. Even if the project is small.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flo75871pjzbs5lre1cp3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flo75871pjzbs5lre1cp3.png" alt=" " width="800" height="488"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What Was Fixed in Recent Versions
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;fmix&lt;/code&gt; has already gone through several generations of changes.&lt;/p&gt;

&lt;p&gt;I wrote the first versions myself. But I am not a very strong Forth developer, so many things were difficult for me. I made one major refactoring with the help of Gemini. I finished the latest version with Cursor.&lt;/p&gt;

&lt;p&gt;The latest releases fixed quite a few practical problems.&lt;/p&gt;

&lt;p&gt;GitHub Actions CI was added: the workflow builds &lt;a href="https://www.gnu.org/software/gforth/" rel="noopener noreferrer"&gt;GForth&lt;/a&gt; 0.7.9 from source and runs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gforth fmix.4th &lt;span class="nt"&gt;-e&lt;/span&gt; version
gforth fmix.4th &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Later, a release pipeline was added: when a version tag is pushed, a GitHub Release is created automatically, and the release text is taken from &lt;code&gt;.github/RELEASE_NOTES_X.Y.Z.md&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Path handling was also fixed. Previously, part of the logic depended on &lt;code&gt;PWD&lt;/code&gt;. Now the project is detected from the directory where the command is started. This matters because &lt;code&gt;FMIX_HOME&lt;/code&gt; points to the installed &lt;code&gt;fmix&lt;/code&gt;, while commands should operate on the current project.&lt;/p&gt;

&lt;p&gt;Several dependency installation problems were fixed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;git clone&lt;/code&gt; now checks its result;&lt;/li&gt;
&lt;li&gt;failed shell commands make GForth exit with code &lt;code&gt;1&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;parent directories are created before &lt;code&gt;git clone&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;git fetch&lt;/code&gt; and &lt;code&gt;checkout&lt;/code&gt; are executed so that failures are not hidden;&lt;/li&gt;
&lt;li&gt;Git commands use &lt;code&gt;GIT_TERMINAL_PROMPT=0&lt;/code&gt;, so the command does not hang in a non-interactive environment.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Another important thing is input validation. &lt;code&gt;fmix&lt;/code&gt; validates package names, versions, paths, Git URLs, and Git refs before calling &lt;code&gt;cp&lt;/code&gt;, &lt;code&gt;sed&lt;/code&gt;, or &lt;code&gt;git&lt;/code&gt;. It is not a complex escaping system, but a simple whitelist. It rejects spaces, &lt;code&gt;;&lt;/code&gt;, &lt;code&gt;$&lt;/code&gt;, backticks, pipes, and other shell metacharacters.&lt;/p&gt;

&lt;h2&gt;
  
  
  An Unexpected Terminal Problem
&lt;/h2&gt;

&lt;p&gt;There was a separate story with the terminal. Before using the &lt;code&gt;fmix&lt;/code&gt; command in the console, it had to be configured as an alias.&lt;/p&gt;

&lt;p&gt;When running through a simple alias like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;fmix&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'gforth "$FMIX_HOME/fmix.4th" -e'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the terminal sometimes ended up in a bad state after commands finished. Strange symbols appeared in the prompt, for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0c0c
[?2004l
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This was especially visible in WSL.&lt;/p&gt;

&lt;p&gt;In version &lt;code&gt;0.4.4&lt;/code&gt;, I switched to the &lt;code&gt;bin/fmix&lt;/code&gt; launcher script. It restores the TTY after commands, resets bracketed paste mode, and briefly drains queued input from &lt;code&gt;/dev/tty&lt;/code&gt;. To be honest, I would definitely not have solved all of that on my own. I patiently helped the neural network try hypothesis after hypothesis to fix the problem. Unlike the AI tools I had tried before, this time I only had to stop the AI once and create a new context because it seemed to get stuck in an endless correction loop.&lt;/p&gt;

&lt;p&gt;But it worked, and now instead of an alias it is recommended to use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;FMIX_HOME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/fmix"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$FMIX_HOME&lt;/span&gt;&lt;span class="s2"&gt;/bin:&lt;/span&gt;&lt;span class="nv"&gt;$PATH&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then run it simply as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;fmix
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;p&gt;Right now installation looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/VitaSound/fmix.git ~/fmix
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then add this to your shell config, for example &lt;code&gt;.bashrc&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;FMIX_HOME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/fmix"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$FMIX_HOME&lt;/span&gt;&lt;span class="s2"&gt;/bin:&lt;/span&gt;&lt;span class="nv"&gt;$PATH&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that, the command should work directly in the console:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;fmix version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Important: at the moment &lt;code&gt;fmix&lt;/code&gt; expects Linux, Git, sed, cp, and &lt;a href="https://www.gnu.org/software/gforth/" rel="noopener noreferrer"&gt;GForth&lt;/a&gt; 0.7.9.&lt;/p&gt;

&lt;p&gt;I do not recommend using earlier versions of GForth or the &lt;a href="https://snapcraft.io/" rel="noopener noreferrer"&gt;Snap&lt;/a&gt; version. Snap runs programs in a confined environment, so the current directory and paths may not match what the shell session expects. This breaks commands like &lt;code&gt;new&lt;/code&gt; and &lt;code&gt;packages.get&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It is better to use GForth from apt, a local build, or a tarball from the &lt;a href="https://www.gnu.org/software/gforth/" rel="noopener noreferrer"&gt;official GForth page&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Matters
&lt;/h2&gt;

&lt;p&gt;I think old languages really need tools like this to fit modern realities.&lt;/p&gt;

&lt;p&gt;They do not have to be huge. They do not have to be perfect. But they should at least cover the basic scenarios. When a language has convenient tooling around projects, it becomes friendlier.&lt;/p&gt;

&lt;p&gt;It is easier for a newcomer to try the language. It is easier for an experienced user to start a new project. Libraries are easier to reuse. Tests are easier to run.&lt;/p&gt;

&lt;p&gt;This does not change the language itself, but it changes the experience of working with it. It allows an old tool to be used in new projects.&lt;/p&gt;

&lt;p&gt;In the case of Forth, this is especially interesting. Forth is often seen as something old, strange, and niche. But maybe part of that “oldness” is not only in the language itself, but also in the absence of familiar modern tooling around it.&lt;/p&gt;

&lt;p&gt;If we add convenient tools, the language can feel very different.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsixaust3ka33eqv8z3zr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsixaust3ka33eqv8z3zr.png" alt=" " width="720" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is Next
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;fmix&lt;/code&gt; is still small and experimental.&lt;/p&gt;

&lt;p&gt;Right now it can create packages, fetch dependencies from Git and &lt;code&gt;theforth.net&lt;/code&gt;, run tests, and publish releases through GitHub Actions.&lt;/p&gt;

&lt;p&gt;In the future, I would like to improve compatibility, add documentation, and maybe add more commands around Forth package development.&lt;/p&gt;

&lt;p&gt;But even now, it has become much more convenient for me to work on my Forth projects. But that is another story.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/VitaSound/fmix" rel="noopener noreferrer"&gt;FMix on GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.gnu.org/software/gforth/" rel="noopener noreferrer"&gt;GForth&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://theforth.net/" rel="noopener noreferrer"&gt;theforth.net&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/TG9541/stm8ef" rel="noopener noreferrer"&gt;STM8 eForth&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://t.me/forthchat" rel="noopener noreferrer"&gt;[NF] Forth-like languages, язык Форт&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://t.me/ruforth" rel="noopener noreferrer"&gt;[TF] Форт и общение фортеров&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>forth</category>
      <category>opensource</category>
      <category>tooling</category>
      <category>ai</category>
    </item>
    <item>
      <title>AD9833 DDS Generator Board</title>
      <dc:creator>Alexey Bolshakov</dc:creator>
      <pubDate>Thu, 19 Mar 2026 16:52:05 +0000</pubDate>
      <link>https://dev.to/ua3mqj/ad9833-dds-generator-board-10p7</link>
      <guid>https://dev.to/ua3mqj/ad9833-dds-generator-board-10p7</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Felfheihtro5s2nvhj93x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Felfheihtro5s2nvhj93x.png" alt="Image AD9833"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A frequency generator board based on the AD9833 chip. Purchased as a frequency-tunable clock signal source. The board is equipped with a 25 MHz oscillator. It can generate signals from 0 to 12.5 MHz (though waveform quality may not be satisfactory across the entire range). The waveform can be switched between sine, sawtooth, and square wave. All necessary signals are brought out to pin headers. Controlled via SPI interface.&lt;/p&gt;

&lt;p&gt;Architecturally, it contains one 28-bit phase accumulator register, two frequency tuning registers, and two phase offset registers. Only one pair (frequency/phase) can be active at a time. This allows for frequency modulation without phase discontinuity or phase modulation, if needed. However, there is no dedicated hardware input for selecting the register pair – switching is possible only via SPI commands.&lt;/p&gt;

&lt;p&gt;Oscilloscope waveforms follow below.&lt;/p&gt;




&lt;h2&gt;
  
  
  Test setup
&lt;/h2&gt;

&lt;p&gt;To control the DDS, commands must be sent via SPI. I am using an STM8 (STM8S105K4T6) with its hardware SPI. It was crucial to find the correct SPI operating mode. For the STM8 (and likely for STM32 as well), this is Mode 2 (CPOL = 1, CPHA = 0). For more details, refer to the documentation.(&lt;a href="https://www.st.com/resource/en/reference_manual/cd00190271-stm8s-series-and-stm8af-series-8bit-microcontrollers-stmicroelectronics.pdf" rel="noopener noreferrer"&gt;RM0016&lt;/a&gt; - STM8S Series and STM8AF Series 8-bit microcontrollers (20.4 SPI registers)). Oscilloscope: C1-112A, 10 MHz bandwidth; probe: generic Chinese P6100 type, rated for 100 MHz. Multimeter: Aneng M20, used as a frequency counter.&lt;/p&gt;

&lt;p&gt;I did not write firmware for the microcontroller in the conventional sense. Instead, I flashed the STM8 with the &lt;a href="https://github.com/TG9541/stm8ef/wiki/STM8-eForth-Programming" rel="noopener noreferrer"&gt;eForth&lt;/a&gt; system and connected to it via a serial console. From the console, I sent SPI commands directly, after pre-defining the necessary intermediate words. It looked roughly like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...

: word.hi $0100 / ;
: word.lo $00ff and ;

: spi_wr8 SPI_DR c! TXE? ;
: spi_wr16  dup word.lo swap word.hi spi_wr8 spi_wr8 ;
: spi_wr16n dup word.lo swap word.hi nss.lo spi_wr8 spi_wr8 BSY? nss.hi ;
: spi_wr32n nss.lo spi_wr16 spi_wr16 bsy? nss.hi ;

...

$2100 spi_wr16n         // reset
$5c20 $4a3d spi_wr32n   // freq0
%0111111111111111 %0100000000000000 spi_wr32n   // freq0
%0111111111111111 spi_wr16n %0100000000000000 spi_wr16n
$9c29 $8a3d spi_wr32n   // freq1
$c000 spi_wr16n         // phase0f
$e000 spi_wr16n         // phase1
$2000 spi_wr16n         // sine
$2020 spi_wr16n         // square
$2002 spi_wr16n         // saw      
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It turned out that I used the system interactively, rather than reflashing the firmware each time. This approach reminds me of working with the Erlang virtual machine, where you can debug and modify running code on the fly on production.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhmenxcavudzcsq9l18i1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhmenxcavudzcsq9l18i1.png" alt="Image stage"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Oscilloscope Waveforms
&lt;/h2&gt;

&lt;p&gt;Sine 1 KHz&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgre9dzga7hhnrybkjebz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgre9dzga7hhnrybkjebz.png" alt="Image Sine1 KHz"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;
  10 KHz, 50 KHz, 100 KHz, 500 KHz, 2 MHz, 4 MHz, 8 MHz
  &lt;br&gt;
10 KHz&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5dxg89qfbljtj3vhuzt6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5dxg89qfbljtj3vhuzt6.png" alt="Image 10 KHz"&gt;&lt;/a&gt;

&lt;p&gt;50 KHz&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpi53qz4gy44afwajj3dt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpi53qz4gy44afwajj3dt.png" alt="Image 50 KHz"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;100 KHz&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feh5nv6oq9bxomzjp8gg2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feh5nv6oq9bxomzjp8gg2.png" alt="Image 100 KHz"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;500 KHz&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8ve7ncv6li2zsxvm1ov4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8ve7ncv6li2zsxvm1ov4.png" alt="Image 500 KHz"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;2 MHz&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc6gq0go0fuc27iexxcp8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc6gq0go0fuc27iexxcp8.png" alt="Image 2 MHz"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;4 MHz&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmxk39bzz5ln6jzyvlcqb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmxk39bzz5ln6jzyvlcqb.png" alt="Image 4 MHz"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;8 MHz&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjiy4salusx0vv0pp57t6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjiy4salusx0vv0pp57t6.png" alt="Image 8 MHz"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Saw 1 KHz&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fahqs1lpi4brm6jmor8dc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fahqs1lpi4brm6jmor8dc.png" alt="Image Saw 1 KHz"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;
  10 KHz, 50 KHz, 100 KHz, 500 KHz, 2 MHz, 4 MHz, 8 MHz
  &lt;br&gt;
10 KHz&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnc7dlcl09rcqd9u2qcuy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnc7dlcl09rcqd9u2qcuy.png" alt="Image 10 KHz"&gt;&lt;/a&gt;

&lt;p&gt;50 KHz&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6u9000y6t6jk509jp808.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6u9000y6t6jk509jp808.png" alt="Image 50 KHz"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;100 KHz&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsmjy5uomci3yxtp55ax0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsmjy5uomci3yxtp55ax0.png" alt="Image 100 KHz"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;500 KHz&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgierffe0rmqpqxqed7lg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgierffe0rmqpqxqed7lg.png" alt="Image 500 KHz"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;2 MHz&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgqynd0h8twct13rtitx2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgqynd0h8twct13rtitx2.png" alt="Image 2 MHz"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;4 MHz&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsdxyldw8i9zbh3bmn3mn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsdxyldw8i9zbh3bmn3mn.png" alt="Image 4 MHz"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;8 MHz&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F045pv58x0580w4wo25ao.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F045pv58x0580w4wo25ao.png" alt="Image 8 MHz"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;At 2 MHz, floating peaks on the sawtooth waveform are already visible. At 4 MHz, they become very pronounced. And at 8 MHz, we end up with 25/8 = 3.125 samples per period.&lt;/p&gt;

&lt;p&gt;Purely to explore my oscilloscope and probes, I also tried the square wave mode. However, I couldn't be bothered to recalculate the frequency grid. In square wave mode, the period is twice as long, so the resulting frequencies were different.&lt;/p&gt;

&lt;p&gt;5 kHz&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhoeizj2fsnbn97c61vcg.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhoeizj2fsnbn97c61vcg.jpeg" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;
  25 KHz, 250 KHz, 1 MHz, 2 MHz, 4 MHz
  &lt;br&gt;
25 KHz&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsq3p19qbz6of1ut4cio4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsq3p19qbz6of1ut4cio4.png" alt="Image 25 KHz"&gt;&lt;/a&gt;

&lt;p&gt;250 KHz&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxf9hzwuaib7166jmyri8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxf9hzwuaib7166jmyri8.png" alt="Image 250 KHz"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;1 MHz&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz28r0lvfv3po9dkv0bd9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz28r0lvfv3po9dkv0bd9.png" alt="Image 1 MHz"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;2 MHz&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft3ieelatpjf4uuey8o2v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft3ieelatpjf4uuey8o2v.png" alt="Image 2 MHz"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;4 MHz&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5q96bjuitxchsjbrhf0p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5q96bjuitxchsjbrhf0p.png" alt="Image 4 MHz"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;4 MHz more wide&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F809p1xc65h4nbwnxhisf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F809p1xc65h4nbwnxhisf.png" alt="Image 4 MHz wide"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Starting from 1 MHz, jitter is obviously present; at 2 MHz, it becomes visible on the oscilloscope waveform.&lt;/p&gt;

&lt;p&gt;By the way (for those who aren't aware), it's important to note that at high frequencies, to avoid degrading signal edges, you should use the probe in 10:1 attenuation mode. This reduces the probe's loading effect on the circuit (and it's even better to avoid using alligator clips altogether). However, this will require increasing the oscilloscope's input amplifier gain by a factor of 10 to compensate for the attenuation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm701spnv3sctzfocffhw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm701spnv3sctzfocffhw.png" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Also, don't forget to adjust the probe compensation for accurate waveform display, using a small dielectric (non-metallic) screwdriver.&lt;/p&gt;

&lt;p&gt;For comparison, here's a photo showing the same signal — a 2 MHz square wave — captured with the probe set to 1X versus 10X attenuation.&lt;/p&gt;

&lt;p&gt;2 MHz - 1х&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Farvg1btsyj3ank7liduy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Farvg1btsyj3ank7liduy.png" alt="Image 2 MHz - 1х"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;2 MHz - 10х&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhvems2wak8undlhvq8au.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhvems2wak8undlhvq8au.png" alt="Image 2 MHz - 10х"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By the way, the original probe that came with the C1-112A is also quite decent.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F98989yjzxeu24nflfpx1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F98989yjzxeu24nflfpx1.png" alt="Image probe С1-112А"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;2 MHz - 10х&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc5c12agelm0uzcx9xv3h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc5c12agelm0uzcx9xv3h.png" alt="Image 2 MHz - 10х"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusions
&lt;/h2&gt;

&lt;p&gt;I acquired this board for experiments in the field of hybrid sound synthesis for my synthesizer project. In the future, I plan to use it for a DCO (Digitally Controlled Oscillator) module — but not with a fixed Master Clock frequency; rather, with a frequency that is a multiple of the generated note frequency. This way, the DAC in the DCO can utilize its full scale and DAC resolution without skipping steps. All of this is part of the effort to combat generation accuracy loss and aliasing... But that's a whole different story.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;p&gt;1 The original version of this article&lt;/p&gt;

&lt;p&gt;&lt;a href="https://mysku.club/blog/aliexpress/79168.html" rel="noopener noreferrer"&gt;https://mysku.club/blog/aliexpress/79168.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;2 My Telegram channel "Programmer's Tips": &lt;a href="https://t.me/ProProgs" rel="noopener noreferrer"&gt;https://t.me/ProProgs&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;3 eForth - Forth for microcontrollers&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/TG9541/stm8ef/wiki/STM8-eForth-Programming" rel="noopener noreferrer"&gt;https://github.com/TG9541/stm8ef/wiki/STM8-eForth-Programming&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;4 Links about my synth project&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/UA3MQJ/fpga-synth/wiki" rel="noopener noreferrer"&gt;https://github.com/UA3MQJ/fpga-synth/wiki&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/VitaSound/hdl-modules" rel="noopener noreferrer"&gt;https://github.com/VitaSound/hdl-modules&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://soundcloud.com/vitasynth" rel="noopener noreferrer"&gt;https://soundcloud.com/vitasynth&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.youtube.com/channel/UCGi-A9KGhKhKzVT_baVw3HA" rel="noopener noreferrer"&gt;http://www.youtube.com/channel/UCGi-A9KGhKhKzVT_baVw3HA&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://vk.com/vitasound" rel="noopener noreferrer"&gt;https://vk.com/vitasound&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://boosty.to/vitasound" rel="noopener noreferrer"&gt;https://boosty.to/vitasound&lt;/a&gt;&lt;/p&gt;

</description>
      <category>dds</category>
      <category>microchips</category>
      <category>stm8</category>
      <category>microcontroller</category>
    </item>
    <item>
      <title>Плата DDS генератора AD9833</title>
      <dc:creator>Alexey Bolshakov</dc:creator>
      <pubDate>Thu, 19 Mar 2026 16:35:39 +0000</pubDate>
      <link>https://dev.to/ua3mqj/plata-dds-ghienieratora-ad9833-bh7</link>
      <guid>https://dev.to/ua3mqj/plata-dds-ghienieratora-ad9833-bh7</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Felfheihtro5s2nvhj93x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Felfheihtro5s2nvhj93x.png" alt="Image AD9833"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Плата с DDS генератором частоты на базе микросхемы AD9833. Приобретена в качестве источника тактового сигнала, перестраиваемого по частоте. На плате установлен генератор на 25 МГц. Может генерировать сигналы от 0 до 12.5 МГц (но не во всем диапазоне вас устроит форма сигнала). Можно переключать форму сигнала: синус, пила, меандр. Всё, что нужно, выведено на штыревые контакты. Управляется по SPI. Архитектурно содержит один 28-битный регистр аккумулятора, два регистра приращения, два регистра фазы. В один момент времени может быть выбрана только одна из двух пар. Это позволит, если необходимо, сформировать частотную модуляцию сигнала без разрыва фазы или фазовую модуляцию. Однако, отдельного входа выбора пары нет, переключение возможно только командами по SPI.&lt;/p&gt;

&lt;p&gt;Далее осциллограммы&lt;/p&gt;




&lt;h2&gt;
  
  
  Стенд
&lt;/h2&gt;

&lt;p&gt;Для управления DDS нужно подавать команды по SPI. Использую STM8 (STM8S105K4T6) и его аппаратный SPI. Очень важно было найти правильный режим работы SPI. Для STM8 (и наверняка для STM32) это будет mode 2 (CPOL = 1 and CPHA = 0). Подробнее, см. документацию(&lt;a href="https://www.st.com/resource/en/reference_manual/cd00190271-stm8s-series-and-stm8af-series-8bit-microcontrollers-stmicroelectronics.pdf" rel="noopener noreferrer"&gt;RM0016&lt;/a&gt; - STM8S Series and STM8AF Series 8-bit microcontrollers (20.4 SPI registers)). Осциллограф С1-112А полоса 10 МГц, щуп китайский на 100 китайских МГц (P6100). Мультиметр Aneng M20 в качестве частотомера.&lt;/p&gt;

&lt;p&gt;Прошивку для микроконтроллера в привычном для всех виде я не писал. Просто поставил на микроконтроллер STM8 систему &lt;a href="https://github.com/TG9541/stm8ef/wiki/STM8-eForth-Programming" rel="noopener noreferrer"&gt;eForth&lt;/a&gt; и далее подключался к нему через консоль. И уже в консоли отправлял команды через SPI, задав перед этим необходимые промежуточные слова. Выглядело это примерно вот так&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...

: word.hi $0100 / ;
: word.lo $00ff and ;

: spi_wr8 SPI_DR c! TXE? ;
: spi_wr16  dup word.lo swap word.hi spi_wr8 spi_wr8 ;
: spi_wr16n dup word.lo swap word.hi nss.lo spi_wr8 spi_wr8 BSY? nss.hi ;
: spi_wr32n nss.lo spi_wr16 spi_wr16 bsy? nss.hi ;

...

$2100 spi_wr16n         // reset
$5c20 $4a3d spi_wr32n   // freq0
%0111111111111111 %0100000000000000 spi_wr32n   // freq0
%0111111111111111 spi_wr16n %0100000000000000 spi_wr16n
$9c29 $8a3d spi_wr32n   // freq1
$c000 spi_wr16n         // phase0f
$e000 spi_wr16n         // phase1
$2000 spi_wr16n         // sine
$2020 spi_wr16n         // square
$2002 spi_wr16n         // saw      
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Получилось, что я пользовался системой интерактивно, а не перепрошивая каждый раз. Мне такой подход напоминает работу с Erlang виртуальной машиной, когда можно на ходу отлаживать и менять работающий код.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhmenxcavudzcsq9l18i1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhmenxcavudzcsq9l18i1.png" alt="Image stage"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Осциллограммы
&lt;/h2&gt;

&lt;p&gt;Синус 1 КГц&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgre9dzga7hhnrybkjebz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgre9dzga7hhnrybkjebz.png" alt="Image Синус 1 КГц"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;
  10 КГц, 50 КГц, 100 КГц, 500 КГц, 2 МГц, 4 МГц, 8 МГц
  &lt;br&gt;
10 КГц&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5dxg89qfbljtj3vhuzt6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5dxg89qfbljtj3vhuzt6.png" alt="Image 10 КГц"&gt;&lt;/a&gt;

&lt;p&gt;50 КГц&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpi53qz4gy44afwajj3dt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpi53qz4gy44afwajj3dt.png" alt="Image 50 КГц"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;100 КГц&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feh5nv6oq9bxomzjp8gg2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feh5nv6oq9bxomzjp8gg2.png" alt="Image 100 КГц"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;500 КГц&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8ve7ncv6li2zsxvm1ov4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8ve7ncv6li2zsxvm1ov4.png" alt="Image 500 КГц"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;2 МГц&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc6gq0go0fuc27iexxcp8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc6gq0go0fuc27iexxcp8.png" alt="Image 2 МГц"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;4 МГц&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmxk39bzz5ln6jzyvlcqb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmxk39bzz5ln6jzyvlcqb.png" alt="Image 4 МГц"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;8 МГц&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjiy4salusx0vv0pp57t6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjiy4salusx0vv0pp57t6.png" alt="Image 8 МГц"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Пила 1 КГц&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fahqs1lpi4brm6jmor8dc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fahqs1lpi4brm6jmor8dc.png" alt="Image Пила 1 КГц"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;
  10 КГц, 50 КГц, 100 КГц, 500 КГц, 2 МГц, 4 МГц, 8 МГц
  &lt;br&gt;
10 КГц&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnc7dlcl09rcqd9u2qcuy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnc7dlcl09rcqd9u2qcuy.png" alt="Image 10 КГц"&gt;&lt;/a&gt;

&lt;p&gt;50 КГц&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6u9000y6t6jk509jp808.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6u9000y6t6jk509jp808.png" alt="Image 50 КГц"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;100 КГц&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsmjy5uomci3yxtp55ax0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsmjy5uomci3yxtp55ax0.png" alt="Image 100 КГц"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;500 КГц&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgierffe0rmqpqxqed7lg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgierffe0rmqpqxqed7lg.png" alt="Image 500 КГц"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;2 МГц&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgqynd0h8twct13rtitx2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgqynd0h8twct13rtitx2.png" alt="Image 2 МГц"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;4 МГц&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsdxyldw8i9zbh3bmn3mn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsdxyldw8i9zbh3bmn3mn.png" alt="Image 4 МГц"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;8 МГц&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F045pv58x0580w4wo25ao.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F045pv58x0580w4wo25ao.png" alt="Image 8 МГц"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;На 2 МГц уже видно плавающие пики пилы. На 4 МГц видно уже очень отчетливо. Ну и на 8 МГц у нас получается 25/8 = 3,125 отсчета на период.&lt;/p&gt;

&lt;p&gt;Исключительно ради изучения своего осциллографа и щупов, попробовал меандр. Правда сетку частот пересчитывать было лень. В режиме меандра, период в 2 раза длиннее, поэтому частоты получились другие.&lt;/p&gt;

&lt;p&gt;5 КГц&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fge7bqykm1edhv6737e3z.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fge7bqykm1edhv6737e3z.jpeg" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;
  25 КГц, 250 КГц, 1 МГц, 2 МГц, 4 МГц
  &lt;br&gt;
25 КГц&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsq3p19qbz6of1ut4cio4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsq3p19qbz6of1ut4cio4.png" alt="Image 25 КГц"&gt;&lt;/a&gt;

&lt;p&gt;250 КГц&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxf9hzwuaib7166jmyri8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxf9hzwuaib7166jmyri8.png" alt="Image 250 КГц"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;1 МГц&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz28r0lvfv3po9dkv0bd9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz28r0lvfv3po9dkv0bd9.png" alt="Image 1 МГц"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;2 МГц&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft3ieelatpjf4uuey8o2v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft3ieelatpjf4uuey8o2v.png" alt="Image 2 МГц"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;4 МГц&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5q96bjuitxchsjbrhf0p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5q96bjuitxchsjbrhf0p.png" alt="Image 4 МГц"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;4 МГц более развернуто&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F809p1xc65h4nbwnxhisf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F809p1xc65h4nbwnxhisf.png" alt="Image 4 МГц wide"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;br&gt;
&lt;br&gt;&lt;br&gt;
Начиная с 1 МГц, ясное дело - джиттер, на 2 МГц его видно на осциллограмме.&lt;/p&gt;

&lt;p&gt;Кстати (для тех, кто не в курсе), важно, что на высоких частотах, чтобы не портить фронты, нужно использовать щуп в режиме 1:10, чтобы он меньше влиял на схему (а еще лучше не использовать крокодил). Но потребуется усилить сигнал в 10 раз уже на входном усилителе осциллографа.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm701spnv3sctzfocffhw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm701spnv3sctzfocffhw.png" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Так же, не стоит забывать подстраивать делитель для правильного отображения, диэлектрической отверточкой.&lt;/p&gt;

&lt;p&gt;Для сравнения, фото, как выглядит один и тот же сигнал - меандр 2 МГц, но 1Х или 10Х&lt;/p&gt;

&lt;p&gt;2 МГц - 1х&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Farvg1btsyj3ank7liduy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Farvg1btsyj3ank7liduy.png" alt="Image 2 МГц - 1х"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;2 МГц - 10х&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhvems2wak8undlhvq8au.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhvems2wak8undlhvq8au.png" alt="Image 2 МГц - 10х"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Кстати, родной щуп от С1-112А тоже неплох&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F98989yjzxeu24nflfpx1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F98989yjzxeu24nflfpx1.png" alt="Image щуп от С1-112А"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;2 МГц - 10х&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc5c12agelm0uzcx9xv3h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc5c12agelm0uzcx9xv3h.png" alt="Image 2 МГц - 10х"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Выводы
&lt;/h2&gt;

&lt;p&gt;Эту плату я брал для экспериментов в области создания гибридного синтеза звука своего синтезаторного проекта. В дальнейшем планируется использовать для модуля генератора DCO (Digital VCO) но не с фиксированной частотой Master Clock а с частотой, кратной частоте генерации, для того, чтобы DAC в DCO использовал всю свою шкалу и разрядность, не пропускал шаги. Все это в рамках борьбы с потерей точности генерации, борьбы с алиасингом... Но это уже совсем другая история&lt;/p&gt;

&lt;h2&gt;
  
  
  Ссылки
&lt;/h2&gt;

&lt;p&gt;1 Исходная версия этой статьи&lt;/p&gt;

&lt;p&gt;&lt;a href="https://mysku.club/blog/aliexpress/79168.html" rel="noopener noreferrer"&gt;https://mysku.club/blog/aliexpress/79168.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;2 Мой канал в TG "Советы программиста" &lt;a href="https://t.me/ProProgs" rel="noopener noreferrer"&gt;https://t.me/ProProgs&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;3 eForth - язык Forth для микроконтроллеров &lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/TG9541/stm8ef/wiki/STM8-eForth-Programming" rel="noopener noreferrer"&gt;https://github.com/TG9541/stm8ef/wiki/STM8-eForth-Programming&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;4 Ссылки по моему синтезаторному проекту&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/UA3MQJ/fpga-synth/wiki" rel="noopener noreferrer"&gt;https://github.com/UA3MQJ/fpga-synth/wiki&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/VitaSound/hdl-modules" rel="noopener noreferrer"&gt;https://github.com/VitaSound/hdl-modules&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://soundcloud.com/vitasynth" rel="noopener noreferrer"&gt;https://soundcloud.com/vitasynth&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.youtube.com/channel/UCGi-A9KGhKhKzVT_baVw3HA" rel="noopener noreferrer"&gt;http://www.youtube.com/channel/UCGi-A9KGhKhKzVT_baVw3HA&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://vk.com/vitasound" rel="noopener noreferrer"&gt;https://vk.com/vitasound&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://boosty.to/vitasound" rel="noopener noreferrer"&gt;https://boosty.to/vitasound&lt;/a&gt;&lt;/p&gt;

</description>
      <category>dds</category>
      <category>microchips</category>
      <category>stm8</category>
      <category>microcontroller</category>
    </item>
  </channel>
</rss>
