nedoPC.org

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



Reply to topic  [ 52 posts ]  Go to page Previous  1, 2, 3, 4  Next
3niti alpha simu1 - троичный компьютер на двоичном пике 
Author Message
Retired

Joined: 03 Aug 2003 22:37
Posts: 1474
Location: Moscow
Reply with quote
Post 
Где тут очередь? Я первый?

_________________
Extreme Entertainment


29 Oct 2011 12:29
Profile
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22412
Location: Silicon Valley
Reply with quote
Post 
Mac Buster wrote:
Где тут очередь? Я первый?


Очередь тут:

https://www.tindie.com/products/trc/3niti-alpha-simu1/

_________________
:dj: https://mastodon.social/@Shaos


29 Oct 2011 15:17
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22412
Location: Silicon Valley
Reply with quote
Post 
Собрал первую Rev.B:

Image

И оно с ходу заработало:

Image

:kruto:

P.S. Снял трёхчасовое с хвостиком видео сборки - ускорю в 10 раз и выложу на ютюб...

_________________
:dj: https://mastodon.social/@Shaos


07 Nov 2011 23:24
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22412
Location: Silicon Valley
Reply with quote
Post 
код троичного инвертирования (он просто переставляет местами чётные и нечётные биты):

Code:
tri_neg: ; 14 cycles with call
   movwf   tmp1 ; сохраняем байт в tmp1
   andlw   b'01010101' ; берём по маске каждый чётный бит
   movwf   tmp2 ; сохраняем в tmp2
   movf   tmp1,W ; берём tmp1 (то что пришло на вход функции)
   andlw   b'10101010' ; берём по маске каждый нечётный бит
   movwf   tmp1 ; сохраняем в tmp1
   bcf   STATUS,C ; пишем 0 во флаг C
   rlf   tmp2,F ; сдвигаем влево tmp2
   rrf   tmp1,W ; сдвигаем вправо tmp1 (надо бы перед ним тоже C обнулить, хотя с 3-тритными словами работать должно)
   iorwf   tmp2,W ; складываем по или с tmp2
   return ; возвращаем байт с переставленными чётными и нечётными битами


код снятия состояние переключателей и высвечивания этого состояния на светодиодах:

Code:
loop:
   movlw   b'11111110' ; устанавливаем бегущий ноль в нулевой бит
   movwf   mask ; сохраняем в переменной mask
   movlw   5
   movwf   count ; устанавливаем счётчик в 5
loop0:
   movf   mask,w
   movwf   PORTA ; послать маску в порт A (чтобы выбрать 3 переключателя/светодиода)
   _delay1 10,cnt1 ; ждём
   movf   PORTB,w ; читаем байт из порта B (состояние очередных 3 троичных переключателей)
   call   tri_neg ; троично инвертируем (переключатели вверх-ногами припаяны ;)
   movwf   PORTC ; посылаем получившееся в порт C (на очередные 3 троичных светодиода)
   _delay1   0,cnt1 ; долго ждём
   bsf   STATUS,C ; флаг C = 1
   rlf   mask,f ; сдвигаем наш ноль влево
   decfsz   count,f ; декрементируем счётчик и проверяем, что он ещё не ноль
   goto   loop0 ; переход на следующую итерацию (из пяти)
   goto   loop ; после пяти итераций идём к началу...


P.S. вышеприведённый код работает не с представлением трита как пары битов с состояниями 01,00,10 а с состояниями 10,11,01 (т.е. двоично инвертированными)

P.P.S. подпрограмма tri_neg может корректно троично инвертировать как двоично-инвертированную триаду, так и "нормальную"

_________________
:dj: https://mastodon.social/@Shaos


Last edited by Shaos on 19 Nov 2011 09:16, edited 4 times in total.



16 Nov 2011 19:56
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22412
Location: Silicon Valley
Reply with quote
Post 
Ниже представлен код троичного инкремента триады из второго теста. Триада - это три трита, каждый из которых представлен двумя битами - младшим битом минуса и старшим битом плюса. Триады у нас перевёрнуты из-за особенностей схемы "3niti alpha simu1", т.е. в старших битах находится младший трит, а в младших - старший:

bit 0 - установлен в "1", если старший трит триады отрицателен
bit 1 - установлен в "1", если старший трит триады положителен
bit 2 - установлен в "1", если средней трит триады отрицателен
bit 3 - установлен в "1", если средней трит триады положителен
bit 4 - установлен в "1", если младшей трит триады отрицателен
bit 5 - установлен в "1", если младшей трит триады положителен
bit 6 - должен быть нулевым
bit 7 - должен быть нулевым

Code:
; Ternary increment of W (used tmp1), C if overflow
tri_inc:
   bcf   STATUS,C ; обнуляем флаг переноса C (это у нас признак переполнения при возврате управления из подпрограммы)
   movwf   tmp1 ; сохраняем инкрементируемую триаду в переменной tmp1

; инкремент младшего трита:

tri_i5:   btfss   tmp1,5 ; проверяем взведён ли бит 5 в нашей триаде (это плюс младшего трита)
   goto   tri_i4 ; если взведён, то пропускаем переход на tri_i4 и идём дальше
   bcf   tmp1,5 ; обнуляем  бит 5 (бит плюса младшей триады)
   bsf   tmp1,4 ; взводим бит 4 (бит минуса младшей триады)
   goto   tri_i3 ; в результате получаем -1 вместо +1 в младшей триаде и идём на инкремент следующего трита (перенос)

tri_i4:   btfss   tmp1,4 ; проверяем взведён ли бит 4 в нашей триаде (это минус младшего трита)
   bsf   tmp1,5 ; если не взведён (т.е. младший трит хранил 0), то устанавливаем бит 5 (плюс младшего трита)
   bcf   tmp1,4 ; обнуляем бит 4 (сбрасываем минус младшего трита, если он был)
   movf   tmp1,w ; копируем получившееся представление триады в аккумулятор W
   return ; возвращаем управление из подпрограммы

; инкремент среднего трита:

tri_i3:   btfss   tmp1,3 ; проверяем взведён ли бит 3 в нашей триаде (это плюс среднего трита)
   goto   tri_i2 ; если взведён, то пропускаем переход на tri_i2 и идём дальше
   bcf   tmp1,3 ; обнуляем  бит 3 (бит плюса средней триады)
   bsf   tmp1,2 ; взводим бит 2 (бит минуса средней триады)
   goto   tri_i1 ; в результате получаем -1 вместо +1 в средней триаде и идём на инкремент следующего трита (перенос)
 
tri_i2:   btfss   tmp1,2 ; проверяем взведён ли бит 2 в нашей триаде (это минус среднего трита)
   bsf   tmp1,3 ; если не взведён (т.е. средний трит хранил 0), то устанавливаем бит 3 (плюс среднего трита)
   bcf   tmp1,2 ; обнуляем бит 2 (сбрасываем минус среднего трита, если он был)
   movf   tmp1,w ; копируем получившееся представление триады в аккумулятор W
   return ; возвращаем управление из подпрограммы

; инкремент старшего трита:

tri_i1:   btfss   tmp1,1 ; проверяем взведён ли бит 1 в нашей триаде (это плюс старшего трита)
   goto   tri_i0 ; если взведён, то пропускаем переход на tri_i0 и идём дальше
   bcf   tmp1,1 ; обнуляем  бит 1 (бит плюса старшей триады)
   bsf   tmp1,0 ; взводим бит 0 (бит минуса старшей триады)
   goto   tri_ic ; в результате получаем -1 вместо +1 в старшей триаде и идём на взведение флага переноса (переполнение)

tri_i0:   btfss   tmp1,0 ; проверяем взведён ли бит 0 в нашей триаде (это минус старшего трита)
   bsf   tmp1,1 ; если не взведён (т.е. старший трит хранил 0), то устанавливаем бит 1 (плюс старшего трита)
   bcf   tmp1,0 ; обнуляем бит 0 (сбрасываем минус старшего трита, если он был)
   movf   tmp1,w ; копируем получившееся представление триады в аккумулятор W
   return ; возвращаем управление из подпрограммы

; обработка переполнения:

tri_ic: movf   tmp1,w ; копируем получившееся представление триады в аккумулятор W
   bsf   STATUS,C ; взводим флаг C (признак переполнения)
   return ; возвращаем управление из подпрограммы

_________________
:dj: https://mastodon.social/@Shaos


17 Nov 2011 21:03
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22412
Location: Silicon Valley
Reply with quote
Post 
Рассмотрим принципиальную схему и печатную плату - там видно, что при положении переключателя "вверх" (плюс), контакт 4 подключен к 3, что передаёт сканирующий ноль порта A на чётные биты порта B, при положении "вниз" (минус) - контакт 1 подключен к 3, что задействует нечётные биты порта B, а при среднем положении (ноль) никуда не подключенный контакт 2 идёт на 3, что оставляет на обоих битах высокий уровень (т.к. на порту B включены внутренние подтягивающие резисторы), т.е.:
Code:
        - 0 +
-------------
bit 0 = 1 1 0
bit 1 = 0 1 1

Как видно, чтобы превратить это представление в двоично закодированную троичность (binary coded ternary), нужно заменить пару 11 на пару 00:
Code:
; Fix triad W  (used tmp1)
tri_fix: ; 15-24 cycles with call
  movwf tmp1
tri_f2: ; старший трит
  btfss tmp1,0 ; проверить что бит 0 взведён
  goto tri_f1 ; если нет, то идём на следующую пару бит
  btfss tmp1,1 ; проверить что бит 1 взведён
  goto tri_f1 ; если нет, то идём на следующую пару бит
  bcf tmp1,0 ; сбросить бит 0
  bcf tmp1,1 ; сбросить бит 1
tri_f1: ; средний трит
  btfss tmp1,2 ; проверить что бит 2 взведён
  goto tri_f0 ; если нет, то идём на следующую пару бит
  btfss tmp1,3 ; проверить что бит 3 взведён
  goto tri_f0; если нет, то идём на следующую пару бит
  bcf tmp1,2 ; сбросить бит 2
  bcf tmp1,3 ; сбросить бит 3
tri_f0: ; младший трит
  btfss tmp1,4 ; проверить что бит 4 взведён
  goto tri_fe ; если нет, то делаем возврат из подпрограммы
  btfss tmp1,5 ; проверить что бит 5 взведён
  goto tri_fe ; если нет, то делаем возврат из подпрограммы
  bcf tmp1,4 ; сбросить бит 4
  bcf tmp1,5 ; сбросить бит 5
tri_fe: ; возвращаем скорректированую триаду обратно в W
  movf tmp1,w
  return ; возврат из подпрограммы

Как видно бинарное инвертирование (comf var,w) и затем троичное инвертирование (call tri_neg) будет работать быстрее (как собственно и сделано во втором тесте с часами).

В случае светодиодов ноль в чётном бите подсвечивает красный светодиод (минус), а в нечётном - зелёный (плюс). А чтобы двойной светодиод не горел, оба бита должны содержать "1" (в случае обоих нулей светодиоды дадут жёлтый свет):
Code:
        - 0 +
-------------
bit 0 = 0 1 1
bit 1 = 1 1 0

Значит чтобы отобразить триаду на светодиодах её достаточно бинарно инвертировать:
Code:
comf outvar,w
movwf PORTC

При этом PORTA дожен держать низкий уровень в одном из пяти рядов (через RA0,RA1,RA2,RA3,RA4), соответствующих тройкам светодиодов, которую мы собираемся подсветить.

_________________
:dj: https://mastodon.social/@Shaos


Last edited by Shaos on 19 Nov 2011 14:59, edited 1 time in total.



18 Nov 2011 18:36
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22412
Location: Silicon Valley
Reply with quote
Post 
Shaos wrote:
Триада - это три трита, каждый из которых представлен двумя битами - младшим битом минуса и старшим битом плюса. Триады у нас перевёрнуты из-за особенностей схемы "3niti alpha simu1", т.е. в старших битах находится младший трит, а в младших - старший:

bit 0 - установлен в "1", если старший трит триады отрицателен
bit 1 - установлен в "1", если старший трит триады положителен
bit 2 - установлен в "1", если средней трит триады отрицателен
bit 3 - установлен в "1", если средней трит триады положителен
bit 4 - установлен в "1", если младшей трит триады отрицателен
bit 5 - установлен в "1", если младшей трит триады положителен
bit 6 - должен быть нулевым
bit 7 - должен быть нулевым

Если таким байтом адресоваться к 27-триадному блоку данных, то в двоичной памяти оно расположится так:
Code:
0x00 (00000000) OOO = 0
0x01 (00000001) NOO = -9
0x02 (00000010) POO = +9
0x03 (00000011)
0x04 (00000100) ONO = -3
0x05 (00000101) NNO = -12
0x06 (00000110) PNO = +6
0x07 (00000111)
0x08 (00001000) OPO = +3
0x09 (00001001) NPO = -6
0x0A (00001010) PPO = +12
0x0B (00001011)
0x0C (00001100)
0x0D (00001101)
0x0E (00001110)
0x0F (00001111)
0x10 (00010000) OON = -1
0x11 (00010001) NON = -10
0x12 (00010010) PON = +8
0x13 (00010011)
0x14 (00010100) ONN = -4
0x15 (00010101) NNN = -13
0x16 (00010110) PPN = +5
0x17 (00010111)
0x18 (00011000) OPN = +2
0x19 (00011001) NPN = -7
0x1A (00011010) PPN = +11
0x1B (00011011)
0x1C (00011100)
0x1D (00011101)
0x1E (00011110)
0x1F (00011111)
0x20 (00100000) OOP = +1
0x21 (00100001) NOP = -8
0x22 (00100010) POP = +10
0x23 (00100011)
0x24 (00100100) ONP = -2
0x25 (00100101) NNP = -11
0x26 (00100110) PNP = +7
0x27 (00100111)
0x28 (00101000) OPP = +4
0x29 (00101001) NPP = -5
0x2A (00101010) PPP = +13
0x2B (00101011)
0x2C (00101100)
0x2D (00101101)
0x2E (00101110)
0x2F (00101111)

Как можно видеть, не используются любые ячейки, в адресе которых встречаются две пары единиц у любой из триад (запрещённая комбинация в binary coded ternary).

В первой версии эмулятора для платы "3niti alpha simu1" предлагается держать 27-триад кода в EEPROM (как бы троичный ROM) с вышеуказанными адресами и 27-триад данных в регистровой памяти (как бы троичный RAM) с вышеуказанными адресами, к которым прибавлено число 0x40, т.е. диапазон переменных 0x40...0x6F (нулевой банк файла региcтров в пике).

В терминах длинных адресов "3niti alpha", этот 27-триадный ROM будет отображаться на область OOOOOOxxx, а 27-триадный RAM - на область OPNNNNxxx (начиная с адреса +1093). В текущей прошивке, над которой я сейчас работаю, внешняя память пока использоваться небудет (её можно будет добавить позже - у схемы есть возможность обновления прошивки через бутлоадер).

P.S. Глядя на этот маппинг троичных адресов на двоичные у меня возникла идея - что если прямо так и хранить во внешней памяти? Можно читать по 48 байт (тогда потеряно будет 44% памяти), убрав последние 5 байт получим 43 байта (37% потерь) или даже брать блоками по 11 байт три раза, где будет всего 2 однобайтных дырки (18% потерь). Проблема лишь в том, что придётся адресоваться к памяти через умножение - надо будет умножать на 48 (00110000), 43 (00101011) или 11 (00001011) - хотя точнее надо бы сказать 33 (00100001), т.к. 3 раза по 11. Формула уможения на 48: (x<<5)+(x<<4). Формула умножения на 43: (x<<5)+(x<<3)+(x<<2)+x. Формула умножения на 11: (x<<3)+(x<<1)+x или (x<<3)+(x<<2)-x (т.е. 12*x-x). Формула умножения на 33: (x<<5)+x. Хотя блоками по 27 тоже умножать надо, причём на некрасивое число 00011011...

P.P.S. Прикинул, что при 3x11-байтовом представлении 27-триадной страницы теоретически будет читаться-писаться по 300 страниц в секунду при 100кГц или 1200 страниц при 400кГц. Но т.к. при записи будет до 10 мс задержка на запись очередной порции (до 32 байт длиной) - то это уменьшит скорость записи до 30 страниц в секунду при 100кГц или 120 страниц при 400 кГц. Напомню, что первоначально оговоренный размер блоков RAM и ROM у 3niti alpha составляет (1093*2+1)/27=81 страница, которые можно прочитать меньше чем за треть секунды и записать за 2.7 или за 1.35 секунды в зависимости от тактовой частоты ПЗУ. Байты "потерянные" при такой оптимизации можно использовать для хранения адреса страницы (для проверки корректности места чтения) и её контрольной суммы (для проверки целостности данных).

P.P.P.S. Внимательно прочитал даташит на I2C память - страничная запись подразумевает запись в 32-байтовые области с фиксированными адресами - т.е. придётся таки писать ровно по 32 байта...

_________________
:dj: https://mastodon.social/@Shaos


19 Nov 2011 13:38
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22412
Location: Silicon Valley
Reply with quote
Post 
Троичный инкремент 9-тритового регистра PC (program counter):

Code:
; Ternary increment of 9-trit PC
inc_pc3:
        movf    PC_l,w ; берём млашую триаду PC
        call    tri_inc ; троично инкрементируем её
        movwf   PC_l ; сохраняем обратно
        btfss   STATUS,C ; проверяем флаг переноса C
        return ; если он не взведён - выходим из подпрограммы
        movf    PC_m,w ; берём среднюю триаду PC
        call    tri_inc ; троично инкрементируем её
        movwf   PC_m ; сохраняем обратно
        btfss   STATUS,C ; проверяем флаг переноса c
        return ; если он не взведён - выходим из подпрограммы
        movf    PC_h,w ; берём старшую триаду PC
        call    tri_inc ; троично инкрементируем её
        movwf   PC_h ; сохраняем обратно
        return ; выходим из подпровграммы


Печать триады через функцию печати в терминал из бутлоадера (макрос _serial_send_):

Code:
; Serial print triad from W (used tmp0, cnt1)
print_triad:
        movwf   tmp0
        movlw   3
        movwf   cnt1
ptriad: btfsc   tmp0,0
        goto    ptriadn
        btfsc   tmp0,1
        goto    ptriadp
        _serial_send_ 'O'
        goto ptriad1
ptriadp:
        _serial_send_ 'P'
        goto ptriad1
ptriadn:
        _serial_send_ 'N'
ptriad1:
        rrf     tmp0,f
        rrf     tmp0,f
        decfsz  cnt1,f
        goto    ptriad
        return


Вот код циклического инкремента PC с печатью и результат его работы:
Code:
loop:   call    inc_pc3

        movf    PC_h,w
        call    print_triad
        movf    PC_m,w
        call    print_triad
        movf    PC_l,w
        call    print_triad
        _serial_print_nl

        goto    loop


OOOOOOOOP
OOOOOOOPN
OOOOOOOPO
OOOOOOOPP
OOOOOOPNN
OOOOOOPNO
OOOOOOPNP
OOOOOOPON
OOOOOOPOO
OOOOOOPOP
OOOOOOPPN
OOOOOOPPO
OOOOOOPPP
OOOOOPNNN
OOOOOPNNO
OOOOOPNNP
OOOOOPNON
OOOOOPNOO
OOOOOPNOP
OOOOOPNPN
OOOOOPNPO
OOOOOPNPP
OOOOOPONN
OOOOOPONO
OOOOOPONP
OOOOOPOON
OOOOOPOOO
OOOOOPOOP
OOOOOPOPN
OOOOOPOPO
OOOOOPOPP
OOOOOPPNN
OOOOOPPNO
OOOOOPPNP
OOOOOPPON
OOOOOPPOO
OOOOOPPOP
OOOOOPPPN
OOOOOPPPO
OOOOOPPPP
OOOOPNNNN
OOOOPNNNO
и т.д.

P.S. Замерил без печати - PC полностью пробегает свой диапазон (19683) за 0.104 секунды (точнее это было 64 пробега за 6.66 секунд) - что означает примерно 189000 9-тритовых инкрементов в секунду - это и есть предельная скорость работы нашего эмулируемого процессора "3niti alpha" - 189000 операций в секунду...

P.P.S. Хотя если инкремент триады сделать не процедурным, а табличным, то будет побыстрее...

_________________
:dj: https://mastodon.social/@Shaos


21 Nov 2011 00:48
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22412
Location: Silicon Valley
Reply with quote
Post 
Как ни странно, но табличный метод оказался даже чуть медленнее (примерно 174000 9-тритовых инкрементов в секунду):

Code:
; Fast ternary increment of the triad W, C is overflow (used tmp1)

   ORG   0100h

tri_inc_table:

   retlw   tOOP
   retlw   tNOP
   retlw   tPOP
   retlw   0xFF
   retlw   tONP
   retlw   tNNP
   retlw   tPNP
   retlw   0xFF
   retlw   tOPP
   retlw   tNPP
   retlw   tPPP
   retlw   0xFF
   retlw   0xFF
   retlw   0xFF
   retlw   0xFF
   retlw   0xFF

   retlw   tOOO
   retlw   tNOO
   retlw   tPOO
   retlw   0xFF
   retlw   tONO
   retlw   tNNO
   retlw   tPNO
   retlw   0xFF
   retlw   tOPO
   retlw   tNPO
   retlw   tPPO
   retlw   0xFF
   retlw   0xFF
   retlw   0xFF
   retlw   0xFF
   retlw   0xFF

   retlw   tOPN
   retlw   tNPN
   retlw   tPPN
   retlw   0xFF
   retlw   tOON
   retlw   tNON
   retlw   tPON
   retlw   0xFF
   retlw   tPNN
   retlw   tONN
   retlw   tNNN ; overflow
   retlw   0xFF
   retlw   0xFF
   retlw   0xFF
   retlw   0xFF
   retlw   0xFF

   retlw   0xFF
   retlw   0xFF
   retlw   0xFF
   retlw   0xFF
   retlw   0xFF
   retlw   0xFF
   retlw   0xFF
   retlw   0xFF
   retlw   0xFF
   retlw   0xFF
   retlw   0xFF
   retlw   0xFF
   retlw   0xFF
   retlw   0xFF
   retlw   0xFF
   retlw   0xFF

tri_inc_fast_:
   bsf   PCLATH,0
   movwf   PCL

tri_inc_fast: ; 18 with call
   andlw   0x3F
   call   tri_inc_fast_
   movwf   tmp1
   sublw   tNNN
   bcf   STATUS,C
   btfsc   STATUS,Z
   bsf   STATUS,C
   movf   tmp1,w
   return

_________________
:dj: https://mastodon.social/@Shaos


21 Nov 2011 16:30
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22412
Location: Silicon Valley
Reply with quote
Post 
Самая сложная подпрограмма, необходимая для работы эмулятора "3niti alpha" - сложение двух триад с учётом флага переноса-заёма - реализация частично табличная (для сложения трёх троичных цифр), частично процедурная (для сложения триад):

Code:
tri_add_3trits: ; 6 cycles with call
   addwf   PCL,f ; jump to proper value
   retlw   b'00000000' ; 000000 ->  0+0+0= 0 S=O C=O
   retlw   b'00000001' ; 000001 ->  0+0-1=-1 S=N C=O
   retlw   b'00000010' ; 000010 ->  0+0+1= 1 S=P C=O
   retlw   b'00010000' ; 000011 -> invalid
   retlw   b'00000001' ; 000100 ->  0-1+0=-1 S=N C=O
   retlw   b'00000110' ; 000101 ->  0-1-1=-2 S=P C=N
   retlw   b'00000000' ; 000110 ->  0-1+1= 0 S=O C=O
   retlw   b'00010000' ; 000111 -> invalid
   retlw   b'00000010' ; 001000 ->  0+1+0= 1 S=P C=O
   retlw   b'00000000' ; 001001 ->  0+1-1= 0 S=O C=O
   retlw   b'00001001' ; 001010 ->  0+1+1= 2 S=N C=P
   retlw   b'00010000' ; 001011 -> invalid
   retlw   b'00010000' ; 001100 -> invalid
   retlw   b'00010000' ; 001101 -> invalid
   retlw   b'00010000' ; 001110 -> invalid
   retlw   b'00010000' ; 001111 -> invalid
   retlw   b'00000001' ; 010000 -> -1+0+0=-1 S=N C=O
   retlw   b'00000110' ; 010001 -> -1+0-1=-2 S=P C=N
   retlw   b'00000000' ; 010010 -> -1+0+1= 0 S=O C=O
   retlw   b'00010000' ; 010011 -> invalid
   retlw   b'00000110' ; 010100 -> -1-1+0=-2 S=P C=N
   retlw   b'00000100' ; 010101 -> -1-1-1=-3 S=O C=N
   retlw   b'00000001' ; 010110 -> -1-1+1=-1 S=N C=O
   retlw   b'00010000' ; 010111 -> invalid
   retlw   b'00000000' ; 011000 -> -1+1+0= 0 S=O C=O
   retlw   b'00000001' ; 011001 -> -1+1-1=-1 S=N C=O
   retlw   b'00000010' ; 011010 -> -1+1+1= 1 S=P C=O
   retlw   b'00010000' ; 011011 -> invalid
   retlw   b'00010000' ; 011100 -> invalid
   retlw   b'00010000' ; 011101 -> invalid
   retlw   b'00010000' ; 011110 -> invalid
   retlw   b'00010000' ; 011111 -> invalid
   retlw   b'00000010' ; 100000 ->  1+0+0= 1 S=P C=O
   retlw   b'00000000' ; 100001 ->  1+0-1= 0 S=O C=O
   retlw   b'00001001' ; 100010 ->  1+0+1= 2 S=N C=P
   retlw   b'00010000' ; 100011 -> invalid
   retlw   b'00000000' ; 100100 ->  1-1+0= 0 S=O C=O
   retlw   b'00000001' ; 100101 ->  1-1-1=-1 S=N C=O
   retlw   b'00000010' ; 100110 ->  1-1+1= 1 S=P C=O
   retlw   b'00010000' ; 100111 -> invalid
   retlw   b'00001001' ; 101000 ->  1+1+0= 2 S=N C=P
   retlw   b'00000010' ; 101001 ->  1+1-1= 1 S=P C=O
   retlw   b'00001000' ; 101010 ->  1+1+1= 3 S=O C=P
   retlw   b'00010000' ; 101011 -> invalid
   retlw   b'00010000' ; 101100 -> invalid
   retlw   b'00010000' ; 101101 -> invalid
   retlw   b'00010000' ; 101110 -> invalid
   retlw   b'00010000' ; 101111 -> invalid
   retlw   b'00010000' ; 110000 -> invalid
   retlw   b'00010000' ; 110001 -> invalid
   retlw   b'00010000' ; 110010 -> invalid
   retlw   b'00010000' ; 110011 -> invalid
   retlw   b'00010000' ; 110100 -> invalid
   retlw   b'00010000' ; 110101 -> invalid
   retlw   b'00010000' ; 110110 -> invalid
   retlw   b'00010000' ; 110111 -> invalid
   retlw   b'00010000' ; 111000 -> invalid
   retlw   b'00010000' ; 111001 -> invalid
   retlw   b'00010000' ; 111010 -> invalid
   retlw   b'00010000' ; 111011 -> invalid
   retlw   b'00010000' ; 111100 -> invalid
   retlw   b'00010000' ; 111101 -> invalid
   retlw   b'00010000' ; 111110 -> invalid
   retlw   b'00010000' ; 111111 -> invalid

tri_add_test MACRO B
   movlw   B
   call tri_add_3trits
   ENDM

; Ternary adder W+A_reg+BCF=A_reg and BCF (used tmp0,tmp1,tmp2,tmp3,tmp4,cnt1)
tri_adder:
   movwf   tmp0
   clrf   tmp4
   movlw   3
   movwf   cnt1
   movf   F_reg,w
   andlw   b'00110000'
   movwf   tmp1
tri_add_loop:
   movf   tmp0,w
   andlw   b'00110000'
   movwf   tmp2
   bcf   STATUS,C
   rrf   tmp2,f
   rrf   tmp2,w
   iorwf   tmp1,f
   movf   A_reg,w
   andlw   b'00110000'
   movwf   tmp2
   swapf   tmp2,w
   iorwf   tmp1,w
   call   tri_add_3trits
   movwf   tmp3
   andlw   b'00000011'
   iorwf   tmp4,f
   movf   tmp3,w
   andlw   b'00001100'
   movwf   tmp1
   rlf   tmp1,f
   rlf   tmp1,f
   decfsz   cnt1,f
   goto   tri_add_next
   movf   F_reg,w
   andlw   b'00001111'
   iorwf   tmp1,w
   movwf   F_reg
   movf   tmp4,w
   movwf   A_reg
   return
tri_add_next:
   rlf   tmp4,f
   rlf   tmp4,f
   rlf   tmp0,f
   rlf   tmp0,f
   rlf   A_reg,f
   rlf   A_reg,f
   goto   tri_add_loop


Сделал замеры - если эмулятор не только бежит по PC, но и постоянно складывает две триады (взятые из PC), то скорость проседает до 33000 операций в секунду! Принимаются предложения по оптимизации этого кода :roll:

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

_________________
:dj: https://mastodon.social/@Shaos


21 Nov 2011 22:14
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22412
Location: Silicon Valley
Reply with quote
Post 
Вот функция процедурного декодера кода операции:
Code:
; Perform single step of the program
tri_step:
   movlw   PC_h
   movwf   FSR
   call   tri_read
   movwf   C_reg
   call   tri_inc_pc3
   btfss   C_reg,0
   goto tri_step0
   ; Nxx
   btfss   C_reg,2
   goto   tri_step_0
   ; NNx
   btfss   C_reg,4
   goto   tri_step__0
   ; NNN (-13) SAN
   movlw   DPn_h
   movwf   FSR
   movf   A_reg,w
   call   tri_write
   return
tri_step__0:
   btfsc   C_reg,5
   goto   tri_step__1
   ; NNO (-12) SAO
   movlw   DPo_h
   movwf   FSR
   movf   A_reg,w
   call   tri_write
   return
tri_step__1:
   ; NNP (-11) SAP
   movlw   DPp_h
   movwf   FSR
   movf   A_reg,w
   call   tri_write
   return
tri_step_0:
   btfsc   C_reg,3
   goto   tri_step_1
   ; NOx
   btfss   C_reg,4
   goto   tri_step_00
   ; NON (-10) SAF
   movf   A_reg,w
   movwf   F_reg
   return
tri_step_00:
   btfsc   C_reg,5
   goto   tri_step_01
   ; NOO (-9) SPCD
   call   tri_cur_dp
   movf   PC_h,w
   movwf   INDF
   incf   FSR,f
   movf   PC_m,w
   movwf   INDF
   incf   FSR,f
   movf   PC_l,w
   movwf   INDF
   return
tri_step_01:
   ; NOP (-8) SAB
   movf   A_reg,w
   movwf   B_reg
   return
tri_step_1:
   ; NPx
   btfss   C_reg,4
   goto   tri_step_10
   ; NPN (-7) SAL
   call   tri_cur_dp
   goto   tri_step_sal
tri_step_10:
   btfsc   C_reg,5
   goto   tri_step_11
   ; NPO (-6) SAM
   call   tri_cur_dp
   goto   tri_step_sam
tri_step_11:
   ; NPP (-5) SAH
   call   tri_cur_dp
   goto   tri_step_sah
tri_step_sal:
   incf   FSR,f
tri_step_sam:
   incf   FSR,f
tri_step_sah:
   movf   A_reg,w
   movwf   INDF
   return
tri_step0:
   btfsc   C_reg,1
   goto   tri_step1
   ; Oxx
   btfss   C_reg,2
   goto   tri_step00
   ; ONx
   btfss   C_reg,4
   goto   tri_step0_0
   ; ONN (-4) RLA
   bcf   STATUS,C
   rlf   A_reg,f
   rlf   A_reg,f
   btfsc   F_reg,5
   bsf   A_reg,1
   btfsc   F_reg,4
   bsf   A_reg,0
   bcf   F_reg,5
   btfsc   A_reg,7
   bsf   F_reg,5
   bcf   A_reg,7
   bcf   F_reg,4
   btfsc   A_reg,6
   bsf   F_reg,4
   bcf   A_reg,6
   call   tri_rsf
   return
tri_step0_0:
   btfsc   C_reg,5
   goto   tri_step0_1
   ; ONO (-3) ADD
   movf   B_reg,W
   call   tri_adder
   call   tri_rsf
   return
tri_step0_1:
   ; ONP (-2) RRA
   btfsc   F_reg,5
   bsf   A_reg,7
   btfsc   F_reg,4
   bsf   A_reg,6
   bcf   STATUS,C
   rrf   A_reg,f
   btfsc   STATUS,C
   bsf   F_reg,4
   bcf   STATUS,C
   rrf   A_reg,f
   btfsc   STATUS,C
   bsf   F_reg,5
   call   tri_rsf
   return
tri_step00:
   btfsc   C_reg,3
   goto   tri_step01
   ; OOx
   btfss   C_reg,4
   goto   tri_step000
   ; OON (-1) LAI #
   call   tri_read1pc
   movf   tmp0,w
   movwf   A_reg
   return
tri_step000:
   btfsc   C_reg,5
   goto   tri_step001
   ; OOO (0) ADI #
   call   tri_read1pc
   movf   tmp0,w
   call   tri_adder
   call   tri_rsf
   return
tri_step001:
   ; OOP (1) OPA #
   call   tri_read1pc
   call   tri_opa
   movf   tmp1,w
   movwf   A_reg
   call   tri_rsf
   return
tri_step01:
   ; OPx
   btfss   C_reg,4
   goto   tri_step010
   ; OPN (2) LDI # # #
   call   tri_read3pc
   call   tri_cur_dp
   movf   tmp1,w
   movwf   INDF
   incf   FSR,f
   movf   tmp2,w
   movwf   INDF
   incf   FSR,f
   movf   tmp3,w
   movwf   INDF
   return
tri_step010:
   btfsc   C_reg,5
   goto   tri_step011
   ; OPO (3) JMP # # #
   call   tri_read3pc
   movlw   PC_h
   movwf   FSR
   movf   tmp1,w
   movwf   INDF
   incf   FSR,f
   movf   tmp2,w
   movwf   INDF
   incf   FSR,f
   movf   tmp3,w
   movwf   INDF
   return
tri_step011:
   ; OPP (4) OPB # # #
   call   tri_read3pc
   call   tri_opb
   movf   tmp0,w
   movwf   A_reg
   call   tri_rsf
   return
tri_step1:
   ; Pxx
   btfss   C_reg,2
   goto   tri_step10
   ; PNx
   btfss   C_reg,4
   goto   tri_step1_0
   ; PNN (5) LAN
   movlw   DPn_h
   movwf   FSR
   call   tri_read
   movwf   A_reg
   return
tri_step1_0:
   btfsc   C_reg,5
   goto   tri_step1_1
   ; PNO (6) LAO
   movlw   DPo_h
   movwf   FSR
   call   tri_read
   movwf   A_reg
   return
tri_step1_1:
   ; PNP (7) LAP
   movlw   DPp_h
   movwf   FSR
   call   tri_read
   movwf   A_reg
   return
tri_step10:
   btfsc   C_reg,3
   goto   tri_step11
   ; POx
   btfss   C_reg,4
   goto   tri_step100
   ; PON (8) LAF
   movf   F_reg,w
   movwf   A_reg
   return
tri_step100:
   btfsc   C_reg,5
   goto   tri_step101
   ; POO (9) LPCD
   call   tri_cur_dp
   movf   INDF,w
   movwf   PC_h
   incf   FSR,f
   movf   INDF,w
   movwf   PC_m
   incf   FSR,f
   movf   INDF,w
   movwf   PC_l
   return
tri_step101:
   ; POP (10) LAB
   movf   B_reg,w
   movwf   A_reg
   return
tri_step11:
   ; NPx
   btfss   C_reg,4
   goto   tri_step110
   ; PPN (11) LAL
   call   tri_cur_dp
   goto   tri_step_lal
tri_step110:
   btfsc   C_reg,5
   goto   tri_step111
   ; PPO (12) LAM
   call   tri_cur_dp
   goto   tri_step_lam
tri_step111:
   ; PPP (13) LAH
   call   tri_cur_dp
   goto   tri_step_lah
tri_step_lal:
   incf   FSR,f
tri_step_lam:
   incf   FSR,f
tri_step_lah:
   movf   INDF,w
   movwf   A_reg
   return


Сделал предварительные замеры - простейшие команды типа SAB выполняются порядка 82000 раз в секунду (примерно 12 мкс), чуть посложнее типа OPA или ADD - порядка 27000 раз в секунду (примерно 37 мкс), совсем сложные типа ADI - порядка 21000 раз в секунду (примерно 48 мкс). Это если запускать программу в пределах одной страницы, находящейся в регистрах - если же страница сидит в EEPROM, то к примеру производительность того же ADI падает до 16500 раз в секунду (60 мкс) - это из-за того что процесс чтения из EEPROM (которых в команде ADI два) это штука нетривиальная и требует некоторых странных телодвижений, отсутствующих при обращении к регистрам...

_________________
:dj: https://mastodon.social/@Shaos


Last edited by Shaos on 25 Nov 2011 02:41, edited 1 time in total.



23 Nov 2011 21:25
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22412
Location: Silicon Valley
Reply with quote
Post 
Вот подпрограммы для осуществления универсальных операций OPA и OPB:
Code:
; Perform OPA command on A_reg with code tmp0 and save result in tmp1 (used cnt1)
tri_opa:
   movlw   3
   movwf   cnt1
   clrf   tmp1
tri_opa_:
   btfss   A_reg,0
   goto   tri_opa1
   btfsc   tmp0,0
   bsf   tmp1,6
   btfsc   tmp0,1
   bsf   tmp1,7
   goto   tri_opa_loop
tri_opa1:
   btfss   A_reg,1
   goto   tri_opa0
   btfsc   tmp0,4
   bsf   tmp1,6
   btfsc   tmp0,5
   bsf   tmp1,7
   goto   tri_opa_loop
tri_opa0:
   btfsc   tmp0,2
   bsf   tmp1,6
   btfsc   tmp0,3
   bsf   tmp1,7
tri_opa_loop:
   bcf   STATUS,C
   rrf   tmp1,f
   rrf   tmp1,f
   rrf   A_reg,f
   rrf   A_reg,f
   decfsz   cnt1,f
   goto   tri_opa_
   return

; Perform OPB command on A_reg and B_reg with code tmp1,tmp2,tmp3 and save result in tmp0 (used tmp4,cnt1)
tri_opb:
   movf   tmp1,w
   movwf   tmp4
   movf   tmp3,w
   movwf   tmp0
   call   tri_opa
   movf   tmp1,w
   movwf   tmp3
   movf   tmp2,w
   movwf   tmp0
   call   tri_opa
   movf   tmp1,w
   movwf   tmp2
   movf   tmp4,w
   movwf   tmp0
   call   tri_opa
   clrf   tmp0
   btfss   B_reg,0
   goto   tri_opb_h1
   btfsc   tmp1,0
   bsf   tmp0,0
   btfsc   tmp1,1
   bsf   tmp0,1
   goto   tri_opb_m
tri_opb_h1:
   btfsc   B_reg,1
   goto   tri_opb_h0
   btfsc   tmp3,0
   bsf   tmp0,0
   btfsc   tmp3,1
   bsf   tmp0,1
   goto   tri_opb_m
tri_opb_h0:
   btfsc   tmp2,0
   bsf   tmp0,0
   btfsc   tmp2,1
   bsf   tmp0,1
tri_opb_m:
   btfss   B_reg,2
   goto   tri_opb_m1
   btfsc   tmp1,2
   bsf   tmp0,2
   btfsc   tmp1,3
   bsf   tmp0,3
   goto   tri_opb_l
tri_opb_m1:
   btfsc   B_reg,3
   goto   tri_opb_m0
   btfsc   tmp3,2
   bsf   tmp0,2
   btfsc   tmp3,3
   bsf   tmp0,3
   goto   tri_opb_l
tri_opb_m0:
   btfsc   tmp2,2
   bsf   tmp0,2
   btfsc   tmp2,3
   bsf   tmp0,3
tri_opb_l:
   btfss   B_reg,4
   goto   tri_opb_l1
   btfsc   tmp1,4
   bsf   tmp0,4
   btfsc   tmp1,5
   bsf   tmp0,5
   return
tri_opb_l1:
   btfsc   B_reg,5
   goto   tri_opb_l0
   btfsc   tmp3,4
   bsf   tmp0,4
   btfsc   tmp3,5
   bsf   tmp0,5
   return
tri_opb_l0:
   btfsc   tmp2,4
   bsf   tmp0,4
   btfsc   tmp2,5
   bsf   tmp0,5
   return


в железе они реализуются значительно проще...

замеры по скорости:
OPA - 26800 раз в секунду или 37 мкс
OPB - 11600 раз в секунду или 86 мкс

_________________
:dj: https://mastodon.social/@Shaos


24 Nov 2011 22:45
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22412
Location: Silicon Valley
Reply with quote
Post 
Ещё дополнительные подпрограммы для работы декодера команд:

Code:
; Read one triad from the address stored in 3 triads started from FSR and save result to W
tri_read:
; skip middle address for now...
   movf   INDF,w
   subwf   CA_h,w
   btfsc   STATUS,Z
   goto   tri_read_eep
   movf   INDF,w
   subwf   DA_h,w
   btfsc   STATUS,Z
   goto   tri_read_ram
   call   tri_fail
tri_read_eep:
   incf   FSR,f
   incf   FSR,f
   movf   INDF,w
   call   eeprom_read
   _bank0
   return
tri_read_ram:
   incf   FSR,f
   incf   FSR,f
   movf   INDF,w
   addlw   0x40
   movwf   FSR
   movf   INDF,w
   return

; Write one triad W to the address stored in 3 triads started from FSR (used tmp0)
tri_write:
; skip middle address for now...
   movwf   tmp0
   movf   INDF,w
   subwf   CA_h,w
   btfsc   STATUS,Z
   goto   tri_write_eep
   movf   INDF,w
   subwf   DA_h,w
   btfsc   STATUS,Z
   goto   tri_write_ram
   call tri_fail
tri_write_eep:
   incf   FSR,f
   incf   FSR,f
    movf  tmp0,w
    movwf  eeprom_write_value
   movf   INDF,w
   call   eeprom_write
   return
tri_write_ram:
   incf   FSR,f
   incf   FSR,f
   movf   INDF,w
   addlw   0x40
   movwf   FSR
   movf   tmp0,w
   movwf   INDF
   return

; Set current DP in FSR register
tri_cur_dp:
   btfss   F_reg,2
   goto   tri_cur_dp0
   movlw   DPn_h
   goto   tri_cur_dp_
tri_cur_dp0:
   btfsc   F_reg,3
   goto   tri_cur_dp1
   movlw   DPo_h
   goto   tri_cur_dp_
tri_cur_dp1:
   movlw   DPp_h
tri_cur_dp_:
   movwf   FSR
   return

; Set RSF (higher trit of the register F) based of the sign of the value in the register A
tri_rsf:
   btfsc   A_reg,0
   goto   tri_rsf_p
   btfsc   A_reg,1
   goto   tri_rsf_n
   btfsc   A_reg,2
   goto   tri_rsf_p
   btfsc   A_reg,3
   goto   tri_rsf_n
   btfsc   A_reg,4
   goto   tri_rsf_p
   btfsc   A_reg,5
   goto   tri_rsf_n
tri_rsf_o:
   bcf   F_reg,0
   bcf   F_reg,1
   return
tri_rsf_n:
   bsf   F_reg,0
   bcf   F_reg,1
   return
tri_rsf_p:
   bcf   F_reg,0
   bsf   F_reg,1
   return

; Read 1 immediate triad and save it in tmp0
tri_read1pc:
   movlw   PC_h
   movwf   FSR
   call   tri_read
   movwf   tmp0
   call   tri_inc_pc3
   return

; Read 3 immediate triads and save them in tmp1,tmp2,tmp3
tri_read3pc:
   movlw   PC_h
   movwf   FSR
   call   tri_read
   movwf   tmp1
   call   tri_inc_pc3
   movlw   PC_h
   movwf   FSR
   call   tri_read
   movwf   tmp2
   call   tri_inc_pc3
   movlw   PC_h
   movwf   FSR
   call   tri_read
   movwf   tmp3
   call   tri_inc_pc3
   return


P.S. Полный исходник смотреть тут:
https://gitlab.com/nedopc/pix/-/blob/master/16/t1_test3.asm
он почти в тысячу строк получился...

P.P.S. Подпрограмма tri_fail должна будет вводить систему в состояние фатальной ошибки - например путём переключения всех светодиодов в жёлтый цвет и зависания в этом состоянии...

_________________
:dj: https://mastodon.social/@Shaos


Last edited by Shaos on 25 Nov 2011 09:22, edited 1 time in total.



24 Nov 2011 22:51
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22412
Location: Silicon Valley
Reply with quote
Post 
Вот полная таблица длительностей выполнения каждой инструкции 3niti alpha в микросекундах из регистровой памяти (тут также можно видеть визуальное отличие длительностей):
Code:
NNN (SAN)     14 =====
NNO (SAO)     15 =====
NNP (SAP)     15 =====
NON (SAF)     11 ====
NOO (SPCD)    16 =====
NOP (SAB)     12 ====
NPN (SAL)     15 =====
NPO (SAM)     15 =====
NPP (SAH)     15 =====
ONN (RLA)     16 =====
ONO (ADD)     38 =============
ONP (RRA)     16 =====
OON (LAI #)   20 =======
OOO (ADI #)   48 ================
OOP (OPA #)   37 ============
OPN (LDI ###) 41 ==============
OPO (JMP ###) 38 =============
OPP (OPB ###) 86 =============================
PNN (LAN)     14 =====
PNO (LAO)     15 =====
PNP (LAP)     15 =====
PON (LAF)     12 ====
POO (LPCD)    17 ======
POP (LAB)     13 ====
PPN (LAL)     16 =====
PPO (LAM)     16 =====
PPP (LAH)     16 =====

Как видно самой быстрой командой является SAF (точное значение - 11.4 мкс или примерно 87400 раз в секунду), а самой медленной - OPB (точное значение - 86.2 мкс или примерно 11600 раз в секунду).

А вот тоже самое, но при чтении из EEPROM:
Code:
NNN (SAN)     21 =======
NNO (SAO)     21 =======
NNP (SAP)     22 =======
NON (SAF)     18 ======
NOO (SPCD)    23 =======
NOP (SAB)     19 ======
NPN (SAL)     22 =======
NPO (SAM)     22 =======
NPP (SAH)     22 =======
ONN (RLA)     25 ========
ONO (ADD)     46 ===============
ONP (RRA)     25 ========
OON (LAI #)   34 ===========
OOO (ADI #)   62 =====================
OOP (OPA #)   51 =================
OPN (LDI ###) 69 =======================
OPO (JMP ###) 66 ======================
OPP (OPB ###)113 ======================================
PNN (LAN)     28 =========
PNO (LAO)     29 =========
PNP (LAP)     29 =========
PON (LAF)     19 ======
POO (LPCD)    24 ========
POP (LAB)     20 =======
PPN (LAL)     22 =======
PPO (LAM)     23 ========
PPP (LAH)     23 ========

Как видно однотриадные команды стали дольше примерно на 7 мкс (одно чтение из EEPROM на команду), двухтриадные - на 14 мкс (два чтения из EEPROM на команду), а четырёхтриадные - на 28 мкс (четыре чтения из EEPROM на команду). Исключение составляют лишь команды LAN,LAO,LAP, которые содержат в себе неявное второе обращение к EEPROM. Также есть странная аномалия у RLA и RRA - они удлиннились не на 7, а на 9 мкс. Ещё интересно, что из-за этого неравномерного удлиннения команда ADI стала быстрее чем LDI и JMP. Теперь самая быстрая команда SAF выполняется 18.3 мкс (примерно 54400 раз в секунду), а самая долгая OPB - 113.3 мкс (примерно 8800 раз в секунду).

P.S. Обработка состояния переключателей и подсветка светодиодов добавляют около 7 мкс к каждой команде

P.P.S. Интересно, что прошивка, выполняющая все инструкции "3niti alpha" в двух страницах памяти и обрабатывающая почти всё управление (кроме возврата в главную программу M) влезла в оставленные от бутлоадера 671 байт практически в притык...

_________________
:dj: https://mastodon.social/@Shaos


25 Nov 2011 00:47
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22412
Location: Silicon Valley
Reply with quote
Post 
Эпопею с выкатыванием первой версии эмулятора можно считать законченной:

http://nedopc.org/nedopc/16/t1_test3.hex (3K)
http://nedopc.org/nedopc/16/t1_test3.asm (21K)
http://nedopc.org/nedopc/16/PDBLv1.zip (54K)

Прогон команды ADI # (код OOO) по всей памяти в 19,683 триад даёт примерно 52 мкс на команду (это при том, что реально данные читаются не во всех страницах). Также удалось впихнуть в прошивку хак - если переключатели W/R и I/M оба находятся в нижнем положении, то управление передаётся на бутлоадер PDBLv1, через который можно посмотреть состояние переменных и EEPROM.

Image

_________________
:dj: https://mastodon.social/@Shaos


26 Nov 2011 02:24
Profile WWW
Display posts from previous:  Sort by  
Reply to topic   [ 52 posts ]  Go to page Previous  1, 2, 3, 4  Next

Who is online

Users browsing this forum: No registered users and 5 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.