Dziś opiszę proces stworzenia programowalnego kardridża do komputera Atari 65XE. To jeden z tych projektów, które od zawsze chodziły mi po głowie ale nigdy nie miałem samozaparcia przysiąść i zgłębić temat tego komputera. No to teraz przyszła najlepsza okazja: pomysł powstał przy okazji naprawy tego komputera, a że chciałem przetestować jego działanie i nie miałem innych kardridży, postanowiłem stworzyć swój własny (nota bene - w komputerze uszkodzony był układ PAL, który zastąpiłem wykonaną protezą na układzie CPLD - mała żółta płytka na zdjęciu poniżej:
Atari 65XE to 8 bitowy komputer oparty na procesorze 6502. Tuż po uruchomieniu, zgłasza się do nas znakiem zachęty podobnym jak np. C65 czy Spectrum. W komputerze wbudowany jest mini-system operacyjny oraz BASIC, a do urządzenia można podłączyć zewnęrzne nośniki pamięci (kardridże) lub też magnetofon, drukarkę czy inne akcesoria. Mapę pamięci komputera przedstawia poniższy schemat:
Typowe kardridże możem w zasadzie podzielić na dwa rodzaje:
*XEGS (o pojemności 128 kB), które umieszczają swój kod w obszarze $8000-$9FFF oraz $A000-$BFFF, wyłączając na stałe wewnętrzną w komputerze pamięć. Zapisując pod adres $D5xx wartość, młodsze 4 bity określają numer banku, który będzie zmapowany pod $8000-$9FFF (pod $A000-$BFFF jest na stałe obecny ostatni, 15 bank)
*SXEGS - podobnie jak wyżej, ale kardridż taki dodatkowo może włączyć/wyłączyć wewnętrzną pamięć komputera w trakcie pracy (określa to bit 7 zapisywanej wartości $D500).
Dlaczego akurat $D5xx? Bo w złączu kardridża obecny jest sygnał, który przyjmuje wartość 0, gdy procesor odwołuje się do strony $D5 ($D500-$D5FF).
Jednym z podobnych projektów jest np. ten: https://www.elektroda.pl/rtvforum/topic3076370.html
ale do jego wykonania potrzeba układu PAL16V8. Ja postanowiłem zaprojektować i wykonać płytkę od zera, w oparciu o dyskretne elementy:
Jednak tak wykonany kardridż obsługiwał jedynie tryb XEGS, musiałem więc dodać dodatkowy rejestr, już po fakcie. Obecne przełączniki pozwalają wybrać jeden z czterech 128 kB zestawów gier (gry - pliki xex - można łączyć programem Creaxin1.exe i zaprogramować tak powstały plik wynikowy w pamięci za pomocą zewnętrznego programatora). Niestety, kardridż po wykonaniu nie działał, a ja szukałem przyczyny bezskutecznie.
Postanowiłem więc wykonać drugą wersje, tym razem opartą o układ CPLD - miał on po pierwsze służyć sprawdzeniu, czy logiczne połączenia w poprzedniej wersji były poprawne, a po drugie - być może w przyszłości użyję go także do realizacji dalszych pomysłów (kardridż, oprócz pamięci Flash posiada też SRAM, a prawie wszystkie linie ze złącza krawędziowego doprowadzone sę do CPLD).
Sporym wyzwaniem było zmieszczenie się na dwóch warstwach tak, aby sygnały dotarły zarówno do obu pamięci jak i układu CPLD, jednocześnie minimalizując liczbę przelotek i rozmiar pajęczyny ścieżek.
Ta wersja kardridża zadziałała od razu. Kod układu CPLD można opisać np tak:
Spoiler:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity atari65xe_cart is
Port ( a0 : in STD_LOGIC;
a1 : in STD_LOGIC;
a2 : in STD_LOGIC;
a3 : in STD_LOGIC;
a4 : in STD_LOGIC;
a5 : in STD_LOGIC;
a6 : in STD_LOGIC;
a7 : in STD_LOGIC;
a8 : in STD_LOGIC;
a9 : in STD_LOGIC;
a11 : in STD_LOGIC;
d : inout STD_LOGIC_VECTOR (7 downto 0);
prg_a13 : out STD_LOGIC;
prg_a14 : out STD_LOGIC;
prg_a15 : out STD_LOGIC;
prg_a16 : out STD_LOGIC;
rd4 : out STD_LOGIC;
rd5 : out STD_LOGIC;
ns4 : in STD_LOGIC;
ns5 : in STD_LOGIC;
phi2 : in STD_LOGIC;
ncctl : in STD_LOGIC;
rnw : in STD_LOGIC;
nrom : out STD_LOGIC;
nram : out STD_LOGIC;
wnr : out STD_LOGIC);
end atari65xe_cart;
architecture Behavioral of atari65xe_cart is
signal bank : std_logic_vector(3 downto 0);
signal en : std_logic := '0'; --important
begin
process (phi2) is begin
if falling_edge(phi2) and rnw = '0' and ncctl = '0' then
bank <= d(3 downto 0);
en <= d(7);
end if;
end process;
nram <= '1';
nrom <= '0' when (ns4 = '0' or ns5 = '0') else '1';
wnr <= not rnw;
prg_a13 <= bank(0) when ns4 = '0' else '1';
prg_a14 <= bank(1) when ns4 = '0' else '1';
prg_a15 <= bank(2) when ns4 = '0' else '1';
prg_a16 <= bank(3) when ns4 = '0' else '1';
rd4 <= not en;
rd5 <= not en;
end Behavioral;
Wszystko więc potwierdziło, że pierwszy kardridż został wykonany poprawnie, jednak wciąż nie znając przyczyny jego niedziałania, stworzyłem prostą przejściówkę, umożliwiającą podłączenie go do krzysio-kazzo (adaptera-emulatora-debuggera kardridży do Pegasusa, nieodzownego przy analizie uszkodzonych nośników):
Odczyty pamięci za pomocą adaptera zwracały różną zawartość. Potem przez przypadek zmierzyłem, że np. w przypadku, gdy !SE4 i !SE5 mają oba wartość 1, pamięć w kardridżu nadal jest aktywna (a nie powinna). Już nawet myślałem, że gdzieś jest jakieś mikro-zwarcie czy wręcz uszkodzony scalak 7406 (6x inwerter), bo za równo na jednym z jego wejść jak i na odpowiadającym mu wyjściu był stan niski. Potem dopiero mnie olśniło, że ten układ ma wyjścia typu otwarty kolektor. Zamiana na 7404 (ten sam rozkład wyprowadzeń) rozwiązała problem i kardridż od razu ruszył.
Przydała się też, już wcześniej wykonana, przejściówka padów Pegasus->C64:
W ferworze walki zdobyłem sporo wiedzy na temat działania tego już prawie muzealnego komputerka, a przy okazji był to dość ciekawie (edukacyjnie) spędzony czas.
Fajne? Ranking DIY