Subversion Repositories Code-Repo

Rev

Rev 251 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
248 Kevin 1
//----------------------------------------------------------------------------
2
//  This file contains functions that allow the MSP430 device to access the
3
//  SPI interface.  There are multiple instances of each function; 
4
//  the one to be compiled is selected by the system variable
5
//  SPI_SER_INTF, defined in "hal_hardware_board.h".
6
//----------------------------------------------------------------------------
7
 
8
 
9
//----------------------------------------------------------------------------
10
//  void halSPISetup(void)
11
//
12
//  DESCRIPTION:
13
//  Configures the assigned interface to function as a SPI port and
14
//  initializes it.
15
//----------------------------------------------------------------------------
16
//  void halSPIWriteReg(char addr, char value)
17
//
18
//  DESCRIPTION:
19
//  Writes "value" to a single configuration register at address "addr".
20
//----------------------------------------------------------------------------
21
//  void halSPIWriteBurstReg(char addr, char *buffer, char count)
22
//
23
//  DESCRIPTION:
24
//  Writes values to multiple configuration registers, the first register being
25
//  at address "addr".  First data byte is at "buffer", and both addr and
26
//  buffer are incremented sequentially (within the CCxxxx and MSP430,
27
//  respectively) until "count" writes have been performed.
28
//----------------------------------------------------------------------------
29
//  char halSPIReadReg(char addr)
30
//
31
//  DESCRIPTION:
32
//  Reads a single configuration register at address "addr" and returns the
33
//  value read.
34
//----------------------------------------------------------------------------
35
//  void halSPIReadBurstReg(char addr, char *buffer, char count)
36
//
37
//  DESCRIPTION:
38
//  Reads multiple configuration registers, the first register being at address
39
//  "addr".  Values read are deposited sequentially starting at address
40
//  "buffer", until "count" registers have been read.
41
//----------------------------------------------------------------------------
42
//  char halSPIReadStatus(char addr)
43
//
44
//  DESCRIPTION:
45
//  Special read function for reading status registers.  Reads status register
46
//  at register "addr" and returns the value read.
47
//----------------------------------------------------------------------------
48
//  void halSPIStrobe(char strobe)
49
//
50
//  DESCRIPTION:
51
//  Special write function for writing to command strobe registers.  Writes
52
//  to the strobe at address "addr".
53
//----------------------------------------------------------------------------
54
 
55
/* ***********************************************************
56
* THIS PROGRAM IS PROVIDED "AS IS". TI MAKES NO WARRANTIES OR
57
* REPRESENTATIONS, EITHER EXPRESS, IMPLIED OR STATUTORY, 
58
* INCLUDING ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS 
59
* FOR A PARTICULAR PURPOSE, LACK OF VIRUSES, ACCURACY OR 
60
* COMPLETENESS OF RESPONSES, RESULTS AND LACK OF NEGLIGENCE. 
61
* TI DISCLAIMS ANY WARRANTY OF TITLE, QUIET ENJOYMENT, QUIET 
62
* POSSESSION, AND NON-INFRINGEMENT OF ANY THIRD PARTY 
63
* INTELLECTUAL PROPERTY RIGHTS WITH REGARD TO THE PROGRAM OR 
64
* YOUR USE OF THE PROGRAM.
65
*
66
* IN NO EVENT SHALL TI BE LIABLE FOR ANY SPECIAL, INCIDENTAL, 
67
* CONSEQUENTIAL OR INDIRECT DAMAGES, HOWEVER CAUSED, ON ANY 
68
* THEORY OF LIABILITY AND WHETHER OR NOT TI HAS BEEN ADVISED 
69
* OF THE POSSIBILITY OF SUCH DAMAGES, ARISING IN ANY WAY OUT 
70
* OF THIS AGREEMENT, THE PROGRAM, OR YOUR USE OF THE PROGRAM. 
71
* EXCLUDED DAMAGES INCLUDE, BUT ARE NOT LIMITED TO, COST OF 
72
* REMOVAL OR REINSTALLATION, COMPUTER TIME, LABOR COSTS, LOSS 
73
* OF GOODWILL, LOSS OF PROFITS, LOSS OF SAVINGS, OR LOSS OF 
74
* USE OR INTERRUPTION OF BUSINESS. IN NO EVENT WILL TI'S 
75
* AGGREGATE LIABILITY UNDER THIS AGREEMENT OR ARISING OUT OF 
76
* YOUR USE OF THE PROGRAM EXCEED FIVE HUNDRED DOLLARS 
77
* (U.S.$500).
78
*
79
* Unless otherwise stated, the Program written and copyrighted 
80
* by Texas Instruments is distributed as "freeware".  You may, 
81
* only under TI's copyright in the Program, use and modify the 
82
* Program without any charge or restriction.  You may 
83
* distribute to third parties, provided that you transfer a 
84
* copy of this license to the third party and the third party 
85
* agrees to these terms by its first use of the Program. You 
86
* must reproduce the copyright notice and any other legend of 
87
* ownership on each copy or partial copy, of the Program.
88
*
89
* You acknowledge and agree that the Program contains 
90
* copyrighted material, trade secrets and other TI proprietary 
91
* information and is protected by copyright laws, 
92
* international copyright treaties, and trade secret laws, as 
93
* well as other intellectual property laws.  To protect TI's 
94
* rights in the Program, you agree not to decompile, reverse 
95
* engineer, disassemble or otherwise translate any object code 
96
* versions of the Program to a human-readable form.  You agree 
97
* that in no event will you alter, remove or destroy any 
98
* copyright notice included in the Program.  TI reserves all 
99
* rights not specifically granted under this license. Except 
100
* as specifically provided herein, nothing in this agreement 
101
* shall be construed as conferring by implication, estoppel, 
102
* or otherwise, upon you, any license or other right under any 
103
* TI patents, copyrights or trade secrets.
104
*
105
* You may not use the Program in non-TI devices.
106
* ********************************************************* */
107
 
108
 
109
#ifndef _SPILIB_C
110
#define _SPILIB_C
111
//
112
//---------------------------------------------------------------
113
#include "hal_SPI.h"
114
#include "hal_hardware_board.h"
115
 
116
//#define withDMA
117
 
118
// SPI port functions
119
#if SPI_SER_INTF == SER_INTF_USART0
120
 
121
void halSPISetup(void)
122
{
123
    UCTL0 = CHAR + SYNC + MM + SWRST;         // 8-bit SPI Master **SWRST**
124
    UTCTL0 = CKPL + SSEL1 + SSEL0 + STC;      // SMCLK, 3-pin mode
125
    UBR00 = 0x02;                             // UCLK/2
126
    UBR10 = 0x00;                             // 0
127
    UMCTL0 = 0x00;                            // No modulation
128
    ME1 |= USPIE0;                            // Enable USART0 SPI mode
129
    UCTL0 &= ~SWRST;                          // Initialize USART state machine
130
}
131
 
132
#elif SPI_SER_INTF == SER_INTF_USART1
133
 
134
void halSPISetup(void)
135
{
136
    UCTL1 = CHAR + SYNC + MM + SWRST;         // 8-bit SPI Master **SWRST**
137
    UTCTL1 = CKPL + SSEL1 + SSEL0 + STC;      // SMCLK, 3-pin mode
138
    UBR01 = 0x02;                             // UCLK/2
139
    UBR11 = 0x00;                             // 0
140
    UMCTL1 = 0x00;                            // No modulation
141
    ME2 |= USPIE1;                            // Enable USART1 SPI mode
142
    UCTL1 &= ~SWRST;                          // Initialize USART state machine
143
}
144
 
145
#elif SPI_SER_INTF == SER_INTF_USCIA0
146
 
147
void halSPISetup(void)
148
{
149
    UCA0CTL0 = UCMST+UCCKPL+UCMSB+UCSYNC;     // 3-pin, 8-bit SPI master
150
    UCA0CTL1 = UCSSEL_2 + UCSWRST;            // SMCLK
151
    halSPISetSpeedLow();
152
    UCA0MCTL = 0;
153
    SPI_PxSEL |= SPI_UCLK+SPI_SOMI+SPI_SIMO;
154
	SPI_PxSEL2 |= SPI_UCLK+SPI_SOMI+SPI_SIMO;
155
	SPI_PxOUT |= SPI_SIMO + SPI_SOMI + SPI_UCLK;
156
	SPI_PxDIR |= SPI_SIMO + SPI_UCLK;
157
	SPI_PxDIR &= ~SPI_SOMI;
158
    UCA0CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine**
159
}
160
 
161
void halSPISetSpeedHigh(void) {
162
    UCA0BR0 = 4;    // CLK_FREQ = BRCLK / 4
163
    UCA0BR1 = 0;
164
}
165
 
166
void halSPISetSpeedLow(void) {
167
    UCA0BR0 = 32;   // CLK_FREQ = BRCLK / 32
168
    UCA0BR1 = 0;
169
}
170
 
171
#elif SPI_SER_INTF == SER_INTF_USCIA1
172
 
173
void halSPISetup(void)
174
{
175
    UCA1CTL0 = UCMST+UCCKPL+UCMSB+UCSYNC;     // 3-pin, 8-bit SPI master
176
    UCA1CTL1 = UCSSEL_2 + UCSWRST;            // SMCLK
177
    halSPISetSpeedLow();
178
    UCA1MCTL = 0;
179
    UCA1CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine**
180
}
181
 
182
void halSPISetSpeedHigh(void) {
183
    UCA1BR0 = 4;    // CLK_FREQ = BRCLK / 4
184
    UCA1BR1 = 0;
185
}
186
 
187
void halSPISetSpeedLow(void) {
188
    UCA1BR0 = 32;   // CLK_FREQ = BRCLK / 32
189
    UCA1BR1 = 0;
190
}
191
 
192
#elif SPI_SER_INTF == SER_INTF_USCIB0
193
 
194
void halSPISetup(void)
195
{
251 Kevin 196
    UCB0CTL0 = UCMSB+UCMST+UCMODE_0;			// 3-pin, 8-bit SPI master
197
    halSPISetPolarityPhase(0, 0);
248 Kevin 198
    UCB0CTL1 = UCSSEL_2+UCSWRST;				// SMCLK
199
    halSPISetSpeedLow();
200
    //UCB0MCTL = 0;
201
    SPI_PxSEL |= SPI_UCLK+SPI_SOMI+SPI_SIMO;
251 Kevin 202
	SPI_PxSEL2 |= SPI_UCLK+SPI_SOMI+SPI_SIMO;
248 Kevin 203
    UCB0CTL1 &= ~UCSWRST;						// **Initialize USCI state machine**
204
}
205
 
206
void halSPISetSpeedHigh(void) {
207
    UCB0BR0 = 4;    // CLK_FREQ = BRCLK / 4
208
    UCB0BR1 = 0;
209
}
210
 
211
void halSPISetSpeedLow(void) {
212
    UCB0BR0 = 32;   // CLK_FREQ = BRCLK / 32
213
    UCB0BR1 = 0;
214
}
215
 
251 Kevin 216
void halSPISetPolarityPhase(char polarity, char phase) {
217
	// Polarity 0 = inactive low, Polarity 1 = inactive high
218
	// Phase 0 = Capture on first edge, change on following edge
219
	// Phase 1 = Change on first edge, capture on following edge
220
	// Note: Phase is inverted on MSP430!
221
	UCB0CTL0 &= ~(UCCKPH + UCCKPL);
222
	if (polarity == 0 && phase == 0) {
223
		UCB0CTL0 |= UCCKPH;
224
	} else if (polarity == 1 && phase == 0) {
225
		UCB0CTL0 |= UCCKPH + UCCKPL;
226
	} else if (polarity == 1 && phase == 1) {
227
		UCB0CTL0 |= UCCKPL;
228
	}
229
}
230
 
248 Kevin 231
#elif SPI_SER_INTF == SER_INTF_USCIB1
232
 
233
void halSPISetup(void)
234
{
235
    UCB1CTL0 = UCMST+UCCKPL+UCMSB+UCSYNC;     // 3-pin, 8-bit SPI master
236
    UCB1CTL1 = UCSSEL_2+UCSWRST;              // SMCLK
237
    halSPISetSpeedLow();
238
    UCB1MCTL = 0;
239
    UCB1CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine**
240
}
241
 
242
void halSPISetSpeedHigh(void) {
243
    UCB1BR0 = 4;    // CLK_FREQ = BRCLK / 4
244
    UCB1BR1 = 0;
245
}
246
 
247
void halSPISetSpeedLow(void) {
248
    UCB1BR0 = 32;   // CLK_FREQ = BRCLK / 32
249
    UCB1BR1 = 0;
250
}
251
 
252
#elif SPI_SER_INTF == SER_INTF_USI
253
 
254
void halSPISetup(void)
255
{
256
    USICTL0 = USIPE7+USIPE6+USIPE5+USIMST+USIGE+USIOE+USISWRST; // Port, SPI master
257
    USICKCTL = USISSEL_2;                     // SCLK = SMCLK
258
    USICTL0 &= ~USISWRST;                     // USI released for operation
259
 
260
//  USISRL = 0x00;                            // Ensure SDO low instead of high,
261
//  USICNT = 1;                               // to avoid conflict with CCxxxx
262
}
263
 
264
void halSPISetSpeedHigh(void) {
265
    USICKCTL = (USICKCTL & 0x1F) | USIDIV_2;    // CLK_FREQ = BRCLK / 4
266
}
267
 
268
void halSPISetSpeedLow(void) {
269
    USICKCTL = (USICKCTL & 0x1F) | USIDIV_5;    // CLK_FREQ = BRCLK / 32
270
}
271
 
272
#elif SPI_SER_INTF == SER_INTF_BITBANG
273
 
274
void spi_bitbang_out(unsigned char);
275
unsigned char spi_bitbang_in();
276
unsigned char spi_bitbang_in_data;
277
 
278
void halSPISetup(void)
279
{
280
}
281
 
282
// Output eight-bit value using selected bit-bang pins
283
void spi_bitbang_out(unsigned char value)
284
{
285
    char x;
286
 
287
    for(x=8;x>0;x--)
288
    {
289
 
290
        if(value & 0x80)                        // If bit is high...
291
            MMC_PxOUT |= MMC_SIMO;// Set SIMO high...
292
        else
293
            MMC_PxOUT &= ~MMC_SIMO;//Set SIMO low...
294
        value = value << 1;                     // Rotate bits
295
 
296
        MMC_PxOUT &= ~MMC_UCLK; // Set clock low
297
        MMC_PxOUT |= MMC_UCLK;  // Set clock high
298
    }
299
}
300
 
301
// Input eight-bit value using selected bit-bang pins
302
unsigned char spi_bitbang_in()
303
{
304
    char x=0;
305
    int y;
306
 
307
    for(y=8;y>0;y--)
308
    {
309
        MMC_PxOUT &= ~MMC_UCLK; // Set clock low
310
        MMC_PxOUT |= MMC_UCLK;  // Set clock high
311
 
312
        x = x << 1;                             // Rotate bits
313
        if(MMC_PxIN & MMC_SOMI)                 // If bit is high...
314
            x |= 0x01;                            // input bit high
315
    }
316
    spi_bitbang_in_data = x;
317
    return(x);
318
}
319
// Input eight-bit value using selected bit-bang pins
320
unsigned char spi_bitbang_inout(unsigned char value)
321
{
322
    char x=0;
323
    int y;
324
 
325
    for(y=8;y>0;y--)
326
    {
327
        if(value & 0x80)                        // If bit is high...
328
            MMC_PxOUT |= MMC_SIMO;// Set SIMO high...
329
        else
330
            MMC_PxOUT &= ~MMC_SIMO;//Set SIMO low...
331
        value = value << 1;                     // Rotate bits
332
 
333
        MMC_PxOUT &= ~MMC_UCLK; // Set clock low
334
        MMC_PxOUT |= MMC_UCLK;  // Set clock high
335
 
336
        x = x << 1;                             // Rotate bits
337
        if(MMC_PxIN & MMC_SOMI)                 // If bit is high...
338
            x |= 0x01;                            // input bit high
339
    }
340
    spi_bitbang_in_data = x;
341
    return(x);
342
}
343
#endif
344
 
345
 
346
//Send one byte via SPI
347
unsigned char spiSendByte(const unsigned char data)
348
{
349
    while (halSPITXREADY == 0); // wait while not ready for TX
350
    halSPI_SEND(data); // write
351
    while (halSPIRXREADY == 0); // wait for RX buffer (full)
352
    return (halSPIRXBUF);
353
}
354
 
355
 
356
//Read a frame of bytes via SPI
357
unsigned char spiReadFrame(unsigned char* pBuffer, unsigned int size)
358
{
359
#ifndef withDMA
360
    unsigned long i = 0;
361
    // clock the actual data transfer and receive the bytes; spi_read automatically finds the Data Block
362
    for (i = 0; i < size; i++){
363
        while (halSPITXREADY == 0);   // wait while not ready for TX
364
        halSPI_SEND(DUMMY_CHAR);     // dummy write
365
        while (halSPIRXREADY == 0);   // wait for RX buffer (full)
366
        pBuffer[i] = halSPIRXBUF;
367
    }
368
#else
369
                U1IFG &= ~(URXIFG1 + URXIFG1);      /* clear flags */
370
                /* Get the block */
371
                /* DMA trigger is UART1 receive for both DMA0 and DMA1 */
372
                DMACTL0 &= ~(DMA0TSEL_15 | DMA1TSEL_15);
373
                DMACTL0 |= (DMA0TSEL_9 | DMA1TSEL_9);
374
                /* Source DMA address: receive register.  */
375
                DMA0SA = U1RXBUF_;
376
                /* Destination DMA address: the user data buffer. */
377
                DMA0DA = (unsigned short)pBuffer;
378
                /* The size of the block to be transferred */
379
                DMA0SZ = size;
380
                /* Configure the DMA transfer*/
381
                DMA0CTL =
382
                    DMAIE   |                         /* Enable interrupt */
383
                    DMADT_0 |                         /* Single transfer mode */
384
                    DMASBDB |                         /* Byte mode */
385
                    DMAEN |                           /* Enable DMA */
386
                    DMADSTINCR1 | DMADSTINCR0;        /* Increment the destination address */
387
 
388
                /* We depend on the DMA priorities here.  Both triggers occur at
389
                     the same time, since the source is identical.  DMA0 is handled
390
                     first, and retrieves the byte.  DMA1 is triggered next, and
391
                     sends the next byte. */
392
                /* Source DMA address: constant 0xFF (don't increment)*/
393
                DMA1SA = U1TXBUF_;
394
                /* Destination DMA address: the transmit buffer. */
395
                DMA1DA = U1TXBUF_;
396
                /* Increment the destination address */
397
                /* The size of the block to be transferred */
398
                DMA1SZ = count-1;
399
                /* Configure the DMA transfer*/
400
                DMA1CTL =
401
                    DMADT_0 |                         /* Single transfer mode */
402
                    DMASBDB |                         /* Byte mode */
403
                    DMAEN;                            /* Enable DMA */
404
 
405
                /* Kick off the transfer by sending the first byte */
406
                halMMC_SEND(0xFF);
407
                _EINT(); LPM0;  // wait till done
408
#endif
409
    return(0);
410
}
411
 
412
 
413
//Send a frame of bytes via SPI
414
unsigned char spiSendFrame(unsigned char* pBuffer, unsigned int size)
415
{
416
#ifndef withDMA
417
    unsigned long i = 0;
418
    // clock the actual data transfer and receive the bytes; spi_read automatically finds the Data Block
419
    for (i = 0; i < size; i++){
420
        while (halSPITXREADY ==0);   // wait while not ready for TX
421
        halSPI_SEND(pBuffer[i]);     // write
422
        while (halSPIRXREADY ==0);  // wait for RX buffer (full)
423
        pBuffer[i] = halSPIRXBUF;
424
    }
425
#else
426
            /* Get the block */
427
            /* DMA trigger is UART send */
428
            DMACTL0 &= ~(DMA0TSEL_15);
429
            DMACTL0 |= (DMA0TSEL_9);
430
            /* Source DMA address: the data buffer.  */
431
            DMA0SA = (unsigned short)pBuffer;
432
            /* Destination DMA address: the UART send register. */
433
            DMA0DA = U1TXBUF_;
434
            /* The size of the block to be transferred */
435
            DMA0SZ = count;
436
            /* Configure the DMA transfer*/
437
            DMA0CTL =
438
                DMAREQ  |                           /* start transfer */
439
                DMADT_0 |                           /* Single transfer mode */
440
                DMASBDB |                           /* Byte mode */
441
                DMAEN |                             /* Enable DMA */
442
                DMASRCINCR1 | DMASRCINCR0;          /* Increment the source address */
443
#endif
444
    return(0);
445
}
446
 
447
 
448
#ifdef withDMA
449
#ifdef __IAR_SYSTEMS_ICC__
450
#if __VER__ < 200
451
interrupt[DACDMA_VECTOR] void DMA_isr(void)
452
#else
453
#pragma vector = DACDMA_VECTOR
454
__interrupt void DMA_isr(void)
455
#endif
456
#endif
457
 
458
#ifdef __CROSSWORKS__
459
void DMA_isr(void)   __interrupt[DACDMA_VECTOR]
460
#endif
461
 
462
#ifdef __TI_COMPILER_VERSION__
463
__interrupt void DMA_isr(void);
464
DMA_ISR(DMA_isr)
465
__interrupt void DMA_isr(void)
466
#endif
467
{
468
    DMA0CTL &= ~(DMAIFG);
469
    LPM3_EXIT;
470
}
471
#endif
472
 
473
//---------------------------------------------------------------------
474
#endif /* _SPILIB_C */