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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers lpc17xx_ssp.c Source File

lpc17xx_ssp.c

Go to the documentation of this file.
00001 /**
00002  * @file    : lpc17xx_ssp.c
00003  * @brief    : Contains all functions support for SSP firmware library on LPC17xx
00004  * @version    : 1.0
00005  * @date    : 9. April. 2009
00006  * @author    : HieuNguyen
00007  **************************************************************************
00008  * Software that is described herein is for illustrative purposes only
00009  * which provides customers with programming information regarding the
00010  * products. This software is supplied "AS IS" without any warranties.
00011  * NXP Semiconductors assumes no responsibility or liability for the
00012  * use of the software, conveys no license or title under any patent,
00013  * copyright, or mask work right to the product. NXP Semiconductors
00014  * reserves the right to make changes in the software without
00015  * notification. NXP Semiconductors also make no representation or
00016  * warranty that such application will be suitable for the specified
00017  * use without further testing or modification.
00018  **********************************************************************/
00019 
00020 /* Peripheral group ----------------------------------------------------------- */
00021 /** @addtogroup SSP
00022  * @{
00023  */
00024 
00025 /* Includes ------------------------------------------------------------------- */
00026 #include "lpc17xx_ssp.h"
00027 #include "lpc17xx_clkpwr.h"
00028 
00029 
00030 /* If this source file built with example, the LPC17xx FW library configuration
00031  * file in each example directory ("lpc17xx_libcfg.h") must be included,
00032  * otherwise the default FW library configuration file must be included instead
00033  */
00034 #ifdef __BUILD_WITH_EXAMPLE__
00035 #include "lpc17xx_libcfg.h"
00036 #else
00037 #include "lpc17xx_libcfg_default.h"
00038 #endif /* __BUILD_WITH_EXAMPLE__ */
00039 
00040 
00041 #ifdef _SSP
00042 
00043 /* Private Types -------------------------------------------------------------- */
00044 /** @defgroup SSP_Private_Types
00045  * @{
00046  */
00047 
00048 /** @brief SSP device configuration structure type */
00049 typedef struct
00050 {
00051     int32_t     dataword;                /* Current data word: 0 - 8 bit; 1 - 16 bit */
00052     uint32_t    txrx_setup;             /* Transmission setup */
00053     void        (*inthandler)(LPC_SSP_TypeDef *SSPx);       /* Transmission interrupt handler */
00054 } SSP_CFG_T;
00055 
00056 /**
00057  * @}
00058  */
00059 
00060 /* Private Variables ---------------------------------------------------------- */
00061 /* SSP configuration data */
00062 static SSP_CFG_T sspdat[2];
00063 
00064 
00065 /* Private Functions ---------------------------------------------------------- */
00066 /** @defgroup SSP_Private_Functions
00067  * @{
00068  */
00069 
00070 /**
00071  * @brief Convert from SSP peripheral to number
00072  */
00073 static int32_t SSP_getNum(LPC_SSP_TypeDef *SSPx){
00074     if (SSPx == LPC_SSP0) {
00075         return (0);
00076     } else if (SSPx == LPC_SSP1) {
00077         return (1);
00078     }
00079     return (-1);
00080 }
00081 
00082 
00083 /*********************************************************************//**
00084  * @brief         Standard Private SSP Interrupt handler
00085  * @param        SSPx: SSP peripheral definition, should be
00086  *                       SSP0 or SSP1.
00087  * @return         None
00088  ***********************************************************************/
00089 void SSP_IntHandler(LPC_SSP_TypeDef *SSPx)
00090 {
00091     SSP_DATA_SETUP_Type *xf_setup;
00092     uint16_t tmp;
00093     int32_t sspnum;
00094 
00095     // Disable interrupt
00096     SSPx->IMSC = 0;
00097 
00098     sspnum = SSP_getNum(SSPx);
00099     xf_setup = (SSP_DATA_SETUP_Type *)sspdat[sspnum].txrx_setup;
00100 
00101     // save status
00102     tmp = SSPx->RIS;
00103     xf_setup->status = tmp;
00104 
00105     // Check overrun error
00106     if (tmp & SSP_RIS_ROR){
00107         // Clear interrupt
00108         SSPx->ICR = SSP_RIS_ROR;
00109         // update status
00110         xf_setup->status |= SSP_STAT_ERROR;
00111         // Callback
00112         if (xf_setup->callback != NULL){
00113             xf_setup->callback();
00114         }
00115         return;
00116     }
00117 
00118     if ((xf_setup->tx_cnt != xf_setup->length) || (xf_setup->rx_cnt != xf_setup->length)){
00119         /* check if RX FIFO contains data */
00120         while ((SSPx->SR & SSP_SR_RNE) && (xf_setup->rx_cnt != xf_setup->length)){
00121             // Read data from SSP data
00122             tmp = SSP_ReceiveData(SSPx);
00123 
00124             // Store data to destination
00125             if (xf_setup->rx_data != NULL)
00126             {
00127                 if (sspdat[sspnum].dataword == 0){
00128                     *(uint8_t *)((uint32_t)xf_setup->rx_data + xf_setup->rx_cnt) = (uint8_t) tmp;
00129                 } else {
00130                     *(uint16_t *)((uint32_t)xf_setup->rx_data + xf_setup->rx_cnt) = (uint16_t) tmp;
00131                 }
00132             }
00133             // Increase counter
00134             if (sspdat[sspnum].dataword == 0){
00135                 xf_setup->rx_cnt++;
00136             } else {
00137                 xf_setup->rx_cnt += 2;
00138             }
00139         }
00140 
00141         while ((SSPx->SR & SSP_SR_TNF) && (xf_setup->tx_cnt != xf_setup->length)){
00142             // Write data to buffer
00143             if(xf_setup->tx_data == NULL){
00144                 if (sspdat[sspnum].dataword == 0){
00145                     SSP_SendData(SSPx, 0xFF);
00146                     xf_setup->tx_cnt++;
00147                 } else {
00148                     SSP_SendData(SSPx, 0xFFFF);
00149                     xf_setup->tx_cnt += 2;
00150                 }
00151             } else {
00152                 if (sspdat[sspnum].dataword == 0){
00153                     SSP_SendData(SSPx, (*(uint8_t *)((uint32_t)xf_setup->tx_data + xf_setup->tx_cnt)));
00154                     xf_setup->tx_cnt++;
00155                 } else {
00156                     SSP_SendData(SSPx, (*(uint16_t *)((uint32_t)xf_setup->tx_data + xf_setup->tx_cnt)));
00157                     xf_setup->tx_cnt += 2;
00158                 }
00159             }
00160 
00161             // Check overrun error
00162             if ((tmp = SSPx->RIS) & SSP_RIS_ROR){
00163                 // update status
00164                 xf_setup->status |= SSP_STAT_ERROR;
00165                 // Callback
00166                 if (xf_setup->callback != NULL){
00167                     xf_setup->callback();
00168                 }
00169                 return;
00170             }
00171 
00172             // Check for any data available in RX FIFO
00173             while ((SSPx->SR & SSP_SR_RNE) && (xf_setup->rx_cnt != xf_setup->length)){
00174                 // Read data from SSP data
00175                 tmp = SSP_ReceiveData(SSPx);
00176 
00177                 // Store data to destination
00178                 if (xf_setup->rx_data != NULL)
00179                 {
00180                     if (sspdat[sspnum].dataword == 0){
00181                         *(uint8_t *)((uint32_t)xf_setup->rx_data + xf_setup->rx_cnt) = (uint8_t) tmp;
00182                     } else {
00183                         *(uint16_t *)((uint32_t)xf_setup->rx_data + xf_setup->rx_cnt) = (uint16_t) tmp;
00184                     }
00185                 }
00186                 // Increase counter
00187                 if (sspdat[sspnum].dataword == 0){
00188                     xf_setup->rx_cnt++;
00189                 } else {
00190                     xf_setup->rx_cnt += 2;
00191                 }
00192             }
00193         }
00194     }
00195 
00196     // If there more data to sent or receive
00197     if ((xf_setup->rx_cnt != xf_setup->length) || (xf_setup->tx_cnt != xf_setup->length)){
00198         // Enable all interrupt
00199         SSPx->IMSC = SSP_IMSC_BITMASK;
00200     } else {
00201         // Save status
00202         xf_setup->status = SSP_STAT_DONE;
00203         // Callback
00204         if (xf_setup->callback != NULL){
00205             xf_setup->callback();
00206         }
00207     }
00208 }
00209 
00210 /**
00211  * @}
00212  */
00213 
00214 
00215 /* Public Functions ----------------------------------------------------------- */
00216 /** @addtogroup SSP_Public_Functions
00217  * @{
00218  */
00219 
00220 /*********************************************************************//**
00221  * @brief         Setup clock rate for SSP device
00222  * @param[in]     SSPx    SSP peripheral definition, should be
00223  *                         SSP0 or SSP1.
00224  * @param[in]    target_clock : clock of SSP (Hz)
00225  * @return         None
00226  ***********************************************************************/
00227 void SSP_SetClock (LPC_SSP_TypeDef *SSPx, uint32_t target_clock)
00228 {
00229     uint32_t prescale, cr0_div, cmp_clk, ssp_clk;
00230 
00231     CHECK_PARAM(PARAM_SSPx(SSPx));
00232 
00233     /* The SSP clock is derived from the (main system oscillator / 2),
00234        so compute the best divider from that clock */
00235     if (SSPx == LPC_SSP0){
00236         ssp_clk = CLKPWR_GetPCLK (CLKPWR_PCLKSEL_SSP0);
00237     } else if (SSPx == LPC_SSP1) {
00238         ssp_clk = CLKPWR_GetPCLK (CLKPWR_PCLKSEL_SSP1);
00239     } else {
00240         return;
00241     }
00242 
00243     /* Find closest divider to get at or under the target frequency.
00244        Use smallest prescale possible and rely on the divider to get
00245        the closest target frequency */
00246     cr0_div = 0;
00247     cmp_clk = 0xFFFFFFFF;
00248     prescale = 2;
00249     while (cmp_clk > target_clock)
00250     {
00251         cmp_clk = ssp_clk / ((cr0_div + 1) * prescale);
00252         if (cmp_clk > target_clock)
00253         {
00254             cr0_div++;
00255             if (cr0_div > 0xFF)
00256             {
00257                 cr0_div = 0;
00258                 prescale += 2;
00259             }
00260         }
00261     }
00262 
00263     /* Write computed prescaler and divider back to register */
00264     SSPx->CR0 &= (~SSP_CR0_SCR(0xFF)) & SSP_CR0_BITMASK;
00265     SSPx->CR0 |= (SSP_CR0_SCR(cr0_div)) & SSP_CR0_BITMASK;
00266     SSPx->CPSR = prescale & SSP_CPSR_BITMASK;
00267 }
00268 
00269 
00270 /*********************************************************************//**
00271  * @brief        De-initializes the SSPx peripheral registers to their
00272 *                  default reset values.
00273  * @param[in]    SSPx    SSP peripheral selected, should be SSP0 or SSP1
00274  * @return         None
00275  **********************************************************************/
00276 void SSP_DeInit(LPC_SSP_TypeDef* SSPx)
00277 {
00278     CHECK_PARAM(PARAM_SSPx(SSPx));
00279 
00280     if (SSPx == LPC_SSP0){
00281         /* Set up clock and power for SSP0 module */
00282         CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCSSP0, DISABLE);
00283     } else if (SSPx == LPC_SSP1) {
00284         /* Set up clock and power for SSP1 module */
00285         CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCSSP1, DISABLE);
00286     }
00287 }
00288 
00289 
00290 
00291 /********************************************************************//**
00292  * @brief        Initializes the SSPx peripheral according to the specified
00293 *               parameters in the SSP_ConfigStruct.
00294  * @param[in]    SSPx    SSP peripheral selected, should be SSP0 or SSP1
00295  * @param[in]    SSP_ConfigStruct Pointer to a SSP_CFG_Type structure
00296 *                    that contains the configuration information for the
00297 *                    specified SSP peripheral.
00298  * @return         None
00299  *********************************************************************/
00300 void SSP_Init(LPC_SSP_TypeDef *SSPx, SSP_CFG_Type *SSP_ConfigStruct)
00301 {
00302     uint32_t tmp;
00303 
00304     CHECK_PARAM(PARAM_SSPx(SSPx));
00305 
00306     if(SSPx == LPC_SSP0) {
00307         /* Set up clock and power for SSP0 module */
00308         CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCSSP0, ENABLE);
00309     } else if(SSPx == LPC_SSP1) {
00310         /* Set up clock and power for SSP1 module */
00311         CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCSSP1, ENABLE);
00312     } else {
00313         return;
00314     }
00315 
00316     /* Configure SSP, interrupt is disable, LoopBack mode is disable,
00317      * SSP is disable, Slave output is disable as default
00318      */
00319     tmp = ((SSP_ConfigStruct->CPHA) | (SSP_ConfigStruct->CPOL) \
00320         | (SSP_ConfigStruct->FrameFormat) | (SSP_ConfigStruct->Databit))
00321         & SSP_CR0_BITMASK;
00322     // write back to SSP control register
00323     SSPx->CR0 = tmp;
00324     tmp = SSP_getNum(SSPx);
00325     if (SSP_ConfigStruct->Databit > SSP_DATABIT_8){
00326         sspdat[tmp].dataword = 1;
00327     } else {
00328         sspdat[tmp].dataword = 0;
00329     }
00330 
00331     tmp = SSP_ConfigStruct->Mode & SSP_CR1_BITMASK;
00332     // Write back to CR1
00333     SSPx->CR1 = tmp;
00334 
00335     // Set clock rate for SSP peripheral
00336     SSP_SetClock(SSPx, SSP_ConfigStruct->ClockRate);
00337 }
00338 
00339 
00340 
00341 /*****************************************************************************//**
00342 * @brief        Fills each SSP_InitStruct member with its default value:
00343 *                 - CPHA = SSP_CPHA_FIRST
00344 *                 - CPOL = SSP_CPOL_HI
00345 *                 - ClockRate = 1000000
00346 *                 - Databit = SSP_DATABIT_8
00347 *                 - Mode = SSP_MASTER_MODE
00348 *                 - FrameFormat = SSP_FRAME_SSP
00349 * @param[in]    SSP_InitStruct Pointer to a SSP_CFG_Type structure
00350 *                    which will be initialized.
00351 * @return        None
00352 *******************************************************************************/
00353 void SSP_ConfigStructInit(SSP_CFG_Type *SSP_InitStruct)
00354 {
00355     SSP_InitStruct->CPHA = SSP_CPHA_FIRST;
00356     SSP_InitStruct->CPOL = SSP_CPOL_HI;
00357     SSP_InitStruct->ClockRate = 1000000;
00358     SSP_InitStruct->Databit = SSP_DATABIT_8;
00359     SSP_InitStruct->Mode = SSP_MASTER_MODE;
00360     SSP_InitStruct->FrameFormat = SSP_FRAME_SPI;
00361 }
00362 
00363 
00364 /*********************************************************************//**
00365  * @brief        Enable or disable SSP peripheral's operation
00366  * @param[in]    SSPx    SSP peripheral, should be SSP0 or SSP1
00367  * @param[in]    NewState New State of SSPx peripheral's operation
00368  * @return         none
00369  **********************************************************************/
00370 void SSP_Cmd(LPC_SSP_TypeDef* SSPx, FunctionalState NewState)
00371 {
00372     CHECK_PARAM(PARAM_SSPx(SSPx));
00373     CHECK_PARAM(PARAM_FUNCTIONALSTATE(NewState));
00374 
00375     if (NewState == ENABLE)
00376     {
00377         SSPx->CR1 |= SSP_CR1_SSP_EN;
00378     }
00379     else
00380     {
00381         SSPx->CR1 &= (~SSP_CR1_SSP_EN) & SSP_CR1_BITMASK;
00382     }
00383 }
00384 
00385 
00386 
00387 /*********************************************************************//**
00388  * @brief        Enable or disable Loop Back mode function in SSP peripheral
00389  * @param[in]    SSPx    SSP peripheral selected, should be SSP0 or SSP1
00390  * @param[in]    NewState    New State of Loop Back mode, should be:
00391  *                             - ENABLE: Enable this function
00392  *                             - DISABLE: Disable this function
00393  * @return         None
00394  **********************************************************************/
00395 void SSP_LoopBackCmd(LPC_SSP_TypeDef* SSPx, FunctionalState NewState)
00396 {
00397     CHECK_PARAM(PARAM_SSPx(SSPx));
00398     CHECK_PARAM(PARAM_FUNCTIONALSTATE(NewState));
00399 
00400     if (NewState == ENABLE)
00401     {
00402         SSPx->CR1 |= SSP_CR1_LBM_EN;
00403     }
00404     else
00405     {
00406         SSPx->CR1 &= (~SSP_CR1_LBM_EN) & SSP_CR1_BITMASK;
00407     }
00408 }
00409 
00410 
00411 
00412 /*********************************************************************//**
00413  * @brief        Enable or disable Slave Output function in SSP peripheral
00414  * @param[in]    SSPx    SSP peripheral selected, should be SSP0 or SSP1
00415  * @param[in]    NewState    New State of Slave Output function, should be:
00416  *                             - ENABLE: Slave Output in normal operation
00417  *                             - DISABLE: Slave Output is disabled. This blocks
00418  *                             SSP controller from driving the transmit data
00419  *                             line (MISO)
00420  * Note:         This function is available when SSP peripheral in Slave mode
00421  * @return         None
00422  **********************************************************************/
00423 void SSP_SlaveOutputCmd(LPC_SSP_TypeDef* SSPx, FunctionalState NewState)
00424 {
00425     CHECK_PARAM(PARAM_SSPx(SSPx));
00426     CHECK_PARAM(PARAM_FUNCTIONALSTATE(NewState));
00427 
00428     if (NewState == ENABLE)
00429     {
00430         SSPx->CR1 &= (~SSP_CR1_SO_DISABLE) & SSP_CR1_BITMASK;
00431     }
00432     else
00433     {
00434         SSPx->CR1 |= SSP_CR1_SO_DISABLE;
00435     }
00436 }
00437 
00438 
00439 
00440 /*********************************************************************//**
00441  * @brief        Transmit a single data through SSPx peripheral
00442  * @param[in]    SSPx    SSP peripheral selected, should be SSP
00443  * @param[in]    Data    Data to transmit (must be 16 or 8-bit long,
00444  *                         this depend on SSP data bit number configured)
00445  * @return         none
00446  **********************************************************************/
00447 void SSP_SendData(LPC_SSP_TypeDef* SSPx, uint16_t Data)
00448 {
00449     CHECK_PARAM(PARAM_SSPx(SSPx));
00450 
00451     SSPx->DR = SSP_DR_BITMASK(Data);
00452 }
00453 
00454 
00455 
00456 /*********************************************************************//**
00457  * @brief        Receive a single data from SSPx peripheral
00458  * @param[in]    SSPx    SSP peripheral selected, should be SSP
00459  * @return         Data received (16-bit long)
00460  **********************************************************************/
00461 uint16_t SSP_ReceiveData(LPC_SSP_TypeDef* SSPx)
00462 {
00463     CHECK_PARAM(PARAM_SSPx(SSPx));
00464 
00465     return ((uint16_t) (SSP_DR_BITMASK(SSPx->DR)));
00466 }
00467 
00468 /*********************************************************************//**
00469  * @brief         SSP Read write data function
00470  * @param[in]    SSPx     Pointer to SSP peripheral, should be SSP0 or SSP1
00471  * @param[in]    dataCfg    Pointer to a SSP_DATA_SETUP_Type structure that
00472  *                         contains specified information about transmit
00473  *                         data configuration.
00474  * @param[in]    xfType    Transfer type, should be:
00475  *                         - SSP_TRANSFER_POLLING: Polling mode
00476  *                         - SSP_TRANSFER_INTERRUPT: Interrupt mode
00477  * @return         Actual Data length has been transferred in polling mode.
00478  *                 In interrupt mode, always return (0)
00479  *                 Return (-1) if error.
00480  * Note: This function can be used in both master and slave mode.
00481  ***********************************************************************/
00482 int32_t SSP_ReadWrite (LPC_SSP_TypeDef *SSPx, SSP_DATA_SETUP_Type *dataCfg, \
00483                         SSP_TRANSFER_Type xfType)
00484 {
00485     uint8_t *rdata8=NULL;
00486     uint8_t *wdata8=NULL;
00487     uint16_t *rdata16=NULL;
00488     uint16_t *wdata16=NULL;
00489     uint32_t stat;
00490     uint32_t tmp;
00491     int32_t sspnum;
00492     int32_t dataword;
00493 
00494     dataCfg->rx_cnt = 0;
00495     dataCfg->tx_cnt = 0;
00496     dataCfg->status = 0;
00497 
00498 
00499     /* Clear all remaining data in RX FIFO */
00500     while (SSPx->SR & SSP_SR_RNE){
00501         tmp = (uint32_t) SSP_ReceiveData(SSPx);
00502     }
00503 
00504     // Clear status
00505     SSPx->ICR = SSP_ICR_BITMASK;
00506 
00507     sspnum = SSP_getNum(SSPx);
00508     dataword = sspdat[sspnum].dataword;
00509 
00510     // Polling mode ----------------------------------------------------------------------
00511     if (xfType == SSP_TRANSFER_POLLING){
00512         if (dataword == 0){
00513             rdata8 = (uint8_t *)dataCfg->rx_data;
00514             wdata8 = (uint8_t *)dataCfg->tx_data;
00515         } else {
00516             rdata16 = (uint16_t *)dataCfg->rx_data;
00517             wdata16 = (uint16_t *)dataCfg->tx_data;
00518         }
00519         while ((dataCfg->tx_cnt != dataCfg->length) || (dataCfg->rx_cnt != dataCfg->length)){
00520             if ((SSPx->SR & SSP_SR_TNF) && (dataCfg->tx_cnt != dataCfg->length)){
00521                 // Write data to buffer
00522                 if(dataCfg->tx_data == NULL){
00523                     if (dataword == 0){
00524                         SSP_SendData(SSPx, 0xFF);
00525                         dataCfg->tx_cnt++;
00526                     } else {
00527                         SSP_SendData(SSPx, 0xFFFF);
00528                         dataCfg->tx_cnt += 2;
00529                     }
00530                 } else {
00531                     if (dataword == 0){
00532                         SSP_SendData(SSPx, *wdata8);
00533                         wdata8++;
00534                         dataCfg->tx_cnt++;
00535                     } else {
00536                         SSP_SendData(SSPx, *wdata16);
00537                         wdata16++;
00538                         dataCfg->tx_cnt += 2;
00539                     }
00540                 }
00541             }
00542 
00543             // Check overrun error
00544             if ((stat = SSPx->RIS) & SSP_RIS_ROR){
00545                 // save status and return
00546                 dataCfg->status = stat | SSP_STAT_ERROR;
00547                 return (-1);
00548             }
00549 
00550             // Check for any data available in RX FIFO
00551             while ((SSPx->SR & SSP_SR_RNE) && (dataCfg->rx_cnt != dataCfg->length)){
00552                 // Read data from SSP data
00553                 tmp = SSP_ReceiveData(SSPx);
00554 
00555                 // Store data to destination
00556                 if (dataCfg->rx_data != NULL)
00557                 {
00558                     if (dataword == 0){
00559                         *(rdata8) = (uint8_t) tmp;
00560                         rdata8++;
00561                     } else {
00562                         *(rdata16) = (uint16_t) tmp;
00563                         rdata16++;
00564                     }
00565                 }
00566                 // Increase counter
00567                 if (dataword == 0){
00568                     dataCfg->rx_cnt++;
00569                 } else {
00570                     dataCfg->rx_cnt += 2;
00571                 }
00572             }
00573         }
00574 
00575         // save status
00576         dataCfg->status = SSP_STAT_DONE;
00577 
00578         if (dataCfg->tx_data != NULL){
00579             return dataCfg->tx_cnt;
00580         } else if (dataCfg->rx_data != NULL){
00581             return dataCfg->rx_cnt;
00582         } else {
00583             return (0);
00584         }
00585     }
00586 
00587     // Interrupt mode ----------------------------------------------------------------------
00588     else if (xfType == SSP_TRANSFER_INTERRUPT){
00589         sspdat[sspnum].inthandler = SSP_IntHandler;
00590         sspdat[sspnum].txrx_setup = (uint32_t)dataCfg;
00591 
00592         while ((SSPx->SR & SSP_SR_TNF) && (dataCfg->tx_cnt != dataCfg->length)){
00593             // Write data to buffer
00594             if(dataCfg->tx_data == NULL){
00595                 if (sspdat[sspnum].dataword == 0){
00596                     SSP_SendData(SSPx, 0xFF);
00597                     dataCfg->tx_cnt++;
00598                 } else {
00599                     SSP_SendData(SSPx, 0xFFFF);
00600                     dataCfg->tx_cnt += 2;
00601                 }
00602             } else {
00603                 if (sspdat[sspnum].dataword == 0){
00604                     SSP_SendData(SSPx, (*(uint8_t *)((uint32_t)dataCfg->tx_data + dataCfg->tx_cnt)));
00605                     dataCfg->tx_cnt++;
00606                 } else {
00607                     SSP_SendData(SSPx, (*(uint16_t *)((uint32_t)dataCfg->tx_data + dataCfg->tx_cnt)));
00608                     dataCfg->tx_cnt += 2;
00609                 }
00610             }
00611 
00612             // Check error
00613             if ((stat = SSPx->RIS) & SSP_RIS_ROR){
00614                 // save status and return
00615                 dataCfg->status = stat | SSP_STAT_ERROR;
00616                 return (-1);
00617             }
00618 
00619             // Check for any data available in RX FIFO
00620             while ((SSPx->SR & SSP_SR_RNE) && (dataCfg->rx_cnt != dataCfg->length)){
00621                 // Read data from SSP data
00622                 tmp = SSP_ReceiveData(SSPx);
00623 
00624                 // Store data to destination
00625                 if (dataCfg->rx_data != NULL)
00626                 {
00627                     if (sspdat[sspnum].dataword == 0){
00628                         *(uint8_t *)((uint32_t)dataCfg->rx_data + dataCfg->rx_cnt) = (uint8_t) tmp;
00629                     } else {
00630                         *(uint16_t *)((uint32_t)dataCfg->rx_data + dataCfg->rx_cnt) = (uint16_t) tmp;
00631                     }
00632                 }
00633                 // Increase counter
00634                 if (sspdat[sspnum].dataword == 0){
00635                     dataCfg->rx_cnt++;
00636                 } else {
00637                     dataCfg->rx_cnt += 2;
00638                 }
00639             }
00640         }
00641 
00642         // If there more data to sent or receive
00643         if ((dataCfg->rx_cnt != dataCfg->length) || (dataCfg->tx_cnt != dataCfg->length)){
00644             // Enable all interrupt
00645             SSPx->IMSC = SSP_IMSC_BITMASK;
00646         } else {
00647             // Save status
00648             dataCfg->status = SSP_STAT_DONE;
00649         }
00650         return (0);
00651     }
00652 
00653     return (-1);
00654 }
00655 
00656 /*********************************************************************//**
00657  * @brief        Checks whether the specified SSP status flag is set or not
00658  * @param[in]    SSPx    SSP peripheral selected, should be SSP0 or SSP1
00659  * @param[in]    FlagType    Type of flag to check status, should be one
00660  *                             of following:
00661  *                            - SSP_STAT_TXFIFO_EMPTY: TX FIFO is empty
00662  *                            - SSP_STAT_TXFIFO_NOTFULL: TX FIFO is not full
00663  *                            - SSP_STAT_RXFIFO_NOTEMPTY: RX FIFO is not empty
00664  *                            - SSP_STAT_RXFIFO_FULL: RX FIFO is full
00665  *                            - SSP_STAT_BUSY: SSP peripheral is busy
00666  * @return        New State of specified SSP status flag
00667  **********************************************************************/
00668 FlagStatus SSP_GetStatus(LPC_SSP_TypeDef* SSPx, uint32_t FlagType)
00669 {
00670     CHECK_PARAM(PARAM_SSPx(SSPx));
00671     CHECK_PARAM(PARAM_SSP_STAT(FlagType));
00672 
00673     return ((SSPx->SR & FlagType) ? SET : RESET);
00674 }
00675 
00676 
00677 
00678 /*********************************************************************//**
00679  * @brief        Enable or disable specified interrupt type in SSP peripheral
00680  * @param[in]    SSPx    SSP peripheral selected, should be SSP0 or SSP1
00681  * @param[in]    IntType    Interrupt type in SSP peripheral, should be:
00682  *                 - SSP_INTCFG_ROR: Receive Overrun interrupt
00683  *                 - SSP_INTCFG_RT: Receive Time out interrupt
00684  *                 - SSP_INTCFG_RX: RX FIFO is at least half full interrupt
00685  *                 - SSP_INTCFG_TX: TX FIFO is at least half empty interrupt
00686  * @param[in]    NewState New State of specified interrupt type, should be:
00687  *                 - ENABLE: Enable this interrupt type
00688  *                 - DISABLE: Disable this interrupt type
00689  * @return        None
00690  **********************************************************************/
00691 void SSP_IntConfig(LPC_SSP_TypeDef *SSPx, uint32_t IntType, FunctionalState NewState)
00692 {
00693     CHECK_PARAM(PARAM_SSPx(SSPx));
00694     CHECK_PARAM(PARAM_SSP_INTCFG(IntType));
00695 
00696     if (NewState == ENABLE)
00697     {
00698         SSPx->IMSC |= IntType;
00699     }
00700     else
00701     {
00702         SSPx->IMSC &= (~IntType) & SSP_IMSC_BITMASK;
00703     }
00704 }
00705 
00706 
00707 /*********************************************************************//**
00708  * @brief    Check whether the specified Raw interrupt status flag is
00709  *             set or not
00710  * @param[in]    SSPx    SSP peripheral selected, should be SSP0 or SSP1
00711  * @param[in]    RawIntType    Raw Interrupt Type, should be:
00712  *                 - SSP_INTSTAT_RAW_ROR: Receive Overrun interrupt
00713  *                 - SSP_INTSTAT_RAW_RT: Receive Time out interrupt
00714  *                 - SSP_INTSTAT_RAW_RX: RX FIFO is at least half full interrupt
00715  *                 - SSP_INTSTAT_RAW_TX: TX FIFO is at least half empty interrupt
00716  * @return    New State of specified Raw interrupt status flag in SSP peripheral
00717  * Note: Enabling/Disabling specified interrupt in SSP peripheral does not
00718  *         effect to Raw Interrupt Status flag.
00719  **********************************************************************/
00720 IntStatus SSP_GetRawIntStatus(LPC_SSP_TypeDef *SSPx, uint32_t RawIntType)
00721 {
00722     CHECK_PARAM(PARAM_SSPx(SSPx));
00723     CHECK_PARAM(PARAM_SSP_INTSTAT_RAW(RawIntType));
00724 
00725     return ((SSPx->RIS & RawIntType) ? SET : RESET);
00726 }
00727 
00728 
00729 /*********************************************************************//**
00730  * @brief    Check whether the specified interrupt status flag is
00731  *             set or not
00732  * @param[in]    SSPx    SSP peripheral selected, should be SSP0 or SSP1
00733  * @param[in]    IntType    Raw Interrupt Type, should be:
00734  *                 - SSP_INTSTAT_ROR: Receive Overrun interrupt
00735  *                 - SSP_INTSTAT_RT: Receive Time out interrupt
00736  *                 - SSP_INTSTAT_RX: RX FIFO is at least half full interrupt
00737  *                 - SSP_INTSTAT_TX: TX FIFO is at least half empty interrupt
00738  * @return    New State of specified interrupt status flag in SSP peripheral
00739  * Note: Enabling/Disabling specified interrupt in SSP peripheral effects
00740  *             to Interrupt Status flag.
00741  **********************************************************************/
00742 IntStatus SSP_GetIntStatus (LPC_SSP_TypeDef *SSPx, uint32_t IntType)
00743 {
00744     CHECK_PARAM(PARAM_SSPx(SSPx));
00745     CHECK_PARAM(PARAM_SSP_INTSTAT(IntType));
00746 
00747     return ((SSPx->MIS & IntType) ? SET :RESET);
00748 }
00749 
00750 
00751 
00752 /*********************************************************************//**
00753  * @brief                Clear specified interrupt pending in SSP peripheral
00754  * @param[in]    SSPx    SSP peripheral selected, should be SSP0 or SSP1
00755  * @param[in]    IntType    Interrupt pending to clear, should be:
00756  *                         - SSP_INTCLR_ROR: clears the "frame was received when
00757  *                         RxFIFO was full" interrupt.
00758  *                         - SSP_INTCLR_RT: clears the "Rx FIFO was not empty and
00759  *                         has not been read for a timeout period" interrupt.
00760  * @return        None
00761  **********************************************************************/
00762 void SSP_ClearIntPending(LPC_SSP_TypeDef *SSPx, uint32_t IntType)
00763 {
00764     CHECK_PARAM(PARAM_SSPx(SSPx));
00765     CHECK_PARAM(PARAM_SSP_INTCLR(IntType));
00766 
00767     SSPx->ICR = IntType;
00768 }
00769 
00770 /*********************************************************************//**
00771  * @brief                Enable/Disable DMA function for SSP peripheral
00772  * @param[in]    SSPx    SSP peripheral selected, should be SSP0 or SSP1
00773  * @param[in]    DMAMode    Type of DMA, should be:
00774  *                         - SSP_DMA_TX: DMA for the transmit FIFO
00775  *                         - SSP_DMA_RX: DMA for the Receive FIFO
00776  * @param[in]    NewState    New State of DMA function on SSP peripheral,
00777  *                         should be:
00778  *                         - ENALBE: Enable this function
00779  *                         - DISABLE: Disable this function
00780  * @return        None
00781  **********************************************************************/
00782 void SSP_DMACmd(LPC_SSP_TypeDef *SSPx, uint32_t DMAMode, FunctionalState NewState)
00783 {
00784     CHECK_PARAM(PARAM_SSPx(SSPx));
00785     CHECK_PARAM(PARAM_SSP_DMA(DMAMode));
00786     CHECK_PARAM(PARAM_FUNCTIONALSTATE(NewState));
00787 
00788     if (NewState == ENABLE)
00789     {
00790         SSPx->DMACR |= DMAMode;
00791     }
00792     else
00793     {
00794         SSPx->DMACR &= (~DMAMode) & SSP_DMA_BITMASK;
00795     }
00796 }
00797 
00798 /**
00799  * @brief        Standard SSP0 Interrupt handler
00800  * @param[in]     None
00801  * @return        None
00802  */
00803 void SSP0_StdIntHandler(void)
00804 {
00805     // Call relevant handler
00806     sspdat[0].inthandler(LPC_SSP0);
00807 }
00808 
00809 /**
00810  * @brief        Standard SSP1 Interrupt handler
00811  * @param[in]     None
00812  * @return        None
00813  */
00814 void SSP1_StdIntHandler(void)
00815 {
00816     // Call relevant handler
00817     sspdat[1].inthandler(LPC_SSP1);
00818 }
00819 
00820 /**
00821  * @}
00822  */
00823 
00824 #endif /* _SSP */
00825 
00826 /**
00827  * @}
00828  */
00829 
00830 /* --------------------------------- End Of File ------------------------------ */
00831