А почему бы D1+D2+D12 и D5+D6+D8 не заменить на РТ4?
Вид для печати
Наверно, по той же причине, почему бы не заменить всю конструкцию на ПЛИС и не получить при этом "Комбодевайс2"... :) А если серьёзно -- если что-то можно решить на обычной логике достаточно малым числом корпусов МС, то я не вижу особой необходимости делать это на ПЗУ. Так же, собственно, было сделано и в последующей конструкции КД (на РУ7)...
- - - Добавлено - - -
И ещё, могу уже похвалиться собранной конструкцией по последней схеме:
Вложение 66690
Только вот микросхем памяти пока что ещё нет, т.к. они в доставке с ибея... Но всё остальное, что возможно, протестил -- работает так, как и было задумано. :)
Может, кому пригодится, вот мои тесты для контроллера КД:
Тест 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
[свернуть]
А дальше, я думаю, надо ставить память и тестировать стандартными программами, типа "дождь" и т.д.
Все тесты откомпилированные для монитора-отладчика в одном архиве: Вложение 66691
Запускать можно под любым монитором-отладчиком, режим распределения памяти МО рекомендую выбирать <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
[свернуть]
Эти тесты в откомпилированном виде: Вложение 67032
Погонял тесты, поизучал тему "Временные диаграммы Вектора", а также даташиты на микросхемы, результаты таковы:
- чтение данных из КД в режиме "ОЗУ" работает без проблем.
- запись данных в КД в режиме "ОЗУ" имеет некоторые проблемы -- иногда в последней четверти записываемого блока размером 2000h не проходит запись по одному-трём случайным байтам, т.е. значение в записываемой ячейке не меняется.
- запись данных в КД в режиме "стек" ни разу ошибок не показала.
- чтение данных из КД в режиме "стек" -- это практически 100% ошибок. Причина там в том, что сигнал "СТЕК" и, соответственно, вырабатываемый по его наличию сигнал "БЛК", приходит слишком поздно, в тот момент, когда на ШАП уже сформирована вторая половина адреса, в результате чего чтение происходит с неправильного адреса памяти КД.
Полагаю, что нужно два исправления:
1. Отключаем блокировку сигнала RAS: у микросхемы Д2 отрезаем от линии BLK_INT (по схеме) вывод 5 и соединяем с выводом 6. Теперь микросхема Д3 будет сохранять все адреса, даже во время регенерации памяти, но, думаю, это будет для неё нормальная нагрузка. Заодно такую же операцию делаем и с выводом 8 той же микросхемы Д2, отключив его от BLK_INT и соединив с выводом 9 -- сигнал CAS так тоже не будет блокироваться.
2. Поднять напряжение +5В (сейчас, если верить моему мультиметру, БП Вектора выдаёт 4,7-4,8В), возможно так память будет лучше работать и пропадут случайные ошибки записи в режиме "ОЗУ".
Отключение BLK_INT от Д2 дало определённо положительный эффект: теперь тест "Дождь" даже при продолжительном тестировании не показывает ошибок, "Тест квазидиска" тоже, но "жёлтый" тест КД бракует все микросхемы, да и ещё стандартный "Тест устройств" случайным образом бракует чипы. Также MDOS 2.0 грузится и по "8" не показывает ошибок... но глючит на записи в КД.
Значит, исправляем схему в соответствии с последней доработкой:
https://s8.hostingkartinok.com/uploa...382c1229eb.png
Новая схема и разводка в архиве (гербер не делал): Вложение 67069
И продолжаем тестировать:
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
[свернуть]Архив с откомпилированными тестами: Вложение 67070TestKDo2
Аналогичен предыдущему тесту, только тут тестирование выполняются в два этапа -- сначала цикл записи, а потом цикл проверки. В конце также показывается количество ошибок.Код:.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, но, с другой стороны, данные на ШАВВ должны появляться раньше, чем на ШАП будет сформирован полный адрес. Надо ещё подумать...
И ещё остаётся питание. Проблемы в нём точно есть, но пока у меня не готов БП на замену.
Ну что ж... Могу констатировать, что квази-диск работает! :v2_dizzy_punk:
В кратце: написал очередной супер-мега-тест, и он показал, что при ошибках записи данных в режиме ОЗУ запись происходит по неверному адресу, сбой происходит на 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. По результатам теста можно сравнить адреса и определить сбойные биты.
- ну третий вариант -- пишется неправильный байт (такого не было). Тогда надо проверять шину данных или циклы записи...
Откомпилированный тест в архиве: Вложение 67172
Исходники теста на ассемблере:Код:.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
[свернуть]
Окончательный вариант схемы КД сделаю и выложу тут чуть позже... Хотя, он мало отличается от предыдущего.
Поздравляю! Следующим этапом дисковод? Или дисковод уже есть?
Спасибо. :)
Не, не хочу что-то возиться с дискетами... Думаю о подключении жесткого диска -- у меня как раз завалялся такой вот IDE на 64 мегабайта:
Transcend 64Mb IDE
ссылка на амазон[свернуть]
Где-то ещё его применить, из-за малого объёма, не получится, а для Вектора будет в самый раз.
Твердость диска это хорошо, но для Вектора есть некоторое количество программ, хотя наверное не очень большое, которые общаются с контроллером дисковода напрямую. В основном это демки, конечно.
У меня еще были тайные помыслы сделать простой адаптер SD-карт. Чтобы он был железно прост и потому легко повторим. Опять же, блаженные пуристы, не зная ничего про контроллер флеша в SD-карте, будут думать, что их дисковод не сложнее их компьютера (спойлер: все равно они будут заблуждаться). А со стороны Вектора написать для него драйвер для МикроДОС-а и, может быть, загрузчик. Но я даже не пробовал задуматься, что на самом деле потребуется для такого проекта.
Вот проверенная работающая схема КД:
Вложение 67187
Изменения по отношению к предыдущей версии:
- заменена микросхема Д4 на 74АВТ240
- вернул блокировку сигнала CAS -- на ошибки КД это никак не влияет, но пригодится при совместной работе с другими дисками.
Архив со схемой, разводкой платы и гербер-архивом платы, урезанной до 100х94мм: Вложение 67188
- - - Добавлено - - -
Меня это не сильно пугает. Понадобится дисковод -- сделаю потом... :) Кстати, появилась ещё пара идей, чем заняться в выходные: во-первых, подключить батарейку к памяти КД, чтобы не терять данные при выключении, разводка-то уже вся есть. Думаю, для начала попробовать простую CR2032. Во-вторых, попробовать подключить второй КД к первому. Можно сделать его так, чтобы работал только в режиме "стек" -- замены ОЗУ хватит и с одного диска. Естественно, надо будет что-то придумывать с ОС, или написать свою програмку-копировщик с одного КД на другой.
Тоже интересная идея. А начать её можно с драйвера FAT для Вектора, чтобы можно было отформатированные на PC дискетки читать, а потом уже переходить к SD... Это если не делать обращение к SD аппаратным, эмулирующим ту же дискету.Цитата:
У меня еще были тайные помыслы сделать простой адаптер SD-карт. Чтобы он был железно прост и потому легко повторим. Опять же, блаженные пуристы, не зная ничего про контроллер флеша в SD-карте, будут думать, что их дисковод не сложнее их компьютера (спойлер: все равно они будут заблуждаться). А со стороны Вектора написать для него драйвер для МикроДОС-а и, может быть, загрузчик. Но я даже не пробовал задуматься, что на самом деле потребуется для такого проекта.
Для тех, кто пока не заменил загрузчик на Векторе (как я) на более новый, сделал запуск системы с КД в виде отдельной программки:
Архив с откомпилированным и собранным загрузчиком: Вложение 67266Исходники на ASM
Собственно загрузчик, стартует с адреса 7E00h, указанного в первой строке:Программка-перемещалка для возможности запуска с адреса 0100hКод:.ORG 07E00h
L_7E00: LXI H, 0FF00h ; проверка наличия КД
SHLD 0DED5h
XRA A
STA 0DED2h
STA 0DED3h
INR A
STA 0DED4h
CALL L_0576
CALL Lx04E8 ; проверка наличия OS.COM
JZ L_7E00 ; возврат.
; переход на загрузку с КД
L_050C: LXI H, 00100h
SHLD 0DED5h
MOV B, H
LXI H, 0FF10h ; ссылка на первую запись в директории на КД +10h
L_051E: MVI C, 010h ; <<<---- цикл
L_0520: MOV A, M
ORA A
JZ 0100h ; --------->>>>>>>>> запуск системы
PUSH PSW
PUSH H
STA 0DED3h
MVI A, 001h
L_0553: STA 0DED4h
PUSH PSW
CALL L_0576
JZ L_0562
MVI A, 0FFh
STA 0DED2h
L_0562: POP PSW
LHLD 0DED5h
LXI D, 00080h
DAD D
SHLD 0DED5h
INR A
CPI 009h
JNZ L_0553
POP H
POP PSW
MOV A, B
ADI 004h
MOV B, A
LDA 0DED2h
ORA A
JNZ L_7E00 ; что-то не так.... сброс.
INX H
DCR C
JNZ L_0520
CALL L_04E9 ; проверка наличия OS.COM
JZ 0100h ; ------>>>>>>> запуск 2
LXI D, 0010h
DAD D
JMP L_051E
;
L_0576: PUSH B
PUSH D
LXI H, 00000h
DAD SP
SHLD 0DED0h
LDA 0DED4h
LXI D, 0FF80h
LXI H, 00400h
L_05B8: DAD D
DCR A
JNZ L_05B8
XCHG
LDA 0DED3h
CMA
CPI 0FCh
JNC L_05C9
SUI 010h
L_05C9: SUI 004h
MOV L, A
RLC
RLC
ANI 0FCh
MOV H, A
MOV A, L
MVI L, 000h
DAD D
RLC
RLC
RLC
RLC
ANI 00Ch
PUSH B
MOV C, A
MVI A, 010h
ORA C
POP B
DI
OUT 010h ; подключаем КД
SPHL
LHLD 0DED5h
XRA A
MVI C, 020h
L_058C: POP D ; грузим в цикле
ADD E
ADD D
MOV M, E
INX H
MOV M, D
INX H
;
POP D
ADD E
ADD D
MOV M, E
INX H
MOV M, D
INX H
;
DCR C
JNZ L_058C
MOV C, A
MVI A, 000h ; отключаем КД
OUT 010h
LHLD 0DED0h
SPHL
EI
MOV A, C
PUSH PSW
PUSH D
LXI H, 00000h
DAD SP
SHLD 0DED0h
LDA 0DED3h
MOV L, A
MVI H, 000h
DAD H
DAD H
DAD H
DAD H
MVI A, 0F0h
ADD H
MOV H, A
LDA 0DED4h
DCR A
ADD A
ADD L
MOV L, A
MVI A, 01Ch ; подключаем КД
DI
OUT 010h
SPHL
POP D
MVI A, 000h ; отключаем КД
OUT 010h
LHLD 0DED0h
SPHL
EI
XCHG
POP D
POP PSW
CMP H
JNZ L_061D
SUB L
JZ L_061E
L_061D: MVI A, 0FFh
L_061E: POP D
POP B
RET
;
Lx04E8: MVI A, 000h
JNZ L_04FE
LXI H, 0FF00h
L_04E9: PUSH H
LXI D, L_0500 ; ссылка на строку "OS COM"
MVI C, 00Ch
L_04EF: LDAX D
CMP M
MVI A, 000h
JNZ L_04FD
INX D
INX H
DCR C
JNZ L_04EF
DCR A
L_04FD: POP H
L_04FE: ORA A
RET
;
L_0500:.db 000h ; <_>
.db 04Fh ; <O>
.db 053h ; <S>
.db 020h ; < >
.db 020h ; < >
.db 020h ; < >
.db 020h ; < >
.db 020h ; < >
.db 020h ; < >
.db 043h ; <C>
.db 04Fh ; <O>
.db 04Dh ; <M>
.END
Инструкция по сборке:Код:.ORG 00100h
L_0100: LXI H, 0038h ; адрес для ПП прерываний RST7
MVI A, 0C9h ; записываем туда код RET
LXI H, 013Ch ; сколько
LXI D, L_1000+3 ; откуда
LXI B, 07E00h ; куда
L_018C: LDAX D ; переброска данных
STAX B
INX D
INX B
DCX H
MOV A, L
ORA H
JNZ L_018C
L_1000: JMP 07E00h ; запускаем то, что перебрасывали
;
.END
1. Компилируем оба фрагмента
2. Копируем бинарники в один файл, сначала модуль перемещения, а потом загрузчик, например, так:
Код:copy /b MOVER.obj+BOOTKD.obj BOOTKD.rom
[свернуть]
После загрузки просто запускаем по БЛК-СБРОС и если на КД записана ОС, то она сразу стартует.
Сам код взял из загрузчика BOOT45, сильно не оптимизировал, почти всё оставил, как было, главное -- он работает. :)
Или вот вариант сокращенный до одного блока
Нашёл небольшой косяк в своей схеме КД: если попытаться присоединить два и более КД к Вектору, то они работать не будут. Причина в D12.D, выходы этой микросхемы нельзя объединять по схеме "монтажное И", для этого требуется микросхема с открытым коллектором на выходе. Можно, конечно, заменить 74HC86 (кр1564лп5) на 74ALS136 (кр1533лп12), подтянув к плюсу все четыре её выхода, но я решил пойти другим путём, а именно для сигнала БЛК использовать одиночный буфер SN74LVC1G07DBVR, а микросхему D12 оставить только для выбора адреса КД. Впаял этот буфер "на соплях" с предыдущий вариант схемы диска -- всё работает. Вот обновлённая схема:
Вложение 67881
Более качественный вариант картинки
И архив со схемой, разводкой платы и гербер-архивом для изготовления: Вложение 67882
Примечание: На втором и всех последующих подключаемых квази-дисках сопротивление R3 ставить не обязательно.
Небольшой отчёт по работе КД:
-- Подключил аккумулятор от старого МР3-плеера (ёмкостью всего 210мА/ч), с ним информация на КД сохраняется уже более трёх месяцев. Первоначально вольтаж аккумулятора был 4,07В, сейчас показывает ровно 4,00В, т.е. потребление минимально, на уровне саморазряда. С учётом того, что комбодевайсах используются аналогичные микросхемы памяти, там тоже можно сделать такое квази-постоянное хранение информации на квазидиске. :) Можно ещё добавить готовую платку для подзарядки аккумулятора при включении Вектора, хотя, думаю, с таким потреблением в выключенном режиме это становится не обязательным.
-- Собрал второй КД, на плате от 11-й версии с соответствующими исправлениями. Квазидиск заработал сразу и без ошибок, в том числе и в паре с первым. Единственная программа, которая умеет работать с несколькими дисками, это тест "Дождь", вот как это выглядит:
Дождь
Вложение 68780[свернуть]
Заметил, что при наличии нескольких квазидисков Дождь тестирует их не самым оптимальным образом, по очереди, хотя можно было бы, например, совместить запись сразу на все КД... Но это уже не принципиально, т.к. массовое производство и тестирование дисков нам не грозит.
Ну и напоследок, несколько фоток "бутерброда" из двух квазидисков:
Фотки КД
Вид со стороны Вектора:
Вложение 68781
Справа можно разглядеть платку с дополнительным буфером для линии "БЛК". Аккумулятор держится просто на двухстороннем скотче.
Вид со стороны микросхем:
Вложение 68782
И вид в торец "бутерброда":
Вложение 68783[свернуть]
А ему в режиме хранения 3V хватит?
Может проще "таблетку" впаять вместо аккумулятора?
Вполне. В даташите это напряжение и указано, как необходимое для хранения данных.
Пока ждал из Китая крепление для CR2032, припаял аккумулятор, да так и оставил. На втором КД попробую с таблеткой, отпишусь потом о результатах.Цитата:
Может проще "таблетку" впаять вместо аккумулятора?
Собрал КД работает!!! автору респект. Если кто будет заказывать платы в Китае обратите внимание на маску контактов микросхем, мешает паять.
Спасибо за отзыв. :)
А что не так с маской? У меня пайка проблем не вызвала, хотя заказывал платы также в Китае. Вот для примера фотка платы, только сейчас паял:Цитата:
Если кто будет заказывать платы в Китае обратите внимание на маску контактов микросхем, мешает паять.
Вложение 69465
У меня получилось, что маска закрывает половину контакта, косяк получился при конвертировании в Altium Designer, это мелочи главное работает.
Уже как минимум пара человек (Improver и KTSerg) являются обладателями двух (или более?) квазов. И есть лешадок, который гибкий и потенциально способен на очень многое. Может попробовать договориться и стандартизировать подключение нескольких квазов более рационально, чем к портам 10h, 11h и т.д. (как для теста "дождь")? Например оставить управление "текущим" квазом на 10h, а на 11h сделать выбор текущего кваза? ERAM, как я понимаю, никто собирать не планирует (тем более для оригинального еще и вектор надо переделывать), но хотелось бы иметь некий стандарт на расширенную память. И в эмуляторы добавить.
Дешифратор переделать на другой адрес просто, а сделать один глобальный регистр выбора кваза - получается нужен еще специальный квазорасширитель, который не совсем понятно куда засовывать в случае подключения к реалу.
Сорри за оффтоп.
Если бы без оглядки на реал, то я предложил бы какой-нибудь гибкий и удобный для программиста вариант организации многокваза.
А выбор кваза имхо сделать достаточно несложно, например пускать cas только к выбранному квазу. На мой малообразованный взгляд это буквально пара дополнительных корпусов, если на мелкой логике, причем их достаточно установить только на ближайшем к вектору квазе. Ну нет так нет.
А где уже встречался какой-то единый регистр переключения банков, это в ERAM ?
Подключение нескольких Квазов в любом случае требует схемной доработки, либо самих Квазов, либо коммутации ШАВВ. Организация дополнительного регистра переключения Квазов конечно схемно более сложный вариант, но при этом позволяет не лазить в сами Квазы.
Возможность программно переключать несколько Квазов не создаст проблемы МикроДосу?
Да, но там не самый удачный вариант, т.к. конфликт по номеру порта с часами.
Если ограничиваться только двумя квазами 10 и 11, то, конечно, заморачиваться регистром переключения нет смысла. Но если >2, то стоило бы подумать. Если смотреть на порты, использованные в дожде, то 4 из 8 конфликтуют с другими устройствами (2 с часами, 2 с кишиневским адаптером z80 и омским пзу-8, хотя для пзу-8 вроде была доработка).
- - - Добавлено - - -
Если при вызове функций доса или при выходе в дос будет включен "правильный" кваз, то проблем нет.
Опционально можно подумать о том, чтобы при записи 0 в 10h в порт выбора записывалась исходная комбинация. Но это потребует еще микросхем для реализации и при аккуратном программировании не нужно.
Вместо 11h можно использовать 20h и получить некую совместимость с ERAM.
Другой вариант: отказаться от доработки Баркаря и использовать 7 и 8 биты порта 10h для выбора КД, это даст возможность подключать до 4 дисков.
Ну и в дополнение, третий вариант: можно все порты оставить как есть в "Дожде", и просто написать некую программу, которая будет по необходимости менять в драйверах все "OUT 10h" на адрес нужного КД. :)
А почему бы и нет? Насколько я представляю, на основе моего КД или Лешадок это можно сделать даже без переделки Вектора.Цитата:
ERAM, как я понимаю, никто собирать не планирует (тем более для оригинального еще и вектор надо переделывать)
Да, это есть в ERAM, там по порту 20h можно задать дополнительные режимы замены памяти и выбрать используемые сегменты по 256кБ (которые в свою очередь бьются на страницы по 64кБ).
На мой взгляд в частичной совместимости с ERAM смысла нет. Программы для ERAM работать не будут + конфликт с часами.
Тут я против, т.к. использовал дополнительные возможности Баркаря. Или Бакарь или ERAM, но что-нибудь с возможностью полного перекрытия ВОЗУ нужно.
Было бы здорово.
ivagor, ок, попробую изобразить новую схему ERAM... Хотя это не решит проблему использования нескольких КД на Векторе, тут, наверно, придётся использовать программный метод подмены номера порта в драйверах.
С ERAMом единственная засада - программ нет. Для COMANовских досов нужен еще и свой КНГМД. А для ERAM с кишиневским КНГМД есть скорее всего только пара моих прог - проигрыватель почти wavов (могу доделать до совсем wavов, как сделал для обычного кваза) и bad apple c повышенным разрешением (доисторический HD :D ). С другой стороны для нескольких квазов тоже программ нет кроме дождя.
Был только СР/М с поддержкой ЕРАМ до 768 Кб, а так -- да, больше ничего нет. Ну ещё плюс ЕРАМ будет программно совместим с обычным КД (без доработки Баркаря).
В общем, кругом непаханное поле. С программной точки зрения, мне кажется, одинаково по сложности написать драйвера что для ЕРАМ, что для нескольких КД, так что можно развиваться в любую сторону.Цитата:
С другой стороны для нескольких квазов тоже программ нет кроме дождя.
в 1996 году В. Шашков разрабатывал пакет драйверов "Unidrive" для работы с расширенным электронным диском и другой периферией, но так и не сделал выпустил только бета версию.
VadaOm, спасибо!
Только для принтера.
Идея была хорошая. Чем начинать с нуля, можно его продолжить.
Я уже тут публиковал схему IDE-контроллера, и, как продолжение, не заводя новой темы, сообщаю, что собрал его. :)
Правда, есть небольшие изменения в схеме:
- Вместо КР1533ИР23 использовал КР1533ИР37. Они по функционалу и характеристикам полностью идентичны, но у ИР37 входы/выходы располагаются на разных сторонах корпуса, что существенно упрощает разводку платы.
- Немного "перетасовал" выходы микросхем, также для улучшения разводки.
- Убрал лишние сопротивления, добавил светодиод.
- На линии RESET поставил джампер и, как оказалось, не зря -- тут в форуме часто упоминалось, что эту линию иногда лучше разорвать, и мне также пришлось это сделать.
Вот итоговая схема:
https://s8.hostingkartinok.com/uploa...cca6d287f8.png
И архив с исходными файлами и гербером для изготовления платы (вторая версия): Вложение 69527
Подключил плату с диском к контроллеру КД вторым слоем:
Вложение 69528
В связи с тем, что схема контроллера IDE, фактически, не имеет отличий от стандарта, да и ПО используется всё то же, все глюки, озвученные тут в форуме присутствуют, тест HDD выдаёт некоторые ошибки, но система с диска грузится, диски подключаются, файлы запускаются:
Вложение 69529 Вложение 69530 Вложение 69531
P.S. На диск уже был заранее залит образ, так что форматирование и инициализацию на Векторе не делал.
Тебе пора в команду дизайнеров Raspberry Pi ;)
Кайфовая конструкция! Спасибо, что всё публикуешь.
Такое конструктивное исполнение вроде впервые для вектора и скорее всего это проще и практичнее, чем EPOS, респект.
svofski, ivagor, спасибо за одобрение. :)
Может быть, но используемые тут "штырьково-дырочные" разъёмы имеют свои минусы -- необходимость центрирования штырьков при сборке, достаточно большое усилие при разборке и т.д. А если не принимать в расчёт разъёмы, то EPOS ещё имеет буферы по управляющим каналам и ШАВВ, может быть имеет смысл сделать также, хотя используемые микросхемы серий КР1564 и КР1531 потребляют на входе в десятки раз меньшие токи, чем КР155 и КР555.
Мне кажется, что между таким конструктивом и EPOS есть разделение по сфере применения. Для "старых", классических устройств - EPOS. А для новых - проще такой вариант. При этом скорее всего будут использоваться новые (если сравнивать с 155) серии микросхем и ограничением на количество подключаемых плат может стать даже не нагрузочная способность, а механическая прочность. Сложно судить по фотографии, но создается впечатление, что платы 4 такого размера скорее всего можно подключить друг за другом.
Передаётся вся шина, на фото сверху один разъём на 12 контактов и снизу два таких же, плюс шестиконтактный разъём на питание. На этом фото, может, разъёмы будут виднее:
Вложение 69553
Хотя линии ШАП, как я понимаю, нигде, кроме КД не задействованы, через плату контроллера IDE передаются и они.