;_______________________________________________________________________ ; ; Управляющая прошивка Контроллера Символьного Монитора (КСМ) ; Компилируется при помощи ZMAC cross assembler ; title 'KSM monitor bios' .8080 ;_______________________________________________________________________ ; ; Порты ввода-вывода ; pio_a equ 0x78 ; BB55 порт A pio_b equ 0x79 ; BB55 порт B pio_c equ 0x7A ; BB55 порт C pio_csr equ 0x7B ; BB55 порт управления ; pic_csr equ 0x5E ; ВН59 управление pic_msk equ 0x5F ; ВН59 маска ; key_dat equ 0x6E ; ВВ51 для связи key_csr equ 0x6F ; с клавиатурой 7004 ; sio_dat equ 0x76 ; ВВ51 для связи sio_csr equ 0x77 ; с системой (ЭВМ) ; rx_size equ 64 ; приемный буфер scr_x equ 80 ; размер строки экрана scr_y equ 24 ; вертикальный размер экрана scr_f equ 48 ; число строк в буфере ;_______________________________________________________________________ ; _bs equ 8 ; _tab equ 9 ; _lf equ 10 ; _cr equ 13 ; _rus equ 14 ; _lat equ 15 ; _xon equ 17 ; _xoff equ 19 ; _esc equ 27 ; _space equ 32 ; _rect equ 127 ; символ курсора ; ;_______________________________________________________________________ ; ; Сегмент статического ОЗУ на 541РУ2, используется только 256 байт ; dseg org 0x2000 ram_start: ds 172 ; начало статического ОЗУ stack: ; программный стек org 0x20AD ; ds 1 rx_beg: ds 1 ; начало буфера передачи rx_end: ds 1 ; конец буера передачи ; fline: ds 1 ; физический номер первой ; строки экрана 0-47 ; uart_cmd: ds 1 ; управляющее слово UART uart_baud: ds 1 ; скорость обмена по UART ; 0 - 9600 4 - 600 ; 1 - 4800 5 - 300 ; 2 - 2400 6 - 150 ; 3 - 1200 7 - 75 ; key_ctrl: ds 1 ; признак нажатой СУ/Ctrl key_stat: ds 1 ; key_stat_shft equ (1<<0) ; бит 0 - прижата клавиша ВР key_stat_lat equ (1<<1) ; бит 1 - режим алфавита LAT key_stat_caps equ (1<<2) ; бит 2 - режим верхнего регистра ; key_save: ds 1 ; сохраненый код клавиша key_auto: ds 1 ; код клавиши для автоповтора ; org 0x20C0 ; приемный буфер сиволов, должен rx_buf: ds rx_size ; быть выравнен на размер ; в 64 байта ; ram_end equ 0x2100 ; конец статического ОЗУ ; ;_______________________________________________________________________ ; ; Сегмент динамического видео ЗУ ; dseg org 0xC000 ; mark_start equ 0xC000 ; область курсора mark_end equ 0xD800 ; vbuf_start equ 0xE000 ; область видеоданных vbuf_end equ 0xF800 ; stat_line equ 0xF8C0 ; строка статуса mem_end equ 0x10000 ; конец памяти ; stat_line_lin equ stat_line+13 ; смещение надписи АВТ/ЛИН stat_line_lat equ stat_line+18 ; смещение надписи РУС/ЛАТ stat_line_caps equ stat_line+23 ; смещение надписи НР/ВР stat_line_dkl equ stat_line+27 ; режим ДКЛ/ЗВЫВ stat_line_hold equ stat_line+33 ; режим задержанного вывода stat_line_baud equ stat_line+38 ; смещение надписи РУС/ЛАТ stat_line_koi equ stat_line+46 ; использование КОИ Н0 и Н1 stat_line_arpt equ stat_line+51 ; разрешение автоповтора stat_line_nct equ stat_line+55 ; не отображать управляющие символы stat_line_nopar equ stat_line+58 ; контроль по чет/нечет stat_line_odd equ stat_line+60 ; контроль по нечетности stat_line_xon equ stat_line+44 ; режим квитирования XON/XOFF stat_line_alf equ stat_line+48 ; автоматический LF после CR stat_line_nomrk equ stat_line+53 ; не фиксировать маркер в конце строки stat_line_nstp equ stat_line+62 ; количество стоп-битов ;_______________________________________________________________________ ; aseg ; org 0x0000 ; ; reset: lxi SP, stack ; инициализация стека lxi H, mem_end-1 ; mvi A, high(vbuf_end) ; заполнение видеопамяти @@zeroh: mvi M, 0 ; F900-FFFF нулями dcx H ; cmp H ; jm @@zeroh ; ; mvi A, high(mark_start)-1 ; заполнение видеопамяти @@zerov: mvi M, _space ; C000-F8FF пробелами dcx H ; включая строку статуса cmp H ; jm @@zerov ; ; lxi H, ram_end ; обнуление всего @@zeror: dcr l ; статического ОЗУ mvi M, 0 ; jnz @@zeror ; ; инициализация параллельного порта mvi A, 0x83 ; A вывод, B ввод, C03 ввод, С47-вывод out pio_csr ; mvi A, 0x7E ; настройка UART клавиатуры out key_csr ; синхронизация 1/16, 8 бит, mvi A, 0x14 ; контроль по четности, 1 стоп out key_csr ; ; lxi H, irq_table + 0x16 ; настройка контроллера прерываний mov A, L ; интервал 4 байта, одиночный out pic_csr ; mov A, H ; out pic_msk ; mvi A, 0xF5 ; разрешить прерывания по входам 1 и 3 out pic_msk ; in key_dat ; прочесть данные с клавиатуры mvi A, key_stat_lat ; capslock неактивен. не прижат shift sta key_stat ; выбран режим латинских символов ; call show_ruslat ; вывод режима алфавита ЛАТ/РУС call show_caps ; вывод регистра НР/ВР xra A ; клавиша СУ/Ctrl отжата sta key_ctrl ; mvi A, '0' ; установим режимы в статусной строке sta stat_line_koi ; использовать КОИ Н0 и Н1 sta stat_line_arpt ; разрешение автоповтора sta stat_line_nct ; не отображать управляющие символы sta stat_line_odd ; контроль по нечетности sta stat_line_nopar ; отключить контроль по четности sta stat_line_nomrk ; не фиксировать маркер в конце строки sta stat_line_alf ; нет автоматического LF после CR sta stat_line_xon ; режим XON/XOFF отключен ; mvi A, '2' ; использовать 2 стоп-бита для UART sta stat_line_nstp ; mvi A, 0xCE ; 2 стоп-бита, нет честности sta uart_cmd ; 8 бит данных, делитель 1/16 ; lxi H, stat_line_lin ; вывод в статусной строке ЛИН mvi M, 0xEC ; 'Л' inx H ; mvi M, 0xE9 ; 'И' inx H ; mvi M, 0xEE ; 'Н' ; mvi B, 0 ; координаты курсора - 0,0 mov C, B ; mov A, B ; установка рулона на нулевую строку out pio_a ; call get_adrxy ; mvi M, _rect ; вывод курсора на 0,0 ; установка указателей буфера lxi H, (low(rx_buf)<<8) | low(rx_buf) shld rx_beg ; call get_switch ; установка признаков по ; переключателям конфигурации ; main_loop: call get_char ; прочесть символ с линии cpi _space ; jm proc_ctrl ; это управляющий символ ; точка повторного входа main_ctrl: mov E, A ; сохранить символ в регистре E lda stat_line_koi ; выбран набор КОИ Н2 ? rrc ; jnc L_00A7 ; нет ; точка повторного входа main_lout: mov A,E ; Передать символ в A cpi 96 ; Символ в диапазоне 96-127 ? jp L_00B0 ; Да jmp L_00B7 L_00A7: lda key_stat ; какой режим РУС/ЛАТ ani key_stat_lat ; mov A, E jnz L_00B7 ; Режим ЛАТ L_00B0: cpi _space ; Это управляющий символ ? jm L_00B7 ; Да ori 0x80 ; Установить старший бит (кириллица) L_00B7: mov E,A lda 0x20AD ; Установлен режим псевдографики rrc jnc @@show ; Нет mov A,E ani 0x7F ; Оставить семь бит cpi 64 ; Код меньше 64 ? jm @@show ; Да cpi 96 ; Код больше или равен 96 ? jp @@show ; Да ani 0x1F ; Поставить 7-й бит и убрать 6-й и 5-й ori 0x80 mov E, A ; @@show: mov A, E ; вывод сивола из регистра E call get_adrxy ; вычислить адрес курсора и символа stax D ; сохранить символ в видеопамяти mvi M, _space ; убрать курсор с экрана mov A, C ; координата X cpi scr_x-1 ; достигли границы экрана ? jz @@lend ; да inr C ; X = X + 1 inr L ; перейти к след.адресу курсора @@done: mvi M, _rect ; высветить курсор по новым координатам jmp main_loop ; продолжаем основной цикл ; будем ждать следующий символ @@lend: lda stat_line_nomrk ; установлен режим фиксации курсора ? rrc ; jc @@done ; да (координаты остались прежние) mvi C, 0 ; X = 0 jmp line_feed ; Переход на перевод строки ;_______________________________________________________________________ ; ; Обработчик прерывания от клавиатуры ; irq_key_rx: push PSW ; cохранить регистры в стеке push H ; mvi A, 0x20 ; команда "конец прерывания" out pic_csr ; контроллеру прерываний in key_dat ; чтение кода клавиши из UART cma ; инверсия полученного кода adi low(key_table) ; mov L, A ; добавляем базовый адрес mvi A, 0 ; таблицы декодирования aci high(key_table) ; сканкодов клавиатуры МС-7004 mov H, A ; mov A, M ; A - преобразованный код ; L_0103: sta key_save ; сохранить код в памяти ana A ; Установить признаки jm L_0167 ; Код в диапазоне 80H-FFH jz irq_key_exit ; Код равен нулю - возврат sta key_auto ; Сохранить для автоповтора lda key_ctrl ; Нажата клавиша СУ ? ana A jz @@no_ctrl ; Нет lda key_auto ani 0x1F ; Оставить только 5 мл.битов jmp L_0218 ; Передать в ЭВМ(ЛИН) или обраб.(АВТ) @@no_ctrl: lda key_auto ani 0x40 ; Код в диапазоне 64-127 ? jnz L_014D ; Да lda key_auto ani 0x20 ; Код в диапазоне 32-63 ? jnz L_0135 ; Да L_012F: lda key_auto jmp L_0218 ; Передать в ЭВМ(ЛИН) или обраб.(АВТ) L_0135: lda key_auto ani 0x0F ; Это ПРОБЕЛ или 0 ? jz L_012F ; Да lda key_stat ; ani key_stat_shft | key_stat_caps ; режим capslock или прижат shift ? jpe L_012F ; Нет lda key_auto xri 0x10 ; Изменить 4-й бит jmp L_0218 ; Передать в ЭВМ(ЛИН) или обраб.(АВТ) L_014D: lda key_auto ani 0x5F ; Это ПОДЧЕРКИВАНИЕ или ЗАБОЙ ? cpi 0x5F jz L_012F ; Да lda key_stat ; ani 0x07 ; Режим ВР или РУС ? jpo L_012F ; Режим РУС+ВР или ЛАТ без ВР lda key_auto xri 0x20 ; Изменить 5-й бит (нижн.рег.) jmp L_0218 ; Передать в ЭВМ(ЛИН) или обраб.(АВТ) L_0167: ani 0x40 ; Код в диапазоне C0H-FFH ? jnz L_0193 ; Да lda stat_line_dkl+1 ; Включен режим "ДКЛ" ? rrc jc L_017E ; Да lda key_save ; Прочесть преобр.код из памяти sta key_auto ; Сохранить для автоповтора ani 0x3F ; Выделить младшие 6 разрядов jmp L_0218 ; Передать в ЭВМ L_017E: mvi A,0x1B ; Передать код Esc в ЭВМ call put_char mvi A,0x3F ; Передать '?' в ЭВМ call put_char lda key_save ; Прочесть преобразованный код sta key_auto ; Сохранить для автоповтора xri 0xC0 ; Очистить 8-й и установить 7-й разр. jmp L_0218 ; Передать в ЭВМ L_0193: lda key_save ; Прочесть преобр.код из памяти ani 0x30 ; Код в диапазоне F0H-FFH ? cpi 0x30 jz L_01C5 ; Да mvi A,0x1B ; Передать код Esc в ЭВМ call put_char lda key_save ; Прочесть преобразованный код sta key_auto ; Сохранить для автоповтора ani 0x20 ; Код в диапазоне C0H-DFH ? jz L_01BD ; Да lda key_stat ; Нажата клавиша ВР ? ani key_stat_shft jz L_01BD ; Нет lda key_auto ; Прочесть код xri 0x88 ; Очистить 7-й бит и измен. 3-й бит jmp L_0218 ; Передать в ЭВМ L_01BD: lda key_auto ; Прочесть код ani 0x7F ; Оставить только 7 бит jmp L_0218 ; Передать в ЭВМ L_01C5: lda key_save ; Прочесть преобр.код из памяти cpi 0xFF ; Это автоповтор ? jz L_057A ; Да xra A ; Очистить код автоповтора sta key_auto lda key_save ; Прочесть преобр.код из памяти cpi 0xFE ; Это отжатие СУ или ВР ? jz L_0587 ; cpi 0xFD ; Нажата РУС/ЛАТ ? jz L_05A0 ; cpi 0xFC ; Нажата "пустая" клавиша ? jz L_05CA ; cpi 0xFB ; Нажата ФКС ? jz L_05CD ; cpi 0xFA ; Нажата СУ ? jz L_05DB ; cpi 0xF9 ; Нажата ВР ? jz L_05E3 ; cpi 0xF0 ; Нажата Ф20 ? jz L_051B ; cpi 0xF1 ; Нажата ПАУЗА ? jz L_021F ; cpi 0xF2 ; jz key_set_mode ; нажата УСТ РЕЖИМА cpi 0xF3 ; Нажата Ф5 ? jz L_0542 ; cpi 0xF4 ; Нажата СТОП КАДР ? jz L_0556 ; cpi 0xF5 ; Нажата ОСНОВН КАДР ? jz L_04F4 ; cpi 0xF6 ; Нажата ДОП ВАРИАНТ ? jz L_0568 ; jmp irq_key_exit L_0218: call put_char ; Передать код в ЭВМ irq_key_exit: pop H ; восстановление из стека pop PSW ; сохраненных регистров ei ; разрешить прерывания ret ; возврат из прерывания ;_______________________________________________________________________ ; ; Обработка нажатия ПАУЗА L_021F: mvi L, 0 lda key_stat rrc mov A, L jnc L_022B adi 0x17 L_022B: sta fline jmp irq_key_exit ;_______________________________________________________________________ ; ; Обработка нажатия клавишаш УСТ РЕЖИМА ; key_set_mode: in key_csr ; ждем следующую клавишу rrc ; rrc ; jnc key_set_mode ; пока клавиши нет in key_dat ; читаем код клавиши cma ; инверсия кода клавиши adi low(key_table) ; и преобразование по таблице mov L, A ; mvi A, 0 ; aci high(key_table) ; mov H, A ; mov A, M ; A - преобразованный код cpi 0xB0 ; 0 (доп) jz set_mode_0 ; выбор скорости интерфейса cpi 0xB1 ; 1 (доп) jz set_mode_1 ; режим XON/XOFF cpi 0xB2 ; 2 (доп) jz set_mode_2 ; КОИ Н0/Н1 или КОИ Н2 cpi 0xB3 ; 3 (доп) jz set_mode_3 ; авто ПС, ВК cpi 0xB4 ; 4 (доп) jz set_mode_4 ; запрет автоповтора cpi 0xB5 ; 5 (доп) jz set_mode_5 ; фиксация курсора в крайних положениях cpi 0xB6 ; 6 (доп) jz set_mode_6 ; отображения управляющих символов cpi 0xB7 ; 7 (доп) jz set_mode_7 ; разрешение контроля четности cpi 0xB8 ; 8 (доп) jz set_mode_8 ; выбор контроля чет/нечет cpi 0xB9 ; 9 (доп) jz set_mode_9 ; выбор стоп-бит 1/2 jmp irq_key_exit ; остальное игнорируем ;_______________________________________________________________________ ; ; Подпрограмма передачи кода в ЭВМ в режиме ЛИН (линия). ; В режиме АВТ (автоном) производится имитация приема этого символа от ЭВМ. ; ; A - передаваемый символ ; put_char: push PSW ; сохраним регистры push B ; mov B, A ; cохраним код lda stat_line_lin ; режим ЛИН/АВТ ? rrc ; jc @@auto ; режим АВТономный lda stat_line_alf ; режим авто ВК, ПС ? rrc ; jnc @@nolf ; нет авто ВК, ПС mov A, B ; cpi _lf ; передается символ ПС ? jz @@crlf ; cpi _cr ; передается символ ВК ? jz @@crlf ; ; @@nolf: call @@send ; передаем код в ЭВМ pop B ; восстановим регистры pop PSW ; ret ; ; @@auto: push D ; сохраним регистры push H ; lhld rx_beg ; загрузим указатели буфера mov E, H ; DE = указатель для записи mvi D, high(rx_buf) ; в приемный буфер mov A, E ; передвинем указатель inr A ; ori low(rx_buf) ; mov E, A ; mov H, E ; сохраним указатели shld rx_beg ; mov A, B ; запишем символ в буфер stax D ; pop H ; восстановим регистры pop D ; pop B ; pop PSW ; ret ; ; @@crlf: mvi B, _cr ; передать в ЭВМ код ВК call @@send ; mvi B, _lf ; передать в ЭВМ код ПС call @@send ; pop B ; восстановить регистры pop PSW ; ret ; ; ; Локальная подпрограмма передачи кода в ЭВМ из регистра B ; @@send: in sio_csr ; ждем готовность UART rrc ; jnc @@send ; mov A, B ; сброс старшего бита ani 0x7F ; out sio_dat ; передача данных ret ; ;_______________________________________________________________________ ; ; Обработка нажатия УСТ РЕЖИМА, 2 или установленного бита 7 в порту B ; (выбор КОИ Н0 и Н1 (0) или КОИ Н2 (1)) ; set_mode_2: lda stat_line_koi ; читаем значение признака ori '0' ; xri 0x01 ; меняем признак sta stat_line_koi ; сохраняем признак jmp irq_key_exit ; ;_______________________________________________________________________ ; ; Обработка нажатия УСТ РЕЖИМА, 4 или установленного бита 5 в порту B ; (запрет автоповтора) ; set_mode_4: lda stat_line_arpt ; читаем значение признака ori '0' ; xri 0x01 ; меняем признак sta stat_line_arpt ; сохраняем признак jmp irq_key_exit ; ;_______________________________________________________________________ ; ; Обработка нажатия УСТ РЕЖИМА, 6 или установленного бита 3 в порту B ; (разрешение отображения управляющих символов) ; set_mode_6: lda stat_line_nct ; ori '0' ; xri 0x01 ; sta stat_line_nct ; rrc ; jc @@set ; признак установлен mvi A, 0x0E ; сбросить бит C7 в pio out pio_csr ; jmp irq_key_exit ; @@set: mvi A, 0x0F ; установить бит C7 в pio out pio_csr ; jmp irq_key_exit ; ;_______________________________________________________________________ ; ; Вывод в статусной строке НР/ВР в зависимости от установленного ; регистра - key_stat_caps в ячейке key_stat ; show_caps: push PSW ; lda key_stat ; ani key_stat_caps ; jz @@nocaps ; ; mvi A, 0xEE ; вывод надписи ВР sta stat_line_caps+0 ; jmp @@exit ; ; @@nocaps: mvi A, 0xF7 ; вывод надписи НР sta stat_line_caps+0 ; @@exit: mvi A, 0xF2 ; sta stat_line_caps+1 ; pop PSW ; ret ; ;_______________________________________________________________________ ; ; Вывод в статусной строке ЛАТ или РУС в зависимости от установленного ; режима - бита key_stat_lat в ячейке key_stat ; show_ruslat: push PSW ; сохраним регистры push H ; lxi H,stat_line_lat ; адрес надписи РУС/ЛАТ lda key_stat ; в видеопамяти ani key_stat_lat ; jz @@outrus ; mvi M,0xEC ; вывод надписи ЛАТ inx H ; mvi M,0xE1 ; inx H ; mvi M,0xF4 ; pop H ; pop PSW ; ret ; ; @@outrus: mvi M,0xF2 ; вывод надписи РУС inx H ; mvi M,0xF5 ; inx H ; mvi M,0xF3 ; pop H ; pop PSW ; ret ; ;_______________________________________________________________________ ; ; Обработка нажатия УСТ РЕЖИМА, 0 (выбор скорости интерфейса) set_mode_0: lda uart_baud ; Выбрать следующую скорость inr A ; 0 - 9600, 1 - 4800, 2 - 2400 ani 0x07 ; 3 - 1200, 4 - 600, 5 - 300 sta uart_baud ; 6 - 150, 7 - 75 mvi A,0x40 ; Программный сброс последов. out sio_csr ; интерфейса (линия) call set_baud ; Вывод в служ.стр. и прогр.скорости jmp irq_key_exit ; Возврат ;_______________________________________________________________________ ; ; Вывод в служебную строку значения скорости и программирование последова- ; тельного интерфейса (линия) на заданную скорость set_baud: push PSW ; Сохранить регистры push D push H lda uart_baud ; Прочесть значение скорости lxi H, baud_table ; Получить адрес блока параметров rlc ; равный 03A9H + скорость * 8 rlc rlc add l mov l,A mov A,H aci 0x00 mov H,A lxi D, stat_line_baud ; Адрес надписи в служебной строке mov A,M ; Вывести значение скорости в служебную inx H ; строку stax D inx D mov A,M inx H stax D inx D mov A,M inx H stax D inx D mov A,M inx H stax D inx D mov E,M ; Прочесть байт сброса inx H lda uart_cmd ; Прочесть управляющее слово ana E ; Сбросить биты в упр.слове mov E,M ; Прочесть байт установки inx H ora E ; Установить биты в упр.слове sta uart_cmd ; Сохранить управляющее слово out sio_csr ; Передать упр.слово в посл.интерфейс in pio_c ; Прочесть порт C паралл.интерфейса ani 0x9F ; Сбросить биты 6 и 5 ora M ; Установить биты из бл.параметров out pio_c ; Записать порт C inx H mov A,M ; Прочесть байт уст./сбр. RTS/DTR out key_csr ; Установить/сбросить RTS/DTR lda stat_line_lin ; Режим ЛИН/АВТ ? rrc jnc L_03A1 ; Режим ЛИН mvi A,0x00 ; Запретить прием/передачу с линии out sio_csr jmp L_03A5 L_03A1: mvi A,0x15 ; Разрешить прием/передачу с линии out sio_csr L_03A5: pop H ; Восстановить регистры pop D pop PSW ret baud_table: db '9600', 0xFE, 0x02, 0x40, 0x06 db '4800', 0xFE, 0x02, 0x00, 0x06 db '2400', 0xFE, 0x02, 0x00, 0x24 db '1200', 0xFE, 0x02, 0x20, 0x24 db ' 600', 0xFE, 0x02, 0x40, 0x24 db ' 300', 0xFE, 0x02, 0x60, 0x24 db ' 150', 0xFF, 0x03, 0x40, 0x24 db ' 75', 0xFF, 0x03, 0x60, 0x24 ;_______________________________________________________________________ ; ; Обработка Esc R (сдвиг изображения вверх) lda stat_line_hold ; Устан. режим задержанного вывода ? rrc L_03ED: jc main_loop ; Да - возврат call get_adrxy ; Получить адрес курсора mvi M, _space ; Погасить курсор call L_09C1 ; Сдвинуть изображение вверх call get_adrxy ; Получить адрес курсора mvi M, _rect ; Высветить курсор L_03FD: jmp main_loop ;_______________________________________________________________________ ; ; Обработка Esc S (сдвиг изображения вниз) lda stat_line_hold ; Устан. режим задержанного вывода ? L_0403: rrc jc main_loop ; Да - возврат call get_adrxy ; Получить адрес курсора mvi M, _space ; Погасить курсор L_040C: call L_095B ; Сдвинуть изображение вниз call get_adrxy ; Получить адрес курсора mvi M, _rect ; Высветить курсор jmp main_loop ;_______________________________________________________________________ ; ; Обработка Esc Q (раздвижка вправо) lda stat_line_hold ; Устан. режим задержанного вывода ? rrc jc main_loop ; Да - возврат call get_adrxy ; Получить адрес текущего символа mov H,D ; HL = адрес текущего символа mov A,M ; Прочесть текущий символ ani 0xA0 ; Оставить старший бит и устан. 5-й ori 0x20 ; бит (привести к пробелу) mov E,A ; Сохранить в E mvi A, scr_x-1 ; A = 79 - X (длина остатка строки) sub C L_042B: mov D,M ; Прочесть символ mov M,E ; Сохранить предыдущий (справа) mov E,D ; Сохранить в Е (предыдущий) inr l ; Перейти к след. адресу dcr A ; Уменьшить счетчик оставш.символов jp L_042B jmp main_loop ;_______________________________________________________________________ ; ; Обработка Esc P (раздвижка влево) lda stat_line_hold ; Устан. режим задержанного вывода ? rrc jc main_loop ; Да - возврат call get_adrxy ; Получить адрес текущего символа mov H,D ; HL = адрес послед.символа в строке mov A,E ori 0x7F mov l,A mov A,M ; Прочесть последний символ ani 0xA0 ; Оставить старший бит и устан. 5-й ori 0x20 ; бит (привести к пробелу) mov E,A ; Сохранить в E mvi A, scr_x-1 ; A = 79 - X (длина остатка строки) sub C L_044E: mov D,M ; Прочесть символ mov M,E ; Сохранить предыдущий (справа) mov E,D ; Сохранить в Е (предыдущий) dcr l ; Перейти к пред. адресу dcr A ; Уменьшить счетчик оставш.символов jp L_044E jmp main_loop ;_______________________________________________________________________ ; ; Обработка нажатия УСТАНОВКА РЕЖИМА + 9 ; или бит 0 порта B (переключатели выбора режима) ; ; Отвечает за выбор количества стоп-битов - 1 или 2 ; set_mode_9: lda stat_line_nstp ; прочесть значение признака rrc ; jc L_0483 ; Установлен 1 стоп-бит mvi A,'1' ; признак один стоп-бит sta stat_line_nstp ; вывод символа на экран mvi A,0x40 ; Прогр.сброс послед.порта(линия) out sio_csr lda uart_cmd; Поставить в управл.слове 1 стоп-бит ani 0x7F ori 0x40 L_0470: sta uart_cmd out sio_csr ; Запрограммировать послед.порт lda stat_line_lin ; Режим ЛИН/АВТ ? rrc jc irq_key_exit ; Режим АВТ mvi A,0x15 ; Разрешение приема/передачи с линии out sio_csr jmp irq_key_exit ; Возврат L_0483: mvi A, '2' ; признак два стоп-бита sta stat_line_nstp ; вывод символа на экран mvi A,0x40 ; Прогр.сброс послед.порта(линия) out sio_csr lda uart_cmd ; Поставить в управл.слове 2 стоп-бита ori 0xC0 jmp L_0470 ; Запрограммировать ;_______________________________________________________________________ ; ; Обработка нажатия УСТАНОВКА РЕЖИМА + 8 ; или бит 1 порта B (переключатели выбора режима) ; ; Установка контроля по четности или нечетности ; set_mode_8: mvi A,0x40 ; Прогр.сброс послед.порта(линия) out sio_csr lda stat_line_odd ; Прочесть значение признака xri 0x01 ; Переключить значения признака sta stat_line_odd ; Сохранить значение признака rrc ; Признак установлен ? jc L_04BC ; Да lda uart_cmd ; Поставить в упр.слове 5 бит(четность) ori 0x20 L_04A9: sta uart_cmd out sio_csr ; Запрограммировать послед.порт lda stat_line_lin ; Режим ЛИН/АВТ ? rrc jc irq_key_exit ; Режим АВТ mvi A,0x15 ; Разрешение приема/передачи с линии out sio_csr jmp irq_key_exit ; Возврат L_04BC: lda uart_cmd ; Сбросить в упр.слове 5 бит(нечетность) ani 0xDF jmp L_04A9 ; Запрограммировать ;_______________________________________________________________________ ; ; Обработка нажатия УСТАНОВКА РЕЖИМА + 7 ; или бит 2 порта B (переключатели выбора режима) ; ; Разрешение или запрет контроля по четности/нечетности ; set_mode_7: mvi A,0x40 ; Прогр.сброс послед.порта(линия) out sio_csr lda stat_line_nopar ; Прочесть значение признака xri 0x01 ; Переключить значения признака sta stat_line_nopar ; Сохранить значение признака rrc ; Признак установлен ? jc L_04EC ; Да lda uart_cmd ; Сбросить в упр.слове 4 бит(контроль) ani 0xEF L_04D9: sta uart_cmd out sio_csr ; Запрограммировать послед.порт lda stat_line_lin ; Режим ЛИН/АВТ ? rrc jc irq_key_exit ; Режим АВТ mvi A,0x15 ; Разрешение приема/передачи с линии out sio_csr jmp irq_key_exit ; Возврат L_04EC: lda uart_cmd ; Устан. в упр.слове 4 бит(контроль) ori 0x10 jmp L_04D9 ; Запрограммировать ; Обработка нажатия ОСНОВН КАДР L_04F4: lxi H,0xDF00 ; Заполнение видеопамяти в диапазоне mvi A,0xF7 ; DF00H-F7FFH "пробелами" L_04F9: mvi M, _space inx H cmp H jp L_04F9 push D mvi A, low(rx_buf) ; Установка указателей буферов sta rx_end ; на начало sta rx_beg call get_adrxy ; Получить адрес курсора mvi M, _space ; Погасить курсор в текущей позиции mvi B,0x00 ; Новая позиция курсора - 0, 0 mvi C,0x00 call get_adrxy ; Получить адрес новой позиции курсора mvi M, _rect ; Высветить курсор pop D jmp irq_key_exit ; Возврат ;_______________________________________________________________________ ; ; Изменение режимов ЛИН/АВТ по нажатию Ф20 L_051B: lda stat_line_lin ; Какой режим - ЛИН или АВТ ? rrc lxi H, stat_line_lin ; HL - адрес ЛИН/АВТ jc L_0533 ; Режим АВТ mvi M,0xE1 ; Высветить в служ.строке "АВТ" inx H mvi M,0xF7 inx H mvi M,0xF4 xra A ; Запрет передачи/приема с линии out sio_csr jmp irq_key_exit ; Возврат ;_______________________________________________________________________ ; L_0533: mvi M,0xEC ; Высветить в служ.строке "ЛИН" inx H mvi M,0xE9 inx H mvi M,0xEE mvi A,0x15 ; Разрешить передачу/прием с линии out sio_csr jmp irq_key_exit ; Возврат ;_______________________________________________________________________ ; ; Обработка нажатия Ф5 L_0542: lda stat_line_lin ; Режим ЛИН/АВТ ? rrc jc irq_key_exit ; Возврат (режим АВТ) lda key_stat ; Нажата клавиша ВР ? rrc cnc L_0A3D ; Нет - передать конец строки по линии cc L_09EF ; Да - передать конец страницы jmp irq_key_exit ; Возврат ;_______________________________________________________________________ ; ; Обработка нажатия СТОП КАДР L_0556: mvi A,0x1B ; Послать символ Esc в ЭВМ call put_char lda stat_line_hold ; Режим задержанного вывода ? rrc mvi A,0x5B ; Нет - послать "[" jnc L_0218 inr A ; Да - послать "\" jmp L_0218 ;_______________________________________________________________________ ; ; Обработка нажатия ДОП ВАРИАНТ L_0568: mvi A,0x1B ; Послать символ Esc в ЭВМ call put_char lda stat_line_dkl+1 ; Установлен режим ДКЛ ? rrc mvi A,0x3D ; Нет - послать "=" jnc L_0218 inr A ; Да - послать ">" jmp L_0218 ;_______________________________________________________________________ ; ; Обработка кода автоповтора L_057A: lda stat_line_arpt ; Автоповтор запрещен ? rrc jc irq_key_exit ; Да lda key_auto ; Прочитать код для автоповтора jmp L_0103 ; На обработку клавиши ;_______________________________________________________________________ ; ; Обработка отжатия СУ или ВР L_0587: lda key_ctrl ; Установлен признак нажатия СУ ana A jz L_0595 ; Нет xra A sta key_ctrl ; Очистить признак нажатия СУ jmp irq_key_exit ; Возврат L_0595: lda key_stat ; Очистить признак нажатия ВР ani ~key_stat_shft sta key_stat jmp irq_key_exit ; Возврат ;_______________________________________________________________________ ; ; Обработка нажатия РУС/ЛАТ L_05A0: lda stat_line_koi ; Стоит признак КОИ7 Н2 ? rrc jc L_05BC ; Да lda key_stat ; Какой режим алфавита ? ani key_stat_lat jz L_05B4 ; Режим РУС mvi A, _rus ; Передаем в ЭВМ код 0EH (РУС) jmp L_05B6 L_05B4: mvi A, _lat ; Передаем в ЭВМ код 0FH (ЛАТ) L_05B6: sta key_auto ; Сохранить для автоповтора jmp L_0218 ; Передать в ЭВМ L_05BC: lda key_stat ; Изменить режим алфавита xri key_stat_lat sta key_stat call show_ruslat ; Вывести надпись РУС или ЛАТ jmp irq_key_exit ; Обработка "пустой" клавиши L_05CA: jmp irq_key_exit ; Возврат ; Обработка нажатия ФКС L_05CD: lda key_stat ; Изм. в 20B4 признак регистра (бит 2) xri key_stat_caps sta key_stat call show_caps ; Вывести надпись НР или ВР jmp irq_key_exit ; Обработка нажатия СУ L_05DB: mvi A,0xFF ; Установить в 20B3 признак нажатия СУ sta key_ctrl jmp irq_key_exit ; Обработка нажатия ВР L_05E3: lda key_stat ; Уст. в 20B4 признак нажатия ВР(бит 0) ori key_stat_shft sta key_stat jmp irq_key_exit ; Обработка Esc \ (выход из режима задержанного вывода) lxi H, stat_line_hold-1 ; Стереть в служебной строке ЗВЫВ mvi A, _space mov M,A inx H mov M,A inx H mov M,A inx H mov M,A jmp main_loop ;_______________________________________________________________________ ; ; Обработка Esc = (включение режима ДКЛ) ; proc_esc_eq lxi H,stat_line_dkl ; Вывести в служебной строке ДКЛ mvi M,0xE4 inx H mvi M,0xEB inx H mvi M,0xEC jmp main_loop ;_______________________________________________________________________ ; ; Обработка Esc > (выключение режима ДКЛ) ; proc_esc_os: lxi H, stat_line_dkl ; Стереть в служебной строке ДКЛ mvi A, _space mov M,A inx H mov M,A inx H mov M,A jmp main_loop ;_______________________________________________________________________ ; ; Обработка Esc Z (запрос типа терминала) ; mvi A,0x1B ; Передать по линии Esc /K (VT-52) call L_063F mvi A,0x2F call L_063F mvi A,0x4B call L_063F jmp main_loop ;_______________________________________________________________________ ; ; Обработка Esc [ (установить режим задержанного вывода) ; lxi H, stat_line_hold-1 ; Вывод в служебной строке ЗВЫВ mvi M,0xFA inx H mvi M,0xF7 inx H mvi M,0xF9 inx H mvi M,0xF7 xra A ; Счетчик оставшихся строк = 0 sta fline jmp main_loop ; Подпрограмма посылки данных в ЭВМ по линии L_063F: push PSW lda stat_line_lin ; Режим ЛИН/АВТ ? rrc jc L_0651 ; Режим АВТ L_0647: in sio_csr ; ЭВМ готова принять данные ? rrc jnc L_0647 ; Нет pop PSW out sio_dat ; Передать данные ret L_0651: pop PSW ret ;_______________________________________________________________________ ; ; Обработка Esc J (очистка конца страницы) ; call L_06E3 ; Очистка конца текущей строки push B ; Сохранить текущие координаты mvi C,0x00 ; X = 0 L_0659: mov A, B ; Y = последныы строка ? cpi scr_y-1 jz L_0666 ; Да - достигли конца страницы inr B ; Перейти к следующей строке call L_06E3 ; Очистить строку jmp L_0659 L_0666: pop B ; Восстановить текущие координаты jmp main_loop ;_______________________________________________________________________ ; ; Обработка Esc Y (позиционирование курсора) ; call get_char ; Прочесть очередной символ call get_adrxy ; Получить адрес курсора mvi M, _space ; Погасить курсор cpi _space ; Код символа < 32 ? jm L_0682 ; Да - не обрабатывать cpi 0x38 ; Код символа >= 56 ? jp L_0682 ; Да - не обрабатывать sui 0x20 ; Вычесть 32 mov B,A ; Новая координата Y call get_adrxy ; Получить новый адрес курсора L_0682: mvi M, _rect ; Высветить курсор call get_char ; Прочесть очередной символ call get_adrxy ; Получить адрес курсора mvi M, _space ; Погасить курсор cpi 0x20 ; Код символа < 32 ? jm L_069C ; Да - не обрабатывать cpi 0x70 ; Код символа >= 102 ? jp L_069C ; Да - не обрабатывать sui 0x20 ; Вычесть 32 mov C,A ; Новая координата X call get_adrxy ; Получить новый адрес курсора L_069C: mvi M, _rect ; Высветить курсор jmp main_loop ;_______________________________________________________________________ ; ; Обработка Esc H (курсор в верхний левый угол) ; call get_adrxy ; Получить адрес курсора mvi M, _space ; Погасить курсор mvi B, 0 ; Y = 0 mvi C, 0 ; X = 0 call get_adrxy ; Получить новый адрес курсора mvi M, _rect ; Высветить курсор jmp main_loop ;_______________________________________________________________________ ; ; Обработка Esc I (курсор вверх со сдвигом) ; call get_adrxy ; Получить адрес курсора mvi M, _space ; Погасить курсор mov A,B ; Y = 0 ? ana A jz L_06C5 ; Да dcr B ; Y = Y - 1 L_06BD: call get_adrxy ; Получить новый адрес курсора mvi M, _rect ; Высветить курсор jmp main_loop L_06C5: call L_095B ; Сдвиг изображения вниз на одну строку push B mvi C,0x00 ; X = 0 (временно) call get_adrxy ; Получ.адрес перв.симв.освоб.строки xchg mvi A, scr_x-1 ; Длина строки mvi B, _space ; Заполнение пробелами L_06D3: mov M,B ; Цикл заполн.освоб.строки пробелами inx H dcr A jp L_06D3 pop B jmp L_06BD ;_______________________________________________________________________ ; ; Обработка Esc K (очистка конца строки) ; call L_06E3 ; Очистить конец строки jmp main_loop ;_______________________________________________________________________ ; ; Подпрограмма очистки конца строки ; L_06E3: call get_adrxy ; Получить адрес символа xchg ; Передать адрес символа в HL mvi D, _space ; D = пробел mov A,l ; A = мл.байт адреса OR 80H ori 0x80 ; +1 до 0 равен числу оставш.символов L_06EC: mov M,D ; Цикл заполнения конца строки inx H ; пробелами inr A jnz L_06EC ret ;_______________________________________________________________________ ; ; Обработка Esc D (курсор влево) ; mov A,C ; X = 0 ? ana A jz L_0704 ; Да call get_adrxy ; Получить адрес курсора mvi M, _space ; Погасить курсор dcr C ; X = X - 1 dcr l ; Адрес курсора - 1 mvi M, _rect ; Высветить курсор jmp main_loop L_0704: lda stat_line_nomrk ; Установлен режим фиксации маркера ? rrc jc main_loop ; Да - возврат call get_adrxy ; Получить адрес курсора mvi M, _space ; Погасить курсор mvi C, scr_x-1 ; X = 79 mov A,B ; Y = 0 ? ana A jnz L_0721 ; Нет mvi B, scr_y-1 ; Y = последняя строка L_0719: call get_adrxy ; Получить новый адрес курсора mvi M, _rect ; Высветить курсор jmp main_loop L_0721: dcr B ; Y = Y - 1 jmp L_0719 ;_______________________________________________________________________ ; ; Обработка Esc C (курсор вправо) ; mov A,C ; X = 79 ? cpi scr_x-1 jz L_0737 ; Да call get_adrxy ; Получить адрес курсора mvi M, _space ; Погасить курсор inr C ; X = X + 1 inr l ; Адрес курсора + 1 mvi M, _rect ; Высветить курсор jmp main_loop L_0737: lda stat_line_nomrk ; Установлен режим фиксации маркера ? rrc jc main_loop ; Да - возврат call get_adrxy ; Получить адрес курсора mvi M, _space ; Погасить курсор mvi C, 0 ; X = 0 mov A, B ; Y = последняя строка ? cpi scr_y-1 jnz L_0750 ; Нет mvi B,0x00 ; Y = 0 jmp L_0751 L_0750: inr B ; Y = Y + 1 L_0751: call get_adrxy ; Получить новый адрес курсора mvi M, _rect ; Высветить курсор jmp main_loop ;_______________________________________________________________________ ; ; Обработка Esc A (курсор вверх) ; mov A,B ; Y = 0 ? ana A jz main_loop ; Да - возврат call get_adrxy ; Получить адрес курсора mvi M, _space ; Погасить курсор dcr B ; Y = Y - 1 call get_adrxy ; Получить новые координаты курсора mvi M, _rect ; Высветить курсор jmp main_loop ;_______________________________________________________________________ ; ; Обработка Esc B (курсор вниз) ; mov A,B ; Y = последняя строка ? cpi scr_y-1 jz main_loop ; Да - возврат call get_adrxy ; Получить адрес курсора mvi M, _space ; Погасить курсор inr B ; Y = Y + 1 call get_adrxy ; Получить новые координаты курсора mvi M, _rect ; Высветить курсор jmp main_loop ;_______________________________________________________________________ ; ; Обработка Esc F (вход в псевдографику) ; mvi A,0xFF ; Установить режим псевдографики sta 0x20AD jmp main_loop ;_______________________________________________________________________ ; ; Обработка Esc G (выход из псевдографики) ; xra A ; Сбросить режим псевдографики sta 0x20AD jmp main_loop ;_______________________________________________________________________ ; ; Обработка Ctrl+O (ЛАТ) ; L_078F: mov E,A lda key_stat ; Установить бит 1 в 20B4 (режим ЛАТ) ori key_stat_lat sta key_stat call show_ruslat ; Вывод в статусной строке ЛАТ lda stat_line_koi ; Выбран набор КОИ7 Н2 ? rrc jc main_lout ; Да - вывод на экран jmp main_loop ;_______________________________________________________________________ ; ; Обработка Ctrl+M (возврат каретки) ; L_07A5: lda stat_line_alf ; Установлен режим Авто ПС, ВК ? rrc jc proc_lf ; да, на обработку ПС (Ctrl+J) call get_adrxy ; Получить адрес курсора mvi M, _space ; Погасить курсор mvi C,0x00 ; X = 0 call get_adrxy ; Получить новые координаты курсора mvi M, _rect ; Высветить на экране jmp main_loop ;_______________________________________________________________________ ; ; Обработка Ctrl+N (РУС) ; L_07BB: mov E,A ; lda key_stat ; ani ~key_stat_lat ; сбрасываем маску алфавита sta key_stat ; call show_ruslat ; вывод в статусной строке РУС lda stat_line_koi ; rrc ; выбран набор КОИ7 Н2 jc main_lout ; да - вывод на экран jmp main_loop ; ;_______________________________________________________________________ ; ; Обработка Ctrl+J (перевод строки) ; proc_lf: call get_adrxy ; получить адрес курсора mvi M, _space ; убрать курсор с экрана lda stat_line_alf ; включен режим Авто ПС, ВК ? rrc ; jnc line_feed ; нет mvi C, 0 ; X = 0, автоматический ВК ; line_feed: mov A, B ; Y = Y + 1 inr A ; mov B, A ; cpi scr_y ; Y > последняя строка ? jp L_07EF ; Да L_07E7: call get_adrxy ; Получить новый адрес курсора mvi M, _rect ; Высветить на экране jmp main_loop L_07EF: push B mvi C,0x00 ; X = 0 (временно) call get_adrxy ; Получить адрес видеопамяти xchg ; HL - адрес начала след. строки mvi A,scr_x-1 ; A - длина строки mvi B, _space ; B - код пробела L_07FA: mov M,B ; Заполнение строки пробелами inx H dcr A jp L_07FA pop B dcr B ; Y = Y - 1 (последняя строка) call L_099B ; Прокрутка изображения вверх jmp L_07E7 ;_______________________________________________________________________ ; ; Обработка Ctrl+I (табуляция) ; L_0808: call get_adrxy ; Получить адрес курсора mvi M, _space ; Убрать курсор с экрана mov A, C cpi scr_x-1 ; Координата X равна 79 ? jp L_0820 ; Да cpi 0x47 ; Координата X >= 71 ? jp L_0825 ; Да ani 0xF8 ; Очистить мл.три бита X = X & F8H adi 0x08 ; X = X + 8 L_081C: mov C,A call get_adrxy ; Получить новый адрес курсора L_0820: mvi M, _rect ; Высветить на экране jmp main_loop L_0825: inr A ; X = X + 1 jmp L_081C ;_______________________________________________________________________ ; ; Обработка Ctrl+H (шаг назад) ; L_0829: call get_adrxy ; Получить адрес курсора mvi M, _space ; Убрать курсор с экрана mov A,C ana A ; Координата X равна нулю ? jz L_0838 ; Да dcr A ; Уменьшить координату X mov C,A call get_adrxy ; Получить новый адрес курсора L_0838: mvi M, _rect; Высветить на экране jmp main_loop ;_______________________________________________________________________ ; ; Обработка Ctrl+[ (Esc) ; proc_esc: call get_char ; получаем следующий символ cpi '=' ; jm main_loop ; меньше нижней границы cpi ']' ; jp main_loop ; больше верхней границы sui '=' ; получаем смещение в таблице rlc ; mov E, A ; mvi D, 0 ; lxi H, table_esc ; dad D ; mov E, M ; inx H ; mov D, M ; xchg ; pchl ; переход на процедуру обработки ;_______________________________________________________________________ ; ; Таблица адресов обработки Esc-последовательностей ; table_esc: dw proc_esc_eq ; Esc = dw proc_esc_os ; Esc > dw main_loop ; Esc ? dw main_loop ; Esc @ dw 0x0759 ; Esc A dw 0x076C ; Esc B dw 0x0725 ; Esc C dw 0x06F3 ; Esc D dw 0x008E ; Esc E dw 0x0780 ; Esc F dw 0x0788 ; Esc G dw 0x06A1 ; Esc H dw 0x06B2 ; Esc I dw 0x0653 ; Esc J dw 0x06DD ; Esc K dw main_loop ; Esc L dw main_loop ; Esc M dw main_loop ; Esc N dw main_loop ; Esc O dw 0x0436 ; Esc P dw 0x0417 ; Esc Q dw 0x03E9 ; Esc R dw 0x0400 ; Esc S dw main_loop ; Esc T dw main_loop ; Esc U dw main_loop ; Esc V dw main_loop ; Esc W dw main_loop ; Esc X dw 0x066A ; Esc Y dw 0x0618 ; Esc Z dw 0x062A ; Esc [ dw 0x05EE ; Esc \ ;_______________________________________________________________________ ; ; Подпрограмма обработки прерывания с линии ; irq_sio_rx: push PSW ; сохраняем регистры push D ; push H ; mvi A, 0x20 ; команда "конец прерывания" out pic_csr ; для контроллера прерываний ; in sio_dat ; читаем символ с линии ani 0x7F ; оставляем младшие семь бит cpi 0 ; получили ноль ? jz @@drop ; просто отбросим lhld rx_beg ; читаем указатели буферов mov E, H ; DE указатель на запись mvi D, high(rx_buf) ; mov A, E ; увеличим значение указателя inr A ; ori low(rx_buf) ; mov E, A ; mov H, E ; сохраним новый указатель shld rx_beg ; ; lda stat_line_nopar ; разрешен контроль чтености rrc ; jnc @@noerr ; нет контроля in sio_csr ; читаем слово состояния ani 0x08 ; проверка ошибки четности jz @@noerr ; нет ошибки mvi A, 0x7F ; записываем в буфер 7F stax D ; ; @@waite: in sio_csr ; контроллер готов к передаче rrc ; jnc @@waite ; mvi A, 0x15 ; сброс ошибок контроллера out sio_csr ; jmp @@drop ; ; @@noerr: in sio_dat ; читаем символ с линии ani 0x7F ; оставляем младшие семь бит stax D ; записываем в буфер ; @@drop: in sio_dat ; сброс запроса на прерывание lda stat_line_xon ; установлен режим XON/XOFF rrc ; jnc @@exit ; mov A, L ; указатель на чтение из буфера sui 10 ; вычесть 10 ori low(rx_buf) ; cmp E ; сравнить с указателем на запись jnz @@exit ; не равны - не посылаем XOFF ; @@wait: in sio_csr ; ждем готовность передатчика rrc ; jnc @@wait ; mvi A,_xoff ; посылаем в ЭВМ _XOFF out sio_dat ; (осталось 10 ячеек в буфере) mvi A, 0xB1 ; Установить старший бит в признаке sta stat_line_xon ; режима XON/XOFF @@exit: pop H ; восстановим регистры pop D ; pop PSW ; ei ; разрешим прерывания ret ; возврат из прерывания ;_______________________________________________________________________ ; ; Подпрограмма ожидания прихода символа с линии ; get_wait: lda stat_line_xon ; прочесть признак XON/XOFF ana A ; признак окончания буфера jp @@wait ; нет ani 0x7F ; сбросить признак окончания буфера sta stat_line_xon ; сохранить признак @@waits: lda stat_line_lin ; режим ЛИН/АВТ ? rrc ; jc @@wait ; режим АВТ in sio_csr ; контроллер готов rrc ; к передаче символа? jnc @@waits ; передатчик не готов mvi A, _xon ; послать в ЭВМ код XON out sio_dat ; для разблокировки ; @@wait: ei ; разрешить прерывания hlt ; останов (ожидание прерывания) ;_______________________________________________________________________ ; ; Подпрограмма чтения полученного символа из приемного буфера, если ; буфер пусто то происходит ожидание поступления символа в прерывании ; ; Возвращает: ; A - 7-битный принятый символ ; DE - адрес символа ; get_char: di ; запретить прерывания lhld rx_beg ; прочесть указатели буферов mov E, H ; указатель на запись (мл.байт) mvi H, high(rx_buf) ; HL - указатель на чтение mov A, L ; сравнить указатели cmp E ; если они равны то буфер пуст jz get_wait ; надо ждать приема символа inr A ; увеличить значение указателя ori low(rx_buf) ; mov L, A ; mov A, M ; прочесть символ из буфера ani 0x7F ; оставить семь младших бит mov H, E ; cохранить указатели shld rx_beg ; ei ; разрешить прерывания ret ; ;_______________________________________________________________________ ; ; Получение адресов курсора и символа в видеобуфере с учетом текущей ; отображаемой начальной строки ; ; Входные параметры: ; B - координата Y ; C - координата X ; Возвращает: ; HL - адрес курсора ; DE - адрес символа ; get_adrxy: push PSW ; mov A, C ; корректируем координату X на adi 48 ; смещение видимой части строки mov L, A ; in pio_a ; читаем начальную строку отображения add B ; добавляем координату Y rar ; mov H, A ; jnc @@skipc ; mov A, L ; ori 0x80 ; mov L, A ; ; @@skipc: mvi A, high(mark_start) ; вычисляем адрес курсора add H ; проверим выход за пределы cpi high(mark_end) ; области отображения jm @@markok ; sui high(mark_end-mark_start) ; @@markok: mov H, A ; adi high(vbuf_start-mark_start) mov D, A ; H старшая часть адреса курсора mov E, L ; корректируем смещение до символа pop PSW ; DE адрес символа ret ; ;_______________________________________________________________________ ; ; Сдвиг изображения вниз на одну строку L_095B: push PSW in pio_a ; Прочесть номер первой строки ana A ; Он равен нулю ? jz L_0967 ; Да dcr A ; Вычесть один L_0963: out pio_a ; Записать номер первой строки pop PSW ret L_0967: mvi A,0x2F ; Номер первой строки равен 47 jmp L_0963 ;_______________________________________________________________________ ; ; Обработка управляющих кодов (диапазон 1 - 31) ; proc_ctrl: mov E, A ; lda stat_line_nct ; включен режим отображения rrc ; управляющих символов mov A, E ; jc main_ctrl ; отобразим как обычный cpi _bs ; забой jz L_0829 ; cpi _tab ; табуляция jz L_0808 ; cpi _lf ; перевод строки jz proc_lf ; cpi _cr ; возврат каретки jz L_07A5 ; cpi _rus ; РУС jz L_07BB ; cpi _lat ; ЛАТ jz L_078F ; cpi _esc ; Escape jz proc_esc ; jmp main_loop ; остальное отбрасываем ;_______________________________________________________________________ ; ; Прокрутка изображения вверх с учетом задержанного вывода ; L_099B: lda stat_line_hold ; Включен режим задержанного вывода ? rrc jnc L_09C1 ; Нет lda fline ; Уменьшить счетчик прокрученных строк dcr A sta fline jp L_09C1 ; Счетчик >= 0 mvi A,_xoff call L_063F ; Послать в ЭВМ код 13H (Ctrl+S) L_09B1: hlt ; Останов (обработка прерываний) lda fline ; Счетчик стал >= 0 ana A jm L_09B1 ; Нет, ждем lda stat_line_xon ; Установить признак оконч. ori 0x80 ; буфера режима XON/XOFF sta stat_line_xon L_09C1: in pio_a ; Прочесть номер перв.строки на экране inr A ; Увеличить на один cpi 0x30 ; Номер стал >= 48 ? jm L_09CB ; Нет sui 0x30 ; Вычесть 48 (закольцевать) L_09CB: out pio_a ; Записать номер первой строки ret ; Обработка нажатия УСТ РЕЖИМА, 5 или установленного бита 4 в порту B ; (разрешение/запрет фиксации курсора в крайних положениях строки) set_mode_5: lda stat_line_nomrk ; Прочесть значение признака xri 0x01 ; Изменить значение признака sta stat_line_nomrk ; Сохранить признак jmp irq_key_exit ; Возврат ; Обработка нажатия УСТ РЕЖИМА, 1 или установленного бита 0 в порту С ; (режим XON/XOFF) set_mode_1: lda stat_line_xon ; Прочесть значение признака xri 0x01 ; Изменить значение признака sta stat_line_xon ; Сохранить признак jmp irq_key_exit ; Возврат ; Обработка нажатия УСТ РЕЖИМА, 3 или установленного бита 6 в порту B ; (авто ПС, ВК) set_mode_3: lda stat_line_alf ; Прочесть значение признака xri 0x01 ; Изменить признак sta stat_line_alf ; Сохранить jmp irq_key_exit ; Возврат ; Передача конца страницы по линии L_09EF: push PSW ; Сохранить регистры push B L_09F1: call L_0A3D ; Передать конец текущей строки mov A,B cpi 0x17 ; Достигли последней строки jp L_0A00 ; Да inr B ; Перейти к следующей строки mvi C,0x00 ; Начать передачу с начала jmp L_09F1 L_0A00: pop B ; Восстановить регистры pop PSW ret ; Передача символа в ЭВМ при исполнении п/п передачи строки L_0A03: push H mov l,A ; Сохранить символ в L lda stat_line_xon ; Установлен режим XON/XOFF ? rrc cc L_0A19 ; Да L_0A0C: in sio_csr ; ЭВМ готова принять данные ? rrc jnc L_0A0C ; Нет - ждем mov A,l ani 0x7F out sio_dat ; Передать символ в ЭВМ pop H ret L_0A19: in sio_csr ; Данные переданы из ЭВМ ? rrc rrc rnc ; Нет - возврат in sio_dat ; Прочесть переданный символ ani 0x7F ; Оставить только семь бит cpi _xoff ; Передан символ Ctrl+S ? rnz ; Нет - возврат L_0A25: in key_dat ; Прочесть код символа с клавиатуры cpi 0x83 ; Была нажата Ф20 ? jz L_0A3C ; Да - возврат in sio_csr ; Данные переданы из ЭВМ ? rrc rrc jnc L_0A25 ; Нет - ждем in sio_dat ; Прочесть переданный символ ani 0x7F ; Оставить только семь бит cpi _xon ; Передан символ Ctrl+Q ? jnz L_0A25 ; Нет - ждем L_0A3C: ret ; Передача строки по линии (от позиции курсора до конца) L_0A3D: push PSW ; Сохранить все регистры push B push D push H call get_adrxy ; Получить адреса курсора и символа mov H,D ; DE - адрес конца строки mvi A,0x7F ; HL - адрес строки в позиции курсора ora E mov E,A L_0A49: ldax D ; Получить символ (с конца строки) ani 0x7F ; Сбросить старший бит cpi _space ; Это пробел ? jnz L_0A5A ; Нет mov A,E cmp l ; Дошли до позиции курсора jz L_0A5A ; Да dcr E ; Перейти к предыдущему символу jmp L_0A49 L_0A5A: lda stat_line_koi ; Используется набор КОИ7 Н2 ? rrc cnc L_0A84 ; Нет (послать код РУС или ЛАТ) L_0A61: lda stat_line_koi ; Используется набор КОИ7 Н2 ? rrc cnc L_0A99 ; Нет (сменить алфавит, если надо) mov A,M ; Прочесть символ с видеопамяти call L_0A03 ; Передать в ЭВМ mov A,E ; Адрес конца строки cmp l ; Дошли до конца jz L_0A75 ; Да inr l ; Перейти к следующему символу jmp L_0A61 ; Продолжить L_0A75: mvi A, _cr ; Передать код ВК в ЭВМ call L_0A03 mvi A, _lf ; Передать код ПС в ЭВМ call L_0A03 pop H ; Восстановить регистры pop D pop B pop PSW ret ; Посылка кода РУС или ЛАТ в зависимости от алфавита текущего символа L_0A84: mov A, M ; читаем символ с видеопамяти ani 0x80 ; проверяем старший бит jnz @@rus ; Это русский алфавит mvi A, _lat ; управляющий символ ЛАТ mvi C, 0 ; признак латинского алфавита jmp @@send ; @@rus: mvi A, _rus ; управляющий символ РУС mvi C, 0x80 ; признак русского алфавита @@send: call L_0A03 ; Передача управляющего символа в ЭВМ ret ; Посылка кода РУС или ЛАТ, если алфавит текущего символа не совпадает L_0A99: mov A,M ; Прочесть символ с видеопамяти xra C ; Проверить старший бит cm L_0A84 ; Не совпадает - сменить алфавит ret ;_______________________________________________________________________ ; ; Подпрограмма чтения состояния переключателей и установки режимов ; работы по состоянию DIP-переключателей ; get_switch: in pio_c ; чтение порта C паралл.адаптера rrc ; cc @@bitc ; установлен бит 0 ani 0x07 ; выделить скорость обмена sta uart_baud ; call set_baud ; установка скорости обмена ; in pio_b ; rrc ; cc @@bit0 ; rrc ; cc @@bit1 ; rrc ; cc @@bit2 ; rrc ; cc @@bit3 ; rrc ; cc @@bit4 ; rrc ; cc @@bit5 ; rrc ; cc @@bit6 ; rrc ; cc @@bit7 ; ret ; ; @@bit0: push PSW ; push H ; jmp set_mode_9 ; выбор стоп битов 1 или 2 ; @@bit1: push PSW ; push H ; jmp set_mode_8 ; выбор контроля чет/нечет ; @@bit2: push PSW ; push H ; jmp set_mode_7 ; разрешение контроля четности ; @@bit3: push PSW ; push H ; разрешение отображения jmp set_mode_6 ; управляющих символов ; @@bit4: push PSW ; разрешение/запрет фиксации push H ; курсора в крайних jmp set_mode_5 ; положениях строки ; @@bit5: push PSW ; push H ; jmp set_mode_4 ; запрет автоповтора ; @@bit6: push PSW ; push H ; jmp set_mode_3 ; авто ПС, ВК ; @@bit7: push PSW ; push H ; jmp set_mode_2 ; КОИ Н0/Н1 или КОИ Н2 ; @@bitc: push PSW ; push H ; jmp set_mode_1 ; режим XON/XOFF ;_______________________________________________________________________ ; ; Таблица перекодировки скан-кодов клавиатуры МС-7004 ; Принятый из UART символ предварительно инвертируется ; key_table: db 0 ; 377 db 0 ; 376 db 0x5F ; 375 ~ db 0xFC ; 374 { | db 0x5C ; 373 Э \ db 0x3A ; 372 : * db 0x2D ; 371 - = db 0 ; 370 db '.' ; 367 . > db 'H' ; 366 Х H db 0xFC ; 365 } db 0 ; 364 db ',' ; 363 , < db 'V' ; 362 Ж V db 0x5F ; 361 _ db 'Z' ; 360 З Z db '0' ; 357 0 db 0 ; 356 db '@' ; 355 Ю @ db 'D' ; 354 Д D db ']' ; 353 Щ ] db '9' ; 352 9 ) db 0 ; 351 db 0x42 ; 350 Б B db 0x4C ; 347 Л L db 0x5B ; 346 Ш [ db 0x38 ; 345 8 ( db 0 ; 344 db 0x58 ; 343 Ь X db 0x4F ; 342 О O db 0x47 ; 341 Г G db 0x37 ; 340 7 ' db 0 ; 337 db 0x54 ; 336 Т T db 0x52 ; 335 Р R db 0x4E ; 334 Н N db 0x36 ; 333 6 & db 0 ; 332 db 0x49 ; 331 И I db 0x50 ; 330 П P db 0x45 ; 327 Е E db 0x35 ; 326 5 % db 0 ; 325 db _space ; 324 Пробел db 0x4D ; 323 М M db 0x41 ; 322 А A db 0x4B ; 321 К K db 0x34 ; 320 4 $ db 0 ; 317 db 0x53 ; 316 С S db 0x57 ; 315 В W db 0x55 ; 314 У U db 0x33 ; 313 3 # db 0x2F ; 312 / ? db 0xFC ; 311 Резервная клавиша db 0x5E ; 310 Ч ^ db 0x59 ; 307 Ы Y db 0x43 ; 306 Ц C db 0x32 ; 305 2 " db 0x0A ; 304 Ъ db 0x51 ; 303 Я Q db 0x46 ; 302 Ф F db 0x4A ; 301 Й J db 0x31 ; 300 1 ! db 0x3B ; 277 ; + db 0x09 ; 276 ТАБ db 0x0D ; 275 ВК db 0x7F ; 274 ЗБ dc 7, 0 ; 273-265 db 0xFF ; 264 Автоповтор db 0xFE ; 263 Отжатие СУ или ВР db 0xFD ; 262 РУС/ЛАТ db 0xFC ; 261 КМП db 0xFB ; 260 ФКС db 0xFA ; 257 Нажатие СУ db 0xF9 ; 256 Нажатие ВР db 0 ; 255 db 0 ; 254 db 0 ; 253 db 0xC1 ; 252 Стрелка вверх db 0xC2 ; 251 Стрелка вниз db 0xC3 ; 250 Стрелка вправо db 0xC4 ; 247 Стрелка влево db 0 ; 246 db 0 ; 245 db 0xD3 ; 244 ПФ4 db 0xD2 ; 243 ПФ3 db 0xD1 ; 242 ПФ2 db 0xD0 ; 241 ПФ1 db 0xAD ; 240 - (доп) db 0xB9 ; 237 9 (доп) db 0xB8 ; 236 8 (доп) db 0xB7 ; 235 7 (доп) db 0xAC ; 234 , (доп) db 0xB6 ; 233 6 (доп) db 0xB5 ; 232 5 (доп) db 0xB4 ; 231 4 (доп) db 0xB3 ; 230 3 (доп) db 0xB2 ; 227 2 (доп) db 0xB1 ; 226 1 (доп) db 0x8D ; 225 ВВОД (доп) db 0xAE ; 224 . (доп) db 0 ; 223 db 0xB0 ; 222 0 (доп) db 0 ; 221 db 0 ; 220 db 0xE8 ; 217 СЛЕД КАДР db 0xE7 ; 216 ПРЕД КАДР db 0xE6 ; 215 ВЫБР db 0xE5 ; 214 УДАЛ db 0xE4 ; 213 ВСТ db 0xE3 ; 212 НТ dc 6, 0 ; 211-204 db 0xF0 ; 203 Ф20 db 0xCB ; 202 Ф19 db 0xCA ; 201 Ф18 db 0xC8 ; 200 Ф17 db 0 ; 177 db 0 ; 176 db 0xE2 ; 175 ИСП db 0xE1 ; 174 ПМ dc 7, 0 ; 173-165 db 0xF6 ; 164 ДОП ВАРИАНТ db 0x0A ; 163 Ф13 (ПС) db 0x08 ; 162 Ф12 (ВШ) db _esc ; 161 Ф11 (АР2) dc 8, 0 ; 160-151 db 0x03 ; 150 ВЫХОД db 0xF5 ; 147 ОСНОВН КАДР db 0x15 ; 146 ОТМЕН db _xon ; 145 ПРОДОЛЖ db _xoff ; 144 ПРЕРЫВ dc 9, 0 ; 143-133 db 0xF3 ; 132 Ф5 db 0xF2 ; 131 УСТ РЕЖИМА db 0xF1 ; 130 ПАУЗА db 0xCD ; 127 ПЕЧАТЬ КАДРА db 0xF4 ; 126 СТОП КАДР dc 25, 0 ; не используются ;_______________________________________________________________________ ; org 0x0BC0 ; таблица прерываний ; должна быть выравнена irq_table: jmp reset ; на границы 64 байт nop ; jmp irq_key_rx ; nop ; jmp reset ; nop ; jmp irq_sio_rx ; nop ; jmp reset ; nop ; jmp reset ; nop ; jmp reset ; nop ; jmp reset ; nop ; ; dc 32, 0 ; 32 zero bytes ;_______________________________________________________________________ ; end reset