AT91SAM7 firmware for RC632 based reader.

0. Architecture

We have a Philips CL RC632 connected via SPI to the AT91SAM7.
The AT91SAM7 has a USB device port that is connected to a USB host.


1. USB Protocol / Interface

The AT91SAM7 has four USB endpoints, of which one is used for the control pipe,
and three are available for the user application.

Ideally, the device will provide two configurations, each with one interface
providing three endpoints: IN, OUT, INTERRUPT.



2. Interface configurations

2.1 Dumb interface

In this mode, the AT91SAM7 acts as a stupid interface between SPI and USB.  It
provides access to the following primitives:

- Write Register
- Read Register
- Write FIFO
- Read FIFO
- Write Virtual FIFO
- Read Virtual FIFO
- Signal Interrupt

Since the FIFO of the RC632 are only 64byte deep, and the USB latency is too
big to facilitate FIFO refill while transmit, esp. at 424/848kbps RFID bitrate,
the AT91SAM7 has to provide bigger 'virtual' FIFO buffers to the USB host.

Thus, the USB host can fill a 1024byte-sized buffer using multiple USB packets,
and then ask the AT91SAM7 to write the first 64bytes to the FIFO.   The RC632
will be programmed by the USB host to generate FIFO Level interrupts, to which
the AT91SAM7 will react automatically and re-fill the RC632 FIFO until all host
data has been sent to the RC632.

For the FIFO RX path, the opposite pattern is used:  The AT91SAM7 has a 1024 byte
sized buffer, into which data can be read from the FIFO. 


2.2 Intelligent interface

This interface will be optionally implemented at some later point.  It provides
a 14443 protocol implementation inside the AT91SAM7.


2. Interface configurations

2.1 Dumb interface

EP0	control
EP1	bulk in
EP2	bulk out
EP3	interrupt


3. USB Protocol

3.1 dumb interface

struct usb_pcd_out_hdr {
	u_int8_t cmd;		/* command */
	u_int8_t flags;
	u_int8_t reg;		/* register */
	u_int8_t res;
	u_int16_t len;
	u_int8_t data[0];
} __attribute__ ((packed));

#define USB_PCD_CMD_WRITE_REG	0x01
#define USB_PCD_CMD_WRITE_FIFO	0x02
#define USB_PCD_CMD_WRITE_VFIFO	0x03
#define USB_PCD_CMD_READ_REG	0x11
#define USB_PCD_CMD_READ_FIFO	0x12
#define USB_PCD_CMD_WRITE_VFIFO	0x13

TBD

3.2 Intelligent interface

TBD


4. Firmware code flow architecture

The general idea is to make the firmware as interrupt-driven as possible.
Synchronous waiting for I/O (SPI, USB, ...) should be avoided, and restricted
to slow path operations  (such as USB configuration) only.

Another design goal is to avoid using a dynamic memory allocator.  Dynamic
memory allocation can be costly, leads to all sorts of fragmentation problems,
and will lead to the question of what to do in the case of an OOM situation.

Therefore, all data structures such as buffers will be pre-allocated and
declared as static variables.

4.x Data structures

Any action of the PCD is host-driven.  Therefore, the UDC maintains a set
(2..32) request context structures.  Upon completion of a USB OUT EP DMA,
the corresponding request context is passed on to other parts of the code.
Once the reply to that request has been processed, the context structure
is released.

The context structures are statically allocated, and a single u_int32_t
represents a bitmask of busy context structures.  ffs() or a similar function
is used to search for a free buffer using which the UDC RX DMA can be refilled.


4.1 Examples

4.1.1 Performing SPI Register Read

[ UDC has configured RX FIFO for reception of usb packets ]
- UDC issues interrupt that USB endpoint receive has completed (FIFO)
	- UDC driver defragments multiple packets into one transfer [optional]
	- UDC driver submits another buffer for DMA reception
	- UDC driver parses PCD ommand header and calls rc632 API
	- RC632 driver configures SPI DMA transceive
	- End of UDC interrupt
- idle loop
- SPI DMA completion interrupt happens for TX [do nothing]
- SPI DMA completion interrupt happens for RX
	- callback into UDC driver using request state data 
	- UDC driver sends IN packet/transfer back to host
	- End of SPI DMA interrupt
	
4.1.2 Performing SPI register read

much like register write, although the deferred completion could be skipped and
the usb transfer approved immediately after having submitted the SPI write
request to the RC632

5.1.3 Performing FIFO read

much like register read.  Only difference is size and duration of transfer

5.1.4 Performing FIFO write

much like register write.  Only difference is size and duration of transfer

5.1.5 Performing virtual FIFO read

much like a FIFO write, but make sure to enable FIFO watermark IRQ in RC632.

5.1.6 Performing virtual FIFO write

much like a FIFO read, but make sure to enable FIFO watermark IRQ in RC632.
Response to USB host is only sent after the full virtual FIFO has been emptied
into the physical FIFO.

5.1.6 Reporting RC632 interrupts

Upon reception of a RC632 interrupt, the primary and secondary status registers
are read from the IRQ handler, and an USB packet on the Interrupt In enddpoint is
created and submitted for transmission.

Some special handling (filtering) of FIFO over/underrun interrupts has to be 
implemented for transparent handling of the virtual FIFO.

5.1.7 Reporting virtual FIFO interrupts

The virtual FIFO itself can generate over/underrun interrupts on the USB.  They
are signalled pretty much like real RC632 interrupts.


6. Interrupt priorities

UDC DMA			low priority, since we don't want to overflow with usb packets?
SPI DMA			higher than UDC since it might complete while in UDC code?
RC632_IRQ		high priority, since FIFO refill might be required
DEBUG_UART		do we want it to use IRQ at all? if yes it should have highest prio.

