Programmering

Åpne nye porter til Java med javax.comm

Jeg ble introdusert for javax.comm-pakken med klasser da jeg oppdaget at de ble brukt i utviklingspakken til Java Ring. (For detaljer om javax.comm, se Rinaldo Di Giorgios Java Developer kolonne i mai-utgaven av JavaWorld: "Java får seriell støtte med den nye javax.comm-pakken.") I løpet av det vanvittige jaget mitt på JavaOne for å få et program i ringen min, kom jeg inn på en rekke problemer, ikke minst som det var å kommunisere med ringen. Jeg lastet ned distribusjonen fra Java Developer Connection og prøvde uten hell å bruke den til å snakke med Java Ring. Senere oppdaget jeg problemet med ringen min: Jeg hadde ikke Dallas Semiconductors eldre API-er installert riktig. Da ringen fungerte, glemte jeg i utgangspunktet kommunikasjonspakken. Det vil si inntil en helg for omtrent en måned siden, som er utgangspunktet for denne historien.

Av mange forskjellige grunner (for det meste å gjøre med svært interaktive simulerte miljøer - for eksempel spill), kjører den primære datamaskinen i "laboratoriet" mitt Windows 95. Imidlertid var jeg i denne helgen mer opptatt av en annen datamaskin som på mange måter, var omtrent like kraftig som Java Ring: en Digital Equipment Corporation PDP-8 / e.

PDP-8 var uten tvil den første sanne personlige datamaskinen. Designet på slutten av 1960-tallet og produsert i relativt store mengder på 70-tallet, kunne PDP-8 løftes av en enkelt person, ble drevet av 120 volt ledningsstrøm og kostet mindre enn 0,000. De fleste av disse datamaskinene leveres med en enkelt periferiutstyr: en Teletype Model ASR-33-terminal - den originale "TTY" i datamaskinspråket.

ASR-33-telefontypen var en utskriftsterminal som fulgte med en papirbåndleser og slag. Jepp, det var papirbånd, 1 "stort papir med hull i det, som var det primære lagringsmediet for programmer på PDP-8.

PDP-8 var den første datamaskinen jeg noensinne har programmert, og derfor har den en spesiell plass i hjertet mitt. Videre, på grunn av noen tilfeldige omstendigheter, var jeg på rett sted til rett tid og klarte å redde en PDP-8 som skulle skrotes som søppel. Et fotografi av premien min er vist nedenfor.

På denne spesielle helgen for ikke så lenge siden bestemte jeg meg for å bringe PDP-8 tilbake til livet, om ikke bare for å gjenoppleve de dyrebare tidlige minnene og for å vise datteren min hvor god hun har det med sin "masley gamle 133-MHz Pentium. "

Gjenopplive en klassiker ved å simulere en annen

For å starte vekkelsesarbeidet mitt, måtte jeg få et program inn i PDP-8. På PDP-8 oppnås dette ved å følge en tretrinnsprosess:

  1. Ved å bruke frontpanelbryterne "taster" brukeren et kort program inn i det magnetiske kjerneminnet. Dette programmet kalles RIM Loader, og formålet er å laste et annet program fra papirbånd som er i Read-in-Mode, eller RIM-format.

  2. RIM Loader laster papirbåndet i RIM-format. Dette båndet inneholder et program kalt en BIN Loader, som kan laste programmer fra papirbånd i binært (BIN) format.

  3. Til slutt kjører du BIN Loader for å laste programmet du virkelig ønsker, som er på papirbånd i BIN-format. Whew!

Etter å ha gått gjennom disse tre trinnene, lagres programmet du vil kjøre i kjerneminnet. Alt brukeren trenger å gjøre er å angi startadressen og be maskinen om å "gå".

I mitt forsøk på å gjenopplive maskinen var trinn 1 ikke noe problem, men trinn 2 involverte bruken av papirbåndleseren i Teletype - og jeg hadde ikke en Teletype. Selvfølgelig, jeg gjorde har den stasjonære datamaskinen min, så det logiske trinnet var å simulere en papirbåndleser på skrivebordet mitt.

Fra et logisk og programmeringsmessig synspunkt er det å simulere en papirbåndleser trivielt. Du leser ganske enkelt en fil som inneholder dataene fra "båndet", sender den ut til en seriell port på 110 baud (ja, bare 10 tegn per sekund), til du har brukt opp filen. Jeg kunne skrive et program i C på Solaris-systemet eller FreeBSD-systemet mitt på omtrent 10 minutter som kunne gjøre dette - men husk, jeg var på et Windows 95-system, ikke et Unix-system.

Fra dårlig til stygg og tilbake igjen

Jeg visste at jeg lett kunne skrive dette programmet i C, så det var språket jeg valgte. Dårlig valg. Jeg tok opp eksemplaret av Visual C ++ 5.0 og pisket ut et enkelt program kalt sendtape.c som ringte åpen() på kommunikasjonsporten. Jeg prøvde å sette det inn modus (modus i Unix der operativsystemet ikke prøver å tolke noe på den serielle porten som brukerinngang) og deretter prøvde å kompilere den. Oj, nei ioctl () funksjon eller tty funksjoner - nada, zip, zilch!

Ikke noe problemo, tenkte jeg for meg selv: "Jeg har hele Microsoft Software Developer's nettverksbibliotek på CD med C-kompilatoren min. Jeg vil gjøre et raskt søk på nøkkelordene" COM-port "."

Søket viste mange referanser til Microsoft Component Object Model (også kalt COM), og også referanser til MSComm. MSComm er en C ++ - klasse som Microsoft leverer for å snakke med serielle porter. Jeg så på eksemplene og ble forferdet over hvor mye kode som skulle til for å gjøre en så enkel ting som å skrive byte til serieporten på 110 baud. Alt jeg ønsket å gjøre var å åpne den darnede serielle porten, sette baudhastigheten og legge noen byte ned i den - ikke lage en ny klasse med serielle kommunikasjonsforbedrede applikasjoner!

Det satt Blue Dot-reseptoren for Java-ringen min foran skjermen min, og jeg tenkte med meg selv: "Aha! Folkene i Dallas Semiconductor har funnet ut hvordan de skal snakke med en seriell port på PC-en. La oss se hva de gjør. " Etter å ha sett igjennom selskapets kildekode for Win32, var det klart at å snakke med serielle porter ikke skulle være en enkel oppgave.

Java til unnsetning

På dette punktet i helgen min tenkte jeg kanskje å dra en av Unix-maskinene mine til laboratoriet for å kode programmet på den i stedet for å bruke det jeg allerede hadde. Da husket jeg min erfaring med Java Ring og java.comm-pakken fra Sun. Jeg bestemte meg for å forfølge den alléen i stedet.

Hva gir java.comm?

Java Communications API - eller java.comm - gir en plattformuavhengig metode for tilgang til serielle og parallelle porter fra Java. Som med andre Java APIer som JFC, JDBC og Java 3D, blir et visst nivå av indireksjon tvunget programmereren til å isolere plattformens idé om "hva en seriell port er" fra programmeringsmodellen. Når det gjelder javax.comm-design, brukes aldri elementer som enhetsnavn, som varierer fra plattform til plattform, direkte. De tre grensesnittene til API-en gir plattformuavhengig tilgang til serielle og parallelle porter. Disse grensesnittene gir metodeanrop for å liste opp tilgjengelige kommunikasjonsporter, kontrollere delt og eksklusiv tilgang til porter og kontrollere spesifikke portfunksjoner som baudrate, paritetsgenerering og strømningskontroll.

Da jeg så eksemplet SimpleWrite.java i dokumentasjonen, og sammenlignet de 40 kodelinjene med de 150 til 200 kodelinjene jeg så på å skrive i C, visste jeg at løsningen var tilgjengelig.

Abstraksjonen på høyt nivå for denne pakken er klassen javax.comm.CommPort. De CommPort klasse definerer hva slags ting du vanligvis vil gjøre med en port, som inkluderer å få InputStream og OutputStream objekter som er I / O-kanalene for porten. De CommPort klasse inkluderer også metoder for å kontrollere bufferstørrelser og justere hvordan input håndteres. Siden jeg visste at disse klassene støttet Dallas Semiconductor One-Wire-protokollen (en protokoll som involverte dynamiske endringer i overføringshastighet, og fullstendig gjennomsiktighet for byte som ble overført), visste jeg at javax.comm API måtte være fleksibel. Det som kom som en hyggelig overraskelse, var hvor trange klassene var: De hadde akkurat nok fleksibilitet til å få jobben gjort og ikke mer. Det var lite eller ingen unødvendig oppblåsthet i form av "bekvemmelighetsmetoder" eller støtte av modemprotokoller som Kermit eller xmodem.

En ledsagerklasse til CommPort er den javax.comm.CommPortIdentifier klasse. Denne klassen abstraherer forholdet mellom hvordan en port heter på et bestemt system (det vil si "/ dev / ttya" på Unix-systemer, og "COM1" på Windows-systemer) og hvordan porter blir oppdaget. Den statiske metoden getCommPortIdentifiers vil liste opp alle kjente kommunikasjonsporter på systemet; Videre kan du legge til dine egne portnavn for pseudokommunikasjonsporter ved hjelp av addPortName metode.

De CommPort klasse er faktisk abstrakt, og hva du får tilbake fra en påkallelse av openPort i CommPortIdentifier er en underklasse av CommPort det er enten ParallelPort eller SerialPort. Disse to underklassene har hver tilleggsmetoder som lar deg kontrollere selve porten.

Kraften til Java

Du kan krangle om virkeligheten med å "skrive en gang, løpe hvor som helst" alt du vil, men jeg vil fortelle deg av erfaring at Java for enkelttrådede eller til og med enkle flertrådede ikke-GUI-applikasjoner er der. Spesielt, hvis du vil skrive et program som kjører på Unix-systemer, Win32 og Mac-systemer, og har tilgang til den serielle porten, så er Java kun løsning i dag.

Fordelen her er at det kreves færre ressurser for å opprettholde koden som kjører på et stort antall plattformer - og dette reduserer kostnadene.

En rekke applikasjoner deler krav om å ha ganske lavt nivå tilgang til den serielle porten. Begrepet lavt nivå betyr i denne sammenhengen at et program har tilgang til grensesnitt som tillater det å endre modus på farten og direkte prøve og endre tilstandene til maskinvarestrømkontrollpinnene. Foruten PDP-8-prosjektet mitt, måtte Dallas Semiconductor bruke sine Blue Dot-grensesnitt på serielle porter for å snakke med iButton med Java. I tillegg har produsentene av mikroprosessorer evalueringstavler som bruker en seriell port for kommunikasjon og programlasting. Alle disse applikasjonene kan nå være fullstendig, og bærbart, skrevet i Java - en ganske kraftig uttalelse.

All denne kraften til å kontrollere vertsmaskinens parallelle og serielle porter kommer fra biblioteket javax.comm. Å gi Java-programmerere tilgang til portene åpner et helt nytt sett med applikasjoner som er målrettet mot innebygde systemer. I mitt tilfelle ga det meg muligheten til å skrive TTY-båndleseremulatoren min fullstendig i Java.

Hvordan kommer du til å leke med disse tingene?

For å få en kopi av den nyeste javax.comm-distribusjonen, må du først registrere deg som utvikler på Java Developer Connection (JDC) hvis du ikke allerede har gjort det. (Se ressurser.) JDC er gratis, og som medlem får du tidlig tilgang til Java-klasser som til slutt vil være en del av det endelige produktet.

Gå til Java Communications API-seksjonen og last ned den nyeste arkivfilen javax.comm. Pakk ut filen og installer de delte bibliotekene (ja, den virtuelle Java-maskinen trenger innfødt kode for å snakke med portene - heldigvis for deg, du trenger ikke å skrive den), og installer comm.jar-filen. Til slutt legger du til comm.jar-filen i CLASSPATH variabel.

Når comm.jar-filen er lagret i lib-katalogen til Java-installasjonen din, og win32comm.dll er lagret i bin-katalogen til Java-installasjonen, kan du kompilere og kjøre alle eksemplene som følger med nedlastingen. Jeg oppfordrer deg til å se på dem da det er mye god informasjon som ligger i kildekoden.

Hvor forlater dette PDP-8?

Så, hva har skjedd med PDP-8? Jeg trodde du aldri ville spørre! Etter å ha lest README-dokumentet som fulgte med javax.comm-distribusjonen, og deretter skannet JavaDocs for javax.comm-pakken, satte jeg sammen en applikasjonsklasse kalt SendTape. Denne klassen simulerer en papirbåndleser ved å åpne serieporten og fylle byte over den med 110 baud. Koden for denne klassen vises her:

importere javax.comm. *; importer java.io. *; offentlig klasse SendTape {static final int LEADER = 0; statisk slutt int COLLECT_ADDR = 1; statisk slutt int COLLECT_DATA = 2; statisk slutt int COLLECT_DATA2 = 3; / * Denne matrisen inneholder en kopi av BIN-formatlaster * / statisk byte binloader [] = {(byte) 0x80, (byte) 0x80, (byte) 0x80, (byte) 0x80, ... (byte) 0x80, ( byte) 0x80,}; 

Kodefragmentet ovenfor er den første delen av SendTape klasse. Denne klassen begynner med implisitt å importere alle klasser i javax.comm-pakken og java.io-pakkene. De SendTape klasse definerer deretter noen konstanter og forhåndsinitialiserer en byte-array som inneholder BIN Loader-programmet jeg nevnte tidligere. Jeg inkluderte BIN Loader fordi det alltid er nødvendig når du initialiserer minnet til PDP-8, og jeg fortsatte å miste oversikten over hvor jeg sist hadde lagret filen som inneholder bildet i RIM-format. Med dette viktige papirbåndsbildet innebygd i klassen på denne måten, har jeg alltid muligheten til å laste det med denne klassen.

 / ** * Denne metoden kjører en mini-state maskin som gir * en nyttig menneskelig lesbar utgang av hva som skjer * med nedlastingen. * / static int newState (int oldState, byte b) {...} 

Etter initialiseringen har du koden for metoden newState, vist ovenfor, som sporer innholdet på papirbåndet (enten det er adresseinformasjon eller programmeringsinformasjon). Metoden ovenfor skriver også ut en melding for hver plassering av minne på PDP-8 som er initialisert.

Neste har du hoved- metode, som er vist nedenfor; den åpner filen og leser den inn. Deretter åpner koden den serielle porten og setter kommunikasjonsparametrene.

$config[zx-auto] not found$config[zx-overlay] not found