5,14 → 5,11 |
|
static SPI1_DATA *spi_data_ptr; |
|
void SPI1_Init(SPI1_DATA *data) { |
void SPI1_Init(SPI1_DATA *data, void (*rx_callback)(char)) { |
spi_data_ptr = data; |
spi_data_ptr->outBufferInd = 0; |
spi_data_ptr->outBufferLen = 0; |
#ifndef SPI1_WRITE_ONLY |
spi_data_ptr->inBufferInd = 0; |
spi_data_ptr->inBufferLen = 0; |
#endif |
spi_data_ptr->buffer_out_ind = 0; |
spi_data_ptr->buffer_out_len = 0; |
spi_data_ptr->rx_callback = rx_callback; |
|
INTDisableInterrupts(); |
|
38,7 → 35,7 |
IPC5SET = 0x19000000; // Set IPL=6, Subpriority 1 |
SPI1BRG = 0x1; // Use FPB/4 clock frequency |
SPI1STATCLR = 0x40; // Clear the Overflow |
#ifndef SPI1_WRITE_ONLY |
#ifndef SPI_WRITE_ONLY |
IEC0SET = 0x01800000; // Enable RX and Error interrupts |
#endif |
// Enhanced buffer, SPI on, 8 bits transfer, SMP=1, Master mode |
48,45 → 45,20 |
INTEnableInterrupts(); |
} |
|
#ifndef SPI1_WRITE_ONLY |
int SPI1_Read_Buffer(unsigned char *array, unsigned int count) { |
if (count > SPI1_BUFFER_SIZE) |
return 0; |
if (spi_data_ptr->inBufferLen == 0) |
return 0; |
int SPI1_Write(unsigned char *array, unsigned int count, void (*tx_callback)(void)) { |
spi_data_ptr->tx_callback = tx_callback; |
|
// Save previous interrupt state |
int prev = IEC0 & 0x03800000; |
// Temporarily disable interrupts |
IEC0CLR = 0x03800000; |
int ret = spi_data_ptr->inBufferLen; |
int i; |
for (i = 0; i < count; i++) { |
array[i] = spi_data_ptr->inBuffer[i]; |
} |
// Reset buffer pointers |
spi_data_ptr->inBufferInd = 0; |
spi_data_ptr->inBufferLen = 0; |
// Restore saved interrupt state |
IEC0SET = prev; |
// Return the number of valid bytes in the buffer |
return ret; |
} |
#endif |
|
int SPI1_Write(unsigned char *array, unsigned int count, void (*callback)(void)) { |
spi_data_ptr->callback_function = callback; |
|
if (count > SPI1_BUFFER_SIZE) |
return 0; |
if (spi_data_ptr->outBufferLen != 0) |
if (spi_data_ptr->buffer_out_len != 0) |
return 0; |
|
spi_data_ptr->outBufferLen = count; |
spi_data_ptr->outBufferInd = count-1; |
// Put the data to send into the outbound buffer |
spi_data_ptr->buffer_out_len = count; |
spi_data_ptr->buffer_out_ind = count-1; |
int i; |
for (i = 0; i < count; i++) { |
spi_data_ptr->outBuffer[i] = array[i]; |
spi_data_ptr->buffer_out[i] = array[i]; |
} |
IEC0SET = 0x02000000; // Enable TX interrupt |
return 1; |
93,7 → 65,7 |
} |
|
void __ISR(_SPI_1_VECTOR, ipl6) __SPI_1_Interrupt_Handler(void) { |
#ifndef SPI1_WRITE_ONLY |
#ifndef SPI_WRITE_ONLY |
// Process SPI1 error flag |
if (IFS0bits.SPI1EIF) { |
// Clear the receive overflow bit if it is set |
108,17 → 80,11 |
int i; |
// Read the data received from the last transfer |
int rxBufferCount = SPI1STATbits.RXBUFELM; |
if (spi_data_ptr->inBufferLen + rxBufferCount < SPI1_BUFFER_SIZE) { |
for (i = 0; i < rxBufferCount; i++) { |
spi_data_ptr->inBuffer[spi_data_ptr->inBufferInd] = SPI1BUF; |
spi_data_ptr->inBufferInd++; |
spi_data_ptr->inBufferLen++; |
} |
} else { |
// If buffer is full, discard data in enhanced buffer |
for (i = 0; i < rxBufferCount; i++) { |
int tmp = SPI1BUF; |
} |
for (i = 0; i < rxBufferCount; i++) { |
char c = SPI1BUF; |
// Call the RX callback function on the received data |
if (spi_data_ptr->rx_callback != NULL) |
(*spi_data_ptr->rx_callback)(c); |
} |
IFS0CLR = 0x01000000; // Clear the RX flag |
} |
128,25 → 94,25 |
if (IFS0bits.SPI1TXIF) { |
int i; |
// Disable the transmit interrupt if all data has been sent |
if (spi_data_ptr->outBufferLen == 0) { |
if (spi_data_ptr->buffer_out_len == 0) { |
IEC0CLR=0x02000000; |
if (spi_data_ptr->callback_function != NULL) |
(*spi_data_ptr->callback_function)(); |
if (spi_data_ptr->tx_callback != NULL) |
(*spi_data_ptr->tx_callback)(); |
} else { |
// Start transmitting the data in the buffer |
int txBufferFree = 16 - SPI1STATbits.TXBUFELM; |
if (spi_data_ptr->outBufferLen > txBufferFree) { |
if (spi_data_ptr->buffer_out_len > txBufferFree) { |
for (i = 0; i < txBufferFree; i++) { |
SPI1BUF = spi_data_ptr->outBuffer[spi_data_ptr->outBufferInd]; |
spi_data_ptr->outBufferInd--; |
SPI1BUF = spi_data_ptr->buffer_out[spi_data_ptr->buffer_out_ind]; |
spi_data_ptr->buffer_out_ind--; |
} |
spi_data_ptr->outBufferLen -= txBufferFree; |
spi_data_ptr->buffer_out_len -= txBufferFree; |
} else { |
for (i = 0; i < spi_data_ptr->outBufferLen; i++) { |
SPI1BUF = spi_data_ptr->outBuffer[spi_data_ptr->outBufferInd]; |
spi_data_ptr->outBufferInd--; |
for (i = 0; i < spi_data_ptr->buffer_out_len; i++) { |
SPI1BUF = spi_data_ptr->buffer_out[spi_data_ptr->buffer_out_ind]; |
spi_data_ptr->buffer_out_ind--; |
} |
spi_data_ptr->outBufferLen = 0; |
spi_data_ptr->buffer_out_len = 0; |
} |
} |
IFS0CLR = 0x02000000; // Clear the TX flag |