Subversion Repositories Code-Repo

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
199 Kevin 1
#include <xc.h>
2
#include <plib.h>
3
#include "defines.h"
4
#include "SPI1.h"
5
 
6
static SPI1_DATA *data_ptr;
7
static void (*callback_function)(void);
8
 
9
void SPI1_Init(SPI1_DATA *data) {
10
    data_ptr = data;
11
    data_ptr->outBufferInd = 0;
12
    data_ptr->outBufferLen = 0;
13
#ifndef SPI1_WRITE_ONLY
14
    data_ptr->inBufferInd = 0;
15
    data_ptr->inBufferLen = 0;
16
#endif
17
 
18
    INTDisableInterrupts();
19
 
20
    // Note: FIFO enhanced buffer depth is 4/8/16 for 32/16/8 bit widths
21
 
22
    // Alternative Configuration:
23
    // The third value is the SPI bitrate which is 1/2 the frequency of the
24
    //  desired clock frequency. Thus 40Mhz / (20Mhz / 2) = 4.
25
    // Note: SPI_OPEN_TBE_NOT_FULL should only be used at >10Mhz speeds
26
//    SpiChnOpen(SPI_CHANNEL1, SPI_OPEN_MSTEN | SPI_OPEN_ENHBUF | SPI_OPEN_TBE_NOT_FULL | SPI_OPEN_RBF_NOT_EMPTY, 4);
27
//    INTSetVectorPriority(INT_SPI_1_VECTOR, INT_PRIORITY_LEVEL_6);
28
//    INTSetVectorSubPriority(INT_SPI_1_VECTOR, INT_SUB_PRIORITY_LEVEL_1);
29
//    INTClearFlag(INT_SPI1E);
30
//    INTClearFlag(INT_SPI1TX);
31
//    INTClearFlag(INT_SPI1RX);
32
 
33
    // FSCK = FPB / (2 * (SPIxBRG + 1))
34
    IEC0CLR     = 0x03800000;   // Disable all SPI interrupts
35
    SPI1CON     = 0;            // Stops and resets the SPI1.
36
    int tmp     = SPI1BUF;      // Clears the receive buffer
37
    IFS0CLR     = 0x03800000;   // Clear any existing event
38
    IPC5CLR     = 0x1F000000;   // Clear the priority
39
    IPC5SET     = 0x19000000;   // Set IPL=6, Subpriority 1
40
    SPI1BRG     = 0x1;          // Use FPB/4 clock frequency
41
    SPI1STATCLR = 0x40;         // Clear the Overflow
42
#ifndef SPI1_WRITE_ONLY
43
    IEC0SET = 0x01800000;       // Enable RX and Error interrupts
44
#endif
45
    // Enhanced buffer, SPI on, 8 bits transfer, SMP=1, Master mode
46
    // SPIxTXIF set on buffer empty, SPIxRXIF set on buffer not empty
47
    SPI1CON     = 0x18225;
48
 
49
    INTEnableInterrupts();
50
}
51
 
52
#ifndef SPI1_WRITE_ONLY
53
int SPI1_Read_Buffer(unsigned char *array, unsigned int count) {
54
    if (count > SPI1_BUFFER_SIZE)
55
        return 0;
56
    if (data_ptr->inBufferLen == 0)
57
        return 0;
58
 
59
    // Save previous interrupt state
60
    int prev = IEC0 & 0x03800000;
61
     // Temporarily disable interrupts
62
    IEC0CLR = 0x03800000;
63
    int ret = data_ptr->inBufferLen;
64
    int i;
65
    for (i = 0; i < count; i++) {
66
        array[i] = data_ptr->inBuffer[i];
67
    }
68
    // Reset buffer pointers
69
    data_ptr->inBufferInd = 0;
70
    data_ptr->inBufferLen = 0;
71
    // Restore saved interrupt state
72
    IEC0SET = prev;
73
    // Return the number of valid bytes in the buffer
74
    return ret;
75
}
76
#endif
77
 
78
int SPI1_Write(unsigned char *array, unsigned int count, void (*callback)(void)) {
79
    callback_function = callback;
80
 
81
    if (count > SPI1_BUFFER_SIZE)
82
        return 0;
83
    if (data_ptr->outBufferLen != 0)
84
        return 0;
85
 
86
    data_ptr->outBufferLen = count;
87
    data_ptr->outBufferInd = count-1;
88
    int i;
89
    for (i = 0; i < count; i++) {
90
        data_ptr->outBuffer[i] = array[i];
91
    }
92
    IEC0SET = 0x02000000; // Enable TX interrupt
93
    return 1;
94
}
95
 
96
void __ISR(_SPI_1_VECTOR, ipl6) __SPI_1_Interrupt_Handler(void) {
97
#ifndef SPI1_WRITE_ONLY
98
    // Process SPI1 error flag
99
    if (IFS0bits.SPI1EIF) {
100
        // Clear the receive overflow bit if it is set
101
        if (SPI1STATbits.SPIROV) {
102
            SPI1STATbits.SPIROV = 0;
103
        }
104
        IFS0CLR = 0x00800000; // Clear the error flag
105
    }
106
 
107
    // Process SPI1 receive flag
108
    if (IFS0bits.SPI1RXIF) {
109
        int i;
110
        // Read the data received from the last transfer
111
        int rxBufferCount = SPI1STATbits.RXBUFELM;
112
        if (data_ptr->inBufferLen + rxBufferCount < SPI1_BUFFER_SIZE) {
113
            for (i = 0; i < rxBufferCount; i++) {
114
                data_ptr->inBuffer[data_ptr->inBufferInd] = SPI1BUF;
115
                data_ptr->inBufferInd++;
116
                data_ptr->inBufferLen++;
117
            }
118
        } else {
119
            // If buffer is full, discard data in enhanced buffer
120
            for (i = 0; i < rxBufferCount; i++) {
121
                int tmp = SPI1BUF;
122
            }
123
        }
124
        IFS0CLR = 0x01000000; // Clear the RX flag
125
    }
126
#endif
127
 
128
    // Process SPI1 transmit flag
129
    if (IFS0bits.SPI1TXIF) {
130
        int i;
131
        // Disable the transmit interrupt if all data has been sent
132
        if (data_ptr->outBufferLen == 0) {
133
            IEC0CLR=0x02000000;
134
            if (callback_function != NULL)
135
                (*callback_function)();
136
        } else {
137
            // Start transmitting the data in the buffer
138
            int txBufferFree = 16 - SPI1STATbits.TXBUFELM;
139
            if (data_ptr->outBufferLen > txBufferFree) {
140
                for (i = 0; i < txBufferFree; i++) {
141
                    SPI1BUF = data_ptr->outBuffer[data_ptr->outBufferInd];
142
                    data_ptr->outBufferInd--;
143
                }
144
                data_ptr->outBufferLen -= txBufferFree;
145
            } else {
146
                for (i = 0; i < data_ptr->outBufferLen; i++) {
147
                    SPI1BUF = data_ptr->outBuffer[data_ptr->outBufferInd];
148
                    data_ptr->outBufferInd--;
149
                }
150
                data_ptr->outBufferLen = 0;
151
            }
152
        }
153
        IFS0CLR = 0x02000000; // Clear the TX flag
154
    }
155
}