[comp.sys.mac.programmer] For GURU'S Only

thorson@typhoon.atmos.colostate.edu (Bill Thorson) (02/07/90)

INTRODUCTION:
  This is a question for those C programming Macintosh Guru's out there.  I
have never used nor programmed on a Mac before but it looks like I will have
to do some next month and will only have one week to get it going.  This
is why I need all the knowlege I can get ahead of time.  I brought a MacSE
home to do some learning and testing on.

THE PROBLEM:
  I need to ingest satelite image on a Mac 2x (I think).  The images will
be sent, in groups of three, once an hour.  They will be sent at 56K baud
with no flow control.  The first byte represents the beginning of an image
and a 3+ seconds with no data represents the end of an image.  The images
will be fixed in size with a maximum of 4Meg/image but will be of three
different types.

  Ideally the Mac will be able to ingest these images without stoping
all other processes.  Since the Mac does not multitask this may not be
so easy.

  Realistically this Mac can be dedicated to ingest during the ~15 min
interval of the transfer and used for image analysis during the other
~45 minutes.  The analysis software will also be developed by yours
truely so I can make it stop when I want to.

THE QUESTIONS:

1) Can the Mac 2x 16mhz. keep up with this data rate?

2) Could it keep up while dumping to disk?  (8 meg RAM is available)

3) Can this be done in the background without going to an assembly 
   level?  I don't have to much time.

4) Would anyone have any small example of direct control of the
   serial port?  (in C preferably)

5) Is it true that Cherio's and the Bronco's are different because
   Cherio's belong in a bowl?

SEND RESPONCES TO:
#!/bin/sh
#-----------------------------------------------------------------------#
echo Bill Thorson                   thorson@typhoon.atmos.colostate.edu
echo Dept of Atmospheric Science    (303) 491-8339
echo Colorado State University
echo Ft. Collins,  CO  80523        Cray||Sun||Amiga -- I can't decide?
#-----------------------------------------------------------------------#
#!/bin/sh
#-----------------------------------------------------------------------#
echo Bill Thorson                   thorson@typhoon.atmos.colostate.edu
echo Dept of Atmospheric Science    (303) 491-8339
echo Colorado State University
echo Ft. Collins,  CO  80523        Cray||Sun||Amiga -- I can't decide?
#-----------------------------------------------------------------------#

loganj@yvax.byu.edu (02/08/90)

You can anonymous ftp a simple C program (source included) called "Capture"
that demonstrates Macintosh serial port control from "noc.byu.edu"
(128.187.7.2).  Get a file in the "pub" directory called "CaptureSit.hqx".
It includes a "LightSpeed 3.x" C project, source code, and resource file.

The program allows you to select either the printer port or the modem port
and change the communication parameters for either port (baud rate, stop bits,
parity, handshaking, ...) in a slick little dialog.

It is intended ONLY as a starting point for students and others that need
to use Macintosh for serial communications.  It acts like a very simple
(and VERY slow) terminal emulator by displaying characters from the serial
port in a TextEdit window.  You're expected to make the necessary
modifications to satisfy your communications requirements.  One of the
first changes is usually speeding up the communications by removing the
TextEdit display capability.  TextEdit is used initially only so students
can "see" their data (if you know what I mean) and better understand how
the program works.

Be sure to read the comments at the beginning of the main program,
"Capture.c".

(I am not a GURU)

Regards,
jim
loganj@byuvax.bitnet
loganj@yvax.byu.edu

oster@dewey.soe.berkeley.edu (David Phillip Oster) (02/12/90)

>1) Can the Mac 2x 16mhz. keep up with this data rate?
Yes. For example, LocalTalk Appletalk uses the serial port at 250K baud
and even a MacPlus can keep up with it.

>2) Could it keep up while dumping to disk?  (8 meg RAM is available)
Probably, if you use the Port A, (the port with a picture of a Modem.)
It would be safer to buffer the whole image in RAM, then write it.

>3) Can this be done in the background without going to an assembly
   level?  I don't have to much time.
Yes.

>4) Would anyone have any small example of direct control of the
> serial port?  (in C preferably)
Do not do this. Just use the Serial Driver asynchronously.

Write a simple application as follows. Set its "can Background" bit in its
SIZE resource so multifinder will give it null events in background.

Here is what it does:
OpenDriver("\p.Ain") and
OpenDriver("\p.Aout"). 
Set the speed of the port to 56k. 
Set the serial buffer size to something decently large. 
The serial driver will automatically buffer unread characters into its
buffer, in preparation for a read call sometime later.
Now, enter the event loop of your application. Use WaitNextEvent() and
set your application to wake up every second.
at nullEvent time, check, using TickCount() to see if one second has
elapsed. If it has not, do nothing, just loop around back to
WaitNextEvent().

If the time has elapsed, check the number of unread characters in the
serial driver's buffer. If it is large and hasn't changed in the last two
seconds, you've got a complete image.  FSWrite it to a disk file.
FSRead the serial buffer into itself, or do a KillIO on the serial port to
reset the driver.

Add a menu bar, so the user can Quit the application, and it can reset the
serial buffer, close the port and clean up after itself.

Trivial. No funky calls,  no assembly language.


> The mac is a detour in the inevitable march of mediocre computers.
> drs@bnlux0.bnl.gov (David R. Stampf)
--- David Phillip Oster          -master of the ad hoc odd hack. 
Arpa: oster@dewey.soe.berkeley.edu 
Uucp: {uwvax,decvax}!ucbvax!oster%dewey.soe.berkeley.edu 

loganj@yvax.byu.edu (02/13/90)

We have added a feature to the Capture application (mentioned previously)
to capture data received on one of the serial ports to a disk file without
displaying the data on the screen.  This was needed for engineering research
here, so we thought we would pass it along.

The Capture application v1.1 and source (in a Lightspeed C project) is
available by anonymous ftp from "noc.byu.edu" (128.187.7.2) in the "pub"
directory.

Regards,
jim
loganj@byuvax.bitnet
loganj@yvax.byu.edu

vmrad@pollux (Bernard Littau) (02/13/90)

In article <34253@ucbvax.BERKELEY.EDU> oster@dewey.soe.berkeley.edu.UUCP (David Phillip Oster) writes:
>>1) Can the Mac 2x 16mhz. keep up with this data rate?
>Yes. For example, LocalTalk Appletalk uses the serial port at 250K baud
>and even a MacPlus can keep up with it.
>
Appletalk is packet based, and thus is broken into small asynchronous
chunks.  250K baud is a burst rate, not a sustained rate.  Your answer
is still valid, though.  Any mac should be able to keep up with this
rate.

[ ... deleted ...]
>
>Write a simple application as follows. Set its "can Background" bit in its
>SIZE resource so multifinder will give it null events in background.
>
>Here is what it does:
>OpenDriver("\p.Ain") and
>OpenDriver("\p.Aout"). 
>Set the speed of the port to 56k. 
>Set the serial buffer size to something decently large. 

There is a 16 bit limit on the size of the serial buffer.  The images
in question are much larger than 64k byte.

>The serial driver will automatically buffer unread characters into its
>buffer, in preparation for a read call sometime later.
>Now, enter the event loop of your application. Use WaitNextEvent() and
>set your application to wake up every second.
>at nullEvent time, check, using TickCount() to see if one second has
>elapsed. If it has not, do nothing, just loop around back to
>WaitNextEvent().
>
>If the time has elapsed, check the number of unread characters in the
>serial driver's buffer. If it is large and hasn't changed in the last two
>seconds, you've got a complete image.  FSWrite it to a disk file.
>FSRead the serial buffer into itself, or do a KillIO on the serial port to
>reset the driver.
>

This will not work if the image (data in general) is larger than 64k
bytes.  You will need both the serial buffer and a disk write buffer.
In the event loop, read from the serial buffer to the disk write
buffer every time through the loop.  You must do this at least every
10 seconds or the serial buffer will overflow.  The disk write buffer
can be as large as memory allows.

Bernard Littau

VM Radiological Sciences          Telephone: (916) 752-0184
School of Veterinary Medicine     Internet:  vmrad@ucdavis.edu
University of California          BITNET:    vmrad@ucdavis
Davis, CA 95616                   UUCP: {ucbvax,lll-crg,sdcsvax}!ucdavis!vmrad
Bernard Littau

VM Radiological Sciences          Telephone: (916) 752-0184
School of Veterinary Medicine     Internet:  vmrad@ucdavis.edu

urlichs@smurf.ira.uka.de (Matthias Urlichs) (02/15/90)

In comp.sys.mac.programmer, article <6711@ucdavis.ucdavis.edu>,
  vmrad@pollux (Bernard Littau) writes:
< In article <34253@ucbvax.BERKELEY.EDU> oster@dewey.soe.berkeley.edu.UUCP (David Phillip Oster) writes:
< 
< This will not work if the image (data in general) is larger than 64k
< bytes.  You will need both the serial buffer and a disk write buffer.
< In the event loop, read from the serial buffer to the disk write
< buffer every time through the loop.  You must do this at least every
< 10 seconds or the serial buffer will overflow.  The disk write buffer
< can be as large as memory allows.
< 
I don't think you need a disk write buffer if you write to the hard disk.
What I did was to call PBRead(serial port, (16 kByte or end of picture))
asynchronously, call WaitNextEvent with a reasonable timeout (based on the
serial speed, how much you want to read, and how much is already there), and
call PBWrite to your disk file if that call completes.
Allocate a nice big serial buffer (maybe 48k)...

vmrad@pollux (Bernard Littau) (02/16/90)

In article <1533@smurf.ira.uka.de> urlichs@smurf.ira.uka.de (Matthias Urlichs) writes:
>In comp.sys.mac.programmer, article <6711@ucdavis.ucdavis.edu>,
>  vmrad@pollux (Bernard Littau) writes:
>< In article <34253@ucbvax.BERKELEY.EDU> oster@dewey.soe.berkeley.edu.UUCP (David Phillip Oster) writes:
>< 
>< This will not work if the image (data in general) is larger than 64k
>< bytes.  You will need both the serial buffer and a disk write buffer.
>< In the event loop, read from the serial buffer to the disk write
>< buffer every time through the loop.  You must do this at least every
>< 10 seconds or the serial buffer will overflow.  The disk write buffer
>< can be as large as memory allows.
>< 
>I don't think you need a disk write buffer if you write to the hard disk.
>What I did was to call PBRead(serial port, (16 kByte or end of picture))
>asynchronously, call WaitNextEvent with a reasonable timeout (based on the
>serial speed, how much you want to read, and how much is already there), and
>call PBWrite to your disk file if that call completes.
>Allocate a nice big serial buffer (maybe 48k)...

As I read your reply, you are doing:
SerSetBuf( a 48k buffer)
PBRead(serial port, serial port buffer)
PBWrite(to disk, serial port buffer)

This I am sure will work, once.  Maybe more often.  It is however very
dangerous.  The serial port buffer is a circular buffer.  You could put
yourself in the situation of clobbering your data as you do a PBRead
from the serial port buffer to the serial port buffer.  If, after you
do your PBRead and PBWrite,  you always call SerSetBuf before the next
character is received, this method would work.  This method would not
work in the situation asked about by the original poster.  The images
to be captured are megabytes in size, and there is no ability to pause
the data stream to do a flush of the buffer to disk.


Bernard Littau    VM Radiological Sciences        Telephone: (916) 752-4014
                  School of Veterinary Medicine   Internet:  vmrad@ucdavis.edu
                  University of California        BITNET:    vmrad@ucdavis
                  Davis, CA 95616                 UUCP: ucbvax!ucdavis!vmrad

urlichs@smurf.ira.uka.de (02/16/90)

In comp.sys.mac.programmer, article <6747@ucdavis.ucdavis.edu>,
  vmrad@pollux (Bernard Littau) writes:
< In article <1533@smurf.ira.uka.de> urlichs@smurf.ira.uka.de (Matthias Urlichs) writes:
< >< 
< >I don't think you need a disk write buffer if you write to the hard disk.
< >What I did was to call PBRead(serial port, (16 kByte or end of picture))
< >asynchronously, call WaitNextEvent with a reasonable timeout (based on the
< >serial speed, how much you want to read, and how much is already there), and
< >call PBWrite to your disk file if that call completes.
< >Allocate a nice big serial buffer (maybe 48k)...
< 
< As I read your reply, you are doing:
< SerSetBuf( a 48k buffer)
< PBRead(serial port, serial port buffer)
< PBWrite(to disk, serial port buffer)
Replace this with:
PBRead (serial port, private 16kB buffer)
PBWrite (Disk, same buffer)
< 
< This I am sure will work, once.  Maybe more often.  It is however very
< dangerous.  The serial port buffer is a circular buffer.  You could put
< yourself in the situation of clobbering your data as you do a PBRead
< from the serial port buffer to the serial port buffer. [...]
< 
After I say SerSetBuf(), said buffer belongs to the serial driver until
the next SerSetBuf. I do not assume anything about what the serial driver does
with that buffer.
I never understood why anyone would be reading from the serial buffer to the
serial buffer, much less assume that I implied this...
So, I don't see what could possibly go wrong with the above method.
-- 
Matthias Urlichs

vmrad@pollux (Bernard Littau) (02/17/90)

I say:
>< >I don't think you need a disk write buffer if you write to the hard disk.
>< >What I did was to call PBRead(serial port, (16 kByte or end of picture))
>< >asynchronously, call WaitNextEvent with a reasonable timeout (based on the
>< >serial speed, how much you want to read, and how much is already there), and
>< >call PBWrite to your disk file if that call completes.
>< >Allocate a nice big serial buffer (maybe 48k)...
>< 
>< As I read your reply, you are doing:
>< SerSetBuf( a 48k buffer)
>< PBRead(serial port, serial port buffer)
>< PBWrite(to disk, serial port buffer)

Matias says:
>Replace this with:
>PBRead (serial port, private 16kB buffer)
>PBWrite (Disk, same buffer)
>After I say SerSetBuf(), said buffer belongs to the serial driver until
>the next SerSetBuf. I do not assume anything about what the serial driver does
>with that buffer.
>I never understood why anyone would be reading from the serial buffer to the
>serial buffer, much less assume that I implied this...
>So, I don't see what could possibly go wrong with the above method.

You are completely correct.  Nothing would go wrong with this above
method.  I was let to assume you were reading from serial buffer to
serial buffer by the statement:

	"I don't think you need a disk write buffer..."

and in that I assumed:
	SerSetBuf( a 48k buffer)
	PBRead(serial port, serial port buffer)
implied one single 48k serial port buffer used in both calls.  Bad
assumption, apparently.  Sorry.

In my nomenclature, the serial buffer is used by SetSerBuf, and the
disk write buffer is used by PBRead and PBWrite.  So we all don't
think alike.

Bitte enshuldigen Sie mir!  Ich solte mehr denken, und winiger ouf dem
computer schreiben.  Shade das mein Deutsche ist nicht so gut wie 
Ihren English.

My Respect,

Bernard Littau    VM Radiological Sciences        Telephone: (916) 752-4014
                  School of Veterinary Medicine   Internet:  vmrad@ucdavis.edu
                  University of California        BITNET:    vmrad@ucdavis
                  Davis, CA 95616                 UUCP: ucbvax!ucdavis!vmrad