Memristor-Robotics/mep-master

View on GitHub
src/drivers/motion/lib/UartConnection.cpp

Summary

Maintainability
Test Coverage
/*
 * Uart.cpp
 *
 *  Created on: Nov 7, 2013
 *      Author: LaptopX
 */

#include "UartConnection.h"
#include <unistd.h>            //Used for UART
#include <fcntl.h>            //Used for UART
#include <cstdio>

#define TAG "UartConnection "

namespace uart
{

UartConnection::UartConnection(bool openNow, speed_t baudRate):baudRate(baudRate)
{
    uart0_filestream = -1;
    if(openNow) openUart();
}

UartConnection::~UartConnection()
{
    closeUart();
}

void UartConnection::openUart()
{
    //-------------------------
    //----- SETUP USART 0 -----
    //-------------------------
    //At bootup, pins 8 and 10 are already set to UART0_TXD, UART0_RXD (ie the alt0 function) respectively

    //OPEN THE UART
    //The flags (defined in fcntl.h):
    //    Access modes (use 1 of these):
    //        O_RDONLY - Open for reading only.
    //        O_RDWR - Open for reading and writing.
    //        O_WRONLY - Open for writing only.
    //
    //    O_NDELAY / O_NONBLOCK (same function) - Enables nonblocking mode. When set read requests on the file can return immediately with a failure status
    //                                            if there is no input immediately available (instead of blocking). Likewise, write requests can also return
    //                                            immediately with a failure status if the output can't be written immediately.
    //
    //    O_NOCTTY - When set and path identifies a terminal device, open() shall not cause the terminal device to become the controlling terminal for the process.
    uart0_filestream = open("/dev/ttyAMA0", O_RDWR | O_NOCTTY | O_NDELAY);        //Open in non blocking read/write mode
    if (uart0_filestream == -1)
    {
        //ERROR - CAN'T OPEN SERIAL PORT
    }

    //CONFIGURE THE UART
    //The flags (defined in /usr/include/termios.h - see http://pubs.opengroup.org/onlinepubs/007908799/xsh/termios.h.html):
    //    Baud rate:- B1200, B2400, B4800, B9600, B19200, B38400, B57600, B115200, B230400, B460800, B500000, B576000, B921600, B1000000, B1152000, B1500000, B2000000, B2500000, B3000000, B3500000, B4000000
    //    CSIZE:- CS5, CS6, CS7, CS8
    //    CLOCAL - Ignore modem status lines
    //    CREAD - Enable receiver
    //    IGNPAR = Ignore characters with parity errors
    //    ICRNL - Map CR to NL on input (Use for ASCII comms where you want to auto correct end of line characters - don't use for bianry comms!)
    //    PARENB - Parity enable
    //    PARODD - Odd parity (else even)
    struct termios options;
    tcgetattr(uart0_filestream, &options);
    options.c_cflag = baudRate | CS8 | CLOCAL | CREAD;        //<Set baud rate
    options.c_iflag = IGNPAR;
    options.c_oflag = 0;
    options.c_lflag = 0;
    tcflush(uart0_filestream, TCIFLUSH);
    tcsetattr(uart0_filestream, TCSANOW, &options);
    
    // flushuj na pocetku
    flushInput();
    flushOutput();
    
    dumpReadGarbage();
}

void UartConnection::dumpReadGarbage()
{
    char dump;
    while(readUart(&dump, 1))
    {
        LOG(WARN) << TAG << "Garbage detected = " << dump;
    }
}

void UartConnection::closeUart()
{
    close(uart0_filestream);
    uart0_filestream=-1;
}

void UartConnection::writeUart(const char *data, int dataSize)
{
    if (uart0_filestream != -1)
    {
        int count = write(uart0_filestream, data, dataSize);        //Filestream, bytes to write, number of bytes to write
        if (count < 0)
        {
            //printf("UART TX error\n");
        }
    }
}

void UartConnection::writeUart(const char &data)
{
    writeUart(&data, 1);
}

void UartConnection::readAll(char output[], int numOfBytes)
{
    int currentByte=0;
    int printCont=0;
    int retryCount=0;

    while(true)
    {
        if (retryCount >= MAX_RETRY_COUNT){
            LOG(ERROR) << TAG << "UART not available";
            throw;
        }

        currentByte += readUart(output+currentByte, numOfBytes-currentByte);
        if(currentByte >= numOfBytes) break;
        printCont++;

        if(printCont % PRINT_RETRY_COUNT_EVERY == 0) {
            retryCount++;
            LOG(WARN) << TAG << "UART spin, retry count " << retryCount * PRINT_RETRY_COUNT_EVERY;
        }

        usleep(RETRY_DELAY);
    }
}

int UartConnection::readUart(char output[], int numOfBytes)
{
    //----- CHECK FOR ANY RX BYTES -----
    if (uart0_filestream != -1)
    {
        int rx_length = read(uart0_filestream, (void*)output, numOfBytes);        //Filestream, buffer to store in, number of bytes to read (max)
        if (rx_length < 0)
        {
            //An error occured (will occur if there are no bytes)
        }
        else if (rx_length == 0)
        {
            //No data waiting
        }
        else
        {
            //Bytes received
            return rx_length;
        }
    }

    return 0;
}

void UartConnection::readUart(char &data)
{
    readUart(&data, 1);
}

void UartConnection::flushInput()
{
    tcflush(uart0_filestream, TCIFLUSH);
}

void UartConnection::flushOutput()
{
    tcflush(uart0_filestream, TCOFLUSH);
}

// TODO kad se desi greska da se proba flushovati ili zatvoriti pa otvoriti uart

}