[comp.sys.amiga.tech] Sick, sick idea...

ccplumb@rose.waterloo.edu (Colin Plumb) (10/16/89)

I was recently talking with someone about the possibility of hooking Amy
up to control theatre lighting.  It seems there are two multiplex standards
used to control dimmers.  One is an analog 0-5V system that would require
custom hardware any way it's cut, but the DMX512 (Digital MultipleX, 512
dimmers) standard is vanilla RS422 (RS232+differential line driver) run
at a 4us (250Kbaud) bit time with 8 bits, no parity, 2 stop bits.
Asynchronous, so you don't need to spit out a byte every 44us, but it's nice
to get reasonably close.  You send at least 88us of break (low), followed
by 1 bit time (3.92 to 4.08 us) of high, then a zero byte (values 1-255
reserved for future expansion), then the control byte for dimmer 1 (0-255),
dimmer 2, etc. as many as you have.  After #dimmers bytes, you can start
over again.  There can be an arbitrarily long delay (well, the spec says 1sec
max) between bytes, but the null byte must start 1 bit time after the trailing
edge of the break.

Two possibilities came to mind.  Both are sick, sick ideas for use by lazy
bums who don't want to build a little UARRT & buffer kludge to stick on
the parallel port or some such, let alone build a proper Zorro board.
I wonder what everyone thinks?

Possibility 1:
The floppy drive can send data at 4us/bit.  Actually, it's 2.5% faster than
that, which is slightly off spec, but it'll probably work.  The only
problem is the NRZI encoding the floppy chip does to the data stream,
so you'd have to add a sense line to see what the state of the data line
is so you could flip it, and do some diddling to the input data stream
to get it to come out right.  And gate things so the bus could be shared
with other floppy drives...

The big disadvantage is sharing the floppy bus, as I don't know if there's
a way to get the trackdisk.device to cleanly release the thing, and even
if there was, 1 track's read, 1/6 sec, is a bit long to leave the lights
alone at busy moments.  You should refresh them at *least* once a second.

Possibility 2:
Use the standard serial port.  It can be set to pretty close to the right
baud rate, the problem is driving it that fast and getting that initial
break and first byte close enough together.

The normal way to send a break, as far as I know, is to drop the baud rate
really low and send a null byte (up to 15 null bits, actually).

So to send >88us break followed by a byte, assume the serial port reloads
its counter from the SERPER register every bit (is this wrong?), and
- drop the baud rate
- put a lot of 0's into the SERDAT register, with 1 stop bit, and
  *while this is being sent*
- put the null byte (1100000000 with 2 stop bits) into the register, and
- raise the baud rate back to 250Kbaud.

The last few bits of the break will be sent at high speed (no matter),
then 1 bit time of high for its stop bit, then the null byte immediately
thereafter.  Normal software can take it from here.

But: interrupt-per-character is still highly inefficient.  If there was a
deepish FIFO (16 bytes or so) it might be bearable, but this is going to
crawl.  We want DMA... h'm...

Flash!  Use the copper!  We can put the bytes into the copper list at the
apropriate times and let it copy the data.  We only have to fix things
up at the end of the frame, to ensure nothing gets sent twice.  Restricting
the number of dimmers so everything fits into one frame would make things
easier, but it's possible in principle to have a list that spans two video
frames.  You know the baud rate and the video clock (yes, I know the ECS
and productivity mode will break this badly, but NTSC/PAL doesn't change
too often and can be allowed for), so turning off handshaking is fine.
Just leave a little slop and it'll work fine.

Only problem: all the user copper list support in the graphics.library
handles lists in each ViewPort, translating to View coordinates and
truncating undisplayed portions.  Great for some applications, but
truncating *this* copper list Would Be Bad.

Does anyone know the cleanest way to install such an absolute copper list?
I'm hoping that the struct CopList *DspIns element of a CopList is
in global coordinates, so you can MakeVPort(), then mess with this
list to add your own toys, then MrgCop() will make everyone happy.
Or maybe it's posible to put negative coordinates in a user copper list,
so MakeVPort() will create the right DspIns list.  No, it'll still
get truncated...

Making this work with intuition will require more unsupported tricks.
Basically, you need to make sure Intuition doesn't try to MakeVport()
while the munged copprt list is running.  And get the thing cleared
out again... wait for the start of frame, then MakeScreen() and
RethinkDisplay() to force a MrgCop().  Hopefully, RethinkDisplay()
doesn't take too long if no MakeVPort's need to be done...

Anyway, any opinions?  Can anyone think of a better derogatory term than
"sick"?
-- 
	-Colin

33014-18@sjsumcs.sjsu.edu (Eduardo Horvath) (10/16/89)

In article <17243@watdragon.waterloo.edu> ccplumb@rose.waterloo.edu (Colin Plumb) writes:
>I was recently talking with someone about the possibility of hooking Amy
>up to control theatre lighting.  It seems there are two multiplex standards

[ gulp ]

>The normal way to send a break, as far as I know, is to drop the baud rate
>really low and send a null byte (up to 15 null bits, actually).

	While I have not been working with the Amiga serial port hardware,
I have recently been working with an embedded system that has a MC68681
( I think I have the right part number ) which is a DUART chip.  To send
a break with that, you set the break time, and give a special command.
The DUART does all the rest.

>-- 
>	-Colin

===============================================================================
       x                                        =	MEN AT WORK
    x X X x	Try:  33014-18@sjsumcs.SJSU.EDU =
   x X X X x                                    =	This space
    x X X x		Eduardo Horvath		=	    is
       x 					=	   UNDER 
						=	CONSTRUCTION
       ^Doesn't look much like Boing!, does it?	=
==============================================================================

ccplumb@rose.waterloo.edu (Colin Plumb) (10/19/89)

In article <1989Oct16.143322.29737@sjsumcs.sjsu.edu> 33014-18@sjsumcs.SJSU.EDU (Eduardo Horvath) writes:
>In article <17243@watdragon.waterloo.edu> ccplumb@rose.waterloo.edu (Colin Plumb) writes:
>> The normal way to send a break, as far as I know, is to drop the baud rate
>> really low and send a null byte (up to 15 null bits, actually).
>
>	While I have not been working with the Amiga serial port hardware,
> I have recently been working with an embedded system that has a MC68681
> ( I think I have the right part number ) which is a DUART chip.  To send
> a break with that, you set the break time, and give a special command.
> The DUART does all the rest.

I should have been clearer... the normal way to send a break *with the Amiga
serial hardware* is to play tricks with the baud rate.  Other chips have
different techniques.  The Z8530 has a control register bit that forces
a space condition on the line until the bit is cleared.  There are other
approaches.
-- 
	-Colin

bartonr@jove.cs.pdx.edu (Robert Barton) (10/20/89)

 ccplumb@rose.waterloo.edu (Colin Plumb) writes:
> Does anyone know the cleanest way to install such an absolute copper list?
> I'm hoping that the struct CopList *DspIns element of a CopList is
                                           ViewPort-------^^^^^^^
> in global coordinates, so you can MakeVPort(), then mess with this
> list to add your own toys, then MrgCop() will make everyone happy.
> Or maybe it's posible to put negative coordinates in a user copper list,
> so MakeVPort() will create the right DspIns list.  No, it'll still
> get truncated...

  ViewPort.DspIns is viewport-relative.  One idea I've seen suggested before
is to write your own copper list and then use ViewPort.UCopIns instructions
to set up the copper location registers and jump to this list.
  Negative vertical coordinates are certainly ok.  For example WAIT -1,0
would mean wait for the beginning of the first line before the top of this
ViewPort.  This allows you to do something like set up the new colors for
a ViewPort before it gets displayed.  This is also why ViewPorts have to be
separated by at least one blank line.

> Basically, you need to make sure Intuition doesn't try to MakeVport()
> while the munged copprt list is running.  And get the thing cleared
> out again... wait for the start of frame, then MakeScreen() and
> RethinkDisplay() to force a MrgCop().  Hopefully, RethinkDisplay()
> doesn't take too long if no MakeVPort's need to be done...

  OpenScreen() does a RemakeDisplay(), so you'll have to avoid that.
Moving or depth-arranging screens will call MrgCop() by way of
RethinkDisplay().