uc-sdk
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
lpc17xx_ssp.c
Go to the documentation of this file.
1 /***********************************************************************/
20 /* Peripheral group ----------------------------------------------------------- */
25 /* Includes ------------------------------------------------------------------- */
26 #include "lpc17xx_ssp.h"
27 #include "lpc17xx_clkpwr.h"
28 
29 
30 /* If this source file built with example, the LPC17xx FW library configuration
31  * file in each example directory ("lpc17xx_libcfg.h") must be included,
32  * otherwise the default FW library configuration file must be included instead
33  */
34 #ifdef __BUILD_WITH_EXAMPLE__
35 #include "lpc17xx_libcfg.h"
36 #else
37 #include "lpc17xx_libcfg_default.h"
38 #endif /* __BUILD_WITH_EXAMPLE__ */
39 
40 
41 #ifdef _SSP
42 
43 /* Public Functions ----------------------------------------------------------- */
47 static void setSSPclock (LPC_SSP_TypeDef *SSPx, uint32_t target_clock);
48 
49 /*********************************************************************/
57 static void setSSPclock (LPC_SSP_TypeDef *SSPx, uint32_t target_clock)
58 {
59  uint32_t prescale, cr0_div, cmp_clk, ssp_clk;
60 
61  CHECK_PARAM(PARAM_SSPx(SSPx));
62 
63  /* The SSP clock is derived from the (main system oscillator / 2),
64  so compute the best divider from that clock */
65  if (SSPx == LPC_SSP0){
67  } else if (SSPx == LPC_SSP1) {
69  } else {
70  return;
71  }
72 
73  /* Find closest divider to get at or under the target frequency.
74  Use smallest prescale possible and rely on the divider to get
75  the closest target frequency */
76  cr0_div = 0;
77  cmp_clk = 0xFFFFFFFF;
78  prescale = 2;
79  while (cmp_clk > target_clock)
80  {
81  cmp_clk = ssp_clk / ((cr0_div + 1) * prescale);
82  if (cmp_clk > target_clock)
83  {
84  cr0_div++;
85  if (cr0_div > 0xFF)
86  {
87  cr0_div = 0;
88  prescale += 2;
89  }
90  }
91  }
92 
93  /* Write computed prescaler and divider back to register */
94  SSPx->CR0 &= (~SSP_CR0_SCR(0xFF)) & SSP_CR0_BITMASK;
95  SSPx->CR0 |= (SSP_CR0_SCR(cr0_div)) & SSP_CR0_BITMASK;
96  SSPx->CPSR = prescale & SSP_CPSR_BITMASK;
97 }
98 
103 /* Public Functions ----------------------------------------------------------- */
108 /********************************************************************/
119 void SSP_Init(LPC_SSP_TypeDef *SSPx, SSP_CFG_Type *SSP_ConfigStruct)
120 {
121  uint32_t tmp;
122 
123  CHECK_PARAM(PARAM_SSPx(SSPx));
124 
125  if(SSPx == LPC_SSP0) {
126  /* Set up clock and power for SSP0 module */
128  } else if(SSPx == LPC_SSP1) {
129  /* Set up clock and power for SSP1 module */
131  } else {
132  return;
133  }
134 
135  /* Configure SSP, interrupt is disable, LoopBack mode is disable,
136  * SSP is disable, Slave output is disable as default
137  */
138  tmp = ((SSP_ConfigStruct->CPHA) | (SSP_ConfigStruct->CPOL) \
139  | (SSP_ConfigStruct->FrameFormat) | (SSP_ConfigStruct->Databit))
140  & SSP_CR0_BITMASK;
141  // write back to SSP control register
142  SSPx->CR0 = tmp;
143 
144  tmp = SSP_ConfigStruct->Mode & SSP_CR1_BITMASK;
145  // Write back to CR1
146  SSPx->CR1 = tmp;
147 
148  // Set clock rate for SSP peripheral
149  setSSPclock(SSPx, SSP_ConfigStruct->ClockRate);
150 }
151 
152 /*********************************************************************/
160 void SSP_DeInit(LPC_SSP_TypeDef* SSPx)
161 {
162  CHECK_PARAM(PARAM_SSPx(SSPx));
163 
164  if (SSPx == LPC_SSP0){
165  /* Set up clock and power for SSP0 module */
167  } else if (SSPx == LPC_SSP1) {
168  /* Set up clock and power for SSP1 module */
170  }
171 }
172 
173 /*****************************************************************************/
184 uint8_t SSP_GetDataSize(LPC_SSP_TypeDef* SSPx)
185 {
186  CHECK_PARAM(PARAM_SSPx(SSPx));
187  return (SSPx->CR0 & (0xF));
188 }
189 
190 /*****************************************************************************/
202 void SSP_ConfigStructInit(SSP_CFG_Type *SSP_InitStruct)
203 {
204  SSP_InitStruct->CPHA = SSP_CPHA_FIRST;
205  SSP_InitStruct->CPOL = SSP_CPOL_HI;
206  SSP_InitStruct->ClockRate = 1000000;
207  SSP_InitStruct->Databit = SSP_DATABIT_8;
208  SSP_InitStruct->Mode = SSP_MASTER_MODE;
209  SSP_InitStruct->FrameFormat = SSP_FRAME_SPI;
210 }
211 
212 
213 /*********************************************************************/
221 void SSP_Cmd(LPC_SSP_TypeDef* SSPx, FunctionalState NewState)
222 {
223  CHECK_PARAM(PARAM_SSPx(SSPx));
225 
226  if (NewState == ENABLE)
227  {
228  SSPx->CR1 |= SSP_CR1_SSP_EN;
229  }
230  else
231  {
232  SSPx->CR1 &= (~SSP_CR1_SSP_EN) & SSP_CR1_BITMASK;
233  }
234 }
235 
236 /*********************************************************************/
246 void SSP_LoopBackCmd(LPC_SSP_TypeDef* SSPx, FunctionalState NewState)
247 {
248  CHECK_PARAM(PARAM_SSPx(SSPx));
250 
251  if (NewState == ENABLE)
252  {
253  SSPx->CR1 |= SSP_CR1_LBM_EN;
254  }
255  else
256  {
257  SSPx->CR1 &= (~SSP_CR1_LBM_EN) & SSP_CR1_BITMASK;
258  }
259 }
260 
261 /*********************************************************************/
275 {
276  CHECK_PARAM(PARAM_SSPx(SSPx));
278 
279  if (NewState == ENABLE)
280  {
281  SSPx->CR1 &= (~SSP_CR1_SO_DISABLE) & SSP_CR1_BITMASK;
282  }
283  else
284  {
285  SSPx->CR1 |= SSP_CR1_SO_DISABLE;
286  }
287 }
288 
289 
290 
291 /*********************************************************************/
300 void SSP_SendData(LPC_SSP_TypeDef* SSPx, uint16_t Data)
301 {
302  CHECK_PARAM(PARAM_SSPx(SSPx));
303 
304  SSPx->DR = SSP_DR_BITMASK(Data);
305 }
306 
307 
308 
309 /*********************************************************************/
316 uint16_t SSP_ReceiveData(LPC_SSP_TypeDef* SSPx)
317 {
318  CHECK_PARAM(PARAM_SSPx(SSPx));
319 
320  return ((uint16_t) (SSP_DR_BITMASK(SSPx->DR)));
321 }
322 
323 /*********************************************************************/
339 int32_t SSP_ReadWrite (LPC_SSP_TypeDef *SSPx, SSP_DATA_SETUP_Type *dataCfg, \
340  SSP_TRANSFER_Type xfType)
341 {
342  uint8_t *rdata8 = 0;
343  uint8_t *wdata8 = 0;
344  uint16_t *rdata16 = 0;
345  uint16_t *wdata16 = 0;
346  uint32_t stat;
347  uint32_t tmp;
348  int32_t dataword;
349 
350  dataCfg->rx_cnt = 0;
351  dataCfg->tx_cnt = 0;
352  dataCfg->status = 0;
353 
354 
355  /* Clear all remaining data in RX FIFO */
356  while (SSPx->SR & SSP_SR_RNE){
357  tmp = (uint32_t) SSP_ReceiveData(SSPx);
358  }
359 
360  // Clear status
361  SSPx->ICR = SSP_ICR_BITMASK;
362  if(SSP_GetDataSize(SSPx)>8)
363  dataword = 1;
364  else dataword = 0;
365 
366  // Polling mode ----------------------------------------------------------------------
367  if (xfType == SSP_TRANSFER_POLLING){
368  if (dataword == 0){
369  rdata8 = (uint8_t *)dataCfg->rx_data;
370  wdata8 = (uint8_t *)dataCfg->tx_data;
371  } else {
372  rdata16 = (uint16_t *)dataCfg->rx_data;
373  wdata16 = (uint16_t *)dataCfg->tx_data;
374  }
375  while ((dataCfg->tx_cnt != dataCfg->length) || (dataCfg->rx_cnt != dataCfg->length)){
376  if ((SSPx->SR & SSP_SR_TNF) && (dataCfg->tx_cnt != dataCfg->length)){
377  // Write data to buffer
378  if(dataCfg->tx_data == NULL){
379  if (dataword == 0){
380  SSP_SendData(SSPx, 0xFF);
381  dataCfg->tx_cnt++;
382  } else {
383  SSP_SendData(SSPx, 0xFFFF);
384  dataCfg->tx_cnt += 2;
385  }
386  } else {
387  if (dataword == 0){
388  SSP_SendData(SSPx, *wdata8);
389  wdata8++;
390  dataCfg->tx_cnt++;
391  } else {
392  SSP_SendData(SSPx, *wdata16);
393  wdata16++;
394  dataCfg->tx_cnt += 2;
395  }
396  }
397  }
398 
399  // Check overrun error
400  if ((stat = SSPx->RIS) & SSP_RIS_ROR){
401  // save status and return
402  dataCfg->status = stat | SSP_STAT_ERROR;
403  return (-1);
404  }
405 
406  // Check for any data available in RX FIFO
407  while ((SSPx->SR & SSP_SR_RNE) && (dataCfg->rx_cnt != dataCfg->length)){
408  // Read data from SSP data
409  tmp = SSP_ReceiveData(SSPx);
410 
411  // Store data to destination
412  if (dataCfg->rx_data != NULL)
413  {
414  if (dataword == 0){
415  *(rdata8) = (uint8_t) tmp;
416  rdata8++;
417  } else {
418  *(rdata16) = (uint16_t) tmp;
419  rdata16++;
420  }
421  }
422  // Increase counter
423  if (dataword == 0){
424  dataCfg->rx_cnt++;
425  } else {
426  dataCfg->rx_cnt += 2;
427  }
428  }
429  }
430 
431  // save status
432  dataCfg->status = SSP_STAT_DONE;
433 
434  if (dataCfg->tx_data != NULL){
435  return dataCfg->tx_cnt;
436  } else if (dataCfg->rx_data != NULL){
437  return dataCfg->rx_cnt;
438  } else {
439  return (0);
440  }
441  }
442 
443  // Interrupt mode ----------------------------------------------------------------------
444  else if (xfType == SSP_TRANSFER_INTERRUPT){
445 
446  while ((SSPx->SR & SSP_SR_TNF) && (dataCfg->tx_cnt != dataCfg->length)){
447  // Write data to buffer
448  if(dataCfg->tx_data == NULL){
449  if (dataword == 0){
450  SSP_SendData(SSPx, 0xFF);
451  dataCfg->tx_cnt++;
452  } else {
453  SSP_SendData(SSPx, 0xFFFF);
454  dataCfg->tx_cnt += 2;
455  }
456  } else {
457  if (dataword == 0){
458  SSP_SendData(SSPx, (*(uint8_t *)((uint32_t)dataCfg->tx_data + dataCfg->tx_cnt)));
459  dataCfg->tx_cnt++;
460  } else {
461  SSP_SendData(SSPx, (*(uint16_t *)((uint32_t)dataCfg->tx_data + dataCfg->tx_cnt)));
462  dataCfg->tx_cnt += 2;
463  }
464  }
465 
466  // Check error
467  if ((stat = SSPx->RIS) & SSP_RIS_ROR){
468  // save status and return
469  dataCfg->status = stat | SSP_STAT_ERROR;
470  return (-1);
471  }
472 
473  // Check for any data available in RX FIFO
474  while ((SSPx->SR & SSP_SR_RNE) && (dataCfg->rx_cnt != dataCfg->length)){
475  // Read data from SSP data
476  tmp = SSP_ReceiveData(SSPx);
477 
478  // Store data to destination
479  if (dataCfg->rx_data != NULL)
480  {
481  if (dataword == 0){
482  *(uint8_t *)((uint32_t)dataCfg->rx_data + dataCfg->rx_cnt) = (uint8_t) tmp;
483  } else {
484  *(uint16_t *)((uint32_t)dataCfg->rx_data + dataCfg->rx_cnt) = (uint16_t) tmp;
485  }
486  }
487  // Increase counter
488  if (dataword == 0){
489  dataCfg->rx_cnt++;
490  } else {
491  dataCfg->rx_cnt += 2;
492  }
493  }
494  }
495 
496  // If there more data to sent or receive
497  if ((dataCfg->rx_cnt != dataCfg->length) || (dataCfg->tx_cnt != dataCfg->length)){
498  // Enable all interrupt
499  SSPx->IMSC = SSP_IMSC_BITMASK;
500  } else {
501  // Save status
502  dataCfg->status = SSP_STAT_DONE;
503  }
504  return (0);
505  }
506 
507  return (-1);
508 }
509 
510 /*********************************************************************/
524 FlagStatus SSP_GetStatus(LPC_SSP_TypeDef* SSPx, uint32_t FlagType)
525 {
526  CHECK_PARAM(PARAM_SSPx(SSPx));
527  CHECK_PARAM(PARAM_SSP_STAT(FlagType));
528 
529  return ((SSPx->SR & FlagType) ? SET : RESET);
530 }
531 
532 /*********************************************************************/
548 void SSP_IntConfig(LPC_SSP_TypeDef *SSPx, uint32_t IntType, FunctionalState NewState)
549 {
550  CHECK_PARAM(PARAM_SSPx(SSPx));
551 
552  if (NewState == ENABLE)
553  {
554  SSPx->IMSC |= IntType;
555  }
556  else
557  {
558  SSPx->IMSC &= (~IntType) & SSP_IMSC_BITMASK;
559  }
560 }
561 
562 /*********************************************************************/
577 IntStatus SSP_GetRawIntStatus(LPC_SSP_TypeDef *SSPx, uint32_t RawIntType)
578 {
579  CHECK_PARAM(PARAM_SSPx(SSPx));
580  CHECK_PARAM(PARAM_SSP_INTSTAT_RAW(RawIntType));
581 
582  return ((SSPx->RIS & RawIntType) ? SET : RESET);
583 }
584 
585 /*********************************************************************/
593 {
594  CHECK_PARAM(PARAM_SSPx(SSPx));
595  return (SSPx->RIS);
596 }
597 
598 /*********************************************************************/
613 IntStatus SSP_GetIntStatus (LPC_SSP_TypeDef *SSPx, uint32_t IntType)
614 {
615  CHECK_PARAM(PARAM_SSPx(SSPx));
616  CHECK_PARAM(PARAM_SSP_INTSTAT(IntType));
617 
618  return ((SSPx->MIS & IntType) ? SET :RESET);
619 }
620 
621 /*********************************************************************/
633 void SSP_ClearIntPending(LPC_SSP_TypeDef *SSPx, uint32_t IntType)
634 {
635  CHECK_PARAM(PARAM_SSPx(SSPx));
636  CHECK_PARAM(PARAM_SSP_INTCLR(IntType));
637 
638  SSPx->ICR = IntType;
639 }
640 
641 /*********************************************************************/
655 void SSP_DMACmd(LPC_SSP_TypeDef *SSPx, uint32_t DMAMode, FunctionalState NewState)
656 {
657  CHECK_PARAM(PARAM_SSPx(SSPx));
658  CHECK_PARAM(PARAM_SSP_DMA(DMAMode));
660 
661  if (NewState == ENABLE)
662  {
663  SSPx->DMACR |= DMAMode;
664  }
665  else
666  {
667  SSPx->DMACR &= (~DMAMode) & SSP_DMA_BITMASK;
668  }
669 }
670 
675 #endif /* _SSP */
676 
681 /* --------------------------------- End Of File ------------------------------ */
682