Subversion Repositories Code-Repo

Rev

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

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