
Сегодня принимают поздравления с профессиональным праздником некоторые гики, ну и чтобы поднять настроение себе и остальным, захотелось поделиться историей создания красочного, светодиодного, радиотехнического… И да! для вечно живого Z80!
Если вы не представляете, что ещё можно такого придумать для Z80 в XXI веке, прошу под кат...
Когда под моим прошлым постом посвященным демо Bad Apple для MSX, @DolphinSoftнаписал: "Пускай это будет не последнее творение под MSX", то я поду��ал "Ну уж нет, хватит, нечто новое для Z80 придумать сложно!". Но уже вскоре вдруг пришло желание разнообразить вечерний просмотр демо. Преимуществом MSX перед множеством других моделей компьютеров на Z80 является наличие слота, в который обычно устанавливаются картриджи ROM с играми/программами. Так как слот в большинстве случаев располагается сверху, то визуальный картридж было бы интересно разместить именно в этом слоте, в верхней части картриджа.

Звук в стандарте компьютера MSX реализуется микросхемой трехканального генератора звука Yamaha YM2149, регистры управления которой располагаются на портах 0xA0 и 0xA1. И, к счастью, в слоте картриджа все сигналы для записи в порт присутствуют и их можно перехватить.
Но чтобы разрабатывать картридж было интереснее, то сразу были добавлены несколько ограничений: во-первых картридж должен быть на элементной базе конца 90х годов, дешевой и доступной для покупки на али сейчас, если это условие можно выполнить, значит аналогичный картридж мог бы появиться раньше. Во-вторых, картридж должен быть максимально простым, чтобы остальные радиолюбители могли без проблем его воспроизвести.
Таким образом, какие задачи должен решать такой картридж:
размещаться в слот MSX
перехватывать запись в порты микросхемы звукового генератора
анализировать значения записанных звуковых нот и визуализировать их
На конец 90х годов - начало 2000х уже начали появляться PLD средней степени интеграции MAX7000 серии, в частности EPM7128 содержащие 128 блоков логики с регистром на выходе. И, что приятно, они совместимы с 5В уровнями Z80, не требуют микросхемы для хранения прошивки, имеют достаточно большое количество выводов для подключения диодов, доступны сейчас и дешевы в закупке.
Чтобы убедиться в возможности разработки на такой небольшой микросхеме, было проведено математическое моделирование визуализатора с одновременной разработкой проекта под PLD. Запись в порт с ре��льных игр и демо была записана на эмуляторе openMSX и далее обработана в математической модели PLD на Matlab. Результат работы такой модели на видео, где справа работа 9-ти индикаторов частот аудионот, записываемых в звукогенератор YM2149.

После разработки математической модели визуализатора была проведена работа по упрощению кода PLD таким образом, чтобы логическая схема разместилась в 128 логических блоках EPM7128. В какой-то момент удалось найти баланс между упрощением модели визуализации и плотным заполнением выбранной PLD.
Код пришлось максимально облегчить: собственно захватывается адрес регистра YM2149 при записи в порт 0xA0, далее, в зависимости от адреса, захватывается либо частота ноты, либо её уровень громкости. Значение уровня громкости загружается в один из девяти счетчиков светодиодных баров. С целью упрощения используются не все биты частоты и громкости.
немного кода PLD
cnt_to_3[] = cnt_div.q[15..14];
(spec[8..0], cnt_div).clock = gclk;
(RegAddr[], FreqA[], FreqB[], FreqC[], ValA[], ValB[], ValC[]).clk = gclk;
RegAddr[] = data[3..0];
RegAddr[].ena = !wr&!ioreq&(addr[7..0]==H"A0");
(FreqA[3..2], FreqB[3..2], FreqC[3..2]) = data[7..6];
(FreqA[6..4], FreqB[6..4], FreqC[6..4]) = data[2..0]#data[3];
( ValA[2..0], ValB[2..0], ValC[2..0]) = data[3..1];
FreqA[3..2].ena = !wr&!ioreq&(addr[7..0]==H"A1")&(RegAddr[]==H"00");
FreqB[3..2].ena = !wr&!ioreq&(addr[7..0]==H"A1")&(RegAddr[]==H"02");
FreqC[3..2].ena = !wr&!ioreq&(addr[7..0]==H"A1")&(RegAddr[]==H"04");
FreqA[6..4].ena = !wr&!ioreq&(addr[7..0]==H"A1")&(RegAddr[]==H"01");
FreqB[6..4].ena = !wr&!ioreq&(addr[7..0]==H"A1")&(RegAddr[]==H"03");
FreqC[6..4].ena = !wr&!ioreq&(addr[7..0]==H"A1")&(RegAddr[]==H"05");
ValA[].ena = !wr&!ioreq&(addr[7..0]==H"A1")&(RegAddr[]==H"08");
ValB[].ena = !wr&!ioreq&(addr[7..0]==H"A1")&(RegAddr[]==H"09");
ValC[].ena = !wr&!ioreq&(addr[7..0]==H"A1")&(RegAddr[]==H"0A");
spec[0].cnt_en = !spec[0].cout&cnt_div.cout;
spec[1].cnt_en = (spec[1].q[]>0)&cnt_div.cout; -- (spec[7].q[]>0);
spec[2].cnt_en = (spec[2].q[]>0)&cnt_div.cout; -- (spec[7].q[]>0);
spec[3].cnt_en = (spec[3].q[]>0)&cnt_div.cout; -- (spec[7].q[]>0);
spec[4].cnt_en = (spec[4].q[]>0)&cnt_div.cout; -- (spec[7].q[]>0);
spec[5].cnt_en = (spec[5].q[]>0)&cnt_div.cout; -- (spec[7].q[]>0);
spec[6].cnt_en = (spec[6].q[]>0)&cnt_div.cout; -- (spec[7].q[]>0);
spec[7].cnt_en = (spec[7].q[]>0)&cnt_div.cout; -- (spec[7].q[]>0);
spec[8].cnt_en = (spec[8].q[]>0)&cnt_div.cout; -- (spec[8].q[]>0);
if !wr&!ioreq&(addr[7..0]==H"A1") then
if (RegAddr[]==H"00")#(RegAddr[]==H"01")#(RegAddr[]==H"08") then
Val_ch[] = ValA[];
spec[8].sload = (FreqA[6..2] <H"02");
spec[7].sload = (FreqA[6..2]>=H"02")&(FreqA[6..2] <H"03");
spec[6].sload = (FreqA[6..2]>=H"03")&(FreqA[6..2] <H"05");
spec[5].sload = (FreqA[6..2]>=H"05")&(FreqA[6..2] <H"07");
spec[4].sload = (FreqA[6..2]>=H"07")&(FreqA[6..2] <H"0A");
spec[3].sload = (FreqA[6..2]>=H"0A")&(FreqA[6..2] <H"0C");
spec[2].sload = (FreqA[6..2]>=H"0C")&(FreqA[6..2] <H"0F");
spec[1].sload = (FreqA[6..2]>=H"0F")&(FreqA[6..2] <H"18");
spec[0].sload = (FreqA[6..2]>=H"18");
end if;
if (RegAddr[]==H"02")#(RegAddr[]==H"03")#(RegAddr[]==H"09") then
Val_ch[] = ValB[];
spec[8].sload = (FreqB[6..2] <H"02");
spec[7].sload = (FreqB[6..2]>=H"02")&(FreqB[6..2] <H"03");
spec[6].sload = (FreqB[6..2]>=H"03")&(FreqB[6..2] <H"05");
spec[5].sload = (FreqB[6..2]>=H"05")&(FreqB[6..2] <H"07");
spec[4].sload = (FreqB[6..2]>=H"07")&(FreqB[6..2] <H"0A");
spec[3].sload = (FreqB[6..2]>=H"0A")&(FreqB[6..2] <H"0D");
spec[2].sload = (FreqB[6..2]>=H"0D")&(FreqB[6..2] <H"0F");
spec[1].sload = (FreqB[6..2]>=H"0F")&(FreqB[6..2] <H"18");
spec[0].sload = (FreqB[6..2]>=H"18");
end if;
if (RegAddr[]==H"04")#(RegAddr[]==H"05")#(RegAddr[]==H"0A") then
Val_ch[] = ValC[];
spec[8].sload = (FreqC[6..2] <H"02");
spec[7].sload = (FreqC[6..2]>=H"02")&(FreqC[6..2] <H"03");
spec[6].sload = (FreqC[6..2]>=H"03")&(FreqC[6..2] <H"05");
spec[5].sload = (FreqC[6..2]>=H"05")&(FreqC[6..2] <H"07");
spec[4].sload = (FreqC[6..2]>=H"07")&(FreqC[6..2] <H"0A");
spec[3].sload = (FreqC[6..2]>=H"0A")&(FreqC[6..2] <H"0D");
spec[2].sload = (FreqC[6..2]>=H"0D")&(FreqC[6..2] <H"0F");
spec[1].sload = (FreqC[6..2]>=H"0F")&(FreqC[6..2] <H"18");
spec[0].sload = (FreqC[6..2]>=H"18");
end if;
end if;
spec[0].data[] = Val_ch[];
spec[1].data[] = Val_ch[];
spec[2].data[] = Val_ch[];
spec[3].data[] = Val_ch[];
spec[4].data[] = Val_ch[];
spec[5].data[] = Val_ch[];
spec[6].data[] = Val_ch[];
spec[7].data[] = Val_ch[];
spec[8].data[] = Val_ch[];Когда математическая модель получилась, наступило время приступать к разработке схемы, которая была максимально упрощена: не используются транзисторы или повторители для диодов, а с целью недопущения перегрузки портов PLD диоды разделены на три группы, которые мультиплицируются, не используются стабилизаторы напряжения и генератор. Все резисторы выбраны 1кОм. Такая схема предельно проста, и может быть собрана радиолюбителем.


Ну и самое удивительное для разработчика состояло в том, что после сборки и программирования математической модели плата сразу же ожила, не потребовав отладки, а только настройки диапазонов каждого из девяти каналов. Ниже видео работы платы с играми и демо:
Ну и, конечно же, сразу захотелось добавить аналогичный визуализатор и для своего любимого Скорпиона 256к. Для этого потребовалось разработать подставку для установки слота и картриджа, а также припаять на порты микросхемы AY-3-8910 сигналы



Ну и, конечно же, теперь можно посмотреть любимые демо в новом оформлении =)
ну и видео в корпусе с другими цветами на Скорпионе
Теперь просмотр дем на ZX Spectrum и MSX не будет прежним!
Ну и, наверное, самое главное. Проект локализован группой RBSC и является открытым, каждый может собрать и произвести такой визуализатор для себя. Ссылка на страничку проекта: MSX-EQ PSG Spectrolyzer для платформы MSX.
и проекты на github для MSX и для ZX Spectrum.
Всем кто захочет собрать - легкой сборки, буду рад вашим фото и видео в комментариях =)
Большое спасибо группе RBSC, World_of_MSX, а также всем, кто оказывал поддержку и помогал в тестировании. Очень приятно творить, ощущая вашу поддержку.
Всех с Днем Радио! За связь без брака! 73!