/* ---------------------------------------------------------------------------
 * spi0.c - v1.0                                        (c) 2006 Micro-key bv
 * ---------------------------------------------------------------------------
 * Micro-key bv
 * Industrieweg 28, 9804 TG Noordhorn
 * Postbus 92, 9800 AA Zuidhorn
 * The Netherlands
 * Tel: +31 594 503020
 * Fax: +31 594 505825
 * Email: support@microkey.nl
 * Web: www.microkey.nl
 * ---------------------------------------------------------------------------
 * Description: SPI 0 driver 
 * ---------------------------------------------------------------------------
 * Version(s):  1.0, 07-12-2006, Jos Pasop.
 *                   Creation.
 * ---------------------------------------------------------------------------
 */
#define DEBUG

#include "types.h"
#include "lpc23xx.h"
#include "armVic.h"
#include "spi0.h"

#ifdef DEBUG
#include "uart.h"
#include "gpio.h"
#endif
/* ---------------------------------------------------------------------------
 * Application include files.
 * ---------------------------------------------------------------------------
 */

/* ---------------------------------------------------------------------------
 * Local constant and macro definitions.
 * ---------------------------------------------------------------------------
 */
#define SPI_SPCR_BIT_ENABLE(b) (b<<2)
#define SPI_SPCR_CPHA(b) (b<<3)
#define SPI_SPCR_CPOL(b) (b<<4)
#define SPI_SPCR_MSTR(b) (b<<5)
#define SPI_SPCR_LSBF(b) (b<<6)
#define SPI_SPCR_SPIE(b) (b<<7)
#define SPI_SPCR_BITS(b) (b<<8)

#define SPI_SPSR_ABRT (1<<3)
#define SPI_SPSR_MODF (1<<4)
#define SPI_SPSR_ROVR (1<<5)
#define SPI_SPSR_WCOL (1<<6)
#define SPI_SPSR_SPIF (1<<7)

#define DISABLE_SPI0_IRQ {SPI_SPCR &= ~(SPI_SPCR_SPIE(1))}
#define ENABLE_SPI0_IRQ {SPI_SPCR |= (SPI_SPCR_SPIE(1))}

/* ---------------------------------------------------------------------------
 * Global variable definitions.
 * ---------------------------------------------------------------------------
 */

/* ---------------------------------------------------------------------------
 * Local variable definitions.
 * ---------------------------------------------------------------------------
 */


/* ---------------------------------------------------------------------------
 * Local function declarations.
 * ---------------------------------------------------------------------------
 */
VOID __attribute__ ((interrupt("IRQ"))) spi0Isr (VOID);

/* ---------------------------------------------------------------------------
 * spi0Init -- SPI0 initialize.
 *
 * This function initializes SPI0 to operate at slave at 1.2Mhz and sets up
 * the VIC to for SPI0 interrupt service routine
 *  
 * Global variables: commState, commStateSubI
 * ---------------------------------------------------------------------------
 */
VOID 
spi0Init 
    (
    VOID
    )
    {
#ifdef DEBUG
    /* Used to toggle the led to be able to check isr interrupt rate.       */
    PCB_PINSEL1 &= ~0x3;                 /* set P0.16 (LED) as GPIO         */
    GPIO_FIO0DIR |= LED;                 /* set P0.16 as output             */
    GPIO_FIO0MASK &= ~LED;               /* enable P0.16                    */
#endif

    // OTTO
    //spi0TxBuf [0] = 0xD;
    //spi0TxBuf [1] = 0x1234;

    /* Initialize pin connect block.                                        */
    PCB_PINSEL0 &= ~0xFF00;              /* clear the SPI0 fields           */
    PCB_PINSEL0 |= 0x5500;               /* configure the SPI0 pins         */ 
    
    S0SPCR = 0;
#if 0    
    /* Set SPI0 clock rate. 1.2Mhz @ 48Mhz PCLK.                            */
    SPI_SPCCR  = 40;
#endif
    S0SPCR = 
        SPI_SPCR_BIT_ENABLE (0) |        /* 1 -> enable n of bits selection */
        SPI_SPCR_CPHA       (1) |        /* 1 -> data sampled on 2nd edge   */
                                         /* of sck                          */
        SPI_SPCR_CPOL       (0) |        /* 1 -> active low clock polarity  */
        SPI_SPCR_MSTR       (1) |        /* 1 -> master mode                */
        SPI_SPCR_LSBF       (0) |        /* 1 -> LSB shifted out first      */
        SPI_SPCR_SPIE       (0) |        /* 0 -> hardware interrupt disabled*/
        SPI_SPCR_BITS       (16);        /* 7 < n < 16 -> n of bits,        */
                                         /* 0->16 bits                      */

    /* Initialize the SPI0 interrupt vector.                                */
    //VICVectAddr2 = (UINT32) spi0Isr;      /* address of the ISR             */
    //VICIntSelect &= ~VIC_BIT (VIC_SPI0);  /* select SPI0 as IRQ             */
    //VICVectCntl2 = VIC_IRQ_SLOT_EN | VIC_SPI0;  /* priority 4 interrupt     */
    //VICIntEnable = VIC_BIT (VIC_SPI0);    /* enable SPI0 interrupt          */
    }


VOID spi0Enable (VOID)
{
	// ?
}

VOID spi0Disable (VOID)
{
	// ?
}

RESULT spi0Write (UINT16 data)
{
	/* Check if SPI controller is disabled      */
    
    S0SPDR = data;                                                /* write data        */
    if ((S0SPSR & SPI_SPSR_WCOL) == SPI_SPSR_WCOL) return ERROR;  /* Write collision   */

    return OK;	
}

RESULT spi0WriteRead (UINT16 *data)
{
	volatile int DummyRead;

	/* Check if SPI controller is disabled      */
	  
	DummyRead = S0SPSR;                                           /* For resetting status */
    S0SPDR = *data;                                               /* write data           */
    if ((S0SPSR & SPI_SPSR_WCOL) == SPI_SPSR_WCOL) return ERROR;  /* Write collision      */
	
    while ((S0SPSR & SPI_SPSR_SPIF) == 0);                        /* wait if transmit is completed  */

    *data = S0SPDR;                                               /* read data            */

    if ((S0SPSR & SPI_SPSR_ROVR) == SPI_SPSR_ROVR) return ERROR;  /* Read overrun   */
    
    return OK;	
}

INT16 spi0Read (UINT16 * pData)
{
	volatile int DummyRead;

	/* Check if SPI controller is disabled      */
	  
	DummyRead = S0SPSR;                                           /* For resetting status */
    while ((S0SPSR & SPI_SPSR_SPIF) == 0);                        /* wait if transmit is completed  */
    *data = S0SPDR;                                               /* read data            */
    if ((S0SPSR & SPI_SPSR_ROVR) == SPI_SPSR_ROVR) return ERROR;  /* Read overrun   */

    return ERR_NONE;
	
}

