Subversion Repositories Code-Repo

Rev

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

#include <xc.h>
#include "defines.h"
#include "base_UART.h"

static UART_DATA *uart_data_p;

void UART_Init(UART_DATA *data) {
    uart_data_p = data;

    UART_TX_TRIS = 0; // Tx pin set to output
#ifndef UART_TX_ONLY
    UART_RX_TRIS = 1; // Rx pin set to input
#endif
    LATAbits.LATA0 = 1; // Keep the line high at start

    BAUDCONbits.BRG16 = 0; // 8-bit baud rate generator
    SPBRGL = 25; // Set UART speed to 38400 baud
    TXSTAbits.BRGH = 1; // High speed mode

    TXSTAbits.SYNC = 0; // Async mode
    RCSTAbits.SPEN = 1; // Serial port enable

    TXSTAbits.TX9 = 0; // 8 bit transmission

    TXSTAbits.TXEN = 1; // Transmission enabled

    PIE1bits.TXIE = 0; // Disable TX interrupt
#ifndef UART_TX_ONLY
    RCSTAbits.RX9 = 0; // 8 bit reception
    RCSTAbits.CREN = 1; // Enables receiver
    PIE1bits.RCIE = 1; // Enable RX interrupt

    // Initialize the buffer that holds UART messages
    uart_data_p->buffer_in_read_ind = 0;
    uart_data_p->buffer_in_write_ind = 0;
    uart_data_p->buffer_in_len = 0;
    uart_data_p->buffer_in_len_tmp = 0;
#else
    RCSTAbits.CREN = 0;
#endif
    uart_data_p->buffer_out_ind = 0;
    uart_data_p->buffer_out_len = 0;
}

void UART_Send_Interrupt_Handler() {
    // Put remaining data in TSR for transmit
    if (uart_data_p->buffer_out_ind != uart_data_p->buffer_out_len) {
        TXREG = uart_data_p->buffer_out[uart_data_p->buffer_out_ind];
        uart_data_p->buffer_out_ind++;
    } else {
        while (!TXSTAbits.TRMT); // Wait for last byte to finish sending
        PIE1bits.TXIE = 0;
        uart_data_p->buffer_out_ind = 0;
        uart_data_p->buffer_out_len = 0;
    }
}

void UART_Write(const char *string, char length) {
    while (PIE1bits.TXIE); // Wait for previous message to finish sending
    uart_data_p->buffer_out_len = length;
    uart_data_p->buffer_out_ind = 1;
    for (char i = 0; i < length; i++) {
        uart_data_p->buffer_out[i] = string[i];
    }
    TXREG = uart_data_p->buffer_out[0]; // Put first byte in TSR
    PIE1bits.TXIE = 1;
}

void UART_WriteD(const char* string, char length) {
    PIE1bits.TXIE = 1;
    for (char i = 0; i < length; i++) {
        TXREG = string[i];
        NOP();
        while (!PIR1bits.TXIF);
    }
    PIE1bits.TXIE = 0;
}

#ifndef UART_TX_ONLY
void UART_Recv_Interrupt_Handler() {
    if (PIR1bits.RCIF) { // Check if data receive flag is set
        char c = RCREG;

        // Save received data into buffer
        uart_data_p->buffer_in[uart_data_p->buffer_in_write_ind] = c;
        if (uart_data_p->buffer_in_write_ind == MAXUARTBUF - 1) {
            uart_data_p->buffer_in_write_ind = 0;
        } else {
            uart_data_p->buffer_in_write_ind++;
        }

        // Store the last MAXUARTBUF values entered
        if (uart_data_p->buffer_in_len_tmp < MAXUARTBUF) {
            uart_data_p->buffer_in_len_tmp++;
        } else {
            if (uart_data_p->buffer_in_read_ind == MAXUARTBUF - 1) {
                uart_data_p->buffer_in_read_ind = 0;
            } else {
                uart_data_p->buffer_in_read_ind++;
            }
        }

        // Update buffer size upon receiving newline (0x0D)
        if (c == UART_BREAK_CHAR) {
            uart_data_p->buffer_in_len = uart_data_p->buffer_in_len_tmp;
            uart_data_p->buffer_in_len_tmp = 0;
        }
    }

    if (RCSTAbits.OERR == 1) {
        // We've overrun the USART and must reset
        TXSTAbits.TXEN = 0; // Kill anything currently sending
        RCSTAbits.CREN = 0; // Reset UART1
        RCSTAbits.CREN = 1;
    }
}

char UART_Buffer_Len() {
    return uart_data_p->buffer_in_len;
}

/* Reader interface to the UART buffer, returns the number of bytes read */
char UART_Read_Buffer(char *buffer) {
    char i = 0;
    while (uart_data_p->buffer_in_len != 0) {
        buffer[i] = uart_data_p->buffer_in[uart_data_p->buffer_in_read_ind];
        i++;
        if (uart_data_p->buffer_in_read_ind == MAXUARTBUF - 1) {
            uart_data_p->buffer_in_read_ind = 0;
        } else {
            uart_data_p->buffer_in_read_ind++;
        }
        uart_data_p->buffer_in_len--;
    }
    return i;
}
#endif