ПДП в РК для обновления динамического ОЗУ

Советский компьютер Радио-86РК (1986) и его клоны

Moderator: Shaos

begoon
Senior
Posts: 147
Joined: 22 Aug 2012 17:06
Location: 188.220.42.216

ПДП в РК для обновления динамического ОЗУ

Post by begoon »

Коллеги, проведите, пожалуйста, ликбез для человека, не очень глубоко разбирающегося схемотехнике.

Говорится, что в РК контроллер ПДП ИК57 (i8257) кроме задачи периодической пересылки видео области из ОЗУ в контроллер дисплея ВГ75, используется также для регенерации ОЗУ.

КАК ИМЕННО это происходит?

Я прочитал, что ОЗУ (скажем базовые 16КБ) "освежается" строками по 128 байт, то есть для обновления всех 16КБ нужно пробежать все значения от 00 до 7F по линиями A0-A6 и для каждого значения еще выставить RAS. Обновление каждой строки должно длиться не более 2мс.

Это мне понятно. Что мне НЕ понятно, как именно это "пробегание значений" организовано?

Монитор явно программирует ПДП только для работы с видео областью, по конкретным адресам. Ни какой речи о всей памяти тут не идет.

Видимо, обновление ОЗУ - это какой-то побочный эффект особого использования сигналов микросхемы ПДП, когда она пересылает видео область, так?
b2m
Devil
Posts: 907
Joined: 26 May 2003 06:57

Re: ПДП в РК для обновления динамического ОЗУ

Post by b2m »

Ну, ПДП вроде как считывает из ОЗУ, этого достаточно. Другое дело, как адресацию организовать: младшие биты адреса как раз и будут задаваться по RAS, то есть достаточно подряд 128 байт считать. Экран гораздо больше. Главное, чтобы за время обратного хода луча ничего не потерялось.

А вот когда идёт чтение с магнитофона, то ПДП отключается, и подпрограмма чтения в это время вынуждена читать из памяти командой POP PSW.
Страничка эмулятора наших компьютеров
http://bashkiria-2m.narod.ru/
User avatar
Paguo-86PK
Maniac
Posts: 267
Joined: 12 Apr 2011 20:43
Location: Tashkent

Re: ПДП в РК для обновления динамического ОЗУ

Post by Paguo-86PK »

Вoт если бы удалось в эмуляторе как-то реализовать разрушение данных в ОЗУ при неправильной регенерации - это было бы чудо!
Сталкивался с этим, когда пытался отключать/программировать ПДП при написании сэмплера.
begoon
Senior
Posts: 147
Joined: 22 Aug 2012 17:06
Location: 188.220.42.216

Re: ПДП в РК для обновления динамического ОЗУ

Post by begoon »

b2m wrote:А вот когда идёт чтение с магнитофона, то ПДП отключается, и подпрограмма чтения в это время вынуждена читать из памяти командой POP PSW.
А как этот трюк с POP PSW помогаем память регенерировать?

Вот кусок начала вывода байта. Судя по коду, в начале SP всегда начинается с адреса 0000 и потом начинает увеличиться. То есть проходятся адреса всегда начиная с нуля. А как же остальные ячейки?

Code: Select all

              	; --------------------------------------------------------------
              	; Out byte from c
              	;
FC46:         	entry_outb:
FC46: E5      	                push    h               ; CODE XREF: F80Cj FB4Dp FB58p FB6Ep FB87p FB91p FB95j
FC47: C5      	                push    b
FC48: D5      	                push    d
FC49: F5      	                push    psw
FC4A: 3E80    	                mvi     a, 80h ; '�'
FC4C: 3208E0  	                sta     0E008h
FC4F: 210000  	                lxi     h, 0
FC52: 39      	                dad     sp
FC53: 310000  	                lxi     sp, 0
FC56: 1608    	                mvi     d, 8
              	
FC58:         	loc_0_FC58:
FC58: F1      	                pop     psw             ; CODE XREF: FC82j
FC59: 79      	                mov     a, c
FC5A: 07      	                rlc
FC5B: 4F      	                mov     c, a
FC5C: 3E01    	                mvi     a, 1
FC5E: A9      	                xra     c
FC5F: 320280  	                sta     8002h
FC62: 3A3076  	                lda     7630h
FC65: 47      	                mov     b, a
User avatar
Paguo-86PK
Maniac
Posts: 267
Joined: 12 Apr 2011 20:43
Location: Tashkent

Re: ПДП в РК для обновления динамического ОЗУ

Post by Paguo-86PK »

Микросхемы ОЗУ РУ3 это матрицы 128×128. По RAS считывается вся строка в 128 бит и перезаписывается (внутри ОЗУ) обратно. А по CAS из этих считанных 128 бит выбирается один.

Конкретно в РАДИО-86РК буфер экрана 78×30 и размер символа 6×10 выбраны именно исходя из требований к надёжной регенерации.
То есть, конкретно 80 символов в строке нельзя было делать из-за привязки к периоду регенерации.
Тем самым, исходя из формул по вычислению периода установки флага IR можно примерно знать и конкретный цикл регенерации, реализованный в РК.

Моя утилита «ПСИХ» так и работает.
В ней код располагается порциями по 28 байтов. При отключении ПДП регенерация остальных 100 байтов не производится, а ВГ75 настраивается на отображение буфера в 28 байтов.
А те 100 байтов, которые не регенерировались установленный пользователем интервал, потом отображаются справа, на месте инструкции, текст которой должен постепенно рандомно забиться 0xFF.

Идея «ПСИХа» довольно давняя, но реализовать удалось лишь недавно: Сложные там трюки! :roll:

В эмуляторе разрушение данных в ОЗУ можно симулировать вставкой примерно подобного цикла:

 Самый простой способ

Code: Select all

this.read = function (addr) {
   ...
    // Момент последнего доступа к ОЗУ
    var now = Date.now();

    // Обновляем этот момент для конкретной RAS-строки
    this.ras_last_access[addr & 0x7f] = now;

    // Пробегаемся по всем RAS ОЗУ
    for (i = 0; i < 128; ++ i) {

        // Проверяем, не "состарились" ли данные конкретной строки с момента последней регенерации
        if (now - this.ras_last_access[i] > refresh_period) {

            // Если период регенерации затянулся, симулируем потерю данных по всем CAS-столбцам
            for(j = 0x0000; j < 0x8000; j += 128) {

                // В зависимости от качества конкретной ячейки ОЗУ играем в "рулетку"
                if(Math.random() > quality_factor)
                    this.buf[j + i] |= Math.floor(Math.random() * 16777216) >> 16;

                // Если прошёл критически длинный промежуток времени, вероятность потери данных повышается
                if(elapse > refresh_period * 2)
                    this.buf[j + i] |= Math.floor(Math.random() * 256);            }
        }
    }

    return this.buf[addr];
};

Только это довольно затратный способ, хотя и более-менее точный.
Можно оптимизировать до:

 Менее затратный способ

Code: Select all

this.read = function (addr) {
   ...
    // Момент последнего доступа к ОЗУ
    var now = Date.now();

    // Проверяем, не "состарились" ли данные конкретной строки с момента последней регенерации
    var elapse = now - this.ras_last_access[addr & 0x7f];

    if (elapse > refresh_period) {

        // Если период регенерации затянулся, симулируем потерю данных по всем CAS-столбцам
        for(j = 0x0000; j < 0x8000; j += 128) {

            // В зависимости от качества конкретной ячейки ОЗУ играем в "рулетку"
            if(Math.random() > quality_factor)
                data_killer = Math.floor(Math.random() * 16777216) >> 16;

            // Если прошёл критически длинный промежуток времени, вероятность потери данных повышается
            if(elapse > refresh_period * 2)
                data_killer |= Math.floor(Math.random() * 256);

            // Симулируем "разрушение" данных
            this.buf[j + (addr & 0x7f)] |= data_killer;
        }
    }

    // Обновляем этот момент для конкретной RAS-строки
    this.ras_last_access[addr & 0x7f] = now;

    return this.buf[addr];
};

Для повышения производительность можно и цикл развернуть:

 Оптимизированный по скорости вариант

Code: Select all

this.read = function (addr) {
   ...
    var cas = addr & 0x7f;

    // Момент последнего доступа к ОЗУ
    var now = Date.now();

    // Проверяем, не "состарились" ли данные конкретной строки с момента последней регенерации
    var elapse = now - this.ras_last_access[cas];

    if (elapse > refresh_period) {


        // В зависимости от качества конкретной ячейки ОЗУ играем в "рулетку"
        if(Math.random() > quality_factor)
            data_killer = Math.floor(Math.random() * 16777216) >> 16;

        // Если прошёл критически длинный промежуток времени, вероятность потери данных повышается
        if(elapse > refresh_period * 2)
            data_killer |= Math.floor(Math.random() * 256);

        // Симулируем "разрушение" данных по всем CAS-столбцам
        this.buf[cas] |= data_killer;
        this.buf[cas | 0x80] |= data_killer | (Math.floor(Math.random() * 16777216) >> 16);
        this.buf[cas | 0x100] |= data_killer | (Math.floor(Math.random() * 16777216) >> 16);
        this.buf[cas | 0x180] |= data_killer | (Math.floor(Math.random() * 16777216) >> 16);
        ...
        this.buf[cas | 0x7f00] |= data_killer | (Math.floor(Math.random() * 16777216) >> 16);
        this.buf[cas | 0x7f80] |= data_killer | (Math.floor(Math.random() * 16777216) >> 16);
    }

    // Обновляем этот момент последнего доступа для конкретной RAS-строки
    this.ras_last_access[cas] = now;

    return this.buf[addr];
};

Где «refresh_period», исходя из паспортных данных РУ3, должен быть ≤2 ms (здесь соотношение меняется от >2 на ≤2, исходя из описания цикла регенерации)…

P.S.: Все три примера - с потолка и не гарантирую, что рабочие.
Просто описал суть алгоритма разрушения данных так, как понимаю сам по опыту.
И не учитывается паразитная миграция заряда по ячейкам матрицы ЗУ (как в обсуждении РУ6 в качестве ПЗС).
Инженеры могут высмеять мой приём…
User avatar
Lavr
Supreme God
Posts: 16680
Joined: 21 Oct 2009 08:08
Location: Россия

Re: ПДП в РК для обновления динамического ОЗУ

Post by Lavr »

begoon wrote:
b2m wrote:А вот когда идёт чтение с магнитофона, то ПДП отключается, и подпрограмма чтения в это время вынуждена читать из памяти командой POP PSW.
А как этот трюк с POP PSW помогаем память регенерировать?
Этот трюк с POP PSW как раз и перебирает по 2 адреса за раз чтением... вместо ПДП.
Где-то, кажется в Радио, в своё время объясняли этот трюк, там программа по тактам написана так,
что при переборе адресов через POP PSW информация в ОЗУ не должна потеряться.
POP PSW - просто удобная команда для этого: и чтение, и увеличение адресов одновременно.
Причем очевидно, что чтение - фиктивное:

Code: Select all

FC58: F1                         pop     psw             ; CODE XREF: FC82j
FC59: 79                         mov     a, c
iLavr
begoon
Senior
Posts: 147
Joined: 22 Aug 2012 17:06
Location: 188.220.42.216

Re: ПДП в РК для обновления динамического ОЗУ

Post by begoon »

Lavr wrote:
begoon wrote:
b2m wrote:А вот когда идёт чтение с магнитофона, то ПДП отключается, и подпрограмма чтения в это время вынуждена читать из памяти командой POP PSW.
А как этот трюк с POP PSW помогаем память регенерировать?
Этот трюк с POP PSW как раз и перебирает по 2 адреса за раз чтением... вместо ПДП.
Где-то, кажется в Радио, в своё время объясняли этот трюк, там программа по тактам написана так,
что при переборе адресов через POP PSW информация в ОЗУ не должна потеряться.
POP PSW - просто удобная команда для этого: и чтение, и увеличение адресов одновременно.
Причем очевидно, что чтение - фиктивное:

Code: Select all

FC58: F1                         pop     psw             ; CODE XREF: FC82j
FC59: 79                         mov     a, c
Может я туповат или просто совсем не понимаю схемотехники. :-)

Например, выводим один байт. Это 8 бит. Трюк с POP PSW повторится 16 раз (8 байт по два фронта на каждый, итого 16). В начале SP=0. После 16-ти POP PSW, SP пробежит значения от 0 до 32 (16 раз инкремент по 2). То есть этими POP PSW будут неявно прочитаны ячейки от 0000 до 0020h. А как же ВСЯ остальная память?

Причем для каждого нового байта SP снова будет работать по тем же ячейкам 0000 до 0020h.
User avatar
Lavr
Supreme God
Posts: 16680
Joined: 21 Oct 2009 08:08
Location: Россия

Re: ПДП в РК для обновления динамического ОЗУ

Post by Lavr »

begoon wrote:Может я туповат или просто совсем не понимаю схемотехники. :-)
Заметим... не я это сказал... :lol:
begoon wrote:Например, выводим один байт. Это 8 бит. Трюк с POP PSW повторится 16 раз (8 байт по два фронта на каждый, итого 16). В начале SP=0. После 16-ти POP PSW, SP пробежит значения от 0 до 32 (16 раз инкремент по 2). То есть этими POP PSW будут неявно прочитаны ячейки от 0000 до 0020h. А как же ВСЯ остальная память?
А для всей остальной памяти снова включается ПДП, насколько я вижу...

Code: Select all

     LXI  H,LE004    ;FC86  21 04 E0
     MVI  M,0D0H     ;FC89  36 D0
     MVI  M,76H      ;FC8B  36 76
     INX  H          ;FC8D  23  #
     MVI  M,23H      ;FC8E  36 23
     MVI  M,49H      ;FC90  36 49
     MVI  A,27H      ;FC92  3E 27
     STA  LC001      ;FC94  32 01 C0
     MVI  A,0E0H     ;FC97  3E E0
     STA  LC001      ;FC99  32 01 C0
     MVI  L,08H      ;FC9C  2E 08
     MVI  M,0A4H     ;FC9E  36 A4
     POP  PSW        ;FCA0  F1
LFCA1:
     POP  D          ;FCA1  D1
     POP  B          ;FCA2  C1
     POP  H          ;FCA3  E1
     RET             ;FCA4  C9
Но "самодельную регенерацию" перед этим, похоже, доигрывают:

Code: Select all

LFC7B:
     POP  PSW        ;FC7B  F1
     DCR  B          ;FC7C  05
     JNZ  LFC7B      ;FC7D  C2 7B FC
iLavr
User avatar
Paguo-86PK
Maniac
Posts: 267
Joined: 12 Apr 2011 20:43
Location: Tashkent

Re: ПДП в РК для обновления динамического ОЗУ

Post by Paguo-86PK »

begoon wrote:Например, выводим один байт. Это 8 бит. Трюк с POP PSW повторится 16 раз (8 байт по два фронта на каждый, итого 16). В начале SP=0. После 16-ти POP PSW, SP пробежит значения от 0 до 32 (16 раз инкремент по 2). То есть этими POP PSW будут неявно прочитаны ячейки от 0000 до 0020h. А как же ВСЯ остальная память?
Сущeствуют константы скорости ввода/вывода магнитофона. При задержке POP PSW также выполняется - 29×8 = 148 раз - 296 ячеек обновляется.

Если интересует детализация по тактам, то здесь подробно всё расписано:

Code: Select all

WRBYTE: PUSH    H               ; 11    {{
        PUSH    B               ; 11
        PUSH    D               ; 11
        PUSH    A               ; 11
        MVI     A,80H           ; 7
        STA     VT_57+8         ; 13
        LXI     H,0             ; 10
        DAD     SP              ; 11
        LXI     SP,0            ; 10
        MVI     D,8             ; 7     }} = 95
AFC58:  POP     PSW             ; 10    {{
        MOV     A,C             ; 5
        RLC                     ; 4
        MOV     C,A             ; 5
        MVI     A,1             ; 7
        XRA     C               ; 4
        STA     VV_55+2         ; 13
        LDA     KNS_WR          ; 13
        MOV     B,A             ; 5     }} = 66                                 :: x8 = 528
AFC66:  POP     PSW             ; 10    {{
        DCR     B               ; 5
        JNZ     AFC66           ; 10    }} = 25 * KNS_WR                        :: x8 = 200 * KNS_WR
        MVI     A,0             ; 7     {{
        XRA     C               ; 4
        STA     VV_55+2         ; 13
        DCR     D               ; 5
        LDA     KNS_WR          ; 13
        JNZ     AFC7A           ; 10
        SUI     14              ; 7
AFC7A:  MOV     B,A             ; 5     }} = 57 / 64                            :: x8 = 520
AFC7B:  POP     PSW             ; 10    {{
        DCR     B               ; 5
        JNZ     AFC7B           ; 10    }} = 25 * KNS_WR:25 * (KNS_WR - 14) + 7 :: x8 = 200 * KNS_WR - 350
        INR     D               ; 5     {{
        DCR     D               ; 5
        JNZ     AFC58           ; 10    }} = 20                                 :: x8 = 160
        SPHL                    ; 5     {{
        LXI     H,VT_57+4       ; 10
        MVI     M,0D0H          ; 11
        MVI     M,76H           ; 11
        INX     H               ; 5
        MVI     M,23H           ; 11
        MVI     M,49H           ; 11
        MVI     A,27H           ; 7
        STA     VG_75+1         ; 13
        MVI     A,0E0H          ; 7
        STA     VG_75+1         ; 13
        MVI     L,8             ; 7
        MVI     M,0A4H          ; 11
        POP     PSW             ; 10
POPDBH: POP     D               ; 10
        POP     B               ; 10
        POP     H               ; 10
        RET                     ; 10    }} = 179
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; = 1482 + 376.667 * KNS_WR
Last edited by Paguo-86PK on 13 Mar 2021 08:11, edited 1 time in total.
begoon
Senior
Posts: 147
Joined: 22 Aug 2012 17:06
Location: 188.220.42.216

Re: ПДП в РК для обновления динамического ОЗУ

Post by begoon »

Lavr wrote:
begoon wrote:Например, выводим один байт. Это 8 бит. Трюк с POP PSW повторится 16 раз (8 байт по два фронта на каждый, итого 16). В начале SP=0. После 16-ти POP PSW, SP пробежит значения от 0 до 32 (16 раз инкремент по 2). То есть этими POP PSW будут неявно прочитаны ячейки от 0000 до 0020h. А как же ВСЯ остальная память?
А для всей остальной памяти снова включается ПДП
Ответь мне на простой вопрос: зачем при выводе (или вводе) ЛЮБОГО байта пробегать одни и те же 32 байта от 0000 до 001F? Как именно это решает вопрос регенерации ВСЕЙ памяти?
User avatar
Lavr
Supreme God
Posts: 16680
Joined: 21 Oct 2009 08:08
Location: Россия

Re: ПДП в РК для обновления динамического ОЗУ

Post by Lavr »

begoon wrote:Ответь мне на простой вопрос: зачем при выводе (или вводе) ЛЮБОГО байта пробегать одни и те же 32 байта от 0000 до 001F? Как именно это решает вопрос регенерации ВСЕЙ памяти?
Ты просто не понял - выше тебе всё подробно расписали...
Не 32 байта, а 32 строки, но реально гораздо больше:

Code: Select all

LFC7B:
     POP  PSW        ;FC7B  F1
     DCR  B          ;FC7C  05
     JNZ  LFC7B      ;FC7D  C2 7B FC
iLavr
b2m
Devil
Posts: 907
Joined: 26 May 2003 06:57

Re: ПДП в РК для обновления динамического ОЗУ

Post by b2m »

Lavr wrote:Но "самодельную регенерацию" перед этим, похоже, доигрывают:

Code: Select all

LFC7B:
     POP  PSW        ;FC7B  F1
     DCR  B          ;FC7C  05
     JNZ  LFC7B      ;FC7D  C2 7B FC
Ага, доигрывают, ожидая записи второго полубита.
Страничка эмулятора наших компьютеров
http://bashkiria-2m.narod.ru/
b2m
Devil
Posts: 907
Joined: 26 May 2003 06:57

Re: ПДП в РК для обновления динамического ОЗУ

Post by b2m »

Кстати, если кто не понял, зачем там SUI 14, то это потому-что последний полубит нужно ожидать чуть меньше, т.к. после окончания цикла идёт настройка ПДП, да и вообще, накладные расходы на вход/выход из процедуры.
Страничка эмулятора наших компьютеров
http://bashkiria-2m.narod.ru/
User avatar
Paguo-86PK
Maniac
Posts: 267
Joined: 12 Apr 2011 20:43
Location: Tashkent

Re: ПДП в РК для обновления динамического ОЗУ

Post by Paguo-86PK »

b2m wrote:Кстати, если кто не понял, зачем там SUI 14, то это потому-что последний полубит нужно ожидать чуть меньше, т.к. после окончания цикла идёт настройка ПДП, да и вообще, накладные расходы на вход/выход из процедуры.
И именнo потому константу вывода ставить меньше 15 нельзя.

Вообще-то разработчики РК могли бы поступить иначе: Пропускать ADI 14 в конце.
Тогда бы константы чтения/записи можно было бы указывать от единицы…
b2m
Devil
Posts: 907
Joined: 26 May 2003 06:57

Re: ПДП в РК для обновления динамического ОЗУ

Post by b2m »

Paguo-86PK wrote:Пропускать ADI 14 в конце.
Тогда бы константы чтения/записи можно было бы указывать от единицы…
Вот не понял ты всё-таки, зачем последний полубит в конце должен быть "как бы короче".
Страничка эмулятора наших компьютеров
http://bashkiria-2m.narod.ru/