Здравствуйте, дорогие мои любители программных археологических раскопок и аппаратных копролитов, утонувших во мраке веков. Сегодня наш Отдел Перспективных Разработок представит вам свое новое детище, связанное с доработкой известного в узких кругах ультрабюджетного простейшего многоплатного восьмибитного компьютера Z80-MBC2 для подключения WIFI-модема с целью зайти через него, например, на BBS, или даже, в перспективе, создания подобия простейшего веб-браузера.  Компьютер представляет из себя множество вариантов реализации, раскиданных по всему интернету и поддерживающимися энтузиастами в разных странах, Все реализации, как правило, базируются на примерно одной и той же схеме - основная плата с процессором Z80, 128 Кб статической памяти, переключающей банки памяти одной логической микросхемы (74HC00) и обслуживающего все это хозяйство для связи всех шин передачи данных какого-нибудь контроллера (чаще Atmega-32A, как в оригинальной схеме).  Подробно схему описывать здесь не будем, их полон гугл. Ссылка на оригинал разработчика имеется. С внешним миром данный компьютер общается посредством эмуляции терминала VT-100, через преобразователь TTL-USB или TTL-COM. На отдельных платах так же существуют реализации интерфейсов позволяющие подключать вывод терминала на VGA-дисплей и производить ввод через PS/2-клавиатуру. Компьютер поддерживает широкий ряд софта и операционных систем, где каждый может подобрать что-то интересное для себя: Это и CP/M 2.2 и CP/M 3.0, и QP/M, всякие USCD Pascal, и даже Collapse OS. Некоторые умные люди пытаются прикрутить к подобному семейству компьютеров вариант линукса Fuzix, но, пока дело с портированием застряло. Это и языки программирования, от паскаля до фортрана, естественно, не обходя стороной ассемблер. Пытливый читатель, разумеется, спросит – А зачем все это нужно?  Отдел Перспективных Разработок, конечно же, ответит на этот вопрос:  А не знаю. Мы тут отвечаем на вопросы «Как?». Вопросами же «Зачем?» соседняя лаборатория занимается, но, там сейчас сотрудников нет, поэтому, дело будете иметь со мной, самым молодым сотрудником нашего отдела из одного человека. Кстати, по запросу «Классический ретро-модем 56K для интернета» ищутся носки на Алиэкспрессе, но, это нам сейчас тоже не нужно. Так вот, к сути. Обычно, из-за бедности реализации схем подобных бюджетных хобби-компьютеров, подавляющее большинство их страдает проблемами с подключением периферии, которой у автора не нашлось, и он на гипотетическое ее существование закономерно забил.  Как правило, создатель своего мега-творения все же оставляет в нем лазейки в виде каких-либо пинов GPIO или даже просто оставшихся неприкаянными ножек процессора или контроллера для сомнительных применений в грядущих извращениях последователей своего культа. И это уже хорошо, поскольку заставляет иногда подключать мозг, отдаляя приближение синдрома Альцгеймера. Вы же думаете об этом хоть иногда? В рассматриваемом нами случае все примерно так и обстоит:  Схема Z80-MBC2 имеет один порт TTL ввода-вывода для консоли, а так же, поддержку шин SPI и I2C на уровне контроллера всех этих шин в данной схеме, а именно, Atmega-32A. На шине SPI уже висит модуль SD-карт, с которого производится загрузка операционной системы. Шина I2C обслуживает опционально подключаемый модуль часов DS3231 и микросхему-расширитель портов MCP23017, которая предоставляет пользователю целую гребенку портов GPIO.  К сожалению, в нашем отделе не нашлось в наличии данной микросхемы, заказывать и ждать ее долго, потому, решение было представлено быстрым, простым и понятным любому человеку дендрофекальным методом. Пожалуй, на этом этапе мне стоит предупредить читателей, пока они не заработали при чтении данной статьи и представленного ниже кода каких-либо непоправимых повреждений психики, что, излишне впечатлительным читать далее не следует. Дело в том, что, дендрофекальный метод решения задач в нашем отделе, к некоторому сожалению, в силу скудости материально-технической базы, давно стал основным, и потому, решения и стиль написания кода страшны. Проще говоря, я не заморачивался. Оно работает, выполняет свою миссию, и ладно. Это ведь хобби, господа. Отталкиваться будем от конечного периферийного устройства.  Ретро-модем, в данном случае, – это устройство, подключающееся к современным сетям передачи информации и имитирующее работу обыкновенного древнего модема путем трансляции пакетов информации читаемых с определенного TCP-порта на физический порт RS-232. Это позволяет подключать не менее древний компьютер через единственный имеющийся у него физический порт для подключения модема, например, посредством Telnet к хосту в интернете, на котором работает, например, еще живая BBS и почитать там фидошную почту. Или загрузить побайтово содержимое интернет-странички (Браузеров для древних операционных систем мне лично не попадалось, но, всегда можно написать самому). В интернетах нашлась реализация подобного модема, построенная на базе ESP8266 или подобных контроллеров типа Wemos D1 Mini. Последний, как раз, пылился у меня в столе, и потому, был нещадно применен. Прошив плату скачанной прошивкой, я удостоверился, что через виртуальный порт USB-COM модем прекрасно работает на обычном IBM PC через любой эмулятор терминала и позволяет заходить на BBS (и наблюдать медленную загрузку страничек со скоростью 1200 бод, которая установлена по дефолту).  Первая же всплывшая очевидная проблема на нашем грязном извилистом пути – выход модема некуда подключить к Z80-MBC2, лишних портов RS232 просто нет. Нет не просто физического порта, но и программной части, которая обслуживала бы еще один порт ввода-вывода помимо основного.  Ой, да не проблема это, подумал я, и взялся ковырять исходники CP/M 3.0 в той части, которая обеспечивает ввод-вывод консоли. Для CP-M 3.0 часть функций БИОСа переписана создателем компьютера Z80-MBC2, дабы оная на нем и запускалась. Все драйвера устройств кроме CON немилосердно вырезаны.  Однако, исходники как самой операционки, так и модификаций имеются в свободном доступе, потому, итогом пары ночей курения ассемблера Z80, компиляции на древних компиляторах под эмуляторами (zxcc) и играми с блоками БИОСа стало порождение модификации функций БИОСа операционки, которое добавляет второе виртуальное физическое устройство SIO, позволяющее читать и писать в виртуальный порт RS-232.   Со стороны операционной системы CP/M второй порт ввода-вывода представлен логическим устройством AUX. В оригинальной реализации (далее – оригинальная реализация CP/M 3.0 для Z80-MBC2) порт AUX просто переназначен на физическое устройство CON и читает и пишет на основную консоль ввода/вывода. Поэтому, его пришлось отвязать и переназначить на новонаписанное устройство SIO.  Так же добавлено новое виртуальное физическое устройство LPT, которое является тем же самым устройством SIO, но, используется только для вывода (для возможности назначения виртуальному устройству LST, дабы, в перспективе, еще и вывод на принтер сделать).  Само виртуальное физическое устройство SIO при обращении к нему должно было делать следующие вещи: При записи в устройство посылать на контроллер шины команду с кодом 0x90 (коды взяты от балды, просто первые свободные из всего списка кодов), сигнализирующую о том, что сейчас будет послан байт в наш дополнительный порт, а затем посылать искомый байт. При чтении с устройства посылать на контроллер шины команду с кодом 0x91, сигнализирующую о том, что нужно считать один байт с нашего дополнительного порта, а затем запрашивать один байт. Все исходники для сборки есть на гитхабе, если вдруг кому нужно.  Итак, виртуальный COM-порт у нас уже есть, но, толку от того никакого, поскольку, реализации в железе для него нет. Посмотрев, что есть свободного в наличии на плате самого Z80-MBC2, я сначала хотел привязаться к шине SPI. Но, лишнего пина для выбора устройства на контроллере шины (Atmega32) просто не нашлось, да и GPIO, как я упоминал ранее, у меня просто нет.  Потому, была выбрана шина I2C. Гребенку пинов от нее я зачем-то оставил еще при проектировании платы своего варианта компьютера, и они оставались бесхозными до сего момента. В реализации Z80-MBC2 контроллер шины, а именно, Atmega-32A, привязан только к одной адресной ножке A0 процессора Z80, потому, используются лишь два порта процессора – 1 для вывода и 0 для ввода.  Прошивка контроллера шины была так же модифицирована, дабы работать с посланными кодами. Предполагалось, что в системе появится новое устройство Slave I2C с адресом 0x08, которое будет нужным нам модемом, и будет принимать-передавать байты по шине при запросе к нему. Контроллер шины, читая с порта вывода процессора Z80 байт команды, будет принимать решение – считать с модема байт данных и передать его в порт процессора Z80, или, наоборот, считать с порта Z80 байт и передать его по шине в модем.   Далее потребовалось модифицировать прошивку ретро-модема, дабы она могла отправлять байты не на свои пины RX/TX, а на шину I2C. Но, как водится, здесь тоже подвернулся огромный такой подводный булыжник:  Оказалось, что контроллеры на базе ESP8266 внезапно не хотят работать как Slave-устройства с шиной I2C и не видятся  устройством Master. Интернет пестрит жалобными cообщениями людей, которые сталкивались с данной проблемой, но, адекватного решения из нескольких перебранных мне так и не подвернулось. Если вы имеете счастливый опыт решения проблемы подключения ESP8266 как I2C-Slave, пожалуйста, ткните пальцем на него мне в комментариях, я буду вам очень, очень-очень благодарен. А пока, пришлось снова применить наш известный надежный дендрофекальный метод и прикрутить что-то еще. Чем-то еще в нашем случае стал отдельный контроллер-транслятор из шины I2C на обычные TTL RX/TX (далее - транслятор), а именно, еще одна отысканная в столе плата Arduino Pro Mini. Именно данная плата должна подключаться на шину I2C компьютера Z80-MBC2 в качестве устройства I2C-Slave с адресом 0x08 и транслировать прилетевшие байты со своих пинов RX/TX Serial-порта на RX/TX-пины Serial-порта платы Wemos D1 (модема). Вот такой вот странный бутерброд. Реализация через плату-транслятор тоже оказалась, к сожалению, не совсем гладкой: Внезапно, это всё, наконец, заработало, но, не полностью. Часть читаемых с модема байт данных куда-то пропадала. Выяснилось, что транслятор, как Slave-устройство, прерывается принудительно по прерыванию извне, дабы запросить с него по I2C байт данных. А модем, не подозревая об этом, шлет в Serial данные, которые некому считать в этот момент. Потребовалось как-то притормозить модем, дабы не слать их на плату-транслятор, который в момент отправки данных на I2C занят и ничего читать не может.  По сути, плата-транслятор получилась, как-бы, Slave-прокладкой между двумя Master-устройствами, и проблема эта была метко окрещена в нашем отделе «Double penetration»,  однако, подробности сего мы опустим. Для решения проблемы я соединил два пина – один выходной D9 на плате-трансляторе с входным пином D3 на плате модема. Эта линия должна была сигнализировать модему о том, что можно писать данные в Serial. Если пин установлен в HIGH, модем счастливо валит свой накопленный буфер в Serial, откуда его загребает плата-транслятор. Если LOW, то модем, соответственно, ждет.  Прошивку модема я модифицировал незначительно.  Сначала добавил команду AT$CA для включения режима остановки по проверке пина D3 (он же PIN_ACCESS далее), а потом и просто принудительное включение режима при обнаружении факта, что с D3 читается HIGH. Для этого была добавлена функция замедления, которая вставляется перед выводом каждого символа потока исходящих данных в Serial и ждёт какое-то время, если плата-транслятором ещё не сигнализировала через пин.   В процессе отладки пришлось поиграться так же с буфером чтения платы транслятора с Serial модема. Проще говоря, байты продолжали изредка куда-то теряться из-за каких-то неведомых рассинхронизаций времени срабатывания функций, и потому, чтение байт транслятором с модема свелось к простой последовательности – разрешить модему запись и считать 1-2 байта, отправить по запросу их на I2C, снова разрешить модему запись и считать 1-2 байта, и т.д. Но и это всё еще не всё! Следующей проблемой стало то, что ни одна терминальная программа под CP/M не хотела работать с моим псевдомодемом из самой операционки, поскольку, видимо, не могла конфигурировать что-то там у себя, либо получать нужную информацию с модема.  Нужна была, по сути, простейшая терминальная программа для CP/M, которая бы работала через виртуальный Serial-порт AUX операционки напрямую, читая и записывая байты как есть, без контролей четности, скорости и т.п.  Даже тот же VT100 не нужно было имитировать, поскольку, само по себе консольное устройство CON и подключаемые к нему внешние устройства для Z80-MBC2 могут обрабатывать ESC-последовательности и брать реализацию терминала на себя.  Сил переписывать исходники каких-нибудь утилит типа IMP, Kermit, QModem и подобных у меня уже не оставалось, да и слабоваты мои знания в области организации всех этих Xor/Xoff, 8N1 и контролей четности.  В общем, терминальная программа родилась за час, писаная на коленке на Turbo Pascal 3.0 прямо на этом самом компьютере. Самопальный терминал в цикле читал вывод с устройства AUX и писал его в терминал, а так же опрашивал порт клавиатуры на предмет кодов прилетевших клавиш и писал их обратно в AUX. Код ее я уже приводить не буду, найдете его сами в гитхабе, если интересно. И вуаля, я в сети. Скорость работы всей этой конструкции оказалась довольно низкой, но, много мне тут и не было нужно. Скорость работы самого модема удалось поднять до космических 4800 бод, визуально же, пройдя через все аппаратно-программные трансляции, скорость загрузки на компьютер осталась примерно на уровне 2400 бод, как в древние времена. Если ты дочитал до этих строк, значит, как минимум, тема статьи тебе небезразлична. Потому, если ты обладаешь информацией, как модифицировать любой нормальный терминал под CP/M типа IMP для работы через COM-порт напрямую, минуя контроль, прошу раскрыть свои секретные секреты в комментариях. Может быть, вместе у нас выйдет что-то удачное, а потом мы даже придумаем всему этому назначение, и, взявшись за руки, упрыгаем по цветочному полю в горизонт. Возможно, полезные ссылки: Страница проекта создателя Z80-MBC2 Гитхаб с использованным мной вариантом WiFi-модема Мой гитхаб с доработками CP/M и всеми прошивками     Инженер