[comp.dcom.modems] Reading modem registers in C.

rmorris@hubcap.clemson.edu (Robert Morris) (08/15/90)

I'm trying to read the registers in a Hayes 2400 modem.  I issue a 
ATS#? (# - number of the register).  I then check 0x3f8 for the value.
What I get is an unlikely result (ie. 13 - number of rings that occurred 
and no one called).  I figure the 13 is the carriage return sent to the modem.
I'm using Turbo C 2.01 and would appreciate any help recieved.
						Thanks,
						Robert Morris
						RMORRIS@hubcap.clemson.edu

dgil@pa.reuter.COM (Dave Gillett) (08/16/90)

In <10133@hubcap.clemson.edu> rmorris@hubcap.clemson.edu (Robert Morris) writes:
>I'm trying to read the registers in a Hayes 2400 modem.  I issue a 
>ATS#? (# - number of the register).  I then check 0x3f8 for the value.
>What I get is an unlikely result (ie. 13 - number of rings that occurred 
>and no one called).  I figure the 13 is the carriage return sent to the modem.
>I'm using Turbo C 2.01 and would appreciate any help recieved.

The first character of the response won't be available in the Receive Buffer
Register until Data Ready (bit 0 of the Line Status Register) is turned on.
Then you have to grab that character before the next one arrives.  Yeuchh!

This is basically what the BIOS INT 14H service does.  Except that if you use
INT 14H, there's some chance of your code working with communications setups
that aren't quite asynch ports (such as across a LAN to an asynch server).

If you decide that polling the UART is no fun, you can turn on Data available
(bit 0 in the Interrupt Enable Register) and Out2 in the Modem Control register,(and you may have to toggle bit 4 in the Interrupt Mask Register--which is in
the 8259, not the UART, so it's at a completely different address), and the
system will generate an INT 0CH each time there's a character ready.  Of course,
before you turn those bits on, you set the vector for INT 0CH to point at an
interrupt function that reads the Receive Buffer Register and puts the
character in a buffer that you can read from elsewhere in your program.
(Save the old vector so you can restore it, so line noise doesn't cause an
attempt to call your routine after it's not in memory any more; turn off the
various bits as part of the restore, too.)

Of course, your compiler library probably provides a variety of file I/O
routines which should work on the AUX: device, so if all you're doing is
alternately sending and receiviing strings (especially if you don't really
care how fast the characters are coming) those are probably sufficient.

Plug:  Gofton, Peter W., _Mastering Serial Communications_, Sybex, 1986.
       Don't write PC asynch code without it--or something at least as good.

                                                        Dave

tnixon@hsfmsh.UUCP (Toby Nixon) (08/18/90)

In article <10133@hubcap.clemson.edu>, rmorris@hubcap.clemson.edu
(Robert Morris) asks:

- I'm trying to read the registers in a Hayes 2400 modem.  I issue a
- ATS#? (# - number of the register).  I then check 0x3f8 for the
- value. What I get is an unlikely result (ie. 13 - number of rings
- that occurred and no one called).  I figure the 13 is the carriage
- return sent to the modem. I'm using Turbo C 2.01 and would
- appreciate any help recieved. 

You apparently don't quite understand how a Hayes (or compatible) 
modem sends back responses to ATSn? commands.  It comes as a series 
of characters (not a single character), with the value in decimal 
ASCII representation (so it can be easily interpreted by a human
being at a dumb terminal).  Yes, this makes it a bit more difficult 
for us software writers, but it's still not all that hard to deal 
with.

The characters you get back in response to the command depend on the 
setting of the "V" (verbose) command.  In "V1" mode, the response 
looks like this (assume I issued the command "ATS2?<cr>"):

	<cr><lf>043<cr><lf><cr><lf>OK<cr><lf>

where "<cr>" is the value of register S3 (default $0D or decimal 13, 
ASCII CR) and "<lf>" is the value of register S4 (default $0A or
decimal 10, ASCII LF), and "043" is the ASCII representation of the 
value of the register, always as three digits with leading zeroes 
included ("043" is the decimal value of the default of register S2, 
the ASCII "+" character).

In "V0" mode, the response looks like this:

	043<cr><lf>0<cr>

Note that the leading <cr><lf> is gone, that the second <cr><lf> in 
the middle is also removed, that the trailing <lf> is gone, and that 
the "OK" has been changed to "0".

I suspect that the value 13 you've been reading from 0x3f8 is this 
trailing <cr> (if you're in V0 mode) or the leading <cr> (if you're 
in V1 mode).

Your program should set either V0 or V1 mode directly (e.g. "ATV0") 
before issuing S? commands, so that you know the format to expect 
the responses to be in.  Then, all you have to do is read the entire 
string of characters (not just one), pick out the decimal value of 
the register, and then convert it to an integer to use it.

	-- Toby

-----------------------------------------------------------------------------
Toby Nixon, Principal Engineer     Fax:    +1-404-441-1213  Telex: 6502670805
Hayes Microcomputer Products Inc.  Voice:  +1-404-449-8791  CIS:    70271,404
Norcross, Georgia, USA             BBS:    +1-404-446-6336  MCI:       TNIXON
                                   Telemail: T.NIXON/HAYES  AT&T:     !tnixon
UUCP:   ...!uunet!hayes!tnixon     Internet:        hayes!tnixon@uunet.uu.net
MHS:    C=US / AD=ATTMAIL / PN=TOBY_L_NIXON / DD=TNIXON
-----------------------------------------------------------------------------