Networking With HP Calculators Hi everybody! I send this file because it might answer some common questions about networks and the serial port. Daniel Roggen droggen@dico.epfl.ch ******************************************************************* ******************************************************************* ** ** ** December 1995 ** ** ** ** Networks - Serial port ** ** on HP 48 ** ** ** ******************************************************************* ******************************************************************* 1 Introduction 2 The HP 48 serial interface 2.1 pineout 2.2 An HP-PC cable 2.3 An HP-HP cable 3 Networks with the HP 48 3.1 A Token Ring network 3.1.1 Wiring a Token Ring network 3.1.2 Software for the Token Ring network 4 Contacting me 1 Introduction -------------- Many questions are asked about the HP 48 serial port and the calculator networking capabilities. I'll explain in here the pineout of the 48G serial port and then how to make a TokenRing network for this calculator. I hope that this text will answer the most FAQ... Note: I have made the HP-HP, HP-PC cable and a simple network for 4 HP's, I had no particular problems, but if you have, please let me know so that I can report here those problems. If you have some ideas on another method to make a network (or other), let me know too so that I can make this documentation more complete. You can find how to call me at the end of this document. 2 The HP 48 serial interface ---------------------------- I won't rewrite the whole theory of serial interfaces and asynchronous communications, I just want to explain *HOW* to make an HP-PC, HP-HP cable. **** 2.1 pineout **** Fig 2.1.1 shows the pineout of the HP 48 serial interface. Meaning of the pins: #1 GND This is the logical 0 Volt #2 RX The data are received through this pin #3 TX The data are transmitted through this pin #4 SHIELD Protects TX and RX against interferences +-------------------------+ I I I -----\ I I I I I I I I I I I * I I I T I I I O I I I P +--GND----- #1 I I * +---<<-RX-- #2 I I +--->>-TX-- #3 I I +--SHIELD-- #4 I I I I I I I I -----/ I I I I I +-------------------------+ Fig 2.1.1 pineout of the serial interface **** 2.2 An HP-PC cable **** To make an HP-PC cable, you need a connector fitting in the HP serial port, another connector for your PC ( D-SUB 9 or D-SUB 25 depending on your serial port). All you need to do is to link the HP ground with the PC ground, HP shield with PC shield, HP TX with PC RX and HP RX with PC TX. Fig 2.2.1 shows how this works. +------------------------------------------------------------+ I HP 48 PC I I -----\ I I I I I I I I I D-SUB 9 or D-SUB 25 I I * I I I T I /--- I I O I /-- / I I I P +--GND-----...---GND---+5 I -GND----+ 7 I I I * +---<<-RX--...---TX----+3 I -TX-----+ 2 I I I +--->>-TX--...---RX----+2 I -RX-----+ 3 I I I +--SHIELD--...---------+ I -SHIELD-+ 1 I I I I \-- \ I I I I \--- I I -----/ I I I I I +------------------------------------------------------------+ Fig 2.2.1 HP-PC cable Note that with a D-SUB 9 connector SHIELD remains unconnected, although you could solder it with GND. Pay attention to the TX and RX pins on the D-SUB 9 and D-SUB 25: on the D-SUB 9, TX is pin 3 and on the D-SUB 25, TX is pin 2. **** 2.3 An HP-HP cable **** Making an HP-HP cable is quite the same as making an HP-PC cable. You link the two GROUNDs together, the two SHIELDs together and link TX #1 to RX #2 and RX #1 to TX #2. Fif 2.3.1 shows this. +------------------------------------------------+ I HP 48 #1 HP 48 #2 I I -----\ /----- I I I I I I I I I I I /----------SHIELD-+ I I * I I /-----TX-<<-+ * I I T I I /--I-----RX->>-+ T I I O I I I I ---GND-+ O I I P +--GND-----I--I--I----/ I P I I * +---<<-RX--I--I--/ I * I I +--->>-TX--I--/ I I I +--SHIELD--/ I I I I I I I I I I I -----/ \----- I I I I I +------------------------------------------------+ Fig 2.3.1 HP-HP cable 3 Networks with the HP 48 ------------------------- We can imagine to link several HPs together with their serial ports. We could thus play multiplayer games or we could use it to cheat at school (...) but let us say it is only for a technical purpose that we do it. **** 3.1 A Token Ring network **** I have thought of several different means to do a network for HP 48, I finally decided to make a kind of Token Ring network. The principle of Token Ring is quite easy to understand: a token travels from an HP to the following one until the addressee receives it. +---------------------------+ I <--- I I -- I I ----I#1I----- I I I -- I I I I I I I -- -- I I I#2I I#6I I I -- -- I I I I I I -- -- I I I#3I I#5I I I -- -- I I I I I I I -- I I I ----I#4I---- I I -- I I I +---------------------------+ Fig 3.1.1 A Token Ring with 6 HPs with it's direction This kind of network has advantages and disadvantages. For example, it requires no electronics, but it is not the fastest network that can be made: if HP #1 wants to send a message to HP #6, the message has to travel through HP #2,#3,#4,#5. ****** 3.1.1 Wiring a Token Ring network ****** It's quite easy to wire a Token Ring network for HP. Fig 3.1.1.1 shows how to do it. +--------------------------------------------------+ I I I -- -- -- -- -- -- I I ITRI ITRI ITRI ITRI ITRI ITRI I I ++ ++ ++ ++ ++ ++ I I II II II II II II I I ..- ----- ----- ----- ----- ----- -.. I I I I T = Transmit I I R = Receive I I I +--------------------------------------------------+ Fig 3.1.1.1 Wiring a Token Ring network Each HP Transmit pin is wired to the following HP receive pin, at last all the HP are wired together ( the last HP transmit pin is wired to the first HP receive pin). When HP #1 sends a message, HP #2 receives it. If the message is for this calculator, it can process it, otherwise it sends it to the following HP (HP #3) which will either process it or send it to HP #4. You see here that some strange things can happen (in fact it happened to me!): there may be *LOST* messages, with no destination (or an incorrect one). In this case, the message will endlessly travel from an HP to another!! ****** 3.1.2 Software for the Token Ring network ****** There is another disadventage of the Token Ring network: unless dedicated cards are used, the HP must read all incoming caracters and send them to the next HP, thus consuming a lot of proc time... First of all we must define a protocol to communicate through this network. The protocol that I have used is the following one: each message begins with the ID of the receiver, followed by the ID of the sender, then the size of the block and finally the data. (see Fig 3.1.2.1) +--------------------------------------------------------+ I Description I Receiver I Sender I Size of Data I Data I +--------------------------------------------------------+ I Size (bytes) I 1 I 1 I 2 I n I +--------------------------------------------------------+ Fig 3.1.2.1 Protocol used for the network As you can see, the ID of the HPs is one byte in length, allowing a maximum of 256 different HP. In my protocol, I defined a special ID 0x3f = '?' for the receiver. All the HP will have to read the message, process it and then transmit it to the next HP. This allows to send interrogation messages to detect how many HP are on the net without having to send 255 different messages for each ID. Note: I used a non-optimized form for the size of the data. For example, 23 meant 23 bytes and not 0x3233. A software using this kind of net will have to permanently detect incoming datas, process them, or retransmit them. Thus we could write a function that fill this job. This function would be typically called periodically in a loop. I wrote the followin GetToken function: - GetToken - << 0 0 0 -> t s n << IF BUFLEN DROP 4 >= // Enough chars to define the message? THEN // yes 4 SRECV DROP DUP // read those characters 't' STO 3 4 SUB OBJ-> 'n' STO // n = size of message DO BUFLEN DROP // wait until n characters are present UNTIL n >= END n SRECV DROP 's' STO // read them IF t 1 1 SUB MachineName == // if for us (MachineName = HP's ID) t 1 1 SUB "?" == OR // or '?' THEN t 2 2 SUB s t s + 3 ->LIST 1 // return a list ELSE t s + XMIT DROP 0 // if not for us, send the message END ELSE 0 END >> >> // Returns a list (stk 2) and 1 if a token was read, 0 otherwise We can define a WaitToken function that waits a predefined amount of time for a token before returning: - WaitToken - << TIME 0 -> t r << DO GetToken 'r' STO // Waits until a token comes UNTIL r 1 == TIME t HMS- .0005 >= OR // for a maximum of 5 sec. END r >> >> Before initiating transmissions, we could check the ring, to see if it is not broken. We could for example send a message to ourself and if 5 sec later it hasn't come back, it would mean that the ring is broken. The following function does this: - CHKRING - << "Checking ring" 4 DISP MachineName DUP + "04+CHK" + // Sends the message XMIT DROP WaitToken // Waits a token for 5 sec IF 0 == // no token came -> 0 in the stack THEN 0 ELSE IF 3 GET MachineName DUP + "04+CHK" + == THEN 1 ELSE 0 // wrong token -> 0 in the stack END END IF NOT // if 0 in the stack, ring is broken THEN "Ring broken" MSGBOX KILL END >> We could now make a little application to try this network. RPL isn't the good language to make this network: too slow. It would be better to do it in ML and to redirect interrupts, but I show it here in RPL so that everybody can understand. This program is a "Talk" program: once all the HPs are connected, it allows us to send a message to one of the HP on the net. The following table reports how 3 HP's could detect how many calculators are on the network and then communicate together. There is a special HP, called Server, the other are Clients. There is only a little difference between Client and Server: the server initiates the communication; the clients wait an order before starting. Server has ID M, the clients have ID A,B,... Note: this protocol doesn't automatically detect the machines IDs. You have to manually choose a different ID for each calculator. -------------------------------------------------------------------------------------- Note: -> means that the token is send to the next HP. R means that the message is received S means that the message is send -------------------------------------------------------------------------------------- M A B -------------------------------------------------------------------------------------- *Special code for server* Initialization of variables. Ring checking S MM04+CHK -> MM04CHK -> MM04CHK R MM04CHK The ring is OK. Sending a start message to ourself S MM02+S *Normal code for server and client* -> MM02+S -> MM02+S R MM02+S Start message received. Who is on the net? S ?M04+ASK R ?M04+ASK S MA07+ANSWER S ?M04+ASK -> MA07+ANSWER R ?M04+ASK S MB07+ANSWER S ?M04+ASK R MA07+ANSWER Ok, HP A on the net R MB07+ANSWER Ok, HP B on the net R ?M04+ASK It's my ask message -> I have all the HP on the net. If I am the server (and I am), I can send a start message to each of the HP on the net. S AM02+S S BM02+S R AM02+S Ok, I can ask who is on the net S ?A04+ASK -> BM02+S R ?A04+ASK S AB07+ANSWER S ?A04+ASK R BM02+S Ok, I can ask... S ?B04+ASK -> AB07+ANSWER R ?A04+ASK I am here... S AM07+ANSWER S ?A04+ASK R ?B04+ASK I am here... S BM07+ANSWER S ?B04+ASK R AB07+ANSWER HP B on the net R AM07+ANSER HP M on the net R ?A04+ASK It's my ask message -> I have all the HP on the net in the list. I am not the server -> I don't send a start message. (It is only the server who does this) -> BM07+ANSWER R ?B04+ASK I am here... S BA07+ANSWER S ?B04+ASK R BM07+ANSWER HP M on the net R BA07+ANSWER HP A on the net R ?B04+ASK It's my ask message -> I have all the HP on the net. -------------------------------------------------------------------------------------- At this point, each HP has a list of all the other HP on the net. I hope that you understood the above table... I know, it isn't easy, that's why I haven't make a table with 4 or 5 HP !... I can explain this protocol once more. Each HP waits for a start message. Once it came, the HP asks every other HP with the "?x02+ASK". ? means "to all HP". When an HP receives an ASK message, it checks if it is its own message. If it is, it means that everybody has received this ASK message and thus answered. It means that an HP receiving its own ASK message has also received all ANSWER message from the other HP, and thus, that its list of HP is complete. If the ASK message received isn't its own ask message, the HP sends an ANSWER message and then retransmits the ASK message. When an HP receives an ANSWER message, it adds the sender of the message to the list of HP present on the net. Here is the listing of the TALK program. - SERVE - This program must be used on only one HP << CLRBUF // a function to clear the serial port buffer OPENIO // not included here { } 'MACHINES' STO // Empty list of HP on the net 1 'SRV?' STO // I am the server 0 'CANSEND' STO // I can't send. An HP can send only when its CLLCD // list of HP present on the net is complete. CHKRING // Check ring MachineName DUP + "02+S" + XMIT DROP // Sending a start message to itself PROCESSMESSAGE // Processes incoming messages. >> - CLIENT - This is the client program run on all the other HP << CLRBUF OPENIO 0 'SRV?' STO // I am NOT the server { } 'MACHINES' STO 0 'CANSEND' STO CLLCD "Waiting..." 4 DISP PROCESSMESSAGE >> - PROCESSMESSAGE - Main loop, calls each time GetToken << WHILE 1 // Main loop REPEAT IF KEY 0 =/ CANSEND 1 == AND // If a key is pressed and I can send THEN // -> calls TALK module DROP TALK END IF GetToken 1 == // If a token has been received THEN // then process it. PROCCASE END END >> - PROCCASE - Module processing all incoming messages (see table above to understand how it works) << DUP 2 GET -> t m // m=message t=list returned by GetToken << CASE m "+S" == // START message THEN "Scanning stations..." 4 DISP "?" MachineName + "04+ASK" + // sends the ASK message to all HP XMIT DROP END m "+ASK" == // ASK message THEN IF t 1 GET MachineName == // If it is my own ASK message THEN // I can now talk because I have 1 'CANSEND' STO // received all ANSWER messages IF SRV? THEN // If I am the server, I send MACHINES 1 // a start message to each HP on the net << MachineName + "02+S" + XMIT DROP >> DOSUBS END // The list of HP present on the net CLLCD "Ready" 1 DISP // is now full. I'm ready ELSE // If it wasn't my own ASK message t 1 GET MachineName + // -> I must answer "07+ANSWER" + XMIT DROP t 3 GET XMIT DROP END END m "+ANSWER" == // ANSWER message, add sender THEN // to list of HP present on the net 'MACHINES' t 1 GET STO+ END m t 1 GET DISPM // If it is another message, END // displays it. >> >> - TALK - Called when a key is pressed. Not a very good example for this token ring: while HP waits an input string, all token are stored in the 256-byte buffer. and none can be retransmitted to the next HP. << "MACHINES ON NETWORK" MACHINES 1 IF CHOOSE THEN "Message:" "" INPUT DUP SIZE NBCNVRT SWAP + SWAP MachineName + SWAP + XMIT DROP CLLCD END >> - NBCNVRT - Converts a number to a string of at least 2 chars. << ->STR -> s << IF s SIZE 2 < THEN "0" s + 's' STO END s >> >> - DISPM - Displays incoming messages << -> m f << 0 5 FOR i m i 21 * 1 + i 21 * 21 + SUB i 2 + DISP NEXT "From " f + 1 DISP >> >> Thats all for this Token Ring network! If you have other ideas please send them to me, so that I can include them in this text 4 Contacting me --------------- If you have suggestions, ideas, etc, send them! I will include them in this text with your name. My address: Daniel Roggen Moineaux 1 CH-1028 Pr‚verenges (Switzerland) Voice: +41 21 801 9020 Fax: +41 21 803 5636 EMail: droggen@dico.epfl.ch --------------------------------------------------------------------------- Thanks to Olivier Saudan (Adventurer), Y.B. (makes nice games in RPL!) and DZiR (the first to have an HP in our class).