2013-10-17

CooCox SPI function writing notes

// ***********************************************************************
// SPI testing - 2013oct17
// ***********************************************************************

#include "lpc11xx_ssp.h"

void testSpi()
{
// 1. Enable SSP0 block clock
SYSCON_AHBPeriphClockCmd(SYSCON_AHBPeriph_SSP0, ENABLE);

// 2. Assign P2.11 as SCK0, enable SSEL
SSP_SSP0PinsInit(SCK0_PIO2_11, ENABLE);

// 3.1 Declare SSP Configuration structure variable
SSP_CFG_Type SSP_ConfigStruct;

// 3.2 Initialize SSP configuration structure to default
SSP_ConfigStructInit(&SSP_ConfigStruct);

// 3.3 Initialize SSP peripheral with parameter given in structure above
SSP_Init(LPC_SSP0, &SSP_ConfigStruct);

        // Enable SSP peripheral's operation using SSP_Cmd(). 
        // To write, ...

        // Use SSP_SendData() and SSP_ReceiveData() or SSP_ReadWrite() for 
        // data transfer.
        // To write, ...
}

// ***********************************************************************
// End of SSP testing
// ***********************************************************************







*** SSP: LPC11xx Synchronous Serial Port Driver [from SSP Help] ***

Overview

The SPI/SSP is a Synchronous Serial Port (SSP) controller capable of operation on a SPI, 4-wire SSI, or Microwire bus. It can interact (with frames of 4 bits to 16 bits of data) with multiple masters and slaves on the bus. 

Usage

1. Enable SSP block clock using SYSCON_AHBPeriphClockCmd() (see SYSCON). 


2. Using SSP_SSPxPinsInit() to assign SSP0 or SSP1 pins. 


3. Init SSP using SSP_Init(). 


4. Enable SSP peripheral's operation using SSP_Cmd(). 


5. Then you can use SSP_SendData() and SSP_ReceiveData() or SSP_ReadWrite() for data transfer. 


Source files

lpc11xx_ssp.h 

lpc11xx_ssp.c 

Dependency

SYSCON    IOCON    

*******************************************************************************
1. Enable SSP block clock using SYSCON_AHBPeriphClockCmd() (see SYSCON). 
*******************************************************************************

/* Enable SSP0 block clock */
SYSCON_AHBPeriphClockCmd(SYSCON_AHBPeriph_SSP0, ENABLE);

References: 

/*********************************************************************//**
 * @brief               Configure power supply for each peripheral according to NewState
 * @param[in]   Periph  Type of peripheral used to enable power,
 *                                      should be one of the following:
 *              -  SYSCON_AHBPeriph_SYS        : AHB to APB bridge
 *              -  SYSCON_AHBPeriph_ROM        : ROM
 *              -  SYSCON_AHBPeriph_RAM        : RAM
 *              -  SYSCON_AHBPeriph_FLASHREG   : Flash register interface
 *              -  SYSCON_AHBPeriph_FLASHARRAY : Flash array access
 *              -  SYSCON_AHBPeriph_I2C        : I2C
 *              -  SYSCON_AHBPeriph_GPIO       : GPIO
 *              -  SYSCON_AHBPeriph_CT16B0     : 16-bit counter/timer 0
 *              -  SYSCON_AHBPeriph_CT16B1     : 16-bit counter/timer 1
 *              -  SYSCON_AHBPeriph_CT32B0     : 32-bit counter/timer 0
 *              -  SYSCON_AHBPeriph_CT32B1     : 32-bit counter/timer 1
 *              -  SYSCON_AHBPeriph_SSP0       : SSP0
 *              -  SYSCON_AHBPeriph_UART       : UART
 *              -  SYSCON_AHBPeriph_ADC        : ADC
 *              -  SYSCON_AHBPeriph_WDT        : WDT
 *              -  SYSCON_AHBPeriph_IOCON      : IOCON
 *              -  SYSCON_AHBPeriph_SSP1       : SSP1             
 * @param[in]   NewState        New state of Peripheral Power, should be:
 *                              - ENABLE        : Enable power for this peripheral
 *                              - DISABLE       : Disable power for this peripheral
 *
 * @return none
 **********************************************************************/

void SYSCON_AHBPeriphClockCmd(uint32_t Periph, FunctionalState NewState)
{
    if(NewState == DISABLE) {
        LPC_SYSCON->SYSAHBCLKCTRL &= (~Periph) & SYSCON_AHBPeriph_BITMASK;
    } else if (NewState == ENABLE) {
        LPC_SYSCON->SYSAHBCLKCTRL |= Periph & SYSCON_AHBPeriph_BITMASK;    
    }   
}

/*********************************************************************//**
 * @brief               Configures the SPI0 peripheral clock SPI0_PCLK. The 
 *              SPI0_PCLK can be shut down by setting the DIV bits to 0x0.
 * @param[in]   DivVal  Value of divider           
 *
 * @return none
 **********************************************************************/
void SYSCON_SetSPI0ClockDiv(uint32_t DivVal)
{
    CHECK_PARAM(PARAM_DIVVAL(DivVal));
    LPC_SYSCON->SSP0CLKDIV = DivVal;
}


/*********************************************************************//**
 * @brief               Configures the SPI1 peripheral clock SPI10_PCLK. The 
 *              SPI10_PCLK can be shut down by setting the DivVal to 0x0.
 * @param[in]   DivVal  Value of divider           
 *
 * @return none
 **********************************************************************/

void SYSCON_SetSPI1ClockDiv(uint32_t DivVal)
{
    CHECK_PARAM(PARAM_DIVVAL(DivVal));
    LPC_SYSCON->SSP1CLKDIV = DivVal;
}



*******************************************************************************
2. Using SSP_SSPxPinsInit() to assign SSP0 or SSP1 pins. 
*******************************************************************************

// Assign P2.11 as SCK0, enable SSEL
SSP_SSP0PinsInit(SCK0_PIO2_11, ENABLE);

References: 

void SSP_SSP0PinsInit(SCK0_Position_Typedef sck0, FunctionalState useSSEL);

/********************************************************************//**
 * @brief Assigns SSP0 pins:
 *                MISO : PIO0_8
 *                MOSI : PIO0_9
 *                SCK  : PIO0_10/PIO2_11/PIO0_6
 *                SSEL : PIO0_2
 * @param[in] sck0 Locate SCK0 position, it can be
 *                   SCK0_PIO0_10 : pin location SWCLK/PIO0_10/SCK0/CT16B0_MAT2
 *                                  NOTE: SWCLK is JTAG pin
 *                   SCK0_PIO2_11 : pin location PIO2_11/SCK0
 *                   SCK0_PIO0_6  : pin location PIO0_6/SCK0
 *
 *               Note: SCK0_PIO0_10 is multiplexed with JTAG pins
 * @param[in] useSSEL Assign SSEL pin or not
 * @return None
 *********************************************************************/

void SSP_SSP0PinsInit(SCK0_Position_Typedef sck0, FunctionalState useSSEL)
{
    IOCON_SCK0Locate(sck0);

    IOCON_SetPinFunc(IOCON_PIO0_8, PIO0_8_FUN_MISO0);
    IOCON_SetPinFunc(IOCON_PIO0_9, PIO0_9_FUN_MOSI0);

    if(useSSEL == ENABLE) {
        IOCON_SetPinFunc(IOCON_PIO0_2, PIO0_2_FUN_SSEL0);
    }
           
    switch(sck0) {
    case SCK0_PIO0_10:
        IOCON_SetPinFunc(IOCON_PIO0_10, PIO0_10_FUN_SCK0); break;      
    case SCK0_PIO2_11:
        IOCON_SetPinFunc(IOCON_PIO2_11, PIO2_11_FUN_SCK0); break;
    case SCK0_PIO0_6:
        IOCON_SetPinFunc(IOCON_PIO0_6,  PIO0_6_FUN_SCK0);  break;
    default: break;
    }    
}

/**
 * @brief SCK pin location enumeration
 */
#define  offsetof(TYPE, MEMBER)  ((uint32_t)&((TYPE*)0)->MEMBER)

typedef enum
{
    SCK0_PIO0_10 = 0,     /** Selects SCK0 function in pin location 
                              SWCLK/PIO0_10/SCK0/CT16B0_MAT2        */
    SCK0_PIO2_11,         /** Selects SCK0 function in pin location PIO2_11/SCK0 */
    SCK0_PIO0_6,          /** Selects SCK0 function in pin location PIO0_6/SCK0 */
}SCK0_Position_Typedef;

#define PARAM_SCK(n)     ((n==SCK_PIO0_10) || (n==SCK_PIO2_11) || (n==SCK_PIO0_6))


/**
 * @brief Functional State Definition
 */
typedef enum {DISABLE = 0, ENABLE = !DISABLE} FunctionalState;
#define PARAM_FUNCTIONALSTATE(State) ((State==DISABLE) || (State==ENABLE))


*******************************************************************************
3. Init SSP using SSP_Init(). 
*******************************************************************************

// SSP Configuration structure variable 
SSP_CFG_Type SSP_ConfigStruct;

// initialize SSP configuration structure to default 

SSP_ConfigStructInit(&SSP_ConfigStruct);

// Initialize SSP peripheral with parameter given in structure above 

SSP_Init(LPC_SSP0, &SSP_ConfigStruct);

/*****************************************************************************//**
* @brief Fills each SSP_InitStruct member with its default value:
* - CPHA = SSP_CPHA_FIRST
* - CPOL = SSP_CPOL_HI
* - ClockRate = 1000000
* - Databit = SSP_DATABIT_8
* - Mode = SSP_MASTER_MODE
* - FrameFormat = SSP_FRAME_SSP
* @param[in] SSP_InitStruct Pointer to a SSP_CFG_Type structure
*                    which will be initialized.
* @return None
*******************************************************************************/
void SSP_ConfigStructInit(SSP_CFG_Type *SSP_InitStruct)
{
SSP_InitStruct->CPHA = SSP_CPHA_FIRST;
SSP_InitStruct->CPOL = SSP_CPOL_HI;
SSP_InitStruct->ClockRate = 1000000;
SSP_InitStruct->Databit = SSP_DATABIT_8;
SSP_InitStruct->Mode = SSP_MASTER_MODE;
SSP_InitStruct->FrameFormat = SSP_FRAME_SPI;
}

void SSP_Init(SSP_TypeDef *SSPx, SSP_CFG_Type *SSP_ConfigStruct);

/********************************************************************//**
 * @brief Initializes the SSPx peripheral according to the specified
 *               parameters in the SSP_ConfigStruct.
 * @param[in] SSPx SSP peripheral selected, should be SSP0 or SSP1
 * @param[in] SSP_ConfigStruct Pointer to a SSP_CFG_Type structure
 *                    that contains the configuration information for the
 *                    specified SSP peripheral.
 * @return None
 *********************************************************************/

void SSP_Init(SSP_TypeDef *SSPx, SSP_CFG_Type *SSP_ConfigStruct)
{
uint32_t tmp;

CHECK_PARAM(PARAM_SSPx(SSPx));

if(SSPx == LPC_SSP0) {
/* Set up clock and power for SSP0 module */
SYSCON_AHBPeriphClockCmd(SYSCON_AHBPeriph_SSP0, ENABLE);
} else if(SSPx == LPC_SSP1) {
/* Set up clock and power for SSP1 module */
SYSCON_AHBPeriphClockCmd(SYSCON_AHBPeriph_SSP1, ENABLE);
} else {
return;
}

/* Configure SSP, interrupt is disable, LoopBack mode is disable,
* SSP is disable, Slave output is disable as default
*/
tmp = ((SSP_ConfigStruct->CPHA) | (SSP_ConfigStruct->CPOL) \
| (SSP_ConfigStruct->FrameFormat) | (SSP_ConfigStruct->Databit))
& SSP_CR0_BITMASK;
// write back to SSP control register
SSPx->CR0 = tmp;
tmp = SSP_getNum(SSPx);
if (SSP_ConfigStruct->Databit > SSP_DATABIT_8){
sspdat[tmp].dataword = 1;
} else {
sspdat[tmp].dataword = 0;
}

tmp = SSP_ConfigStruct->Mode & SSP_CR1_BITMASK;
// Write back to CR1
SSPx->CR1 = tmp;

// Set clock rate for SSP peripheral
SSP_SetClock(SSPx, SSP_ConfigStruct->ClockRate);
}


********************************************************************************

/***********************************************************************//**
 * @file : LPC11xx_ssp.h
 * @brief : Contains all macro definitions and function prototypes
 * support for SSP firmware library on LPC11xx
 * @version : 1.0
 * @date : 21. Jan. 2010
 * @author : Coocox
 **************************************************************************/

/* Peripheral group ----------------------------------------------------------- */
/** @defgroup SSP
 * @ingroup LPC1100CMSIS_FwLib_Drivers
 * @{
 */

#ifndef __LPC11XX_SSP_H_
#define __LPC11XX_SSP_H_

/* Includes ------------------------------------------------------------------- */
#include "LPC11xx.h"
#include "lpc11xx_iocon.h"
#include "lpc_types.h"


#ifdef __cplusplus
extern "C"
{
#endif


/* Private Macros ------------------------------------------------------------- */
/** @defgroup SSP_Private_Macros
 * @{
 */

/*********************************************************************//**
 * Macro defines for CR0 register
 **********************************************************************/

/** @defgroup SSP_REGISTER_BIT_DEFINITION
 * @{
 */

/** SSP data size select, must be 4 bits to 16 bits */
#define SSP_CR0_DSS(n)   ((uint32_t)((n-1)&0xF))
/** SSP control 0 Motorola SPI mode */
#define SSP_CR0_FRF_SPI   ((uint32_t)(0<<4))
/** SSP control 0 TI synchronous serial mode */
#define SSP_CR0_FRF_TI   ((uint32_t)(1<<4))
/** SSP control 0 National Micro-wire mode */
#define SSP_CR0_FRF_MICROWIRE   ((uint32_t)(2<<4))
/** SPI clock polarity bit (used in SPI mode only), (1) = maintains the
   bus clock high between frames, (0) = low */
#define SSP_CR0_CPOL_HI ((uint32_t)(1<<6))
/** SPI clock out phase bit (used in SPI mode only), (1) = captures data
   on the second clock transition of the frame, (0) = first */
#define SSP_CR0_CPHA_SECOND ((uint32_t)(1<<7))
/** SSP serial clock rate value load macro, divider rate is
   PERIPH_CLK / (cpsr * (SCR + 1)) */
#define SSP_CR0_SCR(n)   ((uint32_t)((n&0xFF)<<8))
/** SSP CR0 bit mask */
#define SSP_CR0_BITMASK ((uint32_t)(0xFFFF))


/*********************************************************************//**
 * Macro defines for CR1 register
 **********************************************************************/
/** SSP control 1 loopback mode enable bit */
#define SSP_CR1_LBM_EN ((uint32_t)(1<<0))
/** SSP control 1 enable bit */
#define SSP_CR1_SSP_EN ((uint32_t)(1<<1))
/** SSP control 1 slave enable */
#define SSP_CR1_SLAVE_EN ((uint32_t)(1<<2))
/** SSP control 1 slave out disable bit, disables transmit line in slave
   mode */
#define SSP_CR1_SO_DISABLE ((uint32_t)(1<<3))
/** SSP CR1 bit mask */
#define SSP_CR1_BITMASK ((uint32_t)(0x0F))


/*********************************************************************//**
 * Macro defines for DR register
 **********************************************************************/
/** SSP data bit mask */
#define SSP_DR_BITMASK(n)   ((n)&0xFFFF)

/*********************************************************************//**
 * Macro defines for SR register
 **********************************************************************/
/** SSP status TX FIFO Empty bit */
#define SSP_SR_TFE      ((uint32_t)(1<<0))
/** SSP status TX FIFO not full bit */
#define SSP_SR_TNF      ((uint32_t)(1<<1))
/** SSP status RX FIFO not empty bit */
#define SSP_SR_RNE      ((uint32_t)(1<<2))
/** SSP status RX FIFO full bit */
#define SSP_SR_RFF      ((uint32_t)(1<<3))
/** SSP status SSP Busy bit */
#define SSP_SR_BSY      ((uint32_t)(1<<4))
/** SSP SR bit mask */
#define SSP_SR_BITMASK ((uint32_t)(0x1F))


/*********************************************************************//**
 * Macro defines for CPSR register
 **********************************************************************/
/** SSP clock prescaler */
#define SSP_CPSR_CPDVSR(n) ((uint32_t)(n&0xFF))
/** SSP CPSR bit mask */
#define SSP_CPSR_BITMASK ((uint32_t)(0xFF))


/*********************************************************************//**
 * Macro define for (IMSC) Interrupt Mask Set/Clear registers
 **********************************************************************/
/** Receive Overrun */
#define SSP_IMSC_ROR ((uint32_t)(1<<0))
/** Receive TimeOut */
#define SSP_IMSC_RT ((uint32_t)(1<<1))
/** Rx FIFO is at least half full */
#define SSP_IMSC_RX ((uint32_t)(1<<2))
/** Tx FIFO is at least half empty */
#define SSP_IMSC_TX ((uint32_t)(1<<3))
/** IMSC bit mask */
#define SSP_IMSC_BITMASK ((uint32_t)(0x0F))

/*********************************************************************//**
 * Macro define for (RIS) Raw Interrupt Status registers
 **********************************************************************/
/** Receive Overrun */
#define SSP_RIS_ROR ((uint32_t)(1<<0))
/** Receive TimeOut */
#define SSP_RIS_RT ((uint32_t)(1<<1))
/** Rx FIFO is at least half full */
#define SSP_RIS_RX ((uint32_t)(1<<2))
/** Tx FIFO is at least half empty */
#define SSP_RIS_TX ((uint32_t)(1<<3))
/** RIS bit mask */
#define SSP_RIS_BITMASK ((uint32_t)(0x0F))


/*********************************************************************//**
 * Macro define for (MIS) Masked Interrupt Status registers
 **********************************************************************/
/** Receive Overrun */
#define SSP_MIS_ROR ((uint32_t)(1<<0))
/** Receive TimeOut */
#define SSP_MIS_RT ((uint32_t)(1<<1))
/** Rx FIFO is at least half full */
#define SSP_MIS_RX ((uint32_t)(1<<2))
/** Tx FIFO is at least half empty */
#define SSP_MIS_TX ((uint32_t)(1<<3))
/** MIS bit mask */
#define SSP_MIS_BITMASK ((uint32_t)(0x0F))


/*********************************************************************//**
 * Macro define for (ICR) Interrupt Clear registers
 **********************************************************************/
/** Writing a 1 to this bit clears the "frame was received when
 * RxFIFO was full" interrupt */
#define SSP_ICR_ROR ((uint32_t)(1<<0))
/** Writing a 1 to this bit clears the "Rx FIFO was not empty and
 * has not been read for a timeout period" interrupt */
#define SSP_ICR_RT ((uint32_t)(1<<1))
/** ICR bit mask */
#define SSP_ICR_BITMASK ((uint32_t)(0x03))


/*********************************************************************//**
 * Macro defines for DMACR register
 **********************************************************************/
/** SSP bit for enabling RX DMA */
#define SSP_DMA_RXDMA_EN   ((uint32_t)(1<<0))
/** SSP bit for enabling TX DMA */
#define SSP_DMA_TXDMA_EN   ((uint32_t)(1<<1))
/** DMACR bit mask */
#define SSP_DMA_BITMASK ((uint32_t)(0x03))

/**
 * @}
 */

/**
 * @}
 */


/* Public Types --------------------------------------------------------------- */
/** @defgroup SSP_Public_Types
 * @{
 */

/** @brief SSP configuration structure */
typedef struct {
uint32_t Databit; /** Databit number, should be SSP_DATABIT_x,
where x is in range from 4 - 16 */
uint32_t CPHA; /** Clock phase, should be:
- SSP_CPHA_FIRST: first clock edge
- SSP_CPHA_SECOND: second clock edge */
uint32_t CPOL; /** Clock polarity, should be:
- SSP_CPOL_HI: high level
- SSP_CPOL_LO: low level */
uint32_t Mode; /** SSP mode, should be:
- SSP_MASTER_MODE: Master mode
- SSP_SLAVE_MODE: Slave mode */
uint32_t FrameFormat; /** Frame Format:
- SSP_FRAME_SPI: Motorola SPI frame format
- SSP_FRAME_TI: TI frame format
- SSP_FRAME_MICROWIRE: National Microwire frame format */
uint32_t ClockRate; /** Clock rate,in Hz */
} SSP_CFG_Type;

/**
 * @brief SSP Transfer Type definitions
 */
typedef enum {
SSP_TRANSFER_POLLING = 0, /**< Polling transfer */
SSP_TRANSFER_INTERRUPT /**< Interrupt transfer */
} SSP_TRANSFER_Type;

/**
 * @brief SPI Data configuration structure definitions
 */
typedef struct {
void *tx_data; /**< Pointer to transmit data */
uint32_t tx_cnt; /**< Transmit counter */
void *rx_data; /**< Pointer to transmit data */
uint32_t rx_cnt; /**< Receive counter */
uint32_t length; /**< Length of transfer data */
uint32_t status; /**< Current status of SSP activity */
void (*callback)(void); /**< Pointer to Call back function when transmission complete
used in interrupt transfer mode */
} SSP_DATA_SETUP_Type;


/**
 * @}
 */


/* Public Macros -------------------------------------------------------------- */
/** @defgroup SSP_Public_Macros
 * @{
 */

/** Macro to determine if it is valid SSP port number */
#define PARAM_SSPx(n) ((((uint32_t *)n)==((uint32_t *)LPC_SSP0)) \
|| (((uint32_t *)n)==((uint32_t *)LPC_SSP1)))

/*********************************************************************//**
 * SSP configuration parameter defines
 **********************************************************************/
/** Clock phase control bit */
#define SSP_CPHA_FIRST ((uint32_t)(0))
#define SSP_CPHA_SECOND SSP_CR0_CPHA_SECOND
#define PARAM_SSP_CPHA(n) ((n==SSP_CPHA_FIRST) || (n==SSP_CPHA_SECOND))

/** Clock polarity control bit */
#define SSP_CPOL_HI ((uint32_t)(0))
#define SSP_CPOL_LO SSP_CR0_CPOL_LOW
#define PARAM_SSP_CPOL(n) ((n==SSP_CPOL_HI) || (n==SSP_CPOL_LO))

/** SSP master mode enable */
#define SSP_SLAVE_MODE SSP_CR1_SLAVE_EN
#define SSP_MASTER_MODE ((uint32_t)(0))
#define PARAM_SSP_MODE(n) ((n==SSP_SLAVE_MODE) || (n==SSP_MASTER_MODE))

/** SSP data bit number defines */
#define SSP_DATABIT_4 SSP_CR0_DSS(4) /*!< Databit number = 4 */
#define SSP_DATABIT_5 SSP_CR0_DSS(5) /*!< Databit number = 5 */
#define SSP_DATABIT_6 SSP_CR0_DSS(6) /*!< Databit number = 6 */
#define SSP_DATABIT_7 SSP_CR0_DSS(7) /*!< Databit number = 7 */
#define SSP_DATABIT_8 SSP_CR0_DSS(8) /*!< Databit number = 8 */
#define SSP_DATABIT_9 SSP_CR0_DSS(9) /*!< Databit number = 9 */
#define SSP_DATABIT_10 SSP_CR0_DSS(10) /*!< Databit number = 10 */
#define SSP_DATABIT_11 SSP_CR0_DSS(11) /*!< Databit number = 11 */
#define SSP_DATABIT_12 SSP_CR0_DSS(12) /*!< Databit number = 12 */
#define SSP_DATABIT_13 SSP_CR0_DSS(13) /*!< Databit number = 13 */
#define SSP_DATABIT_14 SSP_CR0_DSS(14) /*!< Databit number = 14 */
#define SSP_DATABIT_15 SSP_CR0_DSS(15) /*!< Databit number = 15 */
#define SSP_DATABIT_16 SSP_CR0_DSS(16) /*!< Databit number = 16 */
#define PARAM_SSP_DATABIT(n) ((n==SSP_DATABIT_4) || (n==SSP_DATABIT_5) \
|| (n==SSP_DATABIT_6) || (n==SSP_DATABIT_16) \
|| (n==SSP_DATABIT_7) || (n==SSP_DATABIT_8) \
|| (n==SSP_DATABIT_9) || (n==SSP_DATABIT_10) \
|| (n==SSP_DATABIT_11) || (n==SSP_DATABIT_12) \
|| (n==SSP_DATABIT_13) || (n==SSP_DATABIT_14) \
|| (n==SSP_DATABIT_15))

/** SSP Frame Format definition */
/** Motorola SPI mode */
#define SSP_FRAME_SPI SSP_CR0_FRF_SPI
/** TI synchronous serial mode */
#define SSP_FRAME_TI SSP_CR0_FRF_TI
/** National Micro-wire mode */
#define SSP_FRAME_MICROWIRE SSP_CR0_FRF_MICROWIRE

#define PARAM_SSP_FRAME(n) ((n==SSP_FRAME_SPI) || (n==SSP_FRAME_TI) || (n==SSP_FRAME_MICROWIRE))


/*********************************************************************//**
 * SSP Status defines
 **********************************************************************/
/** SSP status TX FIFO Empty bit */
#define SSP_STAT_TXFIFO_EMPTY SSP_SR_TFE
/** SSP status TX FIFO not full bit */
#define SSP_STAT_TXFIFO_NOTFULL SSP_SR_TNF
/** SSP status RX FIFO not empty bit */
#define SSP_STAT_RXFIFO_NOTEMPTY SSP_SR_RNE
/** SSP status RX FIFO full bit */
#define SSP_STAT_RXFIFO_FULL SSP_SR_RFF
/** SSP status SSP Busy bit */
#define SSP_STAT_BUSY SSP_SR_BSY

#define PARAM_SSP_STAT(n) ((n==SSP_STAT_TXFIFO_EMPTY) || (n==SSP_STAT_TXFIFO_NOTFULL) \
|| (n==SSP_STAT_RXFIFO_NOTEMPTY) || (n==SSP_STAT_RXFIFO_FULL) \
|| (n==SSP_STAT_BUSY))


/*********************************************************************//**
 * SSP Interrupt Configuration defines
 **********************************************************************/
/** Receive Overrun */
#define SSP_INTCFG_ROR SSP_IMSC_ROR
/** Receive TimeOut */
#define SSP_INTCFG_RT SSP_IMSC_RT
/** Rx FIFO is at least half full */
#define SSP_INTCFG_RX SSP_IMSC_RX
/** Tx FIFO is at least half empty */
#define SSP_INTCFG_TX SSP_IMSC_TX

#define PARAM_SSP_INTCFG(n) ((n==SSP_INTCFG_ROR) || (n==SSP_INTCFG_RT) \
|| (n==SSP_INTCFG_RX) || (n==SSP_INTCFG_TX))


/*********************************************************************//**
 * SSP Configured Interrupt Status defines
 **********************************************************************/
/** Receive Overrun */
#define SSP_INTSTAT_ROR SSP_MIS_ROR
/** Receive TimeOut */
#define SSP_INTSTAT_RT SSP_MIS_RT
/** Rx FIFO is at least half full */
#define SSP_INTSTAT_RX SSP_MIS_RX
/** Tx FIFO is at least half empty */
#define SSP_INTSTAT_TX SSP_MIS_TX

#define PARAM_SSP_INTSTAT(n) ((n==SSP_INTSTAT_ROR) || (n==SSP_INTSTAT_RT) \
|| (n==SSP_INTSTAT_RX) || (n==SSP_INTSTAT_TX))


/*********************************************************************//**
 * SSP Raw Interrupt Status defines
 **********************************************************************/
/** Receive Overrun */
#define SSP_INTSTAT_RAW_ROR SSP_RIS_ROR
/** Receive TimeOut */
#define SSP_INTSTAT_RAW_RT SSP_RIS_RT
/** Rx FIFO is at least half full */
#define SSP_INTSTAT_RAW_RX SSP_RIS_RX
/** Tx FIFO is at least half empty */
#define SSP_INTSTAT_RAW_TX SSP_RIS_TX

#define PARAM_SSP_INTSTAT_RAW(n) ((n==SSP_INTSTAT_RAW_ROR) || (n==SSP_INTSTAT_RAW_RT) \
|| (n==SSP_INTSTAT_RAW_RX) || (n==SSP_INTSTAT_RAW_TX))


/*********************************************************************//**
 * SSP Interrupt Clear defines
 **********************************************************************/
/** Writing a 1 to this bit clears the "frame was received when
 * RxFIFO was full" interrupt */
#define SSP_INTCLR_ROR SSP_ICR_ROR
/** Writing a 1 to this bit clears the "Rx FIFO was not empty and
 * has not been read for a timeout period" interrupt */
#define SSP_INTCLR_RT SSP_ICR_RT

#define PARAM_SSP_INTCLR(n) ((n==SSP_INTCLR_ROR) || (n==SSP_INTCLR_RT))


/*********************************************************************//**
 * SSP DMA defines
 **********************************************************************/
/** SSP bit for enabling RX DMA */
#define SSP_DMA_TX SSP_DMA_RXDMA_EN
/** SSP bit for enabling TX DMA */
#define SSP_DMA_RX SSP_DMA_TXDMA_EN

#define PARAM_SSP_DMA(n) ((n==SSP_DMA_TX) || (n==SSP_DMA_RX))

/* SSP Status Implementation definitions */
#define SSP_STAT_DONE (1UL<<8) /**< Done */
#define SSP_STAT_ERROR (1UL<<9) /**< Error */

/**
 * @}
 */


/* Public Functions ----------------------------------------------------------- */
/** @defgroup SSP_Public_Functions
 * @{
 */

void SSP_SetClock (SSP_TypeDef *SSPx, uint32_t target_clock);
void SSP_DeInit(SSP_TypeDef* SSPx);
void SSP_SSP0PinsInit(SCK0_Position_Typedef sck0, FunctionalState useSSEL);
void SSP_SSP1PinsInit(FunctionalState useSSEL);
void SSP_Init(SSP_TypeDef *SSPx, SSP_CFG_Type *SSP_ConfigStruct);
void SSP_ConfigStructInit(SSP_CFG_Type *SSP_InitStruct);
void SSP_Cmd(SSP_TypeDef* SSPx, FunctionalState NewState);
void SSP_LoopBackCmd(SSP_TypeDef* SSPx, FunctionalState NewState);
void SSP_SlaveOutputCmd(SSP_TypeDef* SSPx, FunctionalState NewState);
void SSP_SendData(SSP_TypeDef* SSPx, uint16_t Data);
uint16_t SSP_ReceiveData(SSP_TypeDef* SSPx);
int32_t SSP_ReadWrite (SSP_TypeDef *SSPx, SSP_DATA_SETUP_Type *dataCfg, \
SSP_TRANSFER_Type xfType);
FlagStatus SSP_GetStatus(SSP_TypeDef* SSPx, uint32_t FlagType);
void SSP_IntConfig(SSP_TypeDef *SSPx, uint32_t IntType, FunctionalState NewState);
IntStatus SSP_GetRawIntStatus(SSP_TypeDef *SSPx, uint32_t RawIntType);
IntStatus SSP_GetIntStatus (SSP_TypeDef *SSPx, uint32_t IntType);
void SSP_ClearIntPending(SSP_TypeDef *SSPx, uint32_t IntType);
void SSP0_StdIntHandler(void);
void SSP1_StdIntHandler(void);

/**
 * @}
 */

#ifdef __cplusplus
}
#endif

#endif /* __LPC11XX_SSP_H_ */

/**
 * @}
 */

/* --------------------------------- End Of File ------------------------------ */



/***********************************************************************//**
 * @file : lpc11xx_ssp.c
 * @brief : Contains all functions support for SSP firmware library on LPC11xx
 * @version : 1.0
 * @date : 21. Jan. 2010
 * @author : Coocox
 **********************************************************************/

/* Peripheral group ----------------------------------------------------------- */
/** @addtogroup SSP
 * @{
 */

/* Includes ------------------------------------------------------------------- */
#include "lpc11xx_ssp.h"
#include "lpc11xx_syscon.h"
#include "lpc11xx_libcfg.h"


#if _SSP

/* Private Types -------------------------------------------------------------- */
/** @defgroup SSP_Private_Types
 * @{
 */

/** @brief SSP device configuration structure type */
typedef struct
{
int32_t dataword; /* Current data word: 0 - 8 bit; 1 - 16 bit */
uint32_t    txrx_setup; /* Transmission setup */
void (*inthandler)(SSP_TypeDef *SSPx);   /* Transmission interrupt handler */
} SSP_CFG_T;

/**
 * @}
 */

/* Private Variables ---------------------------------------------------------- */
/** @defgroup SSP_Private_Variables
 * @{
 */

/* SSP configuration data */
static SSP_CFG_T sspdat[2];

/**
 * @}
 */


/* Private Functions ---------------------------------------------------------- */
/** @defgroup SSP_Private_Functions
 * @{
 */

/**
 * @brief Convert from SSP peripheral to number
 */
static int32_t SSP_getNum(SSP_TypeDef *SSPx){
if (SSPx == LPC_SSP0) {
return (0);
} else if (SSPx == LPC_SSP1) {
return (1);
}
return (-1);
}


/*********************************************************************//**
 * @brief Standard Private SSP Interrupt handler
 * @param None
 * @return None
 ***********************************************************************/
void SSP_IntHandler(SSP_TypeDef *SSPx)
{
SSP_DATA_SETUP_Type *xf_setup;
    uint16_t tmp;
    int32_t sspnum;

    // Disable interrupt
    SSPx->IMSC = 0;

    sspnum = SSP_getNum(SSPx);
    xf_setup = (SSP_DATA_SETUP_Type *)sspdat[sspnum].txrx_setup;

    // save status
    tmp = SSPx->RIS;
    xf_setup->status = tmp;

    // Check overrun error
    if (tmp & SSP_RIS_ROR){
    // Clear interrupt
    SSPx->ICR = SSP_RIS_ROR;
    // update status
    xf_setup->status |= SSP_STAT_ERROR;
    // Callback
    if (xf_setup->callback != NULL){
    xf_setup->callback();
    }
    return;
    }

    if ((xf_setup->tx_cnt != xf_setup->length) || (xf_setup->rx_cnt != xf_setup->length)){
    /* check if RX FIFO contains data */
while ((SSPx->SR & SSP_SR_RNE) && (xf_setup->rx_cnt != xf_setup->length)){
// Read data from SSP data
tmp = SSP_ReceiveData(SSPx);

// Store data to destination
if (xf_setup->rx_data != NULL)
{
if (sspdat[sspnum].dataword == 0){
*(uint8_t *)((uint32_t)xf_setup->rx_data + xf_setup->rx_cnt) = (uint8_t) tmp;
} else {
*(uint16_t *)((uint32_t)xf_setup->rx_data + xf_setup->rx_cnt) = (uint16_t) tmp;
}
}
// Increase counter
if (sspdat[sspnum].dataword == 0){
xf_setup->rx_cnt++;
} else {
xf_setup->rx_cnt += 2;
}
}

while ((SSPx->SR & SSP_SR_TNF) && (xf_setup->tx_cnt != xf_setup->length)){
// Write data to buffer
if(xf_setup->tx_data == NULL){
if (sspdat[sspnum].dataword == 0){
SSP_SendData(SSPx, 0xFF);
xf_setup->tx_cnt++;
} else {
SSP_SendData(SSPx, 0xFFFF);
xf_setup->tx_cnt += 2;
}
} else {
if (sspdat[sspnum].dataword == 0){
SSP_SendData(SSPx, (*(uint8_t *)((uint32_t)xf_setup->tx_data + xf_setup->tx_cnt)));
xf_setup->tx_cnt++;
} else {
SSP_SendData(SSPx, (*(uint16_t *)((uint32_t)xf_setup->tx_data + xf_setup->tx_cnt)));
xf_setup->tx_cnt += 2;
}
}

   // Check overrun error
   if ((tmp = SSPx->RIS) & SSP_RIS_ROR){
    // update status
    xf_setup->status |= SSP_STAT_ERROR;
    // Callback
    if (xf_setup->callback != NULL){
    xf_setup->callback();
    }
    return;
   }

// Check for any data available in RX FIFO
while ((SSPx->SR & SSP_SR_RNE) && (xf_setup->rx_cnt != xf_setup->length)){
// Read data from SSP data
tmp = SSP_ReceiveData(SSPx);

// Store data to destination
if (xf_setup->rx_data != NULL)
{
if (sspdat[sspnum].dataword == 0){
*(uint8_t *)((uint32_t)xf_setup->rx_data + xf_setup->rx_cnt) = (uint8_t) tmp;
} else {
*(uint8_t *)((uint32_t)xf_setup->rx_data + xf_setup->rx_cnt) = (uint16_t) tmp;
}
}
// Increase counter
if (sspdat[sspnum].dataword == 0){
xf_setup->rx_cnt++;
} else {
xf_setup->rx_cnt += 2;
}
}
}
    }

// If there more data to sent or receive
if ((xf_setup->rx_cnt != xf_setup->length) || (xf_setup->tx_cnt != xf_setup->length)){
// Enable all interrupt
SSPx->IMSC = SSP_IMSC_BITMASK;
} else {
// Save status
xf_setup->status = SSP_STAT_DONE;
// Callback
if (xf_setup->callback != NULL){
xf_setup->callback();
}
}
}

/**
 * @}
 */


/* Public Functions ----------------------------------------------------------- */
/** @addtogroup SSP_Public_Functions
 * @{
 */

/*********************************************************************//**
 * @brief Setup clock rate for SSP device
 * @param[in] SSPx SSP peripheral definition, should be
 * SSP0 or SSP1.
 * @param[in] target_clock : clock of SSP (Hz)
 * @return None
 ***********************************************************************/
void SSP_SetClock (SSP_TypeDef *SSPx, uint32_t target_clock)
{
    uint32_t prescale, cr0_div, cmp_clk, ssp_clk;

    CHECK_PARAM(PARAM_SSPx(SSPx));

    /* The SSP clock is derived from the (main system oscillator / 2),
       so compute the best divider from that clock */
    if (SSPx == LPC_SSP0){
    ssp_clk = SYSCON_GetSSP0Clock(0);
    } else if (SSPx == LPC_SSP1) {
    ssp_clk = SYSCON_GetSSP0Clock(1);
    } else {
    return;
    }

/* Find closest divider to get at or under the target frequency.
  Use smallest prescale possible and rely on the divider to get
  the closest target frequency */
cr0_div = 0;
cmp_clk = 0xFFFFFFFF;
prescale = 2;
while (cmp_clk > target_clock)
{
cmp_clk = ssp_clk / ((cr0_div + 1) * prescale);
if (cmp_clk > target_clock)
{
cr0_div++;
if (cr0_div > 0xFF)
{
cr0_div = 0;
prescale += 2;
}
}
}

    /* Write computed prescaler and divider back to register */
    SSPx->CR0 &= (~SSP_CR0_SCR(0xFF)) & SSP_CR0_BITMASK;
    SSPx->CR0 |= (SSP_CR0_SCR(cr0_div)) & SSP_CR0_BITMASK;
    SSPx->CPSR = prescale & SSP_CPSR_BITMASK;
}


/*********************************************************************//**
 * @brief De-initializes the SSPx peripheral registers to their
*                  default reset values.
 * @param[in] SSPx SSP peripheral selected, should be SSP0 or SSP1
 * @return None
 **********************************************************************/
void SSP_DeInit(SSP_TypeDef* SSPx)
{
CHECK_PARAM(PARAM_SSPx(SSPx));

if (SSPx == LPC_SSP0){
        /* Reset SSP0 */        
        SYSCON_PeriphResetCmd(SYSCON_RSTPeriph_SSP0, ENABLE);                
        SYSCON_PeriphResetCmd(SYSCON_RSTPeriph_SSP0, DISABLE);                

/* Set up clock and power for SSP0 module */
SYSCON_AHBPeriphClockCmd(SYSCON_AHBPeriph_SSP0, DISABLE);
} else if (SSPx == LPC_SSP1) {
        /* Reset SSP1 */        
        SYSCON_PeriphResetCmd(SYSCON_RSTPeriph_SSP1, ENABLE);                
        SYSCON_PeriphResetCmd(SYSCON_RSTPeriph_SSP1, DISABLE);                        

/* Set up clock and power for SSP1 module */
SYSCON_AHBPeriphClockCmd(SYSCON_AHBPeriph_SSP1, DISABLE);
}
}

/********************************************************************//**
 * @brief Assigns SSP0 pins:
 *                MISO : PIO0_8
 *                MOSI : PIO0_9
 *                SCK  : PIO0_10/PIO2_11/PIO0_6
 *                SSEL : PIO0_2
 * @param[in] sck0 Locate SCK0 position, it can be
 *                   SCK0_PIO0_10 : pin location SWCLK/PIO0_10/SCK0/CT16B0_MAT2
 *                                  NOTE: SWCLK is JTAG pin
 *                   SCK0_PIO2_11 : pin location PIO2_11/SCK0
 *                   SCK0_PIO0_6  : pin location PIO0_6/SCK0
 *
 *               Note: SCK0_PIO0_10 is multiplexed with JTAG pins
 * @param[in] useSSEL Assign SSEL pin or not
 * @return None
 *********************************************************************/
void SSP_SSP0PinsInit(SCK0_Position_Typedef sck0, FunctionalState useSSEL)
{
    IOCON_SCK0Locate(sck0);

    IOCON_SetPinFunc(IOCON_PIO0_8, PIO0_8_FUN_MISO0);
    IOCON_SetPinFunc(IOCON_PIO0_9, PIO0_9_FUN_MOSI0);

    if(useSSEL == ENABLE) {
        IOCON_SetPinFunc(IOCON_PIO0_2, PIO0_2_FUN_SSEL0);
    }
           
    switch(sck0) {
    case SCK0_PIO0_10:
        IOCON_SetPinFunc(IOCON_PIO0_10, PIO0_10_FUN_SCK0); break;      
    case SCK0_PIO2_11:
        IOCON_SetPinFunc(IOCON_PIO2_11, PIO2_11_FUN_SCK0); break;
    case SCK0_PIO0_6:
        IOCON_SetPinFunc(IOCON_PIO0_6,  PIO0_6_FUN_SCK0);  break;
    default: break;
    }    
}

/********************************************************************//**
 * @brief Assigns SSP1 pins:
 *                MISO : PIO2_2
 *                MOSI : PIO2_3
 *                SCK  : PIO2_1
 *                SSEL : PIO2_0
 * @param[in] useSSEL Assign SSEL pin or not
 * @return None
 *********************************************************************/
void SSP_SSP1PinsInit(FunctionalState useSSEL)
{
    IOCON_SetPinFunc(IOCON_PIO2_2, PIO2_2_FUN_MISO1);
    IOCON_SetPinFunc(IOCON_PIO2_3, PIO2_3_FUN_PIO_MOSI1);
    IOCON_SetPinFunc(IOCON_PIO2_1, PIO2_1_FUN_SCK1);

    if(useSSEL == ENABLE) {
        IOCON_SetPinFunc(IOCON_PIO2_0, PIO2_0_FUN_SSEL1);
    }   
}

/********************************************************************//**
 * @brief Initializes the SSPx peripheral according to the specified
*               parameters in the SSP_ConfigStruct.
 * @param[in] SSPx SSP peripheral selected, should be SSP0 or SSP1
 * @param[in] SSP_ConfigStruct Pointer to a SSP_CFG_Type structure
*                    that contains the configuration information for the
*                    specified SSP peripheral.
 * @return None
 *********************************************************************/
void SSP_Init(SSP_TypeDef *SSPx, SSP_CFG_Type *SSP_ConfigStruct)
{
uint32_t tmp;

CHECK_PARAM(PARAM_SSPx(SSPx));

if(SSPx == LPC_SSP0) {
/* Set up clock and power for SSP0 module */
SYSCON_AHBPeriphClockCmd(SYSCON_AHBPeriph_SSP0, ENABLE);
} else if(SSPx == LPC_SSP1) {
/* Set up clock and power for SSP1 module */
SYSCON_AHBPeriphClockCmd(SYSCON_AHBPeriph_SSP1, ENABLE);
} else {
return;
}

/* Configure SSP, interrupt is disable, LoopBack mode is disable,
* SSP is disable, Slave output is disable as default
*/
tmp = ((SSP_ConfigStruct->CPHA) | (SSP_ConfigStruct->CPOL) \
| (SSP_ConfigStruct->FrameFormat) | (SSP_ConfigStruct->Databit))
& SSP_CR0_BITMASK;
// write back to SSP control register
SSPx->CR0 = tmp;
tmp = SSP_getNum(SSPx);
if (SSP_ConfigStruct->Databit > SSP_DATABIT_8){
sspdat[tmp].dataword = 1;
} else {
sspdat[tmp].dataword = 0;
}

tmp = SSP_ConfigStruct->Mode & SSP_CR1_BITMASK;
// Write back to CR1
SSPx->CR1 = tmp;

// Set clock rate for SSP peripheral
SSP_SetClock(SSPx, SSP_ConfigStruct->ClockRate);
}



/*****************************************************************************//**
* @brief Fills each SSP_InitStruct member with its default value:
* - CPHA = SSP_CPHA_FIRST
* - CPOL = SSP_CPOL_HI
* - ClockRate = 1000000
* - Databit = SSP_DATABIT_8
* - Mode = SSP_MASTER_MODE
* - FrameFormat = SSP_FRAME_SSP
* @param[in] SSP_InitStruct Pointer to a SSP_CFG_Type structure
*                    which will be initialized.
* @return None
*******************************************************************************/
void SSP_ConfigStructInit(SSP_CFG_Type *SSP_InitStruct)
{
SSP_InitStruct->CPHA = SSP_CPHA_FIRST;
SSP_InitStruct->CPOL = SSP_CPOL_HI;
SSP_InitStruct->ClockRate = 1000000;
SSP_InitStruct->Databit = SSP_DATABIT_8;
SSP_InitStruct->Mode = SSP_MASTER_MODE;
SSP_InitStruct->FrameFormat = SSP_FRAME_SPI;
}


/*********************************************************************//**
 * @brief Enable or disable SSP peripheral's operation
 * @param[in] SSPx SSP peripheral, should be SSP0 or SSP1
 * @param[in] NewState New State of SSPx peripheral's operation
 * @return none
 **********************************************************************/
void SSP_Cmd(SSP_TypeDef* SSPx, FunctionalState NewState)
{
CHECK_PARAM(PARAM_SSPx(SSPx));
CHECK_PARAM(PARAM_FUNCTIONALSTATE(NewState));

if (NewState == ENABLE)
{
SSPx->CR1 |= SSP_CR1_SSP_EN;
}
else
{
SSPx->CR1 &= (~SSP_CR1_SSP_EN) & SSP_CR1_BITMASK;
}
}



/*********************************************************************//**
 * @brief Enable or disable Loop Back mode function in SSP peripheral
 * @param[in] SSPx SSP peripheral selected, should be SSP0 or SSP1
 * @param[in] NewState New State of Loop Back mode, should be:
 * - ENABLE: Enable this function
 * - DISABLE: Disable this function
 * @return None
 **********************************************************************/
void SSP_LoopBackCmd(SSP_TypeDef* SSPx, FunctionalState NewState)
{
CHECK_PARAM(PARAM_SSPx(SSPx));
CHECK_PARAM(PARAM_FUNCTIONALSTATE(NewState));

if (NewState == ENABLE)
{
SSPx->CR1 |= SSP_CR1_LBM_EN;
}
else
{
SSPx->CR1 &= (~SSP_CR1_LBM_EN) & SSP_CR1_BITMASK;
}
}



/*********************************************************************//**
 * @brief Enable or disable Slave Output function in SSP peripheral
 * @param[in] SSPx SSP peripheral selected, should be SSP0 or SSP1
 * @param[in] NewState New State of Slave Output function, should be:
 * - ENABLE: Slave Output in normal operation
 * - DISABLE: Slave Output is disabled. This blocks
 * SSP controller from driving the transmit data
 * line (MISO)
 * Note: This function is available when SSP peripheral in Slave mode
 * @return None
 **********************************************************************/
void SSP_SlaveOutputCmd(SSP_TypeDef* SSPx, FunctionalState NewState)
{
CHECK_PARAM(PARAM_SSPx(SSPx));
CHECK_PARAM(PARAM_FUNCTIONALSTATE(NewState));

if (NewState == ENABLE)
{
SSPx->CR1 &= (~SSP_CR1_SO_DISABLE) & SSP_CR1_BITMASK;
}
else
{
SSPx->CR1 |= SSP_CR1_SO_DISABLE;
}
}



/*********************************************************************//**
 * @brief Transmit a single data through SSPx peripheral
 * @param[in] SSPx SSP peripheral selected, should be SSP
 * @param[in] Data Data to transmit (must be 16 or 8-bit long,
 * this depend on SSP data bit number configured)
 * @return none
 **********************************************************************/
void SSP_SendData(SSP_TypeDef* SSPx, uint16_t Data)
{
CHECK_PARAM(PARAM_SSPx(SSPx));

SSPx->DR = SSP_DR_BITMASK(Data);
}



/*********************************************************************//**
 * @brief Receive a single data from SSPx peripheral
 * @param[in] SSPx SSP peripheral selected, should be SSP
 * @return Data received (16-bit long)
 **********************************************************************/
uint16_t SSP_ReceiveData(SSP_TypeDef* SSPx)
{
CHECK_PARAM(PARAM_SSPx(SSPx));

return ((uint16_t) (SSP_DR_BITMASK(SSPx->DR)));
}

/*********************************************************************//**
 * @brief SSP Read write data function
 * @param[in] SSPx Pointer to SSP peripheral, should be SSP0 or SSP1
 * @param[in] dataCfg Pointer to a SSP_DATA_SETUP_Type structure that
 * contains specified information about transmit
 * data configuration.
 * @param[in] xfType Transfer type, should be:
 * - SSP_TRANSFER_POLLING: Polling mode
 * - SSP_TRANSFER_INTERRUPT: Interrupt mode
 * @return Actual Data length has been transferred in polling mode.
 * In interrupt mode, always return (0)
 * Return (-1) if error.
 * Note: This function can be used in both master and slave mode.
 ***********************************************************************/
int32_t SSP_ReadWrite (SSP_TypeDef *SSPx, SSP_DATA_SETUP_Type *dataCfg, \
SSP_TRANSFER_Type xfType)
{
uint8_t *rdata8;
    uint8_t *wdata8;
uint16_t *rdata16;
    uint16_t *wdata16;
    uint32_t stat;
    uint32_t tmp;
    int32_t sspnum;
    int32_t dataword;

    dataCfg->rx_cnt = 0;
    dataCfg->tx_cnt = 0;
    dataCfg->status = 0;


/* Clear all remaining data in RX FIFO */
while (SSPx->SR & SSP_SR_RNE){
tmp = (uint32_t) SSP_ReceiveData(SSPx);
}

// Clear status
SSPx->ICR = SSP_ICR_BITMASK;

sspnum = SSP_getNum(SSPx);
dataword = sspdat[sspnum].dataword;

// Polling mode ----------------------------------------------------------------------
if (xfType == SSP_TRANSFER_POLLING){
if (dataword == 0){
rdata8 = (uint8_t *)dataCfg->rx_data;
wdata8 = (uint8_t *)dataCfg->tx_data;
} else {
rdata16 = (uint16_t *)dataCfg->rx_data;
wdata16 = (uint16_t *)dataCfg->tx_data;
}
while ((dataCfg->tx_cnt != dataCfg->length) || (dataCfg->rx_cnt != dataCfg->length)){
if ((SSPx->SR & SSP_SR_TNF) && (dataCfg->tx_cnt != dataCfg->length)){
// Write data to buffer
if(dataCfg->tx_data == NULL){
if (dataword == 0){
SSP_SendData(SSPx, 0xFF);
dataCfg->tx_cnt++;
} else {
SSP_SendData(SSPx, 0xFFFF);
dataCfg->tx_cnt += 2;
}
} else {
if (dataword == 0){
SSP_SendData(SSPx, *wdata8);
wdata8++;
dataCfg->tx_cnt++;
} else {
SSP_SendData(SSPx, *wdata16);
wdata16++;
dataCfg->tx_cnt += 2;
}
}
}

// Check overrun error
if ((stat = SSPx->RIS) & SSP_RIS_ROR){
// save status and return
dataCfg->status = stat | SSP_STAT_ERROR;
return (-1);
}

// Check for any data available in RX FIFO
while ((SSPx->SR & SSP_SR_RNE) && (dataCfg->rx_cnt != dataCfg->length)){
// Read data from SSP data
tmp = SSP_ReceiveData(SSPx);

// Store data to destination
if (dataCfg->rx_data != NULL)
{
if (dataword == 0){
*(rdata8) = (uint8_t) tmp;
rdata8++;
} else {
*(rdata16) = (uint16_t) tmp;
rdata16++;
}
}
// Increase counter
if (dataword == 0){
dataCfg->rx_cnt++;
} else {
dataCfg->rx_cnt += 2;
}
}
}

// save status
dataCfg->status = SSP_STAT_DONE;

if (dataCfg->tx_data != NULL){
return dataCfg->tx_cnt;
} else if (dataCfg->rx_data != NULL){
return dataCfg->rx_cnt;
} else {
return (0);
}
}

// Interrupt mode ----------------------------------------------------------------------
else if (xfType == SSP_TRANSFER_INTERRUPT){
sspdat[sspnum].inthandler = SSP_IntHandler;
sspdat[sspnum].txrx_setup = (uint32_t)dataCfg;

while ((SSPx->SR & SSP_SR_TNF) && (dataCfg->tx_cnt != dataCfg->length)){
// Write data to buffer
if(dataCfg->tx_data == NULL){
if (sspdat[sspnum].dataword == 0){
SSP_SendData(SSPx, 0xFF);
dataCfg->tx_cnt++;
} else {
SSP_SendData(SSPx, 0xFFFF);
dataCfg->tx_cnt += 2;
}
} else {
if (sspdat[sspnum].dataword == 0){
SSP_SendData(SSPx, (*(uint8_t *)((uint32_t)dataCfg->tx_data + dataCfg->tx_cnt)));
dataCfg->tx_cnt++;
} else {
SSP_SendData(SSPx, (*(uint16_t *)((uint32_t)dataCfg->tx_data + dataCfg->tx_cnt)));
dataCfg->tx_cnt += 2;
}
}

// Check error
if ((stat = SSPx->RIS) & SSP_RIS_ROR){
// save status and return
dataCfg->status = stat | SSP_STAT_ERROR;
return (-1);
}

// Check for any data available in RX FIFO
while ((SSPx->SR & SSP_SR_RNE) && (dataCfg->rx_cnt != dataCfg->length)){
// Read data from SSP data
tmp = SSP_ReceiveData(SSPx);

// Store data to destination
if (dataCfg->rx_data != NULL)
{
if (sspdat[sspnum].dataword == 0){
*(uint8_t *)((uint32_t)dataCfg->rx_data + dataCfg->rx_cnt) = (uint8_t) tmp;
} else {
*(uint16_t *)((uint32_t)dataCfg->rx_data + dataCfg->rx_cnt) = (uint16_t) tmp;
}
}
// Increase counter
if (sspdat[sspnum].dataword == 0){
dataCfg->rx_cnt++;
} else {
dataCfg->rx_cnt += 2;
}
}
}

// If there more data to sent or receive
if ((dataCfg->rx_cnt != dataCfg->length) || (dataCfg->tx_cnt != dataCfg->length)){
// Enable all interrupt
SSPx->IMSC = SSP_IMSC_BITMASK;
} else {
// Save status
dataCfg->status = SSP_STAT_DONE;
}
return (0);
}

return (-1);
}

/*********************************************************************//**
 * @brief Checks whether the specified SSP status flag is set or not
 * @param[in] SSPx SSP peripheral selected, should be SSP0 or SSP1
 * @param[in] FlagType Type of flag to check status, should be one
 * of following:
 * - SSP_STAT_TXFIFO_EMPTY: TX FIFO is empty
 * - SSP_STAT_TXFIFO_NOTFULL: TX FIFO is not full
 * - SSP_STAT_RXFIFO_NOTEMPTY: RX FIFO is not empty
 * - SSP_STAT_RXFIFO_FULL: RX FIFO is full
 * - SSP_STAT_BUSY: SSP peripheral is busy
 * @return New State of specified SSP status flag
 **********************************************************************/
FlagStatus SSP_GetStatus(SSP_TypeDef* SSPx, uint32_t FlagType)
{
CHECK_PARAM(PARAM_SSPx(SSPx));
CHECK_PARAM(PARAM_SSP_STAT(FlagType));

return ((SSPx->SR & FlagType) ? SET : RESET);
}



/*********************************************************************//**
 * @brief Enable or disable specified interrupt type in SSP peripheral
 * @param[in] SSPx SSP peripheral selected, should be SSP0 or SSP1
 * @param[in] IntType Interrupt type in SSP peripheral, should be:
 * - SSP_INTCFG_ROR: Receive Overrun interrupt
 * - SSP_INTCFG_RT: Receive Time out interrupt
 * - SSP_INTCFG_RX: RX FIFO is at least half full interrupt
 * - SSP_INTCFG_TX: TX FIFO is at least half empty interrupt
 * @param[in] NewState New State of specified interrupt type, should be:
 * - ENABLE: Enable this interrupt type
 * - DISABLE: Disable this interrupt type
 * @return None
 **********************************************************************/
void SSP_IntConfig(SSP_TypeDef *SSPx, uint32_t IntType, FunctionalState NewState)
{
CHECK_PARAM(PARAM_SSPx(SSPx));
CHECK_PARAM(PARAM_SSP_INTCFG(IntType));

if (NewState == ENABLE)
{
SSPx->IMSC |= IntType;
}
else
{
SSPx->IMSC &= (~IntType) & SSP_IMSC_BITMASK;
}
}


/*********************************************************************//**
 * @brief Check whether the specified Raw interrupt status flag is
 * set or not
 * @param[in] SSPx SSP peripheral selected, should be SSP0 or SSP1
 * @param[in] RawIntType Raw Interrupt Type, should be:
 * - SSP_INTSTAT_RAW_ROR: Receive Overrun interrupt
 * - SSP_INTSTAT_RAW_RT: Receive Time out interrupt
 * - SSP_INTSTAT_RAW_RX: RX FIFO is at least half full interrupt
 * - SSP_INTSTAT_RAW_TX: TX FIFO is at least half empty interrupt
 * @return New State of specified Raw interrupt status flag in SSP peripheral
 * Note: Enabling/Disabling specified interrupt in SSP peripheral does not
 * effect to Raw Interrupt Status flag.
 **********************************************************************/
IntStatus SSP_GetRawIntStatus(SSP_TypeDef *SSPx, uint32_t RawIntType)
{
CHECK_PARAM(PARAM_SSPx(SSPx));
CHECK_PARAM(PARAM_SSP_INTSTAT_RAW(RawIntType));

return ((SSPx->RIS & RawIntType) ? SET : RESET);
}


/*********************************************************************//**
 * @brief Check whether the specified interrupt status flag is
 * set or not
 * @param[in] SSPx SSP peripheral selected, should be SSP0 or SSP1
 * @param[in] RawIntType Raw Interrupt Type, should be:
 * - SSP_INTSTAT_ROR: Receive Overrun interrupt
 * - SSP_INTSTAT_RT: Receive Time out interrupt
 * - SSP_INTSTAT_RX: RX FIFO is at least half full interrupt
 * - SSP_INTSTAT_TX: TX FIFO is at least half empty interrupt
 * @return New State of specified interrupt status flag in SSP peripheral
 * Note: Enabling/Disabling specified interrupt in SSP peripheral effects
 * to Interrupt Status flag.
 **********************************************************************/
IntStatus SSP_GetIntStatus (SSP_TypeDef *SSPx, uint32_t IntType)
{
CHECK_PARAM(PARAM_SSPx(SSPx));
CHECK_PARAM(PARAM_SSP_INTSTAT(IntType));

return ((SSPx->MIS & IntType) ? SET :RESET);
}



/*********************************************************************//**
 * @brief Clear specified interrupt pending in SSP peripheral
 * @param[in] SSPx SSP peripheral selected, should be SSP0 or SSP1
 * @param[in] IntType Interrupt pending to clear, should be:
 * - SSP_INTCLR_ROR: clears the "frame was received when
 * RxFIFO was full" interrupt.
 * - SSP_INTCLR_RT: clears the "Rx FIFO was not empty and
 * has not been read for a timeout period" interrupt.
 * @return None
 **********************************************************************/
void SSP_ClearIntPending(SSP_TypeDef *SSPx, uint32_t IntType)
{
CHECK_PARAM(PARAM_SSPx(SSPx));
CHECK_PARAM(PARAM_SSP_INTCLR(IntType));

SSPx->ICR = IntType;
}

/**
 * @brief Standard SSP0 Interrupt handler
 * @param[in] None
 * @return None
 */
void SSP0_StdIntHandler(void)
{
// Call relevant handler
sspdat[0].inthandler(LPC_SSP0);
}

/**
 * @brief Standard SSP1 Interrupt handler
 * @param[in] None
 * @return None
 */
void SSP1_StdIntHandler(void)
{
// Call relevant handler
sspdat[1].inthandler(LPC_SSP1);
}

/**
 * @}
 */

#endif /* _SSP */

/**
 * @}
 */

/* --------------------------------- End Of File ------------------------------ */







Example for SSP Views ( 893)  ssp master Author: CooCox

http://www.coocox.org/show_exam/SSP/192.html

Description:

This example describes how to use SPP in master mode, it is in self send and receive mode, only need to connect pin0.17 and pin0.18, it has been tested on the MCB-1700 Board. 

if send and receive ok, we blink the led which is connected to the p2.2, else the led which is connected to the p2.4 blink.

Example Code

#include "lpc17xx_ssp.h"
#include "lpc17xx_libcfg_default.h"
#include "lpc17xx_pinsel.h"
#include "lpc17xx_gpio.h"

/************************** PRIVATE DEFINTIONS ************************/
/** Max buffer length */
#define BUFFER_SIZE    0x40

/* SSP Configuration structure variable */
SSP_CFG_Type SSP_ConfigStruct;

/* Tx buffer */
uint8_t Tx_Buf[BUFFER_SIZE];

/* Rx buffer */
uint8_t Rx_Buf[BUFFER_SIZE];

/************************** PRIVATE FUNCTIONS *************************/
void Buffer_Init(void);
void Error_Loop(void);
uint8_t Buffer_Verify(void);
uint32_t i, j;
unsigned long LED_PINS  =  ((uint32_t)1<<2)|((uint32_t)1<<4) ;

/*-------------------------MAIN FUNCTION------------------------------*/
/*********************************************************************//**
 * @brief               c_entry: Main SSP program body
 * @param[in]   None
 * @return              int
 **********************************************************************/
int ssp_master(void)
{
        PINSEL_CFG_Type PinCfg;
        SSP_DATA_SETUP_Type xferConfig;

        /*
         * Initialize SPI pin connect
         * P0.15 - SCK;
         * P0.16 - SSEL
         * P0.17 - MISO
         * P0.18 - MOSI
         */
        PinCfg.Funcnum = 2;
        PinCfg.OpenDrain = 0;
        PinCfg.Pinmode = 0;
        PinCfg.Portnum = 0;
        PinCfg.Pinnum = 15;
        PINSEL_ConfigPin(&PinCfg);
        PinCfg.Pinnum = 17;
        PINSEL_ConfigPin(&PinCfg);
        PinCfg.Pinnum = 18;
        PINSEL_ConfigPin(&PinCfg);
        PinCfg.Pinnum = 16;
        PINSEL_ConfigPin(&PinCfg);

        /* initialize SSP configuration structure to default */
        SSP_ConfigStructInit(&SSP_ConfigStruct);
        /* Initialize SSP peripheral with parameter given in structure above */
        SSP_Init(LPC_SSP0, &SSP_ConfigStruct);

        /* Enable SSP peripheral */
        SSP_Cmd(LPC_SSP0, ENABLE);

        Buffer_Init();

        xferConfig.tx_data = Tx_Buf;
        xferConfig.rx_data = Rx_Buf;
        xferConfig.length = BUFFER_SIZE;
        SSP_ReadWrite(LPC_SSP0, &xferConfig, SSP_TRANSFER_POLLING);

        GPIO_SetDir(2, LED_PINS, 1);
        /* Verify buffer after transferring */
        if (Buffer_Verify()== 1){
                while(1){
                        /* Delay some time */
                        for(i=500; i>0; i--)
                                for(j=10000; j>0; j--) {
                                }
                        /* Output low level  */
                        GPIO_ClearValue(2, 0x04);
                        /* Delay some time */
                        for(i=500; i>0; i--)
                                for(j=10000; j>0; j--) {
                                }
                        /* Output high level */
                        GPIO_SetValue(2, 0x04);
                    }
        }
        else{
                while(1){
                   /* Delay some time */
                        for(i=500; i>0; i--)
                                for(j=10000; j>0; j--) {
                                }
                        /* Output low level  */
                        GPIO_ClearValue(2, 0x10);
                        /* Delay some time */
                        for(i=500; i>0; i--)
                                for(j=10000; j>0; j--) {
                                }
                        /* Output high level */
                        GPIO_SetValue(2, 0x10);
                }
        }
    return 1;
}

/*-------------------------PRIVATE FUNCTIONS------------------------------*/
/*********************************************************************//**
 * @brief               Initialize buffer
 * @param[in]   None
 * @return              None
 **********************************************************************/
void Buffer_Init(void)
{
        uint8_t i;

        for (i = 0; i < BUFFER_SIZE; i++) {
                Tx_Buf[i] = i;
                Rx_Buf[i] = 0;
        }
}

/*********************************************************************//**
 * @brief               Error Loop (called by Buffer_Verify() if any error)
 * @param[in]   none
 * @return              None
 **********************************************************************/
void Error_Loop(void)
{
        /* Loop forever */
        while (1);
}


/*********************************************************************//**
 * @brief               Verify buffer
 * @param[in]   none
 * @return              None
 **********************************************************************/
uint8_t Buffer_Verify(void)
{
        uint8_t i;
        uint8_t *src_addr = (uint8_t *) &Tx_Buf[0];
        uint8_t *dest_addr = (uint8_t *) &Rx_Buf[0];

        for ( i = 0; i < BUFFER_SIZE; i++ )
        {
                if ( *src_addr++ != *dest_addr++ )
                {
                        /* Call Error Loop */
                        return 0;
                }
        }
        return 1;
}

.END

No comments:

Post a Comment