NXP's driver library for LPC17xx, ported to mbed's online compiler. Not tested! I had to fix a lot of warings and found a couple of pretty obvious bugs, so the chances are there are more. Original: http://ics.nxp.com/support/documents/microcontrollers/zip/lpc17xx.cmsis.driver.library.zip

Dependencies:   mbed

Revision:
0:1063a091a062
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/source/lpc17xx_ssp.c	Wed Feb 17 16:22:39 2010 +0000
@@ -0,0 +1,831 @@
+/**
+ * @file    : lpc17xx_ssp.c
+ * @brief    : Contains all functions support for SSP firmware library on LPC17xx
+ * @version    : 1.0
+ * @date    : 9. April. 2009
+ * @author    : HieuNguyen
+ **************************************************************************
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * products. This software is supplied "AS IS" without any warranties.
+ * NXP Semiconductors assumes no responsibility or liability for the
+ * use of the software, conveys no license or title under any patent,
+ * copyright, or mask work right to the product. NXP Semiconductors
+ * reserves the right to make changes in the software without
+ * notification. NXP Semiconductors also make no representation or
+ * warranty that such application will be suitable for the specified
+ * use without further testing or modification.
+ **********************************************************************/
+
+/* Peripheral group ----------------------------------------------------------- */
+/** @addtogroup SSP
+ * @{
+ */
+
+/* Includes ------------------------------------------------------------------- */
+#include "lpc17xx_ssp.h"
+#include "lpc17xx_clkpwr.h"
+
+
+/* If this source file built with example, the LPC17xx FW library configuration
+ * file in each example directory ("lpc17xx_libcfg.h") must be included,
+ * otherwise the default FW library configuration file must be included instead
+ */
+#ifdef __BUILD_WITH_EXAMPLE__
+#include "lpc17xx_libcfg.h"
+#else
+#include "lpc17xx_libcfg_default.h"
+#endif /* __BUILD_WITH_EXAMPLE__ */
+
+
+#ifdef _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)(LPC_SSP_TypeDef *SSPx);       /* Transmission interrupt handler */
+} SSP_CFG_T;
+
+/**
+ * @}
+ */
+
+/* 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(LPC_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        SSPx: SSP peripheral definition, should be
+ *                       SSP0 or SSP1.
+ * @return         None
+ ***********************************************************************/
+void SSP_IntHandler(LPC_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 {
+                        *(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;
+                }
+            }
+        }
+    }
+
+    // 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 (LPC_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 = CLKPWR_GetPCLK (CLKPWR_PCLKSEL_SSP0);
+    } else if (SSPx == LPC_SSP1) {
+        ssp_clk = CLKPWR_GetPCLK (CLKPWR_PCLKSEL_SSP1);
+    } 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(LPC_SSP_TypeDef* SSPx)
+{
+    CHECK_PARAM(PARAM_SSPx(SSPx));
+
+    if (SSPx == LPC_SSP0){
+        /* Set up clock and power for SSP0 module */
+        CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCSSP0, DISABLE);
+    } else if (SSPx == LPC_SSP1) {
+        /* Set up clock and power for SSP1 module */
+        CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCSSP1, DISABLE);
+    }
+}
+
+
+
+/********************************************************************//**
+ * @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(LPC_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 */
+        CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCSSP0, ENABLE);
+    } else if(SSPx == LPC_SSP1) {
+        /* Set up clock and power for SSP1 module */
+        CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCSSP1, 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(LPC_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(LPC_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(LPC_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(LPC_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(LPC_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 (LPC_SSP_TypeDef *SSPx, SSP_DATA_SETUP_Type *dataCfg, \
+                        SSP_TRANSFER_Type xfType)
+{
+    uint8_t *rdata8=NULL;
+    uint8_t *wdata8=NULL;
+    uint16_t *rdata16=NULL;
+    uint16_t *wdata16=NULL;
+    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(LPC_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(LPC_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(LPC_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]    IntType    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 (LPC_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(LPC_SSP_TypeDef *SSPx, uint32_t IntType)
+{
+    CHECK_PARAM(PARAM_SSPx(SSPx));
+    CHECK_PARAM(PARAM_SSP_INTCLR(IntType));
+
+    SSPx->ICR = IntType;
+}
+
+/*********************************************************************//**
+ * @brief                Enable/Disable DMA function for SSP peripheral
+ * @param[in]    SSPx    SSP peripheral selected, should be SSP0 or SSP1
+ * @param[in]    DMAMode    Type of DMA, should be:
+ *                         - SSP_DMA_TX: DMA for the transmit FIFO
+ *                         - SSP_DMA_RX: DMA for the Receive FIFO
+ * @param[in]    NewState    New State of DMA function on SSP peripheral,
+ *                         should be:
+ *                         - ENALBE: Enable this function
+ *                         - DISABLE: Disable this function
+ * @return        None
+ **********************************************************************/
+void SSP_DMACmd(LPC_SSP_TypeDef *SSPx, uint32_t DMAMode, FunctionalState NewState)
+{
+    CHECK_PARAM(PARAM_SSPx(SSPx));
+    CHECK_PARAM(PARAM_SSP_DMA(DMAMode));
+    CHECK_PARAM(PARAM_FUNCTIONALSTATE(NewState));
+
+    if (NewState == ENABLE)
+    {
+        SSPx->DMACR |= DMAMode;
+    }
+    else
+    {
+        SSPx->DMACR &= (~DMAMode) & SSP_DMA_BITMASK;
+    }
+}
+
+/**
+ * @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 ------------------------------ */
+