Programmering

Åbning af nye porte til Java med javax.comm

Jeg blev introduceret til javax.comm-pakken med klasser, da jeg opdagede, at de blev brugt i udviklingssættet til Java Ring. (For detaljer om javax.comm, se Rinaldo Di Giorgios Java-udvikler i maj - udgaven af JavaWorld: "Java får seriel support med den nye javax.comm-pakke.") Under mit vanvittige rush på JavaOne for at få et program ind i min ring, stødte jeg på en række problemer, ikke mindst hvor jeg kommunikerede med ringen. Jeg downloadede distributionen fra Java Developer Connection og forsøgte uden held at bruge den til at tale med Java Ring. Senere opdagede jeg problemet med min ring: Jeg havde ikke Dallas Semiconductors ældre API'er installeret korrekt. Da ringen fungerede, glemte jeg dybest set kommunikationspakken. Det vil sige indtil en weekend for omkring en måned siden, hvilket er udgangspunktet for denne historie.

Af mange forskellige grunde (for det meste at gøre med meget interaktive simulerede miljøer - for eksempel spil) kører den primære computer i mit "laboratorium" Windows 95. Men i denne særlige weekend var jeg mere bekymret over en anden computer, der i på mange måder, var omtrent lige så kraftig som Java Ring: en Digital Equipment Corporation PDP-8 / e.

PDP-8 var uden tvivl den første ægte personlige computer. Designet i slutningen af ​​1960'erne og produceret i relativt store mængder i 70'erne, kunne PDP-8 løftes af en enkelt person, blev drevet af 120 volt ledningsstrøm og kostede mindre end 0,000. De fleste af disse computere leveres med en enkelt periferiudstyr: en Teletype Model ASR-33 terminal - den originale "TTY" i computerlingo.

ASR-33-teletypen var en udskrivningsterminal, der fulgte med en papirbåndlæser og hulning. Ja, det var papirbånd, 1 "bredt papir med huller i, der var det primære lagermedium til programmer på PDP-8.

PDP-8 var den første computer, jeg nogensinde har programmeret, og derfor har den en særlig plads i mit hjerte. På grund af nogle tilfældige omstændigheder var jeg desuden på det rigtige sted på det rigtige tidspunkt og formåede at redde en PDP-8, der skulle skrottes som skrammel. Et fotografi af min pris er vist nedenfor.

I denne specielle weekend for ikke så længe siden besluttede jeg at bringe PDP-8 tilbage til livet, om ikke blot for at genopleve de dyrebare tidlige minder og vise min datter, hvor god hun har det med sin "mager gamle 133-MHz Pentium. "

Genoplive en klassiker ved at simulere en anden

For at begynde min vækkelsesindsats var jeg nødt til at få et program ind i PDP-8. På PDP-8 opnås dette ved at følge en tretrins proces:

  1. Ved hjælp af frontpanelkontakterne "taster" brugeren et kort program i den magnetiske kernehukommelse. Dette program kaldes RIM Loader, og dets formål er at indlæse et andet program fra papirbånd, der er i Read-in-Mode eller RIM-format.

  2. RIM Loader lægger papirbåndet i RIM-format. Dette bånd indeholder et program kaldet en BIN Loader, som kan indlæse programmer fra papirbånd i binært (BIN) format.

  3. Endelig kører du BIN Loader for at indlæse det program, du virkelig vil have, som er på et papirbånd i BIN-format. Whew!

Efter at have gennemgået disse tre trin er det program, du vil køre, gemt i kernehukommelsen. Alt, hvad brugeren skal gøre, er at indstille startadressen og bede maskinen om at "gå".

I mit forsøg på at genoplive maskinen var trin 1 ikke noget problem, men trin 2 involverede brugen af ​​papirbåndlæseren i teletypen - og jeg havde ikke en teletype. Selvfølgelig, jeg gjorde har min stationære computer, så det logiske trin var at simulere en papirbåndlæser på mit skrivebord.

Fra et logisk og programmeringsmæssigt synspunkt er simulation af en papirbåndlæser triviel. Du læser simpelthen en fil, der indeholder data fra "båndet", sender den til en seriel port med 110 baud (ja, kun 10 tegn i sekundet), indtil du har brugt filen ud. Jeg kunne skrive et program i C på mit Solaris-system eller mit FreeBSD-system på cirka 10 minutter, der kunne gøre dette - men husk, jeg var på et Windows 95-system, ikke et Unix-system.

Fra dårligt til grimt og tilbage igen

Jeg vidste, at jeg let kunne skrive dette program i C, så det var mit valgte sprog. Dårligt valg. Jeg bragte min kopi af Visual C ++ 5.0 op og piskede ud et simpelt program kaldet sendtape.c der kaldte åben() på kommunikationsporten. Jeg forsøgte at sætte det ind tilstand (tilstanden i Unix, hvor operativsystemet ikke forsøger at fortolke noget på den serielle port som brugerinput) og derefter forsøgte at kompilere det. Oj, nej ioctl () funktion eller tty funktioner - nada, zip, zilch!

Intet problemo, tænkte jeg ved mig selv: "Jeg har hele Microsoft Software Developer's netværksbibliotek på CD med min C-kompilator. Jeg vil foretage en hurtig søgning på nøgleordene 'COM-port'."

Søgningen viste mange referencer til Microsoft Component Object Model (også kaldet COM) og også referencer til MSComm. MSComm er en C ++ - klasse, som Microsoft leverer for at tale med de serielle porte. Jeg kiggede på eksemplerne og blev rystet over, hvor meget kode det ville tage at gøre en så simpel ting som at skrive bytes til den serielle port ved 110 baud. Alt, hvad jeg ønskede at gøre, var at åbne den darnede serielle port, indstille dens baudhastighed og sætte et par byte ned i den - ikke oprette en ny klasse af serielle kommunikationsforbedrede applikationer!

Der sad Blue Dot-receptoren til min Java-ring foran min skærm, og jeg tænkte ved mig selv: "Aha! Folkene i Dallas Semiconductor har fundet ud af, hvordan man kan tale med en seriel port på pc'en. Lad os se, hvad de gør. " Efter at have gennemgået virksomhedens kildekode til Win32 var det klart, at det ikke ville være en simpel opgave at tale med serielle porte.

Java til undsætning

På dette tidspunkt i min weekend tænkte jeg måske, at jeg ville trække en af ​​mine Unix-maskiner til laboratoriet for at kode programmet på det i stedet for at bruge det, jeg allerede havde. Så huskede jeg min erfaring med Java Ring og java.comm-pakken fra Sun. Jeg besluttede at følge denne vej i stedet.

Hvad giver java.comm?

Java Communications API - eller java.comm - giver en platformuafhængig metode til at få adgang til serielle og parallelle porte fra Java. Som med andre Java API'er som JFC, JDBC og Java 3D tvinges et bestemt niveau af indirektion til programmøren til at isolere platformens idé om "hvad en seriel port er" fra programmeringsmodellen. I tilfælde af javax.comm-design bruges emner som enhedsnavne, der varierer fra platform til platform, aldrig direkte. API's tre grænseflader giver platformuafhængig adgang til serielle og parallelle porte. Disse grænseflader giver metodeopkald for at liste de tilgængelige kommunikationsporte, styre delt og eksklusiv adgang til porte og kontrollere specifikke portfunktioner såsom baudrate, paritetsgenerering og flowkontrol.

Da jeg så eksemplet SimpleWrite.java i dokumentationen og sammenlignede dens 40 kodelinjer med de 150 til 200 linier kode, jeg så på at skrive i C, vidste jeg, at løsningen var ved hånden.

Abstraktionen på højt niveau for denne pakke er klassen javax.comm.CommPort. Det CommPort klasse definerer de slags ting, du typisk ville gøre med en port, som inkluderer hentning InputStream og OutputStream objekter, der er I / O-kanalerne til porten. Det CommPort klasse inkluderer også metoder til styring af bufferstørrelser og justering af, hvordan input håndteres. Da jeg vidste, at disse klasser understøttede Dallas Semiconductor One-Wire-protokollen (en protokol, der involverede dynamiske ændringer i baudhastighed og fuldstændig gennemsigtighed for de bytes, der blev overført), vidste jeg, at javax.comm API måtte være fleksibel. Det, der kom som en behagelig overraskelse, var, hvor tæt klasserne var: De havde lige nok fleksibilitet til at få arbejdet gjort og ikke mere. Der var ringe eller ingen unødvendige bloatware i form af "bekvemhedsmetoder" eller understøttelse af modemprotokoller som Kermit eller xmodem.

En ledsagerklasse til CommPort er javax.comm.CommPortIdentifier klasse. Denne klasse abstraherer forholdet mellem, hvordan en port er navngivet på et bestemt system (det vil sige "/ dev / ttya" på Unix-systemer, og "COM1" på Windows-systemer), og hvordan porte opdages. Den statiske metode getCommPortIdentifiers vil liste alle kendte kommunikationsporte på systemet; desuden kan du tilføje dine egne portnavne til pseudokommunikationsporte ved hjælp af addPortName metode.

Det CommPort klasse er faktisk abstrakt, og hvad du får tilbage fra en påkaldelse af openPort i CommPortIdentifier er en underklasse af CommPort det er enten ParallelPort eller Serie Port. Disse to underklasser har hver yderligere metoder, der giver dig mulighed for at kontrollere selve porten.

Kraften i Java

Du kan argumentere for virkeligheden af ​​at "skrive en gang, køre hvor som helst" alt hvad du vil, men jeg vil fortælle dig af erfaring, at Java for enkelttrådede eller endda enkle multitrådede ikke-GUI-applikationer er der. Specifikt, hvis du vil skrive et program, der kører på Unix-systemer, Win32 og Mac-systemer og kan få adgang til den serielle port, så er Java kun løsning i dag.

Fordelen her er, at der kræves færre ressourcer til at vedligeholde kode, der kører på et stort antal platforme - og dette reducerer omkostningerne.

Et antal applikationer deler et krav om at have ret lavt niveau adgang til den serielle port. Begrebet lavt niveau betyder i denne sammenhæng, at et program har adgang til grænseflader, der tillader det at ændre tilstande on-the-fly og direkte prøveudskifte og ændre tilstandene for hardware flow-kontrol pins. Udover mit PDP-8-projekt havde Dallas Semiconductor brug for at bruge sine Blue Dot-grænseflader på serielle porte til at tale med iButton med Java. Derudover har producenterne af mikroprocessorer evalueringskort, der bruger en seriel port til kommunikation og programindlæsning. Alle disse applikationer kan nu skrives fuldstændigt og bærbart i Java - en ret stærk erklæring.

Al denne styrke til at kontrollere værtsmaskinens parallelle og serielle porte kommer fra biblioteket javax.comm. At give Java-programmører adgang til portene åbner et helt nyt sæt applikationer, der er målrettet mod indlejrede systemer. I mit tilfælde gav det mig muligheden for at skrive min TTY-båndlæseremulator fuldstændigt i Java.

Hvordan kan du lege med disse ting?

For at få en kopi af den nyeste javax.comm-distribution skal du først tilmelde dig som udvikler på Java Developer Connection (JDC), hvis du ikke allerede har gjort det. (Se ressourcer.) JDC er gratis, og som medlem får du tidlig adgang til Java-klasser, der til sidst vil være en del af det endelige produkt.

Gå til sektionen Java Communications API, og download den nyeste javax.comm arkivfil. Udpak filen og installer de delte biblioteker (ja, den virtuelle Java-maskine har brug for indbygget kode for at tale med portene - heldigvis for dig behøver du ikke skrive den), og installer filen comm.jar. Til sidst skal du tilføje comm.jar-filen til din CLASSPATH variabel.

Når comm.jar-filen er gemt i lib-biblioteket i din Java-installation, og win32comm.dll er gemt i bin-biblioteket i din Java-installation, kan du kompilere og køre alle de eksempler, der følger med downloadet. Jeg opfordrer dig til at se på dem, da der er masser af gode oplysninger inde i kildekoden.

Hvor forlader dette PDP-8?

Så hvad er der sket med PDP-8? Jeg troede, du aldrig ville spørge! Efter at have læst README-dokumentet, der fulgte med javax.comm-distributionen, og derefter scannet JavaDocs for javax.comm-pakken, sammensatte jeg en applikationsklasse kaldet SendTape. Denne klasse simulerer en papirbåndlæser ved at åbne den serielle port og fylde bytes over den ved 110 baud. Koden til denne klasse vises her:

import javax.comm. *; import java.io. *; offentlig klasse SendTape {static final int LEADER = 0; statisk endelig int COLLECT_ADDR = 1; statisk endelig int COLLECT_DATA = 2; statisk endelig int COLLECT_DATA2 = 3; / * Denne matrix indeholder en kopi af BIN-formatindlæser * / statisk byte binloader [] = {(byte) 0x80, (byte) 0x80, (byte) 0x80, (byte) 0x80, ... (byte) 0x80, ( byte) 0x80,}; 

Kodefragmentet ovenfor er den første del af SendTape klasse. Denne klasse begynder med implicit at importere alle klasser i pakken javax.comm og pakkerne java.io. Det SendTape klasse definerer derefter nogle konstanter og initialiserer et byte-array til at indeholde det BIN Loader-program, jeg nævnte tidligere. Jeg inkluderede BIN Loader, fordi det altid er nødvendigt, når du initialiserer hukommelsen til PDP-8, og jeg blev ved med at miste styr på, hvor jeg sidst havde gemt filen, der indeholdt dens billede, i RIM-format. Med dette vigtige papirbåndsbillede indlejret i klassen på denne måde har jeg altid evnen til at indlæse det med denne klasse.

 / ** * Denne metode kører en mini-state maskine, der giver * et nyttigt menneskeligt læsbart output af, hvad der sker * med downloadet. * / static int newState (int oldState, byte b) {...} 

Efter initialiseringen har du koden til metoden newState, vist ovenfor, der sporer indholdet af papirbåndet (hvad enten det er adresseinformation eller programmeringsinformation). Metoden ovenfor udskriver også en besked for hver placering af hukommelse på PDP-8, der er initialiseret.

Dernæst har du vigtigste fremgangsmåde, som er vist nedenfor; det åbner filen og læser den ind. Derefter åbner koden den serielle port og indstiller dens kommunikationsparametre.