Ten artykuł ma raczej cel edukacyjny. Jednak na podstawie tej wiedzy można opracować retro komputer, np. ZX Spectrum.
Każdy, kto miał do czynienia z pierwszymi 8-bitowcami na początku ery komputerowej, chyba pamięta, że budowa takiego sprzętu własnymi siłami wiązała się z poważnym problemem — koniecznością zaprogramowania pamięci ROM. Był potrzebny programator i czasem nawet kasowarka UV. Minęło sporo lat, a obecnie powstał dodatkowy kłopot z dostępnością kostek pamięci typu 27C128 itp.
Budowa retro sprzętu: Arduino jako EPROM
Jednak w tym momencie mamy Arduino, za którego pomocą można emulować pamięć ROM. Taka opcja pozwala szybko zmienić kod oprogramowania bez konieczności stosowania programatora i kasowarki UV. Tak naprawdę jeszcze nie realizowałem retro sprzętu, stosując to rozwiązanie, ale nie widzę przeszkód w dalszym rozbudowaniu tego projektu, aż do pełnoprawnego komputera.
Najpierw tradycyjnie spróbujemy sterować diodą świecącą za pomocą procesora Z80 oraz kodu zapisanego w pamięci Arduino, służącej pamięcią EPROM. Napiszemy dla tego krótki kod na assemblerze.
W ten sposób przy załadowaniu tego kodu do pamięci na wyjściu portu FF (procesora Z80) będzie się zmieniać stan od 0 do 1. Czyli podłączona do tego portu dioda będzie migać. Jednak częstotliwość jest za wysoka, żeby to zauważyć. Dlatego, tak samo jak w szkicach do Arduino, mamy dodać komendę opóźnienia (delay). Modyfikujemy kod w ten sposób:
Wartość 0 oznacza, że 8-bitowy procesor wypełni 254 cykli przed zamianą stanu portu FF. To też jest za mało, ażeby to zauważyć. Jednak zmiany zrobimy trochę później.
Teraz kompilujemy w język maszynowy i mamy taki kod: 3E 00 D3 FF 06 00 10 FE 3E 01 D3 FF 06 00 10 FE C3 00 00. Jak widać, zajmuje on 19 bajtów. Ja zaś dla eksperymentów i uproszczenia podłączenia Arduino do procesora Z80 chciałbym używać tylko 4 linie szyny adresowej. Czyli 16 bajtów. Nie bardzo znam się na assemblerze, ale według bardziej doświadczonego fachowca, można wyrzucić komendę: „LD B,0”, bo DJNZ $ powoduje powtarzanie tego rozkazu. Odzyskujemy 17 bajtów. Dalej można przerobić LD B,0 na CPL, która inwertuje bity. Te, które wcześniej zawierały 1, zostaną zmienione na 0, a te, które uprzednio zawierały 0, zostaną zmienione na 1. Oprócz tego JP,0 można przerobić na JR.
Po kompilacji uzyskujemy następny kod: 3E 00 D3 FF 06 00 10 FE 2F D3 FF 10 FE 18 F1 (w kodzie binarnym: 00111110 00000000 11010011 11111111 00000110 00000000 00010000 11111110
00101111 11010011 11111111 00010000 11111110 00011000 11110001). Zajmuje on tylko 15 bajtów. Więc, jak na razie, pasuje do naszych celów. Ten kod przekazujemy do procesora Z80 za pomocą takiego szkicu:
Weryfikacja działania całości
Przed podłączeniem procesora możemy sprawdzić, jak bardzo poprawnie pracuje ten program. Można dla tego wykonać prosty schemat na płytce podkładowej. Oprócz Arduino Nano schemat zawiera 4 przyciski (do określenia adresów oraz komendy), a także 8 diod świecących, które będą wyświetlać dane w kodzie binarnym. Całość wygląda następująco:
Po włączeniu diody świecą w połowie mocy, bo wyjścia są w nieokreślonym stanie. Po naciśnięciu przycisku CS-OE diody muszą pokazać stan bitów pod adresem zera. Czyli 00111110, co w kodzie HEX oznacza 3E. Trzymając przycisk CS-OE, naciskamy KEY4, czyli sprawdzając adres 0001, w ten sposób odzyskujemy 00000000. Naciskamy KEY3 0010 i mamy 11010011, czyli D3. I tak dalej, zgodnie z tablicą:
Jeżeli test się zgadza, możemy podłączyć procesor Z80, według schematu poniżej, który uruchomi program, uzyskany z pamięci ROM w postaci Arduino NANO i zaświeci dioda. Magistrala danych procesora jest podłączona wprost do pinów D0-D7, magistrala adresów — do pinów D8-D11. Wejście OE ROM-u — do wyjścia RD (niski poziom oznacza, że procesor będzie czytał dane z pamięci) procesora. Wejście CS zaś do wyjścia MREQ (niski poziom oznacza, że procesor żąda kontaktu z pamięcią i że szyna adresów zawiera już stabilny adres).
Jak widać, oscylator taktowy IC2.1-2 działa na bardzo niskiej częstotliwości (ok. 400 Hz). To wystarczy dla eksperymentów, ale w praktyce niczego nam nie daje. Problem polega na tym, że Arduino z tym szkicem pracuje dużo wolniej niż normalny ROM. W tym przypadku lepiej napisać odpowiedni program w assemblerze przystosowany dla kontrolerów Atmega i stosować oscylator na normalną częstotliwość. Tak naprawdę ja, póki co, tego nie potrafię. Moim celem było jednak zachęcić początkujących do edukacji w zakresie wiedzy komputerowej.
Każdy, kto miał do czynienia z pierwszymi 8-bitowcami na początku ery komputerowej, chyba pamięta, że budowa takiego sprzętu własnymi siłami wiązała się z poważnym problemem — koniecznością zaprogramowania pamięci ROM. Był potrzebny programator i czasem nawet kasowarka UV. Minęło sporo lat, a obecnie powstał dodatkowy kłopot z dostępnością kostek pamięci typu 27C128 itp.
Budowa retro sprzętu: Arduino jako EPROM
Jednak w tym momencie mamy Arduino, za którego pomocą można emulować pamięć ROM. Taka opcja pozwala szybko zmienić kod oprogramowania bez konieczności stosowania programatora i kasowarki UV. Tak naprawdę jeszcze nie realizowałem retro sprzętu, stosując to rozwiązanie, ale nie widzę przeszkód w dalszym rozbudowaniu tego projektu, aż do pełnoprawnego komputera.
Najpierw tradycyjnie spróbujemy sterować diodą świecącą za pomocą procesora Z80 oraz kodu zapisanego w pamięci Arduino, służącej pamięcią EPROM. Napiszemy dla tego krótki kod na assemblerze.
Kod: x86 Assembly
W ten sposób przy załadowaniu tego kodu do pamięci na wyjściu portu FF (procesora Z80) będzie się zmieniać stan od 0 do 1. Czyli podłączona do tego portu dioda będzie migać. Jednak częstotliwość jest za wysoka, żeby to zauważyć. Dlatego, tak samo jak w szkicach do Arduino, mamy dodać komendę opóźnienia (delay). Modyfikujemy kod w ten sposób:
Kod: x86 Assembly
Wartość 0 oznacza, że 8-bitowy procesor wypełni 254 cykli przed zamianą stanu portu FF. To też jest za mało, ażeby to zauważyć. Jednak zmiany zrobimy trochę później.
Teraz kompilujemy w język maszynowy i mamy taki kod: 3E 00 D3 FF 06 00 10 FE 3E 01 D3 FF 06 00 10 FE C3 00 00. Jak widać, zajmuje on 19 bajtów. Ja zaś dla eksperymentów i uproszczenia podłączenia Arduino do procesora Z80 chciałbym używać tylko 4 linie szyny adresowej. Czyli 16 bajtów. Nie bardzo znam się na assemblerze, ale według bardziej doświadczonego fachowca, można wyrzucić komendę: „LD B,0”, bo DJNZ $ powoduje powtarzanie tego rozkazu. Odzyskujemy 17 bajtów. Dalej można przerobić LD B,0 na CPL, która inwertuje bity. Te, które wcześniej zawierały 1, zostaną zmienione na 0, a te, które uprzednio zawierały 0, zostaną zmienione na 1. Oprócz tego JP,0 można przerobić na JR.
Kod: x86 Assembly
Po kompilacji uzyskujemy następny kod: 3E 00 D3 FF 06 00 10 FE 2F D3 FF 10 FE 18 F1 (w kodzie binarnym: 00111110 00000000 11010011 11111111 00000110 00000000 00010000 11111110
00101111 11010011 11111111 00010000 11111110 00011000 11110001). Zajmuje on tylko 15 bajtów. Więc, jak na razie, pasuje do naszych celów. Ten kod przekazujemy do procesora Z80 za pomocą takiego szkicu:
Kod: Arduino
Weryfikacja działania całości
Przed podłączeniem procesora możemy sprawdzić, jak bardzo poprawnie pracuje ten program. Można dla tego wykonać prosty schemat na płytce podkładowej. Oprócz Arduino Nano schemat zawiera 4 przyciski (do określenia adresów oraz komendy), a także 8 diod świecących, które będą wyświetlać dane w kodzie binarnym. Całość wygląda następująco:
Po włączeniu diody świecą w połowie mocy, bo wyjścia są w nieokreślonym stanie. Po naciśnięciu przycisku CS-OE diody muszą pokazać stan bitów pod adresem zera. Czyli 00111110, co w kodzie HEX oznacza 3E. Trzymając przycisk CS-OE, naciskamy KEY4, czyli sprawdzając adres 0001, w ten sposób odzyskujemy 00000000. Naciskamy KEY3 0010 i mamy 11010011, czyli D3. I tak dalej, zgodnie z tablicą:
0000:3E ORG (0)
0001:00
0002:D3 OUT (0FFh),A
0003: FF
0004:06 LD B,0
0005:00
0006:10 DJNZ $
0007:00
0008:2F CPL
0009: D3 OUT (FF),A
000A:FF
000B:10 DJNZ $
000C:FE
000D:18 JR 0
000E:F1
Jeżeli test się zgadza, możemy podłączyć procesor Z80, według schematu poniżej, który uruchomi program, uzyskany z pamięci ROM w postaci Arduino NANO i zaświeci dioda. Magistrala danych procesora jest podłączona wprost do pinów D0-D7, magistrala adresów — do pinów D8-D11. Wejście OE ROM-u — do wyjścia RD (niski poziom oznacza, że procesor będzie czytał dane z pamięci) procesora. Wejście CS zaś do wyjścia MREQ (niski poziom oznacza, że procesor żąda kontaktu z pamięcią i że szyna adresów zawiera już stabilny adres).
Jak widać, oscylator taktowy IC2.1-2 działa na bardzo niskiej częstotliwości (ok. 400 Hz). To wystarczy dla eksperymentów, ale w praktyce niczego nam nie daje. Problem polega na tym, że Arduino z tym szkicem pracuje dużo wolniej niż normalny ROM. W tym przypadku lepiej napisać odpowiedni program w assemblerze przystosowany dla kontrolerów Atmega i stosować oscylator na normalną częstotliwość. Tak naprawdę ja, póki co, tego nie potrafię. Moim celem było jednak zachęcić początkujących do edukacji w zakresie wiedzy komputerowej.
Fajne? Ranking DIY