פתיחת יציאות חדשות ל- Java באמצעות javax.comm

התוודעתי לחבילת השיעורים javax.comm כשגיליתי שהם משמשים בערכת הפיתוח של Java Ring. (לפרטים על javax.comm, עיין בעמודת Java Developer של רינאלדו די ג'ורג'יו בגיליון מאי של JavaWorld: "ג'אווה זוכה לתמיכה סדרתית עם החבילה החדשה javax.comm.") במהלך העומס המטורף שלי ל- JavaOne להכניס תוכנית לטבעת שלי, נתקלתי במגוון בעיות, לא פחות מהן התקשורת עם הטבעת. הורדתי את ההפצה מחיבור Java Developer וניסיתי להשתמש בה ללא הצלחה כדי לדבר עם Java Ring. מאוחר יותר גיליתי את הבעיה עם הטבעת שלי: לא התקנתי כראוי ממשקי API מדור קודם של דאלאס סמיקונדקטור. כשהטבעת עובדת, בעצם שכחתי מחבילת התקשורת. כלומר, עד סוף שבוע אחד לפני כחודש, שזו נקודת המוצא לסיפור הזה.

מסיבות רבות ושונות (בעיקר הקשורות לסביבות מדומות אינטראקטיביות במיוחד - למשל משחקים), המחשב העיקרי ב"מעבדה "שלי מריץ את Windows 95. עם זאת, בסוף השבוע המסוים הזה הייתי מודאג יותר ממחשב אחר שב- במובנים רבים, היה עוצמתי בערך כמו Java Ring: PDP-8 / e של תאגיד הציוד הדיגיטלי.

ה- PDP-8 היה ללא ספק המחשב האישי האמיתי הראשון. תוכנן בסוף שנות ה -60 והופק בכמויות גבוהות יחסית בשנות ה -70, ה- PDP-8 יכול היה להיות מורם על ידי אדם יחיד, הופעל באמצעות זרם קו 120 וולט, ועלותו נמוכה מ- 0,000. רוב המחשבים האלה נשלחו עם ציוד היקפי יחיד: מסוף ASR-33 מדגם טלטייפ - "TTY" המקורי בשפת המחשבים.

טלטייפ ASR-33 היה מסוף הדפסה שהגיע עם קורא קלטת נייר ואגרוף. כן, היה זה קלטת נייר, נייר בגודל 1 אינץ 'עם חורים שננעצו בתוכו, שהיה אמצעי האחסון העיקרי לתוכניות ב- PDP-8.

ה- PDP-8 היה המחשב הראשון שתכננתי אי פעם ולכן יש לו מקום מיוחד בלב. יתר על כן, בגלל כמה נסיבות מקריות, הייתי במקום הנכון בזמן הנכון והצלחתי להציל PDP-8 שעומד להיסגר כזבל. תצלום של הפרס שלי מוצג למטה.

בסוף השבוע המיוחד הזה לפני זמן לא רב, החלטתי להחזיר את ה- PDP-8 לחיים, ולו רק כדי לחיות מחדש את הזיכרונות המוקדמים היקרים האלה ולהראות לבתי כמה טוב יש לה את זה עם הפנטיום הוותיק וחסר 133-MHz שלה. "

להחיות קלאסיקה אחת על ידי הדמיה של אחרת

כדי להתחיל במאמץ התחייה היה עלי להכניס תוכנית ל- PDP-8. ב- PDP-8, זה מושג על ידי ביצוע תהליך בן שלושה שלבים:

  1. באמצעות מתגי הלוח הקדמי, המשתמש "מקשי" תוכנית קצרה לזיכרון הליבה המגנטי. תוכנית זו נקראת RIM Loader, ומטרתה לטעון תוכנית נוספת מקלטת נייר שנמצאת בפורמט קריאה במצב, או RIM.

  2. RIM Loader טוען את קלטת הנייר בפורמט RIM. קלטת זו מכילה תוכנית הנקראת BIN Loader, אשר יכולה לטעון תוכניות מקלטת נייר בפורמט בינארי (BIN).

  3. לבסוף, אתה מפעיל את BIN Loader כדי לטעון את התוכנית שאתה באמת רוצה, שנמצאת על קלטת נייר בפורמט BIN. וואו!

לאחר שעברת את שלושת השלבים הללו, התוכנית שברצונך להפעיל נשמרת בזיכרון הליבה. כל מה שהמשתמש צריך לעשות אז להגדיר את כתובת ההתחלה ולהגיד למכונה "ללכת".

בניסיוני להחיות את המכונה, שלב 1 לא היה בעיה, אך שלב 2 כלל שימוש בקורא קלטת הנייר בטלטייפ - ולא היה לי טלטייפ. כמובן, אני לא צריך המחשב שולחני שלי, אז הצעד ההגיוני היה לדמות קורא נייר דבק על שולחן העבודה שלי.

מנקודת מבט הגיונית ומתכנתת, הדמיה של קורא קלטות נייר היא טריוויאלית. אתה פשוט קורא קובץ שמכיל את הנתונים מה"קלטת ", שולח אותו ליציאה טורית ב -110 באוד (כן, רק 10 תווים בשנייה), עד שתמצה את הקובץ. יכולתי לכתוב תוכנית ב- C במערכת Solaris שלי או במערכת FreeBSD שלי בתוך כ -10 דקות שיכולה לעשות זאת - אבל, זכור, הייתי במערכת Windows 95, לא במערכת Unix.

מרע למכוער ובחזרה

ידעתי שאני יכול לכתוב את התוכנית בקלות ב- C, אז זו הייתה שפת הבחירה שלי. בחירה רעה. הבאתי את העותק שלי של Visual C ++ 5.0 והקצתי תוכנה פשוטה בשם sendtape.c שקראה open()ליציאת התקשורת. ניסיתי להכניס אותו למצב RAW (המצב ב- Unix שבו מערכת ההפעלה לא מנסה לפרש דבר ביציאה הטורית כקלט משתמש) ואז ניסיתי לקמפל אותו. אופס, אין ioctl()פונקציה או ttyפונקציות - נאדה, רוכסן, זילך!

אין בעיה, חשבתי לעצמי, "יש לי את כל ספריית הרשת של מפתח התוכנה של מיקרוסופט על גבי תקליטור עם מהדר C שלי. אני אעשה חיפוש מהיר במילות המפתח 'יציאת COM'."

בחיפוש נמצאו אזכורים רבים למודל אובייקט הרכיבים של מיקרוסופט (נקרא גם COM), וגם הפניות ל- MSComm. MSComm הוא מחלקה C ++ שמיקרוסופט מספקת כדי לדבר עם היציאות הטוריות. הסתכלתי על הדוגמאות ונחרדתי כמה קוד יידרש כדי לעשות דבר כה פשוט כמו לכתוב בתים ליציאה הטורית ב -110 באוד. כל מה שרציתי לעשות היה לפתוח את היציאה הטורית המוקפדת, להגדיר את קצב השידור שלה ולסחב כמה בתים למטה - לא ליצור סוג חדש של יישומים משופרים בתקשורת טורית!

מול המוניטור שלי ישב הקולטן הכחול של הטבעת של ג'אווה שלי, וחשבתי לעצמי, "אהה! אנשי דאלאס סמיקונדקטור הבינו איך לדבר עם יציאה טורית במחשב האישי. בוא נראה מה הם עושים. " לאחר שעיינו בקוד המקור של החברה עבור Win32, היה ברור ששיחה עם יציאות סדרתיות לא תהיה משימה פשוטה.

ג'אווה להצלה

בשלב זה בסוף השבוע שלי חשבתי שאגרור אחת ממכונות יוניקס שלי למעבדה כדי לקודד את התוכנית בה במקום להשתמש במה שכבר היה לי. ואז נזכרתי בחוויה שלי עם Java Ring וחבילת java.comm מבית Sun. החלטתי להמשיך בשדרה הזו במקום.

מה מספק java.comm?

ממשק ה- API של תקשורת Java - או java.comm - מספק שיטה בלתי תלויה בפלטפורמה לגישה ליציאות טוריות ומקבילות מג'אווה. כמו בממשקי API אחרים של ג'אווה כמו JFC, JDBC ו- Java 3D, רמה מסוימת של כיוון נאלצת על המתכנת לבודד את רעיון הפלטפורמה "מהי יציאה טורית" ממודל התכנות. במקרה של עיצוב javax.comm, פריטים כמו שמות מכשירים, המשתנים מפלטפורמה לפלטפורמה, לעולם אינם משמשים ישירות. שלושת הממשקים של ה- API מספקים גישה עצמאית לפלטפורמה ליציאות סדרתיות ומקבילות. ממשקים אלה מספקים שיחות שיטה כדי לרשום את יציאות התקשורת הזמינות, לשלוט בגישה משותפת ובלעדית ליציאות ולשלוט בתכונות יציאה ספציפיות כגון קצב שידור, יצירת זוגיות ובקרת זרימה.

כשראיתי את הדוגמה SimpleWrite.java בתיעוד, והשוויתי בין 40 שורות הקוד שלה ל -150 עד 200 שורות הקוד שבדקתי לכתוב ב- C, ידעתי שהפתרון נמצא בהישג יד.

ההפשטה ברמה הגבוהה של חבילה זו היא המעמד javax.comm.CommPort. CommPortבכיתה מגדירה את סוגי דברים שאתה בדרך כלל תעשה עם נמל, אשר כולל מתן תשובות InputStreamואת OutputStreamחפצים הנמצאים ערוצי I / O עבור הנמל. הCommPortclass כולל גם שיטות לשליטה בגדלי חיץ והתאמת אופן הטיפול בקלט. מכיוון שידעתי שהשיעורים הללו תומכים בפרוטוקול דאלאס סמיקונדקטור One-Wire (פרוטוקול שכלל שינויים דינמיים בקצב השידור, ושקיפות מוחלטת לבתים המועברים), ידעתי שממשק ה- API של javax.comm צריך להיות גמיש. מה שהגיע כהפתעה נעימה היה עד כמה השיעורים היו הדוקים: היה להם מספיק גמישות לבצע את העבודה ולא יותר. לא היה מעט עד אין תוכנות נפח מיותרות בצורה של "שיטות נוחות" או תמיכה בפרוטוקולי מודם כמו קרמיט או קסמודם.

שיעור נלווה אליו CommPortהוא javax.comm.CommPortIdentifierהכיתה. מחלקה זו ממצה את הקשר בין האופן שבו יציאה נקראת במערכת מסוימת (כלומר "/ dev / ttya" במערכות יוניקס, ו- "COM1" במערכות Windows) לבין אופן גילוי היציאות. השיטה הסטטית תפרט את getCommPortIdentifiersכל יציאות התקשורת הידועות במערכת; יתר על כן, תוכל להוסיף שמות יציאות משלך ליציאות תקשורת פסאודו addPortNameבשיטה.

CommPortבכיתה הוא בעצם מופשט, ומה אתה מקבל בחזרה מתוך השבעה של openPortב CommPortIdentifierהיא תת מחלקה של CommPortזה הוא או ParallelPortאו SerialPort. לשתי מחלקות המשנה האלו ישנן שיטות נוספות המאפשרות לך לשלוט בנמל עצמו.

הכוח של ג'אווה

אתה יכול להתווכח על המציאות של "לכתוב פעם אחת, לרוץ לכל מקום" כל מה שאתה רוצה, אבל אני אגיד לך מנסיון שעבור יישומים שאינם ניתנים לממשק GUI עם הברגה אחת או אפילו פשוטה, Java נמצא שם . באופן ספציפי, אם ברצונך לכתוב תוכנית הפועלת במערכות Unix, Win32 ו- Mac ויכולה לגשת ליציאה הטורית, אז Java היא הפיתרון היחיד כיום.

היתרון כאן הוא שנדרשים פחות משאבים לתחזוקת קוד הפועל במספר רב של פלטפורמות - וזה מפחית את העלות.

מספר יישומים חולקים דרישה לקבל גישה ברמה נמוכה למדי ליציאה הטורית. המונח רמה נמוכה בהקשר זה פירושו שלתוכנית יש גישה לממשקים המאפשרים לה לשנות מצבים באופן טס ולדגום ישירות ולשנות את מצבי סיכות בקרת זרימת החומרה. מלבד פרויקט ה- PDP-8 שלי, דאלאס סמיקונדקטור נדרשה להשתמש בממשקי ה- Blue Dot שלה ביציאות סדרתיות כדי לדבר עם iButton עם Java. בנוסף, ליצרני המיקרו-מעבדים יש לוחות הערכה המשתמשים ביציאה טורית לתקשורת ולהעמסת תוכניות. כל היישומים הללו יכולים להיות כתובים לחלוטין, ובאופן נישא, בג'אווה - הצהרה חזקה למדי.

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) { ... } 

לאחר האתחול יש לך את הקוד עבור השיטה newState, המוצגת לעיל, העוקבת אחר תוכן קלטת הנייר (בין אם מדובר בכתובת או במידע תכנותי). השיטה לעיל מדפיסה גם הודעה עבור כל מיקום זיכרון ב- PDP-8 שמאותחל.

בשלב הבא יש לך את mainהשיטה המוצגת למטה; הוא פותח את הקובץ וקורא אותו פנימה. ואז הקוד פותח את היציאה הטורית וקובע את פרמטרי התקשורת שלו.