ssp_prv.h
Go to the documentation of this file.
1 /*
2  * SocialLedge.com - Copyright (C) 2013
3  *
4  * This file is part of free software framework for embedded processors.
5  * You can use it and/or distribute it as long as this copyright header
6  * remains unmodified. The code is free for personal use and requires
7  * permission to use in a commercial product.
8  *
9  * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
10  * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
12  * I SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
13  * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
14  *
15  * You can reach the author of this software at :
16  * p r e e t . w i k i @ g m a i l . c o m
17  */
18 
23 #ifndef SSP_PRIVATE_H__
24 #define SSP_PRIVATE_H__
25 #ifdef __cplusplus
26 extern "C" {
27 #endif
28 
29 #include "LPC17xx.h"
30 #include "sys_config.h"
31 
32 
33 
39 static inline void ssp_set_max_clock(LPC_SSP_TypeDef *pSSP, unsigned int max_clock_mhz)
40 {
41  unsigned int divider = 2;
42  const unsigned int cpuClockMhz = sys_get_cpu_clock() / (1000 * 1000UL);
43 
44  // Keep scaling down divider until calculated is higher
45  // Example:
46  // 60, need 18
47  // 60/2 18 < 30 YES
48  // 60/4 18 < 15 NO
49  while(max_clock_mhz < (cpuClockMhz / divider) && divider <= 254)
50  {
51  divider += 2;
52  }
53 
54  pSSP->CPSR = divider;
55 }
56 
61 static inline void ssp_init(LPC_SSP_TypeDef *pSSP)
62 {
63  pSSP->CR0 = 7; // 8-bit mode
64  pSSP->CR1 = (1 << 1); // Enable SSP as Master
65  ssp_set_max_clock(pSSP, 1); // Set default speed
66 }
67 
68 
69 
75 static inline char ssp_exchange_byte(LPC_SSP_TypeDef *pSSP, char out)
76 {
77  pSSP->DR = out;
78  while(pSSP->SR & (1 << 4)); // Wait until SSP is busy
79  return pSSP->DR;
80 }
81 
86 static inline void ssp_exchange_data(LPC_SSP_TypeDef *pSSP, void* data, int len)
87 {
88  const uint32_t rx_fifo_half_full_bitmask = (1 << 2);
89  const uint32_t spi_busy_bitmask = (1 << 4);
90  const int spi_fifo_size = 8;
91  const int spi_half_fifo_size = spi_fifo_size / 2;
92 
93  char *dataOut = (char*)data;
94  char *dataIn = (char*)data;
95 
96  while (len > 0) {
97  if (len >= spi_fifo_size) {
98  pSSP->DR = *dataOut++; pSSP->DR = *dataOut++; pSSP->DR = *dataOut++; pSSP->DR = *dataOut++;
99  pSSP->DR = *dataOut++; pSSP->DR = *dataOut++; pSSP->DR = *dataOut++; pSSP->DR = *dataOut++;
100 
101  /* Pick up half the transmitted bytes as soon as RX fifo is half full */
102  len -= spi_fifo_size;
103  while (!(pSSP->RIS & rx_fifo_half_full_bitmask));
104  *dataIn++ = pSSP->DR; *dataIn++ = pSSP->DR; *dataIn++ = pSSP->DR; *dataIn++ = pSSP->DR;
105 
106  /* Pick up the rest of the half after SSP is fully done */
107  while(pSSP->SR & spi_busy_bitmask);
108  *dataIn++ = pSSP->DR; *dataIn++ = pSSP->DR; *dataIn++ = pSSP->DR; *dataIn++ = pSSP->DR;
109  }
110  else if (len >= spi_half_fifo_size) {
111  pSSP->DR = *dataOut++; pSSP->DR = *dataOut++; pSSP->DR = *dataOut++; pSSP->DR = *dataOut++;
112  len -= spi_half_fifo_size;
113  while(pSSP->SR & spi_busy_bitmask);
114  *dataIn++ = pSSP->DR; *dataIn++ = pSSP->DR; *dataIn++ = pSSP->DR; *dataIn++ = pSSP->DR;
115  }
116  else {
117  pSSP->DR = *dataOut++;
118  --len;
119  while(pSSP->SR & spi_busy_bitmask);
120  *dataIn++ = pSSP->DR;
121  }
122  }
123 }
124 
125 
126 
127 #ifdef __cplusplus
128 }
129 #endif
130 #endif /* SSP_PRIVATE_H__ */
unsigned int sys_get_cpu_clock()
Definition: sys_clock.cpp:377
__IO uint32_t CR0
Definition: LPC17xx.h:459
__IO uint32_t DR
Definition: LPC17xx.h:461
unsigned int unsigned int len
Definition: startup.cpp:197
__IO uint32_t CR1
Definition: LPC17xx.h:460
Definition: LPC17xx.h:457
__IO uint32_t CPSR
Definition: LPC17xx.h:463
This file provides the configurable parameters for your project.
CMSIS Cortex-M3 Core Peripheral Access Layer Header File for NXP LPC17xx Device Series.
__IO uint32_t RIS
Definition: LPC17xx.h:465
__I uint32_t SR
Definition: LPC17xx.h:462