Programming documentation for the Catweasel MK3 PCI/Flipper
***
This file is incomplete!
to-do:
- floppy controller memory contents after read w/ and w/o predecode
- memory contents for write
- how to cause an IRQ
- how to use the floppy controller as continuous IRQ source
***


This document is freely distributable as long as it is not changed, and one
of the sources www.jschoenfeld.com, www.jschoenfeld.de, www.siliconsonic.com
is mentioned. 

last update: 
November 8th, 2002 (corrected bit-order of JoyDat register)
November 7th, 2002 (added PCI IDs and PCI bridge init routine)
November 6th, 2002 (initial release)

General
-------
The Catweasel MK3 PCI/Flipper is a flip-card. That means it can be used in
different busses, but not two at a time. There are three ways to install the
hardware: PCI bus, Zorro bus and the so-called clockport of the Amiga 1200.
The memory map is the same for all these kinds of installations, so basically
you can write the same software for all platforms and just adapt the base
address of the controller in the target system.

How to get the base address of the controller
---------------------------------------------
PCI: The PnP manager of the target system has mapped the board to a free space
in memory. Please consult your operating system manual for instructions on
how to determine the base address of a PCI PnP board.

PCI Vendor ID: $e159
PCI device ID: $0001
PCI subsystem ID: $00021212

The string for a Windows *.ini file would be:

PCI\VEN_E159&DEV_0001&SUBSYS_00021212

The board reserves two areas in memory, one in IO space and one ib memory
space. Both are 256 bytes, and both are identical. Writing/reading to/from
the memory space has the same effect as writing/reading to/from the IO space.
It's just a different base address, so it does not matter which space you
choose. However, it's recommended to use the IO space, because future versions
of the PCI bridge may not support the memory space any more. The offset for
the hardware registers is the same for both spaces: $c0. Do not access
the registers below, they control the behaviour of the PCI bridge, so writing
to these registers is a big no-no-no. Only run the given initialization
routine:

Write $f1 to offset $00
write $00 to offset $01
write $00 to offset $02
write $00 to offset $04
write $00 to offset $05
write $00 to offset $29
write $00 to offset $2b

Zorro: The Kickstart system of the Amiga has mapped the board to a 64K
memory space. The offset in this space is $c0.

Zorro vendor ID: $1212 (4626)
Zorro product ID: $42  (66)

As opposed to the PCI interface, there is no need to initialize the Zorro
interface. It works right from the start. Do not run the PCI init sequence
on the Amiga, because this will not reach teh PCI bridge.

Clockport: The base address of the clockport is hard-wired to $dc0001 in the
Amiga 1200 (odd addresses!). If connected to a non-A1200 clockport, please
consult the corresponding documentation for that port to get the base address
of the Catweasel.

Memory map
----------
The Catweasel MK3 has 16 registers that control the whole board. The following
table summarizes these registers. Please keep your source code portable by
using an offset-table for these registers. The register spacing and register
offsets may change in future versions of the controller, so a simple change
in your table will adapt the program to a new version of the hardware.

Name         ! PCI offset     ! Zorro offset      ! Clockport
-------------------------------------------------------------
JoyDat       ! $c0            ! $c0               ! $00
PaddleSelect ! $c4            ! $c4               ! $04
Joybutton    ! $c8            ! $c8               ! $08
Joybuttondir ! $cc            ! $cc               ! $0c
KeyDat       ! $d0            ! $d0               ! $10
KeyStatus    ! $d4            ! $d4               ! $14
SidDat       ! $d8            ! $d8               ! $18
SidCommand   ! $dc            ! $dc               ! $1c
CatMem       ! $e0            ! $e0               ! $20
CatAbort     ! $e4            ! $e4               ! $24
CatControl   ! $e8            ! $e8               ! $28
CatOption    ! $ec            ! $ec               ! $2c
CatStartA    ! $f0            ! $f0               ! $30
CatStartB    ! $f4            ! $f4               ! $34
CatIRQ       ! $fc            ! $fc               ! $3c

Register $f8 (clockport $38) is not used.

Joystick functions
------------------
The JoyDat register contains information about the direction controls of
both joysticks:

bit 0 joystick 1 right
bit 1 joystick 1 left
bit 2 joystick 1 down
bit 3 joystick 1 up
bit 4 joystick 2 right
bit 5 joystick 2 left
bit 6 joystick 2 down
bit 7 joystick 2 up

A bit is 0 if the joystick is moved in the corresponding direction. The
mapping is "direct", no XORing (like in the Amiga) is needed. Connecting
an Amiga or Atari mouse may be possible, but since there are no hardware
counters, this would cause heavy CPU load because of the high rate that would
be necessary to poll the JoyDat register. 

The JoyButton register contains information about the firebuttons of a
digital joystick. The "second and third" buttons of some joysticks can
be read through the paddle registers in the SID chip.

bit 6 joystick 1 button (0=pressed)
bit 7 joystick 2 button (0=pressed)

Bits 0-5 of the register are unused and should be ANDed away for
compatibility with future versions of the Catweasel.

The button-lines of the joystick connectors can also be programmed to be
outputs, just like on the Amiga computer. The default value of the direction
bits after a reset is 0 (input). Bits 6 and 7 of the JoybuttonDir register
control the direction of the button lines.  It is recommended only to program
these lines to be outputs if it's absolutely sure that a hardware is connected
that accepts data through the Firebutton pin. Since a joystick shorts this
line to ground when the button is pressed, it may harm the Catweasel. If in
doubt, set both bits to 0. Emulator programmers could enable mapping of these
bits to the emulated machine with an option called "Dongle support", because
the only known hardware that needs the button line to be an output is dongles
on the Amiga. A warning should be displayed to the user when he's enabling
this option.
Bits 0-5 of the JoyButtonDir register are unused and should be written 0.
If the corresponding direction bits are set to 1, the state of the firebutton
line can be controlled by writing the desired value to the JoyButton register.
If only one of the two bits is set to output, the value that was written to
the input-bit will be stored in the Catweasel hardware, but not routed to the
joystick port.

There are two paddle inputs on each joystick port. The value of these paddles
can only be read if a SID chip is present in the socket of the Catweasel.
Just like in a C-64, only two of the four possible paddles can be read at a
time. The PaddleSelect register determines whether it's the two paddles in
port 1 or the other two paddles in port 2. The PaddleSelect register is a
toggle-register. That means the contents of the register do not matter; only
reading or writing the register will cause an action. Reading the register
gives a value that has no meaning, you can discard it. Reading causes the
analog switch to route the paddles of port 1 to the SID chip. Writing the
PaddleSelect register causes the analog switch to route the paddles of port 2
to the SID chip. It does not matter which value you write, but in order not
to cause any confusion, write a 0.
Please consult the SID section of this file on instructions how to read the
paddle registers of the SID chip.

Keyboard functions
------------------
Amiga keyboards communicate through a serial interface with the computer.
Unfortunately, some keyboards don't behave like defined in the Amiga hardware
reference manual; sometimes they send more than 8 bits of data (trash bits,
they don't seem to have a meaning).

The keyboard interface is designed to provide maximum convenience for the
programmer. All timing-critical things are handled by the hardware, and trash-
bits are filtered automatically. If there is a keystroke value pending in the
data register, the keyboard is halted until the computer has read the value
out of the data register, so no keystroke will be lost. Even the necessary
bit-shifting is done by the hardware, so the value you read is a scancode
that is listed in the Amiga hardware reference manual. The MSB of the
scancode shows if it's a key-up or a key-down code.

The KeyStatus register only contains one valid bit. Bit 7 shows if data in the
KeyDat register is valid (bit 7=1). If this is the case, you can take all the
time you need to read the KeyDat register. After reading the data, you have
to tell the keyboard that it can continue sending data by writing 0 to the
KeyDat register. This will also set bit 7 of the KeyStatus register to 0.

Although every Amiga keyboard supports auto-resyncing, the Catweasel keyboard
interface can also do a manual resync. This is simply done by first writing
0 to KeyStatus, then writing 0 to KeyDat. This may be necessary for the early
A1000 keyboards that do not support auto-resyncing - rumors say that there
have been a few keyboards that lack this option.

Amiga keyboards support hot-plugging. As soon as the keyboard is powered up,
it sends an init-string. This can also be used to detect if a keyboard is
connected or not: Since the KeyStatus register is set to 0 on a reset, you
can tell that there's a keyboard connected with the first time that KeyStatus
bit 7 is 1.

Unlike PC keyboards, no Amiga keyboard supports recieving data. The only
information that is sent back to the keyboard is the handshaking.

Drawbacks of the interface: There is no IRQ for a pending keyboard value, and
the keyboard reset can only be detected from the string that is sent from the
keyboard prior to it's reset procedure.

SID functions
-------------
The SID chip is programmed through a bottleneck. Since the amount of data that
can be written to the chip is very limited, this will not cause any reduction
of performance. The clock rate of the SID is generated by a MOS 8701 PLL chip
that has also been used in the C-64 and the C-128 computers. This will ensure
a genuine sound. The filter capacitors of the SID are fixed at 470pF, because
higher values that have been chosen by Commodore in some versions of the C64
cause the filters to take effect much too early.

There are two registers for communication with the SID. The data register
contains the byte that is read or that will be written to the chip, and the
command register tells the SID bridge which register of the SID is accessed
next. The following table shows the bitmap of the command register:

bit 0: address bit 0
bit 1: address bit 1
bit 2: address bit 2
bit 3: address bit 3
bit 4: address bit 4
bit 5: 0= command write, 1= command read
bit 6: Pitch select. 0=PAL (0,98Mhz), 1=NTSC (1,02Mhz)
bit 7: unused, should be written 0.

SidCommand is a write-only register.

write-byte procedure:

Write the value that you want to send to the SID to the SIDdat register. Then
write the command to the SIDcommand register, and leave the SID bridge
alone for at least 1 microsecond. There is no way to tell whether the SID
bridge is still active or not other than waiting 1 microsecond. This can
either be accomplished by reading the data register twice and discarding the
data, or by allowing context-switching in a multitasking system (this will
most probably take longer than 1 microsecond).

If for example you want to set the volume of the SID to maximum, write
$0f to SIDdata, then write $18 to the command register and wait for 1
microsecond. This also sets the clock rate of the SID to the PAL frequency
of 0,98Mhz. Add 0x40 to the command value to choose NTSC frequency.

read-byte procedure:

If you want to read a SID register, write the register number plus 0x20 to
the command register, then wait for 1 microsecond, then the value is present
in the SIDdata register.

It is not recommended to change the SID frequency during playback. It takes
up to 10ms until the oscillator is stable at the new frequency, so it might
sound "defective" during the transition. Please mind that reading from SID
can also alter the frequency, so you should keep the chosen frequency in a
shadow-register of your access-routine and, if necessary, add 0x40 to the
command value.

Playing back SID tunes requires precise timing. Since nearly no x86 operating
system can generate an exact interrupt rate of 50 per second, the Floppy part
of the Catweasel can be "misused" to generate precise timing through a timer
interrupt. The drawback of using this method is that the floppy controller
will be busy if used as an IRQ source, so it's recommended to use a timer
IRQ of the system for that purpose if available (for example the CIA timers
in an Amiga).

Floppy functions
----------------
The floppy functions of the Catweasel MK3 are a grown structure since summer
1996. The layout of some registers and the methods of how to start an action
in the floppy part had to be adapted to older versions in order to make
existing software for the Catweasel MK2 work. Please mind that the ISA
Catweasel has always been a MK1 design (even the Y2K edition!), and the MK2
has never been documented to the public before (it was only available as
Amiga-hardware), so a lot of features of the floppy part will be completely
new to you if you've programmed the ISA version before.

memory access
-------------
The catweasel memory of 128KBytes is accessed through a bottleneck. Two
registers are used to read and write the memory. Every access to the CatMem
register reads or writes the memory. After every access, the internal memory
pointer of the controller is increased by 1, no matter if it was a read or
a write access. The memory pointer is reset to 0 by writing 0 to the CatAbort
register. No other actions are performed with this write access.
There is no way to read the state of the memory pointer. However, some actions
depend on the state of this pointer, so you MUST hold a shadow register of the
pointer in your program/driver.

The memory is accessed from two sides, either from the computer side (that is
your side!), or from the controller side. Before you access the memory, make
sure that the floppy controller state machines do not access the memory,
otherwise you might mess up the memory pointer. There is only one!

Status/control register
-----------------------
The CatControl register is different on reads and on writes. Writing to the
register controls some lines on the shugart bus, but reading the CatControl
register reads the status register. If you write a value to the CatControl
register, you should keep it in a shadow register, this makes modification of
single bits a lot easier.

CatControl on write accesses:

bit 7: Step
bit 6: Sideselect
bit 5: Motor0 (0=motor on)
bit 4: Dir
bit 3: Sel0 (0=selected)
bit 2: Sel1 (0=selected)
bit 1: Motor1 (0=motor on)
bit 0: Density select (pin 2 of shugart bus, if in doubt, set to 1)

CatControl on read accesses:

bit 7: reading (0=controller is currently reading=memory access!)
bit 6: writing (0=controller is currently writing=memory access!)
bit 5: Diskchange (0=disk has been removed from drive)
bit 4: Diskread (will most probably not be used, should be masked away)
bit 3: WProtect (0=disk is write protected)
bit 2: Track0 (0=head is on outermost position)
bit 1: Index (0=drive motor is currently on index position)
bit 0: Density select (pin 2 of shugart bus)

Please note that bits 5, 4, 3, 2 and 1 are only valid if the corresponding
drive is selected. If no drive is selected, these bits will be 1 (if one of
the bits is still 0, something must be terribly wrong :-)).

Consult the specifications of the floppy drive vendor to get information about
how to step, and about the timing constraints of the signals. For example,
the track 0 signal will be valid no earlier than 4ms after the step on most
drives. That means, even if the drive supports a step rate of 3ms, stepping
towards track 0 must be done at a rate of 4ms if you don't know the exact
position of the read/write head.

Since the CatStart A and B registers have no dedicated function, the
following section only contains sequences that start a read or a write access
to or from the disk. The difference between the accesses is the start and the
end condition. There are some things that all disk acceses have in common:

- any access can be aborted by reading the CatAbort register. The value that
  has been read can be discarded of, it's random and has no meaning. The
  state of the memory pointer will not be changed by this access.
- any access is track-wise. Unlike most other floppy controllers, the
  Catweasel always accesses a whole track in one go. 
- a read access will be stopped automatically if the memory is full, no matter
  what other condition you have chosen to stop the access.
- a write access will always be stopped by a stop command in memory, no matter
  what other condition you have chosen to stop the access. As opposed to a
  read access, a write access is not stopped at the end of memory. Instead,
  the memory pointer wraps around and starts again at 0.

unconditional read:
To start reading a track without any conditions, read the CatStartA register.
The controller will start reading and store the data starting from the
position that the memory pointer is currently at.

unconditional write:
To start writing a track without any contidions, perform the write enable
procedure and then write 0 to the CatStartB register. Do nt access the memory
between the write enable procedure and the CatStartB access, because this
would change the memory pointer, invalidating the internal write enable bit.
The write enable procedure is described at the end of this file.

indexed write:
Indexed write waits for an index pulse before starting to write, and ends at
the next index pulse. Since the index pulse is very long (between 1ms and
8ms), you have to know that the start- and endpoint of the write is at the
beginning of the pulse (falling edge). This is very precise on 3,5" drives,
the position where the start and the end of the write come together is usually
only a stream of less than 10 bits of undefined data. However, you should
not rely on the exact position of the data, because the index pulse may be in
a slightly different position with a different drive. The precision on other
drive sizes has not been checked (yet).

indexed read:
Indexed read waits for the beginning of an index pulse before starting to
read. As opposed to indexed write, the indexed read stops at the end of the
following index pulse, so there's a small overlap.
To start an indexed read, forbid index storing in memory, and read the
CatStartB register. 

Sync read:
This option waits for an MFM sync before starting to read. The expected sync
pattern is $4489 and cannot be changed. This only works at fixed bitrates of
500KBit (DD), 1MBit (HD) and 2MBit (ED), depending on the clock rate that has
been set. See further down to learn how to set the clock rates. Reading starts
immediately after a sync has been recognized in the bit stream. The sync that
has been recognized will not be stored in memory. However, most disk formats
have at least two sync patterns in a row, so it's unlikely (but not
impossible) that there's no sync pattern at the beginning of the data in
memory.
To start a sync read, allow index storing in memory and read the CatStartB
register.

write enable procedure:
Write 0 to the CatAbort register, this resets the memory pointer to 0.
Read the Catmem register once, this sets the memory pointer to 1.
Write 128 (0x80) to the CatOption register.
Advance the memory pointer to 7 by reading CatMem 6 times.
The Floppy controller is now ready for a write access. Please note that
the write enable procedure is different from the procedure that is necessary
on the ISA version of the Catweasel.

allow/forbid index storing:
The index signal can be stored in the catweasel memory in the MSB of each
byte. The MSB (bit 7) cannot be used for anything else. Allowing or
forbidding index storing only affects read accesses. If index storing is
allowed, bit 7 of the memory value will be set to 1 if the index signal was
active at the time of the memory-write. This is very precise if standard-
read without pre-decode is chosen, and a little less precise on read with
MFM-predecode.
To allow index storing, set the memory pointer to 2 and write any value to
the CatOption register. This is the default after a reset. Please mind that
writing to CatOption with the memory pointer at 2 also alters the Predecode
and the IRQ enable bits (see further down). To forbid index storing, set the
memory pointer to 3 and write 0 to the CatOption register.

Setting clock speed:
To set the clockspeed with the CatOption register, reset the memory counter
to 0 by writing 0 to the CatAbort register. Writing 0 to CatOption will set
the clock rate to 14Mhz. Writing 128 (0x80) to CatOption will set the clock
rate to 28Mhz, and writing 192 (0xc0) to CatOption will set the clock speed
to 56Mhz (to be precise, 56.644Mhz).

Predecode, IRQ enable:
To set the Predecode and the IRQenable bits with the CatOption register, set
the memory pointer to 2 by writing 0 to the CatAbort register and reading the
CatMem register twice. Bits 5 and 6 of the CatOption register now control
Predecode and IRQ enable:
        Bit 5=0: Forbid IRQs
        Bit 5=1: Allow IRQs
        Bit 6=0: Standard read mode
        Bit 6=1: MFM-predecode in lower nibble of memory (only set on reads!)
Please mind that any write to the CatOption register with the memory pointer
at 2 also allows index storing. If ths is not desired, forbid index storing
again after setting Predecode and IRQenable to the required values.
If installed in an Amiga, the IRQ will be an IRQ6. Since there is no way to
tell if the IRQ comes from this controller, and the Amiga only has shared
IRQs, this is practically useless. However, the software timers of the
Amiga OS are very precise, and the Catweasel floppy functions have always
worked without IRQs since october 1996, so there's no need to activate this
option on Amiga computers. It's mainly intended for PCs, where software
timers are rather unprecise. To find the IRQ that the Catweasel will use on
the PCI slot, consult your PnP software manual.
To stop an IRQ, write 0 to the CatIRQ register.


** EOF
