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