Subversion Repositories Code-Repo

Rev

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

Rev Author Line No. Line
226 Kevin 1
#include <xc.h>
2
#include <plib.h>
3
#include "defines.h"
4
#include "SPI4.h"
5
 
6
static SPI4_DATA *spi_data_ptr;
7
 
8
void SPI4_Init(SPI4_DATA *data) {
9
    spi_data_ptr = data;
10
    spi_data_ptr->buffer_out_ind = 0;
11
    spi_data_ptr->buffer_out_len = 0;
12
    spi_data_ptr->buffer_in_ind = 0;
13
    spi_data_ptr->buffer_in_len = 0;
14
    spi_data_ptr->write_blank = 0;
15
 
16
    INTDisableInterrupts();
17
 
18
    // Note: FIFO enhanced buffer depth is 4/8/16 for 32/16/8 bit widths
19
 
20
    // FSCK = FPB / (2 * (SPIxBRG + 1))
21
    IEC1CLR     = 0x00000700;   // Disable all SPI interrupts
22
    SPI4CON     = 0;            // Stops and resets the SPI4.
23
    int tmp     = SPI4BUF;      // Clears the receive buffer
24
    IFS1CLR     = 0x00000700;   // Clear any existing event
25
    IPC8CLR     = 0x0000001F;   // Clear the priority
26
    IPC8SET     = 0x0000001A;   // Set IPL=6, Subpriority 2
27
    SPI4BRG     = 0x4;          // Use FPB/10 clock frequency
28
    SPI4STATCLR = 0x40;         // Clear the Overflow
29
    IEC1SET = 0x00000300;       // Enable RX and Error interrupts
30
 
31
    // Enhanced buffer, SPI on, 8 bits transfer, SMP=1, Master mode
32
    // SPIxTXIF set on buffer empty, SPIxRXIF set on buffer not empty
33
    SPI4CON     = 0x18225;
34
 
35
    INTEnableInterrupts();
36
}
37
 
38
int SPI4_Read(int length, void (*rx_callback)(char, char *)) {
39
    spi_data_ptr->rx_callback = rx_callback;
40
 
41
    // Ensure that the receiving buffer is large enough
42
    if (length > SPI4_BUFFER_IN_SIZE)
43
        return 0;
44
 
45
    // Ensure that no previous transactions are in progress
46
    if (spi_data_ptr->buffer_in_len != 0)
47
        return 0;
48
 
49
    spi_data_ptr->write_blank = 1;
50
    spi_data_ptr->buffer_in_len = length;
51
    spi_data_ptr->buffer_in_ind = 0;
52
 
53
    SPI4_Write(NULL, length, NULL);
54
    return 1;
55
}
56
 
57
int SPI4_Write(char *array, int length, void (*tx_callback)(void)) {
58
    spi_data_ptr->tx_callback = tx_callback;
59
 
60
    // We only care about the transmit length if we are sending data
61
    if (length > SPI4_BUFFER_OUT_SIZE && !spi_data_ptr->write_blank)
62
        return 0;
63
 
64
    // Ensure that no previous transactions are in progress
65
    if (spi_data_ptr->buffer_out_len != 0)
66
        return 0;
67
 
68
    // Put the data to send into the outbound buffer
69
    spi_data_ptr->buffer_out_len = length;
70
    spi_data_ptr->buffer_out_ind = 0;
71
 
72
    // Copy only if we are actually going to transmit data
73
    if (!spi_data_ptr->write_blank) {
74
        int i;
75
        for (i = 0; i < length; i++) {
76
            spi_data_ptr->buffer_out[i] = array[i];
77
        }
78
    }
79
    IEC1SET = 0x00000400; // Enable TX interrupt
80
    return 1;
81
}
82
 
83
void __ISR(_SPI_4_VECTOR, ipl6) __SPI_4_Interrupt_Handler(void) {
84
    // Process SPI4 error flag
85
    if (IFS1bits.SPI4EIF) {
86
        // Clear the receive overflow bit if it is set
87
        if (SPI4STATbits.SPIROV) {
88
            SPI4STATbits.SPIROV = 0;
89
        }
90
        IFS1CLR = 0x00000100; // Clear the error flag
91
    }
92
 
93
    // Process SPI4 receive flag
94
    if (IFS1bits.SPI4RXIF) {
95
        int i;
96
        // Read the data received from the last transfer
97
        int rxBufferCount = SPI4STATbits.RXBUFELM;
98
        for (i = 0; i < rxBufferCount; i++) {
99
            char c = SPI4BUF;
100
            // Put the received data into the buffer
101
            if (spi_data_ptr->buffer_in_len != 0) {
102
                spi_data_ptr->buffer_in[spi_data_ptr->buffer_in_ind] = c;
103
                spi_data_ptr->buffer_in_ind++;
104
                // If done acquiring requested length, reset
105
                if (spi_data_ptr->buffer_in_ind == spi_data_ptr->buffer_in_len) {
106
                    // Call the RX callback function on the received data
107
                    if (spi_data_ptr->rx_callback != NULL)
108
                        (*spi_data_ptr->rx_callback)(spi_data_ptr->buffer_in_len, spi_data_ptr->buffer_in);
109
                    spi_data_ptr->buffer_in_len = 0;
110
                }
111
            }
112
        }
113
        IFS1CLR = 0x00000200; // Clear the RX flag
114
    }
115
 
116
    // Process SPI4 transmit flag
117
    if (IFS1bits.SPI4TXIF && IEC1bits.SPI4TXIE) {
118
        int i;
119
        // Disable the transmit interrupt if all data has been sent
120
        if (spi_data_ptr->buffer_out_len == 0) {
121
            IEC1CLR=0x00000400;
122
            spi_data_ptr->write_blank = 0;
123
            // Call the TX callback function at end of transmission
124
            if (spi_data_ptr->tx_callback != NULL)
125
                (*spi_data_ptr->tx_callback)();
126
        } else {
127
            // Start transmitting the data in the buffer
128
            int txBufferFree = 16 - SPI4STATbits.TXBUFELM;
129
            if (spi_data_ptr->buffer_out_len > txBufferFree) {
130
                for (i = 0; i < txBufferFree; i++) {
131
                    if (spi_data_ptr->write_blank) {
132
                        SPI4BUF = 0x00;
133
                    } else {
134
                        SPI4BUF = spi_data_ptr->buffer_out[spi_data_ptr->buffer_out_ind];
135
                        spi_data_ptr->buffer_out_ind++;
136
                    }
137
                }
138
                spi_data_ptr->buffer_out_len -= txBufferFree;
139
            } else {
140
                for (i = 0; i < spi_data_ptr->buffer_out_len; i++) {
141
                    if (spi_data_ptr->write_blank) {
142
                        SPI4BUF = 0x00;
143
                    } else {
144
                        SPI4BUF = spi_data_ptr->buffer_out[spi_data_ptr->buffer_out_ind];
145
                        spi_data_ptr->buffer_out_ind++;
146
                    }
147
                }
148
                spi_data_ptr->buffer_out_len = 0;
149
            }
150
        }
151
        IFS1CLR = 0x00000400; // Clear the TX flag
152
    }
153
}