Subversion Repositories Code-Repo

Rev

Rev 122 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

#include "maindefs.h"
#include "spi.h"

static SPI_DATA spi_data;

void SPI2_Init(unsigned char speed) {
    // Set up SPI2 with specified pins
    RPINR22 = 7; // SPI2 CLK Input  (Pin RB4)
    RPOR7 = 11; // SPI2 CLK Output (Pin RB4)
#ifndef SPI2_WRITE_ONLY
    RPINR21 = 6; // SPI2 Data Input (Pin RB3)
#endif
    RPOR5 = 10; // SPI2 Data Output   (MOSI) (Pin RB2)

    TRISBbits.TRISB4 = 0; // SPI2 clock pin       (Pin RB4)
#ifndef SPI2_WRITE_ONLY
    TRISBbits.TRISB3 = 1; // SPI2 data in pin     (Pin RB3)(MISO)
#endif
    TRISBbits.TRISB2 = 0; // SPI2 data out pin    (Pin RB2)(MOSI)

    TRISBbits.TRISB7 = 0; // SPI2 slave select    (Pin RB7)
    LATBbits.LATB7 = 1; // SPI2 SS high (Idle)

    TRISBbits.TRISB6 = 0; // SPI2 reset   (Pin RB6)
    LATBbits.LATB6 = 1; // SPI2 reset active low

    TRISBbits.TRISB5 = 0; // SPI2 D/C select (Pin RB5)
    LATBbits.LATB5 = 0;

    SSP2STATbits.SMP = 0; // Input is sampled in the middle of data output time
    SSP2STATbits.CKE = 0; // Transmit occurs on transition from Idle to active clock state

    if (speed == SPI2_FOSC_4)
        SSP2CON1bits.SSPM = 0b0000; // Clock = FOSC/4
    else if (speed == SPI2_FOSC_8)
        SSP2CON1bits.SSPM = 0b1010; // Clock = FOSC/8
    else if (speed == SPI2_FOSC_16)
        SSP2CON1bits.SSPM = 0b0001; // Clock = FOSC/16
    else
        SSP2CON1bits.SSPM = 0b0010; // Clock = FOSC/64

    SSP2CON1bits.CKP = 1; // Idle state for clock is a high level
    SSP2CON1bits.SSPEN = 1; // Enable MSSP module

#ifdef SPI2_USE_INTERRUPT
    PIE3bits.SSP2IE = 1; // Enable MSSP2 interrupt
#else
    PIE3bits.SSP2IE = 0;
#endif

    spi_data.buffer_in_len = 0;
    spi_data.buffer_in_read_ind = 0;
    spi_data.buffer_in_write_ind = 0;
    spi_data.buffer_out_ind = 0;
    spi_data.buffer_out_len = 0;
}

void SPI2_Recv_Interrupt_Handler() {
    unsigned char c;

    if (SSP2STATbits.BF) { // Check if data receive flag is set
        if (spi_data.buffer_in_len == MAXSPIBUF - 1) {
            DBG_PRINT_SPI("SPI2: buffer overflow\r\n");
            c = SSP2BUF; // Read SSP2BUF to clear it
        } else {
            // Save received data into buffer
            spi_data.buffer_in[spi_data.buffer_in_write_ind] = SSP2BUF;
            if (spi_data.buffer_in_write_ind == MAXSPIBUF - 1) {
                spi_data.buffer_in_write_ind = 0;
            } else {
                spi_data.buffer_in_write_ind++;
            }
            spi_data.buffer_in_len++;

            // Put next byte in SSP2BUF for transmit
            if (spi_data.buffer_out_ind != spi_data.buffer_out_len) {
                SSP2BUF = spi_data.buffer_out[spi_data.buffer_out_ind];
                spi_data.buffer_out_ind++;
            } else {
                LATBbits.LATB2 = 1; // Bring SS line high
                spi_data.buffer_out_ind = 0;
                spi_data.buffer_out_len = 0;
            }
        }
    }
}

void SPI2_Write(unsigned char *msg, unsigned int length) {
#ifdef SPI2_USE_INTERRUPT
    unsigned char i;
    spi_data.buffer_out_len = length;
    spi_data.buffer_out_ind = 1;
    for (i = 0; i < length; i++) {
        spi_data.buffer_out[i] = msg[i];
    }
    LATBbits.LATB7 = 0; // Bring SS line low
    SSP2BUF = spi_data.buffer_out[0]; // Transmit first byte
#else
    unsigned int i = 0;
    unsigned char tmp = 0;
    LATBbits.LATB7 = 0;
    while (i != length) {
        SSP2BUF = msg[i];
        i++;
        while (!SSP2STATbits.BF);

#ifndef SPI2_WRITE_ONLY
        spi_data.buffer_in[spi_data.buffer_in_write_ind] = SSP2BUF;
        if (spi_data.buffer_in_write_ind == MAXSPIBUF - 1) {
            spi_data.buffer_in_write_ind = 0;
        } else {
            spi_data.buffer_in_write_ind++;
        }
        spi_data.buffer_in_len++;
#else
        // Read data in buffer to clear it
        tmp = SSP2BUF;
#endif
    }
    LATBbits.LATB7 = 1;
#endif
}

void SPI2_Write_Repeat(unsigned char c, unsigned int length) {
#ifdef SPI2_USE_INTERRUPT
    // TODO
#else
    unsigned int i = 0;
    unsigned char tmp = 0;
    LATBbits.LATB7 = 0;
    while (i != length) {
        SSP2BUF = c;
        i++;
        while (!SSP2STATbits.BF);

#ifndef SPI2_WRITE_ONLY
        spi_data.buffer_in[spi_data.buffer_in_write_ind] = SSP2BUF;
        if (spi_data.buffer_in_write_ind == MAXSPIBUF - 1) {
            spi_data.buffer_in_write_ind = 0;
        } else {
            spi_data.buffer_in_write_ind++;
        }
        spi_data.buffer_in_len++;
#else
        // Read data in buffer to clear it
        tmp = SSP2BUF;
#endif
    }
    LATBbits.LATB7 = 1;
#endif
}

void SPI2_Read(unsigned char length) {
#ifdef SPI2_USE_INTERRUPT
    unsigned char i;
    spi_data.buffer_out_len = length;
    spi_data.buffer_out_ind = 1;
    for (i = 0; i < length; i++) {
        spi_data.buffer_out[i] = 0x0;
    }
    LATBbits.LATB7 = 0; // Bring SS line low
    SSP2BUF = spi_data.buffer_out[0]; // Transmit first byte
#else
    unsigned char i = 0;
    LATBbits.LATB7 = 0;

    for (i = 0; i < length; i++) {
        SSP2BUF = 0x0;
        while (!SSP2STATbits.BF);

        spi_data.buffer_in[spi_data.buffer_in_write_ind] = SSP2BUF;
        if (spi_data.buffer_in_write_ind == MAXSPIBUF - 1) {
            spi_data.buffer_in_write_ind = 0;
        } else {
            spi_data.buffer_in_write_ind++;
        }
        spi_data.buffer_in_len++;
    }
    LATBbits.LATB7 = 1;
#endif
}

unsigned char SPI2_Buffer_Len() {
    return spi_data.buffer_in_len;
}

unsigned char SPI2_Buffer_Read(unsigned char* buffer) {
    unsigned char i = 0;
    while (spi_data.buffer_in_len != 0) {
        buffer[i] = spi_data.buffer_in[spi_data.buffer_in_read_ind];
        i++;
        if (spi_data.buffer_in_read_ind == MAXSPIBUF - 1) {
            spi_data.buffer_in_read_ind = 0;
        } else {
            spi_data.buffer_in_read_ind++;
        }
        spi_data.buffer_in_len--;
    }
    return i;
}