Elektroda.pl
Elektroda.pl
X
Please add exception to AdBlock for elektroda.pl.
If you watch the ads, you support portal and users.

Mikrokomputer COBRA 1

coberr 06 Jun 2016 22:39 219252 1263
Computer Controls
  • #211
    zdzis_ek
    Level 16  
    Masz rację coberr, najpierw wersja podstawowa a później eksperymenty.
    Sterowanie pamięci dynamicznych typu 4464 planuję zrealizować tak:
    Mikrokomputer COBRA 1
    Można pozbyć się problemu z sygnałem CAS i zastosować pamięci statyczne.
    Tutaj koledzy z wysp proponują takie rozwiązanie:
    Mikrokomputer COBRA 1

    Dodano: 24.06.2016 r.

    Cobra1 też kibicuje polskim piłkarzom.


  • Computer Controls
  • #212
    wieswas
    Level 34  
    Przypadkiem i z miłym zaskoczeniem natrafiłem na temat Mikrokomputer COBRA 1.
    Przed 30 laty też zbudowałem go i obecnie znajduje się w Muzeum Historii Komputerów i Informatyzacji w Katowicach.
    Mikrokomputer COBRA 1

    Po uruchomieniu podstawowej wersji dorobiłem emulator ZX SPECTRUM
    (mapowane na przemian z COBRĄ : ROM SPECTRUM, pamięć statyczna wyświetlacza SPECTRUM, generacja dźwięku )
    Zastosowałem oczywiście oryginalne adresowanie ZX SPECTRUM oraz kolor z wyjściem RGB (monitorowe)

    Poprzez porty I/O COBRY podłączyłem 3-kanałowy syntezator dźwięku na AY-3-8910, stosowany kiedyś w Amstradzie CPC. Generacja dźwięku nie zajmowała czasu procesora, gdyż wystarczyło do rejestrów wejściowych tego scalaka wpisywać ustawienia, a AY sam generował dźwięk z odpowiednim kształtem, obwiednią i czasem trwania i to niezależnie w 3 kanałach.

    Pod klawiaturę podłączyłem gniazdko joysticka (4styki kierunku + ENTER)

    Miałem też rozpoczęte inne dodatki jak: TIMER, dodatkową kartę wyświetlacza w oparciu o scalak karty HERCULES z PC, ale po kupnie PC tego już nie dokończyłem.

    Czytając cały ten temat nie zauważyłem uwagi na temat błędu układu wyświetlania oryginalnej COBRY. Chodzi o kolizję odczytu z zapisem pamięci statycznej. Objawiało się to dużą ilością poziomych, białych kresek o szerokości 8 pikseli podczas szybkiego przewijania zawartości ekranu.
    Nie jest to błąd, tylko uproszczenie układu przez konstruktorów.
    W swojej COBRZE wykorzystując niewykorzystane bramki znajdujące się na płycie oraz dokładając UCY7474 blokowałem zapis do pamięci ekranu podczas impulsów odczytu. Zapis był możliwy tylko podczas impulsu wygaszania H i V.
    Początkowo odblokowałem tylko czas impulsu ramki, ale to wyraźnie spowalniało komputer, przy szybkich zmianach zawartości ekranu (około 40%).
    Po umożliwieniu zapisu do pamięci w trakcie impulsów wygaszania poziomego spowolnienie stało się niezauważalne, a zakłóceń nie było.
    Niestety nie mam już żadnych notatek dotyczących moich modyfikacji, ale analiza układu umożliwia prostą realizację tej przeróbki. Zapis trwa bardzo krótko w porównianiu z czasem impulsów V i H.

    Miałem też około 30 gier i programów samodzielnie napisanych w kodzie maszynowym Z-80 i kilka w BASICU. Korespondując (nie było wówczas internetu) wymieniałem się kasetami z innymi użytkownikami, więc może gdzieś się jeszcze zachowały (Gwiezdne wojny, Jumping Jack, Wyścig samochodowy, Glizda, Labirynt, Horoskop, Tenis, Hokej, Klocki - tyle pamiętam)

    Do ponownej budowy tego samego brak mi już zapału, ale chętnie pobawię się emulatorem programowym COBRY na PC.
    Życzę powodzenia i gratuluję zapału obecnym konstruktorom.

    PS. Chciałbym uzyskać odpowiedź na kilka pytań dotyczących emulatora COBRY:
    -Czy wszystkie kody maszynowe Z80 użyte we własnym programie napisanym w kodzie HEX jednakowo działają zarówno w emulatorze jak i oryginalnej konstrukcji COBRY ? Czy czasy wykonywania pętli też są zachowane ?
    -Jaką procedurą sprawdzać wciśnięcie klawisza? (nie chodzi o BASIC tylko własny program w kodzie maszynowym).
    Czy należałoby użyć dwóch przełączanych procedur (jedną dla emulatora a inną dla harwarowej wersji COBRY ?
    Kiedyś miałem rozpracowane wszystkie podprogramy EPROMU MONITOR i opisane adresy uruchamiania np. procedury przeglądania klawiatury i rozkaz RET powodował powrót do mojego programu z numerem wciśniętego klawisza w akumulatorze. Obecnie nie mam już tamtych notatek i zaczynam od zera.
    Może ktoś zna adres startowy tej procedury ?
  • #213
    zdzis_ek
    Level 16  
    Napisałem program w Basicu Cobry1.
    Jest to gra logiczna "Juxto", której animację zaprezentowałem wcześniej.
    Gra posiada 9 plansz z puzlami.
    Widok gry i wszystkich 9 plansz pokazuje filmik poniżej.



    Wzbogaci ona nieco dość ubogą bibliotekę programów do Cobry1.
    Niestety gra wykorzystuje dodatkowe znaki semigraficzne.
    Wsad do epromu udostępniłem jakiś czas temu.
    Więc kto chce skorzystać z tego programu będzie musiał przeprogramować generator znaków.
    Myślę, że warto, bo gra prezentuje się dobrze.
    Jeżeli jeszcze coś napiszę w Basicu, to z pewnością z wykorzystaniem tych dodatkowych znaków.
    Gra do pobrania w załączniku.

    Pozdrawiam.
  • #214
    andrzejlisek
    Level 29  
    :arrow:zdzis_ek
    Sprawdziłem tą grę na swoim emulatorze i działa poprawnie, sama gra jest dosyć trudna.

    Odnalazłem ten post, w którym udostępniłeś wsad do generatora znaków. Rzeczywiście, zgodnie z tym, co tam pisałeś, zagospodarowałeś kody od 195 do 255.

    Jednakże, pojawiły się polskie litery i niektóre znaki z zakresu od 0 to 31 też sa inne. Czy to Ty zmodyfikowałeś, czy taki wsad zastałeś? Ja zrobiłem generator w emulatorze według istniejącej dokumentacji.
  • #215
    sq6fmy
    Level 22  
    @wieswas Potwierdzam istnienie kolizji w układzie video (moje PCB to replika), było dla mnie dziwnie, że nikt o tym nie wspomniał ale po analizie schematu zrozumiałem, że tak ma być.
  • #216
    wieswas
    Level 34  
    Schemat modyfikacji układu sterowania pamięcią statyczną wyświetlacza wysyłałem już prawie 30 lat temu użytkownikom COBRY, z którymi prowadziłem korespondencję, a także wysłałem redakcji czasopisma AudioVideo.
    Cykl artykułów na temat COBRY się jednak zakończył i nie wiem czy ktoś to zastosował.
    Obecnie nie mam już notatek z tego okresu. Na oryginalnej płycie COBRY są niewykorzystane bramki. Wykorzystałem je do tej modyfikacji łącząc kynarem.
    Przy impulsach H miałem problem z opóźnieniem wprowadzanym przez bramki.
    Zastosowałem więc "trik", że impuls H sterował więc blokadą następnego impulsu H poprzez celowe opóźnienie, a nie własnego.
    Analiza układu wykazała, że powinienem zablokować chwilę przed zakończeniem impulsu H, aby układ zdążył zareagować i nie wystąpiła kolizja. Odstęp między impulsami H jest znany i stały. Można więc go opóźnić o czas krótszy od taktu jednej linii. Bez tego sposobu sporadycznie pojawiały się nadal pojedyńcze zakłócenia. Po tym "triku" zero kolizji.

    Przy okazji chciałbym wspomnieć o jeszcze jednej modyfikacji:
    Oryginalny układ dźwięku uruchamiany instrukcją mikroprocesora Z-80 OUT(1B),A
    co w kodzie hexadecymalnym reprezentują dwa bajty: D3, 1B uruchamia BEEP o stałej częstotliwości generowanej przez multiwibrator na bramkach NAND 7400 (bramka 115c i 115d) oraz stałym czasie trwania wymuszonym przez układ 74121 (nr 106 na schemacie). W swojej COBRZE wykorzystałem inny bit portu wyjściowego podłączony do scalaka 7474 pracującego jako dzielnik przez 2.
    Instrukcja OUT(PORT),A podawana w pętli czasowej przerzucała stany wyjściowe 7474 , które były zsumowane na tranzystorze sterującym głośnikiem.
    Umożliwiało to generowanie dowolnego dźwięku 1-bitowego o dowolnej częstotliwości i dowolnym czasie trwania. Można więc było płynnie zmieniać wysokości dźwięku dokładnie tak jak robił to ZX SPECTRUM. Moje programy używały więc według potrzeby i BEEP i ten dodatkowy sposób generowania dźwięku. Aby nie spowalniać wydajności Z-80 w pętlach generujących dźwięk nie wstawiałem bezproduktywnego liczenia taktów, tylko konkretne procedury np. graficzne o znanej ilości taktów adekwatnej do wymaganego okresu częstotliwości akustycznej.
  • Computer Controls
  • #218
    PAMPKIN
    Level 12  
    andrzejlisek wrote:
    :arrow:zdzis_ek
    Sprawdziłem tą grę na swoim emulatorze i działa poprawnie, sama gra jest dosyć trudna.

    Odnalazłem ten post, w którym udostępniłeś wsad do generatora znaków. Rzeczywiście, zgodnie z tym, co tam pisałeś, zagospodarowałeś kody od 195 do 255.

    Jednakże, pojawiły się polskie litery i niektóre znaki z zakresu od 0 to 31 też sa inne. Czy to Ty zmodyfikowałeś, czy taki wsad zastałeś? Ja zrobiłem generator w emulatorze według istniejącej dokumentacji.


    zdzis_ek wrote:
    @andrzejlisek, ja zakupiony w tamtym czasie eprom miałem już z polskimi znakami.
    To co było podane w AV, to jakaś pierwsza wersja generatora znaków.


    Oto załącznik z oficjalnej książki na temat BASIC'a i samej Cobry 1 wydanej przez WNT w 1986 r.

    Załączam także spakowane skany w lepszej rozdzielczości (300 dpi).

    Mikrokomputer COBRA 1 Mikrokomputer COBRA 1 Mikrokomputer COBRA 1
  • #219
    jackfinch
    Level 17  
    Witam
    Miałem kiedyś te książkę, jak i wszystkie numery Audio-Video z opisem Cobry ale niestety książka gdzieś zaginęła. Czy możesz zeskanować tę książkę i wrzucić gdzieś na jakiś serwer np: typu dropbox?
    Pozdrawiam
  • #220
    PAMPKIN
    Level 12  
    jackfinch wrote:
    Witam
    Miałem kiedyś te książkę, jak i wszystkie numery Audio-Video z opisem Cobry ale niestety książka gdzieś zaginęła. Czy możesz zeskanować tę książkę i wrzucić gdzieś na jakiś serwer np: typu dropbox?
    Pozdrawiam


    Cześć,

    W wolej chwili postaram się to zrobić. Porządkuję właśnie bibliotekę na temat Cobry 1 i może jeszcze się coś znajdzie czego tutaj nie ma.
  • #221
    andrzejlisek
    Level 29  
    Ja też mam tą książeczkę i całą ją zeskanowałem.

    Jeśli chodzi o generator znaków, to ten udostępniony przez Zdzis_ek wydaje się być bardziej użyteczny, tym bardziej, że oprócz dodatkowych od 192 do 255, taki był sprzedawany. Mam na myśli to, że są polskie litery i że jest pełny komplet semigrafiki 4x4 taki sam, jak w ZX Spectrum. Oczywiście, te dodatkowe znaki również się przydadzą.

    Jeśli chodzi o generator z dokumentacji, to kilka postów wyżej pisałem o możliwych błędach w pojedynczych bajtach, w sumie zmieniłem wartość 5 bajtów i wszystkie znaki wyglądają lepiej.

    Czy prawdziwy komputer Cobra ma zdolność wyświetlania raz czarnych liter na białym tle, a raz białych na czarnym tle na jednym obrazie? Tylko wtedy teoretycznie można było korzystać z semigrafiki 4x4, bo w zestawie znaków jest pierwsze 8, a drugie 8 dorobiłoby się przez użycie negatywu w miejscach, w których są te znaki.
  • #222
    wieswas
    Level 34  
    W oryginalnej COBRZE pozytyw/negatyw ustawiało się za pomocą zwory przełączającej wyjście UCY74165 (układ nr. 109)
    W swoim komputerze wyprowadziłem przełącznik na zewnątrz obudowy.
    Nic nie stoi na przeszkodzie, aby te dwa wyjścia przełączać dodatkowymi bramkami, których aktywność byłaby zależna od przerzutnika (np. 1/2 7474) ustawianego portem wyjściowym instrukcją programową OUT(port).
    Oczywiście przełączanie pozytyw/negatyw dotyczy całego ekranu, a nie pojedynczych znaków.

    Miałbym prośbę do twórców emulatora. Czy mógłby ktoś dołożyć obsługę dźwięku kompatybilnego z ZX SPECTUM. To wzbogaciłoby ogromnie COBRĘ o muzykę podczas gier. Kompatybilność umożliwiłaby wykorzystanie ogromnej ilości efektów dźwiękowych i muzyki zczytanych bezpośrednio z kodów maszynowych gier ZX SPECTRUM. Dla posiadaczy oryginalnej COBRY wystarczyłoby kynarem wyprowadzić sygnał z określonego portu i sterować nim przerzutnik w układzie podziału przez 2, którego wyjście przez opornik sterowałoby bezpośrednio tranzystor głośnika.
  • #223
    andrzejlisek
    Level 29  
    Akurat wczoraj doimplementowałem do emulatora uproszczoną obsługę dwóch drukarek opisanych w AudioVideo. Uproszczenie polega na tym, że przy odczycie drukarki zawsze jest zwracany stan odpowiadający bezczynności lub oczekiwaniu na następny znak. Pomimo tego druk (a właściwie wyprowadzenie tekstu do pola tekstowego) działa poprawnie. Był jeszcze opis obsługi dalekopisu, ale uznałem, że jego implementacja nie ma sensu, bo po pierwsze jest to dużo bardziej skomplikowane, po drugie, jest to dokładnie to samo, tylko, że inny sposób sterowania drukiem jednego znaku od strony komputera. Głównym celem implementacji drukarki była możliwość wyprowadzenia kodu programu Basic wczytanego z nagrania audio. Wtedy odpada próba przetłumaczenia nagrana na ciąg znaków lub wydobywanie tekstu ze zrzutu pamięci. Dorobiłem też wprowadzanie znaków (keystrokes) z pola tekstowego, które w praktyce jest bardziej potrzebne niż wprowadzanie znaków z pliku.

    Skoro wieswas pisze o implementacji dźwięku takiego samego, jak w ZX Spectrum, to jak najbardziej, jest to możliwe, ale przede wszystkim potrzebuję informacji, jak jest ten dźwięk generowany od strony programu, tzn, jaki rozkaz powoduje wygenerowanie dźwięku i jak ustala się jego brzmienie (o ile jest to możliwe). Mając program i informację, co powinienem usłyszeć, będę w stanie zaimplementować obsługę dźwięku. Ja sam nigdy nie programowałem dźwięku w ZX Spectrum, ani nie mam info, jak się go programuje. Poszukam w Google, myślę, że znalazłbym szczegółowe info. Czy to jest tak, że okres czasowy dźwięku (który jest odwrotnie proporcjonalny do częstotliwości) trwa pewien stały odcinek czasu pomnożony przez wartość wystawioną na określony adres? W ten sposób działa pozytywka do CA80.

    Emulator udostępnię w ciągu kilku dni, możliwe, że już z dźwiękiem ZX Spectrum.
  • #224
    wieswas
    Level 34  
    W ZX SPECTRUM wysyła się na port OUT(FE),A zawartość akumulatora naprzemian 04 i 00. Oznacza to, że jedynie bit 4 liczby wysłanej na ten port jest połączony z głośniczkiem tworząc falę prostokątną o częstotliwości zależnej od częstotliwości wywoływania instrukcji OUT(FE),A
    W hardwarowej wersji Cobry jest to banalnie proste, ale w emulatorze na PC może być nieco trudniej, gdyż emulator musi po napotkaniu instrukcji w realizowanym kodzie maszynowym ciągu liczb D3,FE czyli OUT(FE),A
    - przeczytać zawartość akumulatora
    - sprawdzić czy bit 4 akumulatora jest 1 - wówczas wysłać na głośnik stan H i pamiętać go, aż do chwili gdy w kodzie maszynowym programu (gry) znów pojawi się ciąg D3,FE. Jeżeli znów wystąpi 1 (tylko wówczas, gdy programista omyłkowo zrobił błąd w programie) to nic nie zmieniaj.
    Jeżeli po wykryciu D3,FE w akumulatorze 4 bit jest zerem, to wyślij na głośnik stan L. Starałem się opisać w miarę precyzyjnie algorytm działania emulatora po napotkaniu instrukcji OUT(FE),A (4bit=1 lub 4bit=0)
    Nie mam pojęcia jak w PC wysłać stan H i L na głośniczek PC lub kartę dźwiękową.
    Dodatkowo to musi się odbywać w krótkim czasie , gdyż między tymi instrukcjami należy realizować setki innych.

    W ZX SPECTRUM inne bity wysłane na ten port realizują inne funkcje.
    W COBRZE nie są używane. Może więc uprościć i nie sprawdzać tego bitu ?
    Taka uproszczona wersja przesyłałaby na głośnik lub kartę dźwiękową naprzemian stan H i L po każdym napotkaniu w programie instrukcji mikroprocesora Z-80 : OUT(FE),A z obojętnie jaką zawartością akumulatora.
  • #225
    andrzejlisek
    Level 29  
    W moim emulatorze są dwie procedury, jedna uruchamiana przy każdym rozkazie OUT, druga przy każdym rozkazie IN. Ta procedura już określa zachowanie w zależności od adresu i wartości podanej w rozkazie. Biblioteka Qt już zapewnia obsługę dźwięku karty dźwiękowej, jednakże dźwięk musi być buforowany, co objawia się krótkim opóźnieniem w stosunku do zdarzeń generujących dźwięk.

    Na przykład, okres dźwięku 500Hz trwa 0,002 sekundy. Czy dobrze rozumiem, że jeżeli wykonam rozkaz OUT (FE), A przy A=04, a po czasie 0,001 sekundy wykonam rozkaz OUT (FE), A przy A=00, a po kolejnym 0,001 znowu będzie rozkaz OUT (FE), A przy A=04, to usłyszę dźwięk 500Hz z wypełnieniem 50%?

    A jak wyślę rozkaz OUT (FE), A przy A=04, po czasie 0,0005 sekundy wyśle OUT (FE), A przy A=00, a po czasie 0,0015 wyślę ponownie OUT (FE), A przy A=04 i tak w kółko, to usłyszę również dźwięk o częstotliwości podstawowej 500Hz, ale o bardziej ostrzejszym brzmieniu, bo jest to przebieg o wypełnieniu 25%. Czy dobrze rozumiem?
  • #226
    wieswas
    Level 34  
    Druga część wypowiedzi jest jasna. Gdy wytworzymy przebieg prostokątny o wypełnieniu 50%, to dominuje częstotliwość podstawowa (to 500Hz). Dodatkowo występują też harmoniczne, ale dużo słabsze.
    Gdy przebieg jest niesymetryczny, to obok częstotliwości podstawowej otrzymamy wiele harmonicznych oraz dodatkowych częstotliwości, które nie spełniają warunku harmonicznych - nie są całkowitymi wielokrotnościami tonu podstawowego.
    Daje to efekt bardziej ostrego czy charczącego dźwięku. W grach może to być efekt zamierzony. Jakie dodatkowe częstotliwości uzyskamy zmieniając współczynnik wypełnienia najlepiej obejrzeć w programie AUDACITY nagrywając próbki a następnie oglądając obraz transformacji Fouriera, który pokazuje ten sam przebieg ale nie na poziomej skali czasu, ale na skali częstotliwości. Można tam odczytać które piki są największe i jaki mają częstotliwości.
    Natomiast pierwszej części wypowiedzi nie zrozumiałem dokładnie.
    Co robi w emulatorze funkcja OUT(nr. portu),A ?
    Czy jest przypisana do konkretnego numeru portu ?
    Czy dla każdego numeru portu robi coś innego ?
    Przecież w Cobrze OUT(1B) powinien uruchomić standardową procedurę BEEP, a OUT(FF) standardową procedurę tworzenia zapisu na taśmie magnetofonu, jeszcze inny numer wystawia stany linii klawiatury.
    I jeszcze jedno pytanie: Skoro po instrukcji OUT(nr.portu),A emulator analizuje też zawartość wysłanego z akumulatora bajtu to jak to wykorzystuje ?
    Można sobie wyobrazić, że skoro analizuje zawartość akumulatora to można robić dźwięk nie 1-bitowy, a 8-bitowy. Zamiast stanu H i L mamy stany od 0 do 256.
    A to już jest całkiem inna jakość dźwięku, choć nieprzydatna dla COBRY:
    1-zabiera zbyt dużo zasobów procesora Z-80 aby opisać 8 bitami dźwięk !!!
    2-hardware dla oryginalnej COBRY bardzo by się rozbudował. Byłby to już prosty przetwornik cyfrowo-analogowy.
  • #227
    krru
    Level 33  
    Może lepiej podłączyć układ AY-3-8910 (lub 8912), popularny w licznych komputerkach z okresu świetności Z80 (oraz w grach arcade, gdzie często było ich kilka)? Można by użyć adresów takich jak w Spectrum-2 albo w Amstradach by zachować kompatybilność.
  • #228
    andrzejlisek
    Level 29  
    wieswas wrote:
    Natomiast pierwszej części wypowiedzi nie zrozumiałem dokładnie.
    Co robi w emulatorze funkcja OUT(nr. portu),A ?
    Czy jest przypisana do konkretnego numeru portu ?
    Czy dla każdego numeru portu robi coś innego ?
    Przecież w Cobrze OUT(1B) powinien uruchomić standardową procedurę BEEP, a OUT(FF) standardową procedurę tworzenia zapisu na taśmie magnetofonu, jeszcze inny numer wystawia stany linii klawiatury.
    I jeszcze jedno pytanie: Skoro po instrukcji OUT(nr.portu),A emulator analizuje też zawartość wysłanego z akumulatora bajtu to jak to wykorzystuje ?
    Można sobie wyobrazić, że skoro analizuje zawartość akumulatora to można robić dźwięk nie 1-bitowy, a 8-bitowy. Zamiast stanu H i L mamy stany od 0 do 256.
    A to już jest całkiem inna jakość dźwięku, choć nieprzydatna dla COBRY:
    1-zabiera zbyt dużo zasobów procesora Z-80 aby opisać 8 bitami dźwięk !!!
    2-hardware dla oryginalnej COBRY bardzo by się rozbudował. Byłby to już prosty przetwornik cyfrowo-analogowy.


    W uproszczeniu, emulator pracuje tak, że każdy rejestr jest zmienną liczbową i emulator pracuje w pętli, w której przy każdym przebiegu jest odczytywanych tyle kolejnych bajtów, ile ma dany rozkaz (bajty odczytywane po jednym), a potem, w zależności od rozkazu, jest wykonywana pewna czynność. Jeżeli jest rozkaz OUT (xx), A, to jest wywołanie procedury DoOut, do której jest przekazywany jako argument adres z rozkazu i wskaźnik na zmienną reprezentująca rejestr A. W ramach samej procedury są ify, które uzależniają czynności od adresu, w którym są wyzerowane bity niemające znaczenia (wynika to z konstrukcji układu adresowego Cobry), a następnie jest wykonywana określona czynność, która może wykorzystywać przekazaną wartość.
  • #229
    wieswas
    Level 34  
    Dzięki za precyzyjne objaśnienie tej kwestii.
    Rozumiem, że obecny emulator zawiera rozpoznanie każdej instrukcji Z-80, ale dla instrukcji OUT(PORT),A brak mu podprogramu, który wykona jakąś czynność (np. przesłania jakiś danych do karty dźwiękowej), więc powraca do dalszej analizy kodu programu jedynie po obiegu pętli zawierającej warunki IF i standardowo zapamiętując stan akumulatora.
    Sądzę, że ze względu na kompatybilność z ZX SPECTRUM należy wybrać port FE, ale nie sprawdzać 4 bitu akumulatora albo jeśli emulator standardowo analizuje każdy bit akumulatora dla tej instrukcji, to przypisać ten sam podprogram dla wszystkich warunków IF.
    Czyli taki podprogram przy każdym wywołaniu wykonywałby negację dotychczasowego stanu 0 lub 1 i wysyłał na głośnik.
    Dla użytkowników hardwarowej wersji COBRY dorobienie sterowania głośnikiem z portu FE jest bardzo proste, ale analizowanie poszczególnych bitów zawartości akumulatora nie byłoby już takie łatwe.
    A przecież to emulator ma być dostosowany do COBRY, a nie COBRA do emulatora.
    Cały sens istnienia emulatora jest w tym, by tworzone w nim programy działały tak samo w komputerze.
  • #230
    andrzejlisek
    Level 29  
    Robię pierwsze próby implementacji dźwięku zgodnego z ZX Spectrum i słyszane dźwięki zgadzają sie z ponizszymi rozważaniami.

    Rozkaz NOP (kod operachi 00) zajmuje 4 takty zegara. Procesor ma szybkość 3250000Hz, więc po podzieleniu przez 4 jest 812500 rozkazów NOP na sekundę.

    Napisałem taki program testowy:
    Start:
    LD A, #4
    OUT FEh, A
    ORG 1000h
    LD A, #0
    OUT FEh, A
    ORG 2000h
    JP Start

    Ten program kompiluje się nastepująco:
    Po etykiecie Start: 3E,04,D3,FE - stan wysoki na głośniku
    Po ORG 1000h: 3E,00,D3,FE - stan niski na głośniku
    Po ORG 2000h: C3,00,00 - skok do początku
    Nie zwarzając na pojedyncze cykle maszynwe i szczegóły rozkazów, można przyjąć, że czas przejścia od adresu 0000 do adresu 1000, czyli 4096 wykonań rozkazu NOP trwa 4096/812500=0,005 sekundy

    W powyższym przykładzie, przejście od 0000 do 2000, czyli 8192 rozkazów NOP w przybliżeniu, to 0,01 sekundy, czyli powinienem usłyszeć dźwięk o czestotliwości ok 812500/4096=99Hz

    Aby wprowadzić taki program, wystarczy po uruchomieniu Cobry wydatrzy polecenia.

    Zerowanie pierwszych 32kB pamięci:
    Z0000,7FFF,00

    Wprowadzenie rozkazu zapisu 04 do A i wysłania A na FE pod adres 0000:
    M0000,3E,04,D3,FE

    Wprowadzenie rozkazu zapisu 00 do A i wysłania A na FE pod adres 1000:
    M1000,3E,00,D3,FE

    Wprowadzenie rozkazu skoku pod adres 2000
    M2000,C3,00,00


    W przypadku poniższych poleceń będzie dźwięk o częstotliwości 99Hz z wypełnieniem 50%
    Z0000,7FFF,00
    M0000,3E,04,D3,FE
    M1000,3E,00,D3,FE
    M2000,C3,00,00


    W przypadku poniższych poleceń będzie dźwięk o częstotliwości 812500/2048=397Hz z wypełnieniem 50%
    Z0000,7FFF,00
    M0000,3E,04,D3,FE
    M0400,3E,00,D3,FE
    M0800,C3,00,00

    W przypadku poniższych poleceń będzie dźwięk o tej samej częstotliwości, ale z wypełnieniem 25%, czyli ostrzejsze brzmienie
    Z0000,7FFF,00
    M0000,3E,04,D3,FE
    M0200,3E,00,D3,FE
    M0800,C3,00,00

    Czy dobrze wszystko napisałem? Czy tak właśnie wygląda generowanie dxwięku w ZX Spectrum?

    wieswas wrote:
    Rozumiem, że obecny emulator zawiera rozpoznanie każdej instrukcji Z-80, ale dla instrukcji OUT(PORT),A brak mu podprogramu, który wykona jakąś czynność (np. przesłania jakiś danych do karty dźwiękowej), więc powraca do dalszej analizy kodu programu jedynie po obiegu pętli zawierającej warunki IF i standardowo zapamiętując stan akumulatora.

    Zgadza się. Dla każdej obsługiwanej instrukcji Z80 sa wykonane czynności i odliczone cykle maszynowe. Jeżeli jest grupa podobnych rozkazów, to część wspólna jest zawarta w jednej procedurze, która jest uruchamiana z głównej pętli podczas wykonywania danego rozkazu. Dla OUT i IN też jest osobna procedura. Dla przykładu, każdy rozkaz OUT wywołuje taki program (wyciąg z kodu źródłowego emulatora):
    Code: c
    Log in, to see the code


    Jak widać, mozna pod ten rozkaz doimplementować to, co się chce. Dla rozkazów IN jest podobny podprogram.

    Dodano po 1 [godziny] 29 [minuty]:

    wieswas wrote:
    W oryginalnej COBRZE pozytyw/negatyw ustawiało się za pomocą zwory przełączającej wyjście UCY74165 (układ nr. 109)
    W swoim komputerze wyprowadziłem przełącznik na zewnątrz obudowy.

    Czy w wersji Cobry bez semigrafiki, znaki od 128 do 255 są powtórzonymi znakami od 0 do 127? Czy te dalsze znaki są równoważne, czyli zarówno znak 65, jak i 192 wyświetla białą literę A w tych samych kolorach, czy te dalsze znaki miały wtedy odwrócone kolory?
  • #231
    wieswas
    Level 34  
    Na ZX SPECTRUM tak powinno to działać.
    Na Cobrze z wyprowadzonym przewodem z portu FE sterującym przerzutnikiem dzielącym przez 2, z wyjścia którego przez opornik jest sterowana baza tranzystora T3 (głośnikowego) także powinno to działać, chociaż tam nie będzie sprawdzany bit 4 akumulatora.
    Tam wywołanie OUT(FE),A ustawi na wyjściu H, następny OUT(FE),A stan L , kolejny znów stan H, następny stan L itd.
    Stan akumulatora nie miałby żadnego znaczenia.
    Może i w emulatorze zrezygnować z badania 4 bitu ?
    W ZX SPECTRUM ten sam port służy do różnych funkcji , więc musi być analizowane ustawienie bitów. W COBRZE ten port byłby używany tylko do dźwięku, więc nie trzeba sprawdzać bitów akumulatora.

    Korzystając z Twojej pomocy mam jeszcze pytania:
    1.Jaki lub jakie numery portów wejściowych są używane do obsługi klawiatury ?
    2.Gdzie w programie MONITOR COBRY znajduje się procedura czytania klawiatury ?
    3.Czy do modyfikacji emulatora, aby odsługiwał dźwięk wystarczy dokonać przeróbek w kodzie maszynowym, czy będzie wymagana całkowita jego wymiana ?
  • #232
    andrzejlisek
    Level 29  
    wieswas wrote:
    Na ZX SPECTRUM tak powinno to działać.
    Na Cobrze z wyprowadzonym przewodem z portu FE sterującym przerzutnikiem dzielącym przez 2, z wyjścia którego przez opornik jest sterowana baza tranzystora T3 (głośnikowego) także powinno to działać, chociaż tam nie będzie sprawdzany bit 4 akumulatora.
    Tam wywołanie OUT(FE),A ustawi na wyjściu H, następny OUT(FE),A stan L , kolejny znów stan H, następny stan L itd.
    Stan akumulatora nie miałby żadnego znaczenia.
    Może i w emulatorze zrezygnować z badania 4 bitu ?
    W ZX SPECTRUM ten sam port służy do różnych funkcji , więc musi być analizowane ustawienie bitów. W COBRZE ten port byłby używany tylko do dźwięku, więc nie trzeba sprawdzać bitów akumulatora.

    Rozumiem. W takim razie to będzie działać tak, że wartość wysyłana na OUT nie jest istotna, każde wywołanie OUT na adres FE zmienia stan sygnału na głośniku i żeby uzyskać dźwięk o określonej częstotliwości, należy wywoływać ten rozkaz z odpowiednią częstotliwością.
    wieswas wrote:


    1.Jaki lub jakie numery portów wejściowych są używane do obsługi klawiatury ?

    Klawiatura znajduje się pod adresem mniej znaczący bajt 9C (na tym bajcie należy wykonać iloczyn bitowy z wartością 9C w celu odrzucenia niepodłączonych bitów), ale bardziej znaczący bajt to jeden z następujących: FE, FD, FB, F7, EF, DF, BF, 7F. Klawiatura ma 8 sektorów po 5 klawiszy każdy i w zwracanej wartości 5 najmniej znaczących bitów to stan tych 5 klawiszy.
    wieswas wrote:
    2.Gdzie w programie MONITOR COBRY znajduje się procedura czytania klawiatury ?

    Jakiś czas temu analizowałem ten fragment, jak jeszcze miałem problem z implementacją klawiatury. On znajduje się pod adresami od C5FD do C6BB, jeden fragment przeanalizowałem, później nie próbowałem analizować. Zamieszczam notatkę z tej analizy:
    PROCEDURA WYWOŁANA PO SPRAWDZENIU WSZYSTKICH SEKCJI KLAWISZY
    JEJ ZADANIEM PRAWDOPODOBNIE JEST WYŁĄCZNIE PRZEKSZTAŁCENIE WARTOŚCI HL W INNĄ WARTOŚĆ HL
    -- Stos: 48924
    c60e 44        LD      B,H
    c60f 4D        LD      C,L
    ### Do BC jest przepisany HL
    c610 1600      LD      D,00H	Zerowanie rejestru D
    c612 CB28      SRA     B	Przesuniecie w prawo, najmlodszy bit trafia do C, najstarszy pozostaje bez zmian
    c614 9F        SBC     A,A      Jeżeli C==1 to A=01, Z=0, jeżeli C==0, to A=00, Z=1
    c615 F626      OR      26H	Maskowanie rejestru A z 00100110
    c617 2E05      LD      L,05H
    c619 95        SUB     L	Od A odejmuje się 05
    c61a 85        ADD     A,L	Do A dodaje się 05
    c61b 37        SCF     		Ustawienie flagi C
    c61c CB19      RR      C	Obrot bitowy rejestru C w prawo, flaga C do najstarszego, najmlodszy do flagi C
    c61e 38FA      JR      C,0C61AH
    c620 0C        INC     C
    c621 48        LD      C,B
    c622 2D        DEC     L
    c623 2E01      LD      L,01H
    c625 20F3      JR      NZ,0C61AH
    c627 212DC6    LD      HL,0C62DH
    c62a 5F        LD      E,A
    c62b 19        ADD     HL,DE
    c62c 37        SCF     		Ustawienie flagi C
    c62d C9        RET     		Powrot do C60C
    -- Stos: 48924
    
    PROCEDURA SPRAWDZAJACA, CZY NACISNIETO KLAWISZ
       D:01234
    FE9C ^ZXCV
    FD9C ASDFG
    FB9C QWERT
    F79C 12345
    
       D:43210
    EF9C 67890
    DF9C YUIOP
    BF9C HJKL-
    7F9C BNM,_
    
    Dane: D3|D4|D5|__|__|D2|D1|D0
    -- Stos: 48926
    c5e2 21FFFF    LD      HL,0FFFFH
    c5e5 01FFFE    LD      BC,0FEFFH
    c5e8 ED78      IN      A,(C)	Odczyt adresu FEFF
    ### w A jest wartość stanu klawiszy pod adresem FEFF - klawisze ^ZXCV
    c5ea F601      OR      01H	00000001
    c5ec F6E0      OR      0E0H	11100000 < Do tego miejsca przeskakuje z C5FD po sprawdzeniu FD9C, FB9C...7F9C, po FE9C nie ma przeskoku
    ### w A jest wartość stanu klawiszy, ale tylko D1,D2 przy wejsciu do pętli lub D0,D1,D2 przy kolejnym obrocie
    ### Chodzi o to, żeby otczytać D0,D1,D2, ale nie uwzględnić SHIFT przy wejściu do pętli, ale przy ostatnim obrocie Shift będzie uwzględniony
    c5ee 57        LD      D,A
    c5ef 2F        CPL     		Odwrocenie wszystkich bitow rejestru A
    c5f0 FE01      CP      01H	Porownanie z 01, jeżeli A==0, to flaga C jest podnoszona, w przeciwnym wypadku opuszczona
    c5f2 9F        SBC     A,A      Jeżeli C==1 to A=01, Z=0, jeżeli C==0, to A=00, Z=1
    c5f3 B0        OR      B        W kazdym obrocie B przyjmuje kolejno: FE,
    c5f4 A5        AND     L        W kazdym obrocie L przyjmuje kolejno: FF,
    c5f5 6F        LD      L,A
    c5f6 7C        LD      A,H
    c5f7 A2        AND     D
    c5f8 67        LD      H,A
    c5f9 CB00      RLC     B	Przesuniecie w lewo, najstarszy bit wchodzi do C, do najmlodszego wchodzi 0
    c5fb ED78      IN      A,(C)    Odczyt adresow klawiatury, w kolejnych przebiegach petli: FD9C, FB9C, F79C, EF9C, DF9C, BF9C, 7F9C, FE9C
    c5fd 38ED      JR      C,0C5ECH Przeskok do C5EC, jezeli flaga C podniesiona, nastepuje w petli po kolejnych adresach klawiatury, nie nastepuje po przetworzeniu ostatniego
    
    ### Tu wchodzi po ostatnim przebiegu, po drugim odczycie FEFF
    c5ff CB1F      RR      A        Obrot bitowy rejestru A w prawo, flaga C do najstarszego, najmlodszy do flagi C
    ### Teraz w fladze C jest stan klawisza Shift, 0 to naciśnięty, 1 to nienaciśnięty
    c601 CB14      RL      H	Obrot bitowy rejestru H w lewo, flaga C do najmlodszego, najstarszy do flagi C
    ### W najmłodszym bicie rejestru H jest stan klawisza Shift
    c603 3EFF      LD      A,0FFH	Zapis liczby FF do rejestru A
    c605 BD        CP      L	Rejestr L teoretycznie zawiera informację o stanie klawiatury, w praktyce nigdy nie zawiera FF
    c606 2001      JR      NZ,0C609H Przeskok do C609 jezeli L!=FF - warunkiem przeskoku jest liczba inna niż FF w rejestrze L
    c608 C9        RET     		Powrót do programu głównego
    
    ### Wydaje się, że wartość HL zależy od naciśniętego klawisza, w praktyce jest ten sam bez względu na klawisz tak, jakby nie było żadnego nacisniętego
    c609 CD0EC6    CALL    0C60EH   Wywolanie C60E - jako dane wykorzystuje rejestry HL
    c60c 7E        LD      A,(HL)   Ladowanie do A komórki pamięci o adresie zapisanym w HL
    c60d C9        RET     		Powrót do programu głównego
    -- Stos: 48926
    
    
    FRAGMENT PROGRAMU GLOWNEGO, W KTORYM PROGRAM ZATRZYMUJE SIE OCZEKUJAC NA KLAWISZ
    -- Stos: 48928
    c6bb CDE2C5    CALL    0C5E2H   Wywolanie C5E2
    c6be FEFF      CP      0FFH     Porownanie rejestru A z FF
    ### Jeżeli wywołano C60E, to nie wychodzi się z pętli, w przeciwnym razie się wychodzi
    c6c0 20F9      JR      NZ,0C6BBH Przeskok do C6BB jezeli A nie jest zerowy (flaga Z opuszczona) - ZAWSZE NASTEPUJE !!!
    -- Stos: 48928
    
    
    Rozkaz CP:
    A < val ==> S=1, Z=0
    A = val ==> S=0, Z=1
    A > val ==> S=0, Z=0
    
    
    Wnioski:
    Program dochodzi do adresi C6BB, z którego następuje wywołanie programu C5E2, który sprawdza, czy jest naciśnięty
    jakiś klawisz, jeżeli żaden klawisz nie jest nacisnięty, to w rejestrze A jest FF i program C5E2 wywołuje się ponownie.
    
    Potem następuje sprawdzenie adresów sekcji, przy czym na początku jest adres FEFF z pominięciem (maskowaniem Shift),
    w ostatnim przebiegu jest ponownie odczytywany adres FEFF, ale już bez maskowania klawisza Shift.
    

    wieswas wrote:
    3.Czy do modyfikacji emulatora, aby odsługiwał dźwięk wystarczy dokonać przeróbek w kodzie maszynowym, czy będzie wymagana całkowita jego wymiana ?

    Czy pytasz się o zmiany w emulatorze, czy w programie monitora uruchomionym wewnątrz emulatora? Jeżeli to pierwsze, to po prostu robię zmiany w kodzie źródłowym i kompiluję. Jeżeli to drugie, to zależy, co chciałbyś otrzymać i jak chciałbyś używać. Jeżeli to są niewielkie zmiany, to lepiej przerobić istniejący kod maszynowy, podobnie, jak jakiś czas temu wcisnąłem obsługę wielkich i małych liter w programie monitora.
  • #233
    jackfinch
    Level 17  
    Witam

    @andrzejlisek dzięki za skan książki.

    @wieswas, czy pamiętasz z jakich elementów jest zbudowany moduł który odpowiada za emulacje zx spectrum na cobrze (czy zachował się jakiś schemat, cokolwiek co mogłoby przybliżyć w jaki sposób tego dokonałeś).

    Pozdrawiam
  • #234
    andrzejlisek
    Level 29  
    Zgodnie z obietnicą, wysyłam nową wersję emulatora. Doimplementowałem następujące funkcje:

    1. Generator dźwięku zgodny z ZX Spectrum
    2. Możliwość odwrócenia kolorów
    3. Wczytywanie naciśnięć klawiszy z pola tekstowego, nie tylko z pliku
    4. Symulacja drukowania
    5. Możliwość ustalenia początkowej zawartości pamięci RAM
  • #235
    wieswas
    Level 34  
    Do: andrzejlisek
    Dziękuję, za jak zwykle precyzyjne wyjaśnienie procedury obsługi klawiatury na PW.
    Jestem pełen podziwu nad szybkością tworzenia implementacji nowych procedur w emulatorze.
    Procedura MONITORA COBRY wywołana przez CALL C5E2 sprawdza stan klawiatury i wraca z kodem wciśniętego znaku w akumulatorze.
    We własnych grach wystarczy zwykle obsługa 5 klawiszy (A-lewo,S-prawo,W-góra,Z-dół i Enter-strzał) więc mocno to upraszcza pisanie gier.

    Do: jackfinch
    Niestety nie mam żadnych notatek, gdyż nie sądziłem, że jeszcze kiedykolwiek wrócę do tematu Cobra.
    Ale jak widać na fotografiach zamieszczonych przez Muzeum Komputeryzacji i Informatyki w Katowicach na ich stronie, nie ma tam żadnych specjalistycznych układów scalonych.
    Przeróbka polegała na maskowaniu pierwszych 16kB dynamicznej pamięci RAM przez EPROM z zawartością oryginalnego ROMu ZX SPECTRUM oraz części pamięci dynamicznej Cobry pamięcią statyczną wyświetlacza ZX-spectrum.
    Wszystkie pamięci są na stałe podłączone do magistrali adresowej i danych COBRY, a tylko wspólnym przełącznikiem włączałem aktywację/dezaktywację grup pamięci COBRY/ZX SPECTRUM. Do obsługi odczytu pamięci video wykorzystywałem te same sygnały co w Cobrze. Procesor też był wspólny.
    Ale to było ponad ćwierć wieku temu i bez notatek trudno o szczegóły.

    Mam też pytanie: jak zapisać zawartość fragmentu pamięci z wklepanym kodem programu w emulatorze do pliku na PC ? Po wciśnięciu klawisza F3 (zapisz zawartość) otwiera się okno do wpisania nazwy pliku *.HEX oraz katalogu docelowego, ale nie wiem gdzie mu podać zakres adresów, które chciałbym zapisać, aby następnego dnia znów wczytać i kontynuować wklepywanie kodu.
  • #236
    andrzejlisek
    Level 29  
    wieswas wrote:
    Mam też pytanie: jak zapisać zawartość fragmentu pamięci z wklepanym kodem programu w emulatorze do pliku na PC ? Po wciśnięciu klawisza F3 (zapisz zawartość) otwiera się okno do wpisania nazwy pliku *.HEX oraz katalogu docelowego, ale nie wiem gdzie mu podać zakres adresów, które chciałbym zapisać, aby następnego dnia znów wczytać i kontynuować wklepywanie kodu.

    Jak zatwierdzisz nazwę pliku, to pojawią się dwa okna dialogowe z prośbą o wpisanie początkowego i końcowego adresu. Przy wczytywaniu analogicznie pojawia się okienko z prośba o podanie adresu początkowego.
  • #238
    andrzejlisek
    Level 29  
    jackfinch wrote:
    Link do paru ciekawych rzeczy związanych z Cobrą w jednym miejscu:

    Notatnik Fana Starych Komputerów

    Ja testowałem wszystkie gry na moim emulatorze i działają. Tylko gra "Nalot" jest w nietypowym pliku WAV. Wystarczy wczytać do programu dźwiękowego i zapisać jako standardowy WAV, ale ja to już uczyniłem i na którejś z poprzednich stron umieściłem przerobione pliki z tą grą.
  • #239
    wieswas
    Level 34  
    Ponieważ Cobra ma obecnie wiele rozszerzeń w stosunku do oryginału, chciałbym zapytać, jaki zakres pamięci RAM najlepiej stosować podczas tworzenia programów i gier w kodzie maszynowym, aby nie kolidowały z obszarem przeznaczonym na zmienne i programy BASICA , a równocześnie wszyscy mieli dostęp do tego zakresu ?
    I drugie pytanie, czy dałoby się ujednolicić dodatkowe znaki semigrafiki ?
    Taka normalizacja ułatwiłaby wzajemną wymianę.
  • #240
    andrzejlisek
    Level 29  
    wieswas wrote:
    Ponieważ Cobra ma obecnie wiele rozszerzeń w stosunku do oryginału, chciałbym zapytać, jaki zakres pamięci RAM najlepiej stosować podczas tworzenia programów i gier w kodzie maszynowym, aby nie kolidowały z obszarem przeznaczonym na zmienne i programy BASICA , a równocześnie wszyscy mieli dostęp do tego zakresu ?

    Czy chodzi Ci o zarezerwowanie pewnej przestrzeni adresowej na te dodatkowe rozszerzenia? Ja myślę, że, ta zarezerwowana pamięć to byłaby od adresu 4000 do BFFF (16kb), a jak mniej, np. 4 kB, to od B000 do BFFF. Basic TRS za każdym razem pyta się o wielkość pamięci, wydaje mi się, że wpisywanie za każdym razem 32 spowoduje, że Basic nie będzie zajmować więcej niż od 0000 do 7FFF, ale nie jestem tego pewien.
    Jeżeli chcesz tworzyć program w ASM lub w C, nawet ze wstawkami ASM, to po co Ci jednoczesna praca tego programu i Basica? W tym przypadku masz do dyspozycji te 32kB lub 36kB na program i do tego obszaru kompilator SDCC skompiluje i wczytasz do Cobry.
    wieswas wrote:
    I drugie pytanie, czy dałoby się ujednolicić dodatkowe znaki semigrafiki ?

    Moim zdaniem najlepiej przyjąć za standard czcionkę utworzoną przez zdzis_ek, którą też załączam jako domyślną do emulatora w poprzednim poście. W stosunku do tej z Audio-Video, zawiera różne ikony, elementy ramek, a także pełne 16 kombinacji podziału znaku na 4 kwadraty tak, jak w ZX Spectrum.