Membuka port baru ke Java dengan javax.comm

Saya diperkenalkan dengan paket kelas javax.comm ketika saya menemukan mereka digunakan dalam kit pengembangan untuk Java Ring. (Untuk detail tentang javax.comm, lihat kolom Pengembang Java Rinaldo Di Giorgio di JavaWorld edisi Mei: "Java mendapat dukungan serial dengan paket javax.comm baru.") Selama kesibukan saya di JavaOne untuk memasukkan program ke dalam ring saya, saya mengalami berbagai masalah, tidak sedikit yang berkomunikasi dengan ring. Saya mendownload distribusi dari Java Developer Connection dan mencoba tidak berhasil menggunakannya untuk berbicara dengan Java Ring. Kemudian, saya menemukan masalah dengan cincin saya: Saya tidak memasang API warisan Dallas Semiconductor dengan benar. Dengan cincin yang berfungsi, saya pada dasarnya lupa tentang paket komunikasi. Artinya, sampai suatu akhir pekan sekitar sebulan yang lalu, yang menjadi titik awal cerita ini.

Untuk berbagai alasan (kebanyakan berkaitan dengan lingkungan simulasi yang sangat interaktif - misalnya, permainan), komputer utama di "lab" saya menjalankan Windows 95. Namun, pada akhir pekan ini saya lebih memperhatikan komputer lain yang, di dalam banyak hal, sekuat Java Ring: Digital Equipment Corporation PDP-8 / e.

PDP-8 bisa dibilang komputer pribadi pertama yang sebenarnya. Didesain pada akhir 1960-an dan diproduksi dalam jumlah yang relatif tinggi di tahun 70-an, PDP-8 dapat diangkat oleh satu orang, ditenagai oleh arus saluran 120 volt, dan harganya kurang dari 0.000. Sebagian besar komputer ini dikirim dengan satu perangkat: terminal Teletype Model ASR-33 - "TTY" yang asli dalam istilah komputer.

Teletype ASR-33 adalah terminal pencetakan yang dilengkapi dengan pembaca pita kertas dan pelubang kertas. Ya, itu adalah selotip kertas, kertas selebar 1 "dengan lubang berlubang, yang merupakan media penyimpanan utama untuk program pada PDP-8.

PDP-8 adalah komputer pertama yang pernah saya program dan karena itu memiliki tempat khusus di hati saya. Lebih lanjut, karena beberapa keadaan kebetulan, saya berada di tempat yang tepat pada waktu yang tepat dan berhasil menyelamatkan PDP-8 yang akan dibuang sebagai sampah. Foto hadiah saya ditampilkan di bawah.

Pada akhir pekan yang istimewa ini belum lama ini, saya memutuskan untuk menghidupkan kembali PDP-8, jika hanya untuk menghidupkan kembali kenangan awal yang berharga itu dan untuk menunjukkan kepada putri saya betapa baiknya dia memilikinya dengan Pentium "Measley 133-MHz tua". "

Menghidupkan kembali satu klasik dengan mensimulasikan yang lain

Untuk memulai usaha kebangunan rohani saya, saya harus memasukkan program ke dalam PDP-8. Pada PDP-8, ini dicapai dengan mengikuti proses tiga langkah:

  1. Menggunakan saklar panel depan, pengguna "kunci" program pendek ke dalam memori inti magnetik. Program ini disebut RIM Loader, dan tujuannya adalah untuk memuat program lain dari pita kertas dalam format Read-in-Mode, atau RIM.

  2. RIM Loader memuat pita kertas dalam format RIM. Rekaman ini berisi program yang disebut BIN Loader, yang dapat memuat program dari pita kertas dalam format biner (BIN).

  3. Terakhir, Anda menjalankan BIN Loader untuk memuat program yang benar-benar Anda inginkan, yang ada pada pita kertas dalam format BIN. Wah!

Setelah melalui tiga langkah ini, program yang ingin Anda jalankan disimpan di memori inti. Yang perlu dilakukan pengguna adalah menyetel alamat awal dan memberi tahu mesin untuk "pergi."

Dalam upaya saya untuk menghidupkan kembali mesin, Langkah 1 tidak ada masalah, tetapi Langkah 2 melibatkan penggunaan pembaca pita kertas di Teletype - dan saya tidak memiliki Teletype. Tentu saja, saya memang memiliki komputer desktop saya, jadi langkah logisnya adalah mensimulasikan pembaca pita kertas di desktop saya.

Dari sudut pandang logis dan pemrograman, mensimulasikan pembaca pita kertas itu sepele. Anda cukup membaca file yang berisi data dari "tape", mengirimkannya ke port serial dengan kecepatan 110 baud (ya, hanya 10 karakter per detik), sampai Anda kehabisan file. Saya dapat menulis program dalam C pada sistem Solaris saya atau sistem FreeBSD saya dalam waktu sekitar 10 menit yang dapat melakukan ini - tetapi, ingat, saya menggunakan sistem Windows 95, bukan sistem Unix.

Dari buruk menjadi jelek dan kembali lagi

Saya tahu saya dapat dengan mudah menulis program ini dalam C, jadi itu adalah bahasa pilihan saya. Pilihan yang buruk. Saya membawa salinan Visual C ++ 5.0 dan mengeluarkan program sederhana bernama sendtape.c yang memanggil open()port komunikasi. Saya mencoba mengaturnya ke mode RAW (mode di Unix di mana sistem operasi tidak mencoba menafsirkan apa pun di port serial sebagai input pengguna) dan kemudian mencoba mengkompilasinya. Ups, tidak ada ioctl()fungsi atau ttyfungsi - nada, zip, nihil!

Tidak masalah, saya berpikir, "Saya memiliki seluruh pustaka Jaringan Pengembang Perangkat Lunak Microsoft dalam CD dengan kompiler C saya; saya akan melakukan pencarian cepat pada kata kunci 'COM port'."

Pencarian menemukan banyak referensi ke Model Objek Komponen Microsoft (juga disebut COM), dan juga referensi ke MSComm. MSComm adalah kelas C ++ yang disediakan Microsoft untuk berbicara dengan port serial. Saya melihat contoh-contoh dan terkejut betapa banyak kode yang diperlukan untuk melakukan hal yang sederhana seperti menulis byte ke port serial di 110 baud. Yang ingin saya lakukan hanyalah membuka port serial terkutuk, mengatur baud rate-nya, dan memasukkan beberapa byte ke bawahnya - bukan membuat kelas baru dari aplikasi komunikasi serial yang ditingkatkan!

Duduk di depan monitor saya adalah reseptor Blue Dot untuk Java Ring saya, dan saya berpikir, "Aha! Orang-orang di Dallas Semiconductor telah menemukan cara berbicara dengan port serial di PC. Mari kita lihat apa yang mereka lakukan. " Setelah melihat-lihat kode sumber perusahaan untuk Win32, jelas bahwa berbicara dengan port serial tidak akan menjadi tugas yang mudah.

Java untuk menyelamatkan

Pada titik ini di akhir pekan saya, saya berpikir mungkin saya akan menyeret salah satu mesin Unix saya ke lab untuk membuat kode program di atasnya daripada menggunakan apa yang sudah saya miliki. Kemudian saya teringat pengalaman saya dengan Java Ring dan paket java.comm dari Sun. Saya memutuskan untuk mengejar jalan itu sebagai gantinya.

Apa yang java.comm sediakan?

Java Communications API - atau java.comm - menyediakan metode platform-independen untuk mengakses port serial dan paralel dari Java. Seperti Java API lainnya seperti JFC, JDBC, dan Java 3D, tingkat tipuan tertentu memaksa programmer untuk mengisolasi ide platform tentang "apa itu port serial" dari model pemrograman. Dalam kasus desain javax.comm, item seperti nama perangkat, yang bervariasi dari platform ke platform, tidak pernah digunakan secara langsung. Tiga antarmuka API menyediakan akses platform-independen ke port serial dan paralel. Antarmuka ini menyediakan panggilan metode untuk membuat daftar port komunikasi yang tersedia, kontrol bersama dan akses eksklusif ke port, dan mengontrol fitur port tertentu seperti baud rate, parity generation, dan flow control.

Ketika saya melihat contoh SimpleWrite.java di dokumentasi, dan membandingkan 40 baris kodenya dengan 150 hingga 200 baris kode yang saya lihat menulis di C, saya tahu solusinya sudah dekat.

Abstraksi tingkat tinggi untuk paket ini adalah kelasnya javax.comm.CommPort. The CommPortkelas mendefinisikan hal-hal yang biasanya Anda akan melakukan dengan port, yang mencakup mendapatkan InputStreamdan OutputStreambenda-benda yang merupakan saluran I / O untuk pelabuhan. ItuCommPortclass juga menyertakan metode untuk mengontrol ukuran buffer dan menyesuaikan bagaimana input ditangani. Karena saya tahu kelas-kelas ini mendukung protokol Satu Kawat Semikonduktor Dallas (protokol yang melibatkan perubahan dinamis dalam kecepatan baud, dan transparansi penuh pada byte yang ditransfer), saya tahu API javax.comm harus fleksibel. Yang datang sebagai kejutan yang menyenangkan adalah betapa ketatnya kelas: Mereka memiliki cukup fleksibilitas untuk menyelesaikan pekerjaan dan tidak lebih. Ada sedikit atau tidak ada bloatware yang tidak perlu dalam bentuk "metode kemudahan" atau dukungan protokol modem seperti Kermit atau xmodem.

A companion class to CommPort is the javax.comm.CommPortIdentifier class. This class abstracts the relationship between how a port is named on a particular system (that is, "/dev/ttya" on Unix systems, and "COM1" on Windows systems) and how ports are discovered. The static method getCommPortIdentifiers will list all known communication ports on the system; furthermore, you can add your own port names for pseudo communication ports using the addPortName method.

The CommPort class is actually abstract, and what you get back from an invocation of openPort in the CommPortIdentifier is a subclass of CommPort that is either ParallelPort or SerialPort. These two subclasses each have additional methods that let you control the port itself.

The power of Java

You can argue about the reality of "write once, run anywhere" all you want, but I will tell you from experience that for single- threaded or even simple multithreaded non-GUI applications, Java is there. Specifically, if you want to write a program that runs on Unix systems, Win32, and Mac systems, and can access the serial port, then Java is the only solution today.

The benefit here is that fewer resources are required to maintain code that runs on a large number of platforms -- and this reduces cost.

A number of applications share a requirement to have pretty low-level access to the serial port. The term low-level in this context means that a program has access to interfaces that allow it to change modes on-the-fly and directly sample and change the states of the hardware flow-control pins. Besides my PDP-8 project, Dallas Semiconductor needed to use its Blue Dot interfaces on serial ports to talk to the iButton with Java. In addition, the makers of microprocessors have evaluation boards that use a serial port for communications and program loading. All of these applications can now be completely, and portably, written in Java -- a pretty powerful statement.

All of this power to control the parallel and serial ports of the host machine comes from the javax.comm library. Giving Java programmers access to the ports opens up an entirely new set of applications that target embedded systems. In my case, it gave me the ability to write my TTY paper-tape reader emulator completely in Java.

How do you get to play with this stuff?

To get a copy of the latest javax.comm distribution, first you need to sign up as a developer on the Java Developer Connection (JDC) if you haven't done so already. (See Resources.) JDC is free, and as a member you will get early access to Java classes that will eventually be part of the final product.

Go to the Java Communications API section and download the latest javax.comm archive file. Unpack the file and install the shared libraries (yes, the Java virtual machine needs native code to talk to the ports -- fortunately for you, you don't have to write it), and install the comm.jar file. Finally, add the comm.jar file to your CLASSPATH variable.

Once the comm.jar file is stored in the lib directory of your Java installation, and the win32comm.dll is stored in the bin directory of your Java installation, you can compile and run all the examples that come with the download. I encourage you to look them over as there is lots of good information nestled in with the source code.

Where does this leave the PDP-8?

So, what's happened with the PDP-8? I thought you'd never ask! After reading the README document that came with the javax.comm distribution, then scanning the JavaDocs for the javax.comm package, I put together an application class called SendTape. This class simulates a paper-tape reader by opening the serial port and stuffing bytes over it at 110 baud. The code for this class is shown here:

import javax.comm.*; import java.io.*; public class SendTape { static final int LEADER = 0; static final int COLLECT_ADDR = 1; static final int COLLECT_DATA = 2; static final int COLLECT_DATA2 = 3; /* This array holds a copy of the BIN format loader */ static byte binloader[] = { (byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80, ... (byte) 0x80,(byte) 0x80, }; 

The code fragment above is the first part of the SendTape class. This class begins by implicitly importing all classes in the javax.comm package and the java.io packages. The SendTape class then defines some constants and pre-initializes a byte array to contain the BIN Loader program I mentioned earlier. I included the BIN Loader because it is always needed when initializing the memory of the PDP-8 and I kept losing track of where I had last stored the file containing its image in RIM format. With this crucial paper tape image embedded in the class in this way, I always have the ability to load it with this class.

 /** * This method runs a mini-state machine that gives * a useful human readable output of what is happening * with the download. */ static int newState(int oldState, byte b) { ... } 

Setelah inisialisasi, Anda memiliki kode untuk metode newState, yang ditunjukkan di atas, yang melacak isi pita kertas (apakah itu informasi alamat atau informasi pemrograman). Metode di atas juga mencetak pesan untuk setiap lokasi memori pada PDP-8 yang diinisialisasi.

Selanjutnya Anda memiliki mainmetode, yang ditunjukkan di bawah ini; itu membuka file dan membacanya masuk Kemudian kode membuka port serial dan mengatur parameter komunikasinya.