Nerve-SerialConnect is a part of System Nerve Essentials by Numazu Robocon Team.

Dependencies:   AsyncSerial

SerialConnect.cpp

Committer:
babylonica
Date:
2019-01-26
Revision:
1:a8fa09ff3ee9
Parent:
0:28807ec7ed26

File content as of revision 1:a8fa09ff3ee9:

// -*- coding:utf-8-unix -*-
/*!
  @file   SerialConnect.cpp
  @author Takuma Kawamura <bitpositive@MacBook-Pro-13.local>
  @date   Wed Jan 23 13:40:32 2019
  
  @brief  Nerve-SerialConnect

  MbedのUARTポートを使って,uint8_t(unsigned char)型の配列を送受信するためのライブラリ.割り込み処理を使うため効率的.チェックサムやバイト間タイムアウトを搭載しているので安全かつ,完全な状態で通信を行うことができる.

  @version    1.0

  @see      Mbed OS 2のリビジョンは,必ずRev.146以下にすること.

  @copyright  T.Kawamura (C) 2019 <contact@bit-plus.work>
  
*/

#include "SerialConnect.hpp"


SerialConnect::SerialConnect( PinName txpin, PinName rxpin, uint32_t payload_size, uint32_t baudrate, uint32_t uart_fifo_buffer_size )
	: payload_size( payload_size ), load_status( STATE_WAIT_HEADER ), payload_data_count( 0 )
{
  serial_port = new AsyncSerial( txpin, rxpin, baudrate, uart_fifo_buffer_size );
	
	time_out_timer = new Timer;
	time_out_timer->stop();
	time_out_timer->reset();
	
	memset( recieved_payload, 0, NSC_MAX_PACKET_SIZE );
}

SerialConnect::~SerialConnect( void )
{	
	delete serial_port;
  delete time_out_timer;
}

void SerialConnect::send( const uint8_t *payload_array )
{
	uint8_t checksum = 0;
	
	send_buffer[0] = NSC_HEADER;
	send_buffer[1] = payload_size;
	for( int i = 0; i < payload_size; i++ ) {
		send_buffer[i + 2] = payload_array[i];
		checksum += payload_array[i];
	}
	send_buffer[payload_size + 2] = checksum;
	send_buffer[payload_size + 3] = NSC_FOOTER;
	
	serial_port->write( send_buffer, payload_size + 4 );
	
	return;
}

update_result_e SerialConnect::update( void )
{
	uint8_t data;
	uint32_t i;
	uint8_t checksum = 0;
	
	if( serial_port->readable() > 0 ) {
		
		if( time_out_timer->read_ms() > NSC_TIMEOUT && load_status != STATE_WAIT_HEADER ){
			load_status = STATE_WAIT_HEADER;
		}
		time_out_timer->stop();
		time_out_timer->reset();
		
		data = serial_port->getc(); // 1byte取得
		
		switch( load_status ) {
		case STATE_WAIT_HEADER:
			if( data == NSC_HEADER ) {	// '@'
				load_status = STATE_WAIT_LENGTH;    
			}
			break;
			
		case STATE_WAIT_LENGTH:
			if( data == payload_size ) {
				load_status = STATE_WAIT_PAYLOAD;
			} else {
				load_status = STATE_WAIT_HEADER;
			}
			break;

		case STATE_WAIT_PAYLOAD:
			if( payload_data_count < payload_size - 1 ) {
				recv_buffer[payload_data_count] = data;
				payload_data_count++;
			} else {
				recv_buffer[payload_data_count] = data;
				payload_data_count = 0;
				load_status = STATE_WAIT_CHECKSUM;
			}
			break;

		case STATE_WAIT_CHECKSUM:
			for( i = 0; i < payload_size; i++ ) {
				checksum += recv_buffer[i];
			}
                
			if( data == checksum ) {
				load_status = STATE_WAIT_FOOTER;
			} else {
				load_status = STATE_WAIT_HEADER;
			}
			break;
			
		case STATE_WAIT_FOOTER:
			if( data == NSC_FOOTER ) {		// LF
				for( i = 0; i < payload_size; i++ ) {
					recieved_payload[i] = recv_buffer[i];
				}
				load_status = STATE_WAIT_HEADER;
				
				return READY;
			} else {
				load_status = STATE_WAIT_HEADER;
			}
			
			break;
		}
	}
	
	time_out_timer->start();
	
	return NOT_READY;
}