Мы победили в себе склеротИк и откопали такой мы антИк
Мы победили в себе склеротИк и откопали такой мы антИк
С любовью к вам, Yandex.Direct
Размещение рекламы на форуме способствует его дальнейшему развитию
С другой стороны посредине лейбла кишиневского завода с логотипом и серийником (такая же пластина как на самом векторе).
Внутри квазидиск ;-)
Попозжее постараюсь сделать фото.
Уже больше месяца прошло, как исправил схему КД, но вот только сейчас увидел, что не разметил тут те исправления:
1. Микросхема D7 заменена на 74HC273. В принципе, работать будет и в предыдущем варианте, вот только при сбросе с ней триггеры не будут обнуляться.
2. Микросхема D8 заменена на К1533ЛР13, только из соображений быстродействия. К сожалению, это потянуло за собой значительное изменение разводки платы.
3. Ну и попутно немного оптимизировал разводку...
Архив со схемой, разводкой и гербером: kd_sram11.7z
P.S. Диоды D13 и D14 лучше использовать какие-нибудь Шотки, например 1N5819, -- на них меньше падение напряжения. Или же просто поставить перемычку вместо D14, а D13 не ставить совсем, если использование аккумулятора не планируется.
Последний раз редактировалось Improver; 26.10.2018 в 13:20. Причина: Примечание.
Наверно, по той же причине, почему бы не заменить всю конструкцию на ПЛИС и не получить при этом "Комбодевайс2"...А если серьёзно -- если что-то можно решить на обычной логике достаточно малым числом корпусов МС, то я не вижу особой необходимости делать это на ПЗУ. Так же, собственно, было сделано и в последующей конструкции КД (на РУ7)...
- - - Добавлено - - -
И ещё, могу уже похвалиться собранной конструкцией по последней схеме:
Только вот микросхем памяти пока что ещё нет, т.к. они в доставке с ибея... Но всё остальное, что возможно, протестил -- работает так, как и было задумано.
Может, кому пригодится, вот мои тесты для контроллера КД:
Тест 0
Как написано в документации к оригинальному КД, начальный тест -- это просто включение Вектора с подключённым диском. Если загрузке Вектора собранный КД не мешает, то значит всё в порядке.[свернуть]Тест 1
Проверка правильности работы схемы дешифратора адреса порта КД и регистра конфигурации (микросхемы D1, D2:A, D12:A,B,C и D7). Результат тестирования проверяется мультиметром, на соответствующих выводах D7 должны появляться сигналы "1". Запускать с отключённым сигналом "БЛК" (например, без установленной D8), иначе Вектор подвиснет.
Текст теста на ассемблере для запуска в любом мониторе-отладчике:
Код:.ORG 00100h L_0100: LDA L_DATA RLC STA L_DATA OUT 010h ; отправляем в порт LDA L_DT INR A STA L_DT LXI D, L_TEXT MVI C, 009h CALL 5 ; вывод сообщения MVI C,1 LXI D,2000h CALL 5 ; ожидание нажатия клавиши LDA L_DATA CPI 080h ; проверка JNZ L_0100 ; цикл MVI A, '0' STA L_DT RET ; выход ---->>>> L_TEXT: .db 0Dh, 0Ah, "OUT DATA: " L_DT: .db "0$" L_DATA: .db 080h .END[свернуть]Тест 2
Проверка работы в режиме "стек", проверяется формирователь сигнала "БЛК" на МС D8 (и, конечно, дополнительно и то, что проверялось в тесте 1). Этим тестом производится запись данных во все четыре банка КД по адресам, совпадающим с экранной областью монитора-отладчика, и в случае сбоя на экране будут видны "артефакты".
Код:.ORG 00100h L_0100: LXI D, L_DATA PUSH D ; сохраняем в стеке ссылку L_MAIN: POP D ; считываем ссылку LDAX D ; загружаем A по ссылке ORA A RZ ; выход, если там ноль ---->>>> INX D ; DE=DE+1 PUSH D ; сохраняем в стеке новую ссылку DI ; запрещаем прерывания OUT 010h ; отправляем в порт LXI H, 0000h ; заполнение памяти DAD SP ; SP+0 в HL SHLD L_SAVE ; сохранить указатель на стек LXI D, 55AAh ; чем заполнять LXI H, 1000h ; сколько/2 LXI SP,0E000h ; свой указатель на стек L_LOOP: PUSH D ; заполняем через стек... DCX H MOV A, L ORA H JNZ L_LOOP ; зациклено XRA A ; обнуляем аккумулятор OUT 010h ; отправляем в порт -- отключаем КД LHLD L_SAVE ; считать сохранённый указатель на стек в HL SPHL ; восстанавливаем SP EI ; разрешаем прерывания LXI D, L_TEXT MVI C, 009h CALL 5 ; вывод сообщения MVI C,1 LXI D, 2000h CALL 5 ; ожидание нажатия клавиши JMP L_MAIN ; цикл ; L_SAVE: .dw 0000h L_TEXT: .db 0Dh, 0Ah, "-- DONE --$" L_DATA: .db 1Ch ; 00011100b -- вкл. 0 банк как стек на КД .db 18h ; 00011000b -- вкл. 1 банк как стек на КД .db 14h ; 00010100b -- вкл. 2 банк как стек на КД .db 10h ; 00010000b -- вкл. 3 банк как стек на КД .db 00h ; конец .END[свернуть]Тест 3
Проверка работы КД в режиме "замена ОЗУ" по стандартной конфигурации. Дополнительно к предыдущим тестам, проверяются правильность работы МС D5 и D6. Ошибка выдаётся в случае совпадения последнего записанного в КД байта и считанного из ОЗУ после отключения КД.
Код:.ORG 00100h L_0100: LXI D, L_DATA PUSH D ; сохраняем в стеке ссылку L_MAIN: POP D ; считываем ссылку LDAX D ; загружаем A по ссылке ORA A RZ ; выход, если там ноль ---->>>> INX D ; DE=DE+1 PUSH D ; сохраняем в стеке новую ссылку OUT 010h ; отправляем в порт LXI H, 02000h ; заполнение памяти -- сколько LXI B, 0C000h ; с какого адреса L_LOOP: MVI A, 055h ; чем заполнять STAX B ; пишем INX B DCX H MOV A, L ORA H JNZ L_LOOP ; пока HL не обнулится XRA A ; обнуляем аккумулятор OUT 010h ; отправляем в порт -- отключаем КД DCX B ; на шаг назад LDAX B ; считываем последний байт CPI 055h ; сравниваем с тем, что писали LXI D, L_ERRT ; ссылка на сообщение об ошибке JZ L_DONE ; если равны -- значит КД работает не правильно LXI D, L_TEXT L_DONE: MVI C, 009h CALL 5 ; вывод сообщения MVI C,1 LXI D, 2000h CALL 5 ; ожидание нажатия клавиши JMP L_MAIN ; цикл ; L_SAVE: .dw 0000h L_TEXT: .db 0Dh, 0Ah, "-- DONE --$" L_ERRT: .db 0Dh, 0Ah, "-- ERROR --$" L_DATA: .db 23h ; 00100011b -- вкл. 0 банк как ОЗУ A000h-DFFFh .db 22h ; 00100010b -- вкл. 1 банк как ОЗУ A000h-DFFFh .db 21h ; 00100001b -- вкл. 2 банк как ОЗУ A000h-DFFFh .db 20h ; 00100000b -- вкл. 3 банк как ОЗУ A000h-DFFFh .db 00h ; конец .END[свернуть]Тест 4
То же самое, что и в третьем тесте, но только для схемы доработки Баркаря
Код:.ORG 00100h L_0100: LXI D, L_DATA PUSH D ; сохраняем в стеке ссылку L_MAIN: POP D ; считываем ссылку LDAX D ; загружаем A по ссылке ORA A RZ ; выход, если там ноль ---->>>> INX D ; DE=DE+1 PUSH D ; сохраняем в стеке новую ссылку OUT 010h ; отправляем в порт LXI H, 02000h ; заполнение памяти -- сколько CPI 080h LXI B, 08000h ; с какого адреса 1 JC L_LOOP ; если A < 080h LXI B, 0E000h ; с какого адреса 2 L_LOOP: MVI A, 055h ; чем заполнять STAX B ; пишем INX B DCX H MOV A, L ORA H JNZ L_LOOP ; пока HL не обнулится XRA A ; обнуляем аккумулятор OUT 010h ; отправляем в порт -- отключаем КД DCX B ; на шаг назад LDAX B ; считываем последний байт CPI 055h ; сравниваем с тем, что писали LXI D, L_ERRT ; ссылка на сообщение об ошибке JZ L_DONE ; если равны -- значит КД работает не правильно LXI D, L_TEXT L_DONE: MVI C, 009h CALL 5 ; вывод сообщения MVI C,1 LXI D, 2000h CALL 5 ; ожидание нажатия клавиши JMP L_MAIN ; цикл ; L_SAVE: .dw 0000h L_TEXT: .db 0Dh, 0Ah, "-- DONE --$" L_ERRT: .db 0Dh, 0Ah, "-- ERROR --$" L_DATA: .db 43h ; 01000011b -- вкл. 1 банк как ОЗУ 8000h-9FFFh .db 42h ; 01000010b -- вкл. 2 банк как ОЗУ 8000h-9FFFh .db 41h ; 01000001b -- вкл. 3 банк как ОЗУ 8000h-9FFFh .db 40h ; 01000000b -- вкл. 4 банк как ОЗУ 8000h-9FFFh .db 83h ; 10000011b -- вкл. 1 банк как ОЗУ E000h-FFFFh .db 82h ; 10000010b -- вкл. 2 банк как ОЗУ E000h-FFFFh .db 81h ; 10000001b -- вкл. 3 банк как ОЗУ E000h-FFFFh .db 80h ; 10000000b -- вкл. 4 банк как ОЗУ E000h-FFFFh .db 00h ; конец .END[свернуть]
А дальше, я думаю, надо ставить память и тестировать стандартными программами, типа "дождь" и т.д.
Все тесты откомпилированные для монитора-отладчика в одном архиве: MyTestKD.7z
Запускать можно под любым монитором-отладчиком, режим распределения памяти МО рекомендую выбирать <2>.
Пришла мне память... Поставил -- ни один из стандартных тестов не сказал "ОК".На основе одного из предыдущих, по-быстрому написал ещё несколько тестов:
Тест 5
В этом тесте будем пробовать что-то записать в память, а потом считать записанное в экранную область монитора для контроля записи. (Режим "ОЗУ")
Рекомендую после каждого запуска менять записываемый байт по адресу 113h (в "MVI A, 055h"), сделать это можно командой монитора "S113", далее новое значение и выход по точке.
Код:.ORG 00100h L_0100: LXI D, L_DATA PUSH D ; сохраняем в стеке ссылку L_MAIN: POP D ; считываем ссылку LDAX D ; загружаем A по ссылке ORA A RZ ; выход, если там ноль ---->>>> INX D ; DE=DE+1 PUSH D ; сохраняем в стеке новую ссылку OUT 010h ; отправляем в порт LXI H, 02000h ; заполнение памяти -- сколько LXI B, 0C000h ; с какого адреса L_LOOP: MVI A, 055h ; чем заполнять STAX B ; пишем INX B DCX H MOV A, L ORA H JNZ L_LOOP ; пока HL не обнулится LXI H, 02000h ; считываем -- сколько LXI B, 01000h ; куда LXI D, 0C000h ; откуда CALL L_MOVE XRA A ; обнуляем аккумулятор OUT 010h ; отправляем в порт -- отключаем КД LXI H, 02000h ; переброска считанного в экран -- сколько LXI B, 0C000h ; куда LXI D, 01000h ; откуда CALL L_MOVE ; наблюдаем и наслаждаемся... LXI D, L_TEXT L_DONE: MVI C, 009h CALL 5 ; вывод сообщения MVI C,1 LXI D, 2000h CALL 5 ; ожидание нажатия клавиши JMP L_MAIN ; цикл L_MOVE: LDAX D ; пп переброски данных STAX B INX D INX B DCX H MOV A, L ORA H JNZ L_MOVE RET ; L_TEXT: .db 0Dh, 0Ah, "-- DONE --$" L_DATA: .db 23h ; 00100011b -- вкл. 1 банк как ОЗУ A000h-DFFFh .db 22h ; 00100010b -- вкл. 2 банк как ОЗУ A000h-DFFFh .db 21h ; 00100001b -- вкл. 3 банк как ОЗУ A000h-DFFFh .db 20h ; 00100000b -- вкл. 4 банк как ОЗУ A000h-DFFFh .db 00h ; конец .END[свернуть]Тест 6
Проверка работы КД на запись/чтение данных в режиме "стек"
Код:.ORG 00100h L_0100: LXI D, L_DATA PUSH D ; сохраняем в стеке ссылку L_MAIN: POP D ; считываем ссылку LDAX D ; загружаем A по ссылке ORA A RZ ; выход, если там ноль ---->>>> INX D ; DE=DE+1 PUSH D ; сохраняем в стеке новую ссылку DI ; запрещаем прерывания OUT 010h ; отправляем в порт LXI H, 0000h ; заполнение памяти DAD SP ; SP+0 в HL SHLD L_SAVE ; сохранить указатель на стек LXI D, 55AAh ; чем заполнять LXI H, 1000h ; сколько/2 LXI SP,0E000h ; свой указатель на стек L_LOOP: PUSH D ; заполняем через стек... DCX H MOV A, L ORA H JNZ L_LOOP ; зациклено LXI H, 0C000h ; куда LXI B, 1000h ; сколько/2 L_LP2: POP D ; забираем из стека MOV M, E ; записываем в экранную область INX H MOV M, D INX H DCX B ; счётчик MOV A, C ORA B JNZ L_LP2 ; зациклено 2 XRA A ; обнуляем аккумулятор OUT 010h ; отправляем в порт -- отключаем КД LHLD L_SAVE ; считать сохранённый указатель на стек в HL SPHL ; восстанавливаем SP EI ; разрешаем прерывания LXI D, L_TEXT MVI C, 009h CALL 5 ; вывод сообщения MVI C,1 LXI D, 2000h CALL 5 ; ожидание нажатия клавиши JMP L_MAIN ; цикл ; L_SAVE: .dw 0000h L_TEXT: .db 0Dh, 0Ah, "-- DONE --$" L_DATA: .db 1Ch ; 00011100b -- вкл. 3 банк как стек на КД .db 18h ; 00011000b -- вкл. 2 банк как стек на КД .db 14h ; 00010100b -- вкл. 1 банк как стек на КД .db 10h ; 00010000b -- вкл. 0 банк как стек на КД .db 00h ; конец .END[свернуть]Тест 7
Это, скорее, не тест, а заполнение всего КД в режиме "стек" с последующим частичным контролем записи чтением записанного в режиме "ОЗУ". Пригодится при запуске предыдущих тестов, поэтому стартовый адрес сделан 0200h.
Код:.ORG 00200h L_0200: LXI D, L_DATA PUSH D ; сохраняем в стеке ссылку L_MAIN: POP D ; считываем ссылку LDAX D ; загружаем A по ссылке ORA A JZ L_DONE ; переход, если там ноль ---->>>> INX D ; DE=DE+1 PUSH D ; сохраняем в стеке новую ссылку DI ; запрещаем прерывания OUT 010h ; отправляем в порт LXI H, 0000h ; заполнение памяти DAD SP ; SP+0 в HL SHLD L_SAVE ; сохранить указатель на стек LXI D, 0FFFFh ; чем заполнять LXI H, 8000h ; сколько/2 LXI SP,0000h ; свой указатель на стек L_LOOP: PUSH D ; заполняем через стек... DCX H MOV A, L ORA H JNZ L_LOOP ; зациклено XRA A ; обнуляем аккумулятор OUT 010h ; отправляем в порт -- отключаем КД LHLD L_SAVE ; считать сохранённый указатель на стек в HL SPHL ; восстанавливаем SP EI ; разрешаем прерывания JMP L_MAIN ; L_DONE: MVI A, 023h ; 00100011b -- вкл. 3 банк как ОЗУ A000h-DFFFh OUT 010h ; отправляем в порт LXI H, 02000h ; считываем -- сколько LXI B, 01000h ; куда LXI D, 0C000h ; откуда CALL L_MOVE XRA A ; обнуляем аккумулятор OUT 010h ; отправляем в порт -- отключаем КД LXI H, 02000h ; переброска считанного в экран -- сколько LXI B, 0C000h ; куда LXI D, 01000h ; откуда CALL L_MOVE ; наблюдаем и наслаждаемся... LXI D, L_TEXT MVI C, 009h CALL 5 ; вывод сообщения RET ; выход из программы ; L_MOVE: LDAX D ; пп переброски данных STAX B INX D INX B DCX H MOV A, L ORA H JNZ L_MOVE RET ; L_SAVE: .dw 0000h L_TEXT: .db 0Dh, 0Ah, "-- DONE --$" L_DATA: .db 1Ch ; 00011100b -- вкл. 3 банк как стек на КД .db 18h ; 00011000b -- вкл. 2 банк как стек на КД .db 14h ; 00010100b -- вкл. 1 банк как стек на КД .db 10h ; 00010000b -- вкл. 0 банк как стек на КД .db 00h ; конец .END[свернуть]
Эти тесты в откомпилированном виде: MyTestKD5-7.7z
Погонял тесты, поизучал тему "Временные диаграммы Вектора", а также даташиты на микросхемы, результаты таковы:
- чтение данных из КД в режиме "ОЗУ" работает без проблем.
- запись данных в КД в режиме "ОЗУ" имеет некоторые проблемы -- иногда в последней четверти записываемого блока размером 2000h не проходит запись по одному-трём случайным байтам, т.е. значение в записываемой ячейке не меняется.
- запись данных в КД в режиме "стек" ни разу ошибок не показала.
- чтение данных из КД в режиме "стек" -- это практически 100% ошибок. Причина там в том, что сигнал "СТЕК" и, соответственно, вырабатываемый по его наличию сигнал "БЛК", приходит слишком поздно, в тот момент, когда на ШАП уже сформирована вторая половина адреса, в результате чего чтение происходит с неправильного адреса памяти КД.
Полагаю, что нужно два исправления:
1. Отключаем блокировку сигнала RAS: у микросхемы Д2 отрезаем от линии BLK_INT (по схеме) вывод 5 и соединяем с выводом 6. Теперь микросхема Д3 будет сохранять все адреса, даже во время регенерации памяти, но, думаю, это будет для неё нормальная нагрузка. Заодно такую же операцию делаем и с выводом 8 той же микросхемы Д2, отключив его от BLK_INT и соединив с выводом 9 -- сигнал CAS так тоже не будет блокироваться.
2. Поднять напряжение +5В (сейчас, если верить моему мультиметру, БП Вектора выдаёт 4,7-4,8В), возможно так память будет лучше работать и пропадут случайные ошибки записи в режиме "ОЗУ".
Последний раз редактировалось Improver; 26.11.2018 в 09:36. Причина: Поправил выводы, добавил тесты
Отключение BLK_INT от Д2 дало определённо положительный эффект: теперь тест "Дождь" даже при продолжительном тестировании не показывает ошибок, "Тест квазидиска" тоже, но "жёлтый" тест КД бракует все микросхемы, да и ещё стандартный "Тест устройств" случайным образом бракует чипы. Также MDOS 2.0 грузится и по "8" не показывает ошибок... но глючит на записи в КД.
Значит, исправляем схему в соответствии с последней доработкой:
Новая схема и разводка в архиве (гербер не делал): kd_sram11_1.7z
И продолжаем тестировать:
TestKDst
Очистка всего КД и заполнение значением 0AA55h в режиме "стек" с последующим контролем и подсчётом ошибокКод:.ORG 00100h L_0100: LXI D, L_DATA PUSH D ; сохраняем в стеке ссылку L_MAIN: POP D ; считываем ссылку LDAX D ; загружаем A по ссылке ORA A JZ L_DONE ; переход, если там ноль ---->>>> INX D ; DE=DE+1 PUSH D ; сохраняем в стеке новую ссылку DI ; запрещаем прерывания OUT 010h ; отправляем в порт LXI H, 0000h ; заполнение памяти DAD SP ; SP+0 в HL SHLD L_SAVE ; сохранить указатель на стек LXI D, 0FFFFh ; чем заполнять -- предварительная очистка памяти LXI H, 8000h ; сколько/2 LXI SP,0000h ; свой указатель на стек L_LP0: PUSH D ; заполняем через стек... DCX H MOV A, L ORA H JNZ L_LP0 ; зациклено LXI D, 0AA55h ; чем заполнять LXI H, 8000h ; сколько/2 LXI SP,0000h ; свой указатель на стек L_LP1: PUSH D ; заполняем через стек... DCX H MOV A, L ORA H JNZ L_LP1 ; зациклено LXI H, 8000h ; сколько/2 L_LP2: POP B ; вычитываем и проверяем записанное MOV A, B CMP D ; если старший байт прочитанного не равен записанному JNZ L_ERROR ; обработка ошибки MOV A, C CMP E ; если младший байт прочитанного не равен записанному JNZ L_ERROR ; обработка ошибки L_RET: DCX H MOV A, L ORA H JNZ L_LP2 ; зациклено XRA A ; обнуляем аккумулятор OUT 010h ; отправляем в порт -- отключаем КД LHLD L_SAVE ; считать сохранённый указатель на стек в HL SPHL ; восстанавливаем SP EI ; разрешаем прерывания LXI D, L_TEXT2 ; вывод количества найденных ошибок MVI C, 009h CALL 5 ; вывод сообщения LHLD L_ERRS ; считываем количество CALL L_BHEX ; выводим H в шестнадцатиричном виде MOV H, L CALL L_BHEX ; выводим L в шестнадцатиричном виде LXI H, 00000h SHLD L_ERRS ; обнуляем счётчик ошибок JMP L_MAIN ; L_ERROR:SHLD L_SAVE2 ; сохранить счётчик LHLD L_ERRS ; считываем количество ошибок INX H SHLD L_ERRS ; количество ошибок +1 LHLD L_SAVE2 ; восстановить счётчик JMP L_RET ; возврат в цикл ; L_DONE: LXI D, L_TEXT MVI C, 009h CALL 5 ; вывод сообщения RET ; выход из программы ; L_BHEX: MOV A, H ; H-входное значение для вывода RRC RRC RRC RRC ; сдвиг вправо на 4 бита CALL L_BIT ; выводим старшие 4 бита MOV A, H ; восстанавливаем значение L_BIT: ANI 00Fh ; оставляем младшие 4 бита CPI 00Ah JM L_B10 ; если меньше 10 ADI 007h ; +7 L_B10: ADI 030h ; +30h MVI D, 000h MOV E, A MVI C, 002h ; вывод символа PUSH H ; сохраняем HL CALL 5 POP H ; восстанавливаем HL RET ; L_SAVE: .dw 0000h L_SAVE2:.dw 0000h L_TEXT: .db 0Dh, 0Ah, "-- konec testa --$" L_TEXT2:.db 0Dh, 0Ah, "o{ibok = $" L_DATA: .db 1Ch ; 00011100b -- вкл. 3 банк как стек на КД .db 18h ; 00011000b -- вкл. 2 банк как стек на КД .db 14h ; 00010100b -- вкл. 1 банк как стек на КД .db 10h ; 00010000b -- вкл. 0 банк как стек на КД .db 00h ; конец L_ERRS: .dw 0000h ; количество ошибок .END[свернуть]TestKDoz
Тест КД в режиме "ОЗУ" с предварительной полной очисткой, в т.ч. областей по доработке Баркаря, с подсчётом ошибок записи.Код:.ORG 00100h L_0100: LXI D, L_DATA ; для начала очистка КД PUSH D ; сохраняем в стеке ссылку L_CLEAR:POP D ; считываем ссылку LDAX D ; загружаем A по ссылке ORA A INX D ; DE=DE+1 PUSH D ; сохраняем в стеке новую ссылку JZ L_NEXT ; переход, если там ноль ---->>>> DI ; запрещаем прерывания OUT 010h ; отправляем в порт LXI H, 0000h DAD SP ; SP+0 в HL SHLD L_SAVE ; сохранить указатель на стек LXI D, 0FFFFh ; чем заполнять -- предварительная очистка памяти LXI H, 8000h ; сколько/2 LXI SP,0000h ; свой указатель на стек L_LP0: PUSH D ; заполняем КД через стек... DCX H MOV A, L ORA H JNZ L_LP0 ; зациклено XRA A ; обнуляем аккумулятор OUT 010h ; отправляем в порт -- отключаем КД LHLD L_SAVE ; считать сохранённый указатель на стек в HL SPHL ; восстанавливаем SP EI ; разрешаем прерывания JMP L_CLEAR ; цикл очистки ; L_NEXT: LXI D, L_TEXT1 MVI C, 009h CALL 5 ; вывод сообщения об окончании очистки КД L_CHK: POP D ; считываем ссылку LDAX D ; загружаем A по ссылке ORA A JZ L_DONE ; переход, если там ноль ---->>>> INX D ; DE=DE+1 PUSH D ; сохраняем в стеке новую ссылку DI ; запрещаем прерывания OUT 010h ; отправляем в порт LXI H, 08000h ; заполнение памяти -- сколько LXI B, 08000h ; с какого адреса L_LP1: MVI A, 055h ; чем заполнять STAX B ; пишем LDAX B ; читаем в A CPI 055h ; сравниваем JZ L_GOOD ; значения равны PUSH H ; сохранить счётчик LHLD L_ERRS ; считываем количество ошибок INX H SHLD L_ERRS ; количество ошибок +1 POP H ; восстановить счётчик L_GOOD: INX B DCX H MOV A, L ORA H JNZ L_LP1 ; пока HL не обнулится XRA A ; обнуляем аккумулятор OUT 010h ; отправляем в порт -- отключаем КД EI ; разрешаем прерывания LXI D, L_TEXT2 ; вывод количества найденных ошибок MVI C, 009h CALL 5 ; вывод сообщения LHLD L_ERRS ; считываем количество CALL L_BHEX ; выводим H в шестнадцатиричном виде MOV H, L CALL L_BHEX ; выводим L в шестнадцатиричном виде LXI H, 00000h SHLD L_ERRS ; обнуляем счётчик ошибок JMP L_CHK ; цикл проверки ; L_DONE: LXI D, L_TEXT MVI C, 009h CALL 5 ; вывод сообщения об окончании проверки КД RET ; выход из программы ; L_BHEX: MOV A, H ; H-входное значение для вывода RRC RRC RRC RRC ; сдвиг вправо на 4 бита CALL L_BIT ; выводим старшие 4 бита MOV A, H ; восстанавливаем значение L_BIT: ANI 00Fh ; оставляем младшие 4 бита CPI 00Ah JM L_B10 ; если меньше 10 ADI 007h ; +7 L_B10: ADI 030h ; +30h MVI D, 000h MOV E, A MVI C, 002h ; вывод символа PUSH H ; сохраняем HL CALL 5 POP H ; восстанавливаем HL RET ; L_SAVE: .dw 0000h L_TEXT: .db 0Dh, 0Ah, "-- konec testa --$" L_TEXT1:.db 0Dh, 0Ah, "-- o~istka kd wypolnena --$" L_TEXT2:.db 0Dh, 0Ah, "o{ibok = $" L_DATA: .db 01Ch ; 00011100b -- вкл. 3 банк как стек на КД .db 018h ; 00011000b -- вкл. 2 банк как стек на КД .db 014h ; 00010100b -- вкл. 1 банк как стек на КД .db 010h ; 00010000b -- вкл. 0 банк как стек на КД .db 000h ; на второй этап .db 0E3h ; 11100011b -- вкл. 3 банк как ОЗУ 8000h-FFFFh .db 0E2h ; 11100010b -- вкл. 2 банк как ОЗУ 8000h-FFFFh .db 0E1h ; 11100001b -- вкл. 1 банк как ОЗУ 8000h-FFFFh .db 0E0h ; 11100000b -- вкл. 0 банк как ОЗУ 8000h-FFFFh .db 000h ; конец L_ERRS: .dw 0000h ; количество ошибок .END[свернуть]Архив с откомпилированными тестами: MyTestKD_new.7zTestKDo2
Аналогичен предыдущему тесту, только тут тестирование выполняются в два этапа -- сначала цикл записи, а потом цикл проверки. В конце также показывается количество ошибок.Код:.ORG 00100h L_0100: LXI D, L_DATA ; для начала очистка КД PUSH D ; сохраняем в стеке ссылку L_CLEAR:POP D ; считываем ссылку LDAX D ; загружаем A по ссылке ORA A INX D ; DE=DE+1 PUSH D ; сохраняем в стеке новую ссылку JZ L_NEXT ; переход, если там ноль ---->>>> DI ; запрещаем прерывания OUT 010h ; отправляем в порт LXI H, 0000h DAD SP ; SP+0 в HL SHLD L_SAVE ; сохранить указатель на стек LXI D, 0FFFFh ; чем заполнять -- предварительная очистка памяти LXI H, 8000h ; сколько/2 LXI SP,0000h ; свой указатель на стек L_LP0: PUSH D ; заполняем КД через стек... DCX H MOV A, L ORA H JNZ L_LP0 ; зациклено XRA A ; обнуляем аккумулятор OUT 010h ; отправляем в порт -- отключаем КД LHLD L_SAVE ; считать сохранённый указатель на стек в HL SPHL ; восстанавливаем SP EI ; разрешаем прерывания JMP L_CLEAR ; цикл очистки ; L_NEXT: LXI D, L_TEXT1 MVI C, 009h CALL 5 ; вывод сообщения об окончании очистки КД L_CHK: POP D ; считываем ссылку LDAX D ; загружаем A по ссылке ORA A JZ L_DONE ; переход, если там ноль ---->>>> INX D ; DE=DE+1 PUSH D ; сохраняем в стеке новую ссылку DI ; запрещаем прерывания OUT 010h ; отправляем в порт LXI H, 08000h ; заполнение памяти -- сколько LXI B, 08000h ; с какого адреса L_LP1: MVI A, 055h ; чем заполнять STAX B ; пишем INX B DCX H MOV A, L ORA H JNZ L_LP1 ; пока HL не обнулится LXI H, 08000h ; считываем -- сколько LXI B, 08000h ; с какого адреса L_LP2: LDAX B ; читаем в A CPI 055h ; сравниваем JZ L_GOOD ; значения равны PUSH H ; сохранить счётчик LHLD L_ERRS ; считываем количество ошибок INX H SHLD L_ERRS ; количество ошибок +1 POP H ; восстановить счётчик L_GOOD: INX B DCX H MOV A, L ORA H JNZ L_LP2 ; пока HL не обнулится XRA A ; обнуляем аккумулятор OUT 010h ; отправляем в порт -- отключаем КД EI ; разрешаем прерывания LXI D, L_TEXT2 ; вывод количества найденных ошибок MVI C, 009h CALL 5 ; вывод сообщения LHLD L_ERRS ; считываем количество CALL L_BHEX ; выводим H в шестнадцатиричном виде MOV H, L CALL L_BHEX ; выводим L в шестнадцатиричном виде LXI H, 00000h SHLD L_ERRS ; обнуляем счётчик ошибок JMP L_CHK ; цикл проверки ; L_DONE: LXI D, L_TEXT MVI C, 009h CALL 5 ; вывод сообщения об окончании проверки КД RET ; выход из программы ; L_BHEX: MOV A, H ; H-входное значение для вывода RRC RRC RRC RRC ; сдвиг вправо на 4 бита CALL L_BIT ; выводим старшие 4 бита MOV A, H ; восстанавливаем значение L_BIT: ANI 00Fh ; оставляем младшие 4 бита CPI 00Ah JM L_B10 ; если меньше 10 ADI 007h ; +7 L_B10: ADI 030h ; +30h MVI D, 000h MOV E, A MVI C, 002h ; вывод символа PUSH H ; сохраняем HL CALL 5 POP H ; восстанавливаем HL RET ; L_SAVE: .dw 0000h L_TEXT: .db 0Dh, 0Ah, "-- konec testa --$" L_TEXT1:.db 0Dh, 0Ah, "-- o~istka kd wypolnena --$" L_TEXT2:.db 0Dh, 0Ah, "o{ibok = $" L_DATA: .db 01Ch ; 00011100b -- вкл. 3 банк как стек на КД .db 018h ; 00011000b -- вкл. 2 банк как стек на КД .db 014h ; 00010100b -- вкл. 1 банк как стек на КД .db 010h ; 00010000b -- вкл. 0 банк как стек на КД .db 000h ; на второй этап .db 0E3h ; 11100011b -- вкл. 3 банк как ОЗУ 8000h-FFFFh .db 0E2h ; 11100010b -- вкл. 2 банк как ОЗУ 8000h-FFFFh .db 0E1h ; 11100001b -- вкл. 1 банк как ОЗУ 8000h-FFFFh .db 0E0h ; 11100000b -- вкл. 0 банк как ОЗУ 8000h-FFFFh .db 000h ; конец L_ERRS: .dw 0000h ; количество ошибок .END[свернуть]
Что получается:
1. Тест в режиме "стек" ни разу не показал ни одной ошибки.
2. Тест в режиме "ОЗУ" в один этап показывает от 0 до 10 случайных ошибок, в два этапа до 30. Это плохо... Есть подозрение на большие задержки в Д5 и Д6, но, с другой стороны, данные на ШАВВ должны появляться раньше, чем на ШАП будет сформирован полный адрес. Надо ещё подумать...
И ещё остаётся питание. Проблемы в нём точно есть, но пока у меня не готов БП на замену.
Ну что ж... Могу констатировать, что квази-диск работает!
В кратце: написал очередной супер-мега-тест, и он показал, что при ошибках записи данных в режиме ОЗУ запись происходит по неверному адресу, сбой происходит на 12 и 11 бите адреса, причём во всех случаях вместо "1" там попадает "0". Заменил микросхему Д4 с 74HC244 на 74ABT240 -- по выводам они полностью совпадают, только 240-я с инверсией выходов и быстрее (20нс против 5,5нс), ну и как результат -- теперь все тесты проходят на 100% без ошибок, МДОСы работают и не глючат, файлы на КД сохраняются... Правда, я не уверен точно, инверсия адреса на это повлияла, или скорость, но КД заработал, факт.
И да, чем тестировал и нашёл причину сбоев:Тест КД в режиме ОЗУ с анализом ошибок записи
Алгоритм теста такой:
1. Очищаем весь КД в режиме "стек" (заполняем 0FFh).
2. Пишем байт в режиме ОЗУ в доступной области.
3. Считываем и проверяем -- если совпало с записанным, то стираем и идём к следующему адресу и в п.2
4. Если не совпало и не равно 0FFh -- выводим ошибку, стираем и к следующему адресу и в п.2.
5. Если не совпало и равно 0FFh -- выводим ошибку.
6. Ищем по всему диску в режиме "стек" байт, не равный 0FFh и если находим, то выводим его адрес и значение, очищаем и снова в п.2.
Вот как-то так... А результаты можно интерпретировать так:
- если байты в момент сбоя не пишутся на КД вообще -- это проблема с сигналом WE (ЗПЗУ).
- если байты пишутся по неправильному адресу -- проблема с адресной шиной, микросхемами Д3 или Д4. По результатам теста можно сравнить адреса и определить сбойные биты.
- ну третий вариант -- пишется неправильный байт (такого не было). Тогда надо проверять шину данных или циклы записи...
Откомпилированный тест в архиве: MyTestKDer.7z
Исходники теста на ассемблере:Код:.ORG 00100h L_0100: LXI D, L_DTST ; для начала очистка КД PUSH D ; сохраняем в стеке ссылку L_CLEAR:POP D ; считываем ссылку LDAX D ; загружаем A по ссылке ORA A JZ L_NEXT ; переход, если там ноль ---->>>> INX D ; DE=DE+1 PUSH D ; сохраняем в стеке новую ссылку DI ; запрещаем прерывания OUT 010h ; отправляем в порт LXI H, 0000h DAD SP ; SP+0 в HL SHLD L_SAVE ; сохранить указатель на стек LXI D, 0FFFFh ; чем заполнять -- предварительная очистка памяти LXI H, 8000h ; сколько/2 LXI SP,0000h ; свой указатель на стек L_LP0: PUSH D ; заполняем КД через стек... DCX H MOV A, L ORA H JNZ L_LP0 ; зациклено XRA A ; обнуляем аккумулятор OUT 010h ; отправляем в порт -- отключаем КД LHLD L_SAVE ; считать сохранённый указатель на стек в HL SPHL ; восстанавливаем SP EI ; разрешаем прерывания JMP L_CLEAR ; цикл очистки ; L_NEXT: LXI D, L_TEXT1 MVI C, 009h CALL 5 ; вывод сообщения об окончании очистки КД LXI D, L_DTOZU ; ссылка на кофигурацию КД "ОЗУ" PUSH D ; сохраняем в стеке ссылку L_CHK: POP D ; считываем ссылку LDAX D ; загружаем A по ссылке ORA A JZ L_DONE ; переход, если там ноль ---->>>> INX D ; DE=DE+1 PUSH D ; сохраняем в стеке новую ссылку DI ; запрещаем прерывания OUT 010h ; отправляем в порт LXI H, 08000h ; заполнение памяти -- сколько LXI B, 08000h ; с какого адреса L_LP1: MVI A, 055h ; чем заполнять STAX B ; пишем MOV A, M ; читаем в A из другой ячейки (для смены адреса) LDAX B ; читаем записанное ранее в A CPI 055h ; сравниваем JZ L_GOOD ; значения равны -- двигаемся дальше... MOV D, A ; сохраняем считанное значение в D MVI A, 0FFh ; очищаем найденную ячейку STAX B ; пишем STAX B ; пишем второй раз, для надёжности XRA A ; обнуляем аккумулятор OUT 010h ; отправляем в порт -- отключаем КД EI ; разрешаем прерывания PUSH H ; сохранить счётчики PUSH B PUSH D ; сохраняем D LXI D, L_TEXT2 ; сообщение об ошибке по адресу MVI C, 009h CALL 5 ; вывод сообщения POP D POP H ; восстанавливаем адрес PUSH H PUSH D ; сохраняем D CALL L_BHEX ; выводим старший байт адреса в шестнадцатиричном виде MOV H, L CALL L_BHEX ; выводим младший байт адреса в шестнадцатиричном виде LXI D, L_TEXT3 ; сообщение о считанном байте MVI C, 009h CALL 5 ; вывод сообщения POP H ; восстанавливаем плохой байт CALL L_BHEX ; выводим считанный байт в шестнадцатиричном виде MOV A, H CPI 0FFh ; сравниваем c 0FFh CZ L_FDATA ; если так, то запускаем поиск по всему КД POP B ; восстановить счётчики POP H POP D ; считываем адрес на конфигурацию КД PUSH D ; и сохраняем DCX D LDAX D ; загружаем A по ссылке DI ; запрещаем прерывания OUT 010h ; отправляем в порт -- снова включаем КД L_GOOD: MVI A, 0FFh ; очищаем ячейку STAX B ; пишем STAX B ; пишем второй раз, для надёжности INX B DCX H MOV A, L ORA H JNZ L_LP1 ; пока HL не обнулится XRA A ; обнуляем аккумулятор OUT 010h ; отправляем в порт -- отключаем КД EI ; разрешаем прерывания LXI D, L_TEXT4 ; сообщение о переходе к другому банку КД MVI C, 009h CALL 5 ; вывод сообщения JMP L_CHK ; цикл проверки ; L_DONE: LXI D, L_TEXT MVI C, 009h CALL 5 ; вывод сообщения об окончании проверки КД RET ; выход из программы ; L_BHEX: MOV A, H ; H-входное значение для вывода RRC RRC RRC RRC ; сдвиг вправо на 4 бита CALL L_BIT ; выводим старшие 4 бита MOV A, H ; восстанавливаем значение L_BIT: ANI 00Fh ; оставляем младшие 4 бита CPI 00Ah JM L_B10 ; если меньше 10 ADI 007h ; +7 L_B10: ADI 030h ; +30h MVI D, 000h MOV E, A MVI C, 002h ; вывод символа PUSH H ; сохраняем HL CALL 5 POP H ; восстанавливаем HL RET ; ; ПП поиска по всему КД L_FDATA:LXI D, L_TEXT5 ; сообщение о начале поиска на КД MVI C, 009h CALL 5 ; вывод сообщения LXI D, L_DTST ; конфигурация КД PUSH D ; сохраняем в стеке ссылку L_FNC: POP D ; считываем ссылку LDAX D ; загружаем A по ссылке ORA A JNZ L_FNXT ; если не ноль LXI D, L_TEXT6 ; сообщение о том, что ничего не нашли MVI C, 009h CALL 5 ; вывод сообщения RET ; выход из ПП ---->>>> L_FNXT: INX D ; DE=DE+1 PUSH D ; сохраняем в стеке новую ссылку DI ; запрещаем прерывания OUT 010h ; отправляем в порт LXI H, 0000h DAD SP ; SP+0 в HL SHLD L_SAVE ; сохранить указатель на стек LXI H, 00000h ; нач.адрес LXI SP,00000h ; свой указатель на стек L_LPF: POP D ; считываем из стека два байта MOV A, E CPI 0FFh ; если младший байт прочитанного не равен 0FFh JNZ L_FERR ; выход из цикла с сообщением INX H ; адрес +1 MOV A, D CPI 0FFh ; если старший байт прочитанного не равен 0FFh JNZ L_FERR ; выход из цикла с сообщением INX H ; адрес +1 MOV A, L ORA H JNZ L_LPF ; зациклено, пока адрес не обнулится XRA A ; обнуляем аккумулятор OUT 010h ; отправляем в порт -- отключаем КД LHLD L_SAVE ; считать сохранённый указатель на стек в HL SPHL ; восстанавливаем SP EI ; разрешаем прерывания LXI D, L_TEXT4 ; сообщение о переходе к другому банку КД MVI C, 009h CALL 5 ; вывод сообщения JMP L_FNC ; цикл поиска ; L_FERR: STA L_EBYT ; сохраняем найденный байт SHLD L_EADR ; сохраняем адрес LXI D, 0FFFFh ; очищаем ячейку PUSH D XRA A ; обнуляем аккумулятор OUT 010h ; отправляем в порт -- отключаем КД LHLD L_SAVE ; считать сохранённый указатель на стек в HL SPHL ; восстанавливаем SP EI ; разрешаем прерывания POP D ; считываем ссылку (для удаления её из стека) LXI D, L_TEXT2 ; сообщение об ошибке по адресу MVI C, 009h CALL 5 ; вывод сообщения LHLD L_EADR ; читаем найденный адрес CALL L_BHEX ; выводим старший байт адреса в шестнадцатиричном виде MOV H, L CALL L_BHEX ; выводим младший байт адреса в шестнадцатиричном виде LXI D, L_TEXT3 ; сообщение о считанном байте MVI C, 009h CALL 5 ; вывод сообщения LDA L_EBYT ; читаем найденный байт MOV H, A CALL L_BHEX ; выводим считанный байт в шестнадцатиричном виде RET ; завершаем поиск ; L_SAVE: .dw 0000h L_TEXT: .db 0Dh, 0Ah, "-- konec testa --$" L_TEXT1:.db 0Dh, 0Ah, "-- o~istka kd wypolnena --$" L_TEXT2:.db 0Dh, 0Ah, "o{ibka po adresu $" L_TEXT3:.db ", s~itan bajt: $" L_TEXT4:.db 0Dh, 0Ah, "perehod k sledu`}emu" .db " banku kd $" L_TEXT5:.db 0Dh, 0Ah, "i}em bajt na kd...$" L_TEXT6:.db 0Dh, 0Ah, "ni~ego ne na{li. :-)" .db " prodolvaem test.$" L_DTST: .db 01Ch ; 00011100b -- вкл. 3 банк как стек на КД .db 018h ; 00011000b -- вкл. 2 банк как стек на КД .db 014h ; 00010100b -- вкл. 1 банк как стек на КД .db 010h ; 00010000b -- вкл. 0 банк как стек на КД .db 000h ; конец L_DTOZU:.db 0E3h ; 11100011b -- вкл. 3 банк как ОЗУ 8000h-FFFFh .db 0E2h ; 11100010b -- вкл. 2 банк как ОЗУ 8000h-FFFFh .db 0E1h ; 11100001b -- вкл. 1 банк как ОЗУ 8000h-FFFFh .db 0E0h ; 11100000b -- вкл. 0 банк как ОЗУ 8000h-FFFFh .db 000h ; конец L_EADR: .dw 0000h L_EBYT: .db 00h .END[свернуть]
Окончательный вариант схемы КД сделаю и выложу тут чуть позже... Хотя, он мало отличается от предыдущего.
Поздравляю! Следующим этапом дисковод? Или дисковод уже есть?
Больше игр нет
Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)