Subversion Repositories Code-Repo

Rev

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

#include "defines.h"
#include "SPI.h"

static SPI_DATA *spi_data_p;

void SPI_Init(SPI_DATA *data, uint8_t speed) {
    spi_data_p = data;

    SPI_MOSI_TRIS = 0;
    SPI_CLK_TRIS = 0;

#ifndef SPI_WRITE_ONLY
    SPI_MISO_TRIS = 1;
#endif

//    SPI_SLAVE_SELECT_TRIS = 0; // SPI2 slave select
//    SPI_SLAVE_SELECT_LAT = 1; // SPI2 SS high (Idle)

//    SPI_RESET_TRIS = 0; // SPI2 reset
//    SPI_RESET_LAT = 1; // SPI2 reset active low

    SPI_DC_SELECT_TRIS = 0; // SPI2 D/C select
    SPI_DC_SELECT_LAT = 0;

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

    SSP1CON1bits.SSPM = speed;

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

    PIE1bits.SSP1IE = 0;    // Disable MSSP interrupt

#ifndef SPI_WRITE_ONLY
    spi_data_p->buffer_in_len = 0;
    spi_data_p->buffer_in_read_ind = 0;
    spi_data_p->buffer_in_write_ind = 0;
#endif
    spi_data_p->buffer_out_ind = 0;
    spi_data_p->buffer_out_len = 0;
}

void SPI_Write(uint8_t *msg, uint16_t length) {
    uint16_t i = 0;

//    SPI_SLAVE_SELECT_LAT = 0;
    while (i != length) {
        SSP1BUF = msg[i];
        i++;
        while (!SSP1STATbits.BF);

#ifndef SPI_WRITE_ONLY
        spi_data_p->buffer_in[spi_data_p->buffer_in_write_ind] = SSP2BUF;
        if (spi_data_p->buffer_in_write_ind == MAXSPIBUF - 1) {
            spi_data_p->buffer_in_write_ind = 0;
        } else {
            spi_data_p->buffer_in_write_ind++;
        }
        spi_data_p->buffer_in_len++;
#else
        // Read data in buffer to clear it
        uint8_t tmp = SSP1BUF;
#endif
    }
//    SPI_SLAVE_SELECT_LAT = 1;
}

void SPI2_Write_Repeat(uint8_t c, uint16_t length) {
    uint16_t i = 0;
//    SPI_SLAVE_SELECT_LAT = 0;
    while (i != length) {
        SSP1BUF = c;
        i++;
        while (!SSP1STATbits.BF);

#ifndef SPI_WRITE_ONLY
        spi_data_p->buffer_in[spi_data_p->buffer_in_write_ind] = SSP2BUF;
        if (spi_data_p->buffer_in_write_ind == MAXSPIBUF - 1) {
            spi_data_p->buffer_in_write_ind = 0;
        } else {
            spi_data_p->buffer_in_write_ind++;
        }
        spi_data_p->buffer_in_len++;
#else
        // Read data in buffer to clear it
        uint8_t tmp = SSP1BUF;
#endif
    }
//    SPI_SLAVE_SELECT_LAT = 1;
}

#ifndef SPI_WRITE_ONLY
void SPI_Recv_Interrupt_Handler() {
    uint8_t c;

    if (SSP1STATbits.BF) { // Check if data receive flag is set
        if (spi_data_p->buffer_in_len == MAX_SPI_BUFFER - 1) {
            c = SSP1BUF; // Read SSP2BUF to clear it
        } else {
            // Save received data into buffer
            spi_data_p->buffer_in[spi_data_p->buffer_in_write_ind] = SSP1BUF;
            if (spi_data_p->buffer_in_write_ind == MAX_SPI_BUFFER - 1) {
                spi_data_p->buffer_in_write_ind = 0;
            } else {
                spi_data_p->buffer_in_write_ind++;
            }
            spi_data_p->buffer_in_len++;

            // Put next byte in SSP2BUF for transmit
            if (spi_data_p->buffer_out_ind != spi_data_p->buffer_out_len) {
                SSP1BUF = spi_data_p->buffer_out[spi_data_p->buffer_out_ind];
                spi_data_p->buffer_out_ind++;
            } else {
//                SPI_SLAVE_SELECT_LAT = 1; // Bring SS line high
                spi_data_p->buffer_out_ind = 0;
                spi_data_p->buffer_out_len = 0;
            }
        }
    }
}

void SPI_Read(char length) {
//    SPI_SLAVE_SELECT_LAT = 0;

    for (uint8_t i = 0; i < length; i++) {
        SSP1BUF = 0x0;
        while (!SSP1STATbits.BF);

        spi_data_p->buffer_in[spi_data_p->buffer_in_write_ind] = SSP1BUF;
        if (spi_data_p->buffer_in_write_ind == MAX_SPI_BUFFER - 1) {
            spi_data_p->buffer_in_write_ind = 0;
        } else {
            spi_data_p->buffer_in_write_ind++;
        }
        spi_data_p->buffer_in_len++;
    }
//    SPI_SLAVE_SELECT_LAT = 1;
}

uint8_t SPI_Buffer_Len() {
    return spi_data_p->buffer_in_len;
}

uint8_t SPI_Read_Buffer(uint8_t* buffer) {
    uint8_t i = 0;
    while (spi_data_p->buffer_in_len != 0) {
        buffer[i] = spi_data_p->buffer_in[spi_data_p->buffer_in_read_ind];
        i++;
        if (spi_data_p->buffer_in_read_ind == MAX_SPI_BUFFER - 1) {
            spi_data_p->buffer_in_read_ind = 0;
        } else {
            spi_data_p->buffer_in_read_ind++;
        }
        spi_data_p->buffer_in_len--;
    }
    return i;
}
#endif