1 /******************************************************************************
2 *  Filename:       ssi.c
3 *  Revised:        2017-04-26 18:27:45 +0200 (Wed, 26 Apr 2017)
4 *  Revision:       48852
5 *
6 *  Description:    Driver for Synchronous Serial Interface
7 *
8 *  Copyright (c) 2015 - 2017, Texas Instruments Incorporated
9 *  All rights reserved.
10 *
11 *  Redistribution and use in source and binary forms, with or without
12 *  modification, are permitted provided that the following conditions are met:
13 *
14 *  1) Redistributions of source code must retain the above copyright notice,
15 *     this list of conditions and the following disclaimer.
16 *
17 *  2) Redistributions in binary form must reproduce the above copyright notice,
18 *     this list of conditions and the following disclaimer in the documentation
19 *     and/or other materials provided with the distribution.
20 *
21 *  3) Neither the name of the ORGANIZATION nor the names of its contributors may
22 *     be used to endorse or promote products derived from this software without
23 *     specific prior written permission.
24 *
25 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26 *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
29 *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 *  POSSIBILITY OF SUCH DAMAGE.
36 *
37 ******************************************************************************/
38 
39 #include "ssi.h"
40 
41 //*****************************************************************************
42 //
43 // Handle support for DriverLib in ROM:
44 // This section will undo prototype renaming made in the header file
45 //
46 //*****************************************************************************
47 #if !defined(DOXYGEN)
48     #undef  SSIConfigSetExpClk
49     #define SSIConfigSetExpClk              NOROM_SSIConfigSetExpClk
50     #undef  SSIDataPut
51     #define SSIDataPut                      NOROM_SSIDataPut
52     #undef  SSIDataPutNonBlocking
53     #define SSIDataPutNonBlocking           NOROM_SSIDataPutNonBlocking
54     #undef  SSIDataGet
55     #define SSIDataGet                      NOROM_SSIDataGet
56     #undef  SSIDataGetNonBlocking
57     #define SSIDataGetNonBlocking           NOROM_SSIDataGetNonBlocking
58     #undef  SSIIntRegister
59     #define SSIIntRegister                  NOROM_SSIIntRegister
60     #undef  SSIIntUnregister
61     #define SSIIntUnregister                NOROM_SSIIntUnregister
62 #endif
63 
64 //*****************************************************************************
65 //
66 // Configures the synchronous serial port
67 //
68 //*****************************************************************************
69 void
SSIConfigSetExpClk(uint32_t ui32Base,uint32_t ui32SSIClk,uint32_t ui32Protocol,uint32_t ui32Mode,uint32_t ui32BitRate,uint32_t ui32DataWidth)70 SSIConfigSetExpClk(uint32_t ui32Base, uint32_t ui32SSIClk,
71                    uint32_t ui32Protocol, uint32_t ui32Mode,
72                    uint32_t ui32BitRate, uint32_t ui32DataWidth)
73 {
74     uint32_t ui32MaxBitRate;
75     uint32_t ui32RegVal;
76     uint32_t ui32PreDiv;
77     uint32_t ui32SCR;
78     uint32_t ui32SPH_SPO;
79 
80     // Check the arguments.
81     ASSERT(SSIBaseValid(ui32Base));
82     ASSERT((ui32Protocol == SSI_FRF_MOTO_MODE_0) ||
83            (ui32Protocol == SSI_FRF_MOTO_MODE_1) ||
84            (ui32Protocol == SSI_FRF_MOTO_MODE_2) ||
85            (ui32Protocol == SSI_FRF_MOTO_MODE_3) ||
86            (ui32Protocol == SSI_FRF_TI) ||
87            (ui32Protocol == SSI_FRF_NMW));
88     ASSERT((ui32Mode == SSI_MODE_MASTER) ||
89            (ui32Mode == SSI_MODE_SLAVE) ||
90            (ui32Mode == SSI_MODE_SLAVE_OD));
91     ASSERT(((ui32Mode == SSI_MODE_MASTER) && (ui32BitRate <= (ui32SSIClk / 2))) ||
92            ((ui32Mode != SSI_MODE_MASTER) && (ui32BitRate <= (ui32SSIClk / 12))));
93     ASSERT((ui32SSIClk / ui32BitRate) <= (254 * 256));
94     ASSERT((ui32DataWidth >= 4) && (ui32DataWidth <= 16));
95 
96     // Set the mode.
97     ui32RegVal = (ui32Mode == SSI_MODE_SLAVE_OD) ? SSI_CR1_SOD : 0;
98     ui32RegVal |= (ui32Mode == SSI_MODE_MASTER) ? 0 : SSI_CR1_MS;
99     HWREG(ui32Base + SSI_O_CR1) = ui32RegVal;
100 
101     // Set the clock predivider.
102     ui32MaxBitRate = ui32SSIClk / ui32BitRate;
103     ui32PreDiv = 0;
104     do
105     {
106         ui32PreDiv += 2;
107         ui32SCR = (ui32MaxBitRate / ui32PreDiv) - 1;
108     }
109     while(ui32SCR > 255);
110     HWREG(ui32Base + SSI_O_CPSR) = ui32PreDiv;
111 
112     // Set protocol and clock rate.
113     ui32SPH_SPO = (ui32Protocol & 3) << 6;
114     ui32Protocol &= SSI_CR0_FRF_M;
115     ui32RegVal = (ui32SCR << 8) | ui32SPH_SPO | ui32Protocol | (ui32DataWidth - 1);
116     HWREG(ui32Base + SSI_O_CR0) = ui32RegVal;
117 }
118 
119 //*****************************************************************************
120 //
121 // Puts a data element into the SSI transmit FIFO
122 //
123 //*****************************************************************************
124 int32_t
SSIDataPutNonBlocking(uint32_t ui32Base,uint32_t ui32Data)125 SSIDataPutNonBlocking(uint32_t ui32Base, uint32_t ui32Data)
126 {
127     // Check the arguments.
128     ASSERT(SSIBaseValid(ui32Base));
129     ASSERT((ui32Data & (0xfffffffe << (HWREG(ui32Base + SSI_O_CR0) &
130                                        SSI_CR0_DSS_M))) == 0);
131 
132     // Check for space to write.
133     if(HWREG(ui32Base + SSI_O_SR) & SSI_SR_TNF)
134     {
135         HWREG(ui32Base + SSI_O_DR) = ui32Data;
136         return(1);
137     }
138     else
139     {
140         return(0);
141     }
142 }
143 
144 //*****************************************************************************
145 //
146 // Puts a data element into the SSI transmit FIFO
147 //
148 //*****************************************************************************
149 void
SSIDataPut(uint32_t ui32Base,uint32_t ui32Data)150 SSIDataPut(uint32_t ui32Base, uint32_t ui32Data)
151 {
152     // Check the arguments.
153     ASSERT(SSIBaseValid(ui32Base));
154     ASSERT((ui32Data & (0xfffffffe << (HWREG(ui32Base + SSI_O_CR0) &
155                                        SSI_CR0_DSS_M))) == 0);
156 
157     // Wait until there is space.
158     while(!(HWREG(ui32Base + SSI_O_SR) & SSI_SR_TNF))
159     {
160     }
161 
162     // Write the data to the SSI.
163     HWREG(ui32Base + SSI_O_DR) = ui32Data;
164 }
165 
166 //*****************************************************************************
167 //
168 // Gets a data element from the SSI receive FIFO
169 //
170 //*****************************************************************************
171 void
SSIDataGet(uint32_t ui32Base,uint32_t * pui32Data)172 SSIDataGet(uint32_t ui32Base, uint32_t *pui32Data)
173 {
174     // Check the arguments.
175     ASSERT(SSIBaseValid(ui32Base));
176 
177     // Wait until there is data to be read.
178     while(!(HWREG(ui32Base + SSI_O_SR) & SSI_SR_RNE))
179     {
180     }
181 
182     // Read data from SSI.
183     *pui32Data = HWREG(ui32Base + SSI_O_DR);
184 }
185 
186 //*****************************************************************************
187 //
188 // Gets a data element from the SSI receive FIFO
189 //
190 //*****************************************************************************
191 int32_t
SSIDataGetNonBlocking(uint32_t ui32Base,uint32_t * pui32Data)192 SSIDataGetNonBlocking(uint32_t ui32Base, uint32_t *pui32Data)
193 {
194     // Check the arguments.
195     ASSERT(SSIBaseValid(ui32Base));
196 
197     // Check for data to read.
198     if(HWREG(ui32Base + SSI_O_SR) & SSI_SR_RNE)
199     {
200         *pui32Data = HWREG(ui32Base + SSI_O_DR);
201         return(1);
202     }
203     else
204     {
205         return(0);
206     }
207 }
208 
209 //*****************************************************************************
210 //
211 // Registers an interrupt handler for the synchronous serial port
212 //
213 //*****************************************************************************
214 void
SSIIntRegister(uint32_t ui32Base,void (* pfnHandler)(void))215 SSIIntRegister(uint32_t ui32Base, void (*pfnHandler)(void))
216 {
217     uint32_t ui32Int;
218 
219     // Check the arguments.
220     ASSERT(SSIBaseValid(ui32Base));
221 
222     // Determine the interrupt number based on the SSI port.
223     ui32Int = (ui32Base == SSI0_BASE) ? INT_SSI0_COMB : INT_SSI1_COMB;
224 
225     // Register the interrupt handler.
226     IntRegister(ui32Int, pfnHandler);
227 
228     // Enable the synchronous serial port interrupt.
229     IntEnable(ui32Int);
230 }
231 
232 //*****************************************************************************
233 //
234 // Unregisters an interrupt handler for the synchronous serial port
235 //
236 //*****************************************************************************
237 void
SSIIntUnregister(uint32_t ui32Base)238 SSIIntUnregister(uint32_t ui32Base)
239 {
240     uint32_t ui32Int;
241 
242     // Check the arguments.
243     ASSERT(SSIBaseValid(ui32Base));
244 
245     // Determine the interrupt number based on the SSI port.
246     ui32Int = (ui32Base == SSI0_BASE) ? INT_SSI0_COMB : INT_SSI1_COMB;
247 
248     // Disable the interrupt.
249     IntDisable(ui32Int);
250 
251     // Unregister the interrupt handler.
252     IntUnregister(ui32Int);
253 }
254