Asynchronous (Non-blocking) Serial Communication library with variable length software ring buffer (FIFO). You can use RawSerial Library's primary method. Operability confirmed on mbed 2.0.

Dependencies:   FIFO

Dependents:   Brute_TS_Controller_2018_11

AsyncSerial.cpp

Committer:
babylonica
Date:
2017-03-30
Revision:
6:08e3b1bba0ac
Parent:
5:a50cdaa90d6a
Child:
8:7390f9bb28d3

File content as of revision 6:08e3b1bba0ac:

// -*- coding: utf-8 -*-
/**
 @file		AsyncSerial.cpp
 @brief	 	Asynchronous (Non-brocking) Serial Communication library with variable length software ring buffer (FIFO). You can use also RawSerial Library's method. You can set the baudrate of the serial communication when instantiating.
 
 @author	T.Kawamura
 @version	1.1
 @date		2017-03-29	T.Kawamura	Written for C++/mbed.
 @date		2017-03-30	T.Kawamura	Bug Fixed: Cannot use format(), baud().
 
 @see 
 Copyright (C) 2017 T.Kawamura.
 Released under the MIT license.
 http://opensource.org/licenses/mit-license.php
 
*/

#include "AsyncSerial.hpp"

AsyncSerial::AsyncSerial(PinName txpin, PinName rxpin, uint32_t baudrate, uint32_t buffer_size) : RawSerial(txpin, rxpin, baudrate), fifo_tx(buffer_size), fifo_rx(buffer_size){
	//Initialize ISR
	RawSerial::attach(this, &AsyncSerial::ISR_TX, RawSerial::TxIrq);
	RawSerial::attach(this, &AsyncSerial::ISR_RX, RawSerial::RxIrq);

	fifo_tx.clear();
	fifo_rx.clear();
	
	Is_Serial_Sending = false;

	return;
}

AsyncSerial::~AsyncSerial(){
	RawSerial::attach(NULL, RawSerial::TxIrq);
	RawSerial::attach(NULL, RawSerial::RxIrq);

	return;
}

void AsyncSerial::ISR_TX(void){
	int data;

	if( fifo_tx.available() > 0 ){
		data = (int)fifo_tx.get();
		RawSerial::putc(data);
	}else{
		Is_Serial_Sending = false;
	}	
}

void AsyncSerial::ISR_RX(void){
	uint8_t data;

	data = (uint8_t)RawSerial::getc();
	fifo_rx.put(data);
}

int AsyncSerial::readable(void){
	return (int)fifo_rx.available();
}

int AsyncSerial::writeable(void){
	return 1;
}

int AsyncSerial::getc(void){
	return (int)fifo_rx.get();
}

int AsyncSerial::peekc(void){
	return (int)fifo_rx.peek();
}

int AsyncSerial::putc(int c){
	int status;

	if( Is_Serial_Sending ){
		status = fifo_tx.put((uint8_t)c);
		if( status != 0 ){
			return 1;
		}else{
			return 0;
		}
	}else{
		Is_Serial_Sending = true;
		RawSerial::putc(c);
	}
	return 1;
}

int AsyncSerial::puts(const char *str){
	uint8_t temp;
	int status = 0;

	for(uint32_t i = 0; i < strlen(str); i++){
		temp = (uint8_t)str[i];
		status = fifo_tx.put(temp);
	}

	if( !Is_Serial_Sending ){
		Is_Serial_Sending = true;
		RawSerial::putc((int)fifo_tx.get());
	}

	if( status == 0 ){
		return 0;
	}
	
	AsyncSerial::putc('\r');
	AsyncSerial::putc('\n');
	return 1;
}

int AsyncSerial::printf(const char *format, ...){
	int32_t wrote_length = 0;
	char string_buffer[PRINTF_STRING_BUFFER_SIZE];

	memset(string_buffer, 0, PRINTF_STRING_BUFFER_SIZE);
	
	va_list arg;
	va_start(arg, format);
	wrote_length = vsprintf(string_buffer, format, arg);
	
	if( wrote_length > PRINTF_STRING_BUFFER_SIZE ) {
		error("%s @ %d : String is too large, string buffer overwrite. (Max buffer size: %d Wrote length: %d)\n", __FILE__, __LINE__, PRINTF_STRING_BUFFER_SIZE, wrote_length);
		va_end(arg);
		return 0;
	}

	if( wrote_length < 0 ){
		va_end(arg);
		error("Function vsprintf() was failed.");
		return 0;
	}

	va_end(arg);
	wrote_length = AsyncSerial::write((uint8_t*)string_buffer, wrote_length);
	
	return (uint16_t)wrote_length;
}

int AsyncSerial::write(const uint8_t *buffer, int length){
	uint8_t temp;
	int status;
	
	if ( length < 1 ){
		return 0;
	}

	for(uint32_t i = 0; i < length; i++){
		temp = (uint8_t)buffer[i];
		status = fifo_tx.put(temp);
	}

	if( !Is_Serial_Sending ){
		Is_Serial_Sending = true;
		RawSerial::putc((int)fifo_tx.get());
	}

	if( status == 0 ){
		return 0;
	}

	return 1;	
}

void AsyncSerial::flush(void){
	fifo_rx.clear();
	return;
}

void AsyncSerial::wait(void){
	while( fifo_rx.available() > 0 ){}
	return;
}

void AsyncSerial::format(int bits, Parity parity, int stop_bits){
	RawSerial::attach(NULL, RawSerial::TxIrq);
	RawSerial::attach(NULL, RawSerial::RxIrq);

	RawSerial::format(bits, parity, stop_bits);

	RawSerial::attach(this, &AsyncSerial::ISR_TX, RawSerial::TxIrq);
	RawSerial::attach(this, &AsyncSerial::ISR_RX, RawSerial::RxIrq);
}

void AsyncSerial::baud(int baudrate){
	RawSerial::attach(NULL, RawSerial::TxIrq);
	RawSerial::attach(NULL, RawSerial::RxIrq);

	RawSerial::baud(baudrate);

	RawSerial::attach(this, &AsyncSerial::ISR_TX, RawSerial::TxIrq);
	RawSerial::attach(this, &AsyncSerial::ISR_RX, RawSerial::RxIrq);	
}