ZX Spectrum dari coronavirus and sticks (sebenarnya, tidak juga)

Isolasi diri adalah momok kemanusiaan modern. Di sini, misalnya, di kota tetangga, pada hari Jumat dan Sabtu, setelah bertepuk tangan tradisional pada pukul 8 malam, mereka menyelenggarakan konser balkon. Mereka merasa baik, rumah mereka tinggi dan tetangga mereka masih muda. Tetangga kami sudah tua, mereka tidak ingin konser. Dan rumah-rumahnya rendah, yang juga tidak berkontribusi pada kemalasan. Karena itu, kita diselamatkan semampu kita.

Di sore hari, di situs terpencil, tidak terlalu buruk. Seperti pada malam hari, hingga anak-anak tertidur. Seperti di beberapa hari pertama, sampai buku habis dan seri bosan. Tapi satu bulan berlalu, diikuti oleh yang lain. Jiwa membutuhkan besi tua. Tapi tidak adil, tetapi dengan penyimpangan. Dan saya mencari-cari tempat sampah dan menemukan prosesor Zilog Z80 di sana:

gambar

Saya harus mengatakan, saya sangat menyukai prosesor ini. Mungkin satu-satunya hal yang saya sukai dari dia adalah chip ke-486, tetapi tangan saya tidak akan segera mencapainya, karena sulit dan tidak ada gunanya memasukkannya ke papan tempat memotong roti. Harus disolder. Tapi saya belum mau solder. Dan bahkan lebih dari Z80 itu sendiri, saya suka komputer ZX Spectrum yang dibangun atas dasar itu. Tapi Spectrum asli menderita bencana dalam bentuk chip logika kustom ULA, dan klonnya di sisi longgar, meskipun tidak terlalu sulit untuk dibangun dan disempurnakan, masih tidak untuk model papan tempat memotong roti, dan memang, mengapa begitu banyak kekhawatiran ketika ada arduino?

Pembaca yang cerdas, seimbang, dan memadai di sini akan berhenti membaca atau melempar sesuatu seperti "1 mikrosirkuit FPGA akan mengakomodasi kelas komputer Spectrum" sebelum berhenti. Saya tidak pintar, tidak memadai, meskipun seimbang, tetapi saya hanya tahu tentang FPGA bahwa itu keren. Saya hanya bisa melakukan Arduino. Tapi benar-benar ingin menyodok kabel di Z80. Sangat.

Ayo mulai

Tentu saja, mari kita mulai. Tapi pertama-tama, Penafian., , , . — . , , . , (, ?), , , , , . , , , , , .

Untuk mulai dengan, apa yang dimaksud dengan komputer 8-bit yang memadai. Ini sebenarnya adalah prosesor yang terhubung ke ROM dan RAM, dan di sampingnya ada beberapa penghitung untuk ditampilkan pada layar komposit. Terkadang, timer mencicit. ZX Spectrum tidak berbeda dengan skema tradisional, kecuali satu tetapi. Ada ULA. Ini, sebenarnya, adalah "chipset" dari Spectrum. ULA mengelola periferal, seperti tape recorder, tweeter, keyboard (sebagian), output ke layar (ya, ya, kartu video terintegrasi muncul dalam chipset Spectrum bahkan sebelum menjadi mainstream). Ada juga peringatan bersama, 16 KiB RAM pertama (alamat dari 0x4000 hingga 0x5B00). Dari sana, ULA menarik komposit ke layar, dan agar Z80 tidak akan meraba-raba di sana ketika tidak diperlukan, ULA dapat menghentikan prosesor, jika perlu, karena sinyal jam pada Z80 berasal dari itu. Artinya, jika ULA bekerja dengan memori, dan terdeteksi,bahwa prosesor juga merayap ke dalam memori ini (untuk ini, ia terus-menerus memonitor garis MREQ dan A15 dan A14), itu hanya menghentikan clocking prosesor sampai itu sendiri selesai melakukan apa yang diperlukan. By the way, untuk menghindari korupsi data di bus, bagian-bagian bus di sisi prosesor dan di sisi ULA dibatasi oleh ... resistor ... Selain itu, memori duduk di bus dari sisi ULA dan, dengan demikian, jika terjadi tabrakan, sepenuhnya mengabaikan data dan alamat dari sisi prosesor.benar-benar mengabaikan data dan alamat dari prosesor.benar-benar mengabaikan data dan alamat dari prosesor.

Selain itu, Spectrum memiliki ROM (alamat 0x0000 - 0x3FFF) dan memori prosesornya sendiri (0x8000 - 0xFFFF), di mana ULA tidak memiliki akses, dan yang bekerja lebih cepat dari 16 KiB memori bersama, karena prosesor tidak mengganggu ULA di area ini. . Tapi itu hanya pada versi 48K dari komputer. Dalam versi dasar, hanya ada ROM dan 16 KiB yang kompatibel dengan ULA. Kami akan mulai dengannya.

Sangat nyaman bahwa prosesor Z80 dapat membuat ulang DRAM, tetapi bagaimanapun saya tidak ingin repot dengannya, karena SRAM lebih mudah ditemukan dan saya tidak memiliki multiplexer (atau saya tidak dapat menemukannya). Jadi, kita akan menggunakan SRAM. Untuk memulainya, kita akan merakit kerangka utama, di mana semua yang lain bisa digantung. Kerangka akan menjadi prosesor, ROM dengan firmware, dipetakan ke alamat Spectrum's ROM, RAM, dipetakan ke 16 KiB pertama setelah ROM dan beberapa chip untuk membungkus semuanya ... Saya harus mengatakan bahwa untuk waktu yang lama saya tidak ingin memutar, karena saya memiliki tata letak Cina $ 1 untuk 2 lembar dalam ibee. Tapi, bagi saya, keributan itu sepadan. Jika Anda tidak ingin dipusingkan untuk waktu yang lama, lakukan tata letak yang baik.

Jadi, instal Z80.

Seperti yang Anda lihat dari lembar data ,



Prosesor memiliki 40 pin yang dibagi menjadi beberapa kelompok: bus alamat, bus data, kontrol sistem, kontrol prosesor, kontrol bus prosesor, well, daya dan jam. Tidak semua kesimpulan ini digunakan dalam sistem nyata, seperti ZX Spectrum, seperti yang dapat dilihat dari diagram.. Dari "kontrol prosesor" grup dalam Spectrum, hanya sinyal INT dan RESET yang digunakan. Sinyal M1 tidak digunakan dari grup "sistem kontrol", grup "kontrol bus" tidak digunakan sama sekali. Ada alasan untuk ini. Sistem 8-bit yang lama sangat sederhana, dan Spectrum dibuat dengan gagasan sesederhana mungkin dan segala sesuatu yang dapat diabaikan diabaikan. Tentu saja, produsen perangkat dapat menggunakan interupsi (sinyal INT dan NMI), mereka diarahkan ke slot ekspansi, tetapi NMI tidak digunakan dalam spektrum itu sendiri. Seperti dapat dilihat dari diagram di atas, sinyal NMI, WAIT, BUSREQ ditarik oleh resistor daya, karena ini adalah input tingkat rendah yang diaktifkan (ini ditunjukkan oleh bilah di atas nama sinyal), dan harus ada unit logis (mis. + 5V) sehingga Tuhan melarang sinyal yang tidak perlu tidak bekerja. Dan inilah temuannya, BUSACK, HALT, M1,dan menggantung di udara, tidak terhubung dengan apa pun. Omong-omong, perhatikan bahwa tidak ada tombol reset di Spectrum. Pin reset terhubung melaluiRantai RC ke daya (RESET juga diaktifkan oleh level rendah), karena, menurut lembar data, setelah mengaktifkan RESET, setidaknya 3 siklus clock harus aktif agar prosesor memasuki mode operasi. Sirkuit RC ini menjaga level rendah hingga kapasitor dibebankan ke level tinggi melalui resistor.

Mari kita secara singkat memeriksa sisa sinyal:
M1. Kami tidak membutuhkan. Dia melaporkan bahwa prosesor mulai menjalankan instruksi berikutnya.
MREQ. Saya membutuhkannya. Ini melaporkan bahwa prosesor sedang mengakses memori. Jika sinyal ini menjadi rendah (yaitu, terhubung ke catu daya), maka kita harus mengaktifkan memori yang terhubung ke prosesor.
IOREQ . Saya membutuhkannya. Ini melaporkan bahwa prosesor sedang mengakses perangkat periferal. Misalnya ke keyboard.
RD . Saya membutuhkannya. Menginformasikan bahwa prosesor akan membaca data dari memori (jika MREQ aktif) atau periferal (IOREQ).
Wr . Saya membutuhkannya. Laporan bahwa prosesor akan menulis data ke memori / periferal.
RFSH . Saya membutuhkannya. Secara umum, sinyal ini diperlukan untuk memori dinamis (DRAM). Saya tidak berencana untuk menggunakannya, karena pengalamatannya lebih sulit (matriks, bukan linier, yaitu, akan diperlukan untuk menginstal multiplexer), dan secara umum, di zaman kita, mikrosirkulasi SRAM berkapasitas rendah lebih mudah didapat. Tetapi karena prosesor itu sendiri meregenerasi DRAM dengan mengurutkan alamat pada bus memori, sinyal ini akan memungkinkan kita untuk mengabaikan siklus regenerasi dan tidak mengaktifkan memori dengan RFSH aktif.
HALT . Tidak dibutuhkan. Menunjukkan bahwa prosesor dihentikan.
TUNGGU. Tidak dibutuhkan. Sinyal ini diperlukan untuk meminta prosesor berhenti dan menunggu sebentar. Biasanya digunakan oleh periferal atau memori yang lambat. Tapi tidak dalam Spectrum. Ketika dalam peripheral Spectrum (ULA) memutuskan untuk menghentikan prosesor, maka ia hanya berhenti mengirim sinyal jam ke sana. Ini lebih dapat diandalkan, karena setelah menerima WAIT, prosesor tidak segera berhenti.
INT . Mengganggu. Belum jelas. Kami berasumsi bahwa itu belum diperlukan. Lalu kita akan mencari tahu.
NMI . Gangguan yang tak terduga. Super interupsi. Tidak perlu.
RESET . Tanpanya, itu tidak akan terbang.
BUSREQ . Tidak dibutuhkan. Meminta prosesor untuk memutuskan koneksi dari data / bus alamat, serta sinyal kontrol. Diperlukan jika beberapa perangkat ingin mendapatkan kendali atas bus.
BUSACK. Tidak dibutuhkan. Berfungsi untuk memberi tahu perangkat yang melakukan BUSREQ bahwa bus itu gratis.
JAM . Sinyal jam. Jelas, dia dibutuhkan.
Makanan juga dibutuhkan. Glory ke pengembang, hanya + 5V / GND. Tidak ada 3 tekanan untuk Anda.
A0-A15 adalah bus alamat. Di atasnya, prosesor menampilkan alamat memori (MREQ aktif) atau alamat port I / O (IOREQ aktif) dengan panggilan yang sesuai. Seperti yang Anda lihat, bus berukuran 16 bit, yang memungkinkan Anda untuk langsung menangani memori 64 KiB.
D0-D7 - bus data. Prosesor menghasilkan (WR aktif), atau membaca darinya (RD aktif) data yang diminta.

Jadi, kita akan menempatkan prosesor di atas papan tempat memotong roti. Jadi kesimpulannya secara fisik terletak:

gambar

Hubungkan daya (pin 11 dan 29). Untuk jaga-jaga, saya juga meletakkan kapasitor 10 pF di antara kedua kaki ini. Tetapi pada akhirnya dia tidak membantu saya. Pin 27, 23, 18 mungkin tetap tidak terhubung dengan apa pun. Pin 26, 25, 24, 17, 16 terhubung melalui resistor (saya menggunakan 10 kOhm) ke catu daya. Saya membawa bus alamat (pin 1-5 dan 30-40) ke sisi berlawanan dari papan tempat memotong roti, dan bus data (pin 7-10 dan 12-15) ke bus data terpisah yang terbuat dari bus listrik prototipe.
Pin 6 (sinyal jam) dan 26 (RESET) terhubung (kemudian) ke Arduin sehingga Anda dapat mengontrol prosesor dari itu.

Ternyata seperti ini:



Sampai Anda memperhatikan kabel dari atas, mereka pergi dari ROM, kami akan pindah sedikit nanti. Juga, dalam foto di sebelah prosesor, satu chip lagi terlihat. Kami membutuhkannya untuk memecahkan kode bit atas alamat. Seperti yang saya katakan di atas, ada 3 jenis memori dalam Spectrum. Lebih rendah 16 KiB dari ruang alamat adalah ROM. Dengan demikian, jika terminal A14 dan A15 dalam keadaan rendah (0 Volts), kita perlu memutuskan segalanya kecuali chip ROM dari bus. Selanjutnya adalah 16 KiB memori bersama. Oleh karena itu, kita perlu menghubungkan memori ini ke bus (dan lepaskan sisanya) jika output A15 rendah dan A14 tinggi (+5 Volts). Nah, kemudian datang memori cepat 32 KiB. Kami akan memasang memori ini nanti, dan kami akan mengaktifkannya jika output A15 dalam keadaan tinggi. Selain itu, jangan lupa bahwa kami hanya mengaktifkan memori saat aktif (di sini, aktif - rendah,0 Volt) MREQ dan tidak aktif (di sini, tidak aktif - tinggi, + 5V) RFSH. Semua ini cukup sederhana untuk diterapkan pada logika standar, pada NAND yang sama, seperti 74HC00, atau Orthodox K155LA3, dan saya mengerti tugas ini adalah untuk kelompok persiapan TK, namun, saya hanya dapat berpikir dalam tabel kebenaran dalam kebebasan dan dalam penahanan.Saya memiliki diagram Harlequin lengkap di sana , dari mana Anda dapat mengambil bagian di mana U4 ditarik (74HC138, untungnya saya memiliki sekitar seratus dari mereka). Kami akan mengabaikan U11 untuk kejelasan, karena 32KiB atas tidak menarik bagi kami sejauh ini.

Menghubungkan sangat sederhana.



Seperti yang bisa dilihat dari uraian singkatnyaMicrocircuit adalah dekoder yang menerima angka biner dari 000 hingga 111 pada terminal 1 hingga 3 dan mengaktifkan salah satu dari 8 output (kaki 7 dan 9 hingga 15) yang sesuai dengan nomor ini. Karena hanya 8 angka berbeda yang dapat disimpan dalam 3 bit, hanya ada delapan output. Seperti yang Anda lihat, kesimpulannya terbalik, yaitu yang akan aktif akan memiliki level 0V, dan yang lainnya +5V. Selain itu, kunci dalam bentuk gerbang 3-input tipe "I" dibangun ke dalam chip, dan dua dari tiga inputnya juga terbalik.

Dalam kasus kami, kami menghubungkan dekoder itu sendiri sebagai berikut: bit yang paling signifikan (leg ke-3) ke tanah, akan selalu ada 0. Bit tengah adalah untuk garis A15. Hanya akan ada 1 jika prosesor mengakses memori 32KiB atas (alamat 0x8000 - 0xFFFF, atau 1000000000000000 - 111111111111111111 dalam biner, ketika bit paling signifikan selalu disetel ke 1). Kami menghubungkan bit paling tidak signifikan ke garis A14, di mana level tinggi akan dalam hal mengakses baik memori setelah 16 KiB pertama, tetapi naik ke atas 32 KiB (alamat 0x4000 - 0x7FFF, atau 0100000000000000 - 011111111111111111 dalam bentuk biner), atau ke 16 KiB terbaru dari alamat spasi (alamat 0xB000 - 0xFFFF, atau 1100000000000000 - 111111111111111111 dalam bentuk biner).

Mari kita lihat apa hasilnya pada masing-masing kasus:

  • 14 15 , 16 , , 000, 0 ( ), Y0 (15 ). , .
  • 14 , 15 — , 16 , 32 , 001, 1 , Y1 (14 ). , 16 , .
  • 14 , 15 — , - 32 48 , 010, Y2 (13 ). , .
  • Jika kedua saluran (A14 dan A15) aktif, prosesor mengakses 16 KiB memori teratas, dari 48 hingga 64 KiB, kami tidak memilikinya, sehingga pin Y3 (pin ke-12) juga ada di udara.

Selain itu, berkat elemen lain, rangkaian mikro akan mengaktifkan temuannya hanya jika input 4 dan 5 rendah dan 6 tinggi. Input ke-4 selalu dalam kondisi rendah (terhubung langsung ke ground), input ke-5 hanya akan rendah ketika prosesor mengakses memori (ingat, MREQ dalam kondisi rendah berarti mengakses memori), dan ke-6 akan menjadi tinggi ketika prosesor tidak melakukan siklus pembaruan DRAM (kami memiliki SRAM, jadi siklus pembaruan DRAM adalah cara teraman untuk diabaikan). Ternyata bagus.

Selanjutnya, letakkan ROM.

Saya mengambil W27C512 karena harganya murah, ceria, semuanya akan pas dan Anda juga bisa bank. 64KiB! 4 firmware dapat diunggah. Ya, saya punya sekitar satu juta dari sirkuit mikro ini. Saya memutuskan bahwa saya hanya akan menjahit bagian atas, karena pada Harlequin kaki A15 diikat ke + 5V, dan A14 disesuaikan dengan jumper. Jadi, saya bisa menguji firmware pada Harlequin agar tidak dipusingkan untuk waktu yang lama. Lembar data smorim . Kami menempatkan chip di papan tempat memotong roti. Sekali lagi, saya meletakkannya di sudut kanan untuk menempatkan bus alamat di sebelah kiri. Kami menarik kaki A15 ke kekuasaan, kabel A14 ke tanah. Pengkabelan - ini agar Anda dapat mengubah bank memori. Karena A15 akan selalu berada pada level tinggi, hanya 32 KiB flash drive teratas yang akan tersedia untuk kita. Dari jumlah tersebut, garis A14 akan memilih 16 KiB atas (+ 5V) atau lebih rendah. Di dalamnya, saya mengisi gambar uji dengan programmerdan 48K firmware DASAR .

14 baris alamat yang tersisa (A0 - A13) terhubung ke bus alamat di sebelah kiri. Kami menghubungkan bus data (Q0 - Q7) ke bus improvisasi kami dalam bentuk bus listrik dari model papan tempat memotong roti. Jangan lupakan makanan!

Sekarang sinyal kontrol. OE adalah keluaran yang memungkinkan. Kami membutuhkan ROM untuk mengirim data ke bus data ketika prosesor membacanya. Jadi kami terhubung langsung ke output prosesor RD. Dengan mudah, kedua pin, baik OE pada ROM dan RD pada prosesor, aktif dalam kondisi rendah. Ini penting, Anda tidak perlu membalikkan apa pun. Selain itu, ROM memiliki input CS, juga aktif dalam kondisi rendah. Jika input ini tidak aktif, ROM akan mengabaikan semua sinyal lain dan tidak akan mengeluarkan apa pun ke bus data. Kami akan menghubungkan input ini ke pin Y0 (15 pin) dari chip 74HC138, yang juga aktif dalam kondisi rendah. Di sirkuit Harlequin , sinyal ini, untuk beberapa alasan, terhubung melalui resistor. Kami akan melakukan hal yang sama. Kenapa, saya tidak tahu. Mungkin orang pintar memberi tahu saya dalam komentar ... Mereka memberi tahu saya

. Terima kasihsterr:
. , «» . .




Semua.

Sekarang RAM.

Lebih sulit dengan itu, karena tidak hanya prosesor, tetapi juga ULA, atau, dalam kasus kami, Arduino, bekerja dengan RAM (dengan 16 KiB kami). Karena itu perlu untuk membaca sesuatu yang ditampilkan di layar. Oleh karena itu, kita harus dapat memutus sinyal kontrol dan bus alamat RAM dari prosesor. Kami tidak akan memutus bus data, kami akan bertindak seperti dalam spektrum asli (dan dalam Harlequin): kami akan membagi bus dengan resistor (470-500 Ohm). Di satu sisi, resistor akan menjadi prosesor dan ROM, di sisi lain, RAM dan Arduino. Jadi, jika terjadi konflik pada bus data, itu akan berfungsi sebagai 2 bus terpisah. Tetapi untuk sisanya kami menggunakan 74HC245 , seperti pada Harlequin (U43, U44 dalam diagram), meskipun dalam Speccy iniada juga resistor (antara IC1 di satu sisi, ini adalah ULA, dan IC3, IC4 di sisi lain).

74HC245 adalah buffer bus 8-bit. Tetapi kami memiliki 2 sinyal kontrol (RD - dalam hal membaca dari memori dan CE untuk mengaktifkan RAM itu sendiri. Kami akan berurusan dengan WR dalam kasus penulisan ke memori nanti) dan 14 bit alamat: ingat, di atas kami telah menghasilkan sinyal ke memori hanya menggunakan 74HC138 jika prosesor mengaktifkan A14 dengan A15 tidak aktif, jadi kita tidak perlu melakukan decoding alamat tambahan, memori hanya akan berfungsi saat mengakses 16 KiB pertama setelah ROM. Nah, tentu saja, untuk mengatasi 16 KiB Anda hanya perlu 14 baris alamat (A0-A13). Secara total, 16 sinyal diperoleh, jadi kita membutuhkan 2 sirkuit mikro 74HC245. Kami menghubungkan mereka ke papan tempat memotong roti di sebelah kiri, di tempat bus alamat.

Dari lembar data pada 74HC245 jelas bahwa, secara umum, tidak masalah ke sisi mana untuk menyambungkan sirkuit mikro, tetapi karena saya mulai membangun tata letak dari bawah ke atas, dan semua sirkuit mikro lainnya dipasang dengan pin pertama ke kiri, bus alamat akan terhubung ke sisi A (pin 2) -9 chip, dalam lembar data ditetapkan sebagai A0-A7). Arah transfer selalu dari prosesor ke RAM, karena RAM tidak pernah menetapkan alamat, tetapi hanya menerimanya. Pada 74HC245, pin 1 (DIR) bertanggung jawab untuk arah transmisi. Menurut datasheetsehingga output yang sama dengan input dari sisi A muncul di sisi B, DIR harus diatur ke TINGGI. Jadi hubungkan pin 1 dari kedua sirkuit ke + 5V. OE (pin ke-20, diaktifkan oleh level rendah) terhubung menggunakan kabel ke ground sehingga dapat dengan cepat beralih ke +5V dan terputus dari prosesor. Lebih sederhana. Hubungkan daya untuk kedua chip. Pin paling kanan dari rangkaian mikro kanan (pin 8 dan 9, input A6 dan A7) akan menjadi sinyal kontrol. Saya menghubungkan A7 ke terminal RD prosesor, dan A6 ke pin Y1 dari chip 74HC138, karena akan ada level rendah hanya ketika prosesor mengakses RAM kami. Kesimpulan yang tersisa dari sisi A dari kedua sirkuit mikro (kaki 2–9 untuk kiri dan kaki 2–7 untuk kanan) Saya terhubung ke bus alamat, terminal A13-A0. Kita tidak memerlukan 2 bit atas dari alamat, karena mereka sudah diterjemahkan dalam sinyal dari 74HC138.Sekarang tentang RAM itu sendiri. Secara alami, saya menggunakan apa yang sudah saya miliki: chip cache dari motherboard lama. Saya menemukanIS61C256 pada 20 ns, tetapi siapa pun akan melakukannya. Speccy bekerja pada frekuensi 3,5 MHz, tetapi untuk sekarang kita umumnya akan memperlakukan Arduinki. Jika 100 kHz keluar, akan ada kebahagiaan! Jadi, kami terhubung. Tentu saja, jangan lupa soal makanan. Kesimpulan I / O0 - I / O7 terhubung ke papan tempat memotong roti data SETELAH resistor. Saya beruntung (pada kenyataannya, tidak), pada maket Cina saya, bus-bus listrik terbagi persis di tengah. Saya menggunakan fitur ini untuk memisahkan bus dengan resistor. Jika tata letak Anda salah, Anda harus diselewengkanmembuat bus data kedua, dan hubungkan dengan resistor ke yang pertama. Kesimpulan A0-A13 dilemparkan ke B-kesimpulan yang sesuai dari chip 74HC245, tidak lupa bahwa yang paling kanan terhubung bukan ke bus data, tetapi ke sinyal kontrol. A14 - dengan pilihan, baik ke tanah, atau ke + 5V. Chip 32 KiB, jadi kesimpulan ini akan menentukan setengah mana yang akan kita gunakan. Jika Anda menemukan SRAM 16 KiB, tidak akan ada garis A14 di dalamnya. Outputnya adalah KAMI (memungkinkan diaktifkan), CE (memungkinkan chip) dan OE (memungkinkan output). Semua diaktifkan rendah. OE harus terhubung ke RD prosesor, tetapi, tentu saja, tidak secara langsung, tetapi melalui 74HC245 kanan, di mana RD datang ke kaki A7 saya, dan karenanya keluar dari kaki B7 (pin ke-11). Di sana dan terhubung. CE harus terhubung ke Y1 dari 74HC138, yang menerjemahkan kode alamat. Sinyal nya datang kepada saya di A6 dari chip yang tepat 74HC245, masing-masing,keluar dari kaki B6 (12 pin). KITA AKU langsung terhubung ke output prosesor WR. Saya juga memasang kawat jumper dari sinyal OE dan menempelkannya hanya di bagian papan tempat memotong roti yang tidak digunakan. Dengan menghubungkan kabel ini ke catu daya, saya dapat memaksa RAM untuk diaktifkan ketika saya membacanya dari Arduinka. Namun, saya menarik semua sinyal kontrol RAM ke + 5V menggunakan resistor 10 kOhm. Untuk berjaga-jaga. Ternyata seperti ini:



Secara umum, di sini, dan jika sama sekali, di awal, harus ada program pendidikan tentang waktu sinyal pada ban. Saya tidak akan melakukan ini, karena telah dilakukan berkali-kali di jaringan oleh orang-orang yang jauh lebih cerdas daripada saya. Bagi yang tertarik, saya dapat merekomendasikan video ini:


Secara umum, jika Anda tidak berlangganan saluran ini dan tertarik pada elektronik sebagai amatir, dan bukan sebagai profesional, saya sangat merekomendasikannya kepada Anda. Ini adalah konten berkualitas sangat tinggi.

Secara umum, itu hampir semuanya. Sekarang Anda hanya perlu memahami cara membaca data dari RAM di Arduino. Untuk mulai dengan, mari kita hitung berapa banyak kesimpulan Arduinki yang kita butuhkan. Kita perlu memberi sinyal jam dan mengontrol RESET, ini adalah 2 pin. 8 bit bus data - 8 pin lainnya. Ditambah 13 bit alamat, total 23 pin. Selain itu, kita perlu berkomunikasi dengan Arduinka, kita akan melakukan ini melalui antarmuka serialnya, ini adalah 2 pin lainnya. Sayangnya, hanya ada 20 kesimpulan tentang DNA saya.

Yah, itu tidak masalah. Saya tidak tahu satu orang pun yang memiliki Arduino dan tidak memiliki 74HC595. Sepertinya saya hanya dijual dalam kit. Setidaknya saya hanya memiliki chip 74HC00 lebih dari 595x. Jadi kami menggunakannya. Selain itu, saya akan menghemat ruang dalam artikel, karena pekerjaan 595x dengan Arduino dijelaskan dengan sempurna di sini. 595mi kami akan menghasilkan alamat. Chip akan membutuhkan 2 buah (karena kita memiliki 13 bit alamat, dan 595 memiliki 8 pin). Cara menghubungkan beberapa 595x untuk ekspansi bus dijelaskan secara rinci di tautan di atas. Saya hanya mencatat bahwa pada contoh di tautan OE (pin 13) 595x ditarik ke tanah. Kami pasti tidak akan melakukan ini, kami akan mengirim sinyal dari Arduinki di sana, karena pin 595x akan terhubung langsung ke bus alamat RAM, dan kami tidak memerlukan sinyal palsu di sana. Setelah menghubungkan pin 595x ke bus alamat RAM, tidak ada lagi yang perlu dilakukan pada mock-up. Saatnya menghubungkan arduinka. Tapi pertama-tama, tulis sketsa:

// CPU defines
#define CPU_CLOCK_PIN 2
#define CPU_RESET_PIN 3

// RAM defines
#define RAM_OUTPUT_ENABLE_PIN 4
#define RAM_WRITE_ENABLE_PIN 5
#define RAM_CHIP_ENABLE_PIN 6
#define RAM_BUFFER_PIN 7

// Shift Register defines
#define SR_DATA_PIN 8
#define SR_OUTPUT_ENABLE_PIN 9
#define SR_LATCH_PIN 10
#define SR_CLOCK_PIN 11

//////////////////////////////////////////////////////////////////////////

void setup() {
  // All CPU and RAM control signals need to be configured as inputs by default
  // and only changed to outputs when used.
  // Shift register control signals may be preconfigured

  // CPU controls seetup
  DDRC = B00000000;
  pinMode(CPU_CLOCK_PIN, INPUT);
  pinMode(CPU_RESET_PIN, INPUT);

  // RAM setup
  pinMode(RAM_WRITE_ENABLE_PIN, INPUT);
  pinMode(RAM_OUTPUT_ENABLE_PIN, INPUT);
  pinMode(RAM_CHIP_ENABLE_PIN, INPUT);
  pinMode(RAM_BUFFER_PIN, OUTPUT);
  digitalWrite(RAM_BUFFER_PIN, LOW);

  // SR setup
  pinMode(SR_LATCH_PIN, OUTPUT);
  pinMode(SR_CLOCK_PIN, OUTPUT);
  pinMode(SR_DATA_PIN, OUTPUT);
  pinMode(SR_OUTPUT_ENABLE_PIN, OUTPUT);
  digitalWrite(SR_OUTPUT_ENABLE_PIN, HIGH); // active low

  // common setup
  Serial.begin(9600);
  Serial.println("Hello");
}// setup

//////////////////////////////////////////////////////////////////////////

void shiftReadValueFromAddress(uint16_t address, uint8_t *value) {
  // disable RAM output
  pinMode(RAM_WRITE_ENABLE_PIN, OUTPUT);
  digitalWrite(RAM_WRITE_ENABLE_PIN, HIGH); // active low
  pinMode(RAM_OUTPUT_ENABLE_PIN, OUTPUT);
  digitalWrite(RAM_OUTPUT_ENABLE_PIN, HIGH); // active low
  // set address
  digitalWrite(SR_LATCH_PIN, LOW);
  shiftOut(SR_DATA_PIN, SR_CLOCK_PIN, MSBFIRST, address>>8); 
  shiftOut(SR_DATA_PIN, SR_CLOCK_PIN, MSBFIRST, address);  
  digitalWrite(SR_LATCH_PIN, HIGH);
  digitalWrite(SR_OUTPUT_ENABLE_PIN, LOW); // active low
  // write value to RAM
  digitalWrite(RAM_OUTPUT_ENABLE_PIN, LOW); // active low
  delay(1);
  DDRC = B00000000;
  *value = PINC;
  digitalWrite(RAM_OUTPUT_ENABLE_PIN, HIGH); // active low
  // disable SR
  digitalWrite(SR_OUTPUT_ENABLE_PIN, HIGH); // active low
  pinMode(RAM_WRITE_ENABLE_PIN, INPUT);
  pinMode(RAM_OUTPUT_ENABLE_PIN, INPUT);
}// shiftWriteValueToAddress

//////////////////////////////////////////////////////////////////////////

void runClock(uint32_t cycles) {
  uint32_t currCycle = 0;
  pinMode(CPU_CLOCK_PIN, OUTPUT);
  while(currCycle < cycles) {
    digitalWrite(CPU_CLOCK_PIN, HIGH);
    digitalWrite(CPU_CLOCK_PIN, LOW);
    currCycle++;
  }
  pinMode(CPU_CLOCK_PIN, INPUT);
}// runClock

//////////////////////////////////////////////////////////////////////////

void trySpectrum() {
  pinMode(RAM_WRITE_ENABLE_PIN, INPUT);
  pinMode(RAM_OUTPUT_ENABLE_PIN, INPUT);
  pinMode(CPU_RESET_PIN, OUTPUT);
  digitalWrite(CPU_RESET_PIN, LOW);
  runClock(30);
  digitalWrite(CPU_RESET_PIN, HIGH);
  runClock(12500000);
}// trySpectrum

//////////////////////////////////////////////////////////////////////////

void readDisplayLines() {
  uint8_t value;
  digitalWrite(RAM_BUFFER_PIN, HIGH);
  pinMode(RAM_CHIP_ENABLE_PIN, OUTPUT);
  digitalWrite(RAM_CHIP_ENABLE_PIN, LOW);
  for(uint16_t i=16384; i<16384+6144;i++) {
    shiftReadValueFromAddress(i, &value);
    Serial.println(value);
  }
  pinMode(RAM_CHIP_ENABLE_PIN, INPUT);
}// readDisplayLines

//////////////////////////////////////////////////////////////////////////

void loop() {
  trySpectrum();
  Serial.println("Hope we are ok now. Please set up memory for reading");
  delay(40000);
  Serial.println("Reading memory");
  readDisplayLines();
  Serial.println("Done");
  delay(100000);
}// loop

Seperti yang dapat Anda lihat dari sketsa (well, sungguh, tiba-tiba, seseorang membacanya), saya membaca data bus ke port C. Seperti yang diingat Arduischik, di CID port C adalah 6 pin. Artinya, saya hanya membaca 6 bit. Ya, untuk kesederhanaan proses, saya mengabaikan 2 bit tinggi di setiap byte dari buffer layar. Ini akan menghasilkan fakta bahwa setiap 2 piksel setelah 6 akan selalu ada warna latar belakang. Sambil naik, maka perbaiki. Ini kerangkanya.

Sekarang untuk koneksi itu sendiri. Pada prinsipnya, semuanya dilukis di bagian paling atas sketsa:

// CPU defines
#define CPU_CLOCK_PIN 2 -  2     6  ( )
#define CPU_RESET_PIN 3 -  3     26  (RESET)

// RAM defines
#define RAM_OUTPUT_ENABLE_PIN 4 -  4     22  (OE)
#define RAM_WRITE_ENABLE_PIN 5 -  5    .     .
#define RAM_CHIP_ENABLE_PIN 6 -  6     .        ,        .   - ,   -  .   ,   .
#define RAM_BUFFER_PIN 7 -  ,    6,    .

// Shift Register defines
#define SR_DATA_PIN 8   -  8     14 "" 595.        9 ,     .
#define SR_OUTPUT_ENABLE_PIN 9 -   13  595
#define SR_LATCH_PIN 10 -   12  595
#define SR_CLOCK_PIN 11 -   11  595.

Semuanya sederhana. Begini tampilannya seperti semua yang ada di koleksi saya (arduinka terpotong di gambar, tapi tidak banyak yang bisa dilihat):



Saat startup, Arduino dengan ceria mengatakan Halo ke port serial komputer (walaupun virtual), dan mulai menyiksa prosesor. Setelah benar-benar menyiksanya (beberapa menit), program ini akan menghentikan orang miskin dan akan menawarkan Anda untuk mengatur ulang jumper dengan pena di papan tempat memotong roti, melepaskan memori dari bus alamat dan sinyal kontrol prosesor.

Sekarang kita perlu menggunakan pegangan untuk mengatur ulang kabel yang terhubung ke pin 19 dari kedua 74HC245 dari ground ke + 5V. Jadi, kami memutuskan prosesor dari RAM. Pin 22 dari chip RAM itu sendiri harus terhubung ke tanah (saya menulis di atas tentang kabel, yang saya hanya terjebak di papan tempat memotong roti sejauh ini, di tempat yang tidak digunakan). Jadi, kami secara paksa menyalakan RAM.

Setelah itu, setelah menunggu sedikit, Arduinka akan mulai membaca isi dari memori dan mengeluarkannya dalam kolom ke port serial. Akan ada banyak, banyak angka. Sekarang Anda dapat menyalin data ini dari sana dan menempelkannya, katakanlah, ke file teks, tanpa lupa untuk membersihkan semua teks yang tidak perlu (beberapa baris di bagian atas, dan "Selesai" di bagian bawah), kami hanya perlu angka. Inilah yang Speccy kami rekam dalam memori video. Tetap hanya untuk melihat apa yang ada di memori video. Dan memori video Spectrum tidak mudah ...

Seperti yang Anda lihat, pikselnya sendiri disimpan secara terpisah dari warnanya. Kami akan mengabaikan warna untuk saat ini, mari kita baca sendiri pikselnya. Tetapi mereka tidak begitu mudah untuk diterjemahkan. Setelah banyak kesakitan di Visual Studio, saya sampai pada solusi elegan ini:


#include "stdafx.h"
#include <windows.h>
#include <stdint.h>
#include <stdio.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
uint8_t *scrData;

VOID OnPaint(HDC hdc) {
	size_t arrSize = 6144;//sizeof(scrData) / sizeof(scrData[0]);
	//int currRow = 0, currX = 0, currBlock = 0, currY = 0, currBase = 0;
	for (size_t arrPos = 0; arrPos < arrSize; arrPos++) {
		int blockPos = arrPos % 2048;
		int currBase = (blockPos % 256) / 32;
		int currX = blockPos % 32;
		int currBlock = arrPos / 2048;
		int currRow = blockPos / 256;
		int currY = currBlock * 64 + currBase * 8 + currRow;
		for (int trueX = 0; trueX < 8; trueX++) {
			char r = ((scrData[arrPos] >> trueX) & 1)*255;
			SetPixel(hdc, currX * 8 + (8-trueX), currY, RGB(r, r, r));
		}
	}
}

void loadData() {
	FILE *file;
	errno_t err;
	if ((err = fopen_s(&file, "data.txt", "r"))) {
		MessageBox(NULL, L"Unable to oopen the file", L"Error", 1);
	}
	scrData = (uint8_t*)malloc(6144);
	int currDataPos = 0;
	char buffer[256];
	char currChar = 0;
	int currLinePos = 0;
	while (currChar != EOF) {
		currChar = getc(file);
		buffer[currLinePos++] = currChar;
		if (currChar == '\n') {
			buffer[currLinePos] = 0;
			scrData[currDataPos++] = (uint8_t)atoi(buffer);
			currLinePos = 0;
		}
	}
	fclose(file);
}

INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, PSTR, INT iCmdShow) {
	HWND                hWnd;
	MSG                 msg;
	WNDCLASS            wndClass;
	wndClass.style = CS_HREDRAW | CS_VREDRAW;
	wndClass.lpfnWndProc = WndProc;
	wndClass.cbClsExtra = 0;
	wndClass.cbWndExtra = 0;
	wndClass.hInstance = hInstance;
	wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
	wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
	wndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
	wndClass.lpszMenuName = NULL;
	wndClass.lpszClassName = TEXT("GettingStarted");
	RegisterClass(&wndClass);
	hWnd = CreateWindow(
		TEXT("GettingStarted"),   // window class name
		TEXT("Getting Started"),  // window caption
		WS_OVERLAPPEDWINDOW,      // window style
		CW_USEDEFAULT,            // initial x position
		CW_USEDEFAULT,            // initial y position
		CW_USEDEFAULT,            // initial x size
		CW_USEDEFAULT,            // initial y size
		NULL,                     // parent window handle
		NULL,                     // window menu handle
		hInstance,                // program instance handle
		NULL);                    // creation parameters
	loadData();
	ShowWindow(hWnd, iCmdShow);
	UpdateWindow(hWnd);
	while (GetMessage(&msg, NULL, 0, 0)) {
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	return msg.wParam;
}  // WinMain

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
	HDC          hdc;
	PAINTSTRUCT  ps;
	switch (message) {
	case WM_PAINT:
		hdc = BeginPaint(hWnd, &ps);
		OnPaint(hdc);
		EndPaint(hWnd, &ps);
		return 0;
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	default:
		return DefWindowProc(hWnd, message, wParam, lParam);
	}
} // WndProc

Program membuka file data.txt dari direktori-nya. Dalam file ini, output teks dari Arduino (setelah menghapus semua baris tambahan, seperti yang disebutkan di atas.)

Kami memberi makan file yang dihasilkan, dan sebagai hasilnya:



Ya, sementara hasilnya sangat jauh dari ideal, tetapi jelas merupakan output ke layar. Apalagi yang dibutuhkan. Dari ROM dengan firmware diagnostik.

Kerangka komputer sudah siap. Ya, belum memungkinkan untuk menggunakannya, tetapi Anda dapat melihat betapa sangat sederhana komputer 8-bit lama itu diatur. Saya masih berdetak sedikit di atas papan tempat memotong roti, tetapi kesimpulannya hanya bertambah buruk. Tampaknya langkah selanjutnya adalah menyolder papan tempat memotong roti yang normal dan tidak terjual, dengan daya normal.

Tetapi apakah itu perlu?

All Articles