Rev 226 | Blame | Last modification | View Log | Download | RSS feed
#include "defines.h"#include "SPI4.h"static SPI4_DATA *spi_data_ptr;void SPI4_Init(SPI4_DATA *data) {spi_data_ptr = data;spi_data_ptr->buffer_out_ind = 0;spi_data_ptr->buffer_out_len = 0;spi_data_ptr->buffer_in_ind = 0;spi_data_ptr->buffer_in_len = 0;spi_data_ptr->write_blank = 0;INTDisableInterrupts();// Note: FIFO enhanced buffer depth is 4/8/16 for 32/16/8 bit widths// FSCK = FPB / (2 * (SPIxBRG + 1))IEC1CLR = 0x00000700; // Disable all SPI interruptsSPI4CON = 0; // Stops and resets the SPI4.uint32_t tmp = SPI4BUF; // Clears the receive bufferIFS1CLR = 0x00000700; // Clear any existing eventIPC8CLR = 0x0000001F; // Clear the priorityIPC8SET = 0x0000001A; // Set IPL=6, Subpriority 2SPI4BRG = 0x4; // Use FPB/10 clock frequencySPI4STATCLR = 0x40; // Clear the OverflowIEC1SET = 0x00000300; // Enable RX and Error interrupts// Enhanced buffer, SPI on, 8 bits transfer, SMP=1, Master mode// SPIxTXIF set on buffer empty, SPIxRXIF set on buffer not emptySPI4CON = 0x18225;INTEnableInterrupts();}uint8_t SPI4_Read(uint32_t length, void (*rx_callback)(uint8_t, uint8_t *)) {spi_data_ptr->rx_callback = rx_callback;// Ensure that the receiving buffer is large enoughif (length > SPI4_BUFFER_IN_SIZE)return 0;// Ensure that no previous transactions are in progressif (spi_data_ptr->buffer_in_len != 0)return 0;spi_data_ptr->write_blank = 1;spi_data_ptr->buffer_in_len = length;spi_data_ptr->buffer_in_ind = 0;SPI4_Write(NULL, length, NULL);return 1;}uint8_t SPI4_Write(uint8_t *array, uint32_t length, void (*tx_callback)(void)) {spi_data_ptr->tx_callback = tx_callback;// We only care about the transmit length if we are sending dataif (length > SPI4_BUFFER_OUT_SIZE && !spi_data_ptr->write_blank)return 0;// Ensure that no previous transactions are in progressif (spi_data_ptr->buffer_out_len != 0)return 0;// Put the data to send into the outbound bufferspi_data_ptr->buffer_out_len = length;spi_data_ptr->buffer_out_ind = 0;// Copy only if we are actually going to transmit dataif (!spi_data_ptr->write_blank) {int32_t i;for (i = 0; i < length; i++) {spi_data_ptr->buffer_out[i] = array[i];}}IEC1SET = 0x00000400; // Enable TX interruptreturn 1;}void __ISR(_SPI_4_VECTOR, ipl6) __SPI_4_Interrupt_Handler(void) {// Process SPI4 error flagif (IFS1bits.SPI4EIF) {// Clear the receive overflow bit if it is setif (SPI4STATbits.SPIROV) {SPI4STATbits.SPIROV = 0;}IFS1CLR = 0x00000100; // Clear the error flag}// Process SPI4 receive flagif (IFS1bits.SPI4RXIF) {uint32_t i;// Read the data received from the last transferuint32_t rxBufferCount = SPI4STATbits.RXBUFELM;for (i = 0; i < rxBufferCount; i++) {int8_t c = SPI4BUF;// Put the received data into the bufferif (spi_data_ptr->buffer_in_len != 0) {spi_data_ptr->buffer_in[spi_data_ptr->buffer_in_ind] = c;spi_data_ptr->buffer_in_ind++;// If done acquiring requested length, resetif (spi_data_ptr->buffer_in_ind == spi_data_ptr->buffer_in_len) {// Call the RX callback function on the received dataif (spi_data_ptr->rx_callback != NULL)(*spi_data_ptr->rx_callback)(spi_data_ptr->buffer_in_len, spi_data_ptr->buffer_in);spi_data_ptr->buffer_in_len = 0;}}}IFS1CLR = 0x00000200; // Clear the RX flag}// Process SPI4 transmit flagif (IFS1bits.SPI4TXIF && IEC1bits.SPI4TXIE) {int32_t i;// Disable the transmit interrupt if all data has been sentif (spi_data_ptr->buffer_out_len == 0) {IEC1CLR=0x00000400;spi_data_ptr->write_blank = 0;// Call the TX callback function at end of transmissionif (spi_data_ptr->tx_callback != NULL)(*spi_data_ptr->tx_callback)();} else {// Start transmitting the data in the bufferint32_t txBufferFree = 16 - SPI4STATbits.TXBUFELM;if (spi_data_ptr->buffer_out_len > txBufferFree) {for (i = 0; i < txBufferFree; i++) {if (spi_data_ptr->write_blank) {SPI4BUF = 0x00;} else {SPI4BUF = spi_data_ptr->buffer_out[spi_data_ptr->buffer_out_ind];spi_data_ptr->buffer_out_ind++;}}spi_data_ptr->buffer_out_len -= txBufferFree;} else {for (i = 0; i < spi_data_ptr->buffer_out_len; i++) {if (spi_data_ptr->write_blank) {SPI4BUF = 0x00;} else {SPI4BUF = spi_data_ptr->buffer_out[spi_data_ptr->buffer_out_ind];spi_data_ptr->buffer_out_ind++;}}spi_data_ptr->buffer_out_len = 0;}}IFS1CLR = 0x00000400; // Clear the TX flag}}