nedoPC.org

Electronics hobbyists community established in 2002
Atom Feed | View unanswered posts | View active topics It is currently 28 Mar 2024 03:24



Reply to topic  [ 23 posts ]  Go to page 1, 2  Next
ПДП в РК для обновления динамического ОЗУ 
Author Message
Senior

Joined: 22 Aug 2012 17:06
Posts: 144
Location: 188.220.42.216
Reply with quote
Коллеги, проведите, пожалуйста, ликбез для человека, не очень глубоко разбирающегося схемотехнике.

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

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

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

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

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

Видимо, обновление ОЗУ - это какой-то побочный эффект особого использования сигналов микросхемы ПДП, когда она пересылает видео область, так?


12 Mar 2021 03:48
Profile
Devil

Joined: 26 May 2003 06:57
Posts: 859
Reply with quote
Ну, ПДП вроде как считывает из ОЗУ, этого достаточно. Другое дело, как адресацию организовать: младшие биты адреса как раз и будут задаваться по RAS, то есть достаточно подряд 128 байт считать. Экран гораздо больше. Главное, чтобы за время обратного хода луча ничего не потерялось.

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

_________________
Страничка эмулятора наших компьютеров
http://bashkiria-2m.narod.ru/


12 Mar 2021 05:27
Profile WWW
Maniac
User avatar

Joined: 12 Apr 2011 20:43
Posts: 267
Location: Tashkent
Reply with quote
Вoт если бы удалось в эмуляторе как-то реализовать разрушение данных в ОЗУ при неправильной регенерации - это было бы чудо!
Сталкивался с этим, когда пытался отключать/программировать ПДП при написании сэмплера.


12 Mar 2021 08:05
Profile WWW
Senior

Joined: 22 Aug 2012 17:06
Posts: 144
Location: 188.220.42.216
Reply with quote
b2m wrote:
А вот когда идёт чтение с магнитофона, то ПДП отключается, и подпрограмма чтения в это время вынуждена читать из памяти командой POP PSW.

А как этот трюк с POP PSW помогаем память регенерировать?

Вот кусок начала вывода байта. Судя по коду, в начале SP всегда начинается с адреса 0000 и потом начинает увеличиться. То есть проходятся адреса всегда начиная с нуля. А как же остальные ячейки?
Code:
                 ; --------------------------------------------------------------
                 ; 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


12 Mar 2021 11:57
Profile
Maniac
User avatar

Joined: 12 Apr 2011 20:43
Posts: 267
Location: Tashkent
Reply with quote
Микросхемы ОЗУ РУ3 это матрицы 128×128. По RAS считывается вся строка в 128 бит и перезаписывается (внутри ОЗУ) обратно. А по CAS из этих считанных 128 бит выбирается один.

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

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

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

В эмуляторе разрушение данных в ОЗУ можно симулировать вставкой примерно подобного цикла:
 "Самый простой способ"
Code:
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:
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:
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 в качестве ПЗС).
Инженеры могут высмеять мой приём…


12 Mar 2021 12:31
Profile WWW
Supreme God
User avatar

Joined: 21 Oct 2009 08:08
Posts: 7777
Location: Россия
Reply with quote
begoon wrote:
b2m wrote:
А вот когда идёт чтение с магнитофона, то ПДП отключается, и подпрограмма чтения в это время вынуждена читать из памяти командой POP PSW.

А как этот трюк с POP PSW помогаем память регенерировать?

Этот трюк с POP PSW как раз и перебирает по 2 адреса за раз чтением... вместо ПДП.
Где-то, кажется в Радио, в своё время объясняли этот трюк, там программа по тактам написана так,
что при переборе адресов через POP PSW информация в ОЗУ не должна потеряться.
POP PSW - просто удобная команда для этого: и чтение, и увеличение адресов одновременно.
Причем очевидно, что чтение - фиктивное:
Code:
FC58: F1                         pop     psw             ; CODE XREF: FC82j
FC59: 79                         mov     a, c

_________________
iLavr


13 Mar 2021 00:22
Profile
Senior

Joined: 22 Aug 2012 17:06
Posts: 144
Location: 188.220.42.216
Reply with quote
Lavr wrote:
begoon wrote:
b2m wrote:
А вот когда идёт чтение с магнитофона, то ПДП отключается, и подпрограмма чтения в это время вынуждена читать из памяти командой POP PSW.

А как этот трюк с POP PSW помогаем память регенерировать?

Этот трюк с POP PSW как раз и перебирает по 2 адреса за раз чтением... вместо ПДП.
Где-то, кажется в Радио, в своё время объясняли этот трюк, там программа по тактам написана так,
что при переборе адресов через POP PSW информация в ОЗУ не должна потеряться.
POP PSW - просто удобная команда для этого: и чтение, и увеличение адресов одновременно.
Причем очевидно, что чтение - фиктивное:
Code:
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.


13 Mar 2021 04:33
Profile
Supreme God
User avatar

Joined: 21 Oct 2009 08:08
Posts: 7777
Location: Россия
Reply with quote
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:
     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:
LFC7B:
     POP  PSW        ;FC7B  F1
     DCR  B          ;FC7C  05
     JNZ  LFC7B      ;FC7D  C2 7B FC

_________________
iLavr


13 Mar 2021 07:33
Profile
Maniac
User avatar

Joined: 12 Apr 2011 20:43
Posts: 267
Location: Tashkent
Reply with quote
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:
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.



13 Mar 2021 08:03
Profile WWW
Senior

Joined: 22 Aug 2012 17:06
Posts: 144
Location: 188.220.42.216
Reply with quote
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? Как именно это решает вопрос регенерации ВСЕЙ памяти?


13 Mar 2021 08:05
Profile
Supreme God
User avatar

Joined: 21 Oct 2009 08:08
Posts: 7777
Location: Россия
Reply with quote
begoon wrote:
Ответь мне на простой вопрос: зачем при выводе (или вводе) ЛЮБОГО байта пробегать одни и те же 32 байта от 0000 до 001F? Как именно это решает вопрос регенерации ВСЕЙ памяти?

Ты просто не понял - выше тебе всё подробно расписали...
Не 32 байта, а 32 строки, но реально гораздо больше:
Code:
LFC7B:
     POP  PSW        ;FC7B  F1
     DCR  B          ;FC7C  05
     JNZ  LFC7B      ;FC7D  C2 7B FC

_________________
iLavr


13 Mar 2021 08:15
Profile
Devil

Joined: 26 May 2003 06:57
Posts: 859
Reply with quote
Lavr wrote:
Но "самодельную регенерацию" перед этим, похоже, доигрывают:
Code:
LFC7B:
     POP  PSW        ;FC7B  F1
     DCR  B          ;FC7C  05
     JNZ  LFC7B      ;FC7D  C2 7B FC

Ага, доигрывают, ожидая записи второго полубита.

_________________
Страничка эмулятора наших компьютеров
http://bashkiria-2m.narod.ru/


14 Mar 2021 11:31
Profile WWW
Devil

Joined: 26 May 2003 06:57
Posts: 859
Reply with quote
Кстати, если кто не понял, зачем там SUI 14, то это потому-что последний полубит нужно ожидать чуть меньше, т.к. после окончания цикла идёт настройка ПДП, да и вообще, накладные расходы на вход/выход из процедуры.

_________________
Страничка эмулятора наших компьютеров
http://bashkiria-2m.narod.ru/


14 Mar 2021 11:35
Profile WWW
Maniac
User avatar

Joined: 12 Apr 2011 20:43
Posts: 267
Location: Tashkent
Reply with quote
b2m wrote:
Кстати, если кто не понял, зачем там SUI 14, то это потому-что последний полубит нужно ожидать чуть меньше, т.к. после окончания цикла идёт настройка ПДП, да и вообще, накладные расходы на вход/выход из процедуры.
И именнo потому константу вывода ставить меньше 15 нельзя.

Вообще-то разработчики РК могли бы поступить иначе: Пропускать ADI 14 в конце.
Тогда бы константы чтения/записи можно было бы указывать от единицы…


14 Mar 2021 11:40
Profile WWW
Devil

Joined: 26 May 2003 06:57
Posts: 859
Reply with quote
Paguo-86PK wrote:
Пропускать ADI 14 в конце.
Тогда бы константы чтения/записи можно было бы указывать от единицы…

Вот не понял ты всё-таки, зачем последний полубит в конце должен быть "как бы короче".

_________________
Страничка эмулятора наших компьютеров
http://bashkiria-2m.narod.ru/


14 Mar 2021 11:59
Profile WWW
Display posts from previous:  Sort by  
Reply to topic   [ 23 posts ]  Go to page 1, 2  Next

Who is online

Users browsing this forum: No registered users and 9 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group
Designed by ST Software.