Subversion Repositories Code-Repo

Rev

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

Rev Author Line No. Line
199 Kevin 1
#include "defines.h"
2
#include "SPI1.h"
3
 
201 Kevin 4
static SPI1_DATA *spi_data_ptr;
199 Kevin 5
 
231 Kevin 6
void SPI1_Init(SPI1_DATA *data, void (*rx_callback)(uint8_t)) {
201 Kevin 7
    spi_data_ptr = data;
212 Kevin 8
    spi_data_ptr->buffer_out_ind = 0;
9
    spi_data_ptr->buffer_out_len = 0;
10
    spi_data_ptr->rx_callback = rx_callback;
199 Kevin 11
 
12
    INTDisableInterrupts();
13
 
14
    // Note: FIFO enhanced buffer depth is 4/8/16 for 32/16/8 bit widths
15
 
16
    // Alternative Configuration:
17
    // The third value is the SPI bitrate which is 1/2 the frequency of the
18
    //  desired clock frequency. Thus 40Mhz / (20Mhz / 2) = 4.
19
    // Note: SPI_OPEN_TBE_NOT_FULL should only be used at >10Mhz speeds
20
//    SpiChnOpen(SPI_CHANNEL1, SPI_OPEN_MSTEN | SPI_OPEN_ENHBUF | SPI_OPEN_TBE_NOT_FULL | SPI_OPEN_RBF_NOT_EMPTY, 4);
21
//    INTSetVectorPriority(INT_SPI_1_VECTOR, INT_PRIORITY_LEVEL_6);
22
//    INTSetVectorSubPriority(INT_SPI_1_VECTOR, INT_SUB_PRIORITY_LEVEL_1);
23
//    INTClearFlag(INT_SPI1E);
24
//    INTClearFlag(INT_SPI1TX);
25
//    INTClearFlag(INT_SPI1RX);
26
 
27
    // FSCK = FPB / (2 * (SPIxBRG + 1))
28
    IEC0CLR     = 0x03800000;   // Disable all SPI interrupts
29
    SPI1CON     = 0;            // Stops and resets the SPI1.
231 Kevin 30
    uint32_t tmp     = SPI1BUF;      // Clears the receive buffer
199 Kevin 31
    IFS0CLR     = 0x03800000;   // Clear any existing event
32
    IPC5CLR     = 0x1F000000;   // Clear the priority
33
    IPC5SET     = 0x19000000;   // Set IPL=6, Subpriority 1
34
    SPI1BRG     = 0x1;          // Use FPB/4 clock frequency
35
    SPI1STATCLR = 0x40;         // Clear the Overflow
212 Kevin 36
#ifndef SPI_WRITE_ONLY
199 Kevin 37
    IEC0SET = 0x01800000;       // Enable RX and Error interrupts
38
#endif
39
    // Enhanced buffer, SPI on, 8 bits transfer, SMP=1, Master mode
40
    // SPIxTXIF set on buffer empty, SPIxRXIF set on buffer not empty
41
    SPI1CON     = 0x18225;
42
 
43
    INTEnableInterrupts();
44
}
45
 
231 Kevin 46
uint8_t SPI1_Write(uint8_t *array, uint32_t length, void (*tx_callback)(void)) {
212 Kevin 47
    spi_data_ptr->tx_callback = tx_callback;
199 Kevin 48
 
226 Kevin 49
    if (length > SPI1_BUFFER_OUT_SIZE)
199 Kevin 50
        return 0;
212 Kevin 51
    if (spi_data_ptr->buffer_out_len != 0)
199 Kevin 52
        return 0;
53
 
212 Kevin 54
    // Put the data to send into the outbound buffer
226 Kevin 55
    spi_data_ptr->buffer_out_len = length;
56
    spi_data_ptr->buffer_out_ind = length-1;
231 Kevin 57
    int32_t i;
226 Kevin 58
    for (i = 0; i < length; i++) {
212 Kevin 59
        spi_data_ptr->buffer_out[i] = array[i];
199 Kevin 60
    }
61
    IEC0SET = 0x02000000; // Enable TX interrupt
62
    return 1;
63
}
64
 
65
void __ISR(_SPI_1_VECTOR, ipl6) __SPI_1_Interrupt_Handler(void) {
212 Kevin 66
#ifndef SPI_WRITE_ONLY
199 Kevin 67
    // Process SPI1 error flag
68
    if (IFS0bits.SPI1EIF) {
69
        // Clear the receive overflow bit if it is set
70
        if (SPI1STATbits.SPIROV) {
71
            SPI1STATbits.SPIROV = 0;
72
        }
73
        IFS0CLR = 0x00800000; // Clear the error flag
74
    }
75
 
76
    // Process SPI1 receive flag
77
    if (IFS0bits.SPI1RXIF) {
231 Kevin 78
        int32_t i;
199 Kevin 79
        // Read the data received from the last transfer
231 Kevin 80
        int32_t rxBufferCount = SPI1STATbits.RXBUFELM;
212 Kevin 81
        for (i = 0; i < rxBufferCount; i++) {
231 Kevin 82
            int8_t c = SPI1BUF;
212 Kevin 83
            // Call the RX callback function on the received data
84
            if (spi_data_ptr->rx_callback != NULL)
85
                (*spi_data_ptr->rx_callback)(c);
199 Kevin 86
        }
87
        IFS0CLR = 0x01000000; // Clear the RX flag
88
    }
89
#endif
90
 
91
    // Process SPI1 transmit flag
215 Kevin 92
    if (IFS0bits.SPI1TXIF && IEC0bits.SPI1TXIE) {
231 Kevin 93
        int32_t i;
199 Kevin 94
        // Disable the transmit interrupt if all data has been sent
212 Kevin 95
        if (spi_data_ptr->buffer_out_len == 0) {
199 Kevin 96
            IEC0CLR=0x02000000;
212 Kevin 97
            if (spi_data_ptr->tx_callback != NULL)
98
                (*spi_data_ptr->tx_callback)();
199 Kevin 99
        } else {
100
            // Start transmitting the data in the buffer
231 Kevin 101
            int32_t txBufferFree = 16 - SPI1STATbits.TXBUFELM;
212 Kevin 102
            if (spi_data_ptr->buffer_out_len > txBufferFree) {
199 Kevin 103
                for (i = 0; i < txBufferFree; i++) {
212 Kevin 104
                    SPI1BUF = spi_data_ptr->buffer_out[spi_data_ptr->buffer_out_ind];
105
                    spi_data_ptr->buffer_out_ind--;
199 Kevin 106
                }
212 Kevin 107
                spi_data_ptr->buffer_out_len -= txBufferFree;
199 Kevin 108
            } else {
212 Kevin 109
                for (i = 0; i < spi_data_ptr->buffer_out_len; i++) {
110
                    SPI1BUF = spi_data_ptr->buffer_out[spi_data_ptr->buffer_out_ind];
111
                    spi_data_ptr->buffer_out_ind--;
199 Kevin 112
                }
212 Kevin 113
                spi_data_ptr->buffer_out_len = 0;
199 Kevin 114
            }
115
        }
116
        IFS0CLR = 0x02000000; // Clear the TX flag
117
    }
118
}