Code Page 866

CP 866 для совместимости с ЭКВМ. Почему в Новосибирске выбрали кодировку ДОС — могу только догадываться.

В своё время cp866 была распространена. Под неё больше текстов было набрано, чем под MSX и КОИ-8. Винда, конечно, добавила неразберихи. Но если двигаться дальше, имхо надо UTF-8 или сразу 16-битный Юникод. Даже для проекта российского (не советского) ПМК потребуется несколько национальных алфавитов, помимо русского. Не говоря даже о научных обозначениях.

Как-то раз ЗонаТеХе нашёл схему калькулятора, вот ссылка на скачанный в прошлом году файл. Это версия схемы с микроконтроллером в панельке.

Спасибо. То, что нужно. Теперь нужны специалисты по 8051 — какие сигналы генерируются контроллером автоматически, а какие надо дёргать вручную через P2 и др. Ещё нужны схемы клавиатуры и индикатора.

Аппаратный интерфейс к внешней памяти
ALE - для защёлкивания младших линий данных/адреса
P3.6 (WR) - запись данных
P3.7 (RD) - чтение данных

P2.7 (CS) - старшую линию адреса A15 применили для селектора разных микросхем.
OE - принудительно подтянули к 5В (т.к. используют A15)

Шины данных/адреса согласно выводам из описания на микросхему (при беглом взгляде)
P4.0 ... P4.3 управляются вручную или смотреть их спецификацию в описании.
RST - штатная линия прерывания
RX, TX - уточнить по пинам контроллера, но должны совпасть
Другие линии портов P1.1 ..P1.7 P3.0 ..P3.5 - общего назначения

P.S. Остальная логика работы с внешними микросхемами, согласно их описанию.
Примерно так, Есть контроллеры AVR с таким интерфейсом к памяти как у 51-го Atmega162 ... Atmega128 ...
но можно через переходник подключить любой на выбор (например STM32 с 5-ти вольтовыми пинами)
51-й этот вроде пятивольтовый.А прошивка с него не считывается программатором? (хотя смысла наверное нет в ней)
С таким количеством микросхем и ключей (да и сам контроллер не экономичный) + Индикатор ... интересно какой ток потребления при штатном напряжении питания?

Возможно контроллер nuvoton W78E516d как аналог применим вместо штатного. Стоят мало, поддержаны компиляторами и имеют режим самопрограммирования. Документацию на них (nuvoton 51-e вроде даже кто то переводит).

Очдавно этим занимался. Вот основные наработки:
https://vk.com/topic-10838600_33160857
https://pmk.arbinada.com/ru/node/1245
https://pmk.arbinada.com/ru/node/1247

Сейчас я занимаюсь оптимизацией Каллисто на СПФ, поверх языка МК. Но мне очень интересен вопрос встраивания Каллисто в прошивку. Есть МК-161 для опытов, пара W77LE516P и программатор. Не лень загружать двоичные образы и пробовать их на «железке». Главное — получить точки на MT–12864J и научиться опрашивать клавиатуру ЭКВМ. Впрочем, для начала можно оживить машинку через COM-порт, управляя самодельной прошивкой с соседней МК-161 вот этим терминалом:
https://pmk.arbinada.com/ru/node/1331

«А прошивка с него не считывается программатором?» — Нет. В W77LE516P есть бит защиты. Видимо, с его помощью считывание заводской прошивки запрещено. Результат, afair, FF FF …

Имхо, мои попытки были весьма наивными. Возможно, я вручную дёргал те сигналы, которые микроконтроллер выдаёт самостоятельно, выполняя команды обращения к внешней памяти. В любом случае успех был достигнут только в прошивке W77LE516P. Написать код, работающий внутри МК-161, пока не удалось.

и переходник PLCC-> DIP40 в местном магазине, теперь разобраться как их заливать через встроенный загрузчик и требуемую обвязку
и можно создавать какую то прошивку для Каллисто :)
Может быть развести схему подобную МК-161 (152)

P.S. На Github много кода при поиске по 8051, Эту архитектуру, похоже, до сих пор изучают в учебных курсах.
Как я понял МТ12864J сделан на совместимом контроллере дисплея KS0108 (2-a контроллерa для 128x64) Библиотечка для данного контроллера http://en.radzio.dxp.pl/ks0108/ (может ещё надо учесть временные параметры при пересылке данных дисплею согласно документации произволителя МЭЛТ)
Ещё какая то статья по часам с дисплеем от МЭЛТ https://xakep.ru/2014/09/10/hardware-clock/

Загрузчик — важная тема.

  1. В новых микроконтроллерах загрузчика может не быть, afaik. Его туда надо прошить, пример загрузчика есть в даташитах.
  2. Если получится написать свой загрузчик в обвязке МК-161 (она не во всём совпадает с обвязкой МК-152), к работе могут подключиться другие владельцы ЭКВМ. Один раз программатор найти, чтобы прописать в чип загрузчик, просто и дёшево — а дальше можно экспериментировать без программатора. В Москве я могу помочь, с этой первой прошивкой.
  3. На AliExpress.com можно было найти родные W77LE516P, они могут в чём-то отличаться от W78E516D-PG, придётся меньше править код.
  4. Код Каллисто можно будет начать переводить на 8051 сразу, как заработает клавиатура и индикатор. Можно даже побегать чуть впереди паровоза, как заработает терминал через COM. Опять же, я смогу проверять гипотезы о работе и подключению периферии на родном новосибирском железе.
  5. Документация на индикатор здесь, там же можно заказать себе оригинал (1200 руб. за 1-40 шт.): http://www.melt.com.ru/docs/MT-12864J.pdf
  6. Даже если мы сделаем отечественное железо, альтернативное МК-161 и по гуманной цене (не обязательно клон), наладить его производство в России — отдельное приключение. Похожее на разработку «плавучки» для 8051. ^_^ Впрочем, к моменту создания макета ситуация может поменяться в лучшую сторону. :-)

Если делать альтернативное МК161 железо, то стоит ли оставаться на 8051?

Первая задача — отладить Каллисто внутри МК-161. Макет должен по возможности эмулировать новосибирскую схему.

Если доводить свой ПМК до производства, мы не ограничены 8051. Мне бы хотелось полностью отечественный процессор. Пишут, что во время бума FPGA была волна разработки процессоров с отечественной системой команд. Но мне не удалось выяснить, что с той эпохи осталось в камне — так, чтобы потребление было скромным.

В идеале схема нового ПМК должна уметь «спать». Как между нажатиями клавиш, так и между включениями. Возможно, хорошая идея будет работать с пониженным быстродействием, включая режим «турбо» лишь при необходимости. Длительные вычисления, когда требуются, могут проводиться в режиме «турбо» с выключенным индикатором и звуковой сигнализацией по окончанию.

Программа во внутренне ОЗУ данного контроллера загружается или с/в 24с128 I2C микросхемы
или по USB каналу контроллера (почти вариант по дизайну Arduino) штаттным прошивальшиком.
Контроллер используется, чаще всего, во всевозможных логических анализаторов (Saleae Logic, USBee, ...) и их клонов
Открытый проект логического анализатора https://sigrok.org поддерживает много девайсов с этим контроллером
https://sigrok.org/wiki/Fx2lafw
Начал экспериментировать с этим контроллером (платa от LCSOFT) информация по нему полная.

P.S. Можно им снимать (логическим анализатором на этом контроллере) ньюансы обмена сигналами в MK-161 (у кого есть данный калькулятор)
Предполагаю запустить в рамках CY7C68013A вариант Форт (возможно и с кросс компиляцией)
В линейке CY7C68013 есть и более полные контроллеры (100 ... ногие) с интерфейсами к памяти.

Можно и так. Но зачем, если у меня есть W77LE516P с программатором?

Проблема не запустить что-нибудь внутри МК-161. Это не проблема. Проблема написать код, который хотя бы пищит пищалкой, для начала. А потом нужны опрос клавиатуры и вывод точки.

Что на CY7C68013A писать, что на W77LE516P. Одинаково.

Ещё можно начать с RS-232. Поток я могу генерировать и отображать на соседнем МК-161, пользуясь 161eForth.

Первый нативный Форт на МК-161 может вообще не обращаться к консоли и работать через последовательный порт. Пока кто-нибудь, путём экспериментов, не напишет таки BIOS.

//Пример программы для вывода картинки на индикатор MT-12864

void main(void) {
byte	p;//Номер текущей страницы индикатора
byte	c;//Позиция по горизонтали выводимого байта

	LCDinit();
	for(p=0; p<8; p++) {//Цикл по всем 8-ми страницам индикатора
		WriteCodeL(p|0xB8);//Установка текущей страницы для левого кристалла индикатора
		WriteCodeL(0x40);//Установка текущего адреса для записи данных в 0 для левого кристалла индикатора
		for(c=0; c<64; c++) {//Цикл вывода данных в левую половину индикатора
			WriteDataL(Logo128[p][c]);//Вывод очередного байта в индикатор
		}
		WriteCodeR(p|0xB8);//Установка текущей страницы для правого кристалла индикатора
		WriteCodeR(0x40);//Установка текущего адреса для записи данных в 0 для правого кристалла индикатора
		for(c=64; c<128; c++) {//Цикл вывода данных в правую половину индикатора
			WriteDataR(Logo128[p][c]);//Вывод очередного байта в индикатор
		}
	}
}

//Процедура программной инициализации индикатора
void LCDinit(void) {
	LCD.E=0;//Начальное значение сигнала индикатору
	LCD.RES=0;//Выдать сигнал RES=0 индикатору
	Delay(>1us);//Задержка на время больше 1 мкс
	LCD.RES=1;//Снять сигнал RES
	Delay(>10us);//Задержка на время больше 10 мкс
	WriteCodeL(0xC0);//Верхнюю строку на 0
	WriteCodeR(0xC0);//Верхнюю строку на 0
	WriteCodeL(0x3F);//Display on
	WriteCodeR(0x3F);//Display on
}

void Pset(byte x, byte y, bit c) {//Записать одну точку в индикатор (координата 0,0 в левом верхнем углу индикатора)
byte c8;//Временное хранение считаного из индикатора байта
byte m8;//Маска нужного бита в байте
	if ((x>127)||(y>63)) return;//Выход за пределы индикатора
	if (x<64) {//Выводить в левую половину индикатора
		WriteCodeL(0xB8|(y>>3));//Установить нужную страницу индикатора
		WriteCodeL(0x40|x);//Установить адрес нужного байта
		c8=ReadDataL();//Фиктивное чтение
		c8=ReadDataL();//Чтение нужного байта из индикатора
		m8=1<<(y&0x07);//Вычислить маску нужного бита в байте
		if (c==1)	//Зажигать точку?
			c8|=m8//Установить нужный бит в байте
		else		//Или гасить точку?
			c8&=~m8;//Сбросить нужный бит в байте
		WriteCodeL(0x40|x);//Снова установить адрес нужного байта
		WriteDataL(c8);//Записать изменённый байт обратно в индикатор
	} else {//Выводить в правую половину индикатора
		WriteCodeR(0xB8|(y>>3));//Установить нужную страницу индикатора
		WriteCodeR(0x40|(x-64));//Установить адрес нужного байта
		c8=ReadDataR();//Фиктивное чтение
		c8=ReadDataR();//Чтение нужного байта из индикатора
		m8=1<<(y&0x07);//Вычислить маску нужного бита в байте
		if (c==1)	//Зажигать точку?
			c8|=m8//Установить нужный бит в байте
		else		//Или гасить точку?
			c8&=~m8;//Сбросить нужный бит в байте
		WriteCodeR(0x40|(x-64));//Снова установить адрес нужного байта
		WriteDataR(c8);//Записать изменённый байт обратно в индикатор
	}
}

void WriteCodeL(byte b) { WriteByte(b,0,1,0); }//Команду в левый кристалл индикатора
void WriteCodeR(byte b) { WriteByte(b,0,0,1); }//Команду в правый кристалл индикатора

void WriteDataL(byte b) { WriteByte(b,1,1,0); }//Данные в левую половину индикатора
void WriteDataR(byte b) { WriteByte(b,1,0,1); }//Данные в правую половину индикатора

byte ReadDataL(void) { return ReadByte(1,1,0); }//Прочитать байт данных из левой половины индикатора
byte ReadDataR(void) { return ReadByte(1,0,1); }//Прочитать байт данных из правой половины индикатора

//Процедура выдачи байта в индикатор
void WriteByte(byte b, bit cd, bit l, bit r) {
	if ((l==1)&&(r==1)) return;	//Читать (для опроса готовности) одновременно из обоих кристаллов недопустимо!
	WaitReady(l,r);		//Ждать готовности индикатора
//При необходимости настроить здесь шину данных на вывод
	LCD.RW=0; LCD.A0=cd;	//Выдача байта в индикатор как данных или команды
	LCD.E1=l; LCD.E2=r;	//Выбрать нужные нужные кристаллы в индикаторе
	LCD.D=b;		//Выдать байт на шину данных индикатора
	Delay(>140ns);		//Это время предустановки адреса (tAW)
	LCD.E=1;		//Сформировать строб записи в индикатор E=1
	Delay(>450ns);		//Длительность сигнала E=1 (время предустановки данных попало сюда (tDS))
	LCD.E=0;		//Сбросить сигнал E
	Delay(>(1000ns-140ns-450ns));	//Минимально допустимый интервал между сигналами E=1
}

byte ReadByte(bit cd, bit l, bit r) {
byte b;
	if ((l==1)&&(r==1)) return 0;	//Читать одновременно из обоих кристаллов недопустимо!
	WaitReady(l,r);		//Ждать готовности индикатора
	LCD.RW=1; LCD.A0=cd;	//Будем читать байт как команду или данные
	LCD.E1=l; LCD.E2=r;	//Выбрать нужные нужные кристаллы в индикаторе
	Delay(>140ns);		//Это время предустановки адреса (tAW)
	LCD.E=1; 		//Выдать строб в индикатор
	Delay(>450ns);		//Минимально допустимая длительность сигнала E=1 (время доступа (tDDR) попало сюда)
	b=LCD.D;		//Прочитать данные с шины индикатора (они на ней уже минимум 130нс)
	LCD.E=0;		//Сбросить сигнал E
	Delay(>(1000ns-140ns-450ns));	//Минимально допустимый интервал между сигналами E=1
	return b;		//Вернуть прочитанный байт
}

void WaitReady(bit l, bit r) {//Ждать готовности индикатора, опрашивая байт статуса
//При необходимости настроить здесь шину данных на ввод
	LCD.RW=1; LCD.A0=0;	//Чтение флага занятости
	LCD.E1=l; LCD.E2=r;	//Выбрать нужные нужные кристаллы в индикаторе
	Delay(>140ns);		//Это время предустановки адреса (tAW)
	LCD.E=1; Delay(>450ns);	//Минимальная длительность сигнала E=1 (информация на шину данных индикатором будет выдана раньше, не более чем через 320нс)
	while(LCD.D.7==1);	//Ждать сброса флага занятости
	LCD.E=0;		//Сбросить сигнал E
	Delay(>(1000ns-140ns-450ns));	//Минимально допустимый интервал между сигналами E=1
}

//Данные изображения, побитые по строкам и байты будут на индикаторе вертикально.
//Это просто последовательность байт для записи в индикатор начиная с верхней страницы.
//Полностью соответствуют картинке распределения ОЗУ в документации на модуль.
const byte Logo128[8][128]=//128x64 pixel, каждые 8 вертикальных точек собраны в байт
{
	{	0xFF,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
		0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
		0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
		0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
		0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
		0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
		0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
		0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0xFF
	},
	{	0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0xE0,0xC0,0xE0,0xF0,0xF0,0xF0,
		0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xE0,0xE0,0xE0,0xC0,0x80,0x00,
		0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,
		0x00,0x80,0x80,0x00,0x00,0x80,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x80,0x00,0x00,
		0x80,0x00,0x00,0x80,0x00,0x80,0x00,0x80,0x80,0x80,0x00,0x80,0x80,0x00,0x00,0x80,
		0x00,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,
		0x00,0x00,0x80,0x00,0x80,0x00,0x00,0x80,0x80,0x80,0x00,0x80,0x00,0x00,0x80,0x00,
		0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x3F
	},
	{	0x1F,0xC0,0xE0,0xE0,0xFC,0xFE,0xF3,0xE3,0xE3,0xE3,0xE3,0xAF,0x6F,0xFF,0xFF,0xFF,
		0xBF,0xBF,0xFF,0xFF,0x7F,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
		0xFF,0xF6,0xF4,0x1F,0x21,0xE2,0x61,0x6F,0x60,0x6F,0x64,0x6F,0x60,0x6F,0x65,0x68,
		0x60,0x6F,0x62,0x61,0x67,0x68,0x67,0x60,0x6A,0x67,0x60,0x6E,0x61,0x6F,0x60,0x67,
		0x6A,0x6B,0x60,0x6F,0x65,0x68,0x60,0x60,0x6F,0x60,0x60,0x6F,0x62,0x61,0x67,0x68,
		0x67,0x60,0x6F,0x62,0x6F,0x60,0x6F,0x64,0x6F,0x60,0x6F,0x65,0x68,0x64,0x6A,0x6F,
		0x60,0x60,0x6F,0x64,0x6F,0x60,0x60,0x60,0x6F,0x60,0x67,0x6A,0x6B,0x60,0x6D,0x62,
		0x6D,0x60,0x6F,0x62,0x6F,0x60,0x6F,0x64,0x6F,0x60,0x6F,0x65,0x68,0x64,0x6A,0x6F
	},
	{	0xFE,0x3F,0x3F,0x3F,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xF9,0x77,0x37,
		0x03,0x03,0x01,0x00,0x00,0x00,0x00,0x01,0x07,0x0F,0x13,0x01,0x00,0x00,0x01,0x07,
		0xD7,0x0E,0x08,0xC0,0x00,0x10,0x0F,0xF8,0x00,0x00,0x80,0xE0,0xF8,0xFE,0xFF,0xFF,
		0xFF,0xFE,0x00,0x00,0x00,0x00,0x00,0xC0,0xF0,0xFE,0xFF,0xFF,0xFF,0xFE,0x00,0x00,
		0x00,0xE0,0xF0,0xF8,0xFC,0x7C,0x3E,0x1E,0x1F,0x0F,0x0F,0x0F,0x0F,0x1F,0x1E,0x1E,
		0x3E,0x7C,0xFC,0xF8,0xF0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
		0x80,0xC0,0xF0,0xFC,0xFE,0xFF,0xFF,0xFE,0x00,0x00,0x06,0x0F,0x0F,0x0F,0x0F,0x0F,
		0x0F,0x0F,0xFF,0xFF,0xFF,0xFF,0xFF,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x06,0xF0
	},
	{	0x3F,0xE0,0x00,0x00,0x01,0x3F,0xFF,0xFF,0xFF,0xFF,0xFF,0x3F,0x3F,0x00,0x00,0xE0,
		0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
		0x00,0x01,0x01,0xC1,0xE0,0xE0,0xF9,0xFF,0xFC,0xFF,0xFF,0x7F,0x1F,0xFF,0xFF,0xFF,
		0xFF,0xFF,0x80,0xE0,0xF8,0xFE,0xFF,0xFF,0x3F,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,
		0x00,0x00,0x01,0x01,0x00,0x00,0x00,0x30,0x78,0x78,0xFC,0xFC,0xFC,0xFC,0x78,0x78,
		0x30,0x00,0x01,0x07,0xFF,0xFF,0xFF,0xFC,0x00,0x00,0x00,0x00,0x80,0xE0,0xF8,0xFE,
		0xFF,0xFF,0x3F,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
		0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF
	},
	{	0xFC,0x01,0x03,0x04,0x18,0x20,0x40,0x81,0x87,0x07,0x07,0x00,0x00,0x00,0x00,0x00,
		0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,
		0x80,0xE4,0xE7,0xFB,0xFF,0xFF,0x7F,0x3F,0x0F,0x03,0x01,0x00,0x00,0xFF,0xFF,0xFF,
		0xFF,0xFF,0xFF,0x7F,0x1F,0x07,0x03,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,
		0x00,0x70,0xF8,0xF8,0xF0,0xE0,0xE0,0xC0,0xC0,0x80,0x80,0x80,0x80,0xC0,0xC0,0xC0,
		0xE0,0xF0,0xFC,0xFF,0x7F,0x3F,0x0F,0x81,0xE0,0xF8,0xFC,0xFF,0xFF,0x3F,0x1F,0x07,
		0x01,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
		0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF
	},
	{	0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x02,0x04,0x04,0x04,0x0C,
		0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x04,0x04,0x04,0x02,0x03,0x01,0x00,
		0x00,0x03,0x07,0x07,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x07,0x07,
		0x07,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x07,0x07,0x07,0x03,0x00,0x00,
		0x00,0x00,0x00,0x01,0x01,0x03,0x03,0x03,0x07,0x07,0x07,0x07,0x07,0x07,0x03,0x03,
		0x03,0x01,0x01,0x00,0x00,0x00,0x00,0x03,0x07,0x07,0x07,0x03,0x00,0x00,0x00,0x00,
		0x00,0x00,0x00,0x03,0x07,0x07,0x07,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
		0x00,0x00,0x03,0x07,0x07,0x07,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF
	},
	{	0xFF,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
		0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
		0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
		0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
		0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
		0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
		0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
		0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xFF
	}
};

по ссылкам выше схема подключения дисплея в МК-151
и указано, что в МК-161 есть отличия (какие?)

P.S. Теоретически сначала можно код и в симуляторе, типа протеус проверить для 8051 и индикатора т.к. пока у меня нет интереса в этом индикаторе. :) (а собранный бинарный файл на чьём то железе)
Интересно, что для 8051 есть и Паскаль http://turbo51.com/

Вот здесь была похожая схема с кодом, работающим на эмуляторе:
https://pmk.arbinada.com/ru/comment/8418#comment-8418

Но она не была доведена до бинарника, который я мог бы проверить в МК-161. Также схема подключения была взята из МК-152 и говорят, что в МК-161 она немножко другая. Можно запланировать встречу в Скайпе. К ней я могу подготовить сохранённые схемы МК-161 (схему платы индикатора пока не нашёл), мультитестер и другие инструменты. Или просто передать мне кучу бинарников, которые я буду загружать в W77 и проверять их работу на железе.

Один из вариантов для бинарников — попробовать оживить RS-232. Там вариантов подключения меньше. Потом загрузить в камень интерактивную программу на основе кода МЭЛТ, передавая ей по терминалу разные варианты подключения индикатора. Если сразу не нащупаем, можно найти нужный вариант автоматическим перебором под видеокамерой.

Но т.к МК-ххх у меня нет и не планировал покупать - то естественно далее приведенного кода смысла дергаться не было.
Меня не покидает иногда "дурная"мысль - все таки развести плату с кнопками, STM32, SDCard, выведеными наружу интерфесами RS232/485 и несколькими IO и вот таким индикатором c сенсорной панелью: https://www.buydisplay.com/default/2-8-inch-128x64-graphic-module-serial...
Пусть пока просто плату. По отдельности у меня есть наработки на все это. Код симулятора МК-61 тоже Сергей Вакуленко написал. Расширение для МК-161 у меня работает в контроллерах.
Время - ну можно выкроить.

Она имеет несколько преимуществ. Буквы в алфавитном порядке, в отличие от koi-8,
есть все дополнительные украинские и белорусские, так-что 3 в 1, псевдографика и математические символы, включая корень.