Сегодня принимают поздравления с профессиональным праздником некоторые гики, ну и чтобы поднять настроение себе и остальным, захотелось поделиться историей создания красочного, светодиодного, радиотехнического… И да! для вечно живого 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!
DolphinSoft
Продолжу эту славную традицию:
Пускай идеи множатся, их воплощения рождаются и дальше, а полезность этих идей процветает!
Успешных реализаций и впредь, в условиях отсутствия белого дыма! :)
Pyhesty Автор
Спасибо, Dolphin)))
как ни странно идеи еще есть, жаль времени свободного маловато =) современная элементная база очень-очень мощная, но ZX и MSX прекрасны в своей архитектуре и красоте решений, мне нравится к ним обращаться в своих хобби)